vinext 0.1.7 → 0.2.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 (279) hide show
  1. package/README.md +51 -30
  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/layout-classification.js +1 -1
  5. package/dist/build/nitro-route-rules.js +1 -1
  6. package/dist/build/pages-client-assets-module.d.ts +11 -0
  7. package/dist/build/pages-client-assets-module.js +27 -0
  8. package/dist/build/prerender.d.ts +2 -1
  9. package/dist/build/prerender.js +13 -6
  10. package/dist/build/report.d.ts +13 -2
  11. package/dist/build/report.js +99 -2
  12. package/dist/build/run-prerender.d.ts +7 -0
  13. package/dist/build/run-prerender.js +10 -1
  14. package/dist/build/standalone.js +2 -0
  15. package/dist/cache/cache-adapters-virtual.js +3 -3
  16. package/dist/check.d.ts +18 -0
  17. package/dist/check.js +77 -19
  18. package/dist/cli-args.d.ts +1 -2
  19. package/dist/cli-args.js +1 -1
  20. package/dist/cli-dev-config.d.ts +12 -0
  21. package/dist/cli-dev-config.js +23 -0
  22. package/dist/cli.js +113 -97
  23. package/dist/{server → client}/dev-error-overlay-store.d.ts +1 -1
  24. package/dist/{server → client}/dev-error-overlay-store.js +1 -1
  25. package/dist/{server → client}/dev-error-overlay.d.ts +1 -1
  26. package/dist/{server → client}/dev-error-overlay.js +2 -2
  27. package/dist/client/navigation-runtime.d.ts +2 -0
  28. package/dist/client/navigation-runtime.js +3 -1
  29. package/dist/client/window-next.d.ts +2 -1
  30. package/dist/cloudflare/index.d.ts +2 -2
  31. package/dist/cloudflare/index.js +2 -2
  32. package/dist/config/config-matchers.js +14 -10
  33. package/dist/config/next-config.d.ts +6 -3
  34. package/dist/config/next-config.js +47 -1
  35. package/dist/config/prerender.d.ts +34 -0
  36. package/dist/config/prerender.js +55 -0
  37. package/dist/config/server-external-packages.d.ts +4 -0
  38. package/dist/config/server-external-packages.js +91 -0
  39. package/dist/entries/app-rsc-entry.d.ts +2 -1
  40. package/dist/entries/app-rsc-entry.js +89 -15
  41. package/dist/entries/app-rsc-manifest.js +10 -0
  42. package/dist/entries/pages-client-entry.d.ts +3 -0
  43. package/dist/entries/pages-client-entry.js +16 -1
  44. package/dist/entries/pages-server-entry.js +6 -2
  45. package/dist/image/image-adapters-virtual.d.ts +59 -0
  46. package/dist/image/image-adapters-virtual.js +59 -0
  47. package/dist/index.d.ts +33 -0
  48. package/dist/index.js +211 -118
  49. package/dist/init-cloudflare.d.ts +43 -0
  50. package/dist/init-cloudflare.js +839 -0
  51. package/dist/init-platform.d.ts +40 -0
  52. package/dist/init-platform.js +195 -0
  53. package/dist/init.d.ts +16 -38
  54. package/dist/init.js +208 -97
  55. package/dist/node_modules/.pnpm/am-i-vibing@0.5.0/node_modules/am-i-vibing/dist/detector-1yx2Hoe0.js +294 -0
  56. package/dist/node_modules/.pnpm/process-ancestry@0.1.0/node_modules/process-ancestry/dist/index.js +94 -0
  57. package/dist/{cloudflare → packages/cloudflare}/src/cache/cdn-adapter.runtime.js +1 -1
  58. package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.d.ts +2 -2
  59. package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.js +1 -1
  60. package/dist/packages/cloudflare/src/deploy-config.js +150 -0
  61. package/dist/packages/cloudflare/src/deploy-help.js +55 -0
  62. package/dist/packages/cloudflare/src/deploy.js +276 -0
  63. package/dist/{cloudflare → packages/cloudflare/src}/tpr.d.ts +4 -41
  64. package/dist/{cloudflare → packages/cloudflare/src}/tpr.js +18 -15
  65. package/dist/plugins/ast-scope.d.ts +16 -0
  66. package/dist/plugins/ast-scope.js +62 -0
  67. package/dist/plugins/ast-utils.d.ts +27 -1
  68. package/dist/plugins/ast-utils.js +32 -1
  69. package/dist/plugins/css-module-imports.d.ts +14 -0
  70. package/dist/plugins/css-module-imports.js +59 -0
  71. package/dist/plugins/extensionless-dynamic-import.js +2 -2
  72. package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
  73. package/dist/plugins/ignore-dynamic-requests.js +530 -0
  74. package/dist/plugins/middleware-server-only.d.ts +8 -6
  75. package/dist/plugins/middleware-server-only.js +8 -7
  76. package/dist/plugins/optimize-imports.js +1 -1
  77. package/dist/plugins/typeof-window.d.ts +1 -1
  78. package/dist/plugins/typeof-window.js +28 -56
  79. package/dist/routing/app-route-graph.d.ts +29 -4
  80. package/dist/routing/app-route-graph.js +182 -40
  81. package/dist/routing/app-router.d.ts +5 -0
  82. package/dist/routing/app-router.js +5 -0
  83. package/dist/routing/file-matcher.d.ts +8 -0
  84. package/dist/routing/file-matcher.js +10 -1
  85. package/dist/routing/pages-router.js +2 -2
  86. package/dist/server/api-handler.js +9 -14
  87. package/dist/server/app-browser-action-result.d.ts +4 -1
  88. package/dist/server/app-browser-action-result.js +8 -1
  89. package/dist/server/app-browser-entry.js +194 -190
  90. package/dist/server/app-browser-history-controller.d.ts +2 -1
  91. package/dist/server/app-browser-history-controller.js +6 -2
  92. package/dist/server/app-browser-interception-context.d.ts +1 -0
  93. package/dist/server/app-browser-interception-context.js +4 -2
  94. package/dist/server/app-browser-navigation-controller.d.ts +2 -0
  95. package/dist/server/app-browser-navigation-controller.js +60 -31
  96. package/dist/server/app-browser-server-action-client.d.ts +32 -0
  97. package/dist/server/app-browser-server-action-client.js +127 -0
  98. package/dist/server/app-browser-state.d.ts +11 -1
  99. package/dist/server/app-browser-state.js +25 -8
  100. package/dist/server/app-browser-visible-commit.d.ts +6 -1
  101. package/dist/server/app-browser-visible-commit.js +43 -25
  102. package/dist/server/app-elements-wire.d.ts +9 -2
  103. package/dist/server/app-elements-wire.js +8 -1
  104. package/dist/server/app-elements.d.ts +2 -2
  105. package/dist/server/app-elements.js +4 -3
  106. package/dist/server/app-fallback-renderer.d.ts +5 -2
  107. package/dist/server/app-fallback-renderer.js +15 -7
  108. package/dist/server/app-hydration-cache-publication.d.ts +11 -0
  109. package/dist/server/app-hydration-cache-publication.js +43 -0
  110. package/dist/server/app-middleware.d.ts +4 -3
  111. package/dist/server/app-middleware.js +8 -3
  112. package/dist/server/app-optimistic-routing.js +11 -4
  113. package/dist/server/app-page-boundary-render.d.ts +3 -0
  114. package/dist/server/app-page-boundary-render.js +14 -3
  115. package/dist/server/app-page-cache-finalizer.d.ts +1 -0
  116. package/dist/server/app-page-cache-finalizer.js +10 -3
  117. package/dist/server/app-page-cache-render.d.ts +1 -0
  118. package/dist/server/app-page-cache-render.js +8 -4
  119. package/dist/server/app-page-cache.d.ts +1 -0
  120. package/dist/server/app-page-cache.js +5 -2
  121. package/dist/server/app-page-dispatch.d.ts +33 -4
  122. package/dist/server/app-page-dispatch.js +63 -90
  123. package/dist/server/app-page-element-builder.d.ts +9 -2
  124. package/dist/server/app-page-element-builder.js +114 -23
  125. package/dist/server/app-page-head.d.ts +16 -1
  126. package/dist/server/app-page-head.js +44 -22
  127. package/dist/server/app-page-params.d.ts +2 -1
  128. package/dist/server/app-page-params.js +8 -1
  129. package/dist/server/app-page-ppr-runtime.d.ts +7 -0
  130. package/dist/server/app-page-ppr-runtime.js +70 -0
  131. package/dist/server/app-page-probe.d.ts +1 -0
  132. package/dist/server/app-page-probe.js +6 -1
  133. package/dist/server/app-page-render-identity.d.ts +1 -0
  134. package/dist/server/app-page-render-identity.js +1 -1
  135. package/dist/server/app-page-render.d.ts +4 -1
  136. package/dist/server/app-page-render.js +26 -3
  137. package/dist/server/app-page-request.d.ts +22 -1
  138. package/dist/server/app-page-request.js +92 -15
  139. package/dist/server/app-page-route-wiring.d.ts +14 -2
  140. package/dist/server/app-page-route-wiring.js +61 -25
  141. package/dist/server/app-page-search-params-observation.d.ts +4 -2
  142. package/dist/server/app-page-search-params-observation.js +11 -7
  143. package/dist/server/app-page-segment-state.d.ts +2 -1
  144. package/dist/server/app-page-segment-state.js +3 -1
  145. package/dist/server/app-page-stream.d.ts +5 -0
  146. package/dist/server/app-page-stream.js +3 -1
  147. package/dist/server/app-ppr-fallback-shell-render.d.ts +4 -3
  148. package/dist/server/app-route-handler-dispatch.js +1 -0
  149. package/dist/server/app-route-handler-execution.js +7 -2
  150. package/dist/server/app-route-handler-response.js +1 -0
  151. package/dist/server/app-route-handler-runtime.js +1 -1
  152. package/dist/server/app-route-module-loader.d.ts +2 -0
  153. package/dist/server/app-route-module-loader.js +1 -0
  154. package/dist/server/app-router-entry.js +16 -8
  155. package/dist/server/app-rsc-errors.js +7 -1
  156. package/dist/server/app-rsc-handler.d.ts +3 -1
  157. package/dist/server/app-rsc-handler.js +67 -39
  158. package/dist/server/app-rsc-request-normalization.d.ts +3 -2
  159. package/dist/server/app-rsc-request-normalization.js +6 -3
  160. package/dist/server/app-rsc-route-matching.d.ts +7 -0
  161. package/dist/server/app-rsc-route-matching.js +36 -3
  162. package/dist/server/app-segment-config.d.ts +12 -0
  163. package/dist/server/app-segment-config.js +91 -5
  164. package/dist/server/app-server-action-execution.d.ts +5 -0
  165. package/dist/server/app-server-action-execution.js +94 -33
  166. package/dist/server/app-ssr-entry.d.ts +3 -0
  167. package/dist/server/app-ssr-entry.js +19 -8
  168. package/dist/server/app-ssr-stream.d.ts +7 -3
  169. package/dist/server/app-ssr-stream.js +10 -6
  170. package/dist/server/app-static-generation.d.ts +1 -0
  171. package/dist/server/app-static-generation.js +1 -0
  172. package/dist/server/app-visited-response-cache.d.ts +6 -0
  173. package/dist/server/app-visited-response-cache.js +3 -1
  174. package/dist/server/client-trace-metadata.js +26 -0
  175. package/dist/server/default-global-not-found-module.d.ts +14 -0
  176. package/dist/server/default-global-not-found-module.js +14 -0
  177. package/dist/server/dev-route-files.js +4 -0
  178. package/dist/server/dev-server.js +19 -18
  179. package/dist/server/dev-stack-sourcemap.d.ts +1 -1
  180. package/dist/server/dev-stack-sourcemap.js +1 -1
  181. package/dist/server/fetch-handler.d.ts +2 -0
  182. package/dist/server/fetch-handler.js +18 -0
  183. package/dist/server/headers.d.ts +5 -15
  184. package/dist/server/headers.js +4 -15
  185. package/dist/server/image-optimization.d.ts +51 -1
  186. package/dist/server/image-optimization.js +52 -2
  187. package/dist/server/implicit-tags.js +1 -1
  188. package/dist/server/isr-cache.d.ts +1 -1
  189. package/dist/server/isr-cache.js +2 -2
  190. package/dist/server/metadata-routes.d.ts +3 -1
  191. package/dist/server/metadata-routes.js +12 -2
  192. package/dist/server/middleware-runtime.js +6 -1
  193. package/dist/server/navigation-planner.d.ts +1 -0
  194. package/dist/server/navigation-planner.js +14 -3
  195. package/dist/server/pages-api-route.js +2 -2
  196. package/dist/server/pages-asset-tags.d.ts +4 -6
  197. package/dist/server/pages-asset-tags.js +12 -12
  198. package/dist/server/pages-client-assets.d.ts +12 -0
  199. package/dist/server/pages-client-assets.js +10 -0
  200. package/dist/server/pages-node-compat.d.ts +8 -1
  201. package/dist/server/pages-node-compat.js +32 -4
  202. package/dist/server/pages-page-data.d.ts +24 -1
  203. package/dist/server/pages-page-data.js +45 -24
  204. package/dist/server/pages-page-handler.d.ts +2 -1
  205. package/dist/server/pages-page-handler.js +19 -12
  206. package/dist/server/pages-page-response.d.ts +7 -0
  207. package/dist/server/pages-page-response.js +4 -1
  208. package/dist/server/pages-request-pipeline.d.ts +2 -0
  209. package/dist/server/pages-request-pipeline.js +25 -1
  210. package/dist/server/pages-router-entry.d.ts +30 -0
  211. package/dist/server/pages-router-entry.js +108 -0
  212. package/dist/server/prerender-manifest.d.ts +3 -1
  213. package/dist/server/prerender-route-params.js +1 -1
  214. package/dist/server/prod-server.d.ts +1 -1
  215. package/dist/server/prod-server.js +48 -26
  216. package/dist/server/request-pipeline.js +1 -0
  217. package/dist/server/seed-cache.js +4 -4
  218. package/dist/server/worker-utils.d.ts +2 -1
  219. package/dist/server/worker-utils.js +7 -1
  220. package/dist/shims/app-router-scroll-state.d.ts +1 -0
  221. package/dist/shims/app-router-scroll-state.js +1 -0
  222. package/dist/shims/app-router-scroll.js +2 -1
  223. package/dist/shims/cache.js +19 -15
  224. package/dist/shims/cdn-cache.js +1 -1
  225. package/dist/shims/dynamic-preload-chunks.js +2 -1
  226. package/dist/shims/error-boundary.d.ts +19 -1
  227. package/dist/shims/error-boundary.js +11 -1
  228. package/dist/shims/form.d.ts +3 -1
  229. package/dist/shims/form.js +37 -43
  230. package/dist/shims/headers.d.ts +9 -1
  231. package/dist/shims/headers.js +31 -6
  232. package/dist/shims/image.js +75 -14
  233. package/dist/shims/internal/app-route-detection.d.ts +2 -17
  234. package/dist/shims/internal/app-route-detection.js +4 -17
  235. package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +23 -0
  236. package/dist/shims/internal/hybrid-client-route-owner-direct.js +51 -0
  237. package/dist/shims/internal/hybrid-client-route-owner.d.ts +2 -15
  238. package/dist/shims/internal/hybrid-client-route-owner.js +9 -60
  239. package/dist/shims/internal/pages-data-fetch-dedup.d.ts +9 -5
  240. package/dist/shims/internal/pages-data-fetch-dedup.js +73 -14
  241. package/dist/shims/internal/pages-data-target.d.ts +10 -9
  242. package/dist/shims/internal/pages-data-target.js +91 -12
  243. package/dist/shims/internal/pages-router-components.d.ts +7 -0
  244. package/dist/shims/internal/pages-router-components.js +13 -0
  245. package/dist/shims/layout-segment-context.d.ts +4 -1
  246. package/dist/shims/layout-segment-context.js +18 -4
  247. package/dist/shims/link.js +70 -37
  248. package/dist/shims/metadata.d.ts +3 -2
  249. package/dist/shims/metadata.js +8 -4
  250. package/dist/shims/navigation.d.ts +5 -1
  251. package/dist/shims/navigation.js +45 -10
  252. package/dist/shims/navigation.react-server.js +1 -1
  253. package/dist/shims/root-params.d.ts +15 -1
  254. package/dist/shims/root-params.js +21 -1
  255. package/dist/shims/router.d.ts +5 -7
  256. package/dist/shims/router.js +374 -94
  257. package/dist/shims/server.js +3 -2
  258. package/dist/shims/slot.js +3 -6
  259. package/dist/typegen.js +6 -5
  260. package/dist/utils/client-runtime-metadata.d.ts +2 -18
  261. package/dist/utils/client-runtime-metadata.js +31 -22
  262. package/dist/utils/dev-stack-sourcemap-endpoint.d.ts +4 -0
  263. package/dist/{server → utils}/dev-stack-sourcemap-endpoint.js +1 -1
  264. package/dist/utils/domain-locale.d.ts +6 -3
  265. package/dist/{server → utils}/middleware-request-headers.d.ts +1 -1
  266. package/dist/{server → utils}/middleware-request-headers.js +2 -2
  267. package/dist/utils/path.d.ts +2 -1
  268. package/dist/utils/path.js +1 -1
  269. package/dist/utils/project.d.ts +52 -2
  270. package/dist/utils/project.js +230 -5
  271. package/dist/utils/protocol-headers.d.ts +17 -0
  272. package/dist/utils/protocol-headers.js +17 -0
  273. package/dist/utils/react-version.d.ts +4 -0
  274. package/dist/utils/react-version.js +44 -0
  275. package/package.json +53 -4
  276. package/dist/deploy.d.ts +0 -190
  277. package/dist/deploy.js +0 -1033
  278. package/dist/server/dev-stack-sourcemap-endpoint.d.ts +0 -4
  279. /package/dist/{cloudflare → packages/cloudflare}/src/utils/cache-control-metadata.js +0 -0
