@qzsy/vinext 0.1.11 → 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 +28 -24
  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,22 +1,24 @@
1
1
  import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
2
2
  import { hasBasePath, stripBasePath } from "../utils/base-path.js";
3
- import { VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_STATIC_FILE_HEADER } from "./headers.js";
3
+ import { VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER } from "../utils/protocol-headers.js";
4
+ import { VINEXT_STATIC_FILE_HEADER } from "./headers.js";
4
5
  import { normalizePath } from "./normalize-path.js";
5
6
  import { notFoundResponse } from "./http-error-responses.js";
6
7
  import { isOpenRedirectShaped } from "./open-redirect.js";
7
8
  import { filterInternalHeaders } from "./request-pipeline.js";
8
9
  import { isUnknownRecord } from "../utils/record.js";
10
+ import { buildNextDataNotFoundResponse, isNextDataPathname, parseNextDataPathname } from "./pages-data-route.js";
9
11
  import { resolveRequestHost, resolveRequestProtocol, trustProxy, trustedHosts } from "./proxy-trust.js";
10
12
  import { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, isImageOptimizationPath, isSafeImageContentType, parseImageParams } from "./image-optimization.js";
11
13
  import { installSocketErrorBackstop } from "./socket-error-backstop.js";
12
14
  import { ASSET_PREFIX_URL_DIR, assetPrefixPathname, isAbsoluteAssetPrefix } from "../utils/asset-prefix.js";
13
15
  import { CONTENT_TYPES, StaticFileCache, etagFromFilenameHash } from "./static-file-cache.js";
14
- import { buildNextDataNotFoundResponse, isNextDataPathname, parseNextDataPathname } from "./pages-data-route.js";
15
16
  import { collectInlineCssManifest } from "../build/inline-css.js";
16
17
  import { mergeHeaders } from "./worker-utils.js";
17
18
  import { runPagesRequest, wrapMiddlewareWithBasePath } from "./pages-request-pipeline.js";
18
- import { readTrustedPrerenderRouteParamsFromHeaders, serializePrerenderRouteParamsHeader } from "./prerender-route-params.js";
19
19
  import { computeClientRuntimeMetadata } from "../utils/client-runtime-metadata.js";
20
+ import { readTrustedPrerenderRouteParamsFromHeaders, serializePrerenderRouteParamsHeader } from "./prerender-route-params.js";
21
+ import { setPagesClientAssets } from "./pages-client-assets.js";
20
22
  import { readPrerenderSecret } from "../build/server-manifest.js";
21
23
  import { seedMemoryCacheFromPrerender } from "./seed-cache.js";
22
24
  import { negotiateEncoding, parseAcceptedEncodings, selectContentEncoding } from "./accept-encoding.js";
@@ -275,8 +277,11 @@ function installClientBuildManifestGlobals(clientDir, assetBase, assetPrefix) {
275
277
  assetBase,
276
278
  assetPrefix
277
279
  });
278
- globalThis.__VINEXT_LAZY_CHUNKS__ = metadata.lazyChunks;
279
- globalThis.__VINEXT_DYNAMIC_PRELOADS__ = metadata.dynamicPreloads;
280
+ setPagesClientAssets({
281
+ appBootstrapPreinitModules: metadata.appBootstrapPreinitModules,
282
+ lazyChunks: metadata.lazyChunks,
283
+ dynamicPreloads: metadata.dynamicPreloads
284
+ });
280
285
  }
