@wular/pnext 0.0.4 → 0.0.7

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 (395) hide show
  1. package/README.md +22 -16
  2. package/bin/pnext +6 -1
  3. package/config/lint/base.js +7 -7
  4. package/config/ts/base.json +2 -4
  5. package/config/ts/react.json +2 -6
  6. package/package.json +23 -2
  7. package/reference/compat.md +87 -22
  8. package/reference/config.md +40 -93
  9. package/reference/css.md +42 -33
  10. package/reference/dev.md +26 -33
  11. package/reference/env.md +18 -20
  12. package/reference/getting-started.md +132 -0
  13. package/reference/metadata.md +31 -46
  14. package/reference/navigation.md +65 -105
  15. package/reference/performance.md +21 -142
  16. package/reference/rendering.md +78 -75
  17. package/reference/routing.md +97 -107
  18. package/reference/typegen.md +27 -29
  19. package/src/api/cache.ts +36 -37
  20. package/src/api/client-cache.ts +2 -2
  21. package/src/api/client-navigation.ts +121 -114
  22. package/src/api/dynamic.tsx +58 -55
  23. package/src/api/link.tsx +52 -53
  24. package/src/api/navigation.ts +59 -58
  25. package/src/api/server.ts +152 -144
  26. package/src/api/suspense.ts +4 -4
  27. package/src/cli/adapters/vercel-warm.ts +126 -121
  28. package/src/cli/adapters/vercel.ts +437 -443
  29. package/src/cli/analyze.ts +333 -144
  30. package/src/cli/{named-bin.ts → boot/named-bin.ts} +37 -37
  31. package/src/cli/{boot-trace.ts → boot/trace.ts} +10 -10
  32. package/src/cli/build.ts +976 -978
  33. package/src/cli/create.ts +72 -64
  34. package/src/cli/dev.ts +116 -116
  35. package/src/cli/index.ts +94 -85
  36. package/src/cli/migrate/package-json.ts +73 -71
  37. package/src/cli/migrate/report.ts +32 -33
  38. package/src/cli/migrate/{index.ts → run.ts} +48 -49
  39. package/src/cli/migrate/scan.ts +46 -46
  40. package/src/cli/migrate/spinner.ts +9 -9
  41. package/src/cli/migrate/tsconfig.ts +35 -35
  42. package/src/cli/{server-entry.ts → serve/entry.ts} +57 -57
  43. package/src/cli/{request-pipeline.ts → serve/pipeline.ts} +386 -394
  44. package/src/cli/{serve-ui.ts → serve/ui.ts} +47 -47
  45. package/src/cli/start.ts +65 -66
  46. package/src/{typegen.ts → cli/typegen.ts} +59 -59
  47. package/src/client/build.ts +802 -768
  48. package/src/client/chunk-fold.ts +245 -240
  49. package/src/client/{paths.ts → chunk-name.ts} +6 -6
  50. package/src/client/entry.ts +162 -147
  51. package/src/client/prebuilt.ts +231 -223
  52. package/src/client/profile.ts +29 -29
  53. package/src/client/react-compiler.ts +20 -15
  54. package/src/client/{compat-surface.ts → react-tier.ts} +64 -64
  55. package/src/client/reference-stub.ts +51 -51
  56. package/src/client/reference.ts +19 -19
  57. package/src/{api → client}/router/events.ts +32 -17
  58. package/src/{api → client}/router/history.ts +16 -16
  59. package/src/{api → client}/router/hub.ts +52 -53
  60. package/src/{api/router.ts → client/router/index.ts} +61 -60
  61. package/src/{api → client}/router/policies.ts +24 -24
  62. package/src/{api → client}/router/runtime.ts +2022 -1995
  63. package/src/{api → client}/router/types.ts +98 -98
  64. package/src/compat/actions/client-plugin.ts +42 -43
  65. package/src/compat/actions/client-stub.ts +14 -14
  66. package/src/compat/actions/{action-client.ts → client.ts} +194 -193
  67. package/src/compat/actions/config.ts +63 -64
  68. package/src/compat/actions/detect.ts +68 -68
  69. package/src/compat/actions/discovery.ts +105 -105
  70. package/src/compat/actions/{action-dispatch.ts → dispatch.ts} +277 -274
  71. package/src/compat/actions/early-submit.ts +1 -1
  72. package/src/compat/actions/endpoint.ts +198 -198
  73. package/src/compat/actions/extensions.ts +811 -0
  74. package/src/compat/actions/flight.ts +23 -23
  75. package/src/compat/actions/form-state.ts +34 -34
  76. package/src/compat/actions/hoist.ts +382 -236
  77. package/src/compat/actions/ids.ts +7 -12
  78. package/src/compat/actions/index.ts +8 -8
  79. package/src/compat/actions/instances.ts +46 -46
  80. package/src/compat/actions/origin.ts +47 -48
  81. package/src/compat/actions/protocol.ts +22 -22
  82. package/src/compat/actions/registry.ts +19 -19
  83. package/src/compat/{misc/action-return.ts → actions/return.ts} +60 -57
  84. package/src/compat/actions/rewrite.ts +125 -125
  85. package/src/compat/actions/{action-router.ts → router.ts} +10 -10
  86. package/src/compat/actions/serve.ts +132 -136
  87. package/src/compat/actions/server-tag.ts +4 -4
  88. package/src/compat/actions/{action-shared.ts → shared.ts} +34 -34
  89. package/src/compat/actions/unrecognized-error.ts +4 -4
  90. package/src/compat/{index.ts → aliases.ts} +112 -109
  91. package/src/compat/bundler/bun-externals.ts +18 -18
  92. package/src/compat/bundler/cjs-exports.ts +271 -223
  93. package/src/compat/bundler/config.ts +116 -111
  94. package/src/compat/bundler/externals.ts +12 -12
  95. package/src/compat/bundler/import-meta-url.ts +19 -19
  96. package/src/compat/bundler/modularize-imports.ts +36 -33
  97. package/src/compat/bundler/new-url-asset.ts +22 -24
  98. package/src/compat/bundler/optimize-package-imports.ts +111 -107
  99. package/src/compat/bundler/polyfill.ts +28 -28
  100. package/src/compat/bundler/react-compiler.ts +35 -29
  101. package/src/compat/bundler/react-profiler.tsx +11 -11
  102. package/src/compat/bundler/relay-transform.ts +48 -47
  103. package/src/compat/bundler/require-context.ts +119 -113
  104. package/src/compat/bundler/resolve-extensions.ts +19 -19
  105. package/src/compat/bundler/source-cache.ts +25 -25
  106. package/src/compat/bundler/static-imports.ts +7 -7
  107. package/src/compat/bundler/symlink-imports.ts +46 -46
  108. package/src/compat/bundler/tsconfig-paths.ts +13 -15
  109. package/src/compat/bundler/wasm.ts +58 -60
  110. package/src/compat/bundler/webpack-loaders.ts +254 -241
  111. package/src/compat/bundler/worker.ts +101 -104
  112. package/src/compat/cache/build-flags.ts +29 -29
  113. package/src/compat/cache/build-prerender-errors.ts +40 -44
  114. package/src/compat/cache/custom-handler.ts +60 -53
  115. package/src/compat/cache/fetch-patch.ts +240 -240
  116. package/src/compat/cache/handler.ts +27 -31
  117. package/src/compat/cache/modern-handler.ts +148 -126
  118. package/src/compat/cache/resume-data-cache.ts +47 -45
  119. package/src/compat/cache/revalidate.ts +233 -232
  120. package/src/compat/cache/runtime-error.ts +35 -35
  121. package/src/compat/cache/use-cache-transform.ts +442 -417
  122. package/src/compat/cache/use-cache.ts +650 -614
  123. package/src/compat/cache-control.ts +140 -142
  124. package/src/compat/client/base-path.ts +21 -20
  125. package/src/compat/client/css-order.ts +18 -18
  126. package/src/compat/client/errors/bare-boundary.ts +11 -11
  127. package/src/compat/client/errors/control-flow.ts +23 -23
  128. package/src/compat/client/errors/error-boundary.ts +61 -61
  129. package/src/compat/client/errors/global-error.ts +101 -91
  130. package/src/compat/client/errors/install.ts +71 -72
  131. package/src/compat/client/errors/lazy.ts +23 -23
  132. package/src/compat/client/errors/primitive-throw.ts +47 -45
  133. package/src/compat/client/errors/soft-refresh.ts +4 -4
  134. package/src/compat/client/link-status.ts +33 -33
  135. package/src/compat/client/{nav-compat-runtime.ts → nav-runtime.ts} +20 -20
  136. package/src/compat/client/{nav-compat.ts → nav.ts} +12 -13
  137. package/src/compat/client/navigation-scroll.ts +63 -63
  138. package/src/compat/client/optimistic-routing.ts +93 -88
  139. package/src/compat/client/prefetch-cache.ts +23 -24
  140. package/src/compat/client/route-announcer.ts +35 -35
  141. package/src/compat/client/segment-cache-policy.ts +20 -20
  142. package/src/compat/client/segment-cache.ts +309 -315
  143. package/src/compat/client/segment-prefetch.ts +127 -132
  144. package/src/compat/client/trailing-slash.ts +5 -4
  145. package/src/compat/css/chunking.ts +113 -116
  146. package/src/compat/css/inline-css.ts +21 -21
  147. package/src/compat/css/lightningcss.ts +37 -38
  148. package/src/compat/css/modules.ts +161 -175
  149. package/src/compat/css/nonce.ts +7 -7
  150. package/src/compat/css/sass-plugin.ts +18 -21
  151. package/src/compat/css/sass.ts +150 -152
  152. package/src/compat/css/styled-jsx-runtime.ts +27 -27
  153. package/src/compat/css/styled-jsx.ts +21 -21
  154. package/src/compat/edge-runtime.ts +27 -27
  155. package/src/compat/{adapter → export}/build-complete.ts +72 -75
  156. package/src/compat/export/client.ts +29 -31
  157. package/src/compat/export/{index.ts → emit.ts} +111 -110
  158. package/src/compat/export/standalone.ts +62 -54
  159. package/src/compat/image-optimizer/cache.ts +51 -49
  160. package/src/compat/image-optimizer/detect.ts +52 -52
  161. package/src/compat/image-optimizer/{index.ts → optimize.ts} +189 -194
  162. package/src/compat/image-optimizer/source.ts +77 -80
  163. package/src/compat/lifecycle/after-scope.ts +26 -26
  164. package/src/compat/lifecycle/after.ts +48 -45
  165. package/src/compat/lifecycle/error-funnel.ts +98 -102
  166. package/src/compat/lifecycle/error-serialize.ts +30 -26
  167. package/src/compat/lifecycle/error-ui.ts +67 -32
  168. package/src/compat/lifecycle/instrumentation-client.ts +36 -38
  169. package/src/compat/lifecycle/instrumentation.ts +85 -85
  170. package/src/compat/lifecycle/node-console.ts +11 -11
  171. package/src/compat/lifecycle/testmode.ts +160 -132
  172. package/src/compat/mdx/compile.ts +60 -57
  173. package/src/compat/mdx/plugin.ts +11 -11
  174. package/src/compat/mdx/{next-mdx-stub.ts → stub.ts} +5 -5
  175. package/src/compat/{metadata-route-artifacts.ts → metadata-artifacts.ts} +195 -191
  176. package/src/compat/metadata.ts +75 -81
  177. package/src/compat/next/cache.ts +68 -69
  178. package/src/compat/next/canonical-url.ts +9 -9
  179. package/src/compat/next/client-cache.ts +19 -19
  180. package/src/compat/next/client-navigation.ts +112 -116
  181. package/src/compat/next/client-only.ts +1 -1
  182. package/src/compat/next/client-script.tsx +99 -93
  183. package/src/compat/next/client-server.ts +10 -10
  184. package/src/compat/next/config-loader.ts +176 -173
  185. package/src/compat/next/config.ts +7 -7
  186. package/src/compat/next/constants.cjs +6 -6
  187. package/src/compat/next/constants.ts +6 -6
  188. package/src/compat/next/custom-server.ts +26 -24
  189. package/src/compat/next/dist/client/components/app-router-headers.ts +21 -21
  190. package/src/compat/next/dist/server/app-render/work-unit-async-storage.external.cjs +3 -4
  191. package/src/compat/next/dist/server/web/spec-extension/revalidate.ts +1 -1
  192. package/src/compat/next/dist/server/web/spec-extension/unstable-cache.ts +1 -1
  193. package/src/compat/next/dist/server/web/spec-extension/unstable-no-store.ts +1 -1
  194. package/src/compat/next/dynamic.tsx +21 -18
  195. package/src/compat/next/error.tsx +52 -52
  196. package/src/compat/next/font/cache.ts +74 -74
  197. package/src/compat/next/font/google.ts +2 -2
  198. package/src/compat/next/font/index.ts +1 -1
  199. package/src/compat/next/font/local.ts +3 -3
  200. package/src/compat/next/font/runtime-client.ts +17 -15
  201. package/src/compat/next/font/runtime.ts +443 -408
  202. package/src/compat/next/font/shared.ts +120 -108
  203. package/src/compat/next/form.tsx +63 -63
  204. package/src/compat/next/head.tsx +2 -2
  205. package/src/compat/next/headers.ts +103 -95
  206. package/src/compat/next/image/client.tsx +220 -0
  207. package/src/compat/next/image/config.ts +56 -58
  208. package/src/compat/next/image/optimizer.ts +40 -36
  209. package/src/compat/next/image/patterns.ts +37 -40
  210. package/src/compat/next/{image-props.ts → image/props.ts} +208 -202
  211. package/src/compat/next/image/shared.ts +65 -57
  212. package/src/compat/next/image/static-metadata.ts +98 -107
  213. package/src/compat/next/image/validate.ts +79 -88
  214. package/src/compat/next/image.tsx +19 -23
  215. package/src/compat/next/index.ts +1 -1
  216. package/src/compat/next/legacy-image.tsx +59 -60
  217. package/src/compat/next/{link-validation-transform.ts → link-transform.ts} +95 -96
  218. package/src/compat/next/link.tsx +158 -158
  219. package/src/compat/next/navigation.cjs +12 -3
  220. package/src/compat/next/navigation.ts +48 -50
  221. package/src/compat/next/offline.ts +27 -27
  222. package/src/compat/next/og.ts +121 -124
  223. package/src/compat/next/preferred-region.ts +13 -14
  224. package/src/compat/next/redirects.ts +58 -56
  225. package/src/compat/next/resource-hints.ts +73 -76
  226. package/src/compat/next/rewrites.ts +130 -133
  227. package/src/compat/next/root-params.ts +45 -45
  228. package/src/compat/next/{optimistic-route-state.ts → route-state.ts} +52 -52
  229. package/src/compat/next/router.cjs +4 -2
  230. package/src/compat/next/router.ts +58 -61
  231. package/src/compat/next/script.tsx +108 -108
  232. package/src/compat/next/server-only.ts +1 -1
  233. package/src/compat/next/server.ts +19 -19
  234. package/src/compat/next/svgr.ts +18 -17
  235. package/src/compat/next/telemetry.ts +24 -24
  236. package/src/compat/next/{image-usage.ts → usage.ts} +70 -39
  237. package/src/compat/next/user-agent.ts +53 -49
  238. package/src/compat/next/web-vitals.ts +22 -24
  239. package/src/compat/otel/api.ts +41 -41
  240. package/src/compat/otel/client-trace-metadata.ts +25 -27
  241. package/src/compat/otel/fetch-span.ts +29 -29
  242. package/src/compat/otel/tracer.ts +331 -331
  243. package/src/compat/pages/api.ts +456 -0
  244. package/src/compat/pages/client-plugin.ts +36 -36
  245. package/src/compat/pages/router-state.ts +34 -34
  246. package/src/compat/pages/{index.ts → router.ts} +130 -135
  247. package/src/compat/ppr/io.ts +12 -12
  248. package/src/compat/ppr/missing-root-params.ts +34 -38
  249. package/src/compat/ppr/root-params-scan.ts +66 -66
  250. package/src/compat/ppr/root-params-transform.ts +24 -26
  251. package/src/compat/ppr/root-params.ts +30 -30
  252. package/src/compat/ppr/segment-config-incompat.ts +6 -7
  253. package/src/compat/protocol.ts +71 -70
  254. package/src/compat/react/action-state.ts +47 -48
  255. package/src/compat/react/client-lite.ts +15 -15
  256. package/src/compat/react/client.ts +4 -4
  257. package/src/compat/react/compiler-runtime.ts +11 -11
  258. package/src/compat/react/dom-client.ts +44 -44
  259. package/src/compat/react/dom-react-server.ts +10 -16
  260. package/src/compat/react/dom-server.ts +10 -10
  261. package/src/compat/react/dom.ts +52 -52
  262. package/src/compat/react/hooks-extra.ts +34 -35
  263. package/src/compat/react/parity.ts +64 -61
  264. package/src/compat/react/preact.ts +81 -82
  265. package/src/compat/react/react-server.ts +28 -28
  266. package/src/compat/react/router-shim.ts +1 -1
  267. package/src/compat/react/server-component-use.ts +8 -8
  268. package/src/compat/react/server-inserted-html.ts +30 -31
  269. package/src/compat/react/server.ts +53 -55
  270. package/src/compat/react/use.ts +32 -32
  271. package/src/compat/react/view-transition.ts +20 -20
  272. package/src/compat/register/actions.ts +35 -824
  273. package/src/compat/register/boot.ts +41 -41
  274. package/src/compat/register/build-tier.ts +5 -5
  275. package/src/compat/register/build.ts +74 -70
  276. package/src/compat/register/bundler.ts +161 -156
  277. package/src/compat/register/cache.ts +20 -20
  278. package/src/compat/register/client-errors.ts +3 -3
  279. package/src/compat/register/config.ts +6 -6
  280. package/src/compat/register/css-extras.ts +30 -34
  281. package/src/compat/register/edge-runtime.ts +3 -3
  282. package/src/compat/register/errors.ts +10 -12
  283. package/src/compat/register/export.ts +16 -16
  284. package/src/compat/register/font.ts +11 -11
  285. package/src/compat/register/hooks.ts +2 -2
  286. package/src/compat/register/image.ts +40 -40
  287. package/src/compat/register/index.ts +59 -62
  288. package/src/compat/register/instrumentation-client.ts +10 -10
  289. package/src/compat/register/lifecycle.ts +25 -28
  290. package/src/compat/register/mdx.ts +10 -10
  291. package/src/compat/register/middleware.ts +226 -16
  292. package/src/compat/register/otel.ts +80 -88
  293. package/src/compat/register/pages-api.ts +10 -463
  294. package/src/compat/register/ppr.ts +16 -16
  295. package/src/compat/register/protocol.ts +17 -18
  296. package/src/compat/register/proxy.ts +49 -51
  297. package/src/compat/register/render.ts +79 -76
  298. package/src/compat/register/routing.ts +162 -159
  299. package/src/compat/register/segment.ts +24 -1897
  300. package/src/compat/register/static-image.ts +3 -3
  301. package/src/compat/register/{misc.ts → taint.ts} +9 -9
  302. package/src/compat/register/typed-routes.ts +14 -14
  303. package/src/compat/register/{usecache.ts → use-cache.ts} +39 -39
  304. package/src/compat/register/validation.ts +18 -18
  305. package/src/compat/segment/loading-boundary.ts +43 -45
  306. package/src/compat/segment/page-slot.ts +69 -69
  307. package/src/compat/segment/serve.ts +1884 -0
  308. package/src/compat/segment/tree.ts +113 -112
  309. package/src/compat/segment/vary-key.ts +38 -38
  310. package/src/compat/segment/vary-params.ts +138 -142
  311. package/src/compat/static-params.ts +14 -12
  312. package/src/compat/tsconfig-defaults.ts +87 -91
  313. package/src/compat/typecheck/{index.ts → check.ts} +234 -212
  314. package/src/compat/typecheck/worker.ts +15 -12
  315. package/src/compat/typed-routes/{index.ts → generate.ts} +36 -36
  316. package/src/compat/typed-routes/manifest.ts +174 -170
  317. package/src/compat/typed-routes/typegen.ts +127 -110
  318. package/src/compat/validation/errors.ts +16 -19
  319. package/src/compat/validation/prerender-diagnostics.ts +521 -504
  320. package/src/compat/validation/{index.ts → validate.ts} +647 -648
  321. package/src/compat-bootstrap.ts +16 -16
  322. package/src/config.ts +86 -69
  323. package/src/css/build.ts +230 -227
  324. package/src/css/postcss.ts +79 -80
  325. package/src/css/worker.ts +14 -15
  326. package/src/dev/client-actions.ts +10 -10
  327. package/src/dev/client-chunk-store.ts +27 -27
  328. package/src/dev/{client-key-cache.ts → restart/client-key.ts} +76 -76
  329. package/src/dev/{restart-cache.ts → restart/enabled.ts} +1 -1
  330. package/src/dev/{global-css-cache.ts → restart/global-css.ts} +91 -83
  331. package/src/dev/{node-module-bundle-cache.ts → restart/node-modules.ts} +24 -24
  332. package/src/dev/{route-bundle-key-cache.ts → restart/route-bundle-key.ts} +53 -53
  333. package/src/dev/{route-facts-cache.ts → restart/route-facts.ts} +82 -82
  334. package/src/dev/server.ts +804 -820
  335. package/src/env.ts +46 -43
  336. package/src/extensions.ts +491 -478
  337. package/src/index.ts +8 -8
  338. package/src/internal.ts +20 -23
  339. package/src/{islands → render}/boundary-error.ts +3 -3
  340. package/src/render/hooks.ts +71 -71
  341. package/src/render/island-context.ts +14 -14
  342. package/src/render/metadata.ts +310 -310
  343. package/src/{ppr-postpone.ts → render/postpone.ts} +5 -5
  344. package/src/{ppr.ts → render/ppr.ts} +244 -245
  345. package/src/render/renderer.ts +2087 -2082
  346. package/src/render/resource-hints.ts +16 -17
  347. package/src/render/slots.tsx +224 -235
  348. package/src/{islands → render}/static-children.ts +9 -12
  349. package/src/{islands → render}/static-slots.ts +37 -37
  350. package/src/{cache/context.ts → request/cache.ts} +20 -20
  351. package/src/request/context.ts +107 -107
  352. package/src/{dynamic/source.ts → resolve/dynamic.ts} +139 -139
  353. package/src/resolve/engine.ts +90 -77
  354. package/src/resolve/imports.ts +475 -463
  355. package/src/resolve/scan-facts.ts +318 -296
  356. package/src/resolve/source-text.ts +37 -37
  357. package/src/{dynamic → resolve}/tree-shake.ts +132 -128
  358. package/src/routing/forwarded.ts +19 -19
  359. package/src/routing/handler.ts +84 -91
  360. package/src/routing/href.ts +87 -70
  361. package/src/routing/{metadata.ts → metadata-files.ts} +403 -401
  362. package/src/{proxy.ts → routing/proxy.ts} +306 -312
  363. package/src/routing/{request-runtime.ts → request-environment.ts} +10 -10
  364. package/src/routing/routes.ts +827 -815
  365. package/src/routing/slots.ts +164 -160
  366. package/src/runtime/loader.ts +954 -0
  367. package/src/{dev → runtime}/module-cache.ts +309 -287
  368. package/src/{dev → runtime}/module-generations.ts +9 -9
  369. package/src/{dev → runtime}/module-transform.ts +81 -72
  370. package/src/{dev/imports.ts → runtime/modules.ts} +934 -847
  371. package/src/runtime/{server.ts → vendor-build.ts} +848 -1696
  372. package/src/runtime/vendor.ts +428 -406
  373. package/src/styles.d.ts +9 -0
  374. package/src/types.ts +324 -335
  375. package/src/utils/ansi.ts +5 -5
  376. package/src/utils/{source.ts → code.ts} +15 -12
  377. package/src/utils/content-type.ts +3 -3
  378. package/src/utils/decode.ts +2 -2
  379. package/src/utils/dev-profile.ts +13 -13
  380. package/src/utils/error-log.ts +6 -6
  381. package/src/utils/esbuild.ts +18 -18
  382. package/src/utils/fs-cache.ts +13 -13
  383. package/src/utils/fs.ts +57 -49
  384. package/src/utils/html.ts +20 -24
  385. package/src/utils/native-require.ts +8 -8
  386. package/src/utils/serialize.ts +139 -146
  387. package/src/utils/verbose.ts +18 -18
  388. package/reference/overview.md +0 -35
  389. package/src/cli/analyze-print.ts +0 -181
  390. package/src/compat/middleware/manifest.ts +0 -210
  391. package/src/compat/next/image-client.tsx +0 -215
  392. package/src/compat/next/link-usage.ts +0 -29
  393. package/src/css/index.ts +0 -2
  394. package/src/render/index.ts +0 -1
  395. package/src/style-modules.d.ts +0 -9
