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

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 +40 -38
  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,6 +1,8 @@
1
- import { createRootRoute, createRoute, notFound, redirect } from "@tanstack/react-router";
1
+ import { DefaultNotFound } from "@modern-js/runtime/context";
2
+ import { createRootRoute, createRoute, notFound, rootRouteId } from "@tanstack/react-router";
2
3
  import { createElement } from "react";
3
- import { DefaultNotFound } from "./DefaultNotFound.mjs";
4
+ import { isRedirectResponse, isResponse, isTanstackRedirect, throwTanstackRedirect } from "./loaderBridge.mjs";
5
+ import { withModernRouteMatchContext } from "./outlet.mjs";
4
6
  import { isTanstackRscPayloadNavigationEnabled, loadTanstackRscRouteData } from "./rsc/payloadRouter.mjs";
5
7
  function createTanstackRoute(options) {
6
8
  return createRoute(options);
@@ -8,6 +10,10 @@ function createTanstackRoute(options) {
8
10
  function createTanstackRootRoute(options) {
9
11
  return createRootRoute(options);
10
12
  }
13
+ function wrapRouteComponentWithModernContext(route, component, routeId) {
14
+ const routeMatchId = routeId || route.id;
15
+ if (component && routeMatchId) route.options.component = withModernRouteMatchContext(component, routeMatchId);
16
+ }
11
17
  function toTanstackPath(pathname) {
12
18
  return pathname.split('/').map((segment)=>{
13
19
  if (!segment) return segment;
@@ -20,23 +26,6 @@ function toTanstackPath(pathname) {
20
26
  return segment;
21
27
  }).join('/');
22
28
  }
23
- function isResponse(value) {
24
- const record = value;
25
- return null != record && 'object' == typeof record && 'number' == typeof record.status && 'object' == typeof record.headers;
26
- }
27
- function isTanstackRedirect(value) {
28
- return isResponse(value) && 'object' == typeof value.options;
29
- }
30
- const redirectStatusCodes = new Set([
31
- 301,
32
- 302,
33
- 303,
34
- 307,
35
- 308
36
- ]);
37
- function isRedirectResponse(res) {
38
- return redirectStatusCodes.has(res.status);
39
- }
40
29
  function isModernDeferredData(value) {
41
30
  if (!value || 'object' != typeof value) return false;
42
31
  const deferred = value;
@@ -89,34 +78,6 @@ function createServerLazyImportComponent(lazyImport, fallbackComponent) {
89
78
  Component.preload = load;
90
79
  return Component;
91
80
  }
92
- function isAbsoluteUrl(value) {
93
- try {
94
- new URL(value);
95
- return true;
96
- } catch {
97
- return false;
98
- }
99
- }
100
- function throwTanstackRedirect(location) {
101
- const target = location || '/';
102
- if (isAbsoluteUrl(target)) throw redirect({
103
- href: target
104
- });
105
- throw redirect({
106
- to: target
107
- });
108
- }
109
- function mapParamsForModernLoader({ modernRoute, params }) {
110
- if ('nested' === modernRoute.type && modernRoute.path?.includes('*')) {
111
- const { _splat, ...rest } = params;
112
- if (void 0 !== _splat) return {
113
- ...rest,
114
- '*': _splat
115
- };
116
- return rest;
117
- }
118
- return params;
119
- }
120
81
  function createModernRequest(input, signal) {
121
82
  return new Request(input, {
122
83
  signal
@@ -150,52 +111,6 @@ function createModernShouldReload(shouldRevalidate, state) {
150
111
  return 'boolean' == typeof result ? result : void 0;
151
112
  };
152
113
  }
153
- function wrapModernLoader(modernRoute, modernLoader, revalidationState, options = {}) {
154
- const route = modernRoute;
155
- return async (ctx)=>{
156
- try {
157
- if (revalidationState) rememberRouteLocation(revalidationState, ctx);
158
- if ('function' == typeof route.lazyImport) try {
159
- await route.lazyImport();
160
- } catch {}
161
- const signal = ctx?.abortController?.signal || ctx?.signal || new AbortController().signal;
162
- const baseRequest = ctx?.context?.request instanceof Request ? ctx.context.request : void 0;
163
- const href = 'string' == typeof ctx?.location ? ctx.location : ctx?.location?.publicHref || ctx?.location?.href || ctx?.location?.url?.href || '';
164
- const request = void 0 !== baseRequest ? new Request(baseRequest, {
165
- signal
166
- }) : createModernRequest(href, signal);
167
- const params = mapParamsForModernLoader({
168
- modernRoute,
169
- params: ctx.params || {}
170
- });
171
- const loadModernData = async ()=>{
172
- const result = modernLoader ? await modernLoader({
173
- request,
174
- params,
175
- context: ctx?.context?.requestContext
176
- }) : null;
177
- return normalizeModernLoaderResponse(result);
178
- };
179
- if (options.rscPayloadRouter && isTanstackRscPayloadNavigationEnabled()) return loadTanstackRscRouteData({
180
- hasClientLoader: route.hasClientLoader || void 0 !== route.clientData,
181
- loadClientData: loadModernData,
182
- request,
183
- routeId: ctx.route?.id
184
- });
185
- return loadModernData();
186
- } catch (err) {
187
- if (isResponse(err)) {
188
- if (isTanstackRedirect(err)) throw err;
189
- if (isRedirectResponse(err)) {
190
- const location = err.headers.get('Location') || '/';
191
- throwTanstackRedirect(location);
192
- }
193
- if (404 === err.status) throw notFound();
194
- }
195
- throw err;
196
- }
197
- };
198
- }
199
114
  function isRouteObjectPathlessLayout(route) {
200
115
  return !route.path && !route.index;
201
116
  }
@@ -270,11 +185,6 @@ function toRouteComponent(routeObject) {
270
185
  const element = route.element;
271
186
  if (element) return ()=>element;
272
187
  }
273
- function toModernRouteComponent(route) {
274
- const component = route.component || void 0;
275
- if ('function' == typeof route.lazyImport && component) return createServerLazyImportComponent(route.lazyImport, component);
276
- return component;
277
- }
278
188
  function toErrorComponent(routeObject) {
279
189
  const route = routeObject;
280
190
  if (route.ErrorBoundary) return route.ErrorBoundary;
@@ -312,9 +222,10 @@ function createRouteFromRouteObject(opts) {
312
222
  const shouldRevalidate = modernRouteObject.shouldRevalidate;
313
223
  const shouldReload = createModernShouldReload(shouldRevalidate, revalidationState);
314
224
  const stableFallbackId = routeObject.id || modernRouteObject.file || routeObject.path || 'pathless';
225
+ const component = toRouteComponent(routeObject);
315
226
  const base = {
316
227
  getParentRoute: ()=>parent,
317
- component: toRouteComponent(routeObject),
228
+ component,
318
229
  pendingComponent: toPendingComponent(routeObject),
319
230
  errorComponent: toErrorComponent(routeObject),
320
231
  validateSearch: modernRouteObject.validateSearch,
@@ -337,6 +248,7 @@ function createRouteFromRouteObject(opts) {
337
248
  if (isRouteObjectPathlessLayout(routeObject)) base.id = stableFallbackId;
338
249
  else base.path = routeObject.index ? '/' : toTanstackPath(routeObject.path || '');
339
250
  const route = createTanstackRoute(base);
251
+ wrapRouteComponentWithModernContext(route, component, routeObject.id);
340
252
  const children = routeObject.children;
341
253
  if (children && children.length > 0) {
342
254
  const childRoutes = children.map((child)=>createRouteFromRouteObject({
@@ -348,103 +260,6 @@ function createRouteFromRouteObject(opts) {
348
260
  }
349
261
  return route;
350
262
  }
351
- function createRouteFromModernRoute(opts) {
352
- const { options = {}, parent, modernRoute } = opts;
353
- const route = modernRoute;
354
- const revalidationState = {};
355
- const modernId = route.id;
356
- const stableFallbackId = modernId || route._component || route.filename || route.data || ('function' == typeof route.loader ? route.id : void 0);
357
- const pendingComponent = route.loading || route.pendingComponent;
358
- const errorComponent = route.error || route.errorComponent;
359
- const component = toModernRouteComponent(route);
360
- const modernLoader = route.loader;
361
- const modernAction = route.action;
362
- const modernShouldRevalidate = route.shouldRevalidate;
363
- const shouldReload = createModernShouldReload(modernShouldRevalidate, revalidationState);
364
- const isPathlessLayout = 'nested' === route.type && 'boolean' != typeof route.index && void 0 === route.path;
365
- const isIndexRoute = 'nested' === route.type && Boolean(route.index);
366
- const base = {
367
- getParentRoute: ()=>parent,
368
- component: component || void 0,
369
- pendingComponent: pendingComponent || void 0,
370
- errorComponent: errorComponent || void 0,
371
- validateSearch: route.validateSearch,
372
- loaderDeps: route.loaderDeps,
373
- staticData: createRouteStaticData({
374
- modernRouteId: modernId,
375
- modernRouteAction: modernAction,
376
- modernRouteHandle: mergeModernRouteHandle(route),
377
- modernRouteHasAction: route.hasAction || Boolean(modernAction),
378
- modernRouteHasClientLoader: route.hasClientLoader || void 0 !== route.clientData,
379
- modernRouteHasLoader: route.hasLoader || 'function' == typeof modernLoader,
380
- modernRouteIsClientComponent: route.isClientComponent,
381
- modernRouteLoader: modernLoader,
382
- modernRouteShouldRevalidate: modernShouldRevalidate
383
- }),
384
- loader: wrapModernLoader(modernRoute, modernLoader, revalidationState, options)
385
- };
386
- if (route.inValidSSRRoute) base.ssr = false;
387
- if (shouldReload) base.shouldReload = shouldReload;
388
- if (isPathlessLayout) base.id = stableFallbackId || 'pathless';
389
- else {
390
- const rawPath = route.path;
391
- base.path = isIndexRoute ? '/' : toTanstackPath(rawPath || '');
392
- }
393
- const tanstackRoute = createTanstackRoute(base);
394
- const children = route.children;
395
- if (children && children.length > 0) {
396
- const childRoutes = children.map((child)=>createRouteFromModernRoute({
397
- options,
398
- parent: tanstackRoute,
399
- modernRoute: child
400
- }));
401
- tanstackRoute.addChildren(childRoutes);
402
- }
403
- return tanstackRoute;
404
- }
405
- function createRouteTreeFromModernRoutes(routes, options = {}) {
406
- const rootModern = routes.find((r)=>r && 'nested' === r.type && r.isRoot);
407
- const rootComponent = rootModern ? toModernRouteComponent(rootModern) : void 0;
408
- const pendingComponent = rootModern?.loading;
409
- const errorComponent = rootModern?.error;
410
- const rootLoader = rootModern?.loader;
411
- const rootAction = rootModern?.action;
412
- const rootModernId = rootModern?.id;
413
- const rootShouldRevalidate = rootModern?.shouldRevalidate;
414
- const rootRevalidationState = {};
415
- const rootShouldReload = createModernShouldReload(rootShouldRevalidate, rootRevalidationState);
416
- const rootRouteOptions = {
417
- component: rootComponent || void 0,
418
- pendingComponent: pendingComponent || void 0,
419
- errorComponent: errorComponent || void 0,
420
- validateSearch: rootModern?.validateSearch,
421
- loaderDeps: rootModern?.loaderDeps,
422
- notFoundComponent: DefaultNotFound,
423
- staticData: createRouteStaticData({
424
- modernRouteId: rootModernId,
425
- modernRouteAction: rootAction,
426
- modernRouteHandle: rootModern ? mergeModernRouteHandle(rootModern) : void 0,
427
- modernRouteHasAction: rootModern?.hasAction || Boolean(rootAction),
428
- modernRouteHasClientLoader: rootModern?.hasClientLoader || void 0 !== rootModern?.clientData,
429
- modernRouteHasLoader: rootModern?.hasLoader || 'function' == typeof rootLoader,
430
- modernRouteIsClientComponent: rootModern?.isClientComponent,
431
- modernRouteLoader: rootLoader,
432
- modernRouteShouldRevalidate: rootShouldRevalidate
433
- }),
434
- loader: rootModern ? wrapModernLoader(rootModern, rootLoader, rootRevalidationState, options) : void 0
435
- };
436
- if (rootShouldReload) rootRouteOptions.shouldReload = rootShouldReload;
437
- if (rootModern?.inValidSSRRoute) rootRouteOptions.ssr = false;
438
- const rootRoute = createTanstackRootRoute(rootRouteOptions);
439
- const topLevel = rootModern ? rootModern.children || [] : routes;
440
- const childRoutes = topLevel.map((child)=>createRouteFromModernRoute({
441
- options,
442
- parent: rootRoute,
443
- modernRoute: child
444
- }));
445
- rootRoute.addChildren(childRoutes);
446
- return rootRoute;
447
- }
448
263
  function getRootLikeRouteObject(routes) {
449
264
  return routes.find((route)=>'/' === route.path && !route.index);
450
265
  }
@@ -453,8 +268,9 @@ function createRouteTreeFromRouteObjects(routes, options = {}) {
453
268
  const rootRevalidationState = {};
454
269
  const rootShouldRevalidate = rootLikeRoute?.shouldRevalidate;
455
270
  const rootShouldReload = createModernShouldReload(rootShouldRevalidate, rootRevalidationState);
271
+ const rootComponent = rootLikeRoute ? toRouteComponent(rootLikeRoute) : void 0;
456
272
  const rootRouteOptions = {
457
- component: rootLikeRoute ? toRouteComponent(rootLikeRoute) : void 0,
273
+ component: rootComponent,
458
274
  pendingComponent: rootLikeRoute ? toPendingComponent(rootLikeRoute) : void 0,
459
275
  errorComponent: rootLikeRoute ? toErrorComponent(rootLikeRoute) : void 0,
460
276
  validateSearch: rootLikeRoute?.validateSearch,
@@ -476,6 +292,7 @@ function createRouteTreeFromRouteObjects(routes, options = {}) {
476
292
  if (rootShouldReload) rootRouteOptions.shouldReload = rootShouldReload;
477
293
  if (rootLikeRoute?.inValidSSRRoute) rootRouteOptions.ssr = false;
478
294
  const rootRoute = createTanstackRootRoute(rootRouteOptions);
295
+ if (rootComponent) rootRoute.options.component = withModernRouteMatchContext(rootComponent, rootRouteId);
479
296
  const topLevel = rootLikeRoute ? [
480
297
  ...rootLikeRoute.children || [],
481
298
  ...routes.filter((route)=>route !== rootLikeRoute)
@@ -498,4 +315,4 @@ function getModernRouteIdsFromMatches(router) {
498
315
  }).filter((id)=>'string' == typeof id);
499
316
  return Array.from(new Set(ids));
500
317
  }
501
- export { createRouteTreeFromModernRoutes, createRouteTreeFromRouteObjects, getModernRouteIdsFromMatches };
318
+ export { createRouteTreeFromRouteObjects, getModernRouteIdsFromMatches };
@@ -0,0 +1,2 @@
1
+ import "./register.mjs";
2
+ export { routerPlugin } from "@modern-js/runtime/router/internal";
@@ -1,3 +1,4 @@
1
+ import { isRouteErrorResponse } from "@modern-js/runtime-utils/router";
1
2
  import { notFound, redirect } from "@tanstack/react-router";
2
3
  const payloadFetchCache = new Map();
3
4
  let payloadDecoder;
@@ -37,6 +38,39 @@ function toPayloadRoute(match) {
37
38
  pathnameBase: 'string' == typeof match.pathnameBase ? match.pathnameBase : pathname
38
39
  };
39
40
  }
41
+ function shouldRedactServerError(status = 500) {
42
+ return status >= 500 && 'development' !== process.env.NODE_ENV && 'test' !== process.env.NODE_ENV;
43
+ }
44
+ function serializePayloadError(error) {
45
+ if (isRouteErrorResponse(error)) {
46
+ if (shouldRedactServerError(error.status)) return {
47
+ status: error.status,
48
+ statusText: 'Internal Server Error',
49
+ data: 'Unexpected Server Error',
50
+ __type: 'RouteErrorResponse'
51
+ };
52
+ return {
53
+ ...error,
54
+ __type: 'RouteErrorResponse'
55
+ };
56
+ }
57
+ if (error instanceof Error) {
58
+ if (shouldRedactServerError()) return {
59
+ message: 'Unexpected Server Error',
60
+ stack: void 0,
61
+ __type: 'Error'
62
+ };
63
+ return {
64
+ message: error.message,
65
+ stack: error.stack,
66
+ __type: 'Error',
67
+ ...'Error' !== error.name ? {
68
+ __subType: error.name
69
+ } : {}
70
+ };
71
+ }
72
+ return error;
73
+ }
40
74
  function createTanstackRscServerPayload(router, options = {}) {
41
75
  const matches = Array.isArray(router.state?.matches) ? router.state.matches : [];
42
76
  const routes = [];
@@ -47,7 +81,7 @@ function createTanstackRscServerPayload(router, options = {}) {
47
81
  if (payloadRoute) {
48
82
  routes.push(payloadRoute);
49
83
  if ('loaderData' in match && void 0 !== match.loaderData && !(options.omitClientLoaderData && payloadRoute.hasClientLoader)) loaderData[payloadRoute.id] = match.loaderData;
50
- if (void 0 !== match.error) errors[payloadRoute.id] = match.error;
84
+ if (void 0 !== match.error) errors[payloadRoute.id] = serializePayloadError(match.error);
51
85
  }
52
86
  }
53
87
  return {
@@ -0,0 +1,7 @@
1
+ import { getRouterRuntimeState } from "@modern-js/runtime/context";
2
+ function getTanstackRouterState(context) {
3
+ const state = getRouterRuntimeState(context);
4
+ if (void 0 === state || 'tanstack' !== state.framework) return;
5
+ return state;
6
+ }
7
+ export { getTanstackRouterState };
@@ -1,6 +1,5 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import react from "react";
3
- import { DefaultNotFound } from "./DefaultNotFound.mjs";
4
3
  function getRouteObjects(routes, { globalApp, ssrMode, props }) {
5
4
  const createLayoutElement = (Component)=>{
6
5
  const GlobalLayout = globalApp;
@@ -21,7 +20,6 @@ function getRouteObjects(routes, { globalApp, ssrMode, props }) {
21
20
  id: route.id,
22
21
  loader: route.loader,
23
22
  action: route.action,
24
- hasErrorBoundary: route.hasErrorBoundary,
25
23
  shouldRevalidate: route.shouldRevalidate,
26
24
  handle: {
27
25
  ...route.handle,
@@ -57,10 +55,6 @@ function getRouteObjects(routes, { globalApp, ssrMode, props }) {
57
55
  };
58
56
  routeObjects.push(routeObject);
59
57
  }
60
- routeObjects.push({
61
- path: '*',
62
- element: /*#__PURE__*/ jsx(DefaultNotFound, {})
63
- });
64
58
  return routeObjects;
65
59
  }
66
60
  function createRouteObjectsFromConfig({ routesConfig, props, ssrMode }) {
@@ -1,14 +1,14 @@
1
1
  import "node:module";
2
2
  import node_path from "node:path";
3
3
  import { NESTED_ROUTE_SPEC_FILE, filterRoutesForServer, fs } from "@modern-js/utils";
4
- import { createTanstackRsbuildRouteSplittingProfile, isTanstackStartRouteModuleSource, resolveTanstackRouteCodeSplittingEnabled } from "./routeSplitting.mjs";
5
- import { generateTanstackRouterTypesSourceForEntry, isTanstackRouterFrameworkEnabled } from "./tanstackTypes.mjs";
4
+ import { createTanstackRsbuildRouteSplittingProfile, resolveTanstackRouteCodeSplittingEnabled } from "./routeSplitting.mjs";
5
+ import { collectCanonicalRoutesForEntry, generateTanstackRouterTypesSourceForEntry } from "./tanstackTypes.mjs";
6
6
  import { __webpack_require__ } from "../rslib-runtime.mjs";
7
7
  import { fileURLToPath as __rspack_fileURLToPath } from "node:url";
8
8
  import { dirname as __rspack_dirname } from "node:path";
9
9
  import * as __rspack_external__modern_js_runtime_cli_401ee077 from "@modern-js/runtime/cli";
10
10
  __webpack_require__.add({
11
- "@modern-js/runtime/cli" (module) {
11
+ "@modern-js/runtime/cli?9b14" (module) {
12
12
  module.exports = __rspack_external__modern_js_runtime_cli_401ee077;
13
13
  }
14
14
  });
@@ -19,8 +19,8 @@ const ENTRYPOINTS_KEY = '@modern-js/plugin-tanstack';
19
19
  let runtimeRouterCli;
20
20
  function getRuntimeRouterCli() {
21
21
  if (runtimeRouterCli) return runtimeRouterCli;
22
- const cli = __webpack_require__("@modern-js/runtime/cli");
23
- if (cli.handleGeneratorEntryCode && cli.getEntrypointRoutesDir) {
22
+ const cli = __webpack_require__("@modern-js/runtime/cli?9b14");
23
+ if (cli.handleGeneratorEntryCode && cli.getEntrypointRoutesDir && cli.getEntrypointRoutesOwner) {
24
24
  runtimeRouterCli = cli;
25
25
  return runtimeRouterCli;
26
26
  }
@@ -36,6 +36,14 @@ async function writeFileIfChanged(filePath, content) {
36
36
  function createRegisterDtsContent(opts) {
37
37
  const importStatements = opts.entries.map((entryName, index)=>`import type { router as router${index} } from './${entryName}/router.gen';`).join('\n');
38
38
  const routerUnionType = opts.entries.map((_, index)=>`typeof router${index}`).join(' | ');
39
+ const canonicalEntries = Object.entries(opts.canonicalRoutes ?? {});
40
+ const canonicalRoutesAugmentation = canonicalEntries.length > 0 ? `
41
+ declare module '${opts.i18nRuntimeModule || '@modern-js/plugin-i18n/runtime'}' {
42
+ interface UltramodernCanonicalRoutes {
43
+ ${canonicalEntries.map(([routePath, paramsType])=>` '${routePath}': ${paramsType};`).join('\n')}
44
+ }
45
+ }
46
+ ` : '';
39
47
  return `// This file is auto-generated by Modern.js. Do not edit manually.
40
48
 
41
49
  ${importStatements}
@@ -45,19 +53,21 @@ declare module '${opts.runtimeModule}' {
45
53
  router: ${routerUnionType};
46
54
  }
47
55
  }
48
- `;
56
+ ${canonicalRoutesAugmentation}`;
49
57
  }
50
58
  async function writeTanstackRegisterFile(opts) {
51
- const { entries, generatedDirName = DEFAULT_GENERATED_DIR_NAME, runtimeModule = '@modern-js/plugin-tanstack/runtime', srcDirectory } = opts;
59
+ const { entries, generatedDirName = DEFAULT_GENERATED_DIR_NAME, runtimeModule = '@modern-js/plugin-tanstack/runtime', srcDirectory, canonicalRoutes, i18nRuntimeModule } = opts;
52
60
  if (0 === entries.length) return;
53
61
  const registerDtsPath = node_path.join(srcDirectory, generatedDirName, 'register.gen.d.ts');
54
62
  await writeFileIfChanged(registerDtsPath, createRegisterDtsContent({
55
63
  entries,
56
- runtimeModule
64
+ runtimeModule,
65
+ canonicalRoutes,
66
+ i18nRuntimeModule
57
67
  }));
58
68
  }
59
69
  async function writeTanstackRouterTypesForEntries(opts) {
60
- const { appContext, generatedDirName = DEFAULT_GENERATED_DIR_NAME, routesByEntry } = opts;
70
+ const { appContext, generatedDirName = DEFAULT_GENERATED_DIR_NAME, routesByEntry, i18nPluginInstalled = false } = opts;
61
71
  const entryNames = Object.keys(routesByEntry);
62
72
  await Promise.all(entryNames.map(async (entryName)=>{
63
73
  const { routerGenTs } = await generateTanstackRouterTypesSourceForEntry({
@@ -74,10 +84,21 @@ async function writeTanstackRouterTypesForEntries(opts) {
74
84
  if (mainEntryName && b === mainEntryName) return 1;
75
85
  return a.localeCompare(b);
76
86
  });
87
+ let canonicalRoutes = null;
88
+ if (i18nPluginInstalled) for (const entryName of registerEntries){
89
+ const entryCanonicalRoutes = collectCanonicalRoutesForEntry(routesByEntry[entryName], {
90
+ localeParamHeuristic: true
91
+ });
92
+ if (entryCanonicalRoutes) canonicalRoutes = {
93
+ ...entryCanonicalRoutes,
94
+ ...canonicalRoutes ?? {}
95
+ };
96
+ }
77
97
  await writeTanstackRegisterFile({
78
98
  entries: registerEntries,
79
99
  generatedDirName,
80
- srcDirectory: appContext.srcDirectory
100
+ srcDirectory: appContext.srcDirectory,
101
+ canonicalRoutes
81
102
  });
82
103
  }
83
104
  function tanstackRouterPlugin(options = {}) {
@@ -95,16 +116,42 @@ function tanstackRouterPlugin(options = {}) {
95
116
  const { getEntrypointRoutesDir } = getRuntimeRouterCli();
96
117
  return getEntrypointRoutesDir(entrypoint) === routesDir;
97
118
  };
119
+ const isForeignRouteEntrypoint = (entrypoint)=>{
120
+ const { getEntrypointRoutesDir, getEntrypointRoutesOwner } = getRuntimeRouterCli();
121
+ if (getEntrypointRoutesOwner(entrypoint)) return true;
122
+ if (entrypoint.pageRoutesEntry) return true;
123
+ return null !== getEntrypointRoutesDir(entrypoint);
124
+ };
125
+ const isI18nPluginInstalled = ()=>{
126
+ const { plugins } = api.getAppContext();
127
+ return Boolean(plugins?.some((plugin)=>plugin?.name === '@modern-js/plugin-i18n'));
128
+ };
98
129
  api._internalRuntimePlugins(({ entrypoint, plugins })=>{
99
- if (!isTanstackEntrypoint(entrypoint)) return {
130
+ const { metaName, serverRoutes } = api.getAppContext();
131
+ const serverBase = serverRoutes.filter((route)=>route.entryName === entrypoint.entryName).map((route)=>route.urlPath).sort((a, b)=>a.length - b.length > 0 ? -1 : 1);
132
+ if (isTanstackEntrypoint(entrypoint)) {
133
+ plugins.push({
134
+ name: 'tanstackRouter',
135
+ path: `@${metaName}/plugin-tanstack/runtime`,
136
+ config: {
137
+ serverBase
138
+ }
139
+ });
140
+ return {
141
+ entrypoint,
142
+ plugins
143
+ };
144
+ }
145
+ if (isForeignRouteEntrypoint(entrypoint)) return {
100
146
  entrypoint,
101
147
  plugins
102
148
  };
103
- const { metaName, serverRoutes } = api.getAppContext();
104
- const serverBase = serverRoutes.filter((route)=>route.entryName === entrypoint.entryName).map((route)=>route.urlPath).sort((a, b)=>a.length - b.length > 0 ? -1 : 1);
105
- plugins.push({
106
- name: 'tanstackRouter',
107
- path: `@${metaName}/plugin-tanstack/runtime`,
149
+ const routerWrapperPath = `@${metaName}/plugin-tanstack/runtime/router`;
150
+ const existingRouterPlugin = plugins.find((plugin)=>'router' === plugin.name);
151
+ if (existingRouterPlugin) existingRouterPlugin.path = routerWrapperPath;
152
+ else plugins.push({
153
+ name: 'router',
154
+ path: routerWrapperPath,
108
155
  config: {
109
156
  serverBase
110
157
  }
@@ -123,7 +170,9 @@ function tanstackRouterPlugin(options = {}) {
123
170
  source: {
124
171
  include: [
125
172
  /[\\/]node_modules[\\/]@tanstack[\\/]react-router[\\/]/,
126
- node_path.resolve(cli_dirname, '../runtime').replace('cjs', 'esm')
173
+ /[\\/]node_modules[\\/]@tanstack[\\/]router-core[\\/]/,
174
+ /[\\/]node_modules[\\/]@tanstack[\\/]react-store[\\/]/,
175
+ node_path.resolve(cli_dirname, '..', '..')
127
176
  ]
128
177
  }
129
178
  }));
@@ -140,15 +189,13 @@ function tanstackRouterPlugin(options = {}) {
140
189
  if (0 === tanstackEntrypoints.length) return;
141
190
  const { handleGeneratorEntryCode } = getRuntimeRouterCli();
142
191
  const routesByEntry = await handleGeneratorEntryCode(api, tanstackEntrypoints, {
143
- entrypointsKey: ENTRYPOINTS_KEY,
144
- generateCodeOptions: {
145
- enableTanstackTypes: false
146
- }
192
+ entrypointsKey: ENTRYPOINTS_KEY
147
193
  });
148
194
  await writeTanstackRouterTypesForEntries({
149
195
  appContext: api.getAppContext(),
150
196
  generatedDirName,
151
- routesByEntry
197
+ routesByEntry,
198
+ i18nPluginInstalled: isI18nPluginInstalled()
152
199
  });
153
200
  });
154
201
  api.onFileChanged(async (event)=>{
@@ -162,15 +209,13 @@ function tanstackRouterPlugin(options = {}) {
162
209
  regenerate: async ({ api, entrypoints })=>{
163
210
  const { handleGeneratorEntryCode } = getRuntimeRouterCli();
164
211
  const routesByEntry = await handleGeneratorEntryCode(api, entrypoints, {
165
- entrypointsKey: ENTRYPOINTS_KEY,
166
- generateCodeOptions: {
167
- enableTanstackTypes: false
168
- }
212
+ entrypointsKey: ENTRYPOINTS_KEY
169
213
  });
170
214
  await writeTanstackRouterTypesForEntries({
171
215
  appContext: api.getAppContext(),
172
216
  generatedDirName,
173
- routesByEntry
217
+ routesByEntry,
218
+ i18nPluginInstalled: isI18nPluginInstalled()
174
219
  });
175
220
  }
176
221
  });
@@ -202,4 +247,4 @@ function tanstackRouterPlugin(options = {}) {
202
247
  }
203
248
  const src_cli = tanstackRouterPlugin;
204
249
  export default src_cli;
205
- export { createTanstackRsbuildRouteSplittingProfile, generateTanstackRouterTypesSourceForEntry, isTanstackRouterFrameworkEnabled, isTanstackStartRouteModuleSource, resolveTanstackRouteCodeSplittingEnabled, tanstackRouterPlugin, writeTanstackRegisterFile, writeTanstackRouterTypesForEntries };
250
+ export { collectCanonicalRoutesForEntry, createTanstackRsbuildRouteSplittingProfile, generateTanstackRouterTypesSourceForEntry, resolveTanstackRouteCodeSplittingEnabled, tanstackRouterPlugin, writeTanstackRegisterFile, writeTanstackRouterTypesForEntries };
@@ -1,13 +1,4 @@
1
1
  import "node:module";
2
- const TANSTACK_START_ROUTE_FACTORY_CALLS = [
3
- 'createFileRoute',
4
- 'createRootRoute',
5
- 'createRootRouteWithContext'
6
- ];
7
- const TANSTACK_START_ROUTE_FACTORY_REGEX = /\b(createFileRoute|createRootRoute|createRootRouteWithContext)\s*(?:<|\()/;
8
- function isTanstackStartRouteModuleSource(source) {
9
- return TANSTACK_START_ROUTE_FACTORY_REGEX.test(source);
10
- }
11
2
  function resolveTanstackRouteCodeSplittingEnabled(option) {
12
3
  if ('boolean' == typeof option) return option;
13
4
  return option?.enabled ?? true;
@@ -18,27 +9,7 @@ function createTanstackRsbuildRouteSplittingProfile(opts) {
18
9
  output: {
19
10
  splitRouteChunks: resolveTanstackRouteCodeSplittingEnabled(opts.routeCodeSplitting)
20
11
  }
21
- },
22
- modernRouteChunks: {
23
- enabled: resolveTanstackRouteCodeSplittingEnabled(opts.routeCodeSplitting),
24
- owner: 'modern'
25
- },
26
- builderChunkSplit: {
27
- owner: 'modern-rsbuild',
28
- preserved: true
29
- },
30
- tanstackStartRspackSplitter: {
31
- compatible: false,
32
- reason: 'TanStack Start Rsbuild route splitting is tied to TanStack file-route factory modules; Modern generates TanStack route trees from Modern route metadata and owns route chunking through output.splitRouteChunks.',
33
- clientDeleteNodes: [
34
- 'ssr',
35
- 'server',
36
- 'headers'
37
- ],
38
- routeFactoryCalls: [
39
- ...TANSTACK_START_ROUTE_FACTORY_CALLS
40
- ]
41
12
  }
42
13
  };
43
14
  }
44
- export { createTanstackRsbuildRouteSplittingProfile, isTanstackStartRouteModuleSource, resolveTanstackRouteCodeSplittingEnabled };
15
+ export { createTanstackRsbuildRouteSplittingProfile, resolveTanstackRouteCodeSplittingEnabled };