@remix-run/router 1.13.1 → 1.14.0-pre.0

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
@@ -12,6 +12,13 @@ export interface Router {
12
12
  * Return the basename for the router
13
13
  */
14
14
  get basename(): RouterInit["basename"];
15
+ /**
16
+ * @internal
17
+ * PRIVATE - DO NOT USE
18
+ *
19
+ * Return the future config for the router
20
+ */
21
+ get future(): FutureConfig;
15
22
  /**
16
23
  * @internal
17
24
  * PRIVATE - DO NOT USE
@@ -248,7 +255,9 @@ export type HydrationState = Partial<Pick<RouterState, "loaderData" | "actionDat
248
255
  export interface FutureConfig {
249
256
  v7_fetcherPersist: boolean;
250
257
  v7_normalizeFormMethod: boolean;
258
+ v7_partialHydration: boolean;
251
259
  v7_prependBasename: boolean;
260
+ v7_relativeSplatPath: boolean;
252
261
  }
253
262
  /**
254
263
  * Initialization options for createRouter
@@ -473,6 +482,12 @@ export declare const IDLE_BLOCKER: BlockerUnblocked;
473
482
  */
474
483
  export declare function createRouter(init: RouterInit): Router;
475
484
  export declare const UNSAFE_DEFERRED_SYMBOL: unique symbol;
485
+ /**
486
+ * Future flags to toggle new feature behavior
487
+ */
488
+ export interface StaticHandlerFutureConfig {
489
+ v7_relativeSplatPath: boolean;
490
+ }
476
491
  export interface CreateStaticHandlerOptions {
477
492
  basename?: string;
478
493
  /**
@@ -480,6 +495,7 @@ export interface CreateStaticHandlerOptions {
480
495
  */
481
496
  detectErrorBoundary?: DetectErrorBoundaryFunction;
482
497
  mapRouteProperties?: MapRoutePropertiesFunction;
498
+ future?: Partial<StaticHandlerFutureConfig>;
483
499
  }
484
500
  export declare function createStaticHandler(routes: AgnosticRouteObject[], opts?: CreateStaticHandlerOptions): StaticHandler;
485
501
  /**
package/dist/router.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @remix-run/router v1.13.1
2
+ * @remix-run/router v1.14.0-pre.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -938,6 +938,18 @@ function getInvalidPathError(char, field, dest, path) {
938
938
  function getPathContributingMatches(matches) {
939
939
  return matches.filter((match, index) => index === 0 || match.route.path && match.route.path.length > 0);
940
940
  }
941
+ // Return the array of pathnames for the current route matches - used to
942
+ // generate the routePathnames input for resolveTo()
943
+ function getResolveToMatches(matches, v7_relativeSplatPath) {
944
+ let pathMatches = getPathContributingMatches(matches);
945
+ // When v7_relativeSplatPath is enabled, use the full pathname for the leaf
946
+ // match so we include splat values for "." links. See:
947
+ // https://github.com/remix-run/react-router/issues/11052#issuecomment-1836589329
948
+ if (v7_relativeSplatPath) {
949
+ return pathMatches.map((match, idx) => idx === matches.length - 1 ? match.pathname : match.pathnameBase);
950
+ }
951
+ return pathMatches.map(match => match.pathnameBase);
952
+ }
941
953
  /**
942
954
  * @private
943
955
  */
@@ -969,7 +981,7 @@ function resolveTo(toArg, routePathnames, locationPathname, isPathRelative) {
969
981
  if (toPathname == null) {
970
982
  from = locationPathname;
971
983
  } else if (isPathRelative) {
972
- let fromSegments = routePathnames[routePathnames.length - 1].replace(/^\//, "").split("/");
984
+ let fromSegments = routePathnames.length === 0 ? [] : routePathnames[routePathnames.length - 1].replace(/^\//, "").split("/");
973
985
  if (toPathname.startsWith("..")) {
974
986
  let toSegments = toPathname.split("/");
975
987
  // With relative="path", each leading .. segment means "go up one URL segment"
@@ -1330,7 +1342,9 @@ function createRouter(init) {
1330
1342
  let future = _extends({
1331
1343
  v7_fetcherPersist: false,
1332
1344
  v7_normalizeFormMethod: false,
1333
- v7_prependBasename: false
1345
+ v7_partialHydration: false,
1346
+ v7_prependBasename: false,
1347
+ v7_relativeSplatPath: false
1334
1348
  }, init.future);
1335
1349
  // Cleanup function for history
1336
1350
  let unlistenHistory = null;
@@ -1366,7 +1380,12 @@ function createRouter(init) {
1366
1380
  [route.id]: error
1367
1381
  };
1368
1382
  }
1369
- let initialized =
1383
+ // "Initialized" here really means "Can `RouterProvider` render my route tree?"
1384
+ // Prior to `route.HydrateFallback`, we only had a root `fallbackElement` so we used
1385
+ // `state.initialized` to render that instead of `<DataRoutes>`. Now that we
1386
+ // support route level fallbacks we can always render and we'll just render
1387
+ // as deep as we have data for and detect the nearest ancestor HydrateFallback
1388
+ let initialized = future.v7_partialHydration ||
1370
1389
  // All initialMatches need to be loaded before we're ready. If we have lazy
1371
1390
  // functions around still then we'll need to run them in initialize()
1372
1391
  !initialMatches.some(m => m.route.lazy) && (
@@ -1514,8 +1533,10 @@ function createRouter(init) {
1514
1533
  // in the normal navigation flow. For SSR it's expected that lazy modules are
1515
1534
  // resolved prior to router creation since we can't go into a fallbackElement
1516
1535
  // UI for SSR'd apps
1517
- if (!state.initialized) {
1518
- startNavigation(Action.Pop, state.location);
1536
+ if (!state.initialized || future.v7_partialHydration && state.matches.some(m => isUnhydratedRoute(state, m.route))) {
1537
+ startNavigation(Action.Pop, state.location, {
1538
+ initialHydration: true
1539
+ });
1519
1540
  }
1520
1541
  return router;
1521
1542
  }
@@ -1690,7 +1711,7 @@ function createRouter(init) {
1690
1711
  init.history.go(to);
1691
1712
  return;
1692
1713
  }
1693
- let normalizedPath = normalizeTo(state.location, state.matches, basename, future.v7_prependBasename, to, opts == null ? void 0 : opts.fromRouteId, opts == null ? void 0 : opts.relative);
1714
+ let normalizedPath = normalizeTo(state.location, state.matches, basename, future.v7_prependBasename, to, future.v7_relativeSplatPath, opts == null ? void 0 : opts.fromRouteId, opts == null ? void 0 : opts.relative);
1694
1715
  let {
1695
1716
  path,
1696
1717
  submission,
@@ -1879,7 +1900,7 @@ function createRouter(init) {
1879
1900
  shortCircuited,
1880
1901
  loaderData,
1881
1902
  errors
1882
- } = await handleLoaders(request, location, matches, loadingNavigation, opts && opts.submission, opts && opts.fetcherSubmission, opts && opts.replace, flushSync, pendingActionData, pendingError);
1903
+ } = await handleLoaders(request, location, matches, loadingNavigation, opts && opts.submission, opts && opts.fetcherSubmission, opts && opts.replace, opts && opts.initialHydration === true, flushSync, pendingActionData, pendingError);
1883
1904
  if (shortCircuited) {
1884
1905
  return;
1885
1906
  }
@@ -1923,7 +1944,7 @@ function createRouter(init) {
1923
1944
  })
1924
1945
  };
1925
1946
  } else {
1926
- result = await callLoaderOrAction("action", request, actionMatch, matches, manifest, mapRouteProperties, basename);
1947
+ result = await callLoaderOrAction("action", request, actionMatch, matches, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath);
1927
1948
  if (request.signal.aborted) {
1928
1949
  return {
1929
1950
  shortCircuited: true
@@ -1980,14 +2001,14 @@ function createRouter(init) {
1980
2001
  }
1981
2002
  // Call all applicable loaders for the given matches, handling redirects,
1982
2003
  // errors, etc.
1983
- async function handleLoaders(request, location, matches, overrideNavigation, submission, fetcherSubmission, replace, flushSync, pendingActionData, pendingError) {
2004
+ async function handleLoaders(request, location, matches, overrideNavigation, submission, fetcherSubmission, replace, initialHydration, flushSync, pendingActionData, pendingError) {
1984
2005
  // Figure out the right navigation we want to use for data loading
1985
2006
  let loadingNavigation = overrideNavigation || getLoadingNavigation(location, submission);
1986
2007
  // If this was a redirect from an action we don't have a "submission" but
1987
2008
  // we have it on the loading navigation so use that if available
1988
2009
  let activeSubmission = submission || fetcherSubmission || getSubmissionFromNavigation(loadingNavigation);
1989
2010
  let routesToUse = inFlightDataRoutes || dataRoutes;
1990
- let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, activeSubmission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, deletedFetchers, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, pendingActionData, pendingError);
2011
+ let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, activeSubmission, location, future.v7_partialHydration && initialHydration === true, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, deletedFetchers, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, pendingActionData, pendingError);
1991
2012
  // Cancel pending deferreds for no-longer-matched routes or routes we're
1992
2013
  // about to reload. Note that if this is an action reload we would have
1993
2014
  // already cancelled all pending deferreds so this would be a no-op
@@ -2016,7 +2037,9 @@ function createRouter(init) {
2016
2037
  // state. If not, we need to switch to our loading state and load data,
2017
2038
  // preserving any new action data or existing action data (in the case of
2018
2039
  // a revalidation interrupting an actionReload)
2019
- if (!isUninterruptedRevalidation) {
2040
+ // If we have partialHydration enabled, then don't update the state for the
2041
+ // initial data load since iot's not a "navigation"
2042
+ if (!isUninterruptedRevalidation && (!future.v7_partialHydration || !initialHydration)) {
2020
2043
  revalidatingFetchers.forEach(rf => {
2021
2044
  let fetcher = state.fetchers.get(rf.key);
2022
2045
  let revalidatingFetcher = getLoadingFetcher(undefined, fetcher ? fetcher.data : undefined);
@@ -2119,7 +2142,7 @@ function createRouter(init) {
2119
2142
  if (fetchControllers.has(key)) abortFetcher(key);
2120
2143
  let flushSync = (opts && opts.unstable_flushSync) === true;
2121
2144
  let routesToUse = inFlightDataRoutes || dataRoutes;
2122
- let normalizedPath = normalizeTo(state.location, state.matches, basename, future.v7_prependBasename, href, routeId, opts == null ? void 0 : opts.relative);
2145
+ let normalizedPath = normalizeTo(state.location, state.matches, basename, future.v7_prependBasename, href, future.v7_relativeSplatPath, routeId, opts == null ? void 0 : opts.relative);
2123
2146
  let matches = matchRoutes(routesToUse, normalizedPath, basename);
2124
2147
  if (!matches) {
2125
2148
  setFetcherError(key, routeId, getInternalRouterError(404, {
@@ -2180,7 +2203,7 @@ function createRouter(init) {
2180
2203
  let fetchRequest = createClientSideRequest(init.history, path, abortController.signal, submission);
2181
2204
  fetchControllers.set(key, abortController);
2182
2205
  let originatingLoadId = incrementingLoadId;
2183
- let actionResult = await callLoaderOrAction("action", fetchRequest, match, requestMatches, manifest, mapRouteProperties, basename);
2206
+ let actionResult = await callLoaderOrAction("action", fetchRequest, match, requestMatches, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath);
2184
2207
  if (fetchRequest.signal.aborted) {
2185
2208
  // We can delete this so long as we weren't aborted by our own fetcher
2186
2209
  // re-submit which would have put _new_ controller is in fetchControllers
@@ -2231,7 +2254,7 @@ function createRouter(init) {
2231
2254
  fetchReloadIds.set(key, loadId);
2232
2255
  let loadFetcher = getLoadingFetcher(submission, actionResult.data);
2233
2256
  state.fetchers.set(key, loadFetcher);
2234
- let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, submission, nextLocation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, deletedFetchers, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, {
2257
+ let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, submission, nextLocation, false, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, deletedFetchers, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, {
2235
2258
  [match.route.id]: actionResult.data
2236
2259
  }, undefined // No need to send through errors since we short circuit above
2237
2260
  );
@@ -2325,7 +2348,7 @@ function createRouter(init) {
2325
2348
  let fetchRequest = createClientSideRequest(init.history, path, abortController.signal);
2326
2349
  fetchControllers.set(key, abortController);
2327
2350
  let originatingLoadId = incrementingLoadId;
2328
- let result = await callLoaderOrAction("loader", fetchRequest, match, matches, manifest, mapRouteProperties, basename);
2351
+ let result = await callLoaderOrAction("loader", fetchRequest, match, matches, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath);
2329
2352
  // Deferred isn't supported for fetcher loads, await everything and treat it
2330
2353
  // as a normal load. resolveDeferredData will return undefined if this
2331
2354
  // fetcher gets aborted, so we just leave result untouched and short circuit
@@ -2464,9 +2487,9 @@ function createRouter(init) {
2464
2487
  // Call all navigation loaders and revalidating fetcher loaders in parallel,
2465
2488
  // then slice off the results into separate arrays so we can handle them
2466
2489
  // accordingly
2467
- let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, manifest, mapRouteProperties, basename)), ...fetchersToLoad.map(f => {
2490
+ let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath)), ...fetchersToLoad.map(f => {
2468
2491
  if (f.matches && f.match && f.controller) {
2469
- return callLoaderOrAction("loader", createClientSideRequest(init.history, f.path, f.controller.signal), f.match, f.matches, manifest, mapRouteProperties, basename);
2492
+ return callLoaderOrAction("loader", createClientSideRequest(init.history, f.path, f.controller.signal), f.match, f.matches, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath);
2470
2493
  } else {
2471
2494
  let error = {
2472
2495
  type: ResultType.error,
@@ -2735,6 +2758,9 @@ function createRouter(init) {
2735
2758
  get basename() {
2736
2759
  return basename;
2737
2760
  },
2761
+ get future() {
2762
+ return future;
2763
+ },
2738
2764
  get state() {
2739
2765
  return state;
2740
2766
  },
@@ -2788,6 +2814,10 @@ function createStaticHandler(routes, opts) {
2788
2814
  } else {
2789
2815
  mapRouteProperties = defaultMapRouteProperties;
2790
2816
  }
2817
+ // Config driven behavior flags
2818
+ let future = _extends({
2819
+ v7_relativeSplatPath: false
2820
+ }, opts ? opts.future : null);
2791
2821
  let dataRoutes = convertRoutesToDataRoutes(routes, mapRouteProperties, undefined, manifest);
2792
2822
  /**
2793
2823
  * The query() method is intended for document requests, in which we want to
@@ -2997,7 +3027,7 @@ function createStaticHandler(routes, opts) {
2997
3027
  error
2998
3028
  };
2999
3029
  } else {
3000
- result = await callLoaderOrAction("action", request, actionMatch, matches, manifest, mapRouteProperties, basename, {
3030
+ result = await callLoaderOrAction("action", request, actionMatch, matches, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath, {
3001
3031
  isStaticRequest: true,
3002
3032
  isRouteRequest,
3003
3033
  requestContext
@@ -3112,7 +3142,7 @@ function createStaticHandler(routes, opts) {
3112
3142
  activeDeferreds: null
3113
3143
  };
3114
3144
  }
3115
- let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, manifest, mapRouteProperties, basename, {
3145
+ let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath, {
3116
3146
  isStaticRequest: true,
3117
3147
  isRouteRequest,
3118
3148
  requestContext
@@ -3162,7 +3192,7 @@ function getStaticContextFromError(routes, context, error) {
3162
3192
  function isSubmissionNavigation(opts) {
3163
3193
  return opts != null && ("formData" in opts && opts.formData != null || "body" in opts && opts.body !== undefined);
3164
3194
  }
3165
- function normalizeTo(location, matches, basename, prependBasename, to, fromRouteId, relative) {
3195
+ function normalizeTo(location, matches, basename, prependBasename, to, v7_relativeSplatPath, fromRouteId, relative) {
3166
3196
  let contextualMatches;
3167
3197
  let activeRouteMatch;
3168
3198
  if (fromRouteId) {
@@ -3181,7 +3211,7 @@ function normalizeTo(location, matches, basename, prependBasename, to, fromRoute
3181
3211
  activeRouteMatch = matches[matches.length - 1];
3182
3212
  }
3183
3213
  // Resolve the relative path
3184
- let path = resolveTo(to ? to : ".", getPathContributingMatches(contextualMatches).map(m => m.pathnameBase), stripBasename(location.pathname, basename) || location.pathname, relative === "path");
3214
+ let path = resolveTo(to ? to : ".", getResolveToMatches(contextualMatches, v7_relativeSplatPath), stripBasename(location.pathname, basename) || location.pathname, relative === "path");
3185
3215
  // When `to` is not specified we inherit search/hash from the current
3186
3216
  // location, unlike when to="." and we just inherit the path.
3187
3217
  // See https://github.com/remix-run/remix/issues/927
@@ -3338,7 +3368,7 @@ function getLoaderMatchesUntilBoundary(matches, boundaryId) {
3338
3368
  }
3339
3369
  return boundaryMatches;
3340
3370
  }
3341
- function getMatchesToLoad(history, state, matches, submission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, deletedFetchers, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, pendingActionData, pendingError) {
3371
+ function getMatchesToLoad(history, state, matches, submission, location, isInitialLoad, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, deletedFetchers, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, pendingActionData, pendingError) {
3342
3372
  let actionResult = pendingError ? Object.values(pendingError)[0] : pendingActionData ? Object.values(pendingActionData)[0] : undefined;
3343
3373
  let currentUrl = history.createURL(state.location);
3344
3374
  let nextUrl = history.createURL(location);
@@ -3346,6 +3376,11 @@ function getMatchesToLoad(history, state, matches, submission, location, isReval
3346
3376
  let boundaryId = pendingError ? Object.keys(pendingError)[0] : undefined;
3347
3377
  let boundaryMatches = getLoaderMatchesUntilBoundary(matches, boundaryId);
3348
3378
  let navigationMatches = boundaryMatches.filter((match, index) => {
3379
+ if (isInitialLoad) {
3380
+ // On initial hydration we don't do any shouldRevalidate stuff - we just
3381
+ // call the unhydrated loaders
3382
+ return isUnhydratedRoute(state, match.route);
3383
+ }
3349
3384
  if (match.route.lazy) {
3350
3385
  // We haven't loaded this route yet so we don't know if it's got a loader!
3351
3386
  return true;
@@ -3382,8 +3417,12 @@ function getMatchesToLoad(history, state, matches, submission, location, isReval
3382
3417
  // Pick fetcher.loads that need to be revalidated
3383
3418
  let revalidatingFetchers = [];
3384
3419
  fetchLoadMatches.forEach((f, key) => {
3385
- // Don't revalidate if fetcher won't be present in the subsequent render
3386
- if (!matches.some(m => m.route.id === f.routeId) || deletedFetchers.has(key)) {
3420
+ // Don't revalidate:
3421
+ // - on initial load (shouldn't be any fetchers then anyway)
3422
+ // - if fetcher won't be present in the subsequent render
3423
+ // - no longer matches the URL (v7_fetcherPersist=false)
3424
+ // - was unmounted but persisted due to v7_fetcherPersist=true
3425
+ if (isInitialLoad || !matches.some(m => m.route.id === f.routeId) || deletedFetchers.has(key)) {
3387
3426
  return;
3388
3427
  }
3389
3428
  let fetcherMatches = matchRoutes(routesToUse, f.path, basename);
@@ -3445,6 +3484,19 @@ function getMatchesToLoad(history, state, matches, submission, location, isReval
3445
3484
  });
3446
3485
  return [navigationMatches, revalidatingFetchers];
3447
3486
  }
3487
+ // Is this route unhydrated (when v7_partialHydration=true) such that we need
3488
+ // to call it's loader on the initial router creation
3489
+ function isUnhydratedRoute(state, route) {
3490
+ if (!route.loader) {
3491
+ return false;
3492
+ }
3493
+ if (route.loader.hydrate) {
3494
+ return true;
3495
+ }
3496
+ return state.loaderData[route.id] === undefined && (!state.errors ||
3497
+ // Loader ran but errored - don't re-run
3498
+ state.errors[route.id] === undefined);
3499
+ }
3448
3500
  function isNewLoader(currentLoaderData, currentMatch, match) {
3449
3501
  let isNew =
3450
3502
  // [a] -> [a, b]
@@ -3524,7 +3576,7 @@ async function loadLazyRouteModule(route, mapRouteProperties, manifest) {
3524
3576
  lazy: undefined
3525
3577
  }));
3526
3578
  }
3527
- async function callLoaderOrAction(type, request, match, matches, manifest, mapRouteProperties, basename, opts) {
3579
+ async function callLoaderOrAction(type, request, match, matches, manifest, mapRouteProperties, basename, v7_relativeSplatPath, opts) {
3528
3580
  if (opts === void 0) {
3529
3581
  opts = {};
3530
3582
  }
@@ -3612,7 +3664,7 @@ async function callLoaderOrAction(type, request, match, matches, manifest, mapRo
3612
3664
  invariant(location, "Redirects returned/thrown from loaders/actions must have a Location header");
3613
3665
  // Support relative routing in internal redirects
3614
3666
  if (!ABSOLUTE_URL_REGEX.test(location)) {
3615
- location = normalizeTo(new URL(request.url), matches.slice(0, matches.indexOf(match) + 1), basename, true, location);
3667
+ location = normalizeTo(new URL(request.url), matches.slice(0, matches.indexOf(match) + 1), basename, true, location, v7_relativeSplatPath);
3616
3668
  } else if (!opts.isStaticRequest) {
3617
3669
  // Strip off the protocol+origin for same-origin + same-basename absolute
3618
3670
  // redirects. If this is a static request, we can let it go back to the
@@ -3651,13 +3703,20 @@ async function callLoaderOrAction(type, request, match, matches, manifest, mapRo
3651
3703
  throw queryRouteResponse;
3652
3704
  }
3653
3705
  let data;
3654
- let contentType = result.headers.get("Content-Type");
3655
- // Check between word boundaries instead of startsWith() due to the last
3656
- // paragraph of https://httpwg.org/specs/rfc9110.html#field.content-type
3657
- if (contentType && /\bapplication\/json\b/.test(contentType)) {
3658
- data = await result.json();
3659
- } else {
3660
- data = await result.text();
3706
+ try {
3707
+ let contentType = result.headers.get("Content-Type");
3708
+ // Check between word boundaries instead of startsWith() due to the last
3709
+ // paragraph of https://httpwg.org/specs/rfc9110.html#field.content-type
3710
+ if (contentType && /\bapplication\/json\b/.test(contentType)) {
3711
+ data = await result.json();
3712
+ } else {
3713
+ data = await result.text();
3714
+ }
3715
+ } catch (e) {
3716
+ return {
3717
+ type: ResultType.error,
3718
+ error: e
3719
+ };
3661
3720
  }
3662
3721
  if (resultType === ResultType.error) {
3663
3722
  return {
@@ -4233,5 +4292,5 @@ function persistAppliedTransitions(_window, transitions) {
4233
4292
  }
4234
4293
  //#endregion
4235
4294
 
4236
- 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, getPathContributingMatches as UNSAFE_getPathContributingMatches, 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 };
4295
+ 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 };
4237
4296
  //# sourceMappingURL=router.js.map