jazelle/commands/upgrade.js (60 lines of code) (raw):

// @flow const {minVersion, satisfies} = require('../utils/cached-semver'); const {getManifest} = require('../utils/get-manifest.js'); const {findLocalDependency} = require('../utils/find-local-dependency.js'); const {upgrade: upgradeDep} = require('../utils/lockfile.js'); const {read, write} = require('../utils/node-helpers.js'); const sortPackageJson = require('../utils/sort-package-json'); /*:: export type UpgradeArgs = { root: string, args: Array<string>, }; export type Upgrade = (UpgradeArgs) => Promise<void>; */ const upgrade /*: Upgrade */ = async ({root, args}) => { const {projects, registry} = /*:: await */ await getManifest({root}); // FIXME: double await is due to Flow bug const roots = projects.map(dir => `${root}/${dir}`); // group by whether the dep is local (listed in manifest.json) or external (from registry) const locals = []; const externals = []; for (const arg of args) { let [, name, version] = arg.match(/(@?[^@]*)@?(.*)/) || []; const local = await findLocalDependency({root, name}); if (local) locals.push({local, name, version}); else externals.push({name, range: version}); } // upgrade local deps if (locals.length > 0) { await Promise.all( roots.map(async cwd => { const meta = JSON.parse(await read(`${cwd}/package.json`, 'utf8')); for (const {local, name, version} of locals) { if (version && version !== local.meta.version) { const error = `You must use version ${name}@${local.meta.version}`; throw new Error(error); } update(meta, 'dependencies', name, local.meta.version); update(meta, 'devDependencies', name, local.meta.version); update(meta, 'peerDependencies', name, local.meta.version); update(meta, 'optionalDependencies', name, local.meta.version); } await write(`${cwd}/package.json`, sortPackageJson(meta), 'utf8'); }) ); } // upgrade external deps if (externals.length > 0) { const tmp = `${root}/third_party/jazelle/temp/yarn-utilities-tmp`; await upgradeDep({ roots, upgrades: externals, ignore: await Promise.all( projects.map(async project => { const metaFile = `${root}/${project}/package.json`; const data = await read(metaFile, 'utf8'); return JSON.parse(data).name; }) ), tmp, registry, }); } }; const update = (meta, type, name, version, from) => { if (meta[type] && meta[type][name]) { const min = minVersion(meta[type][name]); const inRange = !from || satisfies(min, from); if (inRange) meta[type][name] = version; } }; module.exports = {upgrade};