@ooneex/database component is the connection layer for relational and key-value stores. PostgreSQL and SQLite adapters extend TypeormDatabase and hand you a typed TypeORM Repository per entity; RedisDatabase wraps Bun’s native Redis client. Every adapter exposes the same lifecycle — open, close, drop — and registers with the container through @decorator.database().
Why this component
- One lifecycle, several engines.
open,close, anddropmean the same thing whether you target Postgres, SQLite, or Redis. - Typed repositories.
open(Entity)returns a TypeORMRepository<Entity>with full query-builder and entity-manager access. - Connection reuse. Adapters cache their
DataSourceand only initialize it once, so repeatedopencalls share a single pool. - Container-managed. Register an adapter with
@decorator.database()and resolve it from the container for dependency injection. - Config from the environment. Connection details come from
AppEnv(DATABASE_URL,DATABASE_REDIS_URL,SQLITE_DATABASE_PATH) or from explicit options.
How it works
You pick (or scaffold) an adapter and register it. Relational adapters extend the abstractTypeormDatabase and implement a single getSource() that builds a TypeORM DataSource; the base class handles initialization, repositories, transactions, and teardown. The Redis adapter constructs a Bun RedisClient from a connection URL.
| Method | Engine | Purpose |
|---|---|---|
open<Entity>(entity, database?) | Postgres / SQLite | Initialize the DataSource if needed and return a Repository<Entity>. |
open() | Redis | Connect (if not already) and return the Bun RedisClient. |
close() | All | Destroy the DataSource / close the Redis connection. |
drop() | All | Drop the database schema (FLUSHDB for Redis). Destructive. |
getEntityManager(database?) | Postgres / SQLite | Return the TypeORM EntityManager for transactions. |
getSource(database?) | Postgres / SQLite | Build (and cache) the underlying DataSource. |
getClient() | Redis | Return the underlying Bun RedisClient. |
| Adapter | Engine | Best for | Returns from open |
|---|---|---|---|
TypeormPgDatabase | PostgreSQL (TypeORM) | Production relational data, connection pooling | Repository<Entity> |
TypeormSqliteDatabase | SQLite via better-sqlite3 (TypeORM) | Local development, embedded and analytics stores | Repository<Entity> |
RedisDatabase | Redis (Bun client) | Caching, sessions, ephemeral key-value data | RedisClient |
VectorDatabase adapter ships in @ooneex/rag and is scaffolded with vector-database:create (see the CLI command below).
synchronize defaults to false on every relational adapter — schema changes go through migrations, not auto-sync. Adapters cache their DataSource, so call close() when you are done to release the pool.
Environment variables
| Variable | Adapter | Required | Purpose |
|---|---|---|---|
DATABASE_URL | TypeormPgDatabase | Yes (unless passed in config) | Postgres connection string, e.g. postgres://user:pass@localhost:5432/app. Missing throws DatabaseException (CONNECTION_FAILED). |
SQLITE_DATABASE_PATH | TypeormSqliteDatabase | Yes (unless passed in config) | Path to the SQLite database file, e.g. var/db. Missing throws DatabaseException (CONNECTION_FAILED). |
DATABASE_REDIS_URL | RedisDatabase | Yes (unless passed in config) | Redis connection string, e.g. redis://localhost:6379. Missing throws DatabaseException (CONNECTION_FAILED). |
database.url, database.sqlite.path, and database.redis.url keys in the app’s env configuration.
Usage
A relational adapter implementsgetSource() and inherits the lifecycle. Resolve it from the container, then open() per entity to get a repository:
RedisDatabase hands you Bun’s native client:
Decorator and usage
@decorator.database()
Registers a database adapter with the container. It accepts an optional scope (defaults to singleton). Use it on an adapter that extends TypeormDatabase (Postgres/SQLite) or RedisDatabase.
Exceptions
The component throwsDatabaseException when an adapter is misconfigured or an operation fails. It carries a machine-readable key, a human-readable message, a data object, and a 500 HTTP status.
| Key | When |
|---|---|
CONNECTION_FAILED | A required connection setting is missing — no DATABASE_URL, SQLITE_DATABASE_PATH, or DATABASE_REDIS_URL (and none passed in config). |
OPERATION_FAILED | A Redis open, close, or drop call failed at runtime. The data carries the connection URL and underlying error. |
Best practices
- Keep
synchronizeoff. Evolve the schema through migrations, not auto-sync, so changes are reviewable and reversible. - Reuse the cached source. Resolve adapters from the container as singletons and let them cache the
DataSource— don’t build a new connection per request. - Close what you open. Call
close()on shutdown (or when a one-off adapter is done) to release the pool and Redis socket. - Guard
drop(). It destroys data (FLUSHDBon Redis); never call it against a shared or production database. - Configure from the environment. Read connection details from
AppEnvso the same code runs across dev, test, and production. - Use the entity manager for transactions. Wrap multi-entity writes in
manager.transaction()so they commit or roll back together. - Throw
DatabaseExceptionwith a stablekey. In custom adapters, keep keys constant (CONNECTION_FAILED,OPERATION_FAILED) and put variable detail indata.
CLI command
Scaffold a database adapter and its test file with the generator. It prompts for the engine (postgres, sqlite, or redis), writes the class under modules/<module>/src/databases/<Name>Database.ts, generates a matching spec, and installs @ooneex/database if it is missing.
| Option | Description | Default |
|---|---|---|
--name | Database class name. The Database suffix is appended automatically. | Prompted if omitted |
--module | Target module the class is generated into. | shared |
--override | Overwrite an existing class without prompting. | false |
DataSource:
ooneex vector-database:create scaffolds a VectorDatabase adapter (from @ooneex/rag) with an embedding model and Arrow schema. See database:create and vector-database:create for the full command references.
Use with Claude and Codex
The generator ships matchingdatabase:create and database:migrate skills. They run the scaffold and then guide your AI agent through completing the adapter — registering entities, configuring the DataSource, and applying migrations. Initialize the skills once for your agent:
- Claude
- Codex
Prompt
database:create --name=App with the postgres engine, then registers your entities on the DataSource.