react-router 7.0.0-pre.1 → 7.0.0-pre.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/dom-export.mjs +10 -2
  3. package/dist/dom-export.mjs.map +1 -1
  4. package/dist/index.d.ts +2 -3
  5. package/dist/index.mjs +1375 -219
  6. package/dist/index.mjs.map +1 -1
  7. package/dist/lib/components.d.ts +6 -6
  8. package/dist/lib/dom/lib.d.ts +3 -2
  9. package/dist/lib/dom/ssr/components.d.ts +0 -1
  10. package/dist/lib/dom/ssr/data.d.ts +0 -5
  11. package/dist/lib/dom/ssr/entry.d.ts +2 -1
  12. package/dist/lib/dom/ssr/routeModules.d.ts +64 -22
  13. package/dist/lib/dom/ssr/routes.d.ts +2 -5
  14. package/dist/lib/hooks.d.ts +4 -3
  15. package/dist/lib/router/router.d.ts +4 -0
  16. package/dist/lib/router/utils.d.ts +1 -9
  17. package/dist/lib/server-runtime/build.d.ts +1 -1
  18. package/dist/lib/server-runtime/cookies.d.ts +5 -5
  19. package/dist/lib/server-runtime/data.d.ts +1 -5
  20. package/dist/lib/server-runtime/routeModules.d.ts +3 -175
  21. package/dist/lib/server-runtime/routes.d.ts +2 -22
  22. package/dist/lib/server-runtime/sessions.d.ts +4 -4
  23. package/dist/lib/types.d.ts +17 -10
  24. package/dist/lib/types.mjs +1 -1
  25. package/dist/main-dom-export.js +1 -1
  26. package/dist/main.js +1 -1
  27. package/dist/react-router-dom.development.js +2 -2
  28. package/dist/react-router-dom.development.js.map +1 -1
  29. package/dist/react-router-dom.production.min.js +2 -2
  30. package/dist/react-router-dom.production.min.js.map +1 -1
  31. package/dist/react-router.development.js +196 -171
  32. package/dist/react-router.development.js.map +1 -1
  33. package/dist/react-router.production.min.js +2 -2
  34. package/dist/react-router.production.min.js.map +1 -1
  35. package/dist/umd/react-router-dom.development.js +2 -2
  36. package/dist/umd/react-router-dom.development.js.map +1 -1
  37. package/dist/umd/react-router-dom.production.min.js +2 -2
  38. package/dist/umd/react-router-dom.production.min.js.map +1 -1
  39. package/dist/umd/react-router.development.js +195 -179
  40. package/dist/umd/react-router.development.js.map +1 -1
  41. package/dist/umd/react-router.production.min.js +2 -2
  42. package/dist/umd/react-router.production.min.js.map +1 -1
  43. package/package.json +4 -4
  44. package/dist/lib/server-runtime/jsonify.d.ts +0 -33
  45. package/dist/lib/server-runtime/responses.d.ts +0 -37
@@ -1,5 +1,5 @@
1
1
  /**
2
- * React Router v7.0.0-pre.1
2
+ * React Router v7.0.0-pre.2
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -310,7 +310,7 @@
310
310
  pathname = "/",
311
311
  search = "",
312
312
  hash = ""
313
- } = parsePath(window.location.hash.substr(1));
313
+ } = parsePath(window.location.hash.substring(1));
314
314
 
315
315
  // Hash URL should always have a leading / just like window.location.pathname
316
316
  // does, so if an app ends up at a route like /#something then we add a
@@ -373,7 +373,7 @@
373
373
  }
374
374
  }
375
375
  function createKey$1() {
376
- return Math.random().toString(36).substr(2, 8);
376
+ return Math.random().toString(36).substring(2, 10);
377
377
  }
378
378
 
379
379
  /**
@@ -435,13 +435,13 @@
435
435
  if (path) {
436
436
  let hashIndex = path.indexOf("#");
437
437
  if (hashIndex >= 0) {
438
- parsedPath.hash = path.substr(hashIndex);
439
- path = path.substr(0, hashIndex);
438
+ parsedPath.hash = path.substring(hashIndex);
439
+ path = path.substring(0, hashIndex);
440
440
  }
441
441
  let searchIndex = path.indexOf("?");
442
442
  if (searchIndex >= 0) {
443
- parsedPath.search = path.substr(searchIndex);
444
- path = path.substr(0, searchIndex);
443
+ parsedPath.search = path.substring(searchIndex);
444
+ path = path.substring(0, searchIndex);
445
445
  }
446
446
  if (path) {
447
447
  parsedPath.pathname = path;
@@ -1335,28 +1335,6 @@
1335
1335
  * @private
1336
1336
  */
1337
1337
  const normalizeHash = hash => !hash || hash === "#" ? "" : hash.startsWith("#") ? hash : "#" + hash;
1338
-
1339
- /**
1340
- * This is a shortcut for creating `application/json` responses. Converts `data`
1341
- * to JSON and sets the `Content-Type` header.
1342
- *
1343
- * @category Utils
1344
- */
1345
- const json$1 = function json(data, init) {
1346
- if (init === void 0) {
1347
- init = {};
1348
- }
1349
- let responseInit = typeof init === "number" ? {
1350
- status: init
1351
- } : init;
1352
- let headers = new Headers(responseInit.headers);
1353
- if (!headers.has("Content-Type")) {
1354
- headers.set("Content-Type", "application/json; charset=utf-8");
1355
- }
1356
- return new Response(JSON.stringify(data), _extends({}, responseInit, {
1357
- headers
1358
- }));
1359
- };
1360
1338
  class DataWithResponseInit {
1361
1339
  constructor(data, init) {
1362
1340
  this.type = "DataWithResponseInit";
@@ -1376,6 +1354,10 @@
1376
1354
  status: init
1377
1355
  } : init);
