Adapters
Database adapters for the event store — SQLite, in-memory, and custom.
Adapters persist PaymentEvent entries to the event store. The default is in-memory (lost on restart) — swap to a persistent adapter for production.
Comparison
| Memory (default) | SQLite | Custom / Bring-your-own | |
|---|---|---|---|
| Persists on restart | ❌ | ✅ | Depends on your impl |
| Zero dependencies | ✅ | ❌ (better-sqlite3) | Depends |
| Dev / CI ready | ✅ | ✅ | — |
| Production ready | ❌ | ✅ | ✅ |
Available adapters
SQLite (@borapesa/sqlite)
Zero-config persistent storage powered by better-sqlite3. The database file is created automatically at the given path.
pnpm add @borapesa/sqliteimport { SQLiteAdapter } from '@borapesa/sqlite';
const pesa = createPesa({
provider: new ClickPesaProvider({ ... }),
db: new SQLiteAdapter('./pesa.db'),
});WAL mode is enabled by default for concurrent read/write performance. See the @borapesa/sqlite API docs for full details.
@borapesa/sqlite is the only adapter package provided. For other databases, implement the interface yourself — the SQLiteAdapter source is the reference.
Writing your own
Implement PesaDatabaseAdapter — four methods:
import type { PesaDatabaseAdapter, PaymentEvent } from '@borapesa/pesa';
class MyAdapter implements PesaDatabaseAdapter {
async saveEvent(event: PaymentEvent): Promise<void> {
// Persist a verified PaymentEvent
}
async getEvent(id: string): Promise<PaymentEvent | null> {
// Retrieve a single event by UUID
}
async getEventsByReference(reference: string): Promise<PaymentEvent[]> {
// Retrieve all events for a merchant reference
}
async getEventsByOrderId(orderId: string): Promise<PaymentEvent[]> {
// Retrieve all events for a provider order ID
}
}Pass your adapter via the db field in PesaConfig:
const pesa = createPesa({
provider: new ClickPesaProvider({ ... }),
db: new MyAdapter(),
});See the Architecture page for how the event store fits into the webhook lifecycle.