@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.
Files changed (55) hide show
  1. package/dist/cjs/cli/index.js +10 -2
  2. package/dist/cjs/cli/tanstackTypes/source.js +9 -20
  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 +10 -2
  10. package/dist/esm/cli/tanstackTypes/source.mjs +9 -10
  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 +10 -2
  18. package/dist/esm-node/cli/tanstackTypes/source.mjs +9 -10
  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 +27 -20
  28. package/rstest.config.mts +2 -0
  29. package/src/cli/index.ts +12 -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 +3 -4
  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 +204 -96
  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/routerCompatibility.test.ts +0 -6
  50. package/tests/router/rscDecoderSecurity.test.ts +113 -0
  51. package/tests/router/serverPlugin.test.ts +115 -0
  52. package/tests/router/tanstackTypes.test.ts +668 -356
  53. package/src/runtime/ssr-shim.d.ts +0 -10
  54. package/tests/castRatchet.test.ts +0 -85
  55. package/tests/router/fixtures/router-gen.golden.txt +0 -71
@@ -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 = 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);
@@ -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: {} as ModernRouterContext,
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
- 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) {
@@ -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 = 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);
@@ -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: {} as ModernRouterContext,
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
- 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) {
@@ -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 = 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);
@@ -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: {} as ModernRouterContext,
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
- 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 };