@bleedingdev/modern-js-plugin-tanstack 3.5.0-ultramodern.4 → 3.5.0-ultramodern.41

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 (260) 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 +256 -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 +117 -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 +1 -47
  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/rsc/CompositeComponent.js +18 -13
  28. package/dist/cjs/runtime/rsc/ReplayableStream.js +0 -4
  29. package/dist/cjs/runtime/rsc/RscNodeRenderer.js +5 -16
  30. package/dist/cjs/runtime/rsc/client.js +8 -25
  31. package/dist/cjs/runtime/rsc/flightSerialization.js +132 -0
  32. package/dist/cjs/runtime/rsc/payloadErrors.js +99 -0
  33. package/dist/cjs/runtime/rsc/payloadFetch.js +105 -0
  34. package/dist/cjs/runtime/rsc/payloadRouter.js +21 -142
  35. package/dist/cjs/runtime/rsc/payloadRoutes.js +94 -0
  36. package/dist/cjs/runtime/rsc/payloadStorage.js +58 -0
  37. package/dist/cjs/runtime/rsc/server.js +14 -18
  38. package/dist/cjs/runtime/rsc/shared.js +68 -0
  39. package/dist/cjs/runtime/rsc/slotUsageSanitizer.js +1 -0
  40. package/dist/cjs/runtime/rsc/treeGetter.js +72 -0
  41. package/dist/cjs/runtime/shared/isAbsoluteUrl.js +47 -0
  42. package/dist/cjs/runtime/ssrManagedTags.js +103 -0
  43. package/dist/cjs/runtime/ssrPreload.js +89 -0
  44. package/dist/cjs/runtime/ssrTypes.js +18 -0
  45. package/dist/cjs/runtime/state.js +1 -1
  46. package/dist/cjs/runtime/submitAction.js +161 -0
  47. package/dist/cjs/runtime/utils.js +49 -86
  48. package/dist/esm/cli/artifacts.mjs +103 -0
  49. package/dist/esm/cli/index.mjs +8 -82
  50. package/dist/esm/cli/tanstackTypes/canonicalRoutes.mjs +75 -0
  51. package/dist/esm/cli/tanstackTypes/shared.mjs +61 -0
  52. package/dist/esm/cli/tanstackTypes/source.mjs +208 -0
  53. package/dist/esm/cli/tanstackTypes.mjs +2 -339
  54. package/dist/esm/runtime/blockingSubscribe.mjs +19 -0
  55. package/dist/esm/runtime/clientBasepath.mjs +10 -0
  56. package/dist/esm/runtime/clientHydration.mjs +70 -0
  57. package/dist/esm/runtime/dataMutation.mjs +2 -167
  58. package/dist/esm/runtime/formData.mjs +63 -0
  59. package/dist/esm/runtime/loaderBridge.mjs +5 -9
  60. package/dist/esm/runtime/plugin.mjs +14 -118
  61. package/dist/esm/runtime/plugin.node.mjs +41 -121
  62. package/dist/esm/runtime/pluginShared.mjs +40 -0
  63. package/dist/esm/runtime/prefetchLink.mjs +18 -5
  64. package/dist/esm/runtime/register.mjs +0 -14
  65. package/dist/esm/runtime/routeTree/components.mjs +55 -0
  66. package/dist/esm/runtime/routeTree/construction.mjs +111 -0
  67. package/dist/esm/runtime/routeTree/index.mjs +2 -0
  68. package/dist/esm/runtime/routeTree/loaders.mjs +117 -0
  69. package/dist/esm/runtime/routeTree/paths.mjs +16 -0
  70. package/dist/esm/runtime/routeTree/staticData.mjs +22 -0
  71. package/dist/esm/runtime/routeTree/tanstackRoutes.mjs +13 -0
  72. package/dist/esm/runtime/routeTree/types.mjs +0 -0
  73. package/dist/esm/runtime/routeTree.mjs +1 -318
  74. package/dist/esm/runtime/rsc/CompositeComponent.mjs +18 -13
  75. package/dist/esm/runtime/rsc/ReplayableStream.mjs +1 -1
  76. package/dist/esm/runtime/rsc/RscNodeRenderer.mjs +4 -15
  77. package/dist/esm/runtime/rsc/client.mjs +6 -26
  78. package/dist/esm/runtime/rsc/flightSerialization.mjs +88 -0
  79. package/dist/esm/runtime/rsc/payloadErrors.mjs +49 -0
  80. package/dist/esm/runtime/rsc/payloadFetch.mjs +55 -0
  81. package/dist/esm/runtime/rsc/payloadRouter.mjs +12 -133
  82. package/dist/esm/runtime/rsc/payloadRoutes.mjs +50 -0
  83. package/dist/esm/runtime/rsc/payloadStorage.mjs +14 -0
  84. package/dist/esm/runtime/rsc/server.mjs +17 -21
  85. package/dist/esm/runtime/rsc/shared.mjs +21 -0
  86. package/dist/esm/runtime/rsc/slotUsageSanitizer.mjs +1 -0
  87. package/dist/esm/runtime/rsc/treeGetter.mjs +34 -0
  88. package/dist/esm/runtime/shared/isAbsoluteUrl.mjs +9 -0
  89. package/dist/esm/runtime/ssrManagedTags.mjs +53 -0
  90. package/dist/esm/runtime/ssrPreload.mjs +51 -0
  91. package/dist/esm/runtime/ssrTypes.mjs +0 -0
  92. package/dist/esm/runtime/state.mjs +1 -1
  93. package/dist/esm/runtime/submitAction.mjs +120 -0
  94. package/dist/esm/runtime/utils.mjs +47 -75
  95. package/dist/esm-node/cli/artifacts.mjs +104 -0
  96. package/dist/esm-node/cli/index.mjs +8 -82
  97. package/dist/esm-node/cli/tanstackTypes/canonicalRoutes.mjs +76 -0
  98. package/dist/esm-node/cli/tanstackTypes/shared.mjs +62 -0
  99. package/dist/esm-node/cli/tanstackTypes/source.mjs +209 -0
  100. package/dist/esm-node/cli/tanstackTypes.mjs +2 -339
  101. package/dist/esm-node/runtime/blockingSubscribe.mjs +20 -0
  102. package/dist/esm-node/runtime/clientBasepath.mjs +11 -0
  103. package/dist/esm-node/runtime/clientHydration.mjs +71 -0
  104. package/dist/esm-node/runtime/dataMutation.mjs +2 -167
  105. package/dist/esm-node/runtime/formData.mjs +64 -0
  106. package/dist/esm-node/runtime/loaderBridge.mjs +5 -9
  107. package/dist/esm-node/runtime/plugin.mjs +14 -118
  108. package/dist/esm-node/runtime/plugin.node.mjs +41 -121
  109. package/dist/esm-node/runtime/pluginShared.mjs +41 -0
  110. package/dist/esm-node/runtime/prefetchLink.mjs +18 -5
  111. package/dist/esm-node/runtime/register.mjs +0 -14
  112. package/dist/esm-node/runtime/routeTree/components.mjs +56 -0
  113. package/dist/esm-node/runtime/routeTree/construction.mjs +112 -0
  114. package/dist/esm-node/runtime/routeTree/index.mjs +3 -0
  115. package/dist/esm-node/runtime/routeTree/loaders.mjs +118 -0
  116. package/dist/esm-node/runtime/routeTree/paths.mjs +17 -0
  117. package/dist/esm-node/runtime/routeTree/staticData.mjs +23 -0
  118. package/dist/esm-node/runtime/routeTree/tanstackRoutes.mjs +14 -0
  119. package/dist/esm-node/runtime/routeTree/types.mjs +1 -0
  120. package/dist/esm-node/runtime/routeTree.mjs +1 -318
  121. package/dist/esm-node/runtime/rsc/CompositeComponent.mjs +18 -13
  122. package/dist/esm-node/runtime/rsc/ReplayableStream.mjs +1 -1
  123. package/dist/esm-node/runtime/rsc/RscNodeRenderer.mjs +4 -15
  124. package/dist/esm-node/runtime/rsc/client.mjs +6 -26
  125. package/dist/esm-node/runtime/rsc/flightSerialization.mjs +89 -0
  126. package/dist/esm-node/runtime/rsc/payloadErrors.mjs +50 -0
  127. package/dist/esm-node/runtime/rsc/payloadFetch.mjs +56 -0
  128. package/dist/esm-node/runtime/rsc/payloadRouter.mjs +12 -133
  129. package/dist/esm-node/runtime/rsc/payloadRoutes.mjs +51 -0
  130. package/dist/esm-node/runtime/rsc/payloadStorage.mjs +15 -0
  131. package/dist/esm-node/runtime/rsc/server.mjs +17 -21
  132. package/dist/esm-node/runtime/rsc/shared.mjs +22 -0
  133. package/dist/esm-node/runtime/rsc/slotUsageSanitizer.mjs +1 -0
  134. package/dist/esm-node/runtime/rsc/treeGetter.mjs +35 -0
  135. package/dist/esm-node/runtime/shared/isAbsoluteUrl.mjs +10 -0
  136. package/dist/esm-node/runtime/ssrManagedTags.mjs +54 -0
  137. package/dist/esm-node/runtime/ssrPreload.mjs +52 -0
  138. package/dist/esm-node/runtime/ssrTypes.mjs +1 -0
  139. package/dist/esm-node/runtime/state.mjs +1 -1
  140. package/dist/esm-node/runtime/submitAction.mjs +121 -0
  141. package/dist/esm-node/runtime/utils.mjs +47 -75
  142. package/dist/types/cli/artifacts.d.ts +33 -0
  143. package/dist/types/cli/index.d.ts +2 -22
  144. package/dist/types/cli/tanstackTypes/canonicalRoutes.d.ts +22 -0
  145. package/dist/types/cli/tanstackTypes/shared.d.ts +20 -0
  146. package/dist/types/cli/tanstackTypes/source.d.ts +12 -0
  147. package/dist/types/cli/tanstackTypes.d.ts +3 -31
  148. package/dist/types/runtime/blockingSubscribe.d.ts +1 -0
  149. package/dist/types/runtime/clientBasepath.d.ts +1 -0
  150. package/dist/types/runtime/clientHydration.d.ts +10 -0
  151. package/dist/types/runtime/dataMutation.d.ts +3 -12
  152. package/dist/types/runtime/formData.d.ts +24 -0
  153. package/dist/types/runtime/loaderBridge.d.ts +2 -1
  154. package/dist/types/runtime/plugin.d.ts +1 -1
  155. package/dist/types/runtime/plugin.node.d.ts +1 -1
  156. package/dist/types/runtime/pluginShared.d.ts +38 -0
  157. package/dist/types/runtime/register.d.ts +1 -9
  158. package/dist/types/runtime/routeTree/components.d.ts +7 -0
  159. package/dist/types/runtime/routeTree/construction.d.ts +5 -0
  160. package/dist/types/runtime/routeTree/index.d.ts +2 -0
  161. package/dist/types/runtime/routeTree/loaders.d.ts +4 -0
  162. package/dist/types/runtime/routeTree/paths.d.ts +3 -0
  163. package/dist/types/runtime/routeTree/staticData.d.ts +19 -0
  164. package/dist/types/runtime/routeTree/tanstackRoutes.d.ts +4 -0
  165. package/dist/types/runtime/routeTree/types.d.ts +76 -0
  166. package/dist/types/runtime/routeTree.d.ts +1 -9
  167. package/dist/types/runtime/rsc/CompositeComponent.d.ts +1 -2
  168. package/dist/types/runtime/rsc/ReplayableStream.d.ts +3 -2
  169. package/dist/types/runtime/rsc/RscNodeRenderer.d.ts +2 -3
  170. package/dist/types/runtime/rsc/SlotContext.d.ts +2 -1
  171. package/dist/types/runtime/rsc/client.d.ts +2 -0
  172. package/dist/types/runtime/rsc/flightSerialization.d.ts +3 -0
  173. package/dist/types/runtime/rsc/payloadErrors.d.ts +6 -0
  174. package/dist/types/runtime/rsc/payloadFetch.d.ts +8 -0
  175. package/dist/types/runtime/rsc/payloadRouter.d.ts +2 -10
  176. package/dist/types/runtime/rsc/payloadRoutes.d.ts +40 -0
  177. package/dist/types/runtime/rsc/payloadStorage.d.ts +5 -0
  178. package/dist/types/runtime/rsc/shared.d.ts +18 -0
  179. package/dist/types/runtime/rsc/treeGetter.d.ts +1 -0
  180. package/dist/types/runtime/shared/isAbsoluteUrl.d.ts +1 -0
  181. package/dist/types/runtime/ssrManagedTags.d.ts +7 -0
  182. package/dist/types/runtime/ssrPreload.d.ts +2 -0
  183. package/dist/types/runtime/ssrTypes.d.ts +44 -0
  184. package/dist/types/runtime/state.d.ts +1 -1
  185. package/dist/types/runtime/submitAction.d.ts +14 -0
  186. package/dist/types/runtime/types.d.ts +4 -10
  187. package/dist/types/runtime/utils.d.ts +4 -24
  188. package/package.json +35 -14
  189. package/rstest.config.mts +6 -0
  190. package/src/cli/artifacts.ts +255 -0
  191. package/src/cli/index.ts +7 -185
  192. package/src/cli/tanstackTypes/canonicalRoutes.ts +157 -0
  193. package/src/cli/tanstackTypes/shared.ts +113 -0
  194. package/src/cli/tanstackTypes/source.ts +415 -0
  195. package/src/cli/tanstackTypes.ts +4 -647
  196. package/src/runtime/blockingSubscribe.ts +48 -0
  197. package/src/runtime/clientBasepath.ts +12 -0
  198. package/src/runtime/clientHydration.ts +146 -0
  199. package/src/runtime/dataMutation.tsx +9 -306
  200. package/src/runtime/formData.ts +153 -0
  201. package/src/runtime/loaderBridge.ts +11 -12
  202. package/src/runtime/plugin.node.tsx +76 -291
  203. package/src/runtime/plugin.tsx +21 -257
  204. package/src/runtime/pluginShared.ts +112 -0
  205. package/src/runtime/prefetchLink.tsx +78 -15
  206. package/src/runtime/register.ts +5 -37
  207. package/src/runtime/routeTree/components.ts +130 -0
  208. package/src/runtime/routeTree/construction.ts +238 -0
  209. package/src/runtime/routeTree/index.ts +7 -0
  210. package/src/runtime/routeTree/loaders.ts +232 -0
  211. package/src/runtime/routeTree/paths.ts +36 -0
  212. package/src/runtime/routeTree/staticData.ts +66 -0
  213. package/src/runtime/routeTree/tanstackRoutes.ts +36 -0
  214. package/src/runtime/routeTree/types.ts +87 -0
  215. package/src/runtime/routeTree.ts +5 -750
  216. package/src/runtime/rsc/CompositeComponent.tsx +29 -20
  217. package/src/runtime/rsc/ReplayableStream.ts +2 -2
  218. package/src/runtime/rsc/RscNodeRenderer.tsx +9 -27
  219. package/src/runtime/rsc/SlotContext.tsx +1 -1
  220. package/src/runtime/rsc/client.tsx +12 -40
  221. package/src/runtime/rsc/flightSerialization.ts +158 -0
  222. package/src/runtime/rsc/payloadErrors.ts +73 -0
  223. package/src/runtime/rsc/payloadFetch.ts +92 -0
  224. package/src/runtime/rsc/payloadRouter.ts +29 -234
  225. package/src/runtime/rsc/payloadRoutes.ts +122 -0
  226. package/src/runtime/rsc/payloadStorage.ts +35 -0
  227. package/src/runtime/rsc/server.tsx +20 -29
  228. package/src/runtime/rsc/shared.ts +70 -0
  229. package/src/runtime/rsc/slotUsageSanitizer.ts +4 -0
  230. package/src/runtime/rsc/treeGetter.tsx +52 -0
  231. package/src/runtime/shared/isAbsoluteUrl.ts +8 -0
  232. package/src/runtime/ssrManagedTags.ts +107 -0
  233. package/src/runtime/ssrPreload.ts +125 -0
  234. package/src/runtime/ssrTypes.ts +51 -0
  235. package/src/runtime/state.ts +9 -3
  236. package/src/runtime/submitAction.ts +201 -0
  237. package/src/runtime/types.ts +4 -18
  238. package/src/runtime/utils.tsx +76 -110
  239. package/src/types/react-server-dom-rspack.d.ts +56 -0
  240. package/tests/castRatchet.test.ts +85 -0
  241. package/tests/router/cli.test.ts +7 -0
  242. package/tests/router/dataMutation.test.tsx +59 -0
  243. package/tests/router/fixtures/router-gen.golden.txt +72 -0
  244. package/tests/router/flightSerialization.roundtrip.test.tsx +137 -0
  245. package/tests/router/generateRouteArtifacts.test.ts +106 -0
  246. package/tests/router/hooks.test.ts +14 -0
  247. package/tests/router/loaderBridge.test.ts +21 -0
  248. package/tests/router/prefetchLink.test.tsx +106 -59
  249. package/tests/router/prefetchLinkPreload.test.tsx +85 -0
  250. package/tests/router/register.test.ts +1 -39
  251. package/tests/router/routeTree.test.ts +51 -11
  252. package/tests/router/rsc.test.tsx +189 -0
  253. package/tests/router/rscPayloadRouterMatrix.test.ts +197 -0
  254. package/tests/router/slotUsageSanitizer.test.ts +23 -0
  255. package/tests/router/ssrPreload.test.ts +30 -0
  256. package/tests/router/tanstackTypes.test.ts +254 -1
  257. package/dist/esm/runtime/pluginCore.mjs +0 -14
  258. package/dist/esm-node/runtime/pluginCore.mjs +0 -15
  259. package/dist/types/runtime/pluginCore.d.ts +0 -21
  260. package/src/runtime/pluginCore.ts +0 -48
