11import type { Bom } from '$lib/cyclonedx/models' ;
22import { type TreeItem , TreeItemImpl } from '$lib/models/tree' ;
33
4- export function createTreeDataFromBom ( bom : Bom ) : TreeItem [ ] {
4+ const PlaceholderTreeItemForCycle : TreeItem = new TreeItemImpl ( '[cycle]' , 'cycle' ) ;
5+
6+ export function createTreeDataFromBom ( bom : Bom , maxDepth : number = 4 ) : TreeItem [ ] {
57 const componentRefToName = new Map < string , string > ( ) ;
68 const dependencyMap = new Map < string , string [ ] > ( ) ;
79
@@ -21,40 +23,52 @@ export function createTreeDataFromBom(bom: Bom): TreeItem[] {
2123
2224 const childrenCache = new Map < string , TreeItem [ ] | undefined > ( ) ;
2325
24- function getChildTreeItems ( componentRef : string , visited : Set < string > ) : TreeItem [ ] {
25- // If we've already visited this component, return an empty array to prevent cycles
26- if ( visited . has ( componentRef ) ) {
27- console . warn ( `Cycle detected for ${ componentRef } ` ) ;
28- return [ ] ;
29- }
26+ let nodeCount = 1 ;
3027
28+ function getChildTreeItems (
29+ componentRef : string ,
30+ visited : Set < string > ,
31+ maxDepth : number
32+ ) : TreeItem [ ] {
3133 // Mark the current component as visited
3234 visited . add ( componentRef ) ;
3335
34- const parentChildren : TreeItemImpl [ ] = [ ] ;
36+ const parentChildren : TreeItem [ ] = [ ] ;
3537
36- for ( const child of dependencyMap . get ( componentRef ) ?? [ ] ) {
37- if ( componentRefToName . has ( child ) ) {
38+ for ( const childRef of dependencyMap . get ( componentRef ) ?? [ ] ) {
39+ let childName = componentRefToName . get ( childRef ) ;
40+ if ( childName ) {
3841 let childChildren ;
39- if ( childrenCache . has ( child ) ) {
40- childChildren = childrenCache . get ( child ) ;
42+ if ( maxDepth <= 0 ) {
43+ console . warn ( 'Maximum depth reached' ) ;
44+ childName += '…' ;
45+ childChildren = [ ] ;
46+ } else if ( visited . has ( childRef ) ) {
47+ // If we've already visited this component, return placeholder to prevent cycles
48+ console . warn ( `Cycle detected for ${ componentRef } ` ) ;
49+ childChildren = [ PlaceholderTreeItemForCycle ] ;
50+ } else if ( childrenCache . has ( childRef ) ) {
51+ childChildren = childrenCache . get ( childRef ) ;
4152 } else {
42- childChildren = getChildTreeItems ( child , new Set ( visited ) ) ;
43- childrenCache . set ( child , childChildren ) ;
53+ childChildren = getChildTreeItems ( childRef , new Set ( visited ) , maxDepth - 1 ) ;
54+ childrenCache . set ( childRef , childChildren ) ;
4455 }
45- parentChildren . push ( new TreeItemImpl ( componentRefToName . get ( child ) ! , child , childChildren ) ) ;
56+ nodeCount ++ ;
57+ parentChildren . push ( new TreeItemImpl ( childName , childRef , childChildren ) ) ;
4658 }
4759 }
4860
4961 return parentChildren ;
5062 }
5163
5264 if ( subject && subject [ 'bom-ref' ] ) {
53- data . push ( ...getChildTreeItems ( subject [ 'bom-ref' ] , new Set < string > ( ) ) ) ;
65+ data . push ( ...getChildTreeItems ( subject [ 'bom-ref' ] , new Set < string > ( ) , maxDepth ) ) ;
5466 } else {
5567 console . error ( `No subject found in ${ bom . metadata } ` ) ;
5668 }
5769
58- console . log ( 'Successfully created tree' ) ;
70+ console . log (
71+ `Successfully created a tree with ${ nodeCount } nodes`
72+ ) ;
5973 return data ;
6074}
0 commit comments