@@ -1,14 +1,14 @@
1
- import { existsSync, readFileSync, statSync } from 'node:fs';
2
- import path from 'node:path';
1
+ import { existsSync, readFileSync, statSync } from 'node:fs'
2
+ import path from 'node:path'
3
3
  // Lazy: the oxc-parser native binding costs ~12.6 MB RSS; load it only when a parse happens.
4
4
  const parseSync: typeof import('oxc-parser').parseSync = (...args) =>
5
5
  // eslint-disable-next-line @typescript-eslint/no-require-imports
6
- loadNative(() => require('oxc-parser') as typeof import('oxc-parser')).parseSync(...args);
7
- import { loadNative } from './utils/native-require';
8
- import { registerServerRuntime } from './runtime/server';
9
- import { pathToFileHref, type ResolvedConfig } from './config';
10
- import { devServerModuleHref } from './dev/imports';
11
- import { runWithRequest } from './request/context';
6
+ loadNative(() => require('oxc-parser') as typeof import('oxc-parser')).parseSync(...args)
7
+ import { loadNative } from '../utils/native-require'
8
+ import { registerServerRuntime } from '../runtime/loader'
9
+ import { pathToFileHref, type ResolvedConfig } from '../config'
10
+ import { devServerModuleHref } from '../runtime/modules'
11
+ import { runWithRequest } from '../request/context'
12
12
  import {
13
13
  copyMiddlewareHeaders,
14
14
  forwardMiddlewareRequestHeaders,
@@ -18,107 +18,106 @@ import {
18
18
  parseCookies,
19
19
  requestCookieHeader,
20
20
  toNextRequest,
21
- } from './api/server';
22
- import type { ExternalLoadTarget } from './resolve/imports';
23
- import { getProxyExtensions, withRouteRuntime } from './extensions';
24
- import { canonicalTrailingSlashPath } from './routing/href';
21
+ } from '../api/server'
22
+ import type { ExternalLoadTarget } from '../resolve/imports'
23
+ import { getProxyExtensions, withRouteRuntime } from '../extensions'
24
+ import { canonicalTrailingSlashPath } from './href'
25
25
 