1378
1356
  }
1357
+
1358
+ // This is now only used by the Await component and will eventually probably
1359
+ // go away in favor of the format used by `React.use`
1360
+
1379
1361
  /**
1380
1362
  * A redirect response. Sets the status code and the `Location` header.
1381
1363
  * Defaults to "302 Found".
@@ -1564,7 +1546,7 @@
1564
1546
  const validMutationMethods = new Set(validMutationMethodsArr);
1565
1547
  const validRequestMethodsArr = ["GET", ...validMutationMethodsArr];
1566
1548
  const validRequestMethods = new Set(validRequestMethodsArr);
1567
- const redirectStatusCodes$1 = new Set([301, 302, 303, 307, 308]);
1549
+ const redirectStatusCodes = new Set([301, 302, 303, 307, 308]);
1568
1550
  const redirectPreserveMethodStatusCodes = new Set([307, 308]);
1569
1551
  const IDLE_NAVIGATION = {
1570
1552
  state: "idle",
@@ -3083,7 +3065,7 @@
3083
3065
  return dataResults;
3084
3066
  }
3085
3067
  for (let [routeId, result] of Object.entries(results)) {
3086
- if (isRedirectDataStrategyResultResult(result)) {
3068
+ if (isRedirectDataStrategyResult(result)) {
3087
3069
  let response = result.result;
3088
3070
  dataResults[routeId] = {
3089
3071
  type: ResultType.redirect,
@@ -3096,8 +3078,6 @@
3096
3078
  return dataResults;
3097
3079
  }
3098
3080
  async function callLoadersAndMaybeResolveData(state, matches, matchesToLoad, fetchersToLoad, request) {
3099
- state.matches;
3100
-
3101
3081
  // Kick off loaders and fetchers in parallel
3102
3082
  let loaderResultsPromise = callDataStrategy("loader", state, request, matchesToLoad, matches, null);
3103
3083
  let fetcherResultsPromise = Promise.all(fetchersToLoad.map(async f => {
@@ -3609,7 +3589,7 @@
3609
3589
  };
3610
3590
  }
3611
3591
  let result = await queryImpl(request, location, matches, requestContext, dataStrategy || null, skipLoaderErrorBubbling === true, null);
3612
- if (isResponse$2(result)) {
3592
+ if (isResponse(result)) {
3613
3593
  return result;
3614
3594
  }
3615
3595
 
@@ -3682,7 +3662,7 @@
3682
3662
  });
3683
3663
  }
3684
3664
  let result = await queryImpl(request, location, matches, requestContext, dataStrategy || null, false, match);
3685
- if (isResponse$2(result)) {
3665
+ if (isResponse(result)) {
3686
3666
  return result;
3687
3667
  }
3688
3668
  let error = result.errors ? Object.values(result.errors)[0] : undefined;
@@ -3711,7 +3691,7 @@
3711
3691
  return result;
3712
3692
  }
3713
3693
  let result = await loadRouteData(request, matches, requestContext, dataStrategy, skipLoaderErrorBubbling, routeMatch);
3714
- return isResponse$2(result) ? result : _extends({}, result, {
3694
+ return isResponse(result) ? result : _extends({}, result, {
3715
3695
  actionData: null,
3716
3696
  actionHeaders: {}
3717
3697
  });
@@ -3719,7 +3699,7 @@
3719
3699
  // If the user threw/returned a Response in callLoaderOrAction for a
3720
3700
  // `queryRoute` call, we throw the `DataStrategyResult` to bail out early
3721
3701
  // and then return or throw the raw Response here accordingly
3722
- if (isDataStrategyResult(e) && isResponse$2(e.result)) {
3702
+ if (isDataStrategyResult(e) && isResponse(e.result)) {
3723
3703
  if (e.type === ResultType.error) {
3724
3704
  throw e.result;
3725
3705
  }
@@ -3727,7 +3707,7 @@
3727
3707
  }
3728
3708
  // Redirects are always returned since they don't propagate to catch
3729
3709
  // boundaries
3730
- if (isRedirectResponse$1(e)) {
3710
+ if (isRedirectResponse(e)) {
3731
3711
  return e;
3732
3712
  }
3733
3713
  throw e;
@@ -3881,12 +3861,12 @@
3881
3861
  return;
3882
3862
  }
3883
3863
  let result = results[match.route.id];
3884
- if (isRedirectDataStrategyResultResult(result)) {
3864
+ if (isRedirectDataStrategyResult(result)) {
3885
3865
  let response = result.result;
3886
3866
  // Throw redirects and let the server handle them with an HTTP redirect
3887
3867
  throw normalizeRelativeRoutingRedirectResponse(response, request, match.route.id, matches, basename);
3888
3868
  }
3889
- if (isResponse$2(result.result) && isRouteRequest) {
3869
+ if (isResponse(result.result) && isRouteRequest) {
3890
3870
  // For SSR single-route requests, we want to hand Responses back
3891
3871
  // directly without unwrapping
3892
3872
  throw result;
@@ -4597,7 +4577,7 @@
4597
4577
  result,
4598
4578
  type
4599
4579
  } = dataStrategyResult;
4600
- if (isResponse$2(result)) {
4580
+ if (isResponse(result)) {
4601
4581
  let data;
4602
4582
  try {
4603
4583
  let contentType = result.headers.get("Content-Type");
@@ -5009,8 +4989,8 @@
5009
4989
  function isDataStrategyResult(result) {
5010
4990
  return result != null && typeof result === "object" && "type" in result && "result" in result && (result.type === ResultType.data || result.type === ResultType.error);
5011
4991
  }
5012
- function isRedirectDataStrategyResultResult(result) {
5013
- return isResponse$2(result.result) && redirectStatusCodes$1.has(result.result.status);
4992
+ function isRedirectDataStrategyResult(result) {
4993
+ return isResponse(result.result) && redirectStatusCodes.has(result.result.status);
5014
4994
  }
5015
4995
  function isErrorResult(result) {
5016
4996
  return result.type === ResultType.error;
@@ -5021,16 +5001,14 @@
5021
5001
  function isDataWithResponseInit(value) {
5022
5002
  return typeof value === "object" && value != null && "type" in value && "data" in value && "init" in value && value.type === "DataWithResponseInit";
5023
5003
  }
5024
- function isResponse$2(value) {
5004
+ function isResponse(value) {
5025
5005
  return value != null && typeof value.status === "number" && typeof value.statusText === "string" && typeof value.headers === "object" && typeof value.body !== "undefined";
5026
5006
  }
5027
- function isRedirectResponse$1(result) {
5028
- if (!isResponse$2(result)) {
5029
- return false;
5030
- }
5031
- let status = result.status;
5032
- let location = result.headers.get("Location");
5033
- return status >= 300 && status <= 399 && location != null;
5007
+ function isRedirectStatusCode(statusCode) {
5008
+ return redirectStatusCodes.has(statusCode);
5009
+ }
5010
+ function isRedirectResponse(result) {
5011
+ return isResponse(result) && isRedirectStatusCode(result.status) && result.headers.has("Location");
5034
5012
  }
5035
5013
  function isValidMethod(method) {
5036
5014
  return validRequestMethods.has(method.toUpperCase());
@@ -6473,8 +6451,8 @@
6473
6451
  let setState = React__namespace.useCallback((newState, _ref2) => {
6474
6452
  let {
6475
6453
  deletedFetchers,
6476
- flushSync: flushSync,
6477
- viewTransitionOpts: viewTransitionOpts
6454
+ flushSync,
6455
+ viewTransitionOpts
6478
6456
  } = _ref2;
6479
6457
  deletedFetchers.forEach(key => fetcherData.current.delete(key));
6480
6458
  newState.fetchers.forEach((fetcher, key) => {
@@ -7376,7 +7354,56 @@
7376
7354
  * @see https://remix.run/route/meta
7377
7355
  */
