@bleedingdev/modern-js-plugin-tanstack 3.2.0-ultramodern.5 → 3.2.0-ultramodern.50

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 (41) hide show
  1. package/dist/cjs/cli/index.js +3 -6
  2. package/dist/cjs/cli/tanstackTypes.js +20 -6
  3. package/dist/cjs/runtime/plugin.js +2 -0
  4. package/dist/cjs/runtime/plugin.node.js +17 -1
  5. package/dist/cjs/runtime/plugin.worker.js +49 -0
  6. package/dist/cjs/runtime/routeTree.js +38 -2
  7. package/dist/esm/cli/index.mjs +3 -6
  8. package/dist/esm/cli/tanstackTypes.mjs +20 -6
  9. package/dist/esm/runtime/plugin.mjs +2 -0
  10. package/dist/esm/runtime/plugin.node.mjs +17 -1
  11. package/dist/esm/runtime/plugin.worker.mjs +1 -0
  12. package/dist/esm/runtime/routeTree.mjs +38 -2
  13. package/dist/esm-node/cli/index.mjs +3 -6
  14. package/dist/esm-node/cli/tanstackTypes.mjs +20 -6
  15. package/dist/esm-node/runtime/plugin.mjs +2 -0
  16. package/dist/esm-node/runtime/plugin.node.mjs +17 -1
  17. package/dist/esm-node/runtime/plugin.worker.mjs +2 -0
  18. package/dist/esm-node/runtime/routeTree.mjs +38 -2
  19. package/dist/types/runtime/plugin.worker.d.ts +1 -0
  20. package/package.json +13 -13
  21. package/src/cli/index.ts +15 -18
  22. package/src/cli/tanstackTypes.ts +34 -9
  23. package/src/runtime/basepathRewrite.ts +1 -0
  24. package/src/runtime/dataMutation.tsx +1 -0
  25. package/src/runtime/lifecycle.ts +1 -0
  26. package/src/runtime/plugin.node.tsx +43 -1
  27. package/src/runtime/plugin.tsx +3 -0
  28. package/src/runtime/plugin.worker.tsx +4 -0
  29. package/src/runtime/routeTree.ts +102 -2
  30. package/src/runtime/rsc/ClientSlot.tsx +1 -0
  31. package/src/runtime/rsc/CompositeComponent.tsx +1 -0
  32. package/src/runtime/rsc/ReplayableStream.ts +1 -0
  33. package/src/runtime/rsc/RscNodeRenderer.tsx +1 -0
  34. package/src/runtime/rsc/client.tsx +2 -3
  35. package/src/runtime/rsc/createRscProxy.tsx +1 -0
  36. package/src/runtime/rsc/payloadRouter.ts +1 -0
  37. package/src/runtime/rsc/server.tsx +1 -0
  38. package/src/runtime/rsc/slotUsageSanitizer.ts +1 -0
  39. package/src/runtime/utils.tsx +1 -0
  40. package/tests/router/routeTree.test.ts +72 -1
  41. package/tests/router/tanstackTypes.test.ts +64 -0
@@ -159,13 +159,10 @@ declare module '${opts.runtimeModule}' {
159
159
  plugins
160
160
  };
161
161
  });
