yerror 9.1.1 → 11.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/src/index.test.ts CHANGED
@@ -1,115 +1,139 @@
1
1
  import { describe, test, expect } from '@jest/globals';
2
- import { hasYErrorCode, pickYErrorWithCode, YError } from './index.js';
2
+ import {
3
+ hasYErrorCode,
4
+ pickYErrorWithCode,
5
+ printStackTrace,
6
+ YError,
7
+ } from './index.js';
8
+
9
+ declare module './index.js' {
10
+ interface YErrorRegistry {
11
+ E_ERROR: `arg${number}`[];
12
+ E_ERROR_1: [string, string];
13
+ E_ERROR_2: [`arg2.1`, `arg2.2`];
14
+ E_ERROR_3: [`arg3.1`, `arg3.2`];
15
+ // Not an array will trigger type errors
16
+ E_ERROR_4: { foo: 'bar' };
17
+ }
18
+ }
3
19
 
4
20
  describe('YError', () => {
5
21
  describe('.__constructor', () => {
6
- test('Should work', () => {
22
+ test('should work', () => {
7
23
  const err = new YError('E_ERROR', ['arg1', 'arg2']);
8
24
 
9
25
  expect(err instanceof Error).toBeTruthy();
10
26
  expect(err.name).toEqual(err.toString());
11
27
  expect(err.code).toEqual('E_ERROR');
12
- expect(err.debugValues).toEqual(['arg1', 'arg2']);
28
+ expect(err.debug).toEqual(['arg1', 'arg2']);
13
29
  expect(err.toString()).toEqual('YError: E_ERROR (["arg1","arg2"])');
14
30
  });
15
- test('Should work without code', () => {
31
+ test('should work without code', () => {
16
32
  const err = new YError();
17
33
 
18
34
  expect(err.code).toEqual('E_UNEXPECTED');
19
- expect(err.debugValues).toEqual([]);
35
+ expect(err.debug).toEqual([]);
20
36
  expect(err.toString()).toEqual('YError: E_UNEXPECTED ([])');
21
37
  expect(err.name).toEqual(err.toString());
22
38
  });
23
- test('Should work without new', () => {
39
+ test('should work without new', () => {
24
40
  const err = new YError('E_ERROR', ['arg1', 'arg2']);
25
41
 
26
42
  expect(err.code).toEqual('E_ERROR');
27
43
  expect(err instanceof YError).toBeTruthy();
28
- expect(err.debugValues).toEqual(['arg1', 'arg2']);
44
+ expect(err.debug).toEqual(['arg1', 'arg2']);
29
45
  expect(err.toString()).toEqual('YError: E_ERROR (["arg1","arg2"])');
30
46
  expect(err.name).toEqual(err.toString());
31
47
  });
32
48
  });
33
49
 
34
50
  describe('.wrap()', () => {
35
- test('Should work with standard errors and a message', () => {
36
- const err = YError.wrap(new Error('This is an error!'));
51
+ test('should work with standard errors and a message', () => {
52
+ const causeErr = new Error('This is an error!');
53
+ const err = YError.wrap(causeErr);
37
54
 
38
55
  expect(err.code).toEqual('E_UNEXPECTED');
39
- expect(err.wrappedErrors.length).toEqual(1);
40
- expect(err.debugValues).toEqual([]);
56
+ expect(err.cause).toEqual(causeErr);
57
+ expect(err.debug).toEqual([]);
41
58
 
42
59
  if ('captureStackTrace' in Error) {
43
60
  expect(
44
- -1 !== (err.stack || '').indexOf('Error: This is an error!'),
61
+ -1 !== printStackTrace(err).indexOf('Error: This is an error!'),
45
62
  ).toBeTruthy();
46
63
  expect(
47
- -1 !== (err.stack || '').indexOf('YError: E_UNEXPECTED ([])'),
64
+ -1 !==
65
+ printStackTrace(err).indexOf('YError: E_UNEXPECTED ([])'),
48
66
  ).toBeTruthy();
49
67
  expect(err.name).toEqual(err.toString());
50
68
  }
51
69
  });
52
70
 
53
- test('Should work with standard errors and an error code', () => {
54
- const err = YError.wrap(new Error('E_ERROR'));
71
+ test('should work with standard errors and an error code', () => {
72
+ const causeErr = new Error('E_ERROR');
73
+ const err = YError.wrap(causeErr);
55
74
 
56
75
  expect(err.code).toEqual('E_ERROR');
57
- expect(err.wrappedErrors.length).toEqual(1);
58
- expect(err.debugValues).toEqual([]);
76
+ expect(err.cause).toEqual(causeErr);
77
+ expect(err.debug).toEqual([]);
59
78
 
60
79
  if ('captureStackTrace' in Error) {
61
- expect(-1 !== (err.stack || '').indexOf('Error: E_ERROR')).toBeTruthy();
62
80
  expect(
63
- -1 !== (err.stack || '').indexOf('YError: E_ERROR ([])'),
81
+ -1 !== printStackTrace(err).indexOf('Error: E_ERROR'),
82
+ ).toBeTruthy();
83
+ expect(
84
+ -1 !== printStackTrace(err).indexOf('YError: E_ERROR ([])'),
64
85
  ).toBeTruthy();
65
86
  }
66
87
  expect(err.name).toEqual(err.toString());
67
88
  });
68
89
 
69
- test('Should work with standard errors, an error code and params', () => {
70
- const err = YError.wrap(new Error('E_ERROR'), 'E_ERROR_2', [
71
- 'arg1',
72
- 'arg2',
73
- ]);
90
+ test('should work with standard errors, an error code and params', () => {
91
+ const causeErr = new Error('E_ERROR');
92
+ const err = YError.wrap(causeErr, 'E_ERROR_2', ['arg2.1', 'arg2.2']);
74
93
 
75
94
  expect(err.code).toEqual('E_ERROR_2');
76
- expect(err.wrappedErrors.length).toEqual(1);
77
- expect(err.debugValues).toEqual(['arg1', 'arg2']);
95
+ expect(err.cause).toEqual(causeErr);
96
+ expect(err.debug).toEqual(['arg2.1', 'arg2.2']);
78
97
 
79
98
  if ('captureStackTrace' in Error) {
80
- expect(-1 !== (err.stack || '').indexOf('Error: E_ERROR')).toBeTruthy();
99
+ expect(
100
+ -1 !== printStackTrace(err).indexOf('Error: E_ERROR'),
101
+ ).toBeTruthy();
81
102
  expect(
82
103
  -1 !==
83
- (err.stack || '').indexOf('YError: E_ERROR_2 (["arg1","arg2"])'),
104
+ printStackTrace(err).indexOf(
105
+ 'YError: E_ERROR_2 (["arg2.1","arg2.2"])',
106
+ ),
84
107
  ).toBeTruthy();
85
108
  }
86
109
  expect(err.name).toEqual(err.toString());
87
110
  });
88
111
 
89
- test('Should work with several wrapped errors', () => {
90
- const err = YError.wrap(
91
- YError.wrap(new Error('E_ERROR_1'), 'E_ERROR_2', ['arg2.1', 'arg2.2']),
92
- 'E_ERROR_3',
93
- ['arg3.1', 'arg3.2'],
94
- );
112
+ test('should work with several wrapped errors', () => {
113
+ const causeErr1 = new Error('E_ERROR_1');
114
+ const causeErr2 = YError.wrap(causeErr1, 'E_ERROR_2', [
115
+ 'arg2.1',
116
+ 'arg2.2',
117
+ ]);
118
+ const err = YError.wrap(causeErr2, 'E_ERROR_3', ['arg3.1', 'arg3.2']);
95
119
 
96
120
  expect(err.code).toEqual('E_ERROR_3');
97
- expect(err.wrappedErrors.length).toEqual(2);
98
- expect(err.debugValues).toEqual(['arg3.1', 'arg3.2']);
99
-
121
+ expect(err.cause).toEqual(causeErr2);
122
+ expect(err.debug).toEqual(['arg3.1', 'arg3.2']);
123
+ console.log(printStackTrace(err));
100
124
  if ('captureStackTrace' in Error) {
101
125
  expect(
102
- -1 !== (err.stack || '').indexOf('Error: E_ERROR_1'),
126
+ -1 !== printStackTrace(err).indexOf('Error: E_ERROR_1'),
103
127
  ).toBeTruthy();
104
128
  expect(
105
129
  -1 !==
106
- (err.stack || '').indexOf(
130
+ printStackTrace(err).indexOf(
107
131
  'YError: E_ERROR_2 (["arg2.1","arg2.2"])',
108
132
  ),
109
133
  ).toBeTruthy();
110
134
  expect(
111
135
  -1 !==
112
- (err.stack || '').indexOf(
136
+ printStackTrace(err).indexOf(
113
137
  'YError: E_ERROR_3 (["arg3.1","arg3.2"])',
114
138
  ),
115
139
  ).toBeTruthy();
@@ -119,33 +143,38 @@ describe('YError', () => {
119
143
  });
120
144
 
121
145
  describe('.cast()', () => {
122
- test('Should work with standard errors and a message', () => {
123
- const err = YError.cast(new Error('This is an error!'));
146
+ test('should work with standard errors and a message', () => {
147
+ const causeErr = new Error('This is an error!');
148
+ const err = YError.cast(causeErr);
124
149
 
125
150
  expect(err.code).toEqual('E_UNEXPECTED');
126
- expect(err.wrappedErrors.length).toEqual(1);
127
- expect(err.debugValues).toEqual([]);
151
+ expect(err.cause).toEqual(causeErr);
152
+ expect(err.debug).toEqual([]);
128
153
 
129
154
  if ('captureStackTrace' in Error) {
130
155
  expect(
131
- -1 !== (err.stack || '').indexOf('Error: This is an error!'),
156
+ -1 !== printStackTrace(err).indexOf('Error: This is an error!'),
132
157
  ).toBeTruthy();
133
158
  expect(
134
- -1 !== (err.stack || '').indexOf('YError: E_UNEXPECTED ([])'),
159
+ -1 !==
160
+ printStackTrace(err).indexOf('YError: E_UNEXPECTED ([])'),
135
161
  ).toBeTruthy();
136
162
  }
137
163
  expect(err.name).toEqual(err.toString());
138
164
  });
139
165
 
140
- test('Should let YError instances pass through', () => {
141
- const err = YError.cast(new YError('E_ERROR', ['arg1', 'arg2']));
166
+ test('should let YError instances pass through', () => {
167
+ const causeErr = new YError('E_ERROR', ['arg1', 'arg2']);
168
+ const err = YError.cast(causeErr);
142
169
 
143
170
  expect(err.code).toEqual('E_ERROR');
144
- expect(err.debugValues).toEqual(['arg1', 'arg2']);
171
+ expect(err.cause).toBeUndefined();
172
+ expect(err.debug).toEqual(['arg1', 'arg2']);
145
173
 
146
174
  if ('captureStackTrace' in Error) {
147
175
  expect(
148
- -1 !== (err.stack || '').indexOf('YError: E_ERROR (["arg1","arg2"])'),
176
+ -1 !==
177
+ printStackTrace(err).indexOf('YError: E_ERROR (["arg1","arg2"])'),
149
178
  ).toBeTruthy();
150
179
  }
151
180
  expect(err.name).toEqual(err.toString());
@@ -153,43 +182,45 @@ describe('YError', () => {
153
182
  });
154
183
 
155
184
  describe('.bump()', () => {
156
- test('Should work with standard errors and a message', () => {
157
- const err = YError.bump(new Error('This is an error!'));
185
+ test('should work with standard errors and a message', () => {
186
+ const causeErr = new Error('This is an error!');
187
+ const err = YError.bump(causeErr);
158
188
 
159
189
  expect(err.code).toEqual('E_UNEXPECTED');
160
- expect(err.wrappedErrors.length).toEqual(1);
161
- expect(err.debugValues).toEqual([]);
190
+ expect(err.cause).toEqual(causeErr);
191
+ expect(err.debug).toEqual([]);
162
192
 
163
193
  if ('captureStackTrace' in Error) {
164
194
  expect(
165
- -1 !== (err.stack || '').indexOf('Error: This is an error!'),
195
+ -1 !== printStackTrace(err).indexOf('Error: This is an error!'),
166
196
  ).toBeTruthy();
167
197
  expect(
168
- -1 !== (err.stack || '').indexOf('YError: E_UNEXPECTED ([])'),
198
+ -1 !==
199
+ printStackTrace(err).indexOf('YError: E_UNEXPECTED ([])'),
169
200
  ).toBeTruthy();
170
201
  }
171
202
  expect(err.name).toEqual(err.toString());
172
203
  });
173
204
 
174
- test('Should work with YError like errors', () => {
205
+ test('should work with YError like errors', () => {
175
206
  const baseErr = new Error('E_A_NEW_ERROR');
176
207
 
177
208
  (baseErr as YError).code = 'E_A_NEW_ERROR';
178
- (baseErr as YError).debugValues = ['baseParam1', 'baseParam2'];
209
+ (baseErr as YError).debug = ['baseParam1', 'baseParam2'];
179
210
 
180
211
  const err = YError.bump(baseErr);
181
212
 
182
213
  expect(err.code).toEqual('E_A_NEW_ERROR');
183
- expect(err.wrappedErrors.length).toEqual(1);
184
- expect(err.debugValues).toEqual(['baseParam1', 'baseParam2']);
214
+ expect(err.cause).toEqual(baseErr);
215
+ expect(err.debug).toEqual(['baseParam1', 'baseParam2']);
185
216
 
186
217
  if ('captureStackTrace' in Error) {
187
218
  expect(
188
- -1 !== (err.stack || '').indexOf('Error: E_A_NEW_ERROR'),
219
+ -1 !== printStackTrace(err).indexOf('Error: E_A_NEW_ERROR'),
189
220
  ).toBeTruthy();
190
221
  expect(
191
222
  -1 !==
192
- (err.stack || '').indexOf(
223
+ printStackTrace(err).indexOf(
193
224
  'YError: E_A_NEW_ERROR (["baseParam1","baseParam2"])',
194
225
  ),
195
226
  ).toBeTruthy();
@@ -197,7 +228,7 @@ describe('YError', () => {
197
228
  expect(err.name).toEqual(err.toString());
198
229
  });
199
230
 
200
- test('Should work with Y errors and a message', () => {
231
+ test('should work with Y errors and a message', () => {
201
232
  const err = YError.bump(
202
233
  new YError('E_ERROR', ['arg1.1', 'arg1.2']),
203
234
  'E_ERROR_2',
@@ -205,16 +236,20 @@ describe('YError', () => {
205
236
  );
206
237
 
207
238
  expect(err.code).toEqual('E_ERROR');
208
- expect(err.debugValues).toEqual(['arg1.1', 'arg1.2']);
239
+ expect(err.debug).toEqual(['arg1.1', 'arg1.2']);
209
240
 
210
241
  if ('captureStackTrace' in Error) {
211
242
  expect(
212
243
  -1 !==
213
- (err.stack || '').indexOf('YError: E_ERROR (["arg1.1","arg1.2"])'),
244
+ printStackTrace(err).indexOf(
245
+ 'YError: E_ERROR (["arg1.1","arg1.2"])',
246
+ ),
214
247
  ).toBeTruthy();
215
248
  expect(
216
249
  -1 !==
217
- (err.stack || '').indexOf('YError: E_ERROR (["arg1.1","arg1.2"])'),
250
+ printStackTrace(err).indexOf(
251
+ 'YError: E_ERROR (["arg1.1","arg1.2"])',
252
+ ),
218
253
  ).toBeTruthy();
219
254
  }
220
255
  expect(err.name).toEqual(err.toString());
@@ -225,13 +260,13 @@ describe('YError', () => {
225
260
  test('should work with defined debug value type', () => {
226
261
  const err = new YError('E_ERROR', ['arg1.1', 'arg1.2']);
227
262
 
228
- expect(hasYErrorCode<`arg${string}`[]>(err, 'E_ERROR')).toBeTruthy();
263
+ expect(hasYErrorCode(err, 'E_ERROR')).toBeTruthy();
229
264
  });
230
265
 
231
266
  test('should work with undefined debug value type', () => {
232
- const err = new YError('E_ERROR', ['arg1.1', 'arg1.2']);
267
+ const err = new YError('E_ERROR_2', ['arg2.1', 'arg2.2']);
233
268
 
234
- expect(hasYErrorCode(err, 'E_ERROR')).toBeTruthy();
269
+ expect(hasYErrorCode(err, 'E_ERROR_2')).toBeTruthy();
235
270
  });
236
271
 
237
272
  test('should work with native errors', () => {
@@ -244,12 +279,61 @@ describe('YError', () => {
244
279
  describe('.pickYErrorWithCode()', () => {
245
280
  test('should work', () => {
246
281
  const err1 = new Error('E_ERROR_1');
247
- const err2 = YError.wrap(err1, 'E_ERROR_2', ['arg1.1', 'arg1.2']);
248
- const err3 = YError.wrap(err2, 'E_ERROR_3', ['arg1.1', 'arg1.2']);
282
+ const err2 = YError.wrap(err1, 'E_ERROR_2', ['arg2.1', 'arg2.2']);
283
+ const err3 = YError.wrap(err2, 'E_ERROR_3', ['arg3.1', 'arg3.2']);
249
284
 
250
285
  expect(pickYErrorWithCode(err3, 'E_ERROR_1')).toEqual(null);
251
286
  expect(pickYErrorWithCode(err3, 'E_ERROR_2')).toEqual(err2);
252
287
  expect(pickYErrorWithCode(err3, 'E_ERROR_3')).toEqual(err3);
253
288
  });
254
289
  });
290
+
291
+ describe('.printStackTrace()', () => {
292
+ test('should work with non errors', () => {
293
+ expect(printStackTrace('an error string')).toEqual(
294
+ '[no_stack_trace]: error is serializable ("an error string")',
295
+ );
296
+ expect(printStackTrace(undefined)).toEqual(
297
+ '[no_stack_trace]: error is serializable (undefined)',
298
+ );
299
+ expect(printStackTrace(null)).toEqual(
300
+ '[no_stack_trace]: error is serializable (null)',
301
+ );
302
+ expect(printStackTrace(global)).toEqual(
303
+ '[no_stack_trace]: error is circular ("[object Object]")',
304
+ );
305
+ });
306
+ });
307
+
308
+ test('should enforce types from registry', () => {
309
+ // @ts-expect-error : E_ERROR_1 expects [string, string]
310
+ new YError('E_ERROR_1', ['only one']);
311
+ // Must work
312
+ new YError('E_WHATEVER', ['only one']);
313
+ new YError('E_WHATEVER', undefined);
314
+ new YError('E_WHATEVER');
315
+
316
+ const err = new YError('E_ERROR_2', ['arg2.1', 'arg2.2']);
317
+ const val: 'arg2.1' | undefined = err.debug?.[0];
318
+
319
+ expect(val);
320
+
321
+ const err2 = err as YError;
322
+
323
+ // @ts-expect-error : still unknown at this level
324
+ const val2: 'arg2.1' = err2.debug[0];
325
+
326
+ expect(val2);
327
+
328
+ if (!hasYErrorCode(err2, 'E_ERROR_2')) {
329
+ throw new YError('E_UNEXPECTED');
330
+ }
331
+
332
+ const val3: 'arg2.1' = err2.debug[0];
333
+
334
+ expect(val3);
335
+
336
+ // @ts-expect-error : expect error since not an array
337
+ new YError('E_ERROR_4', { foo: 'bar' });
338
+ });
255
339
  });