@oglofus/drizzle-events
v0.0.5
Published
A lightweight, strongly-typed event management library for Drizzle ORM.
Maintainers
Readme
@oglofus/drizzle-events
A lightweight, type-safe event layer for Drizzle ORM operations. It lets you hook into CRUD lifecycles (pre/post insert, update, delete) to validate, transform, and optionally cancel operations, with optional automatic rollback for post-event cancellations.
Currently focuses on Drizzle SQLite via drizzle-orm/sqlite-core.
- Events: pre-insert, post-insert, pre-update, post-update, pre-delete, post-delete
- Cancel or modify payloads in pre events
- Optionally rollback changes if a post event is cancelled
- Deep merge support when updating JSON-like objects
Installation
npm install @oglofus/drizzle-events @oglofus/event-manager drizzle-ormThis library is ESM-only.
Quick start (SQLite)
import { sqliteTable, integer, text } from 'drizzle-orm/sqlite-core';
import { Database } from 'drizzle-orm/sqlite-core'; // your BaseSQLiteDatabase type/instance
import { SQLiteEventManager } from '@oglofus/drizzle-events/sqlite';
// Define a Drizzle table
export const users = sqliteTable('users', {
id: integer('id').primaryKey({ autoIncrement: true }),
email: text('email').notNull().unique(),
profile: text('profile') // JSON string in this simple example
});
// Create your Drizzle database instance "db" with sqlite driver of your choice
// const db: BaseSQLiteDatabase = ...
const events = new SQLiteEventManager(db, {
merge_objects: true, // Deep-merge objects on update
array_strategy: 'union', // Array merge strategy: 'replace' | 'concat' | 'union'
rollback_on_cancel: true // Rollback when a post-event is cancelled
});
// Add a pre-insert validation and transformation
events.put(users, 'pre-insert', (ev) => {
const data = ev.data;
if (!('email' in data) || typeof data.email !== 'string') {
ev.cancel('email is required');
return;
}
// Example transformation
ev.data = {
...data,
email: data.email.toLowerCase()
};
});
// Insert with events
const result = await events.insert(users, 'id', { email: '[email protected]' });
if (result.type === 'error') {
console.error('Insert failed:', result.message);
} else {
console.log('Inserted row:', result.data);
}API
SQLiteEventManager
new SQLiteEventManager(database, config)database: A Drizzle BaseSQLiteDatabase instanceconfig(optional):merge_objects: boolean— Deep-merge nested objects on update (default:true)array_strategy: 'replace' | 'concat' | 'union'— How to merge arrays whenmerge_objectsis enabled (default:union)rollback_on_cancel: boolean— If a post-event is cancelled, revert the change (default:true)
Methods:
insert(table, primary_field, data)- Emits
pre-insertwith a mutabledatapayload - On success, emits
post-insertwith the insertedrow - Returns
{ type: 'success', data: row }or{ type: 'error', message } - If
post-insertis cancelled androllback_on_cancelis true, the inserted row is deleted
- Emits
update(table, primary_field, primary_value, data)- Emits
pre-updatewith a mutabledataand the currentrow - If
merge_objectsis true, object fields indataare deep-merged into existing row values - On success, emits
post-updatewithrowandold_row - Returns
{ type: 'success', data: row }or{ type: 'error', message } - If
post-updateis cancelled androllback_on_cancelis true, reverts toold_row
- Emits
delete(table, primary_field, primary_value)- Emits
pre-deletewith the currentrow - On success, emits
post-deletewith the deletedrow - Returns
{ type: 'success', data: row }or{ type: 'error', message } - If
post-deleteis cancelled androllback_on_cancelis true, reinserts therow
- Emits
Registering handlers
events.put(table, type, handler, priority)type: one of'pre-insert' | 'post-insert' | 'pre-update' | 'post-update' | 'pre-delete' | 'post-delete'handler(event): function receiving a cancellable event objectpriority(optional): number (higher runs earlier). Uses priorities from@oglofus/event-manager.
Event objects share a common cancellable interface from @oglofus/event-manager:
event.cancel(reason?: string)— marks the event as cancelledevent.isCancelled()— returns booleanevent.getCancelReason()— string | undefined
Per event type:
pre-insert—event.data: insert payload (mutable)post-insert—event.row: inserted row (readonly)pre-update—event.data(mutable),event.row(current row before update)post-update—event.row(updated row),event.old_row(previous row)pre-delete—event.row(row to be deleted)post-delete—event.row(deleted row)
Deep merge behavior on update
When merge_objects is enabled (default), and you pass partial objects in data to update, nested objects are deep-merged with existing row values. Arrays use the configured array_strategy:
replace— replace existing array with the new oneconcat— concatenate arraysunion— unique set union (default)
Error handling
All public operations return a discriminated union:
type Response<T> =
| { type: 'success'; data: T }
| { type: 'error'; message?: string };Check result.type to branch success vs error.
Import paths
- Full package:
@oglofus/drizzle-events - SQLite module:
@oglofus/drizzle-events/sqlite - Base utilities/types:
@oglofus/drizzle-events/base
Examples:
import { SQLiteEventManager } from '@oglofus/drizzle-events/sqlite';
import { deepMerge } from '@oglofus/drizzle-events/base';Notes
- This package builds on top of
@oglofus/event-managerfor the core event system. - Current focus is SQLite; additional dialects can follow a similar pattern.
License
ISC © oglofus
