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

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 (270) hide show
  1. package/dist/devtools-client/200.html +1 -0
  2. package/dist/devtools-client/404.html +1 -0
  3. package/dist/devtools-client/_fonts/4ppnHhMi-pBsWSPo7mY0avYxlDoAg1N3PTzCwXLZ5rA-d9oibkGnTd1JL3tc_xnaVgBLYmOB8kjrK2cvZaqwj9s.woff2 +0 -0
  4. package/dist/devtools-client/_fonts/4qBuU9MRVUlPZNPSF7Xom_sK8RBEnfYu-9VXFrdq8A8-8TDwLE1HAj1sQn7XxVWtM_7sIaPM-DTdO3Pf8U2DF1U.woff2 +0 -0
  5. package/dist/devtools-client/_fonts/6dYsbWUd_BpKJ7mdDihgOcya1gHXLpJBuMYXux3WMjE-q3fYNS8YbW5n7ZeXI2vSNgkRWW5VDPKAl51SNTjG2qk.woff2 +0 -0
  6. package/dist/devtools-client/_fonts/Lr-hqqZZsYmCt0ITUlr1CUrWim9fsKvoDFZliMxgNHY-iTa_Yt_PzhOY9TX7ZXdSlEPim6iRt92xhECwaxWxd5w.woff2 +0 -0
  7. package/dist/devtools-client/_fonts/OknHvWI6KtYn1JQBzX7eSpNDBQ8520F9TvSUJYkVf6A-xeZn9253svK_8Q2LD0XEruY_MnEsuCRO5LenPoggC0Y.woff2 +0 -0
  8. package/dist/devtools-client/_fonts/PV2hrQG6wq5BlIPDjdL1IcOflycaghyt5MHzlBqZtlo-lb_WexLz3VZqfTN0oi554iBH5tT2j2UFEV-XErCAS3E.woff2 +0 -0
  9. package/dist/devtools-client/_fonts/UA7OtwYHwGN_HjcVGTdmiQxUit7FlqkCwxVUWSeXVnQ-B4OXCFOL_tWrYODpQTc07aMaj0c2cewTOmBRWR9tD-A.woff2 +0 -0
  10. package/dist/devtools-client/_fonts/VE4cDVCv5MxbFM7ZLoLCGbIpNd71zhp7MDI9lmN5Y7I-xZyDYCUVrd6LV8eVGF3Um3UZjBFuUtDGtvdyTBBRYBo.woff2 +0 -0
  11. package/dist/devtools-client/_fonts/fVoGbnMbBFd5L9BBp9fUPavUSkZ_EmsQNSyadkT-108-U4T0khaeLQSIhtt9eVvaCEKJjtWJ4ioRJOf8hvqkWY0.woff2 +0 -0
  12. package/dist/devtools-client/_fonts/lQAxeCEs1R0Lw-H9XRU1RlOARQN8J6npRsPjyEDMe5s-_DUSLEkO3tKTuun_gSnDLoQPVEnpOnyqZMOw0ByZ6PA.woff2 +0 -0
  13. package/dist/devtools-client/_fonts/lntlqNHKLV2n82yTwMde70QqOjcfLE2XJ5oKZ3vRPWc-z6TxpIZQdWXztWLr9_OFWqt_WJJoeGtuK_-XQMZGQwE.woff2 +0 -0
  14. package/dist/devtools-client/_fonts/qxAYvKsXWeYv731eb-h5TRurcdIP_W44mpNdX-HABAk-zUDeMEFlNtNbrwvT9JxLEBg0TphGy70O6RfIoIX_ZwU.woff2 +0 -0
  15. package/dist/devtools-client/_nuxt/B3kN3DAy.js +1 -0
  16. package/dist/devtools-client/_nuxt/B8PEiB0p.js +1 -0
  17. package/dist/devtools-client/_nuxt/C8jhSQ8l.js +1 -0
  18. package/dist/devtools-client/_nuxt/CJD6wrkT.js +188 -0
  19. package/dist/devtools-client/_nuxt/CfOsp0mU.js +1 -0
  20. package/dist/devtools-client/_nuxt/DKL6PHO3.js +1 -0
  21. package/dist/devtools-client/_nuxt/ajngqPCs.js +1 -0
  22. package/dist/devtools-client/_nuxt/builds/latest.json +1 -0
  23. package/dist/devtools-client/_nuxt/builds/meta/cb4e67c6-e8b7-4205-95b7-708fd96ffab6.json +1 -0
  24. package/dist/devtools-client/_nuxt/dlaR8P-P.js +1 -0
  25. package/dist/devtools-client/_nuxt/entry.BwpOBArY.css +1 -0
  26. package/dist/devtools-client/_nuxt/error-404.CvOVjXeC.css +1 -0
  27. package/dist/devtools-client/_nuxt/error-500.BIm53nmx.css +1 -0
  28. package/dist/devtools-client/_nuxt/first-party.C8Ha4JLM.css +1 -0
  29. package/dist/devtools-client/_nuxt/index.CA-OpSj0.css +1 -0
  30. package/dist/devtools-client/_nuxt/registry.B9lnjF_b.css +1 -0
  31. package/dist/devtools-client/_nuxt/wDzz0qaB.js +1 -0
  32. package/dist/devtools-client/docs/index.html +1 -0
  33. package/dist/devtools-client/first-party/index.html +1 -0
  34. package/dist/devtools-client/index.html +1 -0
  35. package/dist/devtools-client/registry/index.html +1 -0
  36. package/dist/module.d.mts +29 -84
  37. package/dist/module.d.ts +121 -0
  38. package/dist/module.json +1 -1
  39. package/dist/module.mjs +940 -755
  40. package/dist/registry.d.mts +91 -4
  41. package/dist/registry.d.ts +93 -0
  42. package/dist/registry.mjs +668 -326
  43. package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.d.vue.ts +19 -87
  44. package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.vue +79 -180
  45. package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.vue.d.ts +19 -87
  46. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsAdvancedMarkerElement.d.vue.ts +6 -55
  47. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsAdvancedMarkerElement.vue +12 -83
  48. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsAdvancedMarkerElement.vue.d.ts +6 -55
  49. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsCircle.d.vue.ts +5 -1
  50. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsCircle.vue +24 -38
  51. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsCircle.vue.d.ts +5 -1
  52. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsGeoJson.d.vue.ts +43 -0
  53. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsGeoJson.vue +60 -0
  54. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsGeoJson.vue.d.ts +43 -0
  55. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsHeatmapLayer.d.vue.ts +4 -0
  56. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsHeatmapLayer.vue +22 -26
  57. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsHeatmapLayer.vue.d.ts +4 -0
  58. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsInfoWindow.d.vue.ts +11 -8
  59. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsInfoWindow.vue +57 -57
  60. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsInfoWindow.vue.d.ts +11 -8
  61. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarker.d.vue.ts +24 -42
  62. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarker.vue +70 -73
  63. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarker.vue.d.ts +24 -42
  64. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.d.vue.ts +42 -5
  65. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.vue +83 -37
  66. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.vue.d.ts +42 -5
  67. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsOverlayView.d.vue.ts +77 -0
  68. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsOverlayView.vue +223 -0
  69. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsOverlayView.vue.d.ts +77 -0
  70. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPinElement.d.vue.ts +10 -3
  71. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPinElement.vue +9 -41
  72. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPinElement.vue.d.ts +10 -3
  73. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPolygon.d.vue.ts +7 -3
  74. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPolygon.vue +23 -38
  75. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPolygon.vue.d.ts +7 -3
  76. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPolyline.d.vue.ts +7 -3
  77. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPolyline.vue +23 -38
  78. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPolyline.vue.d.ts +7 -3
  79. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsRectangle.d.vue.ts +7 -3
  80. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsRectangle.vue +24 -38
  81. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsRectangle.vue.d.ts +7 -3
  82. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsStaticMap.d.vue.ts +200 -0
  83. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsStaticMap.vue +166 -0
  84. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsStaticMap.vue.d.ts +200 -0
  85. package/dist/runtime/components/GoogleMaps/bindGoogleMapsEvents.d.ts +13 -0
  86. package/dist/runtime/components/GoogleMaps/bindGoogleMapsEvents.js +8 -0
  87. package/dist/runtime/components/GoogleMaps/injectionKeys.d.ts +10 -0
  88. package/dist/runtime/components/GoogleMaps/injectionKeys.js +2 -0
  89. package/dist/runtime/components/GoogleMaps/useGoogleMapsResource.d.ts +48 -0
  90. package/dist/runtime/components/GoogleMaps/useGoogleMapsResource.js +51 -0
  91. package/dist/runtime/components/ScriptBlueskyEmbed.d.vue.ts +84 -0
  92. package/dist/runtime/components/ScriptBlueskyEmbed.vue +89 -0
  93. package/dist/runtime/components/ScriptBlueskyEmbed.vue.d.ts +84 -0
  94. package/dist/runtime/components/ScriptCarbonAds.d.vue.ts +4 -7
  95. package/dist/runtime/components/ScriptCarbonAds.vue +1 -0
  96. package/dist/runtime/components/ScriptCarbonAds.vue.d.ts +4 -7
  97. package/dist/runtime/components/ScriptCrisp.d.vue.ts +7 -11
  98. package/dist/runtime/components/ScriptCrisp.vue +2 -1
  99. package/dist/runtime/components/ScriptCrisp.vue.d.ts +7 -11
  100. package/dist/runtime/components/ScriptGoogleAdsense.d.vue.ts +4 -7
  101. package/dist/runtime/components/ScriptGoogleAdsense.vue +2 -1
  102. package/dist/runtime/components/ScriptGoogleAdsense.vue.d.ts +4 -7
  103. package/dist/runtime/components/ScriptGravatar.d.vue.ts +22 -0
  104. package/dist/runtime/components/ScriptGravatar.vue +46 -0
  105. package/dist/runtime/components/ScriptGravatar.vue.d.ts +22 -0
  106. package/dist/runtime/components/ScriptInstagramEmbed.d.vue.ts +12 -15
  107. package/dist/runtime/components/ScriptInstagramEmbed.vue +9 -3
  108. package/dist/runtime/components/ScriptInstagramEmbed.vue.d.ts +12 -15
  109. package/dist/runtime/components/ScriptIntercom.d.vue.ts +7 -11
  110. package/dist/runtime/components/ScriptIntercom.vue +5 -3
  111. package/dist/runtime/components/ScriptIntercom.vue.d.ts +7 -11
  112. package/dist/runtime/components/ScriptLemonSqueezy.d.vue.ts +2 -3
  113. package/dist/runtime/components/ScriptLemonSqueezy.vue +1 -0
  114. package/dist/runtime/components/ScriptLemonSqueezy.vue.d.ts +2 -3
  115. package/dist/runtime/components/ScriptPayPalButtons.d.vue.ts +43 -37
  116. package/dist/runtime/components/ScriptPayPalButtons.vue +49 -79
  117. package/dist/runtime/components/ScriptPayPalButtons.vue.d.ts +43 -37
  118. package/dist/runtime/components/ScriptPayPalMessages.d.vue.ts +37 -28
  119. package/dist/runtime/components/ScriptPayPalMessages.vue +47 -50
  120. package/dist/runtime/components/ScriptPayPalMessages.vue.d.ts +37 -28
  121. package/dist/runtime/components/ScriptStripePricingTable.d.vue.ts +5 -9
  122. package/dist/runtime/components/ScriptStripePricingTable.vue +3 -2
  123. package/dist/runtime/components/ScriptStripePricingTable.vue.d.ts +5 -9
  124. package/dist/runtime/components/ScriptVimeoPlayer.d.vue.ts +17 -11
  125. package/dist/runtime/components/ScriptVimeoPlayer.vue +14 -10
  126. package/dist/runtime/components/ScriptVimeoPlayer.vue.d.ts +17 -11
  127. package/dist/runtime/components/ScriptXEmbed.d.vue.ts +10 -13
  128. package/dist/runtime/components/ScriptXEmbed.vue +15 -8
  129. package/dist/runtime/components/ScriptXEmbed.vue.d.ts +10 -13
  130. package/dist/runtime/components/ScriptYouTubePlayer.d.vue.ts +10 -15
  131. package/dist/runtime/components/ScriptYouTubePlayer.vue +12 -5
  132. package/dist/runtime/components/ScriptYouTubePlayer.vue.d.ts +10 -15
  133. package/dist/runtime/composables/useScript.js +148 -8
  134. package/dist/runtime/composables/useScriptEventPage.js +2 -2
  135. package/dist/runtime/composables/useScriptTriggerConsent.d.ts +10 -0
  136. package/dist/runtime/composables/useScriptTriggerConsent.js +33 -20
  137. package/dist/runtime/composables/useScriptTriggerElement.js +1 -1
  138. package/dist/runtime/composables/useScriptTriggerIdleTimeout.js +1 -1
  139. package/dist/runtime/devtools-standalone-bridge.client.d.ts +8 -0
  140. package/dist/runtime/devtools-standalone-bridge.client.js +50 -0
  141. package/dist/runtime/registry/bing-uet.d.ts +20 -0
  142. package/dist/runtime/registry/bing-uet.js +29 -0
  143. package/dist/runtime/registry/bluesky-embed.d.ts +116 -0
  144. package/dist/runtime/registry/bluesky-embed.js +72 -0
  145. package/dist/runtime/registry/clarity.d.ts +10 -15
  146. package/dist/runtime/registry/clarity.js +22 -31
  147. package/dist/runtime/registry/cloudflare-web-analytics.d.ts +2 -13
  148. package/dist/runtime/registry/cloudflare-web-analytics.js +2 -14
  149. package/dist/runtime/registry/crisp.d.ts +10 -40
  150. package/dist/runtime/registry/crisp.js +2 -33
  151. package/dist/runtime/registry/databuddy-analytics.d.ts +2 -35
  152. package/dist/runtime/registry/databuddy-analytics.js +20 -45
  153. package/dist/runtime/registry/fathom-analytics.d.ts +7 -26
  154. package/dist/runtime/registry/fathom-analytics.js +3 -25
  155. package/dist/runtime/registry/google-adsense.d.ts +3 -11
  156. package/dist/runtime/registry/google-adsense.js +2 -11
  157. package/dist/runtime/registry/google-analytics.d.ts +3 -5
  158. package/dist/runtime/registry/google-analytics.js +3 -8
  159. package/dist/runtime/registry/google-maps.d.ts +3 -9
  160. package/dist/runtime/registry/google-maps.js +2 -8
  161. package/dist/runtime/registry/google-recaptcha.d.ts +2 -6
  162. package/dist/runtime/registry/google-recaptcha.js +4 -12
  163. package/dist/runtime/registry/google-sign-in.d.ts +2 -13
  164. package/dist/runtime/registry/google-sign-in.js +2 -22
  165. package/dist/runtime/registry/google-tag-manager.d.ts +3 -28
  166. package/dist/runtime/registry/google-tag-manager.js +4 -27
  167. package/dist/runtime/registry/gravatar.d.ts +26 -0
  168. package/dist/runtime/registry/gravatar.js +36 -0
  169. package/dist/runtime/registry/hotjar.d.ts +4 -6
  170. package/dist/runtime/registry/hotjar.js +2 -5
  171. package/dist/runtime/registry/instagram-embed.d.ts +3 -18
  172. package/dist/runtime/registry/instagram-embed.js +4 -19
  173. package/dist/runtime/registry/intercom.d.ts +5 -13
  174. package/dist/runtime/registry/intercom.js +2 -12
  175. package/dist/runtime/registry/matomo-analytics.d.ts +3 -12
  176. package/dist/runtime/registry/matomo-analytics.js +3 -12
  177. package/dist/runtime/registry/meta-pixel.d.ts +4 -6
  178. package/dist/runtime/registry/meta-pixel.js +2 -4
  179. package/dist/runtime/registry/mixpanel-analytics.d.ts +22 -0
  180. package/dist/runtime/registry/mixpanel-analytics.js +46 -0
  181. package/dist/runtime/registry/npm.d.ts +3 -7
  182. package/dist/runtime/registry/npm.js +2 -9
  183. package/dist/runtime/registry/paypal.d.ts +4 -25
  184. package/dist/runtime/registry/paypal.js +3 -66
  185. package/dist/runtime/registry/plausible-analytics.js +19 -14
  186. package/dist/runtime/registry/posthog.d.ts +10 -12
  187. package/dist/runtime/registry/posthog.js +3 -12
  188. package/dist/runtime/registry/reddit-pixel.d.ts +5 -6
  189. package/dist/runtime/registry/reddit-pixel.js +2 -4
  190. package/dist/runtime/registry/rybbit-analytics.d.ts +2 -14
  191. package/dist/runtime/registry/rybbit-analytics.js +10 -20
  192. package/dist/runtime/registry/schemas.d.ts +982 -0
  193. package/dist/runtime/registry/schemas.js +937 -0
  194. package/dist/runtime/registry/segment.d.ts +2 -5
  195. package/dist/runtime/registry/segment.js +2 -5
  196. package/dist/runtime/registry/snapchat-pixel.d.ts +5 -34
  197. package/dist/runtime/registry/snapchat-pixel.js +2 -20
  198. package/dist/runtime/registry/stripe.d.ts +3 -4
  199. package/dist/runtime/registry/stripe.js +2 -4
  200. package/dist/runtime/registry/tiktok-pixel.d.ts +4 -7
  201. package/dist/runtime/registry/tiktok-pixel.js +2 -6
  202. package/dist/runtime/registry/umami-analytics.d.ts +2 -31
  203. package/dist/runtime/registry/umami-analytics.js +2 -36
  204. package/dist/runtime/registry/vercel-analytics.d.ts +29 -0
  205. package/dist/runtime/registry/vercel-analytics.js +84 -0
  206. package/dist/runtime/registry/vimeo-player.d.ts +2 -2
  207. package/dist/runtime/registry/vimeo-player.js +1 -1
  208. package/dist/runtime/registry/x-embed.d.ts +3 -17
  209. package/dist/runtime/registry/x-embed.js +3 -18
  210. package/dist/runtime/registry/x-pixel.d.ts +4 -7
  211. package/dist/runtime/registry/x-pixel.js +2 -5
  212. package/dist/runtime/registry/youtube-player.d.ts +7 -7
  213. package/dist/runtime/registry/youtube-player.js +1 -1
  214. package/dist/runtime/server/bluesky-embed-image.d.ts +2 -0
  215. package/dist/runtime/server/bluesky-embed-image.js +7 -0
  216. package/dist/runtime/server/bluesky-embed.d.ts +16 -0
  217. package/dist/runtime/server/bluesky-embed.js +59 -0
  218. package/dist/runtime/server/google-maps-geocode-proxy.d.ts +2 -0
  219. package/dist/runtime/server/google-maps-geocode-proxy.js +34 -0
  220. package/dist/runtime/server/google-static-maps-proxy.js +2 -13
  221. package/dist/runtime/server/gravatar-proxy.d.ts +2 -0
  222. package/dist/runtime/server/gravatar-proxy.js +46 -0
  223. package/dist/runtime/server/instagram-embed-asset.js +8 -41
  224. package/dist/runtime/server/instagram-embed-image.js +6 -53
  225. package/dist/runtime/server/instagram-embed.d.ts +16 -0
  226. package/dist/runtime/server/instagram-embed.js +176 -35
  227. package/dist/runtime/server/proxy-handler.js +101 -83
  228. package/dist/runtime/server/utils/image-proxy.d.ts +12 -0
  229. package/dist/runtime/server/utils/image-proxy.js +70 -0
  230. package/dist/runtime/server/utils/privacy.d.ts +1 -10
  231. package/dist/runtime/server/utils/privacy.js +60 -40
  232. package/dist/runtime/server/x-embed-image.js +5 -49
  233. package/dist/runtime/server/x-embed.js +3 -2
  234. package/dist/runtime/types.d.ts +277 -53
  235. package/dist/runtime/types.js +0 -2
  236. package/dist/runtime/utils/pure.d.ts +1 -1
  237. package/dist/runtime/utils.d.ts +6 -4
  238. package/dist/runtime/utils.js +31 -14
  239. package/dist/stats.d.mts +202 -0
  240. package/dist/stats.d.ts +202 -0
  241. package/dist/stats.mjs +3875 -0
  242. package/dist/types-source.d.mts +17 -0
  243. package/dist/types-source.d.ts +17 -0
  244. package/dist/types-source.mjs +3835 -0
  245. package/dist/types.d.mts +4 -2
  246. package/package.json +35 -61
  247. package/README.md +0 -86
  248. package/dist/client/200.html +0 -1
  249. package/dist/client/404.html +0 -1
  250. package/dist/client/_nuxt/BJa0m50V.js +0 -1
  251. package/dist/client/_nuxt/BPQ3VLAy.js +0 -1
  252. package/dist/client/_nuxt/Ci5iXYuB.js +0 -1
  253. package/dist/client/_nuxt/DaI2y8Uz.js +0 -162
  254. package/dist/client/_nuxt/builds/latest.json +0 -1
  255. package/dist/client/_nuxt/builds/meta/9b4fb16a-3c62-48b0-8295-126cb077b5d3.json +0 -1
  256. package/dist/client/_nuxt/entry.D45OuV0w.css +0 -1
  257. package/dist/client/_nuxt/error-404.B57D-jUQ.css +0 -1
  258. package/dist/client/_nuxt/error-500.DTHUW7BI.css +0 -1
  259. package/dist/client/_nuxt/vPLZfVXe.js +0 -1
  260. package/dist/client/index.html +0 -1
  261. package/dist/runtime/components/ScriptPayPalMarks.d.vue.ts +0 -52
  262. package/dist/runtime/components/ScriptPayPalMarks.vue +0 -69
  263. package/dist/runtime/components/ScriptPayPalMarks.vue.d.ts +0 -52
  264. package/dist/runtime/validation/mock.d.ts +0 -42
  265. package/dist/runtime/validation/mock.js +0 -21
  266. package/dist/runtime/validation/valibot.d.ts +0 -1
  267. package/dist/runtime/validation/valibot.js +0 -1
  268. /package/dist/{client → devtools-client}/_nuxt/CVO1_9PV.js +0 -0
  269. /package/dist/{client → devtools-client}/_nuxt/Cp-IABpG.js +0 -0
  270. /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
