"use strict";
// Copyright 2024 - 2025 Gnuxie <Gnuxie@protonmail.com>
// Copyright 2022 The Matrix.org Foundation C.I.C.
//
// SPDX-License-Identifier: Apache-2.0
//
// SPDX-FileAttributionText: <text>
// This modified file incorporates work from matrix-appservice-bridge
// https://github.com/matrix-org/matrix-appservice-bridge
// </text>
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.BetterSqliteStore = void 0;
exports.makeBetterSqliteDB = makeBetterSqliteDB;
exports.flatTransaction = flatTransaction;
const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
const SqliteSchema_1 = require("./SqliteSchema");
function makeBetterSqliteDB(options, log) {
    log.info("Opening db: ", options.path);
    const db = new better_sqlite3_1.default(options.path, options);
    if (options.path === ":memory:") {
        db.pragma("temp_store = memory");
    }
    else {
        db.pragma("temp_store = file"); // Avoid unnecessary memory usage.
    }
    if (options.WALMode) {
        db.pragma("journal_mode = WAL");
    }
    if (options.foreignKeys) {
        db.pragma("foreign_keys = ON");
    }
    process.once("beforeExit", () => {
        // Ensure we clean up on exit
        try {
            log.info("Destroy called on db", options.path);
            if (db.open) {
                // No-op if end has already been called.
                return;
            }
            db.close();
            log.info("connection ended on db", options.path);
        }
        catch (ex) {
            log.warn("Failed to cleanly exit", ex);
        }
    });
    return db;
}
/**
 * BetterSqliteStore datastore abstraction which can be inherited by a specialised bridge class.
 * Please note, that the client library provides synchronous access to sqlite.
 *
 * @example
 * class MyBridgeStore extends BetterSqliteStore {
 *   constructor(myurl) {
 *     super([schemav1, schemav2, schemav3], { url: myurl });
 *   }
 *
 *   async getData() {
 *     return this.sql`SELECT * FROM mytable`
 *   }
 * }
 *
 * // Which can then be used by doing
 * const store = new MyBridgeStore("data.db");
 * store.ensureSchema();
 * const data = await store.getData();
 */
class BetterSqliteStore {
    schema;
    db;
    log;
    /**
     * Construct a new store.
     * @param schemas The set of schema functions to apply to a database. The ordering of this array determines the
     *                schema number.
     * @param opts Options to supply to the BetterSqliteStore client, such as `path`.
     */
    constructor(schema, db, log) {
        this.schema = schema;
        this.db = db;
        this.log = log;
        (0, SqliteSchema_1.ensureSqliteSchema)(this.db, this.log, this.schema);
    }
    /**
     * Clean away any resources used by the database
     */
    destroy() {
        this.log.info("Destroy called");
        if (this.db.open) {
            // No-op if end has already been called.
            return;
        }
        this.db.close();
        this.log.info("connection ended");
    }
}
exports.BetterSqliteStore = BetterSqliteStore;
/**
 * Wraps `fn` in a transaction without creating nested SAVEPOINTs.
 * Reduces the likelihood of temporary file creation.
 * Initially investigated as part of #746.
 *
 * See https://www.sqlite.org/lang_savepoint.html
 * See https://github.com/WiseLibs/better-sqlite3/blob/master/docs/api.md#transactionfunction---function
 */
function flatTransaction(db, fn) {
    const t = db.transaction(fn);
    return (...args) => db.inTransaction ? fn(...args) : t(...args);
}
//# sourceMappingURL=BetterSqliteStore.js.map