From e0394f6383bc1c7f01bf6349be103209c98fdc11 Mon Sep 17 00:00:00 2001 From: Jeff Dickey <216188+jdxcode@users.noreply.github.com> Date: Tue, 16 Jan 2018 09:36:12 -0800 Subject: [PATCH] fix: scopes --- src/errors.ts | 10 +++++----- src/index.ts | 48 ++++++++++++++++++++++++------------------------ src/logger.ts | 15 +++++++-------- src/message.ts | 7 +++++++ src/output.ts | 12 ++++++------ 5 files changed, 49 insertions(+), 43 deletions(-) diff --git a/src/errors.ts b/src/errors.ts index f7c67a6f..f357ccf4 100644 --- a/src/errors.ts +++ b/src/errors.ts @@ -46,12 +46,12 @@ function wrap(msg: string): string { })(msg) } -export default function (cli: CLI): Rx.Observable { +export default function (o: Rx.Subject): Rx.Observable { function renderError(message: ErrorMessage): string { let bang = chalk.red(arrow) if (message.severity === 'fatal') bang = chalk.bgRed.bold.white(' FATAL ') if (message.severity === 'warn') bang = chalk.yellow(arrow) - const msg = cli.scope ? `${cli.scope}: ${getErrorMessage(message.error)}` : getErrorMessage(message.error) + const msg = message.scope ? `${message.scope}: ${getErrorMessage(message.error)}` : getErrorMessage(message.error) return bangify(wrap(msg), bang) } @@ -90,11 +90,11 @@ export default function (cli: CLI): Rx.Observable { handleUnhandleds() - return cli - .takeUntil(cli.filter(m => m.type === 'done')) + return o + .takeUntil(o.filter(m => m.type === 'done')) .filter((m): m is ErrorMessage => m.type === 'error') .do(m => { - cli.next({type: 'logger', severity: m.severity, message: getErrorMessage(m.error)}) + o.next({type: 'logger', scope: m.scope, severity: m.severity, message: getErrorMessage(m.error)}) process.stderr.write(renderError(m) + '\n') }) } diff --git a/src/index.ts b/src/index.ts index ee7ab6e1..7adadb41 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,20 +13,19 @@ export interface IErrorOptions { severity?: 'fatal' | 'error' | 'warn' } -export class CLI extends Rx.Subject { - children: Rx.Observable - subscription: Rx.Subscription +let subject: Rx.Subject = new Rx.Subject() +let children: Rx.Observable + +config.subscribe(subject) + +export class CLI { config: Config = config - constructor(public scope?: string) { - super() - this.reset() - this.config.subscribe(this) - } + constructor(public scope?: string) {} error(input: Error | string, options: IErrorOptions = {}) { const error = input instanceof Error ? input : new Error(input) - this.next({type: 'error', severity: options.severity || 'error', error} as ErrorMessage) + subject.next({type: 'error', scope: this.scope, severity: options.severity || 'error', error} as ErrorMessage) const code = getExitCode(options) if (code !== false) this.exit(code, error) } @@ -34,28 +33,19 @@ export class CLI extends Rx.Subject { fatal(input: Error | string, options: IErrorOptions = {}) { this.error(input, {...options, severity: 'fatal'}) } warn(input: Error | string) { this.error(input, {severity: 'warn', exit: false}) } - info(...input: any[]) { this.next({type: 'output', severity: 'info', input}) } log(...input: any[]) { this.info(...input) } - debug(...input: any[]) { this.next({type: 'output', severity: 'debug', input}) } - trace(...input: any[]) { this.next({type: 'output', severity: 'trace', input}) } + info(...input: any[]) { subject.next({type: 'output', scope: this.scope, severity: 'info', input}) } + debug(...input: any[]) { subject.next({type: 'output', scope: this.scope, severity: 'debug', input}) } + trace(...input: any[]) { subject.next({type: 'output', scope: this.scope, severity: 'trace', input}) } exit(code = 1, error?: Error) { throw new ExitError(code, error) } async done() { await new Promise((resolve, reject) => { - this.children.subscribe({error: reject, complete: resolve}) - this.next({type: 'done'}) + children.subscribe({error: reject, complete: resolve}) + subject.next({type: 'done'}) }) - this.reset() - } - - private reset() { - this.children = Rx.Observable.forkJoin( - errors(this), - output(this), - logger(this), - ).share() - this.children.subscribe() + reset() } } @@ -66,4 +56,14 @@ function getExitCode(options: IErrorOptions): false | number { return exit } +function reset() { + children = Rx.Observable.forkJoin( + errors(subject), + output(subject), + logger(subject), + ).share() + children.subscribe() +} +reset() + export default new CLI() diff --git a/src/logger.ts b/src/logger.ts index 736ce2ce..85c0acbe 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -3,13 +3,12 @@ import * as _ from 'lodash' import * as path from 'path' import Rx = require('rxjs/Rx') -import {CLI} from '.' import {config} from './config' import {ConfigMessage, LoggerMessage, Message} from './message' const timestamp = () => new Date().toISOString() -export default function setup(cli: CLI): Rx.Observable { +export default function setup(o: Rx.Subject): Rx.Observable { function log(file: string) { let stream: Promise | undefined function getStream() { @@ -37,8 +36,8 @@ export default function setup(cli: CLI): Rx.Observable { if (!file) return Rx.Observable.empty() - const messages$ = cli - .takeUntil(cli.filter(m => m.type === 'done')) + const messages$ = o + .takeUntil(o.filter(m => m.type === 'done')) .filter((m): m is LoggerMessage => m.type === 'logger') .filter(m => { switch (config.logLevel) { @@ -50,7 +49,7 @@ export default function setup(cli: CLI): Rx.Observable { default: return false } }) - .map(m => _([timestamp(), m.severity.toUpperCase(), cli.scope, m.message]).compact().join(' ')) + .map(m => _([timestamp(), m.severity.toUpperCase(), m.scope, m.message]).compact().join(' ')) return messages$ .bufferWhen(() => messages$.delay(10)) .filter(lines => lines.length > 0) @@ -63,9 +62,9 @@ export default function setup(cli: CLI): Rx.Observable { .finally(close) } - return cli - .takeUntil(cli.filter(m => m.type === 'done')) - .startWith({type: 'config', prop: 'errlog', value: cli.config.errlog}) + return o + .takeUntil(o.filter(m => m.type === 'done')) + .startWith({type: 'config', prop: 'errlog', value: config.errlog}) .filter((m): m is ConfigMessage => m.type === 'config' && m.prop === 'errlog') .switchMap(m => log(m.value)) } diff --git a/src/message.ts b/src/message.ts index cb999bb4..f12c6038 100644 --- a/src/message.ts +++ b/src/message.ts @@ -8,34 +8,41 @@ export interface ConfigMessage { export type OutputMessage = { type: 'output' + scope: string | undefined severity: 'trace' input: any[] } | { type: 'output' + scope: string | undefined severity: 'debug' input: any[] } | { type: 'output' + scope: string | undefined severity: 'info' input: any[] } export type ErrorMessage = { type: 'error' + scope: string | undefined severity: 'warn' error: Error } | { type: 'error' + scope: string | undefined severity: 'error' error: Error } | { type: 'error' + scope: string | undefined severity: 'fatal' error: Error } export interface LoggerMessage { type: 'logger' + scope: string | undefined message: string severity: Levels } diff --git a/src/output.ts b/src/output.ts index 380175aa..7d22db6d 100644 --- a/src/output.ts +++ b/src/output.ts @@ -1,20 +1,20 @@ import Rx = require('rxjs/Rx') import {inspect} from 'util' -import {CLI} from '.' +import {config} from './config' import {Message, OutputMessage} from './message' -export default function (cli: CLI): Rx.Observable { +export default function (o: Rx.Observable): Rx.Observable { function content(m: OutputMessage): string { const msg = m.input.map(a => typeof a === 'string' ? a : inspect(a)).join(' ') - return (cli.scope ? `${cli.scope}: ${msg}` : msg) + '\n' + return (m.scope ? `${m.scope}: ${msg}` : msg) + '\n' } - return cli - .takeUntil(cli.filter(m => m.type === 'done')) + return o + .takeUntil(o.filter(m => m.type === 'done')) .filter((m): m is OutputMessage => m.type === 'output') .filter(m => { - switch (cli.config.outputLevel) { + switch (config.outputLevel) { case 'info': return m.severity === 'info' case 'debug': return ['info', 'debug'].includes(m.severity) case 'trace': return ['info', 'debug', 'trace'].includes(m.severity)