@remix-run/router 1.0.1 → 1.0.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # `@remix-run/router`
2
2
 
3
+ ## 1.0.2
4
+
5
+ ### Patch Changes
6
+
7
+ - Reset `actionData` after a successful action redirect ([#9334](https://github.com/remix-run/react-router/pull/9334))
8
+ - Update `matchPath` to avoid false positives on dash-separated segments ([#9300](https://github.com/remix-run/react-router/pull/9300))
9
+ - If an index route has children, it will result in a runtime error. We have strengthened our `RouteObject`/`RouteProps` types to surface the error in TypeScript. ([#9366](https://github.com/remix-run/react-router/pull/9366))
10
+
3
11
  ## 1.0.1
4
12
 
5
13
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { convertRoutesToDataRoutes } from "./utils";
2
- export type { ActionFunction, ActionFunctionArgs, AgnosticDataRouteMatch, AgnosticDataRouteObject, AgnosticRouteMatch, AgnosticRouteObject, TrackedPromise, FormEncType, FormMethod, JsonFunction, LoaderFunction, LoaderFunctionArgs, ParamParseKey, Params, PathMatch, PathPattern, RedirectFunction, ShouldRevalidateFunction, Submission, } from "./utils";
2
+ export type { ActionFunction, ActionFunctionArgs, AgnosticDataIndexRouteObject, AgnosticDataNonIndexRouteObject, AgnosticDataRouteMatch, AgnosticDataRouteObject, AgnosticIndexRouteObject, AgnosticNonIndexRouteObject, AgnosticRouteMatch, AgnosticRouteObject, TrackedPromise, FormEncType, FormMethod, JsonFunction, LoaderFunction, LoaderFunctionArgs, ParamParseKey, Params, PathMatch, PathPattern, RedirectFunction, ShouldRevalidateFunction, Submission, } from "./utils";
3
3
  export { AbortedDeferredError, ErrorResponse, defer, generatePath, getToPathname, invariant, isRouteErrorResponse, joinPaths, json, matchPath, matchRoutes, normalizePathname, redirect, resolvePath, resolveTo, stripBasename, warning, } from "./utils";
4
4
  export type { BrowserHistory, BrowserHistoryOptions, HashHistory, HashHistoryOptions, History, InitialEntry, Location, MemoryHistory, MemoryHistoryOptions, Path, To, } from "./history";
5
5
  export { Action, createBrowserHistory, createPath, createHashHistory, createMemoryHistory, parsePath, } from "./history";
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @remix-run/router v1.0.1
2
+ * @remix-run/router v1.0.2
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -487,8 +487,12 @@ let ResultType;
487
487
  ResultType["error"] = "error";
488
488
  })(ResultType || (ResultType = {}));
489
489
 
490
- // Walk the route tree generating unique IDs where necessary so we are working
490
+ function isIndexRoute(route) {
491
+ return route.index === true;
492
+ } // Walk the route tree generating unique IDs where necessary so we are working
491
493
  // solely with AgnosticDataRouteObject's within the Router
494
+
495
+
492
496
  function convertRoutesToDataRoutes(routes, parentPath, allIds) {
493
497
  if (parentPath === void 0) {
494
498
  parentPath = [];
@@ -501,15 +505,24 @@ function convertRoutesToDataRoutes(routes, parentPath, allIds) {
501
505
  return routes.map((route, index) => {
502
506
  let treePath = [...parentPath, index];
503
507
  let id = typeof route.id === "string" ? route.id : treePath.join("-");
508
+ invariant(route.index !== true || !route.children, "Cannot specify children on an index route");
504
509
  invariant(!allIds.has(id), "Found a route id collision on id \"" + id + "\". Route " + "id's must be globally unique within Data Router usages");
505
510
  allIds.add(id);
506
511
 
507
- let dataRoute = _extends({}, route, {
508
- id,
509
- children: route.children ? convertRoutesToDataRoutes(route.children, treePath, allIds) : undefined
510
- });
512
+ if (isIndexRoute(route)) {
513
+ let indexRoute = _extends({}, route, {
514
+ id
515
+ });
516
+
517
+ return indexRoute;
518
+ } else {
519
+ let pathOrLayoutRoute = _extends({}, route, {
520
+ id,
521
+ children: route.children ? convertRoutesToDataRoutes(route.children, treePath, allIds) : undefined
522
+ });
511
523
 
512
- return dataRoute;
524
+ return pathOrLayoutRoute;
525
+ }
513
526
  });
514
527
  }
515
528
  /**
@@ -573,7 +586,9 @@ function flattenRoutes(routes, branches, parentsMeta, parentPath) {
573
586
  // the "flattened" version.
574
587
 
575
588
  if (route.children && route.children.length > 0) {
576
- invariant(route.index !== true, "Index routes must not have child routes. Please remove " + ("all child routes from route path \"" + path + "\"."));
589
+ invariant( // Our types know better, but runtime JS may not!
590
+ // @ts-expect-error
591
+ route.index !== true, "Index routes must not have child routes. Please remove " + ("all child routes from route path \"" + path + "\"."));
577
592
  flattenRoutes(route.children, branches, routesMeta, path);
578
593
  } // Routes without a path shouldn't ever match by themselves unless they are
579
594
  // index routes, so don't add them to the list of possible branches.
@@ -762,16 +777,19 @@ function compilePath(path, caseSensitive, end) {
762
777
  paramNames.push("*");
763
778
  regexpSource += path === "*" || path === "/*" ? "(.*)$" // Already matched the initial /, just match the rest
764
779
  : "(?:\\/(.+)|\\/*)$"; // Don't include the / in params["*"]
765
- } else {
766
- regexpSource += end ? "\\/*$" // When matching to the end, ignore trailing slashes
767
- : // Otherwise, match a word boundary or a proceeding /. The word boundary restricts
768
- // parent routes to matching only their own words and nothing more, e.g. parent
769
- // route "/home" should not match "/home2".
770
- // Additionally, allow paths starting with `.`, `-`, `~`, and url-encoded entities,
771
- // but do not consume the character in the matched path so they can match against
772
- // nested paths.
773
- "(?:(?=[@.~-]|%[0-9A-F]{2})|\\b|\\/|$)";
774
- }
780
+ } else if (end) {
781
+ // When matching to the end, ignore trailing slashes
782
+ regexpSource += "\\/*$";
783
+ } else if (path !== "" && path !== "/") {
784
+ // If our path is non-empty and contains anything beyond an initial slash,
785
+ // then we have _some_ form of path in our regex so we should expect to
786
+ // match only if we find the end of this path segment. Look for an optional
787
+ // non-captured trailing slash (to match a portion of the URL) or the end
788
+ // of the path (if we've matched to the end). We used to do this with a
789
+ // word boundary but that gives false positives on routes like
790
+ // /user-preferences since `-` counts as a word boundary.
791
+ regexpSource += "(?:(?=\\/|$))";
792
+ } else ;
775
793
 
776
794
  let matcher = new RegExp(regexpSource, caseSensitive ? undefined : "i");
777
795
  return [matcher, paramNames];
@@ -874,6 +892,10 @@ function resolvePathname(relativePath, fromPathname) {
874
892
  });
875
893
  return segments.length > 1 ? segments.join("/") : "/";
876
894
  }
895
+
896
+ function getInvalidPathError(char, field, dest, path) {
897
+ return "Cannot include a '" + char + "' character in a manually specified " + ("`to." + field + "` field [" + JSON.stringify(path) + "]. Please separate it out to the ") + ("`to." + dest + "` field. Alternatively you may provide the full path as ") + "a string in <Link to=\"...\"> and the router will parse it for you.";
898
+ }
877
899
  /**
878
900
  * @private
879
901
  */
@@ -884,7 +906,17 @@ function resolveTo(toArg, routePathnames, locationPathname, isPathRelative) {
884
906
  isPathRelative = false;
885
907
  }
886
908
 
887
- let to = typeof toArg === "string" ? parsePath(toArg) : _extends({}, toArg);
909
+ let to;
910
+
911
+ if (typeof toArg === "string") {
912
+ to = parsePath(toArg);
913
+ } else {
914
+ to = _extends({}, toArg);
915
+ invariant(!to.pathname || !to.pathname.includes("?"), getInvalidPathError("?", "pathname", "search", to));
916
+ invariant(!to.pathname || !to.pathname.includes("#"), getInvalidPathError("#", "pathname", "hash", to));
917
+ invariant(!to.search || !to.search.includes("#"), getInvalidPathError("#", "search", "hash", to));
918
+ }
919
+
888
920
  let isEmptyPath = toArg === "" || to.pathname === "";
889
921
  let toPathname = isEmptyPath ? "/" : to.pathname;
890
922
  let from; // Routing is relative to the current pathname if explicitly requested.
@@ -1347,15 +1379,17 @@ function createRouter(init) {
1347
1379
 
1348
1380
 
1349
1381
  function completeNavigation(location, newState) {
1382
+ var _state$navigation$for;
1383
+
1350
1384
  // Deduce if we're in a loading/actionReload state:
1351
1385
  // - We have committed actionData in the store
1352
1386
  // - The current navigation was a submission
1353
1387
  // - We're past the submitting state and into the loading state
1354
- // - This should not be susceptible to false positives for
1355
- // loading/submissionRedirect since there would not be actionData in the
1356
- // state since the prior action would have returned a redirect response
1357
- // and short circuited
1358
- let isActionReload = state.actionData != null && state.navigation.formMethod != null && state.navigation.state === "loading"; // Always preserve any existing loaderData from re-used routes
1388
+ // - The location we've finished loading is different from the submission
1389
+ // location, indicating we redirected from the action (avoids false
1390
+ // positives for loading/submissionRedirect when actionData returned
1391
+ // on a prior submission)
1392
+ let isActionReload = state.actionData != null && state.navigation.formMethod != null && state.navigation.state === "loading" && ((_state$navigation$for = state.navigation.formAction) == null ? void 0 : _state$navigation$for.split("?")[0]) === location.pathname; // Always preserve any existing loaderData from re-used routes
1359
1393
 
1360
1394
  let newLoaderData = newState.loaderData ? {
1361
1395
  loaderData: mergeLoaderData(state.loaderData, newState.loaderData, newState.matches || [])
@@ -2314,10 +2348,31 @@ function unstable_createStaticHandler(routes) {
2314
2348
 
2315
2349
  if (result instanceof Response) {
2316
2350
  return result;
2351
+ }
2352
+
2353
+ let error = result.errors ? Object.values(result.errors)[0] : undefined;
2354
+
2355
+ if (error !== undefined) {
2356
+ // While we always re-throw Responses returned from loaders/actions
2357
+ // directly for route requests and prevent the unwrapping into an
2358
+ // ErrorResponse, we still need this for error cases _prior_ the
2359
+ // execution of the loader/action, such as a 404/405 error.
2360
+ if (isRouteErrorResponse(error)) {
2361
+ return new Response(error.data, {
2362
+ status: error.status,
2363
+ statusText: error.statusText
2364
+ });
2365
+ } // If we got back result.errors, that means the loader/action threw
2366
+ // _something_ that wasn't a Response, but it's not guaranteed/required
2367
+ // to be an `instanceof Error` either, so we have to use throw here to
2368
+ // preserve the "error" state outside of queryImpl.
2369
+
2370
+
2371
+ throw error;
2317
2372
  } // Pick off the right state value to return
2318
2373
 
2319
2374
 
2320
- let routeData = [result.errors, result.actionData, result.loaderData].find(v => v);
2375
+ let routeData = [result.actionData, result.loaderData].find(v => v);
2321
2376
  let value = Object.values(routeData || {})[0];
2322
2377
 
2323
2378
  if (isRouteErrorResponse(value)) {
@@ -2923,7 +2978,7 @@ function processRouteLoaderData(matches, matchesToLoad, results, pendingError, a
2923
2978
  loaderData[id] = result.data; // Error status codes always override success status codes, but if all
2924
2979
  // loaders are successful we take the deepest status code.
2925
2980
 
2926
- if (result.statusCode !== 200 && !foundError) {
2981
+ if (result.statusCode != null && result.statusCode !== 200 && !foundError) {
2927
2982
  statusCode = result.statusCode;
2928
2983
  }
2929
2984