import type * as d from '../../../declarations' ; import { createImportStatement , getModuleFromSourceFile } from '../transform-utils' ; import { dashToPascalCase } from '@utils' ; import ts from 'typescript' ; import { createComponentMetadataProxy } from '../add-component-meta-proxy' ; import { addCoreRuntimeApi , RUNTIME_APIS } from '../core-runtime-apis' ; param compilerCtx param components param outputTarget returns export const addDefineCustomElementFunctions = ( compilerCtx , components , outputTarget ) : ts . TransformerFactory < ts . SourceFile > => { return ( ) => { return ( tsSourceFile ) : ts . SourceFile => { const moduleFile = getModuleFromSourceFile ( compilerCtx , tsSourceFile ) ; const newStatements = [ ] ; const caseStatements = [ ] ; const tagNames = [ ] ; addCoreRuntimeApi ( moduleFile , RUNTIME_APIS . proxyCustomElement ) ; if ( moduleFile . cmps . length ) { const principalComponent = moduleFile . cmps [ 0 ] ; tagNames . push ( principalComponent . tagName ) ; const proxyDefinition = createComponentMetadataProxy ( principalComponent ) ; const metaExpression = ts . factory . createExpressionStatement ( ts . factory . createBinaryExpression ( ts . factory . createIdentifier ( principalComponent . componentClassName ) , ts . factory . createToken ( ts . SyntaxKind . EqualsToken ) , proxyDefinition ) ) ; newStatements . push ( metaExpression ) ; ts . addSyntheticLeadingComment ( proxyDefinition , ts . SyntaxKind . MultiLineCommentTrivia , '@__PURE__' , false ) ; const customElementsDefineCallExpression = ts . factory . createCallExpression ( ts . factory . createPropertyAccessExpression ( ts . factory . createIdentifier ( 'customElements' ) , 'define' ) , undefined , [ ts . factory . createIdentifier ( 'tagName' ) , ts . factory . createIdentifier ( principalComponent . componentClassName ) ] ) ; caseStatements . push ( createCustomElementsDefineCase ( principalComponent . tagName , customElementsDefineCallExpression ) ) ; setupComponentDependencies ( moduleFile , components , newStatements , caseStatements , tagNames ) ; addDefineCustomElementFunction ( tagNames , newStatements , caseStatements ) ; if ( outputTarget . autoDefineCustomElements ) { const conditionalDefineCustomElementCall = createAutoDefinitionExpression ( principalComponent . componentClassName ) ; newStatements . push ( conditionalDefineCustomElementCall ) ; } } tsSourceFile = ts . factory . updateSourceFile ( tsSourceFile , [ ... tsSourceFile . statements , ... newStatements ] ) ; return tsSourceFile ; } ; } ; } ; param moduleFile param components param newStatements param caseStatements param tagNames const setupComponentDependencies = ( moduleFile , components , newStatements , caseStatements , tagNames ) => { moduleFile . cmps . forEach ( ( cmp ) => { cmp . dependencies . forEach ( ( dCmp ) => { const foundDep = components . find ( ( dComp ) => dComp . tagName === dCmp ) ; const exportName = dashToPascalCase ( foundDep . tagName ) ; const importAs = `$${ exportName }DefineCustomElement` ; tagNames . push ( foundDep . tagName ) ; newStatements . push ( createImportStatement ( [ `defineCustomElement as ${ importAs }` ] , foundDep . sourceFilePath ) ) ; const callExpression = ts . factory . createCallExpression ( ts . factory . createIdentifier ( importAs ) , undefined , [ ] ) ; caseStatements . push ( createCustomElementsDefineCase ( foundDep . tagName , callExpression ) ) ; } ) ; } ) ; } ; param tagName param actionExpression returns const createCustomElementsDefineCase = ( tagName , actionExpression ) : ts . CaseClause => { return ts . factory . createCaseClause ( ts . factory . createStringLiteral ( tagName ) , [ ts . factory . createIfStatement ( ts . factory . createPrefixUnaryExpression ( ts . SyntaxKind . ExclamationToken , ts . factory . createCallExpression ( ts . factory . createPropertyAccessExpression ( ts . factory . createIdentifier ( 'customElements' ) , 'get' ) , undefined , [ ts . factory . createIdentifier ( 'tagName' ) ] ) ) , ts . factory . createBlock ( [ ts . factory . createExpressionStatement ( actionExpression ) ] ) ) , ts . factory . createBreakStatement ( ) , ] ) ; } ; param tagNames param newStatements param caseStatements const addDefineCustomElementFunction = ( tagNames , newStatements , caseStatements ) => { const newExpression = ts . factory . createFunctionDeclaration ( undefined , [ ts . factory . createModifier ( ts . SyntaxKind . ExportKeyword ) ] , undefined , ts . factory . createIdentifier ( 'defineCustomElement' ) , undefined , undefined , undefined , ts . factory . createBlock ( [ ts . factory . createIfStatement ( ts . factory . createStrictEquality ( ts . factory . createTypeOfExpression ( ts . factory . createIdentifier ( 'customElements' ) ) , ts . factory . createStringLiteral ( 'undefined' ) ) , ts . factory . createBlock ( [ ts . factory . createReturnStatement ( ) ] ) ) , ts . factory . createVariableStatement ( undefined , ts . factory . createVariableDeclarationList ( [ ts . factory . createVariableDeclaration ( 'components' , undefined , undefined , ts . factory . createArrayLiteralExpression ( tagNames . map ( ( tagName ) => ts . factory . createStringLiteral ( tagName ) ) ) ) , ] , ts . NodeFlags . Const ) ) , ts . factory . createExpressionStatement ( ts . factory . createCallExpression ( ts . factory . createPropertyAccessExpression ( ts . factory . createIdentifier ( 'components' ) , 'forEach' ) , undefined , [ ts . factory . createArrowFunction ( undefined , undefined , [ ts . factory . createParameterDeclaration ( undefined , undefined , undefined , ts . factory . createIdentifier ( 'tagName' ) , undefined , undefined ) , ] , undefined , ts . factory . createToken ( ts . SyntaxKind . EqualsGreaterThanToken ) , ts . factory . createBlock ( [ ts . factory . createSwitchStatement ( ts . factory . createIdentifier ( 'tagName' ) , ts . factory . createCaseBlock ( caseStatements ) ) , ] ) ) , ] ) ) , ] , true ) ) ; newStatements . push ( newExpression ) ; } ; returns function createAutoDefinitionExpression ( componentName ) { return ts . factory . createExpressionStatement ( ts . factory . createCallExpression ( ts . factory . createIdentifier ( 'defineCustomElement' ) , undefined , [ ts . factory . createIdentifier ( componentName ) , ] ) ) ; }