router_register.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import { Application, Context } from 'egg';
  2. /**
  3. * 记录各个routerUrl的路由配置,使用initRouter统一设置
  4. */
  5. const __router__: any = {};
  6. /**
  7. * egg suport http method
  8. */
  9. export type HttpMethod = 'get' | 'post' | 'patch' | 'delete' | 'options' | 'put' | 'all';
  10. /**
  11. * RouterOption
  12. */
  13. interface RouterOption {
  14. httpMethod: HttpMethod;
  15. handleName: string;
  16. beforeMiddlewares: any[];
  17. constructorFn: any;
  18. className: string;
  19. validator?: Validator | undefined | null;
  20. url: string;
  21. }
  22. interface Validator {
  23. params?: any;
  24. body?: any;
  25. }
  26. /**
  27. * 推入路由配置
  28. */
  29. function _setRouter(url: string, option: RouterOption) {
  30. __router__[url] = __router__[url] || [];
  31. __router__[url].push(option);
  32. }
  33. /**
  34. * 注册路由,路由信息是通过装饰器收集的
  35. * router.head - HEAD
  36. * router.options - OPTIONS
  37. * router.get - GET
  38. * router.put - PUT
  39. * router.post - POST
  40. * router.patch - PATCH
  41. * router.delete - DELETE
  42. * router.del - 由于 delete 是一个保留字,所以提供了一个 delete 方法的别名。
  43. * router.redirect - 可以对 URL 进行重定向处理,比如我们最经常使用的可以把用户访问的根目录路由到某个主页。
  44. * @param app Application
  45. */
  46. export function initRouter(app: Application) {
  47. // eslint-disable-next-line @typescript-eslint/no-unused-vars
  48. const { router } = app;
  49. Object.keys(__router__).forEach(url => {
  50. __router__[url].forEach((opt: RouterOption) => {
  51. router[opt.httpMethod](opt.url, ...opt.beforeMiddlewares, async (ctx: Context) => {
  52. const ist = new opt.constructorFn(ctx);
  53. if (opt.validator) {
  54. // 如果存在validator,则先进行参数校验
  55. if (opt.httpMethod === 'get') {
  56. const query = opt.validator.params ? await ctx.validate(opt.validator.params, ctx.request.query) : null;
  57. await ist[opt.handleName].call(ist, { query });
  58. } else {
  59. const query = opt.validator.params ? await ctx.validate(opt.validator.params, ctx.request.query) : null;
  60. const body = opt.validator.body ? await ctx.validate(opt.validator.body, ctx.request.body) : null;
  61. await ist[opt.handleName].call(ist, { body, query });
  62. }
  63. } else {
  64. await ist[opt.handleName].call(ist);
  65. }
  66. // await ist[opt.handleName].call(ist);
  67. });
  68. });
  69. });
  70. }
  71. /**
  72. * 收集路由信息,使用@Route装饰器
  73. */
  74. export function Route(url: string, method: HttpMethod, validator?: Validator, beforeMiddlewares: any[] = []) {
  75. // eslint-disable-next-line @typescript-eslint/no-unused-vars
  76. return function(target: any, funcName: string, _descriptor: PropertyDescriptor) {
  77. _setRouter(url, {
  78. httpMethod: method,
  79. beforeMiddlewares,
  80. handleName: funcName,
  81. constructorFn: target.constructor,
  82. className: target.constructor.name,
  83. validator,
  84. url,
  85. });
  86. };
  87. }
  88. const PREFIX_ADMIN = '/admin';
  89. /**
  90. * 自动添加/admin前缀的Url路由装饰器
  91. * 例如 url 为 /sys/user/add, 使用该装饰器可直接变为/admin/sys/user/add
  92. */
  93. export function AdminRoute(url: string, method: HttpMethod, validator?: Validator, beforeMiddlewares: any[] = []) {
  94. // eslint-disable-next-line @typescript-eslint/no-unused-vars
  95. return function(target: any, funcName: string, _descriptor: PropertyDescriptor) {
  96. _setRouter(url, {
  97. httpMethod: method,
  98. beforeMiddlewares,
  99. handleName: funcName,
  100. constructorFn: target.constructor,
  101. className: target.constructor.name,
  102. validator,
  103. url: `${PREFIX_ADMIN}${url}`,
  104. });
  105. };
  106. }