vinext 0.0.45 → 0.0.47

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 (311) hide show
  1. package/README.md +7 -5
  2. package/dist/build/prerender.d.ts +2 -1
  3. package/dist/build/prerender.js +80 -17
  4. package/dist/build/prerender.js.map +1 -1
  5. package/dist/build/report.d.ts +1 -1
  6. package/dist/build/route-classification-injector.d.ts +35 -0
  7. package/dist/build/route-classification-injector.js +61 -0
  8. package/dist/build/route-classification-injector.js.map +1 -0
  9. package/dist/build/route-classification-manifest.d.ts +1 -1
  10. package/dist/build/standalone.js +4 -3
  11. package/dist/build/standalone.js.map +1 -1
  12. package/dist/build/static-export.d.ts +1 -1
  13. package/dist/check.js +30 -18
  14. package/dist/check.js.map +1 -1
  15. package/dist/cli-args.d.ts +31 -0
  16. package/dist/cli-args.js +104 -0
  17. package/dist/cli-args.js.map +1 -0
  18. package/dist/cli.js +6 -19
  19. package/dist/cli.js.map +1 -1
  20. package/dist/cloudflare/kv-cache-handler.js +29 -9
  21. package/dist/cloudflare/kv-cache-handler.js.map +1 -1
  22. package/dist/config/config-matchers.js +1 -0
  23. package/dist/config/config-matchers.js.map +1 -1
  24. package/dist/config/next-config.d.ts +42 -4
  25. package/dist/config/next-config.js +27 -0
  26. package/dist/config/next-config.js.map +1 -1
  27. package/dist/deploy.js +18 -23
  28. package/dist/deploy.js.map +1 -1
  29. package/dist/entries/app-rsc-entry.d.ts +4 -3
  30. package/dist/entries/app-rsc-entry.js +435 -2317
  31. package/dist/entries/app-rsc-entry.js.map +1 -1
  32. package/dist/entries/app-rsc-manifest.d.ts +24 -0
  33. package/dist/entries/app-rsc-manifest.js +155 -0
  34. package/dist/entries/app-rsc-manifest.js.map +1 -0
  35. package/dist/entries/pages-server-entry.js +18 -105
  36. package/dist/entries/pages-server-entry.js.map +1 -1
  37. package/dist/index.js +82 -85
  38. package/dist/index.js.map +1 -1
  39. package/dist/plugins/fonts.js +54 -32
  40. package/dist/plugins/fonts.js.map +1 -1
  41. package/dist/plugins/rsc-client-shim-excludes.d.ts +6 -0
  42. package/dist/plugins/rsc-client-shim-excludes.js +28 -0
  43. package/dist/plugins/rsc-client-shim-excludes.js.map +1 -0
  44. package/dist/routing/app-route-graph.d.ts +109 -0
  45. package/dist/routing/app-route-graph.js +819 -0
  46. package/dist/routing/app-route-graph.js.map +1 -0
  47. package/dist/routing/app-router.d.ts +2 -79
  48. package/dist/routing/app-router.js +7 -621
  49. package/dist/routing/app-router.js.map +1 -1
  50. package/dist/routing/route-pattern.d.ts +9 -0
  51. package/dist/routing/route-pattern.js +90 -0
  52. package/dist/routing/route-pattern.js.map +1 -0
  53. package/dist/routing/route-trie.js +10 -11
  54. package/dist/routing/route-trie.js.map +1 -1
  55. package/dist/server/app-browser-entry.js +94 -232
  56. package/dist/server/app-browser-entry.js.map +1 -1
  57. package/dist/server/app-browser-error.d.ts +3 -4
  58. package/dist/server/app-browser-error.js +8 -4
  59. package/dist/server/app-browser-error.js.map +1 -1
  60. package/dist/server/app-browser-navigation-controller.d.ts +73 -0
  61. package/dist/server/app-browser-navigation-controller.js +282 -0
  62. package/dist/server/app-browser-navigation-controller.js.map +1 -0
  63. package/dist/server/app-browser-state.d.ts +1 -1
  64. package/dist/server/app-browser-state.js.map +1 -1
  65. package/dist/server/app-elements.js +1 -5
  66. package/dist/server/app-elements.js.map +1 -1
  67. package/dist/server/app-fallback-renderer.d.ts +57 -0
  68. package/dist/server/app-fallback-renderer.js +79 -0
  69. package/dist/server/app-fallback-renderer.js.map +1 -0
  70. package/dist/server/app-hook-warning-suppression.d.ts +7 -0
  71. package/dist/server/app-hook-warning-suppression.js +12 -0
  72. package/dist/server/app-hook-warning-suppression.js.map +1 -0
  73. package/dist/server/app-middleware.d.ts +32 -0
  74. package/dist/server/app-middleware.js +147 -0
  75. package/dist/server/app-middleware.js.map +1 -0
  76. package/dist/server/app-mounted-slots-header.d.ts +17 -0
  77. package/dist/server/app-mounted-slots-header.js +21 -0
  78. package/dist/server/app-mounted-slots-header.js.map +1 -0
  79. package/dist/server/app-page-boundary-render.d.ts +4 -2
  80. package/dist/server/app-page-boundary-render.js +50 -30
  81. package/dist/server/app-page-boundary-render.js.map +1 -1
  82. package/dist/server/app-page-boundary.d.ts +12 -1
  83. package/dist/server/app-page-boundary.js +27 -12
  84. package/dist/server/app-page-boundary.js.map +1 -1
  85. package/dist/server/app-page-cache.d.ts +22 -5
  86. package/dist/server/app-page-cache.js +90 -11
  87. package/dist/server/app-page-cache.js.map +1 -1
  88. package/dist/server/app-page-dispatch.d.ts +123 -0
  89. package/dist/server/app-page-dispatch.js +348 -0
  90. package/dist/server/app-page-dispatch.js.map +1 -0
  91. package/dist/server/app-page-element-builder.d.ts +61 -0
  92. package/dist/server/app-page-element-builder.js +139 -0
  93. package/dist/server/app-page-element-builder.js.map +1 -0
  94. package/dist/server/app-page-execution.d.ts +4 -3
  95. package/dist/server/app-page-execution.js +5 -8
  96. package/dist/server/app-page-execution.js.map +1 -1
  97. package/dist/server/app-page-head.d.ts +55 -0
  98. package/dist/server/app-page-head.js +196 -0
  99. package/dist/server/app-page-head.js.map +1 -0
  100. package/dist/server/app-page-method.d.ts +16 -0
  101. package/dist/server/app-page-method.js +30 -0
  102. package/dist/server/app-page-method.js.map +1 -0
  103. package/dist/server/app-page-params.d.ts +8 -0
  104. package/dist/server/app-page-params.js +28 -0
  105. package/dist/server/app-page-params.js.map +1 -0
  106. package/dist/server/app-page-render.d.ts +7 -2
  107. package/dist/server/app-page-render.js +131 -32
  108. package/dist/server/app-page-render.js.map +1 -1
  109. package/dist/server/app-page-request.d.ts +23 -8
  110. package/dist/server/app-page-request.js +51 -6
  111. package/dist/server/app-page-request.js.map +1 -1
  112. package/dist/server/app-page-response.d.ts +1 -0
  113. package/dist/server/app-page-response.js +3 -7
  114. package/dist/server/app-page-response.js.map +1 -1
  115. package/dist/server/app-page-route-wiring.d.ts +29 -5
  116. package/dist/server/app-page-route-wiring.js +30 -8
  117. package/dist/server/app-page-route-wiring.js.map +1 -1
  118. package/dist/server/app-page-stream.d.ts +10 -0
  119. package/dist/server/app-page-stream.js +5 -1
  120. package/dist/server/app-page-stream.js.map +1 -1
  121. package/dist/server/app-post-middleware-context.d.ts +16 -0
  122. package/dist/server/app-post-middleware-context.js +28 -0
  123. package/dist/server/app-post-middleware-context.js.map +1 -0
  124. package/dist/server/app-prerender-endpoints.d.ts +19 -0
  125. package/dist/server/app-prerender-endpoints.js +96 -0
  126. package/dist/server/app-prerender-endpoints.js.map +1 -0
  127. package/dist/server/app-prerender-static-params.d.ts +16 -0
  128. package/dist/server/app-prerender-static-params.js +14 -0
  129. package/dist/server/app-prerender-static-params.js.map +1 -0
  130. package/dist/server/app-request-context.d.ts +22 -0
  131. package/dist/server/app-request-context.js +30 -0
  132. package/dist/server/app-request-context.js.map +1 -0
  133. package/dist/server/app-route-handler-cache.d.ts +4 -0
  134. package/dist/server/app-route-handler-cache.js +11 -3
  135. package/dist/server/app-route-handler-cache.js.map +1 -1
  136. package/dist/server/app-route-handler-dispatch.d.ts +43 -0
  137. package/dist/server/app-route-handler-dispatch.js +149 -0
  138. package/dist/server/app-route-handler-dispatch.js.map +1 -0
  139. package/dist/server/app-route-handler-execution.d.ts +8 -3
  140. package/dist/server/app-route-handler-execution.js +25 -4
  141. package/dist/server/app-route-handler-execution.js.map +1 -1
  142. package/dist/server/app-route-handler-response.d.ts +6 -3
  143. package/dist/server/app-route-handler-response.js +52 -11
  144. package/dist/server/app-route-handler-response.js.map +1 -1
  145. package/dist/server/app-route-handler-runtime.d.ts +4 -1
  146. package/dist/server/app-route-handler-runtime.js +107 -1
  147. package/dist/server/app-route-handler-runtime.js.map +1 -1
  148. package/dist/server/app-router-entry.js.map +1 -1
  149. package/dist/server/app-rsc-error-handler.d.ts +21 -0
  150. package/dist/server/app-rsc-error-handler.js +30 -0
  151. package/dist/server/app-rsc-error-handler.js.map +1 -0
  152. package/dist/server/app-rsc-errors.d.ts +27 -0
  153. package/dist/server/app-rsc-errors.js +42 -0
  154. package/dist/server/app-rsc-errors.js.map +1 -0
  155. package/dist/server/app-rsc-handler.d.ts +117 -0
  156. package/dist/server/app-rsc-handler.js +260 -0
  157. package/dist/server/app-rsc-handler.js.map +1 -0
  158. package/dist/server/app-rsc-request-normalization.d.ts +40 -0
  159. package/dist/server/app-rsc-request-normalization.js +63 -0
  160. package/dist/server/app-rsc-request-normalization.js.map +1 -0
  161. package/dist/server/app-rsc-response-finalizer.d.ts +30 -0
  162. package/dist/server/app-rsc-response-finalizer.js +38 -0
  163. package/dist/server/app-rsc-response-finalizer.js.map +1 -0
  164. package/dist/server/app-rsc-route-matching.d.ts +40 -0
  165. package/dist/server/app-rsc-route-matching.js +66 -0
  166. package/dist/server/app-rsc-route-matching.js.map +1 -0
  167. package/dist/server/app-segment-config.d.ts +33 -0
  168. package/dist/server/app-segment-config.js +86 -0
  169. package/dist/server/app-segment-config.js.map +1 -0
  170. package/dist/server/app-server-action-execution.d.ts +88 -1
  171. package/dist/server/app-server-action-execution.js +257 -5
  172. package/dist/server/app-server-action-execution.js.map +1 -1
  173. package/dist/server/app-ssr-entry.d.ts +7 -0
  174. package/dist/server/app-ssr-entry.js +30 -9
  175. package/dist/server/app-ssr-entry.js.map +1 -1
  176. package/dist/server/app-ssr-stream.d.ts +4 -2
  177. package/dist/server/app-ssr-stream.js +29 -2
  178. package/dist/server/app-ssr-stream.js.map +1 -1
  179. package/dist/server/app-static-generation.d.ts +15 -0
  180. package/dist/server/app-static-generation.js +20 -0
  181. package/dist/server/app-static-generation.js.map +1 -0
  182. package/dist/server/cache-control.d.ts +24 -0
  183. package/dist/server/cache-control.js +33 -0
  184. package/dist/server/cache-control.js.map +1 -0
  185. package/dist/server/dev-error-overlay-store.d.ts +23 -0
  186. package/dist/server/dev-error-overlay-store.js +67 -0
  187. package/dist/server/dev-error-overlay-store.js.map +1 -0
  188. package/dist/server/dev-error-overlay.d.ts +15 -0
  189. package/dist/server/dev-error-overlay.js +548 -0
  190. package/dist/server/dev-error-overlay.js.map +1 -0
  191. package/dist/server/dev-route-files.d.ts +7 -0
  192. package/dist/server/dev-route-files.js +73 -0
  193. package/dist/server/dev-route-files.js.map +1 -0
  194. package/dist/server/dev-server.js +4 -0
  195. package/dist/server/dev-server.js.map +1 -1
  196. package/dist/server/file-based-metadata.d.ts +17 -0
  197. package/dist/server/file-based-metadata.js +356 -0
  198. package/dist/server/file-based-metadata.js.map +1 -0
  199. package/dist/server/implicit-tags.d.ts +6 -0
  200. package/dist/server/implicit-tags.js +42 -0
  201. package/dist/server/implicit-tags.js.map +1 -0
  202. package/dist/server/instrumentation-runtime.d.ts +44 -0
  203. package/dist/server/instrumentation-runtime.js +29 -0
  204. package/dist/server/instrumentation-runtime.js.map +1 -0
  205. package/dist/server/instrumentation.js.map +1 -1
  206. package/dist/server/isr-cache.d.ts +16 -3
  207. package/dist/server/isr-cache.js +56 -8
  208. package/dist/server/isr-cache.js.map +1 -1
  209. package/dist/server/metadata-route-build-data.d.ts +25 -0
  210. package/dist/server/metadata-route-build-data.js +150 -0
  211. package/dist/server/metadata-route-build-data.js.map +1 -0
  212. package/dist/server/metadata-route-response.d.ts +17 -0
  213. package/dist/server/metadata-route-response.js +187 -0
  214. package/dist/server/metadata-route-response.js.map +1 -0
  215. package/dist/server/metadata-routes.d.ts +42 -4
  216. package/dist/server/metadata-routes.js +127 -11
  217. package/dist/server/metadata-routes.js.map +1 -1
  218. package/dist/server/middleware-matcher.d.ts +15 -0
  219. package/dist/server/middleware-matcher.js +102 -0
  220. package/dist/server/middleware-matcher.js.map +1 -0
  221. package/dist/server/middleware-request-headers.js +2 -1
  222. package/dist/server/middleware-request-headers.js.map +1 -1
  223. package/dist/server/middleware-runtime.d.ts +39 -0
  224. package/dist/server/middleware-runtime.js +159 -0
  225. package/dist/server/middleware-runtime.js.map +1 -0
  226. package/dist/server/middleware.d.ts +4 -36
  227. package/dist/server/middleware.js +18 -228
  228. package/dist/server/middleware.js.map +1 -1
  229. package/dist/server/pages-page-data.d.ts +7 -2
  230. package/dist/server/pages-page-data.js +10 -5
  231. package/dist/server/pages-page-data.js.map +1 -1
  232. package/dist/server/pages-page-response.d.ts +2 -1
  233. package/dist/server/pages-page-response.js +5 -3
  234. package/dist/server/pages-page-response.js.map +1 -1
  235. package/dist/server/prerender-work-unit-setup.d.ts +7 -0
  236. package/dist/server/prerender-work-unit-setup.js +30 -0
  237. package/dist/server/prerender-work-unit-setup.js.map +1 -0
  238. package/dist/server/prod-server.js +10 -14
  239. package/dist/server/prod-server.js.map +1 -1
  240. package/dist/server/request-pipeline.d.ts +46 -5
  241. package/dist/server/request-pipeline.js +84 -5
  242. package/dist/server/request-pipeline.js.map +1 -1
  243. package/dist/server/rsc-stream-hints.d.ts +7 -0
  244. package/dist/server/rsc-stream-hints.js +38 -0
  245. package/dist/server/rsc-stream-hints.js.map +1 -0
  246. package/dist/server/seed-cache.js +19 -8
  247. package/dist/server/seed-cache.js.map +1 -1
  248. package/dist/server/server-action-not-found.d.ts +9 -0
  249. package/dist/server/server-action-not-found.js +40 -0
  250. package/dist/server/server-action-not-found.js.map +1 -0
  251. package/dist/shims/cache-runtime.js +28 -11
  252. package/dist/shims/cache-runtime.js.map +1 -1
  253. package/dist/shims/cache.d.ts +39 -4
  254. package/dist/shims/cache.js +93 -16
  255. package/dist/shims/cache.js.map +1 -1
  256. package/dist/shims/error-boundary.d.ts +66 -5
  257. package/dist/shims/error-boundary.js +106 -4
  258. package/dist/shims/error-boundary.js.map +1 -1
  259. package/dist/shims/fetch-cache.d.ts +4 -1
  260. package/dist/shims/fetch-cache.js +55 -13
  261. package/dist/shims/fetch-cache.js.map +1 -1
  262. package/dist/shims/font-google-base.d.ts +5 -4
  263. package/dist/shims/font-google-base.js +61 -13
  264. package/dist/shims/font-google-base.js.map +1 -1
  265. package/dist/shims/headers.d.ts +14 -2
  266. package/dist/shims/headers.js +127 -17
  267. package/dist/shims/headers.js.map +1 -1
  268. package/dist/shims/image.js +116 -10
  269. package/dist/shims/image.js.map +1 -1
  270. package/dist/shims/internal/make-hanging-promise.d.ts +16 -0
  271. package/dist/shims/internal/make-hanging-promise.js +46 -0
  272. package/dist/shims/internal/make-hanging-promise.js.map +1 -0
  273. package/dist/shims/internal/work-unit-async-storage.d.ts +26 -3
  274. package/dist/shims/internal/work-unit-async-storage.js +6 -3
  275. package/dist/shims/internal/work-unit-async-storage.js.map +1 -1
  276. package/dist/shims/metadata.d.ts +38 -26
  277. package/dist/shims/metadata.js +75 -45
  278. package/dist/shims/metadata.js.map +1 -1
  279. package/dist/shims/navigation.d.ts +10 -1
  280. package/dist/shims/navigation.js +18 -1
  281. package/dist/shims/navigation.js.map +1 -1
  282. package/dist/shims/navigation.react-server.d.ts +2 -2
  283. package/dist/shims/navigation.react-server.js +2 -2
  284. package/dist/shims/navigation.react-server.js.map +1 -1
  285. package/dist/shims/offline.d.ts +5 -0
  286. package/dist/shims/offline.js +17 -0
  287. package/dist/shims/offline.js.map +1 -0
  288. package/dist/shims/request-state-types.d.ts +3 -2
  289. package/dist/shims/root-params.d.ts +11 -0
  290. package/dist/shims/root-params.js +24 -0
  291. package/dist/shims/root-params.js.map +1 -0
  292. package/dist/shims/router.js +1 -1
  293. package/dist/shims/server.d.ts +3 -1
  294. package/dist/shims/server.js +83 -5
  295. package/dist/shims/server.js.map +1 -1
  296. package/dist/shims/thenable-params.d.ts +5 -0
  297. package/dist/shims/thenable-params.js +37 -0
  298. package/dist/shims/thenable-params.js.map +1 -0
  299. package/dist/shims/unified-request-context.d.ts +3 -2
  300. package/dist/shims/unified-request-context.js +3 -0
  301. package/dist/shims/unified-request-context.js.map +1 -1
  302. package/dist/shims/use-merged-ref.d.ts +7 -0
  303. package/dist/shims/use-merged-ref.js +40 -0
  304. package/dist/shims/use-merged-ref.js.map +1 -0
  305. package/dist/utils/cache-control-metadata.d.ts +6 -0
  306. package/dist/utils/cache-control-metadata.js +16 -0
  307. package/dist/utils/cache-control-metadata.js.map +1 -0
  308. package/package.json +6 -1
  309. package/dist/server/middleware-codegen.d.ts +0 -54
  310. package/dist/server/middleware-codegen.js +0 -414
  311. package/dist/server/middleware-codegen.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"image.js","names":["UnpicImage"],"sources":["../../src/shims/image.tsx"],"sourcesContent":["/**\n * next/image shim\n *\n * Translates Next.js Image props to @unpic/react Image component.\n * @unpic/react auto-detects CDN from URL and uses native transforms.\n * For local images (relative paths), routes through `/_vinext/image`\n * for server-side optimization (resize, format negotiation, quality).\n *\n * Remote images are validated against `images.remotePatterns` and\n * `images.domains` from next.config.js. Unmatched URLs are blocked\n * in production and warn in development, matching Next.js behavior.\n */\nimport React, { forwardRef } from \"react\";\nimport { Image as UnpicImage } from \"@unpic/react\";\nimport { hasRemoteMatch, type RemotePattern } from \"./image-config.js\";\n\nexport type StaticImageData = {\n src: string;\n height: number;\n width: number;\n blurDataURL?: string;\n};\n\n/**\n * Image config injected at build time via Vite define.\n * Serialized as JSON — parsed once at module level.\n */\nconst __imageRemotePatterns: RemotePattern[] = (() => {\n try {\n return JSON.parse(process.env.__VINEXT_IMAGE_REMOTE_PATTERNS ?? \"[]\");\n } catch {\n return [];\n }\n})();\nconst __imageDomains: string[] = (() => {\n try {\n return JSON.parse(process.env.__VINEXT_IMAGE_DOMAINS ?? \"[]\");\n } catch {\n return [];\n }\n})();\nconst __hasImageConfig = __imageRemotePatterns.length > 0 || __imageDomains.length > 0;\nconst __isDev = process.env.NODE_ENV !== \"production\";\nconst __imageDeviceSizes: number[] = (() => {\n try {\n return JSON.parse(\n process.env.__VINEXT_IMAGE_DEVICE_SIZES ?? \"[640,750,828,1080,1200,1920,2048,3840]\",\n );\n } catch {\n return [640, 750, 828, 1080, 1200, 1920, 2048, 3840];\n }\n})();\n/**\n * Whether dangerouslyAllowSVG is enabled in next.config.js.\n * When false (default), .svg sources auto-skip the optimization endpoint\n * and are served directly, matching Next.js behavior.\n * When true, .svg sources are routed through the optimizer (served as-is\n * with security headers).\n */\nconst __dangerouslyAllowSVG = process.env.__VINEXT_IMAGE_DANGEROUSLY_ALLOW_SVG === \"true\";\n/**\n * Validate that a remote URL is allowed by the configured remote patterns.\n * Returns true if the URL is allowed, false otherwise.\n *\n * When no remotePatterns/domains are configured, all remote URLs are allowed\n * (backwards-compatible — user hasn't opted into restriction).\n *\n * When patterns ARE configured, only matching URLs are allowed.\n * In development, non-matching URLs produce a console warning.\n * In production, non-matching URLs are blocked (src replaced with empty string).\n */\nfunction validateRemoteUrl(src: string): { allowed: boolean; reason?: string } {\n if (!__hasImageConfig) {\n // No image config — allow everything (backwards-compatible)\n return { allowed: true };\n }\n\n let url: URL;\n try {\n url = new URL(src, \"http://n\");\n } catch {\n return { allowed: false, reason: `Invalid URL: ${src}` };\n }\n\n if (hasRemoteMatch(__imageDomains, __imageRemotePatterns, url)) {\n return { allowed: true };\n }\n\n return {\n allowed: false,\n reason: `Image URL \"${src}\" is not configured in images.remotePatterns or images.domains in next.config.js. See: https://nextjs.org/docs/messages/next-image-unconfigured-host`,\n };\n}\n\ntype ImageProps = {\n src: string | StaticImageData;\n alt: string;\n width?: number;\n height?: number;\n fill?: boolean;\n priority?: boolean;\n quality?: number;\n placeholder?: \"blur\" | \"empty\";\n blurDataURL?: string;\n loader?: (params: { src: string; width: number; quality?: number }) => string;\n sizes?: string;\n className?: string;\n style?: React.CSSProperties;\n onLoad?: React.ReactEventHandler<HTMLImageElement>;\n /** @deprecated Use onLoad instead. Still supported for migration compat. */\n onLoadingComplete?: (img: HTMLImageElement) => void;\n onError?: React.ReactEventHandler<HTMLImageElement>;\n onClick?: React.MouseEventHandler<HTMLImageElement>;\n id?: string;\n // Accept and ignore Next.js-specific props that don't apply\n unoptimized?: boolean;\n overrideSrc?: string;\n loading?: \"lazy\" | \"eager\";\n};\n\n/**\n * Sanitize a blurDataURL to prevent CSS injection.\n *\n * A crafted data URL containing `)` can break out of the `url()` CSS function,\n * allowing injection of arbitrary CSS properties or rules. Characters like `{`,\n * `}`, and `\\` can also assist in crafting injection payloads.\n *\n * This validates the URL starts with `data:image/` and rejects characters that\n * could escape the `url()` context. Semicolons are allowed since they're part\n * of valid data URLs (`data:image/png;base64,...`) and harmless inside `url()`.\n *\n * Returns undefined for invalid URLs, which causes the blur placeholder to be\n * skipped gracefully.\n */\nfunction sanitizeBlurDataURL(url: string): string | undefined {\n // Must be a data: image URL\n if (!url.startsWith(\"data:image/\")) return undefined;\n // Reject characters that can break out of CSS url():\n // ) - closes url()\n // ( - could open nested functions\n // { } - CSS rule boundaries\n // \\ - CSS escape sequences\n // newlines - break CSS parsing\n if (/[)(}{\\\\'\"\\n\\r]/.test(url)) return undefined;\n return url;\n}\n\n/**\n * Determine if a src is a remote URL (CDN-optimizable) or local.\n */\nfunction isRemoteUrl(src: string): boolean {\n return src.startsWith(\"http://\") || src.startsWith(\"https://\") || src.startsWith(\"//\");\n}\n\n/**\n * Resolve src, width, height, blurDataURL from Image props (string or StaticImageData).\n * Shared by the Image component and getImageProps to keep behavior in sync.\n */\nfunction resolveImageSource(v: {\n src: string | StaticImageData;\n width?: number;\n height?: number;\n blurDataURL?: string;\n}): { src: string; width?: number; height?: number; blurDataURL?: string } {\n const src = typeof v.src === \"string\" ? v.src : v.src.src;\n const imgWidth = v.width ?? (typeof v.src === \"object\" ? v.src.width : undefined);\n const imgHeight = v.height ?? (typeof v.src === \"object\" ? v.src.height : undefined);\n const imgBlurDataURL =\n v.blurDataURL ?? (typeof v.src === \"object\" ? v.src.blurDataURL : undefined);\n return { src, width: imgWidth, height: imgHeight, blurDataURL: imgBlurDataURL };\n}\n\n/**\n * Responsive image widths matching Next.js's device sizes config.\n * These are the breakpoints used for srcSet generation.\n * Configurable via `images.deviceSizes` in next.config.js.\n */\nconst RESPONSIVE_WIDTHS = __imageDeviceSizes;\n\n/**\n * Build a `/_vinext/image` optimization URL.\n *\n * In production (Cloudflare Workers), the worker intercepts this path and uses\n * the Images binding to resize/transcode on the fly. In dev, the Vite dev\n * server handles it as a passthrough (serves the original file).\n */\nexport function imageOptimizationUrl(src: string, width: number, quality: number = 75): string {\n return `/_vinext/image?url=${encodeURIComponent(src)}&w=${width}&q=${quality}`;\n}\n\n/**\n * Generate a srcSet string for responsive images.\n *\n * Each width points to the `/_vinext/image` optimization endpoint so the\n * server can resize and transcode the image. Only includes widths that are\n * <= 2x the original image width to avoid pointless upscaling.\n */\nfunction generateSrcSet(src: string, originalWidth: number, quality: number = 75): string {\n const widths = RESPONSIVE_WIDTHS.filter((w) => w <= originalWidth * 2);\n if (widths.length === 0)\n return `${imageOptimizationUrl(src, originalWidth, quality)} ${originalWidth}w`;\n return widths.map((w) => `${imageOptimizationUrl(src, w, quality)} ${w}w`).join(\", \");\n}\n\nconst Image = forwardRef<HTMLImageElement, ImageProps>(function Image(\n {\n src: srcProp,\n alt,\n width,\n height,\n fill,\n priority,\n quality,\n placeholder,\n blurDataURL,\n loader,\n sizes,\n className,\n style,\n onLoad,\n onLoadingComplete,\n unoptimized: _unoptimized,\n overrideSrc: _overrideSrc,\n loading,\n ...rest\n },\n ref,\n) {\n // Wire onLoadingComplete (deprecated) into onLoad — matches Next.js behavior.\n // onLoad fires first, then onLoadingComplete receives the HTMLImageElement.\n const handleLoad = onLoadingComplete\n ? (e: React.SyntheticEvent<HTMLImageElement>) => {\n onLoad?.(e);\n onLoadingComplete(e.currentTarget);\n }\n : onLoad;\n\n const {\n src,\n width: imgWidth,\n height: imgHeight,\n blurDataURL: imgBlurDataURL,\n } = resolveImageSource({ src: srcProp, width, height, blurDataURL });\n\n // If a custom loader is provided, use basic img with loader URL\n if (loader) {\n const resolvedSrc = loader({ src, width: imgWidth ?? 0, quality: quality ?? 75 });\n return (\n <img\n ref={ref}\n src={resolvedSrc}\n alt={alt}\n width={fill ? undefined : imgWidth}\n height={fill ? undefined : imgHeight}\n loading={priority ? \"eager\" : (loading ?? \"lazy\")}\n decoding=\"async\"\n sizes={sizes}\n className={className}\n onLoad={handleLoad}\n style={\n fill\n ? {\n position: \"absolute\",\n inset: 0,\n width: \"100%\",\n height: \"100%\",\n objectFit: \"cover\",\n ...style,\n }\n : style\n }\n {...rest}\n />\n );\n }\n\n // For remote URLs, validate against remotePatterns then use @unpic/react\n if (isRemoteUrl(src)) {\n const validation = validateRemoteUrl(src);\n if (!validation.allowed) {\n if (__isDev) {\n console.warn(`[next/image] ${validation.reason}`);\n // In dev, render the image but with a warning — matches Next.js dev behavior\n } else {\n // In production, block the image entirely\n console.error(`[next/image] ${validation.reason}`);\n return null;\n }\n }\n\n const sanitizedBlur = imgBlurDataURL ? sanitizeBlurDataURL(imgBlurDataURL) : undefined;\n const bg = placeholder === \"blur\" && sanitizedBlur ? `url(${sanitizedBlur})` : undefined;\n\n if (fill) {\n return (\n <UnpicImage\n src={src}\n alt={alt}\n layout=\"fullWidth\"\n // `priority` is a Next.js concept — translate it to HTML attributes so\n // it is never forwarded to the DOM as a non-boolean attribute, which\n // would trigger React's \"Received `true` for a non-boolean attribute\"\n // warning.\n loading={priority ? \"eager\" : (loading ?? \"lazy\")}\n fetchPriority={priority ? \"high\" : undefined}\n sizes={sizes}\n className={className}\n background={bg}\n onLoad={handleLoad}\n />\n );\n }\n // constrained layout requires width+height or aspectRatio\n if (imgWidth && imgHeight) {\n return (\n <UnpicImage\n src={src}\n alt={alt}\n width={imgWidth}\n height={imgHeight}\n layout=\"constrained\"\n // Same translation as above — never pass `priority` to the DOM.\n loading={priority ? \"eager\" : (loading ?? \"lazy\")}\n fetchPriority={priority ? \"high\" : undefined}\n sizes={sizes}\n className={className}\n background={bg}\n onLoad={handleLoad}\n />\n );\n }\n // Fall through to basic <img> if dimensions not provided\n // (unpic requires them for constrained layout)\n }\n\n // Route local images through the /_vinext/image optimization endpoint.\n // In production on Cloudflare Workers, this resizes and transcodes via\n // the Images binding. In dev, it serves the original file as a passthrough.\n // When `unoptimized` is true, bypass the endpoint entirely (Next.js compat).\n // SVG sources auto-skip unless dangerouslyAllowSVG is enabled, matching\n // Next.js behavior where .svg triggers unoptimized=true by default.\n const imgQuality = quality ?? 75;\n const isSvg = src.endsWith(\".svg\");\n const skipOptimization = _unoptimized === true || (isSvg && !__dangerouslyAllowSVG);\n\n // Build srcSet for responsive local images (common breakpoints).\n // Each entry points to /_vinext/image with the appropriate width.\n const srcSet =\n imgWidth && !fill && !skipOptimization\n ? generateSrcSet(src, imgWidth, imgQuality)\n : imgWidth && !fill\n ? RESPONSIVE_WIDTHS.filter((w) => w <= imgWidth * 2)\n .map((w) => `${src} ${w}w`)\n .join(\", \") || `${src} ${imgWidth}w`\n : undefined;\n\n // The main `src` also goes through the optimization endpoint. Use the\n // declared width (or the first responsive width as fallback).\n const optimizedSrc = skipOptimization\n ? src\n : imgWidth\n ? imageOptimizationUrl(src, imgWidth, imgQuality)\n : imageOptimizationUrl(src, RESPONSIVE_WIDTHS[0], imgQuality);\n\n // Blur placeholder: show a low-quality background while the image loads.\n // Sanitize blurDataURL to prevent CSS injection via crafted data URLs.\n const sanitizedLocalBlur = imgBlurDataURL ? sanitizeBlurDataURL(imgBlurDataURL) : undefined;\n const blurStyle =\n placeholder === \"blur\" && sanitizedLocalBlur\n ? {\n backgroundImage: `url(${sanitizedLocalBlur})`,\n backgroundSize: \"cover\",\n backgroundRepeat: \"no-repeat\",\n backgroundPosition: \"center\",\n }\n : undefined;\n\n // For local images, render a standard <img> tag with srcSet and blur support.\n // The src and srcSet point to the /_vinext/image optimization endpoint.\n return (\n <img\n ref={ref}\n src={optimizedSrc}\n alt={alt}\n width={fill ? undefined : imgWidth}\n height={fill ? undefined : imgHeight}\n loading={priority ? \"eager\" : (loading ?? \"lazy\")}\n fetchPriority={priority ? \"high\" : undefined}\n decoding=\"async\"\n srcSet={srcSet}\n sizes={sizes ?? (fill ? \"100vw\" : undefined)}\n className={className}\n data-nimg={fill ? \"fill\" : \"1\"}\n onLoad={handleLoad}\n style={\n fill\n ? {\n position: \"absolute\",\n inset: 0,\n width: \"100%\",\n height: \"100%\",\n objectFit: \"cover\",\n ...blurStyle,\n ...style,\n }\n : { ...blurStyle, ...style }\n }\n {...rest}\n />\n );\n});\n\n/**\n * getImageProps — for advanced use cases (picture elements, background images).\n * Returns the props that would be passed to the underlying <img> element.\n */\nexport function getImageProps(props: ImageProps): {\n props: React.ImgHTMLAttributes<HTMLImageElement>;\n} {\n const {\n src: srcProp,\n alt,\n width,\n height,\n fill,\n priority,\n quality: _quality,\n placeholder,\n blurDataURL: blurDataURLProp,\n loader,\n sizes,\n className,\n style,\n onLoad: _onLoad,\n onLoadingComplete: _onLoadingComplete,\n unoptimized: _unoptimized,\n overrideSrc: _overrideSrc,\n loading,\n ...rest\n } = props;\n\n const {\n src,\n width: imgWidth,\n height: imgHeight,\n blurDataURL: imgBlurDataURL,\n } = resolveImageSource({ src: srcProp, width, height, blurDataURL: blurDataURLProp });\n\n // Validate remote URLs against configured patterns\n let blockedInProd = false;\n if (isRemoteUrl(src)) {\n const validation = validateRemoteUrl(src);\n if (!validation.allowed) {\n if (__isDev) {\n console.warn(`[next/image] ${validation.reason}`);\n } else {\n console.error(`[next/image] ${validation.reason}`);\n blockedInProd = true;\n }\n }\n }\n\n // Resolve src through custom loader if provided\n const imgQuality = _quality ?? 75;\n const resolvedSrc = blockedInProd\n ? \"\"\n : loader\n ? loader({ src, width: imgWidth ?? 0, quality: imgQuality })\n : src;\n\n // For local images (no loader, not remote), route through optimization endpoint.\n // When `unoptimized` is true, bypass the endpoint entirely (Next.js compat).\n // SVG sources auto-skip unless dangerouslyAllowSVG is enabled.\n const isSvg = resolvedSrc.endsWith(\".svg\");\n const skipOpt =\n _unoptimized === true ||\n (isSvg && !__dangerouslyAllowSVG) ||\n blockedInProd ||\n !!loader ||\n isRemoteUrl(resolvedSrc);\n const optimizedSrc = skipOpt\n ? resolvedSrc\n : imgWidth\n ? imageOptimizationUrl(resolvedSrc, imgWidth, imgQuality)\n : imageOptimizationUrl(resolvedSrc, RESPONSIVE_WIDTHS[0], imgQuality);\n\n // Build srcSet for local images — each width points to /_vinext/image\n const srcSet =\n imgWidth && !fill && !isRemoteUrl(resolvedSrc) && !loader && !skipOpt\n ? generateSrcSet(resolvedSrc, imgWidth, imgQuality)\n : undefined;\n\n // Blur placeholder styles — sanitize to prevent CSS injection\n const sanitizedBlurURL = imgBlurDataURL ? sanitizeBlurDataURL(imgBlurDataURL) : undefined;\n const blurStyle =\n placeholder === \"blur\" && sanitizedBlurURL\n ? {\n backgroundImage: `url(${sanitizedBlurURL})`,\n backgroundSize: \"cover\",\n backgroundRepeat: \"no-repeat\" as const,\n backgroundPosition: \"center\" as const,\n }\n : undefined;\n\n return {\n props: {\n src: optimizedSrc,\n alt,\n width: fill ? undefined : imgWidth,\n height: fill ? undefined : imgHeight,\n loading: priority ? \"eager\" : (loading ?? \"lazy\"),\n fetchPriority: priority ? (\"high\" as const) : undefined,\n decoding: \"async\" as const,\n srcSet,\n sizes: sizes ?? (fill ? \"100vw\" : undefined),\n className,\n \"data-nimg\": fill ? \"fill\" : \"1\",\n style: fill\n ? {\n position: \"absolute\" as const,\n inset: 0,\n width: \"100%\",\n height: \"100%\",\n objectFit: \"cover\" as const,\n ...blurStyle,\n ...style,\n }\n : { ...blurStyle, ...style },\n ...rest,\n } as React.ImgHTMLAttributes<HTMLImageElement>,\n };\n}\n\nexport default Image;\n"],"mappings":"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"}
