@wular/pnext 0.0.3 → 0.0.6

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 (392) hide show
  1. package/README.md +11 -11
  2. package/bin/pnext +1 -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 +1 -1
  8. package/reference/config.md +2 -2
  9. package/reference/css.md +13 -9
  10. package/reference/dev.md +1 -1
  11. package/reference/metadata.md +7 -7
  12. package/reference/navigation.md +35 -28
  13. package/reference/performance.md +70 -70
  14. package/reference/rendering.md +17 -17
  15. package/reference/routing.md +17 -17
  16. package/reference/typegen.md +12 -8
  17. package/src/api/cache.ts +36 -37
  18. package/src/api/client-cache.ts +2 -2
  19. package/src/api/client-navigation.ts +113 -109
  20. package/src/api/dynamic.tsx +58 -55
  21. package/src/api/link.tsx +49 -52
  22. package/src/api/navigation.ts +59 -58
  23. package/src/api/server.ts +152 -144
  24. package/src/api/suspense.ts +4 -4
  25. package/src/cli/adapters/vercel-warm.ts +126 -121
  26. package/src/cli/adapters/vercel.ts +437 -443
  27. package/src/cli/analyze.ts +333 -144
  28. package/src/cli/{named-bin.ts → boot/named-bin.ts} +37 -37
  29. package/src/cli/{boot-trace.ts → boot/trace.ts} +10 -10
  30. package/src/cli/build.ts +976 -978
  31. package/src/cli/create.ts +71 -63
  32. package/src/cli/dev.ts +116 -116
  33. package/src/cli/index.ts +88 -85
  34. package/src/cli/migrate/package-json.ts +73 -71
  35. package/src/cli/migrate/report.ts +32 -33
  36. package/src/cli/migrate/{index.ts → run.ts} +48 -49
  37. package/src/cli/migrate/scan.ts +46 -46
  38. package/src/cli/migrate/spinner.ts +9 -9
  39. package/src/cli/migrate/tsconfig.ts +35 -35
  40. package/src/cli/{server-entry.ts → serve/entry.ts} +57 -57
  41. package/src/cli/{request-pipeline.ts → serve/pipeline.ts} +386 -394
  42. package/src/cli/{serve-ui.ts → serve/ui.ts} +47 -47
  43. package/src/cli/start.ts +65 -66
  44. package/src/{typegen.ts → cli/typegen.ts} +59 -59
  45. package/src/client/build.ts +794 -768
  46. package/src/client/chunk-fold.ts +245 -240
  47. package/src/client/{paths.ts → chunk-name.ts} +6 -6
  48. package/src/client/entry.ts +162 -147
  49. package/src/client/prebuilt.ts +231 -223
  50. package/src/client/profile.ts +29 -29
  51. package/src/client/react-compiler.ts +20 -15
  52. package/src/client/{compat-surface.ts → react-tier.ts} +64 -64
  53. package/src/client/reference-stub.ts +51 -51
  54. package/src/client/reference.ts +19 -19
  55. package/src/{api → client}/router/events.ts +17 -17
  56. package/src/{api → client}/router/history.ts +16 -16
  57. package/src/{api → client}/router/hub.ts +52 -53
  58. package/src/{api/router.ts → client/router/index.ts} +61 -60
  59. package/src/{api → client}/router/policies.ts +24 -24
  60. package/src/{api → client}/router/runtime.ts +1988 -1961
  61. package/src/{api → client}/router/types.ts +93 -98
  62. package/src/compat/actions/client-plugin.ts +42 -43
  63. package/src/compat/actions/client-stub.ts +14 -14
  64. package/src/compat/actions/{action-client.ts → client.ts} +194 -193
  65. package/src/compat/actions/config.ts +63 -64
  66. package/src/compat/actions/detect.ts +68 -68
  67. package/src/compat/actions/discovery.ts +105 -105
  68. package/src/compat/actions/{action-dispatch.ts → dispatch.ts} +277 -274
  69. package/src/compat/actions/early-submit.ts +1 -1
  70. package/src/compat/actions/endpoint.ts +198 -198
  71. package/src/compat/actions/extensions.ts +811 -0
  72. package/src/compat/actions/flight.ts +23 -23
  73. package/src/compat/actions/form-state.ts +34 -34
  74. package/src/compat/actions/hoist.ts +382 -236
  75. package/src/compat/actions/ids.ts +7 -12
  76. package/src/compat/actions/index.ts +8 -8
  77. package/src/compat/actions/instances.ts +46 -46
  78. package/src/compat/actions/origin.ts +47 -48
  79. package/src/compat/actions/protocol.ts +22 -22
  80. package/src/compat/actions/registry.ts +19 -19
  81. package/src/compat/{misc/action-return.ts → actions/return.ts} +60 -57
  82. package/src/compat/actions/rewrite.ts +125 -125
  83. package/src/compat/actions/{action-router.ts → router.ts} +10 -10
  84. package/src/compat/actions/serve.ts +132 -136
  85. package/src/compat/actions/server-tag.ts +4 -4
  86. package/src/compat/actions/{action-shared.ts → shared.ts} +34 -34
  87. package/src/compat/actions/unrecognized-error.ts +4 -4
  88. package/src/compat/{index.ts → aliases.ts} +112 -109
  89. package/src/compat/bundler/bun-externals.ts +18 -18
  90. package/src/compat/bundler/cjs-exports.ts +271 -223
  91. package/src/compat/bundler/config.ts +116 -111
  92. package/src/compat/bundler/externals.ts +12 -12
  93. package/src/compat/bundler/import-meta-url.ts +19 -19
  94. package/src/compat/bundler/modularize-imports.ts +36 -33
  95. package/src/compat/bundler/new-url-asset.ts +22 -24
  96. package/src/compat/bundler/optimize-package-imports.ts +111 -107
  97. package/src/compat/bundler/polyfill.ts +28 -28
  98. package/src/compat/bundler/react-compiler.ts +35 -29
  99. package/src/compat/bundler/react-profiler.tsx +11 -11
  100. package/src/compat/bundler/relay-transform.ts +48 -47
  101. package/src/compat/bundler/require-context.ts +119 -113
  102. package/src/compat/bundler/resolve-extensions.ts +19 -19
  103. package/src/compat/bundler/source-cache.ts +25 -25
  104. package/src/compat/bundler/static-imports.ts +7 -7
  105. package/src/compat/bundler/symlink-imports.ts +46 -46
  106. package/src/compat/bundler/tsconfig-paths.ts +13 -15
  107. package/src/compat/bundler/wasm.ts +58 -60
  108. package/src/compat/bundler/webpack-loaders.ts +254 -241
  109. package/src/compat/bundler/worker.ts +101 -104
  110. package/src/compat/cache/build-flags.ts +29 -29
  111. package/src/compat/cache/build-prerender-errors.ts +40 -44
  112. package/src/compat/cache/custom-handler.ts +60 -53
  113. package/src/compat/cache/fetch-patch.ts +240 -240
  114. package/src/compat/cache/handler.ts +27 -31
  115. package/src/compat/cache/modern-handler.ts +148 -126
  116. package/src/compat/cache/resume-data-cache.ts +47 -45
  117. package/src/compat/cache/revalidate.ts +233 -232
  118. package/src/compat/cache/runtime-error.ts +35 -35
  119. package/src/compat/cache/use-cache-transform.ts +442 -417
  120. package/src/compat/cache/use-cache.ts +650 -614
  121. package/src/compat/cache-control.ts +140 -142
  122. package/src/compat/client/base-path.ts +21 -20
  123. package/src/compat/client/css-order.ts +18 -18
  124. package/src/compat/client/errors/bare-boundary.ts +11 -11
  125. package/src/compat/client/errors/control-flow.ts +23 -23
  126. package/src/compat/client/errors/error-boundary.ts +61 -61
  127. package/src/compat/client/errors/global-error.ts +101 -91
  128. package/src/compat/client/errors/install.ts +71 -72
  129. package/src/compat/client/errors/lazy.ts +23 -23
  130. package/src/compat/client/errors/primitive-throw.ts +47 -45
  131. package/src/compat/client/errors/soft-refresh.ts +4 -4
  132. package/src/compat/client/link-status.ts +33 -33
  133. package/src/compat/client/{nav-compat-runtime.ts → nav-runtime.ts} +20 -20
  134. package/src/compat/client/{nav-compat.ts → nav.ts} +12 -13
  135. package/src/compat/client/navigation-scroll.ts +63 -63
  136. package/src/compat/client/optimistic-routing.ts +93 -88
  137. package/src/compat/client/prefetch-cache.ts +23 -24
  138. package/src/compat/client/route-announcer.ts +35 -35
  139. package/src/compat/client/segment-cache-policy.ts +20 -20
  140. package/src/compat/client/segment-cache.ts +309 -315
  141. package/src/compat/client/segment-prefetch.ts +127 -132
  142. package/src/compat/client/trailing-slash.ts +5 -4
  143. package/src/compat/css/chunking.ts +113 -116
  144. package/src/compat/css/inline-css.ts +21 -21
  145. package/src/compat/css/lightningcss.ts +37 -38
  146. package/src/compat/css/modules.ts +161 -175
  147. package/src/compat/css/nonce.ts +7 -7
  148. package/src/compat/css/sass-plugin.ts +18 -21
  149. package/src/compat/css/sass.ts +150 -152
  150. package/src/compat/css/styled-jsx-runtime.ts +27 -27
  151. package/src/compat/css/styled-jsx.ts +21 -21
  152. package/src/compat/edge-runtime.ts +27 -27
  153. package/src/compat/{adapter → export}/build-complete.ts +72 -75
  154. package/src/compat/export/client.ts +29 -31
  155. package/src/compat/export/{index.ts → emit.ts} +111 -110
  156. package/src/compat/export/standalone.ts +62 -54
  157. package/src/compat/image-optimizer/cache.ts +51 -49
  158. package/src/compat/image-optimizer/detect.ts +52 -52
  159. package/src/compat/image-optimizer/{index.ts → optimize.ts} +189 -194
  160. package/src/compat/image-optimizer/source.ts +77 -80
  161. package/src/compat/lifecycle/after-scope.ts +26 -26
  162. package/src/compat/lifecycle/after.ts +48 -45
  163. package/src/compat/lifecycle/error-funnel.ts +98 -102
  164. package/src/compat/lifecycle/error-serialize.ts +30 -26
  165. package/src/compat/lifecycle/error-ui.ts +67 -32
  166. package/src/compat/lifecycle/instrumentation-client.ts +36 -38
  167. package/src/compat/lifecycle/instrumentation.ts +85 -85
  168. package/src/compat/lifecycle/node-console.ts +11 -11
  169. package/src/compat/lifecycle/testmode.ts +160 -132
  170. package/src/compat/mdx/compile.ts +60 -57
  171. package/src/compat/mdx/plugin.ts +11 -11
  172. package/src/compat/mdx/{next-mdx-stub.ts → stub.ts} +5 -5
  173. package/src/compat/{metadata-route-artifacts.ts → metadata-artifacts.ts} +195 -191
  174. package/src/compat/metadata.ts +75 -81
  175. package/src/compat/next/cache.ts +68 -69
  176. package/src/compat/next/canonical-url.ts +9 -9
  177. package/src/compat/next/client-cache.ts +19 -19
  178. package/src/compat/next/client-navigation.ts +112 -116
  179. package/src/compat/next/client-only.ts +1 -1
  180. package/src/compat/next/client-script.tsx +99 -93
  181. package/src/compat/next/client-server.ts +10 -10
  182. package/src/compat/next/config-loader.ts +176 -173
  183. package/src/compat/next/config.ts +7 -7
  184. package/src/compat/next/constants.cjs +6 -6
  185. package/src/compat/next/constants.ts +6 -6
  186. package/src/compat/next/custom-server.ts +26 -24
  187. package/src/compat/next/dist/client/components/app-router-headers.ts +21 -21
  188. package/src/compat/next/dist/server/app-render/work-unit-async-storage.external.cjs +3 -4
  189. package/src/compat/next/dist/server/web/spec-extension/revalidate.ts +1 -1
  190. package/src/compat/next/dist/server/web/spec-extension/unstable-cache.ts +1 -1
  191. package/src/compat/next/dist/server/web/spec-extension/unstable-no-store.ts +1 -1
  192. package/src/compat/next/dynamic.tsx +21 -18
  193. package/src/compat/next/error.tsx +52 -52
  194. package/src/compat/next/font/cache.ts +74 -74
  195. package/src/compat/next/font/google.ts +2 -2
  196. package/src/compat/next/font/index.ts +1 -1
  197. package/src/compat/next/font/local.ts +3 -3
  198. package/src/compat/next/font/runtime-client.ts +17 -15
  199. package/src/compat/next/font/runtime.ts +443 -408
  200. package/src/compat/next/font/shared.ts +120 -108
  201. package/src/compat/next/form.tsx +63 -63
  202. package/src/compat/next/head.tsx +2 -2
  203. package/src/compat/next/headers.ts +103 -95
  204. package/src/compat/next/image/client.tsx +220 -0
  205. package/src/compat/next/image/config.ts +56 -58
  206. package/src/compat/next/image/optimizer.ts +40 -36
  207. package/src/compat/next/image/patterns.ts +37 -40
  208. package/src/compat/next/{image-props.ts → image/props.ts} +208 -202
  209. package/src/compat/next/image/shared.ts +65 -57
  210. package/src/compat/next/image/static-metadata.ts +98 -107
  211. package/src/compat/next/image/validate.ts +79 -88
  212. package/src/compat/next/image.tsx +19 -23
  213. package/src/compat/next/index.ts +1 -1
  214. package/src/compat/next/legacy-image.tsx +59 -60
  215. package/src/compat/next/{link-validation-transform.ts → link-transform.ts} +95 -96
  216. package/src/compat/next/link.tsx +158 -158
  217. package/src/compat/next/navigation.cjs +12 -3
  218. package/src/compat/next/navigation.ts +48 -50
  219. package/src/compat/next/offline.ts +27 -27
  220. package/src/compat/next/og.ts +121 -124
  221. package/src/compat/next/preferred-region.ts +13 -14
  222. package/src/compat/next/redirects.ts +58 -56
  223. package/src/compat/next/resource-hints.ts +73 -76
  224. package/src/compat/next/rewrites.ts +130 -133
  225. package/src/compat/next/root-params.ts +45 -45
  226. package/src/compat/next/{optimistic-route-state.ts → route-state.ts} +52 -52
  227. package/src/compat/next/router.cjs +4 -2
  228. package/src/compat/next/router.ts +58 -61
  229. package/src/compat/next/script.tsx +108 -108
  230. package/src/compat/next/server-only.ts +1 -1
  231. package/src/compat/next/server.ts +19 -19
  232. package/src/compat/next/svgr.ts +18 -17
  233. package/src/compat/next/telemetry.ts +24 -24
  234. package/src/compat/next/{image-usage.ts → usage.ts} +70 -39
  235. package/src/compat/next/user-agent.ts +53 -49
  236. package/src/compat/next/web-vitals.ts +22 -24
  237. package/src/compat/otel/api.ts +41 -41
  238. package/src/compat/otel/client-trace-metadata.ts +25 -27
  239. package/src/compat/otel/fetch-span.ts +29 -29
  240. package/src/compat/otel/tracer.ts +331 -331
  241. package/src/compat/pages/api.ts +456 -0
  242. package/src/compat/pages/client-plugin.ts +36 -36
  243. package/src/compat/pages/router-state.ts +34 -34
  244. package/src/compat/pages/{index.ts → router.ts} +130 -135
  245. package/src/compat/ppr/io.ts +12 -12
  246. package/src/compat/ppr/missing-root-params.ts +34 -38
  247. package/src/compat/ppr/root-params-scan.ts +66 -66
  248. package/src/compat/ppr/root-params-transform.ts +24 -26
  249. package/src/compat/ppr/root-params.ts +30 -30
  250. package/src/compat/ppr/segment-config-incompat.ts +6 -7
  251. package/src/compat/protocol.ts +71 -70
  252. package/src/compat/react/action-state.ts +47 -48
  253. package/src/compat/react/client-lite.ts +15 -15
  254. package/src/compat/react/client.ts +4 -4
  255. package/src/compat/react/compiler-runtime.ts +11 -11
  256. package/src/compat/react/dom-client.ts +44 -44
  257. package/src/compat/react/dom-react-server.ts +10 -16
  258. package/src/compat/react/dom-server.ts +10 -10
  259. package/src/compat/react/dom.ts +52 -52
  260. package/src/compat/react/hooks-extra.ts +34 -35
  261. package/src/compat/react/parity.ts +64 -61
  262. package/src/compat/react/preact.ts +81 -82
  263. package/src/compat/react/react-server.ts +28 -28
  264. package/src/compat/react/router-shim.ts +1 -1
  265. package/src/compat/react/server-component-use.ts +8 -8
  266. package/src/compat/react/server-inserted-html.ts +30 -31
  267. package/src/compat/react/server.ts +53 -55
  268. package/src/compat/react/use.ts +32 -32
  269. package/src/compat/react/view-transition.ts +20 -20
  270. package/src/compat/register/actions.ts +35 -824
  271. package/src/compat/register/boot.ts +41 -41
  272. package/src/compat/register/build-tier.ts +5 -5
  273. package/src/compat/register/build.ts +74 -70
  274. package/src/compat/register/bundler.ts +161 -156
  275. package/src/compat/register/cache.ts +20 -20
  276. package/src/compat/register/client-errors.ts +3 -3
  277. package/src/compat/register/config.ts +6 -6
  278. package/src/compat/register/css-extras.ts +30 -34
  279. package/src/compat/register/edge-runtime.ts +3 -3
  280. package/src/compat/register/errors.ts +10 -12
  281. package/src/compat/register/export.ts +16 -16
  282. package/src/compat/register/font.ts +11 -11
  283. package/src/compat/register/hooks.ts +2 -2
  284. package/src/compat/register/image.ts +40 -40
  285. package/src/compat/register/index.ts +59 -62
  286. package/src/compat/register/instrumentation-client.ts +10 -10
  287. package/src/compat/register/lifecycle.ts +25 -28
  288. package/src/compat/register/mdx.ts +10 -10
  289. package/src/compat/register/middleware.ts +226 -16
  290. package/src/compat/register/otel.ts +80 -88
  291. package/src/compat/register/pages-api.ts +10 -463
  292. package/src/compat/register/ppr.ts +16 -16
  293. package/src/compat/register/protocol.ts +17 -18
  294. package/src/compat/register/proxy.ts +49 -51
  295. package/src/compat/register/render.ts +79 -76
  296. package/src/compat/register/routing.ts +162 -159
  297. package/src/compat/register/segment.ts +24 -1887
  298. package/src/compat/register/static-image.ts +3 -3
  299. package/src/compat/register/{misc.ts → taint.ts} +9 -9
  300. package/src/compat/register/typed-routes.ts +14 -14
  301. package/src/compat/register/{usecache.ts → use-cache.ts} +39 -39
  302. package/src/compat/register/validation.ts +18 -18
  303. package/src/compat/segment/loading-boundary.ts +43 -45
  304. package/src/compat/segment/page-slot.ts +69 -69
  305. package/src/compat/segment/serve.ts +1884 -0
  306. package/src/compat/segment/tree.ts +113 -112
  307. package/src/compat/segment/vary-key.ts +38 -38
  308. package/src/compat/segment/vary-params.ts +138 -142
  309. package/src/compat/static-params.ts +14 -12
  310. package/src/compat/tsconfig-defaults.ts +87 -91
  311. package/src/compat/typecheck/{index.ts → check.ts} +234 -212
  312. package/src/compat/typecheck/worker.ts +15 -12
  313. package/src/compat/typed-routes/{index.ts → generate.ts} +36 -36
  314. package/src/compat/typed-routes/manifest.ts +174 -170
  315. package/src/compat/typed-routes/typegen.ts +127 -110
  316. package/src/compat/validation/errors.ts +16 -19
  317. package/src/compat/validation/prerender-diagnostics.ts +521 -504
  318. package/src/compat/validation/{index.ts → validate.ts} +647 -648
  319. package/src/compat-bootstrap.ts +16 -16
  320. package/src/config.ts +69 -69
  321. package/src/css/build.ts +230 -227
  322. package/src/css/postcss.ts +79 -80
  323. package/src/css/worker.ts +14 -15
  324. package/src/dev/client-actions.ts +10 -10
  325. package/src/dev/client-chunk-store.ts +27 -27
  326. package/src/dev/{client-key-cache.ts → restart/client-key.ts} +76 -76
  327. package/src/dev/{restart-cache.ts → restart/enabled.ts} +1 -1
  328. package/src/dev/{global-css-cache.ts → restart/global-css.ts} +91 -83
  329. package/src/dev/{node-module-bundle-cache.ts → restart/node-modules.ts} +24 -24
  330. package/src/dev/{route-bundle-key-cache.ts → restart/route-bundle-key.ts} +53 -53
  331. package/src/dev/{route-facts-cache.ts → restart/route-facts.ts} +82 -82
  332. package/src/dev/server.ts +804 -820
  333. package/src/env.ts +46 -43
  334. package/src/extensions.ts +491 -478
  335. package/src/index.ts +8 -8
  336. package/src/internal.ts +20 -23
  337. package/src/{islands → render}/boundary-error.ts +3 -3
  338. package/src/render/hooks.ts +71 -71
  339. package/src/render/island-context.ts +14 -14
  340. package/src/render/metadata.ts +310 -310
  341. package/src/{ppr-postpone.ts → render/postpone.ts} +5 -5
  342. package/src/{ppr.ts → render/ppr.ts} +244 -245
  343. package/src/render/renderer.ts +2076 -2082
  344. package/src/render/resource-hints.ts +16 -17
  345. package/src/render/slots.tsx +224 -235
  346. package/src/{islands → render}/static-children.ts +9 -12
  347. package/src/{islands → render}/static-slots.ts +37 -37
  348. package/src/{cache/context.ts → request/cache.ts} +20 -20
  349. package/src/request/context.ts +107 -107
  350. package/src/{dynamic/source.ts → resolve/dynamic.ts} +152 -143
  351. package/src/resolve/engine.ts +90 -77
  352. package/src/resolve/imports.ts +475 -463
  353. package/src/resolve/scan-facts.ts +442 -186
  354. package/src/resolve/source-text.ts +37 -37
  355. package/src/{dynamic → resolve}/tree-shake.ts +132 -128
  356. package/src/routing/forwarded.ts +19 -19
  357. package/src/routing/handler.ts +84 -91
  358. package/src/routing/href.ts +69 -70
  359. package/src/routing/{metadata.ts → metadata-files.ts} +403 -401
  360. package/src/{proxy.ts → routing/proxy.ts} +306 -312
  361. package/src/routing/{request-runtime.ts → request-environment.ts} +10 -10
  362. package/src/routing/routes.ts +833 -848
  363. package/src/routing/slots.ts +164 -160
  364. package/src/runtime/loader.ts +952 -0
  365. package/src/{dev → runtime}/module-cache.ts +309 -287
  366. package/src/{dev → runtime}/module-generations.ts +9 -9
  367. package/src/{dev → runtime}/module-transform.ts +81 -72
  368. package/src/{dev/imports.ts → runtime/modules.ts} +934 -847
  369. package/src/runtime/{server.ts → vendor-build.ts} +848 -1696
  370. package/src/runtime/vendor.ts +425 -404
  371. package/src/styles.d.ts +9 -0
  372. package/src/types.ts +320 -335
  373. package/src/utils/ansi.ts +5 -5
  374. package/src/utils/{source.ts → code.ts} +15 -12
  375. package/src/utils/content-type.ts +3 -3
  376. package/src/utils/decode.ts +2 -2
  377. package/src/utils/dev-profile.ts +13 -13
  378. package/src/utils/error-log.ts +6 -6
  379. package/src/utils/esbuild.ts +18 -18
  380. package/src/utils/fs-cache.ts +13 -13
  381. package/src/utils/fs.ts +57 -49
  382. package/src/utils/html.ts +20 -24
  383. package/src/utils/native-require.ts +8 -8
  384. package/src/utils/serialize.ts +139 -146
  385. package/src/utils/verbose.ts +18 -18
  386. package/src/cli/analyze-print.ts +0 -181
  387. package/src/compat/middleware/manifest.ts +0 -210
  388. package/src/compat/next/image-client.tsx +0 -215
  389. package/src/compat/next/link-usage.ts +0 -29
  390. package/src/css/index.ts +0 -2
  391. package/src/render/index.ts +0 -1
  392. package/src/style-modules.d.ts +0 -9
