@tanstack/router-core 0.0.1-beta.185 → 0.0.1-beta.187

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.
@@ -105,11 +105,13 @@
105
105
  };
106
106
  },
107
107
  push: (path, state) => {
108
+ assignKey(state);
108
109
  queueTask(() => {
109
110
  opts.pushState(path, state);
110
111
  });
111
112
  },
112
113
  replace: (path, state) => {
114
+ assignKey(state);
113
115
  queueTask(() => {
114
116
  opts.replaceState(path, state);
115
117
  });
@@ -146,6 +148,16 @@
146
148
  }
147
149
  };
148
150
  }
151
+ function assignKey(state) {
152
+ state.key = createRandomKey();
153
+ // if (state.__actualLocation) {
154
+ // state.__actualLocation.state = {
155
+ // ...state.__actualLocation.state,
156
+ // key,
157
+ // }
158
+ // }
159
+ }
160
+
149
161
  function createBrowserHistory(opts) {
150
162
  const getHref = opts?.getHref ?? (() => `${window.location.pathname}${window.location.search}${window.location.hash}`);
151
163
  const createHref = opts?.createHref ?? (path => path);
@@ -175,16 +187,10 @@
175
187
  };
176
188
  },
177
189
  pushState: (path, state) => {
178
- window.history.pushState({
179
- ...state,
180
- key: createRandomKey()
181
- }, '', createHref(path));
190
+ window.history.pushState(state, '', createHref(path));
182
191
  },
183
192
  replaceState: (path, state) => {
184
- window.history.replaceState({
185
- ...state,
186
- key: createRandomKey()
187
- }, '', createHref(path));
193
+ window.history.replaceState(state, '', createHref(path));
188
194
  },
189
195
  back: () => window.history.back(),
190
196
  forward: () => window.history.forward(),
@@ -203,24 +209,20 @@
203
209
  }) {
204
210
  const entries = opts.initialEntries;
205
211
  let index = opts.initialIndex ?? entries.length - 1;
206
- let currentState = {};
212
+ let currentState = {
213
+ key: createRandomKey()
214
+ };
207
215
  const getLocation = () => parseLocation(entries[index], currentState);
208
216
  return createHistory({
209
217
  getLocation,
210
218
  subscriber: false,
211
219
  pushState: (path, state) => {
212
- currentState = {
213
- ...state,
214
- key: createRandomKey()
215
- };
220
+ currentState = state;
216
221
  entries.push(path);
217
222
  index++;
218
223
  },
219
224
  replaceState: (path, state) => {
220
- currentState = {
221
- ...state,
222
- key: createRandomKey()
223
- };
225
+ currentState = state;
224
226
  entries[index] = path;
225
227
  },
226
228
  back: () => {
@@ -241,7 +243,7 @@
241
243
  pathname: href.substring(0, hashIndex > 0 ? searchIndex > 0 ? Math.min(hashIndex, searchIndex) : hashIndex : searchIndex > 0 ? searchIndex : href.length),
242
244
  hash: hashIndex > -1 ? href.substring(hashIndex) : '',
243
245
  search: searchIndex > -1 ? href.slice(searchIndex, hashIndex === -1 ? undefined : hashIndex) : '',
244
- state
246
+ state: state || {}
245
247
  };
246
248
  }
247
249
 
@@ -250,6 +252,21 @@
250
252
  return (Math.random() + 1).toString(36).substring(7);
251
253
  }
252
254
 
255
+ // type Compute<T> = { [K in keyof T]: T[K] } | never
256
+
257
+ // type AllKeys<T> = T extends any ? keyof T : never
258
+
259
+ // export type MergeUnion<T, Keys extends keyof T = keyof T> = Compute<
260
+ // {
261
+ // [K in Keys]: T[Keys]
262
+ // } & {
263
+ // [K in AllKeys<T>]?: T extends any
264
+ // ? K extends keyof T
265
+ // ? T[K]
266
+ // : never
267
+ // : never
268
+ // }
269
+ // >
253
270
  function last(arr) {
254
271
  return arr[arr.length - 1];
255
272
  }
@@ -659,6 +676,9 @@
659
676
  super(options);
660
677
  }
661
678
  }
679
+ function createRouteMask(opts) {
680
+ return opts;
681
+ }
662
682
 
