@cdxgen/cdxgen 13.3.0 → 13.5.0

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 (372) hide show
  1. package/README.md +12 -9
  2. package/bin/cdxgen-secure.js +15 -0
  3. package/bin/cdxgen.js +115 -31
  4. package/bin/evinse.js +23 -1
  5. package/bin/hbom.js +15 -7
  6. package/bin/repl.js +115 -0
  7. package/bin/sign.js +45 -15
  8. package/bin/tracebom.js +5 -1
  9. package/bin/validate.js +84 -18
  10. package/bin/verify.js +155 -86
  11. package/data/cbomosdb-queries.json +13 -1
  12. package/data/component-tags.json +8 -0
  13. package/data/helpers/init.gradle +46 -21
  14. package/data/queries-darwin.json +25 -1
  15. package/data/queries-win.json +19 -1
  16. package/data/queries.json +41 -0
  17. package/data/remediations.json +344 -1
  18. package/data/rules/cbom-security.yaml +235 -4
  19. package/data/rules/dependency-sources.yaml +67 -0
  20. package/data/rules/go-binaries.yaml +46 -0
  21. package/data/rules/golem-go.yaml +80 -0
  22. package/data/rules/hbom-compliance.yaml +40 -22
  23. package/data/rules/hbom-performance.yaml +7 -1
  24. package/data/rules/host-topology.yaml +1 -1
  25. package/data/rules/obom-runtime.yaml +31 -2
  26. package/data/rules/php-runtime.yaml +143 -0
  27. package/data/rules/scala-evidence.yaml +115 -0
  28. package/lib/audit/index.js +52 -6
  29. package/lib/cli/bomAssembly.js +28 -3
  30. package/lib/cli/cliOptions.js +110 -3
  31. package/lib/cli/index.js +186 -58
  32. package/lib/cli/jsBom.js +50 -29
  33. package/lib/cli/jvmBom.js +779 -146
  34. package/lib/cli/managedBom.js +1021 -261
  35. package/lib/cli/nativeBom.js +364 -58
  36. package/lib/core/activity.js +12 -0
  37. package/lib/core/env.js +47 -17
  38. package/lib/core/fs.js +31 -21
  39. package/lib/core/httpClient.js +233 -69
  40. package/lib/core/pluginRun.js +184 -0
  41. package/lib/core/processTree.js +100 -0
  42. package/lib/core/projectConfig.js +1 -0
  43. package/lib/core/projectTooling.js +97 -0
  44. package/lib/core/propertySanitizer.js +72 -0
  45. package/lib/core/runState.js +39 -0
  46. package/lib/core/toml.js +72 -0
  47. package/lib/ecosystems/asarutils.js +4 -2
  48. package/lib/ecosystems/bunutils.js +5 -7
  49. package/lib/ecosystems/cargoCache.js +231 -8
  50. package/lib/ecosystems/cmakeResolver.js +10 -21
  51. package/lib/ecosystems/cppBuildContext.js +631 -0
  52. package/lib/ecosystems/cppEvidence.js +337 -22
  53. package/lib/ecosystems/cppIncludeResolver.js +294 -0
  54. package/lib/ecosystems/denoutils.js +93 -66
  55. package/lib/ecosystems/ecosystems.js +1967 -788
  56. package/lib/ecosystems/golem.js +578 -18
  57. package/lib/ecosystems/gradleutils.js +340 -46
  58. package/lib/ecosystems/jsEvidence.js +85 -24
  59. package/lib/ecosystems/kosi.js +21 -4
  60. package/lib/ecosystems/npmutils.js +64 -0
  61. package/lib/ecosystems/parsers-dotnet.js +668 -153
  62. package/lib/ecosystems/parsers-elm.js +46 -28
  63. package/lib/ecosystems/parsers-gleam.js +3 -4
  64. package/lib/ecosystems/parsers-go.js +1283 -297
  65. package/lib/ecosystems/parsers-js.js +92 -26
  66. package/lib/ecosystems/parsers-julia.js +2 -3
  67. package/lib/ecosystems/parsers-jvm.js +463 -29
  68. package/lib/ecosystems/parsers-misc.js +405 -93
  69. package/lib/ecosystems/parsers-python.js +152 -20
  70. package/lib/ecosystems/parsers-rust.js +4 -4
  71. package/lib/ecosystems/parsers-terraform.js +1573 -19
  72. package/lib/ecosystems/pythonutils.js +102 -6
  73. package/lib/ecosystems/remote/huggingface.js +3 -0
  74. package/lib/ecosystems/rubyutils.js +73 -20
  75. package/lib/ecosystems/rusi.js +32 -9
  76. package/lib/ecosystems/sbtutils.js +243 -187
  77. package/lib/ecosystems/scalacliutils.js +343 -0
  78. package/lib/ecosystems/scalasem.js +2620 -0
  79. package/lib/ecosystems/terraformRegistry.js +288 -0
  80. package/lib/ecosystems/utils.js +2 -0
  81. package/lib/ecosystems/vendoredCode.js +156 -0
  82. package/lib/evinser/evinser.js +695 -78
  83. package/lib/evinser/swiftsem.js +68 -5
  84. package/lib/helpers/agenticToolutils.js +2 -2
  85. package/lib/helpers/bomSigner.js +576 -128
  86. package/lib/inventory/agentSkillSpec.js +17 -0
  87. package/lib/inventory/aiCollector.js +4 -1
  88. package/lib/inventory/analyzer.js +110 -127
  89. package/lib/inventory/apkInstalledDb.js +243 -0
  90. package/lib/inventory/atomUtils.js +204 -48
  91. package/lib/inventory/auditCategories.js +10 -3
  92. package/lib/inventory/buildToolRateLimit.js +144 -0
  93. package/lib/inventory/cacheCommands.js +2 -1
  94. package/lib/inventory/cacheDir.js +52 -9
  95. package/lib/inventory/certificates.js +2371 -0
  96. package/lib/inventory/cmakeBuildDirs.js +254 -0
  97. package/lib/inventory/communityAiConfigParser.js +4 -9
  98. package/lib/inventory/deps.js +507 -128
  99. package/lib/inventory/display.js +200 -3
  100. package/lib/inventory/dosai.js +747 -101
  101. package/lib/inventory/dosaiParsers.js +310 -15
  102. package/lib/inventory/dynamic.js +96 -8
  103. package/lib/inventory/envcontext.js +168 -5
  104. package/lib/inventory/evidenceUtils.js +590 -132
  105. package/lib/inventory/fetchBatch.js +574 -38
  106. package/lib/inventory/fetchDiskCache.js +597 -0
  107. package/lib/inventory/forgeEnricher.js +14 -5
  108. package/lib/inventory/formulationParsers.js +3 -2
  109. package/lib/inventory/goBuildInfo.js +140 -0
  110. package/lib/inventory/hbom.js +67 -7
  111. package/lib/inventory/hbomAnalysis.js +16 -0
  112. package/lib/inventory/hostTopology.js +21 -0
  113. package/lib/inventory/jvmLocalRepos.js +917 -0
  114. package/lib/inventory/mcpConfigParser.js +2 -3
  115. package/lib/inventory/osPackagePurl.js +244 -0
  116. package/lib/inventory/osPackageResolver.js +89 -87
  117. package/lib/inventory/osinfo.js +79 -31
  118. package/lib/inventory/osqueryTransform.js +114 -5
  119. package/lib/inventory/parentSelection.js +146 -0
  120. package/lib/inventory/phpBuildInfo.js +487 -0
  121. package/lib/inventory/phpHostProbe.js +641 -0
  122. package/lib/inventory/rootfsCerts.js +426 -0
  123. package/lib/inventory/rustFormulationParser.js +3 -4
  124. package/lib/inventory/scalaCoords.js +153 -0
  125. package/lib/inventory/source.js +215 -11
  126. package/lib/inventory/spdx.js +245 -0
  127. package/lib/inventory/traceRunner.js +93 -8
  128. package/lib/inventory/tracedCrypto.js +423 -0
  129. package/lib/managers/binary.js +529 -183
  130. package/lib/managers/docker.js +199 -44
  131. package/lib/managers/oci.js +24 -2
  132. package/lib/parsers/cmakeCache.js +69 -0
  133. package/lib/parsers/cmakeLists.js +16 -2
  134. package/lib/parsers/cmakePresets.js +400 -0
  135. package/lib/parsers/compileCommands.js +557 -0
  136. package/lib/parsers/email.js +277 -0
  137. package/lib/parsers/largeJson.js +34 -2
  138. package/lib/parsers/strictJson.js +322 -0
  139. package/lib/parsers/terraformConfig.js +1073 -0
  140. package/lib/parsers/terraformSource.js +652 -0
  141. package/lib/server/server.js +209 -1
  142. package/lib/stages/postgen/annotator.js +17 -1
  143. package/lib/stages/postgen/introspection/markers.js +1 -1
  144. package/lib/stages/postgen/introspection/reflect.js +4 -1
  145. package/lib/stages/postgen/postgen.js +20 -6
  146. package/lib/stages/postgen/ruleEngine.js +58 -1
  147. package/lib/stages/postgen/specVersionCompat.js +62 -0
  148. package/lib/stages/pregen/pregen.js +117 -5
  149. package/lib/validator/bomValidator.js +26 -5
  150. package/lib/validator/generated/runtime.mjs +13 -0
  151. package/lib/validator/generated/validate-1.6.mjs +26 -7
  152. package/lib/validator/generated/validate-1.7.mjs +31 -12
  153. package/lib/validator/generated/validate-2.0.mjs +30 -11
  154. package/lib/validator/index.js +25 -10
  155. package/lib/validator/reporters/json.js +1 -0
  156. package/package.json +23 -23
  157. package/types/bin/cdxgen-secure.d.ts +3 -0
  158. package/types/bin/cdxgen-secure.d.ts.map +1 -0
  159. package/types/bin/repl.d.ts.map +1 -1
  160. package/types/lib/audit/index.d.ts.map +1 -1
  161. package/types/lib/cli/bomAssembly.d.ts +9 -2
  162. package/types/lib/cli/bomAssembly.d.ts.map +1 -1
  163. package/types/lib/cli/cliOptions.d.ts +43 -0
  164. package/types/lib/cli/cliOptions.d.ts.map +1 -1
  165. package/types/lib/cli/index.d.ts.map +1 -1
  166. package/types/lib/cli/jsBom.d.ts.map +1 -1
  167. package/types/lib/cli/jvmBom.d.ts +44 -1
  168. package/types/lib/cli/jvmBom.d.ts.map +1 -1
  169. package/types/lib/cli/managedBom.d.ts +7 -4
  170. package/types/lib/cli/managedBom.d.ts.map +1 -1
  171. package/types/lib/cli/nativeBom.d.ts +3 -1
  172. package/types/lib/cli/nativeBom.d.ts.map +1 -1
  173. package/types/lib/core/activity.d.ts.map +1 -1
  174. package/types/lib/core/env.d.ts +27 -2
  175. package/types/lib/core/env.d.ts.map +1 -1
  176. package/types/lib/core/fs.d.ts.map +1 -1
  177. package/types/lib/core/httpClient.d.ts +13 -8
  178. package/types/lib/core/httpClient.d.ts.map +1 -1
  179. package/types/lib/core/pluginRun.d.ts +97 -0
  180. package/types/lib/core/pluginRun.d.ts.map +1 -0
  181. package/types/lib/core/processTree.d.ts +36 -0
  182. package/types/lib/core/processTree.d.ts.map +1 -0
  183. package/types/lib/core/projectConfig.d.ts.map +1 -1
  184. package/types/lib/core/projectTooling.d.ts +41 -0
  185. package/types/lib/core/projectTooling.d.ts.map +1 -0
  186. package/types/lib/core/propertySanitizer.d.ts +26 -0
  187. package/types/lib/core/propertySanitizer.d.ts.map +1 -1
  188. package/types/lib/core/runState.d.ts +29 -0
  189. package/types/lib/core/runState.d.ts.map +1 -0
  190. package/types/lib/core/toml.d.ts +20 -0
  191. package/types/lib/core/toml.d.ts.map +1 -0
  192. package/types/lib/ecosystems/asarutils.d.ts.map +1 -1
  193. package/types/lib/ecosystems/bunutils.d.ts.map +1 -1
  194. package/types/lib/ecosystems/cargoCache.d.ts +12 -0
  195. package/types/lib/ecosystems/cargoCache.d.ts.map +1 -1
  196. package/types/lib/ecosystems/cmakeResolver.d.ts +5 -3
  197. package/types/lib/ecosystems/cmakeResolver.d.ts.map +1 -1
  198. package/types/lib/ecosystems/cppBuildContext.d.ts +55 -0
  199. package/types/lib/ecosystems/cppBuildContext.d.ts.map +1 -0
  200. package/types/lib/ecosystems/cppEvidence.d.ts +19 -3
  201. package/types/lib/ecosystems/cppEvidence.d.ts.map +1 -1
  202. package/types/lib/ecosystems/cppIncludeResolver.d.ts +92 -0
  203. package/types/lib/ecosystems/cppIncludeResolver.d.ts.map +1 -0
  204. package/types/lib/ecosystems/denoutils.d.ts +9 -3
  205. package/types/lib/ecosystems/denoutils.d.ts.map +1 -1
  206. package/types/lib/ecosystems/ecosystems.d.ts +62 -13
  207. package/types/lib/ecosystems/ecosystems.d.ts.map +1 -1
  208. package/types/lib/ecosystems/golem.d.ts +81 -1
  209. package/types/lib/ecosystems/golem.d.ts.map +1 -1
  210. package/types/lib/ecosystems/gradleutils.d.ts +59 -7
  211. package/types/lib/ecosystems/gradleutils.d.ts.map +1 -1
  212. package/types/lib/ecosystems/jsEvidence.d.ts.map +1 -1
  213. package/types/lib/ecosystems/kosi.d.ts.map +1 -1
  214. package/types/lib/ecosystems/npmutils.d.ts +15 -0
  215. package/types/lib/ecosystems/npmutils.d.ts.map +1 -1
  216. package/types/lib/ecosystems/parsers-dotnet.d.ts +155 -5
  217. package/types/lib/ecosystems/parsers-dotnet.d.ts.map +1 -1
  218. package/types/lib/ecosystems/parsers-elm.d.ts.map +1 -1
  219. package/types/lib/ecosystems/parsers-gleam.d.ts.map +1 -1
  220. package/types/lib/ecosystems/parsers-go.d.ts +119 -5
  221. package/types/lib/ecosystems/parsers-go.d.ts.map +1 -1
  222. package/types/lib/ecosystems/parsers-js.d.ts +6 -1
  223. package/types/lib/ecosystems/parsers-js.d.ts.map +1 -1
  224. package/types/lib/ecosystems/parsers-julia.d.ts.map +1 -1
  225. package/types/lib/ecosystems/parsers-jvm.d.ts +74 -3
  226. package/types/lib/ecosystems/parsers-jvm.d.ts.map +1 -1
  227. package/types/lib/ecosystems/parsers-misc.d.ts +21 -59
  228. package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -1
  229. package/types/lib/ecosystems/parsers-python.d.ts +57 -6
  230. package/types/lib/ecosystems/parsers-python.d.ts.map +1 -1
  231. package/types/lib/ecosystems/parsers-terraform.d.ts +38 -21
  232. package/types/lib/ecosystems/parsers-terraform.d.ts.map +1 -1
  233. package/types/lib/ecosystems/pythonutils.d.ts +26 -1
  234. package/types/lib/ecosystems/pythonutils.d.ts.map +1 -1
  235. package/types/lib/ecosystems/remote/huggingface.d.ts.map +1 -1
  236. package/types/lib/ecosystems/rubyutils.d.ts +21 -1
  237. package/types/lib/ecosystems/rubyutils.d.ts.map +1 -1
  238. package/types/lib/ecosystems/rusi.d.ts.map +1 -1
  239. package/types/lib/ecosystems/sbtutils.d.ts +88 -2
  240. package/types/lib/ecosystems/sbtutils.d.ts.map +1 -1
  241. package/types/lib/ecosystems/scalacliutils.d.ts +56 -0
  242. package/types/lib/ecosystems/scalacliutils.d.ts.map +1 -0
  243. package/types/lib/ecosystems/scalasem.d.ts +311 -0
  244. package/types/lib/ecosystems/scalasem.d.ts.map +1 -0
  245. package/types/lib/ecosystems/terraformRegistry.d.ts +9 -0
  246. package/types/lib/ecosystems/terraformRegistry.d.ts.map +1 -0
  247. package/types/lib/ecosystems/utils.d.ts +2 -2
  248. package/types/lib/ecosystems/utils.d.ts.map +1 -1
  249. package/types/lib/ecosystems/vendoredCode.d.ts +32 -0
  250. package/types/lib/ecosystems/vendoredCode.d.ts.map +1 -0
  251. package/types/lib/evinser/evinser.d.ts +100 -8
  252. package/types/lib/evinser/evinser.d.ts.map +1 -1
  253. package/types/lib/evinser/swiftsem.d.ts +10 -0
  254. package/types/lib/evinser/swiftsem.d.ts.map +1 -1
  255. package/types/lib/helpers/bomSigner.d.ts +80 -4
  256. package/types/lib/helpers/bomSigner.d.ts.map +1 -1
  257. package/types/lib/inventory/agentSkillSpec.d.ts +13 -0
  258. package/types/lib/inventory/agentSkillSpec.d.ts.map +1 -0
  259. package/types/lib/inventory/aiCollector.d.ts.map +1 -1
  260. package/types/lib/inventory/analyzer.d.ts.map +1 -1
  261. package/types/lib/inventory/apkInstalledDb.d.ts +42 -0
  262. package/types/lib/inventory/apkInstalledDb.d.ts.map +1 -0
  263. package/types/lib/inventory/atomUtils.d.ts +96 -10
  264. package/types/lib/inventory/atomUtils.d.ts.map +1 -1
  265. package/types/lib/inventory/auditCategories.d.ts +3 -0
  266. package/types/lib/inventory/auditCategories.d.ts.map +1 -1
  267. package/types/lib/inventory/buildToolRateLimit.d.ts +38 -0
  268. package/types/lib/inventory/buildToolRateLimit.d.ts.map +1 -0
  269. package/types/lib/inventory/cacheCommands.d.ts +2 -1
  270. package/types/lib/inventory/cacheCommands.d.ts.map +1 -1
  271. package/types/lib/inventory/cacheDir.d.ts +12 -4
  272. package/types/lib/inventory/cacheDir.d.ts.map +1 -1
  273. package/types/lib/inventory/certificates.d.ts +205 -0
  274. package/types/lib/inventory/certificates.d.ts.map +1 -0
  275. package/types/lib/inventory/cmakeBuildDirs.d.ts +58 -0
  276. package/types/lib/inventory/cmakeBuildDirs.d.ts.map +1 -0
  277. package/types/lib/inventory/communityAiConfigParser.d.ts.map +1 -1
  278. package/types/lib/inventory/deps.d.ts +61 -2
  279. package/types/lib/inventory/deps.d.ts.map +1 -1
  280. package/types/lib/inventory/display.d.ts +18 -0
  281. package/types/lib/inventory/display.d.ts.map +1 -1
  282. package/types/lib/inventory/dosai.d.ts +202 -14
  283. package/types/lib/inventory/dosai.d.ts.map +1 -1
  284. package/types/lib/inventory/dosaiParsers.d.ts +53 -7
  285. package/types/lib/inventory/dosaiParsers.d.ts.map +1 -1
  286. package/types/lib/inventory/dynamic.d.ts +16 -1
  287. package/types/lib/inventory/dynamic.d.ts.map +1 -1
  288. package/types/lib/inventory/envcontext.d.ts +40 -2
  289. package/types/lib/inventory/envcontext.d.ts.map +1 -1
  290. package/types/lib/inventory/evidenceUtils.d.ts +48 -14
  291. package/types/lib/inventory/evidenceUtils.d.ts.map +1 -1
  292. package/types/lib/inventory/fetchBatch.d.ts +83 -14
  293. package/types/lib/inventory/fetchBatch.d.ts.map +1 -1
  294. package/types/lib/inventory/fetchDiskCache.d.ts +169 -0
  295. package/types/lib/inventory/fetchDiskCache.d.ts.map +1 -0
  296. package/types/lib/inventory/forgeEnricher.d.ts.map +1 -1
  297. package/types/lib/inventory/formulationParsers.d.ts.map +1 -1
  298. package/types/lib/inventory/goBuildInfo.d.ts +10 -0
  299. package/types/lib/inventory/goBuildInfo.d.ts.map +1 -0
  300. package/types/lib/inventory/hbom.d.ts.map +1 -1
  301. package/types/lib/inventory/hbomAnalysis.d.ts +10 -0
  302. package/types/lib/inventory/hbomAnalysis.d.ts.map +1 -1
  303. package/types/lib/inventory/hostTopology.d.ts.map +1 -1
  304. package/types/lib/inventory/jvmLocalRepos.d.ts +178 -0
  305. package/types/lib/inventory/jvmLocalRepos.d.ts.map +1 -0
  306. package/types/lib/inventory/mcpConfigParser.d.ts.map +1 -1
  307. package/types/lib/inventory/osPackagePurl.d.ts +99 -0
  308. package/types/lib/inventory/osPackagePurl.d.ts.map +1 -0
  309. package/types/lib/inventory/osPackageResolver.d.ts +6 -2
  310. package/types/lib/inventory/osPackageResolver.d.ts.map +1 -1
  311. package/types/lib/inventory/osinfo.d.ts +31 -6
  312. package/types/lib/inventory/osinfo.d.ts.map +1 -1
  313. package/types/lib/inventory/osqueryTransform.d.ts +51 -0
  314. package/types/lib/inventory/osqueryTransform.d.ts.map +1 -1
  315. package/types/lib/inventory/parentSelection.d.ts +34 -0
  316. package/types/lib/inventory/parentSelection.d.ts.map +1 -0
  317. package/types/lib/inventory/phpBuildInfo.d.ts +142 -0
  318. package/types/lib/inventory/phpBuildInfo.d.ts.map +1 -0
  319. package/types/lib/inventory/phpHostProbe.d.ts +35 -0
  320. package/types/lib/inventory/phpHostProbe.d.ts.map +1 -0
  321. package/types/lib/inventory/rootfsCerts.d.ts +27 -0
  322. package/types/lib/inventory/rootfsCerts.d.ts.map +1 -0
  323. package/types/lib/inventory/rustFormulationParser.d.ts.map +1 -1
  324. package/types/lib/inventory/scalaCoords.d.ts +80 -0
  325. package/types/lib/inventory/scalaCoords.d.ts.map +1 -0
  326. package/types/lib/inventory/source.d.ts +28 -0
  327. package/types/lib/inventory/source.d.ts.map +1 -1
  328. package/types/lib/inventory/spdx.d.ts +24 -0
  329. package/types/lib/inventory/spdx.d.ts.map +1 -1
  330. package/types/lib/inventory/traceRunner.d.ts +16 -1
  331. package/types/lib/inventory/traceRunner.d.ts.map +1 -1
  332. package/types/lib/inventory/tracedCrypto.d.ts +64 -0
  333. package/types/lib/inventory/tracedCrypto.d.ts.map +1 -0
  334. package/types/lib/managers/binary.d.ts +10 -0
  335. package/types/lib/managers/binary.d.ts.map +1 -1
  336. package/types/lib/managers/docker.d.ts +12 -0
  337. package/types/lib/managers/docker.d.ts.map +1 -1
  338. package/types/lib/managers/oci.d.ts +3 -1
  339. package/types/lib/managers/oci.d.ts.map +1 -1
  340. package/types/lib/parsers/cmakeCache.d.ts +16 -0
  341. package/types/lib/parsers/cmakeCache.d.ts.map +1 -1
  342. package/types/lib/parsers/cmakeLists.d.ts +2 -1
  343. package/types/lib/parsers/cmakeLists.d.ts.map +1 -1
  344. package/types/lib/parsers/cmakePresets.d.ts +78 -0
  345. package/types/lib/parsers/cmakePresets.d.ts.map +1 -0
  346. package/types/lib/parsers/compileCommands.d.ts +115 -0
  347. package/types/lib/parsers/compileCommands.d.ts.map +1 -0
  348. package/types/lib/parsers/email.d.ts +19 -0
  349. package/types/lib/parsers/email.d.ts.map +1 -0
  350. package/types/lib/parsers/largeJson.d.ts +13 -0
  351. package/types/lib/parsers/largeJson.d.ts.map +1 -1
  352. package/types/lib/parsers/strictJson.d.ts +46 -0
  353. package/types/lib/parsers/strictJson.d.ts.map +1 -0
  354. package/types/lib/parsers/terraformConfig.d.ts +70 -0
  355. package/types/lib/parsers/terraformConfig.d.ts.map +1 -0
  356. package/types/lib/parsers/terraformSource.d.ts +66 -0
  357. package/types/lib/parsers/terraformSource.d.ts.map +1 -0
  358. package/types/lib/server/server.d.ts +8 -0
  359. package/types/lib/server/server.d.ts.map +1 -1
  360. package/types/lib/stages/postgen/annotator.d.ts.map +1 -1
  361. package/types/lib/stages/postgen/introspection/reflect.d.ts.map +1 -1
  362. package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
  363. package/types/lib/stages/postgen/ruleEngine.d.ts +7 -4
  364. package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -1
  365. package/types/lib/stages/postgen/specVersionCompat.d.ts.map +1 -1
  366. package/types/lib/stages/pregen/pregen.d.ts +14 -1
  367. package/types/lib/stages/pregen/pregen.d.ts.map +1 -1
  368. package/types/lib/validator/bomValidator.d.ts.map +1 -1
  369. package/types/lib/validator/index.d.ts +8 -0
  370. package/types/lib/validator/index.d.ts.map +1 -1
  371. package/types/lib/validator/reporters/json.d.ts.map +1 -1
  372. package/lib/third-party/arborist/snapshots/calc-dep-flags.test.cjs +0 -462
