router-branch.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. import {Route} from '../route/index.js';
  2. import {cloneDeep} from '../utils/index.js';
  3. import {TrieRouter} from '../trie-router.js';
  4. import {InvalidArgumentError} from '@e22m4u/js-format';
  5. import {normalizePath} from '../utils/normalize-path.js';
  6. import {DebuggableService} from '../debuggable-service.js';
  7. import {validateRouteDefinition} from '../route/validate-route-definition.js';
  8. import {mergeRouterBranchDefinitions} from './merge-router-branch-definitions.js';
  9. import {validateRouterBranchDefinition} from './validate-router-branch-definition.js';
  10. /**
  11. * @typedef {import('./request-context.js').RequestContext} RequestContext
  12. * @typedef {import('../route/index.js').RoutePreHandler} RoutePreHandler
  13. * @typedef {import('../route/index.js').RoutePostHandler} RoutePostHandler
  14. * @typedef {{
  15. * path: string,
  16. * preHandler?: RoutePreHandler|(RoutePreHandler[]),
  17. * postHandler?: RoutePostHandler|(RoutePostHandler[]),
  18. * meta?: object,
  19. * }} RouterBranchDefinition
  20. */
  21. /**
  22. * Router branch.
  23. */
  24. export class RouterBranch extends DebuggableService {
  25. /**
  26. * Router.
  27. *
  28. * @type {TrieRouter}
  29. */
  30. _router;
  31. /**
  32. * Get router.
  33. *
  34. * @type {TrieRouter}
  35. */
  36. getRouter() {
  37. return this._router;
  38. }
  39. /**
  40. * Branch definition.
  41. *
  42. * @type {RouterBranchDefinition}
  43. */
  44. _definition;
  45. /**
  46. * Get branch definition.
  47. *
  48. * @type {RouterBranchDefinition}
  49. */
  50. getDefinition() {
  51. return this._definition;
  52. }
  53. /**
  54. * Parent branch.
  55. *
  56. * @type {RouterBranch|undefined}
  57. */
  58. _parentBranch;
  59. /**
  60. * Has parent branch.
  61. *
  62. * @returns {boolean}
  63. */
  64. hasParentBranch() {
  65. return Boolean(this._parentBranch);
  66. }
  67. /**
  68. * Get parent branch.
  69. *
  70. * @returns {RouterBranch|undefined}
  71. */
  72. getParentBranch() {
  73. if (!this._parentBranch) {
  74. throw new InvalidArgumentError(
  75. 'Parent branch does not exist in the router branch.',
  76. );
  77. }
  78. return this._parentBranch;
  79. }
  80. /**
  81. * Constructor.
  82. *
  83. * @param {TrieRouter} router
  84. * @param {RouterBranchDefinition} branchDef
  85. * @param {RouterBranch} [parentBranch]
  86. */
  87. constructor(router, branchDef, parentBranch) {
  88. super(router.container);
  89. if (!(router instanceof TrieRouter)) {
  90. throw new InvalidArgumentError(
  91. 'Parameter "router" must be a TrieRouter instance, but %v was given.',
  92. router,
  93. );
  94. }
  95. this._router = router;
  96. if (parentBranch !== undefined && !(parentBranch instanceof RouterBranch)) {
  97. throw new InvalidArgumentError(
  98. 'Parameter "parentBranch" must be a RouterBranch instance, ' +
  99. 'but %v was given.',
  100. parentBranch,
  101. );
  102. }
  103. this._parentBranch = parentBranch;
  104. if (parentBranch) {
  105. const mergedDef = mergeRouterBranchDefinitions(
  106. parentBranch.getDefinition(),
  107. branchDef,
  108. );
  109. this._definition = cloneDeep(mergedDef);
  110. } else {
  111. validateRouterBranchDefinition(branchDef);
  112. this._definition = cloneDeep(branchDef);
  113. }
  114. this.ctorDebug('Branch %v created.', normalizePath(branchDef.path, true));
  115. this.ctorDebug('Branch path was %v.', this._definition.path);
  116. }
  117. /**
  118. * Define route.
  119. *
  120. * @param {import('../route/index.js').RouteDefinition} routeDef
  121. * @returns {Route}
  122. */
  123. defineRoute(routeDef) {
  124. validateRouteDefinition(routeDef);
  125. const {method, handler, ...routeDefAsBranchDef} = routeDef;
  126. const mergedDef = mergeRouterBranchDefinitions(
  127. this._definition,
  128. routeDefAsBranchDef,
  129. );
  130. mergedDef.method = method;
  131. mergedDef.handler = handler;
  132. return this._router.defineRoute(mergedDef);
  133. }
  134. /**
  135. * Create branch.
  136. *
  137. * @param {RouterBranch} branchDef
  138. * @returns {RouterBranch}
  139. */
  140. createBranch(branchDef) {
  141. return new RouterBranch(this._router, branchDef, this);
  142. }
  143. }