@tanstack/router-core 1.125.4 → 1.127.0

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 (77) hide show
  1. package/dist/cjs/Matches.cjs.map +1 -1
  2. package/dist/cjs/Matches.d.cts +1 -1
  3. package/dist/cjs/RouterProvider.d.cts +1 -0
  4. package/dist/cjs/index.d.cts +1 -2
  5. package/dist/cjs/router.cjs +26 -33
  6. package/dist/cjs/router.cjs.map +1 -1
  7. package/dist/cjs/router.d.cts +10 -57
  8. package/dist/cjs/ssr/client.cjs +0 -2
  9. package/dist/cjs/ssr/client.cjs.map +1 -1
  10. package/dist/cjs/ssr/client.d.cts +1 -2
  11. package/dist/cjs/ssr/createRequestHandler.cjs +2 -1
  12. package/dist/cjs/ssr/createRequestHandler.cjs.map +1 -1
  13. package/dist/cjs/ssr/seroval-plugins.cjs +34 -0
  14. package/dist/cjs/ssr/seroval-plugins.cjs.map +1 -0
  15. package/dist/cjs/ssr/seroval-plugins.d.cts +10 -0
  16. package/dist/cjs/ssr/server.cjs +0 -4
  17. package/dist/cjs/ssr/server.cjs.map +1 -1
  18. package/dist/cjs/ssr/server.d.cts +1 -3
  19. package/dist/cjs/ssr/ssr-client.cjs +18 -56
  20. package/dist/cjs/ssr/ssr-client.cjs.map +1 -1
  21. package/dist/cjs/ssr/ssr-client.d.cts +17 -57
  22. package/dist/cjs/ssr/ssr-server.cjs +75 -220
  23. package/dist/cjs/ssr/ssr-server.cjs.map +1 -1
  24. package/dist/cjs/ssr/ssr-server.d.cts +14 -28
  25. package/dist/cjs/ssr/transformStreamWithRouter.cjs +1 -0
  26. package/dist/cjs/ssr/transformStreamWithRouter.cjs.map +1 -1
  27. package/dist/cjs/ssr/tsrScript.cjs +1 -1
  28. package/dist/cjs/ssr/tsrScript.cjs.map +1 -1
  29. package/dist/cjs/ssr/tsrScript.d.cts +0 -1
  30. package/dist/esm/Matches.d.ts +1 -1
  31. package/dist/esm/Matches.js.map +1 -1
  32. package/dist/esm/RouterProvider.d.ts +1 -0
  33. package/dist/esm/index.d.ts +1 -2
  34. package/dist/esm/router.d.ts +10 -57
  35. package/dist/esm/router.js +26 -33
  36. package/dist/esm/router.js.map +1 -1
  37. package/dist/esm/ssr/client.d.ts +1 -2
  38. package/dist/esm/ssr/client.js +1 -3
  39. package/dist/esm/ssr/client.js.map +1 -1
  40. package/dist/esm/ssr/createRequestHandler.js +3 -2
  41. package/dist/esm/ssr/createRequestHandler.js.map +1 -1
  42. package/dist/esm/ssr/seroval-plugins.d.ts +10 -0
  43. package/dist/esm/ssr/seroval-plugins.js +34 -0
  44. package/dist/esm/ssr/seroval-plugins.js.map +1 -0
  45. package/dist/esm/ssr/server.d.ts +1 -3
  46. package/dist/esm/ssr/server.js +1 -5
  47. package/dist/esm/ssr/ssr-client.d.ts +17 -57
  48. package/dist/esm/ssr/ssr-client.js +18 -56
  49. package/dist/esm/ssr/ssr-client.js.map +1 -1
  50. package/dist/esm/ssr/ssr-server.d.ts +14 -28
  51. package/dist/esm/ssr/ssr-server.js +76 -221
  52. package/dist/esm/ssr/ssr-server.js.map +1 -1
  53. package/dist/esm/ssr/transformStreamWithRouter.js +1 -0
  54. package/dist/esm/ssr/transformStreamWithRouter.js.map +1 -1
  55. package/dist/esm/ssr/tsrScript.d.ts +0 -1
  56. package/dist/esm/ssr/tsrScript.js +1 -1
  57. package/dist/esm/ssr/tsrScript.js.map +1 -1
  58. package/package.json +3 -1
  59. package/src/Matches.ts +1 -1
  60. package/src/RouterProvider.ts +1 -0
  61. package/src/index.ts +0 -18
  62. package/src/router.ts +41 -89
  63. package/src/ssr/client.ts +1 -11
  64. package/src/ssr/createRequestHandler.ts +2 -2
  65. package/src/ssr/seroval-plugins.ts +43 -0
  66. package/src/ssr/server.ts +1 -14
  67. package/src/ssr/ssr-client.ts +35 -128
  68. package/src/ssr/ssr-server.ts +89 -307
  69. package/src/ssr/transformStreamWithRouter.ts +1 -0
  70. package/src/ssr/tsrScript.ts +4 -88
  71. package/dist/cjs/serializer.cjs +0 -146
  72. package/dist/cjs/serializer.cjs.map +0 -1
  73. package/dist/cjs/serializer.d.cts +0 -28
  74. package/dist/esm/serializer.d.ts +0 -28
  75. package/dist/esm/serializer.js +0 -146
  76. package/dist/esm/serializer.js.map +0 -1
  77. package/src/serializer.ts +0 -205
