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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (221) hide show
  1. package/dist/cjs/cli/artifacts.js +157 -0
  2. package/dist/cjs/cli/index.js +6 -103
  3. package/dist/cjs/cli/tanstackTypes/canonicalRoutes.js +113 -0
  4. package/dist/cjs/cli/tanstackTypes/shared.js +130 -0
  5. package/dist/cjs/cli/tanstackTypes/source.js +251 -0
  6. package/dist/cjs/cli/tanstackTypes.js +4 -350
  7. package/dist/cjs/runtime/blockingSubscribe.js +64 -0
  8. package/dist/cjs/runtime/{pluginCore.js → clientBasepath.js} +12 -19
  9. package/dist/cjs/runtime/clientHydration.js +129 -0
  10. package/dist/cjs/runtime/dataMutation.js +11 -176
  11. package/dist/cjs/runtime/formData.js +116 -0
  12. package/dist/cjs/runtime/loaderBridge.js +4 -1
  13. package/dist/cjs/runtime/plugin.js +21 -125
  14. package/dist/cjs/runtime/plugin.node.js +38 -119
  15. package/dist/cjs/runtime/pluginShared.js +90 -0
  16. package/dist/cjs/runtime/routeTree/components.js +102 -0
  17. package/dist/cjs/runtime/routeTree/construction.js +152 -0
  18. package/dist/cjs/runtime/routeTree/index.js +47 -0
  19. package/dist/cjs/runtime/routeTree/loaders.js +158 -0
  20. package/dist/cjs/runtime/routeTree/paths.js +57 -0
  21. package/dist/cjs/runtime/routeTree/staticData.js +63 -0
  22. package/dist/cjs/runtime/routeTree/tanstackRoutes.js +57 -0
  23. package/dist/cjs/runtime/routeTree/types.js +18 -0
  24. package/dist/cjs/runtime/routeTree.js +7 -320
  25. package/dist/cjs/runtime/rsc/CompositeComponent.js +18 -13
  26. package/dist/cjs/runtime/rsc/RscNodeRenderer.js +5 -16
  27. package/dist/cjs/runtime/rsc/client.js +8 -25
  28. package/dist/cjs/runtime/rsc/flightSerialization.js +132 -0
  29. package/dist/cjs/runtime/rsc/payloadErrors.js +99 -0
  30. package/dist/cjs/runtime/rsc/payloadFetch.js +117 -0
  31. package/dist/cjs/runtime/rsc/payloadRouter.js +21 -142
  32. package/dist/cjs/runtime/rsc/payloadRoutes.js +106 -0
  33. package/dist/cjs/runtime/rsc/payloadStorage.js +58 -0
  34. package/dist/cjs/runtime/rsc/server.js +14 -18
  35. package/dist/cjs/runtime/rsc/shared.js +71 -0
  36. package/dist/cjs/runtime/rsc/treeGetter.js +72 -0
  37. package/dist/cjs/runtime/ssrManagedTags.js +103 -0
  38. package/dist/cjs/runtime/ssrPreload.js +89 -0
  39. package/dist/cjs/runtime/ssrTypes.js +18 -0
  40. package/dist/cjs/runtime/submitAction.js +161 -0
  41. package/dist/cjs/runtime/utils.js +49 -86
  42. package/dist/esm/cli/artifacts.mjs +103 -0
  43. package/dist/esm/cli/index.mjs +4 -101
  44. package/dist/esm/cli/tanstackTypes/canonicalRoutes.mjs +75 -0
  45. package/dist/esm/cli/tanstackTypes/shared.mjs +68 -0
  46. package/dist/esm/cli/tanstackTypes/source.mjs +203 -0
  47. package/dist/esm/cli/tanstackTypes.mjs +2 -339
  48. package/dist/esm/runtime/blockingSubscribe.mjs +19 -0
  49. package/dist/esm/runtime/clientBasepath.mjs +10 -0
  50. package/dist/esm/runtime/clientHydration.mjs +70 -0
  51. package/dist/esm/runtime/dataMutation.mjs +2 -167
  52. package/dist/esm/runtime/formData.mjs +63 -0
  53. package/dist/esm/runtime/loaderBridge.mjs +4 -1
  54. package/dist/esm/runtime/plugin.mjs +14 -118
  55. package/dist/esm/runtime/plugin.node.mjs +33 -114
  56. package/dist/esm/runtime/pluginShared.mjs +40 -0
  57. package/dist/esm/runtime/routeTree/components.mjs +55 -0
  58. package/dist/esm/runtime/routeTree/construction.mjs +111 -0
  59. package/dist/esm/runtime/routeTree/index.mjs +2 -0
  60. package/dist/esm/runtime/routeTree/loaders.mjs +117 -0
  61. package/dist/esm/runtime/routeTree/paths.mjs +16 -0
  62. package/dist/esm/runtime/routeTree/staticData.mjs +22 -0
  63. package/dist/esm/runtime/routeTree/tanstackRoutes.mjs +13 -0
  64. package/dist/esm/runtime/routeTree/types.mjs +0 -0
  65. package/dist/esm/runtime/routeTree.mjs +1 -318
  66. package/dist/esm/runtime/rsc/CompositeComponent.mjs +18 -13
  67. package/dist/esm/runtime/rsc/RscNodeRenderer.mjs +4 -15
  68. package/dist/esm/runtime/rsc/client.mjs +6 -26
  69. package/dist/esm/runtime/rsc/flightSerialization.mjs +88 -0
  70. package/dist/esm/runtime/rsc/payloadErrors.mjs +49 -0
  71. package/dist/esm/runtime/rsc/payloadFetch.mjs +61 -0
  72. package/dist/esm/runtime/rsc/payloadRouter.mjs +12 -133
  73. package/dist/esm/runtime/rsc/payloadRoutes.mjs +50 -0
  74. package/dist/esm/runtime/rsc/payloadStorage.mjs +14 -0
  75. package/dist/esm/runtime/rsc/server.mjs +17 -21
  76. package/dist/esm/runtime/rsc/shared.mjs +21 -0
  77. package/dist/esm/runtime/rsc/treeGetter.mjs +34 -0
  78. package/dist/esm/runtime/ssrManagedTags.mjs +53 -0
  79. package/dist/esm/runtime/ssrPreload.mjs +51 -0
  80. package/dist/esm/runtime/ssrTypes.mjs +0 -0
  81. package/dist/esm/runtime/submitAction.mjs +120 -0
  82. package/dist/esm/runtime/utils.mjs +47 -75
  83. package/dist/esm-node/cli/artifacts.mjs +104 -0
  84. package/dist/esm-node/cli/index.mjs +4 -101
  85. package/dist/esm-node/cli/tanstackTypes/canonicalRoutes.mjs +76 -0
  86. package/dist/esm-node/cli/tanstackTypes/shared.mjs +69 -0
  87. package/dist/esm-node/cli/tanstackTypes/source.mjs +204 -0
  88. package/dist/esm-node/cli/tanstackTypes.mjs +2 -339
  89. package/dist/esm-node/runtime/blockingSubscribe.mjs +20 -0
  90. package/dist/esm-node/runtime/clientBasepath.mjs +11 -0
  91. package/dist/esm-node/runtime/clientHydration.mjs +71 -0
  92. package/dist/esm-node/runtime/dataMutation.mjs +2 -167
  93. package/dist/esm-node/runtime/formData.mjs +64 -0
  94. package/dist/esm-node/runtime/loaderBridge.mjs +4 -1
  95. package/dist/esm-node/runtime/plugin.mjs +14 -118
  96. package/dist/esm-node/runtime/plugin.node.mjs +33 -114
  97. package/dist/esm-node/runtime/pluginShared.mjs +41 -0
  98. package/dist/esm-node/runtime/routeTree/components.mjs +56 -0
  99. package/dist/esm-node/runtime/routeTree/construction.mjs +112 -0
  100. package/dist/esm-node/runtime/routeTree/index.mjs +3 -0
  101. package/dist/esm-node/runtime/routeTree/loaders.mjs +118 -0
  102. package/dist/esm-node/runtime/routeTree/paths.mjs +17 -0
  103. package/dist/esm-node/runtime/routeTree/staticData.mjs +23 -0
  104. package/dist/esm-node/runtime/routeTree/tanstackRoutes.mjs +14 -0
  105. package/dist/esm-node/runtime/routeTree/types.mjs +1 -0
  106. package/dist/esm-node/runtime/routeTree.mjs +1 -318
  107. package/dist/esm-node/runtime/rsc/CompositeComponent.mjs +18 -13
  108. package/dist/esm-node/runtime/rsc/RscNodeRenderer.mjs +4 -15
  109. package/dist/esm-node/runtime/rsc/client.mjs +6 -26
  110. package/dist/esm-node/runtime/rsc/flightSerialization.mjs +89 -0
  111. package/dist/esm-node/runtime/rsc/payloadErrors.mjs +50 -0
  112. package/dist/esm-node/runtime/rsc/payloadFetch.mjs +62 -0
  113. package/dist/esm-node/runtime/rsc/payloadRouter.mjs +12 -133
  114. package/dist/esm-node/runtime/rsc/payloadRoutes.mjs +51 -0
  115. package/dist/esm-node/runtime/rsc/payloadStorage.mjs +15 -0
  116. package/dist/esm-node/runtime/rsc/server.mjs +17 -21
  117. package/dist/esm-node/runtime/rsc/shared.mjs +22 -0
  118. package/dist/esm-node/runtime/rsc/treeGetter.mjs +35 -0
  119. package/dist/esm-node/runtime/ssrManagedTags.mjs +54 -0
  120. package/dist/esm-node/runtime/ssrPreload.mjs +52 -0
  121. package/dist/esm-node/runtime/ssrTypes.mjs +1 -0
  122. package/dist/esm-node/runtime/submitAction.mjs +121 -0
  123. package/dist/esm-node/runtime/utils.mjs +47 -75
  124. package/dist/types/cli/artifacts.d.ts +33 -0
  125. package/dist/types/cli/index.d.ts +2 -33
  126. package/dist/types/cli/tanstackTypes/canonicalRoutes.d.ts +22 -0
  127. package/dist/types/cli/tanstackTypes/shared.d.ts +20 -0
  128. package/dist/types/cli/tanstackTypes/source.d.ts +10 -0
  129. package/dist/types/cli/tanstackTypes.d.ts +3 -31
  130. package/dist/types/runtime/blockingSubscribe.d.ts +3 -0
  131. package/dist/types/runtime/clientBasepath.d.ts +1 -0
  132. package/dist/types/runtime/clientHydration.d.ts +19 -0
  133. package/dist/types/runtime/dataMutation.d.ts +3 -12
  134. package/dist/types/runtime/formData.d.ts +23 -0
  135. package/dist/types/runtime/plugin.d.ts +1 -1
  136. package/dist/types/runtime/plugin.node.d.ts +1 -1
  137. package/dist/types/runtime/{pluginCore.d.ts → pluginShared.d.ts} +14 -0
  138. package/dist/types/runtime/routeTree/components.d.ts +7 -0
  139. package/dist/types/runtime/routeTree/construction.d.ts +5 -0
  140. package/dist/types/runtime/routeTree/index.d.ts +2 -0
  141. package/dist/types/runtime/routeTree/loaders.d.ts +4 -0
  142. package/dist/types/runtime/routeTree/paths.d.ts +3 -0
  143. package/dist/types/runtime/routeTree/staticData.d.ts +19 -0
  144. package/dist/types/runtime/routeTree/tanstackRoutes.d.ts +4 -0
  145. package/dist/types/runtime/routeTree/types.d.ts +75 -0
  146. package/dist/types/runtime/routeTree.d.ts +1 -9
  147. package/dist/types/runtime/rsc/CompositeComponent.d.ts +1 -2
  148. package/dist/types/runtime/rsc/RscNodeRenderer.d.ts +2 -3
  149. package/dist/types/runtime/rsc/client.d.ts +2 -0
  150. package/dist/types/runtime/rsc/flightSerialization.d.ts +3 -0
  151. package/dist/types/runtime/rsc/payloadErrors.d.ts +6 -0
  152. package/dist/types/runtime/rsc/payloadFetch.d.ts +10 -0
  153. package/dist/types/runtime/rsc/payloadRouter.d.ts +2 -10
  154. package/dist/types/runtime/rsc/payloadRoutes.d.ts +43 -0
  155. package/dist/types/runtime/rsc/payloadStorage.d.ts +5 -0
  156. package/dist/types/runtime/rsc/shared.d.ts +19 -0
  157. package/dist/types/runtime/rsc/treeGetter.d.ts +1 -0
  158. package/dist/types/runtime/ssrManagedTags.d.ts +7 -0
  159. package/dist/types/runtime/ssrPreload.d.ts +2 -0
  160. package/dist/types/runtime/ssrTypes.d.ts +43 -0
  161. package/dist/types/runtime/state.d.ts +1 -1
  162. package/dist/types/runtime/submitAction.d.ts +14 -0
  163. package/dist/types/runtime/types.d.ts +3 -46
  164. package/dist/types/runtime/utils.d.ts +1 -22
  165. package/package.json +30 -9
  166. package/rstest.config.mts +1 -0
  167. package/src/cli/artifacts.ts +255 -0
  168. package/src/cli/index.ts +6 -246
  169. package/src/cli/tanstackTypes/canonicalRoutes.ts +157 -0
  170. package/src/cli/tanstackTypes/shared.ts +119 -0
  171. package/src/cli/tanstackTypes/source.ts +405 -0
  172. package/src/cli/tanstackTypes.ts +4 -647
  173. package/src/runtime/blockingSubscribe.ts +48 -0
  174. package/src/runtime/clientBasepath.ts +12 -0
  175. package/src/runtime/clientHydration.ts +151 -0
  176. package/src/runtime/dataMutation.tsx +9 -306
  177. package/src/runtime/formData.ts +153 -0
  178. package/src/runtime/loaderBridge.ts +8 -3
  179. package/src/runtime/plugin.node.tsx +60 -284
  180. package/src/runtime/plugin.tsx +21 -257
  181. package/src/runtime/pluginShared.ts +112 -0
  182. package/src/runtime/routeTree/components.ts +130 -0
  183. package/src/runtime/routeTree/construction.ts +238 -0
  184. package/src/runtime/routeTree/index.ts +7 -0
  185. package/src/runtime/routeTree/loaders.ts +232 -0
  186. package/src/runtime/routeTree/paths.ts +36 -0
  187. package/src/runtime/routeTree/staticData.ts +66 -0
  188. package/src/runtime/routeTree/tanstackRoutes.ts +36 -0
  189. package/src/runtime/routeTree/types.ts +87 -0
  190. package/src/runtime/routeTree.ts +5 -750
  191. package/src/runtime/rsc/CompositeComponent.tsx +29 -20
  192. package/src/runtime/rsc/RscNodeRenderer.tsx +9 -27
  193. package/src/runtime/rsc/client.tsx +12 -40
  194. package/src/runtime/rsc/flightSerialization.ts +158 -0
  195. package/src/runtime/rsc/payloadErrors.ts +73 -0
  196. package/src/runtime/rsc/payloadFetch.ts +97 -0
  197. package/src/runtime/rsc/payloadRouter.ts +29 -234
  198. package/src/runtime/rsc/payloadRoutes.ts +122 -0
  199. package/src/runtime/rsc/payloadStorage.ts +35 -0
  200. package/src/runtime/rsc/server.tsx +20 -29
  201. package/src/runtime/rsc/shared.ts +70 -0
  202. package/src/runtime/rsc/treeGetter.tsx +52 -0
  203. package/src/runtime/ssrManagedTags.ts +107 -0
  204. package/src/runtime/ssrPreload.ts +125 -0
  205. package/src/runtime/ssrTypes.ts +51 -0
  206. package/src/runtime/state.ts +4 -2
  207. package/src/runtime/submitAction.ts +194 -0
  208. package/src/runtime/types.ts +14 -51
  209. package/src/runtime/utils.tsx +72 -108
  210. package/src/types/react-server-dom-rspack.d.ts +56 -0
  211. package/tests/castRatchet.test.ts +85 -0
  212. package/tests/router/dataMutation.test.tsx +59 -0
  213. package/tests/router/fixtures/router-gen.golden.txt +72 -0
  214. package/tests/router/loaderBridge.test.ts +21 -0
  215. package/tests/router/routeTree.test.ts +46 -11
  216. package/tests/router/rsc.test.tsx +189 -0
  217. package/tests/router/ssrPreload.test.ts +30 -0
  218. package/tests/router/tanstackTypes.test.ts +254 -1
  219. package/dist/esm/runtime/pluginCore.mjs +0 -14
  220. package/dist/esm-node/runtime/pluginCore.mjs +0 -15
  221. package/src/runtime/pluginCore.ts +0 -56
