@bleedingdev/modern-js-plugin-tanstack 3.9.0-ultramodern.11 → 3.9.0-ultramodern.13

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 (81) hide show
  1. package/dist/cjs/cli/artifacts.js +2 -1
  2. package/dist/cjs/cli/tanstackTypes/canonicalRoutes.js +7 -7
  3. package/dist/cjs/cli/tanstackTypes/shared.js +0 -14
  4. package/dist/cjs/cli/tanstackTypes/source.js +28 -63
  5. package/dist/cjs/runtime/lifecycle.js +0 -3
  6. package/dist/cjs/runtime/loaderBridge.js +10 -4
  7. package/dist/cjs/runtime/navigation.js +102 -0
  8. package/dist/cjs/runtime/plugin.js +6 -1
  9. package/dist/cjs/runtime/plugin.node.js +81 -63
  10. package/dist/cjs/runtime/routeTree/construction.js +19 -61
  11. package/dist/cjs/runtime/routeTree/loaders.js +1 -1
  12. package/dist/cjs/runtime/routeTree/paths.js +0 -6
  13. package/dist/cjs/runtime/ssrManagedTags.js +2 -12
  14. package/dist/cjs/runtime/utils.js +1 -0
  15. package/dist/cjs/shared/routeDescriptor.js +60 -0
  16. package/dist/esm/cli/artifacts.mjs +2 -1
  17. package/dist/esm/cli/index.mjs +1 -7
  18. package/dist/esm/cli/tanstackTypes/canonicalRoutes.mjs +7 -7
  19. package/dist/esm/cli/tanstackTypes/shared.mjs +1 -9
  20. package/dist/esm/cli/tanstackTypes/source.mjs +29 -64
  21. package/dist/esm/runtime/lifecycle.mjs +1 -1
  22. package/dist/esm/runtime/loaderBridge.mjs +8 -5
  23. package/dist/esm/runtime/navigation.mjs +64 -0
  24. package/dist/esm/runtime/plugin.mjs +6 -1
  25. package/dist/esm/runtime/plugin.node.mjs +83 -65
  26. package/dist/esm/runtime/routeTree/construction.mjs +19 -61
  27. package/dist/esm/runtime/routeTree/loaders.mjs +2 -2
  28. package/dist/esm/runtime/routeTree/paths.mjs +1 -4
  29. package/dist/esm/runtime/ssrManagedTags.mjs +1 -8
  30. package/dist/esm/runtime/utils.mjs +1 -0
  31. package/dist/esm/shared/routeDescriptor.mjs +22 -0
  32. package/dist/esm-node/cli/artifacts.mjs +2 -1
  33. package/dist/esm-node/cli/index.mjs +1 -7
  34. package/dist/esm-node/cli/tanstackTypes/canonicalRoutes.mjs +7 -7
  35. package/dist/esm-node/cli/tanstackTypes/shared.mjs +1 -9
  36. package/dist/esm-node/cli/tanstackTypes/source.mjs +29 -64
  37. package/dist/esm-node/runtime/lifecycle.mjs +1 -1
  38. package/dist/esm-node/runtime/loaderBridge.mjs +8 -5
  39. package/dist/esm-node/runtime/navigation.mjs +65 -0
  40. package/dist/esm-node/runtime/plugin.mjs +6 -1
  41. package/dist/esm-node/runtime/plugin.node.mjs +83 -65
  42. package/dist/esm-node/runtime/routeTree/construction.mjs +19 -61
  43. package/dist/esm-node/runtime/routeTree/loaders.mjs +2 -2
  44. package/dist/esm-node/runtime/routeTree/paths.mjs +1 -4
  45. package/dist/esm-node/runtime/ssrManagedTags.mjs +1 -8
  46. package/dist/esm-node/runtime/utils.mjs +1 -0
  47. package/dist/esm-node/shared/routeDescriptor.mjs +23 -0
  48. package/dist/types/cli/tanstackTypes/shared.d.ts +0 -2
  49. package/dist/types/runtime/lifecycle.d.ts +1 -1
  50. package/dist/types/runtime/loaderBridge.d.ts +1 -0
  51. package/dist/types/runtime/navigation.d.ts +4 -0
  52. package/dist/types/runtime/routeTree/paths.d.ts +0 -2
  53. package/dist/types/runtime/ssrManagedTags.d.ts +0 -1
  54. package/dist/types/runtime/ssrTypes.d.ts +0 -7
  55. package/dist/types/shared/routeDescriptor.d.ts +26 -0
  56. package/package.json +21 -21
  57. package/src/cli/artifacts.ts +6 -1
  58. package/src/cli/tanstackTypes/canonicalRoutes.ts +17 -12
  59. package/src/cli/tanstackTypes/shared.ts +0 -14
  60. package/src/cli/tanstackTypes/source.ts +43 -119
  61. package/src/runtime/lifecycle.ts +0 -1
  62. package/src/runtime/loaderBridge.ts +9 -9
  63. package/src/runtime/navigation.ts +78 -0
  64. package/src/runtime/plugin.node.tsx +111 -91
  65. package/src/runtime/plugin.tsx +6 -0
  66. package/src/runtime/routeTree/construction.ts +32 -112
  67. package/src/runtime/routeTree/loaders.ts +2 -4
  68. package/src/runtime/routeTree/paths.ts +0 -6
  69. package/src/runtime/ssrManagedTags.ts +0 -17
  70. package/src/runtime/ssrTypes.ts +0 -7
  71. package/src/runtime/utils.tsx +1 -0
  72. package/src/shared/routeDescriptor.ts +46 -0
  73. package/tests/router/clientNavigation.ts +13 -0
  74. package/tests/router/generateRouteArtifacts.test.ts +36 -2
  75. package/tests/router/localisedIdentity.test.tsx +7 -2
  76. package/tests/router/prefetchLink.test.tsx +29 -0
  77. package/tests/router/routeHooks.test.ts +2 -1
  78. package/tests/router/serverPlugin.test.ts +150 -0
  79. package/tests/router/tanstackTypes.test.ts +121 -2
  80. package/dist/esm/rslib-runtime~1.mjs +0 -18
  81. package/dist/esm-node/rslib-runtime~0.mjs +0 -19
