@lerna/publish
Version:
Publish packages in the current project
705 lines (704 loc) • 29.3 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_crypto = __toESM(require("crypto"));
var import_fs = __toESM(require("fs"));
var import_os = __toESM(require("os"));
var import_p_map = __toESM(require("p-map"));
var import_p_pipe = __toESM(require("p-pipe"));
var import_path = __toESM(require("path"));
var import_semver = __toESM(require("semver"));
const versionCommand = require("@lerna/commands/version");
const { createTempLicenses } = require("./lib/create-temp-licenses");
const { getCurrentSHA } = require("./lib/get-current-sha");
const { getCurrentTags } = require("./lib/get-current-tags");
const { getUnpublishedPackages } = require("./lib/get-unpublished-packages");
const { getNpmUsername } = require("./lib/get-npm-username");
const { getTaggedPackages } = require("./lib/get-tagged-packages");
const { getPackagesWithoutLicense } = require("./lib/get-packages-without-license");
const { gitCheckout } = require("./lib/git-checkout");
const { removeTempLicenses } = require("./lib/remove-temp-licenses");
const { verifyNpmPackageAccess } = require("./lib/verify-npm-package-access");
const { getTwoFactorAuthRequired } = require("./lib/get-two-factor-auth-required");
module.exports = function factory(argv) {
return new PublishCommand(argv);
};
class PublishCommand extends import_core.Command {
get otherCommandConfigs() {
return ["version"];
}
get requiresGit() {
return this.options.bump !== "from-package";
}
configureProperties() {
super.configureProperties();
this.toposort = this.options.sort !== false;
const {
// prettier-ignore
exact,
gitHead,
gitReset,
tagVersionPrefix = "v",
verifyAccess
} = this.options;
if (this.requiresGit && gitHead) {
throw new import_core.ValidationError("EGITHEAD", "--git-head is only allowed with 'from-package' positional");
}
this.savePrefix = exact ? "" : "^";
this.tagPrefix = tagVersionPrefix;
this.gitReset = gitReset !== false;
this.npmSession = import_crypto.default.randomBytes(8).toString("hex");
this.verifyAccess = verifyAccess;
}
get userAgent() {
return `lerna/${this.options.lernaVersion}/node@${process.version}+${process.arch} (${process.platform})`;
}
initialize() {
if (this.options.verifyAccess === false) {
this.logger.warn(
"verify-access",
"--verify-access=false and --no-verify-access are no longer needed, because the legacy preemptive access verification is now disabled by default. Requests will fail with appropriate errors when not authorized correctly."
);
}
if (this.options.graphType === "dependencies") {
this.logger.warn(
"graph-type",
"--graph-type=dependencies is deprecated and will be removed in lerna v6. If you have a use-case you feel requires it please open an issue to discuss: https://github.com/lerna/lerna/issues/new/choose"
);
}
if (this.options.includePrivate) {
if (this.options.includePrivate.length === 0) {
throw new import_core.ValidationError(
"EINCLPRIV",
"Must specify at least one private package to include with --include-private."
);
}
this.logger.info("publish", `Including private packages %j`, this.options.includePrivate);
}
if (this.options.skipNpm) {
this.logger.warn("deprecated", "Instead of --skip-npm, call `lerna version` directly");
return versionCommand(this.argv).then(() => false);
}
if (this.options.buildMetadata && this.options.canary) {
throw new import_core.ValidationError(
"ENOTSATISFIED",
"Cannot use --build-metadata in conjunction with --canary option."
);
} else if (this.options.canary) {
this.logger.info("canary", "enabled");
}
if (this.options.requireScripts) {
this.logger.info("require-scripts", "enabled");
}
this.logger.verbose("session", this.npmSession);
this.logger.verbose("user-agent", this.userAgent);
this.conf = (0, import_core.npmConf)({
lernaCommand: "publish",
_auth: this.options.legacyAuth,
npmSession: this.npmSession,
npmVersion: this.userAgent,
otp: this.options.otp,
registry: this.options.registry,
"ignore-prepublish": this.options.ignorePrepublish,
"ignore-scripts": this.options.ignoreScripts
});
this.otpCache = { otp: this.conf.get("otp") };
this.conf.set("user-agent", this.userAgent, "cli");
if (this.conf.get("registry") === "https://registry.yarnpkg.com") {
this.logger.warn("", "Yarn's registry proxy is broken, replacing with public npm registry");
this.logger.warn("", "If you don't have an npm token, you should exit and run `npm login`");
this.conf.set("registry", "https://registry.npmjs.org/", "cli");
}
const distTag = this.getDistTag();
if (distTag) {
this.conf.set("tag", distTag.trim(), "cli");
}
this.hasRootedLeaf = this.packageGraph.has(this.project.manifest.name);
if (this.hasRootedLeaf) {
this.logger.info("publish", "rooted leaf detected, skipping synthetic root lifecycles");
}
this.runPackageLifecycle = (0, import_core.createRunner)(this.options);
this.runRootLifecycle = /^(pre|post)?publish$/.test(process.env.npm_lifecycle_event) ? (stage) => {
this.logger.warn("lifecycle", "Skipping root %j because it has already been called", stage);
} : (stage) => this.runPackageLifecycle(this.project.manifest, stage);
let chain = Promise.resolve();
if (this.options.bump === "from-git") {
chain = chain.then(() => this.detectFromGit());
} else if (this.options.bump === "from-package") {
chain = chain.then(() => this.detectFromPackage());
} else if (this.options.canary) {
chain = chain.then(() => this.detectCanaryVersions());
} else {
chain = chain.then(() => versionCommand(this.argv));
}
return chain.then((result) => {
if (!result) {
return false;
}
if (!result.updates.length) {
this.logger.success("No changed packages to publish");
return false;
}
this.updates = this.filterPrivatePkgUpdates(result.updates);
this.updatesVersions = new Map(result.updatesVersions);
this.packagesToPublish = this.updates.map((node) => node.pkg);
if (this.options.contents) {
for (const pkg of this.packagesToPublish) {
pkg.contents = this.options.contents;
}
}
if (result.needsConfirmation) {
return this.confirmPublish();
}
return true;
});
}
execute() {
this.enableProgressBar();
this.logger.info("publish", "Publishing packages to npm...");
let chain = Promise.resolve();
chain = chain.then(() => this.prepareRegistryActions());
chain = chain.then(() => this.prepareLicenseActions());
chain = chain.then(() => this.preparePrivatePackages());
if (this.options.canary) {
chain = chain.then(() => this.updateCanaryVersions());
}
chain = chain.then(() => this.resolveLocalDependencyLinks());
chain = chain.then(() => this.resolveWorkspaceDependencyLinks());
chain = chain.then(() => this.annotateGitHead());
chain = chain.then(() => this.serializeChanges());
chain = chain.then(() => this.packUpdated());
chain = chain.then(() => this.publishPacked());
chain = chain.then(() => this.restorePrivatePackages());
chain = chain.then(() => this.serializeChanges());
if (this.gitReset) {
chain = chain.then(() => this.resetChanges());
}
if (this.options.tempTag) {
chain = chain.then(() => this.npmUpdateAsLatest());
}
return chain.then(() => {
const count = this.publishedPackages.length;
const publishedPackagesSorted = this.publishedPackages.sort((a, b) => a.name.localeCompare(b.name));
if (!count) {
this.logger.success("All packages have already been published.");
return;
}
(0, import_core.output)("Successfully published:");
if (this.options.summaryFile !== void 0) {
const filePath = this.options.summaryFile ? `${this.options.summaryFile}/lerna-publish-summary.json` : "./lerna-publish-summary.json";
const jsonObject = publishedPackagesSorted.map((pkg) => {
return {
packageName: pkg.name,
version: pkg.version
};
});
(0, import_core.output)(jsonObject);
try {
import_fs.default.writeFileSync(filePath, JSON.stringify(jsonObject));
(0, import_core.output)("Publish summary created: ", filePath);
} catch (error) {
(0, import_core.output)("Failed to create the summary report", error);
}
} else {
const message = publishedPackagesSorted.map((pkg) => ` - ${pkg.name}@${pkg.version}`);
(0, import_core.output)(message.join(import_os.default.EOL));
}
this.logger.success("published", "%d %s", count, count === 1 ? "package" : "packages");
});
}
verifyWorkingTreeClean() {
return (0, import_core.describeRef)(this.execOpts).then(import_core.throwIfUncommitted);
}
detectFromGit() {
const matchingPattern = this.project.isIndependent() ? "*@*" : `${this.tagPrefix}*.*.*`;
let chain = Promise.resolve();
chain = chain.then(() => this.verifyWorkingTreeClean()).catch((err) => {
if (err.failed && /git describe/.test(err.command)) {
this.logger.silly("EWORKINGTREE", err.message);
this.logger.notice("FYI", "Unable to verify working tree, proceed at your own risk");
} else {
throw err;
}
});
chain = chain.then(() => getCurrentTags(this.execOpts, matchingPattern));
chain = chain.then((taggedPackageNames) => {
if (!taggedPackageNames.length) {
this.logger.notice("from-git", "No tagged release found");
return [];
}
if (this.project.isIndependent()) {
return taggedPackageNames.map((name) => this.packageGraph.get(name));
}
return getTaggedPackages(this.packageGraph, this.project.rootPath, this.execOpts);
});
chain = chain.then((updates) => this.filterPrivatePkgUpdates(updates));
return chain.then((updates) => {
const updatesVersions = updates.map((node) => [node.name, node.version]);
return {
updates,
updatesVersions,
needsConfirmation: true
};
});
}
detectFromPackage() {
let chain = Promise.resolve();
chain = chain.then(() => this.verifyWorkingTreeClean()).catch((err) => {
if (err.failed && /git describe/.test(err.command)) {
this.logger.silly("EWORKINGTREE", err.message);
this.logger.notice("FYI", "Unable to verify working tree, proceed at your own risk");
process.exitCode = 0;
} else {
throw err;
}
});
chain = chain.then(() => getUnpublishedPackages(this.packageGraph, this.conf.snapshot));
chain = chain.then((updates) => this.filterPrivatePkgUpdates(updates));
chain = chain.then((unpublished) => {
if (!unpublished.length) {
this.logger.notice("from-package", "No unpublished release found");
}
return unpublished;
});
return chain.then((updates) => {
const updatesVersions = updates.map((node) => [node.name, node.version]);
return {
updates,
updatesVersions,
needsConfirmation: true
};
});
}
detectCanaryVersions() {
const { cwd } = this.execOpts;
const {
bump = "prepatch",
preid = "alpha",
ignoreChanges,
forcePublish,
includeMergedTags
} = this.options;
const release = bump.startsWith("pre") ? bump.replace("release", "patch") : `pre${bump}`;
let chain = Promise.resolve();
chain = chain.then(() => this.verifyWorkingTreeClean()).catch((err) => {
if (err.failed && /git describe/.test(err.command)) {
this.logger.silly("EWORKINGTREE", err.message);
this.logger.notice("FYI", "Unable to verify working tree, proceed at your own risk");
} else {
throw err;
}
});
chain = chain.then(
() => this.filterPrivatePkgUpdates(
(0, import_core.collectUpdates)(this.packageGraph.rawPackageList, this.packageGraph, this.execOpts, {
bump: "prerelease",
canary: true,
ignoreChanges,
forcePublish,
includeMergedTags
})
)
);
const makeVersion = (fallback) => ({ lastVersion = fallback, refCount, sha }) => {
const nextVersion = import_semver.default.inc(lastVersion.replace(this.tagPrefix, ""), release.replace("pre", ""));
return `${nextVersion}-${preid}.${Math.max(0, refCount - 1)}+${sha}`;
};
if (this.project.isIndependent()) {
chain = chain.then(
(updates) => (0, import_p_map.default)(
updates,
(node) => (0, import_core.describeRef)(
{
match: `${node.name}@*`,
cwd
},
includeMergedTags
).then(makeVersion(node.version)).then((version) => [node.name, version])
).then((updatesVersions) => ({
updates,
updatesVersions
}))
);
} else {
chain = chain.then(
(updates) => (0, import_core.describeRef)(
{
match: `${this.tagPrefix}*.*.*`,
cwd
},
includeMergedTags
).then(makeVersion(this.project.version)).then((version) => updates.map((node) => [node.name, version])).then((updatesVersions) => ({
updates,
updatesVersions
}))
);
}
return chain.then(({ updates, updatesVersions }) => ({
updates,
updatesVersions,
needsConfirmation: true
}));
}
confirmPublish() {
const count = this.packagesToPublish.length;
const message = this.packagesToPublish.map(
(pkg) => ` - ${pkg.name} => ${this.updatesVersions.get(pkg.name)}${pkg.private ? " (private!)" : ""}`
);
(0, import_core.output)("");
(0, import_core.output)(`Found ${count} ${count === 1 ? "package" : "packages"} to publish:`);
(0, import_core.output)(message.join(import_os.default.EOL));
(0, import_core.output)("");
if (this.options.yes) {
this.logger.info("auto-confirmed");
return true;
}
return (0, import_core.promptConfirmation)("Are you sure you want to publish these packages?");
}
preparePrivatePackages() {
return Promise.resolve().then(() => {
this.privatePackagesToPublish = [];
this.packagesToPublish.forEach((pkg) => {
if (pkg.private) {
pkg.removePrivate();
this.privatePackagesToPublish.push(pkg);
}
});
});
}
restorePrivatePackages() {
return Promise.resolve().then(() => {
this.privatePackagesToPublish.forEach((pkg) => {
pkg.private = true;
});
});
}
prepareLicenseActions() {
return Promise.resolve().then(() => getPackagesWithoutLicense(this.project, this.packagesToPublish)).then((packagesWithoutLicense) => {
if (packagesWithoutLicense.length && !this.project.licensePath) {
this.packagesToBeLicensed = [];
const names = packagesWithoutLicense.map((pkg) => pkg.name);
const noun = names.length > 1 ? "Packages" : "Package";
const verb = names.length > 1 ? "are" : "is";
const list = names.length > 1 ? `${names.slice(0, -1).join(", ")}${names.length > 2 ? "," : ""} and ${names[names.length - 1]}` : names[0];
this.logger.warn(
"ENOLICENSE",
"%s %s %s missing a license.\n%s\n%s",
noun,
list,
verb,
"One way to fix this is to add a LICENSE.md file to the root of this repository.",
"See https://choosealicense.com for additional guidance."
);
} else {
this.packagesToBeLicensed = packagesWithoutLicense;
}
});
}
prepareRegistryActions() {
let chain = Promise.resolve();
if (this.conf.get("registry") !== "https://registry.npmjs.org/") {
this.logger.notice("", "Skipping all user and access validation due to third-party registry");
this.logger.notice("", "Make sure you're authenticated properly \xAF\\_(\u30C4)_/\xAF");
return chain;
}
if (process.env.LERNA_INTEGRATION) {
return chain;
}
if (this.verifyAccess) {
chain = chain.then(() => getNpmUsername(this.conf.snapshot));
chain = chain.then((username) => {
if (username) {
return verifyNpmPackageAccess(this.packagesToPublish, username, this.conf.snapshot);
}
});
chain = chain.then(() => getTwoFactorAuthRequired(this.conf.snapshot));
chain = chain.then((isRequired) => {
this.twoFactorAuthRequired = isRequired;
});
}
return chain;
}
updateCanaryVersions() {
return (0, import_p_map.default)(this.updates, (node) => {
node.pkg.set("version", this.updatesVersions.get(node.name));
for (const [depName, resolved] of node.localDependencies) {
const depVersion = this.updatesVersions.get(depName) || this.packageGraph.get(depName).pkg.version;
node.pkg.updateLocalDependency(resolved, depVersion, this.savePrefix);
}
});
}
resolveLocalDependencyLinks() {
const updatesWithLocalLinks = this.updates.filter(
(node) => Array.from(node.localDependencies.values()).some((resolved) => resolved.type === "directory")
);
return (0, import_p_map.default)(updatesWithLocalLinks, (node) => {
for (const [depName, resolved] of node.localDependencies) {
const depVersion = this.updatesVersions.get(depName) || this.packageGraph.get(depName).pkg.version;
node.pkg.updateLocalDependency(resolved, depVersion, this.savePrefix);
}
});
}
resolveWorkspaceDependencyLinks() {
const updatesWithWorkspaceLinks = this.updates.filter(
(node) => Array.from(node.localDependencies.values()).some((resolved) => !!resolved.workspaceSpec)
);
return (0, import_p_map.default)(updatesWithWorkspaceLinks, (node) => {
for (const [depName, resolved] of node.localDependencies) {
if (resolved.workspaceSpec) {
let depVersion;
let savePrefix;
if (resolved.workspaceAlias) {
depVersion = this.updatesVersions.get(depName) || this.packageGraph.get(depName).pkg.version;
savePrefix = resolved.workspaceAlias === "*" ? "" : resolved.workspaceAlias;
} else {
const specMatch = resolved.workspaceSpec.match(/^workspace:([~^]?)(.*)/);
savePrefix = specMatch[1];
depVersion = specMatch[2];
}
node.pkg.updateLocalDependency(resolved, depVersion, savePrefix, { retainWorkspacePrefix: false });
}
}
});
}
annotateGitHead() {
try {
const gitHead = this.options.gitHead || getCurrentSHA(this.execOpts);
for (const pkg of this.packagesToPublish) {
pkg.set("gitHead", gitHead);
}
} catch (err) {
this.logger.silly("EGITHEAD", err.message);
this.logger.notice(
"FYI",
"Unable to set temporary gitHead property, it will be missing from registry metadata"
);
}
}
serializeChanges() {
return (0, import_p_map.default)(this.packagesToPublish, (pkg) => pkg.serialize());
}
resetChanges() {
const { cwd } = this.execOpts;
const gitOpts = {
granularPathspec: this.options.granularPathspec !== false
};
const dirtyManifests = [this.project.manifest].concat(this.packagesToPublish).map((pkg) => import_path.default.relative(cwd, pkg.manifestLocation));
return gitCheckout(dirtyManifests, gitOpts, this.execOpts).catch((err) => {
this.logger.silly("EGITCHECKOUT", err.message);
this.logger.notice("FYI", "Unable to reset working tree changes, this probably isn't a git repo.");
});
}
execScript(pkg, script) {
const scriptLocation = import_path.default.join(pkg.location, "scripts", script);
try {
require(scriptLocation);
} catch (ex) {
this.logger.silly("execScript", `No ${script} script found at ${scriptLocation}`);
}
return pkg;
}
removeTempLicensesOnError(error) {
return Promise.resolve().then(
() => removeTempLicenses(this.packagesToBeLicensed).catch((removeError) => {
this.logger.error(
"licenses",
"error removing temporary license files",
removeError.stack || removeError
);
})
).then(() => {
throw error;
});
}
requestOneTimePassword() {
if (this.otpCache.otp) {
return;
}
return Promise.resolve().then(() => (0, import_core.getOneTimePassword)("Enter OTP:")).then((otp) => {
this.otpCache.otp = otp;
});
}
topoMapPackages(mapper) {
return (0, import_core.runTopologically)(this.packagesToPublish, mapper, {
concurrency: this.concurrency,
rejectCycles: this.options.rejectCycles,
/**
* Previously `publish` had unique default behavior for graph creation vs other commands: it would only consider dependencies when finding
* edges by default (i.e. relationships between packages specified via devDependencies would be ignored). It was documented to be the case
* in order to try and reduce the chance of dependency cycles.
*
* We are removing this behavior altogether in v6 because we do not want to have different ways of constructing the graph,
* only different ways of utilizing it (e.g. --no-sort vs topological sort).
*
* Therefore until we remove graphType altogether in v6, we provide a way for users to opt into the old default behavior
* by setting the `graphType` option to `dependencies`.
*/
graphType: this.options.graphType === "dependencies" ? "dependencies" : "allDependencies"
});
}
packUpdated() {
const tracker = this.logger.newItem("npm pack");
tracker.addWork(this.packagesToPublish.length);
let chain = Promise.resolve();
chain = chain.then(() => createTempLicenses(this.project.licensePath, this.packagesToBeLicensed));
if (!this.hasRootedLeaf) {
chain = chain.then(() => this.runRootLifecycle("prepublish"));
chain = chain.then(() => this.runPackageLifecycle(this.project.manifest, "prepare"));
chain = chain.then(() => this.runPackageLifecycle(this.project.manifest, "prepublishOnly"));
chain = chain.then(() => this.runPackageLifecycle(this.project.manifest, "prepack"));
}
const opts = this.conf.snapshot;
const mapper = (0, import_p_pipe.default)(
...[
this.options.requireScripts && ((pkg) => this.execScript(pkg, "prepublish")),
(pkg) => (0, import_core.pulseTillDone)((0, import_core.packDirectory)(pkg, pkg.location, opts)).then((packed) => {
tracker.verbose("packed", import_path.default.relative(this.project.rootPath, pkg.contents));
tracker.completeWork(1);
pkg.packed = packed;
return pkg.refresh();
})
].filter(Boolean)
);
chain = chain.then(() => {
if (this.toposort) {
return this.topoMapPackages(mapper);
}
return (0, import_p_map.default)(this.packagesToPublish, mapper, { concurrency: this.concurrency });
});
chain = chain.then(() => removeTempLicenses(this.packagesToBeLicensed));
chain = chain.catch((error) => this.removeTempLicensesOnError(error));
if (!this.hasRootedLeaf) {
chain = chain.then(() => this.runPackageLifecycle(this.project.manifest, "postpack"));
}
return chain.finally(() => tracker.finish());
}
publishPacked() {
this.publishedPackages = [];
const tracker = this.logger.newItem("publish");
tracker.addWork(this.packagesToPublish.length);
let chain = Promise.resolve();
if (this.twoFactorAuthRequired) {
chain = chain.then(() => this.requestOneTimePassword());
}
const opts = Object.assign(this.conf.snapshot, {
// distTag defaults to "latest" OR whatever is in pkg.publishConfig.tag
// if we skip temp tags we should tag with the proper value immediately
tag: this.options.tempTag ? "lerna-temp" : this.conf.get("tag")
});
const mapper = (0, import_p_pipe.default)(
...[
(pkg) => {
const preDistTag = this.getPreDistTag(pkg);
const tag = !this.options.tempTag && preDistTag ? preDistTag : opts.tag;
const pkgOpts = Object.assign({}, opts, { tag });
return (0, import_core.pulseTillDone)((0, import_core.npmPublish)(pkg, pkg.packed.tarFilePath, pkgOpts, this.otpCache)).then(() => {
this.publishedPackages.push(pkg);
tracker.success("published", pkg.name, pkg.version);
tracker.completeWork(1);
(0, import_core.logPacked)(pkg.packed);
return pkg;
}).catch((err) => {
if (err.code === "EPUBLISHCONFLICT") {
tracker.warn("publish", `Package is already published: ${pkg.name}@${pkg.version}`);
tracker.completeWork(1);
return pkg;
}
this.logger.silly("", err);
this.logger.error(err.code, err.body && err.body.error || err.message);
err.name = "ValidationError";
process.exitCode = "errno" in err ? err.errno : 1;
throw err;
});
},
this.options.requireScripts && ((pkg) => this.execScript(pkg, "postpublish"))
].filter(Boolean)
);
chain = chain.then(() => {
if (this.toposort) {
return this.topoMapPackages(mapper);
}
return (0, import_p_map.default)(this.packagesToPublish, mapper, { concurrency: this.concurrency });
});
if (!this.hasRootedLeaf) {
chain = chain.then(() => this.runRootLifecycle("publish"));
chain = chain.then(() => this.runRootLifecycle("postpublish"));
}
return chain.finally(() => tracker.finish());
}
npmUpdateAsLatest() {
const tracker = this.logger.newItem("npmUpdateAsLatest");
tracker.addWork(this.packagesToPublish.length);
tracker.showProgress();
let chain = Promise.resolve();
const opts = this.conf.snapshot;
const getDistTag = (publishConfig) => {
if (opts.tag === "latest" && publishConfig && publishConfig.tag) {
return publishConfig.tag;
}
return opts.tag;
};
const mapper = (pkg) => {
const spec = `${pkg.name}@${pkg.version}`;
const preDistTag = this.getPreDistTag(pkg);
const distTag = preDistTag || getDistTag(pkg.get("publishConfig"));
return Promise.resolve().then(() => (0, import_core.pulseTillDone)(import_core.npmDistTag.remove(spec, "lerna-temp", opts, this.otpCache))).then(() => (0, import_core.pulseTillDone)(import_core.npmDistTag.add(spec, distTag, opts, this.otpCache))).then(() => {
tracker.success("dist-tag", "%s@%s => %j", pkg.name, pkg.version, distTag);
tracker.completeWork(1);
return pkg;
});
};
chain = chain.then(() => {
if (this.toposort) {
return this.topoMapPackages(mapper);
}
return (0, import_p_map.default)(this.packagesToPublish, mapper, { concurrency: this.concurrency });
});
return chain.finally(() => tracker.finish());
}
getDistTag() {
if (this.options.distTag) {
return this.options.distTag;
}
if (this.options.canary) {
return "canary";
}
}
getPreDistTag(pkg) {
if (!this.options.preDistTag) {
return;
}
const isPrerelease = (0, import_core.prereleaseIdFromVersion)(pkg.version);
if (isPrerelease) {
return this.options.preDistTag;
}
}
// filter out private packages, respecting the --include-private option
filterPrivatePkgUpdates(updates) {
const privatePackagesToInclude = new Set(this.options.includePrivate || []);
return updates.filter(
(node) => !node.pkg.private || privatePackagesToInclude.has("*") || privatePackagesToInclude.has(node.pkg.name)
);
}
}
module.exports.PublishCommand = PublishCommand;