26
26
  export interface ProxyModule {
27
- default?: ProxyHandler;
28
- proxy?: ProxyHandler;
29
- config?: ProxyConfig;
27
+ default?: ProxyHandler
28
+ proxy?: ProxyHandler
29
+ config?: ProxyConfig
30
30
  }
31
31
 
32
32
  export type ProxyHandler = (
33
- request: import('./types').NextRequest,
34
- event: import('./types').NextFetchEvent,
35
- ) => Response | undefined | void | Promise<Response | undefined | void>;
33
+ request: import('../types').NextRequest,
34
+ event: import('../types').NextFetchEvent,
35
+ ) => Response | undefined | void | Promise<Response | undefined | void>
36
36
 
37
37
  export interface ProxyConfig {
38
- matcher?: ProxyMatcher | ProxyMatcher[];
38
+ matcher?: ProxyMatcher | ProxyMatcher[]
39
39
  }
40
40
 
41
41
  export interface ProxyRouteCondition {
42
- type: 'header' | 'query' | 'cookie' | 'host';
43
- key?: string;
44
- value?: string;
42
+ type: 'header' | 'query' | 'cookie' | 'host'
43
+ key?: string
44
+ value?: string
45
45
  }
46
46
 
47
47
  type ProxyMatcher =
48
- | string
49
- | { source: string; has?: ProxyRouteCondition[]; missing?: ProxyRouteCondition[] };
48
+ string | { source: string; has?: ProxyRouteCondition[]; missing?: ProxyRouteCondition[] }
50
49
 
