@tanstack/router-core 1.171.14 → 1.171.16-pre.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 (139) hide show
  1. package/dist/cjs/Matches.cjs.map +1 -1
  2. package/dist/cjs/Matches.d.cts +3 -12
  3. package/dist/cjs/await-signal.cjs +21 -0
  4. package/dist/cjs/await-signal.cjs.map +1 -0
  5. package/dist/cjs/await-signal.d.cts +1 -0
  6. package/dist/cjs/index.cjs +3 -1
  7. package/dist/cjs/index.d.cts +3 -2
  8. package/dist/cjs/isServer/client.cjs +2 -0
  9. package/dist/cjs/isServer/client.cjs.map +1 -1
  10. package/dist/cjs/isServer/client.d.cts +1 -0
  11. package/dist/cjs/isServer/development.cjs +2 -0
  12. package/dist/cjs/isServer/development.cjs.map +1 -1
  13. package/dist/cjs/isServer/development.d.cts +1 -0
  14. package/dist/cjs/isServer/server.cjs +2 -0
  15. package/dist/cjs/isServer/server.cjs.map +1 -1
  16. package/dist/cjs/isServer/server.d.cts +1 -0
  17. package/dist/cjs/load-client.cjs +1470 -0
  18. package/dist/cjs/load-client.cjs.map +1 -0
  19. package/dist/cjs/load-client.d.cts +147 -0
  20. package/dist/cjs/load-server.cjs +565 -0
  21. package/dist/cjs/load-server.cjs.map +1 -0
  22. package/dist/cjs/load-server.d.cts +16 -0
  23. package/dist/cjs/redirect.cjs.map +1 -1
  24. package/dist/cjs/redirect.d.cts +0 -1
  25. package/dist/cjs/route.cjs.map +1 -1
  26. package/dist/cjs/router.cjs +187 -445
  27. package/dist/cjs/router.cjs.map +1 -1
  28. package/dist/cjs/router.d.cts +62 -52
  29. package/dist/cjs/scroll-restoration.cjs +27 -34
  30. package/dist/cjs/scroll-restoration.cjs.map +1 -1
  31. package/dist/cjs/ssr/client.cjs +2 -2
  32. package/dist/cjs/ssr/createRequestHandler.cjs +60 -9
  33. package/dist/cjs/ssr/createRequestHandler.cjs.map +1 -1
  34. package/dist/cjs/ssr/createRequestHandler.d.cts +1 -0
  35. package/dist/cjs/ssr/handlerCallback.cjs +49 -4
  36. package/dist/cjs/ssr/handlerCallback.cjs.map +1 -1
  37. package/dist/cjs/ssr/handlerCallback.d.cts +3 -0
  38. package/dist/cjs/ssr/server.cjs +4 -0
  39. package/dist/cjs/ssr/server.d.cts +2 -2
  40. package/dist/cjs/ssr/ssr-client.d.cts +1 -10
  41. package/dist/cjs/ssr/ssr-match-id.cjs +2 -2
  42. package/dist/cjs/ssr/ssr-match-id.cjs.map +1 -1
  43. package/dist/cjs/ssr/ssr-server.cjs +6 -6
  44. package/dist/cjs/ssr/ssr-server.cjs.map +1 -1
  45. package/dist/cjs/ssr/transformStreamWithRouter.cjs +27 -1
  46. package/dist/cjs/ssr/transformStreamWithRouter.cjs.map +1 -1
  47. package/dist/cjs/ssr/transformStreamWithRouter.d.cts +2 -0
  48. package/dist/cjs/ssr/types.d.cts +0 -1
  49. package/dist/cjs/stores.cjs +30 -104
  50. package/dist/cjs/stores.cjs.map +1 -1
  51. package/dist/cjs/stores.d.cts +7 -32
  52. package/dist/cjs/utils.cjs +0 -4
  53. package/dist/cjs/utils.cjs.map +1 -1
  54. package/dist/esm/Matches.d.ts +3 -12
  55. package/dist/esm/Matches.js.map +1 -1
  56. package/dist/esm/await-signal.d.ts +1 -0
  57. package/dist/esm/await-signal.js +21 -0
  58. package/dist/esm/await-signal.js.map +1 -0
  59. package/dist/esm/index.d.ts +3 -2
  60. package/dist/esm/index.js +3 -2
  61. package/dist/esm/isServer/client.d.ts +1 -0
  62. package/dist/esm/isServer/client.js +2 -1
  63. package/dist/esm/isServer/client.js.map +1 -1
  64. package/dist/esm/isServer/development.d.ts +1 -0
  65. package/dist/esm/isServer/development.js +2 -1
  66. package/dist/esm/isServer/development.js.map +1 -1
  67. package/dist/esm/isServer/server.d.ts +1 -0
  68. package/dist/esm/isServer/server.js +2 -1
  69. package/dist/esm/isServer/server.js.map +1 -1
  70. package/dist/esm/load-client.d.ts +147 -0
  71. package/dist/esm/load-client.js +1462 -0
  72. package/dist/esm/load-client.js.map +1 -0
  73. package/dist/esm/load-server.d.ts +16 -0
  74. package/dist/esm/load-server.js +565 -0
  75. package/dist/esm/load-server.js.map +1 -0
  76. package/dist/esm/redirect.d.ts +0 -1
  77. package/dist/esm/redirect.js.map +1 -1
  78. package/dist/esm/route.js.map +1 -1
  79. package/dist/esm/router.d.ts +62 -52
  80. package/dist/esm/router.js +188 -446
  81. package/dist/esm/router.js.map +1 -1
  82. package/dist/esm/scroll-restoration.js +27 -34
  83. package/dist/esm/scroll-restoration.js.map +1 -1
  84. package/dist/esm/ssr/client.js +1 -1
  85. package/dist/esm/ssr/createRequestHandler.d.ts +1 -0
  86. package/dist/esm/ssr/createRequestHandler.js +61 -11
  87. package/dist/esm/ssr/createRequestHandler.js.map +1 -1
  88. package/dist/esm/ssr/handlerCallback.d.ts +3 -0
  89. package/dist/esm/ssr/handlerCallback.js +47 -5
  90. package/dist/esm/ssr/handlerCallback.js.map +1 -1
  91. package/dist/esm/ssr/server.d.ts +2 -2
  92. package/dist/esm/ssr/server.js +3 -3
  93. package/dist/esm/ssr/ssr-client.d.ts +1 -10
  94. package/dist/esm/ssr/ssr-match-id.js +2 -2
  95. package/dist/esm/ssr/ssr-match-id.js.map +1 -1
  96. package/dist/esm/ssr/ssr-server.js +6 -6
  97. package/dist/esm/ssr/ssr-server.js.map +1 -1
  98. package/dist/esm/ssr/transformStreamWithRouter.d.ts +2 -0
  99. package/dist/esm/ssr/transformStreamWithRouter.js +27 -1
  100. package/dist/esm/ssr/transformStreamWithRouter.js.map +1 -1
  101. package/dist/esm/ssr/types.d.ts +0 -1
  102. package/dist/esm/stores.d.ts +7 -32
  103. package/dist/esm/stores.js +30 -104
  104. package/dist/esm/stores.js.map +1 -1
  105. package/dist/esm/utils.js +1 -4
  106. package/dist/esm/utils.js.map +1 -1
  107. package/package.json +3 -3
  108. package/src/Matches.ts +6 -21
  109. package/src/await-signal.ts +27 -0
  110. package/src/index.ts +1 -3
  111. package/src/isServer/client.ts +1 -0
  112. package/src/isServer/development.ts +1 -0
  113. package/src/isServer/server.ts +1 -0
  114. package/src/load-client.ts +2701 -0
  115. package/src/load-server.ts +849 -0
  116. package/src/redirect.ts +0 -1
  117. package/src/route.ts +2 -11
  118. package/src/router.ts +380 -774
  119. package/src/scroll-restoration.ts +40 -56
  120. package/src/ssr/createRequestHandler.ts +109 -16
  121. package/src/ssr/handlerCallback.ts +76 -10
  122. package/src/ssr/server.ts +4 -1
  123. package/src/ssr/ssr-client.ts +1 -310
  124. package/src/ssr/ssr-match-id.ts +11 -2
  125. package/src/ssr/ssr-server.ts +9 -8
  126. package/src/ssr/transformStreamWithRouter.ts +37 -1
  127. package/src/ssr/types.ts +0 -1
  128. package/src/stores.ts +46 -208
  129. package/dist/cjs/load-matches.cjs +0 -658
  130. package/dist/cjs/load-matches.cjs.map +0 -1
  131. package/dist/cjs/load-matches.d.cts +0 -18
  132. package/dist/cjs/ssr/ssr-client.cjs +0 -183
  133. package/dist/cjs/ssr/ssr-client.cjs.map +0 -1
  134. package/dist/esm/load-matches.d.ts +0 -18
  135. package/dist/esm/load-matches.js +0 -656
  136. package/dist/esm/load-matches.js.map +0 -1
  137. package/dist/esm/ssr/ssr-client.js +0 -183
  138. package/dist/esm/ssr/ssr-client.js.map +0 -1
  139. package/src/load-matches.ts +0 -1278
