ditto/src/subs.ts

80 lines
1.7 KiB
TypeScript
Raw Normal View History

2023-08-24 20:28:13 +00:00
import { type Event } from '@/deps.ts';
import { Subscription } from '@/subscription.ts';
2023-08-24 04:25:38 +00:00
2023-08-24 22:00:08 +00:00
import type { DittoFilter, EventData } from '@/types.ts';
2023-08-24 04:25:38 +00:00
/**
* Manages Ditto event subscriptions.
* Subscriptions can be added, removed, and matched against events.
*/
class SubscriptionStore {
#store = new Map<WebSocket, Map<string, Subscription>>();
/**
* Add a subscription to the store, and then iterate over it.
*
* ```ts
* for (const event of Sub.sub(socket, subId, filters)) {
* console.log(event);
* }
* ```
*/
sub(socket: WebSocket, id: string, filters: DittoFilter[]): Subscription {
let subs = this.#store.get(socket);
2023-08-24 04:25:38 +00:00
if (!subs) {
subs = new Map();
this.#store.set(socket, subs);
2023-08-24 04:25:38 +00:00
}
const sub = new Subscription(filters);
this.unsub(socket, id);
subs.set(id, sub);
return sub;
2023-08-24 04:25:38 +00:00
}
/** Remove a subscription from the store. */
unsub(socket: WebSocket, id: string): void {
this.#store.get(socket)?.get(id)?.close();
this.#store.get(socket)?.delete(id);
2023-08-24 04:25:38 +00:00
}
/** Remove an entire socket. */
close(socket: WebSocket): void {
const subs = this.#store.get(socket);
if (subs) {
for (const sub of subs.values()) {
sub.close();
}
}
2023-08-24 04:25:38 +00:00
this.#store.delete(socket);
}
/**
* Loop through matching subscriptions to stream out.
*
* ```ts
* for (const sub of Sub.matches(event, data)) {
* sub.stream(event);
2023-08-24 04:25:38 +00:00
* }
* ```
*/
2023-08-24 22:00:08 +00:00
*matches(event: Event, data: EventData): Iterable<Subscription> {
2023-08-24 04:25:38 +00:00
for (const subs of this.#store.values()) {
for (const sub of subs.values()) {
if (sub.matches(event, data)) {
2023-08-24 04:25:38 +00:00
yield sub;
}
}
}
}
}
const Sub = new SubscriptionStore();
export { Sub };