@machina.ai/openapi-contract-tester 2.1.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/.env.example +91 -0
- package/README.md +472 -0
- package/dist/ai-engine/assertion-generator.d.ts +48 -0
- package/dist/ai-engine/assertion-generator.d.ts.map +1 -0
- package/dist/ai-engine/assertion-generator.js +166 -0
- package/dist/ai-engine/assertion-generator.js.map +1 -0
- package/dist/ai-engine/context-data-generator.d.ts +38 -0
- package/dist/ai-engine/context-data-generator.d.ts.map +1 -0
- package/dist/ai-engine/context-data-generator.js +146 -0
- package/dist/ai-engine/context-data-generator.js.map +1 -0
- package/dist/ai-engine/dataflow-detector.d.ts +53 -0
- package/dist/ai-engine/dataflow-detector.d.ts.map +1 -0
- package/dist/ai-engine/dataflow-detector.js +217 -0
- package/dist/ai-engine/dataflow-detector.js.map +1 -0
- package/dist/ai-engine/dependency-detector.d.ts +52 -0
- package/dist/ai-engine/dependency-detector.d.ts.map +1 -0
- package/dist/ai-engine/dependency-detector.js +241 -0
- package/dist/ai-engine/dependency-detector.js.map +1 -0
- package/dist/ai-engine/edge-case-suggester.d.ts +63 -0
- package/dist/ai-engine/edge-case-suggester.d.ts.map +1 -0
- package/dist/ai-engine/edge-case-suggester.js +177 -0
- package/dist/ai-engine/edge-case-suggester.js.map +1 -0
- package/dist/ai-engine/index.d.ts +13 -0
- package/dist/ai-engine/index.d.ts.map +1 -0
- package/dist/ai-engine/index.js +13 -0
- package/dist/ai-engine/index.js.map +1 -0
- package/dist/analyzers/ai-failure-analyzer.d.ts +41 -0
- package/dist/analyzers/ai-failure-analyzer.d.ts.map +1 -0
- package/dist/analyzers/ai-failure-analyzer.js +220 -0
- package/dist/analyzers/ai-failure-analyzer.js.map +1 -0
- package/dist/analyzers/comparison-utils.d.ts +31 -0
- package/dist/analyzers/comparison-utils.d.ts.map +1 -0
- package/dist/analyzers/comparison-utils.js +85 -0
- package/dist/analyzers/comparison-utils.js.map +1 -0
- package/dist/analyzers/context-analyzer.d.ts +49 -0
- package/dist/analyzers/context-analyzer.d.ts.map +1 -0
- package/dist/analyzers/context-analyzer.js +292 -0
- package/dist/analyzers/context-analyzer.js.map +1 -0
- package/dist/analyzers/dependency-analyzer.d.ts +44 -0
- package/dist/analyzers/dependency-analyzer.d.ts.map +1 -0
- package/dist/analyzers/dependency-analyzer.js +313 -0
- package/dist/analyzers/dependency-analyzer.js.map +1 -0
- package/dist/analyzers/failure-analyzer.d.ts +122 -0
- package/dist/analyzers/failure-analyzer.d.ts.map +1 -0
- package/dist/analyzers/failure-analyzer.js +140 -0
- package/dist/analyzers/failure-analyzer.js.map +1 -0
- package/dist/analyzers/failure-detectors/index.d.ts +33 -0
- package/dist/analyzers/failure-detectors/index.d.ts.map +1 -0
- package/dist/analyzers/failure-detectors/index.js +164 -0
- package/dist/analyzers/failure-detectors/index.js.map +1 -0
- package/dist/analyzers/failure-discrepancy-correlator.d.ts +111 -0
- package/dist/analyzers/failure-discrepancy-correlator.d.ts.map +1 -0
- package/dist/analyzers/failure-discrepancy-correlator.js +202 -0
- package/dist/analyzers/failure-discrepancy-correlator.js.map +1 -0
- package/dist/analyzers/index.d.ts +10 -0
- package/dist/analyzers/index.d.ts.map +1 -0
- package/dist/analyzers/index.js +10 -0
- package/dist/analyzers/index.js.map +1 -0
- package/dist/analyzers/semantic-matcher.d.ts +123 -0
- package/dist/analyzers/semantic-matcher.d.ts.map +1 -0
- package/dist/analyzers/semantic-matcher.js +297 -0
- package/dist/analyzers/semantic-matcher.js.map +1 -0
- package/dist/analyzers/source-comparator.d.ts +177 -0
- package/dist/analyzers/source-comparator.d.ts.map +1 -0
- package/dist/analyzers/source-comparator.js +225 -0
- package/dist/analyzers/source-comparator.js.map +1 -0
- package/dist/business-rules/business-rules-analyzer.d.ts +44 -0
- package/dist/business-rules/business-rules-analyzer.d.ts.map +1 -0
- package/dist/business-rules/business-rules-analyzer.js +363 -0
- package/dist/business-rules/business-rules-analyzer.js.map +1 -0
- package/dist/business-rules/business-rules-generator.d.ts +78 -0
- package/dist/business-rules/business-rules-generator.d.ts.map +1 -0
- package/dist/business-rules/business-rules-generator.js +357 -0
- package/dist/business-rules/business-rules-generator.js.map +1 -0
- package/dist/business-rules/extractors/rule-extractors.d.ts +50 -0
- package/dist/business-rules/extractors/rule-extractors.d.ts.map +1 -0
- package/dist/business-rules/extractors/rule-extractors.js +189 -0
- package/dist/business-rules/extractors/rule-extractors.js.map +1 -0
- package/dist/business-rules/value-generators.d.ts +70 -0
- package/dist/business-rules/value-generators.d.ts.map +1 -0
- package/dist/business-rules/value-generators.js +142 -0
- package/dist/business-rules/value-generators.js.map +1 -0
- package/dist/executor/auth-providers/auth-header-builder.d.ts +16 -0
- package/dist/executor/auth-providers/auth-header-builder.d.ts.map +1 -0
- package/dist/executor/auth-providers/auth-header-builder.js +47 -0
- package/dist/executor/auth-providers/auth-header-builder.js.map +1 -0
- package/dist/executor/auth-providers/oauth2-provider.d.ts +19 -0
- package/dist/executor/auth-providers/oauth2-provider.d.ts.map +1 -0
- package/dist/executor/auth-providers/oauth2-provider.js +114 -0
- package/dist/executor/auth-providers/oauth2-provider.js.map +1 -0
- package/dist/executor/http-client.d.ts +133 -0
- package/dist/executor/http-client.d.ts.map +1 -0
- package/dist/executor/http-client.js +172 -0
- package/dist/executor/http-client.js.map +1 -0
- package/dist/executor/http-request-builder.d.ts +69 -0
- package/dist/executor/http-request-builder.d.ts.map +1 -0
- package/dist/executor/http-request-builder.js +140 -0
- package/dist/executor/http-request-builder.js.map +1 -0
- package/dist/executor/http-response-parser.d.ts +28 -0
- package/dist/executor/http-response-parser.d.ts.map +1 -0
- package/dist/executor/http-response-parser.js +74 -0
- package/dist/executor/http-response-parser.js.map +1 -0
- package/dist/executor/response-handler.d.ts +66 -0
- package/dist/executor/response-handler.d.ts.map +1 -0
- package/dist/executor/response-handler.js +135 -0
- package/dist/executor/response-handler.js.map +1 -0
- package/dist/executor/result-processor.d.ts +27 -0
- package/dist/executor/result-processor.d.ts.map +1 -0
- package/dist/executor/result-processor.js +140 -0
- package/dist/executor/result-processor.js.map +1 -0
- package/dist/executor/result-utils.d.ts +21 -0
- package/dist/executor/result-utils.d.ts.map +1 -0
- package/dist/executor/result-utils.js +29 -0
- package/dist/executor/result-utils.js.map +1 -0
- package/dist/executor/test-executor.d.ts +49 -0
- package/dist/executor/test-executor.d.ts.map +1 -0
- package/dist/executor/test-executor.js +226 -0
- package/dist/executor/test-executor.js.map +1 -0
- package/dist/executor/test-runner.d.ts +85 -0
- package/dist/executor/test-runner.d.ts.map +1 -0
- package/dist/executor/test-runner.js +177 -0
- package/dist/executor/test-runner.js.map +1 -0
- package/dist/executor/token-detector/index.d.ts +7 -0
- package/dist/executor/token-detector/index.d.ts.map +1 -0
- package/dist/executor/token-detector/index.js +7 -0
- package/dist/executor/token-detector/index.js.map +1 -0
- package/dist/executor/token-detector/token-detector.d.ts +64 -0
- package/dist/executor/token-detector/token-detector.d.ts.map +1 -0
- package/dist/executor/token-detector/token-detector.js +140 -0
- package/dist/executor/token-detector/token-detector.js.map +1 -0
- package/dist/generators/business-rule-from-stories-generator.d.ts +30 -0
- package/dist/generators/business-rule-from-stories-generator.d.ts.map +1 -0
- package/dist/generators/business-rule-from-stories-generator.js +227 -0
- package/dist/generators/business-rule-from-stories-generator.js.map +1 -0
- package/dist/generators/data/ai-data-generator.d.ts +23 -0
- package/dist/generators/data/ai-data-generator.d.ts.map +1 -0
- package/dist/generators/data/ai-data-generator.js +41 -0
- package/dist/generators/data/ai-data-generator.js.map +1 -0
- package/dist/generators/data/base-generator.d.ts +121 -0
- package/dist/generators/data/base-generator.d.ts.map +1 -0
- package/dist/generators/data/base-generator.js +200 -0
- package/dist/generators/data/base-generator.js.map +1 -0
- package/dist/generators/data/heuristic-data-generator.d.ts +28 -0
- package/dist/generators/data/heuristic-data-generator.d.ts.map +1 -0
- package/dist/generators/data/heuristic-data-generator.js +49 -0
- package/dist/generators/data/heuristic-data-generator.js.map +1 -0
- package/dist/generators/data/index.d.ts +48 -0
- package/dist/generators/data/index.d.ts.map +1 -0
- package/dist/generators/data/index.js +201 -0
- package/dist/generators/data/index.js.map +1 -0
- package/dist/generators/data/schema-walker.d.ts +45 -0
- package/dist/generators/data/schema-walker.d.ts.map +1 -0
- package/dist/generators/data/schema-walker.js +103 -0
- package/dist/generators/data/schema-walker.js.map +1 -0
- package/dist/generators/data/type-strategies.d.ts +79 -0
- package/dist/generators/data/type-strategies.d.ts.map +1 -0
- package/dist/generators/data/type-strategies.js +394 -0
- package/dist/generators/data/type-strategies.js.map +1 -0
- package/dist/generators/data-generator.d.ts +11 -0
- package/dist/generators/data-generator.d.ts.map +1 -0
- package/dist/generators/data-generator.js +11 -0
- package/dist/generators/data-generator.js.map +1 -0
- package/dist/generators/edge-case-generator.d.ts +55 -0
- package/dist/generators/edge-case-generator.d.ts.map +1 -0
- package/dist/generators/edge-case-generator.js +327 -0
- package/dist/generators/edge-case-generator.js.map +1 -0
- package/dist/generators/edge-cases/boundary-analyzer.d.ts +26 -0
- package/dist/generators/edge-cases/boundary-analyzer.d.ts.map +1 -0
- package/dist/generators/edge-cases/boundary-analyzer.js +95 -0
- package/dist/generators/edge-cases/boundary-analyzer.js.map +1 -0
- package/dist/generators/error-case-generator.d.ts +11 -0
- package/dist/generators/error-case-generator.d.ts.map +1 -0
- package/dist/generators/error-case-generator.js +11 -0
- package/dist/generators/error-case-generator.js.map +1 -0
- package/dist/generators/errors/auth-error-strategy.d.ts +36 -0
- package/dist/generators/errors/auth-error-strategy.d.ts.map +1 -0
- package/dist/generators/errors/auth-error-strategy.js +118 -0
- package/dist/generators/errors/auth-error-strategy.js.map +1 -0
- package/dist/generators/errors/business-error-strategy.d.ts +44 -0
- package/dist/generators/errors/business-error-strategy.d.ts.map +1 -0
- package/dist/generators/errors/business-error-strategy.js +152 -0
- package/dist/generators/errors/business-error-strategy.js.map +1 -0
- package/dist/generators/errors/error-strategy-factory.d.ts +27 -0
- package/dist/generators/errors/error-strategy-factory.d.ts.map +1 -0
- package/dist/generators/errors/error-strategy-factory.js +47 -0
- package/dist/generators/errors/error-strategy-factory.js.map +1 -0
- package/dist/generators/errors/error-strategy.d.ts +62 -0
- package/dist/generators/errors/error-strategy.d.ts.map +1 -0
- package/dist/generators/errors/error-strategy.js +69 -0
- package/dist/generators/errors/error-strategy.js.map +1 -0
- package/dist/generators/errors/index.d.ts +23 -0
- package/dist/generators/errors/index.d.ts.map +1 -0
- package/dist/generators/errors/index.js +73 -0
- package/dist/generators/errors/index.js.map +1 -0
- package/dist/generators/errors/validation-error-strategy.d.ts +25 -0
- package/dist/generators/errors/validation-error-strategy.d.ts.map +1 -0
- package/dist/generators/errors/validation-error-strategy.js +214 -0
- package/dist/generators/errors/validation-error-strategy.js.map +1 -0
- package/dist/generators/happy-path-generator.d.ts +93 -0
- package/dist/generators/happy-path-generator.d.ts.map +1 -0
- package/dist/generators/happy-path-generator.js +275 -0
- package/dist/generators/happy-path-generator.js.map +1 -0
- package/dist/generators/test-enricher.d.ts +44 -0
- package/dist/generators/test-enricher.d.ts.map +1 -0
- package/dist/generators/test-enricher.js +109 -0
- package/dist/generators/test-enricher.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/llm/ai-cache.d.ts +123 -0
- package/dist/llm/ai-cache.d.ts.map +1 -0
- package/dist/llm/ai-cache.js +220 -0
- package/dist/llm/ai-cache.js.map +1 -0
- package/dist/llm/ai-client.d.ts +92 -0
- package/dist/llm/ai-client.d.ts.map +1 -0
- package/dist/llm/ai-client.js +386 -0
- package/dist/llm/ai-client.js.map +1 -0
- package/dist/llm/data-generator-ai.d.ts +84 -0
- package/dist/llm/data-generator-ai.d.ts.map +1 -0
- package/dist/llm/data-generator-ai.js +284 -0
- package/dist/llm/data-generator-ai.js.map +1 -0
- package/dist/llm/index.d.ts +7 -0
- package/dist/llm/index.d.ts.map +1 -0
- package/dist/llm/index.js +7 -0
- package/dist/llm/index.js.map +1 -0
- package/dist/mcp/handlers/base-handler.d.ts +72 -0
- package/dist/mcp/handlers/base-handler.d.ts.map +1 -0
- package/dist/mcp/handlers/base-handler.js +86 -0
- package/dist/mcp/handlers/base-handler.js.map +1 -0
- package/dist/mcp/handlers/compare-sources.d.ts +91 -0
- package/dist/mcp/handlers/compare-sources.d.ts.map +1 -0
- package/dist/mcp/handlers/compare-sources.js +182 -0
- package/dist/mcp/handlers/compare-sources.js.map +1 -0
- package/dist/mcp/handlers/export-results.d.ts +53 -0
- package/dist/mcp/handlers/export-results.d.ts.map +1 -0
- package/dist/mcp/handlers/export-results.js +132 -0
- package/dist/mcp/handlers/export-results.js.map +1 -0
- package/dist/mcp/handlers/export-to-postman.d.ts +65 -0
- package/dist/mcp/handlers/export-to-postman.d.ts.map +1 -0
- package/dist/mcp/handlers/export-to-postman.js +128 -0
- package/dist/mcp/handlers/export-to-postman.js.map +1 -0
- package/dist/mcp/handlers/generate-tests.d.ts +74 -0
- package/dist/mcp/handlers/generate-tests.d.ts.map +1 -0
- package/dist/mcp/handlers/generate-tests.js +519 -0
- package/dist/mcp/handlers/generate-tests.js.map +1 -0
- package/dist/mcp/handlers/index.d.ts +13 -0
- package/dist/mcp/handlers/index.d.ts.map +1 -0
- package/dist/mcp/handlers/index.js +12 -0
- package/dist/mcp/handlers/index.js.map +1 -0
- package/dist/mcp/handlers/run-tests.d.ts +89 -0
- package/dist/mcp/handlers/run-tests.d.ts.map +1 -0
- package/dist/mcp/handlers/run-tests.js +233 -0
- package/dist/mcp/handlers/run-tests.js.map +1 -0
- package/dist/mcp/handlers/types.d.ts +61 -0
- package/dist/mcp/handlers/types.d.ts.map +1 -0
- package/dist/mcp/handlers/types.js +9 -0
- package/dist/mcp/handlers/types.js.map +1 -0
- package/dist/mcp/server.d.ts +64 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +200 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/services/file-service.d.ts +66 -0
- package/dist/mcp/services/file-service.d.ts.map +1 -0
- package/dist/mcp/services/file-service.js +143 -0
- package/dist/mcp/services/file-service.js.map +1 -0
- package/dist/mcp/services/llm-service.d.ts +70 -0
- package/dist/mcp/services/llm-service.d.ts.map +1 -0
- package/dist/mcp/services/llm-service.js +189 -0
- package/dist/mcp/services/llm-service.js.map +1 -0
- package/dist/mcp/services/postman-service.d.ts +128 -0
- package/dist/mcp/services/postman-service.d.ts.map +1 -0
- package/dist/mcp/services/postman-service.js +266 -0
- package/dist/mcp/services/postman-service.js.map +1 -0
- package/dist/mcp/services/report-service.d.ts +81 -0
- package/dist/mcp/services/report-service.d.ts.map +1 -0
- package/dist/mcp/services/report-service.js +210 -0
- package/dist/mcp/services/report-service.js.map +1 -0
- package/dist/mcp/services/spec-service.d.ts +58 -0
- package/dist/mcp/services/spec-service.d.ts.map +1 -0
- package/dist/mcp/services/spec-service.js +140 -0
- package/dist/mcp/services/spec-service.js.map +1 -0
- package/dist/parsers/endpoint-extractor.d.ts +32 -0
- package/dist/parsers/endpoint-extractor.d.ts.map +1 -0
- package/dist/parsers/endpoint-extractor.js +160 -0
- package/dist/parsers/endpoint-extractor.js.map +1 -0
- package/dist/parsers/openapi-parser.d.ts +120 -0
- package/dist/parsers/openapi-parser.d.ts.map +1 -0
- package/dist/parsers/openapi-parser.js +257 -0
- package/dist/parsers/openapi-parser.js.map +1 -0
- package/dist/parsers/visitors/auth-visitor.d.ts +28 -0
- package/dist/parsers/visitors/auth-visitor.d.ts.map +1 -0
- package/dist/parsers/visitors/auth-visitor.js +116 -0
- package/dist/parsers/visitors/auth-visitor.js.map +1 -0
- package/dist/prd/index.d.ts +10 -0
- package/dist/prd/index.d.ts.map +1 -0
- package/dist/prd/index.js +10 -0
- package/dist/prd/index.js.map +1 -0
- package/dist/prd/prd-reader.d.ts +124 -0
- package/dist/prd/prd-reader.d.ts.map +1 -0
- package/dist/prd/prd-reader.js +308 -0
- package/dist/prd/prd-reader.js.map +1 -0
- package/dist/prd/prd-storage.d.ts +232 -0
- package/dist/prd/prd-storage.d.ts.map +1 -0
- package/dist/prd/prd-storage.js +129 -0
- package/dist/prd/prd-storage.js.map +1 -0
- package/dist/repairers/test-auto-repairer.d.ts +61 -0
- package/dist/repairers/test-auto-repairer.d.ts.map +1 -0
- package/dist/repairers/test-auto-repairer.js +213 -0
- package/dist/repairers/test-auto-repairer.js.map +1 -0
- package/dist/reporters/comparison-report-generator.d.ts +58 -0
- package/dist/reporters/comparison-report-generator.d.ts.map +1 -0
- package/dist/reporters/comparison-report-generator.js +369 -0
- package/dist/reporters/comparison-report-generator.js.map +1 -0
- package/dist/reporters/gherkin-formatter.d.ts +34 -0
- package/dist/reporters/gherkin-formatter.d.ts.map +1 -0
- package/dist/reporters/gherkin-formatter.js +231 -0
- package/dist/reporters/gherkin-formatter.js.map +1 -0
- package/dist/reporters/html-report-generator.d.ts +174 -0
- package/dist/reporters/html-report-generator.d.ts.map +1 -0
- package/dist/reporters/html-report-generator.js +194 -0
- package/dist/reporters/html-report-generator.js.map +1 -0
- package/dist/reporters/report-charts.d.ts +23 -0
- package/dist/reporters/report-charts.d.ts.map +1 -0
- package/dist/reporters/report-charts.js +182 -0
- package/dist/reporters/report-charts.js.map +1 -0
- package/dist/reporters/report-sections.d.ts +34 -0
- package/dist/reporters/report-sections.d.ts.map +1 -0
- package/dist/reporters/report-sections.js +481 -0
- package/dist/reporters/report-sections.js.map +1 -0
- package/dist/reporters/report-styles.d.ts +12 -0
- package/dist/reporters/report-styles.d.ts.map +1 -0
- package/dist/reporters/report-styles.js +412 -0
- package/dist/reporters/report-styles.js.map +1 -0
- package/dist/reporters/report-test-details.d.ts +56 -0
- package/dist/reporters/report-test-details.d.ts.map +1 -0
- package/dist/reporters/report-test-details.js +328 -0
- package/dist/reporters/report-test-details.js.map +1 -0
- package/dist/reporters/report-utils.d.ts +40 -0
- package/dist/reporters/report-utils.d.ts.map +1 -0
- package/dist/reporters/report-utils.js +163 -0
- package/dist/reporters/report-utils.js.map +1 -0
- package/dist/types/ai-config.d.ts +63 -0
- package/dist/types/ai-config.d.ts.map +1 -0
- package/dist/types/ai-config.js +79 -0
- package/dist/types/ai-config.js.map +1 -0
- package/dist/types/business-rules.d.ts +235 -0
- package/dist/types/business-rules.d.ts.map +1 -0
- package/dist/types/business-rules.js +6 -0
- package/dist/types/business-rules.js.map +1 -0
- package/dist/types/config.d.ts +106 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +6 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/core.d.ts +72 -0
- package/dist/types/core.d.ts.map +1 -0
- package/dist/types/core.js +6 -0
- package/dist/types/core.js.map +1 -0
- package/dist/types/index.d.ts +17 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +10 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/openapi.d.ts +139 -0
- package/dist/types/openapi.d.ts.map +1 -0
- package/dist/types/openapi.js +6 -0
- package/dist/types/openapi.js.map +1 -0
- package/dist/types/pact.d.ts +101 -0
- package/dist/types/pact.d.ts.map +1 -0
- package/dist/types/pact.js +6 -0
- package/dist/types/pact.js.map +1 -0
- package/dist/types/reporting.d.ts +93 -0
- package/dist/types/reporting.d.ts.map +1 -0
- package/dist/types/reporting.js +6 -0
- package/dist/types/reporting.js.map +1 -0
- package/dist/types/test-case.d.ts +233 -0
- package/dist/types/test-case.d.ts.map +1 -0
- package/dist/types/test-case.js +6 -0
- package/dist/types/test-case.js.map +1 -0
- package/dist/types/test-execution.d.ts +80 -0
- package/dist/types/test-execution.d.ts.map +1 -0
- package/dist/types/test-execution.js +6 -0
- package/dist/types/test-execution.js.map +1 -0
- package/dist/utils/auth-generator.d.ts +30 -0
- package/dist/utils/auth-generator.d.ts.map +1 -0
- package/dist/utils/auth-generator.js +68 -0
- package/dist/utils/auth-generator.js.map +1 -0
- package/dist/utils/config.d.ts +181 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +141 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/coverage-calculator.d.ts +81 -0
- package/dist/utils/coverage-calculator.d.ts.map +1 -0
- package/dist/utils/coverage-calculator.js +134 -0
- package/dist/utils/coverage-calculator.js.map +1 -0
- package/dist/utils/data-loader.d.ts +52 -0
- package/dist/utils/data-loader.d.ts.map +1 -0
- package/dist/utils/data-loader.js +192 -0
- package/dist/utils/data-loader.js.map +1 -0
- package/dist/utils/errors.d.ts +167 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +257 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/logger.d.ts +220 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +325 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/openapi-discovery.d.ts +31 -0
- package/dist/utils/openapi-discovery.d.ts.map +1 -0
- package/dist/utils/openapi-discovery.js +322 -0
- package/dist/utils/openapi-discovery.js.map +1 -0
- package/dist/utils/path-resolver.d.ts +101 -0
- package/dist/utils/path-resolver.d.ts.map +1 -0
- package/dist/utils/path-resolver.js +167 -0
- package/dist/utils/path-resolver.js.map +1 -0
- package/dist/utils/resilience.d.ts +181 -0
- package/dist/utils/resilience.d.ts.map +1 -0
- package/dist/utils/resilience.js +269 -0
- package/dist/utils/resilience.js.map +1 -0
- package/dist/validators/openapi-validator.d.ts +198 -0
- package/dist/validators/openapi-validator.d.ts.map +1 -0
- package/dist/validators/openapi-validator.js +349 -0
- package/dist/validators/openapi-validator.js.map +1 -0
- package/dist/validators/response-matcher.d.ts +84 -0
- package/dist/validators/response-matcher.d.ts.map +1 -0
- package/dist/validators/response-matcher.js +234 -0
- package/dist/validators/response-matcher.js.map +1 -0
- package/dist/validators/schema-validator.d.ts +174 -0
- package/dist/validators/schema-validator.d.ts.map +1 -0
- package/dist/validators/schema-validator.js +340 -0
- package/dist/validators/schema-validator.js.map +1 -0
- package/package.json +76 -0
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized Logger for OpenAPI Contract Tester
|
|
3
|
+
*
|
|
4
|
+
* Provides robust logging with support for:
|
|
5
|
+
* - MCP mode (writes to file, not stdout/stderr to avoid breaking STDIO protocol)
|
|
6
|
+
* - Standalone mode (uses console for development/testing)
|
|
7
|
+
* - Log levels (DEBUG, INFO, WARN, ERROR)
|
|
8
|
+
* - Structured logging (JSON format)
|
|
9
|
+
* - Automatic log rotation
|
|
10
|
+
*
|
|
11
|
+
* @module utils/logger
|
|
12
|
+
*/
|
|
13
|
+
import * as fs from 'fs';
|
|
14
|
+
import * as path from 'path';
|
|
15
|
+
import { config } from './config.js';
|
|
16
|
+
/**
|
|
17
|
+
* Log levels in order of severity
|
|
18
|
+
*/
|
|
19
|
+
export var LogLevel;
|
|
20
|
+
(function (LogLevel) {
|
|
21
|
+
LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
|
|
22
|
+
LogLevel[LogLevel["INFO"] = 1] = "INFO";
|
|
23
|
+
LogLevel[LogLevel["WARN"] = 2] = "WARN";
|
|
24
|
+
LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
|
|
25
|
+
})(LogLevel || (LogLevel = {}));
|
|
26
|
+
/**
|
|
27
|
+
* Centralized logger for the application
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* // Initialize for MCP mode (no console output)
|
|
32
|
+
* const logger = new Logger({
|
|
33
|
+
* useConsole: false,
|
|
34
|
+
* writeToFile: true,
|
|
35
|
+
* minLevel: LogLevel.INFO
|
|
36
|
+
* });
|
|
37
|
+
*
|
|
38
|
+
* // Log messages
|
|
39
|
+
* logger.info('Server started', { port: 3000 });
|
|
40
|
+
* logger.error('Failed to parse spec', { error, file: 'api.yml' });
|
|
41
|
+
*
|
|
42
|
+
* // Log with source
|
|
43
|
+
* logger.warn('Endpoint not found', { endpoint: 'POST /users' }, 'business-rules-generator');
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export class Logger {
|
|
47
|
+
config;
|
|
48
|
+
currentLogFile = null;
|
|
49
|
+
currentLogSize = 0;
|
|
50
|
+
constructor(config = {}) {
|
|
51
|
+
this.config = {
|
|
52
|
+
minLevel: config.minLevel ?? LogLevel.INFO,
|
|
53
|
+
logDir: config.logDir ?? './logs',
|
|
54
|
+
logFileName: config.logFileName ?? 'mcp-server',
|
|
55
|
+
maxFileSize: config.maxFileSize ?? 10 * 1024 * 1024, // 10MB
|
|
56
|
+
maxFiles: config.maxFiles ?? 5,
|
|
57
|
+
useConsole: config.useConsole ?? true,
|
|
58
|
+
writeToFile: config.writeToFile ?? false,
|
|
59
|
+
includeSource: config.includeSource ?? true,
|
|
60
|
+
};
|
|
61
|
+
// Create log directory if it doesn't exist
|
|
62
|
+
if (this.config.writeToFile) {
|
|
63
|
+
this.ensureLogDirectory();
|
|
64
|
+
this.currentLogFile = this.getLogFilePath();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Logs a debug message
|
|
69
|
+
*
|
|
70
|
+
* @param message - Log message
|
|
71
|
+
* @param meta - Optional metadata
|
|
72
|
+
* @param source - Optional source component
|
|
73
|
+
*/
|
|
74
|
+
debug(message, meta, source) {
|
|
75
|
+
this.log(LogLevel.DEBUG, 'debug', message, meta, source);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Logs an info message
|
|
79
|
+
*
|
|
80
|
+
* @param message - Log message
|
|
81
|
+
* @param meta - Optional metadata
|
|
82
|
+
* @param source - Optional source component
|
|
83
|
+
*/
|
|
84
|
+
info(message, meta, source) {
|
|
85
|
+
this.log(LogLevel.INFO, 'info', message, meta, source);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Logs a warning message
|
|
89
|
+
*
|
|
90
|
+
* @param message - Log message
|
|
91
|
+
* @param meta - Optional metadata
|
|
92
|
+
* @param source - Optional source component
|
|
93
|
+
*/
|
|
94
|
+
warn(message, meta, source) {
|
|
95
|
+
this.log(LogLevel.WARN, 'warn', message, meta, source);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Logs an error message
|
|
99
|
+
*
|
|
100
|
+
* @param message - Log message
|
|
101
|
+
* @param meta - Optional metadata (can include Error object)
|
|
102
|
+
* @param source - Optional source component
|
|
103
|
+
*/
|
|
104
|
+
error(message, meta, source) {
|
|
105
|
+
this.log(LogLevel.ERROR, 'error', message, meta, source);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Core logging method
|
|
109
|
+
* @internal
|
|
110
|
+
*/
|
|
111
|
+
log(level, levelName, message, meta, source) {
|
|
112
|
+
// Check if we should log this level
|
|
113
|
+
if (level < this.config.minLevel) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const entry = {
|
|
117
|
+
timestamp: new Date().toISOString(),
|
|
118
|
+
level: levelName,
|
|
119
|
+
message,
|
|
120
|
+
};
|
|
121
|
+
if (meta !== undefined) {
|
|
122
|
+
// Serialize Error objects properly
|
|
123
|
+
if (meta instanceof Error) {
|
|
124
|
+
entry.meta = {
|
|
125
|
+
name: meta.name,
|
|
126
|
+
message: meta.message,
|
|
127
|
+
stack: meta.stack,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
entry.meta = meta;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (source && this.config.includeSource) {
|
|
135
|
+
entry.source = source;
|
|
136
|
+
}
|
|
137
|
+
// Write to console if enabled
|
|
138
|
+
if (this.config.useConsole) {
|
|
139
|
+
this.writeToConsole(levelName, entry);
|
|
140
|
+
}
|
|
141
|
+
// Write to file if enabled
|
|
142
|
+
if (this.config.writeToFile && this.currentLogFile) {
|
|
143
|
+
this.writeToFile(entry);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Writes log entry to console (for standalone mode)
|
|
148
|
+
* @internal
|
|
149
|
+
*/
|
|
150
|
+
writeToConsole(level, entry) {
|
|
151
|
+
const prefix = `[${entry.timestamp}] [${level.toUpperCase()}]${entry.source ? ` [${entry.source}]` : ''}`;
|
|
152
|
+
const message = `${prefix} ${entry.message}`;
|
|
153
|
+
if (level === 'error') {
|
|
154
|
+
console.error(message, entry.meta || '');
|
|
155
|
+
}
|
|
156
|
+
else if (level === 'warn') {
|
|
157
|
+
console.warn(message, entry.meta || '');
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
console.log(message, entry.meta || '');
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Writes log entry to file (for MCP mode)
|
|
165
|
+
* @internal
|
|
166
|
+
*/
|
|
167
|
+
writeToFile(entry) {
|
|
168
|
+
if (!this.currentLogFile)
|
|
169
|
+
return;
|
|
170
|
+
try {
|
|
171
|
+
const line = JSON.stringify(entry) + '\n';
|
|
172
|
+
const lineSize = Buffer.byteLength(line, 'utf8');
|
|
173
|
+
// Check if we need to rotate
|
|
174
|
+
if (this.currentLogSize + lineSize > this.config.maxFileSize) {
|
|
175
|
+
this.rotateLogFile();
|
|
176
|
+
}
|
|
177
|
+
// Append to current log file
|
|
178
|
+
fs.appendFileSync(this.currentLogFile, line, 'utf8');
|
|
179
|
+
this.currentLogSize += lineSize;
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
// Fallback to stderr only if writing to file fails
|
|
183
|
+
// This won't break MCP protocol as it's an exceptional case
|
|
184
|
+
if (error instanceof Error) {
|
|
185
|
+
process.stderr.write(`Logger error: ${error.message}\n`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Ensures log directory exists
|
|
191
|
+
* @internal
|
|
192
|
+
*/
|
|
193
|
+
ensureLogDirectory() {
|
|
194
|
+
if (!fs.existsSync(this.config.logDir)) {
|
|
195
|
+
fs.mkdirSync(this.config.logDir, { recursive: true });
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Gets the current log file path
|
|
200
|
+
* @internal
|
|
201
|
+
*/
|
|
202
|
+
getLogFilePath() {
|
|
203
|
+
const date = new Date().toISOString().split('T')[0]; // YYYY-MM-DD
|
|
204
|
+
return path.join(this.config.logDir, `${this.config.logFileName}-${date}.log`);
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Rotates log files when max size is reached
|
|
208
|
+
* @internal
|
|
209
|
+
*/
|
|
210
|
+
rotateLogFile() {
|
|
211
|
+
if (!this.currentLogFile)
|
|
212
|
+
return;
|
|
213
|
+
try {
|
|
214
|
+
// Rename current file with timestamp
|
|
215
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
216
|
+
const rotatedFile = this.currentLogFile.replace('.log', `-${timestamp}.log`);
|
|
217
|
+
if (fs.existsSync(this.currentLogFile)) {
|
|
218
|
+
fs.renameSync(this.currentLogFile, rotatedFile);
|
|
219
|
+
}
|
|
220
|
+
// Clean up old log files (keep only maxFiles)
|
|
221
|
+
this.cleanupOldLogs();
|
|
222
|
+
// Reset current log file
|
|
223
|
+
this.currentLogFile = this.getLogFilePath();
|
|
224
|
+
this.currentLogSize = 0;
|
|
225
|
+
}
|
|
226
|
+
catch (error) {
|
|
227
|
+
// Log rotation failure - continue with current file
|
|
228
|
+
if (error instanceof Error) {
|
|
229
|
+
process.stderr.write(`Log rotation error: ${error.message}\n`);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Removes old log files beyond maxFiles limit
|
|
235
|
+
* @internal
|
|
236
|
+
*/
|
|
237
|
+
cleanupOldLogs() {
|
|
238
|
+
try {
|
|
239
|
+
const files = fs.readdirSync(this.config.logDir)
|
|
240
|
+
.filter(f => f.startsWith(this.config.logFileName) && f.endsWith('.log'))
|
|
241
|
+
.map(f => ({
|
|
242
|
+
name: f,
|
|
243
|
+
path: path.join(this.config.logDir, f),
|
|
244
|
+
mtime: fs.statSync(path.join(this.config.logDir, f)).mtime.getTime()
|
|
245
|
+
}))
|
|
246
|
+
.sort((a, b) => b.mtime - a.mtime); // newest first
|
|
247
|
+
// Remove files beyond maxFiles limit
|
|
248
|
+
const filesToRemove = files.slice(this.config.maxFiles);
|
|
249
|
+
for (const file of filesToRemove) {
|
|
250
|
+
fs.unlinkSync(file.path);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
catch (error) {
|
|
254
|
+
// Cleanup failure - not critical, just log to stderr
|
|
255
|
+
if (error instanceof Error) {
|
|
256
|
+
process.stderr.write(`Log cleanup error: ${error.message}\n`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Flushes any pending logs (useful before shutdown)
|
|
262
|
+
*/
|
|
263
|
+
flush() {
|
|
264
|
+
// In this implementation, logs are written synchronously,
|
|
265
|
+
// so there's nothing to flush. This method is provided for
|
|
266
|
+
// API compatibility in case we add async logging later.
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Map config log level to LogLevel enum
|
|
271
|
+
*/
|
|
272
|
+
function mapLogLevel(level) {
|
|
273
|
+
switch (level) {
|
|
274
|
+
case 'debug':
|
|
275
|
+
return LogLevel.DEBUG;
|
|
276
|
+
case 'info':
|
|
277
|
+
return LogLevel.INFO;
|
|
278
|
+
case 'warn':
|
|
279
|
+
return LogLevel.WARN;
|
|
280
|
+
case 'error':
|
|
281
|
+
return LogLevel.ERROR;
|
|
282
|
+
default:
|
|
283
|
+
return LogLevel.INFO;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Global logger instance
|
|
288
|
+
*
|
|
289
|
+
* Configured from environment variables via config module:
|
|
290
|
+
* - MCP_MODE: Enable file logging (auto-detected from STDIO)
|
|
291
|
+
* - LOG_LEVEL: Minimum log level (debug, info, warn, error)
|
|
292
|
+
* - LOG_DIR or MCP_ROOT/logs: Log directory
|
|
293
|
+
* - MAX_LOG_FILE_SIZE: Maximum file size before rotation (bytes)
|
|
294
|
+
* - MAX_LOG_FILES: Number of rotated files to keep
|
|
295
|
+
*/
|
|
296
|
+
export const logger = new Logger({
|
|
297
|
+
useConsole: !config.mcpMode,
|
|
298
|
+
writeToFile: config.mcpMode,
|
|
299
|
+
minLevel: mapLogLevel(config.log.level),
|
|
300
|
+
logDir: config.log.logDir,
|
|
301
|
+
maxFileSize: config.log.maxFileSize,
|
|
302
|
+
maxFiles: config.log.maxFiles,
|
|
303
|
+
});
|
|
304
|
+
/**
|
|
305
|
+
* Creates a logger with a specific source tag
|
|
306
|
+
*
|
|
307
|
+
* @param source - Source component name
|
|
308
|
+
* @returns Logger wrapper with source pre-set
|
|
309
|
+
*
|
|
310
|
+
* @example
|
|
311
|
+
* ```typescript
|
|
312
|
+
* const log = createLogger('business-rules-generator');
|
|
313
|
+
* log.info('Processing rules', { count: 20 });
|
|
314
|
+
* // Output: [2025-01-19T10:00:00Z] [INFO] [business-rules-generator] Processing rules
|
|
315
|
+
* ```
|
|
316
|
+
*/
|
|
317
|
+
export function createLogger(source) {
|
|
318
|
+
return {
|
|
319
|
+
debug: (message, meta) => logger.debug(message, meta, source),
|
|
320
|
+
info: (message, meta) => logger.info(message, meta, source),
|
|
321
|
+
warn: (message, meta) => logger.warn(message, meta, source),
|
|
322
|
+
error: (message, meta) => logger.error(message, meta, source),
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAPI Auto-Discovery Utility
|
|
3
|
+
*
|
|
4
|
+
* Automatically discovers OpenAPI specifications from a base URL by:
|
|
5
|
+
* 1. Trying common paths (fast)
|
|
6
|
+
* 2. Using AI to extract from documentation (slower, more comprehensive)
|
|
7
|
+
*
|
|
8
|
+
* @module utils/openapi-discovery
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Attempts to discover OpenAPI specification from a base URL
|
|
12
|
+
*
|
|
13
|
+
* @param baseUrl - Base URL of the API
|
|
14
|
+
* @returns OpenAPI spec content or null if not found
|
|
15
|
+
*/
|
|
16
|
+
export declare function discoverOpenAPI(baseUrl: string): Promise<string | null>;
|
|
17
|
+
/**
|
|
18
|
+
* Tries to fetch OpenAPI spec from common paths
|
|
19
|
+
*
|
|
20
|
+
* @param baseUrl - Base URL of the API
|
|
21
|
+
* @returns OpenAPI spec content or null
|
|
22
|
+
*/
|
|
23
|
+
export declare function tryCommonPaths(baseUrl: string): Promise<string | null>;
|
|
24
|
+
/**
|
|
25
|
+
* Attempts to extract OpenAPI spec from documentation pages using AI
|
|
26
|
+
*
|
|
27
|
+
* @param baseUrl - Base URL of the API
|
|
28
|
+
* @returns OpenAPI spec content or null
|
|
29
|
+
*/
|
|
30
|
+
export declare function extractFromDocs(baseUrl: string): Promise<string | null>;
|
|
31
|
+
//# sourceMappingURL=openapi-discovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openapi-discovery.d.ts","sourceRoot":"","sources":["../../src/utils/openapi-discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAgDH;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiB7E;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA8C5E;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAkD7E"}
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAPI Auto-Discovery Utility
|
|
3
|
+
*
|
|
4
|
+
* Automatically discovers OpenAPI specifications from a base URL by:
|
|
5
|
+
* 1. Trying common paths (fast)
|
|
6
|
+
* 2. Using AI to extract from documentation (slower, more comprehensive)
|
|
7
|
+
*
|
|
8
|
+
* @module utils/openapi-discovery
|
|
9
|
+
*/
|
|
10
|
+
import { callLLM } from '../llm/ai-client.js';
|
|
11
|
+
import { createLogger } from './logger.js';
|
|
12
|
+
const log = createLogger('openapi-discovery');
|
|
13
|
+
/**
|
|
14
|
+
* Common paths where OpenAPI specs are typically located
|
|
15
|
+
*/
|
|
16
|
+
const COMMON_SPEC_PATHS = [
|
|
17
|
+
'/openapi.json',
|
|
18
|
+
'/openapi.yaml',
|
|
19
|
+
'/swagger.json',
|
|
20
|
+
'/swagger.yaml',
|
|
21
|
+
'/api-docs',
|
|
22
|
+
'/api-docs.json',
|
|
23
|
+
'/api-docs.yaml',
|
|
24
|
+
'/docs/openapi.json',
|
|
25
|
+
'/docs/openapi.yaml',
|
|
26
|
+
'/docs/swagger.json',
|
|
27
|
+
'/docs/swagger.yaml',
|
|
28
|
+
'/v1/openapi.json',
|
|
29
|
+
'/v1/swagger.json',
|
|
30
|
+
'/v2/openapi.json',
|
|
31
|
+
'/v3/openapi.json',
|
|
32
|
+
'/api/openapi.json',
|
|
33
|
+
'/api/swagger.json',
|
|
34
|
+
'/.well-known/api-docs',
|
|
35
|
+
'/.well-known/openapi.json',
|
|
36
|
+
'/redoc/openapi.json',
|
|
37
|
+
'/swagger-ui/openapi.json'
|
|
38
|
+
];
|
|
39
|
+
/**
|
|
40
|
+
* Common documentation paths to check
|
|
41
|
+
*/
|
|
42
|
+
const COMMON_DOC_PATHS = [
|
|
43
|
+
'/docs',
|
|
44
|
+
'/api-docs',
|
|
45
|
+
'/documentation',
|
|
46
|
+
'/swagger-ui',
|
|
47
|
+
'/swagger',
|
|
48
|
+
'/redoc',
|
|
49
|
+
'/api/docs',
|
|
50
|
+
'/api/documentation'
|
|
51
|
+
];
|
|
52
|
+
/**
|
|
53
|
+
* Attempts to discover OpenAPI specification from a base URL
|
|
54
|
+
*
|
|
55
|
+
* @param baseUrl - Base URL of the API
|
|
56
|
+
* @returns OpenAPI spec content or null if not found
|
|
57
|
+
*/
|
|
58
|
+
export async function discoverOpenAPI(baseUrl) {
|
|
59
|
+
log.info('Starting OpenAPI auto-discovery', { baseUrl });
|
|
60
|
+
// Phase 1: Try common paths (fast)
|
|
61
|
+
const specFromCommonPath = await tryCommonPaths(baseUrl);
|
|
62
|
+
if (specFromCommonPath) {
|
|
63
|
+
return specFromCommonPath;
|
|
64
|
+
}
|
|
65
|
+
// Phase 2: Try to extract from documentation (slower)
|
|
66
|
+
const specFromDocs = await extractFromDocs(baseUrl);
|
|
67
|
+
if (specFromDocs) {
|
|
68
|
+
return specFromDocs;
|
|
69
|
+
}
|
|
70
|
+
log.warn('OpenAPI spec not found', { baseUrl });
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Tries to fetch OpenAPI spec from common paths
|
|
75
|
+
*
|
|
76
|
+
* @param baseUrl - Base URL of the API
|
|
77
|
+
* @returns OpenAPI spec content or null
|
|
78
|
+
*/
|
|
79
|
+
export async function tryCommonPaths(baseUrl) {
|
|
80
|
+
log.info('Trying common OpenAPI paths', { baseUrl, pathCount: COMMON_SPEC_PATHS.length });
|
|
81
|
+
// Ensure baseUrl doesn't end with slash
|
|
82
|
+
const cleanBaseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
|
|
83
|
+
for (const path of COMMON_SPEC_PATHS) {
|
|
84
|
+
try {
|
|
85
|
+
const url = cleanBaseUrl + path;
|
|
86
|
+
log.debug('Attempting to fetch spec', { url });
|
|
87
|
+
const controller = new AbortController();
|
|
88
|
+
const timeoutId = setTimeout(() => controller.abort(), 5000);
|
|
89
|
+
const response = await fetch(url, {
|
|
90
|
+
method: 'GET',
|
|
91
|
+
headers: {
|
|
92
|
+
'Accept': 'application/json, application/yaml, application/x-yaml, text/yaml, text/x-yaml'
|
|
93
|
+
},
|
|
94
|
+
signal: controller.signal
|
|
95
|
+
});
|
|
96
|
+
clearTimeout(timeoutId);
|
|
97
|
+
if (response.ok) {
|
|
98
|
+
const content = await response.text();
|
|
99
|
+
// Validate that it looks like an OpenAPI spec
|
|
100
|
+
if (isValidOpenAPISpec(content)) {
|
|
101
|
+
log.info('OpenAPI spec discovered', { url, size: content.length });
|
|
102
|
+
return content;
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
log.debug('Invalid OpenAPI spec format', { url });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
// Ignore errors, try next path
|
|
111
|
+
log.debug('Failed to fetch spec', {
|
|
112
|
+
path,
|
|
113
|
+
error: error instanceof Error ? error.message : String(error)
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
log.info('No OpenAPI spec found in common paths');
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Attempts to extract OpenAPI spec from documentation pages using AI
|
|
122
|
+
*
|
|
123
|
+
* @param baseUrl - Base URL of the API
|
|
124
|
+
* @returns OpenAPI spec content or null
|
|
125
|
+
*/
|
|
126
|
+
export async function extractFromDocs(baseUrl) {
|
|
127
|
+
log.info('Attempting to extract OpenAPI from documentation', { baseUrl });
|
|
128
|
+
const cleanBaseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
|
|
129
|
+
// Try to fetch documentation pages
|
|
130
|
+
for (const docPath of COMMON_DOC_PATHS) {
|
|
131
|
+
try {
|
|
132
|
+
const url = cleanBaseUrl + docPath;
|
|
133
|
+
log.debug('Fetching documentation page', { url });
|
|
134
|
+
const controller = new AbortController();
|
|
135
|
+
const timeoutId = setTimeout(() => controller.abort(), 5000);
|
|
136
|
+
const response = await fetch(url, {
|
|
137
|
+
method: 'GET',
|
|
138
|
+
headers: {
|
|
139
|
+
'Accept': 'text/html, application/xhtml+xml'
|
|
140
|
+
},
|
|
141
|
+
signal: controller.signal
|
|
142
|
+
});
|
|
143
|
+
clearTimeout(timeoutId);
|
|
144
|
+
if (response.ok) {
|
|
145
|
+
const html = await response.text();
|
|
146
|
+
// Check if the HTML contains references to OpenAPI spec
|
|
147
|
+
const specUrl = extractSpecUrlFromHTML(html, cleanBaseUrl);
|
|
148
|
+
if (specUrl) {
|
|
149
|
+
log.info('Found OpenAPI spec URL in docs', { specUrl });
|
|
150
|
+
return await fetchSpec(specUrl);
|
|
151
|
+
}
|
|
152
|
+
// If no direct URL found, try to extract with AI
|
|
153
|
+
const extractedSpec = await extractSpecWithAI(html, baseUrl);
|
|
154
|
+
if (extractedSpec) {
|
|
155
|
+
return extractedSpec;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
log.debug('Failed to fetch documentation', {
|
|
161
|
+
docPath,
|
|
162
|
+
error: error instanceof Error ? error.message : String(error)
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
log.info('Could not extract OpenAPI from documentation');
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Extracts OpenAPI spec URL from HTML content
|
|
171
|
+
*
|
|
172
|
+
* @param html - HTML content
|
|
173
|
+
* @param baseUrl - Base URL for resolving relative URLs
|
|
174
|
+
* @returns OpenAPI spec URL or null
|
|
175
|
+
*/
|
|
176
|
+
function extractSpecUrlFromHTML(html, baseUrl) {
|
|
177
|
+
// Common patterns in Swagger UI and ReDoc
|
|
178
|
+
const patterns = [
|
|
179
|
+
/url:\s*["']([^"']+)["']/,
|
|
180
|
+
/spec-url:\s*["']([^"']+)["']/,
|
|
181
|
+
/spec:\s*["']([^"']+)["']/,
|
|
182
|
+
/data-spec-url=["']([^"']+)["']/,
|
|
183
|
+
/"specUrl":\s*["']([^"']+)["']/,
|
|
184
|
+
/"spec":\s*["']([^"']+)["']/
|
|
185
|
+
];
|
|
186
|
+
for (const pattern of patterns) {
|
|
187
|
+
const match = html.match(pattern);
|
|
188
|
+
if (match && match[1]) {
|
|
189
|
+
const specUrl = match[1];
|
|
190
|
+
// Resolve relative URLs
|
|
191
|
+
if (specUrl.startsWith('http')) {
|
|
192
|
+
return specUrl;
|
|
193
|
+
}
|
|
194
|
+
else if (specUrl.startsWith('/')) {
|
|
195
|
+
return baseUrl + specUrl;
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
return baseUrl + '/' + specUrl;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Fetches OpenAPI spec from a URL
|
|
206
|
+
*
|
|
207
|
+
* @param url - URL of the spec
|
|
208
|
+
* @returns Spec content or null
|
|
209
|
+
*/
|
|
210
|
+
async function fetchSpec(url) {
|
|
211
|
+
try {
|
|
212
|
+
const controller = new AbortController();
|
|
213
|
+
const timeoutId = setTimeout(() => controller.abort(), 5000);
|
|
214
|
+
const response = await fetch(url, {
|
|
215
|
+
method: 'GET',
|
|
216
|
+
headers: {
|
|
217
|
+
'Accept': 'application/json, application/yaml'
|
|
218
|
+
},
|
|
219
|
+
signal: controller.signal
|
|
220
|
+
});
|
|
221
|
+
clearTimeout(timeoutId);
|
|
222
|
+
if (response.ok) {
|
|
223
|
+
const content = await response.text();
|
|
224
|
+
if (isValidOpenAPISpec(content)) {
|
|
225
|
+
return content;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
log.debug('Failed to fetch spec', {
|
|
231
|
+
url,
|
|
232
|
+
error: error instanceof Error ? error.message : String(error)
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Uses AI to extract API endpoints from documentation and generate OpenAPI spec
|
|
239
|
+
*
|
|
240
|
+
* @param html - HTML documentation content
|
|
241
|
+
* @param baseUrl - Base URL of the API
|
|
242
|
+
* @returns Generated OpenAPI spec or null
|
|
243
|
+
*/
|
|
244
|
+
async function extractSpecWithAI(html, baseUrl) {
|
|
245
|
+
try {
|
|
246
|
+
// Truncate HTML to avoid token limits (first 10000 chars)
|
|
247
|
+
const truncatedHtml = html.slice(0, 10000);
|
|
248
|
+
const prompt = `Extract API endpoints from this HTML documentation and generate a basic OpenAPI 3.0 specification.
|
|
249
|
+
|
|
250
|
+
Base URL: ${baseUrl}
|
|
251
|
+
|
|
252
|
+
HTML Documentation (truncated):
|
|
253
|
+
${truncatedHtml}
|
|
254
|
+
|
|
255
|
+
Generate a valid OpenAPI 3.0 JSON specification with:
|
|
256
|
+
- info.title (extract from HTML)
|
|
257
|
+
- info.version (use "1.0.0" if not found)
|
|
258
|
+
- paths with methods (GET, POST, PUT, DELETE, etc.)
|
|
259
|
+
- basic request/response schemas (if visible in docs)
|
|
260
|
+
|
|
261
|
+
Respond with ONLY valid JSON in OpenAPI 3.0 format. Do not include explanations or markdown.`;
|
|
262
|
+
log.info('Attempting AI extraction from documentation');
|
|
263
|
+
const result = await callLLM(prompt, {
|
|
264
|
+
maxTokens: 4096,
|
|
265
|
+
temperature: 0.2,
|
|
266
|
+
timeout: 30000
|
|
267
|
+
});
|
|
268
|
+
if (!result.success || !result.text) {
|
|
269
|
+
log.warn('AI extraction failed', { error: result.error });
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
// Clean the response (remove markdown code blocks if present)
|
|
273
|
+
let cleanedText = result.text.trim();
|
|
274
|
+
if (cleanedText.startsWith('```')) {
|
|
275
|
+
cleanedText = cleanedText.replace(/^```(?:json)?\n/, '').replace(/\n```$/, '');
|
|
276
|
+
}
|
|
277
|
+
// Validate JSON
|
|
278
|
+
try {
|
|
279
|
+
JSON.parse(cleanedText);
|
|
280
|
+
log.info('AI successfully extracted OpenAPI spec', { size: cleanedText.length });
|
|
281
|
+
return cleanedText;
|
|
282
|
+
}
|
|
283
|
+
catch (parseError) {
|
|
284
|
+
log.warn('AI generated invalid JSON', { parseError });
|
|
285
|
+
return null;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
catch (error) {
|
|
289
|
+
log.error('AI extraction error', {
|
|
290
|
+
error: error instanceof Error ? error.message : String(error)
|
|
291
|
+
});
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Validates if content looks like a valid OpenAPI specification
|
|
297
|
+
*
|
|
298
|
+
* @param content - Content to validate
|
|
299
|
+
* @returns true if content appears to be OpenAPI spec
|
|
300
|
+
*/
|
|
301
|
+
function isValidOpenAPISpec(content) {
|
|
302
|
+
try {
|
|
303
|
+
// Try to parse as JSON
|
|
304
|
+
const parsed = JSON.parse(content);
|
|
305
|
+
// Check for OpenAPI indicators
|
|
306
|
+
if (parsed.openapi && parsed.openapi.startsWith('3.')) {
|
|
307
|
+
return true;
|
|
308
|
+
}
|
|
309
|
+
if (parsed.swagger && parsed.swagger.startsWith('2.')) {
|
|
310
|
+
return true;
|
|
311
|
+
}
|
|
312
|
+
return false;
|
|
313
|
+
}
|
|
314
|
+
catch {
|
|
315
|
+
// Not JSON, might be YAML
|
|
316
|
+
// Check for OpenAPI/Swagger keywords
|
|
317
|
+
const lowerContent = content.toLowerCase();
|
|
318
|
+
return ((lowerContent.includes('openapi:') && lowerContent.includes('paths:')) ||
|
|
319
|
+
(lowerContent.includes('swagger:') && lowerContent.includes('paths:')));
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
//# sourceMappingURL=openapi-discovery.js.map
|