import type * as d from '../../declarations' ; import { sortBy } from '@utils' ; import { getDefaultBundles } from './default-bundles' ; param config param defaultBundles param allCmps returns export function computeUsedComponents ( config , defaultBundles , allCmps ) { if ( ! config . excludeUnusedDependencies ) { return new Set ( allCmps . map ( ( c ) => c . tagName ) ) ; } const usedComponents = new Set < string > ( ) ; defaultBundles . forEach ( ( entry ) => { entry . forEach ( ( cmp ) => usedComponents . add ( cmp . tagName ) ) ; } ) ; allCmps . forEach ( ( cmp ) => { if ( ! cmp . isCollectionDependency ) { usedComponents . add ( cmp . tagName ) ; } } ) ; allCmps . forEach ( ( cmp ) => { if ( cmp . isCollectionDependency ) { if ( cmp . dependents . some ( ( dep ) => usedComponents . has ( dep ) ) ) { usedComponents . add ( cmp . tagName ) ; } } } ) ; return usedComponents ; } param config param buildCtx returns export function generateComponentBundles ( config , buildCtx ) { const cmps = sortBy ( buildCtx . components , ( cmp ) => cmp . dependents . length ) ; const defaultBundles = getDefaultBundles ( config , buildCtx , cmps ) ; const usedComponents = computeUsedComponents ( config , defaultBundles , cmps ) ; if ( config . devMode ) { return cmps . filter ( ( c ) => usedComponents . has ( c . tagName ) ) . map ( ( cmp ) => [ cmp ] ) ; } const alreadyBundled = new Set ( ) ; defaultBundles . forEach ( ( entry ) => { entry . forEach ( ( cmp ) => alreadyBundled . add ( cmp ) ) ; } ) ; const bundlers = cmps . filter ( ( cmp ) => usedComponents . has ( cmp . tagName ) && ! alreadyBundled . has ( cmp ) ) . map ( ( c ) => [ c ] ) ; return [ ... defaultBundles , ... optimizeBundlers ( bundlers , 0.6 ) ] . filter ( ( b ) => b . length > 0 ) ; } param bundles param threshold returns function optimizeBundlers ( bundles , threshold ) { /**
     * build a mapping of component tag names in each `bundles` entry to the index where that entry occurs in `bundles`:
     * ```ts
     * bundles = [
     *   [
     *     {
     *       tagName: 'my-foo', ...<other_fields>,
     *     },
     *   ],
     *   [
     *     {
     *       tagName: 'my-bar', ...<other_fields>,
     *     },
     *     {
     *       tagName: 'my-baz', ...<other_fields>,
     *     },
     *   ],
     * ];
     * // yields
     * {
     *   'my-foo': 0,
     *   'my-bar': 1,
     *   'my-baz': 1,
     * }
     * ```
     * note that in the event of a component being found >1 time, store the index of the last entry in which it's found
     */ const cmpIndexMap = new Map < string , number > ( ) ; bundles . forEach ( ( entry , index ) => { entry . forEach ( ( cmp ) => { cmpIndexMap . set ( cmp . tagName , index ) ; } ) ; } ) ; const matrix = bundles . map ( ( entry ) => { const vector = new Uint8Array ( bundles . length ) ; entry . forEach ( ( cmp ) => { cmp . dependents . forEach ( ( tag ) => { const index = cmpIndexMap . get ( tag ) ; if ( index !== undefined ) { vector [ index ] = 1 ; } } ) ; } ) ; entry . forEach ( ( cmp ) => { const index = cmpIndexMap . get ( cmp . tagName ) ; if ( index !== undefined ) { vector [ index ] = 0 ; } } ) ; return vector ; } ) ; const newBundles = [ ] ; const visited = new Uint8Array ( bundles . length ) ; for ( let i = 0 ; i < matrix . length ; i ++ ) { if ( visited [ i ] === 0 ) { const bundle = [ ... bundles [ i ] ] ; visited [ i ] = 1 ; for ( let j = i + 1 ; j < matrix . length ; j ++ ) { if ( visited [ j ] === 0 && computeScore ( matrix [ i ] , matrix [ j ] ) >= threshold ) { bundle . push ( ... bundles [ j ] ) ; visited [ j ] = 1 ; } } newBundles . push ( bundle ) ; } } return newBundles ; } param m0 param m1 returns function computeScore ( m0 , m1 ) { let total = 0 ; let match = 0 ; for ( let i = 0 ; i < m0 . length ; i ++ ) { if ( m0 [ i ] === 1 || m1 [ i ] === 1 ) { total ++ ; if ( m0 [ i ] === m1 [ i ] ) { match ++ ; } } } return match / total ; }