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

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 +51 -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
@@ -20,19 +20,28 @@ import {
20
20
  } from '@tanstack/react-router';
21
21
  import { useContext, useMemo } from 'react';
22
22
  import { createModernBasepathRewrite } from './basepathRewrite';
23
+ import { wrapRouterSubscribeWithBlockState } from './blockingSubscribe';
24
+ import { isSegmentPrefix } from './clientBasepath';
25
+ import {
26
+ getTanstackSsrHydrationPromise,
27
+ hasTanstackSsrHydrationRecord,
28
+ ModernRouterClient,
29
+ type WindowWithTanstackSsr,
30
+ } from './clientHydration';
23
31
  import { routerProviderRegistryHooks } from './hooks';
24
32
  import { wrapTanstackSsrHydrationBoundary } from './hydrationBoundary';
25
33
  import {
26
34
  applyRouterRuntimeState,
27
35
  type RouterLifecycleContext,
28
36
  } from './lifecycle';
29
- import { withModernRouteMatchContext } from './outlet';
30
37
  import {
31
- getFinalRouteConfig,
38
+ createTanstackRouteObjects,
32
39
  getMergedRouterConfig,
40
+ getTanstackRouteConfig,
41
+ joinBasename,
33
42
  type TanstackRouterPluginAPI,
34
43
  type TanstackRouterRuntimePlugin,
35
- } from './pluginCore';
44
+ } from './pluginShared';
36
45
  import { Link } from './prefetchLink';
37
46
  import { useMatches } from './routeHooks';
38
47
  import { createRouteTreeFromRouteObjects } from './routeTree';
@@ -41,245 +50,6 @@ import {
41
50
  getModernTanstackRouterFastDefaults,
42
51
  type RouterConfig,
43
52
  } from './types';
