1- import handleCliError , { validateOptions , type Options } from 'handle-cli-error'
1+ import beautifulError from 'beautiful-error'
2+ import handleCliError , {
3+ validateOptions ,
4+ type Options as HandleCliErrorOptions ,
5+ } from 'handle-cli-error'
26import type { Info , Plugin } from 'modern-errors'
37
48/**
59 * Options of `modern-errors-cli`
610 */
7- export type { Options }
11+ export type Options = Omit < HandleCliErrorOptions , 'classes' | 'custom' >
12+
13+ // `error.pretty()` is called with `errorString` as argument by
14+ // `beautiful-error`. We ignore that argument and prevent it from being
15+ // considered an invalid options object.
16+ const isOptions = ( options : unknown ) => typeof options !== 'string'
817
918const getOptions = ( options : Options = { } ) => {
10- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1119 validateOptions ( options )
1220
1321 if ( options . classes !== undefined ) {
14- throw new TypeError ( '"classes" must not be defined.' )
22+ throw new TypeError ( 'The "classes" option must not be defined.' )
23+ }
24+
25+ if ( options . custom !== undefined ) {
26+ throw new TypeError ( 'The "custom" option must not be defined.' )
1527 }
1628
1729 return options
@@ -38,16 +50,40 @@ const getOptions = (options: Options = {}) => {
3850 * ```
3951 */
4052const exit = ( { error, options } : Info < Options > [ 'instanceMethods' ] ) => {
41- handleCliError ( error , options )
53+ handleCliError ( error , { ...options , custom : 'pretty' } )
54+ }
55+
56+ // Uses `.pretty()` to avoid conflict with `modern-errors-beautiful`.
57+ // Temporarily unsets `error.pretty()` to avoid recursion.
58+ const pretty = ( {
59+ error,
60+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
61+ options : { exitCode, silent, timeout, log, ...beautifulErrorOptions } ,
62+ } : Info < Options > [ 'instanceMethods' ] ) => {
63+ // eslint-disable-next-line fp/no-mutating-methods
64+ Object . defineProperty ( error , 'pretty' , {
65+ value : undefined ,
66+ enumerable : false ,
67+ writable : true ,
68+ configurable : true ,
69+ } )
70+
71+ try {
72+ return beautifulError ( error , beautifulErrorOptions )
73+ } finally {
74+ // eslint-disable-next-line fp/no-delete
75+ delete ( error as Error & { pretty ?: undefined } ) . pretty
76+ }
4277}
4378
4479/**
4580 * `modern-errors-cli` plugin
4681 */
4782const modernErrorsCli = {
4883 name : 'cli' as const ,
84+ isOptions,
4985 getOptions,
50- instanceMethods : { exit } ,
86+ instanceMethods : { exit, pretty } ,
5187} satisfies Plugin
5288
5389export default modernErrorsCli
0 commit comments