@@ -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
+ export type RouterRouteOptions = {
27
+ component?: unknown;
28
+ errorComponent?: unknown;
29
+ notFoundComponent?: unknown;
30
+ pendingComponent?: unknown;
31
+ };
32
+
33
+ export 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
@@ -0,0 +1,194 @@
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
+ function resolveRouteHandlers(router: AnyRouter, actionTo: string) {
35
+ const builtLocation = router.buildLocation({
36
+ to: actionTo as any,
37
+ } as any);
38
+ const href = router.getParsedLocationHref(builtLocation as any);
39
+ const matchedRoutes = router.getMatchedRoutes(
40
+ (builtLocation as any).pathname,
41
+ );
42
+ const routeStaticData = matchedRoutes.foundRoute?.options?.staticData as
43
+ | Record<string, unknown>
44
+ | undefined;
45
+ const action = routeStaticData?.modernRouteAction as RouteAction | undefined;
46
+ const loader = routeStaticData?.modernRouteLoader as RouteLoader | undefined;
47
+
48
+ return {
49
+ action,
50
+ loader,
51
+ href,
52
+ params: (matchedRoutes.routeParams || {}) as Record<string, string>,
53
+ };
54
+ }
55
+
56
+ function isRedirectResponse(value: unknown): value is Response {
57
+ if (!(value instanceof Response)) {
58
+ return false;
59
+ }
60
+ return [301, 302, 303, 307, 308].includes(value.status);
61
+ }
62
+
63
+ async function parseResponseData(response: Response) {
64
+ if (response.status === 204) {
65
+ return null;
66
+ }
67
+
68
+ const contentType = response.headers.get('Content-Type') || '';
69
+ if (contentType.includes('application/json')) {
70
+ return response.json();
71
+ }
72
+ return response.text();
73
+ }
74
+
75
+ async function parseResponseResultOrThrow(response: Response) {
76
+ const parsed = await parseResponseData(response);
77
+ if (!response.ok) {
78
+ throw new RouteActionResponseError(response, parsed);
79
+ }
80
+ return parsed;
81
+ }
82
+
83
+ export async function submitRouteAction({
84
+ router,
85
+ target,
86
+ options = {},
87
+ isFetcher = false,
88
+ onInvalidateStart,
89
+ }: {
90
+ router: AnyRouter;
91
+ target: SubmitTarget;
92
+ options?: SubmitOptions;
93
+ isFetcher?: boolean;
94
+ onInvalidateStart?: () => void;
95
+ }) {
96
+ const method = (options.method || 'post').toLowerCase();
97
+ const encType = options.encType || 'application/x-www-form-urlencoded';
98
+ const actionTo = options.action || '.';
99
+ const formData = toFormData(target);
100
+ const resolved = resolveRouteHandlers(router, actionTo);
101
+
102
+ if (method === 'get') {
103
+ const search = formDataToUrlSearchParams(formData).toString();
104
+ const requestUrl = new URL(resolved.href, window.location.origin);
105
+ requestUrl.search = search;
106
+
107
+ if (isFetcher && resolved.loader) {
108
+ const result = await resolved.loader({
109
+ request: new Request(requestUrl, {
110
+ method: 'GET',
111
+ }),
112
+ params: resolved.params,
113
+ });
114
+
115
+ if (result instanceof Response) {
116
+ const redirectTo =
117
+ result.headers.get('X-Modernjs-Redirect') ||
118
+ result.headers.get('Location');
119
+ if (redirectTo || isRedirectResponse(result)) {
120
+ await router.navigate({
121
+ to: (redirectTo || '/') as any,
122
+ } as any);
123
+ return parseResponseData(result);
124
+ }
125
+ return parseResponseResultOrThrow(result);
126
+ }
127
+
128
+ return result;
129
+ }
130
+
131
+ await router.navigate({
132
+ href: `${requestUrl.pathname}${requestUrl.search}${requestUrl.hash}`,
133
+ } as any);
134
+ return;
135
+ }
136
+
137
+ if (!resolved.action) {
138
+ throw new Error(`No route action found for "${actionTo}"`);
139
+ }
140
+
141
+ const headers = new Headers();
142
+ let body: BodyInit | null = null;
143
+ if (encType.includes('application/json')) {
144
+ headers.set('Content-Type', 'application/json');
145
+ body = JSON.stringify(
146
+ Object.fromEntries(formDataToUrlSearchParams(formData).entries()),
147
+ );
148
+ } else if (encType.includes('text/plain')) {
149
+ headers.set('Content-Type', 'text/plain;charset=UTF-8');
150
+ body = formDataToTextPlain(formData);
151
+ } else if (encType.includes('application/x-www-form-urlencoded')) {
152
+ headers.set(
153
+ 'Content-Type',
154
+ 'application/x-www-form-urlencoded;charset=UTF-8',
155
+ );
156
+ body = formDataToUrlSearchParams(formData);
157
+ } else {
158
+ body = formData;
159
+ }
160
+
161
+ const request = new Request(new URL(resolved.href, window.location.origin), {
162
+ method: method.toUpperCase(),
163
+ headers,
164
+ body,
165
+ });
166
+
167
+ const result = await resolved.action({
168
+ request,
169
+ params: resolved.params,
170
+ });
171
+
172
+ if (result instanceof Response) {
173
+ const redirectTo =
174
+ result.headers.get('X-Modernjs-Redirect') ||
175
+ result.headers.get('Location');
176
+ if (redirectTo || isRedirectResponse(result)) {
177
+ await router.navigate({
178
+ to: (redirectTo || '/') as any,
179
+ } as any);
180
+ return parseResponseData(result);
181
+ }
182
+
183
+ const parsed = isFetcher
184
+ ? await parseResponseResultOrThrow(result)
185
+ : await parseResponseData(result);
186
+ onInvalidateStart?.();
187
+ await router.invalidate();
188
+ return parsed;
189
+ }
190
+
191
+ onInvalidateStart?.();
192
+ await router.invalidate();
193
+ return result;
194
+ }
@@ -1,57 +1,20 @@
1
+ import type { ModernRoute, RouterFramework } from '@modern-js/runtime/context';
1
2
  import type { RouteObject } from '@modern-js/runtime-utils/router';
