@octanejs/remix-router 0.1.0 → 0.1.2
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/README.md +20 -6
- package/package.json +12 -7
- package/src/index.ts +16 -14
- package/src/lib/Await.tsrx +1 -1
- package/src/lib/DefaultErrorComponent.tsrx +3 -3
- package/src/lib/RenderErrorBoundary.tsrx +1 -1
- package/src/lib/actions.ts +1 -1
- package/src/lib/components/MemoryRouter.tsrx +1 -1
- package/src/lib/components/Navigate.ts +1 -1
- package/src/lib/components/Router.tsrx +1 -1
- package/src/lib/components/RouterProvider.tsrx +1 -1
- package/src/lib/components/Routes.tsrx +1 -1
- package/src/lib/components/routes-collector.ts +1 -8
- package/src/lib/components/utils.ts +4 -65
- package/src/lib/components/with-props.ts +1 -1
- package/src/lib/context.ts +2 -4
- package/src/lib/dom/Form.tsrx +1 -1
- package/src/lib/dom/Link.tsrx +1 -1
- package/src/lib/dom/NavLink.tsrx +1 -1
- package/src/lib/dom/dom.ts +1 -1
- package/src/lib/dom/hooks.ts +1 -1
- package/src/lib/dom/lib.ts +8 -7
- package/src/lib/dom/routers.tsrx +1 -1
- package/src/lib/dom/server.tsrx +6 -28
- package/src/lib/errors.ts +1 -1
- package/src/lib/hooks.ts +6 -16
- package/src/lib/href.ts +9 -4
- package/src/lib/router/history.ts +2 -2
- package/src/lib/router/instrumentation.ts +391 -187
- package/src/lib/router/links.ts +1 -1
- package/src/lib/router/router.ts +128 -78
- package/src/lib/router/server-runtime-types.ts +8 -11
- package/src/lib/router/url.ts +1 -1
- package/src/lib/router/utils.ts +107 -31
- package/src/lib/server-runtime/cookies.ts +7 -7
- package/src/lib/server-runtime/crypto.ts +2 -2
- package/src/lib/server-runtime/mode.ts +1 -1
- package/src/lib/server-runtime/sessions/cookieStorage.ts +1 -1
- package/src/lib/server-runtime/sessions/memoryStorage.ts +1 -1
- package/src/lib/server-runtime/sessions.ts +8 -5
- package/src/lib/server-runtime/warnings.ts +1 -1
- package/src/lib/types/future.ts +1 -7
- package/src/lib/types/params.ts +1 -1
- package/src/lib/types/register.ts +1 -1
- package/src/lib/types/route-module.ts +1 -1
- package/src/lib/types/utils.ts +1 -1
package/src/lib/router/links.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Vendored from react-router@
|
|
1
|
+
// Vendored from react-router@8.2.0 packages/react-router/lib/router/links.ts — unmodified.
|
|
2
2
|
// Re-vendor with `node scripts/vendor-remix-router.mjs`; never hand-edit.
|
|
3
3
|
type Primitive = null | undefined | string | number | boolean | symbol | bigint;
|
|
4
4
|
|
package/src/lib/router/router.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Vendored from react-router@
|
|
1
|
+
// Vendored from react-router@8.2.0 packages/react-router/lib/router/router.ts — unmodified.
|
|
2
2
|
// Re-vendor with `node scripts/vendor-remix-router.mjs`; never hand-edit.
|
|
3
3
|
import type { History, Location, Path, To } from './history';
|
|
4
4
|
import {
|
|
@@ -12,11 +12,17 @@ import {
|
|
|
12
12
|
} from './history';
|
|
13
13
|
import type {
|
|
14
14
|
ClientInstrumentation,
|
|
15
|
+
InstrumentationMetaReceiver,
|
|
16
|
+
InstrumentationResultMeta,
|
|
15
17
|
InstrumentRouteFunction,
|
|
16
18
|
InstrumentRouterFunction,
|
|
17
19
|
ServerInstrumentation,
|
|
18
20
|
} from './instrumentation';
|
|
19
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
consumeInstrumentationClientResultMetaReceiver,
|
|
23
|
+
getRouteInstrumentationUpdates,
|
|
24
|
+
instrumentClientSideRouter,
|
|
25
|
+
} from './instrumentation';
|
|
20
26
|
import type {
|
|
21
27
|
DataRouteMatch,
|
|
22
28
|
DataRouteObject,
|
|
@@ -30,7 +36,6 @@ import type {
|
|
|
30
36
|
FormMethod,
|
|
31
37
|
HTMLFormMethod,
|
|
32
38
|
DataStrategyResult,
|
|
33
|
-
MapRoutePropertiesFunction,
|
|
34
39
|
MaybePromise,
|
|
35
40
|
MutationFormMethod,
|
|
36
41
|
RedirectResult,
|
|
@@ -49,12 +54,14 @@ import type {
|
|
|
49
54
|
MiddlewareNextFunction,
|
|
50
55
|
PatchRoutesOnNavigationFunction,
|
|
51
56
|
RouteBranch,
|
|
57
|
+
MapRoutePropertiesFunction,
|
|
52
58
|
} from './utils';
|
|
53
59
|
import {
|
|
54
60
|
ErrorResponseImpl,
|
|
55
61
|
ResultType,
|
|
56
62
|
convertRouteMatchToUiMatch,
|
|
57
63
|
convertRoutesToDataRoutes,
|
|
64
|
+
createDataFunctionUrl,
|
|
58
65
|
getPathContributingMatches,
|
|
59
66
|
getResolveToMatches,
|
|
60
67
|
isAbsoluteUrl,
|
|
@@ -337,7 +344,7 @@ export interface Router {
|
|
|
337
344
|
* reflect the "old" location unless otherwise noted.
|
|
338
345
|
*/
|
|
339
346
|
export interface RouterState {
|
|
340
|
-
// TODO: (
|
|
347
|
+
// TODO: (v9) should we consider renaming this `navigationType` to align with
|
|
341
348
|
// `useNavigationType` at some point?
|
|
342
349
|
/**
|
|
343
350
|
* The action of the most recent navigation
|
|
@@ -897,10 +904,6 @@ export const IDLE_BLOCKER: BlockerUnblocked = {
|
|
|
897
904
|
location: undefined,
|
|
898
905
|
};
|
|
899
906
|
|
|
900
|
-
const defaultMapRouteProperties: MapRoutePropertiesFunction = (route) => ({
|
|
901
|
-
hasErrorBoundary: Boolean(route.hasErrorBoundary),
|
|
902
|
-
});
|
|
903
|
-
|
|
904
907
|
const TRANSITIONS_STORAGE_KEY = 'remix-router-transitions';
|
|
905
908
|
|
|
906
909
|
// Flag used on new `loaderData` to indicate that we do not want to preserve
|
|
@@ -987,8 +990,10 @@ export function createRouter(init: RouterInit): Router {
|
|
|
987
990
|
invariant(init.routes.length > 0, 'You must provide a non-empty routes array to createRouter');
|
|
988
991
|
|
|
989
992
|
let hydrationRouteProperties = init.hydrationRouteProperties || [];
|
|
990
|
-
let _mapRouteProperties = init.mapRouteProperties
|
|
991
|
-
let mapRouteProperties = _mapRouteProperties
|
|
993
|
+
let _mapRouteProperties = init.mapRouteProperties;
|
|
994
|
+
let mapRouteProperties: MapRoutePropertiesFunction = _mapRouteProperties
|
|
995
|
+
? _mapRouteProperties
|
|
996
|
+
: () => ({});
|
|
992
997
|
|
|
993
998
|
// Leverage the existing mapRouteProperties logic to execute instrumentRoute
|
|
994
999
|
// (if it exists) on all routes in the application
|
|
@@ -997,7 +1002,7 @@ export function createRouter(init: RouterInit): Router {
|
|
|
997
1002
|
|
|
998
1003
|
mapRouteProperties = (route: DataRouteObject) => {
|
|
999
1004
|
return {
|
|
1000
|
-
..._mapRouteProperties(route),
|
|
1005
|
+
..._mapRouteProperties?.(route),
|
|
1001
1006
|
...getRouteInstrumentationUpdates(
|
|
1002
1007
|
instrumentations.map((i) => i.route).filter(Boolean) as InstrumentRouteFunction[],
|
|
1003
1008
|
route,
|
|
@@ -1490,9 +1495,10 @@ export function createRouter(init: RouterInit): Router {
|
|
|
1490
1495
|
: state.loaderData;
|
|
1491
1496
|
|
|
1492
1497
|
// On a successful navigation we can assume we got through all blockers
|
|
1493
|
-
// so we can start fresh
|
|
1498
|
+
// so we can start fresh. A revalidation is not a navigation, so it must
|
|
1499
|
+
// leave any active blocker untouched.
|
|
1494
1500
|
let blockers = state.blockers;
|
|
1495
|
-
if (blockers.size > 0) {
|
|
1501
|
+
if (blockers.size > 0 && !isUninterruptedRevalidation) {
|
|
1496
1502
|
blockers = new Map(blockers);
|
|
1497
1503
|
blockers.forEach((_, k) => blockers.set(k, IDLE_BLOCKER));
|
|
1498
1504
|
}
|
|
@@ -1620,6 +1626,11 @@ export function createRouter(init: RouterInit): Router {
|
|
|
1620
1626
|
return promise;
|
|
1621
1627
|
}
|
|
1622
1628
|
|
|
1629
|
+
// Consume this immediately before any async work kicks off so it doesn't stick
|
|
1630
|
+
// around for subsequent interrupting navigations
|
|
1631
|
+
let instrumentationNavigateMetaReceiver =
|
|
1632
|
+
consumeInstrumentationClientResultMetaReceiver(router);
|
|
1633
|
+
|
|
1623
1634
|
let normalizedPath = normalizeTo(
|
|
1624
1635
|
state.location,
|
|
1625
1636
|
state.matches,
|
|
@@ -1732,6 +1743,7 @@ export function createRouter(init: RouterInit): Router {
|
|
|
1732
1743
|
enableViewTransition: opts && opts.viewTransition,
|
|
1733
1744
|
flushSync,
|
|
1734
1745
|
callSiteDefaultShouldRevalidate: opts && opts.defaultShouldRevalidate,
|
|
1746
|
+
instrumentationNavigateMetaReceiver,
|
|
1735
1747
|
});
|
|
1736
1748
|
}
|
|
1737
1749
|
|
|
@@ -1804,6 +1816,7 @@ export function createRouter(init: RouterInit): Router {
|
|
|
1804
1816
|
enableViewTransition?: boolean;
|
|
1805
1817
|
flushSync?: boolean;
|
|
1806
1818
|
callSiteDefaultShouldRevalidate?: boolean;
|
|
1819
|
+
instrumentationNavigateMetaReceiver?: InstrumentationMetaReceiver;
|
|
1807
1820
|
},
|
|
1808
1821
|
): Promise<void> {
|
|
1809
1822
|
// Abort any in-progress navigations and start a new one. Unset any ongoing
|
|
@@ -1851,6 +1864,11 @@ export function createRouter(init: RouterInit): Router {
|
|
|
1851
1864
|
matches = fogOfWar.matches;
|
|
1852
1865
|
}
|
|
1853
1866
|
|
|
1867
|
+
if (opts?.instrumentationNavigateMetaReceiver) {
|
|
1868
|
+
let meta = getInstrumentationNavigateMeta(init.history, location, matches);
|
|
1869
|
+
opts.instrumentationNavigateMetaReceiver(meta);
|
|
1870
|
+
}
|
|
1871
|
+
|
|
1854
1872
|
// Short circuit with a 404 on the root error boundary if we match nothing
|
|
1855
1873
|
if (!matches) {
|
|
1856
1874
|
let { error, notFoundMatches, route } = handleNavigational404(location.pathname);
|
|
@@ -2412,7 +2430,7 @@ export function createRouter(init: RouterInit): Router {
|
|
|
2412
2430
|
if (pendingActionResult && !isErrorResult(pendingActionResult[1])) {
|
|
2413
2431
|
// This is cast to `any` currently because `RouteData`uses any and it
|
|
2414
2432
|
// would be a breaking change to use any.
|
|
2415
|
-
// TODO:
|
|
2433
|
+
// TODO: (v9) change `RouteData` to use `unknown` instead of `any`
|
|
2416
2434
|
return {
|
|
2417
2435
|
[pendingActionResult[0]]: pendingActionResult[1].data as any,
|
|
2418
2436
|
};
|
|
@@ -2446,6 +2464,10 @@ export function createRouter(init: RouterInit): Router {
|
|
|
2446
2464
|
|
|
2447
2465
|
let flushSync = (opts && opts.flushSync) === true;
|
|
2448
2466
|
|
|
2467
|
+
// Consume this immediately before any async work kicks off so it doesn't stick
|
|
2468
|
+
// around for subsequent interrupting calls
|
|
2469
|
+
let instrumentationResultMetaReceiver = consumeInstrumentationClientResultMetaReceiver(router);
|
|
2470
|
+
|
|
2449
2471
|
let routesToUse = dataRoutes.activeRoutes;
|
|
2450
2472
|
let normalizedPath = normalizeTo(
|
|
2451
2473
|
state.location,
|
|
@@ -2468,6 +2490,11 @@ export function createRouter(init: RouterInit): Router {
|
|
|
2468
2490
|
matches = fogOfWar.matches;
|
|
2469
2491
|
}
|
|
2470
2492
|
|
|
2493
|
+
if (instrumentationResultMetaReceiver) {
|
|
2494
|
+
let meta = getInstrumentationNavigateMeta(init.history, normalizedPath, matches);
|
|
2495
|
+
instrumentationResultMetaReceiver(meta);
|
|
2496
|
+
}
|
|
2497
|
+
|
|
2471
2498
|
if (!matches) {
|
|
2472
2499
|
setFetcherError(key, routeId, getInternalRouterError(404, { pathname: normalizedPath }), {
|
|
2473
2500
|
flushSync,
|
|
@@ -3757,6 +3784,36 @@ export interface CreateStaticHandlerOptions {
|
|
|
3757
3784
|
future?: Partial<FutureConfig>;
|
|
3758
3785
|
}
|
|
3759
3786
|
|
|
3787
|
+
/**
|
|
3788
|
+
* Create a static handler to perform server-side data loading
|
|
3789
|
+
*
|
|
3790
|
+
* @example
|
|
3791
|
+
* export async function handleRequest(request: Request) {
|
|
3792
|
+
* let { query, dataRoutes } = createStaticHandler(routes);
|
|
3793
|
+
* let context = await query(request);
|
|
3794
|
+
*
|
|
3795
|
+
* if (context instanceof Response) {
|
|
3796
|
+
* return context;
|
|
3797
|
+
* }
|
|
3798
|
+
*
|
|
3799
|
+
* let router = createStaticRouter(dataRoutes, context);
|
|
3800
|
+
* return new Response(
|
|
3801
|
+
* ReactDOMServer.renderToString(<StaticRouterProvider ... />),
|
|
3802
|
+
* { headers: { "Content-Type": "text/html" } }
|
|
3803
|
+
* );
|
|
3804
|
+
* }
|
|
3805
|
+
*
|
|
3806
|
+
* @public
|
|
3807
|
+
* @category Data Routers
|
|
3808
|
+
* @mode data
|
|
3809
|
+
* @param routes The {@link RouteObject | route objects} to create a static
|
|
3810
|
+
* handler for
|
|
3811
|
+
* @param opts Options
|
|
3812
|
+
* @param opts.basename The base URL for the static handler (default: `/`)
|
|
3813
|
+
* @param opts.future Future flags for the static handler
|
|
3814
|
+
* @returns A static handler that can be used to query data for the provided
|
|
3815
|
+
* routes
|
|
3816
|
+
*/
|
|
3760
3817
|
export function createStaticHandler(
|
|
3761
3818
|
routes: RouteObject[],
|
|
3762
3819
|
opts?: CreateStaticHandlerOptions,
|
|
@@ -3765,8 +3822,10 @@ export function createStaticHandler(
|
|
|
3765
3822
|
|
|
3766
3823
|
let manifest: RouteManifest = {};
|
|
3767
3824
|
let basename = (opts ? opts.basename : null) || '/';
|
|
3768
|
-
let _mapRouteProperties = opts?.mapRouteProperties
|
|
3769
|
-
let mapRouteProperties = _mapRouteProperties
|
|
3825
|
+
let _mapRouteProperties = opts?.mapRouteProperties;
|
|
3826
|
+
let mapRouteProperties: MapRoutePropertiesFunction = _mapRouteProperties
|
|
3827
|
+
? _mapRouteProperties
|
|
3828
|
+
: () => ({});
|
|
3770
3829
|
// Currently unused in the static handler, but available for additional flags in the future
|
|
3771
3830
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
3772
3831
|
let future: FutureConfig = {
|
|
@@ -3780,7 +3839,7 @@ export function createStaticHandler(
|
|
|
3780
3839
|
|
|
3781
3840
|
mapRouteProperties = (route: DataRouteObject) => {
|
|
3782
3841
|
return {
|
|
3783
|
-
..._mapRouteProperties(route),
|
|
3842
|
+
..._mapRouteProperties?.(route),
|
|
3784
3843
|
...getRouteInstrumentationUpdates(
|
|
3785
3844
|
instrumentations.map((i) => i.route).filter(Boolean) as InstrumentRouteFunction[],
|
|
3786
3845
|
route,
|
|
@@ -3910,9 +3969,7 @@ export function createStaticHandler(
|
|
|
3910
3969
|
pattern: getRoutePattern(matches),
|
|
3911
3970
|
matches,
|
|
3912
3971
|
params: matches[0].params,
|
|
3913
|
-
|
|
3914
|
-
// this to the proper type knowing it's not an `AppLoadContext`
|
|
3915
|
-
context: requestContext as RouterContextProvider,
|
|
3972
|
+
context: requestContext,
|
|
3916
3973
|
},
|
|
3917
3974
|
async () => {
|
|
3918
3975
|
let res = await generateMiddlewareResponse(
|
|
@@ -4134,9 +4191,7 @@ export function createStaticHandler(
|
|
|
4134
4191
|
pattern: getRoutePattern(matches),
|
|
4135
4192
|
matches,
|
|
4136
4193
|
params: matches[0].params,
|
|
4137
|
-
|
|
4138
|
-
// this to the proper type knowing it's not an `AppLoadContext`
|
|
4139
|
-
context: requestContext as RouterContextProvider,
|
|
4194
|
+
context: requestContext,
|
|
4140
4195
|
},
|
|
4141
4196
|
async () => {
|
|
4142
4197
|
let res = await generateMiddlewareResponse(async (innerRequest: Request) => {
|
|
@@ -5087,9 +5142,7 @@ function getMatchesToLoad(
|
|
|
5087
5142
|
fetchLoadMatches.forEach((f, key) => {
|
|
5088
5143
|
// Don't revalidate:
|
|
5089
5144
|
// - on initial hydration (shouldn't be any fetchers then anyway)
|
|
5090
|
-
// - if fetcher won't be present in the subsequent render
|
|
5091
|
-
// - no longer matches the URL (v7_fetcherPersist=false)
|
|
5092
|
-
// - was unmounted but persisted due to v7_fetcherPersist=true
|
|
5145
|
+
// - if fetcher won't be present in the subsequent render (was unmounted but persisted)
|
|
5093
5146
|
if (
|
|
5094
5147
|
initialHydration ||
|
|
5095
5148
|
!matches.some((m) => m.route.id === f.routeId) ||
|
|
@@ -5357,9 +5410,9 @@ function patchRoutesImpl(
|
|
|
5357
5410
|
for (let i = 0; i < existingChildren.length; i++) {
|
|
5358
5411
|
let { existingRoute, newRoute } = existingChildren[i];
|
|
5359
5412
|
let existingRouteTyped = existingRoute as RouteObject;
|
|
5360
|
-
//
|
|
5361
|
-
//
|
|
5362
|
-
// we
|
|
5413
|
+
// This likely ends up being a no-op since there's no need for Component->element
|
|
5414
|
+
// conversions since we're already dealing with elements here. But kept for
|
|
5415
|
+
// safety and future proofing if we added any more logic to mapRouteProperties
|
|
5363
5416
|
let [newRouteTyped] = convertRoutesToDataRoutes(
|
|
5364
5417
|
[newRoute],
|
|
5365
5418
|
mapRouteProperties,
|
|
@@ -5466,7 +5519,7 @@ const loadLazyRouteProperty = ({
|
|
|
5466
5519
|
let propertyPromise = (async () => {
|
|
5467
5520
|
let isUnsupported = isUnsupportedLazyRouteObjectKey(key);
|
|
5468
5521
|
let staticRouteValue = routeToUpdate[key as keyof typeof routeToUpdate];
|
|
5469
|
-
let isStaticallyDefined = staticRouteValue !== undefined
|
|
5522
|
+
let isStaticallyDefined = staticRouteValue !== undefined;
|
|
5470
5523
|
|
|
5471
5524
|
if (isUnsupported) {
|
|
5472
5525
|
warning(
|
|
@@ -5566,11 +5619,7 @@ function loadLazyRoute(
|
|
|
5566
5619
|
|
|
5567
5620
|
let isUnsupported = isUnsupportedLazyRouteFunctionKey(lazyRouteProperty);
|
|
5568
5621
|
let staticRouteValue = routeToUpdate[lazyRouteProperty as keyof typeof routeToUpdate];
|
|
5569
|
-
let isStaticallyDefined =
|
|
5570
|
-
staticRouteValue !== undefined &&
|
|
5571
|
-
// This property isn't static since it should always be updated based
|
|
5572
|
-
// on the route updates
|
|
5573
|
-
lazyRouteProperty !== 'hasErrorBoundary';
|
|
5622
|
+
let isStaticallyDefined = staticRouteValue !== undefined;
|
|
5574
5623
|
|
|
5575
5624
|
if (isUnsupported) {
|
|
5576
5625
|
warning(
|
|
@@ -5595,13 +5644,13 @@ function loadLazyRoute(
|
|
|
5595
5644
|
// the updated version to mapRouteProperties
|
|
5596
5645
|
Object.assign(routeToUpdate, routeUpdates);
|
|
5597
5646
|
|
|
5598
|
-
// Mutate the
|
|
5599
|
-
//
|
|
5600
|
-
// route again.
|
|
5647
|
+
// Mutate the route with framework-aware property updates (e.g.,
|
|
5648
|
+
// `Component`->`element` conversions) and remove the `lazy` function so
|
|
5649
|
+
// we don't resolve the lazy route again.
|
|
5601
5650
|
Object.assign(routeToUpdate, {
|
|
5602
5651
|
// To keep things framework agnostic, we use the provided `mapRouteProperties`
|
|
5603
|
-
// function to set
|
|
5604
|
-
//
|
|
5652
|
+
// function to set framework-aware properties since the logic will
|
|
5653
|
+
// differ between frameworks.
|
|
5605
5654
|
...mapRouteProperties(routeToUpdate),
|
|
5606
5655
|
lazy: undefined,
|
|
5607
5656
|
});
|
|
@@ -5751,17 +5800,15 @@ function runClientMiddlewarePipeline(
|
|
|
5751
5800
|
);
|
|
5752
5801
|
|
|
5753
5802
|
// Handle error bubbling on the client
|
|
5754
|
-
function errorHandler(
|
|
5803
|
+
async function errorHandler(
|
|
5755
5804
|
error: unknown,
|
|
5756
5805
|
routeId: string,
|
|
5757
5806
|
nextResult: { value: Record<string, DataStrategyResult> } | undefined,
|
|
5758
5807
|
): Promise<Record<string, DataStrategyResult>> {
|
|
5759
5808
|
if (nextResult) {
|
|
5760
|
-
return
|
|
5761
|
-
|
|
5762
|
-
|
|
5763
|
-
}),
|
|
5764
|
-
);
|
|
5809
|
+
return Object.assign(nextResult.value, {
|
|
5810
|
+
[routeId]: { type: 'error', result: error },
|
|
5811
|
+
});
|
|
5765
5812
|
} else {
|
|
5766
5813
|
// We never even got to the handlers, so we might not have data for new routes.
|
|
5767
5814
|
// Find the boundary at or above the source of the middleware error or the
|
|
@@ -5780,10 +5827,24 @@ function runClientMiddlewarePipeline(
|
|
|
5780
5827
|
0,
|
|
5781
5828
|
),
|
|
5782
5829
|
);
|
|
5783
|
-
|
|
5784
|
-
|
|
5830
|
+
|
|
5831
|
+
let deepestRouteId = matches[maxBoundaryIdx].route.id;
|
|
5832
|
+
|
|
5833
|
+
// Await lazy route promises before bubbling so any lazy error boundaries
|
|
5834
|
+
// have been loaded
|
|
5835
|
+
for (let match of matches.slice(0, maxBoundaryIdx + 1)) {
|
|
5836
|
+
try {
|
|
5837
|
+
await match._lazyPromises?.route;
|
|
5838
|
+
} catch {
|
|
5839
|
+
deepestRouteId = match.route.id;
|
|
5840
|
+
break;
|
|
5841
|
+
}
|
|
5842
|
+
}
|
|
5843
|
+
|
|
5844
|
+
let boundaryRouteId = findNearestBoundary(matches, deepestRouteId).route.id;
|
|
5845
|
+
return {
|
|
5785
5846
|
[boundaryRouteId]: { type: 'error', result: error },
|
|
5786
|
-
}
|
|
5847
|
+
};
|
|
5787
5848
|
}
|
|
5788
5849
|
}
|
|
5789
5850
|
}
|
|
@@ -6160,7 +6221,7 @@ async function callLoaderOrAction({
|
|
|
6160
6221
|
let isAction = isMutationMethod(request.method);
|
|
6161
6222
|
let type = isAction ? 'action' : 'loader';
|
|
6162
6223
|
let runHandler = (
|
|
6163
|
-
handler: boolean | LoaderFunction<
|
|
6224
|
+
handler: boolean | LoaderFunction<any> | ActionFunction<any>,
|
|
6164
6225
|
): Promise<DataStrategyResult> => {
|
|
6165
6226
|
// Setup a promise we can race against so that abort signals short circuit
|
|
6166
6227
|
let reject: () => void;
|
|
@@ -6473,33 +6534,6 @@ function createClientSideRequest(
|
|
|
6473
6534
|
return new Request(url, init);
|
|
6474
6535
|
}
|
|
6475
6536
|
|
|
6476
|
-
// Create the normalized URL instance to pass to loaders/actions/middleware.
|
|
6477
|
-
// We strip the `?index` param because that is a React Router implementation detail.
|
|
6478
|
-
function createDataFunctionUrl(request: Request, path: To): URL {
|
|
6479
|
-
let url = new URL(request.url);
|
|
6480
|
-
|
|
6481
|
-
let parsed = typeof path === 'string' ? parsePath(path) : path;
|
|
6482
|
-
url.pathname = parsed.pathname || '/';
|
|
6483
|
-
|
|
6484
|
-
if (parsed.search) {
|
|
6485
|
-
let searchParams = new URLSearchParams(parsed.search);
|
|
6486
|
-
|
|
6487
|
-
// Strip naked index param, preserve any other index params with values
|
|
6488
|
-
let indexValues = searchParams.getAll('index');
|
|
6489
|
-
searchParams.delete('index');
|
|
6490
|
-
for (let value of indexValues.filter(Boolean)) {
|
|
6491
|
-
searchParams.append('index', value);
|
|
6492
|
-
}
|
|
6493
|
-
url.search = searchParams.size ? `?${searchParams.toString()}` : '';
|
|
6494
|
-
} else {
|
|
6495
|
-
url.search = '';
|
|
6496
|
-
}
|
|
6497
|
-
|
|
6498
|
-
url.hash = parsed.hash || '';
|
|
6499
|
-
|
|
6500
|
-
return url;
|
|
6501
|
-
}
|
|
6502
|
-
|
|
6503
6537
|
function convertFormDataToSearchParams(formData: FormData): URLSearchParams {
|
|
6504
6538
|
let searchParams = new URLSearchParams();
|
|
6505
6539
|
|
|
@@ -6724,7 +6758,11 @@ function findNearestBoundary(matches: DataRouteMatch[], routeId?: string): DataR
|
|
|
6724
6758
|
let eligibleMatches = routeId
|
|
6725
6759
|
? matches.slice(0, matches.findIndex((m) => m.route.id === routeId) + 1)
|
|
6726
6760
|
: [...matches];
|
|
6727
|
-
return
|
|
6761
|
+
return (
|
|
6762
|
+
eligibleMatches
|
|
6763
|
+
.reverse()
|
|
6764
|
+
.find((m) => m.route.ErrorBoundary != null || m.route.errorElement != null) || matches[0]
|
|
6765
|
+
);
|
|
6728
6766
|
}
|
|
6729
6767
|
|
|
6730
6768
|
function getShortCircuitMatches(routes: DataRouteObject[]): {
|
|
@@ -6942,6 +6980,18 @@ function getTargetMatch(matches: DataRouteMatch[], location: Path | string) {
|
|
|
6942
6980
|
return pathMatches[pathMatches.length - 1];
|
|
6943
6981
|
}
|
|
6944
6982
|
|
|
6983
|
+
function getInstrumentationNavigateMeta(
|
|
6984
|
+
history: History,
|
|
6985
|
+
location: To,
|
|
6986
|
+
matches: DataRouteMatch[] | null,
|
|
6987
|
+
): InstrumentationResultMeta {
|
|
6988
|
+
return {
|
|
6989
|
+
url: createDataFunctionUrl(history.createURL(location), location),
|
|
6990
|
+
pattern: matches ? getRoutePattern(matches) : '',
|
|
6991
|
+
params: matches?.[0]?.params ? { ...matches[0].params } : {},
|
|
6992
|
+
};
|
|
6993
|
+
}
|
|
6994
|
+
|
|
6945
6995
|
function getSubmissionFromNavigation(navigation: Navigation): Submission | undefined {
|
|
6946
6996
|
let { formMethod, formAction, formEncType, text, formData, json } = navigation;
|
|
6947
6997
|
if (!formMethod || !formAction || !formEncType) {
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
// Local type stub for
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
// Shapes mirror react-router@7.18.1 lib/server-runtime/{data,server}.ts
|
|
6
|
-
// (RequestHandler simplified: the MiddlewareEnabled conditional collapses to
|
|
7
|
-
// its AppLoadContext arm — middleware typing is a framework-mode concern).
|
|
8
|
-
export interface AppLoadContext {
|
|
9
|
-
[key: string]: unknown;
|
|
10
|
-
}
|
|
1
|
+
// Local type stub for vendored instrumentation.ts's type-only import from the
|
|
2
|
+
// unvendored framework request handler. In v8 middleware is always enabled, so
|
|
3
|
+
// request context is unconditionally a RouterContextProvider.
|
|
4
|
+
import type { RouterContextProvider } from './utils';
|
|
11
5
|
|
|
12
|
-
export type RequestHandler = (
|
|
6
|
+
export type RequestHandler = (
|
|
7
|
+
request: Request,
|
|
8
|
+
loadContext?: RouterContextProvider,
|
|
9
|
+
) => Promise<Response>;
|
package/src/lib/router/url.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Vendored from react-router@
|
|
1
|
+
// Vendored from react-router@8.2.0 packages/react-router/lib/router/url.ts — unmodified.
|
|
2
2
|
// Re-vendor with `node scripts/vendor-remix-router.mjs`; never hand-edit.
|
|
3
3
|
export const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|[\\/]{2})/i;
|
|
4
4
|
export const PROTOCOL_RELATIVE_URL_REGEX = /^[\\/]{2}/;
|