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