@tanstack/router-core 0.0.1-beta.15 → 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/build/cjs/packages/router-core/src/routeConfig.js.map +1 -1
- package/build/cjs/packages/router-core/src/routeMatch.js +24 -35
- package/build/cjs/packages/router-core/src/routeMatch.js.map +1 -1
- package/build/cjs/packages/router-core/src/router.js +40 -3
- package/build/cjs/packages/router-core/src/router.js.map +1 -1
- package/build/esm/index.js +64 -38
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +130 -130
- package/build/types/index.d.ts +89 -81
- package/build/umd/index.development.js +64 -38
- 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/link.ts +3 -1
- package/src/routeConfig.ts +1 -4
- package/src/routeInfo.ts +2 -2
- package/src/routeMatch.ts +24 -31
- package/src/router.ts +59 -7
package/package.json
CHANGED
package/src/link.ts
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
DefaultAllRouteInfo,
|
|
5
5
|
RouteInfoByPath,
|
|
6
6
|
} from './routeInfo'
|
|
7
|
-
import { Location } from './router'
|
|
7
|
+
import { Location, LocationState } from './router'
|
|
8
8
|
import { Expand, NoInfer, PickAsRequired, PickRequired, Updater } from './utils'
|
|
9
9
|
|
|
10
10
|
export type LinkInfo =
|
|
@@ -126,6 +126,8 @@ export type ToOptions<
|
|
|
126
126
|
to?: ToPathOption<TAllRouteInfo, TFrom, TTo>
|
|
127
127
|
// The new has string or a function to update it
|
|
128
128
|
hash?: Updater<string>
|
|
129
|
+
// State to pass to the history stack
|
|
130
|
+
state?: LocationState
|
|
129
131
|
// The source route path. This is automatically set when using route-level APIs, but for type-safe relative routing on the router itself, this is required
|
|
130
132
|
from?: TFrom
|
|
131
133
|
// // When using relative route paths, this option forces resolution from the current path, instead of the route API's path or `from` path
|
package/src/routeConfig.ts
CHANGED
|
@@ -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 {
|
|
10
|
-
import { replaceEqualDeep,
|
|
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
|
|
205
|
-
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
|
+
}
|
|
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
|
|
244
|
-
|
|
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
|
-
|
|
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
|
-
|
|
293
|
-
|
|
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 =
|
|
170
|
-
TAllParams =
|
|
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 {
|
|
@@ -199,6 +198,7 @@ export interface BuildNextOptions {
|
|
|
199
198
|
params?: true | Updater<Record<string, any>>
|
|
200
199
|
search?: true | Updater<unknown>
|
|
201
200
|
hash?: true | Updater<string>
|
|
201
|
+
state?: LocationState
|
|
202
202
|
key?: string
|
|
203
203
|
from?: string
|
|
204
204
|
fromCurrent?: boolean
|
|
@@ -248,6 +248,13 @@ export interface Router<
|
|
|
248
248
|
TRouteConfig extends AnyRouteConfig = RouteConfig,
|
|
249
249
|
TAllRouteInfo extends AnyAllRouteInfo = AllRouteInfo<TRouteConfig>,
|
|
250
250
|
> {
|
|
251
|
+
types: {
|
|
252
|
+
// Super secret internal stuff
|
|
253
|
+
RouteConfig: TRouteConfig
|
|
254
|
+
AllRouteInfo: TAllRouteInfo
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Public API
|
|
251
258
|
history: BrowserHistory | MemoryHistory | HashHistory
|
|
252
259
|
options: PickAsRequired<
|
|
253
260
|
RouterOptions<TRouteConfig>,
|
|
@@ -256,7 +263,6 @@ export interface Router<
|
|
|
256
263
|
// Computed in this.update()
|
|
257
264
|
basepath: string
|
|
258
265
|
// Internal:
|
|
259
|
-
allRouteInfo: TAllRouteInfo
|
|
260
266
|
listeners: Listener[]
|
|
261
267
|
location: Location
|
|
262
268
|
navigateTimeout?: Timeout
|
|
@@ -299,6 +305,9 @@ export interface Router<
|
|
|
299
305
|
| { preload: true; maxAge: number; gcMaxAge: number }
|
|
300
306
|
| { preload?: false; maxAge?: never; gcMaxAge?: never },
|
|
301
307
|
) => Promise<void>
|
|
308
|
+
loadMatchData: (
|
|
309
|
+
routeMatch: RouteMatch<any, any>,
|
|
310
|
+
) => Promise<Record<string, unknown>>
|
|
302
311
|
invalidateRoute: (opts: MatchLocation) => void
|
|
303
312
|
reload: () => Promise<void>
|
|
304
313
|
resolvePath: (from: string, path: string) => string
|
|
@@ -379,6 +388,9 @@ export function createRouter<
|
|
|
379
388
|
}
|
|
380
389
|
|
|
381
390
|
let router: Router<TRouteConfig, TAllRouteInfo> = {
|
|
391
|
+
types: undefined!,
|
|
392
|
+
|
|
393
|
+
// public api
|
|
382
394
|
history,
|
|
383
395
|
options: originalOptions,
|
|
384
396
|
listeners: [],
|
|
@@ -387,7 +399,6 @@ export function createRouter<
|
|
|
387
399
|
routeTree: undefined!,
|
|
388
400
|
routesById: {} as any,
|
|
389
401
|
location: undefined!,
|
|
390
|
-
allRouteInfo: undefined!,
|
|
391
402
|
//
|
|
392
403
|
navigationPromise: Promise.resolve(),
|
|
393
404
|
resolveNavigation: () => {},
|
|
@@ -840,6 +851,12 @@ export function createRouter<
|
|
|
840
851
|
match.__.validate()
|
|
841
852
|
match.load(loaderOpts)
|
|
842
853
|
|
|
854
|
+
const search = match.search as { __data?: any }
|
|
855
|
+
|
|
856
|
+
if (search.__data && search.__data.matchId !== match.matchId) {
|
|
857
|
+
return
|
|
858
|
+
}
|
|
859
|
+
|
|
843
860
|
if (match.__.loadPromise) {
|
|
844
861
|
// Wait for the first sign of activity from the match
|
|
845
862
|
await match.__.loadPromise
|
|
@@ -851,6 +868,40 @@ export function createRouter<
|
|
|
851
868
|
await Promise.all(matchPromises)
|
|
852
869
|
},
|
|
853
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
|
+
|
|
854
905
|
invalidateRoute: (opts: MatchLocation) => {
|
|
855
906
|
const next = router.buildNext(opts)
|
|
856
907
|
const unloadedMatchIds = router
|
|
@@ -1258,6 +1309,7 @@ export function createRouter<
|
|
|
1258
1309
|
},
|
|
1259
1310
|
{
|
|
1260
1311
|
id,
|
|
1312
|
+
...next.state,
|
|
1261
1313
|
},
|
|
1262
1314
|
)
|
|
1263
1315
|
} else {
|