You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
232 lines
7.3 KiB
JavaScript
232 lines
7.3 KiB
JavaScript
"use strict";
|
|
|
|
const chalk = require("chalk");
|
|
const moment = require("moment");
|
|
const path = require("path");
|
|
|
|
const traverseTransformHistory = require("../util/traverse-transform-history");
|
|
const drawTransformTree = require("./draw-transform-tree");
|
|
const errors = require("../errors/errors");
|
|
|
|
function formatDate(date) {
|
|
return chalk.dim(`[${moment(date).format("LTS")}]`);
|
|
}
|
|
|
|
function formatSuccessfulSourcePath(sourcePath) {
|
|
return chalk.bgGreen.black(` ◆ ${sourcePath} `);
|
|
}
|
|
|
|
function formatFailedSourcePath(sourcePath) {
|
|
return chalk.bgRed.white(` ◆ ${sourcePath} `);
|
|
}
|
|
|
|
function formatDuration(ms) {
|
|
return chalk.bold(`${ms}ms`);
|
|
}
|
|
|
|
function formatTransformDisplayName(displayName) {
|
|
return displayName;
|
|
}
|
|
|
|
function formatTransformPath(relativePath) {
|
|
return chalk.dim(`[${relativePath}]`);
|
|
}
|
|
|
|
function formatSinkPath(sinkPath) {
|
|
return chalk.bold(sinkPath);
|
|
}
|
|
|
|
function formatSuccessfulSourceStep(metadata) {
|
|
return `${formatSuccessfulSourcePath(metadata.relativePath)} ${formatDate(metadata.sourcedDate)}`;
|
|
}
|
|
|
|
function formatSuccessfulTransformStep(metadata) {
|
|
return `${formatDuration(metadata.stepDuration)} ${formatTransformDisplayName(metadata.step.displayName)} ${formatTransformPath(metadata.relativePath)}`;
|
|
}
|
|
|
|
function formatSuccessfulSinkStep(metadata) {
|
|
return formatSinkPath(metadata.targetPath);
|
|
}
|
|
|
|
function formatMissingTransformStep(step) {
|
|
return chalk.dim(`${chalk.bold("not run:")} ${step.displayName}`);
|
|
}
|
|
|
|
function formatMissingSinkStep() {
|
|
return chalk.dim("(no output file produced)");
|
|
}
|
|
|
|
function formatFailedSourceStep(source) {
|
|
return `${formatFailedSourcePath(source.relativePath)} ${formatDate(source.sourcedDate)}`;
|
|
}
|
|
|
|
function formatFailedTransformStepName(step, duration) {
|
|
return chalk.red(`${formatDuration(duration)} ${step.displayName}`);
|
|
}
|
|
|
|
function formatErrorDetail(name, description) {
|
|
return chalk.red(`${chalk.bold(`${name}:`)} ${description}`);
|
|
}
|
|
|
|
function formatFailedTransformStep(step, file, error, pipeline, duration) {
|
|
if (error instanceof errors.SyntaxError) {
|
|
let prefix = formatErrorPrefix("Syntax Error");
|
|
let message = formatErrorMessage(error.error);
|
|
|
|
return [
|
|
formatFailedTransformStepName(step, duration),
|
|
`${prefix}${message}`,
|
|
formatErrorDetail("File", `${path.resolve(pipeline.basePath, file.metadata.relativePath)} ${file.metadata.isVirtual ? chalk.dim("(virtual)") : ""}`),
|
|
formatErrorDetail("Location", `Line ${error.line}, column ${error.column}`),
|
|
(file.metadata.isVirtual)
|
|
? chalk.bgRed.white.bold("This file is a virtual file. That means that the syntax error probably originates from another earlier transform, and there may be a bug in that transform.")
|
|
: ""
|
|
].join("\n");
|
|
} else {
|
|
let prefix = formatErrorPrefix("Error");
|
|
let message = formatErrorMessage(`An unexpected error occurred in the transform`);
|
|
|
|
/* FIXME: */
|
|
// if (error instanceof Error) {
|
|
// console.log(chalk.red(error.stack));
|
|
// } else {
|
|
// console.log(chalk.red(util.inspect(error, {colors: true, depth: null})));
|
|
// console.log(chalk.bgRed.white.bold("This error wasn't actually an error object - that's a bug in the transform! Here's a less precise stacktrace:"));
|
|
// console.log(chalk.red((new Error()).stack));
|
|
// }
|
|
|
|
return [
|
|
formatFailedTransformStepName(step),
|
|
`${prefix}${message}`,
|
|
error.stack
|
|
].join("\n");
|
|
}
|
|
}
|
|
|
|
|
|
// console.log(chalk.bgRed.white.bold(`A syntax error occurred in the transform '${transform.displayName}':`));
|
|
// console.log(chalk.red(` ${chalk.bold("Error:")} ${error.error}`));
|
|
// console.log(chalk.red(` ${chalk.bold("File:")} ${path.resolve(basePath, file.relativePath)} ${file.isVirtual ? chalk.dim("(virtual)") : ""}`));
|
|
// console.log(chalk.red(` ${chalk.bold("Location:")} Line ${error.line}, column ${error.column}`));
|
|
|
|
function formatFailedSinkStep(step, error) {
|
|
let prefix = formatErrorPrefix("Error");
|
|
let message = formatErrorMessage(`Failed to write file to destination`);
|
|
|
|
return [
|
|
formatFailedTransformStepName(step),
|
|
`${prefix}${message}`,
|
|
error.stack
|
|
].join("\n");
|
|
}
|
|
|
|
function formatErrorPrefix(text) {
|
|
return chalk.bgRed.white(` ${text} `);
|
|
}
|
|
|
|
function formatErrorMessage(message) {
|
|
return chalk.bgWhite.black(` ${message} `);
|
|
}
|
|
|
|
function formatCompletedItem(metadata) {
|
|
let history = traverseTransformHistory(metadata);
|
|
|
|
let sourceStep = formatSuccessfulSourceStep(history[0]);
|
|
|
|
let transformSteps = history.slice(1, -1).map((metadata) => {
|
|
return formatSuccessfulTransformStep(metadata);
|
|
});
|
|
|
|
let sinkStep = formatSuccessfulSinkStep(history[history.length - 1]);
|
|
|
|
return drawTransformTree([sourceStep].concat(transformSteps).concat([sinkStep]));
|
|
}
|
|
|
|
function formatFailedItem(pipeline, {error, step, file, duration}) {
|
|
let history = traverseTransformHistory(file.metadata);
|
|
|
|
let sourceStep = formatFailedSourceStep(history[0]);
|
|
|
|
let transformSteps, sinkStep;
|
|
|
|
if (step.__buildStep === "sink") {
|
|
transformSteps = history.slice(1, -1).map((metadata) => {
|
|
return formatSuccessfulTransformStep(metadata);
|
|
});
|
|
|
|
sinkStep = formatFailedSinkStep(history[history.length - 1], error);
|
|
} else {
|
|
let failedIndex = pipeline.steps.indexOf(step);
|
|
|
|
let successfulTransformSteps = history.slice(1, failedIndex).map((metadata) => {
|
|
return formatSuccessfulTransformStep(metadata);
|
|
});
|
|
|
|
let failedTransformStep = formatFailedTransformStep(pipeline.steps[failedIndex], file, error, pipeline, duration);
|
|
|
|
let missingTransformSteps = pipeline.steps.slice(failedIndex + 1, -1).map((step) => {
|
|
return formatMissingTransformStep(step);
|
|
});
|
|
|
|
transformSteps = successfulTransformSteps.concat([failedTransformStep]).concat(missingTransformSteps);
|
|
|
|
sinkStep = formatMissingSinkStep();
|
|
}
|
|
|
|
return drawTransformTree([sourceStep].concat(transformSteps).concat([sinkStep]));
|
|
}
|
|
|
|
module.exports = function runTask(task) {
|
|
let pipeline = task();
|
|
|
|
pipeline.on("error", (failure) => {
|
|
console.log(formatFailedItem(pipeline, failure));
|
|
|
|
if (failure.isFatal) {
|
|
console.log(chalk.bgRed.white.bold("This error is fatal, and the build process will now exit."));
|
|
/* FIXME: Do this more cleanly, with teardown and all. */
|
|
process.exit(1);
|
|
}
|
|
|
|
console.log("");
|
|
});
|
|
|
|
pipeline.on("done", ({metadata, acknowledged}) => {
|
|
console.log(formatCompletedItem(metadata));
|
|
|
|
if (!acknowledged) {
|
|
console.log(chalk.gray("(NOTE: The destination sink doesn't support acknowledgments, so the file may not actually be stored yet.)"));
|
|
}
|
|
|
|
console.log("");
|
|
});
|
|
|
|
pipeline.initialize();
|
|
};
|
|
|
|
|
|
|
|
// function reportError(transform, file, error, isFatal) {
|
|
// if (error instanceof errors.SyntaxError) {
|
|
// console.log(chalk.bgRed.white.bold(`A syntax error occurred in the transform '${transform.displayName}':`));
|
|
// console.log(chalk.red(` ${chalk.bold("Error:")} ${error.error}`));
|
|
// console.log(chalk.red(` ${chalk.bold("File:")} ${path.resolve(basePath, file.relativePath)} ${file.isVirtual ? chalk.dim("(virtual)") : ""}`));
|
|
// console.log(chalk.red(` ${chalk.bold("Location:")} Line ${error.line}, column ${error.column}`));
|
|
//
|
|
//
|
|
// } else {
|
|
// console.log(chalk.bgRed.white.bold(`An error occurred in the transform '${transform.displayName}':`));
|
|
//
|
|
//
|
|
// }
|
|
//
|
|
// }
|
|
|
|
/* FIXME: Move this stuff out, use the acknowledgment event instead for detecting which tasks have finished; also don't forget to add a workaround for sinks that cannot acknowledge */
|
|
|
|
|
|
|
|
// console.log("===============");
|
|
// console.log(metadata);
|
|
// console.log(`Wrote ${targetFilePath}`);
|