@nuxt/scripts 1.0.0-beta.2 → 1.0.0-beta.20
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/README.md +3 -3
- package/dist/client/200.html +1 -1
- package/dist/client/404.html +1 -1
- package/dist/client/_nuxt/{B66N9HCo.js → 9LJPrOyI.js} +1 -1
- package/dist/client/_nuxt/DFEfk2pB.js +162 -0
- package/dist/client/_nuxt/{DvH517bE.js → DMlY-BNa.js} +1 -1
- package/dist/client/_nuxt/{DfLgoB--.js → __ZZTkMj.js} +1 -1
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/8212d4fa-7985-421b-815a-03a886e667d4.json +1 -0
- package/dist/client/_nuxt/entry.CACgbLJl.css +1 -0
- package/dist/client/_nuxt/error-404.CHeaW3dp.css +1 -0
- package/dist/client/_nuxt/error-500.DvOvWme_.css +1 -0
- package/dist/client/index.html +1 -1
- package/dist/module.d.mts +27 -18
- package/dist/module.d.ts +178 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +747 -527
- package/dist/registry.d.ts +6 -0
- package/dist/registry.mjs +74 -21
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.d.vue.ts +2 -2
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.vue +7 -7
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.vue.d.ts +2 -2
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsAdvancedMarkerElement.vue +6 -6
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsCircle.vue +7 -7
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsHeatmapLayer.vue +6 -6
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsInfoWindow.vue +12 -12
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarker.vue +6 -6
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.d.vue.ts +1 -1
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.vue +6 -6
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.vue.d.ts +1 -1
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPinElement.vue +5 -5
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPolygon.vue +7 -7
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPolyline.vue +7 -7
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsRectangle.vue +7 -7
- package/dist/runtime/components/ScriptCrisp.vue +1 -1
- package/dist/runtime/components/ScriptGoogleAdsense.vue +1 -1
- 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.vue +1 -1
- package/dist/runtime/components/ScriptIntercom.vue +4 -3
- package/dist/runtime/components/ScriptPayPalButtons.d.vue.ts +43 -32
- package/dist/runtime/components/ScriptPayPalButtons.vue +48 -79
- package/dist/runtime/components/ScriptPayPalButtons.vue.d.ts +43 -32
- package/dist/runtime/components/ScriptPayPalMessages.d.vue.ts +37 -23
- package/dist/runtime/components/ScriptPayPalMessages.vue +46 -50
- package/dist/runtime/components/ScriptPayPalMessages.vue.d.ts +37 -23
- package/dist/runtime/components/ScriptStripePricingTable.vue +2 -2
- package/dist/runtime/components/ScriptVimeoPlayer.d.vue.ts +9 -0
- package/dist/runtime/components/ScriptVimeoPlayer.vue +13 -10
- package/dist/runtime/components/ScriptVimeoPlayer.vue.d.ts +9 -0
- package/dist/runtime/components/ScriptXEmbed.d.vue.ts +1 -1
- package/dist/runtime/components/ScriptXEmbed.vue +1 -1
- package/dist/runtime/components/ScriptXEmbed.vue.d.ts +1 -1
- package/dist/runtime/components/ScriptYouTubePlayer.d.vue.ts +2 -2
- package/dist/runtime/components/ScriptYouTubePlayer.vue +11 -5
- package/dist/runtime/components/ScriptYouTubePlayer.vue.d.ts +2 -2
- package/dist/runtime/composables/useScript.js +11 -6
- package/dist/runtime/composables/useScriptEventPage.js +2 -2
- package/dist/runtime/composables/useScriptTriggerConsent.js +1 -1
- package/dist/runtime/composables/useScriptTriggerElement.js +1 -1
- package/dist/runtime/composables/useScriptTriggerIdleTimeout.js +1 -1
- package/dist/runtime/registry/clarity.d.ts +10 -15
- package/dist/runtime/registry/clarity.js +22 -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 +9 -39
- 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 +6 -25
- package/dist/runtime/registry/fathom-analytics.js +2 -24
- package/dist/runtime/registry/google-adsense.d.ts +2 -10
- package/dist/runtime/registry/google-adsense.js +2 -11
- package/dist/runtime/registry/google-analytics.d.ts +3 -5
- package/dist/runtime/registry/google-analytics.js +3 -8
- 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 +3 -28
- package/dist/runtime/registry/google-tag-manager.js +4 -27
- package/dist/runtime/registry/gravatar.d.ts +25 -0
- package/dist/runtime/registry/gravatar.js +32 -0
- package/dist/runtime/registry/hotjar.d.ts +3 -5
- package/dist/runtime/registry/hotjar.js +2 -5
- package/dist/runtime/registry/instagram-embed.d.ts +2 -17
- package/dist/runtime/registry/instagram-embed.js +4 -19
- package/dist/runtime/registry/intercom.d.ts +3 -11
- package/dist/runtime/registry/intercom.js +2 -12
- package/dist/runtime/registry/matomo-analytics.d.ts +2 -11
- package/dist/runtime/registry/matomo-analytics.js +3 -12
- package/dist/runtime/registry/meta-pixel.d.ts +3 -5
- package/dist/runtime/registry/meta-pixel.js +2 -4
- package/dist/runtime/registry/npm.d.ts +2 -6
- 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 +18 -13
- package/dist/runtime/registry/posthog.d.ts +10 -11
- package/dist/runtime/registry/posthog.js +7 -20
- package/dist/runtime/registry/reddit-pixel.d.ts +4 -5
- 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 +7 -19
- package/dist/runtime/registry/schemas.d.ts +946 -0
- package/dist/runtime/registry/schemas.js +901 -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 +3 -32
- 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 +3 -6
- package/dist/runtime/registry/tiktok-pixel.js +2 -6
- 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 +2 -16
- package/dist/runtime/registry/x-embed.js +2 -17
- package/dist/runtime/registry/x-pixel.d.ts +3 -6
- 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/google-static-maps-proxy.js +1 -1
- package/dist/runtime/server/{sw-handler.d.ts → gravatar-proxy.d.ts} +1 -1
- package/dist/runtime/server/gravatar-proxy.js +62 -0
- package/dist/runtime/server/instagram-embed-asset.js +2 -1
- package/dist/runtime/server/instagram-embed-image.js +2 -1
- package/dist/runtime/server/instagram-embed.js +22 -13
- package/dist/runtime/server/proxy-handler.js +161 -117
- package/dist/runtime/server/utils/privacy.d.ts +45 -1
- package/dist/runtime/server/utils/privacy.js +103 -40
- package/dist/runtime/server/x-embed.js +3 -2
- package/dist/runtime/types.d.ts +30 -24
- package/dist/runtime/utils/pure.d.ts +0 -4
- package/dist/runtime/utils/pure.js +0 -67
- package/dist/runtime/utils.d.ts +3 -3
- package/dist/runtime/utils.js +12 -7
- package/dist/shared/scripts.Crpn87WB.mjs +318 -0
- package/dist/stats.d.mts +39 -0
- package/dist/stats.d.ts +39 -0
- package/dist/stats.mjs +772 -0
- package/dist/types-source.d.mts +19 -0
- package/dist/types-source.d.ts +19 -0
- package/dist/types-source.mjs +975 -0
- package/package.json +42 -31
- package/dist/client/_nuxt/B8XOar-X.js +0 -162
- package/dist/client/_nuxt/builds/meta/133a46c5-a5c1-4a63-87d1-037947a5bcdb.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/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/plugins/sw-register.client.d.ts +0 -2
- package/dist/runtime/plugins/sw-register.client.js +0 -12
- package/dist/runtime/server/sw-handler.js +0 -25
- package/dist/runtime/sw/proxy-sw.template.d.ts +0 -1
- package/dist/runtime/sw/proxy-sw.template.js +0 -54
package/dist/module.mjs
CHANGED
|
@@ -1,79 +1,36 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { useNuxt, addDevServerHandler, extendRouteRules, tryUseNuxt, extendViteConfig, useLogger, addPluginTemplate, addServerHandler, logger as logger$1, addTypeTemplate, defineNuxtModule, createResolver, hasNuxtModule, addImports, addComponentsDir, addTemplate, addBuildPlugin } from '@nuxt/kit';
|
|
3
3
|
import { defu } from 'defu';
|
|
4
|
+
import { join, resolve, relative } from 'pathe';
|
|
4
5
|
import { resolvePackageJSON, readPackageJSON } from 'pkg-types';
|
|
6
|
+
import { lazyEventHandler, eventHandler, createError } from 'h3';
|
|
7
|
+
import { fetch, $fetch } from 'ofetch';
|
|
8
|
+
import { joinURL, parseURL, parseQuery, hasProtocol } from 'ufo';
|
|
9
|
+
import { createStorage } from 'unstorage';
|
|
10
|
+
import fsDriver from 'unstorage/drivers/fs-lite';
|
|
5
11
|
import { addCustomTab } from '@nuxt/devtools-kit';
|
|
12
|
+
import { isCI, provider } from 'std-env';
|
|
13
|
+
import { parseAndWalk, ScopeTracker, walk, ScopeTrackerFunctionParam, ScopeTrackerVariable } from 'oxc-walker';
|
|
14
|
+
import { createUnplugin } from 'unplugin';
|
|
15
|
+
import { pathToFileURL } from 'node:url';
|
|
6
16
|
import { createHash } from 'node:crypto';
|
|
7
17
|
import fsp from 'node:fs/promises';
|
|
8
|
-
import {
|
|
18
|
+
import { colors } from 'consola/utils';
|
|
9
19
|
import MagicString from 'magic-string';
|
|
10
|
-
import { parseAndWalk } from 'oxc-walker';
|
|
11
|
-
import { joinURL, parseURL, parseQuery, hasProtocol } from 'ufo';
|
|
12
20
|
import { hash } from 'ohash';
|
|
13
|
-
import {
|
|
14
|
-
import { colors } from 'consola/utils';
|
|
15
|
-
import { fetch, $fetch } from 'ofetch';
|
|
16
|
-
import { lazyEventHandler, eventHandler, createError } from 'h3';
|
|
17
|
-
import { createStorage } from 'unstorage';
|
|
18
|
-
import fsDriver from 'unstorage/drivers/fs-lite';
|
|
19
|
-
import { rewriteScriptUrls } from '../dist/runtime/utils/pure.js';
|
|
20
|
-
import { pathToFileURL } from 'node:url';
|
|
21
|
-
import { isCI, provider } from 'std-env';
|
|
21
|
+
import { g as getAllProxyConfigs, r as routesToInterceptRules, a as getProxyConfig } from './shared/scripts.Crpn87WB.mjs';
|
|
22
22
|
import { registry } from './registry.mjs';
|
|
23
23
|
|
|
24
|
-
const DEVTOOLS_UI_ROUTE = "/__nuxt-scripts";
|
|
25
|
-
const DEVTOOLS_UI_LOCAL_PORT = 3300;
|
|
26
|
-
|
|
27
|
-
async function setupDevToolsUI(options, resolve, nuxt = useNuxt()) {
|
|
28
|
-
const clientPath = await resolve("./client");
|
|
29
|
-
const isProductionBuild = existsSync(clientPath);
|
|
30
|
-
if (isProductionBuild) {
|
|
31
|
-
nuxt.hook("vite:serverCreated", async (server) => {
|
|
32
|
-
const sirv = await import('sirv').then((r) => r.default || r);
|
|
33
|
-
server.middlewares.use(
|
|
34
|
-
DEVTOOLS_UI_ROUTE,
|
|
35
|
-
sirv(clientPath, { dev: true, single: true })
|
|
36
|
-
);
|
|
37
|
-
});
|
|
38
|
-
} else {
|
|
39
|
-
extendViteConfig((config) => {
|
|
40
|
-
config.server = config.server || {};
|
|
41
|
-
config.server.proxy = config.server.proxy || {};
|
|
42
|
-
config.server.proxy[DEVTOOLS_UI_ROUTE] = {
|
|
43
|
-
target: `http://localhost:${DEVTOOLS_UI_LOCAL_PORT}${DEVTOOLS_UI_ROUTE}`,
|
|
44
|
-
changeOrigin: true,
|
|
45
|
-
followRedirects: true,
|
|
46
|
-
rewrite: (path) => path.replace(DEVTOOLS_UI_ROUTE, "")
|
|
47
|
-
};
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
addCustomTab({
|
|
51
|
-
// unique identifier
|
|
52
|
-
name: "nuxt-scripts",
|
|
53
|
-
// title to display in the tab
|
|
54
|
-
title: "Scripts",
|
|
55
|
-
// any icon from Iconify, or a URL to an image
|
|
56
|
-
icon: "carbon:script",
|
|
57
|
-
// iframe view
|
|
58
|
-
view: {
|
|
59
|
-
type: "iframe",
|
|
60
|
-
src: DEVTOOLS_UI_ROUTE
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const logger = useLogger("@nuxt/scripts");
|
|
66
|
-
|
|
67
24
|
const renderedScript = /* @__PURE__ */ new Map();
|
|
68
25
|
const ONE_YEAR_IN_SECONDS = 60 * 60 * 24 * 365;
|
|
69
|
-
|
|
26
|
+
function bundleStorage() {
|
|
70
27
|
const nuxt = tryUseNuxt();
|
|
71
28
|
return createStorage({
|
|
72
29
|
driver: fsDriver({
|
|
73
30
|
base: resolve(nuxt?.options.rootDir || "", "node_modules/.cache/nuxt/scripts")
|
|
74
31
|
})
|
|
75
32
|
});
|
|
76
|
-
}
|
|
33
|
+
}
|
|
77
34
|
function setupPublicAssetStrategy(options = {}) {
|
|
78
35
|
const assetsBaseURL = options.prefix || "/_scripts";
|
|
79
36
|
const nuxt = useNuxt();
|
|
@@ -123,179 +80,291 @@ function setupPublicAssetStrategy(options = {}) {
|
|
|
123
80
|
};
|
|
124
81
|
}
|
|
125
82
|
|
|
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
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
83
|
+
const DEVTOOLS_UI_ROUTE = "/__nuxt-scripts";
|
|
84
|
+
const DEVTOOLS_UI_LOCAL_PORT = 3300;
|
|
85
|
+
|
|
86
|
+
async function setupDevToolsUI(options, resolve, nuxt = useNuxt()) {
|
|
87
|
+
const clientPath = await resolve("./client");
|
|
88
|
+
const isProductionBuild = existsSync(clientPath);
|
|
89
|
+
if (isProductionBuild) {
|
|
90
|
+
nuxt.hook("vite:serverCreated", async (server) => {
|
|
91
|
+
const sirv = await import('sirv').then((r) => r.default || r);
|
|
92
|
+
server.middlewares.use(
|
|
93
|
+
DEVTOOLS_UI_ROUTE,
|
|
94
|
+
sirv(clientPath, { dev: true, single: true })
|
|
95
|
+
);
|
|
96
|
+
});
|
|
97
|
+
} else {
|
|
98
|
+
extendViteConfig((config) => {
|
|
99
|
+
config.server = config.server || {};
|
|
100
|
+
config.server.proxy = config.server.proxy || {};
|
|
101
|
+
config.server.proxy[DEVTOOLS_UI_ROUTE] = {
|
|
102
|
+
target: `http://localhost:${DEVTOOLS_UI_LOCAL_PORT}${DEVTOOLS_UI_ROUTE}`,
|
|
103
|
+
changeOrigin: true,
|
|
104
|
+
followRedirects: true,
|
|
105
|
+
rewrite: (path) => path.replace(DEVTOOLS_UI_ROUTE, "")
|
|
106
|
+
};
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
addCustomTab({
|
|
110
|
+
// unique identifier
|
|
111
|
+
name: "nuxt-scripts",
|
|
112
|
+
// title to display in the tab
|
|
113
|
+
title: "Scripts",
|
|
114
|
+
// any icon from Iconify, or a URL to an image
|
|
115
|
+
icon: "carbon:script",
|
|
116
|
+
// iframe view
|
|
117
|
+
view: {
|
|
118
|
+
type: "iframe",
|
|
119
|
+
src: DEVTOOLS_UI_ROUTE
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const logger = useLogger("@nuxt/scripts");
|
|
125
|
+
|
|
126
|
+
const AUTO_INJECT_DEFS = [
|
|
127
|
+
{
|
|
128
|
+
registryKey: "posthog",
|
|
129
|
+
configField: "apiHost",
|
|
130
|
+
computeValue: (collectPrefix, config) => {
|
|
131
|
+
const region = config.region || "us";
|
|
132
|
+
return region === "eu" ? `${collectPrefix}/ph-eu` : `${collectPrefix}/ph`;
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
registryKey: "plausibleAnalytics",
|
|
137
|
+
configField: "endpoint",
|
|
138
|
+
computeValue: (collectPrefix) => `${collectPrefix}/plausible/api/event`
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
registryKey: "umamiAnalytics",
|
|
142
|
+
configField: "hostUrl",
|
|
143
|
+
computeValue: (collectPrefix) => `${collectPrefix}/umami`
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
registryKey: "rybbitAnalytics",
|
|
147
|
+
configField: "analyticsHost",
|
|
148
|
+
computeValue: (collectPrefix) => `${collectPrefix}/rybbit/api`
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
registryKey: "databuddyAnalytics",
|
|
152
|
+
configField: "apiUrl",
|
|
153
|
+
computeValue: (collectPrefix) => `${collectPrefix}/databuddy-api`
|
|
154
|
+
}
|
|
155
|
+
];
|
|
156
|
+
function autoInjectProxyEndpoints(registry, runtimeConfig, collectPrefix) {
|
|
157
|
+
for (const def of AUTO_INJECT_DEFS) {
|
|
158
|
+
const entry = registry[def.registryKey];
|
|
159
|
+
if (!entry || typeof entry !== "object")
|
|
160
|
+
continue;
|
|
161
|
+
const config = Array.isArray(entry) ? entry[0] : entry;
|
|
162
|
+
if (!config || config[def.configField])
|
|
163
|
+
continue;
|
|
164
|
+
config[def.configField] = def.computeValue(collectPrefix, config);
|
|
165
|
+
const rtScripts = runtimeConfig.public?.scripts;
|
|
166
|
+
const rtEntry = rtScripts?.[def.registryKey];
|
|
167
|
+
if (rtEntry && typeof rtEntry === "object") {
|
|
168
|
+
const rtConfig = Array.isArray(rtEntry) ? rtEntry[0] : rtEntry;
|
|
169
|
+
if (rtConfig)
|
|
170
|
+
rtConfig[def.configField] = config[def.configField];
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function generateInterceptPluginContents(interceptRules) {
|
|
176
|
+
const rulesJson = JSON.stringify(interceptRules);
|
|
177
|
+
return `export default defineNuxtPlugin({
|
|
178
|
+
name: 'nuxt-scripts:intercept',
|
|
179
|
+
enforce: 'pre',
|
|
180
|
+
setup() {
|
|
181
|
+
const rules = ${rulesJson};
|
|
182
|
+
const origBeacon = typeof navigator !== 'undefined' && navigator.sendBeacon
|
|
183
|
+
? navigator.sendBeacon.bind(navigator)
|
|
184
|
+
: () => false;
|
|
185
|
+
const origFetch = globalThis.fetch.bind(globalThis);
|
|
186
|
+
|
|
187
|
+
function rewriteUrl(url) {
|
|
188
|
+
try {
|
|
189
|
+
const parsed = new URL(url, location.origin);
|
|
190
|
+
for (const rule of rules) {
|
|
191
|
+
if (parsed.hostname === rule.pattern || parsed.hostname.endsWith('.' + rule.pattern)) {
|
|
192
|
+
if (rule.pathPrefix && !parsed.pathname.startsWith(rule.pathPrefix)) continue;
|
|
193
|
+
const path = rule.pathPrefix ? parsed.pathname.slice(rule.pathPrefix.length) : parsed.pathname;
|
|
194
|
+
return location.origin + rule.target + (path.startsWith('/') ? '' : '/') + path + parsed.search;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
} catch {}
|
|
198
|
+
return url;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// XMLHttpRequest wrapper \u2014 intercepts .open() to rewrite URL
|
|
202
|
+
const OrigXHR = XMLHttpRequest;
|
|
203
|
+
class ProxiedXHR extends OrigXHR {
|
|
204
|
+
open() {
|
|
205
|
+
const args = Array.from(arguments);
|
|
206
|
+
if (typeof args[1] === 'string') args[1] = rewriteUrl(args[1]);
|
|
207
|
+
return super.open.apply(this, args);
|
|
244
208
|
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
// Metrics/telemetry
|
|
259
|
-
{ from: "metrics.hotjar.io", to: `${collectPrefix}/hotjar-metrics` },
|
|
260
|
-
// Insights (ContentSquare integration)
|
|
261
|
-
{ from: "insights.hotjar.com", to: `${collectPrefix}/hotjar-insights` }
|
|
262
|
-
],
|
|
263
|
-
routes: {
|
|
264
|
-
[`${collectPrefix}/hotjar/**`]: { proxy: "https://static.hotjar.com/**" },
|
|
265
|
-
[`${collectPrefix}/hotjar-script/**`]: { proxy: "https://script.hotjar.com/**" },
|
|
266
|
-
[`${collectPrefix}/hotjar-vars/**`]: { proxy: "https://vars.hotjar.com/**" },
|
|
267
|
-
[`${collectPrefix}/hotjar-in/**`]: { proxy: "https://in.hotjar.com/**" },
|
|
268
|
-
[`${collectPrefix}/hotjar-vc/**`]: { proxy: "https://vc.hotjar.com/**" },
|
|
269
|
-
[`${collectPrefix}/hotjar-metrics/**`]: { proxy: "https://metrics.hotjar.io/**" },
|
|
270
|
-
[`${collectPrefix}/hotjar-insights/**`]: { proxy: "https://insights.hotjar.com/**" }
|
|
209
|
+
}
|
|
210
|
+
// Image wrapper \u2014 intercepts .src setter to rewrite URL
|
|
211
|
+
const OrigImage = Image;
|
|
212
|
+
const origSrcDesc = Object.getOwnPropertyDescriptor(HTMLImageElement.prototype, 'src');
|
|
213
|
+
function ProxiedImage(w, h) {
|
|
214
|
+
const img = arguments.length === 2 ? new OrigImage(w, h)
|
|
215
|
+
: arguments.length === 1 ? new OrigImage(w) : new OrigImage();
|
|
216
|
+
if (origSrcDesc && origSrcDesc.set) {
|
|
217
|
+
Object.defineProperty(img, 'src', {
|
|
218
|
+
get() { return origSrcDesc.get.call(this); },
|
|
219
|
+
set(v) { origSrcDesc.set.call(this, typeof v === 'string' ? rewriteUrl(v) : v); },
|
|
220
|
+
configurable: true,
|
|
221
|
+
});
|
|
271
222
|
}
|
|
223
|
+
return img;
|
|
272
224
|
}
|
|
273
|
-
|
|
225
|
+
|
|
226
|
+
globalThis.__nuxtScripts = {
|
|
227
|
+
sendBeacon: (url, data) => origBeacon(rewriteUrl(url), data),
|
|
228
|
+
fetch: (url, opts) => origFetch(typeof url === 'string' ? rewriteUrl(url) : url, opts),
|
|
229
|
+
XMLHttpRequest: ProxiedXHR,
|
|
230
|
+
Image: ProxiedImage,
|
|
231
|
+
};
|
|
232
|
+
},
|
|
233
|
+
})
|
|
234
|
+
`;
|
|
274
235
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
236
|
+
|
|
237
|
+
function resolveFirstPartyConfig(config) {
|
|
238
|
+
const enabled = !!config.firstParty;
|
|
239
|
+
const prefix = typeof config.firstParty === "object" ? config.firstParty.prefix : void 0;
|
|
240
|
+
const collectPrefix = typeof config.firstParty === "object" ? config.firstParty.collectPrefix || "/_proxy" : "/_proxy";
|
|
241
|
+
const privacy = typeof config.firstParty === "object" ? config.firstParty.privacy : void 0;
|
|
242
|
+
const assetsPrefix = prefix || config.assets?.prefix || "/_scripts";
|
|
243
|
+
return { enabled, prefix, collectPrefix, privacy, assetsPrefix };
|
|
278
244
|
}
|
|
279
|
-
function
|
|
280
|
-
|
|
245
|
+
async function setupFirstPartyHandlers(firstParty, resolvePath) {
|
|
246
|
+
const interceptRules = [];
|
|
247
|
+
addPluginTemplate({
|
|
248
|
+
filename: "nuxt-scripts-intercept.client.mjs",
|
|
249
|
+
getContents() {
|
|
250
|
+
return generateInterceptPluginContents(interceptRules);
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
const proxyHandlerPath = await resolvePath("./runtime/server/proxy-handler");
|
|
254
|
+
logger.debug("[nuxt-scripts] Registering proxy handler:", `${firstParty.collectPrefix}/**`, "->", proxyHandlerPath);
|
|
255
|
+
addServerHandler({
|
|
256
|
+
route: `${firstParty.collectPrefix}/**`,
|
|
257
|
+
handler: proxyHandlerPath
|
|
258
|
+
});
|
|
259
|
+
return interceptRules;
|
|
281
260
|
}
|
|
282
|
-
function
|
|
283
|
-
const
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
261
|
+
function finalizeFirstParty(opts) {
|
|
262
|
+
const { firstParty, interceptRules, registryScriptsWithImport, nuxtOptions } = opts;
|
|
263
|
+
const proxyConfigs = getAllProxyConfigs(firstParty.collectPrefix);
|
|
264
|
+
const registryKeys = Object.keys(opts.registry || {});
|
|
265
|
+
const neededRoutes = {};
|
|
266
|
+
const routePrivacyOverrides = {};
|
|
267
|
+
const unsupportedScripts = [];
|
|
268
|
+
for (const key of registryKeys) {
|
|
269
|
+
const script = registryScriptsWithImport.find((s) => s.import.name.toLowerCase() === `usescript${key.toLowerCase()}`);
|
|
270
|
+
const proxyKey = script?.proxy || void 0;
|
|
271
|
+
if (proxyKey) {
|
|
272
|
+
const proxyConfig = proxyConfigs[proxyKey];
|
|
273
|
+
if (proxyConfig?.routes) {
|
|
274
|
+
Object.assign(neededRoutes, proxyConfig.routes);
|
|
275
|
+
for (const routePath of Object.keys(proxyConfig.routes)) {
|
|
276
|
+
routePrivacyOverrides[routePath] = proxyConfig.privacy;
|
|
277
|
+
}
|
|
278
|
+
} else {
|
|
279
|
+
unsupportedScripts.push(key);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
if (opts.registry) {
|
|
284
|
+
autoInjectProxyEndpoints(opts.registry, nuxtOptions.runtimeConfig, firstParty.collectPrefix);
|
|
285
|
+
}
|
|
286
|
+
if (unsupportedScripts.length && nuxtOptions.dev) {
|
|
287
|
+
logger.warn(
|
|
288
|
+
`First-party mode is enabled but these scripts don't support it yet: ${unsupportedScripts.join(", ")}.
|
|
289
|
+
They will load directly from third-party servers. Request support at https://github.com/nuxt/scripts/issues`
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
interceptRules.push(...routesToInterceptRules(neededRoutes));
|
|
293
|
+
const flatRoutes = {};
|
|
294
|
+
for (const [path, config] of Object.entries(neededRoutes)) {
|
|
295
|
+
flatRoutes[path] = config.proxy;
|
|
296
|
+
}
|
|
297
|
+
nuxtOptions.runtimeConfig["nuxt-scripts-proxy"] = {
|
|
298
|
+
routes: flatRoutes,
|
|
299
|
+
privacy: firstParty.privacy,
|
|
300
|
+
routePrivacy: routePrivacyOverrides
|
|
301
|
+
};
|
|
302
|
+
if (Object.keys(neededRoutes).length && nuxtOptions.dev) {
|
|
303
|
+
const routeCount = Object.keys(neededRoutes).length;
|
|
304
|
+
const scriptsCount = registryKeys.length;
|
|
305
|
+
const privacyLabel = firstParty.privacy === void 0 ? "per-script" : typeof firstParty.privacy === "boolean" ? firstParty.privacy ? "anonymize" : "passthrough" : "custom";
|
|
306
|
+
logger.success(`First-party mode enabled for ${scriptsCount} script(s), ${routeCount} proxy route(s) configured (privacy: ${privacyLabel})`);
|
|
307
|
+
if (logger.level >= 4) {
|
|
308
|
+
for (const [path, config] of Object.entries(neededRoutes)) {
|
|
309
|
+
logger.debug(` ${path} \u2192 ${config.proxy}`);
|
|
295
310
|
}
|
|
296
311
|
}
|
|
297
312
|
}
|
|
298
|
-
|
|
313
|
+
const staticPresets = ["static", "github-pages", "cloudflare-pages-static"];
|
|
314
|
+
const preset = process.env.NITRO_PRESET || "";
|
|
315
|
+
if (staticPresets.includes(preset)) {
|
|
316
|
+
logger.warn(
|
|
317
|
+
`First-party collection endpoints require a server runtime (detected: ${preset || "static"}).
|
|
318
|
+
Scripts will be bundled, but collection requests will not be proxied.
|
|
319
|
+
|
|
320
|
+
Options:
|
|
321
|
+
1. Configure platform rewrites (Vercel, Netlify, Cloudflare)
|
|
322
|
+
2. Switch to server-rendered mode (ssr: true)
|
|
323
|
+
3. Disable with firstParty: false
|
|
324
|
+
|
|
325
|
+
See: https://scripts.nuxt.com/docs/guides/first-party#static-hosting`
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
const isStackblitz = provider === "stackblitz";
|
|
331
|
+
async function promptToInstall(name, installCommand, options) {
|
|
332
|
+
if (await resolvePackageJSON(name).catch(() => null))
|
|
333
|
+
return true;
|
|
334
|
+
logger$1.info(`Package ${name} is missing`);
|
|
335
|
+
if (isCI)
|
|
336
|
+
return false;
|
|
337
|
+
if (options.prompt === true || options.prompt !== false && !isStackblitz) {
|
|
338
|
+
const confirm = await logger$1.prompt(`Do you want to install ${name} package?`, {
|
|
339
|
+
type: "confirm",
|
|
340
|
+
name: "confirm",
|
|
341
|
+
initial: true
|
|
342
|
+
});
|
|
343
|
+
if (!confirm)
|
|
344
|
+
return false;
|
|
345
|
+
}
|
|
346
|
+
logger$1.info(`Installing ${name}...`);
|
|
347
|
+
try {
|
|
348
|
+
await installCommand();
|
|
349
|
+
logger$1.success(`Installed ${name}`);
|
|
350
|
+
return true;
|
|
351
|
+
} catch (err) {
|
|
352
|
+
logger$1.error(err);
|
|
353
|
+
return false;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
const installPrompts = /* @__PURE__ */ new Set();
|
|
357
|
+
function installNuxtModule(name, options) {
|
|
358
|
+
if (installPrompts.has(name))
|
|
359
|
+
return;
|
|
360
|
+
installPrompts.add(name);
|
|
361
|
+
const nuxt = tryUseNuxt();
|
|
362
|
+
if (!nuxt)
|
|
363
|
+
return;
|
|
364
|
+
return promptToInstall(name, async () => {
|
|
365
|
+
const { runCommand } = await import(String("nuxi"));
|
|
366
|
+
await runCommand("module", ["add", name, "--cwd", nuxt.options.rootDir]);
|
|
367
|
+
}, { rootDir: nuxt.options.rootDir, searchPaths: nuxt.options.modulesDir, ...options });
|
|
299
368
|
}
|
|
300
369
|
|
|
301
370
|
function isVue(id, opts = {}) {
|
|
@@ -319,13 +388,301 @@ function isVue(id, opts = {}) {
|
|
|
319
388
|
}
|
|
320
389
|
return true;
|
|
321
390
|
}
|
|
322
|
-
const JS_RE = /\.(?:[cm]?j|t)sx?$/;
|
|
391
|
+
const JS_RE$1 = /\.(?:[cm]?j|t)sx?$/;
|
|
323
392
|
function isJS(id) {
|
|
324
393
|
const { pathname } = parseURL(decodeURIComponent(pathToFileURL(id).href));
|
|
325
|
-
return JS_RE.test(pathname);
|
|
394
|
+
return JS_RE$1.test(pathname);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
const VUE_RE$1 = /\.vue/;
|
|
398
|
+
function NuxtScriptsCheckScripts() {
|
|
399
|
+
return createUnplugin(() => {
|
|
400
|
+
return {
|
|
401
|
+
name: "nuxt-scripts:check-scripts",
|
|
402
|
+
transform: {
|
|
403
|
+
filter: {
|
|
404
|
+
id: VUE_RE$1
|
|
405
|
+
},
|
|
406
|
+
handler(code, id) {
|
|
407
|
+
if (!isVue(id, { type: ["script"] }))
|
|
408
|
+
return;
|
|
409
|
+
if (!code.includes("useScript"))
|
|
410
|
+
return;
|
|
411
|
+
let nameNode;
|
|
412
|
+
let errorNode;
|
|
413
|
+
parseAndWalk(code, id, (_node) => {
|
|
414
|
+
if (_node.type === "VariableDeclaration" && _node.declarations?.[0]?.id?.type === "ObjectPattern") {
|
|
415
|
+
const objPattern = _node.declarations[0]?.id;
|
|
416
|
+
for (const property of objPattern.properties) {
|
|
417
|
+
if (property.type === "Property" && property.key.type === "Identifier" && property.key.name === "$script" && property.value.type === "Identifier") {
|
|
418
|
+
nameNode = _node;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
if (nameNode) {
|
|
423
|
+
let sequence = _node.type === "SequenceExpression" ? _node : null;
|
|
424
|
+
let assignmentExpression;
|
|
425
|
+
if (_node.type === "VariableDeclaration") {
|
|
426
|
+
if (_node.declarations[0]?.init?.type === "SequenceExpression") {
|
|
427
|
+
sequence = _node.declarations[0]?.init;
|
|
428
|
+
assignmentExpression = _node.declarations[0]?.init?.expressions?.[0];
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
if (sequence && !assignmentExpression) {
|
|
432
|
+
assignmentExpression = sequence.expressions[0]?.type === "AssignmentExpression" ? sequence.expressions[0] : null;
|
|
433
|
+
}
|
|
434
|
+
if (assignmentExpression) {
|
|
435
|
+
const right = assignmentExpression?.right;
|
|
436
|
+
if (right.callee?.name === "_withAsyncContext") {
|
|
437
|
+
if (right.arguments[0]?.body?.name === "$script" || right.arguments[0]?.body?.callee?.object?.name === "$script") {
|
|
438
|
+
errorNode = nameNode;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
if (errorNode) {
|
|
445
|
+
return this.error(new Error("You can't use a top-level await on $script as it will never resolve."));
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
};
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
const WORD_OR_DOLLAR_RE = /[\w$]/;
|
|
454
|
+
const GA_COLLECT_RE = /([\w$])?"https:\/\/"\+\(.*?\)\+"\.google-analytics\.com\/g\/collect"/g;
|
|
455
|
+
const GA_ANALYTICS_COLLECT_RE = /([\w$])?"https:\/\/"\+\(.*?\)\+"\.analytics\.google\.com\/g\/collect"/g;
|
|
456
|
+
const FATHOM_SELF_HOSTED_RE = /\.src\.indexOf\("cdn\.usefathom\.com"\)\s*<\s*0/;
|
|
457
|
+
function isPropertyKeyAST(parent, ctx) {
|
|
458
|
+
return parent?.type === "Property" && ctx.key === "key" || parent?.type === "SwitchCase" && ctx.key === "test";
|
|
459
|
+
}
|
|
460
|
+
function matchAndRewrite(value, rewrites) {
|
|
461
|
+
for (const { from, to } of rewrites) {
|
|
462
|
+
const isSuffixMatch = from.startsWith(".");
|
|
463
|
+
const fromSlashIdx = from.indexOf("/");
|
|
464
|
+
const fromHost = fromSlashIdx > 0 ? from.slice(0, fromSlashIdx) : from;
|
|
465
|
+
const fromPath = fromSlashIdx > 0 ? from.slice(fromSlashIdx) : "";
|
|
466
|
+
if (!value.includes(fromHost))
|
|
467
|
+
continue;
|
|
468
|
+
const url = parseURL(value);
|
|
469
|
+
let shouldRewrite = false;
|
|
470
|
+
let rewriteSuffix = "";
|
|
471
|
+
if (url.host) {
|
|
472
|
+
const hostMatches = isSuffixMatch ? url.host.endsWith(fromHost) : url.host === fromHost;
|
|
473
|
+
if (hostMatches) {
|
|
474
|
+
const fullPath = url.pathname + (url.search || "") + (url.hash || "");
|
|
475
|
+
if (fromPath && fullPath.startsWith(fromPath)) {
|
|
476
|
+
shouldRewrite = true;
|
|
477
|
+
rewriteSuffix = fullPath.slice(fromPath.length);
|
|
478
|
+
} else if (!fromPath) {
|
|
479
|
+
shouldRewrite = true;
|
|
480
|
+
rewriteSuffix = fullPath;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
} else if (value.startsWith("//")) {
|
|
484
|
+
const hostPart = value.slice(2).split("/")[0];
|
|
485
|
+
const hostMatches = isSuffixMatch ? hostPart?.endsWith(fromHost) ?? false : hostPart === fromHost;
|
|
486
|
+
if (hostMatches) {
|
|
487
|
+
const remainder = value.slice(2 + (hostPart?.length ?? 0));
|
|
488
|
+
if (fromPath && remainder.startsWith(fromPath)) {
|
|
489
|
+
shouldRewrite = true;
|
|
490
|
+
rewriteSuffix = remainder.slice(fromPath.length);
|
|
491
|
+
} else if (!fromPath) {
|
|
492
|
+
shouldRewrite = true;
|
|
493
|
+
rewriteSuffix = remainder;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
} else if (fromPath && (value.startsWith(from) || isSuffixMatch && value.includes(from))) {
|
|
497
|
+
const domainEnd = value.indexOf(from) + from.length;
|
|
498
|
+
const nextChar = value[domainEnd];
|
|
499
|
+
if (!nextChar || nextChar === "/" || nextChar === "?" || nextChar === "#") {
|
|
500
|
+
shouldRewrite = true;
|
|
501
|
+
rewriteSuffix = value.slice(domainEnd);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
if (shouldRewrite) {
|
|
505
|
+
return rewriteSuffix === "/" || rewriteSuffix.startsWith("?") || rewriteSuffix.startsWith("#") ? to + rewriteSuffix : joinURL(to, rewriteSuffix);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
return null;
|
|
509
|
+
}
|
|
510
|
+
const WINDOW_GLOBALS = /* @__PURE__ */ new Set(["window", "self", "globalThis"]);
|
|
511
|
+
const NAVIGATOR_GLOBALS = /* @__PURE__ */ new Set(["navigator"]);
|
|
512
|
+
function resolveToGlobal(name, scopeTracker, depth = 0) {
|
|
513
|
+
if (depth > 10)
|
|
514
|
+
return null;
|
|
515
|
+
const decl = scopeTracker.getDeclaration(name);
|
|
516
|
+
if (!decl)
|
|
517
|
+
return name;
|
|
518
|
+
if (decl instanceof ScopeTrackerFunctionParam)
|
|
519
|
+
return null;
|
|
520
|
+
if (decl instanceof ScopeTrackerVariable) {
|
|
521
|
+
const declarators = decl.variableNode.declarations;
|
|
522
|
+
if (!declarators)
|
|
523
|
+
return null;
|
|
524
|
+
for (const declarator of declarators) {
|
|
525
|
+
const id = declarator.id;
|
|
526
|
+
if (!id || id.name !== name)
|
|
527
|
+
continue;
|
|
528
|
+
const init = declarator.init;
|
|
529
|
+
if (!init)
|
|
530
|
+
return null;
|
|
531
|
+
if (init.type === "Identifier")
|
|
532
|
+
return resolveToGlobal(init.name, scopeTracker, depth + 1);
|
|
533
|
+
if (init.type === "MemberExpression" && !init.computed && init.object?.type === "Identifier" && init.property?.type === "Identifier") {
|
|
534
|
+
const objGlobal = resolveToGlobal(init.object.name, scopeTracker, depth + 1);
|
|
535
|
+
if (!objGlobal)
|
|
536
|
+
return null;
|
|
537
|
+
if (WINDOW_GLOBALS.has(objGlobal) || objGlobal === "document")
|
|
538
|
+
return init.property.name;
|
|
539
|
+
return null;
|
|
540
|
+
}
|
|
541
|
+
return null;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
return null;
|
|
545
|
+
}
|
|
546
|
+
function resolveCalleeTarget(callee, scopeTracker) {
|
|
547
|
+
if (callee?.type !== "MemberExpression")
|
|
548
|
+
return null;
|
|
549
|
+
const propName = callee.computed ? callee.property?.type === "Literal" && typeof callee.property.value === "string" ? callee.property.value : null : callee.property?.name;
|
|
550
|
+
if (!propName)
|
|
551
|
+
return null;
|
|
552
|
+
const obj = callee.object;
|
|
553
|
+
if (!obj || obj.type !== "Identifier")
|
|
554
|
+
return null;
|
|
555
|
+
const resolved = resolveToGlobal(obj.name, scopeTracker);
|
|
556
|
+
if (!resolved)
|
|
557
|
+
return null;
|
|
558
|
+
if (propName === "fetch" && WINDOW_GLOBALS.has(resolved))
|
|
559
|
+
return "fetch";
|
|
560
|
+
if (propName === "sendBeacon" && (NAVIGATOR_GLOBALS.has(resolved) || WINDOW_GLOBALS.has(resolved)))
|
|
561
|
+
return "sendBeacon";
|
|
562
|
+
if (propName === "sendBeacon" && resolved === "navigator")
|
|
563
|
+
return "sendBeacon";
|
|
564
|
+
if (propName === "XMLHttpRequest" && WINDOW_GLOBALS.has(resolved))
|
|
565
|
+
return "XMLHttpRequest";
|
|
566
|
+
if (propName === "Image" && WINDOW_GLOBALS.has(resolved))
|
|
567
|
+
return "Image";
|
|
568
|
+
return null;
|
|
569
|
+
}
|
|
570
|
+
function rewriteScriptUrlsAST(content, filename, rewrites) {
|
|
571
|
+
const s = new MagicString(content);
|
|
572
|
+
function needsLeadingSpace(start) {
|
|
573
|
+
const prev = content[start - 1];
|
|
574
|
+
return prev && WORD_OR_DOLLAR_RE.test(prev) ? " " : "";
|
|
575
|
+
}
|
|
576
|
+
const scopeTracker = new ScopeTracker({ preserveExitedScopes: true });
|
|
577
|
+
const { program } = parseAndWalk(content, filename, { scopeTracker });
|
|
578
|
+
scopeTracker.freeze();
|
|
579
|
+
walk(program, {
|
|
580
|
+
scopeTracker,
|
|
581
|
+
enter(node, parent, ctx) {
|
|
582
|
+
if (node.type === "Literal" && typeof node.value === "string") {
|
|
583
|
+
const value = node.value;
|
|
584
|
+
const rewritten = matchAndRewrite(value, rewrites);
|
|
585
|
+
if (rewritten === null)
|
|
586
|
+
return;
|
|
587
|
+
const quote = content[node.start];
|
|
588
|
+
if (isPropertyKeyAST(parent, ctx)) {
|
|
589
|
+
s.overwrite(node.start, node.end, quote + rewritten + quote);
|
|
590
|
+
} else {
|
|
591
|
+
s.overwrite(node.start, node.end, `${needsLeadingSpace(node.start)}self.location.origin+${quote}${rewritten}${quote}`);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
if (node.type === "TemplateLiteral" && node.expressions?.length === 0) {
|
|
595
|
+
const quasis = node.quasis;
|
|
596
|
+
if (quasis?.length === 1) {
|
|
597
|
+
const value = quasis[0].value?.cooked ?? quasis[0].value?.raw;
|
|
598
|
+
if (typeof value !== "string")
|
|
599
|
+
return;
|
|
600
|
+
const rewritten = matchAndRewrite(value, rewrites);
|
|
601
|
+
if (rewritten === null)
|
|
602
|
+
return;
|
|
603
|
+
if (isPropertyKeyAST(parent, ctx)) {
|
|
604
|
+
s.overwrite(node.start, node.end, `\`${rewritten}\``);
|
|
605
|
+
} else {
|
|
606
|
+
s.overwrite(node.start, node.end, `${needsLeadingSpace(node.start)}self.location.origin+\`${rewritten}\``);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
if (node.type === "CallExpression") {
|
|
611
|
+
const callee = node.callee;
|
|
612
|
+
if (callee?.type === "Identifier" && callee.name === "fetch") {
|
|
613
|
+
if (!scopeTracker.getDeclaration("fetch"))
|
|
614
|
+
s.overwrite(callee.start, callee.end, "__nuxtScripts.fetch");
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
const target = resolveCalleeTarget(callee, scopeTracker);
|
|
618
|
+
if (target === "fetch" || target === "sendBeacon") {
|
|
619
|
+
s.overwrite(callee.start, callee.end, `__nuxtScripts.${target}`);
|
|
620
|
+
return;
|
|
621
|
+
}
|
|
622
|
+
if (callee?.type === "MemberExpression" && !callee.computed && callee.property?.name === "sendBeacon" && callee.object?.type === "Identifier") {
|
|
623
|
+
const resolved = resolveToGlobal(callee.object.name, scopeTracker);
|
|
624
|
+
if (resolved === null) {
|
|
625
|
+
s.overwrite(callee.start, callee.end, "__nuxtScripts.sendBeacon");
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
if (node.type === "NewExpression") {
|
|
630
|
+
const callee = node.callee;
|
|
631
|
+
if (callee?.type === "Identifier" && callee.name === "XMLHttpRequest") {
|
|
632
|
+
if (!scopeTracker.getDeclaration("XMLHttpRequest"))
|
|
633
|
+
s.overwrite(callee.start, callee.end, "__nuxtScripts.XMLHttpRequest");
|
|
634
|
+
return;
|
|
635
|
+
}
|
|
636
|
+
if (callee?.type === "Identifier" && callee.name === "Image") {
|
|
637
|
+
if (!scopeTracker.getDeclaration("Image"))
|
|
638
|
+
s.overwrite(callee.start, callee.end, "__nuxtScripts.Image");
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
const target = resolveCalleeTarget(callee, scopeTracker);
|
|
642
|
+
if (target === "XMLHttpRequest" || target === "Image") {
|
|
643
|
+
s.overwrite(callee.start, callee.end, `__nuxtScripts.${target}`);
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
646
|
+
if (callee?.type === "MemberExpression" && callee.object?.type === "Identifier") {
|
|
647
|
+
const propName = callee.computed ? callee.property?.type === "Literal" && typeof callee.property.value === "string" ? callee.property.value : null : callee.property?.name;
|
|
648
|
+
if (propName === "XMLHttpRequest" || propName === "Image") {
|
|
649
|
+
const resolved = resolveToGlobal(callee.object.name, scopeTracker);
|
|
650
|
+
if (resolved === null) {
|
|
651
|
+
s.overwrite(callee.start, callee.end, `__nuxtScripts.${propName}`);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
});
|
|
658
|
+
let output = s.toString();
|
|
659
|
+
const gaRewrite = rewrites.find((r) => r.from.includes("google-analytics.com/g/collect"));
|
|
660
|
+
if (gaRewrite) {
|
|
661
|
+
output = output.replace(
|
|
662
|
+
GA_COLLECT_RE,
|
|
663
|
+
(_, prevChar) => `${prevChar ? `${prevChar} ` : ""}self.location.origin+"${gaRewrite.to}"`
|
|
664
|
+
);
|
|
665
|
+
output = output.replace(
|
|
666
|
+
GA_ANALYTICS_COLLECT_RE,
|
|
667
|
+
(_, prevChar) => `${prevChar ? `${prevChar} ` : ""}self.location.origin+"${gaRewrite.to}"`
|
|
668
|
+
);
|
|
669
|
+
}
|
|
670
|
+
if (rewrites.some((r) => r.from === "cdn.usefathom.com")) {
|
|
671
|
+
output = output.replace(
|
|
672
|
+
FATHOM_SELF_HOSTED_RE,
|
|
673
|
+
'.src.indexOf("cdn.usefathom.com")<-1'
|
|
674
|
+
);
|
|
675
|
+
}
|
|
676
|
+
return output;
|
|
326
677
|
}
|
|
327
678
|
|
|
328
679
|
const SEVEN_DAYS_IN_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
680
|
+
const PROTOCOL_RELATIVE_RE = /^\/\//;
|
|
681
|
+
const VUE_RE = /\.vue/;
|
|
682
|
+
const JS_RE = /\.[cm]?[jt]sx?$/;
|
|
683
|
+
const TEST_RE = /\.(?:test|spec)\./;
|
|
684
|
+
const UPPERCASE_RE = /^[A-Z]$/;
|
|
685
|
+
const USE_SCRIPT_RE = /^useScript/;
|
|
329
686
|
function calculateIntegrity(content, algorithm = "sha384") {
|
|
330
687
|
const hash = createHash(algorithm).update(content).digest("base64");
|
|
331
688
|
return `${algorithm}-${hash}`;
|
|
@@ -340,12 +697,10 @@ async function isCacheExpired(storage, filename, cacheMaxAge = SEVEN_DAYS_IN_MS)
|
|
|
340
697
|
}
|
|
341
698
|
function normalizeScriptData(src, assetsBaseURL = "/_scripts") {
|
|
342
699
|
if (hasProtocol(src, { acceptRelative: true })) {
|
|
343
|
-
src = src.replace(
|
|
700
|
+
src = src.replace(PROTOCOL_RELATIVE_RE, "https://");
|
|
344
701
|
const url = parseURL(src);
|
|
345
|
-
const
|
|
346
|
-
|
|
347
|
-
// force an extension
|
|
348
|
-
].filter(Boolean).join("-");
|
|
702
|
+
const h = hash(url);
|
|
703
|
+
const file = `${h.startsWith("-") ? `_${h.slice(1)}` : h}.js`;
|
|
349
704
|
const nuxt = tryUseNuxt();
|
|
350
705
|
const cdnURL = nuxt?.options.runtimeConfig?.app?.cdnURL || nuxt?.options.app?.cdnURL || "";
|
|
351
706
|
const baseURL = cdnURL || nuxt?.options.app.baseURL || "";
|
|
@@ -392,7 +747,7 @@ async function downloadScript(opts, renderedScript, fetchOptions, cacheMaxAge) {
|
|
|
392
747
|
await storage.setItemRaw(`bundle:${filename}`, res);
|
|
393
748
|
if (proxyRewrites?.length && res) {
|
|
394
749
|
const content = res.toString("utf-8");
|
|
395
|
-
const rewritten =
|
|
750
|
+
const rewritten = rewriteScriptUrlsAST(content, filename || "script.js", proxyRewrites);
|
|
396
751
|
res = Buffer.from(rewritten, "utf-8");
|
|
397
752
|
logger.debug(`Rewrote ${proxyRewrites.length} URL patterns in ${filename}`);
|
|
398
753
|
}
|
|
@@ -449,8 +804,8 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
449
804
|
transform: {
|
|
450
805
|
filter: {
|
|
451
806
|
id: {
|
|
452
|
-
include: [
|
|
453
|
-
exclude: [
|
|
807
|
+
include: [VUE_RE, JS_RE],
|
|
808
|
+
exclude: [TEST_RE]
|
|
454
809
|
}
|
|
455
810
|
},
|
|
456
811
|
async handler(code, id) {
|
|
@@ -460,11 +815,11 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
460
815
|
return;
|
|
461
816
|
const s = new MagicString(code);
|
|
462
817
|
const deferredOps = [];
|
|
463
|
-
parseAndWalk(code, id,
|
|
818
|
+
parseAndWalk(code, id, (_node) => {
|
|
464
819
|
const calleeName = _node.callee?.name;
|
|
465
820
|
if (!calleeName)
|
|
466
821
|
return;
|
|
467
|
-
const isValidCallee = calleeName === "useScript" || calleeName?.startsWith("useScript") &&
|
|
822
|
+
const isValidCallee = calleeName === "useScript" || calleeName?.startsWith("useScript") && UPPERCASE_RE.test(calleeName?.charAt(9)) && !calleeName.startsWith("useScriptTrigger") && !calleeName.startsWith("useScriptEvent");
|
|
468
823
|
if (_node.type === "CallExpression" && _node.callee.type === "Identifier" && isValidCallee) {
|
|
469
824
|
const fnName = _node.callee?.name;
|
|
470
825
|
const node = _node;
|
|
@@ -472,7 +827,7 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
472
827
|
let src;
|
|
473
828
|
let registryKey;
|
|
474
829
|
if (fnName !== "useScript") {
|
|
475
|
-
const baseName = fnName.replace(
|
|
830
|
+
const baseName = fnName.replace(USE_SCRIPT_RE, "");
|
|
476
831
|
registryKey = baseName.length > 0 ? baseName.charAt(0).toLowerCase() + baseName.slice(1) : void 0;
|
|
477
832
|
}
|
|
478
833
|
if (fnName === "useScript") {
|
|
@@ -652,7 +1007,7 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
652
1007
|
s.appendRight(node.arguments[0].start + 1, ` scriptInput: { src: '${url}'${integrityProps} }, `);
|
|
653
1008
|
}
|
|
654
1009
|
} else {
|
|
655
|
-
s.
|
|
1010
|
+
s.overwrite(node.callee.end, node.end, `({ scriptInput: { src: '${url}'${integrityProps} } })`);
|
|
656
1011
|
}
|
|
657
1012
|
}
|
|
658
1013
|
});
|
|
@@ -676,101 +1031,7 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
676
1031
|
});
|
|
677
1032
|
}
|
|
678
1033
|
|
|
679
|
-
const
|
|
680
|
-
async function promptToInstall(name, installCommand, options) {
|
|
681
|
-
if (await resolvePackageJSON(name).catch(() => null))
|
|
682
|
-
return true;
|
|
683
|
-
logger$1.info(`Package ${name} is missing`);
|
|
684
|
-
if (isCI)
|
|
685
|
-
return false;
|
|
686
|
-
if (options.prompt === true || options.prompt !== false && !isStackblitz) {
|
|
687
|
-
const confirm = await logger$1.prompt(`Do you want to install ${name} package?`, {
|
|
688
|
-
type: "confirm",
|
|
689
|
-
name: "confirm",
|
|
690
|
-
initial: true
|
|
691
|
-
});
|
|
692
|
-
if (!confirm)
|
|
693
|
-
return false;
|
|
694
|
-
}
|
|
695
|
-
logger$1.info(`Installing ${name}...`);
|
|
696
|
-
try {
|
|
697
|
-
await installCommand();
|
|
698
|
-
logger$1.success(`Installed ${name}`);
|
|
699
|
-
return true;
|
|
700
|
-
} catch (err) {
|
|
701
|
-
logger$1.error(err);
|
|
702
|
-
return false;
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
const installPrompts = /* @__PURE__ */ new Set();
|
|
706
|
-
function installNuxtModule(name, options) {
|
|
707
|
-
if (installPrompts.has(name))
|
|
708
|
-
return;
|
|
709
|
-
installPrompts.add(name);
|
|
710
|
-
const nuxt = tryUseNuxt();
|
|
711
|
-
if (!nuxt)
|
|
712
|
-
return;
|
|
713
|
-
return promptToInstall(name, async () => {
|
|
714
|
-
const { runCommand } = await import(String("nuxi"));
|
|
715
|
-
await runCommand("module", ["add", name, "--cwd", nuxt.options.rootDir]);
|
|
716
|
-
}, { rootDir: nuxt.options.rootDir, searchPaths: nuxt.options.modulesDir, ...options });
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
function NuxtScriptsCheckScripts() {
|
|
720
|
-
return createUnplugin(() => {
|
|
721
|
-
return {
|
|
722
|
-
name: "nuxt-scripts:check-scripts",
|
|
723
|
-
transform: {
|
|
724
|
-
filter: {
|
|
725
|
-
id: /\.vue/
|
|
726
|
-
},
|
|
727
|
-
handler(code, id) {
|
|
728
|
-
if (!isVue(id, { type: ["script"] }))
|
|
729
|
-
return;
|
|
730
|
-
if (!code.includes("useScript"))
|
|
731
|
-
return;
|
|
732
|
-
let nameNode;
|
|
733
|
-
let errorNode;
|
|
734
|
-
parseAndWalk(code, id, function(_node) {
|
|
735
|
-
if (_node.type === "VariableDeclaration" && _node.declarations?.[0]?.id?.type === "ObjectPattern") {
|
|
736
|
-
const objPattern = _node.declarations[0]?.id;
|
|
737
|
-
for (const property of objPattern.properties) {
|
|
738
|
-
if (property.type === "Property" && property.key.type === "Identifier" && property.key.name === "$script" && property.value.type === "Identifier") {
|
|
739
|
-
nameNode = _node;
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
}
|
|
743
|
-
if (nameNode) {
|
|
744
|
-
let sequence = _node.type === "SequenceExpression" ? _node : null;
|
|
745
|
-
let assignmentExpression;
|
|
746
|
-
if (_node.type === "VariableDeclaration") {
|
|
747
|
-
if (_node.declarations[0]?.init?.type === "SequenceExpression") {
|
|
748
|
-
sequence = _node.declarations[0]?.init;
|
|
749
|
-
assignmentExpression = _node.declarations[0]?.init?.expressions?.[0];
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
if (sequence && !assignmentExpression) {
|
|
753
|
-
assignmentExpression = sequence.expressions[0]?.type === "AssignmentExpression" ? sequence.expressions[0] : null;
|
|
754
|
-
}
|
|
755
|
-
if (assignmentExpression) {
|
|
756
|
-
const right = assignmentExpression?.right;
|
|
757
|
-
if (right.callee?.name === "_withAsyncContext") {
|
|
758
|
-
if (right.arguments[0]?.body?.name === "$script" || right.arguments[0]?.body?.callee?.object?.name === "$script") {
|
|
759
|
-
errorNode = nameNode;
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
}
|
|
763
|
-
}
|
|
764
|
-
});
|
|
765
|
-
if (errorNode) {
|
|
766
|
-
return this.error(new Error("You can't use a top-level await on $script as it will never resolve."));
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
};
|
|
771
|
-
});
|
|
772
|
-
}
|
|
773
|
-
|
|
1034
|
+
const TRIGGER_PLACEHOLDER_RE = /"__TRIGGER_PLACEHOLDER__"/g;
|
|
774
1035
|
function registerTypeTemplates({ nuxt, config, newScripts }) {
|
|
775
1036
|
addTypeTemplate({
|
|
776
1037
|
filename: "types/nuxt-scripts-augments.d.ts",
|
|
@@ -782,7 +1043,7 @@ function registerTypeTemplates({ nuxt, config, newScripts }) {
|
|
|
782
1043
|
let augments = `// Generated by @nuxt/scripts
|
|
783
1044
|
declare module '#app' {
|
|
784
1045
|
interface NuxtApp {
|
|
785
|
-
$scripts: Record<${[...Object.keys(config.globals || {}), ...Object.keys(config.registry || {})].map((k) => `'${k}'`)
|
|
1046
|
+
$scripts: Record<${[...[...Object.keys(config.globals || {}), ...Object.keys(config.registry || {})].map((k) => `'${k}'`), ...["string"]].join(" | ")}, import('#nuxt-scripts/types').UseScriptContext<any> | undefined>
|
|
786
1047
|
_scripts: Record<string, import('#nuxt-scripts/types').NuxtDevToolsScriptInstance>
|
|
787
1048
|
}
|
|
788
1049
|
interface RuntimeNuxtHooks {
|
|
@@ -863,7 +1124,7 @@ function templatePlugin(config, registry) {
|
|
|
863
1124
|
let needsInteractionImport = false;
|
|
864
1125
|
let needsServiceWorkerImport = false;
|
|
865
1126
|
for (const [k, c] of Object.entries(config.registry || {})) {
|
|
866
|
-
const importDefinition = registry.find((i) => i.
|
|
1127
|
+
const importDefinition = registry.find((i) => i.import.name.toLowerCase() === `usescript${k.toLowerCase()}`);
|
|
867
1128
|
if (importDefinition) {
|
|
868
1129
|
resolvedRegistryKeys.push(k);
|
|
869
1130
|
imports.unshift(`import { ${importDefinition.import.name} } from '${importDefinition.import.from}'`);
|
|
@@ -875,12 +1136,15 @@ function templatePlugin(config, registry) {
|
|
|
875
1136
|
const triggerResolved = resolveTriggerForTemplate(scriptOptions?.trigger);
|
|
876
1137
|
if (triggerResolved) {
|
|
877
1138
|
scriptOptions.trigger = "__TRIGGER_PLACEHOLDER__";
|
|
878
|
-
if (triggerResolved.includes("useScriptTriggerIdleTimeout"))
|
|
879
|
-
|
|
880
|
-
if (triggerResolved.includes("
|
|
1139
|
+
if (triggerResolved.includes("useScriptTriggerIdleTimeout"))
|
|
1140
|
+
needsIdleTimeoutImport = true;
|
|
1141
|
+
if (triggerResolved.includes("useScriptTriggerInteraction"))
|
|
1142
|
+
needsInteractionImport = true;
|
|
1143
|
+
if (triggerResolved.includes("useScriptTriggerServiceWorker"))
|
|
1144
|
+
needsServiceWorkerImport = true;
|
|
881
1145
|
}
|
|
882
1146
|
const args = { ...input, scriptOptions };
|
|
883
|
-
const argsJson = triggerResolved ? JSON.stringify(args).replace(
|
|
1147
|
+
const argsJson = triggerResolved ? JSON.stringify(args).replace(TRIGGER_PLACEHOLDER_RE, triggerResolved) : JSON.stringify(args);
|
|
884
1148
|
inits.push(`const ${k} = ${importDefinition.import.name}(${argsJson})`);
|
|
885
1149
|
} else {
|
|
886
1150
|
const args = (typeof c !== "object" ? {} : c) || {};
|
|
@@ -895,11 +1159,14 @@ function templatePlugin(config, registry) {
|
|
|
895
1159
|
const options = c[1];
|
|
896
1160
|
const triggerResolved = resolveTriggerForTemplate(options?.trigger);
|
|
897
1161
|
if (triggerResolved) {
|
|
898
|
-
if (triggerResolved.includes("useScriptTriggerIdleTimeout"))
|
|
899
|
-
|
|
900
|
-
if (triggerResolved.includes("
|
|
1162
|
+
if (triggerResolved.includes("useScriptTriggerIdleTimeout"))
|
|
1163
|
+
needsIdleTimeoutImport = true;
|
|
1164
|
+
if (triggerResolved.includes("useScriptTriggerInteraction"))
|
|
1165
|
+
needsInteractionImport = true;
|
|
1166
|
+
if (triggerResolved.includes("useScriptTriggerServiceWorker"))
|
|
1167
|
+
needsServiceWorkerImport = true;
|
|
901
1168
|
const resolvedOptions = { ...options, trigger: "__TRIGGER_PLACEHOLDER__" };
|
|
902
|
-
const optionsJson = JSON.stringify(resolvedOptions).replace(
|
|
1169
|
+
const optionsJson = JSON.stringify(resolvedOptions).replace(TRIGGER_PLACEHOLDER_RE, triggerResolved);
|
|
903
1170
|
inits.push(`const ${k} = useScript(${JSON.stringify({ key: k, ...typeof c[0] === "string" ? { src: c[0] } : c[0] })}, { ...${optionsJson}, use: () => ({ ${k}: window.${k} }) })`);
|
|
904
1171
|
} else {
|
|
905
1172
|
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} }) })`);
|
|
@@ -907,11 +1174,14 @@ function templatePlugin(config, registry) {
|
|
|
907
1174
|
} else if (typeof c === "object" && c !== null) {
|
|
908
1175
|
const triggerResolved = resolveTriggerForTemplate(c.trigger);
|
|
909
1176
|
if (triggerResolved) {
|
|
910
|
-
if (triggerResolved.includes("useScriptTriggerIdleTimeout"))
|
|
911
|
-
|
|
912
|
-
if (triggerResolved.includes("
|
|
1177
|
+
if (triggerResolved.includes("useScriptTriggerIdleTimeout"))
|
|
1178
|
+
needsIdleTimeoutImport = true;
|
|
1179
|
+
if (triggerResolved.includes("useScriptTriggerInteraction"))
|
|
1180
|
+
needsInteractionImport = true;
|
|
1181
|
+
if (triggerResolved.includes("useScriptTriggerServiceWorker"))
|
|
1182
|
+
needsServiceWorkerImport = true;
|
|
913
1183
|
const resolvedOptions = { ...c, trigger: "__TRIGGER_PLACEHOLDER__" };
|
|
914
|
-
const argsJson = JSON.stringify({ key: k, ...resolvedOptions }).replace(
|
|
1184
|
+
const argsJson = JSON.stringify({ key: k, ...resolvedOptions }).replace(TRIGGER_PLACEHOLDER_RE, triggerResolved);
|
|
915
1185
|
inits.push(`const ${k} = useScript(${argsJson}, { use: () => ({ ${k}: window.${k} }) })`);
|
|
916
1186
|
} else {
|
|
917
1187
|
inits.push(`const ${k} = useScript(${JSON.stringify({ key: k, ...c })}, { use: () => ({ ${k}: window.${k} }) })`);
|
|
@@ -940,12 +1210,93 @@ function templatePlugin(config, registry) {
|
|
|
940
1210
|
` parallel: true,`,
|
|
941
1211
|
` setup() {`,
|
|
942
1212
|
...inits.map((i) => ` ${i}`),
|
|
943
|
-
` return { provide: {
|
|
1213
|
+
` return { provide: { scripts: { ${[...Object.keys(config.globals || {}), ...resolvedRegistryKeys].join(", ")} } } }`,
|
|
944
1214
|
` }`,
|
|
945
1215
|
`})`
|
|
946
1216
|
].join("\n");
|
|
947
1217
|
}
|
|
948
1218
|
|
|
1219
|
+
const SELF_CLOSING_SCRIPT_RE = /<((?:Script[A-Z]|script-)\w[\w-]*)\b([^>]*?)\/\s*>/g;
|
|
1220
|
+
function fixSelfClosingScriptComponents(nuxt) {
|
|
1221
|
+
function expandTags(content) {
|
|
1222
|
+
SELF_CLOSING_SCRIPT_RE.lastIndex = 0;
|
|
1223
|
+
if (!SELF_CLOSING_SCRIPT_RE.test(content))
|
|
1224
|
+
return null;
|
|
1225
|
+
SELF_CLOSING_SCRIPT_RE.lastIndex = 0;
|
|
1226
|
+
return content.replace(SELF_CLOSING_SCRIPT_RE, (_, tag, attrs) => `<${tag}${attrs.trimEnd()}></${tag}>`);
|
|
1227
|
+
}
|
|
1228
|
+
function fixFile(filePath) {
|
|
1229
|
+
if (!existsSync(filePath))
|
|
1230
|
+
return;
|
|
1231
|
+
const content = readFileSync(filePath, "utf-8");
|
|
1232
|
+
const fixed = expandTags(content);
|
|
1233
|
+
if (fixed)
|
|
1234
|
+
nuxt.vfs[filePath] = fixed;
|
|
1235
|
+
}
|
|
1236
|
+
function scanDir(dir) {
|
|
1237
|
+
if (!existsSync(dir))
|
|
1238
|
+
return;
|
|
1239
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
1240
|
+
const fullPath = resolve(dir, entry.name);
|
|
1241
|
+
if (entry.isDirectory())
|
|
1242
|
+
scanDir(fullPath);
|
|
1243
|
+
else if (entry.name.endsWith(".vue"))
|
|
1244
|
+
fixFile(fullPath);
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
const pagesDirs = /* @__PURE__ */ new Set();
|
|
1248
|
+
for (const layer of nuxt.options._layers) {
|
|
1249
|
+
pagesDirs.add(resolve(
|
|
1250
|
+
layer.config.srcDir,
|
|
1251
|
+
layer.config.dir?.pages || "pages"
|
|
1252
|
+
));
|
|
1253
|
+
}
|
|
1254
|
+
for (const dir of pagesDirs) scanDir(dir);
|
|
1255
|
+
if (nuxt.options.dev) {
|
|
1256
|
+
nuxt.hook("builder:watch", (_event, relativePath) => {
|
|
1257
|
+
if (!relativePath.endsWith(".vue"))
|
|
1258
|
+
return;
|
|
1259
|
+
for (const layer of nuxt.options._layers) {
|
|
1260
|
+
const fullPath = resolve(layer.config.srcDir, relativePath);
|
|
1261
|
+
for (const dir of pagesDirs) {
|
|
1262
|
+
if (fullPath.startsWith(`${dir}/`)) {
|
|
1263
|
+
fixFile(fullPath);
|
|
1264
|
+
return;
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
});
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
const REGISTRY_ENV_DEFAULTS = {
|
|
1272
|
+
clarity: { id: "" },
|
|
1273
|
+
cloudflareWebAnalytics: { token: "" },
|
|
1274
|
+
crisp: { id: "" },
|
|
1275
|
+
databuddyAnalytics: { clientId: "" },
|
|
1276
|
+
fathomAnalytics: { site: "" },
|
|
1277
|
+
googleAdsense: { client: "" },
|
|
1278
|
+
googleAnalytics: { id: "" },
|
|
1279
|
+
googleMaps: { apiKey: "" },
|
|
1280
|
+
googleRecaptcha: { siteKey: "" },
|
|
1281
|
+
googleSignIn: { clientId: "" },
|
|
1282
|
+
googleTagManager: { id: "" },
|
|
1283
|
+
hotjar: { id: "" },
|
|
1284
|
+
intercom: { app_id: "" },
|
|
1285
|
+
matomoAnalytics: { matomoUrl: "" },
|
|
1286
|
+
metaPixel: { id: "" },
|
|
1287
|
+
paypal: { clientId: "" },
|
|
1288
|
+
plausibleAnalytics: { domain: "" },
|
|
1289
|
+
posthog: { apiKey: "" },
|
|
1290
|
+
redditPixel: { id: "" },
|
|
1291
|
+
rybbitAnalytics: { siteId: "" },
|
|
1292
|
+
segment: { writeKey: "" },
|
|
1293
|
+
snapchatPixel: { id: "" },
|
|
1294
|
+
stripe: {},
|
|
1295
|
+
tiktokPixel: { id: "" },
|
|
1296
|
+
umamiAnalytics: { websiteId: "" },
|
|
1297
|
+
vercelAnalytics: {},
|
|
1298
|
+
xPixel: { id: "" }
|
|
1299
|
+
};
|
|
949
1300
|
const PARTYTOWN_FORWARDS = {
|
|
950
1301
|
googleAnalytics: ["dataLayer.push", "gtag"],
|
|
951
1302
|
plausible: ["plausible"],
|
|
@@ -1009,8 +1360,7 @@ const module$1 = defineNuxtModule({
|
|
|
1009
1360
|
nuxt.options.runtimeConfig["nuxt-scripts"] = {
|
|
1010
1361
|
version,
|
|
1011
1362
|
// Private proxy config with API key (server-side only)
|
|
1012
|
-
googleStaticMapsProxy: config.googleStaticMapsProxy?.enabled ? { apiKey: nuxt.options.runtimeConfig.public.scripts?.googleMaps?.apiKey } : void 0
|
|
1013
|
-
swTemplate: readFileSync(await resolvePath("./runtime/sw/proxy-sw.template.js"), "utf-8")
|
|
1363
|
+
googleStaticMapsProxy: config.googleStaticMapsProxy?.enabled ? { apiKey: nuxt.options.runtimeConfig.public.scripts?.googleMaps?.apiKey } : void 0
|
|
1014
1364
|
};
|
|
1015
1365
|
nuxt.options.runtimeConfig.public["nuxt-scripts"] = {
|
|
1016
1366
|
// expose for devtools
|
|
@@ -1021,9 +1371,26 @@ const module$1 = defineNuxtModule({
|
|
|
1021
1371
|
};
|
|
1022
1372
|
if (config.registry) {
|
|
1023
1373
|
nuxt.options.runtimeConfig.public = nuxt.options.runtimeConfig.public || {};
|
|
1374
|
+
const registryWithDefaults = {};
|
|
1375
|
+
for (const [key, value] of Object.entries(config.registry)) {
|
|
1376
|
+
if (value && REGISTRY_ENV_DEFAULTS[key]) {
|
|
1377
|
+
const envDefaults = REGISTRY_ENV_DEFAULTS[key];
|
|
1378
|
+
if (value === true || value === "mock") {
|
|
1379
|
+
registryWithDefaults[key] = { ...envDefaults };
|
|
1380
|
+
} else if (typeof value === "object" && !Array.isArray(value)) {
|
|
1381
|
+
registryWithDefaults[key] = defu(value, envDefaults);
|
|
1382
|
+
} else if (Array.isArray(value)) {
|
|
1383
|
+
registryWithDefaults[key] = defu(value[0] || {}, envDefaults);
|
|
1384
|
+
} else {
|
|
1385
|
+
registryWithDefaults[key] = value;
|
|
1386
|
+
}
|
|
1387
|
+
} else {
|
|
1388
|
+
registryWithDefaults[key] = value;
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1024
1391
|
nuxt.options.runtimeConfig.public.scripts = defu(
|
|
1025
1392
|
nuxt.options.runtimeConfig.public.scripts || {},
|
|
1026
|
-
|
|
1393
|
+
registryWithDefaults
|
|
1027
1394
|
);
|
|
1028
1395
|
}
|
|
1029
1396
|
if (config.defaultScriptOptions?.bundle !== void 0) {
|
|
@@ -1031,14 +1398,8 @@ const module$1 = defineNuxtModule({
|
|
|
1031
1398
|
"`scripts.defaultScriptOptions.bundle` is deprecated. Use `scripts.firstParty: true` instead. First-party mode is now enabled by default."
|
|
1032
1399
|
);
|
|
1033
1400
|
}
|
|
1034
|
-
const
|
|
1035
|
-
const
|
|
1036
|
-
const isStaticPreset = staticPresets.includes(preset);
|
|
1037
|
-
const firstPartyEnabled = !!config.firstParty;
|
|
1038
|
-
const firstPartyPrefix = typeof config.firstParty === "object" ? config.firstParty.prefix : void 0;
|
|
1039
|
-
const firstPartyCollectPrefix = typeof config.firstParty === "object" ? config.firstParty.collectPrefix || "/_proxy" : "/_proxy";
|
|
1040
|
-
const firstPartyPrivacy = typeof config.firstParty === "object" ? config.firstParty.privacy ?? "anonymize" : "anonymize";
|
|
1041
|
-
const assetsPrefix = firstPartyPrefix || config.assets?.prefix || "/_scripts";
|
|
1401
|
+
const firstParty = resolveFirstPartyConfig(config);
|
|
1402
|
+
const assetsPrefix = firstParty.assetsPrefix;
|
|
1042
1403
|
if (config.partytown?.length) {
|
|
1043
1404
|
config.registry = config.registry || {};
|
|
1044
1405
|
const requiredForwards = [];
|
|
@@ -1090,109 +1451,17 @@ const module$1 = defineNuxtModule({
|
|
|
1090
1451
|
path: await resolvePath("./runtime/components"),
|
|
1091
1452
|
pathPrefix: false
|
|
1092
1453
|
});
|
|
1454
|
+
fixSelfClosingScriptComponents(nuxt);
|
|
1093
1455
|
addTemplate({
|
|
1094
1456
|
filename: "nuxt-scripts-trigger-resolver.mjs",
|
|
1095
1457
|
getContents() {
|
|
1096
1458
|
return templateTriggerResolver(config.defaultScriptOptions);
|
|
1097
1459
|
}
|
|
1098
1460
|
});
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
if (
|
|
1102
|
-
|
|
1103
|
-
const swRules = getSWInterceptRules(firstPartyCollectPrefix);
|
|
1104
|
-
addServerHandler({
|
|
1105
|
-
route: swPath,
|
|
1106
|
-
handler: swHandlerPath
|
|
1107
|
-
});
|
|
1108
|
-
addPluginTemplate({
|
|
1109
|
-
filename: "nuxt-scripts-sw-register.client.mjs",
|
|
1110
|
-
getContents() {
|
|
1111
|
-
return `import { defineNuxtPlugin } from 'nuxt/app'
|
|
1112
|
-
|
|
1113
|
-
export default defineNuxtPlugin({
|
|
1114
|
-
name: 'nuxt-scripts:sw-register',
|
|
1115
|
-
enforce: 'pre',
|
|
1116
|
-
async setup() {
|
|
1117
|
-
if (!('serviceWorker' in navigator)) return;
|
|
1118
|
-
|
|
1119
|
-
try {
|
|
1120
|
-
const reg = await navigator.serviceWorker.register('${swPath}', { scope: '/' });
|
|
1121
|
-
|
|
1122
|
-
// Wait for SW to be active and controlling this page
|
|
1123
|
-
if (!navigator.serviceWorker.controller) {
|
|
1124
|
-
await new Promise((resolve) => {
|
|
1125
|
-
const onControllerChange = () => {
|
|
1126
|
-
navigator.serviceWorker.removeEventListener('controllerchange', onControllerChange);
|
|
1127
|
-
resolve();
|
|
1128
|
-
};
|
|
1129
|
-
navigator.serviceWorker.addEventListener('controllerchange', onControllerChange);
|
|
1130
|
-
|
|
1131
|
-
// Fallback timeout
|
|
1132
|
-
setTimeout(resolve, 2000);
|
|
1133
|
-
});
|
|
1134
|
-
}
|
|
1135
|
-
} catch (err) {
|
|
1136
|
-
console.warn('[nuxt-scripts] SW registration failed:', err);
|
|
1137
|
-
}
|
|
1138
|
-
},
|
|
1139
|
-
})
|
|
1140
|
-
`;
|
|
1141
|
-
}
|
|
1142
|
-
});
|
|
1143
|
-
addPluginTemplate({
|
|
1144
|
-
filename: "nuxt-scripts-beacon-intercept.client.mjs",
|
|
1145
|
-
getContents() {
|
|
1146
|
-
const rulesJson = JSON.stringify(swRules);
|
|
1147
|
-
return `export default defineNuxtPlugin({
|
|
1148
|
-
name: 'nuxt-scripts:beacon-intercept',
|
|
1149
|
-
enforce: 'pre',
|
|
1150
|
-
setup() {
|
|
1151
|
-
if (typeof navigator === 'undefined' || !navigator.sendBeacon) return;
|
|
1152
|
-
|
|
1153
|
-
const rules = ${rulesJson};
|
|
1154
|
-
const originalBeacon = navigator.sendBeacon.bind(navigator);
|
|
1155
|
-
|
|
1156
|
-
navigator.sendBeacon = (url, data) => {
|
|
1157
|
-
try {
|
|
1158
|
-
const parsed = new URL(url, window.location.origin);
|
|
1159
|
-
|
|
1160
|
-
// Check if this URL matches any of our proxy rules
|
|
1161
|
-
for (const rule of rules) {
|
|
1162
|
-
if (parsed.hostname === rule.pattern || parsed.hostname.endsWith('.' + rule.pattern)) {
|
|
1163
|
-
// Check path prefix if specified
|
|
1164
|
-
if (rule.pathPrefix && !parsed.pathname.startsWith(rule.pathPrefix)) {
|
|
1165
|
-
continue;
|
|
1166
|
-
}
|
|
1167
|
-
|
|
1168
|
-
// Rewrite to proxy: strip pathPrefix from original, prepend target
|
|
1169
|
-
const pathWithoutPrefix = rule.pathPrefix
|
|
1170
|
-
? parsed.pathname.slice(rule.pathPrefix.length)
|
|
1171
|
-
: parsed.pathname;
|
|
1172
|
-
const separator = pathWithoutPrefix.startsWith('/') ? '' : '/';
|
|
1173
|
-
const proxyUrl = rule.target + separator + pathWithoutPrefix + parsed.search;
|
|
1174
|
-
|
|
1175
|
-
return originalBeacon(proxyUrl, data);
|
|
1176
|
-
}
|
|
1177
|
-
}
|
|
1178
|
-
} catch (e) {
|
|
1179
|
-
// URL parsing failed, pass through
|
|
1180
|
-
}
|
|
1181
|
-
|
|
1182
|
-
return originalBeacon(url, data);
|
|
1183
|
-
};
|
|
1184
|
-
},
|
|
1185
|
-
})
|
|
1186
|
-
`;
|
|
1187
|
-
}
|
|
1188
|
-
});
|
|
1189
|
-
nuxt.options.runtimeConfig.public["nuxt-scripts-sw"] = { path: swPath };
|
|
1190
|
-
const proxyHandlerPath = await resolvePath("./runtime/server/proxy-handler");
|
|
1191
|
-
logger.debug("[nuxt-scripts] Registering proxy handler:", `${firstPartyCollectPrefix}/**`, "->", proxyHandlerPath);
|
|
1192
|
-
addServerHandler({
|
|
1193
|
-
route: `${firstPartyCollectPrefix}/**`,
|
|
1194
|
-
handler: proxyHandlerPath
|
|
1195
|
-
});
|
|
1461
|
+
logger.debug("[nuxt-scripts] First-party config:", firstParty);
|
|
1462
|
+
let interceptRules = [];
|
|
1463
|
+
if (firstParty.enabled) {
|
|
1464
|
+
interceptRules = await setupFirstPartyHandlers(firstParty, resolvePath);
|
|
1196
1465
|
}
|
|
1197
1466
|
const scripts = await registry(resolvePath);
|
|
1198
1467
|
for (const script of scripts) {
|
|
@@ -1221,74 +1490,14 @@ export default defineNuxtPlugin({
|
|
|
1221
1490
|
});
|
|
1222
1491
|
}
|
|
1223
1492
|
const { renderedScript } = setupPublicAssetStrategy(config.assets);
|
|
1224
|
-
if (
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
if (proxyKey) {
|
|
1233
|
-
const proxyConfig = proxyConfigs[proxyKey];
|
|
1234
|
-
if (proxyConfig?.routes) {
|
|
1235
|
-
Object.assign(neededRoutes, proxyConfig.routes);
|
|
1236
|
-
} else {
|
|
1237
|
-
unsupportedScripts.push(key);
|
|
1238
|
-
}
|
|
1239
|
-
}
|
|
1240
|
-
}
|
|
1241
|
-
if (unsupportedScripts.length && nuxt.options.dev) {
|
|
1242
|
-
logger.warn(
|
|
1243
|
-
`First-party mode is enabled but these scripts don't support it yet: ${unsupportedScripts.join(", ")}.
|
|
1244
|
-
They will load directly from third-party servers. Request support at https://github.com/nuxt/scripts/issues`
|
|
1245
|
-
);
|
|
1246
|
-
}
|
|
1247
|
-
const flatRoutes = {};
|
|
1248
|
-
for (const [path, config2] of Object.entries(neededRoutes)) {
|
|
1249
|
-
flatRoutes[path] = config2.proxy;
|
|
1250
|
-
}
|
|
1251
|
-
const allRewrites = [];
|
|
1252
|
-
for (const key of registryKeys) {
|
|
1253
|
-
const script = registryScriptsWithImport.find((s) => s.import.name.toLowerCase() === `usescript${key.toLowerCase()}`);
|
|
1254
|
-
const proxyKey = script?.proxy !== false ? script?.proxy || key : void 0;
|
|
1255
|
-
if (proxyKey) {
|
|
1256
|
-
const proxyConfig = proxyConfigs[proxyKey];
|
|
1257
|
-
if (proxyConfig?.rewrite) {
|
|
1258
|
-
allRewrites.push(...proxyConfig.rewrite);
|
|
1259
|
-
}
|
|
1260
|
-
}
|
|
1261
|
-
}
|
|
1262
|
-
nuxt.options.runtimeConfig["nuxt-scripts-proxy"] = {
|
|
1263
|
-
routes: flatRoutes,
|
|
1264
|
-
privacy: firstPartyPrivacy,
|
|
1265
|
-
rewrites: allRewrites
|
|
1266
|
-
};
|
|
1267
|
-
if (Object.keys(neededRoutes).length) {
|
|
1268
|
-
if (nuxt.options.dev) {
|
|
1269
|
-
const routeCount = Object.keys(neededRoutes).length;
|
|
1270
|
-
const scriptsCount = registryKeys.length;
|
|
1271
|
-
logger.success(`First-party mode enabled for ${scriptsCount} script(s), ${routeCount} proxy route(s) configured (privacy: ${firstPartyPrivacy})`);
|
|
1272
|
-
if (logger.level >= 4) {
|
|
1273
|
-
for (const [path, config2] of Object.entries(neededRoutes)) {
|
|
1274
|
-
logger.debug(` ${path} \u2192 ${config2.proxy}`);
|
|
1275
|
-
}
|
|
1276
|
-
}
|
|
1277
|
-
}
|
|
1278
|
-
}
|
|
1279
|
-
if (isStaticPreset) {
|
|
1280
|
-
logger.warn(
|
|
1281
|
-
`First-party collection endpoints require a server runtime (detected: ${preset || "static"}).
|
|
1282
|
-
Scripts will be bundled, but collection requests will not be proxied.
|
|
1283
|
-
|
|
1284
|
-
Options:
|
|
1285
|
-
1. Configure platform rewrites (Vercel, Netlify, Cloudflare)
|
|
1286
|
-
2. Switch to server-rendered mode (ssr: true)
|
|
1287
|
-
3. Disable with firstParty: false
|
|
1288
|
-
|
|
1289
|
-
See: https://scripts.nuxt.com/docs/guides/first-party#static-hosting`
|
|
1290
|
-
);
|
|
1291
|
-
}
|
|
1493
|
+
if (firstParty.enabled) {
|
|
1494
|
+
finalizeFirstParty({
|
|
1495
|
+
firstParty,
|
|
1496
|
+
interceptRules,
|
|
1497
|
+
registry: config.registry,
|
|
1498
|
+
registryScriptsWithImport,
|
|
1499
|
+
nuxtOptions: nuxt.options
|
|
1500
|
+
});
|
|
1292
1501
|
}
|
|
1293
1502
|
const moduleInstallPromises = /* @__PURE__ */ new Map();
|
|
1294
1503
|
addBuildPlugin(NuxtScriptsCheckScripts(), {
|
|
@@ -1297,9 +1506,9 @@ See: https://scripts.nuxt.com/docs/guides/first-party#static-hosting`
|
|
|
1297
1506
|
addBuildPlugin(NuxtScriptBundleTransformer({
|
|
1298
1507
|
scripts: registryScriptsWithImport,
|
|
1299
1508
|
registryConfig: nuxt.options.runtimeConfig.public.scripts,
|
|
1300
|
-
defaultBundle:
|
|
1301
|
-
firstPartyEnabled,
|
|
1302
|
-
firstPartyCollectPrefix,
|
|
1509
|
+
defaultBundle: firstParty.enabled || config.defaultScriptOptions?.bundle,
|
|
1510
|
+
firstPartyEnabled: firstParty.enabled,
|
|
1511
|
+
firstPartyCollectPrefix: firstParty.collectPrefix,
|
|
1303
1512
|
moduleDetected(module) {
|
|
1304
1513
|
if (nuxt.options.dev && module !== "@nuxt/scripts" && !moduleInstallPromises.has(module) && !hasNuxtModule(module))
|
|
1305
1514
|
moduleInstallPromises.set(module, () => installNuxtModule(module));
|
|
@@ -1312,7 +1521,7 @@ See: https://scripts.nuxt.com/docs/guides/first-party#static-hosting`
|
|
|
1312
1521
|
renderedScript
|
|
1313
1522
|
}));
|
|
1314
1523
|
nuxt.hooks.hook("build:done", async () => {
|
|
1315
|
-
const initPromise =
|
|
1524
|
+
const initPromise = [...moduleInstallPromises.values()];
|
|
1316
1525
|
for (const p of initPromise)
|
|
1317
1526
|
await p?.();
|
|
1318
1527
|
});
|
|
@@ -1323,6 +1532,17 @@ See: https://scripts.nuxt.com/docs/guides/first-party#static-hosting`
|
|
|
1323
1532
|
handler: await resolvePath("./runtime/server/google-static-maps-proxy")
|
|
1324
1533
|
});
|
|
1325
1534
|
}
|
|
1535
|
+
if (config.registry?.gravatar) {
|
|
1536
|
+
const gravatarConfig = typeof config.registry.gravatar === "object" && !Array.isArray(config.registry.gravatar) ? config.registry.gravatar : {};
|
|
1537
|
+
nuxt.options.runtimeConfig.public["nuxt-scripts"] = defu(
|
|
1538
|
+
{ gravatarProxy: { cacheMaxAge: gravatarConfig.cacheMaxAge ?? 3600 } },
|
|
1539
|
+
nuxt.options.runtimeConfig.public["nuxt-scripts"]
|
|
1540
|
+
);
|
|
1541
|
+
addServerHandler({
|
|
1542
|
+
route: "/_scripts/gravatar-proxy",
|
|
1543
|
+
handler: await resolvePath("./runtime/server/gravatar-proxy")
|
|
1544
|
+
});
|
|
1545
|
+
}
|
|
1326
1546
|
addServerHandler({
|
|
1327
1547
|
route: "/api/_scripts/x-embed",
|
|
1328
1548
|
handler: await resolvePath("./runtime/server/x-embed")
|