1
  import { existsSync, readdirSync, readFileSync } from 'node:fs';
3
- import { join, resolve, relative } from 'pathe';
2
+ import { useNuxt, addDevServerHandler, extendRouteRules, tryUseNuxt, createResolver, extendViteConfig, logger as logger$1, useLogger, addTypeTemplate, defineNuxtModule, addPluginTemplate, addServerHandler, addImports, addComponentsDir, addTemplate, hasNuxtModule, addBuildPlugin } from '@nuxt/kit';
4
3
  import { defu } from 'defu';
4
+ import { join, resolve } from 'pathe';
5
5
  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
6
  import { lazyEventHandler, eventHandler, createError } from 'h3';
7
+ import { fetch, $fetch } from 'ofetch';
8
+ import { joinURL, parseURL, parseQuery, hasProtocol } from 'ufo';
17
9
  import { createStorage } from 'unstorage';
18
10
  import fsDriver from 'unstorage/drivers/fs-lite';
19
- import { pathToFileURL } from 'node:url';
20
11
  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");
12
+ import { parseAndWalk, ScopeTracker, walk, ScopeTrackerFunction, ScopeTrackerIdentifier, ScopeTrackerFunctionParam, ScopeTrackerVariable } from 'oxc-walker';
13
+ import { createUnplugin } from 'unplugin';
14
+ import { pathToFileURL } from 'node:url';
15
+ import { createHash } from 'node:crypto';
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,131 @@ 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) {
420
+ return `export default defineNuxtPlugin({
421
+ name: 'nuxt-scripts:intercept',
422
+ enforce: 'pre',
423
+ setup() {
424
+ const proxyPrefix = ${JSON.stringify(proxyPrefix)};
425
+ const origBeacon = typeof navigator !== 'undefined' && navigator.sendBeacon
426
+ ? navigator.sendBeacon.bind(navigator)
427
+ : () => false;
428
+ const origFetch = globalThis.fetch.bind(globalThis);
429
+
430
+ function proxyUrl(url) {
431
+ try {
432
+ const parsed = new URL(url, location.origin);
433
+ if (parsed.origin !== location.origin)
434
+ return location.origin + proxyPrefix + '/' + parsed.host + parsed.pathname + parsed.search;
435
+ } catch {}
436
+ return url;
437
+ }
438
+
439
+ // XMLHttpRequest wrapper \u2014 intercepts .open() to rewrite URL
440
+ const OrigXHR = XMLHttpRequest;
441
+ class ProxiedXHR extends OrigXHR {
442
+ open() {
443
+ const args = Array.from(arguments);
444
+ if (typeof args[1] === 'string') args[1] = proxyUrl(args[1]);
445
+ return super.open.apply(this, args);
446
+ }
447
+ }
448
+ // Image wrapper \u2014 intercepts .src setter to rewrite URL
449
+ const OrigImage = Image;
450
+ const origSrcDesc = Object.getOwnPropertyDescriptor(HTMLImageElement.prototype, 'src');
451
+ function ProxiedImage(w, h) {
452
+ const img = arguments.length === 2 ? new OrigImage(w, h)
453
+ : arguments.length === 1 ? new OrigImage(w) : new OrigImage();
454
+ if (origSrcDesc && origSrcDesc.set) {
455
+ Object.defineProperty(img, 'src', {
456
+ get() { return origSrcDesc.get.call(this); },
457
+ set(v) { origSrcDesc.set.call(this, typeof v === 'string' ? proxyUrl(v) : v); },
458
+ configurable: true,
459
+ });
460
+ }
461
+ return img;
462
+ }
463
+
464
+ globalThis.__nuxtScripts = {
465
+ sendBeacon: (url, data) => origBeacon(proxyUrl(url), data),
466
+ fetch: (url, opts) => {
467
+ if (typeof url === 'string') return origFetch(proxyUrl(url), opts);
468
+ if (url instanceof Request) return origFetch(new Request(proxyUrl(url.url), url), opts);
469
+ return origFetch(url, opts);
470
+ },
471
+ XMLHttpRequest: ProxiedXHR,
472
+ Image: ProxiedImage,
473
+ };
474
+ },
475
+ })
476
+ `;
477
+ }
478
+
479
+ const WORD_OR_DOLLAR_RE = /[\w$]/;
480
+ const PROTOCOL_PREFIX_RE = /^https?:$/;
481
+ const BLANK_CANVAS_DATA_URL = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQIHWNgAAIABQABNjN9GQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAAA0lEQVQI12NgYGBgAAAABQABXvMqOgAAAABJRU5ErkJggg==";
439
482
  function isPropertyKeyAST(parent, ctx) {
440
483
  return parent?.type === "Property" && ctx.key === "key" || parent?.type === "SwitchCase" && ctx.key === "test";
441
484
  }
