Skip to content

Database

Zelavis includes a database core service with documents, events, schemas, projections, and time-series. Application code should usually access it through the Zelavis runtime as zv.db.

The database core service is enabled by default:

import { Zelavis } from 'zelavis';
const zv = new Zelavis({
adapter,
});
import { Zelavis } from 'zelavis';
const zv = new Zelavis();
await zv.db.documents.createCollection({ name: 'posts' });
const doc = await zv.db.documents.insert({
collection: 'posts',
data: { title: 'Hello', published: false },
});
const found = await zv.db.documents.findById({
collection: 'posts',
id: doc.id,
});
await zv.db.documents.update({
collection: 'posts',
id: doc.id,
data: { published: true },
mode: 'merge', // or 'replace'
});
await zv.db.documents.delete({ collection: 'posts', id: doc.id });

zv.db resolves to the same database API instance mounted by the Zelavis runtime, so dashboard routes, services, and application code share one database service.

zv.db exposes scoped APIs for each database capability.

PropertyTypeDescription
documentsDatabaseDocumentsApiCRUD operations on JSON documents.
eventsDatabaseEventsApiAppend-only event log.
schemasDatabaseSchemasApiCollection schema registry.
projectionsDatabaseProjectionsApiEvent-driven read model projections.
timeseriesDatabaseTimeSeriesApiTime-series data derived from events.
sqlSqlDatabase | undefinedRaw SQL access. Only available on drivers that support it.
capabilitiesDatabaseCapabilitiesFeature flags reported by the active driver.
contextDatabaseContextRuntime context (tenant, node, config).
driverDatabaseDriverThe underlying driver instance.
zv.db.documents.createCollection(input): Promise<DatabaseCollection>
zv.db.documents.listCollections(input?): Promise<DatabaseCollection[]>
zv.db.documents.collectionExists(input): Promise<boolean>
zv.db.documents.insert<TData>(input): Promise<DatabaseDocument<TData>>
zv.db.documents.findById(input): Promise<DatabaseDocument | null>
zv.db.documents.findMany(input): Promise<DatabaseDocument[]>
zv.db.documents.update<TData>(input): Promise<DatabaseDocument<TData>>
zv.db.documents.delete(input): Promise<boolean>

Documents are JSON objects stored in named collections. Each document gets an auto-generated id unless one is provided.

await zv.db.documents.createCollection({ name: 'posts' });
const doc = await zv.db.documents.insert({
collection: 'posts',
data: { title: 'Hello', published: false },
});
const found = await zv.db.documents.findById({
collection: 'posts',
id: doc.id,
});
await zv.db.documents.update({
collection: 'posts',
id: doc.id,
data: { published: true },
mode: 'merge', // or 'replace'
});
await zv.db.documents.delete({ collection: 'posts', id: doc.id });
zv.db.events.append<TPayload>(input): Promise<DatabaseEvent<TPayload>>
zv.db.events.read(input?): Promise<DatabaseEvent[]>

The event log is append-only. Events are the source of truth for projections and time-series.

await zv.db.events.append({
type: 'post.published',
payload: { postId: '123', at: Date.now() },
});
zv.db.schemas.register(schema): Promise<DatabaseCollectionSchema>
zv.db.schemas.registerMany(schemas): Promise<void>
zv.db.schemas.listCollections(): DatabaseCollectionSchemaSummary[]
zv.db.schemas.listVersions(collection): DatabaseCollectionSchema[]
zv.db.schemas.getActiveSchema(collection): DatabaseCollectionSchema | null
zv.db.schemas.activate(collection, version): Promise<DatabaseCollectionSchema>
zv.db.schemas.validate(input): ValidateDatabaseDocumentResult

Schemas describe the shape of documents in a collection. Multiple versions can coexist; one version is active at a time.

await zv.db.schemas.register({
collection: 'posts',
version: 1,
activate: true,
document: {
type: 'object',
properties: {
title: { type: 'string' },
published: { type: 'boolean' },
},
required: ['title'],
},
});
zv.db.projections.register(definition): Promise<void>
zv.db.projections.list(): Promise<DatabaseProjectionSummary[]>
zv.db.projections.rebuild(input?): Promise<DatabaseProjectionRebuildResult>

Projections consume events and maintain derived state. Rebuilding replays the event log from the beginning.

await zv.db.projections.register({
name: 'published-posts',
source: { eventTypes: ['post.published'] },
apply: async (event) => {
await zv.db.documents.update({
collection: 'posts',
id: event.payload.postId,
data: { published: true },
mode: 'merge',
});
},
});
zv.db.timeseries.define(definition): Promise<void>
zv.db.timeseries.list(): Promise<DatabaseTimeSeriesSummary[]>
zv.db.timeseries.get(name): DatabaseTimeSeriesHandle

Time-series are defined by mapping events to data points. Once defined, use the handle returned by get to query ranges or aggregates.

await zv.db.timeseries.define({
name: 'publish-rate',
source: { eventTypes: ['post.published'] },
map: (event) => ({
timestamp: event.payload.at,
value: 1,
}),
});
const handle = await zv.db.timeseries.get('publish-rate');
const points = await handle.range({ order: 'desc', limit: 50 });
const total = await handle.aggregate({ op: 'count' });
MethodDescription
range(input?)Returns raw data points. Supports start, end, limit, order.
aggregate(input)Returns a single number. op is one of avg, sum, min, max, count.