44
- import { createRouteObjectsFromConfig, urlJoin } from './utils';
45
-
46
- const BLOCKING_SUBSCRIBE_SYMBOL = Symbol.for(
47
- '@modern-js/plugin-tanstack:blocking-subscribe',
48
- );
49
- const BLOCKING_STATE_SYMBOL = Symbol.for(
50
- '@modern-js/plugin-tanstack:blocking-state',
51
- );
52
- type TanstackRouterWithSubscribe = {
53
- [BLOCKING_STATE_SYMBOL]?: () => boolean;
54
- [BLOCKING_SUBSCRIBE_SYMBOL]?: boolean;
55
- subscribe?: (
56
- eventType: string,
57
- listener: (...args: unknown[]) => void,
58
- ) => () => void;
59
- };
60
-
61
- type WindowWithTanstackSsr = Window & {
62
- $_TSR?: unknown;
63
- };
64
-
65
- type RouteComponentPreloadable = {
66
- load?: () => Promise<unknown>;
67
- preload?: () => Promise<unknown>;
68
- };
69
-
70
- type ModernRouteModule = {
71
- Component?: unknown;
72
- default?: unknown;
73
- };
74
-
75
- type RouterWithPreloadableRoutes = AnyRouter & {
76
- routesById?: Record<
77
- string,
78
- {
79
- options?: {
80
- component?: unknown;
81
- staticData?: {
82
- modernRouteId?: string;
83
- };
84
- };
85
- }
86
- >;
87
- };
88
-
89
- function normalizeBase(b: string) {
90
- if (b.length > 1 && b.endsWith('/')) {
91
- return b.slice(0, -1);
92
- }
93
- return b || '/';
94
- }
95
-
96
- function isSegmentPrefix(pathname: string, base: string) {
97
- const b = normalizeBase(base);
98
- const p = pathname || '/';
99
- return p === b || p.startsWith(`${b}/`);
100
- }
101
-
102
- function wrapRouterSubscribeWithBlockState(
103
- router: unknown,
104
- getBlockNavState?: () => boolean,
105
- ) {
106
- if (!router || typeof router !== 'object') {
107
- return;
108
- }
109
-
110
- const target = router as TanstackRouterWithSubscribe;
111
- target[BLOCKING_STATE_SYMBOL] = getBlockNavState;
112
- if (
113
- target[BLOCKING_SUBSCRIBE_SYMBOL] ||
114
- typeof target.subscribe !== 'function'
115
- ) {
116
- return;
117
- }
118
-
119
- const originSubscribe = target.subscribe.bind(target);
120
- target.subscribe = (eventType, listener) => {
121
- const wrappedListener = (...args: unknown[]) => {
122
- const blockRoute = target[BLOCKING_STATE_SYMBOL]?.() || false;
123
- if (blockRoute) {
124
- return;
125
- }
126
- return listener(...args);
127
- };
128
- return originSubscribe(eventType, wrappedListener);
129
- };
130
- target[BLOCKING_SUBSCRIBE_SYMBOL] = true;
131
- }
132
-
133
- type RouterHydrationRecord = {
134
- error?: unknown;
135
- promise: Promise<unknown>;
136
- status: 'pending' | 'fulfilled' | 'rejected';
137
- };
138
-
139
- const routerHydrationRecords = new WeakMap<AnyRouter, RouterHydrationRecord>();
140
- const routeModulesKey = '_routeModules';
141
-
142
- function pickRouteModuleComponent(
143
- routeModule: unknown,
144
- seen: Set<unknown> = new Set(),
145
- ): unknown {
146
- if (
147
- typeof routeModule === 'function' ||
148
- (routeModule &&
149
- typeof routeModule === 'object' &&
150
- '$$typeof' in routeModule)
151
- ) {
152
- return routeModule;
153
- }
154
-
155
- if (!routeModule || typeof routeModule !== 'object') {
156
- return undefined;
157
- }
158
- if (seen.has(routeModule)) {
159
- return undefined;
160
- }
161
- seen.add(routeModule);
162
-
163
- const module = routeModule as ModernRouteModule;
164
- for (const candidate of [module.default, module.Component]) {
165
- const component = pickRouteModuleComponent(candidate, seen);
166
- if (component) {
167
- return component;
168
- }
169
- }
170
-
171
- return undefined;
172
- }
173
-
174
- function getCachedRouteModule(routeId: string) {
175
- if (typeof window === 'undefined') {
176
- return undefined;
177
- }
178
-
179
- return (window as unknown as Record<string, Record<string, unknown>>)[
180
- routeModulesKey
181
- ]?.[routeId];
182
- }
183
-
184
- function preloadHydratedRouteComponents(router: AnyRouter): Promise<void> {
185
- const preloadableRouter = router as RouterWithPreloadableRoutes;
186
- const routesById = preloadableRouter.routesById || {};
187
- const matches = preloadableRouter.stores.matches.get() as Array<{
188
- routeId?: string;
189
- }>;
190
-
191
- return Promise.all(
192
- matches.map(match => {
193
- if (match.routeId === undefined || match.routeId === '') {
194
- return undefined;
195
- }
196
-
197
- const route = routesById[match.routeId];
198
- const component = route?.options?.component as RouteComponentPreloadable;
199
- const preload = component?.load || component?.preload;
200
- if (typeof preload !== 'function') {
201
- return undefined;
202
- }
203
-
204
- return Promise.resolve(preload.call(component)).then(routeModule => {
205
- const modernRouteId = route?.options?.staticData?.modernRouteId;
206
- const cachedRouteModule =
207
- typeof modernRouteId === 'string' && modernRouteId !== ''
208
- ? getCachedRouteModule(modernRouteId)
209
- : undefined;
210
- const resolvedComponent = pickRouteModuleComponent(
211
- cachedRouteModule ?? routeModule,
212
- );
213
- if (
214
- resolvedComponent !== undefined &&
215
- typeof modernRouteId === 'string' &&
216
- modernRouteId !== ''
217
- ) {
218
- route.options.component = withModernRouteMatchContext(
219
- resolvedComponent,
220
- modernRouteId,
221
- );
222
- }
223
- });
224
- }),
225
- ).then(() => undefined);
226
- }
227
-
228
- function hydrateTanstackRouter(router: AnyRouter) {
229
- return import('@tanstack/react-router/ssr/client').then(({ hydrate }) =>
230
- hydrate(router),
231
- );
232
- }
233
-
234
- function getTanstackSsrHydrationRecord(router: AnyRouter) {
235
- const existingHydrationRecord = routerHydrationRecords.get(router);
236
- if (existingHydrationRecord !== undefined) {
237
- return existingHydrationRecord;
238
- }
239
-
240
- const hydrationRecord: RouterHydrationRecord = {
241
- promise: Promise.resolve(),
242
- status: 'pending',
243
- };
244
- routerHydrationRecords.set(router, hydrationRecord);
245
- try {
246
- hydrationRecord.promise = hydrateTanstackRouter(router)
247
- .then(value => preloadHydratedRouteComponents(router).then(() => value))
248
- .then(
249
- value => {
250
- hydrationRecord.status = 'fulfilled';
251
- return value;
252
- },
253
- error => {
254
- hydrationRecord.status = 'rejected';
255
- hydrationRecord.error = error;
256
- throw error;
257
- },
258
- );
259
- } catch (error) {
260
- hydrationRecord.status = 'rejected';
261
- hydrationRecord.error = error;
262
- hydrationRecord.promise = Promise.reject(error);
263
- hydrationRecord.promise.catch(() => {});
264
- }
265
- return hydrationRecord;
266
- }
267
-
268
- function getTanstackSsrHydrationPromise(router: AnyRouter) {
269
- return getTanstackSsrHydrationRecord(router).promise;
270
- }
271
-
272
- function hasTanstackSsrHydrationRecord(router: AnyRouter) {
273
- return routerHydrationRecords.has(router);
274
- }
275
-
276
- function ModernRouterClient({ router }: { router: AnyRouter }) {
277
- const hydrationRecord = getTanstackSsrHydrationRecord(router);
278
- if (hydrationRecord.status === 'rejected') {
279
- throw hydrationRecord.error;
280
- }
281
- return <RouterProvider router={router} />;
282
- }
283
53
 
