vinext 0.0.49 → 0.0.51

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 (506) hide show
  1. package/dist/build/client-build-config.js.map +1 -1
  2. package/dist/build/google-fonts/build-url.js.map +1 -1
  3. package/dist/build/google-fonts/fallback-metrics-data.js +14031 -0
  4. package/dist/build/google-fonts/fallback-metrics-data.js.map +1 -0
  5. package/dist/build/google-fonts/fallback-metrics.d.ts +13 -0
  6. package/dist/build/google-fonts/fallback-metrics.js +46 -0
  7. package/dist/build/google-fonts/fallback-metrics.js.map +1 -0
  8. package/dist/build/google-fonts/get-axes.js.map +1 -1
  9. package/dist/build/google-fonts/sort-variants.js.map +1 -1
  10. package/dist/build/google-fonts/validate.js.map +1 -1
  11. package/dist/build/layout-classification.js.map +1 -1
  12. package/dist/build/nitro-route-rules.js.map +1 -1
  13. package/dist/build/precompress.d.ts +13 -2
  14. package/dist/build/precompress.js +12 -3
  15. package/dist/build/precompress.js.map +1 -1
  16. package/dist/build/prerender.d.ts +17 -1
  17. package/dist/build/prerender.js +114 -23
  18. package/dist/build/prerender.js.map +1 -1
  19. package/dist/build/report.d.ts +5 -4
  20. package/dist/build/report.js +196 -348
  21. package/dist/build/report.js.map +1 -1
  22. package/dist/build/route-classification-injector.js.map +1 -1
  23. package/dist/build/route-classification-manifest.js.map +1 -1
  24. package/dist/build/run-prerender.js.map +1 -1
  25. package/dist/build/server-manifest.js.map +1 -1
  26. package/dist/build/ssr-manifest.js.map +1 -1
  27. package/dist/build/standalone.js.map +1 -1
  28. package/dist/build/static-export.js.map +1 -1
  29. package/dist/check.js +2 -1
  30. package/dist/check.js.map +1 -1
  31. package/dist/cli-args.js.map +1 -1
  32. package/dist/cli.js +68 -7
  33. package/dist/cli.js.map +1 -1
  34. package/dist/client/instrumentation-client-state.js.map +1 -1
  35. package/dist/client/validate-module-path.js.map +1 -1
  36. package/dist/client/vinext-next-data.d.ts +5 -1
  37. package/dist/client/window-next.d.ts +151 -0
  38. package/dist/client/window-next.js +48 -0
  39. package/dist/client/window-next.js.map +1 -0
  40. package/dist/cloudflare/kv-cache-handler.js.map +1 -1
  41. package/dist/cloudflare/tpr.js +2 -1
  42. package/dist/cloudflare/tpr.js.map +1 -1
  43. package/dist/config/config-matchers.d.ts +3 -1
  44. package/dist/config/config-matchers.js +5 -4
  45. package/dist/config/config-matchers.js.map +1 -1
  46. package/dist/config/dotenv.d.ts +11 -1
  47. package/dist/config/dotenv.js.map +1 -1
  48. package/dist/config/next-config.d.ts +93 -6
  49. package/dist/config/next-config.js +233 -6
  50. package/dist/config/next-config.js.map +1 -1
  51. package/dist/config/tsconfig-paths.d.ts +13 -0
  52. package/dist/config/tsconfig-paths.js +117 -0
  53. package/dist/config/tsconfig-paths.js.map +1 -0
  54. package/dist/deploy.js +16 -7
  55. package/dist/deploy.js.map +1 -1
  56. package/dist/entries/app-browser-entry.d.ts +3 -1
  57. package/dist/entries/app-browser-entry.js +36 -2
  58. package/dist/entries/app-browser-entry.js.map +1 -1
  59. package/dist/entries/app-rsc-entry.d.ts +19 -1
  60. package/dist/entries/app-rsc-entry.js +49 -12
  61. package/dist/entries/app-rsc-entry.js.map +1 -1
  62. package/dist/entries/app-rsc-manifest.d.ts +9 -0
  63. package/dist/entries/app-rsc-manifest.js +8 -1
  64. package/dist/entries/app-rsc-manifest.js.map +1 -1
  65. package/dist/entries/app-ssr-entry.js.map +1 -1
  66. package/dist/entries/pages-client-entry.js +3 -5
  67. package/dist/entries/pages-client-entry.js.map +1 -1
  68. package/dist/entries/pages-entry-helpers.js.map +1 -1
  69. package/dist/entries/pages-server-entry.js +34 -1
  70. package/dist/entries/pages-server-entry.js.map +1 -1
  71. package/dist/entries/runtime-entry-module.js.map +1 -1
  72. package/dist/index.js +204 -53
  73. package/dist/index.js.map +1 -1
  74. package/dist/init.js.map +1 -1
  75. package/dist/plugins/async-hooks-stub.js.map +1 -1
  76. package/dist/plugins/client-reference-dedup.d.ts +15 -2
  77. package/dist/plugins/client-reference-dedup.js +138 -16
  78. package/dist/plugins/client-reference-dedup.js.map +1 -1
  79. package/dist/plugins/fonts.d.ts +2 -2
  80. package/dist/plugins/fonts.js +15 -6
  81. package/dist/plugins/fonts.js.map +1 -1
  82. package/dist/plugins/instrumentation-client.js.map +1 -1
  83. package/dist/plugins/og-assets.js.map +1 -1
  84. package/dist/plugins/optimize-imports.js.map +1 -1
  85. package/dist/plugins/postcss.js.map +1 -1
  86. package/dist/plugins/rsc-client-reference-loaders.d.ts +7 -0
  87. package/dist/plugins/rsc-client-reference-loaders.js +48 -0
  88. package/dist/plugins/rsc-client-reference-loaders.js.map +1 -0
  89. package/dist/plugins/rsc-client-shim-excludes.js.map +1 -1
  90. package/dist/plugins/sass.d.ts +34 -0
  91. package/dist/plugins/sass.js +22 -0
  92. package/dist/plugins/sass.js.map +1 -0
  93. package/dist/plugins/server-externals-manifest.js.map +1 -1
  94. package/dist/plugins/strip-server-exports.js.map +1 -1
  95. package/dist/routing/app-route-graph.d.ts +78 -6
  96. package/dist/routing/app-route-graph.js +241 -25
  97. package/dist/routing/app-route-graph.js.map +1 -1
  98. package/dist/routing/app-router.js.map +1 -1
  99. package/dist/routing/file-matcher.js.map +1 -1
  100. package/dist/routing/pages-router.js.map +1 -1
  101. package/dist/routing/route-matching.js.map +1 -1
  102. package/dist/routing/route-pattern.d.ts +56 -1
  103. package/dist/routing/route-pattern.js +60 -1
  104. package/dist/routing/route-pattern.js.map +1 -1
  105. package/dist/routing/route-trie.js.map +1 -1
  106. package/dist/routing/route-validation.js.map +1 -1
  107. package/dist/routing/utils.js.map +1 -1
  108. package/dist/server/api-handler.js.map +1 -1
  109. package/dist/server/app-browser-action-result.d.ts +44 -0
  110. package/dist/server/app-browser-action-result.js +79 -0
  111. package/dist/server/app-browser-action-result.js.map +1 -0
  112. package/dist/server/app-browser-entry.js +330 -133
  113. package/dist/server/app-browser-entry.js.map +1 -1
  114. package/dist/server/app-browser-error.js.map +1 -1
  115. package/dist/server/app-browser-hydration.d.ts +31 -0
  116. package/dist/server/app-browser-hydration.js +30 -0
  117. package/dist/server/app-browser-hydration.js.map +1 -0
  118. package/dist/server/app-browser-navigation-controller.d.ts +20 -4
  119. package/dist/server/app-browser-navigation-controller.js +90 -23
  120. package/dist/server/app-browser-navigation-controller.js.map +1 -1
  121. package/dist/server/app-browser-popstate.d.ts +16 -0
  122. package/dist/server/app-browser-popstate.js +17 -0
  123. package/dist/server/app-browser-popstate.js.map +1 -0
  124. package/dist/server/app-browser-rsc-redirect.d.ts +28 -0
  125. package/dist/server/app-browser-rsc-redirect.js +37 -0
  126. package/dist/server/app-browser-rsc-redirect.js.map +1 -0
  127. package/dist/server/app-browser-state.d.ts +27 -23
  128. package/dist/server/app-browser-state.js +158 -54
  129. package/dist/server/app-browser-state.js.map +1 -1
  130. package/dist/server/app-browser-stream.d.ts +9 -4
  131. package/dist/server/app-browser-stream.js +29 -8
  132. package/dist/server/app-browser-stream.js.map +1 -1
  133. package/dist/server/app-browser-visible-commit.d.ts +11 -1
  134. package/dist/server/app-browser-visible-commit.js +69 -21
  135. package/dist/server/app-browser-visible-commit.js.map +1 -1
  136. package/dist/server/app-client-reference-preloader.js.map +1 -1
  137. package/dist/server/app-elements-wire.d.ts +43 -6
  138. package/dist/server/app-elements-wire.js +121 -5
  139. package/dist/server/app-elements-wire.js.map +1 -1
  140. package/dist/server/app-elements.d.ts +2 -2
  141. package/dist/server/app-elements.js +2 -2
  142. package/dist/server/app-elements.js.map +1 -1
  143. package/dist/server/app-fallback-renderer.d.ts +10 -1
  144. package/dist/server/app-fallback-renderer.js +37 -1
  145. package/dist/server/app-fallback-renderer.js.map +1 -1
  146. package/dist/server/app-history-state.d.ts +26 -0
  147. package/dist/server/app-history-state.js +53 -0
  148. package/dist/server/app-history-state.js.map +1 -0
  149. package/dist/server/app-hook-warning-suppression.js.map +1 -1
  150. package/dist/server/app-middleware.d.ts +1 -1
  151. package/dist/server/app-middleware.js +4 -9
  152. package/dist/server/app-middleware.js.map +1 -1
  153. package/dist/server/app-mounted-slots-header.js.map +1 -1
  154. package/dist/server/app-page-boundary-render.d.ts +11 -1
  155. package/dist/server/app-page-boundary-render.js +27 -19
  156. package/dist/server/app-page-boundary-render.js.map +1 -1
  157. package/dist/server/app-page-boundary.d.ts +1 -0
  158. package/dist/server/app-page-boundary.js +10 -7
  159. package/dist/server/app-page-boundary.js.map +1 -1
  160. package/dist/server/app-page-cache.d.ts +23 -3
  161. package/dist/server/app-page-cache.js +63 -27
  162. package/dist/server/app-page-cache.js.map +1 -1
  163. package/dist/server/app-page-dispatch.d.ts +11 -1
  164. package/dist/server/app-page-dispatch.js +85 -14
  165. package/dist/server/app-page-dispatch.js.map +1 -1
  166. package/dist/server/app-page-element-builder.d.ts +10 -1
  167. package/dist/server/app-page-element-builder.js +38 -6
  168. package/dist/server/app-page-element-builder.js.map +1 -1
  169. package/dist/server/app-page-execution.js +2 -3
  170. package/dist/server/app-page-execution.js.map +1 -1
  171. package/dist/server/app-page-head.d.ts +7 -0
  172. package/dist/server/app-page-head.js +6 -1
  173. package/dist/server/app-page-head.js.map +1 -1
  174. package/dist/server/app-page-method.js.map +1 -1
  175. package/dist/server/app-page-params.js.map +1 -1
  176. package/dist/server/app-page-probe.d.ts +23 -1
  177. package/dist/server/app-page-probe.js +29 -1
  178. package/dist/server/app-page-probe.js.map +1 -1
  179. package/dist/server/app-page-render-observation.d.ts +35 -0
  180. package/dist/server/app-page-render-observation.js +68 -0
  181. package/dist/server/app-page-render-observation.js.map +1 -0
  182. package/dist/server/app-page-render.d.ts +12 -2
  183. package/dist/server/app-page-render.js +90 -7
  184. package/dist/server/app-page-render.js.map +1 -1
  185. package/dist/server/app-page-request.d.ts +1 -0
  186. package/dist/server/app-page-request.js +2 -1
  187. package/dist/server/app-page-request.js.map +1 -1
  188. package/dist/server/app-page-response.d.ts +2 -0
  189. package/dist/server/app-page-response.js +18 -7
  190. package/dist/server/app-page-response.js.map +1 -1
  191. package/dist/server/app-page-route-wiring.d.ts +9 -3
  192. package/dist/server/app-page-route-wiring.js +91 -62
  193. package/dist/server/app-page-route-wiring.js.map +1 -1
  194. package/dist/server/app-page-segment-state.d.ts +10 -0
  195. package/dist/server/app-page-segment-state.js +87 -0
  196. package/dist/server/app-page-segment-state.js.map +1 -0
  197. package/dist/server/app-page-stream.d.ts +9 -2
  198. package/dist/server/app-page-stream.js +4 -1
  199. package/dist/server/app-page-stream.js.map +1 -1
  200. package/dist/server/app-post-middleware-context.js.map +1 -1
  201. package/dist/server/app-prerender-endpoints.js.map +1 -1
  202. package/dist/server/app-prerender-static-params.js.map +1 -1
  203. package/dist/server/app-render-dependency.js.map +1 -1
  204. package/dist/server/app-request-context.js.map +1 -1
  205. package/dist/server/app-route-handler-cache.js.map +1 -1
  206. package/dist/server/app-route-handler-dispatch.js +3 -1
  207. package/dist/server/app-route-handler-dispatch.js.map +1 -1
  208. package/dist/server/app-route-handler-execution.js.map +1 -1
  209. package/dist/server/app-route-handler-policy.js +1 -0
  210. package/dist/server/app-route-handler-policy.js.map +1 -1
  211. package/dist/server/app-route-handler-response.js +4 -3
  212. package/dist/server/app-route-handler-response.js.map +1 -1
  213. package/dist/server/app-route-handler-runtime.js.map +1 -1
  214. package/dist/server/app-router-entry.js +7 -15
  215. package/dist/server/app-router-entry.js.map +1 -1
  216. package/dist/server/app-rsc-cache-busting.d.ts +23 -2
  217. package/dist/server/app-rsc-cache-busting.js +75 -19
  218. package/dist/server/app-rsc-cache-busting.js.map +1 -1
  219. package/dist/server/app-rsc-embedded-chunks.d.ts +9 -0
  220. package/dist/server/app-rsc-embedded-chunks.js +34 -0
  221. package/dist/server/app-rsc-embedded-chunks.js.map +1 -0
  222. package/dist/server/app-rsc-error-handler.js.map +1 -1
  223. package/dist/server/app-rsc-errors.d.ts +4 -1
  224. package/dist/server/app-rsc-errors.js +1 -1
  225. package/dist/server/app-rsc-errors.js.map +1 -1
  226. package/dist/server/app-rsc-handler.d.ts +18 -1
  227. package/dist/server/app-rsc-handler.js +55 -16
  228. package/dist/server/app-rsc-handler.js.map +1 -1
  229. package/dist/server/app-rsc-render-mode.d.ts +11 -0
  230. package/dist/server/app-rsc-render-mode.js +21 -0
  231. package/dist/server/app-rsc-render-mode.js.map +1 -0
  232. package/dist/server/app-rsc-request-normalization.d.ts +4 -1
  233. package/dist/server/app-rsc-request-normalization.js +7 -2
  234. package/dist/server/app-rsc-request-normalization.js.map +1 -1
  235. package/dist/server/app-rsc-response-finalizer.d.ts +2 -1
  236. package/dist/server/app-rsc-response-finalizer.js +6 -1
  237. package/dist/server/app-rsc-response-finalizer.js.map +1 -1
  238. package/dist/server/app-rsc-route-matching.d.ts +23 -0
  239. package/dist/server/app-rsc-route-matching.js +45 -23
  240. package/dist/server/app-rsc-route-matching.js.map +1 -1
  241. package/dist/server/app-segment-config.js.map +1 -1
  242. package/dist/server/app-server-action-execution.d.ts +51 -5
  243. package/dist/server/app-server-action-execution.js +161 -51
  244. package/dist/server/app-server-action-execution.js.map +1 -1
  245. package/dist/server/app-ssr-entry.d.ts +7 -0
  246. package/dist/server/app-ssr-entry.js +44 -14
  247. package/dist/server/app-ssr-entry.js.map +1 -1
  248. package/dist/server/app-ssr-error-meta.d.ts +14 -0
  249. package/dist/server/app-ssr-error-meta.js +50 -0
  250. package/dist/server/app-ssr-error-meta.js.map +1 -0
  251. package/dist/server/app-ssr-stream.d.ts +1 -1
  252. package/dist/server/app-ssr-stream.js +9 -12
  253. package/dist/server/app-ssr-stream.js.map +1 -1
  254. package/dist/server/app-static-generation.js.map +1 -1
  255. package/dist/server/artifact-compatibility.d.ts +12 -2
  256. package/dist/server/artifact-compatibility.js +12 -8
  257. package/dist/server/artifact-compatibility.js.map +1 -1
  258. package/dist/server/cache-control.js +1 -0
  259. package/dist/server/cache-control.js.map +1 -1
  260. package/dist/server/cache-proof.d.ts +124 -5
  261. package/dist/server/cache-proof.js +416 -18
  262. package/dist/server/cache-proof.js.map +1 -1
  263. package/dist/server/csp.js.map +1 -1
  264. package/dist/server/dev-error-overlay-store.js.map +1 -1
  265. package/dist/server/dev-error-overlay.js +5 -0
  266. package/dist/server/dev-error-overlay.js.map +1 -1
  267. package/dist/server/dev-lockfile.d.ts +110 -0
  268. package/dist/server/dev-lockfile.js +180 -0
  269. package/dist/server/dev-lockfile.js.map +1 -0
  270. package/dist/server/dev-module-runner.js.map +1 -1
  271. package/dist/server/dev-origin-check.js.map +1 -1
  272. package/dist/server/dev-route-files.js.map +1 -1
  273. package/dist/server/dev-server.js +23 -10
  274. package/dist/server/dev-server.js.map +1 -1
  275. package/dist/server/file-based-metadata.d.ts +13 -0
  276. package/dist/server/file-based-metadata.js +49 -2
  277. package/dist/server/file-based-metadata.js.map +1 -1
  278. package/dist/server/headers.d.ts +81 -0
  279. package/dist/server/headers.js +104 -0
  280. package/dist/server/headers.js.map +1 -0
  281. package/dist/server/html.js +1 -1
  282. package/dist/server/html.js.map +1 -1
  283. package/dist/server/http-error-responses.d.ts +10 -0
  284. package/dist/server/http-error-responses.js +11 -1
  285. package/dist/server/http-error-responses.js.map +1 -1
  286. package/dist/server/image-optimization.d.ts +11 -1
  287. package/dist/server/image-optimization.js.map +1 -1
  288. package/dist/server/implicit-tags.js +2 -1
  289. package/dist/server/implicit-tags.js.map +1 -1
  290. package/dist/server/instrumentation-runtime.js.map +1 -1
  291. package/dist/server/instrumentation.js.map +1 -1
  292. package/dist/server/isr-cache.d.ts +12 -2
  293. package/dist/server/isr-cache.js +16 -5
  294. package/dist/server/isr-cache.js.map +1 -1
  295. package/dist/server/metadata-route-build-data.js.map +1 -1
  296. package/dist/server/metadata-route-response.js +22 -5
  297. package/dist/server/metadata-route-response.js.map +1 -1
  298. package/dist/server/metadata-routes.js +27 -8
  299. package/dist/server/metadata-routes.js.map +1 -1
  300. package/dist/server/middleware-matcher.js.map +1 -1
  301. package/dist/server/middleware-request-headers.d.ts +4 -1
  302. package/dist/server/middleware-request-headers.js +15 -8
  303. package/dist/server/middleware-request-headers.js.map +1 -1
  304. package/dist/server/middleware-response-headers.d.ts +2 -1
  305. package/dist/server/middleware-response-headers.js +1 -1
  306. package/dist/server/middleware-response-headers.js.map +1 -1
  307. package/dist/server/middleware-runtime.d.ts +1 -0
  308. package/dist/server/middleware-runtime.js +7 -3
  309. package/dist/server/middleware-runtime.js.map +1 -1
  310. package/dist/server/middleware.d.ts +12 -0
  311. package/dist/server/middleware.js +12 -0
  312. package/dist/server/middleware.js.map +1 -1
  313. package/dist/server/navigation-planner.d.ts +133 -0
  314. package/dist/server/navigation-planner.js +432 -0
  315. package/dist/server/navigation-planner.js.map +1 -0
  316. package/dist/server/navigation-trace.d.ts +19 -2
  317. package/dist/server/navigation-trace.js +20 -1
  318. package/dist/server/navigation-trace.js.map +1 -1
  319. package/dist/server/next-error-digest.d.ts +3 -2
  320. package/dist/server/next-error-digest.js +4 -2
  321. package/dist/server/next-error-digest.js.map +1 -1
  322. package/dist/server/normalize-path.d.ts +2 -1
  323. package/dist/server/normalize-path.js +4 -1
  324. package/dist/server/normalize-path.js.map +1 -1
  325. package/dist/server/pages-api-route.js +1 -0
  326. package/dist/server/pages-api-route.js.map +1 -1
  327. package/dist/server/pages-i18n.js.map +1 -1
  328. package/dist/server/pages-media-type.js.map +1 -1
  329. package/dist/server/pages-node-compat.js.map +1 -1
  330. package/dist/server/pages-page-data.d.ts +3 -2
  331. package/dist/server/pages-page-data.js +27 -5
  332. package/dist/server/pages-page-data.js.map +1 -1
  333. package/dist/server/pages-page-response.js +2 -1
  334. package/dist/server/pages-page-response.js.map +1 -1
  335. package/dist/server/prerender-work-unit-setup.js +1 -1
  336. package/dist/server/prerender-work-unit-setup.js.map +1 -1
  337. package/dist/server/prod-server.d.ts +28 -1
  338. package/dist/server/prod-server.js +97 -22
  339. package/dist/server/prod-server.js.map +1 -1
  340. package/dist/server/request-log.js.map +1 -1
  341. package/dist/server/request-pipeline.d.ts +1 -13
  342. package/dist/server/request-pipeline.js +3 -25
  343. package/dist/server/request-pipeline.js.map +1 -1
  344. package/dist/server/rsc-stream-hints.js.map +1 -1
  345. package/dist/server/seed-cache.js.map +1 -1
  346. package/dist/server/server-action-not-found.d.ts +16 -3
  347. package/dist/server/server-action-not-found.js +22 -4
  348. package/dist/server/server-action-not-found.js.map +1 -1
  349. package/dist/server/server-globals.d.ts +5 -0
  350. package/dist/server/server-globals.js +37 -0
  351. package/dist/server/server-globals.js.map +1 -0
  352. package/dist/server/socket-error-backstop.js.map +1 -1
  353. package/dist/server/static-file-cache.js +1 -1
  354. package/dist/server/static-file-cache.js.map +1 -1
  355. package/dist/server/worker-utils.d.ts +0 -7
  356. package/dist/server/worker-utils.js +3 -2
  357. package/dist/server/worker-utils.js.map +1 -1
  358. package/dist/shims/amp.js.map +1 -1
  359. package/dist/shims/app.d.ts +37 -4
  360. package/dist/shims/app.js +50 -1
  361. package/dist/shims/app.js.map +1 -0
  362. package/dist/shims/cache-for-request.js.map +1 -1
  363. package/dist/shims/cache-runtime.d.ts +19 -2
  364. package/dist/shims/cache-runtime.js +87 -19
  365. package/dist/shims/cache-runtime.js.map +1 -1
  366. package/dist/shims/cache.d.ts +20 -21
  367. package/dist/shims/cache.js +101 -15
  368. package/dist/shims/cache.js.map +1 -1
  369. package/dist/shims/client-hook-error.js.map +1 -1
  370. package/dist/shims/compat-router.js.map +1 -1
  371. package/dist/shims/config.js.map +1 -1
  372. package/dist/shims/constants.js.map +1 -1
  373. package/dist/shims/document.js.map +1 -1
  374. package/dist/shims/dynamic.d.ts +18 -10
  375. package/dist/shims/dynamic.js +107 -51
  376. package/dist/shims/dynamic.js.map +1 -1
  377. package/dist/shims/error-boundary.d.ts +35 -6
  378. package/dist/shims/error-boundary.js +116 -33
  379. package/dist/shims/error-boundary.js.map +1 -1
  380. package/dist/shims/error.d.ts +18 -1
  381. package/dist/shims/error.js +56 -1
  382. package/dist/shims/error.js.map +1 -1
  383. package/dist/shims/fetch-cache.d.ts +25 -1
  384. package/dist/shims/fetch-cache.js +159 -13
  385. package/dist/shims/fetch-cache.js.map +1 -1
  386. package/dist/shims/font-google-base.d.ts +22 -8
  387. package/dist/shims/font-google-base.js +41 -71
  388. package/dist/shims/font-google-base.js.map +1 -1
  389. package/dist/shims/font-local.d.ts +3 -20
  390. package/dist/shims/font-local.js +23 -75
  391. package/dist/shims/font-local.js.map +1 -1
  392. package/dist/shims/font-utils.d.ts +51 -0
  393. package/dist/shims/font-utils.js +97 -0
  394. package/dist/shims/font-utils.js.map +1 -0
  395. package/dist/shims/form.js +3 -1
  396. package/dist/shims/form.js.map +1 -1
  397. package/dist/shims/hash-scroll.d.ts +7 -0
  398. package/dist/shims/hash-scroll.js +30 -0
  399. package/dist/shims/hash-scroll.js.map +1 -0
  400. package/dist/shims/head-state.js.map +1 -1
  401. package/dist/shims/head.d.ts +3 -1
  402. package/dist/shims/head.js +28 -16
  403. package/dist/shims/head.js.map +1 -1
  404. package/dist/shims/headers.d.ts +11 -12
  405. package/dist/shims/headers.js +45 -8
  406. package/dist/shims/headers.js.map +1 -1
  407. package/dist/shims/i18n-context.js.map +1 -1
  408. package/dist/shims/i18n-state.js.map +1 -1
  409. package/dist/shims/image-config.d.ts +14 -1
  410. package/dist/shims/image-config.js +24 -1
  411. package/dist/shims/image-config.js.map +1 -1
  412. package/dist/shims/image.d.ts +1 -0
  413. package/dist/shims/image.js +159 -80
  414. package/dist/shims/image.js.map +1 -1
  415. package/dist/shims/internal/als-registry.js.map +1 -1
  416. package/dist/shims/internal/app-router-context.d.ts +7 -6
  417. package/dist/shims/internal/app-router-context.js +17 -6
  418. package/dist/shims/internal/app-router-context.js.map +1 -1
  419. package/dist/shims/internal/cookie-serialize.js.map +1 -1
  420. package/dist/shims/internal/make-hanging-promise.d.ts +1 -1
  421. package/dist/shims/internal/make-hanging-promise.js +1 -1
  422. package/dist/shims/internal/make-hanging-promise.js.map +1 -1
  423. package/dist/shims/internal/parse-cookie-header.js.map +1 -1
  424. package/dist/shims/internal/utils.js.map +1 -1
  425. package/dist/shims/internal/work-unit-async-storage.js +2 -2
  426. package/dist/shims/internal/work-unit-async-storage.js.map +1 -1
  427. package/dist/shims/layout-segment-context.js.map +1 -1
  428. package/dist/shims/legacy-image.js.map +1 -1
  429. package/dist/shims/link-prefetch.d.ts +42 -0
  430. package/dist/shims/link-prefetch.js +45 -0
  431. package/dist/shims/link-prefetch.js.map +1 -0
  432. package/dist/shims/link.d.ts +37 -4
  433. package/dist/shims/link.js +156 -46
  434. package/dist/shims/link.js.map +1 -1
  435. package/dist/shims/metadata.d.ts +16 -30
  436. package/dist/shims/metadata.js +87 -28
  437. package/dist/shims/metadata.js.map +1 -1
  438. package/dist/shims/navigation-state.js.map +1 -1
  439. package/dist/shims/navigation.d.ts +172 -10
  440. package/dist/shims/navigation.js +335 -70
  441. package/dist/shims/navigation.js.map +1 -1
  442. package/dist/shims/navigation.react-server.d.ts +3 -2
  443. package/dist/shims/navigation.react-server.js +5 -2
  444. package/dist/shims/navigation.react-server.js.map +1 -1
  445. package/dist/shims/offline.js.map +1 -1
  446. package/dist/shims/pages-router-runtime.d.ts +7 -0
  447. package/dist/shims/pages-router-runtime.js +16 -0
  448. package/dist/shims/pages-router-runtime.js.map +1 -0
  449. package/dist/shims/readonly-url-search-params.js.map +1 -1
  450. package/dist/shims/request-context.js.map +1 -1
  451. package/dist/shims/root-params.js.map +1 -1
  452. package/dist/shims/router-state.js.map +1 -1
  453. package/dist/shims/router.d.ts +69 -7
  454. package/dist/shims/router.js +232 -249
  455. package/dist/shims/router.js.map +1 -1
  456. package/dist/shims/script-nonce-context.js.map +1 -1
  457. package/dist/shims/script.js +110 -32
  458. package/dist/shims/script.js.map +1 -1
  459. package/dist/shims/server.js +12 -15
  460. package/dist/shims/server.js.map +1 -1
  461. package/dist/shims/slot.d.ts +7 -1
  462. package/dist/shims/slot.js +60 -7
  463. package/dist/shims/slot.js.map +1 -1
  464. package/dist/shims/thenable-params.js.map +1 -1
  465. package/dist/shims/unified-request-context.js +5 -0
  466. package/dist/shims/unified-request-context.js.map +1 -1
  467. package/dist/shims/unrecognized-action-error.d.ts +35 -0
  468. package/dist/shims/unrecognized-action-error.js +41 -0
  469. package/dist/shims/unrecognized-action-error.js.map +1 -0
  470. package/dist/shims/url-safety.js.map +1 -1
  471. package/dist/shims/url-utils.d.ts +22 -1
  472. package/dist/shims/url-utils.js +76 -3
  473. package/dist/shims/url-utils.js.map +1 -1
  474. package/dist/shims/use-merged-ref.js.map +1 -1
  475. package/dist/shims/web-vitals.d.ts +4 -21
  476. package/dist/shims/web-vitals.js +19 -6
  477. package/dist/shims/web-vitals.js.map +1 -1
  478. package/dist/utils/asset-prefix.d.ts +69 -0
  479. package/dist/utils/asset-prefix.js +91 -0
  480. package/dist/utils/asset-prefix.js.map +1 -0
  481. package/dist/utils/base-path.d.ts +7 -1
  482. package/dist/utils/base-path.js +10 -1
  483. package/dist/utils/base-path.js.map +1 -1
  484. package/dist/utils/cache-control-metadata.js.map +1 -1
  485. package/dist/utils/domain-locale.js.map +1 -1
  486. package/dist/utils/encode-cache-tag.d.ts +31 -0
  487. package/dist/utils/encode-cache-tag.js +38 -0
  488. package/dist/utils/encode-cache-tag.js.map +1 -0
  489. package/dist/utils/error-cause.js.map +1 -1
  490. package/dist/utils/hash.js.map +1 -1
  491. package/dist/utils/lazy-chunks.js.map +1 -1
  492. package/dist/utils/manifest-paths.js.map +1 -1
  493. package/dist/utils/mdx-scan.js.map +1 -1
  494. package/dist/utils/navigation-signal.d.ts +5 -0
  495. package/dist/utils/navigation-signal.js +14 -0
  496. package/dist/utils/navigation-signal.js.map +1 -0
  497. package/dist/utils/project.js.map +1 -1
  498. package/dist/utils/public-routes.js.map +1 -1
  499. package/dist/utils/query.js.map +1 -1
  500. package/dist/utils/safe-json-file.js.map +1 -1
  501. package/dist/utils/sorted-array.d.ts +9 -0
  502. package/dist/utils/sorted-array.js +22 -0
  503. package/dist/utils/sorted-array.js.map +1 -0
  504. package/dist/utils/text-stream.js.map +1 -1
  505. package/dist/utils/vinext-root.js.map +1 -1
  506. package/package.json +8 -6
