@nuxt/scripts 1.0.0-beta.23 → 1.0.0-beta.25

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 (60) 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/2ec0342e-5e00-4781-82aa-c3c0f9154516.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 +331 -280
  17. package/dist/registry.mjs +121 -71
  18. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsAdvancedMarkerElement.vue +5 -1
  19. package/dist/runtime/composables/useScriptTriggerConsent.d.ts +10 -0
  20. package/dist/runtime/composables/useScriptTriggerConsent.js +32 -19
  21. package/dist/runtime/registry/bing-uet.d.ts +20 -0
  22. package/dist/runtime/registry/bing-uet.js +29 -0
  23. package/dist/runtime/registry/bluesky-embed.d.ts +1 -1
  24. package/dist/runtime/registry/crisp.d.ts +1 -1
  25. package/dist/runtime/registry/fathom-analytics.d.ts +1 -1
  26. package/dist/runtime/registry/google-adsense.d.ts +1 -1
  27. package/dist/runtime/registry/hotjar.d.ts +1 -1
  28. package/dist/runtime/registry/instagram-embed.d.ts +1 -1
  29. package/dist/runtime/registry/intercom.d.ts +1 -1
  30. package/dist/runtime/registry/matomo-analytics.d.ts +1 -1
  31. package/dist/runtime/registry/meta-pixel.d.ts +1 -1
  32. package/dist/runtime/registry/mixpanel-analytics.d.ts +22 -0
  33. package/dist/runtime/registry/mixpanel-analytics.js +46 -0
  34. package/dist/runtime/registry/npm.d.ts +1 -1
  35. package/dist/runtime/registry/reddit-pixel.d.ts +1 -1
  36. package/dist/runtime/registry/schemas.d.ts +19 -0
  37. package/dist/runtime/registry/schemas.js +19 -0
  38. package/dist/runtime/registry/snapchat-pixel.d.ts +1 -1
  39. package/dist/runtime/registry/tiktok-pixel.d.ts +1 -1
  40. package/dist/runtime/registry/vercel-analytics.d.ts +1 -1
  41. package/dist/runtime/registry/x-embed.d.ts +1 -1
  42. package/dist/runtime/registry/x-pixel.d.ts +1 -1
  43. package/dist/runtime/server/proxy-handler.js +36 -23
  44. package/dist/runtime/server/utils/privacy.d.ts +1 -2
  45. package/dist/runtime/server/utils/privacy.js +9 -11
  46. package/dist/runtime/types.d.ts +30 -18
  47. package/dist/runtime/utils/pure.d.ts +1 -1
  48. package/dist/runtime/utils.js +1 -1
  49. package/dist/shared/scripts.ViOoYQXH.mjs +381 -0
  50. package/dist/stats.d.mts +78 -3
  51. package/dist/stats.d.ts +78 -3
  52. package/dist/stats.mjs +2261 -162
  53. package/dist/types-source.mjs +47 -0
  54. package/package.json +13 -13
  55. package/dist/client/_nuxt/BNNMZFwZ.js +0 -162
  56. package/dist/client/_nuxt/builds/meta/39ee5395-65bb-4a46-82e0-e68853f94418.json +0 -1
  57. package/dist/client/_nuxt/entry.CACgbLJl.css +0 -1
  58. package/dist/client/_nuxt/error-404.DMdWw4vT.css +0 -1
  59. package/dist/client/_nuxt/error-500.CROTF27X.css +0 -1
  60. 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';
@@ -10,7 +10,7 @@ import { createStorage } from 'unstorage';
10
10
  import fsDriver from 'unstorage/drivers/fs-lite';
11
11
  import { addCustomTab } from '@nuxt/devtools-kit';
12
12
  import { isCI, provider } from 'std-env';
13
- import { parseAndWalk, ScopeTracker, walk, ScopeTrackerFunctionParam, ScopeTrackerVariable } from 'oxc-walker';
13
+ import { parseAndWalk, ScopeTracker, walk, ScopeTrackerFunction, ScopeTrackerIdentifier, ScopeTrackerFunctionParam, ScopeTrackerVariable } from 'oxc-walker';
14
14
  import { createUnplugin } from 'unplugin';
