import { byteSize , sortBy } from '@utils' ; import type * as d from '../../declarations' ; import { isOutputTargetStats } from '../output-targets/output-utils' ; param config param buildCtx returns export function generateBuildStats ( config , buildCtx ) { const buildResults = buildCtx . buildResults ; let jsonData ; try { if ( buildResults . hasError ) { jsonData = { diagnostics : buildResults . diagnostics , } ; } else { const stats = { timestamp : buildResults . timestamp , compiler : { name : config . sys . name , version : config . sys . version , } , app : { namespace : config . namespace , fsNamespace : config . fsNamespace , components : Object . keys ( buildResults . componentGraph ) . length , entries : Object . keys ( buildResults . componentGraph ) . length , bundles : buildResults . outputs . reduce ( ( total , en ) => total + en . files . length , 0 ) , outputs : getAppOutputs ( config , buildResults ) , } , options : { minifyJs : config . minifyJs , minifyCss : config . minifyCss , hashFileNames : config . hashFileNames , hashedFileNameLength : config . hashedFileNameLength , buildEs5 : config . buildEs5 , } , formats : { esmBrowser : sanitizeBundlesForStats ( buildCtx . esmBrowserComponentBundle ) , esm : sanitizeBundlesForStats ( buildCtx . esmComponentBundle ) , es5 : sanitizeBundlesForStats ( buildCtx . es5ComponentBundle ) , system : sanitizeBundlesForStats ( buildCtx . systemComponentBundle ) , commonjs : sanitizeBundlesForStats ( buildCtx . commonJsComponentBundle ) , } , components : getComponentsFileMap ( config , buildCtx ) , entries : buildCtx . entryModules , componentGraph : buildResults . componentGraph , sourceGraph : getSourceGraph ( config , buildCtx ) , rollupResults : buildCtx . rollupResults , collections : getCollections ( config , buildCtx ) , } ; jsonData = stats ; } } catch ( e ) { jsonData = { diagnostics : [ e . message ] , } ; } return jsonData ; } param config param buildCtx returns export async function writeBuildStats ( config , data ) { const statsTargets = config . outputTargets . filter ( isOutputTargetStats ) ; await Promise . all ( statsTargets . map ( async ( outputTarget ) => { const result = await config . sys . writeFile ( outputTarget . file , JSON . stringify ( data , null , 2 ) ) ; if ( result . error ) { config . logger . warn ( [ `Stats failed to write file to ${ outputTarget . file }` ] ) ; } } ) ) ; } function sanitizeBundlesForStats ( bundleArray ) { if ( ! bundleArray ) { return [ ] ; } return bundleArray . map ( ( bundle ) => { return { key : bundle . entryKey , components : bundle . cmps . map ( ( c ) => c . tagName ) , bundleId : bundle . output . bundleId , fileName : bundle . output . fileName , imports : bundle . rollupResult . imports , originalByteSize : byteSize ( bundle . rollupResult . code ) , } ; } ) ; } function getSourceGraph ( config , buildCtx ) { let sourceGraph = { } ; sortBy ( buildCtx . moduleFiles , ( m ) => m . sourceFilePath ) . forEach ( ( moduleFile ) => { const key = relativePath ( config , moduleFile . sourceFilePath ) ; sourceGraph [ key ] = moduleFile . localImports . map ( ( localImport ) => relativePath ( config , localImport ) ) . sort ( ) ; } ) ; return sourceGraph ; } function getAppOutputs ( config , buildResults ) { return buildResults . outputs . map ( ( output ) => { return { name : output . type , files : output . files . length , generatedFiles : output . files . map ( ( file ) => relativePath ( config , file ) ) , } ; } ) ; } function getComponentsFileMap ( config , buildCtx ) { return buildCtx . components . map ( ( component ) => { return { tag : component . tagName , path : relativePath ( config , component . jsFilePath ) , source : relativePath ( config , component . sourceFilePath ) , elementRef : component . elementRef , componentClassName : component . componentClassName , assetsDirs : component . assetsDirs , dependencies : component . dependencies , dependents : component . dependents , directDependencies : component . directDependencies , directDependents : component . directDependents , docs : component . docs , encapsulation : component . encapsulation , excludeFromCollection : component . excludeFromCollection , events : component . events , internal : component . internal , legacyConnect : component . legacyConnect , legacyContext : component . legacyContext , listeners : component . listeners , methods : component . methods , potentialCmpRefs : component . potentialCmpRefs , properties : component . properties , shadowDelegatesFocus : component . shadowDelegatesFocus , states : component . states , } ; } ) ; } function getCollections ( config , buildCtx ) { return buildCtx . collections . map ( ( c ) => { return { name : c . collectionName , source : relativePath ( config , c . moduleDir ) , tags : c . moduleFiles . map ( ( m ) => m . cmps . map ( ( cmp ) => cmp . tagName ) ) . sort ( ) , } ; } ) . sort ( ( a , b ) => { if ( a . name < b . name ) return - 1 ; if ( a . name > b . name ) return 1 ; return 0 ; } ) ; } function relativePath ( config , file ) { return config . sys . normalizePath ( config . sys . platformPath . relative ( config . rootDir , file ) ) ; }