@tanstack/router-core 0.0.1-beta.2 → 0.0.1-beta.21
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/index.js +1 -1
- package/build/cjs/packages/router-core/src/qss.js +1 -0
- package/build/cjs/packages/router-core/src/qss.js.map +1 -1
- package/build/cjs/packages/router-core/src/route.js +9 -23
- 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 +75 -121
- package/build/cjs/packages/router-core/src/routeMatch.js.map +1 -1
- package/build/cjs/packages/router-core/src/router.js +170 -89
- package/build/cjs/packages/router-core/src/router.js.map +1 -1
- package/build/cjs/packages/router-core/src/utils.js +7 -0
- package/build/cjs/packages/router-core/src/utils.js.map +1 -1
- package/build/esm/index.js +257 -227
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +137 -150
- package/build/types/index.d.ts +184 -186
- package/build/umd/index.development.js +257 -227
- 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 +2 -1
- package/src/frameworks.ts +1 -2
- package/src/index.ts +0 -1
- package/src/link.ts +3 -1
- package/src/qss.ts +1 -0
- package/src/route.ts +10 -26
- package/src/routeConfig.ts +25 -20
- package/src/routeInfo.ts +9 -2
- package/src/routeMatch.ts +94 -156
- package/src/router.ts +241 -104
- package/src/utils.ts +7 -0
package/src/routeMatch.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { GetFrameworkGeneric } from './frameworks'
|
|
2
2
|
import { Route } from './route'
|
|
3
|
-
import { AnyPathParams } from './routeConfig'
|
|
4
3
|
import {
|
|
5
4
|
AnyAllRouteInfo,
|
|
6
5
|
AnyRouteInfo,
|
|
@@ -8,7 +7,7 @@ import {
|
|
|
8
7
|
RouteInfo,
|
|
9
8
|
} from './routeInfo'
|
|
10
9
|
import { Router } from './router'
|
|
11
|
-
import { replaceEqualDeep
|
|
10
|
+
import { replaceEqualDeep } from './utils'
|
|
12
11
|
|
|
13
12
|
export interface RouteMatch<
|
|
14
13
|
TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo,
|
|
@@ -16,7 +15,7 @@ export interface RouteMatch<
|
|
|
16
15
|
> extends Route<TAllRouteInfo, TRouteInfo> {
|
|
17
16
|
matchId: string
|
|
18
17
|
pathname: string
|
|
19
|
-
params: TRouteInfo['
|
|
18
|
+
params: TRouteInfo['allParams']
|
|
20
19
|
parentMatch?: RouteMatch
|
|
21
20
|
childMatches: RouteMatch[]
|
|
22
21
|
routeSearch: TRouteInfo['searchSchema']
|
|
@@ -29,20 +28,14 @@ export interface RouteMatch<
|
|
|
29
28
|
loaderData: TRouteInfo['loaderData']
|
|
30
29
|
routeLoaderData: TRouteInfo['routeLoaderData']
|
|
31
30
|
isFetching: boolean
|
|
32
|
-
isPending: boolean
|
|
33
31
|
invalidAt: number
|
|
34
32
|
__: {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
pendingElement?: GetFrameworkGeneric<'Element'> // , TRouteInfo['loaderData']>
|
|
33
|
+
component?: GetFrameworkGeneric<'Component'> // , TRouteInfo['loaderData']>
|
|
34
|
+
errorComponent?: GetFrameworkGeneric<'Component'> // , TRouteInfo['loaderData']>
|
|
35
|
+
pendingComponent?: GetFrameworkGeneric<'Component'> // , TRouteInfo['loaderData']>
|
|
39
36
|
loadPromise?: Promise<void>
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
dataPromise?: Promise<void>
|
|
43
|
-
pendingTimeout?: Timeout
|
|
44
|
-
pendingMinTimeout?: Timeout
|
|
45
|
-
pendingMinPromise?: Promise<void>
|
|
37
|
+
componentsPromise?: Promise<void>
|
|
38
|
+
dataPromise?: Promise<TRouteInfo['routeLoaderData']>
|
|
46
39
|
onExit?:
|
|
47
40
|
| void
|
|
48
41
|
| ((matchContext: {
|
|
@@ -54,28 +47,24 @@ export interface RouteMatch<
|
|
|
54
47
|
// setParentMatch: (parentMatch: RouteMatch) => void
|
|
55
48
|
// addChildMatch: (childMatch: RouteMatch) => void
|
|
56
49
|
validate: () => void
|
|
57
|
-
startPending: () => void
|
|
58
|
-
cancelPending: () => void
|
|
59
50
|
notify: () => void
|
|
60
51
|
resolve: () => void
|
|
61
52
|
}
|
|
62
53
|
cancel: () => void
|
|
63
54
|
load: (
|
|
64
|
-
loaderOpts?:
|
|
55
|
+
loaderOpts?:
|
|
65
56
|
| { preload: true; maxAge: number; gcMaxAge: number }
|
|
66
|
-
| { preload?: false; maxAge?: never; gcMaxAge?: never }
|
|
67
|
-
),
|
|
57
|
+
| { preload?: false; maxAge?: never; gcMaxAge?: never },
|
|
68
58
|
) => Promise<TRouteInfo['routeLoaderData']>
|
|
69
59
|
fetch: (opts?: { maxAge?: number }) => Promise<TRouteInfo['routeLoaderData']>
|
|
70
60
|
invalidate: () => void
|
|
71
61
|
hasLoaders: () => boolean
|
|
72
62
|
}
|
|
73
63
|
|
|
74
|
-
const
|
|
75
|
-
'
|
|
76
|
-
'
|
|
77
|
-
'
|
|
78
|
-
'pendingElement',
|
|
64
|
+
const componentTypes = [
|
|
65
|
+
'component',
|
|
66
|
+
'errorComponent',
|
|
67
|
+
'pendingComponent',
|
|
79
68
|
] as const
|
|
80
69
|
|
|
81
70
|
export function createRouteMatch<
|
|
@@ -85,6 +74,7 @@ export function createRouteMatch<
|
|
|
85
74
|
router: Router<any, any>,
|
|
86
75
|
route: Route<TAllRouteInfo, TRouteInfo>,
|
|
87
76
|
opts: {
|
|
77
|
+
parentMatch?: RouteMatch<any, any>
|
|
88
78
|
matchId: string
|
|
89
79
|
params: TRouteInfo['allParams']
|
|
90
80
|
pathname: string
|
|
@@ -100,10 +90,10 @@ export function createRouteMatch<
|
|
|
100
90
|
status: 'idle',
|
|
101
91
|
routeLoaderData: {} as TRouteInfo['routeLoaderData'],
|
|
102
92
|
loaderData: {} as TRouteInfo['loaderData'],
|
|
103
|
-
isPending: false,
|
|
104
93
|
isFetching: false,
|
|
105
94
|
isInvalid: false,
|
|
106
95
|
invalidAt: Infinity,
|
|
96
|
+
// pendingActions: [],
|
|
107
97
|
getIsInvalid: () => {
|
|
108
98
|
const now = Date.now()
|
|
109
99
|
return routeMatch.isInvalid || routeMatch.invalidAt < now
|
|
@@ -116,49 +106,6 @@ export function createRouteMatch<
|
|
|
116
106
|
routeMatch.__.resolve()
|
|
117
107
|
routeMatch.router.notify()
|
|
118
108
|
},
|
|
119
|
-
startPending: () => {
|
|
120
|
-
const pendingMs =
|
|
121
|
-
routeMatch.options.pendingMs ?? router.options.defaultPendingMs
|
|
122
|
-
const pendingMinMs =
|
|
123
|
-
routeMatch.options.pendingMinMs ?? router.options.defaultPendingMinMs
|
|
124
|
-
|
|
125
|
-
if (
|
|
126
|
-
routeMatch.__.pendingTimeout ||
|
|
127
|
-
routeMatch.status !== 'loading' ||
|
|
128
|
-
typeof pendingMs === 'undefined'
|
|
129
|
-
) {
|
|
130
|
-
return
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
routeMatch.__.pendingTimeout = setTimeout(() => {
|
|
134
|
-
routeMatch.isPending = true
|
|
135
|
-
routeMatch.__.resolve()
|
|
136
|
-
if (typeof pendingMinMs !== 'undefined') {
|
|
137
|
-
routeMatch.__.pendingMinPromise = new Promise(
|
|
138
|
-
(r) =>
|
|
139
|
-
(routeMatch.__.pendingMinTimeout = setTimeout(r, pendingMinMs)),
|
|
140
|
-
)
|
|
141
|
-
}
|
|
142
|
-
}, pendingMs)
|
|
143
|
-
},
|
|
144
|
-
cancelPending: () => {
|
|
145
|
-
routeMatch.isPending = false
|
|
146
|
-
clearTimeout(routeMatch.__.pendingTimeout)
|
|
147
|
-
clearTimeout(routeMatch.__.pendingMinTimeout)
|
|
148
|
-
delete routeMatch.__.pendingMinPromise
|
|
149
|
-
},
|
|
150
|
-
// setParentMatch: (parentMatch?: RouteMatch) => {
|
|
151
|
-
// routeMatch.parentMatch = parentMatch
|
|
152
|
-
// },
|
|
153
|
-
// addChildMatch: (childMatch: RouteMatch) => {
|
|
154
|
-
// if (
|
|
155
|
-
// routeMatch.childMatches.find((d) => d.matchId === childMatch.matchId)
|
|
156
|
-
// ) {
|
|
157
|
-
// return
|
|
158
|
-
// }
|
|
159
|
-
|
|
160
|
-
// routeMatch.childMatches.push(childMatch)
|
|
161
|
-
// },
|
|
162
109
|
validate: () => {
|
|
163
110
|
// Validate the search params and stabilize them
|
|
164
111
|
const parentSearch =
|
|
@@ -174,7 +121,7 @@ export function createRouteMatch<
|
|
|
174
121
|
|
|
175
122
|
let nextSearch = replaceEqualDeep(
|
|
176
123
|
prevSearch,
|
|
177
|
-
validator?.(parentSearch),
|
|
124
|
+
validator?.(parentSearch) ?? {},
|
|
178
125
|
)
|
|
179
126
|
|
|
180
127
|
// Invalidate route matches when search param stability changes
|
|
@@ -188,6 +135,14 @@ export function createRouteMatch<
|
|
|
188
135
|
...parentSearch,
|
|
189
136
|
...nextSearch,
|
|
190
137
|
})
|
|
138
|
+
|
|
139
|
+
componentTypes.map(async (type) => {
|
|
140
|
+
const component = routeMatch.options[type]
|
|
141
|
+
|
|
142
|
+
if (typeof routeMatch.__[type] !== 'function') {
|
|
143
|
+
routeMatch.__[type] = component
|
|
144
|
+
}
|
|
145
|
+
})
|
|
191
146
|
} catch (err: any) {
|
|
192
147
|
console.error(err)
|
|
193
148
|
const error = new (Error as any)('Invalid search params found', {
|
|
@@ -203,7 +158,6 @@ export function createRouteMatch<
|
|
|
203
158
|
},
|
|
204
159
|
cancel: () => {
|
|
205
160
|
routeMatch.__.abortController?.abort()
|
|
206
|
-
routeMatch.__.cancelPending()
|
|
207
161
|
},
|
|
208
162
|
invalidate: () => {
|
|
209
163
|
routeMatch.isInvalid = true
|
|
@@ -211,7 +165,7 @@ export function createRouteMatch<
|
|
|
211
165
|
hasLoaders: () => {
|
|
212
166
|
return !!(
|
|
213
167
|
route.options.loader ||
|
|
214
|
-
|
|
168
|
+
componentTypes.some((d) => route.options[d]?.preload)
|
|
215
169
|
)
|
|
216
170
|
},
|
|
217
171
|
load: async (loaderOpts) => {
|
|
@@ -243,12 +197,18 @@ export function createRouteMatch<
|
|
|
243
197
|
) {
|
|
244
198
|
const maxAge = loaderOpts?.preload ? loaderOpts?.maxAge : undefined
|
|
245
199
|
|
|
246
|
-
routeMatch.fetch({ maxAge })
|
|
200
|
+
await routeMatch.fetch({ maxAge })
|
|
247
201
|
}
|
|
248
202
|
},
|
|
249
203
|
fetch: async (opts) => {
|
|
250
|
-
const
|
|
251
|
-
routeMatch.__.latestId =
|
|
204
|
+
const loadId = '' + Date.now() + Math.random()
|
|
205
|
+
routeMatch.__.latestId = loadId
|
|
206
|
+
const checkLatest = async () => {
|
|
207
|
+
if (loadId !== routeMatch.__.latestId) {
|
|
208
|
+
// warning(true, 'Data loader is out of date!')
|
|
209
|
+
return new Promise(() => {})
|
|
210
|
+
}
|
|
211
|
+
}
|
|
252
212
|
|
|
253
213
|
// If the match was in an error state, set it
|
|
254
214
|
// to a loading state again. Otherwise, keep it
|
|
@@ -266,103 +226,81 @@ export function createRouteMatch<
|
|
|
266
226
|
routeMatch.isFetching = true
|
|
267
227
|
routeMatch.__.resolve = resolve as () => void
|
|
268
228
|
|
|
269
|
-
|
|
270
|
-
//
|
|
271
|
-
|
|
272
|
-
routeMatch.__.elementsPromise = (async () => {
|
|
273
|
-
// then run all element and data loaders in parallel
|
|
274
|
-
// For each element type, potentially load it asynchronously
|
|
229
|
+
routeMatch.__.componentsPromise = (async () => {
|
|
230
|
+
// then run all component and data loaders in parallel
|
|
231
|
+
// For each component type, potentially load it asynchronously
|
|
275
232
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
233
|
+
await Promise.all(
|
|
234
|
+
componentTypes.map(async (type) => {
|
|
235
|
+
const component = routeMatch.options[type]
|
|
279
236
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
routeMatch.__[type] = await router.options.createElement!(
|
|
285
|
-
routeElement,
|
|
286
|
-
)
|
|
287
|
-
}),
|
|
288
|
-
)
|
|
289
|
-
})()
|
|
290
|
-
|
|
291
|
-
routeMatch.__.dataPromise = Promise.resolve().then(async () => {
|
|
292
|
-
try {
|
|
293
|
-
if (routeMatch.options.loader) {
|
|
294
|
-
const data = await routeMatch.options.loader({
|
|
295
|
-
params: routeMatch.params,
|
|
296
|
-
search: routeMatch.routeSearch,
|
|
297
|
-
signal: routeMatch.__.abortController.signal,
|
|
298
|
-
})
|
|
299
|
-
if (id !== routeMatch.__.latestId) {
|
|
300
|
-
return routeMatch.__.loaderPromise
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
routeMatch.routeLoaderData = replaceEqualDeep(
|
|
304
|
-
routeMatch.routeLoaderData,
|
|
305
|
-
data,
|
|
237
|
+
if (routeMatch.__[type]?.preload) {
|
|
238
|
+
routeMatch.__[type] = await router.options.loadComponent!(
|
|
239
|
+
component,
|
|
306
240
|
)
|
|
307
241
|
}
|
|
242
|
+
}),
|
|
243
|
+
)
|
|
244
|
+
})()
|
|
308
245
|
|
|
309
|
-
|
|
310
|
-
routeMatch.status = 'success'
|
|
311
|
-
routeMatch.updatedAt = Date.now()
|
|
312
|
-
routeMatch.invalidAt =
|
|
313
|
-
routeMatch.updatedAt +
|
|
314
|
-
(opts?.maxAge ??
|
|
315
|
-
routeMatch.options.loaderMaxAge ??
|
|
316
|
-
router.options.defaultLoaderMaxAge ??
|
|
317
|
-
0)
|
|
318
|
-
} catch (err) {
|
|
319
|
-
if (id !== routeMatch.__.latestId) {
|
|
320
|
-
return routeMatch.__.loaderPromise
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
324
|
-
console.error(err)
|
|
325
|
-
}
|
|
326
|
-
routeMatch.error = err
|
|
327
|
-
routeMatch.status = 'error'
|
|
328
|
-
routeMatch.updatedAt = Date.now()
|
|
329
|
-
}
|
|
330
|
-
})
|
|
331
|
-
|
|
246
|
+
routeMatch.__.dataPromise = Promise.resolve().then(async () => {
|
|
332
247
|
try {
|
|
333
|
-
|
|
334
|
-
routeMatch
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
248
|
+
if (routeMatch.options.loader) {
|
|
249
|
+
const data = await router.loadMatchData(routeMatch)
|
|
250
|
+
await checkLatest()
|
|
251
|
+
|
|
252
|
+
routeMatch.routeLoaderData = replaceEqualDeep(
|
|
253
|
+
routeMatch.routeLoaderData,
|
|
254
|
+
data,
|
|
255
|
+
)
|
|
339
256
|
}
|
|
340
257
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
258
|
+
routeMatch.error = undefined
|
|
259
|
+
routeMatch.status = 'success'
|
|
260
|
+
routeMatch.updatedAt = Date.now()
|
|
261
|
+
routeMatch.invalidAt =
|
|
262
|
+
routeMatch.updatedAt +
|
|
263
|
+
(opts?.maxAge ??
|
|
264
|
+
routeMatch.options.loaderMaxAge ??
|
|
265
|
+
router.options.defaultLoaderMaxAge ??
|
|
266
|
+
0)
|
|
267
|
+
|
|
268
|
+
return routeMatch.routeLoaderData
|
|
269
|
+
} catch (err) {
|
|
270
|
+
await checkLatest()
|
|
271
|
+
|
|
272
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
273
|
+
console.error(err)
|
|
344
274
|
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
routeMatch.isFetching = false
|
|
352
|
-
routeMatch.__.notify()
|
|
275
|
+
|
|
276
|
+
routeMatch.error = err
|
|
277
|
+
routeMatch.status = 'error'
|
|
278
|
+
routeMatch.updatedAt = Date.now()
|
|
279
|
+
|
|
280
|
+
throw err
|
|
353
281
|
}
|
|
354
|
-
})
|
|
282
|
+
})
|
|
355
283
|
|
|
356
|
-
|
|
357
|
-
|
|
284
|
+
const after = async () => {
|
|
285
|
+
await checkLatest()
|
|
286
|
+
routeMatch.isFetching = false
|
|
287
|
+
delete routeMatch.__.loadPromise
|
|
288
|
+
routeMatch.__.notify()
|
|
289
|
+
}
|
|
358
290
|
|
|
359
|
-
|
|
360
|
-
|
|
291
|
+
try {
|
|
292
|
+
await Promise.all([
|
|
293
|
+
routeMatch.__.componentsPromise,
|
|
294
|
+
routeMatch.__.dataPromise.catch(() => {}),
|
|
295
|
+
])
|
|
296
|
+
after()
|
|
297
|
+
} catch {
|
|
298
|
+
after()
|
|
361
299
|
}
|
|
362
|
-
delete routeMatch.__.loaderPromise
|
|
363
300
|
})
|
|
364
301
|
|
|
365
|
-
|
|
302
|
+
await routeMatch.__.loadPromise
|
|
303
|
+
await checkLatest()
|
|
366
304
|
},
|
|
367
305
|
}
|
|
368
306
|
|