UNPKG

hono

Version:

Web framework built on Web Standards

153 lines (152 loc) 5.27 kB
// src/router/trie-router/node.ts import { METHOD_NAME_ALL } from "../../router.js"; import { getPattern, splitPath, splitRoutingPath } from "../../utils/url.js"; var Node = class { methods; children; patterns; order = 0; name; params = /* @__PURE__ */ Object.create(null); constructor(method, handler, children) { this.children = children || /* @__PURE__ */ Object.create(null); this.methods = []; this.name = ""; if (method && handler) { const m = /* @__PURE__ */ Object.create(null); m[method] = { handler, possibleKeys: [], score: 0, name: this.name }; this.methods = [m]; } this.patterns = []; } insert(method, path, handler) { this.name = `${method} ${path}`; this.order = ++this.order; let curNode = this; const parts = splitRoutingPath(path); const possibleKeys = []; for (let i = 0, len = parts.length; i < len; i++) { const p = parts[i]; if (Object.keys(curNode.children).includes(p)) { curNode = curNode.children[p]; const pattern2 = getPattern(p); if (pattern2) { possibleKeys.push(pattern2[1]); } continue; } curNode.children[p] = new Node(); const pattern = getPattern(p); if (pattern) { curNode.patterns.push(pattern); possibleKeys.push(pattern[1]); } curNode = curNode.children[p]; } if (!curNode.methods.length) { curNode.methods = []; } const m = /* @__PURE__ */ Object.create(null); const handlerSet = { handler, possibleKeys: possibleKeys.filter((v, i, a) => a.indexOf(v) === i), name: this.name, score: this.order }; m[method] = handlerSet; curNode.methods.push(m); return curNode; } gHSets(node, method, nodeParams, params) { const handlerSets = []; for (let i = 0, len = node.methods.length; i < len; i++) { const m = node.methods[i]; const handlerSet = m[method] || m[METHOD_NAME_ALL]; const processedSet = /* @__PURE__ */ Object.create(null); if (handlerSet !== void 0) { handlerSet.params = /* @__PURE__ */ Object.create(null); handlerSet.possibleKeys.forEach((key) => { const processed = processedSet[handlerSet.name]; handlerSet.params[key] = params[key] && !processed ? params[key] : nodeParams[key] ?? params[key]; processedSet[handlerSet.name] = true; }); handlerSets.push(handlerSet); } } return handlerSets; } search(method, path) { const handlerSets = []; this.params = /* @__PURE__ */ Object.create(null); const curNode = this; let curNodes = [curNode]; const parts = splitPath(path); for (let i = 0, len = parts.length; i < len; i++) { const part = parts[i]; const isLast = i === len - 1; const tempNodes = []; for (let j = 0, len2 = curNodes.length; j < len2; j++) { const node = curNodes[j]; const nextNode = node.children[part]; if (nextNode) { nextNode.params = node.params; if (isLast === true) { if (nextNode.children["*"]) { handlerSets.push( ...this.gHSets(nextNode.children["*"], method, node.params, /* @__PURE__ */ Object.create(null)) ); } handlerSets.push(...this.gHSets(nextNode, method, node.params, /* @__PURE__ */ Object.create(null))); } else { tempNodes.push(nextNode); } } for (let k = 0, len3 = node.patterns.length; k < len3; k++) { const pattern = node.patterns[k]; const params = { ...node.params }; if (pattern === "*") { const astNode = node.children["*"]; if (astNode) { handlerSets.push(...this.gHSets(astNode, method, node.params, /* @__PURE__ */ Object.create(null))); tempNodes.push(astNode); } continue; } if (part === "") { continue; } const [key, name, matcher] = pattern; const child = node.children[key]; const restPathString = parts.slice(i).join("/"); if (matcher instanceof RegExp && matcher.test(restPathString)) { params[name] = restPathString; handlerSets.push(...this.gHSets(child, method, node.params, params)); continue; } if (matcher === true || matcher instanceof RegExp && matcher.test(part)) { if (typeof key === "string") { params[name] = part; if (isLast === true) { handlerSets.push(...this.gHSets(child, method, params, node.params)); if (child.children["*"]) { handlerSets.push(...this.gHSets(child.children["*"], method, params, node.params)); } } else { child.params = params; tempNodes.push(child); } } } } } curNodes = tempNodes; } const results = handlerSets.sort((a, b) => { return a.score - b.score; }); return [results.map(({ handler, params }) => [handler, params])]; } }; export { Node };