@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
@@ -10,7 +10,9 @@ import {
10
10
  import { communityAiConfigParser } from "./communityAiConfigParser.js";
11
11
  import { mergeServices, trimComponents } from "./depsUtils.js";
12
12
  import { classifyMcpReference } from "./mcp.js";
13
+ import { mcpbBundleParser } from "./mcpbBundle.js";
13
14
  import { mcpConfigParser } from "./mcpConfigParser.js";
15
+ import { mcpServerManifestParser } from "./mcpServerManifest.js";
14
16
 
15
17
  /** Project types treated as AI-related inventory for collection and parsing. */
16
18
  export const AI_INVENTORY_PROJECT_TYPES = ["mcp", "ai-skill", "ai"];
@@ -64,6 +66,16 @@ const AI_INVENTORY_PARSERS = [
64
66
  parser: mcpConfigParser,
65
67
  types: ["mcp"],
66
68
  },
69
+ {
70
+ id: mcpServerManifestParser.id,
71
+ parser: mcpServerManifestParser,
72
+ types: ["mcp"],
73
+ },
74
+ {
75
+ id: mcpbBundleParser.id,
76
+ parser: mcpbBundleParser,
77
+ types: ["mcp"],
78
+ },
67
79
  {
68
80
  id: communityAiConfigParser.id,
69
81
  parser: communityAiConfigParser,
@@ -25,6 +25,23 @@ import {
25
25
  } from "./analyzerScope.js";
26
26
  import { classifyMcpReference } from "./mcp.js";
27
27
  import { isLocalHost, sanitizeMcpRefToken } from "./mcpDiscovery.js";
28
+ import {
29
+ isPackageStyleUrlReference,
30
+ STYLE_PACKAGE_REFERENCE_PATTERNS,
31
+ } from "./stylePackageRefs.js";
32
+ import {
33
+ extractSvelteScriptLanguages,
34
+ extractSvelteStyleReferences,
35
+ findSvelteRunes,
36
+ getSvelteTemplateParser,
37
+ maskSvelteScripts,
38
+ parseSvelteConfigSource,
39
+ primeSvelteParser,
40
+ SVELTE_DEFAULT_LIB_ALIAS,
41
+ SVELTE_KIT_VIRTUAL_MODULE_PREFIXES,
42
+ SVELTE_SCRIPT_EXECUTABLE_PACKAGE_MAP,
43
+ SVELTE_STYLE_LANG_PACKAGES,
44
+ } from "./svelteUtils.js";
28
45
 
29
46
  const IGNORE_DIRS = readEnvironmentVariable("ASTGEN_IGNORE_DIRS")
30
47
  ? readEnvironmentVariable("ASTGEN_IGNORE_DIRS").split(",")
@@ -53,7 +70,7 @@ const IGNORE_DIRS = readEnvironmentVariable("ASTGEN_IGNORE_DIRS")
53
70
 
54
71
  const IGNORE_FILE_PATTERN = new RegExp(
55
72
  readEnvironmentVariable("ASTGEN_IGNORE_FILE_PATTERN") ||
56
- "(test|spec|mock|setup-jest|\\.d)\\.(js|ts|tsx)$|(?<!vite\\.|vue\\.)(conf|config)\\.(js|ts|tsx)$",
73
+ "(test|spec|mock|setup-jest|\\.d)\\.(js|ts|tsx)$|(?<!vite\\.|vue\\.|svelte\\.)(conf|config)\\.(js|ts|tsx)$",
57
74
  "i",
58
75
  );
59
76
 
@@ -327,7 +344,15 @@ const vueBindRegex = /(:\[)([\s\S]*?)(])/gi;
327
344
 
328
345
  const fileToParseableCode = (file) => {
329
346
  let code = readFileSync(file, "utf-8");
330
- if (file.endsWith(".vue") || file.endsWith(".svelte")) {
347
+ if (file.endsWith(".svelte")) {
348
+ // Svelte components have no <template> element — markup sits at the top
349
+ // level — so the Vue blanking path would leave the raw Svelte markup in
350
+ // the Babel input. Mask everything outside the script bodies instead;
351
+ // the mask preserves offsets and newlines, so import line numbers stay
352
+ // true to the original file.
353
+ return maskSvelteScripts(code);
354
+ }
355
+ if (file.endsWith(".vue")) {
331
356
  code = code
332
357
  .replace(vueCommentRegex, (match) => match.replaceAll(/\S/g, " "))
333
358
  .replace(
@@ -355,6 +380,49 @@ const fileToParseableCode = (file) => {
355
380
  return code;
356
381
  };
357
382
 
383
+ /**
384
+ * Read a file and produce its Babel `File` AST. `.svelte` components prefer
385
+ * the optional atom-parsetools template parser (which re-emits the markup as
386
+ * JSX with absolute offsets) and fall back to a Babel parse of the masked
387
+ * script buffer, both position-preserving. Every other extension goes through
388
+ * `fileToParseableCode` unchanged.
389
+ *
390
+ * @param {string} file Absolute file path.
391
+ * @returns {Object} Babel `File` AST.
392
+ */
393
+ const parseSourceFileAST = (file) => {
394
+ if (!file.endsWith(".svelte")) {
395
+ return parse(fileToParseableCode(file), babelParserOptions);
396
+ }
397
+ const code = readFileSync(file, "utf-8");
398
+ const maskedSource = maskSvelteScripts(code);
399
+ const templateParser = getSvelteTemplateParser();
400
+ if (templateParser) {
401
+ try {
402
+ return templateParser.parseSvelteFile(file, code, babelParserOptions);
403
+ } catch (err) {
404
+ // A genuinely broken template must not abort the component: parse the
405
+ // masked script buffer, recording the template failure when the
406
+ // fallback entry point is available. If that also throws, fall through
407
+ // to the built-in mask parse below.
408
+ try {
409
+ if (typeof templateParser.parseSvelteScriptBuffer === "function") {
410
+ return templateParser.parseSvelteScriptBuffer(
411
+ file,
412
+ code,
413
+ maskedSource,
414
+ babelParserOptions,
415
+ err?.message || String(err),
416
+ );
417
+ }
418
+ } catch (_fallbackErr) {
419
+ // ignore — the tier 1 parse below is the last resort
420
+ }
421
+ }
422
+ }
423
+ return parse(maskedSource, babelParserOptions);
424
+ };
425
+
358
426
  const isWasmPath = (modulePath) =>
359
427
  typeof modulePath === "string" && /\.wasm([?#].*)?$/i.test(modulePath);
360
428
 
@@ -414,11 +482,6 @@ const ANGULAR_WORKSPACE_PACKAGE_STRING_KEYS = new Set([
414
482
 
415
483
  const ANGULAR_STYLE_FILE_EXTENSIONS = [".css", ".less", ".sass", ".scss"];
416
484
 
417
- const ANGULAR_STYLE_REFERENCE_PATTERNS = [
418
- /@(?:import|use|forward)\s+(?:url\(\s*)?['"]([^'"\n)]+)['"]/g,
419
- /url\(\s*['"](~?[^'"\n)]+)['"]\s*\)/g,
420
- ];
421
-
422
485
  const ANGULAR_CONFIG_EVIDENCE_FILE_NAMES = new Set([
423
486
  "karma.conf.js",
424
487
  "karma.conf.cjs",
@@ -626,16 +689,6 @@ const angularUrlRegex = /^[a-z][a-z0-9+.-]*:/i;
626
689
  const angularBareFileRegex =
627
690
  /^[\w.-]+\.(css|eot|gif|html|ico|jpeg|jpg|js|json|less|mjs|png|sass|scss|svg|ts|ttf|webp|woff|woff2)$/i;
628
691
 
629
- const isAngularStyleUrlPackageReference = (reference) => {
630
- const normalizedReference = String(reference || "")
631
- .trim()
632
- .replaceAll("\\", "/");
633
- return (
634
- normalizedReference.startsWith("~") ||
635
- normalizedReference.startsWith("node_modules/")
636
- );
637
- };
638
-
639
692
  const stripAngularRouteFragment = (reference) =>
640
693
  String(reference || "")
641
694
  .split("#")[0]
@@ -770,19 +823,19 @@ const extractScriptSegmentExecutableName = (scriptSegment) => {
770
823
  };
771
824
  };
772
825
 
773
- const addAngularExecutablePackageRef = (
826
+ const addScriptExecutablePackageRef = (
774
827
  allImports,
775
828
  allExports,
776
829
  src,
777
830
  file,
778
831
  executable,
832
+ executablePackageMap,
779
833
  ) => {
780
834
  const executableName = executable?.executableName;
781
835
  if (!executableName) {
782
836
  return;
783
837
  }
784
- const packageName =
785
- ANGULAR_SCRIPT_EXECUTABLE_PACKAGE_MAP[executableName.toLowerCase()];
838
+ const packageName = executablePackageMap[executableName.toLowerCase()];
786
839
  if (packageName) {
787
840
  setAngularPackageRef(
788
841
  allImports,
@@ -1103,7 +1156,7 @@ const getAssignmentTargetName = (astNode) => {
1103
1156
  * references for any import, require or dynamic import files.
1104
1157
  */
1105
1158
  const parseFileASTTree = (src, file, allImports, allExports) => {
1106
- const ast = parse(fileToParseableCode(file), babelParserOptions);
1159
+ const ast = parseSourceFileAST(file);
1107
1160
  const wasmBufferByVarName = new Map();
1108
1161
  const wasmResultByVarName = new Map();
1109
1162
  const wasmInstanceByVarName = new Map();
@@ -2105,7 +2158,7 @@ const parseAngularStyleFiles = (
2105
2158
  } catch {
2106
2159
  continue;
2107
2160
  }
2108
- for (const referencePattern of ANGULAR_STYLE_REFERENCE_PATTERNS) {
2161
+ for (const referencePattern of STYLE_PACKAGE_REFERENCE_PATTERNS) {
2109
2162
  for (const match of content.matchAll(referencePattern)) {
2110
2163
  const reference = match[1];
2111
2164
  if (!reference) {
@@ -2113,7 +2166,7 @@ const parseAngularStyleFiles = (
2113
2166
  }
2114
2167
  if (
2115
2168
  match[0]?.trim().startsWith("url") &&
2116
- !isAngularStyleUrlPackageReference(reference)
2169
+ !isPackageStyleUrlReference(reference)
2117
2170
  ) {
2118
2171
  continue;
2119
2172
  }
@@ -2136,12 +2189,19 @@ const parseAngularStyleFiles = (
2136
2189
  }
2137
2190
  };
2138
2191
 
2139
- const addAngularScriptPackageRefs = (
2192
+ /**
2193
+ * Walk an npm script value's shell segments and attribute each leading
2194
+ * executable to the npm package that provides it, using the given
2195
+ * executable→package map plus the `cdx:npm:bin/` fallback for npx-style
2196
+ * package hints. Shared by the Angular and Svelte script-evidence passes.
2197
+ */
2198
+ const addScriptExecutableSegmentRefs = (
2140
2199
  allImports,
2141
2200
  allExports,
2142
2201
  src,
2143
2202
  file,
2144
2203
  scriptValue,
2204
+ executablePackageMap,
2145
2205
  ) => {
2146
2206
  const script = String(scriptValue || "");
2147
2207
  if (!script) {
@@ -2153,14 +2213,33 @@ const addAngularScriptPackageRefs = (
2153
2213
  .filter(Boolean);
2154
2214
  for (const scriptSegment of scriptSegments) {
2155
2215
  const executable = extractScriptSegmentExecutableName(scriptSegment);
2156
- addAngularExecutablePackageRef(
2216
+ addScriptExecutablePackageRef(
2157
2217
  allImports,
2158
2218
  allExports,
2159
2219
  src,
2160
2220
  file,
2161
2221
  executable,
2222
+ executablePackageMap,
2162
2223
  );
2163
2224
  }
2225
+ };
2226
+
2227
+ const addAngularScriptPackageRefs = (
2228
+ allImports,
2229
+ allExports,
2230
+ src,
2231
+ file,
2232
+ scriptValue,
2233
+ ) => {
2234
+ addScriptExecutableSegmentRefs(
2235
+ allImports,
2236
+ allExports,
2237
+ src,
2238
+ file,
2239
+ scriptValue,
2240
+ ANGULAR_SCRIPT_EXECUTABLE_PACKAGE_MAP,
2241
+ );
2242
+ const script = String(scriptValue || "");
2164
2243
  for (const commandPackage of ANGULAR_SCRIPT_COMMAND_PACKAGES) {
2165
2244
  if (commandPackage.pattern.test(script)) {
2166
2245
  for (const packageName of commandPackage.packages) {
@@ -2953,7 +3032,7 @@ const parseVueConfigFiles = (
2953
3032
  if (!dataValue) {
2954
3033
  continue;
2955
3034
  }
2956
- for (const referencePattern of ANGULAR_STYLE_REFERENCE_PATTERNS) {
3035
+ for (const referencePattern of STYLE_PACKAGE_REFERENCE_PATTERNS) {
2957
3036
  referencePattern.lastIndex = 0;
2958
3037
  for (const styleMatch of dataValue.matchAll(referencePattern)) {
2959
3038
  const reference = styleMatch[1];
@@ -2962,7 +3041,7 @@ const parseVueConfigFiles = (
2962
3041
  }
2963
3042
  if (
2964
3043
  styleMatch[0]?.trim().startsWith("url") &&
2965
- !isAngularStyleUrlPackageReference(reference)
3044
+ !isPackageStyleUrlReference(reference)
2966
3045
  ) {
2967
3046
  continue;
2968
3047
  }
@@ -2980,6 +3059,363 @@ const parseVueConfigFiles = (
2980
3059
  }
2981
3060
  };
2982
3061
 
3062
+ // ---------------------------------------------------------------------------
3063
+ // Svelte / SvelteKit evidence
3064
+ // ---------------------------------------------------------------------------
3065
+
3066
+ const SVELTE_CONFIG_FILE_NAMES = new Set([
3067
+ "svelte.config.cjs",
3068
+ "svelte.config.js",
3069
+ "svelte.config.mjs",
3070
+ "svelte.config.mts",
3071
+ "svelte.config.ts",
3072
+ ]);
3073
+
3074
+ const SVELTE_RUNE_MODULE_EXTENSIONS = [".svelte.js", ".svelte.ts"];
3075
+
3076
+ const getFilesByBaseNames = (
3077
+ dir,
3078
+ fileNames,
3079
+ deep,
3080
+ result = [],
3081
+ rootDir = dir,
3082
+ excludePatterns = [],
3083
+ noIgnore = false,
3084
+ ) => {
3085
+ let files;
3086
+ try {
3087
+ files = readdirSync(dir);
3088
+ } catch {
3089
+ return result;
3090
+ }
3091
+ for (const entry of files) {
3092
+ if (!noIgnore && entry.startsWith(".")) {
3093
+ continue;
3094
+ }
3095
+ const file = join(dir, entry);
3096
+ let fileStat;
3097
+ try {
3098
+ fileStat = lstatSync(file);
3099
+ } catch {
3100
+ continue;
3101
+ }
3102
+ if (fileStat.isSymbolicLink()) {
3103
+ continue;
3104
+ }
3105
+ if (
3106
+ shouldExcludeAnalyzerPath(
3107
+ rootDir,
3108
+ file,
3109
+ excludePatterns,
3110
+ fileStat.isDirectory(),
3111
+ )
3112
+ ) {
3113
+ continue;
3114
+ }
3115
+ if (fileStat.isDirectory()) {
3116
+ const dirName = basename(file);
3117
+ if (
3118
+ !noIgnore &&
3119
+ (dirName.startsWith("__") ||
3120
+ IGNORE_DIRS.includes(dirName.toLowerCase()) ||
3121
+ dirName === "node_modules")
3122
+ ) {
3123
+ continue;
3124
+ }
3125
+ if (deep) {
3126
+ getFilesByBaseNames(
3127
+ file,
3128
+ fileNames,
3129
+ deep,
3130
+ result,
3131
+ rootDir,
3132
+ excludePatterns,
3133
+ noIgnore,
3134
+ );
3135
+ }
3136
+ continue;
3137
+ }
3138
+ if (fileNames.has(entry)) {
3139
+ result.push(file);
3140
+ }
3141
+ }
3142
+ return result;
3143
+ };
3144
+
3145
+ const getLineColumnFromIndex = (content, index) => {
3146
+ const clampedIndex = Math.max(
3147
+ 0,
3148
+ Math.min(Number(index) || 0, String(content).length),
3149
+ );
3150
+ const prefix = content.slice(0, clampedIndex);
3151
+ const prefixLines = prefix.split(/\r?\n/);
3152
+ return {
3153
+ column: prefixLines[prefixLines.length - 1].length,
3154
+ line: prefixLines.length,
3155
+ };
3156
+ };
3157
+
3158
+ const hasSvelteComponentEvidence = (allImports) =>
3159
+ Object.keys(allImports).some(
3160
+ (importName) =>
3161
+ importName === "svelte" ||
3162
+ importName.startsWith("svelte/") ||
3163
+ importName.startsWith("@sveltejs/"),
3164
+ );
3165
+
3166
+ /**
3167
+ * Attribute framework usage recorded inside a Svelte component: the Svelte
3168
+ * compiler itself (component presence plus rune usage), the CSS
3169
+ * preprocessor required by `<style lang="…">`, packages referenced from
3170
+ * style-block `@use`/`@import`/`url()` rules, and `typescript` for
3171
+ * `<script lang="ts">`.
3172
+ */
3173
+ const addSvelteComponentRefs = (allImports, allExports, src, file, content) => {
3174
+ setSyntheticImportRef(allImports, allExports, src, file, "svelte", [], {
3175
+ column: 0,
3176
+ line: 1,
3177
+ });
3178
+ for (const styleBlock of extractSvelteStyleReferences(content)) {
3179
+ const stylePackage = SVELTE_STYLE_LANG_PACKAGES[styleBlock.lang || ""];
3180
+ if (stylePackage) {
3181
+ setSyntheticImportRef(
3182
+ allImports,
3183
+ allExports,
3184
+ src,
3185
+ file,
3186
+ stylePackage,
3187
+ [],
3188
+ getLineColumnFromIndex(content, styleBlock.start),
3189
+ );
3190
+ }
3191
+ for (const styleReference of styleBlock.references) {
3192
+ setAngularPackageRef(
3193
+ allImports,
3194
+ allExports,
3195
+ src,
3196
+ file,
3197
+ styleReference.reference,
3198
+ getLineColumnFromIndex(content, styleReference.index),
3199
+ );
3200
+ }
3201
+ }
3202
+ for (const scriptLang of extractSvelteScriptLanguages(content)) {
3203
+ if (scriptLang === "ts" || scriptLang === "typescript") {
3204
+ setSyntheticImportRef(
3205
+ allImports,
3206
+ allExports,
3207
+ src,
3208
+ file,
3209
+ "typescript",
3210
+ [],
3211
+ { column: 0, line: 1 },
3212
+ );
3213
+ }
3214
+ }
3215
+ for (const rune of findSvelteRunes(content, true)) {
3216
+ setSyntheticImportRef(
3217
+ allImports,
3218
+ allExports,
3219
+ src,
3220
+ file,
3221
+ "svelte",
3222
+ [],
3223
+ getLineColumnFromIndex(content, rune.index),
3224
+ );
3225
+ }
3226
+ };
3227
+
3228
+ const addSvelteConfigRefs = (allImports, allExports, src, file, facts) => {
3229
+ // `adapter: "netlify"` names an adapter package without importing it; the
3230
+ // imported form (`import adapter from "@sveltejs/adapter-node"`) is already
3231
+ // collected by the regular config-file parse.
3232
+ const adapterName = facts.adapterName;
3233
+ if (adapterName) {
3234
+ const packageName = adapterName.startsWith("@")
3235
+ ? adapterName
3236
+ : `@sveltejs/adapter-${adapterName}`;
3237
+ setSyntheticImportRef(allImports, allExports, src, file, packageName, [], {
3238
+ column: 0,
3239
+ line: 1,
3240
+ });
3241
+ }
3242
+ };
3243
+
3244
+ const normalizeSvelteAliasTarget = (aliasTarget) =>
3245
+ String(aliasTarget || "")
3246
+ .replaceAll("\\", "/")
3247
+ .replace(/^\.\//, "")
3248
+ .replace(/\/+$/, "");
3249
+
3250
+ /**
3251
+ * Re-key SvelteKit virtual modules and path aliases so they never surface as
3252
+ * junk package names: `$app/*`, `$env/*`, and `$service-worker` become
3253
+ * `@sveltejs/kit` evidence (the package that provides those modules), and
3254
+ * `$lib/*` plus any configured `$alias/*` become relative file references.
3255
+ * Original occurrences are kept, so file and line evidence survives.
3256
+ */
3257
+ const reattributeSvelteKitModules = (allImports, _allExports, kitAliases) => {
3258
+ const aliasEntries = Object.entries(kitAliases || {}).filter(([aliasKey]) =>
3259
+ aliasKey.startsWith("$"),
3260
+ );
3261
+ for (const importKey of Object.keys(allImports)) {
3262
+ const isVirtualModule = SVELTE_KIT_VIRTUAL_MODULE_PREFIXES.some(
3263
+ (prefix) => importKey === prefix || importKey.startsWith(`${prefix}/`),
3264
+ );
3265
+ const aliasEntry = aliasEntries.find(
3266
+ ([aliasKey]) =>
3267
+ importKey === aliasKey || importKey.startsWith(`${aliasKey}/`),
3268
+ );
3269
+ if (!isVirtualModule && !aliasEntry) {
3270
+ continue;
3271
+ }
3272
+ const occurrences = allImports[importKey] || [];
3273
+ const targetKey = isVirtualModule
3274
+ ? "@sveltejs/kit"
3275
+ : aliasEntry
3276
+ ? importKey === aliasEntry[0]
3277
+ ? normalizeSvelteAliasTarget(aliasEntry[1])
3278
+ : `${normalizeSvelteAliasTarget(aliasEntry[1])}/${importKey.slice(aliasEntry[0].length + 1)}`
3279
+ : undefined;
3280
+ if (!targetKey) {
3281
+ delete allImports[importKey];
3282
+ continue;
3283
+ }
3284
+ allImports[targetKey] = allImports[targetKey] || new Set();
3285
+ for (const occurrence of occurrences) {
3286
+ if (isVirtualModule) {
3287
+ allImports[targetKey].add(occurrence);
3288
+ } else {
3289
+ // A path alias resolves inside the project, never to a package.
3290
+ allImports[targetKey].add({
3291
+ ...occurrence,
3292
+ importedAs: importKey,
3293
+ isExternal: false,
3294
+ });
3295
+ }
3296
+ }
3297
+ delete allImports[importKey];
3298
+ }
3299
+ };
3300
+
3301
+ /**
3302
+ * Collect Svelte framework evidence after the main parse fan-out: component
3303
+ * facts (runes, style/script languages, style package references),
3304
+ * `svelte.config.*` facts (string-form adapter, `kit.alias`), npm script
3305
+ * executables (`svelte-kit sync`, `svelte-check`, ...), and re-attribution
3306
+ * of SvelteKit virtual modules. Returns the resolved alias map (or undefined
3307
+ * when the project shows no Svelte evidence at all).
3308
+ *
3309
+ * `srcFiles` is the file list the parse fan-out already walked, so the Svelte
3310
+ * pass costs no extra directory traversal on projects that turn out not to be
3311
+ * Svelte projects at all.
3312
+ */
3313
+ const parseSvelteEvidenceFiles = (
3314
+ src,
3315
+ allImports,
3316
+ allExports,
3317
+ searchOptions,
3318
+ srcFiles,
3319
+ ) => {
3320
+ const componentFiles = [];
3321
+ const runeModuleFiles = [];
3322
+ for (const srcFile of srcFiles || []) {
3323
+ if (srcFile.endsWith(".svelte")) {
3324
+ componentFiles.push(srcFile);
3325
+ } else if (
3326
+ SVELTE_RUNE_MODULE_EXTENSIONS.some((extension) =>
3327
+ srcFile.endsWith(extension),
3328
+ )
3329
+ ) {
3330
+ runeModuleFiles.push(srcFile);
3331
+ }
3332
+ }
3333
+ if (
3334
+ !componentFiles.length &&
3335
+ !runeModuleFiles.length &&
3336
+ !hasSvelteComponentEvidence(allImports)
3337
+ ) {
3338
+ return undefined;
3339
+ }
3340
+ for (const componentFile of componentFiles) {
3341
+ let content;
3342
+ try {
3343
+ content = readFileSync(componentFile, "utf-8");
3344
+ } catch {
3345
+ continue;
3346
+ }
3347
+ addSvelteComponentRefs(allImports, allExports, src, componentFile, content);
3348
+ }
3349
+ for (const runeModuleFile of runeModuleFiles) {
3350
+ let content;
3351
+ try {
3352
+ content = readFileSync(runeModuleFile, "utf-8");
3353
+ } catch {
3354
+ continue;
3355
+ }
3356
+ for (const rune of findSvelteRunes(content, false)) {
3357
+ setSyntheticImportRef(
3358
+ allImports,
3359
+ allExports,
3360
+ src,
3361
+ runeModuleFile,
3362
+ "svelte",
3363
+ [],
3364
+ getLineColumnFromIndex(content, rune.index),
3365
+ );
3366
+ }
3367
+ }
3368
+ const configAndManifestFiles = getFilesByBaseNames(
3369
+ src,
3370
+ new Set([...SVELTE_CONFIG_FILE_NAMES, "package.json"]),
3371
+ searchOptions.deep,
3372
+ [],
3373
+ src,
3374
+ searchOptions.exclude,
3375
+ searchOptions.noIgnore,
3376
+ );
3377
+ const kitAliases = {};
3378
+ for (const evidenceFile of configAndManifestFiles) {
3379
+ const evidenceFileName = basename(evidenceFile);
3380
+ let content;
3381
+ try {
3382
+ content = readFileSync(evidenceFile, "utf-8");
3383
+ } catch {
3384
+ continue;
3385
+ }
3386
+ if (SVELTE_CONFIG_FILE_NAMES.has(evidenceFileName)) {
3387
+ const facts = parseSvelteConfigSource(content);
3388
+ addSvelteConfigRefs(allImports, allExports, src, evidenceFile, facts);
3389
+ Object.assign(kitAliases, facts.aliases);
3390
+ } else {
3391
+ let packageJson;
3392
+ try {
3393
+ packageJson = JSON.parse(content);
3394
+ } catch {
3395
+ continue;
3396
+ }
3397
+ if (!packageJson?.scripts || typeof packageJson.scripts !== "object") {
3398
+ continue;
3399
+ }
3400
+ for (const scriptValue of Object.values(packageJson.scripts)) {
3401
+ addScriptExecutableSegmentRefs(
3402
+ allImports,
3403
+ allExports,
3404
+ src,
3405
+ evidenceFile,
3406
+ scriptValue,
3407
+ SVELTE_SCRIPT_EXECUTABLE_PACKAGE_MAP,
3408
+ );
3409
+ }
3410
+ }
3411
+ }
3412
+ if (!kitAliases.$lib) {
3413
+ kitAliases.$lib = SVELTE_DEFAULT_LIB_ALIAS;
3414
+ }
3415
+ reattributeSvelteKitModules(allImports, allExports, kitAliases);
3416
+ return kitAliases;
3417
+ };
3418
+
2983
3419
  /**
2984
3420
  * Total source volume, in bytes, below which the file walk stays on the calling
2985
3421
  * thread even when the file count would allow threads.
@@ -3037,6 +3473,11 @@ export const findJSImportsExports = async (src, deep) => {
3037
3473
  const allExports = {};
3038
3474
  try {
3039
3475
  const searchOptions = normalizeAnalyzerSearchOptions(deep);
3476
+ // Resolve the optional Svelte template parser before the fan-out so the
3477
+ // inline path can use it; worker threads resolve it lazily at module
3478
+ // scope of astWorker.js. Absence is silent — tier 1 covers all scope
3479
+ // evidence.
3480
+ await primeSvelteParser();
3040
3481
  const promiseMap = await getAllSrcJSAndTSFiles(src, deep);
3041
3482
  const srcFiles = promiseMap.flat();
3042
3483
  const tasks = srcFiles.map((file) => ({ src, file }));
@@ -3119,6 +3560,13 @@ export const findJSImportsExports = async (src, deep) => {
3119
3560
  searchOptions.exclude,
3120
3561
  searchOptions.noIgnore,
3121
3562
  );
3563
+ parseSvelteEvidenceFiles(
3564
+ src,
3565
+ allImports,
3566
+ allExports,
3567
+ searchOptions,
3568
+ srcFiles,
3569
+ );
3122
3570
  return { allImports, allExports };
3123
3571
  } catch (_err) {
3124
3572
  return { allImports, allExports };
@@ -4229,7 +4677,7 @@ export const detectExtensionCapabilities = (src, deep = false) => {
4229
4677
  };
4230
4678
  for (const file of srcFiles) {
4231
4679
  try {
4232
- const ast = parse(fileToParseableCode(file), babelParserOptions);
4680
+ const ast = parseSourceFileAST(file);
4233
4681
  traverse(ast, {
4234
4682
  MemberExpression: (path) => {
4235
4683
  addSignal(getMemberChainString(path?.node));
@@ -4276,6 +4724,7 @@ const MCP_STDIO_TRANSPORT_NAMES = new Set(["StdioServerTransport"]);
4276
4724
  const MCP_HTTP_TRANSPORT_NAMES = new Set([
4277
4725
  "NodeStreamableHTTPServerTransport",
4278
4726
  "StreamableHTTPServerTransport",
4727
+ "WebStandardsStreamableHTTPServerTransport",
4279
4728
  ]);
4280
4729
  const MCP_STDIO_CLIENT_TRANSPORT_NAMES = new Set(["StdioClientTransport"]);
4281
4730
  const MCP_HTTP_CLIENT_TRANSPORT_NAMES = new Set([
@@ -4289,7 +4738,7 @@ const MCP_AUTH_HELPERS = new Set([
4289
4738
  "createProtectedResourceMetadataRouter",
4290
4739
  "setupAuthServer",
4291
4740
  ]);
4292
- const MCP_APP_FACTORIES = new Set(["createMcpExpressApp"]);
4741
+ const MCP_APP_FACTORIES = new Set(["createMcpExpressApp", "createMcpHandler"]);
4293
4742
  const MCP_CLIENT_CONSTRUCTOR_NAMES = new Set([
4294
4743
  "Client",
4295
4744
  "MCPClient",
@@ -4345,6 +4794,15 @@ const MCP_PROVIDER_HOST_PATTERNS = [
4345
4794
  ["deepseek", /(?:^|\.)deepseek\.com$/i],
4346
4795
  ["ollama", /(?:^|\.)ollama\.com$/i],
4347
4796
  ["groq", /(?:^|\.)groq\.com$/i],
4797
+ ["xai", /(?:^|\.)x\.ai$/i],
4798
+ [
4799
+ "aws-bedrock",
4800
+ /(?:^|\.)bedrock(?:-runtime)?(?:\.[a-z0-9-]+)?\.amazonaws\.com$/i,
4801
+ ],
4802
+ ["openrouter", /(?:^|\.)openrouter\.ai$/i],
4803
+ ["cerebras", /(?:^|\.)api\.cerebras\.ai$/i],
4804
+ ["dashscope", /(?:^|\.)dashscope(?:-intl)?\.aliyuncs\.com$/i],
4805
+ ["nvidia-nim", /(?:^|\.)integrate\.api\.nvidia\.com$/i],
4348
4806
  ];
4349
4807
 
4350
4808
  const providerFamilyFromImportSource = (sourceValue) => {
@@ -5447,7 +5905,7 @@ export const detectMcpInventory = (src, deep = false) => {
5447
5905
  const authMetadataByAlias = new Map();
5448
5906
  let fileHasMcpImports = false;
5449
5907
  try {
5450
- const ast = parse(fileToParseableCode(file), babelParserOptions);
5908
+ const ast = parseSourceFileAST(file);
5451
5909
  traverse(ast, {
5452
5910
  ImportDeclaration: (path) => {
5453
5911
  const sourceValue = getLiteralStringValue(path?.node?.source);