"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
Object.defineProperty(exports, "upgrade", {
    enumerable: true,
    get: function() {
        return upgrade;
    }
});
const _nodecrypto = require("node:crypto");
const _logging = require("@tamanu/shared/services/logging");
const _constants = require("@tamanu/constants");
const _migrations = require("@tamanu/database/services/migrations");
const _listSteps = require("./listSteps.js");
const _step = _export_star(require("./step.js"), exports);
function _export_star(from, to) {
    Object.keys(from).forEach(function(k) {
        if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
            Object.defineProperty(to, k, {
                enumerable: true,
                get: function() {
                    return from[k];
                }
            });
        }
    });
    return from;
}
const EARLIEST_MIGRATION = '1739968205100-addLSFFunction';
const BASELINE_MIGRATION = '000_baseline';
async function upgrade({ sequelize, models, toVersion, serverType }) {
    const fromVersion = await models.LocalSystemFact.get(_constants.FACT_CURRENT_VERSION).catch((err)=>{
        _logging.log.error('Failed to get current version, likely because there is not one recorded yet', err);
        return null;
    }) ?? '0.0.0';
    _logging.log.info('Upgrading Tamanu installation', {
        from: fromVersion,
        to: toVersion
    });
    const upgradeRunId = (0, _nodecrypto.randomUUID)();
    _logging.log.info('Upgrade run id', {
        upgradeRunId
    });
    const { migrations: migrationsUmzug, getDurationStats } = (0, _migrations.createMigrationInterface)(_logging.log, sequelize);
    const migrations = migrationsUmzug;
    let pendingMigrations = await migrations.pending();
    let doneMigrations = await migrations.executed();
    // Ensure the minimum schema is in place before any upgrade steps run.
    // Prefer the historical earliest migration; if it's been squashed into the
    // baseline, fall back to the baseline itself (which supersedes it).
    const pendingEarliestMigration = pendingMigrations.find((mig)=>mig.testFileName(EARLIEST_MIGRATION)) ?? pendingMigrations.find((mig)=>mig.testFileName(BASELINE_MIGRATION));
    if (pendingEarliestMigration) {
        await (0, _migrations.migrateUpTo)({
            log: _logging.log,
            sequelize,
            pending: pendingMigrations,
            migrations,
            getDurationStats,
            upOpts: {
                to: pendingEarliestMigration.file
            },
            upgradeRunId
        });
        pendingMigrations = await migrations.pending();
        doneMigrations = await migrations.executed();
    }
    _logging.log.debug('Loading upgrade steps');
    const { order, steps } = await (0, _listSteps.listSteps)();
    _logging.log.debug('Loaded upgrade steps', {
        count: steps.size
    });
    const stepArgs = {
        sequelize,
        models,
        fromVersion,
        toVersion,
        serverType
    };
    for (const id of order){
        const logger = _logging.log.child({
            step: id
        });
        const args = {
            ...stepArgs,
            log: logger
        };
        if (id === _listSteps.MIGRATIONS_END) {
            logger.debug('Run through all remaining migrations');
            await (0, _migrations.migrateUpTo)({
                log: logger,
                sequelize,
                pending: pendingMigrations,
                migrations,
                getDurationStats,
                upOpts: {},
                upgradeRunId
            });
            continue;
        }
        if (id.endsWith(_step.START) || id.endsWith(_step.END)) {
            continue;
        }
        if (id.startsWith(_step.MIGRATION_PREFIX)) {
            const target = pendingMigrations.find((mig)=>mig.testFileName((0, _step.migrationFile)(id)));
            if (target) {
                await (0, _migrations.migrateUpTo)({
                    log: logger,
                    sequelize,
                    pending: pendingMigrations,
                    migrations,
                    getDurationStats,
                    upOpts: {
                        to: target.file
                    },
                    upgradeRunId
                });
            }
            continue;
        }
        const entry = steps.get(id);
        if (!entry) {
            logger.warn('Missing step (bug!)');
            continue;
        }
        const { step } = entry;
        // before:Migration[] will only run if the migrations haven't run yet
        const beforeMigrations = (0, _step.onlyMigrations)(step.before);
        if (beforeMigrations.length > 0 && beforeMigrations.every((need)=>doneMigrations.some((mig)=>mig.testFileName(need)))) {
            logger.debug('Step has no before:Migration that has not already run, skipping');
            continue;
        }
        // after:Migration[] will only run if the migrations hadn't run yet *before starting this upgrade*
        // (the topo sort ensures that the migrations did run at this point in the loop)
        const afterMigrations = (0, _step.onlyMigrations)(step.after);
        if (afterMigrations.length > 0 && afterMigrations.every((need)=>doneMigrations.some((mig)=>mig.testFileName(need)))) {
            logger.debug('Step has no after:Migration that had not already run, skipping');
            continue;
        }
        logger.debug('Running check');
        if (!await step.check(args)) continue;
        logger.info('Running step');
        await step.run(args);
    }
    _logging.log.info('Tamanu has been upgraded', {
        toVersion
    });
    await models.LocalSystemFact.set(_constants.FACT_CURRENT_VERSION, toVersion);
}

//# sourceMappingURL=index.js.map