@@ -7,12 +7,15 @@ const require_scroll_restoration = require("./scroll-restoration.cjs");
7
7
  const require_searchParams = require("./searchParams.cjs");
8
8
  const require_root = require("./root.cjs");
9
9
  const require_redirect = require("./redirect.cjs");
10
- const require_load_matches = require("./load-matches.cjs");
10
+ const require_load_client = require("./load-client.cjs");
11
11
  const require_rewrite = require("./rewrite.cjs");
12
12
  const require_stores = require("./stores.cjs");
13
13
  let _tanstack_history = require("@tanstack/history");
14
14
  let _tanstack_router_core_isServer = require("@tanstack/router-core/isServer");
15
15
  //#region src/router.ts
16
+ function routeNeedsLoad(route) {
17
+ return route.options.loader || route.options.beforeLoad || route.lazyFn || route.options.component?.preload || route.options.pendingComponent?.preload;
18
+ }
16
19
  /**
17
20
  * Convert an unknown error into a minimal, serializable object.
18
21
  * Includes name and message (and stack in development).
@@ -39,17 +42,33 @@ const trailingSlashOptions = {
39
42
  * resolved locations.
40
43
  */
41
44
  function getLocationChangeInfo(location, resolvedLocation) {
42
- const fromLocation = resolvedLocation;
43
- const toLocation = location;
44
45
  return {
45
- fromLocation,
46
- toLocation,
47
- pathChanged: fromLocation?.pathname !== toLocation.pathname,
48
- hrefChanged: fromLocation?.href !== toLocation.href,
49
- hashChanged: fromLocation?.hash !== toLocation.hash
46
+ fromLocation: resolvedLocation,
47
+ toLocation: location,
48
+ pathChanged: resolvedLocation?.pathname !== location.pathname,
49
+ hrefChanged: resolvedLocation?.href !== location.href,
50
+ hashChanged: resolvedLocation?.hash !== location.hash
50
51
  };
51
52
  }
52
- const locationHistoryActions = /* @__PURE__ */ new WeakMap();
53
+ /**
54
+ * Return only state owned by the application, excluding volatile history
55
+ * bookkeeping. Mask payloads (`__tempLocation`/`__tempKey`) are kept: they
56
+ * distinguish otherwise-identical locations.
57
+ */
58
+ function _getUserHistoryState({ key: _key, __TSR_key: _tsrKey, __TSR_index: _tsrIndex, __hashScrollIntoViewOptions: _hashScroll, ...state }) {
59
+ return state;
60
+ }
61
+ /** Run route lifecycle callbacks in leave/enter/stay phases. */
62
+ function runRouteLifecycle(router, previous, matches, isCurrent) {
63
+ for (const match of previous) {
64
+ if (isCurrent?.() === false) return;
65
+ if (!matches.some((candidate) => candidate.routeId === match.routeId)) router.routesById[match.routeId].options.onLeave?.(match);
66
+ }
67
+ for (const match of matches) {
68
+ if (isCurrent?.() === false) return;
69
+ router.routesById[match.routeId].options[previous.some((candidate) => candidate.routeId === match.routeId) ? "onStay" : "onEnter"]?.(match);
70
+ }
71
+ }
53
72
  /**
54
73
  * Core, framework-agnostic router engine that powers TanStack Router.
55
74
  *
@@ -66,12 +85,15 @@ var RouterCore = class {
66
85
  constructor(options, getStoreConfig) {
67
86
  this.tempLocationKey = `${Math.round(Math.random() * 1e7)}`;
68
87
  this._scroll = { next: true };
69
- this.shouldViewTransition = void 0;
70
- this.isViewTransitionTypesSupported = void 0;
71
88
  this.subscribers = /* @__PURE__ */ new Set();
89
+ this._cache = /* @__PURE__ */ new Map();
90
+ this._committed = [];
72
91
  this.routeBranchCache = /* @__PURE__ */ new WeakMap();
73
92
  this.lightweightCache = /* @__PURE__ */ new WeakMap();
