-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
288 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
import type { Boom } from "@hapi/boom"; | ||
import type { AssertionError } from "assert"; | ||
|
||
export type BounceErrorType = Error | "system" | "boom" | Record<any, any>; | ||
|
||
export interface BounceOptions { | ||
/** | ||
* An object which is assigned to the `err`, copying the properties onto the error. | ||
*/ | ||
decorate?: Record<any, any>; | ||
|
||
/** | ||
* An error used to override `err` when `err` matches. If used with `decorate`, the `override` object is modified. | ||
*/ | ||
override?: Error; | ||
|
||
/** | ||
* If `true`, the error is returned instead of thrown. Defaults to `false`. | ||
* @defaultValue `false` | ||
*/ | ||
return?: boolean; | ||
} | ||
|
||
/** | ||
* A single item or an array of items of: | ||
* - An error constructor (e.g. `SyntaxError`). | ||
* - `'system'` - matches any languange native error or node assertions. | ||
* - `'boom'` - matches [**boom**](https://github.com/hapijs/boom) errors. | ||
* - an object where each property is compared with the error and must match the error property | ||
* value. All the properties in the object must match the error but do not need to include all | ||
* the error properties. | ||
*/ | ||
export type BounceErrorTypes = BounceErrorType | BounceErrorType[]; | ||
|
||
export type BounceReturn< | ||
TErr extends Error, | ||
TOpts extends BounceOptions | ||
> = TOpts extends { return: true } | ||
? TOpts extends { decorate: any } | ||
? (TOpts extends { override: any } ? TOpts["override"] : TErr) & | ||
TOpts["decorate"] | ||
: TOpts extends { override: any } | ||
? TOpts["override"] | ||
: TErr | ||
: void; | ||
|
||
/** | ||
* Throws the error passed if it matches any of the specified rules where: | ||
* - `err` - the error. | ||
* | ||
* @param err The error. | ||
* @param types {@link BounceErrorTypes} | ||
* @param options {@link BounceOptions} | ||
*/ | ||
export function rethrow<TErr extends Error, TOpts extends BounceOptions>( | ||
err: TErr, | ||
types: BounceErrorTypes, | ||
options?: TOpts | ||
): BounceReturn<TErr, TOpts>; | ||
|
||
/** | ||
* The opposite action of {@link rethrow `rethrow()`}. Ignores any errors matching the specified `types`. Any error not matching is thrown after applying the `options`. | ||
* | ||
* @param err The error. | ||
* @param types same as the {@link BounceErrorTypes `types`} argument passed to `rethrow()` | ||
* @param options same as the {@link BounceOptions `options`} argument passed to `rethrow()` | ||
*/ | ||
export function ignore<TErr extends Error, TOpts extends BounceOptions>( | ||
err: TErr, | ||
types: BounceErrorTypes, | ||
options?: TOpts | ||
): BounceReturn<TErr, TOpts>; | ||
|
||
/** | ||
* Awaits for the value to resolve in the background and then apply either the `rethrow()` or `ignore()` actions. | ||
* | ||
* @param operation a function, promise, or value that is `await`ed on inside a `try...catch` and any error thrown processed by the `action` rule. | ||
* @param action one of `'rethrow'` or `'ignore'`. Defaults to `'rethrow'`. | ||
* @param types same as the `types` argument passed to `rethrow()` or `ignore()`. Defaults to `'system'`. | ||
* @param options same as the {@link BounceOptions `options`} argument passed to `rethrow()` or `ignore()`. | ||
*/ | ||
export function background( | ||
operation: Function | Promise<any> | any, | ||
action?: "rethrow" | "ignore", | ||
types?: BounceErrorTypes, | ||
options?: BounceOptions | ||
): Promise<void>; | ||
|
||
/** | ||
* Returns `true` when `err` is a [**boom**](https://github.com/hapijs/boom) error. | ||
* | ||
* @param err The error. | ||
*/ | ||
export function isBoom(err: unknown): err is Boom; | ||
|
||
/** | ||
* Returns `true` when `err` is an error. | ||
* | ||
* @param err The error. | ||
*/ | ||
export function isError(err: unknown): err is Error; | ||
|
||
/** | ||
* Return `true` when `err` is one of: | ||
* - `EvalError` | ||
* - `RangeError` | ||
* - `ReferenceError` | ||
* - `SyntaxError` | ||
* - `TypeError` | ||
* - `URIError` | ||
* - Node's `AssertionError` | ||
* | ||
* @param err The error. | ||
*/ | ||
export function isSystem( | ||
err: unknown | ||
): err is | ||
| EvalError | ||
| RangeError | ||
| ReferenceError | ||
| SyntaxError | ||
| TypeError | ||
| URIError | ||
| AssertionError; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
import * as Bounce from ".."; | ||
import * as Lab from "@hapi/lab"; | ||
|
||
const { expect } = Lab.types; | ||
|
||
class CustomErr extends Error { | ||
customProp = "customProp"; | ||
} | ||
|
||
// rethrow | ||
expect.type<void>(Bounce.rethrow(new Error(), "system")); | ||
expect.type<void>(Bounce.rethrow(new Error(), "boom")); | ||
expect.type<void>(Bounce.rethrow(new Error(), ["system", "boom"])); | ||
expect.type<void>(Bounce.rethrow(new Error(), { prop: "prop" })); | ||
expect.type<void>( | ||
Bounce.rethrow(new Error(), "system", { decorate: { prop: "prop" } }) | ||
); | ||
expect.type<void>( | ||
Bounce.rethrow(new Error(), "system", { | ||
decorate: { prop: "prop" }, | ||
override: new CustomErr(), | ||
}) | ||
); | ||
expect.type<CustomErr & { prop: string }>( | ||
Bounce.rethrow(new Error(), "system", { | ||
decorate: { prop: "prop" }, | ||
override: new CustomErr(), | ||
return: true, | ||
}) | ||
); | ||
expect.type<CustomErr>( | ||
Bounce.rethrow(new Error(), "system", { | ||
override: new CustomErr(), | ||
return: true, | ||
}) | ||
); | ||
expect.type<Error>(Bounce.rethrow(new Error(), "system", { return: true })); | ||
expect.type<Error & { prop: string }>( | ||
Bounce.rethrow(new Error(), "system", { | ||
decorate: { prop: "prop" }, | ||
return: true, | ||
}) | ||
); | ||
|
||
expect.error(Bounce.rethrow(new Error(), "systm")); | ||
expect.error(Bounce.rethrow(new Error(), "bom")); | ||
expect.error(Bounce.rethrow(new Error(), ["system", "bom"])); | ||
expect.error(Bounce.rethrow(new Error(), "system", { decorate: true })); | ||
expect.error( | ||
Bounce.rethrow(new Error(), "system", { override: { prop: "prop" } }) | ||
); | ||
expect.error(Bounce.rethrow(new Error(), "system", { return: 1 })); | ||
|
||
// ignore | ||
expect.type<void>(Bounce.ignore(new Error(), "system")); | ||
expect.type<void>(Bounce.ignore(new Error(), "boom")); | ||
expect.type<void>(Bounce.ignore(new Error(), { prop: "prop" })); | ||
expect.type<void>( | ||
Bounce.ignore(new Error(), "system", { decorate: { prop: "prop" } }) | ||
); | ||
expect.type<void>( | ||
Bounce.ignore(new Error(), "system", { | ||
decorate: { prop: "prop" }, | ||
override: new CustomErr(), | ||
}) | ||
); | ||
expect.type<CustomErr & { prop: string }>( | ||
Bounce.ignore(new Error(), "system", { | ||
decorate: { prop: "prop" }, | ||
override: new CustomErr(), | ||
return: true, | ||
}) | ||
); | ||
expect.type<CustomErr>( | ||
Bounce.ignore(new Error(), "system", { | ||
override: new CustomErr(), | ||
return: true, | ||
}) | ||
); | ||
expect.type<Error>(Bounce.ignore(new Error(), "system", { return: true })); | ||
expect.type<Error & { prop: string }>( | ||
Bounce.ignore(new Error(), "system", { | ||
decorate: { prop: "prop" }, | ||
return: true, | ||
}) | ||
); | ||
|
||
expect.error(Bounce.ignore(new Error(), "systm")); | ||
expect.error(Bounce.ignore(new Error(), "bom")); | ||
expect.error(Bounce.ignore(new Error(), "system", { decorate: true })); | ||
expect.error( | ||
Bounce.ignore(new Error(), "system", { override: { prop: "prop" } }) | ||
); | ||
expect.error(Bounce.ignore(new Error(), "system", { return: 1 })); | ||
|
||
// background | ||
expect.type<Promise<void>>(Bounce.background(() => {})); | ||
expect.type<Promise<void>>(Bounce.background(() => {}, "rethrow")); | ||
expect.type<Promise<void>>(Bounce.background(() => {}, "ignore")); | ||
expect.type<Promise<void>>(Bounce.background(() => {}, "rethrow", "system")); | ||
expect.type<Promise<void>>(Bounce.background(() => {}, "rethrow", "boom")); | ||
expect.type<Promise<void>>( | ||
Bounce.background(() => {}, "rethrow", { prop: "prop" }) | ||
); | ||
expect.type<Promise<void>>( | ||
Bounce.background(() => {}, "rethrow", "system", { | ||
decorate: { prop: "prop" }, | ||
}) | ||
); | ||
expect.type<Promise<void>>( | ||
Bounce.background(() => {}, "rethrow", "system", { | ||
decorate: { prop: "prop" }, | ||
override: new CustomErr(), | ||
}) | ||
); | ||
expect.type<Promise<void>>( | ||
Bounce.background(() => {}, "rethrow", "system", { | ||
decorate: { prop: "prop" }, | ||
override: new CustomErr(), | ||
return: true, | ||
}) | ||
); | ||
expect.type<Promise<void>>( | ||
Bounce.background(() => {}, "rethrow", "system", { | ||
override: new CustomErr(), | ||
return: true, | ||
}) | ||
); | ||
expect.type<Promise<void>>( | ||
Bounce.background(() => {}, "rethrow", "system", { return: true }) | ||
); | ||
expect.type<Promise<void>>( | ||
Bounce.background(() => {}, "rethrow", "system", { | ||
decorate: { prop: "prop" }, | ||
return: true, | ||
}) | ||
); | ||
|
||
expect.error(Bounce.background(() => {}, "rethro")); | ||
expect.error(Bounce.background(() => {}, "ignor")); | ||
expect.error(Bounce.background(() => {}, "rethrow", "systm")); | ||
expect.error(Bounce.background(() => {}, "rethrow", "bom")); | ||
expect.error( | ||
Bounce.background(() => {}, "rethrow", "system", { decorate: true }) | ||
); | ||
expect.error( | ||
Bounce.background(() => {}, "rethrow", "system", { | ||
override: { prop: "prop" }, | ||
}) | ||
); | ||
expect.error(Bounce.background(() => {}, "rethrow", "system", { return: 1 })); | ||
|
||
// isBoom | ||
expect.type<boolean>(Bounce.isBoom("")); | ||
|
||
// isError | ||
expect.type<boolean>(Bounce.isError("")); | ||
|
||
// isSystem | ||
expect.type<boolean>(Bounce.isError("")); |