51
50
  interface CompiledMatcher {
52
- regex: RegExp;
53
- has?: ProxyRouteCondition[];
54
- missing?: ProxyRouteCondition[];
51
+ regex: RegExp
52
+ has?: ProxyRouteCondition[]
53
+ missing?: ProxyRouteCondition[]
55
54
  }
56
55
 
57
56
  export interface ProxyRunOptions {
58
- dev?: boolean;
59
- devImportVersion?: string;
57
+ dev?: boolean
58
+ devImportVersion?: string
60
59
  }
61
60
 
62
- export type ProxyRewriteObserver = (from: URL, to: URL) => void;
61
+ export type ProxyRewriteObserver = (from: URL, to: URL) => void
63
62
 
64
- let proxyRewriteObserver: ProxyRewriteObserver | undefined;
63
+ let proxyRewriteObserver: ProxyRewriteObserver | undefined
65
64
 
66
65
  export function setProxyRewriteObserver(observer: ProxyRewriteObserver | undefined): void {
67
- proxyRewriteObserver = observer;
66
+ proxyRewriteObserver = observer
68
67
  }
69
68
 
70
- export type ProxyRunObserver = <T>(request: Request, fn: () => T) => T;
69
+ export type ProxyRunObserver = <T>(request: Request, fn: () => T) => T
71
70
 
72
- let proxyRunObserver: ProxyRunObserver | undefined;
71
+ let proxyRunObserver: ProxyRunObserver | undefined
73
72
 
74
73
  export function setProxyRunObserver(observer: ProxyRunObserver | undefined): void {
75
- proxyRunObserver = observer;
74
+ proxyRunObserver = observer
76
75
  }
77
76
 
78
77
  function wrapMiddleware<T>(request: Request, fn: () => T): T {
79
- return proxyRunObserver ? proxyRunObserver(request, fn) : fn();
78
+ return proxyRunObserver ? proxyRunObserver(request, fn) : fn()
80
79
  }
81
80
 
82
81
  export interface ProxyNextResult {
83
- request: Request;
84
- response?: Response;
82
+ request: Request
83
+ response?: Response
85
84
  }
86
85
 
87
86
  export interface ProxyRunner {
88
- (request: Request, options?: ProxyRunOptions): Promise<ProxyNextResult | Response | undefined>;
87
+ (request: Request, options?: ProxyRunOptions): Promise<ProxyNextResult | Response | undefined>
89
88
  /**
90
89
  * Start compiling and importing the proxy module now. The proxy runs serially in front of every
91
90
  * request, so leaving its first import to the first request puts the whole compile on the critical
92
91
  * path of the first page; dev calls this at boot so it overlaps route scanning and the warmup.
93
92
  */
94
- warm(options?: ProxyRunOptions): void;
93
+ warm(options?: ProxyRunOptions): void
95
94
  }
96
95
 
97
- const proxyExtensions = ['.ts', '.tsx', '.js', '.jsx', '.mts'];
96
+ const proxyExtensions = ['.ts', '.tsx', '.js', '.jsx', '.mts']
98
97
 
99
98
  export function findProxyFile(config: ResolvedConfig) {
100
- return findProxyFiles(config)[0];
99
+ return findProxyFiles(config)[0]
101
100
  }
102
101
 
103
102
  export function proxyExternalLoadTarget(file: string): ExternalLoadTarget {
104
- return path.basename(file).startsWith('proxy.') ? 'client-ssr' : 'edge';
103
+ return path.basename(file).startsWith('proxy.') ? 'client-ssr' : 'edge'
105
104
  }
106
105
 
107
106
  export function findProxyFiles(config: ResolvedConfig, names = getProxyExtensions().names) {
108
- const files: string[] = [];
107
+ const files: string[] = []
109
108
  for (const base of proxyBases(config)) {
110
109
  for (const name of names) {
111
110
  for (const extension of proxyExtensions) {
112
- const file = path.join(base, `${name}${extension}`);
113
- if (existsSync(file)) files.push(file);
111
+ const file = path.join(base, `${name}${extension}`)
112
+ if (existsSync(file)) files.push(file)
114
113
  }
115
114
  }
116
115
  }
117
- return files;
116
+ return files
118
117
  }
119
118
 
120
119
  export async function validateProxyFiles(config: ResolvedConfig) {
121
- await getProxyExtensions().validateFiles(config);
120
+ await getProxyExtensions().validateFiles(config)
122
121
  }
123
122
 
