import {injectable, inject} from "inversify"; import {CommandUtil} from "../interfaces/command-util"; import path = require('path'); import {IPostal} from "../interfaces/postal"; import {LogConsole} from "../interfaces/log-console"; import {ForceErrorImpl} from "./force-error-impl"; const blackHoleStream = new (require('black-hole-stream'))(); const fs = require('fs'); @injectable() export class CommandUtilImpl extends ForceErrorImpl implements CommandUtil { private _console: LogConsole = { log: this.stdoutLog.bind(this), info: this.stdoutLog.bind(this), warn: this.stdoutLog.bind(this), error: this.stderrLog.bind(this) }; private exitHandler(options, err: Error) { if (options.cleanup) { } if (err) { if (err && err.message) { this.stderrLog(err.message) } } if (options.exit) { process.exit(); } } private registerProcessManagementEvents() { process.stdin.resume(); process.on('exit', this.exitHandler.bind(this, {cleanup: true})); process.on('SIGINT', this.exitHandler.bind(this, {exit: true})); process.on('uncaughtException', this.exitHandler.bind(this, {exit: true})); } constructor(@inject('IPostal') private postal: IPostal) { super(); this.registerProcessManagementEvents(); const cacheStdoutWrite = process.stdout.write; const cacheStderrWrite = process.stderr.write; this.postal.subscribe({ channel: 'CommandUtil', topic: 'SuppressConsoleOutput', callback: (data) => { if (data.suppressConsoleOutput) { process.stdout.write = process.stderr.write = blackHoleStream.write.bind(blackHoleStream); } else { process.stdout.write = cacheStdoutWrite; process.stderr.write = cacheStderrWrite; } } }); this.postal.subscribe({ channel: 'CommandUtil', topic: 'ProgressBarStarted', callback: (data) => { let dataConsole: LogConsole = data.console; this._console.log = dataConsole.log; this._console.info = dataConsole.info; this._console.warn = dataConsole.warn; this._console.error = dataConsole.error; } }); } stderrWrite(msg: string) { process.stderr.write(msg); } stdoutWrite(msg: string) { process.stdout.write(msg); } private stderrLog(msg: string) { this.stderrWrite(`${msg}\n`); } private stdoutLog(msg: string) { this.stdoutWrite(`${msg}\n`); } returnErrorStringOrMessage(err: Error, message: string) { let errorMessage = this.logError(err, false); return errorMessage.length ? errorMessage : message; } error(msg: string) { this._console.error(msg); } log(msg: string) { this._console.log(msg); } logErrors(errs: Error[], writeErrorToConsole: boolean = true): string[] { let retVal: string[] = []; errs.forEach(err => { retVal.push(this.logError(err, writeErrorToConsole)); }); return retVal; } logError(err: Error, writeErrorToConsole: boolean = true): string { if (err) { if (writeErrorToConsole) { this._console.error(err.message); } return err.message; } return ''; } processExitIfError(err: Error) { if (err) { this.processExitWithError(err); } } processExitWithError(err: Error, nonErrorMessage: string = null) { this.processExit(!!err ? 1 : 0, !!err ? err.message : !!nonErrorMessage ? nonErrorMessage : ''); } processExit(exitCode: number = 0, msg: string = null) { this._console.log(!!msg ? msg : ''); process.exit(exitCode); } callbackIfError(cb: (err: Error, anything: any, anything2?: any) => void, err: Error = null, result: any = null): boolean { cb = this.checkCallback(cb); err && cb(err, result); return !!err; } logAndCallback(msg: string, cb: (err: Error, anything: any, anything2?: any) => void, err: Error = null, result: any = null): boolean { this._console.log(err ? err.message : msg); cb = this.checkCallback(cb); cb(err, result); return !!err; } getConfigFilePath(filename: string, extension: string = '.json') { let regex = new RegExp('(.*)\\' + extension + '$', 'i'); let cwd = process.cwd(); filename = regex.test(filename) ? filename.replace(regex, '$1' + extension) : filename + extension; return path.resolve(cwd, filename); } }