@@ -6,6 +6,14 @@ import { hasBasePath, stripBasePath } from "../utils/base-path.js";
6
6
  * Used by link.tsx, navigation.ts, and router.ts to normalize
7
7
  * same-origin absolute URLs to local paths for client-side navigation.
8
8
  */
9
+ const ABSOLUTE_URL_REGEX = /^[a-zA-Z][a-zA-Z\d+\-.]*?:/;
10
+ function isAbsoluteUrl(url) {
11
+ const firstChar = url.charCodeAt(0);
12
+ return (firstChar >= 65 && firstChar <= 90 || firstChar >= 97 && firstChar <= 122) && ABSOLUTE_URL_REGEX.test(url);
13
+ }
14
+ function isAbsoluteOrProtocolRelativeUrl(url) {
15
+ return isAbsoluteUrl(url) || url.startsWith("//");
16
+ }
9
17
  /**
10
18
  * If `url` is an absolute same-origin URL, return the local path
11
19
  * (pathname + search + hash). Returns null for truly external URLs
@@ -36,10 +44,66 @@ function toSameOriginAppPath(url, basePath) {
36
44
  }
37
45
  }
38
46
  /**
47
+ * Split a path string into pathname, query, and hash without depending on
48
+ * the URL constructor (which would resolve relative paths against an origin).
49
+ *
50
+ * Ported from Next.js: packages/next/src/shared/lib/router/utils/parse-path.ts
51
+ */
52
+ function parsePath(path) {
53
+ const hashIndex = path.indexOf("#");
54
+ const queryIndex = path.indexOf("?");
55
+ const hasQuery = queryIndex > -1 && (hashIndex < 0 || queryIndex < hashIndex);
56
+ if (hasQuery || hashIndex > -1) return {
57
+ pathname: path.substring(0, hasQuery ? queryIndex : hashIndex),
58
+ query: hasQuery ? path.substring(queryIndex, hashIndex > -1 ? hashIndex : void 0) : "",
59
+ hash: hashIndex > -1 ? path.slice(hashIndex) : ""
60
+ };
61
+ return {
62
+ pathname: path,
63
+ query: "",
64
+ hash: ""
65
+ };
66
+ }
67
+ /**
68
+ * Drop trailing slashes from a route while preserving the bare root.
69
+ *
70
+ * Ported from Next.js: packages/next/src/shared/lib/router/utils/remove-trailing-slash.ts
71
+ */
72
+ function removeRouteTrailingSlash(route) {
73
+ return route.replace(/\/$/, "") || "/";
74
+ }
75
+ /**
76
+ * Normalise the trailing slash of a local URL according to the
77
+ * `trailingSlash` config option in `next.config.js`. Used by the `<Link>`
78
+ * shim so that rendered `href` attributes match the canonical URL form
79
+ * (which is what the server-side redirect would otherwise enforce).
80
+ *
81
+ * Behaviour matches Next.js's client-side `normalizePathTrailingSlash`:
82
+ * packages/next/src/client/normalize-trailing-slash.ts
83
+ *
84
+ * - Absolute URLs (`http://`, `https://`, `//`) and non-local strings are
85
+ * returned unchanged.
86
+ * - Paths whose final segment looks like a filename (`...\.ext`) have any
87
+ * trailing slash stripped even when `trailingSlash: true`, mirroring the
88
+ * `.well-known`-aware redirect rule shipped in `routes-manifest.json`.
89
+ * - Query strings and hash fragments are preserved verbatim.
90
+ * - Idempotent: already-canonical paths round-trip unchanged.
91
+ */
92
+ function normalizePathTrailingSlash(path, trailingSlash) {
93
+ if (!path.startsWith("/") || path.startsWith("//")) return path;
94
+ const { pathname, query, hash } = parsePath(path);
95
+ if (trailingSlash) {
96
+ if (/\.[^/]+\/?$/.test(pathname)) return `${removeRouteTrailingSlash(pathname)}${query}${hash}`;
97
+ if (pathname.endsWith("/")) return `${pathname}${query}${hash}`;
98
+ return `${pathname}/${query}${hash}`;
99
+ }
100
+ return `${removeRouteTrailingSlash(pathname)}${query}${hash}`;
101
+ }
102
+ /**
39
103
  * Prepend basePath to a local path for browser URLs / fetches.
40
104
  */
