@tanstack/router-core 0.0.1-alpha.9 → 0.0.1-beta.2

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.
@@ -1260,6 +1260,40 @@ function createRoute(routeConfig, options, parent, router) {
1260
1260
  return router.state.actions[id];
1261
1261
  })();
1262
1262
 
1263
+ const loader = router.state.loaders[id] || (() => {
1264
+ router.state.loaders[id] = {
1265
+ pending: [],
1266
+ fetch: async loaderContext => {
1267
+ if (!route) {
1268
+ return;
1269
+ }
1270
+
1271
+ const loaderState = {
1272
+ loadedAt: Date.now(),
1273
+ loaderContext
1274
+ };
1275
+ loader.current = loaderState;
1276
+ loader.latest = loaderState;
1277
+ loader.pending.push(loaderState); // router.state = {
1278
+ // ...router.state,
1279
+ // currentAction: loaderState,
1280
+ // latestAction: loaderState,
1281
+ // }
1282
+
1283
+ router.notify();
1284
+
1285
+ try {
1286
+ return await (route.options.loader == null ? void 0 : route.options.loader(loaderContext));
1287
+ } finally {
1288
+ loader.pending = loader.pending.filter(d => d !== loaderState); // router.removeActionQueue.push({ loader, loaderState })
1289
+
1290
+ router.notify();
1291
+ }
1292
+ }
1293
+ };
1294
+ return router.state.loaders[id];
1295
+ })();
1296
+
1263
1297
  let route = {
1264
1298
  routeId: id,
1265
1299
  routeRouteId: routeId,
@@ -1270,6 +1304,7 @@ function createRoute(routeConfig, options, parent, router) {
1270
1304
  childRoutes: undefined,
1271
1305
  parentRoute: parent,
1272
1306
  action,
1307
+ loader: loader,
1273
1308
  buildLink: options => {
1274
1309
  return router.buildLink(_extends({}, options, {
1275
1310
  from: fullPath
@@ -1457,9 +1492,33 @@ function createRouteMatch(router, route, opts) {
1457
1492
  routeMatch.isInvalid = true;
1458
1493
  },
1459
1494
  hasLoaders: () => {
1460
- return !!(route.options.loader || route.options.import || elementTypes.some(d => typeof route.options[d] === 'function'));
1495
+ return !!(route.options.loader || elementTypes.some(d => typeof route.options[d] === 'function'));
1461
1496
  },
1462
- load: async opts => {
1497
+ load: async loaderOpts => {
1498
+ const now = Date.now();
1499
+ const minMaxAge = loaderOpts != null && loaderOpts.preload ? Math.max(loaderOpts == null ? void 0 : loaderOpts.maxAge, loaderOpts == null ? void 0 : loaderOpts.gcMaxAge) : 0; // If this is a preload, add it to the preload cache
1500
+
1501
+ if (loaderOpts != null && loaderOpts.preload && minMaxAge > 0) {
1502
+ // If the match is currently active, don't preload it
1503
+ if (router.state.matches.find(d => d.matchId === routeMatch.matchId)) {
1504
+ return;
1505
+ }
1506
+
1507
+ router.matchCache[routeMatch.matchId] = {
1508
+ gc: now + loaderOpts.gcMaxAge,
1509
+ match: routeMatch
1510
+ };
1511
+ } // If the match is invalid, errored or idle, trigger it to load
1512
+
1513
+
1514
+ if (routeMatch.status === 'success' && routeMatch.getIsInvalid() || routeMatch.status === 'error' || routeMatch.status === 'idle') {
1515
+ const maxAge = loaderOpts != null && loaderOpts.preload ? loaderOpts == null ? void 0 : loaderOpts.maxAge : undefined;
1516
+ routeMatch.fetch({
1517
+ maxAge
1518
+ });
1519
+ }
1520
+ },
1521
+ fetch: async opts => {
1463
1522
  const id = '' + Date.now() + Math.random();
1464
1523
  routeMatch.__.latestId = id; // If the match was in an error state, set it
1465
1524
  // to a loading state again. Otherwise, keep it
@@ -1478,21 +1537,7 @@ function createRouteMatch(router, route, opts) {
1478
1537
  routeMatch.__.resolve = resolve;
1479
1538
 
1480
1539
  const loaderPromise = (async () => {
1481
- const importer = routeMatch.options.import; // First, run any importers
1482
-
1483
- if (importer) {
1484
- routeMatch.__.importPromise = importer({
1485
- params: routeMatch.params // search: routeMatch.search,
1486
-
1487
- }).then(imported => {
1488
- routeMatch.__ = _extends({}, routeMatch.__, imported);
1489
- });
1490
- } // Wait for the importer to finish before
1491
- // attempting to load elements and data
1492
-
1493
-
1494
- await routeMatch.__.importPromise; // Next, load the elements and data in parallel
1495
-
1540
+ // Load the elements and data in parallel
1496
1541
  routeMatch.__.elementsPromise = (async () => {
1497
1542
  // then run all element and data loaders in parallel
1498
1543
  // For each element type, potentially load it asynchronously
@@ -1503,12 +1548,7 @@ function createRouteMatch(router, route, opts) {
1503
1548
  return;
1504
1549
  }
1505
1550
 
1506
- if (typeof routeElement === 'function') {
1507
- const res = await routeElement(routeMatch);
1508
- routeMatch.__[type] = res;
1509
- } else {
1510
- routeMatch.__[type] = routeMatch.options[type];
1511
- }
1551
+ routeMatch.__[type] = await router.options.createElement(routeElement);
1512
1552
  }));
1513
1553
  })();
1514
1554
 
@@ -1664,6 +1704,7 @@ function createRouter(userOptions) {
1664
1704
  });
1665
1705
 
1666
1706
  let router = {
1707
+ history,
1667
1708
  options: originalOptions,
1668
1709
  listeners: [],
1669
1710
  removeActionQueue: [],
@@ -1682,6 +1723,7 @@ function createRouter(userOptions) {
1682
1723
  location: null,
1683
1724
  matches: [],
1684
1725
  actions: {},
1726
+ loaders: {},
1685
1727
  loaderData: {},
1686
1728
  lastUpdated: Date.now(),
1687
1729
  isFetching: false,
@@ -1703,24 +1745,25 @@ function createRouter(userOptions) {
1703
1745
  isPreloading: Object.values(router.matchCache).some(d => d.match.isFetching && !router.state.matches.find(dd => dd.matchId === d.match.matchId))
1704
1746
  });
1705
1747
  cascadeLoaderData(router.state.matches);
1706
- router.listeners.forEach(listener => listener());
1748
+ router.listeners.forEach(listener => listener(router));
1707
1749
  },
1708
1750
  mount: () => {
1709
- const next = router.buildLocation({
1751
+ const next = router.__.buildLocation({
1710
1752
  to: '.',
1711
1753
  search: true,
1712
1754
  hash: true
1713
1755
  }); // If the current location isn't updated, trigger a navigation
1714
1756
  // to the current location. Otherwise, load the current location.
1715
1757
 
1758
+
1716
1759
  if (next.href !== router.location.href) {
1717
- router.commitLocation(next, true);
1760
+ router.__.commitLocation(next, true);
1718
1761
  } else {
1719
1762
  router.loadLocation();
1720
1763
  }
1721
1764
 
1722
1765
  const unsub = history.listen(event => {
1723
- router.loadLocation(router.parseLocation(event.location, router.location));
1766
+ router.loadLocation(router.__.parseLocation(event.location, router.location));
1724
1767
  }); // addEventListener does not exist in React Native, but window does
1725
1768
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1726
1769
 
@@ -1750,169 +1793,11 @@ function createRouter(userOptions) {
1750
1793
 
1751
1794
  if (routeConfig) {
1752
1795
  router.routesById = {};
1753
- router.routeTree = router.buildRouteTree(routeConfig);
1796
+ router.routeTree = router.__.buildRouteTree(routeConfig);
1754
1797
  }
1755
1798
 
1756
1799
  return router;
1757
1800
  },
1758
- buildRouteTree: rootRouteConfig => {
1759
- const recurseRoutes = (routeConfigs, parent) => {
1760
- return routeConfigs.map(routeConfig => {
1761
- const routeOptions = routeConfig.options;
1762
- const route = createRoute(routeConfig, routeOptions, parent, router); // {
1763
- // pendingMs: routeOptions.pendingMs ?? router.defaultPendingMs,
1764
- // pendingMinMs: routeOptions.pendingMinMs ?? router.defaultPendingMinMs,
1765
- // }
1766
-
1767
- const existingRoute = router.routesById[route.routeId];
1768
-
1769
- if (existingRoute) {
1770
- if (process.env.NODE_ENV !== 'production') {
1771
- console.warn("Duplicate routes found with id: " + String(route.routeId), router.routesById, route);
1772
- }
1773
-
1774
- throw new Error();
1775
- }
1776
- router.routesById[route.routeId] = route;
1777
- const children = routeConfig.children;
1778
- route.childRoutes = children != null && children.length ? recurseRoutes(children, route) : undefined;
1779
- return route;
1780
- });
1781
- };
1782
-
1783
- const routes = recurseRoutes([rootRouteConfig]);
1784
- return routes[0];
1785
- },
1786
- parseLocation: (location, previousLocation) => {
1787
- var _location$hash$split$;
1788
-
1789
- const parsedSearch = router.options.parseSearch(location.search);
1790
- return {
1791
- pathname: location.pathname,
1792
- searchStr: location.search,
1793
- search: replaceEqualDeep(previousLocation == null ? void 0 : previousLocation.search, parsedSearch),
1794
- hash: (_location$hash$split$ = location.hash.split('#').reverse()[0]) != null ? _location$hash$split$ : '',
1795
- href: "" + location.pathname + location.search + location.hash,
1796
- state: location.state,
1797
- key: location.key
1798
- };
1799
- },
1800
- buildLocation: function buildLocation(dest) {
1801
- var _dest$from, _router$basepath, _dest$to, _last, _dest$params, _dest$__preSearchFilt, _functionalUpdate, _dest$__preSearchFilt2, _dest$__postSearchFil;
1802
-
1803
- if (dest === void 0) {
1804
- dest = {};
1805
- }
1806
-
1807
- // const resolvedFrom: Location = {
1808
- // ...router.location,
1809
- const fromPathname = dest.fromCurrent ? router.location.pathname : (_dest$from = dest.from) != null ? _dest$from : router.location.pathname;
1810
-
1811
- let pathname = resolvePath((_router$basepath = router.basepath) != null ? _router$basepath : '/', fromPathname, "" + ((_dest$to = dest.to) != null ? _dest$to : '.'));
1812
-
1813
- const fromMatches = router.matchRoutes(router.location.pathname, {
1814
- strictParseParams: true
1815
- });
1816
- const toMatches = router.matchRoutes(pathname);
1817
-
1818
- const prevParams = _extends({}, (_last = last(fromMatches)) == null ? void 0 : _last.params);
1819
-
1820
- let nextParams = ((_dest$params = dest.params) != null ? _dest$params : true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
1821
-
1822
- if (nextParams) {
1823
- toMatches.map(d => d.options.stringifyParams).filter(Boolean).forEach(fn => {
1824
- Object.assign({}, nextParams, fn(nextParams));
1825
- });
1826
- }
1827
-
1828
- pathname = interpolatePath(pathname, nextParams != null ? nextParams : {}); // Pre filters first
1829
-
1830
- const preFilteredSearch = (_dest$__preSearchFilt = dest.__preSearchFilters) != null && _dest$__preSearchFilt.length ? dest.__preSearchFilters.reduce((prev, next) => next(prev), router.location.search) : router.location.search; // Then the link/navigate function
1831
-
1832
- const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
1833
- : dest.search ? (_functionalUpdate = functionalUpdate(dest.search, preFilteredSearch)) != null ? _functionalUpdate : {} // Updater
1834
- : (_dest$__preSearchFilt2 = dest.__preSearchFilters) != null && _dest$__preSearchFilt2.length ? preFilteredSearch // Preserve resolvedFrom filters
1835
- : {}; // Then post filters
1836
-
1837
- const postFilteredSearch = (_dest$__postSearchFil = dest.__postSearchFilters) != null && _dest$__postSearchFil.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
1838
- const search = replaceEqualDeep(router.location.search, postFilteredSearch);
1839
- const searchStr = router.options.stringifySearch(search);
1840
- let hash = dest.hash === true ? router.location.hash : functionalUpdate(dest.hash, router.location.hash);
1841
- hash = hash ? "#" + hash : '';
1842
- return {
1843
- pathname,
1844
- search,
1845
- searchStr,
1846
- state: router.location.state,
1847
- hash,
1848
- href: "" + pathname + searchStr + hash,
1849
- key: dest.key
1850
- };
1851
- },
1852
- commitLocation: (next, replace) => {
1853
- const id = '' + Date.now() + Math.random();
1854
- if (router.navigateTimeout) clearTimeout(router.navigateTimeout);
1855
- let nextAction = 'replace';
1856
-
1857
- if (!replace) {
1858
- nextAction = 'push';
1859
- }
1860
-
1861
- const isSameUrl = router.parseLocation(history.location).href === next.href;
1862
-
1863
- if (isSameUrl && !next.key) {
1864
- nextAction = 'replace';
1865
- }
1866
-
1867
- if (nextAction === 'replace') {
1868
- history.replace({
1869
- pathname: next.pathname,
1870
- hash: next.hash,
1871
- search: next.searchStr
1872
- }, {
1873
- id
1874
- });
1875
- } else {
1876
- history.push({
1877
- pathname: next.pathname,
1878
- hash: next.hash,
1879
- search: next.searchStr
1880
- }, {
1881
- id
1882
- });
1883
- }
1884
-
1885
- router.navigationPromise = new Promise(resolve => {
1886
- const previousNavigationResolve = router.resolveNavigation;
1887
-
1888
- router.resolveNavigation = () => {
1889
- previousNavigationResolve();
1890
- resolve();
1891
- };
1892
- });
1893
- return router.navigationPromise;
1894
- },
1895
- buildNext: opts => {
1896
- const next = router.buildLocation(opts);
1897
- const matches = router.matchRoutes(next.pathname);
1898
-
1899
- const __preSearchFilters = matches.map(match => {
1900
- var _match$options$preSea;
1901
-
1902
- return (_match$options$preSea = match.options.preSearchFilters) != null ? _match$options$preSea : [];
1903
- }).flat().filter(Boolean);
1904
-
1905
- const __postSearchFilters = matches.map(match => {
1906
- var _match$options$postSe;
1907
-
1908
- return (_match$options$postSe = match.options.postSearchFilters) != null ? _match$options$postSe : [];
1909
- }).flat().filter(Boolean);
1910
-
1911
- return router.buildLocation(_extends({}, opts, {
1912
- __preSearchFilters,
1913
- __postSearchFilters
1914
- }));
1915
- },
1916
1801
  cancelMatches: () => {
1917
1802
  var _router$state$pending, _router$state$pending2;
1918
1803
  [...router.state.matches, ...((_router$state$pending = (_router$state$pending2 = router.state.pending) == null ? void 0 : _router$state$pending2.matches) != null ? _router$state$pending : [])].forEach(match => {
@@ -2015,6 +1900,7 @@ function createRouter(userOptions) {
2015
1900
  params: d.params,
2016
1901
  search: d.search
2017
1902
  });
1903
+ delete router.matchCache[d.matchId];
2018
1904
  });
2019
1905
 
2020
1906
  if (matches.some(d => d.status === 'loading')) {
@@ -2174,32 +2060,11 @@ function createRouter(userOptions) {
2174
2060
  return matches;
2175
2061
  },
2176
2062
  loadMatches: async (resolvedMatches, loaderOpts) => {
2177
- const now = Date.now();
2178
- const minMaxAge = loaderOpts != null && loaderOpts.preload ? Math.max(loaderOpts == null ? void 0 : loaderOpts.maxAge, loaderOpts == null ? void 0 : loaderOpts.gcMaxAge) : 0;
2179
2063
  const matchPromises = resolvedMatches.map(async match => {
2180
2064
  // Validate the match (loads search params etc)
2181
- match.__.validate(); // If this is a preload, add it to the preload cache
2065
+ match.__.validate();
2182
2066
 
2183
-
2184
- if (loaderOpts != null && loaderOpts.preload && minMaxAge > 0) {
2185
- // If the match is currently active, don't preload it
2186
- if (router.state.matches.find(d => d.matchId === match.matchId)) {
2187
- return;
2188
- }
2189
-
2190
- router.matchCache[match.matchId] = {
2191
- gc: now + loaderOpts.gcMaxAge,
2192
- match
2193
- };
2194
- } // If the match is invalid, errored or idle, trigger it to load
2195
-
2196
-
2197
- if (match.status === 'success' && match.getIsInvalid() || match.status === 'error' || match.status === 'idle') {
2198
- const maxAge = loaderOpts != null && loaderOpts.preload ? loaderOpts == null ? void 0 : loaderOpts.maxAge : undefined;
2199
- match.load({
2200
- maxAge
2201
- });
2202
- }
2067
+ match.load(loaderOpts);
2203
2068
 
2204
2069
  if (match.status === 'loading') {
2205
2070
  // If requested, start the pending timers
@@ -2223,7 +2088,7 @@ function createRouter(userOptions) {
2223
2088
  }
2224
2089
  });
2225
2090
  },
2226
- reload: () => router._navigate({
2091
+ reload: () => router.__.navigate({
2227
2092
  fromCurrent: true,
2228
2093
  replace: true,
2229
2094
  search: true
@@ -2256,10 +2121,6 @@ function createRouter(userOptions) {
2256
2121
  to: next.pathname
2257
2122
  }));
2258
2123
  },
2259
- _navigate: location => {
2260
- const next = router.buildNext(location);
2261
- return router.commitLocation(next, location.replace);
2262
- },
2263
2124
  navigate: async _ref8 => {
2264
2125
  let {
2265
2126
  from,
@@ -2283,7 +2144,7 @@ function createRouter(userOptions) {
2283
2144
  } catch (e) {}
2284
2145
 
2285
2146
  invariant(!isExternal, 'Attempting to navigate to external url with router.navigate!');
2286
- return router._navigate({
2147
+ return router.__.navigate({
2287
2148
  from: fromString,
2288
2149
  to: toString,
2289
2150
  search,
@@ -2355,7 +2216,7 @@ function createRouter(userOptions) {
2355
2216
  } // All is well? Navigate!)
2356
2217
 
2357
2218
 
2358
- router._navigate(nextOpts);
2219
+ router.__.navigate(nextOpts);
2359
2220
  }
2360
2221
  }; // The click handler
2361
2222
 
@@ -2406,9 +2267,174 @@ function createRouter(userOptions) {
2406
2267
  isActive,
2407
2268
  disabled
2408
2269
  };
2270
+ },
2271
+ buildNext: opts => {
2272
+ const next = router.__.buildLocation(opts);
2273
+
2274
+ const matches = router.matchRoutes(next.pathname);
2275
+
2276
+ const __preSearchFilters = matches.map(match => {
2277
+ var _match$options$preSea;
2278
+
2279
+ return (_match$options$preSea = match.options.preSearchFilters) != null ? _match$options$preSea : [];
2280
+ }).flat().filter(Boolean);
2281
+
2282
+ const __postSearchFilters = matches.map(match => {
2283
+ var _match$options$postSe;
2284
+
2285
+ return (_match$options$postSe = match.options.postSearchFilters) != null ? _match$options$postSe : [];
2286
+ }).flat().filter(Boolean);
2287
+
2288
+ return router.__.buildLocation(_extends({}, opts, {
2289
+ __preSearchFilters,
2290
+ __postSearchFilters
2291
+ }));
2292
+ },
2293
+ __: {
2294
+ buildRouteTree: rootRouteConfig => {
2295
+ const recurseRoutes = (routeConfigs, parent) => {
2296
+ return routeConfigs.map(routeConfig => {
2297
+ const routeOptions = routeConfig.options;
2298
+ const route = createRoute(routeConfig, routeOptions, parent, router); // {
2299
+ // pendingMs: routeOptions.pendingMs ?? router.defaultPendingMs,
2300
+ // pendingMinMs: routeOptions.pendingMinMs ?? router.defaultPendingMinMs,
2301
+ // }
2302
+
2303
+ const existingRoute = router.routesById[route.routeId];
2304
+
2305
+ if (existingRoute) {
2306
+ if (process.env.NODE_ENV !== 'production') {
2307
+ console.warn("Duplicate routes found with id: " + String(route.routeId), router.routesById, route);
2308
+ }
2309
+
2310
+ throw new Error();
2311
+ }
2312
+ router.routesById[route.routeId] = route;
2313
+ const children = routeConfig.children;
2314
+ route.childRoutes = children != null && children.length ? recurseRoutes(children, route) : undefined;
2315
+ return route;
2316
+ });
2317
+ };
2318
+
2319
+ const routes = recurseRoutes([rootRouteConfig]);
2320
+ return routes[0];
2321
+ },
2322
+ parseLocation: (location, previousLocation) => {
2323
+ var _location$hash$split$;
2324
+
2325
+ const parsedSearch = router.options.parseSearch(location.search);
2326
+ return {
2327
+ pathname: location.pathname,
2328
+ searchStr: location.search,
2329
+ search: replaceEqualDeep(previousLocation == null ? void 0 : previousLocation.search, parsedSearch),
2330
+ hash: (_location$hash$split$ = location.hash.split('#').reverse()[0]) != null ? _location$hash$split$ : '',
2331
+ href: "" + location.pathname + location.search + location.hash,
2332
+ state: location.state,
2333
+ key: location.key
2334
+ };
2335
+ },
2336
+ navigate: location => {
2337
+ const next = router.buildNext(location);
2338
+ return router.__.commitLocation(next, location.replace);
2339
+ },
2340
+ buildLocation: function buildLocation(dest) {
2341
+ var _dest$from, _router$basepath, _dest$to, _last, _dest$params, _dest$__preSearchFilt, _functionalUpdate, _dest$__preSearchFilt2, _dest$__postSearchFil;
2342
+
2343
+ if (dest === void 0) {
2344
+ dest = {};
2345
+ }
2346
+
2347
+ // const resolvedFrom: Location = {
2348
+ // ...router.location,
2349
+ const fromPathname = dest.fromCurrent ? router.location.pathname : (_dest$from = dest.from) != null ? _dest$from : router.location.pathname;
2350
+
2351
+ let pathname = resolvePath((_router$basepath = router.basepath) != null ? _router$basepath : '/', fromPathname, "" + ((_dest$to = dest.to) != null ? _dest$to : '.'));
2352
+
2353
+ const fromMatches = router.matchRoutes(router.location.pathname, {
2354
+ strictParseParams: true
2355
+ });
2356
+ const toMatches = router.matchRoutes(pathname);
2357
+
2358
+ const prevParams = _extends({}, (_last = last(fromMatches)) == null ? void 0 : _last.params);
2359
+
2360
+ let nextParams = ((_dest$params = dest.params) != null ? _dest$params : true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
2361
+
2362
+ if (nextParams) {
2363
+ toMatches.map(d => d.options.stringifyParams).filter(Boolean).forEach(fn => {
2364
+ Object.assign({}, nextParams, fn(nextParams));
2365
+ });
2366
+ }
2367
+
2368
+ pathname = interpolatePath(pathname, nextParams != null ? nextParams : {}); // Pre filters first
2369
+
2370
+ const preFilteredSearch = (_dest$__preSearchFilt = dest.__preSearchFilters) != null && _dest$__preSearchFilt.length ? dest.__preSearchFilters.reduce((prev, next) => next(prev), router.location.search) : router.location.search; // Then the link/navigate function
2371
+
2372
+ const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
2373
+ : dest.search ? (_functionalUpdate = functionalUpdate(dest.search, preFilteredSearch)) != null ? _functionalUpdate : {} // Updater
2374
+ : (_dest$__preSearchFilt2 = dest.__preSearchFilters) != null && _dest$__preSearchFilt2.length ? preFilteredSearch // Preserve resolvedFrom filters
2375
+ : {}; // Then post filters
2376
+
2377
+ const postFilteredSearch = (_dest$__postSearchFil = dest.__postSearchFilters) != null && _dest$__postSearchFil.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
2378
+ const search = replaceEqualDeep(router.location.search, postFilteredSearch);
2379
+ const searchStr = router.options.stringifySearch(search);
2380
+ let hash = dest.hash === true ? router.location.hash : functionalUpdate(dest.hash, router.location.hash);
2381
+ hash = hash ? "#" + hash : '';
2382
+ return {
2383
+ pathname,
2384
+ search,
2385
+ searchStr,
2386
+ state: router.location.state,
2387
+ hash,
2388
+ href: "" + pathname + searchStr + hash,
2389
+ key: dest.key
2390
+ };
2391
+ },
2392
+ commitLocation: (next, replace) => {
2393
+ const id = '' + Date.now() + Math.random();
2394
+ if (router.navigateTimeout) clearTimeout(router.navigateTimeout);
2395
+ let nextAction = 'replace';
2396
+
2397
+ if (!replace) {
2398
+ nextAction = 'push';
2399
+ }
2400
+
2401
+ const isSameUrl = router.__.parseLocation(history.location).href === next.href;
2402
+
2403
+ if (isSameUrl && !next.key) {
2404
+ nextAction = 'replace';
2405
+ }
2406
+
2407
+ if (nextAction === 'replace') {
2408
+ history.replace({
2409
+ pathname: next.pathname,
2410
+ hash: next.hash,
2411
+ search: next.searchStr
2412
+ }, {
2413
+ id
2414
+ });
2415
+ } else {
2416
+ history.push({
2417
+ pathname: next.pathname,
2418
+ hash: next.hash,
2419
+ search: next.searchStr
2420
+ }, {
2421
+ id
2422
+ });
2423
+ }
2424
+
2425
+ router.navigationPromise = new Promise(resolve => {
2426
+ const previousNavigationResolve = router.resolveNavigation;
2427
+
2428
+ router.resolveNavigation = () => {
2429
+ previousNavigationResolve();
2430
+ resolve();
2431
+ };
2432
+ });
2433
+ return router.navigationPromise;
2434
+ }
2409
2435
  }
2410
2436
  };
2411
- router.location = router.parseLocation(history.location);
2437
+ router.location = router.__.parseLocation(history.location);
2412
2438
  router.state.location = router.location;
2413
2439
  router.update(userOptions); // Allow frameworks to hook into the router creation
2414
2440