281
286
  function isNoBodyResponseStatus(status) {
282
287
  return NO_BODY_RESPONSE_STATUSES.has(status);
@@ -305,7 +310,7 @@ function logProdServerStarted(host, port, purpose) {
305
310
  * arguments in (headers, response) order. The request path now calls
306
311
  * `runPagesRequest`, which uses `mergeHeaders` directly; this wrapper is retained
307
312
  * only for its existing tests and any external callers, so there is a single
308
- * implementation to keep in sync. (deploy.ts still emits its own generated copy.)
313
+ * implementation to keep in sync. The init-owned Cloudflare Worker template delegates here.
309
314
  */
310
315
  function mergeWebResponse(middlewareHeaders, response, statusOverride) {
311
316
  return mergeHeaders(response, middlewareHeaders, statusOverride);
@@ -736,18 +741,21 @@ function readSsrManifest(clientDir) {
736
741
  }
737
742
  return parsed;
738
743
  }
739
- function installPagesClientAssetGlobals(options) {
744
+ function installPagesClientAssets(options) {
740
745
  const ssrManifest = readSsrManifest(options.clientDir);
741
- globalThis.__VINEXT_SSR_MANIFEST__ = Object.keys(ssrManifest).length > 0 ? ssrManifest : void 0;
742
746
  const metadata = computeClientRuntimeMetadata({
743
747
  clientDir: options.clientDir,
744
748
  assetBase: options.assetBase,
745
749
  assetPrefix: options.assetPrefix,
746
750
  includeClientEntry: options.clientEntryLookup === "pages-client-entry" ? "pages-client-entry" : true
747
751
  });
748
- globalThis.__VINEXT_CLIENT_ENTRY__ = metadata.clientEntryFile;
749
- globalThis.__VINEXT_LAZY_CHUNKS__ = metadata.lazyChunks;
750
- globalThis.__VINEXT_DYNAMIC_PRELOADS__ = metadata.dynamicPreloads;
752
+ setPagesClientAssets({
753
+ clientEntry: metadata.clientEntryFile,
754
+ appBootstrapPreinitModules: metadata.appBootstrapPreinitModules,
755
+ ssrManifest: Object.keys(ssrManifest).length > 0 ? ssrManifest : void 0,
756
+ lazyChunks: metadata.lazyChunks,
757
+ dynamicPreloads: metadata.dynamicPreloads
758
+ });
751
759
  return ssrManifest;
752
760
  }
753
761
  /**
@@ -769,11 +777,6 @@ function installPagesClientAssetGlobals(options) {
769
777
  */
770
778
  async function startAppRouterServer(options) {
771
779
  const { port, host, clientDir, rscEntryPath, compress, purpose } = options;
772
- let imageConfig;
773
- const imageConfigPath = path.join(path.dirname(rscEntryPath), "image-config.json");
774
- if (fs.existsSync(imageConfigPath)) try {
775
- imageConfig = JSON.parse(fs.readFileSync(imageConfigPath, "utf-8"));
776
- } catch {}
777
780
  const prerenderSecret = readPrerenderSecret(path.dirname(rscEntryPath));
778
781
  const rscModule = await importServerEntryModule(rscEntryPath);
779
782
  const rscHandler = resolveAppRouterHandler(rscModule.default);
@@ -781,10 +784,18 @@ async function startAppRouterServer(options) {
781
784
  const appRouterBasePath = typeof rscModule.__basePath === "string" ? rscModule.__basePath : "";
782
785
  const appRouterInlineCss = rscModule.__inlineCss === true;
783
786
  const appRouterHasPagesDir = rscModule.__hasPagesDir === true;
787
+ const appImageAllowedWidths = Array.isArray(rscModule.__imageAllowedWidths) ? rscModule.__imageAllowedWidths : [...DEFAULT_DEVICE_SIZES, ...DEFAULT_IMAGE_SIZES];
788
+ let imageConfig = typeof rscModule.__imageConfig === "object" && rscModule.__imageConfig !== null ? rscModule.__imageConfig : void 0;
789
+ if (imageConfig === void 0) {
790
+ const imageConfigPath = path.join(path.dirname(rscEntryPath), "image-config.json");
791
+ if (fs.existsSync(imageConfigPath)) try {
792
+ imageConfig = JSON.parse(fs.readFileSync(imageConfigPath, "utf-8"));
793
+ } catch {}
794
+ }
784
795
  globalThis.__VINEXT_INLINE_CSS__ = appRouterInlineCss ? collectInlineCssManifest(clientDir, appRouterAssetPrefix) : void 0;
785
796
  const appAssetPathPrefix = assetPrefixPathname(appRouterAssetPrefix);
786
797
  const appAssetBase = appRouterBasePath ? `${appRouterBasePath}/` : "/";
787
- if (appRouterHasPagesDir) installPagesClientAssetGlobals({
798
+ if (appRouterHasPagesDir) installPagesClientAssets({
788
799
  clientDir,
789
800
  assetPrefix: appRouterAssetPrefix,
790
801
  assetBase: appAssetBase,
@@ -819,17 +830,16 @@ async function startAppRouterServer(options) {
819
830
  return;
820
831
  }
821
832
  }
833
+ let missingBuildAsset = false;
822
834
  {
823
835
  const assetLookupPath = resolveAppRouterAssetPath(pathname, appAssetPathPrefix, appRouterAssetPrefix);
824
836
  if (assetLookupPath) {
825
837
  if (await tryServeStatic(req, res, clientDir, assetLookupPath, compress, staticCache)) return;
826
- res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" });
827
- res.end("Not Found");
828
- return;
838
+ missingBuildAsset = true;
829
839
  }
830
840
  }
831
841
  if (isImageOptimizationPath(pathname)) {
832
- const params = parseImageParams(new URL(rawUrl, "http://localhost"), [...imageConfig?.deviceSizes ?? DEFAULT_DEVICE_SIZES, ...imageConfig?.imageSizes ?? DEFAULT_IMAGE_SIZES], imageConfig?.qualities);
842
+ const params = parseImageParams(new URL(rawUrl, "http://localhost"), appImageAllowedWidths, imageConfig?.qualities);
833
843
  if (!params) {
834
844
  res.writeHead(400);
835
845
  res.end("Bad Request");
@@ -868,6 +878,12 @@ async function startAppRouterServer(options) {
868
878
  await sendWebResponse(notFoundResponse({ headers: toWebHeaders(staticResponseHeaders) }), req, res, compress);
869
879
  return;
870
880
  }
881
+ if (missingBuildAsset && response.status === 404) {
882
+ cancelResponseBody(response);
883
+ res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" });
884
+ res.end("Not Found");
885
+ return;
886
+ }
871
887
  await sendWebResponse(response, req, res, compress);
872
888
  } catch (e) {
873
889
  console.error("[vinext] Server error:", e);
@@ -918,6 +934,7 @@ async function startPagesRouterServer(options) {
918
934
  const serverEntry = await importServerEntryModule(serverEntryPath);
919
935
  const { renderPage, handleApiRoute: handleApi, runMiddleware, vinextConfig, buildId: pagesBuildId } = serverEntry;
920
936
  const matchPageRoute = typeof serverEntry.matchPageRoute === "function" ? serverEntry.matchPageRoute : void 0;
937
+ const hasMiddleware = serverEntry.hasMiddleware === true;
921
938
  const pageRoutes = readPagesServerEntryPageRoutes(serverEntry.pageRoutes);
922
939
  const prerenderSecret = readPrerenderSecret(path.dirname(serverEntryPath));
923
940
  const basePath = vinextConfig?.basePath ?? "";
@@ -941,7 +958,7 @@ async function startPagesRouterServer(options) {
941
958
  contentDispositionType: vinextConfig.images.contentDispositionType,
942
959
  contentSecurityPolicy: vinextConfig.images.contentSecurityPolicy
943
960
  } : void 0;
944
- const ssrManifest = installPagesClientAssetGlobals({
961
+ const ssrManifest = installPagesClientAssets({
945
962
  clientDir,
946
963
  assetPrefix,
947
964
  assetBase,
@@ -1000,11 +1017,9 @@ async function startPagesRouterServer(options) {
1000
1017
  }
1001
1018
  const staticLookupPath = stripBasePath(pathname, basePath);
1002
1019
  const pagesAssetLookup = resolveAppRouterAssetPath(pathname, pagesAssetPathPrefix, assetPrefix);
1020
+ const missingBuildAsset = pagesAssetLookup !== null;
1003
1021
  if (pagesAssetLookup) {
1004
1022
  if (await tryServeStatic(req, res, clientDir, pagesAssetLookup, compress, staticCache)) return;
1005
- res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" });
1006
- res.end("Not Found");
1007
- return;
1008
1023
  }
1009
1024
  if (isImageOptimizationPath(pathname) || isImageOptimizationPath(staticLookupPath)) {
1010
1025
  const params = parseImageParams(new URL(rawUrl, "http://localhost"), allowedImageWidths, pagesImageConfig?.qualities);
@@ -1072,6 +1087,7 @@ async function startPagesRouterServer(options) {
1072
1087
  hadBasePath,
1073
1088
  isDataReq,
1074
1089
  isDataRequest,
1090
+ hasMiddleware,
1075
1091
  ctx: void 0,
1076
1092
  rawSearch: rawQs,
1077
1093
  matchPageRoute: matchPageRoute ?? null,
@@ -1089,6 +1105,12 @@ async function startPagesRouterServer(options) {
1089
1105
  if (result.type === "handled") return;
1090
1106
  if (result.type === "response") {
1091
1107
  const { response } = result;
1108
+ if (missingBuildAsset && response.status === 404) {
1109
+ cancelResponseBody(response);
1110
+ res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" });
1111
+ res.end("Not Found");
1112
+ return;
1113
+ }
1092
1114
  if (isVinextStreamedHtmlResponse(response) || !response.body || result.defaultContentType === void 0) {
1093
1115
  await sendWebResponse(response, req, res, compress);
1094
1116
  return;
@@ -1,4 +1,5 @@
1
1
  import { hasBasePath, removeTrailingSlash, stripBasePath } from "../utils/base-path.js";
2
+ import "../utils/protocol-headers.js";
2
3
  import { INTERNAL_HEADERS, VINEXT_INTERNAL_HEADERS, VINEXT_STATIC_FILE_HEADER } from "./headers.js";
3
4
  import { matchHeaders } from "../config/config-matchers.js";
4
5
  import { forbiddenResponse, notFoundResponse } from "./http-error-responses.js";
@@ -1,8 +1,8 @@
1
1
  import { isrCacheKey, isrSetPrerenderedAppPage } from "./isr-cache.js";
2
+ import { getRenderedAppRoutes, isFallbackShellArtifactPath, readPrerenderManifest } from "./prerender-manifest.js";
2
3
  import { buildAppPageCacheTags } from "./app-page-cache.js";
3
4
  import { getOutputPath, getRscOutputPath } from "../utils/prerender-output-paths.js";
4
5
  import { addPregeneratedConcretePath, clearPregeneratedConcretePaths, normalizePregeneratedPathname } from "./pregenerated-concrete-paths.js";
5
- import { getRenderedAppRoutes, isFallbackShellArtifactPath, readPrerenderManifest } from "./prerender-manifest.js";
6
6
  import fs from "node:fs";
7
7
  import path from "node:path";
8
8
  //#region src/server/seed-cache.ts
@@ -67,7 +67,7 @@ async function seedMemoryCacheFromPrerender(serverDir, options) {
67
67
  const revalidateSeconds = typeof route.revalidate === "number" ? route.revalidate : void 0;
68
68
  const expireSeconds = typeof route.expire === "number" ? route.expire : void 0;
69
69
  const tags = buildAppPageCacheTags(cachePathname, []);
70
- if (await seedHtml(writeAppPageEntry, prerenderDir, htmlKey, artifactPathname, trailingSlash, revalidateSeconds, expireSeconds, tags)) {
70
+ if (await seedHtml(writeAppPageEntry, prerenderDir, htmlKey, artifactPathname, trailingSlash, route.headers, revalidateSeconds, expireSeconds, tags)) {
71
71
  await seedRsc(writeAppPageEntry, prerenderDir, rscKey, artifactPathname, revalidateSeconds, expireSeconds, tags);
72
72
  seeded++;
73
73
  }
@@ -81,7 +81,7 @@ function createDefaultAppPageEntryWriter() {
81
81
  * Seed the HTML cache entry for a single route.
82
82
  * Returns true if the file existed and was seeded.
83
83
  */
84
- async function seedHtml(writeAppPageEntry, prerenderDir, key, pathname, trailingSlash, revalidateSeconds, expireSeconds, tags) {
84
+ async function seedHtml(writeAppPageEntry, prerenderDir, key, pathname, trailingSlash, headers, revalidateSeconds, expireSeconds, tags) {
85
85
  const relPath = getOutputPath(pathname, trailingSlash);
86
86
  const fullPath = path.join(prerenderDir, relPath);
87
87
  if (!fs.existsSync(fullPath)) return false;
@@ -89,7 +89,7 @@ async function seedHtml(writeAppPageEntry, prerenderDir, key, pathname, trailing
89
89
  kind: "APP_PAGE",
90
90
  html: fs.readFileSync(fullPath, "utf-8"),
91
91
  rscData: void 0,
92
- headers: void 0,
92
+ headers,
93
93
  postponed: void 0,
94
94
  status: void 0
95
95
  }, {
@@ -1,7 +1,8 @@
1
1
  //#region src/server/worker-utils.d.ts
2
+ declare function finalizeMissingStaticAssetResponse(response: Response, missingBuildAsset: boolean): Response;
2
3
  declare function mergeHeaders(response: Response, extraHeaders: Record<string, string | string[]>, statusOverride?: number): Response;
3
4
  declare function resolveStaticAssetSignal(signalResponse: Response, options: {
4
5
  fetchAsset(path: string): Promise<Response>;
5
6
  }): Promise<Response | null>;
6
7
  //#endregion
7
- export { mergeHeaders, resolveStaticAssetSignal };
8
+ export { finalizeMissingStaticAssetResponse, mergeHeaders, resolveStaticAssetSignal };
@@ -1,4 +1,5 @@
1
1
  import { VINEXT_STATIC_FILE_HEADER } from "./headers.js";
2
+ import { notFoundStaticAssetResponse } from "./http-error-responses.js";
2
3
  //#region src/server/worker-utils.ts
3
4
  /**
4
5
  * Shared utilities for Cloudflare Worker entries.
@@ -29,6 +30,11 @@ function cancelResponseBody(response) {
29
30
  if (!body || body.locked) return;
30
31
  body.cancel().catch(() => {});
31
32
  }
33
+ function finalizeMissingStaticAssetResponse(response, missingBuildAsset) {
34
+ if (!missingBuildAsset || response.status !== 404) return response;
35
+ cancelResponseBody(response);
36
+ return notFoundStaticAssetResponse();
37
+ }
32
38
  function buildHeaderRecord(response, omitNames = []) {
33
39
  const omitted = new Set(omitNames.map((name) => name.toLowerCase()));
34
40
  const headers = {};
@@ -96,4 +102,4 @@ async function resolveStaticAssetSignal(signalResponse, options) {
96
102
  return mergeHeaders(assetResponse, extraHeaders, assetResponse.ok && signalResponse.status !== 200 ? signalResponse.status : void 0);
97
103
  }
98
104
  //#endregion
99
- export { mergeHeaders, resolveStaticAssetSignal };
105
+ export { finalizeMissingStaticAssetResponse, mergeHeaders, resolveStaticAssetSignal };
@@ -2,6 +2,7 @@
2
2
  type AppRouterScrollIntent = Readonly<{
3
3
  commitId: number | null;
4
4
  hash: string | null;
5
+ headElements: ReadonlySet<Element> | null;
5
6
  id: number;
6
7
  targetHoistedInHead: boolean;
7
8
  }>;
@@ -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*.
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  import { appendAssetDeploymentIdQuery } from "../utils/deployment-id.js";
3
3
  import { useScriptNonce } from "./script-nonce-context.js";
4
+ import { getPagesClientAssets } from "../server/pages-client-assets.js";
4
5
  import React from "react";
5
6
  import * as ReactDOM from "react-dom";
6
7
  //#region src/shims/dynamic-preload-chunks.tsx
@@ -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 };