663
683
  class FileRoute {
664
684
  constructor(path) {
@@ -808,6 +828,9 @@
808
828
  class Router {
809
829
  #unsubHistory;
810
830
  resetNextScroll = false;
831
+ tempLocationKey = `${Math.round(Math.random() * 10000000)}`;
832
+ // nextTemporaryLocation?: ParsedLocation<FullSearchSchema<TRouteTree>>
833
+
811
834
  constructor(options) {
812
835
  this.options = {
813
836
  defaultPreloadDelay: 50,
@@ -856,15 +879,15 @@
856
879
  });
857
880
  this.state = this.__store.state;
858
881
  this.update(options);
859
- const next = this.buildNext({
860
- hash: true,
861
- fromCurrent: true,
882
+ const nextLocation = this.buildLocation({
862
883
  search: true,
884
+ params: true,
885
+ hash: true,
863
886
  state: true
864
887
  });
865
- if (this.state.location.href !== next.href) {
888
+ if (this.state.location.href !== nextLocation.href) {
866
889
  this.#commitLocation({
867
- ...next,
890
+ ...nextLocation,
868
891
  replace: true
869
892
  });
870
893
  }
@@ -907,8 +930,10 @@
907
930
  };
908
931
  };
909
932
  #onFocus = () => {
910
- if (this.options.refetchOnWindowFocus ?? true) {
911
- this.invalidate();
933
+ if (this.options.reloadOnWindowFocus ?? true) {
934
+ this.invalidate({
935
+ __fromFocus: true
936
+ });
912
937
  }
913
938
  };
914
939
  update = opts => {
@@ -947,14 +972,6 @@
947
972
  }
948
973
  return this;
949
974
  };
950
- buildNext = opts => {
951
- const next = this.#buildLocation(opts);
952
- const __matches = this.matchRoutes(next.pathname, next.search);
953
- return this.#buildLocation({
954
- ...opts,
955
- __matches
956
- });
957
- };
958
975
  cancelMatches = () => {
959
976
  this.state.matches.forEach(match => {
960
977
  this.cancelMatch(match.id);
@@ -1013,7 +1030,7 @@
1013
1030
  try {
1014
1031
  // Load the matches
1015
1032
  try {
1016
- await this.loadMatches(pendingMatches);
1033
+ await this.loadMatches(pendingMatches.map(d => d.id));
1017
1034
  } catch (err) {
1018
1035
  // swallow this error, since we'll display the
1019
1036
  // errors on the route components
@@ -1062,10 +1079,19 @@
1062
1079
  return this.latestLoadPromise;
1063
1080
  };
1064
1081
  #mergeMatches = (prevMatchesById, nextMatches) => {
1065
- return {
1066
- ...prevMatchesById,
1067
- ...Object.fromEntries(nextMatches.map(match => [match.id, match]))
1082
+ let matchesById = {
1083
+ ...prevMatchesById
1068
1084
  };
1085
+ nextMatches.forEach(match => {
1086
+ if (!matchesById[match.id]) {
1087
+ matchesById[match.id] = match;
1088
+ }
1089
+ matchesById[match.id] = {
1090
+ ...matchesById[match.id],
1091
+ ...match
1092
+ };
1093
+ });
1094
+ return matchesById;
1069
1095
  };
1070
1096
  getRoute = id => {
1071
1097
  const route = this.routesById[id];
@@ -1073,7 +1099,7 @@
1073
1099
  return route;
1074
1100
  };
1075
1101
  preloadRoute = async (navigateOpts = this.state.location) => {
1076
- const next = this.buildNext(navigateOpts);
1102
+ let next = this.buildLocation(navigateOpts);
1077
1103
  const matches = this.matchRoutes(next.pathname, next.search, {
1078
1104
  throwOnError: true
1079
1105
  });
@@ -1083,11 +1109,11 @@
1083
1109
  matchesById: this.#mergeMatches(s.matchesById, matches)
1084
1110
  };
1085
1111
  });
1086
- await this.loadMatches(matches, {
1112
+ await this.loadMatches(matches.map(d => d.id), {
1087
1113
  preload: true,
1088
1114
  maxAge: navigateOpts.maxAge
1089
1115
  });
1090
- return matches;
1116
+ return [last(matches), matches];
1091
1117
  };
1092
1118
  cleanMatches = () => {
1093
1119
  const now = Date.now();
@@ -1241,8 +1267,8 @@
1241
1267
  });
1242
1268
  return matches;
1243
1269
  };
1244
- loadMatches = async (_resolvedMatches, opts) => {
1245
- const getFreshMatches = () => _resolvedMatches.map(d => this.getRouteMatch(d.id));
1270
+ loadMatches = async (matchIds, opts) => {
1271
+ const getFreshMatches = () => matchIds.map(d => this.getRouteMatch(d));
1246
1272
  if (!opts?.preload) {
1247
1273
  getFreshMatches().forEach(match => {
1248
1274
  // Update each match with its latest route data
@@ -1322,8 +1348,9 @@
1322
1348
  }
1323
1349
  }
1324
1350
  } catch (err) {
1325
- if (!opts?.preload) {
1326
- this.navigate(err);
1351
+ if (isRedirect(err)) {
1352
+ if (!opts?.preload) this.navigate(err);
1353
+ return;
1327
1354
  }
1328
1355
  throw err;
1329
1356
  }
@@ -1432,13 +1459,13 @@
1432
1459
  isExternal = true;
1433
1460
  } catch (e) {}
1434
1461
  invariant(!isExternal, 'Attempting to navigate to external url with this.navigate!');
1435
- return this.#commitLocation({
1462
+ return this.#buildAndCommitLocation({
1436
1463
  from: fromString,
1437
1464
  to: toString,
1438
1465
  search,
1439
1466
  hash,
1440
- replace,
1441
1467
  params,
1468
+ replace,
1442
1469
  resetScroll
1443
1470
  });
1444
1471
  };
