lerna
Version:
Lerna is a fast, modern build system for managing and publishing multiple JavaScript/TypeScript packages from the same repository
154 lines (151 loc) • 4.37 kB
JavaScript
import {
Command,
Profiler,
ValidationError,
filterProjects,
getPackage,
runProjectsTopologically,
spawn,
spawnStreaming
} from "./chunk-WC2B4V4E.js";
// libs/commands/exec/src/index.ts
import pMap from "p-map";
function factory(argv) {
return new ExecCommand(argv);
}
var ExecCommand = class extends Command {
command;
args;
bail;
prefix;
env;
filteredProjects = [];
count;
packagePlural;
joinedCommand = "";
get requiresGit() {
return false;
}
async initialize() {
const dashedArgs = this.options["--"] || [];
this.command = this.options.cmd || dashedArgs.shift();
this.args = (this.options.args || []).concat(dashedArgs);
if (!this.command) {
throw new ValidationError("ENOCOMMAND", "A command to execute is required");
}
this.bail = this.options.bail !== false;
this.prefix = this.options.prefix !== false;
this.env = Object.assign({}, process.env);
this.filteredProjects = filterProjects(this.projectGraph, this.execOpts, this.options);
this.count = this.filteredProjects.length;
this.packagePlural = this.count === 1 ? "package" : "packages";
this.joinedCommand = [this.command].concat(this.args).join(" ");
}
async execute() {
this.logger.info(
"",
"Executing command in %d %s: %j",
this.count,
this.packagePlural,
this.joinedCommand
);
let runCommand;
if (this.options.parallel) {
runCommand = () => this.runCommandInPackagesParallel();
} else if (this.toposort) {
runCommand = () => this.runCommandInPackagesTopological();
} else {
runCommand = () => this.runCommandInPackagesLexical();
}
if (this.bail) {
try {
await runCommand();
} catch (err) {
process.exitCode = err.exitCode;
throw err;
}
} else {
const results = await runCommand();
if (results.some((result) => result.failed)) {
const codes = results.filter((result) => result.failed).map((result) => result.exitCode);
const exitCode = Math.max(...codes, 1);
this.logger.error("", "Received non-zero exit code %d during execution", exitCode);
process.exitCode = exitCode;
}
}
this.logger.success(
"exec",
"Executed command in %d %s: %j",
this.count,
this.packagePlural,
this.joinedCommand
);
}
getOpts(pkg) {
return {
cwd: pkg.location,
shell: true,
extendEnv: false,
env: Object.assign({}, this.env, {
LERNA_PACKAGE_NAME: pkg.name,
LERNA_ROOT_PATH: this.project.rootPath
}),
reject: this.bail,
pkg
};
}
getRunner() {
return this.options.stream ? (pkg) => this.runCommandInPackageStreaming(pkg) : (pkg) => this.runCommandInPackageCapturing(pkg);
}
getShellCommand() {
return [this.joinedCommand, []];
}
runCommandInPackagesTopological() {
let profiler;
let runner;
if (this.options.profile) {
profiler = new Profiler({
concurrency: this.concurrency,
log: this.logger,
outputDirectory: this.options.profileLocation || this.project.rootPath
});
const callback = this.getRunner();
runner = (pkg) => profiler.run(() => callback(pkg), pkg.name);
} else {
runner = this.getRunner();
}
let chain = runProjectsTopologically(
this.filteredProjects,
this.projectGraph,
(p) => runner(getPackage(p)),
{
concurrency: this.concurrency,
rejectCycles: this.options.rejectCycles
}
);
if (profiler) {
chain = chain.then((results) => profiler.output().then(() => results));
}
return chain;
}
runCommandInPackagesParallel() {
return pMap(this.filteredProjects, (p) => this.runCommandInPackageStreaming(getPackage(p)));
}
runCommandInPackagesLexical() {
return pMap(this.filteredProjects, (p) => this.getRunner()(getPackage(p)), {
concurrency: this.concurrency
});
}
runCommandInPackageStreaming(pkg) {
const [command, args] = this.getShellCommand();
return spawnStreaming(command, args, this.getOpts(pkg), this.prefix && pkg.name);
}
runCommandInPackageCapturing(pkg) {
const [command, args] = this.getShellCommand();
return spawn(command, args, this.getOpts(pkg));
}
};
export {
factory,
ExecCommand
};