@nuxt/scripts 1.0.0-beta.24 → 1.0.0-beta.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/dist/client/200.html +1 -1
  2. package/dist/client/404.html +1 -1
  3. package/dist/client/_nuxt/{Bh9fd9qr.js → C-7nRtzO.js} +1 -1
  4. package/dist/client/_nuxt/{UTi7FhVv.js → D5k4eN9O.js} +1 -1
  5. package/dist/client/_nuxt/DjhmCJlE.js +162 -0
  6. package/dist/client/_nuxt/{B7aPLMNo.js → TJ5JFHov.js} +1 -1
  7. package/dist/client/_nuxt/builds/latest.json +1 -1
  8. package/dist/client/_nuxt/builds/meta/33e1ac0e-aba1-4856-8beb-775c426be236.json +1 -0
  9. package/dist/client/_nuxt/entry.C5SUNdim.css +1 -0
  10. package/dist/client/_nuxt/error-404.C_3_IG5y.css +1 -0
  11. package/dist/client/_nuxt/error-500.DSv6YikH.css +1 -0
  12. package/dist/client/index.html +1 -1
  13. package/dist/module.d.mts +6 -20
  14. package/dist/module.d.ts +6 -20
  15. package/dist/module.json +1 -1
  16. package/dist/module.mjs +303 -277
  17. package/dist/registry.mjs +121 -71
  18. package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.d.vue.ts +2 -5
  19. package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.vue +14 -15
  20. package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.vue.d.ts +2 -5
  21. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsAdvancedMarkerElement.d.vue.ts +1 -4
  22. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsAdvancedMarkerElement.vue +30 -37
  23. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsAdvancedMarkerElement.vue.d.ts +1 -4
  24. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsCircle.vue +19 -28
  25. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsHeatmapLayer.vue +18 -22
  26. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsInfoWindow.vue +30 -37
  27. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarker.d.vue.ts +1 -4
  28. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarker.vue +31 -36
  29. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarker.vue.d.ts +1 -4
  30. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.vue +17 -22
  31. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPinElement.vue +19 -28
  32. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPolygon.vue +19 -28
  33. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPolyline.vue +19 -28
  34. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsRectangle.vue +19 -28
  35. package/dist/runtime/components/GoogleMaps/injectionKeys.d.ts +11 -0
  36. package/dist/runtime/components/GoogleMaps/injectionKeys.js +3 -0
  37. package/dist/runtime/components/GoogleMaps/useGoogleMapsResource.d.ts +26 -0
  38. package/dist/runtime/components/GoogleMaps/useGoogleMapsResource.js +37 -0
  39. package/dist/runtime/composables/useScriptTriggerConsent.d.ts +10 -0
  40. package/dist/runtime/composables/useScriptTriggerConsent.js +32 -19
  41. package/dist/runtime/registry/bing-uet.d.ts +20 -0
  42. package/dist/runtime/registry/bing-uet.js +29 -0
  43. package/dist/runtime/registry/bluesky-embed.d.ts +1 -1
  44. package/dist/runtime/registry/crisp.d.ts +1 -1
  45. package/dist/runtime/registry/fathom-analytics.d.ts +1 -1
  46. package/dist/runtime/registry/google-adsense.d.ts +1 -1
  47. package/dist/runtime/registry/hotjar.d.ts +1 -1
  48. package/dist/runtime/registry/instagram-embed.d.ts +1 -1
  49. package/dist/runtime/registry/intercom.d.ts +1 -1
  50. package/dist/runtime/registry/matomo-analytics.d.ts +1 -1
  51. package/dist/runtime/registry/meta-pixel.d.ts +1 -1
  52. package/dist/runtime/registry/mixpanel-analytics.d.ts +22 -0
  53. package/dist/runtime/registry/mixpanel-analytics.js +46 -0
  54. package/dist/runtime/registry/npm.d.ts +1 -1
  55. package/dist/runtime/registry/reddit-pixel.d.ts +1 -1
  56. package/dist/runtime/registry/schemas.d.ts +19 -0
  57. package/dist/runtime/registry/schemas.js +19 -0
  58. package/dist/runtime/registry/snapchat-pixel.d.ts +1 -1
  59. package/dist/runtime/registry/tiktok-pixel.d.ts +1 -1
  60. package/dist/runtime/registry/vercel-analytics.d.ts +1 -1
  61. package/dist/runtime/registry/x-embed.d.ts +1 -1
  62. package/dist/runtime/registry/x-pixel.d.ts +1 -1
  63. package/dist/runtime/server/proxy-handler.js +36 -23
  64. package/dist/runtime/server/utils/privacy.d.ts +1 -1
  65. package/dist/runtime/server/utils/privacy.js +3 -3
  66. package/dist/runtime/types.d.ts +30 -18
  67. package/dist/runtime/utils/pure.d.ts +1 -1
  68. package/dist/runtime/utils.js +1 -1
  69. package/dist/shared/scripts.ViOoYQXH.mjs +381 -0
  70. package/dist/stats.d.mts +95 -3
  71. package/dist/stats.d.ts +95 -3
  72. package/dist/stats.mjs +2845 -169
  73. package/dist/types-source.mjs +47 -0
  74. package/package.json +13 -13
  75. package/dist/client/_nuxt/BNNMZFwZ.js +0 -162
  76. package/dist/client/_nuxt/builds/meta/78647cef-f45a-4560-82b4-b9364815198a.json +0 -1
  77. package/dist/client/_nuxt/entry.CACgbLJl.css +0 -1
  78. package/dist/client/_nuxt/error-404.DMdWw4vT.css +0 -1
  79. package/dist/client/_nuxt/error-500.CROTF27X.css +0 -1
  80. package/dist/shared/scripts.Crpn87WB.mjs +0 -318
