"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
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;
    return g = { next: verb(0), "throw": verb(1), "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 (_) 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 };
    }
};
exports.__esModule = true;
exports.DevfileConverter = void 0;
var api_1 = require("@devfile/api");
var inversify_1 = require("inversify");
var jsYaml = __importStar(require("js-yaml"));
var jsoncparser = __importStar(require("jsonc-parser"));
var DevfileConverter = /** @class */ (function () {
    function DevfileConverter() {
        this.CHE_EDITOR_YAML = '.che/che-editor.yaml';
        this.CHE_THEIA_PLUGINS_YAML = '.che/che-theia-plugins.yaml';
        this.VSCODE_EXTENSIONS_JSON = '.vscode/extensions.json';
        this.VSCODE_LAUNCH_JSON = '.vscode/launch.json';
    }
    DevfileConverter.prototype.componentVolumeV1toComponentVolumeV2 = function (componentVolumes) {
        if (componentVolumes) {
            return componentVolumes.map(function (volumeV1) {
                // eslint-disable-next-line @typescript-eslint/no-explicit-any
                var volume = {};
                if (volumeV1.name) {
                    volume.name = volumeV1.name;
                    // volume names should not use _
                    volume.name = volume.name.replace(/_/g, '-');
                }
                if (volumeV1.containerPath) {
                    volume.path = volumeV1.containerPath;
                }
                return volume;
            });
        }
        return undefined;
    };
    DevfileConverter.prototype.componentVolumeV2toComponentVolumeV1 = function (componentVolumes) {
        if (componentVolumes) {
            return componentVolumes.map(function (volumeV2) {
                // eslint-disable-next-line @typescript-eslint/no-explicit-any
                var volume = {};
                if (volumeV2.name) {
                    volume.name = volumeV2.name;
                }
                if (volumeV2.path) {
                    volume.containerPath = volumeV2.path;
                }
                return volume;
            });
        }
        return undefined;
    };
    DevfileConverter.prototype.componentEndpointV1toComponentEndpointV2 = function (componentEndpoints) {
        if (componentEndpoints) {
            return componentEndpoints.map(function (endpointV1) {
                // eslint-disable-next-line @typescript-eslint/no-explicit-any
                var endpoint = {};
                if (endpointV1.name) {
                    endpoint.name = endpointV1.name;
                }
                if (endpointV1.port) {
                    endpoint.targetPort = endpointV1.port;
                }
                if (endpointV1.attributes) {
                    endpoint.attributes = endpointV1.attributes;
                    if (endpoint.attributes['type'] === 'ide') {
                        endpoint.attributes['type'] = 'main';
                    }
                    if (endpointV1.attributes['public'] !== undefined && endpointV1.attributes['public'] === 'false') {
                        endpoint.exposure = 'internal';
                    }
                }
                return endpoint;
            });
        }
        return undefined;
    };
    DevfileConverter.prototype.componentEndpointV2toComponentEndpointV1 = function (componentEndpoints) {
        if (componentEndpoints) {
            return componentEndpoints.map(function (endpointV2) {
                // eslint-disable-next-line @typescript-eslint/no-explicit-any
                var endpoint = {};
                if (endpointV2.name) {
                    endpoint.name = endpointV2.name;
                }
                if (endpointV2.targetPort) {
                    endpoint.port = endpointV2.targetPort;
                }
                if (endpointV2.attributes) {
                    endpoint.attributes = endpointV2.attributes;
                }
                if (endpointV2.exposure === api_1.V220DevfileComponentsItemsContainerEndpoints.ExposureEnum.Internal) {
                    if (!endpoint.attributes) {
                        endpoint.attributes = {};
                    }
                    endpoint.attributes['public'] = 'false';
                }
                return endpoint;
            });
        }
        return undefined;
    };
    DevfileConverter.prototype.componentEnvV1toComponentEnvV2 = function (componentEnvs) {
        if (componentEnvs) {
            return componentEnvs.map(function (envV1) {
                // eslint-disable-next-line @typescript-eslint/no-explicit-any
                var env = {};
                if (envV1.name !== undefined) {
                    env.name = envV1.name;
                }
                if (envV1.value !== undefined) {
                    env.value = envV1.value;
                }
                return env;
            });
        }
        return undefined;
    };
    DevfileConverter.prototype.componentEnvV2toComponentEnvV1 = function (componentEnvs) {
        if (componentEnvs) {
            return componentEnvs.map(function (envV2) {
                // eslint-disable-next-line @typescript-eslint/no-explicit-any
                var env = {};
                if (envV2.name !== undefined) {
                    env.name = envV2.name;
                }
                if (envV2.value !== undefined) {
                    env.value = envV2.value;
                }
                return env;
            });
        }
        return undefined;
    };
    DevfileConverter.prototype.componentV2toComponentV1 = function (componentV2) {
        if (componentV2.kubernetes) {
            if (componentV2.kubernetes.inlined) {
                // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
                return JSON.parse(componentV2.kubernetes.inlined);
            }
            else {
                return undefined;
            }
        }
        else if (componentV2.openshift) {
            // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
            return JSON.parse(componentV2.openshift.inlined);
        }
        var devfileV1Component = {};
        if (componentV2.container) {
            devfileV1Component.type = 'dockerimage';
            if (componentV2.container.memoryLimit) {
                devfileV1Component.memoryLimit = componentV2.container.memoryLimit;
            }
            if (componentV2.container.memoryRequest) {
                devfileV1Component.memoryRequest = componentV2.container.memoryRequest;
            }
            if (componentV2.container.cpuLimit) {
                devfileV1Component.cpuLimit = componentV2.container.cpuLimit;
            }
            if (componentV2.container.cpuRequest) {
                devfileV1Component.cpuRequest = componentV2.container.cpuRequest;
            }
            if (componentV2.name) {
                devfileV1Component.alias = componentV2.name;
            }
            if (componentV2.container.mountSources) {
                devfileV1Component.mountSources = componentV2.container.mountSources;
            }
            else {
                // if not specified, mountSources needs to be added back on the container
                // as the default is not the same
                devfileV1Component.mountSources = true;
            }
            if (componentV2.container.args) {
                devfileV1Component.args = componentV2.container.args;
            }
            if (componentV2.container.command) {
                devfileV1Component.command = componentV2.container.command;
            }
            if (componentV2.container.image) {
                devfileV1Component.image = componentV2.container.image;
            }
            devfileV1Component.env = this.componentEnvV2toComponentEnvV1(componentV2.container.env);
            devfileV1Component.volumes = this.componentVolumeV2toComponentVolumeV1(componentV2.container.volumeMounts);
            devfileV1Component.endpoints = this.componentEndpointV2toComponentEndpointV1(componentV2.container.endpoints);
        }
        if (!devfileV1Component.env) {
            delete devfileV1Component.env;
        }
        if (!devfileV1Component.volumes) {
            delete devfileV1Component.volumes;
        }
        if (!devfileV1Component.endpoints) {
            delete devfileV1Component.endpoints;
        }
        if (Object.keys(devfileV1Component).length === 0) {
            return undefined;
        }
        return devfileV1Component;
    };
    DevfileConverter.prototype.componentV1toComponentV2 = function (componentV1) {
        var devfileV2Component = {};
        if (componentV1.alias) {
            devfileV2Component.name = componentV1.alias;
        }
        if (componentV1.type === 'dockerimage') {
            devfileV2Component.container = {
                image: componentV1.image
            };
            if (componentV1.command) {
                devfileV2Component.container.command = componentV1.command;
            }
            if (componentV1.args) {
                devfileV2Component.container.args = componentV1.args;
            }
            if (componentV1.cpuLimit) {
                devfileV2Component.container.cpuLimit = componentV1.cpuLimit;
            }
            if (componentV1.cpuRequest) {
                devfileV2Component.container.cpuRequest = componentV1.cpuRequest;
            }
            if (componentV1.memoryLimit) {
                devfileV2Component.container.memoryLimit = componentV1.memoryLimit;
            }
            if (componentV1.memoryRequest) {
                devfileV2Component.container.memoryRequest = componentV1.memoryRequest;
            }
            if (componentV1.mountSources) {
                devfileV2Component.container.mountSources = componentV1.mountSources;
            }
            devfileV2Component.container.env = this.componentEnvV1toComponentEnvV2(componentV1.env);
            devfileV2Component.container.volumeMounts = this.componentVolumeV1toComponentVolumeV2(componentV1.volumes);
            devfileV2Component.container.endpoints = this.componentEndpointV1toComponentEndpointV2(componentV1.endpoints);
        }
        else if (componentV1.type === 'kubernetes') {
            devfileV2Component.kubernetes = {};
            devfileV2Component.kubernetes.inlined = JSON.stringify(componentV1);
        }
        else if (componentV1.type === 'openshift') {
            devfileV2Component.openshift = {};
            devfileV2Component.openshift.inlined = JSON.stringify(componentV1);
        }
        else if (componentV1.type == 'chePlugin' || componentV1.type == 'cheEditor') {
            // components are processed as inline attributes
            return undefined;
        }
        return devfileV2Component;
    };
    DevfileConverter.prototype.commandV1toCommandV2 = function (commandV1) {
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        var devfileV2Command = {};
        if (commandV1.name) {
            // the id can't have spaces
            // replace space by dash and then remove all special characters
            devfileV2Command.id = commandV1.name
                .replace(/\s+/g, '-')
                .replace(/[^a-zA-Z-]/g, '')
                .toLowerCase();
            // needs to be max 63 characters
            if (devfileV2Command.id.length > 63) {
                devfileV2Command.id = devfileV2Command.id.substring(0, 63);
            }
            // trim '-' character from start or end
            devfileV2Command.id = devfileV2Command.id.replace(/^\-+|\-+$/g, '');
        }
        if (commandV1.actions && commandV1.actions[0].type === 'exec') {
            devfileV2Command.exec = {};
            var action = commandV1.actions[0];
            // label is the same as name
            if (commandV1.name) {
                devfileV2Command.exec.label = commandV1.name;
            }
            if (action.command) {
                devfileV2Command.exec.commandLine = action.command;
            }
            if (action.component) {
                devfileV2Command.exec.component = action.component;
            }
            if (action.workdir) {
                devfileV2Command.exec.workingDir = action.workdir;
            }
            return devfileV2Command;
        }
        // undefined if do not know what to do
        return undefined;
    };
    DevfileConverter.prototype.commandV2toCommandV1 = function (commandV2) {
        var devfileV1Command = {};
        if (commandV2.id) {
            devfileV1Command.name = commandV2.id;
        }
        if (commandV2.exec) {
            if (commandV2.exec.label) {
                devfileV1Command.name = commandV2.exec.label;
            }
            var devfileAction = {};
            if (commandV2.exec.commandLine) {
                devfileAction.command = commandV2.exec.commandLine;
            }
            if (commandV2.exec.component) {
                devfileAction.component = commandV2.exec.component;
            }
            if (commandV2.exec.workingDir) {
                devfileAction.workdir = commandV2.exec.workingDir;
            }
            devfileAction.type = 'exec';
            devfileV1Command.actions = [devfileAction];
            return devfileV1Command;
        }
        return undefined;
    };
    DevfileConverter.prototype.projectV1toProjectV2 = function (projectV1) {
        var devfileV2Project = {
            attributes: {},
            name: projectV1.name
        };
        if (projectV1.clonePath) {
            devfileV2Project.clonePath = projectV1.clonePath;
        }
        if (projectV1.source) {
            var source = projectV1.source;
            if (source.type === 'git' || source.type === 'github') {
                var remotes = { origin: source.location };
                devfileV2Project.git = {
                    remotes: remotes
                };
                var checkoutFromRevision = void 0;
                if (source.branch) {
                    checkoutFromRevision = source.branch;
                    devfileV2Project.attributes['source-origin'] = 'branch';
                }
                else if (source.commitId) {
                    checkoutFromRevision = source.commitId;
                    devfileV2Project.attributes['source-origin'] = 'commitId';
                }
                else if (source.startPoint) {
                    checkoutFromRevision = source.startPoint;
                    devfileV2Project.attributes['source-origin'] = 'startPoint';
                }
                else if (source.tag) {
                    checkoutFromRevision = source.tag;
                    devfileV2Project.attributes['source-origin'] = 'tag';
                }
                if (checkoutFromRevision) {
                    devfileV2Project.git.checkoutFrom = {
                        revision: checkoutFromRevision
                    };
                }
            }
            else if (source.type === 'zip') {
                devfileV2Project.zip = {
                    location: source.location
                };
            }
        }
        return devfileV2Project;
    };
    DevfileConverter.prototype.projectInfoToProjectSource = function (project, projectInfo) {
        var gitSource = {};
        if (projectInfo.checkoutFrom) {
            if (project.attributes && project.attributes['source-origin']) {
                var origin = project.attributes['source-origin'];
                delete project.attributes['source-origin'];
                if (origin === 'branch') {
                    gitSource.branch = projectInfo.checkoutFrom.revision;
                }
                if (origin === 'commitId') {
                    gitSource.commitId = projectInfo.checkoutFrom.revision;
                }
                if (origin === 'startPoint') {
                    gitSource.startPoint = projectInfo.checkoutFrom.revision;
                }
                if (origin === 'tag') {
                    gitSource.tag = projectInfo.checkoutFrom.revision;
                }
            }
            else {
                gitSource.startPoint = projectInfo.checkoutFrom.revision;
            }
        }
        var remoteKeys = Object.keys(projectInfo.remotes);
        gitSource.location = projectInfo.remotes[remoteKeys[0]];
        gitSource.type = 'git';
        return gitSource;
    };
    DevfileConverter.prototype.metadataV1toMetadataV2 = function (metadataV1) {
        var devfileMetadataV2 = {};
        if (metadataV1) {
            if (metadataV1.generateName) {
                devfileMetadataV2.name = metadataV1.generateName;
                if (!devfileMetadataV2.attributes) {
                    devfileMetadataV2.attributes = {};
                }
                devfileMetadataV2.attributes['metadata-name-field'] = 'generateName';
                devfileMetadataV2.attributes['metadata-name-original-value'] = metadataV1.generateName;
                // remove the trailing - to make it compliant with kubernetes name
                if (devfileMetadataV2.name.endsWith('-')) {
                    devfileMetadataV2.name = devfileMetadataV2.name.slice(0, -1);
                }
            }
            if (metadataV1.name) {
                devfileMetadataV2.name = metadataV1.name;
                if (!devfileMetadataV2.attributes) {
                    devfileMetadataV2.attributes = {};
                }
                devfileMetadataV2.attributes['metadata-name-field'] = 'name';
            }
        }
        return devfileMetadataV2;
    };
    DevfileConverter.prototype.metadataV2toMetadataV1 = function (metadataV2) {
        var devfileMetadataV1 = {};
        if (metadataV2) {
            if (metadataV2.name) {
                var metaDataAttributes = metadataV2.attributes || {};
                var nameField = metaDataAttributes['metadata-name-field'];
                var originalValue = metaDataAttributes['metadata-name-original-value'];
                if (nameField === 'generateName' && originalValue) {
                    devfileMetadataV1.generateName = originalValue;
                }
                else if (nameField === 'name') {
                    devfileMetadataV1.name = metadataV2.name;
                }
                else {
                    devfileMetadataV1.generateName = metadataV2.name;
                }
                if (metadataV2.attributes) {
                    delete metadataV2.attributes['metadata-name-field'];
                    delete metadataV2.attributes['metadata-name-original-value'];
                }
            }
        }
        return devfileMetadataV1;
    };
    DevfileConverter.prototype.projectV2toProjectV1 = function (projectV2) {
        var devfileV1Project = {
            name: projectV2.name
        };
        if (projectV2.clonePath) {
            devfileV1Project.clonePath = projectV2.clonePath;
        }
        if (projectV2.git) {
            devfileV1Project.source = this.projectInfoToProjectSource(projectV2, projectV2.git);
        }
        else if (projectV2.zip) {
            devfileV1Project.source = {
                type: 'zip',
                location: projectV2.zip.location
            };
        }
        return devfileV1Project;
    };
    DevfileConverter.prototype.inlineCheTheiaPluginsYamlFromComponentsV1 = function (devfilev1Components) {
        if (!devfilev1Components) {
            return undefined;
        }
        // first, search any plugin components
        var chePluginComponents = devfilev1Components.filter(function (component) { return component.type === 'chePlugin'; });
        if (chePluginComponents.length === 0) {
            return undefined;
        }
        var cheTheiaPluginsContent = chePluginComponents.map(function (chePluginComponent) {
            var cheTheiaPlugin = {};
            if (chePluginComponent.id) {
                cheTheiaPlugin.id = chePluginComponent.id;
            }
            if (chePluginComponent.reference) {
                cheTheiaPlugin.reference = chePluginComponent.reference;
            }
            cheTheiaPlugin.override = {
                sidecar: {}
            };
            if (chePluginComponent.registryUrl) {
                cheTheiaPlugin.registryUrl = chePluginComponent.registryUrl;
            }
            if (chePluginComponent.alias) {
                cheTheiaPlugin.override.sidecar.name = chePluginComponent.alias;
            }
            if (chePluginComponent.env) {
                cheTheiaPlugin.override.sidecar.env = chePluginComponent.env;
            }
            if (chePluginComponent.preferences) {
                cheTheiaPlugin.override.preferences = chePluginComponent.preferences;
            }
            if (chePluginComponent.memoryLimit) {
                cheTheiaPlugin.override.sidecar.memoryLimit = chePluginComponent.memoryLimit;
            }
            if (chePluginComponent.memoryRequest) {
                cheTheiaPlugin.override.sidecar.memoryRequest = chePluginComponent.memoryRequest;
            }
            if (chePluginComponent.cpuLimit) {
                cheTheiaPlugin.override.sidecar.cpuLimit = chePluginComponent.cpuLimit;
            }
            if (chePluginComponent.cpuRequest) {
                cheTheiaPlugin.override.sidecar.cpuRequest = chePluginComponent.cpuRequest;
            }
            return cheTheiaPlugin;
        });
        return jsYaml.dump(cheTheiaPluginsContent);
    };
    DevfileConverter.prototype.inlineCheEditorYamlFromComponentsV1 = function (devfilev1Components) {
        if (!devfilev1Components) {
            return undefined;
        }
        // first, search any plugin components
        var cheEditorComponents = devfilev1Components.filter(function (component) { return component.type === 'cheEditor'; });
        if (cheEditorComponents.length === 0) {
            return undefined;
        }
        else if (cheEditorComponents.length > 1) {
            throw new Error('Only one editor component is supported');
        }
        var cheEditorComponentV1 = cheEditorComponents[0];
        var cheEditorYaml = {};
        if (cheEditorComponentV1.id) {
            cheEditorYaml.id = cheEditorComponentV1.id;
        }
        if (cheEditorComponentV1.reference) {
            cheEditorYaml.reference = cheEditorComponentV1.reference;
        }
        if (cheEditorComponentV1.registryUrl) {
            cheEditorYaml.registryUrl = cheEditorComponentV1.registryUrl;
        }
        return jsYaml.dump(cheEditorYaml);
    };
    DevfileConverter.prototype.inlineVsCodeExtensionFromComponentsV1 = function (devfilev1Components) {
        if (!devfilev1Components) {
            return undefined;
        }
        // first, search any plugin components
        var chePluginComponents = devfilev1Components.filter(function (component) { return component.type === 'chePlugin'; });
        if (chePluginComponents.length === 0) {
            return undefined;
        }
        var pluginIds = chePluginComponents
            .map(function (chePluginComponent) {
            if (chePluginComponent.id) {
                var filtered = chePluginComponent.id;
                if (filtered.endsWith('/latest')) {
                    filtered = filtered.substring(0, filtered.length - '/latest'.length);
                }
                return filtered;
            }
            return undefined;
        })
            .filter(function (plugin) { return plugin; });
        if (pluginIds) {
            var jsonObject = {
                recommendations: pluginIds
            };
            return JSON.stringify(jsonObject, undefined, 2);
        }
    };
    DevfileConverter.prototype.devfileV1toDevfileV2 = function (devfileV1) {
        var _a;
        return __awaiter(this, void 0, void 0, function () {
            var devfileV2, inlineCheTheiaPluginsYaml, inlineVsCodeExtensionJson, inlineCheEditorYaml, launchCommand, content;
            var _this = this;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        devfileV2 = {
                            schemaVersion: '2.1.0',
                            metadata: this.metadataV1toMetadataV2(devfileV1.metadata),
                            projects: (devfileV1.projects || []).map(function (project) { return _this.projectV1toProjectV2(project); }),
                            components: (devfileV1.components || [])
                                .map(function (component) { return _this.componentV1toComponentV2(component); })
                                .filter(function (c) { return c; }),
                            commands: (devfileV1.commands || []).map(function (command) { return _this.commandV1toCommandV2(command); }).filter(function (c) { return c; })
                        };
                        devfileV2.attributes = {};
                        inlineCheTheiaPluginsYaml = this.inlineCheTheiaPluginsYamlFromComponentsV1(devfileV1.components);
                        if (inlineCheTheiaPluginsYaml) {
                            devfileV2.attributes[this.CHE_THEIA_PLUGINS_YAML] = inlineCheTheiaPluginsYaml;
                        }
                        inlineVsCodeExtensionJson = this.inlineVsCodeExtensionFromComponentsV1(devfileV1.components);
                        if (inlineVsCodeExtensionJson) {
                            devfileV2.attributes[this.VSCODE_EXTENSIONS_JSON] = inlineVsCodeExtensionJson;
                        }
                        inlineCheEditorYaml = this.inlineCheEditorYamlFromComponentsV1(devfileV1.components);
                        if (inlineCheEditorYaml) {
                            devfileV2.attributes[this.CHE_EDITOR_YAML] = inlineCheEditorYaml;
                        }
                        if (devfileV1.attributes) {
                            Object.assign(devfileV2.metadata.attributes, {});
                            Object.keys(devfileV1.attributes).forEach(function (attributeName) {
                                devfileV2.metadata.attributes[attributeName] = devfileV1.attributes[attributeName];
                            });
                        }
                        launchCommand = (_a = devfileV1.commands) === null || _a === void 0 ? void 0 : _a.find(function (command) { return command.actions[0].type === 'vscode-launch'; });
                        if (launchCommand) {
                            devfileV2.attributes[this.VSCODE_LAUNCH_JSON] = launchCommand.actions[0].referenceContent;
                        }
                        // process plugins and editors
                        return [4 /*yield*/, this.processVolumesFromDevfileV2(devfileV2)];
                    case 1:
                        // process plugins and editors
                        _b.sent();
                        content = JSON.stringify(devfileV2);
                        // update devfile v1 constants
                        content = content.replace(/\$\(CHE_PROJECTS_ROOT\)/g, '$(PROJECTS_ROOT)');
                        content = content.replace(/\$\{CHE_PROJECTS_ROOT\}/g, '${PROJECTS_ROOT}');
                        return [2 /*return*/, JSON.parse(content)];
                }
            });
        });
    };
    // add missing volumes components when a volumeMount is defined in the devfile
    DevfileConverter.prototype.processVolumesFromDevfileV2 = function (devfileV2) {
        return __awaiter(this, void 0, void 0, function () {
            var mountedVolumes, mountedVolumeNames, allComponentVolumeNames, missingVolumes;
            return __generator(this, function (_a) {
                mountedVolumes = devfileV2.components
                    .map(function (component) { return component.container; })
                    .filter(function (container) { return container; })
                    .map(function (container) { return container.volumeMounts; })
                    .reduce(function (acc, volumeMounts) { return acc.concat(volumeMounts); }, [])
                    .filter(function (volume) { return volume; });
                mountedVolumeNames = mountedVolumes.map(function (volume) { return volume.name; });
                allComponentVolumeNames = devfileV2.components
                    .filter(function (component) { return component.volume; })
                    .map(function (component) { return component.name; });
                missingVolumes = mountedVolumeNames.filter(function (volumeName) { return !allComponentVolumeNames.includes(volumeName); });
                // add missing volumes
                missingVolumes.forEach(function (volumeName) {
                    devfileV2.components.push({
                        name: volumeName,
                        volume: {}
                    });
                });
                return [2 /*return*/];
            });
        });
    };
    DevfileConverter.prototype.processPluginsAndEditorsFromDevfileV2 = function (devfileV2, devfileV1, externalContentAccess) {
        return __awaiter(this, void 0, void 0, function () {
            var vsCodeExtensionJsonContent, vsCodeLaunchJsonContent, cheTheiaPluginsYamlContent, cheEditorYamlContent, externalVSCodeExtensionJsonContent, externalVSCodeLaunchJsonContent, externalCheTheiaPluginsYamlContent, externalCheEditorYamlContent, strippedContent, vsCodeExtensionJson, strippedContent, vsCodeLaunchJson, command, cheTheiaPluginsYaml, components, cheEditorYaml, v1component;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        vsCodeExtensionJsonContent = '';
                        vsCodeLaunchJsonContent = '';
                        cheTheiaPluginsYamlContent = '';
                        cheEditorYamlContent = '';
                        if (!externalContentAccess) return [3 /*break*/, 5];
                        return [4 /*yield*/, externalContentAccess(this.VSCODE_EXTENSIONS_JSON)];
                    case 1:
                        externalVSCodeExtensionJsonContent = _a.sent();
                        if (externalVSCodeExtensionJsonContent) {
                            vsCodeExtensionJsonContent = externalVSCodeExtensionJsonContent;
                        }
                        return [4 /*yield*/, externalContentAccess(this.VSCODE_LAUNCH_JSON)];
                    case 2:
                        externalVSCodeLaunchJsonContent = _a.sent();
                        if (externalVSCodeLaunchJsonContent) {
                            vsCodeLaunchJsonContent = externalVSCodeLaunchJsonContent;
                        }
                        return [4 /*yield*/, externalContentAccess(this.CHE_THEIA_PLUGINS_YAML)];
                    case 3:
                        externalCheTheiaPluginsYamlContent = _a.sent();
                        if (externalCheTheiaPluginsYamlContent) {
                            cheTheiaPluginsYamlContent = externalCheTheiaPluginsYamlContent;
                        }
                        return [4 /*yield*/, externalContentAccess(this.CHE_EDITOR_YAML)];
                    case 4:
                        externalCheEditorYamlContent = _a.sent();
                        if (externalCheEditorYamlContent) {
                            cheEditorYamlContent = externalCheEditorYamlContent;
                        }
                        _a.label = 5;
                    case 5:
                        // inline content ?
                        if (devfileV2.attributes) {
                            if (devfileV2.attributes[this.VSCODE_EXTENSIONS_JSON]) {
                                vsCodeExtensionJsonContent = devfileV2.attributes[this.VSCODE_EXTENSIONS_JSON];
                            }
                            if (devfileV2.attributes[this.VSCODE_LAUNCH_JSON]) {
                                vsCodeLaunchJsonContent = devfileV2.attributes[this.VSCODE_LAUNCH_JSON];
                            }
                            if (devfileV2.attributes[this.CHE_THEIA_PLUGINS_YAML]) {
                                cheTheiaPluginsYamlContent = devfileV2.attributes[this.CHE_THEIA_PLUGINS_YAML];
                            }
                            if (devfileV2.attributes[this.CHE_EDITOR_YAML]) {
                                cheEditorYamlContent = devfileV2.attributes[this.CHE_EDITOR_YAML];
                            }
                        }
                        // ok now apply the vscode extension.json content
                        if (vsCodeExtensionJsonContent && vsCodeExtensionJsonContent !== '') {
                            strippedContent = jsoncparser.stripComments(vsCodeExtensionJsonContent);
                            vsCodeExtensionJson = jsoncparser.parse(strippedContent);
                            // for each plugin, add a component
                            vsCodeExtensionJson.recommendations.forEach(function (recommendation) {
                                devfileV1.components.push({
                                    id: "".concat(recommendation.replace(/\./g, '/'), "/latest"),
                                    type: 'chePlugin'
                                });
                            });
                        }
                        // ok now apply the vscode launch.json content
                        if (vsCodeLaunchJsonContent && vsCodeLaunchJsonContent !== '') {
                            strippedContent = jsoncparser.stripComments(vsCodeLaunchJsonContent);
                            vsCodeLaunchJson = jsoncparser.parse(strippedContent);
                            command = {
                                name: vsCodeLaunchJson.configurations[0].name,
                                actions: [
                                    {
                                        type: 'vscode-launch',
                                        referenceContent: vsCodeLaunchJsonContent
                                    },
                                ]
                            };
                            // add a command
                            devfileV1.commands.push(command);
                        }
                        // ok now apply the cheTheiaPlugins Content
                        if (cheTheiaPluginsYamlContent && cheTheiaPluginsYamlContent !== '') {
                            cheTheiaPluginsYaml = jsYaml.load(cheTheiaPluginsYamlContent);
                            if (Array.isArray(cheTheiaPluginsYaml)) {
                                components = cheTheiaPluginsYaml.map(function (component) {
                                    var v1component = {
                                        type: 'chePlugin'
                                    };
                                    if (component.id) {
                                        v1component.id = component.id;
                                    }
                                    if (component.reference) {
                                        v1component.reference = component.reference;
                                    }
                                    if (component.registryUrl) {
                                        v1component.registryUrl = component.registryUrl;
                                    }
                                    if (component.override && component.override.sidecar) {
                                        if (component.override.sidecar.memoryLimit) {
                                            v1component.memoryLimit = component.override.sidecar.memoryLimit;
                                        }
                                        if (component.override.sidecar.memoryRequest) {
                                            v1component.memoryRequest = component.override.sidecar.memoryRequest;
                                        }
                                        if (component.override.sidecar.cpuLimit) {
                                            v1component.cpuLimit = component.override.sidecar.cpuLimit;
                                        }
                                        if (component.override.sidecar.cpuRequest) {
                                            v1component.cpuRequest = component.override.sidecar.cpuRequest;
                                        }
                                        if (component.override.sidecar.env) {
                                            v1component.env = component.override.sidecar.env;
                                        }
                                        if (component.override.preferences) {
                                            v1component.preferences = component.override.preferences;
                                        }
                                        if (component.override.sidecar.name) {
                                            v1component.alias = component.override.sidecar.name;
                                        }
                                    }
                                    return v1component;
                                });
                                // now, override or add any existing component
                                components.forEach(function (component) {
                                    // existing component ?
                                    var existing = devfileV1.components.find(function (devfileV1Component) { return devfileV1Component.type === 'chePlugin' && devfileV1Component.id === component.id; });
                                    if (existing) {
                                        Object.assign(existing, component);
                                    }
                                    else {
                                        devfileV1.components.push(component);
                                    }
                                });
                            }
                        }
                        // ok now apply the cheEditor Content
                        if (cheEditorYamlContent && cheEditorYamlContent !== '') {
                            cheEditorYaml = jsYaml.load(cheEditorYamlContent);
                            if (cheEditorYaml) {
                                v1component = {
                                    type: 'cheEditor'
                                };
                                if (cheEditorYaml.id) {
                                    v1component.id = cheEditorYaml.id;
                                }
                                if (cheEditorYaml.reference) {
                                    v1component.reference = cheEditorYaml.reference;
                                }
                                if (cheEditorYaml.registryUrl) {
                                    v1component.registryUrl = cheEditorYaml.registryUrl;
                                }
                                devfileV1.components.push(v1component);
                            }
                        }
                        return [2 /*return*/];
                }
            });
        });
    };
    DevfileConverter.prototype.findFirstProjectPath = function (devfileV1) {
        var projects = devfileV1.projects;
        if (!projects || projects.length === 0) {
            return undefined;
        }
        // take first project
        var project = projects[0];
        var path;
        if (project.clonePath) {
            path = "${CHE_PROJECTS_ROOT}/".concat(project.clonePath);
        }
        else {
            path = "${CHE_PROJECTS_ROOT}/".concat(project.name);
        }
        return path;
    };
    DevfileConverter.prototype.prunePlaceHolderComponents = function (devfileV1) {
        devfileV1.components = devfileV1.components.filter(function (component) { return component.image !== 'buildguidanceimage-placeholder'; });
    };
    DevfileConverter.prototype.fixNightlyImages = function (devfileV1) {
        devfileV1.components.forEach(function (component) {
            if (component.image && component.image === 'quay.io/eclipse/che-quarkus:nightly') {
                component.image = 'quay.io/eclipse/che-quarkus:next';
            }
            else if (component.image && component.image === 'quay.io/eclipse/che-java11-maven:nightly') {
                component.image = 'quay.io/eclipse/che-java11-maven:next';
            }
        });
    };
    // Apply 1Gi on all components without memoryLimit
    DevfileConverter.prototype.fixMemoryLimit = function (devfileV1) {
        devfileV1.components.forEach(function (component) {
            if (component.type === 'dockerimage' && !component.memoryLimit) {
                component.memoryLimit = '1Gi';
            }
        });
    };
    DevfileConverter.prototype.processDefaultWorkDirCommands = function (devfileV1, path) {
        return __awaiter(this, void 0, void 0, function () {
            var execWithoutWorkingdir;
            return __generator(this, function (_a) {
                execWithoutWorkingdir = devfileV1.commands
                    .filter(function (command) {
                    return command.actions &&
                        command.actions.find(function (action) {
                            return (!action.workdir || action.workdir === '$PROJECTS_ROOT' || action.workdir === '${PROJECTS_ROOT}') &&
                                action.type === 'exec';
                        });
                })
                    .map(function (command) { return command.actions; })
                    .flat();
                // update working directory
                if (execWithoutWorkingdir.length > 0 && path) {
                    // set the working directory to the project directory
                    execWithoutWorkingdir.forEach(function (exec) { return (exec.workdir = path); });
                }
                return [2 /*return*/];
            });
        });
    };
    DevfileConverter.prototype.devfileV2toDevfileV1 = function (devfileV2, externalContentAccess) {
        return __awaiter(this, void 0, void 0, function () {
            var devfileV1, attributeKeys, attributes_1, firstProjectPath, devfileV1Any, content;
            var _this = this;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        devfileV1 = {
                            apiVersion: '1.0.0',
                            metadata: this.metadataV2toMetadataV1(devfileV2.metadata),
                            projects: (devfileV2.projects || []).map(function (project) { return _this.projectV2toProjectV1(project); }),
                            components: (devfileV2.components || [])
                                .map(function (component) { return _this.componentV2toComponentV1(component); })
                                .filter(function (c) { return c; }),
                            commands: (devfileV2.commands || []).map(function (command) { return _this.commandV2toCommandV1(command); }).filter(function (c) { return c; })
                        };
                        if (devfileV2.metadata.attributes) {
                            attributeKeys = Object.keys(devfileV2.metadata.attributes);
                            if (attributeKeys.length > 0) {
                                attributes_1 = devfileV1.attributes || {};
                                attributeKeys.forEach(function (attributeName) {
                                    attributes_1[attributeName] = devfileV2.metadata.attributes[attributeName];
                                });
                                if (Object.keys(attributes_1).length > 0) {
                                    devfileV1.attributes = attributes_1;
                                }
                            }
                        }
                        // process plugins and editors
                        return [4 /*yield*/, this.processPluginsAndEditorsFromDevfileV2(devfileV2, devfileV1, externalContentAccess)];
                    case 1:
                        // process plugins and editors
                        _a.sent();
                        firstProjectPath = this.findFirstProjectPath(devfileV1);
                        // update workDir of commands to be inside the current project if missing
                        return [4 /*yield*/, this.processDefaultWorkDirCommands(devfileV1, firstProjectPath)];
                    case 2:
                        // update workDir of commands to be inside the current project if missing
                        _a.sent();
                        // prune placeholder components
                        this.prunePlaceHolderComponents(devfileV1);
                        // fix nightly images of che
                        this.fixNightlyImages(devfileV1);
                        // memoryLimit is a mandatory attribute in devfile v1
                        this.fixMemoryLimit(devfileV1);
                        devfileV1Any = devfileV1;
                        if (devfileV1.components && devfileV1.components.length === 0) {
                            delete devfileV1Any.components;
                        }
                        if (devfileV1.projects && devfileV1.projects.length === 0) {
                            delete devfileV1Any.projects;
                        }
                        if (devfileV1.commands && devfileV1.commands.length === 0) {
                            delete devfileV1Any.commands;
                        }
                        // cleanup attributes that are not string
                        if (devfileV1.attributes) {
                            Object.keys(devfileV1.attributes).forEach(function (key) {
                                if (typeof devfileV1.attributes[key] !== 'string') {
                                    delete devfileV1.attributes[key];
                                }
                            });
                        }
                        if (devfileV1.attributes && Object.keys(devfileV1.attributes).length === 0) {
                            delete devfileV1Any.attributes;
                        }
                        content = JSON.stringify(devfileV1, undefined, 2);
                        // update devfile v2 constants
                        content = content.replace(/\$\(PROJECTS_ROOT\)/g, '$(CHE_PROJECTS_ROOT)');
                        content = content.replace(/\$\{PROJECTS_ROOT\}/g, '${CHE_PROJECTS_ROOT}');
                        if (firstProjectPath) {
                            content = content.replace(/\$\{PROJECT_SOURCE\}/g, firstProjectPath);
                        }
                        return [2 /*return*/, JSON.parse(content)];
                }
            });
        });
    };
    DevfileConverter = __decorate([
        (0, inversify_1.injectable)()
    ], DevfileConverter);
    return DevfileConverter;
}());
exports.DevfileConverter = DevfileConverter;
//# sourceMappingURL=devfile-converter.js.map