Skip to content

Commit c3a7781

Browse files
chore(internal): minor restructuring (#1278)
1 parent e751614 commit c3a7781

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

@@ -80,7 +81,7 @@ export class Stream<Item> implements AsyncIterable<Item> {
8081
async function* iterLines(): AsyncGenerator<string, void, unknown> {
8182
const lineDecoder = new LineDecoder();
8283

83-
const iter = readableStreamAsyncIterable<Bytes>(readableStream);
84+
const iter = ReadableStreamToAsyncIterable<Bytes>(readableStream);
8485
for await (const chunk of iter) {
8586
for (const line of lineDecoder.decode(chunk)) {
8687
yield line;
@@ -194,7 +195,7 @@ export async function* _iterSSEMessages(
194195
const sseDecoder = new SSEDecoder();
195196
const lineDecoder = new LineDecoder();
196197

197-
const iter = readableStreamAsyncIterable<Bytes>(response.body);
198+
const iter = ReadableStreamToAsyncIterable<Bytes>(response.body);
198199
for await (const sseChunk of iterSSEChunks(iter)) {
199200
for (const line of lineDecoder.decode(sseChunk)) {
200201
const sse = sseDecoder.decode(line);
@@ -347,36 +348,3 @@ function partition(str: string, delimiter: string): [string, string, string] {
347348

348349
return [str, '', ''];
349350
}
350-
351-
/**
352-
* Most browsers don't yet have async iterable support for ReadableStream,
353-
* and Node has a very different way of reading bytes from its "ReadableStream".
354-
*
355-
* This polyfill was pulled from https://github.com/MattiasBuelens/web-streams-polyfill/pull/122#issuecomment-1627354490
356-
*/
357-
export function readableStreamAsyncIterable<T>(stream: any): AsyncIterableIterator<T> {
358-
if (stream[Symbol.asyncIterator]) return stream;
359-
360-
const reader = stream.getReader();
361-
return {
362-
async next() {
363-
try {
364-
const result = await reader.read();
365-
if (result?.done) reader.releaseLock(); // release lock when stream becomes closed
366-
return result;
367-
} catch (e) {
368-
reader.releaseLock(); // release lock when stream becomes errored
369-
throw e;
370-
}
371-
},
372-
async return() {
373-
const cancelPromise = reader.cancel();
374-
reader.releaseLock();
375-
await cancelPromise;
376-
return { done: true, value: undefined };
377-
},
378-
[Symbol.asyncIterator]() {
379-
return this;
380-
},
381-
};
382-
}

0 commit comments

Comments
 (0)