/**
 * NativeDbProxy — wraps a NativeDatabase (rusqlite via napi-rs) to satisfy the
 * BetterSqlite3Database interface.  When the native addon is available, the
 * build pipeline uses this proxy as `ctx.db` so that every stage operates on a
 * single rusqlite connection — no dual-connection WAL corruption, no
 * open/close/reopen dance.
 *
 * When native is unavailable, the pipeline falls back to real better-sqlite3.
 */
/** Sanitize params for napi-rs: better-sqlite3 treats `undefined` as NULL,
 *  but serde_json cannot represent `undefined`. Replace with `null`. */
function sanitize(params) {
    return params.map((p) => (p === undefined ? null : p));
}
export class NativeDbProxy {
    #ndb;
    /** Advisory lock path — set by the pipeline so closeDb() can release it. */
    __lockPath;
    constructor(nativeDb) {
        this.#ndb = nativeDb;
    }
    prepare(sql) {
        const ndb = this.#ndb;
        // Only INSERT statements need last_insert_rowid — skip the extra napi
        // call for UPDATE/DELETE/other DML to halve per-statement overhead.
        const isInsert = sql.trimStart().substring(0, 6).toUpperCase() === 'INSERT';
        const stmt = {
            all(...params) {
                return ndb.queryAll(sql, sanitize(params));
            },
            get(...params) {
                return (ndb.queryGet(sql, sanitize(params)) ?? undefined);
            },
            run(...params) {
                ndb.queryAll(sql, sanitize(params));
                if (isInsert) {
                    const row = ndb.queryGet('SELECT last_insert_rowid() AS rid', []);
                    return { changes: 0, lastInsertRowid: row?.rid ?? 0 };
                }
                return { changes: 0, lastInsertRowid: 0 };
            },
            iterate() {
                throw new Error('iterate() is not supported via NativeDbProxy');
            },
            raw() {
                return stmt; // no-op — .raw() is not used in the build pipeline
            },
        };
        return stmt;
    }
    exec(sql) {
        this.#ndb.exec(sql);
        return this;
    }
    pragma(sql) {
        return this.#ndb.pragma(sql);
    }
    close() {
        // No-op: the pipeline manages the NativeDatabase lifecycle directly.
        // closeDbPair() calls nativeDb.close() separately.
    }
    get open() {
        return this.#ndb.isOpen;
    }
    get name() {
        return this.#ndb.dbPath;
    }
    transaction(fn) {
        const ndb = this.#ndb;
        return ((...args) => {
            // NOTE: nested transactions (savepoints) are not supported — ensure callers
            // do not invoke a transaction() wrapper from within an existing transaction.
            ndb.exec('BEGIN');
            try {
                const result = fn(...args);
                ndb.exec('COMMIT');
                return result;
            }
            catch (e) {
                try {
                    ndb.exec('ROLLBACK');
                }
                catch {
                    // Ignore rollback errors — the original error is more important
                }
                throw e;
            }
        });
    }
}
//# sourceMappingURL=native-db-proxy.js.map