vinext 1.2.1 → 1.3.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 (212) hide show
  1. package/README.md +12 -9
  2. package/dist/build/client-build-config.d.ts +64 -3
  3. package/dist/build/client-build-config.js +131 -4
  4. package/dist/build/client-reference-groups.d.ts +163 -0
  5. package/dist/build/client-reference-groups.js +534 -0
  6. package/dist/build/module-dependency-cache.d.ts +31 -0
  7. package/dist/build/module-dependency-cache.js +51 -1
  8. package/dist/build/next-client-runtime-manifests.d.ts +10 -1
  9. package/dist/build/next-client-runtime-manifests.js +19 -4
  10. package/dist/build/nitro-public-files.d.ts +24 -0
  11. package/dist/build/nitro-public-files.js +60 -0
  12. package/dist/build/pages-client-assets-module.js +1 -1
  13. package/dist/build/prerender-paths.js +5 -2
  14. package/dist/build/server-actions-encryption-key.d.ts +23 -0
  15. package/dist/build/server-actions-encryption-key.js +101 -0
  16. package/dist/build/ssr-manifest.d.ts +3 -0
  17. package/dist/build/ssr-manifest.js +10 -1
  18. package/dist/client/client-rewrite-params.d.ts +9 -0
  19. package/dist/client/client-rewrite-params.js +20 -0
  20. package/dist/client/dev-error-overlay.js +2 -1
  21. package/dist/client/navigation-runtime.d.ts +25 -2
  22. package/dist/client/navigation-runtime.js +42 -11
  23. package/dist/client/vinext-next-data.d.ts +0 -1
  24. package/dist/config/config-matchers.d.ts +15 -40
  25. package/dist/config/config-matchers.js +183 -255
  26. package/dist/config/config-source.d.ts +34 -0
  27. package/dist/config/config-source.js +141 -0
  28. package/dist/config/header-params.d.ts +29 -0
  29. package/dist/config/header-params.js +106 -0
  30. package/dist/config/next-config.d.ts +7 -5
  31. package/dist/config/next-config.js +120 -7
  32. package/dist/entries/app-browser-entry.d.ts +14 -1
  33. package/dist/entries/app-browser-entry.js +26 -36
  34. package/dist/entries/app-rsc-entry.d.ts +2 -0
  35. package/dist/entries/app-rsc-entry.js +92 -57
  36. package/dist/entries/app-rsc-manifest.d.ts +10 -0
  37. package/dist/entries/app-rsc-manifest.js +20 -1
  38. package/dist/entries/app-ssr-entry.d.ts +4 -1
  39. package/dist/entries/app-ssr-entry.js +9 -2
  40. package/dist/entries/pages-client-entry.d.ts +1 -0
  41. package/dist/entries/pages-client-entry.js +6 -6
  42. package/dist/entries/pages-server-entry.js +17 -14
  43. package/dist/index.d.ts +11 -0
  44. package/dist/index.js +239 -83
  45. package/dist/init.js +17 -0
  46. package/dist/plugins/optimize-imports.d.ts +25 -2
  47. package/dist/plugins/optimize-imports.js +106 -20
  48. package/dist/plugins/rsc-client-reference-loaders.d.ts +45 -1
  49. package/dist/plugins/rsc-client-reference-loaders.js +336 -18
  50. package/dist/plugins/use-cache-callable.d.ts +5 -0
  51. package/dist/plugins/use-cache-callable.js +30 -8
  52. package/dist/plugins/worker-image-imports.d.ts +1 -0
  53. package/dist/plugins/worker-image-imports.js +1 -1
  54. package/dist/routing/app-route-graph.d.ts +1 -1
  55. package/dist/routing/browser-route-manifest.d.ts +43 -0
  56. package/dist/routing/browser-route-manifest.js +195 -0
  57. package/dist/routing/hashed-route-patterns.d.ts +4 -0
  58. package/dist/routing/hashed-route-patterns.js +22 -0
  59. package/dist/routing/optimistic-route-trie.d.ts +27 -0
  60. package/dist/routing/optimistic-route-trie.js +102 -0
  61. package/dist/routing/route-validation.d.ts +6 -1
  62. package/dist/routing/route-validation.js +26 -10
  63. package/dist/server/app-action-forwarding.d.ts +8 -0
  64. package/dist/server/app-action-forwarding.js +15 -1
  65. package/dist/server/app-browser-entry.js +147 -60
  66. package/dist/server/app-browser-error.d.ts +3 -1
  67. package/dist/server/app-browser-error.js +7 -2
  68. package/dist/server/app-browser-interception-context.d.ts +2 -2
  69. package/dist/server/app-browser-mpa-navigation.d.ts +1 -0
  70. package/dist/server/app-browser-mpa-navigation.js +6 -5
  71. package/dist/server/app-browser-navigation-controller.d.ts +17 -6
  72. package/dist/server/app-browser-navigation-controller.js +88 -26
  73. package/dist/server/app-browser-state.d.ts +2 -2
  74. package/dist/server/app-browser-visible-commit.d.ts +4 -4
  75. package/dist/server/app-client-reference-preloader.d.ts +23 -0
  76. package/dist/server/app-client-reference-preloader.js +30 -7
  77. package/dist/server/app-fallback-renderer.js +2 -1
  78. package/dist/server/app-middleware.d.ts +6 -0
  79. package/dist/server/app-middleware.js +8 -10
  80. package/dist/server/app-optimistic-routing.d.ts +8 -10
  81. package/dist/server/app-optimistic-routing.js +4 -95
  82. package/dist/server/app-page-boundary-render.js +8 -1
  83. package/dist/server/app-page-cache-render.js +1 -0
  84. package/dist/server/app-page-dispatch.js +2 -0
  85. package/dist/server/app-page-render.js +3 -1
  86. package/dist/server/app-page-rsc-render-status.d.ts +1 -0
  87. package/dist/server/app-page-rsc-render-status.js +1 -0
  88. package/dist/server/app-page-search-params-observation.d.ts +1 -4
  89. package/dist/server/app-page-search-params-observation.js +8 -10
  90. package/dist/server/app-page-stream.d.ts +7 -0
  91. package/dist/server/app-page-stream.js +1 -0
  92. package/dist/server/app-pages-bridge.d.ts +2 -1
  93. package/dist/server/app-pages-bridge.js +11 -7
  94. package/dist/server/app-prerender-static-params.js +3 -2
  95. package/dist/server/app-render-dependency.js +42 -2
  96. package/dist/server/app-request-stage-independent-entry.js +2 -2
  97. package/dist/server/app-response-stage-entry.js +3 -3
  98. package/dist/server/app-route-handler-dispatch.js +3 -1
  99. package/dist/server/app-route-handler-execution.d.ts +2 -0
  100. package/dist/server/app-route-handler-execution.js +9 -2
  101. package/dist/server/app-route-handler-middleware-context.d.ts +2 -1
  102. package/dist/server/app-route-handler-middleware-context.js +3 -3
  103. package/dist/server/app-route-handler-response.d.ts +2 -1
  104. package/dist/server/app-route-handler-response.js +2 -2
  105. package/dist/server/app-route-handler-runtime.d.ts +2 -0
  106. package/dist/server/app-route-handler-runtime.js +20 -3
  107. package/dist/server/app-route-module-loader.js +7 -6
  108. package/dist/server/app-route-tree.d.ts +20 -0
  109. package/dist/server/app-route-tree.js +18 -0
  110. package/dist/server/app-router-entry.js +2 -2
  111. package/dist/server/app-rsc-combined-handler.js +8 -1
  112. package/dist/server/app-rsc-errors.d.ts +7 -0
  113. package/dist/server/app-rsc-errors.js +9 -2
  114. package/dist/server/app-rsc-handler.d.ts +4 -1
  115. package/dist/server/app-rsc-handler.js +146 -130
  116. package/dist/server/app-rsc-response-finalizer.d.ts +5 -0
  117. package/dist/server/app-rsc-response-finalizer.js +4 -1
  118. package/dist/server/app-rsc-response-stage.js +3 -1
  119. package/dist/server/app-rsc-route-matching.d.ts +1 -0
  120. package/dist/server/app-rsc-route-matching.js +1 -1
  121. package/dist/server/app-server-action-execution.d.ts +23 -6
  122. package/dist/server/app-server-action-execution.js +50 -56
  123. package/dist/server/app-ssr-entry.d.ts +6 -0
  124. package/dist/server/app-ssr-entry.js +16 -7
  125. package/dist/server/app-ssr-stream.d.ts +7 -0
  126. package/dist/server/app-ssr-stream.js +13 -1
  127. package/dist/server/config-headers.js +12 -3
  128. package/dist/server/isolate-shared-promise.d.ts +10 -0
  129. package/dist/server/isolate-shared-promise.js +33 -0
  130. package/dist/server/isr-cache.js +3 -2
  131. package/dist/server/middleware-matcher-pattern.d.ts +0 -1
  132. package/dist/server/middleware-matcher-pattern.js +11 -140
  133. package/dist/server/middleware-matcher.js +5 -6
  134. package/dist/server/middleware-response-headers.d.ts +31 -0
  135. package/dist/server/middleware-response-headers.js +57 -1
  136. package/dist/server/middleware-runtime.js +26 -13
  137. package/dist/server/navigation-planner.d.ts +2 -2
  138. package/dist/server/nitro-public-files-plugin.d.ts +38 -0
  139. package/dist/server/nitro-public-files-plugin.js +106 -0
  140. package/dist/server/nitro-public-files.d.ts +21 -0
  141. package/dist/server/nitro-public-files.js +39 -0
  142. package/dist/server/pages-asset-tags.d.ts +5 -0
  143. package/dist/server/pages-asset-tags.js +9 -2
  144. package/dist/server/pages-client-assets.d.ts +4 -1
  145. package/dist/server/pages-i18n.d.ts +18 -0
  146. package/dist/server/pages-i18n.js +18 -2
  147. package/dist/server/pages-node-compat.d.ts +5 -3
  148. package/dist/server/pages-node-compat.js +35 -16
  149. package/dist/server/pages-request-pipeline.d.ts +6 -1
  150. package/dist/server/pages-request-pipeline.js +31 -35
  151. package/dist/server/pages-request-stage-entry.js +16 -6
  152. package/dist/server/pages-response-stage-entry.js +1 -1
  153. package/dist/server/pages-revalidate.js +1 -0
  154. package/dist/server/pages-router-entry.js +1 -1
  155. package/dist/server/prod-server.d.ts +2 -2
  156. package/dist/server/prod-server.js +71 -33
  157. package/dist/server/proxy-trust.d.ts +6 -0
  158. package/dist/server/proxy-trust.js +12 -6
  159. package/dist/server/request-pipeline.d.ts +5 -0
  160. package/dist/server/request-pipeline.js +12 -1
  161. package/dist/server/server-reference-loader.js +10 -1
  162. package/dist/server/static-file-cache.js +15 -3
  163. package/dist/server/worker-utils.js +1 -1
  164. package/dist/shims/cache-handler.js +3 -2
  165. package/dist/shims/cache-request-state.d.ts +40 -3
  166. package/dist/shims/cache-request-state.js +70 -5
  167. package/dist/shims/cache-runtime.js +47 -19
  168. package/dist/shims/cache.d.ts +2 -2
  169. package/dist/shims/cache.js +17 -8
  170. package/dist/shims/cdn-purge-routes.d.ts +24 -0
  171. package/dist/shims/cdn-purge-routes.js +77 -0
  172. package/dist/shims/dynamic.js +17 -4
  173. package/dist/shims/form.js +8 -3
  174. package/dist/shims/image-props.d.ts +93 -0
  175. package/dist/shims/image-props.js +323 -0
  176. package/dist/shims/image.d.ts +4 -18
  177. package/dist/shims/image.js +4 -319
  178. package/dist/shims/internal/headers-state.d.ts +7 -0
  179. package/dist/shims/internal/headers-state.js +14 -2
  180. package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +4 -1
  181. package/dist/shims/internal/hybrid-client-route-owner-direct.js +31 -14
  182. package/dist/shims/internal/hybrid-client-route-owner.js +8 -8
  183. package/dist/shims/link.js +5 -3
  184. package/dist/shims/navigation.d.ts +1 -1
  185. package/dist/shims/navigation.js +17 -5
  186. package/dist/shims/og.js +35 -10
  187. package/dist/shims/request-context.d.ts +13 -0
  188. package/dist/shims/router.js +19 -40
  189. package/dist/shims/server.d.ts +31 -4
  190. package/dist/shims/server.js +58 -10
  191. package/dist/shims/thenable-params.d.ts +6 -1
  192. package/dist/shims/thenable-params.js +11 -2
  193. package/dist/shims/unified-request-context.d.ts +5 -0
  194. package/dist/shims/unified-request-context.js +2 -0
  195. package/dist/utils/asset-prefix.d.ts +7 -0
  196. package/dist/utils/asset-prefix.js +10 -1
  197. package/dist/utils/client-build-manifest.js +12 -5
  198. package/dist/utils/client-runtime-metadata.d.ts +1 -0
  199. package/dist/utils/client-runtime-metadata.js +15 -2
  200. package/dist/utils/lazy-chunks.d.ts +4 -0
  201. package/dist/utils/manifest-paths.d.ts +14 -0
  202. package/dist/utils/manifest-paths.js +22 -1
  203. package/dist/utils/path-to-regexp.d.ts +21 -0
  204. package/dist/{server/middleware-path-to-regexp.js → utils/path-to-regexp.js} +14 -11
  205. package/dist/utils/plugin-react-version.d.ts +15 -0
  206. package/dist/utils/plugin-react-version.js +64 -0
  207. package/dist/utils/public-routes.d.ts +2 -0
  208. package/dist/utils/public-routes.js +18 -7
  209. package/package.json +1 -1
  210. package/dist/server/middleware-path-to-regexp.d.ts +0 -13
  211. package/dist/utils/regex-safety.d.ts +0 -17
  212. package/dist/utils/regex-safety.js +0 -789
