react-router 7.9.4-pre.0 → 7.9.5-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.
Files changed (74) hide show
  1. package/CHANGELOG.md +35 -1
  2. package/dist/development/browser-DM83uryY.d.ts +310 -0
  3. package/dist/development/browser-DfMfSvsC.d.mts +310 -0
  4. package/dist/development/{chunk-I2PHXWY4.mjs → chunk-76L3QNAV.mjs} +365 -22
  5. package/dist/development/{chunk-5IRCOFJ2.mjs → chunk-B6QYCHJF.mjs} +197 -857
  6. package/dist/development/chunk-FXLUBU25.js +1310 -0
  7. package/dist/development/chunk-KXZSW2DO.js +188 -0
  8. package/dist/development/{chunk-V7H6ON6M.js → chunk-TSYPWE43.js} +1226 -122
  9. package/dist/development/dom-export.d.mts +103 -6
  10. package/dist/development/dom-export.d.ts +103 -4
  11. package/dist/development/dom-export.js +708 -20
  12. package/dist/development/dom-export.mjs +692 -11
  13. package/dist/{production/index-react-server-client-BIz4AUNd.d.mts → development/index-react-server-client-B0vnxMMk.d.mts} +137 -78
  14. package/dist/development/{index-react-server-client-BIz4AUNd.d.mts → index-react-server-client-BSxMvS7Z.d.ts} +137 -78
  15. package/dist/development/index-react-server-client.d.mts +2 -3
  16. package/dist/development/index-react-server-client.d.ts +2 -2
  17. package/dist/development/index-react-server-client.js +4 -4
  18. package/dist/development/index-react-server-client.mjs +2 -2
  19. package/dist/development/index-react-server.d.mts +107 -3
  20. package/dist/development/index-react-server.d.ts +107 -3
  21. package/dist/development/index-react-server.js +235 -10
  22. package/dist/development/index-react-server.mjs +235 -10
  23. package/dist/development/index.d.mts +14 -320
  24. package/dist/development/index.d.ts +14 -362
  25. package/dist/development/index.js +146 -962
  26. package/dist/development/index.mjs +3 -9
  27. package/dist/development/{routeModules-D5iJ6JYT.d.ts → instrumentation-iAqbU5Q4.d.ts} +173 -24
  28. package/dist/development/lib/types/internal.d.mts +2 -3
  29. package/dist/development/lib/types/internal.d.ts +2 -2
  30. package/dist/development/lib/types/internal.js +1 -1
  31. package/dist/development/lib/types/internal.mjs +1 -1
  32. package/dist/development/{register-CI4bTprK.d.mts → register-_G476ptB.d.mts} +1 -1
  33. package/dist/{production/register-C34pU-in.d.ts → development/register-c-dooqKE.d.ts} +1 -1
  34. package/dist/development/{context-DSyS5mLj.d.mts → router-DIAPGK5f.d.mts} +1873 -1254
  35. package/dist/production/browser-DM83uryY.d.ts +310 -0
  36. package/dist/production/browser-DfMfSvsC.d.mts +310 -0
  37. package/dist/production/{chunk-TK5RYV7M.mjs → chunk-4JX2RDWY.mjs} +197 -857
  38. package/dist/production/chunk-4SZHQXEM.js +188 -0
  39. package/dist/production/{chunk-VDTQF36D.mjs → chunk-7EXEUENX.mjs} +365 -22
  40. package/dist/production/{chunk-QIDCISSR.js → chunk-ARKB3I5K.js} +1226 -122
  41. package/dist/production/chunk-OB3KSCCZ.js +1310 -0
  42. package/dist/production/dom-export.d.mts +103 -6
  43. package/dist/production/dom-export.d.ts +103 -4
  44. package/dist/production/dom-export.js +708 -20
  45. package/dist/production/dom-export.mjs +692 -11
  46. package/dist/production/{index-react-server-client-BbRcBjrA.d.ts → index-react-server-client-B0vnxMMk.d.mts} +195 -135
  47. package/dist/{development/index-react-server-client-BbRcBjrA.d.ts → production/index-react-server-client-BSxMvS7Z.d.ts} +195 -135
  48. package/dist/production/index-react-server-client.d.mts +2 -3
  49. package/dist/production/index-react-server-client.d.ts +2 -2
  50. package/dist/production/index-react-server-client.js +4 -4
  51. package/dist/production/index-react-server-client.mjs +2 -2
  52. package/dist/production/index-react-server.d.mts +107 -3
  53. package/dist/production/index-react-server.d.ts +107 -3
  54. package/dist/production/index-react-server.js +235 -10
  55. package/dist/production/index-react-server.mjs +235 -10
  56. package/dist/production/index.d.mts +14 -320
  57. package/dist/production/index.d.ts +14 -362
  58. package/dist/production/index.js +146 -962
  59. package/dist/production/index.mjs +3 -9
  60. package/dist/production/{routeModules-D5iJ6JYT.d.ts → instrumentation-iAqbU5Q4.d.ts} +173 -24
  61. package/dist/production/lib/types/internal.d.mts +2 -3
  62. package/dist/production/lib/types/internal.d.ts +2 -2
  63. package/dist/production/lib/types/internal.js +1 -1
  64. package/dist/production/lib/types/internal.mjs +1 -1
  65. package/dist/production/{register-CI4bTprK.d.mts → register-_G476ptB.d.mts} +1 -1
  66. package/dist/{development/register-C34pU-in.d.ts → production/register-c-dooqKE.d.ts} +1 -1
  67. package/dist/production/{context-DSyS5mLj.d.mts → router-DIAPGK5f.d.mts} +1873 -1254
  68. package/package.json +1 -1
  69. package/dist/development/browser-z32v5KVN.d.mts +0 -46
  70. package/dist/development/chunk-JPM6TDKY.js +0 -2089
  71. package/dist/development/route-data-DZQOUSqV.d.mts +0 -473
  72. package/dist/production/browser-z32v5KVN.d.mts +0 -46
  73. package/dist/production/chunk-A4C524Z4.js +0 -2089
  74. package/dist/production/route-data-DZQOUSqV.d.mts +0 -473
