@tanstack/router-core 0.0.1-alpha.5 → 0.0.1-alpha.7

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 (40) hide show
  1. package/build/cjs/packages/router-core/src/index.js +33 -1451
  2. package/build/cjs/packages/router-core/src/index.js.map +1 -1
  3. package/build/cjs/packages/router-core/src/path.js +222 -0
  4. package/build/cjs/packages/router-core/src/path.js.map +1 -0
  5. package/build/cjs/packages/router-core/src/qss.js +1 -1
  6. package/build/cjs/packages/router-core/src/qss.js.map +1 -1
  7. package/build/cjs/packages/router-core/src/route.js +126 -0
  8. package/build/cjs/packages/router-core/src/route.js.map +1 -0
  9. package/build/cjs/packages/router-core/src/routeConfig.js +69 -0
  10. package/build/cjs/packages/router-core/src/routeConfig.js.map +1 -0
  11. package/build/cjs/packages/router-core/src/routeMatch.js +260 -0
  12. package/build/cjs/packages/router-core/src/routeMatch.js.map +1 -0
  13. package/build/cjs/packages/router-core/src/router.js +787 -0
  14. package/build/cjs/packages/router-core/src/router.js.map +1 -0
  15. package/build/cjs/packages/router-core/src/searchParams.js +70 -0
  16. package/build/cjs/packages/router-core/src/searchParams.js.map +1 -0
  17. package/build/cjs/packages/router-core/src/utils.js +118 -0
  18. package/build/cjs/packages/router-core/src/utils.js.map +1 -0
  19. package/build/esm/index.js +1304 -1238
  20. package/build/esm/index.js.map +1 -1
  21. package/build/stats-html.html +1 -1
  22. package/build/stats-react.json +374 -57
  23. package/build/types/index.d.ts +361 -333
  24. package/build/umd/index.development.js +1313 -1238
  25. package/build/umd/index.development.js.map +1 -1
  26. package/build/umd/index.production.js +1 -1
  27. package/build/umd/index.production.js.map +1 -1
  28. package/package.json +2 -3
  29. package/src/frameworks.ts +13 -0
  30. package/src/index.ts +15 -3054
  31. package/src/link.ts +289 -0
  32. package/src/path.ts +236 -0
  33. package/src/qss.ts +1 -1
  34. package/src/route.ts +181 -0
  35. package/src/routeConfig.ts +523 -0
  36. package/src/routeInfo.ts +228 -0
  37. package/src/routeMatch.ts +357 -0
  38. package/src/router.ts +1182 -0
  39. package/src/searchParams.ts +54 -0
  40. package/src/utils.ts +157 -0