@@ -1,27 +1,80 @@
1
- import { readFileSync } from "node:fs";
2
- import { basename, dirname, resolve } from "node:path";
1
+ import { readdirSync, readFileSync } from "node:fs";
2
+ import {
3
+ basename,
4
+ dirname,
5
+ isAbsolute,
6
+ join,
7
+ relative,
8
+ resolve,
9
+ } from "node:path";
3
10
 
4
11
  import { build } from "@cdxgen/cdx-purl";
5
12
  import { parseEDNString } from "edn-data";
6
13
 
7
- import { readEnvironmentVariable } from "../core/activity.js";
14
+ import { DEBUG_MODE, readEnvironmentVariable } from "../core/activity.js";
8
15
  import { recordDegradation } from "../core/buildLedger.js";
9
16
  import { includeMavenTestScope } from "../core/env.js";
17
+ import { safeExistsSync } from "../core/fs.js";
10
18
  import { thoughtLog } from "../core/logger.js";
11
19
  import { applyPurl } from "../inventory/purl.js";
20
+ import { parseScalaArtifact } from "../inventory/scalaCoords.js";
12
21
  import { xml2js } from "../parsers/xml.js";
13
22
 
23
+ /** Bound on the `${...}` references one pom value may expand through. */
24
+ const POM_PROPERTY_EXPANSION_LIMIT = 10;
25
+
26
+ /**
27
+ * Expand the `${name}` references in a pom value. The value is returned only
28
+ * when every reference resolves, so a version is never half expanded.
29
+ *
30
+ * @param {string} value Raw pom value
31
+ * @param {Function} lookup Returns the value of a property name, or undefined
32
+ * @returns {string|undefined} Expanded value, or undefined
33
+ */
34
+ function expandPomValue(value, lookup) {
35
+ let expanded = value;
36
+ for (
37
+ let i = 0;
38
+ i < POM_PROPERTY_EXPANSION_LIMIT && expanded?.includes("${");
39
+ i++
40
+ ) {
41
+ const start = expanded.indexOf("${");
42
+ const end = expanded.indexOf("}", start + 2);
43
+ if (end < 0) {
44
+ return undefined;
45
+ }
46
+ const replacement = lookup(expanded.slice(start + 2, end));
47
+ if (typeof replacement !== "string") {
48
+ return undefined;
49
+ }
50
+ expanded = `${expanded.slice(0, start)}${replacement}${expanded.slice(end + 1)}`;
51
+ }
52
+ return expanded?.includes("${") ? undefined : expanded;
53
+ }
54
+
14
55
  /**
15
56
  * Parse pom file
16
57
  *
58
+ * Versions resolve from the pom's own properties and dependencyManagement.
59
+ * A caller that has read the pom's parents passes what they define in
60
+ * `inherited`, so versions the parents manage resolve too. Imported BOMs and
61
+ * parents outside the scanned directory are not read.
62
+ *
17
63
  * @param {string} pomFile pom file to parse
18
- * @returns {Object} Object containing pom properties, modules, and array of dependencies
64
+ * @param {Object} [inherited] Properties and managed versions from parent poms
65
+ * @param {Object} [inherited.properties] Property name to raw value
66
+ * @param {Object} [inherited.managedVersions] `groupId:artifactId` to version
67
+ * @returns {Object} Object containing pom properties, modules, the parent
68
+ * reference, the user properties and managed versions this pom defines, and
69
+ * array of dependencies
19
70
  */
