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.
- package/README.md +703 -0
- package/config.yaml.example +227 -0
- package/dist/action/src/index.d.ts +2 -0
- package/dist/action/src/index.d.ts.map +1 -0
- package/dist/action/src/index.js +349 -0
- package/dist/action/src/prComment.d.ts +34 -0
- package/dist/action/src/prComment.d.ts.map +1 -0
- package/dist/action/src/prComment.js +146 -0
- package/dist/src/ast/astAnalysisOrchestrator.d.ts +36 -0
- package/dist/src/ast/astAnalysisOrchestrator.d.ts.map +1 -0
- package/dist/src/ast/astAnalysisOrchestrator.js +123 -0
- package/dist/src/ast/astTypes.d.ts +105 -0
- package/dist/src/ast/astTypes.d.ts.map +1 -0
- package/dist/src/ast/astTypes.js +9 -0
- package/dist/src/ast/languageAnalyzer.d.ts +46 -0
- package/dist/src/ast/languageAnalyzer.d.ts.map +1 -0
- package/dist/src/ast/languageAnalyzer.js +9 -0
- package/dist/src/ast/languageCapabilities.d.ts +24 -0
- package/dist/src/ast/languageCapabilities.d.ts.map +1 -0
- package/dist/src/ast/languageCapabilities.js +92 -0
- package/dist/src/ast/parseFile.d.ts +16 -0
- package/dist/src/ast/parseFile.d.ts.map +1 -0
- package/dist/src/ast/parseFile.js +65 -0
- package/dist/src/ast/parserRegistry.d.ts +39 -0
- package/dist/src/ast/parserRegistry.d.ts.map +1 -0
- package/dist/src/ast/parserRegistry.js +66 -0
- package/dist/src/buildSummary.d.ts +26 -0
- package/dist/src/buildSummary.d.ts.map +1 -0
- package/dist/src/buildSummary.js +193 -0
- package/dist/src/businessCoverage.d.ts +68 -0
- package/dist/src/businessCoverage.d.ts.map +1 -0
- package/dist/src/businessCoverage.js +290 -0
- package/dist/src/compatibilityCoverage.d.ts +83 -0
- package/dist/src/compatibilityCoverage.d.ts.map +1 -0
- package/dist/src/compatibilityCoverage.js +501 -0
- package/dist/src/config/defaultConfig.d.ts +9 -0
- package/dist/src/config/defaultConfig.d.ts.map +1 -0
- package/dist/src/config/defaultConfig.js +97 -0
- package/dist/src/config/index.d.ts +12 -0
- package/dist/src/config/index.d.ts.map +1 -0
- package/dist/src/config/index.js +37 -0
- package/dist/src/config/loadConfig.d.ts +29 -0
- package/dist/src/config/loadConfig.d.ts.map +1 -0
- package/dist/src/config/loadConfig.js +135 -0
- package/dist/src/config/mergeConfig.d.ts +15 -0
- package/dist/src/config/mergeConfig.d.ts.map +1 -0
- package/dist/src/config/mergeConfig.js +57 -0
- package/dist/src/config/schema.d.ts +15 -0
- package/dist/src/config/schema.d.ts.map +1 -0
- package/dist/src/config/schema.js +30 -0
- package/dist/src/config/types.d.ts +175 -0
- package/dist/src/config/types.d.ts.map +1 -0
- package/dist/src/config/types.js +9 -0
- package/dist/src/config/validateConfig.d.ts +22 -0
- package/dist/src/config/validateConfig.d.ts.map +1 -0
- package/dist/src/config/validateConfig.js +171 -0
- package/dist/src/config.d.ts +168 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +204 -0
- package/dist/src/coverage/deep-analysis/callGraph.d.ts +67 -0
- package/dist/src/coverage/deep-analysis/callGraph.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/callGraph.js +275 -0
- package/dist/src/coverage/deep-analysis/deepEndpointResolver.d.ts +23 -0
- package/dist/src/coverage/deep-analysis/deepEndpointResolver.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/deepEndpointResolver.js +394 -0
- package/dist/src/coverage/deep-analysis/index.d.ts +17 -0
- package/dist/src/coverage/deep-analysis/index.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/index.js +63 -0
- package/dist/src/coverage/deep-analysis/resolveAssertions.d.ts +60 -0
- package/dist/src/coverage/deep-analysis/resolveAssertions.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/resolveAssertions.js +121 -0
- package/dist/src/coverage/deep-analysis/resolveConstants.d.ts +36 -0
- package/dist/src/coverage/deep-analysis/resolveConstants.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/resolveConstants.js +92 -0
- package/dist/src/coverage/deep-analysis/resolveEnums.d.ts +55 -0
- package/dist/src/coverage/deep-analysis/resolveEnums.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/resolveEnums.js +152 -0
- package/dist/src/coverage/deep-analysis/resolveMethodChains.d.ts +70 -0
- package/dist/src/coverage/deep-analysis/resolveMethodChains.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/resolveMethodChains.js +152 -0
- package/dist/src/coverage/deep-analysis/resolvePaths.d.ts +80 -0
- package/dist/src/coverage/deep-analysis/resolvePaths.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/resolvePaths.js +216 -0
- package/dist/src/coverage/deep-analysis/resolveRequestWrappers.d.ts +71 -0
- package/dist/src/coverage/deep-analysis/resolveRequestWrappers.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/resolveRequestWrappers.js +226 -0
- package/dist/src/coverage/deep-analysis/symbolTable.d.ts +58 -0
- package/dist/src/coverage/deep-analysis/symbolTable.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/symbolTable.js +230 -0
- package/dist/src/coverage/deep-analysis/types.d.ts +122 -0
- package/dist/src/coverage/deep-analysis/types.d.ts.map +1 -0
- package/dist/src/coverage/deep-analysis/types.js +21 -0
- package/dist/src/discovery/fileClassifier.d.ts +50 -0
- package/dist/src/discovery/fileClassifier.d.ts.map +1 -0
- package/dist/src/discovery/fileClassifier.js +238 -0
- package/dist/src/discovery/projectDiscovery.d.ts +66 -0
- package/dist/src/discovery/projectDiscovery.d.ts.map +1 -0
- package/dist/src/discovery/projectDiscovery.js +287 -0
- package/dist/src/endpointCoverage.d.ts +70 -0
- package/dist/src/endpointCoverage.d.ts.map +1 -0
- package/dist/src/endpointCoverage.js +381 -0
- package/dist/src/errorCoverage.d.ts +93 -0
- package/dist/src/errorCoverage.d.ts.map +1 -0
- package/dist/src/errorCoverage.js +698 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +1441 -0
- package/dist/src/inference/businessRuleInference.d.ts +63 -0
- package/dist/src/inference/businessRuleInference.d.ts.map +1 -0
- package/dist/src/inference/businessRuleInference.js +268 -0
- package/dist/src/inference/integrationFlowInference.d.ts +56 -0
- package/dist/src/inference/integrationFlowInference.d.ts.map +1 -0
- package/dist/src/inference/integrationFlowInference.js +266 -0
- package/dist/src/integrationCoverage.d.ts +72 -0
- package/dist/src/integrationCoverage.d.ts.map +1 -0
- package/dist/src/integrationCoverage.js +317 -0
- package/dist/src/intelligence/index.d.ts +20 -0
- package/dist/src/intelligence/index.d.ts.map +1 -0
- package/dist/src/intelligence/index.js +105 -0
- package/dist/src/intelligence/linkageEngine.d.ts +20 -0
- package/dist/src/intelligence/linkageEngine.d.ts.map +1 -0
- package/dist/src/intelligence/linkageEngine.js +522 -0
- package/dist/src/intelligence/markdownReporter.d.ts +12 -0
- package/dist/src/intelligence/markdownReporter.d.ts.map +1 -0
- package/dist/src/intelligence/markdownReporter.js +265 -0
- package/dist/src/intelligence/riskScoring.d.ts +53 -0
- package/dist/src/intelligence/riskScoring.d.ts.map +1 -0
- package/dist/src/intelligence/riskScoring.js +181 -0
- package/dist/src/intelligence/types.d.ts +121 -0
- package/dist/src/intelligence/types.d.ts.map +1 -0
- package/dist/src/intelligence/types.js +8 -0
- package/dist/src/languageDetection.d.ts +100 -0
- package/dist/src/languageDetection.d.ts.map +1 -0
- package/dist/src/languageDetection.js +349 -0
- package/dist/src/languages/java/index.d.ts +16 -0
- package/dist/src/languages/java/index.d.ts.map +1 -0
- package/dist/src/languages/java/index.js +103 -0
- package/dist/src/languages/java/parser.d.ts +7 -0
- package/dist/src/languages/java/parser.d.ts.map +1 -0
- package/dist/src/languages/java/parser.js +50 -0
- package/dist/src/languages/java/semanticBuilder.d.ts +21 -0
- package/dist/src/languages/java/semanticBuilder.d.ts.map +1 -0
- package/dist/src/languages/java/semanticBuilder.js +358 -0
- package/dist/src/languages/javascript/annotationExtractor.d.ts +20 -0
- package/dist/src/languages/javascript/annotationExtractor.d.ts.map +1 -0
- package/dist/src/languages/javascript/annotationExtractor.js +94 -0
- package/dist/src/languages/javascript/assertionResolver.d.ts +18 -0
- package/dist/src/languages/javascript/assertionResolver.d.ts.map +1 -0
- package/dist/src/languages/javascript/assertionResolver.js +150 -0
- package/dist/src/languages/javascript/callResolver.d.ts +23 -0
- package/dist/src/languages/javascript/callResolver.d.ts.map +1 -0
- package/dist/src/languages/javascript/callResolver.js +236 -0
- package/dist/src/languages/javascript/httpInteractionExtractor.d.ts +23 -0
- package/dist/src/languages/javascript/httpInteractionExtractor.d.ts.map +1 -0
- package/dist/src/languages/javascript/httpInteractionExtractor.js +205 -0
- package/dist/src/languages/javascript/index.d.ts +20 -0
- package/dist/src/languages/javascript/index.d.ts.map +1 -0
- package/dist/src/languages/javascript/index.js +136 -0
- package/dist/src/languages/javascript/parser.d.ts +14 -0
- package/dist/src/languages/javascript/parser.d.ts.map +1 -0
- package/dist/src/languages/javascript/parser.js +38 -0
- package/dist/src/languages/javascript/symbolResolver.d.ts +31 -0
- package/dist/src/languages/javascript/symbolResolver.d.ts.map +1 -0
- package/dist/src/languages/javascript/symbolResolver.js +183 -0
- package/dist/src/languages/kotlin/index.d.ts +16 -0
- package/dist/src/languages/kotlin/index.d.ts.map +1 -0
- package/dist/src/languages/kotlin/index.js +151 -0
- package/dist/src/languages/kotlin/parser.d.ts +11 -0
- package/dist/src/languages/kotlin/parser.d.ts.map +1 -0
- package/dist/src/languages/kotlin/parser.js +74 -0
- package/dist/src/languages/python/index.d.ts +15 -0
- package/dist/src/languages/python/index.d.ts.map +1 -0
- package/dist/src/languages/python/index.js +293 -0
- package/dist/src/languages/ruby/index.d.ts +15 -0
- package/dist/src/languages/ruby/index.d.ts.map +1 -0
- package/dist/src/languages/ruby/index.js +274 -0
- package/dist/src/languages/shared/treeSitterUtils.d.ts +43 -0
- package/dist/src/languages/shared/treeSitterUtils.d.ts.map +1 -0
- package/dist/src/languages/shared/treeSitterUtils.js +100 -0
- package/dist/src/languages/typescript/index.d.ts +14 -0
- package/dist/src/languages/typescript/index.d.ts.map +1 -0
- package/dist/src/languages/typescript/index.js +25 -0
- package/dist/src/lib/index.d.ts +228 -0
- package/dist/src/lib/index.d.ts.map +1 -0
- package/dist/src/lib/index.js +486 -0
- package/dist/src/mcp/client/index.d.ts +37 -0
- package/dist/src/mcp/client/index.d.ts.map +1 -0
- package/dist/src/mcp/client/index.js +235 -0
- package/dist/src/mcp/config.d.ts +50 -0
- package/dist/src/mcp/config.d.ts.map +1 -0
- package/dist/src/mcp/config.js +125 -0
- package/dist/src/mcp/events.d.ts +24 -0
- package/dist/src/mcp/events.d.ts.map +1 -0
- package/dist/src/mcp/events.js +48 -0
- package/dist/src/mcp/fallback/index.d.ts +50 -0
- package/dist/src/mcp/fallback/index.d.ts.map +1 -0
- package/dist/src/mcp/fallback/index.js +216 -0
- package/dist/src/mcp/index.d.ts +67 -0
- package/dist/src/mcp/index.d.ts.map +1 -0
- package/dist/src/mcp/index.js +212 -0
- package/dist/src/mcp/normalizer.d.ts +21 -0
- package/dist/src/mcp/normalizer.d.ts.map +1 -0
- package/dist/src/mcp/normalizer.js +99 -0
- package/dist/src/mcp/prompts/index.d.ts +86 -0
- package/dist/src/mcp/prompts/index.d.ts.map +1 -0
- package/dist/src/mcp/prompts/index.js +304 -0
- package/dist/src/mcp/templates/index.d.ts +35 -0
- package/dist/src/mcp/templates/index.d.ts.map +1 -0
- package/dist/src/mcp/templates/index.js +143 -0
- package/dist/src/mcp/testing/mock-server/index.d.ts +47 -0
- package/dist/src/mcp/testing/mock-server/index.d.ts.map +1 -0
- package/dist/src/mcp/testing/mock-server/index.js +157 -0
- package/dist/src/mcp/types.d.ts +127 -0
- package/dist/src/mcp/types.d.ts.map +1 -0
- package/dist/src/mcp/types.js +8 -0
- package/dist/src/observability.d.ts +138 -0
- package/dist/src/observability.d.ts.map +1 -0
- package/dist/src/observability.js +519 -0
- package/dist/src/parameterCoverage.d.ts +75 -0
- package/dist/src/parameterCoverage.d.ts.map +1 -0
- package/dist/src/parameterCoverage.js +629 -0
- package/dist/src/perfResilienceCoverage.d.ts +155 -0
- package/dist/src/perfResilienceCoverage.d.ts.map +1 -0
- package/dist/src/perfResilienceCoverage.js +670 -0
- package/dist/src/pluginLoader.d.ts +51 -0
- package/dist/src/pluginLoader.d.ts.map +1 -0
- package/dist/src/pluginLoader.js +72 -0
- package/dist/src/publishing.d.ts +63 -0
- package/dist/src/publishing.d.ts.map +1 -0
- package/dist/src/publishing.js +379 -0
- package/dist/src/qualityGate.d.ts +58 -0
- package/dist/src/qualityGate.d.ts.map +1 -0
- package/dist/src/qualityGate.js +118 -0
- package/dist/src/reporting.d.ts +41 -0
- package/dist/src/reporting.d.ts.map +1 -0
- package/dist/src/reporting.js +278 -0
- package/dist/src/screenshots.d.ts +71 -0
- package/dist/src/screenshots.d.ts.map +1 -0
- package/dist/src/screenshots.js +141 -0
- package/dist/src/security/gate/index.d.ts +11 -0
- package/dist/src/security/gate/index.d.ts.map +1 -0
- package/dist/src/security/gate/index.js +65 -0
- package/dist/src/security/index.d.ts +30 -0
- package/dist/src/security/index.d.ts.map +1 -0
- package/dist/src/security/index.js +342 -0
- package/dist/src/security/normalizers/semgrep.d.ts +10 -0
- package/dist/src/security/normalizers/semgrep.d.ts.map +1 -0
- package/dist/src/security/normalizers/semgrep.js +104 -0
- package/dist/src/security/normalizers/trivy.d.ts +10 -0
- package/dist/src/security/normalizers/trivy.d.ts.map +1 -0
- package/dist/src/security/normalizers/trivy.js +78 -0
- package/dist/src/security/normalizers/zap.d.ts +10 -0
- package/dist/src/security/normalizers/zap.d.ts.map +1 -0
- package/dist/src/security/normalizers/zap.js +104 -0
- package/dist/src/security/scanners/semgrep.d.ts +6 -0
- package/dist/src/security/scanners/semgrep.d.ts.map +1 -0
- package/dist/src/security/scanners/semgrep.js +125 -0
- package/dist/src/security/scanners/trivy.d.ts +6 -0
- package/dist/src/security/scanners/trivy.d.ts.map +1 -0
- package/dist/src/security/scanners/trivy.js +115 -0
- package/dist/src/security/scanners/zap.d.ts +6 -0
- package/dist/src/security/scanners/zap.d.ts.map +1 -0
- package/dist/src/security/scanners/zap.js +135 -0
- package/dist/src/security/types.d.ts +146 -0
- package/dist/src/security/types.d.ts.map +1 -0
- package/dist/src/security/types.js +6 -0
- package/dist/src/securityCoverage.d.ts +116 -0
- package/dist/src/securityCoverage.d.ts.map +1 -0
- package/dist/src/securityCoverage.js +725 -0
- package/dist/src/summary/buildSummary.d.ts +28 -0
- package/dist/src/summary/buildSummary.d.ts.map +1 -0
- package/dist/src/summary/buildSummary.js +257 -0
- package/dist/src/summary/evaluateMetrics.d.ts +31 -0
- package/dist/src/summary/evaluateMetrics.d.ts.map +1 -0
- package/dist/src/summary/evaluateMetrics.js +118 -0
- package/dist/src/summary/index.d.ts +10 -0
- package/dist/src/summary/index.d.ts.map +1 -0
- package/dist/src/summary/index.js +22 -0
- package/dist/src/summary/markdownRenderer.d.ts +139 -0
- package/dist/src/summary/markdownRenderer.d.ts.map +1 -0
- package/dist/src/summary/markdownRenderer.js +459 -0
- package/dist/src/summary/prSummary.d.ts +24 -0
- package/dist/src/summary/prSummary.d.ts.map +1 -0
- package/dist/src/summary/prSummary.js +233 -0
- package/dist/src/summary/summaryTypes.d.ts +35 -0
- package/dist/src/summary/summaryTypes.d.ts.map +1 -0
- package/dist/src/summary/summaryTypes.js +27 -0
- package/package.json +84 -0
|
@@ -0,0 +1,501 @@
|
|
|
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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.loadSpec = loadSpec;
|
|
40
|
+
exports.compareSpecs = compareSpecs;
|
|
41
|
+
exports.parseContractFiles = parseContractFiles;
|
|
42
|
+
exports.verifyContracts = verifyContracts;
|
|
43
|
+
exports.computeCompatibilityPercent = computeCompatibilityPercent;
|
|
44
|
+
exports.computeContractCoveragePercent = computeContractCoveragePercent;
|
|
45
|
+
exports.buildCompatibilityReport = buildCompatibilityReport;
|
|
46
|
+
exports.generateCompatibilityReports = generateCompatibilityReports;
|
|
47
|
+
const swagger_parser_1 = __importDefault(require("@apidevtools/swagger-parser"));
|
|
48
|
+
const fs = __importStar(require("fs"));
|
|
49
|
+
const path = __importStar(require("path"));
|
|
50
|
+
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
51
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
52
|
+
const HTTP_METHODS = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'];
|
|
53
|
+
function extractEndpoints(api) {
|
|
54
|
+
var _a;
|
|
55
|
+
const results = [];
|
|
56
|
+
const paths = (_a = api.paths) !== null && _a !== void 0 ? _a : {};
|
|
57
|
+
for (const [p, pathItem] of Object.entries(paths)) {
|
|
58
|
+
if (!pathItem)
|
|
59
|
+
continue;
|
|
60
|
+
for (const method of HTTP_METHODS) {
|
|
61
|
+
const op = pathItem[method];
|
|
62
|
+
if (op && typeof op === 'object') {
|
|
63
|
+
results.push({ method, path: p, operation: op });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return results;
|
|
68
|
+
}
|
|
69
|
+
function getResponseCodes(op) {
|
|
70
|
+
var _a;
|
|
71
|
+
return Object.keys((_a = op.responses) !== null && _a !== void 0 ? _a : {});
|
|
72
|
+
}
|
|
73
|
+
function getParameters(op) {
|
|
74
|
+
var _a;
|
|
75
|
+
return ((_a = op.parameters) !== null && _a !== void 0 ? _a : []);
|
|
76
|
+
}
|
|
77
|
+
function paramKey(p) {
|
|
78
|
+
return `${p.in}:${p.name}`;
|
|
79
|
+
}
|
|
80
|
+
// ─── Spec comparison ──────────────────────────────────────────────────────────
|
|
81
|
+
/**
|
|
82
|
+
* Load and dereference an OpenAPI/Swagger spec from a file path.
|
|
83
|
+
*/
|
|
84
|
+
async function loadSpec(specPath) {
|
|
85
|
+
const api = await swagger_parser_1.default.dereference(specPath);
|
|
86
|
+
return api;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Compare two API specs and return a list of detected changes.
|
|
90
|
+
*/
|
|
91
|
+
function compareSpecs(oldApi, newApi) {
|
|
92
|
+
var _a, _b;
|
|
93
|
+
const changes = [];
|
|
94
|
+
const oldEndpoints = extractEndpoints(oldApi);
|
|
95
|
+
const newEndpoints = extractEndpoints(newApi);
|
|
96
|
+
const oldMap = new Map();
|
|
97
|
+
for (const ep of oldEndpoints) {
|
|
98
|
+
oldMap.set(`${ep.method}:${ep.path}`, ep);
|
|
99
|
+
}
|
|
100
|
+
const newMap = new Map();
|
|
101
|
+
for (const ep of newEndpoints) {
|
|
102
|
+
newMap.set(`${ep.method}:${ep.path}`, ep);
|
|
103
|
+
}
|
|
104
|
+
// Removed endpoints (breaking)
|
|
105
|
+
for (const [key, oldEp] of oldMap) {
|
|
106
|
+
if (!newMap.has(key)) {
|
|
107
|
+
changes.push({
|
|
108
|
+
method: oldEp.method,
|
|
109
|
+
path: oldEp.path,
|
|
110
|
+
changeType: 'removed',
|
|
111
|
+
breaking: true,
|
|
112
|
+
description: `Endpoint removed: ${oldEp.method.toUpperCase()} ${oldEp.path}`,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// Added endpoints (non-breaking)
|
|
117
|
+
for (const [key, newEp] of newMap) {
|
|
118
|
+
if (!oldMap.has(key)) {
|
|
119
|
+
changes.push({
|
|
120
|
+
method: newEp.method,
|
|
121
|
+
path: newEp.path,
|
|
122
|
+
changeType: 'added',
|
|
123
|
+
breaking: false,
|
|
124
|
+
description: `Endpoint added: ${newEp.method.toUpperCase()} ${newEp.path}`,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// Changed endpoints
|
|
129
|
+
for (const [key, oldEp] of oldMap) {
|
|
130
|
+
const newEp = newMap.get(key);
|
|
131
|
+
if (!newEp)
|
|
132
|
+
continue;
|
|
133
|
+
// Check response codes
|
|
134
|
+
const oldCodes = new Set(getResponseCodes(oldEp.operation));
|
|
135
|
+
const newCodes = new Set(getResponseCodes(newEp.operation));
|
|
136
|
+
const removedCodes = [...oldCodes].filter((c) => !newCodes.has(c));
|
|
137
|
+
if (removedCodes.length > 0) {
|
|
138
|
+
changes.push({
|
|
139
|
+
method: oldEp.method,
|
|
140
|
+
path: oldEp.path,
|
|
141
|
+
changeType: 'changed-response-codes',
|
|
142
|
+
breaking: true,
|
|
143
|
+
description: `Response codes removed from ${oldEp.method.toUpperCase()} ${oldEp.path}: ${removedCodes.join(', ')}`,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
// Check parameters
|
|
147
|
+
const oldParams = getParameters(oldEp.operation);
|
|
148
|
+
const newParams = getParameters(newEp.operation);
|
|
149
|
+
const newParamMap = new Map(newParams.map((p) => [paramKey(p), p]));
|
|
150
|
+
for (const oldParam of oldParams) {
|
|
151
|
+
const newParam = newParamMap.get(paramKey(oldParam));
|
|
152
|
+
if (!newParam) {
|
|
153
|
+
// Parameter removed — breaking if it was required
|
|
154
|
+
changes.push({
|
|
155
|
+
method: oldEp.method,
|
|
156
|
+
path: oldEp.path,
|
|
157
|
+
changeType: 'changed-parameter',
|
|
158
|
+
breaking: oldParam.required === true,
|
|
159
|
+
description: `Parameter removed from ${oldEp.method.toUpperCase()} ${oldEp.path}: ${oldParam.in} '${oldParam.name}'${oldParam.required ? ' (required)' : ''}`,
|
|
160
|
+
});
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
// Parameter type/format changed — breaking
|
|
164
|
+
const oldSchema = ((_a = oldParam.schema) !== null && _a !== void 0 ? _a : {});
|
|
165
|
+
const newSchema = ((_b = newParam.schema) !== null && _b !== void 0 ? _b : {});
|
|
166
|
+
if (oldSchema['type'] !== newSchema['type'] || oldSchema['format'] !== newSchema['format']) {
|
|
167
|
+
changes.push({
|
|
168
|
+
method: oldEp.method,
|
|
169
|
+
path: oldEp.path,
|
|
170
|
+
changeType: 'changed-parameter',
|
|
171
|
+
breaking: true,
|
|
172
|
+
description: `Parameter type/format changed for ${oldEp.method.toUpperCase()} ${oldEp.path}: '${oldParam.name}' (${oldSchema['type']}/${oldSchema['format']} → ${newSchema['type']}/${newSchema['format']})`,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
// Required flag changed from optional to required — breaking
|
|
176
|
+
if (!oldParam.required && newParam.required) {
|
|
177
|
+
changes.push({
|
|
178
|
+
method: oldEp.method,
|
|
179
|
+
path: oldEp.path,
|
|
180
|
+
changeType: 'changed-parameter',
|
|
181
|
+
breaking: true,
|
|
182
|
+
description: `Parameter '${oldParam.name}' became required in ${oldEp.method.toUpperCase()} ${oldEp.path}`,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
// New required parameters added — breaking
|
|
187
|
+
const oldParamMap = new Map(oldParams.map((p) => [paramKey(p), p]));
|
|
188
|
+
for (const newParam of newParams) {
|
|
189
|
+
if (!oldParamMap.has(paramKey(newParam)) && newParam.required) {
|
|
190
|
+
changes.push({
|
|
191
|
+
method: newEp.method,
|
|
192
|
+
path: newEp.path,
|
|
193
|
+
changeType: 'changed-parameter',
|
|
194
|
+
breaking: true,
|
|
195
|
+
description: `Required parameter added to ${newEp.method.toUpperCase()} ${newEp.path}: ${newParam.in} '${newParam.name}'`,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return changes;
|
|
201
|
+
}
|
|
202
|
+
// ─── Contract parsing ─────────────────────────────────────────────────────────
|
|
203
|
+
/**
|
|
204
|
+
* Parse Pact-format JSON contract files matching the given glob pattern or directory.
|
|
205
|
+
*/
|
|
206
|
+
async function parseContractFiles(contractsGlob) {
|
|
207
|
+
let pattern = contractsGlob;
|
|
208
|
+
// If the provided path is a directory, search recursively for JSON files inside it
|
|
209
|
+
if (fs.existsSync(contractsGlob) && fs.statSync(contractsGlob).isDirectory()) {
|
|
210
|
+
pattern = path.join(contractsGlob, '**/*.json').replace(/\\/g, '/');
|
|
211
|
+
}
|
|
212
|
+
const files = await (0, fast_glob_1.default)(pattern, { absolute: true });
|
|
213
|
+
const contracts = [];
|
|
214
|
+
for (const filePath of files) {
|
|
215
|
+
try {
|
|
216
|
+
const raw = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
217
|
+
const contract = parsePactContract(raw, filePath);
|
|
218
|
+
if (contract)
|
|
219
|
+
contracts.push(contract);
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
// Skip invalid files
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return contracts;
|
|
226
|
+
}
|
|
227
|
+
function parsePactContract(raw, filePath) {
|
|
228
|
+
var _a, _b;
|
|
229
|
+
if (typeof raw !== 'object' || raw === null)
|
|
230
|
+
return null;
|
|
231
|
+
const obj = raw;
|
|
232
|
+
if (!obj['interactions'] || !Array.isArray(obj['interactions']))
|
|
233
|
+
return null;
|
|
234
|
+
const consumer = typeof obj['consumer'] === 'object' && obj['consumer'] !== null
|
|
235
|
+
? (_a = obj['consumer']['name']) !== null && _a !== void 0 ? _a : 'unknown'
|
|
236
|
+
: 'unknown';
|
|
237
|
+
const provider = typeof obj['provider'] === 'object' && obj['provider'] !== null
|
|
238
|
+
? (_b = obj['provider']['name']) !== null && _b !== void 0 ? _b : 'unknown'
|
|
239
|
+
: 'unknown';
|
|
240
|
+
const interactions = [];
|
|
241
|
+
for (const item of obj['interactions']) {
|
|
242
|
+
if (typeof item !== 'object' || item === null)
|
|
243
|
+
continue;
|
|
244
|
+
const interaction = item;
|
|
245
|
+
const request = interaction['request'];
|
|
246
|
+
const response = interaction['response'];
|
|
247
|
+
if (!request)
|
|
248
|
+
continue;
|
|
249
|
+
const method = typeof request['method'] === 'string' ? request['method'].toLowerCase() : '';
|
|
250
|
+
const interactionPath = typeof request['path'] === 'string' ? request['path'] : '';
|
|
251
|
+
if (!method || !interactionPath)
|
|
252
|
+
continue;
|
|
253
|
+
const expectedStatus = typeof (response === null || response === void 0 ? void 0 : response['status']) === 'number' ? response['status'] : 200;
|
|
254
|
+
interactions.push({
|
|
255
|
+
description: typeof interaction['description'] === 'string' ? interaction['description'] : '',
|
|
256
|
+
method,
|
|
257
|
+
path: interactionPath,
|
|
258
|
+
requestBody: request['body'],
|
|
259
|
+
expectedStatus,
|
|
260
|
+
expectedBody: response === null || response === void 0 ? void 0 : response['body'],
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
return { consumer, provider, interactions, filePath };
|
|
264
|
+
}
|
|
265
|
+
// ─── Contract verification ────────────────────────────────────────────────────
|
|
266
|
+
/**
|
|
267
|
+
* Normalise a path template by replacing Pact-style `:param` segments with
|
|
268
|
+
* OpenAPI-style `{param}` segments so the two formats can be compared.
|
|
269
|
+
*/
|
|
270
|
+
function normalisePath(p) {
|
|
271
|
+
return p.replace(/:([^/]+)/g, '{$1}');
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Check whether a path from a contract matches an OpenAPI spec path,
|
|
275
|
+
* accounting for path parameter placeholders in different styles.
|
|
276
|
+
*/
|
|
277
|
+
function pathMatchesSpec(contractPath, specPath) {
|
|
278
|
+
const normalised = normalisePath(contractPath);
|
|
279
|
+
if (normalised === specPath)
|
|
280
|
+
return true;
|
|
281
|
+
// Build a regex from the spec path template and test the contract path
|
|
282
|
+
const regexStr = '^' + specPath.replace(/\{[^}]+\}/g, '[^/]+') + '$';
|
|
283
|
+
return new RegExp(regexStr).test(contractPath);
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Verify consumer contracts against a new API spec.
|
|
287
|
+
*/
|
|
288
|
+
function verifyContracts(contracts, newApi) {
|
|
289
|
+
const endpoints = extractEndpoints(newApi);
|
|
290
|
+
return contracts.map((contract) => {
|
|
291
|
+
const interactionResults = contract.interactions.map((interaction) => {
|
|
292
|
+
// Find matching endpoint in spec
|
|
293
|
+
const match = endpoints.find((ep) => ep.method === interaction.method && pathMatchesSpec(interaction.path, ep.path));
|
|
294
|
+
if (!match) {
|
|
295
|
+
return {
|
|
296
|
+
interaction,
|
|
297
|
+
passed: false,
|
|
298
|
+
reason: `Endpoint not found in new spec: ${interaction.method.toUpperCase()} ${interaction.path}`,
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
// Check expected response status code is present in spec
|
|
302
|
+
const responseCodes = getResponseCodes(match.operation);
|
|
303
|
+
const statusStr = String(interaction.expectedStatus);
|
|
304
|
+
if (!responseCodes.includes(statusStr) &&
|
|
305
|
+
!responseCodes.includes('default')) {
|
|
306
|
+
return {
|
|
307
|
+
interaction,
|
|
308
|
+
passed: false,
|
|
309
|
+
reason: `Expected response status ${interaction.expectedStatus} not defined for ${interaction.method.toUpperCase()} ${interaction.path} in new spec`,
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
return { interaction, passed: true };
|
|
313
|
+
});
|
|
314
|
+
const passed = interactionResults.every((r) => r.passed);
|
|
315
|
+
return { contract, interactionResults, passed };
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
// ─── Metrics ──────────────────────────────────────────────────────────────────
|
|
319
|
+
/**
|
|
320
|
+
* Compute compatibility percentage based on detected breaking changes.
|
|
321
|
+
*/
|
|
322
|
+
function computeCompatibilityPercent(totalOldEndpoints, breakingChanges) {
|
|
323
|
+
if (totalOldEndpoints === 0)
|
|
324
|
+
return 100;
|
|
325
|
+
// Count uniquely affected old endpoints (by method+path)
|
|
326
|
+
const affectedKeys = new Set(breakingChanges
|
|
327
|
+
.filter((c) => c.changeType !== 'added')
|
|
328
|
+
.map((c) => `${c.method}:${c.path}`));
|
|
329
|
+
const unaffected = Math.max(0, totalOldEndpoints - affectedKeys.size);
|
|
330
|
+
return parseFloat(((unaffected / totalOldEndpoints) * 100).toFixed(2));
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Compute what fraction of new spec endpoints are covered by at least one
|
|
334
|
+
* contract interaction.
|
|
335
|
+
*/
|
|
336
|
+
function computeContractCoveragePercent(contracts, newApi) {
|
|
337
|
+
const endpoints = extractEndpoints(newApi);
|
|
338
|
+
const coveredKeys = new Set();
|
|
339
|
+
for (const contract of contracts) {
|
|
340
|
+
for (const interaction of contract.interactions) {
|
|
341
|
+
const match = endpoints.find((ep) => ep.method === interaction.method && pathMatchesSpec(interaction.path, ep.path));
|
|
342
|
+
if (match)
|
|
343
|
+
coveredKeys.add(`${match.method}:${match.path}`);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
const total = endpoints.length;
|
|
347
|
+
const covered = coveredKeys.size;
|
|
348
|
+
const coveragePercent = total === 0 ? 100 : parseFloat(((covered / total) * 100).toFixed(2));
|
|
349
|
+
return { coveredEndpoints: covered, totalEndpoints: total, coveragePercent };
|
|
350
|
+
}
|
|
351
|
+
// ─── Report builder ───────────────────────────────────────────────────────────
|
|
352
|
+
function buildCompatibilityReport(oldApi, newApi, changes, verificationResults, oldSpecPath, newSpecPath) {
|
|
353
|
+
const oldEndpoints = extractEndpoints(oldApi);
|
|
354
|
+
const breakingChanges = changes.filter((c) => c.breaking);
|
|
355
|
+
const nonBreakingChanges = changes.filter((c) => !c.breaking);
|
|
356
|
+
const compatibilityPercent = computeCompatibilityPercent(oldEndpoints.length, breakingChanges);
|
|
357
|
+
const coverageMetrics = computeContractCoveragePercent(verificationResults.map((r) => r.contract), newApi);
|
|
358
|
+
return {
|
|
359
|
+
generatedAt: new Date().toISOString(),
|
|
360
|
+
oldSpecPath,
|
|
361
|
+
newSpecPath,
|
|
362
|
+
totalOldEndpoints: oldEndpoints.length,
|
|
363
|
+
breakingChanges,
|
|
364
|
+
nonBreakingChanges,
|
|
365
|
+
compatibilityPercent,
|
|
366
|
+
contractVerificationResults: verificationResults,
|
|
367
|
+
totalNewEndpoints: coverageMetrics.totalEndpoints,
|
|
368
|
+
contractCoveredEndpoints: coverageMetrics.coveredEndpoints,
|
|
369
|
+
contractCoveragePercent: coverageMetrics.coveragePercent,
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
// ─── Report writers ───────────────────────────────────────────────────────────
|
|
373
|
+
function writeCompatibilityJson(report, reportsDir) {
|
|
374
|
+
const outPath = path.join(reportsDir, 'compatibility-contracts.json');
|
|
375
|
+
fs.writeFileSync(outPath, JSON.stringify(report, null, 2), 'utf-8');
|
|
376
|
+
}
|
|
377
|
+
function writeCompatibilityHtml(report, reportsDir) {
|
|
378
|
+
const breakingRows = report.breakingChanges
|
|
379
|
+
.map((c) => ` <tr class="breaking">
|
|
380
|
+
<td>${c.method.toUpperCase()}</td>
|
|
381
|
+
<td>${c.path}</td>
|
|
382
|
+
<td>${c.changeType}</td>
|
|
383
|
+
<td>${c.description}</td>
|
|
384
|
+
</tr>`)
|
|
385
|
+
.join('\n');
|
|
386
|
+
const nonBreakingRows = report.nonBreakingChanges
|
|
387
|
+
.map((c) => ` <tr class="non-breaking">
|
|
388
|
+
<td>${c.method.toUpperCase()}</td>
|
|
389
|
+
<td>${c.path}</td>
|
|
390
|
+
<td>${c.changeType}</td>
|
|
391
|
+
<td>${c.description}</td>
|
|
392
|
+
</tr>`)
|
|
393
|
+
.join('\n');
|
|
394
|
+
const contractRows = report.contractVerificationResults
|
|
395
|
+
.flatMap((r) => r.interactionResults.map((ir) => {
|
|
396
|
+
var _a;
|
|
397
|
+
return ` <tr class="${ir.passed ? 'pass' : 'fail'}">
|
|
398
|
+
<td>${r.contract.consumer}</td>
|
|
399
|
+
<td>${r.contract.provider}</td>
|
|
400
|
+
<td>${ir.interaction.description}</td>
|
|
401
|
+
<td>${ir.interaction.method.toUpperCase()} ${ir.interaction.path}</td>
|
|
402
|
+
<td>${ir.passed ? '✅ Pass' : '❌ Fail'}</td>
|
|
403
|
+
<td>${(_a = ir.reason) !== null && _a !== void 0 ? _a : ''}</td>
|
|
404
|
+
</tr>`;
|
|
405
|
+
}))
|
|
406
|
+
.join('\n');
|
|
407
|
+
const compatColor = report.compatibilityPercent >= 80
|
|
408
|
+
? '#e6ffe6'
|
|
409
|
+
: report.compatibilityPercent >= 50
|
|
410
|
+
? '#fff9e6'
|
|
411
|
+
: '#ffe6e6';
|
|
412
|
+
const coverageColor = report.contractCoveragePercent >= 80
|
|
413
|
+
? '#e6ffe6'
|
|
414
|
+
: report.contractCoveragePercent >= 50
|
|
415
|
+
? '#fff9e6'
|
|
416
|
+
: '#ffe6e6';
|
|
417
|
+
const html = `<!DOCTYPE html>
|
|
418
|
+
<html lang="en">
|
|
419
|
+
<head>
|
|
420
|
+
<meta charset="UTF-8">
|
|
421
|
+
<title>Compatibility & Contract Report</title>
|
|
422
|
+
<style>
|
|
423
|
+
body { font-family: sans-serif; padding: 2rem; background: #fafafa; }
|
|
424
|
+
h1 { margin-bottom: 0.25rem; }
|
|
425
|
+
h2 { margin-top: 2rem; }
|
|
426
|
+
.meta { color: #666; font-size: 0.9rem; margin-bottom: 1.5rem; }
|
|
427
|
+
table { border-collapse: collapse; width: 100%; max-width: 1000px; margin-bottom: 1.5rem; }
|
|
428
|
+
th, td { border: 1px solid #ccc; padding: 0.5rem 1rem; text-align: left; }
|
|
429
|
+
th { background: #f0f0f0; }
|
|
430
|
+
tr.breaking { background: #ffe6e6; }
|
|
431
|
+
tr.non-breaking { background: #e6ffe6; }
|
|
432
|
+
tr.pass { background: #e6ffe6; }
|
|
433
|
+
tr.fail { background: #ffe6e6; }
|
|
434
|
+
.summary-box { display: inline-block; padding: 1rem 2rem; border-radius: 6px; margin-right: 1rem; font-size: 1.2rem; font-weight: bold; }
|
|
435
|
+
</style>
|
|
436
|
+
</head>
|
|
437
|
+
<body>
|
|
438
|
+
<h1>Compatibility & Contract Report</h1>
|
|
439
|
+
<p class="meta">Generated: ${report.generatedAt} | Old: ${report.oldSpecPath} | New: ${report.newSpecPath}</p>
|
|
440
|
+
|
|
441
|
+
<div>
|
|
442
|
+
<div class="summary-box" style="background:${compatColor}">
|
|
443
|
+
Compatibility: ${report.compatibilityPercent}%
|
|
444
|
+
(${report.breakingChanges.length} breaking change${report.breakingChanges.length !== 1 ? 's' : ''})
|
|
445
|
+
</div>
|
|
446
|
+
<div class="summary-box" style="background:${coverageColor}">
|
|
447
|
+
Contract Coverage: ${report.contractCoveragePercent}%
|
|
448
|
+
(${report.contractCoveredEndpoints}/${report.totalNewEndpoints} endpoints)
|
|
449
|
+
</div>
|
|
450
|
+
</div>
|
|
451
|
+
|
|
452
|
+
<h2>Breaking Changes</h2>
|
|
453
|
+
${report.breakingChanges.length === 0
|
|
454
|
+
? '<p>No breaking changes detected. ✅</p>'
|
|
455
|
+
: `<table>
|
|
456
|
+
<thead>
|
|
457
|
+
<tr><th>Method</th><th>Path</th><th>Change Type</th><th>Description</th></tr>
|
|
458
|
+
</thead>
|
|
459
|
+
<tbody>
|
|
460
|
+
${breakingRows}
|
|
461
|
+
</tbody>
|
|
462
|
+
</table>`}
|
|
463
|
+
|
|
464
|
+
<h2>Non-Breaking Changes</h2>
|
|
465
|
+
${report.nonBreakingChanges.length === 0
|
|
466
|
+
? '<p>No non-breaking changes detected.</p>'
|
|
467
|
+
: `<table>
|
|
468
|
+
<thead>
|
|
469
|
+
<tr><th>Method</th><th>Path</th><th>Change Type</th><th>Description</th></tr>
|
|
470
|
+
</thead>
|
|
471
|
+
<tbody>
|
|
472
|
+
${nonBreakingRows}
|
|
473
|
+
</tbody>
|
|
474
|
+
</table>`}
|
|
475
|
+
|
|
476
|
+
<h2>Contract Verification</h2>
|
|
477
|
+
${report.contractVerificationResults.length === 0
|
|
478
|
+
? '<p>No consumer contracts provided.</p>'
|
|
479
|
+
: `<table>
|
|
480
|
+
<thead>
|
|
481
|
+
<tr><th>Consumer</th><th>Provider</th><th>Interaction</th><th>Endpoint</th><th>Result</th><th>Reason</th></tr>
|
|
482
|
+
</thead>
|
|
483
|
+
<tbody>
|
|
484
|
+
${contractRows}
|
|
485
|
+
</tbody>
|
|
486
|
+
</table>`}
|
|
487
|
+
</body>
|
|
488
|
+
</html>`;
|
|
489
|
+
const outPath = path.join(reportsDir, 'compatibility-contracts.html');
|
|
490
|
+
fs.writeFileSync(outPath, html, 'utf-8');
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Generate JSON and HTML compatibility reports.
|
|
494
|
+
*/
|
|
495
|
+
function generateCompatibilityReports(report, reportsDir) {
|
|
496
|
+
if (!fs.existsSync(reportsDir)) {
|
|
497
|
+
fs.mkdirSync(reportsDir, { recursive: true });
|
|
498
|
+
}
|
|
499
|
+
writeCompatibilityJson(report, reportsDir);
|
|
500
|
+
writeCompatibilityHtml(report, reportsDir);
|
|
501
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Central config — built-in default values.
|
|
3
|
+
*
|
|
4
|
+
* Every config field has a default here. No scanning module may use an
|
|
5
|
+
* inline fallback; all defaults live in this single file.
|
|
6
|
+
*/
|
|
7
|
+
import type { AnalyzerConfig } from './types';
|
|
8
|
+
export declare const DEFAULT_CONFIG: AnalyzerConfig;
|
|
9
|
+
//# sourceMappingURL=defaultConfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaultConfig.d.ts","sourceRoot":"","sources":["../../../src/config/defaultConfig.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAO9C,eAAO,MAAM,cAAc,EAAE,cA+F5B,CAAC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Central config — built-in default values.
|
|
4
|
+
*
|
|
5
|
+
* Every config field has a default here. No scanning module may use an
|
|
6
|
+
* inline fallback; all defaults live in this single file.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.DEFAULT_CONFIG = void 0;
|
|
10
|
+
const schema_1 = require("./schema");
|
|
11
|
+
exports.DEFAULT_CONFIG = {
|
|
12
|
+
version: 1,
|
|
13
|
+
project: {
|
|
14
|
+
name: undefined,
|
|
15
|
+
},
|
|
16
|
+
analysis: {
|
|
17
|
+
defaultMode: 'full',
|
|
18
|
+
failOnConfigMissing: false,
|
|
19
|
+
warnOnConfigMissing: true,
|
|
20
|
+
agnosticDiscovery: true,
|
|
21
|
+
inferBusinessRules: true,
|
|
22
|
+
inferIntegrationFlows: true,
|
|
23
|
+
ast: {
|
|
24
|
+
enabled: true,
|
|
25
|
+
fallbackHeuristics: true,
|
|
26
|
+
maxCallDepth: 4,
|
|
27
|
+
assertionAware: true,
|
|
28
|
+
languages: {
|
|
29
|
+
java: { enabled: true },
|
|
30
|
+
kotlin: { enabled: true },
|
|
31
|
+
python: { enabled: true },
|
|
32
|
+
ruby: { enabled: true },
|
|
33
|
+
javascript: { enabled: true },
|
|
34
|
+
typescript: { enabled: true },
|
|
35
|
+
cucumber: { enabled: true },
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
scans: {
|
|
40
|
+
coverage: {
|
|
41
|
+
enabled: true,
|
|
42
|
+
types: [...schema_1.VALID_COVERAGE_TYPES],
|
|
43
|
+
deepAnalysis: {
|
|
44
|
+
enabled: true,
|
|
45
|
+
maxCallDepth: 4,
|
|
46
|
+
resolveConstants: true,
|
|
47
|
+
resolveEnums: true,
|
|
48
|
+
resolveStringTemplates: true,
|
|
49
|
+
resolveWrappers: true,
|
|
50
|
+
resolveRequestBuilders: true,
|
|
51
|
+
resolveClientMappings: true,
|
|
52
|
+
assertionAware: true,
|
|
53
|
+
clientMappings: [],
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
security: {
|
|
57
|
+
enabled: true,
|
|
58
|
+
scanners: [...schema_1.VALID_SECURITY_SCANNERS],
|
|
59
|
+
},
|
|
60
|
+
intelligence: {
|
|
61
|
+
enabled: true,
|
|
62
|
+
types: [...schema_1.VALID_INTELLIGENCE_TYPES],
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
mcp: {
|
|
66
|
+
// MCP is disabled by default when config is missing to avoid unexpected
|
|
67
|
+
// network calls. Users must explicitly opt in via config.yaml.
|
|
68
|
+
enabled: false,
|
|
69
|
+
defaultTransport: 'stdio',
|
|
70
|
+
timeoutMs: 30000,
|
|
71
|
+
servers: {},
|
|
72
|
+
},
|
|
73
|
+
thresholds: {
|
|
74
|
+
global: 80,
|
|
75
|
+
},
|
|
76
|
+
qualityGate: {
|
|
77
|
+
enabled: true,
|
|
78
|
+
failBuildOnThresholdMiss: false,
|
|
79
|
+
mode: 'warn',
|
|
80
|
+
},
|
|
81
|
+
reports: {
|
|
82
|
+
outputDir: 'reports',
|
|
83
|
+
formats: ['json'],
|
|
84
|
+
},
|
|
85
|
+
publishing: {
|
|
86
|
+
enabled: false,
|
|
87
|
+
githubPages: {
|
|
88
|
+
enabled: false,
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
dashboard: {
|
|
92
|
+
aiSummary: {
|
|
93
|
+
enabled: true,
|
|
94
|
+
collapsedByDefault: true,
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Central config module — public barrel export.
|
|
3
|
+
*
|
|
4
|
+
* Import from here; do not import from individual sub-files.
|
|
5
|
+
*/
|
|
6
|
+
export * from './types';
|
|
7
|
+
export * from './schema';
|
|
8
|
+
export { DEFAULT_CONFIG } from './defaultConfig';
|
|
9
|
+
export { validateConfig, } from './validateConfig';
|
|
10
|
+
export { mergeConfig, } from './mergeConfig';
|
|
11
|
+
export { loadConfig, DEFAULT_CONFIG_FILENAME, DEFAULT_CONFIG_PATH, LEGACY_CONFIG_FILENAME, MISSING_CONFIG_WARNING, LEGACY_CONFIG_WARNING, } from './loadConfig';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/config/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EACL,cAAc,GACf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,WAAW,GACZ,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,UAAU,EACV,uBAAuB,EACvB,mBAAmB,EACnB,sBAAsB,EACtB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Central config module — public barrel export.
|
|
4
|
+
*
|
|
5
|
+
* Import from here; do not import from individual sub-files.
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
19
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
20
|
+
};
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.LEGACY_CONFIG_WARNING = exports.MISSING_CONFIG_WARNING = exports.LEGACY_CONFIG_FILENAME = exports.DEFAULT_CONFIG_PATH = exports.DEFAULT_CONFIG_FILENAME = exports.loadConfig = exports.mergeConfig = exports.validateConfig = exports.DEFAULT_CONFIG = void 0;
|
|
23
|
+
__exportStar(require("./types"), exports);
|
|
24
|
+
__exportStar(require("./schema"), exports);
|
|
25
|
+
var defaultConfig_1 = require("./defaultConfig");
|
|
26
|
+
Object.defineProperty(exports, "DEFAULT_CONFIG", { enumerable: true, get: function () { return defaultConfig_1.DEFAULT_CONFIG; } });
|
|
27
|
+
var validateConfig_1 = require("./validateConfig");
|
|
28
|
+
Object.defineProperty(exports, "validateConfig", { enumerable: true, get: function () { return validateConfig_1.validateConfig; } });
|
|
29
|
+
var mergeConfig_1 = require("./mergeConfig");
|
|
30
|
+
Object.defineProperty(exports, "mergeConfig", { enumerable: true, get: function () { return mergeConfig_1.mergeConfig; } });
|
|
31
|
+
var loadConfig_1 = require("./loadConfig");
|
|
32
|
+
Object.defineProperty(exports, "loadConfig", { enumerable: true, get: function () { return loadConfig_1.loadConfig; } });
|
|
33
|
+
Object.defineProperty(exports, "DEFAULT_CONFIG_FILENAME", { enumerable: true, get: function () { return loadConfig_1.DEFAULT_CONFIG_FILENAME; } });
|
|
34
|
+
Object.defineProperty(exports, "DEFAULT_CONFIG_PATH", { enumerable: true, get: function () { return loadConfig_1.DEFAULT_CONFIG_PATH; } });
|
|
35
|
+
Object.defineProperty(exports, "LEGACY_CONFIG_FILENAME", { enumerable: true, get: function () { return loadConfig_1.LEGACY_CONFIG_FILENAME; } });
|
|
36
|
+
Object.defineProperty(exports, "MISSING_CONFIG_WARNING", { enumerable: true, get: function () { return loadConfig_1.MISSING_CONFIG_WARNING; } });
|
|
37
|
+
Object.defineProperty(exports, "LEGACY_CONFIG_WARNING", { enumerable: true, get: function () { return loadConfig_1.LEGACY_CONFIG_WARNING; } });
|