userface
Version:
Universal Data-Driven UI Engine with live data, validation, and multi-platform support
142 lines (141 loc) • 5.46 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.validationEngine = exports.ValidationEngine = exports.ValidationWarning = void 0;
const errors_1 = require("./errors");
const logger_1 = require("./logger");
class ValidationWarning extends Error {
constructor(message, field, value, rule) {
super(message);
Object.defineProperty(this, "field", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "value", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "rule", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
this.name = 'ValidationWarning';
this.field = field;
this.value = value;
this.rule = rule;
}
}
exports.ValidationWarning = ValidationWarning;
class ValidationEngine {
validateUserFace(spec, schema) {
logger_1.logger.debug(`Validating UserFace: ${spec.component} with schema: ${schema.name}`);
const errors = [];
const warnings = [];
// Валидация пропов
const propsValidation = this.validateProps(spec, schema);
errors.push(...propsValidation.errors);
warnings.push(...propsValidation.warnings);
// Валидация событий
const eventsValidation = this.validateEvents(spec, schema);
errors.push(...eventsValidation.errors);
warnings.push(...eventsValidation.warnings);
return {
isValid: errors.length === 0,
errors,
warnings
};
}
validateProps(spec, schema) {
const errors = [];
const warnings = [];
for (const propDef of schema.props) {
const value = spec[propDef.name];
if (propDef.required && (value === undefined || value === null)) {
errors.push(new errors_1.ValidationError(`Required prop '${propDef.name}' is missing`, propDef.name, value));
continue;
}
if (value !== undefined && value !== null) {
const validation = this.validatePropValue(value, propDef);
if (!validation.isValid) {
errors.push(new errors_1.ValidationError(validation.message, propDef.name, value));
}
}
}
return { isValid: errors.length === 0, errors, warnings };
}
validateEvents(spec, schema) {
const errors = [];
const warnings = [];
if (spec.events) {
for (const eventName in spec.events) {
const eventDef = schema.events.find(e => e.name === eventName);
if (!eventDef) {
warnings.push(new ValidationWarning(`Unknown event '${eventName}'`, eventName, spec.events[eventName], { field: eventName, type: 'custom' }));
}
}
}
return { isValid: errors.length === 0, errors, warnings };
}
validatePropValue(value, propDef) {
// Валидация типа
if (!this.validateType(value, propDef.type)) {
return {
isValid: false,
message: `Expected type '${propDef.type}', got '${typeof value}'`
};
}
// Валидация по правилам
if (propDef.validation && Array.isArray(propDef.validation)) {
for (const rule of propDef.validation) {
if (!this.validateRule(value, rule)) {
return {
isValid: false,
message: rule.message || `Validation failed for '${propDef.name}'`
};
}
}
}
return { isValid: true, message: '' };
}
validateType(value, expectedType) {
switch (expectedType) {
case 'text':
return typeof value === 'string';
case 'number':
return typeof value === 'number' && !isNaN(value);
case 'boolean':
return typeof value === 'boolean';
case 'function':
return typeof value === 'function';
case 'object':
return typeof value === 'object' && value !== null;
case 'array':
return Array.isArray(value);
default:
return true; // Неизвестный тип - пропускаем
}
}
validateRule(value, rule) {
switch (rule.type) {
case 'required':
return value !== undefined && value !== null && value !== '';
case 'min':
return typeof value === 'number' && value >= (rule.value || 0);
case 'max':
return typeof value === 'number' && value <= (rule.value || Infinity);
case 'pattern':
return typeof value === 'string' && new RegExp(rule.value || '').test(value);
case 'custom':
return rule.validator ? rule.validator(value) : true;
default:
return true;
}
}
}
exports.ValidationEngine = ValidationEngine;
exports.validationEngine = new ValidationEngine();