@nuxt/scripts 1.0.0-rc.9 → 1.0.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 (97) 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/{BBS9G2Kb.js → Br5kvbNb.js} +1 -1
  4. package/dist/devtools-client/_nuxt/C25MBdR1.js +1 -0
  5. package/dist/devtools-client/_nuxt/{DCBsJT4N.js → Cg_OIb5q.js} +1 -1
  6. package/dist/devtools-client/_nuxt/{B4uHpJPz.js → D2o5loaz.js} +1 -1
  7. package/dist/devtools-client/_nuxt/De7Wf2b9.js +188 -0
  8. package/dist/devtools-client/_nuxt/{Cxq4HLPL.js → DnVCfhVR.js} +1 -1
  9. package/dist/devtools-client/_nuxt/builds/latest.json +1 -1
  10. package/dist/devtools-client/_nuxt/builds/meta/9d868e70-bc5a-425c-8c84-8defe5186920.json +1 -0
  11. package/dist/devtools-client/_nuxt/{entry.BwpOBArY.css → entry.BSxy0W1q.css} +1 -1
  12. package/dist/devtools-client/_nuxt/index.DZD1lwyI.css +1 -0
  13. package/dist/devtools-client/_nuxt/{DvZScWzI.js → pN4-T8ZD.js} +1 -1
  14. package/dist/devtools-client/docs/index.html +1 -1
  15. package/dist/devtools-client/first-party/index.html +1 -1
  16. package/dist/devtools-client/index.html +1 -1
  17. package/dist/devtools-client/registry/index.html +1 -1
  18. package/dist/module.d.mts +15 -0
  19. package/dist/module.d.ts +15 -0
  20. package/dist/module.json +1 -1
  21. package/dist/module.mjs +35 -8
  22. package/dist/registry.mjs +3 -3
  23. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsStaticMap.vue +6 -2
  24. package/dist/runtime/components/ScriptBlueskyEmbed.d.vue.ts +0 -1
  25. package/dist/runtime/components/ScriptBlueskyEmbed.vue +12 -10
  26. package/dist/runtime/components/ScriptBlueskyEmbed.vue.d.ts +0 -1
  27. package/dist/runtime/components/ScriptInstagramEmbed.vue +3 -1
  28. package/dist/runtime/components/ScriptXEmbed.d.vue.ts +0 -1
  29. package/dist/runtime/components/ScriptXEmbed.vue +11 -9
  30. package/dist/runtime/components/ScriptXEmbed.vue.d.ts +0 -1
  31. package/dist/runtime/composables/useScript.js +17 -6
  32. package/dist/runtime/composables/useScriptProxyToken.d.ts +12 -0
  33. package/dist/runtime/composables/useScriptProxyToken.js +4 -0
  34. package/dist/runtime/composables/useScriptProxyUrl.d.ts +12 -0
  35. package/dist/runtime/composables/useScriptProxyUrl.js +27 -0
  36. package/dist/runtime/plugins/proxy-token.server.d.ts +10 -0
  37. package/dist/runtime/plugins/proxy-token.server.js +17 -0
  38. package/dist/runtime/registry/bing-uet.d.ts +6 -2
  39. package/dist/runtime/registry/bing-uet.js +13 -1
  40. package/dist/runtime/registry/bluesky-embed.d.ts +0 -4
  41. package/dist/runtime/registry/bluesky-embed.js +0 -4
  42. package/dist/runtime/registry/clarity.d.ts +6 -2
  43. package/dist/runtime/registry/clarity.js +12 -1
  44. package/dist/runtime/registry/google-analytics.d.ts +6 -2
  45. package/dist/runtime/registry/google-analytics.js +12 -1
  46. package/dist/runtime/registry/google-tag-manager.d.ts +6 -2
  47. package/dist/runtime/registry/google-tag-manager.js +10 -1
  48. package/dist/runtime/registry/gravatar.js +10 -13
  49. package/dist/runtime/registry/matomo-analytics.d.ts +9 -3
  50. package/dist/runtime/registry/matomo-analytics.js +28 -1
  51. package/dist/runtime/registry/meta-pixel.d.ts +8 -2
  52. package/dist/runtime/registry/meta-pixel.js +10 -1
  53. package/dist/runtime/registry/mixpanel-analytics.d.ts +12 -2
  54. package/dist/runtime/registry/mixpanel-analytics.js +16 -4
  55. package/dist/runtime/registry/posthog.d.ts +8 -2
  56. package/dist/runtime/registry/posthog.js +15 -4
  57. package/dist/runtime/registry/schemas.d.ts +65 -0
  58. package/dist/runtime/registry/schemas.js +75 -8
  59. package/dist/runtime/registry/tiktok-pixel.d.ts +16 -2
  60. package/dist/runtime/registry/tiktok-pixel.js +22 -1
  61. package/dist/runtime/registry/x-embed.d.ts +0 -4
  62. package/dist/runtime/registry/x-embed.js +0 -4
  63. package/dist/runtime/server/bluesky-embed-image.d.ts +1 -1
  64. package/dist/runtime/server/bluesky-embed.d.ts +1 -15
  65. package/dist/runtime/server/bluesky-embed.js +22 -4
  66. package/dist/runtime/server/google-maps-geocode-proxy.js +8 -5
  67. package/dist/runtime/server/google-static-maps-proxy.d.ts +1 -1
  68. package/dist/runtime/server/google-static-maps-proxy.js +13 -8
  69. package/dist/runtime/server/gravatar-proxy.d.ts +1 -1
  70. package/dist/runtime/server/gravatar-proxy.js +6 -7
  71. package/dist/runtime/server/instagram-embed-asset.d.ts +1 -1
  72. package/dist/runtime/server/instagram-embed-image.d.ts +1 -1
  73. package/dist/runtime/server/instagram-embed.js +22 -10
  74. package/dist/runtime/server/utils/cached-upstream.d.ts +55 -0
  75. package/dist/runtime/server/utils/cached-upstream.js +65 -0
  76. package/dist/runtime/server/utils/embed-rewriters.d.ts +19 -0
  77. package/dist/runtime/server/utils/embed-rewriters.js +41 -0
  78. package/dist/runtime/server/utils/image-proxy.d.ts +3 -1
  79. package/dist/runtime/server/utils/image-proxy.js +8 -6
  80. package/dist/runtime/server/utils/instagram-embed.d.ts +4 -4
  81. package/dist/runtime/server/utils/instagram-embed.js +10 -9
  82. package/dist/runtime/server/utils/proxy-url.d.ts +9 -0
  83. package/dist/runtime/server/utils/proxy-url.js +21 -0
  84. package/dist/runtime/server/utils/sign-constants.d.ts +16 -0
  85. package/dist/runtime/server/utils/sign-constants.js +5 -0
  86. package/dist/runtime/server/utils/sign.d.ts +2 -10
  87. package/dist/runtime/server/utils/sign.js +8 -5
  88. package/dist/runtime/server/utils/withSigning.js +3 -2
  89. package/dist/runtime/server/x-embed-image.d.ts +1 -1
  90. package/dist/runtime/server/x-embed.js +20 -2
  91. package/dist/runtime/types.d.ts +24 -1
  92. package/dist/types-source.mjs +104 -11
  93. package/package.json +2 -2
  94. package/dist/devtools-client/_nuxt/CQR4zIAm.js +0 -1
  95. package/dist/devtools-client/_nuxt/DTxy5P8N.js +0 -188
  96. package/dist/devtools-client/_nuxt/builds/meta/bd58b869-1eb5-4c50-871c-707f9b71e8f9.json +0 -1
  97. package/dist/devtools-client/_nuxt/index.CA-OpSj0.css +0 -1
