@taicode/common-base 1.0.2 → 1.1.1

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 (132) hide show
  1. package/README.md +121 -0
  2. package/output/catch/catch.d.ts +9 -0
  3. package/output/catch/catch.d.ts.map +1 -0
  4. package/output/catch/catch.js +26 -0
  5. package/output/catch/catch.test.d.ts +2 -0
  6. package/output/catch/catch.test.d.ts.map +1 -0
  7. package/output/catch/catch.test.js +258 -0
  8. package/output/catch/index.d.ts +2 -0
  9. package/output/catch/index.d.ts.map +1 -0
  10. package/output/catch/index.js +1 -0
  11. package/output/color/color.d.ts +6 -0
  12. package/output/color/color.d.ts.map +1 -0
  13. package/output/color/color.js +57 -0
  14. package/output/color/color.test.d.ts +2 -0
  15. package/output/color/color.test.d.ts.map +1 -0
  16. package/output/color/color.test.js +110 -0
  17. package/output/color/index.d.ts +2 -0
  18. package/output/color/index.d.ts.map +1 -0
  19. package/output/color/index.js +1 -0
  20. package/output/debounce/debounce.d.ts +7 -0
  21. package/output/debounce/debounce.d.ts.map +1 -0
  22. package/output/debounce/debounce.js +36 -0
  23. package/output/debounce/debounce.test.d.ts +2 -0
  24. package/output/debounce/debounce.test.d.ts.map +1 -0
  25. package/output/debounce/debounce.test.js +135 -0
  26. package/output/debounce/index.d.ts +2 -0
  27. package/output/debounce/index.d.ts.map +1 -0
  28. package/output/debounce/index.js +1 -0
  29. package/output/disposer/disposer.d.ts +6 -0
  30. package/output/disposer/disposer.d.ts.map +1 -0
  31. package/output/disposer/disposer.js +19 -0
  32. package/output/disposer/disposer.test.d.ts +2 -0
  33. package/output/disposer/disposer.test.d.ts.map +1 -0
  34. package/output/disposer/disposer.test.js +192 -0
  35. package/output/disposer/index.d.ts +2 -0
  36. package/output/disposer/index.d.ts.map +1 -0
  37. package/output/disposer/index.js +1 -0
  38. package/output/error/error.d.ts +23 -0
  39. package/output/error/error.d.ts.map +1 -0
  40. package/output/error/error.js +37 -0
  41. package/output/error/error.test.d.ts +2 -0
  42. package/output/error/error.test.d.ts.map +1 -0
  43. package/output/error/error.test.js +242 -0
  44. package/output/error/index.d.ts +2 -0
  45. package/output/error/index.d.ts.map +1 -0
  46. package/output/error/index.js +1 -0
  47. package/output/event-emitter/event-emitter.d.ts +33 -0
  48. package/output/event-emitter/event-emitter.d.ts.map +1 -0
  49. package/output/event-emitter/event-emitter.js +66 -0
  50. package/output/event-emitter/event-emitter.test.d.ts +2 -0
  51. package/output/event-emitter/event-emitter.test.d.ts.map +1 -0
  52. package/output/event-emitter/event-emitter.test.js +177 -0
  53. package/output/event-emitter/index.d.ts +2 -0
  54. package/output/event-emitter/index.d.ts.map +1 -0
  55. package/output/event-emitter/index.js +1 -0
  56. package/output/events/disposer.d.ts +6 -0
  57. package/output/events/disposer.d.ts.map +1 -0
  58. package/output/events/disposer.js +19 -0
  59. package/output/events/disposer.test.d.ts +2 -0
  60. package/output/events/disposer.test.d.ts.map +1 -0
  61. package/output/events/disposer.test.js +192 -0
  62. package/output/events/event-emitter.d.ts +33 -0
  63. package/output/events/event-emitter.d.ts.map +1 -0
  64. package/output/events/event-emitter.js +66 -0
  65. package/output/events/event-emitter.test.d.ts +2 -0
  66. package/output/events/event-emitter.test.d.ts.map +1 -0
  67. package/output/events/event-emitter.test.js +213 -0
  68. package/output/events/index.d.ts +3 -0
  69. package/output/events/index.d.ts.map +1 -0
  70. package/output/events/index.js +3 -0
  71. package/output/index.d.ts +11 -0
  72. package/output/index.d.ts.map +1 -0
  73. package/output/index.js +15 -0
  74. package/output/logger/index.d.ts +18 -0
  75. package/output/logger/index.d.ts.map +1 -0
  76. package/output/logger/index.js +34 -0
  77. package/output/logger/logger.test.d.ts +2 -0
  78. package/output/logger/logger.test.d.ts.map +1 -0
  79. package/output/logger/logger.test.js +33 -0
  80. package/output/number/index.d.ts +2 -0
  81. package/output/number/index.d.ts.map +1 -0
  82. package/output/number/index.js +1 -0
  83. package/output/number/number.d.ts +2 -0
  84. package/output/number/number.d.ts.map +1 -0
  85. package/output/number/number.js +23 -0
  86. package/output/number/number.test.d.ts +2 -0
  87. package/output/number/number.test.d.ts.map +1 -0
  88. package/output/number/number.test.js +50 -0
  89. package/output/object/index.d.ts +2 -0
  90. package/output/object/index.d.ts.map +1 -0
  91. package/output/object/index.js +1 -0
  92. package/output/object/object.d.ts +7 -0
  93. package/output/object/object.d.ts.map +1 -0
  94. package/output/object/object.js +27 -0
  95. package/output/object/object.test.d.ts +2 -0
  96. package/output/object/object.test.d.ts.map +1 -0
  97. package/output/object/object.test.js +42 -0
  98. package/output/service/index.d.ts +3 -0
  99. package/output/service/index.d.ts.map +1 -0
  100. package/output/service/index.js +2 -0
  101. package/output/string/index.d.ts +2 -0
  102. package/output/string/index.d.ts.map +1 -0
  103. package/output/string/index.js +1 -0
  104. package/output/string/string.d.ts +3 -0
  105. package/output/string/string.d.ts.map +1 -0
  106. package/output/string/string.js +9 -0
  107. package/output/string/string.test.d.ts +2 -0
  108. package/output/string/string.test.d.ts.map +1 -0
  109. package/output/string/string.test.js +77 -0
  110. package/output/throttle/index.d.ts +2 -0
  111. package/output/throttle/index.d.ts.map +1 -0
  112. package/output/throttle/index.js +1 -0
  113. package/output/throttle/throttle.d.ts +12 -0
  114. package/output/throttle/throttle.d.ts.map +1 -0
  115. package/output/throttle/throttle.js +55 -0
  116. package/output/throttle/throttle.test.d.ts +2 -0
  117. package/output/throttle/throttle.test.d.ts.map +1 -0
  118. package/output/throttle/throttle.test.js +177 -0
  119. package/package.json +24 -3
  120. package/source/decorators/debounce.ts +0 -25
  121. package/source/utils/color/index.ts +0 -66
  122. package/source/utils/disposer/disposer.ts +0 -20
  123. package/source/utils/event-emitter/index.ts +0 -77
  124. package/source/utils/number/index.ts +0 -25
  125. package/source/utils/object/index.test.ts +0 -54
  126. package/source/utils/object/index.ts +0 -29
  127. package/source/utils/poller/index.test.ts +0 -62
  128. package/source/utils/poller/index.ts +0 -57
  129. package/source/utils/promise/index.test.ts +0 -38
  130. package/source/utils/promise/index.ts +0 -45
  131. package/source/utils/string/index.ts +0 -9
  132. package/tsconfig.json +0 -103
