catch-match 1.1.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -50,77 +50,51 @@ npm install catch-match
50
50
  ```
51
51
 
52
52
  ```javascript
53
- import _try from 'catch-match';
53
+ import $try from 'catch-match';
54
54
  // or
55
- import { _try } from 'catch-match';
56
- // or
57
- import { _try as customTry } from 'catch-match';
55
+ import { $try } from 'catch-match';
58
56
  ```
59
57
 
60
58
  ## Example 1
59
+
61
60
  ```javascript
62
- const result = _try(context => {
63
- context.tmp = 'any context data';
64
- console.log('start', context);
65
- return [1, 2, 3, 4, 5]; // value
66
- }).catch(SyntaxError, (context) => {
67
- // noop
68
- }).catch([TypeError, ReferenceError], (context) => {
69
- // noop
70
- }).other((error, context) => {
71
- // noop
72
- }).finally(({value, context, error}) => {
73
- // value: [1, 2, 3, 4, 5]
74
- // context: {tmp: 'any context data'}
75
- // error: undefined
76
- if (!error) {
77
- return value.reverse();
78
- }
61
+ const result = $try(() => {
62
+ throw SyntaxError;
63
+ }).catch(ReferenceError, () => {
64
+ // noop
65
+ }).catch([TypeError, SyntaxError], () => {
66
+ // to be called
67
+ }).other((error) => {
68
+ // noop
69
+ }).finally(({ result, error }) => {
70
+ return result;
79
71
  });
80
72
 
81
- console.log(result);
82
- // {
83
- // value: [5, 4, 3, 2, 1]
84
- // context: {tmp: 'any context data'}
85
- // error: undefined
86
- // }
87
-
73
+ console.log(result); // { error: SyntaxError, result: undefined }
88
74
  ```
89
75
 
90
76
  ## Example 2
77
+
91
78
  ```javascript
92
- const result = _try(context => {
93
- context.tmp = 'any context data';
94
- console.log('start', context);
95
- // ...
96
- throw ReferenceError;
97
- }).catch(SyntaxError, (context) => {
79
+ const result = $try(() => {
80
+ return [1, 2, 3];
81
+ }).catch(ReferenceError, () => {
98
82
  // noop
99
- }).catch([TypeError, ReferenceError], (context) => {
100
- // context: {tmp: 'any context data'}
101
- }).other((error, context) => {
83
+ }).catch([TypeError, SyntaxError], () => {
84
+ // to be called
85
+ }).other((error) => {
102
86
  // noop
103
- }).finally(({value, context, error}) => {
104
- // value: undefined
105
- // context: {tmp: 'any context data'}
106
- // error: ReferenceError
107
- if (!error) {
108
- return value.reverse();
109
- }
87
+ }).finally(({ result, error }) => {
88
+ return result;
110
89
  });
111
90
 
112
- console.log(result);
113
- // {
114
- // value: undefined
115
- // context: {tmp: 'any context data'}
116
- // error: ReferenceError
117
- // }
118
-
91
+ console.log(result); // {error: undefined, result: [1, 2, 3]}
119
92
  ```
120
93
 
121
94
  ## Example 3
95
+
122
96
  ```javascript
123
- const result = _try(context => {
97
+ const result = $try(context => {
124
98
  context.tmp = 'any context data';
125
99
  console.log('start', context);
126
100
  // ...
@@ -140,7 +114,7 @@ const result = _try(context => {
140
114
  }
141
115
  });
142
116
 
143
- console.log(result);
117
+ console.log(result);
144
118
  // {
145
119
  // value: undefined
146
120
  // context: {tmp: 'any context data', unexpectedError: true}
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,29 @@
1
1
  {
2
2
  "name": "catch-match",
3
- "version": "1.1.0",
3
+ "version": "2.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
+ ],
9
17
  "main": "dist/main.js",
10
18
  "scripts": {
11
- "build": "tsc"
19
+ "build": "tsc",
20
+ "test": "jest"
21
+ },
22
+ "devDependencies": {
23
+ "@types/jest": "^27.4.0",
24
+ "jest": "^27.4.7",
25
+ "ts-jest": "^27.1.3"
12
26
  },
13
- "devDependencies": {},
14
27
  "dependencies": {
15
28
  "typescript": "^4.5.4"
16
29
  }
@@ -0,0 +1,226 @@
1
+ import $try from '../main';
2
+
3
+ test('should be return result from `finally` branch', () => {
4
+ let matchReferenceError = jest.fn();
5
+ let matchArrayOfErrors = jest.fn();
6
+ let matchOther = jest.fn();
7
+ let matchFinally = jest.fn();
8
+
9
+ const result = $try(() => {
10
+ return [1, 2, 3];
11
+ }).catch(ReferenceError, () => {
12
+ matchReferenceError();
13
+ }).catch([TypeError, SyntaxError], () => {
14
+ matchArrayOfErrors();
15
+ }).other((error) => {
16
+ matchOther(error);
17
+ }).finally(({ result, error }) => {
18
+ matchFinally({ result, error });
19
+ return result;
20
+ });
21
+
22
+ expect(matchReferenceError).not.toBeCalled();
23
+ expect(matchArrayOfErrors).not.toBeCalled();
24
+ expect(matchOther).not.toBeCalled();
25
+ expect(matchFinally).toBeCalled();
26
+ expect(result).toEqual({ error: undefined, result: [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], () => {
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();
167
+
168
+ class CustomError extends Error {
169
+ }
170
+
171
+ const result = $try(() => {
172
+ throw CustomError;
173
+ }).catch([TypeError, SyntaxError], () => {
174
+ matchArrayOfErrors();
175
+ });
176
+
177
+ expect(matchCustomError).not.toBeCalled();
178
+ expect(matchArrayOfErrors).not.toBeCalled();
179
+ expect(matchOther).not.toBeCalled();
180
+ expect(matchFinally).not.toBeCalled();
181
+ expect(result).toMatchObject({ error: CustomError, result: undefined });
182
+ });
183
+
184
+
185
+ test('should be return result from `other` branch', () => {
186
+ let matchCustomError = jest.fn();
187
+ let matchArrayOfErrors = jest.fn();
188
+ let matchOther = jest.fn();
189
+ let matchFinally = jest.fn();
190
+
191
+ class CustomError extends Error {
192
+ }
193
+
194
+ const result = $try(() => {
195
+ throw CustomError;
196
+ }).other((error) => {
197
+ matchOther(error);
198
+ });
199
+
200
+ expect(matchCustomError).not.toBeCalled();
201
+ expect(matchArrayOfErrors).not.toBeCalled();
202
+ expect(matchOther).toBeCalledWith(CustomError);
203
+ expect(matchFinally).not.toBeCalled();
204
+ expect(result).toMatchObject({ error: CustomError, result: undefined });
205
+ });
206
+
207
+
208
+ test('should be return result without branches', () => {
209
+ let matchCustomError = jest.fn();
210
+ let matchArrayOfErrors = jest.fn();
211
+ let matchOther = jest.fn();
212
+ let matchFinally = jest.fn();
213
+
214
+ class CustomError extends Error {
215
+ }
216
+
217
+ const result = $try(() => {
218
+ throw CustomError;
219
+ });
220
+
221
+ expect(matchCustomError).not.toBeCalled();
222
+ expect(matchArrayOfErrors).not.toBeCalled();
223
+ expect(matchOther).not.toBeCalled();
224
+ expect(matchFinally).not.toBeCalled();
225
+ expect(result).toMatchObject({ error: CustomError, result: undefined });
226
+ });
package/src/main.ts CHANGED
@@ -1,51 +1,71 @@
1
- type InternalData<T> = {
2
- value?: T;
3
- error?: any;
4
- context?: any;
1
+ export type ResultType<Rsult, ErrorType> = {
2
+ result?: Rsult;
3
+ error?: ErrorType;
5
4
  };
6
5
 
7
- export function _try<T>(body: (context: any) => T) {
8
- let error: any;
9
- let result: T;
10
- let context: any = {};
6
+ export type ErrrorHandler<ErrorType> = (error?: ErrorType) => void;
7
+
8
+ export type FinallyCallback<Result, ErrorType> = ((params: ResultType<Result, ErrorType>) => Result | void | undefined);
9
+
10
+ export type TryReturn<Result, ErrorType = any> = {
11
+ catch: (error: ErrorType | ErrorType[], handler: ErrrorHandler<ErrorType>) => TryReturn<Result, ErrorType>;
12
+ other: (handler: ErrrorHandler<ErrorType>) => Pick<TryReturn<Result, ErrorType>, 'finally'>,
13
+ finally: (callback?: FinallyCallback<Result, ErrorType>) => ResultType<Result, ErrorType>,
14
+ result: Result,
15
+ error: ErrorType
16
+ }
17
+
18
+ export type TryBody<Result> = () => Result | never;
19
+
20
+ export function $try<Return>(body: TryBody<Return>): TryReturn<Return> {
21
+ let caught = false;
22
+ let error: any | { constructor?: any; };
23
+ let result: Return | any;
11
24
  const isSameInstance = (e1: any) => e1 === error || e1 === error?.constructor;
12
25
 
13
26
  try {
14
- result = body(context);
27
+ result = body();
15
28
  } catch (e) {
16
29
  error = e;
17
30
  }
18
31
 
19
- const chain = {
20
- catch: (err: any, handler: (context: any) => void) => {
32
+ const chain: TryReturn<typeof result, typeof error> = {
33
+ catch: (err, handler) => {
21
34
  if (!err || !handler) {
22
35
  return chain;
23
36
  }
24
37
  if (isSameInstance(err)) {
25
- handler && handler(context);
26
- } else if (Array.isArray(err)) {
27
- err.some(isSameInstance) && handler(context);
38
+ handler && handler();
39
+ caught = true;
40
+ } else if (Array.isArray(err) && err.some(isSameInstance)) {
41
+ handler && handler();
42
+ caught = true;
28
43
  }
29
44
  return chain;
30
45
  },
31
- other: (handler: (error: any, context: any) => void) => {
32
- if (error) {
33
- handler && handler(error, context);
46
+
47
+ other: (handler) => {
48
+ if (!caught && error) {
49
+ handler && handler(error);
34
50
  }
35
51
  return {
36
- finally: chain.finally
52
+ finally: chain.finally,
53
+ result,
54
+ error,
37
55
  };
38
56
  },
39
- finally: (callback: (params: InternalData<T>) => T): InternalData<T> => {
57
+
58
+ finally: (callback?) => {
40
59
  return {
41
- value: callback ? callback({value: result, error, context}) : result,
60
+ result: callback ? callback({ result, error }) : result,
42
61
  error,
43
- context,
44
62
  };
45
63
  },
64
+ result,
65
+ error,
46
66
  };
47
67
 
48
68
  return chain;
49
69
  }
50
70
 
51
- export default _try;
71
+ 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
+ }