@bleedingdev/modern-js-plugin-tanstack 3.5.0-ultramodern.102 → 3.5.0-ultramodern.103

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 (52) hide show
  1. package/dist/cjs/cli/index.js +4 -0
  2. package/dist/cjs/cli/tanstackTypes/source.js +7 -17
  3. package/dist/cjs/runtime/plugin.node.js +12 -5
  4. package/dist/cjs/runtime/pluginShared.js +3 -3
  5. package/dist/cjs/runtime/rsc/payloadErrors.js +2 -2
  6. package/dist/cjs/runtime/rsc/shared.js +1 -1
  7. package/dist/cjs/runtime/rsc/treeGetter.js +5 -9
  8. package/dist/cjs/runtime/submitAction.js +4 -5
  9. package/dist/esm/cli/index.mjs +4 -0
  10. package/dist/esm/cli/tanstackTypes/source.mjs +7 -7
  11. package/dist/esm/runtime/plugin.node.mjs +12 -5
  12. package/dist/esm/runtime/pluginShared.mjs +3 -3
  13. package/dist/esm/runtime/rsc/payloadErrors.mjs +1 -1
  14. package/dist/esm/runtime/rsc/shared.mjs +1 -1
  15. package/dist/esm/runtime/rsc/treeGetter.mjs +5 -9
  16. package/dist/esm/runtime/submitAction.mjs +4 -5
  17. package/dist/esm-node/cli/index.mjs +4 -0
  18. package/dist/esm-node/cli/tanstackTypes/source.mjs +7 -7
  19. package/dist/esm-node/runtime/plugin.node.mjs +12 -5
  20. package/dist/esm-node/runtime/pluginShared.mjs +3 -3
  21. package/dist/esm-node/runtime/rsc/payloadErrors.mjs +1 -1
  22. package/dist/esm-node/runtime/rsc/shared.mjs +1 -1
  23. package/dist/esm-node/runtime/rsc/treeGetter.mjs +5 -9
  24. package/dist/esm-node/runtime/submitAction.mjs +4 -5
  25. package/dist/types/runtime/clientHydration.d.ts +1 -1
  26. package/dist/types/runtime/ssrTypes.d.ts +0 -2
  27. package/package.json +26 -20
  28. package/rstest.config.mts +2 -0
  29. package/src/cli/index.ts +6 -0
  30. package/src/cli/tanstackTypes/canonicalRoutes.ts +0 -1
  31. package/src/cli/tanstackTypes/shared.ts +0 -1
  32. package/src/cli/tanstackTypes/source.ts +1 -1
  33. package/src/runtime/plugin.node.tsx +17 -11
  34. package/src/runtime/plugin.tsx +0 -2
  35. package/src/runtime/pluginShared.ts +8 -7
  36. package/src/runtime/rsc/payloadErrors.ts +1 -1
  37. package/src/runtime/rsc/shared.ts +1 -1
  38. package/src/runtime/rsc/treeGetter.tsx +9 -8
  39. package/src/runtime/ssrManagedTags.ts +0 -2
  40. package/src/runtime/ssrTypes.ts +0 -4
  41. package/src/runtime/submitAction.ts +6 -11
  42. package/src/types/react-server-dom-rspack.d.ts +4 -52
  43. package/tests/router/cli.test.ts +2 -0
  44. package/tests/router/clientHydration.test.tsx +140 -1
  45. package/tests/router/dataMutation.test.tsx +50 -9
  46. package/tests/router/fixtures/rscDecoderSecurityChild.cjs +162 -0
  47. package/tests/router/preloadRedirect.test.ts +3 -8
  48. package/tests/router/routeTree.test.ts +73 -19
  49. package/tests/router/rscDecoderSecurity.test.ts +113 -0
  50. package/tests/router/serverPlugin.test.ts +115 -0
  51. package/tests/router/tanstackTypes.test.ts +351 -26
  52. package/src/runtime/ssr-shim.d.ts +0 -10
@@ -171,6 +171,8 @@ var __webpack_exports__ = {};
171
171
  const routesByEntry = await handleGeneratorEntryCode(api, tanstackEntrypoints, {
172
172
  entrypointsKey: ENTRYPOINTS_KEY,
173
173
  hydrateRscClientRoutes: true,
174
+ includeRouteServerLoadersInSsrEntry: false,
175
+ isolateRouteDataInRscLayer: true,
174
176
  serverRoutesFileName: 'tanstack-routes.server.js'
175
177
  });
