"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 });
exports.MigrateController = void 0;
const path = require("path");
const semver = require("semver");
const constants = require("../constants");
const glob = require("glob");
const _ = require("lodash");
const update_controller_base_1 = require("./update-controller-base");
const helpers_1 = require("../common/helpers");
const yok_1 = require("../common/yok");
class MigrateController extends update_controller_base_1.UpdateControllerBase {
    constructor($fs, $platformCommandHelper, $platformsDataService, $packageInstallationManager, $packageManager, $pacoteService, $devicePlatformsConstants, $logger, $errors, $addPlatformService, $pluginsService, $projectDataService, $projectConfigService, $options, $platformValidationService, $resources, $injector, $settingsService, $staticConfig) {
        super($fs, $platformCommandHelper, $platformsDataService, $packageInstallationManager, $packageManager, $pacoteService);
        this.$fs = $fs;
        this.$platformCommandHelper = $platformCommandHelper;
        this.$platformsDataService = $platformsDataService;
        this.$packageInstallationManager = $packageInstallationManager;
        this.$packageManager = $packageManager;
        this.$pacoteService = $pacoteService;
        this.$devicePlatformsConstants = $devicePlatformsConstants;
        this.$logger = $logger;
        this.$errors = $errors;
        this.$addPlatformService = $addPlatformService;
        this.$pluginsService = $pluginsService;
        this.$projectDataService = $projectDataService;
        this.$projectConfigService = $projectConfigService;
        this.$options = $options;
        this.$platformValidationService = $platformValidationService;
        this.$resources = $resources;
        this.$injector = $injector;
        this.$settingsService = $settingsService;
        this.$staticConfig = $staticConfig;
        this.migrationDependencies = [
            {
                packageName: constants.SCOPED_TNS_CORE_MODULES,
                verifiedVersion: "7.0.0",
                shouldAddIfMissing: true,
            },
            {
                packageName: constants.TNS_CORE_MODULES_NAME,
                shouldRemove: true,
            },
            {
                packageName: "@nativescript/types",
                verifiedVersion: "7.0.0",
                isDev: true,
            },
            {
                packageName: "tns-platform-declarations",
                replaceWith: "@nativescript/types",
                verifiedVersion: "7.0.0",
                isDev: true,
            },
            {
                packageName: constants.TNS_CORE_MODULES_WIDGETS_NAME,
                shouldRemove: true,
            },
            {
                packageName: "nativescript-dev-webpack",
                shouldRemove: true,
            },
            {
                packageName: constants.WEBPACK_PLUGIN_NAME,
                verifiedVersion: "3.0.0",
                shouldAddIfMissing: true,
                isDev: true,
            },
            {
                packageName: "nativescript-vue",
                verifiedVersion: "2.8.0",
                shouldMigrateAction: (projectData, allowInvalidVersions) => __awaiter(this, void 0, void 0, function* () {
                    const dependency = {
                        packageName: "nativescript-vue",
                        verifiedVersion: "2.8.0",
                        isDev: false,
                    };
                    const result = this.hasDependency(dependency, projectData) &&
                        (yield this.shouldMigrateDependencyVersion(dependency, projectData, allowInvalidVersions));
                    return result;
                }),
                migrateAction: this.migrateNativeScriptVue.bind(this),
            },
            {
                packageName: "nativescript-angular",
                replaceWith: "@nativescript/angular",
                verifiedVersion: "10.0.0",
            },
            {
                packageName: "@nativescript/angular",
                verifiedVersion: "10.0.0",
                shouldMigrateAction: (projectData, allowInvalidVersions) => __awaiter(this, void 0, void 0, function* () {
                    const dependency = {
                        packageName: "@nativescript/angular",
                        verifiedVersion: "10.0.0",
                        isDev: false,
                    };
                    const result = this.hasDependency(dependency, projectData) &&
                        (yield this.shouldMigrateDependencyVersion(dependency, projectData, allowInvalidVersions));
                    return result;
                }),
                migrateAction: this.migrateNativeScriptAngular.bind(this),
            },
            {
                packageName: "@nativescript/unit-test-runner",
                verifiedVersion: "1.0.0",
                shouldMigrateAction: (projectData, allowInvalidVersions) => __awaiter(this, void 0, void 0, function* () {
                    const dependency = {
                        packageName: "@nativescript/unit-test-runner",
                        verifiedVersion: "1.0.0",
                        isDev: false,
                    };
                    const result = this.hasDependency(dependency, projectData) &&
                        (yield this.shouldMigrateDependencyVersion(dependency, projectData, allowInvalidVersions));
                    return result;
                }),
                migrateAction: this.migrateUnitTestRunner.bind(this),
            },
            {
                packageName: MigrateController.typescriptPackageName,
                isDev: true,
                verifiedVersion: "3.9.7",
            },
        ];
    }
    get $jsonFileSettingsService() {
        const cliVersion = semver.coerce(this.$staticConfig.version);
        const shouldMigrateCacheFilePath = path.join(this.$settingsService.getProfileDir(), `should-migrate-cache-${cliVersion}.json`);
        return this.$injector.resolve("jsonFileSettingsService", {
            jsonFileSettingsPath: shouldMigrateCacheFilePath,
        });
    }
    get verifiedPlatformVersions() {
        return {
            [this.$devicePlatformsConstants.Android.toLowerCase()]: "6.5.3",
            [this.$devicePlatformsConstants.iOS.toLowerCase()]: "6.5.2",
        };
    }
    migrate({ projectDir, platforms, allowInvalidVersions = false, }) {
        return __awaiter(this, void 0, void 0, function* () {
            const projectData = this.$projectDataService.getProjectData(projectDir);
            const backupDir = path.join(projectDir, MigrateController.backupFolder);
            try {
                this.$logger.info("Backup project configuration.");
                this.backup([
                    ...MigrateController.folders,
                    path.join(projectData.getAppDirectoryRelativePath(), "package.json"),
                ], backupDir, projectData.projectDir);
                this.$logger.info("Backup project configuration complete.");
            }
            catch (error) {
                this.$logger.error(MigrateController.backupFailMessage);
                this.$fs.deleteDirectory(backupDir);
                return;
            }
            try {
                this.$logger.info("Clean auto-generated files.");
                this.handleAutoGeneratedFiles(backupDir, projectData);
                this.$logger.info("Clean auto-generated files complete.");
            }
            catch (error) {
                this.$logger.trace(`Error during auto-generated files handling. ${(error && error.message) || error}`);
            }
            try {
                yield this.cleanUpProject(projectData);
                yield this.migrateConfig(projectData);
                yield this.migrateDependencies(projectData, platforms, allowInvalidVersions);
            }
            catch (error) {
                const backupFolders = MigrateController.folders;
                const embeddedPackagePath = path.join(projectData.getAppDirectoryRelativePath(), "package.json");
                backupFolders.push(embeddedPackagePath);
                this.restoreBackup(backupFolders, backupDir, projectData.projectDir);
                this.$errors.fail(`${MigrateController.migrateFailMessage} The error is: ${error}`);
            }
            this.$logger.info(MigrateController.MIGRATE_FINISH_MESSAGE);
        });
    }
    shouldMigrate({ projectDir, platforms, allowInvalidVersions = false, }) {
        return __awaiter(this, void 0, void 0, function* () {
            const remainingPlatforms = [];
            let shouldMigrate = false;
            for (const platform of platforms) {
                const cachedResult = yield this.getCachedShouldMigrate(projectDir, platform);
                if (cachedResult !== false) {
                    remainingPlatforms.push(platform);
                }
                else {
                    this.$logger.trace(`Got cached result for shouldMigrate for platform: ${platform}`);
                }
            }
            if (remainingPlatforms.length > 0) {
                shouldMigrate = yield this._shouldMigrate({
                    projectDir,
                    platforms: remainingPlatforms,
                    allowInvalidVersions,
                });
                this.$logger.trace(`Executed shouldMigrate for platforms: ${remainingPlatforms}. Result is: ${shouldMigrate}`);
                if (!shouldMigrate) {
                    for (const remainingPlatform of remainingPlatforms) {
                        yield this.setCachedShouldMigrate(projectDir, remainingPlatform);
                    }
                }
            }
            return shouldMigrate;
        });
    }
    _shouldMigrate({ projectDir, platforms, allowInvalidVersions, }) {
        return __awaiter(this, void 0, void 0, function* () {
            const isMigrate = _.get(this.$options, "argv._[0]") === "migrate";
            const projectData = this.$projectDataService.getProjectData(projectDir);
            const projectInfo = this.$projectConfigService.detectInfo(projectData.projectDir);
            if (!isMigrate && projectInfo.usesLegacyConfig) {
                return;
            }
            const shouldMigrateCommonMessage = "The app is not compatible with this CLI version and it should be migrated. Reason: ";
            for (let i = 0; i < this.migrationDependencies.length; i++) {
                const dependency = this.migrationDependencies[i];
                const hasDependency = this.hasDependency(dependency, projectData);
                if (hasDependency &&
                    dependency.shouldMigrateAction &&
                    (yield dependency.shouldMigrateAction(projectData, allowInvalidVersions))) {
                    this.$logger.trace(`${shouldMigrateCommonMessage}'${dependency.packageName}' requires an update.`);
                    return true;
                }
                if (hasDependency &&
                    (dependency.replaceWith || dependency.shouldRemove)) {
                    this.$logger.trace(`${shouldMigrateCommonMessage}'${dependency.packageName}' is deprecated.`);
                    return true;
                }
                if (hasDependency &&
                    (yield this.shouldMigrateDependencyVersion(dependency, projectData, allowInvalidVersions))) {
                    this.$logger.trace(`${shouldMigrateCommonMessage}'${dependency.packageName}' should be updated.`);
                    return true;
                }
                if (!hasDependency && dependency.shouldAddIfMissing) {
                    this.$logger.trace(`${shouldMigrateCommonMessage}'${dependency.packageName}' is missing.`);
                    return true;
                }
            }
            for (let platform of platforms) {
                platform = platform && platform.toLowerCase();
                if (!this.$platformValidationService.isValidPlatform(platform, projectData)) {
                    continue;
                }
                const hasRuntimeDependency = this.hasRuntimeDependency({
                    platform,
                    projectData,
                });
                if (hasRuntimeDependency &&
                    (yield this.shouldUpdateRuntimeVersion(this.verifiedPlatformVersions[platform.toLowerCase()], platform, projectData, allowInvalidVersions))) {
                    this.$logger.trace(`${shouldMigrateCommonMessage}Platform '${platform}' should be updated.`);
                    return true;
                }
            }
        });
    }
    validate({ projectDir, platforms, allowInvalidVersions = true, }) {
        return __awaiter(this, void 0, void 0, function* () {
            const shouldMigrate = yield this.shouldMigrate({
                projectDir,
                platforms,
                allowInvalidVersions,
            });
            if (shouldMigrate) {
                this.$errors.fail(MigrateController.UNABLE_TO_MIGRATE_APP_ERROR);
            }
        });
    }
    getCachedShouldMigrate(projectDir, platform) {
        return __awaiter(this, void 0, void 0, function* () {
            let cachedShouldMigrateValue = null;
            const cachedHash = yield this.$jsonFileSettingsService.getSettingValue(helpers_1.getHash(`${projectDir}${platform.toLowerCase()}`));
            const packageJsonHash = yield this.getPachageJsonHash(projectDir);
            if (cachedHash === packageJsonHash) {
                cachedShouldMigrateValue = false;
            }
            return cachedShouldMigrateValue;
        });
    }
    setCachedShouldMigrate(projectDir, platform) {
        return __awaiter(this, void 0, void 0, function* () {
            const packageJsonHash = yield this.getPachageJsonHash(projectDir);
            yield this.$jsonFileSettingsService.saveSetting(helpers_1.getHash(`${projectDir}${platform.toLowerCase()}`), packageJsonHash);
        });
    }
    getPachageJsonHash(projectDir) {
        return __awaiter(this, void 0, void 0, function* () {
            const projectPackageJsonFilePath = path.join(projectDir, constants.PACKAGE_JSON_FILE_NAME);
            return yield this.$fs.getFileShasum(projectPackageJsonFilePath);
        });
    }
    cleanUpProject(projectData) {
        return __awaiter(this, void 0, void 0, function* () {
            this.$logger.info("Clean old project artifacts.");
            this.$fs.deleteDirectory(path.join(projectData.projectDir, constants.HOOKS_DIR_NAME));
            this.$fs.deleteDirectory(path.join(projectData.projectDir, constants.PLATFORMS_DIR_NAME));
            this.$fs.deleteDirectory(path.join(projectData.projectDir, constants.NODE_MODULES_FOLDER_NAME));
            this.$fs.deleteFile(path.join(projectData.projectDir, constants.WEBPACK_CONFIG_NAME));
            this.$fs.deleteFile(path.join(projectData.projectDir, constants.PACKAGE_LOCK_JSON_FILE_NAME));
            if (!projectData.isShared) {
                this.$fs.deleteFile(path.join(projectData.projectDir, constants.TSCCONFIG_TNS_JSON_NAME));
            }
            this.$logger.info("Clean old project artifacts complete.");
        });
    }
    handleAutoGeneratedFiles(backupDir, projectData) {
        const globOptions = {
            silent: true,
            nocase: true,
            matchBase: true,
            nodir: true,
            absolute: false,
            cwd: projectData.appDirectoryPath,
        };
        const jsFiles = glob.sync("*.@(js|ts|js.map)", globOptions);
        const autoGeneratedJsFiles = this.getGeneratedFiles(jsFiles, [".js"], [".ts"]);
        const autoGeneratedJsMapFiles = this.getGeneratedFiles(jsFiles, [".map"], [""]);
        const cssFiles = glob.sync("*.@(le|sa|sc|c)ss", globOptions);
        const autoGeneratedCssFiles = this.getGeneratedFiles(cssFiles, [".css"], [".scss", ".sass", ".less"]);
        const allGeneratedFiles = autoGeneratedJsFiles
            .concat(autoGeneratedJsMapFiles)
            .concat(autoGeneratedCssFiles);
        for (const generatedFile of allGeneratedFiles) {
            const sourceFile = path.join(projectData.appDirectoryPath, generatedFile);
            const destinationFile = path.join(backupDir, generatedFile);
            const destinationFileDir = path.dirname(destinationFile);
            this.$fs.ensureDirectoryExists(destinationFileDir);
            this.$fs.rename(sourceFile, destinationFile);
        }
    }
    getGeneratedFiles(allFiles, generatedFileExts, sourceFileExts) {
        const autoGeneratedFiles = allFiles.filter((file) => {
            let isGenerated = false;
            const { dir, name, ext } = path.parse(file);
            if (generatedFileExts.indexOf(ext) > -1) {
                for (const sourceExt of sourceFileExts) {
                    const possibleSourceFile = path.format({ dir, name, ext: sourceExt });
                    isGenerated = allFiles.indexOf(possibleSourceFile) > -1;
                    if (isGenerated) {
                        break;
                    }
                }
            }
            return isGenerated;
        });
        return autoGeneratedFiles;
    }
    migrateDependencies(projectData, platforms, allowInvalidVersions) {
        return __awaiter(this, void 0, void 0, function* () {
            this.$logger.info("Start dependencies migration.");
            for (let i = 0; i < this.migrationDependencies.length; i++) {
                const dependency = this.migrationDependencies[i];
                const hasDependency = this.hasDependency(dependency, projectData);
                if (hasDependency &&
                    dependency.migrateAction &&
                    (yield dependency.shouldMigrateAction(projectData, allowInvalidVersions))) {
                    const newDependencies = yield dependency.migrateAction(projectData, path.join(projectData.projectDir, MigrateController.backupFolder));
                    for (const newDependency of newDependencies) {
                        yield this.migrateDependency(newDependency, projectData, allowInvalidVersions);
                    }
                }
                yield this.migrateDependency(dependency, projectData, allowInvalidVersions);
            }
            for (const platform of platforms) {
                const lowercasePlatform = platform.toLowerCase();
                const hasRuntimeDependency = this.hasRuntimeDependency({
                    platform,
                    projectData,
                });
                if (hasRuntimeDependency &&
                    (yield this.shouldUpdateRuntimeVersion(this.verifiedPlatformVersions[lowercasePlatform], platform, projectData, allowInvalidVersions))) {
                    const verifiedPlatformVersion = this.verifiedPlatformVersions[lowercasePlatform];
                    const platformData = this.$platformsDataService.getPlatformData(lowercasePlatform, projectData);
                    this.$logger.info(`Updating ${platform} platform to version '${verifiedPlatformVersion}'.`);
                    yield this.$addPlatformService.setPlatformVersion(platformData, projectData, verifiedPlatformVersion);
                }
            }
            this.$logger.info("Install packages.");
            yield this.$packageManager.install(projectData.projectDir, projectData.projectDir, {
                disableNpmInstall: false,
                frameworkPath: null,
                ignoreScripts: false,
                path: projectData.projectDir,
            });
            this.$logger.info("Migration complete.");
        });
    }
    migrateDependency(dependency, projectData, allowInvalidVersions) {
        return __awaiter(this, void 0, void 0, function* () {
            const hasDependency = this.hasDependency(dependency, projectData);
            if (hasDependency && dependency.warning) {
                this.$logger.warn(dependency.warning);
            }
            if (hasDependency && (dependency.replaceWith || dependency.shouldRemove)) {
                this.$pluginsService.removeFromPackageJson(dependency.packageName, projectData.projectDir);
                if (dependency.replaceWith) {
                    const replacementDep = _.find(this.migrationDependencies, (migrationPackage) => migrationPackage.packageName === dependency.replaceWith);
                    if (!replacementDep) {
                        this.$errors.fail("Failed to find replacement dependency.");
                    }
                    this.$logger.info(`Replacing '${dependency.packageName}' with '${replacementDep.packageName}'.`);
                    this.$pluginsService.addToPackageJson(replacementDep.packageName, replacementDep.verifiedVersion, replacementDep.isDev, projectData.projectDir);
                }
                return;
            }
            if (hasDependency &&
                (yield this.shouldMigrateDependencyVersion(dependency, projectData, allowInvalidVersions))) {
                this.$logger.info(`Updating '${dependency.packageName}' to compatible version '${dependency.verifiedVersion}'`);
                this.$pluginsService.addToPackageJson(dependency.packageName, dependency.verifiedVersion, dependency.isDev, projectData.projectDir);
                return;
            }
            if (!hasDependency && dependency.shouldAddIfMissing) {
                this.$logger.info(`Adding '${dependency.packageName}' with version '${dependency.verifiedVersion}'`);
                this.$pluginsService.addToPackageJson(dependency.packageName, dependency.verifiedVersion, dependency.isDev, projectData.projectDir);
            }
        });
    }
    shouldMigrateDependencyVersion(dependency, projectData, allowInvalidVersions) {
        return __awaiter(this, void 0, void 0, function* () {
            const installedVersion = yield this.$packageInstallationManager.getInstalledDependencyVersion(dependency.packageName, projectData.projectDir);
            const requiredVersion = dependency.verifiedVersion;
            return this.isOutdatedVersion(installedVersion, requiredVersion, allowInvalidVersions);
        });
    }
    shouldUpdateRuntimeVersion(targetVersion, platform, projectData, allowInvalidVersions) {
        return __awaiter(this, void 0, void 0, function* () {
            const installedVersion = yield this.getMaxRuntimeVersion({
                platform,
                projectData,
            });
            return this.isOutdatedVersion(installedVersion, targetVersion, allowInvalidVersions);
        });
    }
    isOutdatedVersion(version, targetVersion, allowInvalidVersions) {
        return !!version
            ? semver.lt(version, targetVersion)
            : !allowInvalidVersions;
    }
    migrateConfig(projectData) {
        return __awaiter(this, void 0, void 0, function* () {
            this.$logger.info(`Migrating project to use ${constants.CONFIG_FILE_NAME_TS}...`);
            const embeddedPackageJsonPath = path.resolve(projectData.projectDir, projectData.getAppDirectoryRelativePath(), constants.PACKAGE_JSON_FILE_NAME);
            this.$logger.debug(`embeddedPackageJsonPath: ${embeddedPackageJsonPath}`);
            const legacyNsConfigPath = path.resolve(projectData.projectDir, constants.CONFIG_NS_FILE_NAME);
            this.$logger.debug(`legacyNsConfigPath: ${legacyNsConfigPath}`);
            const rootPackageJsonPath = path.resolve(projectData.projectDir, constants.PACKAGE_JSON_FILE_NAME);
            this.$logger.debug(`rootPackageJsonPath: ${rootPackageJsonPath}`);
            let embeddedPackageData = {};
            if (this.$fs.exists(embeddedPackageJsonPath)) {
                embeddedPackageData = this.$fs.readJson(embeddedPackageJsonPath);
            }
            let legacyNsConfigData = {};
            if (this.$fs.exists(legacyNsConfigPath)) {
                legacyNsConfigData = this.$fs.readJson(legacyNsConfigPath);
            }
            let rootPackageJsonData = {};
            if (this.$fs.exists(rootPackageJsonPath)) {
                rootPackageJsonData = this.$fs.readJson(rootPackageJsonPath);
            }
            const dataToMigrate = Object.assign(Object.assign({}, embeddedPackageData), legacyNsConfigData);
            if (dataToMigrate.main) {
                rootPackageJsonData.main = dataToMigrate.main;
                delete dataToMigrate.main;
            }
            const success = yield this.$projectConfigService.setValue("", dataToMigrate);
            if (!success) {
                this.$errors.fail(`Failed to migrate project to use ${constants.CONFIG_FILE_NAME_TS}. One or more values could not be updated.`);
            }
            if (rootPackageJsonData &&
                rootPackageJsonData.nativescript &&
                rootPackageJsonData.nativescript.id) {
                yield this.$projectConfigService.setValue("id", rootPackageJsonData.nativescript.id);
                delete rootPackageJsonData.nativescript;
            }
            const possibleAppPaths = [
                path.resolve(projectData.projectDir, constants.SRC_DIR),
                path.resolve(projectData.projectDir, constants.APP_FOLDER_NAME),
            ];
            const appPath = possibleAppPaths.find((possiblePath) => this.$fs.exists(possiblePath));
            if (appPath) {
                const relativeAppPath = path
                    .relative(projectData.projectDir, appPath)
                    .replace(path.sep, "/");
                this.$logger.trace(`Found app source at '${appPath}'. Writing '${relativeAppPath}' to config.`);
                const ok = yield this.$projectConfigService.setValue("appPath", relativeAppPath.toString());
                this.$logger.trace(ok ? `Ok...` : "Could not write...");
            }
            const possibleAppResourcesPaths = [
                path.resolve(projectData.projectDir, appPath, constants.APP_RESOURCES_FOLDER_NAME),
                path.resolve(projectData.projectDir, constants.APP_RESOURCES_FOLDER_NAME),
            ];
            const appResourcesPath = possibleAppResourcesPaths.find((possiblePath) => this.$fs.exists(possiblePath));
            if (appResourcesPath) {
                const relativeAppResourcesPath = path
                    .relative(projectData.projectDir, appResourcesPath)
                    .replace(path.sep, "/");
                this.$logger.trace(`Found App_Resources at '${appResourcesPath}'. Writing '${relativeAppResourcesPath}' to config.`);
                const ok = yield this.$projectConfigService.setValue("appResourcesPath", relativeAppResourcesPath.toString());
                this.$logger.trace(ok ? `Ok...` : "Could not write...");
            }
            this.$fs.writeJson(rootPackageJsonPath, rootPackageJsonData);
            this.$fs.deleteFile(embeddedPackageJsonPath);
            this.$fs.deleteFile(legacyNsConfigPath);
            this.$logger.info(`Migrated project to use ${constants.CONFIG_FILE_NAME_TS}`);
        });
    }
    migrateUnitTestRunner(projectData, migrationBackupDirPath) {
        return __awaiter(this, void 0, void 0, function* () {
            const pathToKarmaConfig = path.join(migrationBackupDirPath, constants.KARMA_CONFIG_NAME);
            if (this.$fs.exists(pathToKarmaConfig)) {
                const oldKarmaContent = this.$fs.readText(pathToKarmaConfig);
                const regExp = /frameworks:\s+\[([\S\s]*?)\]/g;
                const matches = regExp.exec(oldKarmaContent);
                const frameworks = (matches && matches[1] && matches[1].trim()) || '["jasmine"]';
                const testsDir = path.join(projectData.appDirectoryPath, "tests");
                const relativeTestsDir = path.relative(projectData.projectDir, testsDir);
                const testFiles = `'${helpers_1.fromWindowsRelativePathToUnix(relativeTestsDir)}/**/*.*'`;
                const karmaConfTemplate = this.$resources.readText("test/karma.conf.js");
                const karmaConf = _.template(karmaConfTemplate)({
                    frameworks,
                    testFiles,
                });
                this.$fs.writeFile(path.join(projectData.projectDir, constants.KARMA_CONFIG_NAME), karmaConf);
            }
            const dependencies = [
                {
                    packageName: "karma-webpack",
                    verifiedVersion: "3.0.5",
                    isDev: true,
                    shouldAddIfMissing: true,
                },
                { packageName: "karma-jasmine", verifiedVersion: "2.0.1", isDev: true },
                { packageName: "karma-mocha", verifiedVersion: "1.3.0", isDev: true },
                { packageName: "karma-chai", verifiedVersion: "0.1.0", isDev: true },
                { packageName: "karma-qunit", verifiedVersion: "3.1.2", isDev: true },
                { packageName: "karma", verifiedVersion: "4.1.0", isDev: true },
            ];
            return dependencies;
        });
    }
    migrateNativeScriptAngular() {
        return __awaiter(this, void 0, void 0, function* () {
            const dependencies = [
                {
                    packageName: "@angular/platform-browser-dynamic",
                    verifiedVersion: "10.0.0",
                    shouldAddIfMissing: true,
                },
                {
                    packageName: "@angular/common",
                    verifiedVersion: "10.0.0",
                    shouldAddIfMissing: true,
                },
                {
                    packageName: "@angular/compiler",
                    verifiedVersion: "10.0.0",
                    shouldAddIfMissing: true,
                },
                {
                    packageName: "@angular/core",
                    verifiedVersion: "10.0.0",
                    shouldAddIfMissing: true,
                },
                {
                    packageName: "@angular/forms",
                    verifiedVersion: "10.0.0",
                    shouldAddIfMissing: true,
                },
                {
                    packageName: "@angular/platform-browser",
                    verifiedVersion: "10.0.0",
                    shouldAddIfMissing: true,
                },
                {
                    packageName: "@angular/router",
                    verifiedVersion: "10.0.0",
                    shouldAddIfMissing: true,
                },
                {
                    packageName: "rxjs",
                    verifiedVersion: "6.6.0",
                    shouldAddIfMissing: true,
                },
                {
                    packageName: "zone.js",
                    verifiedVersion: "0.11.1",
                    shouldAddIfMissing: true,
                },
                {
                    packageName: "@angular/animations",
                    verifiedVersion: "10.0.0",
                    shouldAddIfMissing: true,
                },
                {
                    packageName: "@angular/compiler-cli",
                    verifiedVersion: "10.0.0",
                    isDev: true,
                },
                {
                    packageName: "@ngtools/webpack",
                    verifiedVersion: "10.0.0",
                    isDev: true,
                },
                {
                    packageName: "@angular-devkit/build-angular",
                    verifiedVersion: "0.1000.8",
                    isDev: true,
                },
            ];
            return dependencies;
        });
    }
    migrateNativeScriptVue() {
        return __awaiter(this, void 0, void 0, function* () {
            const dependencies = [
                {
                    packageName: "nativescript-vue-template-compiler",
                    verifiedVersion: "2.8.0",
                    isDev: true,
                },
            ];
            return dependencies;
        });
    }
}
exports.MigrateController = MigrateController;
MigrateController.COMMON_MIGRATE_MESSAGE = "not affect the codebase of the application and you might need to do additional changes manually – for more information, refer to the instructions in the following blog post: https://www.nativescript.org/blog/nativescript-6.0-application-migration";
MigrateController.UNABLE_TO_MIGRATE_APP_ERROR = `The current application is not compatible with NativeScript CLI 7.0.
Use the \`ns migrate\` command to migrate the app dependencies to a form compatible with NativeScript 7.0.
Running this command will ${MigrateController.COMMON_MIGRATE_MESSAGE}`;
MigrateController.MIGRATE_FINISH_MESSAGE = `The \`tns migrate\` command does ${MigrateController.COMMON_MIGRATE_MESSAGE}`;
MigrateController.typescriptPackageName = "typescript";
MigrateController.backupFolder = ".migration_backup";
MigrateController.migrateFailMessage = "Could not migrate the project!";
MigrateController.backupFailMessage = "Could not backup project folders!";
MigrateController.folders = [
    constants.LIB_DIR_NAME,
    constants.HOOKS_DIR_NAME,
    constants.WEBPACK_CONFIG_NAME,
    constants.PACKAGE_JSON_FILE_NAME,
    constants.PACKAGE_LOCK_JSON_FILE_NAME,
    constants.TSCCONFIG_TNS_JSON_NAME,
    constants.KARMA_CONFIG_NAME,
    constants.CONFIG_NS_FILE_NAME,
];
yok_1.injector.register("migrateController", MigrateController);
