@taicode/common-base 1.7.4 → 1.7.5

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.
Files changed (34) hide show
  1. package/output/error/error.d.ts +104 -67
  2. package/output/error/error.d.ts.map +1 -1
  3. package/output/error/error.js +85 -59
  4. package/output/error/error.test.d.ts +0 -17
  5. package/output/error/error.test.d.ts.map +1 -1
  6. package/output/error/error.test.js +172 -99
  7. package/output/error/index.d.ts +2 -1
  8. package/output/error/index.d.ts.map +1 -1
  9. package/output/error/index.js +1 -1
  10. package/output/events/disposer.d.ts +6 -0
  11. package/output/events/disposer.d.ts.map +1 -0
  12. package/output/events/disposer.js +19 -0
  13. package/output/events/disposer.test.d.ts +2 -0
  14. package/output/events/disposer.test.d.ts.map +1 -0
  15. package/output/events/disposer.test.js +192 -0
  16. package/output/events/event-emitter.d.ts +33 -0
  17. package/output/events/event-emitter.d.ts.map +1 -0
  18. package/output/events/event-emitter.js +66 -0
  19. package/output/events/event-emitter.test.d.ts +2 -0
  20. package/output/events/event-emitter.test.d.ts.map +1 -0
  21. package/output/events/event-emitter.test.js +213 -0
  22. package/output/events/index.d.ts +3 -0
  23. package/output/events/index.d.ts.map +1 -0
  24. package/output/events/index.js +3 -0
  25. package/output/logger/formatter.d.ts +0 -1
  26. package/output/logger/formatter.d.ts.map +1 -1
  27. package/output/logger/formatter.js +1 -17
  28. package/output/logger/formatter.test.d.ts +0 -24
  29. package/output/logger/formatter.test.d.ts.map +1 -1
  30. package/output/logger/formatter.test.js +11 -30
  31. package/output/logger/logger.test.d.ts +0 -19
  32. package/output/logger/logger.test.d.ts.map +1 -1
  33. package/output/logger/logger.test.js +6 -16
  34. package/package.json +3 -2
@@ -1,11 +1,11 @@
1
1
  import { describe, it, expect } from 'vitest';
