@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
@@ -0,0 +1,277 @@
1
+ import { isIPv4, isIPv6 } from "node:net";
2
+ import { domainToASCII, domainToUnicode } from "node:url";
3
+
4
+ /**
5
+ * Validation of RFC 6531 internationalized email addresses: the JSON Schema
6
+ * `idn-email` format the CycloneDX schemas assert on contact addresses.
7
+ *
8
+ * It follows what `cdxrs validate` (jsonschema-rs) accepts, so the JS and Rust
9
+ * validators agree on the addresses BOMs actually carry, internationalized
10
+ * ones included. Two deliberate differences keep this small:
11
+ * - a `Display Name <address>` string is not an address here, as RFC 6531
12
+ * says; jsonschema-rs tolerates it, but cdxgen never emits one and the
13
+ * source parsers must not mistake one for an email;
14
+ * - the RFC 5892 contextual rules and the RFC 5893 bidi rule are not applied,
15
+ * so a few exotic internationalized domains are accepted that cdxrs
16
+ * rejects. No valid domain is rejected for that.
17
+ *
18
+ * Every check is a bounded pass over the input with no backtracking regular
19
+ * expression.
20
+ */
21
+
22
+ const LOCAL_PART_MAX_LENGTH = 64;
23
+ const HOSTNAME_MAX_LENGTH = 253;
24
+ const LABEL_MAX_LENGTH = 63;
25
+ const ATEXT_SPECIALS = "!#$%&'*+-/=?^_`{|}~";
26
+ // Appended before IDNA conversion so a numeric last label is not read as an
27
+ // IPv4 address by the WHATWG host parser behind `domainToASCII`.
28
+ const CONVERSION_SUFFIX = ".invalid";
29
+ // What an internationalized label may hold: letters, combining marks and
30
+ // decimal digits (RFC 5892 PVALID, by general category), plus the characters
31
+ // RFC 5892 makes PVALID by exception, such as the Catalan middle dot.
32
+ const IDNA_LABEL_CHAR = /^[\p{L}\p{Mn}\p{Mc}\p{Nd}]$/u;
33
+ const IDNA_EXCEPTIONS = new Set([
34
+ "·",
35
+ "͵",
36
+ "׳",
37
+ "״",
38
+ "۽",
39
+ "۾",
40
+ "་",
41
+ "‌",
42
+ "‍",
43
+ "〇",
44
+ "・",
45
+ ]);
46
+ const COMBINING_MARK = /^\p{M}$/u;
47
+
48
+ /**
49
+ * @param {string} text Text to inspect
50
+ * @returns {boolean} Whether the text holds only ASCII
51
+ */
52
+ const isAscii = (text) => {
53
+ for (let index = 0; index < text.length; index++) {
54
+ if (text.charCodeAt(index) > 0x7f) {
55
+ return false;
56
+ }
57
+ }
58
+ return true;
59
+ };
60
+
61
+ /**
62
+ * @param {number} code Code point
63
+ * @returns {boolean} Whether the code point is an ASCII letter or digit
64
+ */
65
+ const isAsciiAlphanumeric = (code) =>
66
+ (code >= 0x30 && code <= 0x39) ||
67
+ (code >= 0x41 && code <= 0x5a) ||
68
+ (code >= 0x61 && code <= 0x7a);
69
+
70
+ /**
71
+ * RFC 5322 `atext`, widened by RFC 6531 to every non-ASCII code point.
72
+ *
73
+ * @param {string} char One code point
74
+ * @returns {boolean} Whether it may appear in an unquoted local part atom
75
+ */
76
+ const isAtext = (char) => {
77
+ const code = char.codePointAt(0);
78
+ return (
79
+ code > 0x7f || isAsciiAlphanumeric(code) || ATEXT_SPECIALS.includes(char)
80
+ );
81
+ };
82
+
83
+ /**
84
+ * The content of a quoted local part: printable ASCII other than `"` and `\`,
85
+ * non-ASCII, spaces and tabs, and backslash-escaped printable characters.
86
+ *
87
+ * @param {string} text Quoted local part without its surrounding quotes
88
+ * @returns {boolean} Whether the quoted content is valid
89
+ */
90
+ const isQuotedContent = (text) => {
91
+ const chars = [...text];
92
+ for (let index = 0; index < chars.length; index++) {
93
+ const code = chars[index].codePointAt(0);
94
+ if (code === 0x5c) {
95
+ index++;
96
+ const escaped = chars[index]?.codePointAt(0);
97
+ if (escaped === undefined || escaped < 0x21 || escaped === 0x7f) {
98
+ return false;
99
+ }
100
+ } else if (code < 0x20 || code === 0x22 || code === 0x7f) {
101
+ if (code !== 0x09) {
102
+ return false;
103
+ }
104
+ }
105
+ }
106
+ return true;
107
+ };
108
+
109
+ /**
110
+ * A dot-atom (`atext` atoms joined by single dots) or a quoted string, at
111
+ * most 64 characters.
112
+ *
113
+ * @param {string} localPart Text before the last `@`
114
+ * @returns {boolean} Whether it is a valid local part
115
+ */
116
+ const isValidLocalPart = (localPart) => {
117
+ if (!localPart || [...localPart].length > LOCAL_PART_MAX_LENGTH) {
118
+ return false;
119
+ }
120
+ if (
121
+ localPart.length >= 2 &&
122
+ localPart.startsWith('"') &&
123
+ localPart.endsWith('"')
124
+ ) {
125
+ // An empty quoted local part (`""@example.com`) is valid per RFC 5321.
126
+ return isQuotedContent(localPart.slice(1, -1));
127
+ }
128
+ return localPart
129
+ .split(".")
130
+ .every((atom) => atom.length > 0 && [...atom].every(isAtext));
131
+ };
132
+
133
+ /**
134
+ * An RFC 1123 label in ASCII (A-label) form.
135
+ *
136
+ * @param {string} label ASCII label
137
+ * @returns {boolean} Whether the label is valid
138
+ */
139
+ const isValidAsciiLabel = (label) => {
140
+ if (
141
+ !label ||
142
+ label.length > LABEL_MAX_LENGTH ||
143
+ label.startsWith("-") ||
144
+ label.endsWith("-")
145
+ ) {
146
+ return false;
147
+ }
148
+ for (let index = 0; index < label.length; index++) {
149
+ const code = label.charCodeAt(index);
150
+ if (!isAsciiAlphanumeric(code) && code !== 0x2d) {
151
+ return false;
152
+ }
153
+ }
154
+ // Hyphens in the third and fourth positions are reserved for A-labels.
155
+ return label.slice(2, 4) !== "--" || label.toLowerCase().startsWith("xn--");
156
+ };
157
+
158
+ /**
159
+ * The Unicode form of a label, as `domainToUnicode` returns it.
160
+ *
161
+ * @param {string} label Unicode label
162
+ * @returns {boolean} Whether the label is valid
163
+ */
164
+ const isValidUnicodeLabel = (label) => {
165
+ // `domainToUnicode` leaves an undecodable A-label as it was.
166
+ if (label.toLowerCase().startsWith("xn--")) {
167
+ return false;
168
+ }
169
+ if (isAscii(label)) {
170
+ return true;
171
+ }
172
+ if (
173
+ label.startsWith("-") ||
174
+ label.endsWith("-") ||
175
+ label.slice(2, 4) === "--"
176
+ ) {
177
+ return false;
178
+ }
179
+ const chars = [...label];
180
+ return (
181
+ !COMBINING_MARK.test(chars[0]) &&
182
+ chars.every(
183
+ (char) =>
184
+ char.charCodeAt(0) <= 0x7f ||
185
+ IDNA_EXCEPTIONS.has(char) ||
186
+ IDNA_LABEL_CHAR.test(char),
187
+ )
188
+ );
189
+ };
190
+
191
+ /**
192
+ * An internationalized hostname: mapped to its A-label form with UTS #46
193
+ * processing, held to the ASCII hostname rules, and every A-label decoded
194
+ * back and checked for the characters IDNA allows.
195
+ *
196
+ * @param {string} hostname Hostname, possibly holding non-ASCII labels
197
+ * @returns {boolean} Whether it is a valid IDN hostname
198
+ */
199
+ export const isValidIdnHostname = (hostname) => {
200
+ if (typeof hostname !== "string" || !hostname) {
201
+ return false;
202
+ }
203
+ for (let index = 0; index < hostname.length; index++) {
204
+ // Controls and spaces never belong in a hostname; the WHATWG parser
205
+ // behind `domainToASCII` would silently strip tabs and newlines.
206
+ const code = hostname.charCodeAt(index);
207
+ if (code <= 0x20 || code === 0x7f) {
208
+ return false;
209
+ }
210
+ }
211
+ let ascii = hostname;
212
+ if (!isAscii(hostname)) {
213
+ const converted = domainToASCII(`${hostname}${CONVERSION_SUFFIX}`);
214
+ if (!converted.endsWith(CONVERSION_SUFFIX)) {
215
+ return false;
216
+ }
217
+ ascii = converted.slice(0, -CONVERSION_SUFFIX.length);
218
+ }
219
+ if (
220
+ !ascii ||
221
+ ascii.length > HOSTNAME_MAX_LENGTH ||
222
+ ascii.endsWith(".") ||
223
+ !ascii.split(".").every(isValidAsciiLabel)
224
+ ) {
225
+ return false;
226
+ }
227
+ if (!/(^|\.)xn--/i.test(ascii)) {
228
+ return true;
229
+ }
230
+ const unicode = domainToUnicode(`${ascii}${CONVERSION_SUFFIX}`);
231
+ return (
232
+ unicode.endsWith(CONVERSION_SUFFIX) &&
233
+ unicode
234
+ .slice(0, -CONVERSION_SUFFIX.length)
235
+ .split(".")
236
+ .every(isValidUnicodeLabel)
237
+ );
238
+ };
239
+
240
+ /**
241
+ * @param {string} domain Text after the last `@`
242
+ * @returns {boolean} Whether it is a valid hostname or address literal
243
+ */
244
+ const isValidEmailDomain = (domain) => {
245
+ if (domain.startsWith("[") && domain.endsWith("]")) {
246
+ const literal = domain.slice(1, -1);
247
+ // RFC 5321 address-literal tags are case-insensitive.
248
+ if (literal.slice(0, 5).toLowerCase() === "ipv6:") {
249
+ return isIPv6(literal.slice(5));
250
+ }
251
+ return isIPv4(literal);
252
+ }
253
+ return isValidIdnHostname(domain);
254
+ };
255
+
256
+ /**
257
+ * Whether a value is a valid RFC 6531 email address (`idn-email`): a dot-atom
258
+ * or quoted local part, where non-ASCII characters are allowed, then `@` and
259
+ * an internationalized hostname or a bracketed IPv4/IPv6 literal.
260
+ *
261
+ * @param {string} value Candidate email address
262
+ * @returns {boolean} true when the value is a valid address
263
+ */
264
+ export const isValidIdnEmail = (value) => {
265
+ if (typeof value !== "string") {
266
+ return false;
267
+ }
268
+ // A domain never holds `@`; a quoted local part may.
269
+ const separator = value.lastIndexOf("@");
270
+ if (separator <= 0 || separator === value.length - 1) {
271
+ return false;
272
+ }
273
+ return (
274
+ isValidLocalPart(value.slice(0, separator)) &&
275
+ isValidEmailDomain(value.slice(separator + 1))
276
+ );
277
+ };
@@ -256,8 +256,9 @@ class ByteCursor {
256
256
 
257
257
  // The members of the object at the cursor, as { key, start, end } byte ranges
258
258
  // of their values, in file order. A repeated key keeps its first position and
259
- // its last range, which is what JSON.parse does.
260
- function scanObjectMembers(cursor) {
259
+ // its last range, which is what JSON.parse does. With `stopAt`, the scan ends
260
+ // at the first member of that name, leaving the rest of the object unread.
261
+ function scanObjectMembers(cursor, stopAt = undefined) {
261
262
  if (cursor.nextToken() !== OPEN_BRACE) {
262
263
  cursor.fail("Expected an object");
263
264
  }
@@ -280,6 +281,9 @@ function scanObjectMembers(cursor) {
280
281
  const start = cursor.offset;
281
282
  cursor.skipValue();
282
283
  members.set(key, { start, end: cursor.offset });
284
+ if (key === stopAt) {
285
+ return members;
286
+ }
283
287
  const delimiter = cursor.nextToken();
284
288
  if (delimiter === CLOSE_BRACE) {
285
289
  return members;
@@ -412,6 +416,34 @@ export function indexJsonObject(filePath, options = {}) {
412
416
  });
413
417
  }
414
418
 
419
+ /**
420
+ * Decode one member of the top-level object in a JSON file, reading the file
421
+ * only up to the end of that member. A member near the start of a large file
422
+ * costs a few bounded reads, however large the rest of the file is; the rest
423
+ * is not checked for well-formedness.
424
+ *
425
+ * @param {string} filePath JSON file whose top-level value is an object
426
+ * @param {string} name Member to decode
427
+ * @param {Object} [options] Batch and chunk size overrides, for tests
428
+ * @returns {*} The decoded value, or undefined when the object has no such member
429
+ * @throws {SyntaxError} When the object is malformed before the member ends
430
+ */
431
+ export function readJsonMember(filePath, name, options = {}) {
432
+ const resolved = resolveOptions(options);
433
+ return withFile(filePath, (fd) => {
434
+ const cursor = new ByteCursor(
435
+ fd,
436
+ 0,
437
+ statSync(filePath).size,
438
+ resolved.chunkBytes,
439
+ );
440
+ const range = scanObjectMembers(cursor, name).get(name);
441
+ return range
442
+ ? decodeRange(fd, range.start, range.end, undefined, resolved)
443
+ : undefined;
444
+ });
445
+ }
446
+
415
447
  /**
416
448
  * Decode the JSON value stored in a byte range of a file, without ever holding
417
449
  * more than a bounded run of it in one string.
@@ -0,0 +1,322 @@
1
+ /**
2
+ * Strict JSON reading for signed documents.
3
+ *
4
+ * JSF signs the RFC 8785 (JCS) form of a document, and JCS is defined over
5
+ * I-JSON (RFC 7493) input. `JSON.parse` and lenient UTF-8 decoding accept
6
+ * things I-JSON rules out, and each lets two parsers read different values
7
+ * from the same signed bytes:
8
+ *
9
+ * - a member name repeated within one object, where `JSON.parse` keeps the last
10
+ * value and other parsers keep the first or refuse the document;
11
+ * - a number an IEEE 754 double cannot hold exactly, which JavaScript rounds
12
+ * while arbitrary-precision parsers keep every digit;
13
+ * - bytes that are not UTF-8, which lenient decoders turn into U+FFFD while
14
+ * others refuse them or read another encoding;
15
+ * - an unpaired UTF-16 surrogate escape, which some parsers keep and others
16
+ * replace.
17
+ *
18
+ * {@link parseStrictJson} rejects all of them, so the values a verifier checks
19
+ * are the values every consumer of the document reads.
20
+ */
21
+
22
+ /**
23
+ * Raised when JSON text is well-formed but breaks one of the rules above.
24
+ */
25
+ export class StrictJsonError extends Error {
26
+ /**
27
+ * @param {string} message - Description of the problem
28
+ * @param {string} pointer - RFC 6901 JSON Pointer to the offending member or value
29
+ */
30
+ constructor(message, pointer) {
31
+ super(message);
32
+ this.name = "StrictJsonError";
33
+ this.pointer = pointer;
34
+ }
35
+ }
36
+
37
+ const QUOTE = 0x22;
38
+ const BACKSLASH = 0x5c;
39
+ const OPEN_OBJECT = 0x7b;
40
+ const CLOSE_OBJECT = 0x7d;
41
+ const OPEN_ARRAY = 0x5b;
42
+ const CLOSE_ARRAY = 0x5d;
43
+ const COMMA = 0x2c;
44
+ const MINUS = 0x2d;
45
+ const PLUS = 0x2b;
46
+ const DOT = 0x2e;
47
+ const DIGIT_0 = 0x30;
48
+ const DIGIT_9 = 0x39;
49
+ const LOWER_E = 0x65;
50
+ const UPPER_E = 0x45;
51
+ const LOWER_U = 0x75;
52
+
53
+ // Integers with at most 15 digits are below 2^53, so a double holds them exactly.
54
+ const EXACT_INTEGER_DIGITS = 15;
55
+ const MAX_SHOWN_NUMBER_LENGTH = 40;
56
+
57
+ function isDigit(code) {
58
+ return code >= DIGIT_0 && code <= DIGIT_9;
59
+ }
60
+
61
+ function escapePointerToken(token) {
62
+ return token.replaceAll("~", "~0").replaceAll("/", "~1");
63
+ }
64
+
65
+ function pointerOf(frames, depth) {
66
+ let pointer = "";
67
+ for (let i = 0; i < depth; i++) {
68
+ const frame = frames[i];
69
+ pointer += `/${frame.object ? escapePointerToken(frame.key) : frame.index}`;
70
+ }
71
+ return pointer;
72
+ }
73
+
74
+ function showNumber(token) {
75
+ return token.length > MAX_SHOWN_NUMBER_LENGTH
76
+ ? `${token.slice(0, MAX_SHOWN_NUMBER_LENGTH)}…`
77
+ : token;
78
+ }
79
+
80
+ /**
81
+ * Reduces a JSON or ECMAScript number literal to its exact decimal value as a
82
+ * significand without leading or trailing zeros and a power-of-ten exponent.
83
+ * The sign is ignored: a finite non-zero double keeps the sign of its literal,
84
+ * and zero compares equal to negative zero.
85
+ */
86
+ function decimalValue(literal) {
87
+ let i = literal.charCodeAt(0) === MINUS ? 1 : 0;
88
+ let digits = "";
89
+ let fractionLength = 0;
90
+ while (i < literal.length && isDigit(literal.charCodeAt(i))) {
91
+ digits += literal[i++];
92
+ }
93
+ if (literal.charCodeAt(i) === DOT) {
94
+ i++;
95
+ while (i < literal.length && isDigit(literal.charCodeAt(i))) {
96
+ digits += literal[i++];
97
+ fractionLength++;
98
+ }
99
+ }
100
+ let exponent = 0;
101
+ const marker = literal.charCodeAt(i);
102
+ if (marker === LOWER_E || marker === UPPER_E) {
103
+ exponent = Number(literal.slice(i + 1));
104
+ }
105
+ let start = 0;
106
+ while (start < digits.length && digits.charCodeAt(start) === DIGIT_0) {
107
+ start++;
108
+ }
109
+ let end = digits.length;
110
+ while (end > start && digits.charCodeAt(end - 1) === DIGIT_0) {
111
+ end--;
112
+ }
113
+ if (start === end) {
114
+ return { significand: "", exponent: 0 };
115
+ }
116
+ return {
117
+ significand: digits.slice(start, end),
118
+ exponent: exponent - fractionLength + (digits.length - end),
119
+ };
120
+ }
121
+
122
+ /**
123
+ * Returns a description of why a JSON number token does not denote exactly the
124
+ * double that `JSON.parse` produces for it, or undefined when it does.
125
+ */
126
+ function numberProblem(token) {
127
+ const negative = token.charCodeAt(0) === MINUS;
128
+ const digitCount = token.length - (negative ? 1 : 0);
129
+ if (digitCount <= EXACT_INTEGER_DIGITS) {
130
+ let integer = true;
131
+ for (let i = negative ? 1 : 0; i < token.length; i++) {
132
+ if (!isDigit(token.charCodeAt(i))) {
133
+ integer = false;
134
+ break;
135
+ }
136
+ }
137
+ if (integer) {
138
+ return undefined;
139
+ }
140
+ }
141
+ const value = Number(token);
142
+ if (!Number.isFinite(value)) {
143
+ return "is outside the range of an IEEE 754 double";
144
+ }
145
+ const written = decimalValue(token);
146
+ const parsed = decimalValue(String(value));
147
+ if (
148
+ written.significand === parsed.significand &&
149
+ (written.significand === "" || written.exponent === parsed.exponent)
150
+ ) {
151
+ return undefined;
152
+ }
153
+ return `cannot be held exactly by an IEEE 754 double; JSON.parse reads it as ${String(value)}`;
154
+ }
155
+
156
+ function isHighSurrogate(unit) {
157
+ return unit >= 0xd800 && unit <= 0xdbff;
158
+ }
159
+
160
+ function isLowSurrogate(unit) {
161
+ return unit >= 0xdc00 && unit <= 0xdfff;
162
+ }
163
+
164
+ /**
165
+ * Finds the end of the string token starting at `start`, and whether it holds
166
+ * escapes or a UTF-16 surrogate, written raw or as `\u` escape, without its
167
+ * other half.
168
+ */
169
+ function stringEnd(text, start) {
170
+ let i = start + 1;
171
+ let escaped = false;
172
+ let unpaired = false;
173
+ let pendingHigh = false;
174
+ for (;;) {
175
+ const code = text.charCodeAt(i);
176
+ if (code === QUOTE) {
177
+ return { end: i + 1, escaped, unpaired: unpaired || pendingHigh };
178
+ }
179
+ let unit = code;
180
+ let width = 1;
181
+ if (code === BACKSLASH) {
182
+ escaped = true;
183
+ if (text.charCodeAt(i + 1) === LOWER_U) {
184
+ unit = Number.parseInt(text.slice(i + 2, i + 6), 16);
185
+ width = 6;
186
+ } else {
187
+ unit = 0;
188
+ width = 2;
189
+ }
190
+ }
191
+ const low = isLowSurrogate(unit);
192
+ if (pendingHigh !== low) {
193
+ unpaired = true;
194
+ }
195
+ pendingHigh = isHighSurrogate(unit);
196
+ i += width;
197
+ }
198
+ }
199
+
200
+ function numberEnd(text, start) {
201
+ let i = start;
202
+ while (i < text.length) {
203
+ const code = text.charCodeAt(i);
204
+ if (
205
+ isDigit(code) ||
206
+ code === MINUS ||
207
+ code === PLUS ||
208
+ code === DOT ||
209
+ code === LOWER_E ||
210
+ code === UPPER_E
211
+ ) {
212
+ i++;
213
+ } else {
214
+ break;
215
+ }
216
+ }
217
+ return i;
218
+ }
219
+
220
+ /**
221
+ * Walks well-formed JSON text without recursion and throws a StrictJsonError
222
+ * at the first repeated member name, inexact number, or unpaired surrogate.
223
+ */
224
+ function checkStrictJson(text) {
225
+ const frames = [];
226
+ let i = 0;
227
+ while (i < text.length) {
228
+ const code = text.charCodeAt(i);
229
+ if (code === OPEN_OBJECT || code === OPEN_ARRAY) {
230
+ frames.push({
231
+ object: code === OPEN_OBJECT,
232
+ names: code === OPEN_OBJECT ? new Set() : undefined,
233
+ key: undefined,
234
+ index: 0,
235
+ expectName: code === OPEN_OBJECT,
236
+ });
237
+ i++;
238
+ } else if (code === CLOSE_OBJECT || code === CLOSE_ARRAY) {
239
+ frames.pop();
240
+ i++;
241
+ } else if (code === COMMA) {
242
+ const top = frames.at(-1);
243
+ if (top.object) {
244
+ top.expectName = true;
245
+ } else {
246
+ top.index++;
247
+ }
248
+ i++;
249
+ } else if (code === QUOTE) {
250
+ const { end, escaped, unpaired } = stringEnd(text, i);
251
+ const top = frames.at(-1);
252
+ const isName = Boolean(top?.object && top.expectName);
253
+ if (unpaired) {
254
+ const pointer = isName
255
+ ? `${pointerOf(frames, frames.length - 1)}/${escapePointerToken(JSON.parse(text.slice(i, end)))}`
256
+ : pointerOf(frames, frames.length);
257
+ throw new StrictJsonError(
258
+ `The ${isName ? "member name" : "string"} at ${pointer || "the document root"} holds an unpaired UTF-16 surrogate, which JSON parsers keep, replace, or reject differently.`,
259
+ pointer,
260
+ );
261
+ }
262
+ if (isName) {
263
+ const name = escaped
264
+ ? JSON.parse(text.slice(i, end))
265
+ : text.slice(i + 1, end - 1);
266
+ if (top.names.has(name)) {
267
+ throw new StrictJsonError(
268
+ `Duplicate member name at ${pointerOf(frames, frames.length - 1)}/${escapePointerToken(name)}. JSON parsers disagree on which of the repeated values the document holds.`,
269
+ `${pointerOf(frames, frames.length - 1)}/${escapePointerToken(name)}`,
270
+ );
271
+ }
272
+ top.names.add(name);
273
+ top.key = name;
274
+ top.expectName = false;
275
+ }
276
+ i = end;
277
+ } else if (code === MINUS || isDigit(code)) {
278
+ const end = numberEnd(text, i);
279
+ const token = text.slice(i, end);
280
+ const problem = numberProblem(token);
281
+ if (problem) {
282
+ const pointer = pointerOf(frames, frames.length);
283
+ throw new StrictJsonError(
284
+ `The number ${showNumber(token)} at ${pointer || "the document root"} ${problem}.`,
285
+ pointer,
286
+ );
287
+ }
288
+ i = end;
289
+ } else {
290
+ i++;
291
+ }
292
+ }
293
+ }
294
+
295
+ /**
296
+ * Parses JSON the way `JSON.parse` does, but refuses bytes that are not UTF-8,
297
+ * repeated member names within an object, numbers that an IEEE 754 double
298
+ * cannot hold exactly, and unpaired UTF-16 surrogates.
299
+ *
300
+ * Pass the raw bytes of a document rather than text decoded elsewhere, so that
301
+ * invalid UTF-8 is detected instead of being replaced by U+FFFD.
302
+ *
303
+ * @param {string|Uint8Array} input - JSON text, or its UTF-8 bytes
304
+ * @returns {any} - The parsed value
305
+ * @throws {SyntaxError} When the text is not JSON
306
+ * @throws {StrictJsonError} When the input breaks one of the rules above
307
+ */
308
+ export function parseStrictJson(input) {
309
+ let text = input;
310
+ if (typeof input !== "string") {
311
+ try {
312
+ text = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(
313
+ input,
314
+ );
315
+ } catch {
316
+ throw new StrictJsonError("The document is not valid UTF-8.", "");
317
+ }
318
+ }
319
+ const value = JSON.parse(text);
320
+ checkStrictJson(text);
321
+ return value;
322
+ }