@nuxt/scripts 1.0.0-beta.7 → 1.0.0-rc.10

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 (300) hide show
  1. package/bin/cli.mjs +2 -0
  2. package/dist/cli.d.mts +2 -0
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.mjs +50 -0
  5. package/dist/devtools-client/200.html +1 -0
  6. package/dist/devtools-client/404.html +1 -0
  7. package/dist/devtools-client/_fonts/4ppnHhMi-pBsWSPo7mY0avYxlDoAg1N3PTzCwXLZ5rA-d9oibkGnTd1JL3tc_xnaVgBLYmOB8kjrK2cvZaqwj9s.woff2 +0 -0
  8. package/dist/devtools-client/_fonts/4qBuU9MRVUlPZNPSF7Xom_sK8RBEnfYu-9VXFrdq8A8-8TDwLE1HAj1sQn7XxVWtM_7sIaPM-DTdO3Pf8U2DF1U.woff2 +0 -0
  9. package/dist/devtools-client/_fonts/6dYsbWUd_BpKJ7mdDihgOcya1gHXLpJBuMYXux3WMjE-q3fYNS8YbW5n7ZeXI2vSNgkRWW5VDPKAl51SNTjG2qk.woff2 +0 -0
  10. package/dist/devtools-client/_fonts/Lr-hqqZZsYmCt0ITUlr1CUrWim9fsKvoDFZliMxgNHY-iTa_Yt_PzhOY9TX7ZXdSlEPim6iRt92xhECwaxWxd5w.woff2 +0 -0
  11. package/dist/devtools-client/_fonts/OknHvWI6KtYn1JQBzX7eSpNDBQ8520F9TvSUJYkVf6A-xeZn9253svK_8Q2LD0XEruY_MnEsuCRO5LenPoggC0Y.woff2 +0 -0
  12. package/dist/devtools-client/_fonts/PV2hrQG6wq5BlIPDjdL1IcOflycaghyt5MHzlBqZtlo-lb_WexLz3VZqfTN0oi554iBH5tT2j2UFEV-XErCAS3E.woff2 +0 -0
  13. package/dist/devtools-client/_fonts/UA7OtwYHwGN_HjcVGTdmiQxUit7FlqkCwxVUWSeXVnQ-B4OXCFOL_tWrYODpQTc07aMaj0c2cewTOmBRWR9tD-A.woff2 +0 -0
  14. package/dist/devtools-client/_fonts/VE4cDVCv5MxbFM7ZLoLCGbIpNd71zhp7MDI9lmN5Y7I-xZyDYCUVrd6LV8eVGF3Um3UZjBFuUtDGtvdyTBBRYBo.woff2 +0 -0
  15. package/dist/devtools-client/_fonts/fVoGbnMbBFd5L9BBp9fUPavUSkZ_EmsQNSyadkT-108-U4T0khaeLQSIhtt9eVvaCEKJjtWJ4ioRJOf8hvqkWY0.woff2 +0 -0
  16. package/dist/devtools-client/_fonts/lQAxeCEs1R0Lw-H9XRU1RlOARQN8J6npRsPjyEDMe5s-_DUSLEkO3tKTuun_gSnDLoQPVEnpOnyqZMOw0ByZ6PA.woff2 +0 -0
  17. package/dist/devtools-client/_fonts/lntlqNHKLV2n82yTwMde70QqOjcfLE2XJ5oKZ3vRPWc-z6TxpIZQdWXztWLr9_OFWqt_WJJoeGtuK_-XQMZGQwE.woff2 +0 -0
  18. package/dist/devtools-client/_fonts/qxAYvKsXWeYv731eb-h5TRurcdIP_W44mpNdX-HABAk-zUDeMEFlNtNbrwvT9JxLEBg0TphGy70O6RfIoIX_ZwU.woff2 +0 -0
  19. package/dist/devtools-client/_nuxt/B8PEiB0p.js +1 -0
  20. package/dist/devtools-client/_nuxt/BgPDxVUn.js +1 -0
  21. package/dist/devtools-client/_nuxt/BmlapxLP.js +1 -0
  22. package/dist/devtools-client/_nuxt/CM2vefXI.js +188 -0
  23. package/dist/devtools-client/_nuxt/DAF5Qk9P.js +1 -0
  24. package/dist/devtools-client/_nuxt/Dx6HhVmj.js +1 -0
  25. package/dist/devtools-client/_nuxt/S8LiR9M1.js +1 -0
  26. package/dist/devtools-client/_nuxt/builds/latest.json +1 -0
  27. package/dist/devtools-client/_nuxt/builds/meta/5458a3f2-af35-479c-8852-bf6f92fed611.json +1 -0
  28. package/dist/devtools-client/_nuxt/entry.BKkVrcJj.css +1 -0
  29. package/dist/devtools-client/_nuxt/error-404.d44aGwWI.css +1 -0
  30. package/dist/devtools-client/_nuxt/error-500.NthMfIEt.css +1 -0
  31. package/dist/devtools-client/_nuxt/first-party.C8Ha4JLM.css +1 -0
  32. package/dist/devtools-client/_nuxt/index.DZD1lwyI.css +1 -0
  33. package/dist/devtools-client/_nuxt/registry.B9lnjF_b.css +1 -0
  34. package/dist/devtools-client/_nuxt/vBkR1GJq.js +1 -0
  35. package/dist/devtools-client/_nuxt/wDzz0qaB.js +1 -0
  36. package/dist/devtools-client/docs/index.html +1 -0
  37. package/dist/devtools-client/first-party/index.html +1 -0
  38. package/dist/devtools-client/index.html +1 -0
  39. package/dist/devtools-client/registry/index.html +1 -0
  40. package/dist/module.d.mts +89 -80
  41. package/dist/module.d.ts +185 -0
  42. package/dist/module.json +1 -1
  43. package/dist/module.mjs +1056 -756
  44. package/dist/registry.d.mts +92 -4
  45. package/dist/registry.d.ts +94 -0
  46. package/dist/registry.mjs +668 -326
  47. package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.d.vue.ts +77 -165
  48. package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.vue +148 -227
  49. package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.vue.d.ts +77 -165
  50. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsAdvancedMarkerElement.d.vue.ts +6 -55
  51. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsAdvancedMarkerElement.vue +12 -83
  52. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsAdvancedMarkerElement.vue.d.ts +6 -55
  53. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsCircle.d.vue.ts +5 -1
  54. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsCircle.vue +24 -38
  55. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsCircle.vue.d.ts +5 -1
  56. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsGeoJson.d.vue.ts +43 -0
  57. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsGeoJson.vue +60 -0
  58. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsGeoJson.vue.d.ts +43 -0
  59. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsHeatmapLayer.d.vue.ts +4 -0
  60. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsHeatmapLayer.vue +22 -26
  61. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsHeatmapLayer.vue.d.ts +4 -0
  62. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsInfoWindow.d.vue.ts +11 -8
  63. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsInfoWindow.vue +57 -57
  64. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsInfoWindow.vue.d.ts +11 -8
  65. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarker.d.vue.ts +24 -42
  66. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarker.vue +71 -74
  67. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarker.vue.d.ts +24 -42
  68. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.d.vue.ts +19 -20
  69. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.vue +85 -38
  70. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.vue.d.ts +19 -20
  71. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsOverlayView.d.vue.ts +98 -0
  72. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsOverlayView.vue +263 -0
  73. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsOverlayView.vue.d.ts +98 -0
  74. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPinElement.d.vue.ts +10 -3
  75. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPinElement.vue +9 -41
  76. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPinElement.vue.d.ts +10 -3
  77. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPolygon.d.vue.ts +7 -3
  78. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPolygon.vue +23 -38
  79. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPolygon.vue.d.ts +7 -3
  80. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPolyline.d.vue.ts +7 -3
  81. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPolyline.vue +23 -38
  82. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPolyline.vue.d.ts +7 -3
  83. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsRectangle.d.vue.ts +7 -3
  84. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsRectangle.vue +24 -38
  85. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsRectangle.vue.d.ts +7 -3
  86. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsStaticMap.d.vue.ts +200 -0
  87. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsStaticMap.vue +170 -0
  88. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsStaticMap.vue.d.ts +200 -0
  89. package/dist/runtime/components/GoogleMaps/bindGoogleMapsEvents.d.ts +13 -0
  90. package/dist/runtime/components/GoogleMaps/bindGoogleMapsEvents.js +8 -0
  91. package/dist/runtime/components/GoogleMaps/injectionKeys.d.ts +10 -0
  92. package/dist/runtime/components/GoogleMaps/injectionKeys.js +2 -0
  93. package/dist/runtime/components/GoogleMaps/types.d.ts +42 -0
  94. package/dist/runtime/components/GoogleMaps/types.js +1 -0
  95. package/dist/runtime/components/GoogleMaps/useGoogleMapsResource.d.ts +98 -0
  96. package/dist/runtime/components/GoogleMaps/useGoogleMapsResource.js +126 -0
  97. package/dist/runtime/components/ScriptBlueskyEmbed.d.vue.ts +83 -0
  98. package/dist/runtime/components/ScriptBlueskyEmbed.vue +91 -0
  99. package/dist/runtime/components/ScriptBlueskyEmbed.vue.d.ts +83 -0
  100. package/dist/runtime/components/ScriptCarbonAds.d.vue.ts +4 -7
  101. package/dist/runtime/components/ScriptCarbonAds.vue +1 -0
  102. package/dist/runtime/components/ScriptCarbonAds.vue.d.ts +4 -7
  103. package/dist/runtime/components/ScriptCrisp.d.vue.ts +7 -11
  104. package/dist/runtime/components/ScriptCrisp.vue +2 -1
  105. package/dist/runtime/components/ScriptCrisp.vue.d.ts +7 -11
  106. package/dist/runtime/components/ScriptGoogleAdsense.d.vue.ts +4 -7
  107. package/dist/runtime/components/ScriptGoogleAdsense.vue +2 -1
  108. package/dist/runtime/components/ScriptGoogleAdsense.vue.d.ts +4 -7
  109. package/dist/runtime/components/ScriptGravatar.d.vue.ts +22 -0
  110. package/dist/runtime/components/ScriptGravatar.vue +46 -0
  111. package/dist/runtime/components/ScriptGravatar.vue.d.ts +22 -0
  112. package/dist/runtime/components/ScriptInstagramEmbed.d.vue.ts +12 -15
  113. package/dist/runtime/components/ScriptInstagramEmbed.vue +11 -3
  114. package/dist/runtime/components/ScriptInstagramEmbed.vue.d.ts +12 -15
  115. package/dist/runtime/components/ScriptIntercom.d.vue.ts +7 -11
  116. package/dist/runtime/components/ScriptIntercom.vue +5 -3
  117. package/dist/runtime/components/ScriptIntercom.vue.d.ts +7 -11
  118. package/dist/runtime/components/ScriptLemonSqueezy.d.vue.ts +2 -3
  119. package/dist/runtime/components/ScriptLemonSqueezy.vue +1 -0
  120. package/dist/runtime/components/ScriptLemonSqueezy.vue.d.ts +2 -3
  121. package/dist/runtime/components/ScriptPayPalButtons.d.vue.ts +43 -37
  122. package/dist/runtime/components/ScriptPayPalButtons.vue +49 -79
  123. package/dist/runtime/components/ScriptPayPalButtons.vue.d.ts +43 -37
  124. package/dist/runtime/components/ScriptPayPalMessages.d.vue.ts +37 -28
  125. package/dist/runtime/components/ScriptPayPalMessages.vue +47 -50
  126. package/dist/runtime/components/ScriptPayPalMessages.vue.d.ts +37 -28
  127. package/dist/runtime/components/ScriptStripePricingTable.d.vue.ts +5 -9
  128. package/dist/runtime/components/ScriptStripePricingTable.vue +3 -2
  129. package/dist/runtime/components/ScriptStripePricingTable.vue.d.ts +5 -9
  130. package/dist/runtime/components/ScriptVimeoPlayer.d.vue.ts +17 -11
  131. package/dist/runtime/components/ScriptVimeoPlayer.vue +14 -10
  132. package/dist/runtime/components/ScriptVimeoPlayer.vue.d.ts +17 -11
  133. package/dist/runtime/components/ScriptXEmbed.d.vue.ts +10 -14
  134. package/dist/runtime/components/ScriptXEmbed.vue +21 -12
  135. package/dist/runtime/components/ScriptXEmbed.vue.d.ts +10 -14
  136. package/dist/runtime/components/ScriptYouTubePlayer.d.vue.ts +10 -15
  137. package/dist/runtime/components/ScriptYouTubePlayer.vue +12 -5
  138. package/dist/runtime/components/ScriptYouTubePlayer.vue.d.ts +10 -15
  139. package/dist/runtime/composables/useScript.js +159 -8
  140. package/dist/runtime/composables/useScriptEventPage.js +2 -2
  141. package/dist/runtime/composables/useScriptProxyToken.d.ts +12 -0
  142. package/dist/runtime/composables/useScriptProxyToken.js +4 -0
  143. package/dist/runtime/composables/useScriptProxyUrl.d.ts +12 -0
  144. package/dist/runtime/composables/useScriptProxyUrl.js +27 -0
  145. package/dist/runtime/composables/useScriptTriggerConsent.d.ts +10 -0
  146. package/dist/runtime/composables/useScriptTriggerConsent.js +33 -20
  147. package/dist/runtime/composables/useScriptTriggerElement.js +1 -1
  148. package/dist/runtime/composables/useScriptTriggerIdleTimeout.js +1 -1
  149. package/dist/runtime/devtools-standalone-bridge.client.d.ts +8 -0
  150. package/dist/runtime/devtools-standalone-bridge.client.js +50 -0
  151. package/dist/runtime/plugins/proxy-token.server.d.ts +10 -0
  152. package/dist/runtime/plugins/proxy-token.server.js +17 -0
  153. package/dist/runtime/registry/bing-uet.d.ts +198 -0
  154. package/dist/runtime/registry/bing-uet.js +43 -0
  155. package/dist/runtime/registry/bluesky-embed.d.ts +112 -0
  156. package/dist/runtime/registry/bluesky-embed.js +68 -0
  157. package/dist/runtime/registry/clarity.d.ts +16 -17
  158. package/dist/runtime/registry/clarity.js +33 -31
  159. package/dist/runtime/registry/cloudflare-web-analytics.d.ts +2 -13
  160. package/dist/runtime/registry/cloudflare-web-analytics.js +2 -14
  161. package/dist/runtime/registry/crisp.d.ts +10 -40
  162. package/dist/runtime/registry/crisp.js +2 -33
  163. package/dist/runtime/registry/databuddy-analytics.d.ts +2 -35
  164. package/dist/runtime/registry/databuddy-analytics.js +20 -45
  165. package/dist/runtime/registry/fathom-analytics.d.ts +7 -26
  166. package/dist/runtime/registry/fathom-analytics.js +3 -25
  167. package/dist/runtime/registry/google-adsense.d.ts +3 -11
  168. package/dist/runtime/registry/google-adsense.js +2 -11
  169. package/dist/runtime/registry/google-analytics.d.ts +9 -7
  170. package/dist/runtime/registry/google-analytics.js +15 -9
  171. package/dist/runtime/registry/google-maps.d.ts +3 -9
  172. package/dist/runtime/registry/google-maps.js +2 -8
  173. package/dist/runtime/registry/google-recaptcha.d.ts +2 -6
  174. package/dist/runtime/registry/google-recaptcha.js +4 -12
  175. package/dist/runtime/registry/google-sign-in.d.ts +2 -13
  176. package/dist/runtime/registry/google-sign-in.js +2 -22
  177. package/dist/runtime/registry/google-tag-manager.d.ts +8 -29
  178. package/dist/runtime/registry/google-tag-manager.js +14 -28
  179. package/dist/runtime/registry/gravatar.d.ts +26 -0
  180. package/dist/runtime/registry/gravatar.js +33 -0
  181. package/dist/runtime/registry/hotjar.d.ts +4 -6
  182. package/dist/runtime/registry/hotjar.js +2 -5
  183. package/dist/runtime/registry/instagram-embed.d.ts +3 -18
  184. package/dist/runtime/registry/instagram-embed.js +4 -19
  185. package/dist/runtime/registry/intercom.d.ts +5 -13
  186. package/dist/runtime/registry/intercom.js +2 -12
  187. package/dist/runtime/registry/matomo-analytics.d.ts +12 -15
  188. package/dist/runtime/registry/matomo-analytics.js +31 -13
  189. package/dist/runtime/registry/meta-pixel.d.ts +12 -8
  190. package/dist/runtime/registry/meta-pixel.js +12 -5
  191. package/dist/runtime/registry/mixpanel-analytics.d.ts +32 -0
  192. package/dist/runtime/registry/mixpanel-analytics.js +58 -0
  193. package/dist/runtime/registry/npm.d.ts +3 -7
  194. package/dist/runtime/registry/npm.js +2 -9
  195. package/dist/runtime/registry/paypal.d.ts +4 -25
  196. package/dist/runtime/registry/paypal.js +3 -66
  197. package/dist/runtime/registry/plausible-analytics.js +19 -14
  198. package/dist/runtime/registry/posthog.d.ts +18 -14
  199. package/dist/runtime/registry/posthog.js +18 -16
  200. package/dist/runtime/registry/reddit-pixel.d.ts +5 -6
  201. package/dist/runtime/registry/reddit-pixel.js +2 -4
  202. package/dist/runtime/registry/rybbit-analytics.d.ts +2 -14
  203. package/dist/runtime/registry/rybbit-analytics.js +10 -20
  204. package/dist/runtime/registry/schemas.d.ts +1047 -0
  205. package/dist/runtime/registry/schemas.js +1004 -0
  206. package/dist/runtime/registry/segment.d.ts +2 -5
  207. package/dist/runtime/registry/segment.js +2 -5
  208. package/dist/runtime/registry/snapchat-pixel.d.ts +5 -34
  209. package/dist/runtime/registry/snapchat-pixel.js +2 -20
  210. package/dist/runtime/registry/stripe.d.ts +3 -4
  211. package/dist/runtime/registry/stripe.js +2 -4
  212. package/dist/runtime/registry/tiktok-pixel.d.ts +20 -9
  213. package/dist/runtime/registry/tiktok-pixel.js +24 -7
  214. package/dist/runtime/registry/umami-analytics.d.ts +2 -31
  215. package/dist/runtime/registry/umami-analytics.js +2 -36
  216. package/dist/runtime/registry/vercel-analytics.d.ts +29 -0
  217. package/dist/runtime/registry/vercel-analytics.js +84 -0
  218. package/dist/runtime/registry/vimeo-player.d.ts +2 -2
  219. package/dist/runtime/registry/vimeo-player.js +1 -1
  220. package/dist/runtime/registry/x-embed.d.ts +3 -21
  221. package/dist/runtime/registry/x-embed.js +2 -21
  222. package/dist/runtime/registry/x-pixel.d.ts +4 -7
  223. package/dist/runtime/registry/x-pixel.js +2 -5
  224. package/dist/runtime/registry/youtube-player.d.ts +7 -7
  225. package/dist/runtime/registry/youtube-player.js +1 -1
  226. package/dist/runtime/server/bluesky-embed-image.d.ts +2 -0
  227. package/dist/runtime/server/bluesky-embed-image.js +7 -0
  228. package/dist/runtime/server/bluesky-embed.d.ts +2 -0
  229. package/dist/runtime/server/bluesky-embed.js +78 -0
  230. package/dist/runtime/server/google-maps-geocode-proxy.d.ts +2 -0
  231. package/dist/runtime/server/google-maps-geocode-proxy.js +38 -0
  232. package/dist/runtime/server/google-static-maps-proxy.d.ts +1 -1
  233. package/dist/runtime/server/google-static-maps-proxy.js +18 -23
  234. package/dist/runtime/server/gravatar-proxy.d.ts +2 -0
  235. package/dist/runtime/server/gravatar-proxy.js +46 -0
  236. package/dist/runtime/server/instagram-embed-asset.d.ts +1 -1
  237. package/dist/runtime/server/instagram-embed-asset.js +8 -41
  238. package/dist/runtime/server/instagram-embed-image.d.ts +1 -1
  239. package/dist/runtime/server/instagram-embed-image.js +6 -53
  240. package/dist/runtime/server/instagram-embed.d.ts +1 -0
  241. package/dist/runtime/server/instagram-embed.js +82 -40
  242. package/dist/runtime/server/proxy-handler.js +102 -85
  243. package/dist/runtime/server/utils/cached-upstream.d.ts +55 -0
  244. package/dist/runtime/server/utils/cached-upstream.js +65 -0
  245. package/dist/runtime/server/utils/embed-rewriters.d.ts +19 -0
  246. package/dist/runtime/server/utils/embed-rewriters.js +41 -0
  247. package/dist/runtime/server/utils/image-proxy.d.ts +14 -0
  248. package/dist/runtime/server/utils/image-proxy.js +73 -0
  249. package/dist/runtime/server/utils/instagram-embed.d.ts +16 -0
  250. package/dist/runtime/server/utils/instagram-embed.js +153 -0
  251. package/dist/runtime/server/utils/privacy.d.ts +1 -10
  252. package/dist/runtime/server/utils/privacy.js +60 -40
  253. package/dist/runtime/server/utils/proxy-url.d.ts +9 -0
  254. package/dist/runtime/server/utils/proxy-url.js +21 -0
  255. package/dist/runtime/server/utils/sign-constants.d.ts +16 -0
  256. package/dist/runtime/server/utils/sign-constants.js +5 -0
  257. package/dist/runtime/server/utils/sign.d.ts +101 -0
  258. package/dist/runtime/server/utils/sign.js +91 -0
  259. package/dist/runtime/server/utils/withSigning.d.ts +23 -0
  260. package/dist/runtime/server/utils/withSigning.js +19 -0
  261. package/dist/runtime/server/x-embed-image.d.ts +1 -1
  262. package/dist/runtime/server/x-embed-image.js +5 -49
  263. package/dist/runtime/server/x-embed.js +26 -6
  264. package/dist/runtime/types.d.ts +311 -55
  265. package/dist/runtime/types.js +1 -2
  266. package/dist/runtime/utils/pure.d.ts +1 -1
  267. package/dist/runtime/utils.d.ts +6 -4
  268. package/dist/runtime/utils.js +31 -14
  269. package/dist/stats.d.mts +202 -0
  270. package/dist/stats.d.ts +202 -0
  271. package/dist/stats.mjs +3835 -0
  272. package/dist/types-source.d.mts +17 -0
  273. package/dist/types-source.d.ts +17 -0
  274. package/dist/types-source.mjs +3787 -0
  275. package/dist/types.d.mts +4 -2
  276. package/package.json +41 -63
  277. package/README.md +0 -86
  278. package/dist/client/200.html +0 -1
  279. package/dist/client/404.html +0 -1
  280. package/dist/client/_nuxt/BJa0m50V.js +0 -1
  281. package/dist/client/_nuxt/BPQ3VLAy.js +0 -1
  282. package/dist/client/_nuxt/Ci5iXYuB.js +0 -1
  283. package/dist/client/_nuxt/DaI2y8Uz.js +0 -162
  284. package/dist/client/_nuxt/builds/latest.json +0 -1
  285. package/dist/client/_nuxt/builds/meta/9b4fb16a-3c62-48b0-8295-126cb077b5d3.json +0 -1
  286. package/dist/client/_nuxt/entry.D45OuV0w.css +0 -1
  287. package/dist/client/_nuxt/error-404.B57D-jUQ.css +0 -1
  288. package/dist/client/_nuxt/error-500.DTHUW7BI.css +0 -1
  289. package/dist/client/_nuxt/vPLZfVXe.js +0 -1
  290. package/dist/client/index.html +0 -1
  291. package/dist/runtime/components/ScriptPayPalMarks.d.vue.ts +0 -52
  292. package/dist/runtime/components/ScriptPayPalMarks.vue +0 -69
  293. package/dist/runtime/components/ScriptPayPalMarks.vue.d.ts +0 -52
  294. package/dist/runtime/validation/mock.d.ts +0 -42
  295. package/dist/runtime/validation/mock.js +0 -21
  296. package/dist/runtime/validation/valibot.d.ts +0 -1
  297. package/dist/runtime/validation/valibot.js +0 -1
  298. /package/dist/{client → devtools-client}/_nuxt/CVO1_9PV.js +0 -0
  299. /package/dist/{client → devtools-client}/_nuxt/Cp-IABpG.js +0 -0
  300. /package/dist/{client → devtools-client}/_nuxt/D0r3Knsf.js +0 -0
