UNPKG

@dependabot/yarn-lib

Version:

📦🐈 Fast, reliable, and secure dependency management.

274 lines (221 loc) 10.2 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.getOutdated = exports.run = exports.requireLockfile = undefined; var _asyncToGenerator2; function _load_asyncToGenerator() { return _asyncToGenerator2 = _interopRequireDefault(require('babel-runtime/helpers/asyncToGenerator')); } let run = exports.run = (() => { var _ref = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (config, reporter, flags, args) { let addArgs = []; const upgradeAll = args.length === 0 && typeof flags.scope === 'undefined' && typeof flags.pattern === 'undefined'; const addFlags = Object.assign({}, flags, { force: true, ignoreWorkspaceRootCheck: true, workspaceRootIsCwd: config.cwd === config.lockfileFolder }); const lockfile = yield (_lockfile || _load_lockfile()).default.fromDirectory(config.lockfileFolder, reporter); const deps = yield getOutdated(config, reporter, flags, lockfile, args); const install = new (_install || _load_install()).Install(flags, config, reporter, lockfile); var _ref2 = yield install.fetchRequestFromCwd(); const packagePatterns = _ref2.requests; setUserRequestedPackageVersions(deps, args, flags.latest, packagePatterns, reporter); cleanLockfile(lockfile, deps, packagePatterns, reporter); addArgs = deps.map(function (dep) { return dep.upgradeTo; }); if (flags.scope && validScopeRegex.test(flags.scope)) { addArgs = addArgs.filter(function (depName) { return depName.startsWith(flags.scope); }); } const add = new (_add || _load_add()).Add(addArgs, addFlags, config, reporter, upgradeAll ? new (_lockfile || _load_lockfile()).default() : lockfile); yield add.init(); }); return function run(_x, _x2, _x3, _x4) { return _ref.apply(this, arguments); }; })(); let getOutdated = exports.getOutdated = (() => { var _ref3 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (config, reporter, flags, lockfile, patterns) { const install = new (_install || _load_install()).Install(flags, config, reporter, lockfile); const outdatedFieldName = flags.latest ? 'latest' : 'wanted'; // ensure scope is of the form `@scope/` const normalizeScope = function normalizeScope() { if (flags.scope) { if (!flags.scope.startsWith('@')) { flags.scope = '@' + flags.scope; } if (!flags.scope.endsWith('/')) { flags.scope += '/'; } } }; const versionFilter = function versionFilter(dep) { return dep.current !== dep[outdatedFieldName]; }; if (!flags.latest) { // these flags only have an affect when --latest is used flags.tilde = false; flags.exact = false; flags.caret = false; } normalizeScope(); const deps = (yield (_packageRequest || _load_packageRequest()).default.getOutdatedPackages(lockfile, install, config, reporter, patterns, flags)).filter(versionFilter).filter(scopeFilter.bind(this, flags)); deps.forEach(function (dep) { dep.upgradeTo = buildPatternToUpgradeTo(dep, flags); reporter.verbose(reporter.lang('verboseUpgradeBecauseOutdated', dep.name, dep.upgradeTo)); }); return deps; }); return function getOutdated(_x5, _x6, _x7, _x8, _x9) { return _ref3.apply(this, arguments); }; })(); exports.cleanLockfile = cleanLockfile; exports.setFlags = setFlags; exports.hasWrapper = hasWrapper; var _add; function _load_add() { return _add = require('./add.js'); } var _lockfile; function _load_lockfile() { return _lockfile = _interopRequireDefault(require('../../lockfile')); } var _packageRequest; function _load_packageRequest() { return _packageRequest = _interopRequireDefault(require('../../package-request.js')); } var _normalizePattern; function _load_normalizePattern() { return _normalizePattern = require('../../util/normalize-pattern.js'); } var _install; function _load_install() { return _install = require('./install.js'); } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } // used to detect whether a semver range is simple enough to preserve when doing a --latest upgrade. // when not matched, the upgraded version range will default to `^` the same as the `add` command would. const basicSemverOperatorRegex = new RegExp('^(\\^|~|>=|<=)?[^ |&,]+$'); // used to detect if a passed parameter is a scope or a package name. const validScopeRegex = /^@[a-zA-Z0-9-][a-zA-Z0-9_.-]*\/$/; // If specific versions were requested for packages, override what getOutdated reported as the latest to install // Also add ones that are missing, since the requested packages may not have been outdated at all. function setUserRequestedPackageVersions(deps, args, latest, packagePatterns, reporter) { args.forEach(requestedPattern => { let found = false; let normalized = (0, (_normalizePattern || _load_normalizePattern()).normalizePattern)(requestedPattern); // if the user specified a package name without a version range, then that implies "latest" // but if the latest flag is not passed then we need to use the version range from package.json if (!normalized.hasVersion && !latest) { packagePatterns.forEach(packagePattern => { const packageNormalized = (0, (_normalizePattern || _load_normalizePattern()).normalizePattern)(packagePattern.pattern); if (packageNormalized.name === normalized.name) { normalized = packageNormalized; } }); } const newPattern = `${normalized.name}@${normalized.range}`; // if this dependency is already in the outdated list, // just update the upgradeTo to whatever version the user requested. deps.forEach(dep => { if (normalized.hasVersion && dep.name === normalized.name) { found = true; dep.upgradeTo = newPattern; reporter.verbose(reporter.lang('verboseUpgradeBecauseRequested', requestedPattern, newPattern)); } }); // if this dependency was not in the outdated list, // then add a new entry if (normalized.hasVersion && !found) { deps.push({ name: normalized.name, wanted: '', latest: '', url: '', hint: '', range: '', current: '', upgradeTo: newPattern, workspaceName: '', workspaceLoc: '' }); reporter.verbose(reporter.lang('verboseUpgradeBecauseRequested', requestedPattern, newPattern)); } }); } // this function attempts to determine the range operator on the semver range. // this will only handle the simple cases of a semver starting with '^', '~', '>=', '<=', or an exact version. // "exotic" semver ranges will not be handled. function getRangeOperator(version) { const result = basicSemverOperatorRegex.exec(version); return result ? result[1] || '' : '^'; } // Attempt to preserve the range operator from the package.json specified semver range. // If an explicit operator was specified using --exact, --tilde, --caret, then that will take precedence. function buildPatternToUpgradeTo(dep, flags) { if (dep.latest === 'exotic') { return `${dep.name}@${dep.url}`; } const toLatest = flags.latest; const toVersion = toLatest ? dep.latest : dep.range; let rangeOperator = ''; if (toLatest) { if (flags.caret) { rangeOperator = '^'; } else if (flags.tilde) { rangeOperator = '~'; } else if (flags.exact) { rangeOperator = ''; } else { rangeOperator = getRangeOperator(dep.range); } } return `${dep.name}@${rangeOperator}${toVersion}`; } function scopeFilter(flags, dep) { if (validScopeRegex.test(flags.scope)) { return dep.name.startsWith(flags.scope); } return true; } // Remove deps being upgraded from the lockfile, or else Add will use the already-installed version // instead of the latest for the range. // We do this recursively so that when Yarn installs the potentially updated transitive deps, // it may upgrade them too instead of just using the "locked" version from the lockfile. // Transitive dependencies that are also a direct dependency are skipped. function cleanLockfile(lockfile, deps, packagePatterns, reporter) { function cleanDepFromLockfile(pattern, depth) { const lockManifest = lockfile.getLocked(pattern); if (!lockManifest || depth > 1 && packagePatterns.some(packagePattern => packagePattern.pattern === pattern)) { reporter.verbose(reporter.lang('verboseUpgradeNotUnlocking', pattern)); return; } const dependencies = Object.assign({}, lockManifest.dependencies || {}, lockManifest.optionalDependencies || {}); const depPatterns = Object.keys(dependencies).map(key => `${key}@${dependencies[key]}`); reporter.verbose(reporter.lang('verboseUpgradeUnlocking', pattern)); lockfile.removePattern(pattern); depPatterns.forEach(pattern => cleanDepFromLockfile(pattern, depth + 1)); } const patterns = deps.map(dep => dep.upgradeTo); patterns.forEach(pattern => cleanDepFromLockfile(pattern, 1)); } function setFlags(commander) { commander.description('Upgrades packages to their latest version based on the specified range.'); commander.usage('upgrade [flags]'); commander.option('-S, --scope <scope>', 'upgrade packages under the specified scope'); commander.option('-L, --latest', 'list the latest version of packages, ignoring version ranges in package.json'); commander.option('-E, --exact', 'install exact version. Only used when --latest is specified.'); commander.option('-P, --pattern [pattern]', 'upgrade packages that match pattern'); commander.option('-T, --tilde', 'install most recent release with the same minor version. Only used when --latest is specified.'); commander.option('-C, --caret', 'install most recent release with the same major version. Only used when --latest is specified.'); commander.option('-A, --audit', 'Run vulnerability audit on installed packages'); } function hasWrapper(commander, args) { return true; } const requireLockfile = exports.requireLockfile = true;