@dependabot/yarn-lib
Version:
📦🐈 Fast, reliable, and secure dependency management.
558 lines (444 loc) • 18.6 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _asyncToGenerator2;
function _load_asyncToGenerator() {
return _asyncToGenerator2 = _interopRequireDefault(require('babel-runtime/helpers/asyncToGenerator'));
}
var _path;
function _load_path() {
return _path = _interopRequireDefault(require('path'));
}
var _invariant;
function _load_invariant() {
return _invariant = _interopRequireDefault(require('invariant'));
}
var _semver;
function _load_semver() {
return _semver = _interopRequireDefault(require('semver'));
}
var _validate;
function _load_validate() {
return _validate = require('./util/normalize-manifest/validate.js');
}
var _lockfile;
function _load_lockfile() {
return _lockfile = _interopRequireDefault(require('./lockfile'));
}
var _packageReference;
function _load_packageReference() {
return _packageReference = _interopRequireDefault(require('./package-reference.js'));
}
var _index;
function _load_index() {
return _index = require('./resolvers/index.js');
}
var _errors;
function _load_errors() {
return _errors = require('./errors.js');
}
var _constants;
function _load_constants() {
return _constants = _interopRequireWildcard(require('./constants.js'));
}
var _version;
function _load_version() {
return _version = _interopRequireWildcard(require('./util/version.js'));
}
var _workspaceResolver;
function _load_workspaceResolver() {
return _workspaceResolver = _interopRequireDefault(require('./resolvers/contextual/workspace-resolver.js'));
}
var _fs;
function _load_fs() {
return _fs = _interopRequireWildcard(require('./util/fs.js'));
}
var _normalizePattern4;
function _load_normalizePattern() {
return _normalizePattern4 = 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 micromatch = require('micromatch');
class PackageRequest {
constructor(req, resolver) {
this.parentRequest = req.parentRequest;
this.parentNames = req.parentNames || [];
this.lockfile = resolver.lockfile;
this.registry = req.registry;
this.reporter = resolver.reporter;
this.resolver = resolver;
this.optional = req.optional;
this.pattern = req.pattern;
this.config = resolver.config;
this.foundInfo = null;
}
init() {
this.resolver.usedRegistries.add(this.registry);
}
getLocked(remoteType) {
// always prioritise root lockfile
const shrunk = this.lockfile.getLocked(this.pattern);
if (shrunk && shrunk.resolved) {
const resolvedParts = (_version || _load_version()).explodeHashedUrl(shrunk.resolved);
// Detect Git protocols (git://HOST/PATH or git+PROTOCOL://HOST/PATH)
const preferredRemoteType = /^git(\+[a-z0-9]+)?:\/\//.test(resolvedParts.url) ? 'git' : remoteType;
return {
name: shrunk.name,
version: shrunk.version,
_uid: shrunk.uid,
_remote: {
resolved: shrunk.resolved,
type: preferredRemoteType,
reference: resolvedParts.url,
hash: resolvedParts.hash,
registry: shrunk.registry
},
optionalDependencies: shrunk.optionalDependencies || {},
dependencies: shrunk.dependencies || {},
prebuiltVariants: shrunk.prebuiltVariants || {}
};
} else {
return null;
}
}
/**
* If the input pattern matches a registry one then attempt to find it on the registry.
* Otherwise fork off to an exotic resolver if one matches.
*/
findVersionOnRegistry(pattern) {
var _this = this;
return (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* () {
var _ref = yield _this.normalize(pattern);
const range = _ref.range,
name = _ref.name;
const exoticResolver = (0, (_index || _load_index()).getExoticResolver)(range);
if (exoticResolver) {
let data = yield _this.findExoticVersionInfo(exoticResolver, range);
// clone data as we're manipulating it in place and this could be resolved multiple
// times
data = Object.assign({}, data);
// this is so the returned package response uses the overridden name. ie. if the
// package's actual name is `bar`, but it's been specified in the manifest like:
// "foo": "http://foo.com/bar.tar.gz"
// then we use the foo name
data.name = name;
return data;
}
const Resolver = _this.getRegistryResolver();
const resolver = new Resolver(_this, name, range);
try {
return yield resolver.resolve();
} catch (err) {
// if it is not an error thrown by yarn and it has a parent request,
// thow a more readable error
if (!(err instanceof (_errors || _load_errors()).MessageError) && _this.parentRequest && _this.parentRequest.pattern) {
throw new (_errors || _load_errors()).MessageError(_this.reporter.lang('requiredPackageNotFoundRegistry', pattern, _this.parentRequest.pattern, _this.registry));
}
throw err;
}
})();
}
/**
* Get the registry resolver associated with this package request.
*/
getRegistryResolver() {
const Resolver = (_index || _load_index()).registries[this.registry];
if (Resolver) {
return Resolver;
} else {
throw new (_errors || _load_errors()).MessageError(this.reporter.lang('unknownRegistryResolver', this.registry));
}
}
normalizeRange(pattern) {
var _this2 = this;
return (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* () {
if (pattern.indexOf(':') > -1 || pattern.indexOf('@') > -1 || (0, (_index || _load_index()).getExoticResolver)(pattern)) {
return pattern;
}
if (!(_semver || _load_semver()).default.validRange(pattern)) {
try {
if (yield (_fs || _load_fs()).exists((_path || _load_path()).default.join(_this2.config.cwd, pattern, (_constants || _load_constants()).NODE_PACKAGE_JSON))) {
_this2.reporter.warn(_this2.reporter.lang('implicitFileDeprecated', pattern));
return `file:${pattern}`;
}
} catch (err) {
// pass
}
}
return pattern;
})();
}
normalize(pattern) {
var _this3 = this;
return (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* () {
var _normalizePattern = (0, (_normalizePattern4 || _load_normalizePattern()).normalizePattern)(pattern);
const name = _normalizePattern.name,
range = _normalizePattern.range,
hasVersion = _normalizePattern.hasVersion;
const newRange = yield _this3.normalizeRange(range);
return { name, range: newRange, hasVersion };
})();
}
/**
* Construct an exotic resolver instance with the input `ExoticResolver` and `range`.
*/
findExoticVersionInfo(ExoticResolver, range) {
const resolver = new ExoticResolver(this, range);
return resolver.resolve();
}
/**
* If the current pattern matches an exotic resolver then delegate to it or else try
* the registry.
*/
findVersionInfo() {
const exoticResolver = (0, (_index || _load_index()).getExoticResolver)(this.pattern);
if (exoticResolver) {
return this.findExoticVersionInfo(exoticResolver, this.pattern);
} else if ((_workspaceResolver || _load_workspaceResolver()).default.isWorkspace(this.pattern, this.resolver.workspaceLayout)) {
(0, (_invariant || _load_invariant()).default)(this.resolver.workspaceLayout, 'expected workspaceLayout');
const resolver = new (_workspaceResolver || _load_workspaceResolver()).default(this, this.pattern, this.resolver.workspaceLayout);
return resolver.resolve();
} else {
return this.findVersionOnRegistry(this.pattern);
}
}
reportResolvedRangeMatch(info, resolved) {}
/**
* Do the final resolve of a package that had a match with an existing version.
* After all unique versions have been discovered, so the best available version
* is found.
*/
resolveToExistingVersion(info) {
// get final resolved version
var _normalizePattern2 = (0, (_normalizePattern4 || _load_normalizePattern()).normalizePattern)(this.pattern);
const range = _normalizePattern2.range,
name = _normalizePattern2.name;
const solvedRange = (_semver || _load_semver()).default.validRange(range) ? info.version : range;
const resolved = this.resolver.getHighestRangeVersionMatch(name, solvedRange, info);
(0, (_invariant || _load_invariant()).default)(resolved, 'should have a resolved reference');
this.reportResolvedRangeMatch(info, resolved);
const ref = resolved._reference;
(0, (_invariant || _load_invariant()).default)(ref, 'Resolved package info has no package reference');
ref.addRequest(this);
ref.addPattern(this.pattern, resolved);
ref.addOptional(this.optional);
}
/**
* TODO description
*/
find({ fresh, frozen }) {
var _this4 = this;
return (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* () {
// find version info for this package pattern
const info = yield _this4.findVersionInfo();
if (!(_semver || _load_semver()).default.valid(info.version)) {
throw new (_errors || _load_errors()).MessageError(_this4.reporter.lang('invalidPackageVersion', info.name, info.version));
}
info.fresh = fresh;
(0, (_validate || _load_validate()).cleanDependencies)(info, false, _this4.reporter, function () {
// swallow warnings
});
// check if while we were resolving this dep we've already resolved one that satisfies
// the same range
var _normalizePattern3 = (0, (_normalizePattern4 || _load_normalizePattern()).normalizePattern)(_this4.pattern);
const range = _normalizePattern3.range,
name = _normalizePattern3.name;
const solvedRange = (_semver || _load_semver()).default.validRange(range) ? info.version : range;
const resolved = !info.fresh || frozen ? _this4.resolver.getExactVersionMatch(name, solvedRange, info) : _this4.resolver.getHighestRangeVersionMatch(name, solvedRange, info);
if (resolved) {
_this4.resolver.reportPackageWithExistingVersion(_this4, info);
return;
}
if (info.flat && !_this4.resolver.flat) {
throw new (_errors || _load_errors()).MessageError(_this4.reporter.lang('flatGlobalError'));
}
// validate version info
PackageRequest.validateVersionInfo(info, _this4.reporter);
//
const remote = info._remote;
(0, (_invariant || _load_invariant()).default)(remote, 'Missing remote');
// set package reference
const ref = new (_packageReference || _load_packageReference()).default(_this4, info, remote);
ref.addPattern(_this4.pattern, info);
ref.addOptional(_this4.optional);
ref.setFresh(fresh);
info._reference = ref;
info._remote = remote;
// start installation of dependencies
const promises = [];
const deps = [];
const parentNames = [..._this4.parentNames, name];
// normal deps
for (const depName in info.dependencies) {
const depPattern = depName + '@' + info.dependencies[depName];
deps.push(depPattern);
promises.push(_this4.resolver.find({
pattern: depPattern,
registry: remote.registry,
// dependencies of optional dependencies should themselves be optional
optional: _this4.optional,
parentRequest: _this4,
parentNames
}));
}
// optional deps
for (const depName in info.optionalDependencies) {
const depPattern = depName + '@' + info.optionalDependencies[depName];
deps.push(depPattern);
promises.push(_this4.resolver.find({
pattern: depPattern,
registry: remote.registry,
optional: true,
parentRequest: _this4,
parentNames
}));
}
if (remote.type === 'workspace' && !_this4.config.production) {
// workspaces support dev dependencies
for (const depName in info.devDependencies) {
const depPattern = depName + '@' + info.devDependencies[depName];
deps.push(depPattern);
promises.push(_this4.resolver.find({
pattern: depPattern,
registry: remote.registry,
optional: false,
parentRequest: _this4,
parentNames
}));
}
}
for (var _iterator = promises, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _ref2;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref2 = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref2 = _i.value;
}
const promise = _ref2;
yield promise;
}
ref.addDependencies(deps);
// Now that we have all dependencies, it's safe to propagate optional
for (var _iterator2 = ref.requests.slice(1), _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {
var _ref3;
if (_isArray2) {
if (_i2 >= _iterator2.length) break;
_ref3 = _iterator2[_i2++];
} else {
_i2 = _iterator2.next();
if (_i2.done) break;
_ref3 = _i2.value;
}
const otherRequest = _ref3;
ref.addOptional(otherRequest.optional);
}
})();
}
/**
* TODO description
*/
static validateVersionInfo(info, reporter) {
// human readable name to use in errors
const human = `${info.name}@${info.version}`;
info.version = PackageRequest.getPackageVersion(info);
for (var _iterator3 = (_constants || _load_constants()).REQUIRED_PACKAGE_KEYS, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) {
var _ref4;
if (_isArray3) {
if (_i3 >= _iterator3.length) break;
_ref4 = _iterator3[_i3++];
} else {
_i3 = _iterator3.next();
if (_i3.done) break;
_ref4 = _i3.value;
}
const key = _ref4;
if (!info[key]) {
throw new (_errors || _load_errors()).MessageError(reporter.lang('missingRequiredPackageKey', human, key));
}
}
}
/**
* Returns the package version if present, else defaults to the uid
*/
static getPackageVersion(info) {
// TODO possibly reconsider this behaviour
return info.version === undefined ? info._uid : info.version;
}
/**
* Gets all of the outdated packages and sorts them appropriately
*/
static getOutdatedPackages(lockfile, install, config, reporter, filterByPatterns, flags) {
return (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* () {
var _ref5 = yield install.fetchRequestFromCwd();
const reqPatterns = _ref5.requests,
workspaceLayout = _ref5.workspaceLayout;
// Filter out workspace patterns if necessary
let depReqPatterns = workspaceLayout ? reqPatterns.filter(function (p) {
return !workspaceLayout.getManifestByPattern(p.pattern);
}) : reqPatterns;
// filter the list down to just the packages requested.
// prevents us from having to query the metadata for all packages.
if (filterByPatterns && filterByPatterns.length) {
const filterByNames = filterByPatterns.map(function (pattern) {
return (0, (_normalizePattern4 || _load_normalizePattern()).normalizePattern)(pattern).name;
});
depReqPatterns = depReqPatterns.filter(function (dep) {
return filterByNames.indexOf((0, (_normalizePattern4 || _load_normalizePattern()).normalizePattern)(dep.pattern).name) >= 0 || flags && flags.pattern && micromatch.contains((0, (_normalizePattern4 || _load_normalizePattern()).normalizePattern)(dep.pattern).name, flags.pattern);
});
}
const deps = yield Promise.all(depReqPatterns.map((() => {
var _ref6 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* ({ pattern, hint, workspaceName, workspaceLoc }) {
const locked = lockfile.getLocked(pattern);
if (!locked) {
throw new (_errors || _load_errors()).MessageError(reporter.lang('lockfileOutdated'));
}
const name = locked.name,
current = locked.version;
let latest = '';
let wanted = '';
let url = '';
const normalized = (0, (_normalizePattern4 || _load_normalizePattern()).normalizePattern)(pattern);
if ((0, (_index || _load_index()).getExoticResolver)(pattern) || (0, (_index || _load_index()).getExoticResolver)(normalized.range)) {
latest = wanted = 'exotic';
url = normalized.range;
} else {
const registry = config.registries[locked.registry];
var _ref7 = yield registry.checkOutdated(config, name, normalized.range);
latest = _ref7.latest;
wanted = _ref7.wanted;
url = _ref7.url;
}
return {
name,
current,
wanted,
latest,
url,
hint,
range: normalized.range,
upgradeTo: '',
workspaceName: workspaceName || '',
workspaceLoc: workspaceLoc || ''
};
});
return function (_x) {
return _ref6.apply(this, arguments);
};
})()));
// Make sure to always output `exotic` versions to be compatible with npm
const isDepOld = function isDepOld({ current, latest, wanted }) {
return latest === 'exotic' || (_semver || _load_semver()).default.lt(current, wanted) || (_semver || _load_semver()).default.lt(current, latest);
};
const orderByName = function orderByName(depA, depB) {
return depA.name.localeCompare(depB.name);
};
return deps.filter(isDepOld).sort(orderByName);
})();
}
}
exports.default = PackageRequest;