@tanstack/router-core 1.121.0-alpha.1 → 1.121.0-alpha.5

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.
@@ -194,9 +194,8 @@ class RouterCore {
194
194
  },
195
195
  opts
196
196
  );
197
- } else {
198
- return this.matchRoutesInternal(pathnameOrNext, locationSearchOrOpts);
199
197
  }
198
+ return this.matchRoutesInternal(pathnameOrNext, locationSearchOrOpts);
200
199
  };
201
200
  this.getMatchedRoutes = (pathname, routePathname) => {
202
201
  return getMatchedRoutes({
@@ -222,173 +221,90 @@ class RouterCore {
222
221
  });
223
222
  };
224
223
  this.buildLocation = (opts) => {
225
- const build = (dest = {}, matchedRoutesResult) => {
226
- var _a, _b, _c, _d, _e, _f, _g;
227
- const fromMatches = dest._fromLocation ? this.matchRoutes(dest._fromLocation, { _buildLocation: true }) : this.state.matches;
228
- const fromMatch = dest.from != null ? fromMatches.find(
229
- (d) => matchPathname(this.basepath, trimPathRight(d.pathname), {
230
- to: dest.from,
231
- caseSensitive: false,
232
- fuzzy: false
233
- })
234
- ) : void 0;
235
- const fromPath = (fromMatch == null ? void 0 : fromMatch.pathname) || this.latestLocation.pathname;
236
- invariant(
237
- dest.from == null || fromMatch != null,
238
- "Could not find match for from: " + dest.from
239
- );
240
- const fromSearch = ((_a = this.state.pendingMatches) == null ? void 0 : _a.length) ? (_b = last(this.state.pendingMatches)) == null ? void 0 : _b.search : ((_c = last(fromMatches)) == null ? void 0 : _c.search) || this.latestLocation.search;
241
- const stayingMatches = matchedRoutesResult == null ? void 0 : matchedRoutesResult.matchedRoutes.filter(
242
- (d) => fromMatches.find((e) => e.routeId === d.id)
243
- );
244
- let pathname;
245
- if (dest.to) {
246
- const resolvePathTo = (fromMatch == null ? void 0 : fromMatch.fullPath) || ((_d = last(fromMatches)) == null ? void 0 : _d.fullPath) || this.latestLocation.pathname;
247
- pathname = this.resolvePathWithBase(resolvePathTo, `${dest.to}`);
248
- } else {
249
- const fromRouteByFromPathRouteId = this.routesById[(_e = stayingMatches == null ? void 0 : stayingMatches.find((route) => {
250
- const interpolatedPath = interpolatePath({
251
- path: route.fullPath,
252
- params: (matchedRoutesResult == null ? void 0 : matchedRoutesResult.routeParams) ?? {},
253
- decodeCharMap: this.pathParamsDecodeCharMap
254
- }).interpolatedPath;
255
- const pathname2 = joinPaths([this.basepath, interpolatedPath]);
256
- return pathname2 === fromPath;
257
- })) == null ? void 0 : _e.id];
258
- pathname = this.resolvePathWithBase(
259
- fromPath,
260
- (fromRouteByFromPathRouteId == null ? void 0 : fromRouteByFromPathRouteId.to) ?? fromPath
261
- );
224
+ const build = (dest = {}) => {
225
+ var _a;
226
+ const currentLocation = dest._fromLocation || this.latestLocation;
227
+ const allFromMatches = this.matchRoutes(currentLocation, {
228
+ _buildLocation: true
229
+ });
230
+ const lastMatch = last(allFromMatches);
231
+ let fromId = lastMatch.fullPath;
232
+ if (dest.to && dest.from) {
233
+ fromId = dest.from;
234
+ }
235
+ const existingFrom = [...allFromMatches].reverse().find((d) => {
236
+ return d.fullPath === fromId || d.fullPath === joinPaths([fromId, "/"]);
237
+ });
238
+ if (!existingFrom) {
239
+ console.warn(`Could not find match for from: ${dest.from}`);
262
240
  }
263
- const prevParams = { ...(_f = last(fromMatches)) == null ? void 0 : _f.params };
264
- let nextParams = (dest.params ?? true) === true ? prevParams : {
265
- ...prevParams,
266
- ...functionalUpdate(dest.params, prevParams)
241
+ const fromSearch = lastMatch.search;
242
+ const fromParams = { ...lastMatch.params };
243
+ const nextTo = dest.to ? this.resolvePathWithBase(fromId, `${dest.to}`) : fromId;
244
+ let nextParams = (dest.params ?? true) === true ? fromParams : {
245
+ ...fromParams,
246
+ ...functionalUpdate(dest.params, fromParams)
267
247
  };
248
+ const destRoutes = this.matchRoutes(
249
+ nextTo,
250
+ {},
251
+ {
252
+ _buildLocation: true
253
+ }
254
+ ).map((d) => this.looseRoutesById[d.routeId]);
268
255
  if (Object.keys(nextParams).length > 0) {
269
- matchedRoutesResult == null ? void 0 : matchedRoutesResult.matchedRoutes.map((route) => {
256
+ destRoutes.map((route) => {
270
257
  var _a2;
271
258
  return ((_a2 = route.options.params) == null ? void 0 : _a2.stringify) ?? route.options.stringifyParams;
272
259
  }).filter(Boolean).forEach((fn) => {
273
260
  nextParams = { ...nextParams, ...fn(nextParams) };
274
261
  });
275
262
  }
276
- pathname = interpolatePath({
277
- path: pathname,
263
+ const nextPathname = interpolatePath({
264
+ path: nextTo,
278
265
  params: nextParams ?? {},
279
266
  leaveWildcards: false,
280
267
  leaveParams: opts.leaveParams,
281
268
  decodeCharMap: this.pathParamsDecodeCharMap
282
269
  }).interpolatedPath;
283
- let search = fromSearch;
284
- if (opts._includeValidateSearch && ((_g = this.options.search) == null ? void 0 : _g.strict)) {
270
+ let nextSearch = fromSearch;
271
+ if (opts._includeValidateSearch && ((_a = this.options.search) == null ? void 0 : _a.strict)) {
285
272
  let validatedSearch = {};
286
- matchedRoutesResult == null ? void 0 : matchedRoutesResult.matchedRoutes.forEach((route) => {
273
+ destRoutes.forEach((route) => {
287
274
  try {
288
275
  if (route.options.validateSearch) {
289
276
  validatedSearch = {
290
277
  ...validatedSearch,
291
278
  ...validateSearch(route.options.validateSearch, {
292
279
  ...validatedSearch,
293
- ...search
280
+ ...nextSearch
294
281
  }) ?? {}
295
282
  };
296
283
  }
297
284
  } catch {
298
285
  }
299
286
  });
300
- search = validatedSearch;
287
+ nextSearch = validatedSearch;
301
288
  }
302
- const applyMiddlewares = (search2) => {
303
- const allMiddlewares = (matchedRoutesResult == null ? void 0 : matchedRoutesResult.matchedRoutes.reduce(
304
- (acc, route) => {
305
- var _a2;
306
- const middlewares = [];
307
- if ("search" in route.options) {
308
- if ((_a2 = route.options.search) == null ? void 0 : _a2.middlewares) {
309
- middlewares.push(...route.options.search.middlewares);
310
- }
311
- } else if (route.options.preSearchFilters || route.options.postSearchFilters) {
312
- const legacyMiddleware = ({
313
- search: search3,
314
- next
315
- }) => {
316
- let nextSearch = search3;
317
- if ("preSearchFilters" in route.options && route.options.preSearchFilters) {
318
- nextSearch = route.options.preSearchFilters.reduce(
319
- (prev, next2) => next2(prev),
320
- search3
321
- );
322
- }
323
- const result = next(nextSearch);
324
- if ("postSearchFilters" in route.options && route.options.postSearchFilters) {
325
- return route.options.postSearchFilters.reduce(
326
- (prev, next2) => next2(prev),
327
- result
328
- );
329
- }
330
- return result;
331
- };
332
- middlewares.push(legacyMiddleware);
333
- }
334
- if (opts._includeValidateSearch && route.options.validateSearch) {
335
- const validate = ({ search: search3, next }) => {
336
- const result = next(search3);
337
- try {
338
- const validatedSearch = {
339
- ...result,
340
- ...validateSearch(
341
- route.options.validateSearch,
342
- result
343
- ) ?? {}
344
- };
345
- return validatedSearch;
346
- } catch {
347
- return result;
348
- }
349
- };
350
- middlewares.push(validate);
351
- }
352
- return acc.concat(middlewares);
353
- },
354
- []
355
- )) ?? [];
356
- const final = ({ search: search3 }) => {
357
- if (!dest.search) {
358
- return {};
359
- }
360
- if (dest.search === true) {
361
- return search3;
362
- }
363
- return functionalUpdate(dest.search, search3);
364
- };
365
- allMiddlewares.push(final);
366
- const applyNext = (index, currentSearch) => {
367
- if (index >= allMiddlewares.length) {
368
- return currentSearch;
369
- }
370
- const middleware = allMiddlewares[index];
371
- const next = (newSearch) => {
372
- return applyNext(index + 1, newSearch);
373
- };
374
- return middleware({ search: currentSearch, next });
375
- };
376
- return applyNext(0, search2);
377
- };
378
- search = applyMiddlewares(search);
379
- search = replaceEqualDeep(fromSearch, search);
380
- const searchStr = this.options.stringifySearch(search);
381
- const hash = dest.hash === true ? this.latestLocation.hash : dest.hash ? functionalUpdate(dest.hash, this.latestLocation.hash) : void 0;
289
+ nextSearch = applySearchMiddleware({
290
+ search: nextSearch,
291
+ dest,
292
+ destRoutes,
293
+ _includeValidateSearch: opts._includeValidateSearch
294
+ });
295
+ nextSearch = replaceEqualDeep(fromSearch, nextSearch);
296
+ const searchStr = this.options.stringifySearch(nextSearch);
297
+ const hash = dest.hash === true ? currentLocation.hash : dest.hash ? functionalUpdate(dest.hash, currentLocation.hash) : void 0;
382
298
  const hashStr = hash ? `#${hash}` : "";
383
- let nextState = dest.state === true ? this.latestLocation.state : dest.state ? functionalUpdate(dest.state, this.latestLocation.state) : {};
384
- nextState = replaceEqualDeep(this.latestLocation.state, nextState);
299
+ let nextState = dest.state === true ? currentLocation.state : dest.state ? functionalUpdate(dest.state, currentLocation.state) : {};
300
+ nextState = replaceEqualDeep(currentLocation.state, nextState);
385
301
  return {
386
- pathname,
387
- search,
302
+ pathname: nextPathname,
303
+ search: nextSearch,
388
304
  searchStr,
389
305
  state: nextState,
390
306
  hash: hash ?? "",
391
- href: `${pathname}${searchStr}${hashStr}`,
307
+ href: `${nextPathname}${searchStr}${hashStr}`,
392
308
  unmaskOnReload: dest.unmaskOnReload
393
309
  };
394
310
  };
@@ -420,20 +336,11 @@ class RouterCore {
420
336
  maskedNext = build(maskedDest);
421
337
  }
422
338
  }
423
- const nextMatches = this.getMatchedRoutes(
424
- next.pathname,
425
- dest.to
426
- );
427
- const final = build(dest, nextMatches);
428
339
  if (maskedNext) {
429
- const maskedMatches = this.getMatchedRoutes(
430
- maskedNext.pathname,
431
- maskedDest == null ? void 0 : maskedDest.to
432
- );
433
- const maskedFinal = build(maskedDest, maskedMatches);
434
- final.maskedLocation = maskedFinal;
340
+ const maskedFinal = build(maskedDest);
341
+ next.maskedLocation = maskedFinal;
435
342
  }
436
- return final;
343
+ return next;
437
344
  };
438
345
  if (opts.mask) {
439
346
  return buildWithMatches(opts, {
@@ -1005,7 +912,7 @@ class RouterCore {
1005
912
  loaderPromise: createControlledPromise(),
1006
913
  preload: !!preload && !this.state.matches.find((d) => d.id === matchId)
1007
914
  }));
1008
- const executeHead = () => {
915
+ const executeHead = async () => {
1009
916
  var _a2, _b2, _c2, _d2, _e, _f;
1010
917
  const match = this.getMatch(matchId);
1011
918
  if (!match) {
@@ -1017,20 +924,13 @@ class RouterCore {
1017
924
  params: match.params,
1018
925
  loaderData: match.loaderData
1019
926
  };
1020
- const headFnContent = (_b2 = (_a2 = route.options).head) == null ? void 0 : _b2.call(_a2, assetContext);
927
+ const headFnContent = await ((_b2 = (_a2 = route.options).head) == null ? void 0 : _b2.call(_a2, assetContext));
1021
928
  const meta = headFnContent == null ? void 0 : headFnContent.meta;
1022
929
  const links = headFnContent == null ? void 0 : headFnContent.links;
1023
930
  const headScripts = headFnContent == null ? void 0 : headFnContent.scripts;
1024
- const scripts = (_d2 = (_c2 = route.options).scripts) == null ? void 0 : _d2.call(_c2, assetContext);
1025
- const headers = (_f = (_e = route.options).headers) == null ? void 0 : _f.call(_e, assetContext);
1026
- updateMatch(matchId, (prev) => ({
1027
- ...prev,
1028
- meta,
1029
- links,
1030
- headScripts,
1031
- headers,
1032
- scripts
1033
- }));
931
+ const scripts = await ((_d2 = (_c2 = route.options).scripts) == null ? void 0 : _d2.call(_c2, assetContext));
932
+ const headers = await ((_f = (_e = route.options).headers) == null ? void 0 : _f.call(_e, assetContext));
933
+ return { meta, links, headScripts, headers, scripts };
1034
934
  };
1035
935
  const runLoader = async () => {
1036
936
  var _a2, _b2, _c2, _d2, _e;
@@ -1055,17 +955,19 @@ class RouterCore {
1055
955
  await route._lazyPromise;
1056
956
  await potentialPendingMinPromise();
1057
957
  await route._componentsPromise;
1058
- batch(() => {
1059
- updateMatch(matchId, (prev) => ({
1060
- ...prev,
1061
- error: void 0,
1062
- status: "success",
1063
- isFetching: false,
1064
- updatedAt: Date.now(),
1065
- loaderData
1066
- }));
1067
- executeHead();
1068
- });
958
+ updateMatch(matchId, (prev) => ({
959
+ ...prev,
960
+ error: void 0,
961
+ status: "success",
962
+ isFetching: false,
963
+ updatedAt: Date.now(),
964
+ loaderData
965
+ }));
966
+ const head = await executeHead();
967
+ updateMatch(matchId, (prev) => ({
968
+ ...prev,
969
+ ...head
970
+ }));
1069
971
  } catch (e) {
1070
972
  let error = e;
1071
973
  await potentialPendingMinPromise();
@@ -1079,28 +981,26 @@ class RouterCore {
1079
981
  onErrorError
1080
982
  );
1081
983
  }
1082
- batch(() => {
1083
- updateMatch(matchId, (prev) => ({
1084
- ...prev,
1085
- error,
1086
- status: "error",
1087
- isFetching: false
1088
- }));
1089
- executeHead();
1090
- });
984
+ const head = await executeHead();
985
+ updateMatch(matchId, (prev) => ({
986
+ ...prev,
987
+ error,
988
+ status: "error",
989
+ isFetching: false,
990
+ ...head
991
+ }));
1091
992
  }
1092
993
  (_e = this.serverSsr) == null ? void 0 : _e.onMatchSettled({
1093
994
  router: this,
1094
995
  match: this.getMatch(matchId)
1095
996
  });
1096
997
  } catch (err) {
1097
- batch(() => {
1098
- updateMatch(matchId, (prev) => ({
1099
- ...prev,
1100
- loaderPromise: void 0
1101
- }));
1102
- executeHead();
1103
- });
998
+ const head = await executeHead();
999
+ updateMatch(matchId, (prev) => ({
1000
+ ...prev,
1001
+ loaderPromise: void 0,
1002
+ ...head
1003
+ }));
1104
1004
  handleRedirectAndNotFound(this.getMatch(matchId), err);
1105
1005
  }
1106
1006
  };
@@ -1128,7 +1028,11 @@ class RouterCore {
1128
1028
  } else if (status !== "success" || loaderShouldRunAsync && sync) {
1129
1029
  await runLoader();
1130
1030
  } else {
1131
- executeHead();
1031
+ const head = await executeHead();
1032
+ updateMatch(matchId, (prev) => ({
1033
+ ...prev,
1034
+ ...head
1035
+ }));
1132
1036
  }
1133
1037
  }
1134
1038
  if (!loaderIsRunningAsync) {
@@ -1792,6 +1696,84 @@ function getMatchedRoutes({
1792
1696
  }
1793
1697
  return { matchedRoutes, routeParams, foundRoute };
1794
1698
  }
1699
+ function applySearchMiddleware({
1700
+ search,
1701
+ dest,
1702
+ destRoutes,
1703
+ _includeValidateSearch
1704
+ }) {
1705
+ const allMiddlewares = destRoutes.reduce(
1706
+ (acc, route) => {
1707
+ var _a;
1708
+ const middlewares = [];
1709
+ if ("search" in route.options) {
1710
+ if ((_a = route.options.search) == null ? void 0 : _a.middlewares) {
1711
+ middlewares.push(...route.options.search.middlewares);
1712
+ }
1713
+ } else if (route.options.preSearchFilters || route.options.postSearchFilters) {
1714
+ const legacyMiddleware = ({
1715
+ search: search2,
1716
+ next
1717
+ }) => {
1718
+ let nextSearch = search2;
1719
+ if ("preSearchFilters" in route.options && route.options.preSearchFilters) {
1720
+ nextSearch = route.options.preSearchFilters.reduce(
1721
+ (prev, next2) => next2(prev),
1722
+ search2
1723
+ );
1724
+ }
1725
+ const result = next(nextSearch);
1726
+ if ("postSearchFilters" in route.options && route.options.postSearchFilters) {
1727
+ return route.options.postSearchFilters.reduce(
1728
+ (prev, next2) => next2(prev),
1729
+ result
1730
+ );
1731
+ }
1732
+ return result;
1733
+ };
1734
+ middlewares.push(legacyMiddleware);
1735
+ }
1736
+ if (_includeValidateSearch && route.options.validateSearch) {
1737
+ const validate = ({ search: search2, next }) => {
1738
+ const result = next(search2);
1739
+ try {
1740
+ const validatedSearch = {
1741
+ ...result,
1742
+ ...validateSearch(route.options.validateSearch, result) ?? {}
1743
+ };
1744
+ return validatedSearch;
1745
+ } catch {
1746
+ return result;
1747
+ }
1748
+ };
1749
+ middlewares.push(validate);
1750
+ }
1751
+ return acc.concat(middlewares);
1752
+ },
1753
+ []
1754
+ ) ?? [];
1755
+ const final = ({ search: search2 }) => {
1756
+ if (!dest.search) {
1757
+ return {};
1758
+ }
1759
+ if (dest.search === true) {
1760
+ return search2;
1761
+ }
1762
+ return functionalUpdate(dest.search, search2);
1763
+ };
1764
+ allMiddlewares.push(final);
1765
+ const applyNext = (index, currentSearch) => {
1766
+ if (index >= allMiddlewares.length) {
1767
+ return currentSearch;
1768
+ }
1769
+ const middleware = allMiddlewares[index];
1770
+ const next = (newSearch) => {
1771
+ return applyNext(index + 1, newSearch);
1772
+ };
1773
+ return middleware({ search: currentSearch, next });
1774
+ };
1775
+ return applyNext(0, search);
1776
+ }
1795
1777
  export {
1796
1778
  PathParamError,
1797
1779
  RouterCore,