@@ -1,105 +1,102 @@
1
- import type { MetadataLink } from '../../types';
2
- import { getWorkUnit } from '../../request/context';
3
- import { registerResponseFinalizers } from '../../extensions';
4
- import type { ResponseFinalizerContext } from '../../extensions';
5
- import { setResourceHintListener } from '../../render/resource-hints';
6
- import { getNextConfig } from './config-loader';
7
-
8
- const RESOURCE_HINTS_KEY = Symbol.for('pnext.compat.resourceHints');
9
- const DEFAULT_REACT_MAX_HEADERS_LENGTH = 6000;
1
+ import type { MetadataLink } from '../../types'
2
+ import { getWorkUnit } from '../../request/context'
3
+ import { registerResponseFinalizers } from '../../extensions'
4
+ import type { ResponseFinalizerContext } from '../../extensions'
5
+ import { setResourceHintListener } from '../../render/resource-hints'
6
+ import { getNextConfig } from './config-loader'
7
+
8
+ const RESOURCE_HINTS_KEY = Symbol.for('pnext.compat.resourceHints')
9
+ const DEFAULT_REACT_MAX_HEADERS_LENGTH = 6000
10
10
  // Next emits react-dom preload()/preconnect() hints as a `Link` response
11
11
  // header by default in production; nothing in the compat runtime ever called
