@contrast/contrast 1.0.6 → 1.0.9
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.
- package/.prettierignore +0 -6
- package/dist/audit/catalogueApplication/catalogueApplication.js +23 -5
- package/dist/audit/languageAnalysisEngine/getProjectRootFilenames.js +10 -19
- package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +98 -37
- package/dist/audit/languageAnalysisEngine/report/models/reportListModel.js +2 -1
- package/dist/audit/languageAnalysisEngine/report/models/reportOutputModel.js +4 -3
- package/dist/audit/languageAnalysisEngine/report/models/severityCountModel.js +3 -0
- package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +87 -19
- package/dist/audit/languageAnalysisEngine/report/utils/reportUtils.js +46 -16
- package/dist/audit/languageAnalysisEngine/sendSnapshot.js +57 -19
- package/dist/audit/save.js +37 -0
- package/dist/commands/audit/auditConfig.js +0 -16
- package/dist/commands/audit/auditController.js +18 -11
- package/dist/commands/audit/help.js +31 -25
- package/dist/commands/audit/processAudit.js +3 -3
- package/dist/commands/audit/saveFile.js +8 -4
- package/dist/commands/scan/sca/scaAnalysis.js +55 -10
- package/dist/common/HTTPClient.js +64 -23
- package/dist/common/errorHandling.js +6 -1
- package/dist/common/versionChecker.js +20 -5
- package/dist/constants/constants.js +7 -2
- package/dist/constants/locales.js +35 -38
- package/dist/constants.js +20 -13
- package/dist/index.js +55 -45
- package/dist/lambda/analytics.js +11 -0
- package/dist/lambda/lambda.js +38 -4
- package/dist/lambda/types.js +13 -0
- package/dist/sbom/generateSbom.js +5 -4
- package/dist/scaAnalysis/common/formatMessage.js +44 -1
- package/dist/scaAnalysis/common/treeUpload.js +4 -6
- package/dist/scaAnalysis/dotnet/analysis.js +43 -0
- package/dist/scaAnalysis/dotnet/index.js +10 -0
- package/dist/scaAnalysis/go/goReadDepFile.js +1 -3
- package/dist/scaAnalysis/java/analysis.js +5 -8
- package/dist/scaAnalysis/java/index.js +2 -2
- package/dist/scaAnalysis/javascript/analysis.js +107 -0
- package/dist/scaAnalysis/javascript/index.js +50 -0
- package/dist/scaAnalysis/php/analysis.js +70 -0
- package/dist/scaAnalysis/php/index.js +17 -0
- package/dist/scaAnalysis/python/analysis.js +42 -0
- package/dist/scaAnalysis/python/index.js +10 -0
- package/dist/scaAnalysis/ruby/analysis.js +218 -0
- package/dist/scaAnalysis/ruby/index.js +10 -0
- package/dist/scan/autoDetection.js +23 -22
- package/dist/scan/fileUtils.js +57 -20
- package/dist/scan/formatScanOutput.js +12 -14
- package/dist/scan/models/groupedResultsModel.js +1 -1
- package/dist/scan/models/scanResultsModel.js +3 -1
- package/dist/scan/populateProjectIdAndProjectName.js +2 -1
- package/dist/scan/scan.js +1 -0
- package/dist/scan/scanConfig.js +8 -3
- package/dist/scan/scanController.js +16 -3
- package/dist/scan/scanResults.js +5 -1
- package/dist/utils/commonApi.js +4 -1
- package/dist/utils/filterProjectPath.js +7 -2
- package/dist/utils/getConfig.js +1 -6
- package/package.json +12 -9
- package/src/audit/catalogueApplication/catalogueApplication.js +28 -7
- package/src/audit/languageAnalysisEngine/getProjectRootFilenames.js +10 -39
- package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.ts +183 -68
- package/src/audit/languageAnalysisEngine/report/models/reportLibraryModel.ts +3 -3
- package/src/audit/languageAnalysisEngine/report/models/reportListModel.ts +18 -11
- package/src/audit/languageAnalysisEngine/report/models/reportOutputModel.ts +11 -5
- package/src/audit/languageAnalysisEngine/report/models/reportSeverityModel.ts +6 -1
- package/src/audit/languageAnalysisEngine/report/models/severityCountModel.ts +4 -0
- package/src/audit/languageAnalysisEngine/report/reportingFeature.ts +86 -32
- package/src/audit/languageAnalysisEngine/report/utils/reportUtils.ts +87 -32
- package/src/audit/languageAnalysisEngine/sendSnapshot.js +69 -20
- package/src/audit/save.js +48 -0
- package/src/commands/audit/auditConfig.ts +0 -25
- package/src/commands/audit/auditController.ts +18 -20
- package/src/commands/audit/help.ts +31 -25
- package/src/commands/audit/processAudit.ts +3 -6
- package/src/commands/audit/saveFile.ts +6 -2
- package/src/commands/scan/processScan.js +0 -1
- package/src/commands/scan/sca/scaAnalysis.js +84 -30
- package/src/common/HTTPClient.js +81 -34
- package/src/common/errorHandling.ts +10 -1
- package/src/common/versionChecker.ts +24 -5
- package/src/constants/constants.js +9 -3
- package/src/constants/locales.js +58 -43
- package/src/constants.js +21 -14
- package/src/index.ts +70 -58
- package/src/lambda/analytics.ts +9 -0
- package/src/lambda/arn.ts +2 -1
- package/src/lambda/lambda.ts +40 -17
- package/src/lambda/types.ts +36 -0
- package/src/lambda/utils.ts +2 -7
- package/src/sbom/generateSbom.ts +2 -2
- package/src/scaAnalysis/common/formatMessage.js +48 -1
- package/src/scaAnalysis/common/treeUpload.js +4 -6
- package/src/scaAnalysis/dotnet/analysis.js +54 -0
- package/src/scaAnalysis/dotnet/index.js +11 -0
- package/src/scaAnalysis/go/goAnalysis.js +2 -3
- package/src/scaAnalysis/go/goReadDepFile.js +1 -3
- package/src/scaAnalysis/java/analysis.js +7 -8
- package/src/scaAnalysis/java/index.js +2 -2
- package/src/scaAnalysis/javascript/analysis.js +126 -0
- package/src/scaAnalysis/javascript/index.js +72 -0
- package/src/scaAnalysis/php/analysis.js +78 -0
- package/src/scaAnalysis/php/index.js +22 -0
- package/src/scaAnalysis/python/analysis.js +49 -0
- package/src/scaAnalysis/python/index.js +11 -0
- package/src/scaAnalysis/ruby/analysis.js +273 -0
- package/src/scaAnalysis/ruby/index.js +11 -0
- package/src/scan/autoDetection.js +24 -26
- package/src/scan/fileUtils.js +60 -20
- package/src/scan/formatScanOutput.ts +14 -15
- package/src/scan/models/groupedResultsModel.ts +3 -3
- package/src/scan/models/resultContentModel.ts +1 -1
- package/src/scan/models/scanResultsModel.ts +5 -2
- package/src/scan/populateProjectIdAndProjectName.js +3 -1
- package/src/scan/scan.ts +1 -0
- package/src/scan/scanConfig.js +7 -5
- package/src/scan/scanController.js +18 -4
- package/src/scan/scanResults.js +10 -0
- package/src/utils/commonApi.js +4 -1
- package/src/utils/filterProjectPath.js +6 -2
- package/src/utils/getConfig.ts +1 -12
- package/dist/audit/AnalysisEngine.js +0 -37
- package/dist/audit/autodetection/autoDetectLanguage.js +0 -32
- package/dist/audit/dotnetAnalysisEngine/index.js +0 -25
- package/dist/audit/dotnetAnalysisEngine/parseLockFileContents.js +0 -35
- package/dist/audit/dotnetAnalysisEngine/parseProjectFileContents.js +0 -15
- package/dist/audit/dotnetAnalysisEngine/readLockFileContents.js +0 -18
- package/dist/audit/dotnetAnalysisEngine/readProjectFileContents.js +0 -14
- package/dist/audit/dotnetAnalysisEngine/sanitizer.js +0 -9
- package/dist/audit/goAnalysisEngine/index.js +0 -17
- package/dist/audit/goAnalysisEngine/parseProjectFileContents.js +0 -164
- package/dist/audit/goAnalysisEngine/readProjectFileContents.js +0 -21
- package/dist/audit/goAnalysisEngine/sanitizer.js +0 -5
- package/dist/audit/javaAnalysisEngine/index.js +0 -34
- package/dist/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +0 -153
- package/dist/audit/javaAnalysisEngine/parseProjectFileContents.js +0 -353
- package/dist/audit/javaAnalysisEngine/readProjectFileContents.js +0 -98
- package/dist/audit/javaAnalysisEngine/sanitizer.js +0 -5
- package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +0 -24
- package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +0 -24
- package/dist/audit/languageAnalysisEngine/checkIdentifiedLanguageHasLockFile.js +0 -35
- package/dist/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +0 -23
- package/dist/audit/languageAnalysisEngine/constants.js +0 -20
- package/dist/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +0 -25
- package/dist/audit/languageAnalysisEngine/index.js +0 -39
- package/dist/audit/languageAnalysisEngine/languageAnalysisFactory.js +0 -87
- package/dist/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +0 -150
- package/dist/audit/nodeAnalysisEngine/handleNPMLockFileV2.js +0 -40
- package/dist/audit/nodeAnalysisEngine/index.js +0 -31
- package/dist/audit/nodeAnalysisEngine/parseNPMLockFileContents.js +0 -18
- package/dist/audit/nodeAnalysisEngine/parseYarnLockFileContents.js +0 -18
- package/dist/audit/nodeAnalysisEngine/readNPMLockFileContents.js +0 -17
- package/dist/audit/nodeAnalysisEngine/readProjectFileContents.js +0 -14
- package/dist/audit/nodeAnalysisEngine/readYarnLockFileContents.js +0 -24
- package/dist/audit/nodeAnalysisEngine/sanitizer.js +0 -9
- package/dist/audit/phpAnalysisEngine/index.js +0 -23
- package/dist/audit/phpAnalysisEngine/parseLockFileContents.js +0 -52
- package/dist/audit/phpAnalysisEngine/readLockFileContents.js +0 -13
- package/dist/audit/phpAnalysisEngine/readProjectFileContents.js +0 -16
- package/dist/audit/phpAnalysisEngine/sanitizer.js +0 -5
- package/dist/audit/pythonAnalysisEngine/index.js +0 -25
- package/dist/audit/pythonAnalysisEngine/parsePipfileLockContents.js +0 -17
- package/dist/audit/pythonAnalysisEngine/parseProjectFileContents.js +0 -21
- package/dist/audit/pythonAnalysisEngine/readPipfileLockFileContents.js +0 -13
- package/dist/audit/pythonAnalysisEngine/readPythonProjectFileContents.js +0 -14
- package/dist/audit/pythonAnalysisEngine/sanitizer.js +0 -7
- package/dist/audit/rubyAnalysisEngine/index.js +0 -25
- package/dist/audit/rubyAnalysisEngine/parseGemfileLockContents.js +0 -176
- package/dist/audit/rubyAnalysisEngine/parsedGemfile.js +0 -22
- package/dist/audit/rubyAnalysisEngine/readGemfileContents.js +0 -14
- package/dist/audit/rubyAnalysisEngine/readGemfileLockContents.js +0 -14
- package/dist/audit/rubyAnalysisEngine/sanitizer.js +0 -6
- package/src/audit/AnalysisEngine.js +0 -103
- package/src/audit/autodetection/autoDetectLanguage.ts +0 -40
- package/src/audit/dotnetAnalysisEngine/index.js +0 -26
- package/src/audit/dotnetAnalysisEngine/parseLockFileContents.js +0 -47
- package/src/audit/dotnetAnalysisEngine/parseProjectFileContents.js +0 -29
- package/src/audit/dotnetAnalysisEngine/readLockFileContents.js +0 -30
- package/src/audit/dotnetAnalysisEngine/readProjectFileContents.js +0 -26
- package/src/audit/dotnetAnalysisEngine/sanitizer.js +0 -11
- package/src/audit/goAnalysisEngine/index.js +0 -18
- package/src/audit/goAnalysisEngine/parseProjectFileContents.js +0 -209
- package/src/audit/goAnalysisEngine/readProjectFileContents.js +0 -31
- package/src/audit/goAnalysisEngine/sanitizer.js +0 -7
- package/src/audit/javaAnalysisEngine/index.js +0 -41
- package/src/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +0 -222
- package/src/audit/javaAnalysisEngine/parseProjectFileContents.js +0 -420
- package/src/audit/javaAnalysisEngine/readProjectFileContents.js +0 -141
- package/src/audit/javaAnalysisEngine/sanitizer.js +0 -6
- package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +0 -35
- package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +0 -41
- package/src/audit/languageAnalysisEngine/checkIdentifiedLanguageHasLockFile.js +0 -54
- package/src/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +0 -32
- package/src/audit/languageAnalysisEngine/constants.js +0 -23
- package/src/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +0 -41
- package/src/audit/languageAnalysisEngine/index.js +0 -45
- package/src/audit/languageAnalysisEngine/languageAnalysisFactory.js +0 -116
- package/src/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +0 -249
- package/src/audit/nodeAnalysisEngine/handleNPMLockFileV2.js +0 -49
- package/src/audit/nodeAnalysisEngine/index.js +0 -35
- package/src/audit/nodeAnalysisEngine/parseNPMLockFileContents.js +0 -20
- package/src/audit/nodeAnalysisEngine/parseYarnLockFileContents.js +0 -26
- package/src/audit/nodeAnalysisEngine/readNPMLockFileContents.js +0 -23
- package/src/audit/nodeAnalysisEngine/readProjectFileContents.js +0 -27
- package/src/audit/nodeAnalysisEngine/readYarnLockFileContents.js +0 -36
- package/src/audit/nodeAnalysisEngine/sanitizer.js +0 -11
- package/src/audit/phpAnalysisEngine/index.js +0 -27
- package/src/audit/phpAnalysisEngine/parseLockFileContents.js +0 -60
- package/src/audit/phpAnalysisEngine/readLockFileContents.js +0 -14
- package/src/audit/phpAnalysisEngine/readProjectFileContents.js +0 -25
- package/src/audit/phpAnalysisEngine/sanitizer.js +0 -4
- package/src/audit/pythonAnalysisEngine/index.js +0 -55
- package/src/audit/pythonAnalysisEngine/parsePipfileLockContents.js +0 -23
- package/src/audit/pythonAnalysisEngine/parseProjectFileContents.js +0 -33
- package/src/audit/pythonAnalysisEngine/readPipfileLockFileContents.js +0 -16
- package/src/audit/pythonAnalysisEngine/readPythonProjectFileContents.js +0 -22
- package/src/audit/pythonAnalysisEngine/sanitizer.js +0 -9
- package/src/audit/rubyAnalysisEngine/index.js +0 -30
- package/src/audit/rubyAnalysisEngine/parseGemfileLockContents.js +0 -215
- package/src/audit/rubyAnalysisEngine/parsedGemfile.js +0 -39
- package/src/audit/rubyAnalysisEngine/readGemfileContents.js +0 -18
- package/src/audit/rubyAnalysisEngine/readGemfileLockContents.js +0 -17
- package/src/audit/rubyAnalysisEngine/sanitizer.js +0 -8
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
const i18n = require('i18n')
|
|
2
2
|
const fileFinder = require('./fileUtils')
|
|
3
|
-
const languageResolver = require('../audit/languageAnalysisEngine/reduceIdentifiedLanguages')
|
|
4
3
|
const rootFile = require('../audit/languageAnalysisEngine/getProjectRootFilenames')
|
|
5
4
|
|
|
6
5
|
const autoDetectFileAndLanguage = async configToUse => {
|
|
@@ -14,6 +13,11 @@ const autoDetectFileAndLanguage = async configToUse => {
|
|
|
14
13
|
process.exit(1)
|
|
15
14
|
}
|
|
16
15
|
|
|
16
|
+
if (fileFinder.fileIsEmpty(entries[0])) {
|
|
17
|
+
console.log(i18n.__('scanFileIsEmpty'))
|
|
18
|
+
process.exit(1)
|
|
19
|
+
}
|
|
20
|
+
|
|
17
21
|
configToUse.file = entries[0]
|
|
18
22
|
if (configToUse.name === undefined) {
|
|
19
23
|
configToUse.name = entries[0]
|
|
@@ -23,39 +27,34 @@ const autoDetectFileAndLanguage = async configToUse => {
|
|
|
23
27
|
}
|
|
24
28
|
}
|
|
25
29
|
|
|
26
|
-
const autoDetectAuditFilesAndLanguages = async
|
|
30
|
+
const autoDetectAuditFilesAndLanguages = async file => {
|
|
31
|
+
const filePath = file
|
|
27
32
|
let languagesFound = []
|
|
28
|
-
console.log(i18n.__('searchingAuditFileDirectory', process.cwd()))
|
|
29
33
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
if (filePath) {
|
|
35
|
+
rootFile.getProjectRootFilenames(filePath)
|
|
36
|
+
console.log(i18n.__('searchingAuditFileDirectory', filePath))
|
|
37
|
+
} else {
|
|
38
|
+
console.log(i18n.__('searchingAuditFileDirectory', process.cwd()))
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
await fileFinder.findFilesJava(languagesFound, filePath)
|
|
42
|
+
await fileFinder.findFilesJavascript(languagesFound, filePath)
|
|
43
|
+
await fileFinder.findFilesPython(languagesFound, filePath)
|
|
44
|
+
await fileFinder.findFilesGo(languagesFound, filePath)
|
|
45
|
+
await fileFinder.findFilesPhp(languagesFound, filePath)
|
|
46
|
+
await fileFinder.findFilesRuby(languagesFound, filePath)
|
|
47
|
+
await fileFinder.findFilesDotNet(languagesFound, filePath)
|
|
36
48
|
|
|
37
|
-
if (languagesFound.length
|
|
49
|
+
if (languagesFound.length <= 1) {
|
|
38
50
|
return languagesFound
|
|
39
51
|
} else {
|
|
40
52
|
console.log(
|
|
41
|
-
'found multiple languages, please specify one using --file to run SCA
|
|
53
|
+
'found multiple languages, please specify one using --file to run SCA audit'
|
|
42
54
|
)
|
|
43
55
|
}
|
|
44
56
|
}
|
|
45
57
|
|
|
46
|
-
const manualDetectAuditFilesAndLanguages = async projectPath => {
|
|
47
|
-
let projectRootFilenames = await rootFile.getProjectRootFilenames(projectPath)
|
|
48
|
-
let identifiedLanguages = languageResolver.deduceLanguageScaAnalysis(
|
|
49
|
-
projectRootFilenames
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
if (Object.keys(identifiedLanguages).length === 0) {
|
|
53
|
-
console.log(i18n.__('languageAnalysisNoLanguage', projectPath))
|
|
54
|
-
return []
|
|
55
|
-
}
|
|
56
|
-
return [identifiedLanguages]
|
|
57
|
-
}
|
|
58
|
-
|
|
59
58
|
const hasWhiteSpace = s => {
|
|
60
59
|
const filename = s.split('/').pop()
|
|
61
60
|
return filename.indexOf(' ') >= 0
|
|
@@ -96,6 +95,5 @@ module.exports = {
|
|
|
96
95
|
autoDetectFileAndLanguage,
|
|
97
96
|
errorOnFileDetection,
|
|
98
97
|
autoDetectAuditFilesAndLanguages,
|
|
99
|
-
errorOnAuditFileDetection
|
|
100
|
-
manualDetectAuditFilesAndLanguages
|
|
98
|
+
errorOnAuditFileDetection
|
|
101
99
|
}
|
package/src/scan/fileUtils.js
CHANGED
|
@@ -11,86 +11,106 @@ const findFile = async () => {
|
|
|
11
11
|
})
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
const findFilesJava = async languagesFound => {
|
|
14
|
+
const findFilesJava = async (languagesFound, filePath) => {
|
|
15
15
|
const result = await fg(
|
|
16
16
|
['**/pom.xml', '**/build.gradle', '**/build.gradle.kts'],
|
|
17
17
|
{
|
|
18
18
|
dot: false,
|
|
19
19
|
deep: 1,
|
|
20
|
-
onlyFiles: true
|
|
20
|
+
onlyFiles: true,
|
|
21
|
+
cwd: filePath ? filePath : process.cwd()
|
|
21
22
|
}
|
|
22
23
|
)
|
|
23
24
|
|
|
24
25
|
if (result.length > 0) {
|
|
25
|
-
return languagesFound.push({
|
|
26
|
+
return languagesFound.push({ JAVA: result })
|
|
26
27
|
}
|
|
27
28
|
return languagesFound
|
|
28
29
|
}
|
|
29
30
|
|
|
30
|
-
const findFilesJavascript = async languagesFound => {
|
|
31
|
+
const findFilesJavascript = async (languagesFound, filePath) => {
|
|
31
32
|
const result = await fg(
|
|
32
|
-
['**/package.json', '**/yarn.lock', '**/package
|
|
33
|
+
['**/package.json', '**/yarn.lock', '**/package-lock.json'],
|
|
33
34
|
{
|
|
34
35
|
dot: false,
|
|
35
36
|
deep: 1,
|
|
36
|
-
onlyFiles: true
|
|
37
|
+
onlyFiles: true,
|
|
38
|
+
cwd: filePath ? filePath : process.cwd()
|
|
37
39
|
}
|
|
38
40
|
)
|
|
39
41
|
|
|
40
42
|
if (result.length > 0) {
|
|
41
|
-
return languagesFound.push({
|
|
43
|
+
return languagesFound.push({ JAVASCRIPT: result })
|
|
42
44
|
}
|
|
43
45
|
return languagesFound
|
|
44
46
|
}
|
|
45
47
|
|
|
46
|
-
const findFilesPython = async languagesFound => {
|
|
48
|
+
const findFilesPython = async (languagesFound, filePath) => {
|
|
47
49
|
const result = await fg(['**/Pipfile.lock', '**/Pipfile'], {
|
|
48
50
|
dot: false,
|
|
49
51
|
deep: 3,
|
|
50
|
-
onlyFiles: true
|
|
52
|
+
onlyFiles: true,
|
|
53
|
+
cwd: filePath ? filePath : process.cwd()
|
|
51
54
|
})
|
|
52
55
|
|
|
53
56
|
if (result.length > 0) {
|
|
54
|
-
return languagesFound.push({
|
|
57
|
+
return languagesFound.push({ PYTHON: result })
|
|
55
58
|
}
|
|
56
59
|
return languagesFound
|
|
57
60
|
}
|
|
58
61
|
|
|
59
|
-
const findFilesGo = async languagesFound => {
|
|
62
|
+
const findFilesGo = async (languagesFound, filePath) => {
|
|
60
63
|
const result = await fg(['**/go.mod'], {
|
|
61
64
|
dot: false,
|
|
62
65
|
deep: 3,
|
|
63
|
-
onlyFiles: true
|
|
66
|
+
onlyFiles: true,
|
|
67
|
+
cwd: filePath ? filePath : process.cwd()
|
|
64
68
|
})
|
|
65
69
|
|
|
66
70
|
if (result.length > 0) {
|
|
67
|
-
return languagesFound.push({
|
|
71
|
+
return languagesFound.push({ GO: result })
|
|
68
72
|
}
|
|
69
73
|
return languagesFound
|
|
70
74
|
}
|
|
71
75
|
|
|
72
|
-
const findFilesRuby = async languagesFound => {
|
|
76
|
+
const findFilesRuby = async (languagesFound, filePath) => {
|
|
73
77
|
const result = await fg(['**/Gemfile', '**/Gemfile.lock'], {
|
|
74
78
|
dot: false,
|
|
75
79
|
deep: 3,
|
|
76
|
-
onlyFiles: true
|
|
80
|
+
onlyFiles: true,
|
|
81
|
+
cwd: filePath ? filePath : process.cwd()
|
|
77
82
|
})
|
|
78
83
|
|
|
79
84
|
if (result.length > 0) {
|
|
80
|
-
return languagesFound.push({
|
|
85
|
+
return languagesFound.push({ RUBY: result })
|
|
81
86
|
}
|
|
82
87
|
return languagesFound
|
|
83
88
|
}
|
|
84
89
|
|
|
85
|
-
const findFilesPhp = async languagesFound => {
|
|
90
|
+
const findFilesPhp = async (languagesFound, filePath) => {
|
|
86
91
|
const result = await fg(['**/composer.json', '**/composer.lock'], {
|
|
87
92
|
dot: false,
|
|
88
93
|
deep: 3,
|
|
89
|
-
onlyFiles: true
|
|
94
|
+
onlyFiles: true,
|
|
95
|
+
cwd: filePath ? filePath : process.cwd()
|
|
90
96
|
})
|
|
91
97
|
|
|
92
98
|
if (result.length > 0) {
|
|
93
|
-
return languagesFound.push({
|
|
99
|
+
return languagesFound.push({ PHP: result })
|
|
100
|
+
}
|
|
101
|
+
return languagesFound
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const findFilesDotNet = async (languagesFound, filePath) => {
|
|
105
|
+
const result = await fg(['**/*.csproj', '**/packages.lock.json'], {
|
|
106
|
+
dot: false,
|
|
107
|
+
deep: 3,
|
|
108
|
+
onlyFiles: true,
|
|
109
|
+
cwd: filePath ? filePath : process.cwd()
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
if (result.length > 0) {
|
|
113
|
+
return languagesFound.push({ DOTNET: result })
|
|
94
114
|
}
|
|
95
115
|
return languagesFound
|
|
96
116
|
}
|
|
@@ -110,6 +130,24 @@ const fileExists = path => {
|
|
|
110
130
|
return fs.existsSync(path)
|
|
111
131
|
}
|
|
112
132
|
|
|
133
|
+
const fileIsEmpty = path => {
|
|
134
|
+
if (fileExists(path) && checkFilePermissions(path)) {
|
|
135
|
+
try {
|
|
136
|
+
return fs.readFileSync(path).length === 0
|
|
137
|
+
} catch (e) {
|
|
138
|
+
if (
|
|
139
|
+
e.message.toString().includes('illegal operation on a directory, read')
|
|
140
|
+
) {
|
|
141
|
+
console.log('file provided cannot be a directory')
|
|
142
|
+
} else {
|
|
143
|
+
console.log(e.message.toString())
|
|
144
|
+
}
|
|
145
|
+
process.exit(0)
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return false
|
|
149
|
+
}
|
|
150
|
+
|
|
113
151
|
module.exports = {
|
|
114
152
|
findFile,
|
|
115
153
|
fileExists,
|
|
@@ -119,5 +157,7 @@ module.exports = {
|
|
|
119
157
|
findFilesPython,
|
|
120
158
|
findFilesGo,
|
|
121
159
|
findFilesPhp,
|
|
122
|
-
findFilesRuby
|
|
160
|
+
findFilesRuby,
|
|
161
|
+
findFilesDotNet,
|
|
162
|
+
fileIsEmpty
|
|
123
163
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {
|
|
2
|
-
ProjectOverview,
|
|
3
2
|
ScanResultsInstances,
|
|
4
3
|
ScanResultsModel
|
|
5
4
|
} from './models/scanResultsModel'
|
|
@@ -20,7 +19,7 @@ import {
|
|
|
20
19
|
export function formatScanOutput(scanResults: ScanResultsModel) {
|
|
21
20
|
const { scanResultsInstances } = scanResults
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
const projectOverview = getProjectOverview(scanResultsInstances)
|
|
24
23
|
if (scanResultsInstances.content.length === 0) {
|
|
25
24
|
console.log(i18n.__('scanNoVulnerabilitiesFound'))
|
|
26
25
|
console.log(i18n.__('scanNoVulnerabilitiesFoundSecureCode'))
|
|
@@ -35,8 +34,9 @@ export function formatScanOutput(scanResults: ScanResultsModel) {
|
|
|
35
34
|
|
|
36
35
|
let defaultView = getDefaultView(scanResultsInstances.content)
|
|
37
36
|
|
|
38
|
-
let count =
|
|
37
|
+
let count = 0
|
|
39
38
|
defaultView.forEach(entry => {
|
|
39
|
+
count++
|
|
40
40
|
let table = new Table({
|
|
41
41
|
chars: {
|
|
42
42
|
top: '',
|
|
@@ -62,7 +62,7 @@ export function formatScanOutput(scanResults: ScanResultsModel) {
|
|
|
62
62
|
})
|
|
63
63
|
let learnRow: string[] = []
|
|
64
64
|
let adviceRow = []
|
|
65
|
-
|
|
65
|
+
const headerRow = [
|
|
66
66
|
chalk
|
|
67
67
|
.hex(entry.colour)
|
|
68
68
|
.bold(`CONTRAST-${count.toString().padStart(3, '0')}`),
|
|
@@ -70,12 +70,15 @@ export function formatScanOutput(scanResults: ScanResultsModel) {
|
|
|
70
70
|
chalk.hex(entry.colour).bold(`[${entry.severity}] ${entry.ruleId}`) +
|
|
71
71
|
entry.message
|
|
72
72
|
]
|
|
73
|
-
|
|
73
|
+
|
|
74
|
+
const codePath = entry.codePath?.replace(/^@/, '')
|
|
75
|
+
|
|
76
|
+
const codeRow = [
|
|
74
77
|
chalk.hex('#F6F5F5').bold(`Code`),
|
|
75
78
|
chalk.hex('#F6F5F5').bold(`:`),
|
|
76
|
-
chalk.hex('#F6F5F5').bold(`${
|
|
79
|
+
chalk.hex('#F6F5F5').bold(`${codePath}`)
|
|
77
80
|
]
|
|
78
|
-
|
|
81
|
+
const issueRow = [chalk.bold(`Issue`), chalk.bold(`:`), `${entry.issue}`]
|
|
79
82
|
|
|
80
83
|
table.push(headerRow, codeRow, issueRow)
|
|
81
84
|
|
|
@@ -96,7 +99,6 @@ export function formatScanOutput(scanResults: ScanResultsModel) {
|
|
|
96
99
|
]
|
|
97
100
|
table.push(learnRow)
|
|
98
101
|
}
|
|
99
|
-
count--
|
|
100
102
|
console.log(table.toString())
|
|
101
103
|
console.log()
|
|
102
104
|
})
|
|
@@ -123,7 +125,7 @@ function printVulnInfo(projectOverview: any) {
|
|
|
123
125
|
}
|
|
124
126
|
|
|
125
127
|
export function getProjectOverview(scanResultsInstances: ScanResultsInstances) {
|
|
126
|
-
|
|
128
|
+
const acc: any = {
|
|
127
129
|
critical: 0,
|
|
128
130
|
high: 0,
|
|
129
131
|
medium: 0,
|
|
@@ -146,7 +148,7 @@ export function getProjectOverview(scanResultsInstances: ScanResultsInstances) {
|
|
|
146
148
|
}
|
|
147
149
|
|
|
148
150
|
export function formatLinks(objName: string, entry: any[]) {
|
|
149
|
-
|
|
151
|
+
const line = chalk.bold(objName + ' : ')
|
|
150
152
|
if (entry.length === 1) {
|
|
151
153
|
console.log(line + chalk.hex('#97DCF7').bold.underline(entry[0]))
|
|
152
154
|
} else {
|
|
@@ -177,7 +179,7 @@ export function getDefaultView(content: ResultContent[]) {
|
|
|
177
179
|
assignBySeverity(resultEntry, groupResultsObj)
|
|
178
180
|
})
|
|
179
181
|
|
|
180
|
-
return sortBy(groupTypeResults, ['priority'])
|
|
182
|
+
return sortBy(groupTypeResults, ['priority'])
|
|
181
183
|
}
|
|
182
184
|
export function editVulName(message: string) {
|
|
183
185
|
return message.substring(message.indexOf(' in '))
|
|
@@ -216,10 +218,7 @@ export function getCodeFlowInfo(resultEntry: ResultContent) {
|
|
|
216
218
|
}
|
|
217
219
|
|
|
218
220
|
export function stripTags(oldString: string) {
|
|
219
|
-
return oldString
|
|
220
|
-
.replace(/\n/g, ' ')
|
|
221
|
-
.replace(/\s+/g, ' ')
|
|
222
|
-
.trim()
|
|
221
|
+
return oldString.replace(/\n/g, ' ').replace(/\s+/g, ' ').trim()
|
|
223
222
|
}
|
|
224
223
|
|
|
225
224
|
export function assignBySeverity(
|
|
@@ -9,12 +9,12 @@ export class GroupedResultsModel {
|
|
|
9
9
|
issue?: string
|
|
10
10
|
priority?: number
|
|
11
11
|
message?: string | undefined
|
|
12
|
-
colour: string
|
|
13
|
-
codePath?: string
|
|
12
|
+
colour: string
|
|
13
|
+
codePath?: string
|
|
14
14
|
|
|
15
15
|
constructor(ruleId: string) {
|
|
16
16
|
this.ruleId = ruleId
|
|
17
17
|
this.colour = '#999999'
|
|
18
|
-
this.codePathSet = new Set<string>
|
|
18
|
+
this.codePathSet = new Set<string>()
|
|
19
19
|
}
|
|
20
20
|
}
|
|
@@ -4,11 +4,14 @@ export class ScanResultsModel {
|
|
|
4
4
|
projectOverview: ProjectOverview
|
|
5
5
|
scanDetail: ScanDetail
|
|
6
6
|
scanResultsInstances: ScanResultsInstances
|
|
7
|
+
newProject: boolean
|
|
7
8
|
|
|
8
9
|
constructor(scan: any) {
|
|
9
10
|
this.projectOverview = scan.projectOverview as ProjectOverview
|
|
10
11
|
this.scanDetail = scan.scanDetail as ScanDetail
|
|
11
|
-
this.scanResultsInstances =
|
|
12
|
+
this.scanResultsInstances =
|
|
13
|
+
scan.scanResultsInstances as ScanResultsInstances
|
|
14
|
+
this.newProject = scan.newProject
|
|
12
15
|
}
|
|
13
16
|
}
|
|
14
17
|
|
|
@@ -49,4 +52,4 @@ export interface ScanDetail {
|
|
|
49
52
|
|
|
50
53
|
export interface ScanResultsInstances {
|
|
51
54
|
content: ResultContent[]
|
|
52
|
-
}
|
|
55
|
+
}
|
|
@@ -8,9 +8,11 @@ const populateProjectId = async config => {
|
|
|
8
8
|
proj = await getExistingProjectIdByName(config, client).then(res => {
|
|
9
9
|
return res
|
|
10
10
|
})
|
|
11
|
+
|
|
12
|
+
return { projectId: proj, isNewProject: false }
|
|
11
13
|
}
|
|
12
14
|
|
|
13
|
-
return proj
|
|
15
|
+
return { projectId: proj, isNewProject: true }
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
const createProjectId = async (config, client) => {
|
package/src/scan/scan.ts
CHANGED
package/src/scan/scanConfig.js
CHANGED
|
@@ -2,9 +2,7 @@ const paramHandler = require('../utils/paramsUtil/paramHandler')
|
|
|
2
2
|
const constants = require('../../src/constants.js')
|
|
3
3
|
const parsedCLIOptions = require('../../src/utils/parsedCLIOptions')
|
|
4
4
|
const path = require('path')
|
|
5
|
-
const {
|
|
6
|
-
supportedLanguages
|
|
7
|
-
} = require('../audit/languageAnalysisEngine/constants')
|
|
5
|
+
const { supportedLanguagesScan } = require('../constants/constants')
|
|
8
6
|
const i18n = require('i18n')
|
|
9
7
|
const { scanUsageGuide } = require('./help')
|
|
10
8
|
|
|
@@ -23,7 +21,7 @@ const getScanConfig = argv => {
|
|
|
23
21
|
|
|
24
22
|
if (scanParams.language) {
|
|
25
23
|
scanParams.language = scanParams.language.toUpperCase()
|
|
26
|
-
if (!Object.values(
|
|
24
|
+
if (!Object.values(supportedLanguagesScan).includes(scanParams.language)) {
|
|
27
25
|
console.log(`Did not recognise --language ${scanParams.language}`)
|
|
28
26
|
console.log(i18n.__('constantsHowToRunDev3'))
|
|
29
27
|
process.exit(1)
|
|
@@ -31,11 +29,15 @@ const getScanConfig = argv => {
|
|
|
31
29
|
}
|
|
32
30
|
|
|
33
31
|
// if no name, take the full file path and use it as the project name
|
|
32
|
+
let projectNameSource
|
|
34
33
|
if (!scanParams.name && scanParams.file) {
|
|
35
34
|
scanParams.name = getFileName(scanParams.file)
|
|
35
|
+
projectNameSource = 'AUTO'
|
|
36
|
+
} else {
|
|
37
|
+
projectNameSource = 'USER'
|
|
36
38
|
}
|
|
37
39
|
|
|
38
|
-
return { ...paramsAuth, ...scanParams }
|
|
40
|
+
return { ...paramsAuth, ...scanParams, projectNameSource }
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
const getFileName = file => {
|
|
@@ -29,6 +29,11 @@ const fileAndLanguageLogic = async configToUse => {
|
|
|
29
29
|
console.log(i18n.__('fileNotExist'))
|
|
30
30
|
process.exit(1)
|
|
31
31
|
}
|
|
32
|
+
|
|
33
|
+
if (fileFunctions.fileIsEmpty(configToUse.file)) {
|
|
34
|
+
console.log(i18n.__('scanFileIsEmpty'))
|
|
35
|
+
process.exit(1)
|
|
36
|
+
}
|
|
32
37
|
return configToUse
|
|
33
38
|
} else {
|
|
34
39
|
if (configToUse.file === undefined || configToUse.file === null) {
|
|
@@ -41,10 +46,15 @@ const startScan = async configToUse => {
|
|
|
41
46
|
const startTime = performance.now()
|
|
42
47
|
await fileAndLanguageLogic(configToUse)
|
|
43
48
|
|
|
49
|
+
let newProject
|
|
50
|
+
|
|
44
51
|
if (!configToUse.projectId) {
|
|
45
|
-
|
|
46
|
-
configToUse
|
|
47
|
-
|
|
52
|
+
const { projectId, isNewProject } =
|
|
53
|
+
await populateProjectIdAndProjectName.populateProjectId(configToUse)
|
|
54
|
+
configToUse.projectId = projectId
|
|
55
|
+
newProject = isNewProject
|
|
56
|
+
} else {
|
|
57
|
+
newProject = false
|
|
48
58
|
}
|
|
49
59
|
const codeArtifactId = await scan.sendScan(configToUse)
|
|
50
60
|
|
|
@@ -54,6 +64,7 @@ const startScan = async configToUse => {
|
|
|
54
64
|
const scanDetail = await scanResults.returnScanResults(
|
|
55
65
|
configToUse,
|
|
56
66
|
codeArtifactId,
|
|
67
|
+
newProject,
|
|
57
68
|
getTimeout(configToUse),
|
|
58
69
|
startScanSpinner
|
|
59
70
|
)
|
|
@@ -74,7 +85,10 @@ const startScan = async configToUse => {
|
|
|
74
85
|
console.log(
|
|
75
86
|
`----- Scan completed in ${(scanDurationMs / 1000).toFixed(2)}s -----`
|
|
76
87
|
)
|
|
77
|
-
return {
|
|
88
|
+
return {
|
|
89
|
+
scanDetail,
|
|
90
|
+
scanResultsInstances: scanResultsInstances.body
|
|
91
|
+
}
|
|
78
92
|
}
|
|
79
93
|
}
|
|
80
94
|
}
|
package/src/scan/scanResults.js
CHANGED
|
@@ -31,11 +31,21 @@ const pollScanResults = async (config, scanId, client) => {
|
|
|
31
31
|
const returnScanResults = async (
|
|
32
32
|
config,
|
|
33
33
|
codeArtifactId,
|
|
34
|
+
newProject,
|
|
34
35
|
timeout,
|
|
35
36
|
startScanSpinner
|
|
36
37
|
) => {
|
|
37
38
|
const client = commonApi.getHttpClient(config)
|
|
38
39
|
let scanId = await getScanId(config, codeArtifactId, client)
|
|
40
|
+
|
|
41
|
+
// send metrics event to sast-event-collector
|
|
42
|
+
if (
|
|
43
|
+
process.env.CODESEC_INVOCATION_ENVIRONMENT &&
|
|
44
|
+
process.env.CODESEC_INVOCATION_ENVIRONMENT.toUpperCase() === 'GITHUB'
|
|
45
|
+
) {
|
|
46
|
+
await client.createNewEvent(config, scanId, newProject)
|
|
47
|
+
}
|
|
48
|
+
|
|
39
49
|
let startTime = new Date()
|
|
40
50
|
let complete = false
|
|
41
51
|
if (!_.isNil(scanId)) {
|
package/src/utils/commonApi.js
CHANGED
|
@@ -4,7 +4,8 @@ const {
|
|
|
4
4
|
unauthenticatedError,
|
|
5
5
|
forbiddenError,
|
|
6
6
|
proxyError,
|
|
7
|
-
genericError
|
|
7
|
+
genericError,
|
|
8
|
+
maxAppError
|
|
8
9
|
} = require('../common/errorHandling')
|
|
9
10
|
|
|
10
11
|
const handleResponseErrors = (res, api) => {
|
|
@@ -16,6 +17,8 @@ const handleResponseErrors = (res, api) => {
|
|
|
16
17
|
forbiddenError()
|
|
17
18
|
} else if (res.statusCode === 407) {
|
|
18
19
|
proxyError()
|
|
20
|
+
} else if (res.statusCode === 412) {
|
|
21
|
+
maxAppError()
|
|
19
22
|
} else {
|
|
20
23
|
genericError()
|
|
21
24
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const path = require('path')
|
|
2
|
+
const child_process = require('child_process')
|
|
2
3
|
|
|
3
4
|
function resolveFilePath(filepath) {
|
|
4
5
|
if (filepath[0] === '~') {
|
|
@@ -8,10 +9,13 @@ function resolveFilePath(filepath) {
|
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
const returnProjectPath = () => {
|
|
11
|
-
if (process.
|
|
12
|
+
if (process.platform == 'win32') {
|
|
13
|
+
let winPath = child_process.execSync('cd').toString()
|
|
14
|
+
return winPath.replace(/\//g, '\\').trim()
|
|
15
|
+
} else if (process.env.PWD !== (undefined || null || 'undefined')) {
|
|
12
16
|
return process.env.PWD
|
|
13
17
|
} else {
|
|
14
|
-
return process.argv[process.argv.indexOf('--
|
|
18
|
+
return process.argv[process.argv.indexOf('--file') + 1]
|
|
15
19
|
}
|
|
16
20
|
}
|
|
17
21
|
|
package/src/utils/getConfig.ts
CHANGED
|
@@ -33,11 +33,6 @@ const localConfig = (name: string, version: string) => {
|
|
|
33
33
|
return config
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
const createConfigFromYaml = (yamlPath: string) => {
|
|
37
|
-
const yamlConfig = {}
|
|
38
|
-
return yamlConfig
|
|
39
|
-
}
|
|
40
|
-
|
|
41
36
|
const setConfigValues = (config: ContrastConf, values: ContrastConfOptions) => {
|
|
42
37
|
config.set('apiKey', values.apiKey)
|
|
43
38
|
config.set('organizationId', values.orgId)
|
|
@@ -45,10 +40,4 @@ const setConfigValues = (config: ContrastConf, values: ContrastConfOptions) => {
|
|
|
45
40
|
values.host ? config.set('host', values.host) : null
|
|
46
41
|
}
|
|
47
42
|
|
|
48
|
-
export {
|
|
49
|
-
localConfig,
|
|
50
|
-
createConfigFromYaml,
|
|
51
|
-
setConfigValues,
|
|
52
|
-
ContrastConf,
|
|
53
|
-
ContrastConfOptions
|
|
54
|
-
}
|
|
43
|
+
export { localConfig, setConfigValues, ContrastConf, ContrastConfOptions }
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
class AnalysisEngine {
|
|
3
|
-
constructor(initAnalysis = {}) {
|
|
4
|
-
this.analyzers = [];
|
|
5
|
-
this.analysis = { ...initAnalysis };
|
|
6
|
-
}
|
|
7
|
-
use(analyzer) {
|
|
8
|
-
if (Array.isArray(analyzer)) {
|
|
9
|
-
this.analyzers = [...this.analyzers, ...analyzer];
|
|
10
|
-
return;
|
|
11
|
-
}
|
|
12
|
-
this.analyzers.push(analyzer);
|
|
13
|
-
}
|
|
14
|
-
analyze(callback, config) {
|
|
15
|
-
let i = 0;
|
|
16
|
-
const next = err => {
|
|
17
|
-
if (err) {
|
|
18
|
-
return setImmediate(() => callback(err, this.analysis));
|
|
19
|
-
}
|
|
20
|
-
if (i >= this.analyzers.length) {
|
|
21
|
-
return setImmediate(() => callback(null, this.analysis));
|
|
22
|
-
}
|
|
23
|
-
const analyzer = this.analyzers[i];
|
|
24
|
-
i++;
|
|
25
|
-
setImmediate(() => {
|
|
26
|
-
try {
|
|
27
|
-
analyzer(this.analysis, next, config);
|
|
28
|
-
}
|
|
29
|
-
catch (uncaughtErr) {
|
|
30
|
-
next(uncaughtErr);
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
};
|
|
34
|
-
next();
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
module.exports = exports = AnalysisEngine;
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.determineProjectLanguage = exports.identifyLanguages = void 0;
|
|
7
|
-
const i18n_1 = __importDefault(require("i18n"));
|
|
8
|
-
const reduceIdentifiedLanguages_1 = require("../languageAnalysisEngine/reduceIdentifiedLanguages");
|
|
9
|
-
const getProjectRootFilenames_1 = require("../languageAnalysisEngine/getProjectRootFilenames");
|
|
10
|
-
function identifyLanguages(config) {
|
|
11
|
-
const { projectPath } = config;
|
|
12
|
-
const projectRootFilenames = (0, getProjectRootFilenames_1.getProjectRootFilenames)(projectPath);
|
|
13
|
-
const identifiedLanguages = projectRootFilenames.reduce((accumulator, filename) => {
|
|
14
|
-
const deducedLanguages = (0, reduceIdentifiedLanguages_1.deduceLanguage)(filename);
|
|
15
|
-
return [...accumulator, ...deducedLanguages];
|
|
16
|
-
}, []);
|
|
17
|
-
if (Object.keys(identifiedLanguages).length === 0) {
|
|
18
|
-
throw new Error(i18n_1.default.__('languageAnalysisNoLanguage', projectPath));
|
|
19
|
-
}
|
|
20
|
-
return (0, reduceIdentifiedLanguages_1.reduceIdentifiedLanguages)(identifiedLanguages);
|
|
21
|
-
}
|
|
22
|
-
exports.identifyLanguages = identifyLanguages;
|
|
23
|
-
function determineProjectLanguage(reducedLanguages) {
|
|
24
|
-
const reducedLanguagesKeys = Object.keys(reducedLanguages);
|
|
25
|
-
if (reducedLanguagesKeys.length === 1) {
|
|
26
|
-
return reducedLanguagesKeys[0];
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
throw new Error('Detected multiple languages. Please specify a single language using --language');
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
exports.determineProjectLanguage = determineProjectLanguage;
|