catch-match 1.0.5 → 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 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
@@ -50,97 +54,96 @@ npm install catch-match
50
54
  ```
51
55
 
52
56
  ```javascript
53
- import { _try } from 'catch-match';
57
+ import $try from 'catch-match';
58
+ // or
59
+ import { $try } from 'catch-match';
54
60
  ```
55
61
 
56
62
  ## Example 1
63
+
57
64
  ```javascript
58
- const result = _try(context => {
59
- context.tmp = 'any context data';
60
- console.log('start', context);
61
- return [1, 2, 3, 4, 5]; // value
62
- }).catch(SyntaxError, (context) => {
63
- // noop
64
- }).catch([TypeError, ReferenceError], (context) => {
65
- // noop
66
- }).other((error, context) => {
67
- // noop
68
- }).finally(({value, context, error}) => {
69
- // value: [1, 2, 3, 4, 5]
70
- // context: {tmp: 'any context data'}
71
- // error: undefined
72
- if (!error) {
73
- return value.reverse();
74
- }
65
+ const result = $try(() => {
66
+ throw SyntaxError;
67
+ }).catch(ReferenceError, () => {
68
+ // noop
69
+ }).catch([TypeError, SyntaxError], () => {
70
+ // to be called
71
+ }).other((error) => {
72
+ // noop
73
+ }).finally(({ result, error }) => {
74
+ return result;
75
75
  });
76
76
 
77
- console.log(result);
78
- // {
79
- // value: [5, 4, 3, 2, 1]
80
- // context: {tmp: 'any context data'}
81
- // error: undefined
82
- // }
83
-
77
+ console.log(result); // { error: SyntaxError, result: undefined }
84
78
  ```
85
79
 
86
80
  ## Example 2
81
+
87
82
  ```javascript
88
- const result = _try(context => {
89
- context.tmp = 'any context data';
90
- console.log('start', context);
91
- // ...
92
- throw ReferenceError;
93
- }).catch(SyntaxError, (context) => {
83
+ const result = $try(() => {
84
+ return [1, 2, 3];
85
+ }).catch(ReferenceError, () => {
94
86
  // noop
95
- }).catch([TypeError, ReferenceError], (context) => {
96
- // context: {tmp: 'any context data'}
97
- }).other((error, context) => {
87
+ }).catch([TypeError, SyntaxError], () => {
88
+ // to be called
89
+ }).other((error) => {
98
90
  // noop
99
- }).finally(({value, context, error}) => {
100
- // value: undefined
101
- // context: {tmp: 'any context data'}
102
- // error: ReferenceError
103
- if (!error) {
104
- return value.reverse();
105
- }
91
+ }).finally(({ result, error }) => {
92
+ return result;
106
93
  });
107
94
 
108
- console.log(result);
109
- // {
110
- // value: undefined
111
- // context: {tmp: 'any context data'}
112
- // error: ReferenceError
113
- // }
114
-
95
+ console.log(result); // {error: undefined, result: [1, 2, 3]}
115
96
  ```
116
97
 
117
98
  ## Example 3
99
+
118
100
  ```javascript
119
- const result = _try(context => {
120
- context.tmp = 'any context data';
121
- console.log('start', context);
122
- // ...
101
+ const result = $try(() => {
123
102
  throw SyntaxError;
124
- }).catch([TypeError, ReferenceError], (context) => {
125
- // noop
126
- }).other((error, context) => {
127
- // error: SyntaxError
128
- // context: {tmp: 'any context data'}
129
- context.unexpectedError = true;
130
- }).finally(({value, context, error}) => {
131
- // value: undefined
132
- // context: {tmp: 'any context data', unexpectedError: true}
133
- // error: SyntaxError
134
- if (!error) {
135
- return value.reverse();
136
- }
137
- });
103
+ })
104
+
105
+ console.log(result); // { error: SyntaxError, result: undefined }
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
+ }
138
141
 
139
- console.log(result);
140
- // {
141
- // value: undefined
142
- // context: {tmp: 'any context data', unexpectedError: true}
143
- // error: SyntaxError
144
- // }
142
+ await proc('resolve') // { value: 'resolved' }}
143
+ await proc('reject') // { error: 'rejected' }
145
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' }
146
149
  ```
package/dist/main.d.ts CHANGED
@@ -10,4 +10,4 @@ export declare function _try<T>(body: (context: any) => T): {
10
10
  };
11
11
  finally: (callback: (params: InternalData<T>) => T) => InternalData<T>;
12
12
  };
13
- export {};
13
+ export default _try;
package/dist/main.js CHANGED
@@ -40,4 +40,5 @@ export function _try(body) {
40
40
  };
41
41
  return chain;
42
42
  }
43
+ export default _try;
43
44
  //# sourceMappingURL=main.js.map
package/dist/main.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,IAAI,CAAI,IAAyB;IAC/C,IAAI,KAAU,CAAC;IACf,IAAI,MAAS,CAAC;IACd,IAAI,OAAO,GAAQ,EAAE,CAAC;IACtB,MAAM,cAAc,GAAG,CAAC,EAAO,EAAE,EAAE,CAAC,EAAE,KAAK,KAAK,IAAI,EAAE,MAAK,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,WAAW,CAAA,CAAC;IAE9E,IAAI;QACF,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;KACxB;IAAC,OAAO,CAAC,EAAE;QACV,KAAK,GAAG,CAAC,CAAC;KACX;IAED,MAAM,KAAK,GAAG;QACZ,KAAK,EAAE,CAAC,GAAQ,EAAE,OAA+B,EAAE,EAAE;YACnD,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,EAAE;gBACpB,OAAO,KAAK,CAAC;aACd;YACD,IAAI,cAAc,CAAC,GAAG,CAAC,EAAE;gBACvB,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;aAC7B;iBAAM,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;gBAC7B,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;aAC9C;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,KAAK,EAAE,CAAC,OAA2C,EAAE,EAAE;YACrD,IAAI,KAAK,EAAE;gBACT,OAAO,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;aACpC;YACD,OAAO;gBACL,OAAO,EAAE,KAAK,CAAC,OAAO;aACvB,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,CAAC,QAAwC,EAAmB,EAAE;YACrE,OAAO;gBACL,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAC,CAAC,CAAC,CAAC,CAAC,MAAM;gBACpE,KAAK;gBACL,OAAO;aACR,CAAC;QACJ,CAAC;KACF,CAAC;IAEF,OAAO,KAAK,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,IAAI,CAAI,IAAyB;IAC/C,IAAI,KAAU,CAAC;IACf,IAAI,MAAS,CAAC;IACd,IAAI,OAAO,GAAQ,EAAE,CAAC;IACtB,MAAM,cAAc,GAAG,CAAC,EAAO,EAAE,EAAE,CAAC,EAAE,KAAK,KAAK,IAAI,EAAE,MAAK,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,WAAW,CAAA,CAAC;IAE9E,IAAI;QACF,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;KACxB;IAAC,OAAO,CAAC,EAAE;QACV,KAAK,GAAG,CAAC,CAAC;KACX;IAED,MAAM,KAAK,GAAG;QACZ,KAAK,EAAE,CAAC,GAAQ,EAAE,OAA+B,EAAE,EAAE;YACnD,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,EAAE;gBACpB,OAAO,KAAK,CAAC;aACd;YACD,IAAI,cAAc,CAAC,GAAG,CAAC,EAAE;gBACvB,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;aAC7B;iBAAM,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;gBAC7B,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;aAC9C;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,KAAK,EAAE,CAAC,OAA2C,EAAE,EAAE;YACrD,IAAI,KAAK,EAAE;gBACT,OAAO,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;aACpC;YACD,OAAO;gBACL,OAAO,EAAE,KAAK,CAAC,OAAO;aACvB,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,CAAC,QAAwC,EAAmB,EAAE;YACrE,OAAO;gBACL,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAC,CAAC,CAAC,CAAC,CAAC,MAAM;gBACpE,KAAK;gBACL,OAAO;aACR,CAAC;QACJ,CAAC;KACF,CAAC;IAEF,OAAO,KAAK,CAAC;AACf,CAAC;AAED,eAAe,IAAI,CAAC"}
package/jest.config.js ADDED
@@ -0,0 +1,10 @@
1
+ /** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
2
+ module.exports = {
3
+ preset: 'ts-jest',
4
+ testEnvironment: 'node',
5
+ globals: {
6
+ 'ts-jest': {
7
+ tsconfig: 'tsconfig.test.json',
8
+ },
9
+ },
10
+ };
package/package.json CHANGED
@@ -1,16 +1,35 @@
1
1
  {
2
2
  "name": "catch-match",
3
- "version": "1.0.5",
3
+ "version": "3.0.0",
4
4
  "repository": {
5
5
  "url": "https://github.com/kobzarvs/catch-match"
6
6
  },
7
- "keywords": ["try", "catch", "match", "pattern", "errors", "exceptions", "throw", "finally"],
8
- "type": "module",
7
+ "keywords": [
8
+ "try",
9
+ "catch",
10
+ "match",
11
+ "pattern",
12
+ "errors",
13
+ "exceptions",
14
+ "throw",
15
+ "finally",
16
+ "promises",
17
+ "resolve",
18
+ "reject",
19
+ "flow",
20
+ "control",
21
+ "process"
22
+ ],
9
23
  "main": "dist/main.js",
10
24
  "scripts": {
11
- "build": "tsc"
25
+ "build": "tsc",
26
+ "test": "jest"
27
+ },
28
+ "devDependencies": {
29
+ "@types/jest": "^27.4.0",
30
+ "jest": "^27.4.7",
31
+ "ts-jest": "^27.1.3"
12
32
  },
13
- "devDependencies": {},
14
33
  "dependencies": {
15
34
  "typescript": "^4.5.4"
16
35
  }
@@ -0,0 +1,502 @@
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
+ });
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], (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
+ });
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], (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 });
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], (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
+ });
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
+ });
134
+
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
+ });
159
+
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
+ });
181
+
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 });
202
+ });
203
+
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
+ });
220
+ });
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
+ });
284
+
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
+ });
360
+
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');
431
+ });
432
+
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
+ });
502
+ });
package/src/main.ts CHANGED
@@ -1,49 +1,127 @@
1
- type InternalData<T> = {
2
- value?: T;
3
- error?: any;
4
- context?: any;
5
- };
6
-
7
- export function _try<T>(body: (context: any) => T) {
8
- let error: any;
9
- let result: T;
10
- let context: any = {};
11
- const isSameInstance = (e1: any) => e1 === error || e1 === error?.constructor;
1
+ export type ErrrorHandler<ErrorType> = (error?: ErrorType) => void
12
2
 
13
- try {
14
- result = body(context);
15
- } catch (e) {
16
- error = e;
3
+ export type FinallyCallback<Result, ErrorType = any> = (params: ResultType<Result, ErrorType>) => void
4
+
5
+ export type TryBody<Result> = () => Result | Promise<Result> | never
6
+
7
+ export type ResultType<Result, ErrorType = any> = {
8
+ value?: Result;
9
+ error?: ErrorType;
10
+ }
11
+
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>
17
19
  }
18
20
 
19
- const chain = {
20
- catch: (err: any, handler: (context: any) => void) => {
21
- if (!err || !handler) {
22
- return chain;
23
- }
24
- if (isSameInstance(err)) {
25
- handler && handler(context);
26
- } else if (Array.isArray(err)) {
27
- err.some(isSameInstance) && handler(context);
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>
31
+
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> {
37
+ let caught = false;
38
+ let error: any | { constructor?: any; } | Promise<any | { constructor?: any; }>;
39
+ let bodyResponse: Return | Promise<Return>;
40
+ let result: PromisedTryReturn<Return>;
41
+
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
+ }
49
+ }
50
+
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> = {
76
+ catch: (err, handler) => {
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);
28
83
  }
29
- return chain;
84
+ return result;
30
85
  },
31
- other: (handler: (error: any, context: any) => void) => {
32
- if (error) {
33
- handler && handler(error, context);
86
+
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);
34
94
  }
35
- return {
36
- finally: chain.finally
37
- };
95
+ return result;
38
96
  },
39
- finally: (callback: (params: InternalData<T>) => T): InternalData<T> => {
40
- return {
41
- value: callback ? callback({value: result, error, context}) : result,
42
- error,
43
- context,
44
- };
97
+
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;
45
110
  },
46
111
  };
47
112
 
48
- return chain;
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;
49
125
  }
126
+
127
+ export default $try;
package/tsconfig.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "target": "es6",
4
4
  "useDefineForClassFields": true,
5
5
  "module": "ESNext",
6
- "lib": ["ESNext"],
6
+ "lib": ["ESNext", "DOM"],
7
7
  "moduleResolution": "Node",
8
8
  "strict": true,
9
9
  "sourceMap": true,
@@ -15,7 +15,7 @@
15
15
  "noUnusedParameters": true,
16
16
  "noImplicitReturns": true,
17
17
  "alwaysStrict": true,
18
- "outDir": "dist"
18
+ "outDir": "dist",
19
19
  },
20
20
  "include": ["./src"]
21
21
  }
@@ -0,0 +1,3 @@
1
+ {
2
+ "extends": "./tsconfig.json"
3
+ }