@bleedingdev/modern-js-plugin-tanstack 3.2.0-ultramodern.12 → 3.2.0-ultramodern.120

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 (87) hide show
  1. package/dist/cjs/cli/index.js +47 -9
  2. package/dist/cjs/cli/routeSplitting.js +87 -0
  3. package/dist/cjs/cli/tanstackTypes.js +230 -63
  4. package/dist/cjs/cli.js +12 -8
  5. package/dist/cjs/runtime/DefaultNotFound.js +9 -5
  6. package/dist/cjs/runtime/basepathRewrite.js +12 -8
  7. package/dist/cjs/runtime/dataMutation.js +9 -5
  8. package/dist/cjs/runtime/hooks.js +9 -5
  9. package/dist/cjs/runtime/hydrationBoundary.js +48 -0
  10. package/dist/cjs/runtime/index.js +330 -74
  11. package/dist/cjs/runtime/lifecycle.js +15 -11
  12. package/dist/cjs/runtime/outlet.js +58 -0
  13. package/dist/cjs/runtime/plugin.js +203 -98
  14. package/dist/cjs/runtime/plugin.node.js +38 -16
  15. package/dist/cjs/runtime/plugin.worker.js +53 -0
  16. package/dist/cjs/runtime/prefetchLink.js +10 -6
  17. package/dist/cjs/runtime/routeTree.js +81 -17
  18. package/dist/cjs/runtime/rsc/ClientSlot.js +9 -5
  19. package/dist/cjs/runtime/rsc/CompositeComponent.js +9 -5
  20. package/dist/cjs/runtime/rsc/ReplayableStream.js +14 -9
  21. package/dist/cjs/runtime/rsc/RscNodeRenderer.js +9 -5
  22. package/dist/cjs/runtime/rsc/SlotContext.js +9 -5
  23. package/dist/cjs/runtime/rsc/client.js +9 -5
  24. package/dist/cjs/runtime/rsc/createRscProxy.js +9 -5
  25. package/dist/cjs/runtime/rsc/index.js +9 -5
  26. package/dist/cjs/runtime/rsc/payloadRouter.js +9 -5
  27. package/dist/cjs/runtime/rsc/server.js +9 -5
  28. package/dist/cjs/runtime/rsc/slotUsageSanitizer.js +9 -5
  29. package/dist/cjs/runtime/rsc/symbols.js +20 -15
  30. package/dist/cjs/runtime/types.js +31 -1
  31. package/dist/cjs/runtime/utils.js +9 -5
  32. package/dist/cjs/runtime.js +9 -5
  33. package/dist/esm/cli/index.mjs +28 -6
  34. package/dist/esm/cli/routeSplitting.mjs +43 -0
  35. package/dist/esm/cli/tanstackTypes.mjs +219 -59
  36. package/dist/esm/runtime/hydrationBoundary.mjs +10 -0
  37. package/dist/esm/runtime/index.mjs +3 -2
  38. package/dist/esm/runtime/outlet.mjs +17 -0
  39. package/dist/esm/runtime/plugin.mjs +197 -96
  40. package/dist/esm/runtime/plugin.node.mjs +30 -12
  41. package/dist/esm/runtime/plugin.worker.mjs +1 -0
  42. package/dist/esm/runtime/prefetchLink.mjs +1 -1
  43. package/dist/esm/runtime/routeTree.mjs +73 -13
  44. package/dist/esm/runtime/types.mjs +7 -0
  45. package/dist/esm-node/cli/index.mjs +28 -6
  46. package/dist/esm-node/cli/routeSplitting.mjs +44 -0
  47. package/dist/esm-node/cli/tanstackTypes.mjs +219 -59
  48. package/dist/esm-node/runtime/hydrationBoundary.mjs +11 -0
  49. package/dist/esm-node/runtime/index.mjs +3 -2
  50. package/dist/esm-node/runtime/outlet.mjs +18 -0
  51. package/dist/esm-node/runtime/plugin.mjs +197 -96
  52. package/dist/esm-node/runtime/plugin.node.mjs +30 -12
  53. package/dist/esm-node/runtime/plugin.worker.mjs +2 -0
  54. package/dist/esm-node/runtime/prefetchLink.mjs +1 -1
  55. package/dist/esm-node/runtime/routeTree.mjs +73 -13
  56. package/dist/esm-node/runtime/types.mjs +7 -0
  57. package/dist/types/cli/index.d.ts +7 -1
  58. package/dist/types/cli/routeSplitting.d.ts +29 -0
  59. package/dist/types/cli/tanstackTypes.d.ts +9 -0
  60. package/dist/types/runtime/hooks.d.ts +9 -24
  61. package/dist/types/runtime/hydrationBoundary.d.ts +2 -0
  62. package/dist/types/runtime/index.d.ts +5 -2
  63. package/dist/types/runtime/outlet.d.ts +2 -0
  64. package/dist/types/runtime/plugin.d.ts +1 -1
  65. package/dist/types/runtime/plugin.node.d.ts +1 -1
  66. package/dist/types/runtime/plugin.worker.d.ts +1 -0
  67. package/dist/types/runtime/types.d.ts +7 -0
  68. package/package.json +20 -20
  69. package/src/cli/index.ts +59 -2
  70. package/src/cli/routeSplitting.ts +81 -0
  71. package/src/cli/tanstackTypes.ts +347 -67
  72. package/src/runtime/hydrationBoundary.tsx +12 -0
  73. package/src/runtime/index.tsx +107 -2
  74. package/src/runtime/outlet.tsx +48 -0
  75. package/src/runtime/plugin.node.tsx +58 -8
  76. package/src/runtime/plugin.tsx +372 -157
  77. package/src/runtime/plugin.worker.tsx +4 -0
  78. package/src/runtime/prefetchLink.tsx +1 -1
  79. package/src/runtime/routeTree.ts +194 -23
  80. package/src/runtime/ssr-shim.d.ts +1 -3
  81. package/src/runtime/types.ts +13 -0
  82. package/tests/router/cli.test.ts +315 -0
  83. package/tests/router/fastDefaults.test.ts +25 -0
  84. package/tests/router/hydrationBoundary.test.tsx +23 -0
  85. package/tests/router/prefetchLink.test.tsx +43 -7
  86. package/tests/router/routeTree.test.ts +416 -1
  87. package/tests/router/tanstackTypes.test.ts +415 -1