@@ -0,0 +1,242 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { UserError, SystemError, UnknownError } from './error';
3
+ describe('UserError', () => {
4
+ describe('constructor', () => {
5
+ it('应该正确创建UserError实例', () => {
6
+ const type = 'VALIDATION_ERROR';
7
+ const message = '输入验证失败';
8
+ const error = new UserError(type, message);
9
+ expect(error).toBeInstanceOf(Error);
10
+ expect(error).toBeInstanceOf(UserError);
11
+ expect(error.name).toBe('UserError');
12
+ expect(error.type).toBe(type);
13
+ expect(error.message).toBe(message);
14
+ });
15
+ it('应该支持ErrorOptions参数', () => {
16
+ const type = 'VALIDATION_ERROR';
17
+ const message = '输入验证失败';
18
+ const cause = new Error('原始错误');
19
+ const error = new UserError(type, message, { cause });
20
+ expect(error.cause).toBe(cause);
21
+ });
22
+ it('应该正确设置错误堆栈信息', () => {
23
+ const error = new UserError('TEST_ERROR', '测试错误');
24
+ expect(error.stack).toBeDefined();
25
+ expect(error.stack).toContain('UserError');
26
+ });
27
+ });
28
+ describe('is', () => {
29
+ it('应该正确识别UserError实例', () => {
30
+ const error = new UserError('TEST_ERROR', '测试错误');
31
+ expect(UserError.is(error)).toBe(true);
32
+ });
33
+ it('应该正确识别非UserError实例', () => {
34
+ const regularError = new Error('普通错误');
35
+ const systemError = new SystemError('SYSTEM_ERROR', '系统错误');
36
+ const unknownError = new UnknownError('未知错误');
37
+ expect(UserError.is(regularError)).toBe(false);
38
+ expect(UserError.is(systemError)).toBe(false);
39
+ expect(UserError.is(unknownError)).toBe(false);
40
+ expect(UserError.is(null)).toBe(false);
41
+ expect(UserError.is(undefined)).toBe(false);
42
+ expect(UserError.is('字符串')).toBe(false);
43
+ expect(UserError.is(123)).toBe(false);
44
+ expect(UserError.is({})).toBe(false);
45
+ });
46
+ it('应该支持类型守卫功能', () => {
47
+ const error = new UserError('TEST_ERROR', '测试错误');
48
+ if (UserError.is(error)) {
49
+ // 在类型守卫内部,error的类型应该被正确推断
50
+ expect(error.type).toBe('TEST_ERROR');
51
+ expect(error.message).toBe('测试错误');
52
+ expect(error.name).toBe('UserError');
53
+ }
54
+ });
55
+ });
56
+ describe('继承行为', () => {
57
+ it('应该正确继承Error的所有属性和方法', () => {
58
+ const error = new UserError('TEST_ERROR', '测试错误');
59
+ expect(error.toString()).toContain('测试错误');
60
+ expect(error.toString()).toContain('UserError');
61
+ expect(error instanceof Error).toBe(true);
62
+ });
63
+ it('应该支持Error的标准用法', () => {
64
+ const error = new UserError('TEST_ERROR', '测试错误');
65
+ try {
66
+ throw error;
67
+ }
68
+ catch (caught) {
69
+ expect(caught).toBe(error);
70
+ expect(caught).toBeInstanceOf(UserError);
71
+ }
72
+ });
73
+ });
74
+ });
75
+ describe('SystemError', () => {
76
+ describe('constructor', () => {
77
+ it('应该正确创建SystemError实例', () => {
78
+ const type = 'DATABASE_ERROR';
79
+ const message = '数据库连接失败';
80
+ const error = new SystemError(type, message);
81
+ expect(error).toBeInstanceOf(Error);
82
+ expect(error).toBeInstanceOf(SystemError);
83
+ expect(error.name).toBe('SystemError');
84
+ expect(error.type).toBe(type);
85
+ expect(error.message).toBe(message);
86
+ });
87
+ it('应该支持ErrorOptions参数', () => {
88
+ const type = 'NETWORK_ERROR';
89
+ const message = '网络请求失败';
90
+ const cause = new Error('连接超时');
91
+ const error = new SystemError(type, message, { cause });
92
+ expect(error.cause).toBe(cause);
93
+ });
94
+ it('应该正确设置错误堆栈信息', () => {
95
+ const error = new SystemError('FILE_ERROR', '文件读取失败');
96
+ expect(error.stack).toBeDefined();
97
+ expect(error.stack).toContain('SystemError');
98
+ });
99
+ });
100
+ describe('is', () => {
101
+ it('应该正确识别SystemError实例', () => {
102
+ const error = new SystemError('TEST_ERROR', '测试错误');
103
+ expect(SystemError.is(error)).toBe(true);
104
+ });
105
+ it('应该正确识别非SystemError实例', () => {
106
+ const regularError = new Error('普通错误');
107
+ const userError = new UserError('USER_ERROR', '用户错误');
108
+ const unknownError = new UnknownError('未知错误');
109
+ expect(SystemError.is(regularError)).toBe(false);
110
+ expect(SystemError.is(userError)).toBe(false);
111
+ expect(SystemError.is(unknownError)).toBe(false);
112
+ expect(SystemError.is(null)).toBe(false);
113
+ expect(SystemError.is(undefined)).toBe(false);
114
+ expect(SystemError.is('字符串')).toBe(false);
115
+ expect(SystemError.is(123)).toBe(false);
116
+ expect(SystemError.is({})).toBe(false);
117
+ });
118
+ it('应该支持类型守卫功能', () => {
119
+ const error = new SystemError('DATABASE_ERROR', '数据库错误');
120
+ if (SystemError.is(error)) {
121
+ // 在类型守卫内部,error的类型应该被正确推断
122
+ expect(error.type).toBe('DATABASE_ERROR');
123
+ expect(error.message).toBe('数据库错误');
124
+ expect(error.name).toBe('SystemError');
125
+ }
126
+ });
127
+ });
128
+ describe('继承行为', () => {
129
+ it('应该正确继承Error的所有属性和方法', () => {
130
+ const error = new SystemError('TEST_ERROR', '测试错误');
131
+ expect(error.toString()).toContain('测试错误');
132
+ expect(error.toString()).toContain('SystemError');
133
+ expect(error instanceof Error).toBe(true);
134
+ });
135
+ it('应该支持Error的标准用法', () => {
136
+ const error = new SystemError('TEST_ERROR', '测试错误');
137
+ try {
138
+ throw error;
139
+ }
140
+ catch (caught) {
141
+ expect(caught).toBe(error);
142
+ expect(caught).toBeInstanceOf(SystemError);
143
+ }
144
+ });
145
+ });
146
+ });
147
+ describe('UnknownError', () => {
148
+ describe('constructor', () => {
149
+ it('应该正确创建UnknownError实例', () => {
150
+ const message = '发生了未知错误';
151
+ const error = new UnknownError(message);
152
+ expect(error).toBeInstanceOf(Error);
153
+ expect(error).toBeInstanceOf(UnknownError);
154
+ expect(error.name).toBe('UnknownError');
155
+ expect(error.message).toBe(message);
156
+ });
157
+ it('应该支持ErrorOptions参数', () => {
158
+ const message = '未知错误';
159
+ const cause = new Error('原始未知错误');
160
+ const error = new UnknownError(message, { cause });
161
+ expect(error.cause).toBe(cause);
162
+ });
163
+ it('应该正确设置错误堆栈信息', () => {
164
+ const error = new UnknownError('测试未知错误');
165
+ expect(error.stack).toBeDefined();
166
+ expect(error.stack).toContain('UnknownError');
167
+ });
168
+ });
169
+ describe('is', () => {
170
+ it('应该正确识别UnknownError实例', () => {
171
+ const error = new UnknownError('测试错误');
172
+ expect(UnknownError.is(error)).toBe(true);
173
+ });
174
+ it('应该正确识别非UnknownError实例', () => {
175
+ const regularError = new Error('普通错误');
176
+ const userError = new UserError('USER_ERROR', '用户错误');
177
+ const systemError = new SystemError('SYSTEM_ERROR', '系统错误');
178
+ expect(UnknownError.is(regularError)).toBe(false);
179
+ expect(UnknownError.is(userError)).toBe(false);
180
+ expect(UnknownError.is(systemError)).toBe(false);
181
+ expect(UnknownError.is(null)).toBe(false);
182
+ expect(UnknownError.is(undefined)).toBe(false);
183
+ expect(UnknownError.is('字符串')).toBe(false);
184
+ expect(UnknownError.is(123)).toBe(false);
185
+ expect(UnknownError.is({})).toBe(false);
186
+ });
187
+ });
188
+ describe('继承行为', () => {
189
+ it('应该正确继承Error的所有属性和方法', () => {
190
+ const error = new UnknownError('测试错误');
191
+ expect(error.toString()).toContain('测试错误');
192
+ expect(error instanceof Error).toBe(true);
193
+ });
194
+ it('应该支持Error的标准用法', () => {
195
+ const error = new UnknownError('测试错误');
196
+ try {
197
+ throw error;
198
+ }
199
+ catch (caught) {
200
+ expect(caught).toBe(error);
201
+ expect(caught).toBeInstanceOf(UnknownError);
202
+ }
203
+ });
204
+ });
205
+ });
206
+ describe('错误类型区分', () => {
207
+ it('三种错误类型应该是不同的类', () => {
208
+ const userError = new UserError('USER_ERROR', '用户错误');
209
+ const systemError = new SystemError('SYSTEM_ERROR', '系统错误');
210
+ const unknownError = new UnknownError('未知错误');
211
+ // 每种错误只能被自己的类型检查函数识别
212
+ expect(UserError.is(userError)).toBe(true);
213
+ expect(SystemError.is(userError)).toBe(false);
214
+ expect(UnknownError.is(userError)).toBe(false);
215
+ expect(UserError.is(systemError)).toBe(false);
216
+ expect(SystemError.is(systemError)).toBe(true);
217
+ expect(UnknownError.is(systemError)).toBe(false);
218
+ expect(UserError.is(unknownError)).toBe(false);
219
+ expect(SystemError.is(unknownError)).toBe(false);
220
+ expect(UnknownError.is(unknownError)).toBe(true);
221
+ });
222
+ it('所有错误类型都应该是Error的实例', () => {
223
+ const userError = new UserError('USER_ERROR', '用户错误');
224
+ const systemError = new SystemError('SYSTEM_ERROR', '系统错误');
225
+ const unknownError = new UnknownError('未知错误');
226
+ expect(userError instanceof Error).toBe(true);
227
+ expect(systemError instanceof Error).toBe(true);
228
+ expect(unknownError instanceof Error).toBe(true);
229
+ });
230
+ });
231
+ describe('泛型类型支持', () => {
232
+ it('UserError应该支持字符串字面量类型', () => {
233
+ const error = new UserError('REQUIRED_FIELD', '字段必填');
234
+ expect(error.type).toBe('REQUIRED_FIELD');
235
+ expect(UserError.is(error)).toBe(true);
236
+ });
237
+ it('SystemError应该支持字符串字面量类型', () => {
238
+ const error = new SystemError('DATABASE_ERROR', '数据库连接失败');
239
+ expect(error.type).toBe('DATABASE_ERROR');
240
+ expect(SystemError.is(error)).toBe(true);
241
+ });
242
+ });
@@ -0,0 +1,2 @@
1
+ export { UserError, SystemError, UnknownError } from './error';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../source/error/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA"}
@@ -0,0 +1 @@
1
+ export { UserError, SystemError, UnknownError } from './error';
@@ -0,0 +1,33 @@
1
+ type OffFn = () => void;
2
+ type Listener<T = unknown> = (data: T) => void;
3
+ export declare class EventEmitter<Events extends object = object> {
4
+ private listeners;
5
+ constructor();
6
+ /**
7
+ * 订阅事件
8
+ * @param type 事件类型
9
+ * @param listener 回调函数
10
+ */
11
+ on<K extends keyof Events>(type: K, listener: Listener<Events[K]>): OffFn;
12
+ /**
13
+ * 取消订阅
14
+ * @param type 事件类型
15
+ * @param listener 要移除的回调函数(可选)
16
+ */
17
+ off<K extends keyof Events>(type: K, listener?: Listener<Events[K]>): void;
18
+ /**
19
+ * 触发事件
20
+ * @param type 事件类型
21
+ * @param data 要传递的数据
22
+ */
23
+ emit<K extends keyof Events>(type: K, data: Events[K]): void;
24
+ /**
25
+ * 一次性订阅
26
+ * @param type 事件类型
27
+ * @param listener 回调函数
28
+ */
29
+ once<K extends keyof Events>(type: K, listener: Listener<Events[K]>): void;
30
+ cleanup(): void;
31
+ }
32
+ export type { OffFn, Listener };
33
+ //# sourceMappingURL=event-emitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-emitter.d.ts","sourceRoot":"","sources":["../../source/event-emitter/event-emitter.ts"],"names":[],"mappings":"AAAA,KAAK,KAAK,GAAG,MAAM,IAAI,CAAA;AACvB,KAAK,QAAQ,CAAC,CAAC,GAAG,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAA;AAE9C,qBAAa,YAAY,CAAC,MAAM,SAAS,MAAM,GAAG,MAAM;IACtD,OAAO,CAAC,SAAS,CAAsD;;IAUvE;;;;OAIG;IACH,EAAE,CAAC,CAAC,SAAS,MAAM,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK;IASzE;;;;OAIG;IACH,GAAG,CAAC,CAAC,SAAS,MAAM,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI;IAc1E;;;;OAIG;IACH,IAAI,CAAC,CAAC,SAAS,MAAM,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI;IAQ5D;;;;OAIG;IACH,IAAI,CAAC,CAAC,SAAS,MAAM,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI;IAQ1E,OAAO;CAGR;AAED,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAA"}
@@ -0,0 +1,66 @@
1
+ export class EventEmitter {
2
+ listeners = {};
3
+ constructor() {
4
+ this.on = this.on.bind(this);
5
+ this.off = this.off.bind(this);
6
+ this.once = this.once.bind(this);
7
+ this.emit = this.emit.bind(this);
8
+ this.cleanup = this.cleanup.bind(this);
9
+ }
10
+ /**
11
+ * 订阅事件
12
+ * @param type 事件类型
13
+ * @param listener 回调函数
14
+ */
15
+ on(type, listener) {
16
+ if (!this.listeners[type]) {
17
+ this.listeners[type] = [];
18
+ }
19
+ this.listeners[type].push(listener);
20
+ return () => this.off(type, listener);
21
+ }
22
+ /**
23
+ * 取消订阅
24
+ * @param type 事件类型
25
+ * @param listener 要移除的回调函数(可选)
26
+ */
27
+ off(type, listener) {
28
+ if (!this.listeners[type])
29
+ return;
30
+ if (!listener) {
31
+ // 移除该事件的所有监听器
32
+ delete this.listeners[type];
33
+ }
34
+ else {
35
+ // 移除特定监听器
36
+ this.listeners[type] = this.listeners[type].filter((fn) => fn !== listener);
37
+ }
38
+ }
39
+ /**
40
+ * 触发事件
41
+ * @param type 事件类型
42
+ * @param data 要传递的数据
43
+ */
44
+ emit(type, data) {
45
+ const listeners = this.listeners[type];
46
+ // 复制数组避免回调中取消订阅导致的遍历问题
47
+ if (listeners) {
48
+ listeners.slice().forEach((fn) => fn(data));
49
+ }
50
+ }
51
+ /**
52
+ * 一次性订阅
53
+ * @param type 事件类型
54
+ * @param listener 回调函数
55
+ */
56
+ once(type, listener) {
57
+ const onceWrapper = (data) => {
58
+ listener(data);
59
+ this.off(type, onceWrapper);
60
+ };
61
+ this.on(type, onceWrapper);
62
+ }
63
+ cleanup() {
64
+ this.listeners = {};
65
+ }
66
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=event-emitter.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-emitter.test.d.ts","sourceRoot":"","sources":["../../source/event-emitter/event-emitter.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,177 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+ import { EventEmitter } from './event-emitter';
3
+ describe('EventEmitter', () => {
4
+ let emitter;
5
+ beforeEach(() => {
6
+ emitter = new EventEmitter();
7
+ });
8
+ describe('on 方法', () => {
9
+ it('应该注册监听器并返回一个关闭函数', () => {
10
+ const listener = vi.fn();
11
+ const off = emitter.on('data-update', listener);
12
+ expect(typeof off).toBe('function');
13
+ emitter.emit('data-update', 'test data');
14
+ expect(listener).toHaveBeenCalledWith('test data');
15
+ });
16
+ it('应该为同一事件注册多个监听器', () => {
17
+ const listener1 = vi.fn();
18
+ const listener2 = vi.fn();
19
+ emitter.on('data-update', listener1);
20
+ emitter.on('data-update', listener2);
21
+ emitter.emit('data-update', 'test data');
22
+ expect(listener1).toHaveBeenCalledWith('test data');
23
+ expect(listener2).toHaveBeenCalledWith('test data');
24
+ });
25
+ it('应该允许同一监听器被多次注册', () => {
26
+ const listener = vi.fn();
27
+ emitter.on('data-update', listener);
28
+ emitter.on('data-update', listener);
29
+ emitter.emit('data-update', 'test data');
30
+ expect(listener).toHaveBeenCalledTimes(2);
31
+ });
32
+ });
33
+ describe('off 方法', () => {
34
+ it('应该移除特定的监听器', () => {
35
+ const listener1 = vi.fn();
36
+ const listener2 = vi.fn();
37
+ emitter.on('data-update', listener1);
38
+ emitter.on('data-update', listener2);
39
+ emitter.off('data-update', listener1);
40
+ emitter.emit('data-update', 'test data');
41
+ expect(listener1).not.toHaveBeenCalled();
42
+ expect(listener2).toHaveBeenCalledWith('test data');
43
+ });
44
+ it('应该在没有提供特定监听器时移除所有监听器', () => {
45
+ const listener1 = vi.fn();
46
+ const listener2 = vi.fn();
47
+ emitter.on('data-update', listener1);
48
+ emitter.on('data-update', listener2);
49
+ emitter.off('data-update');
50
+ emitter.emit('data-update', 'test data');
51
+ expect(listener1).not.toHaveBeenCalled();
52
+ expect(listener2).not.toHaveBeenCalled();
53
+ });
54
+ it('应该优雅地处理移除不存在的监听器', () => {
55
+ const listener = vi.fn();
56
+ // 不应该抛出错误
57
+ expect(() => {
58
+ emitter.off('data-update', listener);
59
+ }).not.toThrow();
60
+ });
61
+ it('应该与 on 方法返回的 off 函数配合使用', () => {
62
+ const listener = vi.fn();
63
+ const off = emitter.on('data-update', listener);
64
+ off();
65
+ emitter.emit('data-update', 'test data');
66
+ expect(listener).not.toHaveBeenCalled();
67
+ });
68
+ });
69
+ describe('emit 方法', () => {
70
+ it('应该用正确的数据调用所有注册的监听器', () => {
71
+ const listener1 = vi.fn();
72
+ const listener2 = vi.fn();
73
+ const testData = { userId: 'user123', timestamp: Date.now() };
74
+ emitter.on('user-login', listener1);
75
+ emitter.on('user-login', listener2);
76
+ emitter.emit('user-login', testData);
77
+ expect(listener1).toHaveBeenCalledWith(testData);
78
+ expect(listener2).toHaveBeenCalledWith(testData);
79
+ });
80
+ it('应该优雅地处理没有监听器的事件', () => {
81
+ expect(() => {
82
+ emitter.emit('data-update', 'test data');
83
+ }).not.toThrow();
84
+ });
85
+ it('应该处理抛出错误的监听器', () => {
86
+ const goodListener = vi.fn();
87
+ const badListener = vi.fn(() => {
88
+ throw new Error('Listener error');
89
+ });
90
+ emitter.on('data-update', goodListener);
91
+ emitter.on('data-update', badListener);
92
+ expect(() => {
93
+ emitter.emit('data-update', 'test data');
94
+ }).toThrow('Listener error');
95
+ expect(goodListener).toHaveBeenCalledWith('test data');
96
+ });
97
+ it('应该创建监听器数组的副本以避免并发修改问题', () => {
98
+ const listeners = [];
99
+ // 创建一个监听器,它会在执行时移除自己
100
+ const selfRemovingListener = () => {
101
+ emitter.off('data-update', selfRemovingListener);
102
+ };
103
+ // 创建其他监听器
104
+ const otherListener = vi.fn();
105
+ emitter.on('data-update', selfRemovingListener);
106
+ emitter.on('data-update', otherListener);
107
+ // 发射事件,这应该不会导致问题
108
+ expect(() => {
109
+ emitter.emit('data-update', 'test data');
110
+ }).not.toThrow();
111
+ expect(otherListener).toHaveBeenCalledWith('test data');
112
+ });
113
+ });
114
+ describe('once 方法', () => {
115
+ it('应该注册一个只触发一次的监听器', () => {
116
+ const listener = vi.fn();
117
+ emitter.once('data-update', listener);
118
+ emitter.emit('data-update', 'first call');
119
+ emitter.emit('data-update', 'second call');
120
+ expect(listener).toHaveBeenCalledTimes(1);
121
+ expect(listener).toHaveBeenCalledWith('first call');
122
+ });
123
+ it('应该处理复杂的事件数据', () => {
124
+ const listener = vi.fn();
125
+ const testData = { userId: 'user123', timestamp: Date.now() };
126
+ emitter.once('user-login', listener);
127
+ emitter.emit('user-login', testData);
128
+ emitter.emit('user-login', { userId: 'user456', timestamp: Date.now() });
129
+ expect(listener).toHaveBeenCalledTimes(1);
130
+ expect(listener).toHaveBeenCalledWith(testData);
131
+ });
132
+ });
133
+ describe('cleanup 方法', () => {
134
+ it('应该移除所有监听器', () => {
135
+ const listener1 = vi.fn();
136
+ const listener2 = vi.fn();
137
+ emitter.on('data-update', listener1);
138
+ emitter.on('user-login', listener2);
139
+ emitter.cleanup();
140
+ emitter.emit('data-update', 'test data');
141
+ emitter.emit('user-login', { userId: 'user123', timestamp: Date.now() });
142
+ expect(listener1).not.toHaveBeenCalled();
143
+ expect(listener2).not.toHaveBeenCalled();
144
+ });
145
+ });
146
+ describe('方法绑定', () => {
147
+ it('应该将方法正确绑定到实例', () => {
148
+ const { on, off, once, emit, cleanup } = emitter;
149
+ const listener = vi.fn();
150
+ // 这些方法应该可以独立调用而不丢失上下文
151
+ expect(() => {
152
+ on('data-update', listener);
153
+ emit('data-update', 'test data');
154
+ off('data-update', listener);
155
+ once('data-update', listener);
156
+ cleanup();
157
+ }).not.toThrow();
158
+ expect(listener).toHaveBeenCalledWith('test data');
159
+ });
160
+ });
161
+ describe('类型安全', () => {
162
+ it('应该处理不同的事件类型', () => {
163
+ const loginListener = vi.fn();
164
+ const logoutListener = vi.fn();
165
+ const errorListener = vi.fn();
166
+ emitter.on('user-login', loginListener);
167
+ emitter.on('user-logout', logoutListener);
168
+ emitter.on('error', errorListener);
169
+ emitter.emit('user-login', { userId: 'user123', timestamp: Date.now() });
170
+ emitter.emit('user-logout', { userId: 'user123' });
171
+ emitter.emit('error', new Error('Test error'));
172
+ expect(loginListener).toHaveBeenCalledWith({ userId: 'user123', timestamp: expect.any(Number) });
173
+ expect(logoutListener).toHaveBeenCalledWith({ userId: 'user123' });
174
+ expect(errorListener).toHaveBeenCalledWith(expect.any(Error));
175
+ });
176
+ });
177
+ });
@@ -0,0 +1,2 @@
1
+ export * from './event-emitter';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../source/event-emitter/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA"}
@@ -0,0 +1 @@
1
+ export * from './event-emitter';
@@ -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":""}