@@ -1,2 +1,2 @@
1
1
  import "node:module";
2
- export { applyRouterRuntimeState, applyRouterServerPrepareResult, createRouterRuntimeState, createRouterServerSnapshot, getRouterRuntimeState, getRouterServerSnapshot } from "@modern-js/runtime-extensions/router-state";
2
+ export { applyRouterRuntimeState, applyRouterServerPrepareResult, createRouterServerSnapshot, getRouterRuntimeState, getRouterServerSnapshot } from "@modern-js/runtime-extensions/router-state";
@@ -37,10 +37,13 @@ function mapSplatParamsForModernLoader(params, hasSplat) {
37
37
  return rest;
38
38
  }
39
39
  function getLoaderSignal(ctx) {
40
- const abortSignal = ctx?.abortController?.signal;
41
- if (abortSignal instanceof AbortSignal) return abortSignal;
42
- if (ctx?.signal instanceof AbortSignal) return ctx.signal;
43
- return new AbortController().signal;
40
+ const matchSignal = ctx?.abortController?.signal ?? ctx?.signal;
41
+ const requestSignal = ctx?.context?.request?.signal;
42
+ const signals = [
43
+ matchSignal,
44
+ requestSignal
45
+ ].filter((signal)=>signal instanceof AbortSignal);
46
+ return AbortSignal.any(signals);
44
47
  }
45
48
  function getLoaderHref(ctx) {
46
49
  if ('string' == typeof ctx?.location) return ctx.location;
@@ -102,4 +105,4 @@ function modernLoaderToTanstack(opts, modernLoader) {
102
105
  };
103
106
  }
104
107
  export { createRouteStaticData } from "../shared/routeStaticData.mjs";
