@continuedev/fetch 1.0.9 → 1.0.10
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/dist/stream.js +2 -2
- package/dist/stream.test.js +53 -3
- package/jest.globals.d.ts +14 -0
- package/package.json +1 -1
- package/src/stream.test.ts +63 -3
- package/src/stream.ts +3 -2
- package/tsconfig.json +1 -1
package/dist/stream.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export async function* toAsyncIterable(nodeReadable) {
|
|
2
2
|
for await (const chunk of nodeReadable) {
|
|
3
|
-
// @ts-
|
|
3
|
+
// @ts-ignore
|
|
4
4
|
yield chunk;
|
|
5
5
|
}
|
|
6
6
|
}
|
|
@@ -64,7 +64,7 @@ export function parseDataLine(line) {
|
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
function parseSseLine(line) {
|
|
67
|
-
if (line.startsWith("data: [DONE]")) {
|
|
67
|
+
if (line.startsWith("data:[DONE]") || line.startsWith("data: [DONE]")) {
|
|
68
68
|
return { done: true, data: undefined };
|
|
69
69
|
}
|
|
70
70
|
if (line.startsWith("data:")) {
|
package/dist/stream.test.js
CHANGED
|
@@ -1,6 +1,56 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { Readable } from "stream";
|
|
2
|
+
import { parseDataLine, streamSse } from "./stream.js";
|
|
3
|
+
function createMockResponse(sseLines) {
|
|
4
|
+
// Create a Readable stream that emits the SSE lines
|
|
5
|
+
const stream = new Readable({
|
|
6
|
+
read() {
|
|
7
|
+
for (const line of sseLines) {
|
|
8
|
+
this.push(line + "\n\n");
|
|
9
|
+
}
|
|
10
|
+
this.push(null); // End of stream
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
// Minimal Response mock
|
|
14
|
+
return {
|
|
15
|
+
status: 200,
|
|
16
|
+
body: stream,
|
|
17
|
+
text: async () => "",
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
describe("streamSse", () => {
|
|
21
|
+
it("yields parsed SSE data objects that ends with `data:[DONE]`", async () => {
|
|
22
|
+
const sseLines = [
|
|
23
|
+
'data: {"foo": "bar"}',
|
|
24
|
+
'data: {"baz": 42}',
|
|
25
|
+
"data:[DONE]",
|
|
26
|
+
];
|
|
27
|
+
const response = createMockResponse(sseLines);
|
|
28
|
+
const results = [];
|
|
29
|
+
for await (const data of streamSse(response)) {
|
|
30
|
+
results.push(data);
|
|
31
|
+
}
|
|
32
|
+
expect(results).toEqual([{ foo: "bar" }, { baz: 42 }]);
|
|
33
|
+
});
|
|
34
|
+
it("yields parsed SSE data objects that ends with `data: [DONE]` (with a space before [DONE]", async () => {
|
|
35
|
+
const sseLines = [
|
|
36
|
+
'data: {"foo": "bar"}',
|
|
37
|
+
'data: {"baz": 42}',
|
|
38
|
+
"data: [DONE]",
|
|
39
|
+
];
|
|
40
|
+
const response = createMockResponse(sseLines);
|
|
41
|
+
const results = [];
|
|
42
|
+
for await (const data of streamSse(response)) {
|
|
43
|
+
results.push(data);
|
|
44
|
+
}
|
|
45
|
+
expect(results).toEqual([{ foo: "bar" }, { baz: 42 }]);
|
|
46
|
+
});
|
|
47
|
+
it("throws on malformed JSON", async () => {
|
|
48
|
+
const sseLines = ['data: {"foo": "bar"', "data:[DONE]"];
|
|
49
|
+
const response = createMockResponse(sseLines);
|
|
50
|
+
const iterator = streamSse(response)[Symbol.asyncIterator]();
|
|
51
|
+
await expect(iterator.next()).rejects.toThrow(/Malformed JSON/);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
4
54
|
describe("parseDataLine", () => {
|
|
5
55
|
test("parseDataLine should parse valid JSON data with 'data: ' prefix", () => {
|
|
6
56
|
const line = 'data: {"message":"hello","status":"ok"}';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// This file declares the Jest globals for TypeScript
|
|
2
|
+
import '@jest/globals';
|
|
3
|
+
|
|
4
|
+
declare global {
|
|
5
|
+
const describe: typeof import('@jest/globals').describe;
|
|
6
|
+
const expect: typeof import('@jest/globals').expect;
|
|
7
|
+
const it: typeof import('@jest/globals').it;
|
|
8
|
+
const test: typeof import('@jest/globals').test;
|
|
9
|
+
const beforeAll: typeof import('@jest/globals').beforeAll;
|
|
10
|
+
const afterAll: typeof import('@jest/globals').afterAll;
|
|
11
|
+
const beforeEach: typeof import('@jest/globals').beforeEach;
|
|
12
|
+
const afterEach: typeof import('@jest/globals').afterEach;
|
|
13
|
+
const jest: typeof import('@jest/globals').jest;
|
|
14
|
+
}
|
package/package.json
CHANGED
package/src/stream.test.ts
CHANGED
|
@@ -1,6 +1,66 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { Readable } from "stream";
|
|
2
|
+
import { parseDataLine, streamSse } from "./stream.js";
|
|
3
|
+
|
|
4
|
+
function createMockResponse(sseLines: string[]): Response {
|
|
5
|
+
// Create a Readable stream that emits the SSE lines
|
|
6
|
+
const stream = new Readable({
|
|
7
|
+
read() {
|
|
8
|
+
for (const line of sseLines) {
|
|
9
|
+
this.push(line + "\n\n");
|
|
10
|
+
}
|
|
11
|
+
this.push(null); // End of stream
|
|
12
|
+
},
|
|
13
|
+
}) as any;
|
|
14
|
+
|
|
15
|
+
// Minimal Response mock
|
|
16
|
+
return {
|
|
17
|
+
status: 200,
|
|
18
|
+
body: stream,
|
|
19
|
+
text: async () => "",
|
|
20
|
+
} as unknown as Response;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
describe("streamSse", () => {
|
|
24
|
+
it("yields parsed SSE data objects that ends with `data:[DONE]`", async () => {
|
|
25
|
+
const sseLines = [
|
|
26
|
+
'data: {"foo": "bar"}',
|
|
27
|
+
'data: {"baz": 42}',
|
|
28
|
+
"data:[DONE]",
|
|
29
|
+
];
|
|
30
|
+
const response = createMockResponse(sseLines);
|
|
31
|
+
|
|
32
|
+
const results = [];
|
|
33
|
+
for await (const data of streamSse(response)) {
|
|
34
|
+
results.push(data);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
expect(results).toEqual([{ foo: "bar" }, { baz: 42 }]);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("yields parsed SSE data objects that ends with `data: [DONE]` (with a space before [DONE]", async () => {
|
|
41
|
+
const sseLines = [
|
|
42
|
+
'data: {"foo": "bar"}',
|
|
43
|
+
'data: {"baz": 42}',
|
|
44
|
+
"data: [DONE]",
|
|
45
|
+
];
|
|
46
|
+
const response = createMockResponse(sseLines);
|
|
47
|
+
|
|
48
|
+
const results = [];
|
|
49
|
+
for await (const data of streamSse(response)) {
|
|
50
|
+
results.push(data);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
expect(results).toEqual([{ foo: "bar" }, { baz: 42 }]);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("throws on malformed JSON", async () => {
|
|
57
|
+
const sseLines = ['data: {"foo": "bar"', "data:[DONE]"];
|
|
58
|
+
const response = createMockResponse(sseLines);
|
|
59
|
+
|
|
60
|
+
const iterator = streamSse(response)[Symbol.asyncIterator]();
|
|
61
|
+
await expect(iterator.next()).rejects.toThrow(/Malformed JSON/);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
4
64
|
|
|
5
65
|
describe("parseDataLine", () => {
|
|
6
66
|
test("parseDataLine should parse valid JSON data with 'data: ' prefix", () => {
|
package/src/stream.ts
CHANGED
|
@@ -2,7 +2,7 @@ export async function* toAsyncIterable(
|
|
|
2
2
|
nodeReadable: NodeJS.ReadableStream,
|
|
3
3
|
): AsyncGenerator<Uint8Array> {
|
|
4
4
|
for await (const chunk of nodeReadable) {
|
|
5
|
-
// @ts-
|
|
5
|
+
// @ts-ignore
|
|
6
6
|
yield chunk as Uint8Array;
|
|
7
7
|
}
|
|
8
8
|
}
|
|
@@ -13,6 +13,7 @@ export async function* streamResponse(
|
|
|
13
13
|
if (response.status === 499) {
|
|
14
14
|
return; // In case of client-side cancellation, just return
|
|
15
15
|
}
|
|
16
|
+
|
|
16
17
|
if (response.status !== 200) {
|
|
17
18
|
throw new Error(await response.text());
|
|
18
19
|
}
|
|
@@ -77,7 +78,7 @@ export function parseDataLine(line: string): any {
|
|
|
77
78
|
}
|
|
78
79
|
|
|
79
80
|
function parseSseLine(line: string): { done: boolean; data: any } {
|
|
80
|
-
if (line.startsWith("data: [DONE]")) {
|
|
81
|
+
if (line.startsWith("data:[DONE]") || line.startsWith("data: [DONE]")) {
|
|
81
82
|
return { done: true, data: undefined };
|
|
82
83
|
}
|
|
83
84
|
if (line.startsWith("data:")) {
|
package/tsconfig.json
CHANGED