2
3
  import type React from 'react';
3
4
 
4
- export type BuiltInRouterFramework = 'react-router' | 'tanstack';
5
- export type RouterFramework = BuiltInRouterFramework | (string & {});
6
-
7
- export type ModernRoute = {
8
- type: 'nested' | 'page';
9
- path?: string;
10
- id?: string;
11
- component?: React.ComponentType | string;
12
- children?: ModernRoute[];
13
- [key: string]: any;
14
- };
15
-
16
- export type RouterRouteMatchSnapshot = {
17
- routeId: string;
18
- assetRouteId?: string;
19
- pathname?: string;
20
- params?: Record<string, string>;
21
- };
22
-
23
- export type InternalRouterServerSnapshot = {
24
- framework?: RouterFramework;
25
- basename?: string;
26
- statusCode?: number;
27
- errors?: Record<string, unknown>;
28
- routerData?: {
29
- loaderData?: Record<string, unknown>;
30
- errors?: Record<string, unknown>;
31
- };
32
- hydrationScript?: string;
33
- hydrationScripts?: string[];
34
- matchedRouteIds?: string[];
35
- matches?: RouterRouteMatchSnapshot[];
36
- };
37
-
38
- export type InternalRouterRuntimeState = {
39
- framework: RouterFramework;
40
- basename?: string;
41
- instance?: unknown;
42
- hydrationScript?: string;
43
- hydrationScripts?: string[];
44
- matchedRouteIds?: string[];
45
- matches?: RouterRouteMatchSnapshot[];
46
- serverSnapshot?: InternalRouterServerSnapshot;
47
- cleanup?: () => void | Promise<void>;
48
- };
49
-
50
- /**
51
- * TanStack-specific router config. Unlike the react-router provider config,
52
- * this intentionally has no `oldVersion`/`future` fields — those are
53
- * react-router-only knobs with no meaning here.
54
- */
5
+ export type {
6
+ BuiltInRouterFramework,
7
+ InternalRouterRuntimeState,
8
+ InternalRouterServerSnapshot,
9
+ LoaderFunction,
10
+ LoaderFunctionArgs,
11
+ ModernRoute,
12
+ RouterFramework,
13
+ RouterRouteMatchSnapshot,
14
+ RouterServerPrepareResult,
15
+ } from '@modern-js/runtime/context';
16
+
17
+ /** TanStack-specific router config. */
55
18
  export type RouterConfig = {
56
19
  framework?: RouterFramework;
57
20
  routesConfig: {