105
- export { getLoaderHref, handleModernLoaderError, handleModernLoaderResult, isAbsoluteUrl, isRedirectResponse, isResponse, isTanstackRedirect, mapSplatParamsForModernLoader, modernLoaderToTanstack, throwTanstackRedirect };
108
+ export { getLoaderHref, getLoaderSignal, handleModernLoaderError, handleModernLoaderResult, isAbsoluteUrl, isRedirectResponse, isResponse, isTanstackRedirect, mapSplatParamsForModernLoader, modernLoaderToTanstack, throwTanstackRedirect };
@@ -0,0 +1,65 @@
1
+ import "node:module";
2
+ import { Link } from "./prefetchLink.mjs";
3
+ function createTanstackNavigation(router) {
4
+ let location;
5
+ let matches;
6
+ let snapshot;
7
+ return {
8
+ Link: Link,
9
+ getSnapshot () {
10
+ const state = router.state;
11
+ if (location !== state.location || void 0 === matches || matches.length !== state.matches.length || matches.some((match, index)=>match.params !== state.matches[index]?.params)) {
12
+ location = state.location;
13
+ matches = state.matches;
14
+ snapshot = {
15
+ location: {
16
+ pathname: location.pathname,
17
+ search: location.searchStr,
18
+ hash: '' !== location.hash ? `#${location.hash.replace(/^#/, '')}` : ''
19
+ },
20
+ params: Object.assign({}, ...matches.map((match)=>match.params))
21
+ };
22
+ }
23
+ return snapshot;
24
+ },
25
+ subscribe (listener) {
26
+ const stops = [
27
+ 'onBeforeNavigate',
28
+ 'onBeforeLoad',
29
+ 'onLoad',
30
+ 'onResolved'
31
+ ].map((event)=>router.subscribe(event, listener));
32
+ return ()=>{
33
+ for (const stop of stops)stop();
34
+ };
35
+ },
36
+ navigate (href, options) {
37
+ return router.navigate({
38
+ to: href,
39
+ replace: options?.replace,
40
+ ...options?.state === void 0 ? {} : {
41
+ state: options.state
42
+ }
43
+ });
44
+ },
45
+ createLinkProps (target) {
46
+ const preload = void 0 !== target.preload ? target.preload : 'none' === target.prefetch ? false : target.prefetch;
47
+ return {
48
+ to: target.pathname,
49
+ ...void 0 !== target.search ? {
50
+ search: target.search
51
+ } : {},
52
+ ...void 0 !== target.hash && '' !== target.hash ? {
53
+ hash: target.hash
54
+ } : {},
55
+ ...void 0 === target.hashScrollIntoView ? {} : {
56
+ hashScrollIntoView: target.hashScrollIntoView
57
+ },
58
+ ...void 0 === preload ? {} : {
59
+ preload
60
+ }
61
+ };
62
+ }
63
+ };
64
+ }
65
+ export { createTanstackNavigation };
@@ -11,6 +11,7 @@ import { ModernRouterClient, getTanstackSsrHydrationPromise, hasTanstackSsrHydra
11
11
  import { routerProviderRegistryHooks } from "./hooks.mjs";
12
12
  import { wrapTanstackSsrHydrationBoundary } from "./hydrationBoundary.mjs";
13
13
  import { applyRouterRuntimeState } from "./lifecycle.mjs";
14
+ import { createTanstackNavigation } from "./navigation.mjs";
14
15
  import { createTanstackRouteObjects, getMergedRouterConfig, getTanstackRouteConfig, joinBasename } from "./pluginShared.mjs";
15
16
  import { Link } from "./prefetchLink.mjs";
16
17
  import { useMatches } from "./routeHooks.mjs";
@@ -143,10 +144,14 @@ const tanstackRouterPlugin = (userConfig = {})=>{
143
144
  runtimeContext
144
145
  ]);
145
146
  if (!router) return App ? /*#__PURE__*/ jsx(App, {}) : null;
147
+ const navigation = useMemo(()=>createTanstackNavigation(router), [
148
+ router
149
+ ]);
146
150
  const runtimeState = applyRouterRuntimeState(runtimeContext, {
147
151
  framework: 'tanstack',
148
152
  basename: _basename,
149
- instance: router
153
+ instance: router,
154
+ navigation
150
155
  });
