@remix-run/router 0.0.0-experimental-832a0ee6 → 0.0.0-experimental-a077dc2d
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/router.cjs.js +68 -26
- package/dist/router.cjs.js.map +1 -1
- package/dist/router.d.ts +9 -0
- package/dist/router.js +67 -25
- package/dist/router.js.map +1 -1
- package/dist/router.umd.js +68 -26
- 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/package.json +1 -1
- package/router.ts +49 -11
- package/utils.ts +19 -15
package/dist/router.cjs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @remix-run/router v0.0.0-experimental-
|
|
2
|
+
* @remix-run/router v0.0.0-experimental-a077dc2d
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -1017,20 +1017,29 @@ function matchPath(pattern, pathname) {
|
|
|
1017
1017
|
end: true
|
|
1018
1018
|
};
|
|
1019
1019
|
}
|
|
1020
|
-
let [matcher,
|
|
1020
|
+
let [matcher, compiledParams] = compilePath(pattern.path, pattern.caseSensitive, pattern.end);
|
|
1021
1021
|
let match = pathname.match(matcher);
|
|
1022
1022
|
if (!match) return null;
|
|
1023
1023
|
let matchedPathname = match[0];
|
|
1024
1024
|
let pathnameBase = matchedPathname.replace(/(.)\/+$/, "$1");
|
|
1025
1025
|
let captureGroups = match.slice(1);
|
|
1026
|
-
let params =
|
|
1026
|
+
let params = compiledParams.reduce((memo, _ref, index) => {
|
|
1027
|
+
let {
|
|
1028
|
+
paramName,
|
|
1029
|
+
isOptional
|
|
1030
|
+
} = _ref;
|
|
1027
1031
|
// We need to compute the pathnameBase here using the raw splat value
|
|
1028
1032
|
// instead of using params["*"] later because it will be decoded then
|
|
1029
1033
|
if (paramName === "*") {
|
|
1030
1034
|
let splatValue = captureGroups[index] || "";
|
|
1031
1035
|
pathnameBase = matchedPathname.slice(0, matchedPathname.length - splatValue.length).replace(/(.)\/+$/, "$1");
|
|
1032
1036
|
}
|
|
1033
|
-
|
|
1037
|
+
const value = captureGroups[index];
|
|
1038
|
+
if (isOptional && !value) {
|
|
1039
|
+
memo[paramName] = undefined;
|
|
1040
|
+
} else {
|
|
1041
|
+
memo[paramName] = safelyDecodeURIComponent(value || "", paramName);
|
|
1042
|
+
}
|
|
1034
1043
|
return memo;
|
|
1035
1044
|
}, {});
|
|
1036
1045
|
return {
|
|
@@ -1048,16 +1057,21 @@ function compilePath(path, caseSensitive, end) {
|
|
|
1048
1057
|
end = true;
|
|
1049
1058
|
}
|
|
1050
1059
|
warning(path === "*" || !path.endsWith("*") || path.endsWith("/*"), "Route path \"" + path + "\" will be treated as if it were " + ("\"" + path.replace(/\*$/, "/*") + "\" because the `*` character must ") + "always follow a `/` in the pattern. To get rid of this warning, " + ("please change the route path to \"" + path.replace(/\*$/, "/*") + "\"."));
|
|
1051
|
-
let
|
|
1060
|
+
let params = [];
|
|
1052
1061
|
let regexpSource = "^" + path.replace(/\/*\*?$/, "") // Ignore trailing / and /*, we'll handle it below
|
|
1053
1062
|
.replace(/^\/*/, "/") // Make sure it has a leading /
|
|
1054
|
-
.replace(/[
|
|
1055
|
-
.replace(/\/:(\w+)
|
|
1056
|
-
|
|
1057
|
-
|
|
1063
|
+
.replace(/[\\.*+^${}|()[\]]/g, "\\$&") // Escape special regex chars
|
|
1064
|
+
.replace(/\/:(\w+)(\?)?/g, (_, paramName, isOptional) => {
|
|
1065
|
+
params.push({
|
|
1066
|
+
paramName,
|
|
1067
|
+
isOptional: isOptional != null
|
|
1068
|
+
});
|
|
1069
|
+
return isOptional ? "/?([^\\/]+)?" : "/([^\\/]+)";
|
|
1058
1070
|
});
|
|
1059
1071
|
if (path.endsWith("*")) {
|
|
1060
|
-
|
|
1072
|
+
params.push({
|
|
1073
|
+
paramName: "*"
|
|
1074
|
+
});
|
|
1061
1075
|
regexpSource += path === "*" || path === "/*" ? "(.*)$" // Already matched the initial /, just match the rest
|
|
1062
1076
|
: "(?:\\/(.+)|\\/*)$"; // Don't include the / in params["*"]
|
|
1063
1077
|
} else if (end) {
|
|
@@ -1074,7 +1088,7 @@ function compilePath(path, caseSensitive, end) {
|
|
|
1074
1088
|
regexpSource += "(?:(?=\\/|$))";
|
|
1075
1089
|
} else ;
|
|
1076
1090
|
let matcher = new RegExp(regexpSource, caseSensitive ? undefined : "i");
|
|
1077
|
-
return [matcher,
|
|
1091
|
+
return [matcher, params];
|
|
1078
1092
|
}
|
|
1079
1093
|
function safelyDecodeURI(value) {
|
|
1080
1094
|
try {
|
|
@@ -1302,8 +1316,8 @@ class DeferredData {
|
|
|
1302
1316
|
let onAbort = () => reject(new AbortedDeferredError("Deferred data aborted"));
|
|
1303
1317
|
this.unlistenAbortSignal = () => this.controller.signal.removeEventListener("abort", onAbort);
|
|
1304
1318
|
this.controller.signal.addEventListener("abort", onAbort);
|
|
1305
|
-
this.data = Object.entries(data).reduce((acc,
|
|
1306
|
-
let [key, value] =
|
|
1319
|
+
this.data = Object.entries(data).reduce((acc, _ref2) => {
|
|
1320
|
+
let [key, value] = _ref2;
|
|
1307
1321
|
return Object.assign(acc, {
|
|
1308
1322
|
[key]: this.trackPromise(key, value)
|
|
1309
1323
|
});
|
|
@@ -1403,8 +1417,8 @@ class DeferredData {
|
|
|
1403
1417
|
}
|
|
1404
1418
|
get unwrappedData() {
|
|
1405
1419
|
invariant(this.data !== null && this.done, "Can only unwrap data on initialized and settled deferreds");
|
|
1406
|
-
return Object.entries(this.data).reduce((acc,
|
|
1407
|
-
let [key, value] =
|
|
1420
|
+
return Object.entries(this.data).reduce((acc, _ref3) => {
|
|
1421
|
+
let [key, value] = _ref3;
|
|
1408
1422
|
return Object.assign(acc, {
|
|
1409
1423
|
[key]: unwrapTrackedPromise(value)
|
|
1410
1424
|
});
|
|
@@ -1649,6 +1663,7 @@ function createRouter(init) {
|
|
|
1649
1663
|
let basename = init.basename || "/";
|
|
1650
1664
|
// Config driven behavior flags
|
|
1651
1665
|
let future = _extends({
|
|
1666
|
+
v7_fetcherPersist: false,
|
|
1652
1667
|
v7_normalizeFormMethod: false,
|
|
1653
1668
|
v7_prependBasename: false
|
|
1654
1669
|
}, init.future);
|
|
@@ -1768,6 +1783,10 @@ function createRouter(init) {
|
|
|
1768
1783
|
// Most recent href/match for fetcher.load calls for fetchers
|
|
1769
1784
|
let fetchLoadMatches = new Map();
|
|
1770
1785
|
|
|
1786
|
+
// Fetchers that have requested a delete when using v7_fetcherPersist,
|
|
1787
|
+
// they'll be officially removed after they return to idle
|
|
1788
|
+
let deletedFetchers = new Set();
|
|
1789
|
+
|
|
1771
1790
|
// Store DeferredData instances for active route matches. When a
|
|
1772
1791
|
// route loader returns defer() we stick one in here. Then, when a nested
|
|
1773
1792
|
// promise resolves we update loaderData. If a new navigation starts we
|
|
@@ -1885,13 +1904,22 @@ function createRouter(init) {
|
|
|
1885
1904
|
}));
|
|
1886
1905
|
|
|
1887
1906
|
// Remove idle fetchers from state since we only care about in-flight fetchers.
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1907
|
+
if (future.v7_fetcherPersist) {
|
|
1908
|
+
state.fetchers.forEach((fetcher, key) => {
|
|
1909
|
+
if (fetcher.state === "idle") {
|
|
1910
|
+
if (deletedFetchers.has(key)) {
|
|
1911
|
+
// If the fetcher has unmounted and called router.deleteFetcher(),
|
|
1912
|
+
// we can totally delete the fetcher
|
|
1913
|
+
deleteFetcher(key);
|
|
1914
|
+
} else {
|
|
1915
|
+
// Otherwise, it must still be mounted in the UI so we just remove
|
|
1916
|
+
// it from state now that we've handed off the data to the React
|
|
1917
|
+
// layer. Things such as fetchLoadMatches remain for revalidation.
|
|
1918
|
+
state.fetchers.delete(key);
|
|
1919
|
+
}
|
|
1920
|
+
}
|
|
1921
|
+
});
|
|
1922
|
+
}
|
|
1895
1923
|
}
|
|
1896
1924
|
|
|
1897
1925
|
// Complete a navigation returning the state.navigation back to the IDLE_NAVIGATION
|
|
@@ -2443,6 +2471,9 @@ function createRouter(init) {
|
|
|
2443
2471
|
fetchers: new Map(state.fetchers)
|
|
2444
2472
|
} : {});
|
|
2445
2473
|
}
|
|
2474
|
+
function getFetcher(key) {
|
|
2475
|
+
return state.fetchers.get(key) || IDLE_FETCHER;
|
|
2476
|
+
}
|
|
2446
2477
|
|
|
2447
2478
|
// Trigger a fetcher load/submit for the given fetcher key
|
|
2448
2479
|
function fetch(key, routeId, href, opts) {
|
|
@@ -2884,7 +2915,6 @@ function createRouter(init) {
|
|
|
2884
2915
|
}
|
|
2885
2916
|
function deleteFetcher(key) {
|
|
2886
2917
|
let fetcher = state.fetchers.get(key);
|
|
2887
|
-
|
|
2888
2918
|
// Don't abort the controller if this is a deletion of a fetcher.submit()
|
|
2889
2919
|
// in it's loading phase since - we don't want to abort the corresponding
|
|
2890
2920
|
// revalidation and want them to complete and land
|
|
@@ -2894,8 +2924,19 @@ function createRouter(init) {
|
|
|
2894
2924
|
fetchLoadMatches.delete(key);
|
|
2895
2925
|
fetchReloadIds.delete(key);
|
|
2896
2926
|
fetchRedirectIds.delete(key);
|
|
2927
|
+
deletedFetchers.delete(key);
|
|
2897
2928
|
state.fetchers.delete(key);
|
|
2898
2929
|
}
|
|
2930
|
+
function deleteFetcherAndUpdateState(key) {
|
|
2931
|
+
if (future.v7_fetcherPersist) {
|
|
2932
|
+
deletedFetchers.add(key);
|
|
2933
|
+
} else {
|
|
2934
|
+
deleteFetcher(key);
|
|
2935
|
+
}
|
|
2936
|
+
updateState({
|
|
2937
|
+
fetchers: new Map(state.fetchers)
|
|
2938
|
+
});
|
|
2939
|
+
}
|
|
2899
2940
|
function abortFetcher(key) {
|
|
2900
2941
|
let controller = fetchControllers.get(key);
|
|
2901
2942
|
invariant(controller, "Expected fetch controller: " + key);
|
|
@@ -2904,8 +2945,8 @@ function createRouter(init) {
|
|
|
2904
2945
|
}
|
|
2905
2946
|
function markFetchersDone(keys) {
|
|
2906
2947
|
for (let key of keys) {
|
|
2907
|
-
let fetcher =
|
|
2908
|
-
let doneFetcher = getDoneFetcher(fetcher
|
|
2948
|
+
let fetcher = getFetcher(key);
|
|
2949
|
+
let doneFetcher = getDoneFetcher(fetcher.data);
|
|
2909
2950
|
state.fetchers.set(key, doneFetcher);
|
|
2910
2951
|
}
|
|
2911
2952
|
}
|
|
@@ -3089,7 +3130,8 @@ function createRouter(init) {
|
|
|
3089
3130
|
// hash-aware URLs in DOM paths
|
|
3090
3131
|
createHref: to => init.history.createHref(to),
|
|
3091
3132
|
encodeLocation: to => init.history.encodeLocation(to),
|
|
3092
|
-
|
|
3133
|
+
getFetcher,
|
|
3134
|
+
deleteFetcher: deleteFetcherAndUpdateState,
|
|
3093
3135
|
dispose,
|
|
3094
3136
|
getBlocker,
|
|
3095
3137
|
deleteBlocker,
|