UNPKG

uxp-linter-test-app

Version:

UXP LINTER is useful for linting your code with ESLint rules and guidelines.

431 lines (380 loc) 18.2 kB
#!/usr/bin/env node "use strict"; require("v8-compile-cache"); var fs = require('fs'), utils = require('./utils'); var path = require('path'), lintIgnore = path.join(__dirname, '.eslintignore'), packageJson = require('./../package.json'), constants = require('./constants'); const { fileTypeArray, outputDirectory, rules_category, eslintPrefix } = constants; const linterDependencies = require('./uxp-linter-dependencies.json'); const installPeerDependencies = utils.isPeerDepsInstallationReqd(); // For starting the configuration for uxp linter function configureLinter(rl, param, type) { return new Promise(function (resolve, reject) { if (param === 'remove') { uninstallUxpLinter(type).then(() => { resolve(true) }); } else { installUxpLinter(rl).then(() => { resolve(true) }); } }); } async function installUxpLinter(rl = {}) { await installRequestedLinter(rl); } async function installRequestedLinter(rl) { return new Promise(function (resolve, reject) { let projectOptions = []; let uxpDependencies = [...linterDependencies.frameworks]; uxpDependencies.sort(function (opt1, opt2) { return opt1.seqNo - opt2.seqNo; }); if ((typeof (rl.question) != 'function')) { let configData = utils.readLinterConfig(); let projTypeArr = uxpDependencies.filter(obj => obj.type == configData['projectType']); if (projTypeArr.length <= 0) { console.error('\x1b[31m%s\x1b[0m', 'No data available!'); process.kill(0); } let projTypeObj = projTypeArr[0]; handlePackageInstallationForUxpLinter(rl, projTypeObj, resolve); } else { for (let i = 0; i < uxpDependencies.length; i++) { projectOptions.push({ 'option': uxpDependencies[i].seqNo, 'text': uxpDependencies[i].type }); } let projTypeMsg = `\nWhich framework does your project use?`; for (let i = 0; i < projectOptions.length; i++) { projTypeMsg += '\n' + projectOptions[i].option + '. ' + projectOptions[i].text; } projTypeMsg += `\nEnter only one option: `; rl.question(projTypeMsg, async function (selectedOption) { let projTypeArr = uxpDependencies.filter(obj => obj.seqNo == selectedOption); if (projTypeArr.length <= 0) { console.error('\x1b[31m%s\x1b[0m', 'Invalid option selected!'); process.kill(0); } let projTypeObj = projTypeArr[0]; handlePackageInstallationForUxpLinter(rl, projTypeObj, resolve) }); } }); } async function handlePackageInstallationForUxpLinter(rl, projTypeObj, resolve) { let languageTypeObj = await askLanguageTypeForUxpLinter(rl, projTypeObj); const updateConfig = {'projectType': projTypeObj.type, 'languageType': languageTypeObj.subType } await utils.updateLinterConfig(updateConfig); console.log('\x1b[33m%s\x1b[0m', '\nInstalling required packages. Please wait...'); let installPackageArr = []; let defaultPackagesArr = linterDependencies.defaultPackages; if (defaultPackagesArr && defaultPackagesArr.length > 0) { for (let i = 0; i < defaultPackagesArr.length; i++) { let packageObj = defaultPackagesArr[i]; let installPackName = packageObj.packageName; if (packageObj.version && packageObj.version.trim().length > 0) { installPackName = installPackName + '@' + packageObj.version; } installPackageArr.push(installPackName); if(installPeerDependencies && packageObj.peerDependencies) { const pkgs = utils.getPackagesList(packageObj.peerDependencies); installPackageArr.push(...pkgs); } } } for (let i = 0; i < languageTypeObj.requiredPackages.length; i++) { let packageObj = languageTypeObj.requiredPackages[i]; let installPackName = packageObj.packageName; // If dependency has cmd array if (packageObj.cmd && packageObj.cmd.length > 0) { for (let j = 0; j < packageObj.cmd.length; j++) { await require(packageObj.cmd[j]); } } else if (packageObj.version && packageObj.version.trim().length > 0) { installPackName = installPackName + '@' + packageObj.version; installPackageArr.push(installPackName); } if(installPeerDependencies && packageObj.peerDependencies) { const pkgs = utils.getPackagesList(packageObj.peerDependencies); installPackageArr.push(...pkgs); } } if (installPackageArr.length > 0) { await utils.installPackages(installPackageArr, true); } // For creating backup of all eslintrc files await utils.createFileBackup(fileTypeArray, '_backup'); // For Copying New eslint file let eslintrcFilePath = path.join(__dirname, languageTypeObj.eslintrcPath); await utils.addConfigFile(eslintrcFilePath, '.eslintrc', true); await utils.createNewDirectory(outputDirectory); await utils.addConfigFile(lintIgnore, '.eslintignore', false); resolve(true); } function getInstalledProjectType() { return new Promise(async function (resolve, reject) { let rawdata = fs.readFileSync('package.json'); var loadDependancy = JSON.parse(rawdata); let projectType = null; if (loadDependancy.config && loadDependancy.config.uxpLinter && loadDependancy.config.uxpLinter.projectType) { projectType = loadDependancy.config.uxpLinter.projectType; } resolve(projectType); }); } function getInstalledLanguageType() { return new Promise(async function (resolve, reject) { let rawdata = fs.readFileSync('package.json'); var loadDependancy = JSON.parse(rawdata); let languageType = null; if (loadDependancy.config && loadDependancy.config.uxpLinter && loadDependancy.config.uxpLinter.languageType) { languageType = loadDependancy.config.uxpLinter.languageType; } resolve(languageType); }); } function uninstallUxpLinter(type) { return new Promise(async function (resolve, reject) { let removePackageNames = []; let defaultPackagesArr = linterDependencies.defaultPackages; if (defaultPackagesArr && defaultPackagesArr.length > 0) { for (let i = 0; i < defaultPackagesArr.length; i++) { removePackageNames.push(defaultPackagesArr[i].packageName); if(installPeerDependencies && defaultPackagesArr[i].peerDependencies) { const pkgs = utils.getPackagesList(defaultPackagesArr[i].peerDependencies); removePackageNames.push(...pkgs); } } } let projectType = await getInstalledProjectType(); let languageType = await getInstalledLanguageType(); if (projectType && languageType) { let uxpDependencies = [...linterDependencies.frameworks]; let projTypeArr = uxpDependencies.filter(obj => obj.type == projectType); if (projTypeArr.length > 0) { let projTypeObj = projTypeArr[0]; let languageTypeArr = projTypeObj.languageType.filter(obj => obj.subType == languageType); if (languageTypeArr.length > 0) { let languageTypeObj = languageTypeArr[0]; for (let i = 0; i < languageTypeObj.requiredPackages.length; i++) { let packageObj = languageTypeObj.requiredPackages[i]; // If dependency has cmd array if (packageObj.cmd && packageObj.cmd.length > 0) { for (let j = 0; j < packageObj.cmd.length; j++) { await require('./scripts/uninstall-cmd-package.js'); } } else { removePackageNames.push(packageObj.packageName); } } } } } if (type == 'all') { removeConfigFiles(); removePackageNames.push(packageJson.name); } if (removePackageNames.length > 0) { await utils.uninstallPackages(removePackageNames); } resolve(true); }); } async function removeConfigFiles() { var fileExistEslintrc = fs.existsSync('.eslintrc'); if (fileExistEslintrc) { fs.unlink('.eslintrc', function (err) { if (err) throw err; }); await utils.restoreBackupFile(fileTypeArray, '_backup'); } var fileExistUxpLintrc = fs.existsSync('.uxplinterrc.json'); if (fileExistUxpLintrc) { fs.unlink('.uxplinterrc.json', function (err) { if (err) throw err; }); await utils.restoreBackupFile(fileTypeArray, '_backup'); } var fileEslintIgnore = fs.existsSync('.eslintignore'); if (fileEslintIgnore) { fs.unlink('.eslintignore', function (err) { if (err) throw err; }); await utils.restoreBackupFile(['eslintignore'], '_backup'); } // Need to add once Sonar Integration is implemented // var fileSonar = fs.existsSync('sonar-project.properties'); // if (fileSonar) { // fs.unlink('sonar-project.properties', function (err) { // if (err) throw err; // }); // await utils.restoreBackupFile(['sonar-project'], '_backup'); // } } function runCategoryScript(rl, rules_profile, option) { return new Promise(async function (resolve, reject) { let runCategory = false; const projectType = await utils.getProjectType(); let config = utils.readLinterConfig(); let language = config.languageType.toLowerCase() let prefix = ''; if (projectType === 'React') { prefix = `${eslintPrefix}/react`; runCategory = true; } else if (projectType === 'Angular') { prefix = `${eslintPrefix}/angular`; runCategory = true; } else if (projectType === 'Vue') { prefix = `${eslintPrefix}/vue`; runCategory = true; } else if (projectType === 'TypeScript') { prefix = `${eslintPrefix}/typescript`; runCategory = true; } else if (projectType === 'Vanilla JS/ES6') { prefix = `${eslintPrefix}/javascript`; runCategory = true; } else { console.error('\x1b[31m%s\x1b[0m', 'Please install UXP-Linter before selecting any rules.'); resolve(true); } if (runCategory) { let fileExist1 = fs.existsSync('.eslintrc'), fileExist2 = fs.existsSync('.eslintrc.js'), getFileName = fileExist1 ? '.eslintrc' : fileExist2 ? '.eslintrc.js' : null, readRowData, parsedRowData, getPromiseData; if (getFileName) { readRowData = fs.readFileSync(getFileName); parsedRowData = JSON.parse(readRowData); } switch (rules_profile) { case 'custom': let questionForCustomRules = function () { return new Promise(async function (resolve, reject) { rl.question("\nPlease enter the path of rules file (File should be in json format): ", function (input) { let inputFileExist = fs.existsSync(input); if (!inputFileExist) { console.log('\x1b[31m%s\x1b[0m', 'Unable to add custom rules! Input file not found.'); resolve(true); } else { if (!input.startsWith("./")) { input = "./" + input; } getPromiseData = utils.extendValueIneslint(parsedRowData, option, input); resolve(true); } }); }); } await questionForCustomRules(); break; case 'sonar': getPromiseData = utils.extendValueIneslint(parsedRowData, option, `${eslintPrefix}/sonar-${language}-essential.js`); break case `${rules_profile}`: let filePath; if (projectType === 'TypeScript' || projectType === 'Vanilla JS/ES6') filePath = `${prefix}-${rules_profile}.js`; else filePath = `${prefix}-${language}-${rules_profile}.js`; getPromiseData = utils.extendValueIneslint(parsedRowData, option, filePath); break; } let rulesProfile = rules_category.filter(e => e.category === rules_profile); rulesProfile = rulesProfile && rulesProfile[0] ? rulesProfile[0].label : ''; if (getFileName && !!getPromiseData) { getPromiseData.then((resolve, reject) => { utils.updateLinterConfig({'linterProfile': rulesProfile}); let data = JSON.stringify(resolve, null, 4); fs.writeFileSync(getFileName, data); }).catch((err) => { console.error(err); }); resolve(true); } else { resolve(true); } } }); } function isJsLinterInstalled() { return new Promise(async function (resolve, reject) { let configData = utils.readLinterConfig(); if (configData['js-linter'] && configData['projectType'] && configData['languageType']) { resolve(true); } else { resolve(false); } }); } function selectLinterRule(rl, i, options) { return new Promise(async function (resolve, reject) { let linterProfile = utils.readLinterConfig('linterProfile'); let initialMessage = `\nPlease select a profile name (Current profile: ${linterProfile}) \n` let finalMessage = rules_category.reduce((message, currentCategory, index) => { const { label, description } = currentCategory; return message + `\n ${(index + 1)}. ${label} (${description})`; }, initialMessage); finalMessage += `\n\nPlease provide any one option : `; rl.question(finalMessage, async function (input) { let index = parseInt(input) - 1; if (index > -1 && index < rules_category.length) { async function showCategoryOption(opt) { const currentCategory = rules_category.filter(el => el.option === opt)[0]; const { category, label } = currentCategory; console.log('\x1b[32m%s\x1b[0m', `\n${label} rules profile has been successfully configured for JS Linter.`); await runCategoryScript(rl, category, i) } await showCategoryOption(index); } else { console.log('\x1b[31m%s\x1b[0m', '\nSorry you have entered wrong option. Please try again.'); } resolve(true); }); }); } function askLanguageTypeForUxpLinter(rl, projTypeObj) { return new Promise(async function (resolve, reject) { let languageTypeObj; if ((typeof (rl.question) != 'function')) { let configData = utils.readLinterConfig(); languageTypeObj = projTypeObj.languageType.filter(obj => obj.subType == configData['languageType'])[0]; } else { if (projTypeObj.languageType.length == 1) { languageTypeObj = projTypeObj.languageType[0]; } else if (projTypeObj.languageType.length > 1) { let languageOptions = []; for (let i = 0; i < projTypeObj.languageType.length; i++) { languageOptions.push({ 'option': (i + 1), 'text': projTypeObj.languageType[i].subType }); } let initMessage = `\nWhat type of language does your project use?`; for (let i = 0; i < languageOptions.length; i++) { initMessage += '\n' + languageOptions[i].option + '. ' + languageOptions[i].text; } initMessage += `\n\nPlease provide any one option : `; let questionForlanguageOptionSelection = function () { return new Promise(async function (resolve, reject) { rl.question(initMessage, async function (selectedOption) { let languageEsOptionArr = languageOptions.filter(obj => obj.option == selectedOption); if (languageEsOptionArr.length <= 0) { console.error('\x1b[31m%s\x1b[0m', 'You have chosen invalid option. Please try again.'); process.kill(0); } let languageEsArr = projTypeObj.languageType.filter(obj => obj.subType == languageEsOptionArr[0].text) resolve(languageEsArr[0]); }); }); } languageTypeObj = await questionForlanguageOptionSelection(); } else { console.error('\x1b[31m%s\x1b[0m', '\nLanguage type not available for selected project type!'); process.kill(0); reject(); } } resolve(languageTypeObj); }); } module.exports = { configureLinter, selectLinterRule, isJsLinterInstalled, getInstalledLanguageType, installUxpLinter }