162
- api.checkEntryPoint(({ path: entryPath, entry })=>{
163
- const { isRouteEntry } = getRuntimeRouterCli();
164
- return {
162
+ api.checkEntryPoint(({ path: entryPath, entry })=>({
165
163
  path: entryPath,
166
- entry: entry || isRouteEntry(entryPath, routesDir)
167
- };
168
- });
164
+ entry: entry || getRuntimeRouterCli().isRouteEntry(entryPath, routesDir)
165
+ }));
169
166
  api.config(()=>({
170
167
  source: {
171
168
  include: [
@@ -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
  };
@@ -272,7 +282,11 @@ 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
291
  if (opts.modernRouteId) {
278
292
  staticData.modernRouteId = opts.modernRouteId;
@@ -286,7 +300,7 @@ function createRouteStaticData(opts: {
286
300
  staticData.modernRouteAction = opts.modernRouteAction;
287
301
  }
288
302
 
289
- return Object.keys(staticData).length > 0 ? staticData : undefined;
303
+ return staticData;
290
304
  }
291
305
 
292
306
  function modernLoaderToTanstack<TLoader extends (args: any) => any>(
@@ -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,
@@ -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?.({});
@@ -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);
@@ -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;
@@ -108,13 +108,10 @@ function tanstackRouterPlugin(options = {}) {
108
108
  plugins
109
109
  };
110
110
  });
111
- api.checkEntryPoint(({ path: entryPath, entry })=>{
112
- const { isRouteEntry } = getRuntimeRouterCli();
113
- return {
111
+ api.checkEntryPoint(({ path: entryPath, entry })=>({
114
112
  path: entryPath,
115
- entry: entry || isRouteEntry(entryPath, routesDir)
116
- };
117
- });
113
+ entry: entry || getRuntimeRouterCli().isRouteEntry(entryPath, routesDir)
114
+ }));
118
115
  api.config(()=>({
119
116
  source: {
120
117
  include: [
@@ -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
  };
@@ -233,7 +243,11 @@ 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
252
  if (opts.modernRouteId) {
239
253
  staticData.modernRouteId = opts.modernRouteId;
@@ -247,7 +261,7 @@ function createRouteStaticData(opts: {
247
261
  staticData.modernRouteAction = opts.modernRouteAction;
248
262
  }
249
263
 
250
- return Object.keys(staticData).length > 0 ? staticData : undefined;
264
+ return staticData;
251
265
  }
252
266
 
253
267
  function modernLoaderToTanstack<TLoader extends (args: any) => any>(
@@ -7,6 +7,7 @@ import { RouterClient } from "@tanstack/react-router/ssr/client";
7
7
  import { createModernBasepathRewrite } from "./basepathRewrite.mjs";
8
8
  import { modifyRoutes, onAfterCreateRouter, onAfterHydrateRouter, onBeforeCreateRouter, onBeforeCreateRoutes, onBeforeHydrateRouter } from "./hooks.mjs";
9
9
  import { applyRouterRuntimeState } from "./lifecycle.mjs";
10
+ import { Link } from "./prefetchLink.mjs";
10
11
  import { createRouteTreeFromRouteObjects } from "./routeTree.mjs";
11
12
  import { getTanstackRscSerializationAdapters } from "./rsc/client.mjs";
12
13
  import { createRouteObjectsFromConfig, urlJoin } from "./utils.mjs";
@@ -73,6 +74,7 @@ const tanstackRouterPlugin = (userConfig = {})=>{
73
74
  }
74
75
  }
75
76
  context.router = {
77
+ Link: Link,
76
78
  useMatches: useMatches,
77
79
  useLocation: useLocation,
78
80
  useNavigate: useNavigate,
@@ -5,7 +5,7 @@ import { createRequestContext, storage } from "@modern-js/runtime-utils/node";
5
5
  import { time } from "@modern-js/runtime-utils/time";
6
6
  import { LOADER_REPORTER_NAME } from "@modern-js/utils/universal/constants";
7
7
  import { RouterProvider, createMemoryHistory, createRouter } from "@tanstack/react-router";
8
- import { attachRouterServerSsrUtils } from "@tanstack/react-router/ssr/server";
8
+ import { attachRouterServerSsrUtils } from "@tanstack/router-core/ssr/server";
9
9
  import { Suspense, useContext } from "react";
10
10
  import { createModernBasepathRewrite } from "./basepathRewrite.mjs";
11
11
  import { modifyRoutes, onAfterCreateRouter, onAfterHydrateRouter, onBeforeCreateRouter, onBeforeCreateRoutes, onBeforeHydrateRouter } from "./hooks.mjs";
@@ -17,12 +17,28 @@ const setTanstackRscServerPayload = (payload)=>{
17
17
  const storageContext = storage.useContext?.();
18
18
  if (storageContext) storageContext.serverPayload = payload;
19
19
  };
20
+ function isPromiseLike(value) {
21
+ return Boolean(value && 'function' == typeof value.then);
22
+ }
20
23
  function isPreloadableRouteComponent(component) {
21
24
  if (!component || 'function' != typeof component) return false;
22
25
  const preloadable = component;
23
26
  return 'function' == typeof preloadable.load || 'function' == typeof preloadable.preload;
24
27
  }
28
+ function isReactLazyRouteComponent(component) {
29
+ return Boolean(component) && 'object' == typeof component && 'function' == typeof component._init && '_payload' in component;
30
+ }
31
+ async function preloadReactLazyRouteComponent(component) {
32
+ try {
33
+ component._init?.(component._payload);
34
+ } catch (thrown) {
35
+ if (!isPromiseLike(thrown)) throw thrown;
36
+ await thrown;
37
+ component._init?.(component._payload);
38
+ }
39
+ }
25
40
  async function preloadRouteComponent(component) {
41
+ if (isReactLazyRouteComponent(component)) return void await preloadReactLazyRouteComponent(component);
26
42
  if (!isPreloadableRouteComponent(component)) return;
27
43
  if ('function' == typeof component.load) return void await component.load({});
28
44
  await component.preload?.({});
@@ -0,0 +1 @@
1
+ export { default, tanstackRouterPlugin } from "./plugin.node.mjs";
@@ -1,4 +1,5 @@
1
1
  import { createRootRoute, createRoute, notFound, redirect } from "@tanstack/react-router";
2
+ import { createElement } from "react";
2
3
  import { DefaultNotFound } from "./DefaultNotFound.mjs";
3
4
  import { isTanstackRscPayloadNavigationEnabled, loadTanstackRscRouteData } from "./rsc/payloadRouter.mjs";
4
5
  function createTanstackRoute(options) {
@@ -54,6 +55,33 @@ function normalizeModernLoaderResponse(result) {
54
55
  }
55
56
  return normalizeModernLoaderResult(result);
56
57
  }
58
+ function pickRouteModuleComponent(routeModule) {
59
+ if ('function' == typeof routeModule || routeModule && 'object' == typeof routeModule && '$$typeof' in routeModule) return routeModule;
60
+ if (!routeModule || 'object' != typeof routeModule) return;
61
+ const module = routeModule;
62
+ const component = module.default || module.Component;
63
+ if ('function' == typeof component || component && 'object' == typeof component && '$$typeof' in component) return component;
64
+ }
65
+ function createServerLazyImportComponent(lazyImport, fallbackComponent) {
66
+ if ("u" > typeof document) return fallbackComponent;
67
+ let resolvedComponent;
68
+ let pendingLoad;
69
+ const load = async ()=>{
70
+ if (resolvedComponent) return resolvedComponent;
71
+ const routeModule = await lazyImport();
72
+ const component = pickRouteModuleComponent(routeModule);
73
+ if (component) resolvedComponent = component;
74
+ return resolvedComponent;
75
+ };
76
+ const Component = (props)=>{
77
+ if (resolvedComponent) return createElement(resolvedComponent, props);
78
+ pendingLoad ||= load();
79
+ throw pendingLoad;
80
+ };
81
+ Component.load = load;
82
+ Component.preload = load;
83
+ return Component;
84
+ }
57
85
  function isAbsoluteUrl(value) {
58
86
  try {
59
87
  new URL(value);
@@ -228,10 +256,18 @@ function wrapRouteObjectLoader(route, revalidationState, options = {}) {
228
256
  }
229
257
  function toRouteComponent(routeObject) {
230
258
  const route = routeObject;
259
+ const lazyImport = 'function' == typeof route.lazyImport ? route.lazyImport : void 0;
260
+ const fallbackComponent = route.Component ? route.Component : route.element ? ()=>route.element : void 0;
261
+ if (lazyImport && fallbackComponent) return createServerLazyImportComponent(lazyImport, fallbackComponent);
231
262
  if (route.Component) return route.Component;
232
263
  const element = route.element;
233
264
  if (element) return ()=>element;
234
265
  }
266
+ function toModernRouteComponent(route) {
267
+ const component = route.component || void 0;
268
+ if ('function' == typeof route.lazyImport && component) return createServerLazyImportComponent(route.lazyImport, component);
269
+ return component;
270
+ }
235
271
  function toErrorComponent(routeObject) {
236
272
  const route = routeObject;
237
273
  if (route.ErrorBoundary) return route.ErrorBoundary;
@@ -312,7 +348,7 @@ function createRouteFromModernRoute(opts) {
312
348
  const stableFallbackId = modernId || route._component || route.filename || route.data || ('function' == typeof route.loader ? route.id : void 0);
313
349
  const pendingComponent = route.loading || route.pendingComponent;
314
350
  const errorComponent = route.error || route.errorComponent;
315
- const component = route.component;
351
+ const component = toModernRouteComponent(route);
316
352
  const modernLoader = route.loader;
317
353
  const modernAction = route.action;
318
354
  const modernShouldRevalidate = route.shouldRevalidate;
@@ -359,7 +395,7 @@ function createRouteFromModernRoute(opts) {
359
395
  }
360
396
  function createRouteTreeFromModernRoutes(routes, options = {}) {
361
397
  const rootModern = routes.find((r)=>r && 'nested' === r.type && r.isRoot);
362
- const rootComponent = rootModern?.component;
398
+ const rootComponent = rootModern ? toModernRouteComponent(rootModern) : void 0;
363
399
  const pendingComponent = rootModern?.loading;
364
400
  const errorComponent = rootModern?.error;
365
401
  const rootLoader = rootModern?.loader;
@@ -112,13 +112,10 @@ function tanstackRouterPlugin(options = {}) {
112
112
  plugins
113
113
  };
114
114
  });
115
- api.checkEntryPoint(({ path: entryPath, entry })=>{
116
- const { isRouteEntry } = getRuntimeRouterCli();
117
- return {
115
+ api.checkEntryPoint(({ path: entryPath, entry })=>({
118
116
  path: entryPath,
119
- entry: entry || isRouteEntry(entryPath, routesDir)
120
- };
121
- });
117
+ entry: entry || getRuntimeRouterCli().isRouteEntry(entryPath, routesDir)
118
+ }));
122
119
  api.config(()=>({
123
120
  source: {
124
121
  include: [
@@ -89,6 +89,7 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
89
89
  const imports = [];
90
90
  const statements = [];
91
91
  const loaderImportMap = new Map();
92
+ const usedRouteVarNames = new Set();
92
93
  let loaderIndex = 0;
93
94
  let routeIndex = 0;
94
95
  const getImportNamesForLoader = async (aliasedNoExtPath, inline, hasAction)=>{
@@ -122,10 +123,17 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
122
123
  actionName
123
124
  };
124
125
  };
126
+ const reserveRouteVarName = (preferred)=>{
127
+ let candidate = preferred;
128
+ let suffix = 1;
129
+ while(usedRouteVarNames.has(candidate))candidate = `${preferred}_${suffix++}`;
130
+ usedRouteVarNames.add(candidate);
131
+ return candidate;
132
+ };
125
133
  const createRouteVarName = (route)=>{
126
134
  const id = route.id;
127
135
  const base = id ? makeLegalIdentifier(id) : `r_${routeIndex++}`;
128
- return `route_${base}`;
136
+ return reserveRouteVarName(`route_${base}`);
129
137
  };
130
138
  const buildRoute = async (opts)=>{
131
139
  const { parentVar, route } = opts;
@@ -154,14 +162,16 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
154
162
  actionName
155
163
  });
156
164
  if (staticDataSnippet) routeOpts.push(staticDataSnippet);
157
- statements.push(`const ${varName} = createRoute({\n ${routeOpts.join('\n ')}\n});`);
158
165
  const children = route.children;
166
+ const hasChildren = Boolean(children && children.length > 0);
167
+ const routeCtorVarName = hasChildren ? reserveRouteVarName(`${varName}__base`) : varName;
168
+ statements.push(`const ${routeCtorVarName} = createRoute({\n ${routeOpts.join('\n ')}\n});`);
159
169
  if (children && children.length > 0) {
160
170
  const childVars = await Promise.all(children.map((child)=>buildRoute({
161
- parentVar: varName,
171
+ parentVar: routeCtorVarName,
162
172
  route: child
163
173
  })));
164
- statements.push(`${varName}.addChildren([${childVars.join(', ')}]);`);
174
+ statements.push(`const ${varName} = ${routeCtorVarName}.addChildren([${childVars.join(', ')}]);`);
165
175
  }
166
176
  return varName;
167
177
  };
@@ -234,7 +244,11 @@ function createRouteStaticData(opts: {
234
244
  modernRouteAction?: unknown;
235
245
  modernRouteLoader?: unknown;
236
246
  }) {
237
- const staticData: Record<string, unknown> = {};
247
+ const staticData: {
248
+ modernRouteId?: string;
249
+ modernRouteAction?: unknown;
250
+ modernRouteLoader?: unknown;
251
+ } = {};
238
252
 
239
253
  if (opts.modernRouteId) {
240
254
  staticData.modernRouteId = opts.modernRouteId;
@@ -248,7 +262,7 @@ function createRouteStaticData(opts: {
248
262
  staticData.modernRouteAction = opts.modernRouteAction;
249
263
  }
250
264
 
251
- return Object.keys(staticData).length > 0 ? staticData : undefined;
265
+ return staticData;
252
266
  }
253
267
 
254
268
  function modernLoaderToTanstack<TLoader extends (args: any) => any>(
@@ -8,6 +8,7 @@ import { RouterClient } from "@tanstack/react-router/ssr/client";
8
8
  import { createModernBasepathRewrite } from "./basepathRewrite.mjs";
9
9
  import { modifyRoutes, onAfterCreateRouter, onAfterHydrateRouter, onBeforeCreateRouter, onBeforeCreateRoutes, onBeforeHydrateRouter } from "./hooks.mjs";
10
10
  import { applyRouterRuntimeState } from "./lifecycle.mjs";
11
+ import { Link } from "./prefetchLink.mjs";
11
12
  import { createRouteTreeFromRouteObjects } from "./routeTree.mjs";
12
13
  import { getTanstackRscSerializationAdapters } from "./rsc/client.mjs";
13
14
  import { createRouteObjectsFromConfig, urlJoin } from "./utils.mjs";
@@ -74,6 +75,7 @@ const tanstackRouterPlugin = (userConfig = {})=>{
74
75
  }
75
76
  }
76
77
  context.router = {
78
+ Link: Link,
77
79
  useMatches: useMatches,
78
80
  useLocation: useLocation,
79
81
  useNavigate: useNavigate,
@@ -6,7 +6,7 @@ import { createRequestContext, storage } from "@modern-js/runtime-utils/node";
6
6
  import { time } from "@modern-js/runtime-utils/time";
7
7
  import { LOADER_REPORTER_NAME } from "@modern-js/utils/universal/constants";
8
8
  import { RouterProvider, createMemoryHistory, createRouter } from "@tanstack/react-router";
9
- import { attachRouterServerSsrUtils } from "@tanstack/react-router/ssr/server";
9
+ import { attachRouterServerSsrUtils } from "@tanstack/router-core/ssr/server";
10
10
  import { Suspense, useContext } from "react";
11
11
  import { createModernBasepathRewrite } from "./basepathRewrite.mjs";
12
12
  import { modifyRoutes, onAfterCreateRouter, onAfterHydrateRouter, onBeforeCreateRouter, onBeforeCreateRoutes, onBeforeHydrateRouter } from "./hooks.mjs";
@@ -18,12 +18,28 @@ const setTanstackRscServerPayload = (payload)=>{
18
18
  const storageContext = storage.useContext?.();
19
19
  if (storageContext) storageContext.serverPayload = payload;
20
20
  };
21
+ function isPromiseLike(value) {
22
+ return Boolean(value && 'function' == typeof value.then);
23
+ }
21
24
  function isPreloadableRouteComponent(component) {
22
25
  if (!component || 'function' != typeof component) return false;
23
26
  const preloadable = component;
24
27
  return 'function' == typeof preloadable.load || 'function' == typeof preloadable.preload;
25
28
  }
29
+ function isReactLazyRouteComponent(component) {
30
+ return Boolean(component) && 'object' == typeof component && 'function' == typeof component._init && '_payload' in component;
31
+ }
32
+ async function preloadReactLazyRouteComponent(component) {
33
+ try {
34
+ component._init?.(component._payload);
35
+ } catch (thrown) {
36
+ if (!isPromiseLike(thrown)) throw thrown;
37
+ await thrown;
38
+ component._init?.(component._payload);
39
+ }
40
+ }
26
41
  async function preloadRouteComponent(component) {
42
+ if (isReactLazyRouteComponent(component)) return void await preloadReactLazyRouteComponent(component);
27
43
  if (!isPreloadableRouteComponent(component)) return;
28
44
  if ('function' == typeof component.load) return void await component.load({});
29
45
  await component.preload?.({});
@@ -0,0 +1,2 @@
1
+ import "node:module";
2
+ export { default, tanstackRouterPlugin } from "./plugin.node.mjs";