@lerna/publish
Version:
Publish packages in the current project
192 lines (191 loc) • 7.33 kB
JavaScript
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var import_core = require("@lerna/core");
var import_dedent = __toESM(require("dedent"));
var import_npm_package_arg = __toESM(require("npm-package-arg"));
var import_p_map = __toESM(require("p-map"));
var import_pacote = __toESM(require("pacote"));
var import_path = __toESM(require("path"));
var import_semver = __toESM(require("semver"));
const bootstrap = require("@lerna/commands/bootstrap");
const { getRangeToReference } = require("./lib/get-range-to-reference");
module.exports = function factory(argv) {
return new AddCommand(argv);
};
class AddCommand extends import_core.Command {
get requiresGit() {
return false;
}
get dependencyType() {
if (this.options.dev) {
return "devDependencies";
}
if (this.options.peer) {
return "peerDependencies";
}
return "dependencies";
}
initialize() {
if (this.options.npmClient === "pnpm") {
throw new import_core.ValidationError(
"EPNPMNOTSUPPORTED",
"Add is not supported when using `pnpm` workspaces. Use `pnpm` directly to add dependencies to packages: https://pnpm.io/cli/add"
);
}
this.spec = (0, import_npm_package_arg.default)(this.options.pkg);
this.dirs = new Set(this.options.globs.map((fp) => import_path.default.resolve(this.project.rootPath, fp)));
this.selfSatisfied = this.packageSatisfied();
this.savePrefix = this.options.exact ? "" : "^";
if (this.packageGraph.has(this.spec.name) && !this.selfSatisfied) {
const available = this.packageGraph.get(this.spec.name).version;
throw new import_core.ValidationError(
"ENOTSATISFIED",
import_dedent.default`
Requested range not satisfiable:
${this.spec.name}@${this.spec.fetchSpec} (available: ${available})
`
);
}
let chain = Promise.resolve();
chain = chain.then(() => this.getPackageVersion());
chain = chain.then((version) => {
if (version == null) {
throw new import_core.ValidationError(
"ENOTSATISFIED",
import_dedent.default`
Requested package has no version: ${this.spec.name}
`
);
}
this.spec.version = version;
});
chain = chain.then(() => (0, import_core.getFilteredPackages)(this.packageGraph, this.execOpts, this.options));
chain = chain.then((filteredPackages) => {
this.filteredPackages = filteredPackages;
});
chain = chain.then(() => this.collectPackagesToChange());
chain = chain.then((packagesToChange) => {
this.packagesToChange = packagesToChange;
});
return chain.then(() => {
const proceed = this.packagesToChange.length > 0;
if (!proceed) {
this.logger.warn(`No packages found where ${this.spec.name} can be added.`);
}
return proceed;
});
}
execute() {
const numberOfPackages = `${this.packagesToChange.length} package${this.packagesToChange.length > 1 ? "s" : ""}`;
this.logger.info("", `Adding ${this.spec.name} in ${numberOfPackages}`);
let chain = Promise.resolve();
chain = chain.then(() => this.makeChanges());
if (this.options.bootstrap !== false) {
chain = chain.then(() => {
const argv = Object.assign({}, this.options, {
args: [],
cwd: this.project.rootPath,
// silence initial cli version logging, etc
composed: "add",
// NEVER pass filter-options, it is very bad
scope: void 0,
ignore: void 0,
private: void 0,
since: void 0,
excludeDependents: void 0,
includeDependents: void 0,
includeDependencies: void 0
});
return bootstrap(argv);
});
}
return chain;
}
collectPackagesToChange() {
const { name: targetName } = this.spec;
let result = this.filteredPackages;
if (this.packageGraph.has(targetName)) {
result = result.filter((pkg) => pkg.name !== targetName);
}
if (this.dirs.size) {
result = result.filter((pkg) => this.dirs.has(pkg.location));
}
result = result.filter((pkg) => {
const deps = this.getPackageDeps(pkg);
if (!(targetName in deps)) {
return true;
}
return getRangeToReference(this.spec, deps, pkg.location, this.savePrefix) !== deps[targetName];
});
return result;
}
makeChanges() {
const { name: targetName } = this.spec;
return (0, import_p_map.default)(this.packagesToChange, (pkg) => {
const deps = this.getPackageDeps(pkg);
const range = getRangeToReference(this.spec, deps, pkg.location, this.savePrefix);
this.logger.verbose("add", `${targetName}@${range} to ${this.dependencyType} in ${pkg.name}`);
deps[targetName] = range;
return pkg.serialize();
});
}
getPackageDeps(pkg) {
let deps = pkg.get(this.dependencyType);
if (!deps) {
deps = {};
pkg.set(this.dependencyType, deps);
}
return deps;
}
getPackageVersion() {
if (this.selfSatisfied) {
const node = this.packageGraph.get(this.spec.name);
return Promise.resolve(this.spec.saveRelativeFileSpec ? node.location : node.version);
}
const opts = (0, import_core.npmConf)({
includeDeprecated: false,
// we can't pass everything, as our --scope conflicts with pacote's --scope
registry: this.options.registry
});
return import_pacote.default.manifest(this.spec, opts.snapshot).then((pkg) => pkg.version);
}
packageSatisfied() {
const { name, fetchSpec } = this.spec;
const pkg = this.packageGraph.get(name);
if (!pkg) {
return false;
}
if (this.spec.type === "directory" && fetchSpec === pkg.location) {
this.spec.saveRelativeFileSpec = true;
return true;
}
this.spec.saveRelativeFileSpec = Array.from(this.packageGraph.values()).some(
(node) => node.localDependencies.size && Array.from(node.localDependencies.values()).some((resolved) => resolved.type === "directory")
);
if (fetchSpec === "latest") {
return true;
}
return import_semver.default.intersects(pkg.version, fetchSpec);
}
}
module.exports.AddCommand = AddCommand;