@bleedingdev/modern-js-plugin-tanstack 3.2.0-ultramodern.8 → 3.2.0-ultramodern.81

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.
@@ -127,6 +127,7 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
127
127
  const imports = [];
128
128
  const statements = [];
129
129
  const loaderImportMap = new Map();
130
+ const usedRouteVarNames = new Set();
130
131
  let loaderIndex = 0;
131
132
  let routeIndex = 0;
132
133
  const getImportNamesForLoader = async (aliasedNoExtPath, inline, hasAction)=>{
@@ -160,10 +161,17 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
160
161
  actionName
161
162
  };
162
163
  };
164
+ const reserveRouteVarName = (preferred)=>{
165
+ let candidate = preferred;
166
+ let suffix = 1;
167
+ while(usedRouteVarNames.has(candidate))candidate = `${preferred}_${suffix++}`;
168
+ usedRouteVarNames.add(candidate);
169
+ return candidate;
170
+ };
163
171
  const createRouteVarName = (route)=>{
164
172
  const id = route.id;
165
173
  const base = id ? makeLegalIdentifier(id) : `r_${routeIndex++}`;
166
- return `route_${base}`;
174
+ return reserveRouteVarName(`route_${base}`);
167
175
  };
168
176
  const buildRoute = async (opts)=>{
169
177
  const { parentVar, route } = opts;
@@ -192,14 +200,16 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
192
200
  actionName
193
201
  });
194
202
  if (staticDataSnippet) routeOpts.push(staticDataSnippet);
195
- statements.push(`const ${varName} = createRoute({\n ${routeOpts.join('\n ')}\n});`);
196
203
  const children = route.children;
204
+ const hasChildren = Boolean(children && children.length > 0);
205
+ const routeCtorVarName = hasChildren ? reserveRouteVarName(`${varName}__base`) : varName;
206
+ statements.push(`const ${routeCtorVarName} = createRoute({\n ${routeOpts.join('\n ')}\n});`);
197
207
  if (children && children.length > 0) {
198
208
  const childVars = await Promise.all(children.map((child)=>buildRoute({
199
- parentVar: varName,
209
+ parentVar: routeCtorVarName,
200
210
  route: child
201
211
  })));
202
- statements.push(`${varName}.addChildren([${childVars.join(', ')}]);`);
212
+ statements.push(`const ${varName} = ${routeCtorVarName}.addChildren([${childVars.join(', ')}]);`);
203
213
  }
204
214
  return varName;
205
215
  };
@@ -246,7 +256,7 @@ function isRedirectResponse(res: Response) {
246
256
  }
247
257
 
