@tanstack/react-router 1.22.5 → 1.22.6
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/CatchBoundary.cjs +1 -2
- package/dist/cjs/CatchBoundary.cjs.map +1 -1
- package/dist/cjs/Matches.cjs +12 -18
- package/dist/cjs/Matches.cjs.map +1 -1
- package/dist/cjs/Matches.d.cts +15 -15
- package/dist/cjs/RouterProvider.cjs +16 -15
- package/dist/cjs/RouterProvider.cjs.map +1 -1
- package/dist/cjs/RouterProvider.d.cts +6 -6
- package/dist/cjs/awaited.cjs +1 -1
- package/dist/cjs/awaited.cjs.map +1 -1
- package/dist/cjs/awaited.d.cts +1 -1
- package/dist/cjs/defer.cjs.map +1 -1
- package/dist/cjs/fileRoute.cjs +1 -1
- package/dist/cjs/fileRoute.cjs.map +1 -1
- package/dist/cjs/fileRoute.d.cts +17 -17
- package/dist/cjs/lazyRouteComponent.cjs.map +1 -1
- package/dist/cjs/lazyRouteComponent.d.cts +1 -1
- package/dist/cjs/link.cjs +10 -11
- package/dist/cjs/link.cjs.map +1 -1
- package/dist/cjs/link.d.cts +16 -13
- package/dist/cjs/location.d.cts +2 -2
- package/dist/cjs/not-found.cjs.map +1 -1
- package/dist/cjs/not-found.d.cts +2 -2
- package/dist/cjs/path.cjs +2 -2
- package/dist/cjs/path.cjs.map +1 -1
- package/dist/cjs/path.d.cts +4 -4
- package/dist/cjs/qss.cjs +4 -3
- package/dist/cjs/qss.cjs.map +1 -1
- package/dist/cjs/redirects.cjs.map +1 -1
- package/dist/cjs/redirects.d.cts +5 -5
- package/dist/cjs/route.cjs.map +1 -1
- package/dist/cjs/route.d.cts +34 -36
- package/dist/cjs/routeInfo.d.cts +5 -5
- package/dist/cjs/router.cjs +63 -66
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +28 -28
- package/dist/cjs/routerContext.cjs +1 -1
- package/dist/cjs/routerContext.cjs.map +1 -1
- package/dist/cjs/routerContext.d.cts +1 -1
- package/dist/cjs/scroll-restoration.cjs +7 -9
- package/dist/cjs/scroll-restoration.cjs.map +1 -1
- package/dist/cjs/scroll-restoration.d.cts +1 -1
- package/dist/cjs/searchParams.cjs +10 -12
- package/dist/cjs/searchParams.cjs.map +1 -1
- package/dist/cjs/searchParams.d.cts +1 -1
- package/dist/cjs/useBlocker.cjs.map +1 -1
- package/dist/cjs/useBlocker.d.cts +2 -2
- package/dist/cjs/useNavigate.cjs +1 -1
- package/dist/cjs/useNavigate.cjs.map +1 -1
- package/dist/cjs/useNavigate.d.cts +4 -4
- package/dist/cjs/useParams.cjs +1 -1
- package/dist/cjs/useParams.cjs.map +1 -1
- package/dist/cjs/useParams.d.cts +5 -5
- package/dist/cjs/useRouteContext.cjs +1 -1
- package/dist/cjs/useRouteContext.cjs.map +1 -1
- package/dist/cjs/useRouteContext.d.cts +4 -4
- package/dist/cjs/useRouter.cjs.map +1 -1
- package/dist/cjs/useRouter.d.cts +2 -2
- package/dist/cjs/useRouterState.cjs.map +1 -1
- package/dist/cjs/useRouterState.d.cts +2 -2
- package/dist/cjs/useSearch.cjs +1 -1
- package/dist/cjs/useSearch.cjs.map +1 -1
- package/dist/cjs/useSearch.d.cts +4 -4
- package/dist/cjs/utils.cjs +2 -2
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +13 -11
- package/dist/esm/CatchBoundary.js +1 -2
- package/dist/esm/CatchBoundary.js.map +1 -1
- package/dist/esm/Matches.d.ts +15 -15
- package/dist/esm/Matches.js +12 -18
- package/dist/esm/Matches.js.map +1 -1
- package/dist/esm/RouterProvider.d.ts +6 -6
- package/dist/esm/RouterProvider.js +16 -15
- package/dist/esm/RouterProvider.js.map +1 -1
- package/dist/esm/awaited.d.ts +1 -1
- package/dist/esm/awaited.js +1 -1
- package/dist/esm/awaited.js.map +1 -1
- package/dist/esm/defer.js.map +1 -1
- package/dist/esm/fileRoute.d.ts +17 -17
- package/dist/esm/fileRoute.js +1 -1
- package/dist/esm/fileRoute.js.map +1 -1
- package/dist/esm/lazyRouteComponent.d.ts +1 -1
- package/dist/esm/lazyRouteComponent.js.map +1 -1
- package/dist/esm/link.d.ts +16 -13
- package/dist/esm/link.js +10 -11
- package/dist/esm/link.js.map +1 -1
- package/dist/esm/location.d.ts +2 -2
- package/dist/esm/not-found.d.ts +2 -2
- package/dist/esm/not-found.js.map +1 -1
- package/dist/esm/path.d.ts +4 -4
- package/dist/esm/path.js +2 -2
- package/dist/esm/path.js.map +1 -1
- package/dist/esm/qss.js +4 -3
- package/dist/esm/qss.js.map +1 -1
- package/dist/esm/redirects.d.ts +5 -5
- package/dist/esm/redirects.js.map +1 -1
- package/dist/esm/route.d.ts +34 -36
- package/dist/esm/route.js.map +1 -1
- package/dist/esm/routeInfo.d.ts +5 -5
- package/dist/esm/router.d.ts +28 -28
- package/dist/esm/router.js +63 -66
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/routerContext.d.ts +1 -1
- package/dist/esm/routerContext.js +1 -1
- package/dist/esm/routerContext.js.map +1 -1
- package/dist/esm/scroll-restoration.d.ts +1 -1
- package/dist/esm/scroll-restoration.js +7 -9
- package/dist/esm/scroll-restoration.js.map +1 -1
- package/dist/esm/searchParams.d.ts +1 -1
- package/dist/esm/searchParams.js +10 -12
- package/dist/esm/searchParams.js.map +1 -1
- package/dist/esm/useBlocker.d.ts +2 -2
- package/dist/esm/useBlocker.js.map +1 -1
- package/dist/esm/useNavigate.d.ts +4 -4
- package/dist/esm/useNavigate.js +1 -1
- package/dist/esm/useNavigate.js.map +1 -1
- package/dist/esm/useParams.d.ts +5 -5
- package/dist/esm/useParams.js +1 -1
- package/dist/esm/useParams.js.map +1 -1
- package/dist/esm/useRouteContext.d.ts +4 -4
- package/dist/esm/useRouteContext.js +1 -1
- package/dist/esm/useRouteContext.js.map +1 -1
- package/dist/esm/useRouter.d.ts +2 -2
- package/dist/esm/useRouter.js.map +1 -1
- package/dist/esm/useRouterState.d.ts +2 -2
- package/dist/esm/useRouterState.js.map +1 -1
- package/dist/esm/useSearch.d.ts +4 -4
- package/dist/esm/useSearch.js +1 -1
- package/dist/esm/useSearch.js.map +1 -1
- package/dist/esm/utils.d.ts +13 -11
- package/dist/esm/utils.js +2 -2
- package/dist/esm/utils.js.map +1 -1
- package/package.json +3 -2
- package/src/CatchBoundary.tsx +1 -1
- package/src/Matches.tsx +41 -48
- package/src/RouterProvider.tsx +22 -16
- package/src/awaited.tsx +3 -3
- package/src/defer.ts +1 -0
- package/src/fileRoute.ts +53 -53
- package/src/history.ts +1 -1
- package/src/lazyRouteComponent.tsx +2 -1
- package/src/link.tsx +50 -42
- package/src/location.ts +2 -2
- package/src/not-found.tsx +3 -2
- package/src/path.ts +8 -8
- package/src/qss.ts +4 -5
- package/src/redirects.ts +5 -5
- package/src/route.ts +73 -67
- package/src/routeInfo.ts +8 -6
- package/src/router.ts +150 -145
- package/src/routerContext.tsx +2 -2
- package/src/scroll-restoration.tsx +9 -12
- package/src/searchParams.ts +11 -13
- package/src/useBlocker.tsx +3 -3
- package/src/useNavigate.tsx +7 -5
- package/src/useParams.tsx +6 -6
- package/src/useRouteContext.ts +7 -8
- package/src/useRouter.tsx +2 -2
- package/src/useRouterState.tsx +2 -2
- package/src/useSearch.tsx +7 -6
- package/src/utils.ts +36 -24
package/src/router.ts
CHANGED
|
@@ -1,76 +1,80 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { createBrowserHistory, createMemoryHistory } from '@tanstack/history'
|
|
2
|
+
import { Store } from '@tanstack/react-store'
|
|
3
|
+
import invariant from 'tiny-invariant'
|
|
4
|
+
import warning from 'tiny-warning'
|
|
5
|
+
import { rootRouteId } from './route'
|
|
6
|
+
import { defaultParseSearch, defaultStringifySearch } from './searchParams'
|
|
7
|
+
import {
|
|
8
|
+
deepEqual,
|
|
9
|
+
escapeJSON,
|
|
10
|
+
functionalUpdate,
|
|
11
|
+
isServer,
|
|
12
|
+
last,
|
|
13
|
+
pick,
|
|
14
|
+
replaceEqualDeep,
|
|
15
|
+
} from './utils'
|
|
16
|
+
import { getRouteMatch } from './RouterProvider'
|
|
2
17
|
import {
|
|
18
|
+
cleanPath,
|
|
19
|
+
interpolatePath,
|
|
20
|
+
joinPaths,
|
|
21
|
+
matchPathname,
|
|
22
|
+
parsePathname,
|
|
23
|
+
resolvePath,
|
|
24
|
+
trimPath,
|
|
25
|
+
trimPathLeft,
|
|
26
|
+
trimPathRight,
|
|
27
|
+
} from './path'
|
|
28
|
+
import { isRedirect } from './redirects'
|
|
29
|
+
import { isNotFound } from './not-found'
|
|
30
|
+
import type * as React from 'react'
|
|
31
|
+
import type {
|
|
3
32
|
HistoryLocation,
|
|
4
33
|
HistoryState,
|
|
5
34
|
RouterHistory,
|
|
6
|
-
createBrowserHistory,
|
|
7
|
-
createMemoryHistory,
|
|
8
35
|
} from '@tanstack/history'
|
|
9
|
-
import { Store } from '@tanstack/react-store'
|
|
10
36
|
|
|
11
37
|
//
|
|
12
38
|
|
|
13
|
-
import {
|
|
14
|
-
AnySearchSchema,
|
|
15
|
-
AnyRoute,
|
|
39
|
+
import type {
|
|
16
40
|
AnyContext,
|
|
17
|
-
|
|
18
|
-
|
|
41
|
+
AnyRoute,
|
|
42
|
+
AnySearchSchema,
|
|
19
43
|
LoaderFnContext,
|
|
20
|
-
rootRouteId,
|
|
21
44
|
NotFoundRouteComponent,
|
|
45
|
+
Route,
|
|
46
|
+
RouteMask,
|
|
22
47
|
} from './route'
|
|
23
|
-
import {
|
|
48
|
+
import type {
|
|
24
49
|
FullSearchSchema,
|
|
25
50
|
RouteById,
|
|
26
51
|
RoutePaths,
|
|
27
52
|
RoutesById,
|
|
28
53
|
RoutesByPath,
|
|
29
54
|
} from './routeInfo'
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
32
|
-
PickAsRequired,
|
|
33
|
-
Updater,
|
|
55
|
+
import type {
|
|
34
56
|
NonNullableUpdater,
|
|
35
|
-
|
|
36
|
-
deepEqual,
|
|
37
|
-
escapeJSON,
|
|
38
|
-
functionalUpdate,
|
|
39
|
-
last,
|
|
40
|
-
pick,
|
|
57
|
+
PickAsRequired,
|
|
41
58
|
Timeout,
|
|
42
|
-
|
|
59
|
+
Updater,
|
|
43
60
|
} from './utils'
|
|
44
|
-
import { RouteComponent } from './route'
|
|
45
|
-
import { AnyRouteMatch, MatchRouteOptions, RouteMatch } from './Matches'
|
|
46
|
-
import { ParsedLocation } from './location'
|
|
47
|
-
import {
|
|
48
|
-
import {
|
|
61
|
+
import type { RouteComponent } from './route'
|
|
62
|
+
import type { AnyRouteMatch, MatchRouteOptions, RouteMatch } from './Matches'
|
|
63
|
+
import type { ParsedLocation } from './location'
|
|
64
|
+
import type { SearchParser, SearchSerializer } from './searchParams'
|
|
65
|
+
import type {
|
|
49
66
|
BuildLocationFn,
|
|
50
67
|
CommitLocationOptions,
|
|
51
68
|
InjectedHtmlEntry,
|
|
52
69
|
NavigateFn,
|
|
53
|
-
getRouteMatch,
|
|
54
70
|
} from './RouterProvider'
|
|
55
71
|
|
|
56
|
-
import {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
resolvePath,
|
|
63
|
-
trimPath,
|
|
64
|
-
trimPathLeft,
|
|
65
|
-
trimPathRight,
|
|
66
|
-
} from './path'
|
|
67
|
-
import invariant from 'tiny-invariant'
|
|
68
|
-
import { AnyRedirect, ResolvedRedirect, isRedirect } from './redirects'
|
|
69
|
-
import { NotFoundError, isNotFound } from './not-found'
|
|
70
|
-
import { NavigateOptions, ResolveRelativePath, ToOptions } from './link'
|
|
71
|
-
import { NoInfer } from '@tanstack/react-store'
|
|
72
|
-
import warning from 'tiny-warning'
|
|
73
|
-
import { DeferredPromiseState } from './defer'
|
|
72
|
+
import type { AnyRedirect, ResolvedRedirect } from './redirects'
|
|
73
|
+
|
|
74
|
+
import type { NotFoundError } from './not-found'
|
|
75
|
+
import type { NavigateOptions, ResolveRelativePath, ToOptions } from './link'
|
|
76
|
+
import type { NoInfer } from '@tanstack/react-store'
|
|
77
|
+
import type { DeferredPromiseState } from './defer'
|
|
74
78
|
|
|
75
79
|
//
|
|
76
80
|
|
|
@@ -133,7 +137,7 @@ export interface RouterOptions<
|
|
|
133
137
|
context?: TRouteTree['types']['routerContext']
|
|
134
138
|
dehydrate?: () => TDehydrated
|
|
135
139
|
hydrate?: (dehydrated: TDehydrated) => void
|
|
136
|
-
routeMasks?: RouteMask<TRouteTree
|
|
140
|
+
routeMasks?: Array<RouteMask<TRouteTree>>
|
|
137
141
|
unmaskOnReload?: boolean
|
|
138
142
|
Wrap?: (props: { children: any }) => React.ReactNode
|
|
139
143
|
InnerWrap?: (props: { children: any }) => React.ReactNode
|
|
@@ -161,9 +165,9 @@ export interface RouterState<TRouteTree extends AnyRoute = AnyRoute> {
|
|
|
161
165
|
status: 'pending' | 'idle'
|
|
162
166
|
isLoading: boolean
|
|
163
167
|
isTransitioning: boolean
|
|
164
|
-
matches: RouteMatch<TRouteTree
|
|
165
|
-
pendingMatches?: RouteMatch<TRouteTree
|
|
166
|
-
cachedMatches: RouteMatch<TRouteTree
|
|
168
|
+
matches: Array<RouteMatch<TRouteTree>>
|
|
169
|
+
pendingMatches?: Array<RouteMatch<TRouteTree>>
|
|
170
|
+
cachedMatches: Array<RouteMatch<TRouteTree>>
|
|
167
171
|
location: ParsedLocation<FullSearchSchema<TRouteTree>>
|
|
168
172
|
resolvedLocation: ParsedLocation<FullSearchSchema<TRouteTree>>
|
|
169
173
|
lastUpdated: number
|
|
@@ -191,7 +195,7 @@ export interface BuildNextOptions {
|
|
|
191
195
|
}
|
|
192
196
|
|
|
193
197
|
export interface DehydratedRouterState {
|
|
194
|
-
dehydratedMatches: DehydratedRouteMatch
|
|
198
|
+
dehydratedMatches: Array<DehydratedRouteMatch>
|
|
195
199
|
}
|
|
196
200
|
|
|
197
201
|
export type DehydratedRouteMatch = Pick<
|
|
@@ -264,11 +268,11 @@ export class Router<
|
|
|
264
268
|
tempLocationKey: string | undefined = `${Math.round(
|
|
265
269
|
Math.random() * 10000000,
|
|
266
270
|
)}`
|
|
267
|
-
resetNextScroll
|
|
271
|
+
resetNextScroll = true
|
|
268
272
|
navigateTimeout: Timeout | null = null
|
|
269
273
|
latestLoadPromise: Promise<void> = Promise.resolve()
|
|
270
274
|
subscribers = new Set<RouterListener<RouterEvent>>()
|
|
271
|
-
injectedHtml: InjectedHtmlEntry
|
|
275
|
+
injectedHtml: Array<InjectedHtmlEntry> = []
|
|
272
276
|
dehydratedData?: TDehydrated
|
|
273
277
|
|
|
274
278
|
// Must build in constructor
|
|
@@ -288,7 +292,7 @@ export class Router<
|
|
|
288
292
|
routeTree!: TRouteTree
|
|
289
293
|
routesById!: RoutesById<TRouteTree>
|
|
290
294
|
routesByPath!: RoutesByPath<TRouteTree>
|
|
291
|
-
flatRoutes!: AnyRoute
|
|
295
|
+
flatRoutes!: Array<AnyRoute>
|
|
292
296
|
|
|
293
297
|
/**
|
|
294
298
|
* @deprecated Use the `createRouter` function instead
|
|
@@ -306,9 +310,9 @@ export class Router<
|
|
|
306
310
|
defaultPendingMinMs: 500,
|
|
307
311
|
context: undefined!,
|
|
308
312
|
...options,
|
|
309
|
-
stringifySearch: options
|
|
310
|
-
parseSearch: options
|
|
311
|
-
transformer: options
|
|
313
|
+
stringifySearch: options.stringifySearch ?? defaultStringifySearch,
|
|
314
|
+
parseSearch: options.parseSearch ?? defaultParseSearch,
|
|
315
|
+
transformer: options.transformer ?? JSON,
|
|
312
316
|
})
|
|
313
317
|
|
|
314
318
|
if (typeof document !== 'undefined') {
|
|
@@ -356,6 +360,7 @@ export class Router<
|
|
|
356
360
|
}
|
|
357
361
|
|
|
358
362
|
if (
|
|
363
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
359
364
|
!this.history ||
|
|
360
365
|
(this.options.history && this.options.history !== this.history)
|
|
361
366
|
) {
|
|
@@ -374,6 +379,7 @@ export class Router<
|
|
|
374
379
|
this.buildRouteTree()
|
|
375
380
|
}
|
|
376
381
|
|
|
382
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
377
383
|
if (!this.__store) {
|
|
378
384
|
this.__store = new Store(getInitialRouterState(this.latestLocation), {
|
|
379
385
|
onUpdate: () => {
|
|
@@ -406,7 +412,7 @@ export class Router<
|
|
|
406
412
|
;(this.routesById as any)[notFoundRoute.id] = notFoundRoute
|
|
407
413
|
}
|
|
408
414
|
|
|
409
|
-
const recurseRoutes = (childRoutes: AnyRoute
|
|
415
|
+
const recurseRoutes = (childRoutes: Array<AnyRoute>) => {
|
|
410
416
|
childRoutes.forEach((childRoute, i) => {
|
|
411
417
|
childRoute.init({ originalIndex: i })
|
|
412
418
|
|
|
@@ -428,7 +434,7 @@ export class Router<
|
|
|
428
434
|
}
|
|
429
435
|
}
|
|
430
436
|
|
|
431
|
-
const children = childRoute.children
|
|
437
|
+
const children = childRoute.children
|
|
432
438
|
|
|
433
439
|
if (children?.length) {
|
|
434
440
|
recurseRoutes(children)
|
|
@@ -438,15 +444,18 @@ export class Router<
|
|
|
438
444
|
|
|
439
445
|
recurseRoutes([this.routeTree])
|
|
440
446
|
|
|
441
|
-
const scoredRoutes: {
|
|
447
|
+
const scoredRoutes: Array<{
|
|
442
448
|
child: AnyRoute
|
|
443
449
|
trimmed: string
|
|
444
450
|
parsed: ReturnType<typeof parsePathname>
|
|
445
451
|
index: number
|
|
446
|
-
scores: number
|
|
447
|
-
}
|
|
452
|
+
scores: Array<number>
|
|
453
|
+
}> = []
|
|
454
|
+
|
|
455
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
456
|
+
const routes = Object.values(this.routesById) as Array<AnyRoute>
|
|
448
457
|
|
|
449
|
-
|
|
458
|
+
routes.forEach((d, i) => {
|
|
450
459
|
if (d.isRoot || !d.path) {
|
|
451
460
|
return
|
|
452
461
|
}
|
|
@@ -458,16 +467,16 @@ export class Router<
|
|
|
458
467
|
parsed.shift()
|
|
459
468
|
}
|
|
460
469
|
|
|
461
|
-
const scores = parsed.map((
|
|
462
|
-
if (
|
|
470
|
+
const scores = parsed.map((segment) => {
|
|
471
|
+
if (segment.value === '/') {
|
|
463
472
|
return 0.75
|
|
464
473
|
}
|
|
465
474
|
|
|
466
|
-
if (
|
|
475
|
+
if (segment.type === 'param') {
|
|
467
476
|
return 0.5
|
|
468
477
|
}
|
|
469
478
|
|
|
470
|
-
if (
|
|
479
|
+
if (segment.type === 'wildcard') {
|
|
471
480
|
return 0.25
|
|
472
481
|
}
|
|
473
482
|
|
|
@@ -496,7 +505,7 @@ export class Router<
|
|
|
496
505
|
// Sort by min available parsed value
|
|
497
506
|
for (let i = 0; i < minLength; i++) {
|
|
498
507
|
if (a.parsed[i]!.value !== b.parsed[i]!.value) {
|
|
499
|
-
return a.parsed[i]!.value
|
|
508
|
+
return a.parsed[i]!.value > b.parsed[i]!.value ? 1 : -1
|
|
500
509
|
}
|
|
501
510
|
}
|
|
502
511
|
|
|
@@ -557,13 +566,13 @@ export class Router<
|
|
|
557
566
|
search: replaceEqualDeep(previousLocation?.search, parsedSearch) as any,
|
|
558
567
|
hash: hash.split('#').reverse()[0] ?? '',
|
|
559
568
|
href: `${pathname}${searchStr}${hash}`,
|
|
560
|
-
state: replaceEqualDeep(previousLocation?.state, state)
|
|
569
|
+
state: replaceEqualDeep(previousLocation?.state, state),
|
|
561
570
|
}
|
|
562
571
|
}
|
|
563
572
|
|
|
564
573
|
const location = parse(this.history.location)
|
|
565
574
|
|
|
566
|
-
|
|
575
|
+
const { __tempLocation, __tempKey } = location.state
|
|
567
576
|
|
|
568
577
|
if (__tempLocation && (!__tempKey || __tempKey === this.tempLocationKey)) {
|
|
569
578
|
// Sync up the location keys
|
|
@@ -582,21 +591,22 @@ export class Router<
|
|
|
582
591
|
}
|
|
583
592
|
|
|
584
593
|
resolvePathWithBase = (from: string, path: string) => {
|
|
585
|
-
return resolvePath(this.basepath
|
|
594
|
+
return resolvePath(this.basepath, from, cleanPath(path))
|
|
586
595
|
}
|
|
587
596
|
|
|
588
597
|
get looseRoutesById() {
|
|
589
598
|
return this.routesById as Record<string, AnyRoute>
|
|
590
599
|
}
|
|
591
600
|
|
|
601
|
+
// eslint-disable-next-line no-shadow
|
|
592
602
|
matchRoutes = <TRouteTree extends AnyRoute>(
|
|
593
603
|
pathname: string,
|
|
594
604
|
locationSearch: AnySearchSchema,
|
|
595
605
|
opts?: { preload?: boolean; throwOnError?: boolean; debug?: boolean },
|
|
596
|
-
): RouteMatch<TRouteTree
|
|
606
|
+
): Array<RouteMatch<TRouteTree>> => {
|
|
597
607
|
let routeParams: Record<string, string> = {}
|
|
598
608
|
|
|
599
|
-
|
|
609
|
+
const foundRoute = this.flatRoutes.find((route) => {
|
|
600
610
|
const matchedParams = matchPathname(
|
|
601
611
|
this.basepath,
|
|
602
612
|
trimPathRight(pathname),
|
|
@@ -619,7 +629,7 @@ export class Router<
|
|
|
619
629
|
let routeCursor: AnyRoute =
|
|
620
630
|
foundRoute || (this.routesById as any)[rootRouteId]
|
|
621
631
|
|
|
622
|
-
|
|
632
|
+
const matchedRoutes: Array<AnyRoute> = [routeCursor]
|
|
623
633
|
|
|
624
634
|
let isGlobalNotFound = false
|
|
625
635
|
|
|
@@ -640,9 +650,9 @@ export class Router<
|
|
|
640
650
|
}
|
|
641
651
|
}
|
|
642
652
|
|
|
643
|
-
while (routeCursor
|
|
653
|
+
while (routeCursor.parentRoute) {
|
|
644
654
|
routeCursor = routeCursor.parentRoute
|
|
645
|
-
|
|
655
|
+
matchedRoutes.unshift(routeCursor)
|
|
646
656
|
}
|
|
647
657
|
|
|
648
658
|
const globalNotFoundRouteId = (() => {
|
|
@@ -689,7 +699,7 @@ export class Router<
|
|
|
689
699
|
return
|
|
690
700
|
})
|
|
691
701
|
|
|
692
|
-
const matches: AnyRouteMatch
|
|
702
|
+
const matches: Array<AnyRouteMatch> = []
|
|
693
703
|
|
|
694
704
|
matchedRoutes.forEach((route, index) => {
|
|
695
705
|
// Take each matched route and resolve + validate its search params
|
|
@@ -712,7 +722,7 @@ export class Router<
|
|
|
712
722
|
? route.options.validateSearch.parse
|
|
713
723
|
: route.options.validateSearch
|
|
714
724
|
|
|
715
|
-
|
|
725
|
+
const search = validator?.(parentSearch) ?? {}
|
|
716
726
|
|
|
717
727
|
return [
|
|
718
728
|
{
|
|
@@ -722,15 +732,15 @@ export class Router<
|
|
|
722
732
|
undefined,
|
|
723
733
|
]
|
|
724
734
|
} catch (err: any) {
|
|
725
|
-
const
|
|
735
|
+
const searchParamError = new SearchParamError(err.message, {
|
|
726
736
|
cause: err,
|
|
727
737
|
})
|
|
728
738
|
|
|
729
739
|
if (opts?.throwOnError) {
|
|
730
|
-
throw
|
|
740
|
+
throw searchParamError
|
|
731
741
|
}
|
|
732
742
|
|
|
733
|
-
return [parentSearch,
|
|
743
|
+
return [parentSearch, searchParamError]
|
|
734
744
|
}
|
|
735
745
|
})()
|
|
736
746
|
|
|
@@ -761,7 +771,7 @@ export class Router<
|
|
|
761
771
|
// Waste not, want not. If we already have a match for this route,
|
|
762
772
|
// reuse it. This is important for layout routes, which might stick
|
|
763
773
|
// around between navigation actions that only change leaf routes.
|
|
764
|
-
|
|
774
|
+
const existingMatch = getRouteMatch(this.state, matchId)
|
|
765
775
|
|
|
766
776
|
const cause = this.state.matches.find((d) => d.id === matchId)
|
|
767
777
|
? 'stay'
|
|
@@ -832,7 +842,7 @@ export class Router<
|
|
|
832
842
|
dest: BuildNextOptions & {
|
|
833
843
|
unmaskOnReload?: boolean
|
|
834
844
|
} = {},
|
|
835
|
-
matches?: AnyRouteMatch
|
|
845
|
+
matches?: Array<AnyRouteMatch>,
|
|
836
846
|
): ParsedLocation => {
|
|
837
847
|
// if (dest.href) {
|
|
838
848
|
// return {
|
|
@@ -848,6 +858,7 @@ export class Router<
|
|
|
848
858
|
|
|
849
859
|
const relevantMatches = this.state.pendingMatches || this.state.matches
|
|
850
860
|
const fromSearch =
|
|
861
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
851
862
|
relevantMatches[relevantMatches.length - 1]?.search ||
|
|
852
863
|
this.latestLocation.search
|
|
853
864
|
|
|
@@ -856,7 +867,7 @@ export class Router<
|
|
|
856
867
|
fromSearch,
|
|
857
868
|
)
|
|
858
869
|
const stayingMatches = matches?.filter((d) =>
|
|
859
|
-
fromMatches
|
|
870
|
+
fromMatches.find((e) => e.routeId === d.routeId),
|
|
860
871
|
)
|
|
861
872
|
|
|
862
873
|
const fromRoute = this.looseRoutesById[last(fromMatches)?.routeId]
|
|
@@ -873,14 +884,14 @@ export class Router<
|
|
|
873
884
|
let nextParams =
|
|
874
885
|
(dest.params ?? true) === true
|
|
875
886
|
? prevParams
|
|
876
|
-
: { ...prevParams, ...functionalUpdate(dest.params
|
|
887
|
+
: { ...prevParams, ...functionalUpdate(dest.params, prevParams) }
|
|
877
888
|
|
|
878
889
|
if (Object.keys(nextParams).length > 0) {
|
|
879
890
|
matches
|
|
880
891
|
?.map((d) => this.looseRoutesById[d.routeId]!.options.stringifyParams)
|
|
881
892
|
.filter(Boolean)
|
|
882
893
|
.forEach((fn) => {
|
|
883
|
-
nextParams = { ...nextParams!, ...fn!(nextParams
|
|
894
|
+
nextParams = { ...nextParams!, ...fn!(nextParams) }
|
|
884
895
|
})
|
|
885
896
|
}
|
|
886
897
|
|
|
@@ -912,11 +923,8 @@ export class Router<
|
|
|
912
923
|
.filter(Boolean) ?? []
|
|
913
924
|
|
|
914
925
|
// Pre filters first
|
|
915
|
-
const preFilteredSearch = preSearchFilters
|
|
916
|
-
? preSearchFilters
|
|
917
|
-
(prev, next) => next(prev) as any,
|
|
918
|
-
fromSearch,
|
|
919
|
-
)
|
|
926
|
+
const preFilteredSearch = preSearchFilters.length
|
|
927
|
+
? preSearchFilters.reduce((prev, next) => next(prev), fromSearch)
|
|
920
928
|
: fromSearch
|
|
921
929
|
|
|
922
930
|
// Then the link/navigate function
|
|
@@ -924,13 +932,13 @@ export class Router<
|
|
|
924
932
|
dest.search === true
|
|
925
933
|
? preFilteredSearch // Preserve resolvedFrom true
|
|
926
934
|
: dest.search
|
|
927
|
-
? functionalUpdate(dest.search, preFilteredSearch)
|
|
928
|
-
: preSearchFilters
|
|
935
|
+
? functionalUpdate(dest.search, preFilteredSearch) // Updater
|
|
936
|
+
: preSearchFilters.length
|
|
929
937
|
? preFilteredSearch // Preserve resolvedFrom filters
|
|
930
938
|
: {}
|
|
931
939
|
|
|
932
940
|
// Then post filters
|
|
933
|
-
const postFilteredSearch = postSearchFilters
|
|
941
|
+
const postFilteredSearch = postSearchFilters.length
|
|
934
942
|
? postSearchFilters.reduce((prev, next) => next(prev), destSearch)
|
|
935
943
|
: destSearch
|
|
936
944
|
|
|
@@ -942,7 +950,7 @@ export class Router<
|
|
|
942
950
|
dest.hash === true
|
|
943
951
|
? this.latestLocation.hash
|
|
944
952
|
: dest.hash
|
|
945
|
-
? functionalUpdate(dest.hash
|
|
953
|
+
? functionalUpdate(dest.hash, this.latestLocation.hash)
|
|
946
954
|
: undefined
|
|
947
955
|
|
|
948
956
|
const hashStr = hash ? `#${hash}` : ''
|
|
@@ -971,13 +979,13 @@ export class Router<
|
|
|
971
979
|
dest: BuildNextOptions = {},
|
|
972
980
|
maskedDest?: BuildNextOptions,
|
|
973
981
|
) => {
|
|
974
|
-
|
|
982
|
+
const next = build(dest)
|
|
975
983
|
let maskedNext = maskedDest ? build(maskedDest) : undefined
|
|
976
984
|
|
|
977
985
|
if (!maskedNext) {
|
|
978
986
|
let params = {}
|
|
979
987
|
|
|
980
|
-
|
|
988
|
+
const foundMask = this.options.routeMasks?.find((d) => {
|
|
981
989
|
const match = matchPathname(this.basepath, next.pathname, {
|
|
982
990
|
to: d.from,
|
|
983
991
|
caseSensitive: false,
|
|
@@ -1040,6 +1048,7 @@ export class Router<
|
|
|
1040
1048
|
// If the next urls are the same and we're not replacing,
|
|
1041
1049
|
// do nothing
|
|
1042
1050
|
if (!isSameUrl) {
|
|
1051
|
+
// eslint-disable-next-line prefer-const
|
|
1043
1052
|
let { maskedLocation, ...nextHistory } = next
|
|
1044
1053
|
|
|
1045
1054
|
if (maskedLocation) {
|
|
@@ -1140,9 +1149,9 @@ export class Router<
|
|
|
1140
1149
|
}: {
|
|
1141
1150
|
checkLatest: () => Promise<void> | undefined
|
|
1142
1151
|
location: ParsedLocation
|
|
1143
|
-
matches: AnyRouteMatch
|
|
1152
|
+
matches: Array<AnyRouteMatch>
|
|
1144
1153
|
preload?: boolean
|
|
1145
|
-
}): Promise<RouteMatch
|
|
1154
|
+
}): Promise<Array<RouteMatch>> => {
|
|
1146
1155
|
let latestPromise
|
|
1147
1156
|
let firstBadMatchIndex: number | undefined
|
|
1148
1157
|
|
|
@@ -1189,6 +1198,7 @@ export class Router<
|
|
|
1189
1198
|
}
|
|
1190
1199
|
|
|
1191
1200
|
// Check each match middleware to see if the route can be accessed
|
|
1201
|
+
// eslint-disable-next-line prefer-const
|
|
1192
1202
|
for (let [index, match] of matches.entries()) {
|
|
1193
1203
|
const parentMatch = matches[index - 1]
|
|
1194
1204
|
const route = this.looseRoutesById[match.routeId]!
|
|
@@ -1280,10 +1290,11 @@ export class Router<
|
|
|
1280
1290
|
}
|
|
1281
1291
|
|
|
1282
1292
|
const validResolvedMatches = matches.slice(0, firstBadMatchIndex)
|
|
1283
|
-
const matchPromises: Promise<any
|
|
1293
|
+
const matchPromises: Array<Promise<any>> = []
|
|
1284
1294
|
|
|
1285
1295
|
validResolvedMatches.forEach((match, index) => {
|
|
1286
1296
|
matchPromises.push(
|
|
1297
|
+
// eslint-disable-next-line no-async-promise-executor
|
|
1287
1298
|
new Promise<void>(async (resolve, reject) => {
|
|
1288
1299
|
const parentMatchPromise = matchPromises[index - 1]
|
|
1289
1300
|
const route = this.looseRoutesById[match.routeId]!
|
|
@@ -1409,13 +1420,14 @@ export class Router<
|
|
|
1409
1420
|
meta,
|
|
1410
1421
|
headers,
|
|
1411
1422
|
}
|
|
1412
|
-
} catch (
|
|
1423
|
+
} catch (e) {
|
|
1424
|
+
let error = e
|
|
1413
1425
|
if ((latestPromise = checkLatest())) return await latestPromise
|
|
1414
1426
|
|
|
1415
|
-
handleError(
|
|
1427
|
+
handleError(e)
|
|
1416
1428
|
|
|
1417
1429
|
try {
|
|
1418
|
-
route.options.onError?.(
|
|
1430
|
+
route.options.onError?.(e)
|
|
1419
1431
|
} catch (onErrorError) {
|
|
1420
1432
|
error = onErrorError
|
|
1421
1433
|
handleError(onErrorError)
|
|
@@ -1435,20 +1447,18 @@ export class Router<
|
|
|
1435
1447
|
// This is where all of the stale-while-revalidate magic happens
|
|
1436
1448
|
const age = Date.now() - match.updatedAt
|
|
1437
1449
|
|
|
1438
|
-
|
|
1450
|
+
const staleAge = preload
|
|
1439
1451
|
? route.options.preloadStaleTime ??
|
|
1440
1452
|
this.options.defaultPreloadStaleTime ??
|
|
1441
1453
|
30_000 // 30 seconds for preloads by default
|
|
1442
1454
|
: route.options.staleTime ?? this.options.defaultStaleTime ?? 0
|
|
1443
1455
|
|
|
1444
|
-
// Default to reloading the route all the time
|
|
1445
|
-
let shouldReload
|
|
1446
|
-
|
|
1447
1456
|
const shouldReloadOption = route.options.shouldReload
|
|
1448
1457
|
|
|
1458
|
+
// Default to reloading the route all the time
|
|
1449
1459
|
// Allow shouldReload to get the last say,
|
|
1450
1460
|
// if provided.
|
|
1451
|
-
shouldReload =
|
|
1461
|
+
const shouldReload =
|
|
1452
1462
|
typeof shouldReloadOption === 'function'
|
|
1453
1463
|
? shouldReloadOption(loaderContext)
|
|
1454
1464
|
: shouldReloadOption
|
|
@@ -1550,10 +1560,11 @@ export class Router<
|
|
|
1550
1560
|
}
|
|
1551
1561
|
|
|
1552
1562
|
load = async (): Promise<void> => {
|
|
1563
|
+
// eslint-disable-next-line no-async-promise-executor
|
|
1553
1564
|
const promise = new Promise<void>(async (resolve, reject) => {
|
|
1554
1565
|
const next = this.latestLocation
|
|
1555
1566
|
const prevLocation = this.state.resolvedLocation
|
|
1556
|
-
const pathDidChange = prevLocation
|
|
1567
|
+
const pathDidChange = prevLocation.href !== next.href
|
|
1557
1568
|
let latestPromise: Promise<void> | undefined | null
|
|
1558
1569
|
|
|
1559
1570
|
// Cancel any pending matches
|
|
@@ -1566,7 +1577,7 @@ export class Router<
|
|
|
1566
1577
|
pathChanged: pathDidChange,
|
|
1567
1578
|
})
|
|
1568
1579
|
|
|
1569
|
-
let pendingMatches!: RouteMatch<any, any
|
|
1580
|
+
let pendingMatches!: Array<RouteMatch<any, any>>
|
|
1570
1581
|
const previousMatches = this.state.matches
|
|
1571
1582
|
|
|
1572
1583
|
this.__store.batch(() => {
|
|
@@ -1591,8 +1602,8 @@ export class Router<
|
|
|
1591
1602
|
})
|
|
1592
1603
|
|
|
1593
1604
|
try {
|
|
1594
|
-
let redirect: ResolvedRedirect
|
|
1595
|
-
let notFound: NotFoundError
|
|
1605
|
+
let redirect: ResolvedRedirect | undefined
|
|
1606
|
+
let notFound: NotFoundError | undefined
|
|
1596
1607
|
|
|
1597
1608
|
try {
|
|
1598
1609
|
// Load the matches
|
|
@@ -1695,7 +1706,7 @@ export class Router<
|
|
|
1695
1706
|
}
|
|
1696
1707
|
|
|
1697
1708
|
resolveRedirect = (err: AnyRedirect): ResolvedRedirect => {
|
|
1698
|
-
|
|
1709
|
+
const redirect = err as ResolvedRedirect
|
|
1699
1710
|
|
|
1700
1711
|
if (!redirect.href) {
|
|
1701
1712
|
redirect.href = this.buildLocation(redirect as any).href
|
|
@@ -1737,8 +1748,8 @@ export class Router<
|
|
|
1737
1748
|
TMaskTo extends string = '',
|
|
1738
1749
|
>(
|
|
1739
1750
|
opts: NavigateOptions<TRouteTree, TFrom, TTo, TMaskFrom, TMaskTo>,
|
|
1740
|
-
): Promise<AnyRouteMatch
|
|
1741
|
-
|
|
1751
|
+
): Promise<Array<AnyRouteMatch> | undefined> => {
|
|
1752
|
+
const next = this.buildLocation(opts as any)
|
|
1742
1753
|
|
|
1743
1754
|
let matches = this.matchRoutes(next.pathname, next.search, {
|
|
1744
1755
|
throwOnError: true,
|
|
@@ -1750,7 +1761,7 @@ export class Router<
|
|
|
1750
1761
|
...this.state.matches,
|
|
1751
1762
|
...(this.state.pendingMatches ?? []),
|
|
1752
1763
|
...this.state.cachedMatches,
|
|
1753
|
-
]
|
|
1764
|
+
].map((d) => [d.id, true]),
|
|
1754
1765
|
)
|
|
1755
1766
|
|
|
1756
1767
|
this.__store.batch(() => {
|
|
@@ -1809,9 +1820,6 @@ export class Router<
|
|
|
1809
1820
|
? this.latestLocation
|
|
1810
1821
|
: this.state.resolvedLocation
|
|
1811
1822
|
|
|
1812
|
-
if (!baseLocation) {
|
|
1813
|
-
return false
|
|
1814
|
-
}
|
|
1815
1823
|
const match = matchPathname(this.basepath, baseLocation.pathname, {
|
|
1816
1824
|
...opts,
|
|
1817
1825
|
to: next.pathname,
|
|
@@ -1884,7 +1892,7 @@ export class Router<
|
|
|
1884
1892
|
/**
|
|
1885
1893
|
* @deprecated Please extract your own data from scripts injected using the `injectHtml` method
|
|
1886
1894
|
*/
|
|
1887
|
-
hydrateData = <T
|
|
1895
|
+
hydrateData = <T = unknown>(key: any) => {
|
|
1888
1896
|
warning(
|
|
1889
1897
|
false,
|
|
1890
1898
|
`The hydrateData method is deprecated. Please use the extractHtml method to extract your own data.`,
|
|
@@ -1939,7 +1947,7 @@ export class Router<
|
|
|
1939
1947
|
this.options.hydrate?.(ctx.payload as any)
|
|
1940
1948
|
const dehydratedState = ctx.router.state
|
|
1941
1949
|
|
|
1942
|
-
|
|
1950
|
+
const matches = this.matchRoutes(
|
|
1943
1951
|
this.state.location.pathname,
|
|
1944
1952
|
this.state.location.search,
|
|
1945
1953
|
).map((match) => {
|
|
@@ -1952,29 +1960,26 @@ export class Router<
|
|
|
1952
1960
|
`Could not find a client-side match for dehydrated match with id: ${match.id}!`,
|
|
1953
1961
|
)
|
|
1954
1962
|
|
|
1955
|
-
|
|
1956
|
-
const route = this.looseRoutesById[match.routeId]!
|
|
1963
|
+
const route = this.looseRoutesById[match.routeId]!
|
|
1957
1964
|
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1965
|
+
const assets =
|
|
1966
|
+
dehydratedMatch.status === 'notFound' ||
|
|
1967
|
+
dehydratedMatch.status === 'redirected'
|
|
1968
|
+
? {}
|
|
1969
|
+
: {
|
|
1970
|
+
meta: route.options.meta?.({
|
|
1971
|
+
params: match.params,
|
|
1972
|
+
loaderData: dehydratedMatch.loaderData,
|
|
1973
|
+
}),
|
|
1974
|
+
links: route.options.links?.(),
|
|
1975
|
+
scripts: route.options.scripts?.(),
|
|
1976
|
+
}
|
|
1970
1977
|
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
}
|
|
1978
|
+
return {
|
|
1979
|
+
...match,
|
|
1980
|
+
...dehydratedMatch,
|
|
1981
|
+
...assets,
|
|
1976
1982
|
}
|
|
1977
|
-
return match
|
|
1978
1983
|
})
|
|
1979
1984
|
|
|
1980
1985
|
this.__store.setState((s) => {
|
|
@@ -1986,7 +1991,7 @@ export class Router<
|
|
|
1986
1991
|
})
|
|
1987
1992
|
}
|
|
1988
1993
|
|
|
1989
|
-
handleNotFound = (matches: AnyRouteMatch
|
|
1994
|
+
handleNotFound = (matches: Array<AnyRouteMatch>, err: NotFoundError) => {
|
|
1990
1995
|
const matchesByRouteId = Object.fromEntries(
|
|
1991
1996
|
matches.map((match) => [match.routeId, match]),
|
|
1992
1997
|
) as Record<string, AnyRouteMatch>
|
|
@@ -2004,7 +2009,7 @@ export class Router<
|
|
|
2004
2009
|
!this.options.defaultNotFoundComponent &&
|
|
2005
2010
|
routeCursor.id !== rootRouteId
|
|
2006
2011
|
) {
|
|
2007
|
-
routeCursor = routeCursor
|
|
2012
|
+
routeCursor = routeCursor.parentRoute
|
|
2008
2013
|
|
|
2009
2014
|
invariant(
|
|
2010
2015
|
routeCursor,
|
|
@@ -2012,7 +2017,7 @@ export class Router<
|
|
|
2012
2017
|
)
|
|
2013
2018
|
}
|
|
2014
2019
|
|
|
2015
|
-
|
|
2020
|
+
const match = matchesByRouteId[routeCursor.id]
|
|
2016
2021
|
|
|
2017
2022
|
invariant(match, 'Could not find match for route: ' + routeCursor.id)
|
|
2018
2023
|
|
|
@@ -2041,7 +2046,7 @@ export class Router<
|
|
|
2041
2046
|
// proxy arguments from the caller to the imported function, retaining all type
|
|
2042
2047
|
// information along the way
|
|
2043
2048
|
export function lazyFn<
|
|
2044
|
-
T extends Record<string, (...args: any
|
|
2049
|
+
T extends Record<string, (...args: Array<any>) => any>,
|
|
2045
2050
|
TKey extends keyof T = 'default',
|
|
2046
2051
|
>(fn: () => Promise<T>, key?: TKey) {
|
|
2047
2052
|
return async (
|