@nuxt/scripts 1.2.1 → 1.3.0

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 (41) hide show
  1. package/dist/devtools-client/200.html +1 -1
  2. package/dist/devtools-client/404.html +1 -1
  3. package/dist/devtools-client/_nuxt/BHx4OUbM.js +195 -0
  4. package/dist/devtools-client/_nuxt/CGpx20cA.js +1 -0
  5. package/dist/devtools-client/_nuxt/CrquxyIP.js +1 -0
  6. package/dist/devtools-client/_nuxt/D2og3hsL.js +1 -0
  7. package/dist/devtools-client/_nuxt/DSsHxmoa.js +1 -0
  8. package/dist/devtools-client/_nuxt/DfHxEc1R.js +1 -0
  9. package/dist/devtools-client/_nuxt/HwG19HWB.js +1 -0
  10. package/dist/devtools-client/_nuxt/builds/latest.json +1 -1
  11. package/dist/devtools-client/_nuxt/builds/meta/95e11f41-6ffd-4129-ac40-6ad3d141308e.json +1 -0
  12. package/dist/devtools-client/_nuxt/entry.DehJww9T.css +1 -0
  13. package/dist/devtools-client/_nuxt/error-404.LWbgYmYe.css +1 -0
  14. package/dist/devtools-client/_nuxt/error-500.C19ZIySL.css +1 -0
  15. package/dist/devtools-client/docs/index.html +1 -1
  16. package/dist/devtools-client/first-party/index.html +1 -1
  17. package/dist/devtools-client/index.html +1 -1
  18. package/dist/devtools-client/registry/index.html +1 -1
  19. package/dist/module.d.mts +29 -1
  20. package/dist/module.d.ts +29 -1
  21. package/dist/module.json +1 -1
  22. package/dist/module.mjs +72 -11
  23. package/dist/registry.d.mts +5 -2
  24. package/dist/registry.d.ts +5 -2
  25. package/dist/registry.mjs +4 -2
  26. package/dist/runtime/composables/useScript.js +6 -1
  27. package/dist/runtime/server/proxy-handler.js +3 -2
  28. package/dist/runtime/server/utils/match-domain.js +1 -1
  29. package/dist/runtime/utils.js +10 -1
  30. package/package.json +6 -6
  31. package/dist/devtools-client/_nuxt/BTXw0v4h.js +0 -1
  32. package/dist/devtools-client/_nuxt/Bf6N2ObH.js +0 -1
  33. package/dist/devtools-client/_nuxt/C5Bq9Qgz.js +0 -1
  34. package/dist/devtools-client/_nuxt/CSw0kWhI.js +0 -1
  35. package/dist/devtools-client/_nuxt/DWvCkA0U.js +0 -195
  36. package/dist/devtools-client/_nuxt/TPgAGQc8.js +0 -1
  37. package/dist/devtools-client/_nuxt/builds/meta/32b705e4-fcb6-4eea-92d5-dbdced5169df.json +0 -1
  38. package/dist/devtools-client/_nuxt/dvDf1_6X.js +0 -1
  39. package/dist/devtools-client/_nuxt/entry.VwiedW44.css +0 -1
  40. package/dist/devtools-client/_nuxt/error-404.DBJH6QEN.css +0 -1
  41. package/dist/devtools-client/_nuxt/error-500.BIIPjeaA.css +0 -1
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/__nuxt-scripts/_nuxt/entry.VwiedW44.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-scripts/_nuxt/DWvCkA0U.js"><script type="module" src="/__nuxt-scripts/_nuxt/DWvCkA0U.js" crossorigin></script><script>"use strict";(()=>{const t=window,e=document.documentElement,c=["dark","light"],n=getStorageValue("localStorage","nuxt-color-mode")||"system";let i=n==="system"?u():n;const r=e.getAttribute("data-color-mode-forced");r&&(i=r),l(i),t["__NUXT_COLOR_MODE__"]={preference:n,value:i,getColorScheme:u,addColorScheme:l,removeColorScheme:d};function l(o){const s=""+o+"",a="";e.classList?e.classList.add(s):e.className+=" "+s,a&&e.setAttribute("data-"+a,o)}function d(o){const s=""+o+"",a="";e.classList?e.classList.remove(s):e.className=e.className.replace(new RegExp(s,"g"),""),a&&e.removeAttribute("data-"+a)}function f(o){return t.matchMedia("(prefers-color-scheme"+o+")")}function u(){if(t.matchMedia&&f("").media!=="not all"){for(const o of c)if(f(":"+o).matches)return o}return"light"}})();function getStorageValue(t,e){switch(t){case"localStorage":return window.localStorage.getItem(e);case"sessionStorage":return window.sessionStorage.getItem(e);case"cookie":return getCookie(e);default:return null}}function getCookie(t){const c=("; "+window.document.cookie).split("; "+t+"=");if(c.length===2)return c.pop()?.split(";").shift()}</script></head><body><div id="__nuxt" class="isolate"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-scripts",buildId:"32b705e4-fcb6-4eea-92d5-dbdced5169df",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1780417333058,false]</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/__nuxt-scripts/_nuxt/entry.DehJww9T.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-scripts/_nuxt/BHx4OUbM.js"><script type="module" src="/__nuxt-scripts/_nuxt/BHx4OUbM.js" crossorigin></script><link rel="prefetch" as="script" crossorigin href="/__nuxt-scripts/_nuxt/B8PEiB0p.js"><link rel="prefetch" as="script" crossorigin href="/__nuxt-scripts/_nuxt/Cp-IABpG.js"><link rel="prefetch" as="script" crossorigin href="/__nuxt-scripts/_nuxt/wDzz0qaB.js"><link rel="prefetch" as="script" crossorigin href="/__nuxt-scripts/_nuxt/CVO1_9PV.js"><link rel="prefetch" as="script" crossorigin href="/__nuxt-scripts/_nuxt/D0r3Knsf.js"><link rel="prefetch" as="style" crossorigin href="/__nuxt-scripts/_nuxt/error-500.C19ZIySL.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-scripts/_nuxt/D2og3hsL.js"><script>"use strict";(()=>{const o=window,e=document.documentElement,c=["dark","light"],s=getStorageValue("localStorage","nuxt-color-mode")||"system";let r=s==="system"?f():s;const l=e.getAttribute("data-color-mode-forced");l&&(r=l),i(r),o["__NUXT_COLOR_MODE__"]={preference:s,value:r,getColorScheme:f,addColorScheme:i,removeColorScheme:d};function i(t){const a=""+t+"",n="";e.classList?e.classList.add(a):e.className+=" "+a,n&&e.setAttribute("data-"+n,t)}function d(t){const a=""+t+"",n="";e.classList?e.classList.remove(a):e.className=e.className.replace(new RegExp(a,"g"),""),n&&e.removeAttribute("data-"+n)}function u(t){return o.matchMedia("(prefers-color-scheme"+t+")")}function f(){if(o.matchMedia&&u("").media!=="not all"){for(const t of c)if(u(":"+t).matches)return t}return"light"}})();function getStorageValue(o,e){switch(o){case"localStorage":try{return window.localStorage.getItem(e)}catch{return null}case"sessionStorage":try{return window.sessionStorage.getItem(e)}catch{return null}case"cookie":try{return getCookie(e)}catch{return null}default:return null}}function getCookie(o){const c=("; "+window.document.cookie).split("; "+o+"=");if(c.length===2){const s=c.pop();return s?s.split(";").shift():null}}</script></head><body><div id="__nuxt" class="isolate"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-scripts",buildId:"95e11f41-6ffd-4129-ac40-6ad3d141308e",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1782832582381,false]</script></body></html>
package/dist/module.d.mts CHANGED
@@ -3,6 +3,17 @@ import { FetchOptions } from 'ofetch';
3
3
  import { RegistryScripts, FirstPartyPrivacy, NuxtConfigScriptRegistry, NuxtUseScriptOptionsSerializable, NuxtUseScriptInput, ResolvedProxyAutoInject, ProxyConfig } from '../dist/runtime/types.js';