package/dist/module.mjs CHANGED
@@ -1,88 +1,45 @@
1
- import { useNuxt, extendViteConfig, useLogger, addDevServerHandler, extendRouteRules, tryUseNuxt, logger as logger$1, addTypeTemplate, defineNuxtModule, createResolver, hasNuxtModule, addImports, addComponentsDir, addTemplate, addPluginTemplate, addServerHandler, addBuildPlugin } from '@nuxt/kit';
2
- import { existsSync, readdirSync, readFileSync } from 'node:fs';
3
- import { join, resolve, relative } from 'pathe';
1
+ import { createHash, randomBytes } from 'node:crypto';
2
+ import { existsSync, readFileSync, appendFileSync, writeFileSync, readdirSync } from 'node:fs';
3
+ import { useNuxt, addDevServerHandler, extendRouteRules, tryUseNuxt, createResolver, extendViteConfig, logger as logger$1, useLogger, addTypeTemplate, defineNuxtModule, addPluginTemplate, addServerHandler, addImports, addComponentsDir, addTemplate, hasNuxtModule, addBuildPlugin, addPlugin } from '@nuxt/kit';
4
4
  import { defu } from 'defu';
5
+ import { join, resolve } from 'pathe';
5
6
  import { resolvePackageJSON, readPackageJSON } from 'pkg-types';
6
- import { addCustomTab } from '@nuxt/devtools-kit';
7
- import { createHash } from 'node:crypto';
8
- import fsp from 'node:fs/promises';
9
- import { createUnplugin } from 'unplugin';
10
- import MagicString from 'magic-string';
11
- import { parseAndWalk } from 'oxc-walker';
12
- import { joinURL, parseURL, parseQuery, hasProtocol } from 'ufo';
13
- import { hash } from 'ohash';
14
- import { colors } from 'consola/utils';
15
- import { fetch, $fetch } from 'ofetch';
16
7
  import { lazyEventHandler, eventHandler, createError } from 'h3';
8
+ import { fetch, $fetch } from 'ofetch';
9
+ import { joinURL, parseURL, parseQuery, hasProtocol } from 'ufo';
17
10
  import { createStorage } from 'unstorage';
18
11
  import fsDriver from 'unstorage/drivers/fs-lite';
19
- import { pathToFileURL } from 'node:url';
20
12
  import { isCI, provider } from 'std-env';
21
- import { registry } from './registry.mjs';
22
-
23
- const DEVTOOLS_UI_ROUTE = "/__nuxt-scripts";
24
- const DEVTOOLS_UI_LOCAL_PORT = 3300;
25
-
26
- async function setupDevToolsUI(options, resolve, nuxt = useNuxt()) {
27
- const clientPath = await resolve("./client");
28
- const isProductionBuild = existsSync(clientPath);
29
- if (isProductionBuild) {
30
- nuxt.hook("vite:serverCreated", async (server) => {
31
- const sirv = await import('sirv').then((r) => r.default || r);
32
- server.middlewares.use(
33
- DEVTOOLS_UI_ROUTE,
34
- sirv(clientPath, { dev: true, single: true })
35
- );
36
- });
37
- } else {
38
- extendViteConfig((config) => {
39
- config.server = config.server || {};
40
- config.server.proxy = config.server.proxy || {};
41
- config.server.proxy[DEVTOOLS_UI_ROUTE] = {
42
- target: `http://localhost:${DEVTOOLS_UI_LOCAL_PORT}${DEVTOOLS_UI_ROUTE}`,
43
- changeOrigin: true,
44
- followRedirects: true,
45
- rewrite: (path) => path.replace(DEVTOOLS_UI_ROUTE, "")
46
- };
47
- });
48
- }
49
- addCustomTab({
50
- // unique identifier
51
- name: "nuxt-scripts",
52
- // title to display in the tab
53
- title: "Scripts",
54
- // any icon from Iconify, or a URL to an image
55
- icon: "carbon:script",
56
- // iframe view
57
- view: {
58
- type: "iframe",
59
- src: DEVTOOLS_UI_ROUTE
60
- }
61
- });
62
- }
63
-
64
- const logger = useLogger("@nuxt/scripts");
13
+ import { parseAndWalk, ScopeTracker, walk, ScopeTrackerFunction, ScopeTrackerIdentifier, ScopeTrackerFunctionParam, ScopeTrackerVariable } from 'oxc-walker';
14
+ import { createUnplugin } from 'unplugin';
15
+ import { pathToFileURL } from 'node:url';
16
+ import fsp from 'node:fs/promises';
17
+ import { colors } from 'consola/utils';
18
+ import MagicString from 'magic-string';
19
+ import { hash } from 'ohash';
20
+ import { getBundleResolve, registry, resolveCapabilities, getPartytownForwards, buildProxyConfigsFromRegistry, generatePartytownResolveUrl } from './registry.mjs';
21
+ import '../dist/runtime/registry/schemas.js';
65
22
 
66
23
  const renderedScript = /* @__PURE__ */ new Map();
67
24
  const ONE_YEAR_IN_SECONDS = 60 * 60 * 24 * 365;
