catch-match 2.0.1 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +47 -0
- package/package.json +8 -2
- package/src/__tests__/main.test.ts +485 -206
- package/src/main.ts +104 -48
package/README.md
CHANGED
@@ -39,6 +39,10 @@ try {
|
|
39
39
|
//> final
|
40
40
|
```
|
41
41
|
|
42
|
+
## Features
|
43
|
+
|
44
|
+
Supporting sync/async functions
|
45
|
+
|
42
46
|
## Getting started
|
43
47
|
|
44
48
|
```shell
|
@@ -100,3 +104,46 @@ const result = $try(() => {
|
|
100
104
|
|
101
105
|
console.log(result); // { error: SyntaxError, result: undefined }
|
102
106
|
```
|
107
|
+
|
108
|
+
## Promises example
|
109
|
+
|
110
|
+
```typescript
|
111
|
+
class AuthError extends Error {}
|
112
|
+
|
113
|
+
function proc(event: string) {
|
114
|
+
return $try(() => new Promise((resolve, reject) => {
|
115
|
+
switch (event) {
|
116
|
+
case 'resolve':
|
117
|
+
resolve('resolved')
|
118
|
+
break;
|
119
|
+
case 'reject':
|
120
|
+
reject('rejected')
|
121
|
+
break;
|
122
|
+
case 'syntax':
|
123
|
+
throw SyntaxError
|
124
|
+
case 'auth':
|
125
|
+
throw AuthError
|
126
|
+
case 'error':
|
127
|
+
throw 'error'
|
128
|
+
default:
|
129
|
+
throw 'other errors'
|
130
|
+
}
|
131
|
+
}).catch('error', () => {
|
132
|
+
// console.log('error')
|
133
|
+
}).catch([SyntaxError, AuthError], (error) => {
|
134
|
+
// console.log(error)
|
135
|
+
}).other((error) => {
|
136
|
+
// console.log(error)
|
137
|
+
}).finally(({ value, error }) => {
|
138
|
+
// console.log({ value, error })
|
139
|
+
})
|
140
|
+
}
|
141
|
+
|
142
|
+
await proc('resolve') // { value: 'resolved' }}
|
143
|
+
await proc('reject') // { error: 'rejected' }
|
144
|
+
|
145
|
+
await proc('syntax') // { error: SyntaxError }
|
146
|
+
await proc('auth') // { error: AuthError }
|
147
|
+
await proc('error') // { error: 'error' }
|
148
|
+
await proc('other') // { error: 'other errors' }
|
149
|
+
```
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "catch-match",
|
3
|
-
"version": "
|
3
|
+
"version": "3.0.0",
|
4
4
|
"repository": {
|
5
5
|
"url": "https://github.com/kobzarvs/catch-match"
|
6
6
|
},
|
@@ -12,7 +12,13 @@
|
|
12
12
|
"errors",
|
13
13
|
"exceptions",
|
14
14
|
"throw",
|
15
|
-
"finally"
|
15
|
+
"finally",
|
16
|
+
"promises",
|
17
|
+
"resolve",
|
18
|
+
"reject",
|
19
|
+
"flow",
|
20
|
+
"control",
|
21
|
+
"process"
|
16
22
|
],
|
17
23
|
"main": "dist/main.js",
|
18
24
|
"scripts": {
|
@@ -1,223 +1,502 @@
|
|
1
|
-
import $try from '../main';
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
});
|
28
|
-
|
29
|
-
test('should be match single exception', () => {
|
30
|
-
let matchReferenceError = jest.fn();
|
31
|
-
let matchArrayOfErrors = jest.fn();
|
32
|
-
let matchOther = jest.fn();
|
33
|
-
let matchFinally = jest.fn();
|
34
|
-
|
35
|
-
const result = $try(() => {
|
36
|
-
throw ReferenceError;
|
37
|
-
}).catch(ReferenceError, () => {
|
38
|
-
matchReferenceError();
|
39
|
-
}).catch([TypeError, SyntaxError], () => {
|
40
|
-
matchArrayOfErrors();
|
41
|
-
}).other((error) => {
|
42
|
-
matchOther(error);
|
43
|
-
}).finally(({ result, error }) => {
|
44
|
-
matchFinally({ result, error });
|
45
|
-
return result;
|
46
|
-
});
|
47
|
-
|
48
|
-
expect(matchReferenceError).toBeCalled();
|
49
|
-
expect(matchArrayOfErrors).not.toBeCalled();
|
50
|
-
expect(matchOther).not.toBeCalled();
|
51
|
-
expect(matchFinally).toBeCalled();
|
52
|
-
expect(result).toEqual({ error: ReferenceError, result: undefined });
|
53
|
-
});
|
54
|
-
|
55
|
-
test('should be match array of exceptions', () => {
|
56
|
-
let matchReferenceError = jest.fn();
|
57
|
-
let matchArrayOfErrors = jest.fn();
|
58
|
-
let matchOther = jest.fn();
|
59
|
-
let matchFinally = jest.fn();
|
60
|
-
|
61
|
-
const result = $try(() => {
|
62
|
-
throw SyntaxError;
|
63
|
-
}).catch(ReferenceError, () => {
|
64
|
-
matchReferenceError();
|
65
|
-
}).catch([TypeError, SyntaxError], () => {
|
66
|
-
matchArrayOfErrors();
|
67
|
-
}).other((error) => {
|
68
|
-
matchOther(error);
|
69
|
-
}).finally(({ result, error }) => {
|
70
|
-
matchFinally({ result, error });
|
71
|
-
return result;
|
72
|
-
});
|
73
|
-
|
74
|
-
expect(matchReferenceError).not.toBeCalled();
|
75
|
-
expect(matchArrayOfErrors).toBeCalled();
|
76
|
-
expect(matchOther).not.toBeCalled();
|
77
|
-
expect(matchFinally).toBeCalled();
|
78
|
-
expect(result).toEqual({ error: SyntaxError, result: undefined });
|
79
|
-
});
|
80
|
-
|
81
|
-
test('should be match any type of exception', () => {
|
82
|
-
let matchReferenceError = jest.fn();
|
83
|
-
let matchArrayOfErrors = jest.fn();
|
84
|
-
let matchOther = jest.fn();
|
85
|
-
let matchFinally = jest.fn();
|
86
|
-
|
87
|
-
const result = $try(() => {
|
88
|
-
throw 'error';
|
89
|
-
}).catch(ReferenceError, () => {
|
90
|
-
matchReferenceError();
|
91
|
-
}).catch([TypeError, SyntaxError], () => {
|
92
|
-
matchArrayOfErrors();
|
93
|
-
}).other((error) => {
|
94
|
-
matchOther(error);
|
95
|
-
}).finally(({ result, error }) => {
|
96
|
-
matchFinally({ result, error });
|
97
|
-
return result;
|
98
|
-
});
|
99
|
-
|
100
|
-
expect(matchReferenceError).not.toBeCalled();
|
101
|
-
expect(matchArrayOfErrors).not.toBeCalled();
|
102
|
-
expect(matchOther).toBeCalled();
|
103
|
-
expect(matchFinally).toBeCalled();
|
104
|
-
expect(result).toEqual({ error: 'error', result: undefined });
|
105
|
-
});
|
106
|
-
|
107
|
-
test('should be match custom exceptions', () => {
|
108
|
-
let matchCustomError = jest.fn();
|
109
|
-
let matchArrayOfErrors = jest.fn();
|
110
|
-
let matchOther = jest.fn();
|
111
|
-
let matchFinally = jest.fn();
|
112
|
-
|
113
|
-
class CustomError extends Error {
|
114
|
-
}
|
115
|
-
|
116
|
-
const result = $try(() => {
|
117
|
-
throw CustomError;
|
118
|
-
}).catch(CustomError, () => {
|
119
|
-
matchCustomError();
|
120
|
-
}).catch([TypeError, SyntaxError], () => {
|
121
|
-
matchArrayOfErrors();
|
122
|
-
}).other((error) => {
|
123
|
-
matchOther(error);
|
124
|
-
}).finally(({ result, error }) => {
|
125
|
-
matchFinally({ result, error });
|
126
|
-
return result;
|
127
|
-
});
|
128
|
-
|
129
|
-
expect(matchCustomError).toBeCalled();
|
130
|
-
expect(matchArrayOfErrors).not.toBeCalled();
|
131
|
-
expect(matchOther).not.toBeCalled();
|
132
|
-
expect(matchFinally).toBeCalled();
|
133
|
-
expect(result).toEqual({ error: CustomError, result: undefined });
|
134
|
-
});
|
135
|
-
|
136
|
-
test('should be return result from `finally` branch without `other`', () => {
|
137
|
-
let matchCustomError = jest.fn();
|
138
|
-
let matchArrayOfErrors = jest.fn();
|
139
|
-
let matchOther = jest.fn();
|
140
|
-
let matchFinally = jest.fn();
|
141
|
-
|
142
|
-
class CustomError extends Error {
|
143
|
-
}
|
144
|
-
|
145
|
-
const result = $try(() => {
|
146
|
-
throw CustomError;
|
147
|
-
}).catch([TypeError, SyntaxError], () => {
|
148
|
-
matchArrayOfErrors();
|
149
|
-
}).finally(({ result, error }) => {
|
150
|
-
matchFinally({ result, error });
|
151
|
-
return result;
|
152
|
-
});
|
153
|
-
|
154
|
-
expect(matchCustomError).not.toBeCalled();
|
155
|
-
expect(matchArrayOfErrors).not.toBeCalled();
|
156
|
-
expect(matchOther).not.toBeCalled();
|
157
|
-
expect(matchFinally).toBeCalled();
|
158
|
-
expect(result).toEqual({ error: CustomError, result: undefined });
|
159
|
-
});
|
160
|
-
|
161
|
-
|
162
|
-
test('should be return result from `catch` branch', () => {
|
163
|
-
let matchCustomError = jest.fn();
|
164
|
-
let matchArrayOfErrors = jest.fn();
|
165
|
-
let matchOther = jest.fn();
|
166
|
-
let matchFinally = jest.fn();
|
1
|
+
import $try, { PromisedTryReturn } from '../main';
|
2
|
+
|
3
|
+
describe('sync version', () => {
|
4
|
+
test('should be return result from `finally` branch', () => {
|
5
|
+
let matchReferenceError = jest.fn();
|
6
|
+
let matchArrayOfErrors = jest.fn();
|
7
|
+
let matchOther = jest.fn();
|
8
|
+
let matchFinally = jest.fn();
|
9
|
+
|
10
|
+
const result = $try(() => {
|
11
|
+
return [1, 2, 3];
|
12
|
+
}).catch(ReferenceError, () => {
|
13
|
+
matchReferenceError();
|
14
|
+
}).catch([TypeError, SyntaxError], (error) => {
|
15
|
+
matchArrayOfErrors(error);
|
16
|
+
}).other((error) => {
|
17
|
+
matchOther(error);
|
18
|
+
}).finally(({ value, error }) => { //?
|
19
|
+
matchFinally({ value, error });
|
20
|
+
});
|
21
|
+
|
22
|
+
expect(matchReferenceError).not.toBeCalled();
|
23
|
+
expect(matchArrayOfErrors).not.toBeCalled();
|
24
|
+
expect(matchOther).not.toBeCalled();
|
25
|
+
expect(matchFinally).toBeCalled();
|
26
|
+
expect(result).toMatchObject({ error: undefined, value: [1, 2, 3] });
|
27
|
+
});
|
167
28
|
|
168
|
-
|
169
|
-
|
29
|
+
test('should be match single exception', () => {
|
30
|
+
let matchReferenceError = jest.fn();
|
31
|
+
let matchArrayOfErrors = jest.fn();
|
32
|
+
let matchOther = jest.fn();
|
33
|
+
let matchFinally = jest.fn();
|
34
|
+
|
35
|
+
const result = $try(() => {
|
36
|
+
throw ReferenceError;
|
37
|
+
}).catch(ReferenceError, () => {
|
38
|
+
matchReferenceError();
|
39
|
+
}).catch([TypeError, SyntaxError], (error) => {
|
40
|
+
matchArrayOfErrors(error);
|
41
|
+
}).other((error) => {
|
42
|
+
matchOther(error);
|
43
|
+
}).finally(({ value, error }) => {
|
44
|
+
matchFinally({ value, error });
|
45
|
+
return value; // ?
|
46
|
+
});
|
47
|
+
|
48
|
+
expect(matchReferenceError).toBeCalled();
|
49
|
+
expect(matchArrayOfErrors).not.toBeCalled();
|
50
|
+
expect(matchOther).not.toBeCalled();
|
51
|
+
expect(matchFinally).toBeCalled();
|
52
|
+
expect(result).toMatchObject({ error: ReferenceError, value: undefined });
|
53
|
+
});
|
170
54
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
55
|
+
test('should be match array of exceptions', () => {
|
56
|
+
let matchReferenceError = jest.fn();
|
57
|
+
let matchArrayOfErrors = jest.fn();
|
58
|
+
let matchOther = jest.fn();
|
59
|
+
let matchFinally = jest.fn();
|
60
|
+
|
61
|
+
const result = $try(() => {
|
62
|
+
throw SyntaxError;
|
63
|
+
}).catch(ReferenceError, () => {
|
64
|
+
matchReferenceError();
|
65
|
+
}).catch([TypeError, SyntaxError], (error) => {
|
66
|
+
matchArrayOfErrors(error);
|
67
|
+
}).other((error) => {
|
68
|
+
matchOther(error);
|
69
|
+
}).finally(({ value, error }) => {
|
70
|
+
matchFinally({ value, error });
|
71
|
+
return value; // ?
|
72
|
+
});
|
73
|
+
|
74
|
+
expect(matchReferenceError).not.toBeCalled();
|
75
|
+
expect(matchArrayOfErrors).toBeCalledWith(SyntaxError);
|
76
|
+
expect(matchOther).not.toBeCalled();
|
77
|
+
expect(matchFinally).toBeCalled();
|
78
|
+
expect(result).toMatchObject({ error: SyntaxError, value: undefined });
|
175
79
|
});
|
176
80
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
81
|
+
test('should be match any type of exception', () => {
|
82
|
+
let matchReferenceError = jest.fn();
|
83
|
+
let matchArrayOfErrors = jest.fn();
|
84
|
+
let matchOther = jest.fn();
|
85
|
+
let matchFinally = jest.fn();
|
86
|
+
|
87
|
+
const result = $try(() => {
|
88
|
+
throw 'error';
|
89
|
+
}).catch(ReferenceError, () => {
|
90
|
+
matchReferenceError();
|
91
|
+
}).catch([TypeError, SyntaxError], (error) => {
|
92
|
+
matchArrayOfErrors(error);
|
93
|
+
}).other((error) => {
|
94
|
+
matchOther(error);
|
95
|
+
}).finally(({ value, error }) => {
|
96
|
+
matchFinally({ value, error });
|
97
|
+
return value; // ?
|
98
|
+
});
|
99
|
+
|
100
|
+
expect(matchReferenceError).not.toBeCalled();
|
101
|
+
expect(matchArrayOfErrors).not.toBeCalled();
|
102
|
+
expect(matchOther).toBeCalled();
|
103
|
+
expect(matchFinally).toBeCalled();
|
104
|
+
expect(result).toMatchObject({ error: 'error', value: undefined });
|
105
|
+
});
|
183
106
|
|
107
|
+
test('should be match custom exceptions', () => {
|
108
|
+
let matchCustomError = jest.fn();
|
109
|
+
let matchArrayOfErrors = jest.fn();
|
110
|
+
let matchOther = jest.fn();
|
111
|
+
let matchFinally = jest.fn();
|
112
|
+
|
113
|
+
class CustomError extends Error {
|
114
|
+
}
|
115
|
+
|
116
|
+
const result = $try(() => {
|
117
|
+
throw CustomError;
|
118
|
+
}).catch(CustomError, () => {
|
119
|
+
matchCustomError();
|
120
|
+
}).catch([TypeError, SyntaxError], (error) => {
|
121
|
+
matchArrayOfErrors(error);
|
122
|
+
}).other((error) => {
|
123
|
+
matchOther(error);
|
124
|
+
}).finally(({ value, error }) => {
|
125
|
+
matchFinally({ value, error });
|
126
|
+
});
|
127
|
+
|
128
|
+
expect(matchCustomError).toBeCalled();
|
129
|
+
expect(matchArrayOfErrors).not.toBeCalled();
|
130
|
+
expect(matchOther).not.toBeCalled();
|
131
|
+
expect(matchFinally).toBeCalled();
|
132
|
+
expect(result).toMatchObject({ error: CustomError, value: undefined });
|
133
|
+
});
|
184
134
|
|
185
|
-
test('should be return result from `
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
135
|
+
test('should be return result from `finally` branch without `other`', () => {
|
136
|
+
let matchCustomError = jest.fn();
|
137
|
+
let matchArrayOfErrors = jest.fn();
|
138
|
+
let matchOther = jest.fn();
|
139
|
+
let matchFinally = jest.fn();
|
140
|
+
|
141
|
+
class CustomError extends Error {
|
142
|
+
}
|
143
|
+
|
144
|
+
const result = $try(() => {
|
145
|
+
throw CustomError;
|
146
|
+
}).catch([TypeError, SyntaxError], (error) => {
|
147
|
+
matchArrayOfErrors(error);
|
148
|
+
}).finally(({ value, error }) => {
|
149
|
+
matchFinally({ value, error });
|
150
|
+
return value; // ?
|
151
|
+
});
|
152
|
+
|
153
|
+
expect(matchCustomError).not.toBeCalled();
|
154
|
+
expect(matchArrayOfErrors).not.toBeCalled();
|
155
|
+
expect(matchOther).not.toBeCalled();
|
156
|
+
expect(matchFinally).toBeCalled();
|
157
|
+
expect(result).toMatchObject({ error: CustomError, value: undefined });
|
158
|
+
});
|
190
159
|
|
191
|
-
|
192
|
-
|
160
|
+
test('should be return result from `catch` branch', () => {
|
161
|
+
let matchCustomError = jest.fn();
|
162
|
+
let matchArrayOfErrors = jest.fn();
|
163
|
+
let matchOther = jest.fn();
|
164
|
+
let matchFinally = jest.fn();
|
165
|
+
|
166
|
+
class CustomError extends Error {
|
167
|
+
}
|
168
|
+
|
169
|
+
const result = $try(() => {
|
170
|
+
throw CustomError;
|
171
|
+
}).catch([TypeError, SyntaxError], (error) => {
|
172
|
+
matchArrayOfErrors(error);
|
173
|
+
});
|
174
|
+
|
175
|
+
expect(matchCustomError).not.toBeCalled();
|
176
|
+
expect(matchArrayOfErrors).not.toBeCalled();
|
177
|
+
expect(matchOther).not.toBeCalled();
|
178
|
+
expect(matchFinally).not.toBeCalled();
|
179
|
+
expect(result).toMatchObject({ error: CustomError, value: undefined });
|
180
|
+
});
|
193
181
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
matchOther(
|
182
|
+
test('should be return result from `other` branch', () => {
|
183
|
+
let matchCustomError = jest.fn();
|
184
|
+
let matchArrayOfErrors = jest.fn();
|
185
|
+
let matchOther = jest.fn();
|
186
|
+
let matchFinally = jest.fn();
|
187
|
+
|
188
|
+
class CustomError extends Error {
|
189
|
+
}
|
190
|
+
|
191
|
+
const result = $try(() => {
|
192
|
+
throw CustomError;
|
193
|
+
}).other((error) => {
|
194
|
+
matchOther(error);
|
195
|
+
});
|
196
|
+
|
197
|
+
expect(matchCustomError).not.toBeCalled();
|
198
|
+
expect(matchArrayOfErrors).not.toBeCalled();
|
199
|
+
expect(matchOther).toBeCalledWith(CustomError);
|
200
|
+
expect(matchFinally).not.toBeCalled();
|
201
|
+
expect(result).toMatchObject({ error: CustomError, value: undefined });
|
198
202
|
});
|
199
203
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
204
|
+
test('should be return result without branches', () => {
|
205
|
+
let matchCustomError = jest.fn();
|
206
|
+
let matchArrayOfErrors = jest.fn();
|
207
|
+
let matchOther = jest.fn();
|
208
|
+
let matchFinally = jest.fn();
|
209
|
+
|
210
|
+
const result = $try(() => {
|
211
|
+
throw SyntaxError;
|
212
|
+
});
|
213
|
+
|
214
|
+
expect(matchCustomError).not.toBeCalled();
|
215
|
+
expect(matchArrayOfErrors).not.toBeCalled();
|
216
|
+
expect(matchOther).not.toBeCalled();
|
217
|
+
expect(matchFinally).not.toBeCalled();
|
218
|
+
expect(result).toMatchObject({ error: SyntaxError, value: undefined });
|
219
|
+
});
|
205
220
|
});
|
206
221
|
|
222
|
+
/**
|
223
|
+
* async tests
|
224
|
+
*/
|
225
|
+
describe('promised version', () => {
|
226
|
+
test('resolve try', async () => {
|
227
|
+
let matchCustomError = jest.fn();
|
228
|
+
let matchArrayOfErrors = jest.fn();
|
229
|
+
let matchOther = jest.fn();
|
230
|
+
let matchFinally = jest.fn();
|
231
|
+
|
232
|
+
const result = $try(() => {
|
233
|
+
return Promise.resolve(42);
|
234
|
+
});
|
235
|
+
|
236
|
+
await result;
|
237
|
+
|
238
|
+
expect(matchCustomError).not.toBeCalled();
|
239
|
+
expect(matchArrayOfErrors).not.toBeCalled();
|
240
|
+
expect(matchOther).not.toBeCalled();
|
241
|
+
expect(matchFinally).not.toBeCalled();
|
242
|
+
|
243
|
+
expect(result).toBeInstanceOf(Promise);
|
244
|
+
expect(await result).toEqual({
|
245
|
+
value: 42,
|
246
|
+
error: undefined,
|
247
|
+
});
|
248
|
+
});
|
249
|
+
test('reject try', async () => {
|
250
|
+
let matchCustomError = jest.fn();
|
251
|
+
let matchArrayOfErrors = jest.fn();
|
252
|
+
let matchOther = jest.fn();
|
253
|
+
let matchFinally = jest.fn();
|
254
|
+
|
255
|
+
const result = $try(() => {
|
256
|
+
return Promise.reject(42);
|
257
|
+
});
|
258
|
+
|
259
|
+
expect(matchCustomError).not.toBeCalled();
|
260
|
+
expect(matchArrayOfErrors).not.toBeCalled();
|
261
|
+
expect(matchOther).not.toBeCalled();
|
262
|
+
expect(matchFinally).not.toBeCalled();
|
263
|
+
|
264
|
+
expect(result).toBeInstanceOf(Promise);
|
265
|
+
expect(await result).toEqual({
|
266
|
+
value: undefined,
|
267
|
+
error: 42,
|
268
|
+
});
|
269
|
+
});
|
270
|
+
test('throw try', async () => {
|
271
|
+
const result = $try(() => {
|
272
|
+
return new Promise(() => {
|
273
|
+
throw new Error('error');
|
274
|
+
});
|
275
|
+
});
|
276
|
+
|
277
|
+
expect(result).toBeInstanceOf(Promise);
|
278
|
+
|
279
|
+
expect(await result).toEqual({
|
280
|
+
value: undefined,
|
281
|
+
error: Error('error'),
|
282
|
+
});
|
283
|
+
});
|
207
284
|
|
208
|
-
test('
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
285
|
+
test('resolve try.catch', async () => {
|
286
|
+
let matchError = jest.fn();
|
287
|
+
let matchSyntaxError = jest.fn();
|
288
|
+
let matchOther = jest.fn();
|
289
|
+
|
290
|
+
const result = $try(() => {
|
291
|
+
return Promise.resolve(42);
|
292
|
+
}).catch(Error, () => {
|
293
|
+
matchError();
|
294
|
+
}).catch(SyntaxError, () => {
|
295
|
+
matchSyntaxError();
|
296
|
+
}).other((error) => {
|
297
|
+
matchOther(error);
|
298
|
+
});
|
299
|
+
|
300
|
+
expect(matchError).not.toBeCalled();
|
301
|
+
expect(matchSyntaxError).not.toBeCalled();
|
302
|
+
expect(matchOther).not.toBeCalled();
|
303
|
+
|
304
|
+
expect(result).toBeInstanceOf(Promise);
|
305
|
+
expect(await result).toEqual({
|
306
|
+
value: 42,
|
307
|
+
error: undefined,
|
308
|
+
});
|
309
|
+
});
|
310
|
+
test('reject try.catch', async () => {
|
311
|
+
let matchError = jest.fn();
|
312
|
+
let matchOther = jest.fn();
|
313
|
+
|
314
|
+
const result = $try(() => {
|
315
|
+
return Promise.reject(123);
|
316
|
+
}).catch(Error, () => {
|
317
|
+
matchOther();
|
318
|
+
}).catch(123, () => {
|
319
|
+
matchError();
|
320
|
+
}).catch('error', () => {
|
321
|
+
matchOther();
|
322
|
+
});
|
323
|
+
|
324
|
+
await result; //?
|
325
|
+
|
326
|
+
expect(matchOther).not.toBeCalled();
|
327
|
+
expect(matchError).toBeCalled();
|
328
|
+
|
329
|
+
expect(result).toBeInstanceOf(Promise);
|
330
|
+
expect(await result).toEqual({
|
331
|
+
value: undefined,
|
332
|
+
error: 123,
|
333
|
+
});
|
334
|
+
});
|
335
|
+
test('throw try.catch', async () => {
|
336
|
+
let matchError = jest.fn();
|
337
|
+
let matchOther = jest.fn();
|
338
|
+
|
339
|
+
const result = $try(() => {
|
340
|
+
return new Promise(() => {
|
341
|
+
throw 'error';
|
342
|
+
});
|
343
|
+
}).catch(Error, () => {
|
344
|
+
matchOther();
|
345
|
+
}).catch(123, () => {
|
346
|
+
matchError();
|
347
|
+
}).catch('error', () => {
|
348
|
+
matchOther();
|
349
|
+
});
|
350
|
+
|
351
|
+
expect(result).toBeInstanceOf(Promise);
|
352
|
+
expect(await result).toEqual({
|
353
|
+
value: undefined,
|
354
|
+
error: 'error',
|
355
|
+
});
|
356
|
+
|
357
|
+
expect(matchOther).toBeCalledTimes(1);
|
358
|
+
expect(matchError).not.toBeCalled();
|
359
|
+
});
|
213
360
|
|
214
|
-
|
215
|
-
|
361
|
+
test('resolve try.other', async () => {
|
362
|
+
let matchCustomError = jest.fn();
|
363
|
+
let matchArrayOfErrors = jest.fn();
|
364
|
+
let matchOther = jest.fn();
|
365
|
+
let matchFinally = jest.fn();
|
366
|
+
|
367
|
+
const result = $try(() => {
|
368
|
+
return Promise.resolve('ok');
|
369
|
+
}).other(({ value, error }) => {
|
370
|
+
matchOther({ value, error });
|
371
|
+
});
|
372
|
+
|
373
|
+
expect(result).toBeInstanceOf(Promise);
|
374
|
+
expect(await result).toEqual({
|
375
|
+
value: 'ok',
|
376
|
+
error: undefined,
|
377
|
+
});
|
378
|
+
|
379
|
+
expect(matchCustomError).not.toBeCalled();
|
380
|
+
expect(matchArrayOfErrors).not.toBeCalled();
|
381
|
+
expect(matchOther).not.toBeCalled();
|
382
|
+
expect(matchFinally).not.toBeCalled();
|
383
|
+
});
|
384
|
+
test('reject try.other', async () => {
|
385
|
+
let matchError = jest.fn();
|
386
|
+
let matchOther = jest.fn();
|
387
|
+
|
388
|
+
const result = $try(() => {
|
389
|
+
return Promise.reject('error');
|
390
|
+
}).catch('error1', () => {
|
391
|
+
matchError();
|
392
|
+
}).catch('error2', () => {
|
393
|
+
matchError();
|
394
|
+
}).other((error) => {
|
395
|
+
matchOther(error);
|
396
|
+
});
|
397
|
+
|
398
|
+
expect(result).toBeInstanceOf(Promise);
|
399
|
+
expect(await result).toEqual({
|
400
|
+
value: undefined,
|
401
|
+
error: 'error',
|
402
|
+
});
|
403
|
+
|
404
|
+
expect(matchError).not.toBeCalled();
|
405
|
+
expect(matchOther).toBeCalledWith('error');
|
406
|
+
});
|
407
|
+
test('throw try.other', async () => {
|
408
|
+
let matchError = jest.fn();
|
409
|
+
let matchOther = jest.fn();
|
410
|
+
|
411
|
+
const result = $try(() => {
|
412
|
+
return new Promise(() => {
|
413
|
+
throw 'error';
|
414
|
+
});
|
415
|
+
}).catch('error1', () => {
|
416
|
+
matchError();
|
417
|
+
}).catch('error2', () => {
|
418
|
+
matchError();
|
419
|
+
}).other((error) => {
|
420
|
+
matchOther(error);
|
421
|
+
});
|
422
|
+
|
423
|
+
expect(result).toBeInstanceOf(Promise);
|
424
|
+
expect(await result).toEqual({
|
425
|
+
value: undefined,
|
426
|
+
error: 'error',
|
427
|
+
});
|
428
|
+
|
429
|
+
expect(matchError).not.toBeCalled();
|
430
|
+
expect(matchOther).toBeCalledWith('error');
|
216
431
|
});
|
217
432
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
433
|
+
test('when throw should be match array or exception', async () => {
|
434
|
+
let matchSingleError = jest.fn();
|
435
|
+
let matchArrayError = jest.fn();
|
436
|
+
let matchOther = jest.fn();
|
437
|
+
let matchFinally = jest.fn();
|
438
|
+
|
439
|
+
const attach = (ctx: PromisedTryReturn<any>) => {
|
440
|
+
return ctx.catch(SyntaxError, () => {
|
441
|
+
matchSingleError(SyntaxError);
|
442
|
+
}).catch([ReferenceError, SyntaxError], (error) => {
|
443
|
+
matchArrayError(error);
|
444
|
+
}).other((error) => {
|
445
|
+
matchOther(error);
|
446
|
+
}).finally(({ value, error }) => {
|
447
|
+
matchFinally({ value, error });
|
448
|
+
});
|
449
|
+
};
|
450
|
+
|
451
|
+
const testSingle = $try(() => new Promise(() => {
|
452
|
+
throw SyntaxError;
|
453
|
+
}));
|
454
|
+
|
455
|
+
const testArray = $try(() => new Promise(() => {
|
456
|
+
throw ReferenceError;
|
457
|
+
}));
|
458
|
+
|
459
|
+
const testOther = $try(() => new Promise(() => {
|
460
|
+
throw TypeError;
|
461
|
+
}));
|
462
|
+
|
463
|
+
const testResolve = $try(() => new Promise((resolve) => {
|
464
|
+
resolve('ok');
|
465
|
+
}));
|
466
|
+
|
467
|
+
const testReject = $try(() => new Promise((_, reject) => {
|
468
|
+
reject('reject');
|
469
|
+
}));
|
470
|
+
|
471
|
+
const resultSingle = attach(testSingle);
|
472
|
+
const resultArray = attach(testArray);
|
473
|
+
const resultOther = attach(testOther);
|
474
|
+
const resultResolve = attach(testResolve);
|
475
|
+
const resultReject = attach(testReject);
|
476
|
+
|
477
|
+
expect(resultSingle).toBeInstanceOf(Promise);
|
478
|
+
expect(resultArray).toBeInstanceOf(Promise);
|
479
|
+
expect(resultOther).toBeInstanceOf(Promise);
|
480
|
+
expect(resultResolve).toBeInstanceOf(Promise);
|
481
|
+
expect(resultReject).toBeInstanceOf(Promise);
|
482
|
+
|
483
|
+
expect(await resultSingle).toEqual({
|
484
|
+
value: undefined,
|
485
|
+
error: SyntaxError,
|
486
|
+
});
|
487
|
+
expect(await resultArray).toEqual({
|
488
|
+
value: undefined,
|
489
|
+
error: ReferenceError,
|
490
|
+
});
|
491
|
+
expect(await resultOther).toEqual({
|
492
|
+
value: undefined,
|
493
|
+
error: TypeError,
|
494
|
+
});
|
495
|
+
expect(await resultResolve).toEqual({
|
496
|
+
value: 'ok',
|
497
|
+
});
|
498
|
+
expect(await resultReject).toEqual({
|
499
|
+
error: 'reject',
|
500
|
+
});
|
501
|
+
});
|
223
502
|
});
|
package/src/main.ts
CHANGED
@@ -1,71 +1,127 @@
|
|
1
|
-
export type
|
2
|
-
result?: Rsult;
|
3
|
-
error?: ErrorType;
|
4
|
-
};
|
1
|
+
export type ErrrorHandler<ErrorType> = (error?: ErrorType) => void
|
5
2
|
|
6
|
-
export type
|
3
|
+
export type FinallyCallback<Result, ErrorType = any> = (params: ResultType<Result, ErrorType>) => void
|
7
4
|
|
8
|
-
export type
|
5
|
+
export type TryBody<Result> = () => Result | Promise<Result> | never
|
9
6
|
|
10
|
-
export type
|
11
|
-
|
12
|
-
|
13
|
-
finally: (callback?: FinallyCallback<Result, ErrorType>) => ResultType<Result, ErrorType>,
|
14
|
-
result: Result,
|
15
|
-
error: ErrorType
|
7
|
+
export type ResultType<Result, ErrorType = any> = {
|
8
|
+
value?: Result;
|
9
|
+
error?: ErrorType;
|
16
10
|
}
|
17
11
|
|
18
|
-
export type
|
12
|
+
export type FinallyReturn<Return, ErrorType = any> =
|
13
|
+
ResultType<Return, ErrorType>
|
14
|
+
|
15
|
+
export type OtherReturn<Return, ErrorType = any> =
|
16
|
+
FinallyReturn<Return, ErrorType> &
|
17
|
+
{
|
18
|
+
finally: (callback: FinallyCallback<Return, ErrorType>) => ResultType<Return, ErrorType>
|
19
|
+
}
|
20
|
+
|
21
|
+
export type CatchReturn<Return, ErrorType = any> =
|
22
|
+
FinallyReturn<Return, ErrorType> &
|
23
|
+
OtherReturn<Return, ErrorType> &
|
24
|
+
{
|
25
|
+
catch: (error: ErrorType | ErrorType[], handler: ErrrorHandler<ErrorType>) => TryReturn<Return, ErrorType>;
|
26
|
+
other: (handler: ErrrorHandler<ErrorType>) => Pick<TryReturn<Return, ErrorType>, 'finally' | 'value' | 'error'>,
|
27
|
+
}
|
28
|
+
|
29
|
+
export type TryReturn<Return, ErrorType = any> =
|
30
|
+
CatchReturn<Return, ErrorType>
|
19
31
|
|
20
|
-
export
|
32
|
+
export type PromisedTryReturn<Return> =
|
33
|
+
TryReturn<Return> |
|
34
|
+
(Promise<ResultType<Return>> & TryReturn<Return>)
|
35
|
+
|
36
|
+
export function $try<Return>(body: TryBody<Return>): PromisedTryReturn<Return> {
|
21
37
|
let caught = false;
|
22
|
-
let error: any | { constructor?: any; };
|
23
|
-
let
|
24
|
-
|
38
|
+
let error: any | { constructor?: any; } | Promise<any | { constructor?: any; }>;
|
39
|
+
let bodyResponse: Return | Promise<Return>;
|
40
|
+
let result: PromisedTryReturn<Return>;
|
25
41
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
42
|
+
const isSameError = (e1: any, error: any) => e1 === error || e1 === error?.constructor;
|
43
|
+
|
44
|
+
function handleErrors(err: any[], err2: any, handler: { (error?: any): void; (error?: any): void; (): any }) {
|
45
|
+
if (isSameError(err, err2) || (Array.isArray(err) && err.some(e => isSameError(e, err2)))) {
|
46
|
+
handler(err2);
|
47
|
+
caught = true;
|
48
|
+
}
|
30
49
|
}
|
31
50
|
|
32
|
-
|
51
|
+
function buildResult(br: typeof bodyResponse): ResultType<Return> | Promise<ResultType<Return>> {
|
52
|
+
if (br instanceof Promise) {
|
53
|
+
const bodyPromise = br as Promise<Return>;
|
54
|
+
return new Promise<ResultType<Return>>(async (resolve) => {
|
55
|
+
bodyPromise.then((response: any) => {
|
56
|
+
resolve({
|
57
|
+
value: response,
|
58
|
+
error: undefined,
|
59
|
+
});
|
60
|
+
}).catch((e: any) => {
|
61
|
+
resolve({
|
62
|
+
value: undefined,
|
63
|
+
error: e,
|
64
|
+
});
|
65
|
+
});
|
66
|
+
});
|
67
|
+
} else {
|
68
|
+
return {
|
69
|
+
value: br,
|
70
|
+
error: undefined,
|
71
|
+
};
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
const chain: TryReturn<Return, typeof error> = {
|
33
76
|
catch: (err, handler) => {
|
34
|
-
if (
|
35
|
-
|
77
|
+
if (result instanceof Promise) {
|
78
|
+
result.then((response) => {
|
79
|
+
typeof response.error !== 'undefined' && !caught && handleErrors(err, response.error, handler);
|
80
|
+
});
|
81
|
+
} else {
|
82
|
+
error && !caught && handleErrors(err, error, handler);
|
36
83
|
}
|
37
|
-
|
38
|
-
handler && handler();
|
39
|
-
caught = true;
|
40
|
-
} else if (Array.isArray(err) && err.some(isSameInstance)) {
|
41
|
-
handler && handler();
|
42
|
-
caught = true;
|
43
|
-
}
|
44
|
-
return chain;
|
84
|
+
return result;
|
45
85
|
},
|
46
86
|
|
47
|
-
other: (
|
48
|
-
if (
|
49
|
-
|
87
|
+
other: (callback) => {
|
88
|
+
if (result instanceof Promise) {
|
89
|
+
result.then((response) => {
|
90
|
+
typeof response.error !== 'undefined' && !caught && callback(response.error);
|
91
|
+
});
|
92
|
+
} else {
|
93
|
+
typeof result.error !== 'undefined' && !caught && callback && callback(result.error);
|
50
94
|
}
|
51
|
-
return
|
52
|
-
finally: chain.finally,
|
53
|
-
result,
|
54
|
-
error,
|
55
|
-
};
|
95
|
+
return result;
|
56
96
|
},
|
57
97
|
|
58
|
-
finally: (callback
|
59
|
-
|
60
|
-
result
|
61
|
-
|
62
|
-
|
98
|
+
finally: (callback) => {
|
99
|
+
if (result instanceof Promise) {
|
100
|
+
result.then((response) => {
|
101
|
+
callback(response);
|
102
|
+
});
|
103
|
+
} else {
|
104
|
+
callback({
|
105
|
+
value: result.value,
|
106
|
+
error: result.error,
|
107
|
+
});
|
108
|
+
}
|
109
|
+
return result;
|
63
110
|
},
|
64
|
-
result,
|
65
|
-
error,
|
66
111
|
};
|
67
112
|
|
68
|
-
|
113
|
+
try {
|
114
|
+
bodyResponse = body();
|
115
|
+
result = Object.assign(buildResult(bodyResponse), chain);
|
116
|
+
} catch (e) {
|
117
|
+
error = e;
|
118
|
+
result = Object.assign(chain, {
|
119
|
+
value: undefined,
|
120
|
+
error: e,
|
121
|
+
});
|
122
|
+
}
|
123
|
+
|
124
|
+
return result;
|
69
125
|
}
|
70
126
|
|
71
127
|
export default $try;
|