@@ -1447,7 +1474,7 @@
1447
1474
  ...location,
1448
1475
  to: location.to ? this.resolvePath(location.from ?? '', location.to) : undefined
1449
1476
  };
1450
- const next = this.buildNext(location);
1477
+ const next = this.buildLocation(location);
1451
1478
  if (opts?.pending && this.state.status !== 'pending') {
1452
1479
  return false;
1453
1480
  }
@@ -1480,6 +1507,7 @@
1480
1507
  preloadDelay: userPreloadDelay,
1481
1508
  disabled,
1482
1509
  state,
1510
+ mask,
1483
1511
  resetScroll
1484
1512
  }) => {
1485
1513
  // If this link simply reloads the current route,
@@ -1503,9 +1531,10 @@
1503
1531
  hash,
1504
1532
  replace,
1505
1533
  state,
1534
+ mask,
1506
1535
  resetScroll
1507
1536
  };
1508
- const next = this.buildNext(nextOpts);
1537
+ const next = this.buildLocation(nextOpts);
1509
1538
  preload = preload ?? this.options.defaultPreload;
1510
1539
  const preloadDelay = userPreloadDelay ?? this.options.defaultPreloadDelay ?? 0;
1511
1540
 
@@ -1527,7 +1556,11 @@
1527
1556
  e.preventDefault();
1528
1557
 
1529
1558
  // All is well? Navigate!
1530
- this.#commitLocation(nextOpts);
1559
+ this.#commitLocation({
1560
+ ...next,
1561
+ replace,
1562
+ resetScroll
1563
+ });
1531
1564
  }
1532
1565
  };
1533
1566
 
@@ -1740,84 +1773,180 @@
1740
1773
  });
1741
1774
  };
1742
1775
  #parseLocation = previousLocation => {
1743
- let {
1776
+ const parse = ({
1744
1777
  pathname,
1745
1778
  search,
1746
1779
  hash,
1747
1780
  state
1748
- } = this.history.location;
1749
- const parsedSearch = this.options.parseSearch(search);
1750
- return {
1751
- pathname: pathname,
1752
- searchStr: search,
1753
- search: replaceEqualDeep(previousLocation?.search, parsedSearch),
1754
- hash: hash.split('#').reverse()[0] ?? '',
1755
- href: `${pathname}${search}${hash}`,
1756
- state: state,
1757
- key: state?.key || '__init__'
1781
+ }) => {
1782
+ const parsedSearch = this.options.parseSearch(search);
1783
+ return {
1784
+ pathname: pathname,
1785
+ searchStr: search,
1786
+ search: replaceEqualDeep(previousLocation?.search, parsedSearch),
1787
+ hash: hash.split('#').reverse()[0] ?? '',
1788
+ href: `${pathname}${search}${hash}`,
1789
+ state: replaceEqualDeep(previousLocation?.state, state)
1790
+ };
1758
1791
  };
1792
+ const location = parse(this.history.location);
1793
+ let {
1794
+ __tempLocation,
1795
+ __tempKey
1796
+ } = location.state;
1797
+ if (__tempLocation && (!__tempKey || __tempKey === this.tempLocationKey)) {
1798
+ // Sync up the location keys
1799
+ const parsedTempLocation = parse(__tempLocation);
1800
+ parsedTempLocation.state.key = location.state.key;
1801
+ delete parsedTempLocation.state.__tempLocation;
1802
+ return {
1803
+ ...parsedTempLocation,
1804
+ maskedLocation: location
1805
+ };
1806
+ }
1807
+ return location;
1759
1808
  };
