@bleedingdev/modern-js-plugin-tanstack 3.9.0-ultramodern.2 → 3.9.0-ultramodern.21

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 (137) hide show
  1. package/dist/cjs/cli/artifacts.js +15 -1
  2. package/dist/cjs/cli/index.js +12 -0
  3. package/dist/cjs/cli/routeMetadata.js +131 -0
  4. package/dist/cjs/cli/tanstackTypes/canonicalRoutes.js +7 -7
  5. package/dist/cjs/cli/tanstackTypes/shared.js +0 -14
  6. package/dist/cjs/cli/tanstackTypes/source.js +27 -60
  7. package/dist/cjs/runtime/basepathRewrite.js +13 -6
  8. package/dist/cjs/runtime/lifecycle.js +6 -9
  9. package/dist/cjs/runtime/loaderBridge.js +10 -4
  10. package/dist/cjs/runtime/navigation.js +102 -0
  11. package/dist/cjs/runtime/plugin.js +7 -2
  12. package/dist/cjs/runtime/plugin.node.js +86 -64
  13. package/dist/cjs/runtime/prefetchLink.js +2 -7
  14. package/dist/cjs/runtime/register.js +0 -2
  15. package/dist/cjs/runtime/routeTree/construction.js +19 -59
  16. package/dist/cjs/runtime/routeTree/loaders.js +1 -1
  17. package/dist/cjs/runtime/routeTree/paths.js +0 -6
  18. package/dist/cjs/runtime/router.js +25 -9
  19. package/dist/cjs/runtime/ssrManagedTags.js +2 -12
  20. package/dist/cjs/runtime/state.js +2 -2
  21. package/dist/cjs/runtime/utils.js +3 -0
  22. package/dist/cjs/shared/routeDescriptor.js +60 -0
  23. package/dist/esm/cli/artifacts.mjs +13 -2
  24. package/dist/esm/cli/index.mjs +12 -9
  25. package/dist/esm/cli/routeMetadata.mjs +71 -0
  26. package/dist/esm/cli/tanstackTypes/canonicalRoutes.mjs +7 -7
  27. package/dist/esm/cli/tanstackTypes/shared.mjs +1 -9
  28. package/dist/esm/cli/tanstackTypes/source.mjs +28 -61
  29. package/dist/esm/runtime/basepathRewrite.mjs +10 -3
  30. package/dist/esm/runtime/lifecycle.mjs +1 -1
  31. package/dist/esm/runtime/loaderBridge.mjs +8 -5
  32. package/dist/esm/runtime/navigation.mjs +64 -0
  33. package/dist/esm/runtime/plugin.mjs +7 -2
  34. package/dist/esm/runtime/plugin.node.mjs +88 -66
  35. package/dist/esm/runtime/prefetchLink.mjs +1 -6
  36. package/dist/esm/runtime/register.mjs +0 -2
  37. package/dist/esm/runtime/routeTree/construction.mjs +19 -59
  38. package/dist/esm/runtime/routeTree/loaders.mjs +2 -2
  39. package/dist/esm/runtime/routeTree/paths.mjs +1 -4
  40. package/dist/esm/runtime/router.mjs +27 -11
  41. package/dist/esm/runtime/ssrManagedTags.mjs +1 -8
  42. package/dist/esm/runtime/state.mjs +1 -1
  43. package/dist/esm/runtime/utils.mjs +3 -0
  44. package/dist/esm/shared/routeDescriptor.mjs +22 -0
  45. package/dist/esm-node/cli/artifacts.mjs +13 -2
  46. package/dist/esm-node/cli/index.mjs +12 -9
  47. package/dist/esm-node/cli/routeMetadata.mjs +72 -0
  48. package/dist/esm-node/cli/tanstackTypes/canonicalRoutes.mjs +7 -7
  49. package/dist/esm-node/cli/tanstackTypes/shared.mjs +1 -9
  50. package/dist/esm-node/cli/tanstackTypes/source.mjs +28 -61
  51. package/dist/esm-node/runtime/basepathRewrite.mjs +10 -3
  52. package/dist/esm-node/runtime/lifecycle.mjs +1 -1
  53. package/dist/esm-node/runtime/loaderBridge.mjs +8 -5
  54. package/dist/esm-node/runtime/navigation.mjs +65 -0
  55. package/dist/esm-node/runtime/plugin.mjs +7 -2
  56. package/dist/esm-node/runtime/plugin.node.mjs +88 -66
  57. package/dist/esm-node/runtime/prefetchLink.mjs +1 -6
  58. package/dist/esm-node/runtime/register.mjs +0 -2
  59. package/dist/esm-node/runtime/routeTree/construction.mjs +19 -59
  60. package/dist/esm-node/runtime/routeTree/loaders.mjs +2 -2
  61. package/dist/esm-node/runtime/routeTree/paths.mjs +1 -4
  62. package/dist/esm-node/runtime/router.mjs +27 -11
  63. package/dist/esm-node/runtime/ssrManagedTags.mjs +1 -8
  64. package/dist/esm-node/runtime/state.mjs +1 -1
  65. package/dist/esm-node/runtime/utils.mjs +3 -0
  66. package/dist/esm-node/shared/routeDescriptor.mjs +23 -0
  67. package/dist/types/cli/artifacts.d.ts +13 -5
  68. package/dist/types/cli/index.d.ts +1 -1
  69. package/dist/types/cli/routeMetadata.d.ts +18 -0
  70. package/dist/types/cli/tanstackTypes/shared.d.ts +0 -2
  71. package/dist/types/runtime/basepathRewrite.d.ts +2 -1
  72. package/dist/types/runtime/lifecycle.d.ts +9 -2
  73. package/dist/types/runtime/loaderBridge.d.ts +1 -0
  74. package/dist/types/runtime/navigation.d.ts +4 -0
  75. package/dist/types/runtime/register.d.ts +1 -9
  76. package/dist/types/runtime/routeTree/paths.d.ts +0 -2
  77. package/dist/types/runtime/router.d.ts +2 -13
  78. package/dist/types/runtime/ssrManagedTags.d.ts +0 -1
  79. package/dist/types/runtime/ssrTypes.d.ts +0 -7
  80. package/dist/types/runtime/state.d.ts +1 -1
  81. package/dist/types/runtime/types.d.ts +2 -1
  82. package/dist/types/shared/routeDescriptor.d.ts +26 -0
  83. package/package.json +22 -19
  84. package/rstest.config.mts +2 -24
  85. package/src/cli/artifacts.ts +53 -6
  86. package/src/cli/index.ts +11 -2
  87. package/src/cli/routeMetadata.ts +121 -0
  88. package/src/cli/tanstackTypes/canonicalRoutes.ts +17 -12
  89. package/src/cli/tanstackTypes/shared.ts +0 -14
  90. package/src/cli/tanstackTypes/source.ts +42 -116
  91. package/src/runtime/basepathRewrite.ts +11 -2
  92. package/src/runtime/lifecycle.ts +14 -4
  93. package/src/runtime/loaderBridge.ts +9 -9
  94. package/src/runtime/navigation.ts +78 -0
  95. package/src/runtime/plugin.node.tsx +120 -93
  96. package/src/runtime/plugin.tsx +11 -1
  97. package/src/runtime/prefetchLink.tsx +1 -23
  98. package/src/runtime/register.ts +1 -12
  99. package/src/runtime/routeTree/construction.ts +32 -110
  100. package/src/runtime/routeTree/loaders.ts +2 -4
  101. package/src/runtime/routeTree/paths.ts +0 -6
  102. package/src/runtime/router.ts +25 -40
  103. package/src/runtime/ssrManagedTags.ts +0 -17
  104. package/src/runtime/ssrTypes.ts +0 -7
  105. package/src/runtime/state.ts +1 -1
  106. package/src/runtime/types.ts +2 -2
  107. package/src/runtime/utils.tsx +4 -1
  108. package/src/shared/routeDescriptor.ts +46 -0
  109. package/tests/router/cli.test.ts +148 -824
  110. package/tests/router/clientNavigation.ts +13 -0
  111. package/tests/router/dataMutation.test.tsx +17 -85
  112. package/tests/router/flightSerialization.roundtrip.test.tsx +9 -6
  113. package/tests/router/generateRouteArtifacts.test.ts +139 -27
  114. package/tests/router/loaderBridge.test.ts +0 -25
  115. package/tests/router/localisedIdentity.test.tsx +100 -0
  116. package/tests/router/prefetchLink.test.tsx +46 -21
  117. package/tests/router/prefetchLinkPreload.test.tsx +11 -32
  118. package/tests/router/routeHooks.test.ts +42 -105
  119. package/tests/router/routeMetadata.test.ts +233 -0
  120. package/tests/router/routeTree.test.ts +144 -836
  121. package/tests/router/rsc.test.tsx +131 -166
  122. package/tests/router/serverPlugin.test.ts +193 -1
  123. package/tests/router/tanstackTypes.test.ts +218 -963
  124. package/dist/esm/rslib-runtime~1.mjs +0 -18
  125. package/dist/esm-node/rslib-runtime~0.mjs +0 -19
  126. package/tests/realm-isolation.test.ts +0 -114
  127. package/tests/router/fastDefaults.test.ts +0 -32
  128. package/tests/router/fixtures/legacyRuntimeRouter.ts +0 -10
  129. package/tests/router/fixtures/rscDecoderSecurityChild.cjs +0 -162
  130. package/tests/router/hooks.test.ts +0 -40
  131. package/tests/router/hydrationBoundary.test.tsx +0 -23
  132. package/tests/router/packageSurface.test.ts +0 -24
  133. package/tests/router/preloadRedirect.test.ts +0 -64
  134. package/tests/router/register.test.ts +0 -8
  135. package/tests/router/routerCompatibility.test.ts +0 -239
  136. package/tests/router/rscDecoderSecurity.test.ts +0 -113
  137. package/tests/router/rscPayloadRouterMatrix.test.ts +0 -197
