@remix-run/router 1.2.1 → 1.3.0-pre.1
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 +18 -0
- package/dist/history.d.ts +6 -1
- package/dist/index.d.ts +1 -2
- package/dist/router.cjs.js +177 -90
- package/dist/router.cjs.js.map +1 -1
- package/dist/router.d.ts +3 -0
- package/dist/router.js +176 -91
- package/dist/router.js.map +1 -1
- package/dist/router.umd.js +177 -90
- package/dist/router.umd.js.map +1 -1
- package/dist/router.umd.min.js +2 -2
- package/dist/router.umd.min.js.map +1 -1
- package/dist/utils.d.ts +14 -7
- package/history.ts +33 -23
- package/index.ts +3 -3
- package/package.json +1 -1
- package/router.ts +95 -39
- package/utils.ts +88 -42
package/dist/router.umd.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @remix-run/router v1.
|
|
2
|
+
* @remix-run/router v1.3.0-pre.1
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -98,6 +98,10 @@
|
|
|
98
98
|
return location;
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
function createHref(to) {
|
|
102
|
+
return typeof to === "string" ? to : createPath(to);
|
|
103
|
+
}
|
|
104
|
+
|
|
101
105
|
let history = {
|
|
102
106
|
get index() {
|
|
103
107
|
return index;
|
|
@@ -111,8 +115,10 @@
|
|
|
111
115
|
return getCurrentLocation();
|
|
112
116
|
},
|
|
113
117
|
|
|
114
|
-
createHref
|
|
115
|
-
|
|
118
|
+
createHref,
|
|
119
|
+
|
|
120
|
+
createURL(to) {
|
|
121
|
+
return new URL(createHref(to), "http://localhost");
|
|
116
122
|
},
|
|
117
123
|
|
|
118
124
|
encodeLocation(to) {
|
|
@@ -391,15 +397,6 @@
|
|
|
391
397
|
|
|
392
398
|
return parsedPath;
|
|
393
399
|
}
|
|
394
|
-
function createClientSideURL(location) {
|
|
395
|
-
// window.location.origin is "null" (the literal string value) in Firefox
|
|
396
|
-
// under certain conditions, notably when serving from a local HTML file
|
|
397
|
-
// See https://bugzilla.mozilla.org/show_bug.cgi?id=878297
|
|
398
|
-
let base = typeof window !== "undefined" && typeof window.location !== "undefined" && window.location.origin !== "null" ? window.location.origin : window.location.href;
|
|
399
|
-
let href = typeof location === "string" ? location : createPath(location);
|
|
400
|
-
invariant(base, "No window.location.(origin|href) available to create URL for href: " + href);
|
|
401
|
-
return new URL(href, base);
|
|
402
|
-
}
|
|
403
400
|
|
|
404
401
|
function getUrlBasedHistory(getLocation, createHref, validateLocation, options) {
|
|
405
402
|
if (options === void 0) {
|
|
@@ -464,6 +461,16 @@
|
|
|
464
461
|
}
|
|
465
462
|
}
|
|
466
463
|
|
|
464
|
+
function createURL(to) {
|
|
465
|
+
// window.location.origin is "null" (the literal string value) in Firefox
|
|
466
|
+
// under certain conditions, notably when serving from a local HTML file
|
|
467
|
+
// See https://bugzilla.mozilla.org/show_bug.cgi?id=878297
|
|
468
|
+
let base = window.location.origin !== "null" ? window.location.origin : window.location.href;
|
|
469
|
+
let href = typeof to === "string" ? to : createPath(to);
|
|
470
|
+
invariant(base, "No window.location.(origin|href) available to create URL for href: " + href);
|
|
471
|
+
return new URL(href, base);
|
|
472
|
+
}
|
|
473
|
+
|
|
467
474
|
let history = {
|
|
468
475
|
get action() {
|
|
469
476
|
return action;
|
|
@@ -490,9 +497,11 @@
|
|
|
490
497
|
return createHref(window, to);
|
|
491
498
|
},
|
|
492
499
|
|
|
500
|
+
createURL,
|
|
501
|
+
|
|
493
502
|
encodeLocation(to) {
|
|
494
503
|
// Encode a Location the same way window.location would
|
|
495
|
-
let url =
|
|
504
|
+
let url = createURL(to);
|
|
496
505
|
return {
|
|
497
506
|
pathname: url.pathname,
|
|
498
507
|
search: url.search,
|
|
@@ -809,13 +818,32 @@
|
|
|
809
818
|
path = path.replace(/\*$/, "/*");
|
|
810
819
|
}
|
|
811
820
|
|
|
812
|
-
return path.replace(/^:(\w+)/g, (_, key) => {
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
821
|
+
return path.replace(/^:(\w+)(\??)/g, (_, key, optional) => {
|
|
822
|
+
let param = params[key];
|
|
823
|
+
|
|
824
|
+
if (optional === "?") {
|
|
825
|
+
return param == null ? "" : param;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
if (param == null) {
|
|
829
|
+
invariant(false, "Missing \":" + key + "\" param");
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
return param;
|
|
833
|
+
}).replace(/\/:(\w+)(\??)/g, (_, key, optional) => {
|
|
834
|
+
let param = params[key];
|
|
835
|
+
|
|
836
|
+
if (optional === "?") {
|
|
837
|
+
return param == null ? "" : "/" + param;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
if (param == null) {
|
|
841
|
+
invariant(false, "Missing \":" + key + "\" param");
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
return "/" + param;
|
|
845
|
+
}) // Remove any optional markers from optional static segments
|
|
846
|
+
.replace(/\?/g, "").replace(/(\/?)\*/, (_, prefix, __, str) => {
|
|
819
847
|
const star = "*";
|
|
820
848
|
|
|
821
849
|
if (params[star] == null) {
|
|
@@ -1162,9 +1190,10 @@
|
|
|
1162
1190
|
};
|
|
1163
1191
|
class AbortedDeferredError extends Error {}
|
|
1164
1192
|
class DeferredData {
|
|
1165
|
-
constructor(data) {
|
|
1166
|
-
this.
|
|
1167
|
-
this.
|
|
1193
|
+
constructor(data, responseInit) {
|
|
1194
|
+
this.pendingKeysSet = new Set();
|
|
1195
|
+
this.subscribers = new Set();
|
|
1196
|
+
this.deferredKeys = [];
|
|
1168
1197
|
invariant(data && typeof data === "object" && !Array.isArray(data), "defer() only accepts plain objects"); // Set up an AbortController + Promise we can race against to exit early
|
|
1169
1198
|
// cancellation
|
|
1170
1199
|
|
|
@@ -1183,6 +1212,7 @@
|
|
|
1183
1212
|
[key]: this.trackPromise(key, value)
|
|
1184
1213
|
});
|
|
1185
1214
|
}, {});
|
|
1215
|
+
this.init = responseInit;
|
|
1186
1216
|
}
|
|
1187
1217
|
|
|
1188
1218
|
trackPromise(key, value) {
|
|
@@ -1190,7 +1220,8 @@
|
|
|
1190
1220
|
return value;
|
|
1191
1221
|
}
|
|
1192
1222
|
|
|
1193
|
-
this.
|
|
1223
|
+
this.deferredKeys.push(key);
|
|
1224
|
+
this.pendingKeysSet.add(key); // We store a little wrapper promise that will be extended with
|
|
1194
1225
|
// _data/_error props upon resolve/reject
|
|
1195
1226
|
|
|
1196
1227
|
let promise = Promise.race([value, this.abortPromise]).then(data => this.onSettle(promise, key, null, data), error => this.onSettle(promise, key, error)); // Register rejection listeners to avoid uncaught promise rejections on
|
|
@@ -1212,39 +1243,41 @@
|
|
|
1212
1243
|
return Promise.reject(error);
|
|
1213
1244
|
}
|
|
1214
1245
|
|
|
1215
|
-
this.
|
|
1246
|
+
this.pendingKeysSet.delete(key);
|
|
1216
1247
|
|
|
1217
1248
|
if (this.done) {
|
|
1218
1249
|
// Nothing left to abort!
|
|
1219
1250
|
this.unlistenAbortSignal();
|
|
1220
1251
|
}
|
|
1221
1252
|
|
|
1222
|
-
const subscriber = this.subscriber;
|
|
1223
|
-
|
|
1224
1253
|
if (error) {
|
|
1225
1254
|
Object.defineProperty(promise, "_error", {
|
|
1226
1255
|
get: () => error
|
|
1227
1256
|
});
|
|
1228
|
-
|
|
1257
|
+
this.emit(false, key);
|
|
1229
1258
|
return Promise.reject(error);
|
|
1230
1259
|
}
|
|
1231
1260
|
|
|
1232
1261
|
Object.defineProperty(promise, "_data", {
|
|
1233
1262
|
get: () => data
|
|
1234
1263
|
});
|
|
1235
|
-
|
|
1264
|
+
this.emit(false, key);
|
|
1236
1265
|
return data;
|
|
1237
1266
|
}
|
|
1238
1267
|
|
|
1268
|
+
emit(aborted, settledKey) {
|
|
1269
|
+
this.subscribers.forEach(subscriber => subscriber(aborted, settledKey));
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1239
1272
|
subscribe(fn) {
|
|
1240
|
-
this.
|
|
1273
|
+
this.subscribers.add(fn);
|
|
1274
|
+
return () => this.subscribers.delete(fn);
|
|
1241
1275
|
}
|
|
1242
1276
|
|
|
1243
1277
|
cancel() {
|
|
1244
1278
|
this.controller.abort();
|
|
1245
|
-
this.
|
|
1246
|
-
|
|
1247
|
-
subscriber && subscriber(true);
|
|
1279
|
+
this.pendingKeysSet.forEach((v, k) => this.pendingKeysSet.delete(k));
|
|
1280
|
+
this.emit(true);
|
|
1248
1281
|
}
|
|
1249
1282
|
|
|
1250
1283
|
async resolveData(signal) {
|
|
@@ -1269,7 +1302,7 @@
|
|
|
1269
1302
|
}
|
|
1270
1303
|
|
|
1271
1304
|
get done() {
|
|
1272
|
-
return this.
|
|
1305
|
+
return this.pendingKeysSet.size === 0;
|
|
1273
1306
|
}
|
|
1274
1307
|
|
|
1275
1308
|
get unwrappedData() {
|
|
@@ -1282,6 +1315,10 @@
|
|
|
1282
1315
|
}, {});
|
|
1283
1316
|
}
|
|
1284
1317
|
|
|
1318
|
+
get pendingKeys() {
|
|
1319
|
+
return Array.from(this.pendingKeysSet);
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1285
1322
|
}
|
|
1286
1323
|
|
|
1287
1324
|
function isTrackedPromise(value) {
|
|
@@ -1300,9 +1337,16 @@
|
|
|
1300
1337
|
return value._data;
|
|
1301
1338
|
}
|
|
1302
1339
|
|
|
1303
|
-
function defer(data) {
|
|
1304
|
-
|
|
1305
|
-
|
|
1340
|
+
const defer = function defer(data, init) {
|
|
1341
|
+
if (init === void 0) {
|
|
1342
|
+
init = {};
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
let responseInit = typeof init === "number" ? {
|
|
1346
|
+
status: init
|
|
1347
|
+
} : init;
|
|
1348
|
+
return new DeferredData(data, responseInit);
|
|
1349
|
+
};
|
|
1306
1350
|
|
|
1307
1351
|
/**
|
|
1308
1352
|
* A redirect response. Sets the status code and the `Location` header.
|
|
@@ -1548,7 +1592,7 @@
|
|
|
1548
1592
|
|
|
1549
1593
|
|
|
1550
1594
|
function completeNavigation(location, newState) {
|
|
1551
|
-
var _location$state;
|
|
1595
|
+
var _location$state, _location$state2;
|
|
1552
1596
|
|
|
1553
1597
|
// Deduce if we're in a loading/actionReload state:
|
|
1554
1598
|
// - We have committed actionData in the store
|
|
@@ -1574,7 +1618,10 @@
|
|
|
1574
1618
|
} // Always preserve any existing loaderData from re-used routes
|
|
1575
1619
|
|
|
1576
1620
|
|
|
1577
|
-
let loaderData = newState.loaderData ? mergeLoaderData(state.loaderData, newState.loaderData, newState.matches || [], newState.errors) : state.loaderData;
|
|
1621
|
+
let loaderData = newState.loaderData ? mergeLoaderData(state.loaderData, newState.loaderData, newState.matches || [], newState.errors) : state.loaderData; // Always respect the user flag. Otherwise don't reset on mutation
|
|
1622
|
+
// submission navigations unless they redirect
|
|
1623
|
+
|
|
1624
|
+
let preventScrollReset = pendingPreventScrollReset === true || state.navigation.formMethod != null && isMutationMethod(state.navigation.formMethod) && ((_location$state2 = location.state) == null ? void 0 : _location$state2._isRedirect) !== true;
|
|
1578
1625
|
updateState(_extends({}, newState, {
|
|
1579
1626
|
// matches, errors, fetchers go through as-is
|
|
1580
1627
|
actionData,
|
|
@@ -1584,9 +1631,8 @@
|
|
|
1584
1631
|
initialized: true,
|
|
1585
1632
|
navigation: IDLE_NAVIGATION,
|
|
1586
1633
|
revalidation: "idle",
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
preventScrollReset: pendingPreventScrollReset
|
|
1634
|
+
restoreScrollPosition: getSavedScrollPosition(location, newState.matches || state.matches),
|
|
1635
|
+
preventScrollReset
|
|
1590
1636
|
}));
|
|
1591
1637
|
|
|
1592
1638
|
if (isUninterruptedRevalidation) ; else if (pendingAction === exports.Action.Pop) ; else if (pendingAction === exports.Action.Push) {
|
|
@@ -1728,7 +1774,7 @@
|
|
|
1728
1774
|
|
|
1729
1775
|
|
|
1730
1776
|
pendingNavigationController = new AbortController();
|
|
1731
|
-
let request = createClientSideRequest(location, pendingNavigationController.signal, opts && opts.submission);
|
|
1777
|
+
let request = createClientSideRequest(init.history, location, pendingNavigationController.signal, opts && opts.submission);
|
|
1732
1778
|
let pendingActionData;
|
|
1733
1779
|
let pendingError;
|
|
1734
1780
|
|
|
@@ -1869,7 +1915,9 @@
|
|
|
1869
1915
|
}
|
|
1870
1916
|
|
|
1871
1917
|
if (isDeferredResult(result)) {
|
|
1872
|
-
throw
|
|
1918
|
+
throw getInternalRouterError(400, {
|
|
1919
|
+
type: "defer-action"
|
|
1920
|
+
});
|
|
1873
1921
|
}
|
|
1874
1922
|
|
|
1875
1923
|
return {
|
|
@@ -1906,7 +1954,7 @@
|
|
|
1906
1954
|
formData: loadingNavigation.formData,
|
|
1907
1955
|
formEncType: loadingNavigation.formEncType
|
|
1908
1956
|
} : undefined;
|
|
1909
|
-
let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(state, matches, activeSubmission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, pendingActionData, pendingError, fetchLoadMatches); // Cancel pending deferreds for no-longer-matched routes or routes we're
|
|
1957
|
+
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
|
|
1910
1958
|
// about to reload. Note that if this is an action reload we would have
|
|
1911
1959
|
// already cancelled all pending deferreds so this would be a no-op
|
|
1912
1960
|
|
|
@@ -2088,7 +2136,7 @@
|
|
|
2088
2136
|
}); // Call the action for the fetcher
|
|
2089
2137
|
|
|
2090
2138
|
let abortController = new AbortController();
|
|
2091
|
-
let fetchRequest = createClientSideRequest(path, abortController.signal, submission);
|
|
2139
|
+
let fetchRequest = createClientSideRequest(init.history, path, abortController.signal, submission);
|
|
2092
2140
|
fetchControllers.set(key, abortController);
|
|
2093
2141
|
let actionResult = await callLoaderOrAction("action", fetchRequest, match, requestMatches, router.basename);
|
|
2094
2142
|
|
|
@@ -2129,13 +2177,15 @@
|
|
|
2129
2177
|
}
|
|
2130
2178
|
|
|
2131
2179
|
if (isDeferredResult(actionResult)) {
|
|
2132
|
-
|
|
2180
|
+
throw getInternalRouterError(400, {
|
|
2181
|
+
type: "defer-action"
|
|
2182
|
+
});
|
|
2133
2183
|
} // Start the data load for current matches, or the next location if we're
|
|
2134
2184
|
// in the middle of a navigation
|
|
2135
2185
|
|
|
2136
2186
|
|
|
2137
2187
|
let nextLocation = state.navigation.location || state.location;
|
|
2138
|
-
let revalidationRequest = createClientSideRequest(nextLocation, abortController.signal);
|
|
2188
|
+
let revalidationRequest = createClientSideRequest(init.history, nextLocation, abortController.signal);
|
|
2139
2189
|
let matches = state.navigation.state !== "idle" ? matchRoutes(dataRoutes, state.navigation.location, init.basename) : state.matches;
|
|
2140
2190
|
invariant(matches, "Didn't find any matches after fetcher action");
|
|
2141
2191
|
let loadId = ++incrementingLoadId;
|
|
@@ -2149,7 +2199,7 @@
|
|
|
2149
2199
|
});
|
|
2150
2200
|
|
|
2151
2201
|
state.fetchers.set(key, loadFetcher);
|
|
2152
|
-
let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(state, matches, submission, nextLocation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, {
|
|
2202
|
+
let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, submission, nextLocation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, {
|
|
2153
2203
|
[match.route.id]: actionResult.data
|
|
2154
2204
|
}, undefined, // No need to send through errors since we short circuit above
|
|
2155
2205
|
fetchLoadMatches); // Put all revalidating fetchers into the loading state, except for the
|
|
@@ -2262,9 +2312,9 @@
|
|
|
2262
2312
|
}); // Call the loader for this fetcher route match
|
|
2263
2313
|
|
|
2264
2314
|
let abortController = new AbortController();
|
|
2265
|
-
let fetchRequest = createClientSideRequest(path, abortController.signal);
|
|
2315
|
+
let fetchRequest = createClientSideRequest(init.history, path, abortController.signal);
|
|
2266
2316
|
fetchControllers.set(key, abortController);
|
|
2267
|
-
let result = await callLoaderOrAction("loader", fetchRequest, match, matches, router.basename); // Deferred isn't supported
|
|
2317
|
+
let result = await callLoaderOrAction("loader", fetchRequest, match, matches, router.basename); // Deferred isn't supported for fetcher loads, await everything and treat it
|
|
2268
2318
|
// as a normal load. resolveDeferredData will return undefined if this
|
|
2269
2319
|
// fetcher gets aborted, so we just leave result untouched and short circuit
|
|
2270
2320
|
// below if that happens
|
|
@@ -2364,7 +2414,7 @@
|
|
|
2364
2414
|
invariant(redirectLocation, "Expected a location on the redirect navigation"); // Check if this an external redirect that goes to a new origin
|
|
2365
2415
|
|
|
2366
2416
|
if (typeof ((_window = window) == null ? void 0 : _window.location) !== "undefined") {
|
|
2367
|
-
let newOrigin =
|
|
2417
|
+
let newOrigin = init.history.createURL(redirect.location).origin;
|
|
2368
2418
|
|
|
2369
2419
|
if (window.location.origin !== newOrigin) {
|
|
2370
2420
|
if (replace) {
|
|
@@ -2406,7 +2456,9 @@
|
|
|
2406
2456
|
await startNavigation(redirectHistoryAction, redirectLocation, {
|
|
2407
2457
|
submission: _extends({}, submission, {
|
|
2408
2458
|
formAction: redirect.location
|
|
2409
|
-
})
|
|
2459
|
+
}),
|
|
2460
|
+
// Preserve this flag across redirects
|
|
2461
|
+
preventScrollReset: pendingPreventScrollReset
|
|
2410
2462
|
});
|
|
2411
2463
|
} else {
|
|
2412
2464
|
// Otherwise, we kick off a new loading navigation, preserving the
|
|
@@ -2419,7 +2471,9 @@
|
|
|
2419
2471
|
formAction: submission ? submission.formAction : undefined,
|
|
2420
2472
|
formEncType: submission ? submission.formEncType : undefined,
|
|
2421
2473
|
formData: submission ? submission.formData : undefined
|
|
2422
|
-
}
|
|
2474
|
+
},
|
|
2475
|
+
// Preserve this flag across redirects
|
|
2476
|
+
preventScrollReset: pendingPreventScrollReset
|
|
2423
2477
|
});
|
|
2424
2478
|
}
|
|
2425
2479
|
}
|
|
@@ -2430,7 +2484,7 @@
|
|
|
2430
2484
|
// accordingly
|
|
2431
2485
|
let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, router.basename)), ...fetchersToLoad.map(_ref8 => {
|
|
2432
2486
|
let [, href, match, fetchMatches] = _ref8;
|
|
2433
|
-
return callLoaderOrAction("loader", createClientSideRequest(href, request.signal), match, fetchMatches, router.basename);
|
|
2487
|
+
return callLoaderOrAction("loader", createClientSideRequest(init.history, href, request.signal), match, fetchMatches, router.basename);
|
|
2434
2488
|
})]);
|
|
2435
2489
|
let loaderResults = results.slice(0, matchesToLoad.length);
|
|
2436
2490
|
let fetcherResults = results.slice(matchesToLoad.length);
|
|
@@ -2639,6 +2693,7 @@
|
|
|
2639
2693
|
//#region createStaticHandler
|
|
2640
2694
|
////////////////////////////////////////////////////////////////////////////////
|
|
2641
2695
|
|
|
2696
|
+
const UNSAFE_DEFERRED_SYMBOL = Symbol("deferred");
|
|
2642
2697
|
function createStaticHandler(routes, opts) {
|
|
2643
2698
|
invariant(routes.length > 0, "You must provide a non-empty routes array to createStaticHandler");
|
|
2644
2699
|
let dataRoutes = convertRoutesToDataRoutes(routes);
|
|
@@ -2691,7 +2746,8 @@
|
|
|
2691
2746
|
},
|
|
2692
2747
|
statusCode: error.status,
|
|
2693
2748
|
loaderHeaders: {},
|
|
2694
|
-
actionHeaders: {}
|
|
2749
|
+
actionHeaders: {},
|
|
2750
|
+
activeDeferreds: null
|
|
2695
2751
|
};
|
|
2696
2752
|
} else if (!matches) {
|
|
2697
2753
|
let error = getInternalRouterError(404, {
|
|
@@ -2712,7 +2768,8 @@
|
|
|
2712
2768
|
},
|
|
2713
2769
|
statusCode: error.status,
|
|
2714
2770
|
loaderHeaders: {},
|
|
2715
|
-
actionHeaders: {}
|
|
2771
|
+
actionHeaders: {},
|
|
2772
|
+
activeDeferreds: null
|
|
2716
2773
|
};
|
|
2717
2774
|
}
|
|
2718
2775
|
|
|
@@ -2803,8 +2860,23 @@
|
|
|
2803
2860
|
} // Pick off the right state value to return
|
|
2804
2861
|
|
|
2805
2862
|
|
|
2806
|
-
|
|
2807
|
-
|
|
2863
|
+
if (result.actionData) {
|
|
2864
|
+
return Object.values(result.actionData)[0];
|
|
2865
|
+
}
|
|
2866
|
+
|
|
2867
|
+
if (result.loaderData) {
|
|
2868
|
+
var _result$activeDeferre;
|
|
2869
|
+
|
|
2870
|
+
let data = Object.values(result.loaderData)[0];
|
|
2871
|
+
|
|
2872
|
+
if ((_result$activeDeferre = result.activeDeferreds) != null && _result$activeDeferre[match.route.id]) {
|
|
2873
|
+
data[UNSAFE_DEFERRED_SYMBOL] = result.activeDeferreds[match.route.id];
|
|
2874
|
+
}
|
|
2875
|
+
|
|
2876
|
+
return data;
|
|
2877
|
+
}
|
|
2878
|
+
|
|
2879
|
+
return undefined;
|
|
2808
2880
|
}
|
|
2809
2881
|
|
|
2810
2882
|
async function queryImpl(request, location, matches, requestContext, routeMatch) {
|
|
@@ -2884,7 +2956,18 @@
|
|
|
2884
2956
|
}
|
|
2885
2957
|
|
|
2886
2958
|
if (isDeferredResult(result)) {
|
|
2887
|
-
|
|
2959
|
+
let error = getInternalRouterError(400, {
|
|
2960
|
+
type: "defer-action"
|
|
2961
|
+
});
|
|
2962
|
+
|
|
2963
|
+
if (isRouteRequest) {
|
|
2964
|
+
throw error;
|
|
2965
|
+
}
|
|
2966
|
+
|
|
2967
|
+
result = {
|
|
2968
|
+
type: ResultType.error,
|
|
2969
|
+
error
|
|
2970
|
+
};
|
|
2888
2971
|
}
|
|
2889
2972
|
|
|
2890
2973
|
if (isRouteRequest) {
|
|
@@ -2905,7 +2988,8 @@
|
|
|
2905
2988
|
// return the raw Response or value
|
|
2906
2989
|
statusCode: 200,
|
|
2907
2990
|
loaderHeaders: {},
|
|
2908
|
-
actionHeaders: {}
|
|
2991
|
+
actionHeaders: {},
|
|
2992
|
+
activeDeferreds: null
|
|
2909
2993
|
};
|
|
2910
2994
|
}
|
|
2911
2995
|
|
|
@@ -2968,7 +3052,8 @@
|
|
|
2968
3052
|
}), {}),
|
|
2969
3053
|
errors: pendingActionError || null,
|
|
2970
3054
|
statusCode: 200,
|
|
2971
|
-
loaderHeaders: {}
|
|
3055
|
+
loaderHeaders: {},
|
|
3056
|
+
activeDeferreds: null
|
|
2972
3057
|
};
|
|
2973
3058
|
}
|
|
2974
3059
|
|
|
@@ -2977,27 +3062,21 @@
|
|
|
2977
3062
|
if (request.signal.aborted) {
|
|
2978
3063
|
let method = isRouteRequest ? "queryRoute" : "query";
|
|
2979
3064
|
throw new Error(method + "() call aborted");
|
|
2980
|
-
}
|
|
2981
|
-
|
|
2982
|
-
let executedLoaders = new Set();
|
|
2983
|
-
results.forEach((result, i) => {
|
|
2984
|
-
executedLoaders.add(matchesToLoad[i].route.id); // Can't do anything with these without the Remix side of things, so just
|
|
2985
|
-
// cancel them for now
|
|
3065
|
+
} // Process and commit output from loaders
|
|
2986
3066
|
|
|
2987
|
-
if (isDeferredResult(result)) {
|
|
2988
|
-
result.deferredData.cancel();
|
|
2989
|
-
}
|
|
2990
|
-
}); // Process and commit output from loaders
|
|
2991
3067
|
|
|
2992
|
-
let
|
|
3068
|
+
let activeDeferreds = new Map();
|
|
3069
|
+
let context = processRouteLoaderData(matches, matchesToLoad, results, pendingActionError, activeDeferreds); // Add a null for any non-loader matches for proper revalidation on the client
|
|
2993
3070
|
|
|
3071
|
+
let executedLoaders = new Set(matchesToLoad.map(match => match.route.id));
|
|
2994
3072
|
matches.forEach(match => {
|
|
2995
3073
|
if (!executedLoaders.has(match.route.id)) {
|
|
2996
3074
|
context.loaderData[match.route.id] = null;
|
|
2997
3075
|
}
|
|
2998
3076
|
});
|
|
2999
3077
|
return _extends({}, context, {
|
|
3000
|
-
matches
|
|
3078
|
+
matches,
|
|
3079
|
+
activeDeferreds: activeDeferreds.size > 0 ? Object.fromEntries(activeDeferreds.entries()) : null
|
|
3001
3080
|
});
|
|
3002
3081
|
}
|
|
3003
3082
|
|
|
@@ -3116,13 +3195,13 @@
|
|
|
3116
3195
|
return boundaryMatches;
|
|
3117
3196
|
}
|
|
3118
3197
|
|
|
3119
|
-
function getMatchesToLoad(state, matches, submission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, pendingActionData, pendingError, fetchLoadMatches) {
|
|
3198
|
+
function getMatchesToLoad(history, state, matches, submission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, pendingActionData, pendingError, fetchLoadMatches) {
|
|
3120
3199
|
let actionResult = pendingError ? Object.values(pendingError)[0] : pendingActionData ? Object.values(pendingActionData)[0] : undefined; // Pick navigation matches that are net-new or qualify for revalidation
|
|
3121
3200
|
|
|
3122
3201
|
let boundaryId = pendingError ? Object.keys(pendingError)[0] : undefined;
|
|
3123
3202
|
let boundaryMatches = getLoaderMatchesUntilBoundary(matches, boundaryId);
|
|
3124
3203
|
let navigationMatches = boundaryMatches.filter((match, index) => match.route.loader != null && (isNewLoader(state.loaderData, state.matches[index], match) || // If this route had a pending deferred cancelled it must be revalidated
|
|
3125
|
-
cancelledDeferredRoutes.some(id => id === match.route.id) || shouldRevalidateLoader(state.location, state.matches[index], submission, location, match, isRevalidationRequired, actionResult))); // Pick fetcher.loads that need to be revalidated
|
|
3204
|
+
cancelledDeferredRoutes.some(id => id === match.route.id) || shouldRevalidateLoader(history, state.location, state.matches[index], submission, location, match, isRevalidationRequired, actionResult))); // Pick fetcher.loads that need to be revalidated
|
|
3126
3205
|
|
|
3127
3206
|
let revalidatingFetchers = [];
|
|
3128
3207
|
fetchLoadMatches && fetchLoadMatches.forEach((_ref10, key) => {
|
|
@@ -3132,7 +3211,7 @@
|
|
|
3132
3211
|
if (cancelledFetcherLoads.includes(key)) {
|
|
3133
3212
|
revalidatingFetchers.push([key, href, match, fetchMatches]);
|
|
3134
3213
|
} else if (isRevalidationRequired) {
|
|
3135
|
-
let shouldRevalidate = shouldRevalidateLoader(href, match, submission, href, match, isRevalidationRequired, actionResult);
|
|
3214
|
+
let shouldRevalidate = shouldRevalidateLoader(history, href, match, submission, href, match, isRevalidationRequired, actionResult);
|
|
3136
3215
|
|
|
3137
3216
|
if (shouldRevalidate) {
|
|
3138
3217
|
revalidatingFetchers.push([key, href, match, fetchMatches]);
|
|
@@ -3162,10 +3241,10 @@
|
|
|
3162
3241
|
);
|
|
3163
3242
|
}
|
|
3164
3243
|
|
|
3165
|
-
function shouldRevalidateLoader(currentLocation, currentMatch, submission, location, match, isRevalidationRequired, actionResult) {
|
|
3166
|
-
let currentUrl =
|
|
3244
|
+
function shouldRevalidateLoader(history, currentLocation, currentMatch, submission, location, match, isRevalidationRequired, actionResult) {
|
|
3245
|
+
let currentUrl = history.createURL(currentLocation);
|
|
3167
3246
|
let currentParams = currentMatch.params;
|
|
3168
|
-
let nextUrl =
|
|
3247
|
+
let nextUrl = history.createURL(location);
|
|
3169
3248
|
let nextParams = match.params; // This is the default implementation as to when we revalidate. If the route
|
|
3170
3249
|
// provides it's own implementation, then we give them full control but
|
|
3171
3250
|
// provide this value so they can leverage it if needed after they check
|
|
@@ -3242,7 +3321,7 @@
|
|
|
3242
3321
|
if (redirectStatusCodes.has(status)) {
|
|
3243
3322
|
let location = result.headers.get("Location");
|
|
3244
3323
|
invariant(location, "Redirects returned/thrown from loaders/actions must have a Location header");
|
|
3245
|
-
let isAbsolute = /^[a-z
|
|
3324
|
+
let isAbsolute = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i.test(location); // Support relative routing in internal redirects
|
|
3246
3325
|
|
|
3247
3326
|
if (!isAbsolute) {
|
|
3248
3327
|
let activeMatches = matches.slice(0, matches.indexOf(match) + 1);
|
|
@@ -3335,8 +3414,8 @@
|
|
|
3335
3414
|
// Request instance from the static handler (query/queryRoute)
|
|
3336
3415
|
|
|
3337
3416
|
|
|
3338
|
-
function createClientSideRequest(location, signal, submission) {
|
|
3339
|
-
let url =
|
|
3417
|
+
function createClientSideRequest(history, location, signal, submission) {
|
|
3418
|
+
let url = history.createURL(stripHashFromPath(location)).toString();
|
|
3340
3419
|
let init = {
|
|
3341
3420
|
signal
|
|
3342
3421
|
};
|
|
@@ -3409,13 +3488,16 @@
|
|
|
3409
3488
|
if (result.headers) {
|
|
3410
3489
|
loaderHeaders[id] = result.headers;
|
|
3411
3490
|
}
|
|
3412
|
-
} else if (isDeferredResult(result)) {
|
|
3413
|
-
activeDeferreds && activeDeferreds.set(id, result.deferredData);
|
|
3414
|
-
loaderData[id] = result.deferredData.data; // TODO: Add statusCode/headers once we wire up streaming in Remix
|
|
3415
3491
|
} else {
|
|
3416
|
-
|
|
3492
|
+
if (isDeferredResult(result)) {
|
|
3493
|
+
activeDeferreds.set(id, result.deferredData);
|
|
3494
|
+
loaderData[id] = result.deferredData.data;
|
|
3495
|
+
} else {
|
|
3496
|
+
loaderData[id] = result.data;
|
|
3497
|
+
} // Error status codes always override success status codes, but if all
|
|
3417
3498
|
// loaders are successful we take the deepest status code.
|
|
3418
3499
|
|
|
3500
|
+
|
|
3419
3501
|
if (result.statusCode != null && result.statusCode !== 200 && !foundError) {
|
|
3420
3502
|
statusCode = result.statusCode;
|
|
3421
3503
|
}
|
|
@@ -3465,11 +3547,11 @@
|
|
|
3465
3547
|
} else if (isRedirectResult(result)) {
|
|
3466
3548
|
// Should never get here, redirects should get processed above, but we
|
|
3467
3549
|
// keep this to type narrow to a success result in the else
|
|
3468
|
-
|
|
3550
|
+
invariant(false, "Unhandled fetcher revalidation redirect");
|
|
3469
3551
|
} else if (isDeferredResult(result)) {
|
|
3470
3552
|
// Should never get here, deferred data should be awaited for fetchers
|
|
3471
3553
|
// in resolveDeferredResults
|
|
3472
|
-
|
|
3554
|
+
invariant(false, "Unhandled fetcher deferred data");
|
|
3473
3555
|
} else {
|
|
3474
3556
|
let doneFetcher = {
|
|
3475
3557
|
state: "idle",
|
|
@@ -3541,7 +3623,8 @@
|
|
|
3541
3623
|
let {
|
|
3542
3624
|
pathname,
|
|
3543
3625
|
routeId,
|
|
3544
|
-
method
|
|
3626
|
+
method,
|
|
3627
|
+
type
|
|
3545
3628
|
} = _temp4 === void 0 ? {} : _temp4;
|
|
3546
3629
|
let statusText = "Unknown Server Error";
|
|
3547
3630
|
let errorMessage = "Unknown @remix-run/router error";
|
|
@@ -3551,6 +3634,8 @@
|
|
|
3551
3634
|
|
|
3552
3635
|
if (method && pathname && routeId) {
|
|
3553
3636
|
errorMessage = "You made a " + method + " request to \"" + pathname + "\" but " + ("did not provide a `loader` for route \"" + routeId + "\", ") + "so there is no way to handle the request.";
|
|
3637
|
+
} else if (type === "defer-action") {
|
|
3638
|
+
errorMessage = "defer() is not supported in actions";
|
|
3554
3639
|
} else {
|
|
3555
3640
|
errorMessage = "Cannot submit binary form data using GET";
|
|
3556
3641
|
}
|
|
@@ -3724,6 +3809,8 @@
|
|
|
3724
3809
|
exports.ErrorResponse = ErrorResponse;
|
|
3725
3810
|
exports.IDLE_FETCHER = IDLE_FETCHER;
|
|
3726
3811
|
exports.IDLE_NAVIGATION = IDLE_NAVIGATION;
|
|
3812
|
+
exports.UNSAFE_DEFERRED_SYMBOL = UNSAFE_DEFERRED_SYMBOL;
|
|
3813
|
+
exports.UNSAFE_DeferredData = DeferredData;
|
|
3727
3814
|
exports.UNSAFE_convertRoutesToDataRoutes = convertRoutesToDataRoutes;
|
|
3728
3815
|
exports.UNSAFE_getPathContributingMatches = getPathContributingMatches;
|
|
3729
3816
|
exports.createBrowserHistory = createBrowserHistory;
|