151
156
  const lifecycleContext = {
152
157
  framework: 'tanstack',
@@ -9,13 +9,14 @@ import { useContext } from "react";
9
9
  import { createModernBasepathRewrite } from "./basepathRewrite.mjs";
10
10
  import { routerProviderRegistryHooks } from "./hooks.mjs";
11
11
  import { wrapTanstackSsrHydrationBoundary } from "./hydrationBoundary.mjs";
12
- import { applyRouterServerPrepareResult, createRouterServerSnapshot, getRouterRuntimeState } from "./lifecycle.mjs";
12
+ import { applyRouterRuntimeState, applyRouterServerPrepareResult, getRouterRuntimeState, getRouterServerSnapshot } from "./lifecycle.mjs";
13
+ import { createTanstackNavigation } from "./navigation.mjs";
13
14
  import { createTanstackRouteObjects, getTanstackRouteConfig, joinBasename } from "./pluginShared.mjs";
14
15
  import { Link } from "./prefetchLink.mjs";
15
16
  import { createRouteTreeFromRouteObjects, getModernRouteIdsFromMatches } from "./routeTree/index.mjs";
16
17
  import { createTanstackRscServerPayload, handleTanstackRscRedirect } from "./rsc/payloadRouter.mjs";
17
18
  import { getTanstackRscRouter, setTanstackRscRouter, setTanstackRscServerPayload } from "./rsc/payloadStorage.mjs";
18
- import { attachServerSsrUtils, collectRouterErrors, createGetSsrHref, routerManagedTagsToHtml, waitForRouterSerialization } from "./ssrManagedTags.mjs";
19
+ import { attachServerSsrUtils, collectRouterErrors, createGetSsrHref, routerManagedTagsToHtml } from "./ssrManagedTags.mjs";
19
20
  import { preloadMatchedRouteComponents } from "./ssrPreload.mjs";
20
21
  import { getModernTanstackRouterFastDefaults } from "./types.mjs";
21
22
  const tanstackRouterPlugin = (userConfig = {})=>{
@@ -88,76 +89,93 @@ const tanstackRouterPlugin = (userConfig = {})=>{
88
89
  });
89
90
  const serverRouter = tanstackRouter;
90
91
  if (enableRsc) setTanstackRscRouter(serverRouter);
91
- await attachServerSsrUtils(serverRouter);
92
- const end = time();
92
+ let disposed = false;
93
+ let prepared = false;
94
+ const onAbort = ()=>controller.abort(rawRequest.signal.reason);
95
+ const cleanup = ()=>{
96
+ if (disposed) return;
97
+ disposed = true;
98
+ rawRequest.signal.removeEventListener('abort', onAbort);
99
+ controller.abort();
100
+ serverRouter.serverSsr?.cleanup();
101
+ };
102
+ applyRouterRuntimeState(context, {
103
+ framework: 'tanstack',
104
+ basename: _basename,
105
+ instance: serverRouter,
106
+ cleanup
107
+ });
108
+ rawRequest.signal.addEventListener('abort', onAbort, {
109
+ once: true
110
+ });
93
111
  try {
94
- await tanstackRouter.load({
95
- sync: true
96
- });
97
- } finally{
98
- const cost = end();
99
- context.ssrContext?.onTiming?.(LOADER_REPORTER_NAME, cost);
100
- }
101
- const serverLoadResult = serverRouter._serverResult;
102
- if (!serverLoadResult) {
112
+ rawRequest.signal.throwIfAborted();
113
+ await attachServerSsrUtils(serverRouter);
114
+ rawRequest.signal.throwIfAborted();
115
+ const end = time();
103
116
  try {
104
- serverRouter.serverSsr?.cleanup?.();
105
- } catch {}
106
- throw new Error('TanStack Router completed an SSR load without a server result.');
107
- }
108
- if ('redirect' === serverLoadResult.type) {
109
- const { redirect } = serverLoadResult;
110
- try {
111
- serverRouter.serverSsr?.cleanup?.();
112
- } catch {}
113
- return interrupt(isRSCNavigation ? handleTanstackRscRedirect(redirect.headers, _basename, redirect.status) : redirect);
114
- }
115
- const routerErrors = collectRouterErrors(tanstackRouter);
116
- if (routerErrors && 'clientRender' === loaderFailureMode) {
117
- context.ssrContext?.response?.status(200);
118
- try {
119
- serverRouter.serverSsr?.cleanup?.();
120
- } catch {}
121
- throw Object.values(routerErrors)[0];
122
- }
123
- await preloadMatchedRouteComponents(serverRouter);
124
- context.ssrContext?.response?.status(serverLoadResult.status);
125
- await serverRouter.serverSsr?.dehydrate?.();
126
- if (enableRsc) {
127
- if (isRSCNavigation) await waitForRouterSerialization(serverRouter);
128
- setTanstackRscServerPayload(createTanstackRscServerPayload(serverRouter, {
117
+ await tanstackRouter.load({
118
+ sync: true
119
+ });
120
+ } finally{
121
+ const cost = end();
122
+ context.ssrContext?.onTiming?.(LOADER_REPORTER_NAME, cost);
123
+ }
124
+ rawRequest.signal.throwIfAborted();
125
+ const serverLoadResult = serverRouter._serverResult;
126
+ if (!serverLoadResult) throw new Error('TanStack Router completed an SSR load without a server result.');
127
+ if ('redirect' === serverLoadResult.type) {
128
+ const { redirect } = serverLoadResult;
129
+ return interrupt(isRSCNavigation ? handleTanstackRscRedirect(redirect.headers, _basename, redirect.status) : redirect);
130
+ }
131
+ const routerErrors = collectRouterErrors(tanstackRouter);
132
+ if (routerErrors && 'clientRender' === loaderFailureMode) {
133
+ context.ssrContext?.response?.status(200);
134
+ throw Object.values(routerErrors)[0];
135
+ }
136
+ await preloadMatchedRouteComponents(serverRouter);
137
+ context.ssrContext?.response?.status(serverLoadResult.status);
138
+ await serverRouter.serverSsr?.dehydrate();
139
+ if (enableRsc) setTanstackRscServerPayload(createTanstackRscServerPayload(serverRouter, {
129
140
  omitClientLoaderData: isRSCNavigation
130
141
  }));
131
- }
132
- const ssrScriptTags = serverRouter.serverSsr?.takeBufferedScripts?.();
133
- const hydrationScripts = routerManagedTagsToHtml(ssrScriptTags);
134
- const matchedRouteIds = getModernRouteIdsFromMatches(serverRouter);
135
- const routerServerSnapshot = createRouterServerSnapshot({
136
- framework: 'tanstack',
137
- basename: _basename,
138
- statusCode: serverLoadResult.status,
139
- errors: routerErrors,
140
- matchedRouteIds,
141
- hydrationScripts
142
- });
143
- const runtimeContext = applyRouterServerPrepareResult(context, {
144
- snapshot: routerServerSnapshot,
145
- cleanup: ()=>serverRouter.serverSsr?.cleanup?.(),
146
- state: {
142
+ const initialScriptTags = serverRouter.serverSsr?.takeInitialHydrationScriptTags();
143
+ const hydrationScripts = initialScriptTags ? routerManagedTagsToHtml([
144
+ ...initialScriptTags.before,
145
+ initialScriptTags.boundary
146
+ ]) : [];
147
+ const matchedRouteIds = getModernRouteIdsFromMatches(serverRouter);
148
+ const routerServerSnapshot = {
147
149
  framework: 'tanstack',
148
150
  basename: _basename,
149
- instance: serverRouter,
150
- hydrationScripts,
151
+ statusCode: serverLoadResult.status,
152
+ errors: routerErrors,
151
153
  matchedRouteIds,
152
- serverSnapshot: routerServerSnapshot
153
- }
154
- });
155
- hooks.onAfterCreateRouter.call({
156
- ...routerLifecycleContext,
157
- router: serverRouter,
158
- serverSnapshot: routerServerSnapshot,
159
- runtimeContext
160
- });
154
+ hydrationScripts
155
+ };
156
+ const runtimeContext = applyRouterServerPrepareResult(context, {
157
+ snapshot: routerServerSnapshot,
158
+ cleanup,
159
+ state: {
160
+ framework: 'tanstack',
161
+ basename: _basename,
162
+ instance: serverRouter,
163
+ navigation: createTanstackNavigation(tanstackRouter)
164
+ }
165
+ });
166
+ rawRequest.signal.throwIfAborted();
167
+ hooks.onAfterCreateRouter.call({
168
+ ...routerLifecycleContext,
169
+ router: serverRouter,
170
+ serverSnapshot: getRouterServerSnapshot(runtimeContext),
171
+ runtimeContext
172
+ });
173
+ prepared = true;
174
+ } finally{
175
+ if (!prepared) try {
176
+ cleanup();
177
+ } catch {}
178
+ }
161
179
  });
