"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 __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.start = exports.lernaBootstrap = exports.init = exports.parseGraph = exports.readConfig = exports.validateConfig = void 0;
const get_project_root_1 = require("../utils/get-project-root");
const get_lerna_graph_1 = require("../utils/get-lerna-graph");
const logs_1 = require("../utils/logs");
const external_binaries_1 = require("../utils/external-binaries");
const child_process_1 = require("child_process");
const server_1 = require("../server");
const socket_1 = require("../server/socket");
const socket_2 = require("../ipc/socket");
const ascii_1 = require("../utils/ascii");
const ora_1 = __importDefault(require("ora"));
const read_config_1 = require("../config/read-config");
const chalk_1 = __importDefault(require("chalk"));
exports.validateConfig = (config, graph) => {
    const validating = ora_1.default('Validating config 🔧').start();
    try {
        config.validate(graph);
    }
    catch (e) {
        validating.fail('Invalid microlambda config file');
        console.error(chalk_1.default.red('Please check the docs and provide a valid configuration.'));
        console.error(chalk_1.default.red(e));
        process.exit(1);
    }
    validating.succeed('Config valid');
    return config.config;
};
exports.readConfig = (projectRoot, logger) => __awaiter(void 0, void 0, void 0, function* () {
    const loadingConfig = ora_1.default('Loading config ⚙️').start();
    const reader = new read_config_1.ConfigReader(logger);
    let config;
    try {
        config = reader.readConfig();
    }
    catch (e) {
        loadingConfig.fail('Cannot read microlambda config file');
        console.error(chalk_1.default.red(e));
        process.exit(1);
    }
    yield external_binaries_1.verifyBinaries(config.compilationMode, projectRoot, logger);
    logger.log('start').debug(config);
    loadingConfig.succeed();
    return reader;
});
exports.parseGraph = (projectRoot, scheduler, config, logger, defaultPort) => __awaiter(void 0, void 0, void 0, function* () {
    let lernaVersion;
    try {
        lernaVersion = child_process_1.execSync('npx lerna -v').toString();
        logger.log('graph').info('Using lerna', lernaVersion);
    }
    catch (e) {
        logger.log('graph').warn('cannot determine lerna version');
    }
    const parsingGraph = ora_1.default('Parsing lerna dependency graph 🐉').start();
    const graph = yield get_lerna_graph_1.getLernaGraph(projectRoot, scheduler, config, logger, defaultPort);
    parsingGraph.succeed();
    return graph;
});
exports.init = (logger, scheduler, defaultPort) => __awaiter(void 0, void 0, void 0, function* () {
    const log = logger.log('start');
    const projectRoot = get_project_root_1.getProjectRoot(logger);
    log.info('Project root resolved', projectRoot);
    const config = yield exports.readConfig(projectRoot, logger);
    const graph = yield exports.parseGraph(projectRoot, scheduler, config.config, logger, defaultPort);
    exports.validateConfig(config, graph);
    return { projectRoot, config: config.config, graph };
});
exports.lernaBootstrap = (graph, logger) => __awaiter(void 0, void 0, void 0, function* () {
    const installing = ora_1.default('Installing dependencies 📦').start();
    yield graph.bootstrap().catch((e) => {
        const message = 'Error installing microservices dependencies. Run in verbose mode (export MILA_DEBUG=*) for more infos.';
        logger.log('bootstrap').error(e);
        logger.log('bootstrap').error(message);
        console.error(message);
        process.exit(1);
    });
    installing.text = 'Dependencies installed 📦';
    installing.succeed();
});
exports.start = (scheduler, options, logger) => __awaiter(void 0, void 0, void 0, function* () {
    console.info(ascii_1.showOff());
    const { projectRoot, config, graph } = yield exports.init(logger, scheduler, options.defaultPort);
    yield exports.lernaBootstrap(graph, logger);
    const startingServer = ora_1.default('Starting server').start();
    const server = yield server_1.startServer(graph, logger);
    startingServer.text = 'Mila server started on http://localhost:4545 ✨';
    startingServer.succeed();
    const starting = ora_1.default('Application started 🚀 !').start();
    starting.succeed();
    scheduler.setGraph(graph);
    const io = new socket_1.IOSocketManager(server, scheduler, logger, graph);
    logger.setIO(io);
    graph.registerIOSockets(io);
    const ipc = new socket_2.IPCSocketsManager(projectRoot, scheduler, logger, graph);
    yield ipc.createServer();
    graph.registerIPCServer(ipc);
    logger.log('start').debug('Services excluded by config', config.noStart);
    const enabledServices = graph.getServices().filter((s) => !config.noStart.includes(s.getName()));
    logger.log('start').debug('Enabled services', enabledServices.map((s) => s.getName()));
    enabledServices.forEach((s) => s.enable());
    graph.enableNodes();
    logger.log('start').debug('Enabled nodes', graph
        .getNodes()
        .filter((n) => n.isEnabled())
        .map((n) => n.getName()));
    logs_1.recreateLogDirectory(projectRoot, logger);
    process.on('SIGINT', () => __awaiter(void 0, void 0, void 0, function* () {
        logger.log('start').warn('SIGINT signal received');
        console.log('\n');
        const gracefulShutdown = ora_1.default('Gracefully shutting down services ☠️');
        try {
            yield scheduler.stopProject(graph);
        }
        catch (e) {
            console.error('Error stopping services. Allocated ports may still be busy !');
            process.exit(2);
        }
        gracefulShutdown.succeed();
        process.exit(0);
    }));
    if (!options.interactive) {
        logger.log('start').info('Starting services');
        yield scheduler.startProject(graph, options.recompile);
    }
});
//# sourceMappingURL=start.js.map