UNPKG

appwrite-utils-cli

Version:

Appwrite Utility Functions to help with database management, data conversion, data import, migrations, and much more. Meant to be used as a CLI tool, I do not recommend installing this in frontend environments.

311 lines (310 loc) 11.9 kB
import { validateCollectionsTablesConfig, reportValidationResults } from "../configValidation.js"; import { MessageFormatter } from "../../shared/messageFormatter.js"; import { logger } from "../../shared/logging.js"; /** * Service for validating Appwrite configuration with support for multiple validation modes * * This service provides centralized configuration validation with: * - Standard validation (warnings allowed) * - Strict validation (warnings treated as errors) * - Detailed error reporting with suggestions * - Configurable output verbosity * * @example * ```typescript * const validationService = new ConfigValidationService(); * * // Standard validation * const result = validationService.validate(config); * if (!result.isValid) { * validationService.reportResults(result, { verbose: true }); * } * * // Strict validation (warnings become errors) * const strictResult = validationService.validateStrict(config); * if (!strictResult.isValid) { * throw new Error("Configuration validation failed in strict mode"); * } * ``` */ export class ConfigValidationService { /** * Validate configuration with standard rules * * Standard validation allows warnings - the configuration is considered valid * even if warnings are present. Only errors cause validation to fail. * * Validation checks include: * - Basic structure validation (required fields, array structure) * - Naming conflict detection (collections vs tables) * - Database reference validation * - Schema consistency validation * - Duplicate definition detection * * @param config - Appwrite configuration to validate * @returns Validation result with errors, warnings, and suggestions * * @example * ```typescript * const result = validationService.validate(config); * * if (result.isValid) { * console.log("Configuration is valid"); * if (result.warnings.length > 0) { * console.log(`Found ${result.warnings.length} warnings`); * } * } else { * console.error(`Configuration has ${result.errors.length} errors`); * } * ``` */ validate(config) { logger.debug("Starting configuration validation (standard mode)"); try { const baseResult = validateCollectionsTablesConfig(config); const result = { isValid: baseResult.isValid, errors: baseResult.errors, warnings: baseResult.warnings, suggestions: baseResult.suggestions }; logger.debug("Configuration validation complete", { isValid: result.isValid, errorCount: result.errors.length, warningCount: result.warnings.length, suggestionCount: result.suggestions?.length || 0 }); return result; } catch (error) { logger.error("Configuration validation failed with exception", { error: error instanceof Error ? error.message : String(error) }); return { isValid: false, errors: [ { type: "schema_inconsistency", message: "Configuration validation failed", details: error instanceof Error ? error.message : String(error), suggestion: "Check configuration file for syntax errors or invalid structure", severity: "error" } ], warnings: [] }; } } /** * Validate configuration with strict rules * * Strict validation treats all warnings as errors. This is useful for: * - CI/CD pipelines (fail builds on any issues) * - Production deployments (ensure highest quality) * - Configuration audits (enforce best practices) * * All warnings are promoted to errors, so the configuration is only * considered valid if there are zero warnings and zero errors. * * @param config - Appwrite configuration to validate * @returns Validation result with promoted warnings as errors * * @example * ```typescript * const result = validationService.validateStrict(config); * * if (!result.isValid) { * console.error("Configuration failed strict validation"); * result.errors.forEach(err => { * console.error(` - ${err.message}`); * }); * process.exit(1); * } * ``` */ validateStrict(config) { logger.debug("Starting configuration validation (strict mode)"); try { const baseResult = validateCollectionsTablesConfig(config); // In strict mode, promote all warnings to errors const promotedWarnings = baseResult.warnings.map(warning => ({ ...warning, severity: "error" })); const allErrors = [...baseResult.errors, ...promotedWarnings]; const result = { isValid: allErrors.length === 0, errors: allErrors, warnings: [], // No warnings in strict mode - all promoted to errors suggestions: baseResult.suggestions }; logger.debug("Configuration validation complete (strict mode)", { isValid: result.isValid, errorCount: result.errors.length, promotedWarnings: promotedWarnings.length, suggestionCount: result.suggestions?.length || 0 }); return result; } catch (error) { logger.error("Configuration validation failed with exception (strict mode)", { error: error instanceof Error ? error.message : String(error) }); return { isValid: false, errors: [ { type: "schema_inconsistency", message: "Configuration validation failed in strict mode", details: error instanceof Error ? error.message : String(error), suggestion: "Check configuration file for syntax errors or invalid structure", severity: "error" } ], warnings: [] }; } } /** * Report validation results to console with formatted output * * Provides user-friendly formatting of validation results: * - Color-coded output (errors in red, warnings in yellow, etc.) * - Detailed error descriptions with suggestions * - Affected items listing * - Optional verbose mode for additional details * * @param validation - Validation result to report * @param options - Reporting options (verbose, silent, exitOnError) * * @example * ```typescript * const result = validationService.validate(config); * * // Basic reporting * validationService.reportResults(result); * * // Verbose reporting with all details * validationService.reportResults(result, { verbose: true }); * * // Report and exit on error (useful for scripts) * validationService.reportResults(result, { exitOnError: true }); * ``` */ reportResults(validation, options = {}) { const { verbose = false, silent = false, exitOnError = false } = options; if (silent) { // Only log to file, don't print to console logger.info("Configuration validation results", { isValid: validation.isValid, errorCount: validation.errors.length, warningCount: validation.warnings.length, suggestionCount: validation.suggestions?.length || 0 }); if (validation.errors.length > 0) { validation.errors.forEach(error => { logger.error("Validation error", { type: error.type, message: error.message, details: error.details, suggestion: error.suggestion, affectedItems: error.affectedItems }); }); } return; } // Use existing reportValidationResults for formatted console output reportValidationResults({ isValid: validation.isValid, errors: validation.errors, warnings: validation.warnings, suggestions: validation.suggestions || [] }, { verbose }); // Exit on error if requested if (exitOnError && !validation.isValid) { logger.error("Exiting due to validation errors"); process.exit(1); } } /** * Validate and report in a single call * * Convenience method that combines validation and reporting. * Useful for quick validation checks in CLI commands. * * @param config - Appwrite configuration to validate * @param strict - Use strict validation mode * @param reportOptions - Reporting options * @returns Validation result * * @example * ```typescript * // Quick validation with reporting * const result = validationService.validateAndReport(config, false, { * verbose: true, * exitOnError: true * }); * ``` */ validateAndReport(config, strict = false, reportOptions = {}) { const result = strict ? this.validateStrict(config) : this.validate(config); this.reportResults(result, reportOptions); return result; } /** * Check if configuration is valid without detailed reporting * * Quick validation check that returns a simple boolean. * Useful for conditional logic where you don't need detailed error information. * * @param config - Appwrite configuration to validate * @param strict - Use strict validation mode * @returns true if configuration is valid, false otherwise * * @example * ```typescript * if (validationService.isValid(config)) { * // Proceed with configuration * } else { * // Show error and prompt for correction * } * ``` */ isValid(config, strict = false) { const result = strict ? this.validateStrict(config) : this.validate(config); return result.isValid; } /** * Get a summary of validation results as a formatted string * * Returns a human-readable summary of validation results suitable for * logging or display in UIs. * * @param validation - Validation result to summarize * @returns Formatted summary string * * @example * ```typescript * const result = validationService.validate(config); * const summary = validationService.getSummary(result); * console.log(summary); * // Output: "Configuration valid with 2 warnings, 1 suggestion" * ``` */ getSummary(validation) { if (validation.isValid) { const parts = ["Configuration valid"]; if (validation.warnings.length > 0) { parts.push(`${validation.warnings.length} warning${validation.warnings.length > 1 ? "s" : ""}`); } if (validation.suggestions && validation.suggestions.length > 0) { parts.push(`${validation.suggestions.length} suggestion${validation.suggestions.length > 1 ? "s" : ""}`); } return parts.join(" with "); } else { return `Configuration invalid: ${validation.errors.length} error${validation.errors.length > 1 ? "s" : ""}`; } } }