@@ -17,17 +17,27 @@ export function registerTypeTemplates({ config, newScripts }: TypeTemplateContex
1717 addTypeTemplate ( {
1818 filename : 'types/nuxt-scripts-augments.d.ts' ,
1919 getContents : ( ) => {
20+ const globalsKeys = Object . keys ( config . globals || { } )
2021 let augments = `// Generated by @nuxt/scripts
2122declare module '#app' {
2223 interface NuxtApp {
23- $scripts: Record<${ [ ...[ ...Object . keys ( config . globals || { } ) , ...Object . keys ( config . registry || { } ) ] . map ( k => `'${ k } '` ) , ...[ 'string' ] ] . join ( ' | ' ) } , import('#nuxt-scripts/types').UseScriptContext<any> | undefined>
24+ $scripts: Record<${ [ ...[ ...globalsKeys , ...Object . keys ( config . registry || { } ) ] . map ( k => `'${ k } '` ) , ...[ 'string' ] ] . join ( ' | ' ) } , import('#nuxt-scripts/types').UseScriptContext<any> | undefined>
2425 _scripts: Record<string, import('#nuxt-scripts/types').NuxtDevToolsScriptInstance>
2526 }
2627 interface RuntimeNuxtHooks {
2728 'scripts:updated': (ctx: { scripts: Record<string, import('#nuxt-scripts/types').NuxtDevToolsScriptInstance> }) => void | Promise<void>
2829 }
2930}
31+ ${ globalsKeys . length
32+ ? `declare module '@nuxt/schema' {
33+ interface PublicRuntimeConfig {
34+ scriptsGlobals?: {
35+ ${ globalsKeys . map ( k => ` ${ JSON . stringify ( k ) } ?: Record<string, any>` ) . join ( '\n' ) }
36+ }
37+ }
38+ }
3039`
40+ : '' } `
3141
3242 if ( newScripts . length ) {
3343 augments += `
@@ -142,45 +152,66 @@ export function templatePlugin(config: Partial<ModuleOptions>, registry: Require
142152 inits . push ( `const ${ k } = ${ importDefinition . import . name } (${ argsJson } )` )
143153 }
144154 }
155+ // Globals input is merged at runtime so `runtimeConfig.public['nuxt-scripts'].globals[<key>]`
156+ // (set via env vars like NUXT_PUBLIC_NUXT_SCRIPTS_GLOBALS_<KEY>_<FIELD>) wins over
157+ // the build-time defaults. scriptOptions/object-triggers stay compile-time.
158+ const hasGlobals = Object . keys ( config . globals || { } ) . length > 0
145159 for ( const [ k , c ] of Object . entries ( config . globals || { } ) ) {
160+ let buildInput : Record < string , any >
161+ let extraOptions : Record < string , any > | undefined
146162 if ( typeof c === 'string' ) {
147- inits . push ( `const ${ k } = useScript( ${ JSON . stringify ( { src : c , key : k } ) } , { use: () => ({ ${ k } : window. ${ k } }) })` )
163+ buildInput = { src : c }
148164 }
149165 else if ( Array . isArray ( c ) && c . length === 2 ) {
150- const options = c [ 1 ]
151- const triggerResolved = resolveTriggerForTemplate ( options ?. trigger )
152- if ( triggerResolved ) {
153- if ( triggerResolved . includes ( 'useScriptTriggerIdleTimeout' ) )
154- needsIdleTimeoutImport = true
155- if ( triggerResolved . includes ( 'useScriptTriggerInteraction' ) )
156- needsInteractionImport = true
157- if ( triggerResolved . includes ( 'useScriptTriggerServiceWorker' ) )
158- needsServiceWorkerImport = true
159- const resolvedOptions = { ...options , trigger : '__TRIGGER_PLACEHOLDER__' } as any
160- const optionsJson = JSON . stringify ( resolvedOptions ) . replace ( TRIGGER_PLACEHOLDER_RE , triggerResolved )
161- inits . push ( `const ${ k } = useScript(${ JSON . stringify ( { key : k , ...( typeof c [ 0 ] === 'string' ? { src : c [ 0 ] } : c [ 0 ] ) } ) } , { ...${ optionsJson } , use: () => ({ ${ k } : window.${ k } }) })` )
162- }
163- else {
164- inits . push ( `const ${ k } = useScript(${ JSON . stringify ( { key : k , ...( typeof c [ 0 ] === 'string' ? { src : c [ 0 ] } : c [ 0 ] ) } ) } , { ...${ JSON . stringify ( c [ 1 ] ) } , use: () => ({ ${ k } : window.${ k } }) })` )
165- }
166+ buildInput = typeof c [ 0 ] === 'string' ? { src : c [ 0 ] } : { ...( c [ 0 ] as any ) }
167+ extraOptions = c [ 1 ] as any
166168 }
167169 else if ( typeof c === 'object' && c !== null ) {
168- const triggerResolved = resolveTriggerForTemplate ( ( c as any ) . trigger )
169- if ( triggerResolved ) {
170- if ( triggerResolved . includes ( 'useScriptTriggerIdleTimeout' ) )
170+ buildInput = { ...( c as any ) }
171+ }
172+ else {
173+ continue
174+ }
175+ // Object-form triggers in the input bag need a placeholder substitution after JSON.stringify.
176+ const inputTrigger = buildInput . trigger
177+ const inputTriggerResolved = resolveTriggerForTemplate ( inputTrigger )
178+ if ( inputTriggerResolved )
179+ buildInput . trigger = '__TRIGGER_PLACEHOLDER__'
180+ let buildInputJson = JSON . stringify ( buildInput )
181+ if ( inputTriggerResolved )
182+ buildInputJson = buildInputJson . replace ( TRIGGER_PLACEHOLDER_RE , inputTriggerResolved )
183+ const inputExpr = `Object.assign({ key: ${ JSON . stringify ( k ) } }, ${ buildInputJson } , __scriptsGlobals[${ JSON . stringify ( k ) } ] || {})`
184+
185+ // scriptOptions trigger (array form, second slot) — same dance, separate JSON.
186+ let optionsJson = ''
187+ if ( extraOptions && Object . keys ( extraOptions ) . length > 0 ) {
188+ const optsCopy : Record < string , any > = { ...extraOptions }
189+ const optsTriggerResolved = resolveTriggerForTemplate ( optsCopy . trigger )
190+ if ( optsTriggerResolved )
191+ optsCopy . trigger = '__TRIGGER_PLACEHOLDER__'
192+ optionsJson = JSON . stringify ( optsCopy )
193+ if ( optsTriggerResolved )
194+ optionsJson = optionsJson . replace ( TRIGGER_PLACEHOLDER_RE , optsTriggerResolved )
195+ if ( optsTriggerResolved ) {
196+ if ( optsTriggerResolved . includes ( 'useScriptTriggerIdleTimeout' ) )
171197 needsIdleTimeoutImport = true
172- if ( triggerResolved . includes ( 'useScriptTriggerInteraction' ) )
198+ if ( optsTriggerResolved . includes ( 'useScriptTriggerInteraction' ) )
173199 needsInteractionImport = true
174- if ( triggerResolved . includes ( 'useScriptTriggerServiceWorker' ) )
200+ if ( optsTriggerResolved . includes ( 'useScriptTriggerServiceWorker' ) )
175201 needsServiceWorkerImport = true
176- const resolvedOptions = { ...c , trigger : '__TRIGGER_PLACEHOLDER__' } as any
177- const argsJson = JSON . stringify ( { key : k , ...resolvedOptions } ) . replace ( TRIGGER_PLACEHOLDER_RE , triggerResolved )
178- inits . push ( `const ${ k } = useScript(${ argsJson } , { use: () => ({ ${ k } : window.${ k } }) })` )
179- }
180- else {
181- inits . push ( `const ${ k } = useScript(${ JSON . stringify ( { key : k , ...c } ) } , { use: () => ({ ${ k } : window.${ k } }) })` )
182202 }
183203 }
204+ if ( inputTriggerResolved ) {
205+ if ( inputTriggerResolved . includes ( 'useScriptTriggerIdleTimeout' ) )
206+ needsIdleTimeoutImport = true
207+ if ( inputTriggerResolved . includes ( 'useScriptTriggerInteraction' ) )
208+ needsInteractionImport = true
209+ if ( inputTriggerResolved . includes ( 'useScriptTriggerServiceWorker' ) )
210+ needsServiceWorkerImport = true
211+ }
212+ const useFn = `use: () => ({ ${ k } : window.${ k } })`
213+ const optionsArg = optionsJson ? `{ ...${ optionsJson } , ${ useFn } }` : `{ ${ useFn } }`
214+ inits . push ( `const ${ k } = useScript(${ inputExpr } , ${ optionsArg } )` )
184215 }
185216 // Add conditional imports for trigger composables
186217 const triggerImports = [ ]
@@ -194,9 +225,14 @@ export function templatePlugin(config: Partial<ModuleOptions>, registry: Require
194225 triggerImports . push ( `import { useScriptTriggerServiceWorker } from '#nuxt-scripts/composables/useScriptTriggerServiceWorker'` )
195226 }
196227
228+ const setupBody : string [ ] = [ ]
229+ if ( hasGlobals )
230+ setupBody . push ( ` const __scriptsGlobals = useRuntimeConfig().public.scriptsGlobals || {}` )
231+ setupBody . push ( ...inits . map ( i => ` ${ i } ` ) )
232+ setupBody . push ( ` return { provide: { scripts: { ${ [ ...Object . keys ( config . globals || { } ) , ...resolvedRegistryKeys ] . join ( ', ' ) } } } }` )
197233 return [
198234 `import { useScript } from '#nuxt-scripts/composables/useScript'` ,
199- `import { defineNuxtPlugin } from 'nuxt/app'` ,
235+ `import { defineNuxtPlugin${ hasGlobals ? ', useRuntimeConfig' : '' } } from 'nuxt/app'` ,
200236 ...triggerImports ,
201237 ...imports ,
202238 '' ,
@@ -205,8 +241,7 @@ export function templatePlugin(config: Partial<ModuleOptions>, registry: Require
205241 ` env: { islands: false },` ,
206242 ` parallel: true,` ,
207243 ` setup() {` ,
208- ...inits . map ( i => ` ${ i } ` ) ,
209- ` return { provide: { scripts: { ${ [ ...Object . keys ( config . globals || { } ) , ...resolvedRegistryKeys ] . join ( ', ' ) } } } }` ,
244+ ...setupBody ,
210245 ` }` ,
211246 `})` ,
212247 ] . join ( '\n' )
0 commit comments