"use strict";
// Copyright 2025 Bea <20361868+enbea@users.noreply.github.com>
// Copyright 2025 Gnuxie <Gnuxie@protonmail.com>
//
// SPDX-License-Identifier: Apache-2.0
Object.defineProperty(exports, "__esModule", { value: true });
exports.ensureSqliteSchema = ensureSqliteSchema;
exports.checkKnownTables = checkKnownTables;
// NOTE: Must be run in a `db.transaction` to rollback on thrown errors
//       and prevent partial upgrades. (allows user to revert to a last
//       known working version of the software in case of errors)
function ensureSchemaPragma(db, log, { upgradeSteps, consistencyCheck, legacyUpgrade }) {
    // remove this check to allow empty (v0) databases
    if (upgradeSteps.length === 0) {
        throw new TypeError("Missing version definitions.");
    }
    // https://www.sqlite.org/pragma.html#pragma_user_version
    const previousVersion = db.pragma("user_version", { simple: true });
    if (previousVersion > upgradeSteps.length) {
        throw new RangeError("Database is newer than defined `upgradeSteps`.");
    }
    const tableCount = db
        .prepare('SELECT count(*) FROM "sqlite_master";')
        .pluck()
        .get();
    if (previousVersion === 0 && tableCount > 0) {
        // Database isn't empty, try to migrate it
        log.info("Running legacy schema upgrade");
        if (legacyUpgrade) {
            legacyUpgrade(db);
        }
        else {
            log.error("Incompatible database"); // log so we can tell which database this is.
            throw new TypeError("Incompatible database");
        }
    }
    // read the version again in case of legacy upgrade changing the number.
    const startAt = db.pragma("user_version", { simple: true });
    upgradeSteps.slice(startAt).forEach((step) => {
        step(db);
    });
    db.pragma(`user_version = ${upgradeSteps.length}`);
    if (consistencyCheck && !consistencyCheck(db)) {
        throw new Error("Database failed the consistency check.");
    }
    const version = db.pragma("user_version", { simple: true });
    if (previousVersion !== version) {
        log.info("Migrated database version from", previousVersion, "to", version);
    }
    return {
        previousVersion,
        version,
    };
}
function ensureSqliteSchema(db, log, options) {
    const migrationVersion = db.transaction(ensureSchemaPragma)(db, log, options);
    db.exec("VACUUM;"); // why not
    return migrationVersion;
}
function checkKnownTables(db, unsortedKnownTables) {
    const knownTables = unsortedKnownTables.slice().sort(), currentTables = db
        .prepare(`SELECT name FROM "sqlite_master" WHERE type = 'table';`)
        .pluck()
        .all()
        .sort()
        .filter((table) => !/^sqlite_/.test(table));
    if (knownTables.length !== currentTables.length) {
        return false;
    }
    if (!knownTables.every((name, i) => currentTables[i] === name)) {
        return false;
    }
    return true;
}
//# sourceMappingURL=SqliteSchema.js.map