ianalyzer-test-app
Version:
A versatile code analysis tool for JavaScript, HTML, CSS, Angular, React, Vue, and ES6. iAnalyzer ensures code quality through linting, integrates with Sonar for in-depth analysis, performs npm package security checks, assesses performance, and enhances a
479 lines (420 loc) • 16.7 kB
JavaScript
;
require('v8-compile-cache');
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const fs = require('fs'),
ScriptData = require('./script-data');
const {spawn} = require('child_process'),
path = require('path'),
constants = require('./constants'),
htmlLinter = require('./html-linter-config'),
cssLinter = require('./css-linter-config'),
prettier = require('./prettier-config'),
sonarConfig = require('./sonar-config');
const ianalyzerrcPath = path.join(__dirname, './../../../.ianalyzerrc.json');
const { ianalyzerrcInitialConfig, noPackageJson, defaultLinterPath, safeNodeVersionForPeerDeps, rules_category, jsLintCommand, jsHtmlLintCommand, packagesToInstall } = constants
//------------------------------------------------------------------------------
// Exports
//------------------------------------------------------------------------------
exports.installPackages = function installPackages(packages = [], isDev) {
return new Promise(async function (resolve) {
const packageNames = packages.reduce((original, newData) => original + ' ' + newData);
const installPkgCmd = `npm install ${isDev ? '--save-dev' : ''} ${packageNames}`;
await executeCommand(installPkgCmd, true);
resolve(true);
});
};
function executeCommand(fullCommand, isErrThrow) {
return new Promise((resolve) => {
try {
let ls = spawn(fullCommand, [], { shell: true, stdio: "inherit" });
ls.on('error', (err) => {
console.error('Failed: ', err);
if (isErrThrow) {
throw err;
} else {
resolve(true);
}
});
ls.on('exit', () => {
resolve(true);
});
} catch (err) {
console.error('Failed: ', err);
}
});
}
exports.uninstallPackages = function uninstallPackages(packages = []) {
return new Promise(async function (resolve) {
const packageNames = packages.reduce((original, newData) => original + ' ' + newData);
const uninstallPkgCmd = `npm uninstall ${packageNames}`;
await executeCommand(uninstallPkgCmd, true);
resolve(true);
});
};
exports.addConfigFile = function addConfigFile(filePath, fileName, force = true) {
return new Promise((resolve) => {
const ifFileExist = fs.existsSync(fileName);
if (force || !ifFileExist) {
fs.copyFileSync(filePath, fileName, fs.constants.COPYFILE_FICLONE);
resolve(true);
}
else {
resolve(true);
}
});
};
exports.removeConfigFile = function removeConfigFile(fileName) {
return new Promise((resolve) => {
const fileExist1 = fs.existsSync(fileName);
if (fileExist1) {
fs.unlink(fileName, (err) => {
if (err) {
throw err;
} else {
resolve(true);
}
});
} else {
resolve(true);
}
});
};
exports.addScriptPackageJSON = function addScriptPackageJSON(scripts = [new ScriptData('', '')], pkgJsonPath = 'package.json') {
return new Promise((resolve) => {
const rawdata = fs.readFileSync(pkgJsonPath);
const loadDependancy = JSON.parse(rawdata);
if (!loadDependancy?.scripts) {
loadDependancy.scripts = {}
}
scripts.forEach((script) => {
loadDependancy.scripts[script.name] = script.value;
});
const data = JSON.stringify(loadDependancy, null, 4);
fs.writeFileSync(pkgJsonPath, data);
resolve(true);
});
};
exports.removeScriptPackageJSON = function removeScriptPackageJSON(scripts = []) {
return new Promise((resolve) => {
const rawdata = fs.readFileSync('package.json');
const loadDependancy = JSON.parse(rawdata);
if (loadDependancy?.scripts) {
scripts.forEach((script) => {
delete loadDependancy.scripts[script];
});
}
const loadData = JSON.stringify(loadDependancy, null, 4);
fs.writeFileSync('package.json', loadData);
resolve(true);
});
};
exports.createFileBackup = function createFileBackup(fileNameArray = [], suffix = '_backup') {
return new Promise((resolve) => {
for (const key in fileNameArray) {
if (fs.existsSync(fileNameArray[key])) {
fs.renameSync(fileNameArray[key], `${fileNameArray[key]}${suffix}`, (err) => {
if (err) {
throw err;
}
});
}
}
resolve(true);
});
};
exports.restoreBackupFile = function restoreBackupFile(fileNameArray = [], suffix = '_backup') {
return new Promise((resolve) => {
for (const key in fileNameArray) {
const backupFileName = fileNameArray[key] + suffix;
if (fs.existsSync(backupFileName)) {
const newFileName = backupFileName.replace(suffix, '');
fs.renameSync(backupFileName, newFileName, (err) => {
if (err) {
throw err;
}
});
}
}
resolve(true);
});
};
exports.createNewDirectory = function createNewDirectory(directoryPath) {
return new Promise((resolve) => {
if (!fs.existsSync(directoryPath)) {
fs.mkdirSync(directoryPath);
}
resolve(true);
});
};
exports.extendValueIneslint = function (parsedRowData, option, entry) {
return new Promise((resolve) => {
const parsedRow = parsedRowData;
if (parsedRow?.extends) {
if (option === 0) {
parsedRow.extends = [];
}
if (!parsedRow.extends.includes(entry)) {
parsedRow.extends.push(entry);
}
}
resolve(parsedRow);
});
}
function isPackageInstalled(packageName) {
return new Promise((resolve) => {
const rawdata = fs.readFileSync('package.json');
const loadDependency = JSON.parse(rawdata);
if (
loadDependency?.dependencies
&& loadDependency?.dependencies[packageName]
) {
resolve(true);
} else if (
loadDependency?.devDependencies
&& loadDependency?.devDependencies[packageName]
) {
resolve(true);
} else {
resolve(false);
}
});
}
exports.isPackageInstalled = isPackageInstalled;
function getLinterPath() {
return new Promise(async function (resolve) {
const config = readLinterConfig();
resolve(config.path || '');
});
}
exports.getLinterPath = getLinterPath;
exports.getProjectType = function getProjectType() {
return new Promise(async function (resolve) {
const config = readLinterConfig();
resolve(config.projectType || '');
});
}
exports.languageType = function languageType() {
return new Promise(async function (resolve) {
const config = readLinterConfig();
resolve(config.languageType || '');
});
}
/**
* For fetching Linting command from linterrc file
*/
exports.getLintCommand = function getLintCommand(linterType, runType) {
return new Promise(async function (resolve) {
const config = readLinterConfig();
const commandType = `${linterType}${runType}Command`;
let command = config[commandType];
if (linterType === 'css') {
if (config.path !== '' && config.path.slice(-1) !== '/') {
config.path = `${config.path}/`;
}
}
if (command.indexOf('$path') > -1) {
command = command.replace('$path', config.path);
}
resolve(command);
});
}
function isPathAlreadySet() {
return new Promise(async function (resolve) {
const currentPath = await getLinterPath();
resolve(currentPath.length !== 0);
});
}
function askPathToLint(rl, currentPath = '') {
return new Promise((resolve) => {
rl.question(`\nPlease provide path to lint ( or Press Enter for current path: ${currentPath || defaultLinterPath} ) : `, async function (pathName) {
if (pathName.length === 0) {
updateLinterConfig({'path': (currentPath || defaultLinterPath)});
}
else {
updateLinterConfig({'path': pathName.trim()});
if (currentPath.length !== 0) console.log('\x1b[32m%s\x1b[0m', '\nPath updated successfully!');
}
resolve(true);
})
})
}
exports.askPathIfNotExist = async function (rl) {
if (!await isPathAlreadySet()) await askPathToLint(rl);
}
exports.askPathToLint = askPathToLint;
exports.executeCommand = executeCommand;
exports.initializeLinterConfig = async function () {
let initialData = ianalyzerrcInitialConfig;
initialData = JSON.stringify(initialData, null, 4);
writeLinterConfig(initialData);
}
function readLinterConfig(key) {
let configData = fs.readFileSync(ianalyzerrcPath);
configData = JSON.parse(configData)
if (key) return configData[key];
return configData;
}
exports.readLinterConfig = readLinterConfig;
function writeLinterConfig(data) {
fs.writeFileSync(ianalyzerrcPath, data);
}
function updateLinterConfig(updateData) {
return new Promise((resolve) => {
let configData = readLinterConfig();
for (const data in updateData) {
configData[data] = updateData[data];
}
configData = JSON.stringify(configData, null, 4);
writeLinterConfig(configData);
resolve(true);
});
}
exports.updateLinterConfig = updateLinterConfig;
/**
* For deleting keys from ianalyzerrc file
*/
function deleteLinterConfig(deleteData) {
return new Promise((resolve) => {
let configData = readLinterConfig();
for (const data of deleteData) {
delete configData[data];
}
configData = JSON.stringify(configData, null, 4);
writeLinterConfig(configData);
resolve(true);
});
}
exports.deleteLinterConfig = deleteLinterConfig;
/**
* For creating Package Json file
*/
exports.initializePackageJson = async function () {
let initialData = noPackageJson;
initialData = JSON.stringify(initialData, null, 4);
fs.writeFileSync(path.join(__dirname, './../../../package.json'), initialData);
}
/**
* For checking required package version of user's project
* @param key - Dependency for checking the versiom
*/
exports.getPackageVersion = function (key) {
return new Promise((resolve) => {
const rawdata = fs.readFileSync('package.json');
const loadDependency = JSON.parse(rawdata);
const keyVal = loadDependency.dependencies[key];
let reqVersion = '';
if (keyVal) {
reqVersion = parseInt(keyVal.substring(1, keyVal.indexOf('.')));
}
resolve(reqVersion);
});
}
exports.getProjectName = function () {
return new Promise((resolve) => {
const rawdata = fs.readFileSync('package.json');
const loadDependency = JSON.parse(rawdata);
const projName = loadDependency.name;
resolve(projName);
});
}
exports.getPackagesList = function (dependencies) {
const packagesArr = [];
if(dependencies.length) {
dependencies.forEach((pkg) => {
const { packageName, version } = pkg;
let dependencyName = packageName;
if (version && version.trim().length > 0) {
dependencyName = dependencyName + '@' + version;
}
packagesArr.push(dependencyName);
})
}
return packagesArr;
}
exports.isPeerDepsInstallationReqd = function () {
return process.version && process.version.split('.')[0].slice(1,) < safeNodeVersionForPeerDeps;
}
exports.getJsLinterCommand = function () {
let currentProfile = readLinterConfig("linterProfile");
let jsHtmlProfile = rules_category.filter((r) => r.category === "recommended")[0].label;
let jsLinterCommand =
(currentProfile === jsHtmlProfile) ? jsHtmlLintCommand : jsLintCommand;
return jsLinterCommand;
};
exports.loggerHandler = function () {
let util = require("util");
let myPath = path.join(__dirname, "/../ianalyzer.log");
let log_file = fs.createWriteStream(myPath, { flags: "a", encoding: "utf8" });
let log_err = fs.createWriteStream(myPath, { flags: "a", encoding: "utf8" });
let log_stdout = process.stdout;
let log_stderr = process.stderr;
let date = new Date();
date = date.getTime();
console.log = function (...d) {
log_file.write(util.format(...d) + ` -${date}\n`);
log_stdout.write(util.format(...d) + '\n');
};
console.error = function (...d) {
log_err.write(util.format(...d) + ` -${date}\n`);
log_stderr.write(util.format(...d) + '\n');
};
};
exports.getFormatTypeForLinter = function (formatTypes, linterTypes, allReportTypeArr, type) {
const i = linterTypes.indexOf(type);
const reportType = allReportTypeArr.find((report) => report.type === formatTypes[i]);
if (reportType) {
return reportType.type;
} else {
return "";
}
}
async function checkLinterPackagesInstalled (linterType) {
let jsLinterPackageName = '';
if(linterType === 'js-linter' && readLinterConfig('projectType') && readLinterConfig('languageType')){
const ianalyzerDependencies = require('./ianalyzer-dependencies.json');
let projectTypeDeps = ianalyzerDependencies?.frameworks?.filter(item => item.type === readLinterConfig('projectType'))[0];
const languageTypeDeps = projectTypeDeps?.languageType;
jsLinterPackageName = languageTypeDeps?.filter(item => item.subType === readLinterConfig('languageType'))[0]?.requiredPackages[0]?.packageName || '';
}
const pkgNames = {
'js-linter' : jsLinterPackageName,
...packagesToInstall
}
const pkgToCheck = pkgNames[linterType];
if(!pkgToCheck || await isPackageInstalled(pkgToCheck))
return true;
return false;
}
exports.checkLinterPackagesInstalled = checkLinterPackagesInstalled;
exports.installRequestedLinter = async function (configData) {
if (configData['js-linter'] && !(await checkLinterPackagesInstalled('js-linter'))) {
console.log('\x1b[32m%s\x1b[0m', '\nStart: JS Linter installation.');
const iAnalyzer = require('./ianalyzer-config');
await iAnalyzer.installIAnalyzer()
console.log("JS installation complete")
}
if (configData['html-linter'] && !(await checkLinterPackagesInstalled('html-linter'))) {
console.log('\x1b[32m%s\x1b[0m', '\nStart: HTML Linter installation.');
await htmlLinter.installHtmlLinter();
console.log("HTML installation complete")
}
if (configData['css-linter'] && !(await checkLinterPackagesInstalled('css-linter'))) {
console.log('\x1b[32m%s\x1b[0m', '\nStart: CSS Linter installation.');
const cssConfigFileName = './.stylelintrc.json';
const eslintConfigFilePath = path.join(__dirname, './templates/.stylelintrc.json');
await cssLinter.installCssLinter(eslintConfigFilePath, cssConfigFileName);
console.log("CSS installation complete")
}
if (configData['prettier'] && !(await checkLinterPackagesInstalled('prettier'))) {
console.log('\x1b[32m%s\x1b[0m', '\nStarting: Prettier installation...');
await prettier.installPrettier();
console.log("Prettier installation complete")
}
if (configData['sonar-scanner'] && !(await checkLinterPackagesInstalled('sonar-scanner'))) {
console.log('\x1b[32m%s\x1b[0m', '\nStarting: Sonarqube Scanner installation...');
await sonarConfig.configureSonarScanner();
console.log("Sonarqube Scanner installation complete")
}
}