7378
7356
 
7379
- // Loose copy from @react-router/server-runtime to avoid circular imports
7357
+ /**
7358
+ * A function that returns an array of data objects to use for rendering
7359
+ * metadata HTML tags in a route. These tags are not rendered on descendant
7360
+ * routes in the route hierarchy. In other words, they will only be rendered on
7361
+ * the route in which they are exported.
7362
+ *
7363
+ * @param Loader - The type of the current route's loader function
7364
+ * @param MatchLoaders - Mapping from a parent route's filepath to its loader
7365
+ * function type
7366
+ *
7367
+ * Note that parent route filepaths are relative to the `app/` directory.
7368
+ *
7369
+ * For example, if this meta function is for `/sales/customers/$customerId`:
7370
+ *
7371
+ * ```ts
7372
+ * // app/root.tsx
7373
+ * const loader = () => ({ hello: "world" })
7374
+ * export type Loader = typeof loader
7375
+ *
7376
+ * // app/routes/sales.tsx
7377
+ * const loader = () => ({ salesCount: 1074 })
7378
+ * export type Loader = typeof loader
7379
+ *
7380
+ * // app/routes/sales/customers.tsx
7381
+ * const loader = () => ({ customerCount: 74 })
7382
+ * export type Loader = typeof loader
7383
+ *
7384
+ * // app/routes/sales/customers/$customersId.tsx
7385
+ * import type { Loader as RootLoader } from "../../../root"
7386
+ * import type { Loader as SalesLoader } from "../../sales"
7387
+ * import type { Loader as CustomersLoader } from "../../sales/customers"
7388
+ *
7389
+ * const loader = () => ({ name: "Customer name" })
7390
+ *
7391
+ * const meta: MetaFunction<typeof loader, {
7392
+ * "root": RootLoader,
7393
+ * "routes/sales": SalesLoader,
7394
+ * "routes/sales/customers": CustomersLoader,
7395
+ * }> = ({ data, matches }) => {
7396
+ * const { name } = data
7397
+ * // ^? string
7398
+ * const { customerCount } = matches.find((match) => match.id === "routes/sales/customers").data
7399
+ * // ^? number
7400
+ * const { salesCount } = matches.find((match) => match.id === "routes/sales").data
7401
+ * // ^? number
7402
+ * const { hello } = matches.find((match) => match.id === "root").data
7403
+ * // ^? "world"
7404
+ * }
7405
+ * ```
7406
+ */
7380
7407
 
