UNPKG

gather-ts

Version:

A powerful code analysis and packaging tool designed for creating AI-friendly code representations for javascript and typescript projects.

235 lines 9.21 kB
"use strict"; // src/utils/validation/Validator.ts Object.defineProperty(exports, "__esModule", { value: true }); exports.Validator = void 0; const errors_1 = require("@/errors"); const services_1 = require("@/types/services"); class Validator extends services_1.BaseService { constructor(deps, options = {}) { super(); this.deps = deps; this.debug = options.debug || false; } async initialize() { await super.initialize(); this.logDebug("Validator service initialized"); } cleanup() { this.logDebug("Validator service cleanup"); super.cleanup(); } logDebug(message) { if (this.debug) { this.deps.logger.debug(message); } } handleValidationError(fieldName, message, details) { const error = new errors_1.ValidationError(message, details); this.deps.logger.error(`Validation error for ${fieldName}: ${message}`); throw error; } validate(value, fieldName, options = {}) { this.checkInitialized(); this.logDebug(`Validating ${fieldName}`); const result = { isValid: true, errors: [], warnings: [], }; try { // Handle optional fields if (value === undefined || value === null) { if (!options.optional) { result.errors.push(`${fieldName} is required`); result.isValid = false; } return result; } // Type validation if (options.type && typeof value !== options.type) { result.errors.push(`${fieldName} must be of type ${options.type}, got ${typeof value}`); result.isValid = false; return result; } // Type-specific validations if (typeof value === "string") { this.validateString(value, fieldName, options, result); } if (typeof value === "number") { this.validateNumber(value, fieldName, options, result); } if (Array.isArray(value)) { this.validateArray(value, fieldName, options, result); } if (this.isObject(value)) { this.validateObject(value, fieldName, options, result); } // Custom validation if (options.customValidator) { this.runCustomValidator(value, fieldName, options.customValidator, result); } } catch (error) { result.errors.push(error instanceof Error ? error.message : String(error)); result.isValid = false; this.deps.logger.error(`Validation error for ${fieldName}: ${error instanceof Error ? error.message : String(error)}`); } this.logDebug(`Validation result for ${fieldName}: ${result.isValid ? "valid" : "invalid"}`); return result; } validateString(value, fieldName, options, result) { if (!options.allowEmpty && value.trim() === "") { result.errors.push(`${fieldName} cannot be empty`); result.isValid = false; return; } if (options.minLength !== undefined && value.length < options.minLength) { result.errors.push(`${fieldName} must be at least ${options.minLength} characters long`); result.isValid = false; } if (options.maxLength !== undefined && value.length > options.maxLength) { result.errors.push(`${fieldName} cannot exceed ${options.maxLength} characters`); result.isValid = false; } if (options.pattern && !options.pattern.test(value)) { result.errors.push(`${fieldName} has an invalid format`); result.isValid = false; } } validateNumber(value, fieldName, options, result) { if (options.min !== undefined && value < options.min) { result.errors.push(`${fieldName} must be at least ${options.min}`); result.isValid = false; } if (options.max !== undefined && value > options.max) { result.errors.push(`${fieldName} cannot exceed ${options.max}`); result.isValid = false; } if (options.integer && !Number.isInteger(value)) { result.errors.push(`${fieldName} must be an integer`); result.isValid = false; } } validateArray(value, fieldName, options, result) { if (options.minLength !== undefined && value.length < options.minLength) { result.errors.push(`${fieldName} must contain at least ${options.minLength} items`); result.isValid = false; } if (options.maxLength !== undefined && value.length > options.maxLength) { result.errors.push(`${fieldName} cannot contain more than ${options.maxLength} items`); result.isValid = false; } if (options.arrayType) { const invalidItems = value.filter((item) => typeof item !== options.arrayType); if (invalidItems.length > 0) { result.errors.push(`All items in ${fieldName} must be of type ${options.arrayType}`); result.isValid = false; } } } validateObject(value, fieldName, options, result) { if (options.requiredFields) { const missingFields = options.requiredFields.filter((field) => !(field in value)); if (missingFields.length > 0) { result.errors.push(`${fieldName} is missing required fields: ${missingFields.join(", ")}`); result.isValid = false; } } } validatePath(path, context) { if (!path || typeof path !== "string") { throw new errors_1.ValidationError(`Invalid ${context} path`, { path }); } // Check for invalid characters in path const invalidChars = /[<>:"|?*]/g; if (invalidChars.test(path)) { throw new errors_1.ValidationError(`${context} path contains invalid characters`, { path, invalidChars: '<>:"|?*', }); } // Check for relative path navigation if (path.includes("../") || path.includes("..\\")) { throw new errors_1.ValidationError(`${context} path cannot contain relative navigation`, { path }); } // Log debug info this.logDebug(`Validated path for ${context}: ${path}`); } runCustomValidator(value, fieldName, validator, result) { try { const customResult = validator(value); if (!customResult) { result.errors.push(`${fieldName} failed custom validation`); result.isValid = false; } } catch (error) { result.errors.push(`Custom validation error for ${fieldName}: ${error instanceof Error ? error.message : String(error)}`); result.isValid = false; } } // Type Guard Implementations isString(value) { return typeof value === "string"; } isNumber(value) { return typeof value === "number" && !isNaN(value); } isBoolean(value) { return typeof value === "boolean"; } isObject(value) { return typeof value === "object" && value !== null && !Array.isArray(value); } isArray(value) { return Array.isArray(value); } isDate(value) { return value instanceof Date && !isNaN(value.getTime()); } // Helper Methods validateNotEmpty(value, fieldName) { const result = this.validate(value, fieldName, { optional: false }); if (!result.isValid) { this.handleValidationError(fieldName, result.errors[0]); } return value; } validateType(value, expectedType, fieldName) { const result = this.validate(value, fieldName, { type: expectedType }); if (!result.isValid) { this.handleValidationError(fieldName, result.errors[0]); } } validateRange(value, min, max, fieldName) { const result = this.validate(value, fieldName, { type: "number", min, max, }); if (!result.isValid) { this.handleValidationError(fieldName, result.errors[0]); } } validateEnum(value, enumValues, fieldName) { const result = this.validate(value, fieldName, { type: "string", customValidator: (val) => enumValues.includes(val), }); if (!result.isValid) { this.handleValidationError(fieldName, `${fieldName} must be one of: ${enumValues.join(", ")}`, { value, allowedValues: enumValues }); } return value; } validatePattern(value, pattern, fieldName) { const result = this.validate(value, fieldName, { type: "string", pattern, }); if (!result.isValid) { this.handleValidationError(fieldName, result.errors[0]); } } } exports.Validator = Validator; //# sourceMappingURL=Validator.js.map