@microsoft/windows-admin-center-sdk
Version:
Microsoft - Windows Admin Center Shell
295 lines (293 loc) • 15.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.EslintUpgrader = exports.EslintUpgraderMessages = exports.UpgradeType = void 0;
const tslib_1 = require("tslib");
const fs_extra_1 = tslib_1.__importStar(require("fs-extra"));
const common_1 = require("../common");
const child_process_1 = require("child_process");
/**
* Represents the type of upgrade that needs to be performed.
*/
var UpgradeType;
(function (UpgradeType) {
UpgradeType["WithBaseConfig"] = "WithBaseConfig";
UpgradeType["WithoutBaseConfig"] = "WithoutBaseConfig";
UpgradeType["NoOperation"] = "NoOperation";
})(UpgradeType = exports.UpgradeType || (exports.UpgradeType = {}));
/**
* Represents the messages that are displayed during the upgrade process.
*/
var EslintUpgraderMessages;
(function (EslintUpgraderMessages) {
EslintUpgraderMessages["StartingUpgrade"] = "Starting upgrade eslinting process...";
EslintUpgraderMessages["CheckingFilePaths"] = "Checking file paths...";
EslintUpgraderMessages["UpdateTypeWithBaseConfig"] = "UpdateType: WithBaseConfig";
EslintUpgraderMessages["UpdateTypeWithoutBaseConfig"] = "UpdateType: WithoutBaseConfig";
EslintUpgraderMessages["UpdateTypeWithoutBoth"] = "UpdateType: NoOperation";
EslintUpgraderMessages["ExitWithoutBaseConfig"] = "Exiting upgrade eslinting process...";
EslintUpgraderMessages["RCANoTsConfigFile"] = "Please manually create a tsconfig.json file in the root of your project.";
EslintUpgraderMessages["GettingTsConfigFile"] = "Getting tsconfig.json file...";
EslintUpgraderMessages["UpdateTsConfigContent"] = "Updating tsconfig.json content...";
EslintUpgraderMessages["RevertTsConfigContent"] = "Reverting tsconfig.json content...";
EslintUpgraderMessages["RenameTsBaseConfig"] = "Renaming tsconfig.base.json to tsconfig.base.json_backup...";
EslintUpgraderMessages["RevertTsBaseConfig"] = "Renaming tsconfig.base.json_backup to tsconfig.base.json...";
EslintUpgraderMessages["UpdateEslintConfig"] = "Updating .eslintrc.json content...";
EslintUpgraderMessages["UpdatePolyfills"] = "Updating polyfills.ts content...";
EslintUpgraderMessages["UpdateKarmaFile"] = "Updating karma.conf.js content...";
EslintUpgraderMessages["FinalizeInfoLintFix"] = "There are eslint violations that needs fix... After fixing the violations, please run the following commands:\n\n npx eslint . --fix \n\n gulp lintApp \n\n gulp build \n\n ";
EslintUpgraderMessages["Completed"] = "Upgrade completed!";
})(EslintUpgraderMessages = exports.EslintUpgraderMessages || (exports.EslintUpgraderMessages = {}));
/**
* This is the main class of the EslintUpgrader tool.
* It is responsible for upgrading the Tslint to Eslint.
*/
class EslintUpgrader {
tsconfigBaseFilePath;
tsconfigFilePath;
angularFilePath;
debug = false;
libUpgrade = false;
tsconfigBaseFileName = 'tsconfig.base.json';
tsconfigFileName = 'tsconfig.json';
tsconfigBaseFileNameBackUp = 'tsconfig.base.json_backup';
angularFileName = 'angular.json';
eslintConfigFileName = '.eslintrc.json';
eslintConfigFileContent = {
"extends": "./node_modules/@microsoft/windows-admin-center-sdk/tools/code-formatter/.eslintrc.base.json"
};
polifillsFilePath = './src/polyfills.ts';
karmaConfigFilePath = './src/karma.conf.js';
eslintDisable = 'eslint-disable';
targetGulpLintFilePath = '.\\gulpfile.ts\\common\\lint.ts';
targetGulpLintIndexFilePath = './gulpfile.ts/index.ts';
targetGulpLintUiTestAutomationFilePath = '.\\gulpfile.ts\\common\\ui-test-automation.ts';
/**
* The main upgrade process
* @param debug - Indicates if the debug mode is enabled.
* @returns Promise<void> - Returns a promise that resolves when the upgrade process is completed.
*/
async upgrade(debug = false) {
this.debug = !!debug;
this.logger(EslintUpgraderMessages.StartingUpgrade);
this.logger(EslintUpgraderMessages.CheckingFilePaths);
const upgradeType = this.checkFileExists();
this.checkLibUpgrade();
switch (upgradeType) {
case UpgradeType.WithBaseConfig:
this.logger(EslintUpgraderMessages.UpdateTypeWithBaseConfig);
this.updateTsConfigContent();
this.renameTsBaseConfig();
await this.addEslintSchematics();
await this.esLintSchematicsRunModuleApp();
if (this.libUpgrade) {
await this.esLintSchematicsRunModuleLib();
}
await this.uninstallDependencies();
await this.installDependencies();
await this.replaceEslintConfig();
this.updateTsConfigContent(true);
this.renameTsBaseConfig(true);
await this.replaceGulpLintFile();
this.cleanUpPolyfills();
this.cleanUpKarmaConfigFile();
await this.fixEslintErrors();
await this.gulpBuild();
break;
case UpgradeType.WithoutBaseConfig:
this.logger(EslintUpgraderMessages.UpdateTypeWithoutBaseConfig);
await this.addEslintSchematics();
await this.esLintSchematicsRunModuleApp();
if (this.libUpgrade) {
await this.esLintSchematicsRunModuleLib();
}
await this.uninstallDependencies();
await this.installDependencies();
await this.replaceEslintConfig();
await this.replaceGulpLintFile();
this.cleanUpPolyfills();
this.cleanUpKarmaConfigFile();
await this.fixEslintErrors();
await this.gulpBuild();
break;
case UpgradeType.NoOperation:
this.logger(EslintUpgraderMessages.UpdateTypeWithoutBoth);
this.logger(EslintUpgraderMessages.ExitWithoutBaseConfig);
this.logger(EslintUpgraderMessages.RCANoTsConfigFile);
break;
default:
break;
}
this.logger(EslintUpgraderMessages.Completed);
}
constructor() {
common_1.Common.rootPath = process.cwd();
this.updateBasicPaths();
}
updateBasicPaths() {
this.tsconfigBaseFilePath = common_1.Common.rootPath + '\\' + this.tsconfigBaseFileName;
this.tsconfigFilePath = common_1.Common.rootPath + '\\' + this.tsconfigFileName;
this.angularFilePath = common_1.Common.rootPath + '\\' + this.angularFileName;
}
checkLibUpgrade() {
const angularFilePathExists = (0, fs_extra_1.pathExists)(this.angularFilePath);
if (!angularFilePathExists) {
return;
}
const angularFileContent = common_1.Common.readFileData(this.angularFilePath);
this.libUpgrade = !!angularFileContent.includes('module-lib');
}
checkFileExists() {
const tsconfigBaseFilePathExists = (0, fs_extra_1.pathExists)(this.tsconfigBaseFilePath);
const tsconfigFilePathExists = (0, fs_extra_1.pathExists)(this.tsconfigFilePath);
if (tsconfigBaseFilePathExists && tsconfigFilePathExists) {
return UpgradeType.WithBaseConfig;
}
else if (tsconfigFilePathExists) {
return UpgradeType.WithoutBaseConfig;
}
else {
return UpgradeType.NoOperation;
}
}
updateTsConfigContent(revert = false) {
revert ? this.logger(EslintUpgraderMessages.RevertTsConfigContent) : this.logger(EslintUpgraderMessages.UpdateTsConfigContent);
revert ?
this.updateFile(this.tsconfigFilePath, `// "extends": "./${this.tsconfigBaseFileName}"`, `"extends": "./${this.tsconfigBaseFileName}"`) :
this.updateFile(this.tsconfigFilePath, `"extends": "./${this.tsconfigBaseFileName}"`, `// "extends": "./${this.tsconfigBaseFileName}"`);
}
updateFile(filePath, prev, target) {
this.logger('Updating file...' + filePath + ',' + prev + ',' + target + '...');
let fileData = common_1.Common.readFileData(filePath);
fileData = fileData.replace(prev, target);
fs_extra_1.default.writeFileSync(filePath, fileData);
}
renameTsBaseConfig(revert = false) {
revert ? this.logger(EslintUpgraderMessages.RenameTsBaseConfig) : this.logger(EslintUpgraderMessages.RevertTsBaseConfig);
const cmd = revert ? `git mv ./${this.tsconfigBaseFileNameBackUp} ./${this.tsconfigBaseFileName}` : `git mv ./${this.tsconfigBaseFileName} ./${this.tsconfigBaseFileNameBackUp}`;
this.runCommand(cmd);
}
async addEslintSchematics() {
const cmd = 'ng add @angular-eslint/schematics --skip-confirmation';
this.logger(cmd);
await this.runCommand(cmd);
}
async esLintSchematicsRunModuleApp() {
const cmd = 'ng g @angular-eslint/schematics:convert-tslint-to-eslint module-app';
this.logger(cmd);
await this.runCommand(cmd);
}
async esLintSchematicsRunModuleLib() {
const cmd = 'ng g @angular-eslint/schematics:convert-tslint-to-eslint module-lib';
this.logger(cmd);
await this.runCommand(cmd);
}
/**
* It updates to the eslintrc.json file on the root of the project.
*/
async replaceEslintConfig() {
const formattedNewContent = JSON.stringify(this.eslintConfigFileContent, null, 2)
.replace('}', '}\n');
this.logger(EslintUpgraderMessages.UpdateEslintConfig);
if (fs_extra_1.default.existsSync(`./${this.eslintConfigFileName}`)) {
this.logger('Updating eslint file');
common_1.Common.writeFileData(`./${this.eslintConfigFileName}`, formattedNewContent);
}
else {
this.logger('Creating new eslint file');
common_1.Common.writeFile(`./${this.eslintConfigFileName}`, formattedNewContent);
}
// race condition for the eslintrc file not being released by the writeFile function.
await this.sleep(1000);
}
async uninstallDependencies() {
const cmd = 'npm uninstall codelyzer gulp-tslint rxjs-tslint rxjs-tslint-rules tslint tslint-consistent-codestyle tslint-eslint-rules tslint-microsoft-contrib';
this.logger(cmd);
await this.runCommand(cmd);
const removeForRollBackCmd = 'npm uninstall gulp-eslint eslint eslint-plugin-angular eslint-plugin-import eslint-plugin-jsdoc eslint-plugin-jsonc eslint-plugin-prefer-arrow ' +
'@typescript-eslint/eslint-plugin @typescript-eslint/parser @angular-eslint/builder @angular-eslint/eslint-plugin @angular-eslint/eslint-plugin-template @angular-eslint/schematics ' +
'@angular-eslint/template-parser';
this.logger(removeForRollBackCmd);
await this.runCommand(removeForRollBackCmd);
}
async installDependencies() {
const cmd = 'npm install gulp-eslint@6.0.0 eslint@7.6.0 eslint-plugin-angular@4.1.0 eslint-plugin-import@2.21.0 eslint-plugin-jsdoc@36.1.1 eslint-plugin-jsonc@2.8.0 eslint-plugin-prefer-arrow@1.2.3 ' +
'@typescript-eslint/eslint-plugin@4.16.1 @typescript-eslint/parser@4.16.1 @angular-eslint/builder@4.3.1 @angular-eslint/eslint-plugin@4.3.1 @angular-eslint/eslint-plugin-template@4.3.1 ' +
'@angular-eslint/schematics@4.3.1 @angular-eslint/template-parser@4.3.1 --save-dev';
this.logger(cmd);
await this.runCommand(cmd);
}
async fixEslintErrors() {
const rootFileLinterFix = 'npx eslint . --fix';
this.logger(rootFileLinterFix);
await this.runCommand(rootFileLinterFix, true, EslintUpgraderMessages.FinalizeInfoLintFix);
const projectLinterFix = 'npx ng lint --fix';
this.logger(projectLinterFix);
await this.runCommand(projectLinterFix, true, EslintUpgraderMessages.FinalizeInfoLintFix);
}
async replaceGulpLintFile() {
const cmd = `del ${this.targetGulpLintFilePath}`;
this.logger(cmd);
await this.runCommand(cmd);
if ((0, fs_extra_1.pathExists)(this.targetGulpLintIndexFilePath)) {
this.updateFile(this.targetGulpLintIndexFilePath, `import { LintModule } from './common/lint'`, `import { LintModule } from '../node_modules/@microsoft/windows-admin-center-sdk/tools/code-formatter/lint'`);
}
if ((0, fs_extra_1.pathExists)(this.targetGulpLintUiTestAutomationFilePath)) {
this.updateFile(this.targetGulpLintUiTestAutomationFilePath, `import { LintModule } from './lint'`, `import { LintModule } from '../../node_modules/@microsoft/windows-admin-center-sdk/tools/code-formatter/lint'`);
// The new UI automation framework will remove this line.
// This is for the repositories that has not yet onboraded to the new frawework.
this.updateFile(this.targetGulpLintUiTestAutomationFilePath, `export const uiTestAutomation = series(LintModule.lintUiTestAutomation, buildUiTestAutomation);`, `export const uiTestAutomation = series(LintModule.lintUiTestAutomation_legacy, buildUiTestAutomation);`);
}
}
async gulpBuild() {
const cmd = 'gulp build';
this.logger(cmd);
await this.runCommand(cmd);
}
cleanUpPolyfills() {
this.logger(EslintUpgraderMessages.UpdatePolyfills);
const fileDataInLines = common_1.Common.readFileData(this.polifillsFilePath).split('\n');
const newLines = fileDataInLines.filter(line => !line.includes(this.eslintDisable));
common_1.Common.writeFileData(this.polifillsFilePath, newLines.join('\n'));
}
cleanUpKarmaConfigFile() {
this.logger(EslintUpgraderMessages.UpdateKarmaFile);
this.updateFile(this.karmaConfigFilePath, `module.exports = (config) => {`, `module.exports = function (config) {`);
}
runCommand(cmd, forceDebug = false, finalizeInfo = undefined) {
console.log(`Running ${cmd}`);
return new Promise((resolve) => {
const child = (0, child_process_1.exec)(cmd, (error, stdout, stderr) => {
if (error) {
console.error(` exec error: ${error}`);
return;
}
stdout.split('\n').filter(line => line.trimEnd()).forEach(line => console.log(line));
stderr.split('\n').filter(line => line.trimEnd()).forEach(line => console.error(line));
resolve();
});
if (this.debug || forceDebug) {
child.stdout.on('data', (data) => {
data.split('\n').filter(line => line.trimEnd()).forEach(line => console.log(` ${line}`));
});
}
child.stderr.on('data', (data) => {
data.split('\n').filter(line => line.trimEnd()).forEach(line => console.error(` ${line}`));
});
child.on('close', (code) => {
console.log(`exitCode: ${code}`);
if (code !== 0 && finalizeInfo) {
this.logger(finalizeInfo);
this.logger(EslintUpgraderMessages.Completed);
}
});
});
}
logger(value, prefix = 'Main thread') {
console.log(`${prefix} - ${value}`);
}
sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
exports.EslintUpgrader = EslintUpgrader;
//# sourceMappingURL=main.js.map