MCPcopy Create free account
hub / github.com/composify-js/composify / Bridge

Class Bridge

packages/react/src/utils/Bridge/Bridge.ts:5–72  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

3export type BridgeEventHandler<Event extends BridgeEvent = BridgeEvent> = (event: Event) => void;
4
5export class Bridge {
6 private readonly target: Window;
7 private readonly origin: string;
8 private readonly abort = new AbortController();
9
10 private listeners = new Map<BridgeEventType, Set<BridgeEventHandler>>();
11
12 public constructor(target: Window, origin = '*') {
13 this.target = target;
14 this.origin = origin;
15
16 this.on = this.on.bind(this);
17 this.emit = this.emit.bind(this);
18 this.dispose = this.dispose.bind(this);
19 this.handle = this.handle.bind(this);
20
21 window.addEventListener('message', this.handle, {
22 signal: this.abort.signal,
23 });
24 }
25
26 public emit(event: BridgeEvent) {
27 this.target.postMessage(event, this.origin);
28 }
29
30 public on<EventType extends BridgeEventType>(
31 type: EventType,
32 listener: BridgeEventHandler<Extract<BridgeEvent, { type: EventType }>>,
33 ) {
34 const listeners = this.listeners.get(type) ?? new Set();
35
36 listeners.add(listener as BridgeEventHandler);
37 this.listeners.set(type, listeners);
38 }
39
40 public dispose() {
41 this.abort.abort();
42 this.listeners.forEach((listeners) => {
43 listeners.clear();
44 });
45 this.listeners.clear();
46 }
47
48 private handle(message: MessageEvent) {
49 if (message.source !== this.target) {
50 return;
51 }
52
53 if (this.origin !== '*' && message.origin !== this.origin) {
54 return;
55 }
56
57 if (!isBridgeEvent(message.data)) {
58 return;
59 }
60
61 const event = message.data;
62 const listeners = this.listeners.get(event.type);

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected