@bleedingdev/modern-js-plugin-tanstack 3.5.0-ultramodern.9 → 3.5.0-ultramodern.90

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 (270) hide show
  1. package/dist/cjs/cli/artifacts.js +157 -0
  2. package/dist/cjs/cli/index.js +8 -79
  3. package/dist/cjs/cli/tanstackTypes/canonicalRoutes.js +113 -0
  4. package/dist/cjs/cli/tanstackTypes/shared.js +123 -0
  5. package/dist/cjs/cli/tanstackTypes/source.js +255 -0
  6. package/dist/cjs/cli/tanstackTypes.js +4 -350
  7. package/dist/cjs/runtime/blockingSubscribe.js +57 -0
  8. package/dist/cjs/runtime/{pluginCore.js → clientBasepath.js} +12 -19
  9. package/dist/cjs/runtime/clientHydration.js +118 -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 +7 -11
  13. package/dist/cjs/runtime/plugin.js +21 -125
  14. package/dist/cjs/runtime/plugin.node.js +45 -125
  15. package/dist/cjs/runtime/pluginShared.js +87 -0
  16. package/dist/cjs/runtime/prefetchLink.js +15 -2
  17. package/dist/cjs/runtime/register.js +3 -16
  18. package/dist/cjs/runtime/routeTree/components.js +102 -0
  19. package/dist/cjs/runtime/routeTree/construction.js +152 -0
  20. package/dist/cjs/runtime/routeTree/index.js +47 -0
  21. package/dist/cjs/runtime/routeTree/loaders.js +158 -0
  22. package/dist/cjs/runtime/routeTree/paths.js +57 -0
  23. package/dist/cjs/runtime/routeTree/staticData.js +63 -0
  24. package/dist/cjs/runtime/routeTree/tanstackRoutes.js +57 -0
  25. package/dist/cjs/runtime/routeTree/types.js +18 -0
  26. package/dist/cjs/runtime/routeTree.js +7 -320
  27. package/dist/cjs/runtime/router.js +15 -2
  28. package/dist/cjs/runtime/rsc/CompositeComponent.js +18 -13
  29. package/dist/cjs/runtime/rsc/ReplayableStream.js +0 -4
  30. package/dist/cjs/runtime/rsc/RscNodeRenderer.js +5 -16
  31. package/dist/cjs/runtime/rsc/client.js +8 -25
  32. package/dist/cjs/runtime/rsc/flightSerialization.js +132 -0
  33. package/dist/cjs/runtime/rsc/payloadErrors.js +99 -0
  34. package/dist/cjs/runtime/rsc/payloadFetch.js +105 -0
  35. package/dist/cjs/runtime/rsc/payloadRouter.js +21 -142
  36. package/dist/cjs/runtime/rsc/payloadRoutes.js +94 -0
  37. package/dist/cjs/runtime/rsc/payloadStorage.js +58 -0
  38. package/dist/cjs/runtime/rsc/server.js +14 -18
  39. package/dist/cjs/runtime/rsc/shared.js +68 -0
  40. package/dist/cjs/runtime/rsc/slotUsageSanitizer.js +1 -0
  41. package/dist/cjs/runtime/rsc/treeGetter.js +72 -0
  42. package/dist/cjs/runtime/shared/isAbsoluteUrl.js +47 -0
  43. package/dist/cjs/runtime/ssrManagedTags.js +103 -0
  44. package/dist/cjs/runtime/ssrPreload.js +89 -0
  45. package/dist/cjs/runtime/ssrTypes.js +18 -0
  46. package/dist/cjs/runtime/state.js +1 -1
  47. package/dist/cjs/runtime/submitAction.js +161 -0
  48. package/dist/cjs/runtime/utils.js +49 -86
  49. package/dist/esm/cli/artifacts.mjs +103 -0
  50. package/dist/esm/cli/index.mjs +8 -82
  51. package/dist/esm/cli/tanstackTypes/canonicalRoutes.mjs +75 -0
  52. package/dist/esm/cli/tanstackTypes/shared.mjs +61 -0
  53. package/dist/esm/cli/tanstackTypes/source.mjs +207 -0
  54. package/dist/esm/cli/tanstackTypes.mjs +2 -339
  55. package/dist/esm/runtime/blockingSubscribe.mjs +19 -0
  56. package/dist/esm/runtime/clientBasepath.mjs +10 -0
  57. package/dist/esm/runtime/clientHydration.mjs +71 -0
  58. package/dist/esm/runtime/dataMutation.mjs +2 -167
  59. package/dist/esm/runtime/formData.mjs +63 -0
  60. package/dist/esm/runtime/loaderBridge.mjs +5 -9
  61. package/dist/esm/runtime/plugin.mjs +14 -118
  62. package/dist/esm/runtime/plugin.node.mjs +41 -121
  63. package/dist/esm/runtime/pluginShared.mjs +40 -0
  64. package/dist/esm/runtime/prefetchLink.mjs +18 -5
  65. package/dist/esm/runtime/register.mjs +1 -14
  66. package/dist/esm/runtime/routeTree/components.mjs +55 -0
  67. package/dist/esm/runtime/routeTree/construction.mjs +111 -0
  68. package/dist/esm/runtime/routeTree/index.mjs +2 -0
  69. package/dist/esm/runtime/routeTree/loaders.mjs +117 -0
  70. package/dist/esm/runtime/routeTree/paths.mjs +16 -0
  71. package/dist/esm/runtime/routeTree/staticData.mjs +22 -0
  72. package/dist/esm/runtime/routeTree/tanstackRoutes.mjs +13 -0
  73. package/dist/esm/runtime/routeTree/types.mjs +0 -0
  74. package/dist/esm/runtime/routeTree.mjs +1 -318
  75. package/dist/esm/runtime/router.mjs +16 -2
  76. package/dist/esm/runtime/rsc/CompositeComponent.mjs +18 -13
  77. package/dist/esm/runtime/rsc/ReplayableStream.mjs +1 -1
  78. package/dist/esm/runtime/rsc/RscNodeRenderer.mjs +4 -15
  79. package/dist/esm/runtime/rsc/client.mjs +6 -26
  80. package/dist/esm/runtime/rsc/flightSerialization.mjs +88 -0
  81. package/dist/esm/runtime/rsc/payloadErrors.mjs +49 -0
  82. package/dist/esm/runtime/rsc/payloadFetch.mjs +55 -0
  83. package/dist/esm/runtime/rsc/payloadRouter.mjs +12 -133
  84. package/dist/esm/runtime/rsc/payloadRoutes.mjs +50 -0
  85. package/dist/esm/runtime/rsc/payloadStorage.mjs +14 -0
  86. package/dist/esm/runtime/rsc/server.mjs +17 -21
  87. package/dist/esm/runtime/rsc/shared.mjs +21 -0
  88. package/dist/esm/runtime/rsc/slotUsageSanitizer.mjs +1 -0
  89. package/dist/esm/runtime/rsc/treeGetter.mjs +34 -0
  90. package/dist/esm/runtime/shared/isAbsoluteUrl.mjs +9 -0
  91. package/dist/esm/runtime/ssrManagedTags.mjs +53 -0
  92. package/dist/esm/runtime/ssrPreload.mjs +51 -0
  93. package/dist/esm/runtime/ssrTypes.mjs +0 -0
  94. package/dist/esm/runtime/state.mjs +1 -1
  95. package/dist/esm/runtime/submitAction.mjs +120 -0
  96. package/dist/esm/runtime/utils.mjs +47 -75
  97. package/dist/esm-node/cli/artifacts.mjs +104 -0
  98. package/dist/esm-node/cli/index.mjs +8 -82
  99. package/dist/esm-node/cli/tanstackTypes/canonicalRoutes.mjs +76 -0
  100. package/dist/esm-node/cli/tanstackTypes/shared.mjs +62 -0
  101. package/dist/esm-node/cli/tanstackTypes/source.mjs +208 -0
  102. package/dist/esm-node/cli/tanstackTypes.mjs +2 -339
  103. package/dist/esm-node/runtime/blockingSubscribe.mjs +20 -0
  104. package/dist/esm-node/runtime/clientBasepath.mjs +11 -0
  105. package/dist/esm-node/runtime/clientHydration.mjs +72 -0
  106. package/dist/esm-node/runtime/dataMutation.mjs +2 -167
  107. package/dist/esm-node/runtime/formData.mjs +64 -0
  108. package/dist/esm-node/runtime/loaderBridge.mjs +5 -9
  109. package/dist/esm-node/runtime/plugin.mjs +14 -118
  110. package/dist/esm-node/runtime/plugin.node.mjs +41 -121
  111. package/dist/esm-node/runtime/pluginShared.mjs +41 -0
  112. package/dist/esm-node/runtime/prefetchLink.mjs +18 -5
  113. package/dist/esm-node/runtime/register.mjs +1 -14
  114. package/dist/esm-node/runtime/routeTree/components.mjs +56 -0
  115. package/dist/esm-node/runtime/routeTree/construction.mjs +112 -0
  116. package/dist/esm-node/runtime/routeTree/index.mjs +3 -0
  117. package/dist/esm-node/runtime/routeTree/loaders.mjs +118 -0
  118. package/dist/esm-node/runtime/routeTree/paths.mjs +17 -0
  119. package/dist/esm-node/runtime/routeTree/staticData.mjs +23 -0
  120. package/dist/esm-node/runtime/routeTree/tanstackRoutes.mjs +14 -0
  121. package/dist/esm-node/runtime/routeTree/types.mjs +1 -0
  122. package/dist/esm-node/runtime/routeTree.mjs +1 -318
  123. package/dist/esm-node/runtime/router.mjs +16 -2
  124. package/dist/esm-node/runtime/rsc/CompositeComponent.mjs +18 -13
  125. package/dist/esm-node/runtime/rsc/ReplayableStream.mjs +1 -1
  126. package/dist/esm-node/runtime/rsc/RscNodeRenderer.mjs +4 -15
  127. package/dist/esm-node/runtime/rsc/client.mjs +6 -26
  128. package/dist/esm-node/runtime/rsc/flightSerialization.mjs +89 -0
  129. package/dist/esm-node/runtime/rsc/payloadErrors.mjs +50 -0
  130. package/dist/esm-node/runtime/rsc/payloadFetch.mjs +56 -0
  131. package/dist/esm-node/runtime/rsc/payloadRouter.mjs +12 -133
  132. package/dist/esm-node/runtime/rsc/payloadRoutes.mjs +51 -0
  133. package/dist/esm-node/runtime/rsc/payloadStorage.mjs +15 -0
  134. package/dist/esm-node/runtime/rsc/server.mjs +17 -21
  135. package/dist/esm-node/runtime/rsc/shared.mjs +22 -0
  136. package/dist/esm-node/runtime/rsc/slotUsageSanitizer.mjs +1 -0
  137. package/dist/esm-node/runtime/rsc/treeGetter.mjs +35 -0
  138. package/dist/esm-node/runtime/shared/isAbsoluteUrl.mjs +10 -0
  139. package/dist/esm-node/runtime/ssrManagedTags.mjs +54 -0
  140. package/dist/esm-node/runtime/ssrPreload.mjs +52 -0
  141. package/dist/esm-node/runtime/ssrTypes.mjs +1 -0
  142. package/dist/esm-node/runtime/state.mjs +1 -1
  143. package/dist/esm-node/runtime/submitAction.mjs +121 -0
  144. package/dist/esm-node/runtime/utils.mjs +47 -75
  145. package/dist/types/cli/artifacts.d.ts +33 -0
  146. package/dist/types/cli/index.d.ts +2 -22
  147. package/dist/types/cli/tanstackTypes/canonicalRoutes.d.ts +22 -0
  148. package/dist/types/cli/tanstackTypes/shared.d.ts +20 -0
  149. package/dist/types/cli/tanstackTypes/source.d.ts +12 -0
  150. package/dist/types/cli/tanstackTypes.d.ts +3 -31
  151. package/dist/types/runtime/blockingSubscribe.d.ts +1 -0
  152. package/dist/types/runtime/clientBasepath.d.ts +1 -0
  153. package/dist/types/runtime/clientHydration.d.ts +10 -0
  154. package/dist/types/runtime/dataMutation.d.ts +3 -12
  155. package/dist/types/runtime/formData.d.ts +24 -0
  156. package/dist/types/runtime/loaderBridge.d.ts +2 -1
  157. package/dist/types/runtime/plugin.d.ts +1 -1
  158. package/dist/types/runtime/plugin.node.d.ts +1 -1
  159. package/dist/types/runtime/pluginShared.d.ts +38 -0
  160. package/dist/types/runtime/register.d.ts +10 -9
  161. package/dist/types/runtime/routeTree/components.d.ts +7 -0
  162. package/dist/types/runtime/routeTree/construction.d.ts +5 -0
  163. package/dist/types/runtime/routeTree/index.d.ts +2 -0
  164. package/dist/types/runtime/routeTree/loaders.d.ts +4 -0
  165. package/dist/types/runtime/routeTree/paths.d.ts +3 -0
  166. package/dist/types/runtime/routeTree/staticData.d.ts +19 -0
  167. package/dist/types/runtime/routeTree/tanstackRoutes.d.ts +4 -0
  168. package/dist/types/runtime/routeTree/types.d.ts +76 -0
  169. package/dist/types/runtime/routeTree.d.ts +1 -9
  170. package/dist/types/runtime/router.d.ts +6 -7
  171. package/dist/types/runtime/rsc/CompositeComponent.d.ts +1 -2
  172. package/dist/types/runtime/rsc/ReplayableStream.d.ts +3 -2
  173. package/dist/types/runtime/rsc/RscNodeRenderer.d.ts +2 -3
  174. package/dist/types/runtime/rsc/SlotContext.d.ts +2 -1
  175. package/dist/types/runtime/rsc/client.d.ts +2 -0
  176. package/dist/types/runtime/rsc/flightSerialization.d.ts +3 -0
  177. package/dist/types/runtime/rsc/payloadErrors.d.ts +6 -0
  178. package/dist/types/runtime/rsc/payloadFetch.d.ts +8 -0
  179. package/dist/types/runtime/rsc/payloadRouter.d.ts +2 -10
  180. package/dist/types/runtime/rsc/payloadRoutes.d.ts +40 -0
  181. package/dist/types/runtime/rsc/payloadStorage.d.ts +5 -0
  182. package/dist/types/runtime/rsc/shared.d.ts +18 -0
  183. package/dist/types/runtime/rsc/treeGetter.d.ts +1 -0
  184. package/dist/types/runtime/shared/isAbsoluteUrl.d.ts +1 -0
  185. package/dist/types/runtime/ssrManagedTags.d.ts +7 -0
  186. package/dist/types/runtime/ssrPreload.d.ts +2 -0
  187. package/dist/types/runtime/ssrTypes.d.ts +44 -0
  188. package/dist/types/runtime/state.d.ts +1 -1
  189. package/dist/types/runtime/submitAction.d.ts +14 -0
  190. package/dist/types/runtime/types.d.ts +4 -10
  191. package/dist/types/runtime/utils.d.ts +4 -24
  192. package/package.json +37 -17
  193. package/rstest.config.mts +23 -0
  194. package/src/cli/artifacts.ts +255 -0
  195. package/src/cli/index.ts +7 -185
  196. package/src/cli/tanstackTypes/canonicalRoutes.ts +157 -0
  197. package/src/cli/tanstackTypes/shared.ts +113 -0
  198. package/src/cli/tanstackTypes/source.ts +414 -0
  199. package/src/cli/tanstackTypes.ts +4 -647
  200. package/src/runtime/blockingSubscribe.ts +48 -0
  201. package/src/runtime/clientBasepath.ts +12 -0
  202. package/src/runtime/clientHydration.ts +149 -0
  203. package/src/runtime/dataMutation.tsx +9 -306
  204. package/src/runtime/formData.ts +153 -0
  205. package/src/runtime/loaderBridge.ts +11 -12
  206. package/src/runtime/plugin.node.tsx +76 -291
  207. package/src/runtime/plugin.tsx +21 -257
  208. package/src/runtime/pluginShared.ts +112 -0
  209. package/src/runtime/prefetchLink.tsx +78 -15
  210. package/src/runtime/register.ts +10 -42
  211. package/src/runtime/routeTree/components.ts +130 -0
  212. package/src/runtime/routeTree/construction.ts +238 -0
  213. package/src/runtime/routeTree/index.ts +7 -0
  214. package/src/runtime/routeTree/loaders.ts +232 -0
  215. package/src/runtime/routeTree/paths.ts +36 -0
  216. package/src/runtime/routeTree/staticData.ts +66 -0
  217. package/src/runtime/routeTree/tanstackRoutes.ts +36 -0
  218. package/src/runtime/routeTree/types.ts +87 -0
  219. package/src/runtime/routeTree.ts +5 -750
  220. package/src/runtime/router.ts +35 -7
  221. package/src/runtime/rsc/CompositeComponent.tsx +29 -20
  222. package/src/runtime/rsc/ReplayableStream.ts +2 -2
  223. package/src/runtime/rsc/RscNodeRenderer.tsx +9 -27
  224. package/src/runtime/rsc/SlotContext.tsx +1 -1
  225. package/src/runtime/rsc/client.tsx +12 -40
  226. package/src/runtime/rsc/flightSerialization.ts +158 -0
  227. package/src/runtime/rsc/payloadErrors.ts +73 -0
  228. package/src/runtime/rsc/payloadFetch.ts +92 -0
  229. package/src/runtime/rsc/payloadRouter.ts +29 -234
  230. package/src/runtime/rsc/payloadRoutes.ts +122 -0
  231. package/src/runtime/rsc/payloadStorage.ts +35 -0
  232. package/src/runtime/rsc/server.tsx +20 -29
  233. package/src/runtime/rsc/shared.ts +70 -0
  234. package/src/runtime/rsc/slotUsageSanitizer.ts +4 -0
  235. package/src/runtime/rsc/treeGetter.tsx +52 -0
  236. package/src/runtime/shared/isAbsoluteUrl.ts +8 -0
  237. package/src/runtime/ssrManagedTags.ts +107 -0
  238. package/src/runtime/ssrPreload.ts +125 -0
  239. package/src/runtime/ssrTypes.ts +51 -0
  240. package/src/runtime/state.ts +9 -3
  241. package/src/runtime/submitAction.ts +201 -0
  242. package/src/runtime/types.ts +4 -18
  243. package/src/runtime/utils.tsx +76 -110
  244. package/src/types/react-server-dom-rspack.d.ts +56 -0
  245. package/tests/castRatchet.test.ts +85 -0
  246. package/tests/realm-isolation.test.ts +114 -0
  247. package/tests/router/cli.test.ts +7 -0
  248. package/tests/router/clientHydration.test.tsx +61 -0
  249. package/tests/router/dataMutation.test.tsx +59 -0
  250. package/tests/router/fixtures/legacyRuntimeRouter.ts +10 -0
  251. package/tests/router/fixtures/router-gen.golden.txt +71 -0
  252. package/tests/router/fixtures/router-gen.oxlint.json +5 -0
  253. package/tests/router/flightSerialization.roundtrip.test.tsx +137 -0
  254. package/tests/router/generateRouteArtifacts.test.ts +106 -0
  255. package/tests/router/hooks.test.ts +14 -0
  256. package/tests/router/loaderBridge.test.ts +21 -0
  257. package/tests/router/prefetchLink.test.tsx +106 -59
  258. package/tests/router/prefetchLinkPreload.test.tsx +85 -0
  259. package/tests/router/register.test.ts +1 -39
  260. package/tests/router/routeTree.test.ts +51 -11
  261. package/tests/router/routerCompatibility.test.ts +245 -0
  262. package/tests/router/rsc.test.tsx +189 -0
  263. package/tests/router/rscPayloadRouterMatrix.test.ts +197 -0
  264. package/tests/router/slotUsageSanitizer.test.ts +23 -0
  265. package/tests/router/ssrPreload.test.ts +30 -0
  266. package/tests/router/tanstackTypes.test.ts +298 -1
  267. package/dist/esm/runtime/pluginCore.mjs +0 -14
  268. package/dist/esm-node/runtime/pluginCore.mjs +0 -15
  269. package/dist/types/runtime/pluginCore.d.ts +0 -21
  270. package/src/runtime/pluginCore.ts +0 -48
