@remix-run/router 0.0.0-experimental-63b6834e → 0.0.0-experimental-cf9637ce
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.
- package/dist/index.d.ts +1 -2
- package/dist/router.cjs.js +118 -254
- package/dist/router.cjs.js.map +1 -1
- package/dist/router.d.ts +11 -9
- package/dist/router.js +118 -250
- package/dist/router.js.map +1 -1
- package/dist/router.umd.js +118 -254
- package/dist/router.umd.js.map +1 -1
- package/dist/router.umd.min.js +2 -2
- package/dist/router.umd.min.js.map +1 -1
- package/dist/utils.d.ts +1 -24
- package/index.ts +0 -2
- package/package.json +1 -1
- package/router.ts +138 -255
- package/utils.ts +7 -61
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
export type { ActionFunction, ActionFunctionArgs, AgnosticDataIndexRouteObject, AgnosticDataNonIndexRouteObject, AgnosticDataRouteMatch, AgnosticDataRouteObject, AgnosticIndexRouteObject, AgnosticNonIndexRouteObject, AgnosticRouteMatch, AgnosticRouteObject,
|
|
1
|
+
export type { ActionFunction, ActionFunctionArgs, AgnosticDataIndexRouteObject, AgnosticDataNonIndexRouteObject, AgnosticDataRouteMatch, AgnosticDataRouteObject, AgnosticIndexRouteObject, AgnosticNonIndexRouteObject, AgnosticRouteMatch, AgnosticRouteObject, TrackedPromise, FormEncType, FormMethod, JsonFunction, LoaderFunction, LoaderFunctionArgs, ParamParseKey, Params, PathMatch, PathPattern, RedirectFunction, ShouldRevalidateFunction, Submission, } from "./utils";
|
|
2
2
|
export { AbortedDeferredError, ErrorResponse, defer, generatePath, getToPathname, isRouteErrorResponse, joinPaths, json, matchPath, matchRoutes, normalizePathname, redirect, resolvePath, resolveTo, stripBasename, warning, } from "./utils";
|
|
3
3
|
export type { BrowserHistory, BrowserHistoryOptions, HashHistory, HashHistoryOptions, History, InitialEntry, Location, MemoryHistory, MemoryHistoryOptions, Path, To, } from "./history";
|
|
4
4
|
export { Action, createBrowserHistory, createPath, createHashHistory, createMemoryHistory, invariant, parsePath, } from "./history";
|
|
5
5
|
export * from "./router";
|
|
6
6
|
/** @internal */
|
|
7
|
-
export type { RouteManifest as UNSAFE_RouteManifest } from "./utils";
|
|
8
7
|
export { DeferredData as UNSAFE_DeferredData, convertRoutesToDataRoutes as UNSAFE_convertRoutesToDataRoutes, getPathContributingMatches as UNSAFE_getPathContributingMatches, } from "./utils";
|
package/dist/router.cjs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @remix-run/router v0.0.0-experimental-
|
|
2
|
+
* @remix-run/router v0.0.0-experimental-cf9637ce
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -565,54 +565,40 @@ let ResultType;
|
|
|
565
565
|
ResultType["error"] = "error";
|
|
566
566
|
})(ResultType || (ResultType = {}));
|
|
567
567
|
|
|
568
|
-
const immutableRouteKeys = new Set(["caseSensitive", "path", "id", "index", "children"]);
|
|
569
|
-
/**
|
|
570
|
-
* lazy() function to load a route definition, which can add non-matching
|
|
571
|
-
* related properties to a route
|
|
572
|
-
*/
|
|
573
|
-
|
|
574
568
|
function isIndexRoute(route) {
|
|
575
569
|
return route.index === true;
|
|
576
570
|
} // Walk the route tree generating unique IDs where necessary so we are working
|
|
577
571
|
// solely with AgnosticDataRouteObject's within the Router
|
|
578
572
|
|
|
579
573
|
|
|
580
|
-
function convertRoutesToDataRoutes(routes,
|
|
574
|
+
function convertRoutesToDataRoutes(routes, parentPath, allIds) {
|
|
581
575
|
if (parentPath === void 0) {
|
|
582
576
|
parentPath = [];
|
|
583
577
|
}
|
|
584
578
|
|
|
585
|
-
if (
|
|
586
|
-
|
|
579
|
+
if (allIds === void 0) {
|
|
580
|
+
allIds = new Set();
|
|
587
581
|
}
|
|
588
582
|
|
|
589
583
|
return routes.map((route, index) => {
|
|
590
584
|
let treePath = [...parentPath, index];
|
|
591
585
|
let id = typeof route.id === "string" ? route.id : treePath.join("-");
|
|
592
586
|
invariant(route.index !== true || !route.children, "Cannot specify children on an index route");
|
|
593
|
-
invariant(!
|
|
587
|
+
invariant(!allIds.has(id), "Found a route id collision on id \"" + id + "\". Route " + "id's must be globally unique within Data Router usages");
|
|
588
|
+
allIds.add(id);
|
|
594
589
|
|
|
595
590
|
if (isIndexRoute(route)) {
|
|
596
591
|
let indexRoute = _extends({}, route, {
|
|
597
|
-
hasErrorBoundary: hasErrorBoundary(route),
|
|
598
592
|
id
|
|
599
593
|
});
|
|
600
594
|
|
|
601
|
-
manifest[id] = indexRoute;
|
|
602
595
|
return indexRoute;
|
|
603
596
|
} else {
|
|
604
597
|
let pathOrLayoutRoute = _extends({}, route, {
|
|
605
598
|
id,
|
|
606
|
-
|
|
607
|
-
children: undefined
|
|
599
|
+
children: route.children ? convertRoutesToDataRoutes(route.children, treePath, allIds) : undefined
|
|
608
600
|
});
|
|
609
601
|
|
|
610
|
-
manifest[id] = pathOrLayoutRoute;
|
|
611
|
-
|
|
612
|
-
if (route.children) {
|
|
613
|
-
pathOrLayoutRoute.children = convertRoutesToDataRoutes(route.children, hasErrorBoundary, treePath, manifest);
|
|
614
|
-
}
|
|
615
|
-
|
|
616
602
|
return pathOrLayoutRoute;
|
|
617
603
|
}
|
|
618
604
|
});
|
|
@@ -1492,9 +1478,7 @@ const IDLE_BLOCKER = {
|
|
|
1492
1478
|
};
|
|
1493
1479
|
const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
|
|
1494
1480
|
const isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
|
|
1495
|
-
const isServer = !isBrowser;
|
|
1496
|
-
|
|
1497
|
-
const defaultHasErrorBoundary = route => Boolean(route.hasErrorBoundary); //#endregion
|
|
1481
|
+
const isServer = !isBrowser; //#endregion
|
|
1498
1482
|
////////////////////////////////////////////////////////////////////////////////
|
|
1499
1483
|
//#region createRouter
|
|
1500
1484
|
////////////////////////////////////////////////////////////////////////////////
|
|
@@ -1503,14 +1487,10 @@ const defaultHasErrorBoundary = route => Boolean(route.hasErrorBoundary); //#end
|
|
|
1503
1487
|
* Create a router and listen to history POP navigations
|
|
1504
1488
|
*/
|
|
1505
1489
|
|
|
1506
|
-
|
|
1507
1490
|
function createRouter(init) {
|
|
1508
1491
|
invariant(init.routes.length > 0, "You must provide a non-empty routes array to createRouter");
|
|
1509
|
-
let
|
|
1510
|
-
|
|
1511
|
-
let manifest = {}; // Routes in tree format for matching
|
|
1512
|
-
|
|
1513
|
-
let dataRoutes = convertRoutesToDataRoutes(init.routes, hasErrorBoundary, undefined, manifest); // Cleanup function for history
|
|
1492
|
+
let dataRoutes = convertRoutesToDataRoutes(init.routes);
|
|
1493
|
+
let inFlightDataRoutes; // Cleanup function for history
|
|
1514
1494
|
|
|
1515
1495
|
let unlistenHistory = null; // Externally-provided functions to call on all state changes
|
|
1516
1496
|
|
|
@@ -1547,10 +1527,7 @@ function createRouter(init) {
|
|
|
1547
1527
|
};
|
|
1548
1528
|
}
|
|
1549
1529
|
|
|
1550
|
-
let initialized =
|
|
1551
|
-
// functions around still then we'll need to run them in initialize()
|
|
1552
|
-
!initialMatches.some(m => m.route.lazy) && ( // And we have to either have no loaders or have been provided hydrationData
|
|
1553
|
-
!initialMatches.some(m => m.route.loader) || init.hydrationData != null);
|
|
1530
|
+
let initialized = !initialMatches.some(m => m.route.loader) || init.hydrationData != null;
|
|
1554
1531
|
let router;
|
|
1555
1532
|
let state = {
|
|
1556
1533
|
historyAction: init.history.action,
|
|
@@ -1674,57 +1651,12 @@ function createRouter(init) {
|
|
|
1674
1651
|
}
|
|
1675
1652
|
|
|
1676
1653
|
return startNavigation(historyAction, location);
|
|
1677
|
-
});
|
|
1654
|
+
}); // Kick off initial data load if needed. Use Pop to avoid modifying history
|
|
1678
1655
|
|
|
1679
|
-
if (
|
|
1680
|
-
if (state.initialized) {
|
|
1681
|
-
// We delay calling the onInitialize function until the next tick so
|
|
1682
|
-
// this function has a chance to return the router instance, otherwise
|
|
1683
|
-
// consumers will get an error if they try to use the returned router
|
|
1684
|
-
// instance in their callback. Note that we also provide the router
|
|
1685
|
-
// instance to the callback as a convenience and to avoid this ambiguity
|
|
1686
|
-
// in the consumer code.
|
|
1687
|
-
Promise.resolve().then(() => init.onInitialize({
|
|
1688
|
-
router
|
|
1689
|
-
}));
|
|
1690
|
-
} else {
|
|
1691
|
-
let unsubscribe = subscribe(updatedState => {
|
|
1692
|
-
if (updatedState.initialized) {
|
|
1693
|
-
unsubscribe();
|
|
1694
|
-
init.onInitialize({
|
|
1695
|
-
router
|
|
1696
|
-
});
|
|
1697
|
-
}
|
|
1698
|
-
});
|
|
1699
|
-
}
|
|
1700
|
-
}
|
|
1701
|
-
|
|
1702
|
-
if (state.initialized) {
|
|
1703
|
-
return router;
|
|
1704
|
-
}
|
|
1705
|
-
|
|
1706
|
-
let lazyMatches = state.matches.filter(m => m.route.lazy);
|
|
1707
|
-
|
|
1708
|
-
if (lazyMatches.length === 0) {
|
|
1709
|
-
// Kick off initial data load if needed. Use Pop to avoid modifying history
|
|
1656
|
+
if (!state.initialized) {
|
|
1710
1657
|
startNavigation(exports.Action.Pop, state.location);
|
|
1711
|
-
|
|
1712
|
-
} // Load lazy modules, then kick off initial data load if needed
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
loadLazyRouteModules(lazyMatches, hasErrorBoundary, manifest).then(() => {
|
|
1716
|
-
let initialized = !state.matches.some(m => m.route.loader) || init.hydrationData != null;
|
|
1658
|
+
}
|
|
1717
1659
|
|
|
1718
|
-
if (initialized) {
|
|
1719
|
-
// We already have required loaderData so we can just set initialized
|
|
1720
|
-
updateState({
|
|
1721
|
-
initialized: true
|
|
1722
|
-
});
|
|
1723
|
-
} else {
|
|
1724
|
-
// We still need to kick off initial data loads
|
|
1725
|
-
startNavigation(exports.Action.Pop, state.location);
|
|
1726
|
-
}
|
|
1727
|
-
});
|
|
1728
1660
|
return router;
|
|
1729
1661
|
} // Clean up a router and it's side effects
|
|
1730
1662
|
|
|
@@ -1794,6 +1726,12 @@ function createRouter(init) {
|
|
|
1794
1726
|
|
|
1795
1727
|
|
|
1796
1728
|
let preventScrollReset = pendingPreventScrollReset === true || state.navigation.formMethod != null && isMutationMethod(state.navigation.formMethod) && ((_location$state2 = location.state) == null ? void 0 : _location$state2._isRedirect) !== true;
|
|
1729
|
+
|
|
1730
|
+
if (inFlightDataRoutes) {
|
|
1731
|
+
dataRoutes = inFlightDataRoutes;
|
|
1732
|
+
inFlightDataRoutes = undefined;
|
|
1733
|
+
}
|
|
1734
|
+
|
|
1797
1735
|
updateState(_extends({}, newState, {
|
|
1798
1736
|
// matches, errors, fetchers go through as-is
|
|
1799
1737
|
actionData,
|
|
@@ -1949,8 +1887,9 @@ function createRouter(init) {
|
|
|
1949
1887
|
|
|
1950
1888
|
saveScrollPosition(state.location, state.matches);
|
|
1951
1889
|
pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;
|
|
1890
|
+
let routesToUse = inFlightDataRoutes || dataRoutes;
|
|
1952
1891
|
let loadingNavigation = opts && opts.overrideNavigation;
|
|
1953
|
-
let matches = matchRoutes(
|
|
1892
|
+
let matches = matchRoutes(routesToUse, location, init.basename); // Short circuit with a 404 on the root error boundary if we match nothing
|
|
1954
1893
|
|
|
1955
1894
|
if (!matches) {
|
|
1956
1895
|
let error = getInternalRouterError(404, {
|
|
@@ -1959,7 +1898,7 @@ function createRouter(init) {
|
|
|
1959
1898
|
let {
|
|
1960
1899
|
matches: notFoundMatches,
|
|
1961
1900
|
route
|
|
1962
|
-
} = getShortCircuitMatches(
|
|
1901
|
+
} = getShortCircuitMatches(routesToUse); // Cancel all pending deferred on 404s since we don't keep any routes
|
|
1963
1902
|
|
|
1964
1903
|
cancelActiveDeferreds();
|
|
1965
1904
|
completeNavigation(location, {
|
|
@@ -2063,16 +2002,6 @@ function createRouter(init) {
|
|
|
2063
2002
|
let result;
|
|
2064
2003
|
let actionMatch = getTargetMatch(matches, location);
|
|
2065
2004
|
|
|
2066
|
-
if (actionMatch.route.lazy) {
|
|
2067
|
-
await loadLazyRouteModules([actionMatch], hasErrorBoundary, manifest);
|
|
2068
|
-
|
|
2069
|
-
if (request.signal.aborted) {
|
|
2070
|
-
return {
|
|
2071
|
-
shortCircuited: true
|
|
2072
|
-
};
|
|
2073
|
-
}
|
|
2074
|
-
}
|
|
2075
|
-
|
|
2076
2005
|
if (!actionMatch.route.action) {
|
|
2077
2006
|
result = {
|
|
2078
2007
|
type: ResultType.error,
|
|
@@ -2174,7 +2103,8 @@ function createRouter(init) {
|
|
|
2174
2103
|
formData: loadingNavigation.formData,
|
|
2175
2104
|
formEncType: loadingNavigation.formEncType
|
|
2176
2105
|
} : undefined;
|
|
2177
|
-
let
|
|
2106
|
+
let routesToUse = inFlightDataRoutes || dataRoutes;
|
|
2107
|
+
let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, activeSubmission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, fetchLoadMatches, routesToUse, init.basename, pendingActionData, pendingError); // Cancel pending deferreds for no-longer-matched routes or routes we're
|
|
2178
2108
|
// about to reload. Note that if this is an action reload we would have
|
|
2179
2109
|
// already cancelled all pending deferreds so this would be a no-op
|
|
2180
2110
|
|
|
@@ -2226,18 +2156,6 @@ function createRouter(init) {
|
|
|
2226
2156
|
|
|
2227
2157
|
pendingNavigationLoadId = ++incrementingLoadId;
|
|
2228
2158
|
revalidatingFetchers.forEach(rf => fetchControllers.set(rf.key, pendingNavigationController));
|
|
2229
|
-
let lazyMatches = matches.filter(m => m.route.lazy);
|
|
2230
|
-
|
|
2231
|
-
if (lazyMatches.length > 0) {
|
|
2232
|
-
await loadLazyRouteModules(lazyMatches, hasErrorBoundary, manifest);
|
|
2233
|
-
|
|
2234
|
-
if (request.signal.aborted) {
|
|
2235
|
-
return {
|
|
2236
|
-
shortCircuited: true
|
|
2237
|
-
};
|
|
2238
|
-
}
|
|
2239
|
-
}
|
|
2240
|
-
|
|
2241
2159
|
let {
|
|
2242
2160
|
results,
|
|
2243
2161
|
loaderResults,
|
|
@@ -2303,7 +2221,8 @@ function createRouter(init) {
|
|
|
2303
2221
|
}
|
|
2304
2222
|
|
|
2305
2223
|
if (fetchControllers.has(key)) abortFetcher(key);
|
|
2306
|
-
let
|
|
2224
|
+
let routesToUse = inFlightDataRoutes || dataRoutes;
|
|
2225
|
+
let matches = matchRoutes(routesToUse, href, init.basename);
|
|
2307
2226
|
|
|
2308
2227
|
if (!matches) {
|
|
2309
2228
|
setFetcherError(key, routeId, getInternalRouterError(404, {
|
|
@@ -2328,9 +2247,7 @@ function createRouter(init) {
|
|
|
2328
2247
|
|
|
2329
2248
|
fetchLoadMatches.set(key, {
|
|
2330
2249
|
routeId,
|
|
2331
|
-
path
|
|
2332
|
-
match,
|
|
2333
|
-
matches
|
|
2250
|
+
path
|
|
2334
2251
|
});
|
|
2335
2252
|
handleFetcherLoader(key, routeId, path, match, matches, submission);
|
|
2336
2253
|
} // Call the action for the matched fetcher.submit(), and then handle redirects,
|
|
@@ -2341,7 +2258,7 @@ function createRouter(init) {
|
|
|
2341
2258
|
interruptActiveLoads();
|
|
2342
2259
|
fetchLoadMatches.delete(key);
|
|
2343
2260
|
|
|
2344
|
-
if (!match.route.
|
|
2261
|
+
if (!match.route.action) {
|
|
2345
2262
|
let error = getInternalRouterError(405, {
|
|
2346
2263
|
method: submission.formMethod,
|
|
2347
2264
|
pathname: path,
|
|
@@ -2369,25 +2286,6 @@ function createRouter(init) {
|
|
|
2369
2286
|
let abortController = new AbortController();
|
|
2370
2287
|
let fetchRequest = createClientSideRequest(init.history, path, abortController.signal, submission);
|
|
2371
2288
|
fetchControllers.set(key, abortController);
|
|
2372
|
-
|
|
2373
|
-
if (match.route.lazy) {
|
|
2374
|
-
await loadLazyRouteModules([match], hasErrorBoundary, manifest);
|
|
2375
|
-
|
|
2376
|
-
if (fetchRequest.signal.aborted) {
|
|
2377
|
-
return;
|
|
2378
|
-
}
|
|
2379
|
-
|
|
2380
|
-
if (!match.route.action) {
|
|
2381
|
-
let error = getInternalRouterError(405, {
|
|
2382
|
-
method: submission.formMethod,
|
|
2383
|
-
pathname: path,
|
|
2384
|
-
routeId: routeId
|
|
2385
|
-
});
|
|
2386
|
-
setFetcherError(key, routeId, error);
|
|
2387
|
-
return;
|
|
2388
|
-
}
|
|
2389
|
-
}
|
|
2390
|
-
|
|
2391
2289
|
let actionResult = await callLoaderOrAction("action", fetchRequest, match, requestMatches, router.basename);
|
|
2392
2290
|
|
|
2393
2291
|
if (fetchRequest.signal.aborted) {
|
|
@@ -2436,7 +2334,8 @@ function createRouter(init) {
|
|
|
2436
2334
|
|
|
2437
2335
|
let nextLocation = state.navigation.location || state.location;
|
|
2438
2336
|
let revalidationRequest = createClientSideRequest(init.history, nextLocation, abortController.signal);
|
|
2439
|
-
let
|
|
2337
|
+
let routesToUse = inFlightDataRoutes || dataRoutes;
|
|
2338
|
+
let matches = state.navigation.state !== "idle" ? matchRoutes(routesToUse, state.navigation.location, init.basename) : state.matches;
|
|
2440
2339
|
invariant(matches, "Didn't find any matches after fetcher action");
|
|
2441
2340
|
let loadId = ++incrementingLoadId;
|
|
2442
2341
|
fetchReloadIds.set(key, loadId);
|
|
@@ -2449,10 +2348,10 @@ function createRouter(init) {
|
|
|
2449
2348
|
});
|
|
2450
2349
|
|
|
2451
2350
|
state.fetchers.set(key, loadFetcher);
|
|
2452
|
-
let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, submission, nextLocation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, {
|
|
2351
|
+
let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, submission, nextLocation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, fetchLoadMatches, routesToUse, init.basename, {
|
|
2453
2352
|
[match.route.id]: actionResult.data
|
|
2454
|
-
}, undefined
|
|
2455
|
-
|
|
2353
|
+
}, undefined // No need to send through errors since we short circuit above
|
|
2354
|
+
); // Put all revalidating fetchers into the loading state, except for the
|
|
2456
2355
|
// current fetcher which we want to keep in it's current loading state which
|
|
2457
2356
|
// contains it's action submission info + action data
|
|
2458
2357
|
|
|
@@ -2474,16 +2373,6 @@ function createRouter(init) {
|
|
|
2474
2373
|
updateState({
|
|
2475
2374
|
fetchers: new Map(state.fetchers)
|
|
2476
2375
|
});
|
|
2477
|
-
let lazyMatches = matches.filter(m => m.route.lazy);
|
|
2478
|
-
|
|
2479
|
-
if (match.route.lazy) {
|
|
2480
|
-
await loadLazyRouteModules(lazyMatches, hasErrorBoundary, manifest);
|
|
2481
|
-
|
|
2482
|
-
if (revalidationRequest.signal.aborted) {
|
|
2483
|
-
return;
|
|
2484
|
-
}
|
|
2485
|
-
}
|
|
2486
|
-
|
|
2487
2376
|
let {
|
|
2488
2377
|
results,
|
|
2489
2378
|
loaderResults,
|
|
@@ -2568,15 +2457,6 @@ function createRouter(init) {
|
|
|
2568
2457
|
let abortController = new AbortController();
|
|
2569
2458
|
let fetchRequest = createClientSideRequest(init.history, path, abortController.signal);
|
|
2570
2459
|
fetchControllers.set(key, abortController);
|
|
2571
|
-
|
|
2572
|
-
if (match.route.lazy) {
|
|
2573
|
-
await loadLazyRouteModules([match], hasErrorBoundary, manifest);
|
|
2574
|
-
|
|
2575
|
-
if (fetchRequest.signal.aborted) {
|
|
2576
|
-
return;
|
|
2577
|
-
}
|
|
2578
|
-
}
|
|
2579
|
-
|
|
2580
2460
|
let result = await callLoaderOrAction("loader", fetchRequest, match, matches, router.basename); // Deferred isn't supported for fetcher loads, await everything and treat it
|
|
2581
2461
|
// as a normal load. resolveDeferredData will return undefined if this
|
|
2582
2462
|
// fetcher gets aborted, so we just leave result untouched and short circuit
|
|
@@ -2745,7 +2625,19 @@ function createRouter(init) {
|
|
|
2745
2625
|
// Call all navigation loaders and revalidating fetcher loaders in parallel,
|
|
2746
2626
|
// then slice off the results into separate arrays so we can handle them
|
|
2747
2627
|
// accordingly
|
|
2748
|
-
let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, router.basename)), ...fetchersToLoad.map(f =>
|
|
2628
|
+
let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, router.basename)), ...fetchersToLoad.map(f => {
|
|
2629
|
+
if (f.matches && f.match) {
|
|
2630
|
+
return callLoaderOrAction("loader", createClientSideRequest(init.history, f.path, request.signal), f.match, f.matches, router.basename);
|
|
2631
|
+
} else {
|
|
2632
|
+
let error = {
|
|
2633
|
+
type: ResultType.error,
|
|
2634
|
+
error: getInternalRouterError(404, {
|
|
2635
|
+
pathname: f.path
|
|
2636
|
+
})
|
|
2637
|
+
};
|
|
2638
|
+
return error;
|
|
2639
|
+
}
|
|
2640
|
+
})]);
|
|
2749
2641
|
let loaderResults = results.slice(0, matchesToLoad.length);
|
|
2750
2642
|
let fetcherResults = results.slice(matchesToLoad.length);
|
|
2751
2643
|
await Promise.all([resolveDeferredResults(currentMatches, matchesToLoad, loaderResults, request.signal, false, state.loaderData), resolveDeferredResults(currentMatches, fetchersToLoad.map(f => f.match), fetcherResults, request.signal, true)]);
|
|
@@ -2980,6 +2872,10 @@ function createRouter(init) {
|
|
|
2980
2872
|
return null;
|
|
2981
2873
|
}
|
|
2982
2874
|
|
|
2875
|
+
function _internalSetRoutes(newRoutes) {
|
|
2876
|
+
inFlightDataRoutes = newRoutes;
|
|
2877
|
+
}
|
|
2878
|
+
|
|
2983
2879
|
router = {
|
|
2984
2880
|
get basename() {
|
|
2985
2881
|
return init.basename;
|
|
@@ -3009,7 +2905,10 @@ function createRouter(init) {
|
|
|
3009
2905
|
getBlocker,
|
|
3010
2906
|
deleteBlocker,
|
|
3011
2907
|
_internalFetchControllers: fetchControllers,
|
|
3012
|
-
_internalActiveDeferreds: activeDeferreds
|
|
2908
|
+
_internalActiveDeferreds: activeDeferreds,
|
|
2909
|
+
// TODO: Remove setRoutes, it's temporary to avoid dealing with
|
|
2910
|
+
// updating the tree while validating the update algorithm.
|
|
2911
|
+
_internalSetRoutes
|
|
3013
2912
|
};
|
|
3014
2913
|
return router;
|
|
3015
2914
|
} //#endregion
|
|
@@ -3020,9 +2919,7 @@ function createRouter(init) {
|
|
|
3020
2919
|
const UNSAFE_DEFERRED_SYMBOL = Symbol("deferred");
|
|
3021
2920
|
function createStaticHandler(routes, opts) {
|
|
3022
2921
|
invariant(routes.length > 0, "You must provide a non-empty routes array to createStaticHandler");
|
|
3023
|
-
let
|
|
3024
|
-
let hasErrorBoundary = (opts == null ? void 0 : opts.hasErrorBoundary) || defaultHasErrorBoundary;
|
|
3025
|
-
let dataRoutes = convertRoutesToDataRoutes(routes, hasErrorBoundary, undefined, manifest);
|
|
2922
|
+
let dataRoutes = convertRoutesToDataRoutes(routes);
|
|
3026
2923
|
let basename = (opts ? opts.basename : null) || "/";
|
|
3027
2924
|
/**
|
|
3028
2925
|
* The query() method is intended for document requests, in which we want to
|
|
@@ -3207,16 +3104,6 @@ function createStaticHandler(routes, opts) {
|
|
|
3207
3104
|
|
|
3208
3105
|
async function queryImpl(request, location, matches, requestContext, routeMatch) {
|
|
3209
3106
|
invariant(request.signal, "query()/queryRoute() requests must contain an AbortController signal");
|
|
3210
|
-
let lazyMatches = matches.filter(m => m.route.lazy);
|
|
3211
|
-
|
|
3212
|
-
if (lazyMatches.length > 0) {
|
|
3213
|
-
await loadLazyRouteModules(lazyMatches, hasErrorBoundary, manifest);
|
|
3214
|
-
|
|
3215
|
-
if (request.signal.aborted) {
|
|
3216
|
-
let method = routeMatch != null ? "queryRoute" : "query";
|
|
3217
|
-
throw new Error(method + "() call aborted");
|
|
3218
|
-
}
|
|
3219
|
-
}
|
|
3220
3107
|
|
|
3221
3108
|
try {
|
|
3222
3109
|
if (isMutationMethod(request.method.toLowerCase())) {
|
|
@@ -3522,7 +3409,7 @@ function getLoaderMatchesUntilBoundary(matches, boundaryId) {
|
|
|
3522
3409
|
return boundaryMatches;
|
|
3523
3410
|
}
|
|
3524
3411
|
|
|
3525
|
-
function getMatchesToLoad(history, state, matches, submission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, pendingActionData, pendingError
|
|
3412
|
+
function getMatchesToLoad(history, state, matches, submission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, fetchLoadMatches, routesToUse, basename, pendingActionData, pendingError) {
|
|
3526
3413
|
let actionResult = pendingError ? Object.values(pendingError)[0] : pendingActionData ? Object.values(pendingActionData)[0] : undefined;
|
|
3527
3414
|
let currentUrl = history.createURL(state.location);
|
|
3528
3415
|
let nextUrl = history.createURL(location);
|
|
@@ -3534,11 +3421,6 @@ function getMatchesToLoad(history, state, matches, submission, location, isReval
|
|
|
3534
3421
|
let boundaryId = pendingError ? Object.keys(pendingError)[0] : undefined;
|
|
3535
3422
|
let boundaryMatches = getLoaderMatchesUntilBoundary(matches, boundaryId);
|
|
3536
3423
|
let navigationMatches = boundaryMatches.filter((match, index) => {
|
|
3537
|
-
if (match.route.lazy) {
|
|
3538
|
-
// We haven't loaded this route yet so we don't know if it's got a loader!
|
|
3539
|
-
return true;
|
|
3540
|
-
}
|
|
3541
|
-
|
|
3542
3424
|
if (match.route.loader == null) {
|
|
3543
3425
|
return false;
|
|
3544
3426
|
} // Always call the loader on new route instances and pending defer cancellations
|
|
@@ -3566,36 +3448,56 @@ function getMatchesToLoad(history, state, matches, submission, location, isReval
|
|
|
3566
3448
|
}); // Pick fetcher.loads that need to be revalidated
|
|
3567
3449
|
|
|
3568
3450
|
let revalidatingFetchers = [];
|
|
3569
|
-
fetchLoadMatches
|
|
3451
|
+
fetchLoadMatches.forEach((f, key) => {
|
|
3452
|
+
// Don't revalidate if fetcher won't be present in the subsequent render
|
|
3570
3453
|
if (!matches.some(m => m.route.id === f.routeId)) {
|
|
3571
|
-
// This fetcher is not going to be present in the subsequent render so
|
|
3572
|
-
// there's no need to revalidate it
|
|
3573
3454
|
return;
|
|
3574
|
-
}
|
|
3575
|
-
|
|
3455
|
+
}
|
|
3456
|
+
|
|
3457
|
+
let fetcherMatches = matchRoutes(routesToUse, f.path, basename); // If the fetcher path no longer matches, push it in with null matches so
|
|
3458
|
+
// we can trigger a 404 in callLoadersAndMaybeResolveData
|
|
3459
|
+
|
|
3460
|
+
if (!fetcherMatches) {
|
|
3576
3461
|
revalidatingFetchers.push(_extends({
|
|
3577
3462
|
key
|
|
3578
|
-
}, f
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
// hit a static href, so they _always_ check shouldRevalidate and the
|
|
3582
|
-
// default is strictly if a revalidation is explicitly required (action
|
|
3583
|
-
// submissions, useRevalidator, X-Remix-Revalidate).
|
|
3584
|
-
let shouldRevalidate = shouldRevalidateLoader(f.match, _extends({
|
|
3585
|
-
currentUrl,
|
|
3586
|
-
currentParams: state.matches[state.matches.length - 1].params,
|
|
3587
|
-
nextUrl,
|
|
3588
|
-
nextParams: matches[matches.length - 1].params
|
|
3589
|
-
}, submission, {
|
|
3590
|
-
actionResult,
|
|
3591
|
-
defaultShouldRevalidate
|
|
3463
|
+
}, f, {
|
|
3464
|
+
matches: null,
|
|
3465
|
+
match: null
|
|
3592
3466
|
}));
|
|
3467
|
+
return;
|
|
3468
|
+
}
|
|
3593
3469
|
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3470
|
+
let fetcherMatch = getTargetMatch(fetcherMatches, f.path);
|
|
3471
|
+
|
|
3472
|
+
if (cancelledFetcherLoads.includes(key)) {
|
|
3473
|
+
revalidatingFetchers.push(_extends({
|
|
3474
|
+
key,
|
|
3475
|
+
matches: fetcherMatches,
|
|
3476
|
+
match: fetcherMatch
|
|
3477
|
+
}, f));
|
|
3478
|
+
return;
|
|
3479
|
+
} // Revalidating fetchers are decoupled from the route matches since they
|
|
3480
|
+
// hit a static href, so they _always_ check shouldRevalidate and the
|
|
3481
|
+
// default is strictly if a revalidation is explicitly required (action
|
|
3482
|
+
// submissions, useRevalidator, X-Remix-Revalidate).
|
|
3483
|
+
|
|
3484
|
+
|
|
3485
|
+
let shouldRevalidate = shouldRevalidateLoader(fetcherMatch, _extends({
|
|
3486
|
+
currentUrl,
|
|
3487
|
+
currentParams: state.matches[state.matches.length - 1].params,
|
|
3488
|
+
nextUrl,
|
|
3489
|
+
nextParams: matches[matches.length - 1].params
|
|
3490
|
+
}, submission, {
|
|
3491
|
+
actionResult,
|
|
3492
|
+
defaultShouldRevalidate
|
|
3493
|
+
}));
|
|
3494
|
+
|
|
3495
|
+
if (shouldRevalidate) {
|
|
3496
|
+
revalidatingFetchers.push(_extends({
|
|
3497
|
+
key,
|
|
3498
|
+
matches: fetcherMatches,
|
|
3499
|
+
match: fetcherMatch
|
|
3500
|
+
}, f));
|
|
3599
3501
|
}
|
|
3600
3502
|
});
|
|
3601
3503
|
return [navigationMatches, revalidatingFetchers];
|
|
@@ -3632,57 +3534,6 @@ function shouldRevalidateLoader(loaderMatch, arg) {
|
|
|
3632
3534
|
|
|
3633
3535
|
return arg.defaultShouldRevalidate;
|
|
3634
3536
|
}
|
|
3635
|
-
/**
|
|
3636
|
-
* Execute route.lazy() methods to lazily load route modules (loader, action,
|
|
3637
|
-
* shouldRevalidate) and update the routeManifest in place which shares objects
|
|
3638
|
-
* with dataRoutes so those get updated as well.
|
|
3639
|
-
*/
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
async function loadLazyRouteModules(lazyMatches, hasErrorBoundary, manifest) {
|
|
3643
|
-
await Promise.all(lazyMatches.map(async match => {
|
|
3644
|
-
let mod = await match.route.lazy(); // If the lazy route function has already been executed and removed from
|
|
3645
|
-
// the route object by another call while we were waiting for the promise
|
|
3646
|
-
// to resolve then we don't want to resolve the same route again.
|
|
3647
|
-
|
|
3648
|
-
if (!match.route.lazy) {
|
|
3649
|
-
return;
|
|
3650
|
-
}
|
|
3651
|
-
|
|
3652
|
-
let routeToUpdate = manifest[match.route.id];
|
|
3653
|
-
invariant(routeToUpdate, "No route found in manifest"); // For now, we update in place. We think this is ok since there's no way
|
|
3654
|
-
// we could yet be sitting on this route since we can't get there without
|
|
3655
|
-
// resolving through here first. This is different than the HMR "update"
|
|
3656
|
-
// use-case where we may actively be on the route being updated. The main
|
|
3657
|
-
// concern boils down to "does this mutation affect any ongoing navigations
|
|
3658
|
-
// or any current state.matches values?". If not, I think it's safe to
|
|
3659
|
-
// mutate in place. It's also worth noting that this is a more targeted
|
|
3660
|
-
// update that cannot touch things like path/index/children so it cannot
|
|
3661
|
-
// affect the routes we've already matched.
|
|
3662
|
-
|
|
3663
|
-
let routeUpdates = {};
|
|
3664
|
-
|
|
3665
|
-
for (let k in mod) {
|
|
3666
|
-
if (!immutableRouteKeys.has(k)) {
|
|
3667
|
-
routeUpdates[k] = mod[k];
|
|
3668
|
-
}
|
|
3669
|
-
} // Mutate the route with the provided updates. Do this first so we pass
|
|
3670
|
-
// the updated version to hasErrorBoundary
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
Object.assign(routeToUpdate, routeUpdates); // Mutate the `hasErrorBoundary` property on the route based on the route
|
|
3674
|
-
// updates and remove the `lazy` function so we don't resolve the lazy
|
|
3675
|
-
// route again.
|
|
3676
|
-
|
|
3677
|
-
Object.assign(routeToUpdate, {
|
|
3678
|
-
// To keep things framework agnostic, we use the provided
|
|
3679
|
-
// `hasErrorBoundary` function to set the `hasErrorBoundary` route
|
|
3680
|
-
// property since the logic will differ between frameworks.
|
|
3681
|
-
hasErrorBoundary: hasErrorBoundary(_extends({}, routeToUpdate)),
|
|
3682
|
-
lazy: undefined
|
|
3683
|
-
});
|
|
3684
|
-
}));
|
|
3685
|
-
}
|
|
3686
3537
|
|
|
3687
3538
|
async function callLoaderOrAction(type, request, match, matches, basename, isStaticRequest, isRouteRequest, requestContext) {
|
|
3688
3539
|
if (basename === void 0) {
|
|
@@ -3816,9 +3667,13 @@ async function callLoaderOrAction(type, request, match, matches, basename, isSta
|
|
|
3816
3667
|
}
|
|
3817
3668
|
|
|
3818
3669
|
if (result instanceof DeferredData) {
|
|
3670
|
+
var _result$init, _result$init2;
|
|
3671
|
+
|
|
3819
3672
|
return {
|
|
3820
3673
|
type: ResultType.deferred,
|
|
3821
|
-
deferredData: result
|
|
3674
|
+
deferredData: result,
|
|
3675
|
+
statusCode: (_result$init = result.init) == null ? void 0 : _result$init.status,
|
|
3676
|
+
headers: ((_result$init2 = result.init) == null ? void 0 : _result$init2.headers) && new Headers(result.init.headers)
|
|
3822
3677
|
};
|
|
3823
3678
|
}
|
|
3824
3679
|
|
|
@@ -3955,7 +3810,7 @@ function processLoaderData(state, matches, matchesToLoad, results, pendingError,
|
|
|
3955
3810
|
let result = fetcherResults[index]; // Process fetcher non-redirect errors
|
|
3956
3811
|
|
|
3957
3812
|
if (isErrorResult(result)) {
|
|
3958
|
-
let boundaryMatch = findNearestBoundary(state.matches, match.route.id);
|
|
3813
|
+
let boundaryMatch = findNearestBoundary(state.matches, match == null ? void 0 : match.route.id);
|
|
3959
3814
|
|
|
3960
3815
|
if (!(errors && errors[boundaryMatch.route.id])) {
|
|
3961
3816
|
errors = _extends({}, errors, {
|
|
@@ -4002,7 +3857,9 @@ function mergeLoaderData(loaderData, newLoaderData, matches, errors) {
|
|
|
4002
3857
|
if (newLoaderData[id] !== undefined) {
|
|
4003
3858
|
mergedLoaderData[id] = newLoaderData[id];
|
|
4004
3859
|
}
|
|
4005
|
-
} else if (loaderData[id] !== undefined) {
|
|
3860
|
+
} else if (loaderData[id] !== undefined && match.route.loader) {
|
|
3861
|
+
// Preserve existing keys not included in newLoaderData and where a loader
|
|
3862
|
+
// wasn't removed by HMR
|
|
4006
3863
|
mergedLoaderData[id] = loaderData[id];
|
|
4007
3864
|
}
|
|
4008
3865
|
|
|
@@ -4139,7 +3996,14 @@ function isMutationMethod(method) {
|
|
|
4139
3996
|
async function resolveDeferredResults(currentMatches, matchesToLoad, results, signal, isFetcher, currentLoaderData) {
|
|
4140
3997
|
for (let index = 0; index < results.length; index++) {
|
|
4141
3998
|
let result = results[index];
|
|
4142
|
-
let match = matchesToLoad[index];
|
|
3999
|
+
let match = matchesToLoad[index]; // If we don't have a match, then we can have a deferred result to do
|
|
4000
|
+
// anything with. This is for revalidating fetchers where the route was
|
|
4001
|
+
// removed during HMR
|
|
4002
|
+
|
|
4003
|
+
if (!match) {
|
|
4004
|
+
continue;
|
|
4005
|
+
}
|
|
4006
|
+
|
|
4143
4007
|
let currentMatch = currentMatches.find(m => m.route.id === match.route.id);
|
|
4144
4008
|
let isRevalidatingLoader = currentMatch != null && !isNewRouteInstance(currentMatch, match) && (currentLoaderData && currentLoaderData[match.route.id]) !== undefined;
|
|
4145
4009
|
|