# `factory/create-db-adapter` — direct-surface adapter factory _(no submodules)_ ## Purpose `createDbAdapter` is the public entry point for host code that wants to wire the `@suaveplan/db` engine adapters to the plugin `AdminDatabaseLike` / `TenantScopedDatabaseLike` surfaces. It composes three pieces from this package — the options validator, the engine registry, and the tenant-scope wrapper — into a single callable that delegates engine identity to the open `DatabaseEngineRegistry`. The result object exposes: - `admin` — the unscoped `AdminDatabaseLike` (used by migrations and admin endpoints). - `scoped(tenantId)` — produces a fresh `TenantScopedDatabaseLike` wrapper over the same admin connection. The wrapper is stateless beyond the rewrite contract, so one admin connection can back many tenant scopes concurrently. - `close()` — closes the underlying admin connection. ## Features - Options are parsed once at factory time; the rest of the API is typed against the *post-parse* `DbAdapterOptions`. - Engine lookup is delegated to `buildEngineAdapter`, so any declaration-merged engine works automatically. - Tenant scoping config (`tenantColumn`, `autoInjectInserts`) flows from the parsed options into every `scoped()` call — no per-call repetition. ## Usage: Basic ```ts import { createDbAdapter } from "@suaveplan/api-db-adapter/adapter"; import { registerEngine } from "@suaveplan/api-db-adapter/engine-registry"; registerEngine("sqlite", buildSqliteEngineFactory()); const db = await createDbAdapter({ engine: "sqlite", url: ":memory:" }); const admin = db.admin; const acme = db.scoped("acme" as TenantId); const rows = await acme.query("SELECT * FROM users"); await db.close(); ``` ## Usage: Advanced ```ts const db = await createDbAdapter({ engine: "postgres", url: "postgres://app@db.local/app", tenantColumn: "org_id", autoInjectInserts: false, pool: { min: 2, max: 16, idleMs: 60_000 }, }); const tx = await db.scoped(tenantId).transaction!(async (tx) => { await tx.execute( "INSERT INTO invoices (id, org_id, amount) VALUES (?, ?, ?)", ["inv_1", tenantId, 100] ); return await tx.query<{ id: string }[]>("SELECT id FROM invoices"); }); ``` ## API Reference - `createDbAdapter(input: DbAdapterOptionsInput): Promise`. - `DbAdapter.admin: AdminDatabaseLike`. - `DbAdapter.scoped(tenantId: TenantId): TenantScopedDatabaseLike`. - `DbAdapter.close(): Promise`. ## Implementation Notes The factory does NOT register engines on import — it expects the host or a downstream adapter package to populate the registry before the first call. This shape keeps `@suaveplan/api-db-adapter` universally importable and prevents engine deps from leaking into bundles that never use them. Errors surface synchronously where possible (options validation, engine lookup); engine handshake errors arrive as the promise rejection.