@tanstack/router-core 1.168.18 → 1.169.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.cjs +1 -0
- package/dist/cjs/index.d.cts +1 -1
- package/dist/cjs/new-process-route-tree.cjs +34 -46
- package/dist/cjs/new-process-route-tree.cjs.map +1 -1
- package/dist/cjs/new-process-route-tree.d.cts +4 -26
- package/dist/cjs/path.cjs +1 -22
- package/dist/cjs/path.cjs.map +1 -1
- package/dist/cjs/route.cjs.map +1 -1
- package/dist/cjs/route.d.cts +1 -32
- package/dist/cjs/router.cjs +34 -19
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +3 -4
- package/dist/cjs/utils.cjs +5 -0
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +1 -0
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +2 -2
- package/dist/esm/new-process-route-tree.d.ts +4 -26
- package/dist/esm/new-process-route-tree.js +34 -47
- package/dist/esm/new-process-route-tree.js.map +1 -1
- package/dist/esm/path.js +1 -22
- package/dist/esm/path.js.map +1 -1
- package/dist/esm/route.d.ts +1 -32
- package/dist/esm/route.js.map +1 -1
- package/dist/esm/router.d.ts +3 -4
- package/dist/esm/router.js +36 -21
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/utils.d.ts +1 -0
- package/dist/esm/utils.js +5 -1
- package/dist/esm/utils.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +1 -0
- package/src/new-process-route-tree.ts +42 -77
- package/src/path.ts +1 -27
- package/src/route.ts +5 -34
- package/src/router.ts +76 -54
- package/src/utils.ts +7 -0
package/dist/cjs/index.cjs
CHANGED
|
@@ -62,6 +62,7 @@ exports.getLocationChangeInfo = require_router.getLocationChangeInfo;
|
|
|
62
62
|
exports.getMatchedRoutes = require_router.getMatchedRoutes;
|
|
63
63
|
exports.getStylesheetHref = require_manifest.getStylesheetHref;
|
|
64
64
|
exports.handleHashScroll = require_hash_scroll.handleHashScroll;
|
|
65
|
+
exports.hasKeys = require_utils.hasKeys;
|
|
65
66
|
exports.interpolatePath = require_path.interpolatePath;
|
|
66
67
|
exports.invariant = require_invariant.invariant;
|
|
67
68
|
exports.isDangerousProtocol = require_utils.isDangerousProtocol;
|
package/dist/cjs/index.d.cts
CHANGED
|
@@ -27,7 +27,7 @@ export { retainSearchParams, stripSearchParams } from './searchMiddleware.cjs';
|
|
|
27
27
|
export { defaultParseSearch, defaultStringifySearch, parseSearchWith, stringifySearchWith, } from './searchParams.cjs';
|
|
28
28
|
export type { SearchSerializer, SearchParser } from './searchParams.cjs';
|
|
29
29
|
export type { OptionalStructuralSharing } from './structuralSharing.cjs';
|
|
30
|
-
export { functionalUpdate, replaceEqualDeep, isPlainObject, isPlainArray, deepEqual, createControlledPromise, isModuleNotFoundError, DEFAULT_PROTOCOL_ALLOWLIST, escapeHtml, isDangerousProtocol, buildDevStylesUrl, } from './utils.cjs';
|
|
30
|
+
export { functionalUpdate, hasKeys, replaceEqualDeep, isPlainObject, isPlainArray, deepEqual, createControlledPromise, isModuleNotFoundError, DEFAULT_PROTOCOL_ALLOWLIST, escapeHtml, isDangerousProtocol, buildDevStylesUrl, } from './utils.cjs';
|
|
31
31
|
export type { NoInfer, IsAny, PickAsRequired, PickRequired, PickOptional, WithoutEmpty, Expand, DeepPartial, MakeDifferenceOptional, IsUnion, IsNonEmptyObject, Assign, IntersectAssign, Timeout, Updater, NonNullableUpdater, StringLiteral, ThrowOrOptional, ThrowConstraint, ControlledPromise, ExtractObjects, PartialMergeAllObject, MergeAllPrimitive, ExtractPrimitives, PartialMergeAll, Constrain, ConstrainLiteral, UnionToIntersection, MergeAllObjects, MergeAll, ValidateJSON, StrictOrFrom, LooseReturnType, LooseAsyncReturnType, Awaitable, } from './utils.cjs';
|
|
32
32
|
export type { StandardSchemaValidatorProps, StandardSchemaValidator, AnyStandardSchemaValidator, StandardSchemaValidatorTypes, AnyStandardSchemaValidateSuccess, AnyStandardSchemaValidateFailure, AnyStandardSchemaValidateIssue, AnyStandardSchemaValidateInput, AnyStandardSchemaValidate, ValidatorObj, AnyValidatorObj, ValidatorAdapter, AnyValidatorAdapter, AnyValidatorFn, ValidatorFn, Validator, AnyValidator, AnySchema, DefaultValidator, ResolveSearchValidatorInputFn, ResolveSearchValidatorInput, ResolveValidatorInputFn, ResolveValidatorInput, ResolveValidatorOutputFn, ResolveValidatorOutput, } from './validators.cjs';
|
|
33
33
|
export type { UseRouteContextBaseOptions, UseRouteContextOptions, UseRouteContextResult, } from './useRouteContext.cjs';
|
|
@@ -122,7 +122,7 @@ function parseSegments(defaultCaseSensitive, data, route, start, node, depth, on
|
|
|
122
122
|
const path = route.fullPath ?? route.from;
|
|
123
123
|
const length = path.length;
|
|
124
124
|
const caseSensitive = route.options?.caseSensitive ?? defaultCaseSensitive;
|
|
125
|
-
const
|
|
125
|
+
const parseParams = route.options?.params?.parse ?? route.options?.parseParams;
|
|
126
126
|
while (cursor < length) {
|
|
127
127
|
const segment = parseSegment(path, cursor, data);
|
|
128
128
|
let nextNode;
|
|
@@ -165,7 +165,7 @@ function parseSegments(defaultCaseSensitive, data, route, start, node, depth, on
|
|
|
165
165
|
const actuallyCaseSensitive = caseSensitive && !!(prefix_raw || suffix_raw);
|
|
166
166
|
const prefix = !prefix_raw ? void 0 : actuallyCaseSensitive ? prefix_raw : prefix_raw.toLowerCase();
|
|
167
167
|
const suffix = !suffix_raw ? void 0 : actuallyCaseSensitive ? suffix_raw : suffix_raw.toLowerCase();
|
|
168
|
-
const existingNode = !
|
|
168
|
+
const existingNode = !parseParams && node.dynamic?.find((s) => !s.parse && s.caseSensitive === actuallyCaseSensitive && s.prefix === prefix && s.suffix === suffix);
|
|
169
169
|
if (existingNode) nextNode = existingNode;
|
|
170
170
|
else {
|
|
171
171
|
const next = createDynamicNode(1, route.fullPath ?? route.from, actuallyCaseSensitive, prefix, suffix);
|
|
@@ -183,7 +183,7 @@ function parseSegments(defaultCaseSensitive, data, route, start, node, depth, on
|
|
|
183
183
|
const actuallyCaseSensitive = caseSensitive && !!(prefix_raw || suffix_raw);
|
|
184
184
|
const prefix = !prefix_raw ? void 0 : actuallyCaseSensitive ? prefix_raw : prefix_raw.toLowerCase();
|
|
185
185
|
const suffix = !suffix_raw ? void 0 : actuallyCaseSensitive ? suffix_raw : suffix_raw.toLowerCase();
|
|
186
|
-
const existingNode = !
|
|
186
|
+
const existingNode = !parseParams && node.optional?.find((s) => !s.parse && s.caseSensitive === actuallyCaseSensitive && s.prefix === prefix && s.suffix === suffix);
|
|
187
187
|
if (existingNode) nextNode = existingNode;
|
|
188
188
|
else {
|
|
189
189
|
const next = createDynamicNode(3, route.fullPath ?? route.from, actuallyCaseSensitive, prefix, suffix);
|
|
@@ -211,7 +211,7 @@ function parseSegments(defaultCaseSensitive, data, route, start, node, depth, on
|
|
|
211
211
|
}
|
|
212
212
|
node = nextNode;
|
|
213
213
|
}
|
|
214
|
-
if (
|
|
214
|
+
if (parseParams && route.children && !route.isRoot && route.id && route.id.charCodeAt(route.id.lastIndexOf("/") + 1) === 95) {
|
|
215
215
|
const pathlessNode = createStaticNode(route.fullPath ?? route.from);
|
|
216
216
|
pathlessNode.kind = SEGMENT_TYPE_PATHLESS;
|
|
217
217
|
pathlessNode.parent = node;
|
|
@@ -231,9 +231,7 @@ function parseSegments(defaultCaseSensitive, data, route, start, node, depth, on
|
|
|
231
231
|
node.index = indexNode;
|
|
232
232
|
node = indexNode;
|
|
233
233
|
}
|
|
234
|
-
node.parse =
|
|
235
|
-
node.skipOnParamError = skipOnParamError;
|
|
236
|
-
node.parsingPriority = route.options?.skipRouteOnParseError?.priority ?? 0;
|
|
234
|
+
node.parse = parseParams ?? null;
|
|
237
235
|
if (isLeaf && !node.route) {
|
|
238
236
|
node.route = route;
|
|
239
237
|
node.fullPath = route.fullPath ?? route.from;
|
|
@@ -242,9 +240,8 @@ function parseSegments(defaultCaseSensitive, data, route, start, node, depth, on
|
|
|
242
240
|
if (route.children) for (const child of route.children) parseSegments(defaultCaseSensitive, data, child, cursor, node, depth, onRoute);
|
|
243
241
|
}
|
|
244
242
|
function sortDynamic(a, b) {
|
|
245
|
-
if (a.
|
|
246
|
-
if (!a.
|
|
247
|
-
if (a.skipOnParamError && b.skipOnParamError && (a.parsingPriority || b.parsingPriority)) return b.parsingPriority - a.parsingPriority;
|
|
243
|
+
if (a.parse && !b.parse) return -1;
|
|
244
|
+
if (!a.parse && b.parse) return 1;
|
|
248
245
|
if (a.prefix && b.prefix && a.prefix !== b.prefix) {
|
|
249
246
|
if (a.prefix.startsWith(b.prefix)) return -1;
|
|
250
247
|
if (b.prefix.startsWith(a.prefix)) return 1;
|
|
@@ -292,9 +289,7 @@ function createStaticNode(fullPath) {
|
|
|
292
289
|
route: null,
|
|
293
290
|
fullPath,
|
|
294
291
|
parent: null,
|
|
295
|
-
parse: null
|
|
296
|
-
skipOnParamError: false,
|
|
297
|
-
parsingPriority: 0
|
|
292
|
+
parse: null
|
|
298
293
|
};
|
|
299
294
|
}
|
|
300
295
|
/**
|
|
@@ -316,8 +311,6 @@ function createDynamicNode(kind, fullPath, caseSensitive, prefix, suffix) {
|
|
|
316
311
|
fullPath,
|
|
317
312
|
parent: null,
|
|
318
313
|
parse: null,
|
|
319
|
-
skipOnParamError: false,
|
|
320
|
-
parsingPriority: 0,
|
|
321
314
|
caseSensitive,
|
|
322
315
|
prefix,
|
|
323
316
|
suffix
|
|
@@ -420,8 +413,7 @@ function findMatch(path, segmentTree, fuzzy = false) {
|
|
|
420
413
|
const [rawParams] = extractParams(path, parts, leaf);
|
|
421
414
|
return {
|
|
422
415
|
route: leaf.node.route,
|
|
423
|
-
rawParams
|
|
424
|
-
parsedParams: leaf.parsedParams
|
|
416
|
+
rawParams
|
|
425
417
|
};
|
|
426
418
|
}
|
|
427
419
|
/**
|
|
@@ -537,13 +529,12 @@ function getNodeMatch(path, parts, segmentTree, fuzzy) {
|
|
|
537
529
|
while (stack.length) {
|
|
538
530
|
const frame = stack.pop();
|
|
539
531
|
const { node, index, skipped, depth, statics, dynamics, optionals } = frame;
|
|
540
|
-
let { extract, rawParams
|
|
532
|
+
let { extract, rawParams } = frame;
|
|
541
533
|
if (node.kind === 2 && node.route && !isFrameMoreSpecific(bestMatch, frame)) continue;
|
|
542
|
-
if (node.
|
|
543
|
-
if (!
|
|
534
|
+
if (node.parse) {
|
|
535
|
+
if (!validateParseParams(path, parts, frame)) continue;
|
|
544
536
|
rawParams = frame.rawParams;
|
|
545
537
|
extract = frame.extract;
|
|
546
|
-
parsedParams = frame.parsedParams;
|
|
547
538
|
}
|
|
548
539
|
if (fuzzy && node.route && node.kind !== SEGMENT_TYPE_INDEX && isFrameMoreSpecific(bestFuzzy, frame)) bestFuzzy = frame;
|
|
549
540
|
const isBeyondPath = index === partsLength;
|
|
@@ -563,12 +554,11 @@ function getNodeMatch(path, parts, segmentTree, fuzzy) {
|
|
|
563
554
|
dynamics,
|
|
564
555
|
optionals,
|
|
565
556
|
extract,
|
|
566
|
-
rawParams
|
|
567
|
-
parsedParams
|
|
557
|
+
rawParams
|
|
568
558
|
};
|
|
569
559
|
let indexValid = true;
|
|
570
|
-
if (node.index.
|
|
571
|
-
if (!
|
|
560
|
+
if (node.index.parse) {
|
|
561
|
+
if (!validateParseParams(path, parts, indexFrame)) indexValid = false;
|
|
572
562
|
}
|
|
573
563
|
if (indexValid) {
|
|
574
564
|
if (!dynamics && !optionals && !skipped && isPerfectStaticMatch(statics, partsLength)) return indexFrame;
|
|
@@ -596,8 +586,7 @@ function getNodeMatch(path, parts, segmentTree, fuzzy) {
|
|
|
596
586
|
dynamics,
|
|
597
587
|
optionals,
|
|
598
588
|
extract,
|
|
599
|
-
rawParams
|
|
600
|
-
parsedParams
|
|
589
|
+
rawParams
|
|
601
590
|
});
|
|
602
591
|
}
|
|
603
592
|
if (node.optional) {
|
|
@@ -614,8 +603,7 @@ function getNodeMatch(path, parts, segmentTree, fuzzy) {
|
|
|
614
603
|
dynamics,
|
|
615
604
|
optionals,
|
|
616
605
|
extract,
|
|
617
|
-
rawParams
|
|
618
|
-
parsedParams
|
|
606
|
+
rawParams
|
|
619
607
|
});
|
|
620
608
|
}
|
|
621
609
|
if (!isBeyondPath) for (let i = node.optional.length - 1; i >= 0; i--) {
|
|
@@ -635,8 +623,7 @@ function getNodeMatch(path, parts, segmentTree, fuzzy) {
|
|
|
635
623
|
dynamics,
|
|
636
624
|
optionals: optionals + segmentScore(partsLength, index),
|
|
637
625
|
extract,
|
|
638
|
-
rawParams
|
|
639
|
-
parsedParams
|
|
626
|
+
rawParams
|
|
640
627
|
});
|
|
641
628
|
}
|
|
642
629
|
}
|
|
@@ -657,8 +644,7 @@ function getNodeMatch(path, parts, segmentTree, fuzzy) {
|
|
|
657
644
|
dynamics: dynamics + segmentScore(partsLength, index),
|
|
658
645
|
optionals,
|
|
659
646
|
extract,
|
|
660
|
-
rawParams
|
|
661
|
-
parsedParams
|
|
647
|
+
rawParams
|
|
662
648
|
});
|
|
663
649
|
}
|
|
664
650
|
if (!isBeyondPath && node.staticInsensitive) {
|
|
@@ -672,8 +658,7 @@ function getNodeMatch(path, parts, segmentTree, fuzzy) {
|
|
|
672
658
|
dynamics,
|
|
673
659
|
optionals,
|
|
674
660
|
extract,
|
|
675
|
-
rawParams
|
|
676
|
-
parsedParams
|
|
661
|
+
rawParams
|
|
677
662
|
});
|
|
678
663
|
}
|
|
679
664
|
if (!isBeyondPath && node.static) {
|
|
@@ -687,8 +672,7 @@ function getNodeMatch(path, parts, segmentTree, fuzzy) {
|
|
|
687
672
|
dynamics,
|
|
688
673
|
optionals,
|
|
689
674
|
extract,
|
|
690
|
-
rawParams
|
|
691
|
-
parsedParams
|
|
675
|
+
rawParams
|
|
692
676
|
});
|
|
693
677
|
}
|
|
694
678
|
if (node.pathless) {
|
|
@@ -704,8 +688,7 @@ function getNodeMatch(path, parts, segmentTree, fuzzy) {
|
|
|
704
688
|
dynamics,
|
|
705
689
|
optionals,
|
|
706
690
|
extract,
|
|
707
|
-
rawParams
|
|
708
|
-
parsedParams
|
|
691
|
+
rawParams
|
|
709
692
|
});
|
|
710
693
|
}
|
|
711
694
|
}
|
|
@@ -727,23 +710,28 @@ function segmentScore(partsLength, index) {
|
|
|
727
710
|
function isPerfectStaticMatch(statics, partsLength) {
|
|
728
711
|
return statics === 2 ** (partsLength - 1) - 1;
|
|
729
712
|
}
|
|
730
|
-
function
|
|
713
|
+
function validateParseParams(path, parts, frame) {
|
|
714
|
+
let rawParams;
|
|
715
|
+
let state;
|
|
731
716
|
try {
|
|
732
|
-
|
|
733
|
-
frame.rawParams = rawParams;
|
|
734
|
-
frame.extract = state;
|
|
735
|
-
const parsed = frame.node.parse(rawParams);
|
|
736
|
-
frame.parsedParams = Object.assign(Object.create(null), frame.parsedParams, parsed);
|
|
737
|
-
return true;
|
|
717
|
+
[rawParams, state] = extractParams(path, parts, frame);
|
|
738
718
|
} catch {
|
|
739
719
|
return null;
|
|
740
720
|
}
|
|
721
|
+
frame.rawParams = rawParams;
|
|
722
|
+
frame.extract = state;
|
|
723
|
+
if (!frame.node.parse) return true;
|
|
724
|
+
try {
|
|
725
|
+
if (frame.node.parse(rawParams) === false) return null;
|
|
726
|
+
} catch {}
|
|
727
|
+
return true;
|
|
741
728
|
}
|
|
742
729
|
function isFrameMoreSpecific(prev, next) {
|
|
743
730
|
if (!prev) return true;
|
|
744
731
|
return next.statics > prev.statics || next.statics === prev.statics && (next.dynamics > prev.dynamics || next.dynamics === prev.dynamics && (next.optionals > prev.optionals || next.optionals === prev.optionals && ((next.node.kind === SEGMENT_TYPE_INDEX) > (prev.node.kind === SEGMENT_TYPE_INDEX) || next.node.kind === SEGMENT_TYPE_INDEX === (prev.node.kind === SEGMENT_TYPE_INDEX) && next.depth > prev.depth)));
|
|
745
732
|
}
|
|
746
733
|
//#endregion
|
|
734
|
+
exports.buildRouteBranch = buildRouteBranch;
|
|
747
735
|
exports.findFlatMatch = findFlatMatch;
|
|
748
736
|
exports.findRouteMatch = findRouteMatch;
|
|
749
737
|
exports.findSingleMatch = findSingleMatch;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"new-process-route-tree.cjs","names":[],"sources":["../../src/new-process-route-tree.ts"],"sourcesContent":["import { invariant } from './invariant'\nimport { createLRUCache } from './lru-cache'\nimport { last } from './utils'\nimport type { LRUCache } from './lru-cache'\n\nexport const SEGMENT_TYPE_PATHNAME = 0\nexport const SEGMENT_TYPE_PARAM = 1\nexport const SEGMENT_TYPE_WILDCARD = 2\nexport const SEGMENT_TYPE_OPTIONAL_PARAM = 3\nconst SEGMENT_TYPE_INDEX = 4\nconst SEGMENT_TYPE_PATHLESS = 5 // only used in matching to represent pathless routes that need to carry more information\n\n/**\n * All the kinds of segments that can be present in a route path.\n */\nexport type SegmentKind =\n | typeof SEGMENT_TYPE_PATHNAME\n | typeof SEGMENT_TYPE_PARAM\n | typeof SEGMENT_TYPE_WILDCARD\n | typeof SEGMENT_TYPE_OPTIONAL_PARAM\n\n/**\n * All the kinds of segments that can be present in the segment tree.\n */\ntype ExtendedSegmentKind =\n | SegmentKind\n | typeof SEGMENT_TYPE_INDEX\n | typeof SEGMENT_TYPE_PATHLESS\n\nfunction getOpenAndCloseBraces(\n part: string,\n): [openBrace: number, closeBrace: number] | null {\n const openBrace = part.indexOf('{')\n if (openBrace === -1) return null\n const closeBrace = part.indexOf('}', openBrace)\n if (closeBrace === -1) return null\n const afterOpen = openBrace + 1\n if (afterOpen >= part.length) return null\n return [openBrace, closeBrace]\n}\n\ntype ParsedSegment = Uint16Array & {\n /** segment type (0 = pathname, 1 = param, 2 = wildcard, 3 = optional param) */\n 0: SegmentKind\n /** index of the end of the prefix */\n 1: number\n /** index of the start of the value */\n 2: number\n /** index of the end of the value */\n 3: number\n /** index of the start of the suffix */\n 4: number\n /** index of the end of the segment */\n 5: number\n}\n\n/**\n * Populates the `output` array with the parsed representation of the given `segment` string.\n *\n * Usage:\n * ```ts\n * let output\n * let cursor = 0\n * while (cursor < path.length) {\n * output = parseSegment(path, cursor, output)\n * const end = output[5]\n * cursor = end + 1\n * ```\n *\n * `output` is stored outside to avoid allocations during repeated calls. It doesn't need to be typed\n * or initialized, it will be done automatically.\n */\nexport function parseSegment(\n /** The full path string containing the segment. */\n path: string,\n /** The starting index of the segment within the path. */\n start: number,\n /** A Uint16Array (length: 6) to populate with the parsed segment data. */\n output: Uint16Array = new Uint16Array(6),\n): ParsedSegment {\n const next = path.indexOf('/', start)\n const end = next === -1 ? path.length : next\n const part = path.substring(start, end)\n\n if (!part || !part.includes('$')) {\n // early escape for static pathname\n output[0] = SEGMENT_TYPE_PATHNAME\n output[1] = start\n output[2] = start\n output[3] = end\n output[4] = end\n output[5] = end\n return output as ParsedSegment\n }\n\n // $ (wildcard)\n if (part === '$') {\n const total = path.length\n output[0] = SEGMENT_TYPE_WILDCARD\n output[1] = start\n output[2] = start\n output[3] = total\n output[4] = total\n output[5] = total\n return output as ParsedSegment\n }\n\n // $paramName\n if (part.charCodeAt(0) === 36) {\n output[0] = SEGMENT_TYPE_PARAM\n output[1] = start\n output[2] = start + 1 // skip '$'\n output[3] = end\n output[4] = end\n output[5] = end\n return output as ParsedSegment\n }\n\n const braces = getOpenAndCloseBraces(part)\n if (braces) {\n const [openBrace, closeBrace] = braces\n const firstChar = part.charCodeAt(openBrace + 1)\n\n // Check for {-$...} (optional param)\n // prefix{-$paramName}suffix\n // /^([^{]*)\\{-\\$([a-zA-Z_$][a-zA-Z0-9_$]*)\\}([^}]*)$/\n if (firstChar === 45) {\n // '-'\n if (\n openBrace + 2 < part.length &&\n part.charCodeAt(openBrace + 2) === 36 // '$'\n ) {\n const paramStart = openBrace + 3\n const paramEnd = closeBrace\n // Validate param name exists\n if (paramStart < paramEnd) {\n output[0] = SEGMENT_TYPE_OPTIONAL_PARAM\n output[1] = start + openBrace\n output[2] = start + paramStart\n output[3] = start + paramEnd\n output[4] = start + closeBrace + 1\n output[5] = end\n return output as ParsedSegment\n }\n }\n } else if (firstChar === 36) {\n // '$'\n const dollarPos = openBrace + 1\n const afterDollar = openBrace + 2\n // Check for {$} (wildcard)\n if (afterDollar === closeBrace) {\n // For wildcard, value should be '$' (from dollarPos to afterDollar)\n // prefix{$}suffix\n // /^([^{]*)\\{\\$\\}([^}]*)$/\n output[0] = SEGMENT_TYPE_WILDCARD\n output[1] = start + openBrace\n output[2] = start + dollarPos\n output[3] = start + afterDollar\n output[4] = start + closeBrace + 1\n output[5] = path.length\n return output as ParsedSegment\n }\n // Regular param {$paramName} - value is the param name (after $)\n // prefix{$paramName}suffix\n // /^([^{]*)\\{\\$([a-zA-Z_$][a-zA-Z0-9_$]*)\\}([^}]*)$/\n output[0] = SEGMENT_TYPE_PARAM\n output[1] = start + openBrace\n output[2] = start + afterDollar\n output[3] = start + closeBrace\n output[4] = start + closeBrace + 1\n output[5] = end\n return output as ParsedSegment\n }\n }\n\n // fallback to static pathname (should never happen)\n output[0] = SEGMENT_TYPE_PATHNAME\n output[1] = start\n output[2] = start\n output[3] = end\n output[4] = end\n output[5] = end\n return output as ParsedSegment\n}\n\n/**\n * Recursively parses the segments of the given route tree and populates a segment trie.\n *\n * @param data A reusable Uint16Array for parsing segments. (non important, we're just avoiding allocations)\n * @param route The current route to parse.\n * @param start The starting index for parsing within the route's full path.\n * @param node The current segment node in the trie to populate.\n * @param onRoute Callback invoked for each route processed.\n */\nfunction parseSegments<TRouteLike extends RouteLike>(\n defaultCaseSensitive: boolean,\n data: Uint16Array,\n route: TRouteLike,\n start: number,\n node: AnySegmentNode<TRouteLike>,\n depth: number,\n onRoute?: (route: TRouteLike) => void,\n) {\n onRoute?.(route)\n let cursor = start\n {\n const path = route.fullPath ?? route.from\n const length = path.length\n const caseSensitive = route.options?.caseSensitive ?? defaultCaseSensitive\n const skipOnParamError = !!(\n route.options?.params?.parse &&\n route.options?.skipRouteOnParseError?.params\n )\n while (cursor < length) {\n const segment = parseSegment(path, cursor, data)\n let nextNode: AnySegmentNode<TRouteLike>\n const start = cursor\n const end = segment[5]\n cursor = end + 1\n depth++\n const kind = segment[0]\n switch (kind) {\n case SEGMENT_TYPE_PATHNAME: {\n const value = path.substring(segment[2], segment[3])\n if (caseSensitive) {\n const existingNode = node.static?.get(value)\n if (existingNode) {\n nextNode = existingNode\n } else {\n node.static ??= new Map()\n const next = createStaticNode<TRouteLike>(\n route.fullPath ?? route.from,\n )\n next.parent = node\n next.depth = depth\n nextNode = next\n node.static.set(value, next)\n }\n } else {\n const name = value.toLowerCase()\n const existingNode = node.staticInsensitive?.get(name)\n if (existingNode) {\n nextNode = existingNode\n } else {\n node.staticInsensitive ??= new Map()\n const next = createStaticNode<TRouteLike>(\n route.fullPath ?? route.from,\n )\n next.parent = node\n next.depth = depth\n nextNode = next\n node.staticInsensitive.set(name, next)\n }\n }\n break\n }\n case SEGMENT_TYPE_PARAM: {\n const prefix_raw = path.substring(start, segment[1])\n const suffix_raw = path.substring(segment[4], end)\n const actuallyCaseSensitive =\n caseSensitive && !!(prefix_raw || suffix_raw)\n const prefix = !prefix_raw\n ? undefined\n : actuallyCaseSensitive\n ? prefix_raw\n : prefix_raw.toLowerCase()\n const suffix = !suffix_raw\n ? undefined\n : actuallyCaseSensitive\n ? suffix_raw\n : suffix_raw.toLowerCase()\n const existingNode =\n !skipOnParamError &&\n node.dynamic?.find(\n (s) =>\n !s.skipOnParamError &&\n s.caseSensitive === actuallyCaseSensitive &&\n s.prefix === prefix &&\n s.suffix === suffix,\n )\n if (existingNode) {\n nextNode = existingNode\n } else {\n const next = createDynamicNode<TRouteLike>(\n SEGMENT_TYPE_PARAM,\n route.fullPath ?? route.from,\n actuallyCaseSensitive,\n prefix,\n suffix,\n )\n nextNode = next\n next.depth = depth\n next.parent = node\n node.dynamic ??= []\n node.dynamic.push(next)\n }\n break\n }\n case SEGMENT_TYPE_OPTIONAL_PARAM: {\n const prefix_raw = path.substring(start, segment[1])\n const suffix_raw = path.substring(segment[4], end)\n const actuallyCaseSensitive =\n caseSensitive && !!(prefix_raw || suffix_raw)\n const prefix = !prefix_raw\n ? undefined\n : actuallyCaseSensitive\n ? prefix_raw\n : prefix_raw.toLowerCase()\n const suffix = !suffix_raw\n ? undefined\n : actuallyCaseSensitive\n ? suffix_raw\n : suffix_raw.toLowerCase()\n const existingNode =\n !skipOnParamError &&\n node.optional?.find(\n (s) =>\n !s.skipOnParamError &&\n s.caseSensitive === actuallyCaseSensitive &&\n s.prefix === prefix &&\n s.suffix === suffix,\n )\n if (existingNode) {\n nextNode = existingNode\n } else {\n const next = createDynamicNode<TRouteLike>(\n SEGMENT_TYPE_OPTIONAL_PARAM,\n route.fullPath ?? route.from,\n actuallyCaseSensitive,\n prefix,\n suffix,\n )\n nextNode = next\n next.parent = node\n next.depth = depth\n node.optional ??= []\n node.optional.push(next)\n }\n break\n }\n case SEGMENT_TYPE_WILDCARD: {\n const prefix_raw = path.substring(start, segment[1])\n const suffix_raw = path.substring(segment[4], end)\n const actuallyCaseSensitive =\n caseSensitive && !!(prefix_raw || suffix_raw)\n const prefix = !prefix_raw\n ? undefined\n : actuallyCaseSensitive\n ? prefix_raw\n : prefix_raw.toLowerCase()\n const suffix = !suffix_raw\n ? undefined\n : actuallyCaseSensitive\n ? suffix_raw\n : suffix_raw.toLowerCase()\n const next = createDynamicNode<TRouteLike>(\n SEGMENT_TYPE_WILDCARD,\n route.fullPath ?? route.from,\n actuallyCaseSensitive,\n prefix,\n suffix,\n )\n nextNode = next\n next.parent = node\n next.depth = depth\n node.wildcard ??= []\n node.wildcard.push(next)\n }\n }\n node = nextNode\n }\n\n // create pathless node\n if (\n skipOnParamError &&\n route.children &&\n !route.isRoot &&\n route.id &&\n route.id.charCodeAt(route.id.lastIndexOf('/') + 1) === 95 /* '_' */\n ) {\n const pathlessNode = createStaticNode<TRouteLike>(\n route.fullPath ?? route.from,\n )\n pathlessNode.kind = SEGMENT_TYPE_PATHLESS\n pathlessNode.parent = node\n depth++\n pathlessNode.depth = depth\n node.pathless ??= []\n node.pathless.push(pathlessNode)\n node = pathlessNode\n }\n\n const isLeaf = (route.path || !route.children) && !route.isRoot\n // create index node\n if (isLeaf && path.endsWith('/')) {\n const indexNode = createStaticNode<TRouteLike>(\n route.fullPath ?? route.from,\n )\n indexNode.kind = SEGMENT_TYPE_INDEX\n indexNode.parent = node\n depth++\n indexNode.depth = depth\n node.index = indexNode\n node = indexNode\n }\n\n node.parse = route.options?.params?.parse ?? null\n node.skipOnParamError = skipOnParamError\n node.parsingPriority = route.options?.skipRouteOnParseError?.priority ?? 0\n\n // make node \"matchable\"\n if (isLeaf && !node.route) {\n node.route = route\n node.fullPath = route.fullPath ?? route.from\n }\n }\n if (route.children)\n for (const child of route.children) {\n parseSegments(\n defaultCaseSensitive,\n data,\n child as TRouteLike,\n cursor,\n node,\n depth,\n onRoute,\n )\n }\n}\n\nfunction sortDynamic(\n a: {\n prefix?: string\n suffix?: string\n caseSensitive: boolean\n skipOnParamError: boolean\n parsingPriority: number\n },\n b: {\n prefix?: string\n suffix?: string\n caseSensitive: boolean\n skipOnParamError: boolean\n parsingPriority: number\n },\n) {\n if (a.skipOnParamError && !b.skipOnParamError) return -1\n if (!a.skipOnParamError && b.skipOnParamError) return 1\n if (\n a.skipOnParamError &&\n b.skipOnParamError &&\n (a.parsingPriority || b.parsingPriority)\n )\n return b.parsingPriority - a.parsingPriority\n if (a.prefix && b.prefix && a.prefix !== b.prefix) {\n if (a.prefix.startsWith(b.prefix)) return -1\n if (b.prefix.startsWith(a.prefix)) return 1\n }\n if (a.suffix && b.suffix && a.suffix !== b.suffix) {\n if (a.suffix.endsWith(b.suffix)) return -1\n if (b.suffix.endsWith(a.suffix)) return 1\n }\n if (a.prefix && !b.prefix) return -1\n if (!a.prefix && b.prefix) return 1\n if (a.suffix && !b.suffix) return -1\n if (!a.suffix && b.suffix) return 1\n if (a.caseSensitive && !b.caseSensitive) return -1\n if (!a.caseSensitive && b.caseSensitive) return 1\n\n // we don't need a tiebreaker here\n // at this point the 2 nodes cannot conflict during matching\n return 0\n}\n\nfunction sortTreeNodes(node: SegmentNode<RouteLike>) {\n if (node.pathless) {\n for (const child of node.pathless) {\n sortTreeNodes(child)\n }\n }\n if (node.static) {\n for (const child of node.static.values()) {\n sortTreeNodes(child)\n }\n }\n if (node.staticInsensitive) {\n for (const child of node.staticInsensitive.values()) {\n sortTreeNodes(child)\n }\n }\n if (node.dynamic?.length) {\n node.dynamic.sort(sortDynamic)\n for (const child of node.dynamic) {\n sortTreeNodes(child)\n }\n }\n if (node.optional?.length) {\n node.optional.sort(sortDynamic)\n for (const child of node.optional) {\n sortTreeNodes(child)\n }\n }\n if (node.wildcard?.length) {\n node.wildcard.sort(sortDynamic)\n for (const child of node.wildcard) {\n sortTreeNodes(child)\n }\n }\n}\n\nfunction createStaticNode<T extends RouteLike>(\n fullPath: string,\n): StaticSegmentNode<T> {\n return {\n kind: SEGMENT_TYPE_PATHNAME,\n depth: 0,\n pathless: null,\n index: null,\n static: null,\n staticInsensitive: null,\n dynamic: null,\n optional: null,\n wildcard: null,\n route: null,\n fullPath,\n parent: null,\n parse: null,\n skipOnParamError: false,\n parsingPriority: 0,\n }\n}\n\n/**\n * Keys must be declared in the same order as in `SegmentNode` type,\n * to ensure they are represented as the same object class in the engine.\n */\nfunction createDynamicNode<T extends RouteLike>(\n kind:\n | typeof SEGMENT_TYPE_PARAM\n | typeof SEGMENT_TYPE_WILDCARD\n | typeof SEGMENT_TYPE_OPTIONAL_PARAM,\n fullPath: string,\n caseSensitive: boolean,\n prefix?: string,\n suffix?: string,\n): DynamicSegmentNode<T> {\n return {\n kind,\n depth: 0,\n pathless: null,\n index: null,\n static: null,\n staticInsensitive: null,\n dynamic: null,\n optional: null,\n wildcard: null,\n route: null,\n fullPath,\n parent: null,\n parse: null,\n skipOnParamError: false,\n parsingPriority: 0,\n caseSensitive,\n prefix,\n suffix,\n }\n}\n\ntype StaticSegmentNode<T extends RouteLike> = SegmentNode<T> & {\n kind:\n | typeof SEGMENT_TYPE_PATHNAME\n | typeof SEGMENT_TYPE_PATHLESS\n | typeof SEGMENT_TYPE_INDEX\n}\n\ntype DynamicSegmentNode<T extends RouteLike> = SegmentNode<T> & {\n kind:\n | typeof SEGMENT_TYPE_PARAM\n | typeof SEGMENT_TYPE_WILDCARD\n | typeof SEGMENT_TYPE_OPTIONAL_PARAM\n prefix?: string\n suffix?: string\n caseSensitive: boolean\n}\n\ntype AnySegmentNode<T extends RouteLike> =\n | StaticSegmentNode<T>\n | DynamicSegmentNode<T>\n\ntype SegmentNode<T extends RouteLike> = {\n kind: ExtendedSegmentKind\n\n pathless: Array<StaticSegmentNode<T>> | null\n\n /** Exact index segment (highest priority) */\n index: StaticSegmentNode<T> | null\n\n /** Static segments (2nd priority) */\n static: Map<string, StaticSegmentNode<T>> | null\n\n /** Case insensitive static segments (3rd highest priority) */\n staticInsensitive: Map<string, StaticSegmentNode<T>> | null\n\n /** Dynamic segments ($param) */\n dynamic: Array<DynamicSegmentNode<T>> | null\n\n /** Optional dynamic segments ({-$param}) */\n optional: Array<DynamicSegmentNode<T>> | null\n\n /** Wildcard segments ($ - lowest priority) */\n wildcard: Array<DynamicSegmentNode<T>> | null\n\n /** Terminal route (if this path can end here) */\n route: T | null\n\n /** The full path for this segment node (will only be valid on leaf nodes) */\n fullPath: string\n\n parent: AnySegmentNode<T> | null\n\n depth: number\n\n /** route.options.params.parse function, set on the last node of the route */\n parse: null | ((params: Record<string, string>) => any)\n\n /** options.skipRouteOnParseError.params ?? false */\n skipOnParamError: boolean\n\n /** options.skipRouteOnParseError.priority ?? 0 */\n parsingPriority: number\n}\n\ntype RouteLike = {\n id?: string\n path?: string // relative path from the parent,\n children?: Array<RouteLike> // child routes,\n parentRoute?: RouteLike // parent route,\n isRoot?: boolean\n options?: {\n skipRouteOnParseError?: {\n params?: boolean\n priority?: number\n }\n caseSensitive?: boolean\n params?: {\n parse?: (params: Record<string, string>) => any\n }\n }\n} &\n // router tree\n (| { fullPath: string; from?: never } // full path from the root\n // flat route masks list\n | { fullPath?: never; from: string } // full path from the root\n )\n\nexport type ProcessedTree<\n TTree extends Extract<RouteLike, { fullPath: string }>,\n TFlat extends Extract<RouteLike, { from: string }>,\n TSingle extends Extract<RouteLike, { from: string }>,\n> = {\n /** a representation of the `routeTree` as a segment tree */\n segmentTree: AnySegmentNode<TTree>\n /** a mini route tree generated from the flat `routeMasks` list */\n masksTree: AnySegmentNode<TFlat> | null\n /** @deprecated keep until v2 so that `router.matchRoute` can keep not caring about the actual route tree */\n singleCache: LRUCache<string, AnySegmentNode<TSingle>>\n /** a cache of route matches from the `segmentTree` */\n matchCache: LRUCache<string, RouteMatch<TTree> | null>\n /** a cache of route matches from the `masksTree` */\n flatCache: LRUCache<string, ReturnType<typeof findMatch<TFlat>>> | null\n}\n\nexport function processRouteMasks<\n TRouteLike extends Extract<RouteLike, { from: string }>,\n>(\n routeList: Array<TRouteLike>,\n processedTree: ProcessedTree<any, TRouteLike, any>,\n) {\n const segmentTree = createStaticNode<TRouteLike>('/')\n const data = new Uint16Array(6)\n for (const route of routeList) {\n parseSegments(false, data, route, 1, segmentTree, 0)\n }\n sortTreeNodes(segmentTree)\n processedTree.masksTree = segmentTree\n processedTree.flatCache = createLRUCache<\n string,\n ReturnType<typeof findMatch<TRouteLike>>\n >(1000)\n}\n\n/**\n * Take an arbitrary list of routes, create a tree from them (if it hasn't been created already), and match a path against it.\n */\nexport function findFlatMatch<T extends Extract<RouteLike, { from: string }>>(\n /** The path to match. */\n path: string,\n /** The `processedTree` returned by the initial `processRouteTree` call. */\n processedTree: ProcessedTree<any, T, any>,\n) {\n path ||= '/'\n const cached = processedTree.flatCache!.get(path)\n if (cached) return cached\n const result = findMatch(path, processedTree.masksTree!)\n processedTree.flatCache!.set(path, result)\n return result\n}\n\n/**\n * @deprecated keep until v2 so that `router.matchRoute` can keep not caring about the actual route tree\n */\nexport function findSingleMatch(\n from: string,\n caseSensitive: boolean,\n fuzzy: boolean,\n path: string,\n processedTree: ProcessedTree<any, any, { from: string }>,\n) {\n from ||= '/'\n path ||= '/'\n const key = caseSensitive ? `case\\0${from}` : from\n let tree = processedTree.singleCache.get(key)\n if (!tree) {\n // single flat routes (router.matchRoute) are not eagerly processed,\n // if we haven't seen this route before, process it now\n tree = createStaticNode<{ from: string }>('/')\n const data = new Uint16Array(6)\n parseSegments(caseSensitive, data, { from }, 1, tree, 0)\n processedTree.singleCache.set(key, tree)\n }\n return findMatch(path, tree, fuzzy)\n}\n\ntype RouteMatch<T extends Extract<RouteLike, { fullPath: string }>> = {\n route: T\n rawParams: Record<string, string>\n parsedParams?: Record<string, unknown>\n branch: ReadonlyArray<T>\n}\n\nexport function findRouteMatch<\n T extends Extract<RouteLike, { fullPath: string }>,\n>(\n /** The path to match against the route tree. */\n path: string,\n /** The `processedTree` returned by the initial `processRouteTree` call. */\n processedTree: ProcessedTree<T, any, any>,\n /** If `true`, allows fuzzy matching (partial matches), i.e. which node in the tree would have been an exact match if the `path` had been shorter? */\n fuzzy = false,\n): RouteMatch<T> | null {\n const key = fuzzy ? path : `nofuzz\\0${path}` // the main use for `findRouteMatch` is fuzzy:true, so we optimize for that case\n const cached = processedTree.matchCache.get(key)\n if (cached !== undefined) return cached\n path ||= '/'\n let result: RouteMatch<T> | null\n\n try {\n result = findMatch(\n path,\n processedTree.segmentTree,\n fuzzy,\n ) as RouteMatch<T> | null\n } catch (err) {\n if (err instanceof URIError) {\n result = null\n } else {\n throw err\n }\n }\n\n if (result) result.branch = buildRouteBranch(result.route)\n processedTree.matchCache.set(key, result)\n return result\n}\n\n/** Trim trailing slashes (except preserving root '/'). */\nexport function trimPathRight(path: string) {\n return path === '/' ? path : path.replace(/\\/{1,}$/, '')\n}\n\nexport interface ProcessRouteTreeResult<\n TRouteLike extends Extract<RouteLike, { fullPath: string }> & { id: string },\n> {\n /** Should be considered a black box, needs to be provided to all matching functions in this module. */\n processedTree: ProcessedTree<TRouteLike, any, any>\n /** A lookup map of routes by their unique IDs. */\n routesById: Record<string, TRouteLike>\n /** A lookup map of routes by their trimmed full paths. */\n routesByPath: Record<string, TRouteLike>\n}\n\n/**\n * Processes a route tree into a segment trie for efficient path matching.\n * Also builds lookup maps for routes by ID and by trimmed full path.\n */\nexport function processRouteTree<\n TRouteLike extends Extract<RouteLike, { fullPath: string }> & { id: string },\n>(\n /** The root of the route tree to process. */\n routeTree: TRouteLike,\n /** Whether matching should be case sensitive by default (overridden by individual route options). */\n caseSensitive: boolean = false,\n /** Optional callback invoked for each route during processing. */\n initRoute?: (route: TRouteLike, index: number) => void,\n): ProcessRouteTreeResult<TRouteLike> {\n const segmentTree = createStaticNode<TRouteLike>(routeTree.fullPath)\n const data = new Uint16Array(6)\n const routesById = {} as Record<string, TRouteLike>\n const routesByPath = {} as Record<string, TRouteLike>\n let index = 0\n parseSegments(caseSensitive, data, routeTree, 1, segmentTree, 0, (route) => {\n initRoute?.(route, index)\n\n if (route.id in routesById) {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n `Invariant failed: Duplicate routes found with id: ${String(route.id)}`,\n )\n }\n\n invariant()\n }\n\n routesById[route.id] = route\n\n if (index !== 0 && route.path) {\n const trimmedFullPath = trimPathRight(route.fullPath)\n if (!routesByPath[trimmedFullPath] || route.fullPath.endsWith('/')) {\n routesByPath[trimmedFullPath] = route\n }\n }\n\n index++\n })\n sortTreeNodes(segmentTree)\n const processedTree: ProcessedTree<TRouteLike, any, any> = {\n segmentTree,\n singleCache: createLRUCache<string, AnySegmentNode<any>>(1000),\n matchCache: createLRUCache<string, RouteMatch<TRouteLike> | null>(1000),\n flatCache: null,\n masksTree: null,\n }\n return {\n processedTree,\n routesById,\n routesByPath,\n }\n}\n\nfunction findMatch<T extends RouteLike>(\n path: string,\n segmentTree: AnySegmentNode<T>,\n fuzzy = false,\n): {\n route: T\n /**\n * The raw (unparsed) params extracted from the path.\n * This will be the exhaustive list of all params defined in the route's path.\n */\n rawParams: Record<string, string>\n /**\n * The accumlulated parsed params of each route in the branch that had `skipRouteOnParseError` enabled.\n * Will not contain all params defined in the route's path. Those w/ a `params.parse` but no `skipRouteOnParseError` will need to be parsed separately.\n */\n parsedParams?: Record<string, unknown>\n} | null {\n const parts = path.split('/')\n const leaf = getNodeMatch(path, parts, segmentTree, fuzzy)\n if (!leaf) return null\n const [rawParams] = extractParams(path, parts, leaf)\n return {\n route: leaf.node.route!,\n rawParams,\n parsedParams: leaf.parsedParams,\n }\n}\n\ntype ParamExtractionState = {\n part: number\n node: number\n path: number\n segment: number\n}\n\n/**\n * This function is \"resumable\":\n * - the `leaf` input can contain `extract` and `rawParams` properties from a previous `extractParams` call\n * - the returned `state` can be passed back as `extract` in a future call to continue extracting params from where we left off\n *\n * Inputs are *not* mutated.\n */\nfunction extractParams<T extends RouteLike>(\n path: string,\n parts: Array<string>,\n leaf: {\n node: AnySegmentNode<T>\n skipped: number\n extract?: ParamExtractionState\n rawParams?: Record<string, string>\n },\n): [rawParams: Record<string, string>, state: ParamExtractionState] {\n const list = buildBranch(leaf.node)\n let nodeParts: Array<string> | null = null\n const rawParams: Record<string, string> = Object.create(null)\n /** which segment of the path we're currently processing */\n let partIndex = leaf.extract?.part ?? 0\n /** which node of the route tree branch we're currently processing */\n let nodeIndex = leaf.extract?.node ?? 0\n /** index of the 1st character of the segment we're processing in the path string */\n let pathIndex = leaf.extract?.path ?? 0\n /** which fullPath segment we're currently processing */\n let segmentCount = leaf.extract?.segment ?? 0\n for (\n ;\n nodeIndex < list.length;\n partIndex++, nodeIndex++, pathIndex++, segmentCount++\n ) {\n const node = list[nodeIndex]!\n // index nodes are terminating nodes, nothing to extract, just leave\n if (node.kind === SEGMENT_TYPE_INDEX) break\n // pathless nodes do not consume a path segment\n if (node.kind === SEGMENT_TYPE_PATHLESS) {\n segmentCount--\n partIndex--\n pathIndex--\n continue\n }\n const part = parts[partIndex]\n const currentPathIndex = pathIndex\n if (part) pathIndex += part.length\n if (node.kind === SEGMENT_TYPE_PARAM) {\n nodeParts ??= leaf.node.fullPath.split('/')\n const nodePart = nodeParts[segmentCount]!\n const preLength = node.prefix?.length ?? 0\n // we can't rely on the presence of prefix/suffix to know whether it's curly-braced or not, because `/{$param}/` is valid, but has no prefix/suffix\n const isCurlyBraced = nodePart.charCodeAt(preLength) === 123 // '{'\n // param name is extracted at match-time so that tree nodes that are identical except for param name can share the same node\n if (isCurlyBraced) {\n const sufLength = node.suffix?.length ?? 0\n const name = nodePart.substring(\n preLength + 2,\n nodePart.length - sufLength - 1,\n )\n const value = part!.substring(preLength, part!.length - sufLength)\n rawParams[name] = decodeURIComponent(value)\n } else {\n const name = nodePart.substring(1)\n rawParams[name] = decodeURIComponent(part!)\n }\n } else if (node.kind === SEGMENT_TYPE_OPTIONAL_PARAM) {\n if (leaf.skipped & (1 << nodeIndex)) {\n partIndex-- // stay on the same part\n pathIndex = currentPathIndex - 1 // undo pathIndex advancement; -1 to account for loop increment\n continue\n }\n nodeParts ??= leaf.node.fullPath.split('/')\n const nodePart = nodeParts[segmentCount]!\n const preLength = node.prefix?.length ?? 0\n const sufLength = node.suffix?.length ?? 0\n const name = nodePart.substring(\n preLength + 3,\n nodePart.length - sufLength - 1,\n )\n const value =\n node.suffix || node.prefix\n ? part!.substring(preLength, part!.length - sufLength)\n : part\n if (value) rawParams[name] = decodeURIComponent(value)\n } else if (node.kind === SEGMENT_TYPE_WILDCARD) {\n const n = node\n const value = path.substring(\n currentPathIndex + (n.prefix?.length ?? 0),\n path.length - (n.suffix?.length ?? 0),\n )\n const splat = decodeURIComponent(value)\n // TODO: Deprecate *\n rawParams['*'] = splat\n rawParams._splat = splat\n break\n }\n }\n if (leaf.rawParams) Object.assign(rawParams, leaf.rawParams)\n return [\n rawParams,\n {\n part: partIndex,\n node: nodeIndex,\n path: pathIndex,\n segment: segmentCount,\n },\n ]\n}\n\nfunction buildRouteBranch<T extends RouteLike>(route: T) {\n const list = [route]\n while (route.parentRoute) {\n route = route.parentRoute as T\n list.push(route)\n }\n list.reverse()\n return list\n}\n\nfunction buildBranch<T extends RouteLike>(node: AnySegmentNode<T>) {\n const list: Array<AnySegmentNode<T>> = Array(node.depth + 1)\n do {\n list[node.depth] = node\n node = node.parent!\n } while (node)\n return list\n}\n\ntype MatchStackFrame<T extends RouteLike> = {\n node: AnySegmentNode<T>\n /** index of the segment of path */\n index: number\n /** how many nodes between `node` and the root of the segment tree */\n depth: number\n /**\n * Bitmask of skipped optional segments.\n *\n * This is a very performant way of storing an \"array of booleans\", but it means beyond 32 segments we can't track skipped optionals.\n * If we really really need to support more than 32 segments we can switch to using a `BigInt` here. It's about 2x slower in worst case scenarios.\n */\n skipped: number\n /** Positional bitmasks tracking which consumed URL segments matched each segment kind. */\n statics: number\n dynamics: number\n optionals: number\n /** intermediary state for param extraction */\n extract?: ParamExtractionState\n /** intermediary params from param extraction */\n rawParams?: Record<string, string>\n parsedParams?: Record<string, unknown>\n}\n\nfunction getNodeMatch<T extends RouteLike>(\n path: string,\n parts: Array<string>,\n segmentTree: AnySegmentNode<T>,\n fuzzy: boolean,\n) {\n // quick check for root index\n // this is an optimization, algorithm should work correctly without this block\n if (path === '/' && segmentTree.index)\n return { node: segmentTree.index, skipped: 0 } as Pick<\n Frame,\n 'node' | 'skipped' | 'parsedParams'\n >\n\n const trailingSlash = !last(parts)\n const pathIsIndex = trailingSlash && path !== '/'\n const partsLength = parts.length - (trailingSlash ? 1 : 0)\n\n type Frame = MatchStackFrame<T>\n\n // use a stack to explore all possible paths (params cause branching)\n // iterate \"backwards\" (low priority first) so that we can push() each candidate, and pop() the highest priority candidate first\n // - pros: it is depth-first, so we find full matches faster\n // - cons: we cannot short-circuit, because highest priority matches are at the end of the loop (for loop with i--) (but we have no good short-circuiting anyway)\n // other possible approaches:\n // - shift instead of pop (measure performance difference), this allows iterating \"forwards\" (effectively breadth-first)\n // - never remove from the stack, keep a cursor instead. Then we can push \"forwards\" and avoid reversing the order of candidates (effectively breadth-first)\n const stack: Array<Frame> = [\n {\n node: segmentTree,\n index: 1,\n skipped: 0,\n depth: 1,\n statics: 0,\n dynamics: 0,\n optionals: 0,\n },\n ]\n\n let bestFuzzy: Frame | null = null\n let bestMatch: Frame | null = null\n\n while (stack.length) {\n const frame = stack.pop()!\n const { node, index, skipped, depth, statics, dynamics, optionals } = frame\n let { extract, rawParams, parsedParams } = frame\n\n // Wildcard candidates are pushed speculatively as fallbacks in case a\n // higher-priority wildcard later fails params.parse. If a better wildcard\n // has already validated and become bestMatch, lower-priority wildcard\n // fallbacks cannot win anymore and should not run params.parse.\n if (\n node.kind === SEGMENT_TYPE_WILDCARD &&\n node.route &&\n !isFrameMoreSpecific(bestMatch, frame)\n ) {\n continue\n }\n\n if (node.skipOnParamError) {\n const result = validateMatchParams(path, parts, frame)\n if (!result) continue\n rawParams = frame.rawParams\n extract = frame.extract\n parsedParams = frame.parsedParams\n }\n\n // In fuzzy mode, track the best partial match we've found so far\n if (\n fuzzy &&\n node.route &&\n node.kind !== SEGMENT_TYPE_INDEX &&\n isFrameMoreSpecific(bestFuzzy, frame)\n ) {\n bestFuzzy = frame\n }\n\n const isBeyondPath = index === partsLength\n if (isBeyondPath) {\n if (\n node.route &&\n (!pathIsIndex ||\n node.kind === SEGMENT_TYPE_INDEX ||\n node.kind === SEGMENT_TYPE_WILDCARD) &&\n isFrameMoreSpecific(bestMatch, frame)\n ) {\n bestMatch = frame\n }\n // beyond the length of the path parts, only some segment types can match\n if (!node.optional && !node.wildcard && !node.index && !node.pathless)\n continue\n }\n\n const part = isBeyondPath ? undefined : parts[index]!\n let lowerPart: string\n\n // 0. Try index match\n if (isBeyondPath && node.index) {\n const indexFrame = {\n node: node.index,\n index,\n skipped,\n depth: depth + 1,\n statics,\n dynamics,\n optionals,\n extract,\n rawParams,\n parsedParams,\n }\n let indexValid = true\n if (node.index.skipOnParamError) {\n const result = validateMatchParams(path, parts, indexFrame)\n if (!result) indexValid = false\n }\n if (indexValid) {\n // perfect match, no need to continue\n // this is an optimization, algorithm should work correctly without this block\n if (\n !dynamics &&\n !optionals &&\n !skipped &&\n isPerfectStaticMatch(statics, partsLength)\n ) {\n return indexFrame\n }\n if (isFrameMoreSpecific(bestMatch, indexFrame)) {\n // index matches skip the stack because they cannot have children\n bestMatch = indexFrame\n }\n }\n }\n\n // 5. Try wildcard match\n if (node.wildcard) {\n for (let i = node.wildcard.length - 1; i >= 0; i--) {\n const segment = node.wildcard[i]!\n const { prefix, suffix } = segment\n if (prefix) {\n if (isBeyondPath) continue\n const casePart = segment.caseSensitive\n ? part\n : (lowerPart ??= part!.toLowerCase())\n if (!casePart!.startsWith(prefix)) continue\n }\n if (suffix) {\n if (isBeyondPath) continue\n const end = parts.slice(index).join('/').slice(-suffix.length)\n const casePart = segment.caseSensitive ? end : end.toLowerCase()\n if (casePart !== suffix) continue\n }\n // wildcard matches consume the rest of the URL and cannot have children\n stack.push({\n node: segment,\n index: partsLength,\n skipped,\n depth: depth + 1,\n statics,\n dynamics,\n optionals,\n extract,\n rawParams,\n parsedParams,\n })\n }\n }\n\n // 4. Try optional match\n if (node.optional) {\n const nextSkipped = skipped | (1 << depth)\n const nextDepth = depth + 1\n for (let i = node.optional.length - 1; i >= 0; i--) {\n const segment = node.optional[i]!\n // when skipping, node and depth advance by 1, but index doesn't\n stack.push({\n node: segment,\n index,\n skipped: nextSkipped,\n depth: nextDepth,\n statics,\n dynamics,\n optionals,\n extract,\n rawParams,\n parsedParams,\n }) // enqueue skipping the optional\n }\n if (!isBeyondPath) {\n for (let i = node.optional.length - 1; i >= 0; i--) {\n const segment = node.optional[i]!\n const { prefix, suffix } = segment\n if (prefix || suffix) {\n const casePart = segment.caseSensitive\n ? part!\n : (lowerPart ??= part!.toLowerCase())\n if (prefix && !casePart.startsWith(prefix)) continue\n if (suffix && !casePart.endsWith(suffix)) continue\n }\n stack.push({\n node: segment,\n index: index + 1,\n skipped,\n depth: nextDepth,\n statics,\n dynamics,\n optionals: optionals + segmentScore(partsLength, index),\n extract,\n rawParams,\n parsedParams,\n })\n }\n }\n }\n\n // 3. Try dynamic match\n if (!isBeyondPath && node.dynamic && part) {\n for (let i = node.dynamic.length - 1; i >= 0; i--) {\n const segment = node.dynamic[i]!\n const { prefix, suffix } = segment\n if (prefix || suffix) {\n const casePart = segment.caseSensitive\n ? part\n : (lowerPart ??= part.toLowerCase())\n if (prefix && !casePart.startsWith(prefix)) continue\n if (suffix && !casePart.endsWith(suffix)) continue\n }\n stack.push({\n node: segment,\n index: index + 1,\n skipped,\n depth: depth + 1,\n statics,\n dynamics: dynamics + segmentScore(partsLength, index),\n optionals,\n extract,\n rawParams,\n parsedParams,\n })\n }\n }\n\n // 2. Try case insensitive static match\n if (!isBeyondPath && node.staticInsensitive) {\n const match = node.staticInsensitive.get(\n (lowerPart ??= part!.toLowerCase()),\n )\n if (match) {\n stack.push({\n node: match,\n index: index + 1,\n skipped,\n depth: depth + 1,\n statics: statics + segmentScore(partsLength, index),\n dynamics,\n optionals,\n extract,\n rawParams,\n parsedParams,\n })\n }\n }\n\n // 1. Try static match\n if (!isBeyondPath && node.static) {\n const match = node.static.get(part!)\n if (match) {\n stack.push({\n node: match,\n index: index + 1,\n skipped,\n depth: depth + 1,\n statics: statics + segmentScore(partsLength, index),\n dynamics,\n optionals,\n extract,\n rawParams,\n parsedParams,\n })\n }\n }\n\n // 0. Try pathless match\n if (node.pathless) {\n const nextDepth = depth + 1\n for (let i = node.pathless.length - 1; i >= 0; i--) {\n const segment = node.pathless[i]!\n stack.push({\n node: segment,\n index,\n skipped,\n depth: nextDepth,\n statics,\n dynamics,\n optionals,\n extract,\n rawParams,\n parsedParams,\n })\n }\n }\n }\n\n if (bestMatch) return bestMatch\n\n if (fuzzy && bestFuzzy) {\n let sliceIndex = bestFuzzy.index\n for (let i = 0; i < bestFuzzy.index; i++) {\n sliceIndex += parts[i]!.length\n }\n const splat = sliceIndex === path.length ? '/' : path.slice(sliceIndex)\n bestFuzzy.rawParams ??= Object.create(null)\n bestFuzzy.rawParams!['**'] = decodeURIComponent(splat)\n return bestFuzzy\n }\n\n return null\n}\n\nfunction segmentScore(partsLength: number, index: number): number {\n // The specificity scores are bitmasks over consumed URL segments. Earlier\n // URL segments should dominate later ones when comparing scores, so the\n // first real segment gets the highest bit and the last gets bit 0. Since\n // `parts[0]` is the empty string before the leading slash, real URL segments\n // are [1, partsLength), making this segment's bit `partsLength - index - 1`.\n return 2 ** (partsLength - index - 1)\n}\n\nfunction isPerfectStaticMatch(statics: number, partsLength: number): boolean {\n return statics === 2 ** (partsLength - 1) - 1\n}\n\nfunction validateMatchParams<T extends RouteLike>(\n path: string,\n parts: Array<string>,\n frame: MatchStackFrame<T>,\n) {\n try {\n const [rawParams, state] = extractParams(path, parts, frame)\n frame.rawParams = rawParams\n frame.extract = state\n const parsed = frame.node.parse!(rawParams)\n frame.parsedParams = Object.assign(\n Object.create(null),\n frame.parsedParams,\n parsed,\n )\n return true\n } catch {\n return null\n }\n}\n\nfunction isFrameMoreSpecific(\n // the stack frame previously saved as \"best match\"\n prev: MatchStackFrame<any> | null,\n // the candidate stack frame\n next: MatchStackFrame<any>,\n): boolean {\n if (!prev) return true\n return (\n next.statics > prev.statics ||\n (next.statics === prev.statics &&\n (next.dynamics > prev.dynamics ||\n (next.dynamics === prev.dynamics &&\n (next.optionals > prev.optionals ||\n (next.optionals === prev.optionals &&\n ((next.node.kind === SEGMENT_TYPE_INDEX) >\n (prev.node.kind === SEGMENT_TYPE_INDEX) ||\n ((next.node.kind === SEGMENT_TYPE_INDEX) ===\n (prev.node.kind === SEGMENT_TYPE_INDEX) &&\n next.depth > prev.depth)))))))\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"new-process-route-tree.cjs","names":[],"sources":["../../src/new-process-route-tree.ts"],"sourcesContent":["import { invariant } from './invariant'\nimport { createLRUCache } from './lru-cache'\nimport { last } from './utils'\nimport type { LRUCache } from './lru-cache'\n\nexport const SEGMENT_TYPE_PATHNAME = 0\nexport const SEGMENT_TYPE_PARAM = 1\nexport const SEGMENT_TYPE_WILDCARD = 2\nexport const SEGMENT_TYPE_OPTIONAL_PARAM = 3\nconst SEGMENT_TYPE_INDEX = 4\nconst SEGMENT_TYPE_PATHLESS = 5 // only used in matching to represent pathless routes that need to carry more information\n\n/**\n * All the kinds of segments that can be present in a route path.\n */\nexport type SegmentKind =\n | typeof SEGMENT_TYPE_PATHNAME\n | typeof SEGMENT_TYPE_PARAM\n | typeof SEGMENT_TYPE_WILDCARD\n | typeof SEGMENT_TYPE_OPTIONAL_PARAM\n\n/**\n * All the kinds of segments that can be present in the segment tree.\n */\ntype ExtendedSegmentKind =\n | SegmentKind\n | typeof SEGMENT_TYPE_INDEX\n | typeof SEGMENT_TYPE_PATHLESS\n\nfunction getOpenAndCloseBraces(\n part: string,\n): [openBrace: number, closeBrace: number] | null {\n const openBrace = part.indexOf('{')\n if (openBrace === -1) return null\n const closeBrace = part.indexOf('}', openBrace)\n if (closeBrace === -1) return null\n const afterOpen = openBrace + 1\n if (afterOpen >= part.length) return null\n return [openBrace, closeBrace]\n}\n\ntype ParsedSegment = Uint16Array & {\n /** segment type (0 = pathname, 1 = param, 2 = wildcard, 3 = optional param) */\n 0: SegmentKind\n /** index of the end of the prefix */\n 1: number\n /** index of the start of the value */\n 2: number\n /** index of the end of the value */\n 3: number\n /** index of the start of the suffix */\n 4: number\n /** index of the end of the segment */\n 5: number\n}\n\n/**\n * Populates the `output` array with the parsed representation of the given `segment` string.\n *\n * Usage:\n * ```ts\n * let output\n * let cursor = 0\n * while (cursor < path.length) {\n * output = parseSegment(path, cursor, output)\n * const end = output[5]\n * cursor = end + 1\n * ```\n *\n * `output` is stored outside to avoid allocations during repeated calls. It doesn't need to be typed\n * or initialized, it will be done automatically.\n */\nexport function parseSegment(\n /** The full path string containing the segment. */\n path: string,\n /** The starting index of the segment within the path. */\n start: number,\n /** A Uint16Array (length: 6) to populate with the parsed segment data. */\n output: Uint16Array = new Uint16Array(6),\n): ParsedSegment {\n const next = path.indexOf('/', start)\n const end = next === -1 ? path.length : next\n const part = path.substring(start, end)\n\n if (!part || !part.includes('$')) {\n // early escape for static pathname\n output[0] = SEGMENT_TYPE_PATHNAME\n output[1] = start\n output[2] = start\n output[3] = end\n output[4] = end\n output[5] = end\n return output as ParsedSegment\n }\n\n // $ (wildcard)\n if (part === '$') {\n const total = path.length\n output[0] = SEGMENT_TYPE_WILDCARD\n output[1] = start\n output[2] = start\n output[3] = total\n output[4] = total\n output[5] = total\n return output as ParsedSegment\n }\n\n // $paramName\n if (part.charCodeAt(0) === 36) {\n output[0] = SEGMENT_TYPE_PARAM\n output[1] = start\n output[2] = start + 1 // skip '$'\n output[3] = end\n output[4] = end\n output[5] = end\n return output as ParsedSegment\n }\n\n const braces = getOpenAndCloseBraces(part)\n if (braces) {\n const [openBrace, closeBrace] = braces\n const firstChar = part.charCodeAt(openBrace + 1)\n\n // Check for {-$...} (optional param)\n // prefix{-$paramName}suffix\n // /^([^{]*)\\{-\\$([a-zA-Z_$][a-zA-Z0-9_$]*)\\}([^}]*)$/\n if (firstChar === 45) {\n // '-'\n if (\n openBrace + 2 < part.length &&\n part.charCodeAt(openBrace + 2) === 36 // '$'\n ) {\n const paramStart = openBrace + 3\n const paramEnd = closeBrace\n // Validate param name exists\n if (paramStart < paramEnd) {\n output[0] = SEGMENT_TYPE_OPTIONAL_PARAM\n output[1] = start + openBrace\n output[2] = start + paramStart\n output[3] = start + paramEnd\n output[4] = start + closeBrace + 1\n output[5] = end\n return output as ParsedSegment\n }\n }\n } else if (firstChar === 36) {\n // '$'\n const dollarPos = openBrace + 1\n const afterDollar = openBrace + 2\n // Check for {$} (wildcard)\n if (afterDollar === closeBrace) {\n // For wildcard, value should be '$' (from dollarPos to afterDollar)\n // prefix{$}suffix\n // /^([^{]*)\\{\\$\\}([^}]*)$/\n output[0] = SEGMENT_TYPE_WILDCARD\n output[1] = start + openBrace\n output[2] = start + dollarPos\n output[3] = start + afterDollar\n output[4] = start + closeBrace + 1\n output[5] = path.length\n return output as ParsedSegment\n }\n // Regular param {$paramName} - value is the param name (after $)\n // prefix{$paramName}suffix\n // /^([^{]*)\\{\\$([a-zA-Z_$][a-zA-Z0-9_$]*)\\}([^}]*)$/\n output[0] = SEGMENT_TYPE_PARAM\n output[1] = start + openBrace\n output[2] = start + afterDollar\n output[3] = start + closeBrace\n output[4] = start + closeBrace + 1\n output[5] = end\n return output as ParsedSegment\n }\n }\n\n // fallback to static pathname (should never happen)\n output[0] = SEGMENT_TYPE_PATHNAME\n output[1] = start\n output[2] = start\n output[3] = end\n output[4] = end\n output[5] = end\n return output as ParsedSegment\n}\n\n/**\n * Recursively parses the segments of the given route tree and populates a segment trie.\n *\n * @param data A reusable Uint16Array for parsing segments. (non important, we're just avoiding allocations)\n * @param route The current route to parse.\n * @param start The starting index for parsing within the route's full path.\n * @param node The current segment node in the trie to populate.\n * @param onRoute Callback invoked for each route processed.\n */\nfunction parseSegments<TRouteLike extends RouteLike>(\n defaultCaseSensitive: boolean,\n data: Uint16Array,\n route: TRouteLike,\n start: number,\n node: AnySegmentNode<TRouteLike>,\n depth: number,\n onRoute?: (route: TRouteLike) => void,\n) {\n onRoute?.(route)\n let cursor = start\n {\n const path = route.fullPath ?? route.from\n const length = path.length\n const caseSensitive = route.options?.caseSensitive ?? defaultCaseSensitive\n const parseParams =\n route.options?.params?.parse ?? route.options?.parseParams\n while (cursor < length) {\n const segment = parseSegment(path, cursor, data)\n let nextNode: AnySegmentNode<TRouteLike>\n const start = cursor\n const end = segment[5]\n cursor = end + 1\n depth++\n const kind = segment[0]\n switch (kind) {\n case SEGMENT_TYPE_PATHNAME: {\n const value = path.substring(segment[2], segment[3])\n if (caseSensitive) {\n const existingNode = node.static?.get(value)\n if (existingNode) {\n nextNode = existingNode\n } else {\n node.static ??= new Map()\n const next = createStaticNode<TRouteLike>(\n route.fullPath ?? route.from,\n )\n next.parent = node\n next.depth = depth\n nextNode = next\n node.static.set(value, next)\n }\n } else {\n const name = value.toLowerCase()\n const existingNode = node.staticInsensitive?.get(name)\n if (existingNode) {\n nextNode = existingNode\n } else {\n node.staticInsensitive ??= new Map()\n const next = createStaticNode<TRouteLike>(\n route.fullPath ?? route.from,\n )\n next.parent = node\n next.depth = depth\n nextNode = next\n node.staticInsensitive.set(name, next)\n }\n }\n break\n }\n case SEGMENT_TYPE_PARAM: {\n const prefix_raw = path.substring(start, segment[1])\n const suffix_raw = path.substring(segment[4], end)\n const actuallyCaseSensitive =\n caseSensitive && !!(prefix_raw || suffix_raw)\n const prefix = !prefix_raw\n ? undefined\n : actuallyCaseSensitive\n ? prefix_raw\n : prefix_raw.toLowerCase()\n const suffix = !suffix_raw\n ? undefined\n : actuallyCaseSensitive\n ? suffix_raw\n : suffix_raw.toLowerCase()\n const existingNode =\n !parseParams &&\n node.dynamic?.find(\n (s) =>\n !s.parse &&\n s.caseSensitive === actuallyCaseSensitive &&\n s.prefix === prefix &&\n s.suffix === suffix,\n )\n if (existingNode) {\n nextNode = existingNode\n } else {\n const next = createDynamicNode<TRouteLike>(\n SEGMENT_TYPE_PARAM,\n route.fullPath ?? route.from,\n actuallyCaseSensitive,\n prefix,\n suffix,\n )\n nextNode = next\n next.depth = depth\n next.parent = node\n node.dynamic ??= []\n node.dynamic.push(next)\n }\n break\n }\n case SEGMENT_TYPE_OPTIONAL_PARAM: {\n const prefix_raw = path.substring(start, segment[1])\n const suffix_raw = path.substring(segment[4], end)\n const actuallyCaseSensitive =\n caseSensitive && !!(prefix_raw || suffix_raw)\n const prefix = !prefix_raw\n ? undefined\n : actuallyCaseSensitive\n ? prefix_raw\n : prefix_raw.toLowerCase()\n const suffix = !suffix_raw\n ? undefined\n : actuallyCaseSensitive\n ? suffix_raw\n : suffix_raw.toLowerCase()\n const existingNode =\n !parseParams &&\n node.optional?.find(\n (s) =>\n !s.parse &&\n s.caseSensitive === actuallyCaseSensitive &&\n s.prefix === prefix &&\n s.suffix === suffix,\n )\n if (existingNode) {\n nextNode = existingNode\n } else {\n const next = createDynamicNode<TRouteLike>(\n SEGMENT_TYPE_OPTIONAL_PARAM,\n route.fullPath ?? route.from,\n actuallyCaseSensitive,\n prefix,\n suffix,\n )\n nextNode = next\n next.parent = node\n next.depth = depth\n node.optional ??= []\n node.optional.push(next)\n }\n break\n }\n case SEGMENT_TYPE_WILDCARD: {\n const prefix_raw = path.substring(start, segment[1])\n const suffix_raw = path.substring(segment[4], end)\n const actuallyCaseSensitive =\n caseSensitive && !!(prefix_raw || suffix_raw)\n const prefix = !prefix_raw\n ? undefined\n : actuallyCaseSensitive\n ? prefix_raw\n : prefix_raw.toLowerCase()\n const suffix = !suffix_raw\n ? undefined\n : actuallyCaseSensitive\n ? suffix_raw\n : suffix_raw.toLowerCase()\n const next = createDynamicNode<TRouteLike>(\n SEGMENT_TYPE_WILDCARD,\n route.fullPath ?? route.from,\n actuallyCaseSensitive,\n prefix,\n suffix,\n )\n nextNode = next\n next.parent = node\n next.depth = depth\n node.wildcard ??= []\n node.wildcard.push(next)\n }\n }\n node = nextNode\n }\n\n // create pathless node\n if (\n parseParams &&\n route.children &&\n !route.isRoot &&\n route.id &&\n route.id.charCodeAt(route.id.lastIndexOf('/') + 1) === 95 /* '_' */\n ) {\n const pathlessNode = createStaticNode<TRouteLike>(\n route.fullPath ?? route.from,\n )\n pathlessNode.kind = SEGMENT_TYPE_PATHLESS\n pathlessNode.parent = node\n depth++\n pathlessNode.depth = depth\n node.pathless ??= []\n node.pathless.push(pathlessNode)\n node = pathlessNode\n }\n\n const isLeaf = (route.path || !route.children) && !route.isRoot\n // create index node\n if (isLeaf && path.endsWith('/')) {\n const indexNode = createStaticNode<TRouteLike>(\n route.fullPath ?? route.from,\n )\n indexNode.kind = SEGMENT_TYPE_INDEX\n indexNode.parent = node\n depth++\n indexNode.depth = depth\n node.index = indexNode\n node = indexNode\n }\n\n node.parse = parseParams ?? null\n\n // make node \"matchable\"\n if (isLeaf && !node.route) {\n node.route = route\n node.fullPath = route.fullPath ?? route.from\n }\n }\n if (route.children)\n for (const child of route.children) {\n parseSegments(\n defaultCaseSensitive,\n data,\n child as TRouteLike,\n cursor,\n node,\n depth,\n onRoute,\n )\n }\n}\n\nfunction sortDynamic(\n a: {\n prefix?: string\n suffix?: string\n caseSensitive: boolean\n parse: null | ((params: Record<string, string>) => unknown)\n },\n b: {\n prefix?: string\n suffix?: string\n caseSensitive: boolean\n parse: null | ((params: Record<string, string>) => unknown)\n },\n) {\n if (a.parse && !b.parse) return -1\n if (!a.parse && b.parse) return 1\n if (a.prefix && b.prefix && a.prefix !== b.prefix) {\n if (a.prefix.startsWith(b.prefix)) return -1\n if (b.prefix.startsWith(a.prefix)) return 1\n }\n if (a.suffix && b.suffix && a.suffix !== b.suffix) {\n if (a.suffix.endsWith(b.suffix)) return -1\n if (b.suffix.endsWith(a.suffix)) return 1\n }\n if (a.prefix && !b.prefix) return -1\n if (!a.prefix && b.prefix) return 1\n if (a.suffix && !b.suffix) return -1\n if (!a.suffix && b.suffix) return 1\n if (a.caseSensitive && !b.caseSensitive) return -1\n if (!a.caseSensitive && b.caseSensitive) return 1\n\n // Equal specificity preserves route declaration order through stable sort.\n return 0\n}\n\nfunction sortTreeNodes(node: SegmentNode<RouteLike>) {\n if (node.pathless) {\n for (const child of node.pathless) {\n sortTreeNodes(child)\n }\n }\n if (node.static) {\n for (const child of node.static.values()) {\n sortTreeNodes(child)\n }\n }\n if (node.staticInsensitive) {\n for (const child of node.staticInsensitive.values()) {\n sortTreeNodes(child)\n }\n }\n if (node.dynamic?.length) {\n node.dynamic.sort(sortDynamic)\n for (const child of node.dynamic) {\n sortTreeNodes(child)\n }\n }\n if (node.optional?.length) {\n node.optional.sort(sortDynamic)\n for (const child of node.optional) {\n sortTreeNodes(child)\n }\n }\n if (node.wildcard?.length) {\n node.wildcard.sort(sortDynamic)\n for (const child of node.wildcard) {\n sortTreeNodes(child)\n }\n }\n}\n\nfunction createStaticNode<T extends RouteLike>(\n fullPath: string,\n): StaticSegmentNode<T> {\n return {\n kind: SEGMENT_TYPE_PATHNAME,\n depth: 0,\n pathless: null,\n index: null,\n static: null,\n staticInsensitive: null,\n dynamic: null,\n optional: null,\n wildcard: null,\n route: null,\n fullPath,\n parent: null,\n parse: null,\n }\n}\n\n/**\n * Keys must be declared in the same order as in `SegmentNode` type,\n * to ensure they are represented as the same object class in the engine.\n */\nfunction createDynamicNode<T extends RouteLike>(\n kind:\n | typeof SEGMENT_TYPE_PARAM\n | typeof SEGMENT_TYPE_WILDCARD\n | typeof SEGMENT_TYPE_OPTIONAL_PARAM,\n fullPath: string,\n caseSensitive: boolean,\n prefix?: string,\n suffix?: string,\n): DynamicSegmentNode<T> {\n return {\n kind,\n depth: 0,\n pathless: null,\n index: null,\n static: null,\n staticInsensitive: null,\n dynamic: null,\n optional: null,\n wildcard: null,\n route: null,\n fullPath,\n parent: null,\n parse: null,\n caseSensitive,\n prefix,\n suffix,\n }\n}\n\ntype StaticSegmentNode<T extends RouteLike> = SegmentNode<T> & {\n kind:\n | typeof SEGMENT_TYPE_PATHNAME\n | typeof SEGMENT_TYPE_PATHLESS\n | typeof SEGMENT_TYPE_INDEX\n}\n\ntype DynamicSegmentNode<T extends RouteLike> = SegmentNode<T> & {\n kind:\n | typeof SEGMENT_TYPE_PARAM\n | typeof SEGMENT_TYPE_WILDCARD\n | typeof SEGMENT_TYPE_OPTIONAL_PARAM\n prefix?: string\n suffix?: string\n caseSensitive: boolean\n}\n\ntype AnySegmentNode<T extends RouteLike> =\n | StaticSegmentNode<T>\n | DynamicSegmentNode<T>\n\ntype SegmentNode<T extends RouteLike> = {\n kind: ExtendedSegmentKind\n\n pathless: Array<StaticSegmentNode<T>> | null\n\n /** Exact index segment (highest priority) */\n index: StaticSegmentNode<T> | null\n\n /** Static segments (2nd priority) */\n static: Map<string, StaticSegmentNode<T>> | null\n\n /** Case insensitive static segments (3rd highest priority) */\n staticInsensitive: Map<string, StaticSegmentNode<T>> | null\n\n /** Dynamic segments ($param) */\n dynamic: Array<DynamicSegmentNode<T>> | null\n\n /** Optional dynamic segments ({-$param}) */\n optional: Array<DynamicSegmentNode<T>> | null\n\n /** Wildcard segments ($ - lowest priority) */\n wildcard: Array<DynamicSegmentNode<T>> | null\n\n /** Terminal route (if this path can end here) */\n route: T | null\n\n /** The full path for this segment node (will only be valid on leaf nodes) */\n fullPath: string\n\n parent: AnySegmentNode<T> | null\n\n depth: number\n\n /** route.options.params.parse function, set on the last node of the route */\n parse: null | ((params: Record<string, string>) => unknown)\n}\n\ntype RouteLike = {\n id?: string\n path?: string // relative path from the parent,\n children?: Array<RouteLike> // child routes,\n parentRoute?: RouteLike // parent route,\n isRoot?: boolean\n options?: {\n caseSensitive?: boolean\n parseParams?: (params: Record<string, string>) => unknown\n params?: {\n parse?: (params: Record<string, string>) => unknown\n }\n }\n} &\n // router tree\n (| { fullPath: string; from?: never } // full path from the root\n // flat route masks list\n | { fullPath?: never; from: string } // full path from the root\n )\n\nexport type ProcessedTree<\n TTree extends Extract<RouteLike, { fullPath: string }>,\n TFlat extends Extract<RouteLike, { from: string }>,\n TSingle extends Extract<RouteLike, { from: string }>,\n> = {\n /** a representation of the `routeTree` as a segment tree */\n segmentTree: AnySegmentNode<TTree>\n /** a mini route tree generated from the flat `routeMasks` list */\n masksTree: AnySegmentNode<TFlat> | null\n /** @deprecated keep until v2 so that `router.matchRoute` can keep not caring about the actual route tree */\n singleCache: LRUCache<string, AnySegmentNode<TSingle>>\n /** a cache of route matches from the `segmentTree` */\n matchCache: LRUCache<string, RouteMatch<TTree> | null>\n /** a cache of route matches from the `masksTree` */\n flatCache: LRUCache<string, ReturnType<typeof findMatch<TFlat>>> | null\n}\n\nexport function processRouteMasks<\n TRouteLike extends Extract<RouteLike, { from: string }>,\n>(\n routeList: Array<TRouteLike>,\n processedTree: ProcessedTree<any, TRouteLike, any>,\n) {\n const segmentTree = createStaticNode<TRouteLike>('/')\n const data = new Uint16Array(6)\n for (const route of routeList) {\n parseSegments(false, data, route, 1, segmentTree, 0)\n }\n sortTreeNodes(segmentTree)\n processedTree.masksTree = segmentTree\n processedTree.flatCache = createLRUCache<\n string,\n ReturnType<typeof findMatch<TRouteLike>>\n >(1000)\n}\n\n/**\n * Take an arbitrary list of routes, create a tree from them (if it hasn't been created already), and match a path against it.\n */\nexport function findFlatMatch<T extends Extract<RouteLike, { from: string }>>(\n /** The path to match. */\n path: string,\n /** The `processedTree` returned by the initial `processRouteTree` call. */\n processedTree: ProcessedTree<any, T, any>,\n) {\n path ||= '/'\n const cached = processedTree.flatCache!.get(path)\n if (cached) return cached\n const result = findMatch(path, processedTree.masksTree!)\n processedTree.flatCache!.set(path, result)\n return result\n}\n\n/**\n * @deprecated keep until v2 so that `router.matchRoute` can keep not caring about the actual route tree\n */\nexport function findSingleMatch(\n from: string,\n caseSensitive: boolean,\n fuzzy: boolean,\n path: string,\n processedTree: ProcessedTree<any, any, { from: string }>,\n) {\n from ||= '/'\n path ||= '/'\n const key = caseSensitive ? `case\\0${from}` : from\n let tree = processedTree.singleCache.get(key)\n if (!tree) {\n // single flat routes (router.matchRoute) are not eagerly processed,\n // if we haven't seen this route before, process it now\n tree = createStaticNode<{ from: string }>('/')\n const data = new Uint16Array(6)\n parseSegments(caseSensitive, data, { from }, 1, tree, 0)\n processedTree.singleCache.set(key, tree)\n }\n return findMatch(path, tree, fuzzy)\n}\n\ntype RouteMatch<T extends Extract<RouteLike, { fullPath: string }>> = {\n route: T\n rawParams: Record<string, string>\n branch: ReadonlyArray<T>\n}\n\nexport function findRouteMatch<\n T extends Extract<RouteLike, { fullPath: string }>,\n>(\n /** The path to match against the route tree. */\n path: string,\n /** The `processedTree` returned by the initial `processRouteTree` call. */\n processedTree: ProcessedTree<T, any, any>,\n /** If `true`, allows fuzzy matching (partial matches), i.e. which node in the tree would have been an exact match if the `path` had been shorter? */\n fuzzy = false,\n): RouteMatch<T> | null {\n const key = fuzzy ? path : `nofuzz\\0${path}` // the main use for `findRouteMatch` is fuzzy:true, so we optimize for that case\n const cached = processedTree.matchCache.get(key)\n if (cached !== undefined) return cached\n path ||= '/'\n let result: RouteMatch<T> | null\n\n try {\n result = findMatch(\n path,\n processedTree.segmentTree,\n fuzzy,\n ) as RouteMatch<T> | null\n } catch (err) {\n if (err instanceof URIError) {\n result = null\n } else {\n throw err\n }\n }\n\n if (result) result.branch = buildRouteBranch(result.route)\n processedTree.matchCache.set(key, result)\n return result\n}\n\n/** Trim trailing slashes (except preserving root '/'). */\nexport function trimPathRight(path: string) {\n return path === '/' ? path : path.replace(/\\/{1,}$/, '')\n}\n\nexport interface ProcessRouteTreeResult<\n TRouteLike extends Extract<RouteLike, { fullPath: string }> & { id: string },\n> {\n /** Should be considered a black box, needs to be provided to all matching functions in this module. */\n processedTree: ProcessedTree<TRouteLike, any, any>\n /** A lookup map of routes by their unique IDs. */\n routesById: Record<string, TRouteLike>\n /** A lookup map of routes by their trimmed full paths. */\n routesByPath: Record<string, TRouteLike>\n}\n\n/**\n * Processes a route tree into a segment trie for efficient path matching.\n * Also builds lookup maps for routes by ID and by trimmed full path.\n */\nexport function processRouteTree<\n TRouteLike extends Extract<RouteLike, { fullPath: string }> & { id: string },\n>(\n /** The root of the route tree to process. */\n routeTree: TRouteLike,\n /** Whether matching should be case sensitive by default (overridden by individual route options). */\n caseSensitive: boolean = false,\n /** Optional callback invoked for each route during processing. */\n initRoute?: (route: TRouteLike, index: number) => void,\n): ProcessRouteTreeResult<TRouteLike> {\n const segmentTree = createStaticNode<TRouteLike>(routeTree.fullPath)\n const data = new Uint16Array(6)\n const routesById = {} as Record<string, TRouteLike>\n const routesByPath = {} as Record<string, TRouteLike>\n let index = 0\n parseSegments(caseSensitive, data, routeTree, 1, segmentTree, 0, (route) => {\n initRoute?.(route, index)\n\n if (route.id in routesById) {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n `Invariant failed: Duplicate routes found with id: ${String(route.id)}`,\n )\n }\n\n invariant()\n }\n\n routesById[route.id] = route\n\n if (index !== 0 && route.path) {\n const trimmedFullPath = trimPathRight(route.fullPath)\n if (!routesByPath[trimmedFullPath] || route.fullPath.endsWith('/')) {\n routesByPath[trimmedFullPath] = route\n }\n }\n\n index++\n })\n sortTreeNodes(segmentTree)\n const processedTree: ProcessedTree<TRouteLike, any, any> = {\n segmentTree,\n singleCache: createLRUCache<string, AnySegmentNode<any>>(1000),\n matchCache: createLRUCache<string, RouteMatch<TRouteLike> | null>(1000),\n flatCache: null,\n masksTree: null,\n }\n return {\n processedTree,\n routesById,\n routesByPath,\n }\n}\n\nfunction findMatch<T extends RouteLike>(\n path: string,\n segmentTree: AnySegmentNode<T>,\n fuzzy = false,\n): {\n route: T\n /**\n * The raw (unparsed) params extracted from the path.\n * This will be the exhaustive list of all params defined in the route's path.\n */\n rawParams: Record<string, string>\n} | null {\n const parts = path.split('/')\n const leaf = getNodeMatch(path, parts, segmentTree, fuzzy)\n if (!leaf) return null\n const [rawParams] = extractParams(path, parts, leaf)\n return {\n route: leaf.node.route!,\n rawParams,\n }\n}\n\ntype ParamExtractionState = {\n part: number\n node: number\n path: number\n segment: number\n}\n\n/**\n * This function is \"resumable\":\n * - the `leaf` input can contain `extract` and `rawParams` properties from a previous `extractParams` call\n * - the returned `state` can be passed back as `extract` in a future call to continue extracting params from where we left off\n *\n * Inputs are *not* mutated.\n */\nfunction extractParams<T extends RouteLike>(\n path: string,\n parts: Array<string>,\n leaf: {\n node: AnySegmentNode<T>\n skipped: number\n extract?: ParamExtractionState\n rawParams?: Record<string, string>\n },\n): [rawParams: Record<string, string>, state: ParamExtractionState] {\n const list = buildBranch(leaf.node)\n let nodeParts: Array<string> | null = null\n const rawParams: Record<string, string> = Object.create(null)\n /** which segment of the path we're currently processing */\n let partIndex = leaf.extract?.part ?? 0\n /** which node of the route tree branch we're currently processing */\n let nodeIndex = leaf.extract?.node ?? 0\n /** index of the 1st character of the segment we're processing in the path string */\n let pathIndex = leaf.extract?.path ?? 0\n /** which fullPath segment we're currently processing */\n let segmentCount = leaf.extract?.segment ?? 0\n for (\n ;\n nodeIndex < list.length;\n partIndex++, nodeIndex++, pathIndex++, segmentCount++\n ) {\n const node = list[nodeIndex]!\n // index nodes are terminating nodes, nothing to extract, just leave\n if (node.kind === SEGMENT_TYPE_INDEX) break\n // pathless nodes do not consume a path segment\n if (node.kind === SEGMENT_TYPE_PATHLESS) {\n segmentCount--\n partIndex--\n pathIndex--\n continue\n }\n const part = parts[partIndex]\n const currentPathIndex = pathIndex\n if (part) pathIndex += part.length\n if (node.kind === SEGMENT_TYPE_PARAM) {\n nodeParts ??= leaf.node.fullPath.split('/')\n const nodePart = nodeParts[segmentCount]!\n const preLength = node.prefix?.length ?? 0\n // we can't rely on the presence of prefix/suffix to know whether it's curly-braced or not, because `/{$param}/` is valid, but has no prefix/suffix\n const isCurlyBraced = nodePart.charCodeAt(preLength) === 123 // '{'\n // param name is extracted at match-time so that tree nodes that are identical except for param name can share the same node\n if (isCurlyBraced) {\n const sufLength = node.suffix?.length ?? 0\n const name = nodePart.substring(\n preLength + 2,\n nodePart.length - sufLength - 1,\n )\n const value = part!.substring(preLength, part!.length - sufLength)\n rawParams[name] = decodeURIComponent(value)\n } else {\n const name = nodePart.substring(1)\n rawParams[name] = decodeURIComponent(part!)\n }\n } else if (node.kind === SEGMENT_TYPE_OPTIONAL_PARAM) {\n if (leaf.skipped & (1 << nodeIndex)) {\n partIndex-- // stay on the same part\n pathIndex = currentPathIndex - 1 // undo pathIndex advancement; -1 to account for loop increment\n continue\n }\n nodeParts ??= leaf.node.fullPath.split('/')\n const nodePart = nodeParts[segmentCount]!\n const preLength = node.prefix?.length ?? 0\n const sufLength = node.suffix?.length ?? 0\n const name = nodePart.substring(\n preLength + 3,\n nodePart.length - sufLength - 1,\n )\n const value =\n node.suffix || node.prefix\n ? part!.substring(preLength, part!.length - sufLength)\n : part\n if (value) rawParams[name] = decodeURIComponent(value)\n } else if (node.kind === SEGMENT_TYPE_WILDCARD) {\n const n = node\n const value = path.substring(\n currentPathIndex + (n.prefix?.length ?? 0),\n path.length - (n.suffix?.length ?? 0),\n )\n const splat = decodeURIComponent(value)\n // TODO: Deprecate *\n rawParams['*'] = splat\n rawParams._splat = splat\n break\n }\n }\n if (leaf.rawParams) Object.assign(rawParams, leaf.rawParams)\n return [\n rawParams,\n {\n part: partIndex,\n node: nodeIndex,\n path: pathIndex,\n segment: segmentCount,\n },\n ]\n}\n\nexport function buildRouteBranch<T extends RouteLike>(route: T) {\n const list = [route]\n while (route.parentRoute) {\n route = route.parentRoute as T\n list.push(route)\n }\n list.reverse()\n return list\n}\n\nfunction buildBranch<T extends RouteLike>(node: AnySegmentNode<T>) {\n const list: Array<AnySegmentNode<T>> = Array(node.depth + 1)\n do {\n list[node.depth] = node\n node = node.parent!\n } while (node)\n return list\n}\n\ntype MatchStackFrame<T extends RouteLike> = {\n node: AnySegmentNode<T>\n /** index of the segment of path */\n index: number\n /** how many nodes between `node` and the root of the segment tree */\n depth: number\n /**\n * Bitmask of skipped optional segments.\n *\n * This is a very performant way of storing an \"array of booleans\", but it means beyond 32 segments we can't track skipped optionals.\n * If we really really need to support more than 32 segments we can switch to using a `BigInt` here. It's about 2x slower in worst case scenarios.\n */\n skipped: number\n /** Positional bitmasks tracking which consumed URL segments matched each segment kind. */\n statics: number\n dynamics: number\n optionals: number\n /** intermediary state for param extraction */\n extract?: ParamExtractionState\n /** intermediary params from param extraction */\n rawParams?: Record<string, string>\n}\n\nfunction getNodeMatch<T extends RouteLike>(\n path: string,\n parts: Array<string>,\n segmentTree: AnySegmentNode<T>,\n fuzzy: boolean,\n) {\n // quick check for root index\n // this is an optimization, algorithm should work correctly without this block\n if (path === '/' && segmentTree.index)\n return { node: segmentTree.index, skipped: 0 } as Pick<\n Frame,\n 'node' | 'skipped'\n >\n\n const trailingSlash = !last(parts)\n const pathIsIndex = trailingSlash && path !== '/'\n const partsLength = parts.length - (trailingSlash ? 1 : 0)\n\n type Frame = MatchStackFrame<T>\n\n // use a stack to explore all possible paths (params cause branching)\n // iterate \"backwards\" (low priority first) so that we can push() each candidate, and pop() the highest priority candidate first\n // - pros: it is depth-first, so we find full matches faster\n // - cons: we cannot short-circuit, because highest priority matches are at the end of the loop (for loop with i--) (but we have no good short-circuiting anyway)\n // other possible approaches:\n // - shift instead of pop (measure performance difference), this allows iterating \"forwards\" (effectively breadth-first)\n // - never remove from the stack, keep a cursor instead. Then we can push \"forwards\" and avoid reversing the order of candidates (effectively breadth-first)\n const stack: Array<Frame> = [\n {\n node: segmentTree,\n index: 1,\n skipped: 0,\n depth: 1,\n statics: 0,\n dynamics: 0,\n optionals: 0,\n },\n ]\n\n let bestFuzzy: Frame | null = null\n let bestMatch: Frame | null = null\n\n while (stack.length) {\n const frame = stack.pop()!\n const { node, index, skipped, depth, statics, dynamics, optionals } = frame\n let { extract, rawParams } = frame\n\n // Wildcard candidates are pushed speculatively as fallbacks in case a\n // higher-priority wildcard later fails params.parse. If a better wildcard\n // has already validated and become bestMatch, lower-priority wildcard\n // fallbacks cannot win anymore and should not run params.parse.\n if (\n node.kind === SEGMENT_TYPE_WILDCARD &&\n node.route &&\n !isFrameMoreSpecific(bestMatch, frame)\n ) {\n continue\n }\n\n if (node.parse) {\n const result = validateParseParams(path, parts, frame)\n if (!result) continue\n rawParams = frame.rawParams\n extract = frame.extract\n }\n\n // In fuzzy mode, track the best partial match we've found so far\n if (\n fuzzy &&\n node.route &&\n node.kind !== SEGMENT_TYPE_INDEX &&\n isFrameMoreSpecific(bestFuzzy, frame)\n ) {\n bestFuzzy = frame\n }\n\n const isBeyondPath = index === partsLength\n if (isBeyondPath) {\n if (\n node.route &&\n (!pathIsIndex ||\n node.kind === SEGMENT_TYPE_INDEX ||\n node.kind === SEGMENT_TYPE_WILDCARD) &&\n isFrameMoreSpecific(bestMatch, frame)\n ) {\n bestMatch = frame\n }\n // beyond the length of the path parts, only some segment types can match\n if (!node.optional && !node.wildcard && !node.index && !node.pathless)\n continue\n }\n\n const part = isBeyondPath ? undefined : parts[index]!\n let lowerPart: string\n\n // 0. Try index match\n if (isBeyondPath && node.index) {\n const indexFrame = {\n node: node.index,\n index,\n skipped,\n depth: depth + 1,\n statics,\n dynamics,\n optionals,\n extract,\n rawParams,\n }\n let indexValid = true\n if (node.index.parse) {\n const result = validateParseParams(path, parts, indexFrame)\n if (!result) indexValid = false\n }\n if (indexValid) {\n // perfect match, no need to continue\n // this is an optimization, algorithm should work correctly without this block\n if (\n !dynamics &&\n !optionals &&\n !skipped &&\n isPerfectStaticMatch(statics, partsLength)\n ) {\n return indexFrame\n }\n if (isFrameMoreSpecific(bestMatch, indexFrame)) {\n // index matches skip the stack because they cannot have children\n bestMatch = indexFrame\n }\n }\n }\n\n // 5. Try wildcard match\n if (node.wildcard) {\n for (let i = node.wildcard.length - 1; i >= 0; i--) {\n const segment = node.wildcard[i]!\n const { prefix, suffix } = segment\n if (prefix) {\n if (isBeyondPath) continue\n const casePart = segment.caseSensitive\n ? part\n : (lowerPart ??= part!.toLowerCase())\n if (!casePart!.startsWith(prefix)) continue\n }\n if (suffix) {\n if (isBeyondPath) continue\n const end = parts.slice(index).join('/').slice(-suffix.length)\n const casePart = segment.caseSensitive ? end : end.toLowerCase()\n if (casePart !== suffix) continue\n }\n // wildcard matches consume the rest of the URL and cannot have children\n stack.push({\n node: segment,\n index: partsLength,\n skipped,\n depth: depth + 1,\n statics,\n dynamics,\n optionals,\n extract,\n rawParams,\n })\n }\n }\n\n // 4. Try optional match\n if (node.optional) {\n const nextSkipped = skipped | (1 << depth)\n const nextDepth = depth + 1\n for (let i = node.optional.length - 1; i >= 0; i--) {\n const segment = node.optional[i]!\n // when skipping, node and depth advance by 1, but index doesn't\n stack.push({\n node: segment,\n index,\n skipped: nextSkipped,\n depth: nextDepth,\n statics,\n dynamics,\n optionals,\n extract,\n rawParams,\n }) // enqueue skipping the optional\n }\n if (!isBeyondPath) {\n for (let i = node.optional.length - 1; i >= 0; i--) {\n const segment = node.optional[i]!\n const { prefix, suffix } = segment\n if (prefix || suffix) {\n const casePart = segment.caseSensitive\n ? part!\n : (lowerPart ??= part!.toLowerCase())\n if (prefix && !casePart.startsWith(prefix)) continue\n if (suffix && !casePart.endsWith(suffix)) continue\n }\n stack.push({\n node: segment,\n index: index + 1,\n skipped,\n depth: nextDepth,\n statics,\n dynamics,\n optionals: optionals + segmentScore(partsLength, index),\n extract,\n rawParams,\n })\n }\n }\n }\n\n // 3. Try dynamic match\n if (!isBeyondPath && node.dynamic && part) {\n for (let i = node.dynamic.length - 1; i >= 0; i--) {\n const segment = node.dynamic[i]!\n const { prefix, suffix } = segment\n if (prefix || suffix) {\n const casePart = segment.caseSensitive\n ? part\n : (lowerPart ??= part.toLowerCase())\n if (prefix && !casePart.startsWith(prefix)) continue\n if (suffix && !casePart.endsWith(suffix)) continue\n }\n stack.push({\n node: segment,\n index: index + 1,\n skipped,\n depth: depth + 1,\n statics,\n dynamics: dynamics + segmentScore(partsLength, index),\n optionals,\n extract,\n rawParams,\n })\n }\n }\n\n // 2. Try case insensitive static match\n if (!isBeyondPath && node.staticInsensitive) {\n const match = node.staticInsensitive.get(\n (lowerPart ??= part!.toLowerCase()),\n )\n if (match) {\n stack.push({\n node: match,\n index: index + 1,\n skipped,\n depth: depth + 1,\n statics: statics + segmentScore(partsLength, index),\n dynamics,\n optionals,\n extract,\n rawParams,\n })\n }\n }\n\n // 1. Try static match\n if (!isBeyondPath && node.static) {\n const match = node.static.get(part!)\n if (match) {\n stack.push({\n node: match,\n index: index + 1,\n skipped,\n depth: depth + 1,\n statics: statics + segmentScore(partsLength, index),\n dynamics,\n optionals,\n extract,\n rawParams,\n })\n }\n }\n\n // 0. Try pathless match\n if (node.pathless) {\n const nextDepth = depth + 1\n for (let i = node.pathless.length - 1; i >= 0; i--) {\n const segment = node.pathless[i]!\n stack.push({\n node: segment,\n index,\n skipped,\n depth: nextDepth,\n statics,\n dynamics,\n optionals,\n extract,\n rawParams,\n })\n }\n }\n }\n\n if (bestMatch) return bestMatch\n\n if (fuzzy && bestFuzzy) {\n let sliceIndex = bestFuzzy.index\n for (let i = 0; i < bestFuzzy.index; i++) {\n sliceIndex += parts[i]!.length\n }\n const splat = sliceIndex === path.length ? '/' : path.slice(sliceIndex)\n bestFuzzy.rawParams ??= Object.create(null)\n bestFuzzy.rawParams!['**'] = decodeURIComponent(splat)\n return bestFuzzy\n }\n\n return null\n}\n\nfunction segmentScore(partsLength: number, index: number): number {\n // The specificity scores are bitmasks over consumed URL segments. Earlier\n // URL segments should dominate later ones when comparing scores, so the\n // first real segment gets the highest bit and the last gets bit 0. Since\n // `parts[0]` is the empty string before the leading slash, real URL segments\n // are [1, partsLength), making this segment's bit `partsLength - index - 1`.\n return 2 ** (partsLength - index - 1)\n}\n\nfunction isPerfectStaticMatch(statics: number, partsLength: number): boolean {\n return statics === 2 ** (partsLength - 1) - 1\n}\n\nfunction validateParseParams<T extends RouteLike>(\n path: string,\n parts: Array<string>,\n frame: MatchStackFrame<T>,\n) {\n let rawParams: Record<string, string>\n let state: ParamExtractionState\n\n try {\n ;[rawParams, state] = extractParams(path, parts, frame)\n } catch {\n return null\n }\n\n frame.rawParams = rawParams\n frame.extract = state\n\n if (!frame.node.parse) return true\n\n try {\n if (frame.node.parse(rawParams) === false) return null\n } catch {\n // Thrown parse errors should be surfaced on the selected match by\n // extractStrictParams, not used as fallback route selection.\n }\n\n return true\n}\n\nfunction isFrameMoreSpecific(\n // the stack frame previously saved as \"best match\"\n prev: MatchStackFrame<any> | null,\n // the candidate stack frame\n next: MatchStackFrame<any>,\n): boolean {\n if (!prev) return true\n return (\n next.statics > prev.statics ||\n (next.statics === prev.statics &&\n (next.dynamics > prev.dynamics ||\n (next.dynamics === prev.dynamics &&\n (next.optionals > prev.optionals ||\n (next.optionals === prev.optionals &&\n ((next.node.kind === SEGMENT_TYPE_INDEX) >\n (prev.node.kind === SEGMENT_TYPE_INDEX) ||\n ((next.node.kind === SEGMENT_TYPE_INDEX) ===\n (prev.node.kind === SEGMENT_TYPE_INDEX) &&\n next.depth > prev.depth)))))))\n )\n}\n"],"mappings":";;;AASA,MAAM,qBAAqB;AAC3B,MAAM,wBAAwB;AAmB9B,SAAS,sBACP,MACgD;CAChD,MAAM,YAAY,KAAK,QAAQ,IAAI;AACnC,KAAI,cAAc,GAAI,QAAO;CAC7B,MAAM,aAAa,KAAK,QAAQ,KAAK,UAAU;AAC/C,KAAI,eAAe,GAAI,QAAO;AAE9B,KADkB,YAAY,KACb,KAAK,OAAQ,QAAO;AACrC,QAAO,CAAC,WAAW,WAAW;;;;;;;;;;;;;;;;;;AAkChC,SAAgB,aAEd,MAEA,OAEA,SAAsB,IAAI,YAAY,EAAE,EACzB;CACf,MAAM,OAAO,KAAK,QAAQ,KAAK,MAAM;CACrC,MAAM,MAAM,SAAS,KAAK,KAAK,SAAS;CACxC,MAAM,OAAO,KAAK,UAAU,OAAO,IAAI;AAEvC,KAAI,CAAC,QAAQ,CAAC,KAAK,SAAS,IAAI,EAAE;AAEhC,SAAO,KAAA;AACP,SAAO,KAAK;AACZ,SAAO,KAAK;AACZ,SAAO,KAAK;AACZ,SAAO,KAAK;AACZ,SAAO,KAAK;AACZ,SAAO;;AAIT,KAAI,SAAS,KAAK;EAChB,MAAM,QAAQ,KAAK;AACnB,SAAO,KAAA;AACP,SAAO,KAAK;AACZ,SAAO,KAAK;AACZ,SAAO,KAAK;AACZ,SAAO,KAAK;AACZ,SAAO,KAAK;AACZ,SAAO;;AAIT,KAAI,KAAK,WAAW,EAAE,KAAK,IAAI;AAC7B,SAAO,KAAA;AACP,SAAO,KAAK;AACZ,SAAO,KAAK,QAAQ;AACpB,SAAO,KAAK;AACZ,SAAO,KAAK;AACZ,SAAO,KAAK;AACZ,SAAO;;CAGT,MAAM,SAAS,sBAAsB,KAAK;AAC1C,KAAI,QAAQ;EACV,MAAM,CAAC,WAAW,cAAc;EAChC,MAAM,YAAY,KAAK,WAAW,YAAY,EAAE;AAKhD,MAAI,cAAc;OAGd,YAAY,IAAI,KAAK,UACrB,KAAK,WAAW,YAAY,EAAE,KAAK,IACnC;IACA,MAAM,aAAa,YAAY;IAC/B,MAAM,WAAW;AAEjB,QAAI,aAAa,UAAU;AACzB,YAAO,KAAA;AACP,YAAO,KAAK,QAAQ;AACpB,YAAO,KAAK,QAAQ;AACpB,YAAO,KAAK,QAAQ;AACpB,YAAO,KAAK,QAAQ,aAAa;AACjC,YAAO,KAAK;AACZ,YAAO;;;aAGF,cAAc,IAAI;GAE3B,MAAM,YAAY,YAAY;GAC9B,MAAM,cAAc,YAAY;AAEhC,OAAI,gBAAgB,YAAY;AAI9B,WAAO,KAAA;AACP,WAAO,KAAK,QAAQ;AACpB,WAAO,KAAK,QAAQ;AACpB,WAAO,KAAK,QAAQ;AACpB,WAAO,KAAK,QAAQ,aAAa;AACjC,WAAO,KAAK,KAAK;AACjB,WAAO;;AAKT,UAAO,KAAA;AACP,UAAO,KAAK,QAAQ;AACpB,UAAO,KAAK,QAAQ;AACpB,UAAO,KAAK,QAAQ;AACpB,UAAO,KAAK,QAAQ,aAAa;AACjC,UAAO,KAAK;AACZ,UAAO;;;AAKX,QAAO,KAAA;AACP,QAAO,KAAK;AACZ,QAAO,KAAK;AACZ,QAAO,KAAK;AACZ,QAAO,KAAK;AACZ,QAAO,KAAK;AACZ,QAAO;;;;;;;;;;;AAYT,SAAS,cACP,sBACA,MACA,OACA,OACA,MACA,OACA,SACA;AACA,WAAU,MAAM;CAChB,IAAI,SAAS;CACb;EACE,MAAM,OAAO,MAAM,YAAY,MAAM;EACrC,MAAM,SAAS,KAAK;EACpB,MAAM,gBAAgB,MAAM,SAAS,iBAAiB;EACtD,MAAM,cACJ,MAAM,SAAS,QAAQ,SAAS,MAAM,SAAS;AACjD,SAAO,SAAS,QAAQ;GACtB,MAAM,UAAU,aAAa,MAAM,QAAQ,KAAK;GAChD,IAAI;GACJ,MAAM,QAAQ;GACd,MAAM,MAAM,QAAQ;AACpB,YAAS,MAAM;AACf;AAEA,WADa,QAAQ,IACrB;IACE,KAAA,GAA4B;KAC1B,MAAM,QAAQ,KAAK,UAAU,QAAQ,IAAI,QAAQ,GAAG;AACpD,SAAI,eAAe;MACjB,MAAM,eAAe,KAAK,QAAQ,IAAI,MAAM;AAC5C,UAAI,aACF,YAAW;WACN;AACL,YAAK,2BAAW,IAAI,KAAK;OACzB,MAAM,OAAO,iBACX,MAAM,YAAY,MAAM,KACzB;AACD,YAAK,SAAS;AACd,YAAK,QAAQ;AACb,kBAAW;AACX,YAAK,OAAO,IAAI,OAAO,KAAK;;YAEzB;MACL,MAAM,OAAO,MAAM,aAAa;MAChC,MAAM,eAAe,KAAK,mBAAmB,IAAI,KAAK;AACtD,UAAI,aACF,YAAW;WACN;AACL,YAAK,sCAAsB,IAAI,KAAK;OACpC,MAAM,OAAO,iBACX,MAAM,YAAY,MAAM,KACzB;AACD,YAAK,SAAS;AACd,YAAK,QAAQ;AACb,kBAAW;AACX,YAAK,kBAAkB,IAAI,MAAM,KAAK;;;AAG1C;;IAEF,KAAA,GAAyB;KACvB,MAAM,aAAa,KAAK,UAAU,OAAO,QAAQ,GAAG;KACpD,MAAM,aAAa,KAAK,UAAU,QAAQ,IAAI,IAAI;KAClD,MAAM,wBACJ,iBAAiB,CAAC,EAAE,cAAc;KACpC,MAAM,SAAS,CAAC,aACZ,KAAA,IACA,wBACE,aACA,WAAW,aAAa;KAC9B,MAAM,SAAS,CAAC,aACZ,KAAA,IACA,wBACE,aACA,WAAW,aAAa;KAC9B,MAAM,eACJ,CAAC,eACD,KAAK,SAAS,MACX,MACC,CAAC,EAAE,SACH,EAAE,kBAAkB,yBACpB,EAAE,WAAW,UACb,EAAE,WAAW,OAChB;AACH,SAAI,aACF,YAAW;UACN;MACL,MAAM,OAAO,kBAAA,GAEX,MAAM,YAAY,MAAM,MACxB,uBACA,QACA,OACD;AACD,iBAAW;AACX,WAAK,QAAQ;AACb,WAAK,SAAS;AACd,WAAK,YAAY,EAAE;AACnB,WAAK,QAAQ,KAAK,KAAK;;AAEzB;;IAEF,KAAA,GAAkC;KAChC,MAAM,aAAa,KAAK,UAAU,OAAO,QAAQ,GAAG;KACpD,MAAM,aAAa,KAAK,UAAU,QAAQ,IAAI,IAAI;KAClD,MAAM,wBACJ,iBAAiB,CAAC,EAAE,cAAc;KACpC,MAAM,SAAS,CAAC,aACZ,KAAA,IACA,wBACE,aACA,WAAW,aAAa;KAC9B,MAAM,SAAS,CAAC,aACZ,KAAA,IACA,wBACE,aACA,WAAW,aAAa;KAC9B,MAAM,eACJ,CAAC,eACD,KAAK,UAAU,MACZ,MACC,CAAC,EAAE,SACH,EAAE,kBAAkB,yBACpB,EAAE,WAAW,UACb,EAAE,WAAW,OAChB;AACH,SAAI,aACF,YAAW;UACN;MACL,MAAM,OAAO,kBAAA,GAEX,MAAM,YAAY,MAAM,MACxB,uBACA,QACA,OACD;AACD,iBAAW;AACX,WAAK,SAAS;AACd,WAAK,QAAQ;AACb,WAAK,aAAa,EAAE;AACpB,WAAK,SAAS,KAAK,KAAK;;AAE1B;;IAEF,KAAA,GAA4B;KAC1B,MAAM,aAAa,KAAK,UAAU,OAAO,QAAQ,GAAG;KACpD,MAAM,aAAa,KAAK,UAAU,QAAQ,IAAI,IAAI;KAClD,MAAM,wBACJ,iBAAiB,CAAC,EAAE,cAAc;KACpC,MAAM,SAAS,CAAC,aACZ,KAAA,IACA,wBACE,aACA,WAAW,aAAa;KAC9B,MAAM,SAAS,CAAC,aACZ,KAAA,IACA,wBACE,aACA,WAAW,aAAa;KAC9B,MAAM,OAAO,kBAAA,GAEX,MAAM,YAAY,MAAM,MACxB,uBACA,QACA,OACD;AACD,gBAAW;AACX,UAAK,SAAS;AACd,UAAK,QAAQ;AACb,UAAK,aAAa,EAAE;AACpB,UAAK,SAAS,KAAK,KAAK;;;AAG5B,UAAO;;AAIT,MACE,eACA,MAAM,YACN,CAAC,MAAM,UACP,MAAM,MACN,MAAM,GAAG,WAAW,MAAM,GAAG,YAAY,IAAI,GAAG,EAAE,KAAK,IACvD;GACA,MAAM,eAAe,iBACnB,MAAM,YAAY,MAAM,KACzB;AACD,gBAAa,OAAO;AACpB,gBAAa,SAAS;AACtB;AACA,gBAAa,QAAQ;AACrB,QAAK,aAAa,EAAE;AACpB,QAAK,SAAS,KAAK,aAAa;AAChC,UAAO;;EAGT,MAAM,UAAU,MAAM,QAAQ,CAAC,MAAM,aAAa,CAAC,MAAM;AAEzD,MAAI,UAAU,KAAK,SAAS,IAAI,EAAE;GAChC,MAAM,YAAY,iBAChB,MAAM,YAAY,MAAM,KACzB;AACD,aAAU,OAAO;AACjB,aAAU,SAAS;AACnB;AACA,aAAU,QAAQ;AAClB,QAAK,QAAQ;AACb,UAAO;;AAGT,OAAK,QAAQ,eAAe;AAG5B,MAAI,UAAU,CAAC,KAAK,OAAO;AACzB,QAAK,QAAQ;AACb,QAAK,WAAW,MAAM,YAAY,MAAM;;;AAG5C,KAAI,MAAM,SACR,MAAK,MAAM,SAAS,MAAM,SACxB,eACE,sBACA,MACA,OACA,QACA,MACA,OACA,QACD;;AAIP,SAAS,YACP,GAMA,GAMA;AACA,KAAI,EAAE,SAAS,CAAC,EAAE,MAAO,QAAO;AAChC,KAAI,CAAC,EAAE,SAAS,EAAE,MAAO,QAAO;AAChC,KAAI,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ;AACjD,MAAI,EAAE,OAAO,WAAW,EAAE,OAAO,CAAE,QAAO;AAC1C,MAAI,EAAE,OAAO,WAAW,EAAE,OAAO,CAAE,QAAO;;AAE5C,KAAI,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ;AACjD,MAAI,EAAE,OAAO,SAAS,EAAE,OAAO,CAAE,QAAO;AACxC,MAAI,EAAE,OAAO,SAAS,EAAE,OAAO,CAAE,QAAO;;AAE1C,KAAI,EAAE,UAAU,CAAC,EAAE,OAAQ,QAAO;AAClC,KAAI,CAAC,EAAE,UAAU,EAAE,OAAQ,QAAO;AAClC,KAAI,EAAE,UAAU,CAAC,EAAE,OAAQ,QAAO;AAClC,KAAI,CAAC,EAAE,UAAU,EAAE,OAAQ,QAAO;AAClC,KAAI,EAAE,iBAAiB,CAAC,EAAE,cAAe,QAAO;AAChD,KAAI,CAAC,EAAE,iBAAiB,EAAE,cAAe,QAAO;AAGhD,QAAO;;AAGT,SAAS,cAAc,MAA8B;AACnD,KAAI,KAAK,SACP,MAAK,MAAM,SAAS,KAAK,SACvB,eAAc,MAAM;AAGxB,KAAI,KAAK,OACP,MAAK,MAAM,SAAS,KAAK,OAAO,QAAQ,CACtC,eAAc,MAAM;AAGxB,KAAI,KAAK,kBACP,MAAK,MAAM,SAAS,KAAK,kBAAkB,QAAQ,CACjD,eAAc,MAAM;AAGxB,KAAI,KAAK,SAAS,QAAQ;AACxB,OAAK,QAAQ,KAAK,YAAY;AAC9B,OAAK,MAAM,SAAS,KAAK,QACvB,eAAc,MAAM;;AAGxB,KAAI,KAAK,UAAU,QAAQ;AACzB,OAAK,SAAS,KAAK,YAAY;AAC/B,OAAK,MAAM,SAAS,KAAK,SACvB,eAAc,MAAM;;AAGxB,KAAI,KAAK,UAAU,QAAQ;AACzB,OAAK,SAAS,KAAK,YAAY;AAC/B,OAAK,MAAM,SAAS,KAAK,SACvB,eAAc,MAAM;;;AAK1B,SAAS,iBACP,UACsB;AACtB,QAAO;EACL,MAAA;EACA,OAAO;EACP,UAAU;EACV,OAAO;EACP,QAAQ;EACR,mBAAmB;EACnB,SAAS;EACT,UAAU;EACV,UAAU;EACV,OAAO;EACP;EACA,QAAQ;EACR,OAAO;EACR;;;;;;AAOH,SAAS,kBACP,MAIA,UACA,eACA,QACA,QACuB;AACvB,QAAO;EACL;EACA,OAAO;EACP,UAAU;EACV,OAAO;EACP,QAAQ;EACR,mBAAmB;EACnB,SAAS;EACT,UAAU;EACV,UAAU;EACV,OAAO;EACP;EACA,QAAQ;EACR,OAAO;EACP;EACA;EACA;EACD;;AAkGH,SAAgB,kBAGd,WACA,eACA;CACA,MAAM,cAAc,iBAA6B,IAAI;CACrD,MAAM,OAAO,IAAI,YAAY,EAAE;AAC/B,MAAK,MAAM,SAAS,UAClB,eAAc,OAAO,MAAM,OAAO,GAAG,aAAa,EAAE;AAEtD,eAAc,YAAY;AAC1B,eAAc,YAAY;AAC1B,eAAc,YAAY,kBAAA,eAGxB,IAAK;;;;;AAMT,SAAgB,cAEd,MAEA,eACA;AACA,UAAS;CACT,MAAM,SAAS,cAAc,UAAW,IAAI,KAAK;AACjD,KAAI,OAAQ,QAAO;CACnB,MAAM,SAAS,UAAU,MAAM,cAAc,UAAW;AACxD,eAAc,UAAW,IAAI,MAAM,OAAO;AAC1C,QAAO;;;;;AAMT,SAAgB,gBACd,MACA,eACA,OACA,MACA,eACA;AACA,UAAS;AACT,UAAS;CACT,MAAM,MAAM,gBAAgB,SAAS,SAAS;CAC9C,IAAI,OAAO,cAAc,YAAY,IAAI,IAAI;AAC7C,KAAI,CAAC,MAAM;AAGT,SAAO,iBAAmC,IAAI;AAE9C,gBAAc,eADD,IAAI,YAAY,EAAE,EACI,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE;AACxD,gBAAc,YAAY,IAAI,KAAK,KAAK;;AAE1C,QAAO,UAAU,MAAM,MAAM,MAAM;;AASrC,SAAgB,eAId,MAEA,eAEA,QAAQ,OACc;CACtB,MAAM,MAAM,QAAQ,OAAO,WAAW;CACtC,MAAM,SAAS,cAAc,WAAW,IAAI,IAAI;AAChD,KAAI,WAAW,KAAA,EAAW,QAAO;AACjC,UAAS;CACT,IAAI;AAEJ,KAAI;AACF,WAAS,UACP,MACA,cAAc,aACd,MACD;UACM,KAAK;AACZ,MAAI,eAAe,SACjB,UAAS;MAET,OAAM;;AAIV,KAAI,OAAQ,QAAO,SAAS,iBAAiB,OAAO,MAAM;AAC1D,eAAc,WAAW,IAAI,KAAK,OAAO;AACzC,QAAO;;;AAIT,SAAgB,cAAc,MAAc;AAC1C,QAAO,SAAS,MAAM,OAAO,KAAK,QAAQ,WAAW,GAAG;;;;;;AAkB1D,SAAgB,iBAId,WAEA,gBAAyB,OAEzB,WACoC;CACpC,MAAM,cAAc,iBAA6B,UAAU,SAAS;CACpE,MAAM,OAAO,IAAI,YAAY,EAAE;CAC/B,MAAM,aAAa,EAAE;CACrB,MAAM,eAAe,EAAE;CACvB,IAAI,QAAQ;AACZ,eAAc,eAAe,MAAM,WAAW,GAAG,aAAa,IAAI,UAAU;AAC1E,cAAY,OAAO,MAAM;AAEzB,MAAI,MAAM,MAAM,YAAY;AAC1B,OAAA,QAAA,IAAA,aAA6B,aAC3B,OAAM,IAAI,MACR,qDAAqD,OAAO,MAAM,GAAG,GACtE;AAGH,qBAAA,WAAW;;AAGb,aAAW,MAAM,MAAM;AAEvB,MAAI,UAAU,KAAK,MAAM,MAAM;GAC7B,MAAM,kBAAkB,cAAc,MAAM,SAAS;AACrD,OAAI,CAAC,aAAa,oBAAoB,MAAM,SAAS,SAAS,IAAI,CAChE,cAAa,mBAAmB;;AAIpC;GACA;AACF,eAAc,YAAY;AAQ1B,QAAO;EACL,eARyD;GACzD;GACA,aAAa,kBAAA,eAA4C,IAAK;GAC9D,YAAY,kBAAA,eAAsD,IAAK;GACvE,WAAW;GACX,WAAW;GACZ;EAGC;EACA;EACD;;AAGH,SAAS,UACP,MACA,aACA,QAAQ,OAQD;CACP,MAAM,QAAQ,KAAK,MAAM,IAAI;CAC7B,MAAM,OAAO,aAAa,MAAM,OAAO,aAAa,MAAM;AAC1D,KAAI,CAAC,KAAM,QAAO;CAClB,MAAM,CAAC,aAAa,cAAc,MAAM,OAAO,KAAK;AACpD,QAAO;EACL,OAAO,KAAK,KAAK;EACjB;EACD;;;;;;;;;AAiBH,SAAS,cACP,MACA,OACA,MAMkE;CAClE,MAAM,OAAO,YAAY,KAAK,KAAK;CACnC,IAAI,YAAkC;CACtC,MAAM,YAAoC,OAAO,OAAO,KAAK;;CAE7D,IAAI,YAAY,KAAK,SAAS,QAAQ;;CAEtC,IAAI,YAAY,KAAK,SAAS,QAAQ;;CAEtC,IAAI,YAAY,KAAK,SAAS,QAAQ;;CAEtC,IAAI,eAAe,KAAK,SAAS,WAAW;AAC5C,QAEE,YAAY,KAAK,QACjB,aAAa,aAAa,aAAa,gBACvC;EACA,MAAM,OAAO,KAAK;AAElB,MAAI,KAAK,SAAS,mBAAoB;AAEtC,MAAI,KAAK,SAAS,uBAAuB;AACvC;AACA;AACA;AACA;;EAEF,MAAM,OAAO,MAAM;EACnB,MAAM,mBAAmB;AACzB,MAAI,KAAM,cAAa,KAAK;AAC5B,MAAI,KAAK,SAAA,GAA6B;AACpC,iBAAc,KAAK,KAAK,SAAS,MAAM,IAAI;GAC3C,MAAM,WAAW,UAAU;GAC3B,MAAM,YAAY,KAAK,QAAQ,UAAU;AAIzC,OAFsB,SAAS,WAAW,UAAU,KAAK,KAEtC;IACjB,MAAM,YAAY,KAAK,QAAQ,UAAU;IACzC,MAAM,OAAO,SAAS,UACpB,YAAY,GACZ,SAAS,SAAS,YAAY,EAC/B;IACD,MAAM,QAAQ,KAAM,UAAU,WAAW,KAAM,SAAS,UAAU;AAClE,cAAU,QAAQ,mBAAmB,MAAM;UACtC;IACL,MAAM,OAAO,SAAS,UAAU,EAAE;AAClC,cAAU,QAAQ,mBAAmB,KAAM;;aAEpC,KAAK,SAAA,GAAsC;AACpD,OAAI,KAAK,UAAW,KAAK,WAAY;AACnC;AACA,gBAAY,mBAAmB;AAC/B;;AAEF,iBAAc,KAAK,KAAK,SAAS,MAAM,IAAI;GAC3C,MAAM,WAAW,UAAU;GAC3B,MAAM,YAAY,KAAK,QAAQ,UAAU;GACzC,MAAM,YAAY,KAAK,QAAQ,UAAU;GACzC,MAAM,OAAO,SAAS,UACpB,YAAY,GACZ,SAAS,SAAS,YAAY,EAC/B;GACD,MAAM,QACJ,KAAK,UAAU,KAAK,SAChB,KAAM,UAAU,WAAW,KAAM,SAAS,UAAU,GACpD;AACN,OAAI,MAAO,WAAU,QAAQ,mBAAmB,MAAM;aAC7C,KAAK,SAAA,GAAgC;GAC9C,MAAM,IAAI;GACV,MAAM,QAAQ,KAAK,UACjB,oBAAoB,EAAE,QAAQ,UAAU,IACxC,KAAK,UAAU,EAAE,QAAQ,UAAU,GACpC;GACD,MAAM,QAAQ,mBAAmB,MAAM;AAEvC,aAAU,OAAO;AACjB,aAAU,SAAS;AACnB;;;AAGJ,KAAI,KAAK,UAAW,QAAO,OAAO,WAAW,KAAK,UAAU;AAC5D,QAAO,CACL,WACA;EACE,MAAM;EACN,MAAM;EACN,MAAM;EACN,SAAS;EACV,CACF;;AAGH,SAAgB,iBAAsC,OAAU;CAC9D,MAAM,OAAO,CAAC,MAAM;AACpB,QAAO,MAAM,aAAa;AACxB,UAAQ,MAAM;AACd,OAAK,KAAK,MAAM;;AAElB,MAAK,SAAS;AACd,QAAO;;AAGT,SAAS,YAAiC,MAAyB;CACjE,MAAM,OAAiC,MAAM,KAAK,QAAQ,EAAE;AAC5D,IAAG;AACD,OAAK,KAAK,SAAS;AACnB,SAAO,KAAK;UACL;AACT,QAAO;;AA0BT,SAAS,aACP,MACA,OACA,aACA,OACA;AAGA,KAAI,SAAS,OAAO,YAAY,MAC9B,QAAO;EAAE,MAAM,YAAY;EAAO,SAAS;EAAG;CAKhD,MAAM,gBAAgB,CAAC,cAAA,KAAK,MAAM;CAClC,MAAM,cAAc,iBAAiB,SAAS;CAC9C,MAAM,cAAc,MAAM,UAAU,gBAAgB,IAAI;CAWxD,MAAM,QAAsB,CAC1B;EACE,MAAM;EACN,OAAO;EACP,SAAS;EACT,OAAO;EACP,SAAS;EACT,UAAU;EACV,WAAW;EACZ,CACF;CAED,IAAI,YAA0B;CAC9B,IAAI,YAA0B;AAE9B,QAAO,MAAM,QAAQ;EACnB,MAAM,QAAQ,MAAM,KAAK;EACzB,MAAM,EAAE,MAAM,OAAO,SAAS,OAAO,SAAS,UAAU,cAAc;EACtE,IAAI,EAAE,SAAS,cAAc;AAM7B,MACE,KAAK,SAAA,KACL,KAAK,SACL,CAAC,oBAAoB,WAAW,MAAM,CAEtC;AAGF,MAAI,KAAK,OAAO;AAEd,OAAI,CADW,oBAAoB,MAAM,OAAO,MAAM,CACzC;AACb,eAAY,MAAM;AAClB,aAAU,MAAM;;AAIlB,MACE,SACA,KAAK,SACL,KAAK,SAAS,sBACd,oBAAoB,WAAW,MAAM,CAErC,aAAY;EAGd,MAAM,eAAe,UAAU;AAC/B,MAAI,cAAc;AAChB,OACE,KAAK,UACJ,CAAC,eACA,KAAK,SAAS,sBACd,KAAK,SAAA,MACP,oBAAoB,WAAW,MAAM,CAErC,aAAY;AAGd,OAAI,CAAC,KAAK,YAAY,CAAC,KAAK,YAAY,CAAC,KAAK,SAAS,CAAC,KAAK,SAC3D;;EAGJ,MAAM,OAAO,eAAe,KAAA,IAAY,MAAM;EAC9C,IAAI;AAGJ,MAAI,gBAAgB,KAAK,OAAO;GAC9B,MAAM,aAAa;IACjB,MAAM,KAAK;IACX;IACA;IACA,OAAO,QAAQ;IACf;IACA;IACA;IACA;IACA;IACD;GACD,IAAI,aAAa;AACjB,OAAI,KAAK,MAAM;QAET,CADW,oBAAoB,MAAM,OAAO,WAAW,CAC9C,cAAa;;AAE5B,OAAI,YAAY;AAGd,QACE,CAAC,YACD,CAAC,aACD,CAAC,WACD,qBAAqB,SAAS,YAAY,CAE1C,QAAO;AAET,QAAI,oBAAoB,WAAW,WAAW,CAE5C,aAAY;;;AAMlB,MAAI,KAAK,SACP,MAAK,IAAI,IAAI,KAAK,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;GAClD,MAAM,UAAU,KAAK,SAAS;GAC9B,MAAM,EAAE,QAAQ,WAAW;AAC3B,OAAI,QAAQ;AACV,QAAI,aAAc;AAIlB,QAAI,EAHa,QAAQ,gBACrB,OACC,cAAc,KAAM,aAAa,EACvB,WAAW,OAAO,CAAE;;AAErC,OAAI,QAAQ;AACV,QAAI,aAAc;IAClB,MAAM,MAAM,MAAM,MAAM,MAAM,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,OAAO,OAAO;AAE9D,SADiB,QAAQ,gBAAgB,MAAM,IAAI,aAAa,MAC/C,OAAQ;;AAG3B,SAAM,KAAK;IACT,MAAM;IACN,OAAO;IACP;IACA,OAAO,QAAQ;IACf;IACA;IACA;IACA;IACA;IACD,CAAC;;AAKN,MAAI,KAAK,UAAU;GACjB,MAAM,cAAc,UAAW,KAAK;GACpC,MAAM,YAAY,QAAQ;AAC1B,QAAK,IAAI,IAAI,KAAK,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;IAClD,MAAM,UAAU,KAAK,SAAS;AAE9B,UAAM,KAAK;KACT,MAAM;KACN;KACA,SAAS;KACT,OAAO;KACP;KACA;KACA;KACA;KACA;KACD,CAAC;;AAEJ,OAAI,CAAC,aACH,MAAK,IAAI,IAAI,KAAK,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;IAClD,MAAM,UAAU,KAAK,SAAS;IAC9B,MAAM,EAAE,QAAQ,WAAW;AAC3B,QAAI,UAAU,QAAQ;KACpB,MAAM,WAAW,QAAQ,gBACrB,OACC,cAAc,KAAM,aAAa;AACtC,SAAI,UAAU,CAAC,SAAS,WAAW,OAAO,CAAE;AAC5C,SAAI,UAAU,CAAC,SAAS,SAAS,OAAO,CAAE;;AAE5C,UAAM,KAAK;KACT,MAAM;KACN,OAAO,QAAQ;KACf;KACA,OAAO;KACP;KACA;KACA,WAAW,YAAY,aAAa,aAAa,MAAM;KACvD;KACA;KACD,CAAC;;;AAMR,MAAI,CAAC,gBAAgB,KAAK,WAAW,KACnC,MAAK,IAAI,IAAI,KAAK,QAAQ,SAAS,GAAG,KAAK,GAAG,KAAK;GACjD,MAAM,UAAU,KAAK,QAAQ;GAC7B,MAAM,EAAE,QAAQ,WAAW;AAC3B,OAAI,UAAU,QAAQ;IACpB,MAAM,WAAW,QAAQ,gBACrB,OACC,cAAc,KAAK,aAAa;AACrC,QAAI,UAAU,CAAC,SAAS,WAAW,OAAO,CAAE;AAC5C,QAAI,UAAU,CAAC,SAAS,SAAS,OAAO,CAAE;;AAE5C,SAAM,KAAK;IACT,MAAM;IACN,OAAO,QAAQ;IACf;IACA,OAAO,QAAQ;IACf;IACA,UAAU,WAAW,aAAa,aAAa,MAAM;IACrD;IACA;IACA;IACD,CAAC;;AAKN,MAAI,CAAC,gBAAgB,KAAK,mBAAmB;GAC3C,MAAM,QAAQ,KAAK,kBAAkB,IAClC,cAAc,KAAM,aAAa,CACnC;AACD,OAAI,MACF,OAAM,KAAK;IACT,MAAM;IACN,OAAO,QAAQ;IACf;IACA,OAAO,QAAQ;IACf,SAAS,UAAU,aAAa,aAAa,MAAM;IACnD;IACA;IACA;IACA;IACD,CAAC;;AAKN,MAAI,CAAC,gBAAgB,KAAK,QAAQ;GAChC,MAAM,QAAQ,KAAK,OAAO,IAAI,KAAM;AACpC,OAAI,MACF,OAAM,KAAK;IACT,MAAM;IACN,OAAO,QAAQ;IACf;IACA,OAAO,QAAQ;IACf,SAAS,UAAU,aAAa,aAAa,MAAM;IACnD;IACA;IACA;IACA;IACD,CAAC;;AAKN,MAAI,KAAK,UAAU;GACjB,MAAM,YAAY,QAAQ;AAC1B,QAAK,IAAI,IAAI,KAAK,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;IAClD,MAAM,UAAU,KAAK,SAAS;AAC9B,UAAM,KAAK;KACT,MAAM;KACN;KACA;KACA,OAAO;KACP;KACA;KACA;KACA;KACA;KACD,CAAC;;;;AAKR,KAAI,UAAW,QAAO;AAEtB,KAAI,SAAS,WAAW;EACtB,IAAI,aAAa,UAAU;AAC3B,OAAK,IAAI,IAAI,GAAG,IAAI,UAAU,OAAO,IACnC,eAAc,MAAM,GAAI;EAE1B,MAAM,QAAQ,eAAe,KAAK,SAAS,MAAM,KAAK,MAAM,WAAW;AACvE,YAAU,cAAc,OAAO,OAAO,KAAK;AAC3C,YAAU,UAAW,QAAQ,mBAAmB,MAAM;AACtD,SAAO;;AAGT,QAAO;;AAGT,SAAS,aAAa,aAAqB,OAAuB;AAMhE,QAAO,MAAM,cAAc,QAAQ;;AAGrC,SAAS,qBAAqB,SAAiB,aAA8B;AAC3E,QAAO,YAAY,MAAM,cAAc,KAAK;;AAG9C,SAAS,oBACP,MACA,OACA,OACA;CACA,IAAI;CACJ,IAAI;AAEJ,KAAI;AACD,GAAC,WAAW,SAAS,cAAc,MAAM,OAAO,MAAM;SACjD;AACN,SAAO;;AAGT,OAAM,YAAY;AAClB,OAAM,UAAU;AAEhB,KAAI,CAAC,MAAM,KAAK,MAAO,QAAO;AAE9B,KAAI;AACF,MAAI,MAAM,KAAK,MAAM,UAAU,KAAK,MAAO,QAAO;SAC5C;AAKR,QAAO;;AAGT,SAAS,oBAEP,MAEA,MACS;AACT,KAAI,CAAC,KAAM,QAAO;AAClB,QACE,KAAK,UAAU,KAAK,WACnB,KAAK,YAAY,KAAK,YACpB,KAAK,WAAW,KAAK,YACnB,KAAK,aAAa,KAAK,aACrB,KAAK,YAAY,KAAK,aACpB,KAAK,cAAc,KAAK,eACrB,KAAK,KAAK,SAAS,uBAClB,KAAK,KAAK,SAAS,uBAClB,KAAK,KAAK,SAAS,wBAClB,KAAK,KAAK,SAAS,uBACpB,KAAK,QAAQ,KAAK"}
|
|
@@ -82,11 +82,7 @@ type SegmentNode<T extends RouteLike> = {
|
|
|
82
82
|
parent: AnySegmentNode<T> | null;
|
|
83
83
|
depth: number;
|
|
84
84
|
/** route.options.params.parse function, set on the last node of the route */
|
|
85
|
-
parse: null | ((params: Record<string, string>) =>
|
|
86
|
-
/** options.skipRouteOnParseError.params ?? false */
|
|
87
|
-
skipOnParamError: boolean;
|
|
88
|
-
/** options.skipRouteOnParseError.priority ?? 0 */
|
|
89
|
-
parsingPriority: number;
|
|
85
|
+
parse: null | ((params: Record<string, string>) => unknown);
|
|
90
86
|
};
|
|
91
87
|
type RouteLike = {
|
|
92
88
|
id?: string;
|
|
@@ -95,13 +91,10 @@ type RouteLike = {
|
|
|
95
91
|
parentRoute?: RouteLike;
|
|
96
92
|
isRoot?: boolean;
|
|
97
93
|
options?: {
|
|
98
|
-
skipRouteOnParseError?: {
|
|
99
|
-
params?: boolean;
|
|
100
|
-
priority?: number;
|
|
101
|
-
};
|
|
102
94
|
caseSensitive?: boolean;
|
|
95
|
+
parseParams?: (params: Record<string, string>) => unknown;
|
|
103
96
|
params?: {
|
|
104
|
-
parse?: (params: Record<string, string>) =>
|
|
97
|
+
parse?: (params: Record<string, string>) => unknown;
|
|
105
98
|
};
|
|
106
99
|
};
|
|
107
100
|
} & ({
|
|
@@ -148,11 +141,6 @@ processedTree: ProcessedTree<any, T, any>): {
|
|
|
148
141
|
* This will be the exhaustive list of all params defined in the route's path.
|
|
149
142
|
*/
|
|
150
143
|
rawParams: Record<string, string>;
|
|
151
|
-
/**
|
|
152
|
-
* The accumlulated parsed params of each route in the branch that had `skipRouteOnParseError` enabled.
|
|
153
|
-
* Will not contain all params defined in the route's path. Those w/ a `params.parse` but no `skipRouteOnParseError` will need to be parsed separately.
|
|
154
|
-
*/
|
|
155
|
-
parsedParams?: Record<string, unknown>;
|
|
156
144
|
} | null;
|
|
157
145
|
/**
|
|
158
146
|
* @deprecated keep until v2 so that `router.matchRoute` can keep not caring about the actual route tree
|
|
@@ -168,18 +156,12 @@ export declare function findSingleMatch(from: string, caseSensitive: boolean, fu
|
|
|
168
156
|
* This will be the exhaustive list of all params defined in the route's path.
|
|
169
157
|
*/
|
|
170
158
|
rawParams: Record<string, string>;
|
|
171
|
-
/**
|
|
172
|
-
* The accumlulated parsed params of each route in the branch that had `skipRouteOnParseError` enabled.
|
|
173
|
-
* Will not contain all params defined in the route's path. Those w/ a `params.parse` but no `skipRouteOnParseError` will need to be parsed separately.
|
|
174
|
-
*/
|
|
175
|
-
parsedParams?: Record<string, unknown>;
|
|
176
159
|
} | null;
|
|
177
160
|
type RouteMatch<T extends Extract<RouteLike, {
|
|
178
161
|
fullPath: string;
|
|
179
162
|
}>> = {
|
|
180
163
|
route: T;
|
|
181
164
|
rawParams: Record<string, string>;
|
|
182
|
-
parsedParams?: Record<string, unknown>;
|
|
183
165
|
branch: ReadonlyArray<T>;
|
|
184
166
|
};
|
|
185
167
|
export declare function findRouteMatch<T extends Extract<RouteLike, {
|
|
@@ -227,10 +209,6 @@ declare function findMatch<T extends RouteLike>(path: string, segmentTree: AnySe
|
|
|
227
209
|
* This will be the exhaustive list of all params defined in the route's path.
|
|
228
210
|
*/
|
|
229
211
|
rawParams: Record<string, string>;
|
|
230
|
-
/**
|
|
231
|
-
* The accumlulated parsed params of each route in the branch that had `skipRouteOnParseError` enabled.
|
|
232
|
-
* Will not contain all params defined in the route's path. Those w/ a `params.parse` but no `skipRouteOnParseError` will need to be parsed separately.
|
|
233
|
-
*/
|
|
234
|
-
parsedParams?: Record<string, unknown>;
|
|
235
212
|
} | null;
|
|
213
|
+
export declare function buildRouteBranch<T extends RouteLike>(route: T): T[];
|
|
236
214
|
export {};
|
package/dist/cjs/path.cjs
CHANGED
|
@@ -71,28 +71,7 @@ function resolvePath({ base, to, trailingSlash = "never", cache }) {
|
|
|
71
71
|
if (trailingSlash === "never") baseSegments.pop();
|
|
72
72
|
} else if (trailingSlash === "always") baseSegments.push("");
|
|
73
73
|
}
|
|
74
|
-
|
|
75
|
-
let joined = "";
|
|
76
|
-
for (let i = 0; i < baseSegments.length; i++) {
|
|
77
|
-
if (i > 0) joined += "/";
|
|
78
|
-
const part = baseSegments[i];
|
|
79
|
-
if (!part) continue;
|
|
80
|
-
segment = require_new_process_route_tree.parseSegment(part, 0, segment);
|
|
81
|
-
const kind = segment[0];
|
|
82
|
-
if (kind === 0) {
|
|
83
|
-
joined += part;
|
|
84
|
-
continue;
|
|
85
|
-
}
|
|
86
|
-
const end = segment[5];
|
|
87
|
-
const prefix = part.substring(0, segment[1]);
|
|
88
|
-
const suffix = part.substring(segment[4], end);
|
|
89
|
-
const value = part.substring(segment[2], segment[3]);
|
|
90
|
-
if (kind === 1) joined += prefix || suffix ? `${prefix}{$${value}}${suffix}` : `$${value}`;
|
|
91
|
-
else if (kind === 2) joined += prefix || suffix ? `${prefix}{$}${suffix}` : "$";
|
|
92
|
-
else joined += `${prefix}{-$${value}}${suffix}`;
|
|
93
|
-
}
|
|
94
|
-
joined = cleanPath(joined);
|
|
95
|
-
const result = joined || "/";
|
|
74
|
+
const result = cleanPath(baseSegments.join("/")) || "/";
|
|
96
75
|
if (key && cache) cache.set(key, result);
|
|
97
76
|
return result;
|
|
98
77
|
}
|