egg-message
-
命名规范
- 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": {
"type": "git",
"url": "git+https://github.com/eggjs/egg-passport.git"
},
- bugs: 项目问题反馈的Url或报告问题的email地址
"bugs": {
"email": "project@hostname.com",
"url": "https://github.com/owner/project/issues"
},
压缩响应消息,
Install
暂时内部使用,直接copy。发布后, $ npm i xxx
Usage
enable message plugin
exports.message = {
enable: true,
package: '../../lib/plugin/egg-message',
};
exports.message = {
enable: true,
package: 'egg-message',
};
Using
exports.msgFilter = {
threshold: 1024
};
exports.message = {
enable: true,
client: {
validate: {
convert: true,
validateRoot: true
},
},
aliLog: {
enable: true,
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.
module.exports = app => {
app.get('/', 'home.index');
app.passport.mount('github');
app.passport.mount('twitter', {
loginURL: '/account/twitter',
successRedirect: '/',
});
};
Verify and store user
Use app.passport.verify(async (ctx, user) => {})
hook:
module.exports = app => {
app.passport.verify(async (ctx, user) => {
assert(user.provider, 'user.provider should exists');
assert(user.id, 'user.id should exists');
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;
}
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.
{
"eggPlugin": {
"name": "passportTwitter",
"dependencies": [
"passport"
]
},
}
- Define config and set default values
Must use key
and secret
instead of consumerKey|clientID
and consumerSecret|clientSecret
.
exports.passportTwitter: {
key: '',
secret: '',
callbackURL: '/passport/twitter/callback',
};
- Init
Strategy
in app.js
and format user in verify callback
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;
config.passReqToCallback = true;
assert(config.key, '[egg-passport-twitter] config.passportTwitter.key required');
assert(config.secret, '[egg-passport-twitter] config.passportTwitter.secret required');
config.consumerKey = config.key;
config.consumerSecret = config.secret;
app.passport.use('twitter', new Strategy(config, (req, token, tokenSecret, params, profile, done) => {
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);
app.passport.doVerify(req, user, done);
}));
};
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 userapp.passport.serializeUser(handler)
: Serialize user before store into sessionapp.passport.deserializeUser(handler)
: Deserialize user after restore from session
extend context
ctx.user
: get the current authenticated userctx.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