hereby
Version:
A simple task runner
69 lines • 2.21 kB
JavaScript
import pc from "picocolors";
export class Runner {
constructor(_d) {
this._d = _d;
this._addedTasks = new Map();
this._errored = false;
this._startTimes = new Map();
}
async runTasks(...tasks) {
// Using allSettled here so that we don't immediately exit; it could be
// the case that a task has code that needs to run before, e.g. a
// cleanup function in a "finally" or something.
const results = await Promise.allSettled(tasks.map((task) => {
const cached = this._addedTasks.get(task);
if (cached) {
return cached;
}
const promise = this._runTask(task);
this._addedTasks.set(task, promise);
return promise;
}));
for (const result of results) {
if (result.status === "rejected") {
throw result.reason;
}
}
}
async _runTask(task) {
const { dependencies, run } = task.options;
if (dependencies) {
await this.runTasks(...dependencies);
}
if (!run) {
return;
}
try {
this.onTaskStart(task);
await run();
this.onTaskFinish(task);
}
catch (e) {
this.onTaskError(task, e);
throw e;
}
}
onTaskStart(task) {
this._startTimes.set(task, Date.now());
if (this._errored) {
return; // Skip logging.
}
this._d.log(`Starting ${pc.blue(task.options.name)}`);
}
onTaskFinish(task) {
if (this._errored) {
return; // Skip logging.
}
const took = Date.now() - this._startTimes.get(task);
this._d.log(`Finished ${pc.green(task.options.name)} in ${this._d.prettyMilliseconds(took)}`);
}
onTaskError(task, e) {
if (this._errored) {
return; // Skip logging.
}
this._errored = true;
const took = Date.now() - this._startTimes.get(task);
this._d.error(`Error in ${pc.red(task.options.name)} in ${this._d.prettyMilliseconds(took)}\n${e}`);
}
}
//# sourceMappingURL=runner.js.map