catch-match 1.0.3 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  # catch-match
2
+ ![image](https://user-images.githubusercontent.com/1615093/149611056-ad5f8c6c-d7fe-4a64-aed4-a1763135e7ee.png)
2
3
 
3
4
  ## Motivation
4
5
 
@@ -49,73 +50,51 @@ npm install catch-match
49
50
  ```
50
51
 
51
52
  ```javascript
52
- import { _try } from 'catch-match';
53
+ import $try from 'catch-match';
54
+ // or
55
+ import { $try } from 'catch-match';
53
56
  ```
54
57
 
55
58
  ## Example 1
59
+
56
60
  ```javascript
57
- const result = _try(context => {
58
- context.tmp = 'any context data';
59
- console.log('start', context);
60
- return [1, 2, 3, 4, 5]; // value
61
- }).catch(SyntaxError, (context) => {
62
- // noop
63
- }).catch([TypeError, ReferenceError], (context) => {
64
- // noop
65
- }).other((error, context) => {
66
- // noop
67
- }).finally(({value, context, error}) => {
68
- // value: [1, 2, 3, 4, 5]
69
- // context: {tmp: 'any context data'}
70
- // error: undefined
71
- if (!error) {
72
- return value.reverse();
73
- }
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;
74
71
  });
75
72
 
76
- console.log(result);
77
- // {
78
- // value: [5, 4, 3, 2, 1]
79
- // context: {tmp: 'any context data'}
80
- // error: undefined
81
- // }
82
-
73
+ console.log(result); // { error: SyntaxError, result: undefined }
83
74
  ```
84
75
 
85
76
  ## Example 2
77
+
86
78
  ```javascript
87
- const result = _try(context => {
88
- context.tmp = 'any context data';
89
- console.log('start', context);
90
- // ...
91
- throw ReferenceError;
92
- }).catch(SyntaxError, (context) => {
79
+ const result = $try(() => {
80
+ return [1, 2, 3];
81
+ }).catch(ReferenceError, () => {
93
82
  // noop
94
- }).catch([TypeError, ReferenceError], (context) => {
95
- // context: {tmp: 'any context data'}
96
- }).other((error, context) => {
83
+ }).catch([TypeError, SyntaxError], () => {
84
+ // to be called
85
+ }).other((error) => {
97
86
  // noop
98
- }).finally(({value, context, error}) => {
99
- // value: undefined
100
- // context: {tmp: 'any context data'}
101
- // error: ReferenceError
102
- if (!error) {
103
- return value.reverse();
104
- }
87
+ }).finally(({ result, error }) => {
88
+ return result;
105
89
  });
106
90
 
107
- console.log(result);
108
- // {
109
- // value: undefined
110
- // context: {tmp: 'any context data'}
111
- // error: ReferenceError
112
- // }
113
-
91
+ console.log(result); // {error: undefined, result: [1, 2, 3]}
114
92
  ```
115
93
 
116
94
  ## Example 3
95
+
117
96
  ```javascript
118
- const result = _try(context => {
97
+ const result = $try(context => {
119
98
  context.tmp = 'any context data';
120
99
  console.log('start', context);
121
100
  // ...
@@ -135,7 +114,7 @@ const result = _try(context => {
135
114
  }
136
115
  });
137
116
 
138
- console.log(result);
117
+ console.log(result);
139
118
  // {
140
119
  // value: undefined
141
120
  // context: {tmp: 'any context data', unexpectedError: true}
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,15 +1,29 @@
1
1
  {
2
2
  "name": "catch-match",
3
- "version": "1.0.3",
3
+ "version": "2.0.0",
4
4
  "repository": {
5
5
  "url": "https://github.com/kobzarvs/catch-match"
6
6
  },
7
- "type": "module",
7
+ "keywords": [
8
+ "try",
9
+ "catch",
10
+ "match",
11
+ "pattern",
12
+ "errors",
13
+ "exceptions",
14
+ "throw",
15
+ "finally"
16
+ ],
8
17
  "main": "dist/main.js",
9
18
  "scripts": {
10
- "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"
11
26
  },
12
- "devDependencies": {},
13
27
  "dependencies": {
14
28
  "typescript": "^4.5.4"
15
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,49 +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
  }
70
+
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
+ }