@remix-run/router 1.2.1 → 1.3.0-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/CHANGELOG.md +12 -0
- package/dist/history.d.ts +6 -1
- package/dist/index.d.ts +1 -2
- package/dist/router.cjs.js +164 -83
- package/dist/router.cjs.js.map +1 -1
- package/dist/router.d.ts +2 -0
- package/dist/router.js +163 -84
- package/dist/router.js.map +1 -1
- package/dist/router.umd.js +164 -83
- 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 +77 -34
- package/utils.ts +88 -42
package/dist/router.d.ts
CHANGED
|
@@ -229,6 +229,7 @@ export interface StaticHandlerContext {
|
|
|
229
229
|
statusCode: number;
|
|
230
230
|
loaderHeaders: Record<string, Headers>;
|
|
231
231
|
actionHeaders: Record<string, Headers>;
|
|
232
|
+
activeDeferreds: Record<string, DeferredData> | null;
|
|
232
233
|
_deepestRenderedBoundaryId?: string | null;
|
|
233
234
|
}
|
|
234
235
|
/**
|
|
@@ -366,6 +367,7 @@ export declare const IDLE_FETCHER: FetcherStates["Idle"];
|
|
|
366
367
|
* Create a router and listen to history POP navigations
|
|
367
368
|
*/
|
|
368
369
|
export declare function createRouter(init: RouterInit): Router;
|
|
370
|
+
export declare const UNSAFE_DEFERRED_SYMBOL: unique symbol;
|
|
369
371
|
export declare function createStaticHandler(routes: AgnosticRouteObject[], opts?: {
|
|
370
372
|
basename?: string;
|
|
371
373
|
}): StaticHandler;
|
package/dist/router.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @remix-run/router v1.
|
|
2
|
+
* @remix-run/router v1.3.0-pre.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -99,6 +99,10 @@ function createMemoryHistory(options) {
|
|
|
99
99
|
return location;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
function createHref(to) {
|
|
103
|
+
return typeof to === "string" ? to : createPath(to);
|
|
104
|
+
}
|
|
105
|
+
|
|
102
106
|
let history = {
|
|
103
107
|
get index() {
|
|
104
108
|
return index;
|
|
@@ -112,8 +116,10 @@ function createMemoryHistory(options) {
|
|
|
112
116
|
return getCurrentLocation();
|
|
113
117
|
},
|
|
114
118
|
|
|
115
|
-
createHref
|
|
116
|
-
|
|
119
|
+
createHref,
|
|
120
|
+
|
|
121
|
+
createURL(to) {
|
|
122
|
+
return new URL(createHref(to), "http://localhost");
|
|
117
123
|
},
|
|
118
124
|
|
|
119
125
|
encodeLocation(to) {
|
|
@@ -358,15 +364,6 @@ function parsePath(path) {
|
|
|
358
364
|
|
|
359
365
|
return parsedPath;
|
|
360
366
|
}
|
|
361
|
-
function createClientSideURL(location) {
|
|
362
|
-
// window.location.origin is "null" (the literal string value) in Firefox
|
|
363
|
-
// under certain conditions, notably when serving from a local HTML file
|
|
364
|
-
// See https://bugzilla.mozilla.org/show_bug.cgi?id=878297
|
|
365
|
-
let base = typeof window !== "undefined" && typeof window.location !== "undefined" && window.location.origin !== "null" ? window.location.origin : window.location.href;
|
|
366
|
-
let href = typeof location === "string" ? location : createPath(location);
|
|
367
|
-
invariant(base, "No window.location.(origin|href) available to create URL for href: " + href);
|
|
368
|
-
return new URL(href, base);
|
|
369
|
-
}
|
|
370
367
|
|
|
371
368
|
function getUrlBasedHistory(getLocation, createHref, validateLocation, options) {
|
|
372
369
|
if (options === void 0) {
|
|
@@ -431,6 +428,16 @@ function getUrlBasedHistory(getLocation, createHref, validateLocation, options)
|
|
|
431
428
|
}
|
|
432
429
|
}
|
|
433
430
|
|
|
431
|
+
function createURL(to) {
|
|
432
|
+
// window.location.origin is "null" (the literal string value) in Firefox
|
|
433
|
+
// under certain conditions, notably when serving from a local HTML file
|
|
434
|
+
// See https://bugzilla.mozilla.org/show_bug.cgi?id=878297
|
|
435
|
+
let base = window.location.origin !== "null" ? window.location.origin : window.location.href;
|
|
436
|
+
let href = typeof to === "string" ? to : createPath(to);
|
|
437
|
+
invariant(base, "No window.location.(origin|href) available to create URL for href: " + href);
|
|
438
|
+
return new URL(href, base);
|
|
439
|
+
}
|
|
440
|
+
|
|
434
441
|
let history = {
|
|
435
442
|
get action() {
|
|
436
443
|
return action;
|
|
@@ -457,9 +464,11 @@ function getUrlBasedHistory(getLocation, createHref, validateLocation, options)
|
|
|
457
464
|
return createHref(window, to);
|
|
458
465
|
},
|
|
459
466
|
|
|
467
|
+
createURL,
|
|
468
|
+
|
|
460
469
|
encodeLocation(to) {
|
|
461
470
|
// Encode a Location the same way window.location would
|
|
462
|
-
let url =
|
|
471
|
+
let url = createURL(to);
|
|
463
472
|
return {
|
|
464
473
|
pathname: url.pathname,
|
|
465
474
|
search: url.search,
|
|
@@ -769,13 +778,32 @@ function generatePath(originalPath, params) {
|
|
|
769
778
|
path = path.replace(/\*$/, "/*");
|
|
770
779
|
}
|
|
771
780
|
|
|
772
|
-
return path.replace(/^:(\w+)/g, (_, key) => {
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
781
|
+
return path.replace(/^:(\w+)(\??)/g, (_, key, optional) => {
|
|
782
|
+
let param = params[key];
|
|
783
|
+
|
|
784
|
+
if (optional === "?") {
|
|
785
|
+
return param == null ? "" : param;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
if (param == null) {
|
|
789
|
+
invariant(false, "Missing \":" + key + "\" param");
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
return param;
|
|
793
|
+
}).replace(/\/:(\w+)(\??)/g, (_, key, optional) => {
|
|
794
|
+
let param = params[key];
|
|
795
|
+
|
|
796
|
+
if (optional === "?") {
|
|
797
|
+
return param == null ? "" : "/" + param;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
if (param == null) {
|
|
801
|
+
invariant(false, "Missing \":" + key + "\" param");
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
return "/" + param;
|
|
805
|
+
}) // Remove any optional markers from optional static segments
|
|
806
|
+
.replace(/\?/g, "").replace(/(\/?)\*/, (_, prefix, __, str) => {
|
|
779
807
|
const star = "*";
|
|
780
808
|
|
|
781
809
|
if (params[star] == null) {
|
|
@@ -1119,9 +1147,10 @@ const json = function json(data, init) {
|
|
|
1119
1147
|
};
|
|
1120
1148
|
class AbortedDeferredError extends Error {}
|
|
1121
1149
|
class DeferredData {
|
|
1122
|
-
constructor(data) {
|
|
1123
|
-
this.
|
|
1124
|
-
this.
|
|
1150
|
+
constructor(data, responseInit) {
|
|
1151
|
+
this.pendingKeysSet = new Set();
|
|
1152
|
+
this.subscribers = new Set();
|
|
1153
|
+
this.deferredKeys = [];
|
|
1125
1154
|
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
|
|
1126
1155
|
// cancellation
|
|
1127
1156
|
|
|
@@ -1140,6 +1169,7 @@ class DeferredData {
|
|
|
1140
1169
|
[key]: this.trackPromise(key, value)
|
|
1141
1170
|
});
|
|
1142
1171
|
}, {});
|
|
1172
|
+
this.init = responseInit;
|
|
1143
1173
|
}
|
|
1144
1174
|
|
|
1145
1175
|
trackPromise(key, value) {
|
|
@@ -1147,7 +1177,8 @@ class DeferredData {
|
|
|
1147
1177
|
return value;
|
|
1148
1178
|
}
|
|
1149
1179
|
|
|
1150
|
-
this.
|
|
1180
|
+
this.deferredKeys.push(key);
|
|
1181
|
+
this.pendingKeysSet.add(key); // We store a little wrapper promise that will be extended with
|
|
1151
1182
|
// _data/_error props upon resolve/reject
|
|
1152
1183
|
|
|
1153
1184
|
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
|
|
@@ -1169,39 +1200,41 @@ class DeferredData {
|
|
|
1169
1200
|
return Promise.reject(error);
|
|
1170
1201
|
}
|
|
1171
1202
|
|
|
1172
|
-
this.
|
|
1203
|
+
this.pendingKeysSet.delete(key);
|
|
1173
1204
|
|
|
1174
1205
|
if (this.done) {
|
|
1175
1206
|
// Nothing left to abort!
|
|
1176
1207
|
this.unlistenAbortSignal();
|
|
1177
1208
|
}
|
|
1178
1209
|
|
|
1179
|
-
const subscriber = this.subscriber;
|
|
1180
|
-
|
|
1181
1210
|
if (error) {
|
|
1182
1211
|
Object.defineProperty(promise, "_error", {
|
|
1183
1212
|
get: () => error
|
|
1184
1213
|
});
|
|
1185
|
-
|
|
1214
|
+
this.emit(false, key);
|
|
1186
1215
|
return Promise.reject(error);
|
|
1187
1216
|
}
|
|
1188
1217
|
|
|
1189
1218
|
Object.defineProperty(promise, "_data", {
|
|
1190
1219
|
get: () => data
|
|
1191
1220
|
});
|
|
1192
|
-
|
|
1221
|
+
this.emit(false, key);
|
|
1193
1222
|
return data;
|
|
1194
1223
|
}
|
|
1195
1224
|
|
|
1225
|
+
emit(aborted, settledKey) {
|
|
1226
|
+
this.subscribers.forEach(subscriber => subscriber(aborted, settledKey));
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1196
1229
|
subscribe(fn) {
|
|
1197
|
-
this.
|
|
1230
|
+
this.subscribers.add(fn);
|
|
1231
|
+
return () => this.subscribers.delete(fn);
|
|
1198
1232
|
}
|
|
1199
1233
|
|
|
1200
1234
|
cancel() {
|
|
1201
1235
|
this.controller.abort();
|
|
1202
|
-
this.
|
|
1203
|
-
|
|
1204
|
-
subscriber && subscriber(true);
|
|
1236
|
+
this.pendingKeysSet.forEach((v, k) => this.pendingKeysSet.delete(k));
|
|
1237
|
+
this.emit(true);
|
|
1205
1238
|
}
|
|
1206
1239
|
|
|
1207
1240
|
async resolveData(signal) {
|
|
@@ -1226,7 +1259,7 @@ class DeferredData {
|
|
|
1226
1259
|
}
|
|
1227
1260
|
|
|
1228
1261
|
get done() {
|
|
1229
|
-
return this.
|
|
1262
|
+
return this.pendingKeysSet.size === 0;
|
|
1230
1263
|
}
|
|
1231
1264
|
|
|
1232
1265
|
get unwrappedData() {
|
|
@@ -1239,6 +1272,10 @@ class DeferredData {
|
|
|
1239
1272
|
}, {});
|
|
1240
1273
|
}
|
|
1241
1274
|
|
|
1275
|
+
get pendingKeys() {
|
|
1276
|
+
return Array.from(this.pendingKeysSet);
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1242
1279
|
}
|
|
1243
1280
|
|
|
1244
1281
|
function isTrackedPromise(value) {
|
|
@@ -1257,9 +1294,16 @@ function unwrapTrackedPromise(value) {
|
|
|
1257
1294
|
return value._data;
|
|
1258
1295
|
}
|
|
1259
1296
|
|
|
1260
|
-
function defer(data) {
|
|
1261
|
-
|
|
1262
|
-
}
|
|
1297
|
+
const defer = function defer(data, init) {
|
|
1298
|
+
if (init === void 0) {
|
|
1299
|
+
init = {};
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
let responseInit = typeof init === "number" ? {
|
|
1303
|
+
status: init
|
|
1304
|
+
} : init;
|
|
1305
|
+
return new DeferredData(data, responseInit);
|
|
1306
|
+
};
|
|
1263
1307
|
/**
|
|
1264
1308
|
* A redirect response. Sets the status code and the `Location` header.
|
|
1265
1309
|
* Defaults to "302 Found".
|
|
@@ -1677,7 +1721,7 @@ function createRouter(init) {
|
|
|
1677
1721
|
|
|
1678
1722
|
|
|
1679
1723
|
pendingNavigationController = new AbortController();
|
|
1680
|
-
let request = createClientSideRequest(location, pendingNavigationController.signal, opts && opts.submission);
|
|
1724
|
+
let request = createClientSideRequest(init.history, location, pendingNavigationController.signal, opts && opts.submission);
|
|
1681
1725
|
let pendingActionData;
|
|
1682
1726
|
let pendingError;
|
|
1683
1727
|
|
|
@@ -1818,7 +1862,9 @@ function createRouter(init) {
|
|
|
1818
1862
|
}
|
|
1819
1863
|
|
|
1820
1864
|
if (isDeferredResult(result)) {
|
|
1821
|
-
throw
|
|
1865
|
+
throw getInternalRouterError(400, {
|
|
1866
|
+
type: "defer-action"
|
|
1867
|
+
});
|
|
1822
1868
|
}
|
|
1823
1869
|
|
|
1824
1870
|
return {
|
|
@@ -1855,7 +1901,7 @@ function createRouter(init) {
|
|
|
1855
1901
|
formData: loadingNavigation.formData,
|
|
1856
1902
|
formEncType: loadingNavigation.formEncType
|
|
1857
1903
|
} : undefined;
|
|
1858
|
-
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
|
|
1904
|
+
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
|
|
1859
1905
|
// about to reload. Note that if this is an action reload we would have
|
|
1860
1906
|
// already cancelled all pending deferreds so this would be a no-op
|
|
1861
1907
|
|
|
@@ -2037,7 +2083,7 @@ function createRouter(init) {
|
|
|
2037
2083
|
}); // Call the action for the fetcher
|
|
2038
2084
|
|
|
2039
2085
|
let abortController = new AbortController();
|
|
2040
|
-
let fetchRequest = createClientSideRequest(path, abortController.signal, submission);
|
|
2086
|
+
let fetchRequest = createClientSideRequest(init.history, path, abortController.signal, submission);
|
|
2041
2087
|
fetchControllers.set(key, abortController);
|
|
2042
2088
|
let actionResult = await callLoaderOrAction("action", fetchRequest, match, requestMatches, router.basename);
|
|
2043
2089
|
|
|
@@ -2078,13 +2124,15 @@ function createRouter(init) {
|
|
|
2078
2124
|
}
|
|
2079
2125
|
|
|
2080
2126
|
if (isDeferredResult(actionResult)) {
|
|
2081
|
-
|
|
2127
|
+
throw getInternalRouterError(400, {
|
|
2128
|
+
type: "defer-action"
|
|
2129
|
+
});
|
|
2082
2130
|
} // Start the data load for current matches, or the next location if we're
|
|
2083
2131
|
// in the middle of a navigation
|
|
2084
2132
|
|
|
2085
2133
|
|
|
2086
2134
|
let nextLocation = state.navigation.location || state.location;
|
|
2087
|
-
let revalidationRequest = createClientSideRequest(nextLocation, abortController.signal);
|
|
2135
|
+
let revalidationRequest = createClientSideRequest(init.history, nextLocation, abortController.signal);
|
|
2088
2136
|
let matches = state.navigation.state !== "idle" ? matchRoutes(dataRoutes, state.navigation.location, init.basename) : state.matches;
|
|
2089
2137
|
invariant(matches, "Didn't find any matches after fetcher action");
|
|
2090
2138
|
let loadId = ++incrementingLoadId;
|
|
@@ -2098,7 +2146,7 @@ function createRouter(init) {
|
|
|
2098
2146
|
});
|
|
2099
2147
|
|
|
2100
2148
|
state.fetchers.set(key, loadFetcher);
|
|
2101
|
-
let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(state, matches, submission, nextLocation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, {
|
|
2149
|
+
let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, submission, nextLocation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, {
|
|
2102
2150
|
[match.route.id]: actionResult.data
|
|
2103
2151
|
}, undefined, // No need to send through errors since we short circuit above
|
|
2104
2152
|
fetchLoadMatches); // Put all revalidating fetchers into the loading state, except for the
|
|
@@ -2211,9 +2259,9 @@ function createRouter(init) {
|
|
|
2211
2259
|
}); // Call the loader for this fetcher route match
|
|
2212
2260
|
|
|
2213
2261
|
let abortController = new AbortController();
|
|
2214
|
-
let fetchRequest = createClientSideRequest(path, abortController.signal);
|
|
2262
|
+
let fetchRequest = createClientSideRequest(init.history, path, abortController.signal);
|
|
2215
2263
|
fetchControllers.set(key, abortController);
|
|
2216
|
-
let result = await callLoaderOrAction("loader", fetchRequest, match, matches, router.basename); // Deferred isn't supported
|
|
2264
|
+
let result = await callLoaderOrAction("loader", fetchRequest, match, matches, router.basename); // Deferred isn't supported for fetcher loads, await everything and treat it
|
|
2217
2265
|
// as a normal load. resolveDeferredData will return undefined if this
|
|
2218
2266
|
// fetcher gets aborted, so we just leave result untouched and short circuit
|
|
2219
2267
|
// below if that happens
|
|
@@ -2313,7 +2361,7 @@ function createRouter(init) {
|
|
|
2313
2361
|
invariant(redirectLocation, "Expected a location on the redirect navigation"); // Check if this an external redirect that goes to a new origin
|
|
2314
2362
|
|
|
2315
2363
|
if (typeof ((_window = window) == null ? void 0 : _window.location) !== "undefined") {
|
|
2316
|
-
let newOrigin =
|
|
2364
|
+
let newOrigin = init.history.createURL(redirect.location).origin;
|
|
2317
2365
|
|
|
2318
2366
|
if (window.location.origin !== newOrigin) {
|
|
2319
2367
|
if (replace) {
|
|
@@ -2379,7 +2427,7 @@ function createRouter(init) {
|
|
|
2379
2427
|
// accordingly
|
|
2380
2428
|
let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, router.basename)), ...fetchersToLoad.map(_ref8 => {
|
|
2381
2429
|
let [, href, match, fetchMatches] = _ref8;
|
|
2382
|
-
return callLoaderOrAction("loader", createClientSideRequest(href, request.signal), match, fetchMatches, router.basename);
|
|
2430
|
+
return callLoaderOrAction("loader", createClientSideRequest(init.history, href, request.signal), match, fetchMatches, router.basename);
|
|
2383
2431
|
})]);
|
|
2384
2432
|
let loaderResults = results.slice(0, matchesToLoad.length);
|
|
2385
2433
|
let fetcherResults = results.slice(matchesToLoad.length);
|
|
@@ -2588,6 +2636,7 @@ function createRouter(init) {
|
|
|
2588
2636
|
//#region createStaticHandler
|
|
2589
2637
|
////////////////////////////////////////////////////////////////////////////////
|
|
2590
2638
|
|
|
2639
|
+
const UNSAFE_DEFERRED_SYMBOL = Symbol("deferred");
|
|
2591
2640
|
function createStaticHandler(routes, opts) {
|
|
2592
2641
|
invariant(routes.length > 0, "You must provide a non-empty routes array to createStaticHandler");
|
|
2593
2642
|
let dataRoutes = convertRoutesToDataRoutes(routes);
|
|
@@ -2640,7 +2689,8 @@ function createStaticHandler(routes, opts) {
|
|
|
2640
2689
|
},
|
|
2641
2690
|
statusCode: error.status,
|
|
2642
2691
|
loaderHeaders: {},
|
|
2643
|
-
actionHeaders: {}
|
|
2692
|
+
actionHeaders: {},
|
|
2693
|
+
activeDeferreds: null
|
|
2644
2694
|
};
|
|
2645
2695
|
} else if (!matches) {
|
|
2646
2696
|
let error = getInternalRouterError(404, {
|
|
@@ -2661,7 +2711,8 @@ function createStaticHandler(routes, opts) {
|
|
|
2661
2711
|
},
|
|
2662
2712
|
statusCode: error.status,
|
|
2663
2713
|
loaderHeaders: {},
|
|
2664
|
-
actionHeaders: {}
|
|
2714
|
+
actionHeaders: {},
|
|
2715
|
+
activeDeferreds: null
|
|
2665
2716
|
};
|
|
2666
2717
|
}
|
|
2667
2718
|
|
|
@@ -2752,8 +2803,23 @@ function createStaticHandler(routes, opts) {
|
|
|
2752
2803
|
} // Pick off the right state value to return
|
|
2753
2804
|
|
|
2754
2805
|
|
|
2755
|
-
|
|
2756
|
-
|
|
2806
|
+
if (result.actionData) {
|
|
2807
|
+
return Object.values(result.actionData)[0];
|
|
2808
|
+
}
|
|
2809
|
+
|
|
2810
|
+
if (result.loaderData) {
|
|
2811
|
+
var _result$activeDeferre;
|
|
2812
|
+
|
|
2813
|
+
let data = Object.values(result.loaderData)[0];
|
|
2814
|
+
|
|
2815
|
+
if ((_result$activeDeferre = result.activeDeferreds) != null && _result$activeDeferre[match.route.id]) {
|
|
2816
|
+
data[UNSAFE_DEFERRED_SYMBOL] = result.activeDeferreds[match.route.id];
|
|
2817
|
+
}
|
|
2818
|
+
|
|
2819
|
+
return data;
|
|
2820
|
+
}
|
|
2821
|
+
|
|
2822
|
+
return undefined;
|
|
2757
2823
|
}
|
|
2758
2824
|
|
|
2759
2825
|
async function queryImpl(request, location, matches, requestContext, routeMatch) {
|
|
@@ -2833,7 +2899,18 @@ function createStaticHandler(routes, opts) {
|
|
|
2833
2899
|
}
|
|
2834
2900
|
|
|
2835
2901
|
if (isDeferredResult(result)) {
|
|
2836
|
-
|
|
2902
|
+
let error = getInternalRouterError(400, {
|
|
2903
|
+
type: "defer-action"
|
|
2904
|
+
});
|
|
2905
|
+
|
|
2906
|
+
if (isRouteRequest) {
|
|
2907
|
+
throw error;
|
|
2908
|
+
}
|
|
2909
|
+
|
|
2910
|
+
result = {
|
|
2911
|
+
type: ResultType.error,
|
|
2912
|
+
error
|
|
2913
|
+
};
|
|
2837
2914
|
}
|
|
2838
2915
|
|
|
2839
2916
|
if (isRouteRequest) {
|
|
@@ -2854,7 +2931,8 @@ function createStaticHandler(routes, opts) {
|
|
|
2854
2931
|
// return the raw Response or value
|
|
2855
2932
|
statusCode: 200,
|
|
2856
2933
|
loaderHeaders: {},
|
|
2857
|
-
actionHeaders: {}
|
|
2934
|
+
actionHeaders: {},
|
|
2935
|
+
activeDeferreds: null
|
|
2858
2936
|
};
|
|
2859
2937
|
}
|
|
2860
2938
|
|
|
@@ -2917,7 +2995,8 @@ function createStaticHandler(routes, opts) {
|
|
|
2917
2995
|
}), {}),
|
|
2918
2996
|
errors: pendingActionError || null,
|
|
2919
2997
|
statusCode: 200,
|
|
2920
|
-
loaderHeaders: {}
|
|
2998
|
+
loaderHeaders: {},
|
|
2999
|
+
activeDeferreds: null
|
|
2921
3000
|
};
|
|
2922
3001
|
}
|
|
2923
3002
|
|
|
@@ -2926,27 +3005,21 @@ function createStaticHandler(routes, opts) {
|
|
|
2926
3005
|
if (request.signal.aborted) {
|
|
2927
3006
|
let method = isRouteRequest ? "queryRoute" : "query";
|
|
2928
3007
|
throw new Error(method + "() call aborted");
|
|
2929
|
-
}
|
|
3008
|
+
} // Process and commit output from loaders
|
|
2930
3009
|
|
|
2931
|
-
let executedLoaders = new Set();
|
|
2932
|
-
results.forEach((result, i) => {
|
|
2933
|
-
executedLoaders.add(matchesToLoad[i].route.id); // Can't do anything with these without the Remix side of things, so just
|
|
2934
|
-
// cancel them for now
|
|
2935
3010
|
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
}
|
|
2939
|
-
}); // Process and commit output from loaders
|
|
2940
|
-
|
|
2941
|
-
let context = processRouteLoaderData(matches, matchesToLoad, results, pendingActionError); // Add a null for any non-loader matches for proper revalidation on the client
|
|
3011
|
+
let activeDeferreds = new Map();
|
|
3012
|
+
let context = processRouteLoaderData(matches, matchesToLoad, results, pendingActionError, activeDeferreds); // Add a null for any non-loader matches for proper revalidation on the client
|
|
2942
3013
|
|
|
3014
|
+
let executedLoaders = new Set(matchesToLoad.map(match => match.route.id));
|
|
2943
3015
|
matches.forEach(match => {
|
|
2944
3016
|
if (!executedLoaders.has(match.route.id)) {
|
|
2945
3017
|
context.loaderData[match.route.id] = null;
|
|
2946
3018
|
}
|
|
2947
3019
|
});
|
|
2948
3020
|
return _extends({}, context, {
|
|
2949
|
-
matches
|
|
3021
|
+
matches,
|
|
3022
|
+
activeDeferreds: activeDeferreds.size > 0 ? Object.fromEntries(activeDeferreds.entries()) : null
|
|
2950
3023
|
});
|
|
2951
3024
|
}
|
|
2952
3025
|
|
|
@@ -3065,13 +3138,13 @@ function getLoaderMatchesUntilBoundary(matches, boundaryId) {
|
|
|
3065
3138
|
return boundaryMatches;
|
|
3066
3139
|
}
|
|
3067
3140
|
|
|
3068
|
-
function getMatchesToLoad(state, matches, submission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, pendingActionData, pendingError, fetchLoadMatches) {
|
|
3141
|
+
function getMatchesToLoad(history, state, matches, submission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, pendingActionData, pendingError, fetchLoadMatches) {
|
|
3069
3142
|
let actionResult = pendingError ? Object.values(pendingError)[0] : pendingActionData ? Object.values(pendingActionData)[0] : undefined; // Pick navigation matches that are net-new or qualify for revalidation
|
|
3070
3143
|
|
|
3071
3144
|
let boundaryId = pendingError ? Object.keys(pendingError)[0] : undefined;
|
|
3072
3145
|
let boundaryMatches = getLoaderMatchesUntilBoundary(matches, boundaryId);
|
|
3073
3146
|
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
|
|
3074
|
-
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
|
|
3147
|
+
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
|
|
3075
3148
|
|
|
3076
3149
|
let revalidatingFetchers = [];
|
|
3077
3150
|
fetchLoadMatches && fetchLoadMatches.forEach((_ref10, key) => {
|
|
@@ -3081,7 +3154,7 @@ function getMatchesToLoad(state, matches, submission, location, isRevalidationRe
|
|
|
3081
3154
|
if (cancelledFetcherLoads.includes(key)) {
|
|
3082
3155
|
revalidatingFetchers.push([key, href, match, fetchMatches]);
|
|
3083
3156
|
} else if (isRevalidationRequired) {
|
|
3084
|
-
let shouldRevalidate = shouldRevalidateLoader(href, match, submission, href, match, isRevalidationRequired, actionResult);
|
|
3157
|
+
let shouldRevalidate = shouldRevalidateLoader(history, href, match, submission, href, match, isRevalidationRequired, actionResult);
|
|
3085
3158
|
|
|
3086
3159
|
if (shouldRevalidate) {
|
|
3087
3160
|
revalidatingFetchers.push([key, href, match, fetchMatches]);
|
|
@@ -3111,10 +3184,10 @@ function isNewRouteInstance(currentMatch, match) {
|
|
|
3111
3184
|
);
|
|
3112
3185
|
}
|
|
3113
3186
|
|
|
3114
|
-
function shouldRevalidateLoader(currentLocation, currentMatch, submission, location, match, isRevalidationRequired, actionResult) {
|
|
3115
|
-
let currentUrl =
|
|
3187
|
+
function shouldRevalidateLoader(history, currentLocation, currentMatch, submission, location, match, isRevalidationRequired, actionResult) {
|
|
3188
|
+
let currentUrl = history.createURL(currentLocation);
|
|
3116
3189
|
let currentParams = currentMatch.params;
|
|
3117
|
-
let nextUrl =
|
|
3190
|
+
let nextUrl = history.createURL(location);
|
|
3118
3191
|
let nextParams = match.params; // This is the default implementation as to when we revalidate. If the route
|
|
3119
3192
|
// provides it's own implementation, then we give them full control but
|
|
3120
3193
|
// provide this value so they can leverage it if needed after they check
|
|
@@ -3191,7 +3264,7 @@ async function callLoaderOrAction(type, request, match, matches, basename, isSta
|
|
|
3191
3264
|
if (redirectStatusCodes.has(status)) {
|
|
3192
3265
|
let location = result.headers.get("Location");
|
|
3193
3266
|
invariant(location, "Redirects returned/thrown from loaders/actions must have a Location header");
|
|
3194
|
-
let isAbsolute = /^[a-z
|
|
3267
|
+
let isAbsolute = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i.test(location); // Support relative routing in internal redirects
|
|
3195
3268
|
|
|
3196
3269
|
if (!isAbsolute) {
|
|
3197
3270
|
let activeMatches = matches.slice(0, matches.indexOf(match) + 1);
|
|
@@ -3284,8 +3357,8 @@ async function callLoaderOrAction(type, request, match, matches, basename, isSta
|
|
|
3284
3357
|
// Request instance from the static handler (query/queryRoute)
|
|
3285
3358
|
|
|
3286
3359
|
|
|
3287
|
-
function createClientSideRequest(location, signal, submission) {
|
|
3288
|
-
let url =
|
|
3360
|
+
function createClientSideRequest(history, location, signal, submission) {
|
|
3361
|
+
let url = history.createURL(stripHashFromPath(location)).toString();
|
|
3289
3362
|
let init = {
|
|
3290
3363
|
signal
|
|
3291
3364
|
};
|
|
@@ -3358,13 +3431,16 @@ function processRouteLoaderData(matches, matchesToLoad, results, pendingError, a
|
|
|
3358
3431
|
if (result.headers) {
|
|
3359
3432
|
loaderHeaders[id] = result.headers;
|
|
3360
3433
|
}
|
|
3361
|
-
} else if (isDeferredResult(result)) {
|
|
3362
|
-
activeDeferreds && activeDeferreds.set(id, result.deferredData);
|
|
3363
|
-
loaderData[id] = result.deferredData.data; // TODO: Add statusCode/headers once we wire up streaming in Remix
|
|
3364
3434
|
} else {
|
|
3365
|
-
|
|
3435
|
+
if (isDeferredResult(result)) {
|
|
3436
|
+
activeDeferreds.set(id, result.deferredData);
|
|
3437
|
+
loaderData[id] = result.deferredData.data;
|
|
3438
|
+
} else {
|
|
3439
|
+
loaderData[id] = result.data;
|
|
3440
|
+
} // Error status codes always override success status codes, but if all
|
|
3366
3441
|
// loaders are successful we take the deepest status code.
|
|
3367
3442
|
|
|
3443
|
+
|
|
3368
3444
|
if (result.statusCode != null && result.statusCode !== 200 && !foundError) {
|
|
3369
3445
|
statusCode = result.statusCode;
|
|
3370
3446
|
}
|
|
@@ -3414,11 +3490,11 @@ function processLoaderData(state, matches, matchesToLoad, results, pendingError,
|
|
|
3414
3490
|
} else if (isRedirectResult(result)) {
|
|
3415
3491
|
// Should never get here, redirects should get processed above, but we
|
|
3416
3492
|
// keep this to type narrow to a success result in the else
|
|
3417
|
-
|
|
3493
|
+
invariant(false, "Unhandled fetcher revalidation redirect");
|
|
3418
3494
|
} else if (isDeferredResult(result)) {
|
|
3419
3495
|
// Should never get here, deferred data should be awaited for fetchers
|
|
3420
3496
|
// in resolveDeferredResults
|
|
3421
|
-
|
|
3497
|
+
invariant(false, "Unhandled fetcher deferred data");
|
|
3422
3498
|
} else {
|
|
3423
3499
|
let doneFetcher = {
|
|
3424
3500
|
state: "idle",
|
|
@@ -3490,7 +3566,8 @@ function getInternalRouterError(status, _temp4) {
|
|
|
3490
3566
|
let {
|
|
3491
3567
|
pathname,
|
|
3492
3568
|
routeId,
|
|
3493
|
-
method
|
|
3569
|
+
method,
|
|
3570
|
+
type
|
|
3494
3571
|
} = _temp4 === void 0 ? {} : _temp4;
|
|
3495
3572
|
let statusText = "Unknown Server Error";
|
|
3496
3573
|
let errorMessage = "Unknown @remix-run/router error";
|
|
@@ -3500,6 +3577,8 @@ function getInternalRouterError(status, _temp4) {
|
|
|
3500
3577
|
|
|
3501
3578
|
if (method && pathname && routeId) {
|
|
3502
3579
|
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.";
|
|
3580
|
+
} else if (type === "defer-action") {
|
|
3581
|
+
errorMessage = "defer() is not supported in actions";
|
|
3503
3582
|
} else {
|
|
3504
3583
|
errorMessage = "Cannot submit binary form data using GET";
|
|
3505
3584
|
}
|
|
@@ -3669,5 +3748,5 @@ function getTargetMatch(matches, location) {
|
|
|
3669
3748
|
return pathMatches[pathMatches.length - 1];
|
|
3670
3749
|
} //#endregion
|
|
3671
3750
|
|
|
3672
|
-
export { AbortedDeferredError, Action, ErrorResponse, IDLE_FETCHER, IDLE_NAVIGATION, 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 };
|
|
3751
|
+
export { AbortedDeferredError, Action, ErrorResponse, 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 };
|
|
3673
3752
|
//# sourceMappingURL=router.js.map
|