hono
Version:
Web framework built on Web Standards
153 lines (152 loc) • 5.27 kB
JavaScript
// 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
};