124
123
  export async function runProxy(
@@ -126,12 +125,12 @@ export async function runProxy(
126
125
  request: Request,
127
126
  options: ProxyRunOptions = {},
128
127
  ): Promise<ProxyNextResult | Response | undefined> {
129
- const url = new URL(request.url);
128
+ const url = new URL(request.url)
130
129
  if (url.pathname.startsWith('/__pnext/') || url.pathname.startsWith('/assets/')) {
131
- return undefined;
130
+ return undefined
132
131
  }
133
132
 
134
- return createProxyRunner(config)(request, options);
133
+ return createProxyRunner(config)(request, options)
135
134
  }
136
135
 
137
136
  export interface ProxyRunnerOptions {
@@ -140,70 +139,69 @@ export interface ProxyRunnerOptions {
140
139
  * cannot resolve bare compat specifiers (next/server etc.), so prod must
141
140
  * load the build-time bundle that has aliases baked in.
142
141
  */
143
- compiledModuleHref?: string;
142
+ compiledModuleHref?: string
144
143
  }
145
144
 
146
145
  export function createProxyRunner(
147
146
  config: ResolvedConfig,
148
147
  runnerOptions: ProxyRunnerOptions = {},
149
148
  ): ProxyRunner {
150
- const file = findProxyFile(config);
151
- registerServerRuntime(config, file ? [file] : []);
152
- let moduleKey: string | undefined;
153
- let modulePromise: Promise<ProxyModule> | undefined;
154
- let matchers: CompiledMatcher[] | undefined;
149
+ const file = findProxyFile(config)
150
+ registerServerRuntime(config, file ? [file] : [])
151
+ let moduleKey: string | undefined
152
+ let modulePromise: Promise<ProxyModule> | undefined
153
+ let matchers: CompiledMatcher[] | undefined
155
154
 
156
155
  /** The module for `options`, started at most once per import version. */
157
156
  function proxyModule(options: ProxyRunOptions) {
158
- const key = proxyModuleKey(options);
157
+ const key = proxyModuleKey(options)
159
158
  if (key !== moduleKey) {
160
- moduleKey = key;
161
- modulePromise = importProxyModule(config, file!, options, runnerOptions);
162
- matchers = undefined;
159
+ moduleKey = key
160
+ modulePromise = importProxyModule(config, file!, options, runnerOptions)
161
+ matchers = undefined
163
162
  }
164
- return (modulePromise ??= importProxyModule(config, file!, options, runnerOptions));
163
+ return (modulePromise ??= importProxyModule(config, file!, options, runnerOptions))
165
164
  }
166
165
 
167
166
  const runner: ProxyRunner = async (request, options = {}) => {
168
- const url = new URL(request.url);
167
+ const url = new URL(request.url)
169
168
  if (url.pathname.startsWith('/__pnext/') || url.pathname.startsWith('/assets/')) {
170
- return undefined;
169
+ return undefined
171
170
  }
172
- if (!file) return undefined;
171
+ if (!file) return undefined
173
172
 
174
173
  // Matcher first, straight off the source: a request no matcher selects must not wait on the
175
174
  // proxy's compile+import, which is otherwise the first serial link of a cold page.
176
175
  if (!matchers && proxyMatcherGateEnabled()) {
177
- const staticMatchers = staticProxyMatchers(file);
178
- if (staticMatchers && !matchesProxy(staticMatchers, url, request)) return undefined;
176
+ const staticMatchers = staticProxyMatchers(file)
177
+ if (staticMatchers && !matchesProxy(staticMatchers, url, request)) return undefined
179
178
  }
180
179
 
181
- const module = await proxyModule(options);
182
- matchers ??= proxyMatchers(module.config);
183
- if (!matchesProxy(matchers, url, request)) return undefined;
180
+ const module = await proxyModule(options)
181
+ matchers ??= proxyMatchers(module.config)
182
+ if (!matchesProxy(matchers, url, request)) return undefined
184
183
 
185
184
  // A proxied request's body is buffered so both the proxy and the matched
186
185
  // route can read it; buffering is capped at clientMaxBodySize (compat maps
187
186
  // experimental.proxyClientMaxBodySize, default 10MB) — the excess is
188
187
  // dropped with a warning, matching Next's router-server behavior.
189
- request = await bufferProxyRequestBody(request, url.pathname);
188
+ request = await bufferProxyRequestBody(request, url.pathname)
190
189
 
191
- const handlerExport = getProxyExtensions().handlerExport(module as Record<string, unknown>);
192
- if (typeof handlerExport !== 'function')
193
- throw new Error(`${file} must export proxy or default`);
194
- const handler = handlerExport as ProxyHandler;
190
+ const handlerExport = getProxyExtensions().handlerExport(module as Record<string, unknown>)
191
+ if (typeof handlerExport !== 'function') throw new Error(`${file} must export proxy or default`)
192
+ const handler = handlerExport as ProxyHandler
195
193
 
196
194
  // Next normally hides the RSC cache key and Flight headers from proxy;
197
195
  // skipProxyUrlNormalize exposes the original request for advanced routing.
198
196
  const handlerRequest = getProxyExtensions().skipUrlNormalize()
199
197
  ? request
200
- : stripFlightHeaders(stripRscUnionQuery(request));
201
- const nextRequest = toNextRequest(handlerRequest);
198
+ : stripFlightHeaders(stripRscUnionQuery(request))
199
+ const nextRequest = toNextRequest(handlerRequest)
202
200
  // Response-headers channel so request-scoped APIs invoked inside the proxy
203
201
  // (notably draftMode().enable()/disable() from next/headers) can emit
204
202
  // Set-Cookie even when the handler returns NextResponse.next() — otherwise
205
203
  // the cookie would be dropped since it is not written onto that response.
206
- const proxyResponseHeaders = new Headers();
204
+ const proxyResponseHeaders = new Headers()
207
205
  let response = await runWithRequest(
208
206
  nextRequest,
209
207
  () =>
@@ -211,39 +209,39 @@ export function createProxyRunner(
211
209
  wrapMiddleware(nextRequest, () =>
212
210
  handler(nextRequest, {
213
211
  waitUntil(promise) {
214
- void promise;
212
+ void promise
215
213
  },
216
214
  }),
217
215
  ),
218
216
  ),
219
217
  {},
220
218
  { responseHeaders: proxyResponseHeaders },
221
- );
219
+ )
222
220
 
223
- const scopedCookies = getSetCookie(proxyResponseHeaders);
221
+ const scopedCookies = getSetCookie(proxyResponseHeaders)
224
222
  if (scopedCookies.length > 0) {
225
223
  // No explicit return means an implicit NextResponse.next(): synthesize one
226
224
  // so the emitted Set-Cookie survives while the request still continues.
227
- if (!response) response = NextResponse.next();
228
- for (const cookie of scopedCookies) response.headers.append('set-cookie', cookie);
225
+ if (!response) response = NextResponse.next()
226
+ for (const cookie of scopedCookies) response.headers.append('set-cookie', cookie)
229
227
  }
230
228
 
231
- if (!response) return { request };
229
+ if (!response) return { request }
232
230
 
233
231
  // Same-origin middleware redirects follow the app's trailing-slash rule,
234
232
  // exactly like a direct navigation would (Next normalizes the Location).
235
233
  // skipTrailingSlashRedirect and cross-origin targets are left untouched.
236
- response = normalizeRedirectLocation(response, url, config);
234
+ response = normalizeRedirectLocation(response, url, config)
237
235
 
238
- const meta = nextResponseMeta(response);
239
- if (!meta) return response;
236
+ const meta = nextResponseMeta(response)
237
+ if (!meta) return response
240
238
  const forwardedRequest = forwardMiddlewareRequestHeaders(
241
239
  response,
242
240
  applyProxyCookies(applyRequestOverride(request, meta.requestHeaders), response),
243
- );
241
+ )
244
242
  if (meta.kind === 'rewrite' && meta.url) {
245
- let rewritten = rewriteRequest(forwardedRequest, meta.url);
246
- const rewrittenUrl = new URL(rewritten.url);
243
+ let rewritten = rewriteRequest(forwardedRequest, meta.url)
244
+ const rewrittenUrl = new URL(rewritten.url)
247
245
  // A rewrite to another origin is proxied: the response for THIS request
248
246
  // comes from the external server (Next's router-server does the same for
249
247
  // any middleware rewrite whose destination carries a protocol).
@@ -251,51 +249,51 @@ export function createProxyRunner(
251
249
  // An RSC fetch's `_rsc` cache-buster must ride along: the external
252
250
  // server cannot recover it from the original URL, and the router keys
253
251
  // its response on it. Only added when the destination lacks its own.
254
- const rscHash = url.searchParams.get('_rsc');
252
+ const rscHash = url.searchParams.get('_rsc')
255
253
  if (rscHash !== null && !rewrittenUrl.searchParams.has('_rsc')) {
256
- rewrittenUrl.searchParams.set('_rsc', rscHash);
257
- rewritten = new Request(rewrittenUrl, rewritten);
254
+ rewrittenUrl.searchParams.set('_rsc', rscHash)
255
+ rewritten = new Request(rewrittenUrl, rewritten)
258
256
  }
259
- getProxyExtensions().onExternalRewrite(rewritten);
257
+ getProxyExtensions().onExternalRewrite(rewritten)
260
258
  // The forwarded request still carries the ORIGINAL Host header (the
261
259
  // local server); Bun uses it for SNI/verification, so an https target
262
260
  // fails certificate checks. Drop it and let fetch derive Host from the
263
261
  // target URL, like Next's external-rewrite proxying.
264
- const externalHeaders = new Headers(rewritten.headers);
265
- externalHeaders.delete('host');
266
- const external = await fetch(new Request(rewritten, { headers: externalHeaders }));
267
- const headers = new Headers(external.headers);
268
- headers.delete('content-encoding');
269
- headers.delete('content-length');
270
- headers.delete('transfer-encoding');
262
+ const externalHeaders = new Headers(rewritten.headers)
263
+ externalHeaders.delete('host')
264
+ const external = await fetch(new Request(rewritten, { headers: externalHeaders }))
265
+ const headers = new Headers(external.headers)
266
+ headers.delete('content-encoding')
267
+ headers.delete('content-length')
268
+ headers.delete('transfer-encoding')
271
269
  const proxied = new Response(external.body, {
272
270
  status: external.status,
273
271
  statusText: external.statusText,
274
272
  headers,
275
- });
276
- copyMiddlewareHeaders(response, proxied);
277
- return proxied;
273
+ })
274
+ copyMiddlewareHeaders(response, proxied)
275
+ return proxied
278
276
  }
279
277
  if (rewrittenUrl.origin === url.origin) {
280
- proxyRewriteObserver?.(url, rewrittenUrl);
278
+ proxyRewriteObserver?.(url, rewrittenUrl)
281
279
  if (request.headers.get('x-nextjs-data') === '1') {
282
- response.headers.set('x-nextjs-rewrite', rewrittenUrl.href);
280
+ response.headers.set('x-nextjs-rewrite', rewrittenUrl.href)
283
281
  }
284
282
  }
285
- return { request: rewritten, response };
283
+ return { request: rewritten, response }
286
284
  }
287
285
 
288
- return { request: forwardedRequest, response };
289
- };
286
+ return { request: forwardedRequest, response }
287
+ }
290
288
 
291
289
  runner.warm = (options = {}) => {
292
- if (!file) return;
290
+ if (!file) return
293
291
  // A failure surfaces on the first request, which awaits this same promise;
294
292
  // the swallow here only keeps the unawaited warm call from going unhandled.
295
- void proxyModule(options).catch(() => undefined);
296
- };
293
+ void proxyModule(options).catch(() => undefined)
294
+ }
297
295
 
298
- return runner;
296
+ return runner
299
297
  }
300
298
 
301
299
  // Apply the app's trailing-slash rule to a same-origin redirect emitted by the
@@ -303,96 +301,96 @@ export function createProxyRunner(
303
301
  // `trailingSlash: true` must land on `/somewhere/`). Cross-origin targets, the
304
302
  // skipTrailingSlashRedirect opt-out, and non-redirect responses pass through.
305
303
  function normalizeRedirectLocation(response: Response, requestUrl: URL, config: ResolvedConfig) {
306
- if (config.skipTrailingSlashRedirect || !config.trailingSlash) return response;
307
- if (response.status < 300 || response.status >= 400) return response;
308
- const location = response.headers.get('location');
309
- if (!location) return response;
310
- let target: URL;
304
+ if (config.skipTrailingSlashRedirect || !config.trailingSlash) return response
305
+ if (response.status < 300 || response.status >= 400) return response
306
+ const location = response.headers.get('location')
307
+ if (!location) return response
308
+ let target: URL
311
309
  try {
312
- target = new URL(location, requestUrl);
310
+ target = new URL(location, requestUrl)
313
311
  } catch {
314
- return response;
312
+ return response
315
313
  }
316
- if (target.origin !== requestUrl.origin) return response;
317
- const normalized = canonicalTrailingSlashPath(target.pathname, true);
318
- if (normalized === target.pathname) return response;
319
- target.pathname = normalized;
314
+ if (target.origin !== requestUrl.origin) return response
315
+ const normalized = canonicalTrailingSlashPath(target.pathname, true)
316
+ if (normalized === target.pathname) return response
317
+ target.pathname = normalized
320
318
  try {
321
- response.headers.set('location', target.href);
322
- return response;
319
+ response.headers.set('location', target.href)
320
+ return response
323
321
  } catch {
324
- const headers = new Headers(response.headers);
325
- headers.set('location', target.href);
322
+ const headers = new Headers(response.headers)
323
+ headers.set('location', target.href)
326
324
  return new Response(response.body, {
327
325
  status: response.status,
328
326
  statusText: response.statusText,
329
327
  headers,
330
- });
328
+ })
331
329
  }
