@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/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-c9f8a7b2
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 = /^:[\w-]+$/;
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(/^:([\w-]+)(\??)$/);
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(/\/:([\w-]+)(\?)?/g, (_, paramName, isOptional) => {
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
- let initialized;
1370
- let hasLazyRoutes = initialMatches.some(m => m.route.lazy);
1371
- let hasLoaders = initialMatches.some(m => m.route.loader);
1372
- if (hasLazyRoutes) {
1373
- // All initialMatches need to be loaded before we're ready. If we have lazy
1374
- // functions around still then we'll need to run them in initialize()
1375
- initialized = false;
1376
- } else if (!hasLoaders) {
1377
- // If we've got no loaders to run, then we're good to go
1378
- initialized = true;
1379
- } else if (future.v7_partialHydration) {
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 callLoadersAndMaybeResolveData(state.matches, matches, matchesToLoad, revalidatingFetchers, request);
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(results);
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 callLoadersAndMaybeResolveData(state.matches, matches, matchesToLoad, revalidatingFetchers, revalidationRequest);
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(results);
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 callLoadersAndMaybeResolveData(currentMatches, matches, matchesToLoad, fetchersToLoad, request) {
2493
- // Call all navigation loaders and revalidating fetcher loaders in parallel,
2494
- // then slice off the results into separate arrays so we can handle them
2495
- // accordingly
2496
- let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath)), ...fetchersToLoad.map(f => {
2497
- if (f.matches && f.match && f.controller) {
2498
- return callLoaderOrAction("loader", createClientSideRequest(init.history, f.path, f.controller.signal), f.match, f.matches, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath);
2499
- } else {
2500
- let error = {
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
- throwStaticHandlerAbortedError(request, isRouteRequest, future);
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 Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath, {
3152
- isStaticRequest: true,
3153
- isRouteRequest,
3154
- requestContext
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
- throwStaticHandlerAbortedError(request, isRouteRequest, future);
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, _ref3) => {
3283
- let [name, value] = _ref3;
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
- let {
3392
- route
3393
- } = match;
3394
- if (route.lazy) {
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
- async function callLoaderOrAction(type, request, match, matches, manifest, mapRouteProperties, basename, v7_relativeSplatPath, opts) {
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
- }), loadLazyRouteModule(match.route, mapRouteProperties, manifest)]);
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 loadLazyRouteModule(match.route, mapRouteProperties, manifest);
3623
- handler = match.route[type];
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.indexOf(match) + 1), basename, true, location, v7_relativeSplatPath);
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
- if (result.body == null) {
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