@contrast/contrast 1.0.2 → 1.0.5

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.
Files changed (113) hide show
  1. package/.prettierignore +4 -0
  2. package/README.md +24 -16
  3. package/dist/audit/autodetection/autoDetectLanguage.js +32 -0
  4. package/dist/audit/catalogueApplication/catalogueApplication.js +2 -11
  5. package/dist/audit/languageAnalysisEngine/{langugageAnalysisFactory.js → languageAnalysisFactory.js} +30 -13
  6. package/dist/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +25 -0
  7. package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +51 -237
  8. package/dist/audit/languageAnalysisEngine/report/models/reportLibraryModel.js +19 -0
  9. package/dist/audit/languageAnalysisEngine/report/models/reportListModel.js +24 -0
  10. package/dist/audit/languageAnalysisEngine/report/models/reportSeverityModel.js +10 -0
  11. package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +24 -129
  12. package/dist/audit/languageAnalysisEngine/report/utils/reportUtils.js +85 -0
  13. package/dist/audit/languageAnalysisEngine/sendSnapshot.js +2 -14
  14. package/dist/commands/audit/auditConfig.js +8 -2
  15. package/dist/commands/audit/auditController.js +14 -5
  16. package/dist/commands/audit/saveFile.js +11 -0
  17. package/dist/commands/auth/auth.js +19 -1
  18. package/dist/commands/config/config.js +19 -8
  19. package/dist/commands/scan/processScan.js +13 -27
  20. package/dist/commands/scan/sca/scaAnalysis.js +44 -0
  21. package/dist/common/HTTPClient.js +29 -26
  22. package/dist/common/errorHandling.js +15 -39
  23. package/dist/common/versionChecker.js +32 -0
  24. package/dist/constants/constants.js +16 -2
  25. package/dist/constants/lambda.js +3 -1
  26. package/dist/constants/locales.js +58 -48
  27. package/dist/constants.js +59 -3
  28. package/dist/index.js +48 -30
  29. package/dist/lambda/help.js +22 -14
  30. package/dist/lambda/lambda.js +6 -0
  31. package/dist/sbom/generateSbom.js +20 -0
  32. package/dist/scaAnalysis/common/formatMessage.js +11 -0
  33. package/dist/scaAnalysis/common/treeUpload.js +30 -0
  34. package/dist/scaAnalysis/java/analysis.js +116 -0
  35. package/dist/scaAnalysis/java/index.js +18 -0
  36. package/dist/scaAnalysis/java/javaBuildDepsParser.js +326 -0
  37. package/dist/scan/autoDetection.js +46 -1
  38. package/dist/scan/fileUtils.js +73 -1
  39. package/dist/scan/formatScanOutput.js +212 -0
  40. package/dist/scan/help.js +6 -2
  41. package/dist/scan/models/groupedResultsModel.js +11 -0
  42. package/dist/scan/models/resultContentModel.js +2 -0
  43. package/dist/scan/models/scanResultsModel.js +11 -0
  44. package/dist/scan/populateProjectIdAndProjectName.js +1 -0
  45. package/dist/scan/saveResults.js +9 -10
  46. package/dist/scan/scan.js +26 -101
  47. package/dist/scan/scanConfig.js +20 -1
  48. package/dist/scan/scanController.js +8 -4
  49. package/dist/scan/scanResults.js +8 -17
  50. package/dist/utils/getConfig.js +3 -0
  51. package/dist/utils/requestUtils.js +1 -1
  52. package/dist/utils/saveFile.js +19 -0
  53. package/package.json +3 -2
  54. package/src/audit/autodetection/autoDetectLanguage.ts +40 -0
  55. package/src/audit/catalogueApplication/catalogueApplication.js +4 -16
  56. package/src/audit/languageAnalysisEngine/{langugageAnalysisFactory.js → languageAnalysisFactory.js} +41 -19
  57. package/src/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +71 -0
  58. package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.ts +105 -0
  59. package/src/audit/languageAnalysisEngine/report/models/reportLibraryModel.ts +30 -0
  60. package/src/audit/languageAnalysisEngine/report/models/reportListModel.ts +32 -0
  61. package/src/audit/languageAnalysisEngine/report/models/reportSeverityModel.ts +9 -0
  62. package/src/audit/languageAnalysisEngine/report/reportingFeature.ts +56 -0
  63. package/src/audit/languageAnalysisEngine/report/utils/reportUtils.ts +110 -0
  64. package/src/audit/languageAnalysisEngine/sendSnapshot.js +2 -22
  65. package/src/commands/audit/auditConfig.ts +12 -3
  66. package/src/commands/audit/auditController.ts +21 -5
  67. package/src/commands/audit/processAudit.ts +3 -1
  68. package/src/commands/audit/saveFile.ts +6 -0
  69. package/src/commands/auth/auth.js +25 -1
  70. package/src/commands/config/config.js +22 -8
  71. package/src/commands/scan/processScan.js +15 -31
  72. package/src/commands/scan/sca/scaAnalysis.js +73 -0
  73. package/src/common/HTTPClient.js +42 -36
  74. package/src/common/errorHandling.ts +17 -48
  75. package/src/common/versionChecker.ts +41 -0
  76. package/src/constants/constants.js +17 -4
  77. package/src/constants/lambda.js +3 -1
  78. package/src/constants/locales.js +69 -63
  79. package/src/constants.js +66 -3
  80. package/src/index.ts +62 -36
  81. package/src/lambda/help.ts +22 -14
  82. package/src/lambda/lambda.ts +8 -0
  83. package/src/sbom/generateSbom.ts +17 -0
  84. package/src/scaAnalysis/common/formatMessage.js +10 -0
  85. package/src/scaAnalysis/common/treeUpload.js +34 -0
  86. package/src/scaAnalysis/java/analysis.js +159 -0
  87. package/src/scaAnalysis/java/index.js +21 -0
  88. package/src/scaAnalysis/java/javaBuildDepsParser.js +391 -0
  89. package/src/scan/autoDetection.js +54 -1
  90. package/src/scan/fileUtils.js +91 -1
  91. package/src/scan/formatScanOutput.ts +241 -0
  92. package/src/scan/help.js +6 -2
  93. package/src/scan/models/groupedResultsModel.ts +20 -0
  94. package/src/scan/models/resultContentModel.ts +86 -0
  95. package/src/scan/models/scanResultsModel.ts +52 -0
  96. package/src/scan/populateProjectIdAndProjectName.js +1 -0
  97. package/src/scan/saveResults.js +8 -9
  98. package/src/scan/scan.ts +62 -0
  99. package/src/scan/scanConfig.js +26 -1
  100. package/src/scan/scanController.js +12 -4
  101. package/src/scan/scanResults.js +19 -17
  102. package/src/utils/getConfig.ts +12 -0
  103. package/src/utils/requestUtils.js +1 -1
  104. package/src/utils/saveFile.js +19 -0
  105. package/dist/audit/languageAnalysisEngine/report/checkIgnoreDevDep.js +0 -17
  106. package/dist/audit/languageAnalysisEngine/report/newReportingFeature.js +0 -81
  107. package/dist/common/findLatestCLIVersion.js +0 -23
  108. package/src/audit/languageAnalysisEngine/report/checkIgnoreDevDep.js +0 -27
  109. package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.js +0 -303
  110. package/src/audit/languageAnalysisEngine/report/newReportingFeature.js +0 -124
  111. package/src/audit/languageAnalysisEngine/report/reportingFeature.js +0 -190
  112. package/src/common/findLatestCLIVersion.ts +0 -27
  113. package/src/scan/scan.js +0 -167