@@ -4,12 +4,40 @@
4
4
  * `router: { framework: 'tanstack', createRoutes }` in modern.runtime.ts).
5
5
  *
6
6
  * The CLI plugin injects `{ name: 'router', path: '<pkg>/runtime/router' }`
7
- * for those entries, so the generated entry code value-imports `routerPlugin`
8
- * from here. That single import both installs the framework-resolving router
9
- * plugin of @modern-js/runtime AND registers the TanStack router provider
10
- * (the './register' side effect) — the registration can therefore never be
11
- * tree-shaken away from the entry that needs it.
7
+ * for those entries. This module creates a framework-resolving wrapper whose
8
+ * app-owned provider realm contains this module graph's TanStack factory.
12
9
  */
13
- import './register';
10
+ import * as runtimeRouter from '@modern-js/runtime/router/internal';
11
+ import { tanstackRouterProviderFactory } from './register';
14
12
 
15
- export { routerPlugin } from '@modern-js/runtime/router/internal';
13
+ type LegacyRouterPlugin = (typeof runtimeRouter)['routerPlugin'];
14
+ type CurrentRouterPluginCreator = (
15
+ localProviders: readonly {
16
+ name: string;
17
+ factory: typeof tanstackRouterProviderFactory;
18
+ }[],
19
+ ) => LegacyRouterPlugin;
20
+
21
+ function getRouterPlugin(): LegacyRouterPlugin {
22
+ const createRouterPlugin = Reflect.get(runtimeRouter, 'createRouterPlugin') as
23
+ | CurrentRouterPluginCreator
24
+ | undefined;
25
+
26
+ if (typeof createRouterPlugin === 'function') {
27
+ return createRouterPlugin([
28
+ { name: 'tanstack', factory: tanstackRouterProviderFactory },
29
+ ]);
30
+ }
31
+
32
+ const legacyRouterPlugin = Reflect.get(runtimeRouter, 'routerPlugin');
33
+
34
+ if (typeof legacyRouterPlugin === 'function') {
35
+ return tanstackRouterProviderFactory as unknown as LegacyRouterPlugin;
36
+ }
37
+
38
+ throw new Error(
39
+ '[@modern-js/plugin-tanstack] The installed @modern-js/runtime/router/internal exports neither createRouterPlugin nor routerPlugin. Install a compatible @modern-js/runtime version.',
40
+ );
41
+ }
42
+
43
+ export const routerPlugin: LegacyRouterPlugin = getRouterPlugin();
@@ -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,5 +1,5 @@
1
1
  // @effect-diagnostics asyncFunction:off newPromise:off strictBooleanExpressions:off
