@bleedingdev/modern-js-plugin-tanstack 3.2.0-ultramodern.120 → 3.2.0-ultramodern.122

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 (94) hide show
  1. package/dist/cjs/cli/index.js +47 -27
  2. package/dist/cjs/cli/routeSplitting.js +0 -32
  3. package/dist/cjs/cli/tanstackTypes.js +34 -199
  4. package/dist/cjs/runtime/hooks.js +11 -14
  5. package/dist/cjs/runtime/index.js +107 -319
  6. package/dist/cjs/runtime/lifecycle.js +12 -86
  7. package/dist/cjs/runtime/loaderBridge.js +173 -0
  8. package/dist/cjs/runtime/plugin.js +6 -30
  9. package/dist/cjs/runtime/plugin.node.js +7 -29
  10. package/dist/cjs/runtime/pluginCore.js +55 -0
  11. package/dist/cjs/runtime/register.js +56 -0
  12. package/dist/cjs/runtime/routeTree.js +10 -207
  13. package/dist/cjs/runtime/{DefaultNotFound.js → router.js} +5 -15
  14. package/dist/cjs/runtime/rsc/payloadRouter.js +35 -1
  15. package/dist/cjs/runtime/state.js +45 -0
  16. package/dist/cjs/runtime/utils.js +0 -5
  17. package/dist/esm/cli/index.mjs +52 -26
  18. package/dist/esm/cli/routeSplitting.mjs +1 -30
  19. package/dist/esm/cli/tanstackTypes.mjs +32 -194
  20. package/dist/esm/runtime/hooks.mjs +1 -8
  21. package/dist/esm/runtime/index.mjs +4 -2
  22. package/dist/esm/runtime/lifecycle.mjs +1 -82
  23. package/dist/esm/runtime/loaderBridge.mjs +114 -0
  24. package/dist/esm/runtime/plugin.mjs +8 -32
  25. package/dist/esm/runtime/plugin.node.mjs +10 -32
  26. package/dist/esm/runtime/pluginCore.mjs +14 -0
  27. package/dist/esm/runtime/register.mjs +18 -0
  28. package/dist/esm/runtime/routeTree.mjs +4 -198
  29. package/dist/esm/runtime/router.mjs +2 -0
  30. package/dist/esm/runtime/rsc/payloadRouter.mjs +35 -1
  31. package/dist/esm/runtime/state.mjs +7 -0
  32. package/dist/esm/runtime/utils.mjs +0 -5
  33. package/dist/esm-node/cli/index.mjs +52 -26
  34. package/dist/esm-node/cli/routeSplitting.mjs +1 -30
  35. package/dist/esm-node/cli/tanstackTypes.mjs +32 -194
  36. package/dist/esm-node/runtime/hooks.mjs +1 -8
  37. package/dist/esm-node/runtime/index.mjs +4 -2
  38. package/dist/esm-node/runtime/lifecycle.mjs +1 -82
  39. package/dist/esm-node/runtime/loaderBridge.mjs +115 -0
  40. package/dist/esm-node/runtime/plugin.mjs +8 -32
  41. package/dist/esm-node/runtime/plugin.node.mjs +10 -32
  42. package/dist/esm-node/runtime/pluginCore.mjs +15 -0
  43. package/dist/esm-node/runtime/register.mjs +19 -0
  44. package/dist/esm-node/runtime/routeTree.mjs +4 -198
  45. package/dist/esm-node/runtime/router.mjs +3 -0
  46. package/dist/esm-node/runtime/rsc/payloadRouter.mjs +35 -1
  47. package/dist/esm-node/runtime/state.mjs +8 -0
  48. package/dist/esm-node/runtime/utils.mjs +0 -5
  49. package/dist/types/cli/index.d.ts +9 -2
  50. package/dist/types/cli/routeSplitting.d.ts +6 -15
  51. package/dist/types/cli/tanstackTypes.d.ts +13 -2
  52. package/dist/types/runtime/hooks.d.ts +8 -18
  53. package/dist/types/runtime/index.d.ts +6 -4
  54. package/dist/types/runtime/lifecycle.d.ts +7 -22
  55. package/dist/types/runtime/loaderBridge.d.ts +48 -0
  56. package/dist/types/runtime/plugin.d.ts +1 -14
  57. package/dist/types/runtime/plugin.node.d.ts +1 -14
  58. package/dist/types/runtime/pluginCore.d.ts +21 -0
  59. package/dist/types/runtime/register.d.ts +9 -0
  60. package/dist/types/runtime/routeTree.d.ts +0 -2
  61. package/dist/types/runtime/router.d.ts +14 -0
  62. package/dist/types/runtime/state.d.ts +16 -0
  63. package/dist/types/runtime/types.d.ts +7 -53
  64. package/package.json +31 -29
  65. package/rstest.config.mts +6 -0
  66. package/src/cli/index.ts +111 -29
  67. package/src/cli/routeSplitting.ts +6 -44
  68. package/src/cli/tanstackTypes.ts +78 -214
  69. package/src/runtime/hooks.ts +10 -27
  70. package/src/runtime/index.tsx +12 -107
  71. package/src/runtime/lifecycle.ts +16 -151
  72. package/src/runtime/loaderBridge.ts +257 -0
  73. package/src/runtime/plugin.node.tsx +14 -77
  74. package/src/runtime/plugin.tsx +12 -72
  75. package/src/runtime/pluginCore.ts +48 -0
  76. package/src/runtime/register.ts +58 -0
  77. package/src/runtime/routeTree.ts +8 -370
  78. package/src/runtime/router.ts +15 -0
  79. package/src/runtime/rsc/payloadRouter.ts +45 -2
  80. package/src/runtime/state.ts +29 -0
  81. package/src/runtime/types.ts +20 -67
  82. package/src/runtime/utils.tsx +3 -6
  83. package/tests/router/cli.test.ts +297 -31
  84. package/tests/router/hooks.test.ts +26 -0
  85. package/tests/router/loaderBridge.test.ts +211 -0
  86. package/tests/router/packageSurface.test.ts +24 -0
  87. package/tests/router/register.test.ts +46 -0
  88. package/tests/router/routeTree.test.ts +65 -180
  89. package/tests/router/rsc.test.tsx +70 -0
  90. package/tests/router/tanstackTypes.test.ts +164 -6
  91. package/dist/esm/runtime/DefaultNotFound.mjs +0 -13
  92. package/dist/esm-node/runtime/DefaultNotFound.mjs +0 -14
  93. package/dist/types/runtime/DefaultNotFound.d.ts +0 -2
  94. package/src/runtime/DefaultNotFound.tsx +0 -15
