225 lines
7.9 KiB
JavaScript
225 lines
7.9 KiB
JavaScript
"use strict";
|
|
var __defProp = Object.defineProperty;
|
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
var __export = (target, all) => {
|
|
for (var name in all)
|
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
};
|
|
var __copyProps = (to, from, except, desc) => {
|
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
for (let key of __getOwnPropNames(from))
|
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
}
|
|
return to;
|
|
};
|
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
var router_exports = {};
|
|
__export(router_exports, {
|
|
RegExpRouter: () => RegExpRouter
|
|
});
|
|
module.exports = __toCommonJS(router_exports);
|
|
var import_router = require("../../router");
|
|
var import_url = require("../../utils/url");
|
|
var import_node = require("./node");
|
|
var import_trie = require("./trie");
|
|
const emptyParam = [];
|
|
const nullMatcher = [/^$/, [], /* @__PURE__ */ Object.create(null)];
|
|
let wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
|
|
function buildWildcardRegExp(path) {
|
|
return wildcardRegExpCache[path] ??= new RegExp(
|
|
path === "*" ? "" : `^${path.replace(
|
|
/\/\*$|([.\\+*[^\]$()])/g,
|
|
(_, metaChar) => metaChar ? `\\${metaChar}` : "(?:|/.*)"
|
|
)}$`
|
|
);
|
|
}
|
|
function clearWildcardRegExpCache() {
|
|
wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
|
|
}
|
|
function buildMatcherFromPreprocessedRoutes(routes) {
|
|
const trie = new import_trie.Trie();
|
|
const handlerData = [];
|
|
if (routes.length === 0) {
|
|
return nullMatcher;
|
|
}
|
|
const routesWithStaticPathFlag = routes.map(
|
|
(route) => [!/\*|\/:/.test(route[0]), ...route]
|
|
).sort(
|
|
([isStaticA, pathA], [isStaticB, pathB]) => isStaticA ? 1 : isStaticB ? -1 : pathA.length - pathB.length
|
|
);
|
|
const staticMap = /* @__PURE__ */ Object.create(null);
|
|
for (let i = 0, j = -1, len = routesWithStaticPathFlag.length; i < len; i++) {
|
|
const [pathErrorCheckOnly, path, handlers] = routesWithStaticPathFlag[i];
|
|
if (pathErrorCheckOnly) {
|
|
staticMap[path] = [handlers.map(([h]) => [h, /* @__PURE__ */ Object.create(null)]), emptyParam];
|
|
} else {
|
|
j++;
|
|
}
|
|
let paramAssoc;
|
|
try {
|
|
paramAssoc = trie.insert(path, j, pathErrorCheckOnly);
|
|
} catch (e) {
|
|
throw e === import_node.PATH_ERROR ? new import_router.UnsupportedPathError(path) : e;
|
|
}
|
|
if (pathErrorCheckOnly) {
|
|
continue;
|
|
}
|
|
handlerData[j] = handlers.map(([h, paramCount]) => {
|
|
const paramIndexMap = /* @__PURE__ */ Object.create(null);
|
|
paramCount -= 1;
|
|
for (; paramCount >= 0; paramCount--) {
|
|
const [key, value] = paramAssoc[paramCount];
|
|
paramIndexMap[key] = value;
|
|
}
|
|
return [h, paramIndexMap];
|
|
});
|
|
}
|
|
const [regexp, indexReplacementMap, paramReplacementMap] = trie.buildRegExp();
|
|
for (let i = 0, len = handlerData.length; i < len; i++) {
|
|
for (let j = 0, len2 = handlerData[i].length; j < len2; j++) {
|
|
const map = handlerData[i][j]?.[1];
|
|
if (!map) {
|
|
continue;
|
|
}
|
|
const keys = Object.keys(map);
|
|
for (let k = 0, len3 = keys.length; k < len3; k++) {
|
|
map[keys[k]] = paramReplacementMap[map[keys[k]]];
|
|
}
|
|
}
|
|
}
|
|
const handlerMap = [];
|
|
for (const i in indexReplacementMap) {
|
|
handlerMap[i] = handlerData[indexReplacementMap[i]];
|
|
}
|
|
return [regexp, handlerMap, staticMap];
|
|
}
|
|
function findMiddleware(middleware, path) {
|
|
if (!middleware) {
|
|
return void 0;
|
|
}
|
|
for (const k of Object.keys(middleware).sort((a, b) => b.length - a.length)) {
|
|
if (buildWildcardRegExp(k).test(path)) {
|
|
return [...middleware[k]];
|
|
}
|
|
}
|
|
return void 0;
|
|
}
|
|
class RegExpRouter {
|
|
name = "RegExpRouter";
|
|
middleware;
|
|
routes;
|
|
constructor() {
|
|
this.middleware = { [import_router.METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) };
|
|
this.routes = { [import_router.METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) };
|
|
}
|
|
add(method, path, handler) {
|
|
const { middleware, routes } = this;
|
|
if (!middleware || !routes) {
|
|
throw new Error(import_router.MESSAGE_MATCHER_IS_ALREADY_BUILT);
|
|
}
|
|
if (!middleware[method]) {
|
|
;
|
|
[middleware, routes].forEach((handlerMap) => {
|
|
handlerMap[method] = /* @__PURE__ */ Object.create(null);
|
|
Object.keys(handlerMap[import_router.METHOD_NAME_ALL]).forEach((p) => {
|
|
handlerMap[method][p] = [...handlerMap[import_router.METHOD_NAME_ALL][p]];
|
|
});
|
|
});
|
|
}
|
|
if (path === "/*") {
|
|
path = "*";
|
|
}
|
|
const paramCount = (path.match(/\/:/g) || []).length;
|
|
if (/\*$/.test(path)) {
|
|
const re = buildWildcardRegExp(path);
|
|
if (method === import_router.METHOD_NAME_ALL) {
|
|
Object.keys(middleware).forEach((m) => {
|
|
middleware[m][path] ||= findMiddleware(middleware[m], path) || findMiddleware(middleware[import_router.METHOD_NAME_ALL], path) || [];
|
|
});
|
|
} else {
|
|
middleware[method][path] ||= findMiddleware(middleware[method], path) || findMiddleware(middleware[import_router.METHOD_NAME_ALL], path) || [];
|
|
}
|
|
Object.keys(middleware).forEach((m) => {
|
|
if (method === import_router.METHOD_NAME_ALL || method === m) {
|
|
Object.keys(middleware[m]).forEach((p) => {
|
|
re.test(p) && middleware[m][p].push([handler, paramCount]);
|
|
});
|
|
}
|
|
});
|
|
Object.keys(routes).forEach((m) => {
|
|
if (method === import_router.METHOD_NAME_ALL || method === m) {
|
|
Object.keys(routes[m]).forEach(
|
|
(p) => re.test(p) && routes[m][p].push([handler, paramCount])
|
|
);
|
|
}
|
|
});
|
|
return;
|
|
}
|
|
const paths = (0, import_url.checkOptionalParameter)(path) || [path];
|
|
for (let i = 0, len = paths.length; i < len; i++) {
|
|
const path2 = paths[i];
|
|
Object.keys(routes).forEach((m) => {
|
|
if (method === import_router.METHOD_NAME_ALL || method === m) {
|
|
routes[m][path2] ||= [
|
|
...findMiddleware(middleware[m], path2) || findMiddleware(middleware[import_router.METHOD_NAME_ALL], path2) || []
|
|
];
|
|
routes[m][path2].push([handler, paramCount - len + i + 1]);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
match(method, path) {
|
|
clearWildcardRegExpCache();
|
|
const matchers = this.buildAllMatchers();
|
|
this.match = (method2, path2) => {
|
|
const matcher = matchers[method2] || matchers[import_router.METHOD_NAME_ALL];
|
|
const staticMatch = matcher[2][path2];
|
|
if (staticMatch) {
|
|
return staticMatch;
|
|
}
|
|
const match = path2.match(matcher[0]);
|
|
if (!match) {
|
|
return [[], emptyParam];
|
|
}
|
|
const index = match.indexOf("", 1);
|
|
return [matcher[1][index], match];
|
|
};
|
|
return this.match(method, path);
|
|
}
|
|
buildAllMatchers() {
|
|
const matchers = /* @__PURE__ */ Object.create(null);
|
|
[...Object.keys(this.routes), ...Object.keys(this.middleware)].forEach((method) => {
|
|
matchers[method] ||= this.buildMatcher(method);
|
|
});
|
|
this.middleware = this.routes = void 0;
|
|
return matchers;
|
|
}
|
|
buildMatcher(method) {
|
|
const routes = [];
|
|
let hasOwnRoute = method === import_router.METHOD_NAME_ALL;
|
|
[this.middleware, this.routes].forEach((r) => {
|
|
const ownRoute = r[method] ? Object.keys(r[method]).map((path) => [path, r[method][path]]) : [];
|
|
if (ownRoute.length !== 0) {
|
|
hasOwnRoute ||= true;
|
|
routes.push(...ownRoute);
|
|
} else if (method !== import_router.METHOD_NAME_ALL) {
|
|
routes.push(
|
|
...Object.keys(r[import_router.METHOD_NAME_ALL]).map((path) => [path, r[import_router.METHOD_NAME_ALL][path]])
|
|
);
|
|
}
|
|
});
|
|
if (!hasOwnRoute) {
|
|
return null;
|
|
} else {
|
|
return buildMatcherFromPreprocessedRoutes(routes);
|
|
}
|
|
}
|
|
}
|
|
// Annotate the CommonJS export names for ESM import in node:
|
|
0 && (module.exports = {
|
|
RegExpRouter
|
|
});
|