41
105
  function withBasePath(path, basePath) {
42
- if (!basePath || !path.startsWith("/") || path.startsWith("http://") || path.startsWith("https://") || path.startsWith("//")) return path;
106
+ if (!basePath || !path.startsWith("/") || isAbsoluteOrProtocolRelativeUrl(path)) return path;
43
107
  return basePath + path;
44
108
  }
45
109
  /**
@@ -49,7 +113,7 @@ function withBasePath(path, basePath) {
49
113
  function resolveRelativeHref(href, currentUrl, basePath = "") {
50
114
  const base = currentUrl ?? (typeof window !== "undefined" ? window.location.href : void 0);
51
115
  if (!base) return href;
52
- if (href.startsWith("/") || href.startsWith("http://") || href.startsWith("https://") || href.startsWith("//")) return href;
116
+ if (href.startsWith("/") || isAbsoluteOrProtocolRelativeUrl(href)) return href;
53
117
  try {
54
118
  const resolved = new URL(href, base);
55
119
  return (basePath && resolved.pathname === basePath ? "" : basePath ? stripBasePath(resolved.pathname, basePath) : resolved.pathname) + resolved.search + resolved.hash;
@@ -68,7 +132,16 @@ function toBrowserNavigationHref(href, currentUrl, basePath = "") {
68
132
  if (resolved.startsWith("?") || resolved.startsWith("#")) return basePath + resolved;
69
133
  return withBasePath(resolved, basePath);
70
134
  }
135
+ function isHashOnlyBrowserUrlChange(href, currentHref, basePath = "") {
136
+ try {
137
+ const current = new URL(currentHref);
138
+ const next = new URL(href, currentHref);
139
+ return stripBasePath(current.pathname, basePath) === stripBasePath(next.pathname, basePath) && current.search === next.search && next.hash !== "";
140
+ } catch {
141
+ return false;
142
+ }
143
+ }
71
144
  //#endregion
72
- export { resolveRelativeHref, toBrowserNavigationHref, toSameOriginAppPath, toSameOriginPath, withBasePath };
145
+ export { isAbsoluteOrProtocolRelativeUrl, isAbsoluteUrl, isHashOnlyBrowserUrlChange, normalizePathTrailingSlash, resolveRelativeHref, toBrowserNavigationHref, toSameOriginAppPath, toSameOriginPath, withBasePath };
73
146
 
74
147
  //# sourceMappingURL=url-utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"url-utils.js","names":[],"sources":["../../src/shims/url-utils.ts"],"sourcesContent":["/**\n * Shared URL utilities for same-origin detection.\n *\n * Used by link.tsx, navigation.ts, and router.ts to normalize\n * same-origin absolute URLs to local paths for client-side navigation.\n */\nimport { hasBasePath, stripBasePath } from \"../utils/base-path.js\";\n\n/**\n * If `url` is an absolute same-origin URL, return the local path\n * (pathname + search + hash). Returns null for truly external URLs\n * or on the server (where origin is unknown).\n */\nexport function toSameOriginPath(url: string): string | null {\n if (typeof window === \"undefined\") return null;\n try {\n const parsed = url.startsWith(\"//\") ? new URL(url, window.location.origin) : new URL(url);\n if (parsed.origin === window.location.origin) {\n return parsed.pathname + parsed.search + parsed.hash;\n }\n } catch {\n // not a valid absolute URL — ignore\n }\n return null;\n}\n\n/**\n * If `url` is an absolute same-origin URL, return the app-relative path\n * (basePath stripped from the pathname, if configured). Returns null for\n * truly external URLs or on the server.\n */\nexport function toSameOriginAppPath(url: string, basePath: string): string | null {\n const localPath = toSameOriginPath(url);\n if (localPath == null || !basePath) return localPath;\n\n try {\n const parsed = new URL(localPath, \"http://vinext.local\");\n if (!hasBasePath(parsed.pathname, basePath)) {\n return null;\n }\n const pathname = stripBasePath(parsed.pathname, basePath);\n return pathname + parsed.search + parsed.hash;\n } catch {\n return localPath;\n }\n}\n\n/**\n * Prepend basePath to a local path for browser URLs / fetches.\n */\nexport function withBasePath(path: string, basePath: string): string {\n if (\n !basePath ||\n !path.startsWith(\"/\") ||\n path.startsWith(\"http://\") ||\n path.startsWith(\"https://\") ||\n path.startsWith(\"//\")\n ) {\n return path;\n }\n\n return basePath + path;\n}\n\n/**\n * Resolve a potentially relative href against the current URL.\n * Handles: \"#hash\", \"?query\", \"?query#hash\", and relative paths.\n */\nexport function resolveRelativeHref(href: string, currentUrl?: string, basePath = \"\"): string {\n const base = currentUrl ?? (typeof window !== \"undefined\" ? window.location.href : undefined);\n\n if (!base) return href;\n\n if (\n href.startsWith(\"/\") ||\n href.startsWith(\"http://\") ||\n href.startsWith(\"https://\") ||\n href.startsWith(\"//\")\n ) {\n return href;\n }\n\n try {\n const resolved = new URL(href, base);\n const pathname =\n basePath && resolved.pathname === basePath\n ? \"\"\n : basePath\n ? stripBasePath(resolved.pathname, basePath)\n : resolved.pathname;\n return pathname + resolved.search + resolved.hash;\n } catch {\n return href;\n }\n}\n\n/**\n * Convert a local navigation target into the browser URL that should be used\n * for history entries, fetches, and onNavigate callbacks.\n */\nexport function toBrowserNavigationHref(href: string, currentUrl?: string, basePath = \"\"): string {\n const resolved = resolveRelativeHref(href, currentUrl, basePath);\n\n if (!basePath) {\n return withBasePath(resolved, basePath);\n }\n\n if (resolved === \"\") {\n return basePath;\n }\n\n if (resolved.startsWith(\"?\") || resolved.startsWith(\"#\")) {\n return basePath + resolved;\n }\n\n return withBasePath(resolved, basePath);\n}\n"],"mappings":";;;;;;;;;;;;;AAaA,SAAgB,iBAAiB,KAA4B;AAC3D,KAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,KAAI;EACF,MAAM,SAAS,IAAI,WAAW,KAAK,GAAG,IAAI,IAAI,KAAK,OAAO,SAAS,OAAO,GAAG,IAAI,IAAI,IAAI;AACzF,MAAI,OAAO,WAAW,OAAO,SAAS,OACpC,QAAO,OAAO,WAAW,OAAO,SAAS,OAAO;SAE5C;AAGR,QAAO;;;;;;;AAQT,SAAgB,oBAAoB,KAAa,UAAiC;CAChF,MAAM,YAAY,iBAAiB,IAAI;AACvC,KAAI,aAAa,QAAQ,CAAC,SAAU,QAAO;AAE3C,KAAI;EACF,MAAM,SAAS,IAAI,IAAI,WAAW,sBAAsB;AACxD,MAAI,CAAC,YAAY,OAAO,UAAU,SAAS,CACzC,QAAO;AAGT,SADiB,cAAc,OAAO,UAAU,SAAS,GACvC,OAAO,SAAS,OAAO;SACnC;AACN,SAAO;;;;;;AAOX,SAAgB,aAAa,MAAc,UAA0B;AACnE,KACE,CAAC,YACD,CAAC,KAAK,WAAW,IAAI,IACrB,KAAK,WAAW,UAAU,IAC1B,KAAK,WAAW,WAAW,IAC3B,KAAK,WAAW,KAAK,CAErB,QAAO;AAGT,QAAO,WAAW;;;;;;AAOpB,SAAgB,oBAAoB,MAAc,YAAqB,WAAW,IAAY;CAC5F,MAAM,OAAO,eAAe,OAAO,WAAW,cAAc,OAAO,SAAS,OAAO,KAAA;AAEnF,KAAI,CAAC,KAAM,QAAO;AAElB,KACE,KAAK,WAAW,IAAI,IACpB,KAAK,WAAW,UAAU,IAC1B,KAAK,WAAW,WAAW,IAC3B,KAAK,WAAW,KAAK,CAErB,QAAO;AAGT,KAAI;EACF,MAAM,WAAW,IAAI,IAAI,MAAM,KAAK;AAOpC,UALE,YAAY,SAAS,aAAa,WAC9B,KACA,WACE,cAAc,SAAS,UAAU,SAAS,GAC1C,SAAS,YACC,SAAS,SAAS,SAAS;SACvC;AACN,SAAO;;;;;;;AAQX,SAAgB,wBAAwB,MAAc,YAAqB,WAAW,IAAY;CAChG,MAAM,WAAW,oBAAoB,MAAM,YAAY,SAAS;AAEhE,KAAI,CAAC,SACH,QAAO,aAAa,UAAU,SAAS;AAGzC,KAAI,aAAa,GACf,QAAO;AAGT,KAAI,SAAS,WAAW,IAAI,IAAI,SAAS,WAAW,IAAI,CACtD,QAAO,WAAW;AAGpB,QAAO,aAAa,UAAU,SAAS"}
