@remix-run/router 1.4.0 → 1.5.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 +20 -1
- package/dist/index.d.ts +1 -1
- package/dist/router.cjs.js +49 -42
- package/dist/router.cjs.js.map +1 -1
- package/dist/router.d.ts +15 -8
- package/dist/router.js +49 -42
- package/dist/router.js.map +1 -1
- package/dist/router.umd.js +49 -42
- 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 +20 -3
- package/index.ts +2 -1
- package/package.json +1 -1
- package/router.ts +93 -58
- package/utils.ts +23 -3
package/dist/router.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { History, Location, Path, To } from "./history";
|
|
2
2
|
import { Action as HistoryAction } from "./history";
|
|
3
|
-
import type { AgnosticDataRouteMatch, AgnosticDataRouteObject, FormEncType, FormMethod, DetectErrorBoundaryFunction, RouteData, AgnosticRouteObject, AgnosticRouteMatch } from "./utils";
|
|
3
|
+
import type { AgnosticDataRouteMatch, AgnosticDataRouteObject, FormEncType, FormMethod, DetectErrorBoundaryFunction, RouteData, AgnosticRouteObject, AgnosticRouteMatch, V7_FormMethod, HTMLFormMethod } from "./utils";
|
|
4
4
|
import { DeferredData } from "./utils";
|
|
5
5
|
/**
|
|
6
6
|
* A Router instance manages all navigation and data loading/mutations
|
|
@@ -236,15 +236,22 @@ export interface RouterState {
|
|
|
236
236
|
* Data that can be passed into hydrate a Router from SSR
|
|
237
237
|
*/
|
|
238
238
|
export declare type HydrationState = Partial<Pick<RouterState, "loaderData" | "actionData" | "errors">>;
|
|
239
|
+
/**
|
|
240
|
+
* Future flags to toggle new feature behavior
|
|
241
|
+
*/
|
|
242
|
+
export interface FutureConfig {
|
|
243
|
+
v7_normalizeFormMethod: boolean;
|
|
244
|
+
}
|
|
239
245
|
/**
|
|
240
246
|
* Initialization options for createRouter
|
|
241
247
|
*/
|
|
242
248
|
export interface RouterInit {
|
|
243
|
-
basename?: string;
|
|
244
249
|
routes: AgnosticRouteObject[];
|
|
245
250
|
history: History;
|
|
246
|
-
|
|
251
|
+
basename?: string;
|
|
247
252
|
detectErrorBoundary?: DetectErrorBoundaryFunction;
|
|
253
|
+
future?: FutureConfig;
|
|
254
|
+
hydrationData?: HydrationState;
|
|
248
255
|
}
|
|
249
256
|
/**
|
|
250
257
|
* State returned from a server-side query() call
|
|
@@ -316,7 +323,7 @@ declare type SubmissionNavigateOptions = {
|
|
|
316
323
|
replace?: boolean;
|
|
317
324
|
state?: any;
|
|
318
325
|
preventScrollReset?: boolean;
|
|
319
|
-
formMethod?:
|
|
326
|
+
formMethod?: HTMLFormMethod;
|
|
320
327
|
formEncType?: FormEncType;
|
|
321
328
|
formData: FormData;
|
|
322
329
|
};
|
|
@@ -343,7 +350,7 @@ export declare type NavigationStates = {
|
|
|
343
350
|
Loading: {
|
|
344
351
|
state: "loading";
|
|
345
352
|
location: Location;
|
|
346
|
-
formMethod: FormMethod | undefined;
|
|
353
|
+
formMethod: FormMethod | V7_FormMethod | undefined;
|
|
347
354
|
formAction: string | undefined;
|
|
348
355
|
formEncType: FormEncType | undefined;
|
|
349
356
|
formData: FormData | undefined;
|
|
@@ -351,7 +358,7 @@ export declare type NavigationStates = {
|
|
|
351
358
|
Submitting: {
|
|
352
359
|
state: "submitting";
|
|
353
360
|
location: Location;
|
|
354
|
-
formMethod: FormMethod;
|
|
361
|
+
formMethod: FormMethod | V7_FormMethod;
|
|
355
362
|
formAction: string;
|
|
356
363
|
formEncType: FormEncType;
|
|
357
364
|
formData: FormData;
|
|
@@ -374,7 +381,7 @@ declare type FetcherStates<TData = any> = {
|
|
|
374
381
|
};
|
|
375
382
|
Loading: {
|
|
376
383
|
state: "loading";
|
|
377
|
-
formMethod: FormMethod | undefined;
|
|
384
|
+
formMethod: FormMethod | V7_FormMethod | undefined;
|
|
378
385
|
formAction: string | undefined;
|
|
379
386
|
formEncType: FormEncType | undefined;
|
|
380
387
|
formData: FormData | undefined;
|
|
@@ -383,7 +390,7 @@ declare type FetcherStates<TData = any> = {
|
|
|
383
390
|
};
|
|
384
391
|
Submitting: {
|
|
385
392
|
state: "submitting";
|
|
386
|
-
formMethod: FormMethod;
|
|
393
|
+
formMethod: FormMethod | V7_FormMethod;
|
|
387
394
|
formAction: string;
|
|
388
395
|
formEncType: FormEncType;
|
|
389
396
|
formData: FormData;
|
package/dist/router.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @remix-run/router v1.
|
|
2
|
+
* @remix-run/router v1.5.0-pre.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -1436,7 +1436,12 @@ function createRouter(init) {
|
|
|
1436
1436
|
let manifest = {}; // Routes in tree format for matching
|
|
1437
1437
|
|
|
1438
1438
|
let dataRoutes = convertRoutesToDataRoutes(init.routes, detectErrorBoundary, undefined, manifest);
|
|
1439
|
-
let inFlightDataRoutes; //
|
|
1439
|
+
let inFlightDataRoutes; // Config driven behavior flags
|
|
1440
|
+
|
|
1441
|
+
let future = _extends({
|
|
1442
|
+
v7_normalizeFormMethod: false
|
|
1443
|
+
}, init.future); // Cleanup function for history
|
|
1444
|
+
|
|
1440
1445
|
|
|
1441
1446
|
let unlistenHistory = null; // Externally-provided functions to call on all state changes
|
|
1442
1447
|
|
|
@@ -1600,35 +1605,16 @@ function createRouter(init) {
|
|
|
1600
1605
|
}
|
|
1601
1606
|
|
|
1602
1607
|
return startNavigation(historyAction, location);
|
|
1603
|
-
});
|
|
1608
|
+
}); // Kick off initial data load if needed. Use Pop to avoid modifying history
|
|
1609
|
+
// Note we don't do any handling of lazy here. For SPA's it'll get handled
|
|
1610
|
+
// in the normal navigation flow. For SSR it's expected that lazy modules are
|
|
1611
|
+
// resolved prior to router creation since we can't go into a fallbackElement
|
|
1612
|
+
// UI for SSR'd apps
|
|
1604
1613
|
|
|
1605
|
-
if (state.initialized) {
|
|
1606
|
-
return router;
|
|
1607
|
-
}
|
|
1608
|
-
|
|
1609
|
-
let lazyMatches = state.matches.filter(m => m.route.lazy);
|
|
1610
|
-
|
|
1611
|
-
if (lazyMatches.length === 0) {
|
|
1612
|
-
// Kick off initial data load if needed. Use Pop to avoid modifying history
|
|
1614
|
+
if (!state.initialized) {
|
|
1613
1615
|
startNavigation(Action.Pop, state.location);
|
|
1614
|
-
|
|
1615
|
-
} // Load lazy modules, then kick off initial data load if needed
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
let lazyPromises = lazyMatches.map(m => loadLazyRouteModule(m.route, detectErrorBoundary, manifest));
|
|
1619
|
-
Promise.all(lazyPromises).then(() => {
|
|
1620
|
-
let initialized = !state.matches.some(m => m.route.loader) || init.hydrationData != null;
|
|
1616
|
+
}
|
|
1621
1617
|
|
|
1622
|
-
if (initialized) {
|
|
1623
|
-
// We already have required loaderData so we can just set initialized
|
|
1624
|
-
updateState({
|
|
1625
|
-
initialized: true
|
|
1626
|
-
});
|
|
1627
|
-
} else {
|
|
1628
|
-
// We still need to kick off initial data loads
|
|
1629
|
-
startNavigation(Action.Pop, state.location);
|
|
1630
|
-
}
|
|
1631
|
-
});
|
|
1632
1618
|
return router;
|
|
1633
1619
|
} // Clean up a router and it's side effects
|
|
1634
1620
|
|
|
@@ -1744,7 +1730,7 @@ function createRouter(init) {
|
|
|
1744
1730
|
path,
|
|
1745
1731
|
submission,
|
|
1746
1732
|
error
|
|
1747
|
-
} = normalizeNavigateOptions(to, opts);
|
|
1733
|
+
} = normalizeNavigateOptions(to, future, opts);
|
|
1748
1734
|
let currentLocation = state.location;
|
|
1749
1735
|
let nextLocation = createLocation(state.location, path, opts && opts.state); // When using navigate as a PUSH/REPLACE we aren't reading an already-encoded
|
|
1750
1736
|
// URL from window.location, so we need to encode it here so the behavior
|
|
@@ -1936,7 +1922,7 @@ function createRouter(init) {
|
|
|
1936
1922
|
shortCircuited,
|
|
1937
1923
|
loaderData,
|
|
1938
1924
|
errors
|
|
1939
|
-
} = await handleLoaders(request, location, matches, loadingNavigation, opts && opts.submission, opts && opts.replace, pendingActionData, pendingError);
|
|
1925
|
+
} = await handleLoaders(request, location, matches, loadingNavigation, opts && opts.submission, opts && opts.fetcherSubmission, opts && opts.replace, pendingActionData, pendingError);
|
|
1940
1926
|
|
|
1941
1927
|
if (shortCircuited) {
|
|
1942
1928
|
return;
|
|
@@ -2049,7 +2035,7 @@ function createRouter(init) {
|
|
|
2049
2035
|
// errors, etc.
|
|
2050
2036
|
|
|
2051
2037
|
|
|
2052
|
-
async function handleLoaders(request, location, matches, overrideNavigation, submission, replace, pendingActionData, pendingError) {
|
|
2038
|
+
async function handleLoaders(request, location, matches, overrideNavigation, submission, fetcherSubmission, replace, pendingActionData, pendingError) {
|
|
2053
2039
|
// Figure out the right navigation we want to use for data loading
|
|
2054
2040
|
let loadingNavigation = overrideNavigation;
|
|
2055
2041
|
|
|
@@ -2068,7 +2054,7 @@ function createRouter(init) {
|
|
|
2068
2054
|
// we have it on the loading navigation so use that if available
|
|
2069
2055
|
|
|
2070
2056
|
|
|
2071
|
-
let activeSubmission = submission ? submission : loadingNavigation.formMethod && loadingNavigation.formAction && loadingNavigation.formData && loadingNavigation.formEncType ? {
|
|
2057
|
+
let activeSubmission = submission || fetcherSubmission ? submission || fetcherSubmission : loadingNavigation.formMethod && loadingNavigation.formAction && loadingNavigation.formData && loadingNavigation.formEncType ? {
|
|
2072
2058
|
formMethod: loadingNavigation.formMethod,
|
|
2073
2059
|
formAction: loadingNavigation.formAction,
|
|
2074
2060
|
formData: loadingNavigation.formData,
|
|
@@ -2205,7 +2191,7 @@ function createRouter(init) {
|
|
|
2205
2191
|
let {
|
|
2206
2192
|
path,
|
|
2207
2193
|
submission
|
|
2208
|
-
} = normalizeNavigateOptions(href, opts, true);
|
|
2194
|
+
} = normalizeNavigateOptions(href, future, opts, true);
|
|
2209
2195
|
let match = getTargetMatch(matches, path);
|
|
2210
2196
|
pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;
|
|
2211
2197
|
|
|
@@ -2285,6 +2271,7 @@ function createRouter(init) {
|
|
|
2285
2271
|
fetchers: new Map(state.fetchers)
|
|
2286
2272
|
});
|
|
2287
2273
|
return startRedirectNavigation(state, actionResult, {
|
|
2274
|
+
submission,
|
|
2288
2275
|
isFetchActionRedirect: true
|
|
2289
2276
|
});
|
|
2290
2277
|
} // Process any non-redirect errors thrown
|
|
@@ -2575,6 +2562,22 @@ function createRouter(init) {
|
|
|
2575
2562
|
// Preserve this flag across redirects
|
|
2576
2563
|
preventScrollReset: pendingPreventScrollReset
|
|
2577
2564
|
});
|
|
2565
|
+
} else if (isFetchActionRedirect) {
|
|
2566
|
+
// For a fetch action redirect, we kick off a new loading navigation
|
|
2567
|
+
// without the fetcher submission, but we send it along for shouldRevalidate
|
|
2568
|
+
await startNavigation(redirectHistoryAction, redirectLocation, {
|
|
2569
|
+
overrideNavigation: {
|
|
2570
|
+
state: "loading",
|
|
2571
|
+
location: redirectLocation,
|
|
2572
|
+
formMethod: undefined,
|
|
2573
|
+
formAction: undefined,
|
|
2574
|
+
formEncType: undefined,
|
|
2575
|
+
formData: undefined
|
|
2576
|
+
},
|
|
2577
|
+
fetcherSubmission: submission,
|
|
2578
|
+
// Preserve this flag across redirects
|
|
2579
|
+
preventScrollReset: pendingPreventScrollReset
|
|
2580
|
+
});
|
|
2578
2581
|
} else {
|
|
2579
2582
|
// Otherwise, we kick off a new loading navigation, preserving the
|
|
2580
2583
|
// submission info for the duration of this navigation
|
|
@@ -2920,11 +2923,11 @@ function createStaticHandler(routes, opts) {
|
|
|
2920
2923
|
requestContext
|
|
2921
2924
|
} = _temp2 === void 0 ? {} : _temp2;
|
|
2922
2925
|
let url = new URL(request.url);
|
|
2923
|
-
let method = request.method
|
|
2926
|
+
let method = request.method;
|
|
2924
2927
|
let location = createLocation("", createPath(url), null, "default");
|
|
2925
2928
|
let matches = matchRoutes(dataRoutes, location, basename); // SSR supports HEAD requests while SPA doesn't
|
|
2926
2929
|
|
|
2927
|
-
if (!isValidMethod(method) && method !== "
|
|
2930
|
+
if (!isValidMethod(method) && method !== "HEAD") {
|
|
2928
2931
|
let error = getInternalRouterError(405, {
|
|
2929
2932
|
method
|
|
2930
2933
|
});
|
|
@@ -3012,11 +3015,11 @@ function createStaticHandler(routes, opts) {
|
|
|
3012
3015
|
requestContext
|
|
3013
3016
|
} = _temp3 === void 0 ? {} : _temp3;
|
|
3014
3017
|
let url = new URL(request.url);
|
|
3015
|
-
let method = request.method
|
|
3018
|
+
let method = request.method;
|
|
3016
3019
|
let location = createLocation("", createPath(url), null, "default");
|
|
3017
3020
|
let matches = matchRoutes(dataRoutes, location, basename); // SSR supports HEAD requests while SPA doesn't
|
|
3018
3021
|
|
|
3019
|
-
if (!isValidMethod(method) && method !== "
|
|
3022
|
+
if (!isValidMethod(method) && method !== "HEAD" && method !== "OPTIONS") {
|
|
3020
3023
|
throw getInternalRouterError(405, {
|
|
3021
3024
|
method
|
|
3022
3025
|
});
|
|
@@ -3309,7 +3312,7 @@ function isSubmissionNavigation(opts) {
|
|
|
3309
3312
|
// URLSearchParams so they behave identically to links with query params
|
|
3310
3313
|
|
|
3311
3314
|
|
|
3312
|
-
function normalizeNavigateOptions(to, opts, isFetcher) {
|
|
3315
|
+
function normalizeNavigateOptions(to, future, opts, isFetcher) {
|
|
3313
3316
|
if (isFetcher === void 0) {
|
|
3314
3317
|
isFetcher = false;
|
|
3315
3318
|
}
|
|
@@ -3335,8 +3338,9 @@ function normalizeNavigateOptions(to, opts, isFetcher) {
|
|
|
3335
3338
|
let submission;
|
|
3336
3339
|
|
|
3337
3340
|
if (opts.formData) {
|
|
3341
|
+
let formMethod = opts.formMethod || "get";
|
|
3338
3342
|
submission = {
|
|
3339
|
-
formMethod:
|
|
3343
|
+
formMethod: future.v7_normalizeFormMethod ? formMethod.toUpperCase() : formMethod.toLowerCase(),
|
|
3340
3344
|
formAction: stripHashFromPath(path),
|
|
3341
3345
|
formEncType: opts && opts.formEncType || "application/x-www-form-urlencoded",
|
|
3342
3346
|
formData: opts.formData
|
|
@@ -3776,7 +3780,10 @@ function createClientSideRequest(history, location, signal, submission) {
|
|
|
3776
3780
|
formMethod,
|
|
3777
3781
|
formEncType,
|
|
3778
3782
|
formData
|
|
3779
|
-
} = submission;
|
|
3783
|
+
} = submission; // Didn't think we needed this but it turns out unlike other methods, patch
|
|
3784
|
+
// won't be properly normalized to uppercase and results in a 405 error.
|
|
3785
|
+
// See: https://fetch.spec.whatwg.org/#concept-method
|
|
3786
|
+
|
|
3780
3787
|
init.method = formMethod.toUpperCase();
|
|
3781
3788
|
init.body = formEncType === "application/x-www-form-urlencoded" ? convertFormDataToSearchParams(formData) : formData;
|
|
3782
3789
|
} // Content-Type is inferred (https://fetch.spec.whatwg.org/#dom-request)
|
|
@@ -4065,11 +4072,11 @@ function isQueryRouteResponse(obj) {
|
|
|
4065
4072
|
}
|
|
4066
4073
|
|
|
4067
4074
|
function isValidMethod(method) {
|
|
4068
|
-
return validRequestMethods.has(method);
|
|
4075
|
+
return validRequestMethods.has(method.toLowerCase());
|
|
4069
4076
|
}
|
|
4070
4077
|
|
|
4071
4078
|
function isMutationMethod(method) {
|
|
4072
|
-
return validMutationMethods.has(method);
|
|
4079
|
+
return validMutationMethods.has(method.toLowerCase());
|
|
4073
4080
|
}
|
|
4074
4081
|
|
|
4075
4082
|
async function resolveDeferredResults(currentMatches, matchesToLoad, results, signal, isFetcher, currentLoaderData) {
|