/**
 * Database wrapper with duck-typed interface.
 *
 * Accepts any client with a query(text, values) method.
 * Both `pg.Pool` and `@electric-sql/pglite` satisfy this interface.
 *
 * Transaction safety is provided by an injected `transaction` callback —
 * the driver adapters (`db/db_pg.ts`, `db/db_pglite.ts`) supply the driver-appropriate
 * implementation. Close is handled externally (returned alongside the `Db`
 * as `DbDriverResult`), not as a method on this class.
 *
 * @module
 */
/**
 * Sentinel transaction function for transaction-scoped `Db` instances.
 *
 * Used by driver adapters when constructing the inner `Db` passed
 * to transaction callbacks.
 *
 * @throws Error always — nested transactions are not supported
 */
export const no_nested_transaction = () => {
    throw new Error('Nested transactions are not supported');
};
/**
 * Database wrapper providing a consistent query and transaction interface.
 *
 * Construct via `create_pg_db()` from `db/db_pg.ts` or `create_pglite_db()` from
 * `db/db_pglite.ts` for proper transaction support, or via `create_db()` for
 * URL-based auto-detection.
 *
 * @example
 * ```ts
 * const {db, close} = await create_db('postgres://...');
 * const users = await db.query<User>('SELECT * FROM users WHERE active = $1', [true]);
 * await db.transaction(async (tx) => {
 *   await tx.query('INSERT INTO users ...');
 *   await tx.query('INSERT INTO audit_log ...');
 * });
 * await close();
 * ```
 */
export class Db {
    client;
    #transaction;
    constructor(options) {
        this.client = options.client;
        this.#transaction = options.transaction;
    }
    /**
     * Execute a query and return all rows.
     *
     * @param text - SQL text with `$1`, `$2`, ... parameter placeholders
     * @param values - parameter values bound to the placeholders in `text`
     * @returns the result rows, typed as `T`
     */
    async query(text, values) {
        const result = await this.client.query(text, values);
        return result.rows;
    }
    /**
     * Execute a query and return the first row, or `undefined` if no rows.
     *
     * @param text - SQL text with `$1`, `$2`, ... parameter placeholders
     * @param values - parameter values bound to the placeholders in `text`
     * @returns the first row, or `undefined` when the result set is empty
     */
    async query_one(text, values) {
        const rows = await this.query(text, values);
        return rows[0];
    }
    /**
     * Run a function inside a database transaction.
     *
     * The callback receives a transaction-scoped `Db`. Queries inside the callback
     * go through the transaction connection; queries outside use the pool normally.
     * Commits on success, rolls back on error.
     *
     * @param fn - async function receiving a transaction-scoped `Db`
     * @returns the value returned by `fn`
     * @throws Error propagated from `fn` after `ROLLBACK`, or from the driver
     *   if `BEGIN` / `COMMIT` / `ROLLBACK` itself fails
     */
    async transaction(fn) {
        return this.#transaction(fn);
    }
}
