handle-cli-error
Advanced tools
Comparing version 2.5.1 to 3.0.0
import process from"process"; | ||
import{handleInvalidOpts}from"./options/invalid.js"; | ||
import{waitForTimeout}from"./timeout.js"; | ||
export const validateExitCode=function(exitCode,optName){ | ||
if( | ||
!Number.isInteger(exitCode)|| | ||
exitCode<MIN_EXIT_CODE|| | ||
exitCode>MAX_EXIT_CODE) | ||
{ | ||
handleInvalidOpts( | ||
`must be between ${MIN_EXIT_CODE} and ${MAX_EXIT_CODE}`, | ||
exitCode, | ||
optName); | ||
} | ||
}; | ||
export const exitProcess=function(exitCode,timeout){ | ||
@@ -16,5 +32,5 @@ process.exitCode=exitCode; | ||
export const MIN_EXIT_CODE=0; | ||
const MIN_EXIT_CODE=0; | ||
export const MAX_EXIT_CODE=124; | ||
const MAX_EXIT_CODE=124; | ||
@@ -21,0 +37,0 @@ export const INVALID_OPTS_EXIT_CODE=125; |
@@ -0,1 +1,4 @@ | ||
import figures from 'figures' | ||
import type { Styles } from 'chalk-string' | ||
/** | ||
@@ -15,11 +18,14 @@ * `handle-cli-error` options | ||
/** | ||
* Logs the `error` message only, not its stack trace. | ||
* Whether to log the `error` stack trace. | ||
* | ||
* This is useful when the error was caused by the user (as opposed to being | ||
* an internal bug), in which cause the stack trace is not relevant to the | ||
* user. | ||
* @default true | ||
*/ | ||
readonly stack?: boolean | ||
/** | ||
* Whether to log the error's additional properties. | ||
* | ||
* @default false | ||
* @default true | ||
*/ | ||
readonly short?: boolean | ||
readonly props?: boolean | ||
@@ -34,2 +40,31 @@ /** | ||
/** | ||
* Whether to colorize the error's message, stack trace and additional properties. | ||
* | ||
* Quoted strings in the error's message are printed in bold (for `"..."` and | ||
* `'...'`) and in italic (for `` `...` ``). | ||
* | ||
* @default `true` in terminals, `false` otherwise | ||
*/ | ||
readonly colors?: boolean | ||
/** | ||
* Icon prepended to the error's name. The available values are listed | ||
* [here](https://github.com/sindresorhus/figures/blob/main/readme.md#figures-1). | ||
* Can be disabled by passing an empty string. | ||
* | ||
* @default 'cross' | ||
*/ | ||
readonly icon?: keyof typeof figures | '' | ||
/** | ||
* Color/style of the error's icon and name. The available values are listed | ||
* [here](https://github.com/ehmicky/chalk-string#available-styles). | ||
* Several styles can be specified by using spaces. | ||
* Can be disabled by passing an empty string. | ||
* | ||
* @default 'red bold' | ||
*/ | ||
readonly header?: Styles | '' | ||
/** | ||
* The process exits gracefully: it waits for any ongoing tasks (callbacks, | ||
@@ -59,4 +94,4 @@ * promises, etc.) to complete, up to a specific `timeout`. | ||
* handleCliError(error, { | ||
* InputError: { exitCode: 1, short: true }, | ||
* DatabaseError: { exitCode: 2, short: true }, | ||
* InputError: { exitCode: 1, stack: false }, | ||
* DatabaseError: { exitCode: 2, stack: false }, | ||
* default: { exitCode: 3 }, | ||
@@ -72,3 +107,3 @@ * }) | ||
/** | ||
* Prints `error` on the console (`stderr`) then exits the process. | ||
* Logs `error` on the console (`stderr`) then exits the process. | ||
* | ||
@@ -87,3 +122,3 @@ * This never throws. Invalid `error`s are silently | ||
* } catch (error) { | ||
* handleCliError(error) // Print `error` then exit the process | ||
* handleCliError(error) // Logs `error` then exit the process | ||
* } | ||
@@ -90,0 +125,0 @@ * } |
@@ -5,3 +5,3 @@ import normalizeException from"normalize-exception"; | ||
import{getOpts}from"./options/main.js"; | ||
import{printError}from"./print.js"; | ||
import{printError}from"./print/main.js"; | ||
@@ -15,7 +15,7 @@ export{validateOptions}from"./options/validate.js"; | ||
error:errorB, | ||
opts:{silent,short,exitCode,timeout}}= | ||
opts:{silent,stack,props,colors,icon,header,exitCode,timeout}}= | ||
getOpts(opts,errorA); | ||
printError(errorB,silent,short); | ||
printError({error:errorB,silent,stack,props,colors,icon,header}); | ||
exitProcess(exitCode,timeout); | ||
} | ||
//# sourceMappingURL=main.js.map |
@@ -12,5 +12,8 @@ import{excludeKeys}from"filter-obj"; | ||
const DEFAULT_OPTS={ | ||
export const DEFAULT_OPTS={ | ||
silent:false, | ||
short:false, | ||
stack:true, | ||
props:true, | ||
icon:"cross", | ||
header:"red bold", | ||
exitCode:DEFAULT_EXIT_CODE, | ||
@@ -17,0 +20,0 @@ timeout:DEFAULT_TIMEOUT}; |
import normalizeException from"normalize-exception"; | ||
import{INVALID_OPTS_EXIT_CODE}from"../exit.js"; | ||
import{DEFAULT_TIMEOUT}from"../timeout.js"; | ||
import{removeUndefined,applyDefaultOpts}from"./default.js"; | ||
import{applyClassesOpts}from"./classes.js"; | ||
import{applyDefaultOpts,DEFAULT_OPTS}from"./default.js"; | ||
import{validateOptions}from"./validate.js"; | ||
@@ -29,14 +29,5 @@ | ||
const applyClassesOpts=function({name},{classes={},...opts}={}){ | ||
const classesOpts=classes[name]||classes.default||{}; | ||
return{...opts,...removeUndefined(classesOpts)}; | ||
}; | ||
const INVALID_OPTS={ | ||
silent:false, | ||
short:false, | ||
exitCode:INVALID_OPTS_EXIT_CODE, | ||
timeout:DEFAULT_TIMEOUT}; | ||
...DEFAULT_OPTS, | ||
exitCode:INVALID_OPTS_EXIT_CODE}; | ||
//# sourceMappingURL=main.js.map |
import isPlainObj from"is-plain-obj"; | ||
import{MIN_EXIT_CODE,MAX_EXIT_CODE}from"../exit.js"; | ||
import{NO_TIMEOUT,INFINITE_TIMEOUT}from"../timeout.js"; | ||
import{validateExitCode}from"../exit.js"; | ||
import{validateHeader}from"../print/header.js"; | ||
import{validateIcon}from"../print/icon.js"; | ||
import{validateTimeout}from"../timeout.js"; | ||
import{validateClasses}from"./classes.js"; | ||
import{handleInvalidOpts}from"./invalid.js"; | ||
export const validateOptions=function(opts){ | ||
@@ -37,3 +42,3 @@ validateAllOpts(opts,[]); | ||
validator(optValue,optName); | ||
validator(optValue,optName,validateAllOpts); | ||
}; | ||
@@ -47,60 +52,12 @@ | ||
const validateExitCode=function(exitCode,optName){ | ||
if( | ||
!Number.isInteger(exitCode)|| | ||
exitCode<MIN_EXIT_CODE|| | ||
exitCode>MAX_EXIT_CODE) | ||
{ | ||
handleInvalidOpts( | ||
`must be between ${MIN_EXIT_CODE} and ${MAX_EXIT_CODE}`, | ||
exitCode, | ||
optName); | ||
} | ||
}; | ||
const validateTimeout=function(timeout,optName){ | ||
if( | ||
(!Number.isInteger(timeout)||timeout<=0)&& | ||
!isSpecialTimeout(timeout)) | ||
{ | ||
handleInvalidOpts( | ||
"must be 0, a positive integer or Infinity", | ||
timeout, | ||
optName); | ||
} | ||
}; | ||
const isSpecialTimeout=function(timeout){ | ||
return timeout===INFINITE_TIMEOUT||timeout===NO_TIMEOUT; | ||
}; | ||
const validateClasses=function(classes,optName){ | ||
if(!isPlainObj(classes)){ | ||
handleInvalidOpts("must be a plain object",classes,optName); | ||
} | ||
if(optName.length>1){ | ||
handleInvalidOpts("must not be defined",classes,optName); | ||
} | ||
Object.entries(classes).forEach(([className,classOpts])=>{ | ||
validateAllOpts(classOpts,[...optName,className]); | ||
}); | ||
}; | ||
const VALIDATORS={ | ||
silent:validateBooleanOpt, | ||
short:validateBooleanOpt, | ||
stack:validateBooleanOpt, | ||
props:validateBooleanOpt, | ||
colors:validateBooleanOpt, | ||
icon:validateIcon, | ||
header:validateHeader, | ||
exitCode:validateExitCode, | ||
timeout:validateTimeout, | ||
classes:validateClasses}; | ||
const handleInvalidOpts=function(message,value,optName){ | ||
const fullOptName= | ||
optName.length===0?"options":`"${optName.join(".")}"`; | ||
throw new Error(`${fullOptName} ${message}: ${value}`); | ||
}; | ||
//# sourceMappingURL=validate.js.map |
@@ -0,5 +1,25 @@ | ||
import{handleInvalidOpts}from"./options/invalid.js"; | ||
export const validateTimeout=function(timeout,optName){ | ||
if( | ||
(!Number.isInteger(timeout)||timeout<=0)&& | ||
!isSpecialTimeout(timeout)) | ||
{ | ||
handleInvalidOpts( | ||
"must be 0, a positive integer or Infinity", | ||
timeout, | ||
optName); | ||
} | ||
}; | ||
const isSpecialTimeout=function(timeout){ | ||
return timeout===INFINITE_TIMEOUT||timeout===NO_TIMEOUT; | ||
}; | ||
export const waitForTimeout=function(timeout,callback){ | ||
@@ -6,0 +26,0 @@ if(timeout===NO_TIMEOUT){ |
{ | ||
"name": "handle-cli-error", | ||
"version": "2.5.1", | ||
"version": "3.0.0", | ||
"type": "module", | ||
@@ -51,3 +51,6 @@ "exports": "./build/src/main.js", | ||
"@sinonjs/fake-timers": "^9.1.2", | ||
"error-serializer": "^3.5.1", | ||
"execa": "^6.1.0", | ||
"has-ansi": "^5.0.1", | ||
"sinon": "^14.0.1", | ||
"test-each": "^5.4.1" | ||
@@ -59,6 +62,10 @@ }, | ||
"dependencies": { | ||
"chalk-string": "^1.1.0", | ||
"figures": "^5.0.0", | ||
"filter-obj": "^5.1.0", | ||
"is-error-instance": "^1.1.0", | ||
"is-plain-obj": "^4.1.0", | ||
"normalize-exception": "^2.8.0" | ||
"normalize-exception": "^2.8.1", | ||
"strip-ansi": "^7.0.1" | ||
} | ||
} |
@@ -16,9 +16,14 @@ <picture> | ||
- 🖍️ Pretty [colors](#%EF%B8%8F-colors), [icons](#-icon) and [header](#-header) | ||
- 💣 [Error class-specific](#-classes) handling | ||
- 🚒 [Graceful exit](#-timeout) | ||
- ⛑️ [Normalize](https://github.com/ehmicky/normalize-exception) invalid errors | ||
- 📕 Log verbosity: full, [short](#-short) or [silent](#-silent) | ||
- 🔕 Log verbosity: [message](#-silent), [stack](#-stack), [properties](#-props) | ||
- 🚨 Custom [exit code](#-exitcode) | ||
- 💥 Exception-safe | ||
# Screenshot | ||
<img alt="handle-cli-error screenshot" src="docs/screenshot.png" width="500"/> | ||
# Example | ||
@@ -36,3 +41,3 @@ | ||
} catch (error) { | ||
handleCliError(error) // Print `error` then exit the process | ||
handleCliError(error) // Logs `error` then exit the process | ||
} | ||
@@ -49,4 +54,4 @@ } | ||
classes: { | ||
InputError: { exitCode: 1, short: true }, | ||
DatabaseError: { exitCode: 2, short: true }, | ||
InputError: { exitCode: 1, stack: false }, | ||
DatabaseError: { exitCode: 2, stack: false }, | ||
default: { exitCode: 3 }, | ||
@@ -75,5 +80,5 @@ }, | ||
Prints `error` on the console (`stderr`) then exits the process. | ||
Logs `error` on the console (`stderr`) then exits the process. | ||
This never throws. Invalid `error`s are silently | ||
This never throws. Invalid errors are silently | ||
[normalized](https://github.com/ehmicky/normalize-exception). | ||
@@ -92,12 +97,16 @@ | ||
#### 📕 short | ||
#### 📕 stack | ||
_Type_: `boolean`\ | ||
_Default_: `false` | ||
_Default_: `true` | ||
Logs the `error` message only, not its stack trace. | ||
Whether to log the error's stack trace. | ||
This is useful when the error was caused by the user (as opposed to being an | ||
internal bug), in which cause the stack trace is not relevant to the user. | ||
#### 📢 props | ||
_Type_: `boolean`\ | ||
_Default_: `true` | ||
Whether to log the error's additional properties. | ||
#### 🔕 silent | ||
@@ -110,2 +119,31 @@ | ||
#### 🖍️ colors | ||
_Type_: `boolean`\ | ||
_Default_: `true` in terminals, `false` otherwise | ||
Whether to colorize the error's message, stack trace and additional properties. | ||
Quoted strings in the error's message are printed in bold (for `"..."` and | ||
`'...'`) and in italic (for `` `...` ``). | ||
#### ❌ icon | ||
_Type_: `string`\ | ||
_Default_: `'cross'` | ||
Icon prepended to the error's name. The available values are listed | ||
[here](https://github.com/sindresorhus/figures/blob/main/readme.md#figures-1). | ||
Can be disabled by passing an empty string. | ||
#### 💄 header | ||
_Type_: `string`\ | ||
_Default_: `'red bold'` | ||
Color/style of the error's [icon](#-icon) and name. The available values are | ||
listed [here](https://github.com/ehmicky/chalk-string#available-styles). Several | ||
styles can be specified by using spaces. Can be disabled by passing an empty | ||
string. | ||
#### 🚒 timeout | ||
@@ -112,0 +150,0 @@ |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
26447
19
591
228
7
7
1
+ Addedchalk-string@^1.1.0
+ Addedfigures@^5.0.0
+ Addedis-error-instance@^1.1.0
+ Addedstrip-ansi@^7.0.1
+ Addedansi-regex@6.1.0(transitive)
+ Addedchalk@5.4.1(transitive)
+ Addedchalk-string@1.2.0(transitive)
+ Addedcolors-option@4.5.0(transitive)
+ Addedescape-string-regexp@5.0.0(transitive)
+ Addedfigures@5.0.0(transitive)
+ Addedis-unicode-supported@1.3.0(transitive)
+ Addedstrip-ansi@7.1.0(transitive)
Updatednormalize-exception@^2.8.1