"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
    return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (g && (g = 0, op[0] && (_ = 0)), _) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
var __values = (this && this.__values) || function(o) {
    var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
    if (m) return m.call(o);
    if (o && typeof o.length === "number") return {
        next: function () {
            if (o && i >= o.length) o = void 0;
            return { value: o && o[i++], done: !o };
        }
    };
    throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ResolveIOServer = void 0;
var mongodb_1 = require("mongodb");
var ResolveIOServer = /** @class */ (function () {
    function ResolveIOServer() {
    }
    ResolveIOServer.connectMongo = function () {
        return __awaiter(this, void 0, void 0, function () {
            var mongoUrl, clientOptions, client;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        mongoUrl = ResolveIOServer.getServerConfig()['MONGO_URL'];
                        clientOptions = ResolveIOServer.resolveMongoClientOptions();
                        return [4 /*yield*/, mongodb_1.MongoClient.connect(mongoUrl, clientOptions)];
                    case 1:
                        client = _a.sent();
                        ResolveIOServer.attachMongoListeners(client);
                        return [2 /*return*/, client];
                }
            });
        });
    };
    ResolveIOServer.attachMongoListeners = function (client) {
        if (!client) {
            return;
        }
        client.on('close', ResolveIOServer.handleMongoClose);
        client.on('error', ResolveIOServer.handleMongoError);
        client.on('connectionPoolCleared', ResolveIOServer.handleMongoPoolCleared);
        client.on('serverClosed', ResolveIOServer.handleMongoServerClosed);
        client.on('topologyClosed', ResolveIOServer.handleMongoTopologyClosed);
    };
    ResolveIOServer.detachMongoListeners = function (client) {
        if (!client) {
            return;
        }
        client.removeListener('close', ResolveIOServer.handleMongoClose);
        client.removeListener('error', ResolveIOServer.handleMongoError);
        client.removeListener('connectionPoolCleared', ResolveIOServer.handleMongoPoolCleared);
        client.removeListener('serverClosed', ResolveIOServer.handleMongoServerClosed);
        client.removeListener('topologyClosed', ResolveIOServer.handleMongoTopologyClosed);
    };
    ResolveIOServer.handleMongoClose = function (signal) {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, ResolveIOServer.handleMongoDisconnectSignal('close', signal)];
                    case 1:
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    ResolveIOServer.handleMongoError = function (signal) {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, ResolveIOServer.handleMongoDisconnectSignal('error', signal)];
                    case 1:
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    ResolveIOServer.handleMongoServerClosed = function (signal) {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, ResolveIOServer.handleMongoDisconnectSignal('serverClosed', signal)];
                    case 1:
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    ResolveIOServer.handleMongoTopologyClosed = function (signal) {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, ResolveIOServer.handleMongoDisconnectSignal('topologyClosed', signal)];
                    case 1:
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    ResolveIOServer.handleMongoPoolCleared = function (signal) {
        return __awaiter(this, void 0, void 0, function () {
            var now, summary;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        now = Date.now();
                        summary = ResolveIOServer.summarizeMongoSignal(signal);
                        if (!ResolveIOServer._lastMongoPoolClearedLogMs || (now - ResolveIOServer._lastMongoPoolClearedLogMs) >= ResolveIOServer.MONGO_POOL_CLEARED_DEBOUNCE_MS) {
                            ResolveIOServer._lastMongoPoolClearedLogMs = now;
                            console.warn(new Date(), 'Mongo connection pool cleared', summary);
                        }
                        return [4 /*yield*/, ResolveIOServer.handleMongoDisconnectSignal('connectionPoolCleared', signal, { verifyBeforeReconnect: true })];
                    case 1:
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    ResolveIOServer.handleMongoDisconnectSignal = function (reason_1, signal_1) {
        return __awaiter(this, arguments, void 0, function (reason, signal, options) {
            var isHealthy;
            if (options === void 0) { options = {}; }
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (!options.verifyBeforeReconnect) return [3 /*break*/, 2];
                        return [4 /*yield*/, ResolveIOServer.isMongoConnectionHealthy()];
                    case 1:
                        isHealthy = _a.sent();
                        if (isHealthy) {
                            return [2 /*return*/];
                        }
                        _a.label = 2;
                    case 2: return [4 /*yield*/, ResolveIOServer.requestMongoReconnect(reason, signal)];
                    case 3:
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    ResolveIOServer.isMongoConnectionHealthy = function () {
        return __awaiter(this, arguments, void 0, function (timeoutMs) {
            var client, pingDatabase, timeoutPromise, _a;
            var _this = this;
            var _b;
            if (timeoutMs === void 0) { timeoutMs = 2500; }
            return __generator(this, function (_c) {
                switch (_c.label) {
                    case 0:
                        client = ResolveIOServer.getMongoConnection();
                        if (!client) {
                            return [2 /*return*/, false];
                        }
                        pingDatabase = ((_b = ResolveIOServer.getServerConfig()) === null || _b === void 0 ? void 0 : _b['DATABASE']) || 'admin';
                        _c.label = 1;
                    case 1:
                        _c.trys.push([1, 3, , 4]);
                        timeoutPromise = (function () { return __awaiter(_this, void 0, void 0, function () {
                            return __generator(this, function (_a) {
                                switch (_a.label) {
                                    case 0: return [4 /*yield*/, ResolveIOServer.delay(timeoutMs)];
                                    case 1:
                                        _a.sent();
                                        throw new Error('mongo-ping-timeout');
                                }
                            });
                        }); })();
                        return [4 /*yield*/, Promise.race([
                                client.db(pingDatabase).command({ ping: 1 }),
                                timeoutPromise
                            ])];
                    case 2:
                        _c.sent();
                        return [2 /*return*/, true];
                    case 3:
                        _a = _c.sent();
                        return [2 /*return*/, false];
                    case 4: return [2 /*return*/];
                }
            });
        });
    };
    ResolveIOServer.requestMongoReconnect = function () {
        return __awaiter(this, arguments, void 0, function (reason, signal) {
            var reconnectPromise, signalSummary;
            var _this = this;
            if (reason === void 0) { reason = 'unknown'; }
            return __generator(this, function (_a) {
                reconnectPromise = ResolveIOServer._mongoReconnectPromise;
                if (reconnectPromise !== null) {
                    return [2 /*return*/, reconnectPromise];
                }
                signalSummary = ResolveIOServer.summarizeMongoSignal(signal);
                ResolveIOServer._reconnecting = true;
                ResolveIOServer._mongoReconnectPromise = (function () { return __awaiter(_this, void 0, void 0, function () {
                    return __generator(this, function (_a) {
                        switch (_a.label) {
                            case 0:
                                _a.trys.push([0, , 2, 3]);
                                console.error(new Date(), 'Mongo connection lost', { reason: reason, signal: signalSummary });
                                return [4 /*yield*/, ResolveIOServer.reconnectMongo(reason, signal)];
                            case 1:
                                _a.sent();
                                return [3 /*break*/, 3];
                            case 2:
                                ResolveIOServer._reconnecting = false;
                                ResolveIOServer._mongoReconnectPromise = null;
                                return [7 /*endfinally*/];
                            case 3: return [2 /*return*/];
                        }
                    });
                }); })();
                return [2 /*return*/, ResolveIOServer._mongoReconnectPromise];
            });
        });
    };
    ResolveIOServer.summarizeMongoSignal = function (signal) {
        if (!signal) {
            return null;
        }
        if (typeof signal !== 'object') {
            return signal;
        }
        return {
            name: signal.name,
            message: signal.message,
            code: signal.code,
            codeName: signal.codeName,
            address: signal.address,
            interruptInUseConnections: signal.interruptInUseConnections
        };
    };
    ResolveIOServer.closeMongoClientQuietly = function (client) {
        return __awaiter(this, void 0, void 0, function () {
            var _a;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        if (!client) {
                            return [2 /*return*/];
                        }
                        _b.label = 1;
                    case 1:
                        _b.trys.push([1, 3, , 4]);
                        ResolveIOServer.detachMongoListeners(client);
                        return [4 /*yield*/, client.close(false)];
                    case 2:
                        _b.sent();
                        return [3 /*break*/, 4];
                    case 3:
                        _a = _b.sent();
                        return [3 /*break*/, 4];
                    case 4: return [2 /*return*/];
                }
            });
        });
    };
    ResolveIOServer.notifyMongoReconnect = function (reason) {
        return __awaiter(this, void 0, void 0, function () {
            var mongoManager, error_1, mainServer, subscriptionManager, error_2;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        _a.trys.push([0, 3, , 4]);
                        mongoManager = ResolveIOServer.getMongoManager();
                        if (!(mongoManager && typeof mongoManager.handleMongoReconnect === 'function')) return [3 /*break*/, 2];
                        return [4 /*yield*/, mongoManager.handleMongoReconnect(reason)];
                    case 1:
                        _a.sent();
                        _a.label = 2;
                    case 2: return [3 /*break*/, 4];
                    case 3:
                        error_1 = _a.sent();
                        console.error(new Date(), 'Mongo reconnect post-hook failed (mongo manager)', error_1);
                        return [3 /*break*/, 4];
                    case 4:
                        _a.trys.push([4, 7, , 8]);
                        mainServer = ResolveIOServer.getMainServer();
                        subscriptionManager = mainServer && typeof mainServer.getSubscriptionManager === 'function'
                            ? mainServer.getSubscriptionManager()
                            : null;
                        if (!(subscriptionManager && typeof subscriptionManager.handleMongoReconnect === 'function')) return [3 /*break*/, 6];
                        return [4 /*yield*/, subscriptionManager.handleMongoReconnect(reason)];
                    case 5:
                        _a.sent();
                        _a.label = 6;
                    case 6: return [3 /*break*/, 8];
                    case 7:
                        error_2 = _a.sent();
                        console.error(new Date(), 'Mongo reconnect post-hook failed (subscription manager)', error_2);
                        return [3 /*break*/, 8];
                    case 8: return [2 /*return*/];
                }
            });
        });
    };
    ResolveIOServer.reconnectMongo = function () {
        return __awaiter(this, arguments, void 0, function (reason, signal) {
            var previousClient, signalSummary, attempt, client, err_1;
            if (reason === void 0) { reason = 'unknown'; }
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        previousClient = ResolveIOServer.getMongoConnection();
                        signalSummary = ResolveIOServer.summarizeMongoSignal(signal);
                        attempt = 0;
                        _a.label = 1;
                    case 1:
                        if (!true) return [3 /*break*/, 9];
                        _a.label = 2;
                    case 2:
                        _a.trys.push([2, 6, , 8]);
                        return [4 /*yield*/, ResolveIOServer.connectMongo()];
                    case 3:
                        client = _a.sent();
                        ResolveIOServer.setMongoConnection(client);
                        ResolveIOServer.setMainDB(client.db(ResolveIOServer.getServerConfig()['DATABASE']));
                        return [4 /*yield*/, ResolveIOServer.closeMongoClientQuietly(previousClient)];
                    case 4:
                        _a.sent();
                        return [4 /*yield*/, ResolveIOServer.notifyMongoReconnect(reason)];
                    case 5:
                        _a.sent();
                        console.log(new Date(), 'Mongo reconnected', { reason: reason, attempts: attempt + 1, signal: signalSummary });
                        return [2 /*return*/];
                    case 6:
                        err_1 = _a.sent();
                        attempt++;
                        console.error(new Date(), 'Mongo reconnect failed', { reason: reason, attempts: attempt, signal: signalSummary, error: ResolveIOServer.summarizeMongoSignal(err_1) });
                        return [4 /*yield*/, ResolveIOServer.delay(Math.min(attempt * 1000, 10000))];
                    case 7:
                        _a.sent();
                        return [3 /*break*/, 8];
                    case 8: return [3 /*break*/, 1];
                    case 9: return [2 /*return*/];
                }
            });
        });
    };
    ResolveIOServer.handleMongoDisconnect = function (err) {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, ResolveIOServer.requestMongoReconnect('legacy-disconnect-signal', err)];
                    case 1:
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    ResolveIOServer.delay = function (ms) {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                // eslint-disable-next-line no-restricted-syntax
                return [2 /*return*/, new Promise(function (resolve) { return setTimeout(resolve, ms); })];
            });
        });
    };
    ResolveIOServer.resolveMongoClientOptions = function () {
        var e_1, _a, _b, e_2, _c, _d;
        var config = ResolveIOServer.getServerConfig();
        var options = {};
        var numericOptionKeys = [
            { key: 'maxPoolSize', env: 'MONGO_MAX_POOL_SIZE', configKey: 'MONGO_MAX_POOL_SIZE' },
            { key: 'minPoolSize', env: 'MONGO_MIN_POOL_SIZE', configKey: 'MONGO_MIN_POOL_SIZE' },
            { key: 'waitQueueTimeoutMS', env: 'MONGO_WAIT_QUEUE_TIMEOUT_MS', configKey: 'MONGO_WAIT_QUEUE_TIMEOUT_MS' },
            { key: 'maxIdleTimeMS', env: 'MONGO_MAX_IDLE_TIME_MS', configKey: 'MONGO_MAX_IDLE_TIME_MS' },
            { key: 'serverSelectionTimeoutMS', env: 'MONGO_SERVER_SELECTION_TIMEOUT_MS', configKey: 'MONGO_SERVER_SELECTION_TIMEOUT_MS' },
            { key: 'connectTimeoutMS', env: 'MONGO_CONNECT_TIMEOUT_MS', configKey: 'MONGO_CONNECT_TIMEOUT_MS' },
            { key: 'socketTimeoutMS', env: 'MONGO_SOCKET_TIMEOUT_MS', configKey: 'MONGO_SOCKET_TIMEOUT_MS' },
            { key: 'heartbeatFrequencyMS', env: 'MONGO_HEARTBEAT_FREQUENCY_MS', configKey: 'MONGO_HEARTBEAT_FREQUENCY_MS' }
        ];
        try {
            for (var numericOptionKeys_1 = __values(numericOptionKeys), numericOptionKeys_1_1 = numericOptionKeys_1.next(); !numericOptionKeys_1_1.done; numericOptionKeys_1_1 = numericOptionKeys_1.next()) {
                var option = numericOptionKeys_1_1.value;
                var value = ResolveIOServer.pickMongoOptionValue(option.env, option.configKey);
                if (typeof value === 'number') {
                    Object.assign(options, (_b = {}, _b[option.key] = value, _b));
                }
            }
        }
        catch (e_1_1) { e_1 = { error: e_1_1 }; }
        finally {
            try {
                if (numericOptionKeys_1_1 && !numericOptionKeys_1_1.done && (_a = numericOptionKeys_1.return)) _a.call(numericOptionKeys_1);
            }
            finally { if (e_1) throw e_1.error; }
        }
        var booleanOptionKeys = [
            { key: 'retryWrites', env: 'MONGO_RETRY_WRITES', configKey: 'MONGO_RETRY_WRITES' }
        ];
        try {
            for (var booleanOptionKeys_1 = __values(booleanOptionKeys), booleanOptionKeys_1_1 = booleanOptionKeys_1.next(); !booleanOptionKeys_1_1.done; booleanOptionKeys_1_1 = booleanOptionKeys_1.next()) {
                var option = booleanOptionKeys_1_1.value;
                var value = ResolveIOServer.pickMongoBooleanOptionValue(option.env, option.configKey);
                if (typeof value === 'boolean') {
                    Object.assign(options, (_d = {}, _d[option.key] = value, _d));
                }
            }
        }
        catch (e_2_1) { e_2 = { error: e_2_1 }; }
        finally {
            try {
                if (booleanOptionKeys_1_1 && !booleanOptionKeys_1_1.done && (_c = booleanOptionKeys_1.return)) _c.call(booleanOptionKeys_1);
            }
            finally { if (e_2) throw e_2.error; }
        }
        var structuredOptions = config === null || config === void 0 ? void 0 : config['MONGO_CLIENT_OPTIONS'];
        if (structuredOptions && typeof structuredOptions === 'object' && !Array.isArray(structuredOptions)) {
            Object.assign(options, structuredOptions);
        }
        return Object.keys(options).length ? options : undefined;
    };
    ResolveIOServer.pickMongoOptionValue = function (envKey, configKey) {
        var rawEnv = process.env[envKey];
        if (rawEnv && !Number.isNaN(Number(rawEnv))) {
            var parsed = parseInt(rawEnv, 10);
            return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
        }
        var config = ResolveIOServer.getServerConfig();
        var configValue = config === null || config === void 0 ? void 0 : config[configKey];
        if (typeof configValue === 'number' && Number.isFinite(configValue) && configValue > 0) {
            return configValue;
        }
        if (typeof configValue === 'string' && configValue.trim().length && !Number.isNaN(Number(configValue))) {
            var parsed = parseInt(configValue, 10);
            return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
        }
        return undefined;
    };
    ResolveIOServer.pickMongoBooleanOptionValue = function (envKey, configKey) {
        var rawEnv = process.env[envKey];
        if (typeof rawEnv === 'string' && rawEnv.length) {
            if (['true', '1', 'yes'].includes(rawEnv.toLowerCase())) {
                return true;
            }
            else if (['false', '0', 'no'].includes(rawEnv.toLowerCase())) {
                return false;
            }
        }
        var config = ResolveIOServer.getServerConfig();
        var configValue = config === null || config === void 0 ? void 0 : config[configKey];
        if (typeof configValue === 'boolean') {
            return configValue;
        }
        if (typeof configValue === 'string' && configValue.length) {
            if (['true', '1', 'yes'].includes(configValue.toLowerCase())) {
                return true;
            }
            else if (['false', '0', 'no'].includes(configValue.toLowerCase())) {
                return false;
            }
        }
        return undefined;
    };
    ResolveIOServer.create = function (serverConfig_1, clientRoutes_1, client_1, clientDir_1) {
        return __awaiter(this, arguments, void 0, function (serverConfig, clientRoutes, client, clientDir, sesMail, publicProgram) {
            var resolveioServer;
            if (sesMail === void 0) { sesMail = true; }
            if (publicProgram === void 0) { publicProgram = false; }
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        resolveioServer = new ResolveIOServer();
                        return [4 /*yield*/, resolveioServer.initialize(serverConfig, clientRoutes, client, clientDir, sesMail, publicProgram)];
                    case 1:
                        _a.sent();
                        return [2 /*return*/, resolveioServer];
                }
            });
        });
    };
    ResolveIOServer.prototype.initialize = function (serverConfig_1, clientRoutes_1, client_1, clientDir_1) {
        return __awaiter(this, arguments, void 0, function (serverConfig, clientRoutes, client, clientDir, sesMail, publicProgram) {
            var dbConnection, LocalLogManager_1, localLogManager, MongoManager_1, mongoManager, serverApp, app, err_2;
            if (sesMail === void 0) { sesMail = true; }
            if (publicProgram === void 0) { publicProgram = false; }
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        ResolveIOServer._serverConfig = serverConfig;
                        ResolveIOServer._clientRoutes = clientRoutes;
                        ResolveIOServer._client = client;
                        ResolveIOServer._clientDir = clientDir;
                        ResolveIOServer._sesMail = sesMail;
                        ResolveIOServer._publicProgram = publicProgram;
                        _a.label = 1;
                    case 1:
                        _a.trys.push([1, 8, , 9]);
                        return [4 /*yield*/, ResolveIOServer.connectMongo()];
                    case 2:
                        dbConnection = _a.sent();
                        process.removeAllListeners('unhandledRejection');
                        ResolveIOServer.setMongoConnection(dbConnection);
                        ResolveIOServer.setMainDB(dbConnection.db(ResolveIOServer.getServerConfig()['DATABASE']));
                        return [4 /*yield*/, Promise.resolve().then(function () { return require('./managers/local-log.manager'); })];
                    case 3:
                        LocalLogManager_1 = (_a.sent()).LocalLogManager;
                        localLogManager = LocalLogManager_1.create();
                        ResolveIOServer.setLocalLogManager(localLogManager);
                        return [4 /*yield*/, Promise.resolve().then(function () { return require('./managers/mongo.manager'); })];
                    case 4:
                        MongoManager_1 = (_a.sent()).MongoManager;
                        return [4 /*yield*/, MongoManager_1.create()];
                    case 5:
                        mongoManager = _a.sent();
                        ResolveIOServer.setMongoManager(mongoManager);
                        return [4 /*yield*/, Promise.resolve().then(function () { return require('./server-app'); })];
                    case 6:
                        serverApp = (_a.sent()).ResolveIOMainServer;
                        return [4 /*yield*/, serverApp.create()];
                    case 7:
                        app = _a.sent();
                        ResolveIOServer.setMainServer(app);
                        return [2 /*return*/, true];
                    case 8:
                        err_2 = _a.sent();
                        err_2.message = 'Error in ResolveIOServer (initialize): Mongo Client Connect And Run ResolveIO Server App Library - ' + err_2.message;
                        console.error(err_2.message);
                        process.exit(1);
                        return [3 /*break*/, 9];
                    case 9: return [2 /*return*/];
                }
            });
        });
    };
    ResolveIOServer.getClientName = function () {
        return this._client;
    };
    ResolveIOServer.getMainServer = function () {
        return ResolveIOServer._mainServer;
    };
    ResolveIOServer.setMainServer = function (mainServer) {
        ResolveIOServer._mainServer = mainServer;
    };
    ResolveIOServer.setMongoConnection = function (mongoConnection) {
        ResolveIOServer._mongoConnection = mongoConnection;
    };
    ResolveIOServer.getMongoConnection = function () {
        return ResolveIOServer._mongoConnection;
    };
    ResolveIOServer.getMainDB = function () {
        return ResolveIOServer._mainDB;
    };
    ResolveIOServer.setMainDB = function (mainDB) {
        ResolveIOServer._mainDB = mainDB;
    };
    ResolveIOServer.getMongoManager = function () {
        return ResolveIOServer._mongoManager;
    };
    ResolveIOServer.setMongoManager = function (mongoManager) {
        ResolveIOServer._mongoManager = mongoManager;
    };
    ResolveIOServer.getLocalLogManager = function () {
        return ResolveIOServer._localLogManager;
    };
    ResolveIOServer.setLocalLogManager = function (localLogManager) {
        ResolveIOServer._localLogManager = localLogManager;
    };
    ResolveIOServer.getServerConfig = function () {
        return ResolveIOServer._serverConfig;
    };
    ResolveIOServer.getLogStorageMode = function () {
        var configuredMode = this.resolveConfiguredLogStorageMode();
        if (configuredMode === 'offline' || configuredMode === 'direct') {
            return configuredMode;
        }
        return this.resolveLegacyLogStorageMode();
    };
    ResolveIOServer.shouldWriteLogsOffline = function () {
        return this.getLogStorageMode() === 'offline';
    };
    ResolveIOServer.resolveConfiguredLogStorageMode = function () {
        var config = ResolveIOServer.getServerConfig() || {};
        var configuredValue = process.env.RESOLVEIO_LOG_STORAGE_MODE
            || process.env.LOG_STORAGE_MODE
            || config['RESOLVEIO_LOG_STORAGE_MODE']
            || config['LOG_STORAGE_MODE']
            || config['LOCAL_LOG_STORAGE_MODE']
            || '';
        var normalized = String(configuredValue || '').trim().toLowerCase();
        if (!normalized || normalized === 'auto') {
            return 'auto';
        }
        if (normalized === 'direct' || normalized === 'database' || normalized === 'db') {
            return 'direct';
        }
        if (normalized === 'offline' || normalized === 'offload' || normalized === 'file' || normalized === 'local') {
            return 'offline';
        }
        return 'auto';
    };
    ResolveIOServer.resolveLegacyLogStorageMode = function () {
        var _a;
        var rootUrl = (_a = ResolveIOServer.getServerConfig()) === null || _a === void 0 ? void 0 : _a['ROOT_URL'];
        if (rootUrl !== 'https://resolveio.com' && rootUrl !== 'http://localhost:4200') {
            return 'offline';
        }
        return 'direct';
    };
    ResolveIOServer.getInstanceHost = function () {
        var config = ResolveIOServer.getServerConfig() || {};
        var explicitHost = this.findFirstNonEmptyString([
            process.env.RESOLVEIO_INSTANCE_HOST,
            process.env.INSTANCE_HOST,
            config['RESOLVEIO_INSTANCE_HOST'],
            config['INSTANCE_HOST'],
            config['SERVER_HOST']
        ]);
        if (explicitHost) {
            return explicitHost;
        }
        var hostFromUrl = this.extractHostName(this.findFirstNonEmptyString([
            process.env.RESOLVEIO_SERVER_URL,
            process.env.SERVER_URL,
            config['RESOLVEIO_SERVER_URL'],
            config['SERVER_URL'],
            process.env.ROOT_URL,
            config['ROOT_URL']
        ]));
        if (hostFromUrl) {
            return hostFromUrl;
        }
        var envHostName = this.findFirstNonEmptyString([
            process.env.EC2_PUBLIC_HOSTNAME,
            process.env.HOSTNAME
        ]);
        if (envHostName) {
            return envHostName;
        }
        return 'local-instance';
    };
    ResolveIOServer.getServerApiBaseUrl = function () {
        var config = ResolveIOServer.getServerConfig() || {};
        var explicitBaseUrl = this.normalizeBaseUrl(this.findFirstNonEmptyString([
            process.env.RESOLVEIO_SERVER_URL,
            process.env.SERVER_URL,
            config['RESOLVEIO_SERVER_URL'],
            config['SERVER_URL']
        ]));
        if (explicitBaseUrl) {
            return explicitBaseUrl;
        }
        var normalizedRootUrl = this.normalizeBaseUrl(this.findFirstNonEmptyString([
            process.env.ROOT_URL,
            config['ROOT_URL']
        ]));
        if (normalizedRootUrl) {
            try {
                var parsedRootUrl = new URL(normalizedRootUrl);
                if (parsedRootUrl.port === '4200') {
                    parsedRootUrl.port = '8080';
                }
                parsedRootUrl.pathname = '';
                parsedRootUrl.search = '';
                parsedRootUrl.hash = '';
                return parsedRootUrl.toString().replace(/\/$/, '');
            }
            catch (_a) {
                return normalizedRootUrl;
            }
        }
        var defaultPort = this.findFirstNonEmptyString([
            process.env.PORT,
            config['PORT']
        ]) || '8080';
        return "http://127.0.0.1:".concat(defaultPort);
    };
    ResolveIOServer.buildServerApiUrl = function (pathname) {
        var normalizedPath = pathname && pathname.startsWith('/')
            ? pathname
            : "/".concat(pathname || '');
        return this.getServerApiBaseUrl().replace(/\/$/, '') + normalizedPath;
    };
    ResolveIOServer.findFirstNonEmptyString = function (values) {
        var e_3, _a;
        try {
            for (var _b = __values(values || []), _c = _b.next(); !_c.done; _c = _b.next()) {
                var value = _c.value;
                if (typeof value === 'string' && value.trim().length) {
                    return value.trim();
                }
            }
        }
        catch (e_3_1) { e_3 = { error: e_3_1 }; }
        finally {
            try {
                if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
            }
            finally { if (e_3) throw e_3.error; }
        }
        return null;
    };
    ResolveIOServer.normalizeBaseUrl = function (value) {
        if (!value || typeof value !== 'string') {
            return null;
        }
        var trimmedValue = value.trim();
        if (!trimmedValue) {
            return null;
        }
        var hasScheme = /^[a-zA-Z][a-zA-Z\d+\-.]*:\/\//.test(trimmedValue);
        var candidate = hasScheme ? trimmedValue : "http://".concat(trimmedValue);
        try {
            var parsed = new URL(candidate);
            parsed.pathname = '';
            parsed.search = '';
            parsed.hash = '';
            return parsed.toString().replace(/\/$/, '');
        }
        catch (_a) {
            return null;
        }
    };
    ResolveIOServer.extractHostName = function (value) {
        var normalizedBase = this.normalizeBaseUrl(value || '');
        if (!normalizedBase) {
            return null;
        }
        try {
            return new URL(normalizedBase).hostname || null;
        }
        catch (_a) {
            return null;
        }
    };
    ResolveIOServer.getClientRoutes = function () {
        return ResolveIOServer._clientRoutes;
    };
    ResolveIOServer.getClientDir = function () {
        return ResolveIOServer._clientDir;
    };
    ResolveIOServer.getSESMail = function () {
        return ResolveIOServer._sesMail;
    };
    ResolveIOServer.getpublicProgram = function () {
        return ResolveIOServer._publicProgram;
    };
    ResolveIOServer._serverConfig = null;
    ResolveIOServer._clientRoutes = [];
    ResolveIOServer._mongoConnection = null;
    ResolveIOServer._mainDB = null;
    ResolveIOServer._mainServer = null;
    ResolveIOServer._localLogManager = null;
    ResolveIOServer._mongoManager = null;
    ResolveIOServer._client = '';
    ResolveIOServer._clientDir = '';
    ResolveIOServer._sesMail = true;
    ResolveIOServer._publicProgram = false;
    ResolveIOServer._reconnecting = false;
    ResolveIOServer._mongoReconnectPromise = null;
    ResolveIOServer._lastMongoPoolClearedLogMs = 0;
    ResolveIOServer.MONGO_POOL_CLEARED_DEBOUNCE_MS = 1000;
    return ResolveIOServer;
}());
exports.ResolveIOServer = ResolveIOServer;

//# sourceMappingURL=resolveio-server-app.js.map