7381
7408
  /**
7382
7409
  * A React component that is rendered for a route.
@@ -7433,7 +7460,7 @@
7433
7460
  let descriptors = matches.map(match => {
7434
7461
  let module = routeModules[match.route.id];
7435
7462
  let route = manifest.routes[match.route.id];
7436
- return [route.css ? route.css.map(href => ({
7463
+ return [route && route.css ? route.css.map(href => ({
7437
7464
  rel: "stylesheet",
7438
7465
  href
7439
7466
  })) : [], (module == null || module.links == null ? void 0 : module.links()) || []];
@@ -7512,8 +7539,12 @@
7512
7539
  }
7513
7540
  async function getKeyedPrefetchLinks(matches, manifest, routeModules) {
7514
7541
  let links = await Promise.all(matches.map(async match => {
7515
- let mod = await loadRouteModule(manifest.routes[match.route.id], routeModules);
7516
- return mod.links ? mod.links() : [];
7542
+ let route = manifest.routes[match.route.id];
7543
+ if (route) {
7544
+ let mod = await loadRouteModule(route, routeModules);
7545
+ return mod.links ? mod.links() : [];
7546
+ }
7547
+ return [];
7517
7548
  }));
7518
7549
  return dedupeLinkDescriptors(links.flat(1).filter(isHtmlLinkDescriptor).filter(link => link.rel === "stylesheet" || link.rel === "preload").map(link => link.rel === "stylesheet" ? _extends({}, link, {
7519
7550
  rel: "prefetch",
@@ -7525,7 +7556,6 @@
7525
7556
 
7526
7557
  // This is ridiculously identical to transition.ts `filterMatchesToLoad`
7527
7558
  function getNewMatchesForLinks(page, nextMatches, currentMatches, manifest, location, mode) {
7528
- let path = parsePathPatch(page);
7529
7559
  let isNew = (match, index) => {
7530
7560
  if (!currentMatches[index]) return true;
7531
7561
  return match.route.id !== currentMatches[index].route.id;
@@ -7540,43 +7570,45 @@
7540
7570
  ((_currentMatches$index = currentMatches[index].route.path) == null ? void 0 : _currentMatches$index.endsWith("*")) && currentMatches[index].params["*"] !== match.params["*"]
7541
7571
  );
7542
7572
  };
7573
+ if (mode === "assets") {
7574
+ return nextMatches.filter((match, index) => isNew(match, index) || matchPathChanged(match, index));
7575
+ }
7543
7576
 
7544
- // NOTE: keep this mostly up-to-date w/ the transition data diff, but this
7577
+ // NOTE: keep this mostly up-to-date w/ the router data diff, but this
7545
7578
  // version doesn't care about submissions
7546
- let newMatches = mode === "data" && location.search !== path.search ?
7547
- // this is really similar to stuff in transition.ts, maybe somebody smarter
7579
+ // TODO: this is really similar to stuff in router.ts, maybe somebody smarter
7548
7580
  // than me (or in less of a hurry) can share some of it. You're the best.
7549
- nextMatches.filter((match, index) => {
7550
- let manifestRoute = manifest.routes[match.route.id];
7551
- if (!manifestRoute.hasLoader) {
7552
- return false;
7553
- }
7554
- if (isNew(match, index) || matchPathChanged(match, index)) {
7555
- return true;
7556
- }
7557
- if (match.route.shouldRevalidate) {
7558
- var _currentMatches$;
7559
- let routeChoice = match.route.shouldRevalidate({
7560
- currentUrl: new URL(location.pathname + location.search + location.hash, window.origin),
7561
- currentParams: ((_currentMatches$ = currentMatches[0]) == null ? void 0 : _currentMatches$.params) || {},
7562
- nextUrl: new URL(page, window.origin),
7563
- nextParams: match.params,
7564
- defaultShouldRevalidate: true
7565
- });
7566
- if (typeof routeChoice === "boolean") {
7567
- return routeChoice;
7581
+ if (mode === "data") {
7582
+ return nextMatches.filter((match, index) => {
7583
+ let manifestRoute = manifest.routes[match.route.id];
7584
+ if (!manifestRoute || !manifestRoute.hasLoader) {
7585
+ return false;
7568
7586
  }
7569
- }
7570
- return true;
7571
- }) : nextMatches.filter((match, index) => {
7572
- let manifestRoute = manifest.routes[match.route.id];
7573
- return (mode === "assets" || manifestRoute.hasLoader) && (isNew(match, index) || matchPathChanged(match, index));
7574
- });
7575
- return newMatches;
7587
+ if (isNew(match, index) || matchPathChanged(match, index)) {
7588
+ return true;
7589
+ }
7590
+ if (match.route.shouldRevalidate) {
7591
+ var _currentMatches$;
7592
+ let routeChoice = match.route.shouldRevalidate({
7593
+ currentUrl: new URL(location.pathname + location.search + location.hash, window.origin),
7594
+ currentParams: ((_currentMatches$ = currentMatches[0]) == null ? void 0 : _currentMatches$.params) || {},
7595
+ nextUrl: new URL(page, window.origin),
7596
+ nextParams: match.params,
7597
+ defaultShouldRevalidate: true
7598
+ });
7599
+ if (typeof routeChoice === "boolean") {
7600
+ return routeChoice;
7601
+ }
7602
+ }
7603
+ return true;
7604
+ });
7605
+ }
7606
+ return [];
7576
7607
  }
7577
7608
  function getModuleLinkHrefs(matches, manifestPatch) {
7578
7609
  return dedupeHrefs(matches.map(match => {
7579
7610
  let route = manifestPatch.routes[match.route.id];
7611
+ if (!route) return [];
7580
7612
  let hrefs = [route.module];
7581
7613
  if (route.imports) {
7582
7614
  hrefs = hrefs.concat(route.imports);
@@ -7591,6 +7623,7 @@
7591
7623
  function getCurrentPageModulePreloadHrefs(matches, manifest) {
7592
7624
  return dedupeHrefs(matches.map(match => {
7593
7625
  let route = manifest.routes[match.route.id];
7626
+ if (!route) return [];
7594
7627
  let hrefs = [route.module];
7595
7628
  if (route.imports) {
7596
7629
  hrefs = hrefs.concat(route.imports);
@@ -7629,13 +7662,6 @@
7629
7662
  }, []);
7630
7663
  }
7631
7664
 
7632
- // https://github.com/remix-run/history/issues/897
7633
- function parsePathPatch(href) {
7634
- let path = parsePath(href);
7635
- if (path.search === undefined) path.search = "";
7636
- return path;
7637
- }
7638
-
7639
7665
  // Detect if this browser supports <link rel="preload"> (or has it enabled).
7640
7666
  // Originally added to handle the firefox `network.preload` config:
7641
7667
  // https://bugzilla.mozilla.org/show_bug.cgi?id=1847811
@@ -7673,13 +7699,6 @@
7673
7699
  };
7674
7700
  }
7675
7701
 
7676
- /**
7677
- * Data for a route that was returned from a `loader()`.
7678
- */
7679
-
7680
- function isResponse$1(value) {
7681
- return value != null && typeof value.status === "number" && typeof value.statusText === "string" && typeof value.headers === "object" && typeof value.body !== "undefined";
7682
- }
7683
7702
  async function createRequestInit(request) {
7684
7703
  let init = {
7685
7704
  signal: request.signal
@@ -7818,7 +7837,7 @@
7818
7837
  });
