Skip to content

Commit ebaf706

Browse files
committed
support npm
1 parent 0b05b46 commit ebaf706

File tree

1 file changed

+102
-42
lines changed

1 file changed

+102
-42
lines changed

packages/cli/src/tools/resolveTransitiveDeps.ts

Lines changed: 102 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -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> {
6262
function 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

104144
export 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

Comments
 (0)