@@ -8,12 +8,14 @@ import { useContext } from "react";
8
8
  import { createModernBasepathRewrite } from "./basepathRewrite.mjs";
9
9
  import { routerProviderRegistryHooks } from "./hooks.mjs";
10
10
  import { wrapTanstackSsrHydrationBoundary } from "./hydrationBoundary.mjs";
11
- import { applyRouterServerPrepareResult, createRouterServerSnapshot, getRouterRuntimeState } from "./lifecycle.mjs";
11
+ import { applyRouterRuntimeState, applyRouterServerPrepareResult, getRouterRuntimeState, getRouterServerSnapshot } from "./lifecycle.mjs";
12
+ import { createTanstackNavigation } from "./navigation.mjs";
12
13
  import { createTanstackRouteObjects, getTanstackRouteConfig, joinBasename } from "./pluginShared.mjs";
14
+ import { Link } from "./prefetchLink.mjs";
13
15
  import { createRouteTreeFromRouteObjects, getModernRouteIdsFromMatches } from "./routeTree/index.mjs";
14
16
  import { createTanstackRscServerPayload, handleTanstackRscRedirect } from "./rsc/payloadRouter.mjs";
15
17
  import { getTanstackRscRouter, setTanstackRscRouter, setTanstackRscServerPayload } from "./rsc/payloadStorage.mjs";
16
- import { attachServerSsrUtils, collectRouterErrors, createGetSsrHref, routerManagedTagsToHtml, waitForRouterSerialization } from "./ssrManagedTags.mjs";
18
+ import { attachServerSsrUtils, collectRouterErrors, createGetSsrHref, routerManagedTagsToHtml } from "./ssrManagedTags.mjs";
17
19
  import { preloadMatchedRouteComponents } from "./ssrPreload.mjs";
