@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
@@ -1,46 +1,8 @@
1
1
  import { resolveRouterProvider } from '@modern-js/runtime/context';
2
- import {
3
- Form,
4
- Link,
5
- NavLink,
6
- Outlet,
7
- RouteActionResponseError,
8
- useFetcher,
9
- } from '../../src/runtime';
10
- import { tanstackRouterCompatBindings } from '../../src/runtime/register';
11
-
12
- const COMPAT_BINDINGS_SLOT = Symbol.for(
13
- '@modern-js/plugin-tanstack:runtime-compat-bindings',
14
- );
2
+ import '../../src/runtime/register';
15
3
 
16
4
  describe("'@modern-js/plugin-tanstack/runtime' import side effects", () => {
17
5
  it('registers the tanstack router provider', () => {
18
6
  expect(typeof resolveRouterProvider('tanstack')).toBe('function');
19
7
  });
20
-
21
- it("publishes the compat bindings consumed by '@modern-js/runtime/tanstack-router'", () => {
22
- const bindings = (globalThis as Record<symbol, unknown>)[
23
- COMPAT_BINDINGS_SLOT
24
- ] as typeof tanstackRouterCompatBindings;
25
-
26
- expect(bindings).toBeDefined();
27
- expect(bindings).toBe(tanstackRouterCompatBindings);
28
- expect(bindings.Form).toBe(Form);
29
- expect(bindings.Link).toBe(Link);
30
- expect(bindings.NavLink).toBe(NavLink);
31
- expect(bindings.Outlet).toBe(Outlet);
32
- expect(bindings.RouteActionResponseError).toBe(RouteActionResponseError);
33
- expect(bindings.useFetcher).toBe(useFetcher);
34
- });
35
-
36
- it('keeps the first published bindings when a duplicate module copy evaluates', () => {
37
- // Simulates a Module Federation remote evaluating its own copy of
38
- // register.ts: `??=` must keep the established bindings.
39
- const host = globalThis as Record<symbol, unknown>;
40
- const established = host[COMPAT_BINDINGS_SLOT];
41
- expect(established).toBeDefined();
42
-
43
- host[COMPAT_BINDINGS_SLOT] ??= { duplicate: true };
44
- expect(host[COMPAT_BINDINGS_SLOT]).toBe(established);
45
- });
46
8
  });
@@ -15,7 +15,7 @@ import {
15
15
  getModernRouteIdsFromMatches,
16
16
  } from '../../src/runtime/routeTree';
17
17
  import { __setTanstackRscPayloadDecoderForTests } from '../../src/runtime/rsc/payloadRouter';
18
- import { createRouteObjectsFromConfig } from '../../src/runtime/utils';
18
+ import { createTanstackRouteObjectsFromConfig } from '../../src/runtime/utils';
19
19
 
20
20
  type LoaderArgs = {
21
21
  params: Record<string, string>;
@@ -151,15 +151,15 @@ describe('tanstack runtime public exports', () => {
151
151
  };
152
152
 
153
153
  expect(packageJson.exports['./runtime/rsc']).toBeUndefined();
154
- expect(packageJson.exports['./runtime/rsc/client']).toBeUndefined();
155
- expect(packageJson.exports['./runtime/rsc/server']).toBeUndefined();
154
+ expect(packageJson.exports['./runtime/rsc/client']).toBeDefined();
155
+ expect(packageJson.exports['./runtime/rsc/server']).toBeDefined();
156
156
  expect(packageJson.typesVersions?.['*']?.['runtime/rsc']).toBeUndefined();
157
- expect(
158
- packageJson.typesVersions?.['*']?.['runtime/rsc/client'],
159
- ).toBeUndefined();
160
- expect(
161
- packageJson.typesVersions?.['*']?.['runtime/rsc/server'],
162
- ).toBeUndefined();
157
+ expect(packageJson.typesVersions?.['*']?.['runtime/rsc/client']).toEqual([
158
+ './dist/types/runtime/rsc/client.d.ts',
159
+ ]);
160
+ expect(packageJson.typesVersions?.['*']?.['runtime/rsc/server']).toEqual([
161
+ './dist/types/runtime/rsc/server.d.ts',
162
+ ]);
163
163
  });
164
164
  });
165
165
 
@@ -201,6 +201,41 @@ describe('tanstack route tree from RouteObject[]', () => {
201
201
  expect(userMatch?.loaderData).toEqual({ id: '123' });
202
202
  });
