full site update
This commit is contained in:
268
node_modules/radix3/dist/index.cjs
generated
vendored
Normal file
268
node_modules/radix3/dist/index.cjs
generated
vendored
Normal file
@@ -0,0 +1,268 @@
|
||||
'use strict';
|
||||
|
||||
const NODE_TYPES = {
|
||||
NORMAL: 0,
|
||||
WILDCARD: 1,
|
||||
PLACEHOLDER: 2
|
||||
};
|
||||
|
||||
function createRouter(options = {}) {
|
||||
const ctx = {
|
||||
options,
|
||||
rootNode: createRadixNode(),
|
||||
staticRoutesMap: {}
|
||||
};
|
||||
const normalizeTrailingSlash = (p) => options.strictTrailingSlash ? p : p.replace(/\/$/, "") || "/";
|
||||
if (options.routes) {
|
||||
for (const path in options.routes) {
|
||||
insert(ctx, normalizeTrailingSlash(path), options.routes[path]);
|
||||
}
|
||||
}
|
||||
return {
|
||||
ctx,
|
||||
lookup: (path) => lookup(ctx, normalizeTrailingSlash(path)),
|
||||
insert: (path, data) => insert(ctx, normalizeTrailingSlash(path), data),
|
||||
remove: (path) => remove(ctx, normalizeTrailingSlash(path))
|
||||
};
|
||||
}
|
||||
function lookup(ctx, path) {
|
||||
const staticPathNode = ctx.staticRoutesMap[path];
|
||||
if (staticPathNode) {
|
||||
return staticPathNode.data;
|
||||
}
|
||||
const sections = path.split("/");
|
||||
const params = {};
|
||||
let paramsFound = false;
|
||||
let wildcardNode = null;
|
||||
let node = ctx.rootNode;
|
||||
let wildCardParam = null;
|
||||
for (let i = 0; i < sections.length; i++) {
|
||||
const section = sections[i];
|
||||
if (node.wildcardChildNode !== null) {
|
||||
wildcardNode = node.wildcardChildNode;
|
||||
wildCardParam = sections.slice(i).join("/");
|
||||
}
|
||||
const nextNode = node.children.get(section);
|
||||
if (nextNode === void 0) {
|
||||
if (node && node.placeholderChildren.length > 1) {
|
||||
const remaining = sections.length - i;
|
||||
node = node.placeholderChildren.find((c) => c.maxDepth === remaining) || null;
|
||||
} else {
|
||||
node = node.placeholderChildren[0] || null;
|
||||
}
|
||||
if (!node) {
|
||||
break;
|
||||
}
|
||||
if (node.paramName) {
|
||||
params[node.paramName] = section;
|
||||
}
|
||||
paramsFound = true;
|
||||
} else {
|
||||
node = nextNode;
|
||||
}
|
||||
}
|
||||
if ((node === null || node.data === null) && wildcardNode !== null) {
|
||||
node = wildcardNode;
|
||||
params[node.paramName || "_"] = wildCardParam;
|
||||
paramsFound = true;
|
||||
}
|
||||
if (!node) {
|
||||
return null;
|
||||
}
|
||||
if (paramsFound) {
|
||||
return {
|
||||
...node.data,
|
||||
params: paramsFound ? params : void 0
|
||||
};
|
||||
}
|
||||
return node.data;
|
||||
}
|
||||
function insert(ctx, path, data) {
|
||||
let isStaticRoute = true;
|
||||
const sections = path.split("/");
|
||||
let node = ctx.rootNode;
|
||||
let _unnamedPlaceholderCtr = 0;
|
||||
const matchedNodes = [node];
|
||||
for (const section of sections) {
|
||||
let childNode;
|
||||
if (childNode = node.children.get(section)) {
|
||||
node = childNode;
|
||||
} else {
|
||||
const type = getNodeType(section);
|
||||
childNode = createRadixNode({ type, parent: node });
|
||||
node.children.set(section, childNode);
|
||||
if (type === NODE_TYPES.PLACEHOLDER) {
|
||||
childNode.paramName = section === "*" ? `_${_unnamedPlaceholderCtr++}` : section.slice(1);
|
||||
node.placeholderChildren.push(childNode);
|
||||
isStaticRoute = false;
|
||||
} else if (type === NODE_TYPES.WILDCARD) {
|
||||
node.wildcardChildNode = childNode;
|
||||
childNode.paramName = section.slice(
|
||||
3
|
||||
/* "**:" */
|
||||
) || "_";
|
||||
isStaticRoute = false;
|
||||
}
|
||||
matchedNodes.push(childNode);
|
||||
node = childNode;
|
||||
}
|
||||
}
|
||||
for (const [depth, node2] of matchedNodes.entries()) {
|
||||
node2.maxDepth = Math.max(matchedNodes.length - depth, node2.maxDepth || 0);
|
||||
}
|
||||
node.data = data;
|
||||
if (isStaticRoute === true) {
|
||||
ctx.staticRoutesMap[path] = node;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
function remove(ctx, path) {
|
||||
let success = false;
|
||||
const sections = path.split("/");
|
||||
let node = ctx.rootNode;
|
||||
for (const section of sections) {
|
||||
node = node.children.get(section);
|
||||
if (!node) {
|
||||
return success;
|
||||
}
|
||||
}
|
||||
if (node.data) {
|
||||
const lastSection = sections.at(-1) || "";
|
||||
node.data = null;
|
||||
if (Object.keys(node.children).length === 0 && node.parent) {
|
||||
node.parent.children.delete(lastSection);
|
||||
node.parent.wildcardChildNode = null;
|
||||
node.parent.placeholderChildren = [];
|
||||
}
|
||||
success = true;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
function createRadixNode(options = {}) {
|
||||
return {
|
||||
type: options.type || NODE_TYPES.NORMAL,
|
||||
maxDepth: 0,
|
||||
parent: options.parent || null,
|
||||
children: /* @__PURE__ */ new Map(),
|
||||
data: options.data || null,
|
||||
paramName: options.paramName || null,
|
||||
wildcardChildNode: null,
|
||||
placeholderChildren: []
|
||||
};
|
||||
}
|
||||
function getNodeType(str) {
|
||||
if (str.startsWith("**")) {
|
||||
return NODE_TYPES.WILDCARD;
|
||||
}
|
||||
if (str[0] === ":" || str === "*") {
|
||||
return NODE_TYPES.PLACEHOLDER;
|
||||
}
|
||||
return NODE_TYPES.NORMAL;
|
||||
}
|
||||
|
||||
function toRouteMatcher(router) {
|
||||
const table = _routerNodeToTable("", router.ctx.rootNode);
|
||||
return _createMatcher(table, router.ctx.options.strictTrailingSlash);
|
||||
}
|
||||
function _createMatcher(table, strictTrailingSlash) {
|
||||
return {
|
||||
ctx: { table },
|
||||
matchAll: (path) => _matchRoutes(path, table, strictTrailingSlash)
|
||||
};
|
||||
}
|
||||
function _createRouteTable() {
|
||||
return {
|
||||
static: /* @__PURE__ */ new Map(),
|
||||
wildcard: /* @__PURE__ */ new Map(),
|
||||
dynamic: /* @__PURE__ */ new Map()
|
||||
};
|
||||
}
|
||||
function _exportMatcherFromTable(table) {
|
||||
const obj = /* @__PURE__ */ Object.create(null);
|
||||
for (const property in table) {
|
||||
obj[property] = property === "dynamic" ? Object.fromEntries(
|
||||
[...table[property].entries()].map(([key, value]) => [
|
||||
key,
|
||||
_exportMatcherFromTable(value)
|
||||
])
|
||||
) : Object.fromEntries(table[property].entries());
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
function exportMatcher(matcher) {
|
||||
return _exportMatcherFromTable(matcher.ctx.table);
|
||||
}
|
||||
function _createTableFromExport(matcherExport) {
|
||||
const table = {};
|
||||
for (const property in matcherExport) {
|
||||
table[property] = property === "dynamic" ? new Map(
|
||||
Object.entries(matcherExport[property]).map(([key, value]) => [
|
||||
key,
|
||||
_createTableFromExport(value)
|
||||
])
|
||||
) : new Map(
|
||||
Object.entries(matcherExport[property])
|
||||
);
|
||||
}
|
||||
return table;
|
||||
}
|
||||
function createMatcherFromExport(matcherExport) {
|
||||
return _createMatcher(_createTableFromExport(matcherExport));
|
||||
}
|
||||
function _matchRoutes(path, table, strictTrailingSlash) {
|
||||
if (strictTrailingSlash !== true && path.endsWith("/")) {
|
||||
path = path.slice(0, -1) || "/";
|
||||
}
|
||||
const matches = [];
|
||||
for (const [key, value] of _sortRoutesMap(table.wildcard)) {
|
||||
if (path === key || path.startsWith(key + "/")) {
|
||||
matches.push(value);
|
||||
}
|
||||
}
|
||||
for (const [key, value] of _sortRoutesMap(table.dynamic)) {
|
||||
if (path.startsWith(key + "/")) {
|
||||
const subPath = "/" + path.slice(key.length).split("/").splice(2).join("/");
|
||||
matches.push(..._matchRoutes(subPath, value));
|
||||
}
|
||||
}
|
||||
const staticMatch = table.static.get(path);
|
||||
if (staticMatch) {
|
||||
matches.push(staticMatch);
|
||||
}
|
||||
return matches.filter(Boolean);
|
||||
}
|
||||
function _sortRoutesMap(m) {
|
||||
return [...m.entries()].sort((a, b) => a[0].length - b[0].length);
|
||||
}
|
||||
function _routerNodeToTable(initialPath, initialNode) {
|
||||
const table = _createRouteTable();
|
||||
function _addNode(path, node) {
|
||||
if (path) {
|
||||
if (node.type === NODE_TYPES.NORMAL && !(path.includes("*") || path.includes(":"))) {
|
||||
if (node.data) {
|
||||
table.static.set(path, node.data);
|
||||
}
|
||||
} else if (node.type === NODE_TYPES.WILDCARD) {
|
||||
table.wildcard.set(path.replace("/**", ""), node.data);
|
||||
} else if (node.type === NODE_TYPES.PLACEHOLDER) {
|
||||
const subTable = _routerNodeToTable("", node);
|
||||
if (node.data) {
|
||||
subTable.static.set("/", node.data);
|
||||
}
|
||||
table.dynamic.set(path.replace(/\/\*|\/:\w+/, ""), subTable);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (const [childPath, child] of node.children.entries()) {
|
||||
_addNode(`${path}/${childPath}`.replace("//", "/"), child);
|
||||
}
|
||||
}
|
||||
_addNode(initialPath, initialNode);
|
||||
return table;
|
||||
}
|
||||
|
||||
exports.NODE_TYPES = NODE_TYPES;
|
||||
exports.createMatcherFromExport = createMatcherFromExport;
|
||||
exports.createRouter = createRouter;
|
||||
exports.exportMatcher = exportMatcher;
|
||||
exports.toRouteMatcher = toRouteMatcher;
|
86
node_modules/radix3/dist/index.d.cts
generated
vendored
Normal file
86
node_modules/radix3/dist/index.d.cts
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
declare const NODE_TYPES: {
|
||||
NORMAL: 0;
|
||||
WILDCARD: 1;
|
||||
PLACEHOLDER: 2;
|
||||
};
|
||||
type _NODE_TYPES = typeof NODE_TYPES;
|
||||
type NODE_TYPE = _NODE_TYPES[keyof _NODE_TYPES];
|
||||
type _RadixNodeDataObject = {
|
||||
params?: never;
|
||||
[key: string]: any;
|
||||
};
|
||||
type RadixNodeData<T extends _RadixNodeDataObject = _RadixNodeDataObject> = T;
|
||||
type MatchedRoute<T extends RadixNodeData = RadixNodeData> = Omit<T, "params"> & {
|
||||
params?: Record<string, any>;
|
||||
};
|
||||
interface RadixNode<T extends RadixNodeData = RadixNodeData> {
|
||||
type: NODE_TYPE;
|
||||
maxDepth: number;
|
||||
parent: RadixNode<T> | null;
|
||||
children: Map<string, RadixNode<T>>;
|
||||
data: RadixNodeData | null;
|
||||
paramName: string | null;
|
||||
wildcardChildNode: RadixNode<T> | null;
|
||||
placeholderChildren: RadixNode<T>[];
|
||||
}
|
||||
interface RadixRouterOptions {
|
||||
strictTrailingSlash?: boolean;
|
||||
routes?: Record<string, any>;
|
||||
}
|
||||
interface RadixRouterContext<T extends RadixNodeData = RadixNodeData> {
|
||||
options: RadixRouterOptions;
|
||||
rootNode: RadixNode<T>;
|
||||
staticRoutesMap: Record<string, RadixNode>;
|
||||
}
|
||||
interface RadixRouter<T extends RadixNodeData = RadixNodeData> {
|
||||
ctx: RadixRouterContext<T>;
|
||||
/**
|
||||
* Perform lookup of given path in radix tree
|
||||
* @param path - the path to search for
|
||||
*
|
||||
* @returns The data that was originally inserted into the tree
|
||||
*/
|
||||
lookup(path: string): MatchedRoute<T> | null;
|
||||
/**
|
||||
* Perform an insert into the radix tree
|
||||
* @param path - the prefix to match
|
||||
* @param data - the associated data to path
|
||||
*
|
||||
*/
|
||||
insert(path: string, data: T): void;
|
||||
/**
|
||||
* Perform a remove on the tree
|
||||
* @param { string } data.path - the route to match
|
||||
*
|
||||
* @returns A boolean signifying if the remove was successful or not
|
||||
*/
|
||||
remove(path: string): boolean;
|
||||
}
|
||||
interface MatcherExport {
|
||||
dynamic: Map<string, MatcherExport>;
|
||||
wildcard: Map<string, {
|
||||
pattern: string;
|
||||
}>;
|
||||
static: Map<string, {
|
||||
pattern: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
declare function createRouter<T extends RadixNodeData = RadixNodeData>(options?: RadixRouterOptions): RadixRouter<T>;
|
||||
|
||||
interface RouteTable {
|
||||
static: Map<string, RadixNodeData | null>;
|
||||
wildcard: Map<string, RadixNodeData | null>;
|
||||
dynamic: Map<string, RouteTable>;
|
||||
}
|
||||
interface RouteMatcher {
|
||||
ctx: {
|
||||
table: RouteTable;
|
||||
};
|
||||
matchAll: (path: string) => RadixNodeData[];
|
||||
}
|
||||
declare function toRouteMatcher(router: RadixRouter): RouteMatcher;
|
||||
declare function exportMatcher(matcher: RouteMatcher): MatcherExport;
|
||||
declare function createMatcherFromExport(matcherExport: MatcherExport): RouteMatcher;
|
||||
|
||||
export { type MatchedRoute, type MatcherExport, type NODE_TYPE, NODE_TYPES, type RadixNode, type RadixNodeData, type RadixRouter, type RadixRouterContext, type RadixRouterOptions, type RouteMatcher, type RouteTable, createMatcherFromExport, createRouter, exportMatcher, toRouteMatcher };
|
86
node_modules/radix3/dist/index.d.mts
generated
vendored
Normal file
86
node_modules/radix3/dist/index.d.mts
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
declare const NODE_TYPES: {
|
||||
NORMAL: 0;
|
||||
WILDCARD: 1;
|
||||
PLACEHOLDER: 2;
|
||||
};
|
||||
type _NODE_TYPES = typeof NODE_TYPES;
|
||||
type NODE_TYPE = _NODE_TYPES[keyof _NODE_TYPES];
|
||||
type _RadixNodeDataObject = {
|
||||
params?: never;
|
||||
[key: string]: any;
|
||||
};
|
||||
type RadixNodeData<T extends _RadixNodeDataObject = _RadixNodeDataObject> = T;
|
||||
type MatchedRoute<T extends RadixNodeData = RadixNodeData> = Omit<T, "params"> & {
|
||||
params?: Record<string, any>;
|
||||
};
|
||||
interface RadixNode<T extends RadixNodeData = RadixNodeData> {
|
||||
type: NODE_TYPE;
|
||||
maxDepth: number;
|
||||
parent: RadixNode<T> | null;
|
||||
children: Map<string, RadixNode<T>>;
|
||||
data: RadixNodeData | null;
|
||||
paramName: string | null;
|
||||
wildcardChildNode: RadixNode<T> | null;
|
||||
placeholderChildren: RadixNode<T>[];
|
||||
}
|
||||
interface RadixRouterOptions {
|
||||
strictTrailingSlash?: boolean;
|
||||
routes?: Record<string, any>;
|
||||
}
|
||||
interface RadixRouterContext<T extends RadixNodeData = RadixNodeData> {
|
||||
options: RadixRouterOptions;
|
||||
rootNode: RadixNode<T>;
|
||||
staticRoutesMap: Record<string, RadixNode>;
|
||||
}
|
||||
interface RadixRouter<T extends RadixNodeData = RadixNodeData> {
|
||||
ctx: RadixRouterContext<T>;
|
||||
/**
|
||||
* Perform lookup of given path in radix tree
|
||||
* @param path - the path to search for
|
||||
*
|
||||
* @returns The data that was originally inserted into the tree
|
||||
*/
|
||||
lookup(path: string): MatchedRoute<T> | null;
|
||||
/**
|
||||
* Perform an insert into the radix tree
|
||||
* @param path - the prefix to match
|
||||
* @param data - the associated data to path
|
||||
*
|
||||
*/
|
||||
insert(path: string, data: T): void;
|
||||
/**
|
||||
* Perform a remove on the tree
|
||||
* @param { string } data.path - the route to match
|
||||
*
|
||||
* @returns A boolean signifying if the remove was successful or not
|
||||
*/
|
||||
remove(path: string): boolean;
|
||||
}
|
||||
interface MatcherExport {
|
||||
dynamic: Map<string, MatcherExport>;
|
||||
wildcard: Map<string, {
|
||||
pattern: string;
|
||||
}>;
|
||||
static: Map<string, {
|
||||
pattern: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
declare function createRouter<T extends RadixNodeData = RadixNodeData>(options?: RadixRouterOptions): RadixRouter<T>;
|
||||
|
||||
interface RouteTable {
|
||||
static: Map<string, RadixNodeData | null>;
|
||||
wildcard: Map<string, RadixNodeData | null>;
|
||||
dynamic: Map<string, RouteTable>;
|
||||
}
|
||||
interface RouteMatcher {
|
||||
ctx: {
|
||||
table: RouteTable;
|
||||
};
|
||||
matchAll: (path: string) => RadixNodeData[];
|
||||
}
|
||||
declare function toRouteMatcher(router: RadixRouter): RouteMatcher;
|
||||
declare function exportMatcher(matcher: RouteMatcher): MatcherExport;
|
||||
declare function createMatcherFromExport(matcherExport: MatcherExport): RouteMatcher;
|
||||
|
||||
export { type MatchedRoute, type MatcherExport, type NODE_TYPE, NODE_TYPES, type RadixNode, type RadixNodeData, type RadixRouter, type RadixRouterContext, type RadixRouterOptions, type RouteMatcher, type RouteTable, createMatcherFromExport, createRouter, exportMatcher, toRouteMatcher };
|
86
node_modules/radix3/dist/index.d.ts
generated
vendored
Normal file
86
node_modules/radix3/dist/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
declare const NODE_TYPES: {
|
||||
NORMAL: 0;
|
||||
WILDCARD: 1;
|
||||
PLACEHOLDER: 2;
|
||||
};
|
||||
type _NODE_TYPES = typeof NODE_TYPES;
|
||||
type NODE_TYPE = _NODE_TYPES[keyof _NODE_TYPES];
|
||||
type _RadixNodeDataObject = {
|
||||
params?: never;
|
||||
[key: string]: any;
|
||||
};
|
||||
type RadixNodeData<T extends _RadixNodeDataObject = _RadixNodeDataObject> = T;
|
||||
type MatchedRoute<T extends RadixNodeData = RadixNodeData> = Omit<T, "params"> & {
|
||||
params?: Record<string, any>;
|
||||
};
|
||||
interface RadixNode<T extends RadixNodeData = RadixNodeData> {
|
||||
type: NODE_TYPE;
|
||||
maxDepth: number;
|
||||
parent: RadixNode<T> | null;
|
||||
children: Map<string, RadixNode<T>>;
|
||||
data: RadixNodeData | null;
|
||||
paramName: string | null;
|
||||
wildcardChildNode: RadixNode<T> | null;
|
||||
placeholderChildren: RadixNode<T>[];
|
||||
}
|
||||
interface RadixRouterOptions {
|
||||
strictTrailingSlash?: boolean;
|
||||
routes?: Record<string, any>;
|
||||
}
|
||||
interface RadixRouterContext<T extends RadixNodeData = RadixNodeData> {
|
||||
options: RadixRouterOptions;
|
||||
rootNode: RadixNode<T>;
|
||||
staticRoutesMap: Record<string, RadixNode>;
|
||||
}
|
||||
interface RadixRouter<T extends RadixNodeData = RadixNodeData> {
|
||||
ctx: RadixRouterContext<T>;
|
||||
/**
|
||||
* Perform lookup of given path in radix tree
|
||||
* @param path - the path to search for
|
||||
*
|
||||
* @returns The data that was originally inserted into the tree
|
||||
*/
|
||||
lookup(path: string): MatchedRoute<T> | null;
|
||||
/**
|
||||
* Perform an insert into the radix tree
|
||||
* @param path - the prefix to match
|
||||
* @param data - the associated data to path
|
||||
*
|
||||
*/
|
||||
insert(path: string, data: T): void;
|
||||
/**
|
||||
* Perform a remove on the tree
|
||||
* @param { string } data.path - the route to match
|
||||
*
|
||||
* @returns A boolean signifying if the remove was successful or not
|
||||
*/
|
||||
remove(path: string): boolean;
|
||||
}
|
||||
interface MatcherExport {
|
||||
dynamic: Map<string, MatcherExport>;
|
||||
wildcard: Map<string, {
|
||||
pattern: string;
|
||||
}>;
|
||||
static: Map<string, {
|
||||
pattern: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
declare function createRouter<T extends RadixNodeData = RadixNodeData>(options?: RadixRouterOptions): RadixRouter<T>;
|
||||
|
||||
interface RouteTable {
|
||||
static: Map<string, RadixNodeData | null>;
|
||||
wildcard: Map<string, RadixNodeData | null>;
|
||||
dynamic: Map<string, RouteTable>;
|
||||
}
|
||||
interface RouteMatcher {
|
||||
ctx: {
|
||||
table: RouteTable;
|
||||
};
|
||||
matchAll: (path: string) => RadixNodeData[];
|
||||
}
|
||||
declare function toRouteMatcher(router: RadixRouter): RouteMatcher;
|
||||
declare function exportMatcher(matcher: RouteMatcher): MatcherExport;
|
||||
declare function createMatcherFromExport(matcherExport: MatcherExport): RouteMatcher;
|
||||
|
||||
export { type MatchedRoute, type MatcherExport, type NODE_TYPE, NODE_TYPES, type RadixNode, type RadixNodeData, type RadixRouter, type RadixRouterContext, type RadixRouterOptions, type RouteMatcher, type RouteTable, createMatcherFromExport, createRouter, exportMatcher, toRouteMatcher };
|
262
node_modules/radix3/dist/index.mjs
generated
vendored
Normal file
262
node_modules/radix3/dist/index.mjs
generated
vendored
Normal file
@@ -0,0 +1,262 @@
|
||||
const NODE_TYPES = {
|
||||
NORMAL: 0,
|
||||
WILDCARD: 1,
|
||||
PLACEHOLDER: 2
|
||||
};
|
||||
|
||||
function createRouter(options = {}) {
|
||||
const ctx = {
|
||||
options,
|
||||
rootNode: createRadixNode(),
|
||||
staticRoutesMap: {}
|
||||
};
|
||||
const normalizeTrailingSlash = (p) => options.strictTrailingSlash ? p : p.replace(/\/$/, "") || "/";
|
||||
if (options.routes) {
|
||||
for (const path in options.routes) {
|
||||
insert(ctx, normalizeTrailingSlash(path), options.routes[path]);
|
||||
}
|
||||
}
|
||||
return {
|
||||
ctx,
|
||||
lookup: (path) => lookup(ctx, normalizeTrailingSlash(path)),
|
||||
insert: (path, data) => insert(ctx, normalizeTrailingSlash(path), data),
|
||||
remove: (path) => remove(ctx, normalizeTrailingSlash(path))
|
||||
};
|
||||
}
|
||||
function lookup(ctx, path) {
|
||||
const staticPathNode = ctx.staticRoutesMap[path];
|
||||
if (staticPathNode) {
|
||||
return staticPathNode.data;
|
||||
}
|
||||
const sections = path.split("/");
|
||||
const params = {};
|
||||
let paramsFound = false;
|
||||
let wildcardNode = null;
|
||||
let node = ctx.rootNode;
|
||||
let wildCardParam = null;
|
||||
for (let i = 0; i < sections.length; i++) {
|
||||
const section = sections[i];
|
||||
if (node.wildcardChildNode !== null) {
|
||||
wildcardNode = node.wildcardChildNode;
|
||||
wildCardParam = sections.slice(i).join("/");
|
||||
}
|
||||
const nextNode = node.children.get(section);
|
||||
if (nextNode === void 0) {
|
||||
if (node && node.placeholderChildren.length > 1) {
|
||||
const remaining = sections.length - i;
|
||||
node = node.placeholderChildren.find((c) => c.maxDepth === remaining) || null;
|
||||
} else {
|
||||
node = node.placeholderChildren[0] || null;
|
||||
}
|
||||
if (!node) {
|
||||
break;
|
||||
}
|
||||
if (node.paramName) {
|
||||
params[node.paramName] = section;
|
||||
}
|
||||
paramsFound = true;
|
||||
} else {
|
||||
node = nextNode;
|
||||
}
|
||||
}
|
||||
if ((node === null || node.data === null) && wildcardNode !== null) {
|
||||
node = wildcardNode;
|
||||
params[node.paramName || "_"] = wildCardParam;
|
||||
paramsFound = true;
|
||||
}
|
||||
if (!node) {
|
||||
return null;
|
||||
}
|
||||
if (paramsFound) {
|
||||
return {
|
||||
...node.data,
|
||||
params: paramsFound ? params : void 0
|
||||
};
|
||||
}
|
||||
return node.data;
|
||||
}
|
||||
function insert(ctx, path, data) {
|
||||
let isStaticRoute = true;
|
||||
const sections = path.split("/");
|
||||
let node = ctx.rootNode;
|
||||
let _unnamedPlaceholderCtr = 0;
|
||||
const matchedNodes = [node];
|
||||
for (const section of sections) {
|
||||
let childNode;
|
||||
if (childNode = node.children.get(section)) {
|
||||
node = childNode;
|
||||
} else {
|
||||
const type = getNodeType(section);
|
||||
childNode = createRadixNode({ type, parent: node });
|
||||
node.children.set(section, childNode);
|
||||
if (type === NODE_TYPES.PLACEHOLDER) {
|
||||
childNode.paramName = section === "*" ? `_${_unnamedPlaceholderCtr++}` : section.slice(1);
|
||||
node.placeholderChildren.push(childNode);
|
||||
isStaticRoute = false;
|
||||
} else if (type === NODE_TYPES.WILDCARD) {
|
||||
node.wildcardChildNode = childNode;
|
||||
childNode.paramName = section.slice(
|
||||
3
|
||||
/* "**:" */
|
||||
) || "_";
|
||||
isStaticRoute = false;
|
||||
}
|
||||
matchedNodes.push(childNode);
|
||||
node = childNode;
|
||||
}
|
||||
}
|
||||
for (const [depth, node2] of matchedNodes.entries()) {
|
||||
node2.maxDepth = Math.max(matchedNodes.length - depth, node2.maxDepth || 0);
|
||||
}
|
||||
node.data = data;
|
||||
if (isStaticRoute === true) {
|
||||
ctx.staticRoutesMap[path] = node;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
function remove(ctx, path) {
|
||||
let success = false;
|
||||
const sections = path.split("/");
|
||||
let node = ctx.rootNode;
|
||||
for (const section of sections) {
|
||||
node = node.children.get(section);
|
||||
if (!node) {
|
||||
return success;
|
||||
}
|
||||
}
|
||||
if (node.data) {
|
||||
const lastSection = sections.at(-1) || "";
|
||||
node.data = null;
|
||||
if (Object.keys(node.children).length === 0 && node.parent) {
|
||||
node.parent.children.delete(lastSection);
|
||||
node.parent.wildcardChildNode = null;
|
||||
node.parent.placeholderChildren = [];
|
||||
}
|
||||
success = true;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
function createRadixNode(options = {}) {
|
||||
return {
|
||||
type: options.type || NODE_TYPES.NORMAL,
|
||||
maxDepth: 0,
|
||||
parent: options.parent || null,
|
||||
children: /* @__PURE__ */ new Map(),
|
||||
data: options.data || null,
|
||||
paramName: options.paramName || null,
|
||||
wildcardChildNode: null,
|
||||
placeholderChildren: []
|
||||
};
|
||||
}
|
||||
function getNodeType(str) {
|
||||
if (str.startsWith("**")) {
|
||||
return NODE_TYPES.WILDCARD;
|
||||
}
|
||||
if (str[0] === ":" || str === "*") {
|
||||
return NODE_TYPES.PLACEHOLDER;
|
||||
}
|
||||
return NODE_TYPES.NORMAL;
|
||||
}
|
||||
|
||||
function toRouteMatcher(router) {
|
||||
const table = _routerNodeToTable("", router.ctx.rootNode);
|
||||
return _createMatcher(table, router.ctx.options.strictTrailingSlash);
|
||||
}
|
||||
function _createMatcher(table, strictTrailingSlash) {
|
||||
return {
|
||||
ctx: { table },
|
||||
matchAll: (path) => _matchRoutes(path, table, strictTrailingSlash)
|
||||
};
|
||||
}
|
||||
function _createRouteTable() {
|
||||
return {
|
||||
static: /* @__PURE__ */ new Map(),
|
||||
wildcard: /* @__PURE__ */ new Map(),
|
||||
dynamic: /* @__PURE__ */ new Map()
|
||||
};
|
||||
}
|
||||
function _exportMatcherFromTable(table) {
|
||||
const obj = /* @__PURE__ */ Object.create(null);
|
||||
for (const property in table) {
|
||||
obj[property] = property === "dynamic" ? Object.fromEntries(
|
||||
[...table[property].entries()].map(([key, value]) => [
|
||||
key,
|
||||
_exportMatcherFromTable(value)
|
||||
])
|
||||
) : Object.fromEntries(table[property].entries());
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
function exportMatcher(matcher) {
|
||||
return _exportMatcherFromTable(matcher.ctx.table);
|
||||
}
|
||||
function _createTableFromExport(matcherExport) {
|
||||
const table = {};
|
||||
for (const property in matcherExport) {
|
||||
table[property] = property === "dynamic" ? new Map(
|
||||
Object.entries(matcherExport[property]).map(([key, value]) => [
|
||||
key,
|
||||
_createTableFromExport(value)
|
||||
])
|
||||
) : new Map(
|
||||
Object.entries(matcherExport[property])
|
||||
);
|
||||
}
|
||||
return table;
|
||||
}
|
||||
function createMatcherFromExport(matcherExport) {
|
||||
return _createMatcher(_createTableFromExport(matcherExport));
|
||||
}
|
||||
function _matchRoutes(path, table, strictTrailingSlash) {
|
||||
if (strictTrailingSlash !== true && path.endsWith("/")) {
|
||||
path = path.slice(0, -1) || "/";
|
||||
}
|
||||
const matches = [];
|
||||
for (const [key, value] of _sortRoutesMap(table.wildcard)) {
|
||||
if (path === key || path.startsWith(key + "/")) {
|
||||
matches.push(value);
|
||||
}
|
||||
}
|
||||
for (const [key, value] of _sortRoutesMap(table.dynamic)) {
|
||||
if (path.startsWith(key + "/")) {
|
||||
const subPath = "/" + path.slice(key.length).split("/").splice(2).join("/");
|
||||
matches.push(..._matchRoutes(subPath, value));
|
||||
}
|
||||
}
|
||||
const staticMatch = table.static.get(path);
|
||||
if (staticMatch) {
|
||||
matches.push(staticMatch);
|
||||
}
|
||||
return matches.filter(Boolean);
|
||||
}
|
||||
function _sortRoutesMap(m) {
|
||||
return [...m.entries()].sort((a, b) => a[0].length - b[0].length);
|
||||
}
|
||||
function _routerNodeToTable(initialPath, initialNode) {
|
||||
const table = _createRouteTable();
|
||||
function _addNode(path, node) {
|
||||
if (path) {
|
||||
if (node.type === NODE_TYPES.NORMAL && !(path.includes("*") || path.includes(":"))) {
|
||||
if (node.data) {
|
||||
table.static.set(path, node.data);
|
||||
}
|
||||
} else if (node.type === NODE_TYPES.WILDCARD) {
|
||||
table.wildcard.set(path.replace("/**", ""), node.data);
|
||||
} else if (node.type === NODE_TYPES.PLACEHOLDER) {
|
||||
const subTable = _routerNodeToTable("", node);
|
||||
if (node.data) {
|
||||
subTable.static.set("/", node.data);
|
||||
}
|
||||
table.dynamic.set(path.replace(/\/\*|\/:\w+/, ""), subTable);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (const [childPath, child] of node.children.entries()) {
|
||||
_addNode(`${path}/${childPath}`.replace("//", "/"), child);
|
||||
}
|
||||
}
|
||||
_addNode(initialPath, initialNode);
|
||||
return table;
|
||||
}
|
||||
|
||||
export { NODE_TYPES, createMatcherFromExport, createRouter, exportMatcher, toRouteMatcher };
|
Reference in New Issue
Block a user