18
20
  import { getModernTanstackRouterFastDefaults } from "./types.mjs";
19
21
  const tanstackRouterPlugin = (userConfig = {})=>{
@@ -35,6 +37,9 @@ const tanstackRouterPlugin = (userConfig = {})=>{
35
37
  routeConfig
36
38
  });
37
39
  if (!modifiedRouteObjects.length) return;
40
+ context.router = {
41
+ Link: Link
42
+ };
38
43
  const { request, nonce, baseUrl, loaderFailureMode = 'errorBoundary' } = context.ssrContext;
39
44
  const _basename = '/' === baseUrl ? joinBasename(baseUrl, basename || '') : baseUrl;
40
45
  const rawRequest = request.raw;
@@ -57,7 +62,7 @@ const tanstackRouterPlugin = (userConfig = {})=>{
57
62
  initialHref
58
63
  ]
59
64
  });
60
- const rewrite = createModernBasepathRewrite(_basename);
65
+ const rewrite = createModernBasepathRewrite(_basename, false, modifiedRouteObjects);
61
66
  const routerLifecycleContext = {
62
67
  framework: 'tanstack',
63
68
  phase: 'ssr-prepare',
@@ -83,76 +88,93 @@ const tanstackRouterPlugin = (userConfig = {})=>{
83
88
  });
84
89
  const serverRouter = tanstackRouter;
85
90
  if (enableRsc) setTanstackRscRouter(serverRouter);
86
- await attachServerSsrUtils(serverRouter);
87
- const end = time();
91
+ let disposed = false;
92
+ let prepared = false;
93
+ const onAbort = ()=>controller.abort(rawRequest.signal.reason);
94
+ const cleanup = ()=>{
95
+ if (disposed) return;
96
+ disposed = true;
97
+ rawRequest.signal.removeEventListener('abort', onAbort);
98
+ controller.abort();
99
+ serverRouter.serverSsr?.cleanup();
100
+ };
101
+ applyRouterRuntimeState(context, {
102
+ framework: 'tanstack',
103
+ basename: _basename,
104
+ instance: serverRouter,
105
+ cleanup
106
+ });
107
+ rawRequest.signal.addEventListener('abort', onAbort, {
108
+ once: true
109
+ });
88
110
  try {
89
- await tanstackRouter.load({
90
- sync: true
91
- });
92
- } finally{
93
- const cost = end();
94
- context.ssrContext?.onTiming?.(LOADER_REPORTER_NAME, cost);
95
- }
96
- const serverLoadResult = serverRouter._serverResult;
97
- if (!serverLoadResult) {
111
+ rawRequest.signal.throwIfAborted();
112
+ await attachServerSsrUtils(serverRouter);
113
+ rawRequest.signal.throwIfAborted();
114
+ const end = time();
98
115
  try {
99
- serverRouter.serverSsr?.cleanup?.();
100
- } catch {}
101
- throw new Error('TanStack Router completed an SSR load without a server result.');
102
- }
103
- if ('redirect' === serverLoadResult.type) {
104
- const { redirect } = serverLoadResult;
105
- try {
106
- serverRouter.serverSsr?.cleanup?.();
107
- } catch {}
108
- return interrupt(isRSCNavigation ? handleTanstackRscRedirect(redirect.headers, _basename, redirect.status) : redirect);
109
- }
110
- const routerErrors = collectRouterErrors(tanstackRouter);
111
- if (routerErrors && 'clientRender' === loaderFailureMode) {
112
- context.ssrContext?.response?.status(200);
113
- try {
114
- serverRouter.serverSsr?.cleanup?.();
115
- } catch {}
116
- throw Object.values(routerErrors)[0];
117
- }
118
- await preloadMatchedRouteComponents(serverRouter);
119
- context.ssrContext?.response?.status(serverLoadResult.status);
120
- await serverRouter.serverSsr?.dehydrate?.();
121
- if (enableRsc) {
122
- if (isRSCNavigation) await waitForRouterSerialization(serverRouter);
123
- setTanstackRscServerPayload(createTanstackRscServerPayload(serverRouter, {
116
+ await tanstackRouter.load({
117
+ sync: true
118
+ });
119
+ } finally{
120
+ const cost = end();
121
+ context.ssrContext?.onTiming?.(LOADER_REPORTER_NAME, cost);
122
+ }
123
+ rawRequest.signal.throwIfAborted();
124
+ const serverLoadResult = serverRouter._serverResult;
125
+ if (!serverLoadResult) throw new Error('TanStack Router completed an SSR load without a server result.');
126
+ if ('redirect' === serverLoadResult.type) {
127
+ const { redirect } = serverLoadResult;
128
+ return interrupt(isRSCNavigation ? handleTanstackRscRedirect(redirect.headers, _basename, redirect.status) : redirect);
129
+ }
130
+ const routerErrors = collectRouterErrors(tanstackRouter);
131
+ if (routerErrors && 'clientRender' === loaderFailureMode) {
132
+ context.ssrContext?.response?.status(200);
133
+ throw Object.values(routerErrors)[0];
134
+ }
135
+ await preloadMatchedRouteComponents(serverRouter);
136
+ context.ssrContext?.response?.status(serverLoadResult.status);
137
+ await serverRouter.serverSsr?.dehydrate();
138
+ if (enableRsc) setTanstackRscServerPayload(createTanstackRscServerPayload(serverRouter, {
124
139
  omitClientLoaderData: isRSCNavigation
125
140
  }));
126
- }
127
- const ssrScriptTags = serverRouter.serverSsr?.takeBufferedScripts?.();
128
- const hydrationScripts = routerManagedTagsToHtml(ssrScriptTags);
129
- const matchedRouteIds = getModernRouteIdsFromMatches(serverRouter);
130
- const routerServerSnapshot = createRouterServerSnapshot({
131
- framework: 'tanstack',
132
- basename: _basename,
133
- statusCode: serverLoadResult.status,
134
- errors: routerErrors,
135
- matchedRouteIds,
136
- hydrationScripts
137
- });
138
- const runtimeContext = applyRouterServerPrepareResult(context, {
139
- snapshot: routerServerSnapshot,
140
- cleanup: ()=>serverRouter.serverSsr?.cleanup?.(),
141
- state: {
141
+ const initialScriptTags = serverRouter.serverSsr?.takeInitialHydrationScriptTags();
142
+ const hydrationScripts = initialScriptTags ? routerManagedTagsToHtml([
143
+ ...initialScriptTags.before,
144
+ initialScriptTags.boundary
145
+ ]) : [];
146
+ const matchedRouteIds = getModernRouteIdsFromMatches(serverRouter);
147
+ const routerServerSnapshot = {
142
148
  framework: 'tanstack',
143
149
  basename: _basename,
144
- instance: serverRouter,
145
- hydrationScripts,
150
+ statusCode: serverLoadResult.status,
151
+ errors: routerErrors,
146
152
  matchedRouteIds,
147
- serverSnapshot: routerServerSnapshot
148
- }
149
- });
150
- hooks.onAfterCreateRouter.call({
151
- ...routerLifecycleContext,
152
- router: serverRouter,
153
- serverSnapshot: routerServerSnapshot,
154
- runtimeContext
155
- });
153
+ hydrationScripts
154
+ };
155
+ const runtimeContext = applyRouterServerPrepareResult(context, {
156
+ snapshot: routerServerSnapshot,
157
+ cleanup,
158
+ state: {
159
+ framework: 'tanstack',
160
+ basename: _basename,
161
+ instance: serverRouter,
162
+ navigation: createTanstackNavigation(tanstackRouter)
163
+ }
164
+ });
165
+ rawRequest.signal.throwIfAborted();
166
+ hooks.onAfterCreateRouter.call({
167
+ ...routerLifecycleContext,
168
+ router: serverRouter,
169
+ serverSnapshot: getRouterServerSnapshot(runtimeContext),
170
+ runtimeContext
171
+ });
172
+ prepared = true;
173
+ } finally{
174
+ if (!prepared) try {
175
+ cleanup();
176
+ } catch {}
177
+ }
156
178
  });
