Skip to content

Commit 223c63f

Browse files
committed
feat: add TypeScript types
1 parent 87228f0 commit 223c63f

File tree

3 files changed

+290
-2
lines changed

3 files changed

+290
-2
lines changed

lib/index.d.ts

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import type { Boom } from "@hapi/boom";
2+
import type { AssertionError } from "assert";
3+
4+
export type BounceErrorType = Error | "system" | "boom" | Record<any, any>;
5+
6+
export interface BounceOptions {
7+
/**
8+
* An object which is assigned to the `err`, copying the properties onto the error.
9+
*/
10+
decorate?: Record<any, any>;
11+
12+
/**
13+
* An error used to override `err` when `err` matches. If used with `decorate`, the `override` object is modified.
14+
*/
15+
override?: Error;
16+
17+
/**
18+
* If `true`, the error is returned instead of thrown. Defaults to `false`.
19+
* @defaultValue `false`
20+
*/
21+
return?: boolean;
22+
}
23+
24+
/**
25+
* A single item or an array of items of:
26+
* - An error constructor (e.g. `SyntaxError`).
27+
* - `'system'` - matches any languange native error or node assertions.
28+
* - `'boom'` - matches [**boom**](https://github.com/hapijs/boom) errors.
29+
* - an object where each property is compared with the error and must match the error property
30+
* value. All the properties in the object must match the error but do not need to include all
31+
* the error properties.
32+
*/
33+
export type BounceErrorTypes = BounceErrorType | BounceErrorType[];
34+
35+
export type BounceReturn<
36+
TErr extends Error,
37+
TOpts extends BounceOptions
38+
> = TOpts extends { return: true }
39+
? TOpts extends { decorate: any }
40+
? (TOpts extends { override: any } ? TOpts["override"] : TErr) &
41+
TOpts["decorate"]
42+
: TOpts extends { override: any }
43+
? TOpts["override"]
44+
: TErr
45+
: void;
46+
47+
/**
48+
* Throws the error passed if it matches any of the specified rules where:
49+
* - `err` - the error.
50+
*
51+
* @param err The error.
52+
* @param types {@link BounceErrorTypes}
53+
* @param options {@link BounceOptions}
54+
*/
55+
export function rethrow<TErr extends Error, TOpts extends BounceOptions>(
56+
err: TErr,
57+
types: BounceErrorTypes,
58+
options?: TOpts
59+
): BounceReturn<TErr, TOpts>;
60+
61+
/**
62+
* The opposite action of {@link rethrow `rethrow()`}. Ignores any errors matching the specified `types`. Any error not matching is thrown after applying the `options`.
63+
*
64+
* @param err The error.
65+
* @param types same as the {@link BounceErrorTypes `types`} argument passed to `rethrow()`
66+
* @param options same as the {@link BounceOptions `options`} argument passed to `rethrow()`
67+
*/
68+
export function ignore<TErr extends Error, TOpts extends BounceOptions>(
69+
err: TErr,
70+
types: BounceErrorTypes,
71+
options?: TOpts
72+
): BounceReturn<TErr, TOpts>;
73+
74+
/**
75+
* Awaits for the value to resolve in the background and then apply either the `rethrow()` or `ignore()` actions.
76+
*
77+
* @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.
78+
* @param action one of `'rethrow'` or `'ignore'`. Defaults to `'rethrow'`.
79+
* @param types same as the `types` argument passed to `rethrow()` or `ignore()`. Defaults to `'system'`.
80+
* @param options same as the {@link BounceOptions `options`} argument passed to `rethrow()` or `ignore()`.
81+
*/
82+
export function background(
83+
operation: Function | Promise<any> | any,
84+
action?: "rethrow" | "ignore",
85+
types?: BounceErrorTypes,
86+
options?: BounceOptions
87+
): Promise<void>;
88+
89+
/**
90+
* Returns `true` when `err` is a [**boom**](https://github.com/hapijs/boom) error.
91+
*
92+
* @param err The error.
93+
*/
94+
export function isBoom(err: unknown): err is Boom;
95+
96+
/**
97+
* Returns `true` when `err` is an error.
98+
*
99+
* @param err The error.
100+
*/
101+
export function isError(err: unknown): err is Error;
102+
103+
/**
104+
* Return `true` when `err` is one of:
105+
* - `EvalError`
106+
* - `RangeError`
107+
* - `ReferenceError`
108+
* - `SyntaxError`
109+
* - `TypeError`
110+
* - `URIError`
111+
* - Node's `AssertionError`
112+
*
113+
* @param err The error.
114+
*/
115+
export function isSystem(
116+
err: unknown
117+
): err is
118+
| EvalError
119+
| RangeError
120+
| ReferenceError
121+
| SyntaxError
122+
| TypeError
123+
| URIError
124+
| AssertionError;

