@bleedingdev/modern-js-plugin-tanstack 3.5.0-ultramodern.99 → 3.8.1-ultramodern.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/cli/index.js +10 -2
- package/dist/cjs/cli/tanstackTypes/source.js +9 -20
- package/dist/cjs/runtime/plugin.node.js +12 -5
- package/dist/cjs/runtime/pluginShared.js +3 -3
- package/dist/cjs/runtime/rsc/payloadErrors.js +2 -2
- package/dist/cjs/runtime/rsc/shared.js +1 -1
- package/dist/cjs/runtime/rsc/treeGetter.js +5 -9
- package/dist/cjs/runtime/submitAction.js +4 -5
- package/dist/esm/cli/index.mjs +10 -2
- package/dist/esm/cli/tanstackTypes/source.mjs +9 -10
- package/dist/esm/runtime/plugin.node.mjs +12 -5
- package/dist/esm/runtime/pluginShared.mjs +3 -3
- package/dist/esm/runtime/rsc/payloadErrors.mjs +1 -1
- package/dist/esm/runtime/rsc/shared.mjs +1 -1
- package/dist/esm/runtime/rsc/treeGetter.mjs +5 -9
- package/dist/esm/runtime/submitAction.mjs +4 -5
- package/dist/esm-node/cli/index.mjs +10 -2
- package/dist/esm-node/cli/tanstackTypes/source.mjs +9 -10
- package/dist/esm-node/runtime/plugin.node.mjs +12 -5
- package/dist/esm-node/runtime/pluginShared.mjs +3 -3
- package/dist/esm-node/runtime/rsc/payloadErrors.mjs +1 -1
- package/dist/esm-node/runtime/rsc/shared.mjs +1 -1
- package/dist/esm-node/runtime/rsc/treeGetter.mjs +5 -9
- package/dist/esm-node/runtime/submitAction.mjs +4 -5
- package/dist/types/runtime/clientHydration.d.ts +1 -1
- package/dist/types/runtime/ssrTypes.d.ts +0 -2
- package/package.json +27 -20
- package/rstest.config.mts +2 -0
- package/src/cli/index.ts +12 -0
- package/src/cli/tanstackTypes/canonicalRoutes.ts +0 -1
- package/src/cli/tanstackTypes/shared.ts +0 -1
- package/src/cli/tanstackTypes/source.ts +3 -4
- package/src/runtime/plugin.node.tsx +17 -11
- package/src/runtime/plugin.tsx +0 -2
- package/src/runtime/pluginShared.ts +8 -7
- package/src/runtime/rsc/payloadErrors.ts +1 -1
- package/src/runtime/rsc/shared.ts +1 -1
- package/src/runtime/rsc/treeGetter.tsx +9 -8
- package/src/runtime/ssrManagedTags.ts +0 -2
- package/src/runtime/ssrTypes.ts +0 -4
- package/src/runtime/submitAction.ts +6 -11
- package/src/types/react-server-dom-rspack.d.ts +4 -52
- package/tests/router/cli.test.ts +204 -96
- package/tests/router/clientHydration.test.tsx +140 -1
- package/tests/router/dataMutation.test.tsx +50 -9
- package/tests/router/fixtures/rscDecoderSecurityChild.cjs +162 -0
- package/tests/router/preloadRedirect.test.ts +3 -8
- package/tests/router/routeTree.test.ts +73 -19
- package/tests/router/routerCompatibility.test.ts +0 -6
- package/tests/router/rscDecoderSecurity.test.ts +113 -0
- package/tests/router/serverPlugin.test.ts +115 -0
- package/tests/router/tanstackTypes.test.ts +668 -356
- package/src/runtime/ssr-shim.d.ts +0 -10
- package/tests/castRatchet.test.ts +0 -85
- package/tests/router/fixtures/router-gen.golden.txt +0 -71
package/dist/cjs/cli/index.js
CHANGED
|
@@ -169,7 +169,11 @@ var __webpack_exports__ = {};
|
|
|
169
169
|
if (0 === tanstackEntrypoints.length) return;
|
|
170
170
|
const { handleGeneratorEntryCode } = getRuntimeRouterCli();
|
|
171
171
|
const routesByEntry = await handleGeneratorEntryCode(api, tanstackEntrypoints, {
|
|
172
|
-
entrypointsKey: ENTRYPOINTS_KEY
|
|
172
|
+
entrypointsKey: ENTRYPOINTS_KEY,
|
|
173
|
+
hydrateRscClientRoutes: true,
|
|
174
|
+
includeRouteServerLoadersInSsrEntry: false,
|
|
175
|
+
isolateRouteDataInRscLayer: true,
|
|
176
|
+
serverRoutesFileName: 'tanstack-routes.server.js'
|
|
173
177
|
});
|
|
174
178
|
await (0, external_artifacts_js_namespaceObject.writeTanstackRouterTypesForEntries)({
|
|
175
179
|
appContext: api.getAppContext(),
|
|
@@ -189,7 +193,11 @@ var __webpack_exports__ = {};
|
|
|
189
193
|
regenerate: async ({ api, entrypoints })=>{
|
|
190
194
|
const { handleGeneratorEntryCode } = getRuntimeRouterCli();
|
|
191
195
|
const routesByEntry = await handleGeneratorEntryCode(api, entrypoints, {
|
|
192
|
-
entrypointsKey: ENTRYPOINTS_KEY
|
|
196
|
+
entrypointsKey: ENTRYPOINTS_KEY,
|
|
197
|
+
hydrateRscClientRoutes: true,
|
|
198
|
+
includeRouteServerLoadersInSsrEntry: false,
|
|
199
|
+
isolateRouteDataInRscLayer: true,
|
|
200
|
+
serverRoutesFileName: 'tanstack-routes.server.js'
|
|
193
201
|
});
|
|
194
202
|
await (0, external_artifacts_js_namespaceObject.writeTanstackRouterTypesForEntries)({
|
|
195
203
|
appContext: api.getAppContext(),
|
|
@@ -1,14 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __webpack_require__ = {};
|
|
3
|
-
(()=>{
|
|
4
|
-
__webpack_require__.n = (module)=>{
|
|
5
|
-
var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
|
|
6
|
-
__webpack_require__.d(getter, {
|
|
7
|
-
a: getter
|
|
8
|
-
});
|
|
9
|
-
return getter;
|
|
10
|
-
};
|
|
11
|
-
})();
|
|
12
3
|
(()=>{
|
|
13
4
|
__webpack_require__.d = (exports1, getters, values)=>{
|
|
14
5
|
var define = (defs, kind)=>{
|
|
@@ -39,13 +30,12 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
39
30
|
__webpack_require__.d(__webpack_exports__, {
|
|
40
31
|
generateTanstackRouterTypesSourceForEntry: ()=>generateTanstackRouterTypesSourceForEntry
|
|
41
32
|
});
|
|
42
|
-
const external_node_path_namespaceObject = require("node:path");
|
|
43
|
-
var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
|
|
44
33
|
const cli_namespaceObject = require("@modern-js/runtime/cli");
|
|
34
|
+
const utils_namespaceObject = require("@modern-js/utils");
|
|
45
35
|
const external_shared_js_namespaceObject = require("./shared.js");
|
|
46
36
|
async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
47
37
|
const { appContext, entryName, generatedDirName = 'modern-tanstack', routes } = opts;
|
|
48
|
-
const outDir =
|
|
38
|
+
const outDir = utils_namespaceObject.upath.join(appContext.srcDirectory, generatedDirName, entryName);
|
|
49
39
|
const rootModern = routes.find((r)=>{
|
|
50
40
|
const extras = r;
|
|
51
41
|
return r && 'nested' === extras.type && extras.isRoot;
|
|
@@ -70,7 +60,7 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
|
70
60
|
pendingImportName = (async ()=>{
|
|
71
61
|
const resolvedNoExt = await resolveRouteModuleNoExt(componentPath);
|
|
72
62
|
if (!resolvedNoExt) return null;
|
|
73
|
-
const relImport = (0, external_shared_js_namespaceObject.normalizeRelativeImport)(
|
|
63
|
+
const relImport = (0, external_shared_js_namespaceObject.normalizeRelativeImport)(utils_namespaceObject.upath.relative(outDir, resolvedNoExt));
|
|
74
64
|
const componentName = `component_${componentIndex++}`;
|
|
75
65
|
imports.push(`import ${componentName} from ${(0, external_shared_js_namespaceObject.quote)(relImport)};`);
|
|
76
66
|
return componentName;
|
|
@@ -84,8 +74,8 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
|
84
74
|
let absNoExt;
|
|
85
75
|
if (aliasedNoExtPath.startsWith(prefix)) {
|
|
86
76
|
const rel = aliasedNoExtPath.slice(prefix.length);
|
|
87
|
-
absNoExt =
|
|
88
|
-
} else absNoExt =
|
|
77
|
+
absNoExt = utils_namespaceObject.upath.join(appContext.srcDirectory, rel);
|
|
78
|
+
} else absNoExt = utils_namespaceObject.upath.isAbsolute(aliasedNoExtPath) ? aliasedNoExtPath : utils_namespaceObject.upath.join(appContext.srcDirectory, aliasedNoExtPath);
|
|
89
79
|
return (0, external_shared_js_namespaceObject.resolveFileNoExt)(absNoExt);
|
|
90
80
|
};
|
|
91
81
|
const getImportNamesForLoader = async (aliasedNoExtPath, inline, hasAction)=>{
|
|
@@ -97,7 +87,7 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
|
97
87
|
};
|
|
98
88
|
const resolvedNoExt = await resolveRouteModuleNoExt(aliasedNoExtPath);
|
|
99
89
|
if (!resolvedNoExt) return null;
|
|
100
|
-
const relImport = (0, external_shared_js_namespaceObject.normalizeRelativeImport)(
|
|
90
|
+
const relImport = (0, external_shared_js_namespaceObject.normalizeRelativeImport)(utils_namespaceObject.upath.relative(outDir, resolvedNoExt));
|
|
101
91
|
const importName = `loader_${loaderIndex++}`;
|
|
102
92
|
const actionName = hasAction ? importName.replace(/^loader_/, 'action_') : null;
|
|
103
93
|
if (inline) {
|
|
@@ -119,7 +109,7 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
|
119
109
|
if (existing) return existing;
|
|
120
110
|
const resolvedNoExt = await resolveRouteModuleNoExt(aliasedNoExtPath);
|
|
121
111
|
if (!resolvedNoExt) return null;
|
|
122
|
-
const relImport = (0, external_shared_js_namespaceObject.normalizeRelativeImport)(
|
|
112
|
+
const relImport = (0, external_shared_js_namespaceObject.normalizeRelativeImport)(utils_namespaceObject.upath.relative(outDir, resolvedNoExt));
|
|
123
113
|
const importName = 'validateSearch' === exportName ? `validateSearch_${validateSearchIndex++}` : `loaderDeps_${loaderDepsIndex++}`;
|
|
124
114
|
imports.push(`import { ${exportName} as ${importName} } from ${(0, external_shared_js_namespaceObject.quote)(relImport)};`);
|
|
125
115
|
searchContractImportMap.set(key, importName);
|
|
@@ -214,8 +204,7 @@ import {
|
|
|
214
204
|
createRouter,
|
|
215
205
|
createRouteStaticData,
|
|
216
206
|
type ModernRouterContext,
|
|
217
|
-
modernLoaderToTanstack,
|
|
218
|
-
modernTanstackRouterFastDefaults,
|
|
207
|
+
${loaderImportMap.size > 0 ? ' modernLoaderToTanstack,\n' : ''} modernTanstackRouterFastDefaults,
|
|
219
208
|
} from '@modern-js/plugin-tanstack/runtime';
|
|
220
209
|
|
|
221
210
|
${imports.join('\n')}
|
|
@@ -239,7 +228,7 @@ export const router = createRouter({
|
|
|
239
228
|
history: createMemoryHistory({
|
|
240
229
|
initialEntries: ['/'],
|
|
241
230
|
}),
|
|
242
|
-
context: {}
|
|
231
|
+
context: {},
|
|
243
232
|
});
|
|
244
233
|
`;
|
|
245
234
|
return {
|
|
@@ -127,12 +127,19 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
127
127
|
const cost = end();
|
|
128
128
|
context.ssrContext?.onTiming?.(constants_namespaceObject.LOADER_REPORTER_NAME, cost);
|
|
129
129
|
}
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
const serverLoadResult = serverRouter._serverResult;
|
|
131
|
+
if (!serverLoadResult) {
|
|
132
132
|
try {
|
|
133
133
|
serverRouter.serverSsr?.cleanup?.();
|
|
134
134
|
} catch {}
|
|
135
|
-
|
|
135
|
+
throw new Error('TanStack Router completed an SSR load without a server result.');
|
|
136
|
+
}
|
|
137
|
+
if ('redirect' === serverLoadResult.type) {
|
|
138
|
+
const { redirect } = serverLoadResult;
|
|
139
|
+
try {
|
|
140
|
+
serverRouter.serverSsr?.cleanup?.();
|
|
141
|
+
} catch {}
|
|
142
|
+
return interrupt(isRSCNavigation ? (0, payloadRouter_js_namespaceObject.handleTanstackRscRedirect)(redirect.headers, _basename, redirect.status) : redirect);
|
|
136
143
|
}
|
|
137
144
|
const routerErrors = (0, external_ssrManagedTags_js_namespaceObject.collectRouterErrors)(tanstackRouter);
|
|
138
145
|
if (routerErrors && 'clientRender' === loaderFailureMode) {
|
|
@@ -143,7 +150,7 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
143
150
|
throw Object.values(routerErrors)[0];
|
|
144
151
|
}
|
|
145
152
|
await (0, external_ssrPreload_js_namespaceObject.preloadMatchedRouteComponents)(serverRouter);
|
|
146
|
-
context.ssrContext?.response?.status(
|
|
153
|
+
context.ssrContext?.response?.status(serverLoadResult.status);
|
|
147
154
|
await serverRouter.serverSsr?.dehydrate?.();
|
|
148
155
|
if (enableRsc) {
|
|
149
156
|
if (isRSCNavigation) await (0, external_ssrManagedTags_js_namespaceObject.waitForRouterSerialization)(serverRouter);
|
|
@@ -157,7 +164,7 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
157
164
|
const routerServerSnapshot = (0, external_lifecycle_js_namespaceObject.createRouterServerSnapshot)({
|
|
158
165
|
framework: 'tanstack',
|
|
159
166
|
basename: _basename,
|
|
160
|
-
statusCode:
|
|
167
|
+
statusCode: serverLoadResult.status,
|
|
161
168
|
errors: routerErrors,
|
|
162
169
|
matchedRouteIds,
|
|
163
170
|
hydrationScripts
|
|
@@ -58,10 +58,10 @@ function getTanstackRouteConfig(api, userConfig) {
|
|
|
58
58
|
}
|
|
59
59
|
function createTanstackRouteObjects({ hooks, routeConfig, ssrMode }) {
|
|
60
60
|
const { mergedConfig, finalRouteConfig } = routeConfig;
|
|
61
|
-
const routeObjects = mergedConfig.createRoutes ? mergedConfig.createRoutes() : (0, external_utils_js_namespaceObject.createTanstackRouteObjectsFromConfig)({
|
|
61
|
+
const routeObjects = void 0 !== mergedConfig.createRoutes ? mergedConfig.createRoutes() : (0, external_utils_js_namespaceObject.createTanstackRouteObjectsFromConfig)({
|
|
62
62
|
routesConfig: finalRouteConfig,
|
|
63
63
|
ssrMode
|
|
64
|
-
})
|
|
64
|
+
}) ?? [];
|
|
65
65
|
return hooks.modifyRoutes.call(routeObjects);
|
|
66
66
|
}
|
|
67
67
|
function joinBasename(baseUrl, basename) {
|
|
@@ -69,7 +69,7 @@ function joinBasename(baseUrl, basename) {
|
|
|
69
69
|
const normalizedBase = base.startsWith('/') ? base : `/${base}`;
|
|
70
70
|
const trimmedBase = normalizedBase.length > 1 ? normalizedBase.replace(/\/+$/g, '') : normalizedBase;
|
|
71
71
|
const trimmedBasename = basename.replace(/^\/+|\/+$/g, '');
|
|
72
|
-
if (
|
|
72
|
+
if (0 === trimmedBasename.length) return trimmedBase || '/';
|
|
73
73
|
return `${trimmedBase}/${trimmedBasename}`.replace(/\/{2,}/g, '/');
|
|
74
74
|
}
|
|
75
75
|
exports.createTanstackRouteObjects = __webpack_exports__.createTanstackRouteObjects;
|
|
@@ -34,12 +34,12 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
34
34
|
toRouteErrors: ()=>toRouteErrors,
|
|
35
35
|
toRouteLoaderData: ()=>toRouteLoaderData
|
|
36
36
|
});
|
|
37
|
-
const
|
|
37
|
+
const routerHelper_namespaceObject = require("@modern-js/runtime/routerHelper");
|
|
38
38
|
function shouldRedactServerError(status = 500) {
|
|
39
39
|
return status >= 500 && 'development' !== process.env.NODE_ENV && 'test' !== process.env.NODE_ENV;
|
|
40
40
|
}
|
|
41
41
|
function serializePayloadError(error) {
|
|
42
|
-
if ((0,
|
|
42
|
+
if ((0, routerHelper_namespaceObject.isRouteErrorResponse)(error)) {
|
|
43
43
|
if (shouldRedactServerError(error.status)) return {
|
|
44
44
|
status: error.status,
|
|
45
45
|
statusText: 'Internal Server Error',
|
|
@@ -50,7 +50,7 @@ function selectTreePath(tree, path) {
|
|
|
50
50
|
return current;
|
|
51
51
|
}
|
|
52
52
|
function renderSelectedTree(src, { getTree = src[external_symbols_js_namespaceObject.RSC_PROXY_GET_TREE], missingTreeError }) {
|
|
53
|
-
if (
|
|
53
|
+
if (void 0 === getTree) throw new Error(missingTreeError);
|
|
54
54
|
return selectTreePath(getTree(), src[external_symbols_js_namespaceObject.RSC_PROXY_PATH] || []);
|
|
55
55
|
}
|
|
56
56
|
exports.EmptyFallback = __webpack_exports__.EmptyFallback;
|
|
@@ -40,15 +40,11 @@ function loadModernRscClientRuntime() {
|
|
|
40
40
|
});
|
|
41
41
|
return modernRscClientRuntimePromise;
|
|
42
42
|
}
|
|
43
|
-
|
|
44
|
-
if ("u" < typeof window)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const runtime = await loadModernRscClientRuntime();
|
|
49
|
-
return runtime.createFromReadableStream(stream, {
|
|
50
|
-
callServer: runtime.callServer
|
|
51
|
-
});
|
|
43
|
+
function createFromFlightStream(stream) {
|
|
44
|
+
if ("u" < typeof window) return import("react-server-dom-rspack/client.edge").then((runtime)=>runtime.createFromReadableStream(stream));
|
|
45
|
+
return loadModernRscClientRuntime().then((runtime)=>runtime.createFromReadableStream(stream, {
|
|
46
|
+
callServer: runtime.callServer
|
|
47
|
+
}));
|
|
52
48
|
}
|
|
53
49
|
function createTreeGetterFromFlightStream(stream) {
|
|
54
50
|
let ready = false;
|
|
@@ -44,16 +44,15 @@ function resolveRouteHandlers(router, actionTo) {
|
|
|
44
44
|
const builtLocation = router.buildLocation({
|
|
45
45
|
to: actionTo
|
|
46
46
|
});
|
|
47
|
-
const
|
|
48
|
-
const
|
|
49
|
-
const routeStaticData = matchedRoutes.foundRoute?.options?.staticData;
|
|
47
|
+
const [, routeParams, foundRoute] = router.getMatchedRoutes(builtLocation.pathname);
|
|
48
|
+
const routeStaticData = foundRoute?.options?.staticData;
|
|
50
49
|
const action = routeStaticData?.modernRouteAction;
|
|
51
50
|
const loader = routeStaticData?.modernRouteLoader;
|
|
52
51
|
return {
|
|
53
52
|
action,
|
|
54
53
|
loader,
|
|
55
|
-
href,
|
|
56
|
-
params:
|
|
54
|
+
href: builtLocation.href,
|
|
55
|
+
params: routeParams
|
|
57
56
|
};
|
|
58
57
|
}
|
|
59
58
|
function isRedirectResponse(value) {
|
package/dist/esm/cli/index.mjs
CHANGED
|
@@ -110,7 +110,11 @@ function tanstackRouterPlugin(options = {}) {
|
|
|
110
110
|
if (0 === tanstackEntrypoints.length) return;
|
|
111
111
|
const { handleGeneratorEntryCode } = getRuntimeRouterCli();
|
|
112
112
|
const routesByEntry = await handleGeneratorEntryCode(api, tanstackEntrypoints, {
|
|
113
|
-
entrypointsKey: ENTRYPOINTS_KEY
|
|
113
|
+
entrypointsKey: ENTRYPOINTS_KEY,
|
|
114
|
+
hydrateRscClientRoutes: true,
|
|
115
|
+
includeRouteServerLoadersInSsrEntry: false,
|
|
116
|
+
isolateRouteDataInRscLayer: true,
|
|
117
|
+
serverRoutesFileName: 'tanstack-routes.server.js'
|
|
114
118
|
});
|
|
115
119
|
await writeTanstackRouterTypesForEntries({
|
|
116
120
|
appContext: api.getAppContext(),
|
|
@@ -130,7 +134,11 @@ function tanstackRouterPlugin(options = {}) {
|
|
|
130
134
|
regenerate: async ({ api, entrypoints })=>{
|
|
131
135
|
const { handleGeneratorEntryCode } = getRuntimeRouterCli();
|
|
132
136
|
const routesByEntry = await handleGeneratorEntryCode(api, entrypoints, {
|
|
133
|
-
entrypointsKey: ENTRYPOINTS_KEY
|
|
137
|
+
entrypointsKey: ENTRYPOINTS_KEY,
|
|
138
|
+
hydrateRscClientRoutes: true,
|
|
139
|
+
includeRouteServerLoadersInSsrEntry: false,
|
|
140
|
+
isolateRouteDataInRscLayer: true,
|
|
141
|
+
serverRoutesFileName: 'tanstack-routes.server.js'
|
|
134
142
|
});
|
|
135
143
|
await writeTanstackRouterTypesForEntries({
|
|
136
144
|
appContext: api.getAppContext(),
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import node_path from "node:path";
|
|
2
1
|
import { makeLegalIdentifier } from "@modern-js/runtime/cli";
|
|
2
|
+
import { upath } from "@modern-js/utils";
|
|
3
3
|
import { createRouteStaticDataSnippet, isIndexRoute, isPathlessLayout, normalizeRelativeImport, pickModernLoaderModule, pickRouteSearchContractModules, quote, resolveFileNoExt, toTanstackPath } from "./shared.mjs";
|
|
4
4
|
async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
5
5
|
const { appContext, entryName, generatedDirName = 'modern-tanstack', routes } = opts;
|
|
6
|
-
const outDir =
|
|
6
|
+
const outDir = upath.join(appContext.srcDirectory, generatedDirName, entryName);
|
|
7
7
|
const rootModern = routes.find((r)=>{
|
|
8
8
|
const extras = r;
|
|
9
9
|
return r && 'nested' === extras.type && extras.isRoot;
|
|
@@ -28,7 +28,7 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
|
28
28
|
pendingImportName = (async ()=>{
|
|
29
29
|
const resolvedNoExt = await resolveRouteModuleNoExt(componentPath);
|
|
30
30
|
if (!resolvedNoExt) return null;
|
|
31
|
-
const relImport = normalizeRelativeImport(
|
|
31
|
+
const relImport = normalizeRelativeImport(upath.relative(outDir, resolvedNoExt));
|
|
32
32
|
const componentName = `component_${componentIndex++}`;
|
|
33
33
|
imports.push(`import ${componentName} from ${quote(relImport)};`);
|
|
34
34
|
return componentName;
|
|
@@ -42,8 +42,8 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
|
42
42
|
let absNoExt;
|
|
43
43
|
if (aliasedNoExtPath.startsWith(prefix)) {
|
|
44
44
|
const rel = aliasedNoExtPath.slice(prefix.length);
|
|
45
|
-
absNoExt =
|
|
46
|
-
} else absNoExt =
|
|
45
|
+
absNoExt = upath.join(appContext.srcDirectory, rel);
|
|
46
|
+
} else absNoExt = upath.isAbsolute(aliasedNoExtPath) ? aliasedNoExtPath : upath.join(appContext.srcDirectory, aliasedNoExtPath);
|
|
47
47
|
return resolveFileNoExt(absNoExt);
|
|
48
48
|
};
|
|
49
49
|
const getImportNamesForLoader = async (aliasedNoExtPath, inline, hasAction)=>{
|
|
@@ -55,7 +55,7 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
|
55
55
|
};
|
|
56
56
|
const resolvedNoExt = await resolveRouteModuleNoExt(aliasedNoExtPath);
|
|
57
57
|
if (!resolvedNoExt) return null;
|
|
58
|
-
const relImport = normalizeRelativeImport(
|
|
58
|
+
const relImport = normalizeRelativeImport(upath.relative(outDir, resolvedNoExt));
|
|
59
59
|
const importName = `loader_${loaderIndex++}`;
|
|
60
60
|
const actionName = hasAction ? importName.replace(/^loader_/, 'action_') : null;
|
|
61
61
|
if (inline) {
|
|
@@ -77,7 +77,7 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
|
77
77
|
if (existing) return existing;
|
|
78
78
|
const resolvedNoExt = await resolveRouteModuleNoExt(aliasedNoExtPath);
|
|
79
79
|
if (!resolvedNoExt) return null;
|
|
80
|
-
const relImport = normalizeRelativeImport(
|
|
80
|
+
const relImport = normalizeRelativeImport(upath.relative(outDir, resolvedNoExt));
|
|
81
81
|
const importName = 'validateSearch' === exportName ? `validateSearch_${validateSearchIndex++}` : `loaderDeps_${loaderDepsIndex++}`;
|
|
82
82
|
imports.push(`import { ${exportName} as ${importName} } from ${quote(relImport)};`);
|
|
83
83
|
searchContractImportMap.set(key, importName);
|
|
@@ -172,8 +172,7 @@ import {
|
|
|
172
172
|
createRouter,
|
|
173
173
|
createRouteStaticData,
|
|
174
174
|
type ModernRouterContext,
|
|
175
|
-
modernLoaderToTanstack,
|
|
176
|
-
modernTanstackRouterFastDefaults,
|
|
175
|
+
${loaderImportMap.size > 0 ? ' modernLoaderToTanstack,\n' : ''} modernTanstackRouterFastDefaults,
|
|
177
176
|
} from '@modern-js/plugin-tanstack/runtime';
|
|
178
177
|
|
|
179
178
|
${imports.join('\n')}
|
|
@@ -197,7 +196,7 @@ export const router = createRouter({
|
|
|
197
196
|
history: createMemoryHistory({
|
|
198
197
|
initialEntries: ['/'],
|
|
199
198
|
}),
|
|
200
|
-
context: {}
|
|
199
|
+
context: {},
|
|
201
200
|
});
|
|
202
201
|
`;
|
|
203
202
|
return {
|
|
@@ -94,12 +94,19 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
94
94
|
const cost = end();
|
|
95
95
|
context.ssrContext?.onTiming?.(LOADER_REPORTER_NAME, cost);
|
|
96
96
|
}
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
const serverLoadResult = serverRouter._serverResult;
|
|
98
|
+
if (!serverLoadResult) {
|
|
99
99
|
try {
|
|
100
100
|
serverRouter.serverSsr?.cleanup?.();
|
|
101
101
|
} catch {}
|
|
102
|
-
|
|
102
|
+
throw new Error('TanStack Router completed an SSR load without a server result.');
|
|
103
|
+
}
|
|
104
|
+
if ('redirect' === serverLoadResult.type) {
|
|
105
|
+
const { redirect } = serverLoadResult;
|
|
106
|
+
try {
|
|
107
|
+
serverRouter.serverSsr?.cleanup?.();
|
|
108
|
+
} catch {}
|
|
109
|
+
return interrupt(isRSCNavigation ? handleTanstackRscRedirect(redirect.headers, _basename, redirect.status) : redirect);
|
|
103
110
|
}
|
|
104
111
|
const routerErrors = collectRouterErrors(tanstackRouter);
|
|
105
112
|
if (routerErrors && 'clientRender' === loaderFailureMode) {
|
|
@@ -110,7 +117,7 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
110
117
|
throw Object.values(routerErrors)[0];
|
|
111
118
|
}
|
|
112
119
|
await preloadMatchedRouteComponents(serverRouter);
|
|
113
|
-
context.ssrContext?.response?.status(
|
|
120
|
+
context.ssrContext?.response?.status(serverLoadResult.status);
|
|
114
121
|
await serverRouter.serverSsr?.dehydrate?.();
|
|
115
122
|
if (enableRsc) {
|
|
116
123
|
if (isRSCNavigation) await waitForRouterSerialization(serverRouter);
|
|
@@ -124,7 +131,7 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
124
131
|
const routerServerSnapshot = createRouterServerSnapshot({
|
|
125
132
|
framework: 'tanstack',
|
|
126
133
|
basename: _basename,
|
|
127
|
-
statusCode:
|
|
134
|
+
statusCode: serverLoadResult.status,
|
|
128
135
|
errors: routerErrors,
|
|
129
136
|
matchedRouteIds,
|
|
130
137
|
hydrationScripts
|
|
@@ -23,10 +23,10 @@ function getTanstackRouteConfig(api, userConfig) {
|
|
|
23
23
|
}
|
|
24
24
|
function createTanstackRouteObjects({ hooks, routeConfig, ssrMode }) {
|
|
25
25
|
const { mergedConfig, finalRouteConfig } = routeConfig;
|
|
26
|
-
const routeObjects = mergedConfig.createRoutes ? mergedConfig.createRoutes() : createTanstackRouteObjectsFromConfig({
|
|
26
|
+
const routeObjects = void 0 !== mergedConfig.createRoutes ? mergedConfig.createRoutes() : createTanstackRouteObjectsFromConfig({
|
|
27
27
|
routesConfig: finalRouteConfig,
|
|
28
28
|
ssrMode
|
|
29
|
-
})
|
|
29
|
+
}) ?? [];
|
|
30
30
|
return hooks.modifyRoutes.call(routeObjects);
|
|
31
31
|
}
|
|
32
32
|
function joinBasename(baseUrl, basename) {
|
|
@@ -34,7 +34,7 @@ function joinBasename(baseUrl, basename) {
|
|
|
34
34
|
const normalizedBase = base.startsWith('/') ? base : `/${base}`;
|
|
35
35
|
const trimmedBase = normalizedBase.length > 1 ? normalizedBase.replace(/\/+$/g, '') : normalizedBase;
|
|
36
36
|
const trimmedBasename = basename.replace(/^\/+|\/+$/g, '');
|
|
37
|
-
if (
|
|
37
|
+
if (0 === trimmedBasename.length) return trimmedBase || '/';
|
|
38
38
|
return `${trimmedBase}/${trimmedBasename}`.replace(/\/{2,}/g, '/');
|
|
39
39
|
}
|
|
40
40
|
export { createTanstackRouteObjects, getMergedRouterConfig, getTanstackRouteConfig, joinBasename };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isRouteErrorResponse } from "@modern-js/runtime
|
|
1
|
+
import { isRouteErrorResponse } from "@modern-js/runtime/routerHelper";
|
|
2
2
|
function shouldRedactServerError(status = 500) {
|
|
3
3
|
return status >= 500 && 'development' !== process.env.NODE_ENV && 'test' !== process.env.NODE_ENV;
|
|
4
4
|
}
|
|
@@ -15,7 +15,7 @@ function selectTreePath(tree, path) {
|
|
|
15
15
|
return current;
|
|
16
16
|
}
|
|
17
17
|
function renderSelectedTree(src, { getTree = src[RSC_PROXY_GET_TREE], missingTreeError }) {
|
|
18
|
-
if (
|
|
18
|
+
if (void 0 === getTree) throw new Error(missingTreeError);
|
|
19
19
|
return selectTreePath(getTree(), src[RSC_PROXY_PATH] || []);
|
|
20
20
|
}
|
|
21
21
|
export { EmptyFallback, TANSTACK_RSC_FLIGHT_VALUE, isSerializedTanstackRscFlightValue, renderSelectedTree };
|
|
@@ -8,15 +8,11 @@ function loadModernRscClientRuntime() {
|
|
|
8
8
|
});
|
|
9
9
|
return modernRscClientRuntimePromise;
|
|
10
10
|
}
|
|
11
|
-
|
|
12
|
-
if ("u" < typeof window)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const runtime = await loadModernRscClientRuntime();
|
|
17
|
-
return runtime.createFromReadableStream(stream, {
|
|
18
|
-
callServer: runtime.callServer
|
|
19
|
-
});
|
|
11
|
+
function createFromFlightStream(stream) {
|
|
12
|
+
if ("u" < typeof window) return import("react-server-dom-rspack/client.edge").then((runtime)=>runtime.createFromReadableStream(stream));
|
|
13
|
+
return loadModernRscClientRuntime().then((runtime)=>runtime.createFromReadableStream(stream, {
|
|
14
|
+
callServer: runtime.callServer
|
|
15
|
+
}));
|
|
20
16
|
}
|
|
21
17
|
function createTreeGetterFromFlightStream(stream) {
|
|
22
18
|
let ready = false;
|
|
@@ -11,16 +11,15 @@ function resolveRouteHandlers(router, actionTo) {
|
|
|
11
11
|
const builtLocation = router.buildLocation({
|
|
12
12
|
to: actionTo
|
|
13
13
|
});
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const routeStaticData = matchedRoutes.foundRoute?.options?.staticData;
|
|
14
|
+
const [, routeParams, foundRoute] = router.getMatchedRoutes(builtLocation.pathname);
|
|
15
|
+
const routeStaticData = foundRoute?.options?.staticData;
|
|
17
16
|
const action = routeStaticData?.modernRouteAction;
|
|
18
17
|
const loader = routeStaticData?.modernRouteLoader;
|
|
19
18
|
return {
|
|
20
19
|
action,
|
|
21
20
|
loader,
|
|
22
|
-
href,
|
|
23
|
-
params:
|
|
21
|
+
href: builtLocation.href,
|
|
22
|
+
params: routeParams
|
|
24
23
|
};
|
|
25
24
|
}
|
|
26
25
|
function isRedirectResponse(value) {
|
|
@@ -114,7 +114,11 @@ function tanstackRouterPlugin(options = {}) {
|
|
|
114
114
|
if (0 === tanstackEntrypoints.length) return;
|
|
115
115
|
const { handleGeneratorEntryCode } = getRuntimeRouterCli();
|
|
116
116
|
const routesByEntry = await handleGeneratorEntryCode(api, tanstackEntrypoints, {
|
|
117
|
-
entrypointsKey: ENTRYPOINTS_KEY
|
|
117
|
+
entrypointsKey: ENTRYPOINTS_KEY,
|
|
118
|
+
hydrateRscClientRoutes: true,
|
|
119
|
+
includeRouteServerLoadersInSsrEntry: false,
|
|
120
|
+
isolateRouteDataInRscLayer: true,
|
|
121
|
+
serverRoutesFileName: 'tanstack-routes.server.js'
|
|
118
122
|
});
|
|
119
123
|
await writeTanstackRouterTypesForEntries({
|
|
120
124
|
appContext: api.getAppContext(),
|
|
@@ -134,7 +138,11 @@ function tanstackRouterPlugin(options = {}) {
|
|
|
134
138
|
regenerate: async ({ api, entrypoints })=>{
|
|
135
139
|
const { handleGeneratorEntryCode } = getRuntimeRouterCli();
|
|
136
140
|
const routesByEntry = await handleGeneratorEntryCode(api, entrypoints, {
|
|
137
|
-
entrypointsKey: ENTRYPOINTS_KEY
|
|
141
|
+
entrypointsKey: ENTRYPOINTS_KEY,
|
|
142
|
+
hydrateRscClientRoutes: true,
|
|
143
|
+
includeRouteServerLoadersInSsrEntry: false,
|
|
144
|
+
isolateRouteDataInRscLayer: true,
|
|
145
|
+
serverRoutesFileName: 'tanstack-routes.server.js'
|
|
138
146
|
});
|
|
139
147
|
await writeTanstackRouterTypesForEntries({
|
|
140
148
|
appContext: api.getAppContext(),
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import "node:module";
|
|
2
|
-
import node_path from "node:path";
|
|
3
2
|
import { makeLegalIdentifier } from "@modern-js/runtime/cli";
|
|
3
|
+
import { upath } from "@modern-js/utils";
|
|
4
4
|
import { createRouteStaticDataSnippet, isIndexRoute, isPathlessLayout, normalizeRelativeImport, pickModernLoaderModule, pickRouteSearchContractModules, quote, resolveFileNoExt, toTanstackPath } from "./shared.mjs";
|
|
5
5
|
async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
6
6
|
const { appContext, entryName, generatedDirName = 'modern-tanstack', routes } = opts;
|
|
7
|
-
const outDir =
|
|
7
|
+
const outDir = upath.join(appContext.srcDirectory, generatedDirName, entryName);
|
|
8
8
|
const rootModern = routes.find((r)=>{
|
|
9
9
|
const extras = r;
|
|
10
10
|
return r && 'nested' === extras.type && extras.isRoot;
|
|
@@ -29,7 +29,7 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
|
29
29
|
pendingImportName = (async ()=>{
|
|
30
30
|
const resolvedNoExt = await resolveRouteModuleNoExt(componentPath);
|
|
31
31
|
if (!resolvedNoExt) return null;
|
|
32
|
-
const relImport = normalizeRelativeImport(
|
|
32
|
+
const relImport = normalizeRelativeImport(upath.relative(outDir, resolvedNoExt));
|
|
33
33
|
const componentName = `component_${componentIndex++}`;
|
|
34
34
|
imports.push(`import ${componentName} from ${quote(relImport)};`);
|
|
35
35
|
return componentName;
|
|
@@ -43,8 +43,8 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
|
43
43
|
let absNoExt;
|
|
44
44
|
if (aliasedNoExtPath.startsWith(prefix)) {
|
|
45
45
|
const rel = aliasedNoExtPath.slice(prefix.length);
|
|
46
|
-
absNoExt =
|
|
47
|
-
} else absNoExt =
|
|
46
|
+
absNoExt = upath.join(appContext.srcDirectory, rel);
|
|
47
|
+
} else absNoExt = upath.isAbsolute(aliasedNoExtPath) ? aliasedNoExtPath : upath.join(appContext.srcDirectory, aliasedNoExtPath);
|
|
48
48
|
return resolveFileNoExt(absNoExt);
|
|
49
49
|
};
|
|
50
50
|
const getImportNamesForLoader = async (aliasedNoExtPath, inline, hasAction)=>{
|
|
@@ -56,7 +56,7 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
|
56
56
|
};
|
|
57
57
|
const resolvedNoExt = await resolveRouteModuleNoExt(aliasedNoExtPath);
|
|
58
58
|
if (!resolvedNoExt) return null;
|
|
59
|
-
const relImport = normalizeRelativeImport(
|
|
59
|
+
const relImport = normalizeRelativeImport(upath.relative(outDir, resolvedNoExt));
|
|
60
60
|
const importName = `loader_${loaderIndex++}`;
|
|
61
61
|
const actionName = hasAction ? importName.replace(/^loader_/, 'action_') : null;
|
|
62
62
|
if (inline) {
|
|
@@ -78,7 +78,7 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
|
|
|
78
78
|
if (existing) return existing;
|
|
79
79
|
const resolvedNoExt = await resolveRouteModuleNoExt(aliasedNoExtPath);
|
|
80
80
|
if (!resolvedNoExt) return null;
|
|
81
|
-
const relImport = normalizeRelativeImport(
|
|
81
|
+
const relImport = normalizeRelativeImport(upath.relative(outDir, resolvedNoExt));
|
|
82
82
|
const importName = 'validateSearch' === exportName ? `validateSearch_${validateSearchIndex++}` : `loaderDeps_${loaderDepsIndex++}`;
|
|
83
83
|
imports.push(`import { ${exportName} as ${importName} } from ${quote(relImport)};`);
|
|
84
84
|
searchContractImportMap.set(key, importName);
|
|
@@ -173,8 +173,7 @@ import {
|
|
|
173
173
|
createRouter,
|
|
174
174
|
createRouteStaticData,
|
|
175
175
|
type ModernRouterContext,
|
|
176
|
-
modernLoaderToTanstack,
|
|
177
|
-
modernTanstackRouterFastDefaults,
|
|
176
|
+
${loaderImportMap.size > 0 ? ' modernLoaderToTanstack,\n' : ''} modernTanstackRouterFastDefaults,
|
|
178
177
|
} from '@modern-js/plugin-tanstack/runtime';
|
|
179
178
|
|
|
180
179
|
${imports.join('\n')}
|
|
@@ -198,7 +197,7 @@ export const router = createRouter({
|
|
|
198
197
|
history: createMemoryHistory({
|
|
199
198
|
initialEntries: ['/'],
|
|
200
199
|
}),
|
|
201
|
-
context: {}
|
|
200
|
+
context: {},
|
|
202
201
|
});
|
|
203
202
|
`;
|
|
204
203
|
return {
|
|
@@ -95,12 +95,19 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
95
95
|
const cost = end();
|
|
96
96
|
context.ssrContext?.onTiming?.(LOADER_REPORTER_NAME, cost);
|
|
97
97
|
}
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
const serverLoadResult = serverRouter._serverResult;
|
|
99
|
+
if (!serverLoadResult) {
|
|
100
100
|
try {
|
|
101
101
|
serverRouter.serverSsr?.cleanup?.();
|
|
102
102
|
} catch {}
|
|
103
|
-
|
|
103
|
+
throw new Error('TanStack Router completed an SSR load without a server result.');
|
|
104
|
+
}
|
|
105
|
+
if ('redirect' === serverLoadResult.type) {
|
|
106
|
+
const { redirect } = serverLoadResult;
|
|
107
|
+
try {
|
|
108
|
+
serverRouter.serverSsr?.cleanup?.();
|
|
109
|
+
} catch {}
|
|
110
|
+
return interrupt(isRSCNavigation ? handleTanstackRscRedirect(redirect.headers, _basename, redirect.status) : redirect);
|
|
104
111
|
}
|
|
105
112
|
const routerErrors = collectRouterErrors(tanstackRouter);
|
|
106
113
|
if (routerErrors && 'clientRender' === loaderFailureMode) {
|
|
@@ -111,7 +118,7 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
111
118
|
throw Object.values(routerErrors)[0];
|
|
112
119
|
}
|
|
113
120
|
await preloadMatchedRouteComponents(serverRouter);
|
|
114
|
-
context.ssrContext?.response?.status(
|
|
121
|
+
context.ssrContext?.response?.status(serverLoadResult.status);
|
|
115
122
|
await serverRouter.serverSsr?.dehydrate?.();
|
|
116
123
|
if (enableRsc) {
|
|
117
124
|
if (isRSCNavigation) await waitForRouterSerialization(serverRouter);
|
|
@@ -125,7 +132,7 @@ const tanstackRouterPlugin = (userConfig = {})=>{
|
|
|
125
132
|
const routerServerSnapshot = createRouterServerSnapshot({
|
|
126
133
|
framework: 'tanstack',
|
|
127
134
|
basename: _basename,
|
|
128
|
-
statusCode:
|
|
135
|
+
statusCode: serverLoadResult.status,
|
|
129
136
|
errors: routerErrors,
|
|
130
137
|
matchedRouteIds,
|
|
131
138
|
hydrationScripts
|
|
@@ -24,10 +24,10 @@ function getTanstackRouteConfig(api, userConfig) {
|
|
|
24
24
|
}
|
|
25
25
|
function createTanstackRouteObjects({ hooks, routeConfig, ssrMode }) {
|
|
26
26
|
const { mergedConfig, finalRouteConfig } = routeConfig;
|
|
27
|
-
const routeObjects = mergedConfig.createRoutes ? mergedConfig.createRoutes() : createTanstackRouteObjectsFromConfig({
|
|
27
|
+
const routeObjects = void 0 !== mergedConfig.createRoutes ? mergedConfig.createRoutes() : createTanstackRouteObjectsFromConfig({
|
|
28
28
|
routesConfig: finalRouteConfig,
|
|
29
29
|
ssrMode
|
|
30
|
-
})
|
|
30
|
+
}) ?? [];
|
|
31
31
|
return hooks.modifyRoutes.call(routeObjects);
|
|
32
32
|
}
|
|
33
33
|
function joinBasename(baseUrl, basename) {
|
|
@@ -35,7 +35,7 @@ function joinBasename(baseUrl, basename) {
|
|
|
35
35
|
const normalizedBase = base.startsWith('/') ? base : `/${base}`;
|
|
36
36
|
const trimmedBase = normalizedBase.length > 1 ? normalizedBase.replace(/\/+$/g, '') : normalizedBase;
|
|
37
37
|
const trimmedBasename = basename.replace(/^\/+|\/+$/g, '');
|
|
38
|
-
if (
|
|
38
|
+
if (0 === trimmedBasename.length) return trimmedBase || '/';
|
|
39
39
|
return `${trimmedBase}/${trimmedBasename}`.replace(/\/{2,}/g, '/');
|
|
40
40
|
}
|
|
41
41
|
export { createTanstackRouteObjects, getMergedRouterConfig, getTanstackRouteConfig, joinBasename };
|