332
330
  }
333
331
 
334
332
  // Human label for the truncation warning ("10MB", "500KB") — whole units only,
335
333
  // mirroring Next's log line ("Request body exceeded 10MB for /api/echo").
336
334
  function formatBodyLimit(bytes: number): string {
337
- if (bytes >= 1024 * 1024 && bytes % (1024 * 1024) === 0) return `${bytes / (1024 * 1024)}MB`;
338
- if (bytes >= 1024 && bytes % 1024 === 0) return `${bytes / 1024}KB`;
339
- return `${bytes}B`;
335
+ if (bytes >= 1024 * 1024 && bytes % (1024 * 1024) === 0) return `${bytes / (1024 * 1024)}MB`
336
+ if (bytes >= 1024 && bytes % 1024 === 0) return `${bytes / 1024}KB`
337
+ return `${bytes}B`
340
338
  }
341
339
 
342
340
  async function bufferProxyRequestBody(request: Request, pathname: string): Promise<Request> {
343
- if (request.method === 'GET' || request.method === 'HEAD' || !request.body) return request;
344
- const limit = getProxyExtensions().clientMaxBodySize();
345
- const chunks: Uint8Array[] = [];
346
- let total = 0;
347
- let truncated = false;
348
- const reader = request.body.getReader();
341
+ if (request.method === 'GET' || request.method === 'HEAD' || !request.body) return request
342
+ const limit = getProxyExtensions().clientMaxBodySize()
343
+ const chunks: Uint8Array[] = []
344
+ let total = 0
345
+ let truncated = false
346
+ const reader = request.body.getReader()
349
347
  for (;;) {
350
- const { done, value } = await reader.read();
351
- if (done) break;
348
+ const { done, value } = await reader.read()
349
+ if (done) break
352
350
  if (!truncated && total + value.byteLength > limit) {
353
- const keep = limit - total;
354
- if (keep > 0) chunks.push(value.subarray(0, keep));
355
- total = limit;
356
- truncated = true;
351
+ const keep = limit - total
352
+ if (keep > 0) chunks.push(value.subarray(0, keep))
353
+ total = limit
354
+ truncated = true
357
355
  // Keep draining (and discarding) the rest of the upload — cancelling the
358
356
  // stream mid-upload stalls the connection and the response never flushes.
359
- continue;
357
+ continue
360
358
  }
361
359
  if (!truncated) {
362
- chunks.push(value);
363
- total += value.byteLength;
360
+ chunks.push(value)
361
+ total += value.byteLength
364
362
  }
365
363
  }
366
364
  if (truncated) {
367
- console.warn(`Request body exceeded ${formatBodyLimit(limit)} for ${pathname}`);
365
+ console.warn(`Request body exceeded ${formatBodyLimit(limit)} for ${pathname}`)
368
366
  }
369
- const body = new Uint8Array(total);
370
- let offset = 0;
367
+ const body = new Uint8Array(total)
368
+ let offset = 0
371
369
  for (const chunk of chunks) {
372
- body.set(chunk, offset);
373
- offset += chunk.byteLength;
370
+ body.set(chunk, offset)
371
+ offset += chunk.byteLength
374
372
  }
375
- const headers = new Headers(request.headers);
376
- headers.set('content-length', String(total));
373
+ const headers = new Headers(request.headers)
374
+ headers.set('content-length', String(total))
377
375
  return new Request(request.url, {
378
376
  method: request.method,
379
377
  headers,
380
378
  body,
381
379
  // @ts-expect-error Bun/Node fetch option for streaming request bodies.
382
380
  duplex: 'half',
383
- });
381
+ })
384
382
  }
385
383
 
386
384
  export function applyProxyResponse(response: Response, proxyResponse?: Response) {
387
- if (proxyResponse) copyMiddlewareHeaders(proxyResponse, response);
388
- return response;
385
+ if (proxyResponse) copyMiddlewareHeaders(proxyResponse, response)
386
+ return response
389
387
  }
390
388
 
391
389
  export function proxyRoutePatterns(config: ProxyConfig | undefined) {
392
- const matcher = config?.matcher;
393
- if (!matcher) return ['^/(.*)$'];
394
- const matchers = Array.isArray(matcher) ? matcher : [matcher];
395
- return matchers.map(item => `^${matcherPattern(matcherSource(item))}$`);
390
+ const matcher = config?.matcher
391
+ if (!matcher) return ['^/(.*)$']
392
+ const matchers = Array.isArray(matcher) ? matcher : [matcher]
393
+ return matchers.map(item => `^${matcherPattern(matcherSource(item))}$`)
396
394
  }
397
395
 
398
396
  async function importProxyModule(
@@ -407,14 +405,14 @@ async function importProxyModule(
407
405
  externalLoadTarget: proxyExternalLoadTarget(file),
408
406
  reactServerLayer: true,
409
407
  })
410
- : (runnerOptions.compiledModuleHref ?? pathToFileHref(file));
411
- return import(href) as Promise<ProxyModule>;
408
+ : (runnerOptions.compiledModuleHref ?? pathToFileHref(file))
409
+ return import(href) as Promise<ProxyModule>
412
410
  }
413
411
 
414
412
  function proxyBases(config: ResolvedConfig) {
415
413
  return config.appPath === path.join(config.root, 'src', 'app')
416
414
  ? [path.join(config.root, 'src'), config.root]
417
- : [config.root];
415
+ : [config.root]
418
416
  }
419
417
 
420
418
  /**
@@ -423,11 +421,11 @@ function proxyBases(config: ResolvedConfig) {
423
421
  */
424
422
  function proxyMatcherGateEnabled() {
425
423
  // eslint-disable-next-line turbo/no-undeclared-env-vars
426
- return process.env.PNEXT_PROXY_MATCHER_GATE !== '0';
424
+ return process.env.PNEXT_PROXY_MATCHER_GATE !== '0'
427
425
  }
428
426
 
429
427
  /** Parsed matchers per proxy file, keyed on the source's size+mtime. */
430
- const staticMatcherCache = new Map<string, { key: string; matchers?: CompiledMatcher[] }>();
428
+ const staticMatcherCache = new Map<string, { key: string; matchers?: CompiledMatcher[] }>()
431
429
 
432
430
  /**
433
431
  * Compile the matchers of `export const config` off the proxy source itself. Only a wholly literal config
@@ -436,159 +434,159 @@ const staticMatcherCache = new Map<string, { key: string; matchers?: CompiledMat
436
434
  * literal `config` yields undefined, and the caller falls back to the imported module's config.
437
435
  */
438
436
  function staticProxyMatchers(file: string): CompiledMatcher[] | undefined {
439
- let key: string;
437
+ let key: string
440
438
  try {
441
- const stats = statSync(file);
442
- key = `${stats.size}:${stats.mtimeMs}`;
439
+ const stats = statSync(file)
440
+ key = `${stats.size}:${stats.mtimeMs}`
443
441
  } catch {
444
- return undefined;
442
+ return undefined
445
443
  }
446
- const cached = staticMatcherCache.get(file);
447
- if (cached?.key === key) return cached.matchers;
448
- let matchers: CompiledMatcher[] | undefined;
444
+ const cached = staticMatcherCache.get(file)
445
+ if (cached?.key === key) return cached.matchers
446
+ let matchers: CompiledMatcher[] | undefined
449
447
  try {
450
- const config = staticProxyConfig(file, readFileSync(file, 'utf8'));
451
- if (config) matchers = proxyMatchers(config);
448
+ const config = staticProxyConfig(file, readFileSync(file, 'utf8'))
449
+ if (config) matchers = proxyMatchers(config)
452
450
  } catch {
453
- matchers = undefined;
451
+ matchers = undefined
454
452
  }
455
- staticMatcherCache.set(file, { key, matchers });
456
- return matchers;
453
+ staticMatcherCache.set(file, { key, matchers })
454
+ return matchers
457
455
  }
458
456
 
