@tanstack/router-core 1.126.2 → 1.127.2

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 (74) hide show
  1. package/dist/cjs/Matches.cjs.map +1 -1
  2. package/dist/cjs/Matches.d.cts +1 -1
  3. package/dist/cjs/index.d.cts +1 -2
  4. package/dist/cjs/router.cjs +8 -25
  5. package/dist/cjs/router.cjs.map +1 -1
  6. package/dist/cjs/router.d.cts +9 -57
  7. package/dist/cjs/ssr/client.cjs +0 -2
  8. package/dist/cjs/ssr/client.cjs.map +1 -1
  9. package/dist/cjs/ssr/client.d.cts +1 -2
  10. package/dist/cjs/ssr/createRequestHandler.cjs +2 -1
  11. package/dist/cjs/ssr/createRequestHandler.cjs.map +1 -1
  12. package/dist/cjs/ssr/seroval-plugins.cjs +34 -0
  13. package/dist/cjs/ssr/seroval-plugins.cjs.map +1 -0
  14. package/dist/cjs/ssr/seroval-plugins.d.cts +10 -0
  15. package/dist/cjs/ssr/server.cjs +0 -4
  16. package/dist/cjs/ssr/server.cjs.map +1 -1
  17. package/dist/cjs/ssr/server.d.cts +1 -3
  18. package/dist/cjs/ssr/ssr-client.cjs +18 -56
  19. package/dist/cjs/ssr/ssr-client.cjs.map +1 -1
  20. package/dist/cjs/ssr/ssr-client.d.cts +17 -57
  21. package/dist/cjs/ssr/ssr-server.cjs +75 -220
  22. package/dist/cjs/ssr/ssr-server.cjs.map +1 -1
  23. package/dist/cjs/ssr/ssr-server.d.cts +14 -28
  24. package/dist/cjs/ssr/transformStreamWithRouter.cjs +1 -0
  25. package/dist/cjs/ssr/transformStreamWithRouter.cjs.map +1 -1
  26. package/dist/cjs/ssr/tsrScript.cjs +1 -1
  27. package/dist/cjs/ssr/tsrScript.cjs.map +1 -1
  28. package/dist/cjs/ssr/tsrScript.d.cts +0 -1
  29. package/dist/esm/Matches.d.ts +1 -1
  30. package/dist/esm/Matches.js.map +1 -1
  31. package/dist/esm/index.d.ts +1 -2
  32. package/dist/esm/router.d.ts +9 -57
  33. package/dist/esm/router.js +8 -25
  34. package/dist/esm/router.js.map +1 -1
  35. package/dist/esm/ssr/client.d.ts +1 -2
  36. package/dist/esm/ssr/client.js +1 -3
  37. package/dist/esm/ssr/client.js.map +1 -1
  38. package/dist/esm/ssr/createRequestHandler.js +3 -2
  39. package/dist/esm/ssr/createRequestHandler.js.map +1 -1
  40. package/dist/esm/ssr/seroval-plugins.d.ts +10 -0
  41. package/dist/esm/ssr/seroval-plugins.js +34 -0
  42. package/dist/esm/ssr/seroval-plugins.js.map +1 -0
  43. package/dist/esm/ssr/server.d.ts +1 -3
  44. package/dist/esm/ssr/server.js +1 -5
  45. package/dist/esm/ssr/ssr-client.d.ts +17 -57
  46. package/dist/esm/ssr/ssr-client.js +18 -56
  47. package/dist/esm/ssr/ssr-client.js.map +1 -1
  48. package/dist/esm/ssr/ssr-server.d.ts +14 -28
  49. package/dist/esm/ssr/ssr-server.js +76 -221
  50. package/dist/esm/ssr/ssr-server.js.map +1 -1
  51. package/dist/esm/ssr/transformStreamWithRouter.js +1 -0
  52. package/dist/esm/ssr/transformStreamWithRouter.js.map +1 -1
  53. package/dist/esm/ssr/tsrScript.d.ts +0 -1
  54. package/dist/esm/ssr/tsrScript.js +1 -1
  55. package/dist/esm/ssr/tsrScript.js.map +1 -1
  56. package/package.json +3 -3
  57. package/src/Matches.ts +1 -1
  58. package/src/index.ts +0 -18
  59. package/src/router.ts +15 -82
  60. package/src/ssr/client.ts +1 -11
  61. package/src/ssr/createRequestHandler.ts +2 -2
  62. package/src/ssr/seroval-plugins.ts +43 -0
  63. package/src/ssr/server.ts +1 -14
  64. package/src/ssr/ssr-client.ts +35 -128
  65. package/src/ssr/ssr-server.ts +89 -307
  66. package/src/ssr/transformStreamWithRouter.ts +1 -0
  67. package/src/ssr/tsrScript.ts +4 -88
  68. package/dist/cjs/serializer.cjs +0 -146
  69. package/dist/cjs/serializer.cjs.map +0 -1
  70. package/dist/cjs/serializer.d.cts +0 -28
  71. package/dist/esm/serializer.d.ts +0 -28
  72. package/dist/esm/serializer.js +0 -146
  73. package/dist/esm/serializer.js.map +0 -1
  74. package/src/serializer.ts +0 -205
