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
JavaScript
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" : ""}`;
}
}
}