@@ -1,7 +1,6 @@
1
1
  import "node:module";
2
2
  import { jsx } from "react/jsx-runtime";
3
- import { InternalRuntimeContext, getGlobalEnableRsc, getGlobalLayoutApp, getGlobalRoutes } from "@modern-js/runtime/context";
4
- import { merge } from "@modern-js/runtime-utils/merge";
3
+ import { InternalRuntimeContext, getGlobalEnableRsc } from "@modern-js/runtime/context";
5
4
  import { createRequestContext, storage } from "@modern-js/runtime-utils/node";
6
5
  import { time } from "@modern-js/runtime-utils/time";
7
6
  import { LOADER_REPORTER_NAME } from "@modern-js/utils/universal/constants";
@@ -9,9 +8,10 @@ import { RouterProvider, createMemoryHistory, createRouter } from "@tanstack/rea
9
8
  import { attachRouterServerSsrUtils } from "@tanstack/router-core/ssr/server";
10
9
  import { useContext } from "react";
11
10
  import { createModernBasepathRewrite } from "./basepathRewrite.mjs";
12
- import { modifyRoutes, onAfterCreateRouter, onAfterHydrateRouter, onBeforeCreateRouter, onBeforeCreateRoutes, onBeforeHydrateRouter } from "./hooks.mjs";
11
+ import { routerProviderRegistryHooks } from "./hooks.mjs";
13
12
  import { wrapTanstackSsrHydrationBoundary } from "./hydrationBoundary.mjs";
14
- import { applyRouterServerPrepareResult, createRouterServerSnapshot } from "./lifecycle.mjs";
13
+ import { applyRouterServerPrepareResult, createRouterServerSnapshot, getRouterRuntimeState } from "./lifecycle.mjs";
14
+ import { getFinalRouteConfig, getMergedRouterConfig } from "./pluginCore.mjs";
15
15
  import { createRouteTreeFromRouteObjects, getModernRouteIdsFromMatches } from "./routeTree.mjs";
16
16
  import { createTanstackRscServerPayload, handleTanstackRscRedirect } from "./rsc/payloadRouter.mjs";
17
17
  import { getModernTanstackRouterFastDefaults } from "./types.mjs";
@@ -96,15 +96,6 @@ function createGetSsrHref(request) {
96
96
  const url = new URL(request.url);
97
97
  return `${url.pathname}${url.search}${url.hash}`;
98
98
  }
