@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,375 @@
1
+ /**
2
+ * Module warm-up for the vercel adapter - run in its own process.
3
+ *
4
+ * Request time on Vercel is read-only, so everything a production start would compile or vendor
5
+ * lazily has to be on disk already: this step compiles every module the production server can need
6
+ * into the build cache and imports the app's route handlers once so their on-demand vendor bundles
7
+ * get written now.
8
+ *
9
+ * Importing handlers runs the app's own server code, which can crash the runtime rather than throw,
10
+ * so the whole pass runs in a child that writes into the same on-disk build cache the parent reads
11
+ * back. Because that cache is on disk, a crash costs one file and not the pass: the child reports
12
+ * each file as it lands, and the parent restarts it with those files skipped until an attempt stops
13
+ * making progress.
14
+ *
15
+ * Ordering is load-bearing, not incidental. Compiles come first and handlers last: handler code
16
+ * running *concurrently* with the compile pass takes the runtime down, while the same compiles with
17
+ * handlers skipped, and the same handlers against a populated cache, both run clean.
18
+ *
19
+ * The child starts when the build starts, so its boot overlaps the build. It then compiles the page
20
+ * routes' server modules as soon as the route scan hands them over, and blocks on stdin for the
21
+ * go-ahead to finish the rest once the manifest is written.
22
+ */
23
+ import { existsSync } from 'node:fs';
24
+ import { readFile } from 'node:fs/promises';
25
+ import path from 'node:path';
26
+ import { fileURLToPath } from 'node:url';
27
+ import { loadConfig, pathToFileHref, type ResolvedConfig } from '../../config';
28
+ import { bootstrapCompat } from '../../compat-bootstrap';
29
+ import { ssrClientReference } from '../../client/reference';
30
+ import {
31
+ devClientModuleHref,
32
+ devServerModuleHref,
33
+ setEmitCompiledSpecifiersManifest,
34
+ } from '../../dev/imports';
35
+ import { getCompatModeExtensions } from '../../extensions';
36
+ import { findConventionFiles, findLayouts } from '../../routing/routes';
37
+ import { registerServerRuntime } from '../../runtime/server';
38
+ import { namedBunBinary } from '../named-bin';
39
+ import type { VerboseLogger } from '../../utils/verbose';
40
+ import type { BuildManifest } from '../../types';
41
+
42
+ // The child reports one line per file it finishes — `<source>` for an imported
43
+ // route handler, `<source>\t<compiled>` for a compiled module. Everything else
44
+ // it prints is app output the parent passes through.
45
+ const DONE_MARKER = 'pnext-warm-done:';
46
+
47
+ // Printed once compiles finish and before the handler loop starts: the
48
+ // compiled artifact set is already final at that boundary, so the parent can
49
+ // start tracing the node_modules closure while this process runs handlers.
50
+ const COMPILED_MARKER = 'pnext-warm-compiled';
51
+
52
+ /**
53
+ * What the parent sends over stdin, one JSON object per line. A `prewarm`
54
+ * message names page sources the child may start compiling right away; the
55
+ * `skip` message is the go-ahead for the full pass and always comes last.
56
+ */
57
+ interface WarmRequest {
58
+ /** Files a previous attempt already finished — or died on. */
59
+ skip: string[];
60
+ }
61
+ interface PrewarmRequest {
62
+ /** Page route sources, known from the route scan long before the manifest. */
63
+ prewarm: string[];
64
+ }
65
+
66
+ // An attempt still running after this long is not going to finish: something in
67
+ // the app's own code is holding the process. Bounded so the build completes
68
+ // instead of hanging forever.
69
+ const ATTEMPT_TIMEOUT_MS = 10 * 60_000;
70
+
71
+ // One clean pass, plus enough restarts to step over a couple of poisoned files
72
+ // before concluding the app cannot be warmed.
73
+ const MAX_ATTEMPTS = 3;
74
+
75
+ export interface WarmChild {
76
+ /**
77
+ * Hand the child the page sources from the route scan so it compiles them
78
+ * under the rest of the build. Optional and fire-and-forget: whatever it does
79
+ * not get to, `finish` compiles.
80
+ */
81
+ prewarm(files: string[]): void;
82
+ /**
83
+ * Release the child to warm, and collect the module paths it compiled. `onCompiled`, if given,
84
+ * fires once - as soon as the child reaches its handler phase - with the modules compiled so far,
85
+ * which is already the final set: the caller can start tracing the node_modules closure while the
86
+ * child runs handlers concurrently.
87
+ */
88
+ finish(log: VerboseLogger, onCompiled?: (modules: string[]) => void): Promise<string[]>;
89
+ }
90
+
91
+ type WarmProcess = Bun.Subprocess<'pipe', 'pipe', 'inherit'>;
92
+
93
+ /**
94
+ * Spawn the warm child. Call as early in the build as possible: it boots while the build runs and
95
+ * does no work until `finish`, which must be called only after the build manifest is on disk. Never
96
+ * throws - a warm-up that cannot start degrades to "no warmed modules", which `finish` reports.
97
+ */
98
+ export function startWarmChild(config: ResolvedConfig): WarmChild {
99
+ const spawn = () => spawnWarmProcess(config);
100
+ const first = spawn();
101
+ return {
102
+ prewarm(files) {
103
+ if (!first || files.length === 0) return;
104
+ try {
105
+ void first.stdin.write(`${JSON.stringify({ prewarm: files } satisfies PrewarmRequest)}\n`);
106
+ void first.stdin.flush();
107
+ } catch {
108
+ // broken pipe: the child is gone; `finish` reports why
109
+ }
110
+ },
111
+ finish: (log, onCompiled) => warmWithRestarts(first, spawn, log, onCompiled),
112
+ };
113
+ }
114
+
115
+ function spawnWarmProcess(config: ResolvedConfig): WarmProcess | undefined {
116
+ const entry = fileURLToPath(new URL(import.meta.url));
117
+ try {
118
+ return Bun.spawn(
119
+ [namedBunBinary('pnext-warm'), '--conditions=react-server', entry, config.root],
120
+ { cwd: config.root, stdin: 'pipe', stdout: 'pipe', stderr: 'inherit', env: process.env },
121
+ );
122
+ } catch {
123
+ return undefined; // no child (fork limit, unsupported platform)
124
+ }
125
+ }
126
+
127
+ async function warmWithRestarts(
128
+ first: WarmProcess | undefined,
129
+ spawn: () => WarmProcess | undefined,
130
+ log: VerboseLogger,
131
+ onCompiled?: (modules: string[]) => void,
132
+ ) {
133
+ // Source file -> compiled artifact. Handlers map to nothing but still count as
134
+ // finished, so a restart does not import them a second time.
135
+ const finished = new Map<string, string | undefined>();
136
+ const compiled = () => [...finished.values()].filter((file): file is string => Boolean(file));
137
+ // The marker can only mean "compiled set final" the first time it fires —
138
+ // whichever attempt reaches its own handler phase first.
139
+ let fired = false;
140
+ const fireOnCompiled = onCompiled
141
+ ? () => {
142
+ if (fired) return;
143
+ fired = true;
144
+ onCompiled(compiled());
145
+ }
146
+ : undefined;
147
+ let child = first;
148
+ for (let attempt = 1; attempt <= MAX_ATTEMPTS && child; attempt++) {
149
+ const before = finished.size;
150
+ const failure = await runAttempt(child, { skip: [...finished.keys()] }, finished, fireOnCompiled);
151
+ if (!failure) {
152
+ log.log(`warmed ${compiled().length} modules`);
153
+ return compiled();
154
+ }
155
+ // A restart only helps if the last one got somewhere; otherwise the first
156
+ // thing it would redo is what killed it.
157
+ child = finished.size > before && attempt < MAX_ATTEMPTS ? spawn() : undefined;
158
+ if (child) log.log(`warm-up ${failure} after ${finished.size} files; restarting past them`);
159
+ else warmIncomplete(failure, finished.size);
160
+ }
161
+ fireOnCompiled?.();
162
+ return compiled();
163
+ }
164
+
165
+ /** Runs one attempt to completion. Returns undefined on success, else why it died. */
166
+ async function runAttempt(
167
+ child: WarmProcess,
168
+ request: WarmRequest,
169
+ finished: Map<string, string | undefined>,
170
+ onCompiled?: () => void,
171
+ ) {
172
+ try {
173
+ // Writing the request and closing stdin is the go-ahead; until then the
174
+ // child sits parked after its boot (or busy on a prewarm batch).
175
+ void child.stdin.write(`${JSON.stringify(request)}\n`);
176
+ void child.stdin.end();
177
+ } catch {
178
+ // broken pipe: the child is already gone, and its exit below says why
179
+ }
180
+ const timeout = setTimeout(() => child.kill('SIGKILL'), ATTEMPT_TIMEOUT_MS);
181
+ timeout.unref?.();
182
+
183
+ // Streamed rather than buffered to completion: the compiled-phase marker
184
+ // has to reach the caller while this attempt is still running (the child's
185
+ // handler phase), not after the process exits.
186
+ const processLine = (line: string) => {
187
+ if (!line) return;
188
+ if (line === COMPILED_MARKER) {
189
+ onCompiled?.();
190
+ return;
191
+ }
192
+ if (!line.startsWith(DONE_MARKER)) {
193
+ console.log(line); // app output
194
+ return;
195
+ }
196
+ const [source, artifact] = line.slice(DONE_MARKER.length).split('\t');
197
+ if (source) finished.set(source, artifact || undefined);
198
+ };
199
+ const reader = child.stdout.getReader();
200
+ const decoder = new TextDecoder();
201
+ let buffer = '';
202
+ for (;;) {
203
+ const { done, value } = await reader.read();
204
+ if (done) break;
205
+ buffer += decoder.decode(value, { stream: true });
206
+ let newline: number;
207
+ while ((newline = buffer.indexOf('\n')) >= 0) {
208
+ processLine(buffer.slice(0, newline));
209
+ buffer = buffer.slice(newline + 1);
210
+ }
211
+ }
212
+ if (buffer) processLine(buffer);
213
+
214
+ const code = await child.exited.finally(() => clearTimeout(timeout));
215
+ if (code === 0) return undefined;
216
+ return child.signalCode ? `was killed by ${child.signalCode}` : `exited with code ${code}`;
217
+ }
218
+
219
+ function warmIncomplete(failure: string, done: number) {
220
+ console.warn(
221
+ `vercel adapter: module warm-up ${failure} after warming ${done} file(s). The function ships ` +
222
+ 'without the rest of its module cache and may fail to render those routes at request time, ' +
223
+ "where Vercel's filesystem is read-only.",
224
+ );
225
+ }
226
+
227
+ const report = (file: string, artifact?: string) => {
228
+ console.log(`${DONE_MARKER}${file}${artifact ? `\t${artifact}` : ''}`);
229
+ };
230
+
231
+ /** Every server module a page route pulls in: the page, its layouts, its conventions. */
232
+ function pageServerFiles(config: ResolvedConfig, routeFiles: Iterable<string>) {
233
+ const files = new Set<string>();
234
+ const globalNotFound = path.join(config.appPath, 'not-found.tsx');
235
+ if (existsSync(globalNotFound)) files.add(globalNotFound);
236
+ for (const routeFile of routeFiles) {
237
+ for (const file of [
238
+ routeFile,
239
+ ...findLayouts(config.appPath, routeFile),
240
+ ...['loading.tsx', 'error.tsx', 'not-found.tsx'].flatMap(name =>
241
+ findConventionFiles(config.appPath, routeFile, name),
242
+ ),
243
+ ]) {
244
+ if (existsSync(file)) files.add(file);
245
+ }
246
+ }
247
+ return files;
248
+ }
249
+
250
+ const compileServer = (config: ResolvedConfig, file: string) =>
251
+ devServerModuleHref(config, file, 'build').then(href => report(file, fileURLToPath(href)));
252
+
253
+ /**
254
+ * Compile the page routes' server modules from the build's route scan, long before the manifest
255
+ * exists. Artifacts are content-keyed on disk, so whatever lands here is a straight cache hit for the
256
+ * pass below - the point is to spend this CPU under the build's client stage. Nothing here runs app
257
+ * code, so it is safe to overlap (see the handler note below).
258
+ */
259
+ export async function prewarmPageModules(config: ResolvedConfig, routeFiles: string[]) {
260
+ if (!getCompatModeExtensions().reactEnabled(config)) return;
261
+ await Promise.all(
262
+ [...pageServerFiles(config, routeFiles)].map(file =>
263
+ compileServer(config, file).catch(() => undefined),
264
+ ),
265
+ );
266
+ }
267
+
268
+ /**
269
+ * The warm pass itself, in the child. Reports every file it finishes as it
270
+ * lands, so a parent restart can step over one that takes the process down.
271
+ */
272
+ export async function warmRouteModules(
273
+ config: ResolvedConfig,
274
+ manifest: BuildManifest,
275
+ skip: ReadonlySet<string> = new Set(),
276
+ ) {
277
+ const clientFiles = new Set<string>();
278
+ const handlers: BuildManifest['routes'] = [];
279
+ const pageRoutes: string[] = [];
280
+
281
+ for (const route of manifest.routes) {
282
+ if (route.kind === 'handler') {
283
+ if (!skip.has(route.file)) handlers.push(route);
284
+ continue;
285
+ }
286
+ pageRoutes.push(route.file);
287
+ for (const reference of route.clientReferences) {
288
+ if (ssrClientReference(reference) && existsSync(reference.file)) {
289
+ clientFiles.add(reference.file);
290
+ }
291
+ }
292
+ }
293
+
294
+ // Without react compat the runtime imports page sources directly (Bun
295
+ // transforms in memory); the compiled build cache is only used with compat.
296
+ if (getCompatModeExtensions().reactEnabled(config)) {
297
+ await Promise.all([
298
+ ...[...pageServerFiles(config, pageRoutes)]
299
+ .filter(file => !skip.has(file))
300
+ .map(file => compileServer(config, file)),
301
+ ...[...clientFiles]
302
+ .filter(file => !skip.has(file))
303
+ .map(file =>
304
+ devClientModuleHref(config, file, 'build').then(href =>
305
+ report(file, fileURLToPath(href)),
306
+ ),
307
+ ),
308
+ ]);
309
+ }
310
+ console.log(COMPILED_MARKER);
311
+
312
+ // Handlers come last, and only once nothing else is in flight. Importing them runs the app's own
313
+ // server code (auth, db pools, telemetry), and that code running *concurrently* with the compile
314
+ // pass is what takes the runtime down - the same pass with handlers skipped never crashes, and
315
+ // handlers alone against a populated cache never crash. Doing them after the compiles also means a
316
+ // crash here costs only the remaining handlers, not the whole module pass.
317
+ for (const route of handlers) {
318
+ registerServerRuntime(config, route.sourceFiles);
319
+ // Reported before the import, not after: handlers are imported one at a
320
+ // time, so a handler that takes the process down is unambiguous and a
321
+ // restart must not run it again (Bun caches a failed import for the
322
+ // process' lifetime anyway, so a retry could not succeed either).
323
+ report(route.file);
324
+ try {
325
+ await import(pathToFileHref(route.file));
326
+ } catch (error) {
327
+ console.warn(`vercel adapter: importing ${route.file} failed during warmup:`, error);
328
+ }
329
+ }
330
+ }
331
+
332
+ /**
333
+ * Read the parent's line-delimited requests until the `skip` message, running
334
+ * each prewarm batch as it arrives. Returns the final request.
335
+ */
336
+ async function readWarmRequests(config: ResolvedConfig): Promise<Partial<WarmRequest>> {
337
+ let buffer = '';
338
+ const decoder = new TextDecoder();
339
+ const reader = Bun.stdin.stream().getReader();
340
+ for (;;) {
341
+ const { done, value } = await reader.read();
342
+ if (done) break;
343
+ buffer += decoder.decode(value, { stream: true });
344
+ let newline: number;
345
+ while ((newline = buffer.indexOf('\n')) >= 0) {
346
+ const line = buffer.slice(0, newline).trim();
347
+ buffer = buffer.slice(newline + 1);
348
+ if (!line) continue;
349
+ const message = JSON.parse(line) as Partial<WarmRequest & PrewarmRequest>;
350
+ if (message.skip) return message;
351
+ if (message.prewarm) await prewarmPageModules(config, message.prewarm);
352
+ }
353
+ }
354
+ const rest = buffer.trim();
355
+ return rest ? (JSON.parse(rest) as Partial<WarmRequest>) : {};
356
+ }
357
+
358
+ if (import.meta.main) {
359
+ const root = process.argv[2];
360
+ const config = await loadConfig(root);
361
+ await bootstrapCompat(config);
362
+ // This process only ever runs for a vercel-adapter build; record each
363
+ // artifact's specifiers so the parent's trace step can read them back.
364
+ setEmitCompiledSpecifiersManifest(true);
365
+ // Blocks until the parent sends the go-ahead, i.e. until the manifest is
366
+ // written; a prewarm batch may arrive and run before that.
367
+ const request = await readWarmRequests(config);
368
+ const manifest = JSON.parse(
369
+ await readFile(path.join(config.outPath, 'manifest.json'), 'utf8'),
370
+ ) as BuildManifest;
371
+ await warmRouteModules(config, manifest, new Set(request.skip ?? []));
372
+ // App code reached through a route handler can leave the loop alive (a db
373
+ // pool, a stray interval); the warm pass is done either way.
374
+ process.exit(0);
375
+ }