203
203
 
204
+ test('keeps unnamed sibling pathless layouts distinct', async () => {
205
+ const routes: RouteObject[] = [
206
+ {
207
+ Component: () => null,
208
+ children: [
209
+ {
210
+ path: 'alpha',
211
+ loader: () => ({ value: 'alpha' }),
212
+ Component: () => null,
213
+ },
214
+ ],
215
+ },
216
+ {
217
+ Component: () => null,
218
+ children: [
219
+ {
220
+ path: 'beta',
221
+ loader: () => ({ value: 'beta' }),
222
+ Component: () => null,
223
+ },
224
+ ],
225
+ },
226
+ ];
227
+
228
+ const routeTree = createRouteTreeFromRouteObjects(routes);
229
+ const router = await loadRouteTree(routeTree, '/beta');
230
+
231
+ const matchedLoaderData = router.state.matches
232
+ .map(match => match.loaderData)
233
+ .filter(Boolean);
234
+
235
+ expect(matchedLoaderData).toContainEqual({ value: 'beta' });
236
+ expect(matchedLoaderData).not.toContainEqual({ value: 'alpha' });
237
+ });
238
+
204
239
  test('reports native TanStack unknown routes as HTTP 404', async () => {
205
240
  const routes: RouteObject[] = [
206
241
  {
@@ -774,13 +809,16 @@ describe('tanstack route tree from RouteObject[]', () => {
774
809
  path: 'client',
775
810
  clientData: './client.data',
776
811
  data: './data',
812
+ hasAction: true,
813
+ hasClientLoader: true,
814
+ hasLoader: true,
777
815
  inValidSSRRoute: true,
778
816
  isClientComponent: true,
779
817
  },
780
818
  ],
781
819
  },
782
820
  ];
783
- const routeObjects = createRouteObjectsFromConfig({
821
+ const routeObjects = createTanstackRouteObjectsFromConfig({
784
822
  routesConfig: { routes: modernRoutes },
785
823
  });
786
824
  const routeTree = createRouteTreeFromRouteObjects(routeObjects || []);
@@ -795,7 +833,9 @@ describe('tanstack route tree from RouteObject[]', () => {
795
833
 
796
834
  expect(clientRoute.options.ssr).toBe(false);
797
835
  expect(clientRoute.options.staticData).toMatchObject({
836
+ modernRouteHasAction: true,
798
837
  modernRouteHasClientLoader: true,
838
+ modernRouteHasLoader: true,
799
839
  modernRouteIsClientComponent: true,
800
840
  });
801
841
  });
@@ -825,7 +865,7 @@ describe('tanstack route tree from RouteObject[]', () => {
825
865
  },
826
866
  ];
827
867
 
828
- const routeObjects = createRouteObjectsFromConfig({
868
+ const routeObjects = createTanstackRouteObjectsFromConfig({
829
869
  routesConfig: { routes: modernRoutes },
830
870
  });
831
871
  const rootRoute = routeObjects?.[0];
@@ -0,0 +1,245 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import {
3
+ mkdirSync,
4
+ mkdtempSync,
5
+ readFileSync,
6
+ rmSync,
7
+ writeFileSync,
8
+ } from 'node:fs';
9
+ import { tmpdir } from 'node:os';
10
+ import path from 'node:path';
11
+
12
+ const REGISTRY_SLOT: unique symbol = Symbol.for(
13
+ '@modern-js/runtime:router-providers:v3',
14
+ );
15
+ const registryHost = globalThis as { [REGISTRY_SLOT]?: unknown };
16
+ const webpackHost = globalThis as typeof globalThis & {
17
+ __webpack_require__?: { u: (chunkId: unknown) => string };
18
+ };
19
+ const installWebpackRequire = () => {
20
+ webpackHost.__webpack_require__ = { u: chunkId => String(chunkId) };
21
+ };
22
+
23
+ type LegacyRuntimeRouterModule = {
24
+ getLegacyRouterPluginInvocationCount: () => number;
25
+ routerPlugin: (...args: unknown[]) => unknown;
26
+ };
27
+
28
+ type CompatibilityGraph = {
29
+ factory: (...args: any[]) => any;
30
+ legacyRuntimeRouter: LegacyRuntimeRouterModule;
31
+ resolveRouterProvider: (
32
+ framework?: string,
33
+ ) => (...args: unknown[]) => unknown;
34
+ routerPlugin: (...args: any[]) => any;
35
+ };
36
+
37
+ async function loadCompatibilityGraph(): Promise<CompatibilityGraph> {
38
+ rstest.resetModules();
39
+ installWebpackRequire();
40
+
41
+ const legacyRuntimeRouter = (await import(
42
+ '@modern-js/runtime/router/internal'
43
+ )) as unknown as LegacyRuntimeRouterModule;
44
+ const { routerPlugin } = await import('../../src/runtime/router');
45
+ const { tanstackRouterProviderFactory } = await import(
46
+ '../../src/runtime/register'
47
+ );
48
+ const { resolveRouterProvider } = await import('@modern-js/runtime/context');
49
+
50
+ return {
51
+ factory: tanstackRouterProviderFactory,
52
+ legacyRuntimeRouter,
53
+ resolveRouterProvider,
54
+ routerPlugin,
55
+ };
56
+ }
57
+
58
+ function resolveTsgoBin(): string {
59
+ const packageJsonPath = require.resolve(
60
+ '@typescript/native-preview/package.json',
61
+ );
62
+ const packageDirectory = path.dirname(packageJsonPath);
63
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8')) as {
64
+ bin?: string | { tsgo?: string };
65
+ };
66
+ const binEntry =
67
+ typeof packageJson.bin === 'string'
68
+ ? packageJson.bin
69
+ : packageJson.bin?.tsgo;
70
+
71
+ return path.resolve(packageDirectory, binEntry ?? 'bin/tsgo.js');
72
+ }
73
+
74
+ function runTsgo(tsgoBin: string, configPath: string): void {
75
+ try {
76
+ execFileSync(process.execPath, [tsgoBin, '-p', configPath], {
77
+ stdio: 'pipe',
78
+ });
79
+ } catch (error) {
80
+ const result = error as { stderr?: Buffer; stdout?: Buffer };
81
+ throw new Error(
82
+ `TS-Go compatibility check failed:\n${String(result.stdout ?? '')}${String(
83
+ result.stderr ?? '',
84
+ )}`,
85
+ );
86
+ }
87
+ }
88
+
89
+ installWebpackRequire();
90
+
91
+ describe('runtime router compatibility', () => {
92
+ beforeEach(() => {
93
+ delete registryHost[REGISTRY_SLOT];
94
+ rstest.resetModules();
95
+ installWebpackRequire();
96
+ });
97
+
98
+ afterEach(() => {
99
+ delete registryHost[REGISTRY_SLOT];
100
+ });
101
+
102
+ it('uses the app-local factory instead of the legacy global wrapper', async () => {
103
+ const graph = await loadCompatibilityGraph();
104
+
105
+ expect('createRouterPlugin' in graph.legacyRuntimeRouter).toBe(false);
106
+ expect(graph.routerPlugin).toBe(graph.factory);
107
+ expect(graph.routerPlugin({ framework: 'tanstack' })).toMatchObject({
108
+ name: '@modern-js/plugin-router-tanstack',
109
+ });
110
+ expect(
111
+ graph.legacyRuntimeRouter.getLegacyRouterPluginInvocationCount(),
112
+ ).toBe(0);
113
+ });
114
+
115
+ it('keeps independently evaluated legacy module graphs app-local', async () => {
116
+ const graphA = await loadCompatibilityGraph();
117
+ const graphB = await loadCompatibilityGraph();
118
+
119
+ expect(graphB.factory).not.toBe(graphA.factory);
120
+ expect(graphB.routerPlugin).toBe(graphB.factory);
121
+ expect(graphB.resolveRouterProvider('tanstack')).toBe(graphA.factory);
122
+ expect(graphB.routerPlugin({ framework: 'tanstack' })).toMatchObject({
123
+ name: '@modern-js/plugin-router-tanstack',
124
+ });
125
+ expect(
126
+ graphA.legacyRuntimeRouter.getLegacyRouterPluginInvocationCount(),
127
+ ).toBe(0);
128
+ expect(
129
+ graphB.legacyRuntimeRouter.getLegacyRouterPluginInvocationCount(),
130
+ ).toBe(0);
131
+ });
132
+
133
+ it('emits declarations compatible with the oldest runtime router shape', () => {
134
+ const packageRoot = path.resolve(__dirname, '../..');
135
+ const sourcePath = path.join(packageRoot, 'src/runtime/router.ts');
136
+ const legacyFixturePath = path.join(
137
+ __dirname,
138
+ 'fixtures/legacyRuntimeRouter.ts',
139
+ );
140
+ const tempRoot = mkdtempSync(
141
+ path.join(tmpdir(), 'plugin-tanstack-router-compatibility-'),
142
+ );
143
+ const sourceRoot = path.join(tempRoot, 'src');
144
+ const emittedRoot = path.join(tempRoot, 'types');
145
+ const tsgoBin = resolveTsgoBin();
146
+
147
+ try {
148
+ mkdirSync(sourceRoot, { recursive: true });
149
+ writeFileSync(
150
+ path.join(sourceRoot, 'router.ts'),
151
+ readFileSync(sourcePath, 'utf8'),
152
+ );
153
+ writeFileSync(
154
+ path.join(sourceRoot, 'register.ts'),
155
+ [
156
+ 'export declare const tanstackRouterProviderFactory:',
157
+ ' (userConfig?: Record<string, unknown>) => { name?: string };',
158
+ ].join('\n'),
159
+ );
160
+ writeFileSync(
161
+ path.join(tempRoot, 'currentRuntimeRouter.d.ts'),
162
+ [
163
+ 'export type RouterPluginFactory =',
164
+ ' (userConfig?: Record<string, unknown>) => { name?: string };',
165
+ 'export declare const routerPlugin: RouterPluginFactory;',
166
+ 'export declare const createRouterPlugin:',
167
+ ' (providers: readonly unknown[]) => RouterPluginFactory;',
168
+ ].join('\n'),
169
+ );
170
+ writeFileSync(
171
+ path.join(tempRoot, 'emit.json'),
172
+ JSON.stringify(
173
+ {
174
+ compilerOptions: {
175
+ declaration: true,
176
+ emitDeclarationOnly: true,
177
+ module: 'Preserve',
178
+ moduleResolution: 'Bundler',
179
+ noCheck: true,
180
+ outDir: emittedRoot,
181
+ paths: {
182
+ '@modern-js/runtime/router/internal': [
183
+ './currentRuntimeRouter.d.ts',
184
+ ],
185
+ },
186
+ rootDir: sourceRoot,
187
+ skipLibCheck: false,
188
+ strict: true,
189
+ target: 'ESNext',
190
+ types: [],
191
+ },
192
+ files: [path.join(sourceRoot, 'router.ts')],
193
+ },
194
+ null,
195
+ 2,
196
+ ),
197
+ );
198
+
199
+ runTsgo(tsgoBin, path.join(tempRoot, 'emit.json'));
200
+
201
+ const declarationPath = path.join(emittedRoot, 'router.d.ts');
202
+ const declaration = readFileSync(declarationPath, 'utf8');
203
+ expect(declaration).not.toMatch(
204
+ /\b(?:createRouterPlugin|RouterPluginFactory)\b/u,
205
+ );
206
+ expect(declaration).toContain("['routerPlugin']");
207
+
208
+ writeFileSync(
209
+ path.join(tempRoot, 'legacyRuntimeRouter.ts'),
210
+ readFileSync(legacyFixturePath, 'utf8'),
211
+ );
212
+ writeFileSync(
213
+ path.join(tempRoot, 'compatibility.json'),
214
+ JSON.stringify(
215
+ {
216
+ compilerOptions: {
217
+ module: 'Preserve',
218
+ moduleResolution: 'Bundler',
219
+ noEmit: true,
220
+ paths: {
221
+ '@modern-js/runtime/router/internal': [
222
+ './legacyRuntimeRouter.ts',
223
+ ],
224
+ },
225
+ skipLibCheck: false,
226
+ strict: true,
227
+ target: 'ESNext',
228
+ types: [],
229
+ },
230
+ files: [
231
+ declarationPath,
232
+ path.join(tempRoot, 'legacyRuntimeRouter.ts'),
233
+ ],
234
+ },
235
+ null,
236
+ 2,
237
+ ),
238
+ );
239
+
240
+ runTsgo(tsgoBin, path.join(tempRoot, 'compatibility.json'));
241
+ } finally {
242
+ rmSync(tempRoot, { force: true, recursive: true });
243
+ }
244
+ });
245
+ });
@@ -2,6 +2,10 @@ import { UNSAFE_ErrorResponseImpl as ErrorResponseImpl } from '@modern-js/runtim
2
2
  import type React from 'react';
3
3
  import { isValidElement } from 'react';
4
4
  import { createRscProxy } from '../../src/runtime/rsc/createRscProxy';
5
+ import {
6
+ reviveTanstackRscFlightValues,
7
+ serializeTanstackRscFlightValues,
8
+ } from '../../src/runtime/rsc/flightSerialization';
5
9
  import {
6
10
  __setTanstackRscPayloadDecoderForTests,
7
11
  createTanstackRscServerPayload,
@@ -65,6 +69,54 @@ describe('tanstack rsc runtime helpers', () => {
65
69
  ]);
66
70
  });
67
71
 
72
+ test('revives shared structures that the Flight serializer preserves', async () => {
73
+ const shared = { label: 'shared' };
74
+ const serialized = serializeTanstackRscFlightValues({
75
+ left: shared,
76
+ right: shared,
77
+ }) as { left: unknown; right: unknown };
78
+
79
+ const revived = (await reviveTanstackRscFlightValues(serialized)) as {
80
+ left: unknown;
81
+ right: unknown;
82
+ };
83
+
84
+ expect(serialized.left).toBe(serialized.right);
85
+ expect(revived.left).toBe(revived.right);
86
+ });
87
+
88
+ test('serializes TanStack RSC flight values nested in map and set containers', () => {
89
+ const stream: ServerComponentStream = {
90
+ createReplayStream: () => new ReadableStream<Uint8Array>(),
91
+ };
92
+ const proxy = createRscProxy(() => null, {
93
+ renderable: true,
94
+ stream,
95
+ }) as React.ReactElement & Record<PropertyKey, unknown>;
96
+
97
+ const serialized = serializeTanstackRscFlightValues({
98
+ map: new Map([['slot', proxy]]),
99
+ set: new Set([proxy]),
100
+ }) as {
101
+ map: Map<string, Record<string, unknown>>;
102
+ set: Set<Record<string, unknown>>;
103
+ };
104
+
105
+ const mapValue = serialized.map.get('slot');
106
+ const [setValue] = serialized.set;
107
+
108
+ expect(mapValue).not.toBe(proxy);
109
+ expect(setValue).not.toBe(proxy);
110
+ expect(mapValue).toMatchObject({
111
+ __modernTanstackRsc: true,
112
+ kind: 'renderable',
113
+ });
114
+ expect(setValue).toMatchObject({
115
+ __modernTanstackRsc: true,
116
+ kind: 'renderable',
117
+ });
118
+ });
119
+
68
120
  test('renderable RSC proxies preserve React element behavior and metadata', () => {
69
121
  const stream: ServerComponentStream = {
70
122
  createReplayStream: () => new ReadableStream<Uint8Array>(),
@@ -219,6 +271,36 @@ describe('tanstack rsc runtime helpers', () => {
219
271
  expect(JSON.stringify(payload.errors)).not.toContain('stack secret');
220
272
  });
221
273
 
274
+ test('redacts production TanStack RSC non-Error server payload errors', () => {
275
+ const payload = withNodeEnv('production', () =>
276
+ createTanstackRscServerPayload({
277
+ state: {
278
+ location: { href: '/plain' },
279
+ matches: [
280
+ {
281
+ error: { message: 'plain secret', token: 'token secret' },
282
+ params: {},
283
+ pathname: '/plain',
284
+ pathnameBase: '/plain',
285
+ route: { id: '/plain' },
286
+ routeId: '/plain',
287
+ },
288
+ ],
289
+ },
290
+ }),
291
+ );
292
+
293
+ expect(payload.errors).toMatchObject({
294
+ '/plain': {
295
+ message: 'Unexpected Server Error',
296
+ stack: undefined,
297
+ __type: 'Error',
298
+ },
299
+ });
300
+ expect(JSON.stringify(payload.errors)).not.toContain('plain secret');
301
+ expect(JSON.stringify(payload.errors)).not.toContain('token secret');
302
+ });
303
+
222
304
  test('converts TanStack RSC redirects to Modern RSC navigation headers', () => {
223
305
  const response = handleTanstackRscRedirect(
224
306
  new Headers({ Location: '/base/login' }),
@@ -232,6 +314,54 @@ describe('tanstack rsc runtime helpers', () => {
232
314
  expect(response.headers.get('X-Modernjs-BaseUrl')).toBe('/base');
233
315
  });
234
316
 
317
+ test('preserves TanStack RSC redirect paths that do not start with the basename', () => {
318
+ const response = handleTanstackRscRedirect(
319
+ new Headers({ Location: '/shop/base/login' }),
320
+ '/base',
321
+ 302,
322
+ );
323
+
324
+ expect(response.headers.get('X-Modernjs-Redirect')).toBe(
325
+ '/shop/base/login',
326
+ );
327
+ });
328
+
329
+ test('preserves RSC redirect response status and headers in TanStack redirects', async () => {
330
+ rstest.stubGlobal(
331
+ 'fetch',
332
+ rstest.fn(() =>
333
+ Promise.resolve(
334
+ new Response(null, {
335
+ headers: {
336
+ 'X-Modernjs-Redirect': '/login',
337
+ 'X-Trace': 'preserved',
338
+ },
339
+ status: 308,
340
+ }),
341
+ ),
342
+ ),
343
+ );
344
+
345
+ const thrown = (await loadTanstackRscRouteData({
346
+ loadClientData: async () => ({ fallback: true }),
347
+ request: new Request('http://localhost/products'),
348
+ routeId: '/products',
349
+ }).then(
350
+ () => {
351
+ throw new Error('expected redirect');
352
+ },
353
+ err => err,
354
+ )) as Response & {
355
+ options?: { statusCode?: number; to?: string };
356
+ };
357
+
358
+ expect(thrown).toBeInstanceOf(Response);
359
+ expect(thrown.status).toBe(308);
360
+ expect(thrown.headers.get('X-Trace')).toBe('preserved');
361
+ expect(thrown.options?.statusCode).toBe(308);
362
+ expect(thrown.options?.to).toBe('/login');
363
+ });
364
+
235
365
  test('loads one RSC payload for multiple server route loaders', async () => {
236
366
  const payload = {
237
367
  type: 'render',
@@ -275,6 +405,65 @@ describe('tanstack rsc runtime helpers', () => {
275
405
  expect(decodeMock).toHaveBeenCalledTimes(1);
276
406
  });
277
407
 
408
+ test('separates RSC payload cache entries by forwarded request headers', async () => {
409
+ const payloadByUser: Record<string, unknown> = {
410
+ alice: {
411
+ type: 'render',
412
+ actionData: null,
413
+ errors: null,
414
+ loaderData: {
415
+ '/profile': { user: 'alice' },
416
+ },
417
+ location: { href: '/profile' },
418
+ routes: [{ id: '/profile', hasLoader: true }],
419
+ },
420
+ bob: {
421
+ type: 'render',
422
+ actionData: null,
423
+ errors: null,
424
+ loaderData: {
425
+ '/profile': { user: 'bob' },
426
+ },
427
+ location: { href: '/profile' },
428
+ routes: [{ id: '/profile', hasLoader: true }],
429
+ },
430
+ };
431
+ const fetchMock = rstest.fn(
432
+ (_url: string | URL | Request, init?: RequestInit) => {
433
+ const user =
434
+ init?.headers instanceof Headers ? init.headers.get('x-user') : null;
435
+ return Promise.resolve(
436
+ new Response(JSON.stringify(payloadByUser[user || ''])),
437
+ );
438
+ },
439
+ );
440
+ rstest.stubGlobal('fetch', fetchMock);
441
+ __setTanstackRscPayloadDecoderForTests(async stream =>
442
+ JSON.parse(await new Response(stream).text()),
443
+ );
444
+
445
+ const [aliceData, bobData] = await Promise.all([
446
+ loadTanstackRscRouteData({
447
+ loadClientData: async () => ({ fallback: 'alice' }),
448
+ request: new Request('http://localhost/profile', {
449
+ headers: { 'x-user': 'alice' },
450
+ }),
451
+ routeId: '/profile',
452
+ }),
453
+ loadTanstackRscRouteData({
454
+ loadClientData: async () => ({ fallback: 'bob' }),
455
+ request: new Request('http://localhost/profile', {
456
+ headers: { 'x-user': 'bob' },
457
+ }),
458
+ routeId: '/profile',
459
+ }),
460
+ ]);
461
+
462
+ expect(aliceData).toEqual({ user: 'alice' });
463
+ expect(bobData).toEqual({ user: 'bob' });
464
+ expect(fetchMock).toHaveBeenCalledTimes(2);
465
+ });
466
+
278
467
  test('uses client loader data without requesting an RSC payload for client-loader routes', async () => {
279
468
  const fetchMock = rstest.fn();
280
469
  const loadClientData = rstest.fn(async () => ({ client: true }));