@@ -56,6 +56,14 @@ function pickModernLoaderModule(route) {
56
56
  inline
57
57
  };
58
58
  }
59
+ function pickRouteSearchContractModules(route) {
60
+ const validateSearchPath = route.validateSearch;
61
+ const loaderDepsPath = route.loaderDeps;
62
+ return {
63
+ validateSearchPath: 'string' == typeof validateSearchPath ? validateSearchPath : null,
64
+ loaderDepsPath: 'string' == typeof loaderDepsPath ? loaderDepsPath : null
65
+ };
66
+ }
59
67
  function isPathlessLayout(route) {
60
68
  return 'nested' === route.type && 'boolean' != typeof route.index && void 0 === route.path;
61
69
  }
@@ -70,6 +78,78 @@ function createRouteStaticDataSnippet(opts) {
70
78
  if (!staticDataLines.length) return null;
71
79
  return `staticData: createRouteStaticData({\n ${staticDataLines.join('\n ')}\n }),`;
72
80
  }
81
+ const LOCALE_PARAM_SEGMENTS = new Set([
82
+ ':lang',
83
+ ':locale',
84
+ ':language',
85
+ '$lang',
86
+ '$locale',
87
+ '$language'
88
+ ]);
89
+ function paramsTypeForCanonicalPath(canonicalPath) {
90
+ const fields = [];
91
+ for (const segment of canonicalPath.split('/'))if (segment) {
92
+ if ('*' === segment || '$' === segment) {
93
+ fields.push("'_splat'?: string");
94
+ continue;
95
+ }
96
+ if (segment.startsWith('{-$') && segment.endsWith('}')) {
97
+ fields.push(`${JSON.stringify(segment.slice(3, -1))}?: string`);
98
+ continue;
99
+ }
100
+ if (segment.startsWith('$')) {
101
+ fields.push(`${JSON.stringify(segment.slice(1))}: string`);
102
+ continue;
103
+ }
104
+ if (segment.startsWith(':')) {
105
+ const optional = segment.endsWith('?');
106
+ const name = segment.slice(1, optional ? void 0 : segment.length);
107
+ fields.push(`${JSON.stringify(optional ? name.slice(0, -1) : name)}${optional ? '?' : ''}: string`);
108
+ }
109
+ }
110
+ return fields.length > 0 ? `{ ${fields.join('; ')} }` : 'Record<string, never>';
111
+ }
112
+ function collectCanonicalRoutesForEntry(routes) {
113
+ const canonicalParams = new Map();
114
+ let hasI18nSurface = false;
115
+ const normalizeJoined = (joined)=>{
116
+ const collapsed = joined.replace(/\/+/g, '/');
117
+ const withLeading = collapsed.startsWith('/') ? collapsed : `/${collapsed}`;
118
+ return withLeading.length > 1 ? withLeading.replace(/\/+$/, '') : withLeading;
119
+ };
120
+ const record = (canonicalPath)=>{
121
+ const normalized = normalizeJoined(canonicalPath || '/');
122
+ const key = toTanstackPath(normalized);
123
+ if (!canonicalParams.has(key)) canonicalParams.set(key, paramsTypeForCanonicalPath(normalized));
124
+ };
125
+ const visit = (route, parentPath)=>{
126
+ let currentPath = parentPath;
127
+ if ('string' == typeof route.modernCanonicalPath) {
128
+ hasI18nSurface = true;
129
+ currentPath = normalizeJoined(route.modernCanonicalPath);
130
+ } else if ('string' == typeof route.path && route.path.length > 0) {
131
+ const segments = route.path.replace(/\[(.+?)\]/g, ':$1').split('/').filter(Boolean);
132
+ if ('' === parentPath && LOCALE_PARAM_SEGMENTS.has(segments[0])) {
133
+ hasI18nSurface = true;
134
+ segments.shift();
135
+ }
136
+ currentPath = segments.length ? normalizeJoined(`${parentPath}/${segments.join('/')}`) : parentPath;
137
+ }
138
+ const children = route.children;
139
+ if (children && children.length > 0) {
140
+ for (const child of children)visit(child, currentPath);
141
+ return;
142
+ }
143
+ record(currentPath || '/');
144
+ };
145
+ const rootModern = routes.find((route)=>route.isRoot);
146
+ const topLevel = rootModern ? rootModern.children ?? [] : routes;
147
+ for (const route of topLevel)visit(route, '');
148
+ if (!hasI18nSurface || 0 === canonicalParams.size) return null;
149
+ return Object.fromEntries([
150
+ ...canonicalParams.entries()
151
+ ].sort(([a], [b])=>a.localeCompare(b)));
152
+ }
73
153
  async function isTanstackRouterFrameworkEnabled(appContext) {
74
154
  const runtimeConfigBase = path.join(appContext.srcDirectory, appContext.runtimeConfigFile);
75
155
  const runtimeConfigFile = findExists(JS_OR_TS_EXTS.map((ext)=>`${runtimeConfigBase}${ext}`));
@@ -89,8 +169,21 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
89
169
  const imports = [];
90
170
  const statements = [];
91
171
  const loaderImportMap = new Map();
172
+ const searchContractImportMap = new Map();
173
+ const usedRouteVarNames = new Set();
92
174
  let loaderIndex = 0;
175
+ let validateSearchIndex = 0;
176
+ let loaderDepsIndex = 0;
93
177
  let routeIndex = 0;
178
+ const resolveRouteModuleNoExt = async (aliasedNoExtPath)=>{
179
+ const prefix = `${appContext.internalSrcAlias}/`;
180
+ let absNoExt;
181
+ if (aliasedNoExtPath.startsWith(prefix)) {
182
+ const rel = aliasedNoExtPath.slice(prefix.length);
183
+ absNoExt = path.join(appContext.srcDirectory, rel);
184
+ } else absNoExt = path.isAbsolute(aliasedNoExtPath) ? aliasedNoExtPath : path.join(appContext.srcDirectory, aliasedNoExtPath);
185
+ return resolveFileNoExt(absNoExt);
186
+ };
94
187
  const getImportNamesForLoader = async (aliasedNoExtPath, inline, hasAction)=>{
95
188
  const key = `${inline ? 'inline' : 'default'}:${hasAction ? 'action' : 'loader'}:${aliasedNoExtPath}`;
96
189
  const existing = loaderImportMap.get(key);
@@ -98,13 +191,7 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
98
191
  loaderName: existing,
99
192
  actionName: hasAction ? existing.replace(/^loader_/, 'action_') : null
100
193
  };
101
- const prefix = `${appContext.internalSrcAlias}/`;
102
- let absNoExt;
103
- if (aliasedNoExtPath.startsWith(prefix)) {
104
- const rel = aliasedNoExtPath.slice(prefix.length);
105
- absNoExt = path.join(appContext.srcDirectory, rel);
106
- } else absNoExt = path.isAbsolute(aliasedNoExtPath) ? aliasedNoExtPath : path.join(appContext.srcDirectory, aliasedNoExtPath);
107
- const resolvedNoExt = await resolveFileNoExt(absNoExt);
194
+ const resolvedNoExt = await resolveRouteModuleNoExt(aliasedNoExtPath);
108
195
  if (!resolvedNoExt) return null;
109
196
  const relImport = normalizeRelativeImport(path.relative(outDir, resolvedNoExt));
110
197
  const importName = `loader_${loaderIndex++}`;
@@ -122,10 +209,29 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
122
209
  actionName
123
210
  };