284
54
  export const tanstackRouterPlugin = (
285
55
  userConfig: Partial<RouterConfig> = {},
@@ -303,19 +73,10 @@ export const tanstackRouterPlugin = (
303
73
  return cachedRouteObjects;
304
74
  }
305
75
 
306
- const mergedConfig = getMergedConfig();
307
- const { createRoutes } = mergedConfig;
308
- const finalRouteConfig = getFinalRouteConfig(mergedConfig);
309
-
310
- const routeObjects = createRoutes
311
- ? createRoutes()
312
- : createRouteObjectsFromConfig({
313
- routesConfig: finalRouteConfig,
314
- }) || [];
315
-
316
- cachedRouteObjects = hooks.modifyRoutes.call(
317
- routeObjects,
318
- ) as RouteObject[];
76
+ cachedRouteObjects = createTanstackRouteObjects({
77
+ hooks,
78
+ routeConfig: getTanstackRouteConfig(api, userConfig),
79
+ });
319
80
  return cachedRouteObjects;
320
81
  };
321
82
 
@@ -347,7 +108,7 @@ export const tanstackRouterPlugin = (
347
108
  const { basename = '' } = getMergedConfig();
348
109
  const baseUrl = selectBasePath(location.pathname).replace(/^\/*/, '/');
349
110
  return baseUrl === '/'
350
- ? urlJoin(
111
+ ? joinBasename(
351
112
  baseUrl,
352
113
  runtimeContext._internalRouterBaseName || basename || '',
353
114
  )
@@ -394,9 +155,12 @@ export const tanstackRouterPlugin = (
394
155
  const serializationAdapters = getGlobalEnableRsc()
395
156
  ? getTanstackRscSerializationAdapters()
396
157
  : undefined;
158
+ const routerFastDefaults =
159
+ getModernTanstackRouterFastDefaults(mergedConfig);
397
160
 
398
161
  cachedRouter = createRouter({
399
- ...getModernTanstackRouterFastDefaults(mergedConfig),
162
+ ...routerFastDefaults,
163
+ ...(serializationAdapters ? { defaultStructuralSharing: false } : {}),
400
164
  routeTree,
401
165
  basepath: '/',
402
166
  rewrite,
@@ -0,0 +1,112 @@
1
+ import {
2
+ getGlobalLayoutApp,
3
+ getGlobalRoutes,
4
+ type TInternalRuntimeContext,
5
+ } from '@modern-js/runtime/context';
6
+ import { merge } from '@modern-js/runtime-utils/merge';
7
+ import type { RouteObject } from '@modern-js/runtime-utils/router';
8
+ import type { RouterExtendsHooks } from './hooks';
9
+ import type { RouterConfig } from './types';
10
+ import { createTanstackRouteObjectsFromConfig, type SSRMode } from './utils';
11
+
12
+ export type TanstackRouterRuntimeConfig = {
13
+ plugins?: TanstackRouterRuntimePlugin[];
14
+ router?: Partial<RouterConfig>;
15
+ [key: string]: unknown;
16
+ };
17
+
18
+ type RuntimeInterrupt = (value?: unknown) => unknown;
19
+
20
+ export type TanstackRouterPluginAPI = {
21
+ getRuntimeConfig: () => TanstackRouterRuntimeConfig;
22
+ getHooks: () => RouterExtendsHooks;
23
+ onBeforeRender: (
24
+ listener: (
25
+ context: TInternalRuntimeContext,
26
+ interrupt: RuntimeInterrupt,
27
+ ) => unknown,
28
+ ) => void;
29
+ wrapRoot: (listener: (App: any) => any) => void;
30
+ [key: string]: any;
31
+ };
32
+
33
+ export type TanstackRouterRuntimePlugin = {
34
+ name?: string;
35
+ registryHooks?: RouterExtendsHooks;
36
+ setup?: (api: TanstackRouterPluginAPI) => unknown;
37
+ [key: string]: unknown;
38
+ };
39
+
40
+ export type TanstackRouteConfig = {
41
+ mergedConfig: RouterConfig;
42
+ finalRouteConfig: RouterConfig['routesConfig'];
43
+ hasConfiguredRoutes: boolean;
44
+ };
45
+
46
+ export function getMergedRouterConfig(
47
+ api: TanstackRouterPluginAPI,
48
+ userConfig: Partial<RouterConfig>,
49
+ ): RouterConfig {
50
+ const pluginConfig = api.getRuntimeConfig() as {
51
+ router?: Partial<RouterConfig>;
52
+ };
53
+ return merge(pluginConfig.router || {}, userConfig) as RouterConfig;
54
+ }
55
+
56
+ export function getFinalRouteConfig(
57
+ mergedConfig: RouterConfig,
58
+ ): RouterConfig['routesConfig'] {
59
+ return {
60
+ routes: getGlobalRoutes() as RouterConfig['routesConfig']['routes'],
61
+ globalApp: getGlobalLayoutApp(),
62
+ ...mergedConfig.routesConfig,
63
+ };
64
+ }
65
+
66
+ export function getTanstackRouteConfig(
67
+ api: TanstackRouterPluginAPI,
68
+ userConfig: Partial<RouterConfig>,
69
+ ): TanstackRouteConfig {
70
+ const mergedConfig = getMergedRouterConfig(api, userConfig);
71
+ const finalRouteConfig = getFinalRouteConfig(mergedConfig);
72
+ return {
73
+ mergedConfig,
74
+ finalRouteConfig,
75
+ hasConfiguredRoutes:
76
+ Boolean(finalRouteConfig.routes) || Boolean(mergedConfig.createRoutes),
77
+ };
78
+ }
79
+
80
+ export function createTanstackRouteObjects({
81
+ hooks,
82
+ routeConfig,
83
+ ssrMode,
84
+ }: {
85
+ hooks: RouterExtendsHooks;
86
+ routeConfig: TanstackRouteConfig;
87
+ ssrMode?: SSRMode;
88
+ }): RouteObject[] {
89
+ const { mergedConfig, finalRouteConfig } = routeConfig;
90
+ const routeObjects = mergedConfig.createRoutes
91
+ ? mergedConfig.createRoutes()
92
+ : createTanstackRouteObjectsFromConfig({
93
+ routesConfig: finalRouteConfig,
94
+ ssrMode,
95
+ }) || [];
96
+
97
+ return hooks.modifyRoutes.call(routeObjects) as RouteObject[];
98
+ }
99
+
100
+ export function joinBasename(baseUrl: string, basename: string): string {
101
+ const base = baseUrl || '/';
102
+ const normalizedBase = base.startsWith('/') ? base : `/${base}`;
103
+ const trimmedBase =
104
+ normalizedBase.length > 1
105
+ ? normalizedBase.replace(/\/+$/g, '')
106
+ : normalizedBase;
107
+ const trimmedBasename = basename.replace(/^\/+|\/+$/g, '');
108
+ if (!trimmedBasename) {
109
+ return trimmedBase || '/';
110
+ }
111
+ return `${trimmedBase}/${trimmedBasename}`.replace(/\/{2,}/g, '/');
112
+ }
@@ -0,0 +1,130 @@
1
+ // @effect-diagnostics asyncFunction:off strictBooleanExpressions:off
2
+
3
+ import type { RouteObject } from '@modern-js/runtime-utils/router';
4
+ import { createElement, type ElementType } from 'react';
5
+
6
+ import type { ModernRouteObject, RouteTreeOptions } from './types';
7
+
8
+ type ModernRouteModule = {
9
+ Component?: unknown;
10
+ default?: unknown;
11
+ };
12
+ type PreloadableComponent = {
13
+ (props: Record<string, unknown>): ReturnType<typeof createElement>;
14
+ load?: () => Promise<unknown>;
15
+ preload?: () => Promise<unknown>;
16
+ };
17
+
18
+ export function pickRouteModuleComponent(
19
+ routeModule: unknown,
20
+ seen: Set<unknown> = new Set(),
21
+ ): ElementType<Record<string, unknown>> | undefined {
22
+ if (
23
+ typeof routeModule === 'function' ||
24
+ (routeModule &&
25
+ typeof routeModule === 'object' &&
26
+ '$$typeof' in routeModule)
27
+ ) {
28
+ return routeModule as ElementType<Record<string, unknown>>;
29
+ }
30
+
31
+ if (!routeModule || typeof routeModule !== 'object') {
32
+ return undefined;
33
+ }
34
+ if (seen.has(routeModule)) {
35
+ return undefined;
36
+ }
37
+ seen.add(routeModule);
38
+
39
+ const module = routeModule as ModernRouteModule;
40
+ for (const candidate of [module.default, module.Component]) {
41
+ const component = pickRouteModuleComponent(candidate, seen);
42
+ if (component) {
43
+ return component;
44
+ }
45
+ }
46
+
47
+ return undefined;
48
+ }
49
+
50
+ function createServerLazyImportComponent(
51
+ lazyImport: () => unknown,
52
+ fallbackComponent?: unknown,
53
+ ): PreloadableComponent | unknown {
54
+ if (typeof document !== 'undefined') {
55
+ return fallbackComponent;
56
+ }
57
+
58
+ let resolvedComponent: ElementType<Record<string, unknown>> | undefined;
59
+ let pendingLoad: Promise<unknown> | undefined;
60
+
61
+ const load = async () => {
62
+ if (resolvedComponent) {
63
+ return resolvedComponent;
64
+ }
65
+
66
+ const routeModule = await lazyImport();
67
+ const component = pickRouteModuleComponent(routeModule);
68
+ if (component) {
69
+ resolvedComponent = component;
70
+ }
71
+ return resolvedComponent;
72
+ };
73
+
74
+ const Component: PreloadableComponent = props => {
75
+ if (resolvedComponent) {
76
+ return createElement(resolvedComponent, props);
77
+ }
78
+
79
+ pendingLoad ||= load();
80
+ throw pendingLoad;
81
+ };
82
+ Component.load = load;
83
+ Component.preload = load;
84
+
85
+ return Component;
86
+ }
87
+
88
+ export function toRouteComponent(
89
+ routeObject: RouteObject,
90
+ options: RouteTreeOptions = {},
91
+ ): unknown {
92
+ const route = routeObject as ModernRouteObject;
93
+ const lazyImport =
94
+ typeof route.lazyImport === 'function' ? route.lazyImport : undefined;
95
+ const routeComponent = route.Component || route.component;
96
+ const fallbackComponent = routeComponent
97
+ ? routeComponent
98
+ : route.element
99
+ ? () => route.element
100
+ : undefined;
101
+
102
+ if (lazyImport && fallbackComponent) {
103
+ return createServerLazyImportComponent(lazyImport, fallbackComponent);
104
+ }
105
+
106
+ if (routeComponent) {
107
+ return routeComponent;
108
+ }
109
+ const element = route.element;
110
+ if (element) {
111
+ return () => element;
112
+ }
113
+ return undefined;
114
+ }
115
+
116
+ export function toErrorComponent(routeObject: RouteObject): unknown {
117
+ const route = routeObject as ModernRouteObject;
118
+ if (route.ErrorBoundary) {
119
+ return route.ErrorBoundary;
120
+ }
121
+ if (route.errorElement) {
122
+ return () => route.errorElement;
123
+ }
124
+ return undefined;
125
+ }
126
+
127
+ export function toPendingComponent(routeObject: RouteObject): unknown {
128
+ const route = routeObject as ModernRouteObject;
129
+ return route.HydrateFallback || route.pendingComponent || undefined;
130
+ }