package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"version": "3.0.0",
55
"repository": "git://github.com/hapijs/bounce",
66
"main": "lib/index.js",
7+
"types": "lib/index.d.ts",
78
"files": [
89
"lib"
910
],
@@ -23,10 +24,12 @@
2324
"devDependencies": {
2425
"@hapi/code": "^9.0.0",
2526
"@hapi/eslint-plugin": "*",
26-
"@hapi/lab": "25.0.0-beta.1"
27+
"@hapi/lab": "^25.0.1",
28+
"@types/node": "^14.18.18",
29+
"typescript": "^4.7.2"
2730
},
2831
"scripts": {
29-
"test": "lab -a @hapi/code -t 100 -L",
32+
"test": "lab -a @hapi/code -t 100 -L -Y",
3033
"test-cov-html": "lab -a @hapi/code -r html -o coverage.html -L"
3134
},
3235
"license": "BSD-3-Clause"

test/index.ts

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
import * as Bounce from "..";
2+
import * as Boom from "@hapi/boom";
3+
import * as Lab from "@hapi/lab";
4+
5+
const { expect } = Lab.types;
6+
7+
class CustomErr extends Error {
8+
customProp = "customProp";
9+
}
10+
11+
// rethrow
12+
expect.type<void>(Bounce.rethrow(new Error(), "system"));
13+
expect.type<void>(Bounce.rethrow(new Error(), "boom"));
14+
expect.type<void>(Bounce.rethrow(new Error(), ["system", "boom"]));
15+
expect.type<void>(Bounce.rethrow(new Error(), { prop: "prop" }));
16+
expect.type<void>(
17+
Bounce.rethrow(new Error(), "system", { decorate: { prop: "prop" } })
18+
);
19+
expect.type<void>(
20+
Bounce.rethrow(new Error(), "system", {
21+
decorate: { prop: "prop" },
22+
override: new CustomErr(),
23+
})
24+
);
25+
expect.type<CustomErr & { prop: string }>(
26+
Bounce.rethrow(new Error(), "system", {
27+
decorate: { prop: "prop" },
28+
override: new CustomErr(),
29+
return: true,
30+
})
31+
);
32+
expect.type<CustomErr>(
33+
Bounce.rethrow(new Error(), "system", {
34+
override: new CustomErr(),
35+
return: true,
36+
})
37+
);
38+
expect.type<Error>(Bounce.rethrow(new Error(), "system", { return: true }));
39+
expect.type<Error & { prop: string }>(
40+
Bounce.rethrow(new Error(), "system", {
41+
decorate: { prop: "prop" },
42+
return: true,
43+
})
44+
);
45+
46+
expect.error(Bounce.rethrow(new Error(), "systm"));
47+
expect.error(Bounce.rethrow(new Error(), "bom"));
48+
expect.error(Bounce.rethrow(new Error(), ["system", "bom"]));
49+
expect.error(Bounce.rethrow(new Error(), "system", { decorate: true }));
50+
expect.error(
51+
Bounce.rethrow(new Error(), "system", { override: { prop: "prop" } })
52+
);
53+
expect.error(Bounce.rethrow(new Error(), "system", { return: 1 }));
54+
55+
// ignore
56+
expect.type<void>(Bounce.ignore(new TypeError(), "system"));
57+
expect.type<void>(Bounce.ignore(Boom.internal(), "boom"));
58+
expect.type<void>(Bounce.ignore(new CustomErr(), { customProp: "customProp" }));
59+
expect.type<void>(
60+
Bounce.ignore(new TypeError(), "system", { decorate: { prop: "prop" } })
61+
);
62+
expect.type<void>(
63+
Bounce.ignore(new TypeError(), "system", {
64+
decorate: { prop: "prop" },
65+
override: new CustomErr(),
66+
})
67+
);
68+
expect.type<CustomErr & { prop: string }>(
69+
Bounce.ignore(new TypeError(), "system", {
70+
decorate: { prop: "prop" },
71+
override: new CustomErr(),
72+
return: true,
73+
})
74+
);
75+
expect.type<CustomErr>(
76+
Bounce.ignore(new Error(), "system", {
77+
override: new CustomErr(),
78+
return: true,
79+
})
80+
);
81+
expect.type<Error>(Bounce.ignore(new Error(), "system", { return: true }));
82+
expect.type<Error & { prop: string }>(
83+
Bounce.ignore(new Error(), "system", {
84+
decorate: { prop: "prop" },
85+
return: true,
86+
})
87+
);
88+
89+
expect.error(Bounce.ignore(new Error(), "systm"));
90+
expect.error(Bounce.ignore(new Error(), "bom"));
91+
expect.error(Bounce.ignore(new Error(), "system", { decorate: true }));
92+
expect.error(
93+
Bounce.ignore(new TypeError(), "system", { override: { prop: "prop" } })
94+
);
95+
expect.error(Bounce.ignore(new Error(), "system", { return: 1 }));
96+
97+
// background
98+
expect.type<Promise<void>>(Bounce.background(() => {}));
99+
expect.type<Promise<void>>(Bounce.background(() => {}, "rethrow"));
100+
expect.type<Promise<void>>(Bounce.background(() => {}, "ignore"));
101+
expect.type<Promise<void>>(Bounce.background(() => {}, "rethrow", "system"));
102+
expect.type<Promise<void>>(Bounce.background(() => {}, "rethrow", "boom"));
103+
expect.type<Promise<void>>(
104+
Bounce.background(() => {}, "rethrow", { prop: "prop" })
105+
);
106+
expect.type<Promise<void>>(
107+
Bounce.background(() => {}, "rethrow", "system", {
108+
decorate: { prop: "prop" },
109+
})
110+
);
111+
expect.type<Promise<void>>(
112+
Bounce.background(() => {}, "rethrow", "system", {
113+
decorate: { prop: "prop" },
114+
override: new CustomErr(),
115+
})
116+
);
117+
expect.type<Promise<void>>(
118+
Bounce.background(() => {}, "rethrow", "system", {
119+
decorate: { prop: "prop" },
120+
override: new CustomErr(),
121+
return: true,
122+
})
123+
);
124+
expect.type<Promise<void>>(
125+
Bounce.background(() => {}, "rethrow", "system", {
126+
override: new CustomErr(),
127+
return: true,
128+
})
129+
);
130+
expect.type<Promise<void>>(
131+
Bounce.background(() => {}, "rethrow", "system", { return: true })
132+
);
133+
expect.type<Promise<void>>(
134+
Bounce.background(() => {}, "rethrow", "system", {
135+
decorate: { prop: "prop" },
136+
return: true,
137+
})
138+
);
139+
140+
expect.error(Bounce.background(() => {}, "rethro"));
141+
expect.error(Bounce.background(() => {}, "ignor"));
142+
expect.error(Bounce.background(() => {}, "rethrow", "systm"));
143+
expect.error(Bounce.background(() => {}, "rethrow", "bom"));
144+
expect.error(
145+
Bounce.background(() => {}, "rethrow", "system", { decorate: true })
146+
);
147+
expect.error(
148+
Bounce.background(() => {}, "rethrow", "system", {
149+
override: { prop: "prop" },
150+
})
151+
);
152+
expect.error(Bounce.background(() => {}, "rethrow", "system", { return: 1 }));
153+
154+
// isBoom
155+
expect.type<boolean>(Bounce.isBoom(""));
156+
157+
// isError
158+
expect.type<boolean>(Bounce.isError(""));
159+
160+
// isSystem
161+
expect.type<boolean>(Bounce.isError(""));

0 commit comments

Comments
 (0)