@@ -36,6 +36,12 @@ export class NpmNodeModulesCollector extends NodeModulesCollector<NpmDependency,
3636
3737 protected async collectAllDependencies ( tree : NpmDependency ) {
3838 for ( const [ , value ] of Object . entries ( tree . dependencies || { } ) ) {
39+ // Skip @types packages - they're type-only and not needed at runtime
40+ if ( value . name . startsWith ( '@types/' ) ) {
41+ log . debug ( { name : value . name } , "skipping @types package" )
42+ continue
43+ }
44+
3945 const { _dependencies = { } , dependencies = { } } = value
4046 const isDuplicateDep = Object . keys ( _dependencies ) . length > 0 && Object . keys ( dependencies ) . length === 0
4147 if ( isDuplicateDep ) {
@@ -45,26 +51,48 @@ export class NpmNodeModulesCollector extends NodeModulesCollector<NpmDependency,
4551 ...value ,
4652 path : tree . path ,
4753 }
48- m . path = ( await this . resolveModuleDir ( { dependency : m , virtualPath : value . resolved } ) ) !
54+
55+ try {
56+ m . path = ( await this . resolveModuleDir ( { dependency : m , virtualPath : value . resolved } ) ) !
57+ } catch ( err : any ) {
58+ // If we can't resolve it and it's a type-related package, skip it
59+ if ( value . name . includes ( '-types' ) || value . resolved ?. includes ( '@types+' ) ) {
60+ log . debug ( { name : value . name , err : err . message } , "skipping unresolvable type package" )
61+ continue
62+ }
63+ throw err
64+ }
65+
4966 this . allDependencies . set ( this . cacheKey ( m ) , m )
5067 await this . collectAllDependencies ( m )
5168 }
5269
5370 // Collect optional dependencies if they exist
5471 for ( const [ key , value ] of Object . entries ( tree . optionalDependencies || { } ) ) {
72+ // Skip @types packages
73+ if ( key . startsWith ( '@types/' ) ) {
74+ log . debug ( { name : key } , "skipping @types optional package" )
75+ continue
76+ }
77+
5578 const m = {
5679 name : key ,
5780 version : value ,
5881 path : tree . path ,
5982 resolved : tree . path ,
6083 }
61- let p : string
84+ let p : string | null
6285 try {
63- p = ( await this . resolveModuleDir ( { dependency : m , virtualPath : value , isOptionalDependency : true } ) ) !
86+ p = await this . resolveModuleDir ( { dependency : m , virtualPath : value , isOptionalDependency : true } )
6487 } catch {
6588 // ignore. optional dependency may not be installed (we throw in resolveModuleDir in this case)
6689 continue
6790 }
91+
92+ if ( ! p ) {
93+ continue
94+ }
95+
6896 m . path = p
6997 m . resolved = p
7098 const moduleKey = this . cacheKey ( m )
@@ -83,12 +111,17 @@ export class NpmNodeModulesCollector extends NodeModulesCollector<NpmDependency,
83111 const { _dependencies : prodDependencies = { } , dependencies = { } } = tree
84112 const isDuplicateDep = Object . keys ( prodDependencies ) . length > 0 && Object . keys ( dependencies ) . length === 0
85113 const resolvedDeps = isDuplicateDep ? ( this . allDependencies . get ( dependencyId ) ?. dependencies ?? { } ) : dependencies
86- // Initialize with empty dependencies array first to mark this dependency as "in progress"
87- // After initialization, if there are libraries with the same name+version later, they will not be searched recursively again
88- // This will prevents infinite loops when circular dependencies are encountered.
114+
89115 this . productionGraph [ dependencyId ] = { dependencies : [ ] }
116+
90117 const productionDeps = Object . entries ( resolvedDeps )
91- . filter ( ( [ packageName ] ) => prodDependencies [ packageName ] )
118+ . filter ( ( [ packageName ] ) => {
119+ // Filter out @types packages
120+ if ( packageName . startsWith ( '@types/' ) ) {
121+ return false
122+ }
123+ return prodDependencies [ packageName ]
124+ } )
92125 . map ( async ( [ , dependency ] ) => {
93126 const childDependencyId = this . packageVersionString ( dependency )
94127 const dep = {
@@ -98,9 +131,9 @@ export class NpmNodeModulesCollector extends NodeModulesCollector<NpmDependency,
98131 await this . extractProductionDependencyGraph ( dep , childDependencyId )
99132 return childDependencyId
100133 } )
134+
101135 this . productionGraph [ dependencyId ] = { dependencies : await Promise . all ( productionDeps ) }
102136 }
103-
104137 protected async parseDependenciesTree ( jsonBlob : string ) : Promise < NpmDependency > {
105138 return Promise . resolve ( JSON . parse ( jsonBlob ) )
106139 }
0 commit comments