4
4
  export { FirstPartyPrivacy } from '../dist/runtime/types.js';
5
5
 
6
+ /**
7
+ * Proxy path alias configuration.
8
+ * - `false` / `undefined`: proxy paths use the verbatim third-party hostname
9
+ * (`/_scripts/p/us.i.posthog.com/...`).
10
+ * - `true`: every proxied domain gets a short deterministic opaque alias
11
+ * (`/_scripts/p/a1b2c3d4/...`), so the real hostname never appears in client URLs.
12
+ * - `Record<domain, alias>`: explicit aliases (domain → alias). Domains not listed
13
+ * keep their verbatim hostname.
14
+ */
15
+ type ProxyAliasConfig = boolean | Record<string, string> | undefined;
16
+
6
17
  interface ResolvedProxySecret {
7
18
  secret: string;
8
19
  /** True when the secret exists only in memory (dev-only fallback; won't survive restarts). */
@@ -21,7 +32,7 @@ interface ResolvedProxySecret {
21
32
  */
22
33
  declare function resolveProxySecret(rootDir: string, isDev: boolean, configSecret?: string, autoGenerate?: boolean): ResolvedProxySecret | undefined;
23
34
  declare function isProxyDisabled(registryKey: string, registry?: NuxtConfigScriptRegistry, runtimeConfig?: Record<string, any>): boolean;
24
- declare function applyAutoInject(registry: NuxtConfigScriptRegistry, runtimeConfig: Record<string, any>, proxyPrefix: string, registryKey: string, autoInject: ResolvedProxyAutoInject): void;
35
+ declare function applyAutoInject(registry: NuxtConfigScriptRegistry, runtimeConfig: Record<string, any>, proxyPrefix: string, registryKey: string, autoInject: ResolvedProxyAutoInject, alias?: ProxyAliasConfig): void;
25
36
  declare function resolveConfiguredProxyDomains(config: Record<string, any> | undefined, proxyConfig?: Pick<ProxyConfig, 'autoInject' | 'configDomainFields'>): string[];
26
37
  /**
27
38
  * Compute missing required fields for a registry entry, using the merged
@@ -50,6 +61,23 @@ interface ModuleOptions {
50
61
  * @default undefined (per-script defaults)
51
62
  */
52
63
  privacy?: FirstPartyPrivacy;
64
+ /**
65
+ * First-party proxy behaviour.
66
+ */
67
+ proxy?: {
68
+ /**
69
+ * Replace third-party hostnames in proxy paths with aliases, so the real domain
70
+ * (e.g. a self-hosted analytics host) never appears in client-facing URLs.
71
+ *
72
+ * - `false` (default): paths embed the verbatim hostname (`/_scripts/p/us.i.posthog.com/...`)
73
+ * - `true`: auto-generate a short opaque alias per domain (`/_scripts/p/a1b2c3d4/...`)
74
+ * - `Record<domain, alias>`: explicit aliases (domain → alias); unlisted domains stay verbatim
75
+ *
76
+ * @default false
77
+ * @example { 'us.i.posthog.com': 'ph', 'analytics.internal.example.com': 'a' }
78
+ */
79
+ alias?: ProxyAliasConfig;
80
+ };
53
81
  /**
54
82
  * The registry of supported third-party scripts. Presence enables infrastructure (proxy routes, types, bundling, composable auto-imports).
55
83
  * Scripts only auto-load globally when `trigger` is explicitly set in the config object.
package/dist/module.d.ts CHANGED
@@ -3,6 +3,17 @@ import { FetchOptions } from 'ofetch';
3
3
  import { RegistryScripts, FirstPartyPrivacy, NuxtConfigScriptRegistry, NuxtUseScriptOptionsSerializable, NuxtUseScriptInput, ResolvedProxyAutoInject, ProxyConfig } from '../dist/runtime/types.js';
4
4
  export { FirstPartyPrivacy } from '../dist/runtime/types.js';
5
5
 
6
+ /**
7
+ * Proxy path alias configuration.
8
+ * - `false` / `undefined`: proxy paths use the verbatim third-party hostname
9
+ * (`/_scripts/p/us.i.posthog.com/...`).
10
+ * - `true`: every proxied domain gets a short deterministic opaque alias
11
+ * (`/_scripts/p/a1b2c3d4/...`), so the real hostname never appears in client URLs.
12
+ * - `Record<domain, alias>`: explicit aliases (domain → alias). Domains not listed
13
+ * keep their verbatim hostname.
14
+ */
15
+ type ProxyAliasConfig = boolean | Record<string, string> | undefined;
16
+
6
17
  interface ResolvedProxySecret {
7
18
  secret: string;
8
19
  /** True when the secret exists only in memory (dev-only fallback; won't survive restarts). */
@@ -21,7 +32,7 @@ interface ResolvedProxySecret {
21
32
  */
22
33
  declare function resolveProxySecret(rootDir: string, isDev: boolean, configSecret?: string, autoGenerate?: boolean): ResolvedProxySecret | undefined;
23
34
  declare function isProxyDisabled(registryKey: string, registry?: NuxtConfigScriptRegistry, runtimeConfig?: Record<string, any>): boolean;
24
- declare function applyAutoInject(registry: NuxtConfigScriptRegistry, runtimeConfig: Record<string, any>, proxyPrefix: string, registryKey: string, autoInject: ResolvedProxyAutoInject): void;
35
+ declare function applyAutoInject(registry: NuxtConfigScriptRegistry, runtimeConfig: Record<string, any>, proxyPrefix: string, registryKey: string, autoInject: ResolvedProxyAutoInject, alias?: ProxyAliasConfig): void;
25
36
  declare function resolveConfiguredProxyDomains(config: Record<string, any> | undefined, proxyConfig?: Pick<ProxyConfig, 'autoInject' | 'configDomainFields'>): string[];
26
37
  /**
27
38
  * Compute missing required fields for a registry entry, using the merged
@@ -50,6 +61,23 @@ interface ModuleOptions {
50
61
  * @default undefined (per-script defaults)
51
62
  */
52
63
  privacy?: FirstPartyPrivacy;
64
+ /**
65
+ * First-party proxy behaviour.
66
+ */
67
+ proxy?: {
68
+ /**
69
+ * Replace third-party hostnames in proxy paths with aliases, so the real domain
70
+ * (e.g. a self-hosted analytics host) never appears in client-facing URLs.
71
+ *
72
+ * - `false` (default): paths embed the verbatim hostname (`/_scripts/p/us.i.posthog.com/...`)
73
+ * - `true`: auto-generate a short opaque alias per domain (`/_scripts/p/a1b2c3d4/...`)
74
+ * - `Record<domain, alias>`: explicit aliases (domain → alias); unlisted domains stay verbatim
75
+ *
76
+ * @default false
77
+ * @example { 'us.i.posthog.com': 'ph', 'analytics.internal.example.com': 'a' }
78
+ */
79
+ alias?: ProxyAliasConfig;
80
+ };
53
81
  /**
54
82
  * The registry of supported third-party scripts. Presence enables infrastructure (proxy routes, types, bundling, composable auto-imports).
55
83
  * Scripts only auto-load globally when `trigger` is explicitly set in the config object.
package/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": ">=3.16"
6
6
  },
7
- "version": "1.2.1",
7
+ "version": "1.3.0",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.2",
10
10
  "unbuild": "3.6.1"
package/dist/module.mjs CHANGED
@@ -196,7 +196,7 @@ function buildDevtoolsEntry(key, script, configKey, proxyConfig) {
196
196
  domains: [...proxyConfig.domains]
197
197
  };
198
198
  }
199
- function buildDevtoolsData(proxyPrefix, privacyLabel, scripts) {
199
+ function buildDevtoolsData(proxyPrefix, privacyLabel, scripts, aliasToDomain) {
200
200
  const allDomains = /* @__PURE__ */ new Set();
201
201
  for (const s of scripts) {
202
202
  for (const d of s.domains)
@@ -207,7 +207,8 @@ function buildDevtoolsData(proxyPrefix, privacyLabel, scripts) {
207
207
  proxyPrefix,
208
208
  privacyMode: privacyLabel,
209
209
  scripts,
210
- totalDomains: allDomains.size
210
+ totalDomains: allDomains.size,
211
+ aliasToDomain
211
212
  };
212
213
  }
213
214
 
@@ -428,6 +429,7 @@ function generateInterceptPluginContents(proxyPrefix, options) {
428
429
  enforce: 'pre',
429
430
  setup() {
430
431
  const proxyPrefix = ${JSON.stringify(proxyPrefix)};
432
+ const domainAliases = ${JSON.stringify(options?.domainAliases ?? {})};
431
433
  const origBeacon = typeof navigator !== 'undefined' && navigator.sendBeacon
432
434
  ? navigator.sendBeacon.bind(navigator)
433
435
  : () => false;
@@ -436,8 +438,10 @@ function generateInterceptPluginContents(proxyPrefix, options) {
436
438
  function proxyUrl(url) {
437
439
  try {
438
440
  const parsed = new URL(url, location.origin);
439
- if (parsed.origin !== location.origin)
440
- return location.origin + proxyPrefix + '/' + parsed.host + parsed.pathname + parsed.search;
441
+ if (parsed.origin !== location.origin) {
442
+ const seg = domainAliases[parsed.host] || parsed.host;
443
+ return location.origin + proxyPrefix + '/' + seg + parsed.pathname + parsed.search;
444
+ }
441
445
  } catch {}
442
446
  return url;
443
447
  }
@@ -1078,7 +1082,7 @@ function NuxtScriptBundleTransformer(options = {
1078
1082
  const proxyConfig = !firstPartyOptOut && proxyConfigKey ? options.proxyConfigs?.[proxyConfigKey] : void 0;
1079
1083
  const proxyRewrites = proxyConfig?.domains?.filter((domain) => !domain.includes("*")).map((domain) => ({
1080
1084
  from: domain,
1081
- to: `${options.proxyPrefix}/${domain}`
1085
+ to: `${options.proxyPrefix}/${options.domainAliases?.[domain] ?? domain}`
1082
1086
  }));
1083
1087
  const bundleConfig = typeof script?.bundle === "object" ? script.bundle : void 0;
1084
1088
  const sdkPatches = proxyConfig?.sdkPatches ?? bundleConfig?.sdkPatches;
@@ -1170,6 +1174,45 @@ function NuxtScriptBundleTransformer(options = {
1170
1174
  });
1171
1175
  }
1172
1176
 
1177
+ const WILDCARD_RE = /\*/;
1178
+ const SAFE_ALIAS_SEGMENT_RE = /^[\w.-]+$/;
1179
+ function isSafeAliasSegment(alias) {
1180
+ return SAFE_ALIAS_SEGMENT_RE.test(alias);
1181
+ }
1182
+ function aliasForDomain(domain, alias) {
1183
+ if (!alias || WILDCARD_RE.test(domain))
1184
+ return void 0;
1185
+ if (alias === true)
1186
+ return createHash("sha256").update(domain).digest("hex").slice(0, 12);
1187
+ return Object.hasOwn(alias, domain) ? alias[domain] || void 0 : void 0;
1188
+ }
1189
+ function buildDomainAliasMap(domains, alias) {
1190
+ const map = {};
1191
+ for (const domain of domains) {
1192
+ const value = aliasForDomain(domain, alias);
1193
+ if (value)
1194
+ map[domain] = value;
1195
+ }
1196
+ return map;
1197
+ }
1198
+ function invertAliasMap(map) {
1199
+ const out = {};
1200
+ for (const [domain, alias] of Object.entries(map))
1201
+ out[alias] = domain;
1202
+ return out;
1203
+ }
1204
+ function aliasProxyValue(value, proxyPrefix, alias) {
1205
+ const prefix = `${proxyPrefix}/`;
1206
+ if (!alias || !value.startsWith(prefix))
1207
+ return value;
1208
+ const rest = value.slice(prefix.length);
1209
+ const host = rest.match(/^[^/?#]+/)?.[0];
1210
+ if (!host)
1211
+ return value;
1212
+ const aliased = aliasForDomain(host, alias);
1213
+ return aliased ? `${prefix}${aliased}${rest.slice(host.length)}` : value;
1214
+ }
1215
+
1173
1216
  const TRIGGER_PLACEHOLDER_RE = /"__TRIGGER_PLACEHOLDER__"/g;
1174
1217
  function registerTypeTemplates({ config, newScripts }) {
1175
1218
  addTypeTemplate({
@@ -1646,7 +1689,7 @@ function isProxyDisabled(registryKey, registry2, runtimeConfig) {
1646
1689
  }
1647
1690
  return false;
1648
1691
  }
1649
- function applyAutoInject(registry2, runtimeConfig, proxyPrefix, registryKey, autoInject) {
1692
+ function applyAutoInject(registry2, runtimeConfig, proxyPrefix, registryKey, autoInject, alias) {
1650
1693
  if (isProxyDisabled(registryKey, registry2, runtimeConfig))
1651
1694
  return;
1652
1695
  const entry = registry2[registryKey];
@@ -1656,7 +1699,7 @@ function applyAutoInject(registry2, runtimeConfig, proxyPrefix, registryKey, aut
1656
1699
  const config = rtEntry && typeof rtEntry === "object" ? rtEntry : input;
1657
1700
  if (!config || config[autoInject.configField])
1658
1701
  return;
1659
- const value = autoInject.computeValue(proxyPrefix, config);
1702
+ const value = aliasProxyValue(autoInject.computeValue(proxyPrefix, config), proxyPrefix, alias);
1660
1703
  input[autoInject.configField] = value;
1661
1704
  if (rtEntry && typeof rtEntry === "object" && rtEntry !== input)
1662
1705
  rtEntry[autoInject.configField] = value;
@@ -1991,6 +2034,8 @@ const module$1 = defineNuxtModule({
1991
2034
  }
1992
2035
  }
1993
2036
  }
2037
+ const proxyAlias = config.proxy?.alias;
2038
+ let domainAliases = {};
1994
2039
  if (anyNeedsProxy) {
1995
2040
  const builtConfigs = buildProxyConfigsFromRegistry(registryScripts, scriptByKey);
1996
2041
  Object.assign(proxyConfigs, builtConfigs);
@@ -2030,7 +2075,7 @@ const module$1 = defineNuxtModule({
2030
2075
  }
2031
2076
  }
2032
2077
  if (proxyConfig.autoInject && config.registry)
2033
- applyAutoInject(config.registry, nuxt.options.runtimeConfig, proxyPrefix, key, proxyConfig.autoInject);
2078
+ applyAutoInject(config.registry, nuxt.options.runtimeConfig, proxyPrefix, key, proxyConfig.autoInject, proxyAlias);
2034
2079
  if (nuxt.options.dev)
2035
2080
  devtoolsScripts.push(buildDevtoolsEntry(key, script, configKey, proxyConfig));
2036
2081
  }
@@ -2046,15 +2091,30 @@ These scripts will not have proxy routes registered.`
2046
2091
  They will load directly from third-party servers.`
2047
2092
  );
2048
2093
  }
2094
+ domainAliases = buildDomainAliasMap(Object.keys(domainPrivacy), proxyAlias);
2095
+ const realDomains = new Set(Object.keys(domainPrivacy));
2096
+ const aliasOwner = /* @__PURE__ */ new Map();
2097
+ for (const [domain, alias] of Object.entries(domainAliases)) {
2098
+ if (!isSafeAliasSegment(alias))
2099
+ throw new Error(`[nuxt-scripts] Invalid proxy alias "${alias}" for "${domain}": use a single URL-safe path segment (letters, digits, '-', '_', '.').`);
2100
+ if (realDomains.has(alias))
2101
+ throw new Error(`[nuxt-scripts] Proxy alias "${alias}" for "${domain}" collides with proxied domain "${alias}". Pick an alias that is not also a proxied hostname.`);
2102
+ const prev = aliasOwner.get(alias);
2103
+ if (prev)
2104
+ throw new Error(`[nuxt-scripts] Proxy alias collision: "${prev}" and "${domain}" both map to "${alias}". Give each domain a unique alias.`);
2105
+ aliasOwner.set(alias, domain);
2106
+ }
2107
+ const aliasToDomain = invertAliasMap(domainAliases);
2049
2108
  addPluginTemplate({
2050
2109
  filename: "nuxt-scripts-intercept.client.mjs",
2051
2110
  getContents() {
2052
- return generateInterceptPluginContents(proxyPrefix, { testMode: !!nuxt.options.test });
2111
+ return generateInterceptPluginContents(proxyPrefix, { testMode: !!nuxt.options.test, domainAliases });
2053
2112
  }
2054
2113
  });
2055
2114
  nuxt.options.runtimeConfig["nuxt-scripts-proxy"] = {
2056
2115
  proxyPrefix,
2057
2116
  domainPrivacy,
2117
+ aliasToDomain,
2058
2118
  privacy: config.privacy
2059
2119
  };
2060
2120
  const privacyLabel = config.privacy === void 0 ? "per-script" : typeof config.privacy === "boolean" ? config.privacy ? "anonymize" : "passthrough" : "custom";
@@ -2071,12 +2131,12 @@ Options: configure platform rewrites, switch to server-rendered mode, or disable
2071
2131
  );
2072
2132
  }
2073
2133
  if (nuxt.options.dev) {
2074
- nuxt.options.runtimeConfig.public["nuxt-scripts-devtools"] = buildDevtoolsData(proxyPrefix, privacyLabel, devtoolsScripts);
2134
+ nuxt.options.runtimeConfig.public["nuxt-scripts-devtools"] = buildDevtoolsData(proxyPrefix, privacyLabel, devtoolsScripts, aliasToDomain);
2075
2135
  }
2076
2136
  if (partytownScripts.size && hasNuxtModule("@nuxtjs/partytown")) {
2077
2137
  const partytownConfig = nuxt.options.partytown || {};
2078
2138
  if (!partytownConfig.resolveUrl) {
2079
- partytownConfig.resolveUrl = generatePartytownResolveUrl(proxyPrefix);
2139
+ partytownConfig.resolveUrl = generatePartytownResolveUrl(proxyPrefix, domainAliases);
2080
2140
  nuxt.options.partytown = partytownConfig;
2081
2141
  logger.info("[partytown] Auto-configured resolveUrl for proxy");
2082
2142
  } else {
@@ -2093,6 +2153,7 @@ Options: configure platform rewrites, switch to server-rendered mode, or disable
2093
2153
  registryConfig: nuxt.options.runtimeConfig.public.scripts,
2094
2154
  proxyConfigs,
2095
2155
  proxyPrefix,
2156
+ domainAliases,
2096
2157
  partytownScripts,
2097
2158
  moduleDetected(module) {
2098
2159
  if (nuxt.options.dev && module !== "@nuxt/scripts" && !moduleInstallPromises.has(module) && !hasNuxtModule(module))
@@ -71,9 +71,12 @@ declare function registry(resolve?: (path: string) => Promise<string>): Promise<
71
71
  /**
72
72
  * Generate a Partytown `resolveUrl` function string for proxy routing.
73
73
  * Partytown calls this for every network request made by worker-executed scripts.
74
- * Any non-same-origin URL is proxied through `proxyPrefix/<host><path>`.
74
+ * Any non-same-origin URL is proxied through `proxyPrefix/<host-or-alias><path>`.
75
+ *
76
+ * `domainAliases` (real domain → path alias) is embedded so worker requests use the
77
+ * same opaque path segment as build-time rewrites, keeping hostnames out of URLs.
75
78
  */
76
- declare function generatePartytownResolveUrl(proxyPrefix: string): string;
79
+ declare function generatePartytownResolveUrl(proxyPrefix: string, domainAliases?: Record<string, string>): string;
77
80
  /**
78
81
  * Resolve the effective capabilities for a script by merging:
79
82
  * 1. Derive ceiling from script's bundle/proxy/partytown keys
@@ -71,9 +71,12 @@ declare function registry(resolve?: (path: string) => Promise<string>): Promise<
71
71
  /**
72
72
  * Generate a Partytown `resolveUrl` function string for proxy routing.
73
73
  * Partytown calls this for every network request made by worker-executed scripts.
74
- * Any non-same-origin URL is proxied through `proxyPrefix/<host><path>`.
74
+ * Any non-same-origin URL is proxied through `proxyPrefix/<host-or-alias><path>`.
75
+ *
76
+ * `domainAliases` (real domain → path alias) is embedded so worker requests use the
77
+ * same opaque path segment as build-time rewrites, keeping hostnames out of URLs.
75
78
  */
76
- declare function generatePartytownResolveUrl(proxyPrefix: string): string;
79
+ declare function generatePartytownResolveUrl(proxyPrefix: string, domainAliases?: Record<string, string>): string;
77
80
  /**
78
81
  * Resolve the effective capabilities for a script by merging:
79
82
  * 1. Derive ceiling from script's bundle/proxy/partytown keys
package/dist/registry.mjs CHANGED
@@ -800,10 +800,12 @@ async function registry(resolve) {
800
800
  })
801
801
  ]);
802
802
  }
803
- function generatePartytownResolveUrl(proxyPrefix) {
803
+ function generatePartytownResolveUrl(proxyPrefix, domainAliases = {}) {
804
804
  return `function(url, location, type) {
805
805
  if (url.origin !== location.origin) {
806
- return new URL(${JSON.stringify(proxyPrefix)} + '/' + url.host + url.pathname + url.search, location.origin);
806
+ var aliases = ${JSON.stringify(domainAliases)};
807
+ var seg = aliases[url.host] || url.host;
808
+ return new URL(${JSON.stringify(proxyPrefix)} + '/' + seg + url.pathname + url.search, location.origin);
807
809
  }
808
810
  }`;
809
811
  }
@@ -29,6 +29,7 @@ function toNetworkRequest(entry, proxyPrefix) {
29
29
  }
30
30
  function createDomainMatcher(domains, proxyPrefix, scriptSrc) {
31
31
  const localHostname = window.location.hostname;
32
+ const aliasToDomain = useRuntimeConfig().public["nuxt-scripts-devtools"]?.aliasToDomain || {};
32
33
  const scriptUrl = (() => {
33
34
  if (!scriptSrc)
34
35
  return "";
@@ -49,7 +50,8 @@ function createDomainMatcher(domains, proxyPrefix, scriptSrc) {
49
50
  const proxyIdx = entryUrl.pathname.indexOf(proxyPath);
50
51
  if (proxyIdx !== -1) {
51
52
  const afterPrefix = entryUrl.pathname.slice(proxyIdx + proxyPath.length);
52
- const proxyDomain = afterPrefix.split("/")[0];
53
+ const proxySegment = afterPrefix.split("/")[0];
54
+ const proxyDomain = proxySegment ? aliasToDomain[proxySegment] || proxySegment : void 0;
53
55
  if (proxyDomain && domains.has(proxyDomain))
54
56
  return true;
55
57
  }
@@ -116,6 +118,9 @@ export function resolveScriptKey(input) {
116
118
  export function useScript(input, options) {
117
119
  input = typeof input === "string" ? { src: input } : input;
118
120
  options = defu(options, useNuxtScriptRuntimeConfig()?.defaultScriptOptions);
121
+ if (!import.meta.client && options.use) {
122
+ options.use = (() => void 0);
123
+ }
119
124
  if (options.partytown) {
120
125
  const src = input.src;
121
126
  if (!src) {
@@ -42,7 +42,7 @@ export default defineEventHandler(async (event) => {
42
42
  statusMessage: "First-party proxy not configured"
43
43
  });
44
44
  }
45
- const { proxyPrefix, domainPrivacy, privacy: globalPrivacy, debug = import.meta.dev } = proxyConfig;
45
+ const { proxyPrefix, domainPrivacy, aliasToDomain, privacy: globalPrivacy, debug = import.meta.dev } = proxyConfig;
46
46
  const path = event.path;
47
47
  const log = debug ? (message, ...args) => {
48
48
  console.debug(message, ...args);
@@ -50,8 +50,9 @@ export default defineEventHandler(async (event) => {
50
50
  };
51
51
  const afterPrefix = path.slice(proxyPrefix.length + 1);
52
52
  const slashIdx = afterPrefix.indexOf("/");
53
- const domain = slashIdx > 0 ? afterPrefix.slice(0, slashIdx) : afterPrefix;
53
+ const segment = slashIdx > 0 ? afterPrefix.slice(0, slashIdx) : afterPrefix;
54
54
  const remainingPath = slashIdx > 0 ? afterPrefix.slice(slashIdx) : "/";
55
+ const domain = aliasToDomain && Object.hasOwn(aliasToDomain, segment) ? aliasToDomain[segment] : segment;
55
56
  if (!domain) {
56
57
  log("[proxy] No domain in path:", path);
57
58
  throw createError({
@@ -3,7 +3,7 @@ const SUBDOMAIN_LABEL_RE = /^[^.]+$/;
3
3
  export function matchDomain(domain, pattern) {
4
4
  if (!pattern.includes("*"))
5
5
  return domain === pattern || domain.endsWith(`.${pattern}`);
6
- if (pattern.startsWith("*.") && pattern.indexOf("*") === 0) {
6
+ if (pattern.startsWith("*.") && pattern.startsWith("*")) {
7
7
  const suffix = pattern.slice(2);
8
8
  if (!domain.endsWith(`.${suffix}`))
9
9
  return false;
@@ -19,6 +19,12 @@ function validateScriptInputSchema(schema, options) {
19
19
  }
20
20
  return null;
21
21
  }
22
+ function resolveClientUse(use) {
23
+ if (!import.meta.client && use) {
24
+ return (() => void 0);
25
+ }
26
+ return use;
27
+ }
22
28
  export function scriptRuntimeConfig(key) {
23
29
  return (useRuntimeConfig().public.scripts || {})[key];
24
30
  }
@@ -41,7 +47,7 @@ export function useRegistryScript(registryKey, optionsFn, _userOptions) {
41
47
  if (options.scriptMode === "npm") {
42
48
  return createNpmScriptStub({
43
49
  key: String(registryKey),
44
- use: options.scriptOptions?.use,
50
+ use: resolveClientUse(options.scriptOptions?.use),
45
51
  clientInit: options.clientInit,
46
52
  trigger: userOptions.scriptOptions?.trigger
47
53
  });
@@ -63,6 +69,9 @@ export function useRegistryScript(registryKey, optionsFn, _userOptions) {
63
69
  }
64
70
  const scriptInput = defu(finalScriptInput, userOptions.scriptInput, { key: registryKey });
65
71
  const scriptOptions = { ...userOptions?.scriptOptions, ...options.scriptOptions };
72
+ if (scriptOptions.use) {
73
+ scriptOptions.use = resolveClientUse(scriptOptions.use);
74
+ }
66
75
  if (import.meta.dev) {
67
76
  const error = new Error("Stack trace for component location");
68
77
  const stack = error.stack?.split("\n");
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nuxt/scripts",
3
3
  "type": "module",
4
- "version": "1.2.1",
4
+ "version": "1.3.0",
5
5
  "description": "Load third-party scripts with better performance, privacy and DX in Nuxt Apps.",
6
6
  "author": {
7
7
  "name": "Harlan Wilton",
@@ -115,7 +115,7 @@
115
115
  "magic-string": "^0.30.21",
116
116
  "ofetch": "^1.5.1",
117
117
  "ohash": "^2.0.11",
118
- "oxc-parser": "^0.134.0",
118
+ "oxc-parser": "^0.137.0",
119
119
  "oxc-walker": "^1.0.0",
120
120
  "pathe": "^2.0.3",
121
121
  "pkg-types": "^2.3.1",
@@ -123,15 +123,15 @@
123
123
  "std-env": "^4.1.0",
124
124
  "ufo": "^1.6.4",
125
125
  "ultrahtml": "^1.6.0",
126
- "unplugin": "^3.0.0",
126
+ "unplugin": "^3.3.0",
127
127
  "unstorage": "^1.17.5",
128
- "valibot": "^1.4.1"
128
+ "valibot": "^1.4.2"
129
129
  },
130
130
  "devDependencies": {
131
- "@nuxt/kit": "^4.4.6",
131
+ "@nuxt/kit": "^4.4.8",
132
132
  "@nuxt/module-builder": "^1.0.2",
133
133
  "@speedcurve/lux": "^4.4.3",
134
- "rollup": "^4.60.4",
134
+ "rollup": "^4.62.2",
135
135
  "unbuild": "^3.6.1",
136
136
  "unimport": "^6.3.0"
137
137
  },
@@ -1 +0,0 @@
1
- import{y as c,a3 as o,s as n,o as l,h as r,p as a}from"./DWvCkA0U.js";const _={class:"h-full max-h-full overflow-hidden"},u=["src","title"],i=c({__name:"DevtoolsDocs",props:{url:{}},setup(e){return(s,t)=>(o(),n("div",_,[l("iframe",{src:e.url,title:`Documentation - ${e.url}`,class:"w-full h-full border-none",style:{"min-height":"calc(100vh - 100px)"}},null,8,u)]))}}),m=Object.assign(i,{__name:"DevtoolsDocs"}),f={};function h(e,s){const t=m;return o(),a(t,{url:"https://scripts.nuxt.com"})}const p=r(f,[["render",h]]);export{p as default};
@@ -1 +0,0 @@
1
- import{h as s,aA as a,a3 as i,s as u,o as t,ai as n,x as c,aJ as l,w as d,_ as f}from"./DWvCkA0U.js";const p={class:"antialiased bg-white dark:bg-[#020420] dark:text-white font-sans grid min-h-screen overflow-hidden place-content-center text-[#020420] tracking-wide"},m={class:"max-w-520px text-center"},h=["textContent"],x=["textContent"],b=["textContent"],g={class:"flex items-center justify-center w-full"},y={__name:"error-404",props:{appName:{type:String,default:"Nuxt"},status:{type:Number,default:404},statusText:{type:String,default:"Page not found"},description:{type:String,default:"Sorry, the page you are looking for could not be found."},backHome:{type:String,default:"Go back home"}},setup(e){const r=e;return a({title:`${r.status} - ${r.statusText} | ${r.appName}`,script:[{innerHTML:`!function(){const e=document.createElement("link").relList;if(!(e&&e.supports&&e.supports("modulepreload"))){for(const e of document.querySelectorAll('link[rel="modulepreload"]'))r(e);new MutationObserver(e=>{for(const o of e)if("childList"===o.type)for(const e of o.addedNodes)"LINK"===e.tagName&&"modulepreload"===e.rel&&r(e)}).observe(document,{childList:!0,subtree:!0})}function r(e){if(e.ep)return;e.ep=!0;const r=function(e){const r={};return e.integrity&&(r.integrity=e.integrity),e.referrerPolicy&&(r.referrerPolicy=e.referrerPolicy),"use-credentials"===e.crossOrigin?r.credentials="include":"anonymous"===e.crossOrigin?r.credentials="omit":r.credentials="same-origin",r}(e);fetch(e.href,r)}}();`}],style:[{innerHTML:'*,:after,:before{box-sizing:border-box;border-width:0;border-style:solid;border-color:var(--un-default-border-color,#e5e7eb)}:after,:before{--un-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}h1,h2{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}h1,h2,p{margin:0}*,:after,:before{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 transparent;--un-ring-shadow:0 0 transparent;--un-shadow-inset: ;--un-shadow:0 0 transparent;--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgba(147,197,253,.5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }'}]}),(k,w)=>{const o=f;return i(),u("div",p,[t("div",m,[t("h1",{class:"font-semibold leading-none mb-4 sm:text-[110px] tabular-nums text-[80px]",textContent:n(e.status)},null,8,h),t("h2",{class:"font-semibold mb-2 sm:text-3xl text-2xl",textContent:n(e.statusText)},null,8,x),t("p",{class:"mb-4 px-2 text-[#64748B] text-md",textContent:n(e.description)},null,8,b),t("div",g,[c(o,{to:"/",class:"font-medium hover:text-[#00DC82] text-sm underline underline-offset-3"},{default:l(()=>[d(n(e.backHome),1)]),_:1})])])])}}},v=s(y,[["__scopeId","data-v-d10dcac5"]]);export{v as default};