@qzsy/vinext 0.1.12 → 0.1.81

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 (231) 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 +160 -160
  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 +106 -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-response-headers.d.ts +19 -0
  146. package/dist/server/dev-response-headers.js +78 -0
  147. package/dist/server/dev-server.js +8 -15
  148. package/dist/server/dev-stack-sourcemap.d.ts +1 -1
  149. package/dist/server/dev-stack-sourcemap.js +1 -1
  150. package/dist/server/headers.d.ts +7 -15
  151. package/dist/server/headers.js +6 -15
  152. package/dist/server/image-optimization.d.ts +51 -1
  153. package/dist/server/image-optimization.js +52 -2
  154. package/dist/server/isr-cache.d.ts +1 -1
  155. package/dist/server/isr-cache.js +2 -2
  156. package/dist/server/middleware-runtime.js +6 -1
  157. package/dist/server/navigation-planner.d.ts +1 -0
  158. package/dist/server/navigation-planner.js +14 -3
  159. package/dist/server/pages-asset-tags.d.ts +4 -6
  160. package/dist/server/pages-asset-tags.js +12 -12
  161. package/dist/server/pages-client-assets.d.ts +12 -0
  162. package/dist/server/pages-client-assets.js +10 -0
  163. package/dist/server/pages-page-data.d.ts +23 -1
  164. package/dist/server/pages-page-data.js +43 -24
  165. package/dist/server/pages-page-handler.d.ts +2 -1
  166. package/dist/server/pages-page-handler.js +10 -4
  167. package/dist/server/pages-request-pipeline.d.ts +2 -0
  168. package/dist/server/pages-request-pipeline.js +25 -1
  169. package/dist/server/prerender-manifest.d.ts +3 -1
  170. package/dist/server/prerender-route-params.js +1 -1
  171. package/dist/server/prod-server.d.ts +1 -1
  172. package/dist/server/prod-server.js +47 -25
  173. package/dist/server/request-log.d.ts +5 -14
  174. package/dist/server/request-log.js +7 -1
  175. package/dist/server/request-pipeline.js +1 -0
  176. package/dist/server/seed-cache.js +4 -4
  177. package/dist/server/server-action-logger.d.ts +39 -0
  178. package/dist/server/server-action-logger.js +104 -0
  179. package/dist/server/worker-utils.d.ts +2 -1
  180. package/dist/server/worker-utils.js +7 -1
  181. package/dist/shims/app-router-scroll-state.d.ts +1 -0
  182. package/dist/shims/app-router-scroll-state.js +1 -0
  183. package/dist/shims/app-router-scroll.js +2 -1
  184. package/dist/shims/cache.js +19 -15
  185. package/dist/shims/cdn-cache.js +1 -1
  186. package/dist/shims/dynamic-preload-chunks.js +2 -1
  187. package/dist/shims/error-boundary.d.ts +19 -1
  188. package/dist/shims/error-boundary.js +11 -1
  189. package/dist/shims/form.d.ts +3 -1
  190. package/dist/shims/form.js +37 -43
  191. package/dist/shims/headers.d.ts +9 -1
  192. package/dist/shims/headers.js +31 -6
  193. package/dist/shims/image-optimization-url.d.ts +4 -0
  194. package/dist/shims/image-optimization-url.js +33 -1
  195. package/dist/shims/image.js +46 -13
  196. package/dist/shims/internal/app-route-detection.d.ts +2 -17
  197. package/dist/shims/internal/app-route-detection.js +4 -17
  198. package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +23 -0
  199. package/dist/shims/internal/hybrid-client-route-owner-direct.js +51 -0
  200. package/dist/shims/internal/hybrid-client-route-owner.d.ts +2 -5
  201. package/dist/shims/internal/hybrid-client-route-owner.js +9 -60
  202. package/dist/shims/internal/pages-router-components.d.ts +7 -0
  203. package/dist/shims/internal/pages-router-components.js +13 -0
  204. package/dist/shims/link.js +23 -16
  205. package/dist/shims/metadata.d.ts +3 -2
  206. package/dist/shims/metadata.js +8 -4
  207. package/dist/shims/navigation.js +4 -2
  208. package/dist/shims/root-params.d.ts +15 -1
  209. package/dist/shims/root-params.js +21 -1
  210. package/dist/shims/router.d.ts +2 -5
  211. package/dist/shims/router.js +41 -22
  212. package/dist/shims/server.js +3 -2
  213. package/dist/typegen.js +6 -5
  214. package/dist/utils/client-runtime-metadata.d.ts +2 -18
  215. package/dist/utils/client-runtime-metadata.js +31 -22
  216. package/dist/utils/dev-stack-sourcemap-endpoint.d.ts +4 -0
  217. package/dist/{server → utils}/dev-stack-sourcemap-endpoint.js +1 -1
  218. package/dist/utils/domain-locale.d.ts +6 -3
  219. package/dist/{server → utils}/middleware-request-headers.d.ts +1 -1
  220. package/dist/{server → utils}/middleware-request-headers.js +2 -2
  221. package/dist/utils/path.d.ts +2 -1
  222. package/dist/utils/path.js +1 -1
  223. package/dist/utils/project.d.ts +9 -1
  224. package/dist/utils/project.js +21 -4
  225. package/dist/utils/protocol-headers.d.ts +17 -0
  226. package/dist/utils/protocol-headers.js +17 -0
  227. package/dist/utils/react-version.d.ts +4 -0
  228. package/dist/utils/react-version.js +44 -0
  229. package/package.json +29 -23
  230. package/dist/server/dev-stack-sourcemap-endpoint.d.ts +0 -4
  231. /package/dist/{cloudflare → packages/cloudflare}/src/utils/cache-control-metadata.js +0 -0