@@ -445,7 +488,8 @@ function matchAndRewrite(value, rewrites) {
445
488
  const fromSlashIdx = from.indexOf("/");
446
489
  const fromHost = fromSlashIdx > 0 ? from.slice(0, fromSlashIdx) : from;
447
490
  const fromPath = fromSlashIdx > 0 ? from.slice(fromSlashIdx) : "";
448
- if (!value.includes(fromHost)) continue;
491
+ if (!value.includes(fromHost))
492
+ continue;
449
493
  const url = parseURL(value);
450
494
  let shouldRewrite = false;
451
495
  let rewriteSuffix = "";
@@ -488,63 +532,240 @@ function matchAndRewrite(value, rewrites) {
488
532
  }
489
533
  return null;
490
534
  }
491
- function rewriteScriptUrlsAST(content, filename, rewrites) {
535
+ const WINDOW_GLOBALS = /* @__PURE__ */ new Set(["window", "self", "globalThis"]);
536
+ const NAVIGATOR_GLOBALS = /* @__PURE__ */ new Set(["navigator"]);
537
+ function resolveToGlobal(name, scopeTracker, depth = 0) {
538
+ if (depth > 10)
539
+ return null;
540
+ const decl = scopeTracker.getDeclaration(name);
541
+ if (!decl)
542
+ return name;
543
+ if (decl instanceof ScopeTrackerFunctionParam)
544
+ return null;
545
+ if (decl instanceof ScopeTrackerVariable) {
546
+ const declarators = decl.variableNode.declarations;
547
+ if (!declarators)
548
+ return null;
549
+ for (const declarator of declarators) {
550
+ const id = declarator.id;
551
+ if (!id || id.name !== name)
552
+ continue;
553
+ const init = declarator.init;
554
+ if (!init)
555
+ return null;
556
+ if (init.type === "Identifier")
557
+ return resolveToGlobal(init.name, scopeTracker, depth + 1);
558
+ if (init.type === "MemberExpression" && init.object?.type === "Identifier") {
559
+ 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;
560
+ if (!memberProp)
561
+ return null;
562
+ const objGlobal = resolveToGlobal(init.object.name, scopeTracker, depth + 1);
563
+ if (!objGlobal)
564
+ return null;
565
+ if (WINDOW_GLOBALS.has(objGlobal) || objGlobal === "document")
566
+ return memberProp;
567
+ return null;
568
+ }
569
+ return null;
570
+ }
571
+ }
572
+ return null;
573
+ }
574
+ function resolveCalleeTarget(callee, scopeTracker) {
575
+ if (callee?.type !== "MemberExpression")
576
+ return null;
577
+ const propName = callee.computed ? callee.property?.type === "Literal" && typeof callee.property.value === "string" ? callee.property.value : null : callee.property?.name;
578
+ if (!propName)
579
+ return null;
580
+ const obj = callee.object;
581
+ if (!obj || obj.type !== "Identifier")
582
+ return null;
583
+ const resolved = resolveToGlobal(obj.name, scopeTracker);
584
+ if (!resolved)
585
+ return null;
586
+ if (propName === "fetch" && WINDOW_GLOBALS.has(resolved))
587
+ return "fetch";
588
+ if (propName === "sendBeacon" && (NAVIGATOR_GLOBALS.has(resolved) || WINDOW_GLOBALS.has(resolved)))
589
+ return "sendBeacon";
590
+ if (propName === "sendBeacon" && resolved === "navigator")
591
+ return "sendBeacon";
592
+ if (propName === "XMLHttpRequest" && WINDOW_GLOBALS.has(resolved))
593
+ return "XMLHttpRequest";
594
+ if (propName === "Image" && WINDOW_GLOBALS.has(resolved))
595
+ return "Image";
596
+ return null;
597
+ }
598
+ function rewriteScriptUrlsAST(content, filename, rewrites, sdkPatches, options) {
492
599
  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);
503
- }
504
- }
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;
600
+ function needsLeadingSpace(start) {
601
+ const prev = content[start - 1];
602
+ return prev && WORD_OR_DOLLAR_RE.test(prev) ? " " : "";
603
+ }
604
+ const scopeTracker = new ScopeTracker({ preserveExitedScopes: true });
605
+ const { program } = parseAndWalk(content, filename, { scopeTracker });
606
+ scopeTracker.freeze();
607
+ walk(program, {
608
+ scopeTracker,
609
+ enter(node, parent, ctx) {
610
+ if (node.type === "Literal" && typeof node.value === "string") {
611
+ const value = node.value;
510
612
  const rewritten = matchAndRewrite(value, rewrites);
511
- if (rewritten === null) return;
613
+ if (rewritten === null)
614
+ return;
615
+ const quote = content[node.start];
512
616
  if (isPropertyKeyAST(parent, ctx)) {
513
- s.overwrite(node.start, node.end, "`" + rewritten + "`");
617
+ s.overwrite(node.start, node.end, quote + rewritten + quote);
618
+ } else if (value.startsWith("//") && parent?.type === "BinaryExpression" && parent.operator === "+") {
619
+ const sibling = ctx.key === "right" ? parent.left : parent.right;
620
+ if (sibling?.type === "Literal" && typeof sibling.value === "string" && PROTOCOL_PREFIX_RE.test(sibling.value)) {
621
+ s.overwrite(parent.start, parent.end, `${needsLeadingSpace(parent.start)}self.location.origin+${quote}${rewritten}${quote}`);
622
+ } else {
623
+ s.overwrite(node.start, node.end, `${needsLeadingSpace(node.start)}self.location.origin+${quote}${rewritten}${quote}`);
624
+ }
514
625
  } else {
515
- s.overwrite(node.start, node.end, "self.location.origin+`" + rewritten + "`");
626
+ s.overwrite(node.start, node.end, `${needsLeadingSpace(node.start)}self.location.origin+${quote}${rewritten}${quote}`);
516
627
  }
517
628
  }
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");
629
+ if (node.type === "TemplateLiteral") {
630
+ const quasis = node.quasis;
631
+ const expressions = node.expressions;
632
+ if (expressions?.length === 0 && quasis?.length === 1) {
633
+ const value = quasis[0].value?.cooked ?? quasis[0].value?.raw;
634
+ if (typeof value !== "string")
635
+ return;
636
+ const rewritten = matchAndRewrite(value, rewrites);
637
+ if (rewritten === null)
638
+ return;
639
+ if (isPropertyKeyAST(parent, ctx)) {
640
+ s.overwrite(node.start, node.end, `\`${rewritten}\``);
641
+ } else {
642
+ s.overwrite(node.start, node.end, `${needsLeadingSpace(node.start)}self.location.origin+\`${rewritten}\``);
643
+ }
644
+ } else if (expressions?.length > 0 && quasis?.length > 0) {
645
+ const firstQuasi = quasis[0];
646
+ const value = firstQuasi.value?.cooked ?? firstQuasi.value?.raw;
647
+ if (typeof value !== "string" || isPropertyKeyAST(parent, ctx))
648
+ return;
649
+ const rewritten = matchAndRewrite(value, rewrites);
650
+ if (rewritten === null)
651
+ return;
652
+ s.overwrite(node.start, firstQuasi.end, `${needsLeadingSpace(node.start)}self.location.origin+\`${rewritten}`);
653
+ }
654
+ }
655
+ if (node.type === "CallExpression" && !options?.skipApiRewrites) {
656
+ const callee = node.callee;
657
+ const shouldNeutralizeCanvas = options?.neutralizeCanvas !== false;
658
+ 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;
659
+ if (canvasPropName === "toDataURL" && callee.object) {
660
+ const blankCanvas = `"${BLANK_CANVAS_DATA_URL}"`;
661
+ if (callee.object.type === "Identifier") {
662
+ const decl = scopeTracker.getDeclaration(callee.object.name);
663
+ if (decl instanceof ScopeTrackerFunction || decl instanceof ScopeTrackerIdentifier) ; else {
664
+ s.overwrite(node.start, node.end, blankCanvas);
665
+ return;
666
+ }
667
+ } else {
668
+ s.overwrite(node.start, node.end, blankCanvas);
669
+ return;
670
+ }
671
+ }
672
+ if (canvasPropName === "getExtension") {
673
+ const args = node.arguments;
674
+ if (args?.length === 1 && args[0]?.type === "Literal" && args[0].value === "WEBGL_debug_renderer_info") {
675
+ s.overwrite(node.start, node.end, "null");
676
+ return;
677
+ }
678
+ }
679
+ if (callee?.type === "Identifier" && callee.name === "fetch") {
680
+ if (!scopeTracker.getDeclaration("fetch"))
681
+ s.overwrite(callee.start, callee.end, "__nuxtScripts.fetch");
682
+ return;
683
+ }
684
+ const target = resolveCalleeTarget(callee, scopeTracker);
685
+ if (target === "fetch" || target === "sendBeacon") {
686
+ s.overwrite(callee.start, callee.end, `__nuxtScripts.${target}`);
687
+ return;
688
+ }
689
+ if (callee?.type === "MemberExpression" && !callee.computed && callee.property?.name === "sendBeacon" && callee.object?.type === "Identifier") {
690
+ const resolved = resolveToGlobal(callee.object.name, scopeTracker);
691
+ if (resolved === null) {
692
+ s.overwrite(callee.start, callee.end, "__nuxtScripts.sendBeacon");
693
+ }
694
+ }
695
+ }
696
+ if (sdkPatches?.some((p) => p.type === "neutralize-domain-check") && node.type === "BinaryExpression" && node.operator === "<") {
697
+ const left = node.left;
698
+ const right = node.right;
699
+ if (right?.type === "Literal" && right.value === 0 && left?.type === "CallExpression" && left.callee?.type === "MemberExpression") {
700
+ 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;
701
+ if (prop === "indexOf" && left.arguments?.length === 1) {
702
+ const arg = left.arguments[0];
703
+ if (arg?.type === "Literal" && typeof arg.value === "string" && rewrites.some((r) => arg.value.includes(r.from))) {
704
+ s.overwrite(right.start, right.end, "-1");
705
+ }
706
+ }
707
+ }
523
708
  }
524
- if (callee?.type === "Identifier" && callee.name === "fetch") {
525
- s.overwrite(callee.start, callee.end, "__nuxtScripts.fetch");
709
+ if (sdkPatches?.some((p) => p.type === "replace-src-split") && node.type === "MemberExpression" && node.computed) {
710
+ const prop = node.property;
711
+ const obj = node.object;
712
+ if (prop?.type === "Literal" && prop.value === 0 && obj?.type === "CallExpression" && obj.callee?.type === "MemberExpression") {
713
+ 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;
714
+ if (callProp === "split" && obj.arguments?.length === 1) {
715
+ const arg = obj.arguments[0];
716
+ if (arg?.type === "Literal" && typeof arg.value === "string") {
717
+ for (const patch of sdkPatches) {
718
+ if (patch.type !== "replace-src-split" || patch.separator !== arg.value)
719
+ continue;
720
+ const rewrite = rewrites.find((r) => r.from === patch.fromDomain);
721
+ if (!rewrite)
722
+ continue;
723
+ const proxyPath = patch.appendPath ? `${rewrite.to}/${patch.appendPath}` : rewrite.to;
724
+ s.overwrite(node.start, node.end, `${needsLeadingSpace(node.start)}self.location.origin+"${proxyPath}"`);
725
+ }
726
+ }
727
+ }
728
+ }
526
729
  }
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");
730
+ if (node.type === "NewExpression" && !options?.skipApiRewrites) {
731
+ const callee = node.callee;
732
+ if (callee?.type === "Identifier" && callee.name === "XMLHttpRequest") {
733
+ if (!scopeTracker.getDeclaration("XMLHttpRequest"))
734
+ s.overwrite(callee.start, callee.end, "__nuxtScripts.XMLHttpRequest");
735
+ return;
736
+ }
737
+ if (callee?.type === "Identifier" && callee.name === "Image") {
738
+ if (!scopeTracker.getDeclaration("Image"))
739
+ s.overwrite(callee.start, callee.end, "__nuxtScripts.Image");
740
+ return;
741
+ }
742
+ const target = resolveCalleeTarget(callee, scopeTracker);
743
+ if (target === "XMLHttpRequest" || target === "Image") {
744
+ s.overwrite(callee.start, callee.end, `__nuxtScripts.${target}`);
745
+ return;
746
+ }
747
+ if (callee?.type === "MemberExpression" && callee.object?.type === "Identifier") {
748
+ const propName = callee.computed ? callee.property?.type === "Literal" && typeof callee.property.value === "string" ? callee.property.value : null : callee.property?.name;
749
+ if (propName === "XMLHttpRequest" || propName === "Image") {
750
+ const resolved = resolveToGlobal(callee.object.name, scopeTracker);
751
+ if (resolved === null) {
752
+ s.overwrite(callee.start, callee.end, `__nuxtScripts.${propName}`);
753
+ }
754
+ }
755
+ }
529
756
  }
530
757
  }
531
758
  });
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;
759
+ return s.toString();
545
760
  }