1760
- #buildLocation = (dest = {}) => {
1761
- dest.fromCurrent = dest.fromCurrent ?? dest.to === '';
1762
- const fromPathname = dest.fromCurrent ? this.state.location.pathname : dest.from ?? this.state.location.pathname;
1763
- let pathname = resolvePath(this.basepath ?? '/', fromPathname, `${dest.to ?? ''}`);
1764
- const fromMatches = this.matchRoutes(this.state.location.pathname, this.state.location.search);
1765
- const prevParams = {
1766
- ...last(fromMatches)?.params
1809
+ buildLocation = (opts = {}) => {
1810
+ const build = (dest = {}, matches) => {
1811
+ const from = this.state.location;
1812
+ const fromPathname = dest.from ?? from.pathname;
1813
+ let pathname = resolvePath(this.basepath ?? '/', fromPathname, `${dest.to ?? ''}`);
1814
+ const fromMatches = this.matchRoutes(fromPathname, from.search);
1815
+ const prevParams = {
1816
+ ...last(fromMatches)?.params
1817
+ };
1818
+ let nextParams = (dest.params ?? true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
1819
+ if (nextParams) {
1820
+ matches?.map(d => this.getRoute(d.routeId).options.stringifyParams).filter(Boolean).forEach(fn => {
1821
+ nextParams = {
1822
+ ...nextParams,
1823
+ ...fn(nextParams)
1824
+ };
1825
+ });
1826
+ }
1827
+ pathname = interpolatePath(pathname, nextParams ?? {});
1828
+ const preSearchFilters = matches?.map(match => this.getRoute(match.routeId).options.preSearchFilters ?? []).flat().filter(Boolean) ?? [];
1829
+ const postSearchFilters = matches?.map(match => this.getRoute(match.routeId).options.postSearchFilters ?? []).flat().filter(Boolean) ?? [];
1830
+
1831
+ // Pre filters first
1832
+ const preFilteredSearch = preSearchFilters?.length ? preSearchFilters?.reduce((prev, next) => next(prev), from.search) : from.search;
1833
+
1834
+ // Then the link/navigate function
1835
+ const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
1836
+ : dest.search ? functionalUpdate(dest.search, preFilteredSearch) ?? {} // Updater
1837
+ : preSearchFilters?.length ? preFilteredSearch // Preserve resolvedFrom filters
1838
+ : {};
1839
+
1840
+ // Then post filters
1841
+ const postFilteredSearch = postSearchFilters?.length ? postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
1842
+ const search = replaceEqualDeep(from.search, postFilteredSearch);
1843
+ const searchStr = this.options.stringifySearch(search);
1844
+ const hash = dest.hash === true ? from.hash : dest.hash ? functionalUpdate(dest.hash, from.hash) : from.hash;
1845
+ const hashStr = hash ? `#${hash}` : '';
1846
+ let nextState = dest.state === true ? from.state : dest.state ? functionalUpdate(dest.state, from.state) : from.state;
1847
+ nextState = replaceEqualDeep(from.state, nextState);
1848
+ return {
1849
+ pathname,
1850
+ search,
1851
+ searchStr,
1852
+ state: nextState,
1853
+ hash,
1854
+ href: this.history.createHref(`${pathname}${searchStr}${hashStr}`),
1855
+ unmaskOnReload: dest.unmaskOnReload
1856
+ };
1767
1857
  };
1768
- let nextParams = (dest.params ?? true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
1769
- if (nextParams) {
1770
- dest.__matches?.map(d => this.getRoute(d.routeId).options.stringifyParams).filter(Boolean).forEach(fn => {
1771
- nextParams = {
1772
- ...nextParams,
1773
- ...fn(nextParams)
1774
- };
1858
+ const buildWithMatches = (dest = {}, maskedDest) => {
1859
+ let next = build(dest);
1860
+ let maskedNext = maskedDest ? build(maskedDest) : undefined;
1861
+ if (!maskedNext) {
1862
+ let params = {};
1863
+ let foundMask = this.options.routeMasks?.find(d => {
1864
+ const match = matchPathname(this.basepath, next.pathname, {
1865
+ to: d.from,
1866
+ fuzzy: false
1867
+ });
1868
+ if (match) {
1869
+ params = match;
1870
+ return true;
1871
+ }
1872
+ return false;
1873
+ });
1874
+ if (foundMask) {
1875
+ foundMask = {
1876
+ ...foundMask,
1877
+ from: interpolatePath(foundMask.from, params)
1878
+ };
1879
+ maskedDest = foundMask;
1880
+ maskedNext = build(maskedDest);
1881
+ }
1882
+ }
1883
+ const nextMatches = this.matchRoutes(next.pathname, next.search);
1884
+ const maskedMatches = maskedNext ? this.matchRoutes(maskedNext.pathname, maskedNext.search) : undefined;
1885
+ const maskedFinal = maskedNext ? build(maskedDest, maskedMatches) : undefined;
1886
+ const final = build(dest, nextMatches);
1887
+ if (maskedFinal) {
1888
+ final.maskedLocation = maskedFinal;
1889
+ }
1890
+ return final;
1891
+ };
1892
+ if (opts.mask) {
1893
+ return buildWithMatches(opts, {
1894
+ ...pick(opts, ['from']),
1895
+ ...opts.mask
1775
1896
  });
1776
1897
  }
1777
- pathname = interpolatePath(pathname, nextParams ?? {});
1778
- const preSearchFilters = dest.__matches?.map(match => this.getRoute(match.routeId).options.preSearchFilters ?? []).flat().filter(Boolean) ?? [];
1779
- const postSearchFilters = dest.__matches?.map(match => this.getRoute(match.routeId).options.postSearchFilters ?? []).flat().filter(Boolean) ?? [];
1780
-
1781
- // Pre filters first
1782
- const preFilteredSearch = preSearchFilters?.length ? preSearchFilters?.reduce((prev, next) => next(prev), this.state.location.search) : this.state.location.search;
1783
-
1784
- // Then the link/navigate function
1785
- const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
1786
- : dest.search ? functionalUpdate(dest.search, preFilteredSearch) ?? {} // Updater
1787
- : preSearchFilters?.length ? preFilteredSearch // Preserve resolvedFrom filters
1788
- : {};
1789
-
1790
- // Then post filters
1791
- const postFilteredSearch = postSearchFilters?.length ? postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
1792
- const search = replaceEqualDeep(this.state.location.search, postFilteredSearch);
1793
- const searchStr = this.options.stringifySearch(search);
1794
- const hash = dest.hash === true ? this.state.location.hash : functionalUpdate(dest.hash, this.state.location.hash);
1795
- const hashStr = hash ? `#${hash}` : '';
1796
- const nextState = dest.state === true ? this.state.location.state : functionalUpdate(dest.state, this.state.location.state);
1797
- return {
1798
- pathname,
1799
- search,
1800
- searchStr,
1801
- state: nextState,
1802
- hash,
1803
- href: this.history.createHref(`${pathname}${searchStr}${hashStr}`),
1804
- key: dest.key
1805
- };
1898
+ return buildWithMatches(opts);
1899
+ };
1900
+ #buildAndCommitLocation = ({
1901
+ replace,
1902
+ resetScroll,
1903
+ ...rest
1904
+ } = {}) => {
1905
+ const location = this.buildLocation(rest);
1906
+ return this.#commitLocation({
1907
+ ...location,
1908
+ replace,
1909
+ resetScroll
1910
+ });
1806
1911
  };
1807
- #commitLocation = async location => {
1808
- const next = this.buildNext(location);
1912
+ #commitLocation = async next => {
1809
1913
  if (this.navigateTimeout) clearTimeout(this.navigateTimeout);
1810
1914
  let nextAction = 'replace';
1811
- if (!location.replace) {
1915
+ if (!next.replace) {
1812
1916
  nextAction = 'push';
1813
1917
  }
1814
1918
  const isSameUrl = this.state.location.href === next.href;
1815
- if (isSameUrl && !next.key) {
1919
+ if (isSameUrl) {
1816
1920
  nextAction = 'replace';
1817
1921
  }
1818
- const href = `${next.pathname}${next.searchStr}${next.hash ? `#${next.hash}` : ''}`;
1819
- this.history[nextAction === 'push' ? 'push' : 'replace'](href, next.state);
1820
- this.resetNextScroll = location.resetScroll ?? true;
1922
+ let {
1923
+ maskedLocation,
1924
+ ...nextHistory
1925
+ } = next;
1926
+ if (maskedLocation) {
1927
+ nextHistory = {
1928
+ ...maskedLocation,
1929
+ state: {
1930
+ ...maskedLocation.state,
1931
+ __tempKey: undefined,
1932
+ __tempLocation: {
1933
+ ...nextHistory,
1934
+ search: nextHistory.searchStr,
1935
+ state: {
1936
+ ...nextHistory.state,
1937
+ __tempKey: undefined,
1938
+ __tempLocation: undefined,
1939
+ key: undefined
1940
+ }
1941
+ }
1942
+ }
1943
+ };
1944
+ if (nextHistory.unmaskOnReload ?? this.options.unmaskOnReload ?? false) {
1945
+ nextHistory.state.__tempKey = this.tempLocationKey;
1946
+ }
1947
+ }
1948
+ this.history[nextAction === 'push' ? 'push' : 'replace'](nextHistory.href, nextHistory.state);
1949
+ this.resetNextScroll = next.resetScroll ?? true;
1821
1950
  return this.latestLoadPromise;
1822
1951
  };
1823
1952
  getRouteMatch = id => {
@@ -1866,25 +1995,26 @@
1866
1995
  if (childMatch) {
1867
1996
  return this.invalidate({
1868
1997
  matchId: childMatch.id,
1869
- reload: false
1998
+ reload: false,
1999
+ __fromFocus: opts.__fromFocus
1870
2000
  });
1871
2001
  }
1872
2002
  } else {
1873
2003
  this.__store.batch(() => {
1874
2004
  Object.values(this.state.matchesById).forEach(match => {
1875
- this.setRouteMatch(match.id, s => ({
1876
- ...s,
1877
- invalid: true
1878
- }));
2005
+ const route = this.getRoute(match.routeId);
2006
+ const shouldInvalidate = opts?.__fromFocus ? route.options.reloadOnWindowFocus ?? true : true;
2007
+ if (shouldInvalidate) {
2008
+ this.setRouteMatch(match.id, s => ({
2009
+ ...s,
2010
+ invalid: true
2011
+ }));
2012
+ }
1879
2013
  });
1880
2014
  });
1881
2015
  }
1882
2016
  if (opts?.reload ?? true) {
1883
- return this.navigate({
1884
- fromCurrent: true,
1885
- replace: true,
1886
- search: true
1887
- });
2017
+ return this.load();
1888
2018
  }
1889
2019
  };
1890
2020
  }
@@ -1951,7 +2081,7 @@
1951
2081
  let cache;
1952
2082
  let pathDidChange = false;
1953
2083
  const sessionsStorage = typeof window !== 'undefined' && window.sessionStorage;
1954
- const defaultGetKey = location => location.key;
2084
+ const defaultGetKey = location => location.state.key;
1955
2085
  function watchScrollPositions(router, opts) {
1956
2086
  const getKey = opts?.getKey || defaultGetKey;
1957
2087
  if (sessionsStorage) {
@@ -2101,6 +2231,7 @@
2101
2231
  exports.createBrowserHistory = createBrowserHistory;
2102
2232
  exports.createHashHistory = createHashHistory;
2103
2233
  exports.createMemoryHistory = createMemoryHistory;
2234
+ exports.createRouteMask = createRouteMask;
2104
2235
  exports.decode = decode;
2105
2236
  exports.defaultParseSearch = defaultParseSearch;
2106
2237
  exports.defaultStringifySearch = defaultStringifySearch;