459
457
  function staticProxyConfig(file: string, source: string): ProxyConfig | undefined {
460
- const result = parseSync(file, source, { lang: parserLang(file) });
458
+ const result = parseSync(file, source, { lang: parserLang(file) })
461
459
  // A recovered parse may have dropped the very declaration we are reading.
462
- if (result.errors.length > 0) return undefined;
460
+ if (result.errors.length > 0) return undefined
463
461
  for (const statement of result.program.body as StaticNode[]) {
464
- if (statement.type !== 'ExportNamedDeclaration') continue;
465
- const declaration = statement.declaration;
466
- if (declaration?.type !== 'VariableDeclaration') continue;
462
+ if (statement.type !== 'ExportNamedDeclaration') continue
463
+ const declaration = statement.declaration
464
+ if (declaration?.type !== 'VariableDeclaration') continue
467
465
  for (const declarator of declaration.declarations ?? []) {
468
- if (declarator.id?.type !== 'Identifier' || declarator.id.name !== 'config') continue;
469
- const value = staticValue(declarator.init);
470
- return isProxyConfigShape(value) ? (value as ProxyConfig) : undefined;
466
+ if (declarator.id?.type !== 'Identifier' || declarator.id.name !== 'config') continue
467
+ const value = staticValue(declarator.init)
468
+ return isProxyConfigShape(value) ? (value as ProxyConfig) : undefined
471
469
  }
472
470
  }
473
- return undefined;
471
+ return undefined
474
472
  }
475
473
 
476
474
  function parserLang(file: string) {
477
- const ext = path.extname(file);
478
- if (ext === '.tsx') return 'tsx';
479
- if (ext === '.jsx') return 'jsx';
480
- return ext === '.js' || ext === '.mjs' ? 'js' : 'ts';
475
+ const ext = path.extname(file)
476
+ if (ext === '.tsx') return 'tsx'
477
+ if (ext === '.jsx') return 'jsx'
478
+ return ext === '.js' || ext === '.mjs' ? 'js' : 'ts'
481
479
  }
482
480
 
483
481
  /** Structural view of the oxc AST nodes this file reads — no full type import. */
484
482
  interface StaticNode {
485
- type: string;
486
- name?: string;
487
- value?: unknown;
488
- computed?: boolean;
489
- shorthand?: boolean;
490
- key?: StaticNode;
491
- init?: StaticNode;
492
- id?: StaticNode;
493
- declaration?: StaticNode;
494
- declarations?: StaticNode[];
495
- expression?: StaticNode;
496
- properties?: StaticNode[];
497
- elements?: (StaticNode | null)[];
498
- expressions?: StaticNode[];
499
- quasis?: { value?: { cooked?: string } }[];
483
+ type: string
484
+ name?: string
485
+ value?: unknown
486
+ computed?: boolean
487
+ shorthand?: boolean
488
+ key?: StaticNode
489
+ init?: StaticNode
490
+ id?: StaticNode
491
+ declaration?: StaticNode
492
+ declarations?: StaticNode[]
493
+ expression?: StaticNode
494
+ properties?: StaticNode[]
495
+ elements?: (StaticNode | null)[]
496
+ expressions?: StaticNode[]
497
+ quasis?: { value?: { cooked?: string } }[]
500
498
  }
501
499
 
502
500
  /** Literal-only evaluation; `undefined` marks "not statically known". */
503
501
  function staticValue(node: StaticNode | undefined | null): unknown {
504
- if (!node) return undefined;
502
+ if (!node) return undefined
505
503
  switch (node.type) {
506
504
  // `… as const` / `… satisfies ProxyConfig` wrap the literal, they never change it.
507
505
  case 'TSAsExpression':
508
506
  case 'TSSatisfiesExpression':
509
507
  case 'TSNonNullExpression':
510
- return staticValue(node.expression);
508
+ return staticValue(node.expression)
511
509
  case 'Literal':
512
510
  case 'StringLiteral':
513
511
  case 'NumericLiteral':
514
512
  case 'BooleanLiteral':
515
513
  // A regex literal reports `value: null` here; it is not a matcher shape.
516
- return node.value === null ? undefined : node.value;
514
+ return node.value === null ? undefined : node.value
517
515
  case 'TemplateLiteral':
518
516
  return node.expressions?.length === 0
519
517
  ? (node.quasis?.[0]?.value?.cooked ?? undefined)
520
- : undefined;
518
+ : undefined
521
519
  case 'ArrayExpression': {
522
- const items: unknown[] = [];
520
+ const items: unknown[] = []
523
521
  for (const element of node.elements ?? []) {
524
- const value = staticValue(element);
525
- if (value === undefined) return undefined;
526
- items.push(value);
522
+ const value = staticValue(element)
523
+ if (value === undefined) return undefined
524
+ items.push(value)
527
525
  }
528
- return items;
526
+ return items
529
527
  }
530
528
  case 'ObjectExpression': {
531
- const object: Record<string, unknown> = {};
529
+ const object: Record<string, unknown> = {}
532
530
  for (const property of node.properties ?? []) {
533
- if (property.type !== 'Property' && property.type !== 'ObjectProperty') return undefined;
534
- if (property.computed) return undefined;
531
+ if (property.type !== 'Property' && property.type !== 'ObjectProperty') return undefined
532
+ if (property.computed) return undefined
535
533
  const key =
536
- property.key?.type === 'Identifier' ? property.key.name : (property.key?.value as string);
537
- if (typeof key !== 'string') return undefined;
538
- const value = staticValue(property.value as StaticNode | undefined);
539
- if (value === undefined) return undefined;
540
- object[key] = value;
534
+ property.key?.type === 'Identifier' ? property.key.name : (property.key?.value as string)
535
+ if (typeof key !== 'string') return undefined
536
+ const value = staticValue(property.value as StaticNode | undefined)
537
+ if (value === undefined) return undefined
538
+ object[key] = value
541
539
  }
542
- return object;
540
+ return object
543
541
  }
544
542
  default:
545
- return undefined;
543
+ return undefined
546
544
  }
547
545
  }
548
546
 
549
547
  /** Only a config whose `matcher` is exactly the documented shape may gate. */
550
548
  function isProxyConfigShape(value: unknown): boolean {
551
- if (typeof value !== 'object' || value === null) return false;
552
- const matcher = (value as { matcher?: unknown }).matcher;
553
- if (matcher === undefined) return true;
554
- const items = Array.isArray(matcher) ? matcher : [matcher];
549
+ if (typeof value !== 'object' || value === null) return false
550
+ const matcher = (value as { matcher?: unknown }).matcher
551
+ if (matcher === undefined) return true
552
+ const items = Array.isArray(matcher) ? matcher : [matcher]
555
553
  return items.every(item => {
556
- if (typeof item === 'string') return true;
557
- if (typeof item !== 'object' || item === null) return false;
558
- const { source, has, missing } = item as Record<string, unknown>;
559
- if (typeof source !== 'string') return false;
554
+ if (typeof item === 'string') return true
555
+ if (typeof item !== 'object' || item === null) return false
556
+ const { source, has, missing } = item as Record<string, unknown>
557
+ if (typeof source !== 'string') return false
560
558
  return [has, missing].every(
561
559
  list => list === undefined || (Array.isArray(list) && list.every(isConditionShape)),
562
- );
563
- });
560
+ )
561
+ })
564
562
  }
565
563
 
566
564
  function isConditionShape(value: unknown): boolean {
567
- if (typeof value !== 'object' || value === null) return false;
568
- const { type, key, value: expected } = value as Record<string, unknown>;
569
- if (type !== 'header' && type !== 'query' && type !== 'cookie' && type !== 'host') return false;
570
- if (key !== undefined && typeof key !== 'string') return false;
571
- return expected === undefined || typeof expected === 'string';
565
+ if (typeof value !== 'object' || value === null) return false
566
+ const { type, key, value: expected } = value as Record<string, unknown>
567
+ if (type !== 'header' && type !== 'query' && type !== 'cookie' && type !== 'host') return false
568
+ if (key !== undefined && typeof key !== 'string') return false
569
+ return expected === undefined || typeof expected === 'string'
572
570
  }
573
571
 
574
572
  function proxyMatchers(config: ProxyConfig | undefined): CompiledMatcher[] {
575
- const matcher = config?.matcher;
576
- if (!matcher) return [{ regex: /.*/ }];
577
- const matchers = Array.isArray(matcher) ? matcher : [matcher];
573
+ const matcher = config?.matcher
574
+ if (!matcher) return [{ regex: /.*/ }]
575
+ const matchers = Array.isArray(matcher) ? matcher : [matcher]
578
576
  return matchers.map(item => ({
579
577
  regex: matcherRegex(matcherSource(item)),
580
578
  ...(typeof item === 'object' && item.has ? { has: item.has } : {}),
581
579
  ...(typeof item === 'object' && item.missing ? { missing: item.missing } : {}),
582
- }));
580
+ }))
583
581
  }
584
582
 
585
583
  function matchesProxy(matchers: CompiledMatcher[], url: URL, request: Request) {
586
- const decoded = decodePathSeparators(url.pathname);
584
+ const decoded = decodePathSeparators(url.pathname)
587
585
  return matchers.some(
588
586
  matcher =>
589
587
  (matcher.regex.test(url.pathname) || matcher.regex.test(decoded)) &&
590
588
  matchesConditions(matcher, url, request),
591
- );
589
+ )
592
590
  }
593
591
 
594
592
  // A matcher applies only when every `has` condition is present and no `missing`
