@wular/pnext 0.1.6 → 0.1.8

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 (337) hide show
  1. package/bin/pnext +9 -2
  2. package/dist/server/_chunks/aliases-pycbtjt1.js +46 -0
  3. package/dist/server/_chunks/analyze-4d9e00g9.js +449 -0
  4. package/dist/server/_chunks/boot-bhemypxz.js +38 -0
  5. package/dist/server/_chunks/build-c991dv65.js +86 -0
  6. package/dist/server/_chunks/build-kh5e3x48.js +3341 -0
  7. package/dist/server/_chunks/build-tier-0a96kmx3.js +2456 -0
  8. package/dist/server/_chunks/compile-040r79gj.js +22 -0
  9. package/dist/server/_chunks/config-0tvz03a6.js +24 -0
  10. package/dist/server/_chunks/config-27rj7830.js +36 -0
  11. package/dist/server/_chunks/create-9rvwshsp.js +135 -0
  12. package/dist/server/_chunks/dev-ex9exynt.js +220 -0
  13. package/dist/server/_chunks/esbuild-yyktfrtt.js +15 -0
  14. package/dist/server/_chunks/generate-myw9hef7.js +22 -0
  15. package/dist/server/_chunks/index-0r5eqfc7.js +279 -0
  16. package/dist/server/_chunks/index-0yjv5v47.js +105 -0
  17. package/dist/server/_chunks/index-11xpbfej.js +17 -0
  18. package/dist/server/_chunks/index-141vcwk6.js +109 -0
  19. package/dist/server/_chunks/index-1pzm1hdy.js +4130 -0
  20. package/dist/server/_chunks/index-29pq0kax.js +590 -0
  21. package/dist/server/_chunks/index-2vz0wzdn.js +59 -0
  22. package/dist/server/_chunks/index-2wfv4kvx.js +182 -0
  23. package/dist/server/_chunks/index-38xpdxwd.js +194 -0
  24. package/dist/server/_chunks/index-3e075kny.js +128 -0
  25. package/dist/server/_chunks/index-3ycf5ckv.js +472 -0
  26. package/dist/server/_chunks/index-4399bvd2.js +18 -0
  27. package/dist/server/_chunks/index-4da76t62.js +297 -0
  28. package/dist/server/_chunks/index-4t92hdxd.js +172 -0
  29. package/dist/server/_chunks/index-4zzebszd.js +10 -0
  30. package/dist/server/_chunks/index-52k54ykj.js +95 -0
  31. package/dist/server/_chunks/index-5hr4062s.js +70 -0
  32. package/dist/server/_chunks/index-68m3mwbd.js +84 -0
  33. package/dist/server/_chunks/index-6b009mt0.js +56 -0
  34. package/dist/server/_chunks/index-6gex3pfa.js +15 -0
  35. package/dist/server/_chunks/index-6kp9r0d9.js +11 -0
  36. package/dist/server/_chunks/index-6q7zvrap.js +134 -0
  37. package/dist/server/_chunks/index-71885zaq.js +284 -0
  38. package/dist/server/_chunks/index-73z4esab.js +38 -0
  39. package/dist/server/_chunks/index-79ngvam8.js +60 -0
  40. package/dist/server/_chunks/index-7wc9n8be.js +25 -0
  41. package/dist/server/_chunks/index-8ct7rqy3.js +198 -0
  42. package/dist/server/_chunks/index-8kcxdfya.js +206 -0
  43. package/dist/server/_chunks/index-9ch50vtq.js +18 -0
  44. package/dist/server/_chunks/index-9f49w76j.js +213 -0
  45. package/dist/server/_chunks/index-9hz3s0m8.js +851 -0
  46. package/dist/server/_chunks/index-akkrvjn6.js +535 -0
  47. package/dist/server/_chunks/index-b6wtkdp4.js +24 -0
  48. package/dist/server/_chunks/index-b7j671dj.js +207 -0
  49. package/dist/server/_chunks/index-bcws5eh2.js +35 -0
  50. package/dist/server/_chunks/index-bzd2ef7t.js +10 -0
  51. package/dist/server/_chunks/index-cjgqs13g.js +65 -0
  52. package/dist/server/_chunks/index-ckkdpht5.js +41 -0
  53. package/dist/server/_chunks/index-cn86z041.js +296 -0
  54. package/dist/server/_chunks/index-cvr4z22m.js +92 -0
  55. package/dist/server/_chunks/index-cyfednwb.js +87 -0
  56. package/dist/server/_chunks/index-d158y67j.js +152 -0
  57. package/dist/server/_chunks/index-d1jsmhhk.js +955 -0
  58. package/dist/server/_chunks/index-dg0f05zs.js +199 -0
  59. package/dist/server/_chunks/index-dgr390q7.js +9438 -0
  60. package/dist/server/_chunks/index-drwv61cc.js +185 -0
  61. package/dist/server/_chunks/index-e3a6yx84.js +18 -0
  62. package/dist/server/_chunks/index-e88tyv35.js +45 -0
  63. package/dist/server/_chunks/index-en7n9f7m.js +22 -0
  64. package/dist/server/_chunks/index-entm8bmz.js +28 -0
  65. package/dist/server/_chunks/index-evhd413j.js +57 -0
  66. package/dist/server/_chunks/index-ezgj0tr1.js +88 -0
  67. package/dist/server/_chunks/index-fjv96re1.js +5295 -0
  68. package/dist/server/_chunks/index-fn1chkkd.js +214 -0
  69. package/dist/server/_chunks/index-fp8r0sqs.js +64 -0
  70. package/dist/server/_chunks/index-gcmj16xy.js +92 -0
  71. package/dist/server/_chunks/index-gkndxkxf.js +736 -0
  72. package/dist/server/_chunks/index-grta8ap3.js +238 -0
  73. package/dist/server/_chunks/index-h2a70tg4.js +7 -0
  74. package/dist/server/_chunks/index-h4xy648y.js +51 -0
  75. package/dist/server/_chunks/index-hdbwtdv2.js +352 -0
  76. package/dist/server/_chunks/index-he6n2bvp.js +1270 -0
  77. package/dist/server/_chunks/index-j0m1jxqa.js +1253 -0
  78. package/dist/server/_chunks/index-j2zrcp1k.js +66 -0
  79. package/dist/server/_chunks/index-j681c48a.js +2530 -0
  80. package/dist/server/_chunks/index-jbj7ehef.js +50 -0
  81. package/dist/server/_chunks/index-jcsjq3d1.js +20 -0
  82. package/dist/server/_chunks/index-jks0x0a1.js +14 -0
  83. package/dist/server/_chunks/index-jn9rbhrx.js +1599 -0
  84. package/dist/server/_chunks/index-jt8e1pje.js +12 -0
  85. package/dist/server/_chunks/index-kdhxpwyq.js +483 -0
  86. package/dist/server/_chunks/index-knp0s912.js +7 -0
  87. package/dist/server/_chunks/index-kqyy1d4f.js +50 -0
  88. package/dist/server/_chunks/index-kresp2n8.js +445 -0
  89. package/dist/server/_chunks/index-m63czgq5.js +590 -0
  90. package/dist/server/_chunks/index-ms9v9tnx.js +31 -0
  91. package/dist/server/_chunks/index-n4hxpng2.js +11 -0
  92. package/dist/server/_chunks/index-n629dy38.js +1071 -0
  93. package/dist/server/_chunks/index-nf3df4jy.js +266 -0
  94. package/dist/server/_chunks/index-nqh3xhdc.js +57 -0
  95. package/dist/server/_chunks/index-pym1cezq.js +39 -0
  96. package/dist/server/_chunks/index-q3r9z8mq.js +213 -0
  97. package/dist/server/_chunks/index-q738kkhj.js +100 -0
  98. package/dist/server/_chunks/index-qcrvt6er.js +112 -0
  99. package/dist/server/_chunks/index-qjj6gddn.js +54 -0
  100. package/dist/server/_chunks/index-qpwsgt3a.js +158 -0
  101. package/dist/server/_chunks/index-r97ptz1q.js +97 -0
  102. package/dist/server/_chunks/index-ras0sdab.js +26 -0
  103. package/dist/server/_chunks/index-rcs322t1.js +19 -0
  104. package/dist/server/_chunks/index-rgj5mx84.js +101 -0
  105. package/dist/server/_chunks/index-rjegyfx4.js +1435 -0
  106. package/dist/server/_chunks/index-rt9qq1va.js +4 -0
  107. package/dist/server/_chunks/index-rthrsed5.js +356 -0
  108. package/dist/server/_chunks/index-sq3kvz3g.js +200 -0
  109. package/dist/server/_chunks/index-stbk3jhn.js +31 -0
  110. package/dist/server/_chunks/index-tf4j19ge.js +130 -0
  111. package/dist/server/_chunks/index-tgcakdxc.js +125 -0
  112. package/dist/server/_chunks/index-tgsfjmep.js +74 -0
  113. package/dist/server/_chunks/index-tq1f96v7.js +51 -0
  114. package/dist/server/_chunks/index-tq3b39a5.js +107 -0
  115. package/dist/server/_chunks/index-typcbcsv.js +819 -0
  116. package/dist/server/_chunks/index-v1ags1na.js +132 -0
  117. package/dist/server/_chunks/index-vmr35jjw.js +170 -0
  118. package/dist/server/_chunks/index-vvq7rqtn.js +329 -0
  119. package/dist/server/_chunks/index-vz0km5qk.js +33 -0
  120. package/dist/server/_chunks/index-w6h8m6vp.js +138 -0
  121. package/dist/server/_chunks/index-web361b8.js +138 -0
  122. package/dist/server/_chunks/index-wm36rj4v.js +311 -0
  123. package/dist/server/_chunks/index-x0y005nh.js +283 -0
  124. package/dist/server/_chunks/index-x2m17v9c.js +6166 -0
  125. package/dist/server/_chunks/index-x3yn4ywm.js +22 -0
  126. package/dist/server/_chunks/index-x9c55pzy.js +871 -0
  127. package/dist/server/_chunks/index-xh1nbk46.js +1299 -0
  128. package/dist/server/_chunks/index-xvj80c3a.js +30 -0
  129. package/dist/server/_chunks/index-xywjg2vc.js +100 -0
  130. package/dist/server/_chunks/index-y4d02znn.js +66 -0
  131. package/dist/server/_chunks/index-y7mzvq2q.js +110 -0
  132. package/dist/server/_chunks/index-ye9hmsvf.js +47 -0
  133. package/dist/server/_chunks/index-yhxkxghe.js +56 -0
  134. package/dist/server/_chunks/index-yrjkqtfj.js +86 -0
  135. package/dist/server/_chunks/index-z88qv16t.js +11 -0
  136. package/dist/server/_chunks/index-zfrwq472.js +154 -0
  137. package/dist/server/_chunks/index-zqpqyg8p.js +666 -0
  138. package/dist/server/_chunks/loader-5en7wpt5.js +80 -0
  139. package/dist/server/_chunks/modules-t92favpj.js +76 -0
  140. package/dist/server/_chunks/pipeline-4t9q43ht.js +836 -0
  141. package/dist/server/_chunks/production-385bw8df.js +55 -0
  142. package/dist/server/_chunks/proxy-config-60gprphe.js +23 -0
  143. package/dist/server/_chunks/proxy-gfhmktbk.js +35 -0
  144. package/dist/server/_chunks/router-xnrva921.js +501 -0
  145. package/dist/server/_chunks/routes-ht868pdc.js +66 -0
  146. package/dist/server/_chunks/run-d40d63ag.js +697 -0
  147. package/dist/server/_chunks/server-2p8fgqq2.js +1839 -0
  148. package/dist/server/_chunks/tsconfig-defaults-bcn34eqb.js +21 -0
  149. package/dist/server/_chunks/typegen-dvtcjtaw.js +37 -0
  150. package/dist/server/api/client-cache.js +14 -0
  151. package/dist/server/cli/index.js +375 -0
  152. package/dist/server/cli/start.js +158 -0
  153. package/dist/server/client/reference.js +16 -0
  154. package/dist/server/compat/next/cache.js +56 -0
  155. package/dist/server/compat/next/canonical-url.js +13 -0
  156. package/dist/server/compat/next/client-cache.js +57 -0
  157. package/dist/server/compat/next/client-navigation.js +232 -0
  158. package/dist/server/compat/next/client-only.js +1 -0
  159. package/dist/server/compat/next/client-script.js +178 -0
  160. package/dist/server/compat/next/client-server.js +34 -0
  161. package/dist/server/compat/next/config-headers.js +34 -0
  162. package/dist/server/compat/next/config-loader.js +25 -0
  163. package/dist/server/compat/next/config.js +10 -0
  164. package/dist/server/compat/next/constants.js +18 -0
  165. package/dist/server/compat/next/custom-server.js +10 -0
  166. package/dist/server/compat/next/dist/client/components/app-router-headers.js +48 -0
  167. package/dist/server/compat/next/dist/server/web/spec-extension/revalidate.js +27 -0
  168. package/dist/server/compat/next/dist/server/web/spec-extension/unstable-cache.js +25 -0
  169. package/dist/server/compat/next/dist/server/web/spec-extension/unstable-no-store.js +25 -0
  170. package/dist/server/compat/next/dynamic.js +21 -0
  171. package/dist/server/compat/next/error.js +112 -0
  172. package/dist/server/compat/next/font/cache.js +16 -0
  173. package/dist/server/compat/next/font/google.js +3 -0
  174. package/dist/server/compat/next/font/index.js +1 -0
  175. package/dist/server/compat/next/font/local.js +24 -0
  176. package/dist/server/compat/next/font/runtime-client.js +33 -0
  177. package/dist/server/compat/next/font/runtime.js +43 -0
  178. package/dist/server/compat/next/font/shared.js +22 -0
  179. package/dist/server/compat/next/form.js +129 -0
  180. package/dist/server/compat/next/head.js +10 -0
  181. package/dist/server/compat/next/headers.js +30 -0
  182. package/dist/server/compat/next/image/client.js +11 -0
  183. package/dist/server/compat/next/image/config.js +18 -0
  184. package/dist/server/compat/next/image/optimizer.js +25 -0
  185. package/dist/server/compat/next/image/patterns.js +12 -0
  186. package/dist/server/compat/next/image/props.js +16 -0
  187. package/dist/server/compat/next/image/shared.js +86 -0
  188. package/dist/server/compat/next/image/static-metadata.js +32 -0
  189. package/dist/server/compat/next/image/validate.js +8 -0
  190. package/dist/server/compat/next/image.js +59 -0
  191. package/dist/server/compat/next/index.js +1 -0
  192. package/dist/server/compat/next/legacy-image.js +78 -0
  193. package/dist/server/compat/next/legacy-request-apis.js +24 -0
  194. package/dist/server/compat/next/link-transform.js +15 -0
  195. package/dist/server/compat/next/link.js +14 -0
  196. package/dist/server/compat/next/navigation.js +191 -0
  197. package/dist/server/compat/next/offline.js +45 -0
  198. package/dist/server/compat/next/og.js +8 -0
  199. package/dist/server/compat/next/preferred-region.js +8 -0
  200. package/dist/server/compat/next/redirects.js +32 -0
  201. package/dist/server/compat/next/resource-hints.js +30 -0
  202. package/dist/server/compat/next/rewrites.js +43 -0
  203. package/dist/server/compat/next/root-params.js +121 -0
  204. package/dist/server/compat/next/route-state.js +23 -0
  205. package/dist/server/compat/next/router.js +103 -0
  206. package/dist/server/compat/next/script.js +37 -0
  207. package/dist/server/compat/next/server-only.js +1 -0
  208. package/dist/server/compat/next/server.js +131 -0
  209. package/dist/server/compat/next/svgr.js +14 -0
  210. package/dist/server/compat/next/telemetry.js +10 -0
  211. package/dist/server/compat/next/usage.js +13 -0
  212. package/dist/server/compat/next/user-agent.js +12 -0
  213. package/dist/server/compat/next/web-vitals.js +35 -0
  214. package/dist/server/compat/react/action-state.js +11 -0
  215. package/dist/server/compat/react/client-lite.js +83 -0
  216. package/dist/server/compat/react/client.js +131 -0
  217. package/dist/server/compat/react/compiler-runtime.js +42 -0
  218. package/dist/server/compat/react/dom-client.js +106 -0
  219. package/dist/server/compat/react/dom-react-server.js +37 -0
  220. package/dist/server/compat/react/dom-server.js +40 -0
  221. package/dist/server/compat/react/dom.js +52 -0
  222. package/dist/server/compat/react/hooks-extra.js +12 -0
  223. package/dist/server/compat/react/internals.js +14 -0
  224. package/dist/server/compat/react/parity.js +11 -0
  225. package/dist/server/compat/react/preact.js +113 -0
  226. package/dist/server/compat/react/react-server.js +133 -0
  227. package/dist/server/compat/react/router-shim.js +8 -0
  228. package/dist/server/compat/react/server-component-use.js +14 -0
  229. package/dist/server/compat/react/server-inserted-html.js +14 -0
  230. package/dist/server/compat/react/server.js +194 -0
  231. package/dist/server/compat/react/style-values.js +10 -0
  232. package/dist/server/compat/react/use.js +10 -0
  233. package/dist/server/compat/react/view-transition.js +12 -0
  234. package/dist/server/generation.json +1 -0
  235. package/package.json +4 -1
  236. package/reference/compat.md +1 -1
  237. package/reference/config.md +2 -2
  238. package/reference/dev.md +1 -1
  239. package/reference/getting-started.md +1 -1
  240. package/reference/rendering.md +4 -4
  241. package/src/api/dynamic.tsx +86 -4
  242. package/src/api/server.ts +24 -6
  243. package/src/cli/adapters/vercel-warm.ts +327 -62
  244. package/src/cli/adapters/vercel.ts +164 -1054
  245. package/src/cli/analyze.ts +3 -2
  246. package/src/cli/build/cache.ts +6 -6
  247. package/src/cli/build.ts +78 -45
  248. package/src/cli/index.ts +21 -3
  249. package/src/cli/serve/immutable.ts +31 -0
  250. package/src/cli/serve/pipeline.ts +97 -93
  251. package/src/cli/serve/standalone-worker.ts +8 -0
  252. package/src/cli/serve/standalone.ts +703 -0
  253. package/src/cli/start.ts +31 -8
  254. package/src/client/build.ts +1 -1
  255. package/src/client/chunk-fold.ts +19 -6
  256. package/src/client/react-tier.ts +3 -2
  257. package/src/client/reference-stub.ts +23 -36
  258. package/src/compat/actions/client-plugin.ts +4 -2
  259. package/src/compat/actions/config.ts +6 -5
  260. package/src/compat/actions/extensions.ts +5 -5
  261. package/src/compat/aliases.ts +8 -1
  262. package/src/compat/bundler/config.ts +88 -0
  263. package/src/compat/bundler/optimize-package-imports.ts +86 -26
  264. package/src/compat/bundler/relay-transform.ts +15 -3
  265. package/src/compat/bundler/require-context.ts +2 -1
  266. package/src/compat/bundler/webpack-loaders.ts +3 -2
  267. package/src/compat/bundler/worker.ts +2 -2
  268. package/src/compat/cache-control.ts +16 -8
  269. package/src/compat/css/inline-css.ts +1 -1
  270. package/src/compat/css/modules.ts +18 -5
  271. package/src/compat/export/build-complete.ts +1 -1
  272. package/src/compat/export/emit.ts +4 -4
  273. package/src/compat/export/standalone.ts +30 -65
  274. package/src/compat/image-optimizer/optimize.ts +1 -1
  275. package/src/compat/lifecycle/error-funnel.ts +1 -1
  276. package/src/compat/lifecycle/instrumentation-client.ts +4 -3
  277. package/src/compat/lifecycle/instrumentation.ts +117 -24
  278. package/src/compat/lifecycle/testmode.ts +3 -2
  279. package/src/compat/metadata-artifacts.ts +1 -1
  280. package/src/compat/next/config-loader.ts +140 -13
  281. package/src/compat/next/dynamic.tsx +10 -23
  282. package/src/compat/next/font/cache.ts +2 -1
  283. package/src/compat/next/font/runtime.ts +23 -3
  284. package/src/compat/next/og.ts +3 -3
  285. package/src/compat/next/usage.ts +3 -2
  286. package/src/compat/pages/api.ts +83 -14
  287. package/src/compat/pages/router.ts +30 -14
  288. package/src/compat/register/bundler.ts +3 -1
  289. package/src/compat/register/image.ts +1 -1
  290. package/src/compat/register/middleware.ts +1 -1
  291. package/src/compat/register/otel.ts +5 -9
  292. package/src/compat/register/render.ts +3 -1
  293. package/src/compat/register/use-cache.ts +3 -1
  294. package/src/compat/release.ts +46 -0
  295. package/src/compat/segment/serve.ts +1 -1
  296. package/src/compat/typecheck/check.ts +6 -4
  297. package/src/compat/validation/validate.ts +10 -7
  298. package/src/config.ts +76 -9
  299. package/src/css/assets.ts +213 -0
  300. package/src/css/build.ts +190 -247
  301. package/src/dev/client-chunk-store.ts +2 -1
  302. package/src/dev/restart/client-key.ts +2 -1
  303. package/src/dev/restart/global-css.ts +2 -1
  304. package/src/dev/restart/route-bundle-key.ts +2 -1
  305. package/src/dev/restart/route-facts.ts +2 -1
  306. package/src/dev/server.ts +34 -14
  307. package/src/extensions.ts +4 -0
  308. package/src/out-paths.ts +10 -0
  309. package/src/render/hooks.ts +13 -0
  310. package/src/render/renderer.ts +53 -33
  311. package/src/request/context.ts +9 -0
  312. package/src/resolve/dynamic.ts +7 -1
  313. package/src/resolve/engine.ts +2 -12
  314. package/src/resolve/imports.ts +12 -52
  315. package/src/resolve/package-json.ts +56 -0
  316. package/src/resolve/scan-facts.ts +250 -1
  317. package/src/routing/href.ts +10 -3
  318. package/src/routing/match.ts +287 -0
  319. package/src/routing/metadata-files.ts +20 -6
  320. package/src/routing/proxy-config.ts +137 -0
  321. package/src/routing/proxy.ts +35 -134
  322. package/src/routing/routes.ts +22 -281
  323. package/src/runtime/fingerprint.ts +23 -8
  324. package/src/runtime/load.ts +170 -0
  325. package/src/runtime/loader.ts +218 -44
  326. package/src/runtime/module-cache.ts +15 -1
  327. package/src/runtime/modules.ts +405 -82
  328. package/src/runtime/prebundle.ts +101 -0
  329. package/src/runtime/production.ts +456 -0
  330. package/src/runtime/release-graph.ts +342 -0
  331. package/src/runtime/vendor-build.ts +750 -17
  332. package/src/runtime/vendor.ts +16 -3
  333. package/src/types.ts +4 -3
  334. package/src/utils/directive.ts +40 -0
  335. package/src/utils/fs.ts +95 -4
  336. package/src/utils/resource-query.ts +12 -0
  337. package/src/cli/serve/entry.ts +0 -45