@@ -0,0 +1 @@
1
+ .script-status[data-v-5cf865ba]{align-items:center;border-radius:9999px;display:inline-flex;font-size:.6875rem;font-weight:600;gap:.375rem;letter-spacing:.01em;line-height:1.4;padding:.125rem .5rem}.script-status-dot[data-v-5cf865ba]{border-radius:50%;flex-shrink:0;height:6px;width:6px}.status-loaded[data-v-5cf865ba]{background:#6bc6701f;color:#006818;color:oklch(45% .15 145)}.status-loaded .script-status-dot[data-v-5cf865ba]{background:#11ad32;box-shadow:0 0 6px #11ad3280}.dark .status-loaded[data-v-5cf865ba]{background:#10782326;color:#75d079}.status-loading[data-v-5cf865ba]{background:#70b3f71a;color:#0065b0;color:oklch(50% .15 250)}.status-loading .script-status-dot[data-v-5cf865ba]{animation:pulse-dot-5cf865ba 1.5s ease-in-out infinite;background:#0083e0;background:oklch(60% .18 250)}.dark .status-loading[data-v-5cf865ba]{background:#23588a26;color:#70b3f7}.status-awaiting[data-v-5cf865ba]{background:#d9b9821a;color:#946900;color:oklch(55% .12 80)}.status-awaiting .script-status-dot[data-v-5cf865ba]{background:#cd9200;background:oklch(70% .15 80)}.dark .status-awaiting[data-v-5cf865ba]{background:#67522d26;color:#cfa761}.status-error[data-v-5cf865ba]{background:#ce70691a;color:#a83634}.status-error .script-status-dot[data-v-5cf865ba]{background:#de3b3d}.dark .status-error[data-v-5cf865ba]{background:#843c3826;color:#e6857e}.status-validation[data-v-5cf865ba]{background:#a890d41a;color:#6e519d}.status-validation .script-status-dot[data-v-5cf865ba]{background:#8f68cb}.dark .status-validation[data-v-5cf865ba]{background:#4e3d6c26;color:#b7a0e4}.status-unknown[data-v-5cf865ba]{background:var(--color-surface-sunken);color:var(--color-text-muted)}.status-unknown .script-status-dot[data-v-5cf865ba]{background:var(--color-neutral-400)}@keyframes pulse-dot-5cf865ba{0%,to{opacity:1;transform:scale(1)}50%{opacity:.5;transform:scale(.85)}}.script-metric[data-v-b147450b]{align-items:center;background:var(--color-surface-sunken);border:1px solid var(--color-border-subtle);border-radius:9999px;color:var(--color-text-muted);display:inline-flex;font-family:var(--font-mono);font-size:.6875rem;font-weight:500;gap:.25rem;letter-spacing:-.01em;padding:.125rem .5rem}.script-metric[data-v-c6837c50]{align-items:center;background:#6bc67014;border:1px solid oklch(65% .15 145/.12);border-radius:9999px;color:#2f7434;display:inline-flex;font-family:var(--font-mono);font-size:.6875rem;font-weight:500;gap:.25rem;letter-spacing:-.01em;padding:.125rem .5rem}.dark .script-metric[data-v-c6837c50]{background:#2c63301f;border-color:#49814c26;color:#85cc87}.ui-tooltip-panel[data-v-16948115]{background:var(--color-surface-elevated);border:1px solid var(--color-border);border-radius:var(--radius-md);box-shadow:0 4px 12px #0000001a;color:var(--color-text);font-size:.75rem;font-weight:400;line-height:1.4;padding:.5rem .75rem;pointer-events:none;white-space:normal}.dark .ui-tooltip-panel[data-v-16948115]{box-shadow:0 4px 12px #0000004d}.waterfall-container[data-v-d16c88db]{display:flex;flex-direction:column;gap:.5rem;padding:.75rem}.waterfall-stats[data-v-d16c88db]{align-items:center;display:flex;font-size:.6875rem;gap:.5rem}.waterfall-stat[data-v-d16c88db]{align-items:baseline;display:inline-flex;font-variant-numeric:tabular-nums;gap:.25rem}.waterfall-stat-value[data-v-d16c88db]{color:var(--color-text);font-weight:700}.waterfall-stat-label[data-v-d16c88db]{color:var(--color-text-subtle)}.waterfall-sep[data-v-d16c88db]{background:var(--color-text-subtle);border-radius:50%;height:3px;opacity:.3;width:3px}.waterfall-proxied-badge[data-v-d16c88db]{align-items:center;color:#107823;display:inline-flex;gap:.25rem}.dark .waterfall-proxied-badge[data-v-d16c88db]{color:#85cc87}.domain-pill[data-v-d16c88db]{align-items:center;background:var(--color-surface-sunken);border:1px solid var(--color-border-subtle);border-radius:9999px;color:var(--color-text-subtle);display:inline-flex;font-family:var(--font-mono);font-size:.625rem;gap:.125rem;padding:.0625rem .375rem}.domain-pill-proxied[data-v-d16c88db]{background:#6bc67014;border-color:#4aa6511f;color:#2f7434}.dark .domain-pill-proxied[data-v-d16c88db]{background:#2f74341a;color:#8fc990}.waterfall-table[data-v-d16c88db]{background:var(--color-surface-elevated);border:1px solid var(--color-border-subtle);border-radius:var(--radius-md);overflow:hidden}.waterfall-legend[data-v-d16c88db]{align-items:center;background:var(--color-surface-sunken);border-bottom:1px solid var(--color-border-subtle);display:flex;gap:.75rem;padding:.25rem .5rem}.waterfall-legend-item[data-v-d16c88db]{align-items:center;color:var(--color-text-subtle);display:flex;font-size:.5625rem;font-weight:600;gap:.25rem;letter-spacing:.04em;text-transform:uppercase}.waterfall-legend-dot[data-v-d16c88db]{border-radius:2px;height:5px;width:5px}.waterfall-row[data-v-d16c88db]{align-items:center;cursor:default;display:flex;font-size:.6875rem;gap:.375rem;padding:.1875rem .5rem;transition:background .1s}.waterfall-row[data-v-d16c88db]:hover{background:var(--color-surface-sunken)}.waterfall-row-proxied[data-v-d16c88db]{background:#6bc67008}.waterfall-row-proxied[data-v-d16c88db]:hover{background:#6bc6700f}.waterfall-status[data-v-d16c88db]{border-radius:3px;flex-shrink:0;font-family:var(--font-mono);font-size:.625rem;font-weight:600;line-height:1;padding:.125rem 0;text-align:center;width:1.5rem}.waterfall-status-200[data-v-d16c88db]{background:#6bc6701a;color:#107823}.dark .waterfall-status-200[data-v-d16c88db]{background:#2f74341f;color:#85cc87}.waterfall-status-304[data-v-d16c88db]{background:#d9b9821a;color:#946900;color:oklch(55% .12 80)}.dark .waterfall-status-304[data-v-d16c88db]{background:#75603b1f;color:#cfa761}.waterfall-row-icon[data-v-d16c88db]{color:var(--color-text-subtle);flex-shrink:0;font-size:.625rem;opacity:.4}.waterfall-row-icon-proxied[data-v-d16c88db]{color:#278733;opacity:1}.dark .waterfall-row-icon-proxied[data-v-d16c88db]{color:#85cc87}.waterfall-url[data-v-d16c88db]{color:var(--color-text-muted);flex-shrink:0;font-family:var(--font-mono);font-size:.625rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:15rem}.waterfall-bar-track[data-v-d16c88db]{background:var(--color-surface-sunken);border-radius:3px;flex:1;height:.875rem;overflow:hidden;position:relative}.waterfall-bar[data-v-d16c88db]{border-radius:3px;display:flex;height:100%;overflow:hidden;position:absolute}.waterfall-duration[data-v-d16c88db]{color:var(--color-text-subtle);flex-shrink:0;font-family:var(--font-mono);font-size:.625rem;font-variant-numeric:tabular-nums;text-align:right;width:2.5rem}.devtools-snippet[data-v-265ccc31]{margin:.5rem .75rem}.devtools-snippet-header[data-v-265ccc31]{align-items:center;display:flex;justify-content:space-between;margin-bottom:.375rem}.devtools-snippet-label[data-v-265ccc31]{color:var(--color-text-muted);font-family:var(--font-mono);font-size:.6875rem;font-weight:500;letter-spacing:-.01em}.devtools-snippet-block[data-v-265ccc31]{border-radius:var(--radius-sm);font-size:.6875rem;line-height:1.6;max-height:300px;overflow-y:auto;padding:.5rem .625rem!important}.filter-bar[data-v-1d33b8c9]{align-items:center;display:flex;gap:.25rem;margin-bottom:.75rem;padding:0 .25rem}.filter-chip[data-v-1d33b8c9]{align-items:center;background:transparent;border:1px solid var(--color-border-subtle);border-radius:9999px;color:var(--color-text-subtle);cursor:pointer;display:inline-flex;font-size:.6875rem;font-weight:500;gap:.375rem;padding:.25rem .625rem;transition:all .15s}.filter-chip[data-v-1d33b8c9]:hover{border-color:var(--color-border);color:var(--color-text-muted)}.filter-chip-active[data-v-1d33b8c9]{background:var(--color-surface-sunken);border-color:var(--color-border);color:var(--color-text)}.filter-chip-count[data-v-1d33b8c9]{background:var(--color-surface-sunken);border-radius:9999px;color:var(--color-text-subtle);font-size:.625rem;font-variant-numeric:tabular-nums;min-width:1.25rem;padding:0 .25rem;text-align:center}.filter-chip-active .filter-chip-count[data-v-1d33b8c9]{background:var(--color-surface-elevated)}.sub-tab[data-v-1d33b8c9]{align-items:center;border-bottom:2px solid transparent;color:var(--color-text-subtle);cursor:pointer;display:flex;font-size:.75rem;font-weight:500;gap:.375rem;margin-bottom:-1px;padding:.5rem .75rem;transition:color .15s,border-color .15s}.sub-tab[data-v-1d33b8c9]:hover{color:var(--color-text-muted)}.sub-tab-active[data-v-1d33b8c9]{border-bottom-color:var(--seo-green);color:var(--color-text)}.event-timeline[data-v-1d33b8c9]{display:flex;flex-direction:column;gap:.125rem}.event-row[data-v-1d33b8c9]{align-items:center;border-radius:var(--radius-sm);display:flex;font-size:.6875rem;gap:.625rem;padding:.25rem .375rem;transition:background .1s}.event-row[data-v-1d33b8c9]:hover{background:var(--color-surface-sunken)}.event-time[data-v-1d33b8c9]{color:var(--color-text-subtle);font-family:var(--font-mono);font-size:.625rem;font-variant-numeric:tabular-nums;min-width:5.5rem;white-space:nowrap}.event-badge[data-v-1d33b8c9]{border-radius:9999px;display:inline-flex;font-size:.625rem;font-weight:600;letter-spacing:.01em;padding:.0625rem .375rem;white-space:nowrap}.event-fn[data-v-1d33b8c9]{background:var(--color-surface-sunken);border:1px solid var(--color-border-subtle);border-radius:var(--radius-sm);color:var(--color-text-muted);font-family:var(--font-mono);font-size:.6875rem;max-width:100%;overflow:hidden;padding:.0625rem .5rem;text-overflow:ellipsis;white-space:nowrap}.status-badge-loaded[data-v-1d33b8c9]{background:#6bc6701f;color:#006818;color:oklch(45% .15 145)}.dark .status-badge-loaded[data-v-1d33b8c9]{background:#10782326;color:#75d079}.status-badge-loading[data-v-1d33b8c9]{background:#d9b9821f;color:#946900;color:oklch(55% .12 80)}.dark .status-badge-loading[data-v-1d33b8c9]{background:#67522d26;color:#cfa761}.status-badge-awaiting[data-v-1d33b8c9]{background:var(--color-surface-sunken);color:var(--color-text-muted)}.status-badge-error[data-v-1d33b8c9]{background:#ce70691a;color:#a83634}.dark .status-badge-error[data-v-1d33b8c9]{background:#843c3826;color:#e6857e}.status-badge-validation[data-v-1d33b8c9]{background:#a890d41a;color:#6e519d}.dark .status-badge-validation[data-v-1d33b8c9]{background:#4e3d6c26;color:#b7a0e4}.status-badge-default[data-v-1d33b8c9]{background:var(--color-surface-sunken);color:var(--color-text-subtle)}
@@ -1 +1 @@
1
- import{f as s,o,c as n,a as l,_ as r,g as a}from"./DTxy5P8N.js";const _={class:"h-full max-h-full overflow-hidden"},u=["src","title"],i=s({__name:"DevtoolsDocs",props:{url:{}},setup(e){return(c,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)]))}}),f=Object.assign(i,{__name:"DevtoolsDocs"}),m={};function d(e,c){const t=f;return o(),a(t,{url:"https://scripts.nuxt.com"})}const p=r(m,[["render",d]]);export{p as default};
1
+ import{f as s,o,c as n,a as l,_ as r,g as a}from"./De7Wf2b9.js";const _={class:"h-full max-h-full overflow-hidden"},u=["src","title"],i=s({__name:"DevtoolsDocs",props:{url:{}},setup(e){return(c,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)]))}}),f=Object.assign(i,{__name:"DevtoolsDocs"}),m={};function d(e,c){const t=f;return o(),a(t,{url:"https://scripts.nuxt.com"})}const p=r(m,[["render",d]]);export{p as default};
@@ -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.BwpOBArY.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-scripts/_nuxt/DTxy5P8N.js"><script type="module" src="/__nuxt-scripts/_nuxt/DTxy5P8N.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:"bd58b869-1eb5-4c50-871c-707f9b71e8f9",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1776170341853,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.BSxy0W1q.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-scripts/_nuxt/De7Wf2b9.js"><script type="module" src="/__nuxt-scripts/_nuxt/De7Wf2b9.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:"9d868e70-bc5a-425c-8c84-8defe5186920",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1776270313716,false]</script></body></html>
@@ -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.BwpOBArY.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-scripts/_nuxt/DTxy5P8N.js"><script type="module" src="/__nuxt-scripts/_nuxt/DTxy5P8N.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:"bd58b869-1eb5-4c50-871c-707f9b71e8f9",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1776170341854,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.BSxy0W1q.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-scripts/_nuxt/De7Wf2b9.js"><script type="module" src="/__nuxt-scripts/_nuxt/De7Wf2b9.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:"9d868e70-bc5a-425c-8c84-8defe5186920",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1776270313717,false]</script></body></html>
@@ -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.BwpOBArY.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-scripts/_nuxt/DTxy5P8N.js"><script type="module" src="/__nuxt-scripts/_nuxt/DTxy5P8N.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:"bd58b869-1eb5-4c50-871c-707f9b71e8f9",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1776170341855,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.BSxy0W1q.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-scripts/_nuxt/De7Wf2b9.js"><script type="module" src="/__nuxt-scripts/_nuxt/De7Wf2b9.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:"9d868e70-bc5a-425c-8c84-8defe5186920",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1776270313718,false]</script></body></html>
@@ -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.BwpOBArY.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-scripts/_nuxt/DTxy5P8N.js"><script type="module" src="/__nuxt-scripts/_nuxt/DTxy5P8N.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:"bd58b869-1eb5-4c50-871c-707f9b71e8f9",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1776170341855,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.BSxy0W1q.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-scripts/_nuxt/De7Wf2b9.js"><script type="module" src="/__nuxt-scripts/_nuxt/De7Wf2b9.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:"9d868e70-bc5a-425c-8c84-8defe5186920",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1776270313718,false]</script></body></html>
package/dist/module.d.mts CHANGED
@@ -120,6 +120,21 @@ interface ModuleOptions {
120
120
  * @default true
121
121
  */
122
122
  autoGenerateSecret?: boolean;
123
+ /**
124
+ * How long (in seconds) a page token issued during SSR remains valid on the
125
+ * client. Client-driven proxy requests (dynamic fetches, runtime image
126
+ * helpers) attach this token so `withSigning` accepts them without each URL
127
+ * being HMAC-signed up front.
128
+ *
129
+ * The default of 1 hour is safe for SSR; for SSG or prerendered routes,
130
+ * deployed HTML carries the build-time token, so bump this (e.g. `2592000`
131
+ * for 30 days) to keep client-side proxy calls working after the build.
132
+ * Longer TTLs widen the replay window if a token is scraped, so prefer the
133
+ * shortest value that covers your cache horizon.
134
+ *
135
+ * @default 3600
136
+ */
137
+ pageTokenMaxAge?: number;
123
138
  };