124
211
  };
212
+ const getImportNameForSearchContract = async (aliasedNoExtPath, exportName)=>{
213
+ const key = `${exportName}:${aliasedNoExtPath}`;
214
+ const existing = searchContractImportMap.get(key);
215
+ if (existing) return existing;
216
+ const resolvedNoExt = await resolveRouteModuleNoExt(aliasedNoExtPath);
217
+ if (!resolvedNoExt) return null;
218
+ const relImport = normalizeRelativeImport(path.relative(outDir, resolvedNoExt));
219
+ const importName = 'validateSearch' === exportName ? `validateSearch_${validateSearchIndex++}` : `loaderDeps_${loaderDepsIndex++}`;
220
+ imports.push(`import { ${exportName} as ${importName} } from ${quote(relImport)};`);
221
+ searchContractImportMap.set(key, importName);
222
+ return importName;
223
+ };
224
+ const reserveRouteVarName = (preferred)=>{
225
+ let candidate = preferred;
226
+ let suffix = 1;
227
+ while(usedRouteVarNames.has(candidate))candidate = `${preferred}_${suffix++}`;
228
+ usedRouteVarNames.add(candidate);
229
+ return candidate;
230
+ };
125
231
  const createRouteVarName = (route)=>{
126
232
  const id = route.id;
127
233
  const base = id ? makeLegalIdentifier(id) : `r_${routeIndex++}`;
128
- return `route_${base}`;
234
+ return reserveRouteVarName(`route_${base}`);
129
235
  };
