@contrast/contrast 1.0.8 → 1.0.11
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/README.md +2 -2
- package/dist/audit/languageAnalysisEngine/getProjectRootFilenames.js +16 -25
- package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +103 -57
- package/dist/audit/languageAnalysisEngine/report/models/reportGuidanceModel.js +6 -0
- package/dist/audit/languageAnalysisEngine/report/models/reportOutputModel.js +3 -3
- package/dist/audit/languageAnalysisEngine/report/models/severityCountModel.js +1 -0
- package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +68 -17
- package/dist/audit/languageAnalysisEngine/report/utils/reportUtils.js +39 -7
- package/dist/audit/languageAnalysisEngine/sendSnapshot.js +6 -30
- package/dist/audit/save.js +21 -13
- package/dist/commands/audit/auditConfig.js +3 -19
- package/dist/commands/audit/auditController.js +1 -10
- package/dist/commands/audit/help.js +7 -24
- package/dist/commands/audit/processAudit.js +5 -9
- package/dist/commands/audit/saveFile.js +2 -2
- package/dist/commands/auth/auth.js +1 -1
- package/dist/commands/config/config.js +2 -2
- package/dist/commands/scan/processScan.js +11 -4
- package/dist/commands/scan/sca/scaAnalysis.js +37 -13
- package/dist/common/HTTPClient.js +17 -8
- package/dist/common/errorHandling.js +2 -2
- package/dist/common/fail.js +66 -0
- package/dist/common/versionChecker.js +1 -1
- package/dist/constants/constants.js +7 -2
- package/dist/constants/locales.js +40 -38
- package/dist/constants.js +62 -12
- package/dist/index.js +57 -45
- package/dist/lambda/lambda.js +5 -2
- package/dist/sbom/generateSbom.js +2 -2
- package/dist/scaAnalysis/common/formatMessage.js +7 -1
- package/dist/scaAnalysis/common/scaParserForGoAndJava.js +32 -0
- package/dist/scaAnalysis/common/treeUpload.js +24 -10
- package/dist/scaAnalysis/dotnet/analysis.js +55 -0
- package/dist/scaAnalysis/dotnet/index.js +10 -0
- package/dist/scaAnalysis/go/goAnalysis.js +8 -2
- package/dist/scaAnalysis/java/analysis.js +10 -6
- package/dist/scaAnalysis/java/index.js +7 -1
- package/dist/scaAnalysis/java/javaBuildDepsParser.js +19 -3
- package/dist/scaAnalysis/javascript/analysis.js +4 -7
- package/dist/scaAnalysis/javascript/index.js +16 -4
- package/dist/scaAnalysis/php/analysis.js +14 -33
- package/dist/scaAnalysis/php/index.js +11 -4
- package/dist/scaAnalysis/python/analysis.js +43 -5
- package/dist/scaAnalysis/python/index.js +7 -2
- package/dist/scaAnalysis/ruby/analysis.js +16 -14
- package/dist/scan/autoDetection.js +13 -24
- package/dist/scan/fileUtils.js +31 -12
- package/dist/scan/formatScanOutput.js +9 -8
- package/dist/scan/populateProjectIdAndProjectName.js +5 -0
- package/dist/scan/scan.js +4 -0
- package/dist/scan/scanConfig.js +5 -5
- package/dist/scan/scanResults.js +39 -3
- package/dist/telemetry/telemetry.js +137 -0
- package/dist/utils/commonApi.js +1 -1
- package/dist/utils/getConfig.js +3 -8
- package/dist/utils/parsedCLIOptions.js +3 -1
- package/dist/utils/requestUtils.js +7 -1
- package/package.json +2 -3
- package/src/audit/languageAnalysisEngine/getProjectRootFilenames.js +21 -57
- package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.ts +155 -77
- package/src/audit/languageAnalysisEngine/report/models/reportGuidanceModel.ts +5 -0
- package/src/audit/languageAnalysisEngine/report/models/reportOutputModel.ts +5 -5
- package/src/audit/languageAnalysisEngine/report/models/severityCountModel.ts +2 -0
- package/src/audit/languageAnalysisEngine/report/reportingFeature.ts +56 -27
- package/src/audit/languageAnalysisEngine/report/utils/reportUtils.ts +45 -6
- package/src/audit/languageAnalysisEngine/sendSnapshot.js +6 -32
- package/src/audit/save.js +32 -16
- package/src/commands/audit/auditConfig.ts +10 -28
- package/src/commands/audit/auditController.ts +0 -11
- package/src/commands/audit/help.ts +7 -24
- package/src/commands/audit/processAudit.ts +16 -8
- package/src/commands/audit/saveFile.ts +2 -2
- package/src/commands/auth/auth.js +3 -1
- package/src/commands/config/config.js +4 -2
- package/src/commands/scan/processScan.js +18 -5
- package/src/commands/scan/sca/scaAnalysis.js +50 -18
- package/src/common/HTTPClient.js +23 -9
- package/src/common/errorHandling.ts +2 -3
- package/src/common/fail.js +75 -0
- package/src/common/versionChecker.ts +1 -1
- package/src/constants/constants.js +9 -3
- package/src/constants/locales.js +70 -45
- package/src/constants.js +67 -13
- package/src/index.ts +91 -66
- package/src/lambda/lambda.ts +5 -2
- package/src/lambda/types.ts +1 -0
- package/src/sbom/generateSbom.ts +2 -2
- package/src/scaAnalysis/common/formatMessage.js +8 -1
- package/src/scaAnalysis/common/scaParserForGoAndJava.js +41 -0
- package/src/scaAnalysis/common/treeUpload.js +25 -11
- package/src/scaAnalysis/dotnet/analysis.js +72 -0
- package/src/scaAnalysis/dotnet/index.js +11 -0
- package/src/scaAnalysis/go/goAnalysis.js +9 -2
- package/src/scaAnalysis/java/analysis.js +11 -6
- package/src/scaAnalysis/java/index.js +9 -1
- package/src/scaAnalysis/java/javaBuildDepsParser.js +25 -6
- package/src/scaAnalysis/javascript/analysis.js +6 -7
- package/src/scaAnalysis/javascript/index.js +25 -6
- package/src/scaAnalysis/php/analysis.js +15 -35
- package/src/scaAnalysis/php/index.js +15 -4
- package/src/scaAnalysis/python/analysis.js +49 -5
- package/src/scaAnalysis/python/index.js +7 -2
- package/src/scaAnalysis/ruby/analysis.js +18 -15
- package/src/scan/autoDetection.js +14 -27
- package/src/scan/fileUtils.js +33 -12
- package/src/scan/formatScanOutput.ts +10 -8
- package/src/scan/populateProjectIdAndProjectName.js +5 -1
- package/src/scan/scan.ts +4 -0
- package/src/scan/scanConfig.js +7 -7
- package/src/scan/scanResults.js +46 -3
- package/src/telemetry/telemetry.ts +154 -0
- package/src/utils/commonApi.js +1 -1
- package/src/utils/getConfig.ts +5 -18
- package/src/utils/parsedCLIOptions.js +14 -1
- package/src/utils/requestUtils.js +8 -1
- 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 -155
- 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 -25
- package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +0 -25
- package/dist/audit/languageAnalysisEngine/checkIdentifiedLanguageHasLockFile.js +0 -35
- package/dist/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +0 -24
- 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 -66
- package/dist/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +0 -166
- 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 -225
- 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 -36
- package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +0 -42
- package/src/audit/languageAnalysisEngine/checkIdentifiedLanguageHasLockFile.js +0 -54
- package/src/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +0 -33
- 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 -96
- package/src/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +0 -251
- 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
package/dist/scan/fileUtils.js
CHANGED
|
@@ -10,72 +10,90 @@ const findFile = async () => {
|
|
|
10
10
|
onlyFiles: true
|
|
11
11
|
});
|
|
12
12
|
};
|
|
13
|
-
const findFilesJava = async (languagesFound) => {
|
|
13
|
+
const findFilesJava = async (languagesFound, filePath) => {
|
|
14
14
|
const result = await fg(['**/pom.xml', '**/build.gradle', '**/build.gradle.kts'], {
|
|
15
15
|
dot: false,
|
|
16
16
|
deep: 1,
|
|
17
|
-
onlyFiles: true
|
|
17
|
+
onlyFiles: true,
|
|
18
|
+
cwd: filePath ? filePath : process.cwd()
|
|
18
19
|
});
|
|
19
20
|
if (result.length > 0) {
|
|
20
21
|
return languagesFound.push({ JAVA: result });
|
|
21
22
|
}
|
|
22
23
|
return languagesFound;
|
|
23
24
|
};
|
|
24
|
-
const findFilesJavascript = async (languagesFound) => {
|
|
25
|
+
const findFilesJavascript = async (languagesFound, filePath) => {
|
|
25
26
|
const result = await fg(['**/package.json', '**/yarn.lock', '**/package-lock.json'], {
|
|
26
27
|
dot: false,
|
|
27
28
|
deep: 1,
|
|
28
|
-
onlyFiles: true
|
|
29
|
+
onlyFiles: true,
|
|
30
|
+
cwd: filePath ? filePath : process.cwd()
|
|
29
31
|
});
|
|
30
32
|
if (result.length > 0) {
|
|
31
33
|
return languagesFound.push({ JAVASCRIPT: result });
|
|
32
34
|
}
|
|
33
35
|
return languagesFound;
|
|
34
36
|
};
|
|
35
|
-
const findFilesPython = async (languagesFound) => {
|
|
37
|
+
const findFilesPython = async (languagesFound, filePath) => {
|
|
36
38
|
const result = await fg(['**/Pipfile.lock', '**/Pipfile'], {
|
|
37
39
|
dot: false,
|
|
38
40
|
deep: 3,
|
|
39
|
-
onlyFiles: true
|
|
41
|
+
onlyFiles: true,
|
|
42
|
+
cwd: filePath ? filePath : process.cwd()
|
|
40
43
|
});
|
|
41
44
|
if (result.length > 0) {
|
|
42
45
|
return languagesFound.push({ PYTHON: result });
|
|
43
46
|
}
|
|
44
47
|
return languagesFound;
|
|
45
48
|
};
|
|
46
|
-
const findFilesGo = async (languagesFound) => {
|
|
49
|
+
const findFilesGo = async (languagesFound, filePath) => {
|
|
47
50
|
const result = await fg(['**/go.mod'], {
|
|
48
51
|
dot: false,
|
|
49
52
|
deep: 3,
|
|
50
|
-
onlyFiles: true
|
|
53
|
+
onlyFiles: true,
|
|
54
|
+
cwd: filePath ? filePath : process.cwd()
|
|
51
55
|
});
|
|
52
56
|
if (result.length > 0) {
|
|
53
57
|
return languagesFound.push({ GO: result });
|
|
54
58
|
}
|
|
55
59
|
return languagesFound;
|
|
56
60
|
};
|
|
57
|
-
const findFilesRuby = async (languagesFound) => {
|
|
61
|
+
const findFilesRuby = async (languagesFound, filePath) => {
|
|
58
62
|
const result = await fg(['**/Gemfile', '**/Gemfile.lock'], {
|
|
59
63
|
dot: false,
|
|
60
64
|
deep: 3,
|
|
61
|
-
onlyFiles: true
|
|
65
|
+
onlyFiles: true,
|
|
66
|
+
cwd: filePath ? filePath : process.cwd()
|
|
62
67
|
});
|
|
63
68
|
if (result.length > 0) {
|
|
64
69
|
return languagesFound.push({ RUBY: result });
|
|
65
70
|
}
|
|
66
71
|
return languagesFound;
|
|
67
72
|
};
|
|
68
|
-
const findFilesPhp = async (languagesFound) => {
|
|
73
|
+
const findFilesPhp = async (languagesFound, filePath) => {
|
|
69
74
|
const result = await fg(['**/composer.json', '**/composer.lock'], {
|
|
70
75
|
dot: false,
|
|
71
76
|
deep: 3,
|
|
72
|
-
onlyFiles: true
|
|
77
|
+
onlyFiles: true,
|
|
78
|
+
cwd: filePath ? filePath : process.cwd()
|
|
73
79
|
});
|
|
74
80
|
if (result.length > 0) {
|
|
75
81
|
return languagesFound.push({ PHP: result });
|
|
76
82
|
}
|
|
77
83
|
return languagesFound;
|
|
78
84
|
};
|
|
85
|
+
const findFilesDotNet = async (languagesFound, filePath) => {
|
|
86
|
+
const result = await fg(['**/*.csproj', '**/packages.lock.json'], {
|
|
87
|
+
dot: false,
|
|
88
|
+
deep: 3,
|
|
89
|
+
onlyFiles: true,
|
|
90
|
+
cwd: filePath ? filePath : process.cwd()
|
|
91
|
+
});
|
|
92
|
+
if (result.length > 0) {
|
|
93
|
+
return languagesFound.push({ DOTNET: result });
|
|
94
|
+
}
|
|
95
|
+
return languagesFound;
|
|
96
|
+
};
|
|
79
97
|
const checkFilePermissions = file => {
|
|
80
98
|
let readableFile = false;
|
|
81
99
|
try {
|
|
@@ -117,5 +135,6 @@ module.exports = {
|
|
|
117
135
|
findFilesGo,
|
|
118
136
|
findFilesPhp,
|
|
119
137
|
findFilesRuby,
|
|
138
|
+
findFilesDotNet,
|
|
120
139
|
fileIsEmpty
|
|
121
140
|
};
|
|
@@ -25,8 +25,9 @@ function formatScanOutput(scanResults) {
|
|
|
25
25
|
console.log(chalk_1.default.bold(message));
|
|
26
26
|
console.log();
|
|
27
27
|
let defaultView = getDefaultView(scanResultsInstances.content);
|
|
28
|
-
let count =
|
|
28
|
+
let count = 0;
|
|
29
29
|
defaultView.forEach(entry => {
|
|
30
|
+
count++;
|
|
30
31
|
let table = new cli_table3_1.default({
|
|
31
32
|
chars: {
|
|
32
33
|
top: '',
|
|
@@ -52,12 +53,12 @@ function formatScanOutput(scanResults) {
|
|
|
52
53
|
});
|
|
53
54
|
let learnRow = [];
|
|
54
55
|
let adviceRow = [];
|
|
56
|
+
const headerColour = chalk_1.default.hex(entry.colour);
|
|
55
57
|
const headerRow = [
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
chalk_1.default.hex(entry.colour).bold(`[${entry.severity}] ${entry.ruleId}`) +
|
|
58
|
+
headerColour(`CONTRAST-${count.toString().padStart(3, '0')}`),
|
|
59
|
+
headerColour(`-`),
|
|
60
|
+
headerColour(`[${entry.severity}] `) +
|
|
61
|
+
headerColour.bold(`${entry.ruleId}`) +
|
|
61
62
|
entry.message
|
|
62
63
|
];
|
|
63
64
|
const codePath = entry.codePath?.replace(/^@/, '');
|
|
@@ -84,12 +85,12 @@ function formatScanOutput(scanResults) {
|
|
|
84
85
|
];
|
|
85
86
|
table.push(learnRow);
|
|
86
87
|
}
|
|
87
|
-
count--;
|
|
88
88
|
console.log(table.toString());
|
|
89
89
|
console.log();
|
|
90
90
|
});
|
|
91
91
|
}
|
|
92
92
|
printVulnInfo(projectOverview);
|
|
93
|
+
return projectOverview;
|
|
93
94
|
}
|
|
94
95
|
exports.formatScanOutput = formatScanOutput;
|
|
95
96
|
function printVulnInfo(projectOverview) {
|
|
@@ -149,7 +150,7 @@ function getDefaultView(content) {
|
|
|
149
150
|
groupTypeResults.push(groupResultsObj);
|
|
150
151
|
assignBySeverity(resultEntry, groupResultsObj);
|
|
151
152
|
});
|
|
152
|
-
return (0, lodash_1.sortBy)(groupTypeResults, ['priority'])
|
|
153
|
+
return (0, lodash_1.sortBy)(groupTypeResults, ['priority']);
|
|
153
154
|
}
|
|
154
155
|
exports.getDefaultView = getDefaultView;
|
|
155
156
|
function editVulName(message) {
|
|
@@ -25,6 +25,11 @@ const createProjectId = async (config, client) => {
|
|
|
25
25
|
process.exit(1);
|
|
26
26
|
return;
|
|
27
27
|
}
|
|
28
|
+
if (res.statusCode === 429) {
|
|
29
|
+
console.log(i18n.__('exceededFreeTier'));
|
|
30
|
+
process.exit(1);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
28
33
|
if (res.statusCode === 201) {
|
|
29
34
|
console.log(i18n.__('projectCreatedScan'));
|
|
30
35
|
if (config.verbose) {
|
package/dist/scan/scan.js
CHANGED
|
@@ -45,6 +45,10 @@ const sendScan = async (config) => {
|
|
|
45
45
|
oraWrapper_1.default.failSpinner(startUploadSpinner, i18n_1.default.__('uploadingScanFail'));
|
|
46
46
|
console.log(i18n_1.default.__('genericServiceError', res.statusCode));
|
|
47
47
|
}
|
|
48
|
+
if (res.statusCode === 429) {
|
|
49
|
+
console.log(i18n_1.default.__('exceededFreeTier'));
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
48
52
|
if (res.statusCode === 403) {
|
|
49
53
|
console.log(i18n_1.default.__('permissionsError'));
|
|
50
54
|
process.exit(1);
|
package/dist/scan/scanConfig.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const paramHandler = require('../utils/paramsUtil/paramHandler');
|
|
3
3
|
const constants = require('../../src/constants.js');
|
|
4
|
-
const parsedCLIOptions = require('../../src/utils/parsedCLIOptions');
|
|
5
4
|
const path = require('path');
|
|
6
|
-
const {
|
|
5
|
+
const { supportedLanguagesScan } = require('../constants/constants');
|
|
7
6
|
const i18n = require('i18n');
|
|
8
7
|
const { scanUsageGuide } = require('./help');
|
|
9
|
-
const
|
|
10
|
-
|
|
8
|
+
const parsedCLIOptions = require('../utils/parsedCLIOptions');
|
|
9
|
+
const getScanConfig = async (contrastConf, command, argv) => {
|
|
10
|
+
let scanParams = await parsedCLIOptions.getCommandLineArgsCustom(contrastConf, command, argv, constants.commandLineDefinitions.scanOptionDefinitions);
|
|
11
11
|
if (scanParams.help) {
|
|
12
12
|
printHelpMessage();
|
|
13
13
|
process.exit(0);
|
|
@@ -15,7 +15,7 @@ const getScanConfig = argv => {
|
|
|
15
15
|
const paramsAuth = paramHandler.getAuth(scanParams);
|
|
16
16
|
if (scanParams.language) {
|
|
17
17
|
scanParams.language = scanParams.language.toUpperCase();
|
|
18
|
-
if (!Object.values(
|
|
18
|
+
if (!Object.values(supportedLanguagesScan).includes(scanParams.language)) {
|
|
19
19
|
console.log(`Did not recognise --language ${scanParams.language}`);
|
|
20
20
|
console.log(i18n.__('constantsHowToRunDev3'));
|
|
21
21
|
process.exit(1);
|
package/dist/scan/scanResults.js
CHANGED
|
@@ -5,10 +5,14 @@ const oraFunctions = require('../utils/oraWrapper');
|
|
|
5
5
|
const _ = require('lodash');
|
|
6
6
|
const i18n = require('i18n');
|
|
7
7
|
const oraWrapper = require('../utils/oraWrapper');
|
|
8
|
+
const readLine = require('readline');
|
|
8
9
|
const getScanId = async (config, codeArtifactId, client) => {
|
|
9
10
|
return client
|
|
10
11
|
.getScanId(config, codeArtifactId)
|
|
11
12
|
.then(res => {
|
|
13
|
+
if (res.statusCode == 429) {
|
|
14
|
+
throw new Error(i18n.__('exceededFreeTier'));
|
|
15
|
+
}
|
|
12
16
|
return res.body.id;
|
|
13
17
|
})
|
|
14
18
|
.catch(err => {
|
|
@@ -61,12 +65,43 @@ const returnScanResults = async (config, codeArtifactId, newProject, timeout, st
|
|
|
61
65
|
let endTime = new Date() - startTime;
|
|
62
66
|
if (requestUtils.millisToSeconds(endTime) > timeout) {
|
|
63
67
|
oraFunctions.failSpinner(startScanSpinner, 'Contrast Scan timed out at the specified ' + timeout + ' seconds.');
|
|
64
|
-
|
|
65
|
-
|
|
68
|
+
if (!config.isCI) {
|
|
69
|
+
const retry = await retryScanPrompt();
|
|
70
|
+
timeout = retry.timeout;
|
|
71
|
+
}
|
|
66
72
|
}
|
|
67
73
|
}
|
|
68
74
|
}
|
|
69
75
|
};
|
|
76
|
+
const retryScanPrompt = async () => {
|
|
77
|
+
const rl = readLine.createInterface({
|
|
78
|
+
input: process.stdin,
|
|
79
|
+
output: process.stdout
|
|
80
|
+
});
|
|
81
|
+
return new Promise((resolve, reject) => {
|
|
82
|
+
requestUtils.timeOutError(30000, reject);
|
|
83
|
+
rl.question('🔁 Do you want to continue waiting on Scan? [Y/N]\n', async (input) => {
|
|
84
|
+
if (input.toLowerCase() === 'yes' || input.toLowerCase() === 'y') {
|
|
85
|
+
console.log('Continuing wait for Scan');
|
|
86
|
+
rl.close();
|
|
87
|
+
resolve({ timeout: 300 });
|
|
88
|
+
}
|
|
89
|
+
else if (input.toLowerCase() === 'no' ||
|
|
90
|
+
input.toLowerCase() === 'n') {
|
|
91
|
+
rl.close();
|
|
92
|
+
console.log('Contrast Scan Retry Cancelled: Exiting');
|
|
93
|
+
resolve(process.exit(1));
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
rl.close();
|
|
97
|
+
console.log('Invalid Input: Exiting');
|
|
98
|
+
resolve(process.exit(1));
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}).catch(e => {
|
|
102
|
+
throw e;
|
|
103
|
+
});
|
|
104
|
+
};
|
|
70
105
|
const returnScanResultsInstances = async (config, scanId) => {
|
|
71
106
|
const client = commonApi.getHttpClient(config);
|
|
72
107
|
let result;
|
|
@@ -89,5 +124,6 @@ module.exports = {
|
|
|
89
124
|
getScanId: getScanId,
|
|
90
125
|
returnScanResults: returnScanResults,
|
|
91
126
|
pollScanResults: pollScanResults,
|
|
92
|
-
returnScanResultsInstances: returnScanResultsInstances
|
|
127
|
+
returnScanResultsInstances: returnScanResultsInstances,
|
|
128
|
+
retryScanPrompt
|
|
93
129
|
};
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.sha1Base64Value = exports.findParamValueFromArgs = exports.paramExists = exports.obfuscateParams = exports.sendTelemetryRequest = exports.sendTelemetryConfigAsObject = exports.sendTelemetryConfigAsConfObj = exports.TELEMETRY_CLI_TIME_TO_AUTH_EVENT = exports.TELEMETRY_CLI_COMMANDS_EVENT = void 0;
|
|
27
|
+
const commonApi_1 = require("../utils/commonApi");
|
|
28
|
+
const crypto = __importStar(require("crypto"));
|
|
29
|
+
exports.TELEMETRY_CLI_COMMANDS_EVENT = 'CLI_COMMANDS';
|
|
30
|
+
exports.TELEMETRY_CLI_TIME_TO_AUTH_EVENT = 'CLI_TIME_TO_AUTH';
|
|
31
|
+
const sendTelemetryConfigAsConfObj = async (config, command, argv, result, language) => {
|
|
32
|
+
const hostParam = '--host';
|
|
33
|
+
const hostParamAlias = '-h';
|
|
34
|
+
const orgIdParam = '--organization-id';
|
|
35
|
+
const orgIdParamAlias = '-o';
|
|
36
|
+
const authParam = '--authorization';
|
|
37
|
+
const apiKeyParam = '--api-key';
|
|
38
|
+
let configToUse;
|
|
39
|
+
if ((0, exports.paramExists)(argv, hostParam, hostParamAlias) &&
|
|
40
|
+
(0, exports.paramExists)(argv, orgIdParam, orgIdParamAlias) &&
|
|
41
|
+
(0, exports.paramExists)(argv, authParam, null) &&
|
|
42
|
+
(0, exports.paramExists)(argv, apiKeyParam, null)) {
|
|
43
|
+
configToUse = {
|
|
44
|
+
host: (0, exports.findParamValueFromArgs)(argv, hostParam, hostParamAlias),
|
|
45
|
+
organizationId: (0, exports.findParamValueFromArgs)(argv, orgIdParam, orgIdParamAlias),
|
|
46
|
+
authorization: (0, exports.findParamValueFromArgs)(argv, authParam, null),
|
|
47
|
+
apiKey: (0, exports.findParamValueFromArgs)(argv, apiKeyParam, null)
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
else if (config &&
|
|
51
|
+
config.get('host') &&
|
|
52
|
+
config.get('organizationId') &&
|
|
53
|
+
config.get('authorization') &&
|
|
54
|
+
config.get('apiKey')) {
|
|
55
|
+
configToUse = {
|
|
56
|
+
host: config.get('host')?.slice(0, -1),
|
|
57
|
+
organizationId: config.get('organizationId'),
|
|
58
|
+
authorization: config.get('authorization'),
|
|
59
|
+
apiKey: config.get('apiKey')
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
return await (0, exports.sendTelemetryConfigAsObject)(configToUse, command, argv, result, language);
|
|
66
|
+
};
|
|
67
|
+
exports.sendTelemetryConfigAsConfObj = sendTelemetryConfigAsConfObj;
|
|
68
|
+
const sendTelemetryConfigAsObject = async (config, command, argv, result, language) => {
|
|
69
|
+
const obfuscatedParams = (0, exports.obfuscateParams)(argv);
|
|
70
|
+
const requestBody = {
|
|
71
|
+
event: exports.TELEMETRY_CLI_COMMANDS_EVENT,
|
|
72
|
+
details: {
|
|
73
|
+
ip_address: '',
|
|
74
|
+
account_name: '',
|
|
75
|
+
account_host: '',
|
|
76
|
+
company_domain: '',
|
|
77
|
+
command: `contrast ${command} ${obfuscatedParams}`,
|
|
78
|
+
app_id: config && config.applicationId
|
|
79
|
+
? (0, exports.sha1Base64Value)(config.applicationId)
|
|
80
|
+
: 'undefined',
|
|
81
|
+
project_id: config && config.projectId
|
|
82
|
+
? (0, exports.sha1Base64Value)(config.projectId)
|
|
83
|
+
: 'undefined',
|
|
84
|
+
language: language,
|
|
85
|
+
result: result,
|
|
86
|
+
additional_info: '',
|
|
87
|
+
timestamp: new Date().toUTCString()
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
return await (0, exports.sendTelemetryRequest)(config, requestBody);
|
|
91
|
+
};
|
|
92
|
+
exports.sendTelemetryConfigAsObject = sendTelemetryConfigAsObject;
|
|
93
|
+
const sendTelemetryRequest = async (config, requestBody) => {
|
|
94
|
+
const client = (0, commonApi_1.getHttpClient)(config);
|
|
95
|
+
return client
|
|
96
|
+
.postTelemetry(config, requestBody)
|
|
97
|
+
.then((res) => {
|
|
98
|
+
if (res.statusCode !== 200 && config.debug === true) {
|
|
99
|
+
console.log('Telemetry failed to send with status', res.statusCode);
|
|
100
|
+
}
|
|
101
|
+
return { statusCode: res.statusCode, statusMessage: res.statusMessage };
|
|
102
|
+
})
|
|
103
|
+
.catch((err) => {
|
|
104
|
+
return;
|
|
105
|
+
});
|
|
106
|
+
};
|
|
107
|
+
exports.sendTelemetryRequest = sendTelemetryRequest;
|
|
108
|
+
const obfuscateParams = (argv) => {
|
|
109
|
+
return argv
|
|
110
|
+
.join(' ')
|
|
111
|
+
.replace(/--(authorization [A-Z0-9]+)/gi, '--authorization *****')
|
|
112
|
+
.replace(/-(o [A-Z0-9-]+)/gi, '-o *****')
|
|
113
|
+
.replace(/--(organization-id [A-Z0-9-]+)/gi, '--organization-id *****')
|
|
114
|
+
.replace(/--(api-key [A-Z0-9]+)/gi, '--api-key *****');
|
|
115
|
+
};
|
|
116
|
+
exports.obfuscateParams = obfuscateParams;
|
|
117
|
+
const paramExists = (argv, param, paramAlias) => {
|
|
118
|
+
return argv.find((arg) => arg === param || arg === paramAlias);
|
|
119
|
+
};
|
|
120
|
+
exports.paramExists = paramExists;
|
|
121
|
+
const findParamValueFromArgs = (argv, param, paramAlias) => {
|
|
122
|
+
let paramAsValue;
|
|
123
|
+
argv.forEach((arg, index) => {
|
|
124
|
+
if (arg === param ||
|
|
125
|
+
(arg === paramAlias &&
|
|
126
|
+
argv[index + 1] !== undefined &&
|
|
127
|
+
argv[index + 1] !== null)) {
|
|
128
|
+
paramAsValue = argv[index + 1];
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
return paramAsValue;
|
|
132
|
+
};
|
|
133
|
+
exports.findParamValueFromArgs = findParamValueFromArgs;
|
|
134
|
+
const sha1Base64Value = (value) => {
|
|
135
|
+
return crypto.createHash('sha1').update(value).digest('base64');
|
|
136
|
+
};
|
|
137
|
+
exports.sha1Base64Value = sha1Base64Value;
|
package/dist/utils/commonApi.js
CHANGED
package/dist/utils/getConfig.js
CHANGED
|
@@ -3,15 +3,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.setConfigValues = exports.
|
|
6
|
+
exports.setConfigValues = exports.localConfig = void 0;
|
|
7
7
|
const conf_1 = __importDefault(require("conf"));
|
|
8
8
|
const localConfig = (name, version) => {
|
|
9
9
|
const config = new conf_1.default({
|
|
10
10
|
configName: name
|
|
11
11
|
});
|
|
12
12
|
config.set('version', version);
|
|
13
|
-
if (process.env.
|
|
14
|
-
config.set('
|
|
13
|
+
if (process.env.CONTRAST_CODSEC_CI) {
|
|
14
|
+
config.set('isCI', JSON.parse(process.env.CONTRAST_CODSEC_CI.toLowerCase()));
|
|
15
15
|
}
|
|
16
16
|
if (!config.has('host')) {
|
|
17
17
|
config.set('host', 'https://ce.contrastsecurity.com/');
|
|
@@ -19,11 +19,6 @@ const localConfig = (name, version) => {
|
|
|
19
19
|
return config;
|
|
20
20
|
};
|
|
21
21
|
exports.localConfig = localConfig;
|
|
22
|
-
const createConfigFromYaml = (yamlPath) => {
|
|
23
|
-
const yamlConfig = {};
|
|
24
|
-
return yamlConfig;
|
|
25
|
-
};
|
|
26
|
-
exports.createConfigFromYaml = createConfigFromYaml;
|
|
27
22
|
const setConfigValues = (config, values) => {
|
|
28
23
|
config.set('apiKey', values.apiKey);
|
|
29
24
|
config.set('organizationId', values.orgId);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const commandLineArgs = require('command-line-args');
|
|
3
|
-
const
|
|
3
|
+
const { sendTelemetryConfigAsConfObj } = require('../telemetry/telemetry');
|
|
4
|
+
const getCommandLineArgsCustom = async (contrastConf, command, parameterList, optionDefinitions) => {
|
|
4
5
|
try {
|
|
5
6
|
return commandLineArgs(optionDefinitions, {
|
|
6
7
|
argv: parameterList,
|
|
@@ -10,6 +11,7 @@ const getCommandLineArgsCustom = (parameterList, optionDefinitions) => {
|
|
|
10
11
|
});
|
|
11
12
|
}
|
|
12
13
|
catch (e) {
|
|
14
|
+
await sendTelemetryConfigAsConfObj(contrastConf, command, parameterList, 'FAILURE', 'undefined');
|
|
13
15
|
console.log(e.message.toString());
|
|
14
16
|
process.exit(1);
|
|
15
17
|
}
|
|
@@ -11,8 +11,14 @@ const millisToSeconds = millis => {
|
|
|
11
11
|
const sleep = ms => {
|
|
12
12
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
13
13
|
};
|
|
14
|
+
const timeOutError = (ms, reject) => {
|
|
15
|
+
return setTimeout(() => {
|
|
16
|
+
reject(new Error(`No input detected after 30s`));
|
|
17
|
+
}, ms);
|
|
18
|
+
};
|
|
14
19
|
module.exports = {
|
|
15
20
|
sendRequest: sendRequest,
|
|
16
21
|
sleep: sleep,
|
|
17
|
-
millisToSeconds: millisToSeconds
|
|
22
|
+
millisToSeconds: millisToSeconds,
|
|
23
|
+
timeOutError: timeOutError
|
|
18
24
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contrast/contrast",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.11",
|
|
4
4
|
"description": "Contrast Security's command line tool",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -23,8 +23,7 @@
|
|
|
23
23
|
"test": "jest --testPathIgnorePatterns=./test-integration/",
|
|
24
24
|
"test-int": "jest ./test-integration/",
|
|
25
25
|
"test-int-scan": "jest ./test-integration/scan",
|
|
26
|
-
"test-int-audit": "jest
|
|
27
|
-
"test-int-audit-experimental": "jest ./test-integration/audit/audit-experimental.spec.js",
|
|
26
|
+
"test-int-audit": "jest test-integration/audit/audit-int.spec.js",
|
|
28
27
|
"format": "prettier --write \"**/*.{ts,tsx,js,json,md,yml}\" .eslintrc.*",
|
|
29
28
|
"check-format": "prettier --check \"**/*.{ts,tsx,js,json,md,yml}\" .eslintrc.*",
|
|
30
29
|
"coverage-local": "nyc --reporter=text mocha './test/**/*.spec.js'",
|
|
@@ -1,72 +1,36 @@
|
|
|
1
1
|
const fs = require('fs')
|
|
2
2
|
const path = require('path')
|
|
3
3
|
const i18n = require('i18n')
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
* @return {string[]} List of filenames associated with a projects root
|
|
16
|
-
* directory or the name of the specific project file if that was provided to
|
|
17
|
-
* the 'file' parameter
|
|
18
|
-
*
|
|
19
|
-
* @throws {Error} If the project path doesn't exist
|
|
20
|
-
* @throws {Error} If the project path information can't be collected
|
|
21
|
-
* @throws {Error} If a non-file or non-directory inspected
|
|
22
|
-
*/
|
|
23
|
-
module.exports = exports = (analysis, next) => {
|
|
24
|
-
const { file, languageAnalysis } = analysis
|
|
25
|
-
try {
|
|
26
|
-
languageAnalysis.projectRootFilenames = getProjectRootFilenames(file)
|
|
27
|
-
} catch (err) {
|
|
28
|
-
next(err)
|
|
29
|
-
return
|
|
4
|
+
|
|
5
|
+
const getDirectoryFromPathGiven = file => {
|
|
6
|
+
let projectStats = getProjectStats(file)
|
|
7
|
+
|
|
8
|
+
if (projectStats.isFile()) {
|
|
9
|
+
let newPath = path.resolve(file)
|
|
10
|
+
return path.dirname(newPath)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (projectStats.isDirectory()) {
|
|
14
|
+
return file
|
|
30
15
|
}
|
|
31
|
-
next()
|
|
32
16
|
}
|
|
33
17
|
|
|
34
|
-
const
|
|
35
|
-
let projectStats = null
|
|
18
|
+
const getProjectStats = file => {
|
|
36
19
|
try {
|
|
37
|
-
|
|
20
|
+
//might not need this
|
|
21
|
+
if (file.endsWith('/')) {
|
|
22
|
+
file = file.slice(0, -1)
|
|
23
|
+
}
|
|
24
|
+
return fs.statSync(file)
|
|
38
25
|
} catch (err) {
|
|
39
26
|
throw new Error(
|
|
40
27
|
i18n.__('languageAnalysisProjectRootFileNameFailure', file) +
|
|
41
28
|
`${err.message}`
|
|
42
29
|
)
|
|
43
30
|
}
|
|
44
|
-
|
|
45
|
-
// Return the contents of a directory...
|
|
46
|
-
if (projectStats.isDirectory()) {
|
|
47
|
-
try {
|
|
48
|
-
return fs.readdirSync(file)
|
|
49
|
-
} catch (err) {
|
|
50
|
-
throw new Error(
|
|
51
|
-
i18n.__('languageAnalysisProjectRootFileNameReadError', file) +
|
|
52
|
-
`${err.message}`
|
|
53
|
-
)
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// If we are working with a file return it in a list as we do when we work
|
|
58
|
-
// with a directory...
|
|
59
|
-
if (projectStats.isFile()) {
|
|
60
|
-
return [path.basename(file)]
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Error out if we are working with something like a socket file or some
|
|
64
|
-
// other craziness...
|
|
65
|
-
throw new Error(
|
|
66
|
-
i18n.__('languageAnalysisProjectRootFileNameMissingError'),
|
|
67
|
-
file
|
|
68
|
-
)
|
|
69
31
|
}
|
|
70
32
|
|
|
71
|
-
|
|
72
|
-
|
|
33
|
+
module.exports = {
|
|
34
|
+
getProjectStats,
|
|
35
|
+
getDirectoryFromPathGiven: getDirectoryFromPathGiven
|
|
36
|
+
}
|