package/dist/module.mjs CHANGED
@@ -1,5 +1,5 @@
1
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';
2
+ import { useLogger, addServerHandler, addPluginTemplate, useNuxt, addDevServerHandler, extendRouteRules, tryUseNuxt, extendViteConfig, logger as logger$1, addTypeTemplate, defineNuxtModule, createResolver, hasNuxtModule, addImports, addComponentsDir, addTemplate, addBuildPlugin } from '@nuxt/kit';
3
3
  import { defu } from 'defu';
4
4
  import { join, resolve, relative } from 'pathe';
5
5
  import { resolvePackageJSON, readPackageJSON } from 'pkg-types';
@@ -18,170 +18,11 @@ import fsp from 'node:fs/promises';
18
18
  import { colors } from 'consola/utils';
19
19
  import MagicString from 'magic-string';
20
20
  import { hash } from 'ohash';
21
- import { g as getAllProxyConfigs, r as routesToInterceptRules, a as getProxyConfig } from './shared/scripts.Crpn87WB.mjs';
22
21
  import { registry } from './registry.mjs';
23
-
24
- const renderedScript = /* @__PURE__ */ new Map();
25
- const ONE_YEAR_IN_SECONDS = 60 * 60 * 24 * 365;
26
- function bundleStorage() {
27
- const nuxt = tryUseNuxt();
28
- return createStorage({
29
- driver: fsDriver({
30
- base: resolve(nuxt?.options.rootDir || "", "node_modules/.cache/nuxt/scripts")
31
- })
32
- });
33
- }
34
- function setupPublicAssetStrategy(options = {}) {
35
- const assetsBaseURL = options.prefix || "/_scripts/assets";
36
- const nuxt = useNuxt();
37
- const storage = bundleStorage();
38
- addDevServerHandler({
39
- route: assetsBaseURL,
40
- handler: lazyEventHandler(async () => {
41
- return eventHandler(async (event) => {
42
- const filename = event.path.slice(1);
43
- const scriptDescriptor = renderedScript.get(join(assetsBaseURL, event.path.slice(1)));
44
- if (!scriptDescriptor || scriptDescriptor instanceof Error)
45
- throw createError({ statusCode: 404 });
46
- if (scriptDescriptor.content) {
47
- return scriptDescriptor.content;
48
- }
49
- const key = `bundle:${filename}`;
50
- let res = await storage.getItemRaw(key);
51
- if (!res) {
52
- res = await fetch(scriptDescriptor.src).then((r) => r.arrayBuffer()).then((r) => Buffer.from(r));
53
- await storage.setItemRaw(key, res);
54
- }
55
- return res;
56
- });
57
- })
58
- });
59
- if (nuxt.options.dev) {
60
- extendRouteRules(joinURL(assetsBaseURL, "**"), {
61
- cache: {
62
- maxAge: ONE_YEAR_IN_SECONDS
63
- }
64
- });
65
- }
66
- const cacheDir = join(nuxt.options.buildDir, "cache", "scripts");
67
- nuxt.hook("nitro:config", (nitroConfig) => {
68
- nitroConfig.publicAssets ||= [];
69
- nitroConfig.publicAssets.push({
70
- dir: cacheDir,
71
- maxAge: ONE_YEAR_IN_SECONDS,
72
- baseURL: assetsBaseURL
73
- });
74
- nitroConfig.prerender ||= {};
75
- nitroConfig.prerender.ignore ||= [];
76
- nitroConfig.prerender.ignore.push(assetsBaseURL);
77
- });
78
- return {
79
- renderedScript
80
- };
81
- }
82
-
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
- }
22
+ import { g as getAllProxyConfigs, r as routesToInterceptRules } from './shared/scripts.ViOoYQXH.mjs';
123
23
 
124
24
  const logger = useLogger("@nuxt/scripts");
125
25
 
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)
160
- continue;
161
- const rtScripts = runtimeConfig.public?.scripts;
162
- const rtEntry = rtScripts?.[def.registryKey];
163
- const rtConfig = rtEntry && typeof rtEntry === "object" ? Array.isArray(rtEntry) ? rtEntry[0] : rtEntry : void 0;
164
- let config;
165
- if (entry === true || entry === "mock") {
166
- if (!rtConfig)
167
- continue;
168
- config = rtConfig;
169
- } else if (typeof entry === "object") {
170
- config = Array.isArray(entry) ? entry[0] : entry;
171
- }
172
- if (!config || config[def.configField])
173
- continue;
174
- const value = def.computeValue(collectPrefix, config);
175
- if (typeof entry === "object") {
176
- config[def.configField] = value;
177
- if (rtConfig)
178
- rtConfig[def.configField] = value;
179
- } else {
180
- config[def.configField] = value;
181
- }
182
- }
183
- }
184
-
185
26
  function generateInterceptPluginContents(interceptRules) {
186
27
  const rulesJson = JSON.stringify(interceptRules);
187
28
  return `export default defineNuxtPlugin({
@@ -244,65 +85,123 @@ function generateInterceptPluginContents(interceptRules) {
244
85
  `;
245
86
  }
246
87
 