162
180
  api.wrapRoot((App)=>{
163
181
  const getRouteApp = ()=>{
@@ -1,24 +1,20 @@
1
1
  import "node:module";
2
- import { canonicaliseLocalisedRoutes } from "@modern-js/i18n-runtime-extensions";
3
2
  import { DefaultNotFound } from "@modern-js/runtime/context";
4
3
  import { rootRouteId } from "@tanstack/react-router";
4
+ import { describeRouteTree } from "../../shared/routeDescriptor.mjs";
5
5
  import { createRouteStaticData } from "../../shared/routeStaticData.mjs";
6
6
  import { withModernRouteMatchContext } from "../outlet.mjs";
7
7
  import { toErrorComponent, toPendingComponent, toRouteComponent } from "./components.mjs";
8
8
  import { createModernShouldReload, wrapRouteObjectLoader } from "./loaders.mjs";
9
- import { isRouteObjectPathlessLayout, toTanstackPath } from "./paths.mjs";
10
9
  import { mergeModernRouteHandle } from "./staticData.mjs";
11
10
  import { createTanstackRootRoute, createTanstackRoute, wrapRouteComponentWithModernContext } from "./tanstackRoutes.mjs";
12
- function createRouteFromRouteObject(opts) {
13
- const { options = {}, parent, pathlessFallbackId = 'pathless', routeObject } = opts;
11
+ function createRouteOptions(routeObject, options) {
14
12
  const modernRouteObject = routeObject;
15
13
  const revalidationState = {};
16
14
  const shouldRevalidate = modernRouteObject.shouldRevalidate;
17
15
  const shouldReload = createModernShouldReload(shouldRevalidate, revalidationState);
18
- const stableFallbackId = routeObject.id || modernRouteObject.file || pathlessFallbackId;
19
16
  const component = toRouteComponent(routeObject);
20
17
  const base = {
21
- getParentRoute: ()=>parent,
22
18
  component,
23
19
  pendingComponent: toPendingComponent(routeObject),
24
20
  errorComponent: toErrorComponent(routeObject),
@@ -39,67 +35,29 @@ function createRouteFromRouteObject(opts) {
39
35
  };
40
36
  if (modernRouteObject.inValidSSRRoute) base.ssr = false;
41
37
  if (shouldReload) base.shouldReload = shouldReload;
42
- if (isRouteObjectPathlessLayout(routeObject)) base.id = stableFallbackId;
43
- else base.path = routeObject.index ? '/' : toTanstackPath(routeObject.path || '');
44
- const route = createTanstackRoute(base);
45
- wrapRouteComponentWithModernContext(route, component, routeObject.id);
46
- const children = routeObject.children;
47
- if (children && children.length > 0) {
48
- const childRoutes = children.map((child, index)=>createRouteFromRouteObject({
49
- options,
50
- parent: route,
51
- pathlessFallbackId: `pathless-${index}`,
52
- routeObject: child
53
- }));
54
- route.addChildren(childRoutes);
55
- }
56
- return route;
38
+ return base;
57
39
  }
58
- function getRootLikeRouteObject(routes) {
59
- return routes.find((route)=>'/' === route.path && !route.index);
40
+ function createRouteFromDescriptor(descriptor, parent, options) {
41
+ const { source, location, children } = descriptor;
42
+ const routeOptions = createRouteOptions(source, options);
43
+ const route = createTanstackRoute({
44
+ ...routeOptions,
45
+ ...location,
46
+ getParentRoute: ()=>parent
47
+ });
48
+ wrapRouteComponentWithModernContext(route, routeOptions.component, source.id);
49
+ if (children.length) route.addChildren(children.map((child)=>createRouteFromDescriptor(child, route, options)));
50
+ return route;
60
51
  }
61
52
  function createRouteTreeFromRouteObjects(routes, options = {}) {
62
- routes = canonicaliseLocalisedRoutes(routes);
63
- const rootLikeRoute = getRootLikeRouteObject(routes);
64
- const rootRevalidationState = {};
65
- const rootShouldRevalidate = rootLikeRoute?.shouldRevalidate;
66
- const rootShouldReload = createModernShouldReload(rootShouldRevalidate, rootRevalidationState);
67
- const rootComponent = rootLikeRoute ? toRouteComponent(rootLikeRoute) : void 0;
53
+ const { root, children } = describeRouteTree(routes);
68
54
  const rootRouteOptions = {
69
- component: rootComponent,
70
- pendingComponent: rootLikeRoute ? toPendingComponent(rootLikeRoute) : void 0,
71
- errorComponent: rootLikeRoute ? toErrorComponent(rootLikeRoute) : void 0,
72
- validateSearch: rootLikeRoute?.validateSearch,
73
- loaderDeps: rootLikeRoute?.loaderDeps,
74
- notFoundComponent: DefaultNotFound,
75
- staticData: createRouteStaticData({
76
- modernRouteId: rootLikeRoute?.id,
77
- modernRouteAction: rootLikeRoute?.action,
78
- modernRouteHandle: rootLikeRoute ? mergeModernRouteHandle(rootLikeRoute) : void 0,
79
- modernRouteHasAction: rootLikeRoute?.hasAction || Boolean(rootLikeRoute?.action),
80
- modernRouteHasClientLoader: rootLikeRoute?.hasClientLoader || void 0 !== rootLikeRoute?.clientData,
81
- modernRouteHasLoader: rootLikeRoute?.hasLoader || 'function' == typeof rootLikeRoute?.loader,
82
- modernRouteIsClientComponent: rootLikeRoute?.isClientComponent,
83
- modernRouteLoader: rootLikeRoute?.loader,
84
- modernRouteShouldRevalidate: rootShouldRevalidate
85
- }),
86
- loader: rootLikeRoute ? wrapRouteObjectLoader(rootLikeRoute, rootRevalidationState, options) : void 0
55
+ ...root ? createRouteOptions(root, options) : {},
56
+ notFoundComponent: DefaultNotFound
87
57
  };
88
- if (rootShouldReload) rootRouteOptions.shouldReload = rootShouldReload;
89
- if (rootLikeRoute?.inValidSSRRoute) rootRouteOptions.ssr = false;
90
58
  const rootRoute = createTanstackRootRoute(rootRouteOptions);
91
- if (rootComponent) rootRoute.options.component = withModernRouteMatchContext(rootComponent, rootRouteId);
92
- const topLevel = rootLikeRoute ? [
93
- ...rootLikeRoute.children || [],
94
- ...routes.filter((route)=>route !== rootLikeRoute)
95
- ] : routes;
96
- const childRoutes = topLevel.map((routeObject, index)=>createRouteFromRouteObject({
97
- options,
98
- parent: rootRoute,
99
- pathlessFallbackId: `pathless-${index}`,
100
- routeObject
101
- }));
102
- rootRoute.addChildren(childRoutes);
59
+ if (rootRouteOptions.component) rootRoute.options.component = withModernRouteMatchContext(rootRouteOptions.component, rootRouteId);
60
+ rootRoute.addChildren(children.map((child)=>createRouteFromDescriptor(child, rootRoute, options)));
103
61
  return rootRoute;
104
62
  }
105
63
  function getModernRouteIdsFromMatches(router) {
@@ -1,5 +1,5 @@
1
1
  import "node:module";
2
- import { getLoaderHref, handleModernLoaderError, handleModernLoaderResult, mapSplatParamsForModernLoader } from "../loaderBridge.mjs";
2
+ import { getLoaderHref, getLoaderSignal, handleModernLoaderError, handleModernLoaderResult, mapSplatParamsForModernLoader } from "../loaderBridge.mjs";
3
3
  import { isTanstackRscPayloadNavigationEnabled, loadTanstackRscRouteData } from "../rsc/payloadRouter.mjs";
4
4
  function isModernDeferredData(value) {
5
5
  if (!value || 'object' != typeof value) return false;
@@ -50,7 +50,7 @@ function wrapRouteObjectLoader(route, revalidationState, options = {}) {
50
50
  if ('function' == typeof modernRoute.lazyImport) try {
51
51
  await modernRoute.lazyImport();
52
52
  } catch {}
53
- const signal = ctx?.abortController?.signal || ctx?.signal || new AbortController().signal;
53
+ const signal = getLoaderSignal(ctx);
54
54
  const baseRequest = ctx?.context?.request instanceof Request ? ctx.context.request : void 0;
55
55
  const href = getLoaderHref(ctx);
56
56
  const request = void 0 !== baseRequest ? new Request(baseRequest, {
@@ -11,7 +11,4 @@ function toTanstackPath(pathname) {
11
11
  return segment;
12
12
  }).join('/');
13
13
  }
14
- function isRouteObjectPathlessLayout(route) {
15
- return !route.path && !route.index;
16
- }
17
- export { isRouteObjectPathlessLayout, toTanstackPath };
14
+ export { toTanstackPath };
@@ -1,11 +1,4 @@
1
1
  import "node:module";
2
- async function waitForRouterSerialization(tanstackRouter) {
3
- const serverSsr = tanstackRouter.serverSsr;
4
- if (!serverSsr || 'function' != typeof serverSsr.onSerializationFinished || serverSsr.isSerializationFinished?.()) return;
5
- await new Promise((resolve)=>{
6
- serverSsr.onSerializationFinished?.(resolve);
7
- });
8
- }
9
2
  function htmlEscapeAttr(value) {
10
3
  return value.replace(/&/g, '&').replace(/"/g, '"');
11
4
  }
@@ -51,4 +44,4 @@ async function attachServerSsrUtils(router) {
51
44
  manifest: void 0
52
45
  });
53
46
  }
54
- export { attachServerSsrUtils, collectRouterErrors, createGetSsrHref, routerManagedTagsToHtml, waitForRouterSerialization };
47
+ export { attachServerSsrUtils, collectRouterErrors, createGetSsrHref, routerManagedTagsToHtml };
@@ -15,6 +15,7 @@ function withGlobalLayout(Component, globalApp) {
15
15
  function toTanstackRouteObject(route, globalApp) {
16
16
  if ('nested' === route.type) return {
17
17
  modernLocalisedRoute: Reflect.get(route, 'modernLocalisedRoute'),
18
+ isRoot: Reflect.get(route, 'isRoot'),
18
19
  path: route.path,
19
20
  id: route.id,
20
21
  loader: route.loader,
@@ -0,0 +1,23 @@
1
+ import "node:module";
2
+ import { toTanstackPath } from "../runtime/routeTree/paths.mjs";
3
+ function describeRouteTree(routes) {
4
+ const root = routes.find((route)=>true === route.isRoot || '/' === route.path && true !== route.index);
5
+ const describe = (route, index)=>({
6
+ source: route,
7
+ location: 0 === (route.path ?? '').length && true !== route.index ? {
8
+ id: route.id || route.file || `pathless-${index}`
9
+ } : {
10
+ path: true === route.index ? '/' : toTanstackPath(route.path || '')
11
+ },
12
+ hasSplat: Boolean(route.path?.includes('*')),
13
+ children: (route.children ?? []).map(describe)
14
+ });
15
+ return {
16
+ root,
17
+ children: (void 0 !== root ? [
18
+ ...root.children ?? [],
19
+ ...routes.filter((route)=>route !== root)
20
+ ] : routes).map(describe)
21
+ };
22
+ }
23
+ export { describeRouteTree };
@@ -11,8 +11,6 @@ export declare function pickRouteSearchContractModules(route: NestedRouteForCli
11
11
  validateSearchPath: string | null;
12
12
  loaderDepsPath: string | null;
13
13
  };
14
- export declare function isPathlessLayout(route: NestedRouteForCli | PageRoute): boolean;
15
- export declare function isIndexRoute(route: NestedRouteForCli | PageRoute): boolean;
16
14
  export declare function createRouteStaticDataSnippet(opts: {
17
15
  modernRouteId?: string;
18
16
  loaderName?: string | null;
@@ -11,4 +11,4 @@ export type RouterLifecycleContext = NativeRouterLifecycleContext & {
11
11
  cleanup?: () => void | Promise<void>;
12
12
  serverSnapshot?: InternalRouterServerSnapshot;
13
13
  };
14
- export { applyRouterRuntimeState, applyRouterServerPrepareResult, createRouterRuntimeState, createRouterServerSnapshot, getRouterRuntimeState, getRouterServerSnapshot, type RouterLifecyclePhase, } from '@modern-js/runtime-extensions/router-state';
14
+ export { applyRouterRuntimeState, applyRouterServerPrepareResult, createRouterServerSnapshot, getRouterRuntimeState, getRouterServerSnapshot, type RouterLifecyclePhase, } from '@modern-js/runtime-extensions/router-state';
@@ -39,6 +39,7 @@ type LoaderLikeContext = {
39
39
  };
40
40
  params?: Record<string, string>;
41
41
  };
42
+ export declare function getLoaderSignal(ctx: LoaderLikeContext | undefined): AbortSignal;
42
43
  export declare function getLoaderHref(ctx: LoaderLikeContext | undefined): string;
43
44
  export declare function handleModernLoaderResult<LoaderResult>(result: LoaderResult): LoaderResult;
44
45
  export declare function handleModernLoaderError(err: unknown): never;
@@ -0,0 +1,4 @@
1
+ import type { RouterNavigationCapability } from '@modern-js/runtime-extensions/router-state';
2
+ import type { AnyRouter } from '@tanstack/react-router';
3
+ /** Native TanStack navigation, exposed through the provider contract. */
4
+ export declare function createTanstackNavigation(router: AnyRouter): RouterNavigationCapability;
@@ -1,3 +1 @@
1
- import type { RouteObject } from '@modern-js/runtime-utils/router';
2
1
  export declare function toTanstackPath(pathname: string): string;
3
- export declare function isRouteObjectPathlessLayout(route: RouteObject): boolean;
@@ -1,6 +1,5 @@
1
1
  import type { AnyRouter } from '@tanstack/react-router';
2
2
  import type { TanstackRouterWithServerSsr } from './ssrTypes.js';
3
- export declare function waitForRouterSerialization(tanstackRouter: TanstackRouterWithServerSsr): Promise<void>;
4
3
  export declare function routerManagedTagsToHtml(tags: unknown): string[];
5
4
  export declare function createGetSsrHref(request: Request): string;
6
5
  export declare function collectRouterErrors(tanstackRouter: AnyRouter): Record<string, unknown> | undefined;
@@ -28,13 +28,6 @@ type RouterRouteWithOptions = {
28
28
  };
29
29
  export type TanstackRouterWithServerSsr = AnyRouter & {
30
30
  routesById?: Record<string, RouterRouteWithOptions>;
31
- serverSsr?: {
32
- cleanup?: () => void;
33
- dehydrate?: () => Promise<void> | void;
34
- isSerializationFinished?: () => boolean;
35
- onSerializationFinished?: (listener: () => void) => void;
36
- takeBufferedScripts?: () => unknown;
37
- };
38
31
  state: AnyRouter['state'] & {
39
32
  matches?: unknown;
40
33
  };
@@ -0,0 +1,26 @@
1
+ type RouteShape = {
2
+ id?: string;
3
+ file?: string;
4
+ path?: string;
5
+ index?: boolean;
6
+ isRoot?: boolean;
7
+ children?: RouteShape[];
8
+ };
9
+ /** Browser-safe structure shared by the executable tree and concrete TS emitter. */
10
+ export type RouteDescriptor<T extends RouteShape> = {
11
+ source: T;
12
+ location: {
13
+ id: string;
14
+ path?: never;
15
+ } | {
16
+ path: string;
17
+ id?: never;
18
+ };
19
+ hasSplat: boolean;
20
+ children: RouteDescriptor<T>[];
21
+ };
22
+ export declare function describeRouteTree<T extends RouteShape>(routes: T[]): {
23
+ root: T | undefined;
24
+ children: RouteDescriptor<T>[];
25
+ };
26
+ export {};