@@ -597,89 +595,85 @@ function matchesProxy(matchers: CompiledMatcher[], url: URL, request: Request) {
597
595
  // opts out of running for prefetch requests.
598
596
  function matchesConditions(matcher: CompiledMatcher, url: URL, request: Request) {
599
597
  if (matcher.has && !matcher.has.every(condition => hasCondition(condition, url, request))) {
600
- return false;
598
+ return false
601
599
  }
602
600
  if (matcher.missing?.some(condition => hasCondition(condition, url, request))) {
603
- return false;
601
+ return false
604
602
  }
605
- return true;
603
+ return true
606
604
  }
607
605
 
608
606
  function hasCondition(condition: ProxyRouteCondition, url: URL, request: Request): boolean {
609
- const actual = conditionValue(condition, url, request);
610
- if (actual === null) return false;
611
- if (condition.value === undefined) return true;
607
+ const actual = conditionValue(condition, url, request)
608
+ if (actual === null) return false
609
+ if (condition.value === undefined) return true
612
610
  try {
613
- return new RegExp(`^${condition.value}$`).test(actual);
611
+ return new RegExp(`^${condition.value}$`).test(actual)
614
612
  } catch {
615
- return condition.value === actual;
613
+ return condition.value === actual
616
614
  }
617
615
  }
618
616
 
619
- function conditionValue(
620
- condition: ProxyRouteCondition,
621
- url: URL,
622
- request: Request,
623
- ): string | null {
617
+ function conditionValue(condition: ProxyRouteCondition, url: URL, request: Request): string | null {
624
618
  switch (condition.type) {
625
619
  case 'header':
626
- return condition.key ? request.headers.get(condition.key) : null;
620
+ return condition.key ? request.headers.get(condition.key) : null
627
621
  case 'query':
628
- return condition.key ? url.searchParams.get(condition.key) : null;
622
+ return condition.key ? url.searchParams.get(condition.key) : null
629
623
  case 'cookie': {
630
- if (!condition.key) return null;
624
+ if (!condition.key) return null
631
625
  const cookie = parseCookies(request.headers.get('cookie') ?? '').find(
632
626
  item => item.name === condition.key,
633
- );
634
- return cookie ? cookie.value : null;
627
+ )
628
+ return cookie ? cookie.value : null
635
629
  }
636
630
  case 'host':
637
- return url.host;
631
+ return url.host
638
632
  default:
639
- return null;
633
+ return null
640
634
  }
641
635
  }
642
636
 
643
637
  function decodePathSeparators(pathname: string) {
644
- return pathname.replace(/%2f/gi, '/');
638
+ return pathname.replace(/%2f/gi, '/')
645
639
  }
646
640
 
647
641
  function matcherSource(matcher: ProxyMatcher) {
648
- return typeof matcher === 'string' ? matcher : matcher.source;
642
+ return typeof matcher === 'string' ? matcher : matcher.source
649
643
  }
650
644
 
651
645
  function matcherRegex(matcher: string) {
652
- return new RegExp(`^${matcherPattern(matcher)}$`);
646
+ return new RegExp(`^${matcherPattern(matcher)}$`)
653
647
  }
654
648
 
655
649
  function matcherPattern(matcher: string) {
656
- if (matcher.includes('(')) return matcher;
657
- if (matcher === '/') return '/';
650
+ if (matcher.includes('(')) return matcher
651
+ if (matcher === '/') return '/'
658
652
 
659
- let source = '';
653
+ let source = ''
660
654
  for (const segment of matcher.split('/').filter(Boolean)) {
661
655
  if (/^:[^/]+\*$/.test(segment)) {
662
- source += '(?:/.*)?';
656
+ source += '(?:/.*)?'
663
657
  } else if (/^:[^/]+$/.test(segment)) {
664
- source += '/[^/]+';
658
+ source += '/[^/]+'
665
659
  } else {
666
- source += `/${escapeRegex(segment)}`;
660
+ source += `/${escapeRegex(segment)}`
667
661
  }
668
662
  }
669
- return source || '/';
663
+ return source || '/'
670
664
  }
671
665
 
672
666
  function rewriteRequest(request: Request, url: string) {
673
- return new Request(new URL(url, request.url), request);
667
+ return new Request(new URL(url, request.url), request)
674
668
  }
675
669
 
676
670
  // Drop `?_rsc=<hash>` from the request the middleware handler sees. GET/HEAD
677
671
  // only ever carry it (router fetches), so re-wrapping the Request is body-safe.
678
672
  function stripRscUnionQuery(request: Request): Request {
679
- const url = new URL(request.url);
680
- if (!url.searchParams.has('_rsc')) return request;
681
- url.searchParams.delete('_rsc');
682
- return new Request(url, request);
673
+ const url = new URL(request.url)
674
+ if (!url.searchParams.has('_rsc')) return request
675
+ url.searchParams.delete('_rsc')
676
+ return new Request(url, request)
683
677
  }
684
678
 
685
679
  // The app-router flight headers Next removes from the request middleware sees
@@ -691,66 +685,66 @@ const FLIGHT_HEADERS = [
691
685
  'next-router-prefetch',
692
686
  'next-hmr-refresh',
693
687
  'next-router-segment-prefetch',
694
- ];
688
+ ]
695
689
 
696
690
  // Drop the flight headers from the request the middleware handler sees. GET/HEAD
697
691
  // router fetches carry them, so re-wrapping the Request is body-safe.
698
692
  function stripFlightHeaders(request: Request): Request {
699
- if (!FLIGHT_HEADERS.some(header => request.headers.has(header))) return request;
700
- const headers = new Headers(request.headers);
701
- for (const header of FLIGHT_HEADERS) headers.delete(header);
702
- return new Request(request, { headers });
693
+ if (!FLIGHT_HEADERS.some(header => request.headers.has(header))) return request
694
+ const headers = new Headers(request.headers)
695
+ for (const header of FLIGHT_HEADERS) headers.delete(header)
696
+ return new Request(request, { headers })
703
697
  }
704
698
 
705
699
  function applyRequestOverride(request: Request, headers: Headers | undefined) {
706
- if (!headers) return request;
707
- return new Request(request, { headers });
700
+ if (!headers) return request
701
+ return new Request(request, { headers })
708
702
  }
709
703
 
710
704
  function applyProxyCookies(request: Request, response: Response) {
711
- const setCookies = getSetCookie(response.headers);
712
- if (setCookies.length === 0) return request;
705
+ const setCookies = getSetCookie(response.headers)
706
+ if (setCookies.length === 0) return request
713
707
 
714
- const cookies = parseCookies(request.headers.get('cookie') ?? '');
708
+ const cookies = parseCookies(request.headers.get('cookie') ?? '')
715
709
  for (const header of setCookies) {
716
- const cookie = parseSetCookie(header);
717
- if (!cookie) continue;
718
- const index = cookies.findIndex(item => item.name === cookie.name);
710
+ const cookie = parseSetCookie(header)
711
+ if (!cookie) continue
712
+ const index = cookies.findIndex(item => item.name === cookie.name)
719
713
  if (cookie.deleted) {
720
- if (index !== -1) cookies.splice(index, 1);
721
- continue;
714
+ if (index !== -1) cookies.splice(index, 1)
715
+ continue
722
716
  }
723
- if (index === -1) cookies.push({ name: cookie.name, value: cookie.value });
724
- else cookies[index] = { name: cookie.name, value: cookie.value };
717
+ if (index === -1) cookies.push({ name: cookie.name, value: cookie.value })
718
+ else cookies[index] = { name: cookie.name, value: cookie.value }
725
719
  }
726
720
 
727
- const headers = new Headers(request.headers);
728
- const cookieHeader = requestCookieHeader(cookies);
729
- if (cookieHeader) headers.set('cookie', cookieHeader);
730
- else headers.delete('cookie');
731
- return new Request(request, { headers });
721
+ const headers = new Headers(request.headers)
722
+ const cookieHeader = requestCookieHeader(cookies)
723
+ if (cookieHeader) headers.set('cookie', cookieHeader)
724
+ else headers.delete('cookie')
725
+ return new Request(request, { headers })
732
726
  }
733
727
 
734
728
  function parseSetCookie(header: string) {
735
- const [pair = '', ...attributes] = header.split(';').map(part => part.trim());
736
- const [name = '', ...valueParts] = pair.split('=');
737
- if (!name) return undefined;
738
- const deleted = attributes.some(attribute => /^max-age=0$/i.test(attribute));
739
- return { name: decodeCookiePart(name), value: decodeCookiePart(valueParts.join('=')), deleted };
729
+ const [pair = '', ...attributes] = header.split(';').map(part => part.trim())
730
+ const [name = '', ...valueParts] = pair.split('=')
731
+ if (!name) return undefined
732
+ const deleted = attributes.some(attribute => /^max-age=0$/i.test(attribute))
733
+ return { name: decodeCookiePart(name), value: decodeCookiePart(valueParts.join('=')), deleted }
740
734
  }
741
735
 
742
736
  function decodeCookiePart(value: string) {
743
737
  try {
744
- return decodeURIComponent(value);
738
+ return decodeURIComponent(value)
745
739
  } catch {
746
- return value;
740
+ return value
747
741
  }
748
742
  }
749
743
 
750
744
  function escapeRegex(value: string) {
751
- return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
745
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
752
746
  }
753
747
 
754
748
  function proxyModuleKey(options: ProxyRunOptions) {
755
- return options.dev ? `dev:${options.devImportVersion ?? 'dev'}` : 'prod';
749
+ return options.dev ? `dev:${options.devImportVersion ?? 'dev'}` : 'prod'
756
750
  }