| 190 | } |
| 191 | |
| 192 | const sse = <A>(descriptor: RequestDescriptor, requestOptions?: RequestOptions): AsyncIterable<A> => ({ |
| 193 | async *[Symbol.asyncIterator]() { |
| 194 | const response = await execute(descriptor, requestOptions) |
| 195 | if (response.status !== descriptor.successStatus) await responseError(response, descriptor) |
| 196 | if (!isContentType(response, "text/event-stream")) { |
| 197 | try { |
| 198 | await response.body?.cancel() |
| 199 | } catch {} |
| 200 | throw new ClientError("UnsupportedContentType") |
| 201 | } |
| 202 | if (response.body === null) throw new ClientError("MalformedResponse") |
| 203 | const reader = response.body.getReader() |
| 204 | const decoder = new TextDecoder() |
| 205 | let buffer = "" |
| 206 | try { |
| 207 | while (true) { |
| 208 | let next |
| 209 | try { |
| 210 | next = await reader.read() |
| 211 | } catch (cause) { |
| 212 | throw new ClientError("Transport", { cause }) |
| 213 | } |
| 214 | buffer += decoder.decode(next.value, { stream: !next.done }) |
| 215 | if (buffer.length > 1_048_576) throw new ClientError("MalformedResponse") |
| 216 | const trailingCarriageReturn = !next.done && buffer.endsWith("\r") |
| 217 | if (trailingCarriageReturn) buffer = buffer.slice(0, -1) |
| 218 | buffer = buffer.replaceAll("\r\n", "\n").replaceAll("\r", "\n") |
| 219 | if (trailingCarriageReturn) buffer += "\r" |
| 220 | if (next.done && buffer !== "") buffer += "\n\n" |
| 221 | let boundary = buffer.indexOf("\n\n") |
| 222 | while (boundary >= 0) { |
| 223 | const block = buffer.slice(0, boundary) |
| 224 | buffer = buffer.slice(boundary + 2) |
| 225 | const data = block |
| 226 | .split("\n") |
| 227 | .flatMap((line) => (line.startsWith("data:") ? [line.slice(5).trimStart()] : [])) |
| 228 | .join("\n") |
| 229 | if (data !== "") { |
| 230 | try { |
| 231 | yield JSON.parse(data) as A |
| 232 | } catch (cause) { |
| 233 | throw new ClientError("MalformedResponse", { cause }) |
| 234 | } |
| 235 | } |
| 236 | boundary = buffer.indexOf("\n\n") |
| 237 | } |
| 238 | if (next.done) return |
| 239 | } |
| 240 | } finally { |
| 241 | try { |
| 242 | await reader.cancel() |
| 243 | } catch {} |
| 244 | reader.releaseLock() |
| 245 | } |
| 246 | }, |
| 247 | }) |
| 248 | |
| 249 | return { |