@@ -15,10 +15,10 @@ function isUsingYarn(root: string) {
1515 return fs . existsSync ( path . join ( root , 'yarn.lock' ) ) ;
1616}
1717
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 > {
2222 const dependenciesAndPeerDependencies = new Map < string , DependencyInfo > ( ) ;
2323
2424 for ( const dependency in packageJson . dependencies ) {
@@ -62,14 +62,21 @@ function getPeerDependencies(root: string): Map<string, DependencyInfo> {
6262function excludeInstalledPeerDependencies (
6363 root : string ,
6464 peerDependencies : Map < string , DependencyInfo > ,
65+ yarn = true ,
6566) {
67+ const packageJson = require ( path . join ( root , 'package.json' ) ) ;
6668 const missingPeerDependencies : Record < string , Record < string , string > > = { } ;
67-
6869 peerDependencies . forEach ( ( value , key ) => {
6970 const missingDeps = Object . entries ( value . peerDependencies ) . reduce (
7071 ( missingDepsList , [ name , version ] ) => {
7172 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+ ) {
7380 missingDepsList [ name ] = version ;
7481 }
7582 return missingDepsList ;
@@ -85,69 +92,122 @@ function excludeInstalledPeerDependencies(
8592 return missingPeerDependencies ;
8693}
8794
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+ }
100126
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 ;
102142}
103143
104144export default async function installTransitiveDeps ( ) {
105145 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 ) ;
108150 const depsToInstall = excludeInstalledPeerDependencies (
109151 root ,
110152 peerDependencies ,
153+ isYarn ,
111154 ) ;
155+
112156 const dependenciesWithMissingDeps = Object . keys ( depsToInstall ) ;
113157 if ( dependenciesWithMissingDeps . length > 0 ) {
114158 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, '' ) ,
122171 ) ;
123172 const { install} = await prompt ( {
124173 type : 'confirm' ,
125174 name : 'install' ,
126175 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 .' ,
128177 } ) ;
129178 const loader = getLoader ( { text : 'Installing peer dependencies...' } ) ;
130179
131180 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+ }
143195 } ) ;
144- loader . start ( ) ;
196+ } ) ;
197+ loader . start ( ) ;
198+
199+ if ( isYarn ) {
145200 execa . sync ( 'yarn' , [
146201 'add' ,
147202 ...Object . entries ( deps ) . map ( ( [ k , v ] ) => `${ k } @^${ v } ` ) ,
148203 ] ) ;
149- loader . succeed ( ) ;
204+ } else {
205+ execa . sync ( 'npm' , [
206+ 'install' ,
207+ ...Object . entries ( deps ) . map ( ( [ k , v ] ) => `${ k } @^${ v } ` ) ,
208+ ] ) ;
150209 }
210+ loader . succeed ( ) ;
151211 }
152212 }
153213}
0 commit comments