2
- export interface ReplayableStreamOptions {
2
+ interface ReplayableStreamOptions {
3
3
  signal?: AbortSignal;
4
4
  }
5
5
 
@@ -8,7 +8,7 @@ type Waiter = {
8
8
  resolve: () => void;
9
9
  };
10
10
 
11
- export const REPLAYABLE_STREAM_MARKER = Symbol.for(
11
+ const REPLAYABLE_STREAM_MARKER = Symbol.for(
12
12
  'modern.tanstack.rsc.ReplayableStream',
13
13
  );
14
14
 
@@ -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({
@@ -3,7 +3,7 @@
3
3
  import type React from 'react';
4
4
  import { createContext, use } from 'react';
5
5
 
6
- export type SlotImplementations = Record<string, unknown>;
6
+ type SlotImplementations = Record<string, unknown>;
7
7
 
8
8
  const SlotContext = createContext<{
9
9
  implementations: SlotImplementations;
@@ -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,92 @@
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 { isAbsoluteUrl } from '../shared/isAbsoluteUrl';
5
+ import { reviveTanstackRscFlightValues } from './flightSerialization';
6
+
7
+ export { isAbsoluteUrl };
8
+
9
+ type PayloadDecoder = (stream: ReadableStream<Uint8Array>) => Promise<unknown>;
10
+
11
+ export const payloadFetchCache = new Map<string, Promise<ServerPayload>>();
12
+ let payloadDecoder: PayloadDecoder | undefined;
13
+
14
+ async function decodePayload(stream: ReadableStream<Uint8Array>) {
15
+ if (payloadDecoder) {
16
+ return reviveTanstackRscFlightValues(await payloadDecoder(stream));
17
+ }
18
+
19
+ const runtime = await import('@modern-js/runtime/rsc/client');
20
+ return reviveTanstackRscFlightValues(
21
+ await runtime.createFromReadableStream(stream),
22
+ );
23
+ }
24
+
25
+ function isServerPayload(value: unknown): value is ServerPayload {
26
+ return (
27
+ Boolean(value) &&
28
+ typeof value === 'object' &&
29
+ (value as ServerPayload).type === 'render' &&
30
+ Array.isArray((value as ServerPayload).routes)
31
+ );
32
+ }
33
+
34
+ export function createPayloadFetchKey(request: Request) {
35
+ return JSON.stringify([
36
+ request.url,
37
+ request.method,
38
+ [...request.headers.entries()].sort(([left], [right]) =>
39
+ left.localeCompare(right),
40
+ ),
41
+ ]);
42
+ }
43
+
44
+ export async function fetchTanstackRscPayload(request: Request) {
45
+ const headers = new Headers(request.headers);
46
+ headers.set('x-rsc-tree', 'true');
47
+
48
+ const response = await fetch(request.url, {
49
+ credentials: 'same-origin',
50
+ headers,
51
+ method: 'GET',
52
+ signal: request.signal,
53
+ });
54
+
55
+ const redirectLocation = response.headers.get('X-Modernjs-Redirect');
56
+ if (redirectLocation) {
57
+ if (isAbsoluteUrl(redirectLocation)) {
58
+ throw redirect({
59
+ headers: response.headers,
60
+ href: redirectLocation,
61
+ statusCode: response.status,
62
+ });
63
+ }
64
+ throw redirect({
65
+ headers: response.headers,
66
+ statusCode: response.status,
67
+ to: redirectLocation || '/',
68
+ });
69
+ }
70
+
71
+ if (response.status === 404 && !response.body) {
72
+ throw notFound();
73
+ }
74
+
75
+ if (!response.body) {
76
+ throw new Error('TanStack RSC payload response body is null.');
77
+ }
78
+
79
+ const payload = await decodePayload(response.body);
80
+ if (!isServerPayload(payload)) {
81
+ throw new Error('Unexpected TanStack RSC payload type.');
82
+ }
83
+
84
+ return payload;
85
+ }
86
+
87
+ export function __setTanstackRscPayloadDecoderForTests(
88
+ decoder?: PayloadDecoder,
89
+ ) {
90
+ payloadDecoder = decoder;
91
+ payloadFetchCache.clear();
92
+ }