Files
SnowLuma/.pnpm-store/v11/files/28/8ab0f59cedd354fa723070b5291542d094396aea79f37b4d5320e2e12087d49bb27d52eb764d04ecb3217dd9de611bcce0fee7e5e73aef0b67c7dd4da4c175
T
TanTan 2a69b23b47
Dev Build / cleanup (push) Waiting to run
Dev Build / typecheck (push) Waiting to run
docs: 仓库链接指向本镜像仓库
2026-11-13 09:27:07 +08:00

135 lines
4.5 KiB
Plaintext

import { getPattern, splitPath, splitRoutingPath } from "../../utils/url.js";
import "../../router.js";
import { createNullObject } from "../utils.js";
//#region src/router/trie-router/node.ts
const emptyParams = createNullObject();
let order = 0;
var Node = class Node {
#methods = [];
#children = createNullObject();
#patterns = [];
#pattern;
#params = emptyParams;
insert(method, path, handler) {
let curNode = this;
const parts = splitRoutingPath(path);
const possibleKeys = /* @__PURE__ */ new Set();
let i = 0;
for (const p of parts) {
const nextP = parts[++i];
const pattern = getPattern(p, nextP) || (nextP === void 0 && p && p.indexOf("*") === p.length - 1 ? p : null);
const isParam = Array.isArray(pattern);
const key = isParam ? pattern[0] : pattern || p;
const child = curNode.#children[key] ||= new Node();
if (pattern && !child.#pattern) {
child.#pattern = pattern;
curNode.#patterns.push(child);
}
curNode = child;
if (isParam) possibleKeys.add(pattern[1]);
}
curNode.#methods.push({ [method]: {
handler,
possibleKeys: [...possibleKeys],
score: ++order
} });
}
#pushHandlerSets(handlerSets, node, method, nodeParams, params) {
for (let i = 0, len = node.#methods.length; i < len; i++) {
const m = node.#methods[i];
const handlerSet = m[method] || m["ALL"];
if (handlerSet) {
handlerSet.params = createNullObject();
handlerSets.push(handlerSet);
for (let i = 0, len = handlerSet.possibleKeys.length; i < len; i++) {
const key = handlerSet.possibleKeys[i];
handlerSet.params[key] = params?.[key] && !i ? params[key] : nodeParams[key] ?? params?.[key];
}
}
}
}
search(method, path) {
const handlerSets = [];
this.#params = emptyParams;
let curNodes = [this];
const parts = splitPath(path);
const curNodesQueue = [];
const len = parts.length;
let partOffsets = null;
for (let i = 0; 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) {
if (nextNode.#children["*"]) this.#pushHandlerSets(handlerSets, nextNode.#children["*"], method, node.#params);
this.#pushHandlerSets(handlerSets, nextNode, method, node.#params);
} else tempNodes.push(nextNode);
}
for (const child of node.#patterns) {
const pattern = child.#pattern;
const params = node.#params === emptyParams ? {} : { ...node.#params };
if (typeof pattern === "string") {
if (pattern === "*" || part.startsWith(pattern.slice(0, -1))) {
this.#pushHandlerSets(handlerSets, child, method, node.#params);
if (pattern === "*") {
child.#params = params;
tempNodes.push(child);
}
}
continue;
}
const [, name, matcher] = pattern;
if (!part && matcher === true) continue;
if (matcher !== true) {
if (!partOffsets) {
partOffsets = [];
let offset = path[0] === "/" ? 1 : 0;
for (let p = 0; p < len; p++) {
partOffsets[p] = offset;
offset += parts[p].length + 1;
}
}
const restPathString = path.slice(partOffsets[i]);
const m = matcher.exec(restPathString);
if (m) {
params[name] = m[0];
this.#pushHandlerSets(handlerSets, child, method, node.#params, params);
if (m[0].length === restPathString.length && child.#children["*"]) this.#pushHandlerSets(handlerSets, child.#children["*"], method, node.#params, params);
for (const _ in child.#children) {
child.#params = params;
const componentCount = m[0].match(/\//g)?.length ?? 0;
(curNodesQueue[componentCount] ||= []).push(child);
break;
}
continue;
}
}
if (matcher === true || matcher.test(part)) {
params[name] = part;
if (isLast) {
this.#pushHandlerSets(handlerSets, child, method, params, node.#params);
if (child.#children["*"]) this.#pushHandlerSets(handlerSets, child.#children["*"], method, params, node.#params);
} else {
child.#params = params;
tempNodes.push(child);
}
}
}
}
const shifted = curNodesQueue.shift();
curNodes = shifted ? tempNodes.concat(shifted) : tempNodes;
}
if (handlerSets[1]) handlerSets.sort((a, b) => {
return a.score - b.score;
});
return [handlerSets.map(({ handler, params }) => [handler, params])];
}
};
//#endregion
export { Node };