@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.
- package/dist/cjs/cli/artifacts.js +2 -1
- package/dist/cjs/cli/tanstackTypes/canonicalRoutes.js +7 -7
- package/dist/cjs/cli/tanstackTypes/shared.js +0 -14
- package/dist/cjs/cli/tanstackTypes/source.js +28 -63
- package/dist/cjs/runtime/lifecycle.js +0 -3
- package/dist/cjs/runtime/loaderBridge.js +10 -4
- package/dist/cjs/runtime/navigation.js +102 -0
- package/dist/cjs/runtime/plugin.js +6 -1
- package/dist/cjs/runtime/plugin.node.js +81 -63
- package/dist/cjs/runtime/routeTree/construction.js +19 -61
- package/dist/cjs/runtime/routeTree/loaders.js +1 -1
- package/dist/cjs/runtime/routeTree/paths.js +0 -6
- package/dist/cjs/runtime/ssrManagedTags.js +2 -12
- package/dist/cjs/runtime/utils.js +1 -0
- package/dist/cjs/shared/routeDescriptor.js +60 -0
- package/dist/esm/cli/artifacts.mjs +2 -1
- package/dist/esm/cli/index.mjs +1 -7
- package/dist/esm/cli/tanstackTypes/canonicalRoutes.mjs +7 -7
- package/dist/esm/cli/tanstackTypes/shared.mjs +1 -9
- package/dist/esm/cli/tanstackTypes/source.mjs +29 -64
- package/dist/esm/runtime/lifecycle.mjs +1 -1
- package/dist/esm/runtime/loaderBridge.mjs +8 -5
- package/dist/esm/runtime/navigation.mjs +64 -0
- package/dist/esm/runtime/plugin.mjs +6 -1
- package/dist/esm/runtime/plugin.node.mjs +83 -65
- package/dist/esm/runtime/routeTree/construction.mjs +19 -61
- package/dist/esm/runtime/routeTree/loaders.mjs +2 -2
- package/dist/esm/runtime/routeTree/paths.mjs +1 -4
- package/dist/esm/runtime/ssrManagedTags.mjs +1 -8
- package/dist/esm/runtime/utils.mjs +1 -0
- package/dist/esm/shared/routeDescriptor.mjs +22 -0
- package/dist/esm-node/cli/artifacts.mjs +2 -1
- package/dist/esm-node/cli/index.mjs +1 -7
- package/dist/esm-node/cli/tanstackTypes/canonicalRoutes.mjs +7 -7
- package/dist/esm-node/cli/tanstackTypes/shared.mjs +1 -9
- package/dist/esm-node/cli/tanstackTypes/source.mjs +29 -64
- package/dist/esm-node/runtime/lifecycle.mjs +1 -1
- package/dist/esm-node/runtime/loaderBridge.mjs +8 -5
- package/dist/esm-node/runtime/navigation.mjs +65 -0
- package/dist/esm-node/runtime/plugin.mjs +6 -1
- package/dist/esm-node/runtime/plugin.node.mjs +83 -65
- package/dist/esm-node/runtime/routeTree/construction.mjs +19 -61
- package/dist/esm-node/runtime/routeTree/loaders.mjs +2 -2
- package/dist/esm-node/runtime/routeTree/paths.mjs +1 -4
- package/dist/esm-node/runtime/ssrManagedTags.mjs +1 -8
- package/dist/esm-node/runtime/utils.mjs +1 -0
- package/dist/esm-node/shared/routeDescriptor.mjs +23 -0
- package/dist/types/cli/tanstackTypes/shared.d.ts +0 -2
- package/dist/types/runtime/lifecycle.d.ts +1 -1
- package/dist/types/runtime/loaderBridge.d.ts +1 -0
- package/dist/types/runtime/navigation.d.ts +4 -0
- package/dist/types/runtime/routeTree/paths.d.ts +0 -2
- package/dist/types/runtime/ssrManagedTags.d.ts +0 -1
- package/dist/types/runtime/ssrTypes.d.ts +0 -7
- package/dist/types/shared/routeDescriptor.d.ts +26 -0
- package/package.json +21 -21
- package/src/cli/artifacts.ts +6 -1
- package/src/cli/tanstackTypes/canonicalRoutes.ts +17 -12
- package/src/cli/tanstackTypes/shared.ts +0 -14
- package/src/cli/tanstackTypes/source.ts +43 -119
- package/src/runtime/lifecycle.ts +0 -1
- package/src/runtime/loaderBridge.ts +9 -9
- package/src/runtime/navigation.ts +78 -0
- package/src/runtime/plugin.node.tsx +111 -91
- package/src/runtime/plugin.tsx +6 -0
- package/src/runtime/routeTree/construction.ts +32 -112
- package/src/runtime/routeTree/loaders.ts +2 -4
- package/src/runtime/routeTree/paths.ts +0 -6
- package/src/runtime/ssrManagedTags.ts +0 -17
- package/src/runtime/ssrTypes.ts +0 -7
- package/src/runtime/utils.tsx +1 -0
- package/src/shared/routeDescriptor.ts +46 -0
- package/tests/router/clientNavigation.ts +13 -0
- package/tests/router/generateRouteArtifacts.test.ts +36 -2
- package/tests/router/localisedIdentity.test.tsx +7 -2
- package/tests/router/prefetchLink.test.tsx +29 -0
- package/tests/router/routeHooks.test.ts +2 -1
- package/tests/router/serverPlugin.test.ts +150 -0
- package/tests/router/tanstackTypes.test.ts +121 -2
- package/dist/esm/rslib-runtime~1.mjs +0 -18
- package/dist/esm-node/rslib-runtime~0.mjs +0 -19
|
@@ -8,13 +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 {
|
|
11
|
+
import { applyRouterRuntimeState, applyRouterServerPrepareResult, getRouterRuntimeState, getRouterServerSnapshot } from "./lifecycle.mjs";
|
|
12
|
+
import { createTanstackNavigation } from "./navigation.mjs";
|
|
12
13
|
import { createTanstackRouteObjects, getTanstackRouteConfig, joinBasename } from "./pluginShared.mjs";
|
|
13
14
|
import { Link } from "./prefetchLink.mjs";
|
|
14
15
|
import { createRouteTreeFromRouteObjects, getModernRouteIdsFromMatches } from "./routeTree/index.mjs";
|
|
15
16
|
import { createTanstackRscServerPayload, handleTanstackRscRedirect } from "./rsc/payloadRouter.mjs";
|
|
16
17
|
import { getTanstackRscRouter, setTanstackRscRouter, setTanstackRscServerPayload } from "./rsc/payloadStorage.mjs";
|
|
17
|
-
import { attachServerSsrUtils, collectRouterErrors, createGetSsrHref, routerManagedTagsToHtml
|
|
18
|
+
import { attachServerSsrUtils, collectRouterErrors, createGetSsrHref, routerManagedTagsToHtml } from "./ssrManagedTags.mjs";
|
|
18
19
|
import { preloadMatchedRouteComponents } from "./ssrPreload.mjs";
|
|
19
20
|
import { getModernTanstackRouterFastDefaults } from "./types.mjs";
|
|
20
21
|
const tanstackRouterPlugin = (userConfig = {})=>{
|
|
@@ -87,76 +88,93 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
87
88
|
});
|
|
88
89
|
const serverRouter = tanstackRouter;
|
|
89
90
|
if (enableRsc) setTanstackRscRouter(serverRouter);
|
|
90
|
-
|
|
91
|
-
|
|
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
|
+
});
|
|
92
110
|
try {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
const cost = end();
|
|
98
|
-
context.ssrContext?.onTiming?.(LOADER_REPORTER_NAME, cost);
|
|
99
|
-
}
|
|
100
|
-
const serverLoadResult = serverRouter._serverResult;
|
|
101
|
-
if (!serverLoadResult) {
|
|
111
|
+
rawRequest.signal.throwIfAborted();
|
|
112
|
+
await attachServerSsrUtils(serverRouter);
|
|
113
|
+
rawRequest.signal.throwIfAborted();
|
|
114
|
+
const end = time();
|
|
102
115
|
try {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
if (isRSCNavigation) await waitForRouterSerialization(serverRouter);
|
|
127
|
-
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, {
|
|
128
139
|
omitClientLoaderData: isRSCNavigation
|
|
129
140
|
}));
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
statusCode: serverLoadResult.status,
|
|
138
|
-
errors: routerErrors,
|
|
139
|
-
matchedRouteIds,
|
|
140
|
-
hydrationScripts
|
|
141
|
-
});
|
|
142
|
-
const runtimeContext = applyRouterServerPrepareResult(context, {
|
|
143
|
-
snapshot: routerServerSnapshot,
|
|
144
|
-
cleanup: ()=>serverRouter.serverSsr?.cleanup?.(),
|
|
145
|
-
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 = {
|
|
146
148
|
framework: 'tanstack',
|
|
147
149
|
basename: _basename,
|
|
148
|
-
|
|
149
|
-
|
|
150
|
+
statusCode: serverLoadResult.status,
|
|
151
|
+
errors: routerErrors,
|
|
150
152
|
matchedRouteIds,
|
|
151
|
-
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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
|
+
}
|
|
160
178
|
});
|
|
161
179
|
api.wrapRoot((App)=>{
|
|
162
180
|
const getRouteApp = ()=>{
|
|
@@ -1,23 +1,19 @@
|
|
|
1
|
-
import { canonicaliseLocalisedRoutes } from "@modern-js/i18n-runtime-extensions";
|
|
2
1
|
import { DefaultNotFound } from "@modern-js/runtime/context";
|
|
3
2
|
import { rootRouteId } from "@tanstack/react-router";
|
|
3
|
+
import { describeRouteTree } from "../../shared/routeDescriptor.mjs";
|
|
4
4
|
import { createRouteStaticData } from "../../shared/routeStaticData.mjs";
|
|
5
5
|
import { withModernRouteMatchContext } from "../outlet.mjs";
|
|
6
6
|
import { toErrorComponent, toPendingComponent, toRouteComponent } from "./components.mjs";
|
|
7
7
|
import { createModernShouldReload, wrapRouteObjectLoader } from "./loaders.mjs";
|
|
8
|
-
import { isRouteObjectPathlessLayout, toTanstackPath } from "./paths.mjs";
|
|
9
8
|
import { mergeModernRouteHandle } from "./staticData.mjs";
|
|
10
9
|
import { createTanstackRootRoute, createTanstackRoute, wrapRouteComponentWithModernContext } from "./tanstackRoutes.mjs";
|
|
11
|
-
function
|
|
12
|
-
const { options = {}, parent, pathlessFallbackId = 'pathless', routeObject } = opts;
|
|
10
|
+
function createRouteOptions(routeObject, options) {
|
|
13
11
|
const modernRouteObject = routeObject;
|
|
14
12
|
const revalidationState = {};
|
|
15
13
|
const shouldRevalidate = modernRouteObject.shouldRevalidate;
|
|
16
14
|
const shouldReload = createModernShouldReload(shouldRevalidate, revalidationState);
|
|
17
|
-
const stableFallbackId = routeObject.id || modernRouteObject.file || pathlessFallbackId;
|
|
18
15
|
const component = toRouteComponent(routeObject);
|
|
19
16
|
const base = {
|
|
20
|
-
getParentRoute: ()=>parent,
|
|
21
17
|
component,
|
|
22
18
|
pendingComponent: toPendingComponent(routeObject),
|
|
23
19
|
errorComponent: toErrorComponent(routeObject),
|
|
@@ -38,67 +34,29 @@ function createRouteFromRouteObject(opts) {
|
|
|
38
34
|
};
|
|
39
35
|
if (modernRouteObject.inValidSSRRoute) base.ssr = false;
|
|
40
36
|
if (shouldReload) base.shouldReload = shouldReload;
|
|
41
|
-
|
|
42
|
-
else base.path = routeObject.index ? '/' : toTanstackPath(routeObject.path || '');
|
|
43
|
-
const route = createTanstackRoute(base);
|
|
44
|
-
wrapRouteComponentWithModernContext(route, component, routeObject.id);
|
|
45
|
-
const children = routeObject.children;
|
|
46
|
-
if (children && children.length > 0) {
|
|
47
|
-
const childRoutes = children.map((child, index)=>createRouteFromRouteObject({
|
|
48
|
-
options,
|
|
49
|
-
parent: route,
|
|
50
|
-
pathlessFallbackId: `pathless-${index}`,
|
|
51
|
-
routeObject: child
|
|
52
|
-
}));
|
|
53
|
-
route.addChildren(childRoutes);
|
|
54
|
-
}
|
|
55
|
-
return route;
|
|
37
|
+
return base;
|
|
56
38
|
}
|
|
57
|
-
function
|
|
58
|
-
|
|
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;
|
|
59
50
|
}
|
|
60
51
|
function createRouteTreeFromRouteObjects(routes, options = {}) {
|
|
61
|
-
|
|
62
|
-
const rootLikeRoute = getRootLikeRouteObject(routes);
|
|
63
|
-
const rootRevalidationState = {};
|
|
64
|
-
const rootShouldRevalidate = rootLikeRoute?.shouldRevalidate;
|
|
65
|
-
const rootShouldReload = createModernShouldReload(rootShouldRevalidate, rootRevalidationState);
|
|
66
|
-
const rootComponent = rootLikeRoute ? toRouteComponent(rootLikeRoute) : void 0;
|
|
52
|
+
const { root, children } = describeRouteTree(routes);
|
|
67
53
|
const rootRouteOptions = {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
errorComponent: rootLikeRoute ? toErrorComponent(rootLikeRoute) : void 0,
|
|
71
|
-
validateSearch: rootLikeRoute?.validateSearch,
|
|
72
|
-
loaderDeps: rootLikeRoute?.loaderDeps,
|
|
73
|
-
notFoundComponent: DefaultNotFound,
|
|
74
|
-
staticData: createRouteStaticData({
|
|
75
|
-
modernRouteId: rootLikeRoute?.id,
|
|
76
|
-
modernRouteAction: rootLikeRoute?.action,
|
|
77
|
-
modernRouteHandle: rootLikeRoute ? mergeModernRouteHandle(rootLikeRoute) : void 0,
|
|
78
|
-
modernRouteHasAction: rootLikeRoute?.hasAction || Boolean(rootLikeRoute?.action),
|
|
79
|
-
modernRouteHasClientLoader: rootLikeRoute?.hasClientLoader || void 0 !== rootLikeRoute?.clientData,
|
|
80
|
-
modernRouteHasLoader: rootLikeRoute?.hasLoader || 'function' == typeof rootLikeRoute?.loader,
|
|
81
|
-
modernRouteIsClientComponent: rootLikeRoute?.isClientComponent,
|
|
82
|
-
modernRouteLoader: rootLikeRoute?.loader,
|
|
83
|
-
modernRouteShouldRevalidate: rootShouldRevalidate
|
|
84
|
-
}),
|
|
85
|
-
loader: rootLikeRoute ? wrapRouteObjectLoader(rootLikeRoute, rootRevalidationState, options) : void 0
|
|
54
|
+
...root ? createRouteOptions(root, options) : {},
|
|
55
|
+
notFoundComponent: DefaultNotFound
|
|
86
56
|
};
|
|
87
|
-
if (rootShouldReload) rootRouteOptions.shouldReload = rootShouldReload;
|
|
88
|
-
if (rootLikeRoute?.inValidSSRRoute) rootRouteOptions.ssr = false;
|
|
89
57
|
const rootRoute = createTanstackRootRoute(rootRouteOptions);
|
|
90
|
-
if (
|
|
91
|
-
|
|
92
|
-
...rootLikeRoute.children || [],
|
|
93
|
-
...routes.filter((route)=>route !== rootLikeRoute)
|
|
94
|
-
] : routes;
|
|
95
|
-
const childRoutes = topLevel.map((routeObject, index)=>createRouteFromRouteObject({
|
|
96
|
-
options,
|
|
97
|
-
parent: rootRoute,
|
|
98
|
-
pathlessFallbackId: `pathless-${index}`,
|
|
99
|
-
routeObject
|
|
100
|
-
}));
|
|
101
|
-
rootRoute.addChildren(childRoutes);
|
|
58
|
+
if (rootRouteOptions.component) rootRoute.options.component = withModernRouteMatchContext(rootRouteOptions.component, rootRouteId);
|
|
59
|
+
rootRoute.addChildren(children.map((child)=>createRouteFromDescriptor(child, rootRoute, options)));
|
|
102
60
|
return rootRoute;
|
|
103
61
|
}
|
|
104
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
|
|
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, {
|
|
@@ -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
|
|
46
|
+
export { attachServerSsrUtils, collectRouterErrors, createGetSsrHref, routerManagedTagsToHtml };
|
|
@@ -14,6 +14,7 @@ function withGlobalLayout(Component, globalApp) {
|
|
|
14
14
|
function toTanstackRouteObject(route, globalApp) {
|
|
15
15
|
if ('nested' === route.type) return {
|
|
16
16
|
modernLocalisedRoute: Reflect.get(route, 'modernLocalisedRoute'),
|
|
17
|
+
isRoot: Reflect.get(route, 'isRoot'),
|
|
17
18
|
path: route.path,
|
|
18
19
|
id: route.id,
|
|
19
20
|
loader: route.loader,
|
|
@@ -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 };
|
|
@@ -96,9 +96,10 @@ async function generateTanstackRouteArtifacts(opts) {
|
|
|
96
96
|
version: opts.version || process.env.MODERN_JS_VERSION || '0.0.0-routes-generate',
|
|
97
97
|
internalPlugins: utils.INTERNAL_RUNTIME_PLUGINS
|
|
98
98
|
});
|
|
99
|
-
await cli.init({
|
|
99
|
+
const { appContext } = await cli.init({
|
|
100
100
|
...runOptions,
|
|
101
101
|
command: 'build'
|
|
102
102
|
});
|
|
103
|
+
await appContext.hooks.onBeforeExit.call();
|
|
103
104
|
}
|
|
104
105
|
export { generateTanstackRouteArtifacts, writeTanstackRegisterFile, writeTanstackRouterTypesForEntries };
|
|
@@ -3,24 +3,18 @@ import node_path from "node:path";
|
|
|
3
3
|
import { NESTED_ROUTE_SPEC_FILE, filterRoutesForServer } from "@modern-js/utils";
|
|
4
4
|
import { generateTanstackRouteArtifacts, 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 =
|
|
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;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import "node:module";
|
|
2
|
+
import { describeRouteTree } from "../../shared/routeDescriptor.mjs";
|
|
2
3
|
import { toTanstackPath } from "./shared.mjs";
|
|
3
4
|
const LOCALE_PARAM_SEGMENTS = new Set([
|
|
4
5
|
':lang',
|
|
@@ -45,11 +46,13 @@ function collectCanonicalRoutesForEntry(routes, options = {}) {
|
|
|
45
46
|
const key = toTanstackPath(normalized);
|
|
46
47
|
if (!canonicalParams.has(key)) canonicalParams.set(key, paramsTypeForCanonicalPath(normalized));
|
|
47
48
|
};
|
|
48
|
-
const visit = (
|
|
49
|
+
const visit = (descriptor, parentPath)=>{
|
|
50
|
+
const { source: route, children } = descriptor;
|
|
49
51
|
let currentPath = parentPath;
|
|
50
|
-
|
|
52
|
+
const canonicalPath = route.modernLocalisedRoute?.canonicalPath ?? route.modernCanonicalPath;
|
|
53
|
+
if ('string' == typeof canonicalPath) {
|
|
51
54
|
hasI18nSurface = true;
|
|
52
|
-
currentPath = normalizeJoined(
|
|
55
|
+
currentPath = canonicalPath ? normalizeJoined(canonicalPath) : '';
|
|
53
56
|
} else if ('string' == typeof route.path && route.path.length > 0) {
|
|
54
57
|
const segments = route.path.replace(/\[(.+?)\]/g, ':$1').split('/').filter(Boolean);
|
|
55
58
|
if (localeParamHeuristic && '' === parentPath && LOCALE_PARAM_SEGMENTS.has(segments[0])) {
|
|
@@ -58,16 +61,13 @@ function collectCanonicalRoutesForEntry(routes, options = {}) {
|
|
|
58
61
|
}
|
|
59
62
|
currentPath = segments.length ? normalizeJoined(`${parentPath}/${segments.join('/')}`) : parentPath;
|
|
60
63
|
}
|
|
61
|
-
const children = route.children;
|
|
62
64
|
if (children && children.length > 0) {
|
|
63
65
|
for (const child of children)visit(child, currentPath);
|
|
64
66
|
return;
|
|
65
67
|
}
|
|
66
68
|
record(currentPath || '/');
|
|
67
69
|
};
|
|
68
|
-
const
|
|
69
|
-
const topLevel = rootModern ? rootModern.children ?? [] : routes;
|
|
70
|
-
for (const route of topLevel)visit(route, '');
|
|
70
|
+
for (const route of describeRouteTree(routes).children)visit(route, '');
|
|
71
71
|
if (!hasI18nSurface || 0 === canonicalParams.size) return null;
|
|
72
72
|
return Object.fromEntries([
|
|
73
73
|
...canonicalParams.entries()
|
|
@@ -43,14 +43,6 @@ function pickRouteSearchContractModules(route) {
|
|
|
43
43
|
loaderDepsPath: 'string' == typeof loaderDepsPath ? loaderDepsPath : null
|
|
44
44
|
};
|
|
45
45
|
}
|
|
46
|
-
function isPathlessLayout(route) {
|
|
47
|
-
const extras = route;
|
|
48
|
-
return 'nested' === extras.type && 'boolean' != typeof extras.index && void 0 === extras.path;
|
|
49
|
-
}
|
|
50
|
-
function isIndexRoute(route) {
|
|
51
|
-
const extras = route;
|
|
52
|
-
return 'nested' === extras.type && Boolean(extras.index);
|
|
53
|
-
}
|
|
54
46
|
function createRouteStaticDataSnippet(opts) {
|
|
55
47
|
const staticData = createRouteStaticData({
|
|
56
48
|
modernRouteId: opts.modernRouteId && quote(opts.modernRouteId),
|
|
@@ -61,4 +53,4 @@ function createRouteStaticDataSnippet(opts) {
|
|
|
61
53
|
return entries.length > 0 ? `staticData: createRouteStaticData({\n ${entries.map(([key, value])=>`${key}: ${value},`).join('\n ')}\n }),` : null;
|
|
62
54
|
}
|
|
63
55
|
export { toTanstackPath } from "../../runtime/routeTree/paths.mjs";
|
|
64
|
-
export { createRouteStaticDataSnippet,
|
|
56
|
+
export { createRouteStaticDataSnippet, normalizeRelativeImport, pickModernLoaderModule, pickRouteSearchContractModules, quote, resolveFileNoExt };
|
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
import "node:module";
|
|
2
|
-
import { canonicaliseLocalisedRoutes } from "@modern-js/i18n-runtime-extensions";
|
|
3
2
|
import { makeLegalIdentifier } from "@modern-js/runtime/cli";
|
|
4
3
|
import { upath } from "@modern-js/utils";
|
|
5
|
-
import {
|
|
4
|
+
import { describeRouteTree } from "../../shared/routeDescriptor.mjs";
|
|
5
|
+
import { createRouteStaticDataSnippet, normalizeRelativeImport, pickModernLoaderModule, pickRouteSearchContractModules, quote, resolveFileNoExt } from "./shared.mjs";
|
|
6
6
|
async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
7
|
-
const { appContext, entryName, generatedDirName = 'modern-tanstack', routes
|
|
8
|
-
const routes = canonicaliseLocalisedRoutes(rawRoutes);
|
|
7
|
+
const { appContext, entryName, generatedDirName = 'modern-tanstack', routes } = opts;
|
|
9
8
|
const outDir = upath.join(appContext.srcDirectory, generatedDirName, entryName);
|
|
10
|
-
const rootModern = routes
|
|
11
|
-
const extras = r;
|
|
12
|
-
return r && 'nested' === extras.type && extras.isRoot;
|
|
13
|
-
});
|
|
14
|
-
const rootExtras = rootModern;
|
|
15
|
-
const topLevel = rootModern ? rootExtras?.children || [] : routes;
|
|
9
|
+
const { root: rootModern, children: topLevel } = describeRouteTree(routes);
|
|
16
10
|
const imports = [];
|
|
17
11
|
const statements = [];
|
|
18
12
|
const loaderImportMap = new Map();
|
|
@@ -29,9 +23,8 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
|
29
23
|
let pendingImportName = componentImportMap.get(componentPath);
|
|
30
24
|
if (!pendingImportName) {
|
|
31
25
|
pendingImportName = (async ()=>{
|
|
32
|
-
const
|
|
33
|
-
if (!
|
|
34
|
-
const relImport = normalizeRelativeImport(upath.relative(outDir, resolvedNoExt));
|
|
26
|
+
const relImport = await resolveRouteImport(componentPath);
|
|
27
|
+
if (!relImport) return null;
|
|
35
28
|
const componentName = `component_${componentIndex++}`;
|
|
36
29
|
imports.push(`import ${componentName} from ${quote(relImport)};`);
|
|
37
30
|
return componentName;
|
|
@@ -40,14 +33,15 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
|
40
33
|
}
|
|
41
34
|
return pendingImportName;
|
|
42
35
|
};
|
|
43
|
-
const
|
|
36
|
+
const resolveRouteImport = async (aliasedNoExtPath)=>{
|
|
44
37
|
const prefix = `${appContext.internalSrcAlias}/`;
|
|
45
38
|
let absNoExt;
|
|
46
39
|
if (aliasedNoExtPath.startsWith(prefix)) {
|
|
47
40
|
const rel = aliasedNoExtPath.slice(prefix.length);
|
|
48
41
|
absNoExt = upath.join(appContext.srcDirectory, rel);
|
|
49
42
|
} else absNoExt = upath.isAbsolute(aliasedNoExtPath) ? aliasedNoExtPath : upath.join(appContext.srcDirectory, aliasedNoExtPath);
|
|
50
|
-
|
|
43
|
+
const resolvedNoExt = await resolveFileNoExt(absNoExt);
|
|
44
|
+
return resolvedNoExt ? normalizeRelativeImport(upath.relative(outDir, resolvedNoExt)) : null;
|
|
51
45
|
};
|
|
52
46
|
const getImportNamesForLoader = async (aliasedNoExtPath, inline, hasAction)=>{
|
|
53
47
|
const key = `${inline ? 'inline' : 'default'}:${hasAction ? 'action' : 'loader'}:${aliasedNoExtPath}`;
|
|
@@ -56,9 +50,8 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
|
56
50
|
loaderName: existing,
|
|
57
51
|
actionName: hasAction ? existing.replace(/^loader_/, 'action_') : null
|
|
58
52
|
};
|
|
59
|
-
const
|
|
60
|
-
if (!
|
|
61
|
-
const relImport = normalizeRelativeImport(upath.relative(outDir, resolvedNoExt));
|
|
53
|
+
const relImport = await resolveRouteImport(aliasedNoExtPath);
|
|
54
|
+
if (!relImport) return null;
|
|
62
55
|
const importName = `loader_${loaderIndex++}`;
|
|
63
56
|
const actionName = hasAction ? importName.replace(/^loader_/, 'action_') : null;
|
|
64
57
|
if (inline) {
|
|
@@ -78,9 +71,8 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
|
78
71
|
const key = `${exportName}:${aliasedNoExtPath}`;
|
|
79
72
|
const existing = searchContractImportMap.get(key);
|
|
80
73
|
if (existing) return existing;
|
|
81
|
-
const
|
|
82
|
-
if (!
|
|
83
|
-
const relImport = normalizeRelativeImport(upath.relative(outDir, resolvedNoExt));
|
|
74
|
+
const relImport = await resolveRouteImport(aliasedNoExtPath);
|
|
75
|
+
if (!relImport) return null;
|
|
84
76
|
const importName = 'validateSearch' === exportName ? `validateSearch_${validateSearchIndex++}` : `loaderDeps_${loaderDepsIndex++}`;
|
|
85
77
|
imports.push(`import { ${exportName} as ${importName} } from ${quote(relImport)};`);
|
|
86
78
|
searchContractImportMap.set(key, importName);
|
|
@@ -98,9 +90,7 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
|
98
90
|
const base = id ? makeLegalIdentifier(id) : `r_${routeIndex++}`;
|
|
99
91
|
return reserveRouteVarName(`route_${base}`);
|
|
100
92
|
};
|
|
101
|
-
const
|
|
102
|
-
const { parentVar, route } = opts;
|
|
103
|
-
const varName = createRouteVarName(route);
|
|
93
|
+
const createRouteOptions = async (route, hasSplat)=>{
|
|
104
94
|
const routeExtras = route;
|
|
105
95
|
const loaderInfo = pickModernLoaderModule(route);
|
|
106
96
|
const routeAction = routeExtras.action;
|
|
@@ -110,20 +100,9 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
|
110
100
|
const searchContractInfo = pickRouteSearchContractModules(route);
|
|
111
101
|
const validateSearchName = searchContractInfo.validateSearchPath ? await getImportNameForSearchContract(searchContractInfo.validateSearchPath, 'validateSearch') : null;
|
|
112
102
|
const loaderDepsName = searchContractInfo.loaderDepsPath ? await getImportNameForSearchContract(searchContractInfo.loaderDepsPath, 'loaderDeps') : null;
|
|
113
|
-
const
|
|
114
|
-
const hasSplat = 'string' == typeof rawPath && rawPath.includes('*');
|
|
115
|
-
const routeOpts = [
|
|
116
|
-
`getParentRoute: () => ${parentVar},`
|
|
117
|
-
];
|
|
103
|
+
const routeOpts = [];
|
|
118
104
|
const componentName = await getImportNameForComponent(routeExtras._component);
|
|
119
105
|
if (componentName) routeOpts.push(`component: ${componentName},`);
|
|
120
|
-
if (isPathlessLayout(route)) {
|
|
121
|
-
const id = routeExtras.id;
|
|
122
|
-
routeOpts.push(`id: ${quote(id || 'pathless')},`);
|
|
123
|
-
} else {
|
|
124
|
-
const p = isIndexRoute(route) ? '/' : toTanstackPath(rawPath || '');
|
|
125
|
-
routeOpts.push(`path: ${quote(p)},`);
|
|
126
|
-
}
|
|
127
106
|
if (loaderName) routeOpts.push(`loader: modernLoaderToTanstack({ hasSplat: ${hasSplat} }, ${loaderName}),`);
|
|
128
107
|
if (validateSearchName) routeOpts.push(`validateSearch: ${validateSearchName},`);
|
|
129
108
|
if (loaderDepsName) routeOpts.push(`loaderDeps: ${loaderDepsName},`);
|
|
@@ -133,39 +112,29 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
|
133
112
|
actionName
|
|
134
113
|
});
|
|
135
114
|
if (staticDataSnippet) routeOpts.push(staticDataSnippet);
|
|
136
|
-
|
|
115
|
+
return routeOpts;
|
|
116
|
+
};
|
|
117
|
+
const buildRoute = async (descriptor, parentVar)=>{
|
|
118
|
+
const { source: route, location, hasSplat, children } = descriptor;
|
|
119
|
+
const varName = createRouteVarName(route);
|
|
120
|
+
const routeOpts = [
|
|
121
|
+
`getParentRoute: () => ${parentVar},`,
|
|
122
|
+
...Object.entries(location).map(([key, value])=>`${key}: ${quote(value)},`),
|
|
123
|
+
...await createRouteOptions(route, hasSplat)
|
|
124
|
+
];
|
|
137
125
|
const hasChildren = Boolean(children && children.length > 0);
|
|
138
126
|
const routeCtorVarName = hasChildren ? reserveRouteVarName(`${varName}__base`) : varName;
|
|
139
127
|
statements.push(`const ${routeCtorVarName} = createRoute({\n ${routeOpts.join('\n ')}\n});`);
|
|
140
128
|
if (children && children.length > 0) {
|
|
141
129
|
const childVars = [];
|
|
142
|
-
for (const child of children)childVars.push(await buildRoute(
|
|
143
|
-
parentVar: routeCtorVarName,
|
|
144
|
-
route: child
|
|
145
|
-
}));
|
|
130
|
+
for (const child of children)childVars.push(await buildRoute(child, routeCtorVarName));
|
|
146
131
|
statements.push(`const ${varName} = ${routeCtorVarName}.addChildren([${childVars.join(', ')}]);`);
|
|
147
132
|
}
|
|
148
133
|
return varName;
|
|
149
134
|
};
|
|
150
|
-
const rootLoaderInfo = rootModern ? pickModernLoaderModule(rootModern) : null;
|
|
151
|
-
const rootAction = rootExtras?.action;
|
|
152
|
-
const rootLoaderImports = rootLoaderInfo?.loaderPath ? await getImportNamesForLoader(rootLoaderInfo.loaderPath, rootLoaderInfo.inline, Boolean(rootLoaderInfo.inline && rootAction === rootLoaderInfo.loaderPath)) : null;
|
|
153
|
-
const rootLoaderName = rootLoaderImports?.loaderName || null;
|
|
154
|
-
const rootActionName = rootLoaderImports?.actionName || null;
|
|
155
|
-
const rootSearchContractInfo = rootModern ? pickRouteSearchContractModules(rootModern) : null;
|
|
156
|
-
const rootValidateSearchName = rootSearchContractInfo?.validateSearchPath ? await getImportNameForSearchContract(rootSearchContractInfo.validateSearchPath, 'validateSearch') : null;
|
|
157
|
-
const rootLoaderDepsName = rootSearchContractInfo?.loaderDepsPath ? await getImportNameForSearchContract(rootSearchContractInfo.loaderDepsPath, 'loaderDeps') : null;
|
|
158
135
|
const topLevelVars = [];
|
|
159
|
-
for (const route of topLevel)topLevelVars.push(await buildRoute(
|
|
160
|
-
|
|
161
|
-
route
|
|
162
|
-
}));
|
|
163
|
-
const rootOpts = [];
|
|
164
|
-
const rootComponentName = await getImportNameForComponent(rootExtras?._component);
|
|
165
|
-
if (rootComponentName) rootOpts.push(`component: ${rootComponentName},`);
|
|
166
|
-
if (rootLoaderName) rootOpts.push(`loader: modernLoaderToTanstack({ hasSplat: false }, ${rootLoaderName}),`);
|
|
167
|
-
if (rootValidateSearchName) rootOpts.push(`validateSearch: ${rootValidateSearchName},`);
|
|
168
|
-
if (rootLoaderDepsName) rootOpts.push(`loaderDeps: ${rootLoaderDepsName},`);
|
|
136
|
+
for (const route of topLevel)topLevelVars.push(await buildRoute(route, 'rootRoute'));
|
|
137
|
+
const rootOpts = rootModern ? await createRouteOptions(rootModern, false) : [];
|
|
169
138
|
const routerGenTs = `// This file is auto-generated by Modern.js. Do not edit manually.
|
|
170
139
|
|
|
171
140
|
import {
|
|
@@ -182,11 +151,7 @@ ${imports.join('\n')}
|
|
|
182
151
|
|
|
183
152
|
export const rootRoute = createRootRouteWithContext<ModernRouterContext>()({
|
|
184
153
|
${rootOpts.join('\n ')}
|
|
185
|
-
|
|
186
|
-
modernRouteId: rootExtras?.id,
|
|
187
|
-
loaderName: rootLoaderName,
|
|
188
|
-
actionName: rootActionName
|
|
189
|
-
}) || ''}
|
|
154
|
+
|
|
190
155
|
});
|
|
191
156
|
|
|
192
157
|
${statements.join('\n\n')}
|