@taicode/common-base 1.1.0 → 1.1.2

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 (157) hide show
  1. package/output/catch/catch.d.ts +9 -0
  2. package/output/catch/catch.d.ts.map +1 -0
  3. package/output/catch/catch.js +26 -0
  4. package/output/catch/catch.test.d.ts +2 -0
  5. package/output/catch/catch.test.d.ts.map +1 -0
  6. package/output/catch/catch.test.js +258 -0
  7. package/output/catch/index.d.ts +2 -0
  8. package/output/catch/index.d.ts.map +1 -0
  9. package/output/catch/index.js +1 -0
  10. package/output/color/color.d.ts +6 -0
  11. package/output/color/color.d.ts.map +1 -0
  12. package/output/color/color.js +57 -0
  13. package/output/color/color.test.d.ts +2 -0
  14. package/output/color/color.test.d.ts.map +1 -0
  15. package/output/color/color.test.js +110 -0
  16. package/output/color/index.d.ts +2 -0
  17. package/output/color/index.d.ts.map +1 -0
  18. package/output/color/index.js +1 -0
  19. package/output/debounce/debounce.d.ts +7 -0
  20. package/output/debounce/debounce.d.ts.map +1 -0
  21. package/output/debounce/debounce.js +36 -0
  22. package/output/debounce/debounce.test.d.ts +2 -0
  23. package/output/debounce/debounce.test.d.ts.map +1 -0
  24. package/output/debounce/debounce.test.js +135 -0
  25. package/output/debounce/index.d.ts +2 -0
  26. package/output/debounce/index.d.ts.map +1 -0
  27. package/output/debounce/index.js +1 -0
  28. package/output/disposer/disposer.d.ts +6 -0
  29. package/output/disposer/disposer.d.ts.map +1 -0
  30. package/output/disposer/disposer.js +19 -0
  31. package/output/disposer/disposer.test.d.ts +2 -0
  32. package/output/disposer/disposer.test.d.ts.map +1 -0
  33. package/output/disposer/disposer.test.js +192 -0
  34. package/output/disposer/index.d.ts +2 -0
  35. package/output/disposer/index.d.ts.map +1 -0
  36. package/output/disposer/index.js +1 -0
  37. package/output/error/error.d.ts +23 -0
  38. package/output/error/error.d.ts.map +1 -0
  39. package/output/error/error.js +37 -0
  40. package/output/error/error.test.d.ts +2 -0
  41. package/output/error/error.test.d.ts.map +1 -0
  42. package/output/error/error.test.js +242 -0
  43. package/output/error/index.d.ts +2 -0
  44. package/output/error/index.d.ts.map +1 -0
  45. package/output/error/index.js +1 -0
  46. package/output/event-emitter/event-emitter.d.ts +33 -0
  47. package/output/event-emitter/event-emitter.d.ts.map +1 -0
  48. package/output/event-emitter/event-emitter.js +66 -0
  49. package/output/event-emitter/event-emitter.test.d.ts +2 -0
  50. package/output/event-emitter/event-emitter.test.d.ts.map +1 -0
  51. package/output/event-emitter/event-emitter.test.js +177 -0
  52. package/output/event-emitter/index.d.ts +2 -0
  53. package/output/event-emitter/index.d.ts.map +1 -0
  54. package/output/event-emitter/index.js +1 -0
  55. package/output/events/disposer.d.ts +6 -0
  56. package/output/events/disposer.d.ts.map +1 -0
  57. package/output/events/disposer.js +19 -0
  58. package/output/events/disposer.test.d.ts +2 -0
  59. package/output/events/disposer.test.d.ts.map +1 -0
  60. package/output/events/disposer.test.js +192 -0
  61. package/output/events/event-emitter.d.ts +33 -0
  62. package/output/events/event-emitter.d.ts.map +1 -0
  63. package/output/events/event-emitter.js +66 -0
  64. package/output/events/event-emitter.test.d.ts +2 -0
  65. package/output/events/event-emitter.test.d.ts.map +1 -0
  66. package/output/events/event-emitter.test.js +213 -0
  67. package/output/events/index.d.ts +3 -0
  68. package/output/events/index.d.ts.map +1 -0
  69. package/output/events/index.js +3 -0
  70. package/output/index.d.ts +11 -0
  71. package/output/index.d.ts.map +1 -0
  72. package/output/index.js +15 -0
  73. package/output/logger/index.d.ts +18 -0
  74. package/output/logger/index.d.ts.map +1 -0
  75. package/output/logger/index.js +34 -0
  76. package/output/logger/logger.test.d.ts +2 -0
  77. package/output/logger/logger.test.d.ts.map +1 -0
  78. package/output/logger/logger.test.js +33 -0
  79. package/output/number/index.d.ts +2 -0
  80. package/output/number/index.d.ts.map +1 -0
  81. package/output/number/index.js +1 -0
  82. package/output/number/number.d.ts +2 -0
  83. package/output/number/number.d.ts.map +1 -0
  84. package/output/number/number.js +23 -0
  85. package/output/number/number.test.d.ts +2 -0
  86. package/output/number/number.test.d.ts.map +1 -0
  87. package/output/number/number.test.js +50 -0
  88. package/output/object/index.d.ts +2 -0
  89. package/output/object/index.d.ts.map +1 -0
  90. package/output/object/index.js +1 -0
  91. package/output/object/object.d.ts +7 -0
  92. package/output/object/object.d.ts.map +1 -0
  93. package/output/object/object.js +27 -0
  94. package/output/object/object.test.d.ts +2 -0
  95. package/output/object/object.test.d.ts.map +1 -0
  96. package/output/object/object.test.js +42 -0
  97. package/output/service/index.d.ts +2 -0
  98. package/output/service/index.d.ts.map +1 -0
  99. package/output/service/index.js +1 -0
  100. package/output/service/service.d.ts +6 -0
  101. package/output/service/service.d.ts.map +1 -0
  102. package/output/service/service.js +3 -0
  103. package/output/string/index.d.ts +2 -0
  104. package/output/string/index.d.ts.map +1 -0
  105. package/output/string/index.js +1 -0
  106. package/output/string/string.d.ts +3 -0
  107. package/output/string/string.d.ts.map +1 -0
  108. package/output/string/string.js +9 -0
  109. package/output/string/string.test.d.ts +2 -0
  110. package/output/string/string.test.d.ts.map +1 -0
  111. package/output/string/string.test.js +77 -0
  112. package/output/throttle/index.d.ts +2 -0
  113. package/output/throttle/index.d.ts.map +1 -0
  114. package/output/throttle/index.js +1 -0
  115. package/output/throttle/throttle.d.ts +12 -0
  116. package/output/throttle/throttle.d.ts.map +1 -0
  117. package/output/throttle/throttle.js +55 -0
  118. package/output/throttle/throttle.test.d.ts +2 -0
  119. package/output/throttle/throttle.test.d.ts.map +1 -0
  120. package/output/throttle/throttle.test.js +177 -0
  121. package/package.json +4 -1
  122. package/source/catch/catch.test.ts +0 -341
  123. package/source/catch/catch.ts +0 -35
  124. package/source/catch/index.ts +0 -1
  125. package/source/color/color.test.ts +0 -144
  126. package/source/color/color.ts +0 -73
  127. package/source/color/index.ts +0 -1
  128. package/source/debounce/debounce.test.ts +0 -179
  129. package/source/debounce/debounce.ts +0 -42
  130. package/source/debounce/index.ts +0 -1
  131. package/source/disposer/disposer.test.ts +0 -257
  132. package/source/disposer/disposer.ts +0 -20
  133. package/source/disposer/index.ts +0 -1
  134. package/source/error/error.test.ts +0 -293
  135. package/source/error/error.ts +0 -38
  136. package/source/error/index.ts +0 -1
  137. package/source/event-emitter/event-emitter.test.ts +0 -247
  138. package/source/event-emitter/event-emitter.ts +0 -79
  139. package/source/event-emitter/index.ts +0 -1
  140. package/source/index.ts +0 -19
  141. package/source/logger/index.ts +0 -43
  142. package/source/logger/logger.test.ts +0 -36
  143. package/source/number/index.ts +0 -1
  144. package/source/number/number.test.ts +0 -60
  145. package/source/number/number.ts +0 -25
  146. package/source/object/index.ts +0 -1
  147. package/source/object/object.test.ts +0 -54
  148. package/source/object/object.ts +0 -29
  149. package/source/string/index.ts +0 -1
  150. package/source/string/string.test.ts +0 -98
  151. package/source/string/string.ts +0 -9
  152. package/source/throttle/index.ts +0 -1
  153. package/source/throttle/throttle.test.ts +0 -228
  154. package/source/throttle/throttle.ts +0 -76
  155. package/test-exports.js +0 -6
  156. package/tsconfig.json +0 -98
  157. package/vitest.config.ts +0 -8