12
12
  // enableResourceHintHeaders, so the finalizer was dead code. The finalizer is
13
13
  // only registered under next-compat, so defaulting on is scoped already.
14
- let resourceHintHeadersEnabled = true;
14
+ let resourceHintHeadersEnabled = true
15
15
 
16
16
  export type ResourceHint = MetadataLink & {
17
- rel: string;
18
- url: string;
19
- };
17
+ rel: string
18
+ url: string
19
+ }
20
20
 
21
21
  export function enableResourceHintHeaders(enabled: boolean): void {
22
- resourceHintHeadersEnabled = enabled;
22
+ resourceHintHeadersEnabled = enabled
23
23
  }
24
24
 
25
25
  export function registerResourceHintFinalizer(): void {
26
- registerResponseFinalizers(resourceHintResponseFinalizer);
26
+ registerResponseFinalizers(resourceHintResponseFinalizer)
27
27
  // Every react-dom preload()/preconnect()/preinit() during a render lands on
28
28
  // the active work unit so the finalizer (and the build prerender) can emit
29
29
  // Next's `Link` response header alongside the in-document <link> tags.
30
- setResourceHintListener(hint => recordResourceHint(hint as ResourceHint));
30
+ setResourceHintListener(hint => recordResourceHint(hint as ResourceHint))
31
31
  }
