@@ -21,6 +21,10 @@ export function isUsingYarn(root: string) {
2121 return fs . existsSync ( path . join ( root , 'yarn.lock' ) ) ;
2222}
2323
24+ function writeFile ( filePath : string , content : string ) {
25+ fs . writeFileSync ( filePath , content , { encoding : 'utf8' } ) ;
26+ }
27+
2428async function fetchAvailableVersions ( packageName : string ) : Promise < string [ ] > {
2529 const response = await fetch . json ( `/${ packageName } ` ) ;
2630
@@ -170,6 +174,74 @@ function filterInstalledPeers(
170174 return data ;
171175}
172176
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+
173245export default async function findPeerDepsForAutolinking ( root : string ) {
174246 const deps = collectDependencies ( root ) ;
175247 const nonEmptyPeers = filterNativeDependencies ( root , deps ) ;
@@ -240,7 +312,10 @@ async function getPackagesVersion(
240312 return workingVersions ;
241313}
242314
243- function installMissingPackages ( packages : Record < string , string | null > ) {
315+ function installMissingPackages (
316+ packages : Record < string , string | null > ,
317+ yarn = true ,
318+ ) {
244319 const packageVersions = Object . entries ( packages ) . map (
245320 ( [ name , version ] ) => `${ name } @^${ version } ` ,
246321 ) ;
@@ -249,7 +324,12 @@ function installMissingPackages(packages: Record<string, string | null>) {
249324 const loader = getLoader ( { text : 'Installing peer dependencies...' } ) ;
250325 loader . start ( ) ;
251326 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+ }
253333 loader . succeed ( ) ;
254334
255335 return true ;
@@ -262,6 +342,11 @@ function installMissingPackages(packages: Record<string, string | null>) {
262342
263343export async function resolveTransitiveDeps ( ) {
264344 const root = process . cwd ( ) ;
345+ const isYarn = isUsingYarn ( root ) ;
346+
347+ if ( isYarn ) {
348+ await yarnSilentInstallPeerDeps ( root ) ;
349+ }
265350
266351 const missingPeerDependencies = await findPeerDepsForAutolinking ( root ) ;
267352
@@ -275,7 +360,7 @@ export async function resolveTransitiveDeps() {
275360 missingPeerDependencies ,
276361 ) ;
277362
278- return installMissingPackages ( packagesVersions ) ;
363+ return installMissingPackages ( packagesVersions , isYarn ) ;
279364 }
280365 }
281366
0 commit comments