130
236
  const buildRoute = async (opts)=>{
131
237
  const { parentVar, route } = opts;
@@ -135,6 +241,9 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
135
241
  const loaderImports = loaderInfo ? await getImportNamesForLoader(loaderInfo.loaderPath, loaderInfo.inline, Boolean(loaderInfo.inline && routeAction === loaderInfo.loaderPath)) : null;
136
242
  const loaderName = loaderImports?.loaderName || null;
137
243
  const actionName = loaderImports?.actionName || null;
244
+ const searchContractInfo = pickRouteSearchContractModules(route);
245
+ const validateSearchName = searchContractInfo.validateSearchPath ? await getImportNameForSearchContract(searchContractInfo.validateSearchPath, 'validateSearch') : null;
246
+ const loaderDepsName = searchContractInfo.loaderDepsPath ? await getImportNameForSearchContract(searchContractInfo.loaderDepsPath, 'loaderDeps') : null;
138
247
  const rawPath = route.path;
139
248
  const hasSplat = 'string' == typeof rawPath && rawPath.includes('*');
140
249
  const routeOpts = [
@@ -148,20 +257,24 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
148
257
  routeOpts.push(`path: ${quote(p)},`);
149
258
  }
150
259
  if (loaderName) routeOpts.push(`loader: modernLoaderToTanstack({ hasSplat: ${hasSplat} }, ${loaderName}),`);
260
+ if (validateSearchName) routeOpts.push(`validateSearch: ${validateSearchName},`);
261
+ if (loaderDepsName) routeOpts.push(`loaderDeps: ${loaderDepsName},`);
151
262
  const staticDataSnippet = createRouteStaticDataSnippet({
152
263
  modernRouteId: route.id,
153
264
  loaderName,
154
265
  actionName
155
266
  });
156
267
  if (staticDataSnippet) routeOpts.push(staticDataSnippet);
157
- statements.push(`const ${varName} = createRoute({\n ${routeOpts.join('\n ')}\n});`);
158
268
  const children = route.children;
269
+ const hasChildren = Boolean(children && children.length > 0);
270
+ const routeCtorVarName = hasChildren ? reserveRouteVarName(`${varName}__base`) : varName;
271
+ statements.push(`const ${routeCtorVarName} = createRoute({\n ${routeOpts.join('\n ')}\n});`);
159
272
  if (children && children.length > 0) {
160
273
  const childVars = await Promise.all(children.map((child)=>buildRoute({
161
- parentVar: varName,
274
+ parentVar: routeCtorVarName,
162
275
  route: child
163
276
  })));
164
- statements.push(`${varName}.addChildren([${childVars.join(', ')}]);`);
277
+ statements.push(`const ${varName} = ${routeCtorVarName}.addChildren([${childVars.join(', ')}]);`);
165
278
  }
166
279
  return varName;
167
280
  };
