Skip to content

Commit 9a625b2

Browse files
authored
Create error.ts
1 parent 72515d4 commit 9a625b2

File tree

1 file changed

+174
-0
lines changed

1 file changed

+174
-0
lines changed

src/error/error.ts

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
/**
2+
* ErrorHandler provides a fluent API for selectively handling errors.
3+
*
4+
* Supports built-in errors (SyntaxError, TypeError, ReferenceError) as well as custom errors
5+
* through the `.catch()` method. If no handler matches, the error is automatically thrown.
6+
*/
7+
class ErrorHandler {
8+
private handled : boolean = false;
9+
private scheduled : boolean = false;
10+
11+
/**
12+
* Creates a new ErrorHandler instance for the given error.
13+
*
14+
* @param currentError The error to handle (unknown)
15+
*/
16+
constructor(private currentError : unknown) {}
17+
18+
/** Marks the error as handled */
19+
private markHandled() : void {
20+
this.handled = true;
21+
}
22+
23+
/**
24+
* Checks if the current error is an instance of the given class
25+
* and calls the callback if it matches.
26+
*
27+
* @param errorClass The constructor of the error class
28+
* @param callback Function to handle the error if it matches
29+
*/
30+
private handleOnce<ErrorType extends Error>(
31+
errorClass : new (...args : string[]) => ErrorType,
32+
callback : (error : ErrorType) => void
33+
) : void {
34+
if (!this.handled && this.currentError instanceof errorClass) {
35+
callback(this.currentError as ErrorType);
36+
this.markHandled();
37+
}
38+
this.scheduleDone();
39+
}
40+
41+
/** Checks if the error has been handled and throws it otherwise */
42+
private done() : void {
43+
if (!this.handled) {
44+
throw this.currentError;
45+
}
46+
}
47+
48+
/**
49+
* Schedules an asynchronous call to `done()` after the current call stack,
50+
* ensuring automatic check at the end of the chain.
51+
*/
52+
private scheduleDone() : void {
53+
if (!this.scheduled) {
54+
this.scheduled = true;
55+
setTimeout(() => {
56+
this.done();
57+
}, 0);
58+
}
59+
}
60+
61+
/**
62+
* Handles the error if it is a SyntaxError.
63+
*
64+
* @param callback Function that handles the SyntaxError
65+
*/
66+
syntax(callback : (error : SyntaxError) => void) : this {
67+
this.handleOnce(SyntaxError, callback);
68+
return this;
69+
}
70+
71+
/**
72+
* Handles the error if it is a TypeError.
73+
*
74+
* @param callback Function that handles the TypeError
75+
*/
76+
type(callback : (error : TypeError) => void) : this {
77+
this.handleOnce(TypeError, callback);
78+
return this;
79+
}
80+
81+
/**
82+
* Handles the error if it is a ReferenceError.
83+
*
84+
* @param callback Function that handles the ReferenceError
85+
*/
86+
reference(callback : (error : ReferenceError) => void) : this {
87+
this.handleOnce(ReferenceError, callback);
88+
return this;
89+
}
90+
91+
/**
92+
* Handles the error if it is a RangeError.
93+
*
94+
* @param callback Function that handles the RangeError
95+
*/
96+
range(callback : (error : RangeError) => void) : this {
97+
this.handleOnce(RangeError, callback);
98+
return this;
99+
}
100+
101+
/**
102+
* Handles the error if it is a URIError.
103+
*
104+
* @param callback Function that handles the URIError
105+
*/
106+
uri(callback : (error : URIError) => void) : this {
107+
this.handleOnce(URIError, callback);
108+
return this;
109+
}
110+
111+
/**
112+
* Handles the error if it is a EvalError.
113+
*
114+
* @param callback Function that handles the EvalError
115+
*/
116+
eval(callback : (error : EvalError) => void) : this {
117+
this.handleOnce(EvalError, callback);
118+
return this;
119+
}
120+
121+
/**
122+
* Handles the error if it is an instance of the provided error class.
123+
* Supports custom errors as well.
124+
*
125+
* @param errorClass The constructor of the error class
126+
* @param callback Function to handle the error if it matches
127+
*/
128+
catch<ErrorType extends Error>(
129+
errorClass : new (...args : unknown[]) => ErrorType,
130+
callback : (error : ErrorType) => void
131+
): this {
132+
this.handleOnce(errorClass, callback);
133+
return this;
134+
}
135+
136+
/**
137+
* Fallback handler: called if no previous handler matched the error.
138+
*
139+
* @param callback Function that handles the error
140+
*/
141+
otherwise(callback : (error : unknown) => void) : this {
142+
if (!this.handled) {
143+
callback(this.currentError);
144+
this.markHandled();
145+
}
146+
return this;
147+
}
148+
}
149+
150+
/**
151+
* Creates a new ErrorHandler for the given error and returns a Proxy
152+
* that supports fluent API and method chaining.
153+
*
154+
* @param error The error object (unknown)
155+
* @returns ErrorHandler Proxy for fluent chaining
156+
*/
157+
export function error(error : unknown): ErrorHandler {
158+
const handler = new ErrorHandler(error);
159+
160+
return new Proxy(handler, {
161+
// deno-lint-ignore no-explicit-any
162+
get(target, prop, receiver) : any {
163+
// deno-lint-ignore no-explicit-any
164+
const orig = (target as any)[prop];
165+
if (typeof orig === "function") {
166+
return (...args: unknown[]) => {
167+
orig.apply(target, args);
168+
return receiver;
169+
};
170+
}
171+
return orig;
172+
},
173+
});
174+
}

0 commit comments

Comments
 (0)