74
- this.startTransition = (fn) => fn();
93
+ this.startTransition = async (fn) => {
94
+ fn();
95
+ return false;
96
+ };
75
97
  this.update = (newOptions) => {
76
98
  if (process.env.NODE_ENV !== "production") {
77
99
  if (newOptions.notFoundRoute) console.warn("The notFoundRoute API is deprecated and will be removed in the next major version. See https://tanstack.com/router/v1/docs/framework/react/guide/not-found-errors#migrating-from-notfoundroute for more info.");
@@ -84,7 +106,7 @@ var RouterCore = class {
84
106
  ...prevOptions,
85
107
  ...newOptions
86
108
  };
87
- this.isServer = this.options.isServer ?? typeof document === "undefined";
109
+ this.isServer = this.options.isServer ?? _tanstack_router_core_isServer.isServer ?? typeof document === "undefined";
88
110
  this.protocolAllowlist = new Set(this.options.protocolAllowlist);
89
111
  if (this.options.pathParamsAllowedCharacters) this.pathParamsDecoder = require_path.compileDecodeCharMap(this.options.pathParamsAllowedCharacters);
90
112
  if (!this.history || this.options.history && this.options.history !== this.history) if (!this.options.history) {
@@ -115,10 +137,9 @@ var RouterCore = class {
115
137
  if (!this.stores && this.latestLocation) {
116
138
  const config = this.getStoreConfig(this);
117
139
  this.batch = config.batch;
118
- this.stores = require_stores.createRouterStores(getInitialRouterState(this.latestLocation), config);
140
+ this.stores = require_stores.createRouterStores(this.latestLocation, config);
119
141
  if (!(_tanstack_router_core_isServer.isServer ?? this.isServer)) require_scroll_restoration.setupScrollRestoration(this);
120
142
  }
121
- let needsLocationUpdate = false;
122
143
  const nextBasepath = this.options.basepath ?? "/";
123
144
  const nextRewriteOption = this.options.rewrite;
124
145
  if (basepathWasUnset || prevBasepath !== nextBasepath || prevRewriteOption !== nextRewriteOption) {
@@ -129,10 +150,8 @@ var RouterCore = class {
129
150
  if (nextRewriteOption) rewrites.push(nextRewriteOption);
130
151
  this.rewrite = rewrites.length === 0 ? void 0 : rewrites.length === 1 ? rewrites[0] : require_rewrite.composeRewrites(rewrites);
131
152
  if (this.history) this.updateLatestLocation();
132
- needsLocationUpdate = true;
153
+ if (this.stores) this.stores.location.set(this.latestLocation);
133
154
  }
134
- if (needsLocationUpdate && this.stores) this.stores.location.set(this.latestLocation);
135
- if (typeof window !== "undefined" && "CSS" in window && typeof window.CSS?.supports === "function") this.isViewTransitionTypesSupported = window.CSS.supports("selector(:active-view-transition-type(a))");
136
155
  };
137
156
  this.updateLatestLocation = () => {
138
157
  this.latestLocation = this.parseLocation(this.history.location, this.latestLocation);
@@ -155,9 +174,11 @@ var RouterCore = class {
155
174
  };
156
175
  };
157
176
  this.emit = (routerEvent) => {
158
- this.subscribers.forEach((listener) => {
159
- if (listener.eventType === routerEvent.type) listener.fn(routerEvent);
160
- });
177
+ for (const listener of this.subscribers) if (listener.eventType === routerEvent.type) try {
178
+ listener.fn(routerEvent);
179
+ } catch (e) {
180
+ console.error(e);
181
+ }
161
182
  };
162
183
  this.parseLocation = (locationToParse, previousLocation) => {
163
184
  const parse = ({ pathname, search, hash, href, state }) => {
@@ -221,33 +242,18 @@ var RouterCore = class {
221
242
  return this.matchRoutesInternal(pathnameOrNext, locationSearchOrOpts);
222
243
  };
223
244
  this.getMatchedRoutes = (pathname) => {
224
- return getMatchedRoutes({
225
- pathname,
226
- routesById: this.routesById,
227
- processedTree: this.processedTree
228
- });
229
- };
230
- this.cancelMatch = (id) => {
231
- const match = this.getMatch(id);
232
- if (!match) return;
233
- match.abortController.abort();
234
- clearTimeout(match._nonReactive.pendingTimeout);
235
- match._nonReactive.pendingTimeout = void 0;
236
- };
237
- this.cancelMatches = () => {
238
- this.stores.pendingIds.get().forEach((matchId) => {
239
- this.cancelMatch(matchId);
240
- });
241
- this.stores.matchesId.get().forEach((matchId) => {
242
- if (this.stores.pendingMatchStores.has(matchId)) return;
243
- const match = this.stores.matchStores.get(matchId)?.get();
244
- if (!match) return;
245
- if (match.status === "pending" || match.isFetching === "loader") this.cancelMatch(matchId);
246
- });
245
+ const routeParams = Object.create(null);
246
+ const match = require_new_process_route_tree.findRouteMatch(require_path.trimPathRight(pathname), this.processedTree, true);
247
+ if (match) Object.assign(routeParams, match.rawParams);
248
+ return {
249
+ matchedRoutes: match?.branch || [this.routesById["__root__"]],
250
+ routeParams,
251
+ foundRoute: match?.route
252
+ };
247
253
  };
248
254
  this.buildLocation = (opts) => {
249
255
  const build = (dest = {}) => {
250
- const currentLocation = dest._fromLocation || this.pendingBuiltLocation || this.latestLocation;
256
+ const currentLocation = dest._fromLocation || this._pendingLocation || this.latestLocation;
251
257
  const lightweightResult = this.matchRoutesLightweight(currentLocation);
252
258
  if (dest.from && process.env.NODE_ENV !== "production" && dest._isNavigate) {
253
259
  const allFromMatches = this.getMatchedRoutes(dest.from).matchedRoutes;
@@ -265,7 +271,7 @@ var RouterCore = class {
265
271
  const fromParams = Object.assign(Object.create(null), lightweightResult.params);
266
272
  const sourcePath = destTo?.charCodeAt(0) === 47 ? "/" : this.resolvePathWithBase(defaultedFromPath, ".");
267
273
  const nextTo = destTo ? this.resolvePathWithBase(sourcePath, destTo) : sourcePath;
268
- const nextParams = dest.params === false || dest.params === null ? Object.create(null) : (dest.params ?? true) === true ? fromParams : Object.assign(fromParams, require_utils.functionalUpdate(dest.params, fromParams));
274
+ const nextParams = resolveNextParams(dest.params, fromParams);
269
275
  const destRoute = this.routesByPath[require_path.trimPathRight(nextTo)];
270
276
  let destRoutes;
271
277
  if (destRoute) destRoutes = this.getRouteBranch(destRoute);
@@ -304,12 +310,7 @@ var RouterCore = class {
304
310
  });
305
311
  nextSearch = validatedSearch;
306
312
  }
307
- nextSearch = applySearchMiddleware({
308
- search: nextSearch,
309
- dest,
310
- destRoutes,
311
- _includeValidateSearch: opts._includeValidateSearch
312
- });
313
+ nextSearch = applySearchMiddleware(nextSearch, dest, destRoutes, opts._includeValidateSearch);
313
314
  nextSearch = require_utils.nullReplaceEqualDeep(fromSearch, nextSearch);
314
315
  const searchStr = this.options.stringifySearch(nextSearch);
315
316
  const hash = dest.hash === true ? currentLocation.hash : dest.hash ? require_utils.functionalUpdate(dest.hash, currentLocation.hash) : void 0;
@@ -354,7 +355,7 @@ var RouterCore = class {
354
355
  if (match) {
355
356
  Object.assign(params, match.rawParams);
356
357
  const { from: _from, params: maskParams, ...maskProps } = match.route;
357
- const nextParams = maskParams === false || maskParams === null ? Object.create(null) : (maskParams ?? true) === true ? params : Object.assign(params, require_utils.functionalUpdate(maskParams, params));
358
+ const nextParams = resolveNextParams(maskParams, params);
358
359
  maskedDest = {
359
360
  from: opts.from,
360
361
  ...maskProps,
@@ -375,29 +376,18 @@ var RouterCore = class {
375
376
  };
376
377
  this.commitLocation = async ({ viewTransition, ignoreBlocker, ...next }) => {
377
378
  let historyAction;
378
- const isSameState = () => {
379
- const ignoredProps = [
380
- "key",
381
- "__TSR_key",
382
- "__TSR_index",
383
- "__hashScrollIntoViewOptions"
384
- ];
385
- ignoredProps.forEach((prop) => {
386
- next.state[prop] = this.latestLocation.state[prop];
387
- });
388
- const isEqual = require_utils.deepEqual(next.state, this.latestLocation.state);
389
- ignoredProps.forEach((prop) => {
390
- delete next.state[prop];
391
- });
392
- return isEqual;
393
- };
394
- const isSameUrl = require_path.trimPathRight(this.latestLocation.href) === require_path.trimPathRight(next.href);
395
- let previousCommitPromise = this.commitLocationPromise;
396
- this.commitLocationPromise = require_utils.createControlledPromise(() => {
397
- previousCommitPromise?.resolve();
398
- previousCommitPromise = void 0;
379
+ const isSameLocation = require_path.trimPathRight(this.latestLocation.href) === require_path.trimPathRight(next.href) && require_utils.deepEqual(_getUserHistoryState(next.state), _getUserHistoryState(this.latestLocation.state));
380
+ const previousCommitPromise = this._commitPromise;
381
+ let resolve;
382
+ const commitPromise = new Promise((done) => {
383
+ resolve = done;
399
384
  });
400
- if (isSameUrl && isSameState()) this.load();
385
+ commitPromise.resolve = () => {
386
+ resolve();
387
+ previousCommitPromise?.resolve();
388
+ };
389
+ this._commitPromise = commitPromise;
390
+ if (isSameLocation) this.load({ _dedupe: true });
401
391
  else {
402
392
  let { maskedLocation, hashScrollIntoView, ...nextHistory } = next;
403
393
  if (maskedLocation) {
@@ -425,12 +415,12 @@ var RouterCore = class {
425
415
  this.shouldViewTransition = viewTransition;
426
416
  historyAction = next.replace ? "REPLACE" : "PUSH";
427
417
  this.history[historyAction === "REPLACE" ? "replace" : "push"](nextHistory.publicHref, nextHistory.state, { ignoreBlocker });
418
+ if (!this.history.subscribers.size) this.load({ action: { type: historyAction } });
428
419
  }
429
420
  this._scroll.next = next.resetScroll ?? true;
430
- if (!this.history.subscribers.size) this.load(historyAction ? { action: { type: historyAction } } : void 0);
431
- return this.commitLocationPromise;
421
+ return this._commitPromise;
432
422
  };
433
- this.buildAndCommitLocation = ({ replace, resetScroll, hashScrollIntoView, viewTransition, ignoreBlocker, href, ...rest } = {}) => {
423
+ this.buildAndCommitLocation = ({ replace, resetScroll, hashScrollIntoView, viewTransition, ignoreBlocker, _redirects, href, ...rest } = {}) => {
434
424
  if (href) {
435
425
  const currentIndex = this.history.location.state.__TSR_index;
436
426
  const parsed = (0, _tanstack_history.parseHref)(href, { __TSR_index: replace ? currentIndex : currentIndex + 1 });
@@ -443,7 +433,8 @@ var RouterCore = class {
443
433
  ...rest,
444
434
  _includeValidateSearch: true
445
435
  });
446
- this.pendingBuiltLocation = location;
436
+ if (_redirects) location._redirects = _redirects;
437
+ this._pendingLocation = location;
447
438
  const commitPromise = this.commitLocation({
448
439
  ...location,
449
440
  viewTransition,
@@ -453,7 +444,7 @@ var RouterCore = class {
453
444
  ignoreBlocker
454
445
  });
455
446
  queueMicrotask(() => {
456
- if (this.pendingBuiltLocation === location) this.pendingBuiltLocation = void 0;
447
+ if (this._pendingLocation === location) this._pendingLocation = void 0;
457
448
  });
458
449
  return commitPromise;
459
450
  };
@@ -499,217 +490,63 @@ var RouterCore = class {
499
490
  _isNavigate: true
500
491
  });
501
492
  };
502
- this.beforeLoad = () => {
503
- this.cancelMatches();
504
- this.updateLatestLocation();
505
- if (_tanstack_router_core_isServer.isServer ?? this.isServer) {
506
- const nextLocation = this.buildLocation({
507
- to: this.latestLocation.pathname,
508
- search: true,
509
- params: true,
510
- hash: true,
511
- state: true,
512
- _includeValidateSearch: true
513
- });
514
- if (this.latestLocation.publicHref !== nextLocation.publicHref) {
515
- const href = this.getParsedLocationHref(nextLocation);
516
- if (nextLocation.external) throw require_redirect.redirect({ href });
517
- else throw require_redirect.redirect({
518
- href,
519
- _builtLocation: nextLocation
520
- });
521
- }
522
- }
523
- const pendingMatches = this.matchRoutes(this.latestLocation);
524
- const nextCachedMatches = this.stores.cachedMatches.get().filter((d) => !pendingMatches.some((e) => e.id === d.id));
525
- this.batch(() => {
526
- this.stores.status.set("pending");
527
- this.stores.statusCode.set(200);
528
- this.stores.isLoading.set(true);
529
- this.stores.location.set(this.latestLocation);
530
- this.stores.setPending(pendingMatches);
531
- this.stores.setCached(nextCachedMatches);
532
- });
533
- };
534
493
  this.load = async (opts) => {
535
- const historyAction = opts?.action?.type;
536
- let redirect;
537
- let notFound;
538
- let loadPromise;
539
- const previousLocation = this.stores.resolvedLocation.get() ?? this.stores.location.get();
540
- loadPromise = new Promise((resolve) => {
541
- this.startTransition(async () => {
542
- try {
543
- this.beforeLoad();
544
- if (historyAction) locationHistoryActions.set(this.latestLocation, historyAction);
545
- else locationHistoryActions.delete(this.latestLocation);
546
- const next = this.latestLocation;
547
- const locationChangeInfo = getLocationChangeInfo(next, this.stores.resolvedLocation.get());
548
- if (!this.stores.redirect.get()) this.emit({
549
- type: "onBeforeNavigate",
550
- ...locationChangeInfo
551
- });
552
- this.emit({
553
- type: "onBeforeLoad",
554
- ...locationChangeInfo
555
- });
556
- await require_load_matches.loadMatches({
557
- router: this,
558
- sync: opts?.sync,
559
- forceStaleReload: previousLocation.href === next.href,
560
- matches: this.stores.pendingMatches.get(),
561
- location: next,
562
- updateMatch: this.updateMatch,
563
- onReady: async () => {
564
- this.startTransition(() => {
565
- this.startViewTransition(async () => {
566
- let exitingMatches = null;
567
- let hookExitingMatches = null;
568
- let hookEnteringMatches = null;
569
- let hookStayingMatches = null;
570
- this.batch(() => {
571
- const pendingMatches = this.stores.pendingMatches.get();
572
- const mountPending = pendingMatches.length;
573
- const currentMatches = this.stores.matches.get();
574
- exitingMatches = mountPending ? currentMatches.filter((match) => !this.stores.pendingMatchStores.has(match.id)) : null;
575
- const pendingRouteIds = /* @__PURE__ */ new Set();
576
- for (const s of this.stores.pendingMatchStores.values()) if (s.routeId) pendingRouteIds.add(s.routeId);
577
- const activeRouteIds = /* @__PURE__ */ new Set();
578
- for (const s of this.stores.matchStores.values()) if (s.routeId) activeRouteIds.add(s.routeId);
579
- hookExitingMatches = mountPending ? currentMatches.filter((match) => !pendingRouteIds.has(match.routeId)) : null;
580
- hookEnteringMatches = mountPending ? pendingMatches.filter((match) => !activeRouteIds.has(match.routeId)) : null;
581
- hookStayingMatches = mountPending ? pendingMatches.filter((match) => activeRouteIds.has(match.routeId)) : currentMatches;
582
- this.stores.isLoading.set(false);
583
- this.stores.loadedAt.set(Date.now());
584
- /**
585
- * When committing new matches, cache any exiting matches that are still usable.
586
- * Routes that resolved with `status: 'error'` or `status: 'notFound'` are
587
- * deliberately excluded from `cachedMatches` so that subsequent invalidations
588
- * or reloads re-run their loaders instead of reusing the failed/not-found data.
589
- */
590
- if (mountPending) {
591
- this.stores.setMatches(pendingMatches);
592
- this.stores.setPending([]);
593
- this.stores.setCached([...this.stores.cachedMatches.get(), ...exitingMatches.filter((d) => d.status !== "error" && d.status !== "notFound" && d.status !== "redirected")]);
594
- this.clearExpiredCache();
595
- }
596
- });
597
- for (const [matches, hook] of [
598
- [hookExitingMatches, "onLeave"],
599
- [hookEnteringMatches, "onEnter"],
600
- [hookStayingMatches, "onStay"]
601
- ]) {
602
- if (!matches) continue;
603
- for (const match of matches) this.looseRoutesById[match.routeId].options[hook]?.(match);
604
- }
605
- });
606
- });
607
- }
608
- });
609
- } catch (err) {
610
- if (require_redirect.isRedirect(err)) {
611
- redirect = err;
612
- if (!(_tanstack_router_core_isServer.isServer ?? this.isServer)) this.navigate({
613
- ...redirect.options,
614
- replace: true,
615
- ignoreBlocker: true
616
- });
617
- } else if (require_not_found.isNotFound(err)) notFound = err;
618
- const nextStatusCode = redirect ? redirect.status : notFound ? 404 : this.stores.matches.get().some((d) => d.status === "error") ? 500 : 200;
619
- this.batch(() => {
620
- this.stores.statusCode.set(nextStatusCode);
621
- this.stores.redirect.set(redirect);
622
- });
623
- }
624
- if (this.latestLoadPromise === loadPromise) {
625
- this.commitLocationPromise?.resolve();
626
- this.latestLoadPromise = void 0;
627
- this.commitLocationPromise = void 0;
628
- }
629
- resolve();
630
- });
631
- });
632
- this.latestLoadPromise = loadPromise;
633
- await loadPromise;
634
- while (this.latestLoadPromise && loadPromise !== this.latestLoadPromise) await this.latestLoadPromise;
635
- let newStatusCode = void 0;
636
- if (this.hasNotFoundMatch()) newStatusCode = 404;
637
- else if (this.stores.matches.get().some((d) => d.status === "error")) newStatusCode = 500;
638
- if (newStatusCode !== void 0) this.stores.statusCode.set(newStatusCode);
494
+ if (_tanstack_router_core_isServer.isServer ?? this.isServer) return (0, _tanstack_router_core_isServer.loadServerRoute)(this, opts);
495
+ this.updateLatestLocation();
496
+ if (opts?.action) this._scroll.hash = opts.action.type === "PUSH" || opts.action.type === "REPLACE";
497
+ await require_load_client.loadClientRoute(this, opts);
639
498
  };
640
499
  this.startViewTransition = (fn) => {
641
500
  const shouldViewTransition = this.shouldViewTransition ?? this.options.defaultViewTransition;
642
501
  this.shouldViewTransition = void 0;
643
- if (shouldViewTransition && typeof document !== "undefined" && "startViewTransition" in document && typeof document.startViewTransition === "function") {
502
+ if (shouldViewTransition && !(_tanstack_router_core_isServer.isServer ?? typeof document === "undefined") && typeof document.startViewTransition === "function") {
644
503
  let startViewTransitionParams;
645
- if (typeof shouldViewTransition === "object" && this.isViewTransitionTypesSupported) {
504
+ if (typeof shouldViewTransition === "object" && window.CSS?.supports?.("selector(:active-view-transition-type(a))")) {
646
505
  const next = this.latestLocation;
647
506
  const prevLocation = this.stores.resolvedLocation.get();
648
507
  const resolvedViewTransitionTypes = typeof shouldViewTransition.types === "function" ? shouldViewTransition.types(getLocationChangeInfo(next, prevLocation)) : shouldViewTransition.types;
649
- if (resolvedViewTransitionTypes === false) {
650
- fn();
651
- return;
652
- }
508
+ if (resolvedViewTransitionTypes === false) return fn();
653
509
  startViewTransitionParams = {
654
510
  update: fn,
655
511
  types: resolvedViewTransitionTypes
656
512
  };
657
513
  } else startViewTransitionParams = fn;
658
- document.startViewTransition(startViewTransitionParams);
659
- } else fn();
660
- };
661
- this.updateMatch = (id, updater) => {
662
- this.startTransition(() => {
663
- const pendingMatch = this.stores.pendingMatchStores.get(id);
664
- if (pendingMatch) {
665
- pendingMatch.set(updater);
666
- return;
667
- }
668
- const activeMatch = this.stores.matchStores.get(id);
669
- if (activeMatch) {
670
- activeMatch.set(updater);
671
- return;
672
- }
673
- const cachedMatch = this.stores.cachedMatchStores.get(id);
674
- if (cachedMatch) {
675
- const next = updater(cachedMatch.get());
676
- if (next.status === "redirected") {
677
- if (this.stores.cachedMatchStores.delete(id)) this.stores.cachedIds.set((prev) => prev.filter((matchId) => matchId !== id));
678
- } else cachedMatch.set(next);
679
- }
680
- });
681
- };
682
- this.getMatch = (matchId) => {
683
- return this.stores.cachedMatchStores.get(matchId)?.get() ?? this.stores.pendingMatchStores.get(matchId)?.get() ?? this.stores.matchStores.get(matchId)?.get();
514
+ return document.startViewTransition(startViewTransitionParams).updateCallbackDone;
515
+ }
516
+ return fn();
684
517
  };
685
518
  this.invalidate = (opts) => {
519
+ const committedMatches = this._committed;
520
+ const filter = opts?.filter;
521
+ const invalidIds = filter ? new Set([...committedMatches, ...this._cache.values()].filter((match) => filter(match)).map((match) => match.id)) : void 0;
686
522
  const invalidate = (d) => {
687
- if (opts?.filter?.(d) ?? true) return {
688
- ...d,
689
- invalid: true,
690
- ...opts?.forcePending || d.status === "error" || d.status === "notFound" ? {
691
- status: "pending",
692
- error: void 0
693
- } : void 0
694
- };
523
+ if (!invalidIds || invalidIds.has(d.id)) {
524
+ const route = this.routesById[d.routeId];
525
+ const next = {
526
+ ...d,
527
+ invalid: true,
528
+ ...(opts?.forcePending || d.status === "error" || d.status === "notFound") && routeNeedsLoad(route) ? {
529
+ status: "pending",
530
+ error: void 0
531
+ } : void 0
532
+ };
533
+ d._flight = void 0;
534
+ return next;
535
+ }
695
536
  return d;
696
537
  };
697
- this.batch(() => {
698
- this.stores.setMatches(this.stores.matches.get().map(invalidate));
699
- this.stores.setCached(this.stores.cachedMatches.get().map(invalidate));
700
- this.stores.setPending(this.stores.pendingMatches.get().map(invalidate));
701
- });
538
+ const committed = committedMatches.map(invalidate);
539
+ this._committed = committed;
540
+ const cache = /* @__PURE__ */ new Map();
541
+ for (const [id, match] of this._cache) cache.set(id, invalidate(match));
542
+ this._cache = cache;
702
543
  this.shouldViewTransition = false;
703
544
  return this.load({ sync: opts?.sync });
704
545
  };
705
- this.getParsedLocationHref = (location) => {
706
- return location.publicHref || "/";
707
- };
708
546
  this.resolveRedirect = (redirect) => {
709
547
  const locationHeader = redirect.headers.get("Location");
710
548
  if (!redirect.options.href || redirect.options._builtLocation) {
711
- const location = redirect.options._builtLocation ?? this.buildLocation(redirect.options);
712
- const href = this.getParsedLocationHref(location);
549
+ const href = (redirect.options._builtLocation ?? this.buildLocation(redirect.options)).publicHref || "/";
713
550
  redirect.options.href = href;
714
551
  redirect.headers.set("Location", href);
715
552
  } else if (locationHeader) try {
@@ -725,60 +562,26 @@ var RouterCore = class {
725
562
  return redirect;
726
563
  };
727
564
  this.clearCache = (opts) => {
565
+ const cached = this._cache;
566
+ const preloads = this._preloads;
728
567
  const filter = opts?.filter;
729
- if (filter !== void 0) this.stores.setCached(this.stores.cachedMatches.get().filter((m) => !filter(m)));
730
- else this.stores.setCached([]);
731
- };
732
- this.clearExpiredCache = () => {
733
- const now = Date.now();
734
- const filter = (d) => {
735
- const route = this.looseRoutesById[d.routeId];
736
- if (!route.options.loader) return true;
737
- const gcTime = (d.preload ? route.options.preloadGcTime ?? this.options.defaultPreloadGcTime : route.options.gcTime ?? this.options.defaultGcTime) ?? 300 * 1e3;
738
- if (d.status === "error") return true;
739
- return now - d.updatedAt >= gcTime;
740
- };
741
- this.clearCache({ filter });
742
- };
743
- this.loadRouteChunk = require_load_matches.loadRouteChunk;
744
- this.preloadRoute = async (opts) => {
745
- const next = opts._builtLocation ?? this.buildLocation(opts);
746
- let matches = this.matchRoutes(next, {
747
- throwOnError: true,
748
- preload: true,
749
- dest: opts
750
- });
751
- const activeMatchIds = new Set([...this.stores.matchesId.get(), ...this.stores.pendingIds.get()]);
752
- const loadedMatchIds = new Set([...activeMatchIds, ...this.stores.cachedIds.get()]);
753
- const matchesToCache = matches.filter((match) => !loadedMatchIds.has(match.id));
754
- if (matchesToCache.length) {
755
- const cachedMatches = this.stores.cachedMatches.get();
756
- this.stores.setCached([...cachedMatches, ...matchesToCache]);
757
- }
758
- try {
759
- matches = await require_load_matches.loadMatches({
760
- router: this,
761
- matches,
762
- location: next,
763
- preload: true,
764
- updateMatch: (id, updater) => {
765
- if (activeMatchIds.has(id)) matches = matches.map((d) => d.id === id ? updater(d) : d);
766
- else this.updateMatch(id, updater);
767
- }
768
- });
769
- return matches;
770
- } catch (err) {
771
- if (require_redirect.isRedirect(err)) {
772
- if (err.options.reloadDocument) return;
773
- return await this.preloadRoute({
774
- ...err.options,
775
- _fromLocation: next
776
- });
777
- }
778
- if (!require_not_found.isNotFound(err)) console.error(err);
779
- return;
780
- }
568
+ const retained = /* @__PURE__ */ new Map();
569
+ const discarded = [];
570
+ for (const [id, match] of cached) if (filter && !filter(match)) retained.set(id, match);
571
+ else discarded.push(match);
572
+ const retainedPreloads = /* @__PURE__ */ new Map();
573
+ const discardedPreloads = [];
574
+ for (const [href, preload] of preloads ?? []) if (!filter || preload[0].some(filter)) {
575
+ discardedPreloads.push(preload);
576
+ discarded.push(...preload[0]);
577
+ } else retainedPreloads.set(href, preload);
578
+ this._cache = retained;
579
+ this._preloads = retainedPreloads;
580
+ require_load_client.transferMatchResources(this, discarded);
581
+ for (const preload of discardedPreloads) preload[1].abort();
781
582
  };
583
+ this.loadRouteChunk = require_load_client.loadRouteChunk;
584
+ this.preloadRoute = (opts) => require_load_client.preloadClientRoute(this, opts);
782
585
  this.matchRoute = (location, opts) => {
783
586
  const matchLocation = {
784
587
  ...location,
@@ -787,8 +590,9 @@ var RouterCore = class {
787
590
  leaveParams: true
788
591
  };
789
592
  const next = this.buildLocation(matchLocation);
790
- if (opts?.pending && this.stores.status.get() !== "pending") return false;
791
- const baseLocation = (opts?.pending === void 0 ? !this.stores.isLoading.get() : opts.pending) ? this.latestLocation : this.stores.resolvedLocation.get() || this.stores.location.get();
593
+ const isPending = this.stores.status.get() === "pending";
594
+ if (opts?.pending && !isPending) return false;
595
+ const baseLocation = opts?.pending ?? !isPending ? this.latestLocation : this.stores.resolvedLocation.get() || this.stores.location.get();
792
596
  const match = require_new_process_route_tree.findSingleMatch(next.pathname, opts?.caseSensitive ?? false, opts?.fuzzy ?? false, baseLocation.pathname, this.processedTree);
793
597
  if (!match) return false;
794
598
  if (location.params) {
@@ -797,9 +601,6 @@ var RouterCore = class {
797
601
  if (opts?.includeSearch ?? true) return require_utils.deepEqual(baseLocation.search, next.search, { partial: true }) ? match.rawParams : false;
798
602
  return match.rawParams;
799
603
  };
800
- this.hasNotFoundMatch = () => {
801
- return this.stores.matches.get().some((d) => d.status === "notFound" || d.globalNotFound);
802
- };
803
604
  this.getStoreConfig = getStoreConfig;
804
605
  this.update({
805
606
  defaultPreloadDelay: 50,
@@ -813,14 +614,11 @@ var RouterCore = class {
813
614
  parseSearch: options.parseSearch ?? require_searchParams.defaultParseSearch,
814
615
  protocolAllowlist: options.protocolAllowlist ?? require_utils.DEFAULT_PROTOCOL_ALLOWLIST
815
616
  });
816
- if (typeof document !== "undefined") self.__TSR_ROUTER__ = this;
617
+ if (!(_tanstack_router_core_isServer.isServer ?? typeof document === "undefined")) self.__TSR_ROUTER__ = this;
817
618
  }
818
619
  isShell() {
819
620
  return !!this.options.isShell;
820
621
  }
821
- isPrerendering() {
822
- return !!this.options.isPrerendering;
823
- }
824
622
  get state() {
825
623
  return this.stores.__store.get();
826
624
  }
@@ -842,12 +640,6 @@ var RouterCore = class {
842
640
  }
843
641
  return branch;
844
642
  }
845
- get looseRoutesById() {
846
- return this.routesById;
847
- }
848
- getParentContext(parentMatch) {
849
- return !parentMatch?.id ? this.options.context ?? void 0 : parentMatch.context ?? this.options.context ?? void 0;
850
- }
851
643
  matchRoutesInternal(next, opts) {
852
644
  const matchedRoutesResult = this.getMatchedRoutes(next.pathname);
853
645
  const { foundRoute, routeParams } = matchedRoutesResult;
@@ -855,10 +647,13 @@ var RouterCore = class {
855
647
  let isGlobalNotFound = false;
856
648
  if (foundRoute ? foundRoute.path !== "/" && routeParams["**"] : require_path.trimPathRight(next.pathname)) if (this.options.notFoundRoute) matchedRoutes = [...matchedRoutes, this.options.notFoundRoute];
857
649
  else isGlobalNotFound = true;
858
- const globalNotFoundRouteId = isGlobalNotFound ? findGlobalNotFoundRouteId(this.options.notFoundMode, matchedRoutes) : void 0;
650
+ const _notFoundRouteId = isGlobalNotFound ? findGlobalNotFoundRouteId(this.options.notFoundMode, matchedRoutes) : void 0;
859
651
  const matches = new Array(matchedRoutes.length);
860
- const previousActiveMatchesByRouteId = /* @__PURE__ */ new Map();
861
- for (const store of this.stores.matchStores.values()) if (store.routeId) previousActiveMatchesByRouteId.set(store.routeId, store.get());
652
+ const committed = this._committed;
653
+ const previousAt = (route, index) => {
654
+ const match = committed[index];
655
+ return match?.routeId === route.id ? match : route === this.options.notFoundRoute ? committed.find((candidate) => candidate.routeId === route.id) : void 0;
656
+ };
862
657
  for (let index = 0; index < matchedRoutes.length; index++) {
863
658
  const route = matchedRoutes[index];
864
659
  const parentMatch = matches[index - 1];
@@ -878,7 +673,6 @@ var RouterCore = class {
878
673
  ...parentStrictSearch,
879
674
  ...strictSearch
880
675
  };
881
- searchError = void 0;
882
676
  } catch (err) {
883
677
  let searchParamError = err;
884
678
  if (!(err instanceof SearchParamError)) searchParamError = new SearchParamError(err.message, { cause: err });
@@ -888,8 +682,15 @@ var RouterCore = class {
888
682
  searchError = searchParamError;
889
683
  }
890
684
  }
891
- const loaderDeps = route.options.loaderDeps?.({ search: preMatchSearch }) ?? "";
892
- const loaderDepsHash = loaderDeps ? JSON.stringify(loaderDeps) : "";
685
+ let loaderDeps = "";
686
+ let loaderDepsHash = "";
687
+ try {
688
+ loaderDeps = route.options.loaderDeps?.({ search: preMatchSearch }) ?? "";
689
+ loaderDepsHash = loaderDeps ? JSON.stringify(loaderDeps) || "" : "";
690
+ } catch (cause) {
691
+ if (opts?.throwOnError) throw cause;
692
+ searchError ??= cause;
693
+ }
893
694
  const { interpolatedPath, usedParams } = require_path.interpolatePath({
894
695
  path: route.fullPath,
895
696
  params: routeParams,
@@ -897,10 +698,10 @@ var RouterCore = class {
897
698
  server: this.isServer
898
699
  });
899
700
  const matchId = route.id + interpolatedPath + loaderDepsHash;
900
- const existingMatch = this.getMatch(matchId);
901
- const previousMatch = previousActiveMatchesByRouteId.get(route.id);
701
+ const previousMatch = previousAt(route, index);
702
+ const existingMatch = process.env.NODE_ENV !== "production" && opts?._rematerialize ? void 0 : this._cache.get(matchId) ?? (previousMatch?.id === matchId ? previousMatch : void 0);
902
703
  const strictParams = existingMatch?._strictParams ?? usedParams;
903
- let paramsError = void 0;
704
+ let paramsError;
904
705
  if (!existingMatch) try {
905
706
  extractStrictParams(route, strictParams);
906
707
  } catch (err) {
@@ -917,10 +718,11 @@ var RouterCore = class {
917
718
  params: previousMatch?.params ?? routeParams,
918
719
  _strictParams: strictParams,
919
720
  search: previousMatch ? require_utils.nullReplaceEqualDeep(previousMatch.search, preMatchSearch) : require_utils.nullReplaceEqualDeep(existingMatch.search, preMatchSearch),
920
- _strictSearch: strictMatchSearch
721
+ _strictSearch: strictMatchSearch,
722
+ searchError
921
723
  };
922
724
  else {
923
- const status = route.options.loader || route.options.beforeLoad || route.lazyFn || require_load_matches.routeNeedsPreload(route) ? "pending" : "success";
725
+ const status = routeNeedsLoad(route) ? "pending" : "success";
924
726
  match = {
925
727
  id: matchId,
926
728
  ssr: _tanstack_router_core_isServer.isServer ?? this.isServer ? void 0 : route.options.ssr,
@@ -932,83 +734,42 @@ var RouterCore = class {
932
734
  updatedAt: Date.now(),
933
735
  search: previousMatch ? require_utils.nullReplaceEqualDeep(previousMatch.search, preMatchSearch) : preMatchSearch,
934
736
  _strictSearch: strictMatchSearch,
935
- searchError: void 0,
737
+ searchError,
936
738
  status,
937
739
  isFetching: false,
938
740
  error: void 0,
939
741
  paramsError,
940
- __routeContext: void 0,
941
- _nonReactive: { loadPromise: require_utils.createControlledPromise() },
942
- __beforeLoadContext: void 0,
943
742
  context: {},
944
- abortController: new AbortController(),
945
- fetchCount: 0,
743
+ abortController: opts?._controller ?? new AbortController(),
946
744
  cause,
947
745
  loaderDeps: previousMatch ? require_utils.replaceEqualDeep(previousMatch.loaderDeps, loaderDeps) : loaderDeps,
948
746
  invalid: false,
949
747
  preload: false,
950
- links: void 0,
951
- scripts: void 0,
952
- headScripts: void 0,
953
- meta: void 0,
954
748
  staticData: route.options.staticData || {},
955
749
  fullPath: route.fullPath
956
750
  };
957
751
  }
958
- if (!opts?.preload) match.globalNotFound = globalNotFoundRouteId === route.id;
959
- match.searchError = searchError;
960
- const parentContext = this.getParentContext(parentMatch);
961
- match.context = {
962
- ...parentContext,
963
- ...match.__routeContext,
964
- ...match.__beforeLoadContext
965
- };
752
+ const _notFound = _notFoundRouteId === route.id;
753
+ if (match._notFound && !_notFound) match.error = void 0;
754
+ match._notFound = _notFound;
966
755
  matches[index] = match;
967
756
  }
968
757
  for (let index = 0; index < matches.length; index++) {
969
758
  const match = matches[index];
970
- const route = this.looseRoutesById[match.routeId];
971
- const existingMatch = this.getMatch(match.id);
972
- const previousMatch = previousActiveMatchesByRouteId.get(match.routeId);
973
- match.params = previousMatch ? require_utils.nullReplaceEqualDeep(previousMatch.params, routeParams) : routeParams;
974
- if (!existingMatch) {
975
- const parentMatch = matches[index - 1];
976
- const parentContext = this.getParentContext(parentMatch);
977
- if (route.options.context) {
978
- const contextFnContext = {
979
- deps: match.loaderDeps,
980
- params: match.params,
981
- context: parentContext ?? {},
982
- location: next,
983
- navigate: (opts) => this.navigate({
984
- ...opts,
985
- _fromLocation: next
986
- }),
987
- buildLocation: this.buildLocation,
988
- cause: match.cause,
989
- abortController: match.abortController,
990
- preload: !!match.preload,
991
- matches,
992
- routeId: route.id
993
- };
994
- match.__routeContext = route.options.context(contextFnContext) ?? void 0;
995
- }
996
- match.context = {
997
- ...parentContext,
998
- ...match.__routeContext,
999
- ...match.__beforeLoadContext
1000
- };
1001
- }
759
+ match.params = match.cause === "stay" ? require_utils.nullReplaceEqualDeep(match.params, routeParams) : routeParams;
760
+ if (opts?._controller) match.context = {};
1002
761
  }
1003
762
  return matches;
1004
763
  }
1005
764
  /**
1006
765
  * Lightweight route matching for buildLocation.
1007
766
  * Only computes fullPath, accumulated search, and params - skipping expensive
1008
- * operations like AbortController, ControlledPromise, loaderDeps, and full match objects.
767
+ * operations like AbortController, loaderDeps, and full match objects.
1009
768
  */
1010
769
  matchRoutesLightweight(location) {
1011
- const lastStateMatchId = require_utils.last(this.stores.matchesId.get());
770
+ const lastRouteId = require_utils.last(this.stores.ids.get());
771
+ const lastStateMatch = lastRouteId ? this.stores.byRoute.get(lastRouteId).get() : void 0;
772
+ const lastStateMatchId = lastStateMatch?.id;
1012
773
  const cached = this.lightweightCache.get(location);
1013
774
  if (cached && cached[0] === lastStateMatchId) return cached[1];
1014
775
  const { matchedRoutes, routeParams } = this.getMatchedRoutes(location.pathname);
@@ -1017,7 +778,6 @@ var RouterCore = class {
1017
778
  for (const route of matchedRoutes) try {
1018
779
  Object.assign(accumulatedSearch, validateSearch(route.options.validateSearch, accumulatedSearch));
1019
780
  } catch {}
1020
- const lastStateMatch = lastStateMatchId && this.stores.matchStores.get(lastStateMatchId)?.get();
1021
781
  const canReuseParams = lastStateMatch && lastStateMatch.routeId === lastRoute.id && lastStateMatch.pathname === location.pathname;
1022
782
  let params;
1023
783
  if (canReuseParams) params = lastStateMatch.params;
@@ -1038,6 +798,19 @@ var RouterCore = class {
1038
798
  return result;
1039
799
  }
1040
800
  };
801
+ /**
802
+ * In non-production environments,
803
+ * augment the RouterCore class with a `_refreshRoute` method
804
+ * dedicated to HMR.
805
+ */
806
+ if (process.env.NODE_ENV !== "production") {
807
+ RouterCore.prototype._replaceRouteChunk = require_load_client.replaceRouteChunk;
808
+ RouterCore.prototype._refreshRoute = async function() {
809
+ this._serverResult = void 0;
810
+ this.updateLatestLocation();
811
+ await require_load_client.refreshClientRoute(this);
812
+ };
813
+ }
1041
814
  /** Error thrown when search parameter validation fails. */
1042
815
  var SearchParamError = class extends Error {};
1043
816
  /** Error thrown when path parameter parsing/validation fails. */
@@ -1058,14 +831,11 @@ function lazyFn(fn, key) {
1058
831
  /** Create an initial RouterState from a parsed location. */
1059
832
  function getInitialRouterState(location) {
1060
833
  return {
1061
- loadedAt: 0,
1062
834
  isLoading: false,
1063
- isTransitioning: false,
1064
835
  status: "idle",
1065
836
  resolvedLocation: void 0,
1066
837
  location,
1067
- matches: [],
1068
- statusCode: 200
838
+ matches: []
1069
839
  };
1070
840
  }
1071
841
  function validateSearch(validateSearch, input) {
@@ -1080,35 +850,7 @@ function validateSearch(validateSearch, input) {
1080
850
  if (typeof validateSearch === "function") return validateSearch(input);
1081
851
  return {};
1082
852
  }
1083
- /**
1084
- * Build the matched route chain and extract params for a pathname.
1085
- * Falls back to the root route if no specific route is found.
1086
- */
1087
- function getMatchedRoutes({ pathname, routesById, processedTree }) {
1088
- const routeParams = Object.create(null);
1089
- const trimmedPath = require_path.trimPathRight(pathname);
1090
- let foundRoute = void 0;
1091
- const match = require_new_process_route_tree.findRouteMatch(trimmedPath, processedTree, true);
1092
- if (match) {
1093
- foundRoute = match.route;
1094
- Object.assign(routeParams, match.rawParams);
1095
- }
1096
- return {
1097
- matchedRoutes: match?.branch || [routesById["__root__"]],
1098
- routeParams,
1099
- foundRoute
1100
- };
1101
- }
1102
- /**
1103
- * TODO: once caches are persisted across requests on the server,
1104
- * we can cache the built middleware chain using `last(destRoutes)` as the key
1105
- */
1106
- function applySearchMiddleware({ search, dest, destRoutes, _includeValidateSearch }) {
1107
- return buildMiddlewareChain(destRoutes)(search, dest, _includeValidateSearch ?? false);
1108
- }
1109
- function buildMiddlewareChain(destRoutes) {
1110
- let dest;
1111
- let includeValidateSearch;
853
+ function applySearchMiddleware(search, dest, destRoutes, includeValidateSearch) {
1112
854
  const middlewares = [];
1113
855
  for (const route of destRoutes) {
1114
856
  const routeOptions = route.options;
@@ -1164,37 +906,37 @@ function buildMiddlewareChain(destRoutes) {
1164
906
  meta
1165
907
  });
1166
908
  };
1167
- return function middleware(search, nextDest, _includeValidateSearch) {
1168
- dest = nextDest;
1169
- includeValidateSearch = _includeValidateSearch;
1170
- return applyNext(0, search);
1171
- };
909
+ return applyNext(0, search);
1172
910
  }
1173
911
  function findGlobalNotFoundRouteId(notFoundMode, routes) {
1174
- if (notFoundMode !== "root") for (let i = routes.length - 1; i >= 0; i--) {
1175
- const route = routes[i];
1176
- if (route.children) return route.id;
912
+ if (notFoundMode !== "root") {
913
+ let fallback;
914
+ for (let i = routes.length - 1; i >= 0; i--) {
915
+ const route = routes[i];
916
+ if (route.options.notFoundComponent) return route.id;
917
+ fallback ||= route.children && route.id;
918
+ }
919
+ if (fallback) return fallback;
1177
920
  }
1178
921
  return require_root.rootRouteId;
1179
922
  }
923
+ function resolveNextParams(spec, base) {
924
+ return spec === false || spec === null ? Object.create(null) : (spec ?? true) === true ? base : Object.assign(base, require_utils.functionalUpdate(spec, base));
925
+ }
1180
926
  function extractStrictParams(route, accumulatedParams) {
1181
927
  const parseParams = route.options.params?.parse ?? route.options.parseParams;
1182
- if (parseParams) {
1183
- const result = parseParams(accumulatedParams);
1184
- if (result === false) throw new Error("Route params.parse returned false for a matched route");
1185
- Object.assign(accumulatedParams, result);
1186
- }
928
+ if (parseParams) Object.assign(accumulatedParams, parseParams(accumulatedParams));
1187
929
  }
1188
930
  //#endregion
1189
931
  exports.PathParamError = PathParamError;
1190
932
  exports.RouterCore = RouterCore;
1191
933
  exports.SearchParamError = SearchParamError;
934
+ exports._getUserHistoryState = _getUserHistoryState;
1192
935
  exports.defaultSerializeError = defaultSerializeError;
1193
936
  exports.getInitialRouterState = getInitialRouterState;
1194
937
  exports.getLocationChangeInfo = getLocationChangeInfo;
1195
- exports.getMatchedRoutes = getMatchedRoutes;
1196
938
  exports.lazyFn = lazyFn;
1197
- exports.locationHistoryActions = locationHistoryActions;
939
+ exports.runRouteLifecycle = runRouteLifecycle;
1198
940
  exports.trailingSlashOptions = trailingSlashOptions;
1199
941
 
1200
942
  //# sourceMappingURL=router.cjs.map