@@ -15,10 +15,10 @@ function isUsingYarn(root: string) {
15
15
return fs . existsSync ( path . join ( root , 'yarn.lock' ) ) ;
16
16
}
17
17
18
- function getPeerDependencies ( root : string ) : Map < string , DependencyInfo > {
19
- const packageJsonPath = path . join ( root , 'package.json' ) ;
20
- const packageJson = require ( packageJsonPath ) ;
21
-
18
+ function getPeerDependencies (
19
+ root : string ,
20
+ packageJson : any ,
21
+ ) : Map < string , DependencyInfo > {
22
22
const dependenciesAndPeerDependencies = new Map < string , DependencyInfo > ( ) ;
23
23
24
24
for ( const dependency in packageJson . dependencies ) {
@@ -62,14 +62,21 @@ function getPeerDependencies(root: string): Map<string, DependencyInfo> {
62
62
function excludeInstalledPeerDependencies (
63
63
root : string ,
64
64
peerDependencies : Map < string , DependencyInfo > ,
65
+ yarn = true ,
65
66
) {
67
+ const packageJson = require ( path . join ( root , 'package.json' ) ) ;
66
68
const missingPeerDependencies : Record < string , Record < string , string > > = { } ;
67
-
68
69
peerDependencies . forEach ( ( value , key ) => {
69
70
const missingDeps = Object . entries ( value . peerDependencies ) . reduce (
70
71
( missingDepsList , [ name , version ] ) => {
71
72
const rootPath = path . join ( root , 'node_modules' , name ) ;
72
- if ( ! fs . existsSync ( rootPath ) ) {
73
+ if (
74
+ ( yarn && ! fs . existsSync ( rootPath ) ) ||
75
+ ( ! yarn &&
76
+ ( fs . existsSync ( path . join ( rootPath , 'ios' ) ) ||
77
+ fs . existsSync ( path . join ( rootPath , 'android' ) ) ) &&
78
+ ! Object . keys ( packageJson . dependencies ) . includes ( name ) )
79
+ ) {
73
80
missingDepsList [ name ] = version ;
74
81
}
75
82
return missingDepsList ;
@@ -85,69 +92,122 @@ function excludeInstalledPeerDependencies(
85
92
return missingPeerDependencies ;
86
93
}
87
94
88
- function getMatchingPackageVersion ( packageName : string , range : string ) {
89
- const { stdout} = execa . sync ( 'yarn' , [
90
- 'info' ,
91
- packageName ,
92
- 'versions' ,
93
- '--json' ,
94
- ] ) ;
95
- const versions = JSON . parse ( stdout ) . data as string [ ] ;
96
- const satisfying = versions . filter ( ( version ) =>
97
- semver . satisfies ( version , range ) ,
98
- ) ;
99
- const maxSatisfying = semver . maxSatisfying ( satisfying , range ) ;
95
+ function getMatchingPackageVersion (
96
+ packageName : string ,
97
+ range : string ,
98
+ yarn = true ,
99
+ ) {
100
+ if ( yarn ) {
101
+ const { stdout} = execa . sync ( 'yarn' , [
102
+ 'info' ,
103
+ packageName ,
104
+ 'versions' ,
105
+ '--json' ,
106
+ ] ) ;
107
+ const versions = JSON . parse ( stdout ) . data as string [ ] ;
108
+ const satisfying = versions . filter ( ( version ) =>
109
+ semver . satisfies ( version , range ) ,
110
+ ) ;
111
+ const maxSatisfying = semver . maxSatisfying ( satisfying , range ) ;
112
+
113
+ return maxSatisfying ;
114
+ } else {
115
+ const { stdout} = execa . sync ( 'npm' , [
116
+ 'view' ,
117
+ `${ packageName } @${ range } ` ,
118
+ 'version' ,
119
+ '--json' ,
120
+ ] ) ;
121
+ const versions = JSON . parse ( stdout ) ;
122
+ const maxSatisfying = semver . maxSatisfying ( versions , range ) ;
123
+ return maxSatisfying ;
124
+ }
125
+ }
100
126
101
- return maxSatisfying ;
127
+ function flattenSemver ( input ) {
128
+ const result = { } ;
129
+ input . forEach ( ( item ) => {
130
+ Object . entries ( item ) . forEach ( ( [ key , value ] ) => {
131
+ if ( result [ key ] ) {
132
+ if ( value !== '*' && result [ key ] !== '*' ) {
133
+ result [ key ] = `${ result [ key ] } && ${ value } ` ;
134
+ }
135
+ } else {
136
+ result [ key ] = value ;
137
+ }
138
+ } ) ;
139
+ } ) ;
140
+
141
+ return result ;
102
142
}
103
143
104
144
export default async function installTransitiveDeps ( ) {
105
145
const root = process . cwd ( ) ;
106
-
107
- const peerDependencies = getPeerDependencies ( root ) ;
146
+ const packageJsonPath = path . join ( root , 'package.json' ) ;
147
+ const packageJson = require ( packageJsonPath ) ;
148
+ const isYarn = isUsingYarn ( root ) ;
149
+ const peerDependencies = getPeerDependencies ( root , packageJson ) ;
108
150
const depsToInstall = excludeInstalledPeerDependencies (
109
151
root ,
110
152
peerDependencies ,
153
+ isYarn ,
111
154
) ;
155
+
112
156
const dependenciesWithMissingDeps = Object . keys ( depsToInstall ) ;
113
157
if ( dependenciesWithMissingDeps . length > 0 ) {
114
158
logger . warn (
115
- `Looks like you are missing some of the peer dependencies of your libraries:
116
- ${ dependenciesWithMissingDeps . map (
117
- ( dep ) =>
118
- `${ chalk . bold ( dep ) } :\n ${ Object . keys ( depsToInstall [ dep ] ) . map (
119
- ( d ) => `\t-${ d } \n` ,
120
- ) } `,
121
- ) } `,
159
+ 'Looks like you are missing some of the peer dependencies of your libraries:\n' ,
160
+ ) ;
161
+ logger . log (
162
+ dependenciesWithMissingDeps
163
+ . map (
164
+ ( dep ) =>
165
+ `\t${ chalk . bold ( dep ) } :\n ${ Object . keys ( depsToInstall [ dep ] ) . map (
166
+ ( d ) => `\t- ${ d } \n` ,
167
+ ) } `,
168
+ )
169
+ . join ( '\n' )
170
+ . replace ( / , / g, '' ) ,
122
171
) ;
123
172
const { install} = await prompt ( {
124
173
type : 'confirm' ,
125
174
name : 'install' ,
126
175
message :
127
- 'Do you want to install them now? The matching versions will be added as project dependencies.' ,
176
+ 'Do you want to install them now? The matching versions will be added as project dependencies and become visible for autolinking .' ,
128
177
} ) ;
129
178
const loader = getLoader ( { text : 'Installing peer dependencies...' } ) ;
130
179
131
180
if ( install ) {
132
- if ( isUsingYarn ( root ) ) {
133
- let deps = { } as Record < string , string > ;
134
- dependenciesWithMissingDeps . map ( ( dep ) => {
135
- const missingDeps = depsToInstall [ dep ] ;
136
-
137
- Object . entries ( missingDeps ) . map ( ( [ name , range ] ) => {
138
- const version = getMatchingPackageVersion ( name , range ) ;
139
- if ( version ) {
140
- deps [ name ] = version ;
141
- }
142
- } ) ;
181
+ let deps = { } as Record < string , string > ;
182
+ const semverRanges = flattenSemver ( Object . values ( depsToInstall ) ) ;
183
+
184
+ dependenciesWithMissingDeps . map ( ( dep ) => {
185
+ const missingDeps = depsToInstall [ dep ] ;
186
+ Object . entries ( missingDeps ) . map ( ( [ name ] ) => {
187
+ const version = getMatchingPackageVersion (
188
+ name ,
189
+ semverRanges [ name ] ,
190
+ isYarn ,
191
+ ) ;
192
+ if ( version ) {
193
+ deps [ name ] = version ;
194
+ }
143
195
} ) ;
144
- loader . start ( ) ;
196
+ } ) ;
197
+ loader . start ( ) ;
198
+
199
+ if ( isYarn ) {
145
200
execa . sync ( 'yarn' , [
146
201
'add' ,
147
202
...Object . entries ( deps ) . map ( ( [ k , v ] ) => `${ k } @^${ v } ` ) ,
148
203
] ) ;
149
- loader . succeed ( ) ;
204
+ } else {
205
+ execa . sync ( 'npm' , [
206
+ 'install' ,
207
+ ...Object . entries ( deps ) . map ( ( [ k , v ] ) => `${ k } @^${ v } ` ) ,
208
+ ] ) ;
150
209
}
210
+ loader . succeed ( ) ;
151
211
}
152
212
}
153
213
}
0 commit comments