32
32
 
33
33
  export function recordResourceHint(hint: ResourceHint): void {
34
- const unit = getWorkUnit();
35
- if (!unit) return;
34
+ const unit = getWorkUnit()
35
+ if (!unit) return
36
36
 
37
- const existing = (unit.compat?.[RESOURCE_HINTS_KEY] as ResourceHint[] | undefined) ?? [];
38
- if (!unit.compat) unit.compat = {};
39
- unit.compat[RESOURCE_HINTS_KEY] = dedupeResourceHints([...existing, hint]);
37
+ const existing = (unit.compat?.[RESOURCE_HINTS_KEY] as ResourceHint[] | undefined) ?? []
38
+ if (!unit.compat) unit.compat = {}
39
+ unit.compat[RESOURCE_HINTS_KEY] = dedupeResourceHints([...existing, hint])
40
40
  }
41
41
 
42
42
  export function takeResourceHintsForResponse(): ResourceHint[] {
43
- const unit = getWorkUnit();
44
- const compat = unit?.compat;
45
- if (!compat) return [];
46
- const hints = (compat[RESOURCE_HINTS_KEY] as ResourceHint[] | undefined) ?? [];
47
- compat[RESOURCE_HINTS_KEY] = undefined;
48
- return hints;
43
+ const unit = getWorkUnit()
44
+ const compat = unit?.compat
45
+ if (!compat) return []
46
+ const hints = (compat[RESOURCE_HINTS_KEY] as ResourceHint[] | undefined) ?? []
47
+ compat[RESOURCE_HINTS_KEY] = undefined
48
+ return hints
49
49
  }
