npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

egg-message1

v1.0.1

Published

passport plugin for egg, base on passportjs

Downloads

2

Readme

egg-message

egg插件开发package.json详解

  • 命名规范

    • npm 包名以 egg- 开头,且为全小写,例如:egg-xx。比较长的词组用中划线:egg-foo-bar
    • 对应的插件名使用小驼峰,小驼峰转换规则以 npm 包名的中划线为准 egg-foo-bar => fooBar
    • 对于可以中划线也可以不用的情况,不做强制约定,例如:userservice(egg-userservice) 还是 user-service(egg-user-service) 都可以
  • package.json 书写规范

    • 只书写我自己不知道的关键字,其他的请自行在package.json中自我查询

    • eggPlugin:

      • {String} name - 插件名(必须配置),具有唯一性,配置依赖关系时会指定依赖插件的 name。
      • {Array} dependencies - 当前插件强依赖的插件列表(如果依赖的插件没找到,应用启动失败)
        • 此处注意:不要和package.json本身的dependencies关键字弄混,这个在eggPlugin内的,是依赖的egg插件,egg-xxxx格式的,而外面的是正常普通npm包】
        • 比如我们的插件依赖一个叫egg-pwd的插件,那么"dependencies": [ "pwd" ],不需要再去增加 egg-
      • {Array} optionalDependencies - 当前插件的可选依赖插件列表(如果依赖的插件未开启,只会 warning,不会影响应用启动)。
      • {Array} env - 只有在指定运行环境才能开启,具体有哪些环境可以参考运行环境。此配置是可选的,一般情况下都不需要配置。
        {
          "name": "egg-rpc",
          "eggPlugin": {
            "name": "rpc", // 插件名
            "dependencies": [ "registry" ], // 强依赖的插件列表
            "optionalDependencies": [ "vip" ], // 可选依赖插件列表
            "env": [ "local", "test", "unittest", "prod" ] // 指定运行环境
          }
        }
    • description:意义与keywords相似,就是对于插件做一个简介,让使用者更明白他是做什么的

    • 在 keywords 里加上 egg、egg-plugin、eggPlugin 等关键字,便于索引【其实就是类似与淘宝对于商品的多个关键词,便于在插件发布后,提高插件的曝光率】【与description差不多意思】

      {
        "name": "egg-view-nunjucks",
        "version": "1.0.0", // 你的插件的版本号
        "description": "view plugin for egg",
        "eggPlugin": {
          "name": "nunjucks",
          "dep": [
            "security"
          ]
        },
        "keywords": [
          "egg",
          "egg-plugin",
          "eggPlugin",
          "egg-plugin-view",
          "egg-view",
          "nunjucks"
        ],
      }

      举例:针对于egg-view-nunjucks, 我们写的几个关键字,egg,egg-plugin,eggPlugin:属于egg框架能用的插件,egg-plugin-view,egg-view,nunjucks告诉我们这个插件与什么有关


    • 发布文件配置(files)

      files 字段用于描述我们使用 npm publish 命令后推送到 npm 服务器的文件列表,如果指定文件夹,则文件夹内的所有内容都会包含进来。我们可以查看下载的 antd 的 package.json 的files 字段,内容如下:

        "files": [
          "dist",
          "lib",
          "es"
        ],

      可以看到下载后的 antd 包是下面的目录结构: image1-url

      • repository: 项目代码存放地方
        "repository": {
          "type": "git",
          "url": "git+https://github.com/eggjs/egg-passport.git" // git地址
        },
      • bugs: 项目问题反馈的Url或报告问题的email地址
        "bugs": {
          "email": "[email protected]", // 反馈问题邮箱
          "url": "https://github.com/owner/project/issues" // 反馈问题地址
        },

压缩响应消息,

Install

暂时内部使用,直接copy。发布后, $ npm i xxx

Usage

enable message plugin

// 发布前
// config/plugin.js
exports.message = {
  enable: true,
  package: '../../lib/plugin/egg-message',
};
// 发布后
exports.message = {
  enable: true,
  package: 'egg-message',
};

Using

// config/config.default.js
exports.msgFilter = {
  threshold: 1024 // 小于 1k 的响应体不压缩【默认1024】
};
exports.message = {
    enable: true, // 
    client: {
        /**
         * parameter config  https://github.com/node-modules/parameter
         */
        validate: {
            // enable: true,
            convert: true,
            validateRoot: true
        },
    },
    /**
     * logAli 上传慢查询日志插件配置
     */
    aliLog: {
        enable: true, // 是否将应用日志发送到远程 阿里云sls
        limitTime: 20, // 毫秒, 上传大于此值的日志,
        SlowQueryLog: 'slow_query_log', // 慢查询日志上传表名
        ErrorLog: 'error_log' // 错误日志上传表名
    }
};

