@tanstack/router-core 0.0.1-beta.16 → 0.0.1-beta.19

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tanstack/router-core",
3
3
  "author": "Tanner Linsley",
4
- "version": "0.0.1-beta.16",
4
+ "version": "0.0.1-beta.19",
5
5
  "license": "MIT",
6
6
  "repository": "tanstack/router",
7
7
  "homepage": "https://tanstack.com/router",
@@ -70,7 +70,7 @@ export interface LoaderContext<
70
70
  params: TAllParams
71
71
  search: TFullSearchSchema
72
72
  signal?: AbortSignal
73
- parentLoaderPromise?: Promise<TParentRouteLoaderData>
73
+ // parentLoaderPromise?: Promise<TParentRouteLoaderData>
74
74
  }
75
75
 
76
76
  export type ActionFn<TActionPayload = unknown, TActionResponse = unknown> = (
@@ -138,9 +138,6 @@ export type RouteOptions<
138
138
  // An asynchronous function made available to the route for performing asynchronous or mutative actions that
139
139
  // might invalidate the route's data.
140
140
  action?: ActionFn<TActionPayload, TActionResponse>
141
- // Set this to true to rethrow errors up the component tree to either the nearest error boundary or
142
- // route with error component, whichever comes first.
143
- useErrorBoundary?: boolean
144
141
  // This function is called
145
142
  // when moving from an inactive state to an active one. Likewise, when moving from
146
143
  // an active to an inactive state, the return function (if provided) is called.
package/src/routeInfo.ts CHANGED
@@ -116,10 +116,10 @@ export interface RoutesInfoInner<
116
116
  any,
117
117
  any
118
118
  > = RouteInfo,
119
- TRouteInfoById = {
119
+ TRouteInfoById = { '/': TRouteInfo } & {
120
120
  [TInfo in TRouteInfo as TInfo['id']]: TInfo
121
121
  },
122
- TRouteInfoByFullPath = {
122
+ TRouteInfoByFullPath = { '/': TRouteInfo } & {
123
123
  [TInfo in TRouteInfo as TInfo['fullPath'] extends RootRouteId
124
124
  ? never
125
125
  : string extends TInfo['fullPath']
package/src/routeMatch.ts CHANGED
@@ -6,8 +6,8 @@ import {
6
6
  DefaultAllRouteInfo,
7
7
  RouteInfo,
8
8
  } from './routeInfo'
9
- import { ActionState, Router } from './router'
10
- import { replaceEqualDeep, Timeout } from './utils'
9
+ import { Router } from './router'
10
+ import { replaceEqualDeep, warning } from './utils'
11
11
 
12
12
  export interface RouteMatch<
13
13
  TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo,
@@ -201,8 +201,14 @@ export function createRouteMatch<
201
201
  }
202
202
  },
203
203
  fetch: async (opts) => {
204
- const id = '' + Date.now() + Math.random()
205
- routeMatch.__.latestId = id
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
+ }
206
212
 
207
213
  // If the match was in an error state, set it
208
214
  // to a loading state again. Otherwise, keep it
@@ -240,15 +246,8 @@ export function createRouteMatch<
240
246
  routeMatch.__.dataPromise = Promise.resolve().then(async () => {
241
247
  try {
242
248
  if (routeMatch.options.loader) {
243
- const data = await routeMatch.options.loader({
244
- parentLoaderPromise: routeMatch.parentMatch?.__.dataPromise,
245
- params: routeMatch.params,
246
- search: routeMatch.routeSearch,
247
- signal: routeMatch.__.abortController.signal,
248
- })
249
- if (id !== routeMatch.__.latestId) {
250
- return routeMatch.__.loadPromise
251
- }
249
+ const data = await router.loadMatchData(routeMatch)
250
+ await checkLatest()
252
251
 
253
252
  routeMatch.routeLoaderData = replaceEqualDeep(
254
253
  routeMatch.routeLoaderData,
@@ -268,9 +267,7 @@ export function createRouteMatch<
268
267
 
269
268
  return routeMatch.routeLoaderData
270
269
  } catch (err) {
271
- if (id !== routeMatch.__.latestId) {
272
- return routeMatch.__.loadPromise
273
- }
270
+ await checkLatest()
274
271
 
275
272
  if (process.env.NODE_ENV !== 'production') {
276
273
  console.error(err)
@@ -284,30 +281,26 @@ export function createRouteMatch<
284
281
  }
285
282
  })
286
283
 
284
+ const after = async () => {
285
+ await checkLatest()
286
+ routeMatch.isFetching = false
287
+ delete routeMatch.__.loadPromise
288
+ routeMatch.__.notify()
289
+ }
290
+
287
291
  try {
288
292
  await Promise.all([
289
293
  routeMatch.__.componentsPromise,
290
294
  routeMatch.__.dataPromise.catch(() => {}),
291
295
  ])
292
- if (id !== routeMatch.__.latestId) {
293
- return routeMatch.__.loadPromise
294
- }
295
- } finally {
296
- if (id !== routeMatch.__.latestId) {
297
- return routeMatch.__.loadPromise
298
- }
299
- routeMatch.isFetching = false
300
- routeMatch.__.notify()
296
+ after()
297
+ } catch {
298
+ after()
301
299
  }
302
300
  })
303
301
 
304
302
  await routeMatch.__.loadPromise
305
-
306
- if (id !== routeMatch.__.latestId) {
307
- return routeMatch.__.loadPromise
308
- }
309
-
310
- delete routeMatch.__.loadPromise
303
+ await checkLatest()
311
304
  },
312
305
  }
313
306
 
package/src/router.ts CHANGED
@@ -6,7 +6,6 @@ import {
6
6
  History,
7
7
  MemoryHistory,
8
8
  } from 'history'
9
- import React from 'react'
10
9
  import invariant from 'tiny-invariant'
11
10
  import { GetFrameworkGeneric } from './frameworks'
12
11
 
@@ -91,7 +90,6 @@ export interface RouterOptions<TRouteConfig extends AnyRouteConfig> {
91
90
  defaultPreloadMaxAge?: number
92
91
  defaultPreloadGcMaxAge?: number
93
92
  defaultPreloadDelay?: number
94
- useErrorBoundary?: boolean
95
93
  defaultComponent?: GetFrameworkGeneric<'Component'>
96
94
  defaultErrorComponent?: GetFrameworkGeneric<'Component'>
97
95
  defaultPendingComponent?: GetFrameworkGeneric<'Component'>
@@ -100,6 +98,7 @@ export interface RouterOptions<TRouteConfig extends AnyRouteConfig> {
100
98
  caseSensitive?: boolean
101
99
  routeConfig?: TRouteConfig
102
100
  basepath?: string
101
+ useServerData?: boolean
103
102
  createRouter?: (router: Router<any, any>) => void
104
103
  createRoute?: (opts: { route: AnyRoute; router: Router<any, any> }) => void
105
104
  loadComponent?: (
@@ -166,11 +165,11 @@ export interface Loader<
166
165
  }
167
166
 
168
167
  export interface LoaderState<
169
- TFullSearchSchema = unknown,
170
- TAllParams = unknown,
168
+ TFullSearchSchema extends AnySearchSchema = {},
169
+ TAllParams extends AnyPathParams = {},
171
170
  > {
172
171
  loadedAt: number
173
- loaderContext: LoaderContext<TFullSearchSchema, TAllParams>
172
+ loaderContext: LoaderContext<AnyLoaderData, TFullSearchSchema, TAllParams>
174
173
  }
175
174
 
176
175
  export interface RouterState {
@@ -249,6 +248,13 @@ export interface Router<
249
248
  TRouteConfig extends AnyRouteConfig = RouteConfig,
250
249
  TAllRouteInfo extends AnyAllRouteInfo = AllRouteInfo<TRouteConfig>,
251
250
  > {
251
+ types: {
252
+ // Super secret internal stuff
253
+ RouteConfig: TRouteConfig
254
+ AllRouteInfo: TAllRouteInfo
255
+ }
256
+
257
+ // Public API
252
258
  history: BrowserHistory | MemoryHistory | HashHistory
253
259
  options: PickAsRequired<
254
260
  RouterOptions<TRouteConfig>,
@@ -257,7 +263,6 @@ export interface Router<
257
263
  // Computed in this.update()
258
264
  basepath: string
259
265
  // Internal:
260
- allRouteInfo: TAllRouteInfo
261
266
  listeners: Listener[]
262
267
  location: Location
263
268
  navigateTimeout?: Timeout
@@ -300,6 +305,9 @@ export interface Router<
300
305
  | { preload: true; maxAge: number; gcMaxAge: number }
301
306
  | { preload?: false; maxAge?: never; gcMaxAge?: never },
302
307
  ) => Promise<void>
308
+ loadMatchData: (
309
+ routeMatch: RouteMatch<any, any>,
310
+ ) => Promise<Record<string, unknown>>
303
311
  invalidateRoute: (opts: MatchLocation) => void
304
312
  reload: () => Promise<void>
305
313
  resolvePath: (from: string, path: string) => string
@@ -380,6 +388,9 @@ export function createRouter<
380
388
  }
381
389
 
382
390
  let router: Router<TRouteConfig, TAllRouteInfo> = {
391
+ types: undefined!,
392
+
393
+ // public api
383
394
  history,
384
395
  options: originalOptions,
385
396
  listeners: [],
@@ -388,7 +399,6 @@ export function createRouter<
388
399
  routeTree: undefined!,
389
400
  routesById: {} as any,
390
401
  location: undefined!,
391
- allRouteInfo: undefined!,
392
402
  //
393
403
  navigationPromise: Promise.resolve(),
394
404
  resolveNavigation: () => {},
@@ -841,6 +851,12 @@ export function createRouter<
841
851
  match.__.validate()
842
852
  match.load(loaderOpts)
843
853
 
854
+ const search = match.search as { __data?: any }
855
+
856
+ if (search.__data && search.__data.matchId !== match.matchId) {
857
+ return
858
+ }
859
+
844
860
  if (match.__.loadPromise) {
845
861
  // Wait for the first sign of activity from the match
846
862
  await match.__.loadPromise
@@ -852,6 +868,40 @@ export function createRouter<
852
868
  await Promise.all(matchPromises)
853
869
  },
854
870
 
871
+ loadMatchData: async (routeMatch) => {
872
+ if (isServer || !router.options.useServerData) {
873
+ return (
874
+ (await routeMatch.options.loader?.({
875
+ // parentLoaderPromise: routeMatch.parentMatch?.__.dataPromise,
876
+ params: routeMatch.params,
877
+ search: routeMatch.routeSearch,
878
+ signal: routeMatch.__.abortController.signal,
879
+ })) ?? {}
880
+ )
881
+ } else {
882
+ const next = router.buildNext({
883
+ to: '.',
884
+ search: (d: any) => ({
885
+ ...(d ?? {}),
886
+ __data: {
887
+ matchId: routeMatch.matchId,
888
+ },
889
+ }),
890
+ })
891
+
892
+ const res = await fetch(next.href, {
893
+ method: 'GET',
894
+ // signal: routeMatch.__.abortController.signal,
895
+ })
896
+
897
+ if (res.ok) {
898
+ return res.json()
899
+ }
900
+
901
+ throw new Error('Failed to fetch match data')
902
+ }
903
+ },
904
+
855
905
  invalidateRoute: (opts: MatchLocation) => {
856
906
  const next = router.buildNext(opts)
857
907
  const unloadedMatchIds = router