"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
let fipsError;
function enableFipsIfRequested() {
    if (process.argv.includes('--tlsFIPSMode')) {
        try {
            require('crypto').setFips(1);
        }
        catch (err) {
            fipsError ??= err;
        }
    }
}
enableFipsIfRequested();
const startup_timing_1 = require("./startup-timing");
const cli_repl_1 = require("./cli-repl");
const arg_parser_1 = require("./arg-parser");
const smoke_tests_1 = require("./smoke-tests");
const constants_1 = require("./constants");
const build_info_1 = require("./build-info");
const config_directory_1 = require("./config-directory");
const crypt_library_paths_1 = require("./crypt-library-paths");
const tls_certificate_selector_1 = require("./tls-certificate-selector");
const pac_proxy_s390x_patch_1 = require("./pac-proxy-s390x-patch");
const mongodb_redact_1 = require("mongodb-redact");
const arg_parser_2 = require("@mongosh/arg-parser");
const askcharacter_1 = __importDefault(require("askcharacter"));
const stream_1 = require("stream");
const crypto_1 = __importDefault(require("crypto"));
const net_1 = __importDefault(require("net"));
const v8_1 = __importDefault(require("v8"));
const types_1 = require("@mongosh/types");
require("./webpack-self-inspection");
const devtools_proxy_support_1 = require("@mongodb-js/devtools-proxy-support");
if (v8_1.default?.startupSnapshot?.isBuildingSnapshot?.()) {
    require('@mongodb-js/saslprep');
    require('socks');
    require('emphasize');
    require('ipv6-normalize');
    require('bindings');
    require('system-ca');
    require('@mongodb-js/socksv5/lib/server');
    require('@mongodb-js/socksv5/lib/auth/None');
    require('@mongodb-js/socksv5/lib/auth/UserPassword');
    require('lru-cache');
    {
        const console = require('console');
        const ConsoleCtor = console.Console;
        v8_1.default.startupSnapshot.addDeserializeCallback(() => {
            console.Console = ConsoleCtor;
            process.chdir('.');
        });
    }
    v8_1.default.startupSnapshot.setDeserializeMainFunction(() => {
        enableFipsIfRequested();
        (0, startup_timing_1.markTime)(types_1.TimingCategories.Snapshot, 'loaded pre-snapshot deps');
        void main();
    });
}
else {
    void main();
}
async function main() {
    (0, startup_timing_1.markTime)(types_1.TimingCategories.Main, 'entered main');
    suppressExperimentalWarnings();
    if (process.env.MONGOSH_RUN_NODE_SCRIPT) {
        process.argv.splice(1, 1);
        require('module').runMain(process.argv[1]);
        return;
    }
    let repl;
    let isSingleConsoleProcess = false;
    try {
        net_1.default?.setDefaultAutoSelectFamily?.(true);
        const { parsed: options, warnings } = (0, arg_parser_1.parseMongoshArgs)(process.argv);
        for (const warning of warnings) {
            console.warn(warning);
        }
        const { version } = require('../package.json');
        if (options.tlsFIPSMode) {
            if (!fipsError && !crypto_1.default.getFips()) {
                fipsError = new Error('FIPS mode not enabled despite requested');
            }
            if (fipsError) {
                if (process.config.variables.node_shared_openssl) {
                    console.error('Could not enable FIPS mode. Please ensure that your system OpenSSL installation');
                    console.error('supports FIPS, and see the mongosh FIPS documentation for more information.');
                }
                else {
                    console.error('Could not enable FIPS mode. This mongosh installation does not appear to');
                    console.error('support FIPS. Please see the mongosh FIPS documentation for more information.');
                }
                console.error('Error details:');
                console.error(fipsError);
                process.exit(1);
            }
        }
        if (options.help) {
            console.log(constants_1.USAGE);
            return;
        }
        if (options.version) {
            console.log((0, build_info_1.baseBuildInfo)().version);
            return;
        }
        if (options.buildInfo) {
            console.log(JSON.stringify(await (0, build_info_1.buildInfo)(), null, '  '));
            return;
        }
        if (options.smokeTests || options.perfTests) {
            const smokeTestServer = process.env.MONGOSH_SMOKE_TEST_SERVER;
            const cryptLibraryOpts = options.cryptSharedLibPath
                ? [`--cryptSharedLibPath=${options.cryptSharedLibPath}`]
                : [];
            if (process.execPath === process.argv[1]) {
                await (0, smoke_tests_1.runSmokeTests)({
                    smokeTestServer,
                    args: [process.execPath, ...cryptLibraryOpts],
                    wantPerformanceTesting: !!options.perfTests,
                });
            }
            else {
                await (0, smoke_tests_1.runSmokeTests)({
                    smokeTestServer,
                    args: [process.execPath, process.argv[1], ...cryptLibraryOpts],
                    wantPerformanceTesting: !!options.perfTests,
                });
            }
            return;
        }
        if (process.execPath === process.argv[1]) {
            process.removeAllListeners('warning');
        }
        if (process.env.CLEAR_SIGINT_LISTENERS) {
            process.removeAllListeners('SIGINT');
        }
        (0, pac_proxy_s390x_patch_1.applyPacProxyS390XPatch)();
        process.on('exit', () => {
            process.stdin?.setRawMode?.(false);
        });
        isSingleConsoleProcess =
            !!process.env.MONGOSH_FORCE_CONNECTION_STRING_PROMPT;
        if ((!options.connectionSpecifier &&
            process.platform === 'win32' &&
            process.stdin.isTTY &&
            process.stdout.isTTY) ||
            isSingleConsoleProcess) {
            try {
                isSingleConsoleProcess ||=
                    require('get-console-process-list')().length === 1;
            }
            catch {
            }
            if (isSingleConsoleProcess) {
                const result = await ask('Please enter a MongoDB connection string (Default: mongodb://localhost/): ');
                if (result.trim() !== '') {
                    options.connectionSpecifier = result.trim();
                }
            }
        }
        (0, startup_timing_1.markTime)(types_1.TimingCategories.Main, 'scheduling system-ca loading');
        (0, devtools_proxy_support_1.systemCA)().catch(() => undefined);
        (0, startup_timing_1.markTime)(types_1.TimingCategories.Main, 'scheduled system-ca loading');
        const connectionInfo = (0, arg_parser_2.generateConnectionInfoFromCliArgs)(options);
        connectionInfo.driverOptions = {
            ...connectionInfo.driverOptions,
            ...(await (0, tls_certificate_selector_1.getTlsCertificateSelector)(options.tlsCertificateSelector)),
            driverInfo: { name: 'mongosh', version },
        };
        const title = `mongosh ${(0, mongodb_redact_1.redactConnectionString)(connectionInfo.connectionString)}`;
        process.title = title;
        setTerminalWindowTitle(title);
        const shellHomePaths = (0, config_directory_1.getStoragePaths)();
        const globalConfigPaths = (0, config_directory_1.getGlobalConfigPaths)();
        repl = new cli_repl_1.CliRepl({
            shellCliOptions: {
                ...options,
            },
            getCryptLibraryPaths: crypt_library_paths_1.getCryptLibraryPaths,
            input: process.stdin,
            output: process.stdout,
            promptOutput: process.env.TEST_USE_STDOUT_FOR_PASSWORD || process.stdout.isTTY
                ? process.stdout
                : process.stderr,
            onExit,
            shellHomePaths: shellHomePaths,
            globalConfigPaths: globalConfigPaths,
        });
        (0, startup_timing_1.markTime)(types_1.TimingCategories.REPLInstantiation, 'entering repl.start()');
        await repl.start(connectionInfo.connectionString, {
            productName: 'MongoDB Shell',
            productDocsLink: 'https://www.mongodb.com/docs/mongodb-shell/',
            ...connectionInfo.driverOptions,
        });
    }
    catch (e) {
        if (process.env.MONGOSH_DISPLAY_STARTUP_STACK_TRACE)
            console.error(e?.stack);
        else
            console.error(`${e?.name}: ${e?.message}`);
        if (repl !== undefined) {
            repl.bus.emit('mongosh:error', e, 'startup');
        }
        if (isSingleConsoleProcess) {
            process.stdout.write('Press any key to exit: ');
            await (0, askcharacter_1.default)({ input: process.stdin, output: process.stdout });
            process.stdout.write('\n');
        }
        process.exit(1);
    }
}
function setTerminalWindowTitle(title) {
    if (!process.stdout.isTTY) {
        return;
    }
    const term = process.env.TERM ?? '';
    if (/^(linux|xterm|rxvt)/.test(term)) {
        process.stdout.write(`\u001b]0;${title}\u0007`);
    }
    else if (/^screen/.test(term)) {
        process.stdout.write(`\u001bk${title}\u001b\\`);
    }
}
async function ask(prompt) {
    const stdinCopy = process.stdin.pipe(new stream_1.PassThrough());
    try {
        const { createInterface } = require('readline');
        const readlineInterface = createInterface({
            input: stdinCopy,
            output: process.stdout,
            prompt,
        });
        readlineInterface.prompt();
        for await (const line of readlineInterface) {
            return line;
        }
        return '';
    }
    finally {
        process.stdin.unpipe(stdinCopy);
    }
}
function suppressExperimentalWarnings() {
    const nodeMajorVersion = process.versions.node.split('.').map(Number)[0];
    if (nodeMajorVersion >= 23) {
        const originalEmit = process.emitWarning;
        process.emitWarning = (warning, ...args) => {
            if (args[0] === 'ExperimentalWarning') {
                return;
            }
            if (typeof args[0] === 'object' &&
                args[0].type === 'ExperimentalWarning') {
                return;
            }
            return originalEmit(warning, ...args);
        };
    }
}
function onExit(code) {
    setTerminalWindowTitle('');
    try {
        try {
            if (code === undefined)
                process.exit();
            else
                process.exit(code);
        }
        finally {
            if (code === undefined)
                process.exit();
            else
                process.exit(code);
        }
    }
    catch (err) {
        process.stderr.write(String(err) + '\n');
    }
    finally {
        process.stderr.write('process.exit() returned -- aborting\n');
        process.abort();
    }
}
//# sourceMappingURL=run.js.map