@wular/pnext 0.0.1

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 (371) hide show
  1. package/README.md +153 -0
  2. package/bin/pnext +67 -0
  3. package/config/lint/base.js +48 -0
  4. package/config/ts/base.json +26 -0
  5. package/config/ts/react.json +13 -0
  6. package/package.json +70 -0
  7. package/reference/compat.md +63 -0
  8. package/reference/config.md +120 -0
  9. package/reference/css.md +58 -0
  10. package/reference/dev.md +69 -0
  11. package/reference/env.md +40 -0
  12. package/reference/metadata.md +86 -0
  13. package/reference/navigation.md +149 -0
  14. package/reference/overview.md +35 -0
  15. package/reference/performance.md +97 -0
  16. package/reference/rendering.md +127 -0
  17. package/reference/routing.md +167 -0
  18. package/reference/typegen.md +64 -0
  19. package/src/api/cache.ts +80 -0
  20. package/src/api/client-cache.ts +9 -0
  21. package/src/api/client-navigation.ts +279 -0
  22. package/src/api/dynamic.tsx +102 -0
  23. package/src/api/link.tsx +119 -0
  24. package/src/api/navigation.ts +198 -0
  25. package/src/api/router/events.ts +53 -0
  26. package/src/api/router/history.ts +70 -0
  27. package/src/api/router/hub.ts +194 -0
  28. package/src/api/router/policies.ts +107 -0
  29. package/src/api/router/runtime.ts +5238 -0
  30. package/src/api/router/types.ts +299 -0
  31. package/src/api/router.ts +167 -0
  32. package/src/api/server.ts +323 -0
  33. package/src/api/suspense.ts +16 -0
  34. package/src/cache/context.ts +61 -0
  35. package/src/cli/adapters/vercel-warm.ts +375 -0
  36. package/src/cli/adapters/vercel.ts +1310 -0
  37. package/src/cli/analyze-print.ts +181 -0
  38. package/src/cli/analyze.ts +328 -0
  39. package/src/cli/boot-trace.ts +29 -0
  40. package/src/cli/build.ts +3114 -0
  41. package/src/cli/dev.ts +276 -0
  42. package/src/cli/index.ts +196 -0
  43. package/src/cli/named-bin.ts +119 -0
  44. package/src/cli/serve-ui.ts +160 -0
  45. package/src/cli/start.ts +1425 -0
  46. package/src/client/build.ts +2136 -0
  47. package/src/client/chunk-fold.ts +526 -0
  48. package/src/client/entry.ts +1525 -0
  49. package/src/client/paths.ts +22 -0
  50. package/src/client/prebuilt.ts +621 -0
  51. package/src/client/profile.ts +75 -0
  52. package/src/client/react-compiler.ts +94 -0
  53. package/src/client/reference-stub.ts +145 -0
  54. package/src/client/reference.ts +47 -0
  55. package/src/compat/actions/action-client.ts +531 -0
  56. package/src/compat/actions/action-dispatch.ts +676 -0
  57. package/src/compat/actions/action-router.ts +40 -0
  58. package/src/compat/actions/action-shared.ts +95 -0
  59. package/src/compat/actions/client-plugin.ts +135 -0
  60. package/src/compat/actions/client-stub.ts +65 -0
  61. package/src/compat/actions/config.ts +164 -0
  62. package/src/compat/actions/detect.ts +208 -0
  63. package/src/compat/actions/discovery.ts +244 -0
  64. package/src/compat/actions/early-submit.ts +40 -0
  65. package/src/compat/actions/endpoint.ts +602 -0
  66. package/src/compat/actions/flight.ts +52 -0
  67. package/src/compat/actions/form-state.ts +73 -0
  68. package/src/compat/actions/hoist.ts +485 -0
  69. package/src/compat/actions/ids.ts +39 -0
  70. package/src/compat/actions/index.ts +41 -0
  71. package/src/compat/actions/instances.ts +144 -0
  72. package/src/compat/actions/origin.ts +109 -0
  73. package/src/compat/actions/protocol.ts +125 -0
  74. package/src/compat/actions/registry.ts +74 -0
  75. package/src/compat/actions/rewrite.ts +282 -0
  76. package/src/compat/actions/serve.ts +414 -0
  77. package/src/compat/actions/server-tag.ts +21 -0
  78. package/src/compat/actions/unrecognized-error.ts +30 -0
  79. package/src/compat/adapter/build-complete.ts +257 -0
  80. package/src/compat/bundler/bun-externals.ts +53 -0
  81. package/src/compat/bundler/cjs-exports.ts +542 -0
  82. package/src/compat/bundler/config.ts +363 -0
  83. package/src/compat/bundler/externals.ts +34 -0
  84. package/src/compat/bundler/import-meta-url.ts +60 -0
  85. package/src/compat/bundler/modularize-imports.ts +119 -0
  86. package/src/compat/bundler/new-url-asset.ts +87 -0
  87. package/src/compat/bundler/optimize-package-imports.ts +273 -0
  88. package/src/compat/bundler/polyfill.ts +88 -0
  89. package/src/compat/bundler/react-compiler.ts +61 -0
  90. package/src/compat/bundler/react-profiler.tsx +25 -0
  91. package/src/compat/bundler/relay-transform.ts +116 -0
  92. package/src/compat/bundler/require-context.ts +281 -0
  93. package/src/compat/bundler/resolve-extensions.ts +75 -0
  94. package/src/compat/bundler/source-cache.ts +61 -0
  95. package/src/compat/bundler/static-imports.ts +25 -0
  96. package/src/compat/bundler/symlink-imports.ts +119 -0
  97. package/src/compat/bundler/tsconfig-paths.ts +50 -0
  98. package/src/compat/bundler/wasm.ts +153 -0
  99. package/src/compat/bundler/webpack-loaders.ts +685 -0
  100. package/src/compat/bundler/worker.ts +278 -0
  101. package/src/compat/cache/build-flags.ts +81 -0
  102. package/src/compat/cache/build-prerender-errors.ts +163 -0
  103. package/src/compat/cache/custom-handler.ts +159 -0
  104. package/src/compat/cache/fetch-patch.ts +745 -0
  105. package/src/compat/cache/handler.ts +100 -0
  106. package/src/compat/cache/modern-handler.ts +275 -0
  107. package/src/compat/cache/resume-data-cache.ts +143 -0
  108. package/src/compat/cache/revalidate.ts +759 -0
  109. package/src/compat/cache/runtime-error.ts +124 -0
  110. package/src/compat/cache/use-cache-transform.ts +961 -0
  111. package/src/compat/cache/use-cache.ts +1695 -0
  112. package/src/compat/cache-control.ts +269 -0
  113. package/src/compat/client/base-path.ts +64 -0
  114. package/src/compat/client/css-order.ts +36 -0
  115. package/src/compat/client/errors/control-flow.ts +92 -0
  116. package/src/compat/client/errors/error-boundary.ts +222 -0
  117. package/src/compat/client/errors/global-error.ts +238 -0
  118. package/src/compat/client/errors/install.ts +217 -0
  119. package/src/compat/client/errors/lazy.ts +53 -0
  120. package/src/compat/client/errors/primitive-throw.ts +126 -0
  121. package/src/compat/client/errors/soft-refresh.ts +14 -0
  122. package/src/compat/client/link-status.ts +86 -0
  123. package/src/compat/client/nav-compat-runtime.ts +57 -0
  124. package/src/compat/client/nav-compat.ts +42 -0
  125. package/src/compat/client/navigation-scroll.ts +154 -0
  126. package/src/compat/client/optimistic-routing.ts +206 -0
  127. package/src/compat/client/prefetch-cache.ts +111 -0
  128. package/src/compat/client/route-announcer.ts +72 -0
  129. package/src/compat/client/segment-cache-policy.ts +159 -0
  130. package/src/compat/client/segment-cache.ts +1077 -0
  131. package/src/compat/client/segment-prefetch.ts +375 -0
  132. package/src/compat/client/trailing-slash.ts +24 -0
  133. package/src/compat/css/chunking.ts +254 -0
  134. package/src/compat/css/inline-css.ts +73 -0
  135. package/src/compat/css/lightningcss.ts +90 -0
  136. package/src/compat/css/modules.ts +373 -0
  137. package/src/compat/css/nonce.ts +30 -0
  138. package/src/compat/css/sass-plugin.ts +65 -0
  139. package/src/compat/css/sass.ts +392 -0
  140. package/src/compat/css/styled-jsx-runtime.ts +80 -0
  141. package/src/compat/css/styled-jsx.ts +49 -0
  142. package/src/compat/edge-runtime.ts +71 -0
  143. package/src/compat/export/client.ts +112 -0
  144. package/src/compat/export/index.ts +272 -0
  145. package/src/compat/export/standalone.ts +207 -0
  146. package/src/compat/image-optimizer/cache.ts +119 -0
  147. package/src/compat/image-optimizer/detect.ts +143 -0
  148. package/src/compat/image-optimizer/index.ts +601 -0
  149. package/src/compat/image-optimizer/source.ts +243 -0
  150. package/src/compat/index.ts +458 -0
  151. package/src/compat/lifecycle/after-scope.ts +86 -0
  152. package/src/compat/lifecycle/after.ts +173 -0
  153. package/src/compat/lifecycle/error-funnel.ts +306 -0
  154. package/src/compat/lifecycle/error-serialize.ts +87 -0
  155. package/src/compat/lifecycle/error-ui.ts +167 -0
  156. package/src/compat/lifecycle/instrumentation-client.ts +138 -0
  157. package/src/compat/lifecycle/instrumentation.ts +277 -0
  158. package/src/compat/lifecycle/node-console.ts +19 -0
  159. package/src/compat/lifecycle/testmode.ts +263 -0
  160. package/src/compat/mdx/compile.ts +219 -0
  161. package/src/compat/mdx/next-mdx-stub.ts +46 -0
  162. package/src/compat/mdx/plugin.ts +37 -0
  163. package/src/compat/metadata-route-artifacts.ts +458 -0
  164. package/src/compat/metadata.ts +295 -0
  165. package/src/compat/middleware/manifest.ts +210 -0
  166. package/src/compat/misc/action-return.ts +173 -0
  167. package/src/compat/next/cache.ts +211 -0
  168. package/src/compat/next/canonical-url.ts +35 -0
  169. package/src/compat/next/client-cache.ts +57 -0
  170. package/src/compat/next/client-navigation.ts +313 -0
  171. package/src/compat/next/client-only.ts +3 -0
  172. package/src/compat/next/client-script.tsx +215 -0
  173. package/src/compat/next/client-server.ts +39 -0
  174. package/src/compat/next/config-loader.ts +569 -0
  175. package/src/compat/next/config.ts +29 -0
  176. package/src/compat/next/constants.cjs +6 -0
  177. package/src/compat/next/constants.ts +6 -0
  178. package/src/compat/next/custom-server.ts +236 -0
  179. package/src/compat/next/dist/client/components/app-router-headers.ts +32 -0
  180. package/src/compat/next/dist/server/app-render/work-unit-async-storage.external.cjs +38 -0
  181. package/src/compat/next/dist/server/web/spec-extension/revalidate.ts +1 -0
  182. package/src/compat/next/dist/server/web/spec-extension/unstable-cache.ts +1 -0
  183. package/src/compat/next/dist/server/web/spec-extension/unstable-no-store.ts +1 -0
  184. package/src/compat/next/dynamic.tsx +46 -0
  185. package/src/compat/next/error.tsx +148 -0
  186. package/src/compat/next/font/cache.ts +171 -0
  187. package/src/compat/next/font/google.ts +2 -0
  188. package/src/compat/next/font/index.ts +8 -0
  189. package/src/compat/next/font/local.ts +5 -0
  190. package/src/compat/next/font/runtime-client.ts +71 -0
  191. package/src/compat/next/font/runtime.ts +974 -0
  192. package/src/compat/next/font/shared.ts +281 -0
  193. package/src/compat/next/form.tsx +156 -0
  194. package/src/compat/next/head.tsx +10 -0
  195. package/src/compat/next/headers.ts +247 -0
  196. package/src/compat/next/image/config.ts +196 -0
  197. package/src/compat/next/image/optimizer.ts +96 -0
  198. package/src/compat/next/image/patterns.ts +103 -0
  199. package/src/compat/next/image/shared.ts +141 -0
  200. package/src/compat/next/image/static-metadata.ts +283 -0
  201. package/src/compat/next/image/validate.ts +269 -0
  202. package/src/compat/next/image-client.tsx +215 -0
  203. package/src/compat/next/image-props.ts +575 -0
  204. package/src/compat/next/image-usage.ts +102 -0
  205. package/src/compat/next/image.tsx +56 -0
  206. package/src/compat/next/index.ts +1 -0
  207. package/src/compat/next/legacy-image.tsx +97 -0
  208. package/src/compat/next/link-usage.ts +29 -0
  209. package/src/compat/next/link-validation-transform.ts +200 -0
  210. package/src/compat/next/link.tsx +466 -0
  211. package/src/compat/next/navigation.cjs +21 -0
  212. package/src/compat/next/navigation.ts +188 -0
  213. package/src/compat/next/offline.ts +51 -0
  214. package/src/compat/next/og.ts +324 -0
  215. package/src/compat/next/optimistic-route-state.ts +188 -0
  216. package/src/compat/next/preferred-region.ts +39 -0
  217. package/src/compat/next/redirects.ts +131 -0
  218. package/src/compat/next/resource-hints.ts +136 -0
  219. package/src/compat/next/rewrites.ts +350 -0
  220. package/src/compat/next/root-params.ts +142 -0
  221. package/src/compat/next/router.cjs +49 -0
  222. package/src/compat/next/router.ts +143 -0
  223. package/src/compat/next/script.tsx +355 -0
  224. package/src/compat/next/server-only.ts +3 -0
  225. package/src/compat/next/server.ts +28 -0
  226. package/src/compat/next/svgr.ts +58 -0
  227. package/src/compat/next/telemetry.ts +77 -0
  228. package/src/compat/next/user-agent.ts +100 -0
  229. package/src/compat/next/web-vitals.ts +56 -0
  230. package/src/compat/otel/api.ts +95 -0
  231. package/src/compat/otel/client-trace-metadata.ts +71 -0
  232. package/src/compat/otel/fetch-span.ts +77 -0
  233. package/src/compat/otel/tracer.ts +944 -0
  234. package/src/compat/pages/client-plugin.ts +108 -0
  235. package/src/compat/pages/index.ts +527 -0
  236. package/src/compat/pages/router-state.ts +94 -0
  237. package/src/compat/ppr/io.ts +38 -0
  238. package/src/compat/ppr/missing-root-params.ts +105 -0
  239. package/src/compat/ppr/root-params-scan.ts +164 -0
  240. package/src/compat/ppr/root-params-transform.ts +75 -0
  241. package/src/compat/ppr/root-params.ts +129 -0
  242. package/src/compat/ppr/segment-config-incompat.ts +34 -0
  243. package/src/compat/protocol.ts +202 -0
  244. package/src/compat/react/client.ts +59 -0
  245. package/src/compat/react/compiler-runtime.ts +60 -0
  246. package/src/compat/react/dom-client.ts +115 -0
  247. package/src/compat/react/dom-react-server.ts +20 -0
  248. package/src/compat/react/dom-server.ts +40 -0
  249. package/src/compat/react/dom.ts +154 -0
  250. package/src/compat/react/preact.ts +522 -0
  251. package/src/compat/react/react-server.ts +84 -0
  252. package/src/compat/react/router-shim.ts +26 -0
  253. package/src/compat/react/server-component-use.ts +48 -0
  254. package/src/compat/react/server-inserted-html.ts +87 -0
  255. package/src/compat/react/server.ts +156 -0
  256. package/src/compat/react/view-transition.ts +60 -0
  257. package/src/compat/register/actions.ts +875 -0
  258. package/src/compat/register/boot.ts +141 -0
  259. package/src/compat/register/build-tier.ts +11 -0
  260. package/src/compat/register/build.ts +182 -0
  261. package/src/compat/register/bundler.ts +587 -0
  262. package/src/compat/register/cache.ts +85 -0
  263. package/src/compat/register/client-errors.ts +18 -0
  264. package/src/compat/register/config.ts +17 -0
  265. package/src/compat/register/css-extras.ts +120 -0
  266. package/src/compat/register/edge-runtime.ts +6 -0
  267. package/src/compat/register/errors.ts +46 -0
  268. package/src/compat/register/export.ts +23 -0
  269. package/src/compat/register/font.ts +36 -0
  270. package/src/compat/register/hooks.ts +34 -0
  271. package/src/compat/register/image.ts +133 -0
  272. package/src/compat/register/index.ts +111 -0
  273. package/src/compat/register/instrumentation-client.ts +35 -0
  274. package/src/compat/register/lifecycle.ts +86 -0
  275. package/src/compat/register/mdx.ts +48 -0
  276. package/src/compat/register/middleware.ts +36 -0
  277. package/src/compat/register/misc.ts +44 -0
  278. package/src/compat/register/otel.ts +288 -0
  279. package/src/compat/register/pages-api.ts +473 -0
  280. package/src/compat/register/ppr.ts +56 -0
  281. package/src/compat/register/protocol.ts +57 -0
  282. package/src/compat/register/proxy.ts +127 -0
  283. package/src/compat/register/render.ts +268 -0
  284. package/src/compat/register/routing.ts +410 -0
  285. package/src/compat/register/segment.ts +1903 -0
  286. package/src/compat/register/static-image.ts +21 -0
  287. package/src/compat/register/typed-routes.ts +35 -0
  288. package/src/compat/register/usecache.ts +131 -0
  289. package/src/compat/register/validation.ts +56 -0
  290. package/src/compat/segment/loading-boundary.ts +113 -0
  291. package/src/compat/segment/page-slot.ts +200 -0
  292. package/src/compat/segment/tree.ts +481 -0
  293. package/src/compat/segment/vary-key.ts +102 -0
  294. package/src/compat/segment/vary-params.ts +551 -0
  295. package/src/compat/static-params.ts +33 -0
  296. package/src/compat/tsconfig-defaults.ts +301 -0
  297. package/src/compat/typecheck/index.ts +1481 -0
  298. package/src/compat/typecheck/worker.ts +26 -0
  299. package/src/compat/typed-routes/index.ts +92 -0
  300. package/src/compat/typed-routes/manifest.ts +356 -0
  301. package/src/compat/typed-routes/typegen.ts +566 -0
  302. package/src/compat/validation/errors.ts +159 -0
  303. package/src/compat/validation/index.ts +1770 -0
  304. package/src/compat/validation/prerender-diagnostics.ts +1508 -0
  305. package/src/compat-bootstrap.ts +67 -0
  306. package/src/config.ts +218 -0
  307. package/src/css/build.ts +697 -0
  308. package/src/css/index.ts +2 -0
  309. package/src/css/postcss.ts +236 -0
  310. package/src/css/worker.ts +34 -0
  311. package/src/dev/client-actions.ts +35 -0
  312. package/src/dev/client-chunk-store.ts +92 -0
  313. package/src/dev/client-key-cache.ts +178 -0
  314. package/src/dev/global-css-cache.ts +212 -0
  315. package/src/dev/imports.ts +2430 -0
  316. package/src/dev/module-cache.ts +721 -0
  317. package/src/dev/module-generations.ts +38 -0
  318. package/src/dev/module-transform.ts +188 -0
  319. package/src/dev/node-module-bundle-cache.ts +63 -0
  320. package/src/dev/restart-cache.ts +10 -0
  321. package/src/dev/route-bundle-key-cache.ts +154 -0
  322. package/src/dev/route-facts-cache.ts +223 -0
  323. package/src/dev/server.ts +1710 -0
  324. package/src/dynamic/source.ts +307 -0
  325. package/src/dynamic/tree-shake.ts +262 -0
  326. package/src/env.ts +92 -0
  327. package/src/extensions.ts +1898 -0
  328. package/src/index.ts +34 -0
  329. package/src/internal.ts +43 -0
  330. package/src/islands/boundary-error.ts +8 -0
  331. package/src/islands/static-children.ts +37 -0
  332. package/src/islands/static-slots.ts +106 -0
  333. package/src/ppr-postpone.ts +24 -0
  334. package/src/ppr.ts +784 -0
  335. package/src/proxy.ts +752 -0
  336. package/src/render/hooks.ts +384 -0
  337. package/src/render/index.ts +1 -0
  338. package/src/render/island-context.ts +47 -0
  339. package/src/render/metadata.ts +857 -0
  340. package/src/render/renderer.ts +7391 -0
  341. package/src/render/resource-hints.ts +44 -0
  342. package/src/render/slots.tsx +679 -0
  343. package/src/request/context.ts +396 -0
  344. package/src/resolve/engine.ts +219 -0
  345. package/src/resolve/imports.ts +1104 -0
  346. package/src/resolve/scan-facts.ts +474 -0
  347. package/src/resolve/source-text.ts +86 -0
  348. package/src/routing/forwarded.ts +41 -0
  349. package/src/routing/handler.ts +271 -0
  350. package/src/routing/href.ts +203 -0
  351. package/src/routing/metadata.ts +1018 -0
  352. package/src/routing/request-runtime.ts +43 -0
  353. package/src/routing/routes.ts +2560 -0
  354. package/src/routing/slots.ts +432 -0
  355. package/src/runtime/server.ts +3453 -0
  356. package/src/runtime/vendor.ts +1160 -0
  357. package/src/style-modules.d.ts +9 -0
  358. package/src/typegen.ts +151 -0
  359. package/src/types.ts +725 -0
  360. package/src/utils/ansi.ts +9 -0
  361. package/src/utils/content-type.ts +31 -0
  362. package/src/utils/decode.ts +7 -0
  363. package/src/utils/dev-profile.ts +31 -0
  364. package/src/utils/error-log.ts +29 -0
  365. package/src/utils/fs-cache.ts +31 -0
  366. package/src/utils/fs.ts +119 -0
  367. package/src/utils/html.ts +46 -0
  368. package/src/utils/serialize.ts +378 -0
  369. package/src/utils/source.ts +35 -0
  370. package/src/utils/verbose.ts +39 -0
  371. package/tsconfig.json +10 -0
