For AI agents: the complete documentation index is available at https://dotpress.dev/llms.txt, the full documentation bundle is available at https://dotpress.dev/llms-full.txt, and this page is available as Markdown at https://dotpress.dev/reference/events.md.

Events

The definitions, options, errors and contracts of @dotpress/events. For a guide, see Events and workers; for each queue, Event workers.

defineEvent()

defineEvent({ name: 'invoice.paid', schema: z.object({ invoiceId: z.string() }), transport: 'edge' })
OptionDescription
nameLetters, digits, ., _, : and -.
schemaZod schema of the payload. The payload is serialized as JSON, then validated: describe JSON values.
transportOptional: the name of a transport of the bus, default otherwise.

defineListener()

defineListener(invoicePaid, { name: 'send-receipt', handle: async (context) => { … } })
defineListener(invoicePaid, { name: 'send-receipt', load: () => import('./send-receipt.ts') })
OptionDescription
nameUnique: it identifies the listener in the messages. Renaming it orphans the messages still in queues.
handleThe handler.
loadInstead of handle: imports a module whose default export is the handler, in the workers only.
transportOptional: another transport than the one of its event.

The handler receives:

FieldDescription
payloadThe payload, parsed by the schema, transforms applied.
event, listenerThe names.
idThe message: the same for every attempt. Use it to ignore duplicates.
emissionIdThe emission, shared by the messages of its listeners.
attemptThe attempt number, from 1.
emittedAtThe date of the emission.
metadataThe metadata of the emission: requestId with the plugin.
loggerThe logger of the worker.

A handler throws to be retried.

createEventBus()

OptionDescription
listenersEvery listener of the app: the bus sends one message per listener of an emitted event.
transportThe transport of every event.
transportsInstead of transport: transports by name, default for the events without transport.
loggerAny logger with info, warn and error, and optionally debug. Silent by default.
onFailureFailures of the listeners run by the sync and memory transports.

The bus checks at startup that every listener has its transport. Names other than default are declared for type checking:

declare module '@dotpress/events' {
  interface EventTransports {
    edge: true
  }
}

emit()

const { emissionId, messages } = await events.emit(event, payload, { delay, metadata })
OptionDescription
delaySeconds before the listeners run, within the limit of the transport.
metadataStrings passed to the listeners. Keys: 1 to 128 characters among letters, digits, ., _ and -; values on one line.

messages lists one { id, listener, transport } per listener. An event without listeners is not sent. Each call is a new emission, with new message ids: emitting again after an EventEmitError runs again the listeners whose message was sent.

events.withContext({ logger, metadata }) returns a bus that logs with this logger and adds this metadata: ctx.events is one.

Transports in the process

TransportBehavior
createSyncTransport()Runs the listeners inside emit(), which waits for them and throws an EventEmitError when one fails. Delays are ignored.
createMemoryTransport(options?)An in-process queue with retries. Messages are lost when the process stops.
Option of the memory transportDefaultDescription
maxAttempts3Attempts of a message.
retryDelay(attempt)100 ms, doubled each attemptDelay before a retry, in milliseconds. () => 0 in tests.

The memory transport has sent (the envelopes sent), drain() (waits for every message, retries included) and clear().

createFakeEventBus() checks each emission like a real bus (event, payload, delay, metadata) without running listeners, and records it in emitted; clear() empties it. See Testing helpers.

createWorker()

OptionDescription
listenersThe listeners this worker runs.
loggerThe logger of the worker, given to the listeners.
onFailure(error, info)Called for every failure. Its own errors are logged and ignored.
maxAttemptsThe retry limit of the queue, so that the last attempt is reported as final.

info holds the envelope (undefined when the message is not one), the attempt, final (a dead message, or the last attempt), and the reason:

ReasonResultMeaning
listener-errorretryThe listener threw.
invalid-envelopedeadThe message is not an envelope of Dotpress.
unknown-listenerdeadThe worker does not run this listener: usually a deployment mistake.
invalid-payloaddeadThe payload does not match the current schema of the event.

worker.handle(message, { attempt }) returns success, retry or dead, and never throws: the entry points of the transports (Lambda handler, queue() handler…) are built on it.

startWorker(worker, source, { logger, signal }) reads a source until stopped, and returns { stop() }, which finishes the messages in progress.

eventsPlugin()

import { eventsPlugin } from '@dotpress/events/plugin'

await createApp({ adapter, plugins: [eventsPlugin(events)] })

The plugin, named events, provides ctx.events: the bus, with the request logger, and the requestId in the metadata. Using ctx.events without the plugin throws an explicit error.

Logs

LevelMessage
infoEvent emitted (event, emission id, number of messages); Event worker started, Event worker stopped
debugEvent emitted without listeners; Event listener succeeded
warnEvent listener failed, the message is retried
errorEvent listener failed, the message is not retried; onFailure hook failed

Payloads are never logged.

Errors

ErrorWhen
TypeErrorInvalid options of defineEvent(), defineListener(), createEventBus(), emit()…
EventPayloadErrorAt emit(): the payload does not match the schema, or is not serializable as JSON. Fields: event, issues.
EventEmitErrorSome messages could not be sent. Fields: sent, failed, cause.
PartialSendErrorFor transport authors: some messages of a send() call failed.

The error classes extend EventsError.

Custom transports

A transport has a kind and a send(envelopes, { delay }) method; a source has a kind and a consume(worker, { signal, logger }) method. Envelopes are plain JSON objects:

{ v: 1, id, emissionId, event, listener, payload, emittedAt, metadata }