1
+ {"version":3,"file":"url-utils.js","names":[],"sources":["../../src/shims/url-utils.ts"],"sourcesContent":["/**\n * Shared URL utilities for same-origin detection.\n *\n * Used by link.tsx, navigation.ts, and router.ts to normalize\n * same-origin absolute URLs to local paths for client-side navigation.\n */\nimport { hasBasePath, stripBasePath } from \"../utils/base-path.js\";\n\n// Mirrors Next.js's absolute URL classification:\n// packages/next/src/shared/lib/utils.ts\nconst ABSOLUTE_URL_REGEX = /^[a-zA-Z][a-zA-Z\\d+\\-.]*?:/;\n\nexport function isAbsoluteUrl(url: string): boolean {\n const firstChar = url.charCodeAt(0);\n const startsWithLetter =\n (firstChar >= 65 && firstChar <= 90) || (firstChar >= 97 && firstChar <= 122);\n\n return startsWithLetter && ABSOLUTE_URL_REGEX.test(url);\n}\n\nexport function isAbsoluteOrProtocolRelativeUrl(url: string): boolean {\n return isAbsoluteUrl(url) || url.startsWith(\"//\");\n}\n\n/**\n * If `url` is an absolute same-origin URL, return the local path\n * (pathname + search + hash). Returns null for truly external URLs\n * or on the server (where origin is unknown).\n */\nexport function toSameOriginPath(url: string): string | null {\n if (typeof window === \"undefined\") return null;\n try {\n const parsed = url.startsWith(\"//\") ? new URL(url, window.location.origin) : new URL(url);\n if (parsed.origin === window.location.origin) {\n return parsed.pathname + parsed.search + parsed.hash;\n }\n } catch {\n // not a valid absolute URL — ignore\n }\n return null;\n}\n\n/**\n * If `url` is an absolute same-origin URL, return the app-relative path\n * (basePath stripped from the pathname, if configured). Returns null for\n * truly external URLs or on the server.\n */\nexport function toSameOriginAppPath(url: string, basePath: string): string | null {\n const localPath = toSameOriginPath(url);\n if (localPath == null || !basePath) return localPath;\n\n try {\n const parsed = new URL(localPath, \"http://vinext.local\");\n if (!hasBasePath(parsed.pathname, basePath)) {\n return null;\n }\n const pathname = stripBasePath(parsed.pathname, basePath);\n return pathname + parsed.search + parsed.hash;\n } catch {\n return localPath;\n }\n}\n\n/**\n * Split a path string into pathname, query, and hash without depending on\n * the URL constructor (which would resolve relative paths against an origin).\n *\n * Ported from Next.js: packages/next/src/shared/lib/router/utils/parse-path.ts\n */\nfunction parsePath(path: string): { pathname: string; query: string; hash: string } {\n const hashIndex = path.indexOf(\"#\");\n const queryIndex = path.indexOf(\"?\");\n const hasQuery = queryIndex > -1 && (hashIndex < 0 || queryIndex < hashIndex);\n\n if (hasQuery || hashIndex > -1) {\n return {\n pathname: path.substring(0, hasQuery ? queryIndex : hashIndex),\n query: hasQuery ? path.substring(queryIndex, hashIndex > -1 ? hashIndex : undefined) : \"\",\n hash: hashIndex > -1 ? path.slice(hashIndex) : \"\",\n };\n }\n\n return { pathname: path, query: \"\", hash: \"\" };\n}\n\n/**\n * Drop trailing slashes from a route while preserving the bare root.\n *\n * Ported from Next.js: packages/next/src/shared/lib/router/utils/remove-trailing-slash.ts\n */\nfunction removeRouteTrailingSlash(route: string): string {\n return route.replace(/\\/$/, \"\") || \"/\";\n}\n\n/**\n * Normalise the trailing slash of a local URL according to the\n * `trailingSlash` config option in `next.config.js`. Used by the `<Link>`\n * shim so that rendered `href` attributes match the canonical URL form\n * (which is what the server-side redirect would otherwise enforce).\n *\n * Behaviour matches Next.js's client-side `normalizePathTrailingSlash`:\n * packages/next/src/client/normalize-trailing-slash.ts\n *\n * - Absolute URLs (`http://`, `https://`, `//`) and non-local strings are\n * returned unchanged.\n * - Paths whose final segment looks like a filename (`...\\.ext`) have any\n * trailing slash stripped even when `trailingSlash: true`, mirroring the\n * `.well-known`-aware redirect rule shipped in `routes-manifest.json`.\n * - Query strings and hash fragments are preserved verbatim.\n * - Idempotent: already-canonical paths round-trip unchanged.\n */\nexport function normalizePathTrailingSlash(path: string, trailingSlash: boolean): string {\n if (!path.startsWith(\"/\") || path.startsWith(\"//\")) {\n return path;\n }\n\n const { pathname, query, hash } = parsePath(path);\n\n if (trailingSlash) {\n if (/\\.[^/]+\\/?$/.test(pathname)) {\n // Looks like a filename — strip trailing slash even with trailingSlash: true.\n return `${removeRouteTrailingSlash(pathname)}${query}${hash}`;\n }\n if (pathname.endsWith(\"/\")) {\n return `${pathname}${query}${hash}`;\n }\n return `${pathname}/${query}${hash}`;\n }\n\n return `${removeRouteTrailingSlash(pathname)}${query}${hash}`;\n}\n\n/**\n * Prepend basePath to a local path for browser URLs / fetches.\n */\nexport function withBasePath(path: string, basePath: string): string {\n if (!basePath || !path.startsWith(\"/\") || isAbsoluteOrProtocolRelativeUrl(path)) {\n return path;\n }\n\n return basePath + path;\n}\n\n/**\n * Resolve a potentially relative href against the current URL.\n * Handles: \"#hash\", \"?query\", \"?query#hash\", and relative paths.\n */\nexport function resolveRelativeHref(href: string, currentUrl?: string, basePath = \"\"): string {\n const base = currentUrl ?? (typeof window !== \"undefined\" ? window.location.href : undefined);\n\n if (!base) return href;\n\n if (href.startsWith(\"/\") || isAbsoluteOrProtocolRelativeUrl(href)) {\n return href;\n }\n\n try {\n const resolved = new URL(href, base);\n const pathname =\n basePath && resolved.pathname === basePath\n ? \"\"\n : basePath\n ? stripBasePath(resolved.pathname, basePath)\n : resolved.pathname;\n return pathname + resolved.search + resolved.hash;\n } catch {\n return href;\n }\n}\n\n/**\n * Convert a local navigation target into the browser URL that should be used\n * for history entries, fetches, and onNavigate callbacks.\n */\nexport function toBrowserNavigationHref(href: string, currentUrl?: string, basePath = \"\"): string {\n const resolved = resolveRelativeHref(href, currentUrl, basePath);\n\n if (!basePath) {\n return withBasePath(resolved, basePath);\n }\n\n if (resolved === \"\") {\n return basePath;\n }\n\n if (resolved.startsWith(\"?\") || resolved.startsWith(\"#\")) {\n return basePath + resolved;\n }\n\n return withBasePath(resolved, basePath);\n}\n\nexport function isHashOnlyBrowserUrlChange(\n href: string,\n currentHref: string,\n basePath = \"\",\n): boolean {\n try {\n const current = new URL(currentHref);\n const next = new URL(href, currentHref);\n const currentPathname = stripBasePath(current.pathname, basePath);\n const nextPathname = stripBasePath(next.pathname, basePath);\n return currentPathname === nextPathname && current.search === next.search && next.hash !== \"\";\n } catch {\n return false;\n }\n}\n"],"mappings":";;;;;;;;AAUA,MAAM,qBAAqB;AAE3B,SAAgB,cAAc,KAAsB;CAClD,MAAM,YAAY,IAAI,WAAW,EAAE;CAInC,QAFG,aAAa,MAAM,aAAa,MAAQ,aAAa,MAAM,aAAa,QAEhD,mBAAmB,KAAK,IAAI;;AAGzD,SAAgB,gCAAgC,KAAsB;CACpE,OAAO,cAAc,IAAI,IAAI,IAAI,WAAW,KAAK;;;;;;;AAQnD,SAAgB,iBAAiB,KAA4B;CAC3D,IAAI,OAAO,WAAW,aAAa,OAAO;CAC1C,IAAI;EACF,MAAM,SAAS,IAAI,WAAW,KAAK,GAAG,IAAI,IAAI,KAAK,OAAO,SAAS,OAAO,GAAG,IAAI,IAAI,IAAI;EACzF,IAAI,OAAO,WAAW,OAAO,SAAS,QACpC,OAAO,OAAO,WAAW,OAAO,SAAS,OAAO;SAE5C;CAGR,OAAO;;;;;;;AAQT,SAAgB,oBAAoB,KAAa,UAAiC;CAChF,MAAM,YAAY,iBAAiB,IAAI;CACvC,IAAI,aAAa,QAAQ,CAAC,UAAU,OAAO;CAE3C,IAAI;EACF,MAAM,SAAS,IAAI,IAAI,WAAW,sBAAsB;EACxD,IAAI,CAAC,YAAY,OAAO,UAAU,SAAS,EACzC,OAAO;EAGT,OADiB,cAAc,OAAO,UAAU,SACjC,GAAG,OAAO,SAAS,OAAO;SACnC;EACN,OAAO;;;;;;;;;AAUX,SAAS,UAAU,MAAiE;CAClF,MAAM,YAAY,KAAK,QAAQ,IAAI;CACnC,MAAM,aAAa,KAAK,QAAQ,IAAI;CACpC,MAAM,WAAW,aAAa,OAAO,YAAY,KAAK,aAAa;CAEnE,IAAI,YAAY,YAAY,IAC1B,OAAO;EACL,UAAU,KAAK,UAAU,GAAG,WAAW,aAAa,UAAU;EAC9D,OAAO,WAAW,KAAK,UAAU,YAAY,YAAY,KAAK,YAAY,KAAA,EAAU,GAAG;EACvF,MAAM,YAAY,KAAK,KAAK,MAAM,UAAU,GAAG;EAChD;CAGH,OAAO;EAAE,UAAU;EAAM,OAAO;EAAI,MAAM;EAAI;;;;;;;AAQhD,SAAS,yBAAyB,OAAuB;CACvD,OAAO,MAAM,QAAQ,OAAO,GAAG,IAAI;;;;;;;;;;;;;;;;;;;AAoBrC,SAAgB,2BAA2B,MAAc,eAAgC;CACvF,IAAI,CAAC,KAAK,WAAW,IAAI,IAAI,KAAK,WAAW,KAAK,EAChD,OAAO;CAGT,MAAM,EAAE,UAAU,OAAO,SAAS,UAAU,KAAK;CAEjD,IAAI,eAAe;EACjB,IAAI,cAAc,KAAK,SAAS,EAE9B,OAAO,GAAG,yBAAyB,SAAS,GAAG,QAAQ;EAEzD,IAAI,SAAS,SAAS,IAAI,EACxB,OAAO,GAAG,WAAW,QAAQ;EAE/B,OAAO,GAAG,SAAS,GAAG,QAAQ;;CAGhC,OAAO,GAAG,yBAAyB,SAAS,GAAG,QAAQ;;;;;AAMzD,SAAgB,aAAa,MAAc,UAA0B;CACnE,IAAI,CAAC,YAAY,CAAC,KAAK,WAAW,IAAI,IAAI,gCAAgC,KAAK,EAC7E,OAAO;CAGT,OAAO,WAAW;;;;;;AAOpB,SAAgB,oBAAoB,MAAc,YAAqB,WAAW,IAAY;CAC5F,MAAM,OAAO,eAAe,OAAO,WAAW,cAAc,OAAO,SAAS,OAAO,KAAA;CAEnF,IAAI,CAAC,MAAM,OAAO;CAElB,IAAI,KAAK,WAAW,IAAI,IAAI,gCAAgC,KAAK,EAC/D,OAAO;CAGT,IAAI;EACF,MAAM,WAAW,IAAI,IAAI,MAAM,KAAK;EAOpC,QALE,YAAY,SAAS,aAAa,WAC9B,KACA,WACE,cAAc,SAAS,UAAU,SAAS,GAC1C,SAAS,YACC,SAAS,SAAS,SAAS;SACvC;EACN,OAAO;;;;;;;AAQX,SAAgB,wBAAwB,MAAc,YAAqB,WAAW,IAAY;CAChG,MAAM,WAAW,oBAAoB,MAAM,YAAY,SAAS;CAEhE,IAAI,CAAC,UACH,OAAO,aAAa,UAAU,SAAS;CAGzC,IAAI,aAAa,IACf,OAAO;CAGT,IAAI,SAAS,WAAW,IAAI,IAAI,SAAS,WAAW,IAAI,EACtD,OAAO,WAAW;CAGpB,OAAO,aAAa,UAAU,SAAS;;AAGzC,SAAgB,2BACd,MACA,aACA,WAAW,IACF;CACT,IAAI;EACF,MAAM,UAAU,IAAI,IAAI,YAAY;EACpC,MAAM,OAAO,IAAI,IAAI,MAAM,YAAY;EAGvC,OAFwB,cAAc,QAAQ,UAAU,SAElC,KADD,cAAc,KAAK,UAAU,SACX,IAAI,QAAQ,WAAW,KAAK,UAAU,KAAK,SAAS;SACrF;EACN,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"use-merged-ref.js","names":[],"sources":["../../src/shims/use-merged-ref.ts"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useRef, type Ref } from \"react\";\n\n// Ported from Next.js: packages/next/src/client/use-merged-ref.ts\n// This is a compatibility hook to support React 18 and 19 refs.\n// In 19, a cleanup function from refs may be returned.\n// In 18, returning a cleanup function creates a warning.\n// Since we take userspace refs, we don't know ahead of time if a cleanup function will be returned.\n// This implements cleanup functions with the old behavior in 18.\n// We know refs are always called alternating with `null` and then `T`.\n// So a call with `null` means we need to call the previous cleanup functions.\nexport function useMergedRef<TElement>(refA: Ref<TElement>, refB: Ref<TElement>): Ref<TElement> {\n const cleanupA = useRef<(() => void) | null>(null);\n const cleanupB = useRef<(() => void) | null>(null);\n\n return useCallback(\n (current: TElement | null): void => {\n if (current === null) {\n const cleanupFnA = cleanupA.current;\n if (cleanupFnA) {\n cleanupA.current = null;\n cleanupFnA();\n }\n const cleanupFnB = cleanupB.current;\n if (cleanupFnB) {\n cleanupB.current = null;\n cleanupFnB();\n }\n } else {\n if (refA) {\n cleanupA.current = applyRef(refA, current);\n }\n if (refB) {\n cleanupB.current = applyRef(refB, current);\n }\n }\n },\n [refA, refB],\n );\n}\n\nfunction applyRef<TElement>(refA: NonNullable<Ref<TElement>>, current: TElement) {\n if (typeof refA === \"function\") {\n const cleanup = refA(current);\n if (typeof cleanup === \"function\") {\n return cleanup;\n } else {\n return () => refA(null);\n }\n } else {\n refA.current = current;\n return () => {\n refA.current = null;\n };\n }\n}\n"],"mappings":";;;AAYA,SAAgB,aAAuB,MAAqB,MAAoC;CAC9F,MAAM,WAAW,OAA4B,KAAK;CAClD,MAAM,WAAW,OAA4B,KAAK;AAElD,QAAO,aACJ,YAAmC;AAClC,MAAI,YAAY,MAAM;GACpB,MAAM,aAAa,SAAS;AAC5B,OAAI,YAAY;AACd,aAAS,UAAU;AACnB,gBAAY;;GAEd,MAAM,aAAa,SAAS;AAC5B,OAAI,YAAY;AACd,aAAS,UAAU;AACnB,gBAAY;;SAET;AACL,OAAI,KACF,UAAS,UAAU,SAAS,MAAM,QAAQ;AAE5C,OAAI,KACF,UAAS,UAAU,SAAS,MAAM,QAAQ;;IAIhD,CAAC,MAAM,KAAK,CACb;;AAGH,SAAS,SAAmB,MAAkC,SAAmB;AAC/E,KAAI,OAAO,SAAS,YAAY;EAC9B,MAAM,UAAU,KAAK,QAAQ;AAC7B,MAAI,OAAO,YAAY,WACrB,QAAO;MAEP,cAAa,KAAK,KAAK;QAEpB;AACL,OAAK,UAAU;AACf,eAAa;AACX,QAAK,UAAU"}
1
+ {"version":3,"file":"use-merged-ref.js","names":[],"sources":["../../src/shims/use-merged-ref.ts"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useRef, type Ref } from \"react\";\n\n// Ported from Next.js: packages/next/src/client/use-merged-ref.ts\n// This is a compatibility hook to support React 18 and 19 refs.\n// In 19, a cleanup function from refs may be returned.\n// In 18, returning a cleanup function creates a warning.\n// Since we take userspace refs, we don't know ahead of time if a cleanup function will be returned.\n// This implements cleanup functions with the old behavior in 18.\n// We know refs are always called alternating with `null` and then `T`.\n// So a call with `null` means we need to call the previous cleanup functions.\nexport function useMergedRef<TElement>(refA: Ref<TElement>, refB: Ref<TElement>): Ref<TElement> {\n const cleanupA = useRef<(() => void) | null>(null);\n const cleanupB = useRef<(() => void) | null>(null);\n\n return useCallback(\n (current: TElement | null): void => {\n if (current === null) {\n const cleanupFnA = cleanupA.current;\n if (cleanupFnA) {\n cleanupA.current = null;\n cleanupFnA();\n }\n const cleanupFnB = cleanupB.current;\n if (cleanupFnB) {\n cleanupB.current = null;\n cleanupFnB();\n }\n } else {\n if (refA) {\n cleanupA.current = applyRef(refA, current);\n }\n if (refB) {\n cleanupB.current = applyRef(refB, current);\n }\n }\n },\n [refA, refB],\n );\n}\n\nfunction applyRef<TElement>(refA: NonNullable<Ref<TElement>>, current: TElement) {\n if (typeof refA === \"function\") {\n const cleanup = refA(current);\n if (typeof cleanup === \"function\") {\n return cleanup;\n } else {\n return () => refA(null);\n }\n } else {\n refA.current = current;\n return () => {\n refA.current = null;\n };\n }\n}\n"],"mappings":";;;AAYA,SAAgB,aAAuB,MAAqB,MAAoC;CAC9F,MAAM,WAAW,OAA4B,KAAK;CAClD,MAAM,WAAW,OAA4B,KAAK;CAElD,OAAO,aACJ,YAAmC;EAClC,IAAI,YAAY,MAAM;GACpB,MAAM,aAAa,SAAS;GAC5B,IAAI,YAAY;IACd,SAAS,UAAU;IACnB,YAAY;;GAEd,MAAM,aAAa,SAAS;GAC5B,IAAI,YAAY;IACd,SAAS,UAAU;IACnB,YAAY;;SAET;GACL,IAAI,MACF,SAAS,UAAU,SAAS,MAAM,QAAQ;GAE5C,IAAI,MACF,SAAS,UAAU,SAAS,MAAM,QAAQ;;IAIhD,CAAC,MAAM,KAAK,CACb;;AAGH,SAAS,SAAmB,MAAkC,SAAmB;CAC/E,IAAI,OAAO,SAAS,YAAY;EAC9B,MAAM,UAAU,KAAK,QAAQ;EAC7B,IAAI,OAAO,YAAY,YACrB,OAAO;OAEP,aAAa,KAAK,KAAK;QAEpB;EACL,KAAK,UAAU;EACf,aAAa;GACX,KAAK,UAAU"}
@@ -1,26 +1,9 @@
1
+ import { MetricType } from "web-vitals";
2
+
1
3
  //#region src/shims/web-vitals.d.ts