@@ -4,13 +4,11 @@ import { AnyRedirect, ResolvedRedirect } from './redirect.js';
4
4
  import { HistoryLocation, HistoryState, ParsedHistoryState, RouterHistory } from '@tanstack/history';
5
5
  import { Awaitable, ControlledPromise, NoInfer, NonNullableUpdater, PickAsRequired, Updater } from './utils.js';
6
6
  import { ParsedLocation } from './location.js';
7
- import { DeferredPromiseState } from './defer.js';
8
7
  import { AnyContext, AnyRoute, AnyRouteWithContext, MakeRemountDepsOptionsUnion, RouteMask } from './route.js';
9
8
  import { FullSearchSchema, RouteById, RoutePaths, RoutesById, RoutesByPath } from './routeInfo.js';
10
9
  import { AnyRouteMatch, MakeRouteMatch, MakeRouteMatchUnion, MatchRouteOptions } from './Matches.js';
11
10
  import { BuildLocationFn, CommitLocationOptions, NavigateFn } from './RouterProvider.js';
12
11
  import { Manifest } from './manifest.js';
13
- import { TsrSerializer } from './serializer.js';
14
12
  import { AnySchema } from './validators.js';
15
13
  import { NavigateOptions, ResolveRelativePath, ToOptions } from './link.js';
16
14
  import { NotFoundError } from './not-found.js';
@@ -202,7 +200,7 @@ export interface RouterOptions<TRouteTree extends AnyRoute, TTrailingSlashOption
202
200
  * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RouterOptionsType#dehydrate-method)
