Remove relay package, move everything into net
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import {PublishStatus} from "@welshman/net"
|
||||
import {PublishStatus, LOCAL_RELAY_URL} from "@welshman/net"
|
||||
import {NOTE, DIRECT_MESSAGE, WRAP, makeEvent} from "@welshman/util"
|
||||
import {LOCAL_RELAY_URL} from "@welshman/relay"
|
||||
import {getPubkey, makeSecret, prep} from "@welshman/signer"
|
||||
import {afterEach, beforeEach, describe, expect, it, vi} from "vitest"
|
||||
import {repository, tracker} from "../src/core"
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
"@types/throttle-debounce": "^5.0.2",
|
||||
"@welshman/feeds": "workspace:*",
|
||||
"@welshman/lib": "workspace:*",
|
||||
"@welshman/relay": "workspace:*",
|
||||
"@welshman/router": "workspace:*",
|
||||
"@welshman/net": "workspace:*",
|
||||
"@welshman/signer": "workspace:*",
|
||||
|
||||
@@ -208,7 +208,7 @@ export type SendWrappedOptions = Omit<ThunkOptions, "event" | "relays"> & {
|
||||
recipients: string[]
|
||||
}
|
||||
|
||||
export const sendWrapped = async ({event, recipients, ...options}: SendWrappedOptions) =>
|
||||
export const sendWrapped = ({event, recipients, ...options}: SendWrappedOptions) =>
|
||||
new MergedThunk(
|
||||
uniq(recipients).map(recipient => {
|
||||
const relays = Router.get().PubkeyInbox(recipient).getUrls()
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
import {throttle} from "@welshman/lib"
|
||||
import {Repository, LocalRelay, Tracker} from "@welshman/relay"
|
||||
import {Repository, Tracker} from "@welshman/net"
|
||||
import {custom} from "@welshman/store"
|
||||
|
||||
export const tracker = new Tracker()
|
||||
|
||||
export const repository = Repository.get()
|
||||
|
||||
export const relay = new LocalRelay(repository)
|
||||
|
||||
// Adapt objects to stores
|
||||
|
||||
export const makeRepositoryStore = ({throttle: t = 300}: {throttle?: number} = {}) =>
|
||||
|
||||
@@ -13,8 +13,8 @@ import {
|
||||
getPubkey,
|
||||
ISigner,
|
||||
} from "@welshman/signer"
|
||||
import {WrapManager} from "@welshman/relay"
|
||||
import {relay, tracker} from "./core.js"
|
||||
import {WrapManager} from "@welshman/net"
|
||||
import {tracker, repository} from "./core.js"
|
||||
|
||||
export enum SessionMethod {
|
||||
Nip01 = "nip01",
|
||||
@@ -279,7 +279,7 @@ export const nip44EncryptToSelf = (payload: string) => {
|
||||
|
||||
// Gift wrap utilities
|
||||
|
||||
export const wrapManager = new WrapManager({relay, tracker})
|
||||
export const wrapManager = new WrapManager({repository, tracker})
|
||||
|
||||
export const shouldUnwrap = withGetter(writable(false))
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
"paths": {
|
||||
"@welshman/feeds": ["../feeds/src/index.js"],
|
||||
"@welshman/lib": ["../lib/src/index.js"],
|
||||
"@welshman/relay": ["../relay/src/index.js"],
|
||||
"@welshman/net": ["../net/src/index.js"],
|
||||
"@welshman/signer": ["../signer/src/index.js"],
|
||||
"@welshman/store": ["../store/src/index.js"],
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
"dependencies": {
|
||||
"@welshman/lib": "workspace:*",
|
||||
"@welshman/net": "workspace:*",
|
||||
"@welshman/relay": "workspace:*",
|
||||
"@welshman/router": "workspace:*",
|
||||
"@welshman/signer": "workspace:*",
|
||||
"@welshman/util": "workspace:*",
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
now,
|
||||
} from "@welshman/lib"
|
||||
import {EPOCH, trimFilters, guessFilterDelta, TrustedEvent, Filter} from "@welshman/util"
|
||||
import {Tracker} from "@welshman/relay"
|
||||
import {Tracker} from "@welshman/net"
|
||||
import {Feed, FeedType, RequestItem} from "./core.js"
|
||||
import {FeedCompiler, FeedCompilerOptions} from "./compiler.js"
|
||||
import {requestPage} from "./request.js"
|
||||
|
||||
@@ -10,9 +10,8 @@ import {
|
||||
RELAYS,
|
||||
} from "@welshman/util"
|
||||
import {Nip01Signer, ISigner} from "@welshman/signer"
|
||||
import {LOCAL_RELAY_URL, Tracker} from "@welshman/relay"
|
||||
import {Router, getFilterSelections, addMinimalFallbacks} from "@welshman/router"
|
||||
import {AdapterContext, request, publish} from "@welshman/net"
|
||||
import {LOCAL_RELAY_URL, Tracker, AdapterContext, request, publish} from "@welshman/net"
|
||||
|
||||
export type RequestPageOptions = {
|
||||
filters: Filter[]
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
"outDir": "./dist",
|
||||
"paths": {
|
||||
"@welshman/lib": ["../lib/src/index.js"],
|
||||
"@welshman/net": ["../net/src/index.js"],
|
||||
"@welshman/router": ["../router/src/index.js"],
|
||||
"@welshman/signer": ["../signer/src/index.js"],
|
||||
"@welshman/util": ["../util/src/index.js"]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import EventEmitter from "events"
|
||||
import {describe, expect, it, vi, beforeEach, afterEach} from "vitest"
|
||||
import {LocalRelay, Repository, LOCAL_RELAY_URL} from "@welshman/relay"
|
||||
import {makeEvent} from "@welshman/util"
|
||||
import {prep, getPubkey, makeSecret} from "@welshman/signer"
|
||||
import {AdapterEvent, SocketAdapter, LocalAdapter, getAdapter} from "../src/adapter"
|
||||
import {Repository, LOCAL_RELAY_URL} from "../src/repository"
|
||||
import {ClientMessage, RelayMessage} from "../src/message"
|
||||
import {Socket, SocketEvent} from "../src/socket"
|
||||
import {Pool} from "../src/pool"
|
||||
@@ -69,17 +70,13 @@ describe("SocketAdapter", () => {
|
||||
})
|
||||
|
||||
describe("LocalAdapter", () => {
|
||||
let relay: LocalRelay & EventEmitter
|
||||
let repository: Repository
|
||||
let adapter: LocalAdapter
|
||||
|
||||
beforeEach(() => {
|
||||
const mockRelay = new EventEmitter()
|
||||
Object.assign(mockRelay, {
|
||||
send: vi.fn(),
|
||||
removeAllListeners: vi.fn(),
|
||||
})
|
||||
relay = mockRelay as unknown as LocalRelay & EventEmitter
|
||||
adapter = new LocalAdapter(relay)
|
||||
repository = new Repository()
|
||||
adapter = new LocalAdapter(repository)
|
||||
vi.useFakeTimers()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
@@ -88,32 +85,35 @@ describe("LocalAdapter", () => {
|
||||
})
|
||||
|
||||
it("should initialize with correct relay", () => {
|
||||
expect(adapter.relay).toBe(relay)
|
||||
expect(adapter.urls).toEqual([LOCAL_RELAY_URL])
|
||||
expect(adapter.sockets).toEqual([])
|
||||
})
|
||||
|
||||
it("should forward received messages", () => {
|
||||
const receiveSpy = vi.fn()
|
||||
const pubkey = getPubkey(makeSecret())
|
||||
const event = prep(makeEvent(1), pubkey)
|
||||
|
||||
adapter.send(["REQ", "r1", {kinds: [1]}])
|
||||
adapter.send(["REQ", "r2", {kinds: [2]}])
|
||||
adapter.on(AdapterEvent.Receive, receiveSpy)
|
||||
repository.publish(event)
|
||||
|
||||
const message: RelayMessage = ["EVENT", "123", {id: "123", kind: 1}]
|
||||
relay.emit("*", ...message)
|
||||
|
||||
expect(receiveSpy).toHaveBeenCalledWith(message, LOCAL_RELAY_URL)
|
||||
expect(receiveSpy).toHaveBeenCalledTimes(1)
|
||||
expect(receiveSpy).toHaveBeenCalledWith(["EVENT", "r1", event], LOCAL_RELAY_URL)
|
||||
})
|
||||
|
||||
it("should send messages to relay", () => {
|
||||
const message: ClientMessage = ["EVENT", {id: "123", kind: 1}]
|
||||
adapter.send(message)
|
||||
it("should send messages to relay", async () => {
|
||||
const publishSpy = vi.spyOn(repository, "publish")
|
||||
const pubkey = getPubkey(makeSecret())
|
||||
const event = prep(makeEvent(1), pubkey)
|
||||
|
||||
expect(relay.send).toHaveBeenCalledWith("EVENT", message[1])
|
||||
})
|
||||
adapter.send(["EVENT", event])
|
||||
|
||||
it("should cleanup properly", () => {
|
||||
const removeListenersSpy = vi.spyOn(adapter, "removeAllListeners")
|
||||
adapter.cleanup()
|
||||
expect(removeListenersSpy).toHaveBeenCalled()
|
||||
await vi.runAllTimersAsync()
|
||||
|
||||
expect(publishSpy).toHaveBeenCalledTimes(1)
|
||||
expect(publishSpy).toHaveBeenCalledWith(event)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@welshman/lib": "workspace:*",
|
||||
"@welshman/relay": "workspace:*",
|
||||
"@welshman/util": "workspace:*",
|
||||
"events": "^3.3.0",
|
||||
"isomorphic-ws": "^5.0.0"
|
||||
|
||||
+59
-10
@@ -1,8 +1,16 @@
|
||||
import EventEmitter from "events"
|
||||
import {call, mergeRight, on} from "@welshman/lib"
|
||||
import {isRelayUrl} from "@welshman/util"
|
||||
import {LocalRelay, LOCAL_RELAY_URL} from "@welshman/relay"
|
||||
import {RelayMessage, ClientMessage} from "./message.js"
|
||||
import {call, sleep, mergeRight, on} from "@welshman/lib"
|
||||
import {isRelayUrl, matchFilters, Filter} from "@welshman/util"
|
||||
import {LOCAL_RELAY_URL, Repository} from "./repository"
|
||||
import {
|
||||
RelayMessage,
|
||||
RelayMessageType,
|
||||
ClientMessage,
|
||||
ClientMessageType,
|
||||
ClientEvent,
|
||||
ClientReq,
|
||||
ClientClose,
|
||||
} from "./message.js"
|
||||
import {Socket, SocketEvent} from "./socket.js"
|
||||
import {Unsubscriber} from "./util.js"
|
||||
import {netContext, NetContext} from "./context.js"
|
||||
@@ -53,12 +61,20 @@ export class SocketAdapter extends AbstractAdapter {
|
||||
}
|
||||
|
||||
export class LocalAdapter extends AbstractAdapter {
|
||||
constructor(readonly relay: LocalRelay) {
|
||||
subs = new Map<string, Filter[]>()
|
||||
|
||||
constructor(readonly repository: Repository) {
|
||||
super()
|
||||
|
||||
this._unsubscribers.push(
|
||||
on(relay, "*", (...message: RelayMessage) => {
|
||||
this.emit(AdapterEvent.Receive, message, LOCAL_RELAY_URL)
|
||||
on(repository, "update", ({added}) => {
|
||||
for (const [subId, filters] of this.subs.entries()) {
|
||||
for (const event of added) {
|
||||
if (matchFilters(filters, event)) {
|
||||
this.#receive([RelayMessageType.Event, subId, event])
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
)
|
||||
}
|
||||
@@ -72,9 +88,42 @@ export class LocalAdapter extends AbstractAdapter {
|
||||
}
|
||||
|
||||
send(message: ClientMessage) {
|
||||
const [type, ...rest] = message
|
||||
switch (message[0]) {
|
||||
case ClientMessageType.Event:
|
||||
return this.#handleEVENT(message as ClientEvent)
|
||||
case ClientMessageType.Close:
|
||||
return this.#handleCLOSE(message as ClientClose)
|
||||
case ClientMessageType.Req:
|
||||
return this.#handleREQ(message as ClientReq)
|
||||
}
|
||||
}
|
||||
|
||||
this.relay.send(type, ...rest)
|
||||
#receive(message: RelayMessage) {
|
||||
this.emit(AdapterEvent.Receive, message, LOCAL_RELAY_URL)
|
||||
}
|
||||
|
||||
#handleEVENT([_, event]: ClientEvent) {
|
||||
this.repository.publish(event)
|
||||
|
||||
// Callers generally expect async relays
|
||||
sleep(1).then(() => this.#receive([RelayMessageType.Ok, event.id, true, ""]))
|
||||
}
|
||||
|
||||
#handleCLOSE([_, subId]: ClientClose) {
|
||||
this.subs.delete(subId)
|
||||
}
|
||||
|
||||
#handleREQ([_, subId, ...filters]: ClientReq) {
|
||||
this.subs.set(subId, filters)
|
||||
|
||||
// Callers generally expect async relays
|
||||
sleep(1).then(() => {
|
||||
for (const event of this.repository.query(filters)) {
|
||||
this.#receive([RelayMessageType.Event, subId, event])
|
||||
}
|
||||
|
||||
this.#receive([RelayMessageType.Eose, subId])
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +162,7 @@ export const getAdapter = (url: string, adapterContext: AdapterContext = {}) =>
|
||||
}
|
||||
|
||||
if (url === LOCAL_RELAY_URL) {
|
||||
return new LocalAdapter(new LocalRelay(context.repository))
|
||||
return new LocalAdapter(context.repository)
|
||||
}
|
||||
|
||||
if (isRelayUrl(url)) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {Repository} from "@welshman/relay"
|
||||
import {verifyEvent, TrustedEvent} from "@welshman/util"
|
||||
import {AbstractAdapter} from "./adapter.js"
|
||||
import {Repository} from "./repository.js"
|
||||
import {Pool} from "./pool.js"
|
||||
|
||||
export type NetContext = {
|
||||
|
||||
@@ -8,4 +8,7 @@ export * from "./policy.js"
|
||||
export * from "./pool.js"
|
||||
export * from "./publish.js"
|
||||
export * from "./socket.js"
|
||||
export * from "./repository.js"
|
||||
export * from "./request.js"
|
||||
export * from "./tracker.js"
|
||||
export * from "./wrapManager.js"
|
||||
|
||||
@@ -18,11 +18,11 @@ import {
|
||||
deduplicateEvents,
|
||||
getFilterResultCardinality,
|
||||
} from "@welshman/util"
|
||||
import {Tracker} from "@welshman/relay"
|
||||
import {RelayMessage, ClientMessageType, isRelayEvent, isRelayEose} from "./message.js"
|
||||
import {getAdapter, AdapterContext, AdapterEvent} from "./adapter.js"
|
||||
import {SocketEvent, SocketStatus} from "./socket.js"
|
||||
import {netContext} from "./context.js"
|
||||
import {Tracker} from "./tracker.js"
|
||||
|
||||
export type BaseRequestOptions = {
|
||||
signal?: AbortSignal
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {Emitter, remove, omit} from "@welshman/lib"
|
||||
import {HashedEvent, SignedEvent} from "@welshman/util"
|
||||
import {Tracker} from "./tracker.js"
|
||||
import {LocalRelay} from "./relay.js"
|
||||
import {Repository} from "./repository.js"
|
||||
|
||||
export type WrapItem = Omit<HashedEvent, "content"> & {
|
||||
rumorId: string
|
||||
@@ -11,24 +11,30 @@ export type WrapItem = Omit<HashedEvent, "content"> & {
|
||||
export type WrapReference = string[]
|
||||
|
||||
export type WrapManagerOptions = {
|
||||
relay: LocalRelay
|
||||
repository: Repository
|
||||
tracker: Tracker
|
||||
}
|
||||
|
||||
export class WrapManager extends Emitter {
|
||||
_wrapIndex = new Map<string, WrapItem>()
|
||||
_rumorIndex = new Map<string, WrapReference>()
|
||||
_recipientIndex = new Map<string, WrapReference>()
|
||||
|
||||
constructor(readonly options: WrapManagerOptions) {
|
||||
super()
|
||||
}
|
||||
|
||||
getRumor = (id: string) => {
|
||||
const wrapItem = this._wrapIndex.get(id)
|
||||
// Reading/exporting
|
||||
|
||||
dump = () => Array.from(this._wrapIndex.values())
|
||||
|
||||
getWraps = (rumorId: string) =>
|
||||
this._rumorIndex.get(rumorId).map(wrapId => this._wrapIndex.get(wrapId)!)
|
||||
|
||||
getRumor = (wrapId: string) => {
|
||||
const wrapItem = this._wrapIndex.get(wrapId)
|
||||
|
||||
if (wrapItem) {
|
||||
return this.options.relay.repository.getEvent(wrapItem.rumorId)
|
||||
return this.options.repository.getEvent(wrapItem.rumorId)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,8 +61,8 @@ export class WrapManager extends Emitter {
|
||||
|
||||
this._add(wrapItem)
|
||||
|
||||
// Send via our relay so that listeners get notified
|
||||
this.options.relay.send("EVENT", rumor)
|
||||
// Save to our repository
|
||||
this.options.repository.publish(rumor)
|
||||
|
||||
// Mark the rumor as having come from the wrap's urls
|
||||
this.options.tracker.copy(wrap.id, rumor.id)
|
||||
@@ -71,7 +77,7 @@ export class WrapManager extends Emitter {
|
||||
|
||||
if (wrapItem) {
|
||||
this._remove(wrapItem)
|
||||
this.options.relay.repository.removeEvent(wrapItem.rumorId)
|
||||
this.options.repository.removeEvent(wrapItem.rumorId)
|
||||
this.emit("remove", wrapItem)
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,7 @@
|
||||
"outDir": "./dist",
|
||||
"paths": {
|
||||
"@welshman/lib": ["../lib/src/index.js"],
|
||||
"@welshman/util": ["../util/src/index.js"],
|
||||
"@welshman/relay": ["../relay/src/index.js"]
|
||||
"@welshman/util": ["../util/src/index.js"]
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
build
|
||||
normalize-url
|
||||
Negentropy.ts
|
||||
__tests__
|
||||
@@ -1,156 +0,0 @@
|
||||
import {describe, it, expect, beforeEach, vi, afterEach} from "vitest"
|
||||
import {now} from "@welshman/lib"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {LocalRelay} from "../src/relay"
|
||||
import {Repository} from "../src/repository"
|
||||
|
||||
describe("LocalRelay", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
vi.useFakeTimers()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
vi.useRealTimers()
|
||||
})
|
||||
|
||||
// Realistic Nostr data
|
||||
const pubkey = "ee".repeat(32)
|
||||
const id = "ff".repeat(32)
|
||||
const sig = "00".repeat(64)
|
||||
const currentTime = now()
|
||||
|
||||
const createEvent = (overrides = {}): TrustedEvent => ({
|
||||
id: id,
|
||||
pubkey: pubkey,
|
||||
created_at: currentTime,
|
||||
kind: 1,
|
||||
tags: [],
|
||||
content: "Hello Nostr!",
|
||||
sig: sig,
|
||||
...overrides,
|
||||
})
|
||||
|
||||
describe("LocalRelay class", () => {
|
||||
let relay: LocalRelay
|
||||
let repository: Repository<TrustedEvent>
|
||||
|
||||
beforeEach(() => {
|
||||
repository = new Repository<TrustedEvent>()
|
||||
relay = new LocalRelay(repository)
|
||||
})
|
||||
|
||||
describe("EVENT handling", () => {
|
||||
it("should publish events to repository", async () => {
|
||||
const event = createEvent()
|
||||
const publishSpy = vi.spyOn(repository, "publish")
|
||||
|
||||
relay.send("EVENT", event)
|
||||
|
||||
expect(publishSpy).toHaveBeenCalledWith(event)
|
||||
|
||||
// Should emit OK
|
||||
const okHandler = vi.fn()
|
||||
relay.on("OK", okHandler)
|
||||
|
||||
// Wait for async operations
|
||||
await vi.runAllTimersAsync()
|
||||
|
||||
expect(okHandler).toHaveBeenCalledWith(event.id, true, "")
|
||||
})
|
||||
|
||||
it("should notify matching subscribers", async () => {
|
||||
const event = createEvent()
|
||||
const subId = "test-sub"
|
||||
const filter = {kinds: [1]}
|
||||
|
||||
relay.send("REQ", subId, filter)
|
||||
|
||||
const eventHandler = vi.fn()
|
||||
relay.on("EVENT", eventHandler)
|
||||
|
||||
relay.send("EVENT", event)
|
||||
|
||||
await vi.runAllTimersAsync()
|
||||
|
||||
expect(eventHandler).toHaveBeenCalledWith(subId, event)
|
||||
})
|
||||
|
||||
it("should not notify for deleted events", async () => {
|
||||
const event = createEvent()
|
||||
repository.removeEvent(event.id)
|
||||
|
||||
const eventHandler = vi.fn()
|
||||
relay.on("EVENT", eventHandler)
|
||||
|
||||
relay.send("EVENT", event)
|
||||
|
||||
await vi.runAllTimersAsync()
|
||||
|
||||
expect(eventHandler).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
describe("REQ handling", () => {
|
||||
it("should handle subscription requests", async () => {
|
||||
const event = createEvent()
|
||||
repository.publish(event)
|
||||
|
||||
const subId = "test-sub"
|
||||
const filter = {kinds: [1]}
|
||||
|
||||
const eventHandler = vi.fn()
|
||||
const eoseHandler = vi.fn()
|
||||
|
||||
relay.on("EVENT", eventHandler)
|
||||
relay.on("EOSE", eoseHandler)
|
||||
|
||||
relay.send("REQ", subId, filter)
|
||||
|
||||
await vi.runAllTimersAsync()
|
||||
|
||||
expect(eventHandler).toHaveBeenCalledWith(subId, event)
|
||||
expect(eoseHandler).toHaveBeenCalledWith(subId)
|
||||
})
|
||||
|
||||
it("should handle multiple filters", async () => {
|
||||
const event1 = createEvent({kind: 1})
|
||||
const event2 = createEvent({kind: 2, id: "ee".repeat(31)})
|
||||
repository.publish(event1)
|
||||
repository.publish(event2)
|
||||
|
||||
const subId = "test-sub"
|
||||
const filters = [{kinds: [1]}, {kinds: [2]}]
|
||||
|
||||
const eventHandler = vi.fn()
|
||||
relay.on("EVENT", eventHandler)
|
||||
|
||||
relay.send("REQ", subId, ...filters)
|
||||
|
||||
await vi.runAllTimersAsync()
|
||||
|
||||
expect(eventHandler).toHaveBeenCalledTimes(2)
|
||||
})
|
||||
})
|
||||
|
||||
describe("CLOSE handling", () => {
|
||||
it("should close subscriptions", async () => {
|
||||
const subId = "test-sub"
|
||||
relay.send("REQ", subId, {kinds: [1]})
|
||||
relay.send("CLOSE", subId)
|
||||
|
||||
await vi.runAllTimersAsync()
|
||||
|
||||
const event = createEvent()
|
||||
const eventHandler = vi.fn()
|
||||
relay.on("EVENT", eventHandler)
|
||||
|
||||
relay.send("EVENT", event)
|
||||
|
||||
await vi.runAllTimersAsync()
|
||||
|
||||
expect(eventHandler).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,31 +0,0 @@
|
||||
{
|
||||
"name": "@welshman/relay",
|
||||
"version": "0.5.4",
|
||||
"author": "hodlbod",
|
||||
"license": "MIT",
|
||||
"description": "An in-memory nostr relay implementation.",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"type": "module",
|
||||
"main": "dist/relay/src/index.js",
|
||||
"types": "dist/relay/src/index.d.ts",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "pnpm run clean && pnpm run compile --force",
|
||||
"clean": "rimraf ./dist",
|
||||
"compile": "tsc -b tsconfig.build.json",
|
||||
"prepublishOnly": "pnpm run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@welshman/lib": "workspace:*",
|
||||
"@welshman/util": "workspace:*",
|
||||
"@welshman/signer": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"rimraf": "~6.0.0",
|
||||
"typescript": "~5.8.0"
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
export * from "./relay.js"
|
||||
export * from "./repository.js"
|
||||
export * from "./tracker.js"
|
||||
export * from "./wrapManager.js"
|
||||
@@ -1,56 +0,0 @@
|
||||
import {Emitter, sleep} from "@welshman/lib"
|
||||
import {Filter, TrustedEvent, matchFilters} from "@welshman/util"
|
||||
import {Repository} from "./repository.js"
|
||||
|
||||
export class LocalRelay extends Emitter {
|
||||
subs = new Map<string, Filter[]>()
|
||||
|
||||
constructor(readonly repository: Repository) {
|
||||
super()
|
||||
}
|
||||
|
||||
send(type: string, ...message: any[]) {
|
||||
switch (type) {
|
||||
case "EVENT":
|
||||
return this.handleEVENT(message as [TrustedEvent])
|
||||
case "CLOSE":
|
||||
return this.handleCLOSE(message as [string])
|
||||
case "REQ":
|
||||
return this.handleREQ(message as [string, ...Filter[]])
|
||||
}
|
||||
}
|
||||
|
||||
handleEVENT([event]: [TrustedEvent]) {
|
||||
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 +0,0 @@
|
||||
{
|
||||
"extends": "../../tsconfig.build.json",
|
||||
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"paths": {
|
||||
"@welshman/lib": ["../lib/src/index.js"],
|
||||
"@welshman/util": ["../util/src/index.js"]
|
||||
}
|
||||
},
|
||||
|
||||
"include": [
|
||||
"src/**/*"
|
||||
]
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json"
|
||||
}
|
||||
@@ -22,7 +22,7 @@
|
||||
"dependencies": {
|
||||
"@welshman/lib": "workspace:*",
|
||||
"@welshman/util": "workspace:*",
|
||||
"@welshman/relay": "workspace:*"
|
||||
"@welshman/net": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"rimraf": "~6.0.0",
|
||||
|
||||
@@ -35,7 +35,7 @@ import {
|
||||
getPubkeyTags,
|
||||
RelayMode,
|
||||
} from "@welshman/util"
|
||||
import {Repository} from "@welshman/relay"
|
||||
import {Repository} from "@welshman/net"
|
||||
|
||||
export const INDEXED_KINDS = [PROFILE, RELAYS, INBOX_RELAYS, FOLLOWS]
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
"paths": {
|
||||
"@welshman/lib": ["../lib/src/index.js"],
|
||||
"@welshman/util": ["../util/src/index.js"],
|
||||
"@welshman/relay": ["../relay/src/index.js"],
|
||||
"@welshman/net": ["../net/src/index.js"]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {TrustedEvent} from "@welshman/util"
|
||||
import {Repository} from "@welshman/relay"
|
||||
import {Repository} from "@welshman/net"
|
||||
import {get} from "svelte/store"
|
||||
import {afterEach, beforeEach, describe, expect, it, vi} from "vitest"
|
||||
import {
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
"dependencies": {
|
||||
"@welshman/lib": "workspace:*",
|
||||
"@welshman/util": "workspace:*",
|
||||
"@welshman/relay": "workspace:*",
|
||||
"@welshman/net": "workspace:*",
|
||||
"svelte": "^4.2.18"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {derived} from "svelte/store"
|
||||
import {sortBy, identity, ensurePlural, removeNil, batch, partition, first} from "@welshman/lib"
|
||||
import {Repository} from "@welshman/relay"
|
||||
import {matchFilters, getIdAndAddress, getIdFilters, Filter, TrustedEvent} from "@welshman/util"
|
||||
import {Repository} from "@welshman/net"
|
||||
import {custom} from "./custom.js"
|
||||
|
||||
export type DeriveEventsMappedOptions<T> = {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"paths": {
|
||||
"@welshman/lib": ["../lib/src/index.js"],
|
||||
"@welshman/util": ["../util/src/index.js"],
|
||||
"@welshman/relay": ["../relay/src/index.js"]
|
||||
"@welshman/net": ["../net/src/index.js"]
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user