genesisdb
v1.1.4
Published
GenesisDB SDK
Maintainers
Readme
JavaScript/TypeScript SDK
This is the official JS/TS SDK for GenesisDB, an awesome and production ready event store database system for building event-driven apps.
GenesisDB Advantages
- Incredibly fast when reading, fast when writing 🚀
- Easy backup creation and recovery
- CloudEvents compatible
- GDPR-ready
- Easily accessible via the HTTP interface
- Auditable. Guarantee database consistency
- Logging and metrics for Prometheus
- SQL like query language called GenesisDB Query Language (GDBQL)
- ...
Installation
npm install genesisdbConfiguration
Environment Variables
The following environment variables are required:
GENESISDB_AUTH_TOKEN=<secret>
GENESISDB_API_URL=http://localhost:8080
GENESISDB_API_VERSION=v1Basic Setup
import { Client } from 'genesisdb';
// Initialize the GenesisDB client
const client = new Client();Streaming Events
Basic Event Streaming
// Stream all events for a subject
await client.streamEvents('/customer');Stream Events from Lower Bound
await client.streamEvents('/', {
lowerBound: '2d6d4141-6107-4fb2-905f-445730f4f2a9',
includeLowerBoundEvent: true
});Stream Events with Upper Bound
await client.streamEvents('/', {
upperBound: '9f3e4141-7208-4fb2-905f-445730f4f3b1',
includeUpperBoundEvent: false
});Stream Events with Both Lower and Upper Bounds
await client.streamEvents('/', {
lowerBound: '2d6d4141-6107-4fb2-905f-445730f4f2a9',
includeLowerBoundEvent: true,
upperBound: '9f3e4141-7208-4fb2-905f-445730f4f3b1',
includeUpperBoundEvent: false
});Stream Latest Events by Event Type
await client.streamEvents('/', {
latestByEventType: 'io.genesisdb.app.customer-updated'
});This feature allows you to stream only the latest event of a specific type for each subject. Useful for getting the current state of entities.
Committing Events
Basic Event Committing
await client.commitEvents([
{
source: 'io.genesisdb.app',
subject: '/customer',
type: 'io.genesisdb.app.customer-added',
data: {
firstName: 'Bruce',
lastName: 'Wayne',
emailAddress: '[email protected]'
}
},
{
source: 'io.genesisdb.app',
subject: '/customer',
type: 'io.genesisdb.app.customer-added',
data: {
firstName: 'Alfred',
lastName: 'Pennyworth',
emailAddress: '[email protected]'
}
},
{
source: 'io.genesisdb.store',
subject: '/article',
type: 'io.genesisdb.store.article-added',
data: {
name: 'Tumbler',
color: 'black',
price: 2990000.00
}
},
{
source: 'io.genesisdb.app',
subject: '/customer/fed2902d-0135-460d-8605-263a06308448',
type: 'io.genesisdb.app.customer-personaldata-changed',
data: {
firstName: 'Angus',
lastName: 'MacGyver',
emailAddress: '[email protected]'
}
}
]);Preconditions
Preconditions allow you to enforce certain checks on the server before committing events. GenesisDB supports multiple precondition types:
isSubjectNew
Ensures that a subject is new (has no existing events):
await client.commitEvents([
{
source: 'io.genesisdb.app',
subject: '/user/456',
type: 'io.genesisdb.app.user-created',
data: {
firstName: 'John',
lastName: 'Doe',
email: '[email protected]'
}
}
], [
{
type: 'isSubjectNew',
payload: {
subject: '/user/456'
}
}
]);isSubjectExisting
Ensures that events exist for the specified subject:
await client.commitEvents([
{
source: 'io.genesisdb.app',
subject: '/user/456',
type: 'io.genesisdb.app.user-created',
data: {
firstName: 'John',
lastName: 'Doe',
email: '[email protected]'
}
}
], [
{
type: 'isSubjectExisting',
payload: {
subject: '/user/456'
}
}
]);isQueryResultTrue
Evaluates a query and ensures the result is truthy. Supports the full GDBQL feature set including complex WHERE clauses, aggregations, and calculated fields.
Basic uniqueness check:
await client.commitEvents([
{
source: 'io.genesisdb.app',
subject: '/user/456',
type: 'io.genesisdb.app.user-created',
data: {
firstName: 'John',
lastName: 'Doe',
email: '[email protected]'
}
}
], [
{
type: 'isQueryResultTrue',
payload: {
query: "STREAM e FROM events WHERE e.data.email == '[email protected]' MAP COUNT() == 0"
}
}
]);Business rule enforcement (transaction limits):
await client.commitEvents([
{
source: 'io.genesisdb.banking',
subject: '/user/123/transactions',
type: 'io.genesisdb.banking.transaction-processed',
data: {
amount: 500.00,
currency: 'EUR'
}
}
], [
{
type: 'isQueryResultTrue',
payload: {
query: "STREAM e FROM events WHERE e.subject UNDER '/user/123' AND e.type == 'transaction-processed' AND e.time >= '2024-01-01T00:00:00Z' MAP SUM(e.data.amount) + 500 <= 10000"
}
}
]);Complex validation with aggregations:
await client.commitEvents([
{
source: 'io.genesisdb.events',
subject: '/conference/2024/registrations',
type: 'io.genesisdb.events.registration-created',
data: {
attendeeId: 'att-789',
ticketType: 'premium'
}
}
], [
{
type: 'isQueryResultTrue',
payload: {
query: "STREAM e FROM events WHERE e.subject UNDER '/conference/2024/registrations' AND e.type == 'registration-created' GROUP BY e.data.ticketType HAVING e.data.ticketType == 'premium' MAP COUNT() < 50"
}
}
]);Supported GDBQL Features in Preconditions:
- WHERE conditions with AND/OR/IN/BETWEEN operators
- Hierarchical subject queries (UNDER, DESCENDANTS)
- Aggregation functions (COUNT, SUM, AVG, MIN, MAX)
- GROUP BY with HAVING clauses
- ORDER BY and LIMIT clauses
- Calculated fields and expressions
- Nested field access (e.data.address.city)
- String concatenation and arithmetic operations
If a precondition fails, the commit returns HTTP 412 (Precondition Failed) with details about which condition failed.
GDPR Compliance
Store Data as Reference
await client.commitEvents([
{
source: 'io.genesisdb.app',
subject: '/user/456',
type: 'io.genesisdb.app.user-created',
data: {
firstName: 'John',
lastName: 'Doe',
email: '[email protected]'
},
options: {
storeDataAsReference: true
}
}
]);Delete Referenced Data
await client.eraseData('/user/456');Observing Events
Basic Event Observation
const encoder = new TextEncoder()
const stream = new ReadableStream({
async start(controller) {
try {
for await (const event of client.observeEvents('/customer')) {
controller.enqueue(encoder.encode(JSON.stringify(event) + '\n'))
}
} catch (err) {
console.error('Error:', err)
controller.close()
}
}
})Observe Events from Lower Bound (Message Queue)
for await (const event of client.observeEvents('/customer', {
lowerBound: '2d6d4141-6107-4fb2-905f-445730f4f2a9',
includeLowerBoundEvent: true
})) {
console.log('Received event:', event)
}Observe Events with Upper Bound (Message Queue)
for await (const event of client.observeEvents('/customer', {
upperBound: '9f3e4141-7208-4fb2-905f-445730f4f3b1',
includeUpperBoundEvent: false
})) {
console.log('Received event:', event)
}Observe Events with Both Bounds (Message Queue)
for await (const event of client.observeEvents('/customer', {
lowerBound: '2d6d4141-6107-4fb2-905f-445730f4f2a9',
includeLowerBoundEvent: true,
upperBound: '9f3e4141-7208-4fb2-905f-445730f4f3b1',
includeUpperBoundEvent: false
})) {
console.log('Received event:', event)
}Observe Latest Events by Event Type (Message Queue)
for await (const event of client.observeEvents('/customer', {
latestByEventType: 'io.genesisdb.app.customer-updated'
})) {
console.log('Received latest event:', event)
}Querying Events
const results = await client.queryEvents('STREAM e FROM events WHERE e.type == "io.genesisdb.app.customer-added" ORDER BY e.time DESC LIMIT 20 MAP { subject: e.subject, firstName: e.data.firstName }');
console.log('Query results:', results);Health Checks
// Check API status
const pingResponse = await client.ping();
console.log('Ping response:', pingResponse);
// Run audit to check event consistency
const auditResponse = await client.audit();
console.log('Audit response:', auditResponse);License
MIT
Author
- E-Mail: [email protected]
- URL: https://www.genesisdb.io
- Docs: https://docs.genesisdb.io