124
139
  /**
125
140
  * Google Static Maps proxy configuration.
package/dist/module.d.ts CHANGED
@@ -120,6 +120,21 @@ interface ModuleOptions {
120
120
  * @default true
121
121
  */
122
122
  autoGenerateSecret?: boolean;
123
+ /**
124
+ * How long (in seconds) a page token issued during SSR remains valid on the
125
+ * client. Client-driven proxy requests (dynamic fetches, runtime image
126
+ * helpers) attach this token so `withSigning` accepts them without each URL
127
+ * being HMAC-signed up front.
128
+ *
129
+ * The default of 1 hour is safe for SSR; for SSG or prerendered routes,
130
+ * deployed HTML carries the build-time token, so bump this (e.g. `2592000`
131
+ * for 30 days) to keep client-side proxy calls working after the build.
132
+ * Longer TTLs widen the replay window if a token is scraped, so prefer the
133
+ * shortest value that covers your cache horizon.
134
+ *
135
+ * @default 3600
136
+ */
137
+ pageTokenMaxAge?: number;
123
138
  };
124
139
  /**
125
140
  * Google Static Maps proxy configuration.
package/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": ">=3.16"
6
6
  },
7
- "version": "1.0.0-rc.9",
7
+ "version": "1.0.0",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.2",
10
10
  "unbuild": "3.6.1"
package/dist/module.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { createHash, randomBytes } from 'node:crypto';
2
2
  import { existsSync, readFileSync, appendFileSync, writeFileSync, readdirSync } from 'node:fs';
3
- import { useNuxt, addDevServerHandler, extendRouteRules, tryUseNuxt, createResolver, extendViteConfig, logger as logger$1, useLogger, addTypeTemplate, defineNuxtModule, addPluginTemplate, addServerHandler, addImports, addComponentsDir, addTemplate, hasNuxtModule, addBuildPlugin } from '@nuxt/kit';
3
+ import { useNuxt, addDevServerHandler, extendRouteRules, tryUseNuxt, createResolver, extendViteConfig, logger as logger$1, useLogger, addTypeTemplate, defineNuxtModule, addPluginTemplate, addServerHandler, addImports, addComponentsDir, addTemplate, hasNuxtModule, addBuildPlugin, addPlugin } from '@nuxt/kit';
4
4
  import { defu } from 'defu';
5
5
  import { join, resolve } from 'pathe';
6
6
  import { resolvePackageJSON, readPackageJSON } from 'pkg-types';
@@ -288,7 +288,7 @@ function migrateDeprecatedRegistryKeys(registry, warn) {
288
288
  }
289
289
  }
290
290
  }
291
- function normalizeRegistryConfig(registry, warn) {
291
+ function normalizeRegistryConfig(registry, warn, componentOnlyKeys) {
292
292
  for (const key of Object.keys(registry)) {
293
293
  const entry = registry[key];
294
294
  if (!entry) {
@@ -296,6 +296,10 @@ function normalizeRegistryConfig(registry, warn) {
296
296
  continue;
297
297
  }
298
298
  if (entry === true) {
299
+ if (componentOnlyKeys?.has(key)) {
300
+ registry[key] = [{}];
301
+ continue;
302
+ }
299
303
  warn?.(`[nuxt-scripts] registry.${key}: \`true\` shorthand is deprecated. Use \`{ trigger: 'onNuxtReady' }\` instead.`);
300
304
  registry[key] = [{}, { trigger: "onNuxtReady" }];
301
305
  continue;
@@ -1496,8 +1500,9 @@ const module$1 = defineNuxtModule({
1496
1500
  }
1497
1501
  const scripts = await registry(resolvePath);
1498
1502
  if (config.registry) {
1503
+ const componentOnlyKeys = new Set(scripts.filter((s) => !s.import).map((s) => s.registryKey));
1499
1504
  migrateDeprecatedRegistryKeys(config.registry, (msg) => logger.warn(msg));
1500
- normalizeRegistryConfig(config.registry, (msg) => logger.warn(msg));
1505
+ normalizeRegistryConfig(config.registry, (msg) => logger.warn(msg), componentOnlyKeys);
1501
1506
  nuxt.options.runtimeConfig.public = nuxt.options.runtimeConfig.public || {};
1502
1507
  const registryWithDefaults = {};
1503
1508
  for (const [key, entry] of Object.entries(config.registry)) {
@@ -1550,6 +1555,8 @@ const module$1 = defineNuxtModule({
1550
1555
  const composables = [
1551
1556
  "useScript",
1552
1557
  "useScriptEventPage",
1558
+ "useScriptProxyToken",
1559
+ "useScriptProxyUrl",
1553
1560
  "useScriptTriggerConsent",
1554
1561
  "useScriptTriggerElement",
1555
1562
  "useScriptTriggerIdleTimeout",
@@ -1592,10 +1599,23 @@ const module$1 = defineNuxtModule({
1592
1599
  const script = scripts.find((s) => s.registryKey === key);
1593
1600
  if (!script?.schema)
1594
1601
  continue;
1595
- const requiredFields = extractRequiredFields(script.schema);
1596
- const missing = requiredFields.filter((f) => !input[f]);
1597
- if (missing.length) {
1598
- logger.warn(`[nuxt-scripts] registry.${key}: missing required field${missing.length > 1 ? "s" : ""} ${missing.map((f) => `'${f}'`).join(", ")}. The script infrastructure is registered but will not function without ${missing.length > 1 ? "them" : "it"}.`);
1602
+ const isComponentOnly = !script.import;
1603
+ if (isComponentOnly) {
1604
+ if (scriptOptions && "trigger" in scriptOptions && scriptOptions.trigger !== false) {
1605
+ const pascal = key.charAt(0).toUpperCase() + key.slice(1);
1606
+ logger.warn(
1607
+ `[nuxt-scripts] registry.${key}: \`trigger\` has no effect on component-only scripts. Render <Script${pascal}> in your template to load the embed.`
1608
+ );
1609
+ }
1610
+ continue;
1611
+ }
1612
+ const willAutoLoad = scriptOptions && "trigger" in scriptOptions && scriptOptions.trigger !== false;
1613
+ if (willAutoLoad) {
1614
+ const requiredFields = extractRequiredFields(script.schema);
1615
+ const missing = requiredFields.filter((f) => !input[f]);
1616
+ if (missing.length) {
1617
+ logger.warn(`[nuxt-scripts] registry.${key}: missing required field${missing.length > 1 ? "s" : ""} ${missing.map((f) => `'${f}'`).join(", ")}. The script infrastructure is registered but will not function without ${missing.length > 1 ? "them" : "it"}.`);
1618
+ }
1599
1619
  }
1600
1620
  const envDefaultKeys = new Set(Object.keys(script.envDefaults || {}));
1601
1621
  const userProvidedFields = Object.keys(input).filter((f) => !envDefaultKeys.has(f));
@@ -1830,7 +1850,14 @@ Options: configure platform rewrites, switch to server-rendered mode, or disable
1830
1850
  else if (proxySecretResolved?.source === "memory-generated")
1831
1851
  logger.warn(`[security] Generated an in-memory ${PROXY_SECRET_ENV_KEY} (could not write .env). Signed URLs will break across restarts.`);
1832
1852
  if (proxySecretResolved?.secret) {
1833
- nuxt.options.runtimeConfig["nuxt-scripts"].proxySecret = proxySecretResolved.secret;
1853
+ const scriptsRuntime = nuxt.options.runtimeConfig["nuxt-scripts"];
1854
+ scriptsRuntime.proxySecret = proxySecretResolved.secret;
1855
+ if (config.security?.pageTokenMaxAge !== void 0)
1856
+ scriptsRuntime.pageTokenMaxAge = config.security.pageTokenMaxAge;
1857
+ addPlugin({
1858
+ src: await resolvePath("./runtime/plugins/proxy-token.server"),
1859
+ mode: "server"
1860
+ });
1834
1861
  } else if (!nuxt.options.dev) {
1835
1862
  logger.warn(
1836
1863
  `[security] ${PROXY_SECRET_ENV_KEY} is not set. Proxy endpoints will pass requests through without signature verification.
package/dist/registry.mjs CHANGED
@@ -346,7 +346,7 @@ async function registry(resolve) {
346
346
  return "https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js";
347
347
  }
348
348
  },
349
- partytown: { forwards: ["mixpanel", "mixpanel.init", "mixpanel.track", "mixpanel.identify", "mixpanel.people.set", "mixpanel.reset", "mixpanel.register"] }
349
+ partytown: { forwards: ["mixpanel", "mixpanel.init", "mixpanel.track", "mixpanel.identify", "mixpanel.people.set", "mixpanel.reset", "mixpanel.register", "mixpanel.opt_in_tracking", "mixpanel.opt_out_tracking"] }
350
350
  }),
351
351
  // ad
352
352
  def("bingUet", {
@@ -401,7 +401,7 @@ async function registry(resolve) {
401
401
  domains: ["analytics.tiktok.com", "mon.tiktok.com", "mcs.tiktok.com"],
402
402
  privacy: PRIVACY_FULL
403
403
  },
404
- partytown: { forwards: ["ttq.track", "ttq.page", "ttq.identify"] }
404
+ partytown: { forwards: ["ttq.track", "ttq.page", "ttq.identify", "ttq.grantConsent", "ttq.revokeConsent", "ttq.holdConsent"] }
405
405
  }),
406
406
  def("snapchatPixel", {
407
407
  schema: SnapTrPixelOptions,
@@ -503,7 +503,7 @@ async function registry(resolve) {
503
503
  domains: ["www.clarity.ms", "scripts.clarity.ms", "d.clarity.ms", "e.clarity.ms", "k.clarity.ms", "c.clarity.ms", "a.clarity.ms", "b.clarity.ms"],
504
504
  privacy: PRIVACY_HEATMAP
505
505
  },
506
- partytown: { forwards: [] }
506
+ partytown: { forwards: ["clarity"] }
507
507
  }),
508
508
  // payments
509
509
  def("stripe", {
@@ -4,6 +4,7 @@ import { defu } from "defu";
4
4
  import { useHead, useRuntimeConfig } from "nuxt/app";
5
5
  import { withQuery } from "ufo";
6
6
  import { computed, onMounted, ref } from "vue";
7
+ import { useScriptProxyUrl } from "../../composables/useScriptProxyUrl";
7
8
  </script>
8
9
 
9
10
  <script setup>
@@ -34,6 +35,7 @@ const runtimeConfig = useRuntimeConfig();
34
35
  const proxyConfig = runtimeConfig.public["nuxt-scripts"]?.googleStaticMapsProxy;
35
36
  const apiKey = props.apiKey || scriptRuntimeConfig("googleMaps")?.apiKey;
36
37
  const useProxy = !props.apiKey && proxyConfig?.enabled;
38
+ const proxyUrl = useScriptProxyUrl();
37
39
  if (import.meta.dev) {
38
40
  if (!apiKey && !useProxy)
39
41
  console.warn("[nuxt-scripts] ScriptGoogleMapsStaticMap requires a Google Maps API key with Static Maps API access. Set NUXT_PUBLIC_SCRIPTS_GOOGLE_MAPS_API_KEY in your .env, or enable the proxy via `scripts.registry.googleMaps`.");
@@ -122,8 +124,10 @@ const src = computed(() => {
122
124
  if (query[key] === void 0)
123
125
  delete query[key];
124
126
  }
125
- const baseUrl = useProxy ? "/_scripts/proxy/google-static-maps" : "https://maps.googleapis.com/maps/api/staticmap";
126
- return withQuery(baseUrl, query);
127
+ if (useProxy) {
128
+ return proxyUrl("/_scripts/proxy/google-static-maps", query);
129
+ }
130
+ return withQuery("https://maps.googleapis.com/maps/api/staticmap", query);
127
131
  });
128
132
  const imgAttributes = computed(() => {
129
133
  return defu(props.imgAttrs, {
@@ -32,7 +32,6 @@ declare const slotProps: import("vue").ComputedRef<{
32
32
  displayName: string;
33
33
  handle: string;
34
34
  avatar: string;
35
- avatarOriginal: string;
36
35
  isVerified: boolean;
37
36
  text: string;
38
37
  richText: string;
@@ -1,7 +1,8 @@
1
1
  <script setup>
2
2
  import { useAsyncData } from "nuxt/app";
3
3
  import { computed } from "vue";
4
- import { extractBlueskyPostId, facetsToHtml, formatBlueskyDate, formatCount, proxyBlueskyImageUrl } from "../registry/bluesky-embed";
4
+ import { useScriptProxyUrl } from "../composables/useScriptProxyUrl";
5
+ import { extractBlueskyPostId, facetsToHtml, formatBlueskyDate, formatCount } from "../registry/bluesky-embed";
5
6
  import { requireRegistryEndpoint, scriptsPrefix } from "../utils";
6
7
  const props = defineProps({
7
8
  postUrl: { type: String, required: true },
@@ -15,11 +16,12 @@ const resolvedApiEndpoint = computed(() => props.apiEndpoint || `${prefix}/embed
15
16
  const resolvedImageProxyEndpoint = computed(() => props.imageProxyEndpoint || `${prefix}/embed/bluesky-image`);
16
17
  if (!props.apiEndpoint)
17
18
  requireRegistryEndpoint("ScriptBlueskyEmbed", "blueskyEmbed");
19
+ const proxyUrl = useScriptProxyUrl();
18
20
  const postId = computed(() => extractBlueskyPostId(props.postUrl));
19
21
  const cacheKey = computed(() => `bluesky-embed-${postId.value?.actor}-${postId.value?.rkey}`);
20
22
  const { data: post, status, error } = useAsyncData(
21
23
  cacheKey,
22
- () => $fetch(`${resolvedApiEndpoint.value}?url=${encodeURIComponent(props.postUrl)}`)
24
+ () => $fetch(proxyUrl(resolvedApiEndpoint.value, { url: props.postUrl }))
23
25
  );
24
26
  const slotProps = computed(() => {
25
27
  if (!post.value)
@@ -31,8 +33,7 @@ const slotProps = computed(() => {
31
33
  // Author info
32
34
  displayName: p.author.displayName,
33
35
  handle: p.author.handle,
34
- avatar: proxyBlueskyImageUrl(p.author.avatar, resolvedImageProxyEndpoint.value),
35
- avatarOriginal: p.author.avatar,
36
+ avatar: p.author.avatar,
36
37
  isVerified: p.author.verification?.verifiedStatus === "valid",
37
38
  // Post content
38
39
  text: p.record.text,
@@ -49,10 +50,10 @@ const slotProps = computed(() => {
49
50
  repliesFormatted: formatCount(p.replyCount),
50
51
  quotes: p.quoteCount,
51
52
  quotesFormatted: formatCount(p.quoteCount),
52
- // Media
53
+ // Media (already proxied)
53
54
  images: p.embed?.images?.map((img) => ({
54
- thumb: proxyBlueskyImageUrl(img.thumb, resolvedImageProxyEndpoint.value),
55
- fullsize: proxyBlueskyImageUrl(img.fullsize, resolvedImageProxyEndpoint.value),
55
+ thumb: img.thumb,
56
+ fullsize: img.fullsize,
56
57
  alt: img.alt,
57
58
  aspectRatio: img.aspectRatio
58
59
  })),
@@ -60,13 +61,14 @@ const slotProps = computed(() => {
60
61
  uri: p.embed.external.uri,
61
62
  title: p.embed.external.title,
62
63
  description: p.embed.external.description,
63
- thumb: p.embed.external.thumb ? proxyBlueskyImageUrl(p.embed.external.thumb, resolvedImageProxyEndpoint.value) : void 0
64
+ thumb: p.embed.external.thumb
64
65
  } : void 0,
65
66
  // Links
66
67
  postUrl: props.postUrl,
67
68
  authorUrl: `https://bsky.app/profile/${p.author.handle}`,
68
- // Helpers
69
- proxyImage: (url) => proxyBlueskyImageUrl(url, resolvedImageProxyEndpoint.value)
69
+ // Helpers — proxy an arbitrary URL through the image endpoint at runtime.
70
+ // Uses the page token emitted during SSR so client-generated URLs validate.
71
+ proxyImage: (url) => proxyUrl(resolvedImageProxyEndpoint.value, { url })
70
72
  };
71
73
  });
72
74
  defineExpose({
@@ -32,7 +32,6 @@ declare const slotProps: import("vue").ComputedRef<{
32
32
  displayName: string;
33
33
  handle: string;
34
34
  avatar: string;
35
- avatarOriginal: string;
36
35
  isVerified: boolean;
37
36
  text: string;
38
37
  richText: string;
@@ -1,6 +1,7 @@
1
1
  <script setup>
2
2
  import { useAsyncData } from "nuxt/app";
3
3
  import { computed } from "vue";
4
+ import { useScriptProxyUrl } from "../composables/useScriptProxyUrl";
4
5
  import { extractInstagramShortcode } from "../registry/instagram-embed";
5
6
  import { requireRegistryEndpoint, scriptsPrefix } from "../utils";
6
7
  const props = defineProps({
@@ -14,10 +15,11 @@ const prefix = scriptsPrefix();
14
15
  const apiEndpoint = computed(() => props.apiEndpoint || `${prefix}/embed/instagram`);
15
16
  if (!props.apiEndpoint)
16
17
  requireRegistryEndpoint("ScriptInstagramEmbed", "instagramEmbed");
18
+ const proxyUrl = useScriptProxyUrl();
17
19
  const shortcode = computed(() => extractInstagramShortcode(props.postUrl));
18
20
  const { data: html, status, error } = useAsyncData(
19
21
  `instagram-embed-${props.postUrl}`,
20
- () => $fetch(`${apiEndpoint.value}?url=${encodeURIComponent(props.postUrl)}&captions=${props.captions}`),
22
+ () => $fetch(proxyUrl(apiEndpoint.value, { url: props.postUrl, captions: props.captions })),
21
23
  { watch: [() => props.postUrl, () => props.captions] }
22
24
  );
23
25
  defineExpose({
@@ -31,7 +31,6 @@ declare const slotProps: import("vue").ComputedRef<{
31
31
  userName: string;
32
32
  userHandle: string;
33
33
  userAvatar: string;
34
- userAvatarOriginal: string;
35
34
  isVerified: boolean | undefined;
36
35
  text: string;
37
36
  datetime: string;
@@ -1,7 +1,8 @@
1
1
  <script setup>
2
2
  import { useAsyncData } from "nuxt/app";
3
3
  import { computed } from "vue";
4
- import { formatCount, formatTweetDate, proxyXImageUrl } from "../registry/x-embed";
4
+ import { useScriptProxyUrl } from "../composables/useScriptProxyUrl";
5
+ import { formatCount, formatTweetDate } from "../registry/x-embed";
5
6
  import { requireRegistryEndpoint, scriptsPrefix } from "../utils";
6
7
  const props = defineProps({
7
8
  tweetId: { type: String, required: true },
@@ -15,10 +16,11 @@ const apiEndpoint = computed(() => props.apiEndpoint || `${prefix}/embed/x`);
15
16
  const resolvedImageProxyEndpoint = computed(() => props.imageProxyEndpoint || `${prefix}/embed/x-image`);
16
17
  if (!props.apiEndpoint)
17
18
  requireRegistryEndpoint("ScriptXEmbed", "xEmbed");
19
+ const proxyUrl = useScriptProxyUrl();
18
20
  const cacheKey = computed(() => `x-embed-${props.tweetId}`);
19
21
  const { data: tweet, status, error } = useAsyncData(
20
22
  cacheKey,
21
- () => $fetch(`${apiEndpoint.value}?id=${props.tweetId}`)
23
+ () => $fetch(proxyUrl(apiEndpoint.value, { id: props.tweetId }))
22
24
  );
23
25
  const slotProps = computed(() => {
24
26
  if (!tweet.value)
@@ -30,8 +32,7 @@ const slotProps = computed(() => {
30
32
  // User info
31
33
  userName: t.user.name,
32
34
  userHandle: t.user.screen_name,
33
- userAvatar: proxyXImageUrl(t.user.profile_image_url_https, resolvedImageProxyEndpoint.value),
34
- userAvatarOriginal: t.user.profile_image_url_https,
35
+ userAvatar: t.user.profile_image_url_https,
35
36
  isVerified: t.user.verified || t.user.is_blue_verified,
36
37
  // Tweet content
37
38
  text: t.text,
@@ -42,14 +43,14 @@ const slotProps = computed(() => {
42
43
  likesFormatted: formatCount(t.favorite_count),
43
44
  replies: t.conversation_count,
44
45
  repliesFormatted: formatCount(t.conversation_count),
45
- // Media
46
+ // Media (already proxied)
46
47
  photos: t.photos?.map((p) => ({
47
48
  ...p,
48
- proxiedUrl: proxyXImageUrl(p.url, resolvedImageProxyEndpoint.value)
49
+ proxiedUrl: p.url
49
50
  })),
50
51
  video: t.video ? {
51
52
  ...t.video,
52
- posterProxied: proxyXImageUrl(t.video.poster, resolvedImageProxyEndpoint.value)
53
+ posterProxied: t.video.poster
53
54
  } : null,
54
55
  // Links
55
56
  tweetUrl: `https://x.com/${t.user.screen_name}/status/${t.id_str}`,
@@ -59,8 +60,9 @@ const slotProps = computed(() => {
59
60
  // Reply context
60
61
  isReply: !!t.parent,
61
62
  replyToUser: t.parent?.user.screen_name,
62
- // Helpers
63
- proxyImage: (url) => proxyXImageUrl(url, resolvedImageProxyEndpoint.value)
63
+ // Helpers — proxy an arbitrary URL through the image endpoint at runtime.
64
+ // Uses the page token emitted during SSR so client-generated URLs validate.
65
+ proxyImage: (url) => proxyUrl(resolvedImageProxyEndpoint.value, { url })
64
66
  };
65
67
  });
66
68
  defineExpose({
@@ -31,7 +31,6 @@ declare const slotProps: import("vue").ComputedRef<{
31
31
  userName: string;
32
32
  userHandle: string;
33
33
  userAvatar: string;
34
- userAvatarOriginal: string;
35
34
  isVerified: boolean | undefined;
36
35
  text: string;
37
36
  datetime: string;
@@ -26,11 +26,22 @@ function toNetworkRequest(entry, proxyPrefix) {
26
26
  isProxied
27
27
  };
28
28
  }
29
- function createDomainMatcher(domains, proxyPrefix) {
29
+ function createDomainMatcher(domains, proxyPrefix, scriptSrc) {
30
30
  const localHostname = window.location.hostname;
31
+ const scriptUrl = (() => {
32
+ if (!scriptSrc)
33
+ return "";
34
+ try {
35
+ return new URL(scriptSrc, window.location.origin).href;
36
+ } catch {
37
+ return "";
38
+ }
39
+ })();
31
40
  return function matchesScript(entry) {
32
41
  try {
33
42
  const entryUrl = new URL(entry.name, window.location.origin);
43
+ if (scriptUrl && entryUrl.href === scriptUrl)
44
+ return true;
34
45
  if (entryUrl.hostname !== localHostname && domains.has(entryUrl.hostname))
35
46
  return true;
36
47
  const proxyPath = `${proxyPrefix}/`;
@@ -46,12 +57,12 @@ function createDomainMatcher(domains, proxyPrefix) {
46
57
  return false;
47
58
  };
48
59
  }
49
- function observeNetworkRequests(payload, domains, onUpdate) {
60
+ function observeNetworkRequests(payload, domains, onUpdate, scriptSrc) {
50
61
  if (typeof PerformanceObserver === "undefined")
51
62
  return () => {
52
63
  };
53
64
  const proxyPrefix = resolveProxyPrefix();
54
- const matchesScript = createDomainMatcher(domains, proxyPrefix);
65
+ const matchesScript = createDomainMatcher(domains, proxyPrefix, scriptSrc);
55
66
  const seen = /* @__PURE__ */ new Set();
