@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,358 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
-
import { BatchingBuffer } from './batching-buffer.js';
|
|
3
|
-
describe('BatchingBuffer', () => {
|
|
4
|
-
let batchProcessor;
|
|
5
|
-
let itemProcessor;
|
|
6
|
-
beforeEach(() => {
|
|
7
|
-
batchProcessor = vi.fn();
|
|
8
|
-
itemProcessor = vi.fn();
|
|
9
|
-
vi.useFakeTimers();
|
|
10
|
-
});
|
|
11
|
-
afterEach(() => {
|
|
12
|
-
vi.useRealTimers();
|
|
13
|
-
vi.clearAllMocks();
|
|
14
|
-
});
|
|
15
|
-
describe('构造函数', () => {
|
|
16
|
-
it('应该正确初始化批量处理模式', () => {
|
|
17
|
-
const buffer = new BatchingBuffer({
|
|
18
|
-
batchProcessor: batchProcessor,
|
|
19
|
-
bufferSize: 10,
|
|
20
|
-
flushInterval: 5000
|
|
21
|
-
});
|
|
22
|
-
expect(buffer.size).toBe(0);
|
|
23
|
-
expect(buffer.isEmpty).toBe(true);
|
|
24
|
-
expect(buffer.destroyed).toBe(false);
|
|
25
|
-
});
|
|
26
|
-
it('应该正确初始化单个处理模式', () => {
|
|
27
|
-
const buffer = new BatchingBuffer({
|
|
28
|
-
itemProcessor: itemProcessor,
|
|
29
|
-
bufferSize: 5,
|
|
30
|
-
flushInterval: 3000
|
|
31
|
-
});
|
|
32
|
-
expect(buffer.size).toBe(0);
|
|
33
|
-
expect(buffer.isEmpty).toBe(true);
|
|
34
|
-
expect(buffer.destroyed).toBe(false);
|
|
35
|
-
});
|
|
36
|
-
it('应该使用默认配置', () => {
|
|
37
|
-
const buffer = new BatchingBuffer({
|
|
38
|
-
batchProcessor: batchProcessor
|
|
39
|
-
});
|
|
40
|
-
expect(buffer.size).toBe(0);
|
|
41
|
-
expect(buffer.isEmpty).toBe(true);
|
|
42
|
-
});
|
|
43
|
-
it('应该在没有提供处理器时抛出错误', () => {
|
|
44
|
-
expect(() => {
|
|
45
|
-
new BatchingBuffer({});
|
|
46
|
-
}).toThrow('必须提供 batchProcessor 或 itemProcessor 其中之一');
|
|
47
|
-
});
|
|
48
|
-
it('应该在同时提供两个处理器时抛出错误', () => {
|
|
49
|
-
expect(() => {
|
|
50
|
-
new BatchingBuffer({
|
|
51
|
-
batchProcessor: batchProcessor,
|
|
52
|
-
itemProcessor: itemProcessor
|
|
53
|
-
});
|
|
54
|
-
}).toThrow('只能选择 batchProcessor 或 itemProcessor 中的一个');
|
|
55
|
-
});
|
|
56
|
-
it('应该在 bufferSize 无效时抛出错误', () => {
|
|
57
|
-
expect(() => {
|
|
58
|
-
new BatchingBuffer({
|
|
59
|
-
batchProcessor: batchProcessor,
|
|
60
|
-
bufferSize: 0
|
|
61
|
-
});
|
|
62
|
-
}).toThrow('bufferSize 必须大于 0');
|
|
63
|
-
expect(() => {
|
|
64
|
-
new BatchingBuffer({
|
|
65
|
-
batchProcessor: batchProcessor,
|
|
66
|
-
bufferSize: -1
|
|
67
|
-
});
|
|
68
|
-
}).toThrow('bufferSize 必须大于 0');
|
|
69
|
-
});
|
|
70
|
-
it('应该在 flushInterval 无效时抛出错误', () => {
|
|
71
|
-
expect(() => {
|
|
72
|
-
new BatchingBuffer({
|
|
73
|
-
batchProcessor: batchProcessor,
|
|
74
|
-
flushInterval: 0
|
|
75
|
-
});
|
|
76
|
-
}).toThrow('flushInterval 必须大于 0');
|
|
77
|
-
expect(() => {
|
|
78
|
-
new BatchingBuffer({
|
|
79
|
-
batchProcessor: batchProcessor,
|
|
80
|
-
flushInterval: -1
|
|
81
|
-
});
|
|
82
|
-
}).toThrow('flushInterval 必须大于 0');
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
describe('批量处理模式', () => {
|
|
86
|
-
let buffer;
|
|
87
|
-
beforeEach(() => {
|
|
88
|
-
buffer = new BatchingBuffer({
|
|
89
|
-
batchProcessor: batchProcessor,
|
|
90
|
-
bufferSize: 3,
|
|
91
|
-
flushInterval: 1000
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
|
-
afterEach(async () => {
|
|
95
|
-
await buffer.destroy();
|
|
96
|
-
});
|
|
97
|
-
it('应该在达到缓冲区大小时触发批量处理', () => {
|
|
98
|
-
buffer.add('item1');
|
|
99
|
-
buffer.add('item2');
|
|
100
|
-
expect(batchProcessor).not.toHaveBeenCalled();
|
|
101
|
-
buffer.add('item3');
|
|
102
|
-
expect(batchProcessor).toHaveBeenCalledTimes(1);
|
|
103
|
-
expect(batchProcessor).toHaveBeenCalledWith(['item1', 'item2', 'item3']);
|
|
104
|
-
expect(buffer.size).toBe(0);
|
|
105
|
-
});
|
|
106
|
-
it('应该在时间间隔到达时触发批量处理', async () => {
|
|
107
|
-
buffer.add('item1');
|
|
108
|
-
buffer.add('item2');
|
|
109
|
-
expect(batchProcessor).not.toHaveBeenCalled();
|
|
110
|
-
vi.advanceTimersByTime(1000);
|
|
111
|
-
await vi.runAllTimersAsync();
|
|
112
|
-
expect(batchProcessor).toHaveBeenCalledTimes(1);
|
|
113
|
-
expect(batchProcessor).toHaveBeenCalledWith(['item1', 'item2']);
|
|
114
|
-
expect(buffer.size).toBe(0);
|
|
115
|
-
});
|
|
116
|
-
it('应该支持手动刷新', async () => {
|
|
117
|
-
buffer.add('item1');
|
|
118
|
-
buffer.add('item2');
|
|
119
|
-
await buffer.flush();
|
|
120
|
-
expect(batchProcessor).toHaveBeenCalledTimes(1);
|
|
121
|
-
expect(batchProcessor).toHaveBeenCalledWith(['item1', 'item2']);
|
|
122
|
-
expect(buffer.size).toBe(0);
|
|
123
|
-
});
|
|
124
|
-
it('应该支持批量添加数据', () => {
|
|
125
|
-
buffer.addBatch(['item1', 'item2', 'item3', 'item4', 'item5']);
|
|
126
|
-
expect(batchProcessor).toHaveBeenCalledTimes(2);
|
|
127
|
-
expect(batchProcessor).toHaveBeenNthCalledWith(1, ['item1', 'item2', 'item3']);
|
|
128
|
-
expect(batchProcessor).toHaveBeenNthCalledWith(2, ['item4', 'item5']);
|
|
129
|
-
expect(buffer.size).toBe(0);
|
|
130
|
-
});
|
|
131
|
-
it('应该正确处理处理器异常', () => {
|
|
132
|
-
const error = new Error('处理失败');
|
|
133
|
-
batchProcessor.mockImplementationOnce(() => {
|
|
134
|
-
throw error;
|
|
135
|
-
});
|
|
136
|
-
buffer.add('item1');
|
|
137
|
-
buffer.add('item2');
|
|
138
|
-
expect(() => {
|
|
139
|
-
buffer.add('item3');
|
|
140
|
-
}).toThrow('处理失败');
|
|
141
|
-
// 数据应该重新放回缓冲区
|
|
142
|
-
expect(buffer.size).toBe(3);
|
|
143
|
-
});
|
|
144
|
-
});
|
|
145
|
-
describe('单个处理模式', () => {
|
|
146
|
-
let buffer;
|
|
147
|
-
beforeEach(() => {
|
|
148
|
-
buffer = new BatchingBuffer({
|
|
149
|
-
itemProcessor: itemProcessor,
|
|
150
|
-
bufferSize: 3,
|
|
151
|
-
flushInterval: 1000
|
|
152
|
-
});
|
|
153
|
-
});
|
|
154
|
-
afterEach(async () => {
|
|
155
|
-
await buffer.destroy();
|
|
156
|
-
});
|
|
157
|
-
it('应该在达到缓冲区大小时触发单个处理', () => {
|
|
158
|
-
buffer.add('item1');
|
|
159
|
-
buffer.add('item2');
|
|
160
|
-
expect(itemProcessor).not.toHaveBeenCalled();
|
|
161
|
-
buffer.add('item3');
|
|
162
|
-
expect(itemProcessor).toHaveBeenCalledTimes(3);
|
|
163
|
-
expect(itemProcessor).toHaveBeenNthCalledWith(1, 'item1');
|
|
164
|
-
expect(itemProcessor).toHaveBeenNthCalledWith(2, 'item2');
|
|
165
|
-
expect(itemProcessor).toHaveBeenNthCalledWith(3, 'item3');
|
|
166
|
-
expect(buffer.size).toBe(0);
|
|
167
|
-
});
|
|
168
|
-
it('应该在时间间隔到达时触发单个处理', async () => {
|
|
169
|
-
buffer.add('item1');
|
|
170
|
-
buffer.add('item2');
|
|
171
|
-
expect(itemProcessor).not.toHaveBeenCalled();
|
|
172
|
-
vi.advanceTimersByTime(1000);
|
|
173
|
-
await vi.runAllTimersAsync();
|
|
174
|
-
expect(itemProcessor).toHaveBeenCalledTimes(2);
|
|
175
|
-
expect(itemProcessor).toHaveBeenNthCalledWith(1, 'item1');
|
|
176
|
-
expect(itemProcessor).toHaveBeenNthCalledWith(2, 'item2');
|
|
177
|
-
expect(buffer.size).toBe(0);
|
|
178
|
-
});
|
|
179
|
-
it('应该正确处理单个处理器异常', () => {
|
|
180
|
-
const error = new Error('单个处理失败');
|
|
181
|
-
itemProcessor.mockImplementationOnce(() => {
|
|
182
|
-
throw error;
|
|
183
|
-
});
|
|
184
|
-
buffer.add('item1');
|
|
185
|
-
buffer.add('item2');
|
|
186
|
-
expect(() => {
|
|
187
|
-
buffer.add('item3');
|
|
188
|
-
}).toThrow('单个处理失败');
|
|
189
|
-
// 数据应该重新放回缓冲区
|
|
190
|
-
expect(buffer.size).toBe(3);
|
|
191
|
-
});
|
|
192
|
-
});
|
|
193
|
-
describe('缓冲区状态', () => {
|
|
194
|
-
let buffer;
|
|
195
|
-
beforeEach(() => {
|
|
196
|
-
buffer = new BatchingBuffer({
|
|
197
|
-
batchProcessor: batchProcessor,
|
|
198
|
-
bufferSize: 5,
|
|
199
|
-
flushInterval: 2000
|
|
200
|
-
});
|
|
201
|
-
});
|
|
202
|
-
afterEach(async () => {
|
|
203
|
-
await buffer.destroy();
|
|
204
|
-
});
|
|
205
|
-
it('应该正确报告缓冲区大小', () => {
|
|
206
|
-
expect(buffer.size).toBe(0);
|
|
207
|
-
expect(buffer.isEmpty).toBe(true);
|
|
208
|
-
buffer.add(1);
|
|
209
|
-
expect(buffer.size).toBe(1);
|
|
210
|
-
expect(buffer.isEmpty).toBe(false);
|
|
211
|
-
buffer.add(2);
|
|
212
|
-
buffer.add(3);
|
|
213
|
-
expect(buffer.size).toBe(3);
|
|
214
|
-
expect(buffer.isEmpty).toBe(false);
|
|
215
|
-
});
|
|
216
|
-
it('应该正确报告距离上次刷新的时间', async () => {
|
|
217
|
-
const startTime = Date.now();
|
|
218
|
-
buffer.add(1);
|
|
219
|
-
vi.advanceTimersByTime(500);
|
|
220
|
-
expect(buffer.timeSinceLastFlush).toBeGreaterThanOrEqual(500);
|
|
221
|
-
await buffer.flush();
|
|
222
|
-
expect(buffer.timeSinceLastFlush).toBeLessThan(100);
|
|
223
|
-
});
|
|
224
|
-
});
|
|
225
|
-
describe('销毁功能', () => {
|
|
226
|
-
let buffer;
|
|
227
|
-
beforeEach(() => {
|
|
228
|
-
buffer = new BatchingBuffer({
|
|
229
|
-
batchProcessor: batchProcessor,
|
|
230
|
-
bufferSize: 5,
|
|
231
|
-
flushInterval: 1000
|
|
232
|
-
});
|
|
233
|
-
});
|
|
234
|
-
it('应该在销毁时处理剩余数据', async () => {
|
|
235
|
-
buffer.add('item1');
|
|
236
|
-
buffer.add('item2');
|
|
237
|
-
await buffer.destroy();
|
|
238
|
-
expect(batchProcessor).toHaveBeenCalledTimes(1);
|
|
239
|
-
expect(batchProcessor).toHaveBeenCalledWith(['item1', 'item2']);
|
|
240
|
-
expect(buffer.destroyed).toBe(true);
|
|
241
|
-
expect(buffer.size).toBe(0);
|
|
242
|
-
});
|
|
243
|
-
it('应该在销毁时丢弃剩余数据(如果指定)', async () => {
|
|
244
|
-
buffer.add('item1');
|
|
245
|
-
buffer.add('item2');
|
|
246
|
-
await buffer.destroy(false);
|
|
247
|
-
expect(batchProcessor).not.toHaveBeenCalled();
|
|
248
|
-
expect(buffer.destroyed).toBe(true);
|
|
249
|
-
expect(buffer.size).toBe(0);
|
|
250
|
-
});
|
|
251
|
-
it('应该在销毁后拒绝添加新数据', async () => {
|
|
252
|
-
await buffer.destroy();
|
|
253
|
-
expect(() => {
|
|
254
|
-
buffer.add('item1');
|
|
255
|
-
}).toThrow('BatchingBuffer 已被销毁,不能添加新数据');
|
|
256
|
-
expect(() => {
|
|
257
|
-
buffer.addBatch(['item1', 'item2']);
|
|
258
|
-
}).toThrow('BatchingBuffer 已被销毁,不能添加新数据');
|
|
259
|
-
});
|
|
260
|
-
it('应该支持重复销毁', async () => {
|
|
261
|
-
await buffer.destroy();
|
|
262
|
-
await buffer.destroy();
|
|
263
|
-
expect(buffer.destroyed).toBe(true);
|
|
264
|
-
});
|
|
265
|
-
});
|
|
266
|
-
describe('自动刷新配置', () => {
|
|
267
|
-
it('应该在 autoFlush=false 时不自动启动定时器', async () => {
|
|
268
|
-
const buffer = new BatchingBuffer({
|
|
269
|
-
batchProcessor: batchProcessor,
|
|
270
|
-
bufferSize: 5,
|
|
271
|
-
flushInterval: 1000,
|
|
272
|
-
autoFlush: false
|
|
273
|
-
});
|
|
274
|
-
buffer.add('item1');
|
|
275
|
-
buffer.add('item2');
|
|
276
|
-
vi.advanceTimersByTime(2000);
|
|
277
|
-
await vi.runAllTimersAsync();
|
|
278
|
-
expect(batchProcessor).not.toHaveBeenCalled();
|
|
279
|
-
expect(buffer.size).toBe(2);
|
|
280
|
-
await buffer.destroy();
|
|
281
|
-
});
|
|
282
|
-
it('应该在 autoFlush=false 时仍支持基于大小的触发', async () => {
|
|
283
|
-
const buffer = new BatchingBuffer({
|
|
284
|
-
batchProcessor: batchProcessor,
|
|
285
|
-
bufferSize: 2,
|
|
286
|
-
flushInterval: 1000,
|
|
287
|
-
autoFlush: false
|
|
288
|
-
});
|
|
289
|
-
buffer.add('item1');
|
|
290
|
-
buffer.add('item2');
|
|
291
|
-
await vi.runAllTimersAsync();
|
|
292
|
-
expect(batchProcessor).toHaveBeenCalledTimes(1);
|
|
293
|
-
expect(batchProcessor).toHaveBeenCalledWith(['item1', 'item2']);
|
|
294
|
-
await buffer.destroy();
|
|
295
|
-
});
|
|
296
|
-
});
|
|
297
|
-
describe('复杂数据类型', () => {
|
|
298
|
-
let buffer;
|
|
299
|
-
beforeEach(() => {
|
|
300
|
-
buffer = new BatchingBuffer({
|
|
301
|
-
batchProcessor: batchProcessor,
|
|
302
|
-
bufferSize: 2,
|
|
303
|
-
flushInterval: 1000
|
|
304
|
-
});
|
|
305
|
-
});
|
|
306
|
-
afterEach(async () => {
|
|
307
|
-
await buffer.destroy();
|
|
308
|
-
});
|
|
309
|
-
it('应该正确处理复杂对象', async () => {
|
|
310
|
-
const data1 = { id: 1, name: 'test1' };
|
|
311
|
-
const data2 = { id: 2, name: 'test2' };
|
|
312
|
-
buffer.add(data1);
|
|
313
|
-
buffer.add(data2);
|
|
314
|
-
await vi.runAllTimersAsync();
|
|
315
|
-
expect(batchProcessor).toHaveBeenCalledTimes(1);
|
|
316
|
-
expect(batchProcessor).toHaveBeenCalledWith([data1, data2]);
|
|
317
|
-
});
|
|
318
|
-
});
|
|
319
|
-
describe('异步处理器', () => {
|
|
320
|
-
let asyncBatchProcessor;
|
|
321
|
-
let asyncItemProcessor;
|
|
322
|
-
beforeEach(() => {
|
|
323
|
-
asyncBatchProcessor = vi.fn().mockImplementation(async (items) => {
|
|
324
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
325
|
-
return `处理了 ${items.length} 个项目`;
|
|
326
|
-
});
|
|
327
|
-
asyncItemProcessor = vi.fn().mockImplementation(async (item) => {
|
|
328
|
-
await new Promise(resolve => setTimeout(resolve, 50));
|
|
329
|
-
return `处理了项目: ${item}`;
|
|
330
|
-
});
|
|
331
|
-
});
|
|
332
|
-
it('应该正确处理异步批量处理器', () => {
|
|
333
|
-
const buffer = new BatchingBuffer({
|
|
334
|
-
batchProcessor: asyncBatchProcessor,
|
|
335
|
-
bufferSize: 2,
|
|
336
|
-
flushInterval: 1000
|
|
337
|
-
});
|
|
338
|
-
buffer.add('item1');
|
|
339
|
-
buffer.add('item2');
|
|
340
|
-
expect(asyncBatchProcessor).toHaveBeenCalledTimes(1);
|
|
341
|
-
expect(asyncBatchProcessor).toHaveBeenCalledWith(['item1', 'item2']);
|
|
342
|
-
buffer.destroy();
|
|
343
|
-
});
|
|
344
|
-
it('应该正确处理异步单个处理器', () => {
|
|
345
|
-
const buffer = new BatchingBuffer({
|
|
346
|
-
itemProcessor: asyncItemProcessor,
|
|
347
|
-
bufferSize: 2,
|
|
348
|
-
flushInterval: 1000
|
|
349
|
-
});
|
|
350
|
-
buffer.add('item1');
|
|
351
|
-
buffer.add('item2');
|
|
352
|
-
expect(asyncItemProcessor).toHaveBeenCalledTimes(2);
|
|
353
|
-
expect(asyncItemProcessor).toHaveBeenNthCalledWith(1, 'item1');
|
|
354
|
-
expect(asyncItemProcessor).toHaveBeenNthCalledWith(2, 'item2');
|
|
355
|
-
buffer.destroy();
|
|
356
|
-
});
|
|
357
|
-
});
|
|
358
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../source/batching-buffer/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,YAAY,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { BatchingBuffer } from './batching-buffer.js';
|
package/output/catch/catch.d.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
type CatchType<F extends () => unknown> = F extends () => PromiseLike<infer R> ? R : F extends () => infer R ? R : never;
|
|
2
|
-
/**
|
|
3
|
-
* 成功结果类型
|
|
4
|
-
* 只包含 value 字段,error 字段为 undefined
|
|
5
|
-
*/
|
|
6
|
-
export interface CatchSuccess<T> {
|
|
7
|
-
value: T;
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* 失败结果类型
|
|
11
|
-
* error 字段类型永远为 unknown(或用户自定义),这样最安全,防止误用。
|
|
12
|
-
* 推荐在 error 分支内用 instanceof/typeof 等类型守卫自行收窄类型。
|
|
13
|
-
*/
|
|
14
|
-
export interface CatchFailure<E> {
|
|
15
|
-
error: E;
|
|
16
|
-
context: unknown;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* 捕获结果联合类型,使用判别联合类型以支持类型守卫
|
|
20
|
-
*
|
|
21
|
-
* 设计说明:
|
|
22
|
-
* - 通过 isError 方法进行类型守卫,推荐始终用 result.isError() 判断是否为错误分支。
|
|
23
|
-
* - isError 方法为 function 写法(而非箭头函数),以支持类型谓词,且 this 不会被转移。
|
|
24
|
-
* - 不建议直接用 error !== undefined 判断错误分支,该方式依赖 error 的值,推荐统一用 isError()。
|
|
25
|
-
*/
|
|
26
|
-
export type CatchResult<T, E = unknown> = (CatchSuccess<T> | CatchFailure<E>) & {
|
|
27
|
-
/**
|
|
28
|
-
* 类型守卫方法,判断当前对象是否为 CatchFailure。
|
|
29
|
-
* function 写法,返回类型谓词,保证类型收窄。
|
|
30
|
-
* 推荐用法:if (result.isError()) { ... }
|
|
31
|
-
*/
|
|
32
|
-
isError: (this: unknown) => this is CatchFailure<E>;
|
|
33
|
-
};
|
|
34
|
-
/**
|
|
35
|
-
* 通用错误捕获函数,支持 PromiseLike 和函数执行
|
|
36
|
-
* 返回 { value, error } 的对象格式,便于类型判断
|
|
37
|
-
*
|
|
38
|
-
* 设计说明:
|
|
39
|
-
* - 支持同步/异步/thenable 场景
|
|
40
|
-
* - 推荐通过 isError() 进行类型守卫
|
|
41
|
-
* - error 字段类型为 unknown,需用户自行收窄
|
|
42
|
-
*/
|
|
43
|
-
export declare function catchIt<T, E = unknown>(input: PromiseLike<T>): Promise<CatchResult<T, E>>;
|
|
44
|
-
export declare function catchIt<F extends () => unknown, E = unknown>(input: F): Promise<CatchResult<CatchType<F>, E>>;
|
|
45
|
-
export {};
|
|
46
|
-
//# sourceMappingURL=catch.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"catch.d.ts","sourceRoot":"","sources":["../../source/catch/catch.ts"],"names":[],"mappings":"AAMA,KAAK,SAAS,CAAC,CAAC,SAAS,MAAM,OAAO,IAAI,CAAC,SAAS,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,MAAM,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;AAExH;;;GAGG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,KAAK,EAAE,CAAC,CAAA;CACT;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,KAAK,EAAE,CAAC,CAAA;IACR,OAAO,EAAE,OAAO,CAAA;CACjB;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG;IAC9E;;;;OAIG;IACH,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,IAAI,YAAY,CAAC,CAAC,CAAC,CAAA;CACpD,CAAA;AA0BD;;;;;;;;GAQG;AACH,wBAAsB,OAAO,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;AAChG,wBAAsB,OAAO,CAAC,CAAC,SAAS,MAAM,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA"}
|
package/output/catch/catch.js
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
// 辅助函数:检查是否为 PromiseLike
|
|
2
|
-
function isPromiseLike(value) {
|
|
3
|
-
return value != null && typeof value === 'object' && 'then' in value && typeof value.then === 'function';
|
|
4
|
-
}
|
|
5
|
-
/**
|
|
6
|
-
* 构造成功结果对象
|
|
7
|
-
* isError 始终返回 false
|
|
8
|
-
*/
|
|
9
|
-
function createSuccess(value) {
|
|
10
|
-
return {
|
|
11
|
-
value,
|
|
12
|
-
error: undefined,
|
|
13
|
-
isError() { return false; }
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* 构造失败结果对象
|
|
18
|
-
* isError 始终返回 true
|
|
19
|
-
*/
|
|
20
|
-
function createFailure(error) {
|
|
21
|
-
return {
|
|
22
|
-
error,
|
|
23
|
-
value: undefined,
|
|
24
|
-
isError() { return true; }
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
export async function catchIt(input) {
|
|
28
|
-
try {
|
|
29
|
-
if (isPromiseLike(input)) {
|
|
30
|
-
const result = await Promise.resolve(input);
|
|
31
|
-
return createSuccess(result);
|
|
32
|
-
}
|
|
33
|
-
else if (typeof input === 'function') {
|
|
34
|
-
const result = input();
|
|
35
|
-
if (isPromiseLike(result)) {
|
|
36
|
-
return catchIt(result);
|
|
37
|
-
}
|
|
38
|
-
else {
|
|
39
|
-
return createSuccess(result);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
catch (error) {
|
|
44
|
-
return createFailure(error);
|
|
45
|
-
}
|
|
46
|
-
// 理论上不会到达这里,兜底类型安全
|
|
47
|
-
return createFailure(new Error('Unexpected input type'));
|
|
48
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"catch.test.d.ts","sourceRoot":"","sources":["../../source/catch/catch.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { catchIt } from './catch.js';
|
|
3
|
-
describe('catchIt', () => {
|
|
4
|
-
it('同步函数返回值应为 value,error 为 undefined,isError 为 false', async () => {
|
|
5
|
-
const result = await catchIt(() => 123);
|
|
6
|
-
expect(result.value).toBe(123);
|
|
7
|
-
expect(result.error).toBeUndefined();
|
|
8
|
-
expect(result.isError()).toBe(false);
|
|
9
|
-
});
|
|
10
|
-
it('异步函数返回值应为 value,error 为 undefined,isError 为 false', async () => {
|
|
11
|
-
const result = await catchIt(async () => 456);
|
|
12
|
-
expect(result.value).toBe(456);
|
|
13
|
-
expect(result.error).toBeUndefined();
|
|
14
|
-
expect(result.isError()).toBe(false);
|
|
15
|
-
});
|
|
16
|
-
it('同步抛出异常时应返回 error,value 为 undefined,isError 为 true', async () => {
|
|
17
|
-
const error = new Error('fail');
|
|
18
|
-
const result = await catchIt(() => { throw error; });
|
|
19
|
-
expect(result.value).toBeUndefined();
|
|
20
|
-
expect(result.error).toBe(error);
|
|
21
|
-
expect(result.isError()).toBe(true);
|
|
22
|
-
});
|
|
23
|
-
it('异步抛出异常时应返回 error,value 为 undefined,isError 为 true', async () => {
|
|
24
|
-
const error = new Error('fail-async');
|
|
25
|
-
const result = await catchIt(() => Promise.reject(error));
|
|
26
|
-
expect(result.value).toBeUndefined();
|
|
27
|
-
expect(result.error).toBe(error);
|
|
28
|
-
expect(result.isError()).toBe(true);
|
|
29
|
-
});
|
|
30
|
-
it('PromiseLike resolve 时应返回 value,error 为 undefined,isError 为 false', async () => {
|
|
31
|
-
const result = await catchIt(Promise.resolve('ok'));
|
|
32
|
-
expect(result.value).toBe('ok');
|
|
33
|
-
expect(result.error).toBeUndefined();
|
|
34
|
-
expect(result.isError()).toBe(false);
|
|
35
|
-
});
|
|
36
|
-
it('PromiseLike reject 时应返回 error,value 为 undefined,isError 为 true', async () => {
|
|
37
|
-
const error = new Error('promise-fail');
|
|
38
|
-
const result = await catchIt(Promise.reject(error));
|
|
39
|
-
expect(result.value).toBeUndefined();
|
|
40
|
-
expect(result.error).toBe(error);
|
|
41
|
-
expect(result.isError()).toBe(true);
|
|
42
|
-
});
|
|
43
|
-
});
|
package/output/catch/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../source/catch/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA"}
|
package/output/catch/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './catch.js';
|
package/output/color/color.d.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
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,YAM/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"}
|
package/output/color/color.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
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
|
-
const finalHue = (hue + normalizedOffset) % range;
|
|
18
|
-
return `hsl(${finalHue}, ${saturation}%, ${lightness}%)`;
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
export function getRandomColors(seed, interval, count) {
|
|
22
|
-
const colors = [];
|
|
23
|
-
const colorFunc = getRandomColor(seed);
|
|
24
|
-
for (let i = 0; i < count; i++) {
|
|
25
|
-
colors.push(colorFunc(i * interval));
|
|
26
|
-
}
|
|
27
|
-
return colors;
|
|
28
|
-
}
|
|
29
|
-
export function interpolateColors(color1, color2, steps) {
|
|
30
|
-
function parseHSL(color) {
|
|
31
|
-
const match = color.match(/hsl\((\d+),\s*(\d+)%?,\s*(\d+)%?\)/);
|
|
32
|
-
if (!match) {
|
|
33
|
-
throw new Error(`Invalid HSL color: ${color}`);
|
|
34
|
-
}
|
|
35
|
-
return [parseInt(match[1]), parseInt(match[2]), parseInt(match[3])];
|
|
36
|
-
}
|
|
37
|
-
function hslToString(h, s, l) {
|
|
38
|
-
return `hsl(${Math.round(h)}, ${Math.round(s)}%, ${Math.round(l)}%)`;
|
|
39
|
-
}
|
|
40
|
-
const [h1, s1, l1] = parseHSL(color1);
|
|
41
|
-
const [h2, s2, l2] = parseHSL(color2);
|
|
42
|
-
return (index) => {
|
|
43
|
-
if (index < 0 || index > steps) {
|
|
44
|
-
throw new Error(`Index out of bounds: ${index}. Valid range is 0 to ${steps}.`);
|
|
45
|
-
}
|
|
46
|
-
// 当steps为0时,直接返回第一个颜色
|
|
47
|
-
if (steps === 0) {
|
|
48
|
-
return hslToString(h1, s1, l1);
|
|
49
|
-
}
|
|
50
|
-
const ratio = index / steps;
|
|
51
|
-
const h = h1 + (h2 - h1) * ratio;
|
|
52
|
-
const s = s1 + (s2 - s1) * ratio;
|
|
53
|
-
const l = l1 + (l2 - l1) * ratio;
|
|
54
|
-
return hslToString(h, s, l);
|
|
55
|
-
};
|
|
56
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"color.test.d.ts","sourceRoot":"","sources":["../../source/color/color.test.ts"],"names":[],"mappings":""}
|