7819
7838
  return result;
7820
7839
  });
7821
- if (isResponse$1(result.result) || isRouteErrorResponse(result.result)) {
7840
+ if (isResponse(result.result) || isRouteErrorResponse(result.result)) {
7822
7841
  return {
7823
7842
  [actionMatch.route.id]: result
7824
7843
  };
@@ -7863,6 +7882,7 @@
7863
7882
  let results = {};
7864
7883
  let resolvePromise = Promise.all(matches.map(async (m, i) => m.resolve(async handler => {
7865
7884
  routeDfds[i].resolve();
7885
+ let manifestRoute = manifest.routes[m.route.id];
7866
7886
  if (!m.shouldLoad) {
7867
7887
  var _routeModules$m$route;
7868
7888
  // If we're not yet initialized and this is the initial load, respect
@@ -7875,7 +7895,7 @@
7875
7895
  // Otherwise, we opt out if we currently have data, a `loader`, and a
7876
7896
  // `shouldRevalidate` function. This implies that the user opted out
7877
7897
  // via `shouldRevalidate`
7878
- if (m.route.id in router.state.loaderData && manifest.routes[m.route.id].hasLoader && (_routeModules$m$route = routeModules[m.route.id]) != null && _routeModules$m$route.shouldRevalidate) {
7898
+ if (m.route.id in router.state.loaderData && manifestRoute && manifestRoute.hasLoader && (_routeModules$m$route = routeModules[m.route.id]) != null && _routeModules$m$route.shouldRevalidate) {
7879
7899
  foundOptOutRoute = true;
7880
7900
  return;
7881
7901
  }
@@ -7883,8 +7903,8 @@
7883
7903
 
7884
7904
  // When a route has a client loader, it opts out of the singular call and
7885
7905
  // calls it's server loader via `serverLoader()` using a `?_routes` param
7886
- if (manifest.routes[m.route.id].hasClientLoader) {
7887
- if (manifest.routes[m.route.id].hasLoader) {
7906
+ if (manifestRoute && manifestRoute.hasClientLoader) {
7907
+ if (manifestRoute.hasLoader) {
7888
7908
  foundOptOutRoute = true;
7889
7909
  }
7890
7910
  try {
@@ -7903,7 +7923,7 @@
7903
7923
  }
7904
7924
 
7905
7925
  // Load this route on the server if it has a loader
7906
- if (manifest.routes[m.route.id].hasLoader) {
7926
+ if (manifestRoute && manifestRoute.hasLoader) {
7907
7927
  routesParams.add(m.route.id);
7908
7928
  }
7909
7929
 
@@ -8295,20 +8315,18 @@
8295
8315
  }));
8296
8316
  }
8297
8317
 
8298
- // NOTE: make sure to change the Route in server-runtime if you change this
8299
-
8300
- // NOTE: make sure to change the EntryRoute in server-runtime if you change this
8301
-
8302
8318
  // Create a map of routes by parentId to use recursively instead of
8303
8319
  // repeatedly filtering the manifest.
8304
8320
  function groupRoutesByParentId$1(manifest) {
8305
8321
  let routes = {};
8306
8322
  Object.values(manifest).forEach(route => {
8307
- let parentId = route.parentId || "";
8308
- if (!routes[parentId]) {
8309
- routes[parentId] = [];
8323
+ if (route) {
8324
+ let parentId = route.parentId || "";
8325
+ if (!routes[parentId]) {
8326
+ routes[parentId] = [];
8327
+ }
8328
+ routes[parentId].push(route);
8310
8329
  }
8311
- routes[parentId].push(route);
8312
8330
  });
8313
8331
  return routes;
8314
8332
  }
@@ -8448,7 +8466,7 @@
8448
8466
  // Use critical path modules directly
8449
8467
  Object.assign(dataRoute, _extends({}, dataRoute, getRouteComponents(route, routeModule, isSpaMode), {
8450
8468
  handle: routeModule.handle,
8451
- shouldRevalidate: needsRevalidation ? wrapShouldRevalidateForHdr(route.id, routeModule.shouldRevalidate, needsRevalidation) : routeModule.shouldRevalidate
8469
+ shouldRevalidate: getShouldRevalidateFunction(routeModule, route.id, needsRevalidation)
8452
8470
  }));
8453
8471
  let hasInitialData = initialState && initialState.loaderData && route.id in initialState.loaderData;
8454
8472
  let initialData = hasInitialData ? initialState == null || (_initialState$loaderD = initialState.loaderData) == null ? void 0 : _initialState$loaderD[route.id] : undefined;
@@ -8567,16 +8585,13 @@
8567
8585
  }
8568
8586
  }));
8569
8587
  }
8570
- if (needsRevalidation) {
8571
- lazyRoute.shouldRevalidate = wrapShouldRevalidateForHdr(route.id, mod.shouldRevalidate, needsRevalidation);
8572
- }
8573
8588
  return _extends({}, lazyRoute.loader ? {
8574
8589
  loader: lazyRoute.loader
8575
8590
  } : {}, lazyRoute.action ? {
8576
8591
  action: lazyRoute.action
8577
8592
  } : {}, {
8578
8593
  hasErrorBoundary: lazyRoute.hasErrorBoundary,
8579
- shouldRevalidate: lazyRoute.shouldRevalidate,
8594
+ shouldRevalidate: getShouldRevalidateFunction(lazyRoute, route.id, needsRevalidation),
8580
8595
  handle: lazyRoute.handle,
8581
8596
  // No need to wrap these in layout since the root route is never
8582
8597
  // loaded via route.lazy()
@@ -8590,6 +8605,22 @@
8590
8605
  return dataRoute;
8591
8606
  });
8592
8607
  }
8608
+ function getShouldRevalidateFunction(route, routeId, needsRevalidation) {
8609
+ // During HDR we force revalidation for updated routes
8610
+ if (needsRevalidation) {
8611
+ return wrapShouldRevalidateForHdr(routeId, route.shouldRevalidate, needsRevalidation);
8612
+ }
8613
+
8614
+ // Single fetch revalidates by default, so override the RR default value which
8615
+ // matches the multi-fetch behavior with `true`
8616
+ if (route.shouldRevalidate) {
8617
+ let fn = route.shouldRevalidate;
8618
+ return opts => fn(_extends({}, opts, {
8619
+ defaultShouldRevalidate: true
8620
+ }));
8621
+ }
8622
+ return route.shouldRevalidate;
8623
+ }
8593
8624
 
8594
8625
  // When an HMR / HDR update happens we opt out of all user-defined
8595
8626
  // revalidation logic and force a revalidation on the first call
@@ -8791,9 +8822,12 @@
8791
8822
 
8792
8823
  // Patch routes we don't know about yet into the manifest
8793
8824
  let knownRoutes = new Set(Object.keys(manifest.routes));
8794
- let patches = Object.values(serverPatches).reduce((acc, route) => !knownRoutes.has(route.id) ? Object.assign(acc, {
8795
- [route.id]: route
8796
- }) : acc, {});
8825
+ let patches = Object.values(serverPatches).reduce((acc, route) => {
8826
+ if (route && !knownRoutes.has(route.id)) {
8827
+ acc[route.id] = route;
8828
+ }
8829
+ return acc;
8830
+ }, {});
8797
8831
  Object.assign(manifest.routes, patches);
8798
8832
 
8799
8833
  // Track discovered paths so we don't have to fetch them again
@@ -8803,7 +8837,7 @@
8803
8837
  // in their new children
8804
8838
  let parentIds = new Set();
8805
8839
  Object.values(patches).forEach(patch => {
8806
- if (!patch.parentId || !patches[patch.parentId]) {
8840
+ if (patch && (!patch.parentId || !patches[patch.parentId])) {
8807
8841
  parentIds.add(patch.parentId);
8808
8842
  }
8809
8843
  });
@@ -8833,9 +8867,6 @@
8833
8867
  const _excluded$2 = ["page"],
8834
8868
  _excluded2$1 = ["page", "matches"],
8835
8869
  _excluded3$1 = ["tagName"];
8836
-
8837
- // TODO: Temporary shim until we figure out the way to handle typings in v7
8838
-
8839
8870
  function useDataRouterContext$1() {
8840
8871
  let context = React__namespace.useContext(DataRouterContext);
8841
8872
  !context ? invariant$1(false, "You must render this element inside a <DataRouterContext.Provider> element") : void 0;
@@ -9098,12 +9129,13 @@
9098
9129
  let foundOptOutRoute = false;
9099
9130
  nextMatches.forEach(m => {
9100
9131
  var _routeModules$m$route;
9101
- if (!manifest.routes[m.route.id].hasLoader) {
9132
+ let manifestRoute = manifest.routes[m.route.id];
9133
+ if (!manifestRoute || !manifestRoute.hasLoader) {
9102
9134
  return;
9103
9135
  }
9104
9136
  if (!newMatchesForData.some(m2 => m2.route.id === m.route.id) && m.route.id in loaderData && (_routeModules$m$route = routeModules[m.route.id]) != null && _routeModules$m$route.shouldRevalidate) {
9105
9137
  foundOptOutRoute = true;
9106
- } else if (manifest.routes[m.route.id].hasClientLoader) {
9138
+ } else if (manifestRoute.hasClientLoader) {
9107
9139
  foundOptOutRoute = true;
9108
9140
  } else {
9109
9141
  routesParams.add(m.route.id);
@@ -9374,7 +9406,7 @@
9374
9406
  }, []);
9375
9407
  let routePreloads = matches.map(match => {
9376
9408
  let route = manifest.routes[match.route.id];
9377
- return (route.imports || []).concat([route.module]);
9409
+ return route ? (route.imports || []).concat([route.module]) : [];
9378
9410
  }).flat(1);
9379
9411
  let preloads = isHydrated ? [] : manifest.entry.imports.concat(routePreloads);
9380
9412
  return isHydrated ? null : /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, !enableFogOfWar ? /*#__PURE__*/React__namespace.createElement("link", {
@@ -9414,7 +9446,6 @@
9414
9446
  _excluded2 = ["aria-current", "caseSensitive", "className", "end", "style", "to", "viewTransition", "children"],
9415
9447
  _excluded3 = ["discover", "fetcherKey", "navigate", "reloadDocument", "replace", "state", "method", "action", "onSubmit", "relative", "preventScrollReset", "viewTransition"],
9416
9448
  _excluded4 = ["getKey", "storageKey"];
9417
-
9418
9449
  ////////////////////////////////////////////////////////////////////////////////
9419
9450
  //#region Global Stuff
9420
9451
  ////////////////////////////////////////////////////////////////////////////////
@@ -11092,7 +11123,7 @@
11092
11123
  // route opted into clientLoader hydration and either:
11093
11124
  // * gave us a HydrateFallback
11094
11125
  // * or doesn't have a server loader and we have no data to render
11095
- if (route && shouldHydrateRouteLoader(manifestRoute, route, context.isSpaMode) && (route.HydrateFallback || !manifestRoute.hasLoader)) {
11126
+ if (route && manifestRoute && shouldHydrateRouteLoader(manifestRoute, route, context.isSpaMode) && (route.HydrateFallback || !manifestRoute.hasLoader)) {
11096
11127
  delete context.staticHandlerContext.loaderData[routeId];
11097
11128
  }
11098
11129
  }
@@ -11309,7 +11340,17 @@
11309
11340
  async parse(cookieHeader, parseOptions) {
11310
11341
  if (!cookieHeader) return null;
11311
11342
  let cookies = cookie.parse(cookieHeader, _extends({}, options, parseOptions));
11312
- return name in cookies ? cookies[name] === "" ? "" : await decodeCookieValue(cookies[name], secrets) : null;
11343
+ if (name in cookies) {
11344
+ let value = cookies[name];
11345
+ if (typeof value === "string" && value !== "") {
11346
+ let decoded = await decodeCookieValue(value, secrets);
11347
+ return decoded;
11348
+ } else {
11349
+ return "";
11350
+ }
11351
+ } else {
11352
+ return null;
11353
+ }
11313
11354
  },
11314
11355
  async serialize(value, serializeOptions) {
11315
11356
  return cookie.serialize(name, value === "" ? "" : await encodeCookieValue(value, secrets), _extends({}, options, serializeOptions));
@@ -11416,7 +11457,10 @@
11416
11457
 
11417
11458
  function createEntryRouteModules(manifest) {
11418
11459
  return Object.keys(manifest).reduce((memo, routeId) => {
11419
- memo[routeId] = manifest[routeId].module;
11460
+ let route = manifest[routeId];
11461
+ if (route) {
11462
+ memo[routeId] = route.module;
11463
+ }
11420
11464
  return memo;
11421
11465
  }, {});
11422
11466
  }
@@ -11540,32 +11584,6 @@
11540
11584
  }));
11541
11585
  }
11542
11586
 
11543
- // must be a type since this is a subtype of response
11544
- // interfaces must conform to the types they extend
11545
-
11546
- /**
11547
- * This is a shortcut for creating `application/json` responses. Converts `data`
11548
- * to JSON and sets the `Content-Type` header.
11549
- *
11550
- * @see https://remix.run/utils/json
11551
- */
11552
- const json = function json(data, init) {
11553
- if (init === void 0) {
11554
- init = {};
11555
- }
11556
- return json$1(data, init);
11557
- };
11558
- function isResponse(value) {
11559
- return value != null && typeof value.status === "number" && typeof value.statusText === "string" && typeof value.headers === "object" && typeof value.body !== "undefined";
11560
- }
11561
- const redirectStatusCodes = new Set([301, 302, 303, 307, 308]);
11562
- function isRedirectStatusCode(statusCode) {
11563
- return redirectStatusCodes.has(statusCode);
11564
- }
11565
- function isRedirectResponse(response) {
11566
- return isRedirectStatusCode(response.status);
11567
- }
11568
-
11569
11587
  /**
11570
11588
  * An object of unknown type for route loaders and actions provided by the
11571
11589
  * server's `getLoadContext()` function. This is defined as an empty interface
@@ -11573,10 +11591,6 @@
11573
11591
  * globally: https://www.typescriptlang.org/docs/handbook/declaration-merging.html
11574
11592
  */
11575
11593
 
11576
- /**
11577
- * Data for a route that was returned from a `loader()`.
11578
- */
11579
-
11580
11594
  // Need to use RR's version here to permit the optional context even
11581
11595
  // though we know it'll always be provided in remix
11582
11596
  async function callRouteHandler(handler, args) {
@@ -11639,23 +11653,21 @@
11639
11653
 
11640
11654
  function invariant(value, message) {
11641
11655
  if (value === false || value === null || typeof value === "undefined") {
11642
- console.error("The following error is a bug in Remix; please open an issue! https://github.com/remix-run/remix/issues/new");
11656
+ console.error("The following error is a bug in React Router; please open an issue! https://github.com/remix-run/react-router/issues/new/choose");
11643
11657
  throw new Error(message);
11644
11658
  }
11645
11659
  }
11646
11660
 
11647
- // NOTE: make sure to change the Route in remix-react/react-router-dev if you change this
11648
-
11649
- // NOTE: make sure to change the EntryRoute in react-router/react-router-dev if you change this
11650
-
11651
11661
  function groupRoutesByParentId(manifest) {
11652
11662
  let routes = {};
11653
11663
  Object.values(manifest).forEach(route => {
11654
- let parentId = route.parentId || "";
11655
- if (!routes[parentId]) {
11656
- routes[parentId] = [];
11664
+ if (route) {
11665
+ let parentId = route.parentId || "";
11666
+ if (!routes[parentId]) {
11667
+ routes[parentId] = [];
11668
+ }
11669
+ routes[parentId].push(route);
11657
11670
  }
11658
- routes[parentId].push(route);
11659
11671
  });
11660
11672
  return routes;
11661
11673
  }
@@ -11788,13 +11800,15 @@
11788
11800
  let {
11789
11801
  id
11790
11802
  } = match.route;
11791
- let routeModule = build.routes[id].module;
11803
+ let route = build.routes[id];
11804
+ !route ? invariant(false, "Route with id \"" + id + "\" not found in build") : void 0;
11805
+ let routeModule = route.module;
11792
11806
  let loaderHeaders = context.loaderHeaders[id] || new Headers();
11793
11807
  let actionHeaders = context.actionHeaders[id] || new Headers();
11794
11808
 
11795
11809
  // Only expose errorHeaders to the leaf headers() function to
11796
11810
  // avoid duplication via parentHeaders
11797
- let includeErrorHeaders = errorHeaders != undefined && idx === matches.length - 1;
11811
+ let includeErrorHeaders = errorHeaders != null && idx === matches.length - 1;
11798
11812
  // Only prepend cookies from errorHeaders at the leaf renderable route
11799
11813
  // when it's not the same as loaderHeaders/actionHeaders to avoid
11800
11814
  // duplicate cookies
@@ -12226,15 +12240,18 @@
12226
12240
  if (matches) {
12227
12241
  for (let match of matches) {
12228
12242
  let routeId = match.route.id;
12229
- patches[routeId] = build.assets.routes[routeId];
12243
+ let route = build.assets.routes[routeId];
12244
+ if (route) {
12245
+ patches[routeId] = route;
12246
+ }
12230
12247
  }
12231
12248
  }
12232
12249
  }
12233
- return json(patches, {
12250
+ return Response.json(patches, {
12234
12251
  headers: {
12235
12252
  "Cache-Control": "public, max-age=31536000, immutable"
12236
12253
  }
12237
- }); // Override the TypedResponse stuff from json()
12254
+ });
12238
12255
  }
12239
12256
  return new Response("Invalid Request", {
12240
12257
  status: 400
@@ -12413,7 +12430,7 @@
12413
12430
  }
12414
12431
  }
12415
12432
  function errorResponseToJson(errorResponse, serverMode) {
12416
- return json$1(serializeError(
12433
+ return Response.json(serializeError(
12417
12434
  // @ts-expect-error This is "private" from users but intended for internal use
12418
12435
  errorResponse.error || new Error("Unexpected Server Error"), serverMode), {
12419
12436
  status: errorResponse.status,
@@ -12770,7 +12787,6 @@
12770
12787
  exports.isCookie = isCookie;
12771
12788
  exports.isRouteErrorResponse = isRouteErrorResponse;
12772
12789
  exports.isSession = isSession;
12773
- exports.json = json$1;
12774
12790
  exports.matchPath = matchPath;
12775
12791
  exports.matchRoutes = matchRoutes;
12776
12792
  exports.parsePath = parsePath;