import type * as d from '../../declarations' ; import MagicString from 'magic-string' ; import { createJsVarName , normalizePath , isString , loadTypeScriptDiagnostics } from '@utils' ; import type { LoadResult , Plugin , ResolveIdResult , TransformResult } from 'rollup' ; import { removeCollectionImports } from '../transformers/remove-collection-imports' ; import { APP_DATA_CONDITIONAL , STENCIL_APP_DATA_ID , STENCIL_APP_GLOBALS_ID , STENCIL_CORE_ID , STENCIL_INTERNAL_HYDRATE_ID , } from './entry-alias-ids' ; import ts from 'typescript' ; import { basename } from 'path' ; export const appDataPlugin = ( config , compilerCtx , buildCtx , build , platform ) : Plugin => { if ( ! platform ) { return { name : 'appDataPlugin' , } ; } const globalScripts = getGlobalScriptData ( config , compilerCtx ) ; return { name : 'appDataPlugin' , resolveId ( id , importer ) { if ( id === STENCIL_APP_DATA_ID || id === STENCIL_APP_GLOBALS_ID ) { if ( platform === 'worker' ) { this . error ( '@stencil/core packages cannot be imported from a worker.' ) ; } if ( platform === 'hydrate' || STENCIL_APP_GLOBALS_ID ) { return id ; } else if ( platform === 'client' && importer && importer . endsWith ( APP_DATA_CONDITIONAL ) ) { return id ; } } return null ; } , load ( id ) { if ( id === STENCIL_APP_GLOBALS_ID ) { const s = new MagicString ( `` ) ; appendGlobalScripts ( globalScripts , s ) ; return s . toString ( ) ; } if ( id === STENCIL_APP_DATA_ID ) { const s = new MagicString ( `` ) ; appendNamespace ( config , s ) ; appendBuildConditionals ( config , build , s ) ; appendEnv ( config , s ) ; return s . toString ( ) ; } if ( id !== config . globalScript ) { return null ; } const module = compilerCtx . moduleMap . get ( config . globalScript ) ; if ( ! module ) { return null ; } else if ( ! module . sourceMapFileText ) { return { code : module . staticSourceFileText , map : null , } ; } const sourceMap = JSON . parse ( module . sourceMapFileText ) ; sourceMap . sources = sourceMap . sources . map ( ( src ) => basename ( src ) ) ; return { code : module . staticSourceFileText , map : sourceMap } ; } , transform ( code , id ) { id = normalizePath ( id ) ; if ( globalScripts . some ( ( s ) => s . path === id ) ) { const program = this . parse ( code , { } ) ; const needsDefault = ! ( program as any ) . body . some ( ( s ) => s . type === 'ExportDefaultDeclaration' ) ; const defaultExport = needsDefault ? '\nexport const globalFn = () => {};\nexport default globalFn;' : '' ; code = getContextImport ( platform ) + code + defaultExport ; const compilerOptions = { ... config . tsCompilerOptions } ; compilerOptions . module = ts . ModuleKind . ESNext ; const results = ts . transpileModule ( code , { compilerOptions , fileName : id , transformers : { after : [ removeCollectionImports ( compilerCtx ) ] , } , } ) ; buildCtx . diagnostics . push ( ... loadTypeScriptDiagnostics ( results . diagnostics ) ) ; if ( config . sourceMap ) { const codeMs = new MagicString ( code ) ; const codeMap = codeMs . generateMap ( { source : id , file : id + '.map' , includeContent : true , hires : true , } ) ; return { code : results . outputText , map : codeMap } ; } return { code : results . outputText } ; } return null ; } , } ; } ; export const getGlobalScriptData = ( config , compilerCtx ) => { const globalScripts = [ ] ; if ( isString ( config . globalScript ) ) { const mod = compilerCtx . moduleMap . get ( config . globalScript ) ; const globalScript = compilerCtx . version === 2 ? config . globalScript : mod && mod . jsFilePath ; if ( globalScript ) { globalScripts . push ( { defaultName : createJsVarName ( config . namespace + 'GlobalScript' ) , path : normalizePath ( globalScript ) , } ) ; } } compilerCtx . collections . forEach ( ( collection ) => { if ( collection . global != null && isString ( collection . global . sourceFilePath ) ) { let defaultName = createJsVarName ( collection . collectionName + 'GlobalScript' ) ; if ( globalScripts . some ( ( s ) => s . defaultName === defaultName ) ) { defaultName += globalScripts . length ; } globalScripts . push ( { defaultName , path : normalizePath ( collection . global . sourceFilePath ) , } ) ; } } ) ; return globalScripts ; } ; const appendGlobalScripts = ( globalScripts , s ) => { if ( globalScripts . length === 1 ) { s . prepend ( `import appGlobalScript from '${ globalScripts [ 0 ] . path }';\n` ) ; s . append ( `export const globalScripts = appGlobalScript;\n` ) ; } else if ( globalScripts . length > 1 ) { globalScripts . forEach ( ( globalScript ) => { s . prepend ( `import ${ globalScript . defaultName } from '${ globalScript . path }';\n` ) ; } ) ; s . append ( `export const globalScripts = () => {\n` ) ; globalScripts . forEach ( ( globalScript ) => { s . append ( `  ${ globalScript . defaultName }();\n` ) ; } ) ; s . append ( `};\n` ) ; } else { s . append ( `export const globalScripts = () => {};\n` ) ; } } ; const appendBuildConditionals = ( config , build , s ) => { const buildData = Object . keys ( build ) . sort ( ) . map ( ( key ) => key + ': ' + ( ( build as any ) [ key ] ? 'true' : 'false' ) ) . join ( ', ' ) ; s . append ( `export const BUILD = /* ${ config . fsNamespace } */ { ${ buildData } };\n` ) ; } ; const appendEnv = ( config , s ) => { s . append ( `export const Env = /* ${ config . fsNamespace } */ ${ JSON . stringify ( config . env ) };\n` ) ; } ; const appendNamespace = ( config , s ) => { s . append ( `export const NAMESPACE = '${ config . fsNamespace }';\n` ) ; } ; const getContextImport = ( platform ) => { return `import { Context } from '${ platform === 'hydrate' ? STENCIL_INTERNAL_HYDRATE_ID : STENCIL_CORE_ID }';\n` ; } ; interface GlobalScript { defaultName : string ; path : string ; }