@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.
Files changed (46) hide show
  1. package/README.md +20 -6
  2. package/package.json +12 -7
  3. package/src/index.ts +16 -14
  4. package/src/lib/Await.tsrx +1 -1
  5. package/src/lib/DefaultErrorComponent.tsrx +3 -3
  6. package/src/lib/RenderErrorBoundary.tsrx +1 -1
  7. package/src/lib/actions.ts +1 -1
  8. package/src/lib/components/MemoryRouter.tsrx +1 -1
  9. package/src/lib/components/Navigate.ts +1 -1
  10. package/src/lib/components/Router.tsrx +1 -1
  11. package/src/lib/components/RouterProvider.tsrx +1 -1
  12. package/src/lib/components/Routes.tsrx +1 -1
  13. package/src/lib/components/routes-collector.ts +1 -8
  14. package/src/lib/components/utils.ts +4 -65
  15. package/src/lib/components/with-props.ts +1 -1
  16. package/src/lib/context.ts +2 -4
  17. package/src/lib/dom/Form.tsrx +1 -1
  18. package/src/lib/dom/Link.tsrx +1 -1
  19. package/src/lib/dom/NavLink.tsrx +1 -1
  20. package/src/lib/dom/dom.ts +1 -1
  21. package/src/lib/dom/hooks.ts +1 -1
  22. package/src/lib/dom/lib.ts +8 -7
  23. package/src/lib/dom/routers.tsrx +1 -1
  24. package/src/lib/dom/server.tsrx +6 -28
  25. package/src/lib/errors.ts +1 -1
  26. package/src/lib/hooks.ts +6 -16
  27. package/src/lib/href.ts +9 -4
  28. package/src/lib/router/history.ts +2 -2
  29. package/src/lib/router/instrumentation.ts +391 -187
  30. package/src/lib/router/links.ts +1 -1
  31. package/src/lib/router/router.ts +128 -78
  32. package/src/lib/router/server-runtime-types.ts +8 -11
  33. package/src/lib/router/url.ts +1 -1
  34. package/src/lib/router/utils.ts +107 -31
  35. package/src/lib/server-runtime/cookies.ts +7 -7
  36. package/src/lib/server-runtime/crypto.ts +2 -2
  37. package/src/lib/server-runtime/mode.ts +1 -1
  38. package/src/lib/server-runtime/sessions/cookieStorage.ts +1 -1
  39. package/src/lib/server-runtime/sessions/memoryStorage.ts +1 -1
  40. package/src/lib/server-runtime/sessions.ts +8 -5
  41. package/src/lib/server-runtime/warnings.ts +1 -1
  42. package/src/lib/types/future.ts +1 -7
  43. package/src/lib/types/params.ts +1 -1
  44. package/src/lib/types/register.ts +1 -1
  45. package/src/lib/types/route-module.ts +1 -1
  46. package/src/lib/types/utils.ts +1 -1
@@ -1,4 +1,4 @@
1
- // Vendored from react-router@7.18.1 packages/react-router/lib/router/links.ts — unmodified.
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
 
@@ -1,4 +1,4 @@
1
- // Vendored from react-router@7.18.1 packages/react-router/lib/router/router.ts — unmodified.
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 { getRouteInstrumentationUpdates, instrumentClientSideRouter } from './instrumentation';
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: (v7) should we consider renaming this `navigationType` to align with
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 || defaultMapRouteProperties;
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: v7 - change `RouteData` to use `unknown` instead of `any`
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 || defaultMapRouteProperties;
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
- // If we're calling middleware then it must be enabled so we can cast
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
- // If we're calling middleware then it must be enabled so we can cast
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
- // All this will end up doing for these scenarios is adding `hasErrorBoundary`
5361
- // to the route. There's no need for Component->element conversions since
5362
- // we're already dealing with elements here
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 && key !== 'hasErrorBoundary';
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 `hasErrorBoundary` property on the route based on the route
5599
- // updates and remove the `lazy` function so we don't resolve the lazy
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 the framework-aware properties (`element`/`hasErrorBoundary`)
5604
- // since the logic will differ between frameworks.
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 Promise.resolve(
5761
- Object.assign(nextResult.value, {
5762
- [routeId]: { type: 'error', result: error },
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
- let boundaryRouteId = findNearestBoundary(matches, matches[maxBoundaryIdx].route.id).route.id;
5784
- return Promise.resolve({
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<unknown> | ActionFunction<unknown>,
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 eligibleMatches.reverse().find((m) => m.route.hasErrorBoundary === true) || matches[0];
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 the vendored instrumentation.ts's two type-only
2
- // `../server-runtime/*` imports. The server runtime (createRequestHandler,
3
- // cookies, sessions — react-router's framework-mode server) is out of scope
4
- // for this binding; only these two names are referenced, in type positions.
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 = (request: Request, loadContext?: AppLoadContext) => Promise<Response>;
6
+ export type RequestHandler = (
7
+ request: Request,
8
+ loadContext?: RouterContextProvider,
9
+ ) => Promise<Response>;
@@ -1,4 +1,4 @@
1
- // Vendored from react-router@7.18.1 packages/react-router/lib/router/url.ts — unmodified.
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}/;