in packages/sqrl-cli/src/cli/CliPrettyOutput.ts [45:200]
private writeSummary() {
const count = this.blocked + this.allowed;
const perMin =
(count - this.lastCount) / ((Date.now() - this.lastSummary) / 60000);
let speed;
if (perMin < 1000) {
speed = `${perMin.toFixed(1)}/min`;
} else {
speed = `${(perMin / 60).toFixed(1)}/sec`;
}
if (this.state !== State.summary) {
this.open(State.summary);
}
this.line(
moment().format("YYYY-MM-DD HH:mm:ss ") +
chalk.red(`${this.blocked} actions blocked`) +
", " +
chalk.green(`${this.allowed} actions allowed`) +
chalk.gray(` (${speed})`)
);
this.lastCount = count;
this.lastSummary = Date.now();
}
private open(state: State = State.unknown) {
if (this.state !== State.none) {
// Leave a blank line between each action
this.stdout.write("\n");
}
this.state = state;
}
private line(format: string, ...param: any[]) {
this.stdout.write(util.format(format, ...param) + "\n");
}
private errorText(err: Error) {
if (err instanceof SqrlCompileError) {
return err.toSqrlErrorOutput({
codedError: false,
source: true,
stacktrace: false,
});
} else if (err instanceof CliError) {
let output = chalk.redBright("Error: ") + err.message;
if (err.suggestion) {
output += "\n" + " ".repeat("Error: ".length) + err.suggestion;
}
return output;
} else {
return err.stack;
}
}
close() {
if (this.summaryInterval) {
this.writeSummary();
clearInterval(this.summaryInterval);
this.summaryInterval = null;
}
}
error(err: Error) {
this.line(this.errorText(err));
}
sourceRecompiling() {
this.open(State.recompiling);
this.line(chalk.yellow("Source changed, recompiling..."));
}
sourceUpdated() {
if (this.state === State.recompiling) {
this.state = State.unknown;
} else {
this.open();
}
this.line(chalk.green("Source updated."));
}
sourceRecompileError(err: Error) {
if (this.state === State.recompiling) {
this.state = State.unknown;
} else {
this.open();
}
this.line(chalk.redBright("New source failed to compile:"));
this.line(prefixLines(this.errorText(err), chalk.red(">") + " "));
}
startStream() {
this.summaryInterval = setInterval(() => this.writeSummary(), 1000);
this.summaryInterval.unref();
}
action(
manipulator: CliManipulator,
execution: Execution,
loggedFeatures: FeatureMap
) {
if (manipulator.wasBlocked()) {
this.blocked += 1;
} else {
this.allowed += 1;
}
if (this.options.onlyBlocked && !manipulator.wasBlocked()) {
return;
}
this.open();
const timestamp = moment(execution.getClockMs());
const time = " " + chalk.gray(timestamp.format("YYYY-MM-DD HH:mm")) + " ";
if (manipulator.wasBlocked()) {
this.line(
chalk.red.bold(CROSS) + time + chalk.red("action was blocked.")
);
manipulator.blockedRules.forEach((details) => {
this.line(
chalk.red(
`${DOWNWARDS_ARROW} [${details.name}]` +
(details.reason ? ": " + details.reason : "")
)
);
});
} else {
this.line(
chalk.green(CHECKMARK) + time + chalk.green("action was allowed.")
);
}
Object.assign(loggedFeatures, manipulator.loggedFeatures);
for (const key of Object.keys(loggedFeatures).sort()) {
const value = loggedFeatures[key];
if (value instanceof SqrlObject) {
const json = JSON.stringify(value.getBasicValue());
const rendered = value.render();
if (rendered.text && rendered.text.trimRight() === json) {
this.line("%s=%s", key, json);
} else {
this.line("%s=%s %s", key, json, spanToShell(rendered).trimRight());
}
} else {
this.line("%s=%s", key, JSON.stringify(value));
}
}
manipulator.logged.forEach((message) => this.line(message));
}
}