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

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
@@ -0,0 +1,107 @@
1
+ // @effect-diagnostics asyncFunction:off newPromise:off strictBooleanExpressions:off
2
+ /// <reference path="./ssr-shim.d.ts" />
3
+
4
+ import type { AnyRouter } from '@tanstack/react-router';
5
+ import type {
6
+ RouterManagedTag,
7
+ RouterMatchWithError,
8
+ TanstackRouterWithServerSsr,
9
+ } from './ssrTypes';
10
+
11
+ export async function waitForRouterSerialization(
12
+ tanstackRouter: TanstackRouterWithServerSsr,
13
+ ) {
14
+ const serverSsr = tanstackRouter.serverSsr;
15
+ if (
16
+ !serverSsr ||
17
+ typeof serverSsr.onSerializationFinished !== 'function' ||
18
+ serverSsr.isSerializationFinished?.()
19
+ ) {
20
+ return;
21
+ }
22
+
23
+ await new Promise<void>(resolve => {
24
+ serverSsr.onSerializationFinished?.(resolve);
25
+ });
26
+ }
27
+
28
+ function htmlEscapeAttr(value: string) {
29
+ return value.replace(/&/g, '&amp;').replace(/"/g, '&quot;');
30
+ }
31
+
32
+ function routerManagedTagToHtml(tag: unknown): string {
33
+ if (!tag || typeof tag !== 'object') {
34
+ return '';
35
+ }
36
+
37
+ const managedTag = tag as RouterManagedTag;
38
+ if (!managedTag || managedTag.tag !== 'script') {
39
+ return '';
40
+ }
41
+
42
+ const attrs: Record<string, unknown> = managedTag.attrs || {};
43
+ const attrsStr = Object.entries(attrs)
44
+ .filter(([, v]) => v != null && v !== false)
45
+ .map(([k, v]) => {
46
+ const name = k === 'className' ? 'class' : k;
47
+ if (v === true) {
48
+ return name;
49
+ }
50
+ return `${name}="${htmlEscapeAttr(String(v))}"`;
51
+ })
52
+ .join(' ');
53
+
54
+ const open = attrsStr.length ? `<script ${attrsStr}>` : '<script>';
55
+ const children =
56
+ typeof managedTag.children === 'string' ? managedTag.children : '';
57
+ return `${open}${children}</script>`;
58
+ }
59
+
60
+ export function routerManagedTagsToHtml(tags: unknown): string[] {
61
+ const normalizedTags = Array.isArray(tags) ? tags : [tags];
62
+ return normalizedTags.map(routerManagedTagToHtml).filter(Boolean);
63
+ }
64
+
65
+ export function createGetSsrHref(request: Request): string {
66
+ const url = new URL(request.url);
67
+ return `${url.pathname}${url.search}${url.hash}`;
68
+ }
69
+
70
+ export function collectRouterErrors(
71
+ tanstackRouter: AnyRouter,
72
+ ): Record<string, unknown> | undefined {
73
+ const state = tanstackRouter.state as { matches?: unknown };
74
+ const matches = Array.isArray(state.matches)
75
+ ? (state.matches as RouterMatchWithError[])
76
+ : [];
77
+ const errors = matches.reduce((acc: Record<string, unknown>, match) => {
78
+ if (!match.error) {
79
+ return acc;
80
+ }
81
+
82
+ const routeId =
83
+ typeof match.routeId === 'string'
84
+ ? match.routeId
85
+ : typeof match.route?.id === 'string'
86
+ ? match.route.id
87
+ : `match-${Object.keys(acc).length}`;
88
+
89
+ acc[routeId] = match.error;
90
+ return acc;
91
+ }, {});
92
+
93
+ return Object.keys(errors).length > 0 ? errors : undefined;
94
+ }
95
+
96
+ export async function attachServerSsrUtils(
97
+ router: TanstackRouterWithServerSsr,
98
+ ) {
99
+ const { attachRouterServerSsrUtils } = await import(
100
+ '@tanstack/router-core/ssr/server'
101
+ );
102
+
103
+ attachRouterServerSsrUtils({
104
+ router,
105
+ manifest: undefined,
106
+ });
107
+ }
@@ -0,0 +1,125 @@
1
+ // @effect-diagnostics asyncFunction:off strictBooleanExpressions:off
2
+
3
+ import type {
4
+ RouterMatchWithError,
5
+ TanstackRouterWithServerSsr,
6
+ } from './ssrTypes';
7
+
8
+ type PreloadableRouteComponent = {
9
+ load?: (props?: Record<string, unknown>) => Promise<unknown> | unknown;
10
+ preload?: (props?: Record<string, unknown>) => Promise<unknown> | unknown;
11
+ };
12
+
13
+ type ReactLazyRouteComponent = {
14
+ _init?: (payload: unknown) => unknown;
15
+ _payload?: unknown;
16
+ };
17
+
18
+ function isPromiseLike(value: unknown): value is PromiseLike<unknown> {
19
+ return Boolean(
20
+ value && typeof (value as PromiseLike<unknown>).then === 'function',
21
+ );
22
+ }
23
+
24
+ function isPreloadableRouteComponent(
25
+ component: unknown,
26
+ ): component is PreloadableRouteComponent {
27
+ if (!component || typeof component !== 'function') {
28
+ return false;
29
+ }
30
+
31
+ const preloadable = component as PreloadableRouteComponent;
32
+ return (
33
+ typeof preloadable.load === 'function' ||
34
+ typeof preloadable.preload === 'function'
35
+ );
36
+ }
37
+
38
+ function isReactLazyRouteComponent(
39
+ component: unknown,
40
+ ): component is ReactLazyRouteComponent {
41
+ return (
42
+ component !== null &&
43
+ component !== undefined &&
44
+ typeof component === 'object' &&
45
+ typeof (component as ReactLazyRouteComponent)._init === 'function' &&
46
+ '_payload' in component
47
+ );
48
+ }
49
+
50
+ async function preloadReactLazyRouteComponent(
51
+ component: ReactLazyRouteComponent,
52
+ ) {
53
+ try {
54
+ component._init?.(component._payload);
55
+ } catch (thrown) {
56
+ if (!isPromiseLike(thrown)) {
57
+ throw thrown;
58
+ }
59
+ await thrown;
60
+ component._init?.(component._payload);
61
+ }
62
+ }
63
+
64
+ async function preloadRouteComponent(
65
+ component: unknown,
66
+ preloadedComponents: Set<unknown>,
67
+ ) {
68
+ if (isReactLazyRouteComponent(component)) {
69
+ if (preloadedComponents.has(component)) {
70
+ return;
71
+ }
72
+ preloadedComponents.add(component);
73
+ await preloadReactLazyRouteComponent(component);
74
+ return;
75
+ }
76
+
77
+ if (!isPreloadableRouteComponent(component)) {
78
+ return;
79
+ }
80
+
81
+ if (preloadedComponents.has(component)) {
82
+ return;
83
+ }
84
+ preloadedComponents.add(component);
85
+
86
+ if (typeof component.load === 'function') {
87
+ await component.load({});
88
+ return;
89
+ }
90
+
91
+ await component.preload?.({});
92
+ }
93
+
94
+ export async function preloadMatchedRouteComponents(
95
+ tanstackRouter: TanstackRouterWithServerSsr,
96
+ ) {
97
+ const matches = Array.isArray(tanstackRouter.state.matches)
98
+ ? (tanstackRouter.state.matches as RouterMatchWithError[])
99
+ : [];
100
+ const routesById = tanstackRouter.routesById || {};
101
+ const preloadedComponents = new Set<unknown>();
102
+
103
+ await Promise.all(
104
+ matches.map(async match => {
105
+ const routeId =
106
+ typeof match.routeId === 'string'
107
+ ? match.routeId
108
+ : typeof match.route?.id === 'string'
109
+ ? match.route.id
110
+ : undefined;
111
+ const route = routeId ? routesById[routeId] : match.route;
112
+ const options = route?.options;
113
+ if (!options) {
114
+ return;
115
+ }
116
+
117
+ await Promise.all([
118
+ preloadRouteComponent(options.component, preloadedComponents),
119
+ preloadRouteComponent(options.pendingComponent, preloadedComponents),
120
+ preloadRouteComponent(options.errorComponent, preloadedComponents),
121
+ preloadRouteComponent(options.notFoundComponent, preloadedComponents),
122
+ ]);
123
+ }),
124
+ );
125
+ }
@@ -0,0 +1,51 @@
1
+ /// <reference path="./ssr-shim.d.ts" />
2
+
3
+ import type { RequestContext } from '@modern-js/runtime-utils/node';
4
+ import type { AnyRouter } from '@tanstack/react-router';
5
+
6
+ export type ModernTanstackRouterContext = {
7
+ request: Request;
8
+ requestContext: RequestContext<Record<string, unknown>>;
9
+ };
10
+
11
+ export type RouterManagedTag = {
12
+ attrs?: Record<string, unknown>;
13
+ children?: unknown;
14
+ tag?: unknown;
15
+ };
16
+
17
+ export type RouterMatchWithError = {
18
+ error?: unknown;
19
+ route?: {
20
+ id?: unknown;
21
+ options?: RouterRouteOptions;
22
+ };
23
+ routeId?: unknown;
24
+ };
25
+
26
+ type RouterRouteOptions = {
27
+ component?: unknown;
28
+ errorComponent?: unknown;
29
+ notFoundComponent?: unknown;
30
+ pendingComponent?: unknown;
31
+ };
32
+
33
+ type RouterRouteWithOptions = {
34
+ options?: RouterRouteOptions;
35
+ };
36
+
37
+ export type TanstackRouterWithServerSsr = AnyRouter & {
38
+ resolveRedirect?: (redirect: Response) => Response;
39
+ routesById?: Record<string, RouterRouteWithOptions>;
40
+ serverSsr?: {
41
+ cleanup?: () => void;
42
+ dehydrate?: () => Promise<void> | void;
43
+ isSerializationFinished?: () => boolean;
44
+ onSerializationFinished?: (listener: () => void) => void;
45
+ takeBufferedScripts?: () => unknown;
46
+ };
47
+ state: AnyRouter['state'] & {
48
+ matches?: unknown;
49
+ redirect?: Response;
50
+ };
51
+ };
@@ -1,6 +1,8 @@
1
- import { getRouterRuntimeState } from '@modern-js/runtime/context';
1
+ import {
2
+ getRouterRuntimeState,
3
+ type InternalRouterRuntimeState,
4
+ } from '@modern-js/runtime/context';
2
5
  import type { AnyRouter } from '@tanstack/react-router';
3
- import type { InternalRouterRuntimeState } from './types';
4
6
 
5
7
  /**
6
8
  * Router runtime state as published by the TanStack router provider into the
@@ -21,7 +23,11 @@ export function getTanstackRouterState(
21
23
  context: object,
22
24
  ): TanstackRouterState | undefined {
23
25
  const state = getRouterRuntimeState(context);
24
- if (state === undefined || state.framework !== 'tanstack') {
26
+ if (
27
+ state === undefined ||
28
+ state.framework !== 'tanstack' ||
29
+ state.instance === undefined
30
+ ) {
25
31
  return undefined;
26
32
  }
27
33
 
@@ -0,0 +1,201 @@
1
+ // @effect-diagnostics asyncFunction:off extendsNativeError:off strictBooleanExpressions:off
2
+ import type { AnyRouter } from '@tanstack/react-router';
3
+ import type { SubmitOptions, SubmitTarget } from './formData';
4
+ import {
5
+ formDataToTextPlain,
6
+ formDataToUrlSearchParams,
7
+ toFormData,
8
+ } from './formData';
9
+
10
+ export class RouteActionResponseError<TData = unknown> extends Error {
11
+ readonly response: Response;
12
+ readonly data: TData;
13
+
14
+ constructor(response: Response, data: TData) {
15
+ super(`Route action failed with status ${response.status}`);
16
+ this.name = 'RouteActionResponseError';
17
+ this.response = response;
18
+ this.data = data;
19
+ }
20
+ }
21
+
22
+ type RouteAction = (args: {
23
+ request: Request;
24
+ params: Record<string, string>;
25
+ context?: unknown;
26
+ }) => Promise<unknown> | unknown;
27
+
28
+ type RouteLoader = (args: {
29
+ request: Request;
30
+ params: Record<string, string>;
31
+ context?: unknown;
32
+ }) => Promise<unknown> | unknown;
33
+
34
+ type RouterBuildLocationOptions = Parameters<AnyRouter['buildLocation']>[0];
35
+ type RouterBuiltLocation = ReturnType<AnyRouter['buildLocation']> & {
36
+ pathname: string;
37
+ };
38
+ type RouterParsedLocation = Parameters<AnyRouter['getParsedLocationHref']>[0];
39
+ type RouterNavigateOptions = Parameters<AnyRouter['navigate']>[0];
40
+
41
+ function resolveRouteHandlers(router: AnyRouter, actionTo: string) {
42
+ const builtLocation = router.buildLocation({
43
+ to: actionTo,
44
+ } as RouterBuildLocationOptions) as RouterBuiltLocation;
45
+ const href = router.getParsedLocationHref(
46
+ builtLocation as RouterParsedLocation,
47
+ );
48
+ const matchedRoutes = router.getMatchedRoutes(builtLocation.pathname);
49
+ const routeStaticData = matchedRoutes.foundRoute?.options?.staticData as
50
+ | Record<string, unknown>
51
+ | undefined;
52
+ const action = routeStaticData?.modernRouteAction as RouteAction | undefined;
53
+ const loader = routeStaticData?.modernRouteLoader as RouteLoader | undefined;
54
+
55
+ return {
56
+ action,
57
+ loader,
58
+ href,
59
+ params: (matchedRoutes.routeParams || {}) as Record<string, string>,
60
+ };
61
+ }
62
+
63
+ function isRedirectResponse(value: unknown): value is Response {
64
+ if (!(value instanceof Response)) {
65
+ return false;
66
+ }
67
+ return [301, 302, 303, 307, 308].includes(value.status);
68
+ }
69
+
70
+ async function parseResponseData(response: Response) {
71
+ if (response.status === 204) {
72
+ return null;
73
+ }
74
+
75
+ const contentType = response.headers.get('Content-Type') || '';
76
+ if (contentType.includes('application/json')) {
77
+ return response.json();
78
+ }
79
+ return response.text();
80
+ }
81
+
82
+ async function parseResponseResultOrThrow(response: Response) {
83
+ const parsed = await parseResponseData(response);
84
+ if (!response.ok) {
85
+ throw new RouteActionResponseError(response, parsed);
86
+ }
87
+ return parsed;
88
+ }
89
+
90
+ export async function submitRouteAction({
91
+ router,
92
+ target,
93
+ options = {},
94
+ isFetcher = false,
95
+ onInvalidateStart,
96
+ }: {
97
+ router: AnyRouter;
98
+ target: SubmitTarget;
99
+ options?: SubmitOptions;
100
+ isFetcher?: boolean;
101
+ onInvalidateStart?: () => void;
102
+ }) {
103
+ const method = (options.method || 'post').toLowerCase();
104
+ const encType = options.encType || 'application/x-www-form-urlencoded';
105
+ const actionTo = options.action || '.';
106
+ const formData = toFormData(target);
107
+ const resolved = resolveRouteHandlers(router, actionTo);
108
+
109
+ if (method === 'get') {
110
+ const search = formDataToUrlSearchParams(formData).toString();
111
+ const requestUrl = new URL(resolved.href, window.location.origin);
112
+ requestUrl.search = search;
113
+
114
+ if (isFetcher && resolved.loader) {
115
+ const result = await resolved.loader({
116
+ request: new Request(requestUrl, {
117
+ method: 'GET',
118
+ }),
119
+ params: resolved.params,
120
+ });
121
+
122
+ if (result instanceof Response) {
123
+ const redirectTo =
124
+ result.headers.get('X-Modernjs-Redirect') ||
125
+ result.headers.get('Location');
126
+ if (redirectTo || isRedirectResponse(result)) {
127
+ await router.navigate({
128
+ to: redirectTo || '/',
129
+ } as RouterNavigateOptions);
130
+ return parseResponseData(result);
131
+ }
132
+ return parseResponseResultOrThrow(result);
133
+ }
134
+
135
+ return result;
136
+ }
137
+
138
+ await router.navigate({
139
+ href: `${requestUrl.pathname}${requestUrl.search}${requestUrl.hash}`,
140
+ } as RouterNavigateOptions);
141
+ return;
142
+ }
143
+
144
+ if (!resolved.action) {
145
+ throw new Error(`No route action found for "${actionTo}"`);
146
+ }
147
+
148
+ const headers = new Headers();
149
+ let body: BodyInit | null = null;
150
+ if (encType.includes('application/json')) {
151
+ headers.set('Content-Type', 'application/json');
152
+ body = JSON.stringify(
153
+ Object.fromEntries(formDataToUrlSearchParams(formData).entries()),
154
+ );
155
+ } else if (encType.includes('text/plain')) {
156
+ headers.set('Content-Type', 'text/plain;charset=UTF-8');
157
+ body = formDataToTextPlain(formData);
158
+ } else if (encType.includes('application/x-www-form-urlencoded')) {
159
+ headers.set(
160
+ 'Content-Type',
161
+ 'application/x-www-form-urlencoded;charset=UTF-8',
162
+ );
163
+ body = formDataToUrlSearchParams(formData);
164
+ } else {
165
+ body = formData;
166
+ }
167
+
168
+ const request = new Request(new URL(resolved.href, window.location.origin), {
169
+ method: method.toUpperCase(),
170
+ headers,
171
+ body,
172
+ });
173
+
174
+ const result = await resolved.action({
175
+ request,
176
+ params: resolved.params,
177
+ });
178
+
179
+ if (result instanceof Response) {
180
+ const redirectTo =
181
+ result.headers.get('X-Modernjs-Redirect') ||
182
+ result.headers.get('Location');
183
+ if (redirectTo || isRedirectResponse(result)) {
184
+ await router.navigate({
185
+ to: redirectTo || '/',
186
+ } as RouterNavigateOptions);
187
+ return parseResponseData(result);
188
+ }
189
+
190
+ const parsed = isFetcher
191
+ ? await parseResponseResultOrThrow(result)
192
+ : await parseResponseData(result);
193
+ onInvalidateStart?.();
194
+ await router.invalidate();
195
+ return parsed;
196
+ }
197
+
198
+ onInvalidateStart?.();
199
+ await router.invalidate();
200
+ return result;
201
+ }
@@ -1,32 +1,18 @@
1
- import type {
2
- RouterFramework,
3
- // The router runtime state types are owned by @modern-js/runtime; they are
4
- // imported through the `/context` seam instead of being copied here so
5
- // upstream fixes propagate to this package automatically.
6
- } from '@modern-js/runtime/context';
1
+ import type { ModernRoute } from '@modern-js/runtime/context';
7
2
  import type { RouteObject } from '@modern-js/runtime-utils/router';
8
- import type { NestedRoute, PageRoute } from '@modern-js/types';
9
3
  import type React from 'react';
10
4
 
11
5
  export type {
12
- BuiltInRouterFramework,
13
- InternalRouterRuntimeState,
14
6
  InternalRouterServerSnapshot,
7
+ ModernRoute,
15
8
  RouterFramework,
16
- RouterRouteMatchSnapshot,
17
- RouterServerPrepareResult,
18
9
  } from '@modern-js/runtime/context';
19
10
 
20
- /**
21
- * TanStack-specific router config. Unlike the react-router provider config,
22
- * this intentionally has no `oldVersion`/`future` fields — those are
23
- * react-router-only knobs with no meaning here.
24
- */
11
+ /** TanStack-specific router config. */
25
12
  export type RouterConfig = {
26
- framework?: RouterFramework;
27
13
  routesConfig: {
28
14
  globalApp?: React.ComponentType<any>;
29
- routes?: (NestedRoute | PageRoute)[];
15
+ routes?: ModernRoute[];
30
16
  };
31
17
  serverBase?: string[];
32
18
  supportHtml5History?: boolean;