@taicode/common-base 3.7.5 → 3.7.7
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/LICENSE +21 -0
- package/package.json +7 -8
- package/output/batching-buffer/batching-buffer.d.ts +0 -133
- package/output/batching-buffer/batching-buffer.d.ts.map +0 -1
- package/output/batching-buffer/batching-buffer.js +0 -264
- package/output/batching-buffer/batching-buffer.test.d.ts +0 -2
- package/output/batching-buffer/batching-buffer.test.d.ts.map +0 -1
- package/output/batching-buffer/batching-buffer.test.js +0 -358
- package/output/batching-buffer/index.d.ts +0 -3
- package/output/batching-buffer/index.d.ts.map +0 -1
- package/output/batching-buffer/index.js +0 -1
- package/output/catch/catch.d.ts +0 -46
- package/output/catch/catch.d.ts.map +0 -1
- package/output/catch/catch.js +0 -48
- package/output/catch/catch.test.d.ts +0 -2
- package/output/catch/catch.test.d.ts.map +0 -1
- package/output/catch/catch.test.js +0 -43
- package/output/catch/index.d.ts +0 -2
- package/output/catch/index.d.ts.map +0 -1
- package/output/catch/index.js +0 -1
- package/output/color/color.d.ts +0 -6
- package/output/color/color.d.ts.map +0 -1
- package/output/color/color.js +0 -56
- package/output/color/color.test.d.ts +0 -2
- package/output/color/color.test.d.ts.map +0 -1
- package/output/color/color.test.js +0 -110
- package/output/color/index.d.ts +0 -2
- package/output/color/index.d.ts.map +0 -1
- package/output/color/index.js +0 -1
- package/output/debounce/debounce.d.ts +0 -7
- package/output/debounce/debounce.d.ts.map +0 -1
- package/output/debounce/debounce.js +0 -36
- package/output/debounce/debounce.test.d.ts +0 -2
- package/output/debounce/debounce.test.d.ts.map +0 -1
- package/output/debounce/debounce.test.js +0 -135
- package/output/debounce/index.d.ts +0 -2
- package/output/debounce/index.d.ts.map +0 -1
- package/output/debounce/index.js +0 -1
- package/output/disposer/disposer.d.ts +0 -8
- package/output/disposer/disposer.d.ts.map +0 -1
- package/output/disposer/disposer.js +0 -21
- package/output/disposer/disposer.test.d.ts +0 -2
- package/output/disposer/disposer.test.d.ts.map +0 -1
- package/output/disposer/disposer.test.js +0 -216
- package/output/disposer/index.d.ts +0 -2
- package/output/disposer/index.d.ts.map +0 -1
- package/output/disposer/index.js +0 -1
- package/output/error/error.d.ts +0 -128
- package/output/error/error.d.ts.map +0 -1
- package/output/error/error.js +0 -141
- package/output/error/error.test.d.ts +0 -2
- package/output/error/error.test.d.ts.map +0 -1
- package/output/error/error.test.js +0 -420
- package/output/error/index.d.ts +0 -3
- package/output/error/index.d.ts.map +0 -1
- package/output/error/index.js +0 -1
- package/output/event-emitter/event-emitter.d.ts +0 -33
- package/output/event-emitter/event-emitter.d.ts.map +0 -1
- package/output/event-emitter/event-emitter.js +0 -66
- package/output/event-emitter/event-emitter.test.d.ts +0 -2
- package/output/event-emitter/event-emitter.test.d.ts.map +0 -1
- package/output/event-emitter/event-emitter.test.js +0 -177
- package/output/event-emitter/index.d.ts +0 -2
- package/output/event-emitter/index.d.ts.map +0 -1
- package/output/event-emitter/index.js +0 -1
- package/output/flow-queue/flow-queue.d.ts +0 -486
- package/output/flow-queue/flow-queue.d.ts.map +0 -1
- package/output/flow-queue/flow-queue.js +0 -654
- package/output/flow-queue/flow-queue.test.d.ts +0 -2
- package/output/flow-queue/flow-queue.test.d.ts.map +0 -1
- package/output/flow-queue/flow-queue.test.js +0 -1205
- package/output/flow-queue/index.d.ts +0 -3
- package/output/flow-queue/index.d.ts.map +0 -1
- package/output/flow-queue/index.js +0 -3
- package/output/index.d.ts +0 -18
- package/output/index.d.ts.map +0 -1
- package/output/index.js +0 -26
- package/output/logger/formatter.d.ts +0 -70
- package/output/logger/formatter.d.ts.map +0 -1
- package/output/logger/formatter.js +0 -206
- package/output/logger/formatter.test.d.ts +0 -2
- package/output/logger/formatter.test.d.ts.map +0 -1
- package/output/logger/formatter.test.js +0 -296
- package/output/logger/index.d.ts +0 -4
- package/output/logger/index.d.ts.map +0 -1
- package/output/logger/index.js +0 -3
- package/output/logger/logger.d.ts +0 -64
- package/output/logger/logger.d.ts.map +0 -1
- package/output/logger/logger.js +0 -179
- package/output/logger/logger.test.d.ts +0 -2
- package/output/logger/logger.test.d.ts.map +0 -1
- package/output/logger/logger.test.js +0 -299
- package/output/logger/transport.d.ts +0 -124
- package/output/logger/transport.d.ts.map +0 -1
- package/output/logger/transport.js +0 -153
- package/output/logger/transport.test.d.ts +0 -2
- package/output/logger/transport.test.d.ts.map +0 -1
- package/output/logger/transport.test.js +0 -309
- package/output/lru-cache/index.d.ts +0 -2
- package/output/lru-cache/index.d.ts.map +0 -1
- package/output/lru-cache/index.js +0 -1
- package/output/lru-cache/lru-cache.d.ts +0 -22
- package/output/lru-cache/lru-cache.d.ts.map +0 -1
- package/output/lru-cache/lru-cache.js +0 -147
- package/output/lru-cache/lru-cache.test.d.ts +0 -2
- package/output/lru-cache/lru-cache.test.d.ts.map +0 -1
- package/output/lru-cache/lru-cache.test.js +0 -239
- package/output/number/index.d.ts +0 -2
- package/output/number/index.d.ts.map +0 -1
- package/output/number/index.js +0 -1
- package/output/number/number.d.ts +0 -2
- package/output/number/number.d.ts.map +0 -1
- package/output/number/number.js +0 -23
- package/output/number/number.test.d.ts +0 -2
- package/output/number/number.test.d.ts.map +0 -1
- package/output/number/number.test.js +0 -50
- package/output/object/index.d.ts +0 -2
- package/output/object/index.d.ts.map +0 -1
- package/output/object/index.js +0 -1
- package/output/object/object.d.ts +0 -7
- package/output/object/object.d.ts.map +0 -1
- package/output/object/object.js +0 -27
- package/output/object/object.test.d.ts +0 -2
- package/output/object/object.test.d.ts.map +0 -1
- package/output/object/object.test.js +0 -42
- package/output/ring-cache/index.d.ts +0 -6
- package/output/ring-cache/index.d.ts.map +0 -1
- package/output/ring-cache/index.js +0 -5
- package/output/ring-cache/ring-cache.d.ts +0 -125
- package/output/ring-cache/ring-cache.d.ts.map +0 -1
- package/output/ring-cache/ring-cache.js +0 -197
- package/output/ring-cache/ring-cache.test.d.ts +0 -2
- package/output/ring-cache/ring-cache.test.d.ts.map +0 -1
- package/output/ring-cache/ring-cache.test.js +0 -196
- package/output/service/index.d.ts +0 -2
- package/output/service/index.d.ts.map +0 -1
- package/output/service/index.js +0 -1
- package/output/service/service.d.ts +0 -6
- package/output/service/service.d.ts.map +0 -1
- package/output/service/service.js +0 -3
- package/output/string/index.d.ts +0 -2
- package/output/string/index.d.ts.map +0 -1
- package/output/string/index.js +0 -1
- package/output/string/string.d.ts +0 -3
- package/output/string/string.d.ts.map +0 -1
- package/output/string/string.js +0 -9
- package/output/string/string.test.d.ts +0 -2
- package/output/string/string.test.d.ts.map +0 -1
- package/output/string/string.test.js +0 -77
- package/output/throttle/index.d.ts +0 -2
- package/output/throttle/index.d.ts.map +0 -1
- package/output/throttle/index.js +0 -1
- package/output/throttle/throttle.d.ts +0 -12
- package/output/throttle/throttle.d.ts.map +0 -1
- package/output/throttle/throttle.js +0 -55
- package/output/throttle/throttle.test.d.ts +0 -2
- package/output/throttle/throttle.test.d.ts.map +0 -1
- package/output/throttle/throttle.test.js +0 -177
- package/output/ttl-cache/index.d.ts +0 -2
- package/output/ttl-cache/index.d.ts.map +0 -1
- package/output/ttl-cache/index.js +0 -1
- package/output/ttl-cache/ttl-cache.d.ts +0 -148
- package/output/ttl-cache/ttl-cache.d.ts.map +0 -1
- package/output/ttl-cache/ttl-cache.js +0 -313
- package/output/ttl-cache/ttl-cache.test.d.ts +0 -2
- package/output/ttl-cache/ttl-cache.test.d.ts.map +0 -1
- package/output/ttl-cache/ttl-cache.test.js +0 -222
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
-
import { getRandomColor, getRandomColors, interpolateColors } from './color.js';
|
|
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
|
-
});
|
package/output/color/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../source/color/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA"}
|
package/output/color/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './color.js';
|
|
@@ -1,7 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|
|
@@ -1,36 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"debounce.test.d.ts","sourceRoot":"","sources":["../../source/debounce/debounce.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
-
import { debounce, debounceFn } from './debounce.js';
|
|
3
|
-
describe('debounce', () => {
|
|
4
|
-
beforeEach(() => {
|
|
5
|
-
vi.useFakeTimers();
|
|
6
|
-
});
|
|
7
|
-
afterEach(() => {
|
|
8
|
-
vi.restoreAllMocks();
|
|
9
|
-
vi.useRealTimers();
|
|
10
|
-
});
|
|
11
|
-
describe('debounceFn', () => {
|
|
12
|
-
it('应该延迟函数执行', async () => {
|
|
13
|
-
const mockFn = vi.fn().mockResolvedValue('result');
|
|
14
|
-
const debouncedFn = debounceFn(mockFn, 100);
|
|
15
|
-
const promise = debouncedFn('arg1', 'arg2');
|
|
16
|
-
// 函数不应该立即执行
|
|
17
|
-
expect(mockFn).not.toHaveBeenCalled();
|
|
18
|
-
// 推进时间
|
|
19
|
-
vi.advanceTimersByTime(100);
|
|
20
|
-
await promise;
|
|
21
|
-
expect(mockFn).toHaveBeenCalledOnce();
|
|
22
|
-
expect(mockFn).toHaveBeenCalledWith('arg1', 'arg2');
|
|
23
|
-
});
|
|
24
|
-
it('应该取消之前的调用', async () => {
|
|
25
|
-
const mockFn = vi.fn().mockResolvedValue('result');
|
|
26
|
-
const debouncedFn = debounceFn(mockFn, 100);
|
|
27
|
-
// 快速连续调用
|
|
28
|
-
debouncedFn('first');
|
|
29
|
-
debouncedFn('second');
|
|
30
|
-
const finalPromise = debouncedFn('third');
|
|
31
|
-
// 推进时间
|
|
32
|
-
vi.advanceTimersByTime(100);
|
|
33
|
-
await finalPromise;
|
|
34
|
-
// 只应该执行最后一次调用
|
|
35
|
-
expect(mockFn).toHaveBeenCalledOnce();
|
|
36
|
-
expect(mockFn).toHaveBeenCalledWith('third');
|
|
37
|
-
});
|
|
38
|
-
it('应该处理同步函数', async () => {
|
|
39
|
-
const mockFn = vi.fn().mockReturnValue('sync-result');
|
|
40
|
-
const debouncedFn = debounceFn(mockFn, 100);
|
|
41
|
-
const promise = debouncedFn('arg');
|
|
42
|
-
vi.advanceTimersByTime(100);
|
|
43
|
-
const result = await promise;
|
|
44
|
-
expect(result).toBe('sync-result');
|
|
45
|
-
expect(mockFn).toHaveBeenCalledWith('arg');
|
|
46
|
-
});
|
|
47
|
-
it('应该处理异步函数', async () => {
|
|
48
|
-
const mockFn = vi.fn().mockResolvedValue('async-result');
|
|
49
|
-
const debouncedFn = debounceFn(mockFn, 100);
|
|
50
|
-
const promise = debouncedFn('arg');
|
|
51
|
-
vi.advanceTimersByTime(100);
|
|
52
|
-
const result = await promise;
|
|
53
|
-
expect(result).toBe('async-result');
|
|
54
|
-
});
|
|
55
|
-
it('应该处理函数执行错误', async () => {
|
|
56
|
-
const error = new Error('Test error');
|
|
57
|
-
const mockFn = vi.fn().mockRejectedValue(error);
|
|
58
|
-
const debouncedFn = debounceFn(mockFn, 100);
|
|
59
|
-
const promise = debouncedFn('arg');
|
|
60
|
-
vi.advanceTimersByTime(100);
|
|
61
|
-
await expect(promise).rejects.toThrow('Test error');
|
|
62
|
-
});
|
|
63
|
-
it('应该保持 this 上下文', async () => {
|
|
64
|
-
class TestClass {
|
|
65
|
-
value = 'test-value';
|
|
66
|
-
getValue() {
|
|
67
|
-
return this.value;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
const instance = new TestClass();
|
|
71
|
-
const debouncedMethod = debounceFn(instance.getValue, 100);
|
|
72
|
-
const promise = debouncedMethod.call(instance);
|
|
73
|
-
vi.advanceTimersByTime(100);
|
|
74
|
-
const result = await promise;
|
|
75
|
-
expect(result).toBe('test-value');
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
describe('debounce decorator', () => {
|
|
79
|
-
it('应该装饰类方法', async () => {
|
|
80
|
-
class TestClass {
|
|
81
|
-
callCount = 0;
|
|
82
|
-
@debounce(100)
|
|
83
|
-
increment() {
|
|
84
|
-
this.callCount++;
|
|
85
|
-
return this.callCount;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
const instance = new TestClass();
|
|
89
|
-
// 快速连续调用
|
|
90
|
-
instance.increment();
|
|
91
|
-
instance.increment();
|
|
92
|
-
instance.increment();
|
|
93
|
-
// 推进时间
|
|
94
|
-
vi.advanceTimersByTime(100);
|
|
95
|
-
// 只应该执行一次
|
|
96
|
-
expect(instance.callCount).toBe(1);
|
|
97
|
-
});
|
|
98
|
-
it('应该为每个实例独立工作', async () => {
|
|
99
|
-
class TestClass {
|
|
100
|
-
value = 0;
|
|
101
|
-
@debounce(100)
|
|
102
|
-
async setValue(newValue) {
|
|
103
|
-
this.value = newValue;
|
|
104
|
-
return this.value;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
const instance1 = new TestClass();
|
|
108
|
-
const instance2 = new TestClass();
|
|
109
|
-
const promise1 = instance1.setValue(10);
|
|
110
|
-
const promise2 = instance2.setValue(20);
|
|
111
|
-
vi.advanceTimersByTime(100);
|
|
112
|
-
await Promise.all([promise1, promise2]);
|
|
113
|
-
expect(instance1.value).toBe(10);
|
|
114
|
-
expect(instance2.value).toBe(20);
|
|
115
|
-
});
|
|
116
|
-
it('应该处理带参数的方法', async () => {
|
|
117
|
-
class TestClass {
|
|
118
|
-
lastArgs = [];
|
|
119
|
-
@debounce(100)
|
|
120
|
-
async saveArgs(...args) {
|
|
121
|
-
this.lastArgs = args;
|
|
122
|
-
return args;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
const instance = new TestClass();
|
|
126
|
-
instance.saveArgs(1, 2, 3);
|
|
127
|
-
instance.saveArgs(4, 5, 6);
|
|
128
|
-
const promise = instance.saveArgs(7, 8, 9);
|
|
129
|
-
vi.advanceTimersByTime(100);
|
|
130
|
-
const result = await promise;
|
|
131
|
-
expect(result).toEqual([7, 8, 9]);
|
|
132
|
-
expect(instance.lastArgs).toEqual([7, 8, 9]);
|
|
133
|
-
});
|
|
134
|
-
});
|
|
135
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../source/debounce/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAA"}
|
package/output/debounce/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './debounce.js';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"disposer.d.ts","sourceRoot":"","sources":["../../source/disposer/disposer.ts"],"names":[],"mappings":"AAEA,KAAK,eAAe,GAAG,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;AAEvD,qBAAa,QAAQ;IACnB,OAAO,CAAC,gBAAgB,CAAwB;IAGhD,WAAW,CAAC,SAAS,EAAE,eAAe,GAAG,IAAI;IAKvC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAY/B"}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { logger } from '../logger/index.js';
|
|
2
|
-
export class Disposer {
|
|
3
|
-
cleanupFunctions = [];
|
|
4
|
-
// 添加清理函数
|
|
5
|
-
addDisposer(cleanupFn) {
|
|
6
|
-
this.cleanupFunctions.push(cleanupFn);
|
|
7
|
-
}
|
|
8
|
-
// 执行所有清理函数
|
|
9
|
-
async dispose() {
|
|
10
|
-
const cleanupFunctions = this.cleanupFunctions;
|
|
11
|
-
this.cleanupFunctions = [];
|
|
12
|
-
for (const cleanupFn of cleanupFunctions) {
|
|
13
|
-
try {
|
|
14
|
-
await cleanupFn();
|
|
15
|
-
}
|
|
16
|
-
catch (error) {
|
|
17
|
-
logger.error('Error during cleanup:', error);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"disposer.test.d.ts","sourceRoot":"","sources":["../../source/disposer/disposer.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
-
import { Disposer } from './disposer.js';
|
|
3
|
-
import { logger } from '../logger/index.js';
|
|
4
|
-
describe('Disposer', () => {
|
|
5
|
-
let disposer;
|
|
6
|
-
beforeEach(() => {
|
|
7
|
-
disposer = new Disposer();
|
|
8
|
-
});
|
|
9
|
-
describe('addDisposer', () => {
|
|
10
|
-
it('应该能够添加清理函数', () => {
|
|
11
|
-
const cleanupFn = vi.fn();
|
|
12
|
-
expect(() => {
|
|
13
|
-
disposer.addDisposer(cleanupFn);
|
|
14
|
-
}).not.toThrow();
|
|
15
|
-
});
|
|
16
|
-
it('应该能够添加多个清理函数', async () => {
|
|
17
|
-
const cleanupFn1 = vi.fn();
|
|
18
|
-
const cleanupFn2 = vi.fn();
|
|
19
|
-
const cleanupFn3 = vi.fn();
|
|
20
|
-
disposer.addDisposer(cleanupFn1);
|
|
21
|
-
disposer.addDisposer(cleanupFn2);
|
|
22
|
-
disposer.addDisposer(cleanupFn3);
|
|
23
|
-
await disposer.dispose();
|
|
24
|
-
expect(cleanupFn1).toHaveBeenCalledOnce();
|
|
25
|
-
expect(cleanupFn2).toHaveBeenCalledOnce();
|
|
26
|
-
expect(cleanupFn3).toHaveBeenCalledOnce();
|
|
27
|
-
});
|
|
28
|
-
it('应该能够添加返回不同类型的清理函数', async () => {
|
|
29
|
-
const voidFn = vi.fn(() => { });
|
|
30
|
-
const stringFn = vi.fn(() => 'cleanup result');
|
|
31
|
-
const numberFn = vi.fn(() => 42);
|
|
32
|
-
const promiseFn = vi.fn(() => Promise.resolve('async cleanup'));
|
|
33
|
-
disposer.addDisposer(voidFn);
|
|
34
|
-
disposer.addDisposer(stringFn);
|
|
35
|
-
disposer.addDisposer(numberFn);
|
|
36
|
-
disposer.addDisposer(promiseFn);
|
|
37
|
-
await disposer.dispose();
|
|
38
|
-
expect(voidFn).toHaveBeenCalled();
|
|
39
|
-
expect(stringFn).toHaveBeenCalled();
|
|
40
|
-
expect(numberFn).toHaveBeenCalled();
|
|
41
|
-
expect(promiseFn).toHaveBeenCalled();
|
|
42
|
-
});
|
|
43
|
-
});
|
|
44
|
-
describe('dispose', () => {
|
|
45
|
-
it('应该执行所有清理函数', async () => {
|
|
46
|
-
const cleanupFn1 = vi.fn();
|
|
47
|
-
const cleanupFn2 = vi.fn();
|
|
48
|
-
const cleanupFn3 = vi.fn();
|
|
49
|
-
disposer.addDisposer(cleanupFn1);
|
|
50
|
-
disposer.addDisposer(cleanupFn2);
|
|
51
|
-
disposer.addDisposer(cleanupFn3);
|
|
52
|
-
await disposer.dispose();
|
|
53
|
-
expect(cleanupFn1).toHaveBeenCalledOnce();
|
|
54
|
-
expect(cleanupFn2).toHaveBeenCalledOnce();
|
|
55
|
-
expect(cleanupFn3).toHaveBeenCalledOnce();
|
|
56
|
-
});
|
|
57
|
-
it('应该按添加顺序执行清理函数', async () => {
|
|
58
|
-
const executionOrder = [];
|
|
59
|
-
disposer.addDisposer(() => executionOrder.push(1));
|
|
60
|
-
disposer.addDisposer(() => executionOrder.push(2));
|
|
61
|
-
disposer.addDisposer(() => executionOrder.push(3));
|
|
62
|
-
await disposer.dispose();
|
|
63
|
-
expect(executionOrder).toEqual([1, 2, 3]);
|
|
64
|
-
});
|
|
65
|
-
it('应该按添加顺序执行异步清理函数', async () => {
|
|
66
|
-
const executionOrder = [];
|
|
67
|
-
disposer.addDisposer(async () => {
|
|
68
|
-
await Promise.resolve();
|
|
69
|
-
executionOrder.push(1);
|
|
70
|
-
});
|
|
71
|
-
disposer.addDisposer(async () => {
|
|
72
|
-
await Promise.resolve();
|
|
73
|
-
executionOrder.push(2);
|
|
74
|
-
});
|
|
75
|
-
disposer.addDisposer(async () => {
|
|
76
|
-
await Promise.resolve();
|
|
77
|
-
executionOrder.push(3);
|
|
78
|
-
});
|
|
79
|
-
await disposer.dispose();
|
|
80
|
-
expect(executionOrder).toEqual([1, 2, 3]);
|
|
81
|
-
});
|
|
82
|
-
it('应该处理清理函数中的错误', async () => {
|
|
83
|
-
const workingFn1 = vi.fn();
|
|
84
|
-
const errorFn = vi.fn(() => {
|
|
85
|
-
throw new Error('Cleanup error');
|
|
86
|
-
});
|
|
87
|
-
const workingFn2 = vi.fn();
|
|
88
|
-
// 模拟 logger.error
|
|
89
|
-
const loggerErrorSpy = vi.spyOn(logger, 'error').mockImplementation(() => { });
|
|
90
|
-
disposer.addDisposer(workingFn1);
|
|
91
|
-
disposer.addDisposer(errorFn);
|
|
92
|
-
disposer.addDisposer(workingFn2);
|
|
93
|
-
// dispose 不应该抛出错误
|
|
94
|
-
await expect(disposer.dispose()).resolves.toBeUndefined();
|
|
95
|
-
// 所有函数都应该被调用
|
|
96
|
-
expect(workingFn1).toHaveBeenCalled();
|
|
97
|
-
expect(errorFn).toHaveBeenCalled();
|
|
98
|
-
expect(workingFn2).toHaveBeenCalled();
|
|
99
|
-
// 错误应该被记录
|
|
100
|
-
expect(loggerErrorSpy).toHaveBeenCalledWith('Error during cleanup:', expect.any(Error));
|
|
101
|
-
loggerErrorSpy.mockRestore();
|
|
102
|
-
});
|
|
103
|
-
it('应该在执行后清空清理函数列表', async () => {
|
|
104
|
-
const cleanupFn = vi.fn();
|
|
105
|
-
disposer.addDisposer(cleanupFn);
|
|
106
|
-
await disposer.dispose();
|
|
107
|
-
expect(cleanupFn).toHaveBeenCalledOnce();
|
|
108
|
-
// 再次调用 dispose 不应该执行任何函数
|
|
109
|
-
await disposer.dispose();
|
|
110
|
-
expect(cleanupFn).toHaveBeenCalledOnce();
|
|
111
|
-
});
|
|
112
|
-
it('应该能够在清空后重新添加清理函数', async () => {
|
|
113
|
-
const firstCleanup = vi.fn();
|
|
114
|
-
const secondCleanup = vi.fn();
|
|
115
|
-
disposer.addDisposer(firstCleanup);
|
|
116
|
-
await disposer.dispose();
|
|
117
|
-
disposer.addDisposer(secondCleanup);
|
|
118
|
-
await disposer.dispose();
|
|
119
|
-
expect(firstCleanup).toHaveBeenCalledOnce();
|
|
120
|
-
expect(secondCleanup).toHaveBeenCalledOnce();
|
|
121
|
-
});
|
|
122
|
-
it('应该在没有清理函数时安全执行', async () => {
|
|
123
|
-
await expect(disposer.dispose()).resolves.toBeUndefined();
|
|
124
|
-
});
|
|
125
|
-
it('应该能够多次调用 dispose', async () => {
|
|
126
|
-
const cleanupFn = vi.fn();
|
|
127
|
-
disposer.addDisposer(cleanupFn);
|
|
128
|
-
await disposer.dispose();
|
|
129
|
-
await disposer.dispose();
|
|
130
|
-
await disposer.dispose();
|
|
131
|
-
expect(cleanupFn).toHaveBeenCalledOnce();
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
describe('实际使用场景', () => {
|
|
135
|
-
it('应该能够清理事件监听器', async () => {
|
|
136
|
-
const removeEventListener = vi.fn();
|
|
137
|
-
const unsubscribe = vi.fn();
|
|
138
|
-
disposer.addDisposer(removeEventListener);
|
|
139
|
-
disposer.addDisposer(unsubscribe);
|
|
140
|
-
await disposer.dispose();
|
|
141
|
-
expect(removeEventListener).toHaveBeenCalled();
|
|
142
|
-
expect(unsubscribe).toHaveBeenCalled();
|
|
143
|
-
});
|
|
144
|
-
it('应该能够清理定时器', async () => {
|
|
145
|
-
const clearTimeout = vi.fn();
|
|
146
|
-
const clearInterval = vi.fn();
|
|
147
|
-
disposer.addDisposer(() => clearTimeout(123));
|
|
148
|
-
disposer.addDisposer(() => clearInterval(456));
|
|
149
|
-
await disposer.dispose();
|
|
150
|
-
expect(clearTimeout).toHaveBeenCalledWith(123);
|
|
151
|
-
expect(clearInterval).toHaveBeenCalledWith(456);
|
|
152
|
-
});
|
|
153
|
-
it('应该能够清理资源连接', async () => {
|
|
154
|
-
const closeConnection = vi.fn();
|
|
155
|
-
const releaseResource = vi.fn();
|
|
156
|
-
disposer.addDisposer(() => closeConnection());
|
|
157
|
-
disposer.addDisposer(() => releaseResource());
|
|
158
|
-
await disposer.dispose();
|
|
159
|
-
expect(closeConnection).toHaveBeenCalled();
|
|
160
|
-
expect(releaseResource).toHaveBeenCalled();
|
|
161
|
-
});
|
|
162
|
-
it('应该与 EventEmitter 配合使用', async () => {
|
|
163
|
-
// 模拟 EventEmitter 的使用
|
|
164
|
-
const mockEventEmitter = {
|
|
165
|
-
on: vi.fn().mockReturnValue(vi.fn()), // 返回 off 函数
|
|
166
|
-
cleanup: vi.fn()
|
|
167
|
-
};
|
|
168
|
-
const offFunction1 = mockEventEmitter.on('event1', vi.fn());
|
|
169
|
-
const offFunction2 = mockEventEmitter.on('event2', vi.fn());
|
|
170
|
-
disposer.addDisposer(offFunction1);
|
|
171
|
-
disposer.addDisposer(offFunction2);
|
|
172
|
-
disposer.addDisposer(() => mockEventEmitter.cleanup());
|
|
173
|
-
await disposer.dispose();
|
|
174
|
-
expect(offFunction1).toHaveBeenCalled();
|
|
175
|
-
expect(offFunction2).toHaveBeenCalled();
|
|
176
|
-
expect(mockEventEmitter.cleanup).toHaveBeenCalled();
|
|
177
|
-
});
|
|
178
|
-
});
|
|
179
|
-
describe('错误处理', () => {
|
|
180
|
-
it('应该捕获并记录同步错误', async () => {
|
|
181
|
-
const loggerErrorSpy = vi.spyOn(logger, 'error').mockImplementation(() => { });
|
|
182
|
-
const error = new Error('Sync error');
|
|
183
|
-
disposer.addDisposer(() => {
|
|
184
|
-
throw error;
|
|
185
|
-
});
|
|
186
|
-
await disposer.dispose();
|
|
187
|
-
expect(loggerErrorSpy).toHaveBeenCalledWith('Error during cleanup:', error);
|
|
188
|
-
loggerErrorSpy.mockRestore();
|
|
189
|
-
});
|
|
190
|
-
it('应该处理不同类型的错误', async () => {
|
|
191
|
-
const loggerErrorSpy = vi.spyOn(logger, 'error').mockImplementation(() => { });
|
|
192
|
-
disposer.addDisposer(() => {
|
|
193
|
-
throw new TypeError('Type error');
|
|
194
|
-
});
|
|
195
|
-
disposer.addDisposer(() => {
|
|
196
|
-
throw 'String error';
|
|
197
|
-
});
|
|
198
|
-
disposer.addDisposer(() => {
|
|
199
|
-
throw { message: 'Object error' };
|
|
200
|
-
});
|
|
201
|
-
await disposer.dispose();
|
|
202
|
-
expect(loggerErrorSpy).toHaveBeenCalledTimes(3);
|
|
203
|
-
loggerErrorSpy.mockRestore();
|
|
204
|
-
});
|
|
205
|
-
it('应该捕获并记录异步错误', async () => {
|
|
206
|
-
const loggerErrorSpy = vi.spyOn(logger, 'error').mockImplementation(() => { });
|
|
207
|
-
const asyncError = new Error('Async error');
|
|
208
|
-
disposer.addDisposer(async () => {
|
|
209
|
-
throw asyncError;
|
|
210
|
-
});
|
|
211
|
-
await disposer.dispose();
|
|
212
|
-
expect(loggerErrorSpy).toHaveBeenCalledWith('Error during cleanup:', asyncError);
|
|
213
|
-
loggerErrorSpy.mockRestore();
|
|
214
|
-
});
|
|
215
|
-
});
|
|
216
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../source/disposer/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAA"}
|
package/output/disposer/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './disposer.js';
|