850650
proto定义好接口即可一条命令生成controller及引用的类型的定义 (class & interface). 效仿egg的『约定优于配置』原则, config, midware, controller, 相关type定义等只要按约定放到相应的文件夹即可.
框架还未单独封装, 现在放在framework目录下. 代码生成器还未单独封装, 现在放在codegen目录下. 这些现在是我的业余兴趣, 会利用闲余时间阶段性添加功能.😂 https://github.com/xiaozhongliu/ts-rpc-seed
代码生成
ts-node codegen
运行服务
# 本地使用vscode的话直接进F5调试typescript
# 或者:
npm run tsc
node dist/app.js
测试请求
ts-node tester
# 或者:
npm run tsc
node dist/tester.js
代码样例
入口app.ts
import App from './framework'
new App().start()
config
export default (appInfo: AppInfo): Config => {
return {
// basic
PORT: 50051,
// log
COMMON_LOG_PATH: `${appInfo.rootPath}/log/common`,
REQUEST_LOG_PATH: `${appInfo.rootPath}/log/request`,
}
}
midware
import { Context } from '../framework'
import 'dayjs/locale/zh-cn'
import dayjs from 'dayjs'
dayjs.locale('zh-cn')
export default async (ctx: Context, req: object, next: Function) => {
const start = dayjs()
await next()
const end = dayjs()
ctx.logger.request({
'@duration': end.diff(start, 'millisecond'),
controller: `${ctx.controller}.${ctx.action}`,
metedata: JSON.stringify(ctx.metadata),
request: JSON.stringify(req),
response: JSON.stringify(ctx.response),
})
}
controller
import { Controller, Context } from '../framework'
import HelloReply from '../typings/greeter/HelloReply'
export default class GreeterController extends Controller {
async sayHello(ctx: Context, req: HelloRequest): Promise<HelloReply> {
return new HelloReply(
`Hello ${req.name}`,
)
}
async sayGoodbye(ctx: Context, req: HelloRequest): Promise<HelloReply> {
return new HelloReply(
`Goodbye ${req.name}`,
)
}
}
请求日志输出类似
下一项功能
把在这里用的参数校验中间件搬过来, 用class-validator和class-transformer实现这样的效果, 并大部分自动生成:
import { IsOptional, Length, Min, Max, IsBoolean } from 'class-validator'
export default class IndexRequest {
@Length(4, 8)
@IsOptional()
foo: string
@Min(5)
@Max(10)
@IsOptional()
bar: number
@IsBoolean()
@IsOptional()
baz: boolean
}