@bleedingdev/modern-js-plugin-tanstack 3.2.0-ultramodern.99 → 3.4.0-ultramodern.1

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 (127) hide show
  1. package/dist/cjs/cli/index.js +80 -34
  2. package/dist/cjs/cli/routeSplitting.js +13 -41
  3. package/dist/cjs/cli/tanstackTypes.js +114 -200
  4. package/dist/cjs/cli.js +12 -8
  5. package/dist/cjs/runtime/basepathRewrite.js +12 -8
  6. package/dist/cjs/runtime/dataMutation.js +9 -5
  7. package/dist/cjs/runtime/hooks.js +20 -19
  8. package/dist/cjs/runtime/hydrationBoundary.js +12 -7
  9. package/dist/cjs/runtime/index.js +66 -54
  10. package/dist/cjs/runtime/lifecycle.js +21 -91
  11. package/dist/cjs/runtime/loaderBridge.js +173 -0
  12. package/dist/cjs/runtime/outlet.js +58 -0
  13. package/dist/cjs/runtime/plugin.js +190 -110
  14. package/dist/cjs/runtime/plugin.node.js +25 -40
  15. package/dist/cjs/runtime/plugin.worker.js +9 -5
  16. package/dist/cjs/runtime/pluginCore.js +55 -0
  17. package/dist/cjs/runtime/prefetchLink.js +10 -6
  18. package/dist/cjs/runtime/register.js +56 -0
  19. package/dist/cjs/runtime/routeTree.js +30 -212
  20. package/dist/cjs/runtime/router.js +41 -0
  21. package/dist/cjs/runtime/rsc/ClientSlot.js +9 -5
  22. package/dist/cjs/runtime/rsc/CompositeComponent.js +9 -5
  23. package/dist/cjs/runtime/rsc/ReplayableStream.js +14 -9
  24. package/dist/cjs/runtime/rsc/RscNodeRenderer.js +9 -5
  25. package/dist/cjs/runtime/rsc/SlotContext.js +9 -5
  26. package/dist/cjs/runtime/rsc/client.js +9 -5
  27. package/dist/cjs/runtime/rsc/createRscProxy.js +9 -5
  28. package/dist/cjs/runtime/rsc/index.js +9 -5
  29. package/dist/cjs/runtime/rsc/payloadRouter.js +44 -6
  30. package/dist/cjs/runtime/rsc/server.js +9 -5
  31. package/dist/cjs/runtime/rsc/slotUsageSanitizer.js +9 -5
  32. package/dist/cjs/runtime/rsc/symbols.js +20 -15
  33. package/dist/cjs/runtime/state.js +45 -0
  34. package/dist/cjs/runtime/types.js +13 -9
  35. package/dist/cjs/runtime/utils.js +9 -11
  36. package/dist/cjs/runtime.js +9 -5
  37. package/dist/esm/cli/index.mjs +73 -28
  38. package/dist/esm/cli/routeSplitting.mjs +1 -30
  39. package/dist/esm/cli/tanstackTypes.mjs +100 -190
  40. package/dist/esm/runtime/hooks.mjs +1 -8
  41. package/dist/esm/runtime/hydrationBoundary.mjs +3 -2
  42. package/dist/esm/runtime/index.mjs +4 -2
  43. package/dist/esm/runtime/lifecycle.mjs +1 -82
  44. package/dist/esm/runtime/loaderBridge.mjs +114 -0
  45. package/dist/esm/runtime/outlet.mjs +17 -0
  46. package/dist/esm/runtime/plugin.mjs +183 -107
  47. package/dist/esm/runtime/plugin.node.mjs +19 -38
  48. package/dist/esm/runtime/pluginCore.mjs +14 -0
  49. package/dist/esm/runtime/prefetchLink.mjs +1 -1
  50. package/dist/esm/runtime/register.mjs +18 -0
  51. package/dist/esm/runtime/routeTree.mjs +15 -198
  52. package/dist/esm/runtime/router.mjs +2 -0
  53. package/dist/esm/runtime/rsc/payloadRouter.mjs +35 -1
  54. package/dist/esm/runtime/state.mjs +7 -0
  55. package/dist/esm/runtime/utils.mjs +0 -6
  56. package/dist/esm-node/cli/index.mjs +73 -28
  57. package/dist/esm-node/cli/routeSplitting.mjs +1 -30
  58. package/dist/esm-node/cli/tanstackTypes.mjs +100 -190
  59. package/dist/esm-node/runtime/hooks.mjs +1 -8
  60. package/dist/esm-node/runtime/hydrationBoundary.mjs +3 -2
  61. package/dist/esm-node/runtime/index.mjs +4 -2
  62. package/dist/esm-node/runtime/lifecycle.mjs +1 -82
  63. package/dist/esm-node/runtime/loaderBridge.mjs +115 -0
  64. package/dist/esm-node/runtime/outlet.mjs +18 -0
  65. package/dist/esm-node/runtime/plugin.mjs +183 -107
  66. package/dist/esm-node/runtime/plugin.node.mjs +19 -38
  67. package/dist/esm-node/runtime/pluginCore.mjs +15 -0
  68. package/dist/esm-node/runtime/prefetchLink.mjs +1 -1
  69. package/dist/esm-node/runtime/register.mjs +19 -0
  70. package/dist/esm-node/runtime/routeTree.mjs +15 -198
  71. package/dist/esm-node/runtime/router.mjs +3 -0
  72. package/dist/esm-node/runtime/rsc/payloadRouter.mjs +35 -1
  73. package/dist/esm-node/runtime/state.mjs +8 -0
  74. package/dist/esm-node/runtime/utils.mjs +0 -6
  75. package/dist/types/cli/index.d.ts +11 -2
  76. package/dist/types/cli/routeSplitting.d.ts +6 -15
  77. package/dist/types/cli/tanstackTypes.d.ts +21 -1
  78. package/dist/types/runtime/hooks.d.ts +8 -33
  79. package/dist/types/runtime/index.d.ts +6 -3
  80. package/dist/types/runtime/lifecycle.d.ts +7 -22
  81. package/dist/types/runtime/loaderBridge.d.ts +48 -0
  82. package/dist/types/runtime/outlet.d.ts +2 -0
  83. package/dist/types/runtime/plugin.d.ts +1 -14
  84. package/dist/types/runtime/plugin.node.d.ts +1 -14
  85. package/dist/types/runtime/pluginCore.d.ts +21 -0
  86. package/dist/types/runtime/register.d.ts +9 -0
  87. package/dist/types/runtime/routeTree.d.ts +0 -2
  88. package/dist/types/runtime/router.d.ts +14 -0
  89. package/dist/types/runtime/state.d.ts +16 -0
  90. package/dist/types/runtime/types.d.ts +7 -53
  91. package/package.json +41 -39
  92. package/rstest.config.mts +6 -0
  93. package/src/cli/index.ts +146 -24
  94. package/src/cli/routeSplitting.ts +6 -44
  95. package/src/cli/tanstackTypes.ts +203 -208
  96. package/src/runtime/hooks.ts +10 -27
  97. package/src/runtime/hydrationBoundary.tsx +5 -5
  98. package/src/runtime/index.tsx +12 -14
  99. package/src/runtime/lifecycle.ts +16 -151
  100. package/src/runtime/loaderBridge.ts +257 -0
  101. package/src/runtime/outlet.tsx +48 -0
  102. package/src/runtime/plugin.node.tsx +28 -83
  103. package/src/runtime/plugin.tsx +350 -202
  104. package/src/runtime/pluginCore.ts +48 -0
  105. package/src/runtime/prefetchLink.tsx +1 -1
  106. package/src/runtime/register.ts +58 -0
  107. package/src/runtime/routeTree.ts +41 -365
  108. package/src/runtime/router.ts +15 -0
  109. package/src/runtime/rsc/payloadRouter.ts +45 -2
  110. package/src/runtime/ssr-shim.d.ts +1 -3
  111. package/src/runtime/state.ts +29 -0
  112. package/src/runtime/types.ts +20 -67
  113. package/src/runtime/utils.tsx +3 -7
  114. package/tests/router/cli.test.ts +373 -31
  115. package/tests/router/hooks.test.ts +26 -0
  116. package/tests/router/loaderBridge.test.ts +211 -0
  117. package/tests/router/packageSurface.test.ts +24 -0
  118. package/tests/router/prefetchLink.test.tsx +43 -7
  119. package/tests/router/register.test.ts +46 -0
  120. package/tests/router/routeTree.test.ts +176 -139
  121. package/tests/router/rsc.test.tsx +70 -0
  122. package/tests/router/tanstackTypes.test.ts +395 -7
  123. package/dist/cjs/runtime/DefaultNotFound.js +0 -47
  124. package/dist/esm/runtime/DefaultNotFound.mjs +0 -13
  125. package/dist/esm-node/runtime/DefaultNotFound.mjs +0 -14
  126. package/dist/types/runtime/DefaultNotFound.d.ts +0 -2
  127. package/src/runtime/DefaultNotFound.tsx +0 -15
