@bleedingdev/modern-js-plugin-tanstack 3.5.0-ultramodern.30 → 3.5.0-ultramodern.32

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 (221) hide show
  1. package/dist/cjs/cli/artifacts.js +157 -0
  2. package/dist/cjs/cli/index.js +6 -103
  3. package/dist/cjs/cli/tanstackTypes/canonicalRoutes.js +113 -0
  4. package/dist/cjs/cli/tanstackTypes/shared.js +130 -0
  5. package/dist/cjs/cli/tanstackTypes/source.js +251 -0
  6. package/dist/cjs/cli/tanstackTypes.js +4 -350
  7. package/dist/cjs/runtime/blockingSubscribe.js +64 -0
  8. package/dist/cjs/runtime/{pluginCore.js → clientBasepath.js} +12 -19
  9. package/dist/cjs/runtime/clientHydration.js +129 -0
  10. package/dist/cjs/runtime/dataMutation.js +11 -176
  11. package/dist/cjs/runtime/formData.js +116 -0
  12. package/dist/cjs/runtime/loaderBridge.js +4 -1
  13. package/dist/cjs/runtime/plugin.js +21 -125
  14. package/dist/cjs/runtime/plugin.node.js +38 -119
  15. package/dist/cjs/runtime/pluginShared.js +90 -0
  16. package/dist/cjs/runtime/routeTree/components.js +102 -0
  17. package/dist/cjs/runtime/routeTree/construction.js +152 -0
  18. package/dist/cjs/runtime/routeTree/index.js +47 -0
  19. package/dist/cjs/runtime/routeTree/loaders.js +158 -0
  20. package/dist/cjs/runtime/routeTree/paths.js +57 -0
  21. package/dist/cjs/runtime/routeTree/staticData.js +63 -0
  22. package/dist/cjs/runtime/routeTree/tanstackRoutes.js +57 -0
  23. package/dist/cjs/runtime/routeTree/types.js +18 -0
  24. package/dist/cjs/runtime/routeTree.js +7 -320
  25. package/dist/cjs/runtime/rsc/CompositeComponent.js +18 -13
  26. package/dist/cjs/runtime/rsc/RscNodeRenderer.js +5 -16
  27. package/dist/cjs/runtime/rsc/client.js +8 -25
  28. package/dist/cjs/runtime/rsc/flightSerialization.js +132 -0
  29. package/dist/cjs/runtime/rsc/payloadErrors.js +99 -0
  30. package/dist/cjs/runtime/rsc/payloadFetch.js +117 -0
  31. package/dist/cjs/runtime/rsc/payloadRouter.js +21 -142
  32. package/dist/cjs/runtime/rsc/payloadRoutes.js +106 -0
  33. package/dist/cjs/runtime/rsc/payloadStorage.js +58 -0
  34. package/dist/cjs/runtime/rsc/server.js +14 -18
  35. package/dist/cjs/runtime/rsc/shared.js +71 -0
  36. package/dist/cjs/runtime/rsc/treeGetter.js +72 -0
  37. package/dist/cjs/runtime/ssrManagedTags.js +103 -0
  38. package/dist/cjs/runtime/ssrPreload.js +89 -0
  39. package/dist/cjs/runtime/ssrTypes.js +18 -0
  40. package/dist/cjs/runtime/submitAction.js +161 -0
  41. package/dist/cjs/runtime/utils.js +49 -86
  42. package/dist/esm/cli/artifacts.mjs +103 -0
  43. package/dist/esm/cli/index.mjs +4 -101
  44. package/dist/esm/cli/tanstackTypes/canonicalRoutes.mjs +75 -0
  45. package/dist/esm/cli/tanstackTypes/shared.mjs +68 -0
  46. package/dist/esm/cli/tanstackTypes/source.mjs +203 -0
  47. package/dist/esm/cli/tanstackTypes.mjs +2 -339
  48. package/dist/esm/runtime/blockingSubscribe.mjs +19 -0
  49. package/dist/esm/runtime/clientBasepath.mjs +10 -0
  50. package/dist/esm/runtime/clientHydration.mjs +70 -0
  51. package/dist/esm/runtime/dataMutation.mjs +2 -167
  52. package/dist/esm/runtime/formData.mjs +63 -0
  53. package/dist/esm/runtime/loaderBridge.mjs +4 -1
  54. package/dist/esm/runtime/plugin.mjs +14 -118
  55. package/dist/esm/runtime/plugin.node.mjs +33 -114
  56. package/dist/esm/runtime/pluginShared.mjs +40 -0
  57. package/dist/esm/runtime/routeTree/components.mjs +55 -0
  58. package/dist/esm/runtime/routeTree/construction.mjs +111 -0
  59. package/dist/esm/runtime/routeTree/index.mjs +2 -0
  60. package/dist/esm/runtime/routeTree/loaders.mjs +117 -0
  61. package/dist/esm/runtime/routeTree/paths.mjs +16 -0
  62. package/dist/esm/runtime/routeTree/staticData.mjs +22 -0
  63. package/dist/esm/runtime/routeTree/tanstackRoutes.mjs +13 -0
  64. package/dist/esm/runtime/routeTree/types.mjs +0 -0
  65. package/dist/esm/runtime/routeTree.mjs +1 -318
  66. package/dist/esm/runtime/rsc/CompositeComponent.mjs +18 -13
  67. package/dist/esm/runtime/rsc/RscNodeRenderer.mjs +4 -15
  68. package/dist/esm/runtime/rsc/client.mjs +6 -26
  69. package/dist/esm/runtime/rsc/flightSerialization.mjs +88 -0
  70. package/dist/esm/runtime/rsc/payloadErrors.mjs +49 -0
  71. package/dist/esm/runtime/rsc/payloadFetch.mjs +61 -0
  72. package/dist/esm/runtime/rsc/payloadRouter.mjs +12 -133
  73. package/dist/esm/runtime/rsc/payloadRoutes.mjs +50 -0
  74. package/dist/esm/runtime/rsc/payloadStorage.mjs +14 -0
  75. package/dist/esm/runtime/rsc/server.mjs +17 -21
  76. package/dist/esm/runtime/rsc/shared.mjs +21 -0
  77. package/dist/esm/runtime/rsc/treeGetter.mjs +34 -0
  78. package/dist/esm/runtime/ssrManagedTags.mjs +53 -0
  79. package/dist/esm/runtime/ssrPreload.mjs +51 -0
  80. package/dist/esm/runtime/ssrTypes.mjs +0 -0
  81. package/dist/esm/runtime/submitAction.mjs +120 -0
  82. package/dist/esm/runtime/utils.mjs +47 -75
  83. package/dist/esm-node/cli/artifacts.mjs +104 -0
  84. package/dist/esm-node/cli/index.mjs +4 -101
  85. package/dist/esm-node/cli/tanstackTypes/canonicalRoutes.mjs +76 -0
  86. package/dist/esm-node/cli/tanstackTypes/shared.mjs +69 -0
  87. package/dist/esm-node/cli/tanstackTypes/source.mjs +204 -0
  88. package/dist/esm-node/cli/tanstackTypes.mjs +2 -339
  89. package/dist/esm-node/runtime/blockingSubscribe.mjs +20 -0
  90. package/dist/esm-node/runtime/clientBasepath.mjs +11 -0
  91. package/dist/esm-node/runtime/clientHydration.mjs +71 -0
  92. package/dist/esm-node/runtime/dataMutation.mjs +2 -167
  93. package/dist/esm-node/runtime/formData.mjs +64 -0
  94. package/dist/esm-node/runtime/loaderBridge.mjs +4 -1
  95. package/dist/esm-node/runtime/plugin.mjs +14 -118
  96. package/dist/esm-node/runtime/plugin.node.mjs +33 -114
  97. package/dist/esm-node/runtime/pluginShared.mjs +41 -0
  98. package/dist/esm-node/runtime/routeTree/components.mjs +56 -0
  99. package/dist/esm-node/runtime/routeTree/construction.mjs +112 -0
  100. package/dist/esm-node/runtime/routeTree/index.mjs +3 -0
  101. package/dist/esm-node/runtime/routeTree/loaders.mjs +118 -0
  102. package/dist/esm-node/runtime/routeTree/paths.mjs +17 -0
  103. package/dist/esm-node/runtime/routeTree/staticData.mjs +23 -0
  104. package/dist/esm-node/runtime/routeTree/tanstackRoutes.mjs +14 -0
  105. package/dist/esm-node/runtime/routeTree/types.mjs +1 -0
  106. package/dist/esm-node/runtime/routeTree.mjs +1 -318
  107. package/dist/esm-node/runtime/rsc/CompositeComponent.mjs +18 -13
  108. package/dist/esm-node/runtime/rsc/RscNodeRenderer.mjs +4 -15
  109. package/dist/esm-node/runtime/rsc/client.mjs +6 -26
  110. package/dist/esm-node/runtime/rsc/flightSerialization.mjs +89 -0
  111. package/dist/esm-node/runtime/rsc/payloadErrors.mjs +50 -0
  112. package/dist/esm-node/runtime/rsc/payloadFetch.mjs +62 -0
  113. package/dist/esm-node/runtime/rsc/payloadRouter.mjs +12 -133
  114. package/dist/esm-node/runtime/rsc/payloadRoutes.mjs +51 -0
  115. package/dist/esm-node/runtime/rsc/payloadStorage.mjs +15 -0
  116. package/dist/esm-node/runtime/rsc/server.mjs +17 -21
  117. package/dist/esm-node/runtime/rsc/shared.mjs +22 -0
  118. package/dist/esm-node/runtime/rsc/treeGetter.mjs +35 -0
  119. package/dist/esm-node/runtime/ssrManagedTags.mjs +54 -0
  120. package/dist/esm-node/runtime/ssrPreload.mjs +52 -0
  121. package/dist/esm-node/runtime/ssrTypes.mjs +1 -0
  122. package/dist/esm-node/runtime/submitAction.mjs +121 -0
  123. package/dist/esm-node/runtime/utils.mjs +47 -75
  124. package/dist/types/cli/artifacts.d.ts +33 -0
  125. package/dist/types/cli/index.d.ts +2 -33
  126. package/dist/types/cli/tanstackTypes/canonicalRoutes.d.ts +22 -0
  127. package/dist/types/cli/tanstackTypes/shared.d.ts +20 -0
  128. package/dist/types/cli/tanstackTypes/source.d.ts +10 -0
  129. package/dist/types/cli/tanstackTypes.d.ts +3 -31
  130. package/dist/types/runtime/blockingSubscribe.d.ts +3 -0
  131. package/dist/types/runtime/clientBasepath.d.ts +1 -0
  132. package/dist/types/runtime/clientHydration.d.ts +19 -0
  133. package/dist/types/runtime/dataMutation.d.ts +3 -12
  134. package/dist/types/runtime/formData.d.ts +23 -0
  135. package/dist/types/runtime/plugin.d.ts +1 -1
  136. package/dist/types/runtime/plugin.node.d.ts +1 -1
  137. package/dist/types/runtime/{pluginCore.d.ts → pluginShared.d.ts} +14 -0
  138. package/dist/types/runtime/routeTree/components.d.ts +7 -0
  139. package/dist/types/runtime/routeTree/construction.d.ts +5 -0
  140. package/dist/types/runtime/routeTree/index.d.ts +2 -0
  141. package/dist/types/runtime/routeTree/loaders.d.ts +4 -0
  142. package/dist/types/runtime/routeTree/paths.d.ts +3 -0
  143. package/dist/types/runtime/routeTree/staticData.d.ts +19 -0
  144. package/dist/types/runtime/routeTree/tanstackRoutes.d.ts +4 -0
  145. package/dist/types/runtime/routeTree/types.d.ts +75 -0
  146. package/dist/types/runtime/routeTree.d.ts +1 -9
  147. package/dist/types/runtime/rsc/CompositeComponent.d.ts +1 -2
  148. package/dist/types/runtime/rsc/RscNodeRenderer.d.ts +2 -3
  149. package/dist/types/runtime/rsc/client.d.ts +2 -0
  150. package/dist/types/runtime/rsc/flightSerialization.d.ts +3 -0
  151. package/dist/types/runtime/rsc/payloadErrors.d.ts +6 -0
  152. package/dist/types/runtime/rsc/payloadFetch.d.ts +10 -0
  153. package/dist/types/runtime/rsc/payloadRouter.d.ts +2 -10
  154. package/dist/types/runtime/rsc/payloadRoutes.d.ts +43 -0
  155. package/dist/types/runtime/rsc/payloadStorage.d.ts +5 -0
  156. package/dist/types/runtime/rsc/shared.d.ts +19 -0
  157. package/dist/types/runtime/rsc/treeGetter.d.ts +1 -0
  158. package/dist/types/runtime/ssrManagedTags.d.ts +7 -0
  159. package/dist/types/runtime/ssrPreload.d.ts +2 -0
  160. package/dist/types/runtime/ssrTypes.d.ts +43 -0
  161. package/dist/types/runtime/state.d.ts +1 -1
  162. package/dist/types/runtime/submitAction.d.ts +14 -0
  163. package/dist/types/runtime/types.d.ts +3 -46
  164. package/dist/types/runtime/utils.d.ts +1 -22
  165. package/package.json +30 -9
  166. package/rstest.config.mts +1 -0
  167. package/src/cli/artifacts.ts +255 -0
  168. package/src/cli/index.ts +6 -246
  169. package/src/cli/tanstackTypes/canonicalRoutes.ts +157 -0
  170. package/src/cli/tanstackTypes/shared.ts +119 -0
  171. package/src/cli/tanstackTypes/source.ts +405 -0
  172. package/src/cli/tanstackTypes.ts +4 -647
  173. package/src/runtime/blockingSubscribe.ts +48 -0
  174. package/src/runtime/clientBasepath.ts +12 -0
  175. package/src/runtime/clientHydration.ts +151 -0
  176. package/src/runtime/dataMutation.tsx +9 -306
  177. package/src/runtime/formData.ts +153 -0
  178. package/src/runtime/loaderBridge.ts +8 -3
  179. package/src/runtime/plugin.node.tsx +60 -284
  180. package/src/runtime/plugin.tsx +21 -257
  181. package/src/runtime/pluginShared.ts +112 -0
  182. package/src/runtime/routeTree/components.ts +130 -0
  183. package/src/runtime/routeTree/construction.ts +238 -0
  184. package/src/runtime/routeTree/index.ts +7 -0
  185. package/src/runtime/routeTree/loaders.ts +232 -0
  186. package/src/runtime/routeTree/paths.ts +36 -0
  187. package/src/runtime/routeTree/staticData.ts +66 -0
  188. package/src/runtime/routeTree/tanstackRoutes.ts +36 -0
  189. package/src/runtime/routeTree/types.ts +87 -0
  190. package/src/runtime/routeTree.ts +5 -750
  191. package/src/runtime/rsc/CompositeComponent.tsx +29 -20
  192. package/src/runtime/rsc/RscNodeRenderer.tsx +9 -27
  193. package/src/runtime/rsc/client.tsx +12 -40
  194. package/src/runtime/rsc/flightSerialization.ts +158 -0
  195. package/src/runtime/rsc/payloadErrors.ts +73 -0
  196. package/src/runtime/rsc/payloadFetch.ts +97 -0
  197. package/src/runtime/rsc/payloadRouter.ts +29 -234
  198. package/src/runtime/rsc/payloadRoutes.ts +122 -0
  199. package/src/runtime/rsc/payloadStorage.ts +35 -0
  200. package/src/runtime/rsc/server.tsx +20 -29
  201. package/src/runtime/rsc/shared.ts +70 -0
  202. package/src/runtime/rsc/treeGetter.tsx +52 -0
  203. package/src/runtime/ssrManagedTags.ts +107 -0
  204. package/src/runtime/ssrPreload.ts +125 -0
  205. package/src/runtime/ssrTypes.ts +51 -0
  206. package/src/runtime/state.ts +4 -2
  207. package/src/runtime/submitAction.ts +194 -0
  208. package/src/runtime/types.ts +14 -51
  209. package/src/runtime/utils.tsx +72 -108
  210. package/src/types/react-server-dom-rspack.d.ts +56 -0
  211. package/tests/castRatchet.test.ts +85 -0
  212. package/tests/router/dataMutation.test.tsx +59 -0
  213. package/tests/router/fixtures/router-gen.golden.txt +72 -0
  214. package/tests/router/loaderBridge.test.ts +21 -0
  215. package/tests/router/routeTree.test.ts +51 -11
  216. package/tests/router/rsc.test.tsx +189 -0
  217. package/tests/router/ssrPreload.test.ts +30 -0
  218. package/tests/router/tanstackTypes.test.ts +254 -1
  219. package/dist/esm/runtime/pluginCore.mjs +0 -14
  220. package/dist/esm-node/runtime/pluginCore.mjs +0 -15
  221. package/src/runtime/pluginCore.ts +0 -56
