@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  export async function* toAsyncIterable(nodeReadable) {
2
2
  for await (const chunk of nodeReadable) {
3
- // @ts-expect-error
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:")) {
@@ -1,6 +1,56 @@
1
- // The parseDataLine function is not exported, so we need to import it
2
- // indirectly by re-exporting it for testing purposes
3
- import { parseDataLine } from "./stream.js";
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@continuedev/fetch",
3
- "version": "1.0.9",
3
+ "version": "1.0.10",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,6 +1,66 @@
1
- // The parseDataLine function is not exported, so we need to import it
2
- // indirectly by re-exporting it for testing purposes
3
- import { parseDataLine } from "./stream.js";
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-expect-error
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
@@ -19,5 +19,5 @@
19
19
  "declaration": true
20
20
  // "sourceMap": true
21
21
  },
22
- "include": ["src/**/*"]
22
+ "include": ["src/**/*", "jest.globals.d.ts"]
23
23
  }