@remix-run/router 0.0.0-experimental-bc2c864b → 0.0.0-experimental-acfea932
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/router.cjs.js +58 -40
- package/dist/router.cjs.js.map +1 -1
- package/dist/router.d.ts +1 -0
- package/dist/router.js +57 -39
- package/dist/router.js.map +1 -1
- package/dist/router.umd.js +58 -40
- 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 +4 -3
- package/history.ts +4 -0
- package/package.json +1 -1
- package/router.ts +88 -32
- package/utils.ts +20 -33
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# `@remix-run/router`
|
|
2
2
|
|
|
3
|
+
## 1.15.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Add a `createStaticHandler` `future.v7_throwAbortReason` flag to throw `request.signal.reason` (defaults to a `DOMException`) when a request is aborted instead of an `Error` such as `new Error("query() call aborted: GET /path")` ([#11104](https://github.com/remix-run/react-router/pull/11104))
|
|
8
|
+
|
|
9
|
+
- Please note that `DOMException` was added in Node v17 so you will not get a `DOMException` on Node 16 and below.
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Respect the `ErrorResponse` status code if passed to `getStaticContextFormError` ([#11213](https://github.com/remix-run/react-router/pull/11213))
|
|
14
|
+
|
|
3
15
|
## 1.14.2
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
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-acfea932
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -496,6 +496,10 @@ function getUrlBasedHistory(getLocation, createHref, validateLocation, options)
|
|
|
496
496
|
// See https://bugzilla.mozilla.org/show_bug.cgi?id=878297
|
|
497
497
|
let base = window.location.origin !== "null" ? window.location.origin : window.location.href;
|
|
498
498
|
let href = typeof to === "string" ? to : createPath(to);
|
|
499
|
+
// Treating this as a full URL will strip any trailing spaces so we need to
|
|
500
|
+
// pre-encode them since they might be part of a matching splat param from
|
|
501
|
+
// an ancestor route
|
|
502
|
+
href = href.replace(/ $/, "%20");
|
|
499
503
|
invariant(base, "No window.location.(origin|href) available to create URL for href: " + href);
|
|
500
504
|
return new URL(href, base);
|
|
501
505
|
}
|
|
@@ -756,14 +760,14 @@ function matchRoutes(routes, locationArg, basename) {
|
|
|
756
760
|
rankRouteBranches(branches);
|
|
757
761
|
let matches = null;
|
|
758
762
|
for (let i = 0; matches == null && i < branches.length; ++i) {
|
|
759
|
-
matches = matchRouteBranch(branches[i],
|
|
760
763
|
// Incoming pathnames are generally encoded from either window.location
|
|
761
764
|
// or from router.navigate, but we want to match against the unencoded
|
|
762
765
|
// paths in the route definitions. Memory router locations won't be
|
|
763
766
|
// encoded here but there also shouldn't be anything to decode so this
|
|
764
767
|
// should be a safe operation. This avoids needing matchRoutes to be
|
|
765
768
|
// history-aware.
|
|
766
|
-
|
|
769
|
+
let decoded = decodePath(pathname);
|
|
770
|
+
matches = matchRouteBranch(branches[i], decoded);
|
|
767
771
|
}
|
|
768
772
|
return matches;
|
|
769
773
|
}
|
|
@@ -1042,7 +1046,7 @@ function matchPath(pattern, pathname) {
|
|
|
1042
1046
|
if (isOptional && !value) {
|
|
1043
1047
|
memo[paramName] = undefined;
|
|
1044
1048
|
} else {
|
|
1045
|
-
memo[paramName] =
|
|
1049
|
+
memo[paramName] = (value || "").replace(/%2F/g, "/");
|
|
1046
1050
|
}
|
|
1047
1051
|
return memo;
|
|
1048
1052
|
}, {});
|
|
@@ -1094,22 +1098,14 @@ function compilePath(path, caseSensitive, end) {
|
|
|
1094
1098
|
let matcher = new RegExp(regexpSource, caseSensitive ? undefined : "i");
|
|
1095
1099
|
return [matcher, params];
|
|
1096
1100
|
}
|
|
1097
|
-
function
|
|
1101
|
+
function decodePath(value) {
|
|
1098
1102
|
try {
|
|
1099
|
-
return
|
|
1103
|
+
return value.split("/").map(v => decodeURIComponent(v).replace(/\//g, "%2F")).join("/");
|
|
1100
1104
|
} catch (error) {
|
|
1101
1105
|
warning(false, "The URL path \"" + value + "\" could not be decoded because it is is a " + "malformed URL segment. This is probably due to a bad percent " + ("encoding (" + error + ")."));
|
|
1102
1106
|
return value;
|
|
1103
1107
|
}
|
|
1104
1108
|
}
|
|
1105
|
-
function safelyDecodeURIComponent(value, paramName) {
|
|
1106
|
-
try {
|
|
1107
|
-
return decodeURIComponent(value);
|
|
1108
|
-
} catch (error) {
|
|
1109
|
-
warning(false, "The value for the URL param \"" + paramName + "\" will not be decoded because" + (" the string \"" + value + "\" is a malformed URL segment. This is probably") + (" due to a bad percent encoding (" + error + ")."));
|
|
1110
|
-
return value;
|
|
1111
|
-
}
|
|
1112
|
-
}
|
|
1113
1109
|
|
|
1114
1110
|
/**
|
|
1115
1111
|
* @private
|
|
@@ -1731,7 +1727,7 @@ function createRouter(init) {
|
|
|
1731
1727
|
// were marked for explicit hydration
|
|
1732
1728
|
let loaderData = init.hydrationData ? init.hydrationData.loaderData : null;
|
|
1733
1729
|
let errors = init.hydrationData ? init.hydrationData.errors : null;
|
|
1734
|
-
initialized = initialMatches.every(m => m.route.loader && m.route.loader.hydrate !== true && (loaderData && loaderData[m.route.id] !== undefined || errors && errors[m.route.id] !== undefined));
|
|
1730
|
+
initialized = initialMatches.every(m => m.route.loader && (typeof m.route.loader !== "function" || m.route.loader.hydrate !== true) && (loaderData && loaderData[m.route.id] !== undefined || errors && errors[m.route.id] !== undefined));
|
|
1735
1731
|
} else {
|
|
1736
1732
|
// Without partial hydration - we're initialized if we were provided any
|
|
1737
1733
|
// hydrationData - which is expected to be complete
|
|
@@ -3332,9 +3328,15 @@ function createStaticHandler(routes, opts) {
|
|
|
3332
3328
|
* redirect response is returned or thrown from any action/loader. We
|
|
3333
3329
|
* propagate that out and return the raw Response so the HTTP server can
|
|
3334
3330
|
* return it directly.
|
|
3331
|
+
*
|
|
3332
|
+
* - `opts.loadRouteIds` is an optional array of routeIds if you wish to only
|
|
3333
|
+
* run a subset of route loaders on a GET request
|
|
3334
|
+
* - `opts.requestContext` is an optional server context that will be passed
|
|
3335
|
+
* to actions/loaders in the `context` parameter
|
|
3335
3336
|
*/
|
|
3336
3337
|
async function query(request, _temp3) {
|
|
3337
3338
|
let {
|
|
3339
|
+
loadRouteIds,
|
|
3338
3340
|
requestContext
|
|
3339
3341
|
} = _temp3 === void 0 ? {} : _temp3;
|
|
3340
3342
|
let url = new URL(request.url);
|
|
@@ -3388,7 +3390,7 @@ function createStaticHandler(routes, opts) {
|
|
|
3388
3390
|
activeDeferreds: null
|
|
3389
3391
|
};
|
|
3390
3392
|
}
|
|
3391
|
-
let result = await queryImpl(request, location, matches, requestContext);
|
|
3393
|
+
let result = await queryImpl(request, location, matches, requestContext, loadRouteIds || null, null);
|
|
3392
3394
|
if (isResponse(result)) {
|
|
3393
3395
|
return result;
|
|
3394
3396
|
}
|
|
@@ -3421,6 +3423,12 @@ function createStaticHandler(routes, opts) {
|
|
|
3421
3423
|
* serialize the error as they see fit while including the proper response
|
|
3422
3424
|
* code. Examples here are 404 and 405 errors that occur prior to reaching
|
|
3423
3425
|
* any user-defined loaders.
|
|
3426
|
+
*
|
|
3427
|
+
* - `opts.routeId` allows you to specify the specific route handler to call.
|
|
3428
|
+
* If not provided the handler will determine the proper route by matching
|
|
3429
|
+
* against `request.url`
|
|
3430
|
+
* - `opts.requestContext` is an optional server context that will be passed
|
|
3431
|
+
* to actions/loaders in the `context` parameter
|
|
3424
3432
|
*/
|
|
3425
3433
|
async function queryRoute(request, _temp4) {
|
|
3426
3434
|
let {
|
|
@@ -3454,7 +3462,7 @@ function createStaticHandler(routes, opts) {
|
|
|
3454
3462
|
pathname: location.pathname
|
|
3455
3463
|
});
|
|
3456
3464
|
}
|
|
3457
|
-
let result = await queryImpl(request, location, matches, requestContext, match);
|
|
3465
|
+
let result = await queryImpl(request, location, matches, requestContext, null, match);
|
|
3458
3466
|
if (isResponse(result)) {
|
|
3459
3467
|
return result;
|
|
3460
3468
|
}
|
|
@@ -3481,14 +3489,14 @@ function createStaticHandler(routes, opts) {
|
|
|
3481
3489
|
}
|
|
3482
3490
|
return undefined;
|
|
3483
3491
|
}
|
|
3484
|
-
async function queryImpl(request, location, matches, requestContext, routeMatch) {
|
|
3492
|
+
async function queryImpl(request, location, matches, requestContext, loadRouteIds, routeMatch) {
|
|
3485
3493
|
invariant(request.signal, "query()/queryRoute() requests must contain an AbortController signal");
|
|
3486
3494
|
try {
|
|
3487
3495
|
if (isMutationMethod(request.method.toLowerCase())) {
|
|
3488
|
-
let result = await submit(request, matches, routeMatch || getTargetMatch(matches, location), requestContext, routeMatch != null);
|
|
3496
|
+
let result = await submit(request, matches, routeMatch || getTargetMatch(matches, location), requestContext, loadRouteIds, routeMatch != null);
|
|
3489
3497
|
return result;
|
|
3490
3498
|
}
|
|
3491
|
-
let result = await loadRouteData(request, matches, requestContext, routeMatch);
|
|
3499
|
+
let result = await loadRouteData(request, matches, requestContext, loadRouteIds, routeMatch);
|
|
3492
3500
|
return isResponse(result) ? result : _extends({}, result, {
|
|
3493
3501
|
actionData: null,
|
|
3494
3502
|
actionHeaders: {}
|
|
@@ -3511,7 +3519,7 @@ function createStaticHandler(routes, opts) {
|
|
|
3511
3519
|
throw e;
|
|
3512
3520
|
}
|
|
3513
3521
|
}
|
|
3514
|
-
async function submit(request, matches, actionMatch, requestContext, isRouteRequest) {
|
|
3522
|
+
async function submit(request, matches, actionMatch, requestContext, loadRouteIds, isRouteRequest) {
|
|
3515
3523
|
let result;
|
|
3516
3524
|
if (!actionMatch.route.action && !actionMatch.route.lazy) {
|
|
3517
3525
|
let error = getInternalRouterError(405, {
|
|
@@ -3578,11 +3586,18 @@ function createStaticHandler(routes, opts) {
|
|
|
3578
3586
|
activeDeferreds: null
|
|
3579
3587
|
};
|
|
3580
3588
|
}
|
|
3589
|
+
|
|
3590
|
+
// Create a GET request for the loaders
|
|
3591
|
+
let loaderRequest = new Request(request.url, {
|
|
3592
|
+
headers: request.headers,
|
|
3593
|
+
redirect: request.redirect,
|
|
3594
|
+
signal: request.signal
|
|
3595
|
+
});
|
|
3581
3596
|
if (isErrorResult(result)) {
|
|
3582
3597
|
// Store off the pending error - we use it to determine which loaders
|
|
3583
3598
|
// to call and will commit it when we complete the navigation
|
|
3584
3599
|
let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id);
|
|
3585
|
-
let context = await loadRouteData(
|
|
3600
|
+
let context = await loadRouteData(loaderRequest, matches, requestContext, loadRouteIds, null, {
|
|
3586
3601
|
[boundaryMatch.route.id]: result.error
|
|
3587
3602
|
});
|
|
3588
3603
|
|
|
@@ -3595,14 +3610,7 @@ function createStaticHandler(routes, opts) {
|
|
|
3595
3610
|
} : {})
|
|
3596
3611
|
});
|
|
3597
3612
|
}
|
|
3598
|
-
|
|
3599
|
-
// Create a GET request for the loaders
|
|
3600
|
-
let loaderRequest = new Request(request.url, {
|
|
3601
|
-
headers: request.headers,
|
|
3602
|
-
redirect: request.redirect,
|
|
3603
|
-
signal: request.signal
|
|
3604
|
-
});
|
|
3605
|
-
let context = await loadRouteData(loaderRequest, matches, requestContext);
|
|
3613
|
+
let context = await loadRouteData(loaderRequest, matches, requestContext, loadRouteIds, null);
|
|
3606
3614
|
return _extends({}, context, {
|
|
3607
3615
|
actionData: {
|
|
3608
3616
|
[actionMatch.route.id]: result.data
|
|
@@ -3616,7 +3624,7 @@ function createStaticHandler(routes, opts) {
|
|
|
3616
3624
|
actionHeaders: {}
|
|
3617
3625
|
});
|
|
3618
3626
|
}
|
|
3619
|
-
async function loadRouteData(request, matches, requestContext, routeMatch, pendingActionError) {
|
|
3627
|
+
async function loadRouteData(request, matches, requestContext, loadRouteIds, routeMatch, pendingActionError) {
|
|
3620
3628
|
let isRouteRequest = routeMatch != null;
|
|
3621
3629
|
|
|
3622
3630
|
// Short circuit if we have no loaders to run (queryRoute())
|
|
@@ -3629,6 +3637,9 @@ function createStaticHandler(routes, opts) {
|
|
|
3629
3637
|
}
|
|
3630
3638
|
let requestMatches = routeMatch ? [routeMatch] : getLoaderMatchesUntilBoundary(matches, Object.keys(pendingActionError || {})[0]);
|
|
3631
3639
|
let matchesToLoad = requestMatches.filter(m => m.route.loader || m.route.lazy);
|
|
3640
|
+
if (loadRouteIds) {
|
|
3641
|
+
matchesToLoad = matchesToLoad.filter(m => loadRouteIds.includes(m.route.id));
|
|
3642
|
+
}
|
|
3632
3643
|
|
|
3633
3644
|
// Short circuit if we have no loaders to run (query())
|
|
3634
3645
|
if (matchesToLoad.length === 0) {
|
|
@@ -3924,7 +3935,7 @@ function getMatchesToLoad(history, state, matches, submission, location, isIniti
|
|
|
3924
3935
|
return false;
|
|
3925
3936
|
}
|
|
3926
3937
|
if (isInitialLoad) {
|
|
3927
|
-
if (route.loader.hydrate) {
|
|
3938
|
+
if (typeof route.loader !== "function" || route.loader.hydrate) {
|
|
3928
3939
|
return true;
|
|
3929
3940
|
}
|
|
3930
3941
|
return state.loaderData[route.id] === undefined && (
|
|
@@ -4133,13 +4144,14 @@ async function callDataStrategyImpl(dataStrategyImpl, type, request, matchesToLo
|
|
|
4133
4144
|
// back out below.
|
|
4134
4145
|
let results = await dataStrategyImpl({
|
|
4135
4146
|
matches: matches.map(match => {
|
|
4147
|
+
let bikeshed_load = routeIdsToLoad.has(match.route.id);
|
|
4136
4148
|
// `bikeshed_loadRoute` encapsulates the route.lazy, executing the
|
|
4137
4149
|
// loader/action, and mapping return values/thrown errors to a
|
|
4138
4150
|
// HandlerResult. Users can pass a callback to take fine-grained control
|
|
4139
4151
|
// over the execution of the loader/action
|
|
4140
|
-
let bikeshed_loadRoute =
|
|
4152
|
+
let bikeshed_loadRoute = handlerOverride => {
|
|
4141
4153
|
loadedMatches.add(match.route.id);
|
|
4142
|
-
return
|
|
4154
|
+
return bikeshed_load ? callLoaderOrAction(type, request, match, manifest, mapRouteProperties, handlerOverride, requestContext) :
|
|
4143
4155
|
// TODO: What's the best thing to do here - return an empty "success" result?
|
|
4144
4156
|
// Or return a success result with the current route loader/action data?
|
|
4145
4157
|
// We strip these results out if the route didn't need to be revalidated in
|
|
@@ -4151,6 +4163,7 @@ async function callDataStrategyImpl(dataStrategyImpl, type, request, matchesToLo
|
|
|
4151
4163
|
});
|
|
4152
4164
|
};
|
|
4153
4165
|
return _extends({}, match, {
|
|
4166
|
+
bikeshed_load,
|
|
4154
4167
|
bikeshed_loadRoute
|
|
4155
4168
|
});
|
|
4156
4169
|
}),
|
|
@@ -4169,7 +4182,7 @@ async function callDataStrategyImpl(dataStrategyImpl, type, request, matchesToLo
|
|
|
4169
4182
|
}
|
|
4170
4183
|
|
|
4171
4184
|
// Default logic for calling a loader/action is the user has no specified a dataStrategy
|
|
4172
|
-
async function callLoaderOrAction(type, request, match, manifest, mapRouteProperties,
|
|
4185
|
+
async function callLoaderOrAction(type, request, match, manifest, mapRouteProperties, handlerOverride, staticContext) {
|
|
4173
4186
|
let result;
|
|
4174
4187
|
let onReject;
|
|
4175
4188
|
let runHandler = handler => {
|
|
@@ -4178,12 +4191,17 @@ async function callLoaderOrAction(type, request, match, manifest, mapRouteProper
|
|
|
4178
4191
|
let abortPromise = new Promise((_, r) => reject = r);
|
|
4179
4192
|
onReject = () => reject();
|
|
4180
4193
|
request.signal.addEventListener("abort", onReject);
|
|
4181
|
-
let
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4194
|
+
let runHandlerForReal = ctx => {
|
|
4195
|
+
if (typeof handler !== "function") {
|
|
4196
|
+
return Promise.reject(new Error("You cannot call the handler for a route which defines a boolean " + ("\"" + type + "\" [routeId: " + match.route.id + "]")));
|
|
4197
|
+
}
|
|
4198
|
+
return handler({
|
|
4199
|
+
request,
|
|
4200
|
+
params: match.params,
|
|
4201
|
+
context: staticContext
|
|
4202
|
+
}, ...(ctx !== undefined ? [ctx] : []));
|
|
4185
4203
|
};
|
|
4186
|
-
let handlerPromise =
|
|
4204
|
+
let handlerPromise = handlerOverride ? handlerOverride(async ctx => runHandlerForReal(ctx)) : runHandlerForReal();
|
|
4187
4205
|
return Promise.race([handlerPromise, abortPromise]);
|
|
4188
4206
|
};
|
|
4189
4207
|
try {
|