@ofzza/adventofcode
Version:
Task runner for AdventOfCode.com tasks
174 lines • 6.99 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TaskResult = exports.Task = void 0;
const tslib_1 = require("tslib");
// Dependencies
const child_process_1 = require("child_process");
const config_1 = require("../config");
/**
* Implements task management and running functinoality
*/
class Task {
constructor(task, custom = {}) {
// Set properties
this.name = task.name;
this.type = task.type;
this.command = task.command;
this.args = task.args;
this.value = task.value;
this.runs = task.runs;
this.custom = custom;
}
/**
* Gets list of all runnable tasks
* @param tasks Array of tasks to run
* @param name Start of name of task(s) to run
* @param type Type of tasks to run
* @returns List of all runnable tasks
*/
static get({ tasks = [], name = '', type = '' } = {}) {
return (tasks.length ? tasks : Object.keys(config_1.Configuration.config.tasks).map(i => parseInt(i) + 1))
.map(i => (config_1.Configuration.config.tasks || []).map(task => (task ? new Task(task) : undefined))[i - 1])
.filter(task => !!task)
.filter(task => !name || task.name.startsWith(name))
.filter(task => !type || task.type === type);
}
/**
* Runs requested tasks
* @param argv Startup arguments
* @param name Start of name of task(s) to run
* @param type Type of tasks to run
* @param stdoutCallback: (text: string) => void
*/
static run(argv, stdoutCallback) {
return (0, tslib_1.__asyncGenerator)(this, arguments, function* run_1() {
// Get filters
const tasks = argv.task instanceof Array ? argv.task.map(task => parseInt(task)) : argv.task ? [parseInt(argv.task)] : [];
const type = argv.type;
const name = argv.name;
// Filter tasks to execute
for (const task of Task.get({ tasks, type, name })) {
// Compose and run multiple runs of the task
let taskRuns = !task.runs ? [task] : task.runs.map(run => new Task(Object.assign(Object.assign({}, task), run), run));
for (const taskRun of taskRuns) {
// Process dynamic task arguments
taskRun.args = taskRun.args.map(arg => {
return arg.replace(/\{\{(.*?)\}\}/g, match => {
// Parse dynamic argument
const expr = match.substr(2, match.length - 4);
const parsed = expr.split('??');
const condition = parsed.length > 1 ? parsed[0] : undefined;
const syntax = parsed.length > 1 ? parsed[1] : parsed[0];
// Check if argument enabled
if (!condition || argv[condition] !== undefined || taskRun.custom[condition] !== undefined || taskRun[condition] !== undefined) {
// Replace argument with processed version
return syntax
.split(' ')
.map(s => (!s.startsWith(':') ? s : argv[s.substr(1)] || taskRun.custom[s.substr(1)] || taskRun[s.substr(1)]))
.join(' ');
}
});
});
// Yield task
yield yield (0, tslib_1.__await)(yield (0, tslib_1.__await)(taskRun));
// Execute task and yield result
yield yield (0, tslib_1.__await)(yield (0, tslib_1.__await)(taskRun.run(stdoutCallback)));
}
}
});
}
/**
* Gets high resolution time in [ms]
* @returns High resolution time in [ms]
*/
getHRTime() {
const time = process.hrtime();
return time[0] * 1000 + time[1] / 1e6;
}
/**
* Execute task
* @returns Task execution result
* @param stdoutCallback Callback function called on every stdout event
*/
async run(stdoutCallback) {
// Run task and time task execution
const time = this.getHRTime();
let timeSpawned = time;
let timeStd = time;
try {
// Run command async and stream stdout and stderr
const out = await new Promise(resolve => {
try {
let out = '';
let err = '';
const proc = (0, child_process_1.spawn)(
// Command
this.command,
// Command arguments
this.args,
// Process options
{ cwd: config_1.Configuration.cwd });
proc.on('spawn', () => {
timeSpawned = this.getHRTime();
});
proc.stdout.on('data', (data) => {
out += data.toString();
stdoutCallback(data.toString());
timeStd = this.getHRTime();
});
proc.stderr.on('data', (data) => {
err += data.toString();
stdoutCallback(data.toString());
timeStd = this.getHRTime();
});
proc.on('exit', () => {
resolve(out || new Error(err));
});
}
catch (err) {
resolve(err);
}
});
// Return execution result
const result = out instanceof Error
? out
: out
.replace(/\[.*?m/g, '')
.trim()
.split('\n')
.slice(-1)[0];
return new TaskResult(this, timeStd - timeSpawned, result, out instanceof Error ? out.message : out);
}
catch (err) {
// Return execution result
return new TaskResult(this, timeStd - timeSpawned, err);
}
}
}
exports.Task = Task;
// TODO: expose isError and isValid getters
/**
* Contains results from an executed task
*/
class TaskResult {
constructor(task, time, value, output) {
this.task = task;
this.time = time;
this.value = value;
this.output = output;
}
/**
* If error was thrown while executing the task command
*/
get isError() {
return this.value instanceof Error;
}
/**
* If returned value matches expected value
*/
get isValid() {
return !(this.value instanceof Error) ? (this.task.value !== undefined ? this.task.value.trim() === this.value.trim() : undefined) : false;
}
}
exports.TaskResult = TaskResult;
//# sourceMappingURL=index.js.map