1
+ {"version":3,"file":"image.js","names":["UnpicImage"],"sources":["../../src/shims/image.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * next/image shim\n *\n * Translates Next.js Image props to @unpic/react Image component.\n * @unpic/react auto-detects CDN from URL and uses native transforms.\n * For local images (relative paths), routes through `/_vinext/image`\n * for server-side optimization (resize, format negotiation, quality).\n *\n * Remote images are validated against `images.remotePatterns` and\n * `images.domains` from next.config.js. Unmatched URLs are blocked\n * in production and warn in development, matching Next.js behavior.\n */\nimport React, { forwardRef, useEffect, useLayoutEffect, useRef } from \"react\";\nimport { Image as UnpicImage } from \"@unpic/react\";\nimport { hasRemoteMatch, type RemotePattern } from \"./image-config.js\";\nimport { useMergedRef } from \"./use-merged-ref.js\";\n\nexport type StaticImageData = {\n src: string;\n height: number;\n width: number;\n blurDataURL?: string;\n};\n\n/**\n * Image config injected at build time via Vite define.\n * Serialized as JSON — parsed once at module level.\n */\nconst __imageRemotePatterns: RemotePattern[] = (() => {\n try {\n return JSON.parse(process.env.__VINEXT_IMAGE_REMOTE_PATTERNS ?? \"[]\");\n } catch {\n return [];\n }\n})();\nconst __imageDomains: string[] = (() => {\n try {\n return JSON.parse(process.env.__VINEXT_IMAGE_DOMAINS ?? \"[]\");\n } catch {\n return [];\n }\n})();\nconst __hasImageConfig = __imageRemotePatterns.length > 0 || __imageDomains.length > 0;\nconst __isDev = process.env.NODE_ENV !== \"production\";\nconst __imageDeviceSizes: number[] = (() => {\n try {\n return JSON.parse(\n process.env.__VINEXT_IMAGE_DEVICE_SIZES ?? \"[640,750,828,1080,1200,1920,2048,3840]\",\n );\n } catch {\n return [640, 750, 828, 1080, 1200, 1920, 2048, 3840];\n }\n})();\n/**\n * Whether dangerouslyAllowSVG is enabled in next.config.js.\n * When false (default), .svg sources auto-skip the optimization endpoint\n * and are served directly, matching Next.js behavior.\n * When true, .svg sources are routed through the optimizer (served as-is\n * with security headers).\n */\nconst __dangerouslyAllowSVG = process.env.__VINEXT_IMAGE_DANGEROUSLY_ALLOW_SVG === \"true\";\n/**\n * Validate that a remote URL is allowed by the configured remote patterns.\n * Returns true if the URL is allowed, false otherwise.\n *\n * When no remotePatterns/domains are configured, all remote URLs are allowed\n * (backwards-compatible — user hasn't opted into restriction).\n *\n * When patterns ARE configured, only matching URLs are allowed.\n * In development, non-matching URLs produce a console warning.\n * In production, non-matching URLs are blocked (src replaced with empty string).\n */\nfunction validateRemoteUrl(src: string): { allowed: boolean; reason?: string } {\n if (!__hasImageConfig) {\n // No image config — allow everything (backwards-compatible)\n return { allowed: true };\n }\n\n let url: URL;\n try {\n url = new URL(src, \"http://n\");\n } catch {\n return { allowed: false, reason: `Invalid URL: ${src}` };\n }\n\n if (hasRemoteMatch(__imageDomains, __imageRemotePatterns, url)) {\n return { allowed: true };\n }\n\n return {\n allowed: false,\n reason: `Image URL \"${src}\" is not configured in images.remotePatterns or images.domains in next.config.js. See: https://nextjs.org/docs/messages/next-image-unconfigured-host`,\n };\n}\n\n/**\n * A version of useLayoutEffect that doesn't warn during SSR.\n * Do not rename this to \"isomorphic layout effect\". There is no such thing as\n * an isomorphic Layout Effect since there is no Layout on the server.\n * Ported from Next.js: https://github.com/vercel/next.js/pull/93209\n */\nconst useNonWarningLayoutEffect = typeof window === \"undefined\" ? useEffect : useLayoutEffect;\n\n/**\n * Create a synthetic React load event for replaying onLoad/onLoadingComplete\n * during hydration when the image already completed loading.\n *\n * This function creates a native Event(\"load\") via the DOM Event constructor\n * and must only be called in a browser context (client-side layout effect).\n * It mirrors the pattern used in Next.js `handleLoading`.\n */\nfunction createSyntheticLoadEvent(img: HTMLImageElement): React.SyntheticEvent<HTMLImageElement> {\n const nativeEvent = new Event(\"load\");\n Object.defineProperty(nativeEvent, \"target\", { writable: false, value: img });\n let prevented = false;\n let stopped = false;\n return {\n bubbles: nativeEvent.bubbles,\n cancelable: nativeEvent.cancelable,\n currentTarget: img,\n defaultPrevented: false,\n eventPhase: nativeEvent.eventPhase,\n isTrusted: false,\n nativeEvent,\n target: img,\n timeStamp: nativeEvent.timeStamp,\n type: \"load\",\n isDefaultPrevented: () => prevented,\n isPropagationStopped: () => stopped,\n persist: () => {},\n preventDefault: () => {\n prevented = true;\n nativeEvent.preventDefault();\n },\n stopPropagation: () => {\n stopped = true;\n nativeEvent.stopPropagation();\n },\n };\n}\n\ntype ImageProps = {\n src: string | StaticImageData;\n alt: string;\n width?: number;\n height?: number;\n fill?: boolean;\n priority?: boolean;\n quality?: number;\n placeholder?: \"blur\" | \"empty\";\n blurDataURL?: string;\n loader?: (params: { src: string; width: number; quality?: number }) => string;\n sizes?: string;\n className?: string;\n style?: React.CSSProperties;\n onLoad?: React.ReactEventHandler<HTMLImageElement>;\n /** @deprecated Use onLoad instead. Still supported for migration compat. */\n onLoadingComplete?: (img: HTMLImageElement) => void;\n onError?: React.ReactEventHandler<HTMLImageElement>;\n onClick?: React.MouseEventHandler<HTMLImageElement>;\n id?: string;\n // Accept and ignore Next.js-specific props that don't apply\n unoptimized?: boolean;\n overrideSrc?: string;\n loading?: \"lazy\" | \"eager\";\n};\n\n/**\n * Sanitize a blurDataURL to prevent CSS injection.\n *\n * A crafted data URL containing `)` can break out of the `url()` CSS function,\n * allowing injection of arbitrary CSS properties or rules. Characters like `{`,\n * `}`, and `\\` can also assist in crafting injection payloads.\n *\n * This validates the URL starts with `data:image/` and rejects characters that\n * could escape the `url()` context. Semicolons are allowed since they're part\n * of valid data URLs (`data:image/png;base64,...`) and harmless inside `url()`.\n *\n * Returns undefined for invalid URLs, which causes the blur placeholder to be\n * skipped gracefully.\n */\nfunction sanitizeBlurDataURL(url: string): string | undefined {\n // Must be a data: image URL\n if (!url.startsWith(\"data:image/\")) return undefined;\n // Reject characters that can break out of CSS url():\n // ) - closes url()\n // ( - could open nested functions\n // { } - CSS rule boundaries\n // \\ - CSS escape sequences\n // newlines - break CSS parsing\n if (/[)(}{\\\\'\"\\n\\r]/.test(url)) return undefined;\n return url;\n}\n\n/**\n * Determine if a src is a remote URL (CDN-optimizable) or local.\n */\nfunction isRemoteUrl(src: string): boolean {\n return src.startsWith(\"http://\") || src.startsWith(\"https://\") || src.startsWith(\"//\");\n}\n\n/**\n * Resolve src, width, height, blurDataURL from Image props (string or StaticImageData).\n * Shared by the Image component and getImageProps to keep behavior in sync.\n */\nfunction resolveImageSource(v: {\n src: string | StaticImageData;\n width?: number;\n height?: number;\n blurDataURL?: string;\n}): { src: string; width?: number; height?: number; blurDataURL?: string } {\n const src = typeof v.src === \"string\" ? v.src : v.src.src;\n const imgWidth = v.width ?? (typeof v.src === \"object\" ? v.src.width : undefined);\n const imgHeight = v.height ?? (typeof v.src === \"object\" ? v.src.height : undefined);\n const imgBlurDataURL =\n v.blurDataURL ?? (typeof v.src === \"object\" ? v.src.blurDataURL : undefined);\n return { src, width: imgWidth, height: imgHeight, blurDataURL: imgBlurDataURL };\n}\n\n/**\n * Responsive image widths matching Next.js's device sizes config.\n * These are the breakpoints used for srcSet generation.\n * Configurable via `images.deviceSizes` in next.config.js.\n */\nconst RESPONSIVE_WIDTHS = __imageDeviceSizes;\n\n/**\n * Build a `/_vinext/image` optimization URL.\n *\n * In production (Cloudflare Workers), the worker intercepts this path and uses\n * the Images binding to resize/transcode on the fly. In dev, the Vite dev\n * server handles it as a passthrough (serves the original file).\n */\nexport function imageOptimizationUrl(src: string, width: number, quality: number = 75): string {\n return `/_vinext/image?url=${encodeURIComponent(src)}&w=${width}&q=${quality}`;\n}\n\n/**\n * Generate a srcSet string for responsive images.\n *\n * Each width points to the `/_vinext/image` optimization endpoint so the\n * server can resize and transcode the image. Only includes widths that are\n * <= 2x the original image width to avoid pointless upscaling.\n */\nfunction generateSrcSet(src: string, originalWidth: number, quality: number = 75): string {\n const widths = RESPONSIVE_WIDTHS.filter((w) => w <= originalWidth * 2);\n if (widths.length === 0)\n return `${imageOptimizationUrl(src, originalWidth, quality)} ${originalWidth}w`;\n return widths.map((w) => `${imageOptimizationUrl(src, w, quality)} ${w}w`).join(\", \");\n}\n\nconst Image = forwardRef<HTMLImageElement, ImageProps>(function Image(\n {\n src: srcProp,\n alt,\n width,\n height,\n fill,\n priority,\n quality,\n placeholder,\n blurDataURL,\n loader,\n sizes,\n className,\n style,\n onLoad,\n onLoadingComplete,\n onError,\n unoptimized: _unoptimized,\n overrideSrc: _overrideSrc,\n loading,\n ...rest\n },\n ref,\n) {\n // Dedup refs: ensure onLoad and onError fire at most once per src per mount.\n // Matches Next.js behavior — prevents double-firing from React re-renders,\n // strict-mode double-invocation, or state updates inside the handler itself.\n // Ported from Next.js: https://github.com/vercel/next.js/pull/93209\n const lastLoadedSrcRef = useRef<string | undefined>(undefined);\n const lastErrorSrcRef = useRef<string | undefined>(undefined);\n\n // Hydration-level onError replay: when an image fails to load during SSR\n // streaming or initial HTML parse (before React hydrates), the native browser\n // error event is lost. Re-trigger it via `img.src = img.src` in a layout\n // effect once hydration completes, mirroring the upstream Next.js fix.\n // Ported from Next.js: https://github.com/vercel/next.js/pull/93209\n const didInsertRef = useRef(false);\n const imgElementRef = useRef<HTMLImageElement | null>(null);\n\n // Merge forwarded ref with internal img ref for layout effect access.\n const mergedRef = useMergedRef(ref, imgElementRef);\n\n // Stable refs for onLoad / onError / onLoadingComplete so the layout effect\n // does not re-run (and re-assign img.src) when handler identity changes.\n // Ported from Next.js: https://github.com/vercel/next.js/pull/93209\n //\n // IMPORTANT: The useRef+useEffect sync pattern has a subtle timing gap:\n // during the first render, onLoadRef.current holds the initial value from\n // useRef(onLoad), and the useEffect to sync it runs AFTER the layout effect.\n // This means on first mount the layout effect reads the correct initial\n // value (passed to useRef). If someone changes useRef(onLoad) to\n // useRef(undefined), the layout effect would read undefined on first mount.\n const onLoadRef = useRef(onLoad);\n useEffect(() => {\n onLoadRef.current = onLoad;\n }, [onLoad]);\n const onErrorRef = useRef(onError);\n useEffect(() => {\n onErrorRef.current = onError;\n }, [onError]);\n const onLoadingCompleteRef = useRef(onLoadingComplete);\n useEffect(() => {\n onLoadingCompleteRef.current = onLoadingComplete;\n }, [onLoadingComplete]);\n\n const {\n src,\n width: imgWidth,\n height: imgHeight,\n blurDataURL: imgBlurDataURL,\n } = resolveImageSource({ src: srcProp, width, height, blurDataURL });\n\n useNonWarningLayoutEffect(() => {\n if (!didInsertRef.current && imgElementRef.current !== null) {\n const img = imgElementRef.current;\n // Replay error events lost during SSR/hydration.\n if (onErrorRef.current) {\n // eslint-disable-next-line no-self-assign\n img.src = img.src;\n }\n // Replay onLoad for images that completed loading before React hydrated\n // (e.g. SSR streaming where the image arrives and renders before hydration\n // finishes). Without this, onLoad never fires for those images.\n //\n // img.complete is true for both successfully-loaded and errored images\n // (the HTML spec defines complete as true when the browser finished\n // fetching, regardless of outcome). We must check naturalWidth > 0 to\n // distinguish success from error — a failed image has naturalWidth === 0.\n // Ported from Next.js: https://github.com/vercel/next.js/pull/93209\n if (img.complete && img.naturalWidth > 0) {\n const currentOnLoad = onLoadRef.current;\n const currentOnLoadingComplete = onLoadingCompleteRef.current;\n if (currentOnLoad || currentOnLoadingComplete) {\n // Dedup — fire at most once per src per mount, matching onLoad dedup\n if (lastLoadedSrcRef.current !== src) {\n lastLoadedSrcRef.current = src;\n // Create a synthetic React event with the expected shape.\n // next/image uses a similar pattern in `handleLoading`.\n const syntheticEvent = createSyntheticLoadEvent(img);\n currentOnLoad?.(syntheticEvent);\n currentOnLoadingComplete?.(img);\n }\n }\n }\n didInsertRef.current = true;\n }\n }, [placeholder, sizes, _unoptimized]);\n\n // Wire onLoadingComplete (deprecated) into onLoad — matches Next.js behavior.\n // onLoad fires first, then onLoadingComplete receives the HTMLImageElement.\n const handleLoad = onLoadingComplete\n ? (e: React.SyntheticEvent<HTMLImageElement>) => {\n if (lastLoadedSrcRef.current === src) return;\n lastLoadedSrcRef.current = src;\n onLoad?.(e);\n onLoadingComplete(e.currentTarget);\n }\n : onLoad\n ? (e: React.SyntheticEvent<HTMLImageElement>) => {\n if (lastLoadedSrcRef.current === src) return;\n lastLoadedSrcRef.current = src;\n onLoad(e);\n }\n : undefined;\n\n const handleError = onError\n ? (e: React.SyntheticEvent<HTMLImageElement>) => {\n if (lastErrorSrcRef.current === src) return;\n lastErrorSrcRef.current = src;\n onError(e);\n }\n : undefined;\n\n // If a custom loader is provided, use basic img with loader URL\n if (loader) {\n const resolvedSrc = loader({ src, width: imgWidth ?? 0, quality: quality ?? 75 });\n return (\n <img\n ref={mergedRef}\n src={resolvedSrc}\n alt={alt}\n width={fill ? undefined : imgWidth}\n height={fill ? undefined : imgHeight}\n loading={priority ? \"eager\" : (loading ?? \"lazy\")}\n decoding=\"async\"\n sizes={sizes}\n className={className}\n onLoad={handleLoad}\n onError={handleError}\n style={\n fill\n ? {\n position: \"absolute\",\n inset: 0,\n width: \"100%\",\n height: \"100%\",\n objectFit: \"cover\",\n ...style,\n }\n : style\n }\n {...rest}\n />\n );\n }\n\n // For remote URLs, validate against remotePatterns then use @unpic/react\n if (isRemoteUrl(src)) {\n const validation = validateRemoteUrl(src);\n if (!validation.allowed) {\n if (__isDev) {\n console.warn(`[next/image] ${validation.reason}`);\n // In dev, render the image but with a warning — matches Next.js dev behavior\n } else {\n // In production, block the image entirely\n console.error(`[next/image] ${validation.reason}`);\n return null;\n }\n }\n\n const sanitizedBlur = imgBlurDataURL ? sanitizeBlurDataURL(imgBlurDataURL) : undefined;\n const bg = placeholder === \"blur\" && sanitizedBlur ? `url(${sanitizedBlur})` : undefined;\n\n if (fill) {\n return (\n <UnpicImage\n src={src}\n alt={alt}\n layout=\"fullWidth\"\n // `priority` is a Next.js concept — translate it to HTML attributes so\n // it is never forwarded to the DOM as a non-boolean attribute, which\n // would trigger React's \"Received `true` for a non-boolean attribute\"\n // warning.\n loading={priority ? \"eager\" : (loading ?? \"lazy\")}\n fetchPriority={priority ? \"high\" : undefined}\n sizes={sizes}\n className={className}\n background={bg}\n onLoad={handleLoad}\n onError={handleError}\n ref={mergedRef}\n />\n );\n }\n // constrained layout requires width+height or aspectRatio\n if (imgWidth && imgHeight) {\n return (\n <UnpicImage\n src={src}\n alt={alt}\n width={imgWidth}\n height={imgHeight}\n layout=\"constrained\"\n // Same translation as above — never pass `priority` to the DOM.\n loading={priority ? \"eager\" : (loading ?? \"lazy\")}\n fetchPriority={priority ? \"high\" : undefined}\n sizes={sizes}\n className={className}\n background={bg}\n onLoad={handleLoad}\n onError={handleError}\n ref={mergedRef}\n />\n );\n }\n // Fall through to basic <img> if dimensions not provided\n // (unpic requires them for constrained layout)\n }\n\n // Route local images through the /_vinext/image optimization endpoint.\n // In production on Cloudflare Workers, this resizes and transcodes via\n // the Images binding. In dev, it serves the original file as a passthrough.\n // When `unoptimized` is true, bypass the endpoint entirely (Next.js compat).\n // SVG sources auto-skip unless dangerouslyAllowSVG is enabled, matching\n // Next.js behavior where .svg triggers unoptimized=true by default.\n const imgQuality = quality ?? 75;\n const isSvg = src.endsWith(\".svg\");\n const skipOptimization = _unoptimized === true || (isSvg && !__dangerouslyAllowSVG);\n\n // Build srcSet for responsive local images (common breakpoints).\n // Each entry points to /_vinext/image with the appropriate width.\n const srcSet =\n imgWidth && !fill && !skipOptimization\n ? generateSrcSet(src, imgWidth, imgQuality)\n : imgWidth && !fill\n ? RESPONSIVE_WIDTHS.filter((w) => w <= imgWidth * 2)\n .map((w) => `${src} ${w}w`)\n .join(\", \") || `${src} ${imgWidth}w`\n : undefined;\n\n // The main `src` also goes through the optimization endpoint. Use the\n // declared width (or the first responsive width as fallback).\n const optimizedSrc = skipOptimization\n ? src\n : imgWidth\n ? imageOptimizationUrl(src, imgWidth, imgQuality)\n : imageOptimizationUrl(src, RESPONSIVE_WIDTHS[0], imgQuality);\n\n // Blur placeholder: show a low-quality background while the image loads.\n // Sanitize blurDataURL to prevent CSS injection via crafted data URLs.\n const sanitizedLocalBlur = imgBlurDataURL ? sanitizeBlurDataURL(imgBlurDataURL) : undefined;\n const blurStyle =\n placeholder === \"blur\" && sanitizedLocalBlur\n ? {\n backgroundImage: `url(${sanitizedLocalBlur})`,\n backgroundSize: \"cover\",\n backgroundRepeat: \"no-repeat\",\n backgroundPosition: \"center\",\n }\n : undefined;\n\n // For local images, render a standard <img> tag with srcSet and blur support.\n // The src and srcSet point to the /_vinext/image optimization endpoint.\n return (\n <img\n ref={mergedRef}\n src={optimizedSrc}\n alt={alt}\n width={fill ? undefined : imgWidth}\n height={fill ? undefined : imgHeight}\n loading={priority ? \"eager\" : (loading ?? \"lazy\")}\n fetchPriority={priority ? \"high\" : undefined}\n decoding=\"async\"\n srcSet={srcSet}\n sizes={sizes ?? (fill ? \"100vw\" : undefined)}\n className={className}\n data-nimg={fill ? \"fill\" : \"1\"}\n onLoad={handleLoad}\n onError={handleError}\n style={\n fill\n ? {\n position: \"absolute\",\n inset: 0,\n width: \"100%\",\n height: \"100%\",\n objectFit: \"cover\",\n ...blurStyle,\n ...style,\n }\n : { ...blurStyle, ...style }\n }\n {...rest}\n />\n );\n});\n\n/**\n * getImageProps — for advanced use cases (picture elements, background images).\n * Returns the props that would be passed to the underlying <img> element.\n */\nexport function getImageProps(props: ImageProps): {\n props: React.ImgHTMLAttributes<HTMLImageElement>;\n} {\n const {\n src: srcProp,\n alt,\n width,\n height,\n fill,\n priority,\n quality: _quality,\n placeholder,\n blurDataURL: blurDataURLProp,\n loader,\n sizes,\n className,\n style,\n onLoad: _onLoad,\n onLoadingComplete: _onLoadingComplete,\n unoptimized: _unoptimized,\n overrideSrc: _overrideSrc,\n loading,\n ...rest\n } = props;\n\n const {\n src,\n width: imgWidth,\n height: imgHeight,\n blurDataURL: imgBlurDataURL,\n } = resolveImageSource({ src: srcProp, width, height, blurDataURL: blurDataURLProp });\n\n // Validate remote URLs against configured patterns\n let blockedInProd = false;\n if (isRemoteUrl(src)) {\n const validation = validateRemoteUrl(src);\n if (!validation.allowed) {\n if (__isDev) {\n console.warn(`[next/image] ${validation.reason}`);\n } else {\n console.error(`[next/image] ${validation.reason}`);\n blockedInProd = true;\n }\n }\n }\n\n // Resolve src through custom loader if provided\n const imgQuality = _quality ?? 75;\n const resolvedSrc = blockedInProd\n ? \"\"\n : loader\n ? loader({ src, width: imgWidth ?? 0, quality: imgQuality })\n : src;\n\n // For local images (no loader, not remote), route through optimization endpoint.\n // When `unoptimized` is true, bypass the endpoint entirely (Next.js compat).\n // SVG sources auto-skip unless dangerouslyAllowSVG is enabled.\n const isSvg = resolvedSrc.endsWith(\".svg\");\n const skipOpt =\n _unoptimized === true ||\n (isSvg && !__dangerouslyAllowSVG) ||\n blockedInProd ||\n !!loader ||\n isRemoteUrl(resolvedSrc);\n const optimizedSrc = skipOpt\n ? resolvedSrc\n : imgWidth\n ? imageOptimizationUrl(resolvedSrc, imgWidth, imgQuality)\n : imageOptimizationUrl(resolvedSrc, RESPONSIVE_WIDTHS[0], imgQuality);\n\n // Build srcSet for local images — each width points to /_vinext/image\n const srcSet =\n imgWidth && !fill && !isRemoteUrl(resolvedSrc) && !loader && !skipOpt\n ? generateSrcSet(resolvedSrc, imgWidth, imgQuality)\n : undefined;\n\n // Blur placeholder styles — sanitize to prevent CSS injection\n const sanitizedBlurURL = imgBlurDataURL ? sanitizeBlurDataURL(imgBlurDataURL) : undefined;\n const blurStyle =\n placeholder === \"blur\" && sanitizedBlurURL\n ? {\n backgroundImage: `url(${sanitizedBlurURL})`,\n backgroundSize: \"cover\",\n backgroundRepeat: \"no-repeat\" as const,\n backgroundPosition: \"center\" as const,\n }\n : undefined;\n\n return {\n props: {\n src: optimizedSrc,\n alt,\n width: fill ? undefined : imgWidth,\n height: fill ? undefined : imgHeight,\n loading: priority ? \"eager\" : (loading ?? \"lazy\"),\n fetchPriority: priority ? (\"high\" as const) : undefined,\n decoding: \"async\" as const,\n srcSet,\n sizes: sizes ?? (fill ? \"100vw\" : undefined),\n className,\n \"data-nimg\": fill ? \"fill\" : \"1\",\n style: fill\n ? {\n position: \"absolute\" as const,\n inset: 0,\n width: \"100%\",\n height: \"100%\",\n objectFit: \"cover\" as const,\n ...blurStyle,\n ...style,\n }\n : { ...blurStyle, ...style },\n ...rest,\n } as React.ImgHTMLAttributes<HTMLImageElement>,\n };\n}\n\nexport default Image;\n"],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ //#region src/shims/internal/make-hanging-promise.d.ts
2
+ /**
3
+ * makeHangingPromise — returns a promise that never resolves during prerendering.
4
+ *
5
+ * When prerendering, `unstable_io()` must return a hanging promise to prevent
6
+ * React from executing past the IO boundary. The promise never resolves—it only
7
+ * rejects if the render signal is aborted (e.g., due to a dynamic error or
8
+ * cache-fill completion).
9
+ *
10
+ * Ported from Next.js: packages/next/src/server/dynamic-rendering-utils.ts
11
+ * https://github.com/vercel/next.js/blob/canary/packages/next/src/server/dynamic-rendering-utils.ts
12
+ */
13
+ declare function makeHangingPromise<T>(signal: AbortSignal, route: string, expression: string): Promise<T>;
14
+ //#endregion
15
+ export { makeHangingPromise };
16
+ //# sourceMappingURL=make-hanging-promise.d.ts.map
@@ -0,0 +1,46 @@
1
+ //#region src/shims/internal/make-hanging-promise.ts
2
+ /**
3
+ * makeHangingPromise — returns a promise that never resolves during prerendering.
4
+ *
5
+ * When prerendering, `unstable_io()` must return a hanging promise to prevent
6
+ * React from executing past the IO boundary. The promise never resolves—it only
7
+ * rejects if the render signal is aborted (e.g., due to a dynamic error or
8
+ * cache-fill completion).
9
+ *
10
+ * Ported from Next.js: packages/next/src/server/dynamic-rendering-utils.ts
11
+ * https://github.com/vercel/next.js/blob/canary/packages/next/src/server/dynamic-rendering-utils.ts
12
+ */
13
+ var HangingPromiseRejectionError = class extends Error {
14
+ constructor(route, expression) {
15
+ super(`Route ${route} used ${expression} during prerendering but the render was aborted. This is expected when prerendering is cut short (e.g. due to a dynamic access).`);
16
+ this.name = "HangingPromiseRejectionError";
17
+ }
18
+ };
19
+ const abortListenersBySignal = /* @__PURE__ */ new WeakMap();
20
+ function suppressUnhandledRejection() {}
21
+ function makeHangingPromise(signal, route, expression) {
22
+ if (signal.aborted) {
23
+ const rejected = Promise.reject(new HangingPromiseRejectionError(route, expression));
24
+ rejected.catch(suppressUnhandledRejection);
25
+ return rejected;
26
+ }
27
+ const hangingPromise = new Promise((_, reject) => {
28
+ const boundRejection = reject.bind(null, new HangingPromiseRejectionError(route, expression));
29
+ const currentListeners = abortListenersBySignal.get(signal);
30
+ if (currentListeners) currentListeners.push(boundRejection);
31
+ else {
32
+ const listeners = [boundRejection];
33
+ abortListenersBySignal.set(signal, listeners);
34
+ signal.addEventListener("abort", () => {
35
+ for (let i = 0; i < listeners.length; i++) listeners[i]();
36
+ listeners.length = 0;
37
+ }, { once: true });
38
+ }
39
+ });
40
+ hangingPromise.catch(suppressUnhandledRejection);
41
+ return hangingPromise;
42
+ }
43
+ //#endregion
44
+ export { makeHangingPromise };
45
+
46
+ //# sourceMappingURL=make-hanging-promise.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"make-hanging-promise.js","names":[],"sources":["../../../src/shims/internal/make-hanging-promise.ts"],"sourcesContent":["/**\n * makeHangingPromise — returns a promise that never resolves during prerendering.\n *\n * When prerendering, `unstable_io()` must return a hanging promise to prevent\n * React from executing past the IO boundary. The promise never resolves—it only\n * rejects if the render signal is aborted (e.g., due to a dynamic error or\n * cache-fill completion).\n *\n * Ported from Next.js: packages/next/src/server/dynamic-rendering-utils.ts\n * https://github.com/vercel/next.js/blob/canary/packages/next/src/server/dynamic-rendering-utils.ts\n */\n\nclass HangingPromiseRejectionError extends Error {\n constructor(route: string, expression: string) {\n super(\n `Route ${route} used ${expression} during prerendering but the render was aborted. ` +\n `This is expected when prerendering is cut short (e.g. due to a dynamic access).`,\n );\n this.name = \"HangingPromiseRejectionError\";\n }\n}\n\nconst abortListenersBySignal = new WeakMap<AbortSignal, (() => void)[]>();\n\nfunction suppressUnhandledRejection(): void {\n // intentionally empty — suppresses \"unhandled rejection\" warnings\n}\n\nexport function makeHangingPromise<T>(\n signal: AbortSignal,\n route: string,\n expression: string,\n): Promise<T> {\n if (signal.aborted) {\n const rejected = Promise.reject(new HangingPromiseRejectionError(route, expression));\n rejected.catch(suppressUnhandledRejection);\n return rejected;\n }\n const hangingPromise = new Promise<T>((_, reject) => {\n const boundRejection = reject.bind(null, new HangingPromiseRejectionError(route, expression));\n const currentListeners = abortListenersBySignal.get(signal);\n if (currentListeners) {\n currentListeners.push(boundRejection);\n } else {\n const listeners = [boundRejection];\n abortListenersBySignal.set(signal, listeners);\n signal.addEventListener(\n \"abort\",\n () => {\n for (let i = 0; i < listeners.length; i++) {\n listeners[i]();\n }\n listeners.length = 0;\n },\n { once: true },\n );\n }\n });\n // Suppress unhandled rejection — the promise is expected to be used with\n // React's use() which handles rejections. If never awaited, the abort\n // rejection is a no-op cleanup.\n hangingPromise.catch(suppressUnhandledRejection);\n return hangingPromise;\n}\n"],"mappings":";;;;;;;;;;;;AAYA,IAAM,+BAAN,cAA2C,MAAM;CAC/C,YAAY,OAAe,YAAoB;AAC7C,QACE,SAAS,MAAM,QAAQ,WAAW,kIAEnC;AACD,OAAK,OAAO;;;AAIhB,MAAM,yCAAyB,IAAI,SAAsC;AAEzE,SAAS,6BAAmC;AAI5C,SAAgB,mBACd,QACA,OACA,YACY;AACZ,KAAI,OAAO,SAAS;EAClB,MAAM,WAAW,QAAQ,OAAO,IAAI,6BAA6B,OAAO,WAAW,CAAC;AACpF,WAAS,MAAM,2BAA2B;AAC1C,SAAO;;CAET,MAAM,iBAAiB,IAAI,SAAY,GAAG,WAAW;EACnD,MAAM,iBAAiB,OAAO,KAAK,MAAM,IAAI,6BAA6B,OAAO,WAAW,CAAC;EAC7F,MAAM,mBAAmB,uBAAuB,IAAI,OAAO;AAC3D,MAAI,iBACF,kBAAiB,KAAK,eAAe;OAChC;GACL,MAAM,YAAY,CAAC,eAAe;AAClC,0BAAuB,IAAI,QAAQ,UAAU;AAC7C,UAAO,iBACL,eACM;AACJ,SAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,IACpC,WAAU,IAAI;AAEhB,cAAU,SAAS;MAErB,EAAE,MAAM,MAAM,CACf;;GAEH;AAIF,gBAAe,MAAM,2BAA2B;AAChD,QAAO"}
@@ -1,8 +1,31 @@
1
1
  import { AsyncLocalStorage } from "node:async_hooks";
2
2
 
3
3
  //#region src/shims/internal/work-unit-async-storage.d.ts
4
- declare const workUnitAsyncStorage: AsyncLocalStorage<unknown>;
5
- declare const requestAsyncStorage: AsyncLocalStorage<unknown>;
4
+ type RequestStore = {
5
+ readonly type: "request";
6
+ };
7
+ type PrerenderStore = {
8
+ readonly type: "prerender" | "prerender-client" | "prerender-runtime"; /** AbortSignal that fires when the prerender is cancelled or completed. */
9
+ readonly renderSignal: AbortSignal; /** Optional route identifier for debugging and error messages. */
10
+ readonly route?: string;
11
+ };
12
+ type CacheStore = {
13
+ readonly type: "cache" | "private-cache" | "unstable-cache";
14
+ };
15
+ type GenerateStaticParamsStore = {
16
+ readonly type: "generate-static-params";
17
+ };
18
+ type PrerenderLegacyStore = {
19
+ readonly type: "prerender-legacy";
20
+ };
21
+ /**
22
+ * Discriminated union of all known work unit types.
23
+ * Matches Next.js's WorkUnitStore: packages/next/src/server/app-render/work-unit-async-storage.external.ts
24
+ */
25
+ type WorkUnitStore = RequestStore | PrerenderStore | CacheStore | GenerateStaticParamsStore | PrerenderLegacyStore;
26
+ type WorkUnitAsyncStorage = AsyncLocalStorage<WorkUnitStore>;
27
+ declare const workUnitAsyncStorage: WorkUnitAsyncStorage;
28
+ declare const requestAsyncStorage: WorkUnitAsyncStorage;
6
29
  //#endregion
7
- export { requestAsyncStorage, workUnitAsyncStorage };
30
+ export { CacheStore, GenerateStaticParamsStore, PrerenderLegacyStore, PrerenderStore, RequestStore, WorkUnitAsyncStorage, WorkUnitStore, requestAsyncStorage, workUnitAsyncStorage };
8
31
  //# sourceMappingURL=work-unit-async-storage.d.ts.map
@@ -4,9 +4,12 @@ import { AsyncLocalStorage } from "node:async_hooks";
4
4
  * Shim for next/dist/server/app-render/work-unit-async-storage.external
5
5
  * and next/dist/client/components/request-async-storage.external
6
6
  *
7
- * Used by: @sentry/nextjs (runtime resolve for request context injection).
8
- * Provides a minimal AsyncLocalStorage-like export that Sentry can detect
9
- * and use without crashing.
7
+ * Tracks the current rendering context type so that dynamic APIs
8
+ * (unstable_io, headers, cookies, etc.) can branch on whether they're
9
+ * inside a request, prerender, cache scope, or other context.
10
+ *
11
+ * Used by: @sentry/nextjs (runtime resolve for request context injection),
12
+ * unstable_io() for hanging-promise behavior during prerendering.
10
13
  */
11
14
  const workUnitAsyncStorage = new AsyncLocalStorage();
12
15
  const requestAsyncStorage = workUnitAsyncStorage;
@@ -1 +1 @@
1
- {"version":3,"file":"work-unit-async-storage.js","names":[],"sources":["../../../src/shims/internal/work-unit-async-storage.ts"],"sourcesContent":["/**\n * Shim for next/dist/server/app-render/work-unit-async-storage.external\n * and next/dist/client/components/request-async-storage.external\n *\n * Used by: @sentry/nextjs (runtime resolve for request context injection).\n * Provides a minimal AsyncLocalStorage-like export that Sentry can detect\n * and use without crashing.\n */\nimport { AsyncLocalStorage } from \"node:async_hooks\";\n\nexport const workUnitAsyncStorage = new AsyncLocalStorage<unknown>();\n\n// Legacy name (Next 13.x–14.x)\nexport const requestAsyncStorage = workUnitAsyncStorage;\n"],"mappings":";;;;;;;;;;AAUA,MAAa,uBAAuB,IAAI,mBAA4B;AAGpE,MAAa,sBAAsB"}
1
+ {"version":3,"file":"work-unit-async-storage.js","names":[],"sources":["../../../src/shims/internal/work-unit-async-storage.ts"],"sourcesContent":["/**\n * Shim for next/dist/server/app-render/work-unit-async-storage.external\n * and next/dist/client/components/request-async-storage.external\n *\n * Tracks the current rendering context type so that dynamic APIs\n * (unstable_io, headers, cookies, etc.) can branch on whether they're\n * inside a request, prerender, cache scope, or other context.\n *\n * Used by: @sentry/nextjs (runtime resolve for request context injection),\n * unstable_io() for hanging-promise behavior during prerendering.\n */\nimport { AsyncLocalStorage } from \"node:async_hooks\";\n\n// ── WorkUnitStore discriminated union ───────────────────────────────────\n\nexport type RequestStore = {\n readonly type: \"request\";\n};\n\nexport type PrerenderStore = {\n readonly type: \"prerender\" | \"prerender-client\" | \"prerender-runtime\";\n /** AbortSignal that fires when the prerender is cancelled or completed. */\n readonly renderSignal: AbortSignal;\n /** Optional route identifier for debugging and error messages. */\n readonly route?: string;\n};\n\nexport type CacheStore = {\n readonly type: \"cache\" | \"private-cache\" | \"unstable-cache\";\n};\n\nexport type GenerateStaticParamsStore = {\n readonly type: \"generate-static-params\";\n};\n\nexport type PrerenderLegacyStore = {\n readonly type: \"prerender-legacy\";\n};\n\n/**\n * Discriminated union of all known work unit types.\n * Matches Next.js's WorkUnitStore: packages/next/src/server/app-render/work-unit-async-storage.external.ts\n */\nexport type WorkUnitStore =\n | RequestStore\n | PrerenderStore\n | CacheStore\n | GenerateStaticParamsStore\n | PrerenderLegacyStore;\n\nexport type WorkUnitAsyncStorage = AsyncLocalStorage<WorkUnitStore>;\n\nexport const workUnitAsyncStorage: WorkUnitAsyncStorage = new AsyncLocalStorage();\n\n// Legacy name (Next 13.x–14.x)\nexport const requestAsyncStorage = workUnitAsyncStorage;\n"],"mappings":";;;;;;;;;;;;;AAoDA,MAAa,uBAA6C,IAAI,mBAAmB;AAGjF,MAAa,sBAAsB"}
@@ -73,11 +73,13 @@ type Metadata = {
73
73
  width?: number;
74
74
  height?: number;
75
75
  alt?: string;
76
+ type?: string;
76
77
  } | Array<string | URL | {
77
78
  url: string | URL;
78
79
  width?: number;
79
80
  height?: number;
80
81
  alt?: string;
82
+ type?: string;
81
83
  }>;
82
84
  videos?: Array<{
83
85
  url: string | URL;
@@ -104,37 +106,20 @@ type Metadata = {
104
106
  alt?: string;
105
107
  width?: number;
106
108
  height?: number;
109
+ type?: string;
107
110
  } | Array<string | URL | {
108
111
  url: string | URL;
109
112
  alt?: string;
110
113
  width?: number;
111
114
  height?: number;
115
+ type?: string;
112
116
  }>;
113
117
  creator?: string;
114
118
  creatorId?: string;
115
119
  players?: TwitterPlayerDescriptor | TwitterPlayerDescriptor[];
116
120
  app?: TwitterAppDescriptor;
117
121
  };
118
- icons?: {
119
- icon?: string | URL | Array<{
120
- url: string | URL;
121
- sizes?: string;
122
- type?: string;
123
- media?: string;
124
- }>;
125
- shortcut?: string | URL | Array<string | URL>;
126
- apple?: string | URL | Array<{
127
- url: string | URL;
128
- sizes?: string;
129
- type?: string;
130
- }>;
131
- other?: Array<{
132
- rel: string;
133
- url: string | URL;
134
- sizes?: string;
135
- type?: string;
136
- }>;
137
- };
122
+ icons?: IconsMetadata;
138
123
  manifest?: string | URL;
139
124
  alternates?: {
140
125
  canonical?: string | URL;
@@ -220,6 +205,36 @@ type TwitterAppDescriptor = {
220
205
  };
221
206
  name?: string;
222
207
  };
208
+ type IconDescriptor = {
209
+ url: string | URL;
210
+ sizes?: string;
211
+ type?: string;
212
+ media?: string;
213
+ };
214
+ type AppleIconDescriptor = {
215
+ url: string | URL;
216
+ sizes?: string;
217
+ type?: string;
218
+ };
219
+ type IconInput = string | URL | IconDescriptor;
220
+ type AppleIconInput = string | URL | AppleIconDescriptor;
221
+ type IconsMap = {
222
+ icon?: IconInput | IconInput[];
223
+ shortcut?: string | URL | Array<string | URL>;
224
+ apple?: AppleIconInput | AppleIconInput[];
225
+ other?: Array<{
226
+ rel: string;
227
+ url: string | URL;
228
+ sizes?: string;
229
+ type?: string;
230
+ }>;
231
+ };
232
+ type IconsMetadata = IconInput | IconInput[] | IconsMap;
233
+ type MetadataMergeEntry = {
234
+ contributesTitle?: boolean;
235
+ isPage?: boolean;
236
+ metadata: Metadata;
237
+ };
223
238
  /**
224
239
  * Merge metadata from multiple sources (layouts + page).
225
240
  *
@@ -232,6 +247,7 @@ type TwitterAppDescriptor = {
232
247
  * Shallow merge: later entries override earlier ones (per Next.js docs).
233
248
  */
234
249
  declare function mergeMetadata(metadataList: Metadata[]): Metadata;
250
+ declare function mergeMetadataEntries(entries: readonly MetadataMergeEntry[]): Metadata;
235
251
  /**
236
252
  * Resolve metadata from a module. Handles both static `metadata` export
237
253
  * and async `generateMetadata()` function.
@@ -242,16 +258,12 @@ declare function mergeMetadata(metadataList: Metadata[]): Metadata;
242
258
  * resolution approach. If not provided, defaults to a promise that resolves
243
259
  * to an empty object (so `await parent` never throws).
244
260
  */
245
- declare function resolveModuleMetadata(mod: Record<string, unknown>, params?: Record<string, string | string[]>, searchParams?: Record<string, string>, parent?: Promise<Metadata>): Promise<Metadata | null>;
246
- /**
247
- * React component that renders metadata as HTML head elements.
248
- * Used by the RSC entry to inject into the <head>.
249
- */
261
+ declare function resolveModuleMetadata(mod: Record<string, unknown>, params?: Record<string, string | string[]>, searchParams?: Record<string, string | string[]>, parent?: Promise<Metadata>): Promise<Metadata | null>;
250
262
  declare function MetadataHead({
251
263
  metadata
252
264
  }: {
253
265
  metadata: Metadata;
254
266
  }): _$react_jsx_runtime0.JSX.Element;
255
267
  //#endregion
256
- export { DEFAULT_VIEWPORT, Metadata, MetadataHead, Viewport, ViewportHead, mergeMetadata, mergeViewport, resolveModuleMetadata, resolveModuleViewport };
268
+ export { DEFAULT_VIEWPORT, Metadata, MetadataHead, MetadataMergeEntry, Viewport, ViewportHead, mergeMetadata, mergeMetadataEntries, mergeViewport, resolveModuleMetadata, resolveModuleViewport };
257
269
  //# sourceMappingURL=metadata.d.ts.map
@@ -1,15 +1,8 @@
1
+ import { makeThenableParams } from "./thenable-params.js";
1
2
  import "react";
2
3
  import { Fragment as Fragment$1, jsx } from "react/jsx-runtime";
3
4
  //#region src/shims/metadata.tsx
4
5
  /**
5
- * Normalize null-prototype objects from matchPattern() into thenable objects.
6
- * See entries/app-rsc-entry.ts makeThenableParams() for full explanation.
7
- */
8
- function makeThenableParams(obj) {
9
- const plain = { ...obj };
10
- return Object.assign(Promise.resolve(plain), plain);
11
- }
12
- /**
13
6
  * Resolve viewport config from a module. Handles both static `viewport` export
14
7
  * and async `generateViewport()` function.
15
8
  */
@@ -80,17 +73,25 @@ function ViewportHead({ viewport }) {
80
73
  * Shallow merge: later entries override earlier ones (per Next.js docs).
81
74
  */
82
75
  function mergeMetadata(metadataList) {
83
- if (metadataList.length === 0) return {};
76
+ return mergeMetadataEntries(metadataList.map((metadata, index) => ({
77
+ isPage: index === metadataList.length - 1,
78
+ metadata
79
+ })));
80
+ }
81
+ function mergeMetadataEntries(entries) {
82
+ if (entries.length === 0) return {};
84
83
  const merged = {};
85
84
  let parentTemplate;
86
- for (let i = 0; i < metadataList.length; i++) {
87
- const meta = metadataList[i];
88
- if (!(i === metadataList.length - 1) && meta.title && typeof meta.title === "object" && meta.title.template) parentTemplate = meta.title.template;
85
+ for (const entry of entries) {
86
+ const meta = entry.metadata;
87
+ const isPage = Boolean(entry.isPage);
88
+ const contributesTitle = entry.contributesTitle !== false;
89
+ if (contributesTitle && !isPage && meta.title && typeof meta.title === "object" && meta.title.template) parentTemplate = meta.title.template;
89
90
  for (const key of Object.keys(meta)) {
90
91
  if (key === "title") continue;
91
92
  merged[key] = meta[key];
92
93
  }
93
- if (meta.title !== void 0) merged.title = meta.title;
94
+ if (contributesTitle && meta.title !== void 0) merged.title = meta.title;
94
95
  }
95
96
  const finalTitle = merged.title;
96
97
  if (finalTitle) {
@@ -117,11 +118,11 @@ function mergeMetadata(metadataList) {
117
118
  async function resolveModuleMetadata(mod, params = {}, searchParams, parent = Promise.resolve({})) {
118
119
  if (typeof mod.generateMetadata === "function") {
119
120
  const asyncParams = makeThenableParams(params);
120
- const asyncSp = makeThenableParams(searchParams ?? {});
121
- return await mod.generateMetadata({
121
+ const props = searchParams === void 0 ? { params: asyncParams } : {
122
122
  params: asyncParams,
123
- searchParams: asyncSp
124
- }, parent);
123
+ searchParams: makeThenableParams(searchParams)
124
+ };
125
+ return await mod.generateMetadata(props, parent);
125
126
  }
126
127
  if (mod.metadata && typeof mod.metadata === "object") return mod.metadata;
127
128
  return null;
@@ -130,6 +131,23 @@ async function resolveModuleMetadata(mod, params = {}, searchParams, parent = Pr
130
131
  * React component that renders metadata as HTML head elements.
131
132
  * Used by the RSC entry to inject into the <head>.
132
133
  */
134
+ function isIconDescriptor(value) {
135
+ if (typeof value !== "object" || value === null || value instanceof URL || Array.isArray(value)) return false;
136
+ const urlValue = Reflect.get(value, "url");
137
+ return typeof urlValue === "string" || urlValue instanceof URL;
138
+ }
139
+ function isIconsMap(value) {
140
+ return typeof value === "object" && !(value instanceof URL) && !Array.isArray(value) && !isIconDescriptor(value);
141
+ }
142
+ function normalizeUrlDescriptor(value, createDescriptor) {
143
+ if (typeof value === "string" || value instanceof URL) return createDescriptor(value);
144
+ return value;
145
+ }
146
+ function normalizeUrlDescriptorEntries(value, createDescriptor) {
147
+ if (!value) return [];
148
+ if (Array.isArray(value)) return value.map((entry) => normalizeUrlDescriptor(entry, createDescriptor));
149
+ return [normalizeUrlDescriptor(value, createDescriptor)];
150
+ }
133
151
  function MetadataHead({ metadata }) {
134
152
  const elements = [];
135
153
  let key = 0;
@@ -289,6 +307,10 @@ function MetadataHead({ metadata }) {
289
307
  property: "og:image:height",
290
308
  content: String(img.height)
291
309
  }, key++));
310
+ if (img.type) elements.push(/* @__PURE__ */ jsx("meta", {
311
+ property: "og:image:type",
312
+ content: img.type
313
+ }, key++));
292
314
  if (img.alt) elements.push(/* @__PURE__ */ jsx("meta", {
293
315
  property: "og:image:alt",
294
316
  content: img.alt
@@ -353,10 +375,24 @@ function MetadataHead({ metadata }) {
353
375
  name: "twitter:image",
354
376
  content: resolveUrl(imgUrl)
355
377
  }, key++));
356
- if (typeof img !== "string" && !(img instanceof URL) && img.alt) elements.push(/* @__PURE__ */ jsx("meta", {
357
- name: "twitter:image:alt",
358
- content: img.alt
359
- }, key++));
378
+ if (typeof img !== "string" && !(img instanceof URL)) {
379
+ if (img.type) elements.push(/* @__PURE__ */ jsx("meta", {
380
+ name: "twitter:image:type",
381
+ content: img.type
382
+ }, key++));
383
+ if (img.width) elements.push(/* @__PURE__ */ jsx("meta", {
384
+ name: "twitter:image:width",
385
+ content: String(img.width)
386
+ }, key++));
387
+ if (img.height) elements.push(/* @__PURE__ */ jsx("meta", {
388
+ name: "twitter:image:height",
389
+ content: String(img.height)
390
+ }, key++));
391
+ if (img.alt) elements.push(/* @__PURE__ */ jsx("meta", {
392
+ name: "twitter:image:alt",
393
+ content: img.alt
394
+ }, key++));
395
+ }
360
396
  }
361
397
  }
362
398
  if (tw.players) {
@@ -408,34 +444,28 @@ function MetadataHead({ metadata }) {
408
444
  }
409
445
  }
410
446
  if (metadata.icons) {
411
- const { icon, shortcut, apple, other } = metadata.icons;
412
- if (shortcut) {
413
- const shortcuts = Array.isArray(shortcut) ? shortcut : [shortcut];
447
+ const iconEntries = isIconsMap(metadata.icons) ? normalizeUrlDescriptorEntries(metadata.icons.icon, (url) => ({ url })) : normalizeUrlDescriptorEntries(metadata.icons, (url) => ({ url }));
448
+ if (isIconsMap(metadata.icons) && metadata.icons.shortcut) {
449
+ const shortcuts = Array.isArray(metadata.icons.shortcut) ? metadata.icons.shortcut : [metadata.icons.shortcut];
414
450
  for (const s of shortcuts) elements.push(/* @__PURE__ */ jsx("link", {
415
451
  rel: "shortcut icon",
416
452
  href: resolveUrl(s)
417
453
  }, key++));
418
454
  }
419
- if (icon) {
420
- const icons = typeof icon === "string" || icon instanceof URL ? [{ url: icon }] : icon;
421
- for (const i of icons) elements.push(/* @__PURE__ */ jsx("link", {
422
- rel: "icon",
423
- href: resolveUrl(i.url),
424
- ...i.sizes ? { sizes: i.sizes } : {},
425
- ...i.type ? { type: i.type } : {},
426
- ...i.media ? { media: i.media } : {}
427
- }, key++));
428
- }
429
- if (apple) {
430
- const apples = typeof apple === "string" || apple instanceof URL ? [{ url: apple }] : apple;
431
- for (const a of apples) elements.push(/* @__PURE__ */ jsx("link", {
432
- rel: "apple-touch-icon",
433
- href: resolveUrl(a.url),
434
- ...a.sizes ? { sizes: a.sizes } : {},
435
- ...a.type ? { type: a.type } : {}
436
- }, key++));
437
- }
438
- if (other) for (const o of other) elements.push(/* @__PURE__ */ jsx("link", {
455
+ if (iconEntries.length > 0) for (const i of iconEntries) elements.push(/* @__PURE__ */ jsx("link", {
456
+ rel: "icon",
457
+ href: resolveUrl(i.url),
458
+ ...i.sizes ? { sizes: i.sizes } : {},
459
+ ...i.type ? { type: i.type } : {},
460
+ ...i.media ? { media: i.media } : {}
461
+ }, key++));
462
+ if (isIconsMap(metadata.icons) && metadata.icons.apple) for (const a of normalizeUrlDescriptorEntries(metadata.icons.apple, (url) => ({ url }))) elements.push(/* @__PURE__ */ jsx("link", {
463
+ rel: "apple-touch-icon",
464
+ href: resolveUrl(a.url),
465
+ ...a.sizes ? { sizes: a.sizes } : {},
466
+ ...a.type ? { type: a.type } : {}
467
+ }, key++));
468
+ if (isIconsMap(metadata.icons) && metadata.icons.other) for (const o of metadata.icons.other) elements.push(/* @__PURE__ */ jsx("link", {
439
469
  rel: o.rel,
440
470
  href: resolveUrl(o.url),
441
471
  ...o.sizes ? { sizes: o.sizes } : {}
@@ -557,6 +587,6 @@ function MetadataHead({ metadata }) {
557
587
  return /* @__PURE__ */ jsx(Fragment$1, { children: elements });
558
588
  }
559
589
  //#endregion
560
- export { DEFAULT_VIEWPORT, MetadataHead, ViewportHead, mergeMetadata, mergeViewport, resolveModuleMetadata, resolveModuleViewport };
590
+ export { DEFAULT_VIEWPORT, MetadataHead, ViewportHead, mergeMetadata, mergeMetadataEntries, mergeViewport, resolveModuleMetadata, resolveModuleViewport };
561
591
 
562
592
  //# sourceMappingURL=metadata.js.map