@graphql-hive/pubsub
Version:
69 lines (66 loc) • 1.83 kB
JavaScript
import { Repeater } from '@repeaterjs/repeater';
import { DisposableSymbols } from '@whatwg-node/disposablestack';
import { fakePromise } from '@whatwg-node/promise-helpers';
class MemPubSub {
#disposed = false;
#subscribers = /* @__PURE__ */ new Map();
subscribedTopics() {
return this.#subscribers.keys();
}
publish(topic, data) {
if (this.#disposed) {
throw new Error("PubSub is disposed, cannot publish data");
}
const listeners = this.#subscribers.get(topic);
if (listeners) {
for (const l of listeners.keys()) {
l(data);
}
}
}
subscribe(topic, listener) {
if (this.#disposed) {
throw new Error("PubSub is disposed, cannot subscribe to topics");
}
let listeners = this.#subscribers.get(topic);
if (!listeners) {
listeners = /* @__PURE__ */ new Map();
this.#subscribers.set(topic, listeners);
}
if (!listener) {
return new Repeater((push, stop) => {
listeners.set(push, stop);
return stop.then(() => {
listeners.delete(push);
if (listeners.size === 0) {
this.#subscribers.delete(topic);
}
});
});
}
const listenerRef = new WeakRef(listener);
const unsubscribe = () => {
const l = listenerRef.deref();
if (l) listeners.delete(l);
if (listeners.size === 0) {
this.#subscribers.delete(topic);
}
};
listeners.set(listener, unsubscribe);
return unsubscribe;
}
dispose() {
this.#disposed = true;
for (const sub of this.#subscribers.values()) {
for (const stop of sub.values()) {
stop();
}
sub.clear();
}
this.#subscribers.clear();
}
[DisposableSymbols.asyncDispose]() {
return fakePromise(this.dispose());
}
}
export { MemPubSub };