在线Demo | 文档 | English | 更新日志 | 反馈 | Gitee | 留言板
- 简单高效的架构,全ts编写,高度友好的ts声明支持
- 支持高度自定义和高可扩展的中间件体系,采用洋葱模型,丰富的路由hooks
内置中间件:
内置中间件为sener包中自带的中间 但是使用时也需要手动引入
- router:简单高可扩展的路由规则
- cookie:用于cookie获取和注入
- session:用于session获取和注入(依赖cookie)
- env:用于注入和使用环境变量
- cors:支持跨域请求
- ip-monitor:用于对请求ip进行风控拦截
- validator:支持验证入参和参数类型定义
独立中间件:
使用独立中间需要安装对应的独立包
- json:支持json文件用于数据存储
- static:支持静态文件目录
- form:支持formdata解析和文件上传
- config:支持高度灵活的参数配置和动态变更与监听
- log:支持灵活的日志体系,支持日志级别控制
- mysql:支持mysql连接
- mongodb:支持mongodb连接,collocation的封装
- rpc:远程调用支持,支持客户端和服务端使用,支持注入请求的x-trace-id
npm i sener
最简demo:
import {Sener} from 'sener';
new Sener();
options:
new Sener({
port: 9000, // port: default value is 9000
middlewares: [], // Sener middlewares
});
- 使用ebuild-cli
npm i ebuild-cli -g
ebuild init <Project name>
cd <Project name>
npm i
在随后的模式选择中 选择 sener 即可
- 从github地址上拷贝
git clone https://github.com/theajack/sener-best-practice.git
路由中间件
import {Sener, Router} from 'sener';
const router = new Router({
'/demo': ({ query }) => {
// or: 'get:/demo': ({ query }) => { // get: prefix can be ignored
query.message = 'from get';
return { data: query };
// Custom headers or statusCode
// return { data: query, headers: {}, statusCode: 200 };
},
'post:/demo': async ({ body }) => {
body.message = 'from post'
return { data: body };
},
});
new Sener({
middlewares: [router],
});
使用json文件进行数据存储
npm i sener sener-json
import {Sener, Router} from 'sener';
import {Json} from 'sener-json';
const router = new Router({
'/data': ({ query, read }) => {
// 'data' is json file name
return { data: read('data') };
},
'post:/data': async ({ body, write }) => {
const { data, save, id } = write('aa');
body.message = 'from post'
data.push({...body, id: id()}); // Add increment id
save(); // save it, THIS Method must be called
return { data };
},
});
new Sener({
middlewares: [router, new Json()],
});
可选参数:
new Json({
dir: '', // directory for save json files. default value is ''
format: false, // Whether to format the JSON file. Default value: The development environment is false and the production environment is true
})
npm i sener sener-cors
支持跨域请求的中间件
import {Sener, Cors} from 'sener';
new Sener({
middlewares: [new Cors()],
// new Cors(header); Or Set your custom headers
});
可选参数
new Cors({
// headers: Set your custom headers
})
支持静态资源的中间件
npm i sener sener-static
import {Sener} from 'sener';
import {Static} from 'sener-static';
new Sener({
middlewares: [new Static()],
// new Static({dir}); dir default value is ./public
});
可选参数:
new Static({
dir: './public', // Static directory, default value is ./public
})
支持form表单和文件上传的中间件
npm i sener sener-form
import {Sener, Router} from 'sener';
import {Form} from 'sener-form';
const router = new Router({
'post:/upload': ({ formData, files }) => {
return { formData, files }
},
});
new Sener({
middlewares: [new Form(), router],
// new Form({dir}); dir default value is ./public
});
可选参数
new Form({
dir: './public/upload', // File upload directory, default value is ./public/upload
})
支持日志打印和控制的中间件
npm i sener sener-log
import {Sener, Router} from 'sener';
import {Log} from 'sener-log';
const router = new Router({
'get:/test': ({ query, logger }) => {
logger.log('msg', 'payload')
return { data: query }
},
});
new Sener({
middlewares: [new Log(), router],
});
声明文件
class Logger {
log(msg: string | IMessageData, payload?: any, type?: TLogType): void;
get traceid (): string;
refreshDurationStart(): void;
refreshTraceId(): void;
}
interface IMessageData {
msg?: string;
payload?: any;
type?: 'error' | 'log' | 'warn' | 'info';
level?: number;
extend?: object;
}
可选参数
new Log({
dir: '', // 存储日志文件的目录。默认值为“”,使用根目录
useConsole: false, // 是否启用控制台.log服务运行时打印日志。不建议打开生产环境。默认值为 false
maxRecords: 10000, // 单个日志文件的最大存储记录数,默认值为 10000
level: -1, // 日志打印级别,级别小于此数字的日志将不打印
// level?: ()=>number // 级别也可以是一种动态获取级别值的方法,通常与配置中间件结合使用
})
支持灵活使用 JSON 配置文件的中间件
npm i sener sener-config
import {Sener, Router} from 'sener';
import {Config} from 'sener-config';
const router = new Router({
'get:/test': ({ query, config, writeConfig, onConfigChange }) => {
const level = config.level;
level(); // read config
level(5); // write config
writeConfig('level', 5) // write config with writeConfig
onConfigChange(({key, value, prev}) => { // on config change
console.log(key, value, prev);
})
return { data: query }
},
});
const config = new Config();
// Use config instance
config.onConfigChange(({key, value, prev}) => { // on config change
console.log(key, value, prev);
});
config.data.level(); // read config
config.data.level(5); // write config
config.writeConfig('level', 2); // write config with writeConfig
new Sener({
middlewares: [config, router],
});
options
new Config({
dir: '', // 用于保存配置文件的目录。默认值为“”
initial: {}, // 初始化配置文件列表,key表示文件名(不需要带.json后缀),值表示配置内容。默认值为 {_default: {}}
format: false, // 是否格式化 JSON 文件。默认值:开发环境为假,生产环境为真
})
支持mysql连接的中间件
npm i sener sener-mysql
import {Sener, Router} from 'sener';
import {Mysql} from 'sener-mysql';
const router = new Router({
'get:/test': async ({ query, querySql, mysqlConn }) => {
const { results, fields } = await querySql('select * from user');
// Or use mysqlConn
return { data: query }
},
});
const mysql = new Mysql({
// 详情请参考 [mysql](https://www.npmjs.com/package/mysql)
}
mysql.connection;
new Sener({
middlewares: [mysql, router],
});
详情请参考 mysql
SQL中间件封装了对表的基本操作,使得开发者可以使用API便捷的操作数据表,详情请参考文档
支持mongodb连接的中间件
npm i sener sener-mongodb
import {Sener, Router} from 'sener';
import {Mongo} from 'sener-mongodb';
const router = new Router({
'get:/test': async ({ query, queryMongoDB, mongoClient }) => {
const {db, close} = await queryMongoDB('user');
// do something
// Or use mongoClient
return { data: query }
},
});
const mongodb = new Mongo({
// 详情请参考 [mongodb](https://www.npmjs.com/package/mongodb)
})
mongodb.client;
new Sener({
middlewares: [mongodb, router],
});
详情请参考 mongodb
mongodb中间件封装了对col的基本操作,使得开发者可以使用API便捷的操作数据表,详情请参考文档
rpc 中间件作用是对部署在不同服务器或者同一服务器不同端口上的服务进行远程调用,可以让开发者像函数调用一样像远程服务发起请求
也可用于web客户端像服务端发起请求的场景
该中间还会向请求中注入 x-trace-id header来保证同一次访问调用的接口有相同的tracid,与log中间件配合使用可以很有效的定位问题
npm i sener sener-rpc
- 使用配置
import {Sener, Router} from 'sener';
import {RPC} from 'sener-rpc';
const router = new Router({
'get:/test': async ({ query, rpc }) => {
const list = rpc.comment.get('/message', {page: 1}); // url and query
// use rpc.comment.request for more details
return { data: {query, list} }
},
});
new Sener({
middlewares: [new RPC({
user: 'http://localhost:3000', // user 服务的访问base地址
comment: 'http://localhost:3001', // comment 服务的访问base地址
}), router],
});
- 使用createServices函数
import {Sener, Router} from 'sener';
import {RPC, Request} from 'sener-rpc';
class CommentRequest extends Request {
getList ({ app = 'common', index = 1 }: {
app?: string
index?: number
} = {}) {
return this.get('/message', {
app,
index,
size: 10,
});
}
}
function createServices(traceid = '') {
const base = (port: number) => `http://localhost:${port}`;
return {
comment: new CommentRequest({ base: base(3001), traceid }),
};
}
const router = new Router({
'get:/test': async ({ query, rpc }) => {
const list = rpc.comment.getList();
return { data: {query, list} }
},
});
new Sener({
middlewares: [new RPC(createServices), router],
});
- npm 安装使用
npm i sener-rpc
import {WebRPC} from 'sener-rpc/dist/web.umd';
// 1. 单个服务可以传入base地址
const comment = new WebRPC('http://localhost:3001');
await comment.get('/message', {page: 1});
// 2. 多个服务传入map
const rpc = new WebRPC({
user: 'http://localhost:3000', // user 服务的访问base地址
comment: 'http://localhost:3001', // comment 服务的访问base地址
});
await rpc.comment.get('/message', {page: 1});
// 3. 使用继承方式
class Comment extends WebRPC {
getList ({ app = 'common', index = 1 }: {
app?: string
index?: number
} = {}) {
return this.get('/message', {
app,
index,
size: 10,
});
}
}
await (new Comment()).getList();
- cdn 使用
<script src='https://cdn.jsdelivr.net/npm/sener-rpc'></script>
<script>
SenerRpc.WebRPC
</script>
- Dir
Sener 默认将所有数据文件存储在 ~/sener-data 文件夹中
let BASE_SENER_DIR = path.resolve(homedir(), './sener-data')
如果想要修改这个目录,请使用sener静态属性
Sener.Dir = 'xxxxx'
- Version
获取版本号
Sener.Version
文档将持续完善中
现在请参考 中间件包