50
50
 
51
- const ALLOWED_ROUTE_KINDS = new Set<ResponseFinalizerContext['routeKind']>([
52
- 'html',
53
- 'data',
54
- ]);
51
+ const ALLOWED_ROUTE_KINDS = new Set<ResponseFinalizerContext['routeKind']>(['html', 'data'])
55
52
 
56
53
  function resourceHintResponseFinalizer(ctx: ResponseFinalizerContext): void {
57
- if (!shouldEmitResourceHintsHeader()) return;
58
- if (ctx.hints?.runtime === 'edge') return;
59
- if (!ALLOWED_ROUTE_KINDS.has(ctx.routeKind)) return;
60
-
61
- const value = takeResourceHintHeader();
62
- if (value === undefined) return;
63
- const existing = ctx.headers.get('link');
64
- ctx.headers.set('link', existing ? `${existing}, ${value}` : value);
54
+ if (!shouldEmitResourceHintsHeader()) return
55
+ if (ctx.hints?.runtime === 'edge') return
56
+ if (!ALLOWED_ROUTE_KINDS.has(ctx.routeKind)) return
57
+
58
+ const value = takeResourceHintHeader()
59
+ if (value === undefined) return
60
+ const existing = ctx.headers.get('link')
61
+ ctx.headers.set('link', existing ? `${existing}, ${value}` : value)
65
62
  }
66
63
 
67
64
  function shouldEmitResourceHintsHeader(): boolean {
68
- return resourceHintHeadersEnabled;
65
+ return resourceHintHeadersEnabled
69
66
  }
70
67
 
71
68
  function getReactMaxHeadersLength(): number {
72
- const configValue = getNextConfig().reactMaxHeadersLength;
69
+ const configValue = getNextConfig().reactMaxHeadersLength
73
70
  if (typeof configValue === 'number' && Number.isFinite(configValue) && configValue >= 0) {
74
- return Math.floor(configValue);
71
+ return Math.floor(configValue)
75
72
  }
76
73
  // eslint-disable-next-line turbo/no-undeclared-env-vars
77
- const envValue = process.env.TEST_REACT_MAX_HEADERS_LENGTH;
74
+ const envValue = process.env.TEST_REACT_MAX_HEADERS_LENGTH
78
75
  if (typeof envValue === 'string' && envValue.trim() !== '') {
79
- const parsed = Number.parseInt(envValue, 10);
80
- if (Number.isFinite(parsed) && parsed >= 0) return Math.floor(parsed);
76
+ const parsed = Number.parseInt(envValue, 10)
77
+ if (Number.isFinite(parsed) && parsed >= 0) return Math.floor(parsed)
81
78
  }
82
- return DEFAULT_REACT_MAX_HEADERS_LENGTH;
79
+ return DEFAULT_REACT_MAX_HEADERS_LENGTH
83
80
  }
84
81
 
85
82
  export function takeResourceHintHeader(): string | undefined {
86
- const hints = takeResourceHintsForResponse();
87
- if (hints.length === 0) return undefined;
83
+ const hints = takeResourceHintsForResponse()
84
+ if (hints.length === 0) return undefined
88
85
 
89
- const maxLength = getReactMaxHeadersLength();
90
- if (!(maxLength > 0)) return undefined;
86
+ const maxLength = getReactMaxHeadersLength()
87
+ if (!(maxLength > 0)) return undefined
91
88
 
92
- const entries = hints.map(hint => formatLinkHeaderEntry(hint)).filter(Boolean);
93
- if (entries.length === 0) return undefined;
89
+ const entries = hints.map(hint => formatLinkHeaderEntry(hint)).filter(Boolean)
90
+ if (entries.length === 0) return undefined
94
91
 
95
- const values: string[] = [];
92
+ const values: string[] = []
96
93
  for (const entry of entries) {
97
- const candidate = values.length > 0 ? `${values.join(', ')}, ${entry}` : entry;
98
- if (candidate.length > maxLength) break;
99
- values.push(entry);
94
+ const candidate = values.length > 0 ? `${values.join(', ')}, ${entry}` : entry
95
+ if (candidate.length > maxLength) break
96
+ values.push(entry)
100
97
  }
101
98
 
102
- return values.length === 0 ? undefined : values.join(', ');
99
+ return values.length === 0 ? undefined : values.join(', ')
103
100
  }
104
101
 
105
102
  // React's Link-header entry shape (ReactFizz getPreloadAsHeader): the rel is
