@bleedingdev/modern-js-plugin-tanstack 3.5.0-ultramodern.3 → 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 (230) 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 +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 +45 -125
  15. package/dist/cjs/runtime/pluginShared.js +90 -0
  16. package/dist/cjs/runtime/prefetchLink.js +15 -2
  17. package/dist/cjs/runtime/routeTree/components.js +102 -0
  18. package/dist/cjs/runtime/routeTree/construction.js +152 -0
  19. package/dist/cjs/runtime/routeTree/index.js +47 -0
  20. package/dist/cjs/runtime/routeTree/loaders.js +158 -0
  21. package/dist/cjs/runtime/routeTree/paths.js +57 -0
  22. package/dist/cjs/runtime/routeTree/staticData.js +63 -0
  23. package/dist/cjs/runtime/routeTree/tanstackRoutes.js +57 -0
  24. package/dist/cjs/runtime/routeTree/types.js +18 -0
  25. package/dist/cjs/runtime/routeTree.js +7 -320
  26. package/dist/cjs/runtime/rsc/CompositeComponent.js +18 -13
  27. package/dist/cjs/runtime/rsc/RscNodeRenderer.js +5 -16
  28. package/dist/cjs/runtime/rsc/client.js +8 -25
  29. package/dist/cjs/runtime/rsc/flightSerialization.js +132 -0
  30. package/dist/cjs/runtime/rsc/payloadErrors.js +99 -0
  31. package/dist/cjs/runtime/rsc/payloadFetch.js +117 -0
  32. package/dist/cjs/runtime/rsc/payloadRouter.js +21 -142
  33. package/dist/cjs/runtime/rsc/payloadRoutes.js +106 -0
  34. package/dist/cjs/runtime/rsc/payloadStorage.js +58 -0
  35. package/dist/cjs/runtime/rsc/server.js +14 -18
  36. package/dist/cjs/runtime/rsc/shared.js +71 -0
  37. package/dist/cjs/runtime/rsc/treeGetter.js +72 -0
  38. package/dist/cjs/runtime/ssrManagedTags.js +103 -0
  39. package/dist/cjs/runtime/ssrPreload.js +89 -0
  40. package/dist/cjs/runtime/ssrTypes.js +18 -0
  41. package/dist/cjs/runtime/submitAction.js +161 -0
  42. package/dist/cjs/runtime/utils.js +49 -86
  43. package/dist/esm/cli/artifacts.mjs +103 -0
  44. package/dist/esm/cli/index.mjs +4 -78
  45. package/dist/esm/cli/tanstackTypes/canonicalRoutes.mjs +75 -0
  46. package/dist/esm/cli/tanstackTypes/shared.mjs +68 -0
  47. package/dist/esm/cli/tanstackTypes/source.mjs +203 -0
  48. package/dist/esm/cli/tanstackTypes.mjs +2 -339
  49. package/dist/esm/runtime/blockingSubscribe.mjs +19 -0
  50. package/dist/esm/runtime/clientBasepath.mjs +10 -0
  51. package/dist/esm/runtime/clientHydration.mjs +70 -0
  52. package/dist/esm/runtime/dataMutation.mjs +2 -167
  53. package/dist/esm/runtime/formData.mjs +63 -0
  54. package/dist/esm/runtime/loaderBridge.mjs +4 -1
  55. package/dist/esm/runtime/plugin.mjs +14 -118
  56. package/dist/esm/runtime/plugin.node.mjs +41 -121
  57. package/dist/esm/runtime/pluginShared.mjs +40 -0
  58. package/dist/esm/runtime/prefetchLink.mjs +18 -5
  59. package/dist/esm/runtime/routeTree/components.mjs +55 -0
  60. package/dist/esm/runtime/routeTree/construction.mjs +111 -0
  61. package/dist/esm/runtime/routeTree/index.mjs +2 -0
  62. package/dist/esm/runtime/routeTree/loaders.mjs +117 -0
  63. package/dist/esm/runtime/routeTree/paths.mjs +16 -0
  64. package/dist/esm/runtime/routeTree/staticData.mjs +22 -0
  65. package/dist/esm/runtime/routeTree/tanstackRoutes.mjs +13 -0
  66. package/dist/esm/runtime/routeTree/types.mjs +0 -0
  67. package/dist/esm/runtime/routeTree.mjs +1 -318
  68. package/dist/esm/runtime/rsc/CompositeComponent.mjs +18 -13
  69. package/dist/esm/runtime/rsc/RscNodeRenderer.mjs +4 -15
  70. package/dist/esm/runtime/rsc/client.mjs +6 -26
  71. package/dist/esm/runtime/rsc/flightSerialization.mjs +88 -0
  72. package/dist/esm/runtime/rsc/payloadErrors.mjs +49 -0
  73. package/dist/esm/runtime/rsc/payloadFetch.mjs +61 -0
  74. package/dist/esm/runtime/rsc/payloadRouter.mjs +12 -133
  75. package/dist/esm/runtime/rsc/payloadRoutes.mjs +50 -0
  76. package/dist/esm/runtime/rsc/payloadStorage.mjs +14 -0
  77. package/dist/esm/runtime/rsc/server.mjs +17 -21
  78. package/dist/esm/runtime/rsc/shared.mjs +21 -0
  79. package/dist/esm/runtime/rsc/treeGetter.mjs +34 -0
  80. package/dist/esm/runtime/ssrManagedTags.mjs +53 -0
  81. package/dist/esm/runtime/ssrPreload.mjs +51 -0
  82. package/dist/esm/runtime/ssrTypes.mjs +0 -0
  83. package/dist/esm/runtime/submitAction.mjs +120 -0
  84. package/dist/esm/runtime/utils.mjs +47 -75
  85. package/dist/esm-node/cli/artifacts.mjs +104 -0
  86. package/dist/esm-node/cli/index.mjs +4 -78
  87. package/dist/esm-node/cli/tanstackTypes/canonicalRoutes.mjs +76 -0
  88. package/dist/esm-node/cli/tanstackTypes/shared.mjs +69 -0
  89. package/dist/esm-node/cli/tanstackTypes/source.mjs +204 -0
  90. package/dist/esm-node/cli/tanstackTypes.mjs +2 -339
  91. package/dist/esm-node/runtime/blockingSubscribe.mjs +20 -0
  92. package/dist/esm-node/runtime/clientBasepath.mjs +11 -0
  93. package/dist/esm-node/runtime/clientHydration.mjs +71 -0
  94. package/dist/esm-node/runtime/dataMutation.mjs +2 -167
  95. package/dist/esm-node/runtime/formData.mjs +64 -0
  96. package/dist/esm-node/runtime/loaderBridge.mjs +4 -1
  97. package/dist/esm-node/runtime/plugin.mjs +14 -118
  98. package/dist/esm-node/runtime/plugin.node.mjs +41 -121
  99. package/dist/esm-node/runtime/pluginShared.mjs +41 -0
  100. package/dist/esm-node/runtime/prefetchLink.mjs +18 -5
  101. package/dist/esm-node/runtime/routeTree/components.mjs +56 -0
  102. package/dist/esm-node/runtime/routeTree/construction.mjs +112 -0
  103. package/dist/esm-node/runtime/routeTree/index.mjs +3 -0
  104. package/dist/esm-node/runtime/routeTree/loaders.mjs +118 -0
  105. package/dist/esm-node/runtime/routeTree/paths.mjs +17 -0
  106. package/dist/esm-node/runtime/routeTree/staticData.mjs +23 -0
  107. package/dist/esm-node/runtime/routeTree/tanstackRoutes.mjs +14 -0
  108. package/dist/esm-node/runtime/routeTree/types.mjs +1 -0
  109. package/dist/esm-node/runtime/routeTree.mjs +1 -318
  110. package/dist/esm-node/runtime/rsc/CompositeComponent.mjs +18 -13
  111. package/dist/esm-node/runtime/rsc/RscNodeRenderer.mjs +4 -15
  112. package/dist/esm-node/runtime/rsc/client.mjs +6 -26
  113. package/dist/esm-node/runtime/rsc/flightSerialization.mjs +89 -0
  114. package/dist/esm-node/runtime/rsc/payloadErrors.mjs +50 -0
  115. package/dist/esm-node/runtime/rsc/payloadFetch.mjs +62 -0
  116. package/dist/esm-node/runtime/rsc/payloadRouter.mjs +12 -133
  117. package/dist/esm-node/runtime/rsc/payloadRoutes.mjs +51 -0
  118. package/dist/esm-node/runtime/rsc/payloadStorage.mjs +15 -0
  119. package/dist/esm-node/runtime/rsc/server.mjs +17 -21
  120. package/dist/esm-node/runtime/rsc/shared.mjs +22 -0
  121. package/dist/esm-node/runtime/rsc/treeGetter.mjs +35 -0
  122. package/dist/esm-node/runtime/ssrManagedTags.mjs +54 -0
  123. package/dist/esm-node/runtime/ssrPreload.mjs +52 -0
  124. package/dist/esm-node/runtime/ssrTypes.mjs +1 -0
  125. package/dist/esm-node/runtime/submitAction.mjs +121 -0
  126. package/dist/esm-node/runtime/utils.mjs +47 -75
  127. package/dist/types/cli/artifacts.d.ts +33 -0
  128. package/dist/types/cli/index.d.ts +2 -22
  129. package/dist/types/cli/tanstackTypes/canonicalRoutes.d.ts +22 -0
  130. package/dist/types/cli/tanstackTypes/shared.d.ts +20 -0
  131. package/dist/types/cli/tanstackTypes/source.d.ts +10 -0
  132. package/dist/types/cli/tanstackTypes.d.ts +3 -31
  133. package/dist/types/runtime/blockingSubscribe.d.ts +3 -0
  134. package/dist/types/runtime/clientBasepath.d.ts +1 -0
  135. package/dist/types/runtime/clientHydration.d.ts +19 -0
  136. package/dist/types/runtime/dataMutation.d.ts +3 -12
  137. package/dist/types/runtime/formData.d.ts +23 -0
  138. package/dist/types/runtime/plugin.d.ts +1 -1
  139. package/dist/types/runtime/plugin.node.d.ts +1 -1
  140. package/dist/types/runtime/pluginShared.d.ts +39 -0
  141. package/dist/types/runtime/routeTree/components.d.ts +7 -0
  142. package/dist/types/runtime/routeTree/construction.d.ts +5 -0
  143. package/dist/types/runtime/routeTree/index.d.ts +2 -0
  144. package/dist/types/runtime/routeTree/loaders.d.ts +4 -0
  145. package/dist/types/runtime/routeTree/paths.d.ts +3 -0
  146. package/dist/types/runtime/routeTree/staticData.d.ts +19 -0
  147. package/dist/types/runtime/routeTree/tanstackRoutes.d.ts +4 -0
  148. package/dist/types/runtime/routeTree/types.d.ts +75 -0
  149. package/dist/types/runtime/routeTree.d.ts +1 -9
  150. package/dist/types/runtime/rsc/CompositeComponent.d.ts +1 -2
  151. package/dist/types/runtime/rsc/RscNodeRenderer.d.ts +2 -3
  152. package/dist/types/runtime/rsc/client.d.ts +2 -0
  153. package/dist/types/runtime/rsc/flightSerialization.d.ts +3 -0
  154. package/dist/types/runtime/rsc/payloadErrors.d.ts +6 -0
  155. package/dist/types/runtime/rsc/payloadFetch.d.ts +10 -0
  156. package/dist/types/runtime/rsc/payloadRouter.d.ts +2 -10
  157. package/dist/types/runtime/rsc/payloadRoutes.d.ts +43 -0
  158. package/dist/types/runtime/rsc/payloadStorage.d.ts +5 -0
  159. package/dist/types/runtime/rsc/shared.d.ts +19 -0
  160. package/dist/types/runtime/rsc/treeGetter.d.ts +1 -0
  161. package/dist/types/runtime/ssrManagedTags.d.ts +7 -0
  162. package/dist/types/runtime/ssrPreload.d.ts +2 -0
  163. package/dist/types/runtime/ssrTypes.d.ts +43 -0
  164. package/dist/types/runtime/state.d.ts +1 -1
  165. package/dist/types/runtime/submitAction.d.ts +14 -0
  166. package/dist/types/runtime/types.d.ts +4 -9
  167. package/dist/types/runtime/utils.d.ts +4 -24
  168. package/package.json +30 -8
  169. package/rstest.config.mts +3 -0
  170. package/src/cli/artifacts.ts +255 -0
  171. package/src/cli/index.ts +7 -185
  172. package/src/cli/tanstackTypes/canonicalRoutes.ts +157 -0
  173. package/src/cli/tanstackTypes/shared.ts +119 -0
  174. package/src/cli/tanstackTypes/source.ts +405 -0
  175. package/src/cli/tanstackTypes.ts +4 -647
  176. package/src/runtime/blockingSubscribe.ts +48 -0
  177. package/src/runtime/clientBasepath.ts +12 -0
  178. package/src/runtime/clientHydration.ts +151 -0
  179. package/src/runtime/dataMutation.tsx +9 -306
  180. package/src/runtime/formData.ts +153 -0
  181. package/src/runtime/loaderBridge.ts +8 -3
  182. package/src/runtime/plugin.node.tsx +76 -291
  183. package/src/runtime/plugin.tsx +21 -257
  184. package/src/runtime/pluginShared.ts +112 -0
  185. package/src/runtime/prefetchLink.tsx +78 -15
  186. package/src/runtime/routeTree/components.ts +130 -0
  187. package/src/runtime/routeTree/construction.ts +238 -0
  188. package/src/runtime/routeTree/index.ts +7 -0
  189. package/src/runtime/routeTree/loaders.ts +232 -0
  190. package/src/runtime/routeTree/paths.ts +36 -0
  191. package/src/runtime/routeTree/staticData.ts +66 -0
  192. package/src/runtime/routeTree/tanstackRoutes.ts +36 -0
  193. package/src/runtime/routeTree/types.ts +87 -0
  194. package/src/runtime/routeTree.ts +5 -750
  195. package/src/runtime/rsc/CompositeComponent.tsx +29 -20
  196. package/src/runtime/rsc/RscNodeRenderer.tsx +9 -27
  197. package/src/runtime/rsc/client.tsx +12 -40
  198. package/src/runtime/rsc/flightSerialization.ts +158 -0
  199. package/src/runtime/rsc/payloadErrors.ts +73 -0
  200. package/src/runtime/rsc/payloadFetch.ts +97 -0
  201. package/src/runtime/rsc/payloadRouter.ts +29 -234
  202. package/src/runtime/rsc/payloadRoutes.ts +122 -0
  203. package/src/runtime/rsc/payloadStorage.ts +35 -0
  204. package/src/runtime/rsc/server.tsx +20 -29
  205. package/src/runtime/rsc/shared.ts +70 -0
  206. package/src/runtime/rsc/treeGetter.tsx +52 -0
  207. package/src/runtime/ssrManagedTags.ts +107 -0
  208. package/src/runtime/ssrPreload.ts +125 -0
  209. package/src/runtime/ssrTypes.ts +51 -0
  210. package/src/runtime/state.ts +4 -2
  211. package/src/runtime/submitAction.ts +194 -0
  212. package/src/runtime/types.ts +6 -13
  213. package/src/runtime/utils.tsx +76 -110
  214. package/src/types/react-server-dom-rspack.d.ts +56 -0
  215. package/tests/castRatchet.test.ts +85 -0
  216. package/tests/router/cli.test.ts +7 -0
  217. package/tests/router/dataMutation.test.tsx +59 -0
  218. package/tests/router/fixtures/router-gen.golden.txt +72 -0
  219. package/tests/router/generateRouteArtifacts.test.ts +106 -0
  220. package/tests/router/loaderBridge.test.ts +21 -0
  221. package/tests/router/prefetchLink.test.tsx +106 -59
  222. package/tests/router/prefetchLinkPreload.test.tsx +85 -0
  223. package/tests/router/routeTree.test.ts +46 -11
  224. package/tests/router/rsc.test.tsx +189 -0
  225. package/tests/router/ssrPreload.test.ts +30 -0
  226. package/tests/router/tanstackTypes.test.ts +254 -1
  227. package/dist/esm/runtime/pluginCore.mjs +0 -14
  228. package/dist/esm-node/runtime/pluginCore.mjs +0 -15
  229. package/dist/types/runtime/pluginCore.d.ts +0 -21
  230. package/src/runtime/pluginCore.ts +0 -48
