"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.__tsfTypeAliases = void 0;
exports.createDatabaseClass = createDatabaseClass;
exports.createMySQLDatabase = createMySQLDatabase;
exports.createPostgresDatabase = createPostgresDatabase;
exports.createDatabase = createDatabase;
const tslib_1 = require("tslib");
const _a = tslib_1.__importStar(require("@zyno-io/ts-server-foundation/type-metadata-runtime"));
const config_1 = require("../app/config");
const config_loader_1 = require("../app/config-loader");
const resolver_1 = require("../app/resolver");
const env_1 = require("../env");
const database_1 = require("./database");
const drivers_1 = require("./drivers");
function createDatabaseClass(driverFactory, entities = [], options = {}) {
    return class extends database_1.BaseDatabase {
        constructor() {
            super(driverFactory(), entities, options);
        }
    };
}
function createMySQLDatabase(config = {}, entities = []) {
    return class extends database_1.BaseDatabase {
        constructor() {
            const { driverInput, options } = resolveMySQLInput(config);
            super(new drivers_1.MySQLDriver(driverInput), entities, options);
        }
    };
}
function createPostgresDatabase(config = {}, entities = []) {
    return class extends database_1.BaseDatabase {
        constructor() {
            const { driverInput, options } = resolvePostgresInput(config);
            super(new drivers_1.PostgresDriver(driverInput), entities, options);
        }
    };
}
function createDatabase(dialectOrConfig, configOrEntities, entities = []) {
    if (typeof dialectOrConfig === 'string') {
        const dialect = dialectOrConfig;
        const config = configOrEntities && !Array.isArray(configOrEntities) ? configOrEntities : {};
        const entityList = Array.isArray(configOrEntities) ? configOrEntities : entities;
        return dialect === 'mysql'
            ? createMySQLDatabase(config, entityList)
            : createPostgresDatabase(config, entityList);
    }
    const dialect = env_1.Env.DB_ADAPTER;
    const config = dialectOrConfig ?? {};
    const entityList = Array.isArray(configOrEntities) ? configOrEntities : entities;
    if (dialect === 'mysql')
        return createMySQLDatabase(config, entityList);
    if (dialect === 'postgres')
        return createPostgresDatabase(config, entityList);
    throw new Error("DB_ADAPTER must be set to 'mysql' or 'postgres' when createDatabase() is called without an explicit dialect");
}
function resolveMySQLInput(config) {
    if (isMySQLPoolLike(config))
        return { driverInput: config, options: {} };
    const appConfig = readAppConfig();
    const production = appConfig.APP_ENV === 'production';
    const { enableLocksTable, lockTableName, ...poolConfig } = config;
    const testDatabaseName = appConfig.APP_ENV === 'test' ? env_1.Env.TSF_TEST_DATABASE_NAME : undefined;
    const sharedSessionKey = appConfig.APP_ENV === 'test' ? env_1.Env.TSF_TEST_MYSQL_SESSION_KEY : undefined;
    const sharedSessionLeaseId = appConfig.APP_ENV === 'test' ? env_1.Env.TSF_TEST_MYSQL_SESSION_LEASE_ID : undefined;
    if (sharedSessionKey && (0, drivers_1.getSharedMySQLSessionManagerConfig)()) {
        return {
            driverInput: (0, drivers_1.createSharedMySQLSessionPool)(sharedSessionKey, undefined, sharedSessionLeaseId),
            options: { enableLocksTable, lockTableName }
        };
    }
    return {
        driverInput: {
            host: appConfig.MYSQL_HOST,
            port: appConfig.MYSQL_PORT,
            user: appConfig.MYSQL_USER,
            password: appConfig.MYSQL_PASSWORD_SECRET,
            database: appConfig.MYSQL_DATABASE,
            waitForConnections: true,
            connectionLimit: appConfig.MYSQL_CONNECTION_LIMIT ?? (production ? 10 : 5),
            idleTimeout: (appConfig.MYSQL_IDLE_TIMEOUT_SECONDS ?? (production ? 60 : 5)) * 1000,
            ...poolConfig,
            ...(testDatabaseName ? { database: testDatabaseName } : {})
        },
        options: { enableLocksTable, lockTableName }
    };
}
function resolvePostgresInput(config) {
    if (isPgPoolLike(config))
        return { driverInput: config, options: {} };
    const appConfig = readAppConfig();
    const production = appConfig.APP_ENV === 'production';
    const { enableLocksTable: _enableLocksTable, lockTableName, ...poolConfig } = config;
    const ssl = appConfig.PG_SSL ? { rejectUnauthorized: appConfig.PG_SSL_REJECT_UNAUTHORIZED ?? true } : undefined;
    const testDatabaseName = appConfig.APP_ENV === 'test' ? env_1.Env.TSF_TEST_DATABASE_NAME : undefined;
    return {
        driverInput: {
            host: appConfig.PG_HOST,
            port: appConfig.PG_PORT,
            user: appConfig.PG_USER,
            password: appConfig.PG_PASSWORD_SECRET,
            database: appConfig.PG_DATABASE,
            ssl,
            max: appConfig.PG_CONNECTION_LIMIT ?? (production ? 10 : 5),
            idleTimeoutMillis: (appConfig.PG_IDLE_TIMEOUT_SECONDS ?? (production ? 60 : 5)) * 1000,
            ...poolConfig,
            ...(testDatabaseName ? { database: testDatabaseName } : {})
        },
        options: { lockTableName }
    };
}
function readAppConfig() {
    try {
        return (0, resolver_1.getAppConfig)();
    }
    catch {
        return new config_loader_1.ConfigLoader(config_1.BaseAppConfig).load();
    }
}
function isMySQLPoolLike(value) {
    return typeof value.getConnection === 'function' && typeof value.end === 'function';
}
function isPgPoolLike(value) {
    return typeof value.connect === 'function' && typeof value.end === 'function';
}
exports.__tsfTypeAliases = _a.decodeCompactMetadataV1("[1,{\"DatabaseDialect\":{\"kind\":12,\"types\":[{\"kind\":10,\"literal\":\"mysql\"},{\"kind\":10,\"literal\":\"postgres\"}],\"typeName\":\"DatabaseDialect\"},\"MySQLDatabaseConfig\":{\"kind\":18,\"typeName\":\"MySQLDatabaseConfig\",\"types\":[{\"kind\":20,\"name\":\"enableLocksTable\",\"type\":{\"kind\":12,\"types\":[{\"kind\":8},{\"kind\":4}]},\"optional\":true},{\"kind\":20,\"name\":\"lockTableName\",\"type\":{\"kind\":12,\"types\":[{\"kind\":6},{\"kind\":4}]},\"optional\":true},{\"kind\":20,\"name\":\"enableLocksTable\",\"type\":{\"kind\":12,\"types\":[{\"kind\":8},{\"kind\":4}]},\"optional\":true}],\"implements\":[{\"$tsfAlias\":[0,\"mysql2/promise\",\"PoolOptions\",\"PoolOptions\"]}]},\"PostgresDatabaseConfig\":{\"kind\":18,\"typeName\":\"PostgresDatabaseConfig\",\"types\":[{\"kind\":20,\"name\":\"enableLocksTable\",\"type\":{\"kind\":12,\"types\":[{\"kind\":8},{\"kind\":4}]},\"optional\":true},{\"kind\":20,\"name\":\"lockTableName\",\"type\":{\"kind\":12,\"types\":[{\"kind\":6},{\"kind\":4}]},\"optional\":true},{\"kind\":20,\"name\":\"enableLocksTable\",\"type\":{\"kind\":12,\"types\":[{\"kind\":8},{\"kind\":4}]},\"optional\":true}],\"implements\":[{\"$tsfAlias\":[0,\"pg\",\"PoolConfig\",\"PoolConfig\"]}]},\"SharedDatabaseConfig\":{\"kind\":18,\"typeName\":\"SharedDatabaseConfig\",\"types\":[{\"kind\":20,\"name\":\"enableLocksTable\",\"type\":{\"kind\":12,\"types\":[{\"kind\":8},{\"kind\":4}]},\"optional\":true},{\"kind\":20,\"name\":\"lockTableName\",\"type\":{\"kind\":12,\"types\":[{\"kind\":6},{\"kind\":4}]},\"optional\":true},{\"kind\":20,\"name\":\"enableLocksTable\",\"type\":{\"kind\":12,\"types\":[{\"kind\":8},{\"kind\":4}]},\"optional\":true}]}}]", [require]);
//# sourceMappingURL=factory.js.map