@@ -16,41 +16,44 @@ interface PackageJson {
16
16
peerDependencies : {
17
17
[ key : string ] : string ;
18
18
} ;
19
+ // deprecated: use peerDependenciesMeta.foo.dev
20
+ peerDevDependencies : string [ ] ;
21
+ // See: https://github.com/yarnpkg/rfcs/blob/master/accepted/0000-optional-peer-dependencies.md
22
+ peerDependenciesMeta : {
23
+ [ key : string ] : {
24
+ optional ?: boolean ;
25
+ // non-standard
26
+ dev ?: boolean ;
27
+ } ;
28
+ } ;
19
29
optionalDependencies : {
20
30
[ key : string ] : string ;
21
31
} ;
22
-
23
- // What is a peerDevDependency? This is not a standard.
24
- // This is an array of package names found in `peerDependencies` which should be installed as devDependencies.
25
- // This addresses a specific use case: to provide downstream projects with package building opinions such as
26
- // a specific version of react and rollup and typescript.
27
- // Example:
28
- // peerDevDependencies: ["rollup", "typescript"]
29
- peerDevDependencies : string [ ] ;
30
32
}
31
33
32
34
export interface Dependency {
33
35
name : string ;
34
36
version : string ;
35
- depender : string ;
36
- dependerPath : string ;
37
- dependerVersion : string ;
37
+ depender : PackageMeta ;
38
+ type : 'dependencies' | 'devDependencies' | 'peerDependencies' | 'optionalDependencies' ;
39
+ isPeerOptionalDependency : boolean ;
40
+ isPeerDevDependency : boolean ;
38
41
installedVersion ?: string | undefined ;
39
42
semverSatisfies ?: boolean ;
40
43
isYalc ?: boolean ;
41
- isPeerDevDependency ?: boolean ;
42
44
}
43
45
44
- interface PackageDependencies {
45
- packageName : string ;
46
+ interface PackageMeta {
47
+ name : string ;
48
+ version : string ;
49
+ packagePath : string ;
46
50
dependencies : Dependency [ ] ;
47
51
devDependencies : Dependency [ ] ;
48
- peerDependencies : Dependency [ ] ;
49
52
optionalDependencies : Dependency [ ] ;
50
- peerDevDependencies : string [ ] ;
53
+ peerDependencies : Dependency [ ] ;
51
54
}
52
55
53
- type DependencyWalkVisitor = ( packagePath : string , packageJson : PackageJson , packageDependencies : PackageDependencies ) => void ;
56
+ type DependencyWalkVisitor = ( packagePath : string , packageJson : PackageJson , packageMeta : PackageMeta ) => void ;
54
57
55
58
export function gatherPeerDependencies ( packagePath , options : CliOptions ) : Dependency [ ] {
56
59
let peerDeps : Dependency [ ] = [ ] ;
@@ -80,7 +83,7 @@ export function walkPackageDependencyTree(packagePath: string, visitor: Dependen
80
83
}
81
84
82
85
const packageJson = readJson ( packageJsonPath ) as PackageJson ;
83
- const packageDependencies = getPackageDependencies ( packagePath , packageJson ) ;
86
+ const packageDependencies = getPackageMeta ( packagePath , packageJson ) ;
84
87
85
88
if ( options . debug ) {
86
89
console . log ( packageJsonPath ) ;
@@ -114,37 +117,39 @@ export function walkPackageDependencyTree(packagePath: string, visitor: Dependen
114
117
if ( isRootPackage || ! options . runOnlyOnRootDependencies ) packageDependencies . dependencies . forEach ( walkDependency )
115
118
}
116
119
117
- function buildDependencyArray ( packagePath : string , packageJson : PackageJson , dependenciesObject : any ) : Dependency [ ] {
118
- return Object . keys ( dependenciesObject ) . map ( name => ( {
119
- name : name ,
120
- version : dependenciesObject [ name ] ,
121
- depender : packageJson . name ,
122
- dependerVersion : packageJson . version ,
123
- dependerPath : packagePath ,
124
- } ) ) ;
120
+ function buildDependencyArray ( type : Dependency [ "type" ] , pkgJson : PackageJson , depender : PackageMeta ) : Dependency [ ] {
121
+ const dependenciesObject = pkgJson [ type ] || { } ;
122
+ const peerDependenciesMeta = pkgJson . peerDependenciesMeta || { } ;
123
+ // backwards compat
124
+ const peerDevDependencies = pkgJson . peerDevDependencies || [ ] ;
125
+
126
+ const packageNames = Object . keys ( dependenciesObject ) ;
127
+
128
+ return packageNames . map ( name => {
129
+ const isPeerOptionalDependency = ! ! peerDependenciesMeta [ name ] ?. optional ;
130
+ const isPeerDevDependency = ! ! peerDependenciesMeta [ name ] ?. dev || ! ! peerDevDependencies . includes ( name ) ;
131
+
132
+ return {
133
+ name,
134
+ type,
135
+ version : dependenciesObject [ name ] ,
136
+ isPeerDevDependency,
137
+ isPeerOptionalDependency,
138
+ depender,
139
+ } ;
140
+ } ) ;
125
141
}
126
142
127
- export function getPackageDependencies ( packagePath : string , packageJson : PackageJson ) : PackageDependencies {
128
- const {
129
- name,
130
- dependencies = { } ,
131
- devDependencies = { } ,
132
- optionalDependencies = { } ,
133
- peerDependencies = { } ,
134
- peerDevDependencies = [ ]
135
- } = packageJson ;
136
-
137
- const applyPeerDevDependencies = ( dep : Dependency ) : Dependency =>
138
- ( { ...dep , isPeerDevDependency : peerDevDependencies . includes && peerDevDependencies . includes ( dep . name ) } ) ;
139
-
140
- return {
141
- packageName : name ,
142
- dependencies : buildDependencyArray ( packagePath , packageJson , dependencies ) ,
143
- devDependencies : buildDependencyArray ( packagePath , packageJson , devDependencies ) ,
144
- optionalDependencies : buildDependencyArray ( packagePath , packageJson , optionalDependencies ) ,
145
- peerDependencies : buildDependencyArray ( packagePath , packageJson , peerDependencies ) . map ( applyPeerDevDependencies ) ,
146
- peerDevDependencies,
147
- } ;
143
+ export function getPackageMeta ( packagePath : string , packageJson : PackageJson ) : PackageMeta {
144
+ const { name, version} = packageJson ;
145
+ const packageMeta = { name, version, packagePath } as PackageMeta ;
146
+
147
+ packageMeta . dependencies = buildDependencyArray ( "dependencies" , packageJson , packageMeta ) ;
148
+ packageMeta . devDependencies = buildDependencyArray ( "devDependencies" , packageJson , packageMeta ) ;
149
+ packageMeta . optionalDependencies = buildDependencyArray ( "optionalDependencies" , packageJson , packageMeta ) ;
150
+ packageMeta . peerDependencies = buildDependencyArray ( "peerDependencies" , packageJson , packageMeta ) ;
151
+
152
+ return packageMeta ;
148
153
}
149
154
150
155
export function resolvePackageDir ( basedir : string , packageName : string ) {
@@ -181,17 +186,9 @@ export function getInstalledVersion(dep: Dependency): string | undefined {
181
186
182
187
183
188
export function isSameDep ( a : Dependency , b : Dependency ) {
184
- const keys : Array < keyof Dependency > = [
185
- "name" ,
186
- "version" ,
187
- "depender" ,
188
- "dependerPath" ,
189
- "dependerVersion" ,
190
- "installedVersion" ,
191
- "semverSatisfies" ,
192
- "isYalc" ,
193
- "isPeerDevDependency" ,
194
- ] ;
195
-
196
- return keys . every ( key => a [ key ] === b [ key ] ) ;
189
+ const keys : Array < keyof Dependency > = [ "name" , "version" , "installedVersion" , "semverSatisfies" , "isYalc" , "isPeerDevDependency" , ] ;
190
+ return keys . every ( key => a [ key ] === b [ key ] ) &&
191
+ a . depender . name === b . depender . name &&
192
+ a . depender . version === b . depender . version &&
193
+ a . depender . packagePath === b . depender . packagePath ;
197
194
}
0 commit comments