1- import { isEmptyOrSpaces , log } from "builder-util"
2- import * as path from "path"
1+ import { log } from "builder-util"
32import { NodeModulesCollector } from "./nodeModulesCollector"
43import { PM } from "./packageManager"
54import { PnpmDependency } from "./types"
@@ -14,67 +13,61 @@ export class PnpmNodeModulesCollector extends NodeModulesCollector<PnpmDependenc
1413 return [ "list" , "--prod" , "--json" , "--depth" , "Infinity" ]
1514 }
1615
17- private async getProductionDependencies ( depTree : PnpmDependency ) : Promise < { path : string ; dependencies : Record < string , string > ; optionalDependencies : Record < string , string > } > {
18- const packageName = depTree . name || depTree . from
19- if ( isEmptyOrSpaces ( packageName ) ) {
20- log . error ( depTree , `Cannot determine production dependencies for package with empty name` )
21- throw new Error ( `Cannot compute production dependencies for package with empty name: ${ packageName } ` )
22- }
23-
24- const result = await this . cache . locatePackageVersion ( { parentDir : depTree . path , pkgName : packageName , requiredRange : depTree . version } )
25- if ( result == null ) {
26- return { path : path . resolve ( depTree . path ) , dependencies : { } , optionalDependencies : { } }
27- }
28-
29- const { dependencies, optionalDependencies } = result . packageJson
30- return { path : result . packageDir , dependencies : { ...dependencies } , optionalDependencies : { ...optionalDependencies } }
31- }
32-
3316 protected async extractProductionDependencyGraph ( tree : PnpmDependency , dependencyId : string ) {
3417 if ( this . productionGraph [ dependencyId ] ) {
3518 return
3619 }
3720 this . productionGraph [ dependencyId ] = { dependencies : [ ] }
3821
3922 const packageName = tree . name || tree . from
23+ const { packageJson } = ( await this . cache . locatePackageVersion ( { pkgName : packageName , parentDir : this . rootDir , requiredRange : tree . version } ) ) || { }
4024
41- const treeDep = { ...( tree . dependencies || { } ) , ...( tree . optionalDependencies || { } ) }
42- const json = packageName === dependencyId ? null : await this . getProductionDependencies ( tree )
43- const prodDependencies = json ? { ...json . dependencies , ...json . optionalDependencies } : treeDep
25+ const all = packageJson ? { ...packageJson . dependencies , ...packageJson . optionalDependencies } : { ...tree . dependencies , ...tree . optionalDependencies }
26+ const optional = packageJson ? { ...packageJson . optionalDependencies } : { }
4427
45- const collectedDependencies : string [ ] = [ ]
46- for ( const packageName in treeDep ) {
47- if ( ! prodDependencies [ packageName ] ) {
48- continue
28+ const deps = { ...( tree . dependencies || { } ) , ...( tree . optionalDependencies || { } ) }
29+ this . productionGraph [ dependencyId ] = { dependencies : [ ] }
30+ const depPromises = Object . entries ( deps ) . map ( async ( [ packageName , dependency ] ) => {
31+ // First check if it's in production dependencies
32+ if ( ! all [ packageName ] ) {
33+ return undefined
4934 }
5035
5136 // Then check if optional dependency path exists (using actual resolved path)
52- const version = json ?. optionalDependencies ?. [ packageName ] || tree . optionalDependencies ?. [ packageName ] ?. version || ""
53- const result = await this . locatePackageWithVersion ( { name : packageName , version, path : json ?. path ?? tree . path } )
54- if ( result == null || ! ( await this . cache . exists [ result . packageDir ] ) ) {
55- log . debug ( { packageName, version : version , searchPath : result ?. packageDir } , `optional dependency not installed, skipping` )
56- continue
37+ if ( optional [ packageName ] ) {
38+ const pkg = await this . cache . locatePackageVersion ( { pkgName : packageName , parentDir : this . rootDir , requiredRange : dependency . version } )
39+ if ( ! pkg ) {
40+ log . debug ( { name : packageName , version : dependency . version , path : dependency . path } , `optional dependency doesn't exist, skipping - likely not installed` )
41+ return undefined
42+ }
5743 }
58- const dependency = treeDep [ packageName ]
5944 const childDependencyId = this . packageVersionString ( dependency )
6045 await this . extractProductionDependencyGraph ( dependency , childDependencyId )
61- collectedDependencies . push ( childDependencyId )
46+ return childDependencyId
47+ } )
48+
49+ const collectedDependencies : string [ ] = [ ]
50+ for ( const dep of depPromises ) {
51+ const result = await dep
52+ if ( result !== undefined ) {
53+ collectedDependencies . push ( result )
54+ }
6255 }
6356 this . productionGraph [ dependencyId ] = { dependencies : collectedDependencies }
6457 }
6558
6659 protected async collectAllDependencies ( tree : PnpmDependency ) {
6760 // Collect regular dependencies
6861 for ( const [ key , value ] of Object . entries ( tree . dependencies || { } ) ) {
69- const json = await this . getProductionDependencies ( { ... value , name : key } )
70- this . allDependencies . set ( `${ key } @${ value . version } ` , { ...value , path : json . path } )
62+ const pkg = await this . cache . locatePackageVersion ( { pkgName : key , parentDir : this . rootDir , requiredRange : value . version } )
63+ this . allDependencies . set ( `${ key } @${ value . version } ` , { ...value , path : pkg ?. packageDir ?? value . path } )
7164 await this . collectAllDependencies ( value )
7265 }
7366
7467 // Collect optional dependencies if they exist
7568 for ( const [ key , value ] of Object . entries ( tree . optionalDependencies || { } ) ) {
76- const json = await this . getProductionDependencies ( value )
77- this . allDependencies . set ( `${ key } @${ value . version } ` , { ...value , path : json . path } )
69+ const pkg = await this . cache . locatePackageVersion ( { pkgName : key , parentDir : this . rootDir , requiredRange : value . version } )
70+ this . allDependencies . set ( `${ key } @${ value . version } ` , { ...value , path : pkg ?. packageDir ?? value . path } )
7871 await this . collectAllDependencies ( value )
7972 }
8073 }
0 commit comments