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