Skip to content

Commit 9136ed5

Browse files
committed
feat: add TypeScript types
1 parent 87228f0 commit 9136ed5

File tree

3 files changed

+288
-2
lines changed

3 files changed

+288
-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: 4 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,11 @@
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+
"typescript": "^4.7.2"
2729
},
2830
"scripts": {
29-
"test": "lab -a @hapi/code -t 100 -L",
31+
"test": "lab -a @hapi/code -t 100 -L -Y",
3032
"test-cov-html": "lab -a @hapi/code -r html -o coverage.html -L"
3133
},
3234
"license": "BSD-3-Clause"

test/index.ts

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

0 commit comments

Comments
 (0)