@@ -0,0 +1,523 @@
1
+ import { GetFrameworkGeneric } from './frameworks'
2
+ import { ParsePathParams } from './link'
3
+ import { joinPaths, trimPath, trimPathRight } from './path'
4
+ import { RouteInfo } from './routeInfo'
5
+ import { RouteMatch } from './routeMatch'
6
+ import {
7
+ DeepAwaited,
8
+ Expand,
9
+ IsAny,
10
+ NoInfer,
11
+ PickUnsafe,
12
+ Values,
13
+ } from './utils'
14
+
15
+ export const rootRouteId = '__root__' as const
16
+ export type RootRouteId = typeof rootRouteId
17
+
18
+ export type AnyLoaderData = {}
19
+ export type AnyPathParams = {}
20
+ export type AnySearchSchema = {}
21
+ export interface RouteMeta {}
22
+
23
+ // The parse type here allows a zod schema to be passed directly to the validator
24
+ export type SearchSchemaValidator<TReturn, TParentSchema> =
25
+ | SearchSchemaValidatorObj<TReturn, TParentSchema>
26
+ | SearchSchemaValidatorFn<TReturn, TParentSchema>
27
+
28
+ export type SearchSchemaValidatorObj<TReturn, TParentSchema> = {
29
+ parse?: SearchSchemaValidatorFn<TReturn, TParentSchema>
30
+ }
31
+
32
+ export type SearchSchemaValidatorFn<TReturn, TParentSchema> = (
33
+ searchObj: Record<string, unknown>,
34
+ ) => {} extends TParentSchema
35
+ ? TReturn
36
+ : keyof TReturn extends keyof TParentSchema
37
+ ? {
38
+ error: 'Top level search params cannot be redefined by child routes!'
39
+ keys: keyof TReturn & keyof TParentSchema
40
+ }
41
+ : TReturn
42
+
43
+ export type DefinedPathParamWarning =
44
+ 'Path params cannot be redefined by child routes!'
45
+
46
+ export type ParentParams<TParentParams> = AnyPathParams extends TParentParams
47
+ ? {}
48
+ : {
49
+ [Key in keyof TParentParams]?: DefinedPathParamWarning
50
+ }
51
+
52
+ export type LoaderFn<
53
+ TRouteLoaderData extends AnyLoaderData,
54
+ TFullSearchSchema extends AnySearchSchema = {},
55
+ TAllParams extends AnyPathParams = {},
56
+ > = (loaderContext: {
57
+ params: TAllParams
58
+ search: TFullSearchSchema
59
+ signal?: AbortSignal
60
+ }) => Promise<TRouteLoaderData>
61
+
62
+ export type ActionFn<TActionPayload = unknown, TActionResponse = unknown> = (
63
+ submission: TActionPayload,
64
+ ) => TActionResponse | Promise<TActionResponse>
65
+
66
+ export type UnloaderFn<TPath extends string> = (
67
+ routeMatch: RouteMatch<any, RouteInfo<string, TPath>>,
68
+ ) => void
69
+
70
+ export type RouteOptions<
71
+ TRouteId extends string = string,
72
+ TPath extends string = string,
73
+ TRouteLoaderData extends AnyLoaderData = {},
74
+ TLoaderData extends AnyLoaderData = {},
75
+ TActionPayload = unknown,
76
+ TActionResponse = unknown,
77
+ TParentSearchSchema extends {} = {},
78
+ TSearchSchema extends AnySearchSchema = {},
79
+ TFullSearchSchema extends AnySearchSchema = TSearchSchema,
80
+ TParentParams extends AnyPathParams = {},
81
+ TParams extends Record<ParsePathParams<TPath>, unknown> = Record<
82
+ ParsePathParams<TPath>,
83
+ string
84
+ >,
85
+ TAllParams extends AnyPathParams = {},
86
+ > = (
87
+ | {
88
+ // The path to match (relative to the nearest parent `Route` component or root basepath)
89
+ path: TPath
90
+ }
91
+ | {
92
+ id: TRouteId
93
+ }
94
+ ) & {
95
+ // If true, this route will be matched as case-sensitive
96
+ caseSensitive?: boolean
97
+ validateSearch?: SearchSchemaValidator<TSearchSchema, TParentSearchSchema>
98
+ // Filter functions that can manipulate search params *before* they are passed to links and navigate
99
+ // calls that match this route.
100
+ preSearchFilters?: SearchFilter<TFullSearchSchema>[]
101
+ // Filter functions that can manipulate search params *after* they are passed to links and navigate
102
+ // calls that match this route.
103
+ postSearchFilters?: SearchFilter<TFullSearchSchema>[]
104
+ // The duration to wait during `loader` execution before showing the `pendingElement`
105
+ pendingMs?: number
106
+ // _If the `pendingElement` is shown_, the minimum duration for which it will be visible.
107
+ pendingMinMs?: number
108
+ // // An array of child routes
109
+ // children?: Route<any, any, any, any>[]
110
+ } & (
111
+ | {
112
+ parseParams?: never
113
+ stringifyParams?: never
114
+ }
115
+ | {
116
+ // Parse params optionally receives path params as strings and returns them in a parsed format (like a number or boolean)
117
+ parseParams: (
118
+ rawParams: IsAny<TPath, any, Record<ParsePathParams<TPath>, string>>,
119
+ ) => TParams
120
+ stringifyParams: (
121
+ params: TParams,
122
+ ) => Record<ParsePathParams<TPath>, string>
123
+ }
124
+ ) &
125
+ RouteLoaders<
126
+ // Route Loaders (see below) can be inline on the route, or resolved async
127
+ TRouteLoaderData,
128
+ TLoaderData,
129
+ TActionPayload,
130
+ TActionResponse,
131
+ TFullSearchSchema,
132
+ TAllParams
133
+ > & {
134
+ // If `import` is defined, this route can resolve its elements and loaders in a single asynchronous call
135
+ // This is particularly useful for code-splitting or module federation
136
+ import?: (opts: {
137
+ params: AnyPathParams
138
+ }) => Promise<
139
+ RouteLoaders<
140
+ TRouteLoaderData,
141
+ TLoaderData,
142
+ TActionPayload,
143
+ TActionResponse,
144
+ TFullSearchSchema,
145
+ TAllParams
146
+ >
147
+ >
148
+ } & (PickUnsafe<TParentParams, ParsePathParams<TPath>> extends never // Detect if an existing path param is being redefined
149
+ ? {}
150
+ : 'Cannot redefined path params in child routes!')
151
+
152
+ export interface RouteLoaders<
153
+ TRouteLoaderData extends AnyLoaderData = {},
154
+ TLoaderData extends AnyLoaderData = {},
155
+ TActionPayload = unknown,
156
+ TActionResponse = unknown,
157
+ TFullSearchSchema extends AnySearchSchema = {},
158
+ TAllParams extends AnyPathParams = {},
159
+ > {
160
+ // The content to be rendered when the route is matched. If no element is provided, defaults to `<Outlet />`
161
+ element?: GetFrameworkGeneric<'SyncOrAsyncElement'> // , NoInfer<TLoaderData>>
162
+ // The content to be rendered when `loader` encounters an error
163
+ errorElement?: GetFrameworkGeneric<'SyncOrAsyncElement'> // , NoInfer<TLoaderData>>
164
+ // The content to be rendered when rendering encounters an error
165
+ catchElement?: GetFrameworkGeneric<'SyncOrAsyncElement'> // , NoInfer<TLoaderData>>
166
+ // The content to be rendered when the duration of `loader` execution surpasses the `pendingMs` duration
167
+ pendingElement?: GetFrameworkGeneric<'SyncOrAsyncElement'> //, NoInfer<TLoaderData>>
168
+ // An asynchronous function responsible for preparing or fetching data for the route before it is rendered
169
+ loader?: LoaderFn<TRouteLoaderData, TFullSearchSchema, TAllParams>
170
+ // The max age to consider loader data fresh (not-stale) for this route in milliseconds from the time of fetch
171
+ // Defaults to 0. Only stale loader data is refetched.
172
+ loaderMaxAge?: number
173
+ // The max age to cache the loader data for this route in milliseconds from the time of route inactivity
174
+ // before it is garbage collected.
175
+ loaderGcMaxAge?: number
176
+ // An asynchronous function made available to the route for performing asynchronous or mutative actions that
177
+ // might invalidate the route's data.
178
+ action?: ActionFn<TActionPayload, TActionResponse>
179
+ // Set this to true to rethrow errors up the component tree to either the nearest error boundary or
180
+ // route with error element, whichever comes first.
181
+ useErrorBoundary?: boolean
182
+ // This function is called
183
+ // when moving from an inactive state to an active one. Likewise, when moving from
184
+ // an active to an inactive state, the return function (if provided) is called.
185
+ onMatch?: (matchContext: {
186
+ params: TAllParams
187
+ search: TFullSearchSchema
188
+ }) =>
189
+ | void
190
+ | undefined
191
+ | ((match: { params: TAllParams; search: TFullSearchSchema }) => void)
192
+ // This function is called when the route remains active from one transition to the next.
193
+ onTransition?: (match: {
194
+ params: TAllParams
195
+ search: TFullSearchSchema
196
+ }) => void
197
+ // An object of whatever you want! This object is accessible anywhere matches are.
198
+ meta?: RouteMeta // TODO: Make this nested and mergeable
199
+ }
200
+
201
+ export type SearchFilter<T, U = T> = (prev: T) => U
202
+
203
+ export interface RouteConfig<
204
+ TId extends string = string,
205
+ TRouteId extends string = string,
206
+ TPath extends string = string,
207
+ TFullPath extends string = string,
208
+ TRouteLoaderData extends AnyLoaderData = AnyLoaderData,
209
+ TLoaderData extends AnyLoaderData = AnyLoaderData,
210
+ TActionPayload = unknown,
211
+ TActionResponse = unknown,
212
+ TParentSearchSchema extends {} = {},
213
+ TSearchSchema extends AnySearchSchema = {},
214
+ TFullSearchSchema extends AnySearchSchema = {},
215
+ TParentParams extends AnyPathParams = {},
216
+ TParams extends Record<ParsePathParams<TPath>, unknown> = Record<
217
+ ParsePathParams<TPath>,
218
+ string
219
+ >,
220
+ TAllParams extends AnyPathParams = {},
221
+ TKnownChildren = unknown,
222
+ > {
223
+ id: TId
224
+ routeId: TRouteId
225
+ path: NoInfer<TPath>
226
+ fullPath: TFullPath
227
+ options: RouteOptions<
228
+ TRouteId,
229
+ TPath,
230
+ TRouteLoaderData,
231
+ TLoaderData,
232
+ TActionPayload,
233
+ TActionResponse,
234
+ TParentSearchSchema,
235
+ TSearchSchema,
236
+ TFullSearchSchema,
237
+ TParentParams,
238
+ TParams,
239
+ TAllParams
240
+ >
241
+ children?: TKnownChildren
242
+ addChildren: IsAny<
243
+ TId,
244
+ any,
245
+ <TNewChildren extends any>(
246
+ children: TNewChildren extends AnyRouteConfig[]
247
+ ? TNewChildren
248
+ : { error: 'Invalid route detected'; route: TNewChildren },
249
+ ) => RouteConfig<
250
+ TId,
251
+ TRouteId,
252
+ TPath,
253
+ TFullPath,
254
+ TRouteLoaderData,
255
+ TLoaderData,
256
+ TActionPayload,
257
+ TActionResponse,
258
+ TParentSearchSchema,
259
+ TSearchSchema,
260
+ TFullSearchSchema,
261
+ TParentParams,
262
+ TParams,
263
+ TAllParams,
264
+ TNewChildren
265
+ >
266
+ >
267
+ createChildren: IsAny<
268
+ TId,
269
+ any,
270
+ <TNewChildren extends any>(
271
+ cb: (
272
+ createChildRoute: CreateRouteConfigFn<
273
+ false,
274
+ TId,
275
+ TFullPath,
276
+ TLoaderData,
277
+ TFullSearchSchema,
278
+ TAllParams
279
+ >,
280
+ ) => TNewChildren extends AnyRouteConfig[]
281
+ ? TNewChildren
282
+ : { error: 'Invalid route detected'; route: TNewChildren },
283
+ ) => RouteConfig<
284
+ TId,
285
+ TRouteId,
286
+ TPath,
287
+ TFullPath,
288
+ TRouteLoaderData,
289
+ TLoaderData,
290
+ TActionPayload,
291
+ TActionResponse,
292
+ TParentSearchSchema,
293
+ TSearchSchema,
294
+ TFullSearchSchema,
295
+ TParentParams,
296
+ TParams,
297
+ TAllParams,
298
+ TNewChildren
299
+ >
300
+ >
301
+ createRoute: CreateRouteConfigFn<
302
+ false,
303
+ TId,
304
+ TFullPath,
305
+ TLoaderData,
306
+ TFullSearchSchema,
307
+ TAllParams
308
+ >
309
+ }
310
+
311
+ type CreateRouteConfigFn<
312
+ TIsRoot extends boolean = false,
313
+ TParentId extends string = string,
314
+ TParentPath extends string = string,
315
+ TParentAllLoaderData extends AnyLoaderData = {},
316
+ TParentSearchSchema extends AnySearchSchema = {},
317
+ TParentParams extends AnyPathParams = {},
318
+ > = <
319
+ TRouteId extends string,
320
+ TPath extends string,
321
+ TRouteLoaderData extends AnyLoaderData,
322
+ TActionPayload,
323
+ TActionResponse,
324
+ TSearchSchema extends AnySearchSchema = AnySearchSchema,
325
+ TParams extends Record<ParsePathParams<TPath>, unknown> = Record<
326
+ ParsePathParams<TPath>,
327
+ string
328
+ >,
329
+ TAllParams extends AnyPathParams extends TParams
330
+ ? Record<ParsePathParams<TPath>, string>
331
+ : NoInfer<TParams> = AnyPathParams extends TParams
332
+ ? Record<ParsePathParams<TPath>, string>
333
+ : NoInfer<TParams>,
334
+ TKnownChildren extends RouteConfig[] = RouteConfig[],
335
+ TResolvedId extends string = string extends TRouteId
336
+ ? string extends TPath
337
+ ? string
338
+ : TPath
339
+ : TRouteId,
340
+ >(
341
+ options?: TIsRoot extends true
342
+ ? Omit<
343
+ RouteOptions<
344
+ TRouteId,
345
+ TPath,
346
+ TRouteLoaderData,
347
+ Expand<TParentAllLoaderData & DeepAwaited<NoInfer<TRouteLoaderData>>>,
348
+ TActionPayload,
349
+ TActionResponse,
350
+ TParentSearchSchema,
351
+ TSearchSchema,
352
+ Expand<TParentSearchSchema & TSearchSchema>,
353
+ TParentParams,
354
+ TParams,
355
+ Expand<TParentParams & TAllParams>
356
+ >,
357
+ 'path'
358
+ > & { path?: never }
359
+ : RouteOptions<
360
+ TRouteId,
361
+ TPath,
362
+ TRouteLoaderData,
363
+ Expand<TParentAllLoaderData & DeepAwaited<NoInfer<TRouteLoaderData>>>,
364
+ TActionPayload,
365
+ TActionResponse,
366
+ TParentSearchSchema,
367
+ TSearchSchema,
368
+ Expand<TParentSearchSchema & TSearchSchema>,
369
+ TParentParams,
370
+ TParams,
371
+ Expand<TParentParams & TAllParams>
372
+ >,
373
+ children?: TKnownChildren,
374
+ isRoot?: boolean,
375
+ parentId?: string,
376
+ parentPath?: string,
377
+ ) => RouteConfig<
378
+ RoutePrefix<TParentId, TResolvedId>,
379
+ TResolvedId,
380
+ TPath,
381
+ string extends TPath ? '' : RoutePath<RoutePrefix<TParentPath, TPath>>,
382
+ TRouteLoaderData,
383
+ Expand<TParentAllLoaderData & DeepAwaited<NoInfer<TRouteLoaderData>>>,
384
+ TActionPayload,
385
+ TActionResponse,
386
+ TParentSearchSchema,
387
+ TSearchSchema,
388
+ Expand<TParentSearchSchema & TSearchSchema>,
389
+ TParentParams,
390
+ TParams,
391
+ Expand<TParentParams & TAllParams>,
392
+ TKnownChildren
393
+ >
394
+
395
+ type RoutePath<T extends string> = T extends RootRouteId
396
+ ? '/'
397
+ : TrimPathRight<`${T}`>
398
+
399
+ type RoutePrefix<
400
+ TPrefix extends string,
401
+ TId extends string,
402
+ > = string extends TId
403
+ ? RootRouteId
404
+ : TId extends string
405
+ ? `${TPrefix}/${TId}` extends '/'
406
+ ? '/'
407
+ : `/${TrimPathLeft<`${TrimPathRight<TPrefix>}/${TrimPath<TId>}`>}`
408
+ : never
409
+
410
+ export interface AnyRouteConfig
411
+ extends RouteConfig<
412
+ any,
413
+ any,
414
+ any,
415
+ any,
416
+ any,
417
+ any,
418
+ any,
419
+ any,
420
+ any,
421
+ any,
422
+ any,
423
+ any,
424
+ any,
425
+ any,
426
+ any
427
+ > {}
428
+
429
+ export interface AnyRouteConfigWithChildren<TChildren>
430
+ extends RouteConfig<
431
+ any,
432
+ any,
433
+ any,
434
+ any,
435
+ any,
436
+ any,
437
+ any,
438
+ any,
439
+ any,
440
+ any,
441
+ any,
442
+ any,
443
+ any,
444
+ any,
445
+ TChildren
446
+ > {}
447
+
448
+ type TrimPath<T extends string> = '' extends T
449
+ ? ''
450
+ : TrimPathRight<TrimPathLeft<T>>
451
+
452
+ type TrimPathLeft<T extends string> = T extends `${RootRouteId}/${infer U}`
453
+ ? TrimPathLeft<U>
454
+ : T extends `/${infer U}`
455
+ ? TrimPathLeft<U>
456
+ : T
457
+ type TrimPathRight<T extends string> = T extends '/'
458
+ ? '/'
459
+ : T extends `${infer U}/`
460
+ ? TrimPathRight<U>
461
+ : T
462
+
463
+ export const createRouteConfig: CreateRouteConfigFn<true> = (
464
+ options = {} as any,
465
+ children,
466
+ isRoot = true,
467
+ parentId,
468
+ parentPath,
469
+ ) => {
470
+ if (isRoot) {
471
+ ;(options as any).path = rootRouteId
472
+ }
473
+
474
+ // Strip the root from parentIds
475
+ if (parentId === rootRouteId) {
476
+ parentId = ''
477
+ }
478
+
479
+ let path: undefined | string = isRoot ? rootRouteId : options.path
480
+
481
+ // If the path is anything other than an index path, trim it up
482
+ if (path && path !== '/') {
483
+ path = trimPath(path)
484
+ }
485
+
486
+ const routeId = path || (options as { id?: string }).id
487
+
488
+ let id = joinPaths([parentId, routeId])
489
+
490
+ if (path === rootRouteId) {
491
+ path = '/'
492
+ }
493
+
494
+ if (id !== rootRouteId) {
495
+ id = joinPaths(['/', id])
496
+ }
497
+
498
+ const fullPath =
499
+ id === rootRouteId ? '/' : trimPathRight(joinPaths([parentPath, path]))
500
+
501
+ return {
502
+ id: id as any,
503
+ routeId: routeId as any,
504
+ path: path as any,
505
+ fullPath: fullPath as any,
506
+ options: options as any,
507
+ children,
508
+ createChildren: (cb: any) =>
509
+ createRouteConfig(
510
+ options,
511
+ cb((childOptions: any) =>
512
+ createRouteConfig(childOptions, undefined, false, id, fullPath),
513
+ ),
514
+ false,
515
+ parentId,
516
+ parentPath,
517
+ ),
518
+ addChildren: (children: any) =>
519
+ createRouteConfig(options, children, false, parentId, parentPath),
520
+ createRoute: (childOptions: any) =>
521
+ createRouteConfig(childOptions, undefined, false, id, fullPath) as any,
522
+ }
523
+ }