@tanstack/router-core 1.119.0 → 1.120.4-alpha.1
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/fileRoute.d.cts +6 -2
- package/dist/cjs/index.cjs +4 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +5 -5
- package/dist/cjs/link.cjs.map +1 -1
- package/dist/cjs/link.d.cts +7 -2
- package/dist/cjs/path.cjs +130 -16
- package/dist/cjs/path.cjs.map +1 -1
- package/dist/cjs/path.d.cts +17 -0
- package/dist/cjs/redirect.cjs +19 -14
- package/dist/cjs/redirect.cjs.map +1 -1
- package/dist/cjs/redirect.d.cts +10 -8
- package/dist/cjs/route.cjs +12 -1
- package/dist/cjs/route.cjs.map +1 -1
- package/dist/cjs/route.d.cts +10 -11
- package/dist/cjs/router.cjs +227 -155
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +50 -7
- package/dist/cjs/typePrimitives.d.cts +2 -2
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +3 -1
- package/dist/esm/fileRoute.d.ts +6 -2
- package/dist/esm/index.d.ts +5 -5
- package/dist/esm/index.js +7 -3
- package/dist/esm/link.d.ts +7 -2
- package/dist/esm/link.js.map +1 -1
- package/dist/esm/path.d.ts +17 -0
- package/dist/esm/path.js +130 -16
- package/dist/esm/path.js.map +1 -1
- package/dist/esm/redirect.d.ts +10 -8
- package/dist/esm/redirect.js +20 -15
- package/dist/esm/redirect.js.map +1 -1
- package/dist/esm/route.d.ts +10 -11
- package/dist/esm/route.js +12 -1
- package/dist/esm/route.js.map +1 -1
- package/dist/esm/router.d.ts +50 -7
- package/dist/esm/router.js +230 -158
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/typePrimitives.d.ts +2 -2
- package/dist/esm/utils.d.ts +3 -1
- package/dist/esm/utils.js.map +1 -1
- package/package.json +2 -2
- package/src/fileRoute.ts +90 -1
- package/src/index.ts +13 -3
- package/src/link.ts +10 -7
- package/src/path.ts +181 -16
- package/src/redirect.ts +42 -28
- package/src/route.ts +96 -23
- package/src/router.ts +332 -215
- package/src/typePrimitives.ts +2 -2
- package/src/utils.ts +20 -6
package/dist/esm/path.js
CHANGED
|
@@ -65,9 +65,35 @@ function resolvePath({
|
|
|
65
65
|
baseSegments.push({ type: "pathname", value: "/" });
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
|
-
const
|
|
68
|
+
const segmentValues = baseSegments.map((segment) => {
|
|
69
|
+
if (segment.type === "param") {
|
|
70
|
+
const param = segment.value.substring(1);
|
|
71
|
+
if (segment.prefixSegment && segment.suffixSegment) {
|
|
72
|
+
return `${segment.prefixSegment}{$${param}}${segment.suffixSegment}`;
|
|
73
|
+
} else if (segment.prefixSegment) {
|
|
74
|
+
return `${segment.prefixSegment}{$${param}}`;
|
|
75
|
+
} else if (segment.suffixSegment) {
|
|
76
|
+
return `{$${param}}${segment.suffixSegment}`;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (segment.type === "wildcard") {
|
|
80
|
+
if (segment.prefixSegment && segment.suffixSegment) {
|
|
81
|
+
return `${segment.prefixSegment}{$}${segment.suffixSegment}`;
|
|
82
|
+
} else if (segment.prefixSegment) {
|
|
83
|
+
return `${segment.prefixSegment}{$}`;
|
|
84
|
+
} else if (segment.suffixSegment) {
|
|
85
|
+
return `{$}${segment.suffixSegment}`;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return segment.value;
|
|
89
|
+
});
|
|
90
|
+
const joined = joinPaths([basepath, ...segmentValues]);
|
|
69
91
|
return cleanPath(joined);
|
|
70
92
|
}
|
|
93
|
+
const PARAM_RE = /^\$.{1,}$/;
|
|
94
|
+
const PARAM_W_CURLY_BRACES_RE = /^(.*?)\{(\$[a-zA-Z_$][a-zA-Z0-9_$]*)\}(.*)$/;
|
|
95
|
+
const WILDCARD_RE = /^\$$/;
|
|
96
|
+
const WILDCARD_W_CURLY_BRACES_RE = /^(.*?)\{\$\}(.*)$/;
|
|
71
97
|
function parsePathname(pathname) {
|
|
72
98
|
if (!pathname) {
|
|
73
99
|
return [];
|
|
@@ -87,16 +113,44 @@ function parsePathname(pathname) {
|
|
|
87
113
|
const split = pathname.split("/").filter(Boolean);
|
|
88
114
|
segments.push(
|
|
89
115
|
...split.map((part) => {
|
|
90
|
-
|
|
116
|
+
const wildcardBracesMatch = part.match(WILDCARD_W_CURLY_BRACES_RE);
|
|
117
|
+
if (wildcardBracesMatch) {
|
|
118
|
+
const prefix = wildcardBracesMatch[1];
|
|
119
|
+
const suffix = wildcardBracesMatch[2];
|
|
91
120
|
return {
|
|
92
121
|
type: "wildcard",
|
|
93
|
-
value:
|
|
122
|
+
value: "$",
|
|
123
|
+
prefixSegment: prefix || void 0,
|
|
124
|
+
suffixSegment: suffix || void 0
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
const paramBracesMatch = part.match(PARAM_W_CURLY_BRACES_RE);
|
|
128
|
+
if (paramBracesMatch) {
|
|
129
|
+
const prefix = paramBracesMatch[1];
|
|
130
|
+
const paramName = paramBracesMatch[2];
|
|
131
|
+
const suffix = paramBracesMatch[3];
|
|
132
|
+
return {
|
|
133
|
+
type: "param",
|
|
134
|
+
value: "" + paramName,
|
|
135
|
+
prefixSegment: prefix || void 0,
|
|
136
|
+
suffixSegment: suffix || void 0
|
|
94
137
|
};
|
|
95
138
|
}
|
|
96
|
-
if (
|
|
139
|
+
if (PARAM_RE.test(part)) {
|
|
140
|
+
const paramName = part.substring(1);
|
|
97
141
|
return {
|
|
98
142
|
type: "param",
|
|
99
|
-
value:
|
|
143
|
+
value: "$" + paramName,
|
|
144
|
+
prefixSegment: void 0,
|
|
145
|
+
suffixSegment: void 0
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
if (WILDCARD_RE.test(part)) {
|
|
149
|
+
return {
|
|
150
|
+
type: "wildcard",
|
|
151
|
+
value: "$",
|
|
152
|
+
prefixSegment: void 0,
|
|
153
|
+
suffixSegment: void 0
|
|
100
154
|
};
|
|
101
155
|
}
|
|
102
156
|
return {
|
|
@@ -137,9 +191,13 @@ function interpolatePath({
|
|
|
137
191
|
interpolatedPathSegments.map((segment) => {
|
|
138
192
|
if (segment.type === "wildcard") {
|
|
139
193
|
usedParams._splat = params._splat;
|
|
194
|
+
const segmentPrefix = segment.prefixSegment || "";
|
|
195
|
+
const segmentSuffix = segment.suffixSegment || "";
|
|
140
196
|
const value = encodeParam("_splat");
|
|
141
|
-
if (leaveWildcards)
|
|
142
|
-
|
|
197
|
+
if (leaveWildcards) {
|
|
198
|
+
return `${segmentPrefix}${segment.value}${value ?? ""}${segmentSuffix}`;
|
|
199
|
+
}
|
|
200
|
+
return `${segmentPrefix}${value}${segmentSuffix}`;
|
|
143
201
|
}
|
|
144
202
|
if (segment.type === "param") {
|
|
145
203
|
const key = segment.value.substring(1);
|
|
@@ -147,11 +205,13 @@ function interpolatePath({
|
|
|
147
205
|
isMissingParams = true;
|
|
148
206
|
}
|
|
149
207
|
usedParams[key] = params[key];
|
|
208
|
+
const segmentPrefix = segment.prefixSegment || "";
|
|
209
|
+
const segmentSuffix = segment.suffixSegment || "";
|
|
150
210
|
if (leaveParams) {
|
|
151
211
|
const value = encodeParam(segment.value);
|
|
152
|
-
return `${segment.value}${value ?? ""}`;
|
|
212
|
+
return `${segmentPrefix}${segment.value}${value ?? ""}${segmentSuffix}`;
|
|
153
213
|
}
|
|
154
|
-
return encodeParam(key) ?? "undefined"
|
|
214
|
+
return `${segmentPrefix}${encodeParam(key) ?? "undefined"}${segmentSuffix}`;
|
|
155
215
|
}
|
|
156
216
|
return segment.value;
|
|
157
217
|
})
|
|
@@ -229,6 +289,7 @@ function matchByPath(basepath, from, matchLocation) {
|
|
|
229
289
|
}
|
|
230
290
|
const params = {};
|
|
231
291
|
const isMatch = (() => {
|
|
292
|
+
var _a;
|
|
232
293
|
for (let i = 0; i < Math.max(baseSegments.length, routeSegments.length); i++) {
|
|
233
294
|
const baseSegment = baseSegments[i];
|
|
234
295
|
const routeSegment = routeSegments[i];
|
|
@@ -236,9 +297,41 @@ function matchByPath(basepath, from, matchLocation) {
|
|
|
236
297
|
const isLastRouteSegment = i >= routeSegments.length - 1;
|
|
237
298
|
if (routeSegment) {
|
|
238
299
|
if (routeSegment.type === "wildcard") {
|
|
239
|
-
const
|
|
240
|
-
|
|
241
|
-
)
|
|
300
|
+
const remainingBaseSegments = baseSegments.slice(i);
|
|
301
|
+
let _splat;
|
|
302
|
+
if (routeSegment.prefixSegment || routeSegment.suffixSegment) {
|
|
303
|
+
if (!baseSegment) return false;
|
|
304
|
+
const prefix = routeSegment.prefixSegment || "";
|
|
305
|
+
const suffix = routeSegment.suffixSegment || "";
|
|
306
|
+
const baseValue = baseSegment.value;
|
|
307
|
+
if ("prefixSegment" in routeSegment) {
|
|
308
|
+
if (!baseValue.startsWith(prefix)) {
|
|
309
|
+
return false;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
if ("suffixSegment" in routeSegment) {
|
|
313
|
+
if (!((_a = baseSegments[baseSegments.length - 1]) == null ? void 0 : _a.value.endsWith(suffix))) {
|
|
314
|
+
return false;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
let rejoinedSplat = decodeURI(
|
|
318
|
+
joinPaths(remainingBaseSegments.map((d) => d.value))
|
|
319
|
+
);
|
|
320
|
+
if (prefix && rejoinedSplat.startsWith(prefix)) {
|
|
321
|
+
rejoinedSplat = rejoinedSplat.slice(prefix.length);
|
|
322
|
+
}
|
|
323
|
+
if (suffix && rejoinedSplat.endsWith(suffix)) {
|
|
324
|
+
rejoinedSplat = rejoinedSplat.slice(
|
|
325
|
+
0,
|
|
326
|
+
rejoinedSplat.length - suffix.length
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
_splat = rejoinedSplat;
|
|
330
|
+
} else {
|
|
331
|
+
_splat = decodeURI(
|
|
332
|
+
joinPaths(remainingBaseSegments.map((d) => d.value))
|
|
333
|
+
);
|
|
334
|
+
}
|
|
242
335
|
params["*"] = _splat;
|
|
243
336
|
params["_splat"] = _splat;
|
|
244
337
|
return true;
|
|
@@ -264,11 +357,32 @@ function matchByPath(basepath, from, matchLocation) {
|
|
|
264
357
|
if (baseSegment.value === "/") {
|
|
265
358
|
return false;
|
|
266
359
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
360
|
+
let _paramValue;
|
|
361
|
+
if (routeSegment.prefixSegment || routeSegment.suffixSegment) {
|
|
362
|
+
const prefix = routeSegment.prefixSegment || "";
|
|
363
|
+
const suffix = routeSegment.suffixSegment || "";
|
|
364
|
+
const baseValue = baseSegment.value;
|
|
365
|
+
if (prefix && !baseValue.startsWith(prefix)) {
|
|
366
|
+
return false;
|
|
367
|
+
}
|
|
368
|
+
if (suffix && !baseValue.endsWith(suffix)) {
|
|
369
|
+
return false;
|
|
370
|
+
}
|
|
371
|
+
let paramValue = baseValue;
|
|
372
|
+
if (prefix && paramValue.startsWith(prefix)) {
|
|
373
|
+
paramValue = paramValue.slice(prefix.length);
|
|
374
|
+
}
|
|
375
|
+
if (suffix && paramValue.endsWith(suffix)) {
|
|
376
|
+
paramValue = paramValue.slice(
|
|
377
|
+
0,
|
|
378
|
+
paramValue.length - suffix.length
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
_paramValue = decodeURIComponent(paramValue);
|
|
382
|
+
} else {
|
|
383
|
+
_paramValue = decodeURIComponent(baseSegment.value);
|
|
271
384
|
}
|
|
385
|
+
params[routeSegment.value.substring(1)] = _paramValue;
|
|
272
386
|
}
|
|
273
387
|
}
|
|
274
388
|
if (!isLastBaseSegment && isLastRouteSegment) {
|
package/dist/esm/path.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"path.js","sources":["../../src/path.ts"],"sourcesContent":["import { last } from './utils'\nimport type { MatchLocation } from './RouterProvider'\nimport type { AnyPathParams } from './route'\n\nexport interface Segment {\n type: 'pathname' | 'param' | 'wildcard'\n value: string\n}\n\nexport function joinPaths(paths: Array<string | undefined>) {\n return cleanPath(\n paths\n .filter((val) => {\n return val !== undefined\n })\n .join('/'),\n )\n}\n\nexport function cleanPath(path: string) {\n // remove double slashes\n return path.replace(/\\/{2,}/g, '/')\n}\n\nexport function trimPathLeft(path: string) {\n return path === '/' ? path : path.replace(/^\\/{1,}/, '')\n}\n\nexport function trimPathRight(path: string) {\n return path === '/' ? path : path.replace(/\\/{1,}$/, '')\n}\n\nexport function trimPath(path: string) {\n return trimPathRight(trimPathLeft(path))\n}\n\nexport function removeTrailingSlash(value: string, basepath: string): string {\n if (value?.endsWith('/') && value !== '/' && value !== `${basepath}/`) {\n return value.slice(0, -1)\n }\n return value\n}\n\n// intended to only compare path name\n// see the usage in the isActive under useLinkProps\n// /sample/path1 = /sample/path1/\n// /sample/path1/some <> /sample/path1\nexport function exactPathTest(\n pathName1: string,\n pathName2: string,\n basepath: string,\n): boolean {\n return (\n removeTrailingSlash(pathName1, basepath) ===\n removeTrailingSlash(pathName2, basepath)\n )\n}\n\n// When resolving relative paths, we treat all paths as if they are trailing slash\n// documents. All trailing slashes are removed after the path is resolved.\n// Here are a few examples:\n//\n// /a/b/c + ./d = /a/b/c/d\n// /a/b/c + ../d = /a/b/d\n// /a/b/c + ./d/ = /a/b/c/d\n// /a/b/c + ../d/ = /a/b/d\n// /a/b/c + ./ = /a/b/c\n//\n// Absolute paths that start with `/` short circuit the resolution process to the root\n// path.\n//\n// Here are some examples:\n//\n// /a/b/c + /d = /d\n// /a/b/c + /d/ = /d\n// /a/b/c + / = /\n//\n// Non-.-prefixed paths are still treated as relative paths, resolved like `./`\n//\n// Here are some examples:\n//\n// /a/b/c + d = /a/b/c/d\n// /a/b/c + d/ = /a/b/c/d\n// /a/b/c + d/e = /a/b/c/d/e\ninterface ResolvePathOptions {\n basepath: string\n base: string\n to: string\n trailingSlash?: 'always' | 'never' | 'preserve'\n caseSensitive?: boolean\n}\n\nexport function resolvePath({\n basepath,\n base,\n to,\n trailingSlash = 'never',\n caseSensitive,\n}: ResolvePathOptions) {\n base = removeBasepath(basepath, base, caseSensitive)\n to = removeBasepath(basepath, to, caseSensitive)\n\n let baseSegments = parsePathname(base)\n const toSegments = parsePathname(to)\n\n if (baseSegments.length > 1 && last(baseSegments)?.value === '/') {\n baseSegments.pop()\n }\n\n toSegments.forEach((toSegment, index) => {\n if (toSegment.value === '/') {\n if (!index) {\n // Leading slash\n baseSegments = [toSegment]\n } else if (index === toSegments.length - 1) {\n // Trailing Slash\n baseSegments.push(toSegment)\n } else {\n // ignore inter-slashes\n }\n } else if (toSegment.value === '..') {\n baseSegments.pop()\n } else if (toSegment.value === '.') {\n // ignore\n } else {\n baseSegments.push(toSegment)\n }\n })\n\n if (baseSegments.length > 1) {\n if (last(baseSegments)?.value === '/') {\n if (trailingSlash === 'never') {\n baseSegments.pop()\n }\n } else if (trailingSlash === 'always') {\n baseSegments.push({ type: 'pathname', value: '/' })\n }\n }\n\n const joined = joinPaths([basepath, ...baseSegments.map((d) => d.value)])\n return cleanPath(joined)\n}\n\nexport function parsePathname(pathname?: string): Array<Segment> {\n if (!pathname) {\n return []\n }\n\n pathname = cleanPath(pathname)\n\n const segments: Array<Segment> = []\n\n if (pathname.slice(0, 1) === '/') {\n pathname = pathname.substring(1)\n segments.push({\n type: 'pathname',\n value: '/',\n })\n }\n\n if (!pathname) {\n return segments\n }\n\n // Remove empty segments and '.' segments\n const split = pathname.split('/').filter(Boolean)\n\n segments.push(\n ...split.map((part): Segment => {\n if (part === '$' || part === '*') {\n return {\n type: 'wildcard',\n value: part,\n }\n }\n\n if (part.charAt(0) === '$') {\n return {\n type: 'param',\n value: part,\n }\n }\n\n return {\n type: 'pathname',\n value: part.includes('%25')\n ? part\n .split('%25')\n .map((segment) => decodeURI(segment))\n .join('%25')\n : decodeURI(part),\n }\n }),\n )\n\n if (pathname.slice(-1) === '/') {\n pathname = pathname.substring(1)\n segments.push({\n type: 'pathname',\n value: '/',\n })\n }\n\n return segments\n}\n\ninterface InterpolatePathOptions {\n path?: string\n params: Record<string, unknown>\n leaveWildcards?: boolean\n leaveParams?: boolean\n // Map of encoded chars to decoded chars (e.g. '%40' -> '@') that should remain decoded in path params\n decodeCharMap?: Map<string, string>\n}\n\ntype InterPolatePathResult = {\n interpolatedPath: string\n usedParams: Record<string, unknown>\n isMissingParams: boolean // true if any params were not available when being looked up in the params object\n}\nexport function interpolatePath({\n path,\n params,\n leaveWildcards,\n leaveParams,\n decodeCharMap,\n}: InterpolatePathOptions): InterPolatePathResult {\n const interpolatedPathSegments = parsePathname(path)\n\n function encodeParam(key: string): any {\n const value = params[key]\n const isValueString = typeof value === 'string'\n\n if (['*', '_splat'].includes(key)) {\n // the splat/catch-all routes shouldn't have the '/' encoded out\n return isValueString ? encodeURI(value) : value\n } else {\n return isValueString ? encodePathParam(value, decodeCharMap) : value\n }\n }\n\n // Tracking if any params are missing in the `params` object\n // when interpolating the path\n let isMissingParams = false\n\n const usedParams: Record<string, unknown> = {}\n const interpolatedPath = joinPaths(\n interpolatedPathSegments.map((segment) => {\n if (segment.type === 'wildcard') {\n usedParams._splat = params._splat\n const value = encodeParam('_splat')\n if (leaveWildcards) return `${segment.value}${value ?? ''}`\n return value\n }\n\n if (segment.type === 'param') {\n const key = segment.value.substring(1)\n if (!isMissingParams && !(key in params)) {\n isMissingParams = true\n }\n usedParams[key] = params[key]\n if (leaveParams) {\n const value = encodeParam(segment.value)\n return `${segment.value}${value ?? ''}`\n }\n return encodeParam(key) ?? 'undefined'\n }\n\n return segment.value\n }),\n )\n return { usedParams, interpolatedPath, isMissingParams }\n}\n\nfunction encodePathParam(value: string, decodeCharMap?: Map<string, string>) {\n let encoded = encodeURIComponent(value)\n if (decodeCharMap) {\n for (const [encodedChar, char] of decodeCharMap) {\n encoded = encoded.replaceAll(encodedChar, char)\n }\n }\n return encoded\n}\n\nexport function matchPathname(\n basepath: string,\n currentPathname: string,\n matchLocation: Pick<MatchLocation, 'to' | 'fuzzy' | 'caseSensitive'>,\n): AnyPathParams | undefined {\n const pathParams = matchByPath(basepath, currentPathname, matchLocation)\n // const searchMatched = matchBySearch(location.search, matchLocation)\n\n if (matchLocation.to && !pathParams) {\n return\n }\n\n return pathParams ?? {}\n}\n\nexport function removeBasepath(\n basepath: string,\n pathname: string,\n caseSensitive: boolean = false,\n) {\n // normalize basepath and pathname for case-insensitive comparison if needed\n const normalizedBasepath = caseSensitive ? basepath : basepath.toLowerCase()\n const normalizedPathname = caseSensitive ? pathname : pathname.toLowerCase()\n\n switch (true) {\n // default behaviour is to serve app from the root - pathname\n // left untouched\n case normalizedBasepath === '/':\n return pathname\n\n // shortcut for removing the basepath if it matches the pathname\n case normalizedPathname === normalizedBasepath:\n return ''\n\n // in case pathname is shorter than basepath - there is\n // nothing to remove\n case pathname.length < basepath.length:\n return pathname\n\n // avoid matching partial segments - strict equality handled\n // earlier, otherwise, basepath separated from pathname with\n // separator, therefore lack of separator means partial\n // segment match (`/app` should not match `/application`)\n case normalizedPathname[normalizedBasepath.length] !== '/':\n return pathname\n\n // remove the basepath from the pathname if it starts with it\n case normalizedPathname.startsWith(normalizedBasepath):\n return pathname.slice(basepath.length)\n\n // otherwise, return the pathname as is\n default:\n return pathname\n }\n}\n\nexport function matchByPath(\n basepath: string,\n from: string,\n matchLocation: Pick<MatchLocation, 'to' | 'caseSensitive' | 'fuzzy'>,\n): Record<string, string> | undefined {\n // check basepath first\n if (basepath !== '/' && !from.startsWith(basepath)) {\n return undefined\n }\n // Remove the base path from the pathname\n from = removeBasepath(basepath, from, matchLocation.caseSensitive)\n // Default to to $ (wildcard)\n const to = removeBasepath(\n basepath,\n `${matchLocation.to ?? '$'}`,\n matchLocation.caseSensitive,\n )\n\n // Parse the from and to\n const baseSegments = parsePathname(from)\n const routeSegments = parsePathname(to)\n\n if (!from.startsWith('/')) {\n baseSegments.unshift({\n type: 'pathname',\n value: '/',\n })\n }\n\n if (!to.startsWith('/')) {\n routeSegments.unshift({\n type: 'pathname',\n value: '/',\n })\n }\n\n const params: Record<string, string> = {}\n\n const isMatch = (() => {\n for (\n let i = 0;\n i < Math.max(baseSegments.length, routeSegments.length);\n i++\n ) {\n const baseSegment = baseSegments[i]\n const routeSegment = routeSegments[i]\n\n const isLastBaseSegment = i >= baseSegments.length - 1\n const isLastRouteSegment = i >= routeSegments.length - 1\n\n if (routeSegment) {\n if (routeSegment.type === 'wildcard') {\n const _splat = decodeURI(\n joinPaths(baseSegments.slice(i).map((d) => d.value)),\n )\n // TODO: Deprecate *\n params['*'] = _splat\n params['_splat'] = _splat\n return true\n }\n\n if (routeSegment.type === 'pathname') {\n if (routeSegment.value === '/' && !baseSegment?.value) {\n return true\n }\n\n if (baseSegment) {\n if (matchLocation.caseSensitive) {\n if (routeSegment.value !== baseSegment.value) {\n return false\n }\n } else if (\n routeSegment.value.toLowerCase() !==\n baseSegment.value.toLowerCase()\n ) {\n return false\n }\n }\n }\n\n if (!baseSegment) {\n return false\n }\n\n if (routeSegment.type === 'param') {\n if (baseSegment.value === '/') {\n return false\n }\n if (baseSegment.value.charAt(0) !== '$') {\n params[routeSegment.value.substring(1)] = decodeURIComponent(\n baseSegment.value,\n )\n }\n }\n }\n\n if (!isLastBaseSegment && isLastRouteSegment) {\n params['**'] = joinPaths(baseSegments.slice(i + 1).map((d) => d.value))\n return !!matchLocation.fuzzy && routeSegment?.value !== '/'\n }\n }\n\n return true\n })()\n\n return isMatch ? params : undefined\n}\n"],"names":[],"mappings":";AASO,SAAS,UAAU,OAAkC;AACnD,SAAA;AAAA,IACL,MACG,OAAO,CAAC,QAAQ;AACf,aAAO,QAAQ;AAAA,IAAA,CAChB,EACA,KAAK,GAAG;AAAA,EACb;AACF;AAEO,SAAS,UAAU,MAAc;AAE/B,SAAA,KAAK,QAAQ,WAAW,GAAG;AACpC;AAEO,SAAS,aAAa,MAAc;AACzC,SAAO,SAAS,MAAM,OAAO,KAAK,QAAQ,WAAW,EAAE;AACzD;AAEO,SAAS,cAAc,MAAc;AAC1C,SAAO,SAAS,MAAM,OAAO,KAAK,QAAQ,WAAW,EAAE;AACzD;AAEO,SAAS,SAAS,MAAc;AAC9B,SAAA,cAAc,aAAa,IAAI,CAAC;AACzC;AAEgB,SAAA,oBAAoB,OAAe,UAA0B;AACvE,OAAA,+BAAO,SAAS,SAAQ,UAAU,OAAO,UAAU,GAAG,QAAQ,KAAK;AAC9D,WAAA,MAAM,MAAM,GAAG,EAAE;AAAA,EAAA;AAEnB,SAAA;AACT;AAMgB,SAAA,cACd,WACA,WACA,UACS;AACT,SACE,oBAAoB,WAAW,QAAQ,MACvC,oBAAoB,WAAW,QAAQ;AAE3C;AAoCO,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA,gBAAgB;AAAA,EAChB;AACF,GAAuB;;AACd,SAAA,eAAe,UAAU,MAAM,aAAa;AAC9C,OAAA,eAAe,UAAU,IAAI,aAAa;AAE3C,MAAA,eAAe,cAAc,IAAI;AAC/B,QAAA,aAAa,cAAc,EAAE;AAEnC,MAAI,aAAa,SAAS,OAAK,UAAK,YAAY,MAAjB,mBAAoB,WAAU,KAAK;AAChE,iBAAa,IAAI;AAAA,EAAA;AAGR,aAAA,QAAQ,CAAC,WAAW,UAAU;AACnC,QAAA,UAAU,UAAU,KAAK;AAC3B,UAAI,CAAC,OAAO;AAEV,uBAAe,CAAC,SAAS;AAAA,MAChB,WAAA,UAAU,WAAW,SAAS,GAAG;AAE1C,qBAAa,KAAK,SAAS;AAAA,MAAA,MACtB;AAAA,IAEP,WACS,UAAU,UAAU,MAAM;AACnC,mBAAa,IAAI;AAAA,IACnB,WAAW,UAAU,UAAU,IAAK;AAAA,SAE7B;AACL,mBAAa,KAAK,SAAS;AAAA,IAAA;AAAA,EAC7B,CACD;AAEG,MAAA,aAAa,SAAS,GAAG;AAC3B,UAAI,UAAK,YAAY,MAAjB,mBAAoB,WAAU,KAAK;AACrC,UAAI,kBAAkB,SAAS;AAC7B,qBAAa,IAAI;AAAA,MAAA;AAAA,IACnB,WACS,kBAAkB,UAAU;AACrC,mBAAa,KAAK,EAAE,MAAM,YAAY,OAAO,KAAK;AAAA,IAAA;AAAA,EACpD;AAGF,QAAM,SAAS,UAAU,CAAC,UAAU,GAAG,aAAa,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AACxE,SAAO,UAAU,MAAM;AACzB;AAEO,SAAS,cAAc,UAAmC;AAC/D,MAAI,CAAC,UAAU;AACb,WAAO,CAAC;AAAA,EAAA;AAGV,aAAW,UAAU,QAAQ;AAE7B,QAAM,WAA2B,CAAC;AAElC,MAAI,SAAS,MAAM,GAAG,CAAC,MAAM,KAAK;AACrB,eAAA,SAAS,UAAU,CAAC;AAC/B,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,OAAO;AAAA,IAAA,CACR;AAAA,EAAA;AAGH,MAAI,CAAC,UAAU;AACN,WAAA;AAAA,EAAA;AAIT,QAAM,QAAQ,SAAS,MAAM,GAAG,EAAE,OAAO,OAAO;AAEvC,WAAA;AAAA,IACP,GAAG,MAAM,IAAI,CAAC,SAAkB;AAC1B,UAAA,SAAS,OAAO,SAAS,KAAK;AACzB,eAAA;AAAA,UACL,MAAM;AAAA,UACN,OAAO;AAAA,QACT;AAAA,MAAA;AAGF,UAAI,KAAK,OAAO,CAAC,MAAM,KAAK;AACnB,eAAA;AAAA,UACL,MAAM;AAAA,UACN,OAAO;AAAA,QACT;AAAA,MAAA;AAGK,aAAA;AAAA,QACL,MAAM;AAAA,QACN,OAAO,KAAK,SAAS,KAAK,IACtB,KACG,MAAM,KAAK,EACX,IAAI,CAAC,YAAY,UAAU,OAAO,CAAC,EACnC,KAAK,KAAK,IACb,UAAU,IAAI;AAAA,MACpB;AAAA,IACD,CAAA;AAAA,EACH;AAEA,MAAI,SAAS,MAAM,EAAE,MAAM,KAAK;AACnB,eAAA,SAAS,UAAU,CAAC;AAC/B,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,OAAO;AAAA,IAAA,CACR;AAAA,EAAA;AAGI,SAAA;AACT;AAgBO,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAkD;AAC1C,QAAA,2BAA2B,cAAc,IAAI;AAEnD,WAAS,YAAY,KAAkB;AAC/B,UAAA,QAAQ,OAAO,GAAG;AAClB,UAAA,gBAAgB,OAAO,UAAU;AAEvC,QAAI,CAAC,KAAK,QAAQ,EAAE,SAAS,GAAG,GAAG;AAE1B,aAAA,gBAAgB,UAAU,KAAK,IAAI;AAAA,IAAA,OACrC;AACL,aAAO,gBAAgB,gBAAgB,OAAO,aAAa,IAAI;AAAA,IAAA;AAAA,EACjE;AAKF,MAAI,kBAAkB;AAEtB,QAAM,aAAsC,CAAC;AAC7C,QAAM,mBAAmB;AAAA,IACvB,yBAAyB,IAAI,CAAC,YAAY;AACpC,UAAA,QAAQ,SAAS,YAAY;AAC/B,mBAAW,SAAS,OAAO;AACrB,cAAA,QAAQ,YAAY,QAAQ;AAClC,YAAI,eAAuB,QAAA,GAAG,QAAQ,KAAK,GAAG,SAAS,EAAE;AAClD,eAAA;AAAA,MAAA;AAGL,UAAA,QAAQ,SAAS,SAAS;AAC5B,cAAM,MAAM,QAAQ,MAAM,UAAU,CAAC;AACrC,YAAI,CAAC,mBAAmB,EAAE,OAAO,SAAS;AACtB,4BAAA;AAAA,QAAA;AAET,mBAAA,GAAG,IAAI,OAAO,GAAG;AAC5B,YAAI,aAAa;AACT,gBAAA,QAAQ,YAAY,QAAQ,KAAK;AACvC,iBAAO,GAAG,QAAQ,KAAK,GAAG,SAAS,EAAE;AAAA,QAAA;AAEhC,eAAA,YAAY,GAAG,KAAK;AAAA,MAAA;AAG7B,aAAO,QAAQ;AAAA,IAChB,CAAA;AAAA,EACH;AACO,SAAA,EAAE,YAAY,kBAAkB,gBAAgB;AACzD;AAEA,SAAS,gBAAgB,OAAe,eAAqC;AACvE,MAAA,UAAU,mBAAmB,KAAK;AACtC,MAAI,eAAe;AACjB,eAAW,CAAC,aAAa,IAAI,KAAK,eAAe;AACrC,gBAAA,QAAQ,WAAW,aAAa,IAAI;AAAA,IAAA;AAAA,EAChD;AAEK,SAAA;AACT;AAEgB,SAAA,cACd,UACA,iBACA,eAC2B;AAC3B,QAAM,aAAa,YAAY,UAAU,iBAAiB,aAAa;AAGnE,MAAA,cAAc,MAAM,CAAC,YAAY;AACnC;AAAA,EAAA;AAGF,SAAO,cAAc,CAAC;AACxB;AAEO,SAAS,eACd,UACA,UACA,gBAAyB,OACzB;AAEA,QAAM,qBAAqB,gBAAgB,WAAW,SAAS,YAAY;AAC3E,QAAM,qBAAqB,gBAAgB,WAAW,SAAS,YAAY;AAE3E,UAAQ,MAAM;AAAA;AAAA;AAAA,IAGZ,KAAK,uBAAuB;AACnB,aAAA;AAAA;AAAA,IAGT,KAAK,uBAAuB;AACnB,aAAA;AAAA;AAAA;AAAA,IAIT,KAAK,SAAS,SAAS,SAAS;AACvB,aAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMT,KAAK,mBAAmB,mBAAmB,MAAM,MAAM;AAC9C,aAAA;AAAA;AAAA,IAGT,KAAK,mBAAmB,WAAW,kBAAkB;AAC5C,aAAA,SAAS,MAAM,SAAS,MAAM;AAAA;AAAA,IAGvC;AACS,aAAA;AAAA,EAAA;AAEb;AAEgB,SAAA,YACd,UACA,MACA,eACoC;AAEpC,MAAI,aAAa,OAAO,CAAC,KAAK,WAAW,QAAQ,GAAG;AAC3C,WAAA;AAAA,EAAA;AAGT,SAAO,eAAe,UAAU,MAAM,cAAc,aAAa;AAEjE,QAAM,KAAK;AAAA,IACT;AAAA,IACA,GAAG,cAAc,MAAM,GAAG;AAAA,IAC1B,cAAc;AAAA,EAChB;AAGM,QAAA,eAAe,cAAc,IAAI;AACjC,QAAA,gBAAgB,cAAc,EAAE;AAEtC,MAAI,CAAC,KAAK,WAAW,GAAG,GAAG;AACzB,iBAAa,QAAQ;AAAA,MACnB,MAAM;AAAA,MACN,OAAO;AAAA,IAAA,CACR;AAAA,EAAA;AAGH,MAAI,CAAC,GAAG,WAAW,GAAG,GAAG;AACvB,kBAAc,QAAQ;AAAA,MACpB,MAAM;AAAA,MACN,OAAO;AAAA,IAAA,CACR;AAAA,EAAA;AAGH,QAAM,SAAiC,CAAC;AAExC,QAAM,WAAW,MAAM;AAEf,aAAA,IAAI,GACR,IAAI,KAAK,IAAI,aAAa,QAAQ,cAAc,MAAM,GACtD,KACA;AACM,YAAA,cAAc,aAAa,CAAC;AAC5B,YAAA,eAAe,cAAc,CAAC;AAE9B,YAAA,oBAAoB,KAAK,aAAa,SAAS;AAC/C,YAAA,qBAAqB,KAAK,cAAc,SAAS;AAEvD,UAAI,cAAc;AACZ,YAAA,aAAa,SAAS,YAAY;AACpC,gBAAM,SAAS;AAAA,YACb,UAAU,aAAa,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AAAA,UACrD;AAEA,iBAAO,GAAG,IAAI;AACd,iBAAO,QAAQ,IAAI;AACZ,iBAAA;AAAA,QAAA;AAGL,YAAA,aAAa,SAAS,YAAY;AACpC,cAAI,aAAa,UAAU,OAAO,EAAC,2CAAa,QAAO;AAC9C,mBAAA;AAAA,UAAA;AAGT,cAAI,aAAa;AACf,gBAAI,cAAc,eAAe;AAC3B,kBAAA,aAAa,UAAU,YAAY,OAAO;AACrC,uBAAA;AAAA,cAAA;AAAA,YACT,WAEA,aAAa,MAAM,kBACnB,YAAY,MAAM,eAClB;AACO,qBAAA;AAAA,YAAA;AAAA,UACT;AAAA,QACF;AAGF,YAAI,CAAC,aAAa;AACT,iBAAA;AAAA,QAAA;AAGL,YAAA,aAAa,SAAS,SAAS;AAC7B,cAAA,YAAY,UAAU,KAAK;AACtB,mBAAA;AAAA,UAAA;AAET,cAAI,YAAY,MAAM,OAAO,CAAC,MAAM,KAAK;AACvC,mBAAO,aAAa,MAAM,UAAU,CAAC,CAAC,IAAI;AAAA,cACxC,YAAY;AAAA,YACd;AAAA,UAAA;AAAA,QACF;AAAA,MACF;AAGE,UAAA,CAAC,qBAAqB,oBAAoB;AAC5C,eAAO,IAAI,IAAI,UAAU,aAAa,MAAM,IAAI,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AACtE,eAAO,CAAC,CAAC,cAAc,UAAS,6CAAc,WAAU;AAAA,MAAA;AAAA,IAC1D;AAGK,WAAA;AAAA,EAAA,GACN;AAEH,SAAO,UAAU,SAAS;AAC5B;"}
|
|
1
|
+
{"version":3,"file":"path.js","sources":["../../src/path.ts"],"sourcesContent":["import { last } from './utils'\nimport type { MatchLocation } from './RouterProvider'\nimport type { AnyPathParams } from './route'\n\nexport interface Segment {\n type: 'pathname' | 'param' | 'wildcard'\n value: string\n // Add a new property to store the static segment if present\n prefixSegment?: string\n suffixSegment?: string\n}\n\nexport function joinPaths(paths: Array<string | undefined>) {\n return cleanPath(\n paths\n .filter((val) => {\n return val !== undefined\n })\n .join('/'),\n )\n}\n\nexport function cleanPath(path: string) {\n // remove double slashes\n return path.replace(/\\/{2,}/g, '/')\n}\n\nexport function trimPathLeft(path: string) {\n return path === '/' ? path : path.replace(/^\\/{1,}/, '')\n}\n\nexport function trimPathRight(path: string) {\n return path === '/' ? path : path.replace(/\\/{1,}$/, '')\n}\n\nexport function trimPath(path: string) {\n return trimPathRight(trimPathLeft(path))\n}\n\nexport function removeTrailingSlash(value: string, basepath: string): string {\n if (value?.endsWith('/') && value !== '/' && value !== `${basepath}/`) {\n return value.slice(0, -1)\n }\n return value\n}\n\n// intended to only compare path name\n// see the usage in the isActive under useLinkProps\n// /sample/path1 = /sample/path1/\n// /sample/path1/some <> /sample/path1\nexport function exactPathTest(\n pathName1: string,\n pathName2: string,\n basepath: string,\n): boolean {\n return (\n removeTrailingSlash(pathName1, basepath) ===\n removeTrailingSlash(pathName2, basepath)\n )\n}\n\n// When resolving relative paths, we treat all paths as if they are trailing slash\n// documents. All trailing slashes are removed after the path is resolved.\n// Here are a few examples:\n//\n// /a/b/c + ./d = /a/b/c/d\n// /a/b/c + ../d = /a/b/d\n// /a/b/c + ./d/ = /a/b/c/d\n// /a/b/c + ../d/ = /a/b/d\n// /a/b/c + ./ = /a/b/c\n//\n// Absolute paths that start with `/` short circuit the resolution process to the root\n// path.\n//\n// Here are some examples:\n//\n// /a/b/c + /d = /d\n// /a/b/c + /d/ = /d\n// /a/b/c + / = /\n//\n// Non-.-prefixed paths are still treated as relative paths, resolved like `./`\n//\n// Here are some examples:\n//\n// /a/b/c + d = /a/b/c/d\n// /a/b/c + d/ = /a/b/c/d\n// /a/b/c + d/e = /a/b/c/d/e\ninterface ResolvePathOptions {\n basepath: string\n base: string\n to: string\n trailingSlash?: 'always' | 'never' | 'preserve'\n caseSensitive?: boolean\n}\n\nexport function resolvePath({\n basepath,\n base,\n to,\n trailingSlash = 'never',\n caseSensitive,\n}: ResolvePathOptions) {\n base = removeBasepath(basepath, base, caseSensitive)\n to = removeBasepath(basepath, to, caseSensitive)\n\n let baseSegments = parsePathname(base)\n const toSegments = parsePathname(to)\n\n if (baseSegments.length > 1 && last(baseSegments)?.value === '/') {\n baseSegments.pop()\n }\n\n toSegments.forEach((toSegment, index) => {\n if (toSegment.value === '/') {\n if (!index) {\n // Leading slash\n baseSegments = [toSegment]\n } else if (index === toSegments.length - 1) {\n // Trailing Slash\n baseSegments.push(toSegment)\n } else {\n // ignore inter-slashes\n }\n } else if (toSegment.value === '..') {\n baseSegments.pop()\n } else if (toSegment.value === '.') {\n // ignore\n } else {\n baseSegments.push(toSegment)\n }\n })\n\n if (baseSegments.length > 1) {\n if (last(baseSegments)?.value === '/') {\n if (trailingSlash === 'never') {\n baseSegments.pop()\n }\n } else if (trailingSlash === 'always') {\n baseSegments.push({ type: 'pathname', value: '/' })\n }\n }\n\n const segmentValues = baseSegments.map((segment) => {\n if (segment.type === 'param') {\n const param = segment.value.substring(1)\n if (segment.prefixSegment && segment.suffixSegment) {\n return `${segment.prefixSegment}{$${param}}${segment.suffixSegment}`\n } else if (segment.prefixSegment) {\n return `${segment.prefixSegment}{$${param}}`\n } else if (segment.suffixSegment) {\n return `{$${param}}${segment.suffixSegment}`\n }\n }\n if (segment.type === 'wildcard') {\n if (segment.prefixSegment && segment.suffixSegment) {\n return `${segment.prefixSegment}{$}${segment.suffixSegment}`\n } else if (segment.prefixSegment) {\n return `${segment.prefixSegment}{$}`\n } else if (segment.suffixSegment) {\n return `{$}${segment.suffixSegment}`\n }\n }\n return segment.value\n })\n const joined = joinPaths([basepath, ...segmentValues])\n return cleanPath(joined)\n}\n\nconst PARAM_RE = /^\\$.{1,}$/ // $paramName\nconst PARAM_W_CURLY_BRACES_RE = /^(.*?)\\{(\\$[a-zA-Z_$][a-zA-Z0-9_$]*)\\}(.*)$/ // prefix{$paramName}suffix\nconst WILDCARD_RE = /^\\$$/ // $\nconst WILDCARD_W_CURLY_BRACES_RE = /^(.*?)\\{\\$\\}(.*)$/ // prefix{$}suffix\n\n/**\n * Required: `/foo/$bar` ✅\n * Prefix and Suffix: `/foo/prefix${bar}suffix` ✅\n * Wildcard: `/foo/$` ✅\n * Wildcard with Prefix and Suffix: `/foo/prefix{$}suffix` ✅\n *\n * Future:\n * Optional: `/foo/{-bar}`\n * Optional named segment: `/foo/{bar}`\n * Optional named segment with Prefix and Suffix: `/foo/prefix{-bar}suffix`\n * Escape special characters:\n * - `/foo/[$]` - Static route\n * - `/foo/[$]{$foo} - Dynamic route with a static prefix of `$`\n * - `/foo/{$foo}[$]` - Dynamic route with a static suffix of `$`\n */\nexport function parsePathname(pathname?: string): Array<Segment> {\n if (!pathname) {\n return []\n }\n\n pathname = cleanPath(pathname)\n\n const segments: Array<Segment> = []\n\n if (pathname.slice(0, 1) === '/') {\n pathname = pathname.substring(1)\n segments.push({\n type: 'pathname',\n value: '/',\n })\n }\n\n if (!pathname) {\n return segments\n }\n\n // Remove empty segments and '.' segments\n const split = pathname.split('/').filter(Boolean)\n\n segments.push(\n ...split.map((part): Segment => {\n // Check for wildcard with curly braces: prefix{$}suffix\n const wildcardBracesMatch = part.match(WILDCARD_W_CURLY_BRACES_RE)\n if (wildcardBracesMatch) {\n const prefix = wildcardBracesMatch[1]\n const suffix = wildcardBracesMatch[2]\n return {\n type: 'wildcard',\n value: '$',\n prefixSegment: prefix || undefined,\n suffixSegment: suffix || undefined,\n }\n }\n\n // Check for the new parameter format: prefix{$paramName}suffix\n const paramBracesMatch = part.match(PARAM_W_CURLY_BRACES_RE)\n if (paramBracesMatch) {\n const prefix = paramBracesMatch[1]\n const paramName = paramBracesMatch[2]\n const suffix = paramBracesMatch[3]\n return {\n type: 'param',\n value: '' + paramName,\n prefixSegment: prefix || undefined,\n suffixSegment: suffix || undefined,\n }\n }\n\n // Check for bare parameter format: $paramName (without curly braces)\n if (PARAM_RE.test(part)) {\n const paramName = part.substring(1)\n return {\n type: 'param',\n value: '$' + paramName,\n prefixSegment: undefined,\n suffixSegment: undefined,\n }\n }\n\n // Check for bare wildcard: $ (without curly braces)\n if (WILDCARD_RE.test(part)) {\n return {\n type: 'wildcard',\n value: '$',\n prefixSegment: undefined,\n suffixSegment: undefined,\n }\n }\n\n // Handle regular pathname segment\n return {\n type: 'pathname',\n value: part.includes('%25')\n ? part\n .split('%25')\n .map((segment) => decodeURI(segment))\n .join('%25')\n : decodeURI(part),\n }\n }),\n )\n\n if (pathname.slice(-1) === '/') {\n pathname = pathname.substring(1)\n segments.push({\n type: 'pathname',\n value: '/',\n })\n }\n\n return segments\n}\n\ninterface InterpolatePathOptions {\n path?: string\n params: Record<string, unknown>\n leaveWildcards?: boolean\n leaveParams?: boolean\n // Map of encoded chars to decoded chars (e.g. '%40' -> '@') that should remain decoded in path params\n decodeCharMap?: Map<string, string>\n}\n\ntype InterPolatePathResult = {\n interpolatedPath: string\n usedParams: Record<string, unknown>\n isMissingParams: boolean // true if any params were not available when being looked up in the params object\n}\nexport function interpolatePath({\n path,\n params,\n leaveWildcards,\n leaveParams,\n decodeCharMap,\n}: InterpolatePathOptions): InterPolatePathResult {\n const interpolatedPathSegments = parsePathname(path)\n\n function encodeParam(key: string): any {\n const value = params[key]\n const isValueString = typeof value === 'string'\n\n if (['*', '_splat'].includes(key)) {\n // the splat/catch-all routes shouldn't have the '/' encoded out\n return isValueString ? encodeURI(value) : value\n } else {\n return isValueString ? encodePathParam(value, decodeCharMap) : value\n }\n }\n\n // Tracking if any params are missing in the `params` object\n // when interpolating the path\n let isMissingParams = false\n\n const usedParams: Record<string, unknown> = {}\n const interpolatedPath = joinPaths(\n interpolatedPathSegments.map((segment) => {\n if (segment.type === 'wildcard') {\n usedParams._splat = params._splat\n const segmentPrefix = segment.prefixSegment || ''\n const segmentSuffix = segment.suffixSegment || ''\n const value = encodeParam('_splat')\n if (leaveWildcards) {\n return `${segmentPrefix}${segment.value}${value ?? ''}${segmentSuffix}`\n }\n return `${segmentPrefix}${value}${segmentSuffix}`\n }\n\n if (segment.type === 'param') {\n const key = segment.value.substring(1)\n if (!isMissingParams && !(key in params)) {\n isMissingParams = true\n }\n usedParams[key] = params[key]\n\n const segmentPrefix = segment.prefixSegment || ''\n const segmentSuffix = segment.suffixSegment || ''\n if (leaveParams) {\n const value = encodeParam(segment.value)\n return `${segmentPrefix}${segment.value}${value ?? ''}${segmentSuffix}`\n }\n return `${segmentPrefix}${encodeParam(key) ?? 'undefined'}${segmentSuffix}`\n }\n\n return segment.value\n }),\n )\n return { usedParams, interpolatedPath, isMissingParams }\n}\n\nfunction encodePathParam(value: string, decodeCharMap?: Map<string, string>) {\n let encoded = encodeURIComponent(value)\n if (decodeCharMap) {\n for (const [encodedChar, char] of decodeCharMap) {\n encoded = encoded.replaceAll(encodedChar, char)\n }\n }\n return encoded\n}\n\nexport function matchPathname(\n basepath: string,\n currentPathname: string,\n matchLocation: Pick<MatchLocation, 'to' | 'fuzzy' | 'caseSensitive'>,\n): AnyPathParams | undefined {\n const pathParams = matchByPath(basepath, currentPathname, matchLocation)\n // const searchMatched = matchBySearch(location.search, matchLocation)\n\n if (matchLocation.to && !pathParams) {\n return\n }\n\n return pathParams ?? {}\n}\n\nexport function removeBasepath(\n basepath: string,\n pathname: string,\n caseSensitive: boolean = false,\n) {\n // normalize basepath and pathname for case-insensitive comparison if needed\n const normalizedBasepath = caseSensitive ? basepath : basepath.toLowerCase()\n const normalizedPathname = caseSensitive ? pathname : pathname.toLowerCase()\n\n switch (true) {\n // default behaviour is to serve app from the root - pathname\n // left untouched\n case normalizedBasepath === '/':\n return pathname\n\n // shortcut for removing the basepath if it matches the pathname\n case normalizedPathname === normalizedBasepath:\n return ''\n\n // in case pathname is shorter than basepath - there is\n // nothing to remove\n case pathname.length < basepath.length:\n return pathname\n\n // avoid matching partial segments - strict equality handled\n // earlier, otherwise, basepath separated from pathname with\n // separator, therefore lack of separator means partial\n // segment match (`/app` should not match `/application`)\n case normalizedPathname[normalizedBasepath.length] !== '/':\n return pathname\n\n // remove the basepath from the pathname if it starts with it\n case normalizedPathname.startsWith(normalizedBasepath):\n return pathname.slice(basepath.length)\n\n // otherwise, return the pathname as is\n default:\n return pathname\n }\n}\n\nexport function matchByPath(\n basepath: string,\n from: string,\n matchLocation: Pick<MatchLocation, 'to' | 'caseSensitive' | 'fuzzy'>,\n): Record<string, string> | undefined {\n // check basepath first\n if (basepath !== '/' && !from.startsWith(basepath)) {\n return undefined\n }\n // Remove the base path from the pathname\n from = removeBasepath(basepath, from, matchLocation.caseSensitive)\n // Default to to $ (wildcard)\n const to = removeBasepath(\n basepath,\n `${matchLocation.to ?? '$'}`,\n matchLocation.caseSensitive,\n )\n\n // Parse the from and to\n const baseSegments = parsePathname(from)\n const routeSegments = parsePathname(to)\n\n if (!from.startsWith('/')) {\n baseSegments.unshift({\n type: 'pathname',\n value: '/',\n })\n }\n\n if (!to.startsWith('/')) {\n routeSegments.unshift({\n type: 'pathname',\n value: '/',\n })\n }\n\n const params: Record<string, string> = {}\n\n const isMatch = (() => {\n for (\n let i = 0;\n i < Math.max(baseSegments.length, routeSegments.length);\n i++\n ) {\n const baseSegment = baseSegments[i]\n const routeSegment = routeSegments[i]\n\n const isLastBaseSegment = i >= baseSegments.length - 1\n const isLastRouteSegment = i >= routeSegments.length - 1\n\n if (routeSegment) {\n if (routeSegment.type === 'wildcard') {\n // Capture all remaining segments for a wildcard\n const remainingBaseSegments = baseSegments.slice(i)\n\n let _splat: string\n\n // If this is a wildcard with prefix/suffix, we need to handle the first segment specially\n if (routeSegment.prefixSegment || routeSegment.suffixSegment) {\n if (!baseSegment) return false\n\n const prefix = routeSegment.prefixSegment || ''\n const suffix = routeSegment.suffixSegment || ''\n\n // Check if the base segment starts with prefix and ends with suffix\n const baseValue = baseSegment.value\n if ('prefixSegment' in routeSegment) {\n if (!baseValue.startsWith(prefix)) {\n return false\n }\n }\n if ('suffixSegment' in routeSegment) {\n if (\n !baseSegments[baseSegments.length - 1]?.value.endsWith(suffix)\n ) {\n return false\n }\n }\n\n let rejoinedSplat = decodeURI(\n joinPaths(remainingBaseSegments.map((d) => d.value)),\n )\n\n // Remove the prefix and suffix from the rejoined splat\n if (prefix && rejoinedSplat.startsWith(prefix)) {\n rejoinedSplat = rejoinedSplat.slice(prefix.length)\n }\n\n if (suffix && rejoinedSplat.endsWith(suffix)) {\n rejoinedSplat = rejoinedSplat.slice(\n 0,\n rejoinedSplat.length - suffix.length,\n )\n }\n\n _splat = rejoinedSplat\n } else {\n // If no prefix/suffix, just rejoin the remaining segments\n _splat = decodeURI(\n joinPaths(remainingBaseSegments.map((d) => d.value)),\n )\n }\n\n // TODO: Deprecate *\n params['*'] = _splat\n params['_splat'] = _splat\n return true\n }\n\n if (routeSegment.type === 'pathname') {\n if (routeSegment.value === '/' && !baseSegment?.value) {\n return true\n }\n\n if (baseSegment) {\n if (matchLocation.caseSensitive) {\n if (routeSegment.value !== baseSegment.value) {\n return false\n }\n } else if (\n routeSegment.value.toLowerCase() !==\n baseSegment.value.toLowerCase()\n ) {\n return false\n }\n }\n }\n\n if (!baseSegment) {\n return false\n }\n\n if (routeSegment.type === 'param') {\n if (baseSegment.value === '/') {\n return false\n }\n\n let _paramValue: string\n\n // If this param has prefix/suffix, we need to extract the actual parameter value\n if (routeSegment.prefixSegment || routeSegment.suffixSegment) {\n const prefix = routeSegment.prefixSegment || ''\n const suffix = routeSegment.suffixSegment || ''\n\n // Check if the base segment starts with prefix and ends with suffix\n const baseValue = baseSegment.value\n if (prefix && !baseValue.startsWith(prefix)) {\n return false\n }\n if (suffix && !baseValue.endsWith(suffix)) {\n return false\n }\n\n let paramValue = baseValue\n if (prefix && paramValue.startsWith(prefix)) {\n paramValue = paramValue.slice(prefix.length)\n }\n if (suffix && paramValue.endsWith(suffix)) {\n paramValue = paramValue.slice(\n 0,\n paramValue.length - suffix.length,\n )\n }\n\n _paramValue = decodeURIComponent(paramValue)\n } else {\n // If no prefix/suffix, just decode the base segment value\n _paramValue = decodeURIComponent(baseSegment.value)\n }\n\n params[routeSegment.value.substring(1)] = _paramValue\n }\n }\n\n if (!isLastBaseSegment && isLastRouteSegment) {\n params['**'] = joinPaths(baseSegments.slice(i + 1).map((d) => d.value))\n return !!matchLocation.fuzzy && routeSegment?.value !== '/'\n }\n }\n\n return true\n })()\n\n return isMatch ? params : undefined\n}\n"],"names":[],"mappings":"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"}
|
package/dist/esm/redirect.d.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { NavigateOptions } from './link.js';
|
|
2
|
-
import { RoutePaths } from './routeInfo.js';
|
|
3
2
|
import { AnyRouter, RegisteredRouter } from './router.js';
|
|
4
|
-
|
|
3
|
+
export declare const tsrRedirectHeaderKey = "X-Tanstack-Router-Redirect-Options";
|
|
5
4
|
export type AnyRedirect = Redirect<any, any, any, any, any>;
|
|
6
5
|
/**
|
|
7
6
|
* @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType)
|
|
8
7
|
*/
|
|
9
|
-
export type Redirect<TRouter extends AnyRouter = RegisteredRouter, TFrom extends
|
|
8
|
+
export type Redirect<TRouter extends AnyRouter = RegisteredRouter, TFrom extends string = string, TTo extends string | undefined = undefined, TMaskFrom extends string = TFrom, TMaskTo extends string = '.'> = Response & {
|
|
9
|
+
options: NavigateOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>;
|
|
10
|
+
redirectHandled?: boolean;
|
|
11
|
+
};
|
|
12
|
+
export type RedirectOptions<TRouter extends AnyRouter = RegisteredRouter, TFrom extends string = string, TTo extends string | undefined = undefined, TMaskFrom extends string = TFrom, TMaskTo extends string = '.'> = {
|
|
10
13
|
href?: string;
|
|
11
14
|
/**
|
|
12
15
|
* @deprecated Use `statusCode` instead
|
|
@@ -28,9 +31,8 @@ export type Redirect<TRouter extends AnyRouter = RegisteredRouter, TFrom extends
|
|
|
28
31
|
*/
|
|
29
32
|
headers?: HeadersInit;
|
|
30
33
|
} & NavigateOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>;
|
|
31
|
-
export type ResolvedRedirect<TRouter extends AnyRouter = RegisteredRouter, TFrom extends
|
|
32
|
-
|
|
33
|
-
};
|
|
34
|
-
export declare function redirect<TRouter extends AnyRouter = RegisteredRouter, const TTo extends string | undefined = '.', const TFrom extends string = string, const TMaskFrom extends string = TFrom, const TMaskTo extends string = ''>(opts: Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>): Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>;
|
|
34
|
+
export type ResolvedRedirect<TRouter extends AnyRouter = RegisteredRouter, TFrom extends string = string, TTo extends string = '', TMaskFrom extends string = TFrom, TMaskTo extends string = ''> = Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>;
|
|
35
|
+
export declare function redirect<TRouter extends AnyRouter = RegisteredRouter, const TTo extends string | undefined = '.', const TFrom extends string = string, const TMaskFrom extends string = TFrom, const TMaskTo extends string = ''>(opts: RedirectOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>): Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>;
|
|
35
36
|
export declare function isRedirect(obj: any): obj is AnyRedirect;
|
|
36
|
-
export declare function isResolvedRedirect(obj: any): obj is
|
|
37
|
+
export declare function isResolvedRedirect(obj: any): obj is AnyRedirect;
|
|
38
|
+
export declare function parseRedirect(obj: any): Redirect<AnyRouter, string, ".", string, ""> | undefined;
|
package/dist/esm/redirect.js
CHANGED
|
@@ -1,29 +1,34 @@
|
|
|
1
|
+
const tsrRedirectHeaderKey = "X-Tanstack-Router-Redirect-Options";
|
|
1
2
|
function redirect(opts) {
|
|
2
|
-
opts.isRedirect = true;
|
|
3
3
|
opts.statusCode = opts.statusCode || opts.code || 307;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
opts.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
} catch {
|
|
11
|
-
}
|
|
12
|
-
}
|
|
4
|
+
const headers = new Headers(opts.headers || {});
|
|
5
|
+
const response = new Response(null, {
|
|
6
|
+
status: opts.statusCode,
|
|
7
|
+
headers
|
|
8
|
+
});
|
|
9
|
+
response.options = opts;
|
|
13
10
|
if (opts.throw) {
|
|
14
|
-
throw
|
|
11
|
+
throw response;
|
|
15
12
|
}
|
|
16
|
-
return
|
|
13
|
+
return response;
|
|
17
14
|
}
|
|
18
15
|
function isRedirect(obj) {
|
|
19
|
-
return
|
|
16
|
+
return obj instanceof Response && !!obj.options;
|
|
20
17
|
}
|
|
21
18
|
function isResolvedRedirect(obj) {
|
|
22
|
-
return
|
|
19
|
+
return isRedirect(obj) && !!obj.options.href;
|
|
20
|
+
}
|
|
21
|
+
function parseRedirect(obj) {
|
|
22
|
+
if (typeof obj === "object" && obj.isSerializedRedirect) {
|
|
23
|
+
return redirect(obj);
|
|
24
|
+
}
|
|
25
|
+
return void 0;
|
|
23
26
|
}
|
|
24
27
|
export {
|
|
25
28
|
isRedirect,
|
|
26
29
|
isResolvedRedirect,
|
|
27
|
-
|
|
30
|
+
parseRedirect,
|
|
31
|
+
redirect,
|
|
32
|
+
tsrRedirectHeaderKey
|
|
28
33
|
};
|
|
29
34
|
//# sourceMappingURL=redirect.js.map
|
package/dist/esm/redirect.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redirect.js","sources":["../../src/redirect.ts"],"sourcesContent":["import type { NavigateOptions } from './link'\nimport type {
|
|
1
|
+
{"version":3,"file":"redirect.js","sources":["../../src/redirect.ts"],"sourcesContent":["import type { NavigateOptions } from './link'\nimport type { AnyRouter, RegisteredRouter } from './router'\n\nexport const tsrRedirectHeaderKey = 'X-Tanstack-Router-Redirect-Options'\n\nexport type AnyRedirect = Redirect<any, any, any, any, any>\n\n/**\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType)\n */\nexport type Redirect<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = undefined,\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '.',\n> = Response & {\n options: NavigateOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>\n redirectHandled?: boolean\n}\n\nexport type RedirectOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = undefined,\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '.',\n> = {\n href?: string\n /**\n * @deprecated Use `statusCode` instead\n **/\n code?: number\n /**\n * The HTTP status code to use when redirecting.\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType#statuscode-property)\n */\n statusCode?: number\n /**\n * If provided, will throw the redirect object instead of returning it. This can be useful in places where `throwing` in a function might cause it to have a return type of `never`. In that case, you can use `redirect({ throw: true })` to throw the redirect object instead of returning it.\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType#throw-property)\n */\n throw?: any\n /**\n * The HTTP headers to use when redirecting.\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType#headers-property)\n */\n headers?: HeadersInit\n} & NavigateOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>\n\nexport type ResolvedRedirect<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string = '',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '',\n> = Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>\n\nexport function redirect<\n TRouter extends AnyRouter = RegisteredRouter,\n const TTo extends string | undefined = '.',\n const TFrom extends string = string,\n const TMaskFrom extends string = TFrom,\n const TMaskTo extends string = '',\n>(\n opts: RedirectOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,\n): Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> {\n opts.statusCode = opts.statusCode || opts.code || 307\n const headers = new Headers(opts.headers || {})\n\n const response = new Response(null, {\n status: opts.statusCode,\n headers,\n })\n\n ;(response as Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>).options =\n opts\n\n if (opts.throw) {\n throw response\n }\n\n return response as Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>\n}\n\nexport function isRedirect(obj: any): obj is AnyRedirect {\n return obj instanceof Response && !!(obj as any).options\n}\n\nexport function isResolvedRedirect(obj: any): obj is AnyRedirect {\n return isRedirect(obj) && !!obj.options.href\n}\n\nexport function parseRedirect(obj: any) {\n if (typeof obj === 'object' && obj.isSerializedRedirect) {\n return redirect(obj)\n }\n\n return undefined\n}\n"],"names":[],"mappings":"AAGO,MAAM,uBAAuB;AAuD7B,SAAS,SAOd,MACmD;AACnD,OAAK,aAAa,KAAK,cAAc,KAAK,QAAQ;AAClD,QAAM,UAAU,IAAI,QAAQ,KAAK,WAAW,CAAA,CAAE;AAExC,QAAA,WAAW,IAAI,SAAS,MAAM;AAAA,IAClC,QAAQ,KAAK;AAAA,IACb;AAAA,EAAA,CACD;AAEC,WAA+D,UAC/D;AAEF,MAAI,KAAK,OAAO;AACR,UAAA;AAAA,EAAA;AAGD,SAAA;AACT;AAEO,SAAS,WAAW,KAA8B;AACvD,SAAO,eAAe,YAAY,CAAC,CAAE,IAAY;AACnD;AAEO,SAAS,mBAAmB,KAA8B;AAC/D,SAAO,WAAW,GAAG,KAAK,CAAC,CAAC,IAAI,QAAQ;AAC1C;AAEO,SAAS,cAAc,KAAU;AACtC,MAAI,OAAO,QAAQ,YAAY,IAAI,sBAAsB;AACvD,WAAO,SAAS,GAAG;AAAA,EAAA;AAGd,SAAA;AACT;"}
|
package/dist/esm/route.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { RootRouteId } from './root.js';
|
|
|
7
7
|
import { ParseRoute, RouteById, RoutePaths } from './routeInfo.js';
|
|
8
8
|
import { AnyRouter, RegisteredRouter } from './router.js';
|
|
9
9
|
import { BuildLocationFn, NavigateFn } from './RouterProvider.js';
|
|
10
|
-
import { Assign, Constrain, Expand, IntersectAssign, NoInfer } from './utils.js';
|
|
10
|
+
import { Assign, Constrain, Expand, IntersectAssign, LooseAsyncReturnType, LooseReturnType, NoInfer } from './utils.js';
|
|
11
11
|
import { AnySchema, AnyStandardSchemaValidator, AnyValidator, AnyValidatorAdapter, AnyValidatorObj, DefaultValidator, ResolveSearchValidatorInput, ResolveValidatorOutput, StandardSchemaValidator, ValidatorAdapter, ValidatorFn, ValidatorObj } from './validators.js';
|
|
12
12
|
export type AnyPathParams = {};
|
|
13
13
|
export type SearchSchemaInput = {
|
|
@@ -126,8 +126,6 @@ export type RoutePrefix<TPrefix extends string, TPath extends string> = string e
|
|
|
126
126
|
export type TrimPath<T extends string> = '' extends T ? '' : TrimPathRight<TrimPathLeft<T>>;
|
|
127
127
|
export type TrimPathLeft<T extends string> = T extends `${RootRouteId}/${infer U}` ? TrimPathLeft<U> : T extends `/${infer U}` ? TrimPathLeft<U> : T;
|
|
128
128
|
export type TrimPathRight<T extends string> = T extends '/' ? '/' : T extends `${infer U}/` ? TrimPathRight<U> : T;
|
|
129
|
-
export type LooseReturnType<T> = T extends (...args: Array<any>) => infer TReturn ? TReturn : never;
|
|
130
|
-
export type LooseAsyncReturnType<T> = T extends (...args: Array<any>) => infer TReturn ? TReturn extends Promise<infer TReturn> ? TReturn : TReturn : never;
|
|
131
129
|
export type ContextReturnType<TContextFn> = unknown extends TContextFn ? TContextFn : LooseReturnType<TContextFn> extends never ? AnyContext : LooseReturnType<TContextFn>;
|
|
132
130
|
export type ContextAsyncReturnType<TContextFn> = unknown extends TContextFn ? TContextFn : LooseAsyncReturnType<TContextFn> extends never ? AnyContext : LooseAsyncReturnType<TContextFn>;
|
|
133
131
|
export type ResolveRouteContext<TRouteContextFn, TBeforeLoadFn> = Assign<ContextReturnType<TRouteContextFn>, ContextAsyncReturnType<TBeforeLoadFn>>;
|
|
@@ -173,23 +171,23 @@ export interface RouteTypes<in out TParentRoute extends AnyRoute, in out TPath e
|
|
|
173
171
|
fileRouteTypes: TFileRouteTypes;
|
|
174
172
|
}
|
|
175
173
|
export type ResolveFullPath<TParentRoute extends AnyRoute, TPath extends string, TPrefixed = RoutePrefix<TParentRoute['fullPath'], TPath>> = TPrefixed extends RootRouteId ? '/' : TPrefixed;
|
|
176
|
-
export interface RouteExtensions<TId, TFullPath> {
|
|
174
|
+
export interface RouteExtensions<in out TId, in out TFullPath> {
|
|
175
|
+
id: TId;
|
|
176
|
+
fullPath: TFullPath;
|
|
177
177
|
}
|
|
178
|
-
export type RouteLazyFn<TRoute extends AnyRoute> = (lazyFn: () => Promise<LazyRoute
|
|
178
|
+
export type RouteLazyFn<TRoute extends AnyRoute> = (lazyFn: () => Promise<LazyRoute<TRoute>>) => TRoute;
|
|
179
179
|
export type RouteAddChildrenFn<in out TParentRoute extends AnyRoute, in out TPath extends string, in out TFullPath extends string, in out TCustomId extends string, in out TId extends string, in out TSearchValidator, in out TParams, in out TRouterContext, in out TRouteContextFn, in out TBeforeLoadFn, in out TLoaderDeps extends Record<string, any>, in out TLoaderFn, in out TFileRouteTypes> = <const TNewChildren>(children: Constrain<TNewChildren, ReadonlyArray<AnyRoute> | Record<string, AnyRoute>>) => Route<TParentRoute, TPath, TFullPath, TCustomId, TId, TSearchValidator, TParams, TRouterContext, TRouteContextFn, TBeforeLoadFn, TLoaderDeps, TLoaderFn, TNewChildren, TFileRouteTypes>;
|
|
180
180
|
export type RouteAddFileChildrenFn<in out TParentRoute extends AnyRoute, in out TPath extends string, in out TFullPath extends string, in out TCustomId extends string, in out TId extends string, in out TSearchValidator, in out TParams, in out TRouterContext, in out TRouteContextFn, in out TBeforeLoadFn, in out TLoaderDeps extends Record<string, any>, in out TLoaderFn, in out TFileRouteTypes> = <const TNewChildren>(children: TNewChildren) => Route<TParentRoute, TPath, TFullPath, TCustomId, TId, TSearchValidator, TParams, TRouterContext, TRouteContextFn, TBeforeLoadFn, TLoaderDeps, TLoaderFn, TNewChildren, TFileRouteTypes>;
|
|
181
181
|
export type RouteAddFileTypesFn<TParentRoute extends AnyRoute, TPath extends string, TFullPath extends string, TCustomId extends string, TId extends string, TSearchValidator, TParams, TRouterContext, TRouteContextFn, TBeforeLoadFn, TLoaderDeps extends Record<string, any>, TLoaderFn, TChildren> = <TNewFileRouteTypes>() => Route<TParentRoute, TPath, TFullPath, TCustomId, TId, TSearchValidator, TParams, TRouterContext, TRouteContextFn, TBeforeLoadFn, TLoaderDeps, TLoaderFn, TChildren, TNewFileRouteTypes>;
|
|
182
182
|
export interface Route<in out TParentRoute extends AnyRoute, in out TPath extends string, in out TFullPath extends string, in out TCustomId extends string, in out TId extends string, in out TSearchValidator, in out TParams, in out TRouterContext, in out TRouteContextFn, in out TBeforeLoadFn, in out TLoaderDeps extends Record<string, any>, in out TLoaderFn, in out TChildren, in out TFileRouteTypes> extends RouteExtensions<TId, TFullPath> {
|
|
183
|
-
fullPath: TFullPath;
|
|
184
183
|
path: TPath;
|
|
185
|
-
id: TId;
|
|
186
184
|
parentRoute: TParentRoute;
|
|
187
185
|
children?: TChildren;
|
|
188
186
|
types: RouteTypes<TParentRoute, TPath, TFullPath, TCustomId, TId, TSearchValidator, TParams, TRouterContext, TRouteContextFn, TBeforeLoadFn, TLoaderDeps, TLoaderFn, TChildren, TFileRouteTypes>;
|
|
189
187
|
options: RouteOptions<TParentRoute, TId, TCustomId, TFullPath, TPath, TSearchValidator, TParams, TLoaderDeps, TLoaderFn, TRouterContext, TRouteContextFn, TBeforeLoadFn>;
|
|
190
188
|
isRoot: TParentRoute extends AnyRoute ? true : false;
|
|
191
189
|
_componentsPromise?: Promise<Array<void>>;
|
|
192
|
-
lazyFn?: () => Promise<LazyRoute
|
|
190
|
+
lazyFn?: () => Promise<LazyRoute<Route<TParentRoute, TPath, TFullPath, TCustomId, TId, TSearchValidator, TParams, TRouterContext, TRouteContextFn, TBeforeLoadFn, TLoaderDeps, TLoaderFn, TChildren, TFileRouteTypes>>>;
|
|
193
191
|
_lazyPromise?: Promise<void>;
|
|
194
192
|
rank: number;
|
|
195
193
|
to: TrimPathRight<TFullPath>;
|
|
@@ -198,7 +196,7 @@ export interface Route<in out TParentRoute extends AnyRoute, in out TPath extend
|
|
|
198
196
|
defaultSsr?: boolean;
|
|
199
197
|
}) => void;
|
|
200
198
|
update: (options: UpdatableRouteOptions<TParentRoute, TCustomId, TFullPath, TParams, TSearchValidator, TLoaderFn, TLoaderDeps, TRouterContext, TRouteContextFn, TBeforeLoadFn>) => this;
|
|
201
|
-
lazy: RouteLazyFn<
|
|
199
|
+
lazy: RouteLazyFn<Route<TParentRoute, TPath, TFullPath, TCustomId, TId, TSearchValidator, TParams, TRouterContext, TRouteContextFn, TBeforeLoadFn, TLoaderDeps, TLoaderFn, TChildren, TFileRouteTypes>>;
|
|
202
200
|
addChildren: RouteAddChildrenFn<TParentRoute, TPath, TFullPath, TCustomId, TId, TSearchValidator, TParams, TRouterContext, TRouteContextFn, TBeforeLoadFn, TLoaderDeps, TLoaderFn, TFileRouteTypes>;
|
|
203
201
|
_addFileChildren: RouteAddFileChildrenFn<TParentRoute, TPath, TFullPath, TCustomId, TId, TSearchValidator, TParams, TRouterContext, TRouteContextFn, TBeforeLoadFn, TLoaderDeps, TLoaderFn, TFileRouteTypes>;
|
|
204
202
|
_addFileTypes: RouteAddFileTypesFn<TParentRoute, TPath, TFullPath, TCustomId, TId, TSearchValidator, TParams, TRouterContext, TRouteContextFn, TBeforeLoadFn, TLoaderDeps, TLoaderFn, TChildren>;
|
|
@@ -384,7 +382,7 @@ export declare class BaseRoute<in out TParentRoute extends AnyRoute = AnyRoute,
|
|
|
384
382
|
children?: TChildren;
|
|
385
383
|
originalIndex?: number;
|
|
386
384
|
rank: number;
|
|
387
|
-
lazyFn?: () => Promise<LazyRoute
|
|
385
|
+
lazyFn?: () => Promise<LazyRoute<Route<TParentRoute, TPath, TFullPath, TCustomId, TId, TSearchValidator, TParams, TRouterContext, TRouteContextFn, TBeforeLoadFn, TLoaderDeps, TLoaderFn, TChildren, TFileRouteTypes>>>;
|
|
388
386
|
_lazyPromise?: Promise<void>;
|
|
389
387
|
_componentsPromise?: Promise<Array<void>>;
|
|
390
388
|
constructor(options?: RouteOptions<TParentRoute, TId, TCustomId, TFullPath, TPath, TSearchValidator, TParams, TLoaderDeps, TLoaderFn, TRouterContext, TRouteContextFn, TBeforeLoadFn>);
|
|
@@ -393,6 +391,7 @@ export declare class BaseRoute<in out TParentRoute extends AnyRoute = AnyRoute,
|
|
|
393
391
|
originalIndex: number;
|
|
394
392
|
defaultSsr?: boolean;
|
|
395
393
|
}) => void;
|
|
394
|
+
clone: (other: typeof this) => void;
|
|
396
395
|
addChildren: RouteAddChildrenFn<TParentRoute, TPath, TFullPath, TCustomId, TId, TSearchValidator, TParams, TRouterContext, TRouteContextFn, TBeforeLoadFn, TLoaderDeps, TLoaderFn, TFileRouteTypes>;
|
|
397
396
|
_addFileChildren: RouteAddFileChildrenFn<TParentRoute, TPath, TFullPath, TCustomId, TId, TSearchValidator, TParams, TRouterContext, TRouteContextFn, TBeforeLoadFn, TLoaderDeps, TLoaderFn, TFileRouteTypes>;
|
|
398
397
|
_addFileTypes: RouteAddFileTypesFn<TParentRoute, TPath, TFullPath, TCustomId, TId, TSearchValidator, TParams, TRouterContext, TRouteContextFn, TBeforeLoadFn, TLoaderDeps, TLoaderFn, TChildren>;
|
|
@@ -400,7 +399,7 @@ export declare class BaseRoute<in out TParentRoute extends AnyRoute = AnyRoute,
|
|
|
400
399
|
loader: Constrain<TNewLoaderFn, RouteLoaderFn<TParentRoute, TCustomId, TParams, TLoaderDeps, TRouterContext, TRouteContextFn, TBeforeLoadFn>>;
|
|
401
400
|
}) => BaseRoute<TParentRoute, TPath, TFullPath, TCustomId, TId, TSearchValidator, TParams, TRouterContext, TRouteContextFn, TBeforeLoadFn, TLoaderDeps, TNewLoaderFn, TChildren, TFileRouteTypes>;
|
|
402
401
|
update: (options: UpdatableRouteOptions<TParentRoute, TCustomId, TFullPath, TParams, TSearchValidator, TLoaderFn, TLoaderDeps, TRouterContext, TRouteContextFn, TBeforeLoadFn>) => this;
|
|
403
|
-
lazy: RouteLazyFn<
|
|
402
|
+
lazy: RouteLazyFn<Route<TParentRoute, TPath, TFullPath, TCustomId, TId, TSearchValidator, TParams, TRouterContext, TRouteContextFn, TBeforeLoadFn, TLoaderDeps, TLoaderFn, TChildren, TFileRouteTypes>>;
|
|
404
403
|
}
|
|
405
404
|
export declare class BaseRouteApi<TId, TRouter extends AnyRouter = RegisteredRouter> {
|
|
406
405
|
id: TId;
|
package/dist/esm/route.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import invariant from "tiny-invariant";
|
|
1
2
|
import { trimPathLeft, joinPaths } from "./path.js";
|
|
2
3
|
import { notFound } from "./not-found.js";
|
|
3
4
|
import { rootRouteId } from "./root.js";
|
|
@@ -12,7 +13,8 @@ class BaseRoute {
|
|
|
12
13
|
if (isRoot) {
|
|
13
14
|
this._path = rootRouteId;
|
|
14
15
|
} else if (!this.parentRoute) {
|
|
15
|
-
|
|
16
|
+
invariant(
|
|
17
|
+
false,
|
|
16
18
|
`Child Route instances must pass a 'getParentRoute: () => ParentRoute' option that returns a Route instance.`
|
|
17
19
|
);
|
|
18
20
|
}
|
|
@@ -38,6 +40,15 @@ class BaseRoute {
|
|
|
38
40
|
this._to = fullPath;
|
|
39
41
|
this._ssr = (options2 == null ? void 0 : options2.ssr) ?? opts.defaultSsr ?? true;
|
|
40
42
|
};
|
|
43
|
+
this.clone = (other) => {
|
|
44
|
+
this._path = other._path;
|
|
45
|
+
this._id = other._id;
|
|
46
|
+
this._fullPath = other._fullPath;
|
|
47
|
+
this._to = other._to;
|
|
48
|
+
this._ssr = other._ssr;
|
|
49
|
+
this.options.getParentRoute = other.options.getParentRoute;
|
|
50
|
+
this.children = other.children;
|
|
51
|
+
};
|
|
41
52
|
this.addChildren = (children) => {
|
|
42
53
|
return this._addFileChildren(children);
|
|
43
54
|
};
|