UNPKG

@lerna/publish

Version:

Publish packages in the current project

705 lines (704 loc) 29.3 kB
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;