"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());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
// NOTE: This file is used to clean up resources used by CLI, when the CLI is killed.
// The instances here are not shared with the ones in main CLI process.
const fs = require("fs");
const path = require("path");
const shelljs = require("shelljs");
const _ = require("lodash");
const file_log_service_1 = require("./file-log-service");
const yok_1 = require("../common/yok");
const pathToBootstrap = process.argv[2];
if (!pathToBootstrap || !fs.existsSync(pathToBootstrap)) {
    throw new Error("Invalid path to bootstrap.");
}
const logFile = process.argv[3];
// After requiring the bootstrap we can use $injector
require(pathToBootstrap);
const fileLogService = yok_1.injector.resolve(file_log_service_1.FileLogService, {
    logFile,
});
fileLogService.logData({ message: "Initializing Cleanup process." });
const commandsInfos = [];
const filesToDelete = [];
const jsCommands = [];
const requests = [];
const executeRequest = (request) => __awaiter(void 0, void 0, void 0, function* () {
    const $httpClient = yok_1.injector.resolve("httpClient");
    try {
        fileLogService.logData({
            message: `Start executing request: ${request.method} ${request.url}`,
        });
        const response = yield $httpClient.httpRequest({
            url: request.url,
            method: request.method,
            headers: request.headers,
            body: request.body,
        });
        const responseStatus = response && response.response && response.response.statusCode;
        fileLogService.logData({
            message: `Finished executing request: ${request.method} ${request.url} and got status ${responseStatus}`,
        });
    }
    catch (e) {
        fileLogService.logData({
            message: `Unable to execute request: ${request.method} ${request.url}`,
        });
    }
});
const executeJSCleanup = (jsCommand) => __awaiter(void 0, void 0, void 0, function* () {
    const $childProcess = yok_1.injector.resolve("childProcess");
    try {
        fileLogService.logData({
            message: `Start executing action for file: ${jsCommand.filePath} and data ${JSON.stringify(jsCommand.data)}`,
        });
        yield $childProcess.trySpawnFromCloseEvent(process.execPath, [
            path.join(__dirname, "cleanup-js-subprocess.js"),
            pathToBootstrap,
            logFile,
            jsCommand.filePath,
            JSON.stringify(jsCommand.data),
        ], {}, { throwError: true, timeout: jsCommand.timeout || 3000 });
        fileLogService.logData({
            message: `Finished executing action for file: ${jsCommand.filePath} and data ${JSON.stringify(jsCommand.data)}`,
        });
    }
    catch (err) {
        fileLogService.logData({
            message: `Unable to execute action for file ${jsCommand.filePath} with data ${JSON.stringify(jsCommand.data)}. Error is: ${err}.`,
            type: "Error" /* FileLogMessageType.Error */,
        });
    }
});
const executeCleanup = () => __awaiter(void 0, void 0, void 0, function* () {
    const $childProcess = yok_1.injector.resolve("childProcess");
    for (const request of requests) {
        yield executeRequest(request);
    }
    for (const jsCommand of jsCommands) {
        yield executeJSCleanup(jsCommand);
    }
    for (const commandInfo of commandsInfos) {
        try {
            fileLogService.logData({
                message: `Start executing command: ${JSON.stringify(commandInfo)}`,
            });
            yield $childProcess.trySpawnFromCloseEvent(commandInfo.command, commandInfo.args, commandInfo.options || {}, { throwError: true, timeout: commandInfo.timeout || 3000 });
            fileLogService.logData({
                message: `Successfully executed command: ${JSON.stringify(commandInfo)}`,
            });
        }
        catch (err) {
            fileLogService.logData({
                message: `Unable to execute command: ${JSON.stringify(commandInfo)}. Error is: ${err}.`,
                type: "Error" /* FileLogMessageType.Error */,
            });
        }
    }
    if (filesToDelete.length) {
        try {
            fileLogService.logData({
                message: `Deleting files ${filesToDelete.join(" ")}`,
            });
            shelljs.rm("-Rf", filesToDelete);
        }
        catch (err) {
            fileLogService.logData({
                message: `Unable to delete files: ${JSON.stringify(filesToDelete)}. Error is: ${err}.`,
                type: "Error" /* FileLogMessageType.Error */,
            });
        }
    }
    fileLogService.logData({ message: `cleanup-process finished` });
    process.exit();
});
const addCleanupAction = (commandInfo) => {
    if (_.some(commandsInfos, (currentCommandInfo) => _.isEqual(currentCommandInfo, commandInfo))) {
        fileLogService.logData({
            message: `cleanup-process will not add command for execution as it has been added already: ${JSON.stringify(commandInfo)}`,
        });
    }
    else {
        fileLogService.logData({
            message: `cleanup-process added command for execution: ${JSON.stringify(commandInfo)}`,
        });
        commandsInfos.push(commandInfo);
    }
};
const removeCleanupAction = (commandInfo) => {
    if (_.some(commandsInfos, (currentCommandInfo) => _.isEqual(currentCommandInfo, commandInfo))) {
        _.remove(commandsInfos, (currentCommandInfo) => _.isEqual(currentCommandInfo, commandInfo));
        fileLogService.logData({
            message: `cleanup-process removed command for execution: ${JSON.stringify(commandInfo)}`,
        });
    }
    else {
        fileLogService.logData({
            message: `cleanup-process cannot remove command for execution as it has not been added before: ${JSON.stringify(commandInfo)}`,
        });
    }
};
const addRequest = (requestInfo) => {
    if (_.some(requests, (currentRequestInfo) => _.isEqual(currentRequestInfo, requestInfo))) {
        fileLogService.logData({
            message: `cleanup-process will not add request for execution as it has been added already: ${JSON.stringify(requestInfo)}`,
        });
    }
    else {
        fileLogService.logData({
            message: `cleanup-process added request for execution: ${JSON.stringify(requestInfo)}`,
        });
        requests.push(requestInfo);
    }
};
const removeRequest = (requestInfo) => {
    if (_.some(requests, (currentRequestInfo) => _.isEqual(currentRequestInfo, currentRequestInfo))) {
        _.remove(requests, (currentRequestInfo) => _.isEqual(currentRequestInfo, requestInfo));
        fileLogService.logData({
            message: `cleanup-process removed request for execution: ${JSON.stringify(requestInfo)}`,
        });
    }
    else {
        fileLogService.logData({
            message: `cleanup-process cannot remove request for execution as it has not been added before: ${JSON.stringify(requestInfo)}`,
        });
    }
};
const addDeleteAction = (filePath) => {
    const fullPath = path.resolve(filePath);
    if (_.some(filesToDelete, (f) => f === fullPath)) {
        fileLogService.logData({
            message: `cleanup-process will not add ${fullPath} for deletion as it has been added already`,
        });
    }
    else {
        filesToDelete.push(fullPath);
        fileLogService.logData({
            message: `cleanup-process added ${fullPath} for deletion`,
        });
    }
};
const removeDeleteAction = (filePath) => {
    const fullPath = path.resolve(filePath);
    if (_.some(filesToDelete, (f) => f === fullPath)) {
        _.remove(filesToDelete, (f) => f === fullPath);
        fileLogService.logData({
            message: `cleanup-process removed ${fullPath} from the list of files for deletion.`,
        });
    }
    else {
        fileLogService.logData({
            message: `cleanup-process cannot remove ${fullPath} for deletion as no such entry is found in the files marked for deletion`,
        });
    }
};
const addJSFile = (jsCommand) => {
    const fullPath = path.resolve(jsCommand.filePath);
    jsCommand.filePath = fullPath;
    if (_.some(jsCommands, (currentJSCommand) => _.isEqual(currentJSCommand, jsCommand))) {
        fileLogService.logData({
            message: `cleanup-process will not add JS file for execution as it has been added already: ${JSON.stringify(jsCommand)}`,
        });
    }
    else {
        fileLogService.logData({
            message: `cleanup-process added JS file for execution: ${JSON.stringify(jsCommand)}`,
        });
        jsCommands.push(jsCommand);
    }
};
const removeJSFile = (jsCommand) => {
    const fullPath = path.resolve(jsCommand.filePath);
    jsCommand.filePath = fullPath;
    if (_.some(jsCommands, (currentJSCommand) => _.isEqual(currentJSCommand, jsCommand))) {
        _.remove(jsCommands, (currentJSCommand) => _.isEqual(currentJSCommand, jsCommand));
        fileLogService.logData({
            message: `cleanup-process removed JS action for execution: ${JSON.stringify(jsCommand)}`,
        });
    }
    else {
        fileLogService.logData({
            message: `cleanup-process cannot remove JS action for execution as it has not been added before: ${JSON.stringify(jsCommand)}`,
        });
    }
};
process.on("message", (cleanupProcessMessage) => __awaiter(void 0, void 0, void 0, function* () {
    fileLogService.logData({
        message: `cleanup-process received message of type: ${JSON.stringify(cleanupProcessMessage)}`,
    });
    switch (cleanupProcessMessage.messageType) {
        case "AddCleanCommand" /* CleanupProcessMessage.AddCleanCommand */:
            addCleanupAction(cleanupProcessMessage.commandInfo);
            break;
        case "RemoveCleanCommand" /* CleanupProcessMessage.RemoveCleanCommand */:
            removeCleanupAction(cleanupProcessMessage.commandInfo);
            break;
        case "AddRequest" /* CleanupProcessMessage.AddRequest */:
            addRequest(cleanupProcessMessage.requestInfo);
            break;
        case "RemoveRequest" /* CleanupProcessMessage.RemoveRequest */:
            removeRequest(cleanupProcessMessage.requestInfo);
            break;
        case "AddDeleteFileAction" /* CleanupProcessMessage.AddDeleteFileAction */:
            addDeleteAction(cleanupProcessMessage.filePath);
            break;
        case "RemoveDeleteFileAction" /* CleanupProcessMessage.RemoveDeleteFileAction */:
            removeDeleteAction(cleanupProcessMessage.filePath);
            break;
        case "AddJSFileToRequire" /* CleanupProcessMessage.AddJSFileToRequire */:
            const jsCleanupMessage = cleanupProcessMessage;
            addJSFile(jsCleanupMessage.jsCommand);
            break;
        case "RemoveJSFileToRequire" /* CleanupProcessMessage.RemoveJSFileToRequire */:
            const msgToRemove = cleanupProcessMessage;
            removeJSFile(msgToRemove.jsCommand);
            break;
        default:
            fileLogService.logData({
                message: `Unable to handle message of type ${cleanupProcessMessage.messageType}. Full message is ${JSON.stringify(cleanupProcessMessage)}`,
                type: "Error" /* FileLogMessageType.Error */,
            });
            break;
    }
}));
process.on("disconnect", () => __awaiter(void 0, void 0, void 0, function* () {
    fileLogService.logData({
        message: "cleanup-process received process.disconnect event",
    });
    yield executeCleanup();
    yok_1.injector.dispose();
    process.exit();
}));
fileLogService.logData({
    message: `cleanup-process will send ${"ProcessReadyToReceive" /* DetachedProcessMessages.ProcessReadyToReceive */} message`,
});
process.send("ProcessReadyToReceive" /* DetachedProcessMessages.ProcessReadyToReceive */);
//# sourceMappingURL=cleanup-process.js.map