import type {Maybe, MaybeAsync} from "@welshman/lib" import type {EventTemplate, SignedEvent, StampedEvent} from "@welshman/util" import type {TestUser} from "../keys" // A queued write, drained in declaration order by `seed` in scenario.ts. export type Enqueue = (write: () => Promise) => void // Seeding calls record what to write and return before anything is written. export type SeededEvent = { readonly event: SignedEvent readonly id: string } // A domain writer needs a relay url to resolve its hints against, so anything it builds is deferred. export type SeededTemplate = StampedEvent | (() => MaybeAsync) // `write` is what an outbox-routed load resolves to, `read` is what a feed asks for that pubkey. export type RelayListUrls = { read?: string[] write?: string[] } export type ProfileValues = { name?: string about?: string picture?: string nip05?: string } export type PublisherOptions = { // The relay these events are seeded into, for the error a read-too-early raises. name: string enqueue: Enqueue // The moment the scenario began. A fixture with no timestamp is stamped with it, not the wall clock. startedAt: number // Deferred, since a space's relay handle only exists once the queue has started draining. sign: (user: TestUser, template: StampedEvent) => Promise } // What to write is recorded now and published when `seed()` drains. export const makePublisher = ({name, enqueue, startedAt, sign}: PublisherOptions) => { // Queues a write and hands back a getter for whatever it produced. const seeded = (write: () => Promise) => { let value: Maybe enqueue(async () => { value = await write() }) return () => { if (value) { return value } throw new Error(`An event seeded into "${name}" was read before seed() published it`) } } const publish = (write: () => Promise): SeededEvent => { const event = seeded(write) return { get event() { return event() }, get id() { return event().id }, } } const event = (user: TestUser, template: SeededTemplate, createdAt = startedAt) => publish(async () => { if (typeof template === "function") { return sign(user, {...(await template()), created_at: createdAt}) } return sign(user, template) }) return {seeded, publish, event} } export type Publisher = ReturnType