● Zion Boggan
repos/Drophawk/frontend/lib/sse.ts
zionboggan.com ↗
54 lines · typescript
History for this file →
1
 
2
import type { Drop, StreamEventName } from "./types";
3
 
4
const DROP_EVENTS: StreamEventName[] = [
5
  "drop.new",
6
  "drop.status",
7
  "drop.price",
8
  "drop.inventory",
9
  "drop.announcement",
10
];
11
 
12
export type StreamStatus = "connecting" | "open" | "closed";
13
 
14
export interface StreamHandlers {
15
  onDrop: (drop: Drop, eventName: StreamEventName) => void;
16
  onStatus: (status: StreamStatus) => void;
17
  onSourceHealth?: (payload: unknown) => void;
18
}
19
 
20
export function openDropStream(handlers: StreamHandlers): () => void {
21
  const es = new EventSource("/api/drops/stream");
22
 
23
  handlers.onStatus("connecting");
24
  es.onopen = () => handlers.onStatus("open");
25
  es.onerror = () => {
26
    handlers.onStatus(es.readyState === EventSource.CLOSED ? "closed" : "connecting");
27
  };
28
 
29
  const handleDrop = (name: StreamEventName) => (ev: MessageEvent<string>) => {
30
    try {
31
      const drop = JSON.parse(ev.data) as Drop;
32
      handlers.onDrop(drop, name);
33
    } catch {
34
    }
35
  };
36
 
37
  for (const name of DROP_EVENTS) {
38
    es.addEventListener(name, handleDrop(name) as EventListener);
39
  }
40
 
41
  if (handlers.onSourceHealth) {
42
    es.addEventListener("source.health", (ev) => {
43
      try {
44
        handlers.onSourceHealth?.(JSON.parse((ev as MessageEvent<string>).data));
45
      } catch {
46
      }
47
    });
48
  }
49
 
50
  return () => {
51
    es.close();
52
    handlers.onStatus("closed");
53
  };
54
}