@@ -14,12 +14,18 @@ import { resolvePagesI18nRequest } from "./pages-i18n.js";
14
14
  import { buildDefaultPagesNotFoundResponse } from "./pages-default-404.js";
15
15
  import { buildPagesReadinessNextData } from "./pages-readiness.js";
16
16
  import { resolvePagesPageMethodResponse } from "./pages-page-method.js";
17
+ import { renderPagesPageResponse } from "./pages-page-response.js";
18
+ import { hasPagesGetInitialProps } from "./pages-get-initial-props.js";
17
19
  import { buildNextDataNotFoundResponse, buildNextDataPropsJsonResponse, normalizePagesDataRequest, parseNextDataPathname } from "./pages-data-route.js";
20
+ import { resolvePagesPageData } from "./pages-page-data.js";
18
21
  import { createPagesReqRes } from "./pages-node-compat.js";
19
22
  import { collectAssetTags, resolveClientModuleUrl } from "./pages-asset-tags.js";
20
- import { renderPagesPageResponse } from "./pages-page-response.js";
21
- import { resolvePagesPageData } from "./pages-page-data.js";
22
23
  //#region src/server/pages-page-handler.ts
24
+ function shouldEmitPagesClientTraceMetadata(pageModule, appComponent) {
25
+ if (typeof pageModule.getServerSideProps === "function") return true;
26
+ if (typeof pageModule.getStaticProps === "function") return false;
27
+ return hasPagesGetInitialProps(pageModule.default) || hasPagesGetInitialProps(appComponent);
28
+ }
23
29
  function buildI18nRenderContext(i18nConfig, locale, currentDefaultLocale, domainLocales) {
24
30
  return {
25
31
  locale,
@@ -334,7 +340,7 @@ function createPagesPageHandler(opts) {
334
340
  getFontLinks,
335
341
  getFontStyles,
336
342
  getSSRHeadHTML: typeof getSSRHeadHTML === "function" ? getSSRHeadHTML : void 0,
337
- clientTraceMetadata: vinextConfig.clientTraceMetadata,
343
+ clientTraceMetadata: shouldEmitPagesClientTraceMetadata(pageModule, AppComponent) ? vinextConfig.clientTraceMetadata : void 0,
338
344
  gsspRes,
339
345
  isrCacheKey: pageIsrCacheKey,
340
346
  expireSeconds: vinextConfig.expireTime,
@@ -400,4 +406,4 @@ function createPagesPageHandler(opts) {
400
406
  return renderPage;
401
407
  }
402
408
  //#endregion
403
- export { createPagesPageHandler };
409
+ export { createPagesPageHandler, shouldEmitPagesClientTraceMetadata };
@@ -34,11 +34,13 @@ type PagesPipelineDeps = {
34
34
  hadBasePath: boolean;
35
35
  isDataReq: boolean;
36
36
  isDataRequest: boolean;
37
+ hasMiddleware: boolean;
37
38
  ctx?: unknown;
38
39
  rawSearch?: string;
39
40
  matchPageRoute?: ((pathname: string, request: Request) => {
40
41
  route: {
41
42
  isDynamic: boolean;
43
+ pattern?: string;
42
44
  };
43
45
  } | null) | null;
44
46
  runMiddleware?: ((request: Request, ctx: unknown, opts: {
@@ -1,4 +1,5 @@
1
1
  import { addBasePathToPathname, hasBasePath } from "../utils/base-path.js";
2
+ import { patternToNextFormat } from "../routing/route-validation.js";
2
3
  import { applyMiddlewareRequestHeaders, isExternalUrl, matchRedirect, matchRewrite, preserveRedirectDestinationQuery, proxyExternalRequest, requestContextFromRequest, sanitizeDestination } from "../config/config-matchers.js";
3
4
  import { applyConfigHeadersToHeaderRecord, cloneRequestWithUrl, normalizeTrailingSlash } from "./request-pipeline.js";
4
5
  import { mergeRewriteQuery } from "../utils/query.js";
@@ -141,6 +142,13 @@ async function runPagesRequest(request, deps) {
141
142
  });
142
143
  let resolvedPathname = pathnameForResolvedUrl(resolvedUrl);
143
144
  const matchResolvedPathname = (p) => i18nConfig ? normalizeDefaultLocalePathname(p, i18nConfig, { hostname: requestHostname }) : p;
145
+ const matchedPathnameForRoute = (routePattern) => {
146
+ const matchedPathname = routePattern ? patternToNextFormat(routePattern) : resolvedPathname;
147
+ if (!i18nConfig) return matchedPathname;
148
+ const resolvedLocale = resolvedPathname.split("/", 3)[1];
149
+ if (resolvedLocale && i18nConfig.locales.includes(resolvedLocale)) return matchedPathname === "/" ? `/${resolvedLocale}` : `/${resolvedLocale}${matchedPathname}`;
150
+ return matchResolvedPathname(matchedPathname);
151
+ };
144
152
  if (configHeaders.length) applyConfigHeadersToHeaderRecord(middlewareHeaders, {
145
153
  configHeaders,
146
154
  pathname: matchPathname,
@@ -268,12 +276,28 @@ async function runPagesRequest(request, deps) {
268
276
  if (fallbackFilesystemResult) return fallbackFilesystemResult;
269
277
  const fallbackApiResult = await handleResolvedApiRoute();
270
278
  if (fallbackApiResult) return fallbackApiResult;
279
+ renderPageMatch = deps.matchPageRoute ? deps.matchPageRoute(resolvedPathname, request) : null;
271
280
  response = await deps.renderPage(request, resolvedUrl, void 0, stagedHeaders);
272
281
  matchedFallbackRewrite = true;
273
282
  if (response.status !== 404) break;
274
283
  }
275
284
  if (response.status === 404 && shouldDeferErrorPageOnMiss && !matchedFallbackRewrite) response = await deps.renderPage(request, resolvedUrl, void 0, stagedHeaders);
276
- const merged = mergeHeaders(response, middlewareHeaders, middlewareStatus);
285
+ const matchedPathHeaders = { ...middlewareHeaders };
286
+ if ((isDataReq || isDataRequest) && deps.hasMiddleware && !renderPageMatch && response.status === 404 && (middlewareStatus === void 0 || middlewareStatus === 200 || middlewareStatus === 404)) {
287
+ const headers = new Headers(response.headers);
288
+ headers.set("content-type", "application/json");
289
+ headers.set("x-nextjs-matched-path", matchResolvedPathname(pathname));
290
+ return {
291
+ type: "response",
292
+ response: mergeHeaders(new Response("{}", {
293
+ status: 200,
294
+ headers
295
+ }), matchedPathHeaders, void 0),
296
+ defaultContentType: "application/json"
297
+ };
298
+ }
299
+ if ((isDataReq || isDataRequest) && renderPageMatch && (middlewareStatus ?? response.status) === 200) matchedPathHeaders["x-nextjs-matched-path"] = matchedPathnameForRoute(renderPageMatch?.route.pattern);
300
+ const merged = mergeHeaders(response, matchedPathHeaders, middlewareStatus);
277
301
  if (merged !== response) merged.__vinextStreamedHtmlResponse = response.__vinextStreamedHtmlResponse;
278
302
  return {
279
303
  type: "response",
@@ -7,11 +7,13 @@ type PrerenderManifestRoute = {
7
7
  path?: string;
8
8
  router?: string;
9
9
  fallback?: boolean;
10
+ headers?: Record<string, string>;
10
11
  };
11
12
  type PrerenderManifest = {
12
13
  buildId?: string;
13
14
  trailingSlash?: boolean;
14
15
  routes?: PrerenderManifestRoute[];
16
+ pregeneratedConcretePaths?: Array<[string, string[]]>;
15
17
  };
16
18
  declare function readPrerenderManifest(manifestPath: string): PrerenderManifest | null;
17
19
  declare function getRenderedAppRoutes(routes: PrerenderManifestRoute[]): PrerenderManifestRoute[];
@@ -30,4 +32,4 @@ declare function isFallbackShellArtifactPath(pathname: string, route?: Prerender
30
32
  */
31
33
  declare function buildPregeneratedConcretePathTable(manifest: PrerenderManifest): Array<[string, string[]]>;
32
34
  //#endregion
33
- export { buildPregeneratedConcretePathTable, getRenderedAppRoutes, isFallbackShellArtifactPath, readPrerenderManifest };
35
+ export { PrerenderManifest, buildPregeneratedConcretePathTable, getRenderedAppRoutes, isFallbackShellArtifactPath, readPrerenderManifest };
@@ -1,4 +1,4 @@
1
- import { VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER } from "./headers.js";
1
+ import { VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER } from "../utils/protocol-headers.js";
2
2
  import { isUnknownRecord } from "../utils/record.js";
3
3
  //#region src/server/prerender-route-params.ts
4
4
  function isPrerenderRouteParams(value) {
@@ -74,7 +74,7 @@ declare function mergeResponseHeaders(middlewareHeaders: Record<string, string |
74
74
  * arguments in (headers, response) order. The request path now calls
75
75
  * `runPagesRequest`, which uses `mergeHeaders` directly; this wrapper is retained
76
76
  * only for its existing tests and any external callers, so there is a single
77
- * implementation to keep in sync. (deploy.ts still emits its own generated copy.)
77
+ * implementation to keep in sync. The init-owned Cloudflare Worker template delegates here.
78
78
  */
79
79
  declare function mergeWebResponse(middlewareHeaders: Record<string, string | string[]>, response: Response, statusOverride?: number): Response;
80
80
  /**
@@ -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,17 +1,6 @@
1
+ import { ServerActionLogInfo } from "./server-action-logger.js";
2
+
1
3
  //#region src/server/request-log.d.ts
2
- /**
3
- * Request logging for the vinext dev server.
4
- *
5
- * Matches Next.js's request log format:
6
- * GET /path 200 in 123ms (compile: 45ms, render: 78ms)
7
- *
8
- * Color coding matches Next.js:
9
- * - 2xx: green
10
- * - 3xx: cyan
11
- * - 4xx: yellow
12
- * - 5xx: red
13
- * - Method: bold
14
- */
15
4
  type RequestLogOptions = {
16
5
  method: string;
17
6
  url: string;
@@ -20,6 +9,8 @@ type RequestLogOptions = {
20
9
  compileMs?: number; /** Time spent in React rendering / HTML streaming. */
21
10
  renderMs?: number;
22
11
  };
12
+ /** Print the nested server action log line under the request log. */
13
+ declare function logServerAction(info: ServerActionLogInfo): void;
23
14
  /**
24
15
  * Print a single request log line to stdout.
25
16
  */
@@ -36,4 +27,4 @@ declare function logRequest({
36
27
  */
37
28
  declare function now(): number;
38
29
  //#endregion
39
- export { logRequest, now };
30
+ export { RequestLogOptions, logRequest, logServerAction, now };
@@ -1,3 +1,4 @@
1
+ import { formatActionArgs } from "./server-action-logger.js";
1
2
  //#region src/server/request-log.ts
2
3
  /**
3
4
  * Request logging for the vinext dev server.
@@ -31,6 +32,11 @@ function formatDuration(ms) {
31
32
  if (ms >= 1e3) return `${(ms / 1e3).toFixed(1)}s`;
32
33
  return `${Math.round(ms)}ms`;
33
34
  }
35
+ /** Print the nested server action log line under the request log. */
36
+ function logServerAction(info) {
37
+ const argsStr = formatActionArgs(info.args);
38
+ process.stdout.write(` └─ ƒ ${info.functionName}(${argsStr}) in ${info.duration}ms ${pretty.dim(info.location)}\n`);
39
+ }
34
40
  /**
35
41
  * Print a single request log line to stdout.
36
42
  */
@@ -53,4 +59,4 @@ function now() {
53
59
  return performance.now();
54
60
  }
55
61
  //#endregion
56
- export { logRequest, now };
62
+ export { logRequest, logServerAction, now };
@@ -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
  }, {
@@ -0,0 +1,39 @@
1
+ //#region src/server/server-action-logger.d.ts
2
+ /**
3
+ * Dev-only Server Action logging — metadata and wire-format helpers.
4
+ *
5
+ * Terminal output lives in `request-log.ts`. Dev middleware interception lives
6
+ * in `dev-response-headers.ts`.
7
+ *
8
+ * Ported from Next.js:
9
+ * - packages/next/src/server/dev/server-action-logger.ts
10
+ * - packages/next/src/server/dev/log-requests.ts
11
+ *
12
+ * https://github.com/vercel/next.js/pull/88277
13
+ */
14
+ type ServerActionLogInfo = {
15
+ functionName: string;
16
+ args: unknown[];
17
+ location: string;
18
+ duration: number;
19
+ };
20
+ declare function isDevServerActionLoggingEnabled(): boolean;
21
+ /**
22
+ * Resolve display metadata from an `x-rsc-action` / `next-action` action id.
23
+ *
24
+ * Action ids encode module path and export name:
25
+ * `/app/actions/actions.ts#echoAction`
26
+ */
27
+ declare function resolveServerActionLogMeta(actionId: string | null): Pick<ServerActionLogInfo, "functionName" | "location"> | null;
28
+ /** Format action arguments for the dev log line. */
29
+ declare function formatActionArgs(args: unknown[]): string;
30
+ declare function serializeServerActionLogHeader(info: ServerActionLogInfo): string;
31
+ declare function parseServerActionLogHeader(value: string): ServerActionLogInfo | null;
32
+ declare function applyServerActionLogHeader(headers: Headers, info: ServerActionLogInfo | null): void;
33
+ declare function createServerActionLogInfo(options: {
34
+ actionId: string | null;
35
+ args: readonly unknown[];
36
+ durationMs: number;
37
+ }): ServerActionLogInfo | null;
38
+ //#endregion
39
+ export { ServerActionLogInfo, applyServerActionLogHeader, createServerActionLogInfo, formatActionArgs, isDevServerActionLoggingEnabled, parseServerActionLogHeader, resolveServerActionLogMeta, serializeServerActionLogHeader };
@@ -0,0 +1,104 @@
1
+ import { VINEXT_ACTION_LOG_HEADER } from "./headers.js";
2
+ //#region src/server/server-action-logger.ts
3
+ /**
4
+ * Dev-only Server Action logging — metadata and wire-format helpers.
5
+ *
6
+ * Terminal output lives in `request-log.ts`. Dev middleware interception lives
7
+ * in `dev-response-headers.ts`.
8
+ *
9
+ * Ported from Next.js:
10
+ * - packages/next/src/server/dev/server-action-logger.ts
11
+ * - packages/next/src/server/dev/log-requests.ts
12
+ *
13
+ * https://github.com/vercel/next.js/pull/88277
14
+ */
15
+ const INLINE_ACTION_PREFIXES = ["$$RSC_SERVER_ACTION_", "$$hoist_"];
16
+ const USE_CACHE_ACTION_PREFIX = "$$RSC_SERVER_CACHE_";
17
+ function isDevServerActionLoggingEnabled() {
18
+ return process.env.NODE_ENV !== "production";
19
+ }
20
+ function isInlineActionExport(exportedName) {
21
+ return INLINE_ACTION_PREFIXES.some((prefix) => exportedName.startsWith(prefix));
22
+ }
23
+ function isUseCacheActionExport(exportedName) {
24
+ return exportedName.startsWith(USE_CACHE_ACTION_PREFIX);
25
+ }
26
+ /**
27
+ * Resolve display metadata from an `x-rsc-action` / `next-action` action id.
28
+ *
29
+ * Action ids encode module path and export name:
30
+ * `/app/actions/actions.ts#echoAction`
31
+ */
32
+ function resolveServerActionLogMeta(actionId) {
33
+ if (!actionId) return null;
34
+ const hashIndex = actionId.lastIndexOf("#");
35
+ if (hashIndex <= 0) return null;
36
+ const exportedName = actionId.slice(hashIndex + 1);
37
+ if (isUseCacheActionExport(exportedName)) return null;
38
+ const location = actionId.slice(0, hashIndex).replace(/\\/g, "/").replace(/^\//, "");
39
+ let functionName;
40
+ if (isInlineActionExport(exportedName)) functionName = "";
41
+ else if (exportedName === "default") functionName = "default";
42
+ else functionName = exportedName;
43
+ return {
44
+ functionName,
45
+ location
46
+ };
47
+ }
48
+ function formatArg(arg, depth = 0) {
49
+ if (arg === null) return "null";
50
+ if (arg === void 0) return "undefined";
51
+ if (typeof arg === "string") return JSON.stringify(arg);
52
+ if (typeof arg === "number" || typeof arg === "boolean" || typeof arg === "bigint") return String(arg);
53
+ if (typeof arg === "symbol") return String(arg);
54
+ if (typeof arg === "function") return "[Function]";
55
+ if (depth >= 2) return "[Object]";
56
+ if (Array.isArray(arg)) {
57
+ const items = arg.slice(0, 3).map((item) => formatArg(item, depth + 1));
58
+ if (arg.length > 3) items.push("...");
59
+ return `[${items.join(",")}]`;
60
+ }
61
+ if (typeof arg === "object") try {
62
+ const formatted = Object.entries(arg).slice(0, 3).map(([key, value]) => `${JSON.stringify(key)}:${formatArg(value, depth + 1)}`);
63
+ if (Object.keys(arg).length > 3) formatted.push("...");
64
+ return `{${formatted.join(",")}}`;
65
+ } catch {
66
+ return "[Object]";
67
+ }
68
+ try {
69
+ return JSON.stringify(arg);
70
+ } catch {
71
+ return "[unserializable]";
72
+ }
73
+ }
74
+ /** Format action arguments for the dev log line. */
75
+ function formatActionArgs(args) {
76
+ return args.map((arg) => formatArg(arg)).join(", ");
77
+ }
78
+ function serializeServerActionLogHeader(info) {
79
+ return JSON.stringify(info);
80
+ }
81
+ function parseServerActionLogHeader(value) {
82
+ try {
83
+ const parsed = JSON.parse(value);
84
+ if (typeof parsed.functionName === "string" && Array.isArray(parsed.args) && typeof parsed.location === "string" && typeof parsed.duration === "number") return parsed;
85
+ } catch {}
86
+ return null;
87
+ }
88
+ function applyServerActionLogHeader(headers, info) {
89
+ if (!info) return;
90
+ headers.set(VINEXT_ACTION_LOG_HEADER, serializeServerActionLogHeader(info));
91
+ }
92
+ function createServerActionLogInfo(options) {
93
+ if (!isDevServerActionLoggingEnabled()) return null;
94
+ const meta = resolveServerActionLogMeta(options.actionId);
95
+ if (!meta) return null;
96
+ const args = Array.isArray(options.args) ? options.args : [options.args];
97
+ return {
98
+ ...meta,
99
+ args: [...args],
100
+ duration: options.durationMs
101
+ };
102
+ }
103
+ //#endregion
104
+ export { applyServerActionLogHeader, createServerActionLogInfo, formatActionArgs, isDevServerActionLoggingEnabled, parseServerActionLogHeader, resolveServerActionLogMeta, serializeServerActionLogHeader };
@@ -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
  }