@@ -14,6 +14,7 @@ function beginAppRouterScrollIntent(hash) {
14
14
  const intent = {
15
15
  commitId: null,
16
16
  hash,
17
+ headElements: typeof document === "undefined" ? null : new Set(document.head?.children ?? []),
17
18
  id: store.nextId,
18
19
  targetHoistedInHead: false
19
20
  };
@@ -99,7 +99,8 @@ var AppRouterScrollTargetInner = class extends React$1.Component {
99
99
  else node = null;
100
100
  if (node === null) {
101
101
  node = findDOMNode(this);
102
- if (node !== null && isInDocumentHead(node)) {
102
+ const headElement = node instanceof Element ? node : node?.parentElement;
103
+ if (node !== null && headElement != null && isInDocumentHead(node) && !intent.headElements?.has(headElement)) {
103
104
  markAppRouterScrollIntentHeadHoisted(intent, this.props.commitId);
104
105
  return;
105
106
  }
@@ -5,7 +5,7 @@ import { MemoryCacheHandler, NoOpCacheHandler, configureMemoryCacheHandler, getC
5
5
  import { getCdnCacheAdapter } from "./cdn-cache.js";
6
6
  import { fnv1a64 } from "../utils/hash.js";
7
7
  import { makeHangingPromise } from "./internal/make-hanging-promise.js";
8
- import { getHeadersAccessPhase, markDynamicUsage } from "./headers.js";
8
+ import { getHeadersAccessPhase, isDraftModeEnabled, markDynamicUsage } from "./headers.js";
9
9
  import { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, _consumeRequestScopedCacheLife, _initRequestScopedCacheState, _peekRequestScopedCacheLife, _peekUnstableCacheObservations, _registerCacheContextAccessor, _runWithCacheState, _setRequestScopedCacheLife, cacheLifeProfiles, getAndClearActionRevalidationKind, getRegisteredCacheContext, markActionRevalidation, recordUnstableCacheObservation, shouldServeStaleUnstableCacheEntry } from "./cache-request-state.js";
10
10
  import { encodeCacheTag, encodeCacheTags } from "../utils/encode-cache-tag.js";
11
11
  import { workUnitAsyncStorage } from "./internal/work-unit-async-storage.js";
@@ -110,10 +110,10 @@ function refresh() {
110
110
  *
111
111
  * @see https://nextjs.org/docs/app/api-reference/functions/updateTag
112
112
  */
113
- async function updateTag(tag) {
113
+ function updateTag(tag) {
114
114
  if (getHeadersAccessPhase() !== "action") throw new Error("updateTag can only be called from within a Server Action. To invalidate cache tags in Route Handlers or other contexts, use revalidateTag instead. See more info here: https://nextjs.org/docs/app/api-reference/functions/updateTag");
115
115
  markActionRevalidation(1);
116
- await _invalidateEncodedTag(encodeCacheTag(tag));
116
+ return _invalidateEncodedTag(encodeCacheTag(tag));
117
117
  }
118
118
  /**
119
119
  * Opt out of static rendering and indicate a particular component should not be cached.
@@ -380,19 +380,23 @@ function unstable_cache(fn, keyParts, options) {
380
380
  tagCount: tags.length,
381
381
  tagHash: tags.length > 0 ? fnv1a64(JSON.stringify(tags)) : null
382
382
  });
383
- const existing = await getDataCacheHandler().get(cacheKey, {
384
- kind: "FETCH",
385
- tags
386
- });
387
- if (existing?.value && existing.value.kind === "FETCH") {
388
- const cached = tryDeserializeUnstableCacheResult(existing.value.data.body);
389
- if (cached.ok) if (existing.cacheState === "stale") {
390
- if (shouldServeStaleUnstableCacheEntry()) {
391
- scheduleUnstableCacheBackgroundRevalidation(cacheKey, () => refreshUnstableCacheResult(fn, args, cacheKey, tags, revalidateSeconds));
392
- return cached.value;
393
- }
394
- } else return cached.value;
383
+ const isDraftMode = isDraftModeEnabled();
384
+ if (!isDraftMode) {
385
+ const existing = await getDataCacheHandler().get(cacheKey, {
386
+ kind: "FETCH",
387
+ tags
388
+ });
389
+ if (existing?.value && existing.value.kind === "FETCH") {
390
+ const cached = tryDeserializeUnstableCacheResult(existing.value.data.body);
391
+ if (cached.ok) if (existing.cacheState === "stale") {
392
+ if (shouldServeStaleUnstableCacheEntry()) {
393
+ scheduleUnstableCacheBackgroundRevalidation(cacheKey, () => refreshUnstableCacheResult(fn, args, cacheKey, tags, revalidateSeconds));
394
+ return cached.value;
395
+ }
396
+ } else return cached.value;
397
+ }
395
398
  }
399
+ if (isDraftMode) return await _unstableCacheAls.run(true, () => fn(...args));
396
400
  return await refreshUnstableCacheResult(fn, args, cacheKey, tags, revalidateSeconds);
397
401
  };
398
402
  return cachedFn;
@@ -1,6 +1,6 @@
1
1
  import { getRequestExecutionContext } from "./request-context.js";
2
2
  import { getDataCacheHandler } from "./cache-handler.js";
3
- import { CloudflareCdnCacheAdapter } from "../cloudflare/src/cache/cdn-adapter.runtime.js";
3
+ import { CloudflareCdnCacheAdapter } from "../packages/cloudflare/src/cache/cdn-adapter.runtime.js";
4
4
  //#region src/shims/cdn-cache.ts
5
5
  /**
6
6
  * CDN cache adapter — owns the *page-level ISR serving strategy*.
@@ -3,6 +3,7 @@ import { appendAssetDeploymentIdQuery } from "../utils/deployment-id.js";
3
3
  import { useScriptNonce } from "./script-nonce-context.js";
4
4
  import React from "react";
5
5
  import * as ReactDOM from "react-dom";
6
+ import { getPagesClientAssets } from "vinext/server/pages-client-assets";
6
7
  //#region src/shims/dynamic-preload-chunks.tsx
7
8
  /**
8
9
  * Preload links for rendered next/dynamic() boundaries.
@@ -34,7 +35,7 @@ function dynamicPreloadHref(file) {
34
35
  }
35
36
  function resolveDynamicPreloadFiles(moduleIds) {
36
37
  if (!moduleIds || moduleIds.length === 0) return [];
37
- const preloadMap = globalThis.__VINEXT_DYNAMIC_PRELOADS__;
38
+ const preloadMap = getPagesClientAssets().dynamicPreloads;
38
39
  if (!preloadMap) return [];
39
40
  const files = [];
40
41
  const seen = /* @__PURE__ */ new Set();
@@ -9,6 +9,24 @@ type ErrorBoundaryProps = {
9
9
  children: React.ReactNode;
10
10
  resetKey?: string | null;
11
11
  };
12
+ type SerializedBoundaryError = {
13
+ digest?: string;
14
+ message: string;
15
+ name?: string;
16
+ stack?: string;
17
+ };
18
+ declare function SerializedErrorBoundary({
19
+ fallback: Fallback,
20
+ error
21
+ }: {
22
+ fallback: React.ComponentType<{
23
+ error: Error & {
24
+ digest?: string;
25
+ };
26
+ reset: () => void;
27
+ }>;
28
+ error: SerializedBoundaryError;
29
+ }): React.JSX.Element;
12
30
  type CapturedError = {
13
31
  thrownValue: unknown;
14
32
  };
@@ -152,4 +170,4 @@ declare class DevRecoveryBoundary extends React.Component<DevRecoveryBoundaryPro
152
170
  render(): React.ReactNode;
153
171
  }
154
172
  //#endregion
155
- export { DevRecoveryBoundary, DevRecoveryBoundaryProps, ErrorBoundary, ErrorBoundaryInner, ErrorBoundaryProps, ErrorBoundaryState, ForbiddenBoundary, ForbiddenBoundaryInner, GlobalErrorBoundary, NotFoundBoundary, RedirectBoundary, RedirectErrorBoundary, UnauthorizedBoundary, UnauthorizedBoundaryInner };
173
+ export { DevRecoveryBoundary, DevRecoveryBoundaryProps, ErrorBoundary, ErrorBoundaryInner, ErrorBoundaryProps, ErrorBoundaryState, ForbiddenBoundary, ForbiddenBoundaryInner, GlobalErrorBoundary, NotFoundBoundary, RedirectBoundary, RedirectErrorBoundary, SerializedBoundaryError, SerializedErrorBoundary, UnauthorizedBoundary, UnauthorizedBoundaryInner };
@@ -9,6 +9,16 @@ import { isNavigationSignalError } from "../utils/navigation-signal.js";
9
9
  import React from "react";
10
10
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
11
11
  //#region src/shims/error-boundary.tsx
12
+ function SerializedErrorBoundary({ fallback: Fallback, error }) {
13
+ return /* @__PURE__ */ jsx(Fallback, {
14
+ error: Object.assign(new Error(error.message), {
15
+ digest: error.digest,
16
+ name: error.name ?? "Error",
17
+ stack: error.stack
18
+ }),
19
+ reset: () => globalThis.location?.reload()
20
+ });
21
+ }
12
22
  function normalizeBoundaryResetKey(resetKey) {
13
23
  return resetKey === void 0 || resetKey === null || resetKey === "" ? null : resetKey;
14
24
  }
@@ -339,4 +349,4 @@ var DevRecoveryBoundary = class extends React.Component {
339
349
  }
340
350
  };
341
351
  //#endregion
342
- export { DevRecoveryBoundary, ErrorBoundary, ErrorBoundaryInner, ForbiddenBoundary, ForbiddenBoundaryInner, GlobalErrorBoundary, NotFoundBoundary, RedirectBoundary, RedirectErrorBoundary, UnauthorizedBoundary, UnauthorizedBoundaryInner };
352
+ export { DevRecoveryBoundary, ErrorBoundary, ErrorBoundaryInner, ForbiddenBoundary, ForbiddenBoundaryInner, GlobalErrorBoundary, NotFoundBoundary, RedirectBoundary, RedirectErrorBoundary, SerializedErrorBoundary, UnauthorizedBoundary, UnauthorizedBoundaryInner };
@@ -1,6 +1,8 @@
1
1
  import { FormHTMLAttributes, useActionState } from "react";
2
2
 
3
3
  //#region src/shims/form.d.ts
4
+ type FormSubmitter = HTMLButtonElement | HTMLInputElement;
5
+ declare function createFormSubmitDestinationUrl(action: string, form: HTMLFormElement, submitter: FormSubmitter | null): string;
4
6
  declare const Form: import("react").ForwardRefExoticComponent<{
5
7
  /** Target URL for GET forms, or server action for POST forms */action: string | ((formData: FormData) => void | Promise<void>); /** Replace instead of push in history (default: false) */
6
8
  replace?: boolean; /** Scroll to top after navigation (default: true) */
@@ -16,4 +18,4 @@ declare const Form: import("react").ForwardRefExoticComponent<{
16
18
  prefetch?: false | null;
17
19
  } & Omit<FormHTMLAttributes<HTMLFormElement>, "method" | "encType" | "target"> & import("react").RefAttributes<HTMLFormElement>>;
18
20
  //#endregion
19
- export { Form as default, useActionState };
21
+ export { createFormSubmitDestinationUrl, Form as default, useActionState };
@@ -1,9 +1,11 @@
1
1
  "use client";
2
2
  import { VINEXT_MOUNTED_SLOTS_HEADER } from "../server/headers.js";
3
- import { isDangerousScheme } from "./url-safety.js";
3
+ import { assertSafeNavigationUrl } from "./url-safety.js";
4
4
  import { AppElementsWire } from "../server/app-elements-wire.js";
5
+ import { APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL } from "../server/app-rsc-render-mode.js";
5
6
  import "../server/app-elements.js";
6
- import { toSameOriginPath, withBasePath } from "./url-utils.js";
7
+ import { withBasePath } from "./url-utils.js";
8
+ import { isBotUserAgent } from "../utils/html-limited-bots.js";
7
9
  import { createRscRequestHeaders, createRscRequestUrl } from "../server/app-rsc-cache-busting.js";
8
10
  import { hasAppNavigationRuntime } from "../client/navigation-runtime.js";
9
11
  import { getMountedSlotsHeader, getPrefetchInterceptionContext, getPrefetchedUrls, hasPrefetchCacheEntryForNavigation, navigateClientSide, prefetchRscResponse } from "./navigation.js";
@@ -37,18 +39,13 @@ const DISALLOWED_FORM_PROPS = [
37
39
  const SUPPORTED_FORM_ENCTYPE = "application/x-www-form-urlencoded";
38
40
  const SUPPORTED_FORM_METHOD = "GET";
39
41
  const SUPPORTED_FORM_TARGET = "_self";
40
- function isSafeAction(action) {
41
- if (isDangerousScheme(action)) return false;
42
- if (action.startsWith("//")) return false;
43
- if (/^https?:\/\//i.test(action)) {
44
- if (typeof window !== "undefined") try {
45
- return new URL(action).origin === window.location.origin;
46
- } catch {
47
- return false;
48
- }
42
+ function isPrefetchableAction(action) {
43
+ try {
44
+ const actionUrl = new URL(action, window.location.href);
45
+ return (actionUrl.protocol === "http:" || actionUrl.protocol === "https:") && actionUrl.origin === window.location.origin;
46
+ } catch {
49
47
  return false;
50
48
  }
51
- return true;
52
49
  }
53
50
  function getSubmitter(nativeEvent) {
54
51
  const submitter = nativeEvent && typeof nativeEvent === "object" && "submitter" in nativeEvent && nativeEvent.submitter instanceof Element ? nativeEvent.submitter : null;
@@ -103,7 +100,7 @@ function createFormSubmitDestinationUrl(action, form, submitter) {
103
100
  if (process.env.NODE_ENV !== "production") console.warn("<Form> only supports file inputs if `action` is a function. File inputs cannot be used if `action` is a string, because files cannot be encoded as search params.");
104
101
  targetUrl.searchParams.append(name, value.name);
105
102
  } else targetUrl.searchParams.append(name, value);
106
- return toSameOriginPath(targetUrl.href) ?? targetUrl.href;
103
+ return targetUrl.href;
107
104
  }
108
105
  function buildFormData(form, submitter) {
109
106
  if (!submitter) return new FormData(form);
@@ -137,7 +134,7 @@ const Form = forwardRef(function Form(props, ref) {
137
134
  useEffect(() => {
138
135
  if (typeof action !== "string") return;
139
136
  if (prefetch === false || process.env.NODE_ENV !== "production") return;
140
- if (!isSafeAction(action)) return;
137
+ if (!isPrefetchableAction(actionHref)) return;
141
138
  if (!hasAppNavigationRuntime()) return;
142
139
  const node = formRef.current;
143
140
  if (!node) return;
@@ -145,9 +142,13 @@ const Form = forwardRef(function Form(props, ref) {
145
142
  const observer = new IntersectionObserver((entries) => {
146
143
  for (const entry of entries) if (entry.isIntersecting || entry.intersectionRatio > 0) {
147
144
  (async () => {
145
+ if (isBotUserAgent(window.navigator?.userAgent ?? "")) return;
148
146
  const interceptionContext = getPrefetchInterceptionContext(actionHref);
149
147
  const mountedSlotsHeader = getMountedSlotsHeader();
150
- const headers = createRscRequestHeaders({ interceptionContext });
148
+ const headers = createRscRequestHeaders({
149
+ interceptionContext,
150
+ renderMode: APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL
151
+ });
151
152
  if (mountedSlotsHeader) headers.set(VINEXT_MOUNTED_SLOTS_HEADER, mountedSlotsHeader);
152
153
  const rscUrl = await createRscRequestUrl(actionHref, headers);
153
154
  const cacheKey = AppElementsWire.encodeCacheKey(rscUrl, interceptionContext);
@@ -161,8 +162,8 @@ const Form = forwardRef(function Form(props, ref) {
161
162
  priority: "low",
162
163
  purpose: "prefetch"
163
164
  }), interceptionContext, mountedSlotsHeader, void 0, {
164
- cacheForNavigation: true,
165
- optimisticRouteShell: false
165
+ cacheForNavigation: false,
166
+ optimisticRouteShell: true
166
167
  });
167
168
  })();
168
169
  observer.unobserve(node);
@@ -183,15 +184,7 @@ const Form = forwardRef(function Form(props, ref) {
183
184
  onSubmit,
184
185
  ...cleanRest
185
186
  });
186
- if (!isSafeAction(action)) {
187
- if (process.env.NODE_ENV !== "production") console.warn(`<Form> blocked unsafe action: ${action}`);
188
- return /* @__PURE__ */ jsx("form", {
189
- ref: setRefs,
190
- onSubmit,
191
- ...cleanRest
192
- });
193
- }
194
- async function handleSubmit(e) {
187
+ function handleSubmit(e) {
195
188
  if (onSubmit) {
196
189
  onSubmit(e);
197
190
  if (e.defaultPrevented) return;
@@ -204,23 +197,24 @@ const Form = forwardRef(function Form(props, ref) {
204
197
  }
205
198
  const effectiveAction = getEffectiveAction(submitter, actionHref);
206
199
  if (process.env.NODE_ENV !== "production" && submitter?.getAttribute("formaction") !== null) checkFormActionUrl(effectiveAction, "formAction");
207
- if (!isSafeAction(effectiveAction)) {
208
- if (process.env.NODE_ENV !== "production") console.warn(`<Form> blocked unsafe action: ${effectiveAction}`);
209
- e.preventDefault();
210
- return;
211
- }
212
- e.preventDefault();
213
200
  const url = createFormSubmitDestinationUrl(effectiveAction, e.currentTarget, submitter);
214
- if (hasAppNavigationRuntime()) await navigateClientSide(url, replace ? "replace" : "push", scroll);
215
- else try {
216
- const Router = (await import("./router.js")).default;
217
- if (replace) await Router.replace(url, void 0, { scroll });
218
- else await Router.push(url, void 0, { scroll });
219
- } catch {
220
- if (replace) window.history.replaceState({}, "", url);
221
- else window.history.pushState({}, "", url);
222
- window.dispatchEvent(new PopStateEvent("popstate"));
223
- if (scroll) window.scrollTo(0, 0);
201
+ e.preventDefault();
202
+ if (hasAppNavigationRuntime()) {
203
+ assertSafeNavigationUrl(url);
204
+ navigateClientSide(url, replace ? "replace" : "push", scroll);
205
+ } else {
206
+ assertSafeNavigationUrl(url);
207
+ (async () => {
208
+ let Router;
209
+ try {
210
+ Router = (await import("./router.js")).default;
211
+ if (replace) await Router.replace(url, void 0, { scroll });
212
+ else await Router.push(url, void 0, { scroll });
213
+ } catch {
214
+ if (replace) window.location.replace(url);
215
+ else window.location.assign(url);
216
+ }
217
+ })();
224
218
  }
225
219
  }
226
220
  return /* @__PURE__ */ jsx("form", {
@@ -233,4 +227,4 @@ const Form = forwardRef(function Form(props, ref) {
233
227
  });
234
228
  });
235
229
  //#endregion
236
- export { Form as default, useActionState };
230
+ export { createFormSubmitDestinationUrl, Form as default, useActionState };
@@ -5,6 +5,7 @@ type HeadersContext = {
5
5
  headers: Headers;
6
6
  cookies: Map<string, string>;
7
7
  accessError?: Error;
8
+ draftModeEnabled?: boolean;
8
9
  forceStatic?: boolean;
9
10
  mutableCookies?: RequestCookies;
10
11
  readonlyCookies?: RequestCookies;
@@ -47,6 +48,7 @@ type ConnectionProbeResult<T> = {
47
48
  */
48
49
  declare function markDynamicUsage(): void;
49
50
  declare function markRenderRequestApiUsage(kind: RenderRequestApiKind): void;
51
+ declare function throwIfStaticGenerationAccessError(): void;
50
52
  declare function runWithConnectionProbe<T>(fn: () => T | Promise<T>): Promise<ConnectionProbeResult<T>>;
51
53
  declare function suspendConnectionProbe(): Promise<never> | null;
52
54
  declare function peekRenderRequestApiUsage(): RenderRequestApiKind[];
@@ -177,6 +179,12 @@ declare function getAndClearPendingCookies(): string[];
177
179
  */
178
180
  declare function getDraftModeCookieHeader(): string | null;
179
181
  declare function isDraftModeRequest(request: Request, draftModeSecret: string): boolean;
182
+ /**
183
+ * Read the active request's draft-mode state without recording request API usage.
184
+ * Internal cache implementations use this to bypass persistent reads and writes,
185
+ * matching Next.js's request-level `workStore.isDraftMode` guard.
186
+ */
187
+ declare function isDraftModeEnabled(): boolean;
180
188
  type DraftModeResult = {
181
189
  readonly isEnabled: boolean;
182
190
  enable(): void;
@@ -250,4 +258,4 @@ declare class RequestCookies {
250
258
  toString(): string;
251
259
  }
252
260
  //#endregion
253
- export { HeadersAccessPhase, HeadersContext, type RequestCookies, VinextHeadersShimState, applyMiddlewareRequestHeaders, consumeDynamicUsage, consumeInvalidDynamicUsageError, consumeRenderRequestApiUsage, cookies, draftMode, getAndClearPendingCookies, getDraftModeCookieHeader, getHeadersAccessPhase, getHeadersContext, headers, headersContextFromRequest, isDraftModeRequest, markDynamicUsage, markRenderRequestApiUsage, peekDynamicUsage, peekRenderRequestApiUsage, runWithConnectionProbe, runWithHeadersContext, setHeadersAccessPhase, setHeadersContext, suspendConnectionProbe, throwIfInsideCacheScope };
261
+ export { HeadersAccessPhase, HeadersContext, type RequestCookies, VinextHeadersShimState, 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 };
@@ -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 };
@@ -1,4 +1,5 @@
1
1
  "use client";
2
+ import { getDeploymentId } from "../utils/deployment-id.js";
2
3
  import { useMergedRef } from "./use-merged-ref.js";
3
4
  import { hasRemoteMatch, isPrivateIp } from "./image-config.js";
4
5
  import { forwardRef, useEffect, useLayoutEffect, useRef, useState } from "react";
@@ -54,6 +55,22 @@ const __imageDeviceSizes = (() => {
54
55
  ];
55
56
  }
56
57
  })();
58
+ const __imageSizes = (() => {
59
+ try {
60
+ return JSON.parse(process.env.__VINEXT_IMAGE_SIZES ?? "[16,32,48,64,96,128,256,384]");
61
+ } catch {
62
+ return [
63
+ 16,
64
+ 32,
65
+ 48,
66
+ 64,
67
+ 96,
68
+ 128,
69
+ 256,
70
+ 384
71
+ ];
72
+ }
73
+ })();
57
74
  /**
58
75
  * Whether dangerouslyAllowSVG is enabled in next.config.js.
59
76
  * When false (default), .svg sources auto-skip the optimization endpoint
@@ -68,6 +85,7 @@ const __dangerouslyAllowSVG = process.env.__VINEXT_IMAGE_DANGEROUSLY_ALLOW_SVG =
68
85
  * are blocked to mitigate SSRF risk.
69
86
  */
70
87
  const __dangerouslyAllowLocalIP = process.env.__VINEXT_IMAGE_DANGEROUSLY_ALLOW_LOCAL_IP === "true";
88
+ const __globallyUnoptimized = process.env.__VINEXT_IMAGE_UNOPTIMIZED === "true";
71
89
  /**
72
90
  * Validate that a remote URL is allowed by the configured remote patterns.
73
91
  * Returns true if the URL is allowed, false otherwise.
@@ -210,7 +228,33 @@ function resolveImageSource(v) {
210
228
  * These are the breakpoints used for srcSet generation.
211
229
  * Configurable via `images.deviceSizes` in next.config.js.
212
230
  */
213
- const RESPONSIVE_WIDTHS = __imageDeviceSizes;
231
+ const RESPONSIVE_WIDTHS = [...__imageDeviceSizes].sort((left, right) => left - right);
232
+ const ALL_IMAGE_WIDTHS = [...RESPONSIVE_WIDTHS, ...__imageSizes].sort((left, right) => left - right);
233
+ function extractLocalDeploymentId(src) {
234
+ let deploymentId = getDeploymentId();
235
+ if (!src.startsWith("/") || src.startsWith("//")) return {
236
+ src,
237
+ deploymentId
238
+ };
239
+ const queryIndex = src.indexOf("?");
240
+ if (queryIndex === -1) return {
241
+ src,
242
+ deploymentId
243
+ };
244
+ const params = new URLSearchParams(src.slice(queryIndex + 1));
245
+ const sourceDeploymentId = params.get("dpl");
246
+ if (!sourceDeploymentId) return {
247
+ src,
248
+ deploymentId
249
+ };
250
+ deploymentId = sourceDeploymentId;
251
+ params.delete("dpl");
252
+ const remainingQuery = params.toString();
253
+ return {
254
+ src: src.slice(0, queryIndex) + (remainingQuery ? `?${remainingQuery}` : ""),
255
+ deploymentId
256
+ };
257
+ }
214
258
  /**
215
259
  * Build a `/_next/image` optimization URL.
216
260
  *
@@ -219,7 +263,9 @@ const RESPONSIVE_WIDTHS = __imageDeviceSizes;
219
263
  * server handles it as a passthrough (serves the original file).
220
264
  */
221
265
  function imageOptimizationUrl(src, width, quality = 75) {
222
- return `/_next/image?url=${encodeURIComponent(src)}&w=${width}&q=${quality}`;
266
+ const source = extractLocalDeploymentId(src);
267
+ const deploymentQuery = source.src.startsWith("/") && source.deploymentId ? `&dpl=${source.deploymentId}` : "";
268
+ return `/_next/image?url=${encodeURIComponent(source.src)}&w=${width}&q=${quality}${deploymentQuery}`;
223
269
  }
224
270
  function preloadImageResource(input) {
225
271
  if (!input.shouldPreload) return;
@@ -235,13 +281,26 @@ function preloadImageResource(input) {
235
281
  * Generate a srcSet string for responsive images.
236
282
  *
237
283
  * 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.
284
+ * server can resize and transcode the image.
240
285
  */
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(", ");
286
+ function getImageWidths(width) {
287
+ return [...new Set([width, width * 2].map((targetWidth) => ALL_IMAGE_WIDTHS.find((configuredWidth) => configuredWidth >= targetWidth) ?? ALL_IMAGE_WIDTHS[ALL_IMAGE_WIDTHS.length - 1]))];
288
+ }
289
+ function generateImageAttributes(src, width, quality = 75, sizes) {
290
+ if (sizes) {
291
+ const viewportPercentages = Array.from(sizes.matchAll(/(^|\s)(1?\d?\d)vw/g), (match) => Number.parseInt(match[2], 10));
292
+ const minimumWidth = viewportPercentages.length > 0 ? RESPONSIVE_WIDTHS[0] * (Math.min(...viewportPercentages) * .01) : 0;
293
+ const candidates = ALL_IMAGE_WIDTHS.filter((candidateWidth) => candidateWidth >= minimumWidth);
294
+ return {
295
+ src: imageOptimizationUrl(src, candidates[candidates.length - 1], quality),
296
+ srcSet: candidates.map((candidateWidth) => `${imageOptimizationUrl(src, candidateWidth, quality)} ${candidateWidth}w`).join(", ")
297
+ };
298
+ }
299
+ const widths = getImageWidths(width);
300
+ return {
301
+ src: imageOptimizationUrl(src, widths[widths.length - 1], quality),
302
+ srcSet: widths.map((candidateWidth, index) => `${imageOptimizationUrl(src, candidateWidth, quality)} ${index + 1}x`).join(", ")
303
+ };
245
304
  }
246
305
  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
306
  const lastLoadedSrcRef = useRef(void 0);
@@ -326,7 +385,7 @@ const Image = forwardRef(function Image({ src: srcProp, alt, width, height, fill
326
385
  lastErrorSrcRef.current = src;
327
386
  markBlurComplete();
328
387
  } : void 0;
329
- if (_unoptimized === true) {
388
+ if (_unoptimized === true || __globallyUnoptimized) {
330
389
  const renderedSrc = overrideSrc || src;
331
390
  const sanitizedBlur = imgBlurDataURL ? sanitizeBlurDataURL(imgBlurDataURL) : void 0;
332
391
  const blurStyle = !blurComplete && placeholder === "blur" && sanitizedBlur ? {
@@ -456,8 +515,9 @@ const Image = forwardRef(function Image({ src: srcProp, alt, width, height, fill
456
515
  }
457
516
  const imgQuality = quality ?? 75;
458
517
  const skipOptimization = isSvgUrl(src) && !__dangerouslyAllowSVG;
459
- 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;
460
- const optimizedSrc = skipOptimization ? src : imgWidth ? imageOptimizationUrl(src, imgWidth, imgQuality) : imageOptimizationUrl(src, RESPONSIVE_WIDTHS[0], imgQuality);
518
+ const optimizedAttributes = imgWidth && !fill && !skipOptimization ? generateImageAttributes(src, imgWidth, imgQuality, sizes) : void 0;
519
+ 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;
520
+ const optimizedSrc = skipOptimization ? src : optimizedAttributes ? optimizedAttributes.src : imageOptimizationUrl(src, RESPONSIVE_WIDTHS[0], imgQuality);
461
521
  const sanitizedLocalBlur = imgBlurDataURL ? sanitizeBlurDataURL(imgBlurDataURL) : void 0;
462
522
  const blurStyle = !blurComplete && placeholder === "blur" && sanitizedLocalBlur ? {
463
523
  backgroundImage: `url(${sanitizedLocalBlur})`,
@@ -508,7 +568,7 @@ function getImageProps(props) {
508
568
  blurDataURL: blurDataURLProp
509
569
  });
510
570
  const shouldPreload = _preload === true || priority === true;
511
- if (_unoptimized === true) {
571
+ if (_unoptimized === true || __globallyUnoptimized) {
512
572
  const renderedSrc = overrideSrc || src;
513
573
  const sanitizedBlurURL = imgBlurDataURL ? sanitizeBlurDataURL(imgBlurDataURL) : void 0;
514
574
  const blurStyle = placeholder === "blur" && sanitizedBlurURL ? {
@@ -550,8 +610,9 @@ function getImageProps(props) {
550
610
  quality: imgQuality
551
611
  }) : src;
552
612
  const skipOpt = isSvgUrl(resolvedSrc) && !__dangerouslyAllowSVG || blockedInProd || !!loader || isRemoteUrl(resolvedSrc);
553
- const optimizedSrc = skipOpt ? resolvedSrc : imgWidth ? imageOptimizationUrl(resolvedSrc, imgWidth, imgQuality) : imageOptimizationUrl(resolvedSrc, RESPONSIVE_WIDTHS[0], imgQuality);
554
- const srcSet = imgWidth && !fill && !isRemoteUrl(resolvedSrc) && !loader && !skipOpt ? generateSrcSet(resolvedSrc, imgWidth, imgQuality) : void 0;
613
+ const optimizedAttributes = imgWidth && !fill && !skipOpt ? generateImageAttributes(resolvedSrc, imgWidth, imgQuality, sizes) : null;
614
+ const optimizedSrc = skipOpt ? resolvedSrc : optimizedAttributes ? optimizedAttributes.src : imageOptimizationUrl(resolvedSrc, RESPONSIVE_WIDTHS[0], imgQuality);
615
+ const srcSet = optimizedAttributes?.srcSet;
555
616
  const sanitizedBlurURL = imgBlurDataURL ? sanitizeBlurDataURL(imgBlurDataURL) : void 0;
556
617
  const blurStyle = placeholder === "blur" && sanitizedBlurURL ? {
557
618
  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 };