2
- /**
3
- * next/web-vitals shim
4
- *
5
- * Provides useReportWebVitals() — a no-op hook for compatibility.
6
- * In real Next.js, this sends Core Web Vitals to an analytics endpoint.
7
- * Apps can use the web-vitals library directly instead.
8
- */
9
- type WebVitalsMetric = {
10
- id: string;
11
- name: string;
12
- value: number;
13
- rating?: "good" | "needs-improvement" | "poor";
14
- delta: number;
15
- navigationType?: "navigate" | "reload" | "back-forward" | "prerender";
16
- };
4
+ type WebVitalsMetric = MetricType;
17
5
  type ReportWebVitalsCallback = (metric: WebVitalsMetric) => void;
18
- /**
19
- * Register a callback to receive Core Web Vitals metrics.
20
- * No-op in our implementation — use the `web-vitals` library directly
21
- * for production metrics collection.
22
- */
23
- declare function useReportWebVitals(_callback: ReportWebVitalsCallback): void;
6
+ declare function useReportWebVitals(callback: ReportWebVitalsCallback): void;
24
7
  //#endregion
25
8
  export { type ReportWebVitalsCallback, type WebVitalsMetric, useReportWebVitals };
26
9
  //# sourceMappingURL=web-vitals.d.ts.map
@@ -1,10 +1,23 @@
1
+ import { useEffect, useRef } from "react";
2
+ import { onCLS, onFCP, onFID, onINP, onLCP, onTTFB } from "web-vitals";
1
3
  //#region src/shims/web-vitals.ts
2
- /**
3
- * Register a callback to receive Core Web Vitals metrics.
4
- * No-op in our implementation — use the `web-vitals` library directly
5
- * for production metrics collection.
6
- */
7
- function useReportWebVitals(_callback) {}
4
+ function useReportWebVitals(callback) {
5
+ const callbackRef = useRef(callback);
6
+ useEffect(() => {
7
+ callbackRef.current = callback;
8
+ }, [callback]);
9
+ useEffect(() => {
10
+ const reportWebVitals = (metric) => {
11
+ callbackRef.current(metric);
12
+ };
13
+ onCLS(reportWebVitals);
14
+ onFID(reportWebVitals);
15
+ onLCP(reportWebVitals);
16
+ onINP(reportWebVitals);
17
+ onFCP(reportWebVitals);
18
+ onTTFB(reportWebVitals);
19
+ }, []);
20
+ }
8
21
  //#endregion
9
22
  export { useReportWebVitals };
10
23
 
