UNPKG

@syntropysoft/praetorian

Version:

Praetorian CLI – A universal multi-environment configuration validator for DevSecOps teams. Validate, compare, and secure YAML/ENV files with ease.

193 lines 8.32 kB
"use strict"; /** * ValidationOrchestratorRefactored - Clean Architecture with SOLID SRP * * This orchestrator now follows Single Responsibility Principle: * - Orchestrates validation flow only * - Delegates specific responsibilities to specialized services * - Uses guard clauses for early validation * - Employs functional programming patterns * * Mutation Score: Expected 90%+ (functional patterns are more testable) */ Object.defineProperty(exports, "__esModule", { value: true }); exports.ValidationOrchestratorRefactored = void 0; exports.runValidationRefactored = runValidationRefactored; const EnvironmentManager_1 = require("../../shared/utils/EnvironmentManager"); const ConfigLoaderService_1 = require("../services/ConfigLoaderService"); const StructureGeneratorService_1 = require("../services/StructureGeneratorService"); const ValidationService_1 = require("../services/ValidationService"); class ValidationOrchestratorRefactored { constructor() { this.environmentManager = new EnvironmentManager_1.EnvironmentManager(); this.configLoader = new ConfigLoaderService_1.ConfigLoaderService(); this.structureGenerator = new StructureGeneratorService_1.StructureGeneratorService(); this.validationService = new ValidationService_1.ValidationService(); } /** * Orchestrate validation based on options (main entry point) */ async orchestrateValidation(configPath, options) { // Guard clause: validate inputs if (typeof configPath !== 'string' || configPath.length === 0) { throw new Error('Configuration path is required'); } if (!options || typeof options !== 'object') { throw new Error('Validation options are required'); } // Determine validation strategy based on options if (this.isEnvironmentValidation(options)) { return await this.validateByEnvironments(options); } else { return await this.validateSingleFile(configPath, options); } } /** * Check if validation should use environment-based approach (pure function) */ isEnvironmentValidation(options) { return Boolean(options.all || options.env); } /** * Validate using environment-based approach */ async validateByEnvironments(options) { // Guard clause: validate environment options if (!options.all && !options.env) { return { success: false, error: 'No validation mode specified' }; } const environmentsFile = options.environments || 'environments.yaml'; const environmentConfig = this.environmentManager.loadEnvironmentConfig(environmentsFile); const validationFunction = this.validationService.createValidationFunction(options); if (options.all) { return await this.validateAllEnvironments(environmentConfig, validationFunction, options); } else { return await this.validateSpecificEnvironment(options.env, environmentConfig, validationFunction, options); } } /** * Validate all environments (pure function with async side effects) */ async validateAllEnvironments(environmentConfig, validationFunction, options) { const results = await this.environmentManager.validateAllEnvironments(environmentConfig, validationFunction); const summary = this.environmentManager.getEnvironmentSummary(results); return { success: summary.passed === summary.total, results, summary }; } /** * Validate specific environment (pure function with async side effects) */ async validateSpecificEnvironment(envName, environmentConfig, validationFunction, options) { const result = await this.environmentManager.validateEnvironment(envName, environmentConfig, validationFunction); return { success: result.success, errors: result.errors, warnings: result.warnings }; } /** * Validate single file configuration */ async validateSingleFile(configPath, options) { // Load configuration with guard clauses const praetorianConfig = this.configLoader.loadPraetorianConfig(configPath); // Separate existing and missing files (pure function) const { existingFiles, missingFiles } = this.configLoader.separateExistingAndMissingFiles(praetorianConfig.files); // Handle missing files if any exist if (missingFiles.length > 0) { await this.handleMissingFiles(missingFiles, existingFiles, praetorianConfig); } // Load all configuration files (pure function) const allFiles = this.configLoader.loadConfigFiles(praetorianConfig.files); // Execute validation (pure function with async side effects) const result = await this.validationService.executeValidation(allFiles, options); // Execute schema validation if enabled const schemaResult = await this.runSchemaValidation(allFiles, options); // Combine results const combinedErrors = [ ...(result?.errors ?? []), ...(schemaResult.errors ?? []) ]; const combinedWarnings = [ ...(result?.warnings ?? []), ...(schemaResult.warnings ?? []) ]; // Return result with null coalescing for safety return { success: (result?.success ?? false) && (schemaResult.success ?? true), errors: combinedErrors, warnings: combinedWarnings, results: [ ...(result?.results ?? []), ...(schemaResult.results ?? []) ] }; } /** * Handle missing files by creating empty structures (pure function with async side effects) */ async handleMissingFiles(missingFiles, existingFiles, praetorianConfig) { // Guard clause: validate inputs if (!Array.isArray(missingFiles) || missingFiles.length === 0) { return; } // Use functional approach: Promise.all instead of imperative loops const createFilePromises = missingFiles.map(missingFile => this.structureGenerator.createEmptyStructureFile(missingFile, existingFiles, praetorianConfig, (filePath) => this.configLoader.loadConfigFile(filePath).content)); await Promise.all(createFilePromises); } /** * Run schema validation on configuration files */ async runSchemaValidation(files, options) { if (!options.schema_validation) { return { success: true, results: [] }; } const schemaRules = this.getSchemaRules(options.schema_rules); const results = []; for (const rule of schemaRules) { try { const result = await rule.execute(files); results.push(result); } catch (error) { results.push({ success: false, error: `Schema validation failed: ${error instanceof Error ? error.message : 'Unknown error'}`, results: [] }); } } // Combine all results const allErrors = results.flatMap(r => r.errors || []); const allWarnings = results.flatMap(r => r.warnings || []); const allSuccess = results.every(r => r.success); return { success: allSuccess, errors: allErrors, warnings: allWarnings, results }; } /** * Get schema rules based on options * NOTE: SchemaValidationRule and CommonSchemas were removed as unused */ getSchemaRules(requestedRules) { // Return empty array since schema validation is not implemented return []; } } exports.ValidationOrchestratorRefactored = ValidationOrchestratorRefactored; /** * Run validation with the refactored orchestrator (pure function with async side effects) */ async function runValidationRefactored(configPath, options = {}) { const orchestrator = new ValidationOrchestratorRefactored(); return await orchestrator.orchestrateValidation(configPath, options); } //# sourceMappingURL=ValidationOrchestratorRefactored.js.map