@agentica/core 0.18.0 → 0.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.mjs +32 -14
- package/lib/index.mjs.map +1 -1
- package/lib/utils/AsyncQueue.d.ts +10 -0
- package/lib/utils/AsyncQueue.js +33 -9
- package/lib/utils/AsyncQueue.js.map +1 -1
- package/lib/utils/AsyncQueue.spec.d.ts +1 -0
- package/lib/utils/AsyncQueue.spec.js +280 -0
- package/lib/utils/AsyncQueue.spec.js.map +1 -0
- package/lib/utils/MPSC.spec.d.ts +1 -0
- package/lib/utils/MPSC.spec.js +222 -0
- package/lib/utils/MPSC.spec.js.map +1 -0
- package/lib/utils/StreamUtil.spec.d.ts +1 -0
- package/lib/utils/StreamUtil.spec.js +471 -0
- package/lib/utils/StreamUtil.spec.js.map +1 -0
- package/package.json +1 -1
- package/src/utils/AsyncQueue.spec.ts +355 -0
- package/src/utils/AsyncQueue.ts +36 -8
- package/src/utils/MPSC.spec.ts +276 -0
- package/src/utils/StreamUtil.spec.ts +520 -0
|
@@ -0,0 +1,520 @@
|
|
|
1
|
+
import { streamDefaultReaderToAsyncGenerator, StreamUtil, toAsyncGenerator } from "./StreamUtil";
|
|
2
|
+
|
|
3
|
+
// Helper function to create a stream with numbers from start to end
|
|
4
|
+
function createNumberStream(
|
|
5
|
+
start: number,
|
|
6
|
+
end: number,
|
|
7
|
+
): ReadableStream<number> {
|
|
8
|
+
return new ReadableStream<number>({
|
|
9
|
+
start(controller) {
|
|
10
|
+
for (let i = start; i <= end; i++) {
|
|
11
|
+
controller.enqueue(i);
|
|
12
|
+
}
|
|
13
|
+
controller.close();
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Helper function to create an empty stream
|
|
19
|
+
function createEmptyStream<T>(): ReadableStream<T> {
|
|
20
|
+
return new ReadableStream<T>({
|
|
21
|
+
start(controller) {
|
|
22
|
+
controller.close();
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Helper function to convert ReadableStream to array
|
|
28
|
+
async function streamToArray<T>(stream: ReadableStream<T>): Promise<T[]> {
|
|
29
|
+
const reader = stream.getReader();
|
|
30
|
+
const result: T[] = [];
|
|
31
|
+
|
|
32
|
+
while (true) {
|
|
33
|
+
const { done, value } = await reader.read();
|
|
34
|
+
if (done) {
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
result.push(value);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Helper function to create test stream
|
|
44
|
+
function createTestStream<T>(items: T[]): ReadableStream<T> {
|
|
45
|
+
return new ReadableStream<T>({
|
|
46
|
+
start(controller) {
|
|
47
|
+
for (const item of items) {
|
|
48
|
+
controller.enqueue(item);
|
|
49
|
+
}
|
|
50
|
+
controller.close();
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Delay function (for simulating async operations)
|
|
56
|
+
async function delay(ms: number): Promise<void> {
|
|
57
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Helper function to create a stream with numbers from start to end asynchronously
|
|
61
|
+
async function createDelayedNumberStream(
|
|
62
|
+
start: number,
|
|
63
|
+
end: number,
|
|
64
|
+
delayMs: number,
|
|
65
|
+
): Promise<ReadableStream<number>> {
|
|
66
|
+
// Simulate async work
|
|
67
|
+
await delay(delayMs);
|
|
68
|
+
|
|
69
|
+
return new ReadableStream<number>({
|
|
70
|
+
start(controller) {
|
|
71
|
+
for (let i = start; i <= end; i++) {
|
|
72
|
+
controller.enqueue(i);
|
|
73
|
+
}
|
|
74
|
+
controller.close();
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Helper function to create an empty stream asynchronously
|
|
80
|
+
async function createEmptyDelayedStream<T>(
|
|
81
|
+
delayMs: number,
|
|
82
|
+
): Promise<ReadableStream<T>> {
|
|
83
|
+
// Simulate async work
|
|
84
|
+
await delay(delayMs);
|
|
85
|
+
|
|
86
|
+
return new ReadableStream<T>({
|
|
87
|
+
start(controller) {
|
|
88
|
+
controller.close();
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Helper function to create a stream with items having various delay times
|
|
94
|
+
async function createVariableDelayedNumberStream(
|
|
95
|
+
items: Array<{ value: number; delay: number }>,
|
|
96
|
+
): Promise<ReadableStream<number>> {
|
|
97
|
+
// Wait for all items to be ready based on their delays
|
|
98
|
+
await Promise.all(items.map(async item => delay(item.delay)));
|
|
99
|
+
|
|
100
|
+
return new ReadableStream<number>({
|
|
101
|
+
start(controller) {
|
|
102
|
+
for (const item of items) {
|
|
103
|
+
controller.enqueue(item.value);
|
|
104
|
+
}
|
|
105
|
+
controller.close();
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
describe("streamUtil", () => {
|
|
111
|
+
describe("readAll", () => {
|
|
112
|
+
it("should read all values from a stream", async () => {
|
|
113
|
+
const stream = createNumberStream(1, 5);
|
|
114
|
+
const result = await StreamUtil.readAll(stream);
|
|
115
|
+
|
|
116
|
+
expect(result).toEqual([1, 2, 3, 4, 5]);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it("should return empty array for empty stream", async () => {
|
|
120
|
+
const stream = createEmptyStream<number>();
|
|
121
|
+
const result = await StreamUtil.readAll(stream);
|
|
122
|
+
|
|
123
|
+
expect(result).toEqual([]);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it("should handle error in stream", async () => {
|
|
127
|
+
const stream = new ReadableStream<number>({
|
|
128
|
+
start(controller) {
|
|
129
|
+
controller.enqueue(1);
|
|
130
|
+
controller.enqueue(2);
|
|
131
|
+
controller.error(new Error("Stream error"));
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
await expect(StreamUtil.readAll(stream)).rejects.toThrow("Stream error");
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it("should handle null or undefined values in stream", async () => {
|
|
139
|
+
const stream = createTestStream<number | null | undefined>([1, null, 3, undefined, 5]);
|
|
140
|
+
|
|
141
|
+
const result = await StreamUtil.readAll(stream);
|
|
142
|
+
expect(result).toEqual([1, null, 3, undefined, 5]);
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
describe("reduce", () => {
|
|
147
|
+
it("should concatenate strings from number stream", async () => {
|
|
148
|
+
const stringStream = createNumberStream(1, 3);
|
|
149
|
+
const stringResult = await StreamUtil.reduce<number, string>(
|
|
150
|
+
stringStream,
|
|
151
|
+
(acc, cur) => acc + cur.toString(),
|
|
152
|
+
"",
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
expect(stringResult).toBe("123");
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it("should sum numbers from stream", async () => {
|
|
159
|
+
const sumStream = createNumberStream(1, 5);
|
|
160
|
+
const sumResult = await StreamUtil.reduce<number, number>(
|
|
161
|
+
sumStream,
|
|
162
|
+
(acc, cur) => acc + cur,
|
|
163
|
+
0,
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
expect(sumResult).toBe(15);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it("should work without initial value", async () => {
|
|
170
|
+
const noInitialStream = createNumberStream(1, 4);
|
|
171
|
+
const noInitialResult = await StreamUtil.reduce<number>(
|
|
172
|
+
noInitialStream,
|
|
173
|
+
(acc, cur) => acc + cur,
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
expect(noInitialResult).toBe(10);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it("should return initial value for empty stream", async () => {
|
|
180
|
+
const emptyStream = createEmptyStream<number>();
|
|
181
|
+
const emptyResult = await StreamUtil.reduce<number, string>(
|
|
182
|
+
emptyStream,
|
|
183
|
+
(acc, cur) => acc + cur.toString(),
|
|
184
|
+
"initial value",
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
expect(emptyResult).toBe("initial value");
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it("should return null for empty stream without initial value", async () => {
|
|
191
|
+
const emptyNoInitialStream = createEmptyStream<number>();
|
|
192
|
+
const emptyNoInitialResult = await StreamUtil.reduce<number>(
|
|
193
|
+
emptyNoInitialStream,
|
|
194
|
+
(acc, cur) => acc + cur,
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
expect(emptyNoInitialResult).toBeNull();
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it("should work with async generated stream", async () => {
|
|
201
|
+
const stringStream = await createDelayedNumberStream(1, 3, 10);
|
|
202
|
+
const stringResult = await StreamUtil.reduce<number, string>(
|
|
203
|
+
stringStream,
|
|
204
|
+
(acc, cur) => acc + cur.toString(),
|
|
205
|
+
"",
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
expect(stringResult).toBe("123");
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it("should work with async stream without initial value", async () => {
|
|
212
|
+
const noInitialStream = await createDelayedNumberStream(1, 4, 15);
|
|
213
|
+
const noInitialResult = await StreamUtil.reduce<number>(
|
|
214
|
+
noInitialStream,
|
|
215
|
+
(acc, cur) => acc + cur,
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
expect(noInitialResult).toBe(10);
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it("should work with async stream transformation and aggregation into array", async () => {
|
|
222
|
+
const transformStream = await createDelayedNumberStream(1, 3, 10);
|
|
223
|
+
const transformResult = await StreamUtil.reduce<number, string[]>(
|
|
224
|
+
transformStream,
|
|
225
|
+
(acc: string[] | number, cur: number): string[] => {
|
|
226
|
+
if (typeof acc === "number") {
|
|
227
|
+
// Handle case when no initial value is provided
|
|
228
|
+
return [`item${acc}`, `item${cur}`];
|
|
229
|
+
}
|
|
230
|
+
return [...acc, `item${cur}`];
|
|
231
|
+
},
|
|
232
|
+
[],
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
expect(transformResult).toEqual(["item1", "item2", "item3"]);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it("should return initial value for async generated empty stream", async () => {
|
|
239
|
+
const emptyStream = await createEmptyDelayedStream<number>(30);
|
|
240
|
+
const emptyResult = await StreamUtil.reduce<number, string>(
|
|
241
|
+
emptyStream,
|
|
242
|
+
(acc, cur) => acc + cur.toString(),
|
|
243
|
+
"initial",
|
|
244
|
+
);
|
|
245
|
+
|
|
246
|
+
expect(emptyResult).toBe("initial");
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
it("should work with stream with values created with various async delays", async () => {
|
|
250
|
+
const delayStream = await createVariableDelayedNumberStream([
|
|
251
|
+
{ value: 1, delay: 20 },
|
|
252
|
+
{ value: 2, delay: 40 },
|
|
253
|
+
{ value: 3, delay: 10 },
|
|
254
|
+
]);
|
|
255
|
+
|
|
256
|
+
const delayResult = await StreamUtil.reduce<number, number>(
|
|
257
|
+
delayStream,
|
|
258
|
+
(acc, cur) => acc + cur,
|
|
259
|
+
0,
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
expect(delayResult).toBe(6);
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
it("should handle error in reducer function", async () => {
|
|
266
|
+
const stream = createNumberStream(1, 3);
|
|
267
|
+
|
|
268
|
+
await expect(
|
|
269
|
+
StreamUtil.reduce<number, number>(
|
|
270
|
+
stream,
|
|
271
|
+
(acc, cur) => {
|
|
272
|
+
if (cur === 2) {
|
|
273
|
+
throw new Error("Test error");
|
|
274
|
+
}
|
|
275
|
+
return acc + cur;
|
|
276
|
+
},
|
|
277
|
+
0,
|
|
278
|
+
),
|
|
279
|
+
).rejects.toThrow("Test error");
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
it("should handle null or undefined values in stream", async () => {
|
|
283
|
+
const stream = createTestStream<number | null | undefined>([1, null, 3, undefined, 5]);
|
|
284
|
+
|
|
285
|
+
const result = await StreamUtil.reduce<number | null | undefined, number>(
|
|
286
|
+
stream,
|
|
287
|
+
(acc, cur) => (acc ?? 0) + (cur ?? 0),
|
|
288
|
+
0,
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
expect(result).toBe(9); // 1 + 0 + 3 + 0 + 5 = 9
|
|
292
|
+
});
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
describe("from", () => {
|
|
296
|
+
it("should create a stream with a single value", async () => {
|
|
297
|
+
const stream = StreamUtil.from("Hello, world!");
|
|
298
|
+
const reader = stream.getReader();
|
|
299
|
+
const { done, value } = await reader.read();
|
|
300
|
+
|
|
301
|
+
expect(done).toBe(false);
|
|
302
|
+
expect(value).toBe("Hello, world!");
|
|
303
|
+
|
|
304
|
+
const next = await reader.read();
|
|
305
|
+
expect(next.done).toBe(true);
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
it("should handle null or undefined values", async () => {
|
|
309
|
+
const stream = StreamUtil.from(null);
|
|
310
|
+
const reader = stream.getReader();
|
|
311
|
+
const { done, value } = await reader.read();
|
|
312
|
+
|
|
313
|
+
expect(done).toBe(false);
|
|
314
|
+
expect(value).toBeNull();
|
|
315
|
+
|
|
316
|
+
const next = await reader.read();
|
|
317
|
+
expect(next.done).toBe(true);
|
|
318
|
+
});
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
describe("transform", () => {
|
|
322
|
+
it("should transform number stream by doubling", async () => {
|
|
323
|
+
const numbersInput = [1, 2, 3, 4, 5];
|
|
324
|
+
const numberStream = createTestStream(numbersInput);
|
|
325
|
+
|
|
326
|
+
const doubledStream = StreamUtil.transform(
|
|
327
|
+
numberStream,
|
|
328
|
+
(num: number) => num * 2,
|
|
329
|
+
);
|
|
330
|
+
|
|
331
|
+
const doubledResult = await streamToArray(doubledStream);
|
|
332
|
+
const expectedDoubled = numbersInput.map(n => n * 2);
|
|
333
|
+
|
|
334
|
+
expect(doubledResult).toEqual(expectedDoubled);
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
it("should transform object stream", async () => {
|
|
338
|
+
const objectsInput = [
|
|
339
|
+
{ name: "item1", value: 10 },
|
|
340
|
+
{ name: "item2", value: 20 },
|
|
341
|
+
{ name: "item3", value: 30 },
|
|
342
|
+
];
|
|
343
|
+
|
|
344
|
+
const objectStream = createTestStream(objectsInput);
|
|
345
|
+
|
|
346
|
+
const transformedObjectStream = StreamUtil.transform(objectStream, obj => ({
|
|
347
|
+
id: obj.name.toUpperCase(),
|
|
348
|
+
doubledValue: obj.value * 2,
|
|
349
|
+
}));
|
|
350
|
+
|
|
351
|
+
const transformedObjects = await streamToArray(transformedObjectStream);
|
|
352
|
+
const expectedObjects = objectsInput.map(obj => ({
|
|
353
|
+
id: obj.name.toUpperCase(),
|
|
354
|
+
doubledValue: obj.value * 2,
|
|
355
|
+
}));
|
|
356
|
+
|
|
357
|
+
expect(transformedObjects).toEqual(expectedObjects);
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
it("should handle empty stream", async () => {
|
|
361
|
+
const emptyStream = createEmptyStream<number>();
|
|
362
|
+
const transformedEmptyStream = StreamUtil.transform(
|
|
363
|
+
emptyStream,
|
|
364
|
+
n => n * 2,
|
|
365
|
+
);
|
|
366
|
+
|
|
367
|
+
const emptyResult = await streamToArray(transformedEmptyStream);
|
|
368
|
+
|
|
369
|
+
expect(emptyResult).toEqual([]);
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
it("should transform type (number -> string)", async () => {
|
|
373
|
+
const numbersInput = [1, 2, 3, 4, 5];
|
|
374
|
+
const numberStream = createTestStream(numbersInput);
|
|
375
|
+
|
|
376
|
+
const stringStream = StreamUtil.transform(
|
|
377
|
+
numberStream,
|
|
378
|
+
num => `Number: ${num}`,
|
|
379
|
+
);
|
|
380
|
+
|
|
381
|
+
const stringResult = await streamToArray(stringStream);
|
|
382
|
+
const expectedStrings = numbersInput.map(n => `Number: ${n}`);
|
|
383
|
+
|
|
384
|
+
expect(stringResult).toEqual(expectedStrings);
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
it("should handle error in transformer function", async () => {
|
|
388
|
+
const stream = createNumberStream(1, 3);
|
|
389
|
+
|
|
390
|
+
const transformedStream = StreamUtil.transform(
|
|
391
|
+
stream,
|
|
392
|
+
(num) => {
|
|
393
|
+
if (num === 2) {
|
|
394
|
+
throw new Error("Transform error");
|
|
395
|
+
}
|
|
396
|
+
return num * 2;
|
|
397
|
+
},
|
|
398
|
+
);
|
|
399
|
+
|
|
400
|
+
await expect(streamToArray(transformedStream)).rejects.toThrow("Transform error");
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
it("should handle null or undefined values in stream", async () => {
|
|
404
|
+
const stream = createTestStream<number | null | undefined>([1, null, 3, undefined, 5]);
|
|
405
|
+
|
|
406
|
+
const transformedStream = StreamUtil.transform(
|
|
407
|
+
stream,
|
|
408
|
+
num => (num ?? 0) * 2,
|
|
409
|
+
);
|
|
410
|
+
|
|
411
|
+
const result = await streamToArray(transformedStream);
|
|
412
|
+
expect(result).toEqual([2, 0, 6, 0, 10]);
|
|
413
|
+
});
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
describe("toAsyncGenerator", () => {
|
|
417
|
+
it("should yield a single value", async () => {
|
|
418
|
+
const generator = toAsyncGenerator("test value");
|
|
419
|
+
const result = [];
|
|
420
|
+
|
|
421
|
+
for await (const value of generator) {
|
|
422
|
+
result.push(value);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
expect(result).toEqual(["test value"]);
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
it("should handle null or undefined values", async () => {
|
|
429
|
+
const generator = toAsyncGenerator(null);
|
|
430
|
+
const result = [];
|
|
431
|
+
|
|
432
|
+
for await (const value of generator) {
|
|
433
|
+
result.push(value);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
expect(result).toEqual([null]);
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
it("should handle object values", async () => {
|
|
440
|
+
const testObj = { id: 1, name: "test" };
|
|
441
|
+
const generator = toAsyncGenerator(testObj);
|
|
442
|
+
const result = [];
|
|
443
|
+
|
|
444
|
+
for await (const value of generator) {
|
|
445
|
+
result.push(value);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
expect(result).toEqual([testObj]);
|
|
449
|
+
});
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
describe("streamDefaultReaderToAsyncGenerator", () => {
|
|
453
|
+
it("should convert stream reader to async generator", async () => {
|
|
454
|
+
const stream = createNumberStream(1, 5);
|
|
455
|
+
const reader = stream.getReader();
|
|
456
|
+
const generator = streamDefaultReaderToAsyncGenerator(reader);
|
|
457
|
+
const result = [];
|
|
458
|
+
|
|
459
|
+
for await (const value of generator) {
|
|
460
|
+
result.push(value);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
expect(result).toEqual([1, 2, 3, 4, 5]);
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
it("should handle empty stream", async () => {
|
|
467
|
+
const stream = createEmptyStream<number>();
|
|
468
|
+
const reader = stream.getReader();
|
|
469
|
+
const generator = streamDefaultReaderToAsyncGenerator(reader);
|
|
470
|
+
const result = [];
|
|
471
|
+
|
|
472
|
+
for await (const value of generator) {
|
|
473
|
+
result.push(value);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
expect(result).toEqual([]);
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
it("should handle null or undefined values in stream", async () => {
|
|
480
|
+
const stream = createTestStream<number | null | undefined>([1, null, 3, undefined, 5]);
|
|
481
|
+
const reader = stream.getReader();
|
|
482
|
+
const generator = streamDefaultReaderToAsyncGenerator(reader);
|
|
483
|
+
const result = [];
|
|
484
|
+
|
|
485
|
+
for await (const value of generator) {
|
|
486
|
+
result.push(value);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
expect(result).toEqual([1, null, 3, undefined, 5]);
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
it("should handle error in stream", async () => {
|
|
493
|
+
const stream = new ReadableStream<number>({
|
|
494
|
+
start(controller) {
|
|
495
|
+
controller.enqueue(1);
|
|
496
|
+
controller.enqueue(2);
|
|
497
|
+
delay(1000).then(() => controller.error(new Error("Stream error"))).catch(() => {});
|
|
498
|
+
},
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
const reader = stream.getReader();
|
|
502
|
+
const generator = streamDefaultReaderToAsyncGenerator(reader);
|
|
503
|
+
const result = [];
|
|
504
|
+
|
|
505
|
+
try {
|
|
506
|
+
for await (const value of generator) {
|
|
507
|
+
result.push(value);
|
|
508
|
+
}
|
|
509
|
+
// Should not reach here
|
|
510
|
+
expect(true).toBe(false);
|
|
511
|
+
}
|
|
512
|
+
catch (error) {
|
|
513
|
+
console.error(error);
|
|
514
|
+
expect(error).toBeInstanceOf(Error);
|
|
515
|
+
expect((error as Error).message).toBe("Stream error");
|
|
516
|
+
expect(result).toEqual([1, 2]);
|
|
517
|
+
}
|
|
518
|
+
});
|
|
519
|
+
});
|
|
520
|
+
});
|