1+ import { AxiosInstance } from "axios"
12import { spawn } from "child_process"
23import { Api } from "coder/site/src/api/api"
34import { ProvisionerJobLog , Workspace } from "coder/site/src/api/typesGenerated"
5+ import { FetchLikeInit } from "eventsource"
46import fs from "fs/promises"
57import { ProxyAgent } from "proxy-agent"
68import * as vscode from "vscode"
@@ -120,6 +122,60 @@ export async function makeCoderSdk(baseUrl: string, token: string | undefined, s
120122 return restClient
121123}
122124
125+ /**
126+ * Creates a fetch adapter using an Axios instance that returns streaming responses.
127+ * This can be used with APIs that accept fetch-like interfaces.
128+ */
129+ export function createStreamingFetchAdapter ( axiosInstance : AxiosInstance ) {
130+ return async ( url : string | URL , init ?: FetchLikeInit ) => {
131+ const urlStr = url . toString ( )
132+
133+ const response = await axiosInstance . request ( {
134+ url : urlStr ,
135+ headers : init ?. headers as Record < string , string > ,
136+ responseType : "stream" ,
137+ validateStatus : ( ) => true , // Don't throw on any status code
138+ } )
139+ const stream = new ReadableStream ( {
140+ start ( controller ) {
141+ response . data . on ( "data" , ( chunk : Buffer ) => {
142+ controller . enqueue ( chunk )
143+ } )
144+
145+ response . data . on ( "end" , ( ) => {
146+ controller . close ( )
147+ } )
148+
149+ response . data . on ( "error" , ( err : Error ) => {
150+ controller . error ( err )
151+ } )
152+ } ,
153+
154+ cancel ( ) {
155+ response . data . destroy ( )
156+ return Promise . resolve ( )
157+ } ,
158+ } )
159+
160+ const createReader = ( ) => stream . getReader ( )
161+
162+ return {
163+ body : {
164+ getReader : ( ) => createReader ( ) ,
165+ } ,
166+ url : urlStr ,
167+ status : response . status ,
168+ redirected : response . request . res . responseUrl !== urlStr ,
169+ headers : {
170+ get : ( name : string ) => {
171+ const value = response . headers [ name . toLowerCase ( ) ]
172+ return value === undefined ? null : String ( value )
173+ } ,
174+ } ,
175+ }
176+ }
177+ }
178+
123179/**
124180 * Start or update a workspace and return the updated workspace.
125181 */
@@ -212,6 +268,7 @@ export async function waitForBuild(
212268 path += `&after=${ logs [ logs . length - 1 ] . id } `
213269 }
214270
271+ const agent = await createHttpAgent ( )
215272 await new Promise < void > ( ( resolve , reject ) => {
216273 try {
217274 const baseUrl = new URL ( baseUrlRaw )
@@ -224,6 +281,7 @@ export async function waitForBuild(
224281 | undefined ,
225282 } ,
226283 followRedirects : true ,
284+ agent : agent ,
227285 } )
228286 socket . binaryType = "nodebuffer"
229287 socket . on ( "message" , ( data ) => {
0 commit comments