import { sql } from 'drizzle-orm';
import { ZQLDatabase } from "../zql-database.js";
export class DrizzleConnection {
    #drizzle;
    constructor(drizzle) {
        this.#drizzle = drizzle;
    }
    transaction(fn) {
        return this.#drizzle.transaction(drizzleTx => fn(new DrizzleInternalTransaction(drizzleTx)));
    }
}
class DrizzleInternalTransaction {
    wrappedTransaction;
    constructor(drizzleTx) {
        this.wrappedTransaction = drizzleTx;
    }
    async query(sql, params) {
        const stmt = fromDollarParams(sql, params);
        const result = await this.wrappedTransaction.execute(stmt);
        return toIterableRows(result);
    }
}
/**
 * Turn `$1, $2...` placeholders into a Drizzle SQL object with bound params.
 */
export function fromDollarParams(text, params) {
    const re = /\$(\d+)/g;
    const s = sql.empty();
    let last = 0;
    let m;
    while ((m = re.exec(text)) !== null) {
        const idx = Number(m[1]) - 1;
        if (idx < 0 || idx >= params.length) {
            throw new Error(`Missing param for $${m[1]}`);
        }
        if (m.index > last)
            s.append(sql.raw(text.slice(last, m.index)));
        s.append(sql `${params[idx]}`); // parameterized value
        last = m.index + m[0].length;
    }
    if (last < text.length)
        s.append(sql.raw(text.slice(last)));
    return s;
}
function isIterable(value) {
    return (
    // oxlint-disable-next-line eqeqeq
    value != null &&
        typeof value[Symbol.iterator] === 'function');
}
export function toIterableRows(result) {
    if (result === null || result === undefined) {
        return [];
    }
    if (Array.isArray(result)) {
        return result;
    }
    if (isIterable(result)) {
        return result;
    }
    if (typeof result === 'object') {
        const rows = result.rows;
        if (rows === null || rows === undefined) {
            return [];
        }
        if (Array.isArray(rows)) {
            return rows;
        }
        if (isIterable(rows)) {
            return rows;
        }
    }
    throw new TypeError('Drizzle query result is not iterable');
}
/**
 * Wrap a `drizzle-orm` database for Zero ZQL.
 *
 * Provides ZQL querying plus access to the underlying drizzle transaction.
 * Use {@link DrizzleTransaction} to type your server mutator transaction.
 *
 * @param schema - Zero schema.
 * @param client - Drizzle database.
 *
 * @example
 * ```ts
 * import {Pool} from 'pg';
 * import {drizzle} from 'drizzle-orm/node-postgres';
 * import type {ServerTransaction} from '@rocicorp/zero';
 *
 * const pool = new Pool({connectionString: process.env.ZERO_UPSTREAM_DB!});
 * const drizzleDb = drizzle(pool, {schema: drizzleSchema});
 *
 * const zql = zeroDrizzle(schema, drizzleDb);
 *
 * // Define the server mutator transaction type using the helper
 * type ServerTx = ServerTransaction<Schema, DrizzleTransaction<typeof drizzleDb>>;
 *
 * async function createUser(
 *   tx: ServerTx,
 *   {id, name}: {id: string; name: string},
 * ) {
 *   await tx.dbTransaction.wrappedTransaction
 *     .insert(drizzleSchema.user)
 *     .values({id, name})
 * }
 * ```
 */
export function zeroDrizzle(schema, client) {
    return new ZQLDatabase(new DrizzleConnection(client), schema);
}
//# sourceMappingURL=drizzle.js.map