eventdbxjs) is a native Node-API addon (via napi-rs) that speaks directly to the EventDBX control socket over TCP/Cap’n Proto. It targets Node.js services, serverless API routes, and any runtime that exposes standard TCP primitives.
Feature highlights
- JSON (de)serialisation for aggregate snapshots and event envelopes.
- RFC 6902 JSON Patch helpers baked into
client.patch. - Async/await-friendly API surface with Promise-based helpers.
- Automatic retries with configurable exponential backoff.
- Per-call overrides for tokens, metadata, patch operations, and archived filters.
- Cross-platform builds covering macOS, Linux, Windows, and WASI targets.
Install
Requires Node.js 18+ or any runtime that exposes WHATWG
fetch, Web Crypto
APIs, and raw TCP access to port 6363.Connect and configure
createClient falls back to environment variables when options are omitted. Set EVENTDBX_HOST, EVENTDBX_PORT, EVENTDBX_TOKEN, and EVENTDBX_TENANT_ID (for multi-tenant deployments) to avoid hardcoding credentials in code. The retry option enables exponential backoff without recreating the client.
Connection lifecycle tips
- Connect once per process and reuse the underlying TCP socket to avoid repeated TLS/token handshakes.
await client.disconnect()during graceful shutdown so the server releases cursors quickly.await client.isConnected()lets you guard re-use when hot reloading in development.
Serverless or Edge entry points
Next.js, Remix, Bun’s serverless runtime, or any environment that exposes TCP primitives).
Runtime configuration
| Variable | Default | Description |
|---|---|---|
EVENTDBX_HOST | 127.0.0.1 | Hostname or IP address of the control socket. |
EVENTDBX_PORT | 6363 | TCP port that hosts the control plane. |
EVENTDBX_TOKEN | empty | Authentication token that the client forwards on connect. |
EVENTDBX_TENANT_ID | empty | Tenant identifier included in the handshake. |
createClient. Multi-tenant deployments always require tenantId (or EVENTDBX_TENANT_ID) so the server routes control requests correctly.
Manage authentication and tenancy
Tokens and tenant identifiers can be set globally or per call. Every method that issues a request to the server accepts an optionaltoken, so you can scope permissions to an end-user session without recreating the client.
Retry configuration
Transport-level failures (socket resets, Cap’n Proto decode errors, etc.) can be retried automatically. Retries are disabled by default (attempts = 1), so opt in by setting the retry object:
maxDelayMs is hit. Logical server errors (validation failures, authorization errors, etc.) still bubble to your application immediately.
Write aggregates and events
create seeds a snapshot and first event atomically. apply appends new events. patch issues RFC 6902 operations against the requested historical payload, and archive/restore toggle write access while preserving history.
Read aggregates and events
get when you need the entire snapshot, select for sparse projections, list to traverse many aggregates, and events for CDC-style replay. All read methods share the same pagination helpers and filter grammar, returning a PageResult whose items contain either aggregates or event envelopes.
Filters, sorting, and pagination
Filters use the same SQL-like shorthand as the EventDBX server (field = value AND other_field > 10), and sort fields accept names such as aggregateType, aggregateId, version, merkleRoot, and archived. Each entry in PageResult.items is the aggregate snapshot or event payload returned by the control socket.
includeArchived, archivedOnly, and request-scoped token overrides are part of the PageOptions passed to list and events. Always feed the returned nextCursor back into the next call when you need to resume pagination after hitting server-side page limits.
When you sort aggregates by created_at or updated_at, you can use shorthand timestamp cursors with the same control socket used by eventdbxjs: pass cursor: "ts:<aggregate_type>:<aggregate_id>" alongside the timestamp sort and the server expands it into the full token (ts:<field>:<order>:<scope>:<timestamp_ms>:...) for you.
TypeScript surface area
The SDK exports helper types so you can strongly type payloads, retries, and pagination in your application.index.d.ts file still types aggregate and event payloads as any, but the runtime values follow the Aggregate and Event shapes above, so you can layer your own domain-specific interfaces on top.