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
}
debug with ts-node directly vscode -> F5 -> tsnode
是 vscode -> Ctrl+Shift+d -> F5 么
@waitingsong 我平时是直接F5的,默认快捷键,你说的组合键好像是调试中重启。 友情提醒ts-node调试只有6.x支持。
666
@zuohuadong 今天把坑填完了, 框架封装好了, 后面更新一下说明再发出来. 我想会给大家带来惊喜的. 写框架和用框架包括查看类型定义, 都是ts源码哦, 基本不使用type definition file, 用框架完全感受不到type definition file.
上面的示例应用已经通过npm包使用这个框架了, 剩下个小问题, 我准备搞, 如果有大佬知道怎么搞请告知: tsc的时候node_modules里的框架ts文件会报不影响运行的错误, 如何禁用. 比如: 我的tsconfig:
{
"compileOnSave": true,
"compilerOptions": {
"module": "commonjs",
"target": "es2018",
"charset": "utf8",
"noImplicitAny": true,
"esModuleInterop": true,
"resolveJsonModule": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"forceConsistentCasingInFileNames": true,
"allowSyntheticDefaultImports": true,
"noImplicitUseStrict": true,
"listEmittedFiles": true,
"removeComments": true,
"skipLibCheck": true,
"sourceMap": false,
"pretty": true,
"baseUrl": ".",
"paths": {
"*": [
"node_modules/*",
"typings/*",
],
},
"outDir": "dist",
},
"exclude": [
"node_moddules",
"codegen",
],
}
我记得 grpc 也有个纯js 的实现,不过只有 client ~ 这个要是能有 grpc 官方维护就牛皮了~
https://github.com/nestjs/nest/blob/master/tsconfig.json 附上 nest 的ts 配置参考~
@zuohuadong 这配置没大差异, 是正常的. 找到原因了. tsc --listFiles分析下来就只有我这个npm包是直接走index.ts获取类型的, 其他都是.d.ts或者.js nest那边是框架内部直接export / import definition的, 并不是动态搜索typings目录这种.