Authenticate Requests

Use app.passport.mount(strategy[, options]), specifying the 'github' and 'twitter' strategy, to authenticate requests.

// app/router.js
module.exports = app => {
  app.get('/', 'home.index');

  // authenticates routers
  app.passport.mount('github');
  // this is a passport router helper, it's equal to the below codes
  //
  // const github = app.passport.authenticate('github');
  // app.get('/passport/github', github);
  // app.get('/passport/github/callback', github);

  // custom options.login url and options.successRedirect
  app.passport.mount('twitter', {
    loginURL: '/account/twitter',
    // auth success redirect to /
    successRedirect: '/',
  });
};

Verify and store user

Use app.passport.verify(async (ctx, user) => {}) hook:

// app.js
module.exports = app => {
  app.passport.verify(async (ctx, user) => {
    // check user
    assert(user.provider, 'user.provider should exists');
    assert(user.id, 'user.id should exists');

    // find user from database
    //
    // Authorization Table
    // column   | desc
    // ---      | --
    // provider | provider name, like github, twitter, facebook, weibo and so on
    // uid      | provider unique id
    // user_id  | current application user id
    const auth = await ctx.model.Authorization.findOne({
      uid: user.id,
      provider: user.provider,
    });
    const existsUser = await ctx.model.User.findOne({ id: auth.user_id });
    if (existsUser) {
      return existsUser;
    }
    // call user service to register a new user
    const newUser = await ctx.service.user.register(user);
    return newUser;
  });
};

How to develop an egg-passport-${provider} plugin

See example: egg-passport-twitter.

  • Plugin dependencies on egg-passport to use app.passport APIs.
// package.json
{
  "eggPlugin": {
    "name": "passportTwitter",
    "dependencies": [
      "passport"
    ]
  },
}
  • Define config and set default values

Must use key and secret instead of consumerKey|clientID and consumerSecret|clientSecret.

// config/config.default.js
exports.passportTwitter: {
  key: '',
  secret: '',
  callbackURL: '/passport/twitter/callback',
};
  • Init Strategy in app.js and format user in verify callback
// app.js
const debug = require('debug')('egg-passport-twitter');
const assert = require('assert');
const Strategy = require('passport-twitter').Strategy;

module.exports = app => {
  const config = app.config.passportTwitter;
  // must set passReqToCallback to true
  config.passReqToCallback = true;
  assert(config.key, '[egg-passport-twitter] config.passportTwitter.key required');
  assert(config.secret, '[egg-passport-twitter] config.passportTwitter.secret required');
  // convert to consumerKey and consumerSecret
  config.consumerKey = config.key;
  config.consumerSecret = config.secret;

  // register twitter strategy into `app.passport`
  // must require `req` params
  app.passport.use('twitter', new Strategy(config, (req, token, tokenSecret, params, profile, done) => {
    // format user
    const user = {
      provider: 'twitter',
      id: profile.id,
      name: profile.username,
      displayName: profile.displayName,
      photo: profile.photos && profile.photos[0] && profile.photos[0].value,
      token,
      tokenSecret,
      params,
      profile,
    };
    debug('%s %s get user: %j', req.method, req.url, user);
    // let passport do verify and call verify hook
    app.passport.doVerify(req, user, done);
  }));
};
  • That's all!

APIs

extent application

  • app.passport.mount(strategy, options): Mount the login and the login callback routers to use the given strategy.
  • app.passport.authenticate(strategy, options): Create a middleware that will authorize a third-party account using the given strategy name, with optional options.
  • app.passport.verify(handler): Verify authenticated user
  • app.passport.serializeUser(handler): Serialize user before store into session
  • app.passport.deserializeUser(handler): Deserialize user after restore from session

extend context

  • ctx.user: get the current authenticated user
  • ctx.isAuthenticated(): Test if request is authenticated
  • * ctx.login(user[, options]): Initiate a login session for user.
  • ctx.logout(): Terminate an existing login session

Unit Tests

This plugin has includes some mock methods to helper you writing unit tests more conveniently.

app.mockUser([user]): Mock an authenticated user

const mm = require('egg-mock');

describe('mock user demo', () => {
  let app;
  before(() => {
    app = mm.app();
    return app.ready();
  });
  after(() => app.close());

  afterEach(mm.restore);

  it('should show authenticated user info', () => {
    app.mockUser();
    return request(app.callback())
      .get('/')
      .expect(/user name: mock_name/)
      .expect(200);
  });
});

app.mockUserContext([user]): Mock a context instance with authenticated user

it('should get authenticated user and call service', async () => {
  const ctx = app.mockUserContext();
  const result = await ctx.service.findUser({ id: ctx.user.id });
  assert(result.user.id === ctx.user.id);
});

Questions & Suggestions

Please open an issue here.

License

MIT