Skip to content
This repository has been archived by the owner on Feb 1, 2022. It is now read-only.

Commit

Permalink
fix: scopes
Browse files Browse the repository at this point in the history
  • Loading branch information
jdx committed Jan 16, 2018
1 parent 75ab511 commit e0394f6
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 43 deletions.
10 changes: 5 additions & 5 deletions src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ function wrap(msg: string): string {
})(msg)
}

export default function (cli: CLI): Rx.Observable<any> {
export default function (o: Rx.Subject<Message>): Rx.Observable<any> {
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)
}

Expand Down Expand Up @@ -90,11 +90,11 @@ export default function (cli: CLI): Rx.Observable<any> {

handleUnhandleds()

return cli
.takeUntil(cli.filter(m => m.type === 'done'))
return o
.takeUntil(o.filter(m => m.type === 'done'))
.filter<Message, ErrorMessage>((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')
})
}
48 changes: 24 additions & 24 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,49 +13,39 @@ export interface IErrorOptions {
severity?: 'fatal' | 'error' | 'warn'
}

export class CLI extends Rx.Subject<Message> {
children: Rx.Observable<any>
subscription: Rx.Subscription
let subject: Rx.Subject<Message> = new Rx.Subject()
let children: Rx.Observable<any>

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)
}

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()
}
}

Expand All @@ -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()
15 changes: 7 additions & 8 deletions src/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<any> {
export default function setup(o: Rx.Subject<Message>): Rx.Observable<any> {
function log(file: string) {
let stream: Promise<fs.WriteStream> | undefined
function getStream() {
Expand Down Expand Up @@ -37,8 +36,8 @@ export default function setup(cli: CLI): Rx.Observable<any> {

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<Message, LoggerMessage>((m): m is LoggerMessage => m.type === 'logger')
.filter(m => {
switch (config.logLevel) {
Expand All @@ -50,7 +49,7 @@ export default function setup(cli: CLI): Rx.Observable<any> {
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)
Expand All @@ -63,9 +62,9 @@ export default function setup(cli: CLI): Rx.Observable<any> {
.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<Message, ConfigMessage>((m): m is ConfigMessage => m.type === 'config' && m.prop === 'errlog')
.switchMap(m => log(m.value))
}
7 changes: 7 additions & 0 deletions src/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
12 changes: 6 additions & 6 deletions src/output.ts
Original file line number Diff line number Diff line change
@@ -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<any> {
export default function (o: Rx.Observable<Message>): Rx.Observable<any> {
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<Message, OutputMessage>((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)
Expand Down

0 comments on commit e0394f6

Please sign in to comment.