@@ -0,0 +1,458 @@
1
+ import { createRequire } from 'node:module';
2
+ import { access, mkdir, readdir, readFile, writeFile } from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import type { ResolvedConfig } from '../config';
5
+ import type { BuildManifest, RouteManifestEntry, StaticFileMetadata } from '../types';
6
+ import { nextCompatEnabled } from './index';
7
+ import { discoverStaticMetadataFiles } from '../routing/metadata';
8
+ import { toPosixPath } from '../utils/fs';
9
+
10
+ interface EmitMetadataRouteArtifactsContext {
11
+ config: ResolvedConfig;
12
+ manifest: BuildManifest;
13
+ }
14
+
15
+ interface RouteManifestFile {
16
+ version?: number;
17
+ middleware?: Record<string, Record<string, unknown>>;
18
+ functions?: Record<string, Record<string, unknown>>;
19
+ sortedMiddleware?: unknown[];
20
+ }
21
+
22
+ let foundGeistFontPath: string | undefined;
23
+
24
+ export async function emitMetadataRouteArtifacts(
25
+ ctx: EmitMetadataRouteArtifactsContext,
26
+ ): Promise<void> {
27
+ if (!nextCompatEnabled(ctx.config)) return;
28
+
29
+ const routes = ctx.manifest.routes.filter(
30
+ route => route.kind === 'handler' && route.metadataRoute !== undefined,
31
+ );
32
+ if (routes.length === 0) return;
33
+
34
+ const outPath = ctx.config.outPath;
35
+ const outputRoots = Array.from(
36
+ new Set([
37
+ outPath,
38
+ path.join(ctx.config.root, '.next'),
39
+ path.join(path.dirname(outPath), '.next'),
40
+ path.resolve(process.cwd(), '.next'),
41
+ ]),
42
+ );
43
+ const staticFiles = ctx.manifest.staticFiles ?? {};
44
+ const routeFilesById = staticFilesByRouteId(staticFiles);
45
+ const appDir = path.join(ctx.config.root, ctx.config.appDir);
46
+
47
+ const emittedRouteDirs = new Set<string>();
48
+
49
+ for (const route of routes) {
50
+ const nextPath = toAppPath(route, appDir);
51
+ const routeDir = removeLeadingSlash(nextPath);
52
+ emittedRouteDirs.add(routeDir);
53
+ // A dynamic-code metadata route handler executes user code, so Next lists
54
+ // its client-reference manifest in the route trace (route.js.nft.json) —
55
+ // the same shape as an app page's page_client-reference-manifest.js. The
56
+ // opengraph/icon image routes additionally trace the Geist font they load.
57
+ const fontPaths =
58
+ route.metadataRoute?.kind === 'opengraph-image' ? await resolveGeistFontFiles() : [];
59
+
60
+ for (const root of outputRoots) {
61
+ const routeModuleDir = path.join(root, 'server', 'app', routeDir);
62
+ await mkdir(routeModuleDir, { recursive: true });
63
+ await writeFile(path.join(routeModuleDir, 'route.js'), routeJsModule(route), 'utf8');
64
+ await writeFile(
65
+ path.join(routeModuleDir, 'route_client-reference-manifest.js'),
66
+ 'self.__RSC_MANIFEST={}\n',
67
+ 'utf8',
68
+ );
69
+ await writeFile(
70
+ path.join(routeModuleDir, 'route.js.nft.json'),
71
+ `${JSON.stringify(
72
+ { version: 1, files: ['route_client-reference-manifest.js', ...fontPaths] },
73
+ null,
74
+ 2,
75
+ )}\n`,
76
+ 'utf8',
77
+ );
78
+
79
+ if (isForceDynamicRoute(route)) continue;
80
+
81
+ const outputs = routeFilesById.get(route.id) ?? [];
82
+ for (const relative of outputs) {
83
+ await writeStaticMetadataArtifacts(outPath, root, relative, staticFiles[relative]);
84
+ }
85
+ }
86
+ }
87
+
88
+ await emitStaticMetadataRouteTraces(outputRoots, appDir, emittedRouteDirs);
89
+ await writeAppPathsManifest(outputRoots, routes, appDir);
90
+ await mergeMiddlewareFunctionsManifest(outputRoots, routes, appDir, ctx.manifest.routes);
91
+ await writePrerenderManifests(outputRoots, ctx.manifest);
92
+ }
93
+
94
+ const prerenderAllowHeader = [
95
+ 'host',
96
+ 'x-matched-path',
97
+ 'x-prerender-revalidate',
98
+ 'x-prerender-revalidate-if-generated',
99
+ 'x-next-revalidated-tags',
100
+ 'x-next-revalidate-tag-token',
101
+ ];
102
+
103
+ const prerenderBypass = [
104
+ { key: 'next-action', type: 'header' },
105
+ { key: 'content-type', type: 'header', value: 'multipart/form-data;.*' },
106
+ ];
107
+
108
+ async function writePrerenderManifests(outputRoots: string[], manifest: BuildManifest) {
109
+ const byId = new Map(manifest.routes.map(route => [route.id, route]));
110
+ const entries: Record<string, unknown> = {};
111
+
112
+ for (const [relative, metadata] of Object.entries(manifest.staticFiles ?? {})) {
113
+ const route = metadata.routeId ? byId.get(metadata.routeId) : undefined;
114
+ if (route && isEdgeRoute(route)) continue;
115
+ const pathname = staticFilePathname(relative);
116
+ entries[pathname] = prerenderEntry(pathname, metadata, route);
117
+ }
118
+
119
+ for (const route of manifest.routes) {
120
+ // A generated-param metadata route resolves to one concrete pathname per
121
+ // generated id; Next lists each as a prerendered route even though the
122
+ // pattern itself carries a param.
123
+ for (const generated of route.metadataRoute?.generatedRoutes ?? []) {
124
+ if (entries[generated] || isEdgeRoute(route) || route.usesRequest) continue;
125
+ entries[generated] = prerenderEntry(generated, undefined, route);
126
+ }
127
+ if (entries[route.route] || !isStaticPrerenderRoute(route)) continue;
128
+ entries[route.route] = prerenderEntry(route.route, undefined, route);
129
+ }
130
+
131
+ for (const root of outputRoots) {
132
+ const file = path.join(root, 'prerender-manifest.json');
133
+ const existing = await readJsonManifest<{
134
+ routes?: Record<string, unknown>;
135
+ dynamicRoutes?: Record<string, unknown>;
136
+ notFoundRoutes?: string[];
137
+ preview?: Record<string, string>;
138
+ }>(file);
139
+ await mkdir(path.dirname(file), { recursive: true });
140
+ await writeFile(
141
+ file,
142
+ `${JSON.stringify(
143
+ {
144
+ version: 4,
145
+ routes: { ...(existing?.routes ?? {}), ...entries },
146
+ dynamicRoutes: existing?.dynamicRoutes ?? {},
147
+ notFoundRoutes: existing?.notFoundRoutes ?? [],
148
+ preview: existing?.preview ?? {
149
+ previewModeId: 'pnext-preview-id',
150
+ previewModeSigningKey: 'pnext-preview-signing-key',
151
+ previewModeEncryptionKey: 'pnext-preview-encryption-key',
152
+ },
153
+ },
154
+ null,
155
+ 2,
156
+ )}\n`,
157
+ );
158
+ }
159
+ }
160
+
161
+ function staticFilePathname(relative: string) {
162
+ if (relative === 'index.html') return '/';
163
+ if (relative.endsWith('/index.html')) return `/${relative.slice(0, -'/index.html'.length)}`;
164
+ if (relative.endsWith('.html')) return `/${relative.slice(0, -'.html'.length)}`;
165
+ return `/${relative}`;
166
+ }
167
+
168
+ function isStaticPrerenderRoute(route: RouteManifestEntry) {
169
+ if (route.mode !== 'static' || route.usesRequest || isEdgeRoute(route)) return false;
170
+ if (route.kind === 'page') return route.params.length === 0 && !route.catchAll;
171
+ return route.kind === 'handler' && route.metadataRoute !== undefined && route.params.length === 0;
172
+ }
173
+
174
+ function isEdgeRoute(route: RouteManifestEntry) {
175
+ return (
176
+ route.segmentConfig?.runtime === 'edge' ||
177
+ route.segmentConfig?.runtime === 'experimental-edge'
178
+ );
179
+ }
180
+
181
+ function prerenderEntry(
182
+ pathname: string,
183
+ metadata: StaticFileMetadata | undefined,
184
+ route: RouteManifestEntry | undefined,
185
+ ) {
186
+ return {
187
+ initialRevalidateSeconds: metadata?.revalidateSeconds ?? false,
188
+ srcRoute: route?.route ?? pathname,
189
+ dataRoute: pathname === '/' ? '/index.rsc' : `${pathname}.rsc`,
190
+ allowHeader: prerenderAllowHeader,
191
+ experimentalBypassFor: prerenderBypass,
192
+ };
193
+ }
194
+
195
+ function staticFilesByRouteId(
196
+ staticFiles: Record<string, StaticFileMetadata>,
197
+ ): Map<string, string[]> {
198
+ const routeFilesById = new Map<string, string[]>();
199
+ for (const [relative, metadata] of Object.entries(staticFiles)) {
200
+ if (!metadata.routeId) continue;
201
+ const existing = routeFilesById.get(metadata.routeId) ?? [];
202
+ existing.push(relative);
203
+ routeFilesById.set(metadata.routeId, existing);
204
+ }
205
+ return routeFilesById;
206
+ }
207
+
208
+ /**
209
+ * Static metadata files (favicon.ico, static icon.png, ...) are served by Next as route handlers, so it
210
+ * emits a `route.js.nft.json` trace for each. No user code runs, so the trace never lists a
211
+ * client-reference manifest. Skip any file whose output dir already hosts a dynamic-code metadata route
212
+ * (a static icon.png cannot coexist with an icon.tsx anyway).
213
+ */
214
+ async function emitStaticMetadataRouteTraces(
215
+ outputRoots: string[],
216
+ appDir: string,
217
+ emittedRouteDirs: Set<string>,
218
+ ): Promise<void> {
219
+ for (const file of discoverStaticMetadataFiles(appDir)) {
220
+ const routeDir = file.outputPath;
221
+ if (emittedRouteDirs.has(routeDir)) continue;
222
+ for (const root of outputRoots) {
223
+ const dir = path.join(root, 'server', 'app', routeDir);
224
+ await mkdir(dir, { recursive: true });
225
+ await writeFile(path.join(dir, 'route.js'), 'export default {}\n', 'utf8');
226
+ await writeFile(
227
+ path.join(dir, 'route.js.nft.json'),
228
+ `${JSON.stringify({ version: 1, files: [] }, null, 2)}\n`,
229
+ 'utf8',
230
+ );
231
+ }
232
+ }
233
+ }
234
+
235
+ async function writeAppPathsManifest(
236
+ outputRoots: string[],
237
+ routes: RouteManifestEntry[],
238
+ appDir: string,
239
+ ): Promise<void> {
240
+ const nextEntries: Record<string, string> = {};
241
+ for (const route of routes) {
242
+ const appPath = toAppPath(route, appDir);
243
+ const key = `${appPath}/route`;
244
+ nextEntries[key] = `app${appPath}/route.js`;
245
+ }
246
+
247
+ for (const root of outputRoots) {
248
+ const manifestPath = path.join(root, 'server', 'app-paths-manifest.json');
249
+ const existing = (await readJsonManifest<Record<string, string>>(manifestPath)) ?? {};
250
+ await mkdir(path.dirname(manifestPath), { recursive: true });
251
+ await writeFile(
252
+ manifestPath,
253
+ `${JSON.stringify({ ...existing, ...nextEntries }, null, 2)}\n`,
254
+ );
255
+ }
256
+ }
257
+
258
+ async function mergeMiddlewareFunctionsManifest(
259
+ outputRoots: string[],
260
+ routes: RouteManifestEntry[],
261
+ appDir: string,
262
+ allRoutes: RouteManifestEntry[],
263
+ ): Promise<void> {
264
+ const edgeRoutes = routes.filter(
265
+ route => route.segmentConfig?.runtime === 'edge' || route.segmentConfig?.runtime === 'experimental-edge',
266
+ );
267
+ const edgePages = allRoutes.filter(route => route.kind === 'page' && isEdgeRoute(route));
268
+ if (edgeRoutes.length === 0 && edgePages.length === 0) return;
269
+
270
+ const routeEntries = edgeRoutes.map(route => ({ route: `${toAppPath(route, appDir)}/route`, value: {} }));
271
+ const sharedImageChunk = 'server/edge-chunks/image-response.js';
272
+ const hasImageResponseRoute = routes.some(route =>
273
+ ['opengraph-image', 'twitter-image', 'apple-icon', 'icon'].includes(
274
+ route.metadataRoute?.kind ?? '',
275
+ ),
276
+ );
277
+
278
+ for (const root of outputRoots) {
279
+ const manifestPath = path.join(root, 'server', 'middleware-manifest.json');
280
+ const manifest = await readJsonManifest<RouteManifestFile>(manifestPath);
281
+ const target: RouteManifestFile = {
282
+ version: 3,
283
+ sortedMiddleware: [],
284
+ middleware: {},
285
+ functions: {},
286
+ ...(manifest ?? {}),
287
+ };
288
+ target.functions = target.functions ?? {};
289
+ for (const { route, value } of routeEntries) {
290
+ target.functions[route] = target.functions[route] ?? value;
291
+ }
292
+ if (hasImageResponseRoute && edgePages.length > 0) {
293
+ const chunkPath = path.join(root, sharedImageChunk);
294
+ await mkdir(path.dirname(chunkPath), { recursive: true });
295
+ await writeFile(chunkPath, 'export const loadAdditionalAsset = true\n');
296
+ for (const page of edgePages) {
297
+ const key = page.route === '/' ? '/page' : `${page.route}/page`;
298
+ target.functions[key] = { files: [sharedImageChunk] };
299
+ }
300
+ }
301
+ await mkdir(path.dirname(manifestPath), { recursive: true });
302
+ await writeFile(manifestPath, `${JSON.stringify(target, null, 2)}\n`);
303
+ }
304
+ }
305
+
306
+ function isForceDynamicRoute(route: RouteManifestEntry): boolean {
307
+ return route.segmentConfig?.dynamic === 'force-dynamic';
308
+ }
309
+
310
+ function toRouteMeta(metadata: StaticFileMetadata): { status: number; headers: Record<string, string> } {
311
+ const headers: Record<string, string> = {};
312
+ for (const [name, value] of metadata.headers ?? []) {
313
+ headers[name.toLowerCase()] = value;
314
+ }
315
+ return {
316
+ status: metadata.status,
317
+ headers,
318
+ };
319
+ }
320
+
321
+ async function writeStaticMetadataArtifacts(
322
+ outPath: string,
323
+ root: string,
324
+ relative: string,
325
+ metadata: StaticFileMetadata | undefined,
326
+ ): Promise<void> {
327
+ if (!metadata) return;
328
+ const source = path.join(outPath, 'public', relative);
329
+ const outputBase = path.join(root, 'server', 'app', toPosixPath(relative));
330
+ await mkdir(path.dirname(outputBase), { recursive: true });
331
+ const routeMeta = JSON.stringify(toRouteMeta(metadata));
332
+ await writeFile(`${outputBase}.meta`, routeMeta, 'utf8');
333
+ try {
334
+ await access(source);
335
+ } catch {
336
+ return;
337
+ }
338
+ await writeFile(`${outputBase}.body`, await readFile(source));
339
+ }
340
+
341
+ function routeJsModule(route: RouteManifestEntry): string {
342
+ const runtime = route.segmentConfig?.runtime ?? 'nodejs';
343
+ const data = JSON.stringify({
344
+ segmentConfig: route.segmentConfig ?? null,
345
+ runtime,
346
+ metadataRoute: route.metadataRoute?.kind,
347
+ route: route.route,
348
+ });
349
+ return `export default ${data}\n`;
350
+ }
351
+
352
+ function toAppPath(route: RouteManifestEntry, appDir: string): string {
353
+ const generated = route.metadataRoute?.generatedParam;
354
+ const normalized = route.route.replace(/^\/+|\/+$/g, '');
355
+ const fileSegments = routeFileGroups(route.file, appDir);
356
+ const routeSegments = normalized.length > 0 ? normalized.split('/') : [];
357
+ const converted = routeSegments.map(segment => routeSegmentToNextPath(segment, generated));
358
+ const nextPathSegments = [...fileSegments, ...converted];
359
+ return `/${nextPathSegments.join('/')}`;
360
+ }
361
+
362
+ function routeSegmentToNextPath(segment: string, generatedParam?: string): string {
363
+ const match = /^:([^*.]+)(\*)?(\..*)?$/.exec(segment);
364
+ if (!match) return segment;
365
+ const name = match[1] ?? '';
366
+ const star = match[2] ? '...' : '';
367
+ const suffix = match[3] ?? '';
368
+ const key = generatedParam && name === 'id' ? generatedParam : name;
369
+ return `[${star}${key}]${generatedParam && name === 'id' ? '' : suffix}`;
370
+ }
371
+
372
+ function routeFileGroups(file: string, appDir: string): string[] {
373
+ const relative = toPosixPath(path.relative(appDir, file));
374
+ const parts = relative.split('/').filter(Boolean);
375
+ const withoutLeaf = parts.slice(0, -1);
376
+ const groups: string[] = [];
377
+ for (const segment of withoutLeaf) {
378
+ if (!segment.startsWith('(') || !segment.endsWith(')')) break;
379
+ groups.push(segment);
380
+ }
381
+ return groups;
382
+ }
383
+
384
+ function removeLeadingSlash(pathValue: string) {
385
+ return pathValue.replace(/^\//, '');
386
+ }
387
+
388
+ async function readJsonManifest<T>(filePath: string): Promise<T | undefined> {
389
+ try {
390
+ const raw = await readFile(filePath, 'utf8');
391
+ return JSON.parse(raw) as T;
392
+ } catch {
393
+ return undefined;
394
+ }
395
+ }
396
+
397
+ async function resolveGeistFontFiles(): Promise<string[]> {
398
+ if (foundGeistFontPath) return [foundGeistFontPath];
399
+ const req = createRequire(process.cwd() + '/');
400
+ const candidateRoots = resolveVercelOgRoots(req);
401
+ for (const root of candidateRoots) {
402
+ const files = await findFiles(root, 'Geist-Regular.ttf');
403
+ if (files.length === 0) continue;
404
+ foundGeistFontPath = files[0];
405
+ return files.slice(0, 1);
406
+ }
407
+ return [];
408
+ }
409
+
410
+ function resolveVercelOgRoots(req: ReturnType<typeof createRequire>): string[] {
411
+ const roots: string[] = [];
412
+ for (const spec of ['@vercel/og/package.json', 'next/package.json']) {
413
+ try {
414
+ roots.push(path.dirname(req.resolve(spec)));
415
+ } catch {
416
+ // package not present in the app; skip
417
+ }
418
+ }
419
+ return roots;
420
+ }
421
+
422
+ async function findFiles(root: string, targetName: string): Promise<string[]> {
423
+ const found: string[] = [];
424
+ const stack = [root];
425
+ const maxDepth = 6;
426
+ while (stack.length > 0) {
427
+ const current = stack.pop();
428
+ if (!current) continue;
429
+ const normalizedRoot = root.replace(/\\/g, '/');
430
+ const normalizedCurrent = current.replace(/\\/g, '/');
431
+ if (
432
+ normalizedCurrent.includes(`${path.sep}.next${path.sep}`) ||
433
+ normalizedCurrent.includes(`${path.sep}.git${path.sep}`) ||
434
+ normalizedCurrent.includes(`${path.sep}node_modules${path.sep}.cache${path.sep}`)
435
+ ) {
436
+ continue;
437
+ }
438
+ const depth = normalizedCurrent.split('/').length;
439
+ if (depth > normalizedRoot.split('/').length + maxDepth) continue;
440
+ let entries;
441
+ try {
442
+ entries = await readdir(current, { withFileTypes: true });
443
+ } catch {
444
+ continue;
445
+ }
446
+ for (const entry of entries) {
447
+ const child = path.join(current, entry.name);
448
+ if (entry.isDirectory()) {
449
+ stack.push(child);
450
+ continue;
451
+ }
452
+ if (entry.isFile() && entry.name === targetName) {
453
+ found.push(child);
454
+ }
455
+ }
456
+ }
457
+ return found;
458
+ }