@@ -1,19 +1,163 @@
1
1
  import { execFile } from 'node:child_process';
2
- import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
2
+ import { mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
3
3
  import { tmpdir } from 'node:os';
4
4
  import path from 'node:path';
5
5
  import { promisify } from 'node:util';
6
+ import { isRedirect } from '@tanstack/react-router';
7
+
8
+ const resolverDelays = new Map<string, number>();
9
+
10
+ rstest.mock('../../src/cli/tanstackTypes/shared', () => {
11
+ const actual = rstest.requireActual(
12
+ '../../src/cli/tanstackTypes/shared',
13
+ ) as typeof import('../../src/cli/tanstackTypes/shared');
14
+
15
+ return {
16
+ ...actual,
17
+ resolveFileNoExt: async (inputNoExtPath: string) => {
18
+ const normalized = inputNoExtPath.replaceAll('\\', '/');
19
+ const delay =
20
+ [...resolverDelays.entries()].find(([suffix]) =>
21
+ normalized.endsWith(suffix),
22
+ )?.[1] ?? 0;
23
+
24
+ if (delay > 0) {
25
+ await new Promise(resolve => setTimeout(resolve, delay));
26
+ }
27
+
28
+ return actual.resolveFileNoExt(inputNoExtPath);
29
+ },
30
+ };
31
+ });
32
+
6
33
  import {
7
34
  collectCanonicalRoutesForEntry,
8
35
  generateTanstackRouterTypesSourceForEntry,
9
36
  } from '../../src/cli/tanstackTypes';
37
+ import { throwTanstackRedirect } from '../../src/runtime/loaderBridge';
10
38
 
11
39
  const execFileAsync = promisify(execFile);
40
+ const routerGenGoldenPath = path.join(
41
+ __dirname,
42
+ 'fixtures',
43
+ 'router-gen.golden.txt',
44
+ );
45
+
46
+ type RedirectLike = {
47
+ options?: {
48
+ href?: string;
49
+ to?: string;
50
+ };
51
+ };
52
+
53
+ function catchThrown(fn: () => unknown): unknown {
54
+ try {
55
+ fn();
56
+ } catch (err) {
57
+ return err;
58
+ }
59
+ throw new Error('expected function to throw');
60
+ }
61
+
62
+ function extractRouteGenerationOrder(source: string) {
63
+ return source.split('\n').filter(line => {
64
+ return (
65
+ line.startsWith('import component_') ||
66
+ line.startsWith('const route_') ||
67
+ line.includes('component: component_') ||
68
+ line.startsWith('export const routeTree')
69
+ );
70
+ });
71
+ }
72
+
73
+ async function writeGoldenRouterFixture(srcDirectory: string) {
74
+ const files = new Map([
75
+ [
76
+ 'routes/(app)/layout.tsx',
77
+ 'export default function AppLayout() { return null; }',
78
+ ],
79
+ [
80
+ 'routes/(app)/users/(userId)/page.tsx',
81
+ 'export default function UserPage() { return null; }',
82
+ ],
83
+ [
84
+ 'routes/(app)/users/(userId)/page.data.ts',
85
+ [
86
+ 'export const loader = () => ({ userId: "42" });',
87
+ 'export const action = () => Response.json({ ok: true });',
88
+ ].join('\n'),
89
+ ],
90
+ [
91
+ 'routes/(app)/docs/splat.tsx',
92
+ 'export default function DocsSplatPage() { return null; }',
93
+ ],
94
+ [
95
+ 'routes/search.contract.ts',
96
+ [
97
+ 'export const validateSearch = (search: { tab?: string }) => ({ tab: search.tab ?? "overview" });',
98
+ 'export const loaderDeps = ({ search }: { search: { tab: string } }) => ({ tab: search.tab });',
99
+ ].join('\n'),
100
+ ],
101
+ ]);
102
+
103
+ for (const [relativePath, contents] of files) {
104
+ const filePath = path.join(srcDirectory, relativePath);
105
+ await mkdir(path.dirname(filePath), { recursive: true });
106
+ await writeFile(filePath, contents);
107
+ }
108
+ }
109
+
110
+ async function generateGoldenRouterGen(srcDirectory: string) {
111
+ await writeGoldenRouterFixture(srcDirectory);
112
+
113
+ const { routerGenTs } = await generateTanstackRouterTypesSourceForEntry({
114
+ appContext: {
115
+ srcDirectory,
116
+ internalSrcAlias: '@/_',
117
+ } as any,
118
+ entryName: 'golden',
119
+ routes: [
120
+ {
121
+ type: 'nested',
122
+ id: 'layout',
123
+ isRoot: true,
124
+ children: [
125
+ {
126
+ type: 'nested',
127
+ id: '(app)/layout',
128
+ _component: '@/_/routes/(app)/layout',
129
+ children: [
130
+ {
131
+ type: 'nested',
132
+ id: '(app)/users/(userId)/page',
133
+ path: 'users/:userId',
134
+ _component: '@/_/routes/(app)/users/(userId)/page',
135
+ data: '@/_/routes/(app)/users/(userId)/page.data',
136
+ action: '@/_/routes/(app)/users/(userId)/page.data',
137
+ validateSearch: '@/_/routes/search.contract',
138
+ loaderDeps: '@/_/routes/search.contract',
139
+ },
140
+ {
141
+ type: 'nested',
142
+ id: '(app)/docs/splat/page',
143
+ path: 'docs/*',
144
+ _component: '@/_/routes/(app)/docs/splat',
145
+ },
146
+ ],
147
+ },
148
+ ],
149
+ },
150
+ ] as any,
151
+ });
152
+
153
+ return routerGenTs;
154
+ }
12
155
 
13
156
  describe('tanstack router type generation', () => {
14
157
  let tempDir: string | undefined;
15
158
 
16
159
  afterEach(async () => {
160
+ resolverDelays.clear();
17
161
  if (tempDir) {
18
162
  await rm(tempDir, { recursive: true, force: true });
19
163
  tempDir = undefined;
@@ -77,6 +221,15 @@ describe('tanstack router type generation', () => {
77
221
  expect(routerGenTs).not.toContain('function modernLoaderToTanstack');
78
222
  expect(routerGenTs).not.toContain('function createRouteStaticData');
79
223
  expect(routerGenTs).not.toContain('function throwTanstackRedirect');
224
+ expect(routerGenTs).not.toContain('new URL(target)');
225
+ expect(routerGenTs).not.toContain('redirect({ to: target })');
226
+
227
+ const redirectError = catchThrown(() =>
228
+ throwTanstackRedirect('https://example.com/absolute'),
229
+ ) as RedirectLike;
230
+ expect(isRedirect(redirectError)).toBe(true);
231
+ expect(redirectError.options?.href).toBe('https://example.com/absolute');
232
+ expect(redirectError.options?.to).toBeUndefined();
80
233
  });
81
234
 
82
235
  test('emits resolvable relative component imports for routes carrying _component', async () => {
@@ -167,6 +320,106 @@ describe('tanstack router type generation', () => {
167
320
  expect(dataOnlyRoute).not.toContain('component:');
168
321
  });
169
322
 
323
+ test('keeps generated source stable when route module resolution races', async () => {
324
+ tempDir = await mkdtemp(path.join(tmpdir(), 'modern-tanstack-types-'));
325
+ const srcDirectory = path.join(tempDir, 'src');
326
+
327
+ for (const componentFile of [
328
+ 'routes/slow-page.tsx',
329
+ 'routes/fast-page.tsx',
330
+ 'routes/shared-page.tsx',
331
+ ]) {
332
+ const componentPath = path.join(srcDirectory, componentFile);
333
+ await mkdir(path.dirname(componentPath), { recursive: true });
334
+ await writeFile(
335
+ componentPath,
336
+ 'export default function Page() { return null; }',
337
+ );
338
+ }
339
+
340
+ const routes = [
341
+ {
342
+ type: 'nested',
343
+ id: 'layout',
344
+ isRoot: true,
345
+ children: [
346
+ {
347
+ type: 'nested',
348
+ id: 'slow/page',
349
+ path: 'slow',
350
+ _component: '@/_/routes/slow-page',
351
+ },
352
+ {
353
+ type: 'nested',
354
+ id: 'fast/page',
355
+ path: 'fast',
356
+ _component: '@/_/routes/fast-page',
357
+ },
358
+ {
359
+ type: 'nested',
360
+ id: 'shared-a/page',
361
+ path: 'shared-a',
362
+ _component: '@/_/routes/shared-page',
363
+ },
364
+ {
365
+ type: 'nested',
366
+ id: 'shared-b/page',
367
+ path: 'shared-b',
368
+ _component: '@/_/routes/shared-page',
369
+ },
370
+ ],
371
+ },
372
+ ] as any;
373
+
374
+ const generateWithResolverDelays = async (
375
+ delays: Record<string, number>,
376
+ ) => {
377
+ resolverDelays.clear();
378
+ for (const [suffix, delay] of Object.entries(delays)) {
379
+ resolverDelays.set(suffix, delay);
380
+ }
381
+
382
+ const { routerGenTs } = await generateTanstackRouterTypesSourceForEntry({
383
+ appContext: {
384
+ srcDirectory,
385
+ internalSrcAlias: '@/_',
386
+ } as any,
387
+ entryName: 'index',
388
+ routes,
389
+ });
390
+
391
+ return routerGenTs;
392
+ };
393
+
394
+ const sequentialOutput = await generateWithResolverDelays({});
395
+ const racedOutput = await generateWithResolverDelays({
396
+ '/routes/slow-page': 25,
397
+ });
398
+
399
+ expect(
400
+ racedOutput.match(/from "\.\.\/\.\.\/routes\/shared-page";/g),
401
+ ).toHaveLength(1);
402
+ expect(extractRouteGenerationOrder(racedOutput)).toEqual(
403
+ extractRouteGenerationOrder(sequentialOutput),
404
+ );
405
+ expect(racedOutput).toBe(sequentialOutput);
406
+ });
407
+
408
+ test('matches checked-in router.gen golden output', async () => {
409
+ tempDir = await mkdtemp(path.join(tmpdir(), 'modern-tanstack-types-'));
410
+ const srcDirectory = path.join(tempDir, 'src');
411
+ const routerGenTs = await generateGoldenRouterGen(srcDirectory);
412
+
413
+ if (process.env.UPDATE_TANSTACK_ROUTER_GOLDEN === '1') {
414
+ await mkdir(path.dirname(routerGenGoldenPath), { recursive: true });
415
+ await writeFile(routerGenGoldenPath, routerGenTs);
416
+ }
417
+
418
+ await expect(readFile(routerGenGoldenPath, 'utf8')).resolves.toBe(
419
+ routerGenTs,
420
+ );
421
+ });
422
+
170
423
  test('typechecks generated TanStack search contracts', async () => {
171
424
  tempDir = await mkdtemp(path.join(tmpdir(), 'modern-tanstack-types-'));
172
425
  const srcDirectory = path.join(tempDir, 'src');
@@ -1,14 +0,0 @@
1
- import { getGlobalLayoutApp, getGlobalRoutes } from "@modern-js/runtime/context";
2
- import { merge } from "@modern-js/runtime-utils/merge";
3
- function getMergedRouterConfig(api, userConfig) {
4
- const pluginConfig = api.getRuntimeConfig();
5
- return merge(pluginConfig.router || {}, userConfig);
6
- }
7
- function getFinalRouteConfig(mergedConfig) {
8
- return {
9
- routes: getGlobalRoutes(),
10
- globalApp: getGlobalLayoutApp(),
11
- ...mergedConfig.routesConfig
12
- };
13
- }
14
- export { getFinalRouteConfig, getMergedRouterConfig };
@@ -1,15 +0,0 @@
1
- import "node:module";
2
- import { getGlobalLayoutApp, getGlobalRoutes } from "@modern-js/runtime/context";
3
- import { merge } from "@modern-js/runtime-utils/merge";
4
- function getMergedRouterConfig(api, userConfig) {
5
- const pluginConfig = api.getRuntimeConfig();
6
- return merge(pluginConfig.router || {}, userConfig);
7
- }
8
- function getFinalRouteConfig(mergedConfig) {
9
- return {
10
- routes: getGlobalRoutes(),
11
- globalApp: getGlobalLayoutApp(),
12
- ...mergedConfig.routesConfig
13
- };
14
- }
15
- export { getFinalRouteConfig, getMergedRouterConfig };
@@ -1,21 +0,0 @@
1
- import type { Plugin, RuntimePluginExtends } from '@modern-js/plugin';
2
- import type { RuntimePluginAPI } from '@modern-js/plugin/runtime';
3
- import { type TInternalRuntimeContext } from '@modern-js/runtime/context';
4
- import type { RouterExtendsHooks } from './hooks';
5
- import type { RouterConfig } from './types';
6
- export type TanstackRouterRuntimeConfig = {
7
- plugins?: TanstackRouterRuntimePlugin[];
8
- router?: Partial<RouterConfig>;
9
- [key: string]: unknown;
10
- };
11
- type TanstackRouterRuntimeExtends = Required<RuntimePluginExtends<TanstackRouterRuntimeConfig, TInternalRuntimeContext>> & {
12
- extendHooks: RouterExtendsHooks;
13
- };
14
- export type TanstackRouterPluginAPI = RuntimePluginAPI<TanstackRouterRuntimeExtends>;
15
- export type TanstackRouterRuntimePlugin = Plugin<TanstackRouterPluginAPI, TInternalRuntimeContext>;
16
- export declare function getMergedRouterConfig(api: TanstackRouterPluginAPI, userConfig: Partial<RouterConfig>): RouterConfig;
17
- export declare function getFinalRouteConfig(mergedConfig: RouterConfig): {
18
- routes: (import("@modern-js/types").NestedRoute<string | (() => JSX.Element)> | import("@modern-js/types").PageRoute)[] | undefined;
19
- globalApp: import("react").ComponentClass<{}, any> | import("react").FunctionComponent<{}> | undefined;
20
- };
21
- export {};
@@ -1,48 +0,0 @@
1
- import type { Plugin, RuntimePluginExtends } from '@modern-js/plugin';
2
- import type { RuntimePluginAPI } from '@modern-js/plugin/runtime';
3
- import {
4
- getGlobalLayoutApp,
5
- getGlobalRoutes,
6
- type TInternalRuntimeContext,
7
- } from '@modern-js/runtime/context';
8
- import { merge } from '@modern-js/runtime-utils/merge';
9
- import type { RouterExtendsHooks } from './hooks';
10
- import type { RouterConfig } from './types';
11
-
12
- export type TanstackRouterRuntimeConfig = {
13
- plugins?: TanstackRouterRuntimePlugin[];
14
- router?: Partial<RouterConfig>;
15
- [key: string]: unknown;
16
- };
17
-
18
- type TanstackRouterRuntimeExtends = Required<
19
- RuntimePluginExtends<TanstackRouterRuntimeConfig, TInternalRuntimeContext>
20
- > & {
21
- extendHooks: RouterExtendsHooks;
22
- };
23
-
24
- export type TanstackRouterPluginAPI =
25
- RuntimePluginAPI<TanstackRouterRuntimeExtends>;
26
-
27
- export type TanstackRouterRuntimePlugin = Plugin<
28
- TanstackRouterPluginAPI,
29
- TInternalRuntimeContext
30
- >;
31
-
32
- export function getMergedRouterConfig(
33
- api: TanstackRouterPluginAPI,
34
- userConfig: Partial<RouterConfig>,
35
- ): RouterConfig {
36
- const pluginConfig = api.getRuntimeConfig() as {
37
- router?: Partial<RouterConfig>;
38
- };
39
- return merge(pluginConfig.router || {}, userConfig) as RouterConfig;
40
- }
41
-
42
- export function getFinalRouteConfig(mergedConfig: RouterConfig) {
43
- return {
44
- routes: getGlobalRoutes(),
45
- globalApp: getGlobalLayoutApp(),
46
- ...mergedConfig.routesConfig,
47
- };
48
- }