@@ -351,6 +351,11 @@ type DefaultContext = MiddlewareEnabled extends true ? Readonly<RouterContextPro
351
351
  interface DataFunctionArgs<Context> {
352
352
  /** A {@link https://developer.mozilla.org/en-US/docs/Web/API/Request Fetch Request instance} which you can use to read headers (like cookies, and {@link https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams URLSearchParams} from the request. */
353
353
  request: Request;
354
+ /**
355
+ * Matched un-interpolated route pattern for the current path (i.e., /blog/:slug).
356
+ * Mostly useful as a identifier to aggregate on for logging/tracing/etc.
357
+ */
358
+ unstable_pattern: string;
354
359
  /**
355
360
  * {@link https://reactrouter.com/start/framework/routing#dynamic-segments Dynamic route params} for the current route.
356
361
  * @example
@@ -571,7 +576,7 @@ type AgnosticPatchRoutesOnNavigationFunction<O extends AgnosticRouteObject = Agn
571
576
  * properties from framework-agnostic properties
572
577
  */
573
578
  interface MapRoutePropertiesFunction {
574
- (route: AgnosticRouteObject): {
579
+ (route: AgnosticDataRouteObject): {
575
580
  hasErrorBoundary: boolean;
576
581
  } & Record<string, any>;
577
582
  }
@@ -887,6 +892,98 @@ type ErrorResponse = {
887
892
  */
888
893
  declare function isRouteErrorResponse(error: any): error is ErrorResponse;
889
894
 
895
+ /**
896
+ * An object of unknown type for route loaders and actions provided by the
897
+ * server's `getLoadContext()` function. This is defined as an empty interface
898
+ * specifically so apps can leverage declaration merging to augment this type
899
+ * globally: https://www.typescriptlang.org/docs/handbook/declaration-merging.html
900
+ */
901
+ interface AppLoadContext {
902
+ [key: string]: unknown;
903
+ }
904
+
905
+ type unstable_ServerInstrumentation = {
906
+ handler?: unstable_InstrumentRequestHandlerFunction;
907
+ route?: unstable_InstrumentRouteFunction;
908
+ };
909
+ type unstable_ClientInstrumentation = {
910
+ router?: unstable_InstrumentRouterFunction;
911
+ route?: unstable_InstrumentRouteFunction;
912
+ };
913
+ type unstable_InstrumentRequestHandlerFunction = (handler: InstrumentableRequestHandler) => void;
914
+ type unstable_InstrumentRouterFunction = (router: InstrumentableRouter) => void;
915
+ type unstable_InstrumentRouteFunction = (route: InstrumentableRoute) => void;
916
+ type unstable_InstrumentationHandlerResult = {
917
+ status: "success";
918
+ error: undefined;
919
+ } | {
920
+ status: "error";
921
+ error: Error;
922
+ };
923
+ type InstrumentFunction<T> = (handler: () => Promise<unstable_InstrumentationHandlerResult>, info: T) => Promise<void>;
924
+ type ReadonlyRequest = {
925
+ method: string;
926
+ url: string;
927
+ headers: Pick<Headers, "get">;
928
+ };
929
+ type ReadonlyContext = MiddlewareEnabled extends true ? Pick<RouterContextProvider, "get"> : Readonly<AppLoadContext>;
930
+ type InstrumentableRoute = {
931
+ id: string;
932
+ index: boolean | undefined;
933
+ path: string | undefined;
934
+ instrument(instrumentations: RouteInstrumentations): void;
935
+ };
936
+ type RouteInstrumentations = {
937
+ lazy?: InstrumentFunction<RouteLazyInstrumentationInfo>;
938
+ "lazy.loader"?: InstrumentFunction<RouteLazyInstrumentationInfo>;
939
+ "lazy.action"?: InstrumentFunction<RouteLazyInstrumentationInfo>;
940
+ "lazy.middleware"?: InstrumentFunction<RouteLazyInstrumentationInfo>;
941
+ middleware?: InstrumentFunction<RouteHandlerInstrumentationInfo>;
942
+ loader?: InstrumentFunction<RouteHandlerInstrumentationInfo>;
943
+ action?: InstrumentFunction<RouteHandlerInstrumentationInfo>;
944
+ };
945
+ type RouteLazyInstrumentationInfo = undefined;
946
+ type RouteHandlerInstrumentationInfo = Readonly<{
947
+ request: ReadonlyRequest;
948
+ params: LoaderFunctionArgs["params"];
949
+ unstable_pattern: string;
950
+ context: ReadonlyContext;
951
+ }>;
952
+ type InstrumentableRouter = {
953
+ instrument(instrumentations: RouterInstrumentations): void;
954
+ };
955
+ type RouterInstrumentations = {
956
+ navigate?: InstrumentFunction<RouterNavigationInstrumentationInfo>;
957
+ fetch?: InstrumentFunction<RouterFetchInstrumentationInfo>;
958
+ };
959
+ type RouterNavigationInstrumentationInfo = Readonly<{
960
+ to: string | number;
961
+ currentUrl: string;
962
+ formMethod?: HTMLFormMethod;
963
+ formEncType?: FormEncType;
964
+ formData?: FormData;
965
+ body?: any;
966
+ }>;
967
+ type RouterFetchInstrumentationInfo = Readonly<{
968
+ href: string;
969
+ currentUrl: string;
970
+ fetcherKey: string;
971
+ formMethod?: HTMLFormMethod;
972
+ formEncType?: FormEncType;
973
+ formData?: FormData;
974
+ body?: any;
975
+ }>;
976
+ type InstrumentableRequestHandler = {
977
+ instrument(instrumentations: RequestHandlerInstrumentations): void;
978
+ };
979
+ type RequestHandlerInstrumentations = {
980
+ request?: InstrumentFunction<RequestHandlerInstrumentationInfo>;
981
+ };
982
+ type RequestHandlerInstrumentationInfo = Readonly<{
983
+ request: ReadonlyRequest;
984
+ context: ReadonlyContext | undefined;
985
+ }>;
986
+
890
987
  /**
891
988
  * A Router instance manages all navigation and data loading/mutations
892
989
  */
@@ -1171,6 +1268,7 @@ interface RouterInit {
1171
1268
  history: History;
1172
1269
  basename?: string;
1173
1270
  getContext?: () => MaybePromise<RouterContextProvider>;
1271
+ unstable_instrumentations?: unstable_ClientInstrumentation[];
1174
1272
  mapRouteProperties?: MapRoutePropertiesFunction;
1175
1273
  future?: Partial<FutureConfig>;
1176
1274
  hydrationRouteProperties?: string[];
@@ -1437,6 +1535,7 @@ type BlockerFunction = (args: {
1437
1535
  interface CreateStaticHandlerOptions {
1438
1536
  basename?: string;
1439
1537
  mapRouteProperties?: MapRoutePropertiesFunction;
1538
+ unstable_instrumentations?: Pick<unstable_ServerInstrumentation, "route">[];
1440
1539
  future?: {};
1441
1540
  }
1442
1541
  declare function createStaticHandler(routes: AgnosticRouteObject[], opts?: CreateStaticHandlerOptions): StaticHandler;
@@ -1807,6 +1906,11 @@ type ClientDataFunctionArgs<Params> = {
1807
1906
  * }
1808
1907
  **/
1809
1908
  params: Params;
1909
+ /**
1910
+ * Matched un-interpolated route pattern for the current path (i.e., /blog/:slug).
1911
+ * Mostly useful as a identifier to aggregate on for logging/tracing/etc.
1912
+ */
1913
+ unstable_pattern: string;
1810
1914
  /**
1811
1915
  * When `future.v8_middleware` is not enabled, this is undefined.
1812
1916
  *
@@ -1860,7 +1964,7 @@ interface HeadersFunction {
1860
1964
  * A function that defines `<link>` tags to be inserted into the `<head>` of
1861
1965
  * the document on route transitions.
1862
1966
  *
1863
- * @see https://remix.run/route/meta
1967
+ * @see https://reactrouter.com/start/framework/route-module#meta
1864
1968
  */
1865
1969
  interface LinksFunction {
1866
1970
  (): LinkDescriptor[];
@@ -1973,7 +2077,7 @@ type LdJsonValue = LdJsonPrimitive | LdJsonObject | LdJsonArray;
1973
2077
  /**
1974
2078
  * An arbitrary object that is associated with a route.
1975
2079
  *
1976
- * @see https://remix.run/route/handle
2080
+ * @see https://reactrouter.com/how-to/using-handle
1977
2081
  */
1978
2082
  type RouteHandle = unknown;
1979
2083
 
@@ -27,7 +27,7 @@ function _interopNamespace(e) {
27
27
  var React2__namespace = /*#__PURE__*/_interopNamespace(React2);
28
28
 
29
29
  /**
30
- * react-router v7.9.4-pre.0
30
+ * react-router v7.9.5-pre.0
31
31
  *
32
32
  * Copyright (c) Remix Software Inc.
33
33
  *
@@ -107,6 +107,185 @@ function parsePath(path) {
107
107
  return parsedPath;
108
108
  }
109
109
 
110
+ // lib/router/instrumentation.ts
111
+ var UninstrumentedSymbol = Symbol("Uninstrumented");
112
+ function getRouteInstrumentationUpdates(fns, route) {
113
+ let aggregated = {
114
+ lazy: [],
115
+ "lazy.loader": [],
116
+ "lazy.action": [],
117
+ "lazy.middleware": [],
118
+ middleware: [],
119
+ loader: [],
120
+ action: []
121
+ };
122
+ fns.forEach(
123
+ (fn) => fn({
124
+ id: route.id,
125
+ index: route.index,
126
+ path: route.path,
127
+ instrument(i) {
128
+ let keys = Object.keys(aggregated);
129
+ for (let key of keys) {
130
+ if (i[key]) {
131
+ aggregated[key].push(i[key]);
132
+ }
133
+ }
134
+ }
135
+ })
136
+ );
137
+ let updates = {};
138
+ if (typeof route.lazy === "function" && aggregated.lazy.length > 0) {
139
+ let instrumented = wrapImpl(aggregated.lazy, route.lazy, () => void 0);
140
+ if (instrumented) {
141
+ updates.lazy = instrumented;
142
+ }
143
+ }
144
+ if (typeof route.lazy === "object") {
145
+ let lazyObject = route.lazy;
146
+ ["middleware", "loader", "action"].forEach((key) => {
147
+ let lazyFn = lazyObject[key];
148
+ let instrumentations = aggregated[`lazy.${key}`];
149
+ if (typeof lazyFn === "function" && instrumentations.length > 0) {
150
+ let instrumented = wrapImpl(instrumentations, lazyFn, () => void 0);
151
+ if (instrumented) {
152
+ updates.lazy = Object.assign(updates.lazy || {}, {
153
+ [key]: instrumented
154
+ });
155
+ }
156
+ }
157
+ });
158
+ }
159
+ ["loader", "action"].forEach((key) => {
160
+ let handler = route[key];
161
+ if (typeof handler === "function" && aggregated[key].length > 0) {
162
+ let original = handler[UninstrumentedSymbol] ?? handler;
163
+ let instrumented = wrapImpl(
164
+ aggregated[key],
165
+ original,
166
+ (...args) => getHandlerInfo(args[0])
167
+ );
168
+ if (instrumented) {
169
+ instrumented[UninstrumentedSymbol] = original;
170
+ updates[key] = instrumented;
171
+ }
172
+ }
173
+ });
174
+ if (route.middleware && route.middleware.length > 0 && aggregated.middleware.length > 0) {
175
+ updates.middleware = route.middleware.map((middleware) => {
176
+ let original = middleware[UninstrumentedSymbol] ?? middleware;
177
+ let instrumented = wrapImpl(
178
+ aggregated.middleware,
179
+ original,
180
+ (...args) => getHandlerInfo(args[0])
181
+ );
182
+ if (instrumented) {
183
+ instrumented[UninstrumentedSymbol] = original;
184
+ return instrumented;
185
+ }
186
+ return middleware;
187
+ });
188
+ }
189
+ return updates;
190
+ }
191
+ function wrapImpl(impls, handler, getInfo) {
192
+ if (impls.length === 0) {
193
+ return null;
194
+ }
195
+ return async (...args) => {
196
+ let result = await recurseRight(
197
+ impls,
198
+ getInfo(...args),
199
+ () => handler(...args),
200
+ impls.length - 1
201
+ );
202
+ if (result.type === "error") {
203
+ throw result.value;
204
+ }
205
+ return result.value;
206
+ };
207
+ }
208
+ async function recurseRight(impls, info, handler, index) {
209
+ let impl = impls[index];
210
+ let result;
211
+ if (!impl) {
212
+ try {
213
+ let value = await handler();
214
+ result = { type: "success", value };
215
+ } catch (e) {
216
+ result = { type: "error", value: e };
217
+ }
218
+ } else {
219
+ let handlerPromise = void 0;
220
+ let callHandler = async () => {
221
+ if (handlerPromise) {
222
+ console.error("You cannot call instrumented handlers more than once");
223
+ } else {
224
+ handlerPromise = recurseRight(impls, info, handler, index - 1);
225
+ }
226
+ result = await handlerPromise;
227
+ invariant(result, "Expected a result");
228
+ if (result.type === "error" && result.value instanceof Error) {
229
+ return { status: "error", error: result.value };
230
+ }
231
+ return { status: "success", error: void 0 };
232
+ };
233
+ try {
234
+ await impl(callHandler, info);
235
+ } catch (e) {
236
+ console.error("An instrumentation function threw an error:", e);
237
+ }
238
+ if (!handlerPromise) {
239
+ await callHandler();
240
+ }
241
+ await handlerPromise;
242
+ }
243
+ if (result) {
244
+ return result;
245
+ }
246
+ return {
247
+ type: "error",
248
+ value: new Error("No result assigned in instrumentation chain.")
249
+ };
250
+ }
251
+ function getHandlerInfo(args) {
252
+ let { request, context, params, unstable_pattern } = args;
253
+ return {
254
+ request: getReadonlyRequest(request),
255
+ params: { ...params },
256
+ unstable_pattern,
257
+ context: getReadonlyContext(context)
258
+ };
259
+ }
260
+ function getReadonlyRequest(request) {
261
+ return {
262
+ method: request.method,
263
+ url: request.url,
264
+ headers: {
265
+ get: (...args) => request.headers.get(...args)
266
+ }
267
+ };
268
+ }
269
+ function getReadonlyContext(context) {
270
+ if (isPlainObject(context)) {
271
+ let frozen = { ...context };
272
+ Object.freeze(frozen);
273
+ return frozen;
274
+ } else {
275
+ return {
276
+ get: (ctx) => context.get(ctx)
277
+ };
278
+ }
279
+ }
280
+ var objectProtoNames = Object.getOwnPropertyNames(Object.prototype).sort().join("\0");
281
+ function isPlainObject(thing) {
282
+ if (thing === null || typeof thing !== "object") {
283
+ return false;
284
+ }
285
+ const proto = Object.getPrototypeOf(thing);
286
+ return proto === Object.prototype || proto === null || Object.getOwnPropertyNames(proto).sort().join("\0") === objectProtoNames;
287
+ }
288
+
110
289
  // lib/router/utils.ts
111
290
  function createContext(defaultValue) {
112
291
  return { defaultValue };
@@ -200,19 +379,23 @@ function convertRoutesToDataRoutes(routes, mapRouteProperties, parentPath = [],
200
379
  if (isIndexRoute(route)) {
201
380
  let indexRoute = {
202
381
  ...route,
203
- ...mapRouteProperties(route),
204
382
  id
205
383
  };
206
- manifest[id] = indexRoute;
384
+ manifest[id] = mergeRouteUpdates(
385
+ indexRoute,
386
+ mapRouteProperties(indexRoute)
387
+ );
207
388
  return indexRoute;
208
389
  } else {
209
390
  let pathOrLayoutRoute = {
210
391
  ...route,
211
- ...mapRouteProperties(route),
212
392
  id,
213
393
  children: void 0
214
394
  };
215
- manifest[id] = pathOrLayoutRoute;
395
+ manifest[id] = mergeRouteUpdates(
396
+ pathOrLayoutRoute,
397
+ mapRouteProperties(pathOrLayoutRoute)
398
+ );
216
399
  if (route.children) {
217
400
  pathOrLayoutRoute.children = convertRoutesToDataRoutes(
218
401
  route.children,
@@ -226,6 +409,17 @@ function convertRoutesToDataRoutes(routes, mapRouteProperties, parentPath = [],
226
409
  }
227
410
  });
228
411
  }
412
+ function mergeRouteUpdates(route, updates) {
413
+ return Object.assign(route, {
414
+ ...updates,
415
+ ...typeof updates.lazy === "object" && updates.lazy != null ? {
416
+ lazy: {
417
+ ...route.lazy,
418
+ ...updates.lazy
419
+ }
420
+ } : {}
421
+ });
422
+ }
229
423
  function matchRoutes(routes, locationArg, basename = "/") {
230
424
  return matchRoutesImpl(routes, locationArg, basename, false);
231
425
  }
@@ -652,6 +846,9 @@ var ErrorResponseImpl = class {
652
846
  function isRouteErrorResponse(error) {
653
847
  return error != null && typeof error.status === "number" && typeof error.statusText === "string" && typeof error.internal === "boolean" && "data" in error;
654
848
  }
849
+ function getRoutePattern(paths) {
850
+ return paths.filter(Boolean).join("/").replace(/\/\/*/g, "/") || "/";
851
+ }
655
852
 
656
853
  // lib/router/router.ts
657
854
  var validMutationMethodsArr = [
@@ -682,7 +879,20 @@ function createStaticHandler(routes, opts) {
682
879
  );
683
880
  let manifest = {};
684
881
  let basename = (opts ? opts.basename : null) || "/";
685
- let mapRouteProperties = opts?.mapRouteProperties || defaultMapRouteProperties;
882
+ let _mapRouteProperties = opts?.mapRouteProperties || defaultMapRouteProperties;
883
+ let mapRouteProperties = _mapRouteProperties;
884
+ if (opts?.unstable_instrumentations) {
885
+ let instrumentations = opts.unstable_instrumentations;
886
+ mapRouteProperties = (route) => {
887
+ return {
888
+ ..._mapRouteProperties(route),
889
+ ...getRouteInstrumentationUpdates(
890
+ instrumentations.map((i) => i.route).filter(Boolean),
891
+ route
892
+ )
893
+ };
894
+ };
895
+ }
686
896
  let dataRoutes = convertRoutesToDataRoutes(
687
897
  routes,
688
898
  mapRouteProperties,
@@ -752,6 +962,7 @@ function createStaticHandler(routes, opts) {
752
962
  let response = await runServerMiddlewarePipeline(
753
963
  {
754
964
  request,
965
+ unstable_pattern: getRoutePattern(matches.map((m) => m.route.path)),
755
966
  matches,
756
967
  params: matches[0].params,
757
968
  // If we're calling middleware then it must be enabled so we can cast
@@ -897,6 +1108,7 @@ function createStaticHandler(routes, opts) {
897
1108
  let response = await runServerMiddlewarePipeline(
898
1109
  {
899
1110
  request,
1111
+ unstable_pattern: getRoutePattern(matches.map((m) => m.route.path)),
900
1112
  matches,
901
1113
  params: matches[0].params,
902
1114
  // If we're calling middleware then it must be enabled so we can cast
@@ -1172,12 +1384,14 @@ function createStaticHandler(routes, opts) {
1172
1384
  // Up to but not including the boundary
1173
1385
  matches.findIndex((m) => m.route.id === pendingActionResult[0]) - 1
1174
1386
  ) : void 0;
1387
+ let pattern = getRoutePattern(matches.map((m) => m.route.path));
1175
1388
  dsMatches = matches.map((match, index) => {
1176
1389
  if (maxIdx != null && index > maxIdx) {
1177
1390
  return getDataStrategyMatch(
1178
1391
  mapRouteProperties,
1179
1392
  manifest,
1180
1393
  request,
1394
+ pattern,
1181
1395
  match,
1182
1396
  [],
1183
1397
  requestContext,
@@ -1188,6 +1402,7 @@ function createStaticHandler(routes, opts) {
1188
1402
  mapRouteProperties,
1189
1403
  manifest,
1190
1404
  request,
1405
+ pattern,
1191
1406
  match,
1192
1407
  [],
1193
1408
  requestContext,
@@ -1526,12 +1741,17 @@ function runServerMiddlewarePipeline(args, handler, errorHandler) {
1526
1741
  }
1527
1742
  }
1528
1743
  async function runMiddlewarePipeline(args, handler, processResult, isResult, errorHandler) {
1529
- let { matches, request, params, context } = args;
1744
+ let { matches, request, params, context, unstable_pattern } = args;
1530
1745
  let tuples = matches.flatMap(
1531
1746
  (m) => m.route.middleware ? m.route.middleware.map((fn) => [m.route.id, fn]) : []
1532
1747
  );
1533
1748
  let result = await callRouteMiddleware(
1534
- { request, params, context },
1749
+ {
1750
+ request,
1751
+ params,
1752
+ context,
1753
+ unstable_pattern
1754
+ },
1535
1755
  tuples,
1536
1756
  handler,
1537
1757
  processResult,
@@ -1609,7 +1829,7 @@ function getDataStrategyMatchLazyPromises(mapRouteProperties, manifest, request,
1609
1829
  handler: lazyRoutePromises.lazyHandlerPromise
1610
1830
  };
1611
1831
  }
1612
- function getDataStrategyMatch(mapRouteProperties, manifest, request, match, lazyRoutePropertiesToSkip, scopedContext, shouldLoad, unstable_shouldRevalidateArgs = null) {
1832
+ function getDataStrategyMatch(mapRouteProperties, manifest, request, unstable_pattern, match, lazyRoutePropertiesToSkip, scopedContext, shouldLoad, unstable_shouldRevalidateArgs = null) {
1613
1833
  let isUsingNewApi = false;
1614
1834
  let _lazyPromises = getDataStrategyMatchLazyPromises(
1615
1835
  mapRouteProperties,
@@ -1640,9 +1860,10 @@ function getDataStrategyMatch(mapRouteProperties, manifest, request, match, lazy
1640
1860
  let { lazy, loader, middleware } = match.route;
1641
1861
  let callHandler = isUsingNewApi || shouldLoad || handlerOverride && !isMutationMethod(request.method) && (lazy || loader);
1642
1862
  let isMiddlewareOnlyRoute = middleware && middleware.length > 0 && !loader && !lazy;
1643
- if (callHandler && !isMiddlewareOnlyRoute) {
1863
+ if (callHandler && (isMutationMethod(request.method) || !isMiddlewareOnlyRoute)) {
1644
1864
  return callLoaderOrAction({
1645
1865
  request,
1866
+ unstable_pattern,
1646
1867
  match,
1647
1868
  lazyHandlerPromise: _lazyPromises?.handler,
1648
1869
  lazyRoutePromise: _lazyPromises?.route,
@@ -1676,6 +1897,7 @@ function getTargetedDataStrategyMatches(mapRouteProperties, manifest, request, m
1676
1897
  mapRouteProperties,
1677
1898
  manifest,
1678
1899
  request,
1900
+ getRoutePattern(matches.map((m) => m.route.path)),
1679
1901
  match,
1680
1902
  lazyRoutePropertiesToSkip,
1681
1903
  scopedContext,
@@ -1690,6 +1912,7 @@ async function callDataStrategyImpl(dataStrategyImpl, request, matches, fetcherK
1690
1912
  }
1691
1913
  let dataStrategyArgs = {
1692
1914
  request,
1915
+ unstable_pattern: getRoutePattern(matches.map((m) => m.route.path)),
1693
1916
  params: matches[0].params,
1694
1917
  context: scopedContext,
1695
1918
  matches
@@ -1717,6 +1940,7 @@ async function callDataStrategyImpl(dataStrategyImpl, request, matches, fetcherK
1717
1940
  }
1718
1941
  async function callLoaderOrAction({
1719
1942
  request,
1943
+ unstable_pattern,
1720
1944
  match,
1721
1945
  lazyHandlerPromise,
1722
1946
  lazyRoutePromise,
@@ -1743,6 +1967,7 @@ async function callLoaderOrAction({
1743
1967
  return handler(
1744
1968
  {
1745
1969
  request,
1970
+ unstable_pattern,
1746
1971
  params: match.params,
1747
1972
  context: scopedContext
1748
1973
  },