@contrast/contrast 1.0.4 → 1.0.7

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 (115) hide show
  1. package/.prettierignore +0 -3
  2. package/dist/audit/autodetection/autoDetectLanguage.js +32 -0
  3. package/dist/audit/catalogueApplication/catalogueApplication.js +2 -11
  4. package/dist/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +4 -2
  5. package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +2 -1
  6. package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +2 -1
  7. package/dist/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +2 -1
  8. package/dist/audit/languageAnalysisEngine/languageAnalysisFactory.js +6 -2
  9. package/dist/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +39 -1
  10. package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +69 -30
  11. package/dist/audit/languageAnalysisEngine/report/models/reportOutputModel.js +24 -0
  12. package/dist/audit/languageAnalysisEngine/report/models/reportSeverityModel.js +3 -1
  13. package/dist/audit/languageAnalysisEngine/report/models/severityCountModel.js +13 -0
  14. package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +2 -2
  15. package/dist/audit/languageAnalysisEngine/report/utils/reportUtils.js +56 -45
  16. package/dist/audit/languageAnalysisEngine/sendSnapshot.js +65 -17
  17. package/dist/commands/audit/auditConfig.js +8 -2
  18. package/dist/commands/audit/auditController.js +9 -3
  19. package/dist/commands/audit/processAudit.js +1 -1
  20. package/dist/commands/scan/processScan.js +7 -4
  21. package/dist/commands/scan/sca/scaAnalysis.js +60 -0
  22. package/dist/common/HTTPClient.js +50 -16
  23. package/dist/common/errorHandling.js +11 -16
  24. package/dist/common/versionChecker.js +1 -1
  25. package/dist/constants/constants.js +24 -2
  26. package/dist/constants/locales.js +31 -36
  27. package/dist/constants.js +20 -0
  28. package/dist/lambda/analytics.js +11 -0
  29. package/dist/lambda/lambda.js +35 -4
  30. package/dist/lambda/types.js +13 -0
  31. package/dist/scaAnalysis/common/formatMessage.js +35 -0
  32. package/dist/scaAnalysis/common/treeUpload.js +29 -0
  33. package/dist/scaAnalysis/go/goAnalysis.js +17 -0
  34. package/dist/scaAnalysis/go/goParseDeps.js +158 -0
  35. package/dist/scaAnalysis/go/goReadDepFile.js +23 -0
  36. package/dist/scaAnalysis/java/analysis.js +105 -0
  37. package/dist/scaAnalysis/java/index.js +18 -0
  38. package/dist/scaAnalysis/java/javaBuildDepsParser.js +339 -0
  39. package/dist/scaAnalysis/python/analysis.js +41 -0
  40. package/dist/scaAnalysis/python/index.js +10 -0
  41. package/dist/scaAnalysis/ruby/analysis.js +226 -0
  42. package/dist/scaAnalysis/ruby/index.js +10 -0
  43. package/dist/scan/autoDetection.js +50 -1
  44. package/dist/scan/fileUtils.js +80 -1
  45. package/dist/scan/formatScanOutput.js +213 -0
  46. package/dist/scan/help.js +3 -1
  47. package/dist/scan/models/groupedResultsModel.js +2 -1
  48. package/dist/scan/models/scanResultsModel.js +3 -1
  49. package/dist/scan/populateProjectIdAndProjectName.js +2 -1
  50. package/dist/scan/scan.js +6 -99
  51. package/dist/scan/scanConfig.js +6 -1
  52. package/dist/scan/scanController.js +26 -7
  53. package/dist/scan/scanResults.js +20 -20
  54. package/dist/utils/commonApi.js +4 -1
  55. package/dist/utils/oraWrapper.js +5 -1
  56. package/package.json +12 -7
  57. package/src/audit/autodetection/autoDetectLanguage.ts +40 -0
  58. package/src/audit/catalogueApplication/catalogueApplication.js +3 -16
  59. package/src/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +11 -8
  60. package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +2 -1
  61. package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +2 -1
  62. package/src/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +2 -1
  63. package/src/audit/languageAnalysisEngine/languageAnalysisFactory.js +17 -5
  64. package/src/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +76 -3
  65. package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.ts +122 -40
  66. package/src/audit/languageAnalysisEngine/report/models/reportLibraryModel.ts +3 -3
  67. package/src/audit/languageAnalysisEngine/report/models/reportListModel.ts +15 -11
  68. package/src/audit/languageAnalysisEngine/report/models/reportOutputModel.ts +29 -0
  69. package/src/audit/languageAnalysisEngine/report/models/reportSeverityModel.ts +12 -3
  70. package/src/audit/languageAnalysisEngine/report/models/severityCountModel.ts +16 -0
  71. package/src/audit/languageAnalysisEngine/report/reportingFeature.ts +3 -3
  72. package/src/audit/languageAnalysisEngine/report/utils/reportUtils.ts +87 -65
  73. package/src/audit/languageAnalysisEngine/sendSnapshot.js +78 -25
  74. package/src/commands/audit/auditConfig.ts +12 -3
  75. package/src/commands/audit/auditController.ts +9 -3
  76. package/src/commands/audit/processAudit.ts +4 -1
  77. package/src/commands/scan/processScan.js +10 -4
  78. package/src/commands/scan/sca/scaAnalysis.js +83 -0
  79. package/src/common/HTTPClient.js +65 -25
  80. package/src/common/errorHandling.ts +14 -22
  81. package/src/common/versionChecker.ts +1 -1
  82. package/src/constants/constants.js +24 -2
  83. package/src/constants/locales.js +33 -50
  84. package/src/constants.js +22 -0
  85. package/src/lambda/analytics.ts +9 -0
  86. package/src/lambda/arn.ts +2 -1
  87. package/src/lambda/lambda.ts +37 -17
  88. package/src/lambda/types.ts +35 -0
  89. package/src/lambda/utils.ts +2 -7
  90. package/src/scaAnalysis/common/formatMessage.js +38 -0
  91. package/src/scaAnalysis/common/treeUpload.js +30 -0
  92. package/src/scaAnalysis/go/goAnalysis.js +19 -0
  93. package/src/scaAnalysis/go/goParseDeps.js +203 -0
  94. package/src/scaAnalysis/go/goReadDepFile.js +32 -0
  95. package/src/scaAnalysis/java/analysis.js +142 -0
  96. package/src/scaAnalysis/java/index.js +21 -0
  97. package/src/scaAnalysis/java/javaBuildDepsParser.js +404 -0
  98. package/src/scaAnalysis/python/analysis.js +48 -0
  99. package/src/scaAnalysis/python/index.js +11 -0
  100. package/src/scaAnalysis/ruby/analysis.js +282 -0
  101. package/src/scaAnalysis/ruby/index.js +11 -0
  102. package/src/scan/autoDetection.js +58 -1
  103. package/src/scan/fileUtils.js +99 -1
  104. package/src/scan/formatScanOutput.ts +249 -0
  105. package/src/scan/help.js +3 -1
  106. package/src/scan/models/groupedResultsModel.ts +7 -5
  107. package/src/scan/models/resultContentModel.ts +2 -2
  108. package/src/scan/models/scanResultsModel.ts +5 -2
  109. package/src/scan/populateProjectIdAndProjectName.js +3 -1
  110. package/src/scan/scan.ts +8 -136
  111. package/src/scan/scanConfig.js +5 -1
  112. package/src/scan/scanController.js +30 -10
  113. package/src/scan/scanResults.js +31 -18
  114. package/src/utils/commonApi.js +4 -1
  115. package/src/utils/oraWrapper.js +6 -1