176
178
  await (0, external_artifacts_js_namespaceObject.writeTanstackRouterTypesForEntries)({
@@ -193,6 +195,8 @@ var __webpack_exports__ = {};
193
195
  const routesByEntry = await handleGeneratorEntryCode(api, entrypoints, {
194
196
  entrypointsKey: ENTRYPOINTS_KEY,
195
197
  hydrateRscClientRoutes: true,
198
+ includeRouteServerLoadersInSsrEntry: false,
199
+ isolateRouteDataInRscLayer: true,
196
200
  serverRoutesFileName: 'tanstack-routes.server.js'
197
201
  });
198
202
  await (0, external_artifacts_js_namespaceObject.writeTanstackRouterTypesForEntries)({
@@ -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 = external_node_path_default().join(appContext.srcDirectory, generatedDirName, entryName);
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)(external_node_path_default().relative(outDir, resolvedNoExt));
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 = external_node_path_default().join(appContext.srcDirectory, rel);
88
- } else absNoExt = external_node_path_default().isAbsolute(aliasedNoExtPath) ? aliasedNoExtPath : external_node_path_default().join(appContext.srcDirectory, aliasedNoExtPath);
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)(external_node_path_default().relative(outDir, resolvedNoExt));
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)(external_node_path_default().relative(outDir, resolvedNoExt));
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);
@@ -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
- if (serverRouter.state.redirect) {
131
- const resolved = serverRouter.resolveRedirect ? serverRouter.resolveRedirect(serverRouter.state.redirect) : serverRouter.state.redirect;
130
+ const serverLoadResult = serverRouter._serverResult;
131
+ if (!serverLoadResult) {
132
132
  try {
133
133
  serverRouter.serverSsr?.cleanup?.();
134
134
  } catch {}
135
- return interrupt(isRSCNavigation ? (0, payloadRouter_js_namespaceObject.handleTanstackRscRedirect)(resolved.headers, _basename, resolved.status) : resolved);
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(tanstackRouter.state.statusCode);
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: tanstackRouter.state.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 (!trimmedBasename) return trimmedBase || '/';
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 router_namespaceObject = require("@modern-js/runtime-utils/router");
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, router_namespaceObject.isRouteErrorResponse)(error)) {
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 (!getTree) throw new Error(missingTreeError);
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
- async function createFromFlightStream(stream) {
44
- if ("u" < typeof window) {
45
- const runtime = await import("react-server-dom-rspack/client.edge");
46
- return runtime.createFromReadableStream(stream);
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 href = router.getParsedLocationHref(builtLocation);
48
- const matchedRoutes = router.getMatchedRoutes(builtLocation.pathname);
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: matchedRoutes.routeParams || {}
54
+ href: builtLocation.href,
55
+ params: routeParams
57
56
  };
58
57
  }
59
58
  function isRedirectResponse(value) {
@@ -112,6 +112,8 @@ function tanstackRouterPlugin(options = {}) {
112
112
  const routesByEntry = await handleGeneratorEntryCode(api, tanstackEntrypoints, {
113
113
  entrypointsKey: ENTRYPOINTS_KEY,
114
114
  hydrateRscClientRoutes: true,
115
+ includeRouteServerLoadersInSsrEntry: false,
116
+ isolateRouteDataInRscLayer: true,
115
117
  serverRoutesFileName: 'tanstack-routes.server.js'
116
118
  });
117
119
  await writeTanstackRouterTypesForEntries({
@@ -134,6 +136,8 @@ function tanstackRouterPlugin(options = {}) {
134
136
  const routesByEntry = await handleGeneratorEntryCode(api, entrypoints, {
135
137
  entrypointsKey: ENTRYPOINTS_KEY,
136
138
  hydrateRscClientRoutes: true,
139
+ includeRouteServerLoadersInSsrEntry: false,
140
+ isolateRouteDataInRscLayer: true,
137
141
  serverRoutesFileName: 'tanstack-routes.server.js'
138
142
  });
139
143
  await writeTanstackRouterTypesForEntries({
@@ -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 = node_path.join(appContext.srcDirectory, generatedDirName, entryName);
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(node_path.relative(outDir, resolvedNoExt));
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 = node_path.join(appContext.srcDirectory, rel);
46
- } else absNoExt = node_path.isAbsolute(aliasedNoExtPath) ? aliasedNoExtPath : node_path.join(appContext.srcDirectory, aliasedNoExtPath);
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(node_path.relative(outDir, resolvedNoExt));
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(node_path.relative(outDir, resolvedNoExt));
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);
@@ -94,12 +94,19 @@ const tanstackRouterPlugin = (userConfig = {})=>{
94
94
  const cost = end();
95
95
  context.ssrContext?.onTiming?.(LOADER_REPORTER_NAME, cost);
96
96
  }
97
- if (serverRouter.state.redirect) {
98
- const resolved = serverRouter.resolveRedirect ? serverRouter.resolveRedirect(serverRouter.state.redirect) : serverRouter.state.redirect;
97
+ const serverLoadResult = serverRouter._serverResult;
98
+ if (!serverLoadResult) {
99
99
  try {
100
100
  serverRouter.serverSsr?.cleanup?.();
101
101
  } catch {}
102
- return interrupt(isRSCNavigation ? handleTanstackRscRedirect(resolved.headers, _basename, resolved.status) : resolved);
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(tanstackRouter.state.statusCode);
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: tanstackRouter.state.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 (!trimmedBasename) return trimmedBase || '/';
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-utils/router";
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 (!getTree) throw new Error(missingTreeError);
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
- async function createFromFlightStream(stream) {
12
- if ("u" < typeof window) {
13
- const runtime = await import("react-server-dom-rspack/client.edge");
14
- return runtime.createFromReadableStream(stream);
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 href = router.getParsedLocationHref(builtLocation);
15
- const matchedRoutes = router.getMatchedRoutes(builtLocation.pathname);
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: matchedRoutes.routeParams || {}
21
+ href: builtLocation.href,
22
+ params: routeParams
24
23
  };
25
24
  }
26
25
  function isRedirectResponse(value) {
@@ -116,6 +116,8 @@ function tanstackRouterPlugin(options = {}) {
116
116
  const routesByEntry = await handleGeneratorEntryCode(api, tanstackEntrypoints, {
117
117
  entrypointsKey: ENTRYPOINTS_KEY,
118
118
  hydrateRscClientRoutes: true,
119
+ includeRouteServerLoadersInSsrEntry: false,
120
+ isolateRouteDataInRscLayer: true,
119
121
  serverRoutesFileName: 'tanstack-routes.server.js'
120
122
  });
121
123
  await writeTanstackRouterTypesForEntries({
@@ -138,6 +140,8 @@ function tanstackRouterPlugin(options = {}) {
138
140
  const routesByEntry = await handleGeneratorEntryCode(api, entrypoints, {
139
141
  entrypointsKey: ENTRYPOINTS_KEY,
140
142
  hydrateRscClientRoutes: true,
143
+ includeRouteServerLoadersInSsrEntry: false,
144
+ isolateRouteDataInRscLayer: true,
141
145
  serverRoutesFileName: 'tanstack-routes.server.js'
142
146
  });
143
147
  await writeTanstackRouterTypesForEntries({
@@ -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 = node_path.join(appContext.srcDirectory, generatedDirName, entryName);
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(node_path.relative(outDir, resolvedNoExt));
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 = node_path.join(appContext.srcDirectory, rel);
47
- } else absNoExt = node_path.isAbsolute(aliasedNoExtPath) ? aliasedNoExtPath : node_path.join(appContext.srcDirectory, aliasedNoExtPath);
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(node_path.relative(outDir, resolvedNoExt));
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(node_path.relative(outDir, resolvedNoExt));
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);
@@ -95,12 +95,19 @@ const tanstackRouterPlugin = (userConfig = {})=>{
95
95
  const cost = end();
96
96
  context.ssrContext?.onTiming?.(LOADER_REPORTER_NAME, cost);
97
97
  }
98
- if (serverRouter.state.redirect) {
99
- const resolved = serverRouter.resolveRedirect ? serverRouter.resolveRedirect(serverRouter.state.redirect) : serverRouter.state.redirect;
98
+ const serverLoadResult = serverRouter._serverResult;
99
+ if (!serverLoadResult) {
100
100
  try {
101
101
  serverRouter.serverSsr?.cleanup?.();
102
102
  } catch {}
103
- return interrupt(isRSCNavigation ? handleTanstackRscRedirect(resolved.headers, _basename, resolved.status) : resolved);
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(tanstackRouter.state.statusCode);
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: tanstackRouter.state.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 (!trimmedBasename) return trimmedBase || '/';
38
+ if (0 === trimmedBasename.length) return trimmedBase || '/';
39
39
  return `${trimmedBase}/${trimmedBasename}`.replace(/\/{2,}/g, '/');
40
40
  }
41
41
  export { createTanstackRouteObjects, getMergedRouterConfig, getTanstackRouteConfig, joinBasename };
@@ -1,5 +1,5 @@
1
1
  import "node:module";
2
- import { isRouteErrorResponse } from "@modern-js/runtime-utils/router";
2
+ import { isRouteErrorResponse } from "@modern-js/runtime/routerHelper";
3
3
  function shouldRedactServerError(status = 500) {
4
4
  return status >= 500 && 'development' !== process.env.NODE_ENV && 'test' !== process.env.NODE_ENV;
5
5
  }
@@ -16,7 +16,7 @@ function selectTreePath(tree, path) {
16
16
  return current;
17
17
  }
18
18
  function renderSelectedTree(src, { getTree = src[RSC_PROXY_GET_TREE], missingTreeError }) {
19
- if (!getTree) throw new Error(missingTreeError);
19
+ if (void 0 === getTree) throw new Error(missingTreeError);
20
20
  return selectTreePath(getTree(), src[RSC_PROXY_PATH] || []);
21
21
  }
22
22
  export { EmptyFallback, TANSTACK_RSC_FLIGHT_VALUE, isSerializedTanstackRscFlightValue, renderSelectedTree };
@@ -9,15 +9,11 @@ function loadModernRscClientRuntime() {
9
9
  });
10
10
  return modernRscClientRuntimePromise;
11
11
  }
12
- async function createFromFlightStream(stream) {
13
- if ("u" < typeof window) {
14
- const runtime = await import("react-server-dom-rspack/client.edge");
15
- return runtime.createFromReadableStream(stream);
16
- }
17
- const runtime = await loadModernRscClientRuntime();
18
- return runtime.createFromReadableStream(stream, {
19
- callServer: runtime.callServer
20
- });
12
+ function createFromFlightStream(stream) {
13
+ if ("u" < typeof window) return import("react-server-dom-rspack/client.edge").then((runtime)=>runtime.createFromReadableStream(stream));
14
+ return loadModernRscClientRuntime().then((runtime)=>runtime.createFromReadableStream(stream, {
15
+ callServer: runtime.callServer
16
+ }));
21
17
  }
22
18
  function createTreeGetterFromFlightStream(stream) {
23
19
  let ready = false;
@@ -12,16 +12,15 @@ function resolveRouteHandlers(router, actionTo) {
12
12
  const builtLocation = router.buildLocation({
13
13
  to: actionTo
14
14
  });
15
- const href = router.getParsedLocationHref(builtLocation);
16
- const matchedRoutes = router.getMatchedRoutes(builtLocation.pathname);
17
- const routeStaticData = matchedRoutes.foundRoute?.options?.staticData;
15
+ const [, routeParams, foundRoute] = router.getMatchedRoutes(builtLocation.pathname);
16
+ const routeStaticData = foundRoute?.options?.staticData;
18
17
  const action = routeStaticData?.modernRouteAction;
19
18
  const loader = routeStaticData?.modernRouteLoader;
20
19
  return {
21
20
  action,
22
21
  loader,
23
- href,
24
- params: matchedRoutes.routeParams || {}
22
+ href: builtLocation.href,
23
+ params: routeParams
25
24
  };
26
25
  }
27
26
  function isRedirectResponse(value) {
@@ -2,7 +2,7 @@ import { type AnyRouter } from '@tanstack/react-router';
2
2
  export type WindowWithTanstackSsr = Window & {
3
3
  $_TSR?: unknown;
4
4
  };
5
- export declare function hydrateTanstackRouter(router: AnyRouter): Promise<unknown>;
5
+ export declare function hydrateTanstackRouter(router: AnyRouter): Promise<void>;
6
6
  export declare function getTanstackSsrHydrationPromise(router: AnyRouter): Promise<unknown>;
7
7
  export declare function hasTanstackSsrHydrationRecord(router: AnyRouter): boolean;
8
8
  export declare function ModernRouterClient({ router }: {