@tanstack/react-router 1.97.14 → 1.97.17
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/dist/cjs/Match.cjs +8 -24
- package/dist/cjs/Match.cjs.map +1 -1
- package/dist/cjs/Matches.cjs +1 -1
- package/dist/cjs/Matches.cjs.map +1 -1
- package/dist/cjs/RouterProvider.cjs.map +1 -1
- package/dist/cjs/RouterProvider.d.cts +0 -1
- package/dist/cjs/ScriptOnce.cjs +1 -8
- package/dist/cjs/ScriptOnce.cjs.map +1 -1
- package/dist/cjs/ScriptOnce.d.cts +1 -1
- package/dist/cjs/Transitioner.cjs +1 -2
- package/dist/cjs/Transitioner.cjs.map +1 -1
- package/dist/cjs/awaited.cjs +1 -22
- package/dist/cjs/awaited.cjs.map +1 -1
- package/dist/cjs/index.cjs +2 -7
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +4 -6
- package/dist/cjs/router.cjs +11 -129
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +33 -93
- package/dist/cjs/routerContext.cjs.map +1 -1
- package/dist/cjs/routerContext.d.cts +7 -2
- package/dist/cjs/serializer.d.cts +15 -0
- package/dist/cjs/useRouterState.cjs +1 -1
- package/dist/cjs/useRouterState.cjs.map +1 -1
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +2 -2
- package/dist/esm/Match.js +9 -25
- package/dist/esm/Match.js.map +1 -1
- package/dist/esm/Matches.js +1 -1
- package/dist/esm/Matches.js.map +1 -1
- package/dist/esm/RouterProvider.d.ts +0 -1
- package/dist/esm/RouterProvider.js.map +1 -1
- package/dist/esm/ScriptOnce.d.ts +1 -1
- package/dist/esm/ScriptOnce.js +1 -8
- package/dist/esm/ScriptOnce.js.map +1 -1
- package/dist/esm/Transitioner.js +1 -2
- package/dist/esm/Transitioner.js.map +1 -1
- package/dist/esm/awaited.js +1 -22
- package/dist/esm/awaited.js.map +1 -1
- package/dist/esm/index.d.ts +4 -6
- package/dist/esm/index.js +1 -6
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/router.d.ts +33 -93
- package/dist/esm/router.js +11 -129
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/routerContext.d.ts +7 -2
- package/dist/esm/routerContext.js.map +1 -1
- package/dist/esm/serializer.d.ts +15 -0
- package/dist/esm/useRouterState.js +1 -1
- package/dist/esm/useRouterState.js.map +1 -1
- package/dist/esm/utils.d.ts +2 -2
- package/dist/esm/utils.js.map +1 -1
- package/package.json +1 -1
- package/src/Match.tsx +4 -29
- package/src/Matches.tsx +1 -1
- package/src/RouterProvider.tsx +3 -3
- package/src/ScriptOnce.tsx +0 -8
- package/src/Transitioner.tsx +1 -1
- package/src/awaited.tsx +3 -25
- package/src/index.tsx +12 -34
- package/src/router.ts +44 -271
- package/src/routerContext.tsx +7 -1
- package/src/serializer.ts +24 -0
- package/src/useRouterState.tsx +1 -1
- package/src/utils.ts +1 -1
- package/dist/cjs/isServerSideError.cjs +0 -22
- package/dist/cjs/isServerSideError.cjs.map +0 -1
- package/dist/cjs/isServerSideError.d.cts +0 -5
- package/dist/cjs/transformer.cjs +0 -137
- package/dist/cjs/transformer.cjs.map +0 -1
- package/dist/cjs/transformer.d.cts +0 -16
- package/dist/esm/isServerSideError.d.ts +0 -5
- package/dist/esm/isServerSideError.js +0 -22
- package/dist/esm/isServerSideError.js.map +0 -1
- package/dist/esm/transformer.d.ts +0 -16
- package/dist/esm/transformer.js +0 -137
- package/dist/esm/transformer.js.map +0 -1
- package/src/isServerSideError.tsx +0 -23
- package/src/transformer.ts +0 -192
package/src/router.ts
CHANGED
|
@@ -5,8 +5,6 @@ import {
|
|
|
5
5
|
} from '@tanstack/history'
|
|
6
6
|
import { Store, batch } from '@tanstack/react-store'
|
|
7
7
|
import invariant from 'tiny-invariant'
|
|
8
|
-
import warning from 'tiny-warning'
|
|
9
|
-
import jsesc from 'jsesc'
|
|
10
8
|
import { rootRouteId } from './root'
|
|
11
9
|
import { defaultParseSearch, defaultStringifySearch } from './searchParams'
|
|
12
10
|
import {
|
|
@@ -30,7 +28,7 @@ import {
|
|
|
30
28
|
} from './path'
|
|
31
29
|
import { isRedirect, isResolvedRedirect } from './redirects'
|
|
32
30
|
import { isNotFound } from './not-found'
|
|
33
|
-
import {
|
|
31
|
+
import type { StartSerializer } from './serializer'
|
|
34
32
|
import type * as React from 'react'
|
|
35
33
|
import type {
|
|
36
34
|
HistoryLocation,
|
|
@@ -83,42 +81,15 @@ import type {
|
|
|
83
81
|
import type { AnyRedirect, ResolvedRedirect } from './redirects'
|
|
84
82
|
import type { NotFoundError } from './not-found'
|
|
85
83
|
import type { NavigateOptions, ResolveRelativePath, ToOptions } from './link'
|
|
86
|
-
import type { RouterTransformer } from './transformer'
|
|
87
84
|
import type { AnySchema, AnyValidator } from './validators'
|
|
88
85
|
|
|
89
|
-
export interface TSRGlobalMatch {
|
|
90
|
-
index: number
|
|
91
|
-
__beforeLoadContext?: string
|
|
92
|
-
loaderData?: string
|
|
93
|
-
extracted: Record<string, ClientExtractedEntry>
|
|
94
|
-
}
|
|
95
|
-
export interface TSRGlobal {
|
|
96
|
-
matches: Array<TSRGlobalMatch>
|
|
97
|
-
streamedValues: Record<
|
|
98
|
-
string,
|
|
99
|
-
{
|
|
100
|
-
value: any
|
|
101
|
-
parsed: any
|
|
102
|
-
}
|
|
103
|
-
>
|
|
104
|
-
cleanScripts: () => void
|
|
105
|
-
dehydrated?: any
|
|
106
|
-
}
|
|
107
86
|
declare global {
|
|
108
87
|
interface Window {
|
|
109
|
-
|
|
110
|
-
__TSR_ROUTER_CONTEXT__?: React.Context<Router<any, any, any>>
|
|
88
|
+
__TSR_ROUTER__?: AnyRouter
|
|
111
89
|
}
|
|
112
90
|
}
|
|
113
91
|
|
|
114
|
-
type RegisteredTSRGlobal = Register extends {
|
|
115
|
-
__TSR__: infer TTSR extends TSRGlobal
|
|
116
|
-
}
|
|
117
|
-
? TTSR
|
|
118
|
-
: TSRGlobal
|
|
119
|
-
|
|
120
92
|
export interface Register {
|
|
121
|
-
// __TSR__: TSRGlobal
|
|
122
93
|
// router: Router
|
|
123
94
|
}
|
|
124
95
|
|
|
@@ -138,11 +109,6 @@ export type RegisteredRouter = Register extends {
|
|
|
138
109
|
? TRouter
|
|
139
110
|
: AnyRouter
|
|
140
111
|
|
|
141
|
-
export type HydrationCtx = {
|
|
142
|
-
router: DehydratedRouter
|
|
143
|
-
payload: Record<string, any>
|
|
144
|
-
}
|
|
145
|
-
|
|
146
112
|
export type InferRouterContext<TRouteTree extends AnyRoute> =
|
|
147
113
|
TRouteTree extends RootRoute<
|
|
148
114
|
any,
|
|
@@ -157,32 +123,10 @@ export type InferRouterContext<TRouteTree extends AnyRoute> =
|
|
|
157
123
|
? TRouterContext
|
|
158
124
|
: AnyContext
|
|
159
125
|
|
|
160
|
-
export interface ClientExtractedBaseEntry {
|
|
161
|
-
type: string
|
|
162
|
-
path: Array<string>
|
|
163
|
-
}
|
|
164
|
-
|
|
165
126
|
export type ControllablePromise<T = any> = Promise<T> & {
|
|
166
127
|
resolve: (value: T) => void
|
|
167
128
|
reject: (value?: any) => void
|
|
168
129
|
}
|
|
169
|
-
export interface ClientExtractedPromise extends ClientExtractedBaseEntry {
|
|
170
|
-
type: 'promise'
|
|
171
|
-
value?: ControllablePromise<any>
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
export interface ClientExtractedStream extends ClientExtractedBaseEntry {
|
|
175
|
-
type: 'stream'
|
|
176
|
-
value?: ReadableStream & { controller?: ReadableStreamDefaultController }
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
export type ClientExtractedEntry =
|
|
180
|
-
| ClientExtractedStream
|
|
181
|
-
| ClientExtractedPromise
|
|
182
|
-
|
|
183
|
-
export type StreamState = {
|
|
184
|
-
promises: Array<ControlledPromise<string | null>>
|
|
185
|
-
}
|
|
186
130
|
|
|
187
131
|
export type RouterContextOptions<TRouteTree extends AnyRoute> =
|
|
188
132
|
AnyContext extends InferRouterContext<TRouteTree>
|
|
@@ -195,13 +139,14 @@ export type RouterContextOptions<TRouteTree extends AnyRoute> =
|
|
|
195
139
|
|
|
196
140
|
export type TrailingSlashOption = 'always' | 'never' | 'preserve'
|
|
197
141
|
|
|
142
|
+
export type InjectedHtmlEntry = Promise<string>
|
|
143
|
+
|
|
198
144
|
export interface RouterOptions<
|
|
199
145
|
TRouteTree extends AnyRoute,
|
|
200
146
|
TTrailingSlashOption extends TrailingSlashOption,
|
|
201
147
|
TDefaultStructuralSharingOption extends boolean = false,
|
|
202
148
|
TRouterHistory extends RouterHistory = RouterHistory,
|
|
203
149
|
TDehydrated extends Record<string, any> = Record<string, any>,
|
|
204
|
-
TSerializedError extends Record<string, any> = Record<string, any>,
|
|
205
150
|
> {
|
|
206
151
|
/**
|
|
207
152
|
* The history object that will be used to manage the browser history.
|
|
@@ -456,19 +401,6 @@ export interface RouterOptions<
|
|
|
456
401
|
* @link [Guide](https://tanstack.com/router/latest/docs/framework/react/guide/not-found-errors#default-router-wide-not-found-handling)
|
|
457
402
|
*/
|
|
458
403
|
defaultNotFoundComponent?: NotFoundRouteComponent
|
|
459
|
-
/**
|
|
460
|
-
* The transformer that will be used when sending data between the server and the client during SSR.
|
|
461
|
-
*
|
|
462
|
-
* @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RouterOptionsType#transformer-property)
|
|
463
|
-
* @link [Guide](https://tanstack.com/router/latest/docs/framework/react/guide/ssr#data-transformers)
|
|
464
|
-
*/
|
|
465
|
-
transformer?: RouterTransformer
|
|
466
|
-
/**
|
|
467
|
-
* The serializer object that will be used to determine how errors are serialized and deserialized between the server and the client.
|
|
468
|
-
*
|
|
469
|
-
* @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RouterOptionsType#errorserializer-property)
|
|
470
|
-
*/
|
|
471
|
-
errorSerializer?: RouterErrorSerializer<TSerializedError>
|
|
472
404
|
/**
|
|
473
405
|
* Configures how trailing slashes are treated.
|
|
474
406
|
*
|
|
@@ -566,20 +498,6 @@ export interface MatchedRoutesResult {
|
|
|
566
498
|
routeParams: Record<string, string>
|
|
567
499
|
}
|
|
568
500
|
|
|
569
|
-
export interface DehydratedRouterState {
|
|
570
|
-
dehydratedMatches: Array<DehydratedRouteMatch>
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
export type DehydratedRouteMatch = Pick<
|
|
574
|
-
MakeRouteMatch,
|
|
575
|
-
'id' | 'status' | 'updatedAt' | 'loaderData'
|
|
576
|
-
>
|
|
577
|
-
|
|
578
|
-
export interface DehydratedRouter {
|
|
579
|
-
state: DehydratedRouterState
|
|
580
|
-
manifest?: Manifest
|
|
581
|
-
}
|
|
582
|
-
|
|
583
501
|
export interface ViewTransitionOptions {
|
|
584
502
|
types: Array<string>
|
|
585
503
|
}
|
|
@@ -590,15 +508,13 @@ export type RouterConstructorOptions<
|
|
|
590
508
|
TDefaultStructuralSharingOption extends boolean,
|
|
591
509
|
TRouterHistory extends RouterHistory,
|
|
592
510
|
TDehydrated extends Record<string, any>,
|
|
593
|
-
TSerializedError extends Record<string, any>,
|
|
594
511
|
> = Omit<
|
|
595
512
|
RouterOptions<
|
|
596
513
|
TRouteTree,
|
|
597
514
|
TTrailingSlashOption,
|
|
598
515
|
TDefaultStructuralSharingOption,
|
|
599
516
|
TRouterHistory,
|
|
600
|
-
TDehydrated
|
|
601
|
-
TSerializedError
|
|
517
|
+
TDehydrated
|
|
602
518
|
>,
|
|
603
519
|
'context'
|
|
604
520
|
> &
|
|
@@ -682,6 +598,10 @@ export type RouterEvents = {
|
|
|
682
598
|
pathChanged: boolean
|
|
683
599
|
hrefChanged: boolean
|
|
684
600
|
}
|
|
601
|
+
onInjectedHtml: {
|
|
602
|
+
type: 'onInjectedHtml'
|
|
603
|
+
promise: Promise<string>
|
|
604
|
+
}
|
|
685
605
|
}
|
|
686
606
|
|
|
687
607
|
export type RouterEvent = RouterEvents[keyof RouterEvents]
|
|
@@ -706,8 +626,7 @@ export function createRouter<
|
|
|
706
626
|
TTrailingSlashOption,
|
|
707
627
|
TDefaultStructuralSharingOption,
|
|
708
628
|
TRouterHistory,
|
|
709
|
-
TDehydrated
|
|
710
|
-
TSerializedError
|
|
629
|
+
TDehydrated
|
|
711
630
|
>,
|
|
712
631
|
) {
|
|
713
632
|
return new Router<
|
|
@@ -743,42 +662,18 @@ export class Router<
|
|
|
743
662
|
shouldViewTransition?: boolean | ViewTransitionOptions = undefined
|
|
744
663
|
isViewTransitionTypesSupported?: boolean = undefined
|
|
745
664
|
subscribers = new Set<RouterListener<RouterEvent>>()
|
|
746
|
-
dehydratedData?: TDehydrated
|
|
747
665
|
viewTransitionPromise?: ControlledPromise<true>
|
|
748
|
-
manifest?: Manifest
|
|
749
|
-
AfterEachMatch?: (props: {
|
|
750
|
-
match: Pick<
|
|
751
|
-
AnyRouteMatch,
|
|
752
|
-
'id' | 'status' | 'error' | 'loadPromise' | 'minPendingPromise'
|
|
753
|
-
>
|
|
754
|
-
matchIndex: number
|
|
755
|
-
}) => any
|
|
756
|
-
serializeLoaderData?: (
|
|
757
|
-
type: '__beforeLoadContext' | 'loaderData',
|
|
758
|
-
loaderData: any,
|
|
759
|
-
ctx: {
|
|
760
|
-
router: AnyRouter
|
|
761
|
-
match: AnyRouteMatch
|
|
762
|
-
},
|
|
763
|
-
) => any
|
|
764
|
-
serializer?: (data: any) => string
|
|
765
666
|
|
|
766
667
|
// Must build in constructor
|
|
767
668
|
__store!: Store<RouterState<TRouteTree>>
|
|
768
669
|
options!: PickAsRequired<
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
TSerializedError
|
|
777
|
-
>,
|
|
778
|
-
'transformer'
|
|
779
|
-
> & {
|
|
780
|
-
transformer: RouterTransformer
|
|
781
|
-
},
|
|
670
|
+
RouterOptions<
|
|
671
|
+
TRouteTree,
|
|
672
|
+
TTrailingSlashOption,
|
|
673
|
+
TDefaultStructuralSharingOption,
|
|
674
|
+
TRouterHistory,
|
|
675
|
+
TDehydrated
|
|
676
|
+
>,
|
|
782
677
|
'stringifySearch' | 'parseSearch' | 'context'
|
|
783
678
|
>
|
|
784
679
|
history!: TRouterHistory
|
|
@@ -800,8 +695,7 @@ export class Router<
|
|
|
800
695
|
TTrailingSlashOption,
|
|
801
696
|
TDefaultStructuralSharingOption,
|
|
802
697
|
TRouterHistory,
|
|
803
|
-
TDehydrated
|
|
804
|
-
TSerializedError
|
|
698
|
+
TDehydrated
|
|
805
699
|
>,
|
|
806
700
|
) {
|
|
807
701
|
this.update({
|
|
@@ -814,11 +708,10 @@ export class Router<
|
|
|
814
708
|
notFoundMode: options.notFoundMode ?? 'fuzzy',
|
|
815
709
|
stringifySearch: options.stringifySearch ?? defaultStringifySearch,
|
|
816
710
|
parseSearch: options.parseSearch ?? defaultParseSearch,
|
|
817
|
-
transformer: options.transformer ?? defaultTransformer,
|
|
818
711
|
})
|
|
819
712
|
|
|
820
713
|
if (typeof document !== 'undefined') {
|
|
821
|
-
;(window as any).
|
|
714
|
+
;(window as any).__TSR_ROUTER__ = this
|
|
822
715
|
}
|
|
823
716
|
}
|
|
824
717
|
|
|
@@ -833,8 +726,7 @@ export class Router<
|
|
|
833
726
|
TTrailingSlashOption,
|
|
834
727
|
TDefaultStructuralSharingOption,
|
|
835
728
|
TRouterHistory,
|
|
836
|
-
TDehydrated
|
|
837
|
-
TSerializedError
|
|
729
|
+
TDehydrated
|
|
838
730
|
>,
|
|
839
731
|
) => {
|
|
840
732
|
if (newOptions.notFoundRoute) {
|
|
@@ -1623,7 +1515,7 @@ export class Router<
|
|
|
1623
1515
|
}) ?? {}),
|
|
1624
1516
|
}
|
|
1625
1517
|
}
|
|
1626
|
-
} catch
|
|
1518
|
+
} catch {
|
|
1627
1519
|
// ignore errors here because they are already handled in matchRoutes
|
|
1628
1520
|
}
|
|
1629
1521
|
})
|
|
@@ -1685,7 +1577,7 @@ export class Router<
|
|
|
1685
1577
|
) ?? {}),
|
|
1686
1578
|
}
|
|
1687
1579
|
return validatedSearch
|
|
1688
|
-
} catch
|
|
1580
|
+
} catch {
|
|
1689
1581
|
// ignore errors here because they are already handled in matchRoutes
|
|
1690
1582
|
}
|
|
1691
1583
|
}
|
|
@@ -2448,21 +2340,10 @@ export class Router<
|
|
|
2448
2340
|
matches,
|
|
2449
2341
|
}
|
|
2450
2342
|
|
|
2451
|
-
|
|
2343
|
+
const beforeLoadContext =
|
|
2452
2344
|
(await route.options.beforeLoad?.(beforeLoadFnContext)) ??
|
|
2453
2345
|
{}
|
|
2454
2346
|
|
|
2455
|
-
if (this.serializeLoaderData) {
|
|
2456
|
-
beforeLoadContext = this.serializeLoaderData(
|
|
2457
|
-
'__beforeLoadContext',
|
|
2458
|
-
beforeLoadContext,
|
|
2459
|
-
{
|
|
2460
|
-
router: this,
|
|
2461
|
-
match: this.getMatch(matchId)!,
|
|
2462
|
-
},
|
|
2463
|
-
)
|
|
2464
|
-
}
|
|
2465
|
-
|
|
2466
2347
|
if (
|
|
2467
2348
|
isRedirect(beforeLoadContext) ||
|
|
2468
2349
|
isNotFound(beforeLoadContext)
|
|
@@ -2602,20 +2483,9 @@ export class Router<
|
|
|
2602
2483
|
}))
|
|
2603
2484
|
|
|
2604
2485
|
// Kick off the loader!
|
|
2605
|
-
|
|
2486
|
+
const loaderData =
|
|
2606
2487
|
await route.options.loader?.(getLoaderContext())
|
|
2607
2488
|
|
|
2608
|
-
if (this.serializeLoaderData) {
|
|
2609
|
-
loaderData = this.serializeLoaderData(
|
|
2610
|
-
'loaderData',
|
|
2611
|
-
loaderData,
|
|
2612
|
-
{
|
|
2613
|
-
router: this,
|
|
2614
|
-
match: this.getMatch(matchId)!,
|
|
2615
|
-
},
|
|
2616
|
-
)
|
|
2617
|
-
}
|
|
2618
|
-
|
|
2619
2489
|
handleRedirectAndNotFound(
|
|
2620
2490
|
this.getMatch(matchId)!,
|
|
2621
2491
|
loaderData,
|
|
@@ -2679,6 +2549,11 @@ export class Router<
|
|
|
2679
2549
|
}))
|
|
2680
2550
|
}
|
|
2681
2551
|
|
|
2552
|
+
this.serverSsr?.onMatchSettled({
|
|
2553
|
+
router: this,
|
|
2554
|
+
match: this.getMatch(matchId)!,
|
|
2555
|
+
})
|
|
2556
|
+
|
|
2682
2557
|
// Last but not least, wait for the the components
|
|
2683
2558
|
// to be preloaded before we resolve the match
|
|
2684
2559
|
await route._componentsPromise
|
|
@@ -3028,127 +2903,25 @@ export class Router<
|
|
|
3028
2903
|
return match
|
|
3029
2904
|
}
|
|
3030
2905
|
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
return {
|
|
3036
|
-
state: {
|
|
3037
|
-
dehydratedMatches: this.state.matches.map((d) => {
|
|
3038
|
-
return {
|
|
3039
|
-
...pick(d, ['id', 'status', 'updatedAt']),
|
|
3040
|
-
// If an error occurs server-side during SSRing,
|
|
3041
|
-
// send a small subset of the error to the client
|
|
3042
|
-
error: d.error
|
|
3043
|
-
? {
|
|
3044
|
-
data: pickError(d.error),
|
|
3045
|
-
__isServerError: true,
|
|
3046
|
-
}
|
|
3047
|
-
: undefined,
|
|
3048
|
-
// NOTE: We don't send the loader data here, because
|
|
3049
|
-
// there is a potential that it needs to be streamed.
|
|
3050
|
-
// Instead, we render it next to the route match in the HTML
|
|
3051
|
-
// which gives us the potential to stream it via suspense.
|
|
3052
|
-
}
|
|
3053
|
-
}),
|
|
3054
|
-
},
|
|
3055
|
-
manifest: this.manifest,
|
|
3056
|
-
}
|
|
2906
|
+
ssr?: {
|
|
2907
|
+
manifest: Manifest | undefined
|
|
2908
|
+
serializer: StartSerializer
|
|
3057
2909
|
}
|
|
3058
2910
|
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
'Expected to find a dehydrated data on window.__TSR__.dehydrated... but we did not. Please file an issue!',
|
|
3070
|
-
)
|
|
3071
|
-
|
|
3072
|
-
this.dehydratedData = ctx.payload as any
|
|
3073
|
-
this.options.hydrate?.(ctx.payload as any)
|
|
3074
|
-
const dehydratedState = ctx.router.state
|
|
3075
|
-
|
|
3076
|
-
const matches = this.matchRoutes(this.state.location).map((match) => {
|
|
3077
|
-
const dehydratedMatch = dehydratedState.dehydratedMatches.find(
|
|
3078
|
-
(d) => d.id === match.id,
|
|
3079
|
-
)
|
|
3080
|
-
|
|
3081
|
-
invariant(
|
|
3082
|
-
dehydratedMatch,
|
|
3083
|
-
`Could not find a client-side match for dehydrated match with id: ${match.id}!`,
|
|
3084
|
-
)
|
|
3085
|
-
|
|
3086
|
-
return {
|
|
3087
|
-
...match,
|
|
3088
|
-
...dehydratedMatch,
|
|
3089
|
-
}
|
|
3090
|
-
})
|
|
3091
|
-
|
|
3092
|
-
this.__store.setState((s) => {
|
|
3093
|
-
return {
|
|
3094
|
-
...s,
|
|
3095
|
-
matches: matches as any,
|
|
3096
|
-
}
|
|
3097
|
-
})
|
|
3098
|
-
|
|
3099
|
-
this.manifest = ctx.router.manifest
|
|
2911
|
+
serverSsr?: {
|
|
2912
|
+
injectedHtml: Array<InjectedHtmlEntry>
|
|
2913
|
+
injectHtml: (getHtml: () => string | Promise<string>) => Promise<void>
|
|
2914
|
+
injectScript: (
|
|
2915
|
+
getScript: () => string | Promise<string>,
|
|
2916
|
+
opts?: { logScript?: boolean },
|
|
2917
|
+
) => Promise<void>
|
|
2918
|
+
streamValue: (key: string, value: any) => void
|
|
2919
|
+
streamedKeys: Set<string>
|
|
2920
|
+
onMatchSettled: (opts: { router: AnyRouter; match: AnyRouteMatch }) => any
|
|
3100
2921
|
}
|
|
3101
2922
|
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
const cb = () => {
|
|
3105
|
-
this.injectedHtml = this.injectedHtml.filter((d) => d !== cb)
|
|
3106
|
-
return html
|
|
3107
|
-
}
|
|
3108
|
-
|
|
3109
|
-
this.injectedHtml.push(cb)
|
|
3110
|
-
}
|
|
3111
|
-
injectScript = (script: string, opts?: { logScript?: boolean }) => {
|
|
3112
|
-
this.injectHtml(
|
|
3113
|
-
`<script class='tsr-once'>${script}${
|
|
3114
|
-
process.env.NODE_ENV === 'development' && (opts?.logScript ?? true)
|
|
3115
|
-
? `; console.info(\`Injected From Server:
|
|
3116
|
-
${jsesc(script, { quotes: 'backtick' })}\`)`
|
|
3117
|
-
: ''
|
|
3118
|
-
}; if (typeof __TSR__ !== 'undefined') __TSR__.cleanScripts()</script>`,
|
|
3119
|
-
)
|
|
3120
|
-
}
|
|
3121
|
-
|
|
3122
|
-
streamedKeys: Set<string> = new Set()
|
|
3123
|
-
|
|
3124
|
-
getStreamedValue = <T>(key: string): T | undefined => {
|
|
3125
|
-
if (this.isServer) {
|
|
3126
|
-
return undefined
|
|
3127
|
-
}
|
|
3128
|
-
|
|
3129
|
-
const streamedValue = window.__TSR__?.streamedValues[key]
|
|
3130
|
-
|
|
3131
|
-
if (!streamedValue) {
|
|
3132
|
-
return
|
|
3133
|
-
}
|
|
3134
|
-
|
|
3135
|
-
if (!streamedValue.parsed) {
|
|
3136
|
-
streamedValue.parsed = this.options.transformer.parse(streamedValue.value)
|
|
3137
|
-
}
|
|
3138
|
-
|
|
3139
|
-
return streamedValue.parsed
|
|
3140
|
-
}
|
|
3141
|
-
|
|
3142
|
-
streamValue = (key: string, value: any) => {
|
|
3143
|
-
warning(
|
|
3144
|
-
!this.streamedKeys.has(key),
|
|
3145
|
-
'Key has already been streamed: ' + key,
|
|
3146
|
-
)
|
|
3147
|
-
|
|
3148
|
-
this.streamedKeys.add(key)
|
|
3149
|
-
this.injectScript(
|
|
3150
|
-
`__TSR__.streamedValues['${key}'] = { value: ${this.serializer?.(this.options.transformer.stringify(value))}}`,
|
|
3151
|
-
)
|
|
2923
|
+
clientSsr?: {
|
|
2924
|
+
getStreamedValue: <T>(key: string) => T | undefined
|
|
3152
2925
|
}
|
|
3153
2926
|
|
|
3154
2927
|
_handleNotFound = (
|
package/src/routerContext.tsx
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
|
-
import type { Router } from './router'
|
|
2
|
+
import type { AnyRouter, Router } from './router'
|
|
3
|
+
|
|
4
|
+
declare global {
|
|
5
|
+
interface Window {
|
|
6
|
+
__TSR_ROUTER_CONTEXT__?: React.Context<AnyRouter>
|
|
7
|
+
}
|
|
8
|
+
}
|
|
3
9
|
|
|
4
10
|
const routerContext = React.createContext<Router<any, any, any>>(null!)
|
|
5
11
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface StartSerializer {
|
|
2
|
+
stringify: (obj: unknown) => string
|
|
3
|
+
parse: (str: string) => unknown
|
|
4
|
+
encode: <T>(value: T) => T
|
|
5
|
+
decode: <T>(value: T) => T
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export type SerializerStringifyBy<T, TSerializable> = T extends TSerializable
|
|
9
|
+
? T
|
|
10
|
+
: T extends (...args: Array<any>) => any
|
|
11
|
+
? 'Function is not serializable'
|
|
12
|
+
: { [K in keyof T]: SerializerStringifyBy<T[K], TSerializable> }
|
|
13
|
+
|
|
14
|
+
export type SerializerParseBy<T, TSerializable> = T extends TSerializable
|
|
15
|
+
? T
|
|
16
|
+
: T extends React.JSX.Element
|
|
17
|
+
? ReadableStream
|
|
18
|
+
: { [K in keyof T]: SerializerParseBy<T[K], TSerializable> }
|
|
19
|
+
|
|
20
|
+
export type Serializable = Date | undefined | Error | FormData
|
|
21
|
+
|
|
22
|
+
export type SerializerStringify<T> = SerializerStringifyBy<T, Serializable>
|
|
23
|
+
|
|
24
|
+
export type SerializerParse<T> = SerializerParseBy<T, Serializable>
|
package/src/useRouterState.tsx
CHANGED
|
@@ -36,7 +36,7 @@ export function useRouterState<
|
|
|
36
36
|
})
|
|
37
37
|
const router = opts?.router || contextRouter
|
|
38
38
|
const previousResult =
|
|
39
|
-
useRef<ValidateSelected<TRouter, TSelected, TStructuralSharing>>()
|
|
39
|
+
useRef<ValidateSelected<TRouter, TSelected, TStructuralSharing>>(undefined)
|
|
40
40
|
|
|
41
41
|
return useStore(router.__store, (state) => {
|
|
42
42
|
if (opts?.select) {
|
package/src/utils.ts
CHANGED
|
@@ -470,7 +470,7 @@ export function usePrevious<T>(value: T): T | null {
|
|
|
470
470
|
* ```
|
|
471
471
|
*/
|
|
472
472
|
export function useIntersectionObserver<T extends Element>(
|
|
473
|
-
ref: React.RefObject<T>,
|
|
473
|
+
ref: React.RefObject<T | null>,
|
|
474
474
|
callback: (entry: IntersectionObserverEntry | undefined) => void,
|
|
475
475
|
intersectionObserverOptions: IntersectionObserverInit = {},
|
|
476
476
|
options: { disabled?: boolean } = {},
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
function isServerSideError(error) {
|
|
4
|
-
if (!(typeof error === "object" && error && "data" in error)) return false;
|
|
5
|
-
if (!("__isServerError" in error && error.__isServerError)) return false;
|
|
6
|
-
if (!(typeof error.data === "object" && error.data)) return false;
|
|
7
|
-
return error.__isServerError === true;
|
|
8
|
-
}
|
|
9
|
-
function defaultDeserializeError(serializedData) {
|
|
10
|
-
if ("name" in serializedData && "message" in serializedData) {
|
|
11
|
-
const error = new Error(serializedData.message);
|
|
12
|
-
error.name = serializedData.name;
|
|
13
|
-
if (process.env.NODE_ENV === "development") {
|
|
14
|
-
error.stack = serializedData.stack;
|
|
15
|
-
}
|
|
16
|
-
return error;
|
|
17
|
-
}
|
|
18
|
-
return serializedData.data;
|
|
19
|
-
}
|
|
20
|
-
exports.defaultDeserializeError = defaultDeserializeError;
|
|
21
|
-
exports.isServerSideError = isServerSideError;
|
|
22
|
-
//# sourceMappingURL=isServerSideError.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"isServerSideError.cjs","sources":["../../src/isServerSideError.tsx"],"sourcesContent":["export function isServerSideError(error: unknown): error is {\n __isServerError: true\n data: Record<string, any>\n} {\n if (!(typeof error === 'object' && error && 'data' in error)) return false\n if (!('__isServerError' in error && error.__isServerError)) return false\n if (!(typeof error.data === 'object' && error.data)) return false\n\n return error.__isServerError === true\n}\n\nexport function defaultDeserializeError(serializedData: Record<string, any>) {\n if ('name' in serializedData && 'message' in serializedData) {\n const error = new Error(serializedData.message)\n error.name = serializedData.name\n if (process.env.NODE_ENV === 'development') {\n error.stack = serializedData.stack\n }\n return error\n }\n\n return serializedData.data\n}\n"],"names":[],"mappings":";;AAAO,SAAS,kBAAkB,OAGhC;AACA,MAAI,EAAE,OAAO,UAAU,YAAY,SAAS,UAAU,OAAe,QAAA;AACrE,MAAI,EAAE,qBAAqB,SAAS,MAAM,iBAAyB,QAAA;AACnE,MAAI,EAAE,OAAO,MAAM,SAAS,YAAY,MAAM,MAAc,QAAA;AAE5D,SAAO,MAAM,oBAAoB;AACnC;AAEO,SAAS,wBAAwB,gBAAqC;AACvE,MAAA,UAAU,kBAAkB,aAAa,gBAAgB;AAC3D,UAAM,QAAQ,IAAI,MAAM,eAAe,OAAO;AAC9C,UAAM,OAAO,eAAe;AACxB,QAAA,QAAQ,IAAI,aAAa,eAAe;AAC1C,YAAM,QAAQ,eAAe;AAAA,IAAA;AAExB,WAAA;AAAA,EAAA;AAGT,SAAO,eAAe;AACxB;;;"}
|