@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,28 @@
1
+ import { requireRequest, requestApiPromise } from '../../request/context';
2
+ import { assertRequestApiAllowedInAfter } from '../lifecycle/after-scope';
3
+ import { assertNoDynamicApiInsideCache } from '../cache/revalidate';
4
+ import { assertDynamicErrorRequestApi } from './headers';
5
+
6
+ export { after } from '../lifecycle/after';
7
+ export { io } from '../ppr/io';
8
+ export { NextRequest, NextResponse } from '../../api/server';
9
+ export type { NextRequestGeo } from '../../api/server';
10
+ export type { NextFetchEvent } from '../../types';
11
+ export type { ProxyConfig } from '../../proxy';
12
+ export { ImageResponse } from './og';
13
+ // Pure UA/URLPattern helpers live in a client-safe module so the client
14
+ // `next/server` variant (client-server.ts) can share them without pulling this
15
+ // file's node:async_hooks imports into the browser bundle.
16
+ export { URLPattern, userAgent, userAgentFromString } from './user-agent';
17
+ export type { UserAgent } from './user-agent';
18
+
19
+ /** Marks the surrounding scope as dynamic, like headers()/cookies(). */
20
+ export function connection(): Promise<Record<never, never>> {
21
+ assertRequestApiAllowedInAfter('connection()');
22
+ assertDynamicErrorRequestApi('connection()');
23
+ assertNoDynamicApiInsideCache('connection()');
24
+ return requestApiPromise('connection()', () => {
25
+ requireRequest('connection()');
26
+ return {};
27
+ });
28
+ }
@@ -0,0 +1,58 @@
1
+ // SVGR-style `.svg`-as-component detection + inline SVG component generation (COMPAT).
2
+ //
3
+ // Projects commonly wire `@svgr/webpack` into next.config's `webpack()` to import `.svg` files as
4
+ // React/Preact components instead of static asset URLs. pnext has no webpack graph to run that loader
5
+ // against, but the overwhelming majority of configurations use its stock defaults, so detect the
6
+ // reference and reproduce the import-as-component semantics directly against core's `staticAssetModule`
7
+ // seam (see image/static-metadata.ts) instead of executing the loader.
8
+
9
+ let svgAsComponent = false;
10
+
11
+ /** Derived per config load (see config-loader's setNextConfig) — never a process one-shot. */
12
+ export function setSvgAsComponentEnabled(enabled: boolean): void {
13
+ svgAsComponent = enabled;
14
+ }
15
+
16
+ export function isSvgAsComponentEnabled(): boolean {
17
+ return svgAsComponent;
18
+ }
19
+
20
+ /** True when next.config's `webpack()` references `@svgr/webpack` (the common custom-loader use). */
21
+ export function webpackReferencesSvgr(config: { webpack?: unknown }): boolean {
22
+ return typeof config.webpack === 'function' && String(config.webpack).includes('@svgr/webpack');
23
+ }
24
+
25
+ const XML_PROLOGUE = /^\uFEFF?\s*(?:<\?xml[^>]*\?>\s*)?(?:<!DOCTYPE[^>]*>\s*)?/i;
26
+ const SVG_TAG = /^<svg([^>]*)>([\s\S]*)<\/svg>\s*$/i;
27
+ const ATTR = /([a-zA-Z_:][-a-zA-Z0-9_:.]*)\s*=\s*"([^"]*)"|([a-zA-Z_:][-a-zA-Z0-9_:.]*)\s*=\s*'([^']*)'/g;
28
+
29
+ function parseRootAttrs(raw: string): Record<string, string> {
30
+ const attrs: Record<string, string> = {};
31
+ for (const match of raw.matchAll(ATTR)) {
32
+ const name = match[1] ?? match[3];
33
+ const value = match[2] ?? match[4] ?? '';
34
+ if (name) attrs[name] = value;
35
+ }
36
+ return attrs;
37
+ }
38
+
39
+ /**
40
+ * Generate the ESM module text an SVGR-mode `.svg` import evaluates to: a Preact component rendering the
41
+ * SVG inline. Root attributes spread first so a caller's `className`/`width`/`height`/etc. props override
42
+ * them — matching `@svgr/webpack`'s default output semantics. Identical for server and client bundles, so
43
+ * hydration sees the same markup the server rendered.
44
+ */
45
+ export function svgComponentModule(bytes: Uint8Array): string {
46
+ const text = new TextDecoder().decode(bytes).replace(XML_PROLOGUE, '').trim();
47
+ const match = SVG_TAG.exec(text);
48
+ const rootAttrs = match ? parseRootAttrs(match[1] ?? '') : {};
49
+ const inner = match ? match[2] : text;
50
+ return `import { h } from 'preact';
51
+ const __pnextSvgAttrs = ${JSON.stringify(rootAttrs)};
52
+ const __pnextSvgInner = ${JSON.stringify(inner)};
53
+ function SvgComponent(props) {
54
+ return h('svg', { ...__pnextSvgAttrs, ...props, dangerouslySetInnerHTML: { __html: __pnextSvgInner } });
55
+ }
56
+ export default SvgComponent;
57
+ `;
58
+ }
@@ -0,0 +1,77 @@
1
+ // Telemetry debug emission (COMPAT).
2
+ //
3
+ // Next prints every telemetry event to stdout when NEXT_TELEMETRY_DEBUG is set: `[telemetry] ` plus a
4
+ // pretty-printed `{ eventName, payload }`. Harnesses parse that output with a regex, so the two-space
5
+ // indentation (closing brace at column 0) is part of the contract. pnext sends nothing anywhere - this
6
+ // is wire-format parity only, emitted once per CLI session after next.config loads.
7
+
8
+ import type { NextConfigObject } from './config-loader';
9
+
10
+ const EVENT_CLI_SESSION_STARTED = 'NEXT_CLI_SESSION_STARTED';
11
+ const EVENT_BUILD_FEATURE_USAGE = 'NEXT_BUILD_FEATURE_USAGE';
12
+
13
+ let emitted = false;
14
+ let featureUsageEmitted = false;
15
+
16
+ function configuredStaleTimes(config: NextConfigObject): { static?: number; dynamic?: number } {
17
+ const experimental = config.experimental;
18
+ if (!experimental || typeof experimental !== 'object') return {};
19
+ const staleTimes = (experimental as { staleTimes?: unknown }).staleTimes;
20
+ if (!staleTimes || typeof staleTimes !== 'object') return {};
21
+ const value = staleTimes as { static?: unknown; dynamic?: unknown };
22
+ return {
23
+ ...(typeof value.static === 'number' ? { static: value.static } : {}),
24
+ ...(typeof value.dynamic === 'number' ? { dynamic: value.dynamic } : {}),
25
+ };
26
+ }
27
+
28
+ /** Print the session-started telemetry event when NEXT_TELEMETRY_DEBUG is on. */
29
+ export function emitSessionStartedTelemetry(config: NextConfigObject): void {
30
+ if (emitted) return;
31
+ // eslint-disable-next-line turbo/no-undeclared-env-vars
32
+ if (!process.env.NEXT_TELEMETRY_DEBUG) return;
33
+ emitted = true;
34
+ const staleTimes = configuredStaleTimes(config);
35
+ const event = {
36
+ eventName: EVENT_CLI_SESSION_STARTED,
37
+ payload: {
38
+ nodeVersion: process.version,
39
+ cliCommand: process.argv[2] ?? 'unknown',
40
+ staticStaleTime: staleTimes.static ?? null,
41
+ dynamicStaleTime: staleTimes.dynamic ?? null,
42
+ },
43
+ };
44
+ console.log(`[telemetry] ${JSON.stringify(event, null, 2)}`);
45
+ }
46
+
47
+ /**
48
+ * Print `NEXT_BUILD_FEATURE_USAGE` events for the next.config features the suites assert on.
49
+ * Build-command only, matching Next (the event is produced by the build pipeline, not by start). Payload
50
+ * shape is exactly `{ featureName, invocationCount }` - the upstream assertions use `toContainEqual`, so
51
+ * any extra key fails the deep match.
52
+ */
53
+ export function emitBuildFeatureUsageTelemetry(config: NextConfigObject): void {
54
+ if (featureUsageEmitted) return;
55
+ // eslint-disable-next-line turbo/no-undeclared-env-vars
56
+ if (!process.env.NEXT_TELEMETRY_DEBUG) return;
57
+ if ((process.argv[2] ?? '') !== 'build') return;
58
+ featureUsageEmitted = true;
59
+ const experimental = config.experimental;
60
+ const esmExternals =
61
+ experimental && typeof experimental === 'object'
62
+ ? (experimental as { esmExternals?: unknown }).esmExternals
63
+ : undefined;
64
+ // Next counts a feature as "used" only when it is set away from its default.
65
+ if (esmExternals !== undefined && esmExternals !== true) {
66
+ console.log(
67
+ `[telemetry] ${JSON.stringify(
68
+ {
69
+ eventName: EVENT_BUILD_FEATURE_USAGE,
70
+ payload: { featureName: 'esmExternals', invocationCount: 1 },
71
+ },
72
+ null,
73
+ 2,
74
+ )}`,
75
+ );
76
+ }
77
+ }
@@ -0,0 +1,100 @@
1
+ // Pure (client-safe) `next/server` helpers: userAgent parsing + URLPattern.
2
+ //
3
+ // These carry no request scope and import no node:* builtins, so both the
4
+ // server entry (server.ts) and the client-safe entry (client-server.ts)
5
+ // re-export them. Kept in their own module so the client `next/server` variant
6
+ // can pull them in without dragging server.ts's node:async_hooks imports
7
+ // (request/context, ppr, cache/revalidate) into the browser bundle.
8
+
9
+ /** Native URLPattern when the runtime provides one (Bun/Node 23+/browsers). */
10
+ export const URLPattern = (globalThis as { URLPattern?: unknown }).URLPattern;
11
+
12
+ export interface UserAgent {
13
+ ua: string;
14
+ browser: { name?: string; version?: string };
15
+ os: { name?: string; version?: string };
16
+ device: { type?: string; vendor?: string; model?: string };
17
+ engine: { name?: string; version?: string };
18
+ cpu: { architecture?: string };
19
+ isBot: boolean;
20
+ }
21
+
22
+ const botPattern =
23
+ /bot|crawler|spider|crawling|slurp|bingpreview|facebookexternalhit|mediapartners|headless/i;
24
+
25
+ export function userAgentFromString(input: string | undefined): UserAgent {
26
+ const ua = input ?? '';
27
+ return {
28
+ ua,
29
+ browser: parseBrowser(ua),
30
+ os: parseOs(ua),
31
+ device: parseDevice(ua),
32
+ engine: parseEngine(ua),
33
+ cpu: parseCpu(ua),
34
+ isBot: botPattern.test(ua),
35
+ };
36
+ }
37
+
38
+ export function userAgent({ headers }: { headers: Headers }): UserAgent {
39
+ return userAgentFromString(headers.get('user-agent') ?? undefined);
40
+ }
41
+
42
+ function parseBrowser(ua: string): UserAgent['browser'] {
43
+ const edge = ua.match(/Edg(?:e|A|iOS)?\/([\d.]+)/);
44
+ if (edge) return { name: 'Edge', version: edge[1] };
45
+ const samsung = ua.match(/SamsungBrowser\/([\d.]+)/);
46
+ if (samsung) return { name: 'Samsung Internet', version: samsung[1] };
47
+ const chrome = ua.match(/(?:Chrome|CriOS)\/([\d.]+)/);
48
+ if (chrome) return { name: 'Chrome', version: chrome[1] };
49
+ const firefox = ua.match(/(?:Firefox|FxiOS)\/([\d.]+)/);
50
+ if (firefox) return { name: 'Firefox', version: firefox[1] };
51
+ if (ua.includes('Safari')) return { name: 'Safari', version: ua.match(/Version\/([\d.]+)/)?.[1] };
52
+ return {};
53
+ }
54
+
55
+ function parseEngine(ua: string): UserAgent['engine'] {
56
+ const gecko = ua.match(/rv:([\d.]+)\).*Gecko/);
57
+ if (gecko) return { name: 'Gecko', version: gecko[1] };
58
+ const webkit = ua.match(/AppleWebKit\/([\d.]+)/);
59
+ if (webkit) {
60
+ const chrome = ua.match(/(?:Chrome|CriOS|Edg(?:e|A|iOS)?|OPR)\/([\d.]+)/);
61
+ if (chrome) return { name: 'Blink', version: chrome[1] };
62
+ return { name: 'WebKit', version: webkit[1] };
63
+ }
64
+ return {};
65
+ }
66
+
67
+ function parseCpu(ua: string): UserAgent['cpu'] {
68
+ if (/arm64|aarch64/i.test(ua)) return { architecture: 'arm64' };
69
+ if (/\barm\b/i.test(ua)) return { architecture: 'arm' };
70
+ if (/x86_64|x64|Win64|WOW64/i.test(ua)) return { architecture: 'amd64' };
71
+ if (/i686|\bx86\b/i.test(ua)) return { architecture: 'ia32' };
72
+ return {};
73
+ }
74
+
75
+ function parseOs(ua: string): UserAgent['os'] {
76
+ if (ua.includes('Windows')) return { name: 'Windows', version: ua.match(/Windows NT ([\d.]+)/)?.[1] };
77
+ if (ua.includes('Android')) return { name: 'Android', version: ua.match(/Android ([\d.]+)/)?.[1] };
78
+ if (/iPhone|iPad|iPod/.test(ua)) {
79
+ return { name: 'iOS', version: ua.match(/OS (\d+(?:[_.]\d+)*)/)?.[1]?.replace(/_/g, '.') };
80
+ }
81
+ if (ua.includes('Mac OS X')) {
82
+ return { name: 'Mac OS', version: ua.match(/Mac OS X (\d+(?:[_.]\d+)*)/)?.[1]?.replace(/_/g, '.') };
83
+ }
84
+ if (ua.includes('Linux')) return { name: 'Linux' };
85
+ return {};
86
+ }
87
+
88
+ function parseDevice(ua: string): UserAgent['device'] {
89
+ if (ua.includes('iPhone')) return { type: 'mobile', vendor: 'Apple', model: 'iPhone' };
90
+ if (ua.includes('iPad')) return { type: 'tablet', vendor: 'Apple', model: 'iPad' };
91
+ if (ua.includes('Android')) {
92
+ const type = ua.includes('Mobile') ? 'mobile' : 'tablet';
93
+ const samsung = ua.match(/\b(SM-[\w]+)\b/);
94
+ if (samsung) return { type, vendor: 'Samsung', model: samsung[1] };
95
+ const pixel = ua.match(/;\s*(Pixel[\w ]*?)\s*(?:Build|\))/);
96
+ if (pixel) return { type, vendor: 'Google', model: pixel[1] };
97
+ return { type };
98
+ }
99
+ return ua.includes('Mobile') ? { type: 'mobile' } : {};
100
+ }
@@ -0,0 +1,56 @@
1
+ 'use client';
2
+
3
+ // `next/web-vitals` compat surface. Next measures Core Web Vitals (plus its own Next.js-* custom
4
+ // metrics) and invokes the reporter callback per registered hook instance. The Core Web Vitals are
5
+ // backed by the `web-vitals` package - this is browser-bundled client code, so the import stays a plain
6
+ // static import for the bundler to resolve. Next's own custom metrics are not emitted here.
7
+ import { useEffect, useRef } from 'preact/hooks';
8
+ import * as webVitals from 'web-vitals';
9
+ import type { Metric } from 'web-vitals';
10
+
11
+ export interface NextWebVitalsMetric {
12
+ id: string;
13
+ name: string;
14
+ startTime: number;
15
+ value: number;
16
+ label: 'web-vital' | 'custom';
17
+ }
18
+
19
+ export function useReportWebVitals(
20
+ reportWebVitalsFn: (metric: NextWebVitalsMetric) => void,
21
+ ): void {
22
+ // Route metrics through a ref so the latest reporter identity receives them
23
+ // without resubscribing to web-vitals on every render.
24
+ const reporterRef = useRef(reportWebVitalsFn);
25
+ useEffect(() => {
26
+ reporterRef.current = reportWebVitalsFn;
27
+ }, [reportWebVitalsFn]);
28
+
29
+ useEffect(() => {
30
+ const report = (metric: Metric): void => {
31
+ reporterRef.current({
32
+ id: metric.id,
33
+ name: metric.name,
34
+ startTime: metric.entries[0]?.startTime ?? 0,
35
+ value: metric.value,
36
+ label: 'web-vital',
37
+ });
38
+ };
39
+
40
+ webVitals.onTTFB(report);
41
+ webVitals.onFCP(report);
42
+ webVitals.onLCP(report);
43
+ // CLS and INP accumulate over the page lifetime and, by default, only settle
44
+ // when the page is hidden. A page that is never hidden (or one torn down by a
45
+ // navigation before the visibilitychange flush lands) therefore never reports
46
+ // them at all. Both metrics are documented as multi-report: `reportAllChanges`
47
+ // emits each new value as it is determined instead of a single deferred one,
48
+ // so opting in makes delivery deterministic without dropping any information.
49
+ webVitals.onCLS(report, { reportAllChanges: true });
50
+ webVitals.onINP(report, { reportAllChanges: true });
51
+ // `onFID` is deprecated (removed in newer majors); subscribe only if present.
52
+ if (typeof webVitals.onFID === 'function') {
53
+ webVitals.onFID(report);
54
+ }
55
+ }, []);
56
+ }
@@ -0,0 +1,95 @@
1
+ // @opentelemetry/api loader + thin typed surface (COMPAT).
2
+ //
3
+ // pnext emits Next's span taxonomy through the GLOBAL OpenTelemetry API the app's instrumentation.ts
4
+ // registers. Only `@opentelemetry/api` (the stable facade) is ever touched; the app supplies the SDK.
5
+ // The api package is an OPTIONAL runtime dependency: absent, every helper is an inert no-op so a
6
+ // pure-core app is byte-identical.
7
+ //
8
+ // Resolution: `@opentelemetry/api` is not vendored into pnext (it would pin a version and duplicate the
9
+ // singleton the app registered). It is resolved from the app's own node_modules, so pnext and the app
10
+ // share ONE api singleton - the same module instance the app's provider.register() mutated. A bare
11
+ // import would resolve against pnext's location and never see the registered provider.
12
+
13
+ import { createRequire } from 'node:module';
14
+ import path from 'node:path';
15
+
16
+ // Structural subset of @opentelemetry/api we use. Kept local so pnext carries no
17
+ // type dependency on the package (it may be absent).
18
+ export interface OtelSpanContext {
19
+ traceId: string;
20
+ spanId: string;
21
+ traceFlags: number;
22
+ }
23
+
24
+ export interface OtelSpan {
25
+ setAttribute(key: string, value: unknown): OtelSpan;
26
+ setAttributes(attrs: Record<string, unknown>): OtelSpan;
27
+ setStatus(status: { code: number; message?: string }): OtelSpan;
28
+ recordException(error: unknown): void;
29
+ updateName(name: string): OtelSpan;
30
+ end(endTime?: number): void;
31
+ spanContext(): OtelSpanContext;
32
+ isRecording(): boolean;
33
+ }
34
+
35
+ export interface OtelContext {
36
+ // opaque
37
+ readonly __brand?: 'otel-context';
38
+ }
39
+
40
+ export interface OtelTracer {
41
+ startSpan(
42
+ name: string,
43
+ options?: { kind?: number; attributes?: Record<string, unknown>; startTime?: number },
44
+ context?: OtelContext,
45
+ ): OtelSpan;
46
+ }
47
+
48
+ export interface OtelApi {
49
+ trace: {
50
+ getTracer(name: string, version?: string): OtelTracer;
51
+ getSpan(context: OtelContext): OtelSpan | undefined;
52
+ getSpanContext(context: OtelContext): OtelSpanContext | undefined;
53
+ setSpan(context: OtelContext, span: OtelSpan): OtelContext;
54
+ setSpanContext(context: OtelContext, sc: OtelSpanContext): OtelContext;
55
+ };
56
+ context: {
57
+ active(): OtelContext;
58
+ with<T>(context: OtelContext, fn: () => T): T;
59
+ };
60
+ propagation: {
61
+ extract(context: OtelContext, carrier: unknown, getter?: unknown): OtelContext;
62
+ inject(context: OtelContext, carrier: unknown, setter?: unknown): void;
63
+ fields(): string[];
64
+ };
65
+ ROOT_CONTEXT: OtelContext;
66
+ SpanKind: { INTERNAL: number; SERVER: number; CLIENT: number; PRODUCER: number; CONSUMER: number };
67
+ SpanStatusCode: { UNSET: number; OK: number; ERROR: number };
68
+ TraceFlags: { NONE: number; SAMPLED: number };
69
+ }
70
+
71
+ let resolved: OtelApi | null | undefined;
72
+
73
+ /**
74
+ * Load `@opentelemetry/api` from the app root (once). Returns null when the
75
+ * package is not installed — callers then no-op. Never throws.
76
+ */
77
+ export function getOtelApi(appRoot: string): OtelApi | null {
78
+ if (resolved !== undefined) return resolved;
79
+ resolved = null;
80
+ try {
81
+ // Resolve against a file inside the app root so Node walks the app's
82
+ // node_modules (where instrumentation.ts's @opentelemetry/api lives).
83
+ const req = createRequire(path.join(appRoot, 'package.json'));
84
+ const api = req('@opentelemetry/api') as OtelApi;
85
+ if (api?.trace && api.context) resolved = api;
86
+ } catch {
87
+ resolved = null;
88
+ }
89
+ return resolved;
90
+ }
91
+
92
+ /** Test/bootstrap reset. */
93
+ export function resetOtelApi(): void {
94
+ resolved = undefined;
95
+ }
@@ -0,0 +1,71 @@
1
+ // experimental.clientTraceMetadata (COMPAT).
2
+ //
3
+ // For each key listed in `experimental.clientTraceMetadata`, inject a `<meta name="<key>"
4
+ // content="<value>">` into the HTML head, where the value comes from running the app's GLOBAL
5
+ // propagator inject() against the active render's span context. The app's propagator decides which keys
6
+ // carry a value; keys with no injected value are skipped, and keys the propagator sets but that are not
7
+ // in the config list are dropped.
8
+ //
9
+ // Gating (matches Next): only DYNAMIC renders, and only in production - a prod STATIC page emits
10
+ // nothing, while dev emits for static too. The tags are produced once per document render, so soft navs
11
+ // never mutate them.
12
+
13
+ import { getNextConfig } from '../next/config-loader';
14
+ import { activeOtelContext, carrierSetter } from './tracer';
15
+
16
+ /**
17
+ * Return the clientTraceMetadata `<meta>` tag HTML for the current render, or ''
18
+ * when the feature is off / not applicable. `dynamic` is true when the render is
19
+ * request-dependent (Next only injects on dynamic renders in prod). Values are
20
+ * escaped by the caller's head-composition path if needed; keys/values here come
21
+ * from config + the propagator and are attribute-safe in practice, but we escape
22
+ * defensively.
23
+ */
24
+ export function clientTraceMetadataTags(input: {
25
+ dynamic: boolean;
26
+ isNextStart: boolean;
27
+ rsc: boolean;
28
+ }): string {
29
+ const keys = configuredKeys();
30
+ if (keys.length === 0) return '';
31
+ if (input.rsc) return '';
32
+ // Prod + static → no injection. Dev injects for static too (handled by the
33
+ // caller passing dynamic=true in dev, since a dev render is never prebuilt).
34
+ if (input.isNextStart && !input.dynamic) return '';
35
+
36
+ const active = activeOtelContext();
37
+ if (!active) return '';
38
+ const { api, context } = active;
39
+
40
+ const carrier: Record<string, string> = {};
41
+ try {
42
+ api.propagation.inject(context, carrier, carrierSetter);
43
+ } catch {
44
+ return '';
45
+ }
46
+
47
+ const tags: string[] = [];
48
+ for (const key of keys) {
49
+ const value = carrier[key];
50
+ if (value === undefined || value === null) continue;
51
+ tags.push(`<meta name="${escapeAttr(key)}" content="${escapeAttr(String(value))}"/>`);
52
+ }
53
+ return tags.join('');
54
+ }
55
+
56
+ function configuredKeys(): string[] {
57
+ const experimental = getNextConfig().experimental as
58
+ | { clientTraceMetadata?: unknown }
59
+ | undefined;
60
+ const list = experimental?.clientTraceMetadata;
61
+ if (!Array.isArray(list)) return [];
62
+ return list.filter((k): k is string => typeof k === 'string');
63
+ }
64
+
65
+ function escapeAttr(value: string): string {
66
+ return value
67
+ .replace(/&/g, '&amp;')
68
+ .replace(/"/g, '&quot;')
69
+ .replace(/</g, '&lt;')
70
+ .replace(/>/g, '&gt;');
71
+ }
@@ -0,0 +1,77 @@
1
+ // AppRender.fetch span (COMPAT).
2
+ //
3
+ // Wraps globalThis.fetch to emit a `fetch <METHOD> <url>` CLIENT span nested under the request's render,
4
+ // for every outgoing fetch made during a render. Installed AFTER the cache fetch-patch (register order:
5
+ // cache before otel) so the span brackets the cache layer too. Disabled by NEXT_OTEL_FETCH_DISABLED=1.
6
+ // Only emits when a root span is open, so build-time and out-of-request fetches pass through untouched.
7
+
8
+ import { SPAN_TYPE, withChildSpan, rootOtelContext, otelExportInProgress } from './tracer';
9
+ import { getOtelApi } from './api';
10
+
11
+ let installed = false;
12
+
13
+ export function installFetchSpan(appRoot: string): void {
14
+ if (installed) return;
15
+ // eslint-disable-next-line turbo/no-undeclared-env-vars
16
+ if (process.env.NEXT_OTEL_FETCH_DISABLED === '1') return;
17
+ if (!getOtelApi(appRoot)) return;
18
+ installed = true;
19
+
20
+ const original = globalThis.fetch.bind(globalThis);
21
+ const patched = async function fetch(
22
+ input: Parameters<typeof globalThis.fetch>[0],
23
+ init?: Parameters<typeof globalThis.fetch>[1],
24
+ ): Promise<Response> {
25
+ // Only trace inside an active request render (root span open).
26
+ if (otelExportInProgress()) return original(input, init);
27
+ if (!rootOtelContext()) return original(input, init);
28
+ const info = describeFetch(input, init);
29
+ if (!info) return original(input, init);
30
+ const name = `fetch ${info.method} ${info.url}`;
31
+ return withChildSpan(
32
+ name,
33
+ SPAN_TYPE.fetch,
34
+ {
35
+ 'http.method': info.method,
36
+ 'http.url': info.url,
37
+ 'net.peer.name': info.host,
38
+ },
39
+ () => original(input, init),
40
+ { kind: fetchSpanKind() },
41
+ );
42
+ };
43
+ globalThis.fetch = patched as typeof globalThis.fetch;
44
+ }
45
+
46
+ function fetchSpanKind(): number | undefined {
47
+ // SpanKind.CLIENT (2) — resolved lazily so we don't hold the api reference.
48
+ return 2;
49
+ }
50
+
51
+ function describeFetch(
52
+ input: Parameters<typeof globalThis.fetch>[0],
53
+ init?: Parameters<typeof globalThis.fetch>[1],
54
+ ): { method: string; url: string; host: string } | undefined {
55
+ try {
56
+ let url: string;
57
+ let method = 'GET';
58
+ if (typeof input === 'string' || input instanceof URL) {
59
+ url = String(input);
60
+ method = (init?.method ?? 'GET').toUpperCase();
61
+ } else if (input instanceof Request) {
62
+ url = input.url;
63
+ method = (init?.method ?? input.method).toUpperCase();
64
+ } else {
65
+ return undefined;
66
+ }
67
+ if (!/^https?:/i.test(url)) return undefined;
68
+ const parsed = new URL(url);
69
+ return { method, url: parsed.href, host: parsed.hostname };
70
+ } catch {
71
+ return undefined;
72
+ }
73
+ }
74
+
75
+ export function resetFetchSpanForTest(): void {
76
+ installed = false;
77
+ }