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

Commit

Permalink
fix: only display error when unhandled
Browse files Browse the repository at this point in the history
  • Loading branch information
jdx committed Jan 20, 2018
1 parent c88bcb3 commit 5631c04
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 42 deletions.
3 changes: 2 additions & 1 deletion src/action/spinner.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// tslint:disable restrict-plus-operands

import chalk from 'chalk'
import * as supportsColor from 'supports-color'

import deps from '../deps'
Expand All @@ -10,7 +11,7 @@ const spinners = require('./spinners')
function color(s: string): string {
if (!supportsColor) return s
let has256 = supportsColor.has256 || (process.env.TERM || '').indexOf('256') !== -1
return has256 ? `\u001b[38;5;104m${s}${deps.ansiStyles.reset.open}` : deps.chalk.magenta(s)
return has256 ? `\u001b[38;5;104m${s}${deps.ansiStyles.reset.open}` : chalk.magenta(s)
}

export default class SpinnerAction extends ActionBase {
Expand Down
2 changes: 0 additions & 2 deletions src/deps.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import screen = require('@dxcli/screen')
import ansiStyles = require('ansi-styles')
import {Chalk} from 'chalk'
import stripAnsi = require('strip-ansi')

import prompt = require('./prompt')
Expand All @@ -10,7 +9,6 @@ import styledObject = require('./styled/object')
import table = require('./styled/table')

export const deps = {
get chalk(): Chalk { return fetch('chalk') },
get stripAnsi(): typeof stripAnsi { return fetch('strip-ansi') },
get ansiStyles(): typeof ansiStyles { return fetch('ansi-styles') },
get ansiEscapes(): any { return fetch('ansi-escapes') },
Expand Down
71 changes: 39 additions & 32 deletions src/errors.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// tslint:disable no-console

import chalk from 'chalk'
import {inspect} from 'util'

import CLI from '.'
Expand All @@ -11,7 +12,7 @@ export interface Message {
type: 'error'
scope: string | undefined
severity: 'fatal' | 'error' | 'warn'
error: Error
error: CLIError
}

export interface Options {
Expand Down Expand Up @@ -48,23 +49,35 @@ export function getErrorMessage(err: any): string {
return message || inspect(err)
}

function wrap(msg: string): string {
const linewrap = require('@heroku/linewrap')
return linewrap(6, deps.screen.errtermwidth, {
skip: /^\$ .*$/,
skipScheme: 'ansi-color',
})(msg)
}
function displayError(err: CLIError) {
function wrap(msg: string): string {
const linewrap = require('@heroku/linewrap')
return linewrap(6, deps.screen.errtermwidth, {
skip: /^\$ .*$/,
skipScheme: 'ansi-color',
})(msg)
}

function render(): string {
let bang = chalk.red(arrow)
let msg = err['cli-ux'].scope ? `${err['cli-ux'].scope}: ${getErrorMessage(err)}` : getErrorMessage(err)
if (err['cli-ux'].severity === 'fatal') {
bang = chalk.bgRed.bold.white(' FATAL ')
msg += `\n${inspect(err)}`
}
if (err['cli-ux'].severity === 'warn') bang = chalk.yellow(arrow)
return bangify(wrap(msg), bang)
}

function render(message: Message): string {
let bang = deps.chalk.red(arrow)
let msg = message.scope ? `${message.scope}: ${getErrorMessage(message.error)}` : getErrorMessage(message.error)
if (message.severity === 'fatal') {
bang = deps.chalk.bgRed.bold.white(' FATAL ')
msg += `\n${inspect(message.error)}`
function getBang(): string {
if (err['cli-ux'].severity === 'warn') return chalk.yellowBright('!')
if (err['cli-ux'].severity === 'fatal') return chalk.bold.bgRedBright('!!!')
return chalk.bold.redBright('!')
}
if (message.severity === 'warn') bang = deps.chalk.yellow(arrow)
return bangify(wrap(msg), bang)

config.action.pause(() => {
console.error(render())
}, getBang())
}

export class CLIError extends Error {
Expand All @@ -76,6 +89,13 @@ export class CLIError extends Error {
}

constructor(input: any, severity: 'fatal' | 'error' | 'warn', scope: string | undefined, opts: Options) {
function getExitCode(options: Options): false | number {
let exit = options.exit === undefined ? (options as any).exitCode : options.exit
if (exit === false) return false
if (exit === undefined) return 1
return exit
}

const err: CLIError = typeof input === 'string' ? super(input) && this : input
err['cli-ux'] = err['cli-ux'] || {
severity,
Expand All @@ -86,23 +106,11 @@ export class CLIError extends Error {
}
}

function getExitCode(options: Options): false | number {
let exit = options.exit === undefined ? (options as any).exitCode : options.exit
if (exit === false) return false
if (exit === undefined) return 1
return exit
}

export default (e: IEventEmitter) => {
e.on('output', m => {
if (m.type !== 'error') return
const bang = (m.severity === 'warn' && deps.chalk.yellowBright('!'))
|| (m.severity === 'fatal' && deps.chalk.bold.bgRedBright('!!!'))
|| deps.chalk.bold.redBright('!')
try {
config.action.pause(() => {
console.error(render(m))
}, bang)
if (m.error['cli-ux'].exit === false) displayError(m.error)
} catch (newErr) {
console.error(newErr)
console.error(m.error)
Expand All @@ -120,12 +128,11 @@ export default (e: IEventEmitter) => {
const cli: typeof CLI = require('.').cli.scope(scope)
if (err.code === 'EPIPE') return
if (err['cli-ux'] && typeof err['cli-ux'].exit === 'number') {
displayError(err)
await cli.done().catch(cli.debug)
process.exit(err['cli-ux'].exit as number)
} else {
cli.fatal(err, {exit: false})
await cli.done().catch(cli.debug)
process.exit(100)
cli.fatal(err)
}
} catch (newError) {
console.error(err)
Expand Down
8 changes: 5 additions & 3 deletions src/prompt.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import chalk from 'chalk'

import config from './config'
import deps from './deps'

Expand All @@ -17,7 +19,7 @@ export default {
prompt(name: string, options: IPromptOptions = {}) {
return config.action.pauseAsync(() => {
return _prompt(name, options)
}, deps.chalk.cyan('?'))
}, chalk.cyan('?'))
},
confirm(message: string): Promise<boolean> {
return config.action.pauseAsync(async () => {
Expand All @@ -28,14 +30,14 @@ export default {
return confirm()
}
return confirm()
}, deps.chalk.cyan('?'))
}, chalk.cyan('?'))
}
}

function _prompt(name: string, inputOptions: Partial<IPromptOptions> = {}): Promise<string> {
const options: IPromptConfig = {
isTTY: !!(process.env.TERM !== 'dumb' && process.stdin.isTTY), name,
prompt: name ? deps.chalk.dim(`${name}: `) : deps.chalk.dim('> '),
prompt: name ? chalk.dim(`${name}: `) : chalk.dim('> '),
type: 'normal',
...inputOptions,
}
Expand Down
5 changes: 2 additions & 3 deletions src/styled/object.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
// tslint:disable

import chalk from 'chalk'
import * as util from 'util'

import deps from '../deps'

export default function styledObject(obj: any, keys?: string[]) {
let keyLengths = Object.keys(obj).map(key => key.toString().length)
let maxKeyLength = Math.max.apply(Math, keyLengths) + 2
Expand All @@ -18,7 +17,7 @@ export default function styledObject(obj: any, keys?: string[]) {
}
}
let logKeyValue = (key: string, value: any) => {
console.log(`${deps.chalk.blue(key)}:` + ' '.repeat(maxKeyLength - key.length - 1) + pp(value))
console.log(`${chalk.blue(key)}:` + ' '.repeat(maxKeyLength - key.length - 1) + pp(value))
}
for (let key of keys || Object.keys(obj).sort()) {
let value = obj[key]
Expand Down
1 change: 0 additions & 1 deletion test/errors.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,5 @@ describe.stderr('errors', () => {

it('errors', () => {
expect(() => cli.error('foobar')).to.throw(/foobar/)
expect(output.stderr).to.equal(' ▸ foobar\n')
})
})

0 comments on commit 5631c04

Please sign in to comment.