@@ -1,7 +1,9 @@
1
1
  import "node:module";
2
- import { createRootRoute, createRoute, notFound, redirect } 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";
6
+ import { withModernRouteMatchContext } from "./outlet.mjs";
5
7
  import { isTanstackRscPayloadNavigationEnabled, loadTanstackRscRouteData } from "./rsc/payloadRouter.mjs";
6
8
  function createTanstackRoute(options) {
7
9
  return createRoute(options);
@@ -9,6 +11,10 @@ function createTanstackRoute(options) {
9
11
  function createTanstackRootRoute(options) {
10
12
  return createRootRoute(options);
11
13
  }
14
+ function wrapRouteComponentWithModernContext(route, component, routeId) {
15
+ const routeMatchId = routeId || route.id;
16
+ if (component && routeMatchId) route.options.component = withModernRouteMatchContext(component, routeMatchId);
17
+ }
12
18
  function toTanstackPath(pathname) {
13
19
  return pathname.split('/').map((segment)=>{
14
20
  if (!segment) return segment;
@@ -21,23 +27,6 @@ function toTanstackPath(pathname) {
21
27
  return segment;
22
28
  }).join('/');
23
29
  }
24
- function isResponse(value) {
25
- const record = value;
26
- return null != record && 'object' == typeof record && 'number' == typeof record.status && 'object' == typeof record.headers;
27
- }
28
- function isTanstackRedirect(value) {
29
- return isResponse(value) && 'object' == typeof value.options;
30
- }
31
- const redirectStatusCodes = new Set([
32
- 301,
33
- 302,
34
- 303,
35
- 307,
36
- 308
37
- ]);
38
- function isRedirectResponse(res) {
39
- return redirectStatusCodes.has(res.status);
40
- }
41
30
  function isModernDeferredData(value) {
42
31
  if (!value || 'object' != typeof value) return false;
43
32
  const deferred = value;
@@ -90,34 +79,6 @@ function createServerLazyImportComponent(lazyImport, fallbackComponent) {
90
79
  Component.preload = load;
91
80
  return Component;
92
81
  }
93
- function isAbsoluteUrl(value) {
94
- try {
95
- new URL(value);
96
- return true;
97
- } catch {
98
- return false;
99
- }
100
- }
101
- function throwTanstackRedirect(location) {
102
- const target = location || '/';
103
- if (isAbsoluteUrl(target)) throw redirect({
104
- href: target
105
- });
106
- throw redirect({
107
- to: target
108
- });
109
- }
110
- function mapParamsForModernLoader({ modernRoute, params }) {
111
- if ('nested' === modernRoute.type && modernRoute.path?.includes('*')) {
112
- const { _splat, ...rest } = params;
113
- if (void 0 !== _splat) return {
114
- ...rest,
115
- '*': _splat
116
- };
117
- return rest;
118
- }
119
- return params;
120
- }
121
82
  function createModernRequest(input, signal) {
122
83
  return new Request(input, {
123
84
  signal
@@ -151,52 +112,6 @@ function createModernShouldReload(shouldRevalidate, state) {
151
112
  return 'boolean' == typeof result ? result : void 0;
152
113
  };
153
114
  }
154
- function wrapModernLoader(modernRoute, modernLoader, revalidationState, options = {}) {
155
- const route = modernRoute;
156
- return async (ctx)=>{
157
- try {
158
- if (revalidationState) rememberRouteLocation(revalidationState, ctx);
159
- if ('function' == typeof route.lazyImport) try {
160
- await route.lazyImport();
161
- } catch {}
162
- const signal = ctx?.abortController?.signal || ctx?.signal || new AbortController().signal;
163
- const baseRequest = ctx?.context?.request instanceof Request ? ctx.context.request : void 0;
164
- const href = 'string' == typeof ctx?.location ? ctx.location : ctx?.location?.publicHref || ctx?.location?.href || ctx?.location?.url?.href || '';
165
- const request = void 0 !== baseRequest ? new Request(baseRequest, {
166
- signal
167
- }) : createModernRequest(href, signal);
168
- const params = mapParamsForModernLoader({
169
- modernRoute,
170
- params: ctx.params || {}
171
- });
172
- const loadModernData = async ()=>{
173
- const result = modernLoader ? await modernLoader({
174
- request,
175
- params,
176
- context: ctx?.context?.requestContext
177
- }) : null;
178
- return normalizeModernLoaderResponse(result);
179
- };
180
- if (options.rscPayloadRouter && isTanstackRscPayloadNavigationEnabled()) return loadTanstackRscRouteData({
181
- hasClientLoader: route.hasClientLoader || void 0 !== route.clientData,
182
- loadClientData: loadModernData,
183
- request,
184
- routeId: ctx.route?.id
185
- });
186
- return loadModernData();
187
- } catch (err) {
188
- if (isResponse(err)) {
189
- if (isTanstackRedirect(err)) throw err;
190
- if (isRedirectResponse(err)) {
191
- const location = err.headers.get('Location') || '/';
192
- throwTanstackRedirect(location);
193
- }
194
- if (404 === err.status) throw notFound();
195
- }
196
- throw err;
197
- }
198
- };
199
- }
200
115
  function isRouteObjectPathlessLayout(route) {
201
116
  return !route.path && !route.index;
202
117
  }
@@ -271,11 +186,6 @@ function toRouteComponent(routeObject) {
271
186
  const element = route.element;
272
187
  if (element) return ()=>element;
273
188
  }
274
- function toModernRouteComponent(route) {
275
- const component = route.component || void 0;
276
- if ('function' == typeof route.lazyImport && component) return createServerLazyImportComponent(route.lazyImport, component);
277
- return component;
278
- }
279
189
  function toErrorComponent(routeObject) {
280
190
  const route = routeObject;
281
191
  if (route.ErrorBoundary) return route.ErrorBoundary;
@@ -313,9 +223,10 @@ function createRouteFromRouteObject(opts) {
313
223
  const shouldRevalidate = modernRouteObject.shouldRevalidate;
314
224
  const shouldReload = createModernShouldReload(shouldRevalidate, revalidationState);
315
225
  const stableFallbackId = routeObject.id || modernRouteObject.file || routeObject.path || 'pathless';
226
+ const component = toRouteComponent(routeObject);
316
227
  const base = {
317
228
  getParentRoute: ()=>parent,
318
- component: toRouteComponent(routeObject),
229
+ component,
319
230
  pendingComponent: toPendingComponent(routeObject),
320
231
  errorComponent: toErrorComponent(routeObject),
321
232
  validateSearch: modernRouteObject.validateSearch,
@@ -338,6 +249,7 @@ function createRouteFromRouteObject(opts) {
338
249
  if (isRouteObjectPathlessLayout(routeObject)) base.id = stableFallbackId;
339
250
  else base.path = routeObject.index ? '/' : toTanstackPath(routeObject.path || '');
340
251
  const route = createTanstackRoute(base);
252
+ wrapRouteComponentWithModernContext(route, component, routeObject.id);
341
253
  const children = routeObject.children;
342
254
  if (children && children.length > 0) {
343
255
  const childRoutes = children.map((child)=>createRouteFromRouteObject({
@@ -349,103 +261,6 @@ function createRouteFromRouteObject(opts) {
349
261
  }
350
262
  return route;
351
263
  }
352
- function createRouteFromModernRoute(opts) {
353
- const { options = {}, parent, modernRoute } = opts;
354
- const route = modernRoute;
355
- const revalidationState = {};
356
- const modernId = route.id;
357
- const stableFallbackId = modernId || route._component || route.filename || route.data || ('function' == typeof route.loader ? route.id : void 0);
358
- const pendingComponent = route.loading || route.pendingComponent;
359
- const errorComponent = route.error || route.errorComponent;
360
- const component = toModernRouteComponent(route);
361
- const modernLoader = route.loader;
362
- const modernAction = route.action;
363
- const modernShouldRevalidate = route.shouldRevalidate;
364
- const shouldReload = createModernShouldReload(modernShouldRevalidate, revalidationState);
365
- const isPathlessLayout = 'nested' === route.type && 'boolean' != typeof route.index && void 0 === route.path;
366
- const isIndexRoute = 'nested' === route.type && Boolean(route.index);
367
- const base = {
368
- getParentRoute: ()=>parent,
369
- component: component || void 0,
370
- pendingComponent: pendingComponent || void 0,
371
- errorComponent: errorComponent || void 0,
372
- validateSearch: route.validateSearch,
373
- loaderDeps: route.loaderDeps,
374
- staticData: createRouteStaticData({
375
- modernRouteId: modernId,
376
- modernRouteAction: modernAction,
377
- modernRouteHandle: mergeModernRouteHandle(route),
378
- modernRouteHasAction: route.hasAction || Boolean(modernAction),
379
- modernRouteHasClientLoader: route.hasClientLoader || void 0 !== route.clientData,
380
- modernRouteHasLoader: route.hasLoader || 'function' == typeof modernLoader,
381
- modernRouteIsClientComponent: route.isClientComponent,
382
- modernRouteLoader: modernLoader,
383
- modernRouteShouldRevalidate: modernShouldRevalidate
384
- }),
385
- loader: wrapModernLoader(modernRoute, modernLoader, revalidationState, options)
386
- };
387
- if (route.inValidSSRRoute) base.ssr = false;
388
- if (shouldReload) base.shouldReload = shouldReload;
389
- if (isPathlessLayout) base.id = stableFallbackId || 'pathless';
390
- else {
391
- const rawPath = route.path;
392
- base.path = isIndexRoute ? '/' : toTanstackPath(rawPath || '');
393
- }
394
- const tanstackRoute = createTanstackRoute(base);
395
- const children = route.children;
396
- if (children && children.length > 0) {
397
- const childRoutes = children.map((child)=>createRouteFromModernRoute({
398
- options,
399
- parent: tanstackRoute,
400
- modernRoute: child
401
- }));
402
- tanstackRoute.addChildren(childRoutes);
403
- }
404
- return tanstackRoute;
405
- }
406
- function createRouteTreeFromModernRoutes(routes, options = {}) {
407
- const rootModern = routes.find((r)=>r && 'nested' === r.type && r.isRoot);
408
- const rootComponent = rootModern ? toModernRouteComponent(rootModern) : void 0;
409
- const pendingComponent = rootModern?.loading;
410
- const errorComponent = rootModern?.error;
411
- const rootLoader = rootModern?.loader;
412
- const rootAction = rootModern?.action;
413
- const rootModernId = rootModern?.id;
414
- const rootShouldRevalidate = rootModern?.shouldRevalidate;
415
- const rootRevalidationState = {};
416
- const rootShouldReload = createModernShouldReload(rootShouldRevalidate, rootRevalidationState);
417
- const rootRouteOptions = {
418
- component: rootComponent || void 0,
419
- pendingComponent: pendingComponent || void 0,
420
- errorComponent: errorComponent || void 0,
421
- validateSearch: rootModern?.validateSearch,
422
- loaderDeps: rootModern?.loaderDeps,
423
- notFoundComponent: DefaultNotFound,
424
- staticData: createRouteStaticData({
425
- modernRouteId: rootModernId,
426
- modernRouteAction: rootAction,
427
- modernRouteHandle: rootModern ? mergeModernRouteHandle(rootModern) : void 0,
428
- modernRouteHasAction: rootModern?.hasAction || Boolean(rootAction),
429
- modernRouteHasClientLoader: rootModern?.hasClientLoader || void 0 !== rootModern?.clientData,
430
- modernRouteHasLoader: rootModern?.hasLoader || 'function' == typeof rootLoader,
431
- modernRouteIsClientComponent: rootModern?.isClientComponent,
432
- modernRouteLoader: rootLoader,
433
- modernRouteShouldRevalidate: rootShouldRevalidate
434
- }),
435
- loader: rootModern ? wrapModernLoader(rootModern, rootLoader, rootRevalidationState, options) : void 0
436
- };
437
- if (rootShouldReload) rootRouteOptions.shouldReload = rootShouldReload;
438
- if (rootModern?.inValidSSRRoute) rootRouteOptions.ssr = false;
439
- const rootRoute = createTanstackRootRoute(rootRouteOptions);
440
- const topLevel = rootModern ? rootModern.children || [] : routes;
441
- const childRoutes = topLevel.map((child)=>createRouteFromModernRoute({
442
- options,
443
- parent: rootRoute,
444
- modernRoute: child
445
- }));
446
- rootRoute.addChildren(childRoutes);
447
- return rootRoute;
448
- }
449
264
  function getRootLikeRouteObject(routes) {
450
265
  return routes.find((route)=>'/' === route.path && !route.index);
451
266
  }
@@ -454,8 +269,9 @@ function createRouteTreeFromRouteObjects(routes, options = {}) {
454
269
  const rootRevalidationState = {};
455
270
  const rootShouldRevalidate = rootLikeRoute?.shouldRevalidate;
456
271
  const rootShouldReload = createModernShouldReload(rootShouldRevalidate, rootRevalidationState);
272
+ const rootComponent = rootLikeRoute ? toRouteComponent(rootLikeRoute) : void 0;
457
273
  const rootRouteOptions = {
458
- component: rootLikeRoute ? toRouteComponent(rootLikeRoute) : void 0,
274
+ component: rootComponent,
459
275
  pendingComponent: rootLikeRoute ? toPendingComponent(rootLikeRoute) : void 0,
460
276
  errorComponent: rootLikeRoute ? toErrorComponent(rootLikeRoute) : void 0,
461
277
  validateSearch: rootLikeRoute?.validateSearch,
@@ -477,6 +293,7 @@ function createRouteTreeFromRouteObjects(routes, options = {}) {
477
293
  if (rootShouldReload) rootRouteOptions.shouldReload = rootShouldReload;
478
294
  if (rootLikeRoute?.inValidSSRRoute) rootRouteOptions.ssr = false;
479
295
  const rootRoute = createTanstackRootRoute(rootRouteOptions);
296
+ if (rootComponent) rootRoute.options.component = withModernRouteMatchContext(rootComponent, rootRouteId);
480
297
  const topLevel = rootLikeRoute ? [
481
298
  ...rootLikeRoute.children || [],
482
299
  ...routes.filter((route)=>route !== rootLikeRoute)
@@ -499,4 +316,4 @@ function getModernRouteIdsFromMatches(router) {
499
316
  }).filter((id)=>'string' == typeof id);
500
317
  return Array.from(new Set(ids));
501
318
  }
502
- 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;
@@ -22,7 +21,6 @@ function getRouteObjects(routes, { globalApp, ssrMode, props }) {
22
21
  id: route.id,
23
22
  loader: route.loader,
24
23
  action: route.action,
25
- hasErrorBoundary: route.hasErrorBoundary,
26
24
  shouldRevalidate: route.shouldRevalidate,
27
25
  handle: {
28
26
  ...route.handle,
@@ -58,10 +56,6 @@ function getRouteObjects(routes, { globalApp, ssrMode, props }) {
58
56
  };
59
57
  routeObjects.push(routeObject);
60
58
  }
61
- routeObjects.push({
62
- path: '*',
63
- element: /*#__PURE__*/ jsx(DefaultNotFound, {})
64
- });
65
59
  return routeObjects;
66
60
  }
67
61
  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 { 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;
@@ -14,11 +14,20 @@ export declare function writeTanstackRegisterFile(opts: {
14
14
  generatedDirName?: string;
15
15
  runtimeModule?: string;
16
16
  srcDirectory: string;
17
+ canonicalRoutes?: Record<string, string> | null;
18
+ i18nRuntimeModule?: string;
17
19
  }): Promise<void>;
18
20
  export declare function writeTanstackRouterTypesForEntries(opts: {
19
21
  appContext: AppToolsContext;
20
22
  generatedDirName?: string;
21
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;
22
31
  }): Promise<void>;
23
32
  export declare function tanstackRouterPlugin(options?: TanstackRouterPluginOptions): CliPlugin<AppTools>;
24
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,6 +1,26 @@
1
1
  import type { AppToolsContext } from '@modern-js/app-tools';
2
2
  import type { NestedRouteForCli, PageRoute } from '@modern-js/types';
3
- export declare function isTanstackRouterFrameworkEnabled(appContext: AppToolsContext): Promise<boolean>;
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
+ };
15
+ /**
16
+ * Derive the canonical (language-agnostic) route map for an entry: the
17
+ * leading locale param is stripped and localized physical variants (routes
18
+ * carrying `modernCanonicalPath` metadata from `@modern-js/plugin-i18n`)
19
+ * collapse to their canonical pattern. Returns `null` when the entry has no
20
+ * i18n routing surface (no locale param and no localized variants), so plain
21
+ * TanStack apps never get a `@modern-js/plugin-i18n` module augmentation.
22
+ */
23
+ export declare function collectCanonicalRoutesForEntry(routes: (NestedRouteForCli | PageRoute)[], options?: CollectCanonicalRoutesOptions): Record<string, string> | null;
4
24
  export declare function generateTanstackRouterTypesSourceForEntry(opts: {
5
25
  appContext: AppToolsContext;
6
26
  entryName: string;
@@ -1,33 +1,8 @@
1
- declare const modifyRoutes: {
2
- tap: (cb: any) => void;
3
- call: (...params: any[]) => any;
4
- };
5
- declare const onBeforeCreateRoutes: {
6
- tap: (cb: any) => void;
7
- call: (...params: any[]) => any;
8
- };
9
- declare const onBeforeCreateRouter: {
10
- tap: (cb: any) => void;
11
- call: (...params: any[]) => any;
12
- };
13
- declare const onAfterCreateRouter: {
14
- tap: (cb: any) => void;
15
- call: (...params: any[]) => any;
16
- };
17
- declare const onBeforeHydrateRouter: {
18
- tap: (cb: any) => void;
19
- call: (...params: any[]) => any;
20
- };
21
- declare const onAfterHydrateRouter: {
22
- tap: (cb: any) => void;
23
- call: (...params: any[]) => any;
24
- };
25
- export { modifyRoutes, onAfterCreateRouter, onAfterHydrateRouter, onBeforeCreateRouter, onBeforeCreateRoutes, onBeforeHydrateRouter, };
26
- export type RouterExtendsHooks = {
27
- modifyRoutes: typeof modifyRoutes;
28
- onBeforeCreateRoutes: typeof onBeforeCreateRoutes;
29
- onBeforeCreateRouter: typeof onBeforeCreateRouter;
30
- onAfterCreateRouter: typeof onAfterCreateRouter;
31
- onBeforeHydrateRouter: typeof onBeforeHydrateRouter;
32
- onAfterHydrateRouter: typeof onAfterHydrateRouter;
33
- };
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,11 +1,14 @@
1
+ import './register';
1
2
  export * from '@tanstack/react-router';
2
- export { Outlet, useLocation, useMatch, useMatches, useNavigate, useRouter, } 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';
7
+ export { Outlet } from './outlet';
5
8
  export { tanstackRouterPlugin, tanstackRouterPlugin as default, } from './plugin';
6
9
  export type { LinkProps, NavLinkProps, PrefetchBehavior, } from './prefetchLink';
7
10
  export { Link, NavLink } from './prefetchLink';
8
- export type { AnyCompositeComponent, AnyRenderableServerComponent, CompositeComponentProps, } from './rsc/client';
9
- export { CompositeComponent } from './rsc/client';
11
+ export type { TanstackRouterState } from './state';
12
+ export { getTanstackRouterState } from './state';
10
13
  export type { RouterConfig } from './types';
11
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';
@@ -0,0 +1,48 @@
1
+ /** Router context shape used by the generated TanStack router types. */
2
+ export type ModernRouterContext = {
3
+ request?: Request;
4
+ requestContext?: unknown;
5
+ };
6
+ export declare function isResponse(value: unknown): value is Response;
7
+ export declare function isRedirectResponse(res: Response): boolean;
8
+ /**
9
+ * TanStack redirects are Response objects carrying the original redirect
10
+ * `options`. They must be re-thrown untouched — re-translating them through
11
+ * the Modern Response handling would lose `to`-based (internal) targets.
12
+ */
13
+ export declare function isTanstackRedirect(value: unknown): boolean;
14
+ export declare function isAbsoluteUrl(value: string): boolean;
15
+ /**
16
+ * Re-throw a Modern.js `Location` redirect as a TanStack redirect.
17
+ *
18
+ * Prefers `to` for internal/relative redirects so the basepath rewrite can be
19
+ * applied; absolute (external) URLs go through `href` untouched.
20
+ */
21
+ export declare function throwTanstackRedirect(location: string): never;
22
+ /**
23
+ * React Router uses `*` for splat params, TanStack Router uses `_splat`.
24
+ * Modern loaders expect the React Router spelling.
25
+ */
26
+ export declare function mapSplatParamsForModernLoader(params: Record<string, string>, hasSplat: boolean): Record<string, string>;
27
+ /**
28
+ * Static-data factory used by the generated router files: drops empty fields
29
+ * so route static data stays minimal.
30
+ */
31
+ export declare function createRouteStaticData(opts: {
32
+ modernRouteId?: string;
33
+ modernRouteAction?: unknown;
34
+ modernRouteLoader?: unknown;
35
+ }): {
36
+ modernRouteId?: string;
37
+ modernRouteAction?: unknown;
38
+ modernRouteLoader?: unknown;
39
+ };
40
+ /**
41
+ * Wrap a Modern.js data loader (`page.data.ts` loader/action style) into a
42
+ * TanStack Router loader: builds a `Request` from the loader context, maps
43
+ * splat params, and translates Response redirects/404s into TanStack
44
+ * `redirect()`/`notFound()`.
45
+ */
46
+ export declare function modernLoaderToTanstack<TLoader extends (args: any) => any>(opts: {
47
+ hasSplat: boolean;
48
+ }, modernLoader: TLoader): (ctx: unknown) => Promise<Awaited<ReturnType<TLoader>>>;
@@ -0,0 +1,2 @@
1
+ export declare const Outlet: import("react").MemoExoticComponent<() => import("react").JSX.Element>;
2
+ export declare function withModernRouteMatchContext(component: unknown, _routeId: string): unknown;
@@ -1,17 +1,4 @@
1
- import type { Plugin, RuntimePluginExtends } from '@modern-js/plugin';
2
- import type { RuntimePluginAPI } from '@modern-js/plugin/runtime';
3
- import { type TInternalRuntimeContext } from '@modern-js/runtime/context';
4
- import { type RouterExtendsHooks } from './hooks';
1
+ import { type TanstackRouterRuntimePlugin } from './pluginCore';
5
2
  import { type RouterConfig } from './types';
6
- type TanstackRouterRuntimeConfig = {
7
- plugins?: TanstackRouterRuntimePlugin[];
8
- router?: Partial<RouterConfig>;
9
- [key: string]: unknown;
10
- };
11
- type TanstackRouterRuntimeExtends = Required<RuntimePluginExtends<TanstackRouterRuntimeConfig, TInternalRuntimeContext>> & {
12
- extendHooks: RouterExtendsHooks;
13
- };
14
- type TanstackRouterPluginAPI = RuntimePluginAPI<TanstackRouterRuntimeExtends>;
15
- type TanstackRouterRuntimePlugin = Plugin<TanstackRouterPluginAPI, TInternalRuntimeContext>;
16
3
  export declare const tanstackRouterPlugin: (userConfig?: Partial<RouterConfig>) => TanstackRouterRuntimePlugin;
17
4
  export default tanstackRouterPlugin;