From 1a2e4a834327869e56aa315ff06c007bd650e701 Mon Sep 17 00:00:00 2001
From: Guillaume FORTAINE <guillaume+github@fortaine.com>
Date: Sun, 5 Mar 2023 23:49:09 +0100
Subject: [PATCH] chore(upgrade): add streamCompletion helper function (credits
 to @schnerd & @rauschma)

---
 config-node.yaml                              |  5 +++-
 .../typescript-axios/stream.mustache          | 29 +++++++++++++++++++
 2 files changed, 33 insertions(+), 1 deletion(-)
 create mode 100644 sdk-template-overrides/typescript-axios/stream.mustache

diff --git a/config-node.yaml b/config-node.yaml
index 613c4dd3..316893db 100644
--- a/config-node.yaml
+++ b/config-node.yaml
@@ -6,4 +6,7 @@ additionalProperties:
 files:
   tsc-multi.mustache:
     templateType: SupportingFiles
-    destinationFilename: tsc-multi.json
\ No newline at end of file
+    destinationFilename: tsc-multi.json
+  stream.mustache:
+    templateType: SupportingFiles
+    destinationFilename: stream.ts
\ No newline at end of file
diff --git a/sdk-template-overrides/typescript-axios/stream.mustache b/sdk-template-overrides/typescript-axios/stream.mustache
new file mode 100644
index 00000000..8b200cd4
--- /dev/null
+++ b/sdk-template-overrides/typescript-axios/stream.mustache
@@ -0,0 +1,29 @@
+import { Readable } from 'node:stream';
+
+async function* chunksToLines(chunksAsync: AsyncIterable<Buffer>): AsyncIterable<string> {
+  let previous = "";
+  for await (const chunk of chunksAsync) {
+    const bufferChunk = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
+    previous += bufferChunk;
+    let eolIndex;
+    while ((eolIndex = previous.indexOf("\n")) >= 0) {
+      // line includes the EOL
+      const line = previous.slice(0, eolIndex + 1).trimEnd();
+      if (line === "data: [DONE]") break;
+      if (line.startsWith("data: ")) yield line;
+      previous = previous.slice(eolIndex + 1);
+    }
+  }
+}
+
+async function* linesToMessages(linesAsync: AsyncIterable<string>): AsyncIterable<string> {
+  for await (const line of linesAsync) {
+    const message = line.substring("data :".length);
+
+    yield message;
+  }
+}
+
+export async function* streamCompletion(stream: Readable): AsyncGenerator<string, void, undefined> {
+  yield* linesToMessages(chunksToLines(stream));
+}
\ No newline at end of file