(url: string)
| 2 | import EventSource from "eventsource"; |
| 3 | |
| 4 | export function createEventStream(url: string): AsyncIterable<any> { |
| 5 | return { |
| 6 | async *[Symbol.asyncIterator]() { |
| 7 | const source = new EventSource(url, { withCredentials: true }); |
| 8 | let pullControl: (value: any) => void; |
| 9 | let pushValue: any | Promise<any> = new Promise(resolve => (pullControl = resolve)); |
| 10 | |
| 11 | const push = (value: any) => { |
| 12 | if (pullControl) { |
| 13 | pullControl(value); |
| 14 | pushValue = new Promise(resolve => (pullControl = resolve)); |
| 15 | } |
| 16 | }; |
| 17 | |
| 18 | source.addEventListener("output", e => { |
| 19 | push(e); |
| 20 | }); |
| 21 | |
| 22 | source.addEventListener("error", e => { |
| 23 | Sentry.captureException(e); |
| 24 | push({ |
| 25 | type: "error", |
| 26 | lastEventId: e.lastEventId, |
| 27 | data: e?.data || "Error in response stream", |
| 28 | }); |
| 29 | }); |
| 30 | |
| 31 | source.addEventListener("done", () => { |
| 32 | source.close(); |
| 33 | push(undefined); // Signal the iterator to finish |
| 34 | }); |
| 35 | |
| 36 | while (true) { |
| 37 | const value = await pushValue; |
| 38 | if (value === undefined) return; // If undefined is pushed, break out of the loop |
| 39 | if (value instanceof Error) throw value; // If an error is pushed, throw it |
| 40 | yield value; // Yield the event data |
| 41 | } |
| 42 | }, |
| 43 | }; |
| 44 | } |
no outgoing calls
no test coverage detected