@qzsy/vinext 0.1.12 → 0.1.80

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 (225) hide show
  1. package/README.md +19 -5
  2. package/dist/build/inject-pregenerated-paths.d.ts +4 -0
  3. package/dist/build/inject-pregenerated-paths.js +18 -0
  4. package/dist/build/pages-client-assets-module.d.ts +11 -0
  5. package/dist/build/pages-client-assets-module.js +27 -0
  6. package/dist/build/prerender.d.ts +2 -1
  7. package/dist/build/prerender.js +11 -4
  8. package/dist/build/report.d.ts +2 -1
  9. package/dist/build/report.js +2 -1
  10. package/dist/build/run-prerender.d.ts +7 -0
  11. package/dist/build/run-prerender.js +9 -0
  12. package/dist/build/standalone.js +2 -0
  13. package/dist/check.d.ts +18 -0
  14. package/dist/check.js +77 -19
  15. package/dist/cli-dev-config.d.ts +12 -0
  16. package/dist/cli-dev-config.js +23 -0
  17. package/dist/cli.js +64 -28
  18. package/dist/{server → client}/dev-error-overlay-store.d.ts +1 -1
  19. package/dist/{server → client}/dev-error-overlay-store.js +1 -1
  20. package/dist/{server → client}/dev-error-overlay.d.ts +1 -1
  21. package/dist/{server → client}/dev-error-overlay.js +2 -2
  22. package/dist/cloudflare/deploy-config.d.ts +51 -0
  23. package/dist/cloudflare/deploy-config.js +153 -0
  24. package/dist/cloudflare/index.d.ts +1 -1
  25. package/dist/cloudflare/index.js +1 -1
  26. package/dist/cloudflare/project.d.ts +41 -0
  27. package/dist/cloudflare/project.js +243 -0
  28. package/dist/cloudflare/tpr.js +1 -1
  29. package/dist/config/config-matchers.js +14 -10
  30. package/dist/config/next-config.d.ts +6 -3
  31. package/dist/config/next-config.js +47 -1
  32. package/dist/config/server-external-packages.d.ts +4 -0
  33. package/dist/config/server-external-packages.js +91 -0
  34. package/dist/deploy.d.ts +2 -122
  35. package/dist/deploy.js +20 -793
  36. package/dist/entries/app-rsc-entry.d.ts +2 -1
  37. package/dist/entries/app-rsc-entry.js +70 -12
  38. package/dist/entries/app-rsc-manifest.js +8 -0
  39. package/dist/entries/pages-client-entry.d.ts +1 -0
  40. package/dist/entries/pages-client-entry.js +2 -1
  41. package/dist/entries/pages-server-entry.js +6 -2
  42. package/dist/image/image-adapters-virtual.d.ts +59 -0
  43. package/dist/image/image-adapters-virtual.js +50 -0
  44. package/dist/index.d.ts +12 -0
  45. package/dist/index.js +158 -109
  46. package/dist/init-cloudflare.d.ts +43 -0
  47. package/dist/init-cloudflare.js +1000 -0
  48. package/dist/init-platform.d.ts +38 -0
  49. package/dist/init-platform.js +150 -0
  50. package/dist/init.d.ts +14 -37
  51. package/dist/init.js +205 -95
  52. package/dist/node_modules/.pnpm/am-i-vibing@0.5.0/node_modules/am-i-vibing/dist/detector-1yx2Hoe0.js +294 -0
  53. package/dist/node_modules/.pnpm/process-ancestry@0.1.0/node_modules/process-ancestry/dist/index.js +94 -0
  54. package/dist/{cloudflare → packages/cloudflare}/src/cache/cdn-adapter.runtime.js +1 -1
  55. package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.d.ts +2 -2
  56. package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.js +1 -1
  57. package/dist/plugins/ast-scope.d.ts +16 -0
  58. package/dist/plugins/ast-scope.js +62 -0
  59. package/dist/plugins/ast-utils.js +3 -0
  60. package/dist/plugins/css-module-imports.d.ts +14 -0
  61. package/dist/plugins/css-module-imports.js +59 -0
  62. package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
  63. package/dist/plugins/ignore-dynamic-requests.js +530 -0
  64. package/dist/plugins/middleware-server-only.d.ts +8 -6
  65. package/dist/plugins/middleware-server-only.js +8 -7
  66. package/dist/plugins/optimize-imports.js +1 -1
  67. package/dist/plugins/typeof-window.d.ts +1 -1
  68. package/dist/plugins/typeof-window.js +28 -56
  69. package/dist/routing/app-route-graph.d.ts +13 -2
  70. package/dist/routing/app-route-graph.js +116 -32
  71. package/dist/routing/app-router.d.ts +5 -0
  72. package/dist/routing/app-router.js +5 -0
  73. package/dist/routing/file-matcher.d.ts +8 -0
  74. package/dist/routing/file-matcher.js +10 -1
  75. package/dist/routing/pages-router.js +2 -2
  76. package/dist/server/app-browser-action-result.d.ts +2 -1
  77. package/dist/server/app-browser-action-result.js +5 -1
  78. package/dist/server/app-browser-entry.js +17 -12
  79. package/dist/server/app-browser-history-controller.d.ts +2 -1
  80. package/dist/server/app-browser-history-controller.js +6 -2
  81. package/dist/server/app-browser-interception-context.d.ts +1 -0
  82. package/dist/server/app-browser-interception-context.js +4 -2
  83. package/dist/server/app-browser-navigation-controller.js +1 -0
  84. package/dist/server/app-browser-server-action-client.js +2 -3
  85. package/dist/server/app-browser-state.d.ts +1 -0
  86. package/dist/server/app-browser-state.js +3 -2
  87. package/dist/server/app-fallback-renderer.d.ts +3 -2
  88. package/dist/server/app-fallback-renderer.js +12 -7
  89. package/dist/server/app-middleware.d.ts +2 -3
  90. package/dist/server/app-middleware.js +3 -2
  91. package/dist/server/app-optimistic-routing.js +1 -1
  92. package/dist/server/app-page-boundary-render.d.ts +1 -0
  93. package/dist/server/app-page-boundary-render.js +12 -3
  94. package/dist/server/app-page-cache-finalizer.d.ts +1 -0
  95. package/dist/server/app-page-cache-finalizer.js +10 -3
  96. package/dist/server/app-page-cache-render.d.ts +1 -0
  97. package/dist/server/app-page-cache-render.js +8 -4
  98. package/dist/server/app-page-cache.d.ts +1 -0
  99. package/dist/server/app-page-cache.js +4 -1
  100. package/dist/server/app-page-dispatch.d.ts +11 -3
  101. package/dist/server/app-page-dispatch.js +55 -15
  102. package/dist/server/app-page-element-builder.d.ts +5 -1
  103. package/dist/server/app-page-element-builder.js +57 -20
  104. package/dist/server/app-page-head.d.ts +12 -0
  105. package/dist/server/app-page-head.js +42 -19
  106. package/dist/server/app-page-params.d.ts +2 -1
  107. package/dist/server/app-page-params.js +8 -1
  108. package/dist/server/app-page-probe.d.ts +1 -0
  109. package/dist/server/app-page-probe.js +6 -1
  110. package/dist/server/app-page-render-identity.d.ts +1 -0
  111. package/dist/server/app-page-render-identity.js +1 -1
  112. package/dist/server/app-page-render.d.ts +4 -1
  113. package/dist/server/app-page-render.js +8 -3
  114. package/dist/server/app-page-request.d.ts +22 -1
  115. package/dist/server/app-page-request.js +89 -13
  116. package/dist/server/app-page-route-wiring.d.ts +6 -1
  117. package/dist/server/app-page-route-wiring.js +31 -15
  118. package/dist/server/app-page-search-params-observation.d.ts +4 -2
  119. package/dist/server/app-page-search-params-observation.js +11 -7
  120. package/dist/server/app-page-segment-state.js +2 -0
  121. package/dist/server/app-route-handler-dispatch.js +1 -0
  122. package/dist/server/app-route-handler-execution.js +7 -2
  123. package/dist/server/app-route-handler-response.js +1 -0
  124. package/dist/server/app-route-handler-runtime.js +1 -1
  125. package/dist/server/app-route-module-loader.d.ts +2 -0
  126. package/dist/server/app-route-module-loader.js +1 -0
  127. package/dist/server/app-router-entry.d.ts +12 -0
  128. package/dist/server/app-router-entry.js +22 -8
  129. package/dist/server/app-router-image-optimization.d.ts +37 -0
  130. package/dist/server/app-router-image-optimization.js +40 -0
  131. package/dist/server/app-rsc-errors.js +7 -1
  132. package/dist/server/app-rsc-handler.js +27 -14
  133. package/dist/server/app-rsc-route-matching.d.ts +7 -0
  134. package/dist/server/app-rsc-route-matching.js +36 -3
  135. package/dist/server/app-segment-config.d.ts +12 -0
  136. package/dist/server/app-segment-config.js +91 -5
  137. package/dist/server/app-server-action-execution.d.ts +5 -0
  138. package/dist/server/app-server-action-execution.js +94 -33
  139. package/dist/server/app-ssr-entry.js +12 -1
  140. package/dist/server/app-static-generation.d.ts +1 -0
  141. package/dist/server/app-static-generation.js +1 -0
  142. package/dist/server/client-trace-metadata.js +26 -0
  143. package/dist/server/default-global-not-found-module.d.ts +14 -0
  144. package/dist/server/default-global-not-found-module.js +14 -0
  145. package/dist/server/dev-server.js +8 -15
  146. package/dist/server/dev-stack-sourcemap.d.ts +1 -1
  147. package/dist/server/dev-stack-sourcemap.js +1 -1
  148. package/dist/server/headers.d.ts +5 -15
  149. package/dist/server/headers.js +4 -15
  150. package/dist/server/image-optimization.d.ts +51 -1
  151. package/dist/server/image-optimization.js +52 -2
  152. package/dist/server/isr-cache.d.ts +1 -1
  153. package/dist/server/isr-cache.js +2 -2
  154. package/dist/server/middleware-runtime.js +6 -1
  155. package/dist/server/navigation-planner.d.ts +1 -0
  156. package/dist/server/navigation-planner.js +14 -3
  157. package/dist/server/pages-asset-tags.d.ts +4 -6
  158. package/dist/server/pages-asset-tags.js +12 -12
  159. package/dist/server/pages-client-assets.d.ts +12 -0
  160. package/dist/server/pages-client-assets.js +10 -0
  161. package/dist/server/pages-page-data.d.ts +23 -1
  162. package/dist/server/pages-page-data.js +43 -24
  163. package/dist/server/pages-page-handler.d.ts +2 -1
  164. package/dist/server/pages-page-handler.js +10 -4
  165. package/dist/server/pages-request-pipeline.d.ts +2 -0
  166. package/dist/server/pages-request-pipeline.js +25 -1
  167. package/dist/server/prerender-manifest.d.ts +3 -1
  168. package/dist/server/prerender-route-params.js +1 -1
  169. package/dist/server/prod-server.d.ts +1 -1
  170. package/dist/server/prod-server.js +47 -25
  171. package/dist/server/request-pipeline.js +1 -0
  172. package/dist/server/seed-cache.js +4 -4
  173. package/dist/server/worker-utils.d.ts +2 -1
  174. package/dist/server/worker-utils.js +7 -1
  175. package/dist/shims/app-router-scroll-state.d.ts +1 -0
  176. package/dist/shims/app-router-scroll-state.js +1 -0
  177. package/dist/shims/app-router-scroll.js +2 -1
  178. package/dist/shims/cache.js +19 -15
  179. package/dist/shims/cdn-cache.js +1 -1
  180. package/dist/shims/dynamic-preload-chunks.js +2 -1
  181. package/dist/shims/error-boundary.d.ts +19 -1
  182. package/dist/shims/error-boundary.js +11 -1
  183. package/dist/shims/form.d.ts +3 -1
  184. package/dist/shims/form.js +37 -43
  185. package/dist/shims/headers.d.ts +9 -1
  186. package/dist/shims/headers.js +31 -6
  187. package/dist/shims/image-optimization-url.d.ts +4 -0
  188. package/dist/shims/image-optimization-url.js +33 -1
  189. package/dist/shims/image.js +46 -13
  190. package/dist/shims/internal/app-route-detection.d.ts +2 -17
  191. package/dist/shims/internal/app-route-detection.js +4 -17
  192. package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +23 -0
  193. package/dist/shims/internal/hybrid-client-route-owner-direct.js +51 -0
  194. package/dist/shims/internal/hybrid-client-route-owner.d.ts +2 -5
  195. package/dist/shims/internal/hybrid-client-route-owner.js +9 -60
  196. package/dist/shims/internal/pages-router-components.d.ts +7 -0
  197. package/dist/shims/internal/pages-router-components.js +13 -0
  198. package/dist/shims/link.js +23 -16
  199. package/dist/shims/metadata.d.ts +3 -2
  200. package/dist/shims/metadata.js +8 -4
  201. package/dist/shims/navigation.js +4 -2
  202. package/dist/shims/root-params.d.ts +15 -1
  203. package/dist/shims/root-params.js +21 -1
  204. package/dist/shims/router.d.ts +2 -5
  205. package/dist/shims/router.js +41 -22
  206. package/dist/shims/server.js +3 -2
  207. package/dist/typegen.js +6 -5
  208. package/dist/utils/client-runtime-metadata.d.ts +2 -18
  209. package/dist/utils/client-runtime-metadata.js +31 -22
  210. package/dist/utils/dev-stack-sourcemap-endpoint.d.ts +4 -0
  211. package/dist/{server → utils}/dev-stack-sourcemap-endpoint.js +1 -1
  212. package/dist/utils/domain-locale.d.ts +6 -3
  213. package/dist/{server → utils}/middleware-request-headers.d.ts +1 -1
  214. package/dist/{server → utils}/middleware-request-headers.js +2 -2
  215. package/dist/utils/path.d.ts +2 -1
  216. package/dist/utils/path.js +1 -1
  217. package/dist/utils/project.d.ts +9 -1
  218. package/dist/utils/project.js +21 -4
  219. package/dist/utils/protocol-headers.d.ts +17 -0
  220. package/dist/utils/protocol-headers.js +17 -0
  221. package/dist/utils/react-version.d.ts +4 -0
  222. package/dist/utils/react-version.js +44 -0
  223. package/package.json +6 -1
  224. package/dist/server/dev-stack-sourcemap-endpoint.d.ts +0 -4
  225. /package/dist/{cloudflare → packages/cloudflare}/src/utils/cache-control-metadata.js +0 -0
