api-tests-coverage 1.0.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 (288) hide show
  1. package/README.md +703 -0
  2. package/config.yaml.example +227 -0
  3. package/dist/action/src/index.d.ts +2 -0
  4. package/dist/action/src/index.d.ts.map +1 -0
  5. package/dist/action/src/index.js +349 -0
  6. package/dist/action/src/prComment.d.ts +34 -0
  7. package/dist/action/src/prComment.d.ts.map +1 -0
  8. package/dist/action/src/prComment.js +146 -0
  9. package/dist/src/ast/astAnalysisOrchestrator.d.ts +36 -0
  10. package/dist/src/ast/astAnalysisOrchestrator.d.ts.map +1 -0
  11. package/dist/src/ast/astAnalysisOrchestrator.js +123 -0
  12. package/dist/src/ast/astTypes.d.ts +105 -0
  13. package/dist/src/ast/astTypes.d.ts.map +1 -0
  14. package/dist/src/ast/astTypes.js +9 -0
  15. package/dist/src/ast/languageAnalyzer.d.ts +46 -0
  16. package/dist/src/ast/languageAnalyzer.d.ts.map +1 -0
  17. package/dist/src/ast/languageAnalyzer.js +9 -0
  18. package/dist/src/ast/languageCapabilities.d.ts +24 -0
  19. package/dist/src/ast/languageCapabilities.d.ts.map +1 -0
  20. package/dist/src/ast/languageCapabilities.js +92 -0
  21. package/dist/src/ast/parseFile.d.ts +16 -0
  22. package/dist/src/ast/parseFile.d.ts.map +1 -0
  23. package/dist/src/ast/parseFile.js +65 -0
  24. package/dist/src/ast/parserRegistry.d.ts +39 -0
  25. package/dist/src/ast/parserRegistry.d.ts.map +1 -0
  26. package/dist/src/ast/parserRegistry.js +66 -0
  27. package/dist/src/buildSummary.d.ts +26 -0
  28. package/dist/src/buildSummary.d.ts.map +1 -0
  29. package/dist/src/buildSummary.js +193 -0
  30. package/dist/src/businessCoverage.d.ts +68 -0
  31. package/dist/src/businessCoverage.d.ts.map +1 -0
  32. package/dist/src/businessCoverage.js +290 -0
  33. package/dist/src/compatibilityCoverage.d.ts +83 -0
  34. package/dist/src/compatibilityCoverage.d.ts.map +1 -0
  35. package/dist/src/compatibilityCoverage.js +501 -0
  36. package/dist/src/config/defaultConfig.d.ts +9 -0
  37. package/dist/src/config/defaultConfig.d.ts.map +1 -0
  38. package/dist/src/config/defaultConfig.js +97 -0
  39. package/dist/src/config/index.d.ts +12 -0
  40. package/dist/src/config/index.d.ts.map +1 -0
  41. package/dist/src/config/index.js +37 -0
  42. package/dist/src/config/loadConfig.d.ts +29 -0
  43. package/dist/src/config/loadConfig.d.ts.map +1 -0
  44. package/dist/src/config/loadConfig.js +135 -0
  45. package/dist/src/config/mergeConfig.d.ts +15 -0
  46. package/dist/src/config/mergeConfig.d.ts.map +1 -0
  47. package/dist/src/config/mergeConfig.js +57 -0
  48. package/dist/src/config/schema.d.ts +15 -0
  49. package/dist/src/config/schema.d.ts.map +1 -0
  50. package/dist/src/config/schema.js +30 -0
  51. package/dist/src/config/types.d.ts +175 -0
  52. package/dist/src/config/types.d.ts.map +1 -0
  53. package/dist/src/config/types.js +9 -0
  54. package/dist/src/config/validateConfig.d.ts +22 -0
  55. package/dist/src/config/validateConfig.d.ts.map +1 -0
  56. package/dist/src/config/validateConfig.js +171 -0
  57. package/dist/src/config.d.ts +168 -0
  58. package/dist/src/config.d.ts.map +1 -0
  59. package/dist/src/config.js +204 -0
  60. package/dist/src/coverage/deep-analysis/callGraph.d.ts +67 -0
  61. package/dist/src/coverage/deep-analysis/callGraph.d.ts.map +1 -0
  62. package/dist/src/coverage/deep-analysis/callGraph.js +275 -0
  63. package/dist/src/coverage/deep-analysis/deepEndpointResolver.d.ts +23 -0
  64. package/dist/src/coverage/deep-analysis/deepEndpointResolver.d.ts.map +1 -0
  65. package/dist/src/coverage/deep-analysis/deepEndpointResolver.js +394 -0
  66. package/dist/src/coverage/deep-analysis/index.d.ts +17 -0
  67. package/dist/src/coverage/deep-analysis/index.d.ts.map +1 -0
  68. package/dist/src/coverage/deep-analysis/index.js +63 -0
  69. package/dist/src/coverage/deep-analysis/resolveAssertions.d.ts +60 -0
  70. package/dist/src/coverage/deep-analysis/resolveAssertions.d.ts.map +1 -0
  71. package/dist/src/coverage/deep-analysis/resolveAssertions.js +121 -0
  72. package/dist/src/coverage/deep-analysis/resolveConstants.d.ts +36 -0
  73. package/dist/src/coverage/deep-analysis/resolveConstants.d.ts.map +1 -0
  74. package/dist/src/coverage/deep-analysis/resolveConstants.js +92 -0
  75. package/dist/src/coverage/deep-analysis/resolveEnums.d.ts +55 -0
  76. package/dist/src/coverage/deep-analysis/resolveEnums.d.ts.map +1 -0
  77. package/dist/src/coverage/deep-analysis/resolveEnums.js +152 -0
  78. package/dist/src/coverage/deep-analysis/resolveMethodChains.d.ts +70 -0
  79. package/dist/src/coverage/deep-analysis/resolveMethodChains.d.ts.map +1 -0
  80. package/dist/src/coverage/deep-analysis/resolveMethodChains.js +152 -0
  81. package/dist/src/coverage/deep-analysis/resolvePaths.d.ts +80 -0
  82. package/dist/src/coverage/deep-analysis/resolvePaths.d.ts.map +1 -0
  83. package/dist/src/coverage/deep-analysis/resolvePaths.js +216 -0
  84. package/dist/src/coverage/deep-analysis/resolveRequestWrappers.d.ts +71 -0
  85. package/dist/src/coverage/deep-analysis/resolveRequestWrappers.d.ts.map +1 -0
  86. package/dist/src/coverage/deep-analysis/resolveRequestWrappers.js +226 -0
  87. package/dist/src/coverage/deep-analysis/symbolTable.d.ts +58 -0
  88. package/dist/src/coverage/deep-analysis/symbolTable.d.ts.map +1 -0
  89. package/dist/src/coverage/deep-analysis/symbolTable.js +230 -0
  90. package/dist/src/coverage/deep-analysis/types.d.ts +122 -0
  91. package/dist/src/coverage/deep-analysis/types.d.ts.map +1 -0
  92. package/dist/src/coverage/deep-analysis/types.js +21 -0
  93. package/dist/src/discovery/fileClassifier.d.ts +50 -0
  94. package/dist/src/discovery/fileClassifier.d.ts.map +1 -0
  95. package/dist/src/discovery/fileClassifier.js +238 -0
  96. package/dist/src/discovery/projectDiscovery.d.ts +66 -0
  97. package/dist/src/discovery/projectDiscovery.d.ts.map +1 -0
  98. package/dist/src/discovery/projectDiscovery.js +287 -0
  99. package/dist/src/endpointCoverage.d.ts +70 -0
  100. package/dist/src/endpointCoverage.d.ts.map +1 -0
  101. package/dist/src/endpointCoverage.js +381 -0
  102. package/dist/src/errorCoverage.d.ts +93 -0
  103. package/dist/src/errorCoverage.d.ts.map +1 -0
  104. package/dist/src/errorCoverage.js +698 -0
  105. package/dist/src/index.d.ts +3 -0
  106. package/dist/src/index.d.ts.map +1 -0
  107. package/dist/src/index.js +1441 -0
  108. package/dist/src/inference/businessRuleInference.d.ts +63 -0
  109. package/dist/src/inference/businessRuleInference.d.ts.map +1 -0
  110. package/dist/src/inference/businessRuleInference.js +268 -0
  111. package/dist/src/inference/integrationFlowInference.d.ts +56 -0
  112. package/dist/src/inference/integrationFlowInference.d.ts.map +1 -0
  113. package/dist/src/inference/integrationFlowInference.js +266 -0
  114. package/dist/src/integrationCoverage.d.ts +72 -0
  115. package/dist/src/integrationCoverage.d.ts.map +1 -0
  116. package/dist/src/integrationCoverage.js +317 -0
  117. package/dist/src/intelligence/index.d.ts +20 -0
  118. package/dist/src/intelligence/index.d.ts.map +1 -0
  119. package/dist/src/intelligence/index.js +105 -0
  120. package/dist/src/intelligence/linkageEngine.d.ts +20 -0
  121. package/dist/src/intelligence/linkageEngine.d.ts.map +1 -0
  122. package/dist/src/intelligence/linkageEngine.js +522 -0
  123. package/dist/src/intelligence/markdownReporter.d.ts +12 -0
  124. package/dist/src/intelligence/markdownReporter.d.ts.map +1 -0
  125. package/dist/src/intelligence/markdownReporter.js +265 -0
  126. package/dist/src/intelligence/riskScoring.d.ts +53 -0
  127. package/dist/src/intelligence/riskScoring.d.ts.map +1 -0
  128. package/dist/src/intelligence/riskScoring.js +181 -0
  129. package/dist/src/intelligence/types.d.ts +121 -0
  130. package/dist/src/intelligence/types.d.ts.map +1 -0
  131. package/dist/src/intelligence/types.js +8 -0
  132. package/dist/src/languageDetection.d.ts +100 -0
  133. package/dist/src/languageDetection.d.ts.map +1 -0
  134. package/dist/src/languageDetection.js +349 -0
  135. package/dist/src/languages/java/index.d.ts +16 -0
  136. package/dist/src/languages/java/index.d.ts.map +1 -0
  137. package/dist/src/languages/java/index.js +103 -0
  138. package/dist/src/languages/java/parser.d.ts +7 -0
  139. package/dist/src/languages/java/parser.d.ts.map +1 -0
  140. package/dist/src/languages/java/parser.js +50 -0
  141. package/dist/src/languages/java/semanticBuilder.d.ts +21 -0
  142. package/dist/src/languages/java/semanticBuilder.d.ts.map +1 -0
  143. package/dist/src/languages/java/semanticBuilder.js +358 -0
  144. package/dist/src/languages/javascript/annotationExtractor.d.ts +20 -0
  145. package/dist/src/languages/javascript/annotationExtractor.d.ts.map +1 -0
  146. package/dist/src/languages/javascript/annotationExtractor.js +94 -0
  147. package/dist/src/languages/javascript/assertionResolver.d.ts +18 -0
  148. package/dist/src/languages/javascript/assertionResolver.d.ts.map +1 -0
  149. package/dist/src/languages/javascript/assertionResolver.js +150 -0
  150. package/dist/src/languages/javascript/callResolver.d.ts +23 -0
  151. package/dist/src/languages/javascript/callResolver.d.ts.map +1 -0
  152. package/dist/src/languages/javascript/callResolver.js +236 -0
  153. package/dist/src/languages/javascript/httpInteractionExtractor.d.ts +23 -0
  154. package/dist/src/languages/javascript/httpInteractionExtractor.d.ts.map +1 -0
  155. package/dist/src/languages/javascript/httpInteractionExtractor.js +205 -0
  156. package/dist/src/languages/javascript/index.d.ts +20 -0
  157. package/dist/src/languages/javascript/index.d.ts.map +1 -0
  158. package/dist/src/languages/javascript/index.js +136 -0
  159. package/dist/src/languages/javascript/parser.d.ts +14 -0
  160. package/dist/src/languages/javascript/parser.d.ts.map +1 -0
  161. package/dist/src/languages/javascript/parser.js +38 -0
  162. package/dist/src/languages/javascript/symbolResolver.d.ts +31 -0
  163. package/dist/src/languages/javascript/symbolResolver.d.ts.map +1 -0
  164. package/dist/src/languages/javascript/symbolResolver.js +183 -0
  165. package/dist/src/languages/kotlin/index.d.ts +16 -0
  166. package/dist/src/languages/kotlin/index.d.ts.map +1 -0
  167. package/dist/src/languages/kotlin/index.js +151 -0
  168. package/dist/src/languages/kotlin/parser.d.ts +11 -0
  169. package/dist/src/languages/kotlin/parser.d.ts.map +1 -0
  170. package/dist/src/languages/kotlin/parser.js +74 -0
  171. package/dist/src/languages/python/index.d.ts +15 -0
  172. package/dist/src/languages/python/index.d.ts.map +1 -0
  173. package/dist/src/languages/python/index.js +293 -0
  174. package/dist/src/languages/ruby/index.d.ts +15 -0
  175. package/dist/src/languages/ruby/index.d.ts.map +1 -0
  176. package/dist/src/languages/ruby/index.js +274 -0
  177. package/dist/src/languages/shared/treeSitterUtils.d.ts +43 -0
  178. package/dist/src/languages/shared/treeSitterUtils.d.ts.map +1 -0
  179. package/dist/src/languages/shared/treeSitterUtils.js +100 -0
  180. package/dist/src/languages/typescript/index.d.ts +14 -0
  181. package/dist/src/languages/typescript/index.d.ts.map +1 -0
  182. package/dist/src/languages/typescript/index.js +25 -0
  183. package/dist/src/lib/index.d.ts +228 -0
  184. package/dist/src/lib/index.d.ts.map +1 -0
  185. package/dist/src/lib/index.js +486 -0
  186. package/dist/src/mcp/client/index.d.ts +37 -0
  187. package/dist/src/mcp/client/index.d.ts.map +1 -0
  188. package/dist/src/mcp/client/index.js +235 -0
  189. package/dist/src/mcp/config.d.ts +50 -0
  190. package/dist/src/mcp/config.d.ts.map +1 -0
  191. package/dist/src/mcp/config.js +125 -0
  192. package/dist/src/mcp/events.d.ts +24 -0
  193. package/dist/src/mcp/events.d.ts.map +1 -0
  194. package/dist/src/mcp/events.js +48 -0
  195. package/dist/src/mcp/fallback/index.d.ts +50 -0
  196. package/dist/src/mcp/fallback/index.d.ts.map +1 -0
  197. package/dist/src/mcp/fallback/index.js +216 -0
  198. package/dist/src/mcp/index.d.ts +67 -0
  199. package/dist/src/mcp/index.d.ts.map +1 -0
  200. package/dist/src/mcp/index.js +212 -0
  201. package/dist/src/mcp/normalizer.d.ts +21 -0
  202. package/dist/src/mcp/normalizer.d.ts.map +1 -0
  203. package/dist/src/mcp/normalizer.js +99 -0
  204. package/dist/src/mcp/prompts/index.d.ts +86 -0
  205. package/dist/src/mcp/prompts/index.d.ts.map +1 -0
  206. package/dist/src/mcp/prompts/index.js +304 -0
  207. package/dist/src/mcp/templates/index.d.ts +35 -0
  208. package/dist/src/mcp/templates/index.d.ts.map +1 -0
  209. package/dist/src/mcp/templates/index.js +143 -0
  210. package/dist/src/mcp/testing/mock-server/index.d.ts +47 -0
  211. package/dist/src/mcp/testing/mock-server/index.d.ts.map +1 -0
  212. package/dist/src/mcp/testing/mock-server/index.js +157 -0
  213. package/dist/src/mcp/types.d.ts +127 -0
  214. package/dist/src/mcp/types.d.ts.map +1 -0
  215. package/dist/src/mcp/types.js +8 -0
  216. package/dist/src/observability.d.ts +138 -0
  217. package/dist/src/observability.d.ts.map +1 -0
  218. package/dist/src/observability.js +519 -0
  219. package/dist/src/parameterCoverage.d.ts +75 -0
  220. package/dist/src/parameterCoverage.d.ts.map +1 -0
  221. package/dist/src/parameterCoverage.js +629 -0
  222. package/dist/src/perfResilienceCoverage.d.ts +155 -0
  223. package/dist/src/perfResilienceCoverage.d.ts.map +1 -0
  224. package/dist/src/perfResilienceCoverage.js +670 -0
  225. package/dist/src/pluginLoader.d.ts +51 -0
  226. package/dist/src/pluginLoader.d.ts.map +1 -0
  227. package/dist/src/pluginLoader.js +72 -0
  228. package/dist/src/publishing.d.ts +63 -0
  229. package/dist/src/publishing.d.ts.map +1 -0
  230. package/dist/src/publishing.js +379 -0
  231. package/dist/src/qualityGate.d.ts +58 -0
  232. package/dist/src/qualityGate.d.ts.map +1 -0
  233. package/dist/src/qualityGate.js +118 -0
  234. package/dist/src/reporting.d.ts +41 -0
  235. package/dist/src/reporting.d.ts.map +1 -0
  236. package/dist/src/reporting.js +278 -0
  237. package/dist/src/screenshots.d.ts +71 -0
  238. package/dist/src/screenshots.d.ts.map +1 -0
  239. package/dist/src/screenshots.js +141 -0
  240. package/dist/src/security/gate/index.d.ts +11 -0
  241. package/dist/src/security/gate/index.d.ts.map +1 -0
  242. package/dist/src/security/gate/index.js +65 -0
  243. package/dist/src/security/index.d.ts +30 -0
  244. package/dist/src/security/index.d.ts.map +1 -0
  245. package/dist/src/security/index.js +342 -0
  246. package/dist/src/security/normalizers/semgrep.d.ts +10 -0
  247. package/dist/src/security/normalizers/semgrep.d.ts.map +1 -0
  248. package/dist/src/security/normalizers/semgrep.js +104 -0
  249. package/dist/src/security/normalizers/trivy.d.ts +10 -0
  250. package/dist/src/security/normalizers/trivy.d.ts.map +1 -0
  251. package/dist/src/security/normalizers/trivy.js +78 -0
  252. package/dist/src/security/normalizers/zap.d.ts +10 -0
  253. package/dist/src/security/normalizers/zap.d.ts.map +1 -0
  254. package/dist/src/security/normalizers/zap.js +104 -0
  255. package/dist/src/security/scanners/semgrep.d.ts +6 -0
  256. package/dist/src/security/scanners/semgrep.d.ts.map +1 -0
  257. package/dist/src/security/scanners/semgrep.js +125 -0
  258. package/dist/src/security/scanners/trivy.d.ts +6 -0
  259. package/dist/src/security/scanners/trivy.d.ts.map +1 -0
  260. package/dist/src/security/scanners/trivy.js +115 -0
  261. package/dist/src/security/scanners/zap.d.ts +6 -0
  262. package/dist/src/security/scanners/zap.d.ts.map +1 -0
  263. package/dist/src/security/scanners/zap.js +135 -0
  264. package/dist/src/security/types.d.ts +146 -0
  265. package/dist/src/security/types.d.ts.map +1 -0
  266. package/dist/src/security/types.js +6 -0
  267. package/dist/src/securityCoverage.d.ts +116 -0
  268. package/dist/src/securityCoverage.d.ts.map +1 -0
  269. package/dist/src/securityCoverage.js +725 -0
  270. package/dist/src/summary/buildSummary.d.ts +28 -0
  271. package/dist/src/summary/buildSummary.d.ts.map +1 -0
  272. package/dist/src/summary/buildSummary.js +257 -0
  273. package/dist/src/summary/evaluateMetrics.d.ts +31 -0
  274. package/dist/src/summary/evaluateMetrics.d.ts.map +1 -0
  275. package/dist/src/summary/evaluateMetrics.js +118 -0
  276. package/dist/src/summary/index.d.ts +10 -0
  277. package/dist/src/summary/index.d.ts.map +1 -0
  278. package/dist/src/summary/index.js +22 -0
  279. package/dist/src/summary/markdownRenderer.d.ts +139 -0
  280. package/dist/src/summary/markdownRenderer.d.ts.map +1 -0
  281. package/dist/src/summary/markdownRenderer.js +459 -0
  282. package/dist/src/summary/prSummary.d.ts +24 -0
  283. package/dist/src/summary/prSummary.d.ts.map +1 -0
  284. package/dist/src/summary/prSummary.js +233 -0
  285. package/dist/src/summary/summaryTypes.d.ts +35 -0
  286. package/dist/src/summary/summaryTypes.d.ts.map +1 -0
  287. package/dist/src/summary/summaryTypes.js +27 -0
  288. package/package.json +84 -0
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.matchesBranchPattern = matchesBranchPattern;
4
+ exports.resolveThresholdsForBranch = resolveThresholdsForBranch;
5
+ exports.effectiveThresholdForCategory = effectiveThresholdForCategory;
6
+ exports.evaluateQualityGate = evaluateQualityGate;
7
+ // ─── Branch matching ──────────────────────────────────────────────────────────
8
+ /**
9
+ * Determine whether a branch name matches a glob-style pattern.
10
+ * Supports `*` (single segment) and `**` (any segments).
11
+ */
12
+ function matchesBranchPattern(branchName, pattern) {
13
+ const regexStr = pattern
14
+ .replace(/[.+^${}()|[\]\\]/g, '\\$&')
15
+ .replace(/\*\*/g, '.+')
16
+ .replace(/\*/g, '[^/]+');
17
+ return new RegExp(`^${regexStr}$`).test(branchName);
18
+ }
19
+ /**
20
+ * Resolve the effective threshold map for the given branch, merging
21
+ * branch-aware overrides on top of the global threshold config.
22
+ */
23
+ function resolveThresholdsForBranch(config, branchName) {
24
+ const baseThresholds = {};
25
+ // Start from the global thresholds config
26
+ if (config.thresholds) {
27
+ for (const [key, value] of Object.entries(config.thresholds)) {
28
+ if (value !== undefined) {
29
+ baseThresholds[key] = value;
30
+ }
31
+ }
32
+ }
33
+ // Apply branch-aware overrides if a branch is specified
34
+ if (branchName && config.thresholdsByBranch) {
35
+ for (const [pattern, overrides] of Object.entries(config.thresholdsByBranch)) {
36
+ if (matchesBranchPattern(branchName, pattern)) {
37
+ for (const [key, value] of Object.entries(overrides)) {
38
+ if (value !== undefined) {
39
+ baseThresholds[key] = value;
40
+ }
41
+ }
42
+ break; // first matching pattern wins
43
+ }
44
+ }
45
+ }
46
+ return baseThresholds;
47
+ }
48
+ /**
49
+ * Compute the effective per-category threshold for a given category,
50
+ * using the 'global' key as the default when no category-specific value exists.
51
+ */
52
+ function effectiveThresholdForCategory(thresholds, category) {
53
+ if (thresholds[category] !== undefined)
54
+ return thresholds[category];
55
+ if (thresholds['global'] !== undefined)
56
+ return thresholds['global'];
57
+ return undefined;
58
+ }
59
+ // ─── Core evaluation ──────────────────────────────────────────────────────────
60
+ /**
61
+ * Evaluate all coverage results against configured thresholds.
62
+ *
63
+ * Default behaviour when no thresholds are configured: every category must
64
+ * reach 100% (spec requirement: "default threshold = 100%").
65
+ *
66
+ * @param results Coverage results from one or more analysis passes.
67
+ * @param config Quality-gate / threshold configuration.
68
+ * @param branchName Current git branch name (used for branch-aware thresholds).
69
+ */
70
+ function evaluateQualityGate(results, config, branchName) {
71
+ var _a, _b, _c;
72
+ const gateEnabled = ((_a = config.qualityGate) === null || _a === void 0 ? void 0 : _a.enabled) !== false; // default enabled
73
+ const mode = (_c = (_b = config.qualityGate) === null || _b === void 0 ? void 0 : _b.mode) !== null && _c !== void 0 ? _c : 'strict';
74
+ const resolvedThresholds = resolveThresholdsForBranch(config, branchName);
75
+ const actual = {};
76
+ for (const r of results) {
77
+ actual[r.type] = r.coveragePercent;
78
+ }
79
+ const failures = [];
80
+ if (gateEnabled) {
81
+ for (const result of results) {
82
+ const category = result.type;
83
+ let threshold;
84
+ if (Object.keys(resolvedThresholds).length > 0) {
85
+ const t = effectiveThresholdForCategory(resolvedThresholds, category);
86
+ if (t === undefined)
87
+ continue; // no threshold for this category
88
+ threshold = t;
89
+ }
90
+ else {
91
+ // No threshold config at all → default to 100%
92
+ threshold = 100;
93
+ }
94
+ if (result.coveragePercent < threshold) {
95
+ failures.push({
96
+ category,
97
+ expected: threshold,
98
+ actual: result.coveragePercent,
99
+ gap: Number((threshold - result.coveragePercent).toFixed(2)),
100
+ });
101
+ }
102
+ }
103
+ }
104
+ // In "warn" mode we still compute failures but mark as passed
105
+ const passed = mode === 'warn' ? true : failures.length === 0;
106
+ // Determine the threshold representation for the result
107
+ const thresholdForResult = Object.keys(resolvedThresholds).length === 1 && resolvedThresholds['global'] !== undefined
108
+ ? resolvedThresholds['global']
109
+ : Object.keys(resolvedThresholds).length > 0
110
+ ? resolvedThresholds
111
+ : 100;
112
+ return {
113
+ passed,
114
+ threshold: thresholdForResult,
115
+ actual,
116
+ failures,
117
+ };
118
+ }
@@ -0,0 +1,41 @@
1
+ import type { ObservabilityInfo } from './observability';
2
+ /**
3
+ * Standardized coverage result object produced by each coverage command.
4
+ * All analysis commands return one of these so the reporting module can
5
+ * handle them uniformly.
6
+ */
7
+ export interface CoverageResult {
8
+ /** Identifies which analysis produced this result (e.g. "endpoint", "parameter", "business", "integration") */
9
+ type: string;
10
+ /** Total number of items analysed (endpoints, parameters, rules, flows…) */
11
+ totalItems: number;
12
+ /** Number of items that are considered covered */
13
+ coveredItems: number;
14
+ /** Coverage percentage (0‑100, two decimal places) */
15
+ coveragePercent: number;
16
+ /** Arbitrary per-type detail data serialisable to JSON */
17
+ details: unknown;
18
+ }
19
+ export type ReportFormat = 'json' | 'html' | 'csv' | 'junit';
20
+ /**
21
+ * Parse a comma-separated format string (e.g. "json,html") into an array of
22
+ * validated `ReportFormat` values. Unknown tokens are silently ignored.
23
+ */
24
+ export declare function parseFormats(raw: string): ReportFormat[];
25
+ /**
26
+ * Write coverage reports in the requested formats to `reportsDir`.
27
+ * The directory is created if it does not exist.
28
+ *
29
+ * @param results Array of standardised coverage results
30
+ * @param formats Which output formats to generate
31
+ * @param reportsDir Absolute path to the output directory
32
+ * @param thresholds Optional per-type threshold percentages (used in HTML and JUnit outputs)
33
+ * @param observability Optional observability metadata embedded in JSON and HTML outputs
34
+ */
35
+ export declare function generateMultiFormatReports(results: CoverageResult[], formats: ReportFormat[], reportsDir: string, thresholds?: Record<string, number>, observability?: ObservabilityInfo): void;
36
+ /**
37
+ * Check whether any coverage result falls below its threshold.
38
+ * Returns an array of failure descriptions (empty means all pass).
39
+ */
40
+ export declare function checkThresholds(results: CoverageResult[], thresholds: Record<string, number>): string[];
41
+ //# sourceMappingURL=reporting.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reporting.d.ts","sourceRoot":"","sources":["../../src/reporting.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAIzD;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,+GAA+G;IAC/G,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,UAAU,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,YAAY,EAAE,MAAM,CAAC;IACrB,sDAAsD;IACtD,eAAe,EAAE,MAAM,CAAC;IACxB,0DAA0D;IAC1D,OAAO,EAAE,OAAO,CAAC;CAClB;AAID,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC;AAE7D;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,EAAE,CAMxD;AAwND;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,cAAc,EAAE,EACzB,OAAO,EAAE,YAAY,EAAE,EACvB,UAAU,EAAE,MAAM,EAClB,UAAU,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EACvC,aAAa,CAAC,EAAE,iBAAiB,GAChC,IAAI,CAqBN;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,cAAc,EAAE,EACzB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACjC,MAAM,EAAE,CAYV"}
@@ -0,0 +1,278 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.parseFormats = parseFormats;
37
+ exports.generateMultiFormatReports = generateMultiFormatReports;
38
+ exports.checkThresholds = checkThresholds;
39
+ const fs = __importStar(require("fs"));
40
+ const path = __importStar(require("path"));
41
+ /**
42
+ * Parse a comma-separated format string (e.g. "json,html") into an array of
43
+ * validated `ReportFormat` values. Unknown tokens are silently ignored.
44
+ */
45
+ function parseFormats(raw) {
46
+ const valid = ['json', 'html', 'csv', 'junit'];
47
+ return raw
48
+ .split(',')
49
+ .map((f) => f.trim().toLowerCase())
50
+ .filter((f) => valid.includes(f));
51
+ }
52
+ // ─── Report writers ───────────────────────────────────────────────────────────
53
+ /** Write `reports/coverage-summary.json`, merging with any existing file so that
54
+ * successive per-type runs accumulate a complete summary across all 8 metrics. */
55
+ function writeJson(results, reportsDir, observability) {
56
+ var _a;
57
+ const outPath = path.join(reportsDir, 'coverage-summary.json');
58
+ // Load existing summary/details so that successive single-type runs accumulate
59
+ // all coverage types into one file rather than overwriting each other.
60
+ let existingSummary = [];
61
+ let existingDetails = {};
62
+ try {
63
+ if (fs.existsSync(outPath)) {
64
+ const existing = JSON.parse(fs.readFileSync(outPath, 'utf-8'));
65
+ if (Array.isArray(existing.summary)) {
66
+ existingSummary = existing.summary;
67
+ }
68
+ if (existing.details && typeof existing.details === 'object') {
69
+ existingDetails = existing.details;
70
+ }
71
+ }
72
+ }
73
+ catch {
74
+ // Corrupt file — start fresh
75
+ }
76
+ // New results replace any existing entry for the same type; others are kept.
77
+ const newTypes = new Set(results.map((r) => r.type));
78
+ const mergedSummary = [
79
+ ...existingSummary.filter((s) => !newTypes.has(s.type)),
80
+ ...results.map((r) => ({
81
+ type: r.type,
82
+ totalItems: r.totalItems,
83
+ coveredItems: r.coveredItems,
84
+ coveragePercent: r.coveragePercent,
85
+ })),
86
+ ];
87
+ const mergedDetails = {
88
+ ...existingDetails,
89
+ ...results.reduce((acc, r) => {
90
+ acc[r.type] = r.details;
91
+ return acc;
92
+ }, {}),
93
+ };
94
+ const payload = {
95
+ generatedAt: new Date().toISOString(),
96
+ summary: mergedSummary,
97
+ details: mergedDetails,
98
+ };
99
+ if (observability) {
100
+ payload.observability = {
101
+ metricsUrl: observability.metricsUrl,
102
+ note: observability.metricsUrl
103
+ ? `Prometheus metrics available at ${observability.metricsUrl}`
104
+ : 'Prometheus metrics export not enabled (use --metrics-port to enable)',
105
+ metricNames: observability.metricNames,
106
+ tracing: {
107
+ enabled: observability.tracingEnabled,
108
+ otlpEndpoint: observability.otlpEndpoint,
109
+ note: observability.tracingEnabled
110
+ ? `Traces are exported to ${(_a = observability.otlpEndpoint) !== null && _a !== void 0 ? _a : 'in-memory (no OTLP endpoint configured)'}`
111
+ : 'Tracing not enabled (use --trace to enable)',
112
+ },
113
+ };
114
+ }
115
+ fs.writeFileSync(outPath, JSON.stringify(payload, null, 2), 'utf-8');
116
+ }
117
+ /** Write `reports/coverage-summary.html` */
118
+ function writeHtml(results, reportsDir, thresholds = {}, observability) {
119
+ const rows = results
120
+ .map((r) => {
121
+ var _a;
122
+ const threshold = (_a = thresholds[r.type]) !== null && _a !== void 0 ? _a : 0;
123
+ const belowThreshold = r.coveragePercent < threshold;
124
+ const rowClass = belowThreshold ? 'below' : r.coveragePercent >= 80 ? 'good' : 'warn';
125
+ const thresholdCell = threshold > 0
126
+ ? `<td class="${belowThreshold ? 'fail' : 'pass'}">${threshold}% ${belowThreshold ? '❌' : '✅'}</td>`
127
+ : '<td>—</td>';
128
+ return ` <tr class="${rowClass}">
129
+ <td>${r.type}</td>
130
+ <td>${r.coveredItems}/${r.totalItems}</td>
131
+ <td>${r.coveragePercent}%</td>
132
+ ${thresholdCell}
133
+ </tr>`;
134
+ })
135
+ .join('\n');
136
+ const observabilitySection = observability
137
+ ? `
138
+ <hr>
139
+ <h2>Observability</h2>
140
+ ${observability.metricsUrl
141
+ ? `<p>📊 Prometheus metrics available at <a href="${observability.metricsUrl}">${observability.metricsUrl}</a></p>
142
+ <p>Metric names (replace <code>&lt;type&gt;</code> with the coverage type, e.g. <code>endpoint</code>):</p>
143
+ <ul>
144
+ <li><code>api_coverage_total{coverage_type="&lt;type&gt;"}</code> — total items</li>
145
+ <li><code>api_coverage_covered{coverage_type="&lt;type&gt;"}</code> — covered items</li>
146
+ <li><code>api_coverage_ratio{coverage_type="&lt;type&gt;"}</code> — coverage ratio (0–1)</li>
147
+ <li><code>api_coverage_threshold_failure{coverage_type="&lt;type&gt;"}</code> — 1 if below threshold</li>
148
+ </ul>`
149
+ : '<p>Prometheus metrics export not enabled. Use <code>--metrics-port &lt;port&gt;</code> to enable.</p>'}
150
+ ${observability.tracingEnabled
151
+ ? `<p>🔭 OpenTelemetry tracing enabled${observability.otlpEndpoint ? ` → <code>${observability.otlpEndpoint}</code>` : ' (in-memory only)'}. View traces in Jaeger or Grafana Tempo.</p>`
152
+ : '<p>OpenTelemetry tracing not enabled. Use <code>--trace</code> to enable.</p>'}`
153
+ : '';
154
+ const html = `<!DOCTYPE html>
155
+ <html lang="en">
156
+ <head>
157
+ <meta charset="UTF-8">
158
+ <title>Coverage Summary Report</title>
159
+ <style>
160
+ body { font-family: sans-serif; padding: 2rem; background: #fafafa; }
161
+ h1 { margin-bottom: 0.25rem; }
162
+ .meta { color: #666; font-size: 0.9rem; margin-bottom: 1.5rem; }
163
+ table { border-collapse: collapse; width: 100%; max-width: 800px; }
164
+ th, td { border: 1px solid #ccc; padding: 0.5rem 1rem; text-align: left; }
165
+ th { background: #f0f0f0; }
166
+ tr.good { background: #e6ffe6; }
167
+ tr.warn { background: #fff9e6; }
168
+ tr.below { background: #ffe6e6; }
169
+ td.pass { color: #2a7a2a; font-weight: bold; }
170
+ td.fail { color: #aa2222; font-weight: bold; }
171
+ </style>
172
+ </head>
173
+ <body>
174
+ <h1>Coverage Summary Report</h1>
175
+ <p class="meta">Generated: ${new Date().toISOString()}</p>
176
+ <table>
177
+ <thead>
178
+ <tr>
179
+ <th>Coverage Type</th>
180
+ <th>Covered / Total</th>
181
+ <th>Coverage %</th>
182
+ <th>Threshold</th>
183
+ </tr>
184
+ </thead>
185
+ <tbody>
186
+ ${rows}
187
+ </tbody>
188
+ </table>${observabilitySection}
189
+ </body>
190
+ </html>`;
191
+ const outPath = path.join(reportsDir, 'coverage-summary.html');
192
+ fs.writeFileSync(outPath, html, 'utf-8');
193
+ }
194
+ /** Write `reports/coverage-summary.csv` */
195
+ function writeCsv(results, reportsDir) {
196
+ const lines = ['type,total,covered,percent'];
197
+ for (const r of results) {
198
+ lines.push(`${r.type},${r.totalItems},${r.coveredItems},${r.coveragePercent}`);
199
+ }
200
+ const outPath = path.join(reportsDir, 'coverage-summary.csv');
201
+ fs.writeFileSync(outPath, lines.join('\n') + '\n', 'utf-8');
202
+ }
203
+ /** Write `reports/coverage-summary-junit.xml` (JUnit-compatible XML) */
204
+ function writeJunit(results, reportsDir, thresholds = {}) {
205
+ const testCases = results
206
+ .map((r) => {
207
+ var _a;
208
+ const threshold = (_a = thresholds[r.type]) !== null && _a !== void 0 ? _a : 0;
209
+ const passed = r.coveragePercent >= threshold;
210
+ const name = `${r.type} coverage`;
211
+ if (passed) {
212
+ return ` <testcase name="${name}" classname="CoverageThreshold" time="0"/>`;
213
+ }
214
+ const diff = (threshold - r.coveragePercent).toFixed(2);
215
+ return ` <testcase name="${name}" classname="CoverageThreshold" time="0">
216
+ <failure message="${r.type} coverage ${r.coveragePercent}% is below threshold ${threshold}% (gap: ${diff}%)">
217
+ Coverage: ${r.coveragePercent}% / Threshold: ${threshold}% / Gap: ${diff}%
218
+ </failure>
219
+ </testcase>`;
220
+ })
221
+ .join('\n');
222
+ const failures = results.filter((r) => { var _a; return r.coveragePercent < ((_a = thresholds[r.type]) !== null && _a !== void 0 ? _a : 0); }).length;
223
+ const xml = `<?xml version="1.0" encoding="UTF-8"?>
224
+ <testsuites name="API Coverage" tests="${results.length}" failures="${failures}" time="0">
225
+ <testsuite name="Coverage Thresholds" tests="${results.length}" failures="${failures}" time="0">
226
+ ${testCases}
227
+ </testsuite>
228
+ </testsuites>`;
229
+ const outPath = path.join(reportsDir, 'coverage-summary-junit.xml');
230
+ fs.writeFileSync(outPath, xml, 'utf-8');
231
+ }
232
+ // ─── Public API ───────────────────────────────────────────────────────────────
233
+ /**
234
+ * Write coverage reports in the requested formats to `reportsDir`.
235
+ * The directory is created if it does not exist.
236
+ *
237
+ * @param results Array of standardised coverage results
238
+ * @param formats Which output formats to generate
239
+ * @param reportsDir Absolute path to the output directory
240
+ * @param thresholds Optional per-type threshold percentages (used in HTML and JUnit outputs)
241
+ * @param observability Optional observability metadata embedded in JSON and HTML outputs
242
+ */
243
+ function generateMultiFormatReports(results, formats, reportsDir, thresholds = {}, observability) {
244
+ if (!fs.existsSync(reportsDir)) {
245
+ fs.mkdirSync(reportsDir, { recursive: true });
246
+ }
247
+ for (const fmt of formats) {
248
+ switch (fmt) {
249
+ case 'json':
250
+ writeJson(results, reportsDir, observability);
251
+ break;
252
+ case 'html':
253
+ writeHtml(results, reportsDir, thresholds, observability);
254
+ break;
255
+ case 'csv':
256
+ writeCsv(results, reportsDir);
257
+ break;
258
+ case 'junit':
259
+ writeJunit(results, reportsDir, thresholds);
260
+ break;
261
+ }
262
+ }
263
+ }
264
+ /**
265
+ * Check whether any coverage result falls below its threshold.
266
+ * Returns an array of failure descriptions (empty means all pass).
267
+ */
268
+ function checkThresholds(results, thresholds) {
269
+ const failures = [];
270
+ for (const result of results) {
271
+ const threshold = thresholds[result.type];
272
+ if (threshold !== undefined && result.coveragePercent < threshold) {
273
+ const gap = (threshold - result.coveragePercent).toFixed(2);
274
+ failures.push(`${result.type} coverage ${result.coveragePercent}% is below threshold ${threshold}% (gap: ${gap}%)`);
275
+ }
276
+ }
277
+ return failures;
278
+ }
@@ -0,0 +1,71 @@
1
+ export interface ScreenshotResult {
2
+ page: string;
3
+ filePath: string | null;
4
+ captured: boolean;
5
+ error?: string;
6
+ }
7
+ export interface ScreenshotCaptureConfig {
8
+ /** Whether screenshot capture is enabled */
9
+ enabled?: boolean;
10
+ /** If true, missing screenshots cause a build failure */
11
+ strict?: boolean;
12
+ /** Dashboard URL to screenshot (defaults to http://localhost:4173) */
13
+ dashboardUrl?: string;
14
+ /** Output directory for screenshots */
15
+ outputDir?: string;
16
+ /** Build ID to include in path */
17
+ buildId?: string;
18
+ }
19
+ /** Dashboard pages to capture */
20
+ export declare const SCREENSHOT_PAGES: readonly [{
21
+ readonly name: "overview";
22
+ readonly path: "/";
23
+ }, {
24
+ readonly name: "endpoint-coverage";
25
+ readonly path: "/endpoint";
26
+ }, {
27
+ readonly name: "parameter-coverage";
28
+ readonly path: "/parameter";
29
+ }, {
30
+ readonly name: "business-coverage";
31
+ readonly path: "/business";
32
+ }, {
33
+ readonly name: "integration-flows";
34
+ readonly path: "/integration";
35
+ }, {
36
+ readonly name: "security-coverage";
37
+ readonly path: "/security";
38
+ }, {
39
+ readonly name: "error-coverage";
40
+ readonly path: "/error";
41
+ }, {
42
+ readonly name: "performance-resilience";
43
+ readonly path: "/performance";
44
+ }, {
45
+ readonly name: "compatibility";
46
+ readonly path: "/compatibility";
47
+ }, {
48
+ readonly name: "ai-analysis";
49
+ readonly path: "/ai";
50
+ }];
51
+ /**
52
+ * Attempt to capture screenshots of the dashboard using Playwright or Puppeteer.
53
+ *
54
+ * This function **never throws** when `strict` is false (the default).
55
+ * When headless screenshot tooling is unavailable, it returns results with
56
+ * `captured: false` for each page and includes an informative error message.
57
+ *
58
+ * When `strict: true`, a thrown error will propagate if any screenshot fails.
59
+ */
60
+ export declare function captureScreenshots(config: ScreenshotCaptureConfig): Promise<ScreenshotResult[]>;
61
+ /**
62
+ * Return the relative paths of successfully captured screenshots,
63
+ * suitable for embedding into HTML.
64
+ */
65
+ export declare function getScreenshotRelativePaths(results: ScreenshotResult[], siteDir: string, basePath?: string): string[];
66
+ /**
67
+ * Check whether screenshots are available.
68
+ * Returns `true` when at least one screenshot was captured.
69
+ */
70
+ export declare function hasScreenshots(results: ScreenshotResult[]): boolean;
71
+ //# sourceMappingURL=screenshots.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screenshots.d.ts","sourceRoot":"","sources":["../../src/screenshots.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,uBAAuB;IACtC,4CAA4C;IAC5C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yDAAyD;IACzD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kCAAkC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,iCAAiC;AACjC,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAWnB,CAAC;AAIX;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,uBAAuB,GAC9B,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAqC7B;AAgDD;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,gBAAgB,EAAE,EAC3B,OAAO,EAAE,MAAM,EACf,QAAQ,GAAE,MAAY,GACrB,MAAM,EAAE,CAOV;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAEnE"}
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.SCREENSHOT_PAGES = void 0;
37
+ exports.captureScreenshots = captureScreenshots;
38
+ exports.getScreenshotRelativePaths = getScreenshotRelativePaths;
39
+ exports.hasScreenshots = hasScreenshots;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ /** Dashboard pages to capture */
43
+ exports.SCREENSHOT_PAGES = [
44
+ { name: 'overview', path: '/' },
45
+ { name: 'endpoint-coverage', path: '/endpoint' },
46
+ { name: 'parameter-coverage', path: '/parameter' },
47
+ { name: 'business-coverage', path: '/business' },
48
+ { name: 'integration-flows', path: '/integration' },
49
+ { name: 'security-coverage', path: '/security' },
50
+ { name: 'error-coverage', path: '/error' },
51
+ { name: 'performance-resilience', path: '/performance' },
52
+ { name: 'compatibility', path: '/compatibility' },
53
+ { name: 'ai-analysis', path: '/ai' },
54
+ ];
55
+ // ─── Capture ──────────────────────────────────────────────────────────────────
56
+ /**
57
+ * Attempt to capture screenshots of the dashboard using Playwright or Puppeteer.
58
+ *
59
+ * This function **never throws** when `strict` is false (the default).
60
+ * When headless screenshot tooling is unavailable, it returns results with
61
+ * `captured: false` for each page and includes an informative error message.
62
+ *
63
+ * When `strict: true`, a thrown error will propagate if any screenshot fails.
64
+ */
65
+ async function captureScreenshots(config) {
66
+ var _a, _b, _c;
67
+ if (config.enabled === false) {
68
+ return exports.SCREENSHOT_PAGES.map((p) => ({
69
+ page: p.name,
70
+ filePath: null,
71
+ captured: false,
72
+ error: 'Screenshot capture is disabled',
73
+ }));
74
+ }
75
+ const baseUrl = (_a = config.dashboardUrl) !== null && _a !== void 0 ? _a : 'http://localhost:4173';
76
+ const siteDir = (_b = config.outputDir) !== null && _b !== void 0 ? _b : 'site';
77
+ const buildId = (_c = config.buildId) !== null && _c !== void 0 ? _c : 'latest';
78
+ const screenshotDir = path.join(siteDir, 'assets', 'screenshots', buildId);
79
+ fs.mkdirSync(screenshotDir, { recursive: true });
80
+ const results = [];
81
+ for (const page of exports.SCREENSHOT_PAGES) {
82
+ const filePath = path.join(screenshotDir, `${page.name}.png`);
83
+ try {
84
+ await captureOnePage(baseUrl + page.path, filePath);
85
+ results.push({ page: page.name, filePath, captured: true });
86
+ }
87
+ catch (err) {
88
+ const error = err instanceof Error ? err.message : String(err);
89
+ if (config.strict) {
90
+ throw new Error(`Failed to capture screenshot for page "${page.name}": ${error}`);
91
+ }
92
+ results.push({ page: page.name, filePath: null, captured: false, error });
93
+ }
94
+ }
95
+ return results;
96
+ }
97
+ /**
98
+ * Attempt to capture a single page screenshot.
99
+ * Tries Playwright first, then falls back to a clear "unavailable" error.
100
+ */
101
+ async function captureOnePage(url, outputPath) {
102
+ // Try Playwright (chromium) — it is an optional peer dependency
103
+ let playwright;
104
+ try {
105
+ // Dynamic require to avoid hard dependency
106
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
107
+ playwright = require('playwright');
108
+ }
109
+ catch {
110
+ throw new Error('Playwright is not installed. Install it with: npm install --save-dev playwright');
111
+ }
112
+ const browser = await playwright.chromium.launch({ headless: true });
113
+ try {
114
+ const page = await browser.newPage();
115
+ await page.goto(url, { waitUntil: 'networkidle', timeout: 15000 });
116
+ await page.screenshot({ path: outputPath, fullPage: true });
117
+ }
118
+ finally {
119
+ await browser.close();
120
+ }
121
+ }
122
+ // ─── Helper ───────────────────────────────────────────────────────────────────
123
+ /**
124
+ * Return the relative paths of successfully captured screenshots,
125
+ * suitable for embedding into HTML.
126
+ */
127
+ function getScreenshotRelativePaths(results, siteDir, basePath = '/') {
128
+ return results
129
+ .filter((r) => r.captured && r.filePath !== null)
130
+ .map((r) => {
131
+ const rel = path.relative(siteDir, r.filePath).replace(/\\/g, '/');
132
+ return `${basePath}${rel}`;
133
+ });
134
+ }
135
+ /**
136
+ * Check whether screenshots are available.
137
+ * Returns `true` when at least one screenshot was captured.
138
+ */
139
+ function hasScreenshots(results) {
140
+ return results.some((r) => r.captured);
141
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Security gate evaluator.
3
+ * Evaluates normalized findings against configured thresholds and returns a pass/fail result.
4
+ */
5
+ import { SecurityFinding, SecurityGateConfig, SecurityGateResult } from '../types';
6
+ /**
7
+ * Evaluate the security gate against normalized findings.
8
+ * Returns a SecurityGateResult with pass/fail status and detailed reasons.
9
+ */
10
+ export declare function evaluateSecurityGate(findings: SecurityFinding[], config: SecurityGateConfig): SecurityGateResult;
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/security/gate/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,UAAU,CAAC;AAWlB;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,eAAe,EAAE,EAC3B,MAAM,EAAE,kBAAkB,GACzB,kBAAkB,CA+EpB"}