56
67
  function entryKey(entry) {
57
68
  return `${entry.name}@${entry.startTime}`;
@@ -148,7 +159,7 @@ export function useScript(input, options) {
148
159
  ],
149
160
  networkRequests: []
150
161
  };
151
- disconnectObserver = observeNetworkRequests(payload, domains, syncScripts);
162
+ disconnectObserver = observeNetworkRequests(payload, domains, syncScripts, src);
152
163
  syncScripts();
153
164
  }
154
165
  return stub;
@@ -274,7 +285,7 @@ export function useScript(input, options) {
274
285
  ...scriptHostname ? [scriptHostname] : [],
275
286
  ...options.devtools?.domains || []
276
287
  ]);
277
- let disconnectObserver = observeNetworkRequests(payload, domains, syncScripts);
288
+ let disconnectObserver = observeNetworkRequests(payload, domains, syncScripts, input.src);
278
289
  const _origRemove = instance.remove;
279
290
  const _origReload = instance.reload;
280
291
  instance.remove = () => {
@@ -284,7 +295,7 @@ export function useScript(input, options) {
284
295
  instance.reload = async () => {
285
296
  disconnectObserver();
286
297
  const result = await _origReload();
287
- disconnectObserver = observeNetworkRequests(payload, domains, syncScripts);
298
+ disconnectObserver = observeNetworkRequests(payload, domains, syncScripts, input.src);
288
299
  return result;
289
300
  };
290
301
  syncScripts();
@@ -0,0 +1,12 @@
1
+ export interface ScriptProxyToken {
2
+ token: string;
3
+ ts: number;
4
+ }
5
+ /**
6
+ * Shared `useState` holding the proxy page token emitted during SSR.
7
+ *
8
+ * Populated by the `nuxt-scripts:proxy-token` server plugin when
9
+ * `runtimeConfig['nuxt-scripts'].proxySecret` is set, and hydrated to the
10
+ * client via the Nuxt payload. Stays null when signing is disabled.
11
+ */
12
+ export declare function useScriptProxyToken(): import("vue").Ref<ScriptProxyToken | null, ScriptProxyToken | null>;
@@ -0,0 +1,4 @@
1
+ import { useState } from "nuxt/app";
2
+ export function useScriptProxyToken() {
3
+ return useState("nuxt-scripts:proxy-token", () => null);
4
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Build proxy URLs that the server's `withSigning` middleware accepts.
3
+ *
4
+ * Attaches the page token emitted during SSR (`_pt` + `_ts`) when one is
5
+ * available, so client-driven proxy calls (e.g. reactive fetches, dynamic
6
+ * image helpers exposed in slot props) authenticate without needing a
7
+ * server round-trip to sign each URL.
8
+ *
9
+ * When no token is present (signing disabled or no secret), emits plain
10
+ * `?url=...` URLs, matching the pre-signing behavior.
11
+ */
12
+ export declare function useScriptProxyUrl(): (path: string, query?: Record<string, unknown>) => string;
@@ -0,0 +1,27 @@
1
+ import { PAGE_TOKEN_PARAM, PAGE_TOKEN_TS_PARAM } from "../server/utils/sign-constants.js";
2
+ import { useScriptProxyToken } from "./useScriptProxyToken.js";
3
+ export function useScriptProxyUrl() {
4
+ const token = useScriptProxyToken();
5
+ return (path, query = {}) => {
6
+ const parts = [];
7
+ for (const [key, value] of Object.entries(query)) {
8
+ if (value === void 0 || value === null)
9
+ continue;
10
+ const encodedKey = encodeURIComponent(key);
11
+ if (Array.isArray(value)) {
12
+ for (const item of value) {
13
+ if (item === void 0 || item === null)
14
+ continue;
15
+ parts.push(`${encodedKey}=${encodeURIComponent(String(item))}`);
16
+ }
17
+ } else {
18
+ parts.push(`${encodedKey}=${encodeURIComponent(String(value))}`);
19
+ }
20
+ }
21
+ if (token.value) {
22
+ parts.push(`${PAGE_TOKEN_PARAM}=${encodeURIComponent(token.value.token)}`);
23
+ parts.push(`${PAGE_TOKEN_TS_PARAM}=${token.value.ts}`);
24
+ }
25
+ return parts.length ? `${path}?${parts.join("&")}` : path;
26
+ };
27
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Emit a per-request proxy page token into the SSR payload.
3
+ *
4
+ * The token authorizes client-side proxy calls (`/embed/x-image?url=...`,
5
+ * `/embed/bluesky?url=...`, etc.) without needing each URL to be signed
6
+ * ahead of time. It stays null when no proxy secret is configured, in
7
+ * which case `withSigning` passes requests through unchecked.
8
+ */
9
+ declare const _default: import("nuxt/app").Plugin<Record<string, unknown>> & import("nuxt/app").ObjectPlugin<Record<string, unknown>>;
10
+ export default _default;