@@ -1,752 +1,7 @@
1
1
  // @effect-diagnostics asyncFunction:off strictBooleanExpressions:off
2
2
 
3
- import { DefaultNotFound } from '@modern-js/runtime/context';
4
- import type { RouteObject } from '@modern-js/runtime-utils/router';
5
- import type {
6
- AnyRoute,
7
- AnyRouter,
8
- RootRoute as TanstackRootRoute,
9
- } from '@tanstack/react-router';
10
- import {
11
- createRootRoute,
12
- createRoute,
13
- notFound,
14
- rootRouteId,
15
- } from '@tanstack/react-router';
16
- import { createElement, type ElementType } from 'react';
17
- import {
18
- isRedirectResponse,
19
- isResponse,
20
- isTanstackRedirect,
21
- throwTanstackRedirect,
22
- } from './loaderBridge';
23
- import { withModernRouteMatchContext } from './outlet';
24
- import {
25
- isTanstackRscPayloadNavigationEnabled,
26
- loadTanstackRscRouteData,
27
- } from './rsc/payloadRouter';
28
-
29
- type RouteParams = Record<string, string>;
30
-
31
- type ModernLoader = (args: {
32
- request: Request;
33
- params: RouteParams;
34
- context?: unknown;
35
- }) => unknown | Promise<unknown>;
36
-
37
- type ModernShouldRevalidate = (args: {
38
- currentParams: RouteParams;
39
- currentUrl: URL;
40
- nextParams: RouteParams;
41
- nextUrl: URL;
42
- defaultShouldRevalidate?: boolean;
43
- }) => boolean | undefined;
44
-
45
- type TanstackLoaderContext = {
46
- abortController?: AbortController;
47
- cause?: string;
48
- signal?: AbortSignal;
49
- context?: {
50
- request?: Request;
51
- requestContext?: unknown;
52
- };
53
- location?:
54
- | string
55
- | {
56
- publicHref?: string;
57
- href?: string;
58
- url?: { href?: string };
59
- };
60
- params?: RouteParams;
61
- route?: {
62
- id?: string;
63
- };
64
- };
65
-
66
- type RouteRevalidationState = {
67
- currentParams?: RouteParams;
68
- currentUrl?: URL;
69
- };
70
-
71
- type ModernRouteObject = RouteObject & {
72
- ErrorBoundary?: unknown;
73
- HydrateFallback?: unknown;
74
- action?: unknown;
75
- clientData?: unknown;
76
- config?: { handle?: Record<string, unknown> } | unknown;
77
- file?: string;
78
- handle?: Record<string, unknown>;
79
- hasAction?: boolean;
80
- hasClientLoader?: boolean;
81
- hasLoader?: boolean;
82
- inValidSSRRoute?: boolean;
83
- isClientComponent?: boolean;
84
- lazyImport?: () => unknown;
85
- loader?: ModernLoader;
86
- loaderDeps?: unknown;
87
- pendingComponent?: unknown;
88
- shouldRevalidate?: ModernShouldRevalidate;
89
- validateSearch?: unknown;
90
- };
91
-
92
- type MutableTanstackRoute = AnyRoute & {
93
- addChildren: (children: AnyRoute[]) => void;
94
- id?: string;
95
- options: {
96
- component?: unknown;
97
- };
98
- };
99
-
100
- type TanstackRouteOptions = Record<string, unknown>;
101
- type TanstackRootRouteOptions = Record<string, unknown>;
102
- type ModernTanstackRootRoute = TanstackRootRoute;
103
- type ModernDeferredDataLike = {
104
- __modern_deferred?: unknown;
105
- data?: unknown;
106
- };
107
- type ModernRouteModule = {
108
- Component?: unknown;
109
- default?: unknown;
110
- };
111
- type PreloadableComponent = {
112
- (props: Record<string, unknown>): ReturnType<typeof createElement>;
113
- load?: () => Promise<unknown>;
114
- preload?: () => Promise<unknown>;
115
- };
116
- type RouteTreeOptions = {
117
- rscPayloadRouter?: boolean;
118
- };
119
-
120
- function createTanstackRoute(
121
- options: TanstackRouteOptions,
122
- ): MutableTanstackRoute {
123
- return createRoute(options as never) as unknown as MutableTanstackRoute;
124
- }
125
-
126
- function createTanstackRootRoute(
127
- options: TanstackRootRouteOptions,
128
- ): MutableTanstackRoute {
129
- return createRootRoute(options as never) as unknown as MutableTanstackRoute;
130
- }
131
-
132
- function wrapRouteComponentWithModernContext(
133
- route: MutableTanstackRoute,
134
- component: unknown,
135
- routeId?: string,
136
- ) {
137
- const routeMatchId = routeId || route.id;
138
- if (component && routeMatchId) {
139
- route.options.component = withModernRouteMatchContext(
140
- component,
141
- routeMatchId,
142
- ) as typeof route.options.component;
143
- }
144
- }
145
-
146
- function toTanstackPath(pathname: string): string {
147
- // TanStack Router uses `$param` and `$` (splat) style params.
148
- // Modern's conventional routing currently generates React Router style params (e.g. `:id`, `*`).
149
- //
150
- // We only convert the subset Modern generates today:
151
- // - `:id` -> `$id`
152
- // - `:id?` -> `{-$id}` (optional param)
153
- // - `*` -> `$`
154
- return pathname
155
- .split('/')
156
- .map(segment => {
157
- if (!segment) {
158
- return segment;
159
- }
160
- if (segment === '*') {
161
- return '$';
162
- }
163
- if (segment.startsWith(':')) {
164
- const name = segment.slice(1);
165
- if (name.endsWith('?')) {
166
- return `{-$${name.slice(0, -1)}}`;
167
- }
168
- return `$${name}`;
169
- }
170
- return segment;
171
- })
172
- .join('/');
173
- }
174
-
175
- function isModernDeferredData(
176
- value: unknown,
177
- ): value is ModernDeferredDataLike & { data: Record<string, unknown> } {
178
- if (!value || typeof value !== 'object') {
179
- return false;
180
- }
181
-
182
- const deferred = value as ModernDeferredDataLike;
183
- return (
184
- deferred.__modern_deferred === true &&
185
- Boolean(deferred.data) &&
186
- typeof deferred.data === 'object' &&
187
- !Array.isArray(deferred.data)
188
- );
189
- }
190
-
191
- function normalizeModernLoaderResult(result: unknown): unknown {
192
- return isModernDeferredData(result) ? result.data : result;
193
- }
194
-
195
- function normalizeModernLoaderResponse(result: unknown): unknown {
196
- if (isResponse(result)) {
197
- if (isRedirectResponse(result)) {
198
- const location = result.headers.get('Location') || '/';
199
- throwTanstackRedirect(location);
200
- }
201
- if (result.status === 404) {
202
- throw notFound();
203
- }
204
- }
205
-
206
- return normalizeModernLoaderResult(result);
207
- }
208
-
209
- function pickRouteModuleComponent(
210
- routeModule: unknown,
211
- seen: Set<unknown> = new Set(),
212
- ): ElementType<Record<string, unknown>> | undefined {
213
- if (
214
- typeof routeModule === 'function' ||
215
- (routeModule &&
216
- typeof routeModule === 'object' &&
217
- '$$typeof' in routeModule)
218
- ) {
219
- return routeModule as ElementType<Record<string, unknown>>;
220
- }
221
-
222
- if (!routeModule || typeof routeModule !== 'object') {
223
- return undefined;
224
- }
225
- if (seen.has(routeModule)) {
226
- return undefined;
227
- }
228
- seen.add(routeModule);
229
-
230
- const module = routeModule as ModernRouteModule;
231
- for (const candidate of [module.default, module.Component]) {
232
- const component = pickRouteModuleComponent(candidate, seen);
233
- if (component) {
234
- return component;
235
- }
236
- }
237
-
238
- return undefined;
239
- }
240
-
241
- function createServerLazyImportComponent(
242
- lazyImport: () => unknown,
243
- fallbackComponent?: unknown,
244
- ): PreloadableComponent | unknown {
245
- if (typeof document !== 'undefined') {
246
- return fallbackComponent;
247
- }
248
-
249
- let resolvedComponent: ElementType<Record<string, unknown>> | undefined;
250
- let pendingLoad: Promise<unknown> | undefined;
251
-
252
- const load = async () => {
253
- if (resolvedComponent) {
254
- return resolvedComponent;
255
- }
256
-
257
- const routeModule = await lazyImport();
258
- const component = pickRouteModuleComponent(routeModule);
259
- if (component) {
260
- resolvedComponent = component;
261
- }
262
- return resolvedComponent;
263
- };
264
-
265
- const Component: PreloadableComponent = props => {
266
- if (resolvedComponent) {
267
- return createElement(resolvedComponent, props);
268
- }
269
-
270
- pendingLoad ||= load();
271
- throw pendingLoad;
272
- };
273
- Component.load = load;
274
- Component.preload = load;
275
-
276
- return Component;
277
- }
278
-
279
- function createModernRequest(input: string, signal: AbortSignal) {
280
- return new Request(input, { signal });
281
- }
282
-
283
- function getModernUrlFromLoaderContext(ctx: TanstackLoaderContext): URL {
284
- const href =
285
- typeof ctx?.location === 'string'
286
- ? ctx.location
287
- : ctx?.location?.publicHref ||
288
- ctx?.location?.href ||
289
- ctx?.location?.url?.href ||
290
- '/';
291
- const baseRequest: Request | undefined =
292
- ctx?.context?.request instanceof Request ? ctx.context.request : undefined;
293
- const baseUrl =
294
- baseRequest?.url ||
295
- (typeof window !== 'undefined' ? window.origin : 'http://localhost');
296
-
297
- return new URL(href || '/', baseUrl);
298
- }
299
-
300
- function rememberRouteLocation(
301
- state: RouteRevalidationState,
302
- ctx: TanstackLoaderContext,
303
- ) {
304
- state.currentUrl = getModernUrlFromLoaderContext(ctx);
305
- state.currentParams = ctx?.params || {};
306
- }
307
-
308
- function createModernShouldReload(
309
- shouldRevalidate: unknown,
310
- state: RouteRevalidationState,
311
- ) {
312
- if (typeof shouldRevalidate !== 'function') {
313
- return undefined;
314
- }
315
- const revalidate = shouldRevalidate as ModernShouldRevalidate;
316
-
317
- return (ctx: TanstackLoaderContext) => {
318
- const nextUrl = getModernUrlFromLoaderContext(ctx);
319
- const nextParams = ctx?.params || {};
320
- const result = revalidate({
321
- currentUrl: state.currentUrl || nextUrl,
322
- currentParams: state.currentParams || nextParams,
323
- nextUrl,
324
- nextParams,
325
- // Returning undefined keeps TanStack's native stale-reload default.
326
- defaultShouldRevalidate: undefined,
327
- });
328
-
329
- state.currentUrl = nextUrl;
330
- state.currentParams = nextParams;
331
-
332
- return typeof result === 'boolean' ? result : undefined;
333
- };
334
- }
335
-
336
- function isRouteObjectPathlessLayout(route: RouteObject) {
337
- return !route.path && !route.index;
338
- }
339
-
340
- function isRouteObjectSplatRoute(route: RouteObject) {
341
- return typeof route.path === 'string' && route.path.includes('*');
342
- }
343
-
344
- function mapParamsForRouteObjectLoader({
345
- route,
346
- params,
347
- }: {
348
- route: RouteObject;
349
- params: RouteParams;
350
- }) {
351
- if (isRouteObjectSplatRoute(route)) {
352
- const { _splat, ...rest } = params as RouteParams & {
353
- _splat?: string;
354
- };
355
- if (typeof _splat !== 'undefined') {
356
- return { ...rest, '*': _splat };
357
- }
358
- return rest;
359
- }
360
- return params;
361
- }
362
-
363
- function wrapRouteObjectLoader(
364
- route: RouteObject,
365
- revalidationState?: RouteRevalidationState,
366
- options: RouteTreeOptions = {},
367
- ) {
368
- const modernRoute = route as ModernRouteObject;
369
- const routeLoader = modernRoute.loader;
370
- if (typeof routeLoader !== 'function') {
371
- return undefined;
372
- }
373
-
374
- return async (ctx: TanstackLoaderContext) => {
375
- try {
376
- if (revalidationState) {
377
- rememberRouteLocation(revalidationState, ctx);
378
- }
379
-
380
- if (typeof modernRoute.lazyImport === 'function') {
381
- try {
382
- await modernRoute.lazyImport();
383
- } catch {}
384
- }
385
-
386
- const signal: AbortSignal =
387
- ctx?.abortController?.signal ||
388
- ctx?.signal ||
389
- new AbortController().signal;
390
- const baseRequest: Request | undefined =
391
- ctx?.context?.request instanceof Request
392
- ? ctx.context.request
393
- : undefined;
394
-
395
- const href =
396
- typeof ctx?.location === 'string'
397
- ? ctx.location
398
- : ctx?.location?.publicHref ||
399
- ctx?.location?.href ||
400
- ctx?.location?.url?.href ||
401
- '';
402
-
403
- const request =
404
- baseRequest !== undefined
405
- ? new Request(baseRequest, { signal })
406
- : createModernRequest(href, signal);
407
-
408
- const params = mapParamsForRouteObjectLoader({
409
- route,
410
- params: ctx.params || {},
411
- });
412
-
413
- const loadModernData = async () => {
414
- const result = await routeLoader({
415
- request,
416
- params,
417
- context: ctx?.context?.requestContext,
418
- });
419
-
420
- return normalizeModernLoaderResponse(result);
421
- };
422
-
423
- if (options.rscPayloadRouter && isTanstackRscPayloadNavigationEnabled()) {
424
- return loadTanstackRscRouteData({
425
- hasClientLoader:
426
- modernRoute.hasClientLoader ||
427
- typeof modernRoute.clientData !== 'undefined',
428
- loadClientData: loadModernData,
429
- request,
430
- routeId: ctx.route?.id,
431
- });
432
- }
433
-
434
- return loadModernData();
435
- } catch (err) {
436
- if (isResponse(err)) {
437
- if (isTanstackRedirect(err)) {
438
- throw err;
439
- }
440
- if (isRedirectResponse(err)) {
441
- const location = err.headers.get('Location') || '/';
442
- throwTanstackRedirect(location);
443
- }
444
- if (err.status === 404) {
445
- throw notFound();
446
- }
447
- }
448
- throw err;
449
- }
450
- };
451
- }
452
-
453
- function toRouteComponent(routeObject: RouteObject): unknown {
454
- const route = routeObject as ModernRouteObject;
455
- const lazyImport =
456
- typeof route.lazyImport === 'function' ? route.lazyImport : undefined;
457
- const fallbackComponent = route.Component
458
- ? route.Component
459
- : route.element
460
- ? () => route.element
461
- : undefined;
462
-
463
- if (lazyImport && fallbackComponent) {
464
- return createServerLazyImportComponent(lazyImport, fallbackComponent);
465
- }
466
-
467
- if (route.Component) {
468
- return route.Component;
469
- }
470
- const element = route.element;
471
- if (element) {
472
- return () => element;
473
- }
474
- return undefined;
475
- }
476
-
477
- function toErrorComponent(routeObject: RouteObject): unknown {
478
- const route = routeObject as ModernRouteObject;
479
- if (route.ErrorBoundary) {
480
- return route.ErrorBoundary;
481
- }
482
- if (route.errorElement) {
483
- return () => route.errorElement;
484
- }
485
- return undefined;
486
- }
487
-
488
- function toPendingComponent(routeObject: RouteObject): unknown {
489
- const route = routeObject as ModernRouteObject;
490
- return route.HydrateFallback || route.pendingComponent || undefined;
491
- }
492
-
493
- function mergeModernRouteHandle(route: {
494
- config?: { handle?: Record<string, unknown> } | unknown;
495
- handle?: Record<string, unknown>;
496
- }) {
497
- const config = route.config as { handle?: Record<string, unknown> } | null;
498
- const handle = {
499
- ...route.handle,
500
- ...(config && typeof config === 'object' ? config.handle : {}),
501
- };
502
-
503
- return Object.keys(handle).length > 0 ? handle : undefined;
504
- }
505
-
506
- function createRouteStaticData(opts: {
507
- modernRouteId?: string;
508
- modernRouteAction?: unknown;
509
- modernRouteHandle?: unknown;
510
- modernRouteHasAction?: boolean;
511
- modernRouteHasClientLoader?: boolean;
512
- modernRouteHasLoader?: boolean;
513
- modernRouteIsClientComponent?: boolean;
514
- modernRouteLoader?: unknown;
515
- modernRouteShouldRevalidate?: unknown;
516
- }) {
517
- const staticData: Record<string, unknown> = {};
518
-
519
- if (opts.modernRouteId) {
520
- staticData.modernRouteId = opts.modernRouteId;
521
- }
522
-
523
- if (opts.modernRouteAction) {
524
- staticData.modernRouteAction = opts.modernRouteAction;
525
- }
526
-
527
- if (opts.modernRouteHandle) {
528
- staticData.modernRouteHandle = opts.modernRouteHandle;
529
- }
530
-
531
- if (opts.modernRouteHasAction) {
532
- staticData.modernRouteHasAction = true;
533
- }
534
-
535
- if (opts.modernRouteHasClientLoader) {
536
- staticData.modernRouteHasClientLoader = true;
537
- }
538
-
539
- if (opts.modernRouteHasLoader) {
540
- staticData.modernRouteHasLoader = true;
541
- }
542
-
543
- if (opts.modernRouteIsClientComponent) {
544
- staticData.modernRouteIsClientComponent = true;
545
- }
546
-
547
- if (opts.modernRouteLoader) {
548
- staticData.modernRouteLoader = opts.modernRouteLoader;
549
- }
550
-
551
- if (opts.modernRouteShouldRevalidate) {
552
- staticData.modernRouteShouldRevalidate = opts.modernRouteShouldRevalidate;
553
- }
554
-
555
- return Object.keys(staticData).length > 0 ? staticData : undefined;
556
- }
557
-
558
- function createRouteFromRouteObject(opts: {
559
- options?: RouteTreeOptions;
560
- parent: AnyRoute;
561
- routeObject: RouteObject;
562
- }): AnyRoute {
563
- const { options = {}, parent, routeObject } = opts;
564
- const modernRouteObject = routeObject as ModernRouteObject;
565
- const revalidationState: RouteRevalidationState = {};
566
- const shouldRevalidate = modernRouteObject.shouldRevalidate;
567
- const shouldReload = createModernShouldReload(
568
- shouldRevalidate,
569
- revalidationState,
570
- );
571
-
572
- const stableFallbackId =
573
- routeObject.id || modernRouteObject.file || routeObject.path || 'pathless';
574
-
575
- const component = toRouteComponent(routeObject);
576
- const base: TanstackRouteOptions = {
577
- getParentRoute: () => parent,
578
- component,
579
- pendingComponent: toPendingComponent(routeObject),
580
- errorComponent: toErrorComponent(routeObject),
581
- validateSearch: modernRouteObject.validateSearch,
582
- loaderDeps: modernRouteObject.loaderDeps,
583
- staticData: createRouteStaticData({
584
- modernRouteId: routeObject.id,
585
- modernRouteAction: modernRouteObject.action,
586
- modernRouteHandle: mergeModernRouteHandle(modernRouteObject),
587
- modernRouteHasAction:
588
- modernRouteObject.hasAction || Boolean(modernRouteObject.action),
589
- modernRouteHasClientLoader:
590
- modernRouteObject.hasClientLoader ||
591
- typeof modernRouteObject.clientData !== 'undefined',
592
- modernRouteHasLoader:
593
- modernRouteObject.hasLoader ||
594
- typeof modernRouteObject.loader === 'function',
595
- modernRouteIsClientComponent: modernRouteObject.isClientComponent,
596
- modernRouteLoader: modernRouteObject.loader,
597
- modernRouteShouldRevalidate: shouldRevalidate,
598
- }),
599
- loader: wrapRouteObjectLoader(routeObject, revalidationState, options),
600
- };
601
- if (modernRouteObject.inValidSSRRoute) {
602
- base.ssr = false;
603
- }
604
- if (shouldReload) {
605
- base.shouldReload = shouldReload;
606
- }
607
-
608
- if (isRouteObjectPathlessLayout(routeObject)) {
609
- base.id = stableFallbackId;
610
- } else {
611
- base.path = routeObject.index
612
- ? '/'
613
- : toTanstackPath((routeObject.path as string) || '');
614
- }
615
-
616
- const route = createTanstackRoute(base);
617
- wrapRouteComponentWithModernContext(route, component, routeObject.id);
618
-
619
- const children = routeObject.children;
620
- if (children && children.length > 0) {
621
- const childRoutes = children.map((child: RouteObject) =>
622
- createRouteFromRouteObject({
623
- options,
624
- parent: route,
625
- routeObject: child,
626
- }),
627
- );
628
- route.addChildren(childRoutes);
629
- }
630
-
631
- return route;
632
- }
633
-
634
- function getRootLikeRouteObject(routes: RouteObject[]) {
635
- return routes.find(route => route.path === '/' && !route.index);
636
- }
637
-
638
- export function createRouteTreeFromRouteObjects(
639
- routes: RouteObject[],
640
- options: RouteTreeOptions = {},
641
- ): ModernTanstackRootRoute {
642
- const rootLikeRoute = getRootLikeRouteObject(routes) as
643
- | ModernRouteObject
644
- | undefined;
645
- const rootRevalidationState: RouteRevalidationState = {};
646
- const rootShouldRevalidate = rootLikeRoute?.shouldRevalidate;
647
- const rootShouldReload = createModernShouldReload(
648
- rootShouldRevalidate,
649
- rootRevalidationState,
650
- );
651
-
652
- const rootComponent = rootLikeRoute
653
- ? toRouteComponent(rootLikeRoute)
654
- : undefined;
655
- const rootRouteOptions: TanstackRootRouteOptions = {
656
- component: rootComponent,
657
- pendingComponent: rootLikeRoute
658
- ? toPendingComponent(rootLikeRoute)
659
- : undefined,
660
- errorComponent: rootLikeRoute ? toErrorComponent(rootLikeRoute) : undefined,
661
- validateSearch: rootLikeRoute?.validateSearch,
662
- loaderDeps: rootLikeRoute?.loaderDeps,
663
- notFoundComponent: DefaultNotFound,
664
- staticData: createRouteStaticData({
665
- modernRouteId: rootLikeRoute?.id,
666
- modernRouteAction: rootLikeRoute?.action,
667
- modernRouteHandle: rootLikeRoute
668
- ? mergeModernRouteHandle(rootLikeRoute)
669
- : undefined,
670
- modernRouteHasAction:
671
- rootLikeRoute?.hasAction || Boolean(rootLikeRoute?.action),
672
- modernRouteHasClientLoader:
673
- rootLikeRoute?.hasClientLoader ||
674
- typeof rootLikeRoute?.clientData !== 'undefined',
675
- modernRouteHasLoader:
676
- rootLikeRoute?.hasLoader || typeof rootLikeRoute?.loader === 'function',
677
- modernRouteIsClientComponent: rootLikeRoute?.isClientComponent,
678
- modernRouteLoader: rootLikeRoute?.loader,
679
- modernRouteShouldRevalidate: rootShouldRevalidate,
680
- }),
681
- loader: rootLikeRoute
682
- ? wrapRouteObjectLoader(rootLikeRoute, rootRevalidationState, options)
683
- : undefined,
684
- };
685
- if (rootShouldReload) {
686
- rootRouteOptions.shouldReload = rootShouldReload;
687
- }
688
- if (rootLikeRoute?.inValidSSRRoute) {
689
- rootRouteOptions.ssr = false;
690
- }
691
-
692
- const rootRoute = createTanstackRootRoute(rootRouteOptions);
693
- if (rootComponent) {
694
- rootRoute.options.component = withModernRouteMatchContext(
695
- rootComponent,
696
- rootRouteId,
697
- ) as typeof rootRoute.options.component;
698
- }
699
-
700
- const topLevel = rootLikeRoute
701
- ? [
702
- ...((rootLikeRoute.children as RouteObject[] | undefined) || []),
703
- ...routes.filter(route => route !== rootLikeRoute),
704
- ]
705
- : routes;
706
-
707
- const childRoutes = topLevel.map(routeObject =>
708
- createRouteFromRouteObject({ options, parent: rootRoute, routeObject }),
709
- );
710
-
711
- rootRoute.addChildren(childRoutes);
712
- return rootRoute as unknown as ModernTanstackRootRoute;
713
- }
714
-
715
- export function getModernRouteIdsFromMatches(router: AnyRouter): string[] {
716
- const matches = router.state.matches || [];
717
- const routesById = (
718
- router as AnyRouter & {
719
- routesById?: Record<
720
- string,
721
- {
722
- options?: {
723
- staticData?: { modernRouteId?: unknown };
724
- };
725
- }
726
- >;
727
- }
728
- ).routesById;
729
- const ids = matches
730
- .map(match => {
731
- const normalizedMatch = match as {
732
- route?: {
733
- options?: {
734
- staticData?: { modernRouteId?: unknown };
735
- };
736
- };
737
- routeId?: unknown;
738
- };
739
- const routeId =
740
- typeof normalizedMatch.routeId === 'string'
741
- ? normalizedMatch.routeId
742
- : undefined;
743
- return (
744
- normalizedMatch.route?.options?.staticData?.modernRouteId ??
745
- (routeId
746
- ? routesById?.[routeId]?.options?.staticData?.modernRouteId
747
- : undefined)
748
- );
749
- })
750
- .filter((id): id is string => typeof id === 'string');
751
- return Array.from(new Set(ids));
752
- }
3
+ export {
4
+ createRouteTreeFromRouteObjects,
5
+ getModernRouteIdsFromMatches,
6
+ pickRouteModuleComponent,
7
+ } from './routeTree/index';