UNPKG

prprompts-flutter-generator

Version:

AI-powered Flutter development with full automation + official extension support - Generate 32 security-audited guides & auto-implement in 2-3 hours. NEW v5.1: Official Claude Code plugin with hooks, Gemini TOML commands, Qwen MCP settings. Features: Comp

529 lines (470 loc) 12.4 kB
/** * ValidationResult.js * Represents validation results with severity levels, messages, and suggestions * * Used to track validation issues during React to Flutter conversion */ /** * Validation severity levels * @enum {string} */ const ValidationSeverity = { ERROR: 'error', WARNING: 'warning', INFO: 'info', SUCCESS: 'success', }; /** * Validation categories * @enum {string} */ const ValidationCategory = { SYNTAX: 'syntax', TYPE: 'type', STRUCTURE: 'structure', NAMING: 'naming', PERFORMANCE: 'performance', SECURITY: 'security', ACCESSIBILITY: 'accessibility', BEST_PRACTICE: 'best_practice', }; /** * Represents a single validation issue */ class ValidationIssue { /** * @param {Object} options * @param {string} options.severity - Severity level * @param {string} options.message - Issue message * @param {string} [options.category] - Issue category * @param {string} [options.code] - Error/warning code * @param {string} [options.file] - File path * @param {number} [options.line] - Line number * @param {number} [options.column] - Column number * @param {string} [options.snippet] - Code snippet * @param {string[]} [options.suggestions=[]] - Suggested fixes * @param {string} [options.documentationUrl] - Link to documentation */ constructor({ severity, message, category = null, code = null, file = null, line = null, column = null, snippet = null, suggestions = [], documentationUrl = null, }) { this._validate({ severity, message }); this.severity = severity; this.message = message; this.category = category; this.code = code; this.file = file; this.line = line; this.column = column; this.snippet = snippet; this.suggestions = suggestions; this.documentationUrl = documentationUrl; this.timestamp = new Date().toISOString(); } _validate({ severity, message }) { if (!severity || !Object.values(ValidationSeverity).includes(severity)) { throw new Error(`ValidationIssue: severity must be one of ${Object.values(ValidationSeverity).join(', ')}`); } if (!message || typeof message !== 'string') { throw new Error('ValidationIssue: message is required and must be a string'); } } /** * Get location string (file:line:column) * @returns {string|null} */ getLocation() { if (!this.file) return null; let location = this.file; if (this.line !== null) { location += `:${this.line}`; if (this.column !== null) { location += `:${this.column}`; } } return location; } /** * Check if issue is an error * @returns {boolean} */ isError() { return this.severity === ValidationSeverity.ERROR; } /** * Check if issue is a warning * @returns {boolean} */ isWarning() { return this.severity === ValidationSeverity.WARNING; } /** * Check if issue is informational * @returns {boolean} */ isInfo() { return this.severity === ValidationSeverity.INFO; } /** * Format issue as string * @param {boolean} [includeSnippet=false] - Include code snippet * @returns {string} */ toString(includeSnippet = false) { let str = `[${this.severity.toUpperCase()}]`; if (this.code) { str += ` ${this.code}`; } if (this.category) { str += ` [${this.category}]`; } const location = this.getLocation(); if (location) { str += ` ${location}`; } str += `: ${this.message}`; if (this.suggestions.length > 0) { str += '\n Suggestions:'; this.suggestions.forEach(suggestion => { str += `\n - ${suggestion}`; }); } if (includeSnippet && this.snippet) { str += `\n Code:\n${this.snippet.split('\n').map(l => ` ${l}`).join('\n')}`; } if (this.documentationUrl) { str += `\n Docs: ${this.documentationUrl}`; } return str; } /** * Convert to JSON * @returns {Object} */ toJSON() { return { severity: this.severity, message: this.message, category: this.category, code: this.code, file: this.file, line: this.line, column: this.column, snippet: this.snippet, suggestions: this.suggestions, documentationUrl: this.documentationUrl, timestamp: this.timestamp, }; } /** * Create from JSON * @param {Object} json * @returns {ValidationIssue} */ static fromJSON(json) { const issue = new ValidationIssue(json); issue.timestamp = json.timestamp; return issue; } } /** * Represents the complete validation result */ class ValidationResult { /** * @param {Object} options * @param {boolean} [options.valid=true] - Whether validation passed * @param {string} [options.target] - Validation target (file, component, etc.) * @param {ValidationIssue[]} [options.issues=[]] - Validation issues * @param {Object} [options.metadata={}] - Additional metadata */ constructor({ valid = true, target = null, issues = [], metadata = {}, } = {}) { this.valid = valid; this.target = target; this.issues = issues.map(i => i instanceof ValidationIssue ? i : new ValidationIssue(i)); this.metadata = metadata; this.timestamp = new Date().toISOString(); } /** * Add a validation issue * @param {ValidationIssue|Object} issue */ addIssue(issue) { const validationIssue = issue instanceof ValidationIssue ? issue : new ValidationIssue(issue); this.issues.push(validationIssue); // Update valid flag if error is added if (validationIssue.isError()) { this.valid = false; } } /** * Add an error * @param {string} message * @param {Object} options - Additional issue options */ addError(message, options = {}) { this.addIssue({ severity: ValidationSeverity.ERROR, message, ...options, }); } /** * Add a warning * @param {string} message * @param {Object} options - Additional issue options */ addWarning(message, options = {}) { this.addIssue({ severity: ValidationSeverity.WARNING, message, ...options, }); } /** * Add an info message * @param {string} message * @param {Object} options - Additional issue options */ addInfo(message, options = {}) { this.addIssue({ severity: ValidationSeverity.INFO, message, ...options, }); } /** * Add a success message * @param {string} message * @param {Object} options - Additional issue options */ addSuccess(message, options = {}) { this.addIssue({ severity: ValidationSeverity.SUCCESS, message, ...options, }); } /** * Get all errors * @returns {ValidationIssue[]} */ getErrors() { return this.issues.filter(i => i.isError()); } /** * Get all warnings * @returns {ValidationIssue[]} */ getWarnings() { return this.issues.filter(i => i.isWarning()); } /** * Get all info messages * @returns {ValidationIssue[]} */ getInfos() { return this.issues.filter(i => i.isInfo()); } /** * Get issues by category * @param {string} category * @returns {ValidationIssue[]} */ getIssuesByCategory(category) { return this.issues.filter(i => i.category === category); } /** * Get issues by severity * @param {string} severity * @returns {ValidationIssue[]} */ getIssuesBySeverity(severity) { return this.issues.filter(i => i.severity === severity); } /** * Check if result has errors * @returns {boolean} */ hasErrors() { return this.getErrors().length > 0; } /** * Check if result has warnings * @returns {boolean} */ hasWarnings() { return this.getWarnings().length > 0; } /** * Check if result has any issues * @returns {boolean} */ hasIssues() { return this.issues.length > 0; } /** * Get issue count by severity * @returns {Object} */ getIssueCounts() { return { errors: this.getErrors().length, warnings: this.getWarnings().length, infos: this.getInfos().length, total: this.issues.length, }; } /** * Get validation score (0-100) * @returns {number} */ getScore() { const counts = this.getIssueCounts(); if (counts.total === 0) return 100; // Calculate score: errors = -10, warnings = -5, infos = -1 const deductions = (counts.errors * 10) + (counts.warnings * 5) + (counts.infos * 1); const score = Math.max(0, 100 - deductions); return Math.round(score); } /** * Get validation grade (A-F) * @returns {string} */ getGrade() { const score = this.getScore(); if (score >= 90) return 'A'; if (score >= 80) return 'B'; if (score >= 70) return 'C'; if (score >= 60) return 'D'; return 'F'; } /** * Format result as string * @param {boolean} [verbose=false] - Include all issue details * @returns {string} */ toString(verbose = false) { const counts = this.getIssueCounts(); const score = this.getScore(); const grade = this.getGrade(); let str = `Validation Result`; if (this.target) { str += ` for ${this.target}`; } str += `:\n`; str += ` Status: ${this.valid ? 'PASS' : 'FAIL'}\n`; str += ` Score: ${score}/100 (Grade: ${grade})\n`; str += ` Errors: ${counts.errors}\n`; str += ` Warnings: ${counts.warnings}\n`; str += ` Info: ${counts.infos}\n`; if (verbose && this.issues.length > 0) { str += `\nIssues:\n`; this.issues.forEach(issue => { str += issue.toString(true) + '\n\n'; }); } return str; } /** * Format result as summary * @returns {string} */ getSummary() { return this.toString(false); } /** * Format result as detailed report * @returns {string} */ getDetailedReport() { return this.toString(true); } /** * Convert to JSON * @returns {Object} */ toJSON() { return { valid: this.valid, target: this.target, issues: this.issues.map(i => i.toJSON()), metadata: this.metadata, timestamp: this.timestamp, score: this.getScore(), grade: this.getGrade(), counts: this.getIssueCounts(), }; } /** * Create from JSON * @param {Object} json * @returns {ValidationResult} */ static fromJSON(json) { const result = new ValidationResult({ valid: json.valid, target: json.target, issues: json.issues || [], metadata: json.metadata || {}, }); result.timestamp = json.timestamp; return result; } /** * Merge multiple validation results * @param {ValidationResult[]} results * @returns {ValidationResult} */ static merge(results) { const merged = new ValidationResult({ valid: results.every(r => r.valid), target: 'merged', }); results.forEach(result => { result.issues.forEach(issue => merged.addIssue(issue)); }); return merged; } /** * Create a passing result * @param {string} target * @returns {ValidationResult} */ static createPass(target = null) { const result = new ValidationResult({ valid: true, target }); result.addSuccess('Validation passed'); return result; } /** * Create a failing result * @param {string} target * @param {string} message * @returns {ValidationResult} */ static createFail(target = null, message = 'Validation failed') { const result = new ValidationResult({ valid: false, target }); result.addError(message); return result; } } module.exports = { ValidationResult, ValidationIssue, ValidationSeverity, ValidationCategory, };