react-router 0.0.0-experimental-4ed3f5da9 → 0.0.0-experimental-cb25a21e1

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/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * React Router v0.0.0-experimental-4ed3f5da9
2
+ * React Router v0.0.0-experimental-cb25a21e1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -12,123 +12,6 @@ import * as React from 'react';
12
12
  import * as ReactDOM from 'react-dom';
13
13
  import { decode } from 'turbo-stream';
14
14
 
15
- function _AsyncGenerator(gen) {
16
- var front, back;
17
- function resume(key, arg) {
18
- try {
19
- var result = gen[key](arg),
20
- value = result.value,
21
- overloaded = value instanceof _OverloadYield;
22
- Promise.resolve(overloaded ? value.v : value).then(function (arg) {
23
- if (overloaded) {
24
- var nextKey = "return" === key ? "return" : "next";
25
- if (!value.k || arg.done) return resume(nextKey, arg);
26
- arg = gen[nextKey](arg).value;
27
- }
28
- settle(result.done ? "return" : "normal", arg);
29
- }, function (err) {
30
- resume("throw", err);
31
- });
32
- } catch (err) {
33
- settle("throw", err);
34
- }
35
- }
36
- function settle(type, value) {
37
- switch (type) {
38
- case "return":
39
- front.resolve({
40
- value: value,
41
- done: !0
42
- });
43
- break;
44
- case "throw":
45
- front.reject(value);
46
- break;
47
- default:
48
- front.resolve({
49
- value: value,
50
- done: !1
51
- });
52
- }
53
- (front = front.next) ? resume(front.key, front.arg) : back = null;
54
- }
55
- this._invoke = function (key, arg) {
56
- return new Promise(function (resolve, reject) {
57
- var request = {
58
- key: key,
59
- arg: arg,
60
- resolve: resolve,
61
- reject: reject,
62
- next: null
63
- };
64
- back ? back = back.next = request : (front = back = request, resume(key, arg));
65
- });
66
- }, "function" != typeof gen.return && (this.return = void 0);
67
- }
68
- _AsyncGenerator.prototype["function" == typeof Symbol && Symbol.asyncIterator || "@@asyncIterator"] = function () {
69
- return this;
70
- }, _AsyncGenerator.prototype.next = function (arg) {
71
- return this._invoke("next", arg);
72
- }, _AsyncGenerator.prototype.throw = function (arg) {
73
- return this._invoke("throw", arg);
74
- }, _AsyncGenerator.prototype.return = function (arg) {
75
- return this._invoke("return", arg);
76
- };
77
- function _OverloadYield(value, kind) {
78
- this.v = value, this.k = kind;
79
- }
80
- function _asyncIterator(iterable) {
81
- var method,
82
- async,
83
- sync,
84
- retry = 2;
85
- for ("undefined" != typeof Symbol && (async = Symbol.asyncIterator, sync = Symbol.iterator); retry--;) {
86
- if (async && null != (method = iterable[async])) return method.call(iterable);
87
- if (sync && null != (method = iterable[sync])) return new AsyncFromSyncIterator(method.call(iterable));
88
- async = "@@asyncIterator", sync = "@@iterator";
89
- }
90
- throw new TypeError("Object is not async iterable");
91
- }
92
- function AsyncFromSyncIterator(s) {
93
- function AsyncFromSyncIteratorContinuation(r) {
94
- if (Object(r) !== r) return Promise.reject(new TypeError(r + " is not an object."));
95
- var done = r.done;
96
- return Promise.resolve(r.value).then(function (value) {
97
- return {
98
- value: value,
99
- done: done
100
- };
101
- });
102
- }
103
- return AsyncFromSyncIterator = function (s) {
104
- this.s = s, this.n = s.next;
105
- }, AsyncFromSyncIterator.prototype = {
106
- s: null,
107
- n: null,
108
- next: function () {
109
- return AsyncFromSyncIteratorContinuation(this.n.apply(this.s, arguments));
110
- },
111
- return: function (value) {
112
- var ret = this.s.return;
113
- return void 0 === ret ? Promise.resolve({
114
- value: value,
115
- done: !0
116
- }) : AsyncFromSyncIteratorContinuation(ret.apply(this.s, arguments));
117
- },
118
- throw: function (value) {
119
- var thr = this.s.return;
120
- return void 0 === thr ? Promise.reject(value) : AsyncFromSyncIteratorContinuation(thr.apply(this.s, arguments));
121
- }
122
- }, new AsyncFromSyncIterator(s);
123
- }
124
- function _awaitAsyncGenerator(value) {
125
- return new _OverloadYield(value, 0);
126
- }
127
- function _wrapAsyncGenerator(fn) {
128
- return function () {
129
- return new _AsyncGenerator(fn.apply(this, arguments));
130
- };
131
- }
132
15
  function _extends() {
133
16
  _extends = Object.assign ? Object.assign.bind() : function (target) {
134
17
  for (var i = 1; i < arguments.length; i++) {
@@ -1603,6 +1486,7 @@ function createRouter(init) {
1603
1486
  // Flag to ignore the next history update, so we can revert the URL change on
1604
1487
  // a POP navigation that was blocked by the user without touching router state
1605
1488
  let ignoreNextHistoryUpdate = false;
1489
+ let pendingRevalidationDfd = null;
1606
1490
  // Initialize the router, all side effects should be kicked off from here.
1607
1491
  // Implemented as a Fluent API for ease of:
1608
1492
  // let router = createRouter(init).initialize();
@@ -1739,7 +1623,7 @@ function createRouter(init) {
1739
1623
  // - Navigation will always be set to IDLE_NAVIGATION
1740
1624
  // - Can pass any other state in newState
1741
1625
  function completeNavigation(location, newState, _temp) {
1742
- var _location$state, _location$state2;
1626
+ var _location$state, _location$state2, _pendingRevalidationD;
1743
1627
  let {
1744
1628
  flushSync
1745
1629
  } = _temp === void 0 ? {} : _temp;
@@ -1839,6 +1723,8 @@ function createRouter(init) {
1839
1723
  pendingViewTransitionEnabled = false;
1840
1724
  isUninterruptedRevalidation = false;
1841
1725
  isRevalidationRequired = false;
1726
+ (_pendingRevalidationD = pendingRevalidationDfd) == null ? void 0 : _pendingRevalidationD.resolve();
1727
+ pendingRevalidationDfd = null;
1842
1728
  cancelledDeferredRoutes = [];
1843
1729
  cancelledFetcherLoads = [];
1844
1730
  }
@@ -1906,7 +1792,7 @@ function createRouter(init) {
1906
1792
  });
1907
1793
  return;
1908
1794
  }
1909
- return await startNavigation(historyAction, nextLocation, {
1795
+ await startNavigation(historyAction, nextLocation, {
1910
1796
  submission,
1911
1797
  // Send through the formData serialization error if we have one so we can
1912
1798
  // render at the right error boundary after we match routes
@@ -1921,14 +1807,29 @@ function createRouter(init) {
1921
1807
  // is interrupted by a navigation, allow this to "succeed" by calling all
1922
1808
  // loaders during the next loader round
1923
1809
  function revalidate() {
1810
+ // We can't just return the promise from `startNavigation` because that
1811
+ // navigation may be interrupted and our revalidation wouldn't be finished
1812
+ // until the _next_ navigation completes. Instead we just track via a
1813
+ // deferred and resolve it the next time we run through `completeNavigation`
1814
+ // This is different than navigations which will settle if interrupted
1815
+ // because the navigation to a specific location is no longer relevant.
1816
+ // Revalidations are location-independent and will settle whenever we land
1817
+ // on our final location
1818
+ if (!pendingRevalidationDfd) {
1819
+ pendingRevalidationDfd = createDeferred();
1820
+ }
1924
1821
  interruptActiveLoads();
1925
1822
  updateState({
1926
1823
  revalidation: "loading"
1927
1824
  });
1825
+ // Capture this here for the edge-case that we have a fully synchronous
1826
+ // startNavigation which would resolve and null out pendingRevalidationDfd
1827
+ // before we return from this function
1828
+ let promise = pendingRevalidationDfd.promise;
1928
1829
  // If we're currently submitting an action, we don't need to start a new
1929
1830
  // navigation, we'll just let the follow up loader execution call all loaders
1930
1831
  if (state.navigation.state === "submitting") {
1931
- return;
1832
+ return promise;
1932
1833
  }
1933
1834
  // If we're currently in an idle state, start a new navigation for the current
1934
1835
  // action/location and mark it as uninterrupted, which will skip the history
@@ -1937,7 +1838,7 @@ function createRouter(init) {
1937
1838
  startNavigation(state.historyAction, state.location, {
1938
1839
  startUninterruptedRevalidation: true
1939
1840
  });
1940
- return;
1841
+ return promise;
1941
1842
  }
1942
1843
  // Otherwise, if we're currently in a loading state, just start a new
1943
1844
  // navigation to the navigation.location but do not trigger an uninterrupted
@@ -1945,6 +1846,7 @@ function createRouter(init) {
1945
1846
  startNavigation(pendingAction || state.historyAction, state.navigation.location, {
1946
1847
  overrideNavigation: state.navigation
1947
1848
  });
1849
+ return promise;
1948
1850
  }
1949
1851
  // Start a navigation to the given action/location. Can optionally provide a
1950
1852
  // overrideNavigation which will override the normalLoad in the case of a redirect
@@ -2287,7 +2189,7 @@ function createRouter(init) {
2287
2189
  } : {});
2288
2190
  }
2289
2191
  // Trigger a fetcher load/submit for the given fetcher key
2290
- function fetch(key, routeId, href, opts) {
2192
+ async function fetch(key, routeId, href, opts) {
2291
2193
  if (isServer) {
2292
2194
  throw new Error("router.fetch() was called during the server render, but it shouldn't be. " + "You are likely calling a useFetcher() method in the body of your component. " + "Try moving it to a useEffect or a callback.");
2293
2195
  }
@@ -2318,7 +2220,7 @@ function createRouter(init) {
2318
2220
  let match = getTargetMatch(matches, path);
2319
2221
  pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;
2320
2222
  if (submission && isMutationMethod(submission.formMethod)) {
2321
- handleFetcherAction(key, routeId, path, match, matches, flushSync, submission);
2223
+ await handleFetcherAction(key, routeId, path, match, matches, flushSync, submission);
2322
2224
  return;
2323
2225
  }
2324
2226
  // Store off the match so we can call it's shouldRevalidate on subsequent
@@ -2327,7 +2229,7 @@ function createRouter(init) {
2327
2229
  routeId,
2328
2230
  path
2329
2231
  });
2330
- handleFetcherLoader(key, routeId, path, match, matches, flushSync, submission);
2232
+ await handleFetcherLoader(key, routeId, path, match, matches, flushSync, submission);
2331
2233
  }
2332
2234
  // Call the action for the matched fetcher.submit(), and then handle redirects,
2333
2235
  // errors, and revalidation
@@ -3082,7 +2984,7 @@ function createStaticHandler$1(routes, opts) {
3082
2984
  };
3083
2985
  }
3084
2986
  let result = await queryImpl(request, location, matches, requestContext, unstable_dataStrategy || null, skipLoaderErrorBubbling === true, null);
3085
- if (isResponse$1(result)) {
2987
+ if (isResponse(result)) {
3086
2988
  return result;
3087
2989
  }
3088
2990
  // When returning StaticHandlerContext, we patch back in the location here
@@ -3151,7 +3053,7 @@ function createStaticHandler$1(routes, opts) {
3151
3053
  });
3152
3054
  }
3153
3055
  let result = await queryImpl(request, location, matches, requestContext, null, false, match);
3154
- if (isResponse$1(result)) {
3056
+ if (isResponse(result)) {
3155
3057
  return result;
3156
3058
  }
3157
3059
  let error = result.errors ? Object.values(result.errors)[0] : undefined;
@@ -3184,7 +3086,7 @@ function createStaticHandler$1(routes, opts) {
3184
3086
  return result;
3185
3087
  }
3186
3088
  let result = await loadRouteData(request, matches, requestContext, unstable_dataStrategy, skipLoaderErrorBubbling, routeMatch);
3187
- return isResponse$1(result) ? result : _extends({}, result, {
3089
+ return isResponse(result) ? result : _extends({}, result, {
3188
3090
  actionData: null,
3189
3091
  actionHeaders: {}
3190
3092
  });
@@ -3192,7 +3094,7 @@ function createStaticHandler$1(routes, opts) {
3192
3094
  // If the user threw/returned a Response in callLoaderOrAction for a
3193
3095
  // `queryRoute` call, we throw the `HandlerResult` to bail out early
3194
3096
  // and then return or throw the raw Response here accordingly
3195
- if (isHandlerResult(e) && isResponse$1(e.result)) {
3097
+ if (isHandlerResult(e) && isResponse(e.result)) {
3196
3098
  if (e.type === ResultType.error) {
3197
3099
  throw e.result;
3198
3100
  }
@@ -3200,7 +3102,7 @@ function createStaticHandler$1(routes, opts) {
3200
3102
  }
3201
3103
  // Redirects are always returned since they don't propagate to catch
3202
3104
  // boundaries
3203
- if (isRedirectResponse$1(e)) {
3105
+ if (isRedirectResponse(e)) {
3204
3106
  return e;
3205
3107
  }
3206
3108
  throw e;
@@ -3363,7 +3265,7 @@ function createStaticHandler$1(routes, opts) {
3363
3265
  // Throw redirects and let the server handle them with an HTTP redirect
3364
3266
  throw normalizeRelativeRoutingRedirectResponse(response, request, matchesToLoad[i].route.id, matches, basename, future.v7_relativeSplatPath);
3365
3267
  }
3366
- if (isResponse$1(result.result) && isRouteRequest) {
3268
+ if (isResponse(result.result) && isRouteRequest) {
3367
3269
  // For SSR single-route requests, we want to hand Responses back
3368
3270
  // directly without unwrapping
3369
3271
  throw result;
@@ -3942,7 +3844,7 @@ async function convertHandlerResultToDataResult(handlerResult) {
3942
3844
  type,
3943
3845
  status
3944
3846
  } = handlerResult;
3945
- if (isResponse$1(result)) {
3847
+ if (isResponse(result)) {
3946
3848
  let data;
3947
3849
  try {
3948
3850
  let contentType = result.headers.get("Content-Type");
@@ -3985,7 +3887,7 @@ async function convertHandlerResultToDataResult(handlerResult) {
3985
3887
  statusCode: isRouteErrorResponse(result) ? result.status : status
3986
3888
  };
3987
3889
  }
3988
- if (isDeferredData$1(result)) {
3890
+ if (isDeferredData(result)) {
3989
3891
  var _result$init, _result$init2;
3990
3892
  return {
3991
3893
  type: ResultType.deferred,
@@ -4332,7 +4234,7 @@ function isHandlerResult(result) {
4332
4234
  return result != null && typeof result === "object" && "type" in result && "result" in result && (result.type === ResultType.data || result.type === ResultType.error);
4333
4235
  }
4334
4236
  function isRedirectHandlerResult(result) {
4335
- return isResponse$1(result.result) && redirectStatusCodes.has(result.result.status);
4237
+ return isResponse(result.result) && redirectStatusCodes.has(result.result.status);
4336
4238
  }
4337
4239
  function isDeferredResult(result) {
4338
4240
  return result.type === ResultType.deferred;
@@ -4343,15 +4245,15 @@ function isErrorResult(result) {
4343
4245
  function isRedirectResult(result) {
4344
4246
  return (result && result.type) === ResultType.redirect;
4345
4247
  }
4346
- function isDeferredData$1(value) {
4248
+ function isDeferredData(value) {
4347
4249
  let deferred = value;
4348
4250
  return deferred && typeof deferred === "object" && typeof deferred.data === "object" && typeof deferred.subscribe === "function" && typeof deferred.cancel === "function" && typeof deferred.resolveData === "function";
4349
4251
  }
4350
- function isResponse$1(value) {
4252
+ function isResponse(value) {
4351
4253
  return value != null && typeof value.status === "number" && typeof value.statusText === "string" && typeof value.headers === "object" && typeof value.body !== "undefined";
4352
4254
  }
4353
- function isRedirectResponse$1(result) {
4354
- if (!isResponse$1(result)) {
4255
+ function isRedirectResponse(result) {
4256
+ if (!isResponse(result)) {
4355
4257
  return false;
4356
4258
  }
4357
4259
  let status = result.status;
@@ -4593,6 +4495,31 @@ function persistAppliedTransitions(_window, transitions) {
4593
4495
  }
4594
4496
  }
4595
4497
  }
4498
+ function createDeferred() {
4499
+ let resolve;
4500
+ let reject;
4501
+ let promise = new Promise((res, rej) => {
4502
+ resolve = async val => {
4503
+ res(val);
4504
+ try {
4505
+ await promise;
4506
+ } catch (e) {}
4507
+ };
4508
+ reject = async error => {
4509
+ rej(error);
4510
+ try {
4511
+ await promise;
4512
+ } catch (e) {}
4513
+ };
4514
+ });
4515
+ return {
4516
+ promise,
4517
+ //@ts-ignore
4518
+ resolve,
4519
+ //@ts-ignore
4520
+ reject
4521
+ };
4522
+ }
4596
4523
  //#endregion
4597
4524
 
4598
4525
  const DataRouterContext = /*#__PURE__*/React.createContext(null);
@@ -5251,9 +5178,11 @@ function useRevalidator() {
5251
5178
  let dataRouterContext = useDataRouterContext$2(DataRouterHook$1.UseRevalidator);
5252
5179
  let state = useDataRouterState$1(DataRouterStateHook$1.UseRevalidator);
5253
5180
  return React.useMemo(() => ({
5254
- revalidate: dataRouterContext.router.revalidate,
5181
+ async revalidate() {
5182
+ await dataRouterContext.router.revalidate();
5183
+ },
5255
5184
  state: state.revalidation
5256
- }), [dataRouterContext.router.revalidate, state.revalidation]);
5185
+ }), [dataRouterContext.router, state.revalidation]);
5257
5186
  }
5258
5187
  /**
5259
5188
  * Returns the active route matches, useful for accessing loaderData for
@@ -5415,7 +5344,7 @@ function useNavigateStable() {
5415
5344
  useIsomorphicLayoutEffect(() => {
5416
5345
  activeRef.current = true;
5417
5346
  });
5418
- let navigate = React.useCallback(function (to, options) {
5347
+ let navigate = React.useCallback(async function (to, options) {
5419
5348
  if (options === void 0) {
5420
5349
  options = {};
5421
5350
  }
@@ -5426,7 +5355,7 @@ function useNavigateStable() {
5426
5355
  if (typeof to === "number") {
5427
5356
  router.navigate(to);
5428
5357
  } else {
5429
- router.navigate(to, _extends({
5358
+ await router.navigate(to, _extends({
5430
5359
  fromRouteId: id
5431
5360
  }, options));
5432
5361
  }
@@ -5689,11 +5618,13 @@ function Navigate(_ref4) {
5689
5618
  // StrictMode they navigate to the same place
5690
5619
  let path = resolveTo(to, getResolveToMatches(matches, future.v7_relativeSplatPath), locationPathname, relative === "path");
5691
5620
  let jsonPath = JSON.stringify(path);
5692
- React.useEffect(() => navigate(JSON.parse(jsonPath), {
5693
- replace,
5694
- state,
5695
- relative
5696
- }), [navigate, jsonPath, relative, replace, state]);
5621
+ React.useEffect(() => {
5622
+ navigate(JSON.parse(jsonPath), {
5623
+ replace,
5624
+ state,
5625
+ relative
5626
+ });
5627
+ }, [navigate, jsonPath, relative, replace, state]);
5697
5628
  return null;
5698
5629
  }
5699
5630
  /**
@@ -6367,18 +6298,6 @@ function getNewMatchesForLinks(page, nextMatches, currentMatches, manifest, loca
6367
6298
  });
6368
6299
  return newMatches;
6369
6300
  }
6370
- function getDataLinkHrefs(page, matches, manifest) {
6371
- let path = parsePathPatch(page);
6372
- return dedupeHrefs(matches.filter(match => manifest.routes[match.route.id].hasLoader).map(match => {
6373
- let {
6374
- pathname,
6375
- search
6376
- } = path;
6377
- let searchParams = new URLSearchParams(search);
6378
- searchParams.set("_data", match.route.id);
6379
- return pathname + "?" + searchParams;
6380
- }));
6381
- }
6382
6301
  function getModuleLinkHrefs(matches, manifestPatch) {
6383
6302
  return dedupeHrefs(matches.map(match => {
6384
6303
  let route = manifestPatch.routes[match.route.id];
@@ -6473,71 +6392,6 @@ function createHtml(html) {
6473
6392
  };
6474
6393
  }
6475
6394
 
6476
- function isCatchResponse(response) {
6477
- return response.headers.get("X-Remix-Catch") != null;
6478
- }
6479
- function isErrorResponse(response) {
6480
- return response.headers.get("X-Remix-Error") != null;
6481
- }
6482
- function isNetworkErrorResponse(response) {
6483
- // If we reach the Remix server, we can safely identify response types via the
6484
- // X-Remix-Error/X-Remix-Catch headers. However, if we never reach the Remix
6485
- // server, and instead receive a 4xx/5xx from somewhere in between (like
6486
- // Cloudflare), then we get a false negative in the isErrorResponse check and
6487
- // we incorrectly assume that the user returns the 4xx/5xx response and
6488
- // consider it successful. To alleviate this, we add X-Remix-Response to any
6489
- // non-Error/non-Catch responses coming back from the server. If we don't
6490
- // see this, we can conclude that a 4xx/5xx response never actually reached
6491
- // the Remix server and we can bubble it up as an error.
6492
- return isResponse(response) && response.status >= 400 && response.headers.get("X-Remix-Error") == null && response.headers.get("X-Remix-Catch") == null && response.headers.get("X-Remix-Response") == null;
6493
- }
6494
- function isRedirectResponse(response) {
6495
- return response.headers.get("X-Remix-Redirect") != null;
6496
- }
6497
- function isDeferredResponse(response) {
6498
- var _response$headers$get;
6499
- return !!((_response$headers$get = response.headers.get("Content-Type")) != null && _response$headers$get.match(/text\/remix-deferred/));
6500
- }
6501
- function isResponse(value) {
6502
- return value != null && typeof value.status === "number" && typeof value.statusText === "string" && typeof value.headers === "object" && typeof value.body !== "undefined";
6503
- }
6504
- function isDeferredData(value) {
6505
- let deferred = value;
6506
- return deferred && typeof deferred === "object" && typeof deferred.data === "object" && typeof deferred.subscribe === "function" && typeof deferred.cancel === "function" && typeof deferred.resolveData === "function";
6507
- }
6508
- async function fetchData(request, routeId, retry) {
6509
- if (retry === void 0) {
6510
- retry = 0;
6511
- }
6512
- let url = new URL(request.url);
6513
- url.searchParams.set("_data", routeId);
6514
- if (retry > 0) {
6515
- // Retry up to 3 times waiting 50, 250, 1250 ms
6516
- // between retries for a total of 1550 ms before giving up.
6517
- await new Promise(resolve => setTimeout(resolve, 5 ** retry * 10));
6518
- }
6519
- let init = await createRequestInit(request);
6520
- let revalidation = window.__remixRevalidation;
6521
- let response = await fetch(url.href, init).catch(error => {
6522
- if (typeof revalidation === "number" && revalidation === window.__remixRevalidation && (error == null ? void 0 : error.name) === "TypeError" && retry < 3) {
6523
- return fetchData(request, routeId, retry + 1);
6524
- }
6525
- throw error;
6526
- });
6527
- if (isErrorResponse(response)) {
6528
- let data = await response.json();
6529
- let error = new Error(data.message);
6530
- error.stack = data.stack;
6531
- return error;
6532
- }
6533
- if (isNetworkErrorResponse(response)) {
6534
- let text = await response.text();
6535
- let error = new Error(text);
6536
- error.stack = undefined;
6537
- return error;
6538
- }
6539
- return response;
6540
- }
6541
6395
  async function createRequestInit(request) {
6542
6396
  let init = {
6543
6397
  signal: request.signal
@@ -6565,184 +6419,6 @@ async function createRequestInit(request) {
6565
6419
  }
6566
6420
  return init;
6567
6421
  }
6568
- const DEFERRED_VALUE_PLACEHOLDER_PREFIX = "__deferred_promise:";
6569
- async function parseDeferredReadableStream(stream) {
6570
- if (!stream) {
6571
- throw new Error("parseDeferredReadableStream requires stream argument");
6572
- }
6573
- let deferredData;
6574
- let deferredResolvers = {};
6575
- try {
6576
- let sectionReader = readStreamSections(stream);
6577
- // Read the first section to get the critical data
6578
- let initialSectionResult = await sectionReader.next();
6579
- let initialSection = initialSectionResult.value;
6580
- if (!initialSection) throw new Error("no critical data");
6581
- let criticalData = JSON.parse(initialSection);
6582
- // Setup deferred data and resolvers for later based on the critical data
6583
- if (typeof criticalData === "object" && criticalData !== null) {
6584
- for (let [eventKey, value] of Object.entries(criticalData)) {
6585
- if (typeof value !== "string" || !value.startsWith(DEFERRED_VALUE_PLACEHOLDER_PREFIX)) {
6586
- continue;
6587
- }
6588
- deferredData = deferredData || {};
6589
- deferredData[eventKey] = new Promise((_resolve, _reject) => {
6590
- deferredResolvers[eventKey] = {
6591
- resolve: value => {
6592
- _resolve(value);
6593
- delete deferredResolvers[eventKey];
6594
- },
6595
- reject: error => {
6596
- _reject(error);
6597
- delete deferredResolvers[eventKey];
6598
- }
6599
- };
6600
- });
6601
- }
6602
- }
6603
- // Read the rest of the stream and resolve deferred promises
6604
- void (async () => {
6605
- try {
6606
- var _iteratorAbruptCompletion = false;
6607
- var _didIteratorError = false;
6608
- var _iteratorError;
6609
- try {
6610
- for (var _iterator = _asyncIterator(sectionReader), _step; _iteratorAbruptCompletion = !(_step = await _iterator.next()).done; _iteratorAbruptCompletion = false) {
6611
- let section = _step.value;
6612
- {
6613
- // Determine event type and data
6614
- let [event, ...sectionDataStrings] = section.split(":");
6615
- let sectionDataString = sectionDataStrings.join(":");
6616
- let data = JSON.parse(sectionDataString);
6617
- if (event === "data") {
6618
- for (let [key, value] of Object.entries(data)) {
6619
- if (deferredResolvers[key]) {
6620
- deferredResolvers[key].resolve(value);
6621
- }
6622
- }
6623
- } else if (event === "error") {
6624
- for (let [key, value] of Object.entries(data)) {
6625
- let err = new Error(value.message);
6626
- err.stack = value.stack;
6627
- if (deferredResolvers[key]) {
6628
- deferredResolvers[key].reject(err);
6629
- }
6630
- }
6631
- }
6632
- }
6633
- }
6634
- } catch (err) {
6635
- _didIteratorError = true;
6636
- _iteratorError = err;
6637
- } finally {
6638
- try {
6639
- if (_iteratorAbruptCompletion && _iterator.return != null) {
6640
- await _iterator.return();
6641
- }
6642
- } finally {
6643
- if (_didIteratorError) {
6644
- throw _iteratorError;
6645
- }
6646
- }
6647
- }
6648
- for (let [key, resolver] of Object.entries(deferredResolvers)) {
6649
- resolver.reject(new AbortedDeferredError("Deferred " + key + " will never be resolved"));
6650
- }
6651
- } catch (error) {
6652
- // Reject any existing deferred promises if something blows up
6653
- for (let resolver of Object.values(deferredResolvers)) {
6654
- resolver.reject(error);
6655
- }
6656
- }
6657
- })();
6658
- return new DeferredData(_extends({}, criticalData, deferredData));
6659
- } catch (error) {
6660
- for (let resolver of Object.values(deferredResolvers)) {
6661
- resolver.reject(error);
6662
- }
6663
- throw error;
6664
- }
6665
- }
6666
- function readStreamSections(_x) {
6667
- return _readStreamSections.apply(this, arguments);
6668
- }
6669
- function _readStreamSections() {
6670
- _readStreamSections = _wrapAsyncGenerator(function* (stream) {
6671
- let reader = stream.getReader();
6672
- let buffer = [];
6673
- let sections = [];
6674
- let closed = false;
6675
- let encoder = new TextEncoder();
6676
- let decoder = new TextDecoder();
6677
- let readStreamSection = async () => {
6678
- if (sections.length > 0) return sections.shift();
6679
- // Read from the stream until we have at least one complete section to process
6680
- while (!closed && sections.length === 0) {
6681
- let chunk = await reader.read();
6682
- if (chunk.done) {
6683
- closed = true;
6684
- break;
6685
- }
6686
- // Buffer the raw chunks
6687
- buffer.push(chunk.value);
6688
- try {
6689
- // Attempt to split off a section from the buffer
6690
- let bufferedString = decoder.decode(mergeArrays(...buffer));
6691
- let splitSections = bufferedString.split("\n\n");
6692
- if (splitSections.length >= 2) {
6693
- // We have a complete section, so add it to the sections array
6694
- sections.push(...splitSections.slice(0, -1));
6695
- // Remove the section from the buffer and store the rest for future processing
6696
- buffer = [encoder.encode(splitSections.slice(-1).join("\n\n"))];
6697
- }
6698
- // If we successfully parsed at least one section, break out of reading the stream
6699
- // to allow upstream processing of the processable sections
6700
- if (sections.length > 0) {
6701
- break;
6702
- }
6703
- } catch (_unused) {
6704
- // If we failed to parse the buffer it was because we failed to decode the stream
6705
- // because we are missing bytes that we haven't yet received, so continue reading
6706
- // from the stream until we have a complete section
6707
- continue;
6708
- }
6709
- }
6710
- // If we have a complete section, return it
6711
- if (sections.length > 0) {
6712
- return sections.shift();
6713
- }
6714
- // If we have no complete section, but we have no more chunks to process,
6715
- // split those sections and clear out the buffer as there is no more data
6716
- // to process. If this errors, let it bubble up as the stream ended
6717
- // without valid data
6718
- if (buffer.length > 0) {
6719
- let bufferedString = decoder.decode(mergeArrays(...buffer));
6720
- sections = bufferedString.split("\n\n").filter(s => s);
6721
- buffer = [];
6722
- }
6723
- // Return any remaining sections that have been processed
6724
- return sections.shift();
6725
- };
6726
- let section = yield _awaitAsyncGenerator(readStreamSection());
6727
- while (section) {
6728
- yield section;
6729
- section = yield _awaitAsyncGenerator(readStreamSection());
6730
- }
6731
- });
6732
- return _readStreamSections.apply(this, arguments);
6733
- }
6734
- function mergeArrays() {
6735
- for (var _len = arguments.length, arrays = new Array(_len), _key = 0; _key < _len; _key++) {
6736
- arrays[_key] = arguments[_key];
6737
- }
6738
- let out = new Uint8Array(arrays.reduce((total, arr) => total + arr.length, 0));
6739
- let offset = 0;
6740
- for (let arr of arrays) {
6741
- out.set(arr, offset);
6742
- offset += arr.length;
6743
- }
6744
- return out;
6745
- }
6746
6422
 
6747
6423
  const SingleFetchRedirectSymbol = Symbol("SingleFetchRedirect");
6748
6424
  // StreamTransfer recursively renders down chunks of the `serverHandoffStream`
@@ -6935,7 +6611,10 @@ function addRevalidationParam(manifest, routeModules, matchedRoutes, loadRoutes,
6935
6611
  return url;
6936
6612
  }
6937
6613
  function singleFetchUrl(reqUrl) {
6938
- let url = typeof reqUrl === "string" ? new URL(reqUrl, window.location.origin) : reqUrl;
6614
+ let url = typeof reqUrl === "string" ? new URL(reqUrl,
6615
+ // This can be called during the SSR flow via PrefetchPageLinksImpl so
6616
+ // don't assume window is available
6617
+ typeof window === "undefined" ? "server://singlefetch/" : window.location.origin) : reqUrl;
6939
6618
  url.pathname = (url.pathname === "/" ? "_root" : url.pathname) + ".data";
6940
6619
  return url;
6941
6620
  }
@@ -7243,7 +6922,6 @@ function PrefetchPageLinksImpl(_ref3) {
7243
6922
  linkProps = _objectWithoutPropertiesLoose(_ref3, _excluded2$1);
7244
6923
  let location = useLocation();
7245
6924
  let {
7246
- future,
7247
6925
  manifest,
7248
6926
  routeModules
7249
6927
  } = useRemixContext();
@@ -7252,21 +6930,12 @@ function PrefetchPageLinksImpl(_ref3) {
7252
6930
  } = useDataRouterStateContext();
7253
6931
  let newMatchesForData = React.useMemo(() => getNewMatchesForLinks(page, nextMatches, matches, manifest, location, "data"), [page, nextMatches, matches, manifest, location]);
7254
6932
  let newMatchesForAssets = React.useMemo(() => getNewMatchesForLinks(page, nextMatches, matches, manifest, location, "assets"), [page, nextMatches, matches, manifest, location]);
7255
- let dataHrefs = React.useMemo(() => getDataLinkHrefs(page, newMatchesForData, manifest), [newMatchesForData, page, manifest]);
7256
6933
  let moduleHrefs = React.useMemo(() => getModuleLinkHrefs(newMatchesForAssets, manifest), [newMatchesForAssets, manifest]);
7257
6934
  // needs to be a hook with async behavior because we need the modules, not
7258
6935
  // just the manifest like the other links in here.
7259
6936
  let keyedPrefetchLinks = useKeyedPrefetchLinks(newMatchesForAssets);
7260
6937
  let linksToRender = null;
7261
- if (!future.unstable_singleFetch) {
7262
- // Non-single-fetch prefetching
7263
- linksToRender = dataHrefs.map(href => ( /*#__PURE__*/React.createElement("link", _extends({
7264
- key: href,
7265
- rel: "prefetch",
7266
- as: "fetch",
7267
- href: href
7268
- }, linkProps))));
7269
- } else if (newMatchesForData.length > 0) {
6938
+ if (newMatchesForData.length > 0) {
7270
6939
  // Single-fetch with routes that require data
7271
6940
  let url = addRevalidationParam(manifest, routeModules, nextMatches.map(m => m.route), newMatchesForData.map(m => m.route), singleFetchUrl(page));
7272
6941
  if (url.searchParams.get("_routes") !== "") {
@@ -7277,7 +6946,7 @@ function PrefetchPageLinksImpl(_ref3) {
7277
6946
  href: url.pathname + url.search
7278
6947
  }, linkProps));
7279
6948
  }
7280
- } else ;
6949
+ }
7281
6950
  return /*#__PURE__*/React.createElement(React.Fragment, null, linksToRender, moduleHrefs.map(href => ( /*#__PURE__*/React.createElement("link", _extends({
7282
6951
  key: href,
7283
6952
  rel: "modulepreload",
@@ -7450,10 +7119,7 @@ function Scripts(props) {
7450
7119
  let {
7451
7120
  manifest,
7452
7121
  serverHandoffString,
7453
- abortDelay,
7454
- serializeError,
7455
7122
  isSpaMode,
7456
- future,
7457
7123
  renderMeta
7458
7124
  } = useRemixContext();
7459
7125
  let {
@@ -7474,89 +7140,10 @@ function Scripts(props) {
7474
7140
  React.useEffect(() => {
7475
7141
  isHydrated = true;
7476
7142
  }, []);
7477
- let serializePreResolvedErrorImp = (key, error) => {
7478
- let toSerialize;
7479
- if (serializeError && error instanceof Error) {
7480
- toSerialize = serializeError(error);
7481
- } else {
7482
- toSerialize = error;
7483
- }
7484
- return JSON.stringify(key) + ":__remixContext.p(!1, " + escapeHtml(JSON.stringify(toSerialize)) + ")";
7485
- };
7486
- let serializePreresolvedDataImp = (routeId, key, data) => {
7487
- let serializedData;
7488
- try {
7489
- serializedData = JSON.stringify(data);
7490
- } catch (error) {
7491
- return serializePreResolvedErrorImp(key, error);
7492
- }
7493
- return JSON.stringify(key) + ":__remixContext.p(" + escapeHtml(serializedData) + ")";
7494
- };
7495
- let serializeErrorImp = (routeId, key, error) => {
7496
- let toSerialize;
7497
- if (serializeError && error instanceof Error) {
7498
- toSerialize = serializeError(error);
7499
- } else {
7500
- toSerialize = error;
7501
- }
7502
- return "__remixContext.r(" + JSON.stringify(routeId) + ", " + JSON.stringify(key) + ", !1, " + escapeHtml(JSON.stringify(toSerialize)) + ")";
7503
- };
7504
- let serializeDataImp = (routeId, key, data) => {
7505
- let serializedData;
7506
- try {
7507
- serializedData = JSON.stringify(data);
7508
- } catch (error) {
7509
- return serializeErrorImp(routeId, key, error);
7510
- }
7511
- return "__remixContext.r(" + JSON.stringify(routeId) + ", " + JSON.stringify(key) + ", " + escapeHtml(serializedData) + ")";
7512
- };
7513
- let deferredScripts = [];
7514
7143
  let initialScripts = React.useMemo(() => {
7515
7144
  var _manifest$hmr;
7516
- let streamScript = future.unstable_singleFetch ?
7517
- // prettier-ignore
7518
- "window.__remixContext.stream = new ReadableStream({" + "start(controller){" + "window.__remixContext.streamController = controller;" + "}" + "}).pipeThrough(new TextEncoderStream());" : "";
7145
+ let streamScript = "window.__remixContext.stream = new ReadableStream({" + "start(controller){" + "window.__remixContext.streamController = controller;" + "}" + "}).pipeThrough(new TextEncoderStream());";
7519
7146
  let contextScript = staticContext ? "window.__remixContext = " + serverHandoffString + ";" + streamScript : " ";
7520
- // When single fetch is enabled, deferred is handled by turbo-stream
7521
- let activeDeferreds = future.unstable_singleFetch ? undefined : staticContext == null ? void 0 : staticContext.activeDeferreds;
7522
- // This sets up the __remixContext with utility functions used by the
7523
- // deferred scripts.
7524
- // - __remixContext.p is a function that takes a resolved value or error and returns a promise.
7525
- // This is used for transmitting pre-resolved promises from the server to the client.
7526
- // - __remixContext.n is a function that takes a routeID and key to returns a promise for later
7527
- // resolution by the subsequently streamed chunks.
7528
- // - __remixContext.r is a function that takes a routeID, key and value or error and resolves
7529
- // the promise created by __remixContext.n.
7530
- // - __remixContext.t is a map or routeId to keys to an object containing `e` and `r` methods
7531
- // to resolve or reject the promise created by __remixContext.n.
7532
- // - __remixContext.a is the active number of deferred scripts that should be rendered to match
7533
- // the SSR tree for hydration on the client.
7534
- contextScript += !activeDeferreds ? "" : ["__remixContext.p = function(v,e,p,x) {", " if (typeof e !== 'undefined') {", process.env.NODE_ENV === "development" ? " x=new Error(e.message);\n x.stack=e.stack;" : ' x=new Error("Unexpected Server Error");\n x.stack=undefined;', " p=Promise.reject(x);", " } else {", " p=Promise.resolve(v);", " }", " return p;", "};", "__remixContext.n = function(i,k) {", " __remixContext.t = __remixContext.t || {};", " __remixContext.t[i] = __remixContext.t[i] || {};", " let p = new Promise((r, e) => {__remixContext.t[i][k] = {r:(v)=>{r(v);},e:(v)=>{e(v);}};});", typeof abortDelay === "number" ? "setTimeout(() => {if(typeof p._error !== \"undefined\" || typeof p._data !== \"undefined\"){return;} __remixContext.t[i][k].e(new Error(\"Server timeout.\"))}, " + abortDelay + ");" : "", " return p;", "};", "__remixContext.r = function(i,k,v,e,p,x) {", " p = __remixContext.t[i][k];", " if (typeof e !== 'undefined') {", process.env.NODE_ENV === "development" ? " x=new Error(e.message);\n x.stack=e.stack;" : ' x=new Error("Unexpected Server Error");\n x.stack=undefined;', " p.e(x);", " } else {", " p.r(v);", " }", "};"].join("\n") + Object.entries(activeDeferreds).map(_ref5 => {
7535
- let [routeId, deferredData] = _ref5;
7536
- let pendingKeys = new Set(deferredData.pendingKeys);
7537
- let promiseKeyValues = deferredData.deferredKeys.map(key => {
7538
- if (pendingKeys.has(key)) {
7539
- deferredScripts.push( /*#__PURE__*/React.createElement(DeferredHydrationScript, {
7540
- key: routeId + " | " + key,
7541
- deferredData: deferredData,
7542
- routeId: routeId,
7543
- dataKey: key,
7544
- scriptProps: props,
7545
- serializeData: serializeDataImp,
7546
- serializeError: serializeErrorImp
7547
- }));
7548
- return JSON.stringify(key) + ":__remixContext.n(" + JSON.stringify(routeId) + ", " + JSON.stringify(key) + ")";
7549
- } else {
7550
- let trackedPromise = deferredData.data[key];
7551
- if (typeof trackedPromise._error !== "undefined") {
7552
- return serializePreResolvedErrorImp(key, trackedPromise._error);
7553
- } else {
7554
- return serializePreresolvedDataImp(routeId, key, trackedPromise._data);
7555
- }
7556
- }
7557
- }).join(",\n");
7558
- return "Object.assign(__remixContext.state.loaderData[" + JSON.stringify(routeId) + "], {" + promiseKeyValues + "});";
7559
- }).join("\n") + (deferredScripts.length > 0 ? "__remixContext.a=" + deferredScripts.length + ";" : "");
7560
7147
  let routeModulesScript = !isStatic ? " " : ((_manifest$hmr = manifest.hmr) != null && _manifest$hmr.runtime ? "import " + JSON.stringify(manifest.hmr.runtime) + ";" : "") + "import " + JSON.stringify(manifest.url) + ";\n" + matches.map((match, index) => "import * as route" + index + " from " + JSON.stringify(manifest.routes[match.route.id].module) + ";").join("\n") + "\nwindow.__remixRouteModules = {" + matches.map((match, index) => JSON.stringify(match.route.id) + ":route" + index).join(",") + "};\n\nimport(" + JSON.stringify(manifest.entry.module) + ");";
7561
7148
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("script", _extends({}, props, {
7562
7149
  suppressHydrationWarning: true,
@@ -7573,16 +7160,6 @@ function Scripts(props) {
7573
7160
  // scripts as they were when the page first loaded
7574
7161
  // eslint-disable-next-line
7575
7162
  }, []);
7576
- if (!isStatic && typeof __remixContext === "object" && __remixContext.a) {
7577
- for (let i = 0; i < __remixContext.a; i++) {
7578
- deferredScripts.push( /*#__PURE__*/React.createElement(DeferredHydrationScript, {
7579
- key: i,
7580
- scriptProps: props,
7581
- serializeData: serializeDataImp,
7582
- serializeError: serializeErrorImp
7583
- }));
7584
- }
7585
- }
7586
7163
  // avoid waterfall when importing the next route module
7587
7164
  let nextMatches = React.useMemo(() => {
7588
7165
  if (navigation.location) {
@@ -7611,71 +7188,7 @@ function Scripts(props) {
7611
7188
  rel: "modulepreload",
7612
7189
  href: path,
7613
7190
  crossOrigin: props.crossOrigin
7614
- }))), initialScripts, deferredScripts));
7615
- }
7616
- function DeferredHydrationScript(_ref6) {
7617
- let {
7618
- dataKey,
7619
- deferredData,
7620
- routeId,
7621
- scriptProps,
7622
- serializeData,
7623
- serializeError
7624
- } = _ref6;
7625
- if (typeof document === "undefined" && deferredData && dataKey && routeId) {
7626
- !deferredData.pendingKeys.includes(dataKey) ? process.env.NODE_ENV !== "production" ? invariant(false, "Deferred data for route " + routeId + " with key " + dataKey + " was not pending but tried to render a script for it.") : invariant(false) : void 0;
7627
- }
7628
- return /*#__PURE__*/React.createElement(React.Suspense, {
7629
- fallback:
7630
- // This makes absolutely no sense. The server renders null as a fallback,
7631
- // but when hydrating, we need to render a script tag to avoid a hydration issue.
7632
- // To reproduce a hydration mismatch, just render null as a fallback.
7633
- typeof document === "undefined" && deferredData && dataKey && routeId ? null : ( /*#__PURE__*/React.createElement("script", _extends({}, scriptProps, {
7634
- async: true,
7635
- suppressHydrationWarning: true,
7636
- dangerouslySetInnerHTML: {
7637
- __html: " "
7638
- }
7639
- })))
7640
- }, typeof document === "undefined" && deferredData && dataKey && routeId ? ( /*#__PURE__*/React.createElement(Await, {
7641
- resolve: deferredData.data[dataKey],
7642
- errorElement: /*#__PURE__*/React.createElement(ErrorDeferredHydrationScript, {
7643
- dataKey: dataKey,
7644
- routeId: routeId,
7645
- scriptProps: scriptProps,
7646
- serializeError: serializeError
7647
- }),
7648
- children: data => {
7649
- return /*#__PURE__*/React.createElement("script", _extends({}, scriptProps, {
7650
- async: true,
7651
- suppressHydrationWarning: true,
7652
- dangerouslySetInnerHTML: {
7653
- __html: serializeData(routeId, dataKey, data)
7654
- }
7655
- }));
7656
- }
7657
- })) : ( /*#__PURE__*/React.createElement("script", _extends({}, scriptProps, {
7658
- async: true,
7659
- suppressHydrationWarning: true,
7660
- dangerouslySetInnerHTML: {
7661
- __html: " "
7662
- }
7663
- }))));
7664
- }
7665
- function ErrorDeferredHydrationScript(_ref7) {
7666
- let {
7667
- dataKey,
7668
- routeId,
7669
- scriptProps,
7670
- serializeError
7671
- } = _ref7;
7672
- let error = useAsyncError();
7673
- return /*#__PURE__*/React.createElement("script", _extends({}, scriptProps, {
7674
- suppressHydrationWarning: true,
7675
- dangerouslySetInnerHTML: {
7676
- __html: serializeError(routeId, dataKey, error)
7677
- }
7678
- }));
7191
+ }))), initialScripts));
7679
7192
  }
7680
7193
  function dedupe(array) {
7681
7194
  return [...new Set(array)];
@@ -8641,7 +8154,7 @@ function useSubmit() {
8641
8154
  basename
8642
8155
  } = React.useContext(NavigationContext);
8643
8156
  let currentRouteId = useRouteId();
8644
- return React.useCallback(function (target, options) {
8157
+ return React.useCallback(async function (target, options) {
8645
8158
  if (options === void 0) {
8646
8159
  options = {};
8647
8160
  }
@@ -8655,7 +8168,7 @@ function useSubmit() {
8655
8168
  } = getFormSubmissionInfo(target, basename);
8656
8169
  if (options.navigate === false) {
8657
8170
  let key = options.fetcherKey || getUniqueFetcherId();
8658
- router.fetch(key, currentRouteId, options.action || action, {
8171
+ await router.fetch(key, currentRouteId, options.action || action, {
8659
8172
  preventScrollReset: options.preventScrollReset,
8660
8173
  formData,
8661
8174
  body,
@@ -8664,7 +8177,7 @@ function useSubmit() {
8664
8177
  unstable_flushSync: options.unstable_flushSync
8665
8178
  });
8666
8179
  } else {
8667
- router.navigate(options.action || action, {
8180
+ await router.navigate(options.action || action, {
8668
8181
  preventScrollReset: options.preventScrollReset,
8669
8182
  formData,
8670
8183
  body,
@@ -8767,13 +8280,13 @@ function useFetcher(_temp3) {
8767
8280
  };
8768
8281
  }, [router, fetcherKey]);
8769
8282
  // Fetcher additions
8770
- let load = React.useCallback((href, opts) => {
8283
+ let load = React.useCallback(async (href, opts) => {
8771
8284
  !routeId ? process.env.NODE_ENV !== "production" ? invariant$1(false, "No routeId available for fetcher.load()") : invariant$1(false) : void 0;
8772
- router.fetch(fetcherKey, routeId, href, opts);
8285
+ await router.fetch(fetcherKey, routeId, href, opts);
8773
8286
  }, [fetcherKey, routeId, router]);
8774
8287
  let submitImpl = useSubmit();
8775
- let submit = React.useCallback((target, opts) => {
8776
- submitImpl(target, _extends({}, opts, {
8288
+ let submit = React.useCallback(async (target, opts) => {
8289
+ await submitImpl(target, _extends({}, opts, {
8777
8290
  navigate: false,
8778
8291
  fetcherKey
8779
8292
  }));
@@ -9610,26 +9123,19 @@ function createClientRoutes(manifest, routeModulesCache, initialState, future, i
9610
9123
  }
9611
9124
  return (routesByParentId[parentId] || []).map(route => {
9612
9125
  let routeModule = routeModulesCache[route.id];
9613
- // Fetch data from the server either via single fetch or the standard `?_data`
9614
- // request. Unwrap it when called via `serverLoader`/`serverAction` in a
9615
- // client handler, otherwise return the raw response for the router to unwrap
9616
- async function fetchServerHandlerAndMaybeUnwrap(request, unwrap, singleFetch) {
9617
- if (typeof singleFetch === "function") {
9618
- let result = await singleFetch();
9619
- return result;
9620
- }
9621
- let result = await fetchServerHandler(request, route);
9622
- return unwrap ? unwrapServerResponse(result) : result;
9126
+ function fetchServerHandler(singleFetch) {
9127
+ !(typeof singleFetch === "function") ? process.env.NODE_ENV !== "production" ? invariant(false, "No single fetch function available for route handler") : invariant(false) : void 0;
9128
+ return singleFetch();
9623
9129
  }
9624
- function fetchServerLoader(request, unwrap, singleFetch) {
9130
+ function fetchServerLoader(singleFetch) {
9625
9131
  if (!route.hasLoader) return Promise.resolve(null);
9626
- return fetchServerHandlerAndMaybeUnwrap(request, unwrap, singleFetch);
9132
+ return fetchServerHandler(singleFetch);
9627
9133
  }
9628
- function fetchServerAction(request, unwrap, singleFetch) {
9134
+ function fetchServerAction(singleFetch) {
9629
9135
  if (!route.hasAction) {
9630
9136
  throw noActionDefinedError("action", route.id);
9631
9137
  }
9632
- return fetchServerHandlerAndMaybeUnwrap(request, unwrap, singleFetch);
9138
+ return fetchServerHandler(singleFetch);
9633
9139
  }
9634
9140
  async function prefetchStylesAndCallHandler(handler) {
9635
9141
  // Only prefetch links if we exist in the routeModulesCache (critical modules
@@ -9670,7 +9176,7 @@ function createClientRoutes(manifest, routeModulesCache, initialState, future, i
9670
9176
  if (!routeModule.clientLoader) {
9671
9177
  if (isSpaMode) return null;
9672
9178
  // Call the server when no client loader exists
9673
- return fetchServerLoader(request, false, singleFetch);
9179
+ return fetchServerLoader(singleFetch);
9674
9180
  }
9675
9181
  return routeModule.clientLoader({
9676
9182
  request,
@@ -9685,7 +9191,7 @@ function createClientRoutes(manifest, routeModulesCache, initialState, future, i
9685
9191
  return initialData;
9686
9192
  }
9687
9193
  // Call the server loader for client-side navigations
9688
- return fetchServerLoader(request, true, singleFetch);
9194
+ return fetchServerLoader(singleFetch);
9689
9195
  }
9690
9196
  });
9691
9197
  });
@@ -9709,14 +9215,14 @@ function createClientRoutes(manifest, routeModulesCache, initialState, future, i
9709
9215
  if (isSpaMode) {
9710
9216
  throw noActionDefinedError("clientAction", route.id);
9711
9217
  }
9712
- return fetchServerAction(request, false, singleFetch);
9218
+ return fetchServerAction(singleFetch);
9713
9219
  }
9714
9220
  return routeModule.clientAction({
9715
9221
  request,
9716
9222
  params,
9717
9223
  async serverAction() {
9718
9224
  preventInvalidServerHandlerCall("action", route, isSpaMode);
9719
- return fetchServerAction(request, true, singleFetch);
9225
+ return fetchServerAction(singleFetch);
9720
9226
  }
9721
9227
  });
9722
9228
  });
@@ -9727,25 +9233,19 @@ function createClientRoutes(manifest, routeModulesCache, initialState, future, i
9727
9233
  // loader/action as static props on the route
9728
9234
  if (!route.hasClientLoader) {
9729
9235
  dataRoute.loader = (_ref3, singleFetch) => {
9730
- let {
9731
- request
9732
- } = _ref3;
9733
9236
  return prefetchStylesAndCallHandler(() => {
9734
9237
  if (isSpaMode) return Promise.resolve(null);
9735
- return fetchServerLoader(request, false, singleFetch);
9238
+ return fetchServerLoader(singleFetch);
9736
9239
  });
9737
9240
  };
9738
9241
  }
9739
9242
  if (!route.hasClientAction) {
9740
9243
  dataRoute.action = (_ref4, singleFetch) => {
9741
- let {
9742
- request
9743
- } = _ref4;
9744
9244
  return prefetchStylesAndCallHandler(() => {
9745
9245
  if (isSpaMode) {
9746
9246
  throw noActionDefinedError("clientAction", route.id);
9747
9247
  }
9748
- return fetchServerAction(request, false, singleFetch);
9248
+ return fetchServerAction(singleFetch);
9749
9249
  });
9750
9250
  };
9751
9251
  }
@@ -9758,7 +9258,7 @@ function createClientRoutes(manifest, routeModulesCache, initialState, future, i
9758
9258
  lazyRoute.loader = (args, singleFetch) => clientLoader(_extends({}, args, {
9759
9259
  async serverLoader() {
9760
9260
  preventInvalidServerHandlerCall("loader", route, isSpaMode);
9761
- return fetchServerLoader(args.request, true, singleFetch);
9261
+ return fetchServerLoader(singleFetch);
9762
9262
  }
9763
9263
  }));
9764
9264
  }
@@ -9767,7 +9267,7 @@ function createClientRoutes(manifest, routeModulesCache, initialState, future, i
9767
9267
  lazyRoute.action = (args, singleFetch) => clientAction(_extends({}, args, {
9768
9268
  async serverAction() {
9769
9269
  preventInvalidServerHandlerCall("action", route, isSpaMode);
9770
- return fetchServerAction(args.request, true, singleFetch);
9270
+ return fetchServerAction(singleFetch);
9771
9271
  }
9772
9272
  }));
9773
9273
  }
@@ -9822,55 +9322,6 @@ async function loadRouteModuleWithBlockingLinks(route, routeModules) {
9822
9322
  shouldRevalidate: routeModule.shouldRevalidate
9823
9323
  };
9824
9324
  }
9825
- async function fetchServerHandler(request, route) {
9826
- let result = await fetchData(request, route.id);
9827
- if (result instanceof Error) {
9828
- throw result;
9829
- }
9830
- if (isRedirectResponse(result)) {
9831
- throw getRedirect(result);
9832
- }
9833
- if (isCatchResponse(result)) {
9834
- throw result;
9835
- }
9836
- if (isDeferredResponse(result) && result.body) {
9837
- return await parseDeferredReadableStream(result.body);
9838
- }
9839
- return result;
9840
- }
9841
- function unwrapServerResponse(result) {
9842
- if (isDeferredData(result)) {
9843
- return result.data;
9844
- }
9845
- if (isResponse(result)) {
9846
- let contentType = result.headers.get("Content-Type");
9847
- // Check between word boundaries instead of startsWith() due to the last
9848
- // paragraph of https://httpwg.org/specs/rfc9110.html#field.content-type
9849
- if (contentType && /\bapplication\/json\b/.test(contentType)) {
9850
- return result.json();
9851
- } else {
9852
- return result.text();
9853
- }
9854
- }
9855
- return result;
9856
- }
9857
- function getRedirect(response) {
9858
- let status = parseInt(response.headers.get("X-Remix-Status"), 10) || 302;
9859
- let url = response.headers.get("X-Remix-Redirect");
9860
- let headers = {};
9861
- let revalidate = response.headers.get("X-Remix-Revalidate");
9862
- if (revalidate) {
9863
- headers["X-Remix-Revalidate"] = revalidate;
9864
- }
9865
- let reloadDocument = response.headers.get("X-Remix-Reload-Document");
9866
- if (reloadDocument) {
9867
- headers["X-Remix-Reload-Document"] = reloadDocument;
9868
- }
9869
- return redirect(url, {
9870
- status,
9871
- headers
9872
- });
9873
- }
9874
9325
  // Our compiler generates the default export as `{}` when no default is provided,
9875
9326
  // which can lead us to trying to use that as a Component in RR and calling
9876
9327
  // createElement on it. Patching here as a quick fix and hoping it's no longer
@@ -9985,30 +9436,28 @@ function createHydratedRouter() {
9985
9436
  }
9986
9437
  // TODO: Do some testing to confirm it's OK to skip the hard reload check
9987
9438
  // now that all route.lazy stuff is wired up
9988
- // When single fetch is enabled, we need to suspend until the initial state
9989
- // snapshot is decoded into window.__remixContext.state
9990
- if (ssrInfo.context.future.unstable_singleFetch) {
9991
- let localSsrInfo = ssrInfo;
9992
- // Note: `stateDecodingPromise` is not coupled to `router` - we'll reach this
9993
- // code potentially many times waiting for our state to arrive, but we'll
9994
- // then only get past here and create the `router` one time
9995
- if (!ssrInfo.stateDecodingPromise) {
9996
- let stream = ssrInfo.context.stream;
9997
- !stream ? process.env.NODE_ENV !== "production" ? invariant(false, "No stream found for single fetch decoding") : invariant(false) : void 0;
9998
- ssrInfo.context.stream = undefined;
9999
- ssrInfo.stateDecodingPromise = decodeViaTurboStream(stream, window).then(value => {
10000
- ssrInfo.context.state = value.value;
10001
- localSsrInfo.stateDecodingPromise.value = true;
10002
- }).catch(e => {
10003
- localSsrInfo.stateDecodingPromise.error = e;
10004
- });
10005
- }
10006
- if (ssrInfo.stateDecodingPromise.error) {
10007
- throw ssrInfo.stateDecodingPromise.error;
10008
- }
10009
- if (!ssrInfo.stateDecodingPromise.value) {
10010
- throw ssrInfo.stateDecodingPromise;
10011
- }
9439
+ // We need to suspend until the initial state snapshot is decoded into
9440
+ // window.__remixContext.state
9441
+ let localSsrInfo = ssrInfo;
9442
+ // Note: `stateDecodingPromise` is not coupled to `router` - we'll reach this
9443
+ // code potentially many times waiting for our state to arrive, but we'll
9444
+ // then only get past here and create the `router` one time
9445
+ if (!ssrInfo.stateDecodingPromise) {
9446
+ let stream = ssrInfo.context.stream;
9447
+ !stream ? process.env.NODE_ENV !== "production" ? invariant(false, "No stream found for single fetch decoding") : invariant(false) : void 0;
9448
+ ssrInfo.context.stream = undefined;
9449
+ ssrInfo.stateDecodingPromise = decodeViaTurboStream(stream, window).then(value => {
9450
+ ssrInfo.context.state = value.value;
9451
+ localSsrInfo.stateDecodingPromise.value = true;
9452
+ }).catch(e => {
9453
+ localSsrInfo.stateDecodingPromise.error = e;
9454
+ });
9455
+ }
9456
+ if (ssrInfo.stateDecodingPromise.error) {
9457
+ throw ssrInfo.stateDecodingPromise.error;
9458
+ }
9459
+ if (!ssrInfo.stateDecodingPromise.value) {
9460
+ throw ssrInfo.stateDecodingPromise;
10012
9461
  }
10013
9462
  let routes = createClientRoutes(ssrInfo.manifest.routes, ssrInfo.routeModules, ssrInfo.context.state, ssrInfo.context.future, ssrInfo.context.isSpaMode);
10014
9463
  let hydrationData = undefined;
@@ -10063,11 +9512,11 @@ function createHydratedRouter() {
10063
9512
  v7_prependBasename: true,
10064
9513
  v7_relativeSplatPath: ssrInfo.context.future.v3_relativeSplatPath,
10065
9514
  // Single fetch enables this underlying behavior
10066
- unstable_skipActionErrorRevalidation: ssrInfo.context.future.unstable_singleFetch === true
9515
+ unstable_skipActionErrorRevalidation: true
10067
9516
  },
10068
9517
  hydrationData,
10069
9518
  mapRouteProperties,
10070
- unstable_dataStrategy: ssrInfo.context.future.unstable_singleFetch ? getSingleFetchDataStrategy(ssrInfo.manifest, ssrInfo.routeModules) : undefined
9519
+ unstable_dataStrategy: getSingleFetchDataStrategy(ssrInfo.manifest, ssrInfo.routeModules)
10071
9520
  });
10072
9521
  ssrInfo.router = router;
10073
9522
  // We can call initialize() immediately if the router doesn't have any
@@ -10140,7 +9589,7 @@ function HydratedRouter() {
10140
9589
  future: {
10141
9590
  v7_startTransition: true
10142
9591
  }
10143
- }))), ssrInfo.context.future.unstable_singleFetch ? /*#__PURE__*/React.createElement(React.Fragment, null) : null)
9592
+ }))), /*#__PURE__*/React.createElement(React.Fragment, null))
10144
9593
  );
10145
9594
  }
10146
9595
 
@@ -10207,7 +9656,7 @@ function RemixServer(_ref) {
10207
9656
  router: router,
10208
9657
  context: context.staticHandlerContext,
10209
9658
  hydrate: false
10210
- }))), context.future.unstable_singleFetch && context.serverHandoffStream ? ( /*#__PURE__*/React.createElement(React.Suspense, null, /*#__PURE__*/React.createElement(StreamTransfer, {
9659
+ }))), context.serverHandoffStream ? ( /*#__PURE__*/React.createElement(React.Suspense, null, /*#__PURE__*/React.createElement(StreamTransfer, {
10211
9660
  context: context,
10212
9661
  identifier: 0,
10213
9662
  reader: context.serverHandoffStream.getReader(),
@@ -10232,8 +9681,7 @@ function createRemixStub(routes, context) {
10232
9681
  remixContextRef.current = {
10233
9682
  future: {
10234
9683
  v3_fetcherPersist: (future == null ? void 0 : future.v3_fetcherPersist) === true,
10235
- v3_relativeSplatPath: (future == null ? void 0 : future.v3_relativeSplatPath) === true,
10236
- unstable_singleFetch: (future == null ? void 0 : future.unstable_singleFetch) === true
9684
+ v3_relativeSplatPath: (future == null ? void 0 : future.v3_relativeSplatPath) === true
10237
9685
  },
10238
9686
  manifest: {
10239
9687
  routes: {},