package/src/router.ts CHANGED
@@ -46,7 +46,6 @@ import type {
46
46
  Updater,
47
47
  } from './utils'
48
48
  import type { ParsedLocation } from './location'
49
- import type { DeferredPromiseState } from './defer'
50
49
  import type {
51
50
  AnyContext,
52
51
  AnyRoute,
@@ -78,7 +77,6 @@ import type {
78
77
  NavigateFn,
79
78
  } from './RouterProvider'
80
79
  import type { Manifest } from './manifest'
81
- import type { TsrSerializer } from './serializer'
82
80
  import type { AnySchema, AnyValidator } from './validators'
83
81
  import type { NavigateOptions, ResolveRelativePath, ToOptions } from './link'
84
82
  import type { NotFoundError } from './not-found'
@@ -288,7 +286,7 @@ export interface RouterOptions<
288
286
  * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RouterOptionsType#dehydrate-method)
289
287
  * @link [Guide](https://tanstack.com/router/latest/docs/framework/react/guide/external-data-loading#critical-dehydrationhydration)
290
288
  */
291
- dehydrate?: () => TDehydrated
289
+ dehydrate?: () => Awaitable<TDehydrated>
292
290
  /**
293
291
  * A function that will be called when the router is hydrated.
294
292
  *
@@ -452,7 +450,7 @@ type NavigationEventInfo = {
452
450
  hashChanged: boolean
453
451
  }
454
452
 
455
- export type RouterEvents = {
453
+ export interface RouterEvents {
456
454
  onBeforeNavigate: {
457
455
  type: 'onBeforeNavigate'
458
456
  } & NavigationEventInfo
@@ -468,10 +466,6 @@ export type RouterEvents = {
468
466
  onBeforeRouteMount: {
469
467
  type: 'onBeforeRouteMount'
470
468
  } & NavigationEventInfo
471
- onInjectedHtml: {
472
- type: 'onInjectedHtml'
473
- promise: Promise<string>
474
- }
475
469
  onRendered: {
476
470
  type: 'onRendered'
477
471
  } & NavigationEventInfo
@@ -486,6 +480,11 @@ export type RouterListener<TRouterEvent extends RouterEvent> = {
486
480
  fn: ListenerFn<TRouterEvent>
487
481
  }
488
482
 
483
+ export type SubscribeFn = <TType extends keyof RouterEvents>(
484
+ eventType: TType,
485
+ fn: ListenerFn<RouterEvents[TType]>,
486
+ ) => () => void
487
+
489
488
  export interface MatchRoutesOpts {
490
489
  preload?: boolean
491
490
  throwOnError?: boolean
@@ -523,11 +522,6 @@ export type RouterConstructorOptions<
523
522
  > &
524
523
  RouterContextOptions<TRouteTree>
525
524
 
526
- export interface RouterErrorSerializer<TSerializedError> {
527
- serialize: (err: unknown) => TSerializedError
528
- deserialize: (err: TSerializedError) => unknown
529
- }
530
-
531
525
  export type PreloadRouteFn<
532
526
  TRouteTree extends AnyRoute,
533
527
  TTrailingSlashOption extends TrailingSlashOption,
@@ -624,11 +618,6 @@ export type CommitLocationFn = ({
624
618
 
625
619
  export type StartTransitionFn = (fn: () => void) => void
626
620
 
627
- export type SubscribeFn = <TType extends keyof RouterEvents>(
628
- eventType: TType,
629
- fn: ListenerFn<RouterEvents[TType]>,
630
- ) => () => void
631
-
632
621
  export interface MatchRoutesFn {
633
622
  (
634
623
  pathname: string,
@@ -658,16 +647,16 @@ export type ClearCacheFn<TRouter extends AnyRouter> = (opts?: {
658
647
  filter?: (d: MakeRouteMatchUnion<TRouter>) => boolean
659
648
  }) => void
660
649
 
661
- export interface ServerSrr {
650
+ export interface ServerSsr {
662
651
  injectedHtml: Array<InjectedHtmlEntry>
663
652
  injectHtml: (getHtml: () => string | Promise<string>) => Promise<void>
664
653
  injectScript: (
665
654
  getScript: () => string | Promise<string>,
666
655
  opts?: { logScript?: boolean },
667
656
  ) => Promise<void>
668
- streamValue: (key: string, value: any) => void
669
- streamedKeys: Set<string>
670
- onMatchSettled: (opts: { router: AnyRouter; match: AnyRouteMatch }) => any
657
+ isDehydrated: () => boolean
658
+ onRenderFinished: (listener: () => void) => void
659
+ dehydrate: () => Promise<void>
671
660
  }
672
661
 
673
662
  export type AnyRouterWithContext<TContext> = RouterCore<
@@ -710,29 +699,6 @@ export function defaultSerializeError(err: unknown) {
710
699
  data: err,
711
700
  }
712
701
  }
713
- export interface ExtractedBaseEntry {
714
- dataType: '__beforeLoadContext' | 'loaderData'
715
- type: string
716
- path: Array<string>
717
- id: number
718
- matchIndex: number
719
- }
720
-
721
- export interface ExtractedStream extends ExtractedBaseEntry {
722
- type: 'stream'
723
- streamState: StreamState
724
- }
725
-
726
- export interface ExtractedPromise extends ExtractedBaseEntry {
727
- type: 'promise'
728
- promiseState: DeferredPromiseState<any>
729
- }
730
-
731
- export type ExtractedEntry = ExtractedStream | ExtractedPromise
732
-
733
- export type StreamState = {
734
- promises: Array<ControlledPromise<string | null>>
735
- }
736
702
 
737
703
  export type TrailingSlashOption = 'always' | 'never' | 'preserve'
738
704
 
@@ -838,7 +804,7 @@ export class RouterCore<
838
804
  })
839
805
 
840
806
  if (typeof document !== 'undefined') {
841
- ;(window as any).__TSR_ROUTER__ = this
807
+ self.__TSR_ROUTER__ = this
842
808
  }
843
809
  }
844
810
 
@@ -1293,7 +1259,7 @@ export class RouterCore<
1293
1259
  error: undefined,
1294
1260
  paramsError: parseErrors[index],
1295
1261
  __routeContext: {},
1296
- __beforeLoadContext: {},
1262
+ __beforeLoadContext: undefined,
1297
1263
  context: {},
1298
1264
  abortController: new AbortController(),
1299
1265
  fetchCount: 0,
@@ -2188,10 +2154,6 @@ export class RouterCore<
2188
2154
  this._handleNotFound(matches, err, {
2189
2155
  updateMatch,
2190
2156
  })
2191
- this.serverSsr?.onMatchSettled({
2192
- router: this,
2193
- match: this.getMatch(match.id)!,
2194
- })
2195
2157
  throw err
2196
2158
  }
2197
2159
  }
@@ -2449,8 +2411,7 @@ export class RouterCore<
2449
2411
  }
2450
2412
 
2451
2413
  const beforeLoadContext =
2452
- (await route.options.beforeLoad?.(beforeLoadFnContext)) ??
2453
- {}
2414
+ await route.options.beforeLoad?.(beforeLoadFnContext)
2454
2415
 
2455
2416
  if (
2456
2417
  isRedirect(beforeLoadContext) ||
@@ -2543,10 +2504,6 @@ export class RouterCore<
2543
2504
  ...prev,
2544
2505
  ...head,
2545
2506
  }))
2546
- this.serverSsr?.onMatchSettled({
2547
- router: this,
2548
- match: this.getMatch(matchId)!,
2549
- })
2550
2507
  return this.getMatch(matchId)!
2551
2508
  } else {
2552
2509
  await potentialPendingMinPromise()
@@ -2708,11 +2665,6 @@ export class RouterCore<
2708
2665
  ...head,
2709
2666
  }))
2710
2667
  }
2711
-
2712
- this.serverSsr?.onMatchSettled({
2713
- router: this,
2714
- match: this.getMatch(matchId)!,
2715
- })
2716
2668
  } catch (err) {
2717
2669
  const head = await executeHead()
2718
2670
 
@@ -2773,10 +2725,6 @@ export class RouterCore<
2773
2725
  ...prev,
2774
2726
  ...head,
2775
2727
  }))
2776
- this.serverSsr?.onMatchSettled({
2777
- router: this,
2778
- match: this.getMatch(matchId)!,
2779
- })
2780
2728
  }
2781
2729
  }
2782
2730
  if (!loaderIsRunningAsync) {
@@ -3076,24 +3024,9 @@ export class RouterCore<
3076
3024
 
3077
3025
  ssr?: {
3078
3026
  manifest: Manifest | undefined
3079
- serializer: TsrSerializer
3080
3027
  }
3081
3028
 
3082
- serverSsr?: {
3083
- injectedHtml: Array<InjectedHtmlEntry>
3084
- injectHtml: (getHtml: () => string | Promise<string>) => Promise<void>
3085
- injectScript: (
3086
- getScript: () => string | Promise<string>,
3087
- opts?: { logScript?: boolean },
3088
- ) => Promise<void>
3089
- streamValue: (key: string, value: any) => void
3090
- streamedKeys: Set<string>
3091
- onMatchSettled: (opts: { router: AnyRouter; match: AnyRouteMatch }) => any
3092
- }
3093
-
3094
- clientSsr?: {
3095
- getStreamedValue: <T>(key: string) => T | undefined
3096
- }
3029
+ serverSsr?: ServerSsr
3097
3030
 
3098
3031
  _handleNotFound = (
3099
3032
  matches: Array<AnyRouteMatch>,
package/src/ssr/client.ts CHANGED
@@ -2,14 +2,4 @@ export { mergeHeaders, headersInitToObject } from './headers'
2
2
  export { json } from './json'
3
3
  export type { JsonResponse } from './json'
4
4
  export { hydrate } from './ssr-client'
5
- export type {
6
- DehydratedRouter,
7
- ClientExtractedBaseEntry,
8
- TsrSsrGlobal,
9
- ClientExtractedEntry,
10
- SsrMatch,
11
- ClientExtractedPromise,
12
- ClientExtractedStream,
13
- ResolvePromiseState,
14
- } from './ssr-client'
15
- export { tsrSerializer } from '../serializer'
5
+ export * from './ssr-client'
@@ -1,6 +1,6 @@
1
1
  import { createMemoryHistory } from '@tanstack/history'
2
2
  import { mergeHeaders } from './headers'
3
- import { attachRouterServerSsrUtils, dehydrateRouter } from './ssr-server'
3
+ import { attachRouterServerSsrUtils } from './ssr-server'
4
4
  import type { HandlerCallback } from './handlerCallback'
5
5
  import type { AnyRouter } from '../router'
6
6
  import type { Manifest } from '../manifest'
@@ -39,7 +39,7 @@ export function createRequestHandler<TRouter extends AnyRouter>({
39
39
 
40
40
  await router.load()
41
41
 
42
- dehydrateRouter(router)
42
+ await router.serverSsr?.dehydrate()
43
43
 
44
44
  const responseHeaders = getRequestHeaders({
45
45
  router,
@@ -0,0 +1,43 @@
1
+ import { createPlugin } from 'seroval'
2
+ import type { SerovalNode } from 'seroval'
3
+
4
+ interface ErrorNode {
5
+ message: SerovalNode
6
+ }
7
+
8
+ /**
9
+ * this plugin serializes only the `message` part of an Error
10
+ * this helps with serializing e.g. a ZodError which has functions attached that cannot be serialized
11
+ */
12
+ export const ShallowErrorPlugin = /* @__PURE__ */ createPlugin<
13
+ Error,
14
+ ErrorNode
15
+ >({
16
+ tag: 'tanstack-start:seroval-plugins/Error',
17
+ test(value) {
18
+ return value instanceof Error
19
+ },
20
+ parse: {
21
+ sync(value, ctx) {
22
+ return {
23
+ message: ctx.parse(value.message),
24
+ }
25
+ },
26
+ async async(value, ctx) {
27
+ return {
28
+ message: await ctx.parse(value.message),
29
+ }
30
+ },
31
+ stream(value, ctx) {
32
+ return {
33
+ message: ctx.parse(value.message),
34
+ }
35
+ },
36
+ },
37
+ serialize(node, ctx) {
38
+ return 'new Error(' + ctx.serialize(node.message) + ')'
39
+ },
40
+ deserialize(node, ctx) {
41
+ return new Error(ctx.deserialize(node.message) as string)
42
+ },
43
+ })
package/src/ssr/server.ts CHANGED
@@ -7,17 +7,4 @@ export {
7
7
  transformStreamWithRouter,
8
8
  transformReadableStreamWithRouter,
9
9
  } from './transformStreamWithRouter'
10
- export {
11
- attachRouterServerSsrUtils,
12
- dehydrateRouter,
13
- extractAsyncLoaderData,
14
- onMatchSettled,
15
- replaceBy,
16
- } from './ssr-server'
17
- export type {
18
- ServerExtractedBaseEntry,
19
- ServerExtractedEntry,
20
- ServerExtractedPromise,
21
- ServerExtractedStream,
22
- } from './ssr-server'
23
- export * from './tsrScript'
10
+ export { attachRouterServerSsrUtils } from './ssr-server'
@@ -1,114 +1,62 @@
1
1
  import invariant from 'tiny-invariant'
2
- import { isPlainObject } from '../utils'
3
- import { tsrSerializer } from '../serializer'
4
- import type { DeferredPromiseState } from '../defer'
5
2
  import type { MakeRouteMatch } from '../Matches'
6
- import type { AnyRouter, ControllablePromise } from '../router'
3
+ import type { AnyRouter } from '../router'
7
4
  import type { Manifest } from '../manifest'
8
5
  import type { RouteContextOptions } from '../route'
6
+ import type { GLOBAL_TSR } from './ssr-server'
9
7
 
10
8
  declare global {
11
9
  interface Window {
12
- __TSR_SSR__?: TsrSsrGlobal
10
+ [GLOBAL_TSR]?: TsrSsrGlobal
13
11
  }
14
12
  }
15
13
 
16
14
  export interface TsrSsrGlobal {
17
- matches: Array<SsrMatch>
18
- streamedValues: Record<
19
- string,
20
- {
21
- value: any
22
- parsed: any
23
- }
24
- >
25
- cleanScripts: () => void
26
- dehydrated?: any
27
- initMatch: (match: SsrMatch) => void
28
- resolvePromise: (opts: {
29
- matchId: string
30
- id: number
31
- promiseState: DeferredPromiseState<any>
32
- }) => void
33
- injectChunk: (opts: { matchId: string; id: number; chunk: string }) => void
34
- closeStream: (opts: { matchId: string; id: number }) => void
35
- }
36
-
37
- export interface SsrMatch {
38
- id: string
39
- __beforeLoadContext: string
40
- loaderData?: string
41
- error?: string
42
- extracted?: Array<ClientExtractedEntry>
43
- updatedAt: MakeRouteMatch['updatedAt']
44
- status: MakeRouteMatch['status']
45
- ssr?: boolean | 'data-only'
15
+ router?: DehydratedRouter
16
+ // clean scripts, shortened since this is sent for each streamed script
17
+ c: () => void
46
18
  }
47
19
 
48
- export type ClientExtractedEntry =
49
- | ClientExtractedStream
50
- | ClientExtractedPromise
51
-
52
- export interface ClientExtractedPromise extends ClientExtractedBaseEntry {
53
- type: 'promise'
54
- value?: ControllablePromise<any>
55
- }
56
-
57
- export interface ClientExtractedStream extends ClientExtractedBaseEntry {
58
- type: 'stream'
59
- value?: ReadableStream & { controller?: ReadableStreamDefaultController }
60
- }
61
-
62
- export interface ClientExtractedBaseEntry {
63
- type: string
64
- path: Array<string>
20
+ function hydrateMatch(
21
+ deyhydratedMatch: DehydratedMatch,
22
+ ): Partial<MakeRouteMatch> {
23
+ return {
24
+ id: deyhydratedMatch.i,
25
+ __beforeLoadContext: deyhydratedMatch.b,
26
+ loaderData: deyhydratedMatch.l,
27
+ status: deyhydratedMatch.s,
28
+ ssr: deyhydratedMatch.ssr,
29
+ updatedAt: deyhydratedMatch.u,
30
+ error: deyhydratedMatch.e,
31
+ }
65
32
  }
66
-
67
- export interface ResolvePromiseState {
68
- matchId: string
69
- id: number
70
- promiseState: DeferredPromiseState<any>
33
+ export interface DehydratedMatch {
34
+ i: MakeRouteMatch['id']
35
+ b?: MakeRouteMatch['__beforeLoadContext']
36
+ l?: MakeRouteMatch['loaderData']
37
+ e?: MakeRouteMatch['error']
38
+ u: MakeRouteMatch['updatedAt']
39
+ s: MakeRouteMatch['status']
40
+ ssr?: MakeRouteMatch['ssr']
71
41
  }
72
42
 
73
43
  export interface DehydratedRouter {
74
44
  manifest: Manifest | undefined
75
- dehydratedData: any
76
- lastMatchId: string
45
+ dehydratedData?: any
46
+ lastMatchId?: string
47
+ matches: Array<DehydratedMatch>
77
48
  }
78
49
 
79
50
  export async function hydrate(router: AnyRouter): Promise<any> {
80
51
  invariant(
81
- window.__TSR_SSR__?.dehydrated,
82
- 'Expected to find a dehydrated data on window.__TSR_SSR__.dehydrated... but we did not. Please file an issue!',
52
+ window.$_TSR?.router,
53
+ 'Expected to find a dehydrated data on window.$_TSR.router, but we did not. Please file an issue!',
83
54
  )
84
55
 
85
- const { manifest, dehydratedData, lastMatchId } = tsrSerializer.parse(
86
- window.__TSR_SSR__.dehydrated,
87
- ) as DehydratedRouter
56
+ const { manifest, dehydratedData, lastMatchId } = window.$_TSR.router
88
57
 
89
58
  router.ssr = {
90
59
  manifest,
91
- serializer: tsrSerializer,
92
- }
93
-
94
- router.clientSsr = {
95
- getStreamedValue: <T>(key: string): T | undefined => {
96
- if (router.isServer) {
97
- return undefined
98
- }
99
-
100
- const streamedValue = window.__TSR_SSR__?.streamedValues[key]
101
-
102
- if (!streamedValue) {
103
- return
104
- }
105
-
106
- if (!streamedValue.parsed) {
107
- streamedValue.parsed = router.ssr!.serializer.parse(streamedValue.value)
108
- }
109
-
110
- return streamedValue.parsed
111
- },
112
60
  }
113
61
 
114
62
  // Hydrate the router state
@@ -126,16 +74,15 @@ export async function hydrate(router: AnyRouter): Promise<any> {
126
74
  // First step is to reyhdrate loaderData and __beforeLoadContext
127
75
  let firstNonSsrMatchIndex: number | undefined = undefined
128
76
  matches.forEach((match) => {
129
- const dehydratedMatch = window.__TSR_SSR__!.matches.find(
130
- (d) => d.id === match.id,
77
+ const dehydratedMatch = window.$_TSR!.router!.matches.find(
78
+ (d) => d.i === match.id,
131
79
  )
132
-
133
80
  if (!dehydratedMatch) {
134
81
  Object.assign(match, { dehydrated: false, ssr: false })
135
82
  return
136
83
  }
137
84
 
138
- Object.assign(match, dehydratedMatch)
85
+ Object.assign(match, hydrateMatch(dehydratedMatch))
139
86
 
140
87
  if (match.ssr === false) {
141
88
  match._dehydrated = false
@@ -153,30 +100,6 @@ export async function hydrate(router: AnyRouter): Promise<any> {
153
100
  if (match.ssr === false) {
154
101
  return
155
102
  }
156
-
157
- // Handle beforeLoadContext
158
- if (dehydratedMatch.__beforeLoadContext) {
159
- match.__beforeLoadContext = router.ssr!.serializer.parse(
160
- dehydratedMatch.__beforeLoadContext,
161
- ) as any
162
- }
163
-
164
- // Handle loaderData
165
- if (dehydratedMatch.loaderData) {
166
- match.loaderData = router.ssr!.serializer.parse(
167
- dehydratedMatch.loaderData,
168
- )
169
- }
170
-
171
- // Handle error
172
- if (dehydratedMatch.error) {
173
- match.error = router.ssr!.serializer.parse(dehydratedMatch.error)
174
- }
175
-
176
- // Handle extracted
177
- ;(match as unknown as SsrMatch).extracted?.forEach((ex) => {
178
- deepMutableSetByPath(match, ['loaderData', ...ex.path], ex.value)
179
- })
180
103
  })
181
104
 
182
105
  router.__store.setState((s) => {
@@ -271,21 +194,5 @@ export async function hydrate(router: AnyRouter): Promise<any> {
271
194
  })
272
195
  })
273
196
  }
274
-
275
197
  return routeChunkPromise
276
198
  }
277
-
278
- function deepMutableSetByPath<T>(obj: T, path: Array<string>, value: any) {
279
- // mutable set by path retaining array and object references
280
- if (path.length === 1) {
281
- ;(obj as any)[path[0]!] = value
282
- }
283
-
284
- const [key, ...rest] = path
285
-
286
- if (Array.isArray(obj)) {
287
- deepMutableSetByPath(obj[Number(key)], rest, value)
288
- } else if (isPlainObject(obj)) {
289
- deepMutableSetByPath((obj as any)[key!], rest, value)
290
- }
291
- }