@@ -0,0 +1,282 @@
1
+ const fs = require('fs')
2
+
3
+ const readAndParseGemfile = projectPath => {
4
+ const fileName = filePathForWindows(projectPath + '/Gemfile')
5
+ const gemFile = fs.readFileSync(fileName, 'utf8')
6
+ const rubyArray = gemFile.split('\n')
7
+
8
+ let filteredRubyDep = rubyArray.filter(element => {
9
+ return (
10
+ !element.includes('#') &&
11
+ element.includes('gem') &&
12
+ !element.includes('source')
13
+ )
14
+ })
15
+
16
+ for (let i = 0; i < filteredRubyDep.length; i++) {
17
+ filteredRubyDep[i] = filteredRubyDep[i].trim()
18
+ }
19
+
20
+ return filteredRubyDep
21
+ }
22
+
23
+ const readAndParseGemLockFile = projectPath => {
24
+ const fileName = filePathForWindows(projectPath + '/Gemfile.lock')
25
+ const lockFile = fs.readFileSync(fileName, 'utf8')
26
+ const dependencyRegEx = /^\s*([A-Za-z0-9.!@#$%\-^&*_+]*)\s*(\((.*?)\))/
27
+
28
+ const lines = lockFile.split('\n')
29
+
30
+ return {
31
+ dependencies: getDirectDependencies(lines, dependencyRegEx),
32
+ runtimeDetails: getLockFileRuntimeInfo(lines),
33
+ sources: getSourceArray(lines, dependencyRegEx)
34
+ }
35
+ }
36
+
37
+ const nonDependencyKeys = (line, sourceObject) => {
38
+ const GEMFILE_KEY_VALUE = /^\s*([^:(]*)\s*\s*(.*)/
39
+ let parts = GEMFILE_KEY_VALUE.exec(line)
40
+ let key = parts[1].trim()
41
+ let value = parts[2] || ''
42
+
43
+ sourceObject[key] = value
44
+ return sourceObject
45
+ }
46
+
47
+ const populateResolveAndPlatform = (version, sourceObject) => {
48
+ const depArr = version.split('-')
49
+ sourceObject.resolved = depArr[0]
50
+ sourceObject.platform = depArr.length > 1 ? depArr[1] : 'UNSPECIFIED'
51
+ return sourceObject
52
+ }
53
+
54
+ const isUpperCase = str => {
55
+ return str === str.toUpperCase()
56
+ }
57
+
58
+ const getDirectDependencies = (lines, dependencyRegEx) => {
59
+ const dependencies = {}
60
+
61
+ let depIndex = 0
62
+ for (let i = 0; i < lines.length; i++) {
63
+ if (lines[i] === 'DEPENDENCIES') {
64
+ depIndex = i
65
+ }
66
+ }
67
+ const getDepArray = lines.slice(depIndex)
68
+
69
+ for (let j = 1; j < getDepArray.length; j++) {
70
+ const element = getDepArray[j]
71
+ if (!isUpperCase(element)) {
72
+ const isDependencyWithVersion = dependencyRegEx.test(element)
73
+ if (isDependencyWithVersion) {
74
+ const dependency = dependencyRegEx.exec(element)
75
+ let name = dependency[1]
76
+ name = name.replace('!', '')
77
+ dependencies[name.trim()] = dependency[3]
78
+ } else {
79
+ let name = element
80
+ name = name.replace('!', ' ')
81
+ dependencies[name.trim()] = 'UNSPECIFIED'
82
+ }
83
+ }
84
+ }
85
+
86
+ return dependencies
87
+ }
88
+
89
+ const getLockFileRuntimeInfo = lines => {
90
+ let rubVersionIndex = 0
91
+ for (let i = 0; i < lines.length; i++) {
92
+ if (lines[i] === 'RUBY VERSION') {
93
+ rubVersionIndex = i
94
+ break
95
+ }
96
+ }
97
+
98
+ const runtimeDetails = {}
99
+ if (rubVersionIndex !== 0) {
100
+ const getRubyVersionArray = lines.slice(rubVersionIndex)
101
+
102
+ for (let element of getRubyVersionArray) {
103
+ if (!isUpperCase(element)) {
104
+ runtimeDetails['version'] = getVersion(element)
105
+ runtimeDetails['patchLevel'] = getPatchLevel(element)
106
+
107
+ if (element.includes('engine')) {
108
+ let splitElement = element.split(' ')
109
+ runtimeDetails[splitElement[0]] = splitElement[1]
110
+ }
111
+ }
112
+ }
113
+ }
114
+ return runtimeDetails
115
+ }
116
+
117
+ const getVersion = element => {
118
+ const versionRegex = /^([ruby\s0-9.*]+)/
119
+ if (versionRegex.test(element)) {
120
+ let version = versionRegex.exec(element)[0]
121
+
122
+ if (version.includes('ruby')) {
123
+ return trimWhiteSpace(version.replace('ruby', ''))
124
+ }
125
+ }
126
+ }
127
+
128
+ const getPatchLevel = element => {
129
+ const patchLevelRegex = /(p\d+)/
130
+ if (patchLevelRegex.test(element)) {
131
+ return patchLevelRegex.exec(element)[0]
132
+ }
133
+ }
134
+
135
+ const formatSourceArr = sourceArr => {
136
+ return sourceArr.map(element => {
137
+ if (element.sourceType === 'GIT') {
138
+ delete element.specs
139
+ }
140
+
141
+ if (element.sourceType === 'GEM') {
142
+ delete element.branch
143
+ delete element.revision
144
+ delete element.depthLevel
145
+ delete element.specs
146
+ }
147
+
148
+ if (element.sourceType === 'PATH') {
149
+ delete element.branch
150
+ delete element.revision
151
+ delete element.depthLevel
152
+ delete element.specs
153
+ delete element.platform
154
+ }
155
+ return element
156
+ })
157
+ }
158
+
159
+ const getSourceArray = (lines, dependencyRegEx) => {
160
+ const sourceObject = {
161
+ dependencies: {}
162
+ }
163
+
164
+ const whitespaceRegx = /^(\s*)/
165
+ let index = 0
166
+
167
+ let line = 0
168
+ const sources = []
169
+ while ((line = lines[index++]) !== undefined) {
170
+ let currentWS = whitespaceRegx.exec(line)[1].length
171
+ if (!line.includes(' bundler (')) {
172
+ if (currentWS === 0 && !line.includes(':') && line !== '') {
173
+ sourceObject.sourceType = line
174
+ }
175
+
176
+ if (currentWS !== 0 && line.includes(':')) {
177
+ nonDependencyKeys(line, sourceObject)
178
+ }
179
+
180
+ if (currentWS > 2) {
181
+ let nexlineWS = whitespaceRegx.exec(lines[index])[1].length
182
+ sourceObject.dependencies = buildSourceDependencyWithVersion(
183
+ whitespaceRegx,
184
+ dependencyRegEx,
185
+ line,
186
+ currentWS,
187
+ sourceObject.name,
188
+ sourceObject.dependencies
189
+ )
190
+
191
+ if (currentWS === 4 && sourceObject.depthLevel === undefined) {
192
+ const dependency = dependencyRegEx.exec(line)
193
+ sourceObject.name = dependency[1]
194
+ sourceObject.depthLevel = currentWS
195
+ populateResolveAndPlatform(dependency[3], sourceObject)
196
+ }
197
+
198
+ if (currentWS === 4 && sourceObject.depthLevel) {
199
+ // create new Parent
200
+ const dependency = dependencyRegEx.exec(line)
201
+ sourceObject.name = dependency[1]
202
+ sourceObject.depthLevel = currentWS
203
+ populateResolveAndPlatform(dependency[3], sourceObject)
204
+ }
205
+
206
+ if (
207
+ (currentWS === 4 && nexlineWS === 4) ||
208
+ (currentWS === 6 && nexlineWS === 4) ||
209
+ nexlineWS === ''
210
+ ) {
211
+ let newObj = {}
212
+ newObj = JSON.parse(JSON.stringify(sourceObject))
213
+ sources.push(newObj)
214
+ sourceObject.dependencies = {}
215
+ }
216
+ }
217
+ }
218
+ }
219
+ return formatSourceArr(sources)
220
+ }
221
+
222
+ const buildSourceDependencyWithVersion = (
223
+ whitespaceRegx,
224
+ dependencyRegEx,
225
+ line,
226
+ currentWhiteSpace,
227
+ name,
228
+ dependencies
229
+ ) => {
230
+ const isDependencyWithVersion = dependencyRegEx.test(line)
231
+
232
+ if (currentWhiteSpace === 6) {
233
+ const dependency = dependencyRegEx.exec(line)
234
+ if (isDependencyWithVersion) {
235
+ if (name !== dependency[1]) {
236
+ dependencies[dependency[1]] = dependency[3]
237
+ }
238
+ } else {
239
+ dependencies[line.trim()] = 'UNSPECIFIED'
240
+ }
241
+ }
242
+
243
+ return dependencies
244
+ }
245
+
246
+ const getRubyDeps = config => {
247
+ try {
248
+ const parsedGem = readAndParseGemfile(config.projectPath)
249
+ const parsedLock = readAndParseGemLockFile(config.projectPath)
250
+
251
+ return { gemfilesDependanceies: parsedGem, gemfileLock: parsedLock }
252
+ } catch (err) {
253
+ console.log(err.message)
254
+ process.exit(1)
255
+ }
256
+ }
257
+
258
+ const trimWhiteSpace = string => {
259
+ return string.replace(/\s+/g, '')
260
+ }
261
+
262
+ const filePathForWindows = path => {
263
+ if (process.platform === 'win32') {
264
+ path = path.replace(/\//g, '\\')
265
+ }
266
+ return path
267
+ }
268
+
269
+ module.exports = {
270
+ getRubyDeps,
271
+ readAndParseGemfile,
272
+ readAndParseGemLockFile,
273
+ nonDependencyKeys,
274
+ populateResolveAndPlatform,
275
+ isUpperCase,
276
+ getDirectDependencies,
277
+ getLockFileRuntimeInfo,
278
+ getVersion,
279
+ getPatchLevel,
280
+ formatSourceArr,
281
+ getSourceArray
282
+ }
@@ -0,0 +1,11 @@
1
+ const { getRubyDeps } = require('./analysis')
2
+ const { createRubyTSMessage } = require('../common/formatMessage')
3
+
4
+ const rubyAnalysis = (config, languageFiles) => {
5
+ const rubyDeps = getRubyDeps(config, languageFiles.RUBY)
6
+ return createRubyTSMessage(rubyDeps)
7
+ }
8
+
9
+ module.exports = {
10
+ rubyAnalysis
11
+ }
@@ -1,5 +1,7 @@
1
1
  const i18n = require('i18n')
2
2
  const fileFinder = require('./fileUtils')
3
+ const languageResolver = require('../audit/languageAnalysisEngine/reduceIdentifiedLanguages')
4
+ const rootFile = require('../audit/languageAnalysisEngine/getProjectRootFilenames')
3
5
 
4
6
  const autoDetectFileAndLanguage = async configToUse => {
5
7
  const entries = await fileFinder.findFile()
@@ -12,6 +14,11 @@ const autoDetectFileAndLanguage = async configToUse => {
12
14
  process.exit(1)
13
15
  }
14
16
 
17
+ if (fileFinder.fileIsEmpty(entries[0])) {
18
+ console.log(i18n.__('scanFileIsEmpty'))
19
+ process.exit(1)
20
+ }
21
+
15
22
  configToUse.file = entries[0]
16
23
  if (configToUse.name === undefined) {
17
24
  configToUse.name = entries[0]
@@ -21,6 +28,38 @@ const autoDetectFileAndLanguage = async configToUse => {
21
28
  }
22
29
  }
23
30
 
31
+ const autoDetectAuditFilesAndLanguages = async () => {
32
+ let languagesFound = []
33
+ console.log(i18n.__('searchingAuditFileDirectory', process.cwd()))
34
+
35
+ await fileFinder.findFilesJava(languagesFound)
36
+ await fileFinder.findFilesJavascript(languagesFound)
37
+ await fileFinder.findFilesPython(languagesFound)
38
+ await fileFinder.findFilesGo(languagesFound)
39
+ await fileFinder.findFilesPhp(languagesFound)
40
+ await fileFinder.findFilesRuby(languagesFound)
41
+
42
+ if (languagesFound.length === 1) {
43
+ return languagesFound
44
+ } else {
45
+ console.log(
46
+ 'found multiple languages, please specify one using --file to run SCA analysis'
47
+ )
48
+ }
49
+ }
50
+
51
+ const manualDetectAuditFilesAndLanguages = projectPath => {
52
+ let projectRootFilenames = rootFile.getProjectRootFilenames(projectPath)
53
+ let identifiedLanguages =
54
+ languageResolver.deduceLanguageScaAnalysis(projectRootFilenames)
55
+
56
+ if (Object.keys(identifiedLanguages).length === 0) {
57
+ console.log(i18n.__('languageAnalysisNoLanguage', projectPath))
58
+ return []
59
+ }
60
+ return [identifiedLanguages]
61
+ }
62
+
24
63
  const hasWhiteSpace = s => {
25
64
  const filename = s.split('/').pop()
26
65
  return filename.indexOf(' ') >= 0
@@ -42,7 +81,25 @@ const errorOnFileDetection = entries => {
42
81
  process.exit(1)
43
82
  }
44
83
 
84
+ const errorOnAuditFileDetection = entries => {
85
+ if (entries.length > 1) {
86
+ console.log(i18n.__('searchingDirectoryScan'))
87
+ for (let file in entries) {
88
+ console.log('-', entries[file])
89
+ }
90
+ console.log('')
91
+ console.log(i18n.__('specifyFileAuditNotFound'))
92
+ } else {
93
+ console.log(i18n.__('noFileFoundScan'))
94
+ console.log('')
95
+ console.log(i18n.__('specifyFileAuditNotFound'))
96
+ }
97
+ }
98
+
45
99
  module.exports = {
46
100
  autoDetectFileAndLanguage,
47
- errorOnFileDetection
101
+ errorOnFileDetection,
102
+ autoDetectAuditFilesAndLanguages,
103
+ errorOnAuditFileDetection,
104
+ manualDetectAuditFilesAndLanguages
48
105
  }
@@ -11,6 +11,90 @@ const findFile = async () => {
11
11
  })
12
12
  }
13
13
 
14
+ const findFilesJava = async languagesFound => {
15
+ const result = await fg(
16
+ ['**/pom.xml', '**/build.gradle', '**/build.gradle.kts'],
17
+ {
18
+ dot: false,
19
+ deep: 1,
20
+ onlyFiles: true
21
+ }
22
+ )
23
+
24
+ if (result.length > 0) {
25
+ return languagesFound.push({ JAVA: result })
26
+ }
27
+ return languagesFound
28
+ }
29
+
30
+ const findFilesJavascript = async languagesFound => {
31
+ const result = await fg(
32
+ ['**/package.json', '**/yarn.lock', '**/package.lock.json'],
33
+ {
34
+ dot: false,
35
+ deep: 1,
36
+ onlyFiles: true
37
+ }
38
+ )
39
+
40
+ if (result.length > 0) {
41
+ return languagesFound.push({ JAVASCRIPT: result })
42
+ }
43
+ return languagesFound
44
+ }
45
+
46
+ const findFilesPython = async languagesFound => {
47
+ const result = await fg(['**/Pipfile.lock', '**/Pipfile'], {
48
+ dot: false,
49
+ deep: 3,
50
+ onlyFiles: true
51
+ })
52
+
53
+ if (result.length > 0) {
54
+ return languagesFound.push({ PYTHON: result })
55
+ }
56
+ return languagesFound
57
+ }
58
+
59
+ const findFilesGo = async languagesFound => {
60
+ const result = await fg(['**/go.mod'], {
61
+ dot: false,
62
+ deep: 3,
63
+ onlyFiles: true
64
+ })
65
+
66
+ if (result.length > 0) {
67
+ return languagesFound.push({ GO: result })
68
+ }
69
+ return languagesFound
70
+ }
71
+
72
+ const findFilesRuby = async languagesFound => {
73
+ const result = await fg(['**/Gemfile', '**/Gemfile.lock'], {
74
+ dot: false,
75
+ deep: 3,
76
+ onlyFiles: true
77
+ })
78
+
79
+ if (result.length > 0) {
80
+ return languagesFound.push({ RUBY: result })
81
+ }
82
+ return languagesFound
83
+ }
84
+
85
+ const findFilesPhp = async languagesFound => {
86
+ const result = await fg(['**/composer.json', '**/composer.lock'], {
87
+ dot: false,
88
+ deep: 3,
89
+ onlyFiles: true
90
+ })
91
+
92
+ if (result.length > 0) {
93
+ return languagesFound.push({ PHP: result })
94
+ }
95
+ return languagesFound
96
+ }
97
+
14
98
  const checkFilePermissions = file => {
15
99
  let readableFile = false
16
100
  try {
@@ -26,8 +110,22 @@ const fileExists = path => {
26
110
  return fs.existsSync(path)
27
111
  }
28
112
 
113
+ const fileIsEmpty = path => {
114
+ if (fileExists(path) && checkFilePermissions(path)) {
115
+ return fs.readFileSync(path).length === 0
116
+ }
117
+ return false
118
+ }
119
+
29
120
  module.exports = {
30
121
  findFile,
31
122
  fileExists,
32
- checkFilePermissions
123
+ checkFilePermissions,
124
+ findFilesJava,
125
+ findFilesJavascript,
126
+ findFilesPython,
127
+ findFilesGo,
128
+ findFilesPhp,
129
+ findFilesRuby,
130
+ fileIsEmpty
33
131
  }