@@ -108,29 +105,29 @@ export function takeResourceHintHeader(): string | undefined {
108
105
  // expected header lengths from React's exact per-entry size, so the format
109
106
  // must match byte-for-byte.
110
107
  function formatLinkHeaderEntry(hint: ResourceHint): string {
111
- const parts = [`<${hint.url}>`, `rel=${hint.rel}`];
112
- if (hint.as) parts.push(`as="${hint.as}"`);
108
+ const parts = [`<${hint.url}>`, `rel=${hint.rel}`]
109
+ if (hint.as) parts.push(`as="${hint.as}"`)
113
110
  if (hint.crossOrigin !== undefined)
114
- parts.push(`crossorigin="${hint.crossOrigin === 'anonymous' ? '' : hint.crossOrigin}"`);
115
- if (hint.type) parts.push(`type="${hint.type}"`);
116
- if (hint.media) parts.push(`media="${hint.media}"`);
117
- if (hint.sizes) parts.push(`sizes="${hint.sizes}"`);
118
- if (hint.title) parts.push(`title="${hint.title}"`);
119
- if (hint.hrefLang) parts.push(`hreflang="${hint.hrefLang}"`);
120
- if (hint.fetchPriority) parts.push(`fetchpriority="${hint.fetchPriority}"`);
121
- if (hint.nonce) parts.push(`nonce="${hint.nonce}"`);
122
- return parts.join('; ');
111
+ parts.push(`crossorigin="${hint.crossOrigin === 'anonymous' ? '' : hint.crossOrigin}"`)
112
+ if (hint.type) parts.push(`type="${hint.type}"`)
113
+ if (hint.media) parts.push(`media="${hint.media}"`)
114
+ if (hint.sizes) parts.push(`sizes="${hint.sizes}"`)
115
+ if (hint.title) parts.push(`title="${hint.title}"`)
116
+ if (hint.hrefLang) parts.push(`hreflang="${hint.hrefLang}"`)
117
+ if (hint.fetchPriority) parts.push(`fetchpriority="${hint.fetchPriority}"`)
118
+ if (hint.nonce) parts.push(`nonce="${hint.nonce}"`)
119
+ return parts.join('; ')
123
120
  }
124
121
 
125
122
  function dedupeResourceHints(hints: ResourceHint[]): ResourceHint[] {
126
- if (hints.length <= 1) return hints;
127
- const seen = new Set<string>();
128
- const next: ResourceHint[] = [];
123
+ if (hints.length <= 1) return hints
124
+ const seen = new Set<string>()
125
+ const next: ResourceHint[] = []
129
126
  for (const hint of hints) {
130
- const key = formatLinkHeaderEntry(hint);
131
- if (seen.has(key)) continue;
132
- seen.add(key);
133
- next.push(hint);
127
+ const key = formatLinkHeaderEntry(hint)
128
+ if (seen.has(key)) continue
129
+ seen.add(key)
130
+ next.push(hint)
134
131
  }
135
- return next;
132
+ return next
136
133
  }
@@ -17,83 +17,83 @@
17
17
  * Divergence: the render sees the destination URL (Next keeps the requested URL as canonical for
18
18
  * usePathname; recordCanonicalUrl handles that separately).
19
19
  */
20
- import { loadNextConfig, loadResolvedNextConfig } from '../actions/config';
20
+ import { loadNextConfig, loadResolvedNextConfig } from '../actions/config'
21
21
 
22
22
  export interface CompatRewrite {
23
- regex: RegExp;
24
- paramNames: string[];
25
- destination: string;
26
- has: RewriteCondition[];
27
- missing: RewriteCondition[];
23
+ regex: RegExp
24
+ paramNames: string[]
25
+ destination: string
26
+ has: RewriteCondition[]
27
+ missing: RewriteCondition[]
28
28
  /**
29
29
  * A `fallback` rewrite: Next applies it only after filesystem AND dynamic
30
30
  * routes have all missed, i.e. only on a request that would otherwise 404.
31
31
  * `beforeFiles`/`afterFiles` (and the array form, which is `afterFiles`)
32
32
  * apply ahead of routing and carry this false.
33
33
  */
34
- fallback: boolean;
34
+ fallback: boolean
35
35
  /**
36
36
  * `basePath: false` on the entry: the source is matched against the RAW
37
37
  * request path, outside the configured basePath. Core 404s such paths before
38
38
  * routing, so these rules get their turn from the outside-basePath pass
39
39
  * instead of the normal one (and never both).
40
40
  */
41
- outsideBasePath: boolean;
41
+ outsideBasePath: boolean
42
42
  }
43
43
 
44
44
  export interface RewriteCondition {
45
- type: 'host' | 'header' | 'query' | 'cookie';
46
- key?: string;
47
- value?: string;
45
+ type: 'host' | 'header' | 'query' | 'cookie'
46
+ key?: string
47
+ value?: string
48
48
  }
49
49
 
50
50
  interface RewriteEntry {
51
- source?: string;
52
- destination?: string;
53
- has?: unknown;
54
- missing?: unknown;
55
- basePath?: unknown;
51
+ source?: string
52
+ destination?: string
53
+ has?: unknown
54
+ missing?: unknown
55
+ basePath?: unknown
56
56
  }
57
57
 
58
58
  /** Request facts a rewrite's `has`/`missing` conditions are evaluated against. */
59
59
  export interface RewriteRequestContext {
60
- host: string;
61
- headers: Headers;
62
- cookies: Record<string, string>;
63
- query: URLSearchParams;
60
+ host: string
61
+ headers: Headers
62
+ cookies: Record<string, string>
63
+ query: URLSearchParams
64
64
  }
65
65
 
66
- const VALID_CONDITION_TYPES = new Set(['host', 'header', 'query', 'cookie']);
66
+ const VALID_CONDITION_TYPES = new Set(['host', 'header', 'query', 'cookie'])
67
67
 
68
68
  export async function loadCompatRewrites(root: string): Promise<CompatRewrite[]> {
69
- let config = await loadResolvedNextConfig(root);
70
- if (typeof config?.rewrites !== 'function') config = await loadNextConfig(root);
71
- const producer = config?.rewrites;
72
- if (typeof producer !== 'function') return [];
73
- let value: unknown;
69
+ let config = await loadResolvedNextConfig(root)
70
+ if (typeof config?.rewrites !== 'function') config = await loadNextConfig(root)
71
+ const producer = config?.rewrites
72
+ if (typeof producer !== 'function') return []
73
+ let value: unknown
74
74
  try {
75
- value = await producer();
75
+ value = await producer()
76
76
  } catch {
77
- return [];
77
+ return []
78
78
  }
79
79
  const entries: (RewriteEntry & { fallback: boolean })[] = Array.isArray(value)
80
80
  ? (value as RewriteEntry[]).map(entry => ({ ...entry, fallback: false }))
81
81
  : value && typeof value === 'object'
82
82
  ? (['beforeFiles', 'afterFiles', 'fallback'] as const).flatMap(key => {
83
- const list = (value as Record<string, unknown>)[key];
83
+ const list = (value as Record<string, unknown>)[key]
84
84
  return Array.isArray(list)
85
85
  ? (list as RewriteEntry[]).map(entry => ({ ...entry, fallback: key === 'fallback' }))
86
- : [];
86
+ : []
87
87
  })
88
- : [];
88
+ : []
89
89
 
90
- const rewrites: CompatRewrite[] = [];
90
+ const rewrites: CompatRewrite[] = []
91
91
  for (const entry of entries) {
92
- if (!entry?.source || !entry.destination) continue;
93
- const has = parseConditions(entry.has);
94
- const missing = parseConditions(entry.missing);
95
- if (has === null || missing === null) continue; // unsupported condition shape
96
- const compiled = compileSource(entry.source);
92
+ if (!entry?.source || !entry.destination) continue
93
+ const has = parseConditions(entry.has)
94
+ const missing = parseConditions(entry.missing)
95
+ if (has === null || missing === null) continue // unsupported condition shape
96
+ const compiled = compileSource(entry.source)
97
97
  if (compiled) {
98
98
  rewrites.push({
99
99
  ...compiled,
@@ -102,78 +102,78 @@ export async function loadCompatRewrites(root: string): Promise<CompatRewrite[]>
102
102
  missing,
103
103
  fallback: entry.fallback,
104
104
  outsideBasePath: entry.basePath === false,
105
- });
105
+ })
106
106
  }
107
107
  }
108
- return rewrites;
108
+ return rewrites
109
109
  }
110
110
 
111
111
  /** Parse a has/missing list into typed conditions; null if any entry is unsupported. */