@@ -1 +1 @@
1
- {"version":3,"file":"web-vitals.js","names":[],"sources":["../../src/shims/web-vitals.ts"],"sourcesContent":["/**\n * next/web-vitals shim\n *\n * Provides useReportWebVitals() a no-op hook for compatibility.\n * In real Next.js, this sends Core Web Vitals to an analytics endpoint.\n * Apps can use the web-vitals library directly instead.\n */\n\ntype WebVitalsMetric = {\n id: string;\n name: string;\n value: number;\n rating?: \"good\" | \"needs-improvement\" | \"poor\";\n delta: number;\n navigationType?: \"navigate\" | \"reload\" | \"back-forward\" | \"prerender\";\n};\n\ntype ReportWebVitalsCallback = (metric: WebVitalsMetric) => void;\n\n/**\n * Register a callback to receive Core Web Vitals metrics.\n * No-op in our implementation — use the `web-vitals` library directly\n * for production metrics collection.\n */\nexport function useReportWebVitals(_callback: ReportWebVitalsCallback): void {\n // No-op — apps should use the web-vitals library directly\n // or their own analytics integration.\n}\n\nexport type { WebVitalsMetric, ReportWebVitalsCallback };\n"],"mappings":";;;;;;AAwBA,SAAgB,mBAAmB,WAA0C"}
1
+ {"version":3,"file":"web-vitals.js","names":[],"sources":["../../src/shims/web-vitals.ts"],"sourcesContent":["import { useEffect, useRef } from \"react\";\nimport { onCLS, onFID, onLCP, onINP, onFCP, onTTFB, type MetricType } from \"web-vitals\";\n\ntype WebVitalsMetric = MetricType;\ntype ReportWebVitalsCallback = (metric: WebVitalsMetric) => void;\n\nexport function useReportWebVitals(callback: ReportWebVitalsCallback): void {\n const callbackRef = useRef(callback);\n\n useEffect(() => {\n callbackRef.current = callback;\n }, [callback]);\n\n useEffect(() => {\n const reportWebVitals = (metric: WebVitalsMetric) => {\n callbackRef.current(metric);\n };\n\n onCLS(reportWebVitals);\n onFID(reportWebVitals);\n onLCP(reportWebVitals);\n onINP(reportWebVitals);\n onFCP(reportWebVitals);\n onTTFB(reportWebVitals);\n }, []);\n}\n\nexport type { WebVitalsMetric, ReportWebVitalsCallback };\n"],"mappings":";;;AAMA,SAAgB,mBAAmB,UAAyC;CAC1E,MAAM,cAAc,OAAO,SAAS;CAEpC,gBAAgB;EACd,YAAY,UAAU;IACrB,CAAC,SAAS,CAAC;CAEd,gBAAgB;EACd,MAAM,mBAAmB,WAA4B;GACnD,YAAY,QAAQ,OAAO;;EAG7B,MAAM,gBAAgB;EACtB,MAAM,gBAAgB;EACtB,MAAM,gBAAgB;EACtB,MAAM,gBAAgB;EACtB,MAAM,gBAAgB;EACtB,OAAO,gBAAgB;IACtB,EAAE,CAAC"}
@@ -0,0 +1,69 @@
1
+ //#region src/utils/asset-prefix.d.ts
2
+ /**
3
+ * Shared helpers for next.config `assetPrefix`.
4
+ *
5
+ * Mirrors Next.js semantics: `assetPrefix` is prepended to every JS/CSS/image/
6
+ * static asset URL emitted in the page. It is distinct from `basePath`, which
7
+ * affects route URLs.
8
+ *
9
+ * - A `assetPrefix` of `""` (empty) means "no prefix" — behaviour matches the
10
+ * historical default.
11
+ * - A path prefix like `"/custom-asset-prefix"` is applied as a URL prefix
12
+ * relative to the deployment origin. The prod server must also serve assets
13
+ * under that prefix.
14
+ * - An absolute URL like `"https://cdn.example.com"` makes asset URLs fully
15
+ * qualified. Runtime serving on the deployment origin is a no-op — the CDN
16
+ * serves the assets directly.
17
+ *
18
+ * The path component of the asset URL after the prefix is always
19
+ * `/_next/static/<filename>` to match Next.js's convention. This is the
20
+ * convention upstream test suites assert against.
21
+ *
22
+ * @see https://nextjs.org/docs/app/api-reference/config/next-config-js/assetPrefix
23
+ */
24
+ /**
25
+ * Suffix appended to the assetPrefix (or used standalone when no prefix is
26
+ * configured) to form the leading portion of every emitted asset URL.
27
+ * Matches Next.js: assets always live under `/_next/static/`.
28
+ */
29
+ declare const ASSET_PREFIX_URL_DIR = "_next/static";
30
+ /** Whether `assetPrefix` is an absolute URL (vs a path prefix). */
31
+ declare function isAbsoluteAssetPrefix(assetPrefix: string): boolean;
32
+ /**
33
+ * Compute the on-disk `build.assetsDir` for the given `assetPrefix`.
34
+ *
35
+ * - Path prefix (`/cdn`): write to `cdn/_next/static/` so the on-disk layout
36
+ * matches the URL — the Cloudflare ASSETS binding (and any static file
37
+ * server) serves them directly without a runtime rewrite.
38
+ * - Absolute URL (with or without path component): write to `_next/static/`.
39
+ * Runtime serving is best-effort — the CDN is expected to serve these.
40
+ * - Empty: keep the historical default of `assets/`, preserving disk layout
41
+ * for projects that haven't opted into `assetPrefix`.
42
+ */
43
+ declare function resolveAssetsDir(assetPrefix: string): string;
44
+ /**
45
+ * Build the URL prefix to apply to emitted asset URLs. Returns the full URL
46
+ * prefix including the `_next/static/` directory, with a trailing slash.
47
+ *
48
+ * Examples:
49
+ * - `""` → `"/_next/static/"`
50
+ * - `"/cdn"` → `"/cdn/_next/static/"`
51
+ * - `"https://cdn.example.com"` → `"https://cdn.example.com/_next/static/"`
52
+ * - `"https://cdn.example.com/sub"` → `"https://cdn.example.com/sub/_next/static/"`
53
+ */
54
+ declare function resolveAssetUrlPrefix(assetPrefix: string): string;
55
+ /**
56
+ * Extract the path portion of `assetPrefix` for use in runtime URL matching.
57
+ *
58
+ * - For a path prefix: returns it verbatim (e.g. `/custom-asset-prefix`).
59
+ * - For an absolute URL: returns its pathname stripped of trailing slashes
60
+ * (e.g. `"https://cdn.example.com/sub"` → `/sub`, plain origin → `""`).
61
+ * - For empty input: returns `""`.
62
+ *
63
+ * Used by the prod server and Cloudflare worker entry to recognise asset
64
+ * requests that arrive at the deployment origin under the configured prefix.
65
+ */
66
+ declare function assetPrefixPathname(assetPrefix: string): string;
67
+ //#endregion
68
+ export { ASSET_PREFIX_URL_DIR, assetPrefixPathname, isAbsoluteAssetPrefix, resolveAssetUrlPrefix, resolveAssetsDir };
69
+ //# sourceMappingURL=asset-prefix.d.ts.map
@@ -0,0 +1,91 @@
1
+ //#region src/utils/asset-prefix.ts
2
+ /**
3
+ * Shared helpers for next.config `assetPrefix`.
4
+ *
5
+ * Mirrors Next.js semantics: `assetPrefix` is prepended to every JS/CSS/image/
6
+ * static asset URL emitted in the page. It is distinct from `basePath`, which
7
+ * affects route URLs.
8
+ *
9
+ * - A `assetPrefix` of `""` (empty) means "no prefix" — behaviour matches the
10
+ * historical default.
11
+ * - A path prefix like `"/custom-asset-prefix"` is applied as a URL prefix
12
+ * relative to the deployment origin. The prod server must also serve assets
13
+ * under that prefix.
14
+ * - An absolute URL like `"https://cdn.example.com"` makes asset URLs fully
15
+ * qualified. Runtime serving on the deployment origin is a no-op — the CDN
16
+ * serves the assets directly.
17
+ *
18
+ * The path component of the asset URL after the prefix is always
19
+ * `/_next/static/<filename>` to match Next.js's convention. This is the
20
+ * convention upstream test suites assert against.
21
+ *
22
+ * @see https://nextjs.org/docs/app/api-reference/config/next-config-js/assetPrefix
23
+ */
24
+ /**
25
+ * Suffix appended to the assetPrefix (or used standalone when no prefix is
26
+ * configured) to form the leading portion of every emitted asset URL.
27
+ * Matches Next.js: assets always live under `/_next/static/`.
28
+ */
29
+ const ASSET_PREFIX_URL_DIR = "_next/static";
30
+ /** Whether `assetPrefix` is an absolute URL (vs a path prefix). */
31
+ function isAbsoluteAssetPrefix(assetPrefix) {
32
+ return /^https?:\/\//i.test(assetPrefix);
33
+ }
34
+ /**
35
+ * Compute the on-disk `build.assetsDir` for the given `assetPrefix`.
36
+ *
37
+ * - Path prefix (`/cdn`): write to `cdn/_next/static/` so the on-disk layout
38
+ * matches the URL — the Cloudflare ASSETS binding (and any static file
39
+ * server) serves them directly without a runtime rewrite.
40
+ * - Absolute URL (with or without path component): write to `_next/static/`.
41
+ * Runtime serving is best-effort — the CDN is expected to serve these.
42
+ * - Empty: keep the historical default of `assets/`, preserving disk layout
43
+ * for projects that haven't opted into `assetPrefix`.
44
+ */
45
+ function resolveAssetsDir(assetPrefix) {
46
+ if (!assetPrefix) return "assets";
47
+ if (isAbsoluteAssetPrefix(assetPrefix)) return ASSET_PREFIX_URL_DIR;
48
+ let stripped = assetPrefix;
49
+ while (stripped.startsWith("/")) stripped = stripped.slice(1);
50
+ return `${stripped}/${ASSET_PREFIX_URL_DIR}`;
51
+ }
52
+ /**
53
+ * Build the URL prefix to apply to emitted asset URLs. Returns the full URL
54
+ * prefix including the `_next/static/` directory, with a trailing slash.
55
+ *
56
+ * Examples:
57
+ * - `""` → `"/_next/static/"`
58
+ * - `"/cdn"` → `"/cdn/_next/static/"`
59
+ * - `"https://cdn.example.com"` → `"https://cdn.example.com/_next/static/"`
60
+ * - `"https://cdn.example.com/sub"` → `"https://cdn.example.com/sub/_next/static/"`
61
+ */
62
+ function resolveAssetUrlPrefix(assetPrefix) {
63
+ if (!assetPrefix) return `/${ASSET_PREFIX_URL_DIR}/`;
64
+ return `${assetPrefix}/${ASSET_PREFIX_URL_DIR}/`;
65
+ }
66
+ /**
67
+ * Extract the path portion of `assetPrefix` for use in runtime URL matching.
68
+ *
69
+ * - For a path prefix: returns it verbatim (e.g. `/custom-asset-prefix`).
70
+ * - For an absolute URL: returns its pathname stripped of trailing slashes
71
+ * (e.g. `"https://cdn.example.com/sub"` → `/sub`, plain origin → `""`).
72
+ * - For empty input: returns `""`.
73
+ *
74
+ * Used by the prod server and Cloudflare worker entry to recognise asset
75
+ * requests that arrive at the deployment origin under the configured prefix.
76
+ */
77
+ function assetPrefixPathname(assetPrefix) {
78
+ if (!assetPrefix) return "";
79
+ if (!isAbsoluteAssetPrefix(assetPrefix)) return assetPrefix;
80
+ try {
81
+ let pathname = new URL(assetPrefix).pathname;
82
+ while (pathname.endsWith("/")) pathname = pathname.slice(0, -1);
83
+ return pathname === "" ? "" : pathname;
84
+ } catch {
85
+ return "";
86
+ }
87
+ }
88
+ //#endregion
89
+ export { ASSET_PREFIX_URL_DIR, assetPrefixPathname, isAbsoluteAssetPrefix, resolveAssetUrlPrefix, resolveAssetsDir };
90
+
91
+ //# sourceMappingURL=asset-prefix.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asset-prefix.js","names":[],"sources":["../../src/utils/asset-prefix.ts"],"sourcesContent":["/**\n * Shared helpers for next.config `assetPrefix`.\n *\n * Mirrors Next.js semantics: `assetPrefix` is prepended to every JS/CSS/image/\n * static asset URL emitted in the page. It is distinct from `basePath`, which\n * affects route URLs.\n *\n * - A `assetPrefix` of `\"\"` (empty) means \"no prefix\" — behaviour matches the\n * historical default.\n * - A path prefix like `\"/custom-asset-prefix\"` is applied as a URL prefix\n * relative to the deployment origin. The prod server must also serve assets\n * under that prefix.\n * - An absolute URL like `\"https://cdn.example.com\"` makes asset URLs fully\n * qualified. Runtime serving on the deployment origin is a no-op — the CDN\n * serves the assets directly.\n *\n * The path component of the asset URL after the prefix is always\n * `/_next/static/<filename>` to match Next.js's convention. This is the\n * convention upstream test suites assert against.\n *\n * @see https://nextjs.org/docs/app/api-reference/config/next-config-js/assetPrefix\n */\n\n/**\n * Suffix appended to the assetPrefix (or used standalone when no prefix is\n * configured) to form the leading portion of every emitted asset URL.\n * Matches Next.js: assets always live under `/_next/static/`.\n */\nexport const ASSET_PREFIX_URL_DIR = \"_next/static\";\n\n/** Whether `assetPrefix` is an absolute URL (vs a path prefix). */\nexport function isAbsoluteAssetPrefix(assetPrefix: string): boolean {\n return /^https?:\\/\\//i.test(assetPrefix);\n}\n\n/**\n * Compute the on-disk `build.assetsDir` for the given `assetPrefix`.\n *\n * - Path prefix (`/cdn`): write to `cdn/_next/static/` so the on-disk layout\n * matches the URL — the Cloudflare ASSETS binding (and any static file\n * server) serves them directly without a runtime rewrite.\n * - Absolute URL (with or without path component): write to `_next/static/`.\n * Runtime serving is best-effort — the CDN is expected to serve these.\n * - Empty: keep the historical default of `assets/`, preserving disk layout\n * for projects that haven't opted into `assetPrefix`.\n */\nexport function resolveAssetsDir(assetPrefix: string): string {\n if (!assetPrefix) return \"assets\";\n if (isAbsoluteAssetPrefix(assetPrefix)) {\n // Files on disk land at `_next/static/...`. The absolute URL is applied\n // at URL-rendering time via renderBuiltUrl; on-disk path is irrelevant\n // to the CDN.\n return ASSET_PREFIX_URL_DIR;\n }\n // Path prefix — strip leading slash so the path joins cleanly with outDir.\n // Use an explicit loop instead of `replace(/^\\/+/, \"\")` so CodeQL doesn't\n // flag the regex as polynomial-time on uncontrolled input.\n let stripped = assetPrefix;\n while (stripped.startsWith(\"/\")) stripped = stripped.slice(1);\n return `${stripped}/${ASSET_PREFIX_URL_DIR}`;\n}\n\n/**\n * Build the URL prefix to apply to emitted asset URLs. Returns the full URL\n * prefix including the `_next/static/` directory, with a trailing slash.\n *\n * Examples:\n * - `\"\"` → `\"/_next/static/\"`\n * - `\"/cdn\"` → `\"/cdn/_next/static/\"`\n * - `\"https://cdn.example.com\"` → `\"https://cdn.example.com/_next/static/\"`\n * - `\"https://cdn.example.com/sub\"` → `\"https://cdn.example.com/sub/_next/static/\"`\n */\nexport function resolveAssetUrlPrefix(assetPrefix: string): string {\n if (!assetPrefix) return `/${ASSET_PREFIX_URL_DIR}/`;\n return `${assetPrefix}/${ASSET_PREFIX_URL_DIR}/`;\n}\n\n/**\n * Extract the path portion of `assetPrefix` for use in runtime URL matching.\n *\n * - For a path prefix: returns it verbatim (e.g. `/custom-asset-prefix`).\n * - For an absolute URL: returns its pathname stripped of trailing slashes\n * (e.g. `\"https://cdn.example.com/sub\"` → `/sub`, plain origin → `\"\"`).\n * - For empty input: returns `\"\"`.\n *\n * Used by the prod server and Cloudflare worker entry to recognise asset\n * requests that arrive at the deployment origin under the configured prefix.\n */\nexport function assetPrefixPathname(assetPrefix: string): string {\n if (!assetPrefix) return \"\";\n if (!isAbsoluteAssetPrefix(assetPrefix)) return assetPrefix;\n try {\n let pathname = new URL(assetPrefix).pathname;\n while (pathname.endsWith(\"/\")) pathname = pathname.slice(0, -1);\n return pathname === \"\" ? \"\" : pathname;\n } catch {\n return \"\";\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,MAAa,uBAAuB;;AAGpC,SAAgB,sBAAsB,aAA8B;CAClE,OAAO,gBAAgB,KAAK,YAAY;;;;;;;;;;;;;AAc1C,SAAgB,iBAAiB,aAA6B;CAC5D,IAAI,CAAC,aAAa,OAAO;CACzB,IAAI,sBAAsB,YAAY,EAIpC,OAAO;CAKT,IAAI,WAAW;CACf,OAAO,SAAS,WAAW,IAAI,EAAE,WAAW,SAAS,MAAM,EAAE;CAC7D,OAAO,GAAG,SAAS,GAAG;;;;;;;;;;;;AAaxB,SAAgB,sBAAsB,aAA6B;CACjE,IAAI,CAAC,aAAa,OAAO,IAAI,qBAAqB;CAClD,OAAO,GAAG,YAAY,GAAG,qBAAqB;;;;;;;;;;;;;AAchD,SAAgB,oBAAoB,aAA6B;CAC/D,IAAI,CAAC,aAAa,OAAO;CACzB,IAAI,CAAC,sBAAsB,YAAY,EAAE,OAAO;CAChD,IAAI;EACF,IAAI,WAAW,IAAI,IAAI,YAAY,CAAC;EACpC,OAAO,SAAS,SAAS,IAAI,EAAE,WAAW,SAAS,MAAM,GAAG,GAAG;EAC/D,OAAO,aAAa,KAAK,KAAK;SACxB;EACN,OAAO"}
@@ -15,6 +15,12 @@ declare function hasBasePath(pathname: string, basePath: string): boolean;
15
15
  * boundary. Returns the original pathname when it is outside the basePath.
16
16
  */
17
17
  declare function stripBasePath(pathname: string, basePath: string): string;
18
+ /**
19
+ * Add the configured basePath to a pathname unless it is already inside that
20
+ * basePath. Query strings and hashes must be handled by callers before calling
21
+ * this pathname-only helper.
22
+ */
23
+ declare function addBasePathToPathname(pathname: string, basePath: string | undefined): string;
18
24
  /**
19
25
  * Remove trailing slashes from a pathname while preserving the root "/".
20
26
  * Collapses any number of trailing slashes ("/a//" → "/a"). Used by the
@@ -22,5 +28,5 @@ declare function stripBasePath(pathname: string, basePath: string): string;
22
28
  */
23
29
  declare function removeTrailingSlash(pathname: string): string;
24
30
  //#endregion
25
- export { hasBasePath, removeTrailingSlash, stripBasePath };
31
+ export { addBasePathToPathname, hasBasePath, removeTrailingSlash, stripBasePath };
26
32
  //# sourceMappingURL=base-path.d.ts.map
@@ -22,6 +22,15 @@ function stripBasePath(pathname, basePath) {
22
22
  return pathname.slice(basePath.length) || "/";
23
23
  }