2
- import { UserError, SystemError, UnknownError } from './error';
2
+ import { UserError, SystemError } from './error';
3
3
  describe('UserError', () => {
4
4
  describe('constructor', () => {
5
5
  it('应该正确创建UserError实例', () => {
6
6
  const type = 'VALIDATION_ERROR';
7
7
  const message = '输入验证失败';
8
- const error = new UserError(type, message);
8
+ const error = new UserError(type, undefined, message);
9
9
  expect(error).toBeInstanceOf(Error);
10
10
  expect(error).toBeInstanceOf(UserError);
11
11
  expect(error.name).toBe('UserError');
@@ -32,7 +32,7 @@ describe('UserError', () => {
32
32
  });
33
33
  it('应该在提供空字符串message时保持空字符串', () => {
34
34
  const type = 'VALIDATION_ERROR';
35
- const error = new UserError(type, '');
35
+ const error = new UserError(type, {}, '');
36
36
  expect(error).toBeInstanceOf(Error);
37
37
  expect(error).toBeInstanceOf(UserError);
38
38
  expect(error.name).toBe('UserError');
@@ -43,34 +43,32 @@ describe('UserError', () => {
43
43
  const type = 'VALIDATION_ERROR';
44
44
  const message = '输入验证失败';
45
45
  const cause = new Error('原始错误');
46
- const error = new UserError(type, message, { cause });
46
+ const error = new UserError(type, { cause }, message);
47
47
  expect(error.cause).toBe(cause);
48
48
  });
49
49
  it('应该支持ErrorOptions参数且message为可选', () => {
50
50
  const type = 'VALIDATION_ERROR';
51
51
  const cause = new Error('原始错误');
52
- const error = new UserError(type, undefined, { cause });
52
+ const error = new UserError(type, { cause });
53
53
  expect(error.cause).toBe(cause);
54
54
  expect(error.message).toBe('');
55
55
  });
56
56
  it('应该正确设置错误堆栈信息', () => {
57
- const error = new UserError('TEST_ERROR', '测试错误');
57
+ const error = new UserError('TEST_ERROR', undefined, '测试错误');
58
58
  expect(error.stack).toBeDefined();
59
59
  expect(error.stack).toContain('UserError');
60
60
  });
61
61
  });
62
62
  describe('is', () => {
63
63
  it('应该正确识别UserError实例', () => {
64
- const error = new UserError('TEST_ERROR', '测试错误');
64
+ const error = new UserError('TEST_ERROR', undefined, '测试错误');
65
65
  expect(UserError.is(error)).toBe(true);
66
66
  });
67
67
  it('应该正确识别非UserError实例', () => {
68
68
  const regularError = new Error('普通错误');
69
- const systemError = new SystemError('SYSTEM_ERROR', '系统错误');
70
- const unknownError = new UnknownError('未知错误');
69
+ const systemError = new SystemError('SYSTEM_ERROR', undefined, '系统错误');
71
70
  expect(UserError.is(regularError)).toBe(false);
72
71
  expect(UserError.is(systemError)).toBe(false);
73
- expect(UserError.is(unknownError)).toBe(false);
74
72
  expect(UserError.is(null)).toBe(false);
75
73
  expect(UserError.is(undefined)).toBe(false);
76
74
  expect(UserError.is('字符串')).toBe(false);
@@ -78,7 +76,7 @@ describe('UserError', () => {
78
76
  expect(UserError.is({})).toBe(false);
79
77
  });
80
78
  it('应该支持类型守卫功能', () => {
81
- const error = new UserError('TEST_ERROR', '测试错误');
79
+ const error = new UserError('TEST_ERROR', undefined, '测试错误');
82
80
  if (UserError.is(error)) {
83
81
  // 在类型守卫内部,error的类型应该被正确推断
84
82
  expect(error.type).toBe('TEST_ERROR');
@@ -89,13 +87,13 @@ describe('UserError', () => {
89
87
  });
90
88
  describe('继承行为', () => {
91
89
  it('应该正确继承Error的所有属性和方法', () => {
92
- const error = new UserError('TEST_ERROR', '测试错误');
90
+ const error = new UserError('TEST_ERROR', undefined, '测试错误');
93
91
  expect(error.toString()).toContain('测试错误');
94
92
  expect(error.toString()).toContain('UserError');
95
93
  expect(error instanceof Error).toBe(true);
96
94
  });
97
95
  it('应该支持Error的标准用法', () => {
98
- const error = new UserError('TEST_ERROR', '测试错误');
96
+ const error = new UserError('TEST_ERROR', undefined, '测试错误');
99
97
  try {
100
98
  throw error;
101
99
  }
@@ -111,7 +109,7 @@ describe('SystemError', () => {
111
109
  it('应该正确创建SystemError实例', () => {
112
110
  const type = 'DATABASE_ERROR';
113
111
  const message = '数据库连接失败';
114
- const error = new SystemError(type, message);
112
+ const error = new SystemError(type, undefined, message);
115
113
  expect(error).toBeInstanceOf(Error);
116
114
  expect(error).toBeInstanceOf(SystemError);
117
115
  expect(error.name).toBe('SystemError');
@@ -138,7 +136,7 @@ describe('SystemError', () => {
138
136
  });
139
137
  it('应该在提供空字符串message时保持空字符串', () => {
140
138
  const type = 'DATABASE_ERROR';
141
- const error = new SystemError(type, '');
139
+ const error = new SystemError(type, {}, '');
142
140
  expect(error).toBeInstanceOf(Error);
143
141
  expect(error).toBeInstanceOf(SystemError);
144
142
  expect(error.name).toBe('SystemError');
@@ -149,34 +147,32 @@ describe('SystemError', () => {
149
147
  const type = 'NETWORK_ERROR';
150
148
  const message = '网络请求失败';
151
149
  const cause = new Error('连接超时');
152
- const error = new SystemError(type, message, { cause });
150
+ const error = new SystemError(type, { cause }, message);
153
151
  expect(error.cause).toBe(cause);
154
152
  });
155
153
  it('应该支持ErrorOptions参数且message为可选', () => {
156
154
  const type = 'NETWORK_ERROR';
157
155
  const cause = new Error('连接超时');
158
- const error = new SystemError(type, undefined, { cause });
156
+ const error = new SystemError(type, { cause });
159
157
  expect(error.cause).toBe(cause);
160
158
  expect(error.message).toBe('');
161
159
  });
162
160
  it('应该正确设置错误堆栈信息', () => {
163
- const error = new SystemError('FILE_ERROR', '文件读取失败');
161
+ const error = new SystemError('FILE_ERROR', undefined, '文件读取失败');
164
162
  expect(error.stack).toBeDefined();
165
163
  expect(error.stack).toContain('SystemError');
166
164
  });
167
165
  });
168
166
  describe('is', () => {
169
167
  it('应该正确识别SystemError实例', () => {
170
- const error = new SystemError('TEST_ERROR', '测试错误');
168
+ const error = new SystemError('TEST_ERROR', undefined, '测试错误');
171
169
  expect(SystemError.is(error)).toBe(true);
172
170
  });
173
171
  it('应该正确识别非SystemError实例', () => {
174
172
  const regularError = new Error('普通错误');
175
- const userError = new UserError('USER_ERROR', '用户错误');
176
- const unknownError = new UnknownError('未知错误');
173
+ const userError = new UserError('USER_ERROR', undefined, '用户错误');
177
174
  expect(SystemError.is(regularError)).toBe(false);
178
175
  expect(SystemError.is(userError)).toBe(false);
179
- expect(SystemError.is(unknownError)).toBe(false);
180
176
  expect(SystemError.is(null)).toBe(false);
181
177
  expect(SystemError.is(undefined)).toBe(false);
182
178
  expect(SystemError.is('字符串')).toBe(false);
@@ -184,7 +180,7 @@ describe('SystemError', () => {
184
180
  expect(SystemError.is({})).toBe(false);
185
181
  });
186
182
  it('应该支持类型守卫功能', () => {
187
- const error = new SystemError('DATABASE_ERROR', '数据库错误');
183
+ const error = new SystemError('DATABASE_ERROR', undefined, '数据库错误');
188
184
  if (SystemError.is(error)) {
189
185
  // 在类型守卫内部,error的类型应该被正确推断
190
186
  expect(error.type).toBe('DATABASE_ERROR');
@@ -195,13 +191,13 @@ describe('SystemError', () => {
195
191
  });
196
192
  describe('继承行为', () => {
197
193
  it('应该正确继承Error的所有属性和方法', () => {
198
- const error = new SystemError('TEST_ERROR', '测试错误');
194
+ const error = new SystemError('TEST_ERROR', undefined, '测试错误');
199
195
  expect(error.toString()).toContain('测试错误');
200
196
  expect(error.toString()).toContain('SystemError');
201
197
  expect(error instanceof Error).toBe(true);
202
198
  });
203
199
  it('应该支持Error的标准用法', () => {
204
- const error = new SystemError('TEST_ERROR', '测试错误');
200
+ const error = new SystemError('TEST_ERROR', undefined, '测试错误');
205
201
  try {
206
202
  throw error;
207
203
  }
@@ -212,99 +208,176 @@ describe('SystemError', () => {
212
208
  });
213
209
  });
214
210
  });
215
- describe('UnknownError', () => {
216
- describe('constructor', () => {
217
- it('应该正确创建UnknownError实例', () => {
218
- const message = '发生了未知错误';
219
- const error = new UnknownError(message);
220
- expect(error).toBeInstanceOf(Error);
221
- expect(error).toBeInstanceOf(UnknownError);
222
- expect(error.name).toBe('UnknownError');
223
- expect(error.message).toBe(message);
224
- });
225
- it('应该支持ErrorOptions参数', () => {
226
- const message = '未知错误';
227
- const cause = new Error('原始未知错误');
228
- const error = new UnknownError(message, { cause });
229
- expect(error.cause).toBe(cause);
230
- });
231
- it('应该正确设置错误堆栈信息', () => {
232
- const error = new UnknownError('测试未知错误');
233
- expect(error.stack).toBeDefined();
234
- expect(error.stack).toContain('UnknownError');
235
- });
236
- });
237
- describe('is', () => {
238
- it('应该正确识别UnknownError实例', () => {
239
- const error = new UnknownError('测试错误');
240
- expect(UnknownError.is(error)).toBe(true);
241
- });
242
- it('应该正确识别非UnknownError实例', () => {
243
- const regularError = new Error('普通错误');
244
- const userError = new UserError('USER_ERROR', '用户错误');
245
- const systemError = new SystemError('SYSTEM_ERROR', '系统错误');
246
- expect(UnknownError.is(regularError)).toBe(false);
247
- expect(UnknownError.is(userError)).toBe(false);
248
- expect(UnknownError.is(systemError)).toBe(false);
249
- expect(UnknownError.is(null)).toBe(false);
250
- expect(UnknownError.is(undefined)).toBe(false);
251
- expect(UnknownError.is('字符串')).toBe(false);
252
- expect(UnknownError.is(123)).toBe(false);
253
- expect(UnknownError.is({})).toBe(false);
254
- });
255
- });
256
- describe('继承行为', () => {
257
- it('应该正确继承Error的所有属性和方法', () => {
258
- const error = new UnknownError('测试错误');
259
- expect(error.toString()).toContain('测试错误');
260
- expect(error instanceof Error).toBe(true);
261
- });
262
- it('应该支持Error的标准用法', () => {
263
- const error = new UnknownError('测试错误');
264
- try {
265
- throw error;
266
- }
267
- catch (caught) {
268
- expect(caught).toBe(error);
269
- expect(caught).toBeInstanceOf(UnknownError);
270
- }
271
- });
272
- });
273
- });
274
211
  describe('错误类型区分', () => {
275
- it('三种错误类型应该是不同的类', () => {
276
- const userError = new UserError('USER_ERROR', '用户错误');
277
- const systemError = new SystemError('SYSTEM_ERROR', '系统错误');
278
- const unknownError = new UnknownError('未知错误');
212
+ it('两种错误类型应该是不同的类', () => {
213
+ const userError = new UserError('USER_ERROR', undefined, '用户错误');
214
+ const systemError = new SystemError('SYSTEM_ERROR', undefined, '系统错误');
279
215
  // 每种错误只能被自己的类型检查函数识别
280
216
  expect(UserError.is(userError)).toBe(true);
281
217
  expect(SystemError.is(userError)).toBe(false);
282
- expect(UnknownError.is(userError)).toBe(false);
283
218
  expect(UserError.is(systemError)).toBe(false);
284
219
  expect(SystemError.is(systemError)).toBe(true);
285
- expect(UnknownError.is(systemError)).toBe(false);
286
- expect(UserError.is(unknownError)).toBe(false);
287
- expect(SystemError.is(unknownError)).toBe(false);
288
- expect(UnknownError.is(unknownError)).toBe(true);
289
220
  });
290
221
  it('所有错误类型都应该是Error的实例', () => {
291
- const userError = new UserError('USER_ERROR', '用户错误');
292
- const systemError = new SystemError('SYSTEM_ERROR', '系统错误');
293
- const unknownError = new UnknownError('未知错误');
222
+ const userError = new UserError('USER_ERROR', undefined, '用户错误');
223
+ const systemError = new SystemError('SYSTEM_ERROR', undefined, '系统错误');
294
224
  expect(userError instanceof Error).toBe(true);
295
225
  expect(systemError instanceof Error).toBe(true);
296
- expect(unknownError instanceof Error).toBe(true);
297
226
  });
298
227
  });
299
228
  describe('泛型类型支持', () => {
300
229
  it('UserError应该支持字符串字面量类型', () => {
301
- const error = new UserError('REQUIRED_FIELD', '字段必填');
230
+ const error = new UserError('REQUIRED_FIELD', {}, '字段必填');
302
231
  expect(error.type).toBe('REQUIRED_FIELD');
303
232
  expect(UserError.is(error)).toBe(true);
304
233
  });
305
234
  it('SystemError应该支持字符串字面量类型', () => {
306
- const error = new SystemError('DATABASE_ERROR', '数据库连接失败');
235
+ const error = new SystemError('DATABASE_ERROR', {}, '数据库连接失败');
307
236
  expect(error.type).toBe('DATABASE_ERROR');
308
237
  expect(SystemError.is(error)).toBe(true);
309
238
  });
310
239
  });
240
+ describe('define 工厂方法', () => {
241
+ describe('UserError.define', () => {
242
+ it('应该定义一个绑定了特定错误类型的 UserError 类', () => {
243
+ const MyUserError = UserError.define({
244
+ 'validation-failed': {},
245
+ 'permission-denied': {},
246
+ 'not-found': {}
247
+ });
248
+ const error = new MyUserError('validation-failed', {
249
+ field: 'email',
250
+ value: 'invalid@'
251
+ }, '验证失败');
252
+ expect(error).toBeInstanceOf(Error);
253
+ expect(error.name).toBe('UserError');
254
+ expect(error.type).toBe('validation-failed');
255
+ expect(error.message).toBe('验证失败');
256
+ expect(error.context).toEqual({ field: 'email', value: 'invalid@' });
257
+ });
258
+ it('应该支持 is 类型守卫', () => {
259
+ const MyUserError = UserError.define({
260
+ 'test-error': {}
261
+ });
262
+ const error = new MyUserError('test-error', { code: 123 }, '测试错误');
263
+ expect(MyUserError.is(error)).toBe(true);
264
+ expect(MyUserError.is(new Error('普通错误'))).toBe(false);
265
+ expect(MyUserError.is(null)).toBe(false);
266
+ });
267
+ it('应该支持多次调用 define 定义不同的错误类', () => {
268
+ const ValidationError = UserError.define({
269
+ 'required': {},
270
+ 'invalid': {}
271
+ });
272
+ const AuthError = UserError.define({
273
+ 'unauthorized': {},
274
+ 'forbidden': {}
275
+ });
276
+ const validationError = new ValidationError('required', { field: 'username' }, '必填字段');
277
+ const authError = new AuthError('unauthorized', { reason: 'token expired' }, '未授权');
278
+ expect(validationError.type).toBe('required');
279
+ expect(authError.type).toBe('unauthorized');
280
+ expect(ValidationError.is(validationError)).toBe(true);
281
+ expect(ValidationError.is(authError)).toBe(false); // 不同的类不会互相识别
282
+ expect(AuthError.is(authError)).toBe(true);
283
+ expect(AuthError.is(validationError)).toBe(false); // 不同的类不会互相识别
284
+ });
285
+ it('应该支持不传 context 参数', () => {
286
+ const MyUserError = UserError.define({
287
+ 'simple-error': {}
288
+ });
289
+ const error = new MyUserError('simple-error', undefined, '简单错误');
290
+ expect(error.type).toBe('simple-error');
291
+ expect(error.message).toBe('简单错误');
292
+ expect(error.context).toBeUndefined();
293
+ });
294
+ it('应该支持不传 message 参数', () => {
295
+ const MyUserError = UserError.define({
296
+ 'no-message': {}
297
+ });
298
+ const error = new MyUserError('no-message');
299
+ expect(error.type).toBe('no-message');
300
+ expect(error.message).toBe('');
301
+ });
302
+ it('应该暴露所有定义的错误类型', () => {
303
+ const MyUserError = UserError.define({
304
+ 'validation-failed': {},
305
+ 'permission-denied': {},
306
+ 'not-found': {}
307
+ });
308
+ expect(MyUserError.types).toEqual(['validation-failed', 'permission-denied', 'not-found']);
309
+ expect(MyUserError.types).toHaveLength(3);
310
+ });
311
+ });
312
+ describe('SystemError.define', () => {
313
+ it('应该定义一个绑定了特定错误类型的 SystemError 类', () => {
314
+ const MySystemError = SystemError.define({
315
+ 'database-error': {},
316
+ 'network-error': {},
317
+ 'service-unavailable': {}
318
+ });
319
+ const error = new MySystemError('database-error', {
320
+ query: 'SELECT * FROM users',
321
+ table: 'users'
322
+ }, '数据库错误');
323
+ expect(error).toBeInstanceOf(Error);
324
+ expect(error.name).toBe('SystemError');
325
+ expect(error.type).toBe('database-error');
326
+ expect(error.message).toBe('数据库错误');
327
+ expect(error.context).toEqual({ query: 'SELECT * FROM users', table: 'users' });
328
+ });
329
+ it('应该支持 is 类型守卫', () => {
330
+ const MySystemError = SystemError.define({
331
+ 'test-error': {}
332
+ });
333
+ const error = new MySystemError('test-error', { code: 500 }, '测试错误');
334
+ expect(MySystemError.is(error)).toBe(true);
335
+ expect(MySystemError.is(new Error('普通错误'))).toBe(false);
336
+ expect(MySystemError.is(null)).toBe(false);
337
+ });
338
+ it('应该支持多次调用 define 定义不同的错误类', () => {
339
+ const DatabaseError = SystemError.define({
340
+ 'connection-failed': {},
341
+ 'query-timeout': {}
342
+ });
343
+ const NetworkError = SystemError.define({
344
+ 'request-failed': {},
345
+ 'timeout': {}
346
+ });
347
+ const dbError = new DatabaseError('connection-failed', { host: 'localhost', port: 5432 }, '连接失败');
348
+ const netError = new NetworkError('request-failed', { url: '/api/data', method: 'GET' }, '请求失败');
349
+ expect(dbError.type).toBe('connection-failed');
350
+ expect(netError.type).toBe('request-failed');
351
+ expect(DatabaseError.is(dbError)).toBe(true);
352
+ expect(DatabaseError.is(netError)).toBe(false); // 不同的类不会互相识别
353
+ expect(NetworkError.is(netError)).toBe(true);
354
+ expect(NetworkError.is(dbError)).toBe(false); // 不同的类不会互相识别
355
+ });
356
+ it('应该支持不传 context 参数', () => {
357
+ const MySystemError = SystemError.define({
358
+ 'simple-error': {}
359
+ });
360
+ const error = new MySystemError('simple-error', undefined, '简单错误');
361
+ expect(error.type).toBe('simple-error');
362
+ expect(error.message).toBe('简单错误');
363
+ expect(error.context).toBeUndefined();
364
+ });
365
+ it('应该支持不传 message 参数', () => {
366
+ const MySystemError = SystemError.define({
367
+ 'no-message': {}
368
+ });
369
+ const error = new MySystemError('no-message');
370
+ expect(error.type).toBe('no-message');
371
+ expect(error.message).toBe('');
372
+ });
373
+ it('应该暴露所有定义的错误类型', () => {
374
+ const MySystemError = SystemError.define({
375
+ 'database-error': {},
376
+ 'network-error': {},
377
+ 'service-unavailable': {}
378
+ });
379
+ expect(MySystemError.types).toEqual(['database-error', 'network-error', 'service-unavailable']);
380
+ expect(MySystemError.types).toHaveLength(3);
381
+ });
382
+ });
383
+ });
@@ -1,2 +1,3 @@
1
- export { UserError, SystemError, UnknownError, UserErrorTypes, SystemErrorTypes, UserErrorType, SystemErrorType, UserErrorContext, SystemErrorContext } from './error';
1
+ export { UserError, SystemError } from './error';
2
+ export type { ErrorContext } from './error';
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../source/error/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,WAAW,EACX,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EACnB,MAAM,SAAS,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../source/error/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,WAAW,EACZ,MAAM,SAAS,CAAA;AAEhB,YAAY,EACV,YAAY,EACb,MAAM,SAAS,CAAA"}
@@ -1 +1 @@
1
- export { UserError, SystemError, UnknownError } from './error';
1
+ export { UserError, SystemError } from './error';
@@ -0,0 +1,6 @@
1
+ export declare class Disposer {
2
+ private cleanupFunctions;
3
+ addDisposer(cleanupFn: () => unknown): void;
4
+ dispose(): void;
5
+ }
6
+ //# sourceMappingURL=disposer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disposer.d.ts","sourceRoot":"","sources":["../../source/events/disposer.ts"],"names":[],"mappings":"AAAA,qBAAa,QAAQ;IACnB,OAAO,CAAC,gBAAgB,CAAyB;IAGjD,WAAW,CAAC,SAAS,EAAE,MAAM,OAAO,GAAG,IAAI;IAK3C,OAAO,IAAI,IAAI;CAUhB"}
@@ -0,0 +1,19 @@
1
+ export class Disposer {
2
+ cleanupFunctions = [];
3
+ // 添加清理函数
4
+ addDisposer(cleanupFn) {
5
+ this.cleanupFunctions.push(cleanupFn);
6
+ }
7
+ // 执行所有清理函数
8
+ dispose() {
9
+ for (const cleanupFn of this.cleanupFunctions) {
10
+ try {
11
+ cleanupFn();
12
+ }
13
+ catch (error) {
14
+ console.error('Error during cleanup:', error);
15
+ }
16
+ }
17
+ this.cleanupFunctions = []; // 清空清理函数列表
18
+ }
19
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=disposer.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disposer.test.d.ts","sourceRoot":"","sources":["../../source/events/disposer.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,192 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+ import { Disposer } from './disposer';
3
+ describe('Disposer', () => {
4
+ let disposer;
5
+ beforeEach(() => {
6
+ disposer = new Disposer();
7
+ });
8
+ describe('addDisposer', () => {
9
+ it('应该能够添加清理函数', () => {
10
+ const cleanupFn = vi.fn();
11
+ expect(() => {
12
+ disposer.addDisposer(cleanupFn);
13
+ }).not.toThrow();
14
+ });
15
+ it('应该能够添加多个清理函数', () => {
16
+ const cleanupFn1 = vi.fn();
17
+ const cleanupFn2 = vi.fn();
18
+ const cleanupFn3 = vi.fn();
19
+ disposer.addDisposer(cleanupFn1);
20
+ disposer.addDisposer(cleanupFn2);
21
+ disposer.addDisposer(cleanupFn3);
22
+ disposer.dispose();
23
+ expect(cleanupFn1).toHaveBeenCalledOnce();
24
+ expect(cleanupFn2).toHaveBeenCalledOnce();
25
+ expect(cleanupFn3).toHaveBeenCalledOnce();
26
+ });
27
+ it('应该能够添加返回不同类型的清理函数', () => {
28
+ const voidFn = vi.fn(() => { });
29
+ const stringFn = vi.fn(() => 'cleanup result');
30
+ const numberFn = vi.fn(() => 42);
31
+ const promiseFn = vi.fn(() => Promise.resolve('async cleanup'));
32
+ disposer.addDisposer(voidFn);
33
+ disposer.addDisposer(stringFn);
34
+ disposer.addDisposer(numberFn);
35
+ disposer.addDisposer(promiseFn);
36
+ disposer.dispose();
37
+ expect(voidFn).toHaveBeenCalled();
38
+ expect(stringFn).toHaveBeenCalled();
39
+ expect(numberFn).toHaveBeenCalled();
40
+ expect(promiseFn).toHaveBeenCalled();
41
+ });
42
+ });
43
+ describe('dispose', () => {
44
+ it('应该执行所有清理函数', () => {
45
+ const cleanupFn1 = vi.fn();
46
+ const cleanupFn2 = vi.fn();
47
+ const cleanupFn3 = vi.fn();
48
+ disposer.addDisposer(cleanupFn1);
49
+ disposer.addDisposer(cleanupFn2);
50
+ disposer.addDisposer(cleanupFn3);
51
+ disposer.dispose();
52
+ expect(cleanupFn1).toHaveBeenCalledOnce();
53
+ expect(cleanupFn2).toHaveBeenCalledOnce();
54
+ expect(cleanupFn3).toHaveBeenCalledOnce();
55
+ });
56
+ it('应该按添加顺序执行清理函数', () => {
57
+ const executionOrder = [];
58
+ disposer.addDisposer(() => executionOrder.push(1));
59
+ disposer.addDisposer(() => executionOrder.push(2));
60
+ disposer.addDisposer(() => executionOrder.push(3));
61
+ disposer.dispose();
62
+ expect(executionOrder).toEqual([1, 2, 3]);
63
+ });
64
+ it('应该处理清理函数中的错误', () => {
65
+ const workingFn1 = vi.fn();
66
+ const errorFn = vi.fn(() => {
67
+ throw new Error('Cleanup error');
68
+ });
69
+ const workingFn2 = vi.fn();
70
+ // 模拟 console.error
71
+ const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
72
+ disposer.addDisposer(workingFn1);
73
+ disposer.addDisposer(errorFn);
74
+ disposer.addDisposer(workingFn2);
75
+ // dispose 不应该抛出错误
76
+ expect(() => {
77
+ disposer.dispose();
78
+ }).not.toThrow();
79
+ // 所有函数都应该被调用
80
+ expect(workingFn1).toHaveBeenCalled();
81
+ expect(errorFn).toHaveBeenCalled();
82
+ expect(workingFn2).toHaveBeenCalled();
83
+ // 错误应该被记录
84
+ expect(consoleSpy).toHaveBeenCalledWith('Error during cleanup:', expect.any(Error));
85
+ consoleSpy.mockRestore();
86
+ });
87
+ it('应该在执行后清空清理函数列表', () => {
88
+ const cleanupFn = vi.fn();
89
+ disposer.addDisposer(cleanupFn);
90
+ disposer.dispose();
91
+ expect(cleanupFn).toHaveBeenCalledOnce();
92
+ // 再次调用 dispose 不应该执行任何函数
93
+ disposer.dispose();
94
+ expect(cleanupFn).toHaveBeenCalledOnce();
95
+ });
96
+ it('应该能够在清空后重新添加清理函数', () => {
97
+ const firstCleanup = vi.fn();
98
+ const secondCleanup = vi.fn();
99
+ disposer.addDisposer(firstCleanup);
100
+ disposer.dispose();
101
+ disposer.addDisposer(secondCleanup);
102
+ disposer.dispose();
103
+ expect(firstCleanup).toHaveBeenCalledOnce();
104
+ expect(secondCleanup).toHaveBeenCalledOnce();
105
+ });
106
+ it('应该在没有清理函数时安全执行', () => {
107
+ expect(() => {
108
+ disposer.dispose();
109
+ }).not.toThrow();
110
+ });
111
+ it('应该能够多次调用 dispose', () => {
112
+ const cleanupFn = vi.fn();
113
+ disposer.addDisposer(cleanupFn);
114
+ disposer.dispose();
115
+ disposer.dispose();
116
+ disposer.dispose();
117
+ expect(cleanupFn).toHaveBeenCalledOnce();
118
+ });
119
+ });
120
+ describe('实际使用场景', () => {
121
+ it('应该能够清理事件监听器', () => {
122
+ const removeEventListener = vi.fn();
123
+ const unsubscribe = vi.fn();
124
+ disposer.addDisposer(removeEventListener);
125
+ disposer.addDisposer(unsubscribe);
126
+ disposer.dispose();
127
+ expect(removeEventListener).toHaveBeenCalled();
128
+ expect(unsubscribe).toHaveBeenCalled();
129
+ });
130
+ it('应该能够清理定时器', () => {
131
+ const clearTimeout = vi.fn();
132
+ const clearInterval = vi.fn();
133
+ disposer.addDisposer(() => clearTimeout(123));
134
+ disposer.addDisposer(() => clearInterval(456));
135
+ disposer.dispose();
136
+ expect(clearTimeout).toHaveBeenCalledWith(123);
137
+ expect(clearInterval).toHaveBeenCalledWith(456);
138
+ });
139
+ it('应该能够清理资源连接', () => {
140
+ const closeConnection = vi.fn();
141
+ const releaseResource = vi.fn();
142
+ disposer.addDisposer(() => closeConnection());
143
+ disposer.addDisposer(() => releaseResource());
144
+ disposer.dispose();
145
+ expect(closeConnection).toHaveBeenCalled();
146
+ expect(releaseResource).toHaveBeenCalled();
147
+ });
148
+ it('应该与 EventEmitter 配合使用', () => {
149
+ // 模拟 EventEmitter 的使用
150
+ const mockEventEmitter = {
151
+ on: vi.fn().mockReturnValue(vi.fn()), // 返回 off 函数
152
+ cleanup: vi.fn()
153
+ };
154
+ const offFunction1 = mockEventEmitter.on('event1', vi.fn());
155
+ const offFunction2 = mockEventEmitter.on('event2', vi.fn());
156
+ disposer.addDisposer(offFunction1);
157
+ disposer.addDisposer(offFunction2);
158
+ disposer.addDisposer(() => mockEventEmitter.cleanup());
159
+ disposer.dispose();
160
+ expect(offFunction1).toHaveBeenCalled();
161
+ expect(offFunction2).toHaveBeenCalled();
162
+ expect(mockEventEmitter.cleanup).toHaveBeenCalled();
163
+ });
164
+ });
165
+ describe('错误处理', () => {
166
+ it('应该捕获并记录同步错误', () => {
167
+ const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
168
+ const error = new Error('Sync error');
169
+ disposer.addDisposer(() => {
170
+ throw error;
171
+ });
172
+ disposer.dispose();
173
+ expect(consoleSpy).toHaveBeenCalledWith('Error during cleanup:', error);
174
+ consoleSpy.mockRestore();
175
+ });
176
+ it('应该处理不同类型的错误', () => {
177
+ const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
178
+ disposer.addDisposer(() => {
179
+ throw new TypeError('Type error');
180
+ });
181
+ disposer.addDisposer(() => {
182
+ throw 'String error';
183
+ });
184
+ disposer.addDisposer(() => {
185
+ throw { message: 'Object error' };
186
+ });
187
+ disposer.dispose();
188
+ expect(consoleSpy).toHaveBeenCalledTimes(3);
189
+ consoleSpy.mockRestore();
190
+ });
191
+ });
192
+ });