@@ -206,7 +206,6 @@ export class CycloneDxWebpackPlugin {
206206
207207 const bom = new CDX . Models . Bom ( )
208208 bom . metadata . lifecycles . add ( CDX . Enums . LifecyclePhase . Build )
209- bom . metadata . component = this . #makeRootComponent( compilation . compiler . context , cdxComponentBuilder , logger . getChildLogger ( 'RootComponentBuilder' ) )
210209
211210 const serializeOptions : CDX . Serialize . Types . SerializerOptions & CDX . Serialize . Types . NormalizerOptions = {
212211 sortLists : this . reproducibleResults ,
@@ -247,6 +246,9 @@ export class CycloneDxWebpackPlugin {
247246 }
248247 }
249248
249+ const rcDesc = getPackageDescription ( compilation . compiler . context )
250+ ?? { path : compilation . compiler . context }
251+
250252 compilation . hooks . afterOptimizeTree . tap (
251253 pluginName ,
252254 ( _ , modules ) => {
@@ -259,23 +261,38 @@ export class CycloneDxWebpackPlugin {
259261 )
260262
261263 thisLogger . log ( 'generating components...' )
262- for ( const component of extractor . generateComponents ( modules , this . collectEvidence , thisLogger . getChildLogger ( 'Extractor' ) ) ) {
263- if ( bom . metadata . component !== undefined &&
264- bom . metadata . component . group === component . group &&
265- bom . metadata . component . name === component . name &&
266- bom . metadata . component . version === component . version
267- ) {
268- // metadata matches this exact component.
269- // -> so the component is actually treated as the root component.
270- thisLogger . debug ( 'update bom.metadata.component - replace' , bom . metadata . component , 'with' , component )
271- bom . metadata . component = component
264+ const components = extractor . generateComponents ( modules , this . collectEvidence , thisLogger . getChildLogger ( 'Extractor' ) )
265+ const rcComponentDetected = components . get ( rcDesc . path )
266+ if ( undefined !== rcComponentDetected ) {
267+ if ( this . rootComponentAutodetect ) {
268+ thisLogger . debug ( 'add to bom.metadata.component' , rcComponentDetected )
269+ bom . metadata . component = rcComponentDetected
270+ components . delete ( rcDesc . path )
272271 } else {
272+ const rcComponent = cdxComponentBuilder . makeComponent ( {
273+ name : this . rootComponentName ,
274+ version : this . rootComponentVersion ,
275+ } )
276+ if ( rcComponent !== undefined ) {
277+ rcComponent . dependencies = rcComponentDetected . dependencies
278+ for ( const { dependencies} of components . values ( ) ) {
279+ if ( dependencies . delete ( rcComponentDetected . bomRef ) ) {
280+ dependencies . add ( rcComponent . bomRef )
281+ }
282+ }
283+ thisLogger . debug ( 'add to bom.metadata.component' , rcComponentDetected )
284+ bom . metadata . component = rcComponent
285+ components . delete ( rcDesc . path )
286+ }
287+ }
288+ }
289+ for ( const component of components . values ( ) ) {
273290 thisLogger . debug ( 'add to bom.components' , component )
274291 bom . components . add ( component )
275- }
276292 }
277293 thisLogger . log ( 'generated components.' )
278294
295+
279296 thisLogger . log ( 'finalizing BOM...' )
280297 this . #finalizeBom( bom , cdxComponentBuilder , cdxPurlFactory , logger . getChildLogger ( 'BomFinalizer' ) )
281298 thisLogger . log ( 'finalized BOM.' )
@@ -368,25 +385,6 @@ export class CycloneDxWebpackPlugin {
368385 }
369386 }
370387
371- #makeRootComponent (
372- path : string ,
373- builder : CDX . Builders . FromNodePackageJson . ComponentBuilder ,
374- logger : WebpackLogger
375- ) : CDX . Models . Component | undefined {
376- /* eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- expected */
377- const thisPackageJson = this . rootComponentAutodetect
378- ? getPackageDescription ( path ) ?. packageJson
379- : { name : this . rootComponentName , version : this . rootComponentVersion }
380- if ( thisPackageJson === undefined ) { return undefined }
381- normalizePackageManifest (
382-
383- thisPackageJson ,
384- w => { logger . debug ( 'normalizePackageJson from PkgPath' , path , 'caused:' , w ) }
385- )
386-
387- return builder . makeComponent ( thisPackageJson )
388- }
389-
390388 #finalizeBom (
391389 bom : CDX . Models . Bom ,
392390 cdxComponentBuilder : CDX . Builders . FromNodePackageJson . ComponentBuilder ,
@@ -410,12 +408,13 @@ export class CycloneDxWebpackPlugin {
410408 bom . metadata . tools . components . add ( toolC )
411409 }
412410
413- if ( bom . metadata . component !== undefined ) {
414- this . #addRootComponentExtRefs( bom . metadata . component , logger )
411+ const rComponent = bom . metadata . component
412+ if ( rComponent !== undefined ) {
413+ this . #addRootComponentExtRefs( rComponent , logger )
415414 /* eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- ack */
416- bom . metadata . component . type = this . rootComponentType as CDX . Models . Component [ 'type' ]
417- bom . metadata . component . purl = cdxPurlFactory . makeFromComponent ( bom . metadata . component )
418- bom . metadata . component . bomRef . value = bom . metadata . component . purl ?. toString ( )
415+ rComponent . type = this . rootComponentType as CDX . Models . Component [ 'type' ]
416+ rComponent . purl = cdxPurlFactory . makeFromComponent ( rComponent )
417+ rComponent . bomRef . value = rComponent . purl ?. toString ( )
419418 }
420419 /* eslint-enable no-param-reassign */
421420 }
0 commit comments