@@ -11,6 +11,11 @@ type FinalizeAppRscResponseOptions = {
11
11
  * default-locale URLs (issue #1336, item 4).
12
12
  */
13
13
  i18nConfig: NextI18nConfig | null;
14
+ /**
15
+ * Whether the root keeps its trailing slash when the default locale is
16
+ * spliced in (`shouldRestoreLocaleRootTrailingSlash` on the raw request).
17
+ */
18
+ restoreLocaleRootTrailingSlash?: boolean;
14
19
  /**
15
20
  * Original pre-middleware request context.
16
21
  * Next.js evaluates config header has/missing conditions against the
@@ -32,7 +32,10 @@ async function applyAppRscConfigHeaders(headers, request, options) {
32
32
  let pathname = url.pathname;
33
33
  const hadBasePath = !options.basePath || hasBasePath(pathname, options.basePath);
34
34
  pathname = stripBasePath(pathname, options.basePath);
35
- const matchPathname = options.i18nConfig ? normalizeDefaultLocalePathname(pathname, options.i18nConfig, { hostname: url.hostname }) : pathname;
35
+ const matchPathname = options.i18nConfig ? normalizeDefaultLocalePathname(pathname, options.i18nConfig, {
36
+ hostname: url.hostname,
37
+ restoreRootTrailingSlash: options.restoreLocaleRootTrailingSlash
38
+ }) : pathname;
36
39
  const { applyConfigHeadersToResponse } = await import("./config-headers.js");
37
40
  applyConfigHeadersToResponse(headers, {
38
41
  configHeaders: options.configHeaders,
@@ -71,9 +71,10 @@ function rematchAppWorkerResponseStageRoute(options, normalized, props) {
71
71
  async function renderAppWorkerResponseStage(options, rawRequest, ctx, props, stageOptions) {
72
72
  if (props.protocolVersion !== 11 || props.buildId !== options.buildId) return new Response("Incompatible vinext App response stage", { status: 409 });
73
73
  if (props.kind === "app-full-request") return new Response("Invalid vinext App response stage", { status: 400 });
74
+ const rawRequestSignal = rawRequest.signal;
74
75
  options.registerCacheAdapters();
75
- await options.ensureInstrumentation?.();
76
76
  const executionContext = isExecutionContextLike(ctx) ? ctx : getRequestExecutionContext() ?? null;
77
+ await options.ensureInstrumentation?.(executionContext);
77
78
  const filteredHeaders = executionContext?.isInternalPagesRevalidation ? new Headers(rawRequest.headers) : filterInternalHeaders(rawRequest.headers);
78
79
  filteredHeaders.delete(VINEXT_REVALIDATE_HOST_HEADER);
79
80
  const request = cloneRequestWithHeaders(rawRequest, filteredHeaders);
@@ -103,6 +104,7 @@ async function renderAppWorkerResponseStage(options, rawRequest, ctx, props, sta
103
104
  const requestContext = createRequestContext({
104
105
  headersContext,
105
106
  executionContext,
107
+ requestSignal: executionContext?.requestSignal ?? rawRequestSignal,
106
108
  unstableCacheRevalidation: "background"
107
109
  });
108
110
  const middlewareContext = {
@@ -120,6 +120,7 @@ type AppRscInterceptLookupEntry = {
120
120
  slotId: string | null;
121
121
  targetRouteGraphId: string | null;
122
122
  };
123
+ export declare function isAppRouteHandlerRoute(route: Pick<AppRscRouteForMatching, "__loadRouteHandler" | "routeHandler">): boolean;
123
124
  /**
124
125
  * @param decodedPathnamePatterns Static page patterns that answer their
125
126
  * segment-decoded pathname (built by `buildAppDecodedPathnamePatterns`).
@@ -282,4 +282,4 @@ function pickPatternParams(params, patternParts) {
282
282
  return picked;
283
283
  }
284
284
  //#endregion
285
- export { SIBLING_PAGE_INTERCEPT_SLOT_KEY, createAppRscRouteMatcher };
285
+ export { SIBLING_PAGE_INTERCEPT_SLOT_KEY, createAppRscRouteMatcher, isAppRouteHandlerRoute };
@@ -19,8 +19,10 @@ type AppServerActionErrorReporter = (error: unknown, request: {
19
19
  renderSource: "react-server-components-payload";
20
20
  revalidateReason: undefined;
21
21
  }) => void;
22
- type AppServerActionDecoder = (body: FormData) => Promise<unknown>;
23
- type AppServerActionFormStateDecoder = (actionResult: unknown, body: FormData) => Promise<ReactFormState | undefined>;
22
+ /** React's `decodeAction()`; bound references resolve through `serverManifest`. */
23
+ type AppServerActionDecoder = (body: FormData, serverManifest: object) => Promise<unknown>;
24
+ /** React's `decodeFormState()`, which decodes the bound references again. */
25
+ type AppServerActionFormStateDecoder = (actionResult: unknown, body: FormData, serverManifest: object) => Promise<ReactFormState | undefined>;
24
26
  type ReadFormDataWithLimit = (request: Request, maxBytes: number) => Promise<FormData>;
25
27
  type ReadBodyWithLimit = (request: Request, maxBytes: number) => Promise<string>;
26
28
  type AppServerActionReturnValue = {
@@ -136,19 +138,22 @@ export type HandleProgressiveServerActionRequestOptions = {
136
138
  cleanPathname: string;
137
139
  clearRequestContext: () => void;
138
140
  contentType: string;
141
+ /** plugin-rsc's server manifest, which resolves any export of a server-reference module. */
142
+ createServerManifest: () => object;
139
143
  decodeAction: AppServerActionDecoder;
140
144
  decodeFormState: AppServerActionFormStateDecoder;
141
145
  getAndClearPendingCookies: () => string[];
142
146
  getDraftModeCookieHeader: () => string | null | undefined;
143
147
  forwardAction?: (actionId: string) => Promise<Response | null>;
144
- validateActionReferences?: (actionIds: readonly string[]) => boolean;
148
+ /** Whether these Server Actions belong to the current route. */
149
+ validateActionReferences: (actionIds: readonly string[]) => boolean;
145
150
  /**
146
151
  * Whether the posted-to route resolves to an App Router *page* (as opposed to
147
152
  * a route handler or no match). Multipart form POSTs to a page are always
148
153
  * server-action attempts in Next.js, so a body that decodes to no action must
149
154
  * surface as 404 action-not-found rather than rendering the page. Route
150
- * handlers (which run *after* this dispatch in vinext) legitimately receive
151
- * raw multipart POSTs, so they must still fall through. See issue #1340.
155
+ * handlers and Pages routes never reach this dispatch (#3886); unmatched
156
+ * routes fall through. See issue #1340.
152
157
  */
153
158
  hasPageRoute: boolean;
154
159
  maxActionBodySize: number;
@@ -176,7 +181,13 @@ export type HandleServerActionRscRequestOptions<TElement, TRoute extends AppServ
176
181
  createPayloadRouteId: (pathname: string, interceptionContext: string | null) => string;
177
182
  createRscOnErrorHandler: (request: Request, pathname: string, pattern: string, overrides?: AppRenderErrorContextOverrides) => (error: unknown) => unknown;
178
183
  createTemporaryReferenceSet: () => TTemporaryReferences;
179
- decodeReply: (body: string | FormData, options: DecodeServerActionReplyOptions<TTemporaryReferences>) => Promise<unknown[]> | unknown[];
184
+ /** plugin-rsc's server manifest, which resolves any export of a server-reference module. */
185
+ createServerManifest: () => object;
186
+ /**
187
+ * React's `decodeReply()`. Every server reference in the arguments resolves
188
+ * through `serverManifest`, so the manifest bounds which functions can decode.
189
+ */
190
+ decodeReply: (body: string | FormData, serverManifest: object, options: DecodeServerActionReplyOptions<TTemporaryReferences>) => Promise<unknown[]> | unknown[];
180
191
  draftModeSecret: string;
181
192
  /**
182
193
  * Hydrate a route's lazy page/route-handler modules before reading
@@ -192,6 +203,12 @@ export type HandleServerActionRscRequestOptions<TElement, TRoute extends AppServ
192
203
  isEdgeRuntime?: boolean;
193
204
  isRscRequest: boolean;
194
205
  loadServerAction: (actionId: string) => Promise<unknown>;
206
+ /**
207
+ * Whether these Server Actions belong to the current route. Next.js resolves
208
+ * argument references through the current page's server module map, so an
209
+ * action owned by another route must not decode into a callable function.
210
+ */
211
+ validateActionReferences: (actionIds: readonly string[]) => boolean;
195
212
  /**
196
213
  * Match an action redirect target. Must use *request* route identity — the
197
214
  * raw, undecoded pathname — because the target is rendered as if the client
@@ -9,6 +9,8 @@ import { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS
9
9
  import { internalServerErrorResponse, payloadTooLargeResponse } from "./http-error-responses.js";
10
10
  import { attachRequestCfMetadata, validateCsrfOrigin, validateServerActionPayload } from "./request-pipeline.js";
11
11
  import { splitPathSegments } from "../routing/utils.js";
12
+ import { getRequestExecutionContext } from "../shims/request-context.js";
13
+ import { shareIsolatePromise } from "./isolate-shared-promise.js";
12
14
  import { APP_RSC_RENDER_MODE_NAVIGATION } from "./app-rsc-render-mode.js";
13
15
  import { isDraftModeRequest, setHeadersContext } from "../shims/headers.js";
14
16
  import { _drainPendingRevalidations, getAndClearActionRevalidationKind } from "../shims/cache-request-state.js";
@@ -43,50 +45,47 @@ import { markAppRscResponseConfigHeadersApplied } from "./app-rsc-response-final
43
45
  *
44
46
  * The result is awaited inside the callback because `decodeReply()` returns a
45
47
  * lazy thenable that only resolves (and imports) its references once awaited.
48
+ *
49
+ * The imports are shared with every later request that names the same modules,
50
+ * and the server-reference loader cannot see this request's execution context
51
+ * once it has been left, so the request is kept alive here until they settle.
52
+ * From here a request that starts a load cannot be told apart from one that
53
+ * joins it, so each keeps its own decode alive; it awaits that decode anyway.
46
54
  */
47
55
  function loadOutsideRequestScopes(load) {
48
- return runOutsideRequestScopes(async () => await load());
56
+ const ctx = getRequestExecutionContext();
57
+ return shareIsolatePromise(runOutsideRequestScopes(async () => await load()), ctx);
49
58
  }
50
- function parseBoundProgressiveActionReference(body, referencePrefix) {
51
- const fieldPrefix = `$ACTION_${referencePrefix}:`;
52
- const chunks = /* @__PURE__ */ new Map();
53
- for (const [key, value] of body) {
54
- if (!key.startsWith(fieldPrefix) || typeof value !== "string") continue;
55
- const chunkId = key.slice(fieldPrefix.length);
56
- if (chunks.has(chunkId)) return null;
57
- try {
58
- chunks.set(chunkId, JSON.parse(value));
59
- } catch {
60
- return null;
61
- }
62
- }
63
- const rootMetadata = chunks.get("0");
64
- if (typeof rootMetadata !== "object" || rootMetadata === null || typeof Reflect.get(rootMetadata, "id") !== "string") return null;
65
- const actionId = Reflect.get(rootMetadata, "id");
66
- const referencedActionIds = /* @__PURE__ */ new Set([actionId]);
67
- for (const chunk of chunks.values()) {
68
- const values = [chunk];
69
- while (values.length > 0) {
70
- const value = values.pop();
71
- if (typeof value === "string") {
72
- if (!value.startsWith("$h")) continue;
73
- const [encodedChunkId, ...path] = value.slice(2).split(":");
74
- const chunkId = Number.parseInt(encodedChunkId, 16);
75
- if (!Number.isSafeInteger(chunkId) || chunkId < 0) return null;
76
- let metadata = chunks.get(String(chunkId));
77
- for (const segment of path) {
78
- if (typeof metadata !== "object" || metadata === null || !Object.hasOwn(metadata, segment)) return null;
79
- metadata = Reflect.get(metadata, segment);
80
- }
81
- if (typeof metadata !== "object" || metadata === null || typeof Reflect.get(metadata, "id") !== "string") return null;
82
- referencedActionIds.add(Reflect.get(metadata, "id"));
83
- } else if (typeof value === "object" && value !== null) values.push(...Object.values(value));
84
- }
59
+ /**
60
+ * Read the action a bound `$ACTION_REF_` submission names, which Next.js checks
61
+ * before decoding (`areAllActionIdsValid()`). The bound arguments are left to
62
+ * React, which resolves their references through the route-scoped manifest.
63
+ */
64
+ function readBoundProgressiveActionId(body, referencePrefix) {
65
+ const descriptors = body.getAll(`$ACTION_${referencePrefix}:0`);
66
+ if (descriptors.length !== 1 || typeof descriptors[0] !== "string") return null;
67
+ let descriptor;
68
+ try {
69
+ descriptor = JSON.parse(descriptors[0]);
70
+ } catch {
71
+ return null;
85
72
  }
86
- return {
87
- actionId,
88
- referencedActionIds: [...referencedActionIds]
89
- };
73
+ const actionId = typeof descriptor === "object" && descriptor !== null ? Reflect.get(descriptor, "id") : void 0;
74
+ return typeof actionId === "string" ? actionId : null;
75
+ }
76
+ /**
77
+ * Scope the manifest React resolves server references through to the current
78
+ * route's Server Actions, as Next.js scopes its server module map to the
79
+ * current page. React then fails to resolve any other id wherever a payload
80
+ * carries it, so that module never loads. A denied lookup throws because React
81
+ * retries a missing `module#a#b` as module `module#a` with export `b`, which
82
+ * would reach a non-action export of an owned module.
83
+ */
84
+ function createRouteServerManifest(manifest, validateActionReferences) {
85
+ return new Proxy(manifest, { get(target, id, receiver) {
86
+ if (typeof id === "string" && !validateActionReferences([id])) throw new Error(`Server reference "${id}" is not a Server Action of this route.`);
87
+ return Reflect.get(target, id, receiver);
88
+ } });
90
89
  }
91
90
  function prepareActionPageRerenderContext(options) {
92
91
  if (options.dynamicConfig === "force-static" || options.dynamicConfig === "error") {
@@ -572,32 +571,26 @@ async function handleProgressiveServerActionRequest(options) {
572
571
  let actionKey = null;
573
572
  for (const key of body.keys()) if (key.startsWith("$ACTION_ID_") || key.startsWith("$ACTION_REF_")) actionKey = key;
574
573
  let directActionId = null;
575
- let referencedActionIds = [];
576
574
  let invalidDirectActionReference = false;
577
- if (actionKey?.startsWith("$ACTION_ID_")) {
578
- directActionId = actionKey.slice(11);
579
- referencedActionIds = [directActionId];
580
- } else if (actionKey?.startsWith("$ACTION_REF_")) {
581
- const referencePrefix = actionKey.slice(12);
582
- const reference = parseBoundProgressiveActionReference(body, referencePrefix);
583
- if (reference) {
584
- directActionId = reference.actionId;
585
- referencedActionIds = reference.referencedActionIds;
586
- } else invalidDirectActionReference = true;
575
+ if (actionKey?.startsWith("$ACTION_ID_")) directActionId = actionKey.slice(11);
576
+ else if (actionKey?.startsWith("$ACTION_REF_")) {
577
+ directActionId = readBoundProgressiveActionId(body, actionKey.slice(12));
578
+ invalidDirectActionReference = directActionId === null;
587
579
  }
588
580
  if (invalidDirectActionReference) return createActionNotFoundResponse(null, {
589
581
  clearRequestContext: options.clearRequestContext,
590
582
  getAndClearPendingCookies: options.getAndClearPendingCookies
591
583
  });
592
- if (directActionId && options.forwardAction) {
584
+ if (directActionId !== null && options.forwardAction) {
593
585
  const forwardResponse = await options.forwardAction(directActionId);
594
586
  if (forwardResponse) return forwardResponse;
595
587
  }
596
- if (options.validateActionReferences && !options.validateActionReferences(referencedActionIds)) return createActionNotFoundResponse(directActionId, {
588
+ if (directActionId !== null && !options.validateActionReferences([directActionId])) return createActionNotFoundResponse(directActionId, {
597
589
  clearRequestContext: options.clearRequestContext,
598
590
  getAndClearPendingCookies: options.getAndClearPendingCookies
599
591
  });
600
- const action = await loadOutsideRequestScopes(() => options.decodeAction(body));
592
+ const serverManifest = createRouteServerManifest(options.createServerManifest(), options.validateActionReferences);
593
+ const action = await loadOutsideRequestScopes(() => options.decodeAction(body, serverManifest));
601
594
  if (!isAppServerActionFunction(action)) {
602
595
  if (options.hasPageRoute) return createActionNotFoundResponse(null, {
603
596
  clearRequestContext: options.clearRequestContext,
@@ -676,7 +669,7 @@ async function handleProgressiveServerActionRequest(options) {
676
669
  };
677
670
  return {
678
671
  kind: "form-state",
679
- formState: await loadOutsideRequestScopes(() => options.decodeFormState(actionResult, body)) ?? null,
672
+ formState: await loadOutsideRequestScopes(() => options.decodeFormState(actionResult, body, serverManifest)) ?? null,
680
673
  pendingCookies: actionPendingCookies,
681
674
  draftCookie: actionDraftCookie,
682
675
  revalidationKind
@@ -821,8 +814,9 @@ async function handleServerActionRscRequest(options) {
821
814
  });
822
815
  action = loadedAction;
823
816
  }
817
+ const serverManifest = createRouteServerManifest(options.createServerManifest(), options.validateActionReferences);
824
818
  const temporaryReferences = options.createTemporaryReferenceSet();
825
- const args = await loadOutsideRequestScopes(() => options.decodeReply(body, { temporaryReferences }));
819
+ const args = await loadOutsideRequestScopes(() => options.decodeReply(body, serverManifest, { temporaryReferences }));
826
820
  let returnValue;
827
821
  let actionRedirect = null;
828
822
  let actionStatus = 200;
@@ -25,6 +25,12 @@ export declare function handleSsr(rscStream: ReadableStream<Uint8Array>, navCont
25
25
  value: Promise<ArrayBuffer> | null;
26
26
  };
27
27
  pprFallbackShellSignal?: AbortSignal;
28
+ /**
29
+ * Pattern of the route this render shows, whose client references load
30
+ * before it starts, or null for a render without a route (a route-miss
31
+ * 404). Omitted, every client reference loads first.
32
+ */
33
+ preloadRoutePattern?: string | null;
28
34
  formState?: ReactFormState | null;
29
35
  basePath?: string;
30
36
  /**
@@ -15,14 +15,15 @@ import "./app-elements.js";
15
15
  import { ServerInsertedHTMLContext, clearServerInsertedHTML, getBfcacheIdMapContext, registerServerInsertedHTMLCallback, renderServerInsertedHTML, setNavigationContext } from "../shims/navigation-context-state.js";
16
16
  import "../shims/navigation-server.js";
17
17
  import DefaultGlobalError from "../shims/default-global-error.js";
18
- import { BfcacheIdentityMapContext, ElementsContext, Slot } from "../shims/slot.js";
18
+ import { BfcacheIdentityMapContext } from "../shims/slot.js";
19
19
  import { getNextErrorDigest } from "./next-error-digest.js";
20
20
  import { createSsrErrorMetaRenderer } from "./app-ssr-error-meta.js";
21
21
  import { createRenderStreamCancellation, isAppRenderAbortError } from "./app-render-abort-error.js";
22
22
  import { RSC_FORM_STATE_GLOBAL } from "../client/browser-globals.js";
23
- import { createNavigationRuntimeRenderedSearchScript, createNavigationRuntimeRscMetadataScript, createRscEmbedTransform, createTickBufferedTransform, waitAtLeastOneReactRenderTask } from "./app-ssr-stream.js";
23
+ import { createNavigationRuntimeRenderedSearchScript, createNavigationRuntimeRscCompatibilityScript, createNavigationRuntimeRscMetadataScript, createRscEmbedTransform, createTickBufferedTransform, waitAtLeastOneReactRenderTask } from "./app-ssr-stream.js";
24
24
  import { createInitialBfcacheMaps } from "./app-bfcache-identity.js";
25
- import { createClientReferencePreloader } from "./app-client-reference-preloader.js";
25
+ import { createAppRouteTree } from "./app-route-tree.js";
26
+ import { createClientReferencePreloader, resolveRouteClientReferences } from "./app-client-reference-preloader.js";
26
27
  import { createClientPageSsrSearchParamsSource } from "./app-page-search-params-observation.js";
27
28
  import { runWithRootParamsScope } from "../shims/root-params.js";
28
29
  import { runWithNavigationContext } from "../shims/navigation-state.js";
@@ -36,7 +37,7 @@ import { Fragment, createElement, use } from "react";
36
37
  import { renderToReadableStream, renderToStaticMarkup } from "react-dom/server.edge";
37
38
  import { preinitModule } from "react-dom";
38
39
  import { createFromReadableStream } from "@vitejs/plugin-rsc/ssr";
39
- import clientReferences from "virtual:vite-rsc/client-references";
40
+ import clientReferences, { routeClientReferences } from "virtual:vite-rsc/client-references";
40
41
  import pagesClientAssets from "virtual:vinext-pages-client-assets";
41
42
  //#region src/server/app-ssr-entry.ts
42
43
  setPagesClientAssets(pagesClientAssets);
@@ -164,7 +165,11 @@ function buildHeadInjectionHtml(navContext, bootstrapModuleUrl, formState, inser
164
165
  pathname: navContext.pathname,
165
166
  searchParams: [...navContext.searchParams.entries()]
166
167
  };
167
- return createInlineScriptTag(createNavigationRuntimeRscMetadataScript(navContext.params, navPayload, dynamicStaleTimeSeconds, searchParamsFromBrowser), scriptNonce) + (formState === null ? "" : createInlineScriptTag("self[" + safeJsonStringify(RSC_FORM_STATE_GLOBAL) + "]=" + safeJsonStringify(formState), scriptNonce)) + buildModulePreloadHtml(bootstrapModuleUrl, scriptNonce) + insertedHTML + fontHTML;
168
+ const rscMetadataScript = createInlineScriptTag(createNavigationRuntimeRscMetadataScript(navContext.params, navPayload, dynamicStaleTimeSeconds, searchParamsFromBrowser), scriptNonce);
169
+ const compatibilityScript = createNavigationRuntimeRscCompatibilityScript();
170
+ const rscCompatibilityScript = compatibilityScript === "" ? "" : createInlineScriptTag(compatibilityScript, scriptNonce);
171
+ const formStateScript = formState === null ? "" : createInlineScriptTag("self[" + safeJsonStringify(RSC_FORM_STATE_GLOBAL) + "]=" + safeJsonStringify(formState), scriptNonce);
172
+ return rscMetadataScript + rscCompatibilityScript + formStateScript + buildModulePreloadHtml(bootstrapModuleUrl, scriptNonce) + insertedHTML + fontHTML;
168
173
  }
169
174
  function requireNavigationContext(navContext) {
170
175
  if (!navContext) throw new Error("App SSR requires navigation context for BFCache state keys");
@@ -189,7 +194,7 @@ async function handleSsr(rscStream, navContext, fontData, options) {
189
194
  isPprFallbackShell: options?.pprFallbackShellSignal !== void 0
190
195
  })
191
196
  };
192
- await clientReferencePreloader.preload();
197
+ await clientReferencePreloader.preload(options?.pprFallbackShellSignal ? void 0 : resolveRouteClientReferences(routeClientReferences, options?.preloadRoutePattern));
193
198
  setNavigationContext(ssrNavigationContext);
194
199
  clearServerInsertedHTML();
195
200
  const cleanup = () => {
@@ -235,7 +240,11 @@ async function handleSsr(rscStream, navContext, fontData, options) {
235
240
  elements,
236
241
  metadata
237
242
  });
238
- const routeTree = createElement(ElementsContext.Provider, { value: elements }, createElement(Slot, { id: metadata.routeId }));
243
+ const routeTree = createAppRouteTree({
244
+ elements,
245
+ historyCommit: null,
246
+ routeId: metadata.routeId
247
+ });
239
248
  const identityMapTree = createElement(BfcacheIdentityMapContext.Provider, { value: bfcacheMaps.identities }, routeTree);
240
249
  return BfcacheIdMapContext ? createElement(BfcacheIdMapContext.Provider, { value: bfcacheMaps.bfcacheIds }, identityMapTree) : identityMapTree;
241
250
  }
@@ -32,6 +32,13 @@ export declare function createNavigationRuntimeRscMetadataScript(params: Record<
32
32
  pathname: string;
33
33
  searchParams: [string, string][];
34
34
  }, dynamicStaleTimeSeconds?: number, searchParamsFromBrowser?: boolean): string;
35
+ /**
36
+ * The compatibility ID of the server rendering this page. The browser compares
37
+ * RSC responses against it, so it is sent with the page rather than inlined
38
+ * into the client bundle, where a per-build value would rename chunks on every
39
+ * build. Static export skips the check, so its pages omit it.
40
+ */
41
+ export declare function createNavigationRuntimeRscCompatibilityScript(): string;
35
42
  /**
36
43
  * The query a client page read during SSR, for a render that turned dynamic
37
44
  * after its head told the browser to read the query from its own URL.
@@ -1,4 +1,5 @@
1
1
  import { createInlineScriptTag, escapeHtmlAttr, htmlTokenListContains, safeJsonStringify } from "./html.js";
2
+ import { getVinextRscCompatibilityId } from "./app-rsc-cache-busting.js";
2
3
  import { bytesToBase64, concatUint8Arrays } from "./app-rsc-embedded-chunks.js";
3
4
  import { NAVIGATION_RUNTIME_SYMBOL_DESCRIPTION } from "../client/browser-globals.js";
4
5
  //#region src/server/app-ssr-stream.ts
@@ -14,6 +15,17 @@ function createNavigationRuntimeRscMetadataScript(params, nav, dynamicStaleTimeS
14
15
  return "Object.assign(" + navigationRuntimeRscBootstrapExpression() + ",{params:" + safeJsonStringify(params) + ",nav:" + safeJsonStringify(nav) + (searchParamsFromBrowser === void 0 ? "" : ",searchParamsFromBrowser:" + safeJsonStringify(searchParamsFromBrowser)) + (dynamicStaleTimeSeconds === void 0 ? "" : ",dynamicStaleTimeSeconds:" + safeJsonStringify(dynamicStaleTimeSeconds)) + "})";
15
16
  }
16
17
  /**
18
+ * The compatibility ID of the server rendering this page. The browser compares
19
+ * RSC responses against it, so it is sent with the page rather than inlined
20
+ * into the client bundle, where a per-build value would rename chunks on every
21
+ * build. Static export skips the check, so its pages omit it.
22
+ */
23
+ function createNavigationRuntimeRscCompatibilityScript() {
24
+ const compatibilityId = getVinextRscCompatibilityId();
25
+ if (compatibilityId === null || process.env.NODE_ENV === "production" && process.env.__NEXT_CONFIG_OUTPUT === "export") return "";
26
+ return "Object.assign(" + navigationRuntimeRscBootstrapExpression() + ",{compatibilityId:" + safeJsonStringify(compatibilityId) + "})";
27
+ }
28
+ /**
17
29
  * The query a client page read during SSR, for a render that turned dynamic
18
30
  * after its head told the browser to read the query from its own URL.
19
31
  */
@@ -474,4 +486,4 @@ function createTickBufferedTransform(rscEmbed, injectHTML = "", injectAfterHeadO
474
486
  });
475
487
  }
476
488
  //#endregion
477
- export { createNavigationRuntimeRenderedSearchScript, createNavigationRuntimeRscMetadataScript, createRscEmbedTransform, createTickBufferedTransform, fixPreloadAs, navigationRuntimeRscBootstrapExpression, waitAtLeastOneReactRenderTask };
489
+ export { createNavigationRuntimeRenderedSearchScript, createNavigationRuntimeRscCompatibilityScript, createNavigationRuntimeRscMetadataScript, createRscEmbedTransform, createTickBufferedTransform, fixPreloadAs, navigationRuntimeRscBootstrapExpression, waitAtLeastOneReactRenderTask };
@@ -76,10 +76,12 @@ function appendVaryHeaderRecord(headers, value) {
76
76
  function applyConfigHeadersToResponse(responseHeaders, options) {
77
77
  const matched = retainLastSingularConfigValues(matchHeaders(options.pathname, options.configHeaders, options.requestContext, options.basePathState, options.recordCacheability === false ? void 0 : markConditionalConfigHeaderCacheability));
78
78
  if (options.recordCacheability !== false) markExplicitConfigResponseVeto(matched);
79
+ const configCookies = [];
79
80
  for (const header of matched) {
80
81
  const lowerName = header.key.toLowerCase();
81
82
  if (lowerName === "x-vinext-special-error-status") continue;
82
- if (lowerName === "link") {
83
+ if (lowerName === "set-cookie") configCookies.push(header.value);
84
+ else if (lowerName === "link") {
83
85
  if (options.middlewareHeaders?.get(lowerName)) continue;
84
86
  const postConfigLink = options.appendToPostConfigLink ? responseHeaders.get(lowerName) : null;
85
87
  responseHeaders.set(header.key, postConfigLink ? `${header.value}, ${postConfigLink}` : header.value);
@@ -88,15 +90,22 @@ function applyConfigHeadersToResponse(responseHeaders, options) {
88
90
  else if (ADDITIVE_CONFIG_HEADER_NAMES.has(lowerName)) responseHeaders.append(header.key, header.value);
89
91
  else if ((typeof options.overwriteExisting === "function" ? options.overwriteExisting(lowerName) : options.overwriteExisting?.has(lowerName)) || !responseHeaders.has(lowerName)) responseHeaders.set(header.key, header.value);
90
92
  }
93
+ if (configCookies.length > 0 && !options.middlewareHeaders?.get("set-cookie")) {
94
+ const responseCookies = responseHeaders.getSetCookie();
95
+ responseHeaders.delete("set-cookie");
96
+ for (const cookie of [...configCookies, ...responseCookies]) responseHeaders.append("set-cookie", cookie);
97
+ }
91
98
  }
92
99
  /** Apply matched next.config.js headers to an early response header record. */
93
100
  function applyConfigHeadersToHeaderRecord(headers, options) {
94
101
  const matched = retainLastSingularConfigValues(matchHeaders(options.pathname, options.configHeaders, options.requestContext, options.basePathState, options.recordCacheability === false ? void 0 : markConditionalConfigHeaderCacheability));
95
102
  if (options.recordCacheability !== false) markExplicitConfigResponseVeto(matched);
103
+ const middlewareSetsCookie = Boolean(options.middlewareHeaders?.get("set-cookie")) || findHeaderRecordKey(headers, "set-cookie") !== void 0;
96
104
  for (const header of matched) {
97
105
  const lowerName = header.key.toLowerCase();
98
- if (lowerName === "set-cookie") appendHeaderRecord(headers, lowerName, header.value);
99
- else if (lowerName === "vary") appendVaryHeaderRecord(headers, header.value);
106
+ if (lowerName === "set-cookie") {
107
+ if (!middlewareSetsCookie) appendHeaderRecord(headers, lowerName, header.value);
108
+ } else if (lowerName === "vary") appendVaryHeaderRecord(headers, header.value);
100
109
  else if (findHeaderRecordKey(headers, lowerName) === void 0) headers[lowerName] = header.value;
101
110
  }
102
111
  }
@@ -0,0 +1,10 @@
1
+ import { ExecutionContextLike } from "../shims/request-context.js";
2
+ //#region src/server/isolate-shared-promise.d.ts
3
+ /**
4
+ * Register `promise` with the creating request's `waitUntil()` and return it.
5
+ *
6
+ * @param ctx - The creating request's execution context. Defaults to the one
7
+ * in scope, for callers inside `runWithExecutionContext()`.
8
+ */
9
+ export declare function shareIsolatePromise<T>(promise: Promise<T>, ctx?: Partial<Pick<ExecutionContextLike, "waitUntil">> | null): Promise<T>;
10
+ //#endregion
@@ -0,0 +1,33 @@
1
+ import { getRequestExecutionContext } from "../shims/request-context.js";
2
+ //#region src/server/isolate-shared-promise.ts
3
+ /**
4
+ * Keep the request that creates an isolate-shared promise alive until it
5
+ * settles.
6
+ *
7
+ * workerd binds the I/O a promise waits on (timers, fetches, dynamic
8
+ * `import()` under the legacy module registry) to the request that started it.
9
+ * If that request is canceled first, for example because the client navigated
10
+ * away or aborted a prefetch, the continuations are dropped and the promise
11
+ * never settles. A promise memoized for the isolate is awaited by every later
12
+ * request too, so they would all wait forever. `waitUntil()` keeps the creating
13
+ * request's context running after cancellation, so the work finishes for
14
+ * everyone.
15
+ *
16
+ * Call this only where the shared promise is created. Later requests that
17
+ * merely await it need nothing.
18
+ */
19
+ function ignore() {}
20
+ /**
21
+ * Register `promise` with the creating request's `waitUntil()` and return it.
22
+ *
23
+ * @param ctx - The creating request's execution context. Defaults to the one
24
+ * in scope, for callers inside `runWithExecutionContext()`.
25
+ */
26
+ function shareIsolatePromise(promise, ctx) {
27
+ (typeof ctx?.waitUntil === "function" ? ctx : getRequestExecutionContext())?.waitUntil?.(promise.then(ignore, ignore));
28
+ return promise;
29
+ }
30
+ const SHARE_ISOLATE_PROMISE_KEY = Symbol.for("vinext.shareIsolatePromise");
31
+ globalThis[SHARE_ISOLATE_PROMISE_KEY] ??= shareIsolatePromise;
32
+ //#endregion
33
+ export { shareIsolatePromise };
@@ -4,6 +4,7 @@ import { getRequestExecutionContext } from "../shims/request-context.js";
4
4
  import { isInterceptionMatchedUrlPath } from "./normalize-path.js";
5
5
  import { reportRequestError } from "./instrumentation.js";
6
6
  import { getCdnCacheAdapter } from "../shims/cdn-cache.js";
7
+ import { shareIsolatePromise } from "./isolate-shared-promise.js";
7
8
  import { normalizeMountedSlotsHeader } from "./app-mounted-slots-header.js";
8
9
  import { APP_RSC_RENDER_MODE_NAVIGATION, getRscRenderModeCacheVariant } from "./app-rsc-render-mode.js";
9
10
  import { getRevalidateSecret, isOnDemandRevalidateRequest, isRevalidateSecret } from "./revalidation-request.js";
@@ -93,9 +94,9 @@ const pendingOnDemandRegenerations = _g[_PENDING_ON_DEMAND_REGEN_KEY] ??= /* @__
93
94
  function coalesceOnDemandRevalidation(key, renderFn) {
94
95
  const pending = pendingOnDemandRegenerations.get(key);
95
96
  if (pending) return pending;
96
- const promise = Promise.resolve().then(renderFn).finally(() => {
97
+ const promise = shareIsolatePromise(Promise.resolve().then(renderFn).finally(() => {
97
98
  if (pendingOnDemandRegenerations.get(key) === promise) pendingOnDemandRegenerations.delete(key);
98
- });
99
+ }));
99
100
  pendingOnDemandRegenerations.set(key, promise);
100
101
  return promise;
101
102
  }
@@ -6,7 +6,6 @@ export type CompiledMiddlewareMatcherPattern = {
6
6
  } | {
7
7
  regexp?: never;
8
8
  error: string;
9
- kind: "invalid" | "unsafe";
10
9
  };
11
10
  export type MiddlewareMatcherObject = {
12
11
  source: string;