@remix-run/router 1.3.2 → 1.3.3-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
@@ -147,6 +147,14 @@ export interface Router {
147
147
  * @param key The identifier for the blocker
148
148
  */
149
149
  deleteBlocker(key: string): void;
150
+ /**
151
+ * @internal
152
+ * PRIVATE - DO NOT USE
153
+ *
154
+ * HMR needs to pass in-flight route updates to React Router
155
+ * TODO: Replace this with granular route update APIs (addRoute, updateRoute, deleteRoute)
156
+ */
157
+ _internalSetRoutes(routes: AgnosticRouteObject[]): void;
150
158
  /**
151
159
  * @internal
152
160
  * PRIVATE - DO NOT USE
package/dist/router.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @remix-run/router v1.3.2
2
+ * @remix-run/router v1.3.3-pre.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1441,7 +1441,8 @@ const isServer = !isBrowser; //#endregion
1441
1441
 
1442
1442
  function createRouter(init) {
1443
1443
  invariant(init.routes.length > 0, "You must provide a non-empty routes array to createRouter");
1444
- let dataRoutes = convertRoutesToDataRoutes(init.routes); // Cleanup function for history
1444
+ let dataRoutes = convertRoutesToDataRoutes(init.routes);
1445
+ let inFlightDataRoutes; // Cleanup function for history
1445
1446
 
1446
1447
  let unlistenHistory = null; // Externally-provided functions to call on all state changes
1447
1448
 
@@ -1677,6 +1678,12 @@ function createRouter(init) {
1677
1678
 
1678
1679
 
1679
1680
  let preventScrollReset = pendingPreventScrollReset === true || state.navigation.formMethod != null && isMutationMethod(state.navigation.formMethod) && ((_location$state2 = location.state) == null ? void 0 : _location$state2._isRedirect) !== true;
1681
+
1682
+ if (inFlightDataRoutes) {
1683
+ dataRoutes = inFlightDataRoutes;
1684
+ inFlightDataRoutes = undefined;
1685
+ }
1686
+
1680
1687
  updateState(_extends({}, newState, {
1681
1688
  actionData,
1682
1689
  loaderData,
@@ -1831,8 +1838,9 @@ function createRouter(init) {
1831
1838
 
1832
1839
  saveScrollPosition(state.location, state.matches);
1833
1840
  pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;
1841
+ let routesToUse = inFlightDataRoutes || dataRoutes;
1834
1842
  let loadingNavigation = opts && opts.overrideNavigation;
1835
- let matches = matchRoutes(dataRoutes, location, init.basename); // Short circuit with a 404 on the root error boundary if we match nothing
1843
+ let matches = matchRoutes(routesToUse, location, init.basename); // Short circuit with a 404 on the root error boundary if we match nothing
1836
1844
 
1837
1845
  if (!matches) {
1838
1846
  let error = getInternalRouterError(404, {
@@ -1841,7 +1849,7 @@ function createRouter(init) {
1841
1849
  let {
1842
1850
  matches: notFoundMatches,
1843
1851
  route
1844
- } = getShortCircuitMatches(dataRoutes); // Cancel all pending deferred on 404s since we don't keep any routes
1852
+ } = getShortCircuitMatches(routesToUse); // Cancel all pending deferred on 404s since we don't keep any routes
1845
1853
 
1846
1854
  cancelActiveDeferreds();
1847
1855
  completeNavigation(location, {
@@ -2046,7 +2054,8 @@ function createRouter(init) {
2046
2054
  formData: loadingNavigation.formData,
2047
2055
  formEncType: loadingNavigation.formEncType
2048
2056
  } : undefined;
2049
- let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, activeSubmission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, pendingActionData, pendingError, fetchLoadMatches); // Cancel pending deferreds for no-longer-matched routes or routes we're
2057
+ let routesToUse = inFlightDataRoutes || dataRoutes;
2058
+ let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, activeSubmission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, fetchLoadMatches, routesToUse, init.basename, pendingActionData, pendingError); // Cancel pending deferreds for no-longer-matched routes or routes we're
2050
2059
  // about to reload. Note that if this is an action reload we would have
2051
2060
  // already cancelled all pending deferreds so this would be a no-op
2052
2061
 
@@ -2163,7 +2172,8 @@ function createRouter(init) {
2163
2172
  }
2164
2173
 
2165
2174
  if (fetchControllers.has(key)) abortFetcher(key);
2166
- let matches = matchRoutes(dataRoutes, href, init.basename);
2175
+ let routesToUse = inFlightDataRoutes || dataRoutes;
2176
+ let matches = matchRoutes(routesToUse, href, init.basename);
2167
2177
 
2168
2178
  if (!matches) {
2169
2179
  setFetcherError(key, routeId, getInternalRouterError(404, {
@@ -2188,9 +2198,7 @@ function createRouter(init) {
2188
2198
 
2189
2199
  fetchLoadMatches.set(key, {
2190
2200
  routeId,
2191
- path,
2192
- match,
2193
- matches
2201
+ path
2194
2202
  });
2195
2203
  handleFetcherLoader(key, routeId, path, match, matches, submission);
2196
2204
  } // Call the action for the matched fetcher.submit(), and then handle redirects,
@@ -2277,7 +2285,8 @@ function createRouter(init) {
2277
2285
 
2278
2286
  let nextLocation = state.navigation.location || state.location;
2279
2287
  let revalidationRequest = createClientSideRequest(init.history, nextLocation, abortController.signal);
2280
- let matches = state.navigation.state !== "idle" ? matchRoutes(dataRoutes, state.navigation.location, init.basename) : state.matches;
2288
+ let routesToUse = inFlightDataRoutes || dataRoutes;
2289
+ let matches = state.navigation.state !== "idle" ? matchRoutes(routesToUse, state.navigation.location, init.basename) : state.matches;
2281
2290
  invariant(matches, "Didn't find any matches after fetcher action");
2282
2291
  let loadId = ++incrementingLoadId;
2283
2292
  fetchReloadIds.set(key, loadId);
@@ -2290,10 +2299,10 @@ function createRouter(init) {
2290
2299
  });
2291
2300
 
2292
2301
  state.fetchers.set(key, loadFetcher);
2293
- let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, submission, nextLocation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, {
2302
+ let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, submission, nextLocation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, fetchLoadMatches, routesToUse, init.basename, {
2294
2303
  [match.route.id]: actionResult.data
2295
- }, undefined, // No need to send through errors since we short circuit above
2296
- fetchLoadMatches); // Put all revalidating fetchers into the loading state, except for the
2304
+ }, undefined // No need to send through errors since we short circuit above
2305
+ ); // Put all revalidating fetchers into the loading state, except for the
2297
2306
  // current fetcher which we want to keep in it's current loading state which
2298
2307
  // contains it's action submission info + action data
2299
2308
 
@@ -2567,7 +2576,19 @@ function createRouter(init) {
2567
2576
  // Call all navigation loaders and revalidating fetcher loaders in parallel,
2568
2577
  // then slice off the results into separate arrays so we can handle them
2569
2578
  // accordingly
2570
- let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, router.basename)), ...fetchersToLoad.map(f => callLoaderOrAction("loader", createClientSideRequest(init.history, f.path, request.signal), f.match, f.matches, router.basename))]);
2579
+ let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, router.basename)), ...fetchersToLoad.map(f => {
2580
+ if (f.matches && f.match) {
2581
+ return callLoaderOrAction("loader", createClientSideRequest(init.history, f.path, request.signal), f.match, f.matches, router.basename);
2582
+ } else {
2583
+ let error = {
2584
+ type: ResultType.error,
2585
+ error: getInternalRouterError(404, {
2586
+ pathname: f.path
2587
+ })
2588
+ };
2589
+ return error;
2590
+ }
2591
+ })]);
2571
2592
  let loaderResults = results.slice(0, matchesToLoad.length);
2572
2593
  let fetcherResults = results.slice(matchesToLoad.length);
2573
2594
  await Promise.all([resolveDeferredResults(currentMatches, matchesToLoad, loaderResults, request.signal, false, state.loaderData), resolveDeferredResults(currentMatches, fetchersToLoad.map(f => f.match), fetcherResults, request.signal, true)]);
@@ -2802,6 +2823,10 @@ function createRouter(init) {
2802
2823
  return null;
2803
2824
  }
2804
2825
 
2826
+ function _internalSetRoutes(newRoutes) {
2827
+ inFlightDataRoutes = newRoutes;
2828
+ }
2829
+
2805
2830
  router = {
2806
2831
  get basename() {
2807
2832
  return init.basename;
@@ -2831,7 +2856,10 @@ function createRouter(init) {
2831
2856
  getBlocker,
2832
2857
  deleteBlocker,
2833
2858
  _internalFetchControllers: fetchControllers,
2834
- _internalActiveDeferreds: activeDeferreds
2859
+ _internalActiveDeferreds: activeDeferreds,
2860
+ // TODO: Remove setRoutes, it's temporary to avoid dealing with
2861
+ // updating the tree while validating the update algorithm.
2862
+ _internalSetRoutes
2835
2863
  };
2836
2864
  return router;
2837
2865
  } //#endregion
@@ -3332,7 +3360,7 @@ function getLoaderMatchesUntilBoundary(matches, boundaryId) {
3332
3360
  return boundaryMatches;
3333
3361
  }
3334
3362
 
3335
- function getMatchesToLoad(history, state, matches, submission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, pendingActionData, pendingError, fetchLoadMatches) {
3363
+ function getMatchesToLoad(history, state, matches, submission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, fetchLoadMatches, routesToUse, basename, pendingActionData, pendingError) {
3336
3364
  let actionResult = pendingError ? Object.values(pendingError)[0] : pendingActionData ? Object.values(pendingActionData)[0] : undefined;
3337
3365
  let currentUrl = history.createURL(state.location);
3338
3366
  let nextUrl = history.createURL(location);
@@ -3371,36 +3399,56 @@ function getMatchesToLoad(history, state, matches, submission, location, isReval
3371
3399
  }); // Pick fetcher.loads that need to be revalidated
3372
3400
 
3373
3401
  let revalidatingFetchers = [];
3374
- fetchLoadMatches && fetchLoadMatches.forEach((f, key) => {
3402
+ fetchLoadMatches.forEach((f, key) => {
3403
+ // Don't revalidate if fetcher won't be present in the subsequent render
3375
3404
  if (!matches.some(m => m.route.id === f.routeId)) {
3376
- // This fetcher is not going to be present in the subsequent render so
3377
- // there's no need to revalidate it
3378
3405
  return;
3379
- } else if (cancelledFetcherLoads.includes(key)) {
3380
- // This fetcher was cancelled from a prior action submission - force reload
3406
+ }
3407
+
3408
+ let fetcherMatches = matchRoutes(routesToUse, f.path, basename); // If the fetcher path no longer matches, push it in with null matches so
3409
+ // we can trigger a 404 in callLoadersAndMaybeResolveData
3410
+
3411
+ if (!fetcherMatches) {
3381
3412
  revalidatingFetchers.push(_extends({
3382
3413
  key
3383
- }, f));
3384
- } else {
3385
- // Revalidating fetchers are decoupled from the route matches since they
3386
- // hit a static href, so they _always_ check shouldRevalidate and the
3387
- // default is strictly if a revalidation is explicitly required (action
3388
- // submissions, useRevalidator, X-Remix-Revalidate).
3389
- let shouldRevalidate = shouldRevalidateLoader(f.match, _extends({
3390
- currentUrl,
3391
- currentParams: state.matches[state.matches.length - 1].params,
3392
- nextUrl,
3393
- nextParams: matches[matches.length - 1].params
3394
- }, submission, {
3395
- actionResult,
3396
- defaultShouldRevalidate
3414
+ }, f, {
3415
+ matches: null,
3416
+ match: null
3397
3417
  }));
3418
+ return;
3419
+ }
3398
3420
 
3399
- if (shouldRevalidate) {
3400
- revalidatingFetchers.push(_extends({
3401
- key
3402
- }, f));
3403
- }
3421
+ let fetcherMatch = getTargetMatch(fetcherMatches, f.path);
3422
+
3423
+ if (cancelledFetcherLoads.includes(key)) {
3424
+ revalidatingFetchers.push(_extends({
3425
+ key,
3426
+ matches: fetcherMatches,
3427
+ match: fetcherMatch
3428
+ }, f));
3429
+ return;
3430
+ } // Revalidating fetchers are decoupled from the route matches since they
3431
+ // hit a static href, so they _always_ check shouldRevalidate and the
3432
+ // default is strictly if a revalidation is explicitly required (action
3433
+ // submissions, useRevalidator, X-Remix-Revalidate).
3434
+
3435
+
3436
+ let shouldRevalidate = shouldRevalidateLoader(fetcherMatch, _extends({
3437
+ currentUrl,
3438
+ currentParams: state.matches[state.matches.length - 1].params,
3439
+ nextUrl,
3440
+ nextParams: matches[matches.length - 1].params
3441
+ }, submission, {
3442
+ actionResult,
3443
+ defaultShouldRevalidate
3444
+ }));
3445
+
3446
+ if (shouldRevalidate) {
3447
+ revalidatingFetchers.push(_extends({
3448
+ key,
3449
+ matches: fetcherMatches,
3450
+ match: fetcherMatch
3451
+ }, f));
3404
3452
  }
3405
3453
  });
3406
3454
  return [navigationMatches, revalidatingFetchers];
@@ -3570,9 +3618,13 @@ async function callLoaderOrAction(type, request, match, matches, basename, isSta
3570
3618
  }
3571
3619
 
3572
3620
  if (result instanceof DeferredData) {
3621
+ var _result$init, _result$init2;
3622
+
3573
3623
  return {
3574
3624
  type: ResultType.deferred,
3575
- deferredData: result
3625
+ deferredData: result,
3626
+ statusCode: (_result$init = result.init) == null ? void 0 : _result$init.status,
3627
+ headers: ((_result$init2 = result.init) == null ? void 0 : _result$init2.headers) && new Headers(result.init.headers)
3576
3628
  };
3577
3629
  }
3578
3630
 
@@ -3709,7 +3761,7 @@ function processLoaderData(state, matches, matchesToLoad, results, pendingError,
3709
3761
  let result = fetcherResults[index]; // Process fetcher non-redirect errors
3710
3762
 
3711
3763
  if (isErrorResult(result)) {
3712
- let boundaryMatch = findNearestBoundary(state.matches, match.route.id);
3764
+ let boundaryMatch = findNearestBoundary(state.matches, match == null ? void 0 : match.route.id);
3713
3765
 
3714
3766
  if (!(errors && errors[boundaryMatch.route.id])) {
3715
3767
  errors = _extends({}, errors, {
@@ -3756,7 +3808,9 @@ function mergeLoaderData(loaderData, newLoaderData, matches, errors) {
3756
3808
  if (newLoaderData[id] !== undefined) {
3757
3809
  mergedLoaderData[id] = newLoaderData[id];
3758
3810
  }
3759
- } else if (loaderData[id] !== undefined) {
3811
+ } else if (loaderData[id] !== undefined && match.route.loader) {
3812
+ // Preserve existing keys not included in newLoaderData and where a loader
3813
+ // wasn't removed by HMR
3760
3814
  mergedLoaderData[id] = loaderData[id];
3761
3815
  }
3762
3816
 
@@ -3893,7 +3947,14 @@ function isMutationMethod(method) {
3893
3947
  async function resolveDeferredResults(currentMatches, matchesToLoad, results, signal, isFetcher, currentLoaderData) {
3894
3948
  for (let index = 0; index < results.length; index++) {
3895
3949
  let result = results[index];
3896
- let match = matchesToLoad[index];
3950
+ let match = matchesToLoad[index]; // If we don't have a match, then we can have a deferred result to do
3951
+ // anything with. This is for revalidating fetchers where the route was
3952
+ // removed during HMR
3953
+
3954
+ if (!match) {
3955
+ continue;
3956
+ }
3957
+
3897
3958
  let currentMatch = currentMatches.find(m => m.route.id === match.route.id);
3898
3959
  let isRevalidatingLoader = currentMatch != null && !isNewRouteInstance(currentMatch, match) && (currentLoaderData && currentLoaderData[match.route.id]) !== undefined;
3899
3960
 
@@ -3977,5 +4038,5 @@ function getTargetMatch(matches, location) {
3977
4038
  return pathMatches[pathMatches.length - 1];
3978
4039
  } //#endregion
3979
4040
 
3980
- export { AbortedDeferredError, Action, ErrorResponse, IDLE_BLOCKER, IDLE_FETCHER, IDLE_NAVIGATION, UNSAFE_DEFERRED_SYMBOL, DeferredData as UNSAFE_DeferredData, convertRoutesToDataRoutes as UNSAFE_convertRoutesToDataRoutes, getPathContributingMatches as UNSAFE_getPathContributingMatches, createBrowserHistory, createHashHistory, createMemoryHistory, createPath, createRouter, createStaticHandler, defer, generatePath, getStaticContextFromError, getToPathname, invariant, isRouteErrorResponse, joinPaths, json, matchPath, matchRoutes, normalizePathname, parsePath, redirect, resolvePath, resolveTo, stripBasename, warning };
4041
+ export { AbortedDeferredError, Action, ErrorResponse, IDLE_BLOCKER, IDLE_FETCHER, IDLE_NAVIGATION, UNSAFE_DEFERRED_SYMBOL, DeferredData as UNSAFE_DeferredData, convertRoutesToDataRoutes as UNSAFE_convertRoutesToDataRoutes, getPathContributingMatches as UNSAFE_getPathContributingMatches, invariant as UNSAFE_invariant, createBrowserHistory, createHashHistory, createMemoryHistory, createPath, createRouter, createStaticHandler, defer, generatePath, getStaticContextFromError, getToPathname, isRouteErrorResponse, joinPaths, json, matchPath, matchRoutes, normalizePathname, parsePath, redirect, resolvePath, resolveTo, stripBasename, warning };
3981
4042
  //# sourceMappingURL=router.js.map