@jumentix/persistence-contracts
Shared TypeScript contracts (IStore, IDatabaseClient, paging) that keep domain/application code free of database vendors.
What it is
Shared TypeScript contracts (IStore, IDatabaseClient, paging) that keep domain/application code free of database vendors.
Why it exists
Without shared ports, every adapter invents incompatible method names and paging shapes.
When to use: You write use-cases or adapters that read/write data through ports.
When not to use: You need a concrete Mongo class (external-db-repositories) or browser IndexedDB (Cana).
Responsibility in context
- Stack layer: persistence / ports (application boundary)
- Problem boundary it owns: Persistence port types only — no runtime drivers.
- Used with: Implemented by external-* packages and database-client-factory compositions.
- Typical composition: Application imports contracts; adapters implement them; guides wire backend-template.
- Journeys: Concepts architecture → REST guide → persistence adapters.
- Not responsible for: Connecting to databases, Redis, or HTTP.
Prerequisites
- Bun 1.3.13+ (monorepo pin) or the Node runtime your service already uses
- Read Getting started first
- Basic TypeScript modules/
importknowledge
Glossary
- Port — TypeScript contract the application depends on (no vendor types).
- Adapter — Concrete implementation that talks to a driver, broker, or protocol.
- Composition root — Process startup code that wires env → adapters → use-cases.
Numbered steps
1. Install
bun add @jumentix/persistence-contracts2. First success (under 30 min)
import type { IStore } from '@jumentix/persistence-contracts';
export async function listItems(store: IStore) {
return store.query({ /* paging / filter per contract */ });
}3. Core workflows
1. Type a use-case port
Accept IStore / IDatabaseClient in application code.
2. Keep adapters behind the port
Only adapters import mongoose/sequelize.
3. Share paging types
Use IPagingRequest / IPagingResponse across HTTP and DB.
4. Full practical surface (exports)
IStoreIDatabaseClientIPagingRequestIPagingResponse
Use exports from application/adapters layers as described above — not from domain entities.
Common errors
| Symptom | Cause | Fix |
|---|---|---|
| Domain imports mongoose | Wrong layer | Depend on these contracts instead. |
Verify success: the first-success snippet runs (or typechecks against your service) and your use-case depends only on ports.
Junior checklist (“I can …”)
- I can write a use-case against IStore without a driver
- I know which package implements the port at runtime
Next step
Continue with external-persistence-core.