@syntropysoft/praetorian
Version:
Praetorian CLI – A universal multi-environment configuration validator for DevSecOps teams. Validate, compare, and secure YAML/ENV files with ease.
179 lines • 5.92 kB
JavaScript
;
/**
* Schema Validator - Refactored with SOLID SRP
*
* Single Responsibility: Orchestrate schema validation by delegating to specialized validators
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.SchemaValidator = void 0;
const StructureValidator_1 = require("./StructureValidator");
/**
* Schema Validator - Functional Programming
*
* Single Responsibility: Orchestrate schema validation by delegating to pure functions
* No state, no side effects, pure functions only
*/
class SchemaValidator {
constructor(options = {}) {
// Guard clause: validate options
this.options = {
stopOnFirstError: false,
includeWarnings: true,
validateAdditionalProperties: true,
...options
};
}
/**
* Validate data against a JSON schema
*/
validate(data, schema, context) {
// Guard clause: validate inputs
if (schema === null || schema === undefined) {
return {
valid: false,
errors: [{
path: '',
message: 'Schema is required',
code: 'MISSING_SCHEMA'
}],
warnings: []
};
}
const errors = [];
const warnings = [];
try {
this.validateValue(data, schema, '', errors, warnings, context);
}
catch (error) {
errors.push({
path: '',
message: `Schema validation failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
code: 'SCHEMA_VALIDATION_ERROR'
});
}
return {
valid: errors.length === 0,
errors,
warnings,
data: errors.length === 0 ? data : undefined
};
}
/**
* Validate a value against a schema - Delegates to specialized validators
*/
validateValue(value, schema, path, errors, warnings, context) {
// Guard clause: validate required properties
if (this.isRequiredPropertyMissing(value, schema, path)) {
errors.push({
path,
message: `Required property '${path}' is missing`,
code: 'REQUIRED_PROPERTY_MISSING',
rule: 'required'
});
return;
}
// Guard clause: handle null/undefined values
if (this.shouldSkipValidation(value, schema)) {
return;
}
// Delegate to specialized validators (SRP)
this.delegateToSpecializedValidators(value, schema, path, errors, warnings, context);
}
/**
* Check if required property is missing
*/
isRequiredPropertyMissing(value, schema, path) {
if (!schema.required || !Array.isArray(schema.required)) {
return false;
}
const propertyName = path.split('.').pop() || '';
return schema.required.includes(propertyName) && (value === undefined || value === null);
}
/**
* Check if validation should be skipped
*/
shouldSkipValidation(value, schema) {
// Handle null values
if (value === null) {
if (schema.type !== 'null' && schema.type !== undefined) {
return false; // Will be handled by type validator
}
return true;
}
// Handle undefined values
if (value === undefined) {
return true;
}
return false;
}
/**
* Delegate validation to pure functions (SRP + Functional)
*/
delegateToSpecializedValidators(value, schema, path, errors, warnings, context) {
// Delegate to pure functions - no state, no side effects
const validationErrors = (0, StructureValidator_1.validateValue)(value, schema, path, context);
errors.push(...validationErrors);
// Custom validation rules
this.validateCustomRules(value, schema, path, errors, context);
}
/**
* Validate custom rules - Pure function delegation
*/
validateCustomRules(value, schema, path, errors, context) {
const customErrors = validateCustomRulesPure(value, schema, path, context);
errors.push(...customErrors);
}
}
exports.SchemaValidator = SchemaValidator;
/**
* Pure function to validate custom rules
*/
const validateCustomRulesPure = (value, schema, path, context) => {
// Guard clause: no custom rules
if (!schema.customRules || !context?.options?.customValidators) {
return [];
}
// Guard clause: no rules defined
if (schema.customRules.length === 0) {
return [];
}
return schema.customRules.flatMap(rule => validateCustomRule(value, rule, path, context));
};
/**
* Pure function to validate a single custom rule
*/
const validateCustomRule = (value, rule, path, context) => {
// Guard clause: rule not found
const validator = context?.options?.customValidators?.[rule.name];
if (!validator) {
return [];
}
try {
const result = validator(value, context);
return !result.success
? [createCustomRuleError(path, rule.message, rule.name)]
: [];
}
catch (error) {
return [createCustomValidationError(path, rule.name, error)];
}
};
/**
* Pure function to create custom rule error
*/
const createCustomRuleError = (path, message, ruleName) => ({
path,
message,
code: `CUSTOM_${ruleName.toUpperCase()}`,
rule: ruleName
});
/**
* Pure function to create custom validation error
*/
const createCustomValidationError = (path, ruleName, error) => ({
path,
message: `Custom validation failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
code: 'CUSTOM_VALIDATION_ERROR',
rule: ruleName
});
//# sourceMappingURL=SchemaValidator.js.map