112
112
  export function parseConditions(value: unknown): RewriteCondition[] | null {
113
- if (value === undefined) return [];
114
- if (!Array.isArray(value)) return null;
115
- const conditions: RewriteCondition[] = [];
113
+ if (value === undefined) return []
114
+ if (!Array.isArray(value)) return null
115
+ const conditions: RewriteCondition[] = []
116
116
  for (const raw of value as unknown[]) {
117
- if (!raw || typeof raw !== 'object') return null;
118
- const { type, key, value: condValue } = raw as Record<string, unknown>;
119
- if (typeof type !== 'string' || !VALID_CONDITION_TYPES.has(type)) return null;
120
- if (key !== undefined && typeof key !== 'string') return null;
121
- if (condValue !== undefined && typeof condValue !== 'string') return null;
117
+ if (!raw || typeof raw !== 'object') return null
118
+ const { type, key, value: condValue } = raw as Record<string, unknown>
119
+ if (typeof type !== 'string' || !VALID_CONDITION_TYPES.has(type)) return null
120
+ if (key !== undefined && typeof key !== 'string') return null
121
+ if (condValue !== undefined && typeof condValue !== 'string') return null
122
122
  conditions.push({
123
123
  type: type as RewriteCondition['type'],
124
124
  ...(typeof key === 'string' ? { key } : {}),
125
125
  ...(typeof condValue === 'string' ? { value: condValue } : {}),
126
- });
126
+ })
127
127
  }
128
- return conditions;
128
+ return conditions
129
129
  }
130
130
 
131
131
  export function compileSource(source: string): { regex: RegExp; paramNames: string[] } | null {
132
- const paramNames: string[] = [];
132
+ const paramNames: string[] = []
133
133
  // Match against the pathname. Note: the source is a path-to-regexp pattern
134
134
  // (query matching is done via `has` conditions), so it never carries a
135
135
  // literal `?query`. We must NOT split on `?` — a `?` may legitimately appear
136
136
  // inside a regex token such as `:path((?!sitemap.xml$).*)` or `(?<name>...)`.
137
- const segments = source.split('/').filter(Boolean);
138
- const parts: string[] = [];
137
+ const segments = source.split('/').filter(Boolean)
138
+ const parts: string[] = []
139
139
  for (const segment of segments) {
140
140
  // :param(customRegex) — a named param with an explicit regex body (may span
141
141
  // the whole segment, e.g. `:path((?!sitemap.xml$).*)`).
142
- const custom = /^:([A-Za-z_$][\w$]*)\((.*)\)$/.exec(segment);
142
+ const custom = /^:([A-Za-z_$][\w$]*)\((.*)\)$/.exec(segment)
143
143
  if (custom?.[1] !== undefined && custom[2] !== undefined) {
144
- paramNames.push(custom[1]);
145
- parts.push(`(${custom[2]})`);
146
- continue;
144
+ paramNames.push(custom[1])
145
+ parts.push(`(${custom[2]})`)
146
+ continue
147
147
  }
148
- const catchAll = /^:([A-Za-z_$][\w$]*)[*+]$/.exec(segment);
148
+ const catchAll = /^:([A-Za-z_$][\w$]*)[*+]$/.exec(segment)
149
149
  if (catchAll?.[1]) {
150
- paramNames.push(catchAll[1]);
151
- parts.push('(.*)');
152
- continue;
150
+ paramNames.push(catchAll[1])
151
+ parts.push('(.*)')
152
+ continue
153
153
  }
154
- const optional = /^:([A-Za-z_$][\w$]*)\?$/.exec(segment);
154
+ const optional = /^:([A-Za-z_$][\w$]*)\?$/.exec(segment)
155
155
  if (optional?.[1]) {
156
- paramNames.push(optional[1]);
157
- parts.push('([^/]*)');
158
- continue;
156
+ paramNames.push(optional[1])
157
+ parts.push('([^/]*)')
158
+ continue
159
159
  }
160
- const param = /^:([A-Za-z_$][\w$]*)$/.exec(segment);
160
+ const param = /^:([A-Za-z_$][\w$]*)$/.exec(segment)
161
161
  if (param?.[1]) {
162
- paramNames.push(param[1]);
163
- parts.push('([^/]+)');
164
- continue;
162
+ paramNames.push(param[1])
163
+ parts.push('([^/]+)')
164
+ continue
165
165
  }
166
166
  // Plain literal segments may carry regex-significant filename characters
167
167
  // (`favicon.ico`, `sitemap.xml`) — escape them. Anything with actual
168
168
  // pattern syntax beyond that is unsupported.
169
169
  if (/^[\w.\- ]+$/.test(segment)) {
170
- parts.push(segment.replace(/\./g, '\\.'));
171
- continue;
170
+ parts.push(segment.replace(/\./g, '\\.'))
171
+ continue
172
172
  }
173
- if (/[.*+?^${}()|[\]\\]/.test(segment)) return null; // unsupported literal syntax
174
- parts.push(segment.replace(/[/\\]/g, ''));
173
+ if (/[.*+?^${}()|[\]\\]/.test(segment)) return null // unsupported literal syntax
174
+ parts.push(segment.replace(/[/\\]/g, ''))
175
175
  }
176
- return { regex: new RegExp(`^/${parts.join('/')}/?$`), paramNames };
176
+ return { regex: new RegExp(`^/${parts.join('/')}/?$`), paramNames }
177
177
  }
178
178
 
179
179
  /** Evaluate a single has/missing condition, returning captured params or null (no match). */
@@ -181,14 +181,14 @@ function evaluateCondition(
181
181
  condition: RewriteCondition,
182
182
  ctx: RewriteRequestContext,
183
183
  ): Record<string, string> | null {
184
- const target = conditionTarget(condition, ctx);
185
- if (target === undefined) return null;
186
- if (condition.value === undefined) return {}; // presence-only match
184
+ const target = conditionTarget(condition, ctx)
185
+ if (target === undefined) return null
186
+ if (condition.value === undefined) return {} // presence-only match
187
187
  // Anchor the value regex the way Next does (full-value match).
188
- const regex = new RegExp(`^(?:${condition.value})$`);
189
- const match = regex.exec(target);
190
- if (!match) return null;
191
- return match.groups ? { ...match.groups } : {};
188
+ const regex = new RegExp(`^(?:${condition.value})$`)
189
+ const match = regex.exec(target)
190
+ if (!match) return null
191
+ return match.groups ? { ...match.groups } : {}
192
192
  }
193
193
 
