@remix-run/router 0.0.0-experimental-c9f8a7b2 → 0.0.0-experimental-e960cf1a
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/CHANGELOG.md +8 -199
- package/dist/index.d.ts +2 -2
- package/dist/router.cjs.js +138 -90
- package/dist/router.cjs.js.map +1 -1
- package/dist/router.d.ts +3 -2
- package/dist/router.js +135 -91
- package/dist/router.js.map +1 -1
- package/dist/router.umd.js +138 -90
- 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 +13 -0
- package/index.ts +5 -0
- package/package.json +1 -1
- package/router.ts +243 -124
- package/utils.ts +25 -9
package/dist/router.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { History, Location, Path, To } from "./history";
|
|
2
2
|
import { Action as HistoryAction } from "./history";
|
|
3
|
-
import type { AgnosticDataRouteMatch, AgnosticDataRouteObject, AgnosticRouteObject, DeferredData, DetectErrorBoundaryFunction, FormEncType, HTMLFormMethod, MapRoutePropertiesFunction, RouteData, Submission, UIMatch } from "./utils";
|
|
3
|
+
import type { AgnosticDataRouteMatch, AgnosticDataRouteObject, AgnosticRouteObject, DataStrategyFunction, DeferredData, DetectErrorBoundaryFunction, FormEncType, HTMLFormMethod, MapRoutePropertiesFunction, RouteData, Submission, UIMatch } from "./utils";
|
|
4
4
|
/**
|
|
5
5
|
* A Router instance manages all navigation and data loading/mutations
|
|
6
6
|
*/
|
|
@@ -274,6 +274,7 @@ export interface RouterInit {
|
|
|
274
274
|
future?: Partial<FutureConfig>;
|
|
275
275
|
hydrationData?: HydrationState;
|
|
276
276
|
window?: Window;
|
|
277
|
+
unstable_dataStrategy?: DataStrategyFunction;
|
|
277
278
|
}
|
|
278
279
|
/**
|
|
279
280
|
* State returned from a server-side query() call
|
|
@@ -487,7 +488,6 @@ export declare const UNSAFE_DEFERRED_SYMBOL: unique symbol;
|
|
|
487
488
|
*/
|
|
488
489
|
export interface StaticHandlerFutureConfig {
|
|
489
490
|
v7_relativeSplatPath: boolean;
|
|
490
|
-
v7_throwAbortReason: boolean;
|
|
491
491
|
}
|
|
492
492
|
export interface CreateStaticHandlerOptions {
|
|
493
493
|
basename?: string;
|
|
@@ -495,6 +495,7 @@ export interface CreateStaticHandlerOptions {
|
|
|
495
495
|
* @deprecated Use `mapRouteProperties` instead
|
|
496
496
|
*/
|
|
497
497
|
detectErrorBoundary?: DetectErrorBoundaryFunction;
|
|
498
|
+
dataStrategy?: DataStrategyFunction;
|
|
498
499
|
mapRouteProperties?: MapRoutePropertiesFunction;
|
|
499
500
|
future?: Partial<StaticHandlerFutureConfig>;
|
|
500
501
|
}
|
package/dist/router.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @remix-run/router v0.0.0-experimental-
|
|
2
|
+
* @remix-run/router v0.0.0-experimental-e960cf1a
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -653,7 +653,7 @@ function rankRouteBranches(branches) {
|
|
|
653
653
|
branches.sort((a, b) => a.score !== b.score ? b.score - a.score // Higher score first
|
|
654
654
|
: compareIndexes(a.routesMeta.map(meta => meta.childrenIndex), b.routesMeta.map(meta => meta.childrenIndex)));
|
|
655
655
|
}
|
|
656
|
-
const paramRe =
|
|
656
|
+
const paramRe = /^:\w+$/;
|
|
657
657
|
const dynamicSegmentValue = 3;
|
|
658
658
|
const indexRouteValue = 2;
|
|
659
659
|
const emptySegmentValue = 1;
|
|
@@ -740,7 +740,7 @@ function generatePath(originalPath, params) {
|
|
|
740
740
|
// Apply the splat
|
|
741
741
|
return stringify(params[star]);
|
|
742
742
|
}
|
|
743
|
-
const keyMatch = segment.match(/^:(
|
|
743
|
+
const keyMatch = segment.match(/^:(\w+)(\??)$/);
|
|
744
744
|
if (keyMatch) {
|
|
745
745
|
const [, key, optional] = keyMatch;
|
|
746
746
|
let param = params[key];
|
|
@@ -812,7 +812,7 @@ function compilePath(path, caseSensitive, end) {
|
|
|
812
812
|
let regexpSource = "^" + path.replace(/\/*\*?$/, "") // Ignore trailing / and /*, we'll handle it below
|
|
813
813
|
.replace(/^\/*/, "/") // Make sure it has a leading /
|
|
814
814
|
.replace(/[\\.*+^${}|()[\]]/g, "\\$&") // Escape special regex chars
|
|
815
|
-
.replace(/\/:(
|
|
815
|
+
.replace(/\/:(\w+)(\?)?/g, (_, paramName, isOptional) => {
|
|
816
816
|
params.push({
|
|
817
817
|
paramName,
|
|
818
818
|
isOptional: isOptional != null
|
|
@@ -1306,6 +1306,8 @@ function createRouter(init) {
|
|
|
1306
1306
|
const isBrowser = typeof routerWindow !== "undefined" && typeof routerWindow.document !== "undefined" && typeof routerWindow.document.createElement !== "undefined";
|
|
1307
1307
|
const isServer = !isBrowser;
|
|
1308
1308
|
invariant(init.routes.length > 0, "You must provide a non-empty routes array to createRouter");
|
|
1309
|
+
const dataStrategy = init.unstable_dataStrategy || defaultDataStrategy;
|
|
1310
|
+
const callLoaderOrAction = createCallLoaderOrAction(dataStrategy);
|
|
1309
1311
|
let mapRouteProperties;
|
|
1310
1312
|
if (init.mapRouteProperties) {
|
|
1311
1313
|
mapRouteProperties = init.mapRouteProperties;
|
|
@@ -1366,28 +1368,17 @@ function createRouter(init) {
|
|
|
1366
1368
|
[route.id]: error
|
|
1367
1369
|
};
|
|
1368
1370
|
}
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
// If partial hydration is enabled, we're initialized so long as we were
|
|
1381
|
-
// provided with hydrationData for every route with a loader, and no loaders
|
|
1382
|
-
// were marked for explicit hydration
|
|
1383
|
-
let loaderData = init.hydrationData ? init.hydrationData.loaderData : null;
|
|
1384
|
-
let errors = init.hydrationData ? init.hydrationData.errors : null;
|
|
1385
|
-
initialized = initialMatches.every(m => m.route.loader && m.route.loader.hydrate !== true && (loaderData && loaderData[m.route.id] !== undefined || errors && errors[m.route.id] !== undefined));
|
|
1386
|
-
} else {
|
|
1387
|
-
// Without partial hydration - we're initialized if we were provided any
|
|
1388
|
-
// hydrationData - which is expected to be complete
|
|
1389
|
-
initialized = init.hydrationData != null;
|
|
1390
|
-
}
|
|
1371
|
+
// "Initialized" here really means "Can `RouterProvider` render my route tree?"
|
|
1372
|
+
// Prior to `route.HydrateFallback`, we only had a root `fallbackElement` so we used
|
|
1373
|
+
// `state.initialized` to render that instead of `<DataRoutes>`. Now that we
|
|
1374
|
+
// support route level fallbacks we can always render and we'll just render
|
|
1375
|
+
// as deep as we have data for and detect the nearest ancestor HydrateFallback
|
|
1376
|
+
let initialized = future.v7_partialHydration ||
|
|
1377
|
+
// All initialMatches need to be loaded before we're ready. If we have lazy
|
|
1378
|
+
// functions around still then we'll need to run them in initialize()
|
|
1379
|
+
!initialMatches.some(m => m.route.lazy) && (
|
|
1380
|
+
// And we have to either have no loaders or have been provided hydrationData
|
|
1381
|
+
!initialMatches.some(m => m.route.loader) || init.hydrationData != null);
|
|
1391
1382
|
let router;
|
|
1392
1383
|
let state = {
|
|
1393
1384
|
historyAction: init.history.action,
|
|
@@ -1530,7 +1521,7 @@ function createRouter(init) {
|
|
|
1530
1521
|
// in the normal navigation flow. For SSR it's expected that lazy modules are
|
|
1531
1522
|
// resolved prior to router creation since we can't go into a fallbackElement
|
|
1532
1523
|
// UI for SSR'd apps
|
|
1533
|
-
if (!state.initialized) {
|
|
1524
|
+
if (!state.initialized || future.v7_partialHydration && state.matches.some(m => isUnhydratedRoute(state, m.route))) {
|
|
1534
1525
|
startNavigation(Action.Pop, state.location, {
|
|
1535
1526
|
initialHydration: true
|
|
1536
1527
|
});
|
|
@@ -2072,10 +2063,9 @@ function createRouter(init) {
|
|
|
2072
2063
|
pendingNavigationController.signal.addEventListener("abort", abortPendingFetchRevalidations);
|
|
2073
2064
|
}
|
|
2074
2065
|
let {
|
|
2075
|
-
results,
|
|
2076
2066
|
loaderResults,
|
|
2077
2067
|
fetcherResults
|
|
2078
|
-
} = await
|
|
2068
|
+
} = await loadDataAndMaybeResolveDeferred(state.matches, matches, matchesToLoad, revalidatingFetchers, request);
|
|
2079
2069
|
if (request.signal.aborted) {
|
|
2080
2070
|
return {
|
|
2081
2071
|
shortCircuited: true
|
|
@@ -2089,7 +2079,7 @@ function createRouter(init) {
|
|
|
2089
2079
|
}
|
|
2090
2080
|
revalidatingFetchers.forEach(rf => fetchControllers.delete(rf.key));
|
|
2091
2081
|
// If any loaders returned a redirect Response, start a new REPLACE navigation
|
|
2092
|
-
let redirect = findRedirect(
|
|
2082
|
+
let redirect = findRedirect([...loaderResults, ...fetcherResults]);
|
|
2093
2083
|
if (redirect) {
|
|
2094
2084
|
if (redirect.idx >= matchesToLoad.length) {
|
|
2095
2085
|
// If this redirect came from a fetcher make sure we mark it in
|
|
@@ -2283,10 +2273,9 @@ function createRouter(init) {
|
|
|
2283
2273
|
let abortPendingFetchRevalidations = () => revalidatingFetchers.forEach(rf => abortFetcher(rf.key));
|
|
2284
2274
|
abortController.signal.addEventListener("abort", abortPendingFetchRevalidations);
|
|
2285
2275
|
let {
|
|
2286
|
-
results,
|
|
2287
2276
|
loaderResults,
|
|
2288
2277
|
fetcherResults
|
|
2289
|
-
} = await
|
|
2278
|
+
} = await loadDataAndMaybeResolveDeferred(state.matches, matches, matchesToLoad, revalidatingFetchers, revalidationRequest);
|
|
2290
2279
|
if (abortController.signal.aborted) {
|
|
2291
2280
|
return;
|
|
2292
2281
|
}
|
|
@@ -2294,7 +2283,7 @@ function createRouter(init) {
|
|
|
2294
2283
|
fetchReloadIds.delete(key);
|
|
2295
2284
|
fetchControllers.delete(key);
|
|
2296
2285
|
revalidatingFetchers.forEach(r => fetchControllers.delete(r.key));
|
|
2297
|
-
let redirect = findRedirect(
|
|
2286
|
+
let redirect = findRedirect([...loaderResults, ...fetcherResults]);
|
|
2298
2287
|
if (redirect) {
|
|
2299
2288
|
if (redirect.idx >= matchesToLoad.length) {
|
|
2300
2289
|
// If this redirect came from a fetcher make sure we mark it in
|
|
@@ -2489,28 +2478,36 @@ function createRouter(init) {
|
|
|
2489
2478
|
});
|
|
2490
2479
|
}
|
|
2491
2480
|
}
|
|
2492
|
-
async function
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
return
|
|
2499
|
-
}
|
|
2500
|
-
|
|
2481
|
+
async function loadDataAndMaybeResolveDeferred(currentMatches, matches, matchesToLoad, fetchersToLoad, request) {
|
|
2482
|
+
let [loaderResults, ...fetcherResults] = await Promise.all([matchesToLoad.length ? dataStrategy({
|
|
2483
|
+
matches: matchesToLoad.map(m => finesseToAgnosticDataStrategyMatch(m, mapRouteProperties, manifest)),
|
|
2484
|
+
request,
|
|
2485
|
+
type: "loader",
|
|
2486
|
+
defaultStrategy(match) {
|
|
2487
|
+
return callLoaderOrActionImplementation("loader", request, match, matches, basename, future.v7_relativeSplatPath);
|
|
2488
|
+
}
|
|
2489
|
+
}) : [], ...fetchersToLoad.map(f => {
|
|
2490
|
+
if (!f.matches || !f.match || !f.controller) {
|
|
2491
|
+
return Promise.resolve({
|
|
2501
2492
|
type: ResultType.error,
|
|
2502
2493
|
error: getInternalRouterError(404, {
|
|
2503
2494
|
pathname: f.path
|
|
2504
2495
|
})
|
|
2505
|
-
};
|
|
2506
|
-
return error;
|
|
2496
|
+
});
|
|
2507
2497
|
}
|
|
2498
|
+
return dataStrategy({
|
|
2499
|
+
matches: [finesseToAgnosticDataStrategyMatch(f.match, mapRouteProperties, manifest)],
|
|
2500
|
+
request,
|
|
2501
|
+
type: "loader",
|
|
2502
|
+
defaultStrategy(match) {
|
|
2503
|
+
invariant(f.controller, "Expected controller for fetcher in defaultStrategy");
|
|
2504
|
+
invariant(f.matches, "Expected matches for fetcher in defaultStrategy");
|
|
2505
|
+
return callLoaderOrActionImplementation("loader", createClientSideRequest(init.history, f.path, f.controller.signal), match, f.matches, basename, future.v7_relativeSplatPath);
|
|
2506
|
+
}
|
|
2507
|
+
}).then(r => r[0]);
|
|
2508
2508
|
})]);
|
|
2509
|
-
let loaderResults = results.slice(0, matchesToLoad.length);
|
|
2510
|
-
let fetcherResults = results.slice(matchesToLoad.length);
|
|
2511
2509
|
await Promise.all([resolveDeferredResults(currentMatches, matchesToLoad, loaderResults, loaderResults.map(() => request.signal), false, state.loaderData), resolveDeferredResults(currentMatches, fetchersToLoad.map(f => f.match), fetcherResults, fetchersToLoad.map(f => f.controller ? f.controller.signal : null), true)]);
|
|
2512
2510
|
return {
|
|
2513
|
-
results,
|
|
2514
2511
|
loaderResults,
|
|
2515
2512
|
fetcherResults
|
|
2516
2513
|
};
|
|
@@ -2806,6 +2803,8 @@ function createRouter(init) {
|
|
|
2806
2803
|
const UNSAFE_DEFERRED_SYMBOL = Symbol("deferred");
|
|
2807
2804
|
function createStaticHandler(routes, opts) {
|
|
2808
2805
|
invariant(routes.length > 0, "You must provide a non-empty routes array to createStaticHandler");
|
|
2806
|
+
const dataStrategy = (opts == null ? void 0 : opts.dataStrategy) || defaultDataStrategy;
|
|
2807
|
+
const callLoaderOrAction = createCallLoaderOrAction(dataStrategy);
|
|
2809
2808
|
let manifest = {};
|
|
2810
2809
|
let basename = (opts ? opts.basename : null) || "/";
|
|
2811
2810
|
let mapRouteProperties;
|
|
@@ -2822,8 +2821,7 @@ function createStaticHandler(routes, opts) {
|
|
|
2822
2821
|
}
|
|
2823
2822
|
// Config driven behavior flags
|
|
2824
2823
|
let future = _extends({
|
|
2825
|
-
v7_relativeSplatPath: false
|
|
2826
|
-
v7_throwAbortReason: false
|
|
2824
|
+
v7_relativeSplatPath: false
|
|
2827
2825
|
}, opts ? opts.future : null);
|
|
2828
2826
|
let dataRoutes = convertRoutesToDataRoutes(routes, mapRouteProperties, undefined, manifest);
|
|
2829
2827
|
/**
|
|
@@ -3040,7 +3038,8 @@ function createStaticHandler(routes, opts) {
|
|
|
3040
3038
|
requestContext
|
|
3041
3039
|
});
|
|
3042
3040
|
if (request.signal.aborted) {
|
|
3043
|
-
|
|
3041
|
+
let method = isRouteRequest ? "queryRoute" : "query";
|
|
3042
|
+
throw new Error(method + "() call aborted: " + request.method + " " + request.url);
|
|
3044
3043
|
}
|
|
3045
3044
|
}
|
|
3046
3045
|
if (isRedirectResult(result)) {
|
|
@@ -3148,13 +3147,21 @@ function createStaticHandler(routes, opts) {
|
|
|
3148
3147
|
activeDeferreds: null
|
|
3149
3148
|
};
|
|
3150
3149
|
}
|
|
3151
|
-
let results = await
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3150
|
+
let results = await dataStrategy({
|
|
3151
|
+
matches: matchesToLoad.map(m => finesseToAgnosticDataStrategyMatch(m, mapRouteProperties, manifest)),
|
|
3152
|
+
request,
|
|
3153
|
+
type: "loader",
|
|
3154
|
+
defaultStrategy(match) {
|
|
3155
|
+
return callLoaderOrActionImplementation("loader", request, match, matches, basename, future.v7_relativeSplatPath, {
|
|
3156
|
+
isStaticRequest: true,
|
|
3157
|
+
isRouteRequest,
|
|
3158
|
+
requestContext
|
|
3159
|
+
});
|
|
3160
|
+
}
|
|
3161
|
+
});
|
|
3156
3162
|
if (request.signal.aborted) {
|
|
3157
|
-
|
|
3163
|
+
let method = isRouteRequest ? "queryRoute" : "query";
|
|
3164
|
+
throw new Error(method + "() call aborted: " + request.method + " " + request.url);
|
|
3158
3165
|
}
|
|
3159
3166
|
// Process and commit output from loaders
|
|
3160
3167
|
let activeDeferreds = new Map();
|
|
@@ -3181,6 +3188,13 @@ function createStaticHandler(routes, opts) {
|
|
|
3181
3188
|
////////////////////////////////////////////////////////////////////////////////
|
|
3182
3189
|
//#region Helpers
|
|
3183
3190
|
////////////////////////////////////////////////////////////////////////////////
|
|
3191
|
+
function defaultDataStrategy(_ref3) {
|
|
3192
|
+
let {
|
|
3193
|
+
defaultStrategy,
|
|
3194
|
+
matches
|
|
3195
|
+
} = _ref3;
|
|
3196
|
+
return Promise.all(matches.map(match => defaultStrategy(match)));
|
|
3197
|
+
}
|
|
3184
3198
|
/**
|
|
3185
3199
|
* Given an existing StaticHandlerContext and an error thrown at render time,
|
|
3186
3200
|
* provide an updated StaticHandlerContext suitable for a second SSR render
|
|
@@ -3194,13 +3208,6 @@ function getStaticContextFromError(routes, context, error) {
|
|
|
3194
3208
|
});
|
|
3195
3209
|
return newContext;
|
|
3196
3210
|
}
|
|
3197
|
-
function throwStaticHandlerAbortedError(request, isRouteRequest, future) {
|
|
3198
|
-
if (future.v7_throwAbortReason && request.signal.reason !== undefined) {
|
|
3199
|
-
throw request.signal.reason;
|
|
3200
|
-
}
|
|
3201
|
-
let method = isRouteRequest ? "queryRoute" : "query";
|
|
3202
|
-
throw new Error(method + "() call aborted: " + request.method + " " + request.url);
|
|
3203
|
-
}
|
|
3204
3211
|
function isSubmissionNavigation(opts) {
|
|
3205
3212
|
return opts != null && ("formData" in opts && opts.formData != null || "body" in opts && opts.body !== undefined);
|
|
3206
3213
|
}
|
|
@@ -3279,8 +3286,8 @@ function normalizeNavigateOptions(normalizeFormMethod, isFetcher, path, opts) {
|
|
|
3279
3286
|
}
|
|
3280
3287
|
let text = typeof opts.body === "string" ? opts.body : opts.body instanceof FormData || opts.body instanceof URLSearchParams ?
|
|
3281
3288
|
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#plain-text-form-data
|
|
3282
|
-
Array.from(opts.body.entries()).reduce((acc,
|
|
3283
|
-
let [name, value] =
|
|
3289
|
+
Array.from(opts.body.entries()).reduce((acc, _ref4) => {
|
|
3290
|
+
let [name, value] = _ref4;
|
|
3284
3291
|
return "" + acc + name + "=" + value + "\n";
|
|
3285
3292
|
}, "") : String(opts.body);
|
|
3286
3293
|
return {
|
|
@@ -3388,24 +3395,18 @@ function getMatchesToLoad(history, state, matches, submission, location, isIniti
|
|
|
3388
3395
|
let boundaryId = pendingError ? Object.keys(pendingError)[0] : undefined;
|
|
3389
3396
|
let boundaryMatches = getLoaderMatchesUntilBoundary(matches, boundaryId);
|
|
3390
3397
|
let navigationMatches = boundaryMatches.filter((match, index) => {
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3398
|
+
if (isInitialLoad) {
|
|
3399
|
+
// On initial hydration we don't do any shouldRevalidate stuff - we just
|
|
3400
|
+
// call the unhydrated loaders
|
|
3401
|
+
return isUnhydratedRoute(state, match.route);
|
|
3402
|
+
}
|
|
3403
|
+
if (match.route.lazy) {
|
|
3395
3404
|
// We haven't loaded this route yet so we don't know if it's got a loader!
|
|
3396
3405
|
return true;
|
|
3397
3406
|
}
|
|
3398
|
-
if (route.loader == null) {
|
|
3407
|
+
if (match.route.loader == null) {
|
|
3399
3408
|
return false;
|
|
3400
3409
|
}
|
|
3401
|
-
if (isInitialLoad) {
|
|
3402
|
-
if (route.loader.hydrate) {
|
|
3403
|
-
return true;
|
|
3404
|
-
}
|
|
3405
|
-
return state.loaderData[route.id] === undefined && (
|
|
3406
|
-
// Don't re-run if the loader ran and threw an error
|
|
3407
|
-
!state.errors || state.errors[route.id] === undefined);
|
|
3408
|
-
}
|
|
3409
3410
|
// Always call the loader on new route instances and pending defer cancellations
|
|
3410
3411
|
if (isNewLoader(state.loaderData, state.matches[index], match) || cancelledDeferredRoutes.some(id => id === match.route.id)) {
|
|
3411
3412
|
return true;
|
|
@@ -3502,6 +3503,19 @@ function getMatchesToLoad(history, state, matches, submission, location, isIniti
|
|
|
3502
3503
|
});
|
|
3503
3504
|
return [navigationMatches, revalidatingFetchers];
|
|
3504
3505
|
}
|
|
3506
|
+
// Is this route unhydrated (when v7_partialHydration=true) such that we need
|
|
3507
|
+
// to call it's loader on the initial router creation
|
|
3508
|
+
function isUnhydratedRoute(state, route) {
|
|
3509
|
+
if (!route.loader) {
|
|
3510
|
+
return false;
|
|
3511
|
+
}
|
|
3512
|
+
if (route.loader.hydrate) {
|
|
3513
|
+
return true;
|
|
3514
|
+
}
|
|
3515
|
+
return state.loaderData[route.id] === undefined && (!state.errors ||
|
|
3516
|
+
// Loader ran but errored - don't re-run
|
|
3517
|
+
state.errors[route.id] === undefined);
|
|
3518
|
+
}
|
|
3505
3519
|
function isNewLoader(currentLoaderData, currentMatch, match) {
|
|
3506
3520
|
let isNew =
|
|
3507
3521
|
// [a] -> [a, b]
|
|
@@ -3540,14 +3554,14 @@ function shouldRevalidateLoader(loaderMatch, arg) {
|
|
|
3540
3554
|
*/
|
|
3541
3555
|
async function loadLazyRouteModule(route, mapRouteProperties, manifest) {
|
|
3542
3556
|
if (!route.lazy) {
|
|
3543
|
-
return;
|
|
3557
|
+
return route;
|
|
3544
3558
|
}
|
|
3545
3559
|
let lazyRoute = await route.lazy();
|
|
3546
3560
|
// If the lazy route function was executed and removed by another parallel
|
|
3547
3561
|
// call then we can return - first lazy() to finish wins because the return
|
|
3548
3562
|
// value of lazy is expected to be static
|
|
3549
3563
|
if (!route.lazy) {
|
|
3550
|
-
return;
|
|
3564
|
+
return route;
|
|
3551
3565
|
}
|
|
3552
3566
|
let routeToUpdate = manifest[route.id];
|
|
3553
3567
|
invariant(routeToUpdate, "No route found in manifest");
|
|
@@ -3580,8 +3594,42 @@ async function loadLazyRouteModule(route, mapRouteProperties, manifest) {
|
|
|
3580
3594
|
Object.assign(routeToUpdate, _extends({}, mapRouteProperties(routeToUpdate), {
|
|
3581
3595
|
lazy: undefined
|
|
3582
3596
|
}));
|
|
3597
|
+
return routeToUpdate;
|
|
3583
3598
|
}
|
|
3584
|
-
|
|
3599
|
+
function createCallLoaderOrAction(dataStrategy) {
|
|
3600
|
+
return async function (type, request, match, matches, manifest, mapRouteProperties, basename, v7_relativeSplatPath, opts) {
|
|
3601
|
+
if (opts === void 0) {
|
|
3602
|
+
opts = {};
|
|
3603
|
+
}
|
|
3604
|
+
let [result] = await dataStrategy({
|
|
3605
|
+
matches: [finesseToAgnosticDataStrategyMatch(match, mapRouteProperties, manifest)],
|
|
3606
|
+
request,
|
|
3607
|
+
type,
|
|
3608
|
+
defaultStrategy(match) {
|
|
3609
|
+
return callLoaderOrActionImplementation(type, request, match, matches, basename, v7_relativeSplatPath, opts);
|
|
3610
|
+
}
|
|
3611
|
+
});
|
|
3612
|
+
return result;
|
|
3613
|
+
};
|
|
3614
|
+
}
|
|
3615
|
+
function finesseToAgnosticDataStrategyMatch(match, mapRouteProperties, manifest) {
|
|
3616
|
+
let loadRoutePromise;
|
|
3617
|
+
if (match.route.lazy) {
|
|
3618
|
+
try {
|
|
3619
|
+
loadRoutePromise = loadLazyRouteModule(match.route, mapRouteProperties, manifest);
|
|
3620
|
+
} catch (error) {
|
|
3621
|
+
loadRoutePromise = Promise.reject(error);
|
|
3622
|
+
}
|
|
3623
|
+
}
|
|
3624
|
+
if (!loadRoutePromise) {
|
|
3625
|
+
loadRoutePromise = Promise.resolve(match.route);
|
|
3626
|
+
}
|
|
3627
|
+
loadRoutePromise.catch(() => {});
|
|
3628
|
+
return _extends({}, match, {
|
|
3629
|
+
route: Object.assign(loadRoutePromise, match.route)
|
|
3630
|
+
});
|
|
3631
|
+
}
|
|
3632
|
+
async function callLoaderOrActionImplementation(type, request, match, matches, basename, v7_relativeSplatPath, opts) {
|
|
3585
3633
|
if (opts === void 0) {
|
|
3586
3634
|
opts = {};
|
|
3587
3635
|
}
|
|
@@ -3612,15 +3660,15 @@ async function callLoaderOrAction(type, request, match, matches, manifest, mapRo
|
|
|
3612
3660
|
// route has a boundary that can handle the error
|
|
3613
3661
|
runHandler(handler).catch(e => {
|
|
3614
3662
|
handlerError = e;
|
|
3615
|
-
}),
|
|
3663
|
+
}), match.route]);
|
|
3616
3664
|
if (handlerError) {
|
|
3617
3665
|
throw handlerError;
|
|
3618
3666
|
}
|
|
3619
3667
|
result = values[0];
|
|
3620
3668
|
} else {
|
|
3621
3669
|
// Load lazy route module, then run any returned handler
|
|
3622
|
-
await
|
|
3623
|
-
handler =
|
|
3670
|
+
let route = await match.route;
|
|
3671
|
+
handler = route[type];
|
|
3624
3672
|
if (handler) {
|
|
3625
3673
|
// Handler still run even if we got interrupted to maintain consistency
|
|
3626
3674
|
// with un-abortable behavior of handler execution on non-lazy or
|
|
@@ -3669,7 +3717,7 @@ async function callLoaderOrAction(type, request, match, matches, manifest, mapRo
|
|
|
3669
3717
|
invariant(location, "Redirects returned/thrown from loaders/actions must have a Location header");
|
|
3670
3718
|
// Support relative routing in internal redirects
|
|
3671
3719
|
if (!ABSOLUTE_URL_REGEX.test(location)) {
|
|
3672
|
-
location = normalizeTo(new URL(request.url), matches.slice(0, matches.
|
|
3720
|
+
location = normalizeTo(new URL(request.url), matches.slice(0, matches.findIndex(m => m.route.id === match.route.id) + 1), basename, true, location, v7_relativeSplatPath);
|
|
3673
3721
|
} else if (!opts.isStaticRequest) {
|
|
3674
3722
|
// Strip off the protocol+origin for same-origin + same-basename absolute
|
|
3675
3723
|
// redirects. If this is a static request, we can let it go back to the
|
|
@@ -3713,11 +3761,7 @@ async function callLoaderOrAction(type, request, match, matches, manifest, mapRo
|
|
|
3713
3761
|
// Check between word boundaries instead of startsWith() due to the last
|
|
3714
3762
|
// paragraph of https://httpwg.org/specs/rfc9110.html#field.content-type
|
|
3715
3763
|
if (contentType && /\bapplication\/json\b/.test(contentType)) {
|
|
3716
|
-
|
|
3717
|
-
data = null;
|
|
3718
|
-
} else {
|
|
3719
|
-
data = await result.json();
|
|
3720
|
-
}
|
|
3764
|
+
data = await result.json();
|
|
3721
3765
|
} else {
|
|
3722
3766
|
data = await result.text();
|
|
3723
3767
|
}
|
|
@@ -4301,5 +4345,5 @@ function persistAppliedTransitions(_window, transitions) {
|
|
|
4301
4345
|
}
|
|
4302
4346
|
//#endregion
|
|
4303
4347
|
|
|
4304
|
-
export { AbortedDeferredError, Action, IDLE_BLOCKER, IDLE_FETCHER, IDLE_NAVIGATION, UNSAFE_DEFERRED_SYMBOL, DeferredData as UNSAFE_DeferredData, ErrorResponseImpl as UNSAFE_ErrorResponseImpl, convertRouteMatchToUiMatch as UNSAFE_convertRouteMatchToUiMatch, convertRoutesToDataRoutes as UNSAFE_convertRoutesToDataRoutes, getResolveToMatches as UNSAFE_getResolveToMatches, invariant as UNSAFE_invariant, warning as UNSAFE_warning, createBrowserHistory, createHashHistory, createMemoryHistory, createPath, createRouter, createStaticHandler, defer, generatePath, getStaticContextFromError, getToPathname, isDeferredData, isRouteErrorResponse, joinPaths, json, matchPath, matchRoutes, normalizePathname, parsePath, redirect, redirectDocument, resolvePath, resolveTo, stripBasename };
|
|
4348
|
+
export { AbortedDeferredError, Action, IDLE_BLOCKER, IDLE_FETCHER, IDLE_NAVIGATION, ResultType, UNSAFE_DEFERRED_SYMBOL, DeferredData as UNSAFE_DeferredData, ErrorResponseImpl as UNSAFE_ErrorResponseImpl, convertRouteMatchToUiMatch as UNSAFE_convertRouteMatchToUiMatch, convertRoutesToDataRoutes as UNSAFE_convertRoutesToDataRoutes, getResolveToMatches as UNSAFE_getResolveToMatches, invariant as UNSAFE_invariant, warning as UNSAFE_warning, createBrowserHistory, createHashHistory, createMemoryHistory, createPath, createRouter, createStaticHandler, defer, generatePath, getStaticContextFromError, getToPathname, isDeferredData, isRouteErrorResponse, joinPaths, json, matchPath, matchRoutes, normalizePathname, parsePath, redirect, redirectDocument, resolvePath, resolveTo, stripBasename };
|
|
4305
4349
|
//# sourceMappingURL=router.js.map
|