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