@@ -21,6 +21,10 @@ export function isUsingYarn(root: string) {
21
21
return fs . existsSync ( path . join ( root , 'yarn.lock' ) ) ;
22
22
}
23
23
24
+ function writeFile ( filePath : string , content : string ) {
25
+ fs . writeFileSync ( filePath , content , { encoding : 'utf8' } ) ;
26
+ }
27
+
24
28
async function fetchAvailableVersions ( packageName : string ) : Promise < string [ ] > {
25
29
const response = await fetch . json ( `/${ packageName } ` ) ;
26
30
@@ -170,6 +174,74 @@ function filterInstalledPeers(
170
174
return data ;
171
175
}
172
176
177
+ function findPeerDepsToInstall (
178
+ root : string ,
179
+ dependencies : Map < string , DependencyData > ,
180
+ ) {
181
+ const rootPackageJson = require ( path . join ( root , 'package.json' ) ) ;
182
+ const dependencyList = {
183
+ ...rootPackageJson . dependencies ,
184
+ ...rootPackageJson . devDependencies ,
185
+ } ;
186
+ const peerDependencies = new Set < string > ( ) ;
187
+ dependencies . forEach ( ( value ) => {
188
+ if ( value . peerDependencies ) {
189
+ Object . keys ( value . peerDependencies ) . forEach ( ( name ) => {
190
+ if ( ! Object . keys ( dependencyList ) . includes ( name ) ) {
191
+ peerDependencies . add ( name ) ;
192
+ }
193
+ } ) ;
194
+ }
195
+ } ) ;
196
+
197
+ return peerDependencies ;
198
+ }
199
+ async function getMissingPeerDepsForYarn ( root : string ) {
200
+ const dependencies = collectDependencies ( root ) ;
201
+ const depsToInstall = findPeerDepsToInstall ( root , dependencies ) ;
202
+
203
+ return depsToInstall ;
204
+ }
205
+
206
+ // install peer deps with yarn without making any changes to package.json and yarn.lock
207
+ async function yarnSilentInstallPeerDeps ( root : string ) {
208
+ const dependenciesToInstall = await getMissingPeerDepsForYarn ( root ) ;
209
+ const packageJsonPath = path . join ( root , 'package.json' ) ;
210
+ const lockfilePath = path . join ( root , 'yarn.lock' ) ;
211
+
212
+ if ( dependenciesToInstall . size > 0 ) {
213
+ const binPackageJson = fs . readFileSync ( packageJsonPath , {
214
+ encoding : 'utf8' ,
215
+ } ) ;
216
+ const binLockfile = fs . readFileSync ( lockfilePath , {
217
+ encoding : 'utf8' ,
218
+ } ) ;
219
+
220
+ if ( ! binPackageJson ) {
221
+ logger . error ( 'package.json is missing' ) ;
222
+ return ;
223
+ }
224
+
225
+ if ( ! binLockfile ) {
226
+ logger . error ( 'yarn.lock is missing' ) ;
227
+ return ;
228
+ }
229
+ const loader = getLoader ( { text : 'Verifying dependencies...' } ) ;
230
+
231
+ loader . start ( ) ;
232
+ try {
233
+ execa . sync ( 'yarn' , [ 'add' , ...dependenciesToInstall ] ) ;
234
+ loader . succeed ( ) ;
235
+ } catch {
236
+ loader . fail ( 'Failed to verify peer dependencies' ) ;
237
+ return ;
238
+ }
239
+
240
+ writeFile ( packageJsonPath , binPackageJson ) ;
241
+ writeFile ( lockfilePath , binLockfile ) ;
242
+ }
243
+ }
244
+
173
245
export default async function findPeerDepsForAutolinking ( root : string ) {
174
246
const deps = collectDependencies ( root ) ;
175
247
const nonEmptyPeers = filterNativeDependencies ( root , deps ) ;
@@ -240,7 +312,10 @@ async function getPackagesVersion(
240
312
return workingVersions ;
241
313
}
242
314
243
- function installMissingPackages ( packages : Record < string , string | null > ) {
315
+ function installMissingPackages (
316
+ packages : Record < string , string | null > ,
317
+ yarn = true ,
318
+ ) {
244
319
const packageVersions = Object . entries ( packages ) . map (
245
320
( [ name , version ] ) => `${ name } @^${ version } ` ,
246
321
) ;
@@ -249,7 +324,12 @@ function installMissingPackages(packages: Record<string, string | null>) {
249
324
const loader = getLoader ( { text : 'Installing peer dependencies...' } ) ;
250
325
loader . start ( ) ;
251
326
try {
252
- execa . sync ( 'npm' , [ 'install' , ...flattenList . map ( ( dep ) => dep ) ] ) ;
327
+ const deps = flattenList . map ( ( dep ) => dep ) ;
328
+ if ( yarn ) {
329
+ execa . sync ( 'yarn' , [ 'add' , ...deps ] ) ;
330
+ } else {
331
+ execa . sync ( 'npm' , [ 'install' , ...deps ] ) ;
332
+ }
253
333
loader . succeed ( ) ;
254
334
255
335
return true ;
@@ -262,6 +342,11 @@ function installMissingPackages(packages: Record<string, string | null>) {
262
342
263
343
export async function resolveTransitiveDeps ( ) {
264
344
const root = process . cwd ( ) ;
345
+ const isYarn = isUsingYarn ( root ) ;
346
+
347
+ if ( isYarn ) {
348
+ await yarnSilentInstallPeerDeps ( root ) ;
349
+ }
265
350
266
351
const missingPeerDependencies = await findPeerDepsForAutolinking ( root ) ;
267
352
@@ -275,7 +360,7 @@ export async function resolveTransitiveDeps() {
275
360
missingPeerDependencies ,
276
361
) ;
277
362
278
- return installMissingPackages ( packagesVersions ) ;
363
+ return installMissingPackages ( packagesVersions , isYarn ) ;
279
364
}
280
365
}
281
366
0 commit comments