@@ -13,7 +13,15 @@ const lambdaUsageGuide = (0, command_line_usage_1.default)([
13
13
  },
14
14
  {
15
15
  header: i18n_1.default.__('constantsPrerequisitesHeader'),
16
- content: [i18n_1.default.__('lambdaPrerequisitesContent')]
16
+ content: [
17
+ '{bold ' +
18
+ i18n_1.default.__('lambdaPrerequisitesContentLambdaLanguages') +
19
+ '}\n\n' +
20
+ '{bold ' +
21
+ i18n_1.default.__('lambdaPrerequisitesContentLambdaDescriptionTitle') +
22
+ '}' +
23
+ i18n_1.default.__('lambdaPrerequisitesContentLambdaDescription')
24
+ ]
17
25
  },
18
26
  {
19
27
  header: i18n_1.default.__('constantsUsage'),
@@ -23,44 +31,44 @@ const lambdaUsageGuide = (0, command_line_usage_1.default)([
23
31
  header: i18n_1.default.__('constantsOptions'),
24
32
  content: [
25
33
  {
26
- name: i18n_1.default.__('lambdaFunctionNameOption'),
34
+ name: '{bold ' + i18n_1.default.__('lambdaFunctionNameOption') + '}',
27
35
  summary: i18n_1.default.__('lambdaFunctionNameSummery')
28
36
  },
29
37
  {
30
- name: i18n_1.default.__('lambdaListFunctionsOption'),
38
+ name: '{bold ' + i18n_1.default.__('lambdaListFunctionsOption') + '}',
31
39
  summary: i18n_1.default.__('lambdaListFunctionsSummery')
32
40
  },
33
41
  {
34
- name: i18n_1.default.__('lambdaEndpointOption'),
35
- summary: '{italic ' +
42
+ name: '{bold ' + i18n_1.default.__('lambdaEndpointOption') + '}',
43
+ summary: '{bold ' +
36
44
  i18n_1.default.__('constantsOptional') +
37
45
  '}: ' +
38
46
  i18n_1.default.__('lambdaEndpointSummery')
39
47
  },
40
48
  {
41
- name: i18n_1.default.__('lambdaRegionOption'),
42
- summary: '{italic ' +
49
+ name: '{bold ' + i18n_1.default.__('lambdaRegionOption') + '}',
50
+ summary: '{bold ' +
43
51
  i18n_1.default.__('constantsOptional') +
44
52
  '}: ' +
45
53
  i18n_1.default.__('lambdaRegionSummery')
46
54
  },
47
55
  {
48
- name: i18n_1.default.__('lambdaProfileOption'),
49
- summary: '{italic ' +
56
+ name: '{bold ' + i18n_1.default.__('lambdaProfileOption') + '}',
57
+ summary: '{bold ' +
50
58
  i18n_1.default.__('constantsOptional') +
51
59
  '}: ' +
52
60
  i18n_1.default.__('lambdaProfileSummery')
53
61
  },
54
62
  {
55
- name: i18n_1.default.__('lambdaJsonOption'),
56
- summary: '{italic ' +
63
+ name: '{bold ' + i18n_1.default.__('lambdaJsonOption') + '}',
64
+ summary: '{bold ' +
57
65
  i18n_1.default.__('constantsOptional') +
58
66
  '}: ' +
59
67
  i18n_1.default.__('lambdaJsonSummery')
60
68
  },
61
69
  {
62
- name: i18n_1.default.__('lambdaVerboseOption'),
63
- summary: '{italic ' +
70
+ name: '{bold ' + i18n_1.default.__('lambdaVerboseOption') + '}',
71
+ summary: '{bold ' +
64
72
  i18n_1.default.__('constantsOptional') +
65
73
  '}: ' +
66
74
  i18n_1.default.__('lambdaVerbosSummery')
@@ -73,7 +81,7 @@ const lambdaUsageGuide = (0, command_line_usage_1.default)([
73
81
  ]
74
82
  },
75
83
  {
76
- content: '{underline https://www.contrastsecurity.com}'
84
+ content: '{underline https://www.contrastsecurity.com/developer/codesec}'
77
85
  }
78
86
  ]);
79
87
  exports.lambdaUsageGuide = lambdaUsageGuide;
@@ -18,6 +18,8 @@ const scanRequest_1 = require("./scanRequest");
18
18
  const scanResults_1 = require("./scanResults");
19
19
  const utils_1 = require("./utils");
20
20
  const lambdaUtils_1 = require("./lambdaUtils");
21
+ const requestUtils_1 = require("../utils/requestUtils");
22
+ const oraWrapper_1 = __importDefault(require("../utils/oraWrapper"));
21
23
  const failedStates = [
22
24
  'UNSUPPORTED',
23
25
  'EXCLUDED',
@@ -101,6 +103,10 @@ const actualProcessLambda = async (lambdaOptions) => {
101
103
  description: failedScan.stateReasonText
102
104
  });
103
105
  }
106
+ const startGetherResultsSpinner = oraWrapper_1.default.returnOra(i18n_1.default.__('gatherResults'));
107
+ oraWrapper_1.default.startSpinner(startGetherResultsSpinner);
108
+ await (0, requestUtils_1.sleep)(15 * 1000);
109
+ oraWrapper_1.default.succeedSpinner(startGetherResultsSpinner, 'Done gathering results');
104
110
  const resultsResponse = await (0, scanResults_1.getScanResults)(auth, params, scanId, functionArn);
105
111
  if (jsonOutput) {
106
112
  console.log(JSON.stringify(resultsResponse?.data?.results, null, 2));
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const commonApi_1 = require("../utils/commonApi");
4
+ function generateSbom(config) {
5
+ const client = (0, commonApi_1.getHttpClient)(config);
6
+ return client
7
+ .getSbom(config)
8
+ .then((res) => {
9
+ if (res.statusCode === 200) {
10
+ return res.body;
11
+ }
12
+ else {
13
+ console.log('Unable to retrieve Software Bill of Materials (SBOM)');
14
+ }
15
+ })
16
+ .catch((err) => {
17
+ console.log(err);
18
+ });
19
+ }
20
+ exports.default = generateSbom;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ const createJavaTSMessage = javaTree => {
3
+ return {
4
+ java: {
5
+ mavenDependencyTrees: javaTree
6
+ }
7
+ };
8
+ };
9
+ module.exports = {
10
+ createJavaTSMessage
11
+ };
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ const { getHttpClient } = require('../../utils/commonApi');
3
+ const { handleResponseErrors } = require('../../common/errorHandling');
4
+ const { APP_VERSION } = require('../../constants/constants');
5
+ const commonSendSnapShot = async (analysis, config) => {
6
+ const requestBody = {
7
+ appID: config.applicationId,
8
+ cliVersion: APP_VERSION,
9
+ snapshot: analysis
10
+ };
11
+ const client = getHttpClient(config);
12
+ return client
13
+ .sendSnapshot(requestBody, config)
14
+ .then(res => {
15
+ if (res.statusCode === 201) {
16
+ console.log('snapshot processed successfully');
17
+ return res.body;
18
+ }
19
+ else {
20
+ console.log(res.statusCode);
21
+ handleResponseErrors(res, 'snapshot');
22
+ }
23
+ })
24
+ .catch(err => {
25
+ console.log(err);
26
+ });
27
+ };
28
+ module.exports = {
29
+ commonSendSnapShot
30
+ };
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ const child_process = require('child_process');
3
+ const path = require('path');
4
+ const i18n = require('i18n');
5
+ const fs = require('fs');
6
+ const MAVEN = 'maven';
7
+ const GRADLE = 'gradle';
8
+ const determineProjectTypeAndCwd = (files, projectPath) => {
9
+ const projectData = {};
10
+ if (files[0].includes('pom.xml')) {
11
+ projectData.projectType = MAVEN;
12
+ projectData.cwd = projectPath
13
+ ? projectPath
14
+ : files[0].replace('pom.xml', '');
15
+ }
16
+ else if (files[0].includes('build.gradle')) {
17
+ projectData.projectType = GRADLE;
18
+ projectData.cwd = projectPath
19
+ ? projectPath
20
+ : files[0].replace('pom.xml', '');
21
+ }
22
+ return projectData;
23
+ };
24
+ const buildMaven = async (config, projectData, timeout) => {
25
+ let cmdStdout;
26
+ let mvn_settings = '';
27
+ try {
28
+ if (config.mavenSettingsPath) {
29
+ mvn_settings = ' -s ' + config.mavenSettingsPath;
30
+ }
31
+ cmdStdout = child_process.execSync('mvn dependency:tree -B' + mvn_settings, {
32
+ cwd: projectData.cwd,
33
+ timeout
34
+ });
35
+ return cmdStdout.toString();
36
+ }
37
+ catch (err) {
38
+ try {
39
+ child_process.execSync('mvn --version', {
40
+ cwd: projectData.cwd,
41
+ timeout
42
+ });
43
+ throw new Error(i18n.__('mavenDependencyTreeNonZero', projectData.cwd, `${err.message}`));
44
+ }
45
+ catch (mvnErr) {
46
+ throw new Error(i18n.__('mavenNotInstalledError', projectData.cwd, `${mvnErr.message}`));
47
+ }
48
+ }
49
+ };
50
+ const buildGradle = (config, projectData, timeout) => {
51
+ let cmdStdout;
52
+ let output = {};
53
+ try {
54
+ if (config.subProject) {
55
+ cmdStdout = child_process.execSync('.' +
56
+ path.sep +
57
+ 'gradlew :' +
58
+ config.subProject +
59
+ ':dependencies --configuration runtimeClasspath', {
60
+ cwd: projectData.cwd,
61
+ timeout
62
+ });
63
+ }
64
+ else {
65
+ cmdStdout = child_process.execSync('.' +
66
+ path.sep +
67
+ 'gradlew dependencies --configuration runtimeClasspath', {
68
+ cwd: projectData.cwd,
69
+ timeout
70
+ });
71
+ }
72
+ if (cmdStdout
73
+ .toString()
74
+ .includes("runtimeClasspath - Runtime classpath of source set 'main'.\n" +
75
+ 'No dependencies')) {
76
+ cmdStdout = child_process.execSync('.' + path.sep + 'gradlew dependencies', {
77
+ cwd: projectData.cwd,
78
+ timeout
79
+ });
80
+ }
81
+ output.mvnDependancyTreeOutput = cmdStdout.toString();
82
+ return output;
83
+ }
84
+ catch (err) {
85
+ if (fs.existsSync(projectData.cwd + 'gradlew') ||
86
+ fs.existsSync(projectData.cwd + 'gradlew.bat')) {
87
+ throw new Error(i18n.__('gradleDependencyTreeNonZero', projectData.cwd, `${err.message}`));
88
+ }
89
+ else {
90
+ throw new Error(i18n.__('gradleWrapperUnavailable', projectData.cwd, `${err.message}`));
91
+ }
92
+ }
93
+ };
94
+ const getJavaBuildDeps = async (config, files) => {
95
+ const timeout = 960000;
96
+ let output = {
97
+ mvnDependancyTreeOutput: undefined,
98
+ projectType: undefined
99
+ };
100
+ try {
101
+ const projectData = determineProjectTypeAndCwd(files, config.projectPath);
102
+ if (projectData.projectType === MAVEN) {
103
+ output.mvnDependancyTreeOutput = await buildMaven(config, projectData, timeout);
104
+ }
105
+ else if (projectData.projectType === GRADLE) {
106
+ output.mvnDependancyTreeOutput = buildGradle(config, projectData, timeout);
107
+ }
108
+ output.projectType = projectData.projectType;
109
+ return output;
110
+ }
111
+ catch (err) {
112
+ }
113
+ };
114
+ module.exports = {
115
+ getJavaBuildDeps
116
+ };
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ const { getJavaBuildDeps } = require('./analysis');
3
+ const { parseBuildDeps } = require('./javaBuildDepsParser');
4
+ const { createJavaTSMessage } = require('../common/formatMessage');
5
+ const javaAnalysis = async (config, languageFiles) => {
6
+ languageFiles.java.forEach(file => {
7
+ file.replace('build.gradle.kts', 'build.gradle');
8
+ });
9
+ const javaDeps = await buildJavaTree(config, languageFiles.java);
10
+ return createJavaTSMessage(javaDeps);
11
+ };
12
+ const buildJavaTree = async (config, files) => {
13
+ const javaBuildDeps = await getJavaBuildDeps(config, files);
14
+ return parseBuildDeps(config, javaBuildDeps);
15
+ };
16
+ module.exports = {
17
+ javaAnalysis
18
+ };
@@ -0,0 +1,326 @@
1
+ "use strict";
2
+ const i18n = require('i18n');
3
+ const StringBuilder = require('string-builder');
4
+ let sb = new StringBuilder();
5
+ const parseBuildDeps = (config, input) => {
6
+ const { mvnDependancyTreeOutput, projectType } = input;
7
+ try {
8
+ return parseGradle(mvnDependancyTreeOutput, config, projectType);
9
+ }
10
+ catch (err) {
11
+ throw new Error(i18n.__('javaParseProjectFile') + `${err.message}`);
12
+ }
13
+ };
14
+ const preParser = shavedOutput => {
15
+ let obj = [];
16
+ for (let dep in shavedOutput) {
17
+ obj.push(shavedOutput[dep]
18
+ .replace('+-', '+---')
19
+ .replace('[INFO]', '')
20
+ .replace('\\-', '\\---')
21
+ .replace(':jar:', ':')
22
+ .replace(':test', '')
23
+ .replace(':compile', '')
24
+ .replace(' +', '+')
25
+ .replace(' |', '|')
26
+ .replace(' \\', '\\')
27
+ .replace(':runtime', ''));
28
+ }
29
+ let depTree = [];
30
+ for (let x in obj) {
31
+ let nodeLevel = computeRelationToLastElement(obj[x]);
32
+ let notLastLevel = obj[x].startsWith('|') ||
33
+ obj[x].startsWith('+') ||
34
+ obj[x].startsWith('\\');
35
+ if (notLastLevel) {
36
+ if (nodeLevel === 0) {
37
+ depTree.push(obj[x]);
38
+ }
39
+ else {
40
+ let level = computeLevel(nodeLevel);
41
+ let validatedLevel = addIndentation(nodeLevel === 2 ? 5 : level, obj[x]);
42
+ depTree.push(validatedLevel);
43
+ }
44
+ }
45
+ else {
46
+ let level = computeLevel(nodeLevel);
47
+ let validatedLevel = addIndentation(nodeLevel === 3 ? 5 : level, obj[x]);
48
+ depTree.push(validatedLevel);
49
+ }
50
+ }
51
+ return depTree;
52
+ };
53
+ const shaveOutput = (gradleDependencyTreeOutput, projectType) => {
54
+ let shavedOutput = gradleDependencyTreeOutput.split('\n');
55
+ if (projectType === 'maven') {
56
+ shavedOutput = preParser(shavedOutput);
57
+ }
58
+ let obj = [];
59
+ for (let key in shavedOutput) {
60
+ if (shavedOutput[key].includes('project :')) {
61
+ }
62
+ else if (shavedOutput[key].includes('+---') ||
63
+ shavedOutput[key].includes('\\---')) {
64
+ obj.push(shavedOutput[key]);
65
+ }
66
+ }
67
+ return obj;
68
+ };
69
+ const computeIndentation = element => {
70
+ let hasPlus = element.includes('+');
71
+ let hasSlash = element.includes('\\');
72
+ if (hasPlus) {
73
+ return element.substring(element.indexOf('+'));
74
+ }
75
+ if (hasSlash) {
76
+ return element.substring(element.indexOf('\\'));
77
+ }
78
+ };
79
+ const computeLevel = nodeLevel => {
80
+ let num = [5, 8, 11, 14, 17, 20];
81
+ for (let z in num) {
82
+ if (num[z] === nodeLevel) {
83
+ let n = parseInt(z);
84
+ return 5 * (n + 2);
85
+ }
86
+ }
87
+ };
88
+ const addIndentation = (number, str) => {
89
+ str = computeIndentation(str);
90
+ sb.clear();
91
+ for (let j = 0; j < number; j++) {
92
+ sb.append(' ');
93
+ }
94
+ sb.append(str);
95
+ return sb.toString();
96
+ };
97
+ const computeRelationToLastElement = element => {
98
+ let hasPlus = element.includes('+---');
99
+ let hasSlash = element.includes('\\---');
100
+ if (hasPlus) {
101
+ return element.split('+---')[0].length;
102
+ }
103
+ if (hasSlash) {
104
+ return element.split('\\---')[0].length;
105
+ }
106
+ };
107
+ const stripElement = element => {
108
+ return element
109
+ .replace(/[|]/g, '')
110
+ .replace('+---', '')
111
+ .replace('\\---', '')
112
+ .replace(/[' ']/g, '')
113
+ .replace('(c)', '')
114
+ .replace('->', '@')
115
+ .replace('(*)', '');
116
+ };
117
+ const checkVersion = element => {
118
+ let version = element.split(':');
119
+ return version[version.length - 1];
120
+ };
121
+ const createElement = (element, isRoot) => {
122
+ let tree;
123
+ let cleanElement = stripElement(element);
124
+ let splitGroupName = cleanElement.split(':');
125
+ let validateVersion = false;
126
+ if (!element.includes('->')) {
127
+ validateVersion = true;
128
+ }
129
+ tree = {
130
+ artifactID: splitGroupName[1],
131
+ group: splitGroupName[0],
132
+ version: validateVersion
133
+ ? checkVersion(cleanElement)
134
+ : splitGroupName[splitGroupName.length - 1],
135
+ scope: 'compile',
136
+ type: isRoot ? 'direct' : 'transitive',
137
+ edges: {}
138
+ };
139
+ return tree;
140
+ };
141
+ const getElementHeader = element => {
142
+ let elementHeader = stripElement(element);
143
+ elementHeader = elementHeader.replace(':', '/');
144
+ elementHeader = elementHeader.replace(':', '@');
145
+ return elementHeader;
146
+ };
147
+ const buildElement = (element, rootElement, parentOfCurrent, tree, isRoot) => {
148
+ let childElement = createElement(element, isRoot);
149
+ let elementHeader = getElementHeader(element);
150
+ let levelsArray = [rootElement, parentOfCurrent];
151
+ const treeNode = getNestedObject(tree, levelsArray);
152
+ const rootNode = getNestedObject(tree, [rootElement]);
153
+ if (!rootNode.hasOwnProperty(elementHeader)) {
154
+ tree[rootElement][elementHeader] = childElement;
155
+ }
156
+ treeNode.edges[elementHeader] = elementHeader;
157
+ };
158
+ const hasChildren = (nextNodeLevel, nodeLevel) => {
159
+ if (nextNodeLevel > nodeLevel) {
160
+ return true;
161
+ }
162
+ };
163
+ const lastChild = (nextNodeLevel, nodeLevel) => {
164
+ if (nextNodeLevel < nodeLevel) {
165
+ return true;
166
+ }
167
+ };
168
+ const calculateLevels = (nextNodeLevel, nodeLevel) => {
169
+ return (nodeLevel - nextNodeLevel) / 5;
170
+ };
171
+ const buildTree = shavedOutput => {
172
+ let tree = {};
173
+ let rootElement;
174
+ let levelNodes = [];
175
+ shavedOutput.forEach((element, index) => {
176
+ if (index === 0) {
177
+ let cleanElement = stripElement(element);
178
+ let elementHeader = getElementHeader(cleanElement);
179
+ let splitElement = element.split(' ');
180
+ let splitGroupName = splitElement[1].split(':');
181
+ let validateVersion = false;
182
+ if (!element.includes('->')) {
183
+ validateVersion = true;
184
+ }
185
+ tree[splitGroupName[0]] = {};
186
+ tree[splitGroupName[0]][elementHeader] = {
187
+ artifactID: splitGroupName[1],
188
+ group: splitGroupName[0],
189
+ version: validateVersion
190
+ ? checkVersion(cleanElement)
191
+ : splitElement[splitElement.length - 1],
192
+ scope: 'compile',
193
+ type: 'direct',
194
+ edges: {}
195
+ };
196
+ rootElement = splitGroupName[0];
197
+ levelNodes.push(elementHeader);
198
+ }
199
+ if (shavedOutput.length - 1 === index) {
200
+ const parentOfCurrent = levelNodes[levelNodes.length - 1];
201
+ let nodeLevel = computeRelationToLastElement(element);
202
+ let validateVersion = false;
203
+ if (!element.includes('->')) {
204
+ validateVersion = true;
205
+ }
206
+ if (nodeLevel === 0) {
207
+ let cleanElement = stripElement(element);
208
+ let elementHeader = getElementHeader(cleanElement);
209
+ let splitElement = element.split(' ');
210
+ let splitGroupName = splitElement[1].split(':');
211
+ tree[rootElement][elementHeader] = {
212
+ artifactID: splitGroupName[1],
213
+ group: splitGroupName[0],
214
+ version: validateVersion
215
+ ? checkVersion(cleanElement)
216
+ : splitElement[splitElement.length - 1],
217
+ scope: 'compile',
218
+ type: 'direct',
219
+ edges: {}
220
+ };
221
+ }
222
+ else {
223
+ buildElement(element, rootElement, parentOfCurrent, tree);
224
+ }
225
+ }
226
+ if (index >= 1 && index < shavedOutput.length - 1) {
227
+ let nodeLevel = computeRelationToLastElement(element);
228
+ let nextNodeLevel = computeRelationToLastElement(shavedOutput[index + 1]);
229
+ const parentOfCurrent = levelNodes[levelNodes.length - 1];
230
+ let isRoot = false;
231
+ if (nodeLevel === 0) {
232
+ isRoot = true;
233
+ }
234
+ if (isRoot) {
235
+ let cleanElement = stripElement(element);
236
+ let elementHeader = getElementHeader(cleanElement);
237
+ let splitElement = element.split(' ');
238
+ let splitGroupName = splitElement[1].split(':');
239
+ let validateVersion = false;
240
+ if (!element.includes('->')) {
241
+ validateVersion = true;
242
+ }
243
+ tree[rootElement][elementHeader] = {
244
+ artifactID: splitGroupName[1],
245
+ group: splitGroupName[0],
246
+ version: validateVersion
247
+ ? checkVersion(cleanElement)
248
+ : splitElement[splitElement.length - 1],
249
+ scope: 'compile',
250
+ type: 'direct',
251
+ edges: {}
252
+ };
253
+ levelNodes.push(elementHeader);
254
+ return;
255
+ }
256
+ let elementHeader = getElementHeader(element);
257
+ buildElement(element, rootElement, parentOfCurrent, tree, isRoot);
258
+ if (hasChildren(nextNodeLevel, nodeLevel)) {
259
+ buildElement(element, rootElement, parentOfCurrent, tree, isRoot);
260
+ levelNodes.push(elementHeader);
261
+ }
262
+ if (lastChild(nextNodeLevel, nodeLevel)) {
263
+ let levelDifference = calculateLevels(nextNodeLevel, nodeLevel);
264
+ if (levelDifference === 0) {
265
+ levelNodes.pop();
266
+ }
267
+ else {
268
+ let i;
269
+ for (i = 0; i < levelDifference; i++) {
270
+ levelNodes.pop();
271
+ }
272
+ }
273
+ }
274
+ }
275
+ });
276
+ return tree;
277
+ };
278
+ const getNestedObject = (nestedObj, pathArr) => {
279
+ return pathArr.reduce((obj, key) => (obj && obj[key] !== 'undefined' ? obj[key] : undefined), nestedObj);
280
+ };
281
+ const parseSubProject = shavedOutput => {
282
+ let obj = [];
283
+ for (let key in shavedOutput) {
284
+ if (!shavedOutput[key].includes('project')) {
285
+ obj.push(shavedOutput[key]);
286
+ }
287
+ }
288
+ return obj;
289
+ };
290
+ const validateIndentation = shavedOutput => {
291
+ let validatedTree = [];
292
+ shavedOutput.forEach((element, index) => {
293
+ let nextNodeLevel;
294
+ let nodeLevel = computeRelationToLastElement(element);
295
+ if (shavedOutput[index + 1] !== undefined) {
296
+ nextNodeLevel = computeRelationToLastElement(shavedOutput[index + 1]);
297
+ }
298
+ if (index === 0) {
299
+ validatedTree.push(shavedOutput[index]);
300
+ validatedTree.push(shavedOutput[index + 1]);
301
+ }
302
+ else if (nextNodeLevel > nodeLevel + 5) {
303
+ return;
304
+ }
305
+ else {
306
+ validatedTree.push(shavedOutput[index + 1]);
307
+ }
308
+ });
309
+ validatedTree.pop();
310
+ return validatedTree;
311
+ };
312
+ const parseGradle = (gradleDependencyTreeOutput, config, projectType) => {
313
+ let shavedOutput = shaveOutput(gradleDependencyTreeOutput, projectType);
314
+ if (config.subProject) {
315
+ let subProject = parseSubProject(shavedOutput);
316
+ let validatedOutput = validateIndentation(subProject);
317
+ return buildTree(validatedOutput);
318
+ }
319
+ else {
320
+ let validatedOutput = validateIndentation(shavedOutput);
321
+ return buildTree(validatedOutput);
322
+ }
323
+ };
324
+ module.exports = {
325
+ parseBuildDeps
326
+ };