@tanstack/solid-router 1.114.23 → 1.114.25

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/src/route.ts CHANGED
@@ -1,9 +1,8 @@
1
- import invariant from 'tiny-invariant'
2
1
  import {
3
- joinPaths,
2
+ BaseRootRoute,
3
+ BaseRoute,
4
+ BaseRouteApi,
4
5
  notFound,
5
- rootRouteId,
6
- trimPathLeft,
7
6
  } from '@tanstack/router-core'
8
7
  import { useLoaderData } from './useLoaderData'
9
8
  import { useLoaderDeps } from './useLoaderDeps'
@@ -16,10 +15,7 @@ import type {
16
15
  AnyContext,
17
16
  AnyRoute,
18
17
  AnyRouter,
19
- Constrain,
20
18
  ConstrainLiteral,
21
- LazyRoute as CoreLazyRoute,
22
- Route as CoreRoute,
23
19
  ErrorComponentProps,
24
20
  NotFoundError,
25
21
  NotFoundRouteProps,
@@ -29,22 +25,13 @@ import type {
29
25
  ResolveParams,
30
26
  RootRouteId,
31
27
  RootRouteOptions,
32
- RouteAddChildrenFn,
33
- RouteAddFileChildrenFn,
34
- RouteAddFileTypesFn,
35
28
  RouteConstraints,
36
29
  RouteIds,
37
- RouteLazyFn,
38
- RouteLoaderFn,
39
30
  RouteMask,
40
31
  RouteOptions,
41
- RoutePathOptionsIntersection,
42
- RouteTypes,
43
32
  RouteTypesById,
44
- Router,
33
+ RouterCore,
45
34
  ToMaskOptions,
46
- TrimPathRight,
47
- UpdatableRouteOptions,
48
35
  UseNavigateResult,
49
36
  } from '@tanstack/router-core'
50
37
  import type { UseLoaderDataRoute } from './useLoaderData'
@@ -84,14 +71,15 @@ export function getRouteApi<
84
71
  return new RouteApi<TId, TRouter>({ id })
85
72
  }
86
73
 
