refactor: extract npm and yarn processing from latestVersion in their own functions

Preparatory refactoring to simplify future compatibility with Yarn 2.
This commit is contained in:
Gaëtan Maisse 2020-02-14 20:56:08 +01:00
parent ab9c9cb589
commit 59fbd10bf5

View File

@ -1,11 +1,38 @@
import { spawn } from 'cross-spawn';
import { satisfies } from 'semver';
/**
* Get latest version of the package available on npmjs.com.
* If constraint is set then it returns a version satisfying it, otherwise the latest version available is returned.
*
* @param {Object} npmOptions Object containing a `useYarn: boolean` attribute
* @param {string} packageName Name of the package
* @param {Object} constraint Version range to use to constraint the returned version
* @return {Promise<string>} Promise resolved with a version
*/
export function latestVersion(npmOptions, packageName, constraint) {
const packageManager = npmOptions.useYarn ? 'yarn' : 'npm';
const getPackageVersions = npmOptions.useYarn
? spawnVersionsWithYarn(packageName, constraint)
: spawnVersionsWithNpm(packageName, constraint);
return getPackageVersions.then(versions => {
if (!constraint) return versions;
return versions.reverse().find(version => satisfies(version, constraint));
});
}
/**
* Get latest version(s) of the package available on npmjs.com using NPM
*
* @param {string} packageName Name of the package
* @param {Object} constraint Version range to use to constraint the returned version
* @returns {Promise<string|Array<string>>} versions Promise resolved with a version or an array of versions
*/
function spawnVersionsWithNpm(packageName, constraint) {
return new Promise((resolve, reject) => {
const command = spawn(
packageManager,
'npm',
['info', packageName, constraint ? 'versions' : 'version', '--json', '--silent'],
{
cwd: process.cwd(),
@ -16,39 +43,57 @@ export function latestVersion(npmOptions, packageName, constraint) {
}
);
const processResult = result => {
if (!constraint) return result;
return result.reverse().find(version => satisfies(version, constraint));
};
command.stdout.on('data', data => {
try {
const info = JSON.parse(data);
if (info.error) {
// npm error
reject(new Error(info.error.summary));
} else if (info.type === 'inspect') {
// yarn success
resolve(processResult(info.data));
} else {
// npm success
resolve(processResult(info));
resolve(info);
}
} catch (e) {
// yarn info output
}
});
command.stderr.on('data', data => {
try {
// yarn error
const info = JSON.parse(data);
if (info.type === 'error') {
reject(new Error(info.data));
}
} catch (e) {
// package manager unstructured info/warnings output
reject(new Error(`Unable to find versions of ${packageName} using npm`));
}
});
});
}
/**
* Get latest version(s) of the package available on npmjs.com using Yarn
*
* @param {string} packageName Name of the package
* @param {Object} constraint Version range to use to constraint the returned version
* @returns {Promise<string|Array<string>>} versions Promise resolved with a version or an array of versions
*/
function spawnVersionsWithYarn(packageName, constraint) {
return new Promise((resolve, reject) => {
const command = spawn(
'yarn',
['info', packageName, constraint ? 'versions' : 'version', '--json', '--silent'],
{
cwd: process.cwd(),
env: process.env,
stdio: 'pipe',
encoding: 'utf-8',
silent: true,
}
);
command.stdout.on('data', data => {
try {
const info = JSON.parse(data);
if (info.type === 'inspect') {
resolve(info.data);
}
} catch (e) {
reject(new Error(`Unable to find versions of ${packageName} using yarn`));
}
});
command.stderr.on('data', data => {
const info = JSON.parse(data);
if (info.type === 'error') {
reject(new Error(info.data));
}
});
});