24
24
  /**
25
+ * Add the configured basePath to a pathname unless it is already inside that
26
+ * basePath. Query strings and hashes must be handled by callers before calling
27
+ * this pathname-only helper.
28
+ */
29
+ function addBasePathToPathname(pathname, basePath) {
30
+ if (!basePath || hasBasePath(pathname, basePath)) return pathname;
31
+ return pathname === "/" ? basePath : `${basePath}${pathname}`;
32
+ }
33
+ /**
25
34
  * Remove trailing slashes from a pathname while preserving the root "/".
26
35
  * Collapses any number of trailing slashes ("/a//" → "/a"). Used by the
27
36
  * trailing-slash redirect path and route pattern normalization.
@@ -33,6 +42,6 @@ function removeTrailingSlash(pathname) {
33
42
  return end === 0 ? "/" : pathname.slice(0, end);
34
43
  }
35
44
  //#endregion
36
- export { hasBasePath, removeTrailingSlash, stripBasePath };
45
+ export { addBasePathToPathname, hasBasePath, removeTrailingSlash, stripBasePath };
37
46
 
38
47
  //# sourceMappingURL=base-path.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"base-path.js","names":[],"sources":["../../src/utils/base-path.ts"],"sourcesContent":["/**\n * Shared basePath helpers.\n *\n * Next.js only treats a pathname as being under basePath when it is an exact\n * match (\"/app\") or starts with the basePath followed by a path separator\n * (\"/app/...\"). Prefix-only matches like \"/application\" must be left intact.\n */\n\n/**\n * Check whether a pathname is inside the configured basePath.\n */\nexport function hasBasePath(pathname: string, basePath: string): boolean {\n if (!basePath) return false;\n return pathname === basePath || pathname.startsWith(basePath + \"/\");\n}\n\n/**\n * Strip the basePath prefix from a pathname when it matches on a segment\n * boundary. Returns the original pathname when it is outside the basePath.\n */\nexport function stripBasePath(pathname: string, basePath: string): string {\n if (!hasBasePath(pathname, basePath)) return pathname;\n return pathname.slice(basePath.length) || \"/\";\n}\n\n/**\n * Remove trailing slashes from a pathname while preserving the root \"/\".\n * Collapses any number of trailing slashes (\"/a//\" → \"/a\"). Used by the\n * trailing-slash redirect path and route pattern normalization.\n */\nexport function removeTrailingSlash(pathname: string): string {\n if (pathname === \"/\") return \"/\";\n let end = pathname.length;\n while (end > 0 && pathname.charCodeAt(end - 1) === 47 /* \"/\" */) end--;\n return end === 0 ? \"/\" : pathname.slice(0, end);\n}\n"],"mappings":";;;;;;;;;;;AAWA,SAAgB,YAAY,UAAkB,UAA2B;AACvE,KAAI,CAAC,SAAU,QAAO;AACtB,QAAO,aAAa,YAAY,SAAS,WAAW,WAAW,IAAI;;;;;;AAOrE,SAAgB,cAAc,UAAkB,UAA0B;AACxE,KAAI,CAAC,YAAY,UAAU,SAAS,CAAE,QAAO;AAC7C,QAAO,SAAS,MAAM,SAAS,OAAO,IAAI;;;;;;;AAQ5C,SAAgB,oBAAoB,UAA0B;AAC5D,KAAI,aAAa,IAAK,QAAO;CAC7B,IAAI,MAAM,SAAS;AACnB,QAAO,MAAM,KAAK,SAAS,WAAW,MAAM,EAAE,KAAK,GAAc;AACjE,QAAO,QAAQ,IAAI,MAAM,SAAS,MAAM,GAAG,IAAI"}
