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"
@@ -90,6 +92,58 @@ export async function makeCoderSdk(baseUrl: string, token: string | undefined, s
9092 return restClient
9193}
9294
95+ /**
96+ * Creates a fetch adapter using an Axios instance that returns streaming responses.
97+ * This can be used with APIs that accept fetch-like interfaces.
98+ */
99+ export function createStreamingFetchAdapter ( axiosInstance : AxiosInstance ) {
100+ return async ( url : string | URL , init ?: FetchLikeInit ) => {
101+ const urlStr = url . toString ( )
102+
103+ const response = await axiosInstance . request ( {
104+ url : urlStr ,
105+ headers : init ?. headers as Record < string , string > ,
106+ responseType : "stream" ,
107+ validateStatus : ( ) => true , // Don't throw on any status code
108+ } )
109+ const stream = new ReadableStream ( {
110+ start ( controller ) {
111+ response . data . on ( "data" , ( chunk : Buffer ) => {
112+ controller . enqueue ( chunk )
113+ } )
114+
115+ response . data . on ( "end" , ( ) => {
116+ controller . close ( )
117+ } )
118+
119+ response . data . on ( "error" , ( err : Error ) => {
120+ controller . error ( err )
121+ } )
122+ } ,
123+
124+ cancel ( ) {
125+ response . data . destroy ( )
126+ return Promise . resolve ( )
127+ } ,
128+ } )
129+
130+ return {
131+ body : {
132+ getReader : ( ) => stream . getReader ( ) ,
133+ } ,
134+ url : urlStr ,
135+ status : response . status ,
136+ redirected : response . request . res . responseUrl !== urlStr ,
137+ headers : {
138+ get : ( name : string ) => {
139+ const value = response . headers [ name . toLowerCase ( ) ]
140+ return value === undefined ? null : String ( value )
141+ } ,
142+ } ,
143+ }
144+ }
145+ }
146+
93147/**
94148 * Start or update a workspace and return the updated workspace.
95149 */
@@ -182,6 +236,7 @@ export async function waitForBuild(
182236 path += `&after=${ logs [ logs . length - 1 ] . id } `
183237 }
184238
239+ const agent = await createHttpAgent ( )
185240 await new Promise < void > ( ( resolve , reject ) => {
186241 try {
187242 const baseUrl = new URL ( baseUrlRaw )
@@ -194,6 +249,7 @@ export async function waitForBuild(
194249 | undefined ,
195250 } ,
196251 followRedirects : true ,
252+ agent : agent ,
197253 } )
198254 socket . binaryType = "nodebuffer"
199255 socket . on ( "message" , ( data ) => {
0 commit comments