157
179
  api.wrapRoot((App)=>{
158
180
  const getRouteApp = ()=>{
@@ -1,11 +1,6 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
+ import { resolvePreloadFromPrefetch } from "@modern-js/runtime-extensions";
2
3
  import { useLinkProps } from "@tanstack/react-router";
3
- function resolvePreloadFromPrefetch(prefetch, preload) {
4
- if (void 0 !== preload) return preload;
5
- if ('none' === prefetch) return false;
6
- if ('intent' === prefetch || 'render' === prefetch || 'viewport' === prefetch) return prefetch;
7
- return 'viewport';
8
- }
9
4
  const LinkComponentImpl = (props)=>{
10
5
  const { prefetch, preload, 'aria-current': ariaCurrentProp, ref, children, ...rest } = props;
11
6
  const hasAriaCurrentOverride = 'aria-current' in props;
@@ -1,5 +1,3 @@
1
- import { registerRouterProvider } from "@modern-js/runtime/context";
2
1
  import { tanstackRouterPlugin } from "./plugin.mjs";
3
2
  const tanstackRouterProviderFactory = (userConfig)=>tanstackRouterPlugin(userConfig);
4
- registerRouterProvider('tanstack', tanstackRouterProviderFactory);
5
3
  export { tanstackRouterProviderFactory };
@@ -1,22 +1,19 @@
1
1
  import { DefaultNotFound } from "@modern-js/runtime/context";
2
2
  import { rootRouteId } from "@tanstack/react-router";
3
+ import { describeRouteTree } from "../../shared/routeDescriptor.mjs";
3
4
  import { createRouteStaticData } from "../../shared/routeStaticData.mjs";
4
5
  import { withModernRouteMatchContext } from "../outlet.mjs";
5
6
  import { toErrorComponent, toPendingComponent, toRouteComponent } from "./components.mjs";
6
7
  import { createModernShouldReload, wrapRouteObjectLoader } from "./loaders.mjs";
7
- import { isRouteObjectPathlessLayout, toTanstackPath } from "./paths.mjs";
8
8
  import { mergeModernRouteHandle } from "./staticData.mjs";
9
9
  import { createTanstackRootRoute, createTanstackRoute, wrapRouteComponentWithModernContext } from "./tanstackRoutes.mjs";
10
- function createRouteFromRouteObject(opts) {
11
- const { options = {}, parent, pathlessFallbackId = 'pathless', routeObject } = opts;
10
+ function createRouteOptions(routeObject, options) {
12
11
  const modernRouteObject = routeObject;
13
12
  const revalidationState = {};
14
13
  const shouldRevalidate = modernRouteObject.shouldRevalidate;
15
14
  const shouldReload = createModernShouldReload(shouldRevalidate, revalidationState);
16
- const stableFallbackId = routeObject.id || modernRouteObject.file || pathlessFallbackId;
17
15
  const component = toRouteComponent(routeObject);
18
16
  const base = {
19
- getParentRoute: ()=>parent,
20
17
  component,
21
18
  pendingComponent: toPendingComponent(routeObject),
22
19
  errorComponent: toErrorComponent(routeObject),
@@ -37,66 +34,29 @@ function createRouteFromRouteObject(opts) {
37
34
  };
38
35
  if (modernRouteObject.inValidSSRRoute) base.ssr = false;
39
36
  if (shouldReload) base.shouldReload = shouldReload;
40
- if (isRouteObjectPathlessLayout(routeObject)) base.id = stableFallbackId;
41
- else base.path = routeObject.index ? '/' : toTanstackPath(routeObject.path || '');
42
- const route = createTanstackRoute(base);
43
- wrapRouteComponentWithModernContext(route, component, routeObject.id);
44
- const children = routeObject.children;
45
- if (children && children.length > 0) {
46
- const childRoutes = children.map((child, index)=>createRouteFromRouteObject({
47
- options,
48
- parent: route,
49
- pathlessFallbackId: `pathless-${index}`,
50
- routeObject: child
51
- }));
52
- route.addChildren(childRoutes);
53
- }
54
- return route;
37
+ return base;
55
38
  }
56
- function getRootLikeRouteObject(routes) {
57
- return routes.find((route)=>'/' === route.path && !route.index);
39
+ function createRouteFromDescriptor(descriptor, parent, options) {
40
+ const { source, location, children } = descriptor;
41
+ const routeOptions = createRouteOptions(source, options);
42
+ const route = createTanstackRoute({
43
+ ...routeOptions,
44
+ ...location,
45
+ getParentRoute: ()=>parent
46
+ });
47
+ wrapRouteComponentWithModernContext(route, routeOptions.component, source.id);
48
+ if (children.length) route.addChildren(children.map((child)=>createRouteFromDescriptor(child, route, options)));
49
+ return route;
58
50
  }
59
51
  function createRouteTreeFromRouteObjects(routes, options = {}) {
60
- const rootLikeRoute = getRootLikeRouteObject(routes);
61
- const rootRevalidationState = {};
62
- const rootShouldRevalidate = rootLikeRoute?.shouldRevalidate;
63
- const rootShouldReload = createModernShouldReload(rootShouldRevalidate, rootRevalidationState);
64
- const rootComponent = rootLikeRoute ? toRouteComponent(rootLikeRoute) : void 0;
52
+ const { root, children } = describeRouteTree(routes);
65
53
  const rootRouteOptions = {
66
- component: rootComponent,
67
- pendingComponent: rootLikeRoute ? toPendingComponent(rootLikeRoute) : void 0,
68
- errorComponent: rootLikeRoute ? toErrorComponent(rootLikeRoute) : void 0,
69
- validateSearch: rootLikeRoute?.validateSearch,
70
- loaderDeps: rootLikeRoute?.loaderDeps,
71
- notFoundComponent: DefaultNotFound,
72
- staticData: createRouteStaticData({
73
- modernRouteId: rootLikeRoute?.id,
74
- modernRouteAction: rootLikeRoute?.action,
75
- modernRouteHandle: rootLikeRoute ? mergeModernRouteHandle(rootLikeRoute) : void 0,
76
- modernRouteHasAction: rootLikeRoute?.hasAction || Boolean(rootLikeRoute?.action),
77
- modernRouteHasClientLoader: rootLikeRoute?.hasClientLoader || void 0 !== rootLikeRoute?.clientData,
78
- modernRouteHasLoader: rootLikeRoute?.hasLoader || 'function' == typeof rootLikeRoute?.loader,
79
- modernRouteIsClientComponent: rootLikeRoute?.isClientComponent,
80
- modernRouteLoader: rootLikeRoute?.loader,
81
- modernRouteShouldRevalidate: rootShouldRevalidate
82
- }),
83
- loader: rootLikeRoute ? wrapRouteObjectLoader(rootLikeRoute, rootRevalidationState, options) : void 0
54
+ ...root ? createRouteOptions(root, options) : {},
55
+ notFoundComponent: DefaultNotFound
84
56
  };
85
- if (rootShouldReload) rootRouteOptions.shouldReload = rootShouldReload;
86
- if (rootLikeRoute?.inValidSSRRoute) rootRouteOptions.ssr = false;
87
57
  const rootRoute = createTanstackRootRoute(rootRouteOptions);
88
- if (rootComponent) rootRoute.options.component = withModernRouteMatchContext(rootComponent, rootRouteId);
89
- const topLevel = rootLikeRoute ? [
90
- ...rootLikeRoute.children || [],
91
- ...routes.filter((route)=>route !== rootLikeRoute)
92
- ] : routes;
93
- const childRoutes = topLevel.map((routeObject, index)=>createRouteFromRouteObject({
94
- options,
95
- parent: rootRoute,
96
- pathlessFallbackId: `pathless-${index}`,
97
- routeObject
98
- }));
99
- rootRoute.addChildren(childRoutes);
58
+ if (rootRouteOptions.component) rootRoute.options.component = withModernRouteMatchContext(rootRouteOptions.component, rootRouteId);
59
+ rootRoute.addChildren(children.map((child)=>createRouteFromDescriptor(child, rootRoute, options)));
100
60
  return rootRoute;
101
61
  }
102
62
  function getModernRouteIdsFromMatches(router) {
@@ -1,4 +1,4 @@
1
- import { getLoaderHref, handleModernLoaderError, handleModernLoaderResult, mapSplatParamsForModernLoader } from "../loaderBridge.mjs";
1
+ import { getLoaderHref, getLoaderSignal, handleModernLoaderError, handleModernLoaderResult, mapSplatParamsForModernLoader } from "../loaderBridge.mjs";
2
2
  import { isTanstackRscPayloadNavigationEnabled, loadTanstackRscRouteData } from "../rsc/payloadRouter.mjs";
3
3
  function isModernDeferredData(value) {
4
4
  if (!value || 'object' != typeof value) return false;
@@ -49,7 +49,7 @@ function wrapRouteObjectLoader(route, revalidationState, options = {}) {
49
49
  if ('function' == typeof modernRoute.lazyImport) try {
50
50
  await modernRoute.lazyImport();
51
51
  } catch {}
52
- const signal = ctx?.abortController?.signal || ctx?.signal || new AbortController().signal;
52
+ const signal = getLoaderSignal(ctx);
53
53
  const baseRequest = ctx?.context?.request instanceof Request ? ctx.context.request : void 0;
54
54
  const href = getLoaderHref(ctx);
55
55
  const request = void 0 !== baseRequest ? new Request(baseRequest, {
@@ -10,7 +10,4 @@ function toTanstackPath(pathname) {
10
10
  return segment;
11
11
  }).join('/');
12
12
  }
13
- function isRouteObjectPathlessLayout(route) {
14
- return !route.path && !route.index;
15
- }
16
- export { isRouteObjectPathlessLayout, toTanstackPath };
13
+ export { toTanstackPath };
@@ -1,16 +1,32 @@
1
- import * as __rspack_external__modern_js_runtime_router_internal_8b8183c5 from "@modern-js/runtime/router/internal";
1
+ import { routerProviderRegistryHooks } from "@modern-js/runtime/context";
2
+ import { routerPlugin } from "@modern-js/runtime/router/internal";
3
+ import { createRouterPlugin } from "@modern-js/runtime-extensions/router-provider";
4
+ import { createRouterStatePlugin } from "@modern-js/runtime-extensions/router-state-plugin";
2
5
  import { tanstackRouterProviderFactory } from "./register.mjs";
3
- function getRouterPlugin() {
4
- const createRouterPlugin = Reflect.get(__rspack_external__modern_js_runtime_router_internal_8b8183c5, 'createRouterPlugin');
5
- if ('function' == typeof createRouterPlugin) return createRouterPlugin([
6
+ const createProviderPlugin = createRouterPlugin({
7
+ defaultProvider: {
8
+ name: 'react-router',
9
+ factory: routerPlugin
10
+ },
11
+ registryHooks: routerProviderRegistryHooks,
12
+ localProviders: [
6
13
  {
7
14
  name: 'tanstack',
8
15
  factory: tanstackRouterProviderFactory
9
16
  }
10
- ]);
11
- const legacyRouterPlugin = Reflect.get(__rspack_external__modern_js_runtime_router_internal_8b8183c5, 'routerPlugin');
12
- if ('function' == typeof legacyRouterPlugin) return tanstackRouterProviderFactory;
13
- throw new Error('[@modern-js/plugin-tanstack] The installed @modern-js/runtime/router/internal exports neither createRouterPlugin nor routerPlugin. Install a compatible @modern-js/runtime version.');
14
- }
15
- const routerPlugin = getRouterPlugin();
16
- export { routerPlugin };
17
+ ]
18
+ });
19
+ const statePlugin = createRouterStatePlugin({
20
+ registryHooks: routerProviderRegistryHooks
21
+ });
22
+ const router_routerPlugin = (userConfig = {})=>{
23
+ const providerPlugin = createProviderPlugin(userConfig);
24
+ return {
25
+ ...providerPlugin,
26
+ setup (api) {
27
+ statePlugin.setup(api);
28
+ providerPlugin.setup(api);
29
+ }
30
+ };
31
+ };
32
+ export { router_routerPlugin as routerPlugin };
@@ -1,10 +1,3 @@
1
- async function waitForRouterSerialization(tanstackRouter) {
2
- const serverSsr = tanstackRouter.serverSsr;
3
- if (!serverSsr || 'function' != typeof serverSsr.onSerializationFinished || serverSsr.isSerializationFinished?.()) return;
4
- await new Promise((resolve)=>{
5
- serverSsr.onSerializationFinished?.(resolve);
6
- });
7
- }
8
1
  function htmlEscapeAttr(value) {
9
2
  return value.replace(/&/g, '&').replace(/"/g, '"');
10
3
  }
@@ -50,4 +43,4 @@ async function attachServerSsrUtils(router) {
50
43
  manifest: void 0
51
44
  });
52
45
  }
53
- export { attachServerSsrUtils, collectRouterErrors, createGetSsrHref, routerManagedTagsToHtml, waitForRouterSerialization };
46
+ export { attachServerSsrUtils, collectRouterErrors, createGetSsrHref, routerManagedTagsToHtml };
@@ -1,4 +1,4 @@
1
- import { getRouterRuntimeState } from "@modern-js/runtime/context";
1
+ import { getRouterRuntimeState } from "@modern-js/runtime-extensions/router-state";
2
2
  function getTanstackRouterState(context) {
3
3
  const state = getRouterRuntimeState(context);
4
4
  if (void 0 === state || 'tanstack' !== state.framework || void 0 === state.instance) return;
@@ -13,6 +13,8 @@ function withGlobalLayout(Component, globalApp) {
13
13
  }
14
14
  function toTanstackRouteObject(route, globalApp) {
15
15
  if ('nested' === route.type) return {
16
+ modernLocalisedRoute: Reflect.get(route, 'modernLocalisedRoute'),
17
+ isRoot: Reflect.get(route, 'isRoot'),
16
18
  path: route.path,
17
19
  id: route.id,
18
20
  loader: route.loader,
@@ -37,6 +39,7 @@ function toTanstackRouteObject(route, globalApp) {
37
39
  if ('function' != typeof route.component && 'object' != typeof route.component) return null;
38
40
  const LayoutComponent = withGlobalLayout(route.component, globalApp);
39
41
  return {
42
+ modernLocalisedRoute: Reflect.get(route, 'modernLocalisedRoute'),
40
43
  path: route.path,
41
44
  element: /*#__PURE__*/ react.createElement(LayoutComponent)
42
45
  };
@@ -0,0 +1,22 @@
1
+ import { toTanstackPath } from "../runtime/routeTree/paths.mjs";
2
+ function describeRouteTree(routes) {
3
+ const root = routes.find((route)=>true === route.isRoot || '/' === route.path && true !== route.index);
4
+ const describe = (route, index)=>({
5
+ source: route,
6
+ location: 0 === (route.path ?? '').length && true !== route.index ? {
7
+ id: route.id || route.file || `pathless-${index}`
8
+ } : {
9
+ path: true === route.index ? '/' : toTanstackPath(route.path || '')
10
+ },
11
+ hasSplat: Boolean(route.path?.includes('*')),
12
+ children: (route.children ?? []).map(describe)
13
+ });
14
+ return {
15
+ root,
16
+ children: (void 0 !== root ? [
17
+ ...root.children ?? [],
18
+ ...routes.filter((route)=>route !== root)
19
+ ] : routes).map(describe)
20
+ };
21
+ }
22
+ export { describeRouteTree };
@@ -1,6 +1,7 @@
1
1
  import "node:module";
2
2
  import node_path from "node:path";
3
3
  import { fs } from "@modern-js/utils";
4
+ import { ROUTE_METADATA_MANIFEST_FILE_NAME, ROUTE_METADATA_MANIFEST_HEADER, findRouteMetaFiles, renderRouteMetadataManifest } from "./routeMetadata.mjs";
4
5
  import { collectCanonicalRoutesForEntry, generateTanstackRouterTypesSourceForEntry } from "./tanstackTypes.mjs";
5
6
  const DEFAULT_GENERATED_DIR_NAME = 'modern-tanstack';
6
7
  async function writeFileIfChanged(filePath, content) {
@@ -78,7 +79,16 @@ async function writeTanstackRouterTypesForEntries(opts) {
78
79
  canonicalRoutes
79
80
  });
80
81
  }
82
+ async function writeRouteMetadataManifest(opts) {
83
+ const routesDirectory = node_path.join(opts.appDirectory, 'src', 'routes');
84
+ const manifestPath = node_path.join(routesDirectory, ROUTE_METADATA_MANIFEST_FILE_NAME);
85
+ const manifest = renderRouteMetadataManifest(await findRouteMetaFiles(routesDirectory));
86
+ if (null !== manifest) return void await writeFileIfChanged(manifestPath, manifest);
87
+ const previous = await fs.pathExists(manifestPath) ? await fs.readFile(manifestPath, 'utf-8') : null;
88
+ if (previous?.startsWith(`${ROUTE_METADATA_MANIFEST_HEADER}\n`)) throw new Error(`[plugin-tanstack] ${manifestPath} is generated from route.meta.ts files, but none remain below ${routesDirectory}. Restore at least one route.meta.ts that exports routeMeta, or delete the manifest together with its imports.`);
89
+ }
81
90
  async function generateTanstackRouteArtifacts(opts) {
91
+ await writeRouteMetadataManifest(opts);
82
92
  const [{ createRunOptions }, { cli }, utils] = await Promise.all([
83
93
  import("@modern-js/app-tools/cli/run"),
84
94
  import("@modern-js/plugin/cli"),
@@ -96,9 +106,10 @@ async function generateTanstackRouteArtifacts(opts) {
96
106
  version: opts.version || process.env.MODERN_JS_VERSION || '0.0.0-routes-generate',
97
107
  internalPlugins: utils.INTERNAL_RUNTIME_PLUGINS
98
108
  });
99
- await cli.init({
109
+ const { appContext } = await cli.init({
100
110
  ...runOptions,
101
111
  command: 'build'
102
112
  });
113
+ await appContext.hooks.onBeforeExit.call();
103
114
  }
104
- export { generateTanstackRouteArtifacts, writeTanstackRegisterFile, writeTanstackRouterTypesForEntries };
115
+ export { generateTanstackRouteArtifacts, writeRouteMetadataManifest, writeTanstackRegisterFile, writeTanstackRouterTypesForEntries };
@@ -1,26 +1,20 @@
1
1
  import "node:module";
2
2
  import node_path from "node:path";
3
3
  import { NESTED_ROUTE_SPEC_FILE, filterRoutesForServer } from "@modern-js/utils";
4
- import { generateTanstackRouteArtifacts, writeTanstackRegisterFile, writeTanstackRouterTypesForEntries } from "./artifacts.mjs";
4
+ import { generateTanstackRouteArtifacts, writeRouteMetadataManifest, writeTanstackRegisterFile, writeTanstackRouterTypesForEntries } from "./artifacts.mjs";
5
5
  import { createTanstackRsbuildRouteSplittingProfile, resolveTanstackRouteCodeSplittingEnabled } from "./routeSplitting.mjs";
6
- import { __webpack_require__ } from "../rslib-runtime~0.mjs";
7
6
  import { fileURLToPath as __rspack_fileURLToPath } from "node:url";
8
7
  import { dirname as __rspack_dirname } from "node:path";
9
8
  var __rspack_import_meta_dirname__ = __rspack_dirname(__rspack_fileURLToPath(import.meta.url));
10
9
  import { createRequire as __rspack_createRequire } from "node:module";
11
10
  const __rspack_createRequire_require = __rspack_createRequire(import.meta.url);
12
- __webpack_require__.add({
13
- "@modern-js/runtime/cli?667f" (module) {
14
- module.exports = __rspack_createRequire_require("@modern-js/runtime/cli");
15
- }
16
- });
17
11
  const DEFAULT_ROUTES_DIR = 'routes';
18
12
  const DEFAULT_GENERATED_DIR_NAME = 'modern-tanstack';
19
13
  const ENTRYPOINTS_KEY = '@modern-js/plugin-tanstack';
20
14
  let runtimeRouterCli;
21
15
  function getRuntimeRouterCli() {
22
16
  if (runtimeRouterCli) return runtimeRouterCli;
23
- const cli = __webpack_require__("@modern-js/runtime/cli?667f");
17
+ const cli = __rspack_createRequire_require("@modern-js/runtime/cli");
24
18
  if (cli.handleGeneratorEntryCode && cli.getEntrypointRoutesDir && cli.getEntrypointRoutesOwner && cli.updateNestedRoutesSpec) {
25
19
  runtimeRouterCli = cli;
26
20
  return runtimeRouterCli;
@@ -37,6 +31,15 @@ function tanstackRouterPlugin(options = {}) {
37
31
  '@modern-js/runtime'
38
32
  ],
39
33
  setup: (api)=>{
34
+ const { srcDirectory, serverCompileExcludedFiles = [] } = api.getAppContext();
35
+ api.updateAppContext({
36
+ serverCompileExcludedFiles: [
37
+ ...new Set([
38
+ ...serverCompileExcludedFiles,
39
+ node_path.join(srcDirectory, generatedDirName, 'register.gen.d.ts')
40
+ ])
41
+ ]
42
+ });
40
43
  const nestedRoutesForServer = {};
41
44
  const isTanstackEntrypoint = (entrypoint)=>{
42
45
  const { getEntrypointRoutesDir } = getRuntimeRouterCli();
@@ -179,4 +182,4 @@ function tanstackRouterPlugin(options = {}) {
179
182
  const src_cli = tanstackRouterPlugin;
180
183
  export { collectCanonicalRoutesForEntry, generateTanstackRouterTypesSourceForEntry } from "./tanstackTypes.mjs";
181
184
  export default src_cli;
182
- export { createTanstackRsbuildRouteSplittingProfile, generateTanstackRouteArtifacts, resolveTanstackRouteCodeSplittingEnabled, tanstackRouterPlugin, writeTanstackRegisterFile, writeTanstackRouterTypesForEntries };
185
+ export { createTanstackRsbuildRouteSplittingProfile, generateTanstackRouteArtifacts, resolveTanstackRouteCodeSplittingEnabled, tanstackRouterPlugin, writeRouteMetadataManifest, writeTanstackRegisterFile, writeTanstackRouterTypesForEntries };
@@ -0,0 +1,72 @@
1
+ import "node:module";
2
+ import { readdir } from "node:fs/promises";
3
+ import node_path from "node:path";
4
+ const ROUTE_META_FILE_NAME = 'route.meta.ts';
5
+ const ROUTE_METADATA_MANIFEST_FILE_NAME = 'ultramodern-route-metadata.ts';
6
+ const ROUTE_METADATA_MANIFEST_HEADER = `// @generated by @modern-js/plugin-tanstack from ${ROUTE_META_FILE_NAME} files. Run routes-generate; do not edit.`;
7
+ const PRINT_WIDTH = 120;
8
+ const MANIFEST_BODY = `export const ultramodernLocalisedUrls = Object.fromEntries(
9
+ ultramodernRouteMetadata
10
+ .filter((route: { canonicalPath: string }) => route.canonicalPath !== '/')
11
+ .map((route) => [route.canonicalPath, route.localisedPaths]),
12
+ );
13
+ export const ultramodernPublicRoutes = ultramodernRouteMetadata
14
+ .filter((route) => route.public && route.indexable)
15
+ .map((route) => ({
16
+ canonicalPath: route.canonicalPath,
17
+ descriptionKey: route.descriptionKey,
18
+ id: route.id,
19
+ localisedPaths: route.localisedPaths,
20
+ namespace: route.namespace,
21
+ ownerAppId: route.ownerAppId,
22
+ titleKey: route.titleKey,
23
+ ...('jsonLd' in route ? { jsonLd: route.jsonLd } : {}),
24
+ }));
25
+ export const ultramodernRouteConfig = {
26
+ authoring: 'colocated-route-meta',
27
+ generatedManifest: true,
28
+ localisedUrls: ultramodernLocalisedUrls,
29
+ namespace: ultramodernRouteNamespace,
30
+ publicRoutes: ultramodernPublicRoutes,
31
+ routes: ultramodernRouteMetadata,
32
+ source: 'route-owned',
33
+ } as const;
34
+ `;
35
+ const compareCodeUnits = (left, right)=>left < right ? -1 : left > right ? 1 : 0;
36
+ const quoteSpecifier = (specifier)=>specifier.includes("'") ? JSON.stringify(specifier) : `'${specifier}'`;
37
+ function renderRouteMetadataManifest(routeMetaFiles) {
38
+ const specifiers = routeMetaFiles.map((file)=>`./${file.replaceAll('\\', '/').replace(/\.ts$/u, '')}`).sort(compareCodeUnits);
39
+ if (0 === specifiers.length) return null;
40
+ const bindings = specifiers.map((_, index)=>`route${index}`);
41
+ const imports = specifiers.map((specifier, index)=>`import { routeMeta as ${bindings[index]} } from ${quoteSpecifier(specifier)};`);
42
+ const inlineRoutes = `export const ultramodernRouteMetadata = [${bindings.join(', ')}] as const;`;
43
+ const routes = inlineRoutes.length <= PRINT_WIDTH ? inlineRoutes : `export const ultramodernRouteMetadata = [\n${bindings.map((binding)=>` ${binding},\n`).join('')}] as const;`;
44
+ return `${ROUTE_METADATA_MANIFEST_HEADER}
45
+ ${imports.join('\n')}
46
+
47
+ export const ultramodernRouteNamespace = route0.namespace;
48
+ ${routes}
49
+ ${MANIFEST_BODY}`;
50
+ }
51
+ async function findRouteMetaFiles(routesDirectory) {
52
+ const files = [];
53
+ const visit = async (relativeDirectory)=>{
54
+ const entries = await readdir(node_path.join(routesDirectory, relativeDirectory), {
55
+ withFileTypes: true
56
+ });
57
+ for (const entry of entries){
58
+ const relativePath = node_path.join(relativeDirectory, entry.name);
59
+ if (entry.isDirectory()) await visit(relativePath);
60
+ else if (entry.isFile() && entry.name === ROUTE_META_FILE_NAME) files.push(relativePath);
61
+ }
62
+ };
63
+ try {
64
+ await visit('');
65
+ } catch (error) {
66
+ const { code, path: missingPath } = error;
67
+ if ('ENOENT' === code && missingPath === routesDirectory) return [];
68
+ throw error;
69
+ }
70
+ return files;
71
+ }
72
+ export { ROUTE_METADATA_MANIFEST_FILE_NAME, ROUTE_METADATA_MANIFEST_HEADER, ROUTE_META_FILE_NAME, findRouteMetaFiles, renderRouteMetadataManifest };