@zohodesk/codestandard-validator 0.0.6-exp-6 → 0.0.6-exp-8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,310 @@
1
+ "use strict";
2
+
3
+ const {
4
+ exec
5
+ } = require('child_process');
6
+ const fs = require('fs');
7
+ const path = require('path');
8
+ const {
9
+ getEslintExecutablePath
10
+ } = require('../../utils/EslintConfigFileUtils/getEslintExecutablePath');
11
+ const {
12
+ getNodeModulesPath
13
+ } = require('../../utils/General/getNodeModulesPath');
14
+ const {
15
+ filterFiles,
16
+ filterWarningInFile
17
+ } = require('../../utils/FileAndFolderOperations/filterFiles');
18
+ const {
19
+ Logger
20
+ } = require('../../utils/Logger/Logger');
21
+ const {
22
+ checkIfPluginsAreInstalled
23
+ } = require('../../utils/PluginsInstallation/checkIfPluginsAreInstalled');
24
+ const {
25
+ getBranchName
26
+ } = require('../../utils/GitActions/gitActions');
27
+ const {
28
+ getConfigurationPrecommit,
29
+ getSupportedLanguage
30
+ } = require('../../utils/General/getGeneralInfo');
31
+ const {
32
+ getRootDirectory
33
+ } = require('../../utils/General/RootDirectoryUtils/getRootDirectory');
34
+ const {
35
+ impactBasedPrecommit,
36
+ shouldWarningsAbortCommit
37
+ } = getConfigurationPrecommit();
38
+
39
+ /**
40
+ * @function isMergeCommit - This method check whether it is merge or not
41
+ * @returns {Boolean} - return boolean based on latest merge changes
42
+ */
43
+ async function isMergeCommit() {
44
+ return new Promise((resolve, reject) => {
45
+ exec('git rev-parse -q --verify MERGE_HEAD', (error, stderr, stdout) => {
46
+ if (error) {
47
+ reject(error.toString().trim());
48
+ } else if (stderr) {
49
+ resolve(stderr.trim());
50
+ } else if (stdout) {
51
+ resolve(stdout.trim());
52
+ }
53
+ });
54
+ });
55
+ }
56
+
57
+ /**
58
+ * @function {getStagedFiles} - methods return staged files
59
+ * @returns {Array<string>} - array of files
60
+ */
61
+
62
+ async function getStagedFiles() {
63
+ return new Promise((resolve, reject) => {
64
+ exec("git diff --staged --name-only", (error, stderr, stdout) => {
65
+ if (error) {
66
+ if (error != null) reject("Couldn't fetch staged files");
67
+ } else if (stderr) {
68
+ resolve(filterDeltedFileFromStagedFiles(stderr.trim().split('\n')));
69
+ } else if (stdout.trim() === '') {
70
+ resolve(stdout.trim());
71
+ }
72
+ });
73
+ });
74
+ }
75
+
76
+ /**
77
+ * @function {filterDeltedFileFromStagedFiles} - filter deleted staged files
78
+ * @param {Array<string>} files - staged files
79
+ * @returns
80
+ */
81
+ function filterDeltedFileFromStagedFiles(files) {
82
+ return files.filter(file => {
83
+ const absolutePath = path.resolve(getRootDirectory(), file);
84
+ if (fs.existsSync(absolutePath)) {
85
+ return true;
86
+ }
87
+ return false;
88
+ });
89
+ }
90
+
91
+ /**
92
+ * @function findEslintErrors - method Lint given file based on given configuration
93
+ * @param {*} file - path of file to lint
94
+ * @returns {Array<string>} - array of command line report as a string
95
+ */
96
+
97
+ async function findEslintErrors(file) {
98
+ let nodeModulesPathOfProject = `${getNodeModulesPath()}`;
99
+ let eslintExecutablePath = getEslintExecutablePath();
100
+ let eslintConfigurationFilePath = `${nodeModulesPathOfProject}/.eslintrc.js`;
101
+ let isEslintExecutablePresent = fs.existsSync(eslintExecutablePath) ? true : false;
102
+ let isNodeModulesPresent = fs.existsSync(nodeModulesPathOfProject);
103
+ if (isNodeModulesPresent) {
104
+ if (isEslintExecutablePresent) {
105
+ return new Promise((resolve, reject) => {
106
+ exec(`npx --ignore-existing "${eslintExecutablePath}" --config "${eslintConfigurationFilePath}" --no-inline-config --resolve-plugins-relative-to="${nodeModulesPathOfProject}/node_modules" ${file}`, (error, stderr, stdout) => {
107
+ if (stderr) {
108
+ resolve(stderr.trim().split('\n'));
109
+ } else if (error) {
110
+ Logger.log(Logger.FAILURE_TYPE, error);
111
+ reject("Error executing eslint command");
112
+ } else {
113
+ resolve([]);
114
+ }
115
+ });
116
+ });
117
+ } else {
118
+ Logger.log(Logger.INFO_TYPE, 'Eslint executable not found. make sure eslint plugin is installed');
119
+ }
120
+ } else {
121
+ Logger.log(Logger.INFO_TYPE, 'node_modules not found');
122
+ }
123
+ }
124
+ /**
125
+ * @function {calculateGitDiffForFile} - method calculate diff of file
126
+ * @param {*} branch_name - branch name
127
+ * @param {*} file - path of file
128
+ * @returns {Promise<Array<string>>} - array of command line report as a string
129
+ */
130
+ async function calculateGitDiffForFile(branch_name, file) {
131
+ let gitDiffCommand = `git diff -U0 ${branch_name.trim()} ${file}`;
132
+ return new Promise((resolve, reject) => {
133
+ exec(gitDiffCommand, (error, stderr) => {
134
+ if (stderr) {
135
+ resolve(stderr.trim().split('\n'));
136
+ } else if (error) {
137
+ reject(error);
138
+ }
139
+ });
140
+ });
141
+ }
142
+ /**
143
+ * @function {areAllPluginsInstalled} - method whether plugin is installed or not
144
+ * @returns {Boolean} - return boolean based on plugin installed or not
145
+ */
146
+
147
+ function areAllPluginsInstalled() {
148
+ let unInstalledPlugins = checkIfPluginsAreInstalled().uninstalledPlugins;
149
+ return unInstalledPlugins.length === 0 ? true : false;
150
+ }
151
+
152
+ /**
153
+ * @function {isOnlyWarningsPresentInFile} - method that checks if only eslint warnings are present in a file
154
+ * @returns {Boolean} - returns boolean based on only warnings present or not in file
155
+ */
156
+ function isOnlyWarningsPresentInFile(eslintErrorsPresent) {
157
+ let severityOfEachErrorInFile = [];
158
+ eslintErrorsPresent.map(error => {
159
+ let partsInString = error.split(" ");
160
+ let severityOfError = partsInString.find(word => word === 'error' || word === 'warning');
161
+ severityOfEachErrorInFile.push(severityOfError);
162
+ });
163
+ return !severityOfEachErrorInFile.includes('error');
164
+ }
165
+
166
+ /**
167
+ * @function {preCommitHook} - method execute pre commit hook
168
+ * @returns {void}
169
+ */
170
+
171
+ async function preCommitHook() {
172
+ Logger.log(Logger.INFO_TYPE, 'Executing pre commit hook...');
173
+ Logger.log(Logger.INFO_TYPE, `working dir : ${process.cwd()}`);
174
+ try {
175
+ let isMerge = await isMergeCommit();
176
+ Logger.log(Logger.INFO_TYPE, 'Looks like you have merged. So skipping pre commit check');
177
+ process.exit(0);
178
+ } catch (error) {
179
+ if (areAllPluginsInstalled()) {
180
+ let staged_files = [];
181
+ let eslintConfigFiles = ['.eslintrc.js'];
182
+ let exemptionFiles = [];
183
+ let current_branch = '';
184
+ let hasEslintErrorsInChangedLines = false;
185
+ let hasEslintErrorsInFiles = false;
186
+ let areFilesStaged = false;
187
+ let shouldAbortCommit = false;
188
+ try {
189
+ current_branch = await getBranchName();
190
+ } catch {
191
+ Logger.log(Logger.INFO_TYPE, "Error fetching current branch");
192
+ }
193
+ try {
194
+ staged_files = await getStagedFiles();
195
+ if (!staged_files.length == 0) {
196
+ staged_files = filterFiles(staged_files, eslintConfigFiles, true);
197
+
198
+ // staged_files = filterFiles(staged_files,exemptionFiles) //this is the code for giving exemption to a file during pre commit
199
+ // if(staged_files.length === 0){
200
+ // Logger.log(Logger.SUCCESS_TYPE,`Commit Successful`)
201
+ // process.exit(0)
202
+ // }
203
+ areFilesStaged = true;
204
+ for (let file in staged_files) {
205
+ let currentFileName = staged_files[file];
206
+ let changedLinesArray = [];
207
+ let eslintErrorsInChangedLines = [];
208
+ let isOnlyEslintWarningsPresentInFile = false;
209
+ if (getSupportedLanguage().includes(path.extname(staged_files[file]))) {
210
+ try {
211
+ var eslintErrorsInFile = await findEslintErrors(staged_files[file]);
212
+ // eslintErrorsInFile = impactBasedPrecommit == false ? filterWarningInFile(eslintErrorsInFile) : eslintErrorsInFile
213
+ if (staged_files[file] && typeof staged_files[file] == 'string') {
214
+ if (!eslintErrorsInFile.length == 0) {
215
+ //Calculating changed lines in a file and storing them in respective arrays
216
+ if (impactBasedPrecommit) {
217
+ //git diff is computed and stored in an array
218
+ let git_diff = await calculateGitDiffForFile(current_branch, staged_files[file]);
219
+ changedLinesArray = git_diff.filter(line => line.startsWith('@@'));
220
+ let changedLinesStartArray = [];
221
+ let changedLinesEndArray = [];
222
+ for (let number of changedLinesArray) {
223
+ let changesStartLine = parseInt(number.split(' ')[2].split(',')[0]);
224
+ changedLinesStartArray.push(changesStartLine);
225
+ let changesEndLine = number.split(' ')[2].split(',')[1];
226
+ if (changesEndLine === undefined) {
227
+ changedLinesEndArray.push(changesStartLine);
228
+ } else {
229
+ changedLinesEndArray.push(changesStartLine + parseInt(changesEndLine) - 1);
230
+ }
231
+ }
232
+ for (let error = 1; error < eslintErrorsInFile.length - 2; error++) {
233
+ //eslintErrorsInFile[error].trim() - 69:26 error => Do not hardcode content. Use I18N key instead no-hardcoding/no-hardcoding,
234
+ //eslintErrorsInFile[error].trim().split(' ')[0] => 69:26
235
+ //eslintErrorsInFile[error].trim().split(' ')[0].split(':')[0] => 69
236
+
237
+ let eslintErrorLineNumber = eslintErrorsInFile[error].trim().split(' ')[0].split(':')[0];
238
+ for (let lineNumber in changedLinesStartArray) {
239
+ if (eslintErrorLineNumber >= changedLinesStartArray[lineNumber] && eslintErrorLineNumber <= changedLinesEndArray[lineNumber]) {
240
+ eslintErrorsInChangedLines.push(eslintErrorsInFile[error]);
241
+ }
242
+ }
243
+ }
244
+ if (eslintErrorsInChangedLines.length > 0) {
245
+ isOnlyEslintWarningsPresentInFile = isOnlyWarningsPresentInFile(eslintErrorsInChangedLines);
246
+ Logger.log(Logger.FAILURE_TYPE, `\x1b[1m${currentFileName}\x1b[0m`);
247
+ for (let eslintError of eslintErrorsInChangedLines) {
248
+ Logger.log(Logger.FAILURE_TYPE, `\x1b[37m${eslintError.trimEnd()}\x1b[0m`);
249
+ }
250
+ if (shouldWarningsAbortCommit) {
251
+ hasEslintErrorsInChangedLines = true;
252
+ shouldAbortCommit = true;
253
+ } else if (!shouldWarningsAbortCommit && isOnlyEslintWarningsPresentInFile) {
254
+ hasEslintErrorsInChangedLines = false;
255
+ } else if (!shouldWarningsAbortCommit && !isOnlyEslintWarningsPresentInFile) {
256
+ hasEslintErrorsInChangedLines = true;
257
+ shouldAbortCommit = true;
258
+ }
259
+ }
260
+ } else {
261
+ if (eslintErrorsInFile.length > 0) {
262
+ let startIndex = 1;
263
+ let endIndex = eslintErrorsInFile.length - 2;
264
+ let listOsEslintErrors = eslintErrorsInFile.slice(startIndex, endIndex);
265
+ isOnlyEslintWarningsPresentInFile = isOnlyWarningsPresentInFile(listOsEslintErrors);
266
+ Logger.log(Logger.FAILURE_TYPE, `\x1b[1m${currentFileName}\x1b[0m`);
267
+ for (let eslintError of listOsEslintErrors) {
268
+ Logger.log(Logger.FAILURE_TYPE, `\x1b[37m${eslintError.trimEnd()}\x1b[0m`);
269
+ }
270
+ if (shouldWarningsAbortCommit) {
271
+ hasEslintErrorsInFiles = true;
272
+ shouldAbortCommit = true;
273
+ } else if (!shouldWarningsAbortCommit && isOnlyEslintWarningsPresentInFile) {
274
+ hasEslintErrorsInFiles = false;
275
+ } else if (!shouldWarningsAbortCommit && !isOnlyEslintWarningsPresentInFile) {
276
+ hasEslintErrorsInFiles = true;
277
+ shouldAbortCommit = true;
278
+ }
279
+ }
280
+ }
281
+ }
282
+ }
283
+ } catch (err) {
284
+ Logger.log(Logger.FAILURE_TYPE, err);
285
+ Logger.log(Logger.FAILURE_TYPE, "Error in executing eslint command");
286
+ }
287
+ }
288
+ }
289
+ } else if (staged_files.length === 0) {
290
+ Logger.log(Logger.INFO_TYPE, 'No files have been staged. Stage your files before committing');
291
+ }
292
+ } catch {
293
+ Logger.log(Logger.INFO_TYPE, 'Error executing pre commit hook');
294
+ }
295
+ if (shouldAbortCommit) {
296
+ Logger.log(Logger.FAILURE_TYPE, `There are eslint errors/warnings present. So commit is aborted.`);
297
+ process.exit(1);
298
+ } else if (shouldAbortCommit === false && staged_files.length !== 0) {
299
+ Logger.log(Logger.SUCCESS_TYPE, `Commit Successful`);
300
+ process.exit(0);
301
+ }
302
+ } else {
303
+ Logger.log(Logger.FAILURE_TYPE, 'Commit failed since some eslint plugins are not installed');
304
+ Logger.log(Logger.INFO_TYPE, `Kindly execute the command \x1b[37mnpx ZDPrecommit setupPlugins \x1b[33mfrom the location where package.json is present to install the plugins`);
305
+ Logger.log(Logger.INFO_TYPE, 'Execute the command and kindly try committing again.');
306
+ process.exit(1);
307
+ }
308
+ }
309
+ }
310
+ preCommitHook();
@@ -19,9 +19,6 @@ const {
19
19
  const {
20
20
  arePluginsInstalled
21
21
  } = require("../../utils/PluginsInstallation/arePluginsInstalled");
22
- const {
23
- default: prePushCheck
24
- } = require("../PrePush/pre-push");
25
22
  async function validateRemotePackages() {
26
23
  try {
27
24
  if (!(getStoredCommitHash() == getLastCommitHash())) {
@@ -36,5 +33,5 @@ async function validateRemotePackages() {
36
33
  }
37
34
  (async function () {
38
35
  await validateRemotePackages();
39
- await prePushCheck();
36
+ require('./lint');
40
37
  })();
@@ -16,14 +16,13 @@ const {
16
16
  function createVersionControlFile(uninstalledPlugins) {
17
17
  Logger.log(Logger.INFO_TYPE, `Rule Plugin Versions are Noted in pluginVersionControl.js`);
18
18
  const versionfilePath = path.join(getNodeModulesPath(), 'node_modules', '@zohodesk', 'codestandard-validator', 'pluginVersionControl.js');
19
- if (existsSync(versionfilePath)) {
20
- writeFileSync(versionfilePath, `module.exports.plugins = [${uninstalledPlugins.map(plugin => {
21
- return JSON.stringify({
22
- plugin: `${plugin}`,
23
- time: `${new Date()}`
24
- });
25
- }).join(',')}]`);
26
- }
19
+ existsSync(versionfilePath) && writeFileSync(versionfilePath, '');
20
+ writeFileSync(versionfilePath, `module.exports.plugins = [${uninstalledPlugins.map(plugin => {
21
+ return JSON.stringify({
22
+ plugin: `${plugin}`,
23
+ time: `${new Date()}`
24
+ });
25
+ }).join(',')}]`);
27
26
  }
28
27
  module.exports = {
29
28
  createVersionControlFile
@@ -21,33 +21,17 @@ const {
21
21
  */
22
22
  function configurePrecommitHook() {
23
23
  let rootDirectory = getRootDirectory();
24
- let customPrecomitHookPath = path.join(getLibraryInstalledLocation(), "bin", "precommit.js");
25
-
26
- // let customPrePushHookPath = path.join(
27
- // getLibraryInstalledLocation(),
28
- // "bin",
29
- // "push.js"
30
- // );
31
-
24
+ let customPrecomitHookPath = path.join(getLibraryInstalledLocation(), "bin", "execute.js");
32
25
  let huskyPrecommitPath = path.join(rootDirectory, ".husky", "pre-commit");
33
- // let huskyPrePushPath = path.join(rootDirectory,".husky","pre-push")
34
26
  let huskyPrecommitHookContent = `#!/bin/sh
35
27
  . "$(dirname "$0")/_/husky.sh"
36
28
 
37
29
  "${customPrecomitHookPath}"
38
30
  `;
39
-
40
- // let huskyPrePushHookContent = `#!/bin/sh
41
- // . "$(dirname "$0")/_/husky.sh"
42
-
43
- // "${customPrePushHookPath}"
44
- // `
45
31
  let isCustomPrecommitConfigurationSuccessful = executeSynchronizedCommands(writeFileSync, [huskyPrecommitPath, huskyPrecommitHookContent, 'utf-8'], '', 'Could not create and write pre-commit.sh inisde husky directory', false, true);
46
- // let isCustomPrePushConfigurationSuccessful = executeSynchronizedCommands(writeFileSync, [huskyPrePushPath, huskyPrePushHookContent, 'utf-8'], '', 'Could not create and write pre-push.sh inisde husky directory', false, true);
47
32
  if (isCustomPrecommitConfigurationSuccessful) {
48
- let isExecutionPermissionGivenSuccessfully_precommit = grantExecutionPermission([huskyPrecommitPath, customPrecomitHookPath]);
49
- // let isExecutionPermissionGivenSuccessfully_prepush = grantExecutionPermission([huskyPrePushPath, customPrePushHookPath]);
50
- return isExecutionPermissionGivenSuccessfully_precommit;
33
+ let isExecutionPermissionGivenSuccessfully = grantExecutionPermission([huskyPrecommitPath, customPrecomitHookPath]);
34
+ return isExecutionPermissionGivenSuccessfully;
51
35
  } else {
52
36
  return false;
53
37
  }
@@ -1,22 +1,15 @@
1
1
  "use strict";
2
2
 
3
3
  const {
4
- readdirSync,
5
4
  existsSync
6
5
  } = require('fs');
7
6
  const path = require('path');
8
- const {
9
- getNodeModulesPath
10
- } = require('../General/getNodeModulesPath');
11
7
  const {
12
8
  Logger
13
9
  } = require('../Logger/Logger');
14
10
  const {
15
11
  getLibraryInstalledLocation
16
12
  } = require('../General/getLibraryInstalledLocation');
17
- const {
18
- executeSynchronizedCommands
19
- } = require('../General/executeSyncCommands');
20
13
  const {
21
14
  endPoint,
22
15
  commonLinterRepoName
@@ -27,32 +20,6 @@ const {
27
20
  const {
28
21
  getServicePathElseCommon
29
22
  } = require('../EslintConfigFileUtils/getLintConfiguration');
30
- function getUnInstalledPlugins(pluginsForCurrentRepo, pluginNamesOfDevDependencyPlugins, devDependencies) {
31
- let pluginsInNodeModules = executeSynchronizedCommands(readdirSync, [path.join(getNodeModulesPath(), 'node_modules')], '', 'Unable to get the plugins inside node_modules', true, false);
32
- let pluginsToBeInstalled = [];
33
- pluginsForCurrentRepo.filter(plugin => {
34
- if (plugin.packageName.startsWith('@')) {
35
- let scope = plugin.packageName.split('/')[0];
36
- let pluginName = plugin.packageName.split('/')[1];
37
- let scopedPlugins = executeSynchronizedCommands(readdirSync, [path.join(getNodeModulesPath(), 'node_modules', scope)], '', 'Unable to get the plugins inside the scope inside node_modules', true, false);
38
- let isPluginInstalled = scopedPlugins.includes(pluginName) ? true : false;
39
- if (!isPluginInstalled) {
40
- pluginsToBeInstalled.push(`${plugin.packageName}@${plugin.version}`);
41
- }
42
- } else {
43
- let isPluginInstalled = pluginsInNodeModules.includes(plugin.packageName) ? true : false;
44
- if (!isPluginInstalled) {
45
- pluginsToBeInstalled.push(`${plugin.packageName}@${plugin.version}`);
46
- }
47
- }
48
- if (pluginNamesOfDevDependencyPlugins.includes(plugin.packageName)) {
49
- if (plugin.version !== devDependencies[plugin.packageName]) {
50
- pluginsToBeInstalled.push(`${plugin.packageName}@${plugin.version}`);
51
- }
52
- }
53
- });
54
- return pluginsToBeInstalled;
55
- }
56
23
  function getAllPlugins() {
57
24
  let serviceSpecificPlugins = [];
58
25
  const pathToCommonPluginsFile = path.join(getLibraryInstalledLocation(), commonLinterRepoName, 'common', 'pluginVersion.js');
@@ -79,29 +46,6 @@ function checkIfPluginsAreInstalled() {
79
46
  noPluginMessage: '',
80
47
  uninstalledPlugins: []
81
48
  };
82
- // let pluginsIndevDependencies = {}
83
- // let pluginNamesOfDevDependencyPlugins = []
84
- // let arePluginsPresentIndevDependencies = false
85
- // var arePluginsPresentForCurrentRepo = false
86
-
87
- // if(existsSync(path.join(getNodeModulesPath(),'package.json'))){
88
- // let packageJsonContent = require(path.join(getNodeModulesPath(),'package.json'))
89
- // pluginsIndevDependencies = packageJsonContent.devDependencies
90
-
91
- // if(pluginsIndevDependencies !== undefined){
92
- // arePluginsPresentIndevDependencies = true
93
- // pluginNamesOfDevDependencyPlugins = Object.keys(pluginsIndevDependencies)
94
- // }
95
- // else if(pluginsIndevDependencies === undefined){
96
- // Logger.log(Logger.INFO_TYPE,'No devDependencies present!')
97
- // }
98
- // }
99
- // else{
100
- // arePluginsPresentIndevDependencies = false
101
- // }
102
-
103
- // arePluginsPresentForCurrentRepo = pluginsForCurrentRepo.length !== 0 ? true : false
104
-
105
49
  uninstalledPlugins = pluginsForCurrentRepo.map(plugin => {
106
50
  const {
107
51
  packageName,
@@ -117,7 +61,6 @@ function checkIfPluginsAreInstalled() {
117
61
  return `${packageName}@${version}`;
118
62
  }).filter(Boolean);
119
63
  if (uninstalledPlugins.length > 0) {
120
- // uninstalledPlugins = getUnInstalledPlugins(pluginsForCurrentRepo, pluginNamesOfDevDependencyPlugins, pluginsIndevDependencies);
121
64
  plugin.noPluginMessage = '';
122
65
  plugin.uninstalledPlugins = uninstalledPlugins;
123
66
  return plugin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zohodesk/codestandard-validator",
3
- "version": "0.0.6-exp-6",
3
+ "version": "0.0.6-exp-8",
4
4
  "description": "library to enforce code standard using eslint",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/bin/push.js DELETED
@@ -1,4 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
-
4
- // require('../build/hooks/PrePush/pre-push')
File without changes