@tanstack/router-core 1.168.17 → 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/Matches.cjs +1 -1
- package/dist/cjs/Matches.cjs.map +1 -1
- package/dist/cjs/config.cjs +1 -1
- package/dist/cjs/config.cjs.map +1 -1
- package/dist/cjs/defer.cjs +1 -1
- package/dist/cjs/defer.cjs.map +1 -1
- package/dist/cjs/index.cjs +1 -0
- package/dist/cjs/index.d.cts +1 -1
- package/dist/cjs/isServer/client.cjs +1 -1
- package/dist/cjs/isServer/client.cjs.map +1 -1
- package/dist/cjs/isServer/development.cjs +1 -1
- package/dist/cjs/isServer/development.cjs.map +1 -1
- package/dist/cjs/isServer/server.cjs +1 -1
- package/dist/cjs/isServer/server.cjs.map +1 -1
- package/dist/cjs/link.cjs +1 -1
- package/dist/cjs/link.cjs.map +1 -1
- package/dist/cjs/load-matches.cjs +19 -19
- package/dist/cjs/load-matches.cjs.map +1 -1
- package/dist/cjs/new-process-route-tree.cjs +36 -48
- 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/root.cjs +1 -1
- package/dist/cjs/root.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 +36 -21
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +3 -4
- package/dist/cjs/scroll-restoration-script/server.cjs +1 -1
- package/dist/cjs/scroll-restoration-script/server.cjs.map +1 -1
- package/dist/cjs/scroll-restoration.cjs +6 -6
- package/dist/cjs/scroll-restoration.cjs.map +1 -1
- package/dist/cjs/searchParams.cjs +2 -2
- package/dist/cjs/searchParams.cjs.map +1 -1
- package/dist/cjs/ssr/constants.cjs +2 -2
- package/dist/cjs/ssr/constants.cjs.map +1 -1
- package/dist/cjs/ssr/serializer/RawStream.cjs +12 -12
- package/dist/cjs/ssr/serializer/RawStream.cjs.map +1 -1
- package/dist/cjs/ssr/serializer/ShallowErrorPlugin.cjs +1 -1
- package/dist/cjs/ssr/serializer/ShallowErrorPlugin.cjs.map +1 -1
- package/dist/cjs/ssr/serializer/seroval-plugins.cjs +1 -1
- package/dist/cjs/ssr/serializer/seroval-plugins.cjs.map +1 -1
- package/dist/cjs/ssr/ssr-server.cjs +9 -9
- package/dist/cjs/ssr/ssr-server.cjs.map +1 -1
- package/dist/cjs/ssr/transformStreamWithRouter.cjs +6 -6
- package/dist/cjs/ssr/transformStreamWithRouter.cjs.map +1 -1
- package/dist/cjs/utils.cjs +12 -7
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +1 -0
- package/dist/esm/Matches.js +1 -1
- package/dist/esm/Matches.js.map +1 -1
- package/dist/esm/config.js +1 -1
- package/dist/esm/config.js.map +1 -1
- package/dist/esm/defer.js +1 -1
- package/dist/esm/defer.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +2 -2
- package/dist/esm/isServer/client.js +1 -1
- package/dist/esm/isServer/client.js.map +1 -1
- package/dist/esm/isServer/development.js +1 -1
- package/dist/esm/isServer/development.js.map +1 -1
- package/dist/esm/isServer/server.js +1 -1
- package/dist/esm/isServer/server.js.map +1 -1
- package/dist/esm/link.js +1 -1
- package/dist/esm/link.js.map +1 -1
- package/dist/esm/load-matches.js +19 -19
- package/dist/esm/load-matches.js.map +1 -1
- package/dist/esm/new-process-route-tree.d.ts +4 -26
- package/dist/esm/new-process-route-tree.js +36 -49
- 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/root.js +1 -1
- package/dist/esm/root.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 +38 -23
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/scroll-restoration-script/server.js +1 -1
- package/dist/esm/scroll-restoration-script/server.js.map +1 -1
- package/dist/esm/scroll-restoration.js +6 -6
- package/dist/esm/scroll-restoration.js.map +1 -1
- package/dist/esm/searchParams.js +2 -2
- package/dist/esm/searchParams.js.map +1 -1
- package/dist/esm/ssr/constants.js +2 -2
- package/dist/esm/ssr/constants.js.map +1 -1
- package/dist/esm/ssr/serializer/RawStream.js +10 -10
- package/dist/esm/ssr/serializer/RawStream.js.map +1 -1
- package/dist/esm/ssr/serializer/ShallowErrorPlugin.js +1 -1
- package/dist/esm/ssr/serializer/ShallowErrorPlugin.js.map +1 -1
- package/dist/esm/ssr/serializer/seroval-plugins.js +1 -1
- package/dist/esm/ssr/serializer/seroval-plugins.js.map +1 -1
- package/dist/esm/ssr/ssr-server.js +9 -9
- package/dist/esm/ssr/ssr-server.js.map +1 -1
- package/dist/esm/ssr/transformStreamWithRouter.js +6 -6
- package/dist/esm/ssr/transformStreamWithRouter.js.map +1 -1
- package/dist/esm/utils.d.ts +1 -0
- package/dist/esm/utils.js +12 -8
- 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/src/path.ts
CHANGED
|
@@ -167,33 +167,7 @@ export function resolvePath({
|
|
|
167
167
|
}
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
-
|
|
171
|
-
let joined = ''
|
|
172
|
-
for (let i = 0; i < baseSegments.length; i++) {
|
|
173
|
-
if (i > 0) joined += '/'
|
|
174
|
-
const part = baseSegments[i]!
|
|
175
|
-
if (!part) continue
|
|
176
|
-
segment = parseSegment(part, 0, segment)
|
|
177
|
-
const kind = segment[0]
|
|
178
|
-
if (kind === SEGMENT_TYPE_PATHNAME) {
|
|
179
|
-
joined += part
|
|
180
|
-
continue
|
|
181
|
-
}
|
|
182
|
-
const end = segment[5]
|
|
183
|
-
const prefix = part.substring(0, segment[1])
|
|
184
|
-
const suffix = part.substring(segment[4], end)
|
|
185
|
-
const value = part.substring(segment[2], segment[3])
|
|
186
|
-
if (kind === SEGMENT_TYPE_PARAM) {
|
|
187
|
-
joined += prefix || suffix ? `${prefix}{$${value}}${suffix}` : `$${value}`
|
|
188
|
-
} else if (kind === SEGMENT_TYPE_WILDCARD) {
|
|
189
|
-
joined += prefix || suffix ? `${prefix}{$}${suffix}` : '$'
|
|
190
|
-
} else {
|
|
191
|
-
// SEGMENT_TYPE_OPTIONAL_PARAM
|
|
192
|
-
joined += `${prefix}{-$${value}}${suffix}`
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
joined = cleanPath(joined)
|
|
196
|
-
const result = joined || '/'
|
|
170
|
+
const result = cleanPath(baseSegments.join('/')) || '/'
|
|
197
171
|
if (key && cache) cache.set(key, result)
|
|
198
172
|
return result
|
|
199
173
|
}
|
package/src/route.ts
CHANGED
|
@@ -173,9 +173,11 @@ export type ResolveParams<
|
|
|
173
173
|
|
|
174
174
|
export type ParseParamsFn<in out TPath extends string, in out TParams> = (
|
|
175
175
|
rawParams: Expand<ResolveParams<TPath>>,
|
|
176
|
-
) =>
|
|
177
|
-
|
|
178
|
-
|
|
176
|
+
) =>
|
|
177
|
+
| (TParams extends ResolveParams<TPath, any>
|
|
178
|
+
? TParams
|
|
179
|
+
: ResolveParams<TPath, any>)
|
|
180
|
+
| false
|
|
179
181
|
|
|
180
182
|
export type StringifyParamsFn<in out TPath extends string, in out TParams> = (
|
|
181
183
|
params: TParams,
|
|
@@ -1248,37 +1250,6 @@ export interface UpdatableRouteOptions<
|
|
|
1248
1250
|
in out TBeforeLoadFn,
|
|
1249
1251
|
>
|
|
1250
1252
|
extends UpdatableStaticRouteOption, UpdatableRouteOptionsExtensions {
|
|
1251
|
-
/**
|
|
1252
|
-
* Options to control route matching behavior with runtime code.
|
|
1253
|
-
*
|
|
1254
|
-
* @experimental 🚧 this feature is subject to change
|
|
1255
|
-
*
|
|
1256
|
-
* @link https://tanstack.com/router/latest/docs/framework/react/api/router/RouteOptionsType
|
|
1257
|
-
*/
|
|
1258
|
-
skipRouteOnParseError?: {
|
|
1259
|
-
/**
|
|
1260
|
-
* If `true`, skip this route during matching if `params.parse` fails.
|
|
1261
|
-
*
|
|
1262
|
-
* Without this option, a `/$param` route could match *any* value for `param`,
|
|
1263
|
-
* and only later during the route lifecycle would `params.parse` run and potentially
|
|
1264
|
-
* show the `errorComponent` if validation failed.
|
|
1265
|
-
*
|
|
1266
|
-
* With this option enabled, the route will only match if `params.parse` succeeds.
|
|
1267
|
-
* If it fails, the router will continue trying to match other routes, potentially
|
|
1268
|
-
* finding a different route that works, or ultimately showing the `notFoundComponent`.
|
|
1269
|
-
*
|
|
1270
|
-
* @default false
|
|
1271
|
-
*/
|
|
1272
|
-
params?: boolean
|
|
1273
|
-
/**
|
|
1274
|
-
* In cases where multiple routes would need to run `params.parse` during matching
|
|
1275
|
-
* to determine which route to pick, this priority number can be used as a tie-breaker
|
|
1276
|
-
* for which route to try first. Higher number = higher priority.
|
|
1277
|
-
*
|
|
1278
|
-
* @default 0
|
|
1279
|
-
*/
|
|
1280
|
-
priority?: number
|
|
1281
|
-
}
|
|
1282
1253
|
/**
|
|
1283
1254
|
* If true, this route will be matched as case-sensitive
|
|
1284
1255
|
*
|
package/src/router.ts
CHANGED
|
@@ -8,12 +8,14 @@ import {
|
|
|
8
8
|
encodePathLikeUrl,
|
|
9
9
|
findLast,
|
|
10
10
|
functionalUpdate,
|
|
11
|
+
hasKeys,
|
|
11
12
|
isDangerousProtocol,
|
|
12
13
|
last,
|
|
13
14
|
nullReplaceEqualDeep,
|
|
14
15
|
replaceEqualDeep,
|
|
15
16
|
} from './utils'
|
|
16
17
|
import {
|
|
18
|
+
buildRouteBranch,
|
|
17
19
|
findFlatMatch,
|
|
18
20
|
findRouteMatch,
|
|
19
21
|
findSingleMatch,
|
|
@@ -732,8 +734,6 @@ export type GetMatchRoutesFn = (pathname: string) => {
|
|
|
732
734
|
matchedRoutes: ReadonlyArray<AnyRoute>
|
|
733
735
|
/** exhaustive params, still in their string form */
|
|
734
736
|
routeParams: Record<string, string>
|
|
735
|
-
/** partial params, parsed from routeParams during matching */
|
|
736
|
-
parsedParams: Record<string, unknown> | undefined
|
|
737
737
|
foundRoute: AnyRoute | undefined
|
|
738
738
|
parseError?: unknown
|
|
739
739
|
}
|
|
@@ -972,6 +972,7 @@ export class RouterCore<
|
|
|
972
972
|
routesByPath!: RoutesByPath<TRouteTree>
|
|
973
973
|
processedTree!: ProcessedTree<TRouteTree, any, any>
|
|
974
974
|
resolvePathCache!: LRUCache<string, string>
|
|
975
|
+
private routeBranchCache = new WeakMap<AnyRoute, ReadonlyArray<AnyRoute>>()
|
|
975
976
|
isServer!: boolean
|
|
976
977
|
pathParamsDecoder?: (encoded: string) => string
|
|
977
978
|
protocolAllowlist!: Set<string>
|
|
@@ -1343,15 +1344,23 @@ export class RouterCore<
|
|
|
1343
1344
|
return location
|
|
1344
1345
|
}
|
|
1345
1346
|
|
|
1346
|
-
/** Resolve a path
|
|
1347
|
+
/** Resolve a path using the router's trailing-slash policy. */
|
|
1347
1348
|
resolvePathWithBase = (from: string, path: string) => {
|
|
1348
|
-
|
|
1349
|
+
return resolvePath({
|
|
1349
1350
|
base: from,
|
|
1350
|
-
to: cleanPath(path),
|
|
1351
|
+
to: path.includes('//') ? cleanPath(path) : path,
|
|
1351
1352
|
trailingSlash: this.options.trailingSlash,
|
|
1352
1353
|
cache: this.resolvePathCache,
|
|
1353
1354
|
})
|
|
1354
|
-
|
|
1355
|
+
}
|
|
1356
|
+
|
|
1357
|
+
private getRouteBranch(route: AnyRoute) {
|
|
1358
|
+
let branch = this.routeBranchCache.get(route)
|
|
1359
|
+
if (!branch) {
|
|
1360
|
+
branch = buildRouteBranch(route)
|
|
1361
|
+
this.routeBranchCache.set(route, branch)
|
|
1362
|
+
}
|
|
1363
|
+
return branch
|
|
1355
1364
|
}
|
|
1356
1365
|
|
|
1357
1366
|
get looseRoutesById() {
|
|
@@ -1391,7 +1400,7 @@ export class RouterCore<
|
|
|
1391
1400
|
opts?: MatchRoutesOpts,
|
|
1392
1401
|
): Array<AnyRouteMatch> {
|
|
1393
1402
|
const matchedRoutesResult = this.getMatchedRoutes(next.pathname)
|
|
1394
|
-
const { foundRoute, routeParams
|
|
1403
|
+
const { foundRoute, routeParams } = matchedRoutesResult
|
|
1395
1404
|
let { matchedRoutes } = matchedRoutesResult
|
|
1396
1405
|
let isGlobalNotFound = false
|
|
1397
1406
|
|
|
@@ -1517,7 +1526,7 @@ export class RouterCore<
|
|
|
1517
1526
|
|
|
1518
1527
|
if (!existingMatch) {
|
|
1519
1528
|
try {
|
|
1520
|
-
extractStrictParams(route,
|
|
1529
|
+
extractStrictParams(route, strictParams)
|
|
1521
1530
|
} catch (err: any) {
|
|
1522
1531
|
if (isNotFound(err) || isRedirect(err)) {
|
|
1523
1532
|
paramsError = err
|
|
@@ -1687,7 +1696,7 @@ export class RouterCore<
|
|
|
1687
1696
|
search: Record<string, unknown>
|
|
1688
1697
|
params: Record<string, unknown>
|
|
1689
1698
|
} {
|
|
1690
|
-
const { matchedRoutes, routeParams
|
|
1699
|
+
const { matchedRoutes, routeParams } = this.getMatchedRoutes(
|
|
1691
1700
|
location.pathname,
|
|
1692
1701
|
)
|
|
1693
1702
|
const lastRoute = last(matchedRoutes)!
|
|
@@ -1734,12 +1743,7 @@ export class RouterCore<
|
|
|
1734
1743
|
)
|
|
1735
1744
|
for (const route of matchedRoutes) {
|
|
1736
1745
|
try {
|
|
1737
|
-
extractStrictParams(
|
|
1738
|
-
route,
|
|
1739
|
-
routeParams,
|
|
1740
|
-
parsedParams ?? {},
|
|
1741
|
-
strictParams,
|
|
1742
|
-
)
|
|
1746
|
+
extractStrictParams(route, strictParams)
|
|
1743
1747
|
} catch {
|
|
1744
1748
|
// Ignore errors, we're not actually routing
|
|
1745
1749
|
}
|
|
@@ -1835,9 +1839,7 @@ export class RouterCore<
|
|
|
1835
1839
|
dest.unsafeRelative === 'path'
|
|
1836
1840
|
? currentLocation.pathname
|
|
1837
1841
|
: (dest.from ?? lightweightResult.fullPath)
|
|
1838
|
-
|
|
1839
|
-
// ensure this includes the basePath if set
|
|
1840
|
-
const fromPath = this.resolvePathWithBase(defaultedFromPath, '.')
|
|
1842
|
+
const destTo = dest.to ? `${dest.to}` : undefined
|
|
1841
1843
|
|
|
1842
1844
|
// From search should always use the current location
|
|
1843
1845
|
const fromSearch = lightweightResult.search
|
|
@@ -1847,11 +1849,15 @@ export class RouterCore<
|
|
|
1847
1849
|
lightweightResult.params,
|
|
1848
1850
|
)
|
|
1849
1851
|
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1852
|
+
const isAbsoluteTo = destTo?.charCodeAt(0) === 47
|
|
1853
|
+
const sourcePath = isAbsoluteTo
|
|
1854
|
+
? '/'
|
|
1855
|
+
: this.resolvePathWithBase(defaultedFromPath, '.')
|
|
1856
|
+
|
|
1857
|
+
// Resolve the destination. Absolute destinations don't need the source path.
|
|
1858
|
+
const nextTo = destTo
|
|
1859
|
+
? this.resolvePathWithBase(sourcePath, destTo)
|
|
1860
|
+
: sourcePath
|
|
1855
1861
|
|
|
1856
1862
|
// Resolve the next params
|
|
1857
1863
|
const nextParams =
|
|
@@ -1864,24 +1870,33 @@ export class RouterCore<
|
|
|
1864
1870
|
functionalUpdate(dest.params as any, fromParams),
|
|
1865
1871
|
)
|
|
1866
1872
|
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
let destRoutes
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1873
|
+
const destRoute = this.routesByPath[
|
|
1874
|
+
trimPathRight(nextTo) as keyof typeof this.routesByPath
|
|
1875
|
+
] as AnyRoute | undefined
|
|
1876
|
+
|
|
1877
|
+
let destRoutes: ReadonlyArray<AnyRoute>
|
|
1878
|
+
if (destRoute) {
|
|
1879
|
+
destRoutes = this.getRouteBranch(destRoute)
|
|
1880
|
+
} else if (nextTo.includes('$')) {
|
|
1881
|
+
// Route templates must match routesByPath exactly. A miss here is a
|
|
1882
|
+
// typed destination mismatch, not a concrete URL to route-match.
|
|
1883
|
+
destRoutes = []
|
|
1884
|
+
} else {
|
|
1885
|
+
const destMatchResult = this.getMatchedRoutes(nextTo)
|
|
1886
|
+
destRoutes = destMatchResult.matchedRoutes
|
|
1878
1887
|
|
|
1879
|
-
|
|
1880
|
-
|
|
1888
|
+
if (
|
|
1889
|
+
this.options.notFoundRoute &&
|
|
1890
|
+
(!destMatchResult.foundRoute ||
|
|
1891
|
+
(destMatchResult.foundRoute.path !== '/' &&
|
|
1892
|
+
destMatchResult.routeParams['**']))
|
|
1893
|
+
) {
|
|
1894
|
+
destRoutes = [...destRoutes, this.options.notFoundRoute]
|
|
1895
|
+
}
|
|
1881
1896
|
}
|
|
1882
1897
|
|
|
1883
1898
|
// If there are any params, we need to stringify them
|
|
1884
|
-
if (
|
|
1899
|
+
if (destRoutes.length && hasKeys(nextParams)) {
|
|
1885
1900
|
for (const route of destRoutes) {
|
|
1886
1901
|
const fn =
|
|
1887
1902
|
route.options.params?.stringify ?? route.options.stringifyParams
|
|
@@ -1900,8 +1915,7 @@ export class RouterCore<
|
|
|
1900
1915
|
}
|
|
1901
1916
|
|
|
1902
1917
|
const nextPathname = opts.leaveParams
|
|
1903
|
-
? //
|
|
1904
|
-
// This preserves the original parameter syntax including optional parameters
|
|
1918
|
+
? // Keep path params uninterpolated for matchRoute/template matching.
|
|
1905
1919
|
nextTo
|
|
1906
1920
|
: decodePath(
|
|
1907
1921
|
interpolatePath({
|
|
@@ -1912,6 +1926,24 @@ export class RouterCore<
|
|
|
1912
1926
|
}).interpolatedPath,
|
|
1913
1927
|
).path
|
|
1914
1928
|
|
|
1929
|
+
if (
|
|
1930
|
+
process.env.NODE_ENV !== 'production' &&
|
|
1931
|
+
destRoute &&
|
|
1932
|
+
!opts.leaveParams
|
|
1933
|
+
) {
|
|
1934
|
+
try {
|
|
1935
|
+
const roundTrip = this.getMatchedRoutes(nextPathname)
|
|
1936
|
+
if (roundTrip.foundRoute?.id !== destRoute.id) {
|
|
1937
|
+
console.warn(
|
|
1938
|
+
`Generated path "${nextPathname}" for route "${destRoute.id}" did not match the same route after params.stringify.`,
|
|
1939
|
+
)
|
|
1940
|
+
}
|
|
1941
|
+
} catch {
|
|
1942
|
+
// Ignore roundtrip validation errors. The generated location will be
|
|
1943
|
+
// handled by the normal navigation flow.
|
|
1944
|
+
}
|
|
1945
|
+
}
|
|
1946
|
+
|
|
1915
1947
|
// Resolve the next search
|
|
1916
1948
|
let nextSearch = fromSearch
|
|
1917
1949
|
if (opts._includeValidateSearch && this.options.search?.strict) {
|
|
@@ -3015,17 +3047,15 @@ export function getMatchedRoutes<TRouteLike extends RouteLike>({
|
|
|
3015
3047
|
const trimmedPath = trimPathRight(pathname)
|
|
3016
3048
|
|
|
3017
3049
|
let foundRoute: TRouteLike | undefined = undefined
|
|
3018
|
-
let parsedParams: Record<string, unknown> | undefined = undefined
|
|
3019
3050
|
const match = findRouteMatch<TRouteLike>(trimmedPath, processedTree, true)
|
|
3020
3051
|
if (match) {
|
|
3021
3052
|
foundRoute = match.route
|
|
3022
3053
|
Object.assign(routeParams, match.rawParams) // Copy params, because they're cached
|
|
3023
|
-
parsedParams = Object.assign(Object.create(null), match.parsedParams)
|
|
3024
3054
|
}
|
|
3025
3055
|
|
|
3026
3056
|
const matchedRoutes = match?.branch || [routesById[rootRouteId]!]
|
|
3027
3057
|
|
|
3028
|
-
return { matchedRoutes, routeParams, foundRoute
|
|
3058
|
+
return { matchedRoutes, routeParams, foundRoute }
|
|
3029
3059
|
}
|
|
3030
3060
|
|
|
3031
3061
|
/**
|
|
@@ -3177,22 +3207,14 @@ function findGlobalNotFoundRouteId(
|
|
|
3177
3207
|
|
|
3178
3208
|
function extractStrictParams(
|
|
3179
3209
|
route: AnyRoute,
|
|
3180
|
-
referenceParams: Record<string, unknown>,
|
|
3181
|
-
parsedParams: Record<string, unknown>,
|
|
3182
3210
|
accumulatedParams: Record<string, unknown>,
|
|
3183
3211
|
) {
|
|
3184
3212
|
const parseParams = route.options.params?.parse ?? route.options.parseParams
|
|
3185
3213
|
if (parseParams) {
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
if (key in parsedParams) {
|
|
3190
|
-
accumulatedParams[key] = parsedParams[key]
|
|
3191
|
-
}
|
|
3192
|
-
}
|
|
3193
|
-
} else {
|
|
3194
|
-
const result = parseParams(accumulatedParams as Record<string, string>)
|
|
3195
|
-
Object.assign(accumulatedParams, result)
|
|
3214
|
+
const result = parseParams(accumulatedParams as Record<string, string>)
|
|
3215
|
+
if (result === false) {
|
|
3216
|
+
throw new Error('Route params.parse returned false for a matched route')
|
|
3196
3217
|
}
|
|
3218
|
+
Object.assign(accumulatedParams, result)
|
|
3197
3219
|
}
|
|
3198
3220
|
}
|
package/src/utils.ts
CHANGED
|
@@ -215,6 +215,13 @@ export function functionalUpdate<TPrevious, TResult = TPrevious>(
|
|
|
215
215
|
const hasOwn = Object.prototype.hasOwnProperty
|
|
216
216
|
const isEnumerable = Object.prototype.propertyIsEnumerable
|
|
217
217
|
|
|
218
|
+
export function hasKeys(obj: Record<string, unknown>) {
|
|
219
|
+
for (const key in obj) {
|
|
220
|
+
if (hasOwn.call(obj, key)) return true
|
|
221
|
+
}
|
|
222
|
+
return false
|
|
223
|
+
}
|
|
224
|
+
|
|
218
225
|
const createNull = () => Object.create(null)
|
|
219
226
|
export const nullReplaceEqualDeep: typeof replaceEqualDeep = (prev, next) =>
|
|
220
227
|
replaceEqualDeep(prev, next, createNull)
|