@@ -170,17 +283,23 @@ async function generateTanstackRouterTypesSourceForEntry(opts) {
170
283
  const rootLoaderImports = rootLoaderInfo?.loaderPath ? await getImportNamesForLoader(rootLoaderInfo.loaderPath, rootLoaderInfo.inline, Boolean(rootLoaderInfo.inline && rootAction === rootLoaderInfo.loaderPath)) : null;
171
284
  const rootLoaderName = rootLoaderImports?.loaderName || null;
172
285
  const rootActionName = rootLoaderImports?.actionName || null;
286
+ const rootSearchContractInfo = rootModern ? pickRouteSearchContractModules(rootModern) : null;
287
+ const rootValidateSearchName = rootSearchContractInfo?.validateSearchPath ? await getImportNameForSearchContract(rootSearchContractInfo.validateSearchPath, 'validateSearch') : null;
288
+ const rootLoaderDepsName = rootSearchContractInfo?.loaderDepsPath ? await getImportNameForSearchContract(rootSearchContractInfo.loaderDepsPath, 'loaderDeps') : null;
173
289
  const topLevelVars = await Promise.all(topLevel.map((route)=>buildRoute({
174
290
  parentVar: 'rootRoute',
175
291
  route
176
292
  })));
177
293
  const rootOpts = [];
178
294
  if (rootLoaderName) rootOpts.push(`loader: modernLoaderToTanstack({ hasSplat: false }, ${rootLoaderName}),`);
295
+ if (rootValidateSearchName) rootOpts.push(`validateSearch: ${rootValidateSearchName},`);
296
+ if (rootLoaderDepsName) rootOpts.push(`loaderDeps: ${rootLoaderDepsName},`);
179
297
  const routerGenTs = `/* eslint-disable */
180
298
  // This file is auto-generated by Modern.js. Do not edit manually.
181
299
 
182
300
  import {
183
301
  createMemoryHistory,
302
+ modernTanstackRouterFastDefaults,
184
303
  createRootRouteWithContext,
185
304
  createRoute,
186
305
  createRouter,
@@ -208,7 +327,7 @@ function isRedirectResponse(res: Response) {
208
327
  }
209
328
 
210
329
  function throwTanstackRedirect(location: string) {
211
- const target = location || '/';
330
+ const target = location.length > 0 ? location : '/';
212
331
  try {
213
332
  void new URL(target);
214
333
  throw redirect({ href: target });
@@ -234,21 +353,87 @@ function createRouteStaticData(opts: {
234
353
  modernRouteAction?: unknown;
235
354
  modernRouteLoader?: unknown;
236
355
  }) {
237
- const staticData: Record<string, unknown> = {};
356
+ const staticData: {
357
+ modernRouteId?: string;
358
+ modernRouteAction?: unknown;
359
+ modernRouteLoader?: unknown;
360
+ } = {};
238
361
 
239
- if (opts.modernRouteId) {
362
+ if (typeof opts.modernRouteId === 'string' && opts.modernRouteId.length > 0) {
240
363
  staticData.modernRouteId = opts.modernRouteId;
241
364
  }
242
365
 
243
- if (opts.modernRouteLoader) {
366
+ if (typeof opts.modernRouteLoader !== 'undefined') {
244
367
  staticData.modernRouteLoader = opts.modernRouteLoader;
245
368
  }
246
369
 
247
- if (opts.modernRouteAction) {
370
+ if (typeof opts.modernRouteAction !== 'undefined') {
248
371
  staticData.modernRouteAction = opts.modernRouteAction;
249
372
  }
250
373
 
251
- return Object.keys(staticData).length > 0 ? staticData : undefined;
374
+ return staticData;
375
+ }
376
+
377
+ function getLoaderSignal(ctx: any): AbortSignal {
378
+ const abortSignal = ctx?.abortController?.signal;
379
+ if (abortSignal instanceof AbortSignal) {
380
+ return abortSignal;
381
+ }
382
+ if (ctx?.signal instanceof AbortSignal) {
383
+ return ctx.signal;
384
+ }
385
+ return new AbortController().signal;
386
+ }
387
+
388
+ function getLoaderHref(ctx: any): string {
389
+ if (typeof ctx?.location === 'string') {
390
+ return ctx.location;
391
+ }
392
+
393
+ const publicHref = ctx?.location?.publicHref;
394
+ if (typeof publicHref === 'string') {
395
+ return publicHref;
396
+ }
397
+
398
+ const href = ctx?.location?.href;
399
+ if (typeof href === 'string') {
400
+ return href;
401
+ }
402
+
403
+ const urlHref = ctx?.location?.url?.href;
404
+ return typeof urlHref === 'string' ? urlHref : '';
405
+ }
406
+
407
+ function getLoaderParams(ctx: any): Record<string, string> {
408
+ return typeof ctx?.params === 'object' && ctx.params !== null ? ctx.params : {};
409
+ }
410
+
411
+ function handleModernLoaderResult<LoaderResult>(result: LoaderResult): LoaderResult {
412
+ if (isResponse(result)) {
413
+ if (isRedirectResponse(result)) {
414
+ const location = result.headers.get('Location') ?? '/';
415
+ throwTanstackRedirect(location);
416
+ }
417
+ if (result.status === 404) {
418
+ throw notFound();
419
+ }
420
+ }
421
+
422
+ return result;
423
+ }
424
+
425
+ function handleModernLoaderError(err: unknown): never {
426
+ if (isResponse(err)) {
427
+ if (isRedirectResponse(err)) {
428
+ const location = err.headers.get('Location') ?? '/';
429
+ throwTanstackRedirect(location);
430
+ }
431
+ if (err.status === 404) {
432
+ throw notFound();
433
+ }
434
+ }
435
+
436
+ throw err;
252
437
  }
253
438
 
254
439
  function modernLoaderToTanstack<TLoader extends (args: any) => any>(
@@ -257,57 +442,31 @@ function modernLoaderToTanstack<TLoader extends (args: any) => any>(
257
442
  ) {
258
443
  type LoaderResult = Awaited<ReturnType<TLoader>>;
259
444
 
260
- return async (ctx: any): Promise<LoaderResult> => {
445
+ return (ctx: any): Promise<LoaderResult> => {
261
446
  try {
262
- const signal: AbortSignal =
263
- ctx?.abortController?.signal ||
264
- ctx?.signal ||
265
- new AbortController().signal;
447
+ const signal = getLoaderSignal(ctx);
266
448
  const baseRequest: Request | undefined =
267
449
  ctx?.context?.request instanceof Request ? ctx.context.request : undefined;
268
450
 
269
- const href =
270
- typeof ctx?.location === 'string'
271
- ? ctx.location
272
- : ctx?.location?.publicHref ||
273
- ctx?.location?.href ||
274
- ctx?.location?.url?.href ||
275
- '';
451
+ const href = getLoaderHref(ctx);
276
452
 
277
- const request = baseRequest
453
+ const request = baseRequest !== undefined
278
454
  ? new Request(baseRequest, { signal })
279
455
  : new Request(href, { signal });
280
456
 
281
- const params = mapParamsForModernLoader(ctx?.params || {}, opts.hasSplat);
282
-
283
- const result = await (modernLoader as any)({
284
- request,
285
- params,
286
- context: ctx?.context?.requestContext,
287
- });
288
-
289
- if (isResponse(result)) {
290
- if (isRedirectResponse(result)) {
291
- const location = result.headers.get('Location') || '/';
292
- throwTanstackRedirect(location);
293
- }
294
- if (result.status === 404) {
295
- throw notFound();
296
- }
297
- }
457
+ const params = mapParamsForModernLoader(getLoaderParams(ctx), opts.hasSplat);
298
458
 
299
- return result as LoaderResult;
459
+ return Promise.resolve(
460
+ (modernLoader as any)({
461
+ request,
462
+ params,
463
+ context: ctx?.context?.requestContext,
464
+ }),
465
+ )
466
+ .then((result: LoaderResult) => handleModernLoaderResult(result))
467
+ .catch(handleModernLoaderError);
300
468
  } catch (err) {
301
- if (isResponse(err)) {
302
- if (isRedirectResponse(err)) {
303
- const location = err.headers.get('Location') || '/';
304
- throwTanstackRedirect(location);
305
- }
306
- if (err.status === 404) {
307
- throw notFound();
308
- }
309
- }
310
- throw err;
469
+ handleModernLoaderError(err);
311
470
  }
312
471
  };
313
472
  }
@@ -328,6 +487,7 @@ ${statements.join('\n\n')}
328
487
  export const routeTree = rootRoute.addChildren([${topLevelVars.join(', ')}]);
329
488
 
330
489
  export const router = createRouter({
490
+ ...modernTanstackRouterFastDefaults,
331
491
  routeTree,
332
492
  history: createMemoryHistory({
333
493
  initialEntries: ['/'],
@@ -339,4 +499,4 @@ export const router = createRouter({
339
499
  routerGenTs
340
500
  };
341
501
  }
342
- export { generateTanstackRouterTypesSourceForEntry, isTanstackRouterFrameworkEnabled };
502
+ export { collectCanonicalRoutesForEntry, generateTanstackRouterTypesSourceForEntry, isTanstackRouterFrameworkEnabled };
@@ -0,0 +1,11 @@
1
+ import "node:module";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { Suspense } from "react";
4
+ function wrapTanstackSsrHydrationBoundary(routerContent, shouldWrap) {
5
+ if (shouldWrap) return /*#__PURE__*/ jsx(Suspense, {
6
+ fallback: null,
7
+ children: routerContent
8
+ });
9
+ return routerContent;
10
+ }
11
+ export { wrapTanstackSsrHydrationBoundary };
@@ -1,7 +1,8 @@
1
1
  import "node:module";
2
- export * from "@tanstack/react-router";
3
- export { useMatch } from "@tanstack/react-router";
2
+ export { Asset, Await, Block, CatchBoundary, CatchNotFound, ClientOnly, DEFAULT_PROTOCOL_ALLOWLIST, DefaultGlobalNotFound, ErrorComponent, FileRoute, FileRouteLoader, HeadContent, LazyRoute, Match, MatchRoute, Matches, Navigate, NotFoundRoute, RootRoute, Route, RouteApi, Router, RouterContextProvider, RouterProvider, ScriptOnce, Scripts, ScrollRestoration, SearchParamError, cleanPath, composeRewrites, createBrowserHistory, createControlledPromise, createFileRoute, createHashHistory, createHistory, createLazyFileRoute, createLazyRoute, createLink, createMemoryHistory, createRootRoute, createRootRouteWithContext, createRoute, createRouteMask, createRouter, createRouterConfig, createSerializationAdapter, deepEqual, defaultParseSearch, defaultStringifySearch, defer, functionalUpdate, getRouteApi, interpolatePath, isMatch, isNotFound, isPlainArray, isPlainObject, isRedirect, joinPaths, lazyFn, lazyRouteComponent, linkOptions, notFound, parseSearchWith, reactUse, redirect, replaceEqualDeep, resolvePath, retainSearchParams, rootRouteId, rootRouteWithContext, stringifySearchWith, stripSearchParams, trimPath, trimPathLeft, trimPathRight, useAwaited, useBlocker, useCanGoBack, useChildMatches, useElementScrollRestoration, useHydrated, useLayoutEffect, useLinkProps, useLoaderData, useLoaderDeps, useLocation, useMatch, useMatchRoute, useMatches, useNavigate, useParams, useParentMatches, useRouteContext, useRouter, useRouterState, useSearch, useTags } from "@tanstack/react-router";
4
3
  export { Form, RouteActionResponseError, useFetcher } from "./dataMutation.mjs";
4
+ export { Outlet } from "./outlet.mjs";
5
5
  export { tanstackRouterPlugin as default, tanstackRouterPlugin } from "./plugin.mjs";
6
6
  export { Link, NavLink } from "./prefetchLink.mjs";
7
7
  export { CompositeComponent } from "./rsc/client.mjs";
8
+ export { getModernTanstackRouterFastDefaults, modernTanstackRouterFastDefaults } from "./types.mjs";
@@ -0,0 +1,18 @@
1
+ import "node:module";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { Outlet } from "@tanstack/react-router";
4
+ import { createElement, memo } from "react";
5
+ const outlet_Outlet = /*#__PURE__*/ memo(function() {
6
+ return /*#__PURE__*/ jsx(Outlet, {});
7
+ });
8
+ function withModernRouteMatchContext(component, _routeId) {
9
+ if (null == component) return component;
10
+ const Component = component;
11
+ const WrappedRouteComponent = (props)=>/*#__PURE__*/ createElement(Component, props);
12
+ const preloadable = component;
13
+ if ('function' == typeof preloadable.load) WrappedRouteComponent.load = preloadable.load.bind(preloadable);
14
+ if ('function' == typeof preloadable.preload) WrappedRouteComponent.preload = preloadable.preload.bind(preloadable);
15
+ else if ('function' == typeof preloadable.load) WrappedRouteComponent.preload = WrappedRouteComponent.load;
16
+ return WrappedRouteComponent;
17
+ }
18
+ export { outlet_Outlet as Outlet, withModernRouteMatchContext };