546
761
 
547
762
  const SEVEN_DAYS_IN_MS = 7 * 24 * 60 * 60 * 1e3;
763
+ const PROTOCOL_RELATIVE_RE = /^\/\//;
764
+ const VUE_RE = /\.vue/;
765
+ const JS_RE = /\.[cm]?[jt]sx?$/;
766
+ const TEST_RE = /\.(?:test|spec)\./;
767
+ const UPPERCASE_RE = /^[A-Z]$/;
768
+ const USE_SCRIPT_RE = /^useScript/;
548
769
  function calculateIntegrity(content, algorithm = "sha384") {
549
770
  const hash = createHash(algorithm).update(content).digest("base64");
550
771
  return `${algorithm}-${hash}`;
@@ -557,9 +778,9 @@ async function isCacheExpired(storage, filename, cacheMaxAge = SEVEN_DAYS_IN_MS)
557
778
  }
558
779
  return Date.now() - meta.timestamp > cacheMaxAge;
559
780
  }
560
- function normalizeScriptData(src, assetsBaseURL = "/_scripts") {
781
+ function normalizeScriptData(src, assetsBaseURL = "/_scripts/assets") {
561
782
  if (hasProtocol(src, { acceptRelative: true })) {
562
- src = src.replace(/^\/\//, "https://");
783
+ src = src.replace(PROTOCOL_RELATIVE_RE, "https://");
563
784
  const url = parseURL(src);
564
785
  const h = hash(url);
565
786
  const file = `${h.startsWith("-") ? `_${h.slice(1)}` : h}.js`;
@@ -571,7 +792,7 @@ function normalizeScriptData(src, assetsBaseURL = "/_scripts") {
571
792
  return { url: src };
572
793
  }
573
794
  async function downloadScript(opts, renderedScript, fetchOptions, cacheMaxAge) {
574
- const { src, url, filename, forceDownload, integrity, proxyRewrites } = opts;
795
+ const { src, url, filename, forceDownload, integrity, proxyRewrites, sdkPatches, skipApiRewrites, neutralizeCanvas } = opts;
575
796
  if (src === url || !filename) {
576
797
  return;
577
798
  }
@@ -609,7 +830,7 @@ async function downloadScript(opts, renderedScript, fetchOptions, cacheMaxAge) {
609
830
  await storage.setItemRaw(`bundle:${filename}`, res);
610
831
  if (proxyRewrites?.length && res) {
611
832
  const content = res.toString("utf-8");
612
- const rewritten = rewriteScriptUrlsAST(content, filename || "script.js", proxyRewrites);
833
+ const rewritten = rewriteScriptUrlsAST(content, filename || "script.js", proxyRewrites, sdkPatches, { skipApiRewrites, neutralizeCanvas });
613
834
  res = Buffer.from(rewritten, "utf-8");
614
835
  logger.debug(`Rewrote ${proxyRewrites.length} URL patterns in ${filename}`);
615
836
  }
@@ -666,8 +887,8 @@ function NuxtScriptBundleTransformer(options = {
666
887
  transform: {
667
888
  filter: {
668
889
  id: {
669
- include: [/\.vue/, /\.[cm]?[jt]sx?$/],
670
- exclude: [/\.(?:test|spec)\./]
890
+ include: [VUE_RE, JS_RE],
891
+ exclude: [TEST_RE]
671
892
  }
672
893
  },
673
894
  async handler(code, id) {
@@ -677,11 +898,11 @@ function NuxtScriptBundleTransformer(options = {
677
898
  return;
678
899
  const s = new MagicString(code);
679
900
  const deferredOps = [];
680
- parseAndWalk(code, id, function(_node) {
901
+ parseAndWalk(code, id, (_node) => {
681
902
  const calleeName = _node.callee?.name;
682
903
  if (!calleeName)
683
904
  return;
684
- const isValidCallee = calleeName === "useScript" || calleeName?.startsWith("useScript") && /^[A-Z]$/.test(calleeName?.charAt(9)) && !calleeName.startsWith("useScriptTrigger") && !calleeName.startsWith("useScriptEvent");
905
+ const isValidCallee = calleeName === "useScript" || calleeName?.startsWith("useScript") && UPPERCASE_RE.test(calleeName?.charAt(9)) && !calleeName.startsWith("useScriptTrigger") && !calleeName.startsWith("useScriptEvent");
685
906
  if (_node.type === "CallExpression" && _node.callee.type === "Identifier" && isValidCallee) {
686
907
  const fnName = _node.callee?.name;
687
908
  const node = _node;
@@ -689,7 +910,7 @@ function NuxtScriptBundleTransformer(options = {
689
910
  let src;
690
911
  let registryKey;
691
912
  if (fnName !== "useScript") {
692
- const baseName = fnName.replace(/^useScript/, "");
913
+ const baseName = fnName.replace(USE_SCRIPT_RE, "");
693
914
  registryKey = baseName.length > 0 ? baseName.charAt(0).toLowerCase() + baseName.slice(1) : void 0;
694
915
  }
695
916
  if (fnName === "useScript") {
@@ -706,7 +927,8 @@ function NuxtScriptBundleTransformer(options = {
706
927
  if (!registryNode) {
707
928
  return;
708
929
  }
709
- if (!registryNode.scriptBundling && !registryNode.src)
930
+ const bundleResolve = getBundleResolve(registryNode);
931
+ if (!bundleResolve && !registryNode.src)
710
932
  return;
711
933
  const registryConfig = options.registryConfig?.[registryKey || ""] || {};
712
934
  const fnArg0 = {};
@@ -725,7 +947,7 @@ function NuxtScriptBundleTransformer(options = {
725
947
  }
726
948
  if (!scriptSrcNode) {
727
949
  const mergedOptions = { ...registryConfig, ...fnArg0 };
728
- src = registryNode.scriptBundling && registryNode.scriptBundling(mergedOptions);
950
+ src = bundleResolve && bundleResolve(mergedOptions);
729
951
  if (src === false)
730
952
  return;
731
953
  if (!src && registryNode.src)
@@ -753,8 +975,9 @@ function NuxtScriptBundleTransformer(options = {
753
975
  if (scriptSrcNode || src) {
754
976
  src = src || (typeof scriptSrcNode?.value === "string" ? scriptSrcNode?.value : false);
755
977
  if (src) {
756
- let canBundle = options.defaultBundle === true || options.defaultBundle === "force";
757
- let forceDownload = options.defaultBundle === "force";
978
+ const registryScript = fnName !== "useScript" ? options.scripts?.find((s2) => s2.import.name === fnName) : void 0;
979
+ let canBundle = !!registryScript?.bundle;
980
+ let forceDownload = false;
758
981
  if (node.arguments[1]?.type === "ObjectExpression") {
759
982
  const scriptOptionsArg = node.arguments[1];
760
983
  const bundleProperty = scriptOptionsArg.properties.find(
@@ -789,31 +1012,39 @@ function NuxtScriptBundleTransformer(options = {
789
1012
  canBundle = bundleValue === true || bundleValue === "force" || String(bundleValue) === "true";
790
1013
  forceDownload = bundleValue === "force";
791
1014
  }
792
- const firstPartyOption = scriptOptions?.value.properties?.find((prop) => {
793
- return prop.type === "Property" && prop.key?.name === "firstParty" && prop.value.type === "Literal";
1015
+ const rpiOption = scriptOptions?.value.properties?.find((prop) => {
1016
+ return prop.type === "Property" && prop.key?.name === "proxy" && prop.value.type === "Literal";
794
1017
  });
795
- let firstPartyOptOut = firstPartyOption?.value.value === false;
1018
+ let firstPartyOptOut = rpiOption?.value.value === false;
796
1019
  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"
1020
+ const secondArgProp = node.arguments[1].properties.find(
1021
+ (p) => p.type === "Property" && p.key?.name === "proxy" && p.value.type === "Literal"
799
1022
  );
800
- firstPartyOptOut = secondArgFirstPartyProp?.value.value === false;
1023
+ firstPartyOptOut = secondArgProp?.value.value === false;
801
1024
  }
802
1025
  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"
1026
+ const firstArgProp = node.arguments[0].properties.find(
1027
+ (p) => p.type === "Property" && p.key?.name === "proxy" && p.value.type === "Literal"
805
1028
  );
806
- firstPartyOptOut = firstArgFirstPartyProp?.value.value === false;
1029
+ firstPartyOptOut = firstArgProp?.value.value === false;
807
1030
  }
808
1031
  if (canBundle) {
809
1032
  const { url: _url, filename } = normalizeScriptData(src, options.assetsBaseURL);
810
1033
  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;
1034
+ const hasReverseProxy = !!script?.proxy;
1035
+ const proxyConfigKey = hasReverseProxy ? typeof script?.proxy === "string" ? script.proxy : registryKey : void 0;
1036
+ const proxyConfig = !firstPartyOptOut && proxyConfigKey ? options.proxyConfigs?.[proxyConfigKey] : void 0;
1037
+ const proxyRewrites = proxyConfig?.domains?.map((domain) => ({
1038
+ from: domain,
1039
+ to: `${options.proxyPrefix}/${domain}`
1040
+ }));
1041
+ const sdkPatches = proxyConfig?.sdkPatches;
1042
+ const skipApiRewrites = !!(registryKey && options.partytownScripts?.has(registryKey));
1043
+ const neutralizeCanvas = proxyConfig?.privacy !== void 0 && typeof proxyConfig.privacy === "object" ? proxyConfig.privacy.hardware ?? true : true;
813
1044
  deferredOps.push(async () => {
814
1045
  let url = _url;
815
1046
  try {
816
- await downloadScript({ src, url, filename, forceDownload, proxyRewrites, integrity: options.integrity }, renderedScript, options.fetchOptions, options.cacheMaxAge);
1047
+ await downloadScript({ src, url, filename, forceDownload, proxyRewrites, sdkPatches, integrity: options.integrity, skipApiRewrites, neutralizeCanvas }, renderedScript, options.fetchOptions, options.cacheMaxAge);
817
1048
  } catch (e) {
818
1049
  if (options.fallbackOnSrcOnBundleFail) {
819
1050
  logger.warn(`[Nuxt Scripts: Bundle Transformer] Failed to bundle ${src}. Fallback to remote loading.`);
@@ -893,113 +1124,15 @@ function NuxtScriptBundleTransformer(options = {
893
1124
  });
894
1125
  }
895
1126
 
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 }) {
1127
+ const TRIGGER_PLACEHOLDER_RE = /"__TRIGGER_PLACEHOLDER__"/g;
1128
+ function registerTypeTemplates({ config, newScripts }) {
992
1129
  addTypeTemplate({
993
1130
  filename: "types/nuxt-scripts-augments.d.ts",
994
1131
  getContents: () => {
995
- const typesPath = relative(
996
- resolve(nuxt.options.rootDir, nuxt.options.buildDir, "types"),
997
- resolve("runtime/types")
998
- );
999
1132
  let augments = `// Generated by @nuxt/scripts
1000
1133
  declare module '#app' {
1001
1134
  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>
1135
+ $scripts: Record<${[...[...Object.keys(config.globals || {}), ...Object.keys(config.registry || {})].map((k) => `'${k}'`), ...["string"]].join(" | ")}, import('#nuxt-scripts/types').UseScriptContext<any> | undefined>
1003
1136
  _scripts: Record<string, import('#nuxt-scripts/types').NuxtDevToolsScriptInstance>
1004
1137
  }
1005
1138
  interface RuntimeNuxtHooks {
@@ -1010,12 +1143,11 @@ declare module '#app' {
1010
1143
  if (newScripts.length) {
1011
1144
  augments += `
1012
1145
  declare module '#nuxt-scripts/types' {
1013
- type _NuxtScriptOptions = Omit<import('${typesPath}').NuxtUseScriptOptions, 'use' | 'beforeInit'>
1014
1146
  interface ScriptRegistry {
1015
1147
  ${newScripts.map((i) => {
1016
1148
  const key = i.import.name.replace("useScript", "");
1017
1149
  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]`;
1150
+ return ` ${keyLcFirst}?: import('${i.import.from}').${key}Input`;
1019
1151
  }).join("\n")}
1020
1152
  }
1021
1153
  }
@@ -1071,7 +1203,7 @@ function resolveTriggerForTemplate(trigger) {
1071
1203
  function templatePlugin(config, registry) {
1072
1204
  if (Array.isArray(config.globals)) {
1073
1205
  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.");
1206
+ logger.warn("The `globals` array option is deprecated. Convert to an object: `globals: { myScript: 'https://example.com/script.js' }`");
1075
1207
  }
1076
1208
  const imports = [];
1077
1209
  const inits = [];
@@ -1080,29 +1212,31 @@ function templatePlugin(config, registry) {
1080
1212
  let needsInteractionImport = false;
1081
1213
  let needsServiceWorkerImport = false;
1082
1214
  for (const [k, c] of Object.entries(config.registry || {})) {
1215
+ if (c === false)
1216
+ continue;
1217
+ const entry = c;
1218
+ const [, scriptOptions] = entry;
1219
+ if (!scriptOptions?.trigger)
1220
+ continue;
1083
1221
  const importDefinition = registry.find((i) => i.import.name.toLowerCase() === `usescript${k.toLowerCase()}`);
1084
1222
  if (importDefinition) {
1085
1223
  resolvedRegistryKeys.push(k);
1086
1224
  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)})`);
1225
+ const [input] = entry;
1226
+ const opts = { ...scriptOptions };
1227
+ const triggerResolved = resolveTriggerForTemplate(opts.trigger);
1228
+ if (triggerResolved) {
1229
+ opts.trigger = "__TRIGGER_PLACEHOLDER__";
1230
+ if (triggerResolved.includes("useScriptTriggerIdleTimeout"))
1231
+ needsIdleTimeoutImport = true;
1232
+ if (triggerResolved.includes("useScriptTriggerInteraction"))
1233
+ needsInteractionImport = true;
1234
+ if (triggerResolved.includes("useScriptTriggerServiceWorker"))
1235
+ needsServiceWorkerImport = true;
1105
1236
  }
1237
+ const args = { ...input, scriptOptions: opts };
1238
+ const argsJson = triggerResolved ? JSON.stringify(args).replace(TRIGGER_PLACEHOLDER_RE, triggerResolved) : JSON.stringify(args);
1239
+ inits.push(`const ${k} = ${importDefinition.import.name}(${argsJson})`);
1106
1240
  }
1107
1241
  }
1108
1242
  for (const [k, c] of Object.entries(config.globals || {})) {
@@ -1112,11 +1246,14 @@ function templatePlugin(config, registry) {
1112
1246
  const options = c[1];
1113
1247
  const triggerResolved = resolveTriggerForTemplate(options?.trigger);
1114
1248
  if (triggerResolved) {
1115
- if (triggerResolved.includes("useScriptTriggerIdleTimeout")) needsIdleTimeoutImport = true;
1116
- if (triggerResolved.includes("useScriptTriggerInteraction")) needsInteractionImport = true;
1117
- if (triggerResolved.includes("useScriptTriggerServiceWorker")) needsServiceWorkerImport = true;
1249
+ if (triggerResolved.includes("useScriptTriggerIdleTimeout"))
1250
+ needsIdleTimeoutImport = true;
1251
+ if (triggerResolved.includes("useScriptTriggerInteraction"))
1252
+ needsInteractionImport = true;
1253
+ if (triggerResolved.includes("useScriptTriggerServiceWorker"))
1254
+ needsServiceWorkerImport = true;
1118
1255
  const resolvedOptions = { ...options, trigger: "__TRIGGER_PLACEHOLDER__" };
1119
- const optionsJson = JSON.stringify(resolvedOptions).replace(/"__TRIGGER_PLACEHOLDER__"/g, triggerResolved);
1256
+ const optionsJson = JSON.stringify(resolvedOptions).replace(TRIGGER_PLACEHOLDER_RE, triggerResolved);
1120
1257
  inits.push(`const ${k} = useScript(${JSON.stringify({ key: k, ...typeof c[0] === "string" ? { src: c[0] } : c[0] })}, { ...${optionsJson}, use: () => ({ ${k}: window.${k} }) })`);
1121
1258
  } else {
1122
1259
  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 +1261,14 @@ function templatePlugin(config, registry) {
1124
1261
  } else if (typeof c === "object" && c !== null) {
1125
1262
  const triggerResolved = resolveTriggerForTemplate(c.trigger);
1126
1263
  if (triggerResolved) {
1127
- if (triggerResolved.includes("useScriptTriggerIdleTimeout")) needsIdleTimeoutImport = true;
1128
- if (triggerResolved.includes("useScriptTriggerInteraction")) needsInteractionImport = true;
1129
- if (triggerResolved.includes("useScriptTriggerServiceWorker")) needsServiceWorkerImport = true;
1264
+ if (triggerResolved.includes("useScriptTriggerIdleTimeout"))
1265
+ needsIdleTimeoutImport = true;
1266
+ if (triggerResolved.includes("useScriptTriggerInteraction"))
1267
+ needsInteractionImport = true;
1268
+ if (triggerResolved.includes("useScriptTriggerServiceWorker"))
1269
+ needsServiceWorkerImport = true;
1130
1270
  const resolvedOptions = { ...c, trigger: "__TRIGGER_PLACEHOLDER__" };
1131
- const argsJson = JSON.stringify({ key: k, ...resolvedOptions }).replace(/"__TRIGGER_PLACEHOLDER__"/g, triggerResolved);
1271
+ const argsJson = JSON.stringify({ key: k, ...resolvedOptions }).replace(TRIGGER_PLACEHOLDER_RE, triggerResolved);
1132
1272
  inits.push(`const ${k} = useScript(${argsJson}, { use: () => ({ ${k}: window.${k} }) })`);
1133
1273
  } else {
1134
1274
  inits.push(`const ${k} = useScript(${JSON.stringify({ key: k, ...c })}, { use: () => ({ ${k}: window.${k} }) })`);
@@ -1157,7 +1297,7 @@ function templatePlugin(config, registry) {
1157
1297
  ` parallel: true,`,
1158
1298
  ` setup() {`,
1159
1299
  ...inits.map((i) => ` ${i}`),
1160
- ` return { provide: { $scripts: { ${[...Object.keys(config.globals || {}), ...resolvedRegistryKeys].join(", ")} } } }`,
1300
+ ` return { provide: { scripts: { ${[...Object.keys(config.globals || {}), ...resolvedRegistryKeys].join(", ")} } } }`,
1161
1301
  ` }`,
1162
1302
  `})`
1163
1303
  ].join("\n");
@@ -1167,22 +1307,28 @@ const SELF_CLOSING_SCRIPT_RE = /<((?:Script[A-Z]|script-)\w[\w-]*)\b([^>]*?)\/\s
1167
1307
  function fixSelfClosingScriptComponents(nuxt) {
1168
1308
  function expandTags(content) {
1169
1309
  SELF_CLOSING_SCRIPT_RE.lastIndex = 0;
1170
- if (!SELF_CLOSING_SCRIPT_RE.test(content)) return null;
1310
+ if (!SELF_CLOSING_SCRIPT_RE.test(content))
1311
+ return null;
1171
1312
  SELF_CLOSING_SCRIPT_RE.lastIndex = 0;
1172
1313
  return content.replace(SELF_CLOSING_SCRIPT_RE, (_, tag, attrs) => `<${tag}${attrs.trimEnd()}></${tag}>`);
1173
1314
  }
1174
1315
  function fixFile(filePath) {
1175
- if (!existsSync(filePath)) return;
1316
+ if (!existsSync(filePath))
1317
+ return;
1176
1318
  const content = readFileSync(filePath, "utf-8");
1177
1319
  const fixed = expandTags(content);
1178
- if (fixed) nuxt.vfs[filePath] = fixed;
1320
+ if (fixed)
1321
+ nuxt.vfs[filePath] = fixed;
1179
1322
  }
1180
1323
  function scanDir(dir) {
1181
- if (!existsSync(dir)) return;
1324
+ if (!existsSync(dir))
1325
+ return;
1182
1326
  for (const entry of readdirSync(dir, { withFileTypes: true })) {
1183
1327
  const fullPath = resolve(dir, entry.name);
1184
- if (entry.isDirectory()) scanDir(fullPath);
1185
- else if (entry.name.endsWith(".vue")) fixFile(fullPath);
1328
+ if (entry.isDirectory())
1329
+ scanDir(fullPath);
1330
+ else if (entry.name.endsWith(".vue"))
1331
+ fixFile(fullPath);
1186
1332
  }
1187
1333
  }
1188
1334
  const pagesDirs = /* @__PURE__ */ new Set();
@@ -1195,7 +1341,8 @@ function fixSelfClosingScriptComponents(nuxt) {
1195
1341
  for (const dir of pagesDirs) scanDir(dir);
1196
1342
  if (nuxt.options.dev) {
1197
1343
  nuxt.hook("builder:watch", (_event, relativePath) => {
1198
- if (!relativePath.endsWith(".vue")) return;
1344
+ if (!relativePath.endsWith(".vue"))
1345
+ return;
1199
1346
  for (const layer of nuxt.options._layers) {
1200
1347
  const fullPath = resolve(layer.config.srcDir, relativePath);
1201
1348
  for (const dir of pagesDirs) {
@@ -1208,20 +1355,37 @@ function fixSelfClosingScriptComponents(nuxt) {
1208
1355
  });
1209
1356
  }
1210
1357
  }
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
- };
1358
+ const UPPER_RE = /([A-Z])/g;
1359
+ const toScreamingSnake = (s) => s.replace(UPPER_RE, "_$1").toUpperCase();
1360
+ function isProxyDisabled(registryKey, registry2, runtimeConfig) {
1361
+ const entry = registry2?.[registryKey];
1362
+ if (!entry)
1363
+ return true;
1364
+ const [input, scriptOptions] = entry;
1365
+ if (input?.proxy === false || scriptOptions?.proxy === false)
1366
+ return true;
1367
+ if (runtimeConfig) {
1368
+ const rtEntry = runtimeConfig.public?.scripts?.[registryKey];
1369
+ if (rtEntry?.proxy === false)
1370
+ return true;
1371
+ }
1372
+ return false;
1373
+ }
1374
+ function applyAutoInject(registry2, runtimeConfig, proxyPrefix, registryKey, autoInject) {
1375
+ if (isProxyDisabled(registryKey, registry2, runtimeConfig))
1376
+ return;
1377
+ const entry = registry2[registryKey];
1378
+ const input = entry[0];
1379
+ const rtScripts = runtimeConfig.public?.scripts;
1380
+ const rtEntry = rtScripts?.[registryKey];
1381
+ const config = rtEntry && typeof rtEntry === "object" ? rtEntry : input;
1382
+ if (!config || config[autoInject.configField])
1383
+ return;
1384
+ const value = autoInject.computeValue(proxyPrefix, config);
1385
+ input[autoInject.configField] = value;
1386
+ if (rtEntry && typeof rtEntry === "object" && rtEntry !== input)
1387
+ rtEntry[autoInject.configField] = value;
1388
+ }
1225
1389
  const module$1 = defineNuxtModule({
1226
1390
  meta: {
1227
1391
  name: "@nuxt/scripts",
@@ -1231,7 +1395,6 @@ const module$1 = defineNuxtModule({
1231
1395
  }
1232
1396
  },
1233
1397
  defaults: {
1234
- firstParty: true,
1235
1398
  defaultScriptOptions: {
1236
1399
  trigger: "onNuxtReady"
1237
1400
  },
@@ -1253,83 +1416,79 @@ const module$1 = defineNuxtModule({
1253
1416
  debug: false
1254
1417
  },
1255
1418
  async setup(config, nuxt) {
1256
- const { resolvePath } = createResolver(import.meta.url);
1419
+ const { resolve: resolveModule, resolvePath } = createResolver(import.meta.url);
1257
1420
  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
1421
  nuxt.options.alias["#nuxt-scripts"] = await resolvePath("./runtime");
1260
1422
  logger.level = config.debug || nuxt.options.debug ? 4 : 3;
1261
1423
  if (!config.enabled) {
1262
1424
  logger.debug("The module is disabled, skipping setup.");
1263
1425
  return;
1264
1426
  }
1427
+ if (nuxt.options.dev) {
1428
+ setupDevtools(nuxt, { standalone: config._standaloneDevtools });
1429
+ if (config._standaloneDevtools) {
1430
+ const bridgePath = resolveModule("./runtime/devtools-standalone-bridge.client");
1431
+ addPluginTemplate({
1432
+ filename: "modules/nuxt-scripts/devtools-standalone-bridge.client.mjs",
1433
+ getContents() {
1434
+ return `export { default } from '${bridgePath}'`;
1435
+ }
1436
+ });
1437
+ }
1438
+ }
1265
1439
  const { version: unheadVersion } = await readPackageJSON("@unhead/vue", {
1266
1440
  from: nuxt.options.modulesDir
1267
1441
  }).catch(() => ({ version: null }));
1268
1442
  if (unheadVersion?.startsWith("1")) {
1269
1443
  logger.error(`Nuxt Scripts requires Unhead >= 2, you are using v${unheadVersion}. Please run \`nuxi upgrade --clean\` to upgrade...`);
1270
1444
  }
1445
+ const scripts = await registry(resolvePath);
1446
+ if (config.registry) {
1447
+ migrateDeprecatedRegistryKeys(config.registry, (msg) => logger.warn(msg));
1448
+ normalizeRegistryConfig(config.registry, (msg) => logger.warn(msg));
1449
+ nuxt.options.runtimeConfig.public = nuxt.options.runtimeConfig.public || {};
1450
+ const registryWithDefaults = {};
1451
+ for (const [key, entry] of Object.entries(config.registry)) {
1452
+ if (entry === false)
1453
+ continue;
1454
+ const input = entry[0];
1455
+ const envDefaults = scripts.find((s) => s.registryKey === key)?.envDefaults;
1456
+ if (!envDefaults || !Object.keys(envDefaults).length) {
1457
+ registryWithDefaults[key] = input;
1458
+ continue;
1459
+ }
1460
+ const envResolved = {};
1461
+ for (const [field, defaultValue] of Object.entries(envDefaults)) {
1462
+ const envKey = `NUXT_PUBLIC_SCRIPTS_${toScreamingSnake(key)}_${toScreamingSnake(field)}`;
1463
+ envResolved[field] = process.env[envKey] || defaultValue;
1464
+ }
1465
+ registryWithDefaults[key] = defu(input, envResolved);
1466
+ }
1467
+ nuxt.options.runtimeConfig.public.scripts = defu(
1468
+ nuxt.options.runtimeConfig.public.scripts || {},
1469
+ registryWithDefaults
1470
+ );
1471
+ }
1472
+ const googleMapsEnabled = config.googleStaticMapsProxy?.enabled || !!config.registry?.googleMaps;
1271
1473
  nuxt.options.runtimeConfig["nuxt-scripts"] = {
1272
1474
  version,
1273
1475
  // Private proxy config with API key (server-side only)
1274
- googleStaticMapsProxy: config.googleStaticMapsProxy?.enabled ? { apiKey: nuxt.options.runtimeConfig.public.scripts?.googleMaps?.apiKey } : void 0
1476
+ googleStaticMapsProxy: googleMapsEnabled ? { apiKey: nuxt.options.runtimeConfig.public.scripts?.googleMaps?.apiKey } : void 0
1275
1477
  };
1276
1478
  nuxt.options.runtimeConfig.public["nuxt-scripts"] = {
1277
1479
  // expose for devtools
1278
1480
  version: nuxt.options.dev ? version : void 0,
1481
+ prefix: config.prefix || "/_scripts",
1279
1482
  defaultScriptOptions: config.defaultScriptOptions,
1280
1483
  // Only expose enabled and cacheMaxAge to client, not apiKey
1281
- googleStaticMapsProxy: config.googleStaticMapsProxy?.enabled ? { enabled: true, cacheMaxAge: config.googleStaticMapsProxy.cacheMaxAge } : void 0
1484
+ googleStaticMapsProxy: googleMapsEnabled ? { enabled: true, cacheMaxAge: config.googleStaticMapsProxy?.cacheMaxAge ?? 3600 } : void 0
1282
1485
  };
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
- }
1486
+ const scriptsBase = config.prefix || "/_scripts";
1487
+ const proxyPrefix = `${scriptsBase}/p`;
1488
+ const assetsPrefix = `${scriptsBase}/assets`;
1489
+ const proxyConfigs = {};
1490
+ const proxyHandlerPath = await resolvePath("./runtime/server/proxy-handler");
1491
+ addServerHandler({ route: `${proxyPrefix}/**`, handler: proxyHandlerPath });
1333
1492
  const composables = [
1334
1493
  "useScript",
1335
1494
  "useScriptEventPage",
@@ -1358,60 +1517,37 @@ const module$1 = defineNuxtModule({
1358
1517
  return templateTriggerResolver(config.defaultScriptOptions);
1359
1518
  }
1360
1519
  });
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);
1520
+ logger.debug("[nuxt-scripts] Proxy prefix:", proxyPrefix);
1409
1521
  for (const script of scripts) {
1410
1522
  if (script.import?.name) {
1411
1523
  addImports({ priority: 2, ...script.import });
1412
1524
  script._importRegistered = true;
1413
1525
  }
1414
1526
  }
1527
+ if (config.registry) {
1528
+ for (const [key, entry] of Object.entries(config.registry)) {
1529
+ if (!entry)
1530
+ continue;
1531
+ const [input, scriptOptions] = entry;
1532
+ if (scriptOptions?.skipValidation)
1533
+ continue;
1534
+ const script = scripts.find((s) => s.registryKey === key);
1535
+ if (!script?.schema)
1536
+ continue;
1537
+ const requiredFields = extractRequiredFields(script.schema);
1538
+ const missing = requiredFields.filter((f) => !input[f]);
1539
+ if (missing.length) {
1540
+ 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"}.`);
1541
+ }
1542
+ const envDefaultKeys = new Set(Object.keys(script.envDefaults || {}));
1543
+ const userProvidedFields = Object.keys(input).filter((f) => !envDefaultKeys.has(f));
1544
+ if (userProvidedFields.length > 0 && (!scriptOptions || !("trigger" in scriptOptions))) {
1545
+ logger.warn(
1546
+ `[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`
1547
+ );
1548
+ }
1549
+ }
1550
+ }
1415
1551
  nuxt.hooks.hook("modules:done", async () => {
1416
1552
  const registryScripts = [...scripts];
1417
1553
  await nuxt.hooks.callHook("scripts:registry", registryScripts);
@@ -1422,7 +1558,7 @@ const module$1 = defineNuxtModule({
1422
1558
  }
1423
1559
  const registryScriptsWithImport = registryScripts.filter((i) => !!i.import?.name);
1424
1560
  const newScripts = registryScriptsWithImport.filter((i) => !scripts.some((r) => r.import?.name === i.import.name));
1425
- registerTypeTemplates({ nuxt, config, newScripts });
1561
+ registerTypeTemplates({ config, newScripts });
1426
1562
  if (Object.keys(config.globals || {}).length || Object.keys(config.registry || {}).length) {
1427
1563
  addPluginTemplate({
1428
1564
  filename: `modules/${name.replace("/", "-")}/plugin.mjs`,
@@ -1431,79 +1567,123 @@ const module$1 = defineNuxtModule({
1431
1567
  }
1432
1568
  });
1433
1569
  }
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 = {};
1570
+ const { renderedScript } = setupPublicAssetStrategy(assetsPrefix);
1571
+ const scriptByKey = /* @__PURE__ */ new Map();
1572
+ for (const script of registryScripts) {
1573
+ if (script.registryKey)
1574
+ scriptByKey.set(script.registryKey, script);
1575
+ }
1576
+ const partytownScripts = /* @__PURE__ */ new Set();
1577
+ let anyNeedsProxy = false;
1578
+ const registryKeys = Object.keys(config.registry || {});
1579
+ for (const key of registryKeys) {
1580
+ const script = scriptByKey.get(key);
1581
+ if (!script)
1582
+ continue;
1583
+ const entry = config.registry?.[key];
1584
+ const scriptOptions = entry?.[1] || {};
1585
+ const inputOptions = entry?.[0] || {};
1586
+ const mergedOverrides = { ...inputOptions, ...scriptOptions };
1587
+ const resolved = resolveCapabilities(script, mergedOverrides);
1588
+ if (resolved.proxy)
1589
+ anyNeedsProxy = true;
1590
+ if (resolved.partytown) {
1591
+ partytownScripts.add(key);
1592
+ const forwards = getPartytownForwards(script);
1593
+ if (forwards?.length && hasNuxtModule("@nuxtjs/partytown")) {
1594
+ const partytownConfig = nuxt.options.partytown || {};
1595
+ const existingForwards = partytownConfig.forward || [];
1596
+ const newForwards = [.../* @__PURE__ */ new Set([...existingForwards, ...forwards])];
1597
+ nuxt.options.partytown = { ...partytownConfig, forward: newForwards };
1598
+ } else if (!forwards?.length && import.meta.dev) {
1599
+ logger.warn(`[partytown] "${key}" has no known Partytown forwards configured. It may not work correctly or may require manual forward configuration.`);
1600
+ }
1601
+ }
1602
+ }
1603
+ if (anyNeedsProxy) {
1604
+ const builtConfigs = buildProxyConfigsFromRegistry(registryScripts, scriptByKey);
1605
+ Object.assign(proxyConfigs, builtConfigs);
1606
+ const domainPrivacy = {};
1440
1607
  const unsupportedScripts = [];
1608
+ const unmatchedScripts = [];
1609
+ let totalDomains = 0;
1610
+ const devtoolsScripts = [];
1441
1611
  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
- }
1612
+ const script = scriptByKey.get(key);
1613
+ if (!script) {
1614
+ unmatchedScripts.push(key);
1615
+ continue;
1454
1616
  }
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`;
1617
+ if (!script.proxy)
1618
+ continue;
1619
+ if (isProxyDisabled(key, config.registry))
1620
+ continue;
1621
+ const configKey = typeof script.proxy === "string" ? script.proxy : key;
1622
+ const proxyConfig = proxyConfigs[configKey];
1623
+ if (!proxyConfig) {
1624
+ unsupportedScripts.push(key);
1625
+ continue;
1626
+ }
1627
+ const entry = config.registry?.[key];
1628
+ const inputPrivacy = entry?.[0]?.privacy;
1629
+ for (const domain of proxyConfig.domains) {
1630
+ domainPrivacy[domain] = inputPrivacy ?? proxyConfig.privacy;
1631
+ totalDomains++;
1461
1632
  }
1633
+ if (proxyConfig.autoInject && config.registry)
1634
+ applyAutoInject(config.registry, nuxt.options.runtimeConfig, proxyPrefix, key, proxyConfig.autoInject);
1635
+ if (nuxt.options.dev)
1636
+ devtoolsScripts.push(buildDevtoolsEntry(key, script, configKey, proxyConfig));
1462
1637
  }
1463
- if (unsupportedScripts.length && nuxt.options.dev) {
1638
+ if (unmatchedScripts.length) {
1464
1639
  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`
1640
+ `Proxy mode: could not find registry scripts for: ${unmatchedScripts.join(", ")}.
1641
+ These scripts will not have proxy routes registered.`
1467
1642
  );
1468
1643
  }
1469
- interceptRules = routesToInterceptRules(neededRoutes);
1470
- const flatRoutes = {};
1471
- for (const [path, config2] of Object.entries(neededRoutes)) {
1472
- flatRoutes[path] = config2.proxy;
1644
+ if (unsupportedScripts.length && nuxt.options.dev) {
1645
+ logger.warn(
1646
+ `Proxy mode is enabled but these scripts don't support it yet: ${unsupportedScripts.join(", ")}.
1647
+ They will load directly from third-party servers.`
1648
+ );
1473
1649
  }
1650
+ addPluginTemplate({
1651
+ filename: "nuxt-scripts-intercept.client.mjs",
1652
+ getContents() {
1653
+ return generateInterceptPluginContents(proxyPrefix);
1654
+ }
1655
+ });
1474
1656
  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
1657
+ proxyPrefix,
1658
+ domainPrivacy,
1659
+ privacy: config.privacy
1480
1660
  };
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
- }
1661
+ const privacyLabel = config.privacy === void 0 ? "per-script" : typeof config.privacy === "boolean" ? config.privacy ? "anonymize" : "passthrough" : "custom";
1662
+ if (totalDomains > 0 && nuxt.options.dev) {
1663
+ logger.success(`Proxy mode enabled for ${registryKeys.length} script(s), ${totalDomains} domain(s) proxied (privacy: ${privacyLabel})`);
1493
1664
  }
1494
- if (isStaticPreset) {
1665
+ const staticPresets = ["static", "github-pages", "cloudflare-pages-static", "netlify-static", "azure-static", "firebase-static"];
1666
+ const preset = process.env.NITRO_PRESET || "";
1667
+ if (staticPresets.includes(preset)) {
1495
1668
  logger.warn(
1496
- `First-party collection endpoints require a server runtime (detected: ${preset || "static"}).
1669
+ `Proxy collection endpoints require a server runtime (detected: ${preset || "static"}).
1497
1670
  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`
1671
+ Options: configure platform rewrites, switch to server-rendered mode, or disable with proxy: false.`
1505
1672
  );
1506
1673
  }
1674
+ if (nuxt.options.dev) {
1675
+ nuxt.options.runtimeConfig.public["nuxt-scripts-devtools"] = buildDevtoolsData(proxyPrefix, privacyLabel, devtoolsScripts);
1676
+ }
1677
+ if (partytownScripts.size && hasNuxtModule("@nuxtjs/partytown")) {
1678
+ const partytownConfig = nuxt.options.partytown || {};
1679
+ if (!partytownConfig.resolveUrl) {
1680
+ partytownConfig.resolveUrl = generatePartytownResolveUrl(proxyPrefix);
1681
+ nuxt.options.partytown = partytownConfig;
1682
+ logger.info("[partytown] Auto-configured resolveUrl for proxy");
1683
+ } else {
1684
+ logger.warn("[partytown] Custom resolveUrl already set. Add proxy rules to your resolveUrl manually.");
1685
+ }
1686
+ }
1507
1687
  }
1508
1688
  const moduleInstallPromises = /* @__PURE__ */ new Map();
1509
1689
  addBuildPlugin(NuxtScriptsCheckScripts(), {
@@ -1512,9 +1692,9 @@ See: https://scripts.nuxt.com/docs/guides/first-party#static-hosting`
1512
1692
  addBuildPlugin(NuxtScriptBundleTransformer({
1513
1693
  scripts: registryScriptsWithImport,
1514
1694
  registryConfig: nuxt.options.runtimeConfig.public.scripts,
1515
- defaultBundle: firstPartyEnabled || config.defaultScriptOptions?.bundle,
1516
- firstPartyEnabled,
1517
- firstPartyCollectPrefix,
1695
+ proxyConfigs,
1696
+ proxyPrefix,
1697
+ partytownScripts,
1518
1698
  moduleDetected(module) {
1519
1699
  if (nuxt.options.dev && module !== "@nuxt/scripts" && !moduleInstallPromises.has(module) && !hasNuxtModule(module))
1520
1700
  moduleInstallPromises.set(module, () => installNuxtModule(module));
@@ -1527,41 +1707,46 @@ See: https://scripts.nuxt.com/docs/guides/first-party#static-hosting`
1527
1707
  renderedScript
1528
1708
  }));
1529
1709
  nuxt.hooks.hook("build:done", async () => {
1530
- const initPromise = Array.from(moduleInstallPromises.values());
1710
+ const initPromise = [...moduleInstallPromises.values()];
1531
1711
  for (const p of initPromise)
1532
1712
  await p?.();
1533
1713
  });
1534
1714
  });
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
- });
1540
- }
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);
1715
+ const scriptsPrefix = config.prefix || "/_scripts";
1716
+ const enabledEndpoints = {};
1717
+ for (const script of scripts) {
1718
+ if (!script.serverHandlers?.length || !script.registryKey)
1719
+ continue;
1720
+ const isEnabled = script.registryKey === "googleMaps" ? config.googleStaticMapsProxy?.enabled || config.registry?.googleMaps : config.registry?.[script.registryKey];
1721
+ if (!isEnabled)
1722
+ continue;
1723
+ enabledEndpoints[script.registryKey] = true;
1724
+ for (const handler of script.serverHandlers) {
1725
+ addServerHandler({
1726
+ route: handler.route.replace("/_scripts", scriptsPrefix),
1727
+ handler: handler.handler,
1728
+ middleware: handler.middleware
1729
+ });
1730
+ }
1731
+ if (script.registryKey === "gravatar") {
1732
+ const gravatarConfig = config.registry?.gravatar?.[0] || {};
1733
+ nuxt.options.runtimeConfig.public["nuxt-scripts"] = defu(
1734
+ { gravatarProxy: { cacheMaxAge: gravatarConfig.cacheMaxAge ?? 3600 } },
1735
+ nuxt.options.runtimeConfig.public["nuxt-scripts"]
1736
+ );
1737
+ }
1738
+ if (script.registryKey === "googleMaps") {
1739
+ nuxt.options.runtimeConfig["nuxt-scripts"] = defu(
1740
+ { googleMapsGeocodeProxy: { apiKey: nuxt.options.runtimeConfig.public.scripts?.googleMaps?.apiKey } },
1741
+ nuxt.options.runtimeConfig["nuxt-scripts"]
1742
+ );
1743
+ }
1563
1744
  }
1745
+ nuxt.options.runtimeConfig.public["nuxt-scripts"] = defu(
1746
+ { endpoints: enabledEndpoints },
1747
+ nuxt.options.runtimeConfig.public["nuxt-scripts"]
1748
+ );
1564
1749
  }
1565
1750
  });
1566
1751
 
1567
- export { module$1 as default };
1752
+ export { applyAutoInject, module$1 as default, isProxyDisabled };