@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,569 @@
1
+ // ---------------------------------------------------------------------------
2
+ // next.config.(js|cjs|mjs|ts|mts|cts) loader (COMPAT).
3
+ //
4
+ // Loads a Next.js config authored in any of the supported module formats and
5
+ // maps it onto pnext's resolved core config, keeping the full loaded object in
6
+ // a compat-only store other compat modules read via getNextConfig().
7
+ //
8
+ // One esbuild-based loader covers all three e2e suite families
9
+ // (next-config-ts, -native-ts, -native-mts): the config is bundled with the
10
+ // app tsconfig (so `paths` aliases, `extends`, and `.ts`/`.cts`/`.mts` imports
11
+ // resolve), node_modules kept external, then the emitted ESM module imported.
12
+ // This handles export default / export-as-default / async function / Promise
13
+ // export / top-level await / dynamic import() and CJS+ESM authoring styles.
14
+ // ---------------------------------------------------------------------------
15
+
16
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
17
+ import { createRequire } from 'node:module';
18
+ import path from 'node:path';
19
+ import { pathToFileURL } from 'node:url';
20
+ import { build } from 'esbuild';
21
+ import { setConfig } from './config';
22
+ import { setCacheComponents } from '../../ppr';
23
+ import { PHASE_DEVELOPMENT_SERVER, PHASE_PRODUCTION_BUILD } from './constants';
24
+ import { nextMdxConfigStubPlugin } from '../mdx/next-mdx-stub';
25
+ import { collectImagesConfigErrors } from './image/validate';
26
+ import { setSvgAsComponentEnabled, webpackReferencesSvgr } from './svgr';
27
+ import { emitBuildFeatureUsageTelemetry, emitSessionStartedTelemetry } from './telemetry';
28
+
29
+ export type NextConfigObject = Record<string, unknown>;
30
+ type NextConfigFn = (
31
+ phase: string,
32
+ context: { defaultConfig: NextConfigObject },
33
+ ) => NextConfigObject | Promise<NextConfigObject>;
34
+ type NextConfigExport = NextConfigObject | NextConfigFn | Promise<NextConfigObject>;
35
+
36
+ const CONFIG_BASENAMES = [
37
+ 'next.config.ts',
38
+ 'next.config.mts',
39
+ 'next.config.cts',
40
+ 'next.config.js',
41
+ 'next.config.mjs',
42
+ 'next.config.cjs',
43
+ ];
44
+
45
+ let store: NextConfigObject = {};
46
+
47
+ /** The full loaded next.config object; empty until loadNextConfig runs. */
48
+ export function getNextConfig(): NextConfigObject {
49
+ return store;
50
+ }
51
+
52
+ /**
53
+ * Read the effective `cacheComponents` flag from a loaded next.config. Next
54
+ * accepts the modern `cacheComponents: true` and the legacy
55
+ * `experimental.dynamicIO` alias, plus the env override
56
+ * `__NEXT_CACHE_COMPONENTS`. Note that `experimental.useCache` is NOT an alias:
57
+ * it only enables the `use cache` directive (Next maps cacheComponents ->
58
+ * useCache, never the reverse), so a useCache-only app keeps the classic full
59
+ * static/ISR prerender semantics.
60
+ */
61
+ function readCacheComponentsFlag(config: NextConfigObject): boolean {
62
+ // eslint-disable-next-line turbo/no-undeclared-env-vars
63
+ if (process.env.__NEXT_CACHE_COMPONENTS === 'true') return true;
64
+ if (config.cacheComponents === true) return true;
65
+ const experimental = config.experimental as Record<string, unknown> | undefined;
66
+ if (experimental?.cacheComponents === true) return true;
67
+ if (experimental?.dynamicIO === true) return true;
68
+ return false;
69
+ }
70
+
71
+ export function setNextConfig(config: NextConfigObject): void {
72
+ store = config;
73
+ // Derived per config load, never a process one-shot: a second build in the
74
+ // same process (dev server, programmatic API, test suite) must see its OWN
75
+ // app's flag, not the previous app's.
76
+ setCacheComponents(readCacheComponentsFlag(config));
77
+ setSvgAsComponentEnabled(webpackReferencesSvgr(config));
78
+ // Expose basePath to server-side render code through the isomorphic
79
+ // globalThis global (compat/client/base-path.ts reads it). The client reads
80
+ // the window global the render layer injects instead; keeping both in sync
81
+ // lets Link/redirect/nav prefix basePath identically on server and client.
82
+ (globalThis as { __PNEXT_BASE_PATH__?: string }).__PNEXT_BASE_PATH__ =
83
+ typeof config.basePath === 'string' ? config.basePath : '';
84
+ // Expose skipTrailingSlashRedirect the same way so server-rendered Links skip
85
+ // trailing-slash normalization (the client reads the injected window global).
86
+ (globalThis as { __PNEXT_SKIP_TRAILING_SLASH__?: boolean }).__PNEXT_SKIP_TRAILING_SLASH__ =
87
+ config.skipTrailingSlashRedirect === true;
88
+ (globalThis as { __PNEXT_TRAILING_SLASH__?: boolean }).__PNEXT_TRAILING_SLASH__ =
89
+ config.trailingSlash === true;
90
+ }
91
+
92
+ /** Overrides mapped onto pnext's resolved core config. */
93
+ export interface NextConfigCoreOverrides {
94
+ basePath?: string;
95
+ trailingSlash?: boolean;
96
+ skipTrailingSlashRedirect?: boolean;
97
+ outDir?: string;
98
+ assetPrefix?: string;
99
+ productionBrowserSourceMaps?: boolean;
100
+ }
101
+
102
+ export interface LoadNextConfigResult {
103
+ config: NextConfigObject;
104
+ overrides: NextConfigCoreOverrides;
105
+ }
106
+
107
+ function findConfigPath(root: string): string | undefined {
108
+ for (const name of CONFIG_BASENAMES) {
109
+ const candidate = path.join(root, name);
110
+ if (existsSync(candidate)) return candidate;
111
+ }
112
+ return undefined;
113
+ }
114
+
115
+ /** Stable per config content, so the emitted bundle keeps one name per boot. */
116
+ function configSourceKey(configPath: string): string {
117
+ try {
118
+ return Bun.hash(readFileSync(configPath)).toString(36);
119
+ } catch {
120
+ return 'config';
121
+ }
122
+ }
123
+
124
+ function findTsconfig(root: string): string | undefined {
125
+ const candidate = path.join(root, 'tsconfig.json');
126
+ return existsSync(candidate) ? candidate : undefined;
127
+ }
128
+
129
+ /**
130
+ * Bundle the config with esbuild (external node_modules) and import the result.
131
+ * The emitted file is written next to the config so Node resolves the app's
132
+ * node_modules and relative assets from the original location.
133
+ */
134
+ async function importConfigModule(configPath: string, root: string): Promise<NextConfigExport> {
135
+ const outDir = path.join(root, '.pnext', 'config');
136
+ mkdirSync(outDir, { recursive: true });
137
+ const cjs = cjsConfigFormat(configPath, root);
138
+ // Content-addressed, not timestamped: a per-boot name leaked one bundle per
139
+ // dev start and put a path that changes every boot into the module graph,
140
+ // which renamed every artifact that could reach it.
141
+ const outfile = path.join(outDir, `next.config.${configSourceKey(configPath)}.${cjs ? 'cjs' : 'mjs'}`);
142
+ try {
143
+ await build({
144
+ entryPoints: [configPath],
145
+ outfile,
146
+ bundle: true,
147
+ platform: 'node',
148
+ format: cjs ? 'cjs' : 'esm',
149
+ target: 'esnext',
150
+ // Keep bare package imports external so Node resolves them from the app's
151
+ // node_modules at import time (preserves CJS/ESM interop and identity).
152
+ packages: 'external',
153
+ // Fixture/app configs may require() or require.resolve() Next internals
154
+ // (next/dist/*) that don't exist without a real `next` install. Stub them
155
+ // so the config still loads; features pointing at the stubs degrade
156
+ // gracefully instead of crashing config loading.
157
+ plugins: [nextDistStubPlugin(outDir), nextMdxConfigStubPlugin()],
158
+ banner: cjs
159
+ ? {
160
+ js:
161
+ 'var __pnextNodeRequire = module.require.bind(module);\n' +
162
+ `var require = __pnextNodeRequire("node:module").createRequire(${JSON.stringify(pathToFileURL(configPath).href)});`,
163
+ }
164
+ : {
165
+ js:
166
+ 'import { createRequire as __pnextCreateRequire } from "node:module";\n' +
167
+ `const require = __pnextCreateRequire(${JSON.stringify(pathToFileURL(configPath).href)});`,
168
+ },
169
+ // Relative/absolute imports (incl. .ts/.cts/.mts/.cjs/.mjs and tsconfig
170
+ // `paths` aliases) are bundled in. esbuild reads `paths`/`extends` and
171
+ // `baseUrl` from the app tsconfig.
172
+ tsconfig: findTsconfig(root),
173
+ // __dirname / __filename in CJS-authored .ts configs (node-api-cjs) and
174
+ // import.meta.url in ESM configs (node-api-esm) must point at the config's
175
+ // original location, not the emitted file under .pnext/config.
176
+ define: {
177
+ __dirname: JSON.stringify(path.dirname(configPath)),
178
+ __filename: JSON.stringify(configPath),
179
+ 'import.meta.url': JSON.stringify(pathToFileURL(configPath).href),
180
+ },
181
+ logLevel: 'silent',
182
+ sourcemap: false,
183
+ metafile: false,
184
+ });
185
+ if (cjs) {
186
+ const require = createRequire(pathToFileURL(outfile));
187
+ return require(outfile) as NextConfigExport;
188
+ }
189
+ const module = (await import(pathToFileURL(outfile).href)) as { default?: NextConfigExport };
190
+ return module.default ?? {};
191
+ } finally {
192
+ rmSync(outfile, { force: true });
193
+ }
194
+ }
195
+
196
+ function cjsConfigFormat(configPath: string, root: string): boolean {
197
+ if (configPath.endsWith('.cjs') || configPath.endsWith('.cts')) return true;
198
+ if (!configPath.endsWith('.js')) return false;
199
+ try {
200
+ const pkg = JSON.parse(readFileSync(path.join(root, 'package.json'), 'utf8')) as {
201
+ type?: unknown;
202
+ };
203
+ return pkg.type !== 'module';
204
+ } catch {
205
+ return true;
206
+ }
207
+ }
208
+
209
+ // Stub next/dist/* internals during config bundling: imports and requires resolve to an inert module
210
+ // (its default export is a no-op class so `extends` works), and require.resolve() returns the path of a
211
+ // real on-disk stub module instead of throwing. The emitted config calls Node's require.resolve at
212
+ // runtime, so the returned path must exist - and configs commonly feed it back into features like
213
+ // `cacheHandlers`, whose loaders then require() it. Only next/dist deep imports are stubbed; top-level
214
+ // `next/*` config helpers stay external.
215
+ const NEXT_DIST_STUB_CONTENTS =
216
+ 'class PNextConfigStub {}\n' +
217
+ 'module.exports = new Proxy(PNextConfigStub, { get: (t, k) => (k === "default" ? PNextConfigStub : t[k] ?? PNextConfigStub) });\n';
218
+
219
+ function nextDistStubPlugin(outDir: string): import('esbuild').Plugin {
220
+ return {
221
+ name: 'pnext-next-dist-stub',
222
+ setup(build) {
223
+ build.onResolve({ filter: /^next\/dist\// }, args => {
224
+ if (args.kind === 'require-resolve') {
225
+ // Preserve the requested module path under the stub root so loaders
226
+ // downstream can still recognize WHICH next internal was meant.
227
+ const stubPath = path.join(outDir, 'next-dist-stub', `${args.path}.cjs`);
228
+ mkdirSync(path.dirname(stubPath), { recursive: true });
229
+ writeFileSync(stubPath, NEXT_DIST_STUB_CONTENTS);
230
+ return { path: stubPath, external: true };
231
+ }
232
+ return { path: args.path, namespace: 'pnext-next-dist-stub' };
233
+ });
234
+ build.onLoad({ filter: /.*/, namespace: 'pnext-next-dist-stub' }, () => ({
235
+ contents: NEXT_DIST_STUB_CONTENTS,
236
+ loader: 'js',
237
+ }));
238
+ },
239
+ };
240
+ }
241
+
242
+ function currentPhase(dev: boolean): string {
243
+ return dev ? PHASE_DEVELOPMENT_SERVER : PHASE_PRODUCTION_BUILD;
244
+ }
245
+
246
+ /** A missing-module resolution failure (vs a genuine config error to surface). */
247
+ function isModuleNotFoundError(error: unknown): boolean {
248
+ if (!error || typeof error !== 'object') return false;
249
+ const code = (error as { code?: unknown }).code;
250
+ if (code === 'ERR_MODULE_NOT_FOUND' || code === 'MODULE_NOT_FOUND') return true;
251
+ const message = (error as { message?: unknown }).message;
252
+ return typeof message === 'string' && /Cannot find (?:module|package)/.test(message);
253
+ }
254
+
255
+ function describeMissingModule(error: unknown): string {
256
+ const message = (error as { message?: unknown }).message;
257
+ const match =
258
+ typeof message === 'string'
259
+ ? /Cannot find (?:module|package) ['"]([^'"]+)['"]/.exec(message)
260
+ : null;
261
+ return match ? `${match[1]} not installed` : 'a required module is not installed';
262
+ }
263
+
264
+ async function resolveConfigExport(
265
+ exported: NextConfigExport,
266
+ dev: boolean,
267
+ ): Promise<NextConfigObject> {
268
+ const value =
269
+ typeof exported === 'function'
270
+ ? await exported(currentPhase(dev), { defaultConfig: {} })
271
+ : await exported;
272
+ return value ?? {};
273
+ }
274
+
275
+ function mapOverrides(config: NextConfigObject): NextConfigCoreOverrides {
276
+ const overrides: NextConfigCoreOverrides = {};
277
+ if (typeof config.basePath === 'string') overrides.basePath = config.basePath;
278
+ if (typeof config.assetPrefix === 'string' && config.assetPrefix.length > 0) {
279
+ overrides.assetPrefix = config.assetPrefix;
280
+ }
281
+ if (typeof config.trailingSlash === 'boolean') overrides.trailingSlash = config.trailingSlash;
282
+ if (typeof config.skipTrailingSlashRedirect === 'boolean')
283
+ overrides.skipTrailingSlashRedirect = config.skipTrailingSlashRedirect;
284
+ if (typeof config.productionBrowserSourceMaps === 'boolean')
285
+ overrides.productionBrowserSourceMaps = config.productionBrowserSourceMaps;
286
+ // Next's distDir maps onto pnext's outDir. pnext's default output dir is .pnext; only override when
287
+ // the app explicitly sets distDir. Under `output: 'export'` a custom distDir is the EXPORT
288
+ // destination instead - the build keeps its default dir and the static export tree lands in distDir.
289
+ if (
290
+ typeof config.distDir === 'string' &&
291
+ config.distDir.length > 0 &&
292
+ config.output !== 'export'
293
+ ) {
294
+ overrides.outDir = config.distDir;
295
+ }
296
+ return overrides;
297
+ }
298
+
299
+ function normalizeCacheHandlerPath(config: NextConfigObject, root: string): NextConfigObject {
300
+ const value = config.cacheHandler;
301
+ const cacheHandlers = config.cacheHandlers;
302
+ let next = config;
303
+ if (typeof value === 'string' && isRelativePathSpecifier(value)) {
304
+ next = { ...next, cacheHandler: path.resolve(root, value) };
305
+ }
306
+ if (cacheHandlers && typeof cacheHandlers === 'object' && !Array.isArray(cacheHandlers)) {
307
+ const normalized: Record<string, unknown> = {};
308
+ let changed = false;
309
+ for (const [key, handlerPath] of Object.entries(cacheHandlers as Record<string, unknown>)) {
310
+ if (typeof handlerPath === 'string' && isRelativePathSpecifier(handlerPath)) {
311
+ normalized[key] = path.resolve(root, handlerPath);
312
+ changed = true;
313
+ } else {
314
+ normalized[key] = handlerPath;
315
+ }
316
+ }
317
+ if (changed) next = { ...next, cacheHandlers: normalized };
318
+ }
319
+ return next;
320
+ }
321
+
322
+ function isRelativePathSpecifier(value: string): boolean {
323
+ return value === '.' || value === '..' || value.startsWith('./') || value.startsWith('../');
324
+ }
325
+
326
+ /**
327
+ * Apply the config's `env` object to process.env so server-rendered pages read
328
+ * `process.env.<key>` (Next semantics: config env are inlined/defined for the
329
+ * app). Values already present in the environment win.
330
+ */
331
+ function applyEnv(config: NextConfigObject): void {
332
+ const env = config.env;
333
+ if (!env || typeof env !== 'object') return;
334
+ for (const [key, value] of Object.entries(env as Record<string, unknown>)) {
335
+ if (value === undefined || value === null) continue;
336
+ if (process.env[key] !== undefined) continue;
337
+ process.env[key] = typeof value === 'string' ? value : (JSON.stringify(value) ?? '');
338
+ }
339
+ }
340
+
341
+ /** Feed next/config's getConfig() from the loaded config's runtime configs. */
342
+ function applyRuntimeConfig(config: NextConfigObject): void {
343
+ const serverRuntimeConfig = config.serverRuntimeConfig;
344
+ const publicRuntimeConfig = config.publicRuntimeConfig;
345
+ if (!serverRuntimeConfig && !publicRuntimeConfig) return;
346
+ setConfig({
347
+ ...(serverRuntimeConfig && typeof serverRuntimeConfig === 'object'
348
+ ? { serverRuntimeConfig: serverRuntimeConfig as Record<string, unknown> }
349
+ : {}),
350
+ ...(publicRuntimeConfig && typeof publicRuntimeConfig === 'object'
351
+ ? { publicRuntimeConfig: publicRuntimeConfig as Record<string, unknown> }
352
+ : {}),
353
+ });
354
+ }
355
+
356
+ const VALID_DEV_INDICATOR_POSITIONS = new Set([
357
+ 'top-left',
358
+ 'top-right',
359
+ 'bottom-left',
360
+ 'bottom-right',
361
+ ]);
362
+
363
+ const KNOWN_TOP_LEVEL_CONFIG_KEYS = new Set([
364
+ 'adapterPath',
365
+ 'assetPrefix',
366
+ 'basePath',
367
+ 'cacheComponents',
368
+ 'cacheHandler',
369
+ 'cacheHandlers',
370
+ 'cacheLife',
371
+ 'compiler',
372
+ 'devIndicators',
373
+ 'distDir',
374
+ 'env',
375
+ 'expireTime',
376
+ 'experimental',
377
+ 'images',
378
+ 'output',
379
+ 'outputFileTracingRoot',
380
+ 'pageExtensions',
381
+ 'partialPrefetching',
382
+ 'productionBrowserSourceMaps',
383
+ 'publicRuntimeConfig',
384
+ 'reactCompiler',
385
+ 'reactMaxHeadersLength',
386
+ 'resolveExtensions',
387
+ 'redirects',
388
+ 'rewrites',
389
+ 'sassOptions',
390
+ 'serverExternalPackages',
391
+ 'serverRuntimeConfig',
392
+ 'skipProxyUrlNormalize',
393
+ 'skipTrailingSlashRedirect',
394
+ 'i18n',
395
+ 'instrumentationClientInject',
396
+ 'trailingSlash',
397
+ 'skipMiddlewareUrlNormalize',
398
+ 'transpilePackages',
399
+ 'turbopack',
400
+ 'typedRoutes',
401
+ 'typescript',
402
+ 'webpack',
403
+ ]);
404
+
405
+ // Deprecated next.config options and the exact warning Next emits for each. The
406
+ // deprecation-warnings e2e suite asserts these substrings appear on the CLI when
407
+ // the option is explicitly configured (and that none appear otherwise).
408
+ const DEPRECATED_CONFIG_OPTIONS: readonly { key: string; reason: (file: string) => string }[] = [
409
+ {
410
+ key: 'experimental.middlewarePrefetch',
411
+ reason: file =>
412
+ `\`experimental.middlewarePrefetch\` is deprecated. Please use \`experimental.proxyPrefetch\` instead in ${file}.`,
413
+ },
414
+ {
415
+ key: 'experimental.middlewareClientMaxBodySize',
416
+ reason: file =>
417
+ `\`experimental.middlewareClientMaxBodySize\` is deprecated. Please use \`experimental.proxyClientMaxBodySize\` instead in ${file}.`,
418
+ },
419
+ {
420
+ key: 'experimental.externalMiddlewareRewritesResolve',
421
+ reason: file =>
422
+ `\`experimental.externalMiddlewareRewritesResolve\` is deprecated. Please use \`experimental.externalProxyRewritesResolve\` instead in ${file}.`,
423
+ },
424
+ {
425
+ key: 'skipMiddlewareUrlNormalize',
426
+ reason: file =>
427
+ `\`skipMiddlewareUrlNormalize\` is deprecated. Please use \`skipProxyUrlNormalize\` instead in ${file}.`,
428
+ },
429
+ {
430
+ key: 'experimental.instrumentationHook',
431
+ reason: file =>
432
+ `\`experimental.instrumentationHook\` is no longer needed, because \`instrumentation.js\` is available by default. You can remove it from ${file}.`,
433
+ },
434
+ ];
435
+
436
+ // Config-warning de-dup: loadNextConfig runs several times per process, but Next emits each
437
+ // next.config validation warning only ONCE per process. Track which config files have already been
438
+ // warned about so repeated loads within a single process stay silent. Fatal validation is intentionally
439
+ // re-run every call - it throws.
440
+ const warnedConfigPaths = new Set<string>();
441
+
442
+ function validateConfig(config: NextConfigObject, configPath: string): void {
443
+ if (!warnedConfigPaths.has(configPath)) {
444
+ warnedConfigPaths.add(configPath);
445
+ const configFileName = path.basename(configPath);
446
+ warnUnknownConfigKeys(config);
447
+ warnEsmExternalsFalse(config);
448
+ warnDeprecatedConfigOptions(config, configFileName);
449
+ warnWebpackCompat(config, configFileName);
450
+ }
451
+ validateDevIndicatorPosition(config);
452
+ const imageErrors = collectImagesConfigErrors(config, path.dirname(configPath));
453
+ if (imageErrors.length > 0) {
454
+ throw new Error(
455
+ `Invalid next.config.js options detected: \n${imageErrors.map(e => ` ${e}`).join('\n')}\nSee more info here: https://nextjs.org/docs/messages/invalid-next-config`,
456
+ );
457
+ }
458
+ }
459
+
460
+ /** True when a dotted key path (e.g. `experimental.instrumentationHook`) is set. */
461
+ function hasNestedKey(config: NextConfigObject, dottedKey: string): boolean {
462
+ let current: unknown = config;
463
+ for (const key of dottedKey.split('.')) {
464
+ if (!current || typeof current !== 'object') return false;
465
+ current = (current as Record<string, unknown>)[key];
466
+ if (current === undefined) return false;
467
+ }
468
+ return true;
469
+ }
470
+
471
+ function warnDeprecatedConfigOptions(config: NextConfigObject, configFileName: string): void {
472
+ for (const { key, reason } of DEPRECATED_CONFIG_OPTIONS) {
473
+ if (hasNestedKey(config, key)) console.warn(reason(configFileName));
474
+ }
475
+ }
476
+
477
+ function warnUnknownConfigKeys(config: NextConfigObject): void {
478
+ const invalid = Object.keys(config).filter(key => !KNOWN_TOP_LEVEL_CONFIG_KEYS.has(key));
479
+ if (invalid.length === 0) return;
480
+ console.warn(
481
+ `Invalid next.config.js options detected: ${invalid.map(key => `"${key}"`).join(', ')}`,
482
+ );
483
+ }
484
+
485
+ /**
486
+ * pnext bundles with esbuild only; a configured `webpack()` never runs. Warn once per config file (the
487
+ * `webpackReferencesSvgr` check in setNextConfig separately auto-enables the `.svg`-as-component shim for
488
+ * the common `@svgr/webpack` case, but the function itself is still never executed).
489
+ */
490
+ function warnWebpackCompat(config: NextConfigObject, configFileName: string): void {
491
+ if (typeof config.webpack !== 'function') return;
492
+ console.warn(
493
+ `\`webpack\` in ${configFileName} is not executed by pnext — esbuild is the only bundler. ` +
494
+ '`transpilePackages`, `experimental.optimizePackageImports`, and `turbopack.resolveAlias` are ' +
495
+ 'supported natively; see reference/compat.md.',
496
+ );
497
+ if (webpackReferencesSvgr(config)) {
498
+ console.info(
499
+ 'pnext detected @svgr/webpack in `webpack()` and will compile `.svg` imports to inline Preact ' +
500
+ 'components instead (see reference/compat.md).',
501
+ );
502
+ }
503
+ }
504
+
505
+ function warnEsmExternalsFalse(config: NextConfigObject): void {
506
+ const experimental = config.experimental;
507
+ if (!experimental || typeof experimental !== 'object') return;
508
+ if ((experimental as { esmExternals?: unknown }).esmExternals !== false) return;
509
+ console.warn(
510
+ 'The "experimental.esmExternals" option has been modified. experimental.esmExternals is not recommended to be modified as it may disrupt module resolution. It should be removed from your next.config.js',
511
+ );
512
+ }
513
+
514
+ function validateDevIndicatorPosition(config: NextConfigObject): void {
515
+ const devIndicators = config.devIndicators;
516
+ if (!devIndicators || typeof devIndicators !== 'object') return;
517
+ const position = (devIndicators as { position?: unknown }).position;
518
+ if (typeof position !== 'string' || VALID_DEV_INDICATOR_POSITIONS.has(position)) return;
519
+ throw new Error(
520
+ `Invalid "devIndicator.position" provided, expected one of top-left, top-right, bottom-left, bottom-right, received ${position}`,
521
+ );
522
+ }
523
+
524
+ /**
525
+ * Load the app's next.config.* (if present), apply its `env`, stash the full
526
+ * object for other compat modules, and return the subset mapped onto core.
527
+ * Returns empty overrides when no config exists.
528
+ */
529
+ export async function loadNextConfig(
530
+ root: string,
531
+ options: { dev?: boolean } = {},
532
+ ): Promise<LoadNextConfigResult> {
533
+ const configPath = findConfigPath(root);
534
+ if (!configPath) {
535
+ setNextConfig({});
536
+ emitSessionStartedTelemetry({});
537
+ return { config: {}, overrides: {} };
538
+ }
539
+ let exported: NextConfigExport;
540
+ try {
541
+ exported = await importConfigModule(configPath, root);
542
+ } catch (error) {
543
+ // A next.config that pulls in an optional wrapper dependency not installed
544
+ // in this app (e.g. @next/mdx when deps are declared but not installed)
545
+ // must not crash the whole build — the config's extras are optional here.
546
+ // Fall back to defaults instead, matching the next/dist/* stub philosophy.
547
+ if (isModuleNotFoundError(error)) {
548
+ console.warn(
549
+ `pnext: could not load ${path.relative(root, configPath)} ` +
550
+ `(${describeMissingModule(error)}); continuing with default config`,
551
+ );
552
+ setNextConfig({});
553
+ emitSessionStartedTelemetry({});
554
+ return { config: {}, overrides: {} };
555
+ }
556
+ throw error;
557
+ }
558
+ const config = normalizeCacheHandlerPath(
559
+ await resolveConfigExport(exported, Boolean(options.dev)),
560
+ root,
561
+ );
562
+ validateConfig(config, configPath);
563
+ setNextConfig(config);
564
+ applyEnv(config);
565
+ applyRuntimeConfig(config);
566
+ emitSessionStartedTelemetry(config);
567
+ emitBuildFeatureUsageTelemetry(config);
568
+ return { config, overrides: mapOverrides(config) };
569
+ }
@@ -0,0 +1,29 @@
1
+ export interface RuntimeConfig {
2
+ serverRuntimeConfig: Record<string, unknown>;
3
+ publicRuntimeConfig: Record<string, unknown>;
4
+ }
5
+
6
+ // Client-graph bundler defines (see compat/register/bundler.ts). Mirrors the image-config
7
+ // pattern: the boolean twin gates the branch on a literal so the ?? never has to fold an
8
+ // object define, and the define is only emitted when publicRuntimeConfig is non-empty.
9
+ declare const __PNEXT_PUBLIC_RUNTIME_CONFIG_INLINE__: Record<string, unknown>;
10
+ declare const __PNEXT_PUBLIC_RUNTIME_CONFIG_INLINED__: boolean;
11
+
12
+ // Server: populated by config-loader's setConfig() at config load time. Client: inlined at
13
+ // build time from next.config's publicRuntimeConfig; serverRuntimeConfig never reaches the
14
+ // client bundle (matches Next's exact behavior).
15
+ const runtimeConfig: RuntimeConfig = {
16
+ serverRuntimeConfig: {},
17
+ publicRuntimeConfig:
18
+ typeof __PNEXT_PUBLIC_RUNTIME_CONFIG_INLINED__ === 'boolean'
19
+ ? __PNEXT_PUBLIC_RUNTIME_CONFIG_INLINE__
20
+ : {},
21
+ };
22
+
23
+ export default function getConfig(): RuntimeConfig {
24
+ return runtimeConfig;
25
+ }
26
+
27
+ export function setConfig(config: Partial<RuntimeConfig>) {
28
+ Object.assign(runtimeConfig, config);
29
+ }
@@ -0,0 +1,6 @@
1
+ exports.PHASE_EXPORT = 'phase-export';
2
+ exports.PHASE_PRODUCTION_BUILD = 'phase-production-build';
3
+ exports.PHASE_PRODUCTION_SERVER = 'phase-production-server';
4
+ exports.PHASE_DEVELOPMENT_SERVER = 'phase-development-server';
5
+ exports.PHASE_TEST = 'phase-test';
6
+ exports.PHASE_INFO = 'phase-info';
@@ -0,0 +1,6 @@
1
+ export const PHASE_EXPORT = 'phase-export';
2
+ export const PHASE_PRODUCTION_BUILD = 'phase-production-build';
3
+ export const PHASE_PRODUCTION_SERVER = 'phase-production-server';
4
+ export const PHASE_DEVELOPMENT_SERVER = 'phase-development-server';
5
+ export const PHASE_TEST = 'phase-test';
6
+ export const PHASE_INFO = 'phase-info';