1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-01 09:24:20 -04:00
denoland-deno/cli/bench/testdata/npm/hono/dist/router/trie-router/node.js

169 lines
6.6 KiB
JavaScript
Raw Normal View History

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Node = void 0;
const router_1 = require("../../router");
const url_1 = require("../../utils/url");
function findParam(node, name) {
for (let i = 0, len = node.patterns.length; i < len; i++) {
if (typeof node.patterns[i] === 'object' && node.patterns[i][1] === name) {
return true;
}
}
const nodes = Object.values(node.children);
for (let i = 0, len = nodes.length; i < len; i++) {
if (findParam(nodes[i], name)) {
return true;
}
}
return false;
}
class Node {
constructor(method, handler, children) {
this.order = 0;
this.children = children || {};
this.methods = [];
this.name = '';
if (method && handler) {
const m = {};
m[method] = { handler: handler, score: 0, name: this.name };
this.methods = [m];
}
this.patterns = [];
this.handlerSetCache = {};
}
insert(method, path, handler) {
this.name = `${method} ${path}`;
this.order = ++this.order;
// eslint-disable-next-line @typescript-eslint/no-this-alias
let curNode = this;
const parts = (0, url_1.splitPath)(path);
const parentPatterns = [];
const errorMessage = (name) => {
return `Duplicate param name, use another name instead of '${name}' - ${method} ${path} <--- '${name}'`;
};
for (let i = 0, len = parts.length; i < len; i++) {
const p = parts[i];
if (Object.keys(curNode.children).includes(p)) {
parentPatterns.push(...curNode.patterns);
curNode = curNode.children[p];
continue;
}
curNode.children[p] = new Node();
const pattern = (0, url_1.getPattern)(p);
if (pattern) {
if (typeof pattern === 'object') {
for (let j = 0, len = parentPatterns.length; j < len; j++) {
if (typeof parentPatterns[j] === 'object' && parentPatterns[j][1] === pattern[1]) {
throw new Error(errorMessage(pattern[1]));
}
}
if (Object.values(curNode.children).some((n) => findParam(n, pattern[1]))) {
throw new Error(errorMessage(pattern[1]));
}
}
curNode.patterns.push(pattern);
parentPatterns.push(...curNode.patterns);
}
parentPatterns.push(...curNode.patterns);
curNode = curNode.children[p];
}
if (!curNode.methods.length) {
curNode.methods = [];
}
const m = {};
const handlerSet = { handler: handler, name: this.name, score: this.order };
m[method] = handlerSet;
curNode.methods.push(m);
return curNode;
}
getHandlerSets(node, method, wildcard) {
var _a, _b;
return ((_a = node.handlerSetCache)[_b = `${method}:${wildcard ? '1' : '0'}`] || (_a[_b] = (() => {
const handlerSets = [];
node.methods.map((m) => {
const handlerSet = m[method] || m[router_1.METHOD_NAME_ALL];
if (handlerSet !== undefined) {
const hs = { ...handlerSet };
handlerSets.push(hs);
return;
}
});
return handlerSets;
})()));
}
search(method, path) {
const handlerSets = [];
const params = {};
// eslint-disable-next-line @typescript-eslint/no-this-alias
const curNode = this;
let curNodes = [curNode];
const parts = (0, url_1.splitPath)(path);
for (let i = 0, len = parts.length; i < len; i++) {
const part = parts[i];
const isLast = i === len - 1;
const tempNodes = [];
let matched = false;
for (let j = 0, len2 = curNodes.length; j < len2; j++) {
const node = curNodes[j];
const nextNode = node.children[part];
if (nextNode) {
if (isLast === true) {
// '/hello/*' => match '/hello'
if (nextNode.children['*']) {
handlerSets.push(...this.getHandlerSets(nextNode.children['*'], method, true));
}
handlerSets.push(...this.getHandlerSets(nextNode, method));
matched = true;
}
tempNodes.push(nextNode);
}
for (let k = 0, len3 = node.patterns.length; k < len3; k++) {
const pattern = node.patterns[k];
// Wildcard
// '/hello/*/foo' => match /hello/bar/foo
if (pattern === '*') {
const astNode = node.children['*'];
if (astNode) {
handlerSets.push(...this.getHandlerSets(astNode, method));
tempNodes.push(astNode);
}
continue;
}
if (part === '')
continue;
// Named match
// `/posts/:id` => match /posts/123
const [key, name, matcher] = pattern;
if (matcher === true || (matcher instanceof RegExp && matcher.test(part))) {
if (typeof key === 'string') {
if (isLast === true) {
handlerSets.push(...this.getHandlerSets(node.children[key], method));
}
tempNodes.push(node.children[key]);
}
// '/book/a' => not-slug
// '/book/:slug' => slug
// GET /book/a ~> no-slug, param['slug'] => undefined
// GET /book/foo ~> slug, param['slug'] => foo
if (typeof name === 'string' && !matched) {
params[name] = part;
}
}
}
}
curNodes = tempNodes;
}
if (handlerSets.length <= 0)
return null;
const handlers = handlerSets
.sort((a, b) => {
return a.score - b.score;
})
.map((s) => {
return s.handler;
});
return { handlers, params };
}
}
exports.Node = Node;