@cdxgen/cdxgen 13.1.0 → 13.3.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 (283) hide show
  1. package/README.md +32 -15
  2. package/bin/cdxgen.js +243 -122
  3. package/bin/evinse.js +7 -0
  4. package/bin/sign.js +88 -14
  5. package/bin/tracebom.js +64 -4
  6. package/bin/validate.js +29 -7
  7. package/bin/verify.js +79 -39
  8. package/data/crypto-oid.json +88 -12
  9. package/data/remediations.json +47 -0
  10. package/data/rules/ai-bom.yaml +78 -0
  11. package/data/rules/cargo-rust.yaml +132 -0
  12. package/data/rules/mcp-servers.yaml +122 -0
  13. package/lib/audit/targets.js +6 -1
  14. package/lib/cli/bomAssembly.js +117 -15
  15. package/lib/cli/cliOptions.js +93 -1
  16. package/lib/cli/index.js +235 -5
  17. package/lib/cli/jsBom.js +108 -26
  18. package/lib/cli/jvmBom.js +68 -12
  19. package/lib/cli/managedBom.js +264 -41
  20. package/lib/cli/nativeBom.js +923 -15
  21. package/lib/core/activity.js +120 -2
  22. package/lib/core/env.js +44 -7
  23. package/lib/core/fs.js +174 -6
  24. package/lib/core/metadataProperties.js +97 -0
  25. package/lib/core/projectConfig.js +31 -4
  26. package/lib/core/userAgent.js +151 -0
  27. package/lib/ecosystems/bunutils.js +269 -101
  28. package/lib/ecosystems/cargoCache.js +364 -0
  29. package/lib/ecosystems/caxa.js +447 -7
  30. package/lib/ecosystems/cmakeResolver.js +66 -0
  31. package/lib/ecosystems/cppEvidence.js +104 -33
  32. package/lib/ecosystems/ecosystems.js +260 -99
  33. package/lib/ecosystems/golem.js +11 -1
  34. package/lib/ecosystems/gradleutils.js +185 -9
  35. package/lib/ecosystems/jsEvidence.js +19 -20
  36. package/lib/ecosystems/kosi.js +1263 -0
  37. package/lib/ecosystems/npmutils.js +110 -9
  38. package/lib/ecosystems/parsers-crystal.js +179 -0
  39. package/lib/ecosystems/parsers-dotnet.js +120 -49
  40. package/lib/ecosystems/parsers-elm.js +816 -0
  41. package/lib/ecosystems/parsers-gleam.js +1 -1
  42. package/lib/ecosystems/parsers-go.js +47 -9
  43. package/lib/ecosystems/parsers-js.js +171 -50
  44. package/lib/ecosystems/parsers-julia.js +268 -0
  45. package/lib/ecosystems/parsers-lua.js +218 -0
  46. package/lib/ecosystems/parsers-misc.js +919 -161
  47. package/lib/ecosystems/parsers-nim.js +221 -0
  48. package/lib/ecosystems/parsers-opam.js +180 -0
  49. package/lib/ecosystems/parsers-perl.js +277 -0
  50. package/lib/ecosystems/parsers-python.js +27 -15
  51. package/lib/ecosystems/parsers-r.js +148 -0
  52. package/lib/ecosystems/parsers-rebar.js +411 -0
  53. package/lib/ecosystems/parsers-rust.js +954 -33
  54. package/lib/ecosystems/parsers-spack.js +204 -0
  55. package/lib/ecosystems/parsers-stack.js +264 -0
  56. package/lib/ecosystems/parsers-terraform.js +194 -0
  57. package/lib/ecosystems/rubyutils.js +1426 -166
  58. package/lib/ecosystems/rusi.js +158 -7
  59. package/lib/evinser/evinser.js +547 -129
  60. package/lib/evinser/swiftsem.js +1914 -302
  61. package/lib/helpers/agenticToolutils.js +925 -0
  62. package/lib/helpers/bomSigner.js +652 -221
  63. package/lib/inventory/agentFormulationParser.js +57 -4
  64. package/lib/inventory/aiCollector.js +504 -10
  65. package/lib/inventory/aiInventory.js +12 -0
  66. package/lib/inventory/analyzer.js +488 -30
  67. package/lib/inventory/astWorker.js +6 -0
  68. package/lib/inventory/atomUtils.js +568 -31
  69. package/lib/inventory/auditCategories.js +8 -0
  70. package/lib/inventory/cbomutils.js +30 -0
  71. package/lib/inventory/cdxrs.js +110 -14
  72. package/lib/inventory/communityAiConfigParser.js +215 -2
  73. package/lib/inventory/depsUtils.js +183 -11
  74. package/lib/inventory/display.js +4 -5
  75. package/lib/inventory/dosai.js +627 -13
  76. package/lib/inventory/dynamic.js +39 -1
  77. package/lib/inventory/envcontext.js +9 -6
  78. package/lib/inventory/evidenceUtils.js +26 -5
  79. package/lib/inventory/fetchBatch.js +190 -19
  80. package/lib/inventory/fetchRate.js +74 -11
  81. package/lib/inventory/forgeEnricher.js +3 -2
  82. package/lib/inventory/jvmToolEnv.js +6 -5
  83. package/lib/inventory/mcpConfigParser.js +166 -2
  84. package/lib/inventory/mcpDiscovery.js +11 -0
  85. package/lib/inventory/mcpServerManifest.js +389 -0
  86. package/lib/inventory/mcpbBundle.js +419 -0
  87. package/lib/inventory/plugins.js +3 -0
  88. package/lib/inventory/protobom.js +62 -89
  89. package/lib/inventory/protobomLoader.js +4 -0
  90. package/lib/inventory/purl.js +152 -3
  91. package/lib/inventory/rustFormulationParser.js +1 -1
  92. package/lib/inventory/sbomDocument.js +2 -70
  93. package/lib/inventory/source.js +47 -23
  94. package/lib/inventory/stylePackageRefs.js +41 -0
  95. package/lib/inventory/svelteUtils.js +524 -0
  96. package/lib/inventory/traceRunner.js +210 -21
  97. package/lib/managers/binary.js +115 -24
  98. package/lib/managers/docker.js +440 -20
  99. package/lib/managers/oci.js +39 -1
  100. package/lib/parsers/cmakeLists.js +452 -0
  101. package/lib/parsers/huggingfaceUtils.js +15 -7
  102. package/lib/parsers/largeJson.js +454 -0
  103. package/lib/parsers/npmrc.js +19 -1
  104. package/lib/parsers/onnx.js +294 -0
  105. package/lib/parsers/safetensors.js +114 -0
  106. package/lib/stages/postgen/introspection/markers.js +29 -6
  107. package/lib/stages/postgen/postgen.js +237 -16
  108. package/lib/third-party/arborist/snapshots/calc-dep-flags.test.cjs +462 -0
  109. package/lib/validator/bomValidator.js +6 -16
  110. package/lib/validator/index.js +48 -10
  111. package/lib/validator/reporters/console.js +3 -0
  112. package/lib/validator/reporters/json.js +1 -0
  113. package/lib/validator/reporters/sarif.js +7 -0
  114. package/package.json +27 -27
  115. package/types/lib/audit/targets.d.ts.map +1 -1
  116. package/types/lib/cli/bomAssembly.d.ts +2 -1
  117. package/types/lib/cli/bomAssembly.d.ts.map +1 -1
  118. package/types/lib/cli/cliOptions.d.ts +33 -1
  119. package/types/lib/cli/cliOptions.d.ts.map +1 -1
  120. package/types/lib/cli/index.d.ts +2 -2
  121. package/types/lib/cli/index.d.ts.map +1 -1
  122. package/types/lib/cli/jsBom.d.ts +23 -0
  123. package/types/lib/cli/jsBom.d.ts.map +1 -1
  124. package/types/lib/cli/jvmBom.d.ts.map +1 -1
  125. package/types/lib/cli/managedBom.d.ts +33 -0
  126. package/types/lib/cli/managedBom.d.ts.map +1 -1
  127. package/types/lib/cli/nativeBom.d.ts +88 -8
  128. package/types/lib/cli/nativeBom.d.ts.map +1 -1
  129. package/types/lib/core/activity.d.ts.map +1 -1
  130. package/types/lib/core/env.d.ts +21 -0
  131. package/types/lib/core/env.d.ts.map +1 -1
  132. package/types/lib/core/fs.d.ts +55 -0
  133. package/types/lib/core/fs.d.ts.map +1 -1
  134. package/types/lib/core/metadataProperties.d.ts +39 -0
  135. package/types/lib/core/metadataProperties.d.ts.map +1 -0
  136. package/types/lib/core/projectConfig.d.ts +6 -2
  137. package/types/lib/core/projectConfig.d.ts.map +1 -1
  138. package/types/lib/core/userAgent.d.ts +56 -0
  139. package/types/lib/core/userAgent.d.ts.map +1 -0
  140. package/types/lib/ecosystems/bunutils.d.ts +12 -5
  141. package/types/lib/ecosystems/bunutils.d.ts.map +1 -1
  142. package/types/lib/ecosystems/cargoCache.d.ts +75 -0
  143. package/types/lib/ecosystems/cargoCache.d.ts.map +1 -0
  144. package/types/lib/ecosystems/caxa.d.ts +14 -0
  145. package/types/lib/ecosystems/caxa.d.ts.map +1 -1
  146. package/types/lib/ecosystems/cmakeResolver.d.ts +23 -0
  147. package/types/lib/ecosystems/cmakeResolver.d.ts.map +1 -1
  148. package/types/lib/ecosystems/cppEvidence.d.ts +2 -2
  149. package/types/lib/ecosystems/cppEvidence.d.ts.map +1 -1
  150. package/types/lib/ecosystems/ecosystems.d.ts +15 -1
  151. package/types/lib/ecosystems/ecosystems.d.ts.map +1 -1
  152. package/types/lib/ecosystems/golem.d.ts.map +1 -1
  153. package/types/lib/ecosystems/gradleutils.d.ts +40 -4
  154. package/types/lib/ecosystems/gradleutils.d.ts.map +1 -1
  155. package/types/lib/ecosystems/jsEvidence.d.ts +5 -2
  156. package/types/lib/ecosystems/jsEvidence.d.ts.map +1 -1
  157. package/types/lib/ecosystems/kosi.d.ts +86 -0
  158. package/types/lib/ecosystems/kosi.d.ts.map +1 -0
  159. package/types/lib/ecosystems/npmutils.d.ts +42 -0
  160. package/types/lib/ecosystems/npmutils.d.ts.map +1 -1
  161. package/types/lib/ecosystems/parsers-crystal.d.ts +27 -0
  162. package/types/lib/ecosystems/parsers-crystal.d.ts.map +1 -0
  163. package/types/lib/ecosystems/parsers-dotnet.d.ts +19 -0
  164. package/types/lib/ecosystems/parsers-dotnet.d.ts.map +1 -1
  165. package/types/lib/ecosystems/parsers-elm.d.ts +79 -0
  166. package/types/lib/ecosystems/parsers-elm.d.ts.map +1 -0
  167. package/types/lib/ecosystems/parsers-go.d.ts +10 -0
  168. package/types/lib/ecosystems/parsers-go.d.ts.map +1 -1
  169. package/types/lib/ecosystems/parsers-js.d.ts +10 -4
  170. package/types/lib/ecosystems/parsers-js.d.ts.map +1 -1
  171. package/types/lib/ecosystems/parsers-julia.d.ts +57 -0
  172. package/types/lib/ecosystems/parsers-julia.d.ts.map +1 -0
  173. package/types/lib/ecosystems/parsers-lua.d.ts +50 -0
  174. package/types/lib/ecosystems/parsers-lua.d.ts.map +1 -0
  175. package/types/lib/ecosystems/parsers-misc.d.ts +90 -3
  176. package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -1
  177. package/types/lib/ecosystems/parsers-nim.d.ts +43 -0
  178. package/types/lib/ecosystems/parsers-nim.d.ts.map +1 -0
  179. package/types/lib/ecosystems/parsers-opam.d.ts +31 -0
  180. package/types/lib/ecosystems/parsers-opam.d.ts.map +1 -0
  181. package/types/lib/ecosystems/parsers-perl.d.ts +36 -0
  182. package/types/lib/ecosystems/parsers-perl.d.ts.map +1 -0
  183. package/types/lib/ecosystems/parsers-python.d.ts.map +1 -1
  184. package/types/lib/ecosystems/parsers-r.d.ts +35 -0
  185. package/types/lib/ecosystems/parsers-r.d.ts.map +1 -0
  186. package/types/lib/ecosystems/parsers-rebar.d.ts +42 -0
  187. package/types/lib/ecosystems/parsers-rebar.d.ts.map +1 -0
  188. package/types/lib/ecosystems/parsers-rust.d.ts +199 -0
  189. package/types/lib/ecosystems/parsers-rust.d.ts.map +1 -1
  190. package/types/lib/ecosystems/parsers-spack.d.ts +33 -0
  191. package/types/lib/ecosystems/parsers-spack.d.ts.map +1 -0
  192. package/types/lib/ecosystems/parsers-stack.d.ts +35 -0
  193. package/types/lib/ecosystems/parsers-stack.d.ts.map +1 -0
  194. package/types/lib/ecosystems/parsers-terraform.d.ts +34 -0
  195. package/types/lib/ecosystems/parsers-terraform.d.ts.map +1 -0
  196. package/types/lib/ecosystems/pythonutils.d.ts +1 -1
  197. package/types/lib/ecosystems/rubyutils.d.ts +143 -2
  198. package/types/lib/ecosystems/rubyutils.d.ts.map +1 -1
  199. package/types/lib/ecosystems/rusi.d.ts +13 -0
  200. package/types/lib/ecosystems/rusi.d.ts.map +1 -1
  201. package/types/lib/evinser/evinser.d.ts +81 -2
  202. package/types/lib/evinser/evinser.d.ts.map +1 -1
  203. package/types/lib/evinser/swiftsem.d.ts +280 -15
  204. package/types/lib/evinser/swiftsem.d.ts.map +1 -1
  205. package/types/lib/helpers/agenticToolutils.d.ts +87 -0
  206. package/types/lib/helpers/agenticToolutils.d.ts.map +1 -0
  207. package/types/lib/helpers/bomSigner.d.ts +106 -13
  208. package/types/lib/helpers/bomSigner.d.ts.map +1 -1
  209. package/types/lib/inventory/agentFormulationParser.d.ts.map +1 -1
  210. package/types/lib/inventory/aiCollector.d.ts.map +1 -1
  211. package/types/lib/inventory/aiInventory.d.ts.map +1 -1
  212. package/types/lib/inventory/analyzer.d.ts.map +1 -1
  213. package/types/lib/inventory/atomUtils.d.ts +145 -3
  214. package/types/lib/inventory/atomUtils.d.ts.map +1 -1
  215. package/types/lib/inventory/auditCategories.d.ts +4 -0
  216. package/types/lib/inventory/auditCategories.d.ts.map +1 -1
  217. package/types/lib/inventory/cbomutils.d.ts.map +1 -1
  218. package/types/lib/inventory/cdxrs.d.ts +8 -3
  219. package/types/lib/inventory/cdxrs.d.ts.map +1 -1
  220. package/types/lib/inventory/communityAiConfigParser.d.ts.map +1 -1
  221. package/types/lib/inventory/depsUtils.d.ts +15 -0
  222. package/types/lib/inventory/depsUtils.d.ts.map +1 -1
  223. package/types/lib/inventory/display.d.ts.map +1 -1
  224. package/types/lib/inventory/dosai.d.ts +87 -1
  225. package/types/lib/inventory/dosai.d.ts.map +1 -1
  226. package/types/lib/inventory/dynamic.d.ts.map +1 -1
  227. package/types/lib/inventory/envcontext.d.ts.map +1 -1
  228. package/types/lib/inventory/evidenceUtils.d.ts.map +1 -1
  229. package/types/lib/inventory/fetchBatch.d.ts +34 -0
  230. package/types/lib/inventory/fetchBatch.d.ts.map +1 -1
  231. package/types/lib/inventory/fetchRate.d.ts +9 -6
  232. package/types/lib/inventory/fetchRate.d.ts.map +1 -1
  233. package/types/lib/inventory/forgeEnricher.d.ts.map +1 -1
  234. package/types/lib/inventory/jvmToolEnv.d.ts +5 -4
  235. package/types/lib/inventory/jvmToolEnv.d.ts.map +1 -1
  236. package/types/lib/inventory/mcpConfigParser.d.ts.map +1 -1
  237. package/types/lib/inventory/mcpDiscovery.d.ts.map +1 -1
  238. package/types/lib/inventory/mcpServerManifest.d.ts +19 -0
  239. package/types/lib/inventory/mcpServerManifest.d.ts.map +1 -0
  240. package/types/lib/inventory/mcpbBundle.d.ts +19 -0
  241. package/types/lib/inventory/mcpbBundle.d.ts.map +1 -0
  242. package/types/lib/inventory/plugins.d.ts.map +1 -1
  243. package/types/lib/inventory/protobom.d.ts +18 -13
  244. package/types/lib/inventory/protobom.d.ts.map +1 -1
  245. package/types/lib/inventory/protobomLoader.d.ts.map +1 -1
  246. package/types/lib/inventory/purl.d.ts +71 -2
  247. package/types/lib/inventory/purl.d.ts.map +1 -1
  248. package/types/lib/inventory/sbomDocument.d.ts.map +1 -1
  249. package/types/lib/inventory/source.d.ts.map +1 -1
  250. package/types/lib/inventory/stylePackageRefs.d.ts +17 -0
  251. package/types/lib/inventory/stylePackageRefs.d.ts.map +1 -0
  252. package/types/lib/inventory/svelteUtils.d.ts +124 -0
  253. package/types/lib/inventory/svelteUtils.d.ts.map +1 -0
  254. package/types/lib/inventory/traceRunner.d.ts +47 -1
  255. package/types/lib/inventory/traceRunner.d.ts.map +1 -1
  256. package/types/lib/managers/binary.d.ts +30 -1
  257. package/types/lib/managers/binary.d.ts.map +1 -1
  258. package/types/lib/managers/docker.d.ts +29 -0
  259. package/types/lib/managers/docker.d.ts.map +1 -1
  260. package/types/lib/managers/oci.d.ts +14 -0
  261. package/types/lib/managers/oci.d.ts.map +1 -1
  262. package/types/lib/parsers/cmakeLists.d.ts +76 -0
  263. package/types/lib/parsers/cmakeLists.d.ts.map +1 -0
  264. package/types/lib/parsers/huggingfaceUtils.d.ts +8 -1
  265. package/types/lib/parsers/huggingfaceUtils.d.ts.map +1 -1
  266. package/types/lib/parsers/largeJson.d.ts +52 -0
  267. package/types/lib/parsers/largeJson.d.ts.map +1 -0
  268. package/types/lib/parsers/npmrc.d.ts +5 -0
  269. package/types/lib/parsers/npmrc.d.ts.map +1 -1
  270. package/types/lib/parsers/onnx.d.ts +28 -0
  271. package/types/lib/parsers/onnx.d.ts.map +1 -0
  272. package/types/lib/parsers/safetensors.d.ts +22 -0
  273. package/types/lib/parsers/safetensors.d.ts.map +1 -0
  274. package/types/lib/stages/postgen/introspection/markers.d.ts +3 -2
  275. package/types/lib/stages/postgen/introspection/markers.d.ts.map +1 -1
  276. package/types/lib/stages/postgen/postgen.d.ts +33 -0
  277. package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
  278. package/types/lib/validator/bomValidator.d.ts.map +1 -1
  279. package/types/lib/validator/index.d.ts +10 -1
  280. package/types/lib/validator/index.d.ts.map +1 -1
  281. package/types/lib/validator/reporters/console.d.ts.map +1 -1
  282. package/types/lib/validator/reporters/json.d.ts.map +1 -1
  283. package/types/lib/validator/reporters/sarif.d.ts.map +1 -1