1
+ {"version":3,"file":"base-path.js","names":[],"sources":["../../src/utils/base-path.ts"],"sourcesContent":["/**\n * Shared basePath helpers.\n *\n * Next.js only treats a pathname as being under basePath when it is an exact\n * match (\"/app\") or starts with the basePath followed by a path separator\n * (\"/app/...\"). Prefix-only matches like \"/application\" must be left intact.\n */\n\n/**\n * Check whether a pathname is inside the configured basePath.\n */\nexport function hasBasePath(pathname: string, basePath: string): boolean {\n if (!basePath) return false;\n return pathname === basePath || pathname.startsWith(basePath + \"/\");\n}\n\n/**\n * Strip the basePath prefix from a pathname when it matches on a segment\n * boundary. Returns the original pathname when it is outside the basePath.\n */\nexport function stripBasePath(pathname: string, basePath: string): string {\n if (!hasBasePath(pathname, basePath)) return pathname;\n return pathname.slice(basePath.length) || \"/\";\n}\n\n/**\n * Add the configured basePath to a pathname unless it is already inside that\n * basePath. Query strings and hashes must be handled by callers before calling\n * this pathname-only helper.\n */\nexport function addBasePathToPathname(pathname: string, basePath: string | undefined): string {\n if (!basePath || hasBasePath(pathname, basePath)) return pathname;\n return pathname === \"/\" ? basePath : `${basePath}${pathname}`;\n}\n\n/**\n * Remove trailing slashes from a pathname while preserving the root \"/\".\n * Collapses any number of trailing slashes (\"/a//\" → \"/a\"). Used by the\n * trailing-slash redirect path and route pattern normalization.\n */\nexport function removeTrailingSlash(pathname: string): string {\n if (pathname === \"/\") return \"/\";\n let end = pathname.length;\n while (end > 0 && pathname.charCodeAt(end - 1) === 47 /* \"/\" */) end--;\n return end === 0 ? \"/\" : pathname.slice(0, end);\n}\n"],"mappings":";;;;;;;;;;;AAWA,SAAgB,YAAY,UAAkB,UAA2B;CACvE,IAAI,CAAC,UAAU,OAAO;CACtB,OAAO,aAAa,YAAY,SAAS,WAAW,WAAW,IAAI;;;;;;AAOrE,SAAgB,cAAc,UAAkB,UAA0B;CACxE,IAAI,CAAC,YAAY,UAAU,SAAS,EAAE,OAAO;CAC7C,OAAO,SAAS,MAAM,SAAS,OAAO,IAAI;;;;;;;AAQ5C,SAAgB,sBAAsB,UAAkB,UAAsC;CAC5F,IAAI,CAAC,YAAY,YAAY,UAAU,SAAS,EAAE,OAAO;CACzD,OAAO,aAAa,MAAM,WAAW,GAAG,WAAW;;;;;;;AAQrD,SAAgB,oBAAoB,UAA0B;CAC5D,IAAI,aAAa,KAAK,OAAO;CAC7B,IAAI,MAAM,SAAS;CACnB,OAAO,MAAM,KAAK,SAAS,WAAW,MAAM,EAAE,KAAK,IAAc;CACjE,OAAO,QAAQ,IAAI,MAAM,SAAS,MAAM,GAAG,IAAI"}
@@ -1 +1 @@
1
- {"version":3,"file":"cache-control-metadata.js","names":[],"sources":["../../src/utils/cache-control-metadata.ts"],"sourcesContent":["export function isUnknownRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction readRecordField(\n ctx: Record<string, unknown> | undefined,\n field: string,\n): Record<string, unknown> | undefined {\n const value = ctx?.[field];\n return isUnknownRecord(value) ? value : undefined;\n}\n\nexport function readCacheControlNumberField(\n ctx: Record<string, unknown> | undefined,\n field: string,\n): number | undefined {\n const cacheControl = readRecordField(ctx, \"cacheControl\");\n const value = cacheControl?.[field] ?? ctx?.[field];\n return typeof value === \"number\" ? value : undefined;\n}\n"],"mappings":";AAAA,SAAgB,gBAAgB,OAAkD;AAChF,QAAO,UAAU,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,MAAM;;AAG7E,SAAS,gBACP,KACA,OACqC;CACrC,MAAM,QAAQ,MAAM;AACpB,QAAO,gBAAgB,MAAM,GAAG,QAAQ,KAAA;;AAG1C,SAAgB,4BACd,KACA,OACoB;CAEpB,MAAM,QADe,gBAAgB,KAAK,eAAe,GAC5B,UAAU,MAAM;AAC7C,QAAO,OAAO,UAAU,WAAW,QAAQ,KAAA"}
1
+ {"version":3,"file":"cache-control-metadata.js","names":[],"sources":["../../src/utils/cache-control-metadata.ts"],"sourcesContent":["export function isUnknownRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction readRecordField(\n ctx: Record<string, unknown> | undefined,\n field: string,\n): Record<string, unknown> | undefined {\n const value = ctx?.[field];\n return isUnknownRecord(value) ? value : undefined;\n}\n\nexport function readCacheControlNumberField(\n ctx: Record<string, unknown> | undefined,\n field: string,\n): number | undefined {\n const cacheControl = readRecordField(ctx, \"cacheControl\");\n const value = cacheControl?.[field] ?? ctx?.[field];\n return typeof value === \"number\" ? value : undefined;\n}\n"],"mappings":";AAAA,SAAgB,gBAAgB,OAAkD;CAChF,OAAO,UAAU,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,MAAM;;AAG7E,SAAS,gBACP,KACA,OACqC;CACrC,MAAM,QAAQ,MAAM;CACpB,OAAO,gBAAgB,MAAM,GAAG,QAAQ,KAAA;;AAG1C,SAAgB,4BACd,KACA,OACoB;CAEpB,MAAM,QADe,gBAAgB,KAAK,eAChB,GAAG,UAAU,MAAM;CAC7C,OAAO,OAAO,UAAU,WAAW,QAAQ,KAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"domain-locale.js","names":[],"sources":["../../src/utils/domain-locale.ts"],"sourcesContent":["import type { NextI18nConfig } from \"../config/next-config.js\";\n\nexport type DomainLocale = NonNullable<NextI18nConfig[\"domains\"]>[number];\n\nexport function normalizeDomainHostname(hostname: string | null | undefined): string | undefined {\n if (!hostname) return undefined;\n return hostname.split(\",\", 1)[0]?.trim().split(\":\", 1)[0]?.toLowerCase() || undefined;\n}\n\n/**\n * Match a configured domain either by hostname or locale.\n * When both are provided, the checks intentionally use OR semantics so the\n * same helper can cover Next.js's hostname lookup and preferred-locale lookup.\n * If both are passed, the first domain matching either input wins, so callers\n * should pass hostname or detectedLocale, not both.\n */\nexport function detectDomainLocale(\n domainItems?: readonly DomainLocale[],\n hostname?: string,\n detectedLocale?: string,\n): DomainLocale | undefined {\n if (!domainItems?.length) return undefined;\n\n const normalizedHostname = normalizeDomainHostname(hostname);\n const normalizedLocale = detectedLocale?.toLowerCase();\n\n for (const item of domainItems) {\n const domainHostname = normalizeDomainHostname(item.domain);\n if (\n normalizedHostname === domainHostname ||\n normalizedLocale === item.defaultLocale.toLowerCase() ||\n item.locales?.some((locale) => locale.toLowerCase() === normalizedLocale)\n ) {\n return item;\n }\n }\n\n return undefined;\n}\n\nexport function addLocalePrefix(path: string, locale: string, localeDefault: string): string {\n const normalizedLocale = locale.toLowerCase();\n if (normalizedLocale === localeDefault.toLowerCase()) return path;\n\n const pathWithLeadingSlash = path.startsWith(\"/\") ? path : `/${path}`;\n const pathname = pathWithLeadingSlash.split(/[?#]/, 1)[0] ?? pathWithLeadingSlash;\n const normalizedPathname = pathname.toLowerCase();\n const localePrefix = `/${normalizedLocale}`;\n\n if (normalizedPathname === localePrefix || normalizedPathname.startsWith(`${localePrefix}/`)) {\n return path.startsWith(\"/\") ? path : pathWithLeadingSlash;\n }\n\n return `/${locale}${pathWithLeadingSlash}`;\n}\n\nfunction withBasePath(path: string, basePath = \"\"): string {\n if (!basePath) return path;\n return basePath + path;\n}\n\nexport function getDomainLocaleUrl(\n url: string,\n locale: string,\n {\n basePath,\n currentHostname,\n domainItems,\n }: {\n basePath?: string;\n currentHostname?: string | null;\n domainItems?: readonly DomainLocale[];\n },\n): string | undefined {\n if (!domainItems?.length) return undefined;\n\n const targetDomain = detectDomainLocale(domainItems, undefined, locale);\n if (!targetDomain) return undefined;\n\n const currentDomain = detectDomainLocale(domainItems, currentHostname ?? undefined);\n const localizedPath = addLocalePrefix(url, locale, targetDomain.defaultLocale);\n\n if (\n currentDomain &&\n normalizeDomainHostname(currentDomain.domain) === normalizeDomainHostname(targetDomain.domain)\n ) {\n // Same-domain switches fall back to the caller's standard locale-prefix\n // logic. This relies on __VINEXT_DEFAULT_LOCALE__ matching the current\n // domain's defaultLocale, which the server entry keeps in sync.\n return undefined;\n }\n\n const scheme = `http${targetDomain.http ? \"\" : \"s\"}://`;\n return `${scheme}${targetDomain.domain}${withBasePath(localizedPath, basePath)}`;\n}\n"],"mappings":";AAIA,SAAgB,wBAAwB,UAAyD;AAC/F,KAAI,CAAC,SAAU,QAAO,KAAA;AACtB,QAAO,SAAS,MAAM,KAAK,EAAE,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,EAAE,CAAC,IAAI,aAAa,IAAI,KAAA;;;;;;;;;AAU9E,SAAgB,mBACd,aACA,UACA,gBAC0B;AAC1B,KAAI,CAAC,aAAa,OAAQ,QAAO,KAAA;CAEjC,MAAM,qBAAqB,wBAAwB,SAAS;CAC5D,MAAM,mBAAmB,gBAAgB,aAAa;AAEtD,MAAK,MAAM,QAAQ,YAEjB,KACE,uBAFqB,wBAAwB,KAAK,OAAO,IAGzD,qBAAqB,KAAK,cAAc,aAAa,IACrD,KAAK,SAAS,MAAM,WAAW,OAAO,aAAa,KAAK,iBAAiB,CAEzE,QAAO;;AAOb,SAAgB,gBAAgB,MAAc,QAAgB,eAA+B;CAC3F,MAAM,mBAAmB,OAAO,aAAa;AAC7C,KAAI,qBAAqB,cAAc,aAAa,CAAE,QAAO;CAE7D,MAAM,uBAAuB,KAAK,WAAW,IAAI,GAAG,OAAO,IAAI;CAE/D,MAAM,sBADW,qBAAqB,MAAM,QAAQ,EAAE,CAAC,MAAM,sBACzB,aAAa;CACjD,MAAM,eAAe,IAAI;AAEzB,KAAI,uBAAuB,gBAAgB,mBAAmB,WAAW,GAAG,aAAa,GAAG,CAC1F,QAAO,KAAK,WAAW,IAAI,GAAG,OAAO;AAGvC,QAAO,IAAI,SAAS;;AAGtB,SAAS,aAAa,MAAc,WAAW,IAAY;AACzD,KAAI,CAAC,SAAU,QAAO;AACtB,QAAO,WAAW;;AAGpB,SAAgB,mBACd,KACA,QACA,EACE,UACA,iBACA,eAMkB;AACpB,KAAI,CAAC,aAAa,OAAQ,QAAO,KAAA;CAEjC,MAAM,eAAe,mBAAmB,aAAa,KAAA,GAAW,OAAO;AACvE,KAAI,CAAC,aAAc,QAAO,KAAA;CAE1B,MAAM,gBAAgB,mBAAmB,aAAa,mBAAmB,KAAA,EAAU;CACnF,MAAM,gBAAgB,gBAAgB,KAAK,QAAQ,aAAa,cAAc;AAE9E,KACE,iBACA,wBAAwB,cAAc,OAAO,KAAK,wBAAwB,aAAa,OAAO,CAK9F;AAIF,QAAO,GADQ,OAAO,aAAa,OAAO,KAAK,IAAI,OAChC,aAAa,SAAS,aAAa,eAAe,SAAS"}
1
+ {"version":3,"file":"domain-locale.js","names":[],"sources":["../../src/utils/domain-locale.ts"],"sourcesContent":["import type { NextI18nConfig } from \"../config/next-config.js\";\n\nexport type DomainLocale = NonNullable<NextI18nConfig[\"domains\"]>[number];\n\nexport function normalizeDomainHostname(hostname: string | null | undefined): string | undefined {\n if (!hostname) return undefined;\n return hostname.split(\",\", 1)[0]?.trim().split(\":\", 1)[0]?.toLowerCase() || undefined;\n}\n\n/**\n * Match a configured domain either by hostname or locale.\n * When both are provided, the checks intentionally use OR semantics so the\n * same helper can cover Next.js's hostname lookup and preferred-locale lookup.\n * If both are passed, the first domain matching either input wins, so callers\n * should pass hostname or detectedLocale, not both.\n */\nexport function detectDomainLocale(\n domainItems?: readonly DomainLocale[],\n hostname?: string,\n detectedLocale?: string,\n): DomainLocale | undefined {\n if (!domainItems?.length) return undefined;\n\n const normalizedHostname = normalizeDomainHostname(hostname);\n const normalizedLocale = detectedLocale?.toLowerCase();\n\n for (const item of domainItems) {\n const domainHostname = normalizeDomainHostname(item.domain);\n if (\n normalizedHostname === domainHostname ||\n normalizedLocale === item.defaultLocale.toLowerCase() ||\n item.locales?.some((locale) => locale.toLowerCase() === normalizedLocale)\n ) {\n return item;\n }\n }\n\n return undefined;\n}\n\nexport function addLocalePrefix(path: string, locale: string, localeDefault: string): string {\n const normalizedLocale = locale.toLowerCase();\n if (normalizedLocale === localeDefault.toLowerCase()) return path;\n\n const pathWithLeadingSlash = path.startsWith(\"/\") ? path : `/${path}`;\n const pathname = pathWithLeadingSlash.split(/[?#]/, 1)[0] ?? pathWithLeadingSlash;\n const normalizedPathname = pathname.toLowerCase();\n const localePrefix = `/${normalizedLocale}`;\n\n if (normalizedPathname === localePrefix || normalizedPathname.startsWith(`${localePrefix}/`)) {\n return path.startsWith(\"/\") ? path : pathWithLeadingSlash;\n }\n\n return `/${locale}${pathWithLeadingSlash}`;\n}\n\nfunction withBasePath(path: string, basePath = \"\"): string {\n if (!basePath) return path;\n return basePath + path;\n}\n\nexport function getDomainLocaleUrl(\n url: string,\n locale: string,\n {\n basePath,\n currentHostname,\n domainItems,\n }: {\n basePath?: string;\n currentHostname?: string | null;\n domainItems?: readonly DomainLocale[];\n },\n): string | undefined {\n if (!domainItems?.length) return undefined;\n\n const targetDomain = detectDomainLocale(domainItems, undefined, locale);\n if (!targetDomain) return undefined;\n\n const currentDomain = detectDomainLocale(domainItems, currentHostname ?? undefined);\n const localizedPath = addLocalePrefix(url, locale, targetDomain.defaultLocale);\n\n if (\n currentDomain &&\n normalizeDomainHostname(currentDomain.domain) === normalizeDomainHostname(targetDomain.domain)\n ) {\n // Same-domain switches fall back to the caller's standard locale-prefix\n // logic. This relies on __VINEXT_DEFAULT_LOCALE__ matching the current\n // domain's defaultLocale, which the server entry keeps in sync.\n return undefined;\n }\n\n const scheme = `http${targetDomain.http ? \"\" : \"s\"}://`;\n return `${scheme}${targetDomain.domain}${withBasePath(localizedPath, basePath)}`;\n}\n"],"mappings":";AAIA,SAAgB,wBAAwB,UAAyD;CAC/F,IAAI,CAAC,UAAU,OAAO,KAAA;CACtB,OAAO,SAAS,MAAM,KAAK,EAAE,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,EAAE,CAAC,IAAI,aAAa,IAAI,KAAA;;;;;;;;;AAU9E,SAAgB,mBACd,aACA,UACA,gBAC0B;CAC1B,IAAI,CAAC,aAAa,QAAQ,OAAO,KAAA;CAEjC,MAAM,qBAAqB,wBAAwB,SAAS;CAC5D,MAAM,mBAAmB,gBAAgB,aAAa;CAEtD,KAAK,MAAM,QAAQ,aAEjB,IACE,uBAFqB,wBAAwB,KAAK,OAEb,IACrC,qBAAqB,KAAK,cAAc,aAAa,IACrD,KAAK,SAAS,MAAM,WAAW,OAAO,aAAa,KAAK,iBAAiB,EAEzE,OAAO;;AAOb,SAAgB,gBAAgB,MAAc,QAAgB,eAA+B;CAC3F,MAAM,mBAAmB,OAAO,aAAa;CAC7C,IAAI,qBAAqB,cAAc,aAAa,EAAE,OAAO;CAE7D,MAAM,uBAAuB,KAAK,WAAW,IAAI,GAAG,OAAO,IAAI;CAE/D,MAAM,sBADW,qBAAqB,MAAM,QAAQ,EAAE,CAAC,MAAM,sBACzB,aAAa;CACjD,MAAM,eAAe,IAAI;CAEzB,IAAI,uBAAuB,gBAAgB,mBAAmB,WAAW,GAAG,aAAa,GAAG,EAC1F,OAAO,KAAK,WAAW,IAAI,GAAG,OAAO;CAGvC,OAAO,IAAI,SAAS;;AAGtB,SAAS,aAAa,MAAc,WAAW,IAAY;CACzD,IAAI,CAAC,UAAU,OAAO;CACtB,OAAO,WAAW;;AAGpB,SAAgB,mBACd,KACA,QACA,EACE,UACA,iBACA,eAMkB;CACpB,IAAI,CAAC,aAAa,QAAQ,OAAO,KAAA;CAEjC,MAAM,eAAe,mBAAmB,aAAa,KAAA,GAAW,OAAO;CACvE,IAAI,CAAC,cAAc,OAAO,KAAA;CAE1B,MAAM,gBAAgB,mBAAmB,aAAa,mBAAmB,KAAA,EAAU;CACnF,MAAM,gBAAgB,gBAAgB,KAAK,QAAQ,aAAa,cAAc;CAE9E,IACE,iBACA,wBAAwB,cAAc,OAAO,KAAK,wBAAwB,aAAa,OAAO,EAK9F;CAIF,OAAO,GAAG,OADY,aAAa,OAAO,KAAK,IAAI,OAChC,aAAa,SAAS,aAAa,eAAe,SAAS"}
@@ -0,0 +1,31 @@
1
+ //#region src/utils/encode-cache-tag.d.ts
2
+ /**
3
+ * Cache-tag canonicalisation.
4
+ *
5
+ * Tags can flow into HTTP headers (e.g. `x-next-cache-tags` on ISR responses,
6
+ * Cloudflare cache-tag headers, downstream Worker code) where Node's
7
+ * `validateHeaderValue` rejects any byte outside `\t\x20-\x7e` and crashes
8
+ * the response with `ERR_INVALID_CHAR`. Even on platforms with permissive
9
+ * header setters, divergence between storage form and wire form silently
10
+ * breaks invalidation when a `revalidateTag` call's tag does not byte-match
11
+ * the form that was stored.
12
+ *
13
+ * The fix is to apply this encoding at every public boundary so storage,
14
+ * comparison, and the wire all see the same ASCII-safe form. The fast-path
15
+ * returns the input unchanged for already-ASCII tags (the common case), so
16
+ * pre-encoded `%xx` input round-trips losslessly without `decodeURIComponent`
17
+ * mangling literal `%xx` characters.
18
+ *
19
+ * The replacement matches *runs* of out-of-class code units rather than each
20
+ * code unit individually so surrogate pairs (emoji, non-BMP characters) are
21
+ * handed to `encodeURIComponent` as a complete code point — a per-code-unit
22
+ * regex would split the pair and throw `URIError`.
23
+ *
24
+ * Mirrors Next.js's `packages/next/src/server/lib/encode-cache-tag.ts`
25
+ * (introduced in vercel/next.js#93601).
26
+ */
27
+ declare function encodeCacheTag(tag: string): string;
28
+ declare function encodeCacheTags(tags: readonly string[]): string[];
29
+ //#endregion
30
+ export { encodeCacheTag, encodeCacheTags };
31
+ //# sourceMappingURL=encode-cache-tag.d.ts.map
@@ -0,0 +1,38 @@
1
+ //#region src/utils/encode-cache-tag.ts
2
+ /**
3
+ * Cache-tag canonicalisation.
4
+ *
5
+ * Tags can flow into HTTP headers (e.g. `x-next-cache-tags` on ISR responses,
6
+ * Cloudflare cache-tag headers, downstream Worker code) where Node's
7
+ * `validateHeaderValue` rejects any byte outside `\t\x20-\x7e` and crashes
8
+ * the response with `ERR_INVALID_CHAR`. Even on platforms with permissive
9
+ * header setters, divergence between storage form and wire form silently
10
+ * breaks invalidation when a `revalidateTag` call's tag does not byte-match
11
+ * the form that was stored.
12
+ *
13
+ * The fix is to apply this encoding at every public boundary so storage,
14
+ * comparison, and the wire all see the same ASCII-safe form. The fast-path
15
+ * returns the input unchanged for already-ASCII tags (the common case), so
16
+ * pre-encoded `%xx` input round-trips losslessly without `decodeURIComponent`
17
+ * mangling literal `%xx` characters.
18
+ *
19
+ * The replacement matches *runs* of out-of-class code units rather than each
20
+ * code unit individually so surrogate pairs (emoji, non-BMP characters) are
21
+ * handed to `encodeURIComponent` as a complete code point — a per-code-unit
22
+ * regex would split the pair and throw `URIError`.
23
+ *
24
+ * Mirrors Next.js's `packages/next/src/server/lib/encode-cache-tag.ts`
25
+ * (introduced in vercel/next.js#93601).
26
+ */
27
+ const OUT_OF_CLASS_CHAR = /[^\t\x20-\x7e]/;
28
+ const OUT_OF_CLASS_RUN = /[^\t\x20-\x7e]+/g;
29
+ function encodeCacheTag(tag) {
30
+ return OUT_OF_CLASS_CHAR.test(tag) ? tag.replace(OUT_OF_CLASS_RUN, (run) => encodeURIComponent(run)) : tag;
31
+ }
32
+ function encodeCacheTags(tags) {
33
+ return tags.map(encodeCacheTag);
34
+ }
35
+ //#endregion
36
+ export { encodeCacheTag, encodeCacheTags };
37
+
38
+ //# sourceMappingURL=encode-cache-tag.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encode-cache-tag.js","names":[],"sources":["../../src/utils/encode-cache-tag.ts"],"sourcesContent":["/**\n * Cache-tag canonicalisation.\n *\n * Tags can flow into HTTP headers (e.g. `x-next-cache-tags` on ISR responses,\n * Cloudflare cache-tag headers, downstream Worker code) where Node's\n * `validateHeaderValue` rejects any byte outside `\\t\\x20-\\x7e` and crashes\n * the response with `ERR_INVALID_CHAR`. Even on platforms with permissive\n * header setters, divergence between storage form and wire form silently\n * breaks invalidation when a `revalidateTag` call's tag does not byte-match\n * the form that was stored.\n *\n * The fix is to apply this encoding at every public boundary so storage,\n * comparison, and the wire all see the same ASCII-safe form. The fast-path\n * returns the input unchanged for already-ASCII tags (the common case), so\n * pre-encoded `%xx` input round-trips losslessly without `decodeURIComponent`\n * mangling literal `%xx` characters.\n *\n * The replacement matches *runs* of out-of-class code units rather than each\n * code unit individually so surrogate pairs (emoji, non-BMP characters) are\n * handed to `encodeURIComponent` as a complete code point — a per-code-unit\n * regex would split the pair and throw `URIError`.\n *\n * Mirrors Next.js's `packages/next/src/server/lib/encode-cache-tag.ts`\n * (introduced in vercel/next.js#93601).\n */\n\nconst OUT_OF_CLASS_CHAR = /[^\\t\\x20-\\x7e]/;\nconst OUT_OF_CLASS_RUN = /[^\\t\\x20-\\x7e]+/g;\n\nexport function encodeCacheTag(tag: string): string {\n return OUT_OF_CLASS_CHAR.test(tag)\n ? tag.replace(OUT_OF_CLASS_RUN, (run) => encodeURIComponent(run))\n : tag;\n}\n\nexport function encodeCacheTags(tags: readonly string[]): string[] {\n return tags.map(encodeCacheTag);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,MAAM,oBAAoB;AAC1B,MAAM,mBAAmB;AAEzB,SAAgB,eAAe,KAAqB;CAClD,OAAO,kBAAkB,KAAK,IAAI,GAC9B,IAAI,QAAQ,mBAAmB,QAAQ,mBAAmB,IAAI,CAAC,GAC/D;;AAGN,SAAgB,gBAAgB,MAAmC;CACjE,OAAO,KAAK,IAAI,eAAe"}