203
201
  * @link [Guide](https://tanstack.com/router/latest/docs/framework/react/guide/external-data-loading#critical-dehydrationhydration)
204
202
  */
205
- dehydrate?: () => TDehydrated;
203
+ dehydrate?: () => Awaitable<TDehydrated>;
206
204
  /**
207
205
  * A function that will be called when the router is hydrated.
208
206
  *
@@ -340,6 +338,7 @@ export interface BuildNextOptions {
340
338
  href?: string;
341
339
  _fromLocation?: ParsedLocation;
342
340
  unsafeRelative?: 'path';
341
+ _isNavigate?: boolean;
343
342
  }
344
343
  type NavigationEventInfo = {
345
344
  fromLocation?: ParsedLocation;
@@ -348,7 +347,7 @@ type NavigationEventInfo = {
348
347
  hrefChanged: boolean;
349
348
  hashChanged: boolean;
350
349
  };
351
- export type RouterEvents = {
350
+ export interface RouterEvents {
352
351
  onBeforeNavigate: {
353
352
  type: 'onBeforeNavigate';
354
353
  } & NavigationEventInfo;
@@ -364,20 +363,17 @@ export type RouterEvents = {
364
363
  onBeforeRouteMount: {
365
364
  type: 'onBeforeRouteMount';
366
365
  } & NavigationEventInfo;
367
- onInjectedHtml: {
368
- type: 'onInjectedHtml';
369
- promise: Promise<string>;
370
- };
371
366
  onRendered: {
372
367
  type: 'onRendered';
373
368
  } & NavigationEventInfo;
374
- };
369
+ }
375
370
  export type RouterEvent = RouterEvents[keyof RouterEvents];
376
371
  export type ListenerFn<TEvent extends RouterEvent> = (event: TEvent) => void;
377
372
  export type RouterListener<TRouterEvent extends RouterEvent> = {
378
373
  eventType: TRouterEvent['type'];
379
374
  fn: ListenerFn<TRouterEvent>;
380
375
  };
376
+ export type SubscribeFn = <TType extends keyof RouterEvents>(eventType: TType, fn: ListenerFn<RouterEvents[TType]>) => () => void;
381
377
  export interface MatchRoutesOpts {
382
378
  preload?: boolean;
383
379
  throwOnError?: boolean;
@@ -391,10 +387,6 @@ export type RouterContextOptions<TRouteTree extends AnyRoute> = AnyContext exten
391
387
  context: InferRouterContext<TRouteTree>;
392
388
  };
393
389
  export type RouterConstructorOptions<TRouteTree extends AnyRoute, TTrailingSlashOption extends TrailingSlashOption, TDefaultStructuralSharingOption extends boolean, TRouterHistory extends RouterHistory, TDehydrated extends Record<string, any>> = Omit<RouterOptions<TRouteTree, TTrailingSlashOption, TDefaultStructuralSharingOption, TRouterHistory, TDehydrated>, 'context'> & RouterContextOptions<TRouteTree>;
394
- export interface RouterErrorSerializer<TSerializedError> {
395
- serialize: (err: unknown) => TSerializedError;
396
- deserialize: (err: TSerializedError) => unknown;
397
- }
398
390
  export type PreloadRouteFn<TRouteTree extends AnyRoute, TTrailingSlashOption extends TrailingSlashOption, TDefaultStructuralSharingOption extends boolean, TRouterHistory extends RouterHistory> = <TFrom extends RoutePaths<TRouteTree> | string = string, TTo extends string | undefined = undefined, TMaskFrom extends RoutePaths<TRouteTree> | string = TFrom, TMaskTo extends string = ''>(opts: NavigateOptions<RouterCore<TRouteTree, TTrailingSlashOption, TDefaultStructuralSharingOption, TRouterHistory>, TFrom, TTo, TMaskFrom, TMaskTo>) => Promise<Array<AnyRouteMatch> | undefined>;
399
391
  export type MatchRouteFn<TRouteTree extends AnyRoute, TTrailingSlashOption extends TrailingSlashOption, TDefaultStructuralSharingOption extends boolean, TRouterHistory extends RouterHistory> = <TFrom extends RoutePaths<TRouteTree> = '/', TTo extends string | undefined = undefined, TResolved = ResolveRelativePath<TFrom, NoInfer<TTo>>>(location: ToOptions<RouterCore<TRouteTree, TTrailingSlashOption, TDefaultStructuralSharingOption, TRouterHistory>, TFrom, TTo>, opts?: MatchRouteOptions) => false | RouteById<TRouteTree, TResolved>['types']['allParams'];
400
392
  export type UpdateFn<TRouteTree extends AnyRoute, TTrailingSlashOption extends TrailingSlashOption, TDefaultStructuralSharingOption extends boolean, TRouterHistory extends RouterHistory, TDehydrated extends Record<string, any>> = (newOptions: RouterConstructorOptions<TRouteTree, TTrailingSlashOption, TDefaultStructuralSharingOption, TRouterHistory, TDehydrated>) => void;
@@ -415,7 +407,6 @@ export type LoadFn = (opts?: {
415
407
  }) => Promise<void>;
416
408
  export type CommitLocationFn = ({ viewTransition, ignoreBlocker, ...next }: ParsedLocation & CommitLocationOptions) => Promise<void>;
417
409
  export type StartTransitionFn = (fn: () => void) => void;
418
- export type SubscribeFn = <TType extends keyof RouterEvents>(eventType: TType, fn: ListenerFn<RouterEvents[TType]>) => () => void;
419
410
  export interface MatchRoutesFn {
420
411
  (pathname: string, locationSearch: AnySchema, opts?: MatchRoutesOpts): Array<AnyRouteMatch>;
421
412
  (next: ParsedLocation, opts?: MatchRoutesOpts): Array<AnyRouteMatch>;
@@ -428,18 +419,15 @@ export type ResolveRedirect = (err: AnyRedirect) => ResolvedRedirect;
428
419
  export type ClearCacheFn<TRouter extends AnyRouter> = (opts?: {
429
420
  filter?: (d: MakeRouteMatchUnion<TRouter>) => boolean;
430
421
  }) => void;
431
- export interface ServerSrr {
422
+ export interface ServerSsr {
432
423
  injectedHtml: Array<InjectedHtmlEntry>;
433
424
  injectHtml: (getHtml: () => string | Promise<string>) => Promise<void>;
434
425
  injectScript: (getScript: () => string | Promise<string>, opts?: {
435
426
  logScript?: boolean;
436
427
  }) => Promise<void>;
437
- streamValue: (key: string, value: any) => void;
438
- streamedKeys: Set<string>;
439
- onMatchSettled: (opts: {
440
- router: AnyRouter;
441
- match: AnyRouteMatch;
442
- }) => any;
428
+ isDehydrated: () => boolean;
429
+ onRenderFinished: (listener: () => void) => void;
430
+ dehydrate: () => Promise<void>;
443
431
  }
444
432
  export type AnyRouterWithContext<TContext> = RouterCore<AnyRouteWithContext<TContext>, any, any, any, any>;
445
433
  export type AnyRouter = RouterCore<any, any, any, any, any>;
@@ -458,25 +446,6 @@ export declare function defaultSerializeError(err: unknown): {
458
446
  } | {
459
447
  data: unknown;
460
448
  };
461
- export interface ExtractedBaseEntry {
462
- dataType: '__beforeLoadContext' | 'loaderData';
463
- type: string;
464
- path: Array<string>;
465
- id: number;
466
- matchIndex: number;
467
- }
468
- export interface ExtractedStream extends ExtractedBaseEntry {
469
- type: 'stream';
470
- streamState: StreamState;
471
- }
472
- export interface ExtractedPromise extends ExtractedBaseEntry {
473
- type: 'promise';
474
- promiseState: DeferredPromiseState<any>;
475
- }
476
- export type ExtractedEntry = ExtractedStream | ExtractedPromise;
477
- export type StreamState = {
478
- promises: Array<ControlledPromise<string | null>>;
479
- };
480
449
  export type TrailingSlashOption = 'always' | 'never' | 'preserve';
481
450
  export declare function getLocationChangeInfo(routerState: {
482
451
  resolvedLocation?: ParsedLocation;
@@ -567,24 +536,8 @@ export declare class RouterCore<in out TRouteTree extends AnyRoute, in out TTrai
567
536
  matchRoute: MatchRouteFn<TRouteTree, TTrailingSlashOption, TDefaultStructuralSharingOption, TRouterHistory>;
568
537
  ssr?: {
569
538
  manifest: Manifest | undefined;
570
- serializer: TsrSerializer;
571
- };
572
- serverSsr?: {
573
- injectedHtml: Array<InjectedHtmlEntry>;
574
- injectHtml: (getHtml: () => string | Promise<string>) => Promise<void>;
575
- injectScript: (getScript: () => string | Promise<string>, opts?: {
576
- logScript?: boolean;
577
- }) => Promise<void>;
578
- streamValue: (key: string, value: any) => void;
579
- streamedKeys: Set<string>;
580
- onMatchSettled: (opts: {
581
- router: AnyRouter;
582
- match: AnyRouteMatch;
583
- }) => any;
584
- };
585
- clientSsr?: {
586
- getStreamedValue: <T>(key: string) => T | undefined;
587
539
  };
540
+ serverSsr?: ServerSsr;
588
541
  _handleNotFound: (matches: Array<AnyRouteMatch>, err: NotFoundError, { updateMatch, }?: {
589
542
  updateMatch?: (id: string, updater: (match: AnyRouteMatch) => AnyRouteMatch) => void;
590
543
  }) => void;
@@ -229,10 +229,10 @@ class RouterCore {
229
229
  const build = (dest = {}) => {
230
230
  var _a;
231
231
  const currentLocation = dest._fromLocation || this.latestLocation;
232
- const allFromMatches = this.matchRoutes(currentLocation, {
232
+ const allCurrentLocationMatches = this.matchRoutes(currentLocation, {
233
233
  _buildLocation: true
234
234
  });
235
- const lastMatch = last(allFromMatches);
235
+ const lastMatch = last(allCurrentLocationMatches);
236
236
  let fromPath = lastMatch.fullPath;
237
237
  const toPath = dest.to ? this.resolvePathWithBase(fromPath, `${dest.to}`) : this.resolvePathWithBase(fromPath, ".");
238
238
  const routeIsChanging = !!dest.to && !this.comparePaths(dest.to.toString(), fromPath) && !this.comparePaths(toPath, fromPath);
@@ -240,11 +240,20 @@ class RouterCore {
240
240
  fromPath = currentLocation.pathname;
241
241
  } else if (routeIsChanging && dest.from) {
242
242
  fromPath = dest.from;
243
- const existingFrom = [...allFromMatches].reverse().find((d) => {
244
- return this.comparePaths(d.fullPath, fromPath);
245
- });
246
- if (!existingFrom) {
247
- console.warn(`Could not find match for from: ${fromPath}`);
243
+ if (process.env.NODE_ENV !== "production" && dest._isNavigate) {
244
+ const allFromMatches = this.getMatchedRoutes(
245
+ dest.from,
246
+ void 0
247
+ ).matchedRoutes;
248
+ const matchedFrom = [...allCurrentLocationMatches].reverse().find((d) => {
249
+ return this.comparePaths(d.fullPath, fromPath);
250
+ });
251
+ const matchedCurrent = [...allFromMatches].reverse().find((d) => {
252
+ return this.comparePaths(d.fullPath, currentLocation.pathname);
253
+ });
254
+ if (!matchedFrom && !matchedCurrent) {
255
+ console.warn(`Could not find match for from: ${fromPath}`);
256
+ }
248
257
  }
249
258
  }
250
259
  const fromSearch = lastMatch.search;
@@ -482,7 +491,8 @@ class RouterCore {
482
491
  return this.buildAndCommitLocation({
483
492
  ...rest,
484
493
  href,
485
- to
494
+ to,
495
+ _isNavigate: true
486
496
  });
487
497
  };
488
498
  this.beforeLoad = () => {
@@ -735,7 +745,7 @@ class RouterCore {
735
745
  triggerOnReady();
736
746
  }
737
747
  const handleRedirectAndNotFound = (match, err) => {
738
- var _a, _b, _c, _d;
748
+ var _a, _b, _c;
739
749
  if (isRedirect(err) || isNotFound(err)) {
740
750
  if (isRedirect(err)) {
741
751
  if (err.redirectHandled) {
@@ -768,10 +778,6 @@ class RouterCore {
768
778
  this._handleNotFound(matches, err, {
769
779
  updateMatch
770
780
  });
771
- (_d = this.serverSsr) == null ? void 0 : _d.onMatchSettled({
772
- router: this,
773
- match: this.getMatch(match.id)
774
- });
775
781
  throw err;
776
782
  }
777
783
  }
@@ -958,7 +964,7 @@ class RouterCore {
958
964
  cause: preload ? "preload" : cause,
959
965
  matches
960
966
  };
961
- const beforeLoadContext = await ((_d = (_c = route.options).beforeLoad) == null ? void 0 : _d.call(_c, beforeLoadFnContext)) ?? {};
967
+ const beforeLoadContext = await ((_d = (_c = route.options).beforeLoad) == null ? void 0 : _d.call(_c, beforeLoadFnContext));
962
968
  if (isRedirect(beforeLoadContext) || isNotFound(beforeLoadContext)) {
963
969
  handleSerialError(index, beforeLoadContext, "BEFORE_LOAD");
964
970
  }
@@ -993,12 +999,11 @@ class RouterCore {
993
999
  validResolvedMatches.forEach(({ id: matchId, routeId }, index) => {
994
1000
  matchPromises.push(
995
1001
  (async () => {
996
- var _a2, _b2;
997
1002
  let loaderShouldRunAsync = false;
998
1003
  let loaderIsRunningAsync = false;
999
1004
  const route = this.looseRoutesById[routeId];
1000
1005
  const executeHead = async () => {
1001
- var _a3, _b3, _c2, _d2, _e, _f;
1006
+ var _a2, _b2, _c2, _d2, _e, _f;
1002
1007
  const match = this.getMatch(matchId);
1003
1008
  if (!match) {
1004
1009
  return;
@@ -1009,7 +1014,7 @@ class RouterCore {
1009
1014
  params: match.params,
1010
1015
  loaderData: match.loaderData
1011
1016
  };
1012
- const headFnContent = await ((_b3 = (_a3 = route.options).head) == null ? void 0 : _b3.call(_a3, assetContext));
1017
+ const headFnContent = await ((_b2 = (_a2 = route.options).head) == null ? void 0 : _b2.call(_a2, assetContext));
1013
1018
  const meta = headFnContent == null ? void 0 : headFnContent.meta;
1014
1019
  const links = headFnContent == null ? void 0 : headFnContent.links;
1015
1020
  const headScripts = headFnContent == null ? void 0 : headFnContent.scripts;
@@ -1039,10 +1044,6 @@ class RouterCore {
1039
1044
  ...prev,
1040
1045
  ...head
1041
1046
  }));
1042
- (_a2 = this.serverSsr) == null ? void 0 : _a2.onMatchSettled({
1043
- router: this,
1044
- match: this.getMatch(matchId)
1045
- });
1046
1047
  return this.getMatch(matchId);
1047
1048
  } else {
1048
1049
  await potentialPendingMinPromise();
@@ -1091,7 +1092,7 @@ class RouterCore {
1091
1092
  preload: !!preload && !this.state.matches.find((d) => d.id === matchId)
1092
1093
  }));
1093
1094
  const runLoader = async () => {
1094
- var _a3, _b3, _c2, _d2, _e;
1095
+ var _a2, _b2, _c2, _d2;
1095
1096
  try {
1096
1097
  try {
1097
1098
  if (!this.isServer || this.isServer && this.getMatch(matchId).ssr === true) {
@@ -1101,7 +1102,7 @@ class RouterCore {
1101
1102
  ...prev,
1102
1103
  isFetching: "loader"
1103
1104
  }));
1104
- const loaderData = await ((_b3 = (_a3 = route.options).loader) == null ? void 0 : _b3.call(_a3, getLoaderContext()));
1105
+ const loaderData = await ((_b2 = (_a2 = route.options).loader) == null ? void 0 : _b2.call(_a2, getLoaderContext()));
1105
1106
  handleRedirectAndNotFound(
1106
1107
  this.getMatch(matchId),
1107
1108
  loaderData
@@ -1144,10 +1145,6 @@ class RouterCore {
1144
1145
  ...head
1145
1146
  }));
1146
1147
  }
1147
- (_e = this.serverSsr) == null ? void 0 : _e.onMatchSettled({
1148
- router: this,
1149
- match: this.getMatch(matchId)
1150
- });
1151
1148
  } catch (err) {
1152
1149
  const head = await executeHead();
1153
1150
  updateMatch(matchId, (prev) => ({
@@ -1190,10 +1187,6 @@ class RouterCore {
1190
1187
  ...prev,
1191
1188
  ...head
1192
1189
  }));
1193
- (_b2 = this.serverSsr) == null ? void 0 : _b2.onMatchSettled({
1194
- router: this,
1195
- match: this.getMatch(matchId)
1196
- });
1197
1190
  }
1198
1191
  }
1199
1192
  if (!loaderIsRunningAsync) {
@@ -1465,7 +1458,7 @@ class RouterCore {
1465
1458
  parseSearch: options.parseSearch ?? defaultParseSearch
1466
1459
  });
1467
1460
  if (typeof document !== "undefined") {
1468
- window.__TSR_ROUTER__ = this;
1461
+ self.__TSR_ROUTER__ = this;
1469
1462
  }
1470
1463
  }
1471
1464
  get state() {
@@ -1611,7 +1604,7 @@ class RouterCore {
1611
1604
  error: void 0,
1612
1605
  paramsError: parseErrors[index],
1613
1606
  __routeContext: {},
1614
- __beforeLoadContext: {},
1607
+ __beforeLoadContext: void 0,
1615
1608
  context: {},
1616
1609
  abortController: new AbortController(),
1617
1610
  fetchCount: 0,