@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,86 @@
1
+ // Request-lifecycle extension registration (COMPAT).
2
+ //
3
+ // Wires after()/onRequestError/instrumentation/testmode onto the core seams:
4
+ // - initHooks (build + start): load instrumentation.ts and run its register() once; install the
5
+ // testmode fetch patch once (a no-op until a request carries Next-Test-* headers).
6
+ // - RequestExtensions.onRequestError: the error funnel (classify control-flow, dedupe, forward).
7
+ // - a request interceptor: await the instrumentation register() gate so async register() completes
8
+ // before the first request is served, and activate the testmode proxy for Next-Test-* requests.
9
+ //
10
+ // after() itself needs no registration - it is exported from the next/server alias and builds directly on
11
+ // the core work-unit after-queue.
12
+ //
13
+ // Split across the two registration tiers: the hooks core runs at server start register eagerly via
14
+ // registerLifecycleBootHooks(), while the request interceptor registers with the rest of the graph so its
15
+ // position in the interceptor chain is unchanged.
16
+
17
+ import type { ResolvedConfig } from '../../config';
18
+ import {
19
+ registerInitHooks,
20
+ registerRequestInterceptors,
21
+ setRequestExtensions,
22
+ type RequestInterceptor,
23
+ } from '../../extensions';
24
+ import { nextCompatEnabled } from '../index';
25
+ import { getNextConfig } from '../next/config-loader';
26
+ import { instrumentationReady, loadInstrumentation } from '../lifecycle/instrumentation';
27
+ import {
28
+ installUnhandledRejectionGuard,
29
+ reportRequestErrorToUser,
30
+ } from '../lifecycle/error-funnel';
31
+ import { activateTestProxy, installTestProxyFetch } from '../lifecycle/testmode';
32
+ import { recordRequestPath } from '../lifecycle/after-scope';
33
+ import { installNodeConsoleFormat } from '../lifecycle/node-console';
34
+
35
+ /** experimental.testProxy from the loaded next.config. */
36
+ function testProxyEnabled(): boolean {
37
+ const experimental = getNextConfig().experimental as { testProxy?: boolean } | undefined;
38
+ return experimental?.testProxy === true;
39
+ }
40
+
41
+ /** Boot tier: everything that must be installed before the server starts. */
42
+ export function registerLifecycleBootHooks(config: ResolvedConfig): void {
43
+ if (!nextCompatEnabled(config)) return;
44
+ installNodeConsoleFormat();
45
+
46
+ // The user's onRequestError hook (once instrumentation has loaded) receives
47
+ // every real request error; control-flow errors are filtered in the funnel.
48
+ setRequestExtensions({ onRequestError: reportRequestErrorToUser });
49
+
50
+ // Keep the server alive when an SSR error escapes as an unhandled rejection
51
+ // (a client component that throws during server render — preact resolves the
52
+ // string pass to '' and floats the rejection). Without this the process
53
+ // crashes and every later request in the shared harness server fails.
54
+ installUnhandledRejectionGuard();
55
+
56
+ // Load instrumentation and patch fetch at server start. The fetch patch is a no-op until a request
57
+ // activates the test proxy. Instrumentation register() must NOT run during a build: Next only detects
58
+ // the file at build and runs register() at server boot, so build prerenders see a noop tracer - a live
59
+ // TracerProvider at build would bake real span ids into the static shell and 'use cache' entries.
60
+ registerInitHooks((cfg, context) => {
61
+ if (!context.build) loadInstrumentation(cfg);
62
+ installTestProxyFetch();
63
+ });
64
+ }
65
+
66
+ export function registerLifecycleExtensions(config: ResolvedConfig): void {
67
+ if (!nextCompatEnabled(config)) return;
68
+
69
+ const lifecycleInterceptor: RequestInterceptor = async request => {
70
+ // Block the very first requests until instrumentation register() settles.
71
+ await instrumentationReady();
72
+ // Remember the route pathname so an after() callback that runs detached
73
+ // (after a page render) can name the route in its "used ... inside after()"
74
+ // error, matching Next's message.
75
+ try {
76
+ recordRequestPath(new URL(request.url).pathname);
77
+ } catch {
78
+ // ignore malformed URLs
79
+ }
80
+ // Route this request's outgoing fetch through the test proxy when it carries
81
+ // Next-Test-* headers (gated on experimental.testProxy in next.config).
82
+ if (testProxyEnabled()) activateTestProxy(request.headers);
83
+ return undefined;
84
+ };
85
+ registerRequestInterceptors(lifecycleInterceptor);
86
+ }
@@ -0,0 +1,48 @@
1
+ // MDX extension registration (COMPAT).
2
+ //
3
+ // Wires the MDX esbuild plugin into the client and server build graphs so `.mdx`/`.md` modules compile
4
+ // via the JS pipeline. Two integration points:
5
+ //
6
+ // 1. BUNDLER: the MDX plugin is appended to clientEsbuildPlugins and serverEsbuildPlugins.
7
+ // `setBundlerExtensions` REPLACES the factory and register-actions already sets clientEsbuildPlugins,
8
+ // so this COMPOSES with any previously-registered factory rather than clobbering it. Note that
9
+ // `serverEsbuildPlugins` is defined but not yet applied at every server compile site, so until that
10
+ // seam is threaded MDX compiles in the CLIENT graph only; the server factory is registered here so it
11
+ // activates for free once it lands.
12
+ //
13
+ // 2. PAGE EXTENSIONS: core derives its page/convention extension list lazily from a base plus whatever
14
+ // compat registers, so the route scanner discovers `page.mdx` and top-level `.mdx` pages once `mdx`/
15
+ // `md` are registered. `pageExtensions` in next.config (as set by @next/mdx's createMDX) is the single
16
+ // source of truth: when the app sets it, exactly the listed extensions core does not already carry are
17
+ // registered, so `.mdx` routes only when the app opted in - matching Next. When none is configured,
18
+ // nothing extra is registered.
19
+ //
20
+ // The seam is additive-only, so core's base `mjs` cannot be removed even if a configured
21
+ // `pageExtensions` omits it - a documented, harmless divergence. The route scanner needs these
22
+ // extensions at boot, so the registration itself lives in register-boot.ts; only the compilation
23
+ // wiring is here.
24
+
25
+ import type { Plugin } from 'esbuild';
26
+ import type { ResolvedConfig } from '../../config';
27
+ import { getBundlerExtensions, setBundlerExtensions } from '../../extensions';
28
+ import { nextCompatEnabled } from '../../render/hooks';
29
+ import { mdxEsbuildPlugin } from '../mdx/plugin';
30
+
31
+ export function registerMdxExtensions(config: ResolvedConfig): void {
32
+ if (!nextCompatEnabled(config)) return;
33
+
34
+ const existing = getBundlerExtensions();
35
+ const priorClient = existing.clientEsbuildPlugins;
36
+ const priorServer = existing.serverEsbuildPlugins;
37
+
38
+ setBundlerExtensions({
39
+ clientEsbuildPlugins: (cfg: ResolvedConfig): Plugin[] => [
40
+ ...priorClient(cfg),
41
+ mdxEsbuildPlugin(config.root),
42
+ ],
43
+ serverEsbuildPlugins: (cfg: ResolvedConfig, opts?): Plugin[] => [
44
+ ...priorServer(cfg, opts),
45
+ mdxEsbuildPlugin(config.root),
46
+ ],
47
+ });
48
+ }
@@ -0,0 +1,36 @@
1
+ // Middleware extension registration (COMPAT - may import core freely). Registers the build step that
2
+ // emits the Next-shaped middleware manifests (middleware-manifest.json +
3
+ // functions-config-manifest.json). The middleware runtime itself is the existing proxy machinery; this
4
+ // module owns only the build-time manifest output.
5
+
6
+ import path from 'node:path';
7
+ import { fileURLToPath } from 'node:url';
8
+ import { registerBuildSteps } from '../../extensions';
9
+ import { nextCompatEnabled } from '../../compat';
10
+ import { findProxyFile, proxyExternalLoadTarget } from '../../proxy';
11
+ import { devServerModuleHref } from '../../dev/imports';
12
+ import { toPosixPath } from '../../utils/fs';
13
+ import type { RouteManifestEntry } from '../../types';
14
+ import { writeMiddlewareManifests } from '../middleware/manifest';
15
+
16
+ export function registerMiddlewareExtensions(): void {
17
+ registerBuildSteps(async ({ config, routes }) => {
18
+ if (!nextCompatEnabled(config)) return;
19
+ const file = findProxyFile(config);
20
+ let relative: string | undefined;
21
+ if (file) {
22
+ // Must name the SAME artifact buildProxyModule emits (the build copies it to
23
+ // .next/server/middleware.js), so every option that keys the compile profile is spelled out here - a
24
+ // divergence would be a second full compile of the proxy AND a manifest entrypoint pointing at a copy
25
+ // the build never emitted. Same href, so this joins that build's promise.
26
+ const href = await devServerModuleHref(config, file, 'prod', {
27
+ conditionTarget: 'edge',
28
+ externalLoadTarget: proxyExternalLoadTarget(file),
29
+ reactServerLayer: true,
30
+ });
31
+ relative = toPosixPath(path.relative(config.outPath, fileURLToPath(href)));
32
+ }
33
+ // Edge-runtime segments produce manifest entries even with no middleware.
34
+ await writeMiddlewareManifests(config, relative, routes as RouteManifestEntry[]);
35
+ });
36
+ }
@@ -0,0 +1,44 @@
1
+ // Misc long-tail compat cluster registration (COMPAT).
2
+ //
3
+ // The misc singletons in this cluster (temporary-references, actions-streaming) hook the server-action
4
+ // return path directly through the shared action endpoint, and their client counterparts live inline in
5
+ // the action-client runtime bundle - there is no core registry seam to populate for them. The rest of the
6
+ // cluster is satisfied by existing core/compat behavior, so this registrar is a stable no-op hook.
7
+ //
8
+ // Kept as an explicit registrar rather than nothing, so future misc features that DO need a registry
9
+ // have an owned place to register without touching another file.
10
+
11
+ import type { ResolvedConfig } from '../../config';
12
+ import { taintObjectReference } from '../../utils/serialize';
13
+ import { getNextConfig } from '../next/config-loader';
14
+
15
+ // Next's `experimental.taint` message for a `process.env` reference reaching a
16
+ // client component (asserted verbatim by test/e2e/app-dir/taint in dev; prod
17
+ // sees the redacted React #441 text via the normal boundary error path).
18
+ const PROCESS_ENV_TAINT_MESSAGE =
19
+ 'Do not pass process.env to Client Components since it will leak sensitive data';
20
+
21
+ // Prod redacts every RSC serialization error to React's minified #441 text
22
+ // (test/e2e/app-dir/taint asserts this verbatim for a production build).
23
+ const REDACTED_RSC_ERROR_MESSAGE =
24
+ 'Minified React error #441; visit https://react.dev/errors/441 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.';
25
+
26
+ export function registerMiscExtensions(_config: ResolvedConfig): void {
27
+ // No registry wiring required for the current misc cluster; behavior is
28
+ // activated via direct imports in the action endpoint + client runtime.
29
+ registerTaintedReferences();
30
+ }
31
+
32
+ /**
33
+ * `experimental.taint`: React's taint APIs do not exist under preact, so the client-props serializer
34
+ * enforces the same contract by identity - registering `process.env` makes any client-component prop that
35
+ * IS that object throw.
36
+ */
37
+ function registerTaintedReferences(): void {
38
+ const experimental = getNextConfig().experimental as { taint?: unknown } | undefined;
39
+ if (experimental?.taint !== true) return;
40
+ taintObjectReference(
41
+ { dev: PROCESS_ENV_TAINT_MESSAGE, prod: REDACTED_RSC_ERROR_MESSAGE },
42
+ process.env,
43
+ );
44
+ }
@@ -0,0 +1,288 @@
1
+ // OpenTelemetry extension registration (COMPAT).
2
+ //
3
+ // Wires the Next span taxonomy onto core seams without any core edit:
4
+ // - initHooks (build + start): remember the app root (for @opentelemetry/api resolution) and install
5
+ // the AppRender.fetch span wrapper.
6
+ // - requestExtensions.interceptors: open the root BaseServer.handleRequest span (extracting an incoming
7
+ // traceparent) and set its `next.route`/`http.route` from the matched route pattern. Runs late so it
8
+ // observes the request after action-dispatch and rewrites.
9
+ // - requestExtensions.responseFinalizers: close the root span with the final `http.status_code`,
10
+ // pre-flush.
11
+ // - requestExtensions.onRequestError: mark the root span errored for anything the funnel catches.
12
+ //
13
+ // Child spans are emitted from their own compat call sites. The root span alone satisfies the bulk of the
14
+ // opentelemetry suite. Everything is inert unless next compat is on AND @opentelemetry/api resolves from
15
+ // the app.
16
+
17
+ import { readFileSync } from 'node:fs';
18
+ import path from 'node:path';
19
+ import type { ResolvedConfig } from '../../config';
20
+ import type { RouteManifestEntry } from '../../types';
21
+ import {
22
+ registerInitHooks,
23
+ registerRequestInterceptors,
24
+ registerRequestWarmHooks,
25
+ registerResponseFinalizers,
26
+ getRequestExtensions,
27
+ setRequestExtensions,
28
+ type RequestInterceptor,
29
+ type ResponseFinalizer,
30
+ } from '../../extensions';
31
+ import { nextCompatEnabled } from '../index';
32
+ import { getRequestRuntime } from '../../routing/request-runtime';
33
+ import { selectRouteForRequest } from '../../routing/routes';
34
+ import { queueAfterTask } from '../../request/context';
35
+ import {
36
+ getDocumentScriptExtensions,
37
+ setRenderSpanExtensions,
38
+ setDocumentScriptExtensions,
39
+ setStreamBoundaryExtensions,
40
+ } from '../../render/hooks';
41
+ import { setProxyRunObserver } from '../../proxy';
42
+ import {
43
+ SPAN_TYPE,
44
+ emitClientComponentLoadingSpan,
45
+ emitLeafSpan,
46
+ emitStartResponseSpan,
47
+ endRootSpan,
48
+ endRootSpanIfUnclosed,
49
+ markRenderSpanError,
50
+ setOtelAppRoot,
51
+ setRootSpanRoute,
52
+ startRootSpan,
53
+ withChildSpan,
54
+ withMiddlewareSpan,
55
+ withPagesApiHandlerSpan,
56
+ withPagesDataSpan,
57
+ withRenderBodySpan,
58
+ withRouteHandlerSpan,
59
+ } from '../otel/tracer';
60
+ import { getOtelApi } from '../otel/api';
61
+ import { installFetchSpan } from '../otel/fetch-span';
62
+ import { clientTraceMetadataTags } from '../otel/client-trace-metadata';
63
+ import { instrumentationReady } from '../lifecycle/instrumentation';
64
+
65
+ /**
66
+ * The ROOT-span interceptor. Registered FIRST, before every other sub-registrar, so the
67
+ * `BaseServer.handleRequest` span is open before any short-circuiting interceptor (segment `_tree`
68
+ * prefetches, the RSC protocol responder, action dispatch) produces a response - those responses still
69
+ * flow through the response finalizer, which closes the span. The route attributes are stamped
70
+ * immediately from the pre-rewrite match; the LATE interceptor re-stamps them after rewrites.
71
+ */
72
+ export function registerOtelRootInterceptor(config: ResolvedConfig): void {
73
+ if (!nextCompatEnabled(config)) return;
74
+ setOtelAppRoot(config.root);
75
+
76
+ const rootInterceptor: RequestInterceptor = async request => {
77
+ try {
78
+ // Instrumentation register() installs the app's TracerProvider; opening
79
+ // the root span before it completes would produce a non-recording span.
80
+ await instrumentationReady();
81
+ const url = new URL(request.url);
82
+ startRootSpan({
83
+ method: request.method.toUpperCase(),
84
+ target: url.pathname + url.search,
85
+ rsc: request.headers.get('rsc') === '1',
86
+ headers: request.headers,
87
+ });
88
+ stampMatchedRoute(url.pathname);
89
+ // Safety net for the synchronous-500 error path: core's top-level catch
90
+ // returns a bare 500 WITHOUT running responseFinalizers, so the finalizer
91
+ // never closes the root span there. The work-unit after-queue DOES flush
92
+ // on that path (flushWorkUnit in the catch), so end the span as 500 from
93
+ // an after-task. Idempotent: on success paths the finalizer ends it first.
94
+ queueAfterTask(() => endRootSpanIfUnclosed(500));
95
+ } catch {
96
+ // Never let tracing break the request.
97
+ }
98
+ return undefined;
99
+ };
100
+ registerRequestInterceptors(rootInterceptor);
101
+ // Resolving @opentelemetry/api out of the app loads the whole package inside this interceptor on
102
+ // the first request. The result is memoized, so paying it in the dev warm just moves it off that
103
+ // request.
104
+ registerRequestWarmHooks(() => void getOtelApi(config.root));
105
+ }
106
+
107
+ /** Resolve the matched route for `pathname` and stamp it on the root span. */
108
+ function stampMatchedRoute(pathname: string): void {
109
+ const runtime = getRequestRuntime();
110
+ if (!runtime) return;
111
+ const matched = selectRouteForRequest(runtime.routes, pathname, undefined);
112
+ if (!matched) return;
113
+ const routeRuntime = matched.route.segmentConfig?.runtime;
114
+ setRootSpanRoute(routeEntryToDisplay(matched.route), {
115
+ edge: routeRuntime === 'edge' || routeRuntime === 'experimental-edge',
116
+ kind: matched.route.kind === 'handler' ? 'handler' : 'page',
117
+ params: matched.params,
118
+ });
119
+ }
120
+
121
+ export function registerOtelExtensions(config: ResolvedConfig): void {
122
+ if (!nextCompatEnabled(config)) return;
123
+
124
+ const appRoot = config.root;
125
+ setOtelAppRoot(appRoot);
126
+
127
+ // Install the fetch span wrapper at server (and build) start, AFTER the cache
128
+ // fetch-patch has wrapped globalThis.fetch (register order: cache before otel).
129
+ registerInitHooks(() => {
130
+ installFetchSpan(appRoot);
131
+ });
132
+
133
+ // Materialized pages wrappers (compat/pages wrapperSource) call this global —
134
+ // when present — around their getServerSideProps/getStaticProps invocation so
135
+ // the `Render.<kind>` span lands beside the document render span. A global
136
+ // (not an import) keeps the generated bundles pnext-agnostic.
137
+ (
138
+ globalThis as { __PNEXT_PAGES_DATA_SPAN__?: typeof withPagesDataSpan }
139
+ ).__PNEXT_PAGES_DATA_SPAN__ = withPagesDataSpan;
140
+
141
+ // Render-internal spans (nest under the request root span via the work-unit
142
+ // ALS the tracer threads): the render-body span (`render route (app)`), the
143
+ // route-resolution span (`resolve page components`), and cheap leaf
144
+ // segment-module spans. All inert when no root span is open.
145
+ setRenderSpanExtensions({
146
+ withRenderBodySpan: (route, fn) => {
147
+ const displayRoute = routePatternToDisplay(route);
148
+ // A materialized pages route renders through the app pipeline, but Next
149
+ // reports it as the pages-router document render span.
150
+ if (isPagesCompatRoute(route)) {
151
+ return withRenderBodySpan(
152
+ `render route (pages) ${displayRoute}`,
153
+ displayRoute,
154
+ fn,
155
+ SPAN_TYPE.renderDocument,
156
+ );
157
+ }
158
+ return withRenderBodySpan(
159
+ `render route (app) ${displayRoute}`,
160
+ displayRoute,
161
+ fn,
162
+ );
163
+ },
164
+ withFindPageComponentsSpan: (route, fn) => {
165
+ const entry = routeEntryFor(route);
166
+ // A materialized pages-API route reports ONLY its Node.runHandler span
167
+ // (Next's pages-api dispatch has no findPageComponents phase).
168
+ if (entry?.kind === 'handler' && isPagesCompatEntry(entry)) return fn();
169
+ const displayRoute = routePatternToDisplay(route);
170
+ return withChildSpan(
171
+ 'resolve page components',
172
+ SPAN_TYPE.findPageComponents,
173
+ { 'next.route': displayRoute },
174
+ fn,
175
+ );
176
+ },
177
+ emitResolveSegmentSpan: segment =>
178
+ emitLeafSpan('resolve segment modules', SPAN_TYPE.getLayoutOrPageModule, {
179
+ 'next.segment': segment,
180
+ }),
181
+ withRouteHandlerSpan: (route, fn) =>
182
+ isPagesCompatRoute(route)
183
+ ? withPagesApiHandlerSpan(routePatternToDisplay(route), fn)
184
+ : withRouteHandlerSpan(routePatternToDisplay(route), fn),
185
+ });
186
+ setStreamBoundaryExtensions({ onStreamBoundaryError: markRenderSpanError });
187
+
188
+ // clientTraceMetadata meta tags injected once into the document head (dynamic pages only; a production
189
+ // start skips static). Composed with register-render's documentBodyScripts under a separate key.
190
+ // The renderer's `ctx.dynamic` already encodes Next's gating: dev renders are always dynamic, a prod
191
+ // STATIC page is dynamic:false, a prod DYNAMIC page is dynamic:true. So isNextStart:true is safe -
192
+ // clientTraceMetadataTags only drops when isNextStart && !dynamic, exactly the prod-static case.
193
+ const previousHeadTags = getDocumentScriptExtensions().documentHeadTags;
194
+ setDocumentScriptExtensions({
195
+ documentHeadTags: (cfg, ctx) =>
196
+ `${previousHeadTags?.(cfg, ctx) ?? ''}${clientTraceMetadataTags({ dynamic: ctx.dynamic, isNextStart: true, rsc: ctx.rsc })}`,
197
+ });
198
+
199
+ // Middleware.execute span around the proxy/middleware handler run. Parents
200
+ // under the incoming traceparent (top-level trace), NOT the request root span.
201
+ setProxyRunObserver((request, fn) => withMiddlewareSpan(request, fn));
202
+
203
+ const previousOnRequestError = getRequestExtensions().onRequestError;
204
+ setRequestExtensions({
205
+ onRequestError: async (error, requestInfo, context) => {
206
+ markRenderSpanError(error);
207
+ await previousOnRequestError(error, requestInfo, context);
208
+ },
209
+ });
210
+
211
+ // Late interceptor: re-stamp the route attributes after the rewrite/action
212
+ // interceptors ran, so a rewritten request reports its DESTINATION route
213
+ // (the root span itself was opened by the early interceptor with the
214
+ // original target — see registerOtelRootInterceptor).
215
+ const otelRouteInterceptor: RequestInterceptor = request => {
216
+ try {
217
+ stampMatchedRoute(new URL(request.url).pathname);
218
+ } catch {
219
+ // Never let tracing break the request.
220
+ }
221
+ return Promise.resolve(undefined);
222
+ };
223
+ registerRequestInterceptors(otelRouteInterceptor);
224
+
225
+ // Close the root span pre-flush with the final status. Runs on every response-producing path (page
226
+ // render, route handler, static file, redirect, 404). Before closing, emit the pre-flush leaf spans Next
227
+ // nests in the tree: `clientComponentLoading` (page renders only) and `start response` under the open
228
+ // render span for pages, or the root for handlers.
229
+ const otelFinalizer: ResponseFinalizer = ctx => {
230
+ try {
231
+ if (ctx.routeKind === 'html') emitClientComponentLoadingSpan(0);
232
+ if (ctx.routeKind === 'html' || ctx.routeKind === 'route-handler') {
233
+ emitStartResponseSpan();
234
+ }
235
+ endRootSpan(ctx.status);
236
+ } catch {
237
+ // ignore
238
+ }
239
+ };
240
+ registerResponseFinalizers(otelFinalizer);
241
+ }
242
+
243
+ /** The runtime route entry matching a raw route pattern. */
244
+ function routeEntryFor(routePattern: string): RouteManifestEntry | undefined {
245
+ return getRequestRuntime()?.routes.find(r => r.route === routePattern);
246
+ }
247
+
248
+ // A hybrid app materializes BOTH trees under `pnext-pages-compat`: native app
249
+ // files become `source-app/...` shims, pages files become `source-pages/...`
250
+ // wrappers. Only the latter are pages-router routes. The import specifier is a
251
+ // stable generator-owned marker; cache per file (routes don't change at start).
252
+ const pagesCompatFileCache = new Map<string, boolean>();
253
+ function isPagesCompatEntry(entry: RouteManifestEntry | undefined): boolean {
254
+ if (!entry?.file.includes(`${path.sep}pnext-pages-compat${path.sep}`)) return false;
255
+ let cached = pagesCompatFileCache.get(entry.file);
256
+ if (cached === undefined) {
257
+ try {
258
+ cached = readFileSync(entry.file, 'utf8').includes('source-pages/');
259
+ } catch {
260
+ cached = false;
261
+ }
262
+ pagesCompatFileCache.set(entry.file, cached);
263
+ }
264
+ return cached;
265
+ }
266
+
267
+ /** Whether `routePattern` matches a route materialized from `pages/`. */
268
+ function isPagesCompatRoute(routePattern: string): boolean {
269
+ return isPagesCompatEntry(routeEntryFor(routePattern));
270
+ }
271
+
272
+ function routeEntryToDisplay(route: RouteManifestEntry): string {
273
+ let value = route.route || '/';
274
+ if (route.catchAll) {
275
+ const token = route.catchAllOptional
276
+ ? `[[...${route.catchAll}]]`
277
+ : `[...${route.catchAll}]`;
278
+ value = value.replace(`:${route.catchAll}*`, token);
279
+ }
280
+ for (const param of route.params) value = value.replace(`:${param}`, `[${param}]`);
281
+ return value;
282
+ }
283
+
284
+ function routePatternToDisplay(route: string): string {
285
+ return route
286
+ .replace(/:([A-Za-z0-9_]+)\*/g, '[...$1]')
287
+ .replace(/:([A-Za-z0-9_]+)/g, '[$1]');
288
+ }