@@ -1,7 +1,8 @@
1
1
  import { getOrCreateAls } from "./internal/als-registry.js";
2
2
  import { getRequestContext, isInsideUnifiedScope, runWithUnifiedStateMutation } from "./unified-request-context.js";
3
- import { MIDDLEWARE_SET_COOKIE_HEADER } from "../server/headers.js";
4
- import { buildRequestHeadersFromMiddlewareResponse } from "../server/middleware-request-headers.js";
3
+ import { MIDDLEWARE_SET_COOKIE_HEADER } from "../utils/protocol-headers.js";
4
+ import { FLIGHT_HEADERS, NEXT_HTML_REQUEST_ID_HEADER, NEXT_REQUEST_ID_HEADER } from "../server/headers.js";
5
+ import { buildRequestHeadersFromMiddlewareResponse } from "../utils/middleware-request-headers.js";
5
6
  import { serializeSetCookie, validateCookieAttributeValue, validateCookieName } from "./internal/cookie-serialize.js";
6
7
  import { parseEdgeRequestCookieHeader } from "../utils/parse-cookie.js";
7
8
  import { createPprFallbackShellSuspensePromise } from "./ppr-fallback-shell.js";
@@ -117,6 +118,10 @@ function markDynamicUsage() {
117
118
  function markRenderRequestApiUsage(kind) {
118
119
  _getState().renderRequestApiUsage.add(kind);
119
120
  }
121
+ function throwIfStaticGenerationAccessError() {
122
+ const accessError = _getState().headersContext?.accessError;
123
+ if (accessError) throw accessError;
124
+ }
120
125
  async function runWithConnectionProbe(fn) {
121
126
  const state = _getState();
122
127
  const previousProbe = state.connectionProbe;
@@ -468,7 +473,13 @@ function _getReadonlyCookies(ctx) {
468
473
  return ctx.readonlyCookies;
469
474
  }
470
475
  function _getReadonlyHeaders(ctx) {
471
- if (!ctx.readonlyHeaders) ctx.readonlyHeaders = _sealHeaders(ctx.headers);
476
+ if (!ctx.readonlyHeaders) {
477
+ const cleaned = new Headers(ctx.headers);
478
+ for (const header of FLIGHT_HEADERS) cleaned.delete(header);
479
+ cleaned.delete(NEXT_REQUEST_ID_HEADER);
480
+ cleaned.delete(NEXT_HTML_REQUEST_ID_HEADER);
481
+ ctx.readonlyHeaders = _sealHeaders(cleaned);
482
+ }
472
483
  return ctx.readonlyHeaders;
473
484
  }
474
485
  /**
@@ -599,6 +610,19 @@ function isDraftModeRequest(request, draftModeSecret) {
599
610
  if (!cookieHeader) return false;
600
611
  return parseEdgeRequestCookieHeader(cookieHeader).get(DRAFT_MODE_COOKIE) === validateDraftModeSecret(draftModeSecret);
601
612
  }
613
+ /**
614
+ * Read the active request's draft-mode state without recording request API usage.
615
+ * Internal cache implementations use this to bypass persistent reads and writes,
616
+ * matching Next.js's request-level `workStore.isDraftMode` guard.
617
+ */
618
+ function isDraftModeEnabled() {
619
+ const context = _getState().headersContext;
620
+ if (!context) return false;
621
+ if (context.draftModeEnabled !== void 0) return context.draftModeEnabled;
622
+ const secret = context.draftModeSecret;
623
+ if (secret === void 0) return false;
624
+ return context.cookies.get(DRAFT_MODE_COOKIE) === validateDraftModeSecret(secret);
625
+ }
602
626
  function draftModeCookieAttributes() {
603
627
  if (typeof process !== "undefined" && process.env?.NODE_ENV === "development") return "Path=/; HttpOnly; SameSite=Lax";
604
628
  return "Path=/; HttpOnly; SameSite=None; Secure";
@@ -631,16 +655,16 @@ async function draftMode() {
631
655
  const state = _getState();
632
656
  const context = state.headersContext;
633
657
  if (!context) throw createDraftModeScopeError("draftMode()");
634
- if (context.accessError) throw context.accessError;
635
658
  const secret = ensureContextDraftModeSecret(context);
636
659
  return {
637
660
  get isEnabled() {
638
- return context.cookies.get(DRAFT_MODE_COOKIE) === secret;
661
+ return context.draftModeEnabled ?? context.cookies.get(DRAFT_MODE_COOKIE) === secret;
639
662
  },
640
663
  enable() {
641
664
  throwIfInsideCacheScope("draftMode().enable()");
642
665
  const activeContext = requireActiveDraftModeContext(state, context, "draftMode().enable()");
643
666
  markDynamicUsage();
667
+ activeContext.draftModeEnabled = true;
644
668
  activeContext.cookies.set(DRAFT_MODE_COOKIE, secret);
645
669
  state.draftModeCookieHeader = `${DRAFT_MODE_COOKIE}=${secret}; ${draftModeCookieAttributes()}`;
646
670
  },
@@ -648,6 +672,7 @@ async function draftMode() {
648
672
  throwIfInsideCacheScope("draftMode().disable()");
649
673
  const activeContext = requireActiveDraftModeContext(state, context, "draftMode().disable()");
650
674
  markDynamicUsage();
675
+ activeContext.draftModeEnabled = false;
651
676
  activeContext.cookies.delete(DRAFT_MODE_COOKIE);
652
677
  state.draftModeCookieHeader = `${DRAFT_MODE_COOKIE}=; ${draftModeCookieAttributes()}; Expires=${DRAFT_MODE_EXPIRED_DATE}`;
653
678
  }
@@ -751,4 +776,4 @@ var RequestCookies = class {
751
776
  }
752
777
  };
753
778
  //#endregion
754
- export { applyMiddlewareRequestHeaders, consumeDynamicUsage, consumeInvalidDynamicUsageError, consumeRenderRequestApiUsage, cookies, draftMode, getAndClearPendingCookies, getDraftModeCookieHeader, getHeadersAccessPhase, getHeadersContext, headers, headersContextFromRequest, isDraftModeRequest, markDynamicUsage, markRenderRequestApiUsage, peekDynamicUsage, peekRenderRequestApiUsage, runWithConnectionProbe, runWithHeadersContext, setHeadersAccessPhase, setHeadersContext, suspendConnectionProbe, throwIfInsideCacheScope };
779
+ export { applyMiddlewareRequestHeaders, consumeDynamicUsage, consumeInvalidDynamicUsageError, consumeRenderRequestApiUsage, cookies, draftMode, getAndClearPendingCookies, getDraftModeCookieHeader, getHeadersAccessPhase, getHeadersContext, headers, headersContextFromRequest, isDraftModeEnabled, isDraftModeRequest, markDynamicUsage, markRenderRequestApiUsage, peekDynamicUsage, peekRenderRequestApiUsage, runWithConnectionProbe, runWithHeadersContext, setHeadersAccessPhase, setHeadersContext, suspendConnectionProbe, throwIfInsideCacheScope, throwIfStaticGenerationAccessError };
@@ -4,6 +4,10 @@
4
4
  *
5
5
  * Shared by the next/image shim and the default image loader module so
6
6
  * `images.loaderFile` aliasing does not create a circular import.
7
+ *
8
+ * In production (Cloudflare Workers), the worker intercepts this path and uses
9
+ * the Images binding to resize/transcode on the fly. In dev, the Vite dev
10
+ * server handles it as a passthrough (serves the original file).
7
11
  */
8
12
  declare function imageOptimizationUrl(src: string, width: number, quality?: number): string;
9
13
  //#endregion
@@ -1,12 +1,44 @@
1
+ import { getDeploymentId } from "../utils/deployment-id.js";
1
2
  //#region src/shims/image-optimization-url.ts
3
+ function extractLocalDeploymentId(src) {
4
+ let deploymentId = getDeploymentId();
5
+ if (!src.startsWith("/") || src.startsWith("//")) return {
6
+ src,
7
+ deploymentId
8
+ };
9
+ const queryIndex = src.indexOf("?");
10
+ if (queryIndex === -1) return {
11
+ src,
12
+ deploymentId
13
+ };
14
+ const params = new URLSearchParams(src.slice(queryIndex + 1));
15
+ const sourceDeploymentId = params.get("dpl");
16
+ if (!sourceDeploymentId) return {
17
+ src,
18
+ deploymentId
19
+ };
20
+ deploymentId = sourceDeploymentId;
21
+ params.delete("dpl");
22
+ const remainingQuery = params.toString();
23
+ return {
24
+ src: src.slice(0, queryIndex) + (remainingQuery ? `?${remainingQuery}` : ""),
25
+ deploymentId
26
+ };
27
+ }
2
28
  /**
3
29
  * Build a `/_next/image` optimization URL.
4
30
  *
5
31
  * Shared by the next/image shim and the default image loader module so
6
32
  * `images.loaderFile` aliasing does not create a circular import.
33
+ *
34
+ * In production (Cloudflare Workers), the worker intercepts this path and uses
35
+ * the Images binding to resize/transcode on the fly. In dev, the Vite dev
36
+ * server handles it as a passthrough (serves the original file).
7
37
  */
8
38
  function imageOptimizationUrl(src, width, quality = 75) {
9
- return `/_next/image?url=${encodeURIComponent(src)}&w=${width}&q=${quality}`;
39
+ const source = extractLocalDeploymentId(src);
40
+ const deploymentQuery = source.src.startsWith("/") && source.deploymentId ? `&dpl=${source.deploymentId}` : "";
41
+ return `/_next/image?url=${encodeURIComponent(source.src)}&w=${width}&q=${quality}${deploymentQuery}`;
10
42
  }
11
43
  //#endregion
12
44
  export { imageOptimizationUrl };
@@ -56,6 +56,22 @@ const __imageDeviceSizes = (() => {
56
56
  ];
57
57
  }
58
58
  })();
59
+ const __imageSizes = (() => {
60
+ try {
61
+ return JSON.parse(process.env.__VINEXT_IMAGE_SIZES ?? "[16,32,48,64,96,128,256,384]");
62
+ } catch {
63
+ return [
64
+ 16,
65
+ 32,
66
+ 48,
67
+ 64,
68
+ 96,
69
+ 128,
70
+ 256,
71
+ 384
72
+ ];
73
+ }
74
+ })();
59
75
  /**
60
76
  * Whether dangerouslyAllowSVG is enabled in next.config.js.
61
77
  * When false (default), .svg sources auto-skip the optimization endpoint
@@ -78,6 +94,7 @@ function resolveEffectiveLoader(loader) {
78
94
  if (typeof defaultImageLoader !== "function") throw new Error("images.loaderFile detected but the file is missing default export.\nRead more: https://nextjs.org/docs/messages/invalid-images-config");
79
95
  return defaultImageLoader;
80
96
  }
97
+ const __globallyUnoptimized = process.env.__VINEXT_IMAGE_UNOPTIMIZED === "true";
81
98
  /**
82
99
  * Validate that a remote URL is allowed by the configured remote patterns.
83
100
  * Returns true if the URL is allowed, false otherwise.
@@ -220,7 +237,8 @@ function resolveImageSource(v) {
220
237
  * These are the breakpoints used for srcSet generation.
221
238
  * Configurable via `images.deviceSizes` in next.config.js.
222
239
  */
223
- const RESPONSIVE_WIDTHS = __imageDeviceSizes;
240
+ const RESPONSIVE_WIDTHS = [...__imageDeviceSizes].sort((left, right) => left - right);
241
+ const ALL_IMAGE_WIDTHS = [...RESPONSIVE_WIDTHS, ...__imageSizes].sort((left, right) => left - right);
224
242
  function preloadImageResource(input) {
225
243
  if (!input.shouldPreload) return;
226
244
  if (typeof ReactDOM.preload !== "function") return;
@@ -235,13 +253,26 @@ function preloadImageResource(input) {
235
253
  * Generate a srcSet string for responsive images.
236
254
  *
237
255
  * Each width points to the `/_next/image` optimization endpoint so the
238
- * server can resize and transcode the image. Only includes widths that are
239
- * <= 2x the original image width to avoid pointless upscaling.
256
+ * server can resize and transcode the image.
240
257
  */
241
- function generateSrcSet(src, originalWidth, quality = 75) {
242
- const widths = RESPONSIVE_WIDTHS.filter((w) => w <= originalWidth * 2);
243
- if (widths.length === 0) return `${imageOptimizationUrl(src, originalWidth, quality)} ${originalWidth}w`;
244
- return widths.map((w) => `${imageOptimizationUrl(src, w, quality)} ${w}w`).join(", ");
258
+ function getImageWidths(width) {
259
+ return [...new Set([width, width * 2].map((targetWidth) => ALL_IMAGE_WIDTHS.find((configuredWidth) => configuredWidth >= targetWidth) ?? ALL_IMAGE_WIDTHS[ALL_IMAGE_WIDTHS.length - 1]))];
260
+ }
261
+ function generateImageAttributes(src, width, quality = 75, sizes) {
262
+ if (sizes) {
263
+ const viewportPercentages = Array.from(sizes.matchAll(/(^|\s)(1?\d?\d)vw/g), (match) => Number.parseInt(match[2], 10));
264
+ const minimumWidth = viewportPercentages.length > 0 ? RESPONSIVE_WIDTHS[0] * (Math.min(...viewportPercentages) * .01) : 0;
265
+ const candidates = ALL_IMAGE_WIDTHS.filter((candidateWidth) => candidateWidth >= minimumWidth);
266
+ return {
267
+ src: imageOptimizationUrl(src, candidates[candidates.length - 1], quality),
268
+ srcSet: candidates.map((candidateWidth) => `${imageOptimizationUrl(src, candidateWidth, quality)} ${candidateWidth}w`).join(", ")
269
+ };
270
+ }
271
+ const widths = getImageWidths(width);
272
+ return {
273
+ src: imageOptimizationUrl(src, widths[widths.length - 1], quality),
274
+ srcSet: widths.map((candidateWidth, index) => `${imageOptimizationUrl(src, candidateWidth, quality)} ${index + 1}x`).join(", ")
275
+ };
245
276
  }
246
277
  const Image = forwardRef(function Image({ src: srcProp, alt, width, height, fill, preload, priority, quality, placeholder, blurDataURL, loader, sizes, className, style, onLoad, onLoadingComplete, onError, unoptimized: _unoptimized, overrideSrc, loading, ...rest }, ref) {
247
278
  const lastLoadedSrcRef = useRef(void 0);
@@ -327,7 +358,7 @@ const Image = forwardRef(function Image({ src: srcProp, alt, width, height, fill
327
358
  lastErrorSrcRef.current = src;
328
359
  markBlurComplete();
329
360
  } : void 0;
330
- if (_unoptimized === true) {
361
+ if (_unoptimized === true || __globallyUnoptimized) {
331
362
  const renderedSrc = overrideSrc || src;
332
363
  const sanitizedBlur = imgBlurDataURL ? sanitizeBlurDataURL(imgBlurDataURL) : void 0;
333
364
  const blurStyle = !blurComplete && placeholder === "blur" && sanitizedBlur ? {
@@ -457,8 +488,9 @@ const Image = forwardRef(function Image({ src: srcProp, alt, width, height, fill
457
488
  }
458
489
  const imgQuality = quality ?? 75;
459
490
  const skipOptimization = isSvgUrl(src) && !__dangerouslyAllowSVG;
460
- const srcSet = imgWidth && !fill && !skipOptimization ? generateSrcSet(src, imgWidth, imgQuality) : imgWidth && !fill ? RESPONSIVE_WIDTHS.filter((w) => w <= imgWidth * 2).map((w) => `${src} ${w}w`).join(", ") || `${src} ${imgWidth}w` : void 0;
461
- const optimizedSrc = skipOptimization ? src : imgWidth ? imageOptimizationUrl(src, imgWidth, imgQuality) : imageOptimizationUrl(src, RESPONSIVE_WIDTHS[0], imgQuality);
491
+ const optimizedAttributes = imgWidth && !fill && !skipOptimization ? generateImageAttributes(src, imgWidth, imgQuality, sizes) : void 0;
492
+ const srcSet = optimizedAttributes ? optimizedAttributes.srcSet : imgWidth && !fill ? RESPONSIVE_WIDTHS.filter((w) => w <= imgWidth * 2).map((w) => `${src} ${w}w`).join(", ") || `${src} ${imgWidth}w` : void 0;
493
+ const optimizedSrc = skipOptimization ? src : optimizedAttributes ? optimizedAttributes.src : imageOptimizationUrl(src, RESPONSIVE_WIDTHS[0], imgQuality);
462
494
  const sanitizedLocalBlur = imgBlurDataURL ? sanitizeBlurDataURL(imgBlurDataURL) : void 0;
463
495
  const blurStyle = !blurComplete && placeholder === "blur" && sanitizedLocalBlur ? {
464
496
  backgroundImage: `url(${sanitizedLocalBlur})`,
@@ -510,7 +542,7 @@ function getImageProps(props) {
510
542
  });
511
543
  const shouldPreload = _preload === true || priority === true;
512
544
  const effectiveLoader = resolveEffectiveLoader(loader);
513
- if (_unoptimized === true) {
545
+ if (_unoptimized === true || __globallyUnoptimized) {
514
546
  const renderedSrc = overrideSrc || src;
515
547
  const sanitizedBlurURL = imgBlurDataURL ? sanitizeBlurDataURL(imgBlurDataURL) : void 0;
516
548
  const blurStyle = placeholder === "blur" && sanitizedBlurURL ? {
@@ -552,8 +584,9 @@ function getImageProps(props) {
552
584
  quality: imgQuality
553
585
  }) : src;
554
586
  const skipOpt = isSvgUrl(resolvedSrc) && !__dangerouslyAllowSVG || blockedInProd || !!effectiveLoader || isRemoteUrl(resolvedSrc);
555
- const optimizedSrc = skipOpt ? resolvedSrc : imgWidth ? imageOptimizationUrl(resolvedSrc, imgWidth, imgQuality) : imageOptimizationUrl(resolvedSrc, RESPONSIVE_WIDTHS[0], imgQuality);
556
- const srcSet = imgWidth && !fill && !isRemoteUrl(resolvedSrc) && !effectiveLoader && !skipOpt ? generateSrcSet(resolvedSrc, imgWidth, imgQuality) : void 0;
587
+ const optimizedAttributes = imgWidth && !fill && !skipOpt ? generateImageAttributes(resolvedSrc, imgWidth, imgQuality, sizes) : null;
588
+ const optimizedSrc = skipOpt ? resolvedSrc : optimizedAttributes ? optimizedAttributes.src : imageOptimizationUrl(resolvedSrc, RESPONSIVE_WIDTHS[0], imgQuality);
589
+ const srcSet = optimizedAttributes?.srcSet;
557
590
  const sanitizedBlurURL = imgBlurDataURL ? sanitizeBlurDataURL(imgBlurDataURL) : void 0;
558
591
  const blurStyle = placeholder === "blur" && sanitizedBlurURL ? {
559
592
  backgroundImage: `url(${sanitizedBlurURL})`,
@@ -1,4 +1,5 @@
1
1
  import { VinextLinkPrefetchRoute } from "../../client/vinext-next-data.js";
2
+ import { getPagesRouterComponentsMap } from "./pages-router-components.js";
2
3
 
3
4
  //#region src/shims/internal/app-route-detection.d.ts
4
5
  declare global {
@@ -6,22 +7,6 @@ declare global {
6
7
  __VINEXT_LINK_PREFETCH_ROUTES__?: VinextLinkPrefetchRoute[];
7
8
  }
8
9
  }
9
- /**
10
- * Pages Router `components` map shape. Next.js types this loosely (route
11
- * pattern → `PrivateRouteInfo`), but for the App Router-detected case it
12
- * stores `{ __appRouter: true }` as a marker (see Next.js source link above).
13
- * Vinext only writes the marker variant; reads are by test code that checks
14
- * for `__appRouter: true`.
15
- */
16
- type PagesRouterComponentsMap = Record<string, {
17
- __appRouter: true;
18
- } | Record<string, unknown>>;
19
- /**
20
- * Get-or-create the Pages Router `components` map. Returns the same object
21
- * on every call so `router.components` and `window.next.router.components`
22
- * have referential identity.
23
- */
24
- declare function getPagesRouterComponentsMap(): PagesRouterComponentsMap;
25
10
  /**
26
11
  * Record `components[pathname] = { __appRouter: true }` on the shared
27
12
  * Pages Router map when the href matches an App Router route. No-op when the
@@ -34,6 +19,6 @@ declare function getPagesRouterComponentsMap(): PagesRouterComponentsMap;
34
19
  * first (e.g. `link.tsx` normalises to match `trailingSlash` config before
35
20
  * calling, while `router.prefetch()` passes the raw user-supplied URL).
36
21
  */
37
- declare function markAppRouteDetectedOnPrefetch(href: string, basePath: string): void;
22
+ declare function markAppRouteDetectedOnPrefetch(href: string, basePath: string): Promise<void>;
38
23
  //#endregion
39
24
  export { getPagesRouterComponentsMap, markAppRouteDetectedOnPrefetch };
@@ -1,22 +1,7 @@
1
1
  import { removeTrailingSlash, stripBasePath } from "../../utils/base-path.js";
2
2
  import { getLocalePathPrefix } from "../../utils/domain-locale.js";
3
- import { resolveHybridClientRouteOwner } from "./hybrid-client-route-owner.js";
3
+ import { getPagesRouterComponentsMap } from "./pages-router-components.js";
4
4
  //#region src/shims/internal/app-route-detection.ts
5
- const _COMPONENTS_KEY = Symbol.for("vinext.pagesRouter.components");
6
- /**
7
- * Get-or-create the Pages Router `components` map. Returns the same object
8
- * on every call so `router.components` and `window.next.router.components`
9
- * have referential identity.
10
- */
11
- function getPagesRouterComponentsMap() {
12
- const globalState = globalThis;
13
- let components = globalState[_COMPONENTS_KEY];
14
- if (!components) {
15
- components = {};
16
- globalState[_COMPONENTS_KEY] = components;
17
- }
18
- return components;
19
- }
20
5
  /**
21
6
  * Resolve a prefetch href to a same-origin pathname (basePath-stripped),
22
7
  * suitable as the key used by Next.js for `router.components[urlPathname]`.
@@ -50,8 +35,10 @@ function resolveSameOriginPathname(href, basePath) {
50
35
  * first (e.g. `link.tsx` normalises to match `trailingSlash` config before
51
36
  * calling, while `router.prefetch()` passes the raw user-supplied URL).
52
37
  */
53
- function markAppRouteDetectedOnPrefetch(href, basePath) {
38
+ async function markAppRouteDetectedOnPrefetch(href, basePath) {
54
39
  if (typeof window === "undefined") return;
40
+ if (!window.__VINEXT_LINK_PREFETCH_ROUTES__?.length) return;
41
+ const { resolveHybridClientRouteOwner } = await import("./hybrid-client-route-owner.js");
55
42
  if (resolveHybridClientRouteOwner(href, basePath) !== "app") return;
56
43
  const rawPathname = resolveSameOriginPathname(href, basePath);
57
44
  if (rawPathname === null) return;
@@ -0,0 +1,23 @@
1
+ import { VinextLinkPrefetchRoute, VinextPagesLinkPrefetchRoute } from "../../client/vinext-next-data.js";
2
+
3
+ //#region src/shims/internal/hybrid-client-route-owner-direct.d.ts
4
+ type HybridClientOwner = "app" | "document" | "pages";
5
+ type HybridClientRouteMatches = {
6
+ appMatch: VinextLinkPrefetchRoute | null;
7
+ pagesMatch: VinextPagesLinkPrefetchRoute | null;
8
+ };
9
+ declare global {
10
+ interface Window {
11
+ __VINEXT_LINK_PREFETCH_ROUTES__?: VinextLinkPrefetchRoute[];
12
+ __VINEXT_PAGES_LINK_PREFETCH_ROUTES__?: VinextPagesLinkPrefetchRoute[];
13
+ }
14
+ }
15
+ declare function resolveSameOriginPathname(href: string, basePath: string): string | null;
16
+ declare function matchDirectHybridClientRoutes(href: string, basePath: string): HybridClientRouteMatches;
17
+ declare function resolveMatchedHybridClientRouteOwner({
18
+ appMatch,
19
+ pagesMatch
20
+ }: HybridClientRouteMatches): HybridClientOwner | null;
21
+ declare function resolveDirectHybridClientRouteOwner(href: string, basePath: string): HybridClientOwner | null;
22
+ //#endregion
23
+ export { HybridClientOwner, matchDirectHybridClientRoutes, resolveDirectHybridClientRouteOwner, resolveMatchedHybridClientRouteOwner, resolveSameOriginPathname };
@@ -0,0 +1,51 @@
1
+ import { compareHybridRoutePatterns } from "../../routing/utils.js";
2
+ import { stripBasePath } from "../../utils/base-path.js";
3
+ import { createRouteTrieCache, matchRouteWithTrie } from "../../routing/route-matching.js";
4
+ import { getLocalePathPrefix } from "../../utils/domain-locale.js";
5
+ //#region src/shims/internal/hybrid-client-route-owner-direct.ts
6
+ const appRouteTrieCache = createRouteTrieCache();
7
+ const pagesRouteTrieCache = createRouteTrieCache();
8
+ function patternFromParts(parts) {
9
+ return "/" + parts.join("/");
10
+ }
11
+ function resolveSameOriginPathname(href, basePath) {
12
+ if (typeof window === "undefined") return null;
13
+ let url;
14
+ try {
15
+ url = new URL(href, window.location.href);
16
+ } catch {
17
+ return null;
18
+ }
19
+ if (url.origin !== window.location.origin) return null;
20
+ const pathname = stripBasePath(url.pathname, basePath);
21
+ const locale = getLocalePathPrefix(pathname, window.__VINEXT_LOCALES__);
22
+ if (!locale) return pathname;
23
+ const localePrefixLength = locale.length + 1;
24
+ return pathname.length === localePrefixLength ? "/" : pathname.slice(localePrefixLength);
25
+ }
26
+ function matchDirectHybridClientRoutes(href, basePath) {
27
+ const pathname = resolveSameOriginPathname(href, basePath);
28
+ if (pathname === null) return {
29
+ appMatch: null,
30
+ pagesMatch: null
31
+ };
32
+ const appRoutes = window.__VINEXT_LINK_PREFETCH_ROUTES__;
33
+ const pagesRoutes = window.__VINEXT_PAGES_LINK_PREFETCH_ROUTES__;
34
+ return {
35
+ appMatch: appRoutes ? matchRouteWithTrie(pathname, appRoutes, appRouteTrieCache)?.route ?? null : null,
36
+ pagesMatch: pagesRoutes ? matchRouteWithTrie(pathname, pagesRoutes, pagesRouteTrieCache)?.route ?? null : null
37
+ };
38
+ }
39
+ function resolveMatchedHybridClientRouteOwner({ appMatch, pagesMatch }) {
40
+ if (appMatch === null && pagesMatch === null) return null;
41
+ if (pagesMatch === null) return appMatch.documentOnly ? "document" : "app";
42
+ if (appMatch === null) return pagesMatch.documentOnly ? "document" : "pages";
43
+ const owner = compareHybridRoutePatterns(patternFromParts(pagesMatch.patternParts), pagesMatch.isDynamic, patternFromParts(appMatch.patternParts), appMatch.isDynamic);
44
+ return (owner === "app" ? appMatch : pagesMatch).documentOnly ? "document" : owner;
45
+ }
46
+ function resolveDirectHybridClientRouteOwner(href, basePath) {
47
+ if (typeof window === "undefined") return null;
48
+ return resolveMatchedHybridClientRouteOwner(matchDirectHybridClientRoutes(href, basePath));
49
+ }
50
+ //#endregion
51
+ export { matchDirectHybridClientRoutes, resolveDirectHybridClientRouteOwner, resolveMatchedHybridClientRouteOwner, resolveSameOriginPathname };
@@ -1,12 +1,9 @@
1
1
  import { NextRewrite } from "../../config/next-config.js";
2
- import { VinextLinkPrefetchRoute, VinextPagesLinkPrefetchRoute } from "../../client/vinext-next-data.js";
2
+ import { HybridClientOwner } from "./hybrid-client-route-owner-direct.js";
3
3
 
4
4
  //#region src/shims/internal/hybrid-client-route-owner.d.ts
5
- type HybridClientOwner = "app" | "document" | "pages";
6
5
  declare global {
7
6
  interface Window {
8
- __VINEXT_LINK_PREFETCH_ROUTES__?: VinextLinkPrefetchRoute[];
9
- __VINEXT_PAGES_LINK_PREFETCH_ROUTES__?: VinextPagesLinkPrefetchRoute[];
10
7
  __VINEXT_CLIENT_REWRITES__?: {
11
8
  afterFiles: NextRewrite[];
12
9
  beforeFiles: NextRewrite[];
@@ -28,4 +25,4 @@ declare global {
28
25
  */
29
26
  declare function resolveHybridClientRouteOwner(href: string, basePath: string): HybridClientOwner | null;
30
27
  //#endregion
31
- export { HybridClientOwner, resolveHybridClientRouteOwner };
28
+ export { type HybridClientOwner, resolveHybridClientRouteOwner };
@@ -1,8 +1,5 @@
1
- import { compareHybridRoutePatterns } from "../../routing/utils.js";
2
- import { stripBasePath } from "../../utils/base-path.js";
3
- import { createRouteTrieCache, matchRouteWithTrie } from "../../routing/route-matching.js";
4
1
  import { isExternalUrl, matchRewrite, parseCookies } from "../../config/config-matchers.js";
5
- import { getLocalePathPrefix } from "../../utils/domain-locale.js";
2
+ import { matchDirectHybridClientRoutes, resolveMatchedHybridClientRouteOwner, resolveSameOriginPathname } from "./hybrid-client-route-owner-direct.js";
6
3
  import { mergeRewriteQuery } from "../../utils/query.js";
7
4
  //#region src/shims/internal/hybrid-client-route-owner.ts
8
5
  /**
@@ -52,45 +49,6 @@ function resolveClientRewrite(href, basePath, rewrites, continueAfterMatch = fal
52
49
  kind: "rewrite"
53
50
  } : null;
54
51
  }
55
- const appRouteTrieCache = createRouteTrieCache();
56
- const pagesRouteTrieCache = createRouteTrieCache();
57
- /**
58
- * Build a `/`-joined pattern from a manifest's `patternParts`. Mirrors the
59
- * server-side route-graph shape (`{ pattern: string }`) so the
60
- * `compareHybridRoutePatterns` segment-rank comparator can score both Pages
61
- * and App patterns. The
62
- * `patternParts` array never includes an empty string for the static `/`
63
- * route (the App catch-all handles the bare path), so the simple join is
64
- * safe for everything the route trie actually matches.
65
- */
66
- function patternFromParts(parts) {
67
- return "/" + parts.join("/");
68
- }
69
- function resolveSameOriginPathname(href, basePath) {
70
- if (typeof window === "undefined") return null;
71
- let url;
72
- try {
73
- url = new URL(href, window.location.href);
74
- } catch {
75
- return null;
76
- }
77
- if (url.origin !== window.location.origin) return null;
78
- const pathname = stripBasePath(url.pathname, basePath);
79
- const locale = getLocalePathPrefix(pathname, window.__VINEXT_LOCALES__);
80
- if (!locale) return pathname;
81
- const localePrefixLength = locale.length + 1;
82
- return pathname.length === localePrefixLength ? "/" : pathname.slice(localePrefixLength);
83
- }
84
- function matchAppRoute(href, basePath, routes) {
85
- const pathname = resolveSameOriginPathname(href, basePath);
86
- if (pathname === null) return null;
87
- return matchRouteWithTrie(pathname, routes, appRouteTrieCache)?.route ?? null;
88
- }
89
- function matchPagesRoute(href, basePath, routes) {
90
- const pathname = resolveSameOriginPathname(href, basePath);
91
- if (pathname === null) return null;
92
- return matchRouteWithTrie(pathname, routes, pagesRouteTrieCache)?.route ?? null;
93
- }
94
52
  /**
95
53
  * Decide which router should own a soft-navigated URL. Returns:
96
54
  * - "app" → the App Router runtime handles the navigation (RSC fetch).
@@ -105,39 +63,30 @@ function matchPagesRoute(href, basePath, routes) {
105
63
  */
106
64
  function resolveHybridClientRouteOwner(href, basePath) {
107
65
  if (typeof window === "undefined") return null;
108
- const appRoutes = window.__VINEXT_LINK_PREFETCH_ROUTES__;
109
- const pagesRoutes = window.__VINEXT_PAGES_LINK_PREFETCH_ROUTES__;
110
66
  const rewrites = window.__VINEXT_CLIENT_REWRITES__;
111
67
  if (rewrites) {
112
68
  const beforeFilesRewrite = resolveClientRewrite(href, basePath, rewrites.beforeFiles, true);
113
69
  if (beforeFilesRewrite?.kind === "document") return "document";
114
70
  if (beforeFilesRewrite?.kind === "rewrite") href = beforeFilesRewrite.href;
115
71
  }
116
- let appMatch = appRoutes ? matchAppRoute(href, basePath, appRoutes) : null;
117
- let pagesMatch = pagesRoutes ? matchPagesRoute(href, basePath, pagesRoutes) : null;
118
- if (rewrites && (appMatch === null || appMatch.isDynamic) && (pagesMatch === null || pagesMatch.isDynamic)) for (const rewrite of rewrites.afterFiles) {
72
+ let matches = matchDirectHybridClientRoutes(href, basePath);
73
+ if (rewrites && (matches.appMatch === null || matches.appMatch.isDynamic) && (matches.pagesMatch === null || matches.pagesMatch.isDynamic)) for (const rewrite of rewrites.afterFiles) {
119
74
  const afterFilesRewrite = resolveClientRewrite(href, basePath, [rewrite]);
120
75
  if (afterFilesRewrite?.kind === "document") return "document";
121
76
  if (afterFilesRewrite?.kind !== "rewrite") continue;
122
77
  href = afterFilesRewrite.href;
123
- appMatch = appRoutes ? matchAppRoute(href, basePath, appRoutes) : null;
124
- pagesMatch = pagesRoutes ? matchPagesRoute(href, basePath, pagesRoutes) : null;
125
- if (appMatch || pagesMatch) break;
78
+ matches = matchDirectHybridClientRoutes(href, basePath);
79
+ if (matches.appMatch || matches.pagesMatch) break;
126
80
  }
127
- if (rewrites && appMatch === null && pagesMatch === null) for (const rewrite of rewrites.fallback) {
81
+ if (rewrites && matches.appMatch === null && matches.pagesMatch === null) for (const rewrite of rewrites.fallback) {
128
82
  const fallbackRewrite = resolveClientRewrite(href, basePath, [rewrite]);
129
83
  if (fallbackRewrite?.kind === "document") return "document";
130
84
  if (fallbackRewrite?.kind !== "rewrite") continue;
131
85
  href = fallbackRewrite.href;
132
- appMatch = appRoutes ? matchAppRoute(href, basePath, appRoutes) : null;
133
- pagesMatch = pagesRoutes ? matchPagesRoute(href, basePath, pagesRoutes) : null;
134
- if (appMatch || pagesMatch) break;
86
+ matches = matchDirectHybridClientRoutes(href, basePath);
87
+ if (matches.appMatch || matches.pagesMatch) break;
135
88
  }
136
- if (appMatch === null && pagesMatch === null) return null;
137
- if (pagesMatch === null) return appMatch.documentOnly ? "document" : "app";
138
- if (appMatch === null) return pagesMatch.documentOnly ? "document" : "pages";
139
- const owner = compareHybridRoutePatterns(patternFromParts(pagesMatch.patternParts), pagesMatch.isDynamic, patternFromParts(appMatch.patternParts), appMatch.isDynamic);
140
- return (owner === "app" ? appMatch : pagesMatch).documentOnly ? "document" : owner;
89
+ return resolveMatchedHybridClientRouteOwner(matches);
141
90
  }
142
91
  //#endregion
143
92
  export { resolveHybridClientRouteOwner };
@@ -0,0 +1,7 @@
1
+ //#region src/shims/internal/pages-router-components.d.ts
2
+ type PagesRouterComponentsMap = Record<string, {
3
+ __appRouter: true;
4
+ } | Record<string, unknown>>;
5
+ declare function getPagesRouterComponentsMap(): PagesRouterComponentsMap;
6
+ //#endregion
7
+ export { PagesRouterComponentsMap, getPagesRouterComponentsMap };
@@ -0,0 +1,13 @@
1
+ //#region src/shims/internal/pages-router-components.ts
2
+ const COMPONENTS_KEY = Symbol.for("vinext.pagesRouter.components");
3
+ function getPagesRouterComponentsMap() {
4
+ const globalState = globalThis;
5
+ let components = globalState[COMPONENTS_KEY];
6
+ if (!components) {
7
+ components = {};
8
+ globalState[COMPONENTS_KEY] = components;
9
+ }
10
+ return components;
11
+ }
12
+ //#endregion
13
+ export { getPagesRouterComponentsMap };