68
- const bundleStorage = () => {
25
+ function bundleStorage() {
69
26
  const nuxt = tryUseNuxt();
70
27
  return createStorage({
71
28
  driver: fsDriver({
72
29
  base: resolve(nuxt?.options.rootDir || "", "node_modules/.cache/nuxt/scripts")
73
30
  })
74
31
  });
75
- };
76
- function setupPublicAssetStrategy(options = {}) {
77
- const assetsBaseURL = options.prefix || "/_scripts";
32
+ }
33
+ function setupPublicAssetStrategy(assetsBaseURL) {
78
34
  const nuxt = useNuxt();
79
35
  const storage = bundleStorage();
80
36
  addDevServerHandler({
81
37
  route: assetsBaseURL,
82
38
  handler: lazyEventHandler(async () => {
83
39
  return eventHandler(async (event) => {
84
- const filename = event.path.slice(1);
85
- const scriptDescriptor = renderedScript.get(join(assetsBaseURL, event.path.slice(1)));
40
+ const cleanPath = (event.path || "").split("?")[0]?.slice(1) || "";
41
+ const filename = cleanPath;
42
+ const scriptDescriptor = renderedScript.get(join(assetsBaseURL, cleanPath));
86
43
  if (!scriptDescriptor || scriptDescriptor instanceof Error)
87
44
  throw createError({ statusCode: 404 });
88
45
  if (scriptDescriptor.content) {
@@ -122,291 +79,258 @@ function setupPublicAssetStrategy(options = {}) {
122
79
  };
123
80
  }
124
81
 
125
- function buildProxyConfig(collectPrefix) {
126
- return {
127
- googleAnalytics: {
128
- // GA4: screen/timezone/UA needed for device, time, and OS reports; rest anonymized safely
129
- privacy: { ip: true, userAgent: false, language: true, screen: false, timezone: false, hardware: true },
130
- rewrite: [
131
- // Modern gtag.js uses www.google.com/g/collect
132
- { from: "www.google.com/g/collect", to: `${collectPrefix}/ga/g/collect` },
133
- // Older gtag.js constructs URLs dynamically: "https://"+(subdomain)+".google-analytics.com/g/collect"
134
- // We need to catch the suffix pattern with leading dot
135
- { from: ".google-analytics.com/g/collect", to: `${collectPrefix}/ga/g/collect` },
136
- { from: ".analytics.google.com/g/collect", to: `${collectPrefix}/ga/g/collect` },
137
- // Full domain patterns for static URLs
138
- { from: "www.google-analytics.com/g/collect", to: `${collectPrefix}/ga/g/collect` },
139
- { from: "analytics.google.com/g/collect", to: `${collectPrefix}/ga/g/collect` },
140
- // Legacy endpoints still used by some scripts
141
- { from: "www.google-analytics.com", to: `${collectPrefix}/ga` },
142
- { from: "analytics.google.com", to: `${collectPrefix}/ga` },
143
- // DoubleClick tracking (used by GA4 for ads/conversions)
144
- { from: "stats.g.doubleclick.net/g/collect", to: `${collectPrefix}/ga/g/collect` },
145
- { from: "stats.g.doubleclick.net", to: `${collectPrefix}/ga-dc` },
146
- // Google Ads/Syndication tracking
147
- { from: "pagead2.googlesyndication.com", to: `${collectPrefix}/ga-syn` },
148
- { from: "www.googleadservices.com", to: `${collectPrefix}/ga-ads` },
149
- { from: "googleads.g.doubleclick.net", to: `${collectPrefix}/ga-gads` }
150
- ],
151
- routes: {
152
- [`${collectPrefix}/ga/**`]: { proxy: "https://www.google-analytics.com/**" },
153
- [`${collectPrefix}/ga-dc/**`]: { proxy: "https://stats.g.doubleclick.net/**" },
154
- [`${collectPrefix}/ga-syn/**`]: { proxy: "https://pagead2.googlesyndication.com/**" },
155
- [`${collectPrefix}/ga-ads/**`]: { proxy: "https://www.googleadservices.com/**" },
156
- [`${collectPrefix}/ga-gads/**`]: { proxy: "https://googleads.g.doubleclick.net/**" }
157
- }
158
- },
159
- googleTagManager: {
160
- // GTM: container only, passes data through — downstream tags have their own privacy
161
- privacy: { ip: false, userAgent: false, language: false, screen: false, timezone: false, hardware: false },
162
- rewrite: [
163
- { from: "www.googletagmanager.com", to: `${collectPrefix}/gtm` }
164
- ],
165
- routes: {
166
- [`${collectPrefix}/gtm/**`]: { proxy: "https://www.googletagmanager.com/**" }
167
- }
168
- },
169
- metaPixel: {
170
- // Meta: untrusted ad network — full anonymization
171
- privacy: { ip: true, userAgent: true, language: true, screen: true, timezone: true, hardware: true },
172
- rewrite: [
173
- // SDK script loading
174
- { from: "connect.facebook.net", to: `${collectPrefix}/meta` },
175
- // Tracking pixel endpoint (www and non-www)
176
- { from: "www.facebook.com/tr", to: `${collectPrefix}/meta-tr` },
177
- { from: "facebook.com/tr", to: `${collectPrefix}/meta-tr` },
178
- // Additional Meta tracking domains
179
- { from: "pixel.facebook.com", to: `${collectPrefix}/meta-px` },
180
- { from: "www.facebook.com/plugins", to: `${collectPrefix}/meta-plugins` }
181
- ],
182
- routes: {
183
- [`${collectPrefix}/meta/**`]: { proxy: "https://connect.facebook.net/**" },
184
- [`${collectPrefix}/meta-tr/**`]: { proxy: "https://www.facebook.com/tr/**" },
185
- [`${collectPrefix}/meta-px/**`]: { proxy: "https://pixel.facebook.com/**" },
186
- [`${collectPrefix}/meta-plugins/**`]: { proxy: "https://www.facebook.com/plugins/**" }
187
- }
188
- },
189
- tiktokPixel: {
190
- // TikTok: untrusted ad network — full anonymization
191
- privacy: { ip: true, userAgent: true, language: true, screen: true, timezone: true, hardware: true },
192
- rewrite: [
193
- { from: "analytics.tiktok.com", to: `${collectPrefix}/tiktok` }
194
- ],
195
- routes: {
196
- [`${collectPrefix}/tiktok/**`]: { proxy: "https://analytics.tiktok.com/**" }
197
- }
198
- },
199
- segment: {
200
- // Segment: trusted data pipeline — needs maximum fidelity for downstream destinations
201
- privacy: { ip: false, userAgent: false, language: false, screen: false, timezone: false, hardware: false },
202
- rewrite: [
203
- { from: "api.segment.io", to: `${collectPrefix}/segment` },
204
- { from: "cdn.segment.com", to: `${collectPrefix}/segment-cdn` }
205
- ],
206
- routes: {
207
- [`${collectPrefix}/segment/**`]: { proxy: "https://api.segment.io/**" },
208
- [`${collectPrefix}/segment-cdn/**`]: { proxy: "https://cdn.segment.com/**" }
209
- }
210
- },
211
- xPixel: {
212
- // X/Twitter: untrusted ad network — full anonymization
213
- privacy: { ip: true, userAgent: true, language: true, screen: true, timezone: true, hardware: true },
214
- rewrite: [
215
- { from: "analytics.twitter.com", to: `${collectPrefix}/x` },
216
- { from: "t.co", to: `${collectPrefix}/x-t` }
217
- ],
218
- routes: {
219
- [`${collectPrefix}/x/**`]: { proxy: "https://analytics.twitter.com/**" },
220
- [`${collectPrefix}/x-t/**`]: { proxy: "https://t.co/**" }
221
- }
222
- },
223
- snapchatPixel: {
224
- // Snapchat: untrusted ad network — full anonymization
225
- privacy: { ip: true, userAgent: true, language: true, screen: true, timezone: true, hardware: true },
226
- rewrite: [
227
- { from: "tr.snapchat.com", to: `${collectPrefix}/snap` }
228
- ],
229
- routes: {
230
- [`${collectPrefix}/snap/**`]: { proxy: "https://tr.snapchat.com/**" }
231
- }
232
- },
233
- redditPixel: {
234
- // Reddit: untrusted ad network — full anonymization
235
- privacy: { ip: true, userAgent: true, language: true, screen: true, timezone: true, hardware: true },
236
- rewrite: [
237
- { from: "alb.reddit.com", to: `${collectPrefix}/reddit` },
238
- { from: "pixel-config.reddit.com", to: `${collectPrefix}/reddit-cfg` }
239
- ],
240
- routes: {
241
- [`${collectPrefix}/reddit/**`]: { proxy: "https://alb.reddit.com/**" },
242
- [`${collectPrefix}/reddit-cfg/**`]: { proxy: "https://pixel-config.reddit.com/**" }
243
- }
244
- },
245
- clarity: {
246
- // Clarity: screen/UA/timezone needed for heatmaps and device filtering; rest anonymized
247
- privacy: { ip: true, userAgent: false, language: true, screen: false, timezone: false, hardware: true },
248
- rewrite: [
249
- // Main clarity domain
250
- { from: "www.clarity.ms", to: `${collectPrefix}/clarity` },
251
- // Script loader (the actual SDK is loaded from here)
252
- { from: "scripts.clarity.ms", to: `${collectPrefix}/clarity-scripts` },
253
- // Data collection endpoint
254
- { from: "d.clarity.ms", to: `${collectPrefix}/clarity-data` },
255
- // Event collection endpoint
256
- { from: "e.clarity.ms", to: `${collectPrefix}/clarity-events` }
257
- ],
258
- routes: {
259
- [`${collectPrefix}/clarity/**`]: { proxy: "https://www.clarity.ms/**" },
260
- [`${collectPrefix}/clarity-scripts/**`]: { proxy: "https://scripts.clarity.ms/**" },
261
- [`${collectPrefix}/clarity-data/**`]: { proxy: "https://d.clarity.ms/**" },
262
- [`${collectPrefix}/clarity-events/**`]: { proxy: "https://e.clarity.ms/**" }
263
- }
264
- },
265
- posthog: {
266
- // No rewrites needed - PostHog uses NPM mode, SDK URLs are set via api_host config
267
- // PostHog: needs real IP for GeoIP enrichment + feature flag targeting
268
- privacy: { ip: false, userAgent: false, language: false, screen: false, timezone: false, hardware: false },
269
- routes: {
270
- // US region
271
- [`${collectPrefix}/ph/static/**`]: { proxy: "https://us-assets.i.posthog.com/static/**" },
272
- [`${collectPrefix}/ph/**`]: { proxy: "https://us.i.posthog.com/**" },
273
- // EU region
274
- [`${collectPrefix}/ph-eu/static/**`]: { proxy: "https://eu-assets.i.posthog.com/static/**" },
275
- [`${collectPrefix}/ph-eu/**`]: { proxy: "https://eu.i.posthog.com/**" }
276
- }
277
- },
278
- hotjar: {
279
- // Hotjar: screen/UA/timezone needed for heatmaps and device segmentation; rest anonymized
280
- privacy: { ip: true, userAgent: false, language: true, screen: false, timezone: false, hardware: true },
281
- rewrite: [
282
- // Static assets
283
- { from: "static.hotjar.com", to: `${collectPrefix}/hotjar` },
284
- // Script loader (bootstrap script loads the main SDK from here)
285
- { from: "script.hotjar.com", to: `${collectPrefix}/hotjar-script` },
286
- // Configuration/variables
287
- { from: "vars.hotjar.com", to: `${collectPrefix}/hotjar-vars` },
288
- // Data ingestion endpoint
289
- { from: "in.hotjar.com", to: `${collectPrefix}/hotjar-in` },
290
- // Video capture
291
- { from: "vc.hotjar.com", to: `${collectPrefix}/hotjar-vc` },
292
- // Metrics/telemetry
293
- { from: "metrics.hotjar.io", to: `${collectPrefix}/hotjar-metrics` },
294
- // Insights (ContentSquare integration)
295
- { from: "insights.hotjar.com", to: `${collectPrefix}/hotjar-insights` }
296
- ],
297
- routes: {
298
- [`${collectPrefix}/hotjar/**`]: { proxy: "https://static.hotjar.com/**" },
299
- [`${collectPrefix}/hotjar-script/**`]: { proxy: "https://script.hotjar.com/**" },
300
- [`${collectPrefix}/hotjar-vars/**`]: { proxy: "https://vars.hotjar.com/**" },
301
- [`${collectPrefix}/hotjar-in/**`]: { proxy: "https://in.hotjar.com/**" },
302
- [`${collectPrefix}/hotjar-vc/**`]: { proxy: "https://vc.hotjar.com/**" },
303
- [`${collectPrefix}/hotjar-metrics/**`]: { proxy: "https://metrics.hotjar.io/**" },
304
- [`${collectPrefix}/hotjar-insights/**`]: { proxy: "https://insights.hotjar.com/**" }
305
- }
306
- },
307
- plausible: {
308
- privacy: { ip: false, userAgent: false, language: false, screen: false, timezone: false, hardware: false },
309
- rewrite: [
310
- { from: "plausible.io", to: `${collectPrefix}/plausible` }
311
- ],
312
- routes: {
313
- [`${collectPrefix}/plausible/**`]: { proxy: "https://plausible.io/**" }
314
- }
315
- },
316
- cloudflareWebAnalytics: {
317
- privacy: { ip: false, userAgent: false, language: false, screen: false, timezone: false, hardware: false },
318
- rewrite: [
319
- { from: "static.cloudflareinsights.com", to: `${collectPrefix}/cfwa` },
320
- { from: "cloudflareinsights.com", to: `${collectPrefix}/cfwa-beacon` }
321
- ],
322
- routes: {
323
- [`${collectPrefix}/cfwa/**`]: { proxy: "https://static.cloudflareinsights.com/**" },
324
- [`${collectPrefix}/cfwa-beacon/**`]: { proxy: "https://cloudflareinsights.com/**" }
325
- }
326
- },
327
- rybbit: {
328
- privacy: { ip: false, userAgent: false, language: false, screen: false, timezone: false, hardware: false },
329
- rewrite: [
330
- { from: "app.rybbit.io", to: `${collectPrefix}/rybbit` }
331
- ],
332
- routes: {
333
- [`${collectPrefix}/rybbit/**`]: { proxy: "https://app.rybbit.io/**" }
82
+ const DEVTOOLS_UI_ROUTE = "/__nuxt-scripts";
83
+ const DEVTOOLS_UI_LOCAL_PORT = 3030;
84
+ const DEVTOOLS_API_STATE_ROUTE = "/__nuxt-scripts-api/state";
85
+ async function setupDevtools(nuxt, options = {}) {
86
+ const { addCustomTab } = await import('@nuxt/devtools-kit');
87
+ const { resolve } = createResolver(import.meta.url);
88
+ const clientPath = resolve("../dist/devtools-client");
89
+ const isProductionBuild = existsSync(clientPath);
90
+ if (isProductionBuild) {
91
+ nuxt.hook("vite:serverCreated", async (server) => {
92
+ const sirv = await import('sirv').then((r) => r.default || r);
93
+ server.middlewares.use(DEVTOOLS_UI_ROUTE, sirv(clientPath, { dev: true, single: true }));
94
+ });
95
+ } else {
96
+ extendViteConfig((config) => {
97
+ config.server = config.server || {};
98
+ config.server.proxy = config.server.proxy || {};
99
+ config.server.proxy[DEVTOOLS_UI_ROUTE] = {
100
+ target: `http://localhost:${DEVTOOLS_UI_LOCAL_PORT}${DEVTOOLS_UI_ROUTE}`,
101
+ changeOrigin: true,
102
+ followRedirects: true,
103
+ rewrite: (path) => path.replace(DEVTOOLS_UI_ROUTE, "")
104
+ };
105
+ });
106
+ }
107
+ if (options.standalone) {
108
+ setupStandaloneApi(nuxt);
109
+ }
110
+ addCustomTab({
111
+ name: "nuxt-scripts",
112
+ title: "Scripts",
113
+ icon: "carbon:script",
114
+ view: {
115
+ type: "iframe",
116
+ src: DEVTOOLS_UI_ROUTE
117
+ }
118
+ });
119
+ }
120
+ function setupStandaloneApi(nuxt) {
121
+ let scriptsState = {
122
+ scripts: {},
123
+ updatedAt: 0
124
+ };
125
+ nuxt.hook("vite:serverCreated", (server) => {
126
+ server.middlewares.use(DEVTOOLS_API_STATE_ROUTE, (req, res) => {
127
+ res.setHeader("Access-Control-Allow-Origin", "*");
128
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
129
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type");
130
+ if (req.method === "OPTIONS") {
131
+ res.statusCode = 204;
132
+ res.end();
133
+ return;
334
134
  }
335
- },
336
- umami: {
337
- privacy: { ip: false, userAgent: false, language: false, screen: false, timezone: false, hardware: false },
338
- rewrite: [
339
- { from: "cloud.umami.is", to: `${collectPrefix}/umami` }
340
- ],
341
- routes: {
342
- [`${collectPrefix}/umami/**`]: { proxy: "https://cloud.umami.is/**" }
135
+ if (req.method === "GET") {
136
+ res.setHeader("Content-Type", "application/json");
137
+ res.end(JSON.stringify(scriptsState));
138
+ return;
343
139
  }
344
- },
345
- databuddy: {
346
- privacy: { ip: false, userAgent: false, language: false, screen: false, timezone: false, hardware: false },
347
- rewrite: [
348
- { from: "cdn.databuddy.cc", to: `${collectPrefix}/databuddy` },
349
- { from: "basket.databuddy.cc", to: `${collectPrefix}/databuddy-api` }
350
- ],
351
- routes: {
352
- [`${collectPrefix}/databuddy/**`]: { proxy: "https://cdn.databuddy.cc/**" },
353
- [`${collectPrefix}/databuddy-api/**`]: { proxy: "https://basket.databuddy.cc/**" }
140
+ if (req.method === "POST") {
141
+ let body = "";
142
+ req.on("data", (chunk) => {
143
+ body += chunk.toString();
144
+ });
145
+ req.on("end", () => {
146
+ try {
147
+ const data = JSON.parse(body);
148
+ scriptsState = { ...data, updatedAt: Date.now() };
149
+ res.statusCode = 200;
150
+ res.end("ok");
151
+ } catch {
152
+ res.statusCode = 400;
153
+ res.end("invalid json");
154
+ }
155
+ });
156
+ return;
354
157
  }
355
- },
356
- fathom: {
357
- privacy: { ip: false, userAgent: false, language: false, screen: false, timezone: false, hardware: false },
358
- rewrite: [
359
- { from: "cdn.usefathom.com", to: `${collectPrefix}/fathom` }
360
- ],
361
- routes: {
362
- [`${collectPrefix}/fathom/**`]: { proxy: "https://cdn.usefathom.com/**" }
158
+ res.statusCode = 405;
159
+ res.end("method not allowed");
160
+ });
161
+ });
162
+ }
163
+ function computeDevtoolsPrivacyLevel(privacy) {
164
+ const flags = Object.values(privacy);
165
+ if (flags.every(Boolean))
166
+ return "full";
167
+ if (flags.some(Boolean))
168
+ return "partial";
169
+ return "none";
170
+ }
171
+ function buildDevtoolsEntry(key, script, configKey, proxyConfig) {
172
+ const privacy = proxyConfig.privacy;
173
+ const normalizedPrivacy = {
174
+ ip: !!privacy.ip,
175
+ userAgent: !!privacy.userAgent,
176
+ language: !!privacy.language,
177
+ screen: !!privacy.screen,
178
+ timezone: !!privacy.timezone,
179
+ hardware: !!privacy.hardware
180
+ };
181
+ const logo = script.logo;
182
+ const logoStr = typeof logo === "object" ? logo.dark || logo.light : logo || "";
183
+ return {
184
+ registryKey: key,
185
+ label: script.label || key,
186
+ logo: logoStr,
187
+ category: script.category || "unknown",
188
+ configKey,
189
+ mechanism: script.src === false ? "config-injection-proxy" : "bundle-rewrite-intercept",
190
+ hasAutoInject: !!proxyConfig.autoInject,
191
+ autoInjectField: proxyConfig.autoInject?.configField,
192
+ hasPostProcess: !!proxyConfig.sdkPatches?.length,
193
+ privacy: normalizedPrivacy,
194
+ privacyLevel: computeDevtoolsPrivacyLevel(normalizedPrivacy),
195
+ domains: [...proxyConfig.domains]
196
+ };
197
+ }
198
+ function buildDevtoolsData(proxyPrefix, privacyLabel, scripts) {
199
+ const allDomains = /* @__PURE__ */ new Set();
200
+ for (const s of scripts) {
201
+ for (const d of s.domains)
202
+ allDomains.add(d);
203
+ }
204
+ return {
205
+ enabled: true,
206
+ proxyPrefix,
207
+ privacyMode: privacyLabel,
208
+ scripts,
209
+ totalDomains: allDomains.size
210
+ };
211
+ }
212
+
213
+ const isStackblitz = provider === "stackblitz";
214
+ async function promptToInstall(name, installCommand, options) {
215
+ if (await resolvePackageJSON(name).catch(() => null))
216
+ return true;
217
+ logger$1.info(`Package ${name} is missing`);
218
+ if (isCI)
219
+ return false;
220
+ if (options.prompt === true || options.prompt !== false && !isStackblitz) {
221
+ const confirm = await logger$1.prompt(`Do you want to install ${name} package?`, {
222
+ type: "confirm",
223
+ name: "confirm",
224
+ initial: true
225
+ });
226
+ if (!confirm)
227
+ return false;
228
+ }
229
+ logger$1.info(`Installing ${name}...`);
230
+ try {
231
+ await installCommand();
232
+ logger$1.success(`Installed ${name}`);
233
+ return true;
234
+ } catch (err) {
235
+ logger$1.error(err);
236
+ return false;
237
+ }
238
+ }
239
+ const installPrompts = /* @__PURE__ */ new Set();
240
+ function installNuxtModule(name, options) {
241
+ if (installPrompts.has(name))
242
+ return;
243
+ installPrompts.add(name);
244
+ const nuxt = tryUseNuxt();
245
+ if (!nuxt)
246
+ return;
247
+ return promptToInstall(name, async () => {
248
+ const { runCommand } = await import(String("nuxi"));
249
+ await runCommand("module", ["add", name, "--cwd", nuxt.options.rootDir]);
250
+ }, { rootDir: nuxt.options.rootDir, searchPaths: nuxt.options.modulesDir, ...options });
251
+ }
252
+
253
+ const logger = useLogger("@nuxt/scripts");
254
+
255
+ const SCRIPT_OPTION_KEYS = ["trigger", "proxy", "bundle", "partytown"];
256
+ function extractRequiredFields(schema) {
257
+ if (!schema)
258
+ return [];
259
+ return Object.entries(schema.entries).filter(([, field]) => field?.type !== "optional").map(([key]) => key);
260
+ }
261
+ function migrateDeprecatedRegistryKeys(registry, warn) {
262
+ for (const key of Object.keys(registry)) {
263
+ const entry = registry[key];
264
+ if (!entry || typeof entry !== "object")
265
+ continue;
266
+ if (Array.isArray(entry)) {
267
+ const opts = entry[1];
268
+ if (opts && typeof opts === "object" && "reverseProxyIntercept" in opts) {
269
+ warn(`[nuxt-scripts] registry.${key}: \`reverseProxyIntercept\` has been renamed to \`proxy\`. Please update your config. Auto-migrating for now.`);
270
+ const o = opts;
271
+ o.proxy ??= o.reverseProxyIntercept;
272
+ delete o.reverseProxyIntercept;
363
273
  }
364
- },
365
- intercom: {
366
- privacy: { ip: true, userAgent: false, language: false, screen: false, timezone: false, hardware: false },
367
- rewrite: [
368
- { from: "widget.intercom.io", to: `${collectPrefix}/intercom` },
369
- { from: "api-iam.intercom.io", to: `${collectPrefix}/intercom-api` },
370
- { from: "api-iam.eu.intercom.io", to: `${collectPrefix}/intercom-api-eu` },
371
- { from: "api-iam.au.intercom.io", to: `${collectPrefix}/intercom-api-au` }
372
- ],
373
- routes: {
374
- [`${collectPrefix}/intercom/**`]: { proxy: "https://widget.intercom.io/**" },
375
- [`${collectPrefix}/intercom-api/**`]: { proxy: "https://api-iam.intercom.io/**" },
376
- [`${collectPrefix}/intercom-api-eu/**`]: { proxy: "https://api-iam.eu.intercom.io/**" },
377
- [`${collectPrefix}/intercom-api-au/**`]: { proxy: "https://api-iam.au.intercom.io/**" }
274
+ } else {
275
+ const obj = entry;
276
+ if ("reverseProxyIntercept" in obj) {
277
+ warn(`[nuxt-scripts] registry.${key}: \`reverseProxyIntercept\` has been renamed to \`proxy\`. Please update your config. Auto-migrating for now.`);
278
+ obj.proxy ??= obj.reverseProxyIntercept;
279
+ delete obj.reverseProxyIntercept;
378
280
  }
379
- },
380
- crisp: {
381
- privacy: { ip: true, userAgent: false, language: false, screen: false, timezone: false, hardware: false },
382
- rewrite: [
383
- { from: "client.crisp.chat", to: `${collectPrefix}/crisp` }
384
- ],
385
- routes: {
386
- [`${collectPrefix}/crisp/**`]: { proxy: "https://client.crisp.chat/**" }
281
+ const so = obj.scriptOptions;
282
+ if (so && typeof so === "object" && "reverseProxyIntercept" in so) {
283
+ warn(`[nuxt-scripts] registry.${key}: \`scriptOptions.reverseProxyIntercept\` has been renamed to \`proxy\`. Please update your config. Auto-migrating for now.`);
284
+ const s = so;
285
+ s.proxy ??= s.reverseProxyIntercept;
286
+ delete s.reverseProxyIntercept;
387
287
  }
388
288
  }
389
- };
390
- }
391
- function getProxyConfig(key, collectPrefix) {
392
- const configs = buildProxyConfig(collectPrefix);
393
- return configs[key];
394
- }
395
- function getAllProxyConfigs(collectPrefix) {
396
- return buildProxyConfig(collectPrefix);
289
+ }
397
290
  }
398
- function routesToInterceptRules(routes) {
399
- const rules = [];
400
- for (const [localPath, { proxy }] of Object.entries(routes)) {
401
- const match = proxy.match(/^https?:\/\/([^/]+)(\/.*)?\/\*\*$/);
402
- if (match?.[1]) {
403
- const domain = match[1];
404
- const pathPrefix = match[2] || "";
405
- const target = localPath.replace(/\/\*\*$/, "");
406
- rules.push({ pattern: domain, pathPrefix, target });
291
+ function normalizeRegistryConfig(registry, warn) {
292
+ for (const key of Object.keys(registry)) {
293
+ const entry = registry[key];
294
+ if (!entry) {
295
+ delete registry[key];
296
+ continue;
297
+ }
298
+ if (entry === true) {
299
+ warn?.(`[nuxt-scripts] registry.${key}: \`true\` shorthand is deprecated. Use \`{ trigger: 'onNuxtReady' }\` instead.`);
300
+ registry[key] = [{}, { trigger: "onNuxtReady" }];
301
+ continue;
302
+ }
303
+ if (entry === "proxy-only") {
304
+ throw new Error(
305
+ `[nuxt-scripts] registry.${key}: \`'proxy-only'\` is no longer supported. Use \`{}\` instead (infrastructure only is now the default behavior).`
306
+ );
307
+ }
308
+ if (entry === "mock") {
309
+ registry[key] = [{}, { trigger: "manual", skipValidation: true }];
310
+ } else if (Array.isArray(entry)) {
311
+ if (!entry[0] && !entry[1]) {
312
+ delete registry[key];
313
+ continue;
314
+ }
315
+ if (!entry[0])
316
+ entry[0] = {};
317
+ } else if (typeof entry === "object") {
318
+ const { scriptOptions, ...rest } = entry;
319
+ const input = {};
320
+ const mergedScriptOptions = {};
321
+ if (scriptOptions && typeof scriptOptions === "object")
322
+ Object.assign(mergedScriptOptions, scriptOptions);
323
+ for (const [k, v] of Object.entries(rest)) {
324
+ if (SCRIPT_OPTION_KEYS.includes(k))
325
+ mergedScriptOptions[k] = v;
326
+ else
327
+ input[k] = v;
328
+ }
329
+ registry[key] = Object.keys(mergedScriptOptions).length > 0 ? [input, mergedScriptOptions] : [input];
330
+ } else {
331
+ delete registry[key];
407
332
  }
408
333
  }
409
- return rules;
410
334
  }
411
335
 
412
336
  function isVue(id, opts = {}) {
@@ -430,12 +354,138 @@ function isVue(id, opts = {}) {
430
354
  }
431
355
  return true;
432
356
  }
433
- const JS_RE = /\.(?:[cm]?j|t)sx?$/;
357
+ const JS_RE$1 = /\.(?:[cm]?j|t)sx?$/;
434
358
  function isJS(id) {
435
359
  const { pathname } = parseURL(decodeURIComponent(pathToFileURL(id).href));
436
- return JS_RE.test(pathname);
360
+ return JS_RE$1.test(pathname);
437
361
  }
438
362
 
363
+ const VUE_RE$1 = /\.vue/;
364
+ function NuxtScriptsCheckScripts() {
365
+ return createUnplugin(() => {
366
+ return {
367
+ name: "nuxt-scripts:check-scripts",
368
+ transform: {
369
+ filter: {
370
+ id: VUE_RE$1
371
+ },
372
+ handler(code, id) {
373
+ if (!isVue(id, { type: ["script"] }))
374
+ return;
375
+ if (!code.includes("useScript"))
376
+ return;
377
+ let nameNode;
378
+ let errorNode;
379
+ parseAndWalk(code, id, (_node) => {
380
+ if (_node.type === "VariableDeclaration" && _node.declarations?.[0]?.id?.type === "ObjectPattern") {
381
+ const objPattern = _node.declarations[0]?.id;
382
+ for (const property of objPattern.properties) {
383
+ if (property.type === "Property" && property.key.type === "Identifier" && property.key.name === "$script" && property.value.type === "Identifier") {
384
+ nameNode = _node;
385
+ }
386
+ }
387
+ }
388
+ if (nameNode) {
389
+ let sequence = _node.type === "SequenceExpression" ? _node : null;
390
+ let assignmentExpression;
391
+ if (_node.type === "VariableDeclaration") {
392
+ if (_node.declarations[0]?.init?.type === "SequenceExpression") {
393
+ sequence = _node.declarations[0]?.init;
394
+ assignmentExpression = _node.declarations[0]?.init?.expressions?.[0];
395
+ }
396
+ }
397
+ if (sequence && !assignmentExpression) {
398
+ assignmentExpression = sequence.expressions[0]?.type === "AssignmentExpression" ? sequence.expressions[0] : null;
399
+ }
400
+ if (assignmentExpression) {
401
+ const right = assignmentExpression?.right;
402
+ if (right.callee?.name === "_withAsyncContext") {
403
+ if (right.arguments[0]?.body?.name === "$script" || right.arguments[0]?.body?.callee?.object?.name === "$script") {
404
+ errorNode = nameNode;
405
+ }
406
+ }
407
+ }
408
+ }
409
+ });
410
+ if (errorNode) {
411
+ return this.error(new Error("You can't use a top-level await on $script as it will never resolve."));
412
+ }
413
+ }
414
+ }
415
+ };
416
+ });
417
+ }
418
+
419
+ function generateInterceptPluginContents(proxyPrefix, options) {
420
+ const testMode = options?.testMode ?? false;
421
+ return `export default defineNuxtPlugin({
422
+ name: 'nuxt-scripts:intercept',
423
+ enforce: 'pre',
424
+ setup() {
425
+ const proxyPrefix = ${JSON.stringify(proxyPrefix)};
426
+ const origBeacon = typeof navigator !== 'undefined' && navigator.sendBeacon
427
+ ? navigator.sendBeacon.bind(navigator)
428
+ : () => false;
429
+ const origFetch = globalThis.fetch.bind(globalThis);
430
+
431
+ function proxyUrl(url) {
432
+ try {
433
+ const parsed = new URL(url, location.origin);
434
+ if (parsed.origin !== location.origin)
435
+ return location.origin + proxyPrefix + '/' + parsed.host + parsed.pathname + parsed.search;
436
+ } catch {}
437
+ return url;
438
+ }
439
+
440
+ // XMLHttpRequest wrapper \u2014 intercepts .open() to rewrite URL
441
+ const OrigXHR = XMLHttpRequest;
442
+ class ProxiedXHR extends OrigXHR {
443
+ open() {
444
+ const args = Array.from(arguments);
445
+ if (typeof args[1] === 'string') args[1] = proxyUrl(args[1]);
446
+ return super.open.apply(this, args);
447
+ }
448
+ }
449
+ // Image wrapper \u2014 intercepts .src setter to rewrite URL
450
+ const OrigImage = Image;
451
+ const origSrcDesc = Object.getOwnPropertyDescriptor(HTMLImageElement.prototype, 'src');
452
+ function ProxiedImage(w, h) {
453
+ const img = arguments.length === 2 ? new OrigImage(w, h)
454
+ : arguments.length === 1 ? new OrigImage(w) : new OrigImage();
455
+ if (origSrcDesc && origSrcDesc.set) {
456
+ Object.defineProperty(img, 'src', {
457
+ get() { return origSrcDesc.get.call(this); },
458
+ set(v) { origSrcDesc.set.call(this, typeof v === 'string' ? proxyUrl(v) : v); },
459
+ configurable: true,
460
+ });
461
+ }
462
+ return img;
463
+ }
464
+
465
+ globalThis.__nuxtScripts = {${testMode ? `
466
+ // Test mode: replace sendBeacon with fetch for immediate, observable requests
467
+ sendBeacon: (url, data) => {
468
+ const proxied = proxyUrl(url);
469
+ origFetch(proxied, { method: 'POST', body: data, keepalive: true }).catch(() => {});
470
+ return true;
471
+ },` : `
472
+ sendBeacon: (url, data) => origBeacon(proxyUrl(url), data),`}
473
+ fetch: (url, opts) => {
474
+ if (typeof url === 'string') return origFetch(proxyUrl(url), opts);
475
+ if (url instanceof Request) return origFetch(new Request(proxyUrl(url.url), url), opts);
476
+ return origFetch(url, opts);
477
+ },
478
+ XMLHttpRequest: ProxiedXHR,
479
+ Image: ProxiedImage,
480
+ };
481
+ },
482
+ })
483
+ `;
484
+ }
485
+
486
+ const WORD_OR_DOLLAR_RE = /[\w$]/;
487
+ const PROTOCOL_PREFIX_RE = /^https?:$/;
488
+ const BLANK_CANVAS_DATA_URL = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQIHWNgAAIABQABNjN9GQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAAA0lEQVQI12NgYGBgAAAABQABXvMqOgAAAABJRU5ErkJggg==";
439
489
  function isPropertyKeyAST(parent, ctx) {
440
490
  return parent?.type === "Property" && ctx.key === "key" || parent?.type === "SwitchCase" && ctx.key === "test";
441
491
  }
@@ -445,7 +495,8 @@ function matchAndRewrite(value, rewrites) {
445
495
  const fromSlashIdx = from.indexOf("/");
446
496
  const fromHost = fromSlashIdx > 0 ? from.slice(0, fromSlashIdx) : from;
447
497
  const fromPath = fromSlashIdx > 0 ? from.slice(fromSlashIdx) : "";
448
- if (!value.includes(fromHost)) continue;
498
+ if (!value.includes(fromHost))
499
+ continue;
449
500
  const url = parseURL(value);
450
501
  let shouldRewrite = false;
451
502
  let rewriteSuffix = "";
@@ -488,63 +539,240 @@ function matchAndRewrite(value, rewrites) {
488
539
  }
489
540
  return null;
490
541
  }
491
- function rewriteScriptUrlsAST(content, filename, rewrites) {
492
- const s = new MagicString(content);
493
- parseAndWalk(content, filename, function(node, parent, ctx) {
494
- if (node.type === "Literal" && typeof node.value === "string") {
495
- const value = node.value;
496
- const rewritten = matchAndRewrite(value, rewrites);
497
- if (rewritten === null) return;
498
- const quote = content[node.start];
499
- if (isPropertyKeyAST(parent, ctx)) {
500
- s.overwrite(node.start, node.end, quote + rewritten + quote);
501
- } else {
502
- s.overwrite(node.start, node.end, "self.location.origin+" + quote + rewritten + quote);
542
+ const WINDOW_GLOBALS = /* @__PURE__ */ new Set(["window", "self", "globalThis"]);
543
+ const NAVIGATOR_GLOBALS = /* @__PURE__ */ new Set(["navigator"]);
544
+ function resolveToGlobal(name, scopeTracker, depth = 0) {
545
+ if (depth > 10)
546
+ return null;
547
+ const decl = scopeTracker.getDeclaration(name);
548
+ if (!decl)
549
+ return name;
550
+ if (decl instanceof ScopeTrackerFunctionParam)
551
+ return null;
552
+ if (decl instanceof ScopeTrackerVariable) {
553
+ const declarators = decl.variableNode.declarations;
554
+ if (!declarators)
555
+ return null;
556
+ for (const declarator of declarators) {
557
+ const id = declarator.id;
558
+ if (!id || id.name !== name)
559
+ continue;
560
+ const init = declarator.init;
561
+ if (!init)
562
+ return null;
563
+ if (init.type === "Identifier")
564
+ return resolveToGlobal(init.name, scopeTracker, depth + 1);
565
+ if (init.type === "MemberExpression" && init.object?.type === "Identifier") {
566
+ const memberProp = init.computed ? init.property?.type === "Literal" && typeof init.property.value === "string" ? init.property.value : null : init.property?.type === "Identifier" ? init.property.name : null;
567
+ if (!memberProp)
568
+ return null;
569
+ const objGlobal = resolveToGlobal(init.object.name, scopeTracker, depth + 1);
570
+ if (!objGlobal)
571
+ return null;
572
+ if (WINDOW_GLOBALS.has(objGlobal) || objGlobal === "document")
573
+ return memberProp;
574
+ return null;
503
575
  }
576
+ return null;
504
577
  }
505
- if (node.type === "TemplateLiteral" && node.expressions?.length === 0) {
506
- const quasis = node.quasis;
507
- if (quasis?.length === 1) {
508
- const value = quasis[0].value?.cooked ?? quasis[0].value?.raw;
509
- if (typeof value !== "string") return;
578
+ }
579
+ return null;
580
+ }
581
+ function resolveCalleeTarget(callee, scopeTracker) {
582
+ if (callee?.type !== "MemberExpression")
583
+ return null;
584
+ const propName = callee.computed ? callee.property?.type === "Literal" && typeof callee.property.value === "string" ? callee.property.value : null : callee.property?.name;
585
+ if (!propName)
586
+ return null;
587
+ const obj = callee.object;
588
+ if (!obj || obj.type !== "Identifier")
589
+ return null;
590
+ const resolved = resolveToGlobal(obj.name, scopeTracker);
591
+ if (!resolved)
592
+ return null;
593
+ if (propName === "fetch" && WINDOW_GLOBALS.has(resolved))
594
+ return "fetch";
595
+ if (propName === "sendBeacon" && (NAVIGATOR_GLOBALS.has(resolved) || WINDOW_GLOBALS.has(resolved)))
596
+ return "sendBeacon";
597
+ if (propName === "sendBeacon" && resolved === "navigator")
598
+ return "sendBeacon";
599
+ if (propName === "XMLHttpRequest" && WINDOW_GLOBALS.has(resolved))
600
+ return "XMLHttpRequest";
601
+ if (propName === "Image" && WINDOW_GLOBALS.has(resolved))
602
+ return "Image";
603
+ return null;
604
+ }
605
+ function rewriteScriptUrlsAST(content, filename, rewrites, sdkPatches, options) {
606
+ const s = new MagicString(content);
607
+ function needsLeadingSpace(start) {
608
+ const prev = content[start - 1];
609
+ return prev && WORD_OR_DOLLAR_RE.test(prev) ? " " : "";
610
+ }
611
+ const scopeTracker = new ScopeTracker({ preserveExitedScopes: true });
612
+ const { program } = parseAndWalk(content, filename, { scopeTracker });
613
+ scopeTracker.freeze();
614
+ walk(program, {
615
+ scopeTracker,
616
+ enter(node, parent, ctx) {
617
+ if (node.type === "Literal" && typeof node.value === "string") {
618
+ const value = node.value;
510
619
  const rewritten = matchAndRewrite(value, rewrites);
511
- if (rewritten === null) return;
620
+ if (rewritten === null)
621
+ return;
622
+ const quote = content[node.start];
512
623
  if (isPropertyKeyAST(parent, ctx)) {
513
- s.overwrite(node.start, node.end, "`" + rewritten + "`");
624
+ s.overwrite(node.start, node.end, quote + rewritten + quote);
625
+ } else if (value.startsWith("//") && parent?.type === "BinaryExpression" && parent.operator === "+") {
626
+ const sibling = ctx.key === "right" ? parent.left : parent.right;
627
+ if (sibling?.type === "Literal" && typeof sibling.value === "string" && PROTOCOL_PREFIX_RE.test(sibling.value)) {
628
+ s.overwrite(parent.start, parent.end, `${needsLeadingSpace(parent.start)}self.location.origin+${quote}${rewritten}${quote}`);
629
+ } else {
630
+ s.overwrite(node.start, node.end, `${needsLeadingSpace(node.start)}self.location.origin+${quote}${rewritten}${quote}`);
631
+ }
514
632
  } else {
515
- s.overwrite(node.start, node.end, "self.location.origin+`" + rewritten + "`");
633
+ s.overwrite(node.start, node.end, `${needsLeadingSpace(node.start)}self.location.origin+${quote}${rewritten}${quote}`);
634
+ }
635
+ }
636
+ if (node.type === "TemplateLiteral") {
637
+ const quasis = node.quasis;
638
+ const expressions = node.expressions;
639
+ if (expressions?.length === 0 && quasis?.length === 1) {
640
+ const value = quasis[0].value?.cooked ?? quasis[0].value?.raw;
641
+ if (typeof value !== "string")
642
+ return;
643
+ const rewritten = matchAndRewrite(value, rewrites);
644
+ if (rewritten === null)
645
+ return;
646
+ if (isPropertyKeyAST(parent, ctx)) {
647
+ s.overwrite(node.start, node.end, `\`${rewritten}\``);
648
+ } else {
649
+ s.overwrite(node.start, node.end, `${needsLeadingSpace(node.start)}self.location.origin+\`${rewritten}\``);
650
+ }
651
+ } else if (expressions?.length > 0 && quasis?.length > 0) {
652
+ const firstQuasi = quasis[0];
653
+ const value = firstQuasi.value?.cooked ?? firstQuasi.value?.raw;
654
+ if (typeof value !== "string" || isPropertyKeyAST(parent, ctx))
655
+ return;
656
+ const rewritten = matchAndRewrite(value, rewrites);
657
+ if (rewritten === null)
658
+ return;
659
+ s.overwrite(node.start, firstQuasi.end, `${needsLeadingSpace(node.start)}self.location.origin+\`${rewritten}`);
660
+ }
661
+ }
662
+ if (node.type === "CallExpression" && !options?.skipApiRewrites) {
663
+ const callee = node.callee;
664
+ const shouldNeutralizeCanvas = options?.neutralizeCanvas !== false;
665
+ const canvasPropName = shouldNeutralizeCanvas && callee?.type === "MemberExpression" ? callee.computed ? callee.property?.type === "Literal" && typeof callee.property.value === "string" ? callee.property.value : null : callee.property?.name : null;
666
+ if (canvasPropName === "toDataURL" && callee.object) {
667
+ const blankCanvas = `"${BLANK_CANVAS_DATA_URL}"`;
668
+ if (callee.object.type === "Identifier") {
669
+ const decl = scopeTracker.getDeclaration(callee.object.name);
670
+ if (decl instanceof ScopeTrackerFunction || decl instanceof ScopeTrackerIdentifier) ; else {
671
+ s.overwrite(node.start, node.end, blankCanvas);
672
+ return;
673
+ }
674
+ } else {
675
+ s.overwrite(node.start, node.end, blankCanvas);
676
+ return;
677
+ }
678
+ }
679
+ if (canvasPropName === "getExtension") {
680
+ const args = node.arguments;
681
+ if (args?.length === 1 && args[0]?.type === "Literal" && args[0].value === "WEBGL_debug_renderer_info") {
682
+ s.overwrite(node.start, node.end, "null");
683
+ return;
684
+ }
685
+ }
686
+ if (callee?.type === "Identifier" && callee.name === "fetch") {
687
+ if (!scopeTracker.getDeclaration("fetch"))
688
+ s.overwrite(callee.start, callee.end, "__nuxtScripts.fetch");
689
+ return;
690
+ }
691
+ const target = resolveCalleeTarget(callee, scopeTracker);
692
+ if (target === "fetch" || target === "sendBeacon") {
693
+ s.overwrite(callee.start, callee.end, `__nuxtScripts.${target}`);
694
+ return;
695
+ }
696
+ if (callee?.type === "MemberExpression" && !callee.computed && callee.property?.name === "sendBeacon" && callee.object?.type === "Identifier") {
697
+ const resolved = resolveToGlobal(callee.object.name, scopeTracker);
698
+ if (resolved === null) {
699
+ s.overwrite(callee.start, callee.end, "__nuxtScripts.sendBeacon");
700
+ }
516
701
  }
517
702
  }
518
- }
519
- if (node.type === "CallExpression") {
520
- const callee = node.callee;
521
- if (callee?.type === "MemberExpression" && !callee.computed && callee.object?.type === "Identifier" && callee.object.name === "navigator" && callee.property?.name === "sendBeacon") {
522
- s.overwrite(callee.start, callee.end, "__nuxtScripts.sendBeacon");
703
+ if (sdkPatches?.some((p) => p.type === "neutralize-domain-check") && node.type === "BinaryExpression" && node.operator === "<") {
704
+ const left = node.left;
705
+ const right = node.right;
706
+ if (right?.type === "Literal" && right.value === 0 && left?.type === "CallExpression" && left.callee?.type === "MemberExpression") {
707
+ const prop = left.callee.computed ? left.callee.property?.type === "Literal" && typeof left.callee.property.value === "string" ? left.callee.property.value : null : left.callee.property?.name;
708
+ if (prop === "indexOf" && left.arguments?.length === 1) {
709
+ const arg = left.arguments[0];
710
+ if (arg?.type === "Literal" && typeof arg.value === "string" && rewrites.some((r) => arg.value.includes(r.from))) {
711
+ s.overwrite(right.start, right.end, "-1");
712
+ }
713
+ }
714
+ }
523
715
  }
524
- if (callee?.type === "Identifier" && callee.name === "fetch") {
525
- s.overwrite(callee.start, callee.end, "__nuxtScripts.fetch");
716
+ if (sdkPatches?.some((p) => p.type === "replace-src-split") && node.type === "MemberExpression" && node.computed) {
717
+ const prop = node.property;
718
+ const obj = node.object;
719
+ if (prop?.type === "Literal" && prop.value === 0 && obj?.type === "CallExpression" && obj.callee?.type === "MemberExpression") {
720
+ const callProp = obj.callee.computed ? obj.callee.property?.type === "Literal" && typeof obj.callee.property.value === "string" ? obj.callee.property.value : null : obj.callee.property?.name;
721
+ if (callProp === "split" && obj.arguments?.length === 1) {
722
+ const arg = obj.arguments[0];
723
+ if (arg?.type === "Literal" && typeof arg.value === "string") {
724
+ for (const patch of sdkPatches) {
725
+ if (patch.type !== "replace-src-split" || patch.separator !== arg.value)
726
+ continue;
727
+ const rewrite = rewrites.find((r) => r.from === patch.fromDomain);
728
+ if (!rewrite)
729
+ continue;
730
+ const proxyPath = patch.appendPath ? `${rewrite.to}/${patch.appendPath}` : rewrite.to;
731
+ s.overwrite(node.start, node.end, `${needsLeadingSpace(node.start)}self.location.origin+"${proxyPath}"`);
732
+ }
733
+ }
734
+ }
735
+ }
526
736
  }
527
- if (callee?.type === "MemberExpression" && !callee.computed && callee.object?.type === "Identifier" && (callee.object.name === "window" || callee.object.name === "self" || callee.object.name === "globalThis") && callee.property?.name === "fetch") {
528
- s.overwrite(callee.start, callee.end, "__nuxtScripts.fetch");
737
+ if (node.type === "NewExpression" && !options?.skipApiRewrites) {
738
+ const callee = node.callee;
739
+ if (callee?.type === "Identifier" && callee.name === "XMLHttpRequest") {
740
+ if (!scopeTracker.getDeclaration("XMLHttpRequest"))
741
+ s.overwrite(callee.start, callee.end, "__nuxtScripts.XMLHttpRequest");
742
+ return;
743
+ }
744
+ if (callee?.type === "Identifier" && callee.name === "Image") {
745
+ if (!scopeTracker.getDeclaration("Image"))
746
+ s.overwrite(callee.start, callee.end, "__nuxtScripts.Image");
747
+ return;
748
+ }
749
+ const target = resolveCalleeTarget(callee, scopeTracker);
750
+ if (target === "XMLHttpRequest" || target === "Image") {
751
+ s.overwrite(callee.start, callee.end, `__nuxtScripts.${target}`);
752
+ return;
753
+ }
754
+ if (callee?.type === "MemberExpression" && callee.object?.type === "Identifier") {
755
+ const propName = callee.computed ? callee.property?.type === "Literal" && typeof callee.property.value === "string" ? callee.property.value : null : callee.property?.name;
756
+ if (propName === "XMLHttpRequest" || propName === "Image") {
757
+ const resolved = resolveToGlobal(callee.object.name, scopeTracker);
758
+ if (resolved === null) {
759
+ s.overwrite(callee.start, callee.end, `__nuxtScripts.${propName}`);
760
+ }
761
+ }
762
+ }
529
763
  }
530
764
  }
531
765
  });
532
- let output = s.toString();
533
- const gaRewrite = rewrites.find((r) => r.from.includes("google-analytics.com/g/collect"));
534
- if (gaRewrite) {
535
- output = output.replace(
536
- /"https:\/\/"\+\(.*?\)\+"\.google-analytics\.com\/g\/collect"/g,
537
- `self.location.origin+"${gaRewrite.to}"`
538
- );
539
- output = output.replace(
540
- /"https:\/\/"\+\(.*?\)\+"\.analytics\.google\.com\/g\/collect"/g,
541
- `self.location.origin+"${gaRewrite.to}"`
542
- );
543
- }
544
- return output;
766
+ return s.toString();
545
767
  }
546
768
 
547
769
  const SEVEN_DAYS_IN_MS = 7 * 24 * 60 * 60 * 1e3;
770
+ const PROTOCOL_RELATIVE_RE = /^\/\//;
771
+ const VUE_RE = /\.vue/;
772
+ const JS_RE = /\.[cm]?[jt]sx?$/;
773
+ const TEST_RE = /\.(?:test|spec)\./;
774
+ const UPPERCASE_RE = /^[A-Z]$/;
775
+ const USE_SCRIPT_RE = /^useScript/;
548
776
  function calculateIntegrity(content, algorithm = "sha384") {
549
777
  const hash = createHash(algorithm).update(content).digest("base64");
550
778
  return `${algorithm}-${hash}`;
@@ -557,9 +785,9 @@ async function isCacheExpired(storage, filename, cacheMaxAge = SEVEN_DAYS_IN_MS)
557
785
  }
558
786
  return Date.now() - meta.timestamp > cacheMaxAge;
559
787
  }
560
- function normalizeScriptData(src, assetsBaseURL = "/_scripts") {
788
+ function normalizeScriptData(src, assetsBaseURL = "/_scripts/assets") {
561
789
  if (hasProtocol(src, { acceptRelative: true })) {
562
- src = src.replace(/^\/\//, "https://");
790
+ src = src.replace(PROTOCOL_RELATIVE_RE, "https://");
563
791
  const url = parseURL(src);
564
792
  const h = hash(url);
565
793
  const file = `${h.startsWith("-") ? `_${h.slice(1)}` : h}.js`;
@@ -571,7 +799,7 @@ function normalizeScriptData(src, assetsBaseURL = "/_scripts") {
571
799
  return { url: src };
572
800
  }
573
801
  async function downloadScript(opts, renderedScript, fetchOptions, cacheMaxAge) {
574
- const { src, url, filename, forceDownload, integrity, proxyRewrites } = opts;
802
+ const { src, url, filename, forceDownload, integrity, proxyRewrites, sdkPatches, skipApiRewrites, neutralizeCanvas } = opts;
575
803
  if (src === url || !filename) {
576
804
  return;
577
805
  }
@@ -609,7 +837,7 @@ async function downloadScript(opts, renderedScript, fetchOptions, cacheMaxAge) {
609
837
  await storage.setItemRaw(`bundle:${filename}`, res);
610
838
  if (proxyRewrites?.length && res) {
611
839
  const content = res.toString("utf-8");
612
- const rewritten = rewriteScriptUrlsAST(content, filename || "script.js", proxyRewrites);
840
+ const rewritten = rewriteScriptUrlsAST(content, filename || "script.js", proxyRewrites, sdkPatches, { skipApiRewrites, neutralizeCanvas });
613
841
  res = Buffer.from(rewritten, "utf-8");
614
842
  logger.debug(`Rewrote ${proxyRewrites.length} URL patterns in ${filename}`);
615
843
  }
@@ -666,8 +894,8 @@ function NuxtScriptBundleTransformer(options = {
666
894
  transform: {
667
895
  filter: {
668
896
  id: {
669
- include: [/\.vue/, /\.[cm]?[jt]sx?$/],
670
- exclude: [/\.(?:test|spec)\./]
897
+ include: [VUE_RE, JS_RE],
898
+ exclude: [TEST_RE]
671
899
  }
672
900
  },
673
901
  async handler(code, id) {
@@ -677,19 +905,20 @@ function NuxtScriptBundleTransformer(options = {
677
905
  return;
678
906
  const s = new MagicString(code);
679
907
  const deferredOps = [];
680
- parseAndWalk(code, id, function(_node) {
908
+ parseAndWalk(code, id, (_node) => {
681
909
  const calleeName = _node.callee?.name;
682
910
  if (!calleeName)
683
911
  return;
684
- const isValidCallee = calleeName === "useScript" || calleeName?.startsWith("useScript") && /^[A-Z]$/.test(calleeName?.charAt(9)) && !calleeName.startsWith("useScriptTrigger") && !calleeName.startsWith("useScriptEvent");
912
+ const isValidCallee = calleeName === "useScript" || calleeName?.startsWith("useScript") && UPPERCASE_RE.test(calleeName?.charAt(9)) && !calleeName.startsWith("useScriptTrigger") && !calleeName.startsWith("useScriptEvent");
685
913
  if (_node.type === "CallExpression" && _node.callee.type === "Identifier" && isValidCallee) {
686
914
  const fnName = _node.callee?.name;
687
915
  const node = _node;
688
916
  let scriptSrcNode;
689
917
  let src;
918
+ let registryConfig = {};
690
919
  let registryKey;
691
920
  if (fnName !== "useScript") {
692
- const baseName = fnName.replace(/^useScript/, "");
921
+ const baseName = fnName.replace(USE_SCRIPT_RE, "");
693
922
  registryKey = baseName.length > 0 ? baseName.charAt(0).toLowerCase() + baseName.slice(1) : void 0;
694
923
  }
695
924
  if (fnName === "useScript") {
@@ -706,9 +935,10 @@ function NuxtScriptBundleTransformer(options = {
706
935
  if (!registryNode) {
707
936
  return;
708
937
  }
709
- if (!registryNode.scriptBundling && !registryNode.src)
938
+ const bundleResolve = getBundleResolve(registryNode);
939
+ if (!bundleResolve && !registryNode.src)
710
940
  return;
711
- const registryConfig = options.registryConfig?.[registryKey || ""] || {};
941
+ registryConfig = options.registryConfig?.[registryKey || ""] || {};
712
942
  const fnArg0 = {};
713
943
  if (node.arguments[0]?.type === "ObjectExpression") {
714
944
  const optionsNode = node.arguments[0];
@@ -725,7 +955,7 @@ function NuxtScriptBundleTransformer(options = {
725
955
  }
726
956
  if (!scriptSrcNode) {
727
957
  const mergedOptions = { ...registryConfig, ...fnArg0 };
728
- src = registryNode.scriptBundling && registryNode.scriptBundling(mergedOptions);
958
+ src = bundleResolve && bundleResolve(mergedOptions);
729
959
  if (src === false)
730
960
  return;
731
961
  if (!src && registryNode.src)
@@ -753,14 +983,17 @@ function NuxtScriptBundleTransformer(options = {
753
983
  if (scriptSrcNode || src) {
754
984
  src = src || (typeof scriptSrcNode?.value === "string" ? scriptSrcNode?.value : false);
755
985
  if (src) {
756
- let canBundle = options.defaultBundle === true || options.defaultBundle === "force";
757
- let forceDownload = options.defaultBundle === "force";
986
+ const registryScript = fnName !== "useScript" ? options.scripts?.find((s2) => s2.import.name === fnName) : void 0;
987
+ let canBundle = !!registryScript?.bundle;
988
+ let forceDownload = false;
989
+ let explicitBundleInCall = false;
758
990
  if (node.arguments[1]?.type === "ObjectExpression") {
759
991
  const scriptOptionsArg = node.arguments[1];
760
992
  const bundleProperty = scriptOptionsArg.properties.find(
761
993
  (p) => (p.key?.name === "bundle" || p.key?.value === "bundle") && p.type === "Property"
762
994
  );
763
995
  if (bundleProperty && bundleProperty.value.type === "Literal") {
996
+ explicitBundleInCall = true;
764
997
  const bundleValue = bundleProperty.value.value;
765
998
  if (bundleValue !== true && bundleValue !== "force" && String(bundleValue) !== "true") {
766
999
  canBundle = false;
@@ -785,35 +1018,49 @@ function NuxtScriptBundleTransformer(options = {
785
1018
  return prop.type === "Property" && prop.key?.name === "bundle" && prop.value.type === "Literal";
786
1019
  });
787
1020
  if (bundleOption) {
1021
+ explicitBundleInCall = true;
788
1022
  const bundleValue = bundleOption.value.value;
789
1023
  canBundle = bundleValue === true || bundleValue === "force" || String(bundleValue) === "true";
790
1024
  forceDownload = bundleValue === "force";
791
1025
  }
792
- const firstPartyOption = scriptOptions?.value.properties?.find((prop) => {
793
- return prop.type === "Property" && prop.key?.name === "firstParty" && prop.value.type === "Literal";
1026
+ if (!explicitBundleInCall && registryConfig?.scriptOptions?.bundle !== void 0) {
1027
+ const bundleValue = registryConfig.scriptOptions.bundle;
1028
+ canBundle = bundleValue === true || bundleValue === "force" || String(bundleValue) === "true";
1029
+ forceDownload = bundleValue === "force";
1030
+ }
1031
+ const rpiOption = scriptOptions?.value.properties?.find((prop) => {
1032
+ return prop.type === "Property" && prop.key?.name === "proxy" && prop.value.type === "Literal";
794
1033
  });
795
- let firstPartyOptOut = firstPartyOption?.value.value === false;
1034
+ let firstPartyOptOut = rpiOption?.value.value === false;
796
1035
  if (!firstPartyOptOut && node.arguments[1]?.type === "ObjectExpression") {
797
- const secondArgFirstPartyProp = node.arguments[1].properties.find(
798
- (p) => p.type === "Property" && p.key?.name === "firstParty" && p.value.type === "Literal"
1036
+ const secondArgProp = node.arguments[1].properties.find(
1037
+ (p) => p.type === "Property" && p.key?.name === "proxy" && p.value.type === "Literal"
799
1038
  );
800
- firstPartyOptOut = secondArgFirstPartyProp?.value.value === false;
1039
+ firstPartyOptOut = secondArgProp?.value.value === false;
801
1040
  }
802
1041
  if (!firstPartyOptOut && node.arguments[0]?.type === "ObjectExpression") {
803
- const firstArgFirstPartyProp = node.arguments[0].properties.find(
804
- (p) => p.type === "Property" && p.key?.name === "firstParty" && p.value.type === "Literal"
1042
+ const firstArgProp = node.arguments[0].properties.find(
1043
+ (p) => p.type === "Property" && p.key?.name === "proxy" && p.value.type === "Literal"
805
1044
  );
806
- firstPartyOptOut = firstArgFirstPartyProp?.value.value === false;
1045
+ firstPartyOptOut = firstArgProp?.value.value === false;
807
1046
  }
808
1047
  if (canBundle) {
809
1048
  const { url: _url, filename } = normalizeScriptData(src, options.assetsBaseURL);
810
1049
  const script = options.scripts?.find((s2) => s2.import.name === fnName);
811
- const proxyConfigKey = script?.proxy !== false ? script?.proxy || registryKey : void 0;
812
- const proxyRewrites = options.firstPartyEnabled && !firstPartyOptOut && proxyConfigKey && options.firstPartyCollectPrefix ? getProxyConfig(proxyConfigKey, options.firstPartyCollectPrefix)?.rewrite : void 0;
1050
+ const hasReverseProxy = !!script?.proxy;
1051
+ const proxyConfigKey = hasReverseProxy ? typeof script?.proxy === "string" ? script.proxy : registryKey : void 0;
1052
+ const proxyConfig = !firstPartyOptOut && proxyConfigKey ? options.proxyConfigs?.[proxyConfigKey] : void 0;
1053
+ const proxyRewrites = proxyConfig?.domains?.map((domain) => ({
1054
+ from: domain,
1055
+ to: `${options.proxyPrefix}/${domain}`
1056
+ }));
1057
+ const sdkPatches = proxyConfig?.sdkPatches;
1058
+ const skipApiRewrites = !!(registryKey && options.partytownScripts?.has(registryKey));
1059
+ const neutralizeCanvas = proxyConfig?.privacy !== void 0 && typeof proxyConfig.privacy === "object" ? proxyConfig.privacy.hardware ?? true : true;
813
1060
  deferredOps.push(async () => {
814
1061
  let url = _url;
815
1062
  try {
816
- await downloadScript({ src, url, filename, forceDownload, proxyRewrites, integrity: options.integrity }, renderedScript, options.fetchOptions, options.cacheMaxAge);
1063
+ await downloadScript({ src, url, filename, forceDownload, proxyRewrites, sdkPatches, integrity: options.integrity, skipApiRewrites, neutralizeCanvas }, renderedScript, options.fetchOptions, options.cacheMaxAge);
817
1064
  } catch (e) {
818
1065
  if (options.fallbackOnSrcOnBundleFail) {
819
1066
  logger.warn(`[Nuxt Scripts: Bundle Transformer] Failed to bundle ${src}. Fallback to remote loading.`);
@@ -893,113 +1140,15 @@ function NuxtScriptBundleTransformer(options = {
893
1140
  });
894
1141
  }
895
1142
 
896
- const isStackblitz = provider === "stackblitz";
897
- async function promptToInstall(name, installCommand, options) {
898
- if (await resolvePackageJSON(name).catch(() => null))
899
- return true;
900
- logger$1.info(`Package ${name} is missing`);
901
- if (isCI)
902
- return false;
903
- if (options.prompt === true || options.prompt !== false && !isStackblitz) {
904
- const confirm = await logger$1.prompt(`Do you want to install ${name} package?`, {
905
- type: "confirm",
906
- name: "confirm",
907
- initial: true
908
- });
909
- if (!confirm)
910
- return false;
911
- }
912
- logger$1.info(`Installing ${name}...`);
913
- try {
914
- await installCommand();
915
- logger$1.success(`Installed ${name}`);
916
- return true;
917
- } catch (err) {
918
- logger$1.error(err);
919
- return false;
920
- }
921
- }
922
- const installPrompts = /* @__PURE__ */ new Set();
923
- function installNuxtModule(name, options) {
924
- if (installPrompts.has(name))
925
- return;
926
- installPrompts.add(name);
927
- const nuxt = tryUseNuxt();
928
- if (!nuxt)
929
- return;
930
- return promptToInstall(name, async () => {
931
- const { runCommand } = await import(String("nuxi"));
932
- await runCommand("module", ["add", name, "--cwd", nuxt.options.rootDir]);
933
- }, { rootDir: nuxt.options.rootDir, searchPaths: nuxt.options.modulesDir, ...options });
934
- }
935
-
936
- function NuxtScriptsCheckScripts() {
937
- return createUnplugin(() => {
938
- return {
939
- name: "nuxt-scripts:check-scripts",
940
- transform: {
941
- filter: {
942
- id: /\.vue/
943
- },
944
- handler(code, id) {
945
- if (!isVue(id, { type: ["script"] }))
946
- return;
947
- if (!code.includes("useScript"))
948
- return;
949
- let nameNode;
950
- let errorNode;
951
- parseAndWalk(code, id, function(_node) {
952
- if (_node.type === "VariableDeclaration" && _node.declarations?.[0]?.id?.type === "ObjectPattern") {
953
- const objPattern = _node.declarations[0]?.id;
954
- for (const property of objPattern.properties) {
955
- if (property.type === "Property" && property.key.type === "Identifier" && property.key.name === "$script" && property.value.type === "Identifier") {
956
- nameNode = _node;
957
- }
958
- }
959
- }
960
- if (nameNode) {
961
- let sequence = _node.type === "SequenceExpression" ? _node : null;
962
- let assignmentExpression;
963
- if (_node.type === "VariableDeclaration") {
964
- if (_node.declarations[0]?.init?.type === "SequenceExpression") {
965
- sequence = _node.declarations[0]?.init;
966
- assignmentExpression = _node.declarations[0]?.init?.expressions?.[0];
967
- }
968
- }
969
- if (sequence && !assignmentExpression) {
970
- assignmentExpression = sequence.expressions[0]?.type === "AssignmentExpression" ? sequence.expressions[0] : null;
971
- }
972
- if (assignmentExpression) {
973
- const right = assignmentExpression?.right;
974
- if (right.callee?.name === "_withAsyncContext") {
975
- if (right.arguments[0]?.body?.name === "$script" || right.arguments[0]?.body?.callee?.object?.name === "$script") {
976
- errorNode = nameNode;
977
- }
978
- }
979
- }
980
- }
981
- });
982
- if (errorNode) {
983
- return this.error(new Error("You can't use a top-level await on $script as it will never resolve."));
984
- }
985
- }
986
- }
987
- };
988
- });
989
- }
990
-
991
- function registerTypeTemplates({ nuxt, config, newScripts }) {
1143
+ const TRIGGER_PLACEHOLDER_RE = /"__TRIGGER_PLACEHOLDER__"/g;
1144
+ function registerTypeTemplates({ config, newScripts }) {
992
1145
  addTypeTemplate({
993
1146
  filename: "types/nuxt-scripts-augments.d.ts",
994
1147
  getContents: () => {
995
- const typesPath = relative(
996
- resolve(nuxt.options.rootDir, nuxt.options.buildDir, "types"),
997
- resolve("runtime/types")
998
- );
999
1148
  let augments = `// Generated by @nuxt/scripts
1000
1149
  declare module '#app' {
1001
1150
  interface NuxtApp {
1002
- $scripts: Record<${[...Object.keys(config.globals || {}), ...Object.keys(config.registry || {})].map((k) => `'${k}'`).concat(["string"]).join(" | ")}, import('#nuxt-scripts/types').UseScriptContext<any> | undefined>
1151
+ $scripts: Record<${[...[...Object.keys(config.globals || {}), ...Object.keys(config.registry || {})].map((k) => `'${k}'`), ...["string"]].join(" | ")}, import('#nuxt-scripts/types').UseScriptContext<any> | undefined>
1003
1152
  _scripts: Record<string, import('#nuxt-scripts/types').NuxtDevToolsScriptInstance>
1004
1153
  }
1005
1154
  interface RuntimeNuxtHooks {
@@ -1010,12 +1159,11 @@ declare module '#app' {
1010
1159
  if (newScripts.length) {
1011
1160
  augments += `
1012
1161
  declare module '#nuxt-scripts/types' {
1013
- type _NuxtScriptOptions = Omit<import('${typesPath}').NuxtUseScriptOptions, 'use' | 'beforeInit'>
1014
1162
  interface ScriptRegistry {
1015
1163
  ${newScripts.map((i) => {
1016
1164
  const key = i.import.name.replace("useScript", "");
1017
1165
  const keyLcFirst = key.substring(0, 1).toLowerCase() + key.substring(1);
1018
- return ` ${keyLcFirst}?: import('${i.import.from}').${key}Input | [import('${i.import.from}').${key}Input, _NuxtScriptOptions]`;
1166
+ return ` ${keyLcFirst}?: import('${i.import.from}').${key}Input`;
1019
1167
  }).join("\n")}
1020
1168
  }
1021
1169
  }
@@ -1071,7 +1219,7 @@ function resolveTriggerForTemplate(trigger) {
1071
1219
  function templatePlugin(config, registry) {
1072
1220
  if (Array.isArray(config.globals)) {
1073
1221
  config.globals = Object.fromEntries(config.globals.map((i) => [hash(i), i]));
1074
- logger.warn("The `globals` array option is deprecated, please convert to an object.");
1222
+ logger.warn("The `globals` array option is deprecated. Convert to an object: `globals: { myScript: 'https://example.com/script.js' }`");
1075
1223
  }
1076
1224
  const imports = [];
1077
1225
  const inits = [];
@@ -1080,29 +1228,31 @@ function templatePlugin(config, registry) {
1080
1228
  let needsInteractionImport = false;
1081
1229
  let needsServiceWorkerImport = false;
1082
1230
  for (const [k, c] of Object.entries(config.registry || {})) {
1231
+ if (c === false)
1232
+ continue;
1233
+ const entry = c;
1234
+ const [, scriptOptions] = entry;
1235
+ if (!scriptOptions?.trigger)
1236
+ continue;
1083
1237
  const importDefinition = registry.find((i) => i.import.name.toLowerCase() === `usescript${k.toLowerCase()}`);
1084
1238
  if (importDefinition) {
1085
1239
  resolvedRegistryKeys.push(k);
1086
1240
  imports.unshift(`import { ${importDefinition.import.name} } from '${importDefinition.import.from}'`);
1087
- if (c === "mock") {
1088
- inits.push(`const ${k} = ${importDefinition.import.name}({ scriptOptions: { trigger: 'manual', skipValidation: true } })`);
1089
- } else if (Array.isArray(c) && c.length === 2) {
1090
- const input = c[0] || {};
1091
- const scriptOptions = { ...c[1] };
1092
- const triggerResolved = resolveTriggerForTemplate(scriptOptions?.trigger);
1093
- if (triggerResolved) {
1094
- scriptOptions.trigger = "__TRIGGER_PLACEHOLDER__";
1095
- if (triggerResolved.includes("useScriptTriggerIdleTimeout")) needsIdleTimeoutImport = true;
1096
- if (triggerResolved.includes("useScriptTriggerInteraction")) needsInteractionImport = true;
1097
- if (triggerResolved.includes("useScriptTriggerServiceWorker")) needsServiceWorkerImport = true;
1098
- }
1099
- const args = { ...input, scriptOptions };
1100
- const argsJson = triggerResolved ? JSON.stringify(args).replace(/"__TRIGGER_PLACEHOLDER__"/g, triggerResolved) : JSON.stringify(args);
1101
- inits.push(`const ${k} = ${importDefinition.import.name}(${argsJson})`);
1102
- } else {
1103
- const args = (typeof c !== "object" ? {} : c) || {};
1104
- inits.push(`const ${k} = ${importDefinition.import.name}(${JSON.stringify(args)})`);
1241
+ const [input] = entry;
1242
+ const opts = { ...scriptOptions };
1243
+ const triggerResolved = resolveTriggerForTemplate(opts.trigger);
1244
+ if (triggerResolved) {
1245
+ opts.trigger = "__TRIGGER_PLACEHOLDER__";
1246
+ if (triggerResolved.includes("useScriptTriggerIdleTimeout"))
1247
+ needsIdleTimeoutImport = true;
1248
+ if (triggerResolved.includes("useScriptTriggerInteraction"))
1249
+ needsInteractionImport = true;
1250
+ if (triggerResolved.includes("useScriptTriggerServiceWorker"))
1251
+ needsServiceWorkerImport = true;
1105
1252
  }
1253
+ const args = { ...input, scriptOptions: opts };
1254
+ const argsJson = triggerResolved ? JSON.stringify(args).replace(TRIGGER_PLACEHOLDER_RE, triggerResolved) : JSON.stringify(args);
1255
+ inits.push(`const ${k} = ${importDefinition.import.name}(${argsJson})`);
1106
1256
  }
1107
1257
  }
1108
1258
  for (const [k, c] of Object.entries(config.globals || {})) {
@@ -1112,11 +1262,14 @@ function templatePlugin(config, registry) {
1112
1262
  const options = c[1];
1113
1263
  const triggerResolved = resolveTriggerForTemplate(options?.trigger);
1114
1264
  if (triggerResolved) {
1115
- if (triggerResolved.includes("useScriptTriggerIdleTimeout")) needsIdleTimeoutImport = true;
1116
- if (triggerResolved.includes("useScriptTriggerInteraction")) needsInteractionImport = true;
1117
- if (triggerResolved.includes("useScriptTriggerServiceWorker")) needsServiceWorkerImport = true;
1265
+ if (triggerResolved.includes("useScriptTriggerIdleTimeout"))
1266
+ needsIdleTimeoutImport = true;
1267
+ if (triggerResolved.includes("useScriptTriggerInteraction"))
1268
+ needsInteractionImport = true;
1269
+ if (triggerResolved.includes("useScriptTriggerServiceWorker"))
1270
+ needsServiceWorkerImport = true;
1118
1271
  const resolvedOptions = { ...options, trigger: "__TRIGGER_PLACEHOLDER__" };
1119
- const optionsJson = JSON.stringify(resolvedOptions).replace(/"__TRIGGER_PLACEHOLDER__"/g, triggerResolved);
1272
+ const optionsJson = JSON.stringify(resolvedOptions).replace(TRIGGER_PLACEHOLDER_RE, triggerResolved);
1120
1273
  inits.push(`const ${k} = useScript(${JSON.stringify({ key: k, ...typeof c[0] === "string" ? { src: c[0] } : c[0] })}, { ...${optionsJson}, use: () => ({ ${k}: window.${k} }) })`);
1121
1274
  } else {
1122
1275
  inits.push(`const ${k} = useScript(${JSON.stringify({ key: k, ...typeof c[0] === "string" ? { src: c[0] } : c[0] })}, { ...${JSON.stringify(c[1])}, use: () => ({ ${k}: window.${k} }) })`);
@@ -1124,11 +1277,14 @@ function templatePlugin(config, registry) {
1124
1277
  } else if (typeof c === "object" && c !== null) {
1125
1278
  const triggerResolved = resolveTriggerForTemplate(c.trigger);
1126
1279
  if (triggerResolved) {
1127
- if (triggerResolved.includes("useScriptTriggerIdleTimeout")) needsIdleTimeoutImport = true;
1128
- if (triggerResolved.includes("useScriptTriggerInteraction")) needsInteractionImport = true;
1129
- if (triggerResolved.includes("useScriptTriggerServiceWorker")) needsServiceWorkerImport = true;
1280
+ if (triggerResolved.includes("useScriptTriggerIdleTimeout"))
1281
+ needsIdleTimeoutImport = true;
1282
+ if (triggerResolved.includes("useScriptTriggerInteraction"))
1283
+ needsInteractionImport = true;
1284
+ if (triggerResolved.includes("useScriptTriggerServiceWorker"))
1285
+ needsServiceWorkerImport = true;
1130
1286
  const resolvedOptions = { ...c, trigger: "__TRIGGER_PLACEHOLDER__" };
1131
- const argsJson = JSON.stringify({ key: k, ...resolvedOptions }).replace(/"__TRIGGER_PLACEHOLDER__"/g, triggerResolved);
1287
+ const argsJson = JSON.stringify({ key: k, ...resolvedOptions }).replace(TRIGGER_PLACEHOLDER_RE, triggerResolved);
1132
1288
  inits.push(`const ${k} = useScript(${argsJson}, { use: () => ({ ${k}: window.${k} }) })`);
1133
1289
  } else {
1134
1290
  inits.push(`const ${k} = useScript(${JSON.stringify({ key: k, ...c })}, { use: () => ({ ${k}: window.${k} }) })`);
@@ -1157,7 +1313,7 @@ function templatePlugin(config, registry) {
1157
1313
  ` parallel: true,`,
1158
1314
  ` setup() {`,
1159
1315
  ...inits.map((i) => ` ${i}`),
1160
- ` return { provide: { $scripts: { ${[...Object.keys(config.globals || {}), ...resolvedRegistryKeys].join(", ")} } } }`,
1316
+ ` return { provide: { scripts: { ${[...Object.keys(config.globals || {}), ...resolvedRegistryKeys].join(", ")} } } }`,
1161
1317
  ` }`,
1162
1318
  `})`
1163
1319
  ].join("\n");
@@ -1167,22 +1323,28 @@ const SELF_CLOSING_SCRIPT_RE = /<((?:Script[A-Z]|script-)\w[\w-]*)\b([^>]*?)\/\s
1167
1323
  function fixSelfClosingScriptComponents(nuxt) {
1168
1324
  function expandTags(content) {
1169
1325
  SELF_CLOSING_SCRIPT_RE.lastIndex = 0;
1170
- if (!SELF_CLOSING_SCRIPT_RE.test(content)) return null;
1326
+ if (!SELF_CLOSING_SCRIPT_RE.test(content))
1327
+ return null;
1171
1328
  SELF_CLOSING_SCRIPT_RE.lastIndex = 0;
1172
1329
  return content.replace(SELF_CLOSING_SCRIPT_RE, (_, tag, attrs) => `<${tag}${attrs.trimEnd()}></${tag}>`);
1173
1330
  }
1174
1331
  function fixFile(filePath) {
1175
- if (!existsSync(filePath)) return;
1332
+ if (!existsSync(filePath))
1333
+ return;
1176
1334
  const content = readFileSync(filePath, "utf-8");
1177
1335
  const fixed = expandTags(content);
1178
- if (fixed) nuxt.vfs[filePath] = fixed;
1336
+ if (fixed)
1337
+ nuxt.vfs[filePath] = fixed;
1179
1338
  }
1180
1339
  function scanDir(dir) {
1181
- if (!existsSync(dir)) return;
1340
+ if (!existsSync(dir))
1341
+ return;
1182
1342
  for (const entry of readdirSync(dir, { withFileTypes: true })) {
1183
1343
  const fullPath = resolve(dir, entry.name);
1184
- if (entry.isDirectory()) scanDir(fullPath);
1185
- else if (entry.name.endsWith(".vue")) fixFile(fullPath);
1344
+ if (entry.isDirectory())
1345
+ scanDir(fullPath);
1346
+ else if (entry.name.endsWith(".vue"))
1347
+ fixFile(fullPath);
1186
1348
  }
1187
1349
  }
1188
1350
  const pagesDirs = /* @__PURE__ */ new Set();
@@ -1195,7 +1357,8 @@ function fixSelfClosingScriptComponents(nuxt) {
1195
1357
  for (const dir of pagesDirs) scanDir(dir);
1196
1358
  if (nuxt.options.dev) {
1197
1359
  nuxt.hook("builder:watch", (_event, relativePath) => {
1198
- if (!relativePath.endsWith(".vue")) return;
1360
+ if (!relativePath.endsWith(".vue"))
1361
+ return;
1199
1362
  for (const layer of nuxt.options._layers) {
1200
1363
  const fullPath = resolve(layer.config.srcDir, relativePath);
1201
1364
  for (const dir of pagesDirs) {
@@ -1208,20 +1371,73 @@ function fixSelfClosingScriptComponents(nuxt) {
1208
1371
  });
1209
1372
  }
1210
1373
  }
1211
- const PARTYTOWN_FORWARDS = {
1212
- googleAnalytics: ["dataLayer.push", "gtag"],
1213
- plausible: ["plausible"],
1214
- fathom: ["fathom", "fathom.trackEvent", "fathom.trackPageview"],
1215
- umami: ["umami", "umami.track"],
1216
- matomo: ["_paq.push"],
1217
- segment: ["analytics", "analytics.track", "analytics.page", "analytics.identify"],
1218
- metaPixel: ["fbq"],
1219
- xPixel: ["twq"],
1220
- tiktokPixel: ["ttq.track", "ttq.page", "ttq.identify"],
1221
- snapchatPixel: ["snaptr"],
1222
- redditPixel: ["rdt"],
1223
- cloudflareWebAnalytics: ["__cfBeacon"]
1224
- };
1374
+ const UPPER_RE = /([A-Z])/g;
1375
+ const toScreamingSnake = (s) => s.replace(UPPER_RE, "_$1").toUpperCase();
1376
+ const PROXY_SECRET_ENV_KEY = "NUXT_SCRIPTS_PROXY_SECRET";
1377
+ const PROXY_SECRET_ENV_LINE_RE = /^NUXT_SCRIPTS_PROXY_SECRET=/m;
1378
+ const PROXY_SECRET_ENV_VALUE_RE = /^NUXT_SCRIPTS_PROXY_SECRET=(.+)$/m;
1379
+ function resolveProxySecret(rootDir, isDev, configSecret, autoGenerate = true) {
1380
+ if (configSecret)
1381
+ return { secret: configSecret, ephemeral: false, source: "config" };
1382
+ const envSecret = process.env[PROXY_SECRET_ENV_KEY];
1383
+ if (envSecret)
1384
+ return { secret: envSecret, ephemeral: false, source: "env" };
1385
+ if (!isDev || !autoGenerate)
1386
+ return void 0;
1387
+ const secret = randomBytes(32).toString("hex");
1388
+ const envPath = resolve(rootDir, ".env");
1389
+ const line = `${PROXY_SECRET_ENV_KEY}=${secret}
1390
+ `;
1391
+ try {
1392
+ if (existsSync(envPath)) {
1393
+ const contents = readFileSync(envPath, "utf-8");
1394
+ if (PROXY_SECRET_ENV_LINE_RE.test(contents)) {
1395
+ const match = contents.match(PROXY_SECRET_ENV_VALUE_RE);
1396
+ if (match?.[1])
1397
+ return { secret: match[1].trim(), ephemeral: false, source: "dotenv-generated" };
1398
+ }
1399
+ appendFileSync(envPath, contents.endsWith("\n") ? line : `
1400
+ ${line}`);
1401
+ } else {
1402
+ writeFileSync(envPath, `# Generated by @nuxt/scripts
1403
+ ${line}`);
1404
+ }
1405
+ process.env[PROXY_SECRET_ENV_KEY] = secret;
1406
+ return { secret, ephemeral: false, source: "dotenv-generated" };
1407
+ } catch {
1408
+ process.env[PROXY_SECRET_ENV_KEY] = secret;
1409
+ return { secret, ephemeral: true, source: "memory-generated" };
1410
+ }
1411
+ }
1412
+ function isProxyDisabled(registryKey, registry2, runtimeConfig) {
1413
+ const entry = registry2?.[registryKey];
1414
+ if (!entry)
1415
+ return true;
1416
+ const [input, scriptOptions] = entry;
1417
+ if (input?.proxy === false || scriptOptions?.proxy === false)
1418
+ return true;
1419
+ if (runtimeConfig) {
1420
+ const rtEntry = runtimeConfig.public?.scripts?.[registryKey];
1421
+ if (rtEntry?.proxy === false)
1422
+ return true;
1423
+ }
1424
+ return false;
1425
+ }
1426
+ function applyAutoInject(registry2, runtimeConfig, proxyPrefix, registryKey, autoInject) {
1427
+ if (isProxyDisabled(registryKey, registry2, runtimeConfig))
1428
+ return;
1429
+ const entry = registry2[registryKey];
1430
+ const input = entry[0];
1431
+ const rtScripts = runtimeConfig.public?.scripts;
1432
+ const rtEntry = rtScripts?.[registryKey];
1433
+ const config = rtEntry && typeof rtEntry === "object" ? rtEntry : input;
1434
+ if (!config || config[autoInject.configField])
1435
+ return;
1436
+ const value = autoInject.computeValue(proxyPrefix, config);
1437
+ input[autoInject.configField] = value;
1438
+ if (rtEntry && typeof rtEntry === "object" && rtEntry !== input)
1439
+ rtEntry[autoInject.configField] = value;
1440
+ }
1225
1441
  const module$1 = defineNuxtModule({
1226
1442
  meta: {
1227
1443
  name: "@nuxt/scripts",
@@ -1231,7 +1447,6 @@ const module$1 = defineNuxtModule({
1231
1447
  }
1232
1448
  },
1233
1449
  defaults: {
1234
- firstParty: true,
1235
1450
  defaultScriptOptions: {
1236
1451
  trigger: "onNuxtReady"
1237
1452
  },
@@ -1253,86 +1468,90 @@ const module$1 = defineNuxtModule({
1253
1468
  debug: false
1254
1469
  },
1255
1470
  async setup(config, nuxt) {
1256
- const { resolvePath } = createResolver(import.meta.url);
1471
+ const { resolve: resolveModule, resolvePath } = createResolver(import.meta.url);
1257
1472
  const { version, name } = await readPackageJSON(await resolvePath("../package.json"));
1258
- nuxt.options.alias["#nuxt-scripts-validator"] = await resolvePath(`./runtime/validation/${nuxt.options.dev || nuxt.options._prepare ? "valibot" : "mock"}`);
1259
1473
  nuxt.options.alias["#nuxt-scripts"] = await resolvePath("./runtime");
1260
1474
  logger.level = config.debug || nuxt.options.debug ? 4 : 3;
1261
1475
  if (!config.enabled) {
1262
1476
  logger.debug("The module is disabled, skipping setup.");
1263
1477
  return;
1264
1478
  }
1479
+ if (nuxt.options.dev) {
1480
+ setupDevtools(nuxt, { standalone: config._standaloneDevtools });
1481
+ if (config._standaloneDevtools) {
1482
+ const bridgePath = resolveModule("./runtime/devtools-standalone-bridge.client");
1483
+ addPluginTemplate({
1484
+ filename: "modules/nuxt-scripts/devtools-standalone-bridge.client.mjs",
1485
+ getContents() {
1486
+ return `export { default } from '${bridgePath}'`;
1487
+ }
1488
+ });
1489
+ }
1490
+ }
1265
1491
  const { version: unheadVersion } = await readPackageJSON("@unhead/vue", {
1266
1492
  from: nuxt.options.modulesDir
1267
1493
  }).catch(() => ({ version: null }));
1268
1494
  if (unheadVersion?.startsWith("1")) {
1269
1495
  logger.error(`Nuxt Scripts requires Unhead >= 2, you are using v${unheadVersion}. Please run \`nuxi upgrade --clean\` to upgrade...`);
1270
1496
  }
1497
+ const scripts = await registry(resolvePath);
1498
+ if (config.registry) {
1499
+ migrateDeprecatedRegistryKeys(config.registry, (msg) => logger.warn(msg));
1500
+ normalizeRegistryConfig(config.registry, (msg) => logger.warn(msg));
1501
+ nuxt.options.runtimeConfig.public = nuxt.options.runtimeConfig.public || {};
1502
+ const registryWithDefaults = {};
1503
+ for (const [key, entry] of Object.entries(config.registry)) {
1504
+ if (entry === false)
1505
+ continue;
1506
+ const input = entry[0];
1507
+ const scriptOptions = entry[1];
1508
+ const envDefaults = scripts.find((s) => s.registryKey === key)?.envDefaults;
1509
+ const base = {};
1510
+ if (!envDefaults || !Object.keys(envDefaults).length) {
1511
+ Object.assign(base, input);
1512
+ } else {
1513
+ const envResolved = {};
1514
+ for (const [field, defaultValue] of Object.entries(envDefaults)) {
1515
+ const envKey = `NUXT_PUBLIC_SCRIPTS_${toScreamingSnake(key)}_${toScreamingSnake(field)}`;
1516
+ envResolved[field] = process.env[envKey] || defaultValue;
1517
+ }
1518
+ Object.assign(base, defu(input, envResolved));
1519
+ }
1520
+ if (scriptOptions && Object.keys(scriptOptions).length > 0) {
1521
+ base.scriptOptions = scriptOptions;
1522
+ }
1523
+ registryWithDefaults[key] = base;
1524
+ }
1525
+ nuxt.options.runtimeConfig.public.scripts = defu(
1526
+ nuxt.options.runtimeConfig.public.scripts || {},
1527
+ registryWithDefaults
1528
+ );
1529
+ }
1530
+ const googleMapsEnabled = config.googleStaticMapsProxy?.enabled || !!config.registry?.googleMaps;
1271
1531
  nuxt.options.runtimeConfig["nuxt-scripts"] = {
1272
1532
  version,
1273
1533
  // Private proxy config with API key (server-side only)
1274
- googleStaticMapsProxy: config.googleStaticMapsProxy?.enabled ? { apiKey: nuxt.options.runtimeConfig.public.scripts?.googleMaps?.apiKey } : void 0
1534
+ googleStaticMapsProxy: googleMapsEnabled ? { apiKey: nuxt.options.runtimeConfig.public.scripts?.googleMaps?.apiKey } : void 0
1275
1535
  };
1276
1536
  nuxt.options.runtimeConfig.public["nuxt-scripts"] = {
1277
1537
  // expose for devtools
1278
1538
  version: nuxt.options.dev ? version : void 0,
1539
+ prefix: config.prefix || "/_scripts",
1279
1540
  defaultScriptOptions: config.defaultScriptOptions,
1280
1541
  // Only expose enabled and cacheMaxAge to client, not apiKey
1281
- googleStaticMapsProxy: config.googleStaticMapsProxy?.enabled ? { enabled: true, cacheMaxAge: config.googleStaticMapsProxy.cacheMaxAge } : void 0
1542
+ googleStaticMapsProxy: googleMapsEnabled ? { enabled: true, cacheMaxAge: config.googleStaticMapsProxy?.cacheMaxAge ?? 3600 } : void 0
1282
1543
  };
1283
- if (config.registry) {
1284
- nuxt.options.runtimeConfig.public = nuxt.options.runtimeConfig.public || {};
1285
- nuxt.options.runtimeConfig.public.scripts = defu(
1286
- nuxt.options.runtimeConfig.public.scripts || {},
1287
- config.registry
1288
- );
1289
- }
1290
- if (config.defaultScriptOptions?.bundle !== void 0) {
1291
- logger.warn(
1292
- "`scripts.defaultScriptOptions.bundle` is deprecated. Use `scripts.firstParty: true` instead. First-party mode is now enabled by default."
1293
- );
1294
- }
1295
- const staticPresets = ["static", "github-pages", "cloudflare-pages-static"];
1296
- const preset = process.env.NITRO_PRESET || "";
1297
- const isStaticPreset = staticPresets.includes(preset);
1298
- const firstPartyEnabled = !!config.firstParty;
1299
- const firstPartyPrefix = typeof config.firstParty === "object" ? config.firstParty.prefix : void 0;
1300
- const firstPartyCollectPrefix = typeof config.firstParty === "object" ? config.firstParty.collectPrefix || "/_proxy" : "/_proxy";
1301
- const firstPartyPrivacy = typeof config.firstParty === "object" ? config.firstParty.privacy : void 0;
1302
- const assetsPrefix = firstPartyPrefix || config.assets?.prefix || "/_scripts";
1303
- if (config.partytown?.length) {
1304
- config.registry = config.registry || {};
1305
- const requiredForwards = [];
1306
- for (const scriptKey of config.partytown) {
1307
- const forwards = PARTYTOWN_FORWARDS[scriptKey];
1308
- if (forwards) {
1309
- requiredForwards.push(...forwards);
1310
- } else if (import.meta.dev) {
1311
- logger.warn(`[partytown] "${scriptKey}" has no known Partytown forwards configured. It may not work correctly or may require manual forward configuration.`);
1312
- }
1313
- const reg = config.registry;
1314
- const existing = reg[scriptKey];
1315
- if (Array.isArray(existing)) {
1316
- existing[1] = { ...existing[1], partytown: true };
1317
- } else if (existing && typeof existing === "object" && existing !== true && existing !== "mock") {
1318
- reg[scriptKey] = [existing, { partytown: true }];
1319
- } else if (existing === true || existing === "mock") {
1320
- reg[scriptKey] = [{}, { partytown: true }];
1321
- } else {
1322
- reg[scriptKey] = [{}, { partytown: true }];
1323
- }
1324
- }
1325
- if (requiredForwards.length && hasNuxtModule("@nuxtjs/partytown")) {
1326
- const partytownConfig = nuxt.options.partytown || {};
1327
- const existingForwards = partytownConfig.forward || [];
1328
- const newForwards = [.../* @__PURE__ */ new Set([...existingForwards, ...requiredForwards])];
1329
- nuxt.options.partytown = { ...partytownConfig, forward: newForwards };
1330
- logger.info(`[partytown] Auto-configured forwards: ${requiredForwards.join(", ")}`);
1331
- }
1332
- }
1544
+ const scriptsBase = config.prefix || "/_scripts";
1545
+ const proxyPrefix = `${scriptsBase}/p`;
1546
+ const assetsPrefix = `${scriptsBase}/assets`;
1547
+ const proxyConfigs = {};
1548
+ const proxyHandlerPath = await resolvePath("./runtime/server/proxy-handler");
1549
+ addServerHandler({ route: `${proxyPrefix}/**`, handler: proxyHandlerPath });
1333
1550
  const composables = [
1334
1551
  "useScript",
1335
1552
  "useScriptEventPage",
1553
+ "useScriptProxyToken",
1554
+ "useScriptProxyUrl",
1336
1555
  "useScriptTriggerConsent",
1337
1556
  "useScriptTriggerElement",
1338
1557
  "useScriptTriggerIdleTimeout",
@@ -1358,60 +1577,50 @@ const module$1 = defineNuxtModule({
1358
1577
  return templateTriggerResolver(config.defaultScriptOptions);
1359
1578
  }
1360
1579
  });
1361
- logger.debug("[nuxt-scripts] First-party config:", { firstPartyEnabled, firstPartyPrivacy, firstPartyCollectPrefix });
1362
- let interceptRules = [];
1363
- if (firstPartyEnabled) {
1364
- addPluginTemplate({
1365
- filename: "nuxt-scripts-intercept.client.mjs",
1366
- getContents() {
1367
- const rulesJson = JSON.stringify(interceptRules);
1368
- return `export default defineNuxtPlugin({
1369
- name: 'nuxt-scripts:intercept',
1370
- enforce: 'pre',
1371
- setup() {
1372
- const rules = ${rulesJson};
1373
- const origBeacon = typeof navigator !== 'undefined' && navigator.sendBeacon
1374
- ? navigator.sendBeacon.bind(navigator)
1375
- : () => false;
1376
- const origFetch = globalThis.fetch.bind(globalThis);
1377
-
1378
- function rewriteUrl(url) {
1379
- try {
1380
- const parsed = new URL(url, location.origin);
1381
- for (const rule of rules) {
1382
- if (parsed.hostname === rule.pattern || parsed.hostname.endsWith('.' + rule.pattern)) {
1383
- if (rule.pathPrefix && !parsed.pathname.startsWith(rule.pathPrefix)) continue;
1384
- const path = rule.pathPrefix ? parsed.pathname.slice(rule.pathPrefix.length) : parsed.pathname;
1385
- return location.origin + rule.target + (path.startsWith('/') ? '' : '/') + path + parsed.search;
1386
- }
1387
- }
1388
- } catch {}
1389
- return url;
1390
- }
1391
-
1392
- globalThis.__nuxtScripts = {
1393
- sendBeacon: (url, data) => origBeacon(rewriteUrl(url), data),
1394
- fetch: (url, opts) => origFetch(typeof url === 'string' ? rewriteUrl(url) : url, opts),
1395
- };
1396
- },
1397
- })
1398
- `;
1399
- }
1400
- });
1401
- const proxyHandlerPath = await resolvePath("./runtime/server/proxy-handler");
1402
- logger.debug("[nuxt-scripts] Registering proxy handler:", `${firstPartyCollectPrefix}/**`, "->", proxyHandlerPath);
1403
- addServerHandler({
1404
- route: `${firstPartyCollectPrefix}/**`,
1405
- handler: proxyHandlerPath
1406
- });
1407
- }
1408
- const scripts = await registry(resolvePath);
1580
+ logger.debug("[nuxt-scripts] Proxy prefix:", proxyPrefix);
1409
1581
  for (const script of scripts) {
1410
1582
  if (script.import?.name) {
1411
1583
  addImports({ priority: 2, ...script.import });
1412
1584
  script._importRegistered = true;
1413
1585
  }
1414
1586
  }
1587
+ if (config.registry) {
1588
+ for (const [key, entry] of Object.entries(config.registry)) {
1589
+ if (!entry)
1590
+ continue;
1591
+ const [input, scriptOptions] = entry;
1592
+ if (scriptOptions?.skipValidation)
1593
+ continue;
1594
+ const script = scripts.find((s) => s.registryKey === key);
1595
+ if (!script?.schema)
1596
+ continue;
1597
+ const isComponentOnly = !script.import;
1598
+ if (isComponentOnly) {
1599
+ if (scriptOptions && "trigger" in scriptOptions && scriptOptions.trigger !== false) {
1600
+ const pascal = key.charAt(0).toUpperCase() + key.slice(1);
1601
+ logger.warn(
1602
+ `[nuxt-scripts] registry.${key}: \`trigger\` has no effect on component-only scripts. Render <Script${pascal}> in your template to load the embed.`
1603
+ );
1604
+ }
1605
+ continue;
1606
+ }
1607
+ const willAutoLoad = scriptOptions && "trigger" in scriptOptions && scriptOptions.trigger !== false;
1608
+ if (willAutoLoad) {
1609
+ const requiredFields = extractRequiredFields(script.schema);
1610
+ const missing = requiredFields.filter((f) => !input[f]);
1611
+ if (missing.length) {
1612
+ logger.warn(`[nuxt-scripts] registry.${key}: missing required field${missing.length > 1 ? "s" : ""} ${missing.map((f) => `'${f}'`).join(", ")}. The script infrastructure is registered but will not function without ${missing.length > 1 ? "them" : "it"}.`);
1613
+ }
1614
+ }
1615
+ const envDefaultKeys = new Set(Object.keys(script.envDefaults || {}));
1616
+ const userProvidedFields = Object.keys(input).filter((f) => !envDefaultKeys.has(f));
1617
+ if (userProvidedFields.length > 0 && (!scriptOptions || !("trigger" in scriptOptions))) {
1618
+ logger.warn(
1619
+ `[nuxt-scripts] registry.${key}: config provided without a \`trigger\`. The script will not auto-load. Add \`trigger: 'onNuxtReady'\` to auto-load, or \`trigger: false\` for infrastructure only. See https://scripts.nuxt.com/docs/migration-guide/v0-to-v1`
1620
+ );
1621
+ }
1622
+ }
1623
+ }
1415
1624
  nuxt.hooks.hook("modules:done", async () => {
1416
1625
  const registryScripts = [...scripts];
1417
1626
  await nuxt.hooks.callHook("scripts:registry", registryScripts);
@@ -1422,7 +1631,7 @@ const module$1 = defineNuxtModule({
1422
1631
  }
1423
1632
  const registryScriptsWithImport = registryScripts.filter((i) => !!i.import?.name);
1424
1633
  const newScripts = registryScriptsWithImport.filter((i) => !scripts.some((r) => r.import?.name === i.import.name));
1425
- registerTypeTemplates({ nuxt, config, newScripts });
1634
+ registerTypeTemplates({ config, newScripts });
1426
1635
  if (Object.keys(config.globals || {}).length || Object.keys(config.registry || {}).length) {
1427
1636
  addPluginTemplate({
1428
1637
  filename: `modules/${name.replace("/", "-")}/plugin.mjs`,
@@ -1431,79 +1640,123 @@ const module$1 = defineNuxtModule({
1431
1640
  }
1432
1641
  });
1433
1642
  }
1434
- const { renderedScript } = setupPublicAssetStrategy(config.assets);
1435
- if (firstPartyEnabled) {
1436
- const proxyConfigs = getAllProxyConfigs(firstPartyCollectPrefix);
1437
- const registryKeys = Object.keys(config.registry || {});
1438
- const neededRoutes = {};
1439
- const routePrivacyOverrides = {};
1643
+ const { renderedScript } = setupPublicAssetStrategy(assetsPrefix);
1644
+ const scriptByKey = /* @__PURE__ */ new Map();
1645
+ for (const script of registryScripts) {
1646
+ if (script.registryKey)
1647
+ scriptByKey.set(script.registryKey, script);
1648
+ }
1649
+ const partytownScripts = /* @__PURE__ */ new Set();
1650
+ let anyNeedsProxy = false;
1651
+ const registryKeys = Object.keys(config.registry || {});
1652
+ for (const key of registryKeys) {
1653
+ const script = scriptByKey.get(key);
1654
+ if (!script)
1655
+ continue;
1656
+ const entry = config.registry?.[key];
1657
+ const scriptOptions = entry?.[1] || {};
1658
+ const inputOptions = entry?.[0] || {};
1659
+ const mergedOverrides = { ...inputOptions, ...scriptOptions };
1660
+ const resolved = resolveCapabilities(script, mergedOverrides);
1661
+ if (resolved.proxy)
1662
+ anyNeedsProxy = true;
1663
+ if (resolved.partytown) {
1664
+ partytownScripts.add(key);
1665
+ const forwards = getPartytownForwards(script);
1666
+ if (forwards?.length && hasNuxtModule("@nuxtjs/partytown")) {
1667
+ const partytownConfig = nuxt.options.partytown || {};
1668
+ const existingForwards = partytownConfig.forward || [];
1669
+ const newForwards = [.../* @__PURE__ */ new Set([...existingForwards, ...forwards])];
1670
+ nuxt.options.partytown = { ...partytownConfig, forward: newForwards };
1671
+ } else if (!forwards?.length && import.meta.dev) {
1672
+ logger.warn(`[partytown] "${key}" has no known Partytown forwards configured. It may not work correctly or may require manual forward configuration.`);
1673
+ }
1674
+ }
1675
+ }
1676
+ if (anyNeedsProxy) {
1677
+ const builtConfigs = buildProxyConfigsFromRegistry(registryScripts, scriptByKey);
1678
+ Object.assign(proxyConfigs, builtConfigs);
1679
+ const domainPrivacy = {};
1440
1680
  const unsupportedScripts = [];
1681
+ const unmatchedScripts = [];
1682
+ let totalDomains = 0;
1683
+ const devtoolsScripts = [];
1441
1684
  for (const key of registryKeys) {
1442
- const script = registryScriptsWithImport.find((s) => s.import.name.toLowerCase() === `usescript${key.toLowerCase()}`);
1443
- const proxyKey = script?.proxy || void 0;
1444
- if (proxyKey) {
1445
- const proxyConfig = proxyConfigs[proxyKey];
1446
- if (proxyConfig?.routes) {
1447
- Object.assign(neededRoutes, proxyConfig.routes);
1448
- for (const routePath of Object.keys(proxyConfig.routes)) {
1449
- routePrivacyOverrides[routePath] = proxyConfig.privacy;
1450
- }
1451
- } else {
1452
- unsupportedScripts.push(key);
1453
- }
1685
+ const script = scriptByKey.get(key);
1686
+ if (!script) {
1687
+ unmatchedScripts.push(key);
1688
+ continue;
1454
1689
  }
1455
- }
1456
- if (config.registry?.posthog && typeof config.registry.posthog === "object") {
1457
- const phConfig = config.registry.posthog;
1458
- if (!phConfig.apiHost) {
1459
- const region = phConfig.region || "us";
1460
- phConfig.apiHost = region === "eu" ? `${firstPartyCollectPrefix}/ph-eu` : `${firstPartyCollectPrefix}/ph`;
1690
+ if (!script.proxy)
1691
+ continue;
1692
+ if (isProxyDisabled(key, config.registry))
1693
+ continue;
1694
+ const configKey = typeof script.proxy === "string" ? script.proxy : key;
1695
+ const proxyConfig = proxyConfigs[configKey];
1696
+ if (!proxyConfig) {
1697
+ unsupportedScripts.push(key);
1698
+ continue;
1699
+ }
1700
+ const entry = config.registry?.[key];
1701
+ const inputPrivacy = entry?.[0]?.privacy;
1702
+ for (const domain of proxyConfig.domains) {
1703
+ domainPrivacy[domain] = inputPrivacy ?? proxyConfig.privacy;
1704
+ totalDomains++;
1461
1705
  }
1706
+ if (proxyConfig.autoInject && config.registry)
1707
+ applyAutoInject(config.registry, nuxt.options.runtimeConfig, proxyPrefix, key, proxyConfig.autoInject);
1708
+ if (nuxt.options.dev)
1709
+ devtoolsScripts.push(buildDevtoolsEntry(key, script, configKey, proxyConfig));
1462
1710
  }
1463
- if (unsupportedScripts.length && nuxt.options.dev) {
1711
+ if (unmatchedScripts.length) {
1464
1712
  logger.warn(
1465
- `First-party mode is enabled but these scripts don't support it yet: ${unsupportedScripts.join(", ")}.
1466
- They will load directly from third-party servers. Request support at https://github.com/nuxt/scripts/issues`
1713
+ `Proxy mode: could not find registry scripts for: ${unmatchedScripts.join(", ")}.
1714
+ These scripts will not have proxy routes registered.`
1467
1715
  );
1468
1716
  }
1469
- interceptRules = routesToInterceptRules(neededRoutes);
1470
- const flatRoutes = {};
1471
- for (const [path, config2] of Object.entries(neededRoutes)) {
1472
- flatRoutes[path] = config2.proxy;
1717
+ if (unsupportedScripts.length && nuxt.options.dev) {
1718
+ logger.warn(
1719
+ `Proxy mode is enabled but these scripts don't support it yet: ${unsupportedScripts.join(", ")}.
1720
+ They will load directly from third-party servers.`
1721
+ );
1473
1722
  }
1723
+ addPluginTemplate({
1724
+ filename: "nuxt-scripts-intercept.client.mjs",
1725
+ getContents() {
1726
+ return generateInterceptPluginContents(proxyPrefix, { testMode: !!nuxt.options.test });
1727
+ }
1728
+ });
1474
1729
  nuxt.options.runtimeConfig["nuxt-scripts-proxy"] = {
1475
- routes: flatRoutes,
1476
- privacy: firstPartyPrivacy,
1477
- // undefined = use per-script defaults, set = global override
1478
- routePrivacy: routePrivacyOverrides
1479
- // per-script privacy from registry
1730
+ proxyPrefix,
1731
+ domainPrivacy,
1732
+ privacy: config.privacy
1480
1733
  };
1481
- if (Object.keys(neededRoutes).length) {
1482
- if (nuxt.options.dev) {
1483
- const routeCount = Object.keys(neededRoutes).length;
1484
- const scriptsCount = registryKeys.length;
1485
- const privacyLabel = firstPartyPrivacy === void 0 ? "per-script" : typeof firstPartyPrivacy === "boolean" ? firstPartyPrivacy ? "anonymize" : "passthrough" : "custom";
1486
- logger.success(`First-party mode enabled for ${scriptsCount} script(s), ${routeCount} proxy route(s) configured (privacy: ${privacyLabel})`);
1487
- if (logger.level >= 4) {
1488
- for (const [path, config2] of Object.entries(neededRoutes)) {
1489
- logger.debug(` ${path} \u2192 ${config2.proxy}`);
1490
- }
1491
- }
1492
- }
1734
+ const privacyLabel = config.privacy === void 0 ? "per-script" : typeof config.privacy === "boolean" ? config.privacy ? "anonymize" : "passthrough" : "custom";
1735
+ if (totalDomains > 0 && nuxt.options.dev) {
1736
+ logger.success(`Proxy mode enabled for ${registryKeys.length} script(s), ${totalDomains} domain(s) proxied (privacy: ${privacyLabel})`);
1493
1737
  }
1494
- if (isStaticPreset) {
1738
+ const proxyStaticPresets = ["static", "github-pages", "cloudflare-pages-static", "netlify-static", "azure-static", "firebase-static"];
1739
+ const proxyPreset = process.env.NITRO_PRESET || "";
1740
+ if (proxyStaticPresets.includes(proxyPreset)) {
1495
1741
  logger.warn(
1496
- `First-party collection endpoints require a server runtime (detected: ${preset || "static"}).
1497
- Scripts will be bundled, but collection requests will not be proxied.
1498
-
1499
- Options:
1500
- 1. Configure platform rewrites (Vercel, Netlify, Cloudflare)
1501
- 2. Switch to server-rendered mode (ssr: true)
1502
- 3. Disable with firstParty: false
1503
-
1504
- See: https://scripts.nuxt.com/docs/guides/first-party#static-hosting`
1742
+ `Proxy collection endpoints require a server runtime (detected: ${proxyPreset || "static"}).
1743
+ Scripts will be bundled, but collection requests will not be proxied and URL signing will be unavailable.
1744
+ Options: configure platform rewrites, switch to server-rendered mode, or disable with proxy: false.`
1505
1745
  );
1506
1746
  }
1747
+ if (nuxt.options.dev) {
1748
+ nuxt.options.runtimeConfig.public["nuxt-scripts-devtools"] = buildDevtoolsData(proxyPrefix, privacyLabel, devtoolsScripts);
1749
+ }
1750
+ if (partytownScripts.size && hasNuxtModule("@nuxtjs/partytown")) {
1751
+ const partytownConfig = nuxt.options.partytown || {};
1752
+ if (!partytownConfig.resolveUrl) {
1753
+ partytownConfig.resolveUrl = generatePartytownResolveUrl(proxyPrefix);
1754
+ nuxt.options.partytown = partytownConfig;
1755
+ logger.info("[partytown] Auto-configured resolveUrl for proxy");
1756
+ } else {
1757
+ logger.warn("[partytown] Custom resolveUrl already set. Add proxy rules to your resolveUrl manually.");
1758
+ }
1759
+ }
1507
1760
  }
1508
1761
  const moduleInstallPromises = /* @__PURE__ */ new Map();
1509
1762
  addBuildPlugin(NuxtScriptsCheckScripts(), {
@@ -1512,9 +1765,9 @@ See: https://scripts.nuxt.com/docs/guides/first-party#static-hosting`
1512
1765
  addBuildPlugin(NuxtScriptBundleTransformer({
1513
1766
  scripts: registryScriptsWithImport,
1514
1767
  registryConfig: nuxt.options.runtimeConfig.public.scripts,
1515
- defaultBundle: firstPartyEnabled || config.defaultScriptOptions?.bundle,
1516
- firstPartyEnabled,
1517
- firstPartyCollectPrefix,
1768
+ proxyConfigs,
1769
+ proxyPrefix,
1770
+ partytownScripts,
1518
1771
  moduleDetected(module) {
1519
1772
  if (nuxt.options.dev && module !== "@nuxt/scripts" && !moduleInstallPromises.has(module) && !hasNuxtModule(module))
1520
1773
  moduleInstallPromises.set(module, () => installNuxtModule(module));
@@ -1527,41 +1780,88 @@ See: https://scripts.nuxt.com/docs/guides/first-party#static-hosting`
1527
1780
  renderedScript
1528
1781
  }));
1529
1782
  nuxt.hooks.hook("build:done", async () => {
1530
- const initPromise = Array.from(moduleInstallPromises.values());
1783
+ const initPromise = [...moduleInstallPromises.values()];
1531
1784
  for (const p of initPromise)
1532
1785
  await p?.();
1533
1786
  });
1534
1787
  });
1535
- if (config.googleStaticMapsProxy?.enabled) {
1536
- addServerHandler({
1537
- route: "/_scripts/google-static-maps-proxy",
1538
- handler: await resolvePath("./runtime/server/google-static-maps-proxy")
1539
- });
1788
+ const scriptsPrefix = config.prefix || "/_scripts";
1789
+ const enabledEndpoints = {};
1790
+ let anyHandlerRequiresSigning = false;
1791
+ for (const script of scripts) {
1792
+ if (!script.serverHandlers?.length || !script.registryKey)
1793
+ continue;
1794
+ const isEnabled = script.registryKey === "googleMaps" ? config.googleStaticMapsProxy?.enabled || config.registry?.googleMaps : config.registry?.[script.registryKey];
1795
+ if (!isEnabled)
1796
+ continue;
1797
+ enabledEndpoints[script.registryKey] = true;
1798
+ for (const handler of script.serverHandlers) {
1799
+ const resolvedRoute = handler.route.replace("/_scripts", scriptsPrefix);
1800
+ addServerHandler({
1801
+ route: resolvedRoute,
1802
+ handler: handler.handler,
1803
+ middleware: handler.middleware
1804
+ });
1805
+ if (handler.requiresSigning)
1806
+ anyHandlerRequiresSigning = true;
1807
+ }
1808
+ if (script.registryKey === "gravatar") {
1809
+ const gravatarConfig = config.registry?.gravatar?.[0] || {};
1810
+ nuxt.options.runtimeConfig.public["nuxt-scripts"] = defu(
1811
+ { gravatarProxy: { cacheMaxAge: gravatarConfig.cacheMaxAge ?? 3600 } },
1812
+ nuxt.options.runtimeConfig.public["nuxt-scripts"]
1813
+ );
1814
+ }
1815
+ if (script.registryKey === "googleMaps") {
1816
+ nuxt.options.runtimeConfig["nuxt-scripts"] = defu(
1817
+ { googleMapsGeocodeProxy: { apiKey: nuxt.options.runtimeConfig.public.scripts?.googleMaps?.apiKey } },
1818
+ nuxt.options.runtimeConfig["nuxt-scripts"]
1819
+ );
1820
+ }
1540
1821
  }
1541
- addServerHandler({
1542
- route: "/api/_scripts/x-embed",
1543
- handler: await resolvePath("./runtime/server/x-embed")
1544
- });
1545
- addServerHandler({
1546
- route: "/api/_scripts/x-embed-image",
1547
- handler: await resolvePath("./runtime/server/x-embed-image")
1548
- });
1549
- addServerHandler({
1550
- route: "/api/_scripts/instagram-embed",
1551
- handler: await resolvePath("./runtime/server/instagram-embed")
1552
- });
1553
- addServerHandler({
1554
- route: "/api/_scripts/instagram-embed-image",
1555
- handler: await resolvePath("./runtime/server/instagram-embed-image")
1556
- });
1557
- addServerHandler({
1558
- route: "/api/_scripts/instagram-embed-asset",
1559
- handler: await resolvePath("./runtime/server/instagram-embed-asset")
1560
- });
1561
- if (nuxt.options.dev) {
1562
- setupDevToolsUI(config, resolvePath);
1822
+ nuxt.options.runtimeConfig.public["nuxt-scripts"] = defu(
1823
+ { endpoints: enabledEndpoints },
1824
+ nuxt.options.runtimeConfig.public["nuxt-scripts"]
1825
+ );
1826
+ const staticPresets = ["static", "github-pages", "cloudflare-pages-static", "netlify-static", "azure-static", "firebase-static"];
1827
+ const nitroPreset = process.env.NITRO_PRESET || "";
1828
+ const isStaticTarget = staticPresets.includes(nitroPreset);
1829
+ const isSpa = nuxt.options.ssr === false;
1830
+ if (anyHandlerRequiresSigning && (isSpa || isStaticTarget)) {
1831
+ logger.warn(
1832
+ `[security] URL signing requires a server runtime${isStaticTarget ? ` (detected preset: ${nitroPreset})` : " (ssr: false)"}.
1833
+ Proxy endpoints will work without signature verification.
1834
+ To enable signing, deploy with a server-rendered target or configure platform-level rewrites.`
1835
+ );
1836
+ } else if (anyHandlerRequiresSigning) {
1837
+ const proxySecretResolved = resolveProxySecret(
1838
+ nuxt.options.rootDir,
1839
+ !!nuxt.options.dev,
1840
+ config.security?.secret,
1841
+ config.security?.autoGenerateSecret !== false
1842
+ );
1843
+ if (proxySecretResolved?.source === "dotenv-generated")
1844
+ logger.info(`[security] Generated ${PROXY_SECRET_ENV_KEY} in .env for signed proxy URLs.`);
1845
+ else if (proxySecretResolved?.source === "memory-generated")
1846
+ logger.warn(`[security] Generated an in-memory ${PROXY_SECRET_ENV_KEY} (could not write .env). Signed URLs will break across restarts.`);
1847
+ if (proxySecretResolved?.secret) {
1848
+ const scriptsRuntime = nuxt.options.runtimeConfig["nuxt-scripts"];
1849
+ scriptsRuntime.proxySecret = proxySecretResolved.secret;
1850
+ if (config.security?.pageTokenMaxAge !== void 0)
1851
+ scriptsRuntime.pageTokenMaxAge = config.security.pageTokenMaxAge;
1852
+ addPlugin({
1853
+ src: await resolvePath("./runtime/plugins/proxy-token.server"),
1854
+ mode: "server"
1855
+ });
1856
+ } else if (!nuxt.options.dev) {
1857
+ logger.warn(
1858
+ `[security] ${PROXY_SECRET_ENV_KEY} is not set. Proxy endpoints will pass requests through without signature verification.
1859
+ Generate one with: npx @nuxt/scripts generate-secret
1860
+ Then set the env var: ${PROXY_SECRET_ENV_KEY}=<secret>`
1861
+ );
1862
+ }
1563
1863
  }
1564
1864
  }
1565
1865
  });
1566
1866
 
1567
- export { module$1 as default };
1867
+ export { applyAutoInject, module$1 as default, isProxyDisabled, resolveProxySecret };