@@ -1,29 +1,41 @@
1
1
  // @effect-diagnostics strictBooleanExpressions:off
2
2
  'use client';
3
3
 
4
- import type React from 'react';
5
4
  import { Suspense } from 'react';
6
5
  import { SlotProvider } from './SlotContext';
6
+ import { EmptyFallback, renderSelectedTree } from './shared';
7
7
  import {
8
8
  type AnyCompositeComponent,
9
9
  type CompositeComponentProps,
10
10
  RSC_PROXY_GET_TREE,
11
- RSC_PROXY_PATH,
11
+ SERVER_COMPONENT_STREAM,
12
12
  } from './symbols';
13
+ import { createTreeGetterFromFlightStream } from './treeGetter';
13
14
 
14
- function EmptyFallback() {
15
- return null;
16
- }
15
+ const rawServerValueGetters = new WeakMap<object, () => unknown>();
16
+
17
+ function getRawServerTreeGetter(src: unknown) {
18
+ if (!src || (typeof src !== 'object' && typeof src !== 'function')) {
19
+ return;
20
+ }
21
+
22
+ const source = src as {
23
+ [SERVER_COMPONENT_STREAM]?: {
24
+ createReplayStream?: () => ReadableStream<Uint8Array>;
25
+ };
26
+ };
27
+ const stream = source[SERVER_COMPONENT_STREAM];
28
+ if (typeof stream?.createReplayStream !== 'function') {
29
+ return;
30
+ }
17
31
 
18
- function selectTreePath(tree: unknown, path: string[]) {
19
- let current = tree;
20
- for (const key of path) {
21
- if (current === null || typeof current !== 'object') {
22
- return null;
23
- }
24
- current = (current as Record<string, unknown>)[key];
32
+ let getTree = rawServerValueGetters.get(src);
33
+ if (!getTree) {
34
+ getTree = createTreeGetterFromFlightStream(stream.createReplayStream());
35
+ rawServerValueGetters.set(src, getTree);
25
36
  }
26
- return current as React.ReactNode;
37
+
38
+ return getTree;
27
39
  }
28
40
 
29
41
  function CompositeInner<TComp extends AnyCompositeComponent>({
@@ -35,14 +47,11 @@ function CompositeInner<TComp extends AnyCompositeComponent>({
35
47
  src: TComp;
36
48
  strict?: boolean;
37
49
  }) {
38
- const getTree = src[RSC_PROXY_GET_TREE];
39
- if (!getTree) {
40
- throw new Error(
50
+ const tree = renderSelectedTree(src, {
51
+ getTree: src[RSC_PROXY_GET_TREE] || getRawServerTreeGetter(src),
52
+ missingTreeError:
41
53
  'CompositeComponent src must come from createCompositeComponent().',
42
- );
43
- }
44
-
45
- const tree = selectTreePath(getTree(), src[RSC_PROXY_PATH] || []);
54
+ });
46
55
  return (
47
56
  <SlotProvider implementations={slotProps} strict={strict}>
48
57
  {tree}
@@ -1,36 +1,18 @@
1
1
  // @effect-diagnostics strictBooleanExpressions:off
2
2
  'use client';
3
3
 
4
- import type React from 'react';
5
4
  import { Suspense } from 'react';
6
- import {
7
- type AnyRenderableServerComponent,
8
- RSC_PROXY_GET_TREE,
9
- RSC_PROXY_PATH,
10
- } from './symbols';
11
-
12
- function EmptyFallback() {
13
- return null;
14
- }
15
-
16
- function selectTreePath(tree: unknown, path: string[]) {
17
- let current = tree;
18
- for (const key of path) {
19
- if (current === null || typeof current !== 'object') {
20
- return null;
21
- }
22
- current = (current as Record<string, unknown>)[key];
23
- }
24
- return current as React.ReactNode;
25
- }
5
+ import { EmptyFallback, renderSelectedTree } from './shared';
6
+ import type { AnyRenderableServerComponent } from './symbols';
26
7
 
27
8
  function RscNodeRenderInner({ data }: { data: AnyRenderableServerComponent }) {
28
- const getTree = data[RSC_PROXY_GET_TREE];
29
- if (!getTree) {
30
- throw new Error('Renderable RSC is missing its decoded tree getter.');
31
- }
32
-
33
- return <>{selectTreePath(getTree(), data[RSC_PROXY_PATH] || [])}</>;
9
+ return (
10
+ <>
11
+ {renderSelectedTree(data, {
12
+ missingTreeError: 'Renderable RSC is missing its decoded tree getter.',
13
+ })}
14
+ </>
15
+ );
34
16
  }
35
17
 
36
18
  export function RscNodeRenderer({
@@ -1,14 +1,15 @@
1
1
  'use client';
2
2
 
3
3
  import { createSerializationAdapter } from '@tanstack/react-router';
4
- import { use } from 'react';
5
4
  import { CompositeComponent } from './CompositeComponent';
6
5
  import { createRscProxy } from './createRscProxy';
6
+ import type { SerializedTanstackRscFlightValue } from './shared';
7
7
  import type {
8
8
  AnyCompositeComponent,
9
9
  RscSlotUsageEvent,
10
10
  ServerComponentStream,
11
11
  } from './symbols';
12
+ import { createTreeGetterFromFlightStream } from './treeGetter';
12
13
 
13
14
  export type {
14
15
  AnyCompositeComponent,
@@ -23,55 +24,26 @@ type SerializedRsc = {
23
24
  slotUsagesStream?: ReadableStream<RscSlotUsageEvent>;
24
25
  };
25
26
 
26
- type ModernRscClientRuntime = typeof import('@modern-js/runtime/rsc/client');
27
-
28
- let modernRscClientRuntimePromise: Promise<ModernRscClientRuntime> | undefined;
29
-
30
- function loadModernRscClientRuntime() {
31
- modernRscClientRuntimePromise ??= import(
32
- '@modern-js/runtime/rsc/client'
33
- ).then(runtime => {
34
- runtime.setServerCallback(runtime.callServer);
35
- return runtime;
36
- });
37
- return modernRscClientRuntimePromise;
38
- }
39
-
40
- function createTreeGetter(stream: ReadableStream<Uint8Array>) {
41
- let ready = false;
42
- let tree: unknown;
43
- const treePromise = loadModernRscClientRuntime()
44
- .then(runtime =>
45
- runtime.createFromReadableStream(stream, {
46
- callServer: runtime.callServer,
47
- }),
48
- )
49
- .then(value => {
50
- tree = value;
51
- ready = true;
52
- return value;
53
- });
54
-
55
- return () => {
56
- if (ready) {
57
- return tree;
58
- }
59
- return use(treePromise);
60
- };
61
- }
62
-
63
- function createFromFlightStream(serialized: SerializedRsc) {
27
+ function createFromFlightStream(
28
+ serialized: SerializedRsc | SerializedTanstackRscFlightValue,
29
+ ) {
64
30
  const streamWrapper: ServerComponentStream = {
65
31
  createReplayStream: () => serialized.stream,
66
32
  };
67
33
 
68
- return createRscProxy(createTreeGetter(serialized.stream), {
34
+ return createRscProxy(createTreeGetterFromFlightStream(serialized.stream), {
69
35
  renderable: serialized.kind === 'renderable',
70
36
  slotUsagesStream: serialized.slotUsagesStream,
71
37
  stream: streamWrapper,
72
38
  });
73
39
  }
74
40
 
41
+ export function createTanstackRscValueFromFlight(
42
+ serialized: SerializedTanstackRscFlightValue,
43
+ ): AnyCompositeComponent {
44
+ return createFromFlightStream(serialized) as AnyCompositeComponent;
45
+ }
46
+
75
47
  const adapter = createSerializationAdapter({
76
48
  key: '$MODERN_TANSTACK_RSC',
77
49
  test: (_value: unknown): _value is never => false,
@@ -0,0 +1,158 @@
1
+ // @effect-diagnostics asyncFunction:off globalFetch:off processEnv:off strictBooleanExpressions:off
2
+ import {
3
+ isSerializedTanstackRscFlightValue,
4
+ type SerializedTanstackRscFlightValue,
5
+ TANSTACK_RSC_FLIGHT_VALUE,
6
+ } from './shared';
7
+ import {
8
+ isRenderableServerComponent,
9
+ isServerComponent,
10
+ RSC_SLOT_USAGES_STREAM,
11
+ SERVER_COMPONENT_STREAM,
12
+ } from './symbols';
13
+
14
+ export function isPlainObject(
15
+ value: unknown,
16
+ ): value is Record<string, unknown> {
17
+ if (!value || typeof value !== 'object') {
18
+ return false;
19
+ }
20
+ const prototype = Object.getPrototypeOf(value);
21
+ return prototype === Object.prototype || prototype === null;
22
+ }
23
+
24
+ export function serializeTanstackRscFlightValues(
25
+ value: unknown,
26
+ seen = new WeakMap<object, unknown>(),
27
+ ): unknown {
28
+ if (isServerComponent(value)) {
29
+ const streamWrapper = value[SERVER_COMPONENT_STREAM];
30
+ if (!streamWrapper) {
31
+ throw new Error('Cannot serialize TanStack RSC without a Flight stream.');
32
+ }
33
+
34
+ const kind = isRenderableServerComponent(value)
35
+ ? 'renderable'
36
+ : 'composite';
37
+ const slotUsagesStream =
38
+ process.env.NODE_ENV === 'development' && kind === 'composite'
39
+ ? value[RSC_SLOT_USAGES_STREAM]
40
+ : undefined;
41
+
42
+ return {
43
+ [TANSTACK_RSC_FLIGHT_VALUE]: true,
44
+ kind,
45
+ stream: streamWrapper.createReplayStream(),
46
+ ...(slotUsagesStream ? { slotUsagesStream } : {}),
47
+ } satisfies SerializedTanstackRscFlightValue;
48
+ }
49
+
50
+ if (!value || typeof value !== 'object') {
51
+ return value;
52
+ }
53
+ if (seen.has(value)) {
54
+ return seen.get(value);
55
+ }
56
+ if (value instanceof Map) {
57
+ const result = new Map<unknown, unknown>();
58
+ seen.set(value, result);
59
+ for (const [key, item] of value) {
60
+ result.set(
61
+ serializeTanstackRscFlightValues(key, seen),
62
+ serializeTanstackRscFlightValues(item, seen),
63
+ );
64
+ }
65
+ return result;
66
+ }
67
+ if (value instanceof Set) {
68
+ const result = new Set<unknown>();
69
+ seen.set(value, result);
70
+ for (const item of value) {
71
+ result.add(serializeTanstackRscFlightValues(item, seen));
72
+ }
73
+ return result;
74
+ }
75
+ if (Array.isArray(value)) {
76
+ const result: unknown[] = [];
77
+ seen.set(value, result);
78
+ for (const item of value) {
79
+ result.push(serializeTanstackRscFlightValues(item, seen));
80
+ }
81
+ return result;
82
+ }
83
+ if (!isPlainObject(value)) {
84
+ return value;
85
+ }
86
+
87
+ const result: Record<string, unknown> = {};
88
+ seen.set(value, result);
89
+ for (const [key, item] of Object.entries(value)) {
90
+ result[key] = serializeTanstackRscFlightValues(item, seen);
91
+ }
92
+ return result;
93
+ }
94
+
95
+ export async function reviveTanstackRscFlightValues(
96
+ value: unknown,
97
+ seen = new WeakMap<object, unknown>(),
98
+ ): Promise<unknown> {
99
+ let reviver:
100
+ | ((serialized: SerializedTanstackRscFlightValue) => unknown)
101
+ | undefined;
102
+
103
+ const getReviver = async () => {
104
+ if (!reviver) {
105
+ const client = await import('./client');
106
+ reviver = client.createTanstackRscValueFromFlight;
107
+ }
108
+ return reviver;
109
+ };
110
+
111
+ const visit = async (current: unknown): Promise<unknown> => {
112
+ if (isSerializedTanstackRscFlightValue(current)) {
113
+ return (await getReviver())(current);
114
+ }
115
+ if (!current || typeof current !== 'object') {
116
+ return current;
117
+ }
118
+ if (seen.has(current)) {
119
+ return seen.get(current);
120
+ }
121
+ if (current instanceof Map) {
122
+ const result = new Map<unknown, unknown>();
123
+ seen.set(current, result);
124
+ for (const [key, item] of current) {
125
+ result.set(await visit(key), await visit(item));
126
+ }
127
+ return result;
128
+ }
129
+ if (current instanceof Set) {
130
+ const result = new Set<unknown>();
131
+ seen.set(current, result);
132
+ for (const item of current) {
133
+ result.add(await visit(item));
134
+ }
135
+ return result;
136
+ }
137
+ if (Array.isArray(current)) {
138
+ const result: unknown[] = [];
139
+ seen.set(current, result);
140
+ for (const item of current) {
141
+ result.push(await visit(item));
142
+ }
143
+ return result;
144
+ }
145
+ if (!isPlainObject(current)) {
146
+ return current;
147
+ }
148
+
149
+ const result: Record<string, unknown> = {};
150
+ seen.set(current, result);
151
+ for (const [key, item] of Object.entries(current)) {
152
+ result[key] = await visit(item);
153
+ }
154
+ return result;
155
+ };
156
+
157
+ return visit(value);
158
+ }
@@ -0,0 +1,73 @@
1
+ // @effect-diagnostics asyncFunction:off globalFetch:off processEnv:off strictBooleanExpressions:off
2
+ import type { ServerPayload } from '@modern-js/runtime/context';
3
+ import { isRouteErrorResponse } from '@modern-js/runtime-utils/router';
4
+
5
+ export function shouldRedactServerError(status = 500) {
6
+ return (
7
+ status >= 500 &&
8
+ process.env.NODE_ENV !== 'development' &&
9
+ process.env.NODE_ENV !== 'test'
10
+ );
11
+ }
12
+
13
+ export function serializePayloadError(error: unknown): unknown {
14
+ if (isRouteErrorResponse(error)) {
15
+ if (shouldRedactServerError(error.status)) {
16
+ return {
17
+ status: error.status,
18
+ statusText: 'Internal Server Error',
19
+ data: 'Unexpected Server Error',
20
+ __type: 'RouteErrorResponse',
21
+ };
22
+ }
23
+
24
+ return { ...error, __type: 'RouteErrorResponse' };
25
+ }
26
+
27
+ if (error instanceof Error) {
28
+ if (shouldRedactServerError()) {
29
+ return {
30
+ message: 'Unexpected Server Error',
31
+ stack: undefined,
32
+ __type: 'Error',
33
+ };
34
+ }
35
+
36
+ return {
37
+ message: error.message,
38
+ stack: error.stack,
39
+ __type: 'Error',
40
+ ...(error.name !== 'Error' ? { __subType: error.name } : {}),
41
+ };
42
+ }
43
+
44
+ if (shouldRedactServerError()) {
45
+ return {
46
+ message: 'Unexpected Server Error',
47
+ stack: undefined,
48
+ __type: 'Error',
49
+ };
50
+ }
51
+
52
+ return error;
53
+ }
54
+
55
+ export function isSerializedNotFound(value: unknown) {
56
+ return (
57
+ Boolean(value) &&
58
+ typeof value === 'object' &&
59
+ (value as { isNotFound?: unknown }).isNotFound === true
60
+ );
61
+ }
62
+
63
+ export function toRouteErrors(payload: ServerPayload) {
64
+ return payload.errors && typeof payload.errors === 'object'
65
+ ? (payload.errors as Record<string, unknown>)
66
+ : {};
67
+ }
68
+
69
+ export function toRouteLoaderData(payload: ServerPayload) {
70
+ return payload.loaderData && typeof payload.loaderData === 'object'
71
+ ? (payload.loaderData as Record<string, unknown>)
72
+ : {};
73
+ }
@@ -0,0 +1,97 @@
1
+ // @effect-diagnostics asyncFunction:off globalFetch:off processEnv:off strictBooleanExpressions:off
2
+ import type { ServerPayload } from '@modern-js/runtime/context';
3
+ import { notFound, redirect } from '@tanstack/react-router';
4
+ import { reviveTanstackRscFlightValues } from './flightSerialization';
5
+
6
+ type PayloadDecoder = (stream: ReadableStream<Uint8Array>) => Promise<unknown>;
7
+
8
+ export const payloadFetchCache = new Map<string, Promise<ServerPayload>>();
9
+ let payloadDecoder: PayloadDecoder | undefined;
10
+
11
+ export async function decodePayload(stream: ReadableStream<Uint8Array>) {
12
+ if (payloadDecoder) {
13
+ return reviveTanstackRscFlightValues(await payloadDecoder(stream));
14
+ }
15
+
16
+ const runtime = await import('@modern-js/runtime/rsc/client');
17
+ return reviveTanstackRscFlightValues(
18
+ await runtime.createFromReadableStream(stream),
19
+ );
20
+ }
21
+
22
+ export function isServerPayload(value: unknown): value is ServerPayload {
23
+ return (
24
+ Boolean(value) &&
25
+ typeof value === 'object' &&
26
+ (value as ServerPayload).type === 'render' &&
27
+ Array.isArray((value as ServerPayload).routes)
28
+ );
29
+ }
30
+
31
+ export function createPayloadFetchKey(request: Request) {
32
+ return JSON.stringify([
33
+ request.url,
34
+ [...request.headers.entries()].sort(([left], [right]) =>
35
+ left.localeCompare(right),
36
+ ),
37
+ ]);
38
+ }
39
+
40
+ export function isAbsoluteUrl(value: string) {
41
+ try {
42
+ void new URL(value);
43
+ return true;
44
+ } catch {
45
+ return false;
46
+ }
47
+ }
48
+
49
+ export async function fetchTanstackRscPayload(request: Request) {
50
+ const headers = new Headers(request.headers);
51
+ headers.set('x-rsc-tree', 'true');
52
+
53
+ const response = await fetch(request.url, {
54
+ credentials: 'same-origin',
55
+ headers,
56
+ method: 'GET',
57
+ signal: request.signal,
58
+ });
59
+
60
+ const redirectLocation = response.headers.get('X-Modernjs-Redirect');
61
+ if (redirectLocation) {
62
+ if (isAbsoluteUrl(redirectLocation)) {
63
+ throw redirect({
64
+ headers: response.headers,
65
+ href: redirectLocation,
66
+ statusCode: response.status,
67
+ });
68
+ }
69
+ throw redirect({
70
+ headers: response.headers,
71
+ statusCode: response.status,
72
+ to: redirectLocation || '/',
73
+ });
74
+ }
75
+
76
+ if (response.status === 404 && !response.body) {
77
+ throw notFound();
78
+ }
79
+
80
+ if (!response.body) {
81
+ throw new Error('TanStack RSC payload response body is null.');
82
+ }
83
+
84
+ const payload = await decodePayload(response.body);
85
+ if (!isServerPayload(payload)) {
86
+ throw new Error('Unexpected TanStack RSC payload type.');
87
+ }
88
+
89
+ return payload;
90
+ }
91
+
92
+ export function __setTanstackRscPayloadDecoderForTests(
93
+ decoder?: PayloadDecoder,
94
+ ) {
95
+ payloadDecoder = decoder;
96
+ payloadFetchCache.clear();
97
+ }