247
- function resolveFirstPartyConfig(config) {
88
+ async function setupFirstParty(config, resolvePath) {
248
89
  const enabled = !!config.firstParty;
249
- const prefix = typeof config.firstParty === "object" ? config.firstParty.prefix : void 0;
250
- const collectPrefix = typeof config.firstParty === "object" ? config.firstParty.collectPrefix || "/_scripts/c" : "/_scripts/c";
90
+ const proxyPrefix = typeof config.firstParty === "object" ? config.firstParty.proxyPrefix || "/_scripts/p" : "/_scripts/p";
251
91
  const privacy = typeof config.firstParty === "object" ? config.firstParty.privacy : void 0;
252
- const assetsPrefix = prefix || config.assets?.prefix || "/_scripts/assets";
253
- return { enabled, prefix, collectPrefix, privacy, assetsPrefix };
92
+ const assetsPrefix = config.assets?.prefix || "/_scripts/assets";
93
+ const proxyConfigs = enabled ? getAllProxyConfigs(proxyPrefix) : {};
94
+ const firstParty = { enabled, proxyPrefix, privacy, assetsPrefix, proxyConfigs };
95
+ if (enabled) {
96
+ const proxyHandlerPath = await resolvePath("./runtime/server/proxy-handler");
97
+ logger.debug("[nuxt-scripts] Registering proxy handler:", `${proxyPrefix}/**`, "->", proxyHandlerPath);
98
+ addServerHandler({
99
+ route: `${proxyPrefix}/**`,
100
+ handler: proxyHandlerPath
101
+ });
102
+ }
103
+ return firstParty;
254
104
  }
255
- async function setupFirstPartyHandlers(firstParty, resolvePath) {
256
- const interceptRules = [];
257
- addPluginTemplate({
258
- filename: "nuxt-scripts-intercept.client.mjs",
259
- getContents() {
260
- return generateInterceptPluginContents(interceptRules);
261
- }
262
- });
263
- const proxyHandlerPath = await resolvePath("./runtime/server/proxy-handler");
264
- logger.debug("[nuxt-scripts] Registering proxy handler:", `${firstParty.collectPrefix}/**`, "->", proxyHandlerPath);
265
- addServerHandler({
266
- route: `${firstParty.collectPrefix}/**`,
267
- handler: proxyHandlerPath
268
- });
269
- return interceptRules;
105
+ function applyAutoInject(registry, runtimeConfig, proxyPrefix, registryKey, autoInject) {
106
+ const entry = registry[registryKey];
107
+ if (!entry)
108
+ return;
109
+ const input = entry[0];
110
+ const rtScripts = runtimeConfig.public?.scripts;
111
+ const rtEntry = rtScripts?.[registryKey];
112
+ const config = rtEntry && typeof rtEntry === "object" ? rtEntry : input;
113
+ if (!config || config[autoInject.configField])
114
+ return;
115
+ const value = autoInject.computeValue(proxyPrefix, config);
116
+ input[autoInject.configField] = value;
117
+ if (rtEntry && typeof rtEntry === "object" && rtEntry !== input)
118
+ rtEntry[autoInject.configField] = value;
119
+ }
120
+ const DOMAIN_RE = /^https?:\/\/([^/]+)/;
121
+ function extractDomains(routes) {
122
+ const domains = /* @__PURE__ */ new Set();
123
+ for (const { proxy } of Object.values(routes)) {
124
+ const match = proxy.match(DOMAIN_RE);
125
+ if (match?.[1])
126
+ domains.add(match[1]);
127
+ }
128
+ return [...domains].sort();
129
+ }
130
+ function computePrivacyLevel(privacy) {
131
+ const flags = Object.values(privacy);
132
+ if (flags.every(Boolean))
133
+ return "full";
134
+ if (flags.some(Boolean))
135
+ return "partial";
136
+ return "none";
270
137
  }
271
138
  function finalizeFirstParty(opts) {
272
- const { firstParty, interceptRules, registryScripts, registryScriptsWithImport, nuxtOptions } = opts;
273
- const proxyConfigs = getAllProxyConfigs(firstParty.collectPrefix);
139
+ const { firstParty, registryScripts, nuxtOptions } = opts;
140
+ const { proxyConfigs, proxyPrefix } = firstParty;
274
141
  const registryKeys = Object.keys(opts.registry || {});
275
142
  const scriptByKey = /* @__PURE__ */ new Map();
276
143
  for (const script of registryScripts) {
277
- if (script.registryKey) {
144
+ if (script.registryKey)
278
145
  scriptByKey.set(script.registryKey, script);
279
- }
280
146
  }
281
147
  const neededRoutes = {};
282
148
  const routePrivacyOverrides = {};
283
149
  const unsupportedScripts = [];
284
150
  const unmatchedScripts = [];
151
+ const devtoolsScripts = [];
285
152
  for (const key of registryKeys) {
286
- const script = scriptByKey.get(key) || registryScriptsWithImport.find((s) => s.import.name.toLowerCase() === `usescript${key.toLowerCase()}`);
153
+ const script = scriptByKey.get(key);
287
154
  if (!script) {
288
155
  unmatchedScripts.push(key);
289
156
  continue;
290
157
  }
291
- const proxyKey = script?.proxy || void 0;
292
- if (proxyKey) {
293
- const proxyConfig = proxyConfigs[proxyKey];
294
- if (proxyConfig?.routes) {
295
- Object.assign(neededRoutes, proxyConfig.routes);
296
- for (const routePath of Object.keys(proxyConfig.routes)) {
297
- routePrivacyOverrides[routePath] = proxyConfig.privacy;
298
- }
299
- } else {
158
+ if (script.proxy === false)
159
+ continue;
160
+ const configKey = script.proxy || key;
161
+ const proxyConfig = proxyConfigs[configKey];
162
+ if (!proxyConfig) {
163
+ if (script.scriptBundling !== false)
300
164
  unsupportedScripts.push(key);
301
- }
165
+ continue;
166
+ }
167
+ const scriptRoutes = proxyConfig.routes || {};
168
+ if (proxyConfig.routes) {
169
+ Object.assign(neededRoutes, proxyConfig.routes);
170
+ for (const routePath of Object.keys(proxyConfig.routes))
171
+ routePrivacyOverrides[routePath] = proxyConfig.privacy;
172
+ }
173
+ if (proxyConfig.autoInject && opts.registry)
174
+ applyAutoInject(opts.registry, nuxtOptions.runtimeConfig, proxyPrefix, key, proxyConfig.autoInject);
175
+ if (nuxtOptions.dev) {
176
+ const privacy = proxyConfig.privacy;
177
+ const normalizedPrivacy = {
178
+ ip: !!privacy.ip,
179
+ userAgent: !!privacy.userAgent,
180
+ language: !!privacy.language,
181
+ screen: !!privacy.screen,
182
+ timezone: !!privacy.timezone,
183
+ hardware: !!privacy.hardware
184
+ };
185
+ const logo = script.logo;
186
+ const logoStr = typeof logo === "object" ? logo.dark || logo.light : logo || "";
187
+ const interceptRules2 = routesToInterceptRules(scriptRoutes);
188
+ devtoolsScripts.push({
189
+ registryKey: key,
190
+ label: script.label || key,
191
+ logo: logoStr,
192
+ category: script.category || "unknown",
193
+ configKey,
194
+ mechanism: script.src === false ? "config-injection-proxy" : "bundle-rewrite-intercept",
195
+ hasAutoInject: !!proxyConfig.autoInject,
196
+ autoInjectField: proxyConfig.autoInject?.configField,
197
+ hasPostProcess: !!proxyConfig.postProcess,
198
+ privacy: normalizedPrivacy,
199
+ privacyLevel: computePrivacyLevel(normalizedPrivacy),
200
+ domains: extractDomains(scriptRoutes),
201
+ routes: Object.entries(scriptRoutes).map(([local, { proxy }]) => ({ local, target: proxy })),
202
+ interceptRules: interceptRules2
203
+ });
302
204
  }
303
- }
304
- if (opts.registry) {
305
- autoInjectProxyEndpoints(opts.registry, nuxtOptions.runtimeConfig, firstParty.collectPrefix);
306
205
  }
307
206
  if (unmatchedScripts.length) {
308
207
  logger.warn(
@@ -316,28 +215,32 @@ These scripts will not have proxy routes registered. Check that the registry key
316
215
  They will load directly from third-party servers. Request support at https://github.com/nuxt/scripts/issues`
317
216
  );
318
217
  }
319
- interceptRules.push(...routesToInterceptRules(neededRoutes));
218
+ const interceptRules = routesToInterceptRules(neededRoutes);
219
+ addPluginTemplate({
220
+ filename: "nuxt-scripts-intercept.client.mjs",
221
+ getContents() {
222
+ return generateInterceptPluginContents(interceptRules);
223
+ }
224
+ });
320
225
  const flatRoutes = {};
321
- for (const [path, config] of Object.entries(neededRoutes)) {
226
+ for (const [path, config] of Object.entries(neededRoutes))
322
227
  flatRoutes[path] = config.proxy;
323
- }
324
228
  nuxtOptions.runtimeConfig["nuxt-scripts-proxy"] = {
325
229
  routes: flatRoutes,
326
230
  privacy: firstParty.privacy,
327
231
  routePrivacy: routePrivacyOverrides
328
232
  };
233
+ const privacyLabel = firstParty.privacy === void 0 ? "per-script" : typeof firstParty.privacy === "boolean" ? firstParty.privacy ? "anonymize" : "passthrough" : "custom";
329
234
  if (Object.keys(neededRoutes).length && nuxtOptions.dev) {
330
235
  const routeCount = Object.keys(neededRoutes).length;
331
236
  const scriptsCount = registryKeys.length;
332
- const privacyLabel = firstParty.privacy === void 0 ? "per-script" : typeof firstParty.privacy === "boolean" ? firstParty.privacy ? "anonymize" : "passthrough" : "custom";
333
237
  logger.success(`First-party mode enabled for ${scriptsCount} script(s), ${routeCount} proxy route(s) configured (privacy: ${privacyLabel})`);
334
238
  if (logger.level >= 4) {
335
- for (const [path, config] of Object.entries(neededRoutes)) {
239
+ for (const [path, config] of Object.entries(neededRoutes))
336
240
  logger.debug(` ${path} \u2192 ${config.proxy}`);
337
- }
338
241
  }
339
242
  }
340
- const staticPresets = ["static", "github-pages", "cloudflare-pages-static"];
243
+ const staticPresets = ["static", "github-pages", "cloudflare-pages-static", "netlify-static", "azure-static", "firebase-static"];
341
244
  const preset = process.env.NITRO_PRESET || "";
342
245
  if (staticPresets.includes(preset)) {
343
246
  logger.warn(
@@ -352,6 +255,121 @@ Options:
352
255
  See: https://scripts.nuxt.com/docs/guides/first-party#static-hosting`
353
256
  );
354
257
  }
258
+ if (nuxtOptions.dev) {
259
+ const allDomains = /* @__PURE__ */ new Set();
260
+ for (const s of devtoolsScripts) {
261
+ for (const d of s.domains)
262
+ allDomains.add(d);
263
+ }
264
+ return {
265
+ enabled: true,
266
+ proxyPrefix,
267
+ privacyMode: privacyLabel,
268
+ scripts: devtoolsScripts,
269
+ totalRoutes: Object.keys(neededRoutes).length,
270
+ totalDomains: allDomains.size
271
+ };
272
+ }
273
+ }
274
+
275
+ const renderedScript = /* @__PURE__ */ new Map();
276
+ const ONE_YEAR_IN_SECONDS = 60 * 60 * 24 * 365;
277
+ function bundleStorage() {
278
+ const nuxt = tryUseNuxt();
279
+ return createStorage({
280
+ driver: fsDriver({
281
+ base: resolve(nuxt?.options.rootDir || "", "node_modules/.cache/nuxt/scripts")
282
+ })
283
+ });
284
+ }
285
+ function setupPublicAssetStrategy(options = {}) {
286
+ const assetsBaseURL = options.prefix || "/_scripts/assets";
287
+ const nuxt = useNuxt();
288
+ const storage = bundleStorage();
289
+ addDevServerHandler({
290
+ route: assetsBaseURL,
291
+ handler: lazyEventHandler(async () => {
292
+ return eventHandler(async (event) => {
293
+ const filename = event.path.slice(1);
294
+ const scriptDescriptor = renderedScript.get(join(assetsBaseURL, event.path.slice(1)));
295
+ if (!scriptDescriptor || scriptDescriptor instanceof Error)
296
+ throw createError({ statusCode: 404 });
297
+ if (scriptDescriptor.content) {
298
+ return scriptDescriptor.content;
299
+ }
300
+ const key = `bundle:${filename}`;
301
+ let res = await storage.getItemRaw(key);
302
+ if (!res) {
303
+ res = await fetch(scriptDescriptor.src).then((r) => r.arrayBuffer()).then((r) => Buffer.from(r));
304
+ await storage.setItemRaw(key, res);
305
+ }
306
+ return res;
307
+ });
308
+ })
309
+ });
310
+ if (nuxt.options.dev) {
311
+ extendRouteRules(joinURL(assetsBaseURL, "**"), {
312
+ cache: {
313
+ maxAge: ONE_YEAR_IN_SECONDS
314
+ }
315
+ });
316
+ }
317
+ const cacheDir = join(nuxt.options.buildDir, "cache", "scripts");
318
+ nuxt.hook("nitro:config", (nitroConfig) => {
319
+ nitroConfig.publicAssets ||= [];
320
+ nitroConfig.publicAssets.push({
321
+ dir: cacheDir,
322
+ maxAge: ONE_YEAR_IN_SECONDS,
323
+ baseURL: assetsBaseURL
324
+ });
325
+ nitroConfig.prerender ||= {};
326
+ nitroConfig.prerender.ignore ||= [];
327
+ nitroConfig.prerender.ignore.push(assetsBaseURL);
328
+ });
329
+ return {
330
+ renderedScript
331
+ };
332
+ }
333
+
334
+ const DEVTOOLS_UI_ROUTE = "/__nuxt-scripts";
335
+ const DEVTOOLS_UI_LOCAL_PORT = 3300;
336
+
337
+ async function setupDevToolsUI(options, resolve, nuxt = useNuxt()) {
338
+ const clientPath = await resolve("./client");
339
+ const isProductionBuild = existsSync(clientPath);
340
+ if (isProductionBuild) {
341
+ nuxt.hook("vite:serverCreated", async (server) => {
342
+ const sirv = await import('sirv').then((r) => r.default || r);
343
+ server.middlewares.use(
344
+ DEVTOOLS_UI_ROUTE,
345
+ sirv(clientPath, { dev: true, single: true })
346
+ );
347
+ });
348
+ } else {
349
+ extendViteConfig((config) => {
350
+ config.server = config.server || {};
351
+ config.server.proxy = config.server.proxy || {};
352
+ config.server.proxy[DEVTOOLS_UI_ROUTE] = {
353
+ target: `http://localhost:${DEVTOOLS_UI_LOCAL_PORT}${DEVTOOLS_UI_ROUTE}`,
354
+ changeOrigin: true,
355
+ followRedirects: true,
356
+ rewrite: (path) => path.replace(DEVTOOLS_UI_ROUTE, "")
357
+ };
358
+ });
359
+ }
360
+ addCustomTab({
361
+ // unique identifier
362
+ name: "nuxt-scripts",
363
+ // title to display in the tab
364
+ title: "Scripts",
365
+ // any icon from Iconify, or a URL to an image
366
+ icon: "carbon:script",
367
+ // iframe view
368
+ view: {
369
+ type: "iframe",
370
+ src: DEVTOOLS_UI_ROUTE
371
+ }
372
+ });
355
373
  }
356
374
 
357
375
  const isStackblitz = provider === "stackblitz";
@@ -394,6 +412,32 @@ function installNuxtModule(name, options) {
394
412
  }, { rootDir: nuxt.options.rootDir, searchPaths: nuxt.options.modulesDir, ...options });
395
413
  }
396
414
 
415
+ function normalizeRegistryConfig(registry) {
416
+ for (const key of Object.keys(registry)) {
417
+ const entry = registry[key];
418
+ if (!entry) {
419
+ delete registry[key];
420
+ continue;
421
+ }
422
+ if (entry === true) {
423
+ registry[key] = [{}];
424
+ } else if (entry === "mock") {
425
+ registry[key] = [{}, { trigger: "manual", skipValidation: true }];
426
+ } else if (Array.isArray(entry)) {
427
+ if (!entry[0] && !entry[1]) {
428
+ delete registry[key];
429
+ continue;
430
+ }
431
+ if (!entry[0])
432
+ entry[0] = {};
433
+ } else if (typeof entry === "object") {
434
+ registry[key] = [entry];
435
+ } else {
436
+ delete registry[key];
437
+ }
438
+ }
439
+ }
440
+
397
441
  function isVue(id, opts = {}) {
398
442
  const { search } = parseURL(decodeURIComponent(pathToFileURL(id).href));
399
443
  if (id.endsWith(".vue") && !search) {
@@ -479,9 +523,6 @@ function NuxtScriptsCheckScripts() {
479
523
 
480
524
  const WORD_OR_DOLLAR_RE = /[\w$]/;
481
525
  const BLANK_CANVAS_DATA_URL = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQIHWNgAAIABQABNjN9GQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAAA0lEQVQI12NgYGBgAAAABQABXvMqOgAAAABJRU5ErkJggg==";
482
- const GA_COLLECT_RE = /([\w$])?"https:\/\/"\+\(.*?\)\+"\.google-analytics\.com\/g\/collect"/g;
483
- const GA_ANALYTICS_COLLECT_RE = /([\w$])?"https:\/\/"\+\(.*?\)\+"\.analytics\.google\.com\/g\/collect"/g;
484
- const FATHOM_SELF_HOSTED_RE = /\.src\.indexOf\("cdn\.usefathom\.com"\)\s*<\s*0/;
485
526
  function isPropertyKeyAST(parent, ctx) {
486
527
  return parent?.type === "Property" && ctx.key === "key" || parent?.type === "SwitchCase" && ctx.key === "test";
487
528
  }
@@ -598,7 +639,7 @@ function resolveCalleeTarget(callee, scopeTracker) {
598
639
  return "Image";
599
640
  return null;
600
641
  }
601
- function rewriteScriptUrlsAST(content, filename, rewrites) {
642
+ function rewriteScriptUrlsAST(content, filename, rewrites, postProcess) {
602
643
  const s = new MagicString(content);
603
644
  function needsLeadingSpace(start) {
604
645
  const prev = content[start - 1];
@@ -622,9 +663,10 @@ function rewriteScriptUrlsAST(content, filename, rewrites) {
622
663
  s.overwrite(node.start, node.end, `${needsLeadingSpace(node.start)}self.location.origin+${quote}${rewritten}${quote}`);
623
664
  }
624
665
  }
625
- if (node.type === "TemplateLiteral" && node.expressions?.length === 0) {
666
+ if (node.type === "TemplateLiteral") {
626
667
  const quasis = node.quasis;
627
- if (quasis?.length === 1) {
668
+ const expressions = node.expressions;
669
+ if (expressions?.length === 0 && quasis?.length === 1) {
628
670
  const value = quasis[0].value?.cooked ?? quasis[0].value?.raw;
629
671
  if (typeof value !== "string")
630
672
  return;
@@ -636,6 +678,15 @@ function rewriteScriptUrlsAST(content, filename, rewrites) {
636
678
  } else {
637
679
  s.overwrite(node.start, node.end, `${needsLeadingSpace(node.start)}self.location.origin+\`${rewritten}\``);
638
680
  }
681
+ } else if (expressions?.length > 0 && quasis?.length > 0) {
682
+ const firstQuasi = quasis[0];
683
+ const value = firstQuasi.value?.cooked ?? firstQuasi.value?.raw;
684
+ if (typeof value !== "string" || isPropertyKeyAST(parent, ctx))
685
+ return;
686
+ const rewritten = matchAndRewrite(value, rewrites);
687
+ if (rewritten === null)
688
+ return;
689
+ s.overwrite(node.start, firstQuasi.end, `${needsLeadingSpace(node.start)}self.location.origin+\`${rewritten}`);
639
690
  }
640
691
  }
641
692
  if (node.type === "CallExpression") {
@@ -708,22 +759,8 @@ function rewriteScriptUrlsAST(content, filename, rewrites) {
708
759
  }
709
760
  });
710
761
  let output = s.toString();
711
- const gaRewrite = rewrites.find((r) => r.from.includes("google-analytics.com/g/collect"));
712
- if (gaRewrite) {
713
- output = output.replace(
714
- GA_COLLECT_RE,
715
- (_, prevChar) => `${prevChar ? `${prevChar} ` : ""}self.location.origin+"${gaRewrite.to}"`
716
- );
717
- output = output.replace(
718
- GA_ANALYTICS_COLLECT_RE,
719
- (_, prevChar) => `${prevChar ? `${prevChar} ` : ""}self.location.origin+"${gaRewrite.to}"`
720
- );
721
- }
722
- if (rewrites.some((r) => r.from === "cdn.usefathom.com")) {
723
- output = output.replace(
724
- FATHOM_SELF_HOSTED_RE,
725
- '.src.indexOf("cdn.usefathom.com")<-1'
726
- );
762
+ if (postProcess) {
763
+ output = postProcess(output, rewrites);
727
764
  }
728
765
  return output;
729
766
  }
@@ -761,7 +798,7 @@ function normalizeScriptData(src, assetsBaseURL = "/_scripts/assets") {
761
798
  return { url: src };
762
799
  }
763
800
  async function downloadScript(opts, renderedScript, fetchOptions, cacheMaxAge) {
764
- const { src, url, filename, forceDownload, integrity, proxyRewrites } = opts;
801
+ const { src, url, filename, forceDownload, integrity, proxyRewrites, postProcess } = opts;
765
802
  if (src === url || !filename) {
766
803
  return;
767
804
  }
@@ -799,7 +836,7 @@ async function downloadScript(opts, renderedScript, fetchOptions, cacheMaxAge) {
799
836
  await storage.setItemRaw(`bundle:${filename}`, res);
800
837
  if (proxyRewrites?.length && res) {
801
838
  const content = res.toString("utf-8");
802
- const rewritten = rewriteScriptUrlsAST(content, filename || "script.js", proxyRewrites);
839
+ const rewritten = rewriteScriptUrlsAST(content, filename || "script.js", proxyRewrites, postProcess);
803
840
  res = Buffer.from(rewritten, "utf-8");
804
841
  logger.debug(`Rewrote ${proxyRewrites.length} URL patterns in ${filename}`);
805
842
  }
@@ -999,11 +1036,13 @@ function NuxtScriptBundleTransformer(options = {
999
1036
  const { url: _url, filename } = normalizeScriptData(src, options.assetsBaseURL);
1000
1037
  const script = options.scripts?.find((s2) => s2.import.name === fnName);
1001
1038
  const proxyConfigKey = script?.proxy !== false ? script?.proxy || registryKey : void 0;
1002
- const proxyRewrites = options.firstPartyEnabled && !firstPartyOptOut && proxyConfigKey && options.firstPartyCollectPrefix ? getProxyConfig(proxyConfigKey, options.firstPartyCollectPrefix)?.rewrite : void 0;
1039
+ const proxyConfig = !firstPartyOptOut && proxyConfigKey ? options.proxyConfigs?.[proxyConfigKey] : void 0;
1040
+ const proxyRewrites = proxyConfig?.rewrite;
1041
+ const postProcess = proxyConfig?.postProcess;
1003
1042
  deferredOps.push(async () => {
1004
1043
  let url = _url;
1005
1044
  try {
1006
- await downloadScript({ src, url, filename, forceDownload, proxyRewrites, integrity: options.integrity }, renderedScript, options.fetchOptions, options.cacheMaxAge);
1045
+ await downloadScript({ src, url, filename, forceDownload, proxyRewrites, postProcess, integrity: options.integrity }, renderedScript, options.fetchOptions, options.cacheMaxAge);
1007
1046
  } catch (e) {
1008
1047
  if (options.fallbackOnSrcOnBundleFail) {
1009
1048
  logger.warn(`[Nuxt Scripts: Bundle Transformer] Failed to bundle ${src}. Fallback to remote loading.`);
@@ -1176,18 +1215,18 @@ function templatePlugin(config, registry) {
1176
1215
  let needsInteractionImport = false;
1177
1216
  let needsServiceWorkerImport = false;
1178
1217
  for (const [k, c] of Object.entries(config.registry || {})) {
1218
+ if (c === false)
1219
+ continue;
1179
1220
  const importDefinition = registry.find((i) => i.import.name.toLowerCase() === `usescript${k.toLowerCase()}`);
1180
1221
  if (importDefinition) {
1181
1222
  resolvedRegistryKeys.push(k);
1182
1223
  imports.unshift(`import { ${importDefinition.import.name} } from '${importDefinition.import.from}'`);
1183
- if (c === "mock") {
1184
- inits.push(`const ${k} = ${importDefinition.import.name}({ scriptOptions: { trigger: 'manual', skipValidation: true } })`);
1185
- } else if (Array.isArray(c) && c.length === 2) {
1186
- const input = c[0] || {};
1187
- const scriptOptions = { ...c[1] };
1188
- const triggerResolved = resolveTriggerForTemplate(scriptOptions?.trigger);
1224
+ const [input, scriptOptions] = c;
1225
+ if (scriptOptions) {
1226
+ const opts = { ...scriptOptions };
1227
+ const triggerResolved = resolveTriggerForTemplate(opts.trigger);
1189
1228
  if (triggerResolved) {
1190
- scriptOptions.trigger = "__TRIGGER_PLACEHOLDER__";
1229
+ opts.trigger = "__TRIGGER_PLACEHOLDER__";
1191
1230
  if (triggerResolved.includes("useScriptTriggerIdleTimeout"))
1192
1231
  needsIdleTimeoutImport = true;
1193
1232
  if (triggerResolved.includes("useScriptTriggerInteraction"))
@@ -1195,12 +1234,11 @@ function templatePlugin(config, registry) {
1195
1234
  if (triggerResolved.includes("useScriptTriggerServiceWorker"))
1196
1235
  needsServiceWorkerImport = true;
1197
1236
  }
1198
- const args = { ...input, scriptOptions };
1237
+ const args = { ...input, scriptOptions: opts };
1199
1238
  const argsJson = triggerResolved ? JSON.stringify(args).replace(TRIGGER_PLACEHOLDER_RE, triggerResolved) : JSON.stringify(args);
1200
1239
  inits.push(`const ${k} = ${importDefinition.import.name}(${argsJson})`);
1201
1240
  } else {
1202
- const args = (typeof c !== "object" ? {} : c) || {};
1203
- inits.push(`const ${k} = ${importDefinition.import.name}(${JSON.stringify(args)})`);
1241
+ inits.push(`const ${k} = ${importDefinition.import.name}(${JSON.stringify(input)})`);
1204
1242
  }
1205
1243
  }
1206
1244
  }
@@ -1321,6 +1359,7 @@ function fixSelfClosingScriptComponents(nuxt) {
1321
1359
  }
1322
1360
  }
1323
1361
  const REGISTRY_ENV_DEFAULTS = {
1362
+ bingUet: { id: "" },
1324
1363
  clarity: { id: "" },
1325
1364
  cloudflareWebAnalytics: { token: "" },
1326
1365
  crisp: { id: "" },
@@ -1335,6 +1374,7 @@ const REGISTRY_ENV_DEFAULTS = {
1335
1374
  hotjar: { id: "" },
1336
1375
  intercom: { app_id: "" },
1337
1376
  matomoAnalytics: { matomoUrl: "" },
1377
+ mixpanelAnalytics: { token: "" },
1338
1378
  metaPixel: { id: "" },
1339
1379
  paypal: { clientId: "" },
1340
1380
  plausibleAnalytics: { domain: "" },
@@ -1350,12 +1390,14 @@ const REGISTRY_ENV_DEFAULTS = {
1350
1390
  xPixel: { id: "" }
1351
1391
  };
1352
1392
  const PARTYTOWN_FORWARDS = {
1393
+ bingUet: ["uetq.push"],
1353
1394
  googleAnalytics: ["dataLayer.push", "gtag"],
1354
- plausible: ["plausible"],
1355
- fathom: ["fathom", "fathom.trackEvent", "fathom.trackPageview"],
1356
- umami: ["umami", "umami.track"],
1357
- matomo: ["_paq.push"],
1395
+ plausibleAnalytics: ["plausible"],
1396
+ fathomAnalytics: ["fathom", "fathom.trackEvent", "fathom.trackPageview"],
1397
+ umamiAnalytics: ["umami", "umami.track"],
1398
+ matomoAnalytics: ["_paq.push"],
1358
1399
  segment: ["analytics", "analytics.track", "analytics.page", "analytics.identify"],
1400
+ mixpanelAnalytics: ["mixpanel", "mixpanel.init", "mixpanel.track", "mixpanel.identify", "mixpanel.people.set", "mixpanel.reset", "mixpanel.register"],
1359
1401
  metaPixel: ["fbq"],
1360
1402
  xPixel: ["twq"],
1361
1403
  tiktokPixel: ["ttq.track", "ttq.page", "ttq.identify"],
@@ -1423,23 +1465,15 @@ const module$1 = defineNuxtModule({
1423
1465
  googleStaticMapsProxy: googleMapsEnabled ? { enabled: true, cacheMaxAge: config.googleStaticMapsProxy?.cacheMaxAge ?? 3600 } : void 0
1424
1466
  };
1425
1467
  if (config.registry) {
1468
+ normalizeRegistryConfig(config.registry);
1426
1469
  nuxt.options.runtimeConfig.public = nuxt.options.runtimeConfig.public || {};
1427
1470
  const registryWithDefaults = {};
1428
- for (const [key, value] of Object.entries(config.registry)) {
1429
- if (value && REGISTRY_ENV_DEFAULTS[key]) {
1430
- const envDefaults = REGISTRY_ENV_DEFAULTS[key];
1431
- if (value === true || value === "mock") {
1432
- registryWithDefaults[key] = { ...envDefaults };
1433
- } else if (typeof value === "object" && !Array.isArray(value)) {
1434
- registryWithDefaults[key] = defu(value, envDefaults);
1435
- } else if (Array.isArray(value)) {
1436
- registryWithDefaults[key] = defu(value[0] || {}, envDefaults);
1437
- } else {
1438
- registryWithDefaults[key] = value;
1439
- }
1440
- } else {
1441
- registryWithDefaults[key] = value;
1442
- }
1471
+ for (const [key, entry] of Object.entries(config.registry)) {
1472
+ if (entry === false)
1473
+ continue;
1474
+ const input = entry[0];
1475
+ const envDefaults = REGISTRY_ENV_DEFAULTS[key];
1476
+ registryWithDefaults[key] = envDefaults ? defu(input, envDefaults) : input;
1443
1477
  }
1444
1478
  nuxt.options.runtimeConfig.public.scripts = defu(
1445
1479
  nuxt.options.runtimeConfig.public.scripts || {},
@@ -1451,7 +1485,7 @@ const module$1 = defineNuxtModule({
1451
1485
  "`scripts.defaultScriptOptions.bundle` is deprecated. Use `scripts.firstParty: true` instead. First-party mode is now enabled by default."
1452
1486
  );
1453
1487
  }
1454
- const firstParty = resolveFirstPartyConfig(config);
1488
+ const firstParty = await setupFirstParty(config, resolvePath);
1455
1489
  const assetsPrefix = firstParty.assetsPrefix;
1456
1490
  if (config.partytown?.length) {
1457
1491
  config.registry = config.registry || {};
@@ -1465,12 +1499,8 @@ const module$1 = defineNuxtModule({
1465
1499
  }
1466
1500
  const reg = config.registry;
1467
1501
  const existing = reg[scriptKey];
1468
- if (Array.isArray(existing)) {
1502
+ if (existing) {
1469
1503
  existing[1] = { ...existing[1], partytown: true };
1470
- } else if (existing && typeof existing === "object" && existing !== true && existing !== "mock") {
1471
- reg[scriptKey] = [existing, { partytown: true }];
1472
- } else if (existing === true || existing === "mock") {
1473
- reg[scriptKey] = [{}, { partytown: true }];
1474
1504
  } else {
1475
1505
  reg[scriptKey] = [{}, { partytown: true }];
1476
1506
  }
@@ -1512,10 +1542,6 @@ const module$1 = defineNuxtModule({
1512
1542
  }
1513
1543
  });
1514
1544
  logger.debug("[nuxt-scripts] First-party config:", firstParty);
1515
- let interceptRules = [];
1516
- if (firstParty.enabled) {
1517
- interceptRules = await setupFirstPartyHandlers(firstParty, resolvePath);
1518
- }
1519
1545
  const scripts = await registry(resolvePath);
1520
1546
  for (const script of scripts) {
1521
1547
  if (script.import?.name) {
@@ -1544,14 +1570,15 @@ const module$1 = defineNuxtModule({
1544
1570
  }
1545
1571
  const { renderedScript } = setupPublicAssetStrategy(config.assets);
1546
1572
  if (firstParty.enabled) {
1547
- finalizeFirstParty({
1573
+ const devtoolsData = finalizeFirstParty({
1548
1574
  firstParty,
1549
- interceptRules,
1550
1575
  registry: config.registry,
1551
1576
  registryScripts,
1552
- registryScriptsWithImport,
1553
1577
  nuxtOptions: nuxt.options
1554
1578
  });
1579
+ if (devtoolsData) {
1580
+ nuxt.options.runtimeConfig.public["nuxt-scripts-devtools"] = devtoolsData;
1581
+ }
1555
1582
  }
1556
1583
  const moduleInstallPromises = /* @__PURE__ */ new Map();
1557
1584
  addBuildPlugin(NuxtScriptsCheckScripts(), {
@@ -1561,8 +1588,7 @@ const module$1 = defineNuxtModule({
1561
1588
  scripts: registryScriptsWithImport,
1562
1589
  registryConfig: nuxt.options.runtimeConfig.public.scripts,
1563
1590
  defaultBundle: firstParty.enabled || config.defaultScriptOptions?.bundle,
1564
- firstPartyEnabled: firstParty.enabled,
1565
- firstPartyCollectPrefix: firstParty.collectPrefix,
1591
+ proxyConfigs: firstParty.proxyConfigs,
1566
1592
  moduleDetected(module) {
1567
1593
  if (nuxt.options.dev && module !== "@nuxt/scripts" && !moduleInstallPromises.has(module) && !hasNuxtModule(module))
1568
1594
  moduleInstallPromises.set(module, () => installNuxtModule(module));
@@ -1596,7 +1622,7 @@ const module$1 = defineNuxtModule({
1596
1622
  });
1597
1623
  }
1598
1624
  if (script.registryKey === "gravatar") {
1599
- const gravatarConfig = typeof config.registry?.gravatar === "object" && !Array.isArray(config.registry.gravatar) ? config.registry.gravatar : {};
1625
+ const gravatarConfig = config.registry?.gravatar?.[0] || {};
1600
1626
  nuxt.options.runtimeConfig.public["nuxt-scripts"] = defu(
1601
1627
  { gravatarProxy: { cacheMaxAge: gravatarConfig.cacheMaxAge ?? 3600 } },
1602
1628
  nuxt.options.runtimeConfig.public["nuxt-scripts"]