194
194
  function conditionTarget(
@@ -197,24 +197,24 @@ function conditionTarget(
197
197
  ): string | undefined {
198
198
  switch (condition.type) {
199
199
  case 'host':
200
- return ctx.host;
200
+ return ctx.host
201
201
  case 'header':
202
- return condition.key ? (ctx.headers.get(condition.key) ?? undefined) : undefined;
202
+ return condition.key ? (ctx.headers.get(condition.key) ?? undefined) : undefined
203
203
  case 'cookie':
204
- return condition.key ? ctx.cookies[condition.key] : undefined;
204
+ return condition.key ? ctx.cookies[condition.key] : undefined
205
205
  case 'query':
206
- return condition.key ? (ctx.query.get(condition.key) ?? undefined) : undefined;
206
+ return condition.key ? (ctx.query.get(condition.key) ?? undefined) : undefined
207
207
  default:
208
- return undefined;
208
+ return undefined
209
209
  }
210
210
  }
211
211
 
212
212
  export interface RewriteResult {
213
- pathname: string;
213
+ pathname: string
214
214
  /** Search params after the rewrite (original query + any auto-appended params). */
215
- search: URLSearchParams;
215
+ search: URLSearchParams
216
216
  /** Fully-qualified destination for external rewrites (`https://...`). */
217
- destination?: string;
217
+ destination?: string
218
218
  }
219
219
 
220
220
  /**
@@ -228,7 +228,7 @@ export function applyCompatRewrites(
228
228
  pathname: string,
229
229
  ctx?: RewriteRequestContext,
230
230
  ): string | undefined {
231
- return resolveCompatRewrite(rewrites, pathname, ctx)?.pathname;
231
+ return resolveCompatRewrite(rewrites, pathname, ctx)?.pathname
232
232
  }
233
233
 
234
234
  /**
@@ -246,42 +246,42 @@ export function resolveCompatRewrite(
246
246
  headers: new Headers(),
247
247
  cookies: {},
248
248
  query: new URLSearchParams(),
249
- };
249
+ }
250
250
  for (const rewrite of rewrites) {
251
- const match = rewrite.regex.exec(pathname);
252
- if (!match) continue;
251
+ const match = rewrite.regex.exec(pathname)
252
+ if (!match) continue
253
253
 
254
254
  // Collect all params: source captures first, then has/missing captures.
255
- const params: Record<string, string> = {};
255
+ const params: Record<string, string> = {}
256
256
  rewrite.paramNames.forEach((name, index) => {
257
- params[name] = match[index + 1] ?? '';
258
- });
257
+ params[name] = match[index + 1] ?? ''
258
+ })
259
259
 
260
- const conditionParams = evaluateConditions(rewrite, context);
261
- if (conditionParams === null) continue; // has/missing gate failed
262
- Object.assign(params, conditionParams);
260
+ const conditionParams = evaluateConditions(rewrite, context)
261
+ if (conditionParams === null) continue // has/missing gate failed
262
+ Object.assign(params, conditionParams)
263
263
 
264
- const [destPath, destQuery] = splitDestination(rewrite.destination);
265
- const { pathname: newPath, used: usedInPath } = substitute(destPath, params);
266
- const search = new URLSearchParams(context.query);
264
+ const [destPath, destQuery] = splitDestination(rewrite.destination)
265
+ const { pathname: newPath, used: usedInPath } = substitute(destPath, params)
266
+ const search = new URLSearchParams(context.query)
267
267
 
268
268
  // Destination-declared query params (?key=:val) are always applied.
269
- let usedInQuery = false;
269
+ let usedInQuery = false
270
270
  if (destQuery) {
271
- const destParams = new URLSearchParams(destQuery);
271
+ const destParams = new URLSearchParams(destQuery)
272
272
  for (const [key, rawValue] of destParams.entries()) {
273
- const { pathname: value, used } = substitute(rawValue, params);
274
- if (used) usedInQuery = true;
275
- search.set(key, value);
273
+ const { pathname: value, used } = substitute(rawValue, params)
274
+ if (used) usedInQuery = true
275
+ search.set(key, value)
276
276
  }
277
277
  }
278
278
 
279
279
  // Next rule: only auto-append unused params to the query when NONE of the
280
280
  // params were used in the destination. If any param is used, nothing leaks.
281
- const anyUsed = usedInPath.size > 0 || usedInQuery;
281
+ const anyUsed = usedInPath.size > 0 || usedInQuery
282
282
  if (!anyUsed) {
283
283
  for (const [name, value] of Object.entries(params)) {
284
- if (!search.has(name)) search.append(name, value);
284
+ if (!search.has(name)) search.append(name, value)
285
285
  }
286
286
  }
287
287
 
@@ -289,23 +289,20 @@ export function resolveCompatRewrite(
289
289
  pathname: newPath,
290
290
  search,
291
291
  destination: /^https?:/.test(newPath) ? normalizeDestination(newPath, search) : undefined,
292
- };
292
+ }
293
293
  }
294
- return undefined;
294
+ return undefined
295
295
  }
296
296
 
297
- function normalizeDestination(
298
- pathname: string,
299
- search: URLSearchParams,
300
- ): string | undefined {
297
+ function normalizeDestination(pathname: string, search: URLSearchParams): string | undefined {
301
298
  try {
302
- const destination = new URL(pathname);
299
+ const destination = new URL(pathname)
303
300
  for (const [key, value] of search.entries()) {
304
- destination.searchParams.set(key, value);
301
+ destination.searchParams.set(key, value)
305
302
  }
306
- return destination.toString();
303
+ return destination.toString()
307
304
  } catch {
308
- return undefined;
305
+ return undefined
309
306
  }
310
307
  }
311
308
 
@@ -314,22 +311,22 @@ export function evaluateConditions(
314
311
  rule: { has: RewriteCondition[]; missing: RewriteCondition[] },
315
312
  ctx: RewriteRequestContext,
316
313
  ): Record<string, string> | null {
317
- const params: Record<string, string> = {};
314
+ const params: Record<string, string> = {}
318
315
  for (const condition of rule.has) {
319
- const captured = evaluateCondition(condition, ctx);
320
- if (captured === null) return null;
321
- Object.assign(params, captured);
316
+ const captured = evaluateCondition(condition, ctx)
317
+ if (captured === null) return null
318
+ Object.assign(params, captured)
322
319
  }
323
320
  for (const condition of rule.missing) {
324
- if (evaluateCondition(condition, ctx) !== null) return null;
321
+ if (evaluateCondition(condition, ctx) !== null) return null
325
322
  }
326
- return params;
323
+ return params
327
324
  }
328
325
 
329
326
  export function splitDestination(destination: string): [string, string | undefined] {
330
- const index = destination.indexOf('?');
331
- if (index === -1) return [destination, undefined];
332
- return [destination.slice(0, index), destination.slice(index + 1)];
327
+ const index = destination.indexOf('?')
328
+ if (index === -1) return [destination, undefined]
329
+ return [destination.slice(0, index), destination.slice(index + 1)]
333
330
  }
334
331
 
335
332
  /**
@@ -340,11 +337,11 @@ export function substitute(
340
337
  template: string,
341
338
  params: Record<string, string>,
342
339
  ): { pathname: string; used: Set<string> } {
343
- const used = new Set<string>();
340
+ const used = new Set<string>()
344
341
  const result = template.replace(/:([A-Za-z_$][\w$]*)(\*|\+|\?)?/g, (whole, name: string) => {
345
- if (!(name in params)) return whole;
346
- used.add(name);
347
- return params[name] ?? '';
348
- });
349
- return { pathname: result, used };
342
+ if (!(name in params)) return whole
343
+ used.add(name)
344
+ return params[name] ?? ''
345
+ })
346
+ return { pathname: result, used }
350
347
  }