@@ -0,0 +1,101 @@
1
+ // The published package runs production from dist/server (scripts/prebundle.ts). There, app imports
2
+ // of framework source resolve to the same prebundled modules, so the process holds one instance of
3
+ // each registry. A source checkout has no prebundle and resolves source as before.
4
+ import { readFileSync } from 'node:fs'
5
+ import path from 'node:path'
6
+ import { fileURLToPath } from 'node:url'
7
+
8
+ /** Source modules production can import: the start entry and everything app code reaches at runtime. */
9
+ export const runtimeEntryFiles = ['cli/start.ts', 'index.ts', 'internal.ts', 'client/reference.ts']
10
+ export const runtimeEntryDirs = ['api', 'compat/next', 'compat/react']
11
+
12
+ /** Written last by the prebundle: dist is complete, and built from this version and source. */
13
+ export const PREBUNDLE_STAMP = path.join('dist', 'server', 'generation.json')
14
+
15
+ export interface PrebundleStamp {
16
+ version: string
17
+ fingerprint: string
18
+ /** Package-relative sources dist imports rather than inlines: the public API closure. */
19
+ source: string[]
20
+ }
21
+
22
+ declare const PNEXT_PREBUNDLE:
23
+ { version: string; fingerprint: string; entries: string[] } | undefined
24
+
25
+ const prebundle = typeof PNEXT_PREBUNDLE === 'object' ? PNEXT_PREBUNDLE : undefined
26
+ const packageRoot = path.resolve(import.meta.dirname, '..', '..')
27
+ const srcRoot = path.join(packageRoot, 'src') + path.sep
28
+ const distRoot = path.join(packageRoot, 'dist', 'server')
29
+ const entries = new Set(prebundle?.entries)
30
+
31
+ function packageVersion(root: string) {
32
+ return (JSON.parse(readFileSync(path.join(root, 'package.json'), 'utf8')) as { version?: string })
33
+ .version
34
+ }
35
+
36
+ /** The framework's prebundle stamp when its dist is complete and built from `fingerprint`'s source. */
37
+ export function readPrebundleStamp(frameworkRoot: string, fingerprint: string) {
38
+ let stamp: PrebundleStamp
39
+ try {
40
+ stamp = JSON.parse(
41
+ readFileSync(path.join(frameworkRoot, PREBUNDLE_STAMP), 'utf8'),
42
+ ) as PrebundleStamp
43
+ } catch {
44
+ return undefined
45
+ }
46
+ return stamp.fingerprint === fingerprint && stamp.version === packageVersion(frameworkRoot)
47
+ ? stamp
48
+ : undefined
49
+ }
50
+
51
+ /** The prebundled counterpart of a framework source module, else `file` unchanged. */
52
+ export function prebundledFile(file: string): string {
53
+ if (!prebundle || !file.startsWith(srcRoot)) return file
54
+ const entry = file.slice(srcRoot.length).replace(/\.tsx?$/, '')
55
+ return entries.has(entry) ? path.join(distRoot, `${entry}.js`) : file
56
+ }
57
+
58
+ /** A resolve-only `Bun.plugin`, typed here: these modules sit in app type graphs without bun-types. */
59
+ interface ResolvePlugin {
60
+ name: string
61
+ setup(build: {
62
+ onResolve(
63
+ options: { filter: RegExp },
64
+ resolve: (args: { path: string; importer: string }) => { path: string } | undefined,
65
+ ): void
66
+ }): void
67
+ }
68
+
69
+ export function registerResolvePlugin(plugin: ResolvePlugin) {
70
+ ;(globalThis as unknown as { Bun: { plugin(plugin: ResolvePlugin): void } }).Bun.plugin(plugin)
71
+ }
72
+
73
+ let registered = false
74
+
75
+ /** Route imports of framework source, by path, to the prebundle. */
76
+ export function registerPrebundleResolve(): void {
77
+ if (!prebundle || registered) return
78
+ registered = true
79
+ const escaped = srcRoot.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
80
+ registerResolvePlugin({
81
+ name: 'pnext-prebundle',
82
+ setup(build) {
83
+ build.onResolve({ filter: new RegExp(`^${escaped}.*\\.tsx?$`) }, args => {
84
+ const target = prebundledFile(args.path)
85
+ return target === args.path ? undefined : { path: target }
86
+ })
87
+ // A URL encodes the root (`%20` for a space), so it is decoded before the root is compared.
88
+ build.onResolve({ filter: /^file:.*\.tsx?$/ }, args => {
89
+ const file = fileURLToPath(args.path)
90
+ const target = prebundledFile(file)
91
+ return target === file ? undefined : { path: target }
92
+ })
93
+ // Compiled artifacts name framework modules by relative path.
94
+ build.onResolve({ filter: /^\.\.?\/.*\/src\/.*\.tsx?$/ }, args => {
95
+ const file = path.resolve(path.dirname(args.importer), args.path)
96
+ const target = prebundledFile(file)
97
+ return target === file ? undefined : { path: target }
98
+ })
99
+ },
100
+ })
101
+ }
@@ -0,0 +1,456 @@
1
+ /**
2
+ * The release a production server runs from: compiled server artifacts plus the source facts the
3
+ * build froze. A served request never reads, stats or hashes app source or config, and never
4
+ * compiles; everything it imports is named here. Dev and the build itself keep their own loaders.
5
+ */
6
+ import { type Dirent, existsSync, readFileSync, readdirSync, realpathSync } from 'node:fs'
7
+ import { rename, writeFile } from 'node:fs/promises'
8
+ import path from 'node:path'
9
+ import { pathToFileURL } from 'node:url'
10
+ import type { ResolvedConfig } from '../config'
11
+ import type { ReleasedFont } from '../render/hooks'
12
+ import type { StaticMetadataFile } from '../routing/metadata-files'
13
+ import { prebundledFile, registerResolvePlugin } from './prebundle'
14
+ import { splitResourceQuery } from '../utils/resource-query'
15
+
16
+ export const BUILD_INDEX_VERSION = 1
17
+
18
+ /** `server` is the RSC/server layer, `client` the SSR copy of client components. */
19
+ export type ReleaseLayer = 'server' | 'client'
20
+
21
+ /** What the build writes. Paths are relative (to the root, or to the out dir for artifacts). */
22
+ export interface BuildIndex {
23
+ version: number
24
+ /** The framework fingerprint the build compiled with. */
25
+ framework?: string
26
+ config: Record<string, unknown>
27
+ /** The compiled next.config, out-relative. */
28
+ nextConfig?: string
29
+ /** `<layer>:<target>:<releaseSourceKey>` -> artifact. */
30
+ modules: Record<string, string>
31
+ /** App directory -> the convention files and `@slot`/group directories it holds. */
32
+ conventions: Record<string, string[]>
33
+ /** Convention files carrying `'use client'`. */
34
+ clientConventions: string[]
35
+ /** Root layouts that export a default component. */
36
+ documentLayouts: string[]
37
+ /** The root layout's global stylesheet closure, in order. */
38
+ globalCss: string[]
39
+ /** The proxy source and its literal `config` export, when the app has one. */
40
+ proxy?: { file: string; config?: unknown }
41
+ /** Font resolutions by declaration key, files out-relative. */
42
+ fonts?: Record<string, ReleasedFont>
43
+ /** Prebuilt instrumentation instances, out-relative. */
44
+ instrumentation?: { file: string; edge?: string }
45
+ /** App facts compat reads at boot: root param names, pages revalidate windows. */
46
+ compat?: CompatReleaseFacts
47
+ /** The App Router layers' linked server dependency graphs, out-relative. */
48
+ dependencies?: string[]
49
+ }
50
+
51
+ /** What compat contributes to a release. */
52
+ export type CompatRelease = Pick<BuildIndex, 'nextConfig' | 'instrumentation' | 'compat'>
53
+
54
+ export interface CompatReleaseFacts {
55
+ rootParams: string[]
56
+ pagesRevalidate: [string, number][]
57
+ /** Pages API sources (root-relative) and their runtime. */
58
+ pagesApi: Record<string, string>
59
+ /** Compiled cache handlers by role, out-relative. */
60
+ cacheHandlers: Record<string, string>
61
+ /** Materialized pages-router route wrappers, root-relative. */
62
+ pagesRoutes: string[]
63
+ }
64
+
65
+ /** The loaded release, resolved against where it is served from. */
66
+ export interface Release {
67
+ /** `<layer>:<target>:<absolute source>` -> file href. */
68
+ modules: Map<string, string>
69
+ conventions: ConventionFacts
70
+ globalCss: string[]
71
+ proxy: { file?: string; config?: unknown }
72
+ instrumentation?: { file: string; edge?: string }
73
+ compat?: CompatReleaseFacts
74
+ /** Font resolutions by declaration key, files absolute. */
75
+ fonts?: Record<string, ReleasedFont>
76
+ /** The build's static metadata files; the serving pipeline publishes them from its manifest. */
77
+ staticMetadataFiles?: StaticMetadataFile[]
78
+ }
79
+
80
+ export interface ConventionFacts {
81
+ appPath: string
82
+ /** Absolute app directory -> its convention files and child directories. */
83
+ dirs: Map<string, { files: Set<string>; dirs: string[] }>
84
+ client: ReadonlySet<string>
85
+ documentLayouts: ReadonlySet<string>
86
+ }
87
+
88
+ const releases = new WeakMap<object, Release>()
89
+ const WORK_UNIT_STORAGE = Symbol.for('pnext.workUnitStorage')
90
+
91
+ export function buildIndexFile(outPath: string) {
92
+ return path.join(outPath, 'server', 'build-index.json')
93
+ }
94
+
95
+ export function buildManifestFile(outPath: string) {
96
+ return path.join(outPath, 'server', 'manifest.json')
97
+ }
98
+
99
+ /** The framework copy a standalone dir ships: its compiled modules name framework files there. */
100
+ export function releaseFrameworkRoot(outPath: string) {
101
+ try {
102
+ const { name } = JSON.parse(readFileSync(path.join(frameworkRoot, 'package.json'), 'utf8')) as {
103
+ name: string
104
+ }
105
+ return realpathSync(path.join(outPath, 'node_modules', name))
106
+ } catch {
107
+ return frameworkRoot
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Where a release's app sources are, as its compiled modules name them: the app root the build recorded
113
+ * relative to its output. In place that is the real root; a copied standalone keeps the same relation.
114
+ */
115
+ export function releaseSourceRoot(outPath: string, serializedOutPath: string) {
116
+ return path.resolve(outPath, path.relative(serializedOutPath, '.'))
117
+ }
118
+
119
+ /** Build-machine facts about a standalone dir, kept in the build cache beside it. */
120
+ export function standaloneOriginsFile(outPath: string) {
121
+ return path.join(path.dirname(outPath), 'cache', 'standalone.json')
122
+ }
123
+
124
+ let shippedRelease: string | null | undefined
125
+
126
+ /** The standalone dir this framework copy ships in (`<dir>/node_modules/…/<name>`), if it is one. */
127
+ export function servingReleaseDir(): string | undefined {
128
+ if (shippedRelease === undefined) {
129
+ shippedRelease = null
130
+ // Isolated installs nest the copy deeper: `node_modules/.bun/<pkg>/node_modules/<name>`.
131
+ for (
132
+ let dir = path.dirname(frameworkRoot);
133
+ dir !== path.dirname(dir);
134
+ dir = path.dirname(dir)
135
+ ) {
136
+ if (path.basename(dir) === 'node_modules' && existsSync(buildIndexFile(path.dirname(dir)))) {
137
+ shippedRelease = path.dirname(dir)
138
+ break
139
+ }
140
+ }
141
+ }
142
+ return shippedRelease ?? undefined
143
+ }
144
+
145
+ const linkedReleases = new Map<string, boolean>()
146
+
147
+ /**
148
+ * Serve `release` from this framework copy without loading the standalone one beside it: its imports
149
+ * of its `node_modules` copies resolve back to the files they were cloned from, so the process keeps
150
+ * one instance of the framework and of every package. False when this copy cannot serve it in
151
+ * place: the build cache naming the origins is gone, or the release moved since.
152
+ */
153
+ export function linkStandaloneOrigins(release: string): boolean {
154
+ if (servingReleaseDir() === release) return true
155
+ const known = linkedReleases.get(release)
156
+ if (known !== undefined) return known
157
+ let origins: Record<string, string> | undefined
158
+ try {
159
+ const parsed = JSON.parse(readFileSync(standaloneOriginsFile(release), 'utf8')) as {
160
+ release: string
161
+ origins: Record<string, string>
162
+ }
163
+ if (parsed.release === release) origins = parsed.origins
164
+ } catch {
165
+ origins = undefined
166
+ }
167
+ linkedReleases.set(release, origins !== undefined)
168
+ if (!origins) return false
169
+ const files = origins
170
+ const modules = `${path.join(release, 'node_modules')}${path.sep}`
171
+ registerResolvePlugin({
172
+ name: 'pnext-standalone-origins',
173
+ setup(build) {
174
+ build.onResolve({ filter: /node_modules\// }, args => {
175
+ const file = path.resolve(path.dirname(args.importer), splitResourceQuery(args.path).path)
176
+ if (!file.startsWith(modules)) return undefined
177
+ const origin = files[path.relative(release, file).split(path.sep).join('/')]
178
+ return origin && existsSync(origin) ? { path: prebundledFile(origin) } : undefined
179
+ })
180
+ },
181
+ })
182
+ return true
183
+ }
184
+
185
+ export function releaseModuleKey(layer: ReleaseLayer, target: string, file: string) {
186
+ return `${layer}:${target}:${file}`
187
+ }
188
+
189
+ /** The release `config` serves from; undefined for dev and for the build itself. */
190
+ export function productionRelease(config: object): Release | undefined {
191
+ return releases.get(config)
192
+ }
193
+
194
+ /** The release the current request's work unit serves, if any (request/context owns the store). */
195
+ export function servedRelease(): Release | undefined {
196
+ const units = (globalThis as Record<PropertyKey, unknown>)[WORK_UNIT_STORAGE] as
197
+ { getStore(): { release?: Release } | undefined } | undefined
198
+ return units?.getStore()?.release
199
+ }
200
+
201
+ /** The frozen app-directory facts of the release this work serves, if any. */
202
+ export function servedConventions(): ConventionFacts | undefined {
203
+ return servedRelease()?.conventions
204
+ }
205
+
206
+ /** A frozen listing for `dir` when it lies in the served app; undefined defers to the disk. */
207
+ export function frozenDirListing(dir: string) {
208
+ const facts = servedConventions()
209
+ if (!facts || !isInsideDir(facts.appPath, dir)) return undefined
210
+ return facts.dirs.get(dir) ?? { files: new Set<string>(), dirs: [] }
211
+ }
212
+
213
+ /** Whether a convention file exists: the frozen fact in production, the disk otherwise. */
214
+ export function conventionFileExists(file: string) {
215
+ return frozenDirListing(path.dirname(file))?.files.has(path.basename(file)) ?? existsSync(file)
216
+ }
217
+
218
+ /** The compiled artifact for `file`; a module the build did not compile is a build bug, never a compile. */
219
+ export function releaseModuleHref(
220
+ release: Release,
221
+ layer: ReleaseLayer,
222
+ target: string,
223
+ file: string,
224
+ ) {
225
+ const href = release.modules.get(releaseModuleKey(layer, target, path.resolve(file)))
226
+ if (!href) {
227
+ throw new Error(
228
+ `pnext: ${file} (${layer}, ${target}) is not in this build's release. Run 'pnext build' again.`,
229
+ )
230
+ }
231
+ return href
232
+ }
233
+
234
+ /** Read `<outPath>/server/build-index.json` and attach it to `config`. */
235
+ export function attachRelease(config: ResolvedConfig, index = readBuildIndex(config.outPath)) {
236
+ const existing = releases.get(config)
237
+ if (existing) return existing
238
+ const fromRoot = (file: string) => path.resolve(config.root, file)
239
+ const framework = releaseFrameworkRoot(config.outPath)
240
+ const modules = new Map<string, string>()
241
+ for (const [key, artifact] of Object.entries(index.modules)) {
242
+ const second = key.indexOf(':', key.indexOf(':') + 1)
243
+ modules.set(
244
+ `${key.slice(0, second + 1)}${releaseSourceFile(key.slice(second + 1), config.root, config.workspaceRoot, framework)}`,
245
+ pathToFileURL(path.resolve(config.outPath, artifact)).href,
246
+ )
247
+ }
248
+ const dirs = new Map<string, { files: Set<string>; dirs: string[] }>()
249
+ for (const [dir, names] of Object.entries(index.conventions)) {
250
+ dirs.set(fromRoot(dir), {
251
+ files: new Set(names.filter(name => !name.endsWith('/'))),
252
+ dirs: names.filter(name => name.endsWith('/')).map(name => name.slice(0, -1)),
253
+ })
254
+ }
255
+ const release: Release = {
256
+ modules,
257
+ conventions: {
258
+ appPath: config.appPath,
259
+ dirs,
260
+ client: new Set(index.clientConventions.map(fromRoot)),
261
+ documentLayouts: new Set(index.documentLayouts.map(fromRoot)),
262
+ },
263
+ globalCss: index.globalCss.map(fromRoot),
264
+ proxy: index.proxy ? { ...index.proxy, file: fromRoot(index.proxy.file) } : {},
265
+ ...(index.compat ? { compat: index.compat } : {}),
266
+ ...(index.instrumentation
267
+ ? {
268
+ instrumentation: {
269
+ file: path.resolve(config.outPath, index.instrumentation.file),
270
+ ...(index.instrumentation.edge
271
+ ? { edge: path.resolve(config.outPath, index.instrumentation.edge) }
272
+ : {}),
273
+ },
274
+ }
275
+ : {}),
276
+ ...(index.fonts
277
+ ? {
278
+ fonts: Object.fromEntries(
279
+ Object.entries(index.fonts).map(([key, font]) => [
280
+ key,
281
+ { ...font, files: font.files.map(file => path.resolve(config.outPath, file)) },
282
+ ]),
283
+ ),
284
+ }
285
+ : {}),
286
+ }
287
+ releases.set(config, release)
288
+ return release
289
+ }
290
+
291
+ const conventionBases = new Set([
292
+ 'page',
293
+ 'route',
294
+ 'layout',
295
+ 'template',
296
+ 'loading',
297
+ 'error',
298
+ 'not-found',
299
+ 'default',
300
+ 'forbidden',
301
+ 'unauthorized',
302
+ 'global-error',
303
+ 'global-not-found',
304
+ ])
305
+
306
+ const metadataBase =
307
+ /^(?:robots|sitemap|manifest|favicon|(?:apple-)?icon\d*|opengraph-image\d*|twitter-image\d*)$/
308
+ const codeFile = /\.(?:[cm]?[jt]sx?|mdx?)$/
309
+
310
+ function capturedFile(name: string) {
311
+ const base = /^[^.]+/.exec(name)?.[0] ?? name
312
+ return conventionBases.has(base) || metadataBase.test(base)
313
+ }
314
+
315
+ /** Every file of the served app's frozen tree: its convention and metadata files. */
316
+ export function servedAppFiles(facts: ConventionFacts) {
317
+ return [...facts.dirs].flatMap(([dir, listing]) =>
318
+ [...listing.files].map(name => path.join(dir, name)),
319
+ )
320
+ }
321
+
322
+ /** Every app directory with its convention/metadata files and child directories; `files` are the code ones. */
323
+ export function captureConventions(root: string, appPath: string) {
324
+ const conventions: Record<string, string[]> = {}
325
+ const files: string[] = []
326
+ const visit = (dir: string) => {
327
+ let entries: Dirent[]
328
+ try {
329
+ entries = readdirSync(dir, { withFileTypes: true })
330
+ } catch {
331
+ return
332
+ }
333
+ const names: string[] = []
334
+ for (const entry of entries) {
335
+ if (entry.isDirectory()) {
336
+ if (entry.name === 'node_modules' || entry.name.startsWith('.')) continue
337
+ names.push(`${entry.name}/`)
338
+ visit(path.join(dir, entry.name))
339
+ } else if (capturedFile(entry.name)) {
340
+ names.push(entry.name)
341
+ if (codeFile.test(entry.name)) files.push(path.join(dir, entry.name))
342
+ }
343
+ }
344
+ conventions[toPosix(path.relative(root, dir)) || '.'] = names.sort()
345
+ }
346
+ visit(appPath)
347
+ return { conventions, files }
348
+ }
349
+
350
+ // The framework's own package root: compat runtime modules compile like app sources but live here.
351
+ const frameworkRoot = path.resolve(import.meta.dirname, '..', '..')
352
+
353
+ /** A source's identity in the release: root-, workspace- or framework-relative, so a moved build still finds it. */
354
+ export function releaseSourceKey(file: string, root: string, workspaceRoot: string) {
355
+ const inRoot = path.relative(root, file)
356
+ if (!inRoot.startsWith('..') && !path.isAbsolute(inRoot)) return `r:${toPosix(inRoot)}`
357
+ const inWorkspace = path.relative(workspaceRoot, file)
358
+ if (!inWorkspace.startsWith('..') && !path.isAbsolute(inWorkspace))
359
+ return `w:${toPosix(inWorkspace)}`
360
+ const inFramework = path.relative(frameworkRoot, file)
361
+ if (!inFramework.startsWith('..') && !path.isAbsolute(inFramework))
362
+ return `f:${toPosix(inFramework)}`
363
+ // Outside every root (a pages app materialized in tmpdir): root-relative, resolved like the manifest.
364
+ return `r:${toPosix(inRoot)}`
365
+ }
366
+
367
+ export function releaseSourceFile(
368
+ key: string,
369
+ root: string,
370
+ workspaceRoot: string,
371
+ framework = frameworkRoot,
372
+ ) {
373
+ const value = key.slice(2)
374
+ if (key.startsWith('r:')) return path.join(root, value)
375
+ if (key.startsWith('w:')) return path.resolve(workspaceRoot, value)
376
+ if (key.startsWith('f:')) return path.resolve(framework, value)
377
+ return path.join(root, value)
378
+ }
379
+
380
+ function toPosix(file: string) {
381
+ return file.split(path.sep).join('/')
382
+ }
383
+
384
+ function isInsideDir(root: string, file: string) {
385
+ return file === root || file.startsWith(`${root}${path.sep}`)
386
+ }
387
+
388
+ export function readBuildIndex(outPath: string): BuildIndex {
389
+ const file = buildIndexFile(outPath)
390
+ let index: BuildIndex
391
+ try {
392
+ index = JSON.parse(readFileSync(file, 'utf8')) as BuildIndex
393
+ } catch (error) {
394
+ if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error
395
+ throw new Error("No production build found. Run 'pnext build' first.")
396
+ }
397
+ if (index.version !== BUILD_INDEX_VERSION) {
398
+ throw new Error(`pnext: ${file} is from another pnext version. Run 'pnext build' again.`)
399
+ }
400
+ return index
401
+ }
402
+
403
+ /** The resolved config as the build saw it, with paths made relative to the root. */
404
+ export function serializeReleaseConfig(config: ResolvedConfig): Record<string, unknown> {
405
+ const relative = (file: string) => path.relative(config.root, file) || '.'
406
+ return JSON.parse(
407
+ JSON.stringify(
408
+ {
409
+ ...config,
410
+ root: '.',
411
+ workspaceRoot: relative(config.workspaceRoot),
412
+ appPath: relative(config.appPath),
413
+ publicPath: relative(config.publicPath),
414
+ outPath: relative(config.outPath),
415
+ outRootPath: relative(config.outRootPath),
416
+ typesPath: relative(config.typesPath),
417
+ checksPath: relative(config.checksPath),
418
+ },
419
+ (_key, value: unknown) =>
420
+ value instanceof RegExp ? { $regexp: [value.source, value.flags] } : value,
421
+ ),
422
+ ) as Record<string, unknown>
423
+ }
424
+
425
+ /** The inverse of `serializeReleaseConfig`, for a release served from `root` out of `outPath`. */
426
+ export function releaseConfig(
427
+ serialized: Record<string, unknown>,
428
+ root: string,
429
+ outPath: string,
430
+ ): ResolvedConfig {
431
+ const config = JSON.parse(JSON.stringify(serialized), (_key, value: unknown) => {
432
+ const pattern = (value as { $regexp?: [string, string] } | null)?.$regexp
433
+ return pattern ? new RegExp(pattern[0], pattern[1]) : value
434
+ }) as ResolvedConfig
435
+ const fromRoot = (file: string) => path.resolve(root, file)
436
+ const fromOut = (file: string) => path.resolve(outPath, path.relative(config.outPath, file))
437
+ return {
438
+ ...config,
439
+ root,
440
+ workspaceRoot: fromRoot(config.workspaceRoot),
441
+ appPath: fromRoot(config.appPath),
442
+ publicPath: fromRoot(config.publicPath),
443
+ outPath,
444
+ outRootPath: fromOut(config.outRootPath),
445
+ typesPath: fromOut(config.typesPath),
446
+ checksPath: fromOut(config.checksPath),
447
+ }
448
+ }
449
+
450
+ /** Publish the build index last, atomically. */
451
+ export async function writeBuildIndex(config: ResolvedConfig, index: BuildIndex) {
452
+ const file = buildIndexFile(config.outPath)
453
+ const temporary = `${file}.${process.pid}.tmp`
454
+ await writeFile(temporary, JSON.stringify(index))
455
+ await rename(temporary, file)
456
+ }