Drizzle ORM & Generator
@kalamdb/orm is the Drizzle package for KalamDB. Use it when you want generated tables, typed queries, or table-level live helpers. It runs on top of @kalamdb/client.
Install it with the client and Drizzle:
npm i @kalamdb/client @kalamdb/orm drizzle-ormDriver quick start
Copy this after you have a generated schema.ts file.
import { Auth, createClient } from '@kalamdb/client';
import { kalamDriver } from '@kalamdb/orm';
import { messages } from './schema';
const client = createClient({
url: 'http://localhost:8080',
authProvider: async () => Auth.basic('admin', 'AdminPass123!'),
});
const db = kalamDriver(client);
const recent = await db.select().from(messages).limit(20);The driver uses KalamDB SQL over HTTP and normalizes temporal values for Drizzle columns. timestamp(..., { mode: 'date' }), date(..., { mode: 'date' }), and time(...) can read KalamDB’s numeric wire values without app-side parsing.
Table helpers
Use kTable instead of raw pgTable so the schema retains KalamDB table type metadata.
import { bytes, embedding, file, kTable } from '@kalamdb/orm';
import { bigint, jsonb, text, timestamp, uuid } from 'drizzle-orm/pg-core';
export const docs = kTable.shared('app.docs', {
id: bigint('id', { mode: 'bigint' }).primaryKey(),
owner_id: uuid('owner_id').notNull(),
title: text('title').notNull(),
metadata: jsonb('metadata'),
attachment: file('attachment'),
raw_bytes: bytes('raw_bytes'),
doc_embedding: embedding('doc_embedding', 384),
created_at: timestamp('created_at', { mode: 'date' }).notNull(),
});Available table helpers:
| Helper | Use for |
|---|---|
kTable.shared(name, columns, options?) | WITH (TYPE = 'SHARED') tables |
kTable.user(name, columns, options?) | per-user isolated tables |
kTable.stream(name, columns, options?) | stream tables |
kTable.system(name, columns, options?) | system metadata tables |
kSystemColumns([...]) | _seq, _deleted, and _commit_seq typed hidden columns |
KalamDB-specific columns:
| Helper | Runtime value |
|---|---|
file(name) | `FileRef |
bytes(name) | `Uint8Array |
embedding(name, dimensions) | `number[] |
Generate schema.ts
Generate a Drizzle schema from a running KalamDB server:
npx kalamdb-orm \
--url http://localhost:8080 \
--user admin \
--password AdminPass123! \
--namespace app \
--include-system-columns \
--out src/db/schema.tsThe generator reads SHOW TABLES, calls DESCRIBE <namespace.table> when column metadata is incomplete, and emits only the imports needed by the generated tables. It preserves primary keys, not-null constraints, system-column options, comments, table config constants such as chat_messagesConfig, and $inferSelect / $inferInsert aliases.
Options:
| Option | Description |
|---|---|
--namespace <name> | Limit output to one or more namespaces. Repeat it or pass comma-separated names. |
--include-system | Include system and dba tables. |
--include-system-columns <mode> | Add typed hidden columns to generated table definitions. Use all, _seq, or _deleted. |
--bigint-mode <mode> | Choose how generated BIGINT columns are emitted. Accepted values are string, bigint, or number; default is string. |
--no-type-aliases | Skip generated $inferSelect and $inferInsert aliases. |
BIGINT defaults to text() because KalamDB transports Int64 values as strings to preserve precision. Choose --bigint-mode bigint when you want Drizzle to coerce values to native bigint, or --bigint-mode number only when values fit safely in JavaScript numbers.
Exact KalamDB datatype mapping
| KalamDB type | Generated Drizzle helper | Read behavior |
|---|---|---|
BOOLEAN | boolean() | boolean |
INT | integer() | number |
SMALLINT | smallint() | number |
BIGINT | text() by default | string for Int64 precision |
DOUBLE | doublePrecision() | number |
FLOAT | real() | number |
TEXT | text() | string |
TIMESTAMP | timestamp(..., { mode: 'date' }) | Date when using date mode |
DATETIME | timestamp(..., { mode: 'date' }) | Date when using date mode |
DATE | date(..., { mode: 'date' }) | UTC-date Date |
TIME | time() | HH:mm:ss[.fraction] string |
JSON | jsonb() | JSON value |
BYTES | bytes() | Uint8Array |
EMBEDDING(n) | embedding(name, n) | number[] |
UUID | uuid() | UUID string |
DECIMAL(p,s) | numeric() | exact decimal string |
FILE | file() | `FileRef |
Live table helpers
Use liveTable() for React state, dashboards, and admin UI screens that want the current materialized row set.
import { liveTable } from '@kalamdb/orm';
import { messages } from './schema';
const stop = await liveTable(client, messages, (rows) => {
setRows(rows);
}, {
subscriptionOptions: { last_rows: 100 },
});
await stop();Use subscribeTable() when you need lower-level change callbacks. Both helpers reuse the same @kalamdb/client connection and normalize timestamp/date/time fields from the Drizzle table metadata.
UI and example fit
Use this package in UI code or service code that wants typed tables. Worker code should import @kalamdb/consumer only when it needs topic consumption.
Copy This Project Shape
src/
db/
schema.ts # generated by kalamdb-orm
client.ts # createClient() + kalamDriver(client)
app/
messages.ts # Drizzle queries against generated tables