87
- export class RouteApi<TId, TRouter extends AnyRouter = RegisteredRouter> {
88
- id: TId
89
-
74
+ export class RouteApi<
75
+ TId,
76
+ TRouter extends AnyRouter = RegisteredRouter,
77
+ > extends BaseRouteApi<TId, TRouter> {
90
78
  /**
91
79
  * @deprecated Use the `getRouteApi` function instead.
92
80
  */
93
81
  constructor({ id }: { id: TId }) {
94
- this.id = id as any
82
+ super({ id })
95
83
  }
96
84
 
97
85
  useMatch: UseMatchRoute<TId> = (opts) => {
@@ -164,93 +152,22 @@ export class Route<
164
152
  in out TLoaderFn = undefined,
165
153
  in out TChildren = unknown,
166
154
  in out TFileRouteTypes = unknown,
167
- > implements
168
- CoreRoute<
169
- TParentRoute,
170
- TPath,
171
- TFullPath,
172
- TCustomId,
173
- TId,
174
- TSearchValidator,
175
- TParams,
176
- TRouterContext,
177
- TRouteContextFn,
178
- TBeforeLoadFn,
179
- TLoaderDeps,
180
- TLoaderFn,
181
- TChildren,
182
- TFileRouteTypes
183
- >
184
- {
185
- isRoot: TParentRoute extends AnyRoute ? true : false
186
- options: RouteOptions<
187
- TParentRoute,
188
- TId,
189
- TCustomId,
190
- TFullPath,
191
- TPath,
192
- TSearchValidator,
193
- TParams,
194
- TLoaderDeps,
195
- TLoaderFn,
196
- TRouterContext,
197
- TRouteContextFn,
198
- TBeforeLoadFn
199
- >
200
-
201
- // The following properties are set up in this.init()
202
- parentRoute!: TParentRoute
203
- private _id!: TId
204
- private _path!: TPath
205
- private _fullPath!: TFullPath
206
- private _to!: TrimPathRight<TFullPath>
207
- private _ssr!: boolean
208
-
209
- public get to() {
210
- /* invariant(
211
- this._to,
212
- `trying to access property 'to' on a route which is not initialized yet. Route properties are only available after 'createRouter' completed.`,
213
- )*/
214
- return this._to
215
- }
216
-
217
- public get id() {
218
- /* invariant(
219
- this._id,
220
- `trying to access property 'id' on a route which is not initialized yet. Route properties are only available after 'createRouter' completed.`,
221
- )*/
222
- return this._id
223
- }
224
-
225
- public get path() {
226
- /* invariant(
227
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
228
- this.isRoot || this._id || this._path,
229
- `trying to access property 'path' on a route which is not initialized yet. Route properties are only available after 'createRouter' completed.`,
230
- )*/
231
- return this._path
232
- }
233
-
234
- public get fullPath() {
235
- /* invariant(
236
- this._fullPath,
237
- `trying to access property 'fullPath' on a route which is not initialized yet. Route properties are only available after 'createRouter' completed.`,
238
- )*/
239
- return this._fullPath
240
- }
241
-
242
- public get ssr() {
243
- return this._ssr
244
- }
245
-
246
- // Optional
247
- children?: TChildren
248
- originalIndex?: number
249
- rank!: number
250
- lazyFn?: () => Promise<CoreLazyRoute>
251
- _lazyPromise?: Promise<void>
252
- _componentsPromise?: Promise<Array<void>>
253
-
155
+ > extends BaseRoute<
156
+ TParentRoute,
157
+ TPath,
158
+ TFullPath,
159
+ TCustomId,
160
+ TId,
161
+ TSearchValidator,
162
+ TParams,
163
+ TRouterContext,
164
+ TRouteContextFn,
165
+ TBeforeLoadFn,
166
+ TLoaderDeps,
167
+ TLoaderFn,
168
+ TChildren,
169
+ TFileRouteTypes
170
+ > {
254
171
  /**
255
172
  * @deprecated Use the `createRoute` function instead.
256
173
  */
@@ -270,218 +187,7 @@ export class Route<
270
187
  TBeforeLoadFn
271
188
  >,
272
189
  ) {
273
- this.options = (options as any) || {}
274
-
275
- this.isRoot = !options?.getParentRoute as any
276
- invariant(
277
- !((options as any)?.id && (options as any)?.path),
278
- `Route cannot have both an 'id' and a 'path' option.`,
279
- )
280
- }
281
-
282
- types!: RouteTypes<
283
- TParentRoute,
284
- TPath,
285
- TFullPath,
286
- TCustomId,
287
- TId,
288
- TSearchValidator,
289
- TParams,
290
- TRouterContext,
291
- TRouteContextFn,
292
- TBeforeLoadFn,
293
- TLoaderDeps,
294
- TLoaderFn,
295
- TChildren,
296
- TFileRouteTypes
297
- >
298
-
299
- init = (opts: { originalIndex: number; defaultSsr?: boolean }): void => {
300
- this.originalIndex = opts.originalIndex
301
-
302
- const options = this.options as
303
- | (RouteOptions<
304
- TParentRoute,
305
- TId,
306
- TCustomId,
307
- TFullPath,
308
- TPath,
309
- TSearchValidator,
310
- TParams,
311
- TLoaderDeps,
312
- TLoaderFn,
313
- TRouterContext,
314
- TRouteContextFn,
315
- TBeforeLoadFn
316
- > &
317
- RoutePathOptionsIntersection<TCustomId, TPath>)
318
- | undefined
319
-
320
- const isRoot = !options?.path && !options?.id
321
-
322
- this.parentRoute = this.options.getParentRoute?.()
323
-
324
- if (isRoot) {
325
- this._path = rootRouteId as TPath
326
- } else {
327
- invariant(
328
- this.parentRoute,
329
- `Child Route instances must pass a 'getParentRoute: () => ParentRoute' option that returns a Route instance.`,
330
- )
331
- }
332
-
333
- let path: undefined | string = isRoot ? rootRouteId : options.path
334
-
335
- // If the path is anything other than an index path, trim it up
336
- if (path && path !== '/') {
337
- path = trimPathLeft(path)
338
- }
339
-
340
- const customId = options?.id || path
341
-
342
- // Strip the parentId prefix from the first level of children
343
- let id = isRoot
344
- ? rootRouteId
345
- : joinPaths([
346
- this.parentRoute.id === rootRouteId ? '' : this.parentRoute.id,
347
- customId,
348
- ])
349
-
350
- if (path === rootRouteId) {
351
- path = '/'
352
- }
353
-
354
- if (id !== rootRouteId) {
355
- id = joinPaths(['/', id])
356
- }
357
-
358
- const fullPath =
359
- id === rootRouteId ? '/' : joinPaths([this.parentRoute.fullPath, path])
360
-
361
- this._path = path as TPath
362
- this._id = id as TId
363
- // this.customId = customId as TCustomId
364
- this._fullPath = fullPath as TFullPath
365
- this._to = fullPath as TrimPathRight<TFullPath>
366
- this._ssr = options?.ssr ?? opts.defaultSsr ?? true
367
- }
368
-
369
- addChildren: RouteAddChildrenFn<
370
- TParentRoute,
371
- TPath,
372
- TFullPath,
373
- TCustomId,
374
- TId,
375
- TSearchValidator,
376
- TParams,
377
- TRouterContext,
378
- TRouteContextFn,
379
- TBeforeLoadFn,
380
- TLoaderDeps,
381
- TLoaderFn,
382
- TFileRouteTypes
383
- > = (children) => {
384
- return this._addFileChildren(children) as any
385
- }
386
-
387
- _addFileChildren: RouteAddFileChildrenFn<
388
- TParentRoute,
389
- TPath,
390
- TFullPath,
391
- TCustomId,
392
- TId,
393
- TSearchValidator,
394
- TParams,
395
- TRouterContext,
396
- TRouteContextFn,
397
- TBeforeLoadFn,
398
- TLoaderDeps,
399
- TLoaderFn,
400
- TFileRouteTypes
401
- > = (children) => {
402
- if (Array.isArray(children)) {
403
- this.children = children as TChildren
404
- }
405
-
406
- if (typeof children === 'object' && children !== null) {
407
- this.children = Object.values(children) as TChildren
408
- }
409
-
410
- return this as any
411
- }
412
-
413
- _addFileTypes: RouteAddFileTypesFn<
414
- TParentRoute,
415
- TPath,
416
- TFullPath,
417
- TCustomId,
418
- TId,
419
- TSearchValidator,
420
- TParams,
421
- TRouterContext,
422
- TRouteContextFn,
423
- TBeforeLoadFn,
424
- TLoaderDeps,
425
- TLoaderFn,
426
- TChildren
427
- > = () => {
428
- return this as any
429
- }
430
-
431
- updateLoader = <TNewLoaderFn>(options: {
432
- loader: Constrain<
433
- TNewLoaderFn,
434
- RouteLoaderFn<
435
- TParentRoute,
436
- TCustomId,
437
- TParams,
438
- TLoaderDeps,
439
- TRouterContext,
440
- TRouteContextFn,
441
- TBeforeLoadFn
442
- >
443
- >
444
- }) => {
445
- Object.assign(this.options, options)
446
- return this as unknown as Route<
447
- TParentRoute,
448
- TPath,
449
- TFullPath,
450
- TCustomId,
451
- TId,
452
- TSearchValidator,
453
- TParams,
454
- TRouterContext,
455
- TRouteContextFn,
456
- TBeforeLoadFn,
457
- TLoaderDeps,
458
- TNewLoaderFn,
459
- TChildren,
460
- TFileRouteTypes
461
- >
462
- }
463
-
464
- update = (
465
- options: UpdatableRouteOptions<
466
- TParentRoute,
467
- TCustomId,
468
- TFullPath,
469
- TParams,
470
- TSearchValidator,
471
- TLoaderFn,
472
- TLoaderDeps,
473
- TRouterContext,
474
- TRouteContextFn,
475
- TBeforeLoadFn
476
- >,
477
- ): this => {
478
- Object.assign(this.options, options)
479
- return this
480
- }
481
-
482
- lazy: RouteLazyFn<this> = (lazyFn) => {
483
- this.lazyFn = lazyFn
484
- return this
190
+ super(options)
485
191
  }
486
192
 
487
193
  useMatch: UseMatchRoute<TId> = (opts) => {
@@ -561,7 +267,7 @@ export function createRoute<
561
267
  TRouteContextFn,
562
268
  TBeforeLoadFn
563
269
  >,
564
- ): CoreRoute<
270
+ ): Route<
565
271
  TParentRoute,
566
272
  TPath,
567
273
  TFullPath,
@@ -590,7 +296,8 @@ export function createRoute<
590
296
  TBeforeLoadFn,
591
297
  TLoaderDeps,
592
298
  TLoaderFn,
593
- TChildren
299
+ TChildren,
300
+ unknown
594
301
  >(options)
595
302
  }
596
303
 
@@ -638,20 +345,14 @@ export class RootRoute<
638
345
  in out TLoaderFn = undefined,
639
346
  in out TChildren = unknown,
640
347
  in out TFileRouteTypes = unknown,
641
- > extends Route<
642
- any, // TParentRoute
643
- '/', // TPath
644
- '/', // TFullPath
645
- string, // TCustomId
646
- RootRouteId, // TId
647
- TSearchValidator, // TSearchValidator
648
- {}, // TParams
348
+ > extends BaseRootRoute<
349
+ TSearchValidator,
649
350
  TRouterContext,
650
351
  TRouteContextFn,
651
352
  TBeforeLoadFn,
652
353
  TLoaderDeps,
653
354
  TLoaderFn,
654
- TChildren, // TChildren
355
+ TChildren,
655
356
  TFileRouteTypes
656
357
  > {
657
358
  /**
@@ -667,35 +368,49 @@ export class RootRoute<
667
368
  TLoaderFn
668
369
  >,
669
370
  ) {
670
- super(options as any)
371
+ super(options)
671
372
  }
672
- }
673
373
 
674
- export function createRootRoute<
675
- TSearchValidator = undefined,
676
- TRouterContext = {},
677
- TRouteContextFn = AnyContext,
678
- TBeforeLoadFn = AnyContext,
679
- TLoaderDeps extends Record<string, any> = {},
680
- TLoaderFn = undefined,
681
- >(
682
- options?: RootRouteOptions<
683
- TSearchValidator,
684
- TRouterContext,
685
- TRouteContextFn,
686
- TBeforeLoadFn,
687
- TLoaderDeps,
688
- TLoaderFn
689
- >,
690
- ) {
691
- return new RootRoute<
692
- TSearchValidator,
693
- TRouterContext,
694
- TRouteContextFn,
695
- TBeforeLoadFn,
696
- TLoaderDeps,
697
- TLoaderFn
698
- >(options)
374
+ useMatch: UseMatchRoute<RootRouteId> = (opts) => {
375
+ return useMatch({
376
+ select: opts?.select,
377
+ from: this.id,
378
+ } as any) as any
379
+ }
380
+
381
+ useRouteContext: UseRouteContextRoute<RootRouteId> = (opts) => {
382
+ return useMatch({
383
+ ...opts,
384
+ from: this.id,
385
+ select: (d) => (opts?.select ? opts.select(d.context) : d.context),
386
+ }) as any
387
+ }
388
+
389
+ useSearch: UseSearchRoute<RootRouteId> = (opts) => {
390
+ return useSearch({
391
+ select: opts?.select,
392
+ from: this.id,
393
+ } as any) as any
394
+ }
395
+
396
+ useParams: UseParamsRoute<RootRouteId> = (opts) => {
397
+ return useParams({
398
+ select: opts?.select,
399
+ from: this.id,
400
+ } as any) as any
401
+ }
402
+
403
+ useLoaderDeps: UseLoaderDepsRoute<RootRouteId> = (opts) => {
404
+ return useLoaderDeps({ ...opts, from: this.id } as any)
405
+ }
406
+
407
+ useLoaderData: UseLoaderDataRoute<RootRouteId> = (opts) => {
408
+ return useLoaderData({ ...opts, from: this.id } as any)
409
+ }
410
+
411
+ useNavigate = (): UseNavigateResult<'/'> => {
412
+ return useNavigate({ from: this.fullPath })
413
+ }
699
414
  }
700
415
 
701
416
  export function createRouteMask<
@@ -705,7 +420,7 @@ export function createRouteMask<
705
420
  >(
706
421
  opts: {
707
422
  routeTree: TRouteTree
708
- } & ToMaskOptions<Router<TRouteTree, 'never', false>, TFrom, TTo>,
423
+ } & ToMaskOptions<RouterCore<TRouteTree, 'never', false>, TFrom, TTo>,
709
424
  ): RouteMask<TRouteTree> {
710
425
  return opts as any
711
426
  }
@@ -778,3 +493,39 @@ export class NotFoundRoute<
778
493
  })
779
494
  }
780
495
  }
496
+
497
+ export function createRootRoute<
498
+ TSearchValidator = undefined,
499
+ TRouterContext = {},
500
+ TRouteContextFn = AnyContext,
501
+ TBeforeLoadFn = AnyContext,
502
+ TLoaderDeps extends Record<string, any> = {},
503
+ TLoaderFn = undefined,
504
+ >(
505
+ options?: RootRouteOptions<
506
+ TSearchValidator,
507
+ TRouterContext,
508
+ TRouteContextFn,
509
+ TBeforeLoadFn,
510
+ TLoaderDeps,
511
+ TLoaderFn
512
+ >,
513
+ ): RootRoute<
514
+ TSearchValidator,
515
+ TRouterContext,
516
+ TRouteContextFn,
517
+ TBeforeLoadFn,
518
+ TLoaderDeps,
519
+ TLoaderFn,
520
+ unknown,
521
+ unknown
522
+ > {
523
+ return new RootRoute<
524
+ TSearchValidator,
525
+ TRouterContext,
526
+ TRouteContextFn,
527
+ TBeforeLoadFn,
528
+ TLoaderDeps,
529
+ TLoaderFn
530
+ >(options)
531
+ }