Add relay package
This commit is contained in:
+2
-2
@@ -12,7 +12,7 @@ for downstream in $(./get_packages.py); do
|
|||||||
|
|
||||||
if [[ ! -z $v ]]; then
|
if [[ ! -z $v ]]; then
|
||||||
mkdir -p packages/$downstream/node_modules/@welshman/$upstream
|
mkdir -p packages/$downstream/node_modules/@welshman/$upstream
|
||||||
cp -r packages/$upstream/build packages/$downstream/node_modules/@welshman/$upstream > /dev/null 2>&1
|
cp -r packages/$upstream/* packages/$downstream/node_modules/@welshman/$upstream > /dev/null 2>&1
|
||||||
cp -r packages/$upstream/build node_modules/@welshman/$upstream > /dev/null 2>&1
|
cp -r packages/$upstream/* node_modules/@welshman/$upstream > /dev/null 2>&1
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import {throttle} from "@welshman/lib"
|
import {throttle} from "@welshman/lib"
|
||||||
import {Repository, Relay} from "@welshman/util"
|
import {Repository, Relay} from "@welshman/util"
|
||||||
import type {TrustedEvent} from "@welshman/util"
|
|
||||||
import {Tracker} from "@welshman/net"
|
import {Tracker} from "@welshman/net"
|
||||||
import {custom} from "@welshman/store"
|
import {custom} from "@welshman/store"
|
||||||
|
|
||||||
export const repository = new Repository<TrustedEvent>()
|
export const repository = Repository.getSingleton()
|
||||||
|
|
||||||
export const relay = new Relay(repository)
|
export const relay = new Relay(repository)
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,9 @@ export const pull = async ({relays, filters}: AppSyncOpts) => {
|
|||||||
relays.map(async relay => {
|
relays.map(async relay => {
|
||||||
await (hasNegentropy(relay)
|
await (hasNegentropy(relay)
|
||||||
? basePull({filters, events, relays: [relay]})
|
? basePull({filters, events, relays: [relay]})
|
||||||
: pullWithoutNegentropy({filters, relays: [relay]}))
|
: new Promise(resolve => {
|
||||||
|
new SingleRequest({filters, relay, closeOnEose: true}).on(RequestEvent.Close, resolve)
|
||||||
|
})
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -47,19 +49,10 @@ export const push = async ({relays, filters}: AppSyncOpts) => {
|
|||||||
relays.map(async relay => {
|
relays.map(async relay => {
|
||||||
await (hasNegentropy(relay)
|
await (hasNegentropy(relay)
|
||||||
? basePush({filters, events, relays: [relay]})
|
? basePush({filters, events, relays: [relay]})
|
||||||
: pushWithoutNegentropy({events, relays: [relay]}))
|
: new Promise(resolve => {
|
||||||
|
new SinglePublish({events, relay}).on(PublishEvent.Complete, resolve)
|
||||||
|
}))
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
export const sync = async ({relays, filters}: AppSyncOpts) => {
|
|
||||||
const events = query(filters).filter(isSignedEvent)
|
|
||||||
|
|
||||||
await Promise.all(
|
|
||||||
relays.map(async relay => {
|
|
||||||
await (hasNegentropy(relay)
|
|
||||||
? baseSync({filters, events, relays: [relay]})
|
|
||||||
: syncWithoutNegentropy({filters, events, relays: [relay]}))
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import {
|
|||||||
isUnwrappedEvent,
|
isUnwrappedEvent,
|
||||||
isSignedEvent,
|
isSignedEvent,
|
||||||
} from "@welshman/util"
|
} from "@welshman/util"
|
||||||
import {publish, PublishStatus} from "@welshman/net"
|
import {MultiPublish, PublishStatus} from "@welshman/net"
|
||||||
import {repository, tracker} from "./core.js"
|
import {repository, tracker} from "./core.js"
|
||||||
import {pubkey, getSession, getSigner} from "./session.js"
|
import {pubkey, getSession, getSigner} from "./session.js"
|
||||||
|
|
||||||
@@ -225,7 +225,7 @@ thunkWorker.addGlobalHandler((thunk: Thunk) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send it off
|
// Send it off
|
||||||
const pub = publish({event: signedEvent, relays: thunk.request.relays})
|
const pub = new MultiPublish({event: signedEvent, relays: thunk.request.relays})
|
||||||
|
|
||||||
// Copy the signature over since we had deferred it
|
// Copy the signature over since we had deferred it
|
||||||
const savedEvent = repository.getEvent(signedEvent.id) as SignedEvent
|
const savedEvent = repository.getEvent(signedEvent.id) as SignedEvent
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import {writable, derived} from "svelte/store"
|
import {writable, derived} from "svelte/store"
|
||||||
import {type Zapper} from "@welshman/util"
|
import {Zapper} from "@welshman/util"
|
||||||
import {type SubscribeRequestWithHandlers} from "@welshman/net"
|
import {MultiRequestOptions} from "@welshman/net"
|
||||||
import {
|
import {
|
||||||
ctx,
|
ctx,
|
||||||
identity,
|
identity,
|
||||||
@@ -80,10 +80,7 @@ export const {
|
|||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const deriveZapperForPubkey = (
|
export const deriveZapperForPubkey = (pubkey: string, request: Partial<MultiRequestOptions> = {}) =>
|
||||||
pubkey: string,
|
|
||||||
request: Partial<SubscribeRequestWithHandlers> = {},
|
|
||||||
) =>
|
|
||||||
derived([zappersByLnurl, deriveProfile(pubkey, request)], ([$zappersByLnurl, $profile]) => {
|
derived([zappersByLnurl, deriveProfile(pubkey, request)], ([$zappersByLnurl, $profile]) => {
|
||||||
if (!$profile?.lnurl) {
|
if (!$profile?.lnurl) {
|
||||||
return undefined
|
return undefined
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@welshman/lib": "^0.1.0",
|
"@welshman/lib": "^0.1.0",
|
||||||
"@welshman/util": "^0.1.0",
|
"@welshman/util": "^0.1.0",
|
||||||
|
"@welshman/relay": "^0.1.0",
|
||||||
"isomorphic-ws": "^5.0.0",
|
"isomorphic-ws": "^5.0.0",
|
||||||
"nostr-tools": "^2.11.0",
|
"nostr-tools": "^2.11.0",
|
||||||
"typed-emitter": "^2.1.0"
|
"typed-emitter": "^2.1.0"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import EventEmitter from "events"
|
import EventEmitter from "events"
|
||||||
import {call, on} from "@welshman/lib"
|
import {call, on} from "@welshman/lib"
|
||||||
import {Relay, LOCAL_RELAY_URL, isRelayUrl} from "@welshman/util"
|
import {isRelayUrl} from "@welshman/util"
|
||||||
|
import {LocalRelay, LOCAL_RELAY_URL, Repository} from "@welshman/relay"
|
||||||
import {RelayMessage, ClientMessage} from "./message.js"
|
import {RelayMessage, ClientMessage} from "./message.js"
|
||||||
import {Socket, SocketEvent} from "./socket.js"
|
import {Socket, SocketEvent} from "./socket.js"
|
||||||
import {TypedEmitter, Unsubscriber} from "./util.js"
|
import {TypedEmitter, Unsubscriber} from "./util.js"
|
||||||
@@ -52,7 +53,7 @@ export class SocketAdapter extends AbstractAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class LocalAdapter extends AbstractAdapter {
|
export class LocalAdapter extends AbstractAdapter {
|
||||||
constructor(readonly relay: Relay) {
|
constructor(readonly relay: LocalRelay) {
|
||||||
super()
|
super()
|
||||||
|
|
||||||
this._unsubscribers.push(
|
this._unsubscribers.push(
|
||||||
@@ -91,7 +92,7 @@ export class EmptyAdapter extends AbstractAdapter {
|
|||||||
|
|
||||||
export type AdapterContext = {
|
export type AdapterContext = {
|
||||||
pool?: Pool
|
pool?: Pool
|
||||||
relay?: Relay
|
relay?: LocalRelay
|
||||||
getAdapter?: (url: string, context: AdapterContext) => AbstractAdapter
|
getAdapter?: (url: string, context: AdapterContext) => AbstractAdapter
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,7 +106,9 @@ export const getAdapter = (url: string, context: AdapterContext = {}) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (url === LOCAL_RELAY_URL) {
|
if (url === LOCAL_RELAY_URL) {
|
||||||
return context.relay ? new LocalAdapter(context.relay) : new EmptyAdapter()
|
const relay = context.relay || new LocalRelay(Repository.getSingleton())
|
||||||
|
|
||||||
|
return new LocalAdapter(relay)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isRelayUrl(url)) {
|
if (isRelayUrl(url)) {
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
build
|
||||||
|
normalize-url
|
||||||
|
Negentropy.ts
|
||||||
|
__tests__
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
# @welshman/net [](https://npmjs.com/package/@welshman/net)
|
||||||
|
|
||||||
|
Utilities having to do with connection management and nostr messages.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import {ctx, setContext} from '@welshman/lib'
|
||||||
|
import {type TrustedEvent, createEvent, NOTE} from '@welshman/util'
|
||||||
|
import {subscribe, publish, getDefaultNetContext} from '@welshman/net'
|
||||||
|
|
||||||
|
// Sets up customizable event valdation, handlers, etc
|
||||||
|
setContext(getDefaultNetContext())
|
||||||
|
|
||||||
|
// Send a subscription
|
||||||
|
const sub = subscribe({
|
||||||
|
relays: ['wss://relay.example.com/'],
|
||||||
|
filters: [{kinds: [1], limit: 1}],
|
||||||
|
closeOnEose: true,
|
||||||
|
timeout: 10000,
|
||||||
|
})
|
||||||
|
|
||||||
|
sub.on(SubscriptionEvent.Event, (url: string, event: TrustedEvent) => {
|
||||||
|
console.log(url, event)
|
||||||
|
sub.close()
|
||||||
|
})
|
||||||
|
|
||||||
|
// Publish an event
|
||||||
|
const pub = publish({
|
||||||
|
relays: ['wss://relay.example.com/'],
|
||||||
|
event: createEvent(NOTE, {content: 'hi'}),
|
||||||
|
})
|
||||||
|
|
||||||
|
pub.emitter.on('*', (status: PublishStatus, url: string) => {
|
||||||
|
console.log(status, url)
|
||||||
|
})
|
||||||
|
|
||||||
|
// The Tracker class can tell you which relays an event was read from or published to
|
||||||
|
console.log(ctx.net.tracker.getRelays(event.id))
|
||||||
|
```
|
||||||
|
|
||||||
|
The main reason this module exists is to support different backends via Executor and different `target` classes. For example, to add a local relay that automatically gets used:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import {setContext} from '@welshman/lib'
|
||||||
|
import {LOCAL_RELAY_URL, Relay, Repository} from '@welshman/util'
|
||||||
|
import {getDefaultNetContext, Multi, Local, Relays, Executor} from '@welshman/net'
|
||||||
|
|
||||||
|
const repository = new Repository()
|
||||||
|
|
||||||
|
const relay = new Relay(repository)
|
||||||
|
|
||||||
|
setContext(getDefaultNetContext({
|
||||||
|
getExecutor: (relays: string[]) => {
|
||||||
|
return new Executor(
|
||||||
|
new Multi([
|
||||||
|
new Local(relay),
|
||||||
|
new Relays(remoteUrls.map(url => ctx.net.pool.get(url))),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
```
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"name": "@welshman/relay",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"author": "hodlbod",
|
||||||
|
"license": "MIT",
|
||||||
|
"description": "An in-memory nostr relay implementation.",
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
|
"type": "module",
|
||||||
|
"files": [
|
||||||
|
"build"
|
||||||
|
],
|
||||||
|
"types": "./build/src/index.d.ts",
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"types": "./build/src/index.d.ts",
|
||||||
|
"import": "./build/src/index.js",
|
||||||
|
"require": "./build/src/index.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"pub": "npm run lint && npm run build && npm publish",
|
||||||
|
"build": "gts clean && tsc",
|
||||||
|
"lint": "gts lint",
|
||||||
|
"fix": "gts fix"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@welshman/lib": "^0.1.0",
|
||||||
|
"@welshman/util": "^0.1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
export * from "./repository.js"
|
||||||
|
export * from "./relay.js"
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
import {Emitter, sleep} from "@welshman/lib"
|
||||||
|
import {Filter, TrustedEvent, HashedEvent, matchFilters} from "@welshman/util"
|
||||||
|
import {Repository} from "./repository.js"
|
||||||
|
|
||||||
|
export class LocalRelay<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)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +1,34 @@
|
|||||||
import {flatten, pluck, Emitter, sortBy, inc, chunk, uniq, omit, now, range} from "@welshman/lib"
|
import {
|
||||||
import {DELETE} from "./Kinds.js"
|
DAY,
|
||||||
import {EPOCH, matchFilter} from "./Filters.js"
|
Emitter,
|
||||||
import {isReplaceable, isUnwrappedEvent} from "./Events.js"
|
flatten,
|
||||||
import {getAddress} from "./Address.js"
|
pluck,
|
||||||
import type {Filter} from "./Filters.js"
|
sortBy,
|
||||||
import type {TrustedEvent, HashedEvent} from "./Events.js"
|
inc,
|
||||||
|
chunk,
|
||||||
|
uniq,
|
||||||
|
omit,
|
||||||
|
now,
|
||||||
|
range,
|
||||||
|
} from "@welshman/lib"
|
||||||
|
import {
|
||||||
|
DELETE,
|
||||||
|
EPOCH,
|
||||||
|
matchFilter,
|
||||||
|
isReplaceable,
|
||||||
|
isUnwrappedEvent,
|
||||||
|
getAddress,
|
||||||
|
Filter,
|
||||||
|
TrustedEvent,
|
||||||
|
HashedEvent,
|
||||||
|
} from "@welshman/util"
|
||||||
|
|
||||||
export const DAY = 86400
|
export const LOCAL_RELAY_URL = "local://welshman.relay/"
|
||||||
|
|
||||||
const getDay = (ts: number) => Math.floor(ts / DAY)
|
const getDay = (ts: number) => Math.floor(ts / DAY)
|
||||||
|
|
||||||
|
export let repositorySingleton: Repository<TrustedEvent>
|
||||||
|
|
||||||
export class Repository<E extends HashedEvent = TrustedEvent> extends Emitter {
|
export class Repository<E extends HashedEvent = TrustedEvent> extends Emitter {
|
||||||
eventsById = new Map<string, E>()
|
eventsById = new Map<string, E>()
|
||||||
eventsByWrap = new Map<string, E>()
|
eventsByWrap = new Map<string, E>()
|
||||||
@@ -20,6 +39,14 @@ export class Repository<E extends HashedEvent = TrustedEvent> extends Emitter {
|
|||||||
eventsByKind = new Map<number, E[]>()
|
eventsByKind = new Map<number, E[]>()
|
||||||
deletes = new Map<string, number>()
|
deletes = new Map<string, number>()
|
||||||
|
|
||||||
|
static getSingleton() {
|
||||||
|
if (!repositorySingleton) {
|
||||||
|
repositorySingleton = new Repository()
|
||||||
|
}
|
||||||
|
|
||||||
|
return repositorySingleton
|
||||||
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super()
|
super()
|
||||||
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../node_modules/gts/tsconfig-google.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"rootDir": ".",
|
||||||
|
"outDir": "build",
|
||||||
|
"module": "nodenext",
|
||||||
|
"moduleResolution": "nodenext",
|
||||||
|
"lib": ["esnext", "dom"]
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"src/**/*.ts",
|
||||||
|
"test/**/*.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"entryPoints": ["src/index.ts"]
|
||||||
|
}
|
||||||
@@ -28,6 +28,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@welshman/lib": "^0.1.0",
|
"@welshman/lib": "^0.1.0",
|
||||||
"@welshman/util": "^0.1.0",
|
"@welshman/util": "^0.1.0",
|
||||||
|
"@welshman/relay": "^0.1.0",
|
||||||
"svelte": "^4.2.18"
|
"svelte": "^4.2.18"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,10 +10,9 @@ import {
|
|||||||
partition,
|
partition,
|
||||||
first,
|
first,
|
||||||
} from "@welshman/lib"
|
} from "@welshman/lib"
|
||||||
import type {Maybe} from "@welshman/lib"
|
import {Maybe} from "@welshman/lib"
|
||||||
import type {Repository} from "@welshman/util"
|
import {Repository} from "@welshman/relay"
|
||||||
import {matchFilters, getIdAndAddress, getIdFilters} from "@welshman/util"
|
import {matchFilters, getIdAndAddress, getIdFilters, Filter, TrustedEvent} from "@welshman/util"
|
||||||
import type {Filter, TrustedEvent} from "@welshman/util"
|
|
||||||
|
|
||||||
// Sync with localstorage
|
// Sync with localstorage
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,7 @@
|
|||||||
import {last, Emitter, normalizeUrl, sleep, stripProtocol} from "@welshman/lib"
|
import {last, normalizeUrl, 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"
|
|
||||||
|
|
||||||
// Constants and types
|
// Constants and types
|
||||||
|
|
||||||
export const LOCAL_RELAY_URL = "local://welshman.relay/"
|
|
||||||
|
|
||||||
export const BOGUS_RELAY_URL = "bogus://welshman.relay/"
|
|
||||||
|
|
||||||
export type RelayProfile = {
|
export type RelayProfile = {
|
||||||
url: string
|
url: string
|
||||||
icon?: string
|
icon?: string
|
||||||
@@ -83,58 +75,3 @@ export const displayRelayUrl = (url: string) => last(url.split("://")).replace(/
|
|||||||
|
|
||||||
export const displayRelayProfile = (profile?: RelayProfile, fallback = "") =>
|
export const displayRelayProfile = (profile?: RelayProfile, fallback = "") =>
|
||||||
profile?.name || 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)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -8,6 +8,5 @@ export * from "./Links.js"
|
|||||||
export * from "./List.js"
|
export * from "./List.js"
|
||||||
export * from "./Profile.js"
|
export * from "./Profile.js"
|
||||||
export * from "./Relay.js"
|
export * from "./Relay.js"
|
||||||
export * from "./Repository.js"
|
|
||||||
export * from "./Tags.js"
|
export * from "./Tags.js"
|
||||||
export * from "./Zaps.js"
|
export * from "./Zaps.js"
|
||||||
|
|||||||
Reference in New Issue
Block a user