@@ -38,6 +38,16 @@ export interface CollectorOptions {
3838 retryIngestionDelayMs ?: number ; // delay after snapshot submission before retrying dependency review on 404 (default: 3000ms)
3939}
4040
41+ interface ParsedQuery {
42+ raw : string ;
43+ lower : string ;
44+ isPrefixWildcard : boolean ;
45+ exact ?: string ;
46+ type ?: string ;
47+ name ?: string ;
48+ versionConstraint ?: string ;
49+ }
50+
4151export class SbomCollector {
4252 private octokit : ReturnType < typeof createOctokit > | undefined ; // explicit type
4353 private opts : Required < CollectorOptions > ;
@@ -562,15 +572,7 @@ export class SbomCollector {
562572 // New method including the query that produced each match
563573 searchByPurlsWithReasons ( purls : string [ ] ) : Map < string , { purl : string ; reason : string } [ ] > {
564574 purls = purls . map ( q => q . startsWith ( "pkg:" ) ? q : `pkg:${ q } ` ) ;
565- interface ParsedQuery {
566- raw : string ;
567- lower : string ;
568- isPrefixWildcard : boolean ;
569- exact ?: string ;
570- type ?: string ;
571- name ?: string ;
572- versionConstraint ?: string ;
573- }
575+
574576 const looksLikeSemverRange = ( v : string ) => / [ \^ ~ > < = ] | \| \| / . test ( v . trim ( ) ) ;
575577 const parseQuery = ( raw : string ) : ParsedQuery | null => {
576578 const trimmed = raw . trim ( ) ;
@@ -598,7 +600,37 @@ export class SbomCollector {
598600 const queries : ParsedQuery [ ] = purls . map ( parseQuery ) . filter ( ( q ) : q is ParsedQuery => ! ! q ) ;
599601 const results = new Map < string , { purl : string ; reason : string } [ ] > ( ) ;
600602 if ( ! queries . length ) return results ;
601- // Move applyQueries to module scope
603+
604+ for ( const repoSbom of this . sboms ) {
605+ if ( repoSbom . error ) continue ;
606+ interface ExtRef { referenceType : string ; referenceLocator : string }
607+ const found = new Map < string , string > ( ) ; // purl -> query
608+ for ( const pkg of repoSbom . packages as Array < SbomPackage & { externalRefs ?: ExtRef [ ] } > ) {
609+ const refs = pkg . externalRefs ;
610+ const candidatePurls : string [ ] = [ ] ;
611+ if ( refs ) for ( const r of refs ) if ( r . referenceType === "purl" && r . referenceLocator ) candidatePurls . push ( r . referenceLocator ) ;
612+ if ( ( pkg as { purl ?: string } ) . purl ) candidatePurls . push ( ( pkg as { purl ?: string } ) . purl as string ) ;
613+ applyQueries ( candidatePurls , queries , found , undefined , ( pkg . version as string | undefined ) || undefined ) ;
614+ }
615+ // Include dependency review diff additions/updates (head packages only)
616+ if ( repoSbom . branchDiffs ) {
617+ const diffs = repoSbom . branchDiffs . values ( ) ;
618+ for ( const diff of diffs ) {
619+ for ( const change of diff . changes ) {
620+ if ( change . changeType !== "added" && change . changeType !== "updated" ) continue ;
621+ const candidatePurls : string [ ] = [ ] ;
622+ if ( ( change as { purl ?: string } ) . purl ) candidatePurls . push ( ( change as { purl ?: string } ) . purl as string ) ;
623+ if ( change . packageURL ) candidatePurls . push ( change . packageURL ) ;
624+ applyQueries ( candidatePurls , queries , found , diff . head , change . version ) ;
625+ }
626+ }
627+ }
628+ if ( found . size ) results . set ( repoSbom . repo , Array . from ( found . entries ( ) ) . map ( ( [ purl , reason ] ) => ( { purl, reason } ) ) ) ;
629+ }
630+ return results ;
631+ }
632+ }
633+
602634function applyQueries (
603635 candidatePurls : string [ ] ,
604636 queries : ParsedQuery [ ] ,
@@ -639,33 +671,4 @@ function applyQueries(
639671 }
640672 }
641673 }
642- }
643- for ( const repoSbom of this . sboms ) {
644- if ( repoSbom . error ) continue ;
645- interface ExtRef { referenceType : string ; referenceLocator : string }
646- const found = new Map < string , string > ( ) ; // purl -> query
647- for ( const pkg of repoSbom . packages as Array < SbomPackage & { externalRefs ?: ExtRef [ ] } > ) {
648- const refs = pkg . externalRefs ;
649- const candidatePurls : string [ ] = [ ] ;
650- if ( refs ) for ( const r of refs ) if ( r . referenceType === "purl" && r . referenceLocator ) candidatePurls . push ( r . referenceLocator ) ;
651- if ( ( pkg as { purl ?: string } ) . purl ) candidatePurls . push ( ( pkg as { purl ?: string } ) . purl as string ) ;
652- applyQueries ( candidatePurls , queries , found , undefined , ( pkg . version as string | undefined ) || undefined ) ;
653- }
654- // Include dependency review diff additions/updates (head packages only)
655- if ( repoSbom . branchDiffs ) {
656- const diffs = repoSbom . branchDiffs . values ( ) ;
657- for ( const diff of diffs ) {
658- for ( const change of diff . changes ) {
659- if ( change . changeType !== "added" && change . changeType !== "updated" ) continue ;
660- const candidatePurls : string [ ] = [ ] ;
661- if ( ( change as { purl ?: string } ) . purl ) candidatePurls . push ( ( change as { purl ?: string } ) . purl as string ) ;
662- if ( change . packageURL ) candidatePurls . push ( change . packageURL ) ;
663- applyQueries ( candidatePurls , queries , found , diff . head , change . version ) ;
664- }
665- }
666- }
667- if ( found . size ) results . set ( repoSbom . repo , Array . from ( found . entries ( ) ) . map ( ( [ purl , reason ] ) => ( { purl, reason } ) ) ) ;
668- }
669- return results ;
670- }
671674}
0 commit comments