99
- function stripSyntheticNotFoundRoute(routes) {
100
- return routes.filter((route)=>!('*' === route.path && !route.id && !route.loader)).map((route)=>{
101
- if (!route.children?.length) return route;
102
- return {
103
- ...route,
104
- children: stripSyntheticNotFoundRoute(route.children)
105
- };
106
- });
107
- }
108
99
  function collectRouterErrors(tanstackRouter) {
109
100
  const state = tanstackRouter.state;
110
101
  const matches = Array.isArray(state.matches) ? state.matches : [];
@@ -119,26 +110,14 @@ function collectRouterErrors(tanstackRouter) {
119
110
  const tanstackRouterPlugin = (userConfig = {})=>{
120
111
  const plugin = {
121
112
  name: '@modern-js/plugin-router-tanstack',
122
- registryHooks: {
123
- modifyRoutes: modifyRoutes,
124
- onAfterCreateRouter: onAfterCreateRouter,
125
- onAfterHydrateRouter: onAfterHydrateRouter,
126
- onBeforeCreateRouter: onBeforeCreateRouter,
127
- onBeforeCreateRoutes: onBeforeCreateRoutes,
128
- onBeforeHydrateRouter: onBeforeHydrateRouter
129
- },
113
+ registryHooks: routerProviderRegistryHooks,
130
114
  setup: (api)=>{
131
115
  api.onBeforeRender(async (context, interrupt)=>{
132
- const pluginConfig = api.getRuntimeConfig();
133
- const mergedConfig = merge(pluginConfig.router || {}, userConfig);
116
+ const mergedConfig = getMergedRouterConfig(api, userConfig);
134
117
  const serializationAdapters = getGlobalEnableRsc() ? (await import("./rsc/server.mjs")).getTanstackRscSerializationAdapters() : void 0;
135
118
  const enableRsc = getGlobalEnableRsc();
136
- const { basename = '', routesConfig, createRoutes } = mergedConfig;
137
- const finalRouteConfig = {
138
- routes: getGlobalRoutes(),
139
- globalApp: getGlobalLayoutApp(),
140
- ...routesConfig
141
- };
119
+ const { basename = '', createRoutes } = mergedConfig;
120
+ const finalRouteConfig = getFinalRouteConfig(mergedConfig);
142
121
  if (!finalRouteConfig.routes && !createRoutes) return;
143
122
  const hooks = api.getHooks();
144
123
  await hooks.onBeforeCreateRoutes.call(context);
@@ -146,8 +125,7 @@ const tanstackRouterPlugin = (userConfig = {})=>{
146
125
  routesConfig: finalRouteConfig,
147
126
  ssrMode: context.ssrContext?.mode
148
127
  }) || [];
149
- const normalizedRouteObjects = createRoutes ? routeObjects : stripSyntheticNotFoundRoute(routeObjects);
150
- const modifiedRouteObjects = hooks.modifyRoutes.call(normalizedRouteObjects);
128
+ const modifiedRouteObjects = hooks.modifyRoutes.call(routeObjects);
151
129
  if (!modifiedRouteObjects.length) return;
152
130
  const { request, nonce, baseUrl, loaderFailureMode = 'errorBoundary' } = context.ssrContext;
153
131
  const _basename = '/' === baseUrl ? urlJoin(baseUrl, basename || '') : baseUrl;
@@ -265,7 +243,7 @@ const tanstackRouterPlugin = (userConfig = {})=>{
265
243
  api.wrapRoot((App)=>{
266
244
  const getRouteApp = ()=>(props)=>{
267
245
  const context = useContext(InternalRuntimeContext);
268
- const router = context.routerInstance ?? context.routerRuntime?.instance;
246
+ const router = getRouterRuntimeState(context)?.instance;
269
247
  if (!router) return App ? /*#__PURE__*/ jsx(App, {
270
248
  ...props
271
249
  }) : null;
@@ -0,0 +1,15 @@
1
+ import "node:module";
2
+ import { getGlobalLayoutApp, getGlobalRoutes } from "@modern-js/runtime/context";
3
+ import { merge } from "@modern-js/runtime-utils/merge";
4
+ function getMergedRouterConfig(api, userConfig) {
5
+ const pluginConfig = api.getRuntimeConfig();
6
+ return merge(pluginConfig.router || {}, userConfig);
7
+ }
8
+ function getFinalRouteConfig(mergedConfig) {
9
+ return {
10
+ routes: getGlobalRoutes(),
11
+ globalApp: getGlobalLayoutApp(),
12
+ ...mergedConfig.routesConfig
13
+ };
14
+ }
15
+ export { getFinalRouteConfig, getMergedRouterConfig };
@@ -0,0 +1,19 @@
1
+ import "node:module";
2
+ import { registerRouterProvider } from "@modern-js/runtime/context";
3
+ import { Form, RouteActionResponseError, useFetcher } from "./dataMutation.mjs";
4
+ import { Outlet } from "./outlet.mjs";
5
+ import { tanstackRouterPlugin } from "./plugin.mjs";
6
+ import { Link, NavLink } from "./prefetchLink.mjs";
7
+ const tanstackRouterProviderFactory = (userConfig)=>tanstackRouterPlugin(userConfig);
8
+ registerRouterProvider('tanstack', tanstackRouterProviderFactory);
9
+ const COMPAT_BINDINGS_SLOT = Symbol.for('@modern-js/plugin-tanstack:runtime-compat-bindings');
10
+ const tanstackRouterCompatBindings = {
11
+ Form: Form,
12
+ Link: Link,
13
+ NavLink: NavLink,
14
+ Outlet: Outlet,
15
+ RouteActionResponseError: RouteActionResponseError,
16
+ useFetcher: useFetcher
17
+ };
18
+ globalThis[COMPAT_BINDINGS_SLOT] ??= tanstackRouterCompatBindings;
19
+ export { tanstackRouterCompatBindings };
@@ -1,7 +1,8 @@
1
1
  import "node:module";
2
- import { createRootRoute, createRoute, notFound, redirect, rootRouteId } from "@tanstack/react-router";
2
+ import { DefaultNotFound } from "@modern-js/runtime/context";
3
+ import { createRootRoute, createRoute, notFound, rootRouteId } from "@tanstack/react-router";
3
4
  import { createElement } from "react";
4
- import { DefaultNotFound } from "./DefaultNotFound.mjs";
5
+ import { isRedirectResponse, isResponse, isTanstackRedirect, throwTanstackRedirect } from "./loaderBridge.mjs";
5
6
  import { withModernRouteMatchContext } from "./outlet.mjs";
6
7
  import { isTanstackRscPayloadNavigationEnabled, loadTanstackRscRouteData } from "./rsc/payloadRouter.mjs";
7
8
  function createTanstackRoute(options) {
@@ -26,23 +27,6 @@ function toTanstackPath(pathname) {
26
27
  return segment;
27
28
  }).join('/');
28
29
  }
29
- function isResponse(value) {
30
- const record = value;
31
- return null != record && 'object' == typeof record && 'number' == typeof record.status && 'object' == typeof record.headers;
32
- }
33
- function isTanstackRedirect(value) {
34
- return isResponse(value) && 'object' == typeof value.options;
35
- }
36
- const redirectStatusCodes = new Set([
37
- 301,
38
- 302,
39
- 303,
40
- 307,
41
- 308
42
- ]);
43
- function isRedirectResponse(res) {
44
- return redirectStatusCodes.has(res.status);
45
- }
46
30
  function isModernDeferredData(value) {
47
31
  if (!value || 'object' != typeof value) return false;
48
32
  const deferred = value;
@@ -95,34 +79,6 @@ function createServerLazyImportComponent(lazyImport, fallbackComponent) {
95
79
  Component.preload = load;
96
80
  return Component;
97
81
  }
98
- function isAbsoluteUrl(value) {
99
- try {
100
- new URL(value);
101
- return true;
102
- } catch {
103
- return false;
104
- }
105
- }
106
- function throwTanstackRedirect(location) {
107
- const target = location || '/';
108
- if (isAbsoluteUrl(target)) throw redirect({
109
- href: target
110
- });
111
- throw redirect({
112
- to: target
113
- });
114
- }
115
- function mapParamsForModernLoader({ modernRoute, params }) {
116
- if ('nested' === modernRoute.type && modernRoute.path?.includes('*')) {
117
- const { _splat, ...rest } = params;
118
- if (void 0 !== _splat) return {
119
- ...rest,
120
- '*': _splat
121
- };
122
- return rest;
123
- }
124
- return params;
125
- }
126
82
  function createModernRequest(input, signal) {
127
83
  return new Request(input, {
128
84
  signal
@@ -156,52 +112,6 @@ function createModernShouldReload(shouldRevalidate, state) {
156
112
  return 'boolean' == typeof result ? result : void 0;
157
113
  };
158
114
  }
159
- function wrapModernLoader(modernRoute, modernLoader, revalidationState, options = {}) {
160
- const route = modernRoute;
161
- return async (ctx)=>{
162
- try {
163
- if (revalidationState) rememberRouteLocation(revalidationState, ctx);
164
- if ('function' == typeof route.lazyImport) try {
165
- await route.lazyImport();
166
- } catch {}
167
- const signal = ctx?.abortController?.signal || ctx?.signal || new AbortController().signal;
168
- const baseRequest = ctx?.context?.request instanceof Request ? ctx.context.request : void 0;
169
- const href = 'string' == typeof ctx?.location ? ctx.location : ctx?.location?.publicHref || ctx?.location?.href || ctx?.location?.url?.href || '';
170
- const request = void 0 !== baseRequest ? new Request(baseRequest, {
171
- signal
172
- }) : createModernRequest(href, signal);
173
- const params = mapParamsForModernLoader({
174
- modernRoute,
175
- params: ctx.params || {}
176
- });
177
- const loadModernData = async ()=>{
178
- const result = modernLoader ? await modernLoader({
179
- request,
180
- params,
181
- context: ctx?.context?.requestContext
182
- }) : null;
183
- return normalizeModernLoaderResponse(result);
184
- };
185
- if (options.rscPayloadRouter && isTanstackRscPayloadNavigationEnabled()) return loadTanstackRscRouteData({
186
- hasClientLoader: route.hasClientLoader || void 0 !== route.clientData,
187
- loadClientData: loadModernData,
188
- request,
189
- routeId: ctx.route?.id
190
- });
191
- return loadModernData();
192
- } catch (err) {
193
- if (isResponse(err)) {
194
- if (isTanstackRedirect(err)) throw err;
195
- if (isRedirectResponse(err)) {
196
- const location = err.headers.get('Location') || '/';
197
- throwTanstackRedirect(location);
198
- }
199
- if (404 === err.status) throw notFound();
200
- }
201
- throw err;
202
- }
203
- };
204
- }
205
115
  function isRouteObjectPathlessLayout(route) {
206
116
  return !route.path && !route.index;
207
117
  }
@@ -276,11 +186,6 @@ function toRouteComponent(routeObject) {
276
186
  const element = route.element;
277
187
  if (element) return ()=>element;
278
188
  }
279
- function toModernRouteComponent(route) {
280
- const component = route.component || void 0;
281
- if ('function' == typeof route.lazyImport && component) return createServerLazyImportComponent(route.lazyImport, component);
282
- return component;
283
- }
284
189
  function toErrorComponent(routeObject) {
285
190
  const route = routeObject;
286
191
  if (route.ErrorBoundary) return route.ErrorBoundary;
@@ -356,105 +261,6 @@ function createRouteFromRouteObject(opts) {
356
261
  }
357
262
  return route;
358
263
  }
359
- function createRouteFromModernRoute(opts) {
360
- const { options = {}, parent, modernRoute } = opts;
361
- const route = modernRoute;
362
- const revalidationState = {};
363
- const modernId = route.id;
364
- const stableFallbackId = modernId || route._component || route.filename || route.data || ('function' == typeof route.loader ? route.id : void 0);
365
- const pendingComponent = route.loading || route.pendingComponent;
366
- const errorComponent = route.error || route.errorComponent;
367
- const component = toModernRouteComponent(route);
368
- const modernLoader = route.loader;
369
- const modernAction = route.action;
370
- const modernShouldRevalidate = route.shouldRevalidate;
371
- const shouldReload = createModernShouldReload(modernShouldRevalidate, revalidationState);
372
- const isPathlessLayout = 'nested' === route.type && 'boolean' != typeof route.index && void 0 === route.path;
373
- const isIndexRoute = 'nested' === route.type && Boolean(route.index);
374
- const base = {
375
- getParentRoute: ()=>parent,
376
- component: component || void 0,
377
- pendingComponent: pendingComponent || void 0,
378
- errorComponent: errorComponent || void 0,
379
- validateSearch: route.validateSearch,
380
- loaderDeps: route.loaderDeps,
381
- staticData: createRouteStaticData({
382
- modernRouteId: modernId,
383
- modernRouteAction: modernAction,
384
- modernRouteHandle: mergeModernRouteHandle(route),
385
- modernRouteHasAction: route.hasAction || Boolean(modernAction),
386
- modernRouteHasClientLoader: route.hasClientLoader || void 0 !== route.clientData,
387
- modernRouteHasLoader: route.hasLoader || 'function' == typeof modernLoader,
388
- modernRouteIsClientComponent: route.isClientComponent,
389
- modernRouteLoader: modernLoader,
390
- modernRouteShouldRevalidate: modernShouldRevalidate
391
- }),
392
- loader: wrapModernLoader(modernRoute, modernLoader, revalidationState, options)
393
- };
394
- if (route.inValidSSRRoute) base.ssr = false;
395
- if (shouldReload) base.shouldReload = shouldReload;
396
- if (isPathlessLayout) base.id = stableFallbackId || 'pathless';
397
- else {
398
- const rawPath = route.path;
399
- base.path = isIndexRoute ? '/' : toTanstackPath(rawPath || '');
400
- }
401
- const tanstackRoute = createTanstackRoute(base);
402
- wrapRouteComponentWithModernContext(tanstackRoute, component, modernId);
403
- const children = route.children;
404
- if (children && children.length > 0) {
405
- const childRoutes = children.map((child)=>createRouteFromModernRoute({
406
- options,
407
- parent: tanstackRoute,
408
- modernRoute: child
409
- }));
410
- tanstackRoute.addChildren(childRoutes);
411
- }
412
- return tanstackRoute;
413
- }
414
- function createRouteTreeFromModernRoutes(routes, options = {}) {
415
- const rootModern = routes.find((r)=>r && 'nested' === r.type && r.isRoot);
416
- const rootComponent = rootModern ? toModernRouteComponent(rootModern) : void 0;
417
- const pendingComponent = rootModern?.loading;
418
- const errorComponent = rootModern?.error;
419
- const rootLoader = rootModern?.loader;
420
- const rootAction = rootModern?.action;
421
- const rootModernId = rootModern?.id;
422
- const rootShouldRevalidate = rootModern?.shouldRevalidate;
423
- const rootRevalidationState = {};
424
- const rootShouldReload = createModernShouldReload(rootShouldRevalidate, rootRevalidationState);
425
- const rootRouteOptions = {
426
- component: rootComponent || void 0,
427
- pendingComponent: pendingComponent || void 0,
428
- errorComponent: errorComponent || void 0,
429
- validateSearch: rootModern?.validateSearch,
430
- loaderDeps: rootModern?.loaderDeps,
431
- notFoundComponent: DefaultNotFound,
432
- staticData: createRouteStaticData({
433
- modernRouteId: rootModernId,
434
- modernRouteAction: rootAction,
435
- modernRouteHandle: rootModern ? mergeModernRouteHandle(rootModern) : void 0,
436
- modernRouteHasAction: rootModern?.hasAction || Boolean(rootAction),
437
- modernRouteHasClientLoader: rootModern?.hasClientLoader || void 0 !== rootModern?.clientData,
438
- modernRouteHasLoader: rootModern?.hasLoader || 'function' == typeof rootLoader,
439
- modernRouteIsClientComponent: rootModern?.isClientComponent,
440
- modernRouteLoader: rootLoader,
441
- modernRouteShouldRevalidate: rootShouldRevalidate
442
- }),
443
- loader: rootModern ? wrapModernLoader(rootModern, rootLoader, rootRevalidationState, options) : void 0
444
- };
445
- if (rootShouldReload) rootRouteOptions.shouldReload = rootShouldReload;
446
- if (rootModern?.inValidSSRRoute) rootRouteOptions.ssr = false;
447
- const rootRoute = createTanstackRootRoute(rootRouteOptions);
448
- if (rootComponent) rootRoute.options.component = withModernRouteMatchContext(rootComponent, rootRouteId);
449
- const topLevel = rootModern ? rootModern.children || [] : routes;
450
- const childRoutes = topLevel.map((child)=>createRouteFromModernRoute({
451
- options,
452
- parent: rootRoute,
453
- modernRoute: child
454
- }));
455
- rootRoute.addChildren(childRoutes);
456
- return rootRoute;
457
- }
458
264
  function getRootLikeRouteObject(routes) {
459
265
  return routes.find((route)=>'/' === route.path && !route.index);
460
266
  }
@@ -510,4 +316,4 @@ function getModernRouteIdsFromMatches(router) {
510
316
  }).filter((id)=>'string' == typeof id);
511
317
  return Array.from(new Set(ids));
512
318
  }
513
- export { createRouteTreeFromModernRoutes, createRouteTreeFromRouteObjects, getModernRouteIdsFromMatches };
319
+ export { createRouteTreeFromRouteObjects, getModernRouteIdsFromMatches };
@@ -0,0 +1,3 @@
1
+ import "node:module";
2
+ import "./register.mjs";
3
+ export { routerPlugin } from "@modern-js/runtime/router/internal";
@@ -1,4 +1,5 @@
1
1
  import "node:module";
2
+ import { isRouteErrorResponse } from "@modern-js/runtime-utils/router";
2
3
  import { notFound, redirect } from "@tanstack/react-router";
3
4
  const payloadFetchCache = new Map();
4
5
  let payloadDecoder;
@@ -38,6 +39,39 @@ function toPayloadRoute(match) {
38
39
  pathnameBase: 'string' == typeof match.pathnameBase ? match.pathnameBase : pathname
39
40
  };
40
41
  }
42
+ function shouldRedactServerError(status = 500) {
43
+ return status >= 500 && 'development' !== process.env.NODE_ENV && 'test' !== process.env.NODE_ENV;
44
+ }
45
+ function serializePayloadError(error) {
46
+ if (isRouteErrorResponse(error)) {
47
+ if (shouldRedactServerError(error.status)) return {
48
+ status: error.status,
49
+ statusText: 'Internal Server Error',
50
+ data: 'Unexpected Server Error',
51
+ __type: 'RouteErrorResponse'
52
+ };
53
+ return {
54
+ ...error,
55
+ __type: 'RouteErrorResponse'
56
+ };
57
+ }
58
+ if (error instanceof Error) {
59
+ if (shouldRedactServerError()) return {
60
+ message: 'Unexpected Server Error',
61
+ stack: void 0,
62
+ __type: 'Error'
63
+ };
64
+ return {
65
+ message: error.message,
66
+ stack: error.stack,
67
+ __type: 'Error',
68
+ ...'Error' !== error.name ? {
69
+ __subType: error.name
70
+ } : {}
71
+ };
72
+ }
73
+ return error;
74
+ }
41
75
  function createTanstackRscServerPayload(router, options = {}) {
42
76
  const matches = Array.isArray(router.state?.matches) ? router.state.matches : [];
43
77
  const routes = [];
@@ -48,7 +82,7 @@ function createTanstackRscServerPayload(router, options = {}) {
48
82
  if (payloadRoute) {
49
83
  routes.push(payloadRoute);
50
84
  if ('loaderData' in match && void 0 !== match.loaderData && !(options.omitClientLoaderData && payloadRoute.hasClientLoader)) loaderData[payloadRoute.id] = match.loaderData;
51
- if (void 0 !== match.error) errors[payloadRoute.id] = match.error;
85
+ if (void 0 !== match.error) errors[payloadRoute.id] = serializePayloadError(match.error);
52
86
  }
53
87
  }
54
88
  return {
@@ -0,0 +1,8 @@
1
+ import "node:module";
2
+ import { getRouterRuntimeState } from "@modern-js/runtime/context";
3
+ function getTanstackRouterState(context) {
4
+ const state = getRouterRuntimeState(context);
5
+ if (void 0 === state || 'tanstack' !== state.framework) return;
6
+ return state;
7
+ }
8
+ export { getTanstackRouterState };
@@ -1,7 +1,6 @@
1
1
  import "node:module";
2
2
  import { jsx } from "react/jsx-runtime";
3
3
  import react from "react";
4
- import { DefaultNotFound } from "./DefaultNotFound.mjs";
5
4
  function getRouteObjects(routes, { globalApp, ssrMode, props }) {
6
5
  const createLayoutElement = (Component)=>{
7
6
  const GlobalLayout = globalApp;
@@ -58,10 +57,6 @@ function getRouteObjects(routes, { globalApp, ssrMode, props }) {
58
57
  };
59
58
  routeObjects.push(routeObject);
60
59
  }
61
- routeObjects.push({
62
- path: '*',
63
- element: /*#__PURE__*/ jsx(DefaultNotFound, {})
64
- });
65
60
  return routeObjects;
66
61
  }
67
62
  function createRouteObjectsFromConfig({ routesConfig, props, ssrMode }) {
@@ -2,8 +2,8 @@ import type { AppTools, AppToolsContext, CliPlugin } from '@modern-js/app-tools'
2
2
  import type { NestedRouteForCli, PageRoute } from '@modern-js/types';
3
3
  import { type TanstackRouteCodeSplittingOption } from './routeSplitting';
4
4
  export type { TanstackRouteCodeSplittingOption, TanstackRsbuildRouteSplittingProfile, } from './routeSplitting';
5
- export { createTanstackRsbuildRouteSplittingProfile, isTanstackStartRouteModuleSource, resolveTanstackRouteCodeSplittingEnabled, } from './routeSplitting';
6
- export { collectCanonicalRoutesForEntry, generateTanstackRouterTypesSourceForEntry, isTanstackRouterFrameworkEnabled, } from './tanstackTypes';
5
+ export { createTanstackRsbuildRouteSplittingProfile, resolveTanstackRouteCodeSplittingEnabled, } from './routeSplitting';
6
+ export { type CollectCanonicalRoutesOptions, collectCanonicalRoutesForEntry, generateTanstackRouterTypesSourceForEntry, } from './tanstackTypes';
7
7
  export type TanstackRouterPluginOptions = {
8
8
  routesDir?: string;
9
9
  generatedDirName?: string;
@@ -21,6 +21,13 @@ export declare function writeTanstackRouterTypesForEntries(opts: {
21
21
  appContext: AppToolsContext;
22
22
  generatedDirName?: string;
23
23
  routesByEntry: Record<string, (NestedRouteForCli | PageRoute)[]>;
24
+ /**
25
+ * Whether `@modern-js/plugin-i18n` is actually installed in the app. The
26
+ * `register.gen.d.ts` augmentation of '@modern-js/plugin-i18n/runtime' is
27
+ * only emitted when this is true — otherwise apps with a hand-rolled
28
+ * `/:lang/` param would fail typechecking on an unresolvable module.
29
+ */
30
+ i18nPluginInstalled?: boolean;
24
31
  }): Promise<void>;
25
32
  export declare function tanstackRouterPlugin(options?: TanstackRouterPluginOptions): CliPlugin<AppTools>;
26
33
  export default tanstackRouterPlugin;
@@ -7,23 +7,14 @@ export type TanstackRsbuildRouteSplittingProfile = {
7
7
  splitRouteChunks: boolean;
8
8
  };
9
9
  };
10
- modernRouteChunks: {
11
- enabled: boolean;
12
- owner: 'modern';
13
- };
14
- builderChunkSplit: {
15
- owner: 'modern-rsbuild';
16
- preserved: true;
17
- };
18
- tanstackStartRspackSplitter: {
19
- compatible: boolean;
20
- reason: string;
21
- clientDeleteNodes: string[];
22
- routeFactoryCalls: string[];
23
- };
24
10
  };
25
- export declare function isTanstackStartRouteModuleSource(source: string): boolean;
26
11
  export declare function resolveTanstackRouteCodeSplittingEnabled(option?: TanstackRouteCodeSplittingOption): boolean;
12
+ /**
13
+ * Route chunking for TanStack entries is owned by Modern's
14
+ * `output.splitRouteChunks`; the TanStack Start Rspack splitter does not
15
+ * apply because Modern generates TanStack route trees from Modern route
16
+ * metadata rather than TanStack file-route factory modules.
17
+ */
27
18
  export declare function createTanstackRsbuildRouteSplittingProfile(opts: {
28
19
  routeCodeSplitting?: TanstackRouteCodeSplittingOption;
29
20
  }): TanstackRsbuildRouteSplittingProfile;
@@ -1,5 +1,17 @@
1
1
  import type { AppToolsContext } from '@modern-js/app-tools';
2
2
  import type { NestedRouteForCli, PageRoute } from '@modern-js/types';
3
+ export type CollectCanonicalRoutesOptions = {
4
+ /**
5
+ * Whether a leading `:lang`/`:locale`/`:language` route param may be
6
+ * treated as an i18n locale prefix. This MUST only be enabled when
7
+ * `@modern-js/plugin-i18n` is actually installed: the emitted
8
+ * `declare module '@modern-js/plugin-i18n/runtime'` augmentation breaks
9
+ * typechecking (TS2664) for apps that hand-roll a `/:lang/` param without
10
+ * the plugin. Routes carrying `modernCanonicalPath` metadata are always
11
+ * honored — only plugin-i18n produces them.
12
+ */
13
+ localeParamHeuristic?: boolean;
14
+ };
3
15
  /**
4
16
  * Derive the canonical (language-agnostic) route map for an entry: the
5
17
  * leading locale param is stripped and localized physical variants (routes
@@ -8,8 +20,7 @@ import type { NestedRouteForCli, PageRoute } from '@modern-js/types';
8
20
  * i18n routing surface (no locale param and no localized variants), so plain
9
21
  * TanStack apps never get a `@modern-js/plugin-i18n` module augmentation.
10
22
  */
11
- export declare function collectCanonicalRoutesForEntry(routes: (NestedRouteForCli | PageRoute)[]): Record<string, string> | null;
12
- export declare function isTanstackRouterFrameworkEnabled(appContext: AppToolsContext): Promise<boolean>;
23
+ export declare function collectCanonicalRoutesForEntry(routes: (NestedRouteForCli | PageRoute)[], options?: CollectCanonicalRoutesOptions): Record<string, string> | null;
13
24
  export declare function generateTanstackRouterTypesSourceForEntry(opts: {
14
25
  appContext: AppToolsContext;
15
26
  entryName: string;
@@ -1,18 +1,8 @@
1
- import type { TRuntimeContext } from '@modern-js/runtime/context';
2
- import type { RouteObject } from '@modern-js/runtime-utils/router';
3
- import type { RouterLifecycleContext } from './lifecycle';
4
- declare const modifyRoutes: import("@modern-js/plugin").SyncHook<(routes: RouteObject[]) => RouteObject[]>;
5
- declare const onBeforeCreateRoutes: import("@modern-js/plugin").SyncHook<(context: TRuntimeContext) => void>;
6
- declare const onBeforeCreateRouter: import("@modern-js/plugin").SyncHook<(context: RouterLifecycleContext) => void>;
7
- declare const onAfterCreateRouter: import("@modern-js/plugin").SyncHook<(context: RouterLifecycleContext) => void>;
8
- declare const onBeforeHydrateRouter: import("@modern-js/plugin").SyncHook<(context: RouterLifecycleContext) => void>;
9
- declare const onAfterHydrateRouter: import("@modern-js/plugin").SyncHook<(context: RouterLifecycleContext) => void>;
10
- export { modifyRoutes, onAfterCreateRouter, onAfterHydrateRouter, onBeforeCreateRouter, onBeforeCreateRoutes, onBeforeHydrateRouter, };
11
- export type RouterExtendsHooks = {
12
- modifyRoutes: typeof modifyRoutes;
13
- onBeforeCreateRoutes: typeof onBeforeCreateRoutes;
14
- onBeforeCreateRouter: typeof onBeforeCreateRouter;
15
- onAfterCreateRouter: typeof onAfterCreateRouter;
16
- onBeforeHydrateRouter: typeof onBeforeHydrateRouter;
17
- onAfterHydrateRouter: typeof onAfterHydrateRouter;
18
- };
1
+ /**
2
+ * The router hooks are owned by @modern-js/runtime — this module re-exports
3
+ * the canonical instances through the `/context` seam, so the TanStack
4
+ * provider taps and calls the exact same hooks the built-in router wrapper
5
+ * registers. Creating separate hook instances here would silently split the
6
+ * hook registry between the wrapper and this provider.
7
+ */
8
+ export { modifyRoutes, onAfterCreateRouter, onAfterHydrateRouter, onBeforeCreateRouter, onBeforeCreateRoutes, onBeforeHydrateRouter, type RouterExtendsHooks, routerProviderRegistryHooks, } from '@modern-js/runtime/context';
@@ -1,12 +1,14 @@
1
- export type * from '@tanstack/react-router';
2
- export { Asset, Await, Block, CatchBoundary, CatchNotFound, ClientOnly, cleanPath, composeRewrites, createBrowserHistory, createControlledPromise, createFileRoute, createHashHistory, createHistory, createLazyFileRoute, createLazyRoute, createLink, createMemoryHistory, createRootRoute, createRootRouteWithContext, createRoute, createRouteMask, createRouter, createRouterConfig, createSerializationAdapter, DEFAULT_PROTOCOL_ALLOWLIST, DefaultGlobalNotFound, deepEqual, defaultParseSearch, defaultStringifySearch, defer, ErrorComponent, FileRoute, FileRouteLoader, functionalUpdate, getRouteApi, HeadContent, interpolatePath, isMatch, isNotFound, isPlainArray, isPlainObject, isRedirect, joinPaths, LazyRoute, lazyFn, lazyRouteComponent, linkOptions, Match, Matches, MatchRoute, Navigate, NotFoundRoute, notFound, parseSearchWith, RootRoute, Route, RouteApi, Router, RouterContextProvider, RouterProvider, reactUse, redirect, replaceEqualDeep, resolvePath, retainSearchParams, rootRouteId, rootRouteWithContext, ScriptOnce, Scripts, ScrollRestoration, SearchParamError, stringifySearchWith, stripSearchParams, trimPath, trimPathLeft, trimPathRight, useAwaited, useBlocker, useCanGoBack, useChildMatches, useElementScrollRestoration, useHydrated, useLayoutEffect, useLinkProps, useLoaderData, useLoaderDeps, useLocation, useMatch, useMatches, useMatchRoute, useNavigate, useParams, useParentMatches, useRouteContext, useRouter, useRouterState, useSearch, useTags, } from '@tanstack/react-router';
1
+ import './register';
2
+ export * from '@tanstack/react-router';
3
3
  export type { Fetcher, FetcherState, FetcherSubmitOptions, FormProps, SubmitOptions, } from './dataMutation';
4
4
  export { Form, RouteActionResponseError, useFetcher, } from './dataMutation';
5
+ export type { ModernRouterContext } from './loaderBridge';
6
+ export { createRouteStaticData, isAbsoluteUrl, modernLoaderToTanstack, throwTanstackRedirect, } from './loaderBridge';
5
7
  export { Outlet } from './outlet';
6
8
  export { tanstackRouterPlugin, tanstackRouterPlugin as default, } from './plugin';
7
9
  export type { LinkProps, NavLinkProps, PrefetchBehavior, } from './prefetchLink';
8
10
  export { Link, NavLink } from './prefetchLink';
9
- export type { AnyCompositeComponent, AnyRenderableServerComponent, CompositeComponentProps, } from './rsc/client';
10
- export { CompositeComponent } from './rsc/client';
11
+ export type { TanstackRouterState } from './state';
12
+ export { getTanstackRouterState } from './state';
11
13
  export type { RouterConfig } from './types';
12
14
  export { getModernTanstackRouterFastDefaults, modernTanstackRouterFastDefaults, } from './types';
@@ -1,22 +1,7 @@
1
- import type { TInternalRuntimeContext } from '@modern-js/runtime/context';
2
- import type { RouteObject } from '@modern-js/runtime-utils/router';
3
- import type { InternalRouterRuntimeState, InternalRouterServerSnapshot, RouterFramework, RouterRouteMatchSnapshot, RouterServerPrepareResult } from './types';
4
- export type RouterLifecyclePhase = 'ssr-prepare' | 'client-create' | 'hydrate';
5
- export type RouterLifecycleContext = {
6
- framework: RouterFramework;
7
- phase: RouterLifecyclePhase;
8
- routes: RouteObject[];
9
- runtimeContext: TInternalRuntimeContext;
10
- basename?: string;
11
- hydrationData?: unknown;
12
- router?: unknown;
13
- matches?: RouterRouteMatchSnapshot[];
14
- cleanup?: () => void | Promise<void>;
15
- serverSnapshot?: InternalRouterServerSnapshot;
16
- };
17
- type RouterSnapshotLike = Partial<InternalRouterServerSnapshot>;
18
- export declare function createRouterServerSnapshot(state: RouterSnapshotLike): InternalRouterServerSnapshot;
19
- export declare function createRouterRuntimeState(state: InternalRouterRuntimeState): InternalRouterRuntimeState;
20
- export declare function applyRouterRuntimeState(runtimeContext: TInternalRuntimeContext, state: InternalRouterRuntimeState): TInternalRuntimeContext;
21
- export declare function applyRouterServerPrepareResult(runtimeContext: TInternalRuntimeContext, result: RouterServerPrepareResult): TInternalRuntimeContext;
22
- export {};
1
+ /**
2
+ * The router runtime state helpers are owned by @modern-js/runtime (the same
3
+ * implementation backs the built-in react-router provider and the SSR
4
+ * pipeline). This module only re-exports them so every router provider
5
+ * writes to the exact same runtime-context extension slot.
6
+ */
7
+ export { applyRouterRuntimeState, applyRouterServerPrepareResult, createRouterRuntimeState, createRouterServerSnapshot, getRouterRuntimeState, getRouterServerSnapshot, type RouterLifecycleContext, type RouterLifecyclePhase, } from '@modern-js/runtime/context';