router.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. // src/router/linear-router/router.ts
  2. import { METHOD_NAME_ALL, UnsupportedPathError } from "../../router.js";
  3. import { checkOptionalParameter } from "../../utils/url.js";
  4. var emptyParams = /* @__PURE__ */ Object.create(null);
  5. var splitPathRe = /\/(:\w+(?:{(?:(?:{[\d,]+})|[^}])+})?)|\/[^\/\?]+|(\?)/g;
  6. var splitByStarRe = /\*/;
  7. var LinearRouter = class {
  8. name = "LinearRouter";
  9. #routes = [];
  10. add(method, path, handler) {
  11. for (let i = 0, paths = checkOptionalParameter(path) || [path], len = paths.length; i < len; i++) {
  12. this.#routes.push([method, paths[i], handler]);
  13. }
  14. }
  15. match(method, path) {
  16. const handlers = [];
  17. ROUTES_LOOP: for (let i = 0, len = this.#routes.length; i < len; i++) {
  18. const [routeMethod, routePath, handler] = this.#routes[i];
  19. if (routeMethod === method || routeMethod === METHOD_NAME_ALL) {
  20. if (routePath === "*" || routePath === "/*") {
  21. handlers.push([handler, emptyParams]);
  22. continue;
  23. }
  24. const hasStar = routePath.indexOf("*") !== -1;
  25. const hasLabel = routePath.indexOf(":") !== -1;
  26. if (!hasStar && !hasLabel) {
  27. if (routePath === path || routePath + "/" === path) {
  28. handlers.push([handler, emptyParams]);
  29. }
  30. } else if (hasStar && !hasLabel) {
  31. const endsWithStar = routePath.charCodeAt(routePath.length - 1) === 42;
  32. const parts = (endsWithStar ? routePath.slice(0, -2) : routePath).split(splitByStarRe);
  33. const lastIndex = parts.length - 1;
  34. for (let j = 0, pos = 0, len2 = parts.length; j < len2; j++) {
  35. const part = parts[j];
  36. const index = path.indexOf(part, pos);
  37. if (index !== pos) {
  38. continue ROUTES_LOOP;
  39. }
  40. pos += part.length;
  41. if (j === lastIndex) {
  42. if (!endsWithStar && pos !== path.length && !(pos === path.length - 1 && path.charCodeAt(pos) === 47)) {
  43. continue ROUTES_LOOP;
  44. }
  45. } else {
  46. const index2 = path.indexOf("/", pos);
  47. if (index2 === -1) {
  48. continue ROUTES_LOOP;
  49. }
  50. pos = index2;
  51. }
  52. }
  53. handlers.push([handler, emptyParams]);
  54. } else if (hasLabel && !hasStar) {
  55. const params = /* @__PURE__ */ Object.create(null);
  56. const parts = routePath.match(splitPathRe);
  57. const lastIndex = parts.length - 1;
  58. for (let j = 0, pos = 0, len2 = parts.length; j < len2; j++) {
  59. if (pos === -1 || pos >= path.length) {
  60. continue ROUTES_LOOP;
  61. }
  62. const part = parts[j];
  63. if (part.charCodeAt(1) === 58) {
  64. if (path.charCodeAt(pos) !== 47) {
  65. continue ROUTES_LOOP;
  66. }
  67. let name = part.slice(2);
  68. let value;
  69. if (name.charCodeAt(name.length - 1) === 125) {
  70. const openBracePos = name.indexOf("{");
  71. const next = parts[j + 1];
  72. const lookahead = next && next[1] !== ":" && next[1] !== "*" ? `(?=${next})` : "";
  73. const pattern = name.slice(openBracePos + 1, -1) + lookahead;
  74. const restPath = path.slice(pos + 1);
  75. const match = new RegExp(pattern, "d").exec(restPath);
  76. if (!match || match.indices[0][0] !== 0 || match.indices[0][1] === 0) {
  77. continue ROUTES_LOOP;
  78. }
  79. name = name.slice(0, openBracePos);
  80. value = restPath.slice(...match.indices[0]);
  81. pos += match.indices[0][1] + 1;
  82. } else {
  83. let endValuePos = path.indexOf("/", pos + 1);
  84. if (endValuePos === -1) {
  85. if (pos + 1 === path.length) {
  86. continue ROUTES_LOOP;
  87. }
  88. endValuePos = path.length;
  89. }
  90. value = path.slice(pos + 1, endValuePos);
  91. pos = endValuePos;
  92. }
  93. params[name] ||= value;
  94. } else {
  95. const index = path.indexOf(part, pos);
  96. if (index !== pos) {
  97. continue ROUTES_LOOP;
  98. }
  99. pos += part.length;
  100. }
  101. if (j === lastIndex) {
  102. if (pos !== path.length && !(pos === path.length - 1 && path.charCodeAt(pos) === 47)) {
  103. continue ROUTES_LOOP;
  104. }
  105. }
  106. }
  107. handlers.push([handler, params]);
  108. } else if (hasLabel && hasStar) {
  109. throw new UnsupportedPathError();
  110. }
  111. }
  112. }
  113. return [handlers];
  114. }
  115. };
  116. export {
  117. LinearRouter
  118. };