20
- export function parsePom(pomFile) {
71
+ export function parsePom(pomFile, inherited = {}) {
21
72
  const deps = [];
22
73
  let modules;
23
74
  let pomPurl;
24
75
  const properties = {};
76
+ const userProperties = {};
77
+ const managedVersions = {};
25
78
  let isQuarkus = false;
26
79
  const xmlData = readFileSync(pomFile, "utf-8");
27
80
  const project = xml2js(xmlData, {
@@ -54,25 +107,30 @@ export function parsePom(pomFile) {
54
107
  }
55
108
  }
56
109
  // Take the version from the parent if available
57
- if (!properties.version && project.parent) {
110
+ if (!properties.version && project?.parent?.version?._) {
58
111
  properties.version = project.parent.version._;
59
112
  }
60
113
  // Take the groupId from the parent if available
61
- if (!properties.groupId && project.parent) {
114
+ if (!properties.groupId && project?.parent?.groupId?._) {
62
115
  properties.groupId = project.parent.groupId._;
63
116
  }
117
+ let parent;
118
+ if (project?.parent) {
119
+ parent = {
120
+ groupId: project.parent.groupId?._,
121
+ artifactId: project.parent.artifactId?._,
122
+ version: project.parent.version?._,
123
+ // An empty <relativePath/> tells Maven not to look for the parent on
124
+ // disk; a missing one means ../pom.xml.
125
+ relativePath:
126
+ project.parent.relativePath === undefined
127
+ ? "../pom.xml"
128
+ : project.parent.relativePath?._ || "",
129
+ };
130
+ }
64
131
  if (project?.scm?.url?._) {
65
132
  properties.scm = project.scm.url._;
66
133
  }
67
- if (properties.groupId || properties.artifactId) {
68
- pomPurl = build({
69
- type: "maven",
70
- namespace: properties.groupId || "" || null,
71
- name: properties.artifactId,
72
- version: properties.version || null,
73
- qualifiers: { type: properties.packaging || "jar" } || null,
74
- });
75
- }
76
134
  const moduleEntries = [];
77
135
  if (project?.modules?.module) {
78
136
  moduleEntries.push(project.modules.module);
@@ -91,11 +149,80 @@ export function parsePom(pomFile) {
91
149
  if (project?.properties) {
92
150
  for (const aprop of Object.keys(project.properties)) {
93
151
  properties[aprop] = project.properties[aprop]?._;
152
+ userProperties[aprop] = project.properties[aprop]?._;
94
153
  if (!isQuarkus && aprop.startsWith("quarkus.platform")) {
95
154
  isQuarkus = true;
96
155
  }
97
156
  }
98
157
  }
158
+ const inheritedProperties = inherited?.properties || {};
159
+ const lookupProperty = (name) => {
160
+ switch (name) {
161
+ case "project.version":
162
+ case "pom.version":
163
+ case "version":
164
+ return properties.version;
165
+ case "project.groupId":
166
+ case "pom.groupId":
167
+ case "groupId":
168
+ return properties.groupId;
169
+ case "project.artifactId":
170
+ case "pom.artifactId":
171
+ case "artifactId":
172
+ return properties.artifactId;
173
+ case "project.parent.version":
174
+ return parent?.version;
175
+ case "project.parent.groupId":
176
+ return parent?.groupId;
177
+ default:
178
+ return Object.hasOwn(userProperties, name)
179
+ ? userProperties[name]
180
+ : inheritedProperties[name];
181
+ }
182
+ };
183
+ // A property can refer to another, so each lookup expands its value too.
184
+ const expand = (value) =>
185
+ expandPomValue(value, (name) => {
186
+ const raw = lookupProperty(name);
187
+ return raw?.includes("${")
188
+ ? expandPomValue(raw, (inner) =>
189
+ inner === name ? undefined : lookupProperty(inner),
190
+ )
191
+ : raw;
192
+ });
193
+ let managedEntries = project?.dependencyManagement?.dependencies?.dependency;
194
+ if (managedEntries && !Array.isArray(managedEntries)) {
195
+ managedEntries = [managedEntries];
196
+ }
197
+ for (const amanaged of managedEntries || []) {
198
+ // An imported BOM manages versions this pom cannot see without fetching it
199
+ if (amanaged?.scope?._ === "import" || !amanaged?.version?._) {
200
+ continue;
201
+ }
202
+ const group = expand(amanaged.groupId?._);
203
+ const name = expand(amanaged.artifactId?._);
204
+ const version = expand(amanaged.version._);
205
+ if (group && name && version) {
206
+ managedVersions[`${group}:${name}`] = version;
207
+ }
208
+ }
209
+ const inheritedManagedVersions = inherited?.managedVersions || {};
210
+ // CI friendly versions such as ${revision} resolve from the properties
211
+ for (const coordinate of ["groupId", "version"]) {
212
+ if (properties[coordinate]?.includes("${")) {
213
+ properties[coordinate] =
214
+ expand(properties[coordinate]) || properties[coordinate];
215
+ }
216
+ }
217
+ if (properties.groupId || properties.artifactId) {
218
+ pomPurl = build({
219
+ type: "maven",
220
+ namespace: properties.groupId || "" || null,
221
+ name: properties.artifactId,
222
+ version: properties.version || null,
223
+ qualifiers: { type: properties.packaging || "jar" } || null,
224
+ });
225
+ }
99
226
  // Check the plugins for quarkus
100
227
  if (!isQuarkus && project?.build?.plugins?.plugin) {
101
228
  if (Array.isArray(project.build.plugins.plugin)) {
@@ -129,7 +256,18 @@ export function parsePom(pomFile) {
129
256
  versionStr = version._;
130
257
  }
131
258
  if (versionStr?.includes("$")) {
132
- versionStr = properties[versionStr?.replace(/[${}]/g, "")];
259
+ versionStr = expand(versionStr);
260
+ }
261
+ let groupStr = adep.groupId ? adep.groupId._ : "";
262
+ if (groupStr?.includes("${")) {
263
+ groupStr = expand(groupStr) || groupStr;
264
+ }
265
+ const nameStr = adep.artifactId ? adep.artifactId._ : "";
266
+ if (!versionStr && !version?._) {
267
+ const managedKey = `${groupStr}:${nameStr}`;
268
+ versionStr = Object.hasOwn(managedVersions, managedKey)
269
+ ? managedVersions[managedKey]
270
+ : inheritedManagedVersions[managedKey];
133
271
  }
134
272
  const scope = adep.scope?._;
135
273
  const type = adep.type?._ || "jar";
@@ -147,8 +285,8 @@ export function parsePom(pomFile) {
147
285
  }
148
286
  if (includeMavenTestScope || scope !== "test") {
149
287
  deps.push({
150
- group: adep.groupId ? adep.groupId._ : "",
151
- name: adep.artifactId ? adep.artifactId._ : "",
288
+ group: groupStr,
289
+ name: nameStr,
152
290
  version: versionStr,
153
291
  qualifiers,
154
292
  scope: mapMavenScope(scope, optional === "true"),
@@ -170,7 +308,272 @@ export function parsePom(pomFile) {
170
308
  }
171
309
  }
172
310
  }
173
- return { isQuarkus, pomPurl, modules, properties, dependencies: deps };
311
+ return {
312
+ isQuarkus,
313
+ pomPurl,
314
+ modules,
315
+ parent,
316
+ properties,
317
+ userProperties,
318
+ managedVersions,
319
+ dependencies: deps,
320
+ };
321
+ }
322
+
323
+ /** Bound on the chain of parent poms read from disk. */
324
+ const LOCAL_PARENT_DEPTH_LIMIT = 10;
325
+
326
+ /**
327
+ * The pom file a `<parent>` reference points at on disk, when it lies inside
328
+ * the scanned directory and declares the coordinates the reference names.
329
+ *
330
+ * @param {string} pomFile Child pom file
331
+ * @param {Object} parentRef Parent reference from parsePom
332
+ * @param {string} rootDir Scanned directory
333
+ * @returns {string|undefined} Parent pom file
334
+ */
335
+ function locateLocalParentPom(pomFile, parentRef, rootDir) {
336
+ if (!parentRef?.relativePath || !rootDir) {
337
+ return undefined;
338
+ }
339
+ let candidate = resolve(dirname(pomFile), parentRef.relativePath);
340
+ if (!candidate.endsWith(".xml")) {
341
+ candidate = join(candidate, "pom.xml");
342
+ }
343
+ const rel = relative(resolve(rootDir), candidate);
344
+ if (!rel || rel.startsWith("..") || isAbsolute(rel)) {
345
+ return undefined;
346
+ }
347
+ if (!safeExistsSync(candidate)) {
348
+ return undefined;
349
+ }
350
+ try {
351
+ const { groupId, artifactId } = parsePom(candidate).properties || {};
352
+ if (
353
+ artifactId !== parentRef.artifactId ||
354
+ (parentRef.groupId && groupId !== parentRef.groupId)
355
+ ) {
356
+ return undefined;
357
+ }
358
+ } catch (_err) {
359
+ return undefined;
360
+ }
361
+ return candidate;
362
+ }
363
+
364
+ /**
365
+ * What a pom passes on to its children: its user properties and managed
366
+ * versions over those of its own local parents.
367
+ *
368
+ * @param {string} pomFile Pom file
369
+ * @param {string} rootDir Scanned directory
370
+ * @param {Map} cache Results by pom file
371
+ * @param {number} depth Current depth of the parent chain
372
+ * @returns {Object} Inherited properties and managed versions
373
+ */
374
+ function localPomInheritance(pomFile, rootDir, cache, depth) {
375
+ if (cache.has(pomFile)) {
376
+ return cache.get(pomFile);
377
+ }
378
+ const empty = { properties: {}, managedVersions: {} };
379
+ // A parent chain that loops back reads as having no parent
380
+ cache.set(pomFile, empty);
381
+ let inherited = empty;
382
+ try {
383
+ const parentPom =
384
+ depth < LOCAL_PARENT_DEPTH_LIMIT
385
+ ? locateLocalParentPom(pomFile, parsePom(pomFile).parent, rootDir)
386
+ : undefined;
387
+ if (parentPom) {
388
+ inherited = localPomInheritance(parentPom, rootDir, cache, depth + 1);
389
+ }
390
+ const own = parsePom(pomFile, inherited);
391
+ const result = {
392
+ properties: { ...inherited.properties, ...own.userProperties },
393
+ managedVersions: { ...inherited.managedVersions, ...own.managedVersions },
394
+ };
395
+ cache.set(pomFile, result);
396
+ return result;
397
+ } catch (_err) {
398
+ return empty;
399
+ }
400
+ }
401
+
402
+ /**
403
+ * Parse a pom file together with the parent poms it names that are present
404
+ * inside the scanned directory, without running Maven. Properties and
405
+ * dependencyManagement versions from those parents resolve the versions the
406
+ * pom leaves to them. Parents outside the directory and imported BOMs are not
407
+ * read, so the versions they manage stay empty.
408
+ *
409
+ * @param {string} pomFile Pom file to parse
410
+ * @param {string} rootDir Scanned directory; parents outside it are ignored
411
+ * @param {Map} [cache] Reused across the poms of one scan
412
+ * @returns {Object} Same shape as parsePom
413
+ */
414
+ export function parsePomWithLocalParents(pomFile, rootDir, cache = new Map()) {
415
+ const pomPath = resolve(pomFile);
416
+ const parentPom = locateLocalParentPom(
417
+ pomPath,
418
+ parsePom(pomPath).parent,
419
+ rootDir,
420
+ );
421
+ if (!parentPom) {
422
+ return parsePom(pomFile);
423
+ }
424
+ return parsePom(pomFile, localPomInheritance(parentPom, rootDir, cache, 1));
425
+ }
426
+
427
+ /** Bound on the reactor walk. A pom's module list is untrusted input, so the
428
+ * walk cannot trust it to stay finite. */
429
+ const REACTOR_MODULE_LIMIT = 500;
430
+
431
+ /**
432
+ * Every pom file of the reactor an aggregator pom builds: its own modules,
433
+ * recursively through nested aggregators. A recursive dependency:tree run
434
+ * from the aggregator resolves all of them, so their own runs repeat it.
435
+ *
436
+ * A module entry names a directory relative to its pom, sometimes a direct
437
+ * path to a pom file. Entries that are absolute, or that climb out of the
438
+ * aggregator's directory, are ignored: the scan never listed them, and the
439
+ * walk must not follow a pom's pointers outside its own tree.
440
+ *
441
+ * @param {string} rootPom Path of the aggregator pom.
442
+ * @returns {Set<string>} Pom files of the reactor, excluding the aggregator.
443
+ */
444
+ export function resolveReactorPomFiles(rootPom) {
445
+ const pomFiles = new Set();
446
+ const visited = new Set();
447
+ const rootDir = dirname(resolve(rootPom));
448
+ const queue = [resolve(rootPom)];
449
+ while (queue.length > 0 && pomFiles.size < REACTOR_MODULE_LIMIT) {
450
+ const pom = queue.shift();
451
+ if (visited.has(pom)) {
452
+ continue;
453
+ }
454
+ visited.add(pom);
455
+ let modules;
456
+ try {
457
+ modules = parsePom(pom)?.modules;
458
+ } catch (_err) {
459
+ // An unreadable module pom ends this branch of the walk.
460
+ continue;
461
+ }
462
+ for (const module of modules || []) {
463
+ if (typeof module !== "string") {
464
+ continue;
465
+ }
466
+ const cleaned = module.trim().replaceAll("\\", "/");
467
+ if (
468
+ !cleaned ||
469
+ cleaned.includes("\0") ||
470
+ cleaned.startsWith("/") ||
471
+ /^[A-Za-z]:/.test(cleaned)
472
+ ) {
473
+ continue;
474
+ }
475
+ const modulePom = resolve(
476
+ dirname(pom),
477
+ cleaned.endsWith(".xml") ? cleaned : join(cleaned, "pom.xml"),
478
+ );
479
+ const withinRoot = relative(rootDir, modulePom);
480
+ if (
481
+ !withinRoot ||
482
+ withinRoot.startsWith("..") ||
483
+ isAbsolute(withinRoot) ||
484
+ !safeExistsSync(modulePom)
485
+ ) {
486
+ continue;
487
+ }
488
+ if (visited.has(modulePom)) {
489
+ continue;
490
+ }
491
+ pomFiles.add(modulePom);
492
+ queue.push(modulePom);
493
+ }
494
+ }
495
+ return pomFiles;
496
+ }
497
+
498
+ /**
499
+ * File name stem for the trees of one recursive dependency:tree run. Maven
500
+ * expands the project expressions for each reactor module, so every module
501
+ * writes its own file; a fixed name would hold only the last module's tree.
502
+ */
503
+ export const MAVEN_MODULE_TREE_STEM =
504
+ // biome-ignore lint/suspicious/noTemplateCurlyInString: Maven expands these project expressions itself
505
+ "${project.groupId}-${project.artifactId}";
506
+
507
+ /**
508
+ * The groupId-artifactId key a module's tree file is named by.
509
+ *
510
+ * @param {string} pomFile Path of the module pom.
511
+ * @returns {string|undefined} The key, or undefined when the pom cannot be read.
512
+ */
513
+ function moduleTreeKey(pomFile) {
514
+ try {
515
+ const { groupId, artifactId } = parsePom(pomFile)?.properties || {};
516
+ return groupId && artifactId ? `${groupId}-${artifactId}` : undefined;
517
+ } catch (_err) {
518
+ return undefined;
519
+ }
520
+ }
521
+
522
+ /**
523
+ * Read the trees one dependency:tree run wrote, one file per reactor module
524
+ * (see MAVEN_MODULE_TREE_STEM), and tell which of the reactor's pom files
525
+ * they cover. The pom the run started from comes first, then its modules in
526
+ * reactor order. A module pom counts as covered only when its own tree is
527
+ * among the files, so a module the run left out still runs on its own.
528
+ *
529
+ * @param {string} treeDir Directory the run wrote its trees into.
530
+ * @param {string} rootPom The pom file the run started from.
531
+ * @returns {{trees: Array<{pomFile: string, text: string}>, covered: Set<string>}}
532
+ */
533
+ export function readMavenModuleTrees(treeDir, rootPom) {
534
+ const trees = [];
535
+ const covered = new Set();
536
+ let names;
537
+ try {
538
+ names = readdirSync(treeDir).sort();
539
+ } catch (_err) {
540
+ return { trees, covered };
541
+ }
542
+ const byKey = new Map();
543
+ for (const name of names) {
544
+ const stem = name.replace(/\.(json|txt)$/, "");
545
+ if (stem !== name && !byKey.has(stem)) {
546
+ byKey.set(stem, name);
547
+ }
548
+ }
549
+ const take = (key, pomFile) => {
550
+ const name = byKey.get(key);
551
+ if (!name) {
552
+ return false;
553
+ }
554
+ byKey.delete(key);
555
+ trees.push({
556
+ pomFile,
557
+ text: readFileSync(join(treeDir, name), { encoding: "utf-8" }),
558
+ });
559
+ return true;
560
+ };
561
+ const rootKey = moduleTreeKey(rootPom);
562
+ if (rootKey) {
563
+ take(rootKey, rootPom);
564
+ }
565
+ for (const modulePom of resolveReactorPomFiles(rootPom)) {
566
+ const key = moduleTreeKey(modulePom);
567
+ if (key && take(key, modulePom)) {
568
+ covered.add(modulePom);
569
+ }
570
+ }
571
+ // Trees no pom of the reactor names, such as the single file of a Maven
572
+ // that did not expand the expressions, are kept under the root pom.
573
+ for (const key of [...byKey.keys()]) {
574
+ take(key, rootPom);
575
+ }
576
+ return { trees, covered };
174
577
  }
175
578
 
176
579
  function mapMavenScope(componentScope, isOptional = false) {
@@ -471,10 +874,16 @@ export function parseMavenTree(rawOutput, pomFile) {
471
874
  /**
472
875
  * Parse mill dependencies from file
473
876
  *
877
+ * Scala artifacts are emitted in the sbt purl form: the Scala binary suffix
878
+ * is stripped from the artifact name and the version it carried is recorded
879
+ * in the cdx:scala:compilerVersion property, so one library keeps a single
880
+ * purl whichever build tool reported it.
881
+ *
474
882
  * @param {string} module name of the module
475
883
  * @param {map} dependencies the parsed dependencies
476
884
  * @param {map} relations a map containing all relations
477
885
  * @param {string} millRootPath root of the project
886
+ * @param {string} logFileName name of the tree log the module wrote
478
887
  *
479
888
  * @returns the bom-ref of the module
480
889
  */
@@ -483,6 +892,7 @@ export function parseMillDependency(
483
892
  dependencies,
484
893
  relations,
485
894
  millRootPath,
895
+ logFileName = "ivyDepsTree.log",
486
896
  ) {
487
897
  const treeRegex = /^(?<treeIndentation>(?:[?├│└─ ]{3})+)(?<dependency>.*)/m;
488
898
  const ESC = "\\x1B";
@@ -522,12 +932,7 @@ export function parseMillDependency(
522
932
  // Now put the versions we removed above back into the path and replace the brackets at the same time
523
933
  moduleFilePath = moduleFilePath.replace("[]", `/${versionNumber}/`);
524
934
  }
525
- moduleFilePath = resolve(
526
- millRootPath,
527
- "out",
528
- moduleFilePath,
529
- "ivyDepsTree.log",
530
- );
935
+ moduleFilePath = resolve(millRootPath, "out", moduleFilePath, logFileName);
531
936
  moduleComponent.properties = [
532
937
  {
533
938
  name: "internal:SrcFile",
@@ -547,7 +952,27 @@ export function parseMillDependency(
547
952
  ],
548
953
  },
549
954
  };
550
- const dependencyTreeLog = readFileSync(moduleFilePath, "utf-8");
955
+ let dependencyTreeLog;
956
+ try {
957
+ dependencyTreeLog = readFileSync(moduleFilePath, "utf-8");
958
+ } catch (_err) {
959
+ // A cross-published module writes its log under the dotted version
960
+ // directory (0.23.38) while the resolve output prints it with
961
+ // underscores (0_23_38)
962
+ try {
963
+ dependencyTreeLog = readFileSync(
964
+ moduleFilePath.replace(/(\d+)_(\d+)_(\d+)/, "$1.$2.$3"),
965
+ "utf-8",
966
+ );
967
+ } catch (_err2) {
968
+ if (DEBUG_MODE) {
969
+ console.log(
970
+ `No Mill dependency tree log was written for the module ${module}.`,
971
+ );
972
+ }
973
+ return moduleComponent["bom-ref"];
974
+ }
975
+ }
551
976
  const dependencyTreeLines = dependencyTreeLog
552
977
  .trim()
553
978
  .split("\n")
@@ -568,11 +993,20 @@ export function parseMillDependency(
568
993
  [group, name, version] = match.groups.dependency.split(":");
569
994
  version = versionRegex.exec(version).groups.version;
570
995
  }
996
+ const scalaInfo = parseScalaArtifact(name);
571
997
  const component = completeComponent({
572
998
  group,
573
- name,
999
+ name: scalaInfo.purlName,
574
1000
  version,
575
1001
  });
1002
+ if (scalaInfo.binaryVersion) {
1003
+ component.properties = [
1004
+ {
1005
+ name: "cdx:scala:compilerVersion",
1006
+ value: scalaInfo.binaryVersion,
1007
+ },
1008
+ ];
1009
+ }
576
1010
  if (!dependencies.has(component["bom-ref"])) {
577
1011
  dependencies.set(component["bom-ref"], component);
578
1012
  relations.set(component["bom-ref"], []);
@@ -587,7 +1021,7 @@ export function parseMillDependency(
587
1021
  return moduleComponent["bom-ref"];
588
1022
  }
589
1023
 
590
- function completeComponent(component) {
1024
+ export function completeComponent(component) {
591
1025
  component["type"] = component.group ? "library" : "application";
592
1026
  try {
593
1027
  const purl = build({