import type { UseScriptInput, UseScriptOptions, VueScriptInstance } from '@unhead/vue'; import type { Script } from '@unhead/vue/types'; import type { Import } from 'unimport'; import type { InferInput, ObjectEntries, ObjectSchema, UnionSchema, ValiError } from 'valibot'; import type { ComputedRef, Ref } from 'vue'; import type { BingUetInput } from './registry/bing-uet.js'; import type { BlueskyEmbedInput } from './registry/bluesky-embed.js'; import type { ClarityInput } from './registry/clarity.js'; import type { CloudflareWebAnalyticsInput } from './registry/cloudflare-web-analytics.js'; import type { CrispInput } from './registry/crisp.js'; import type { DatabuddyAnalyticsInput } from './registry/databuddy-analytics.js'; import type { FathomAnalyticsInput } from './registry/fathom-analytics.js'; import type { GoogleAdsenseInput } from './registry/google-adsense.js'; import type { GoogleAnalyticsInput } from './registry/google-analytics.js'; import type { GoogleMapsInput } from './registry/google-maps.js'; import type { GoogleRecaptchaInput } from './registry/google-recaptcha.js'; import type { GoogleSignInInput } from './registry/google-sign-in.js'; import type { GoogleTagManagerInput } from './registry/google-tag-manager.js'; import type { GravatarInput } from './registry/gravatar.js'; import type { HotjarInput } from './registry/hotjar.js'; import type { InstagramEmbedInput } from './registry/instagram-embed.js'; import type { IntercomInput } from './registry/intercom.js'; import type { LemonSqueezyInput } from './registry/lemon-squeezy.js'; import type { MatomoAnalyticsInput } from './registry/matomo-analytics.js'; import type { MetaPixelInput } from './registry/meta-pixel.js'; import type { MixpanelAnalyticsInput } from './registry/mixpanel-analytics.js'; import type { NpmInput } from './registry/npm.js'; import type { PayPalInput } from './registry/paypal.js'; import type { PlausibleAnalyticsInput } from './registry/plausible-analytics.js'; import type { PostHogInput } from './registry/posthog.js'; import type { RedditPixelInput } from './registry/reddit-pixel.js'; import type { RybbitAnalyticsInput } from './registry/rybbit-analytics.js'; import type { SegmentInput } from './registry/segment.js'; import type { SnapTrPixelInput } from './registry/snapchat-pixel.js'; import type { StripeInput } from './registry/stripe.js'; import type { TikTokPixelInput } from './registry/tiktok-pixel.js'; import type { UmamiAnalyticsInput } from './registry/umami-analytics.js'; import type { VercelAnalyticsInput } from './registry/vercel-analytics.js'; import type { VimeoPlayerInput } from './registry/vimeo-player.js'; import type { XEmbedInput } from './registry/x-embed.js'; import type { XPixelInput } from './registry/x-pixel.js'; import type { YouTubePlayerInput } from './registry/youtube-player.js'; import type { ProxyPrivacyInput } from './server/utils/privacy.js'; export type { Cluster, ClusterStats, MarkerClustererContext, MarkerClustererInstance, MarkerClustererOptions } from './components/GoogleMaps/types.js'; export { MARKER_CLUSTERER_INJECTION_KEY } from './components/GoogleMaps/types.js'; export type WarmupStrategy = false | 'preload' | 'preconnect' | 'dns-prefetch'; /** * GCMv2 consent category value. * @see https://developers.google.com/tag-platform/security/guides/consent */ export type ConsentCategoryValue = 'granted' | 'denied'; /** * Canonical GCMv2 consent state shape used by vendors that natively consume * Consent Mode v2 (Google Analytics, Google Tag Manager, Bing UET). */ export interface ConsentState { ad_storage?: ConsentCategoryValue; ad_user_data?: ConsentCategoryValue; ad_personalization?: ConsentCategoryValue; analytics_storage?: ConsentCategoryValue; functionality_storage?: ConsentCategoryValue; personalization_storage?: ConsentCategoryValue; security_storage?: ConsentCategoryValue; } export type UseScriptContext, C = unknown> = VueScriptInstance & { /** * Remove and reload the script. Useful for scripts that need to re-execute * after SPA navigation (e.g., DOM-scanning scripts like iubenda). */ reload: () => Promise; /** * Vendor-native consent controls attached by registry scripts. * Shape depends on the vendor (GCMv2 update, binary grant/revoke, three-state, etc.). */ consent?: C; }; export type NuxtUseScriptOptions = {}> = Omit, 'trigger'> & { /** * The trigger to load the script: * - `onNuxtReady` - Load the script when Nuxt is ready. * - `manual` - Load the script manually by calling `load()`. * - `Promise` - Load the script when the promise resolves. */ trigger?: UseScriptOptions['trigger'] | 'onNuxtReady'; /** * Should the script be bundled as an asset and loaded from your server. This is useful for improving the * performance by avoiding the extra DNS lookup and reducing the number of requests. It also * improves privacy by not sharing the user's IP address with third-party servers. * - `true` - Bundle the script as an asset. * - `'force'` - Bundle the script and force download, bypassing cache. Useful for development. * - `false` - Do not bundle the script. (default) * * Note: Using 'force' may significantly increase build time as scripts will be re-downloaded on every build. * * @deprecated Bundling is now auto-enabled per-script via capabilities. Set `bundle: false` per-script to disable. */ bundle?: boolean | 'force'; /** * Control proxying for this script. * When `false`, collection requests go directly to the third-party server. * When `true`, collection requests are proxied through `/_scripts/p/`. * Defaults based on whether the script has a `proxy` capability in the registry. */ proxy?: boolean; /** * Load the script in a web worker using Partytown. * When enabled, adds `type="text/partytown"` to the script tag. * Requires @nuxtjs/partytown to be installed and configured separately. * @see https://partytown.qwik.dev/ */ partytown?: boolean; /** * Skip any schema validation for the script input. This is useful for loading the script stubs for development without * loading the actual script and not getting warnings. */ skipValidation?: boolean; /** * Specify a strategy for warming up the connection to the third-party script. * * The strategy to use for preloading the script. * - `false` - Disable preloading. * - `'preload'` - Preload the script. * - `'preconnect'` | `'dns-prefetch'` - Preconnect to the script. Only works when loading a script from a different origin, will fallback * to `false` if the origin is the same. */ warmupStrategy?: WarmupStrategy; /** * @internal */ devtools?: { /** * Key used to map to the registry script for Nuxt DevTools. * @internal */ registryKey?: string; /** * Extra metadata to show with the registry script * @internal */ registryMeta?: Record; /** * Known third-party domains this script communicates with. * @internal */ domains?: string[]; }; /** * @internal */ _validate?: () => ValiError | null | undefined; }; export type NuxtUseScriptOptionsSerializable = Omit & { trigger?: 'client' | 'server' | 'onNuxtReady' | { idleTimeout: number; } | { interaction: string[]; } | { serviceWorker: true; }; }; export type NuxtUseScriptInput = UseScriptInput; export interface TrackedPage { title?: string; path: string; } type ExcludePromises = T extends Promise ? never : T; export interface ConsentScriptTriggerOptions { /** * An optional reactive (or promise) reference to the consent state. You can use this to accept the consent for scripts * instead of using the accept() method. */ consent?: Promise | Ref | ComputedRef | boolean; /** * Should the script be loaded on the `requestIdleCallback` callback. This is useful for non-essential scripts that * have already been consented to be loaded. */ postConsentTrigger?: ExcludePromises | (() => Promise); } export interface NuxtDevToolsNetworkRequest { url: string; startTime: number; duration: number; transferSize: number; encodedBodySize: number; decodedBodySize: number; initiatorType: string; dns: number; connect: number; ssl: number; ttfb: number; download: number; isProxied: boolean; } export interface NuxtDevToolsScriptInstance { registryKey?: string; registryMeta?: Record; src: string; domains?: string[]; $script: VueScriptInstance; events: { type: string; fn?: string | symbol; args?: any; status?: string; trigger?: NuxtUseScriptOptions['trigger']; at: number; }[]; networkRequests: NuxtDevToolsNetworkRequest[]; } export interface ScriptRegistry { bingUet?: BingUetInput; blueskyEmbed?: BlueskyEmbedInput; carbonAds?: true; crisp?: CrispInput; clarity?: ClarityInput; cloudflareWebAnalytics?: CloudflareWebAnalyticsInput; databuddyAnalytics?: DatabuddyAnalyticsInput; metaPixel?: MetaPixelInput; fathomAnalytics?: FathomAnalyticsInput; instagramEmbed?: InstagramEmbedInput; plausibleAnalytics?: PlausibleAnalyticsInput; googleAdsense?: GoogleAdsenseInput; googleAnalytics?: GoogleAnalyticsInput; googleMaps?: GoogleMapsInput; googleRecaptcha?: GoogleRecaptchaInput; googleSignIn?: GoogleSignInInput; lemonSqueezy?: LemonSqueezyInput; googleTagManager?: GoogleTagManagerInput; hotjar?: HotjarInput; intercom?: IntercomInput; paypal?: PayPalInput; posthog?: PostHogInput; matomoAnalytics?: MatomoAnalyticsInput; mixpanelAnalytics?: MixpanelAnalyticsInput; rybbitAnalytics?: RybbitAnalyticsInput; redditPixel?: RedditPixelInput; segment?: SegmentInput; stripe?: StripeInput; tiktokPixel?: TikTokPixelInput; xEmbed?: XEmbedInput; xPixel?: XPixelInput; snapchatPixel?: SnapTrPixelInput; youtubePlayer?: YouTubePlayerInput; vercelAnalytics?: VercelAnalyticsInput; vimeoPlayer?: VimeoPlayerInput; umamiAnalytics?: UmamiAnalyticsInput; gravatar?: GravatarInput; npm?: NpmInput; [key: `${string}-npm`]: NpmInput; } /** * Built-in registry script keys — not affected by module augmentation. * Use this to type-check records that must enumerate all built-in scripts (logos, meta, etc.). */ export type BuiltInRegistryScriptKey = 'bingUet' | 'blueskyEmbed' | 'carbonAds' | 'crisp' | 'clarity' | 'cloudflareWebAnalytics' | 'databuddyAnalytics' | 'metaPixel' | 'fathomAnalytics' | 'instagramEmbed' | 'plausibleAnalytics' | 'googleAdsense' | 'googleAnalytics' | 'googleMaps' | 'googleRecaptcha' | 'googleSignIn' | 'lemonSqueezy' | 'googleTagManager' | 'hotjar' | 'intercom' | 'paypal' | 'posthog' | 'matomoAnalytics' | 'mixpanelAnalytics' | 'rybbitAnalytics' | 'redditPixel' | 'segment' | 'stripe' | 'tiktokPixel' | 'xEmbed' | 'xPixel' | 'snapchatPixel' | 'youtubePlayer' | 'vercelAnalytics' | 'vimeoPlayer' | 'umamiAnalytics' | 'gravatar' | 'npm'; /** * Union of all explicit registry script keys (excludes npm pattern). * Includes both built-in and augmented keys. */ export type RegistryScriptKey = Exclude; type RegistryConfigInput = 0 extends 1 & T ? Record : [T] extends [true] ? Record : T; export type NuxtConfigScriptRegistryEntry = true | false | 'mock' | (RegistryConfigInput & { trigger?: NuxtUseScriptOptionsSerializable['trigger'] | false; proxy?: boolean; bundle?: boolean; partytown?: boolean; privacy?: ProxyPrivacyInput; }); type _NuxtConfigScriptRegistryEntries = { [K in keyof ScriptRegistry as K extends `${string}-npm` ? never : K]?: NuxtConfigScriptRegistryEntry; }; export interface NuxtConfigScriptRegistry extends _NuxtConfigScriptRegistryEntries { [key: string]: any; } export type UseFunctionType = T extends { use: infer V; } ? V extends (...args: any) => any ? ReturnType : U : U; export type EmptyOptionsSchema = ObjectSchema; type ScriptInput = Script; export type InferIfSchema = T extends ObjectSchema | UnionSchema ? InferInput : T; export interface RegistryScriptInputExtras { /** * A unique key to use for the script, this can be used to load multiple of the same script with different options. */ key?: string; scriptInput?: ScriptInput; scriptOptions?: Omit; } export type RegistryScriptInput = Partial> & RegistryScriptInputExtras; export interface RegistryScriptServerHandler { route: string; handler: string; middleware?: boolean; /** * Whether this handler verifies HMAC signatures via `withSigning()`. * * When any enabled script registers a handler with `requiresSigning: true`, * the module enforces that `NUXT_SCRIPTS_PROXY_SECRET` is set in production, * and the `/_scripts/sign` endpoint will accept this route as a signable path. */ requiresSigning?: boolean; } /** * Declares what optimization modes a script supports and what's active by default. * Each flag is an independent capability that must be explicitly opted into. */ export interface ScriptCapabilities { /** Script can be downloaded at build time and served from `/_scripts/assets/`. */ bundle?: boolean; /** * Collection requests can be proxied through `/_scripts/p/`. * When combined with `bundle`: AST URL rewriting + runtime intercept. * Without `bundle` (npm mode): autoInject sets SDK endpoint to proxy URL. */ proxy?: boolean; /** Script can run in a web worker via Partytown. */ partytown?: boolean; } /** * A third-party domain the script communicates with. * Used for proxy routing, AST rewriting, and connection warming (dns-prefetch/preconnect). */ export interface ScriptDomain { /** The domain hostname (e.g., 'www.google-analytics.com') */ domain: string; /** * Whether this domain is used lazily (e.g., only after user interaction or SDK initialization). * When `true`, connection warming uses `dns-prefetch` instead of `preconnect`. * @default false */ lazy?: boolean; } /** * Bundle capability config. When present, the script can be downloaded at * build time and served from `/_scripts/assets/`. */ export interface BundleCapability { /** Custom URL resolution. If omitted, the script's `src` is used. */ resolve?: (options?: any) => string | false; /** * AST-level SDK patches applied during bundling, independent of proxy. * Use for scripts that need self-hosted detection neutralization but should * still send beacons directly to the origin (e.g. Fathom, where proxying * triggers bot detection but bundling is otherwise safe). */ sdkPatches?: SdkPatch[]; } /** * Proxy capability config. When present, collection requests can be * proxied through `/_scripts/p/`. * When combined with bundle: AST URL rewriting + runtime intercept. * Without bundle (npm/config mode): autoInject sets SDK endpoint to proxy URL. */ export interface ProxyCapability { /** Third-party domains this script communicates with. */ domains: (string | ScriptDomain)[]; /** Privacy controls for proxied requests. */ privacy: import('../runtime/server/utils/privacy').ProxyPrivacyInput; /** Auto-inject proxy endpoint into the script's SDK config. */ autoInject?: ProxyAutoInject; /** Config fields that may contain custom external hosts or endpoints. */ configDomainFields?: string[]; /** AST-level SDK patches applied during URL rewriting. */ sdkPatches?: SdkPatch[]; } /** * Declarative SDK patch applied during AST rewriting. * Replaces fragile regex-based postProcess with targeted AST visitors. */ export type SdkPatch = { type: 'neutralize-domain-check'; domain: string; } /** * Replace `.split("")[0]` patterns used by SDKs that derive * their API host from `document.currentScript.src`. When bundled, the script src * changes, breaking this derivation. This patch replaces the expression with * the correct proxy path. */ | { type: 'replace-src-split'; separator: string; fromDomain: string; appendPath?: string; }; /** * Partytown capability config. When present, the script can run in a * web worker via Partytown. */ export interface PartytownCapability { /** Global API forward declarations for Partytown. */ forwards: string[]; } export interface RegistryScript { /** * The config key used in `scripts.registry` in nuxt.config (e.g., 'googleAnalytics', 'plausibleAnalytics'). * Used for direct lookup from config to script. */ registryKey?: RegistryScriptKey; import?: Import; label?: string; src?: string | false; category?: string; logo?: string | { light: string; dark: string; }; /** Server handlers (routes/middleware) to register when this script is enabled. */ serverHandlers?: RegistryScriptServerHandler[]; /** Valibot schema for the script's input options. */ schema?: ObjectSchema; /** Default env var field names and values for NUXT_PUBLIC_SCRIPTS_