248
258
  function throwTanstackRedirect(location: string) {
249
- const target = location || '/';
259
+ const target = location.length > 0 ? location : '/';
250
260
  try {
251
261
  void new URL(target);
252
262
  throw redirect({ href: target });
@@ -272,21 +282,87 @@ function createRouteStaticData(opts: {
272
282
  modernRouteAction?: unknown;
273
283
  modernRouteLoader?: unknown;
274
284
  }) {
275
- const staticData: Record<string, unknown> = {};
285
+ const staticData: {
286
+ modernRouteId?: string;
287
+ modernRouteAction?: unknown;
288
+ modernRouteLoader?: unknown;
289
+ } = {};
276
290
 
277
- if (opts.modernRouteId) {
291
+ if (typeof opts.modernRouteId === 'string' && opts.modernRouteId.length > 0) {
278
292
  staticData.modernRouteId = opts.modernRouteId;
279
293
  }
280
294
 
281
- if (opts.modernRouteLoader) {
295
+ if (typeof opts.modernRouteLoader !== 'undefined') {
282
296
  staticData.modernRouteLoader = opts.modernRouteLoader;
283
297
  }
284
298
 
285
- if (opts.modernRouteAction) {
299
+ if (typeof opts.modernRouteAction !== 'undefined') {
286
300
  staticData.modernRouteAction = opts.modernRouteAction;
287
301
  }
288
302
 
289
- return Object.keys(staticData).length > 0 ? staticData : undefined;
303
+ return staticData;
304
+ }
305
+
306
+ function getLoaderSignal(ctx: any): AbortSignal {
307
+ const abortSignal = ctx?.abortController?.signal;
308
+ if (abortSignal instanceof AbortSignal) {
309
+ return abortSignal;
310
+ }
311
+ if (ctx?.signal instanceof AbortSignal) {
312
+ return ctx.signal;
313
+ }
314
+ return new AbortController().signal;
315
+ }
316
+
317
+ function getLoaderHref(ctx: any): string {
318
+ if (typeof ctx?.location === 'string') {
319
+ return ctx.location;
320
+ }
321
+
322
+ const publicHref = ctx?.location?.publicHref;
323
+ if (typeof publicHref === 'string') {
324
+ return publicHref;
325
+ }
326
+
327
+ const href = ctx?.location?.href;
328
+ if (typeof href === 'string') {
329
+ return href;
330
+ }
331
+
332
+ const urlHref = ctx?.location?.url?.href;
333
+ return typeof urlHref === 'string' ? urlHref : '';
334
+ }
335
+
336
+ function getLoaderParams(ctx: any): Record<string, string> {
337
+ return typeof ctx?.params === 'object' && ctx.params !== null ? ctx.params : {};
338
+ }
339
+
340
+ function handleModernLoaderResult<LoaderResult>(result: LoaderResult): LoaderResult {
341
+ if (isResponse(result)) {
342
+ if (isRedirectResponse(result)) {
343
+ const location = result.headers.get('Location') ?? '/';
344
+ throwTanstackRedirect(location);
345
+ }
346
+ if (result.status === 404) {
347
+ throw notFound();
348
+ }
349
+ }
350
+
351
+ return result;
352
+ }
353
+
354
+ function handleModernLoaderError(err: unknown): never {
355
+ if (isResponse(err)) {
356
+ if (isRedirectResponse(err)) {
357
+ const location = err.headers.get('Location') ?? '/';
358
+ throwTanstackRedirect(location);
359
+ }
360
+ if (err.status === 404) {
361
+ throw notFound();
362
+ }
363
+ }
364
+
365
+ throw err;
290
366
  }
291
367
 
292
368
  function modernLoaderToTanstack<TLoader extends (args: any) => any>(
@@ -295,57 +371,31 @@ function modernLoaderToTanstack<TLoader extends (args: any) => any>(
295
371
  ) {
296
372
  type LoaderResult = Awaited<ReturnType<TLoader>>;
297
373
 
298
- return async (ctx: any): Promise<LoaderResult> => {
374
+ return (ctx: any): Promise<LoaderResult> => {
299
375
  try {
300
- const signal: AbortSignal =
301
- ctx?.abortController?.signal ||
302
- ctx?.signal ||
303
- new AbortController().signal;
376
+ const signal = getLoaderSignal(ctx);
304
377
  const baseRequest: Request | undefined =
305
378
  ctx?.context?.request instanceof Request ? ctx.context.request : undefined;
306
379
 
307
- const href =
308
- typeof ctx?.location === 'string'
309
- ? ctx.location
310
- : ctx?.location?.publicHref ||
311
- ctx?.location?.href ||
312
- ctx?.location?.url?.href ||
313
- '';
380
+ const href = getLoaderHref(ctx);
314
381
 
315
- const request = baseRequest
382
+ const request = baseRequest !== undefined
316
383
  ? new Request(baseRequest, { signal })
317
384
  : new Request(href, { signal });
318
385
 
319
- const params = mapParamsForModernLoader(ctx?.params || {}, opts.hasSplat);
320
-
321
- const result = await (modernLoader as any)({
322
- request,
323
- params,
324
- context: ctx?.context?.requestContext,
325
- });
326
-
327
- if (isResponse(result)) {
328
- if (isRedirectResponse(result)) {
329
- const location = result.headers.get('Location') || '/';
330
- throwTanstackRedirect(location);
331
- }
332
- if (result.status === 404) {
333
- throw notFound();
334
- }
335
- }
386
+ const params = mapParamsForModernLoader(getLoaderParams(ctx), opts.hasSplat);
336
387
 
337
- return result as LoaderResult;
388
+ return Promise.resolve(
389
+ (modernLoader as any)({
390
+ request,
391
+ params,
392
+ context: ctx?.context?.requestContext,
393
+ }),
394
+ )
395
+ .then((result: LoaderResult) => handleModernLoaderResult(result))
396
+ .catch(handleModernLoaderError);
338
397
  } catch (err) {
339
- if (isResponse(err)) {
340
- if (isRedirectResponse(err)) {
341
- const location = err.headers.get('Location') || '/';
342
- throwTanstackRedirect(location);
343
- }
344
- if (err.status === 404) {
345
- throw notFound();
346
- }
347
- }
348
- throw err;
398
+ handleModernLoaderError(err);
349
399
  }
350
400
  };
351
401
  }
@@ -37,6 +37,7 @@ const external_react_namespaceObject = require("react");
37
37
  const external_basepathRewrite_js_namespaceObject = require("./basepathRewrite.js");
38
38
  const external_hooks_js_namespaceObject = require("./hooks.js");
39
39
  const external_lifecycle_js_namespaceObject = require("./lifecycle.js");
40
+ const external_prefetchLink_js_namespaceObject = require("./prefetchLink.js");
40
41
  const external_routeTree_js_namespaceObject = require("./routeTree.js");
41
42
  const client_js_namespaceObject = require("./rsc/client.js");
42
43
  const external_utils_js_namespaceObject = require("./utils.js");
@@ -102,6 +103,7 @@ const tanstackRouterPlugin = (userConfig = {})=>{
102
103
  }
103
104
  }
104
105
  context.router = {
106
+ Link: external_prefetchLink_js_namespaceObject.Link,
105
107
  useMatches: react_router_namespaceObject.useMatches,
106
108
  useLocation: react_router_namespaceObject.useLocation,
107
109
  useNavigate: react_router_namespaceObject.useNavigate,
@@ -214,11 +216,8 @@ const tanstackRouterPlugin = (userConfig = {})=>{
214
216
  router,
215
217
  runtimeContext: runtimeState
216
218
  });
217
- const RouterContent = hasSSRBootstrap ? /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_react_namespaceObject.Suspense, {
218
- fallback: null,
219
- children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(client_namespaceObject.RouterClient, {
220
- router: router
221
- })
219
+ const RouterContent = hasSSRBootstrap ? /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(client_namespaceObject.RouterClient, {
220
+ router: router
222
221
  }) : /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(react_router_namespaceObject.RouterProvider, {
223
222
  router: router
224
223
  });
@@ -34,7 +34,7 @@ const node_namespaceObject = require("@modern-js/runtime-utils/node");
34
34
  const time_namespaceObject = require("@modern-js/runtime-utils/time");
35
35
  const constants_namespaceObject = require("@modern-js/utils/universal/constants");
36
36
  const react_router_namespaceObject = require("@tanstack/react-router");
37
- const server_namespaceObject = require("@tanstack/react-router/ssr/server");
37
+ const server_namespaceObject = require("@tanstack/router-core/ssr/server");
38
38
  const external_react_namespaceObject = require("react");
39
39
  const external_basepathRewrite_js_namespaceObject = require("./basepathRewrite.js");
40
40
  const external_hooks_js_namespaceObject = require("./hooks.js");
@@ -46,12 +46,28 @@ const setTanstackRscServerPayload = (payload)=>{
46
46
  const storageContext = node_namespaceObject.storage.useContext?.();
47
47
  if (storageContext) storageContext.serverPayload = payload;
48
48
  };
49
+ function isPromiseLike(value) {
50
+ return Boolean(value && 'function' == typeof value.then);
51
+ }
49
52
  function isPreloadableRouteComponent(component) {
50
53
  if (!component || 'function' != typeof component) return false;
51
54
  const preloadable = component;
52
55
  return 'function' == typeof preloadable.load || 'function' == typeof preloadable.preload;
53
56
  }
57
+ function isReactLazyRouteComponent(component) {
58
+ return Boolean(component) && 'object' == typeof component && 'function' == typeof component._init && '_payload' in component;
59
+ }
60
+ async function preloadReactLazyRouteComponent(component) {
61
+ try {
62
+ component._init?.(component._payload);
63
+ } catch (thrown) {
64
+ if (!isPromiseLike(thrown)) throw thrown;
65
+ await thrown;
66
+ component._init?.(component._payload);
67
+ }
68
+ }
54
69
  async function preloadRouteComponent(component) {
70
+ if (isReactLazyRouteComponent(component)) return void await preloadReactLazyRouteComponent(component);
55
71
  if (!isPreloadableRouteComponent(component)) return;
56
72
  if ('function' == typeof component.load) return void await component.load({});
57
73
  await component.preload?.({});
@@ -235,10 +251,12 @@ const tanstackRouterPlugin = (userConfig = {})=>{
235
251
  await preloadMatchedRouteComponents(serverRouter);
236
252
  context.ssrContext?.response.status(tanstackRouter.state.statusCode);
237
253
  await serverRouter.serverSsr?.dehydrate?.();
238
- await waitForRouterSerialization(serverRouter);
239
- if (isRSCNavigation) setTanstackRscServerPayload((0, payloadRouter_js_namespaceObject.createTanstackRscServerPayload)(serverRouter, {
240
- omitClientLoaderData: true
241
- }));
254
+ if (isRSCNavigation) {
255
+ await waitForRouterSerialization(serverRouter);
256
+ setTanstackRscServerPayload((0, payloadRouter_js_namespaceObject.createTanstackRscServerPayload)(serverRouter, {
257
+ omitClientLoaderData: true
258
+ }));
259
+ }
242
260
  const ssrScriptTags = serverRouter.serverSsr?.takeBufferedScripts?.();
243
261
  const hydrationScripts = routerManagedTagsToHtml(ssrScriptTags);
244
262
  const matchedRouteIds = (0, external_routeTree_js_namespaceObject.getModernRouteIdsFromMatches)(serverRouter);
@@ -276,11 +294,8 @@ const tanstackRouterPlugin = (userConfig = {})=>{
276
294
  if (!router) return App ? /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(App, {
277
295
  ...props
278
296
  }) : null;
279
- const routerWrapper = /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_react_namespaceObject.Suspense, {
280
- fallback: null,
281
- children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(react_router_namespaceObject.RouterProvider, {
282
- router: router
283
- })
297
+ const routerWrapper = /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(react_router_namespaceObject.RouterProvider, {
298
+ router: router
284
299
  });
285
300
  return App ? /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(App, {
286
301
  children: routerWrapper
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.n = (module)=>{
5
+ var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
6
+ __webpack_require__.d(getter, {
7
+ a: getter
8
+ });
9
+ return getter;
10
+ };
11
+ })();
12
+ (()=>{
13
+ __webpack_require__.d = (exports1, definition)=>{
14
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
15
+ enumerable: true,
16
+ get: definition[key]
17
+ });
18
+ };
19
+ })();
20
+ (()=>{
21
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
22
+ })();
23
+ (()=>{
24
+ __webpack_require__.r = (exports1)=>{
25
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
26
+ value: 'Module'
27
+ });
28
+ Object.defineProperty(exports1, '__esModule', {
29
+ value: true
30
+ });
31
+ };
32
+ })();
33
+ var __webpack_exports__ = {};
34
+ __webpack_require__.r(__webpack_exports__);
35
+ __webpack_require__.d(__webpack_exports__, {
36
+ default: ()=>external_plugin_node_js_default(),
37
+ tanstackRouterPlugin: ()=>external_plugin_node_js_namespaceObject.tanstackRouterPlugin
38
+ });
39
+ const external_plugin_node_js_namespaceObject = require("./plugin.node.js");
40
+ var external_plugin_node_js_default = /*#__PURE__*/ __webpack_require__.n(external_plugin_node_js_namespaceObject);
41
+ exports["default"] = __webpack_exports__["default"];
42
+ exports.tanstackRouterPlugin = __webpack_exports__.tanstackRouterPlugin;
43
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
44
+ "default",
45
+ "tanstackRouterPlugin"
46
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
47
+ Object.defineProperty(exports, '__esModule', {
48
+ value: true
49
+ });
@@ -29,6 +29,7 @@ __webpack_require__.d(__webpack_exports__, {
29
29
  getModernRouteIdsFromMatches: ()=>getModernRouteIdsFromMatches
30
30
  });
31
31
  const react_router_namespaceObject = require("@tanstack/react-router");
32
+ const external_react_namespaceObject = require("react");
32
33
  const external_DefaultNotFound_js_namespaceObject = require("./DefaultNotFound.js");
33
34
  const payloadRouter_js_namespaceObject = require("./rsc/payloadRouter.js");
34
35
  function createTanstackRoute(options) {
@@ -84,6 +85,33 @@ function normalizeModernLoaderResponse(result) {
84
85
  }
85
86
  return normalizeModernLoaderResult(result);
86
87
  }
88
+ function pickRouteModuleComponent(routeModule) {
89
+ if ('function' == typeof routeModule || routeModule && 'object' == typeof routeModule && '$$typeof' in routeModule) return routeModule;
90
+ if (!routeModule || 'object' != typeof routeModule) return;
91
+ const module = routeModule;
92
+ const component = module.default || module.Component;
93
+ if ('function' == typeof component || component && 'object' == typeof component && '$$typeof' in component) return component;
94
+ }
95
+ function createServerLazyImportComponent(lazyImport, fallbackComponent) {
96
+ if ("u" > typeof document) return fallbackComponent;
97
+ let resolvedComponent;
98
+ let pendingLoad;
99
+ const load = async ()=>{
100
+ if (resolvedComponent) return resolvedComponent;
101
+ const routeModule = await lazyImport();
102
+ const component = pickRouteModuleComponent(routeModule);
103
+ if (component) resolvedComponent = component;
104
+ return resolvedComponent;
105
+ };
106
+ const Component = (props)=>{
107
+ if (resolvedComponent) return (0, external_react_namespaceObject.createElement)(resolvedComponent, props);
108
+ pendingLoad ||= load();
109
+ throw pendingLoad;
110
+ };
111
+ Component.load = load;
112
+ Component.preload = load;
113
+ return Component;
114
+ }
87
115
  function isAbsoluteUrl(value) {
88
116
  try {
89
117
  new URL(value);
@@ -156,7 +184,7 @@ function wrapModernLoader(modernRoute, modernLoader, revalidationState, options
156
184
  const signal = ctx?.abortController?.signal || ctx?.signal || new AbortController().signal;
157
185
  const baseRequest = ctx?.context?.request instanceof Request ? ctx.context.request : void 0;
158
186
  const href = 'string' == typeof ctx?.location ? ctx.location : ctx?.location?.publicHref || ctx?.location?.href || ctx?.location?.url?.href || '';
159
- const request = baseRequest ? new Request(baseRequest, {
187
+ const request = void 0 !== baseRequest ? new Request(baseRequest, {
160
188
  signal
161
189
  }) : createModernRequest(href, signal);
162
190
  const params = mapParamsForModernLoader({
@@ -221,7 +249,7 @@ function wrapRouteObjectLoader(route, revalidationState, options = {}) {
221
249
  const signal = ctx?.abortController?.signal || ctx?.signal || new AbortController().signal;
222
250
  const baseRequest = ctx?.context?.request instanceof Request ? ctx.context.request : void 0;
223
251
  const href = 'string' == typeof ctx?.location ? ctx.location : ctx?.location?.publicHref || ctx?.location?.href || ctx?.location?.url?.href || '';
224
- const request = baseRequest ? new Request(baseRequest, {
252
+ const request = void 0 !== baseRequest ? new Request(baseRequest, {
225
253
  signal
226
254
  }) : createModernRequest(href, signal);
227
255
  const params = mapParamsForRouteObjectLoader({
@@ -258,10 +286,18 @@ function wrapRouteObjectLoader(route, revalidationState, options = {}) {
258
286
  }
259
287
  function toRouteComponent(routeObject) {
260
288
  const route = routeObject;
289
+ const lazyImport = 'function' == typeof route.lazyImport ? route.lazyImport : void 0;
290
+ const fallbackComponent = route.Component ? route.Component : route.element ? ()=>route.element : void 0;
291
+ if (lazyImport && fallbackComponent) return createServerLazyImportComponent(lazyImport, fallbackComponent);
261
292
  if (route.Component) return route.Component;
262
293
  const element = route.element;
263
294
  if (element) return ()=>element;
264
295
  }
296
+ function toModernRouteComponent(route) {
297
+ const component = route.component || void 0;
298
+ if ('function' == typeof route.lazyImport && component) return createServerLazyImportComponent(route.lazyImport, component);
299
+ return component;
300
+ }
265
301
  function toErrorComponent(routeObject) {
266
302
  const route = routeObject;
267
303
  if (route.ErrorBoundary) return route.ErrorBoundary;
@@ -342,7 +378,7 @@ function createRouteFromModernRoute(opts) {
342
378
  const stableFallbackId = modernId || route._component || route.filename || route.data || ('function' == typeof route.loader ? route.id : void 0);
343
379
  const pendingComponent = route.loading || route.pendingComponent;
344
380
  const errorComponent = route.error || route.errorComponent;
345
- const component = route.component;
381
+ const component = toModernRouteComponent(route);
346
382
  const modernLoader = route.loader;
347
383
  const modernAction = route.action;
348
384
  const modernShouldRevalidate = route.shouldRevalidate;
@@ -389,7 +425,7 @@ function createRouteFromModernRoute(opts) {
389
425
  }
390
426
  function createRouteTreeFromModernRoutes(routes, options = {}) {
391
427
  const rootModern = routes.find((r)=>r && 'nested' === r.type && r.isRoot);
392
- const rootComponent = rootModern?.component;
428
+ const rootComponent = rootModern ? toModernRouteComponent(rootModern) : void 0;
393
429
  const pendingComponent = rootModern?.loading;
394
430
  const errorComponent = rootModern?.error;
395
431
  const rootLoader = rootModern?.loader;
@@ -88,6 +88,7 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
88
88
  const imports = [];
89
89
  const statements = [];
90
90
  const loaderImportMap = new Map();
91
+ const usedRouteVarNames = new Set();
91
92
  let loaderIndex = 0;
92
93
  let routeIndex = 0;
93
94
  const getImportNamesForLoader = async (aliasedNoExtPath, inline, hasAction)=>{
@@ -121,10 +122,17 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
121
122
  actionName
122
123
  };
123
124
  };
125
+ const reserveRouteVarName = (preferred)=>{
126
+ let candidate = preferred;
127
+ let suffix = 1;
128
+ while(usedRouteVarNames.has(candidate))candidate = `${preferred}_${suffix++}`;
129
+ usedRouteVarNames.add(candidate);
130
+ return candidate;
131
+ };
124
132
  const createRouteVarName = (route)=>{
125
133
  const id = route.id;
126
134
  const base = id ? makeLegalIdentifier(id) : `r_${routeIndex++}`;
127
- return `route_${base}`;
135
+ return reserveRouteVarName(`route_${base}`);
128
136
  };
129
137
  const buildRoute = async (opts)=>{
130
138
  const { parentVar, route } = opts;
@@ -153,14 +161,16 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
153
161
  actionName
154
162
  });
155
163
  if (staticDataSnippet) routeOpts.push(staticDataSnippet);
156
- statements.push(`const ${varName} = createRoute({\n ${routeOpts.join('\n ')}\n});`);
157
164
  const children = route.children;
165
+ const hasChildren = Boolean(children && children.length > 0);
166
+ const routeCtorVarName = hasChildren ? reserveRouteVarName(`${varName}__base`) : varName;
167
+ statements.push(`const ${routeCtorVarName} = createRoute({\n ${routeOpts.join('\n ')}\n});`);
158
168
  if (children && children.length > 0) {
159
169
  const childVars = await Promise.all(children.map((child)=>buildRoute({
160
- parentVar: varName,
170
+ parentVar: routeCtorVarName,
161
171
  route: child
162
172
  })));
163
- statements.push(`${varName}.addChildren([${childVars.join(', ')}]);`);
173
+ statements.push(`const ${varName} = ${routeCtorVarName}.addChildren([${childVars.join(', ')}]);`);
164
174
  }
165
175
  return varName;
166
176
  };
@@ -207,7 +217,7 @@ function isRedirectResponse(res: Response) {
207
217
  }
208
218
 
209
219
  function throwTanstackRedirect(location: string) {
210
- const target = location || '/';
220
+ const target = location.length > 0 ? location : '/';
211
221
  try {
212
222
  void new URL(target);
213
223
  throw redirect({ href: target });
@@ -233,21 +243,87 @@ function createRouteStaticData(opts: {
233
243
  modernRouteAction?: unknown;
234
244
  modernRouteLoader?: unknown;
235
245
  }) {
236
- const staticData: Record<string, unknown> = {};
246
+ const staticData: {
247
+ modernRouteId?: string;
248
+ modernRouteAction?: unknown;
249
+ modernRouteLoader?: unknown;
250
+ } = {};
237
251
 
238
- if (opts.modernRouteId) {
252
+ if (typeof opts.modernRouteId === 'string' && opts.modernRouteId.length > 0) {
239
253
  staticData.modernRouteId = opts.modernRouteId;
240
254
  }
241
255
 
242
- if (opts.modernRouteLoader) {
256
+ if (typeof opts.modernRouteLoader !== 'undefined') {
243
257
  staticData.modernRouteLoader = opts.modernRouteLoader;
244
258
  }
245
259
 
246
- if (opts.modernRouteAction) {
260
+ if (typeof opts.modernRouteAction !== 'undefined') {
247
261
  staticData.modernRouteAction = opts.modernRouteAction;
248
262
  }
249
263
 
250
- return Object.keys(staticData).length > 0 ? staticData : undefined;
264
+ return staticData;
265
+ }
266
+
267
+ function getLoaderSignal(ctx: any): AbortSignal {
268
+ const abortSignal = ctx?.abortController?.signal;
269
+ if (abortSignal instanceof AbortSignal) {
270
+ return abortSignal;
271
+ }
272
+ if (ctx?.signal instanceof AbortSignal) {
273
+ return ctx.signal;
274
+ }
275
+ return new AbortController().signal;
276
+ }
277
+
278
+ function getLoaderHref(ctx: any): string {
279
+ if (typeof ctx?.location === 'string') {
280
+ return ctx.location;
281
+ }
282
+
283
+ const publicHref = ctx?.location?.publicHref;
284
+ if (typeof publicHref === 'string') {
285
+ return publicHref;
286
+ }
287
+
288
+ const href = ctx?.location?.href;
289
+ if (typeof href === 'string') {
290
+ return href;
291
+ }
292
+
293
+ const urlHref = ctx?.location?.url?.href;
294
+ return typeof urlHref === 'string' ? urlHref : '';
295
+ }
296
+
297
+ function getLoaderParams(ctx: any): Record<string, string> {
298
+ return typeof ctx?.params === 'object' && ctx.params !== null ? ctx.params : {};
299
+ }
300
+
301
+ function handleModernLoaderResult<LoaderResult>(result: LoaderResult): LoaderResult {
302
+ if (isResponse(result)) {
303
+ if (isRedirectResponse(result)) {
304
+ const location = result.headers.get('Location') ?? '/';
305
+ throwTanstackRedirect(location);
306
+ }
307
+ if (result.status === 404) {
308
+ throw notFound();
309
+ }
310
+ }
311
+
312
+ return result;
313
+ }
314
+
315
+ function handleModernLoaderError(err: unknown): never {
316
+ if (isResponse(err)) {
317
+ if (isRedirectResponse(err)) {
318
+ const location = err.headers.get('Location') ?? '/';
319
+ throwTanstackRedirect(location);
320
+ }
321
+ if (err.status === 404) {
322
+ throw notFound();
323
+ }
324
+ }
325
+
326
+ throw err;
251
327
  }
252
328
 
253
329
  function modernLoaderToTanstack<TLoader extends (args: any) => any>(
@@ -256,57 +332,31 @@ function modernLoaderToTanstack<TLoader extends (args: any) => any>(
256
332
  ) {
257
333
  type LoaderResult = Awaited<ReturnType<TLoader>>;
258
334
 
259
- return async (ctx: any): Promise<LoaderResult> => {
335
+ return (ctx: any): Promise<LoaderResult> => {
260
336
  try {
261
- const signal: AbortSignal =
262
- ctx?.abortController?.signal ||
263
- ctx?.signal ||
264
- new AbortController().signal;
337
+ const signal = getLoaderSignal(ctx);
265
338
  const baseRequest: Request | undefined =
266
339
  ctx?.context?.request instanceof Request ? ctx.context.request : undefined;
267
340
 
268
- const href =
269
- typeof ctx?.location === 'string'
270
- ? ctx.location
271
- : ctx?.location?.publicHref ||
272
- ctx?.location?.href ||
273
- ctx?.location?.url?.href ||
274
- '';
341
+ const href = getLoaderHref(ctx);
275
342
 
276
- const request = baseRequest
343
+ const request = baseRequest !== undefined
277
344
  ? new Request(baseRequest, { signal })
278
345
  : new Request(href, { signal });
279
346
 
280
- const params = mapParamsForModernLoader(ctx?.params || {}, opts.hasSplat);
281
-
282
- const result = await (modernLoader as any)({
283
- request,
284
- params,
285
- context: ctx?.context?.requestContext,
286
- });
287
-
288
- if (isResponse(result)) {
289
- if (isRedirectResponse(result)) {
290
- const location = result.headers.get('Location') || '/';
291
- throwTanstackRedirect(location);
292
- }
293
- if (result.status === 404) {
294
- throw notFound();
295
- }
296
- }
347
+ const params = mapParamsForModernLoader(getLoaderParams(ctx), opts.hasSplat);
297
348
 
298
- return result as LoaderResult;
349
+ return Promise.resolve(
350
+ (modernLoader as any)({
351
+ request,
352
+ params,
353
+ context: ctx?.context?.requestContext,
354
+ }),
355
+ )
356
+ .then((result: LoaderResult) => handleModernLoaderResult(result))
357
+ .catch(handleModernLoaderError);
299
358
  } catch (err) {
300
- if (isResponse(err)) {
301
- if (isRedirectResponse(err)) {
302
- const location = err.headers.get('Location') || '/';
303
- throwTanstackRedirect(location);
304
- }
305
- if (err.status === 404) {
306
- throw notFound();
307
- }
308
- }
309
- throw err;
359
+ handleModernLoaderError(err);
310
360
  }
311
361
  };
312
362
  }