@@ -0,0 +1,9 @@
1
+ type CatchType<F extends () => unknown> = F extends () => Promise<infer R> ? R : F extends () => infer R ? R : never;
2
+ /**
3
+ * 通用错误捕获函数,支持 Promise 和函数执行
4
+ * 将结果转换成 [result, error] 的形式
5
+ */
6
+ export declare function catchIt<T>(input: Promise<T>): Promise<[T | undefined, unknown]>;
7
+ export declare function catchIt<F extends () => unknown>(input: F): Promise<[CatchType<F> | undefined, unknown]>;
8
+ export {};
9
+ //# sourceMappingURL=catch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catch.d.ts","sourceRoot":"","sources":["../../source/catch/catch.ts"],"names":[],"mappings":"AAAA,KAAK,SAAS,CAAC,CAAC,SAAS,MAAM,OAAO,IAAI,CAAC,SAAS,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,MAAM,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;AAEpH;;;GAGG;AACH,wBAAsB,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,EAAE,OAAO,CAAC,CAAC,CAAA;AACtF,wBAAsB,OAAO,CAAC,CAAC,SAAS,MAAM,OAAO,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,EAAE,OAAO,CAAC,CAAC,CAAA"}
@@ -0,0 +1,26 @@
1
+ export async function catchIt(input) {
2
+ const returned = [undefined, undefined];
3
+ try {
4
+ if (input instanceof Promise) {
5
+ // 处理 Promise
6
+ await input
7
+ .then((result) => (returned[0] = result))
8
+ .catch((error) => (returned[1] = error));
9
+ }
10
+ else if (typeof input === 'function') {
11
+ // 处理函数
12
+ const result = input();
13
+ if (result instanceof Promise) {
14
+ // 如果函数返回 Promise,递归调用
15
+ return catchIt(result);
16
+ }
17
+ else {
18
+ returned[0] = result;
19
+ }
20
+ }
21
+ }
22
+ catch (error) {
23
+ returned[1] = error;
24
+ }
25
+ return returned;
26
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=catch.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catch.test.d.ts","sourceRoot":"","sources":["../../source/catch/catch.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,258 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { catchIt } from './catch';
3
+ describe('catchIt', () => {
4
+ describe('处理 Promise', () => {
5
+ it('应该正确处理成功的 Promise', async () => {
6
+ const successValue = 'success';
7
+ const promise = Promise.resolve(successValue);
8
+ const [result, error] = await catchIt(promise);
9
+ expect(result).toBe(successValue);
10
+ expect(error).toBeUndefined();
11
+ });
12
+ it('应该正确处理失败的 Promise', async () => {
13
+ const errorValue = new Error('test error');
14
+ const promise = Promise.reject(errorValue);
15
+ const [result, error] = await catchIt(promise);
16
+ expect(result).toBeUndefined();
17
+ expect(error).toBe(errorValue);
18
+ });
19
+ it('应该正确处理返回不同数据类型的 Promise', async () => {
20
+ // 数字类型
21
+ const [numberResult, numberError] = await catchIt(Promise.resolve(42));
22
+ expect(numberResult).toBe(42);
23
+ expect(numberError).toBeUndefined();
24
+ // 对象类型
25
+ const obj = { key: 'value' };
26
+ const [objectResult, objectError] = await catchIt(Promise.resolve(obj));
27
+ expect(objectResult).toBe(obj);
28
+ expect(objectError).toBeUndefined();
29
+ // 数组类型
30
+ const arr = [1, 2, 3];
31
+ const [arrayResult, arrayError] = await catchIt(Promise.resolve(arr));
32
+ expect(arrayResult).toBe(arr);
33
+ expect(arrayError).toBeUndefined();
34
+ // null 和 undefined
35
+ const [nullResult, nullError] = await catchIt(Promise.resolve(null));
36
+ expect(nullResult).toBeNull();
37
+ expect(nullError).toBeUndefined();
38
+ const [undefinedResult, undefinedError] = await catchIt(Promise.resolve(undefined));
39
+ expect(undefinedResult).toBeUndefined();
40
+ expect(undefinedError).toBeUndefined();
41
+ });
42
+ it('应该正确处理不同类型的错误', async () => {
43
+ // Error 对象
44
+ const error = new Error('test error');
45
+ const [, caughtError1] = await catchIt(Promise.reject(error));
46
+ expect(caughtError1).toBe(error);
47
+ // 字符串错误
48
+ const [, caughtError2] = await catchIt(Promise.reject('string error'));
49
+ expect(caughtError2).toBe('string error');
50
+ // 数字错误
51
+ const [, caughtError3] = await catchIt(Promise.reject(404));
52
+ expect(caughtError3).toBe(404);
53
+ // 对象错误
54
+ const objError = { code: 500, message: 'server error' };
55
+ const [, caughtError4] = await catchIt(Promise.reject(objError));
56
+ expect(caughtError4).toBe(objError);
57
+ });
58
+ });
59
+ describe('处理同步函数', () => {
60
+ it('应该正确处理返回值的同步函数', async () => {
61
+ const syncFn = () => 'sync result';
62
+ const [result, error] = await catchIt(syncFn);
63
+ expect(result).toBe('sync result');
64
+ expect(error).toBeUndefined();
65
+ });
66
+ it('应该正确处理抛出错误的同步函数', async () => {
67
+ const errorValue = new Error('sync error');
68
+ const syncFn = () => {
69
+ throw errorValue;
70
+ };
71
+ const [result, error] = await catchIt(syncFn);
72
+ expect(result).toBeUndefined();
73
+ expect(error).toBe(errorValue);
74
+ });
75
+ it('应该正确处理返回不同数据类型的同步函数', async () => {
76
+ // 数字
77
+ const [numberResult] = await catchIt(() => 42);
78
+ expect(numberResult).toBe(42);
79
+ // 字符串
80
+ const [stringResult] = await catchIt(() => 'hello');
81
+ expect(stringResult).toBe('hello');
82
+ // 对象
83
+ const obj = { test: true };
84
+ const [objectResult] = await catchIt(() => obj);
85
+ expect(objectResult).toBe(obj);
86
+ // 数组
87
+ const arr = [1, 2, 3];
88
+ const [arrayResult] = await catchIt(() => arr);
89
+ expect(arrayResult).toBe(arr);
90
+ // boolean
91
+ const [boolResult] = await catchIt(() => true);
92
+ expect(boolResult).toBe(true);
93
+ // null
94
+ const [nullResult] = await catchIt(() => null);
95
+ expect(nullResult).toBeNull();
96
+ // undefined
97
+ const [undefinedResult] = await catchIt(() => undefined);
98
+ expect(undefinedResult).toBeUndefined();
99
+ });
100
+ it('应该确保同步函数被调用', async () => {
101
+ const mockFn = vi.fn(() => 'test');
102
+ await catchIt(mockFn);
103
+ expect(mockFn).toHaveBeenCalledOnce();
104
+ });
105
+ });
106
+ describe('处理返回 Promise 的函数', () => {
107
+ it('应该正确处理返回成功 Promise 的函数', async () => {
108
+ const asyncFn = () => Promise.resolve('async result');
109
+ const [result, error] = await catchIt(asyncFn);
110
+ expect(result).toBe('async result');
111
+ expect(error).toBeUndefined();
112
+ });
113
+ it('应该正确处理返回失败 Promise 的函数', async () => {
114
+ const errorValue = new Error('async error');
115
+ const asyncFn = () => Promise.reject(errorValue);
116
+ const [result, error] = await catchIt(asyncFn);
117
+ expect(result).toBeUndefined();
118
+ expect(error).toBe(errorValue);
119
+ });
120
+ it('应该正确处理返回不同数据类型 Promise 的函数', async () => {
121
+ // 数字
122
+ const [numberResult] = await catchIt(() => Promise.resolve(123));
123
+ expect(numberResult).toBe(123);
124
+ // 对象
125
+ const obj = { async: true };
126
+ const [objectResult] = await catchIt(() => Promise.resolve(obj));
127
+ expect(objectResult).toBe(obj);
128
+ });
129
+ it('应该确保返回 Promise 的函数被调用', async () => {
130
+ const mockAsyncFn = vi.fn(() => Promise.resolve('test'));
131
+ await catchIt(mockAsyncFn);
132
+ expect(mockAsyncFn).toHaveBeenCalledOnce();
133
+ });
134
+ });
135
+ describe('边界情况', () => {
136
+ it('应该正确处理函数中抛出的同步错误', async () => {
137
+ const syncError = new Error('sync throw error');
138
+ const errorFn = () => {
139
+ throw syncError;
140
+ };
141
+ const [result, error] = await catchIt(errorFn);
142
+ expect(result).toBeUndefined();
143
+ expect(error).toBe(syncError);
144
+ });
145
+ it('应该正确处理 Promise 链中的错误', async () => {
146
+ const chainError = new Error('chain error');
147
+ const promise = Promise.resolve()
148
+ .then(() => {
149
+ throw chainError;
150
+ });
151
+ const [result, error] = await catchIt(promise);
152
+ expect(result).toBeUndefined();
153
+ expect(error).toBe(chainError);
154
+ });
155
+ it('应该正确处理延迟的 Promise', async () => {
156
+ const delayedPromise = new Promise((resolve) => {
157
+ setTimeout(() => resolve('delayed result'), 10);
158
+ });
159
+ const [result, error] = await catchIt(delayedPromise);
160
+ expect(result).toBe('delayed result');
161
+ expect(error).toBeUndefined();
162
+ });
163
+ it('应该正确处理返回 falsy 值的函数', async () => {
164
+ // 返回 0
165
+ const [zeroResult] = await catchIt(() => 0);
166
+ expect(zeroResult).toBe(0);
167
+ // 返回空字符串
168
+ const [emptyStringResult] = await catchIt(() => '');
169
+ expect(emptyStringResult).toBe('');
170
+ // 返回 false
171
+ const [falseResult] = await catchIt(() => false);
172
+ expect(falseResult).toBe(false);
173
+ // 返回 null
174
+ const [nullResult] = await catchIt(() => null);
175
+ expect(nullResult).toBeNull();
176
+ // 返回 undefined
177
+ const [undefinedResult] = await catchIt(() => undefined);
178
+ expect(undefinedResult).toBeUndefined();
179
+ });
180
+ });
181
+ describe('类型安全性', () => {
182
+ it('应该保持正确的类型推导 - Promise', async () => {
183
+ // TypeScript 编译时应该能正确推导类型
184
+ const stringPromise = Promise.resolve('string');
185
+ const [stringResult] = await catchIt(stringPromise);
186
+ // stringResult 应该被推导为 string | undefined
187
+ const numberPromise = Promise.resolve(42);
188
+ const [numberResult] = await catchIt(numberPromise);
189
+ // numberResult 应该被推导为 number | undefined
190
+ // 运行时验证
191
+ expect(typeof stringResult).toBe('string');
192
+ expect(typeof numberResult).toBe('number');
193
+ });
194
+ it('应该保持正确的类型推导 - 同步函数', async () => {
195
+ const stringFn = () => 'hello';
196
+ const [stringResult] = await catchIt(stringFn);
197
+ const numberFn = () => 42;
198
+ const [numberResult] = await catchIt(numberFn);
199
+ // 运行时验证
200
+ expect(typeof stringResult).toBe('string');
201
+ expect(typeof numberResult).toBe('number');
202
+ });
203
+ it('应该保持正确的类型推导 - 异步函数', async () => {
204
+ const asyncStringFn = () => Promise.resolve('async hello');
205
+ const [asyncStringResult] = await catchIt(asyncStringFn);
206
+ const asyncNumberFn = () => Promise.resolve(100);
207
+ const [asyncNumberResult] = await catchIt(asyncNumberFn);
208
+ // 运行时验证
209
+ expect(typeof asyncStringResult).toBe('string');
210
+ expect(typeof asyncNumberResult).toBe('number');
211
+ });
212
+ });
213
+ describe('实际使用场景', () => {
214
+ it('应该适用于 API 调用场景', async () => {
215
+ // 模拟成功的 API 调用
216
+ const mockApiCall = () => Promise.resolve({
217
+ data: { id: 1, name: 'test' },
218
+ status: 200
219
+ });
220
+ const [result, error] = await catchIt(mockApiCall);
221
+ expect(result).toEqual({ data: { id: 1, name: 'test' }, status: 200 });
222
+ expect(error).toBeUndefined();
223
+ // 模拟失败的 API 调用
224
+ const failedApiCall = () => Promise.reject({
225
+ status: 404,
226
+ message: 'Not Found'
227
+ });
228
+ const [failedResult, apiError] = await catchIt(failedApiCall);
229
+ expect(failedResult).toBeUndefined();
230
+ expect(apiError).toEqual({ status: 404, message: 'Not Found' });
231
+ });
232
+ it('应该适用于文件操作场景', async () => {
233
+ // 模拟成功的文件读取
234
+ const mockFileRead = () => Promise.resolve('file content');
235
+ const [content, error] = await catchIt(mockFileRead);
236
+ expect(content).toBe('file content');
237
+ expect(error).toBeUndefined();
238
+ // 模拟失败的文件读取
239
+ const failedFileRead = () => Promise.reject(new Error('File not found'));
240
+ const [failedContent, fileError] = await catchIt(failedFileRead);
241
+ expect(failedContent).toBeUndefined();
242
+ expect(fileError).toBeInstanceOf(Error);
243
+ expect(fileError.message).toBe('File not found');
244
+ });
245
+ it('应该适用于数据解析场景', async () => {
246
+ // 模拟成功的 JSON 解析
247
+ const jsonParseSuccess = () => JSON.parse('{"key": "value"}');
248
+ const [parsed, parseError] = await catchIt(jsonParseSuccess);
249
+ expect(parsed).toEqual({ key: 'value' });
250
+ expect(parseError).toBeUndefined();
251
+ // 模拟失败的 JSON 解析
252
+ const jsonParseFailed = () => JSON.parse('invalid json');
253
+ const [failedParsed, jsonError] = await catchIt(jsonParseFailed);
254
+ expect(failedParsed).toBeUndefined();
255
+ expect(jsonError).toBeInstanceOf(SyntaxError);
256
+ });
257
+ });
258
+ });
@@ -0,0 +1,2 @@
1
+ export * from './catch';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../source/catch/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA"}
@@ -0,0 +1 @@
1
+ export * from './catch';
@@ -0,0 +1,6 @@
1
+ type SeedValue = number | string | null;
2
+ export declare function getRandomColor(seed: SeedValue): (offset: SeedValue, range?: number) => string;
3
+ export declare function getRandomColors(seed: SeedValue, interval: number, count: number): string[];
4
+ export declare function interpolateColors(color1: string, color2: string, steps: number): (index: number) => string;
5
+ export type { SeedValue };
6
+ //# sourceMappingURL=color.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"color.d.ts","sourceRoot":"","sources":["../../source/color/color.ts"],"names":[],"mappings":"AAAA,KAAK,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;AAcvC,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,IAMpC,QAAQ,SAAS,EAAE,QAAO,MAAY,YAO/C;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,YAO/E;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,IAgBrE,OAAO,MAAM,KAAG,MAAM,CAgB/B;AAED,YAAY,EAAE,SAAS,EAAE,CAAA"}
@@ -0,0 +1,57 @@
1
+ function normalizeSeed(value) {
2
+ if (typeof value === 'number') {
3
+ return value;
4
+ }
5
+ if (typeof value === 'string') {
6
+ return value.split('').reduce((sum, char) => sum + char.charCodeAt(0), 0);
7
+ }
8
+ return 0;
9
+ }
10
+ export function getRandomColor(seed) {
11
+ // 使用 asciiSum 生成 HSL 值
12
+ const hue = normalizeSeed(seed) % 360; // 色相(0-360)
13
+ const saturation = 80; // 饱和度(0-100)
14
+ const lightness = 45; // 明度(0-100)
15
+ return (offset, range = 360) => {
16
+ const normalizedOffset = normalizeSeed(offset);
17
+ console.log('normalizedOffset', offset, normalizedOffset);
18
+ const finalHue = (hue + normalizedOffset) % range;
19
+ return `hsl(${finalHue}, ${saturation}%, ${lightness}%)`;
20
+ };
21
+ }
22
+ export function getRandomColors(seed, interval, count) {
23
+ const colors = [];
24
+ const colorFunc = getRandomColor(seed);
25
+ for (let i = 0; i < count; i++) {
26
+ colors.push(colorFunc(i * interval));
27
+ }
28
+ return colors;
29
+ }
30
+ export function interpolateColors(color1, color2, steps) {
31
+ function parseHSL(color) {
32
+ const match = color.match(/hsl\((\d+),\s*(\d+)%?,\s*(\d+)%?\)/);
33
+ if (!match) {
34
+ throw new Error(`Invalid HSL color: ${color}`);
35
+ }
36
+ return [parseInt(match[1]), parseInt(match[2]), parseInt(match[3])];
37
+ }
38
+ function hslToString(h, s, l) {
39
+ return `hsl(${Math.round(h)}, ${Math.round(s)}%, ${Math.round(l)}%)`;
40
+ }
41
+ const [h1, s1, l1] = parseHSL(color1);
42
+ const [h2, s2, l2] = parseHSL(color2);
43
+ return (index) => {
44
+ if (index < 0 || index > steps) {
45
+ throw new Error(`Index out of bounds: ${index}. Valid range is 0 to ${steps}.`);
46
+ }
47
+ // 当steps为0时,直接返回第一个颜色
48
+ if (steps === 0) {
49
+ return hslToString(h1, s1, l1);
50
+ }
51
+ const ratio = index / steps;
52
+ const h = h1 + (h2 - h1) * ratio;
53
+ const s = s1 + (s2 - s1) * ratio;
54
+ const l = l1 + (l2 - l1) * ratio;
55
+ return hslToString(h, s, l);
56
+ };
57
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=color.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"color.test.d.ts","sourceRoot":"","sources":["../../source/color/color.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,110 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
+ import { getRandomColor, getRandomColors, interpolateColors } from './color';
3
+ describe('getRandomColor 函数', () => {
4
+ // Mock console.log to avoid noise in tests
5
+ beforeEach(() => {
6
+ vi.spyOn(console, 'log').mockImplementation(() => { });
7
+ });
8
+ afterEach(() => {
9
+ vi.restoreAllMocks();
10
+ });
11
+ it('应该为相同的种子生成一致的颜色', () => {
12
+ const colorFunc = getRandomColor(123);
13
+ const color1 = colorFunc(0);
14
+ const color2 = colorFunc(0);
15
+ expect(color1).toBe(color2);
16
+ expect(color1).toMatch(/^hsl\(\d+, 80%, 45%\)$/);
17
+ });
18
+ it('应该处理数字种子', () => {
19
+ const colorFunc = getRandomColor(42);
20
+ const color = colorFunc(0);
21
+ expect(color).toMatch(/^hsl\(\d+, 80%, 45%\)$/);
22
+ });
23
+ it('应该处理字符串种子', () => {
24
+ const colorFunc = getRandomColor('test');
25
+ const color = colorFunc(0);
26
+ expect(color).toMatch(/^hsl\(\d+, 80%, 45%\)$/);
27
+ });
28
+ it('应该处理 null 种子', () => {
29
+ const colorFunc = getRandomColor(null);
30
+ const color = colorFunc(0);
31
+ expect(color).toBe('hsl(0, 80%, 45%)');
32
+ });
33
+ it('应该为不同的偏移量生成不同的颜色', () => {
34
+ const colorFunc = getRandomColor(123);
35
+ const color1 = colorFunc(0);
36
+ const color2 = colorFunc(100);
37
+ expect(color1).not.toBe(color2);
38
+ });
39
+ it('应该遵守自定义范围参数', () => {
40
+ const colorFunc = getRandomColor(123);
41
+ const color = colorFunc(50, 180);
42
+ // 解析HSL值
43
+ const match = color.match(/hsl\((\d+), 80%, 45%\)/);
44
+ expect(match).toBeTruthy();
45
+ const hue = parseInt(match[1]);
46
+ expect(hue).toBeLessThan(180);
47
+ });
48
+ });
49
+ describe('getRandomColors 函数', () => {
50
+ beforeEach(() => {
51
+ vi.spyOn(console, 'log').mockImplementation(() => { });
52
+ });
53
+ afterEach(() => {
54
+ vi.restoreAllMocks();
55
+ });
56
+ it('应该生成指定数量的颜色', () => {
57
+ const colors = getRandomColors(123, 50, 5);
58
+ expect(colors).toHaveLength(5);
59
+ colors.forEach(color => {
60
+ expect(color).toMatch(/^hsl\(\d+, 80%, 45%\)$/);
61
+ });
62
+ });
63
+ it('应该以间隔生成不同的颜色', () => {
64
+ const colors = getRandomColors(123, 50, 3);
65
+ expect(colors[0]).not.toBe(colors[1]);
66
+ expect(colors[1]).not.toBe(colors[2]);
67
+ });
68
+ it('应该处理零计数', () => {
69
+ const colors = getRandomColors(123, 50, 0);
70
+ expect(colors).toHaveLength(0);
71
+ });
72
+ });
73
+ describe('interpolateColors 函数', () => {
74
+ it('应该在两个 HSL 颜色之间插值', () => {
75
+ const interpolate = interpolateColors('hsl(0, 80%, 45%)', 'hsl(120, 80%, 45%)', 2);
76
+ const color0 = interpolate(0);
77
+ const color1 = interpolate(1);
78
+ const color2 = interpolate(2);
79
+ expect(color0).toBe('hsl(0, 80%, 45%)');
80
+ expect(color1).toBe('hsl(60, 80%, 45%)');
81
+ expect(color2).toBe('hsl(120, 80%, 45%)');
82
+ });
83
+ it('应该处理不同的饱和度和明度值', () => {
84
+ const interpolate = interpolateColors('hsl(0, 50%, 30%)', 'hsl(0, 90%, 70%)', 1);
85
+ const color0 = interpolate(0);
86
+ const color1 = interpolate(1);
87
+ expect(color0).toBe('hsl(0, 50%, 30%)');
88
+ expect(color1).toBe('hsl(0, 90%, 70%)');
89
+ });
90
+ it('应该为无效的 HSL 颜色格式抛出错误', () => {
91
+ expect(() => {
92
+ interpolateColors('invalid-color', 'hsl(120, 80%, 45%)', 2);
93
+ }).toThrow('Invalid HSL color: invalid-color');
94
+ });
95
+ it('应该为索引超出边界抛出错误', () => {
96
+ const interpolate = interpolateColors('hsl(0, 80%, 45%)', 'hsl(120, 80%, 45%)', 2);
97
+ expect(() => {
98
+ interpolate(-1);
99
+ }).toThrow('Index out of bounds: -1. Valid range is 0 to 2.');
100
+ expect(() => {
101
+ interpolate(3);
102
+ }).toThrow('Index out of bounds: 3. Valid range is 0 to 2.');
103
+ });
104
+ it('应该处理零步骤', () => {
105
+ const interpolate = interpolateColors('hsl(0, 80%, 45%)', 'hsl(120, 80%, 45%)', 0);
106
+ const color = interpolate(0);
107
+ // 当步骤为0时,应该返回第一个颜色
108
+ expect(color).toBe('hsl(0, 80%, 45%)');
109
+ });
110
+ });
@@ -0,0 +1,2 @@
1
+ export * from './color';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../source/color/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA"}
@@ -0,0 +1 @@
1
+ export * from './color';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * 防抖装饰器 - 基于 TC39 Stage 3 Decorators 提案
3
+ * 在最后一次调用后等待指定时间才执行函数
4
+ */
5
+ export declare function debounceFn<T extends (...args: any[]) => any>(fn: T, wait: number): T;
6
+ export declare function debounce<T extends (...args: any[]) => any>(wait: number): (originalMethod: T, context: ClassMethodDecoratorContext) => T;
7
+ //# sourceMappingURL=debounce.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debounce.d.ts","sourceRoot":"","sources":["../../source/debounce/debounce.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,wBAAgB,UAAU,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EAC1D,EAAE,EAAE,CAAC,EACL,IAAI,EAAE,MAAM,GACX,CAAC,CAmBH;AAGD,wBAAgB,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EAAE,IAAI,EAAE,MAAM,IACrD,gBAAgB,CAAC,EAAE,SAAS,2BAA2B,KAAG,CAAC,CAS7E"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * 防抖装饰器 - 基于 TC39 Stage 3 Decorators 提案
3
+ * 在最后一次调用后等待指定时间才执行函数
4
+ */
5
+ // 通用防抖函数
6
+ export function debounceFn(fn, wait) {
7
+ let timeout = null;
8
+ function debounced(...args) {
9
+ return new Promise((resolve, reject) => {
10
+ if (timeout)
11
+ clearTimeout(timeout);
12
+ timeout = setTimeout(async () => {
13
+ try {
14
+ const result = await Promise.resolve(fn.apply(this, args));
15
+ resolve(result);
16
+ }
17
+ catch (error) {
18
+ reject(error);
19
+ }
20
+ }, wait);
21
+ });
22
+ }
23
+ return debounced;
24
+ }
25
+ // TC39 Stage 3 装饰器实现
26
+ export function debounce(wait) {
27
+ return function (originalMethod, context) {
28
+ // 每个实例独立
29
+ context.addInitializer(function () {
30
+ const self = this;
31
+ const debouncedMethod = debounceFn(originalMethod.bind(self), wait);
32
+ self[context.name] = debouncedMethod;
33
+ });
34
+ return originalMethod;
35
+ };
36
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=debounce.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debounce.test.d.ts","sourceRoot":"","sources":["../../source/debounce/debounce.test.ts"],"names":[],"mappings":""}