@@ -0,0 +1,452 @@
1
+ /**
2
+ * Pure parser for CMake language files (`CMakeLists.txt`, `*.cmake`).
3
+ *
4
+ * `parseCmakeCommands` splits a file into command invocations the way CMake
5
+ * reads it: command names are case-insensitive, an invocation may span several
6
+ * lines, and arguments may be quoted, bracketed (`[[...]]`) or interleaved with
7
+ * comments. `cmakeFetchDependencies` reads the commands that download a
8
+ * dependency at configure time: `FetchContent_Declare`, `ExternalProject_Add`
9
+ * and the CPM.cmake `CPMAddPackage` family.
10
+ *
11
+ * This module is layer 1 (text in, data out): no filesystem or subprocess
12
+ * access. `lib/ecosystems/parsers-misc.js` turns the facts into components.
13
+ */
14
+
15
+ /**
16
+ * Length of the bracket opener (`[[`, `[=[`, `[==[`, ...) at `text[start]`, or 0.
17
+ *
18
+ * @param {string} text CMake source
19
+ * @param {number} start Index of a `[`
20
+ * @returns {number} Opener length including both brackets, or 0
21
+ */
22
+ function bracketOpenLength(text, start) {
23
+ if (text[start] !== "[") {
24
+ return 0;
25
+ }
26
+ let i = start + 1;
27
+ while (text[i] === "=") {
28
+ i++;
29
+ }
30
+ return text[i] === "[" ? i - start + 1 : 0;
31
+ }
32
+
33
+ /**
34
+ * Index just past the bracket closer matching an opener of `openLength`.
35
+ *
36
+ * @param {string} text CMake source
37
+ * @param {number} contentStart First index after the opener
38
+ * @param {number} openLength Opener length (`[==[` is 4)
39
+ * @returns {number} Index after the closer, or the text length when unclosed
40
+ */
41
+ function bracketCloseEnd(text, contentStart, openLength) {
42
+ const closer = `]${"=".repeat(openLength - 2)}]`;
43
+ const end = text.indexOf(closer, contentStart);
44
+ return end === -1 ? text.length : end + closer.length;
45
+ }
46
+
47
+ /**
48
+ * Index of the end of the comment starting at `text[start]` (a `#`).
49
+ *
50
+ * @param {string} text CMake source
51
+ * @param {number} start Index of the `#`
52
+ * @returns {number} Index of the first character after the comment
53
+ */
54
+ function skipComment(text, start) {
55
+ const openLength = bracketOpenLength(text, start + 1);
56
+ if (openLength) {
57
+ return bracketCloseEnd(text, start + 1 + openLength, openLength);
58
+ }
59
+ const eol = text.indexOf("\n", start);
60
+ return eol === -1 ? text.length : eol;
61
+ }
62
+
63
+ function isIdentifierStart(c) {
64
+ return (c >= "A" && c <= "Z") || (c >= "a" && c <= "z") || c === "_";
65
+ }
66
+
67
+ function isIdentifierPart(c) {
68
+ return isIdentifierStart(c) || (c >= "0" && c <= "9");
69
+ }
70
+
71
+ function isSpace(c) {
72
+ return c === " " || c === "\t" || c === "\r" || c === "\n";
73
+ }
74
+
75
+ /**
76
+ * Split CMake source into command invocations.
77
+ *
78
+ * @param {string} text Contents of a CMake file
79
+ * @returns {{name: string, args: string[], line: number}[]} Invocations in
80
+ * source order. `name` is lower-cased; `args` have their quotes and bracket
81
+ * delimiters removed; `line` is the 1-based line of the command name.
82
+ */
83
+ export function parseCmakeCommands(text) {
84
+ const commands = [];
85
+ if (!text || typeof text !== "string") {
86
+ return commands;
87
+ }
88
+ let line = 1;
89
+ let i = 0;
90
+ const advanceTo = (end) => {
91
+ for (let k = i; k < end; k++) {
92
+ if (text[k] === "\n") {
93
+ line++;
94
+ }
95
+ }
96
+ i = end;
97
+ };
98
+ while (i < text.length) {
99
+ const c = text[i];
100
+ if (c === "#") {
101
+ advanceTo(skipComment(text, i));
102
+ continue;
103
+ }
104
+ if (!isIdentifierStart(c) || (i > 0 && isIdentifierPart(text[i - 1]))) {
105
+ advanceTo(i + 1);
106
+ continue;
107
+ }
108
+ let end = i;
109
+ while (end < text.length && isIdentifierPart(text[end])) {
110
+ end++;
111
+ }
112
+ const name = text.slice(i, end).toLowerCase();
113
+ const commandLine = line;
114
+ let open = end;
115
+ while (text[open] === " " || text[open] === "\t") {
116
+ open++;
117
+ }
118
+ if (text[open] !== "(") {
119
+ advanceTo(end);
120
+ continue;
121
+ }
122
+ advanceTo(open + 1);
123
+ const args = [];
124
+ let depth = 1;
125
+ let current = "";
126
+ let hasToken = false;
127
+ const flush = () => {
128
+ if (hasToken) {
129
+ args.push(current);
130
+ }
131
+ current = "";
132
+ hasToken = false;
133
+ };
134
+ while (i < text.length && depth > 0) {
135
+ const ch = text[i];
136
+ if (ch === "#") {
137
+ flush();
138
+ advanceTo(skipComment(text, i));
139
+ continue;
140
+ }
141
+ if (ch === '"') {
142
+ let k = i + 1;
143
+ let value = "";
144
+ while (k < text.length && text[k] !== '"') {
145
+ if (text[k] === "\\" && k + 1 < text.length) {
146
+ value += text[k + 1];
147
+ k += 2;
148
+ continue;
149
+ }
150
+ value += text[k];
151
+ k++;
152
+ }
153
+ current += value;
154
+ hasToken = true;
155
+ advanceTo(Math.min(k + 1, text.length));
156
+ continue;
157
+ }
158
+ const openLength = bracketOpenLength(text, i);
159
+ if (openLength && !hasToken) {
160
+ const contentStart = i + openLength;
161
+ const closeEnd = bracketCloseEnd(text, contentStart, openLength);
162
+ const contentEnd = Math.max(contentStart, closeEnd - openLength);
163
+ current += text.slice(contentStart, contentEnd);
164
+ hasToken = true;
165
+ advanceTo(closeEnd);
166
+ continue;
167
+ }
168
+ if (ch === "(") {
169
+ depth++;
170
+ } else if (ch === ")") {
171
+ depth--;
172
+ if (depth === 0) {
173
+ flush();
174
+ advanceTo(i + 1);
175
+ break;
176
+ }
177
+ }
178
+ if (isSpace(ch)) {
179
+ flush();
180
+ } else {
181
+ current += ch;
182
+ hasToken = true;
183
+ }
184
+ advanceTo(i + 1);
185
+ }
186
+ commands.push({ name, args, line: commandLine });
187
+ }
188
+ return commands;
189
+ }
190
+
191
+ /**
192
+ * Replace `${VAR}` references with the values of simple `set()` calls. A
193
+ * reference to an unknown variable is left in place, so callers can tell a
194
+ * resolved value from an unresolved one.
195
+ *
196
+ * @param {string} value Argument text
197
+ * @param {Map<string,string>} variables Known variable values
198
+ * @returns {string} The expanded text
199
+ */
200
+ export function expandCmakeVariables(value, variables) {
201
+ let result = value;
202
+ for (let round = 0; round < 5 && result.includes("${"); round++) {
203
+ let next = "";
204
+ let i = 0;
205
+ while (i < result.length) {
206
+ const start = result.indexOf("${", i);
207
+ if (start === -1) {
208
+ next += result.slice(i);
209
+ break;
210
+ }
211
+ const end = result.indexOf("}", start + 2);
212
+ if (end === -1) {
213
+ next += result.slice(i);
214
+ break;
215
+ }
216
+ const key = result.slice(start + 2, end);
217
+ next += result.slice(i, start);
218
+ next += variables.has(key)
219
+ ? variables.get(key)
220
+ : result.slice(start, end + 1);
221
+ i = end + 1;
222
+ }
223
+ if (next === result) {
224
+ break;
225
+ }
226
+ result = next;
227
+ }
228
+ return result;
229
+ }
230
+
231
+ /**
232
+ * The variables a file sets to a single value: `set(FOO_VERSION 1.2.3)` and
233
+ * `set(FOO_VERSION "1.2.3" CACHE STRING "...")`. Later definitions win.
234
+ *
235
+ * @param {{name: string, args: string[]}[]} commands Parsed commands
236
+ * @returns {Map<string,string>} Variable values
237
+ */
238
+ export function cmakeSetVariables(commands) {
239
+ const variables = new Map();
240
+ for (const command of commands) {
241
+ if (command.name !== "set" || command.args.length < 2) {
242
+ continue;
243
+ }
244
+ const [key, value, ...rest] = command.args;
245
+ if (
246
+ rest.length === 0 ||
247
+ rest[0] === "CACHE" ||
248
+ rest[0] === "PARENT_SCOPE"
249
+ ) {
250
+ variables.set(key, expandCmakeVariables(value, variables));
251
+ }
252
+ }
253
+ return variables;
254
+ }
255
+
256
+ /**
257
+ * The value following `keyword` in a keyword-style argument list, skipping the
258
+ * leading positional arguments.
259
+ *
260
+ * @param {string[]} args Command arguments
261
+ * @param {string} keyword Keyword to look up, e.g. `GIT_TAG`
262
+ * @param {number} from First index that may hold a keyword
263
+ * @returns {string|undefined} The value, or undefined when absent
264
+ */
265
+ function keywordValue(args, keyword, from) {
266
+ for (let i = from; i < args.length - 1; i++) {
267
+ if (args[i] === keyword) {
268
+ return args[i + 1];
269
+ }
270
+ }
271
+ return undefined;
272
+ }
273
+
274
+ const HOST_SHORTHANDS = {
275
+ gh: "https://github.com/",
276
+ gl: "https://gitlab.com/",
277
+ bb: "https://bitbucket.org/",
278
+ };
279
+
280
+ /**
281
+ * Read a CPM.cmake shorthand such as `gh:fmtlib/fmt#7.1.3`,
282
+ * `gh:nlohmann/json@3.11.2` or `https://example.com/x.git@1.0#v1.0`.
283
+ *
284
+ * @param {string} spec The single CPMAddPackage argument
285
+ * @returns {{name: string, gitRepository?: string, url?: string, gitTag?: string, version?: string}|undefined}
286
+ */
287
+ function parseCpmShorthand(spec) {
288
+ let rest = spec;
289
+ let gitTag;
290
+ let version;
291
+ const hash = rest.lastIndexOf("#");
292
+ if (hash !== -1) {
293
+ gitTag = rest.slice(hash + 1);
294
+ rest = rest.slice(0, hash);
295
+ }
296
+ const colon = rest.indexOf(":");
297
+ const scheme = colon === -1 ? "" : rest.slice(0, colon);
298
+ let repository;
299
+ if (HOST_SHORTHANDS[scheme]) {
300
+ let path = rest.slice(colon + 1);
301
+ const at = path.lastIndexOf("@");
302
+ if (at !== -1) {
303
+ version = path.slice(at + 1);
304
+ path = path.slice(0, at);
305
+ }
306
+ repository = `${HOST_SHORTHANDS[scheme]}${path}`;
307
+ } else if (scheme === "https" || scheme === "http") {
308
+ const lastSlash = rest.lastIndexOf("/");
309
+ const at = rest.lastIndexOf("@");
310
+ if (at > lastSlash) {
311
+ version = rest.slice(at + 1);
312
+ rest = rest.slice(0, at);
313
+ }
314
+ repository = rest;
315
+ } else {
316
+ return undefined;
317
+ }
318
+ const name = repository
319
+ .split("/")
320
+ .filter(Boolean)
321
+ .pop()
322
+ ?.replace(/\.git$/, "");
323
+ if (!name) {
324
+ return undefined;
325
+ }
326
+ return {
327
+ name,
328
+ gitRepository: repository,
329
+ gitTag: gitTag || (version ? `v${version}` : undefined),
330
+ version,
331
+ };
332
+ }
333
+
334
+ /**
335
+ * The dependencies a CMake file downloads at configure time.
336
+ *
337
+ * `FetchContent_Declare(<name> ...)` and `ExternalProject_Add(<name> ...)` are
338
+ * read for `GIT_REPOSITORY`/`GIT_TAG` and `URL`/`URL_HASH`/`URL_MD5`.
339
+ * `CPMAddPackage`, `CPMFindPackage` and `CPMDeclarePackage` are read in both
340
+ * the shorthand form and the keyword form (`NAME`, `VERSION`,
341
+ * `GITHUB_REPOSITORY`, `GITLAB_REPOSITORY`, `BITBUCKET_REPOSITORY`,
342
+ * `GIT_REPOSITORY`, `GIT_TAG`, `URL`, `URL_HASH`). `${VAR}` references are
343
+ * expanded with the file's simple `set()` values; anything still unresolved
344
+ * stays as written.
345
+ *
346
+ * @param {string} text Contents of a CMake file
347
+ * @returns {{kind: string, name: string, line: number, gitRepository?: string, gitTag?: string, url?: string, urlHash?: string, version?: string, madeAvailable: boolean}[]}
348
+ * `kind` is `fetch`, `external-project` or `cpm`; `madeAvailable` is true
349
+ * when a `FetchContent_MakeAvailable` in the same file names the dependency.
350
+ */
351
+ export function cmakeFetchDependencies(text) {
352
+ const commands = parseCmakeCommands(text);
353
+ const variables = cmakeSetVariables(commands);
354
+ const expand = (value) =>
355
+ value === undefined ? undefined : expandCmakeVariables(value, variables);
356
+ const madeAvailable = new Set();
357
+ for (const command of commands) {
358
+ if (command.name === "fetchcontent_makeavailable") {
359
+ for (const arg of command.args) {
360
+ madeAvailable.add(expand(arg).toLowerCase());
361
+ }
362
+ }
363
+ }
364
+ const deps = [];
365
+ for (const command of commands) {
366
+ const args = command.args.map(expand);
367
+ let dep;
368
+ if (
369
+ (command.name === "fetchcontent_declare" ||
370
+ command.name === "externalproject_add") &&
371
+ args.length
372
+ ) {
373
+ const url = keywordValue(args, "URL", 1);
374
+ const md5 = keywordValue(args, "URL_MD5", 1);
375
+ dep = {
376
+ kind:
377
+ command.name === "fetchcontent_declare"
378
+ ? "fetch"
379
+ : "external-project",
380
+ name: args[0],
381
+ gitRepository: keywordValue(args, "GIT_REPOSITORY", 1),
382
+ gitTag: keywordValue(args, "GIT_TAG", 1),
383
+ url: url?.split(";")[0],
384
+ urlHash: keywordValue(args, "URL_HASH", 1) || (md5 && `MD5=${md5}`),
385
+ };
386
+ } else if (
387
+ command.name === "cpmaddpackage" ||
388
+ command.name === "cpmfindpackage" ||
389
+ command.name === "cpmdeclarepackage"
390
+ ) {
391
+ const positional = command.name === "cpmdeclarepackage" ? 1 : 0;
392
+ if (args.length === positional + 1) {
393
+ const shorthand = parseCpmShorthand(args[positional]);
394
+ if (shorthand) {
395
+ dep = {
396
+ kind: "cpm",
397
+ ...shorthand,
398
+ name: positional ? args[0] : shorthand.name,
399
+ };
400
+ }
401
+ } else if (args.length > positional) {
402
+ const name = positional ? args[0] : keywordValue(args, "NAME", 0);
403
+ const version = keywordValue(args, "VERSION", positional);
404
+ const github = keywordValue(args, "GITHUB_REPOSITORY", positional);
405
+ const gitlab = keywordValue(args, "GITLAB_REPOSITORY", positional);
406
+ const bitbucket = keywordValue(
407
+ args,
408
+ "BITBUCKET_REPOSITORY",
409
+ positional,
410
+ );
411
+ const hosted =
412
+ (github && `${HOST_SHORTHANDS.gh}${github}`) ||
413
+ (gitlab && `${HOST_SHORTHANDS.gl}${gitlab}`) ||
414
+ (bitbucket && `${HOST_SHORTHANDS.bb}${bitbucket}`);
415
+ const gitRepository =
416
+ hosted || keywordValue(args, "GIT_REPOSITORY", positional);
417
+ const url = keywordValue(args, "URL", positional);
418
+ const derivedName =
419
+ name ||
420
+ (gitRepository || url)
421
+ ?.split("/")
422
+ .filter(Boolean)
423
+ .pop()
424
+ ?.replace(/\.git$/, "");
425
+ if (derivedName) {
426
+ dep = {
427
+ kind: "cpm",
428
+ name: derivedName,
429
+ gitRepository,
430
+ gitTag:
431
+ keywordValue(args, "GIT_TAG", positional) ||
432
+ (gitRepository && version ? `v${version}` : undefined),
433
+ url,
434
+ urlHash: keywordValue(args, "URL_HASH", positional),
435
+ version,
436
+ };
437
+ }
438
+ }
439
+ }
440
+ if (dep?.name) {
441
+ for (const key of Object.keys(dep)) {
442
+ if (dep[key] === undefined || dep[key] === "") {
443
+ delete dep[key];
444
+ }
445
+ }
446
+ dep.line = command.line;
447
+ dep.madeAvailable = madeAvailable.has(dep.name.toLowerCase());
448
+ deps.push(dep);
449
+ }
450
+ }
451
+ return deps;
452
+ }
@@ -237,9 +237,14 @@ export function toHuggingFacePurl(repoId, version, repositoryUrl) {
237
237
  * Normalize a direct Hugging Face URL or purl into a repo reference.
238
238
  *
239
239
  * @param {string} value direct URL, API URL, or purl
240
+ * @param {object} [parseOptions] parsing options
241
+ * @param {boolean} [parseOptions.explicitOnly=false] resolve only unambiguous
242
+ * references (`pkg:huggingface/...` purls and huggingface.co URLs) so that
243
+ * ambiguous `owner/repo`-shaped values keep their filesystem-path meaning
244
+ * until an AI inventory type is explicitly selected
240
245
  * @returns {{ assetType: string, repoId: string, version?: string }|undefined} normalized reference
241
246
  */
242
- export function normalizeHuggingFaceReference(value) {
247
+ export function normalizeHuggingFaceReference(value, parseOptions = {}) {
243
248
  if (!value) {
244
249
  return undefined;
245
250
  }
@@ -276,9 +281,11 @@ export function normalizeHuggingFaceReference(value) {
276
281
  // Fall through to the remaining parsers.
277
282
  }
278
283
  }
279
- const directTypedMatch = normalizedValue.match(
280
- /^(models|datasets|spaces)\/([^/\s]+\/[^/\s]+)(?:\/revision\/([^/\s?#]+))?$/u,
281
- );
284
+ const directTypedMatch = parseOptions.explicitOnly
285
+ ? undefined
286
+ : normalizedValue.match(
287
+ /^(models|datasets|spaces)\/([^/\s]+\/[^/\s]+)(?:\/revision\/([^/\s?#]+))?$/u,
288
+ );
282
289
  if (directTypedMatch) {
283
290
  return {
284
291
  assetType:
@@ -296,9 +303,10 @@ export function normalizeHuggingFaceReference(value) {
296
303
  const looksLikeFilesystemPath =
297
304
  /^(?:\/|\.{1,2}(?:\/|$)|~\/|[a-z]:[\\/])/iu.test(normalizedValue) ||
298
305
  normalizedValue.includes("\\");
299
- const directRepoId = looksLikeFilesystemPath
300
- ? undefined
301
- : sanitizeHuggingFaceRepoId(normalizedValue);
306
+ const directRepoId =
307
+ looksLikeFilesystemPath || parseOptions.explicitOnly
308
+ ? undefined
309
+ : sanitizeHuggingFaceRepoId(normalizedValue);
302
310
  if (directRepoId) {
303
311
  return { assetType: "model", repoId: directRepoId };
304
312
  }