@tanstack/router-core 0.0.1-beta.3 → 0.0.1-beta.31

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