Add relay package

This commit is contained in:
Jon Staab
2025-03-31 10:16:28 -07:00
parent 5245993d4e
commit cfd2e3aac7
21 changed files with 234 additions and 106 deletions
+1 -64
View File
@@ -1,15 +1,7 @@
import {last, Emitter, normalizeUrl, sleep, stripProtocol} from "@welshman/lib"
import {matchFilters} from "./Filters.js"
import type {Repository} from "./Repository.js"
import type {Filter} from "./Filters.js"
import type {HashedEvent, TrustedEvent} from "./Events.js"
import {last, normalizeUrl, stripProtocol} from "@welshman/lib"
// Constants and types
export const LOCAL_RELAY_URL = "local://welshman.relay/"
export const BOGUS_RELAY_URL = "bogus://welshman.relay/"
export type RelayProfile = {
url: string
icon?: string
@@ -83,58 +75,3 @@ export const displayRelayUrl = (url: string) => last(url.split("://")).replace(/
export const displayRelayProfile = (profile?: RelayProfile, fallback = "") =>
profile?.name || fallback
// In-memory relay implementation backed by Repository
export class Relay<E extends HashedEvent = TrustedEvent> extends Emitter {
subs = new Map<string, Filter[]>()
constructor(readonly repository: Repository<E>) {
super()
}
send(type: string, ...message: any[]) {
switch (type) {
case "EVENT":
return this.handleEVENT(message as [E])
case "CLOSE":
return this.handleCLOSE(message as [string])
case "REQ":
return this.handleREQ(message as [string, ...Filter[]])
}
}
handleEVENT([event]: [E]) {
this.repository.publish(event)
// Callers generally expect async relays
void sleep(1).then(() => {
this.emit("OK", event.id, true, "")
if (!this.repository.isDeleted(event)) {
for (const [subId, filters] of this.subs.entries()) {
if (matchFilters(filters, event)) {
this.emit("EVENT", subId, event)
}
}
}
})
}
handleCLOSE([subId]: [string]) {
this.subs.delete(subId)
}
handleREQ([subId, ...filters]: [string, ...Filter[]]) {
this.subs.set(subId, filters)
// Callers generally expect async relays
void sleep(1).then(() => {
for (const event of this.repository.query(filters)) {
this.emit("EVENT", subId, event)
}
this.emit("EOSE", subId)
})
}
}