@dependabot/yarn-lib
Version:
📦🐈 Fast, reliable, and secure dependency management.
517 lines (426 loc) • 18.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.run = exports.verifyTreeCheck = exports.noArguments = exports.requireLockfile = undefined;
var _asyncToGenerator2;
function _load_asyncToGenerator() {
return _asyncToGenerator2 = _interopRequireDefault(require('babel-runtime/helpers/asyncToGenerator'));
}
let verifyTreeCheck = exports.verifyTreeCheck = (() => {
var _ref = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (config, reporter, flags, args) {
let errCount = 0;
function reportError(msg, ...vars) {
reporter.error(reporter.lang(msg, ...vars));
errCount++;
}
// check all dependencies recursively without relying on internal resolver
const registryName = 'yarn';
const registryFolder = config.registryFolders[0];
const cwd = config.workspaceRootFolder ? config.lockfileFolder : config.cwd;
const rootManifest = yield config.readManifest(cwd, registryName);
const dependenciesToCheckVersion = [];
if (rootManifest.dependencies) {
for (const name in rootManifest.dependencies) {
const version = rootManifest.dependencies[name];
// skip linked dependencies
const isLinkedDependency = /^link:/i.test(version) || /^file:/i.test(version) && config.linkFileDependencies;
if (isLinkedDependency) {
continue;
}
dependenciesToCheckVersion.push({
name,
originalKey: name,
parentCwd: cwd,
version
});
}
}
if (rootManifest.devDependencies && !config.production) {
for (const name in rootManifest.devDependencies) {
const version = rootManifest.devDependencies[name];
// skip linked dependencies
const isLinkedDependency = /^link:/i.test(version) || /^file:/i.test(version) && config.linkFileDependencies;
if (isLinkedDependency) {
continue;
}
dependenciesToCheckVersion.push({
name,
originalKey: name,
parentCwd: cwd,
version
});
}
}
const locationsVisited = new Set();
while (dependenciesToCheckVersion.length) {
const dep = dependenciesToCheckVersion.shift();
const manifestLoc = path.resolve(dep.parentCwd, registryFolder, dep.name);
if (locationsVisited.has(manifestLoc + `@${dep.version}`)) {
continue;
}
locationsVisited.add(manifestLoc + `@${dep.version}`);
// When plugnplay is enabled, packages aren't copied to the node_modules folder, so this check doesn't make sense
// TODO: We ideally should check that the packages are located inside the cache instead
if (config.plugnplayEnabled) {
continue;
}
if (!(yield (_fs || _load_fs()).exists(manifestLoc))) {
reportError('packageNotInstalled', `${dep.originalKey}`);
continue;
}
if (!(yield (_fs || _load_fs()).exists(path.join(manifestLoc, 'package.json')))) {
continue;
}
const pkg = yield config.readManifest(manifestLoc, registryName);
if (semver.validRange(dep.version, config.looseSemver) && !semver.satisfies(pkg.version, dep.version, config.looseSemver)) {
reportError('packageWrongVersion', dep.originalKey, dep.version, pkg.version);
continue;
}
const dependencies = pkg.dependencies;
if (dependencies) {
for (const subdep in dependencies) {
const subDepPath = path.resolve(manifestLoc, registryFolder, subdep);
let found = false;
const relative = path.relative(cwd, subDepPath);
const locations = path.normalize(relative).split(registryFolder + path.sep).filter(function (dir) {
return !!dir;
});
locations.pop();
while (locations.length >= 0) {
let possiblePath;
if (locations.length > 0) {
possiblePath = path.join(cwd, registryFolder, locations.join(path.sep + registryFolder + path.sep));
} else {
possiblePath = cwd;
}
if (yield (_fs || _load_fs()).exists(path.resolve(possiblePath, registryFolder, subdep))) {
dependenciesToCheckVersion.push({
name: subdep,
originalKey: `${dep.originalKey}#${subdep}`,
parentCwd: possiblePath,
version: dependencies[subdep]
});
found = true;
break;
}
if (!locations.length) {
break;
}
locations.pop();
}
if (!found) {
reportError('packageNotInstalled', `${dep.originalKey}#${subdep}`);
}
}
}
}
if (errCount > 0) {
throw new (_errors || _load_errors()).MessageError(reporter.lang('foundErrors', errCount));
} else {
reporter.success(reporter.lang('folderInSync'));
}
});
return function verifyTreeCheck(_x, _x2, _x3, _x4) {
return _ref.apply(this, arguments);
};
})();
let integrityHashCheck = (() => {
var _ref2 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (config, reporter, flags, args) {
let errCount = 0;
function reportError(msg, ...vars) {
reporter.error(reporter.lang(msg, ...vars));
errCount++;
}
const integrityChecker = new (_integrityChecker || _load_integrityChecker()).default(config);
const lockfile = yield (_lockfile || _load_lockfile()).default.fromDirectory(config.cwd);
const install = new (_install || _load_install()).Install(flags, config, reporter, lockfile);
// get patterns that are installed when running `yarn install`
var _ref3 = yield install.fetchRequestFromCwd();
const patterns = _ref3.patterns,
workspaceLayout = _ref3.workspaceLayout;
const match = yield integrityChecker.check(patterns, lockfile.cache, flags, workspaceLayout);
for (var _iterator = match.missingPatterns, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _ref4;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref4 = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref4 = _i.value;
}
const pattern = _ref4;
reportError('lockfileNotContainPattern', pattern);
}
if (match.integrityFileMissing) {
reportError('noIntegrityFile');
}
if (match.integrityMatches === false) {
reporter.warn(reporter.lang((_integrityChecker2 || _load_integrityChecker2()).integrityErrors[match.integrityError]));
reportError('integrityCheckFailed');
}
if (errCount > 0) {
throw new (_errors || _load_errors()).MessageError(reporter.lang('foundErrors', errCount));
} else {
reporter.success(reporter.lang('folderInSync'));
}
});
return function integrityHashCheck(_x5, _x6, _x7, _x8) {
return _ref2.apply(this, arguments);
};
})();
let run = exports.run = (() => {
var _ref5 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (config, reporter, flags, args) {
if (flags.verifyTree) {
yield verifyTreeCheck(config, reporter, flags, args);
return;
} else if (flags.integrity) {
yield integrityHashCheck(config, reporter, flags, args);
return;
}
const lockfile = yield (_lockfile || _load_lockfile()).default.fromDirectory(config.cwd);
const install = new (_install || _load_install()).Install(flags, config, reporter, lockfile);
function humaniseLocation(loc) {
const relative = path.relative(path.join(config.cwd, 'node_modules'), loc);
const normalized = path.normalize(relative).split(path.sep);
return normalized.filter(p => p !== 'node_modules').reduce((result, part) => {
const length = result.length;
if (length && result[length - 1].startsWith('@') && result[length - 1].indexOf(path.sep) === -1) {
result[length - 1] += path.sep + part;
} else {
result.push(part);
}
return result;
}, []);
}
let warningCount = 0;
let errCount = 0;
function reportError(msg, ...vars) {
reporter.error(reporter.lang(msg, ...vars));
errCount++;
}
// get patterns that are installed when running `yarn install`
var _ref6 = yield install.hydrate();
const rawPatterns = _ref6.patterns,
workspaceLayout = _ref6.workspaceLayout;
const patterns = yield install.flatten(rawPatterns);
// check if patterns exist in lockfile
for (var _iterator2 = patterns, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {
var _ref7;
if (_isArray2) {
if (_i2 >= _iterator2.length) break;
_ref7 = _iterator2[_i2++];
} else {
_i2 = _iterator2.next();
if (_i2.done) break;
_ref7 = _i2.value;
}
const pattern = _ref7;
if (!lockfile.getLocked(pattern) && (!workspaceLayout || !workspaceLayout.getManifestByPattern(pattern))) {
reportError('lockfileNotContainPattern', pattern);
}
}
const bundledDeps = {};
// check if any of the node_modules are out of sync
const res = yield install.linker.getFlatHoistedTree(patterns, workspaceLayout);
for (var _iterator3 = res, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) {
var _ref9;
if (_isArray3) {
if (_i3 >= _iterator3.length) break;
_ref9 = _iterator3[_i3++];
} else {
_i3 = _iterator3.next();
if (_i3.done) break;
_ref9 = _i3.value;
}
const _ref8 = _ref9;
const loc = _ref8[0];
var _ref8$ = _ref8[1];
const originalKey = _ref8$.originalKey;
const pkg = _ref8$.pkg;
const ignore = _ref8$.ignore;
if (ignore) {
continue;
}
const parts = humaniseLocation(loc);
// grey out hoisted portions of key
let human = originalKey;
const hoistedParts = parts.slice();
const hoistedKey = parts.join('#');
if (human !== hoistedKey) {
const humanParts = human.split('#');
for (let i = 0; i < humanParts.length; i++) {
const humanPart = humanParts[i];
if (hoistedParts[0] === humanPart) {
hoistedParts.shift();
if (i < humanParts.length - 1) {
humanParts[i] += '#';
}
} else {
humanParts[i] = reporter.format.dim(`${humanPart}#`);
}
}
human = humanParts.join('');
}
// skip unnecessary checks for linked dependencies
const remoteType = pkg._reference.remote.type;
const isLinkedDependency = remoteType === 'link' || remoteType === 'workspace' || remoteType === 'file' && config.linkFileDependencies;
const isResolution = pkg._reference.hint === 'resolution';
if (isLinkedDependency || isResolution) {
continue;
}
if (!(yield (_fs || _load_fs()).exists(loc))) {
if (pkg._reference.optional) {
reporter.warn(reporter.lang('optionalDepNotInstalled', human));
} else {
reportError('packageNotInstalled', human);
}
continue;
}
const pkgLoc = path.join(loc, 'package.json');
if (yield (_fs || _load_fs()).exists(pkgLoc)) {
const packageJson = yield config.readJson(pkgLoc);
packageJson.version = semver.clean(packageJson.version);
if (pkg.version !== packageJson.version) {
// node_modules contains wrong version
reportError('packageWrongVersion', human, pkg.version, packageJson.version);
}
const deps = Object.assign({}, packageJson.dependencies, packageJson.peerDependencies);
bundledDeps[packageJson.name] = packageJson.bundledDependencies || [];
for (const name in deps) {
const range = deps[name];
if (!semver.validRange(range, config.looseSemver)) {
continue; // exotic
}
const subHuman = `${human}#${name}@${range}`;
// find the package that this will resolve to, factoring in hoisting
const possibles = [];
let depLoc;
for (let i = parts.length; i >= 0; i--) {
const myParts = parts.slice(0, i).concat(name);
// build package.json location for this position
const myDepPkgLoc = path.join(config.cwd, 'node_modules', myParts.join(`${path.sep}node_modules${path.sep}`));
possibles.push(myDepPkgLoc);
}
while (possibles.length) {
const myDepPkgLoc = possibles.shift();
if (yield (_fs || _load_fs()).exists(myDepPkgLoc)) {
depLoc = myDepPkgLoc;
break;
}
}
if (!depLoc) {
// we'll hit the module not install error above when this module is hit
continue;
}
const depPkgLoc = path.join(depLoc, 'package.json');
if (yield (_fs || _load_fs()).exists(depPkgLoc)) {
const depPkg = yield config.readJson(depPkgLoc);
const foundHuman = `${humaniseLocation(path.dirname(depPkgLoc)).join('#')}@${depPkg.version}`;
if (!semver.satisfies(depPkg.version, range, config.looseSemver)) {
// module isn't correct semver
const resPattern = install.resolutionMap.find(name, originalKey.split('#'));
if (resPattern) {
const resHuman = `${human}#${resPattern}`;
var _normalizePattern = (0, (_normalizePattern2 || _load_normalizePattern()).normalizePattern)(resPattern);
const resRange = _normalizePattern.range;
if (semver.satisfies(depPkg.version, resRange, config.looseSemver)) {
reporter.warn(reporter.lang('incompatibleResolutionVersion', foundHuman, subHuman));
warningCount++;
} else {
reportError('packageDontSatisfy', resHuman, foundHuman);
}
} else {
reportError('packageDontSatisfy', subHuman, foundHuman);
}
continue;
}
// check for modules above us that this could be deduped to
for (var _iterator4 = possibles, _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) {
var _ref10;
if (_isArray4) {
if (_i4 >= _iterator4.length) break;
_ref10 = _iterator4[_i4++];
} else {
_i4 = _iterator4.next();
if (_i4.done) break;
_ref10 = _i4.value;
}
const loc = _ref10;
const locPkg = path.join(loc, 'package.json');
if (!(yield (_fs || _load_fs()).exists(locPkg))) {
continue;
}
const packageJson = yield config.readJson(locPkg);
const packagePath = originalKey.split('#');
const rootDep = packagePath[0];
const packageName = packagePath[1] || packageJson.name;
const bundledDep = bundledDeps[rootDep] && bundledDeps[rootDep].indexOf(packageName) !== -1;
if (!bundledDep && (packageJson.version === depPkg.version || semver.satisfies(packageJson.version, range, config.looseSemver) && semver.gt(packageJson.version, depPkg.version, config.looseSemver))) {
reporter.warn(reporter.lang('couldBeDeduped', subHuman, packageJson.version, `${humaniseLocation(path.dirname(locPkg)).join('#')}@${packageJson.version}`));
warningCount++;
}
break;
}
}
}
}
}
if (warningCount > 1) {
reporter.info(reporter.lang('foundWarnings', warningCount));
}
if (errCount > 0) {
throw new (_errors || _load_errors()).MessageError(reporter.lang('foundErrors', errCount));
} else {
reporter.success(reporter.lang('folderInSync'));
}
});
return function run(_x9, _x10, _x11, _x12) {
return _ref5.apply(this, arguments);
};
})();
exports.hasWrapper = hasWrapper;
exports.setFlags = setFlags;
var _errors;
function _load_errors() {
return _errors = require('../../errors.js');
}
var _integrityChecker;
function _load_integrityChecker() {
return _integrityChecker = _interopRequireDefault(require('../../integrity-checker.js'));
}
var _integrityChecker2;
function _load_integrityChecker2() {
return _integrityChecker2 = require('../../integrity-checker.js');
}
var _lockfile;
function _load_lockfile() {
return _lockfile = _interopRequireDefault(require('../../lockfile'));
}
var _fs;
function _load_fs() {
return _fs = _interopRequireWildcard(require('../../util/fs.js'));
}
var _install;
function _load_install() {
return _install = require('./install.js');
}
var _normalizePattern2;
function _load_normalizePattern() {
return _normalizePattern2 = require('../../util/normalize-pattern.js');
}
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const semver = require('semver');
const path = require('path');
const requireLockfile = exports.requireLockfile = false;
const noArguments = exports.noArguments = true;
function hasWrapper(commander) {
return true;
}
function setFlags(commander) {
commander.description('Verifies if versions in the current project’s package.json match that of yarn’s lock file.');
commander.option('--integrity');
commander.option('--verify-tree');
}