const { EOL } = require('os'); const chalk = require('chalk'); const { isObject, last, filter, isString, lowerCase, upperFirst, isArray } = require('lodash'); class Logger { constructor({ isCI = true, isVerbose = false, verbosityLevel = 0, isDryRun = false } = {}) { this.isCI = isCI; this.isVerbose = isVerbose; this.verbosityLevel = verbosityLevel; this.isDryRun = isDryRun; } shouldLog(isExternal) { return this.verbosityLevel === 2 || (this.isVerbose && isExternal); } log(...args) { console.log(...args); // eslint-disable-line no-console } error(...args) { console.error(chalk.red('ERROR'), ...args); // eslint-disable-line no-console } info(...args) { this.log(chalk.grey(...args)); } warn(...args) { this.log(chalk.yellow('WARNING'), ...args); } verbose(...args) { const { isExternal } = isObject(last(args)) ? last(args) : {}; if (this.shouldLog(isExternal)) { this.log(...filter(args, isString)); } } exec(...args) { const { isDryRun: isExecutedInDryRun, isExternal, isCached } = isObject(last(args)) ? last(args) : {}; if (this.shouldLog(isExternal) || this.isDryRun) { const prefix = isExecutedInDryRun == null ? '$' : '!'; const command = args.map(cmd => (isString(cmd) ? cmd : isArray(cmd) ? cmd.join(' ') : '')).join(' '); const message = [prefix, command, isCached ? '[cached]' : ''].join(' ').trim(); this.log(message); } } obtrusive(...args) { if (!this.isCI) this.log(); this.log(...args); if (!this.isCI) this.log(); } preview({ title, text }) { if (text) { const header = chalk.bold(upperFirst(title)); const body = text.replace(new RegExp(EOL + EOL, 'g'), EOL); this.obtrusive(`${header}:${EOL}${body}`); } else { this.obtrusive(`Empty ${lowerCase(title)}`); } } } module.exports = Logger;