15
15
  import { pathToFileURL } from 'node:url';
16
16
  import { createHash } from 'node:crypto';
@@ -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) {
@@ -478,9 +522,7 @@ function NuxtScriptsCheckScripts() {
478
522
  }
479
523
 
480
524
  const WORD_OR_DOLLAR_RE = /[\w$]/;
481
- const GA_COLLECT_RE = /([\w$])?"https:\/\/"\+\(.*?\)\+"\.google-analytics\.com\/g\/collect"/g;
482
- const GA_ANALYTICS_COLLECT_RE = /([\w$])?"https:\/\/"\+\(.*?\)\+"\.analytics\.google\.com\/g\/collect"/g;
483
- const FATHOM_SELF_HOSTED_RE = /\.src\.indexOf\("cdn\.usefathom\.com"\)\s*<\s*0/;
525
+ const BLANK_CANVAS_DATA_URL = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQIHWNgAAIABQABNjN9GQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAAA0lEQVQI12NgYGBgAAAABQABXvMqOgAAAABJRU5ErkJggg==";
484
526
  function isPropertyKeyAST(parent, ctx) {
485
527
  return parent?.type === "Property" && ctx.key === "key" || parent?.type === "SwitchCase" && ctx.key === "test";
486
528
  }
@@ -557,12 +599,15 @@ function resolveToGlobal(name, scopeTracker, depth = 0) {
557
599
  return null;
558
600
  if (init.type === "Identifier")
559
601
  return resolveToGlobal(init.name, scopeTracker, depth + 1);
560
- if (init.type === "MemberExpression" && !init.computed && init.object?.type === "Identifier" && init.property?.type === "Identifier") {
602
+ if (init.type === "MemberExpression" && init.object?.type === "Identifier") {
603
+ const memberProp = init.computed ? init.property?.type === "Literal" && typeof init.property.value === "string" ? init.property.value : null : init.property?.type === "Identifier" ? init.property.name : null;
604
+ if (!memberProp)
605
+ return null;
561
606
  const objGlobal = resolveToGlobal(init.object.name, scopeTracker, depth + 1);
562
607
  if (!objGlobal)
563
608
  return null;
564
609
  if (WINDOW_GLOBALS.has(objGlobal) || objGlobal === "document")
565
- return init.property.name;
610
+ return memberProp;
566
611
  return null;
567
612
  }
568
613
  return null;
@@ -594,7 +639,7 @@ function resolveCalleeTarget(callee, scopeTracker) {
594
639
  return "Image";
595
640
  return null;
596
641
  }
597
- function rewriteScriptUrlsAST(content, filename, rewrites) {
642
+ function rewriteScriptUrlsAST(content, filename, rewrites, postProcess) {
598
643
  const s = new MagicString(content);
599
644
  function needsLeadingSpace(start) {
600
645
  const prev = content[start - 1];
@@ -618,9 +663,10 @@ function rewriteScriptUrlsAST(content, filename, rewrites) {
618
663
  s.overwrite(node.start, node.end, `${needsLeadingSpace(node.start)}self.location.origin+${quote}${rewritten}${quote}`);
619
664
  }
620
665
  }
621
- if (node.type === "TemplateLiteral" && node.expressions?.length === 0) {
666
+ if (node.type === "TemplateLiteral") {
622
667
  const quasis = node.quasis;
623
- if (quasis?.length === 1) {
668
+ const expressions = node.expressions;
669
+ if (expressions?.length === 0 && quasis?.length === 1) {
624
670
  const value = quasis[0].value?.cooked ?? quasis[0].value?.raw;
625
671
  if (typeof value !== "string")
626
672
  return;
@@ -632,10 +678,40 @@ function rewriteScriptUrlsAST(content, filename, rewrites) {
632
678
  } else {
633
679
  s.overwrite(node.start, node.end, `${needsLeadingSpace(node.start)}self.location.origin+\`${rewritten}\``);
634
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}`);
635
690
  }
636
691
  }
637
692
  if (node.type === "CallExpression") {
638
693
  const callee = node.callee;
694
+ const canvasPropName = callee?.type === "MemberExpression" ? callee.computed ? callee.property?.type === "Literal" && typeof callee.property.value === "string" ? callee.property.value : null : callee.property?.name : null;
695
+ if (canvasPropName === "toDataURL" && callee.object) {
696
+ const blankCanvas = `"${BLANK_CANVAS_DATA_URL}"`;
697
+ if (callee.object.type === "Identifier") {
698
+ const decl = scopeTracker.getDeclaration(callee.object.name);
699
+ if (decl instanceof ScopeTrackerFunction || decl instanceof ScopeTrackerIdentifier) ; else {
700
+ s.overwrite(node.start, node.end, blankCanvas);
701
+ return;
702
+ }
703
+ } else {
704
+ s.overwrite(node.start, node.end, blankCanvas);
705
+ return;
706
+ }
707
+ }
708
+ if (canvasPropName === "getExtension") {
709
+ const args = node.arguments;
710
+ if (args?.length === 1 && args[0]?.type === "Literal" && args[0].value === "WEBGL_debug_renderer_info") {
711
+ s.overwrite(node.start, node.end, "null");
712
+ return;
713
+ }
714
+ }
639
715
  if (callee?.type === "Identifier" && callee.name === "fetch") {
640
716
  if (!scopeTracker.getDeclaration("fetch"))
641
717
  s.overwrite(callee.start, callee.end, "__nuxtScripts.fetch");
@@ -683,22 +759,8 @@ function rewriteScriptUrlsAST(content, filename, rewrites) {
683
759
  }
684
760
  });
685
761
  let output = s.toString();
686
- const gaRewrite = rewrites.find((r) => r.from.includes("google-analytics.com/g/collect"));
687
- if (gaRewrite) {
688
- output = output.replace(
689
- GA_COLLECT_RE,
690
- (_, prevChar) => `${prevChar ? `${prevChar} ` : ""}self.location.origin+"${gaRewrite.to}"`
691
- );
692
- output = output.replace(
693
- GA_ANALYTICS_COLLECT_RE,
694
- (_, prevChar) => `${prevChar ? `${prevChar} ` : ""}self.location.origin+"${gaRewrite.to}"`
695
- );
696
- }
697
- if (rewrites.some((r) => r.from === "cdn.usefathom.com")) {
698
- output = output.replace(
699
- FATHOM_SELF_HOSTED_RE,
700
- '.src.indexOf("cdn.usefathom.com")<-1'
701
- );
762
+ if (postProcess) {
763
+ output = postProcess(output, rewrites);
702
764
  }
703
765
  return output;
704
766
  }
@@ -736,7 +798,7 @@ function normalizeScriptData(src, assetsBaseURL = "/_scripts/assets") {
736
798
  return { url: src };
737
799
  }
738
800
  async function downloadScript(opts, renderedScript, fetchOptions, cacheMaxAge) {
739
- const { src, url, filename, forceDownload, integrity, proxyRewrites } = opts;
801
+ const { src, url, filename, forceDownload, integrity, proxyRewrites, postProcess } = opts;
740
802
  if (src === url || !filename) {
741
803
  return;
742
804
  }
@@ -774,7 +836,7 @@ async function downloadScript(opts, renderedScript, fetchOptions, cacheMaxAge) {
774
836
  await storage.setItemRaw(`bundle:${filename}`, res);
775
837
  if (proxyRewrites?.length && res) {
776
838
  const content = res.toString("utf-8");
777
- const rewritten = rewriteScriptUrlsAST(content, filename || "script.js", proxyRewrites);
839
+ const rewritten = rewriteScriptUrlsAST(content, filename || "script.js", proxyRewrites, postProcess);
778
840
  res = Buffer.from(rewritten, "utf-8");
779
841
  logger.debug(`Rewrote ${proxyRewrites.length} URL patterns in ${filename}`);
780
842
  }
@@ -974,11 +1036,13 @@ function NuxtScriptBundleTransformer(options = {
974
1036
  const { url: _url, filename } = normalizeScriptData(src, options.assetsBaseURL);
975
1037
  const script = options.scripts?.find((s2) => s2.import.name === fnName);
976
1038
  const proxyConfigKey = script?.proxy !== false ? script?.proxy || registryKey : void 0;
977
- 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;
978
1042
  deferredOps.push(async () => {
979
1043
  let url = _url;
980
1044
  try {
981
- 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);
982
1046
  } catch (e) {
983
1047
  if (options.fallbackOnSrcOnBundleFail) {
984
1048
  logger.warn(`[Nuxt Scripts: Bundle Transformer] Failed to bundle ${src}. Fallback to remote loading.`);
@@ -1151,18 +1215,18 @@ function templatePlugin(config, registry) {
1151
1215
  let needsInteractionImport = false;
1152
1216
  let needsServiceWorkerImport = false;
1153
1217
  for (const [k, c] of Object.entries(config.registry || {})) {
1218
+ if (c === false)
1219
+ continue;
1154
1220
  const importDefinition = registry.find((i) => i.import.name.toLowerCase() === `usescript${k.toLowerCase()}`);
1155
1221
  if (importDefinition) {
1156
1222
  resolvedRegistryKeys.push(k);
1157
1223
  imports.unshift(`import { ${importDefinition.import.name} } from '${importDefinition.import.from}'`);
1158
- if (c === "mock") {
1159
- inits.push(`const ${k} = ${importDefinition.import.name}({ scriptOptions: { trigger: 'manual', skipValidation: true } })`);
1160
- } else if (Array.isArray(c) && c.length === 2) {
1161
- const input = c[0] || {};
1162
- const scriptOptions = { ...c[1] };
1163
- const triggerResolved = resolveTriggerForTemplate(scriptOptions?.trigger);
1224
+ const [input, scriptOptions] = c;
1225
+ if (scriptOptions) {
1226
+ const opts = { ...scriptOptions };
1227
+ const triggerResolved = resolveTriggerForTemplate(opts.trigger);
1164
1228
  if (triggerResolved) {
1165
- scriptOptions.trigger = "__TRIGGER_PLACEHOLDER__";
1229
+ opts.trigger = "__TRIGGER_PLACEHOLDER__";
1166
1230
  if (triggerResolved.includes("useScriptTriggerIdleTimeout"))
1167
1231
  needsIdleTimeoutImport = true;
1168
1232
  if (triggerResolved.includes("useScriptTriggerInteraction"))
@@ -1170,12 +1234,11 @@ function templatePlugin(config, registry) {
1170
1234
  if (triggerResolved.includes("useScriptTriggerServiceWorker"))
1171
1235
  needsServiceWorkerImport = true;
1172
1236
  }
1173
- const args = { ...input, scriptOptions };
1237
+ const args = { ...input, scriptOptions: opts };
1174
1238
  const argsJson = triggerResolved ? JSON.stringify(args).replace(TRIGGER_PLACEHOLDER_RE, triggerResolved) : JSON.stringify(args);
1175
1239
  inits.push(`const ${k} = ${importDefinition.import.name}(${argsJson})`);
1176
1240
  } else {
1177
- const args = (typeof c !== "object" ? {} : c) || {};
1178
- inits.push(`const ${k} = ${importDefinition.import.name}(${JSON.stringify(args)})`);
1241
+ inits.push(`const ${k} = ${importDefinition.import.name}(${JSON.stringify(input)})`);
1179
1242
  }
1180
1243
  }
1181
1244
  }
@@ -1296,6 +1359,7 @@ function fixSelfClosingScriptComponents(nuxt) {
1296
1359
  }
1297
1360
  }
1298
1361
  const REGISTRY_ENV_DEFAULTS = {
1362
+ bingUet: { id: "" },
1299
1363
  clarity: { id: "" },
1300
1364
  cloudflareWebAnalytics: { token: "" },
1301
1365
  crisp: { id: "" },
@@ -1310,6 +1374,7 @@ const REGISTRY_ENV_DEFAULTS = {
1310
1374
  hotjar: { id: "" },
1311
1375
  intercom: { app_id: "" },
1312
1376
  matomoAnalytics: { matomoUrl: "" },
1377
+ mixpanelAnalytics: { token: "" },
1313
1378
  metaPixel: { id: "" },
1314
1379
  paypal: { clientId: "" },
1315
1380
  plausibleAnalytics: { domain: "" },
@@ -1325,12 +1390,14 @@ const REGISTRY_ENV_DEFAULTS = {
1325
1390
  xPixel: { id: "" }
1326
1391
  };
1327
1392
  const PARTYTOWN_FORWARDS = {
1393
+ bingUet: ["uetq.push"],
1328
1394
  googleAnalytics: ["dataLayer.push", "gtag"],
1329
- plausible: ["plausible"],
1330
- fathom: ["fathom", "fathom.trackEvent", "fathom.trackPageview"],
1331
- umami: ["umami", "umami.track"],
1332
- matomo: ["_paq.push"],
1395
+ plausibleAnalytics: ["plausible"],
1396
+ fathomAnalytics: ["fathom", "fathom.trackEvent", "fathom.trackPageview"],
1397
+ umamiAnalytics: ["umami", "umami.track"],
1398
+ matomoAnalytics: ["_paq.push"],
1333
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"],
1334
1401
  metaPixel: ["fbq"],
1335
1402
  xPixel: ["twq"],
1336
1403
  tiktokPixel: ["ttq.track", "ttq.page", "ttq.identify"],
@@ -1398,23 +1465,15 @@ const module$1 = defineNuxtModule({
1398
1465
  googleStaticMapsProxy: googleMapsEnabled ? { enabled: true, cacheMaxAge: config.googleStaticMapsProxy?.cacheMaxAge ?? 3600 } : void 0
1399
1466
  };
1400
1467
  if (config.registry) {
1468
+ normalizeRegistryConfig(config.registry);
1401
1469
  nuxt.options.runtimeConfig.public = nuxt.options.runtimeConfig.public || {};
1402
1470
  const registryWithDefaults = {};
1403
- for (const [key, value] of Object.entries(config.registry)) {
1404
- if (value && REGISTRY_ENV_DEFAULTS[key]) {
1405
- const envDefaults = REGISTRY_ENV_DEFAULTS[key];
1406
- if (value === true || value === "mock") {
1407
- registryWithDefaults[key] = { ...envDefaults };
1408
- } else if (typeof value === "object" && !Array.isArray(value)) {
1409
- registryWithDefaults[key] = defu(value, envDefaults);
1410
- } else if (Array.isArray(value)) {
1411
- registryWithDefaults[key] = defu(value[0] || {}, envDefaults);
1412
- } else {
1413
- registryWithDefaults[key] = value;
1414
- }
1415
- } else {
1416
- registryWithDefaults[key] = value;
1417
- }
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;
1418
1477
  }
1419
1478
  nuxt.options.runtimeConfig.public.scripts = defu(
1420
1479
  nuxt.options.runtimeConfig.public.scripts || {},
@@ -1426,7 +1485,7 @@ const module$1 = defineNuxtModule({
1426
1485
  "`scripts.defaultScriptOptions.bundle` is deprecated. Use `scripts.firstParty: true` instead. First-party mode is now enabled by default."
1427
1486
  );
1428
1487
  }
1429
- const firstParty = resolveFirstPartyConfig(config);
1488
+ const firstParty = await setupFirstParty(config, resolvePath);
1430
1489
  const assetsPrefix = firstParty.assetsPrefix;
1431
1490
  if (config.partytown?.length) {
1432
1491
  config.registry = config.registry || {};
@@ -1440,12 +1499,8 @@ const module$1 = defineNuxtModule({
1440
1499
  }
1441
1500
  const reg = config.registry;
1442
1501
  const existing = reg[scriptKey];
1443
- if (Array.isArray(existing)) {
1502
+ if (existing) {
1444
1503
  existing[1] = { ...existing[1], partytown: true };
1445
- } else if (existing && typeof existing === "object" && existing !== true && existing !== "mock") {
1446
- reg[scriptKey] = [existing, { partytown: true }];
1447
- } else if (existing === true || existing === "mock") {
1448
- reg[scriptKey] = [{}, { partytown: true }];
1449
1504
  } else {
1450
1505
  reg[scriptKey] = [{}, { partytown: true }];
1451
1506
  }
@@ -1487,10 +1542,6 @@ const module$1 = defineNuxtModule({
1487
1542
  }
1488
1543
  });
1489
1544
  logger.debug("[nuxt-scripts] First-party config:", firstParty);
1490
- let interceptRules = [];
1491
- if (firstParty.enabled) {
1492
- interceptRules = await setupFirstPartyHandlers(firstParty, resolvePath);
1493
- }
1494
1545
  const scripts = await registry(resolvePath);
1495
1546
  for (const script of scripts) {
1496
1547
  if (script.import?.name) {
@@ -1519,14 +1570,15 @@ const module$1 = defineNuxtModule({
1519
1570
  }
1520
1571
  const { renderedScript } = setupPublicAssetStrategy(config.assets);
1521
1572
  if (firstParty.enabled) {
1522
- finalizeFirstParty({
1573
+ const devtoolsData = finalizeFirstParty({
1523
1574
  firstParty,
1524
- interceptRules,
1525
1575
  registry: config.registry,
1526
1576
  registryScripts,
1527
- registryScriptsWithImport,
1528
1577
  nuxtOptions: nuxt.options
1529
1578
  });
1579
+ if (devtoolsData) {
1580
+ nuxt.options.runtimeConfig.public["nuxt-scripts-devtools"] = devtoolsData;
1581
+ }
1530
1582
  }
1531
1583
  const moduleInstallPromises = /* @__PURE__ */ new Map();
1532
1584
  addBuildPlugin(NuxtScriptsCheckScripts(), {
@@ -1536,8 +1588,7 @@ const module$1 = defineNuxtModule({
1536
1588
  scripts: registryScriptsWithImport,
1537
1589
  registryConfig: nuxt.options.runtimeConfig.public.scripts,
1538
1590
  defaultBundle: firstParty.enabled || config.defaultScriptOptions?.bundle,
1539
- firstPartyEnabled: firstParty.enabled,
1540
- firstPartyCollectPrefix: firstParty.collectPrefix,
1591
+ proxyConfigs: firstParty.proxyConfigs,
1541
1592
  moduleDetected(module) {
1542
1593
  if (nuxt.options.dev && module !== "@nuxt/scripts" && !moduleInstallPromises.has(module) && !hasNuxtModule(module))
1543
1594
  moduleInstallPromises.set(module, () => installNuxtModule(module));
@@ -1571,7 +1622,7 @@ const module$1 = defineNuxtModule({
1571
1622
  });
1572
1623
  }
1573
1624
  if (script.registryKey === "gravatar") {
1574
- const gravatarConfig = typeof config.registry?.gravatar === "object" && !Array.isArray(config.registry.gravatar) ? config.registry.gravatar : {};
1625
+ const gravatarConfig = config.registry?.gravatar?.[0] || {};
1575
1626
  nuxt.options.runtimeConfig.public["nuxt-scripts"] = defu(
1576
1627
  { gravatarProxy: { cacheMaxAge: gravatarConfig.cacheMaxAge ?? 3600 } },
1577
1628
  nuxt.options.runtimeConfig.public["nuxt-scripts"]