@tanstack/router-core 0.0.1-alpha.8 → 0.0.1-beta.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/build/cjs/packages/router-core/src/route.js +35 -0
- package/build/cjs/packages/router-core/src/route.js.map +1 -1
- package/build/cjs/packages/router-core/src/routeConfig.js.map +1 -1
- package/build/cjs/packages/router-core/src/routeMatch.js +33 -27
- package/build/cjs/packages/router-core/src/routeMatch.js.map +1 -1
- package/build/cjs/packages/router-core/src/router.js +214 -211
- package/build/cjs/packages/router-core/src/router.js.map +1 -1
- package/build/esm/index.js +282 -238
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +136 -136
- package/build/types/index.d.ts +85 -37
- package/build/umd/index.development.js +282 -238
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js +1 -1
- package/build/umd/index.production.js.map +1 -1
- package/package.json +1 -1
- package/src/frameworks.ts +0 -1
- package/src/link.ts +48 -18
- package/src/route.ts +64 -2
- package/src/routeConfig.ts +27 -55
- package/src/routeMatch.ts +54 -37
- package/src/router.ts +347 -301
package/package.json
CHANGED
package/src/frameworks.ts
CHANGED
package/src/link.ts
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
RouteInfoByPath,
|
|
6
6
|
} from './routeInfo'
|
|
7
7
|
import { Location } from './router'
|
|
8
|
-
import { NoInfer, PickAsRequired, PickRequired, Updater } from './utils'
|
|
8
|
+
import { Expand, NoInfer, PickAsRequired, PickRequired, Updater } from './utils'
|
|
9
9
|
|
|
10
10
|
export type LinkInfo =
|
|
11
11
|
| {
|
|
@@ -35,23 +35,25 @@ type CleanPath<T extends string> = T extends `${infer L}//${infer R}`
|
|
|
35
35
|
? `/${CleanPath<L>}`
|
|
36
36
|
: T
|
|
37
37
|
|
|
38
|
-
export type Split<S,
|
|
38
|
+
export type Split<S, TIncludeTrailingSlash = true> = S extends unknown
|
|
39
39
|
? string extends S
|
|
40
40
|
? string[]
|
|
41
41
|
: S extends string
|
|
42
42
|
? CleanPath<S> extends ''
|
|
43
43
|
? []
|
|
44
|
-
:
|
|
44
|
+
: TIncludeTrailingSlash extends true
|
|
45
45
|
? CleanPath<S> extends `${infer T}/`
|
|
46
|
-
? [T
|
|
46
|
+
? [...Split<T>, '/']
|
|
47
47
|
: CleanPath<S> extends `/${infer U}`
|
|
48
|
-
?
|
|
48
|
+
? Split<U>
|
|
49
49
|
: CleanPath<S> extends `${infer T}/${infer U}`
|
|
50
|
-
? [T
|
|
50
|
+
? [...Split<T>, ...Split<U>]
|
|
51
51
|
: [S]
|
|
52
52
|
: CleanPath<S> extends `${infer T}/${infer U}`
|
|
53
|
-
? [T
|
|
54
|
-
:
|
|
53
|
+
? [...Split<T>, ...Split<U>]
|
|
54
|
+
: S extends string
|
|
55
|
+
? [S]
|
|
56
|
+
: never
|
|
55
57
|
: never
|
|
56
58
|
: never
|
|
57
59
|
|
|
@@ -128,7 +130,7 @@ export type ToOptions<
|
|
|
128
130
|
from?: TFrom
|
|
129
131
|
// // When using relative route paths, this option forces resolution from the current path, instead of the route API's path or `from` path
|
|
130
132
|
// fromCurrent?: boolean
|
|
131
|
-
} & CheckPath<TAllRouteInfo, NoInfer<TResolvedTo
|
|
133
|
+
} & CheckPath<TAllRouteInfo, NoInfer<TResolvedTo>, {}> &
|
|
132
134
|
SearchParamOptions<TAllRouteInfo, TFrom, TResolvedTo> &
|
|
133
135
|
PathParamOptions<TAllRouteInfo, TFrom, TResolvedTo>
|
|
134
136
|
|
|
@@ -220,8 +222,10 @@ export type LinkOptions<
|
|
|
220
222
|
activeOptions?: ActiveOptions
|
|
221
223
|
// If set, will preload the linked route on hover and cache it for this many milliseconds in hopes that the user will eventually navigate there.
|
|
222
224
|
preload?: false | 'intent'
|
|
223
|
-
// When preloaded
|
|
225
|
+
// When preloaded, the preloaded result will be considered "fresh" for this duration in milliseconds
|
|
224
226
|
preloadMaxAge?: number
|
|
227
|
+
// When preloaded and subsequently inactive, the preloaded result will remain in memory for this duration in milliseconds
|
|
228
|
+
preloadGcMaxAge?: number
|
|
225
229
|
// Delay intent preloading by this many milliseconds. If the intent exits before this delay, the preload will be cancelled.
|
|
226
230
|
preloadDelay?: number
|
|
227
231
|
// If true, will render the link without the href attribute
|
|
@@ -246,19 +250,41 @@ export type CheckRelativePath<
|
|
|
246
250
|
: {}
|
|
247
251
|
: {}
|
|
248
252
|
|
|
249
|
-
export type CheckPath<
|
|
253
|
+
export type CheckPath<
|
|
254
|
+
TAllRouteInfo extends AnyAllRouteInfo,
|
|
250
255
|
TPath,
|
|
251
|
-
|
|
252
|
-
> extends never
|
|
253
|
-
?
|
|
256
|
+
TPass,
|
|
257
|
+
> = Exclude<TPath, TAllRouteInfo['routePaths']> extends never
|
|
258
|
+
? TPass
|
|
254
259
|
: CheckPathError<TAllRouteInfo, Exclude<TPath, TAllRouteInfo['routePaths']>>
|
|
255
260
|
|
|
256
|
-
export type CheckPathError<
|
|
261
|
+
export type CheckPathError<
|
|
262
|
+
TAllRouteInfo extends AnyAllRouteInfo,
|
|
263
|
+
TInvalids,
|
|
264
|
+
> = Expand<{
|
|
257
265
|
Error: `${TInvalids extends string
|
|
258
266
|
? TInvalids
|
|
259
267
|
: never} is not a valid route path.`
|
|
260
268
|
'Valid Route Paths': TAllRouteInfo['routePaths']
|
|
261
|
-
}
|
|
269
|
+
}>
|
|
270
|
+
|
|
271
|
+
export type CheckId<
|
|
272
|
+
TAllRouteInfo extends AnyAllRouteInfo,
|
|
273
|
+
TPath,
|
|
274
|
+
TPass,
|
|
275
|
+
> = Exclude<TPath, TAllRouteInfo['routeIds']> extends never
|
|
276
|
+
? TPass
|
|
277
|
+
: CheckIdError<TAllRouteInfo, Exclude<TPath, TAllRouteInfo['routeIds']>>
|
|
278
|
+
|
|
279
|
+
export type CheckIdError<
|
|
280
|
+
TAllRouteInfo extends AnyAllRouteInfo,
|
|
281
|
+
TInvalids,
|
|
282
|
+
> = Expand<{
|
|
283
|
+
Error: `${TInvalids extends string
|
|
284
|
+
? TInvalids
|
|
285
|
+
: never} is not a valid route ID.`
|
|
286
|
+
'Valid Route IDs': TAllRouteInfo['routeIds']
|
|
287
|
+
}>
|
|
262
288
|
|
|
263
289
|
export type ResolveRelativePath<TFrom, TTo = '.'> = TFrom extends string
|
|
264
290
|
? TTo extends string
|
|
@@ -272,10 +298,14 @@ export type ResolveRelativePath<TFrom, TTo = '.'> = TFrom extends string
|
|
|
272
298
|
? TTo
|
|
273
299
|
: Split<TTo> extends ['..', ...infer ToRest]
|
|
274
300
|
? Split<TFrom> extends [...infer FromRest, infer FromTail]
|
|
275
|
-
?
|
|
301
|
+
? ToRest extends ['/']
|
|
302
|
+
? Join<[...FromRest, '/']>
|
|
303
|
+
: ResolveRelativePath<Join<FromRest>, Join<ToRest>>
|
|
276
304
|
: never
|
|
277
305
|
: Split<TTo> extends ['.', ...infer ToRest]
|
|
278
|
-
?
|
|
306
|
+
? ToRest extends ['/']
|
|
307
|
+
? Join<[TFrom, '/']>
|
|
308
|
+
: ResolveRelativePath<TFrom, Join<ToRest>>
|
|
279
309
|
: CleanPath<Join<['/', ...Split<TFrom>, ...Split<TTo>]>>
|
|
280
310
|
: never
|
|
281
311
|
: never
|
package/src/route.ts
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
ResolveRelativePath,
|
|
6
6
|
ToOptions,
|
|
7
7
|
} from './link'
|
|
8
|
-
import { RouteConfig, RouteOptions } from './routeConfig'
|
|
8
|
+
import { LoaderContext, RouteConfig, RouteOptions } from './routeConfig'
|
|
9
9
|
import {
|
|
10
10
|
AnyAllRouteInfo,
|
|
11
11
|
AnyRouteInfo,
|
|
@@ -14,7 +14,14 @@ import {
|
|
|
14
14
|
RouteInfoByPath,
|
|
15
15
|
} from './routeInfo'
|
|
16
16
|
import { RouteMatch } from './routeMatch'
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
Action,
|
|
19
|
+
ActionState,
|
|
20
|
+
Loader,
|
|
21
|
+
LoaderState,
|
|
22
|
+
MatchRouteOptions,
|
|
23
|
+
Router,
|
|
24
|
+
} from './router'
|
|
18
25
|
import { NoInfer, replaceEqualDeep } from './utils'
|
|
19
26
|
|
|
20
27
|
export interface AnyRoute extends Route<any, any> {}
|
|
@@ -57,6 +64,21 @@ export interface Route<
|
|
|
57
64
|
| Action<TRouteInfo['actionPayload'], TRouteInfo['actionResponse']>
|
|
58
65
|
| undefined
|
|
59
66
|
: Action<TRouteInfo['actionPayload'], TRouteInfo['actionResponse']>
|
|
67
|
+
loader: unknown extends TRouteInfo['routeLoaderData']
|
|
68
|
+
?
|
|
69
|
+
| Action<
|
|
70
|
+
LoaderContext<
|
|
71
|
+
TRouteInfo['fullSearchSchema'],
|
|
72
|
+
TRouteInfo['allParams']
|
|
73
|
+
>,
|
|
74
|
+
TRouteInfo['routeLoaderData']
|
|
75
|
+
>
|
|
76
|
+
| undefined
|
|
77
|
+
: Loader<
|
|
78
|
+
TRouteInfo['fullSearchSchema'],
|
|
79
|
+
TRouteInfo['allParams'],
|
|
80
|
+
TRouteInfo['routeLoaderData']
|
|
81
|
+
>
|
|
60
82
|
}
|
|
61
83
|
|
|
62
84
|
export function createRoute<
|
|
@@ -126,6 +148,45 @@ export function createRoute<
|
|
|
126
148
|
return router.state.actions[id]!
|
|
127
149
|
})()
|
|
128
150
|
|
|
151
|
+
const loader =
|
|
152
|
+
router.state.loaders[id] ||
|
|
153
|
+
(() => {
|
|
154
|
+
router.state.loaders[id] = {
|
|
155
|
+
pending: [],
|
|
156
|
+
fetch: (async (loaderContext: LoaderContext<any, any>) => {
|
|
157
|
+
if (!route) {
|
|
158
|
+
return
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const loaderState: LoaderState<any, any> = {
|
|
162
|
+
loadedAt: Date.now(),
|
|
163
|
+
loaderContext,
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
loader.current = loaderState
|
|
167
|
+
loader.latest = loaderState
|
|
168
|
+
loader.pending.push(loaderState)
|
|
169
|
+
|
|
170
|
+
// router.state = {
|
|
171
|
+
// ...router.state,
|
|
172
|
+
// currentAction: loaderState,
|
|
173
|
+
// latestAction: loaderState,
|
|
174
|
+
// }
|
|
175
|
+
|
|
176
|
+
router.notify()
|
|
177
|
+
|
|
178
|
+
try {
|
|
179
|
+
return await route.options.loader?.(loaderContext)
|
|
180
|
+
} finally {
|
|
181
|
+
loader.pending = loader.pending.filter((d) => d !== loaderState)
|
|
182
|
+
// router.removeActionQueue.push({ loader, loaderState })
|
|
183
|
+
router.notify()
|
|
184
|
+
}
|
|
185
|
+
}) as any,
|
|
186
|
+
}
|
|
187
|
+
return router.state.loaders[id]!
|
|
188
|
+
})()
|
|
189
|
+
|
|
129
190
|
let route: Route<TAllRouteInfo, TRouteInfo> = {
|
|
130
191
|
routeId: id,
|
|
131
192
|
routeRouteId: routeId,
|
|
@@ -136,6 +197,7 @@ export function createRoute<
|
|
|
136
197
|
childRoutes: undefined!,
|
|
137
198
|
parentRoute: parent,
|
|
138
199
|
action,
|
|
200
|
+
loader: loader as any,
|
|
139
201
|
|
|
140
202
|
buildLink: (options) => {
|
|
141
203
|
return router.buildLink({
|
package/src/routeConfig.ts
CHANGED
|
@@ -53,11 +53,18 @@ export type LoaderFn<
|
|
|
53
53
|
TRouteLoaderData extends AnyLoaderData,
|
|
54
54
|
TFullSearchSchema extends AnySearchSchema = {},
|
|
55
55
|
TAllParams extends AnyPathParams = {},
|
|
56
|
-
> = (
|
|
56
|
+
> = (
|
|
57
|
+
loaderContext: LoaderContext<TFullSearchSchema, TAllParams>,
|
|
58
|
+
) => Promise<TRouteLoaderData>
|
|
59
|
+
|
|
60
|
+
export interface LoaderContext<
|
|
61
|
+
TFullSearchSchema extends AnySearchSchema = {},
|
|
62
|
+
TAllParams extends AnyPathParams = {},
|
|
63
|
+
> {
|
|
57
64
|
params: TAllParams
|
|
58
65
|
search: TFullSearchSchema
|
|
59
66
|
signal?: AbortSignal
|
|
60
|
-
}
|
|
67
|
+
}
|
|
61
68
|
|
|
62
69
|
export type ActionFn<TActionPayload = unknown, TActionResponse = unknown> = (
|
|
63
70
|
submission: TActionPayload,
|
|
@@ -105,58 +112,6 @@ export type RouteOptions<
|
|
|
105
112
|
pendingMs?: number
|
|
106
113
|
// _If the `pendingElement` is shown_, the minimum duration for which it will be visible.
|
|
107
114
|
pendingMinMs?: number
|
|
108
|
-
// // An array of child routes
|
|
109
|
-
// children?: Route<any, any, any, any>[]
|
|
110
|
-
} & (
|
|
111
|
-
| {
|
|
112
|
-
parseParams?: never
|
|
113
|
-
stringifyParams?: never
|
|
114
|
-
}
|
|
115
|
-
| {
|
|
116
|
-
// Parse params optionally receives path params as strings and returns them in a parsed format (like a number or boolean)
|
|
117
|
-
parseParams: (
|
|
118
|
-
rawParams: IsAny<TPath, any, Record<ParsePathParams<TPath>, string>>,
|
|
119
|
-
) => TParams
|
|
120
|
-
stringifyParams: (
|
|
121
|
-
params: TParams,
|
|
122
|
-
) => Record<ParsePathParams<TPath>, string>
|
|
123
|
-
}
|
|
124
|
-
) &
|
|
125
|
-
RouteLoaders<
|
|
126
|
-
// Route Loaders (see below) can be inline on the route, or resolved async
|
|
127
|
-
TRouteLoaderData,
|
|
128
|
-
TLoaderData,
|
|
129
|
-
TActionPayload,
|
|
130
|
-
TActionResponse,
|
|
131
|
-
TFullSearchSchema,
|
|
132
|
-
TAllParams
|
|
133
|
-
> & {
|
|
134
|
-
// If `import` is defined, this route can resolve its elements and loaders in a single asynchronous call
|
|
135
|
-
// This is particularly useful for code-splitting or module federation
|
|
136
|
-
import?: (opts: {
|
|
137
|
-
params: AnyPathParams
|
|
138
|
-
}) => Promise<
|
|
139
|
-
RouteLoaders<
|
|
140
|
-
TRouteLoaderData,
|
|
141
|
-
TLoaderData,
|
|
142
|
-
TActionPayload,
|
|
143
|
-
TActionResponse,
|
|
144
|
-
TFullSearchSchema,
|
|
145
|
-
TAllParams
|
|
146
|
-
>
|
|
147
|
-
>
|
|
148
|
-
} & (PickUnsafe<TParentParams, ParsePathParams<TPath>> extends never // Detect if an existing path param is being redefined
|
|
149
|
-
? {}
|
|
150
|
-
: 'Cannot redefined path params in child routes!')
|
|
151
|
-
|
|
152
|
-
export interface RouteLoaders<
|
|
153
|
-
TRouteLoaderData extends AnyLoaderData = {},
|
|
154
|
-
TLoaderData extends AnyLoaderData = {},
|
|
155
|
-
TActionPayload = unknown,
|
|
156
|
-
TActionResponse = unknown,
|
|
157
|
-
TFullSearchSchema extends AnySearchSchema = {},
|
|
158
|
-
TAllParams extends AnyPathParams = {},
|
|
159
|
-
> {
|
|
160
115
|
// The content to be rendered when the route is matched. If no element is provided, defaults to `<Outlet />`
|
|
161
116
|
element?: GetFrameworkGeneric<'SyncOrAsyncElement'> // , NoInfer<TLoaderData>>
|
|
162
117
|
// The content to be rendered when `loader` encounters an error
|
|
@@ -196,7 +151,24 @@ export interface RouteLoaders<
|
|
|
196
151
|
}) => void
|
|
197
152
|
// An object of whatever you want! This object is accessible anywhere matches are.
|
|
198
153
|
meta?: RouteMeta // TODO: Make this nested and mergeable
|
|
199
|
-
}
|
|
154
|
+
} & (
|
|
155
|
+
| {
|
|
156
|
+
parseParams?: never
|
|
157
|
+
stringifyParams?: never
|
|
158
|
+
}
|
|
159
|
+
| {
|
|
160
|
+
// Parse params optionally receives path params as strings and returns them in a parsed format (like a number or boolean)
|
|
161
|
+
parseParams: (
|
|
162
|
+
rawParams: IsAny<TPath, any, Record<ParsePathParams<TPath>, string>>,
|
|
163
|
+
) => TParams
|
|
164
|
+
stringifyParams: (
|
|
165
|
+
params: TParams,
|
|
166
|
+
) => Record<ParsePathParams<TPath>, string>
|
|
167
|
+
}
|
|
168
|
+
) &
|
|
169
|
+
(PickUnsafe<TParentParams, ParsePathParams<TPath>> extends never // Detect if an existing path param is being redefined
|
|
170
|
+
? {}
|
|
171
|
+
: 'Cannot redefined path params in child routes!')
|
|
200
172
|
|
|
201
173
|
export type SearchFilter<T, U = T> = (prev: T) => U
|
|
202
174
|
|
package/src/routeMatch.ts
CHANGED
|
@@ -16,7 +16,7 @@ export interface RouteMatch<
|
|
|
16
16
|
> extends Route<TAllRouteInfo, TRouteInfo> {
|
|
17
17
|
matchId: string
|
|
18
18
|
pathname: string
|
|
19
|
-
params:
|
|
19
|
+
params: TRouteInfo['params']
|
|
20
20
|
parentMatch?: RouteMatch
|
|
21
21
|
childMatches: RouteMatch[]
|
|
22
22
|
routeSearch: TRouteInfo['searchSchema']
|
|
@@ -30,6 +30,7 @@ export interface RouteMatch<
|
|
|
30
30
|
routeLoaderData: TRouteInfo['routeLoaderData']
|
|
31
31
|
isFetching: boolean
|
|
32
32
|
isPending: boolean
|
|
33
|
+
invalidAt: number
|
|
33
34
|
__: {
|
|
34
35
|
element?: GetFrameworkGeneric<'Element'> // , TRouteInfo['loaderData']>
|
|
35
36
|
errorElement?: GetFrameworkGeneric<'Element'> // , TRouteInfo['loaderData']>
|
|
@@ -37,7 +38,6 @@ export interface RouteMatch<
|
|
|
37
38
|
pendingElement?: GetFrameworkGeneric<'Element'> // , TRouteInfo['loaderData']>
|
|
38
39
|
loadPromise?: Promise<void>
|
|
39
40
|
loaderPromise?: Promise<void>
|
|
40
|
-
importPromise?: Promise<void>
|
|
41
41
|
elementsPromise?: Promise<void>
|
|
42
42
|
dataPromise?: Promise<void>
|
|
43
43
|
pendingTimeout?: Timeout
|
|
@@ -60,7 +60,13 @@ export interface RouteMatch<
|
|
|
60
60
|
resolve: () => void
|
|
61
61
|
}
|
|
62
62
|
cancel: () => void
|
|
63
|
-
load: (
|
|
63
|
+
load: (
|
|
64
|
+
loaderOpts?: { withPending?: boolean } & (
|
|
65
|
+
| { preload: true; maxAge: number; gcMaxAge: number }
|
|
66
|
+
| { preload?: false; maxAge?: never; gcMaxAge?: never }
|
|
67
|
+
),
|
|
68
|
+
) => Promise<TRouteInfo['routeLoaderData']>
|
|
69
|
+
fetch: (opts?: { maxAge?: number }) => Promise<TRouteInfo['routeLoaderData']>
|
|
64
70
|
invalidate: () => void
|
|
65
71
|
hasLoaders: () => boolean
|
|
66
72
|
}
|
|
@@ -97,13 +103,10 @@ export function createRouteMatch<
|
|
|
97
103
|
isPending: false,
|
|
98
104
|
isFetching: false,
|
|
99
105
|
isInvalid: false,
|
|
106
|
+
invalidAt: Infinity,
|
|
100
107
|
getIsInvalid: () => {
|
|
101
108
|
const now = Date.now()
|
|
102
|
-
|
|
103
|
-
routeMatch.options.loaderMaxAge ??
|
|
104
|
-
router.options.defaultLoaderMaxAge ??
|
|
105
|
-
0
|
|
106
|
-
return routeMatch.isInvalid || routeMatch.updatedAt! + maxAge < now
|
|
109
|
+
return routeMatch.isInvalid || routeMatch.invalidAt < now
|
|
107
110
|
},
|
|
108
111
|
__: {
|
|
109
112
|
abortController: new AbortController(),
|
|
@@ -208,11 +211,42 @@ export function createRouteMatch<
|
|
|
208
211
|
hasLoaders: () => {
|
|
209
212
|
return !!(
|
|
210
213
|
route.options.loader ||
|
|
211
|
-
route.options.import ||
|
|
212
214
|
elementTypes.some((d) => typeof route.options[d] === 'function')
|
|
213
215
|
)
|
|
214
216
|
},
|
|
215
|
-
load: async () => {
|
|
217
|
+
load: async (loaderOpts) => {
|
|
218
|
+
const now = Date.now()
|
|
219
|
+
const minMaxAge = loaderOpts?.preload
|
|
220
|
+
? Math.max(loaderOpts?.maxAge, loaderOpts?.gcMaxAge)
|
|
221
|
+
: 0
|
|
222
|
+
|
|
223
|
+
// If this is a preload, add it to the preload cache
|
|
224
|
+
if (loaderOpts?.preload && minMaxAge > 0) {
|
|
225
|
+
// If the match is currently active, don't preload it
|
|
226
|
+
if (
|
|
227
|
+
router.state.matches.find((d) => d.matchId === routeMatch.matchId)
|
|
228
|
+
) {
|
|
229
|
+
return
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
router.matchCache[routeMatch.matchId] = {
|
|
233
|
+
gc: now + loaderOpts.gcMaxAge,
|
|
234
|
+
match: routeMatch as RouteMatch<any, any>,
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// If the match is invalid, errored or idle, trigger it to load
|
|
239
|
+
if (
|
|
240
|
+
(routeMatch.status === 'success' && routeMatch.getIsInvalid()) ||
|
|
241
|
+
routeMatch.status === 'error' ||
|
|
242
|
+
routeMatch.status === 'idle'
|
|
243
|
+
) {
|
|
244
|
+
const maxAge = loaderOpts?.preload ? loaderOpts?.maxAge : undefined
|
|
245
|
+
|
|
246
|
+
routeMatch.fetch({ maxAge })
|
|
247
|
+
}
|
|
248
|
+
},
|
|
249
|
+
fetch: async (opts) => {
|
|
216
250
|
const id = '' + Date.now() + Math.random()
|
|
217
251
|
routeMatch.__.latestId = id
|
|
218
252
|
|
|
@@ -233,26 +267,7 @@ export function createRouteMatch<
|
|
|
233
267
|
routeMatch.__.resolve = resolve as () => void
|
|
234
268
|
|
|
235
269
|
const loaderPromise = (async () => {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
// First, run any importers
|
|
239
|
-
if (importer) {
|
|
240
|
-
routeMatch.__.importPromise = importer({
|
|
241
|
-
params: routeMatch.params,
|
|
242
|
-
// search: routeMatch.search,
|
|
243
|
-
}).then((imported) => {
|
|
244
|
-
routeMatch.__ = {
|
|
245
|
-
...routeMatch.__,
|
|
246
|
-
...imported,
|
|
247
|
-
}
|
|
248
|
-
})
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
// Wait for the importer to finish before
|
|
252
|
-
// attempting to load elements and data
|
|
253
|
-
await routeMatch.__.importPromise
|
|
254
|
-
|
|
255
|
-
// Next, load the elements and data in parallel
|
|
270
|
+
// Load the elements and data in parallel
|
|
256
271
|
|
|
257
272
|
routeMatch.__.elementsPromise = (async () => {
|
|
258
273
|
// then run all element and data loaders in parallel
|
|
@@ -266,13 +281,9 @@ export function createRouteMatch<
|
|
|
266
281
|
return
|
|
267
282
|
}
|
|
268
283
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
routeMatch.__[type] = res
|
|
273
|
-
} else {
|
|
274
|
-
routeMatch.__[type] = routeMatch.options[type] as any
|
|
275
|
-
}
|
|
284
|
+
routeMatch.__[type] = await router.options.createElement!(
|
|
285
|
+
routeElement,
|
|
286
|
+
)
|
|
276
287
|
}),
|
|
277
288
|
)
|
|
278
289
|
})()
|
|
@@ -298,6 +309,12 @@ export function createRouteMatch<
|
|
|
298
309
|
routeMatch.error = undefined
|
|
299
310
|
routeMatch.status = 'success'
|
|
300
311
|
routeMatch.updatedAt = Date.now()
|
|
312
|
+
routeMatch.invalidAt =
|
|
313
|
+
routeMatch.updatedAt +
|
|
314
|
+
(opts?.maxAge ??
|
|
315
|
+
routeMatch.options.loaderMaxAge ??
|
|
316
|
+
router.options.defaultLoaderMaxAge ??
|
|
317
|
+
0)
|
|
301
318
|
} catch (err) {
|
|
302
319
|
if (id !== routeMatch.__.latestId) {
|
|
303
320
|
return routeMatch.__.loaderPromise
|