Skip to content

Commit c85dc97

Browse files
chore(internal): minor restructuring (#1278)
1 parent a1d0ddc commit c85dc97

File tree

3 files changed

+36
-36
lines changed

3 files changed

+36
-36
lines changed

Diff for: src/internal/decoders/line.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { OpenAIError } from '../../error';
22

3-
type Bytes = string | ArrayBuffer | Uint8Array | Buffer | null | undefined;
3+
export type Bytes = string | ArrayBuffer | Uint8Array | Buffer | null | undefined;
44

55
/**
66
* A re-implementation of httpx's `LineDecoder` in Python that handles incrementally

Diff for: src/internal/stream-utils.ts

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/**
2+
* Most browsers don't yet have async iterable support for ReadableStream,
3+
* and Node has a very different way of reading bytes from its "ReadableStream".
4+
*
5+
* This polyfill was pulled from https://github.com/MattiasBuelens/web-streams-polyfill/pull/122#issuecomment-1627354490
6+
*/
7+
export function ReadableStreamToAsyncIterable<T>(stream: any): AsyncIterableIterator<T> {
8+
if (stream[Symbol.asyncIterator]) return stream;
9+
10+
const reader = stream.getReader();
11+
return {
12+
async next() {
13+
try {
14+
const result = await reader.read();
15+
if (result?.done) reader.releaseLock(); // release lock when stream becomes closed
16+
return result;
17+
} catch (e) {
18+
reader.releaseLock(); // release lock when stream becomes errored
19+
throw e;
20+
}
21+
},
22+
async return() {
23+
const cancelPromise = reader.cancel();
24+
reader.releaseLock();
25+
await cancelPromise;
26+
return { done: true, value: undefined };
27+
},
28+
[Symbol.asyncIterator]() {
29+
return this;
30+
},
31+
};
32+
}

Diff for: src/streaming.ts

+3-35
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { ReadableStream, type Response } from './_shims/index';
22
import { OpenAIError } from './error';
33
import { LineDecoder } from './internal/decoders/line';
4+
import { ReadableStreamToAsyncIterable } from './internal/stream-utils';
45

56
import { APIError } from './error';
67

@@ -96,7 +97,7 @@ export class Stream<Item> implements AsyncIterable<Item> {
9697
async function* iterLines(): AsyncGenerator<string, void, unknown> {
9798
const lineDecoder = new LineDecoder();
9899

99-
const iter = readableStreamAsyncIterable<Bytes>(readableStream);
100+
const iter = ReadableStreamToAsyncIterable<Bytes>(readableStream);
100101
for await (const chunk of iter) {
101102
for (const line of lineDecoder.decode(chunk)) {
102103
yield line;
@@ -210,7 +211,7 @@ export async function* _iterSSEMessages(
210211
const sseDecoder = new SSEDecoder();
211212
const lineDecoder = new LineDecoder();
212213

213-
const iter = readableStreamAsyncIterable<Bytes>(response.body);
214+
const iter = ReadableStreamToAsyncIterable<Bytes>(response.body);
214215
for await (const sseChunk of iterSSEChunks(iter)) {
215216
for (const line of lineDecoder.decode(sseChunk)) {
216217
const sse = sseDecoder.decode(line);
@@ -363,36 +364,3 @@ function partition(str: string, delimiter: string): [string, string, string] {
363364

364365
return [str, '', ''];
365366
}
366-
367-
/**
368-
* Most browsers don't yet have async iterable support for ReadableStream,
369-
* and Node has a very different way of reading bytes from its "ReadableStream".
370-
*
371-
* This polyfill was pulled from https://github.com/MattiasBuelens/web-streams-polyfill/pull/122#issuecomment-1627354490
372-
*/
373-
export function readableStreamAsyncIterable<T>(stream: any): AsyncIterableIterator<T> {
374-
if (stream[Symbol.asyncIterator]) return stream;
375-
376-
const reader = stream.getReader();
377-
return {
378-
async next() {
379-
try {
380-
const result = await reader.read();
381-
if (result?.done) reader.releaseLock(); // release lock when stream becomes closed
382-
return result;
383-
} catch (e) {
384-
reader.releaseLock(); // release lock when stream becomes errored
385-
throw e;
386-
}
387-
},
388-
async return() {
389-
const cancelPromise = reader.cancel();
390-
reader.releaseLock();
391-
await cancelPromise;
392-
return { done: true, value: undefined };
393-
},
394-
[Symbol.asyncIterator]() {
395-
return this;
396-
},
397-
};
398-
}

0 commit comments

Comments
 (0)