UNPKG

polyv-live-cli

Version:

CLI tool for managing PolyV live streaming services.

421 lines 19.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ConfigValidator = void 0; class ConfigValidator { static validateMonitoringConfig(config) { const result = { valid: true, errors: [], warnings: [], critical: [] }; if (!config.version || typeof config.version !== 'string') { result.errors.push('Configuration version is required and must be a string'); } else if (!this.isValidVersion(config.version)) { result.warnings.push(`Configuration version '${config.version}' format is not standard (expected x.y.z)`); } if (!config.theme || typeof config.theme !== 'string') { result.errors.push('Theme is required and must be a string'); } if (!config.layout || typeof config.layout !== 'string') { result.errors.push('Layout is required and must be a string'); } if (typeof config.refreshInterval !== 'number') { result.errors.push('Refresh interval must be a number'); } else if (config.refreshInterval < 1000) { result.errors.push('Refresh interval must be at least 1000ms'); } else if (config.refreshInterval < 2000) { result.warnings.push('Refresh interval below 2000ms may impact performance'); } if (!Array.isArray(config.components)) { result.critical.push('Components must be an array'); } else { config.components.forEach((component, index) => { const componentResult = this.validateComponentConfig(component, index); result.errors.push(...componentResult.errors); result.warnings.push(...componentResult.warnings); result.critical.push(...componentResult.critical); }); if (config.components.length === 0) { result.warnings.push('No components configured - interface will be empty'); } else if (config.components.length > 10) { result.warnings.push('More than 10 components may impact performance'); } } if (config.customThemes && !Array.isArray(config.customThemes)) { result.errors.push('Custom themes must be an array'); } else if (config.customThemes) { config.customThemes.forEach((theme, index) => { const themeResult = this.validateThemeConfig(theme, `customThemes[${index}]`); result.errors.push(...themeResult.errors); result.warnings.push(...themeResult.warnings); result.critical.push(...themeResult.critical); }); } if (config.customLayouts && !Array.isArray(config.customLayouts)) { result.errors.push('Custom layouts must be an array'); } else if (config.customLayouts) { config.customLayouts.forEach((layout, index) => { const layoutResult = this.validateLayoutConfig(layout, `customLayouts[${index}]`); result.errors.push(...layoutResult.errors); result.warnings.push(...layoutResult.warnings); result.critical.push(...layoutResult.critical); }); } if (!config.preferences) { result.errors.push('User preferences are required'); } else { const preferencesResult = this.validateUserPreferences(config.preferences); result.errors.push(...preferencesResult.errors); result.warnings.push(...preferencesResult.warnings); result.critical.push(...preferencesResult.critical); } result.valid = result.errors.length === 0 && result.critical.length === 0; return result; } static validateComponentConfig(component, index) { const result = { valid: true, errors: [], warnings: [], critical: [] }; const prefix = index !== undefined ? `Component[${index}]` : 'Component'; if (!component.type || typeof component.type !== 'string') { result.errors.push(`${prefix}: type is required and must be a string`); } else if (!this.VALID_COMPONENT_TYPES.includes(component.type)) { result.warnings.push(`${prefix}: type '${component.type}' is not a recognized component type`); } if (!component.position || typeof component.position !== 'object') { result.errors.push(`${prefix}: position is required and must be an object`); } else { const { x, y, width, height } = component.position; if (typeof x !== 'number' || x < 0) { result.errors.push(`${prefix}: position.x must be a non-negative number`); } if (typeof y !== 'number' || y < 0) { result.errors.push(`${prefix}: position.y must be a non-negative number`); } if (typeof width !== 'number' || width <= 0) { result.errors.push(`${prefix}: position.width must be a positive number`); } if (typeof height !== 'number' || height <= 0) { result.errors.push(`${prefix}: position.height must be a positive number`); } } if (!component.size || typeof component.size !== 'object') { result.errors.push(`${prefix}: size is required and must be an object`); } else { const { minWidth, minHeight, maxWidth, maxHeight } = component.size; if (typeof minWidth !== 'number' || minWidth <= 0) { result.errors.push(`${prefix}: size.minWidth must be a positive number`); } if (typeof minHeight !== 'number' || minHeight <= 0) { result.errors.push(`${prefix}: size.minHeight must be a positive number`); } if (maxWidth !== undefined && (typeof maxWidth !== 'number' || maxWidth < minWidth)) { result.errors.push(`${prefix}: size.maxWidth must be a number >= minWidth`); } if (maxHeight !== undefined && (typeof maxHeight !== 'number' || maxHeight < minHeight)) { result.errors.push(`${prefix}: size.maxHeight must be a number >= minHeight`); } } if (typeof component.visible !== 'boolean') { result.errors.push(`${prefix}: visible must be a boolean`); } if (typeof component.priority !== 'number') { result.errors.push(`${prefix}: priority must be a number`); } else if (component.priority < 1 || component.priority > 10) { result.errors.push(`${prefix}: priority must be between 1 and 10`); } if (!component.config || typeof component.config !== 'object') { result.errors.push(`${prefix}: config is required and must be an object`); } result.valid = result.errors.length === 0 && result.critical.length === 0; return result; } static validateComponentLayout(component, index) { const result = { valid: true, errors: [], warnings: [], critical: [] }; const prefix = index !== undefined ? `components[${index}]` : 'component'; if (!component.type || typeof component.type !== 'string') { result.errors.push(`${prefix}: type is required and must be a string`); } if (!component.position || typeof component.position !== 'object') { result.errors.push(`${prefix}: position is required and must be an object`); } else { const { x, y } = component.position; if (typeof x !== 'number' || x < 0) { result.errors.push(`${prefix}: position.x must be a non-negative number`); } if (typeof y !== 'number' || y < 0) { result.errors.push(`${prefix}: position.y must be a non-negative number`); } } if (!component.size || typeof component.size !== 'object') { result.errors.push(`${prefix}: size is required and must be an object`); } else { const { minWidth, minHeight } = component.size; if (typeof minWidth !== 'number' || minWidth <= 0) { result.errors.push(`${prefix}: size.minWidth must be a positive number`); } if (typeof minHeight !== 'number' || minHeight <= 0) { result.errors.push(`${prefix}: size.minHeight must be a positive number`); } } if (!component.config || typeof component.config !== 'object') { result.errors.push(`${prefix}: config is required and must be an object`); } result.valid = result.errors.length === 0 && result.critical.length === 0; return result; } static validateThemeConfig(theme, context = 'Theme') { const result = { valid: true, errors: [], warnings: [], critical: [] }; if (!theme.id || typeof theme.id !== 'string') { result.errors.push(`${context}: id is required and must be a string`); } else if (!/^[a-zA-Z0-9_-]+$/.test(theme.id)) { result.errors.push(`${context}: id must contain only alphanumeric characters, underscore, and dash`); } if (!theme.name || typeof theme.name !== 'string') { result.errors.push(`${context}: name is required and must be a string`); } if (typeof theme.isBuiltIn !== 'boolean') { result.errors.push(`${context}: isBuiltIn must be a boolean`); } if (!theme.colors || typeof theme.colors !== 'object') { result.critical.push(`${context}: colors is required and must be an object`); } else { for (const colorName of this.REQUIRED_THEME_COLORS) { if (!theme.colors[colorName]) { result.errors.push(`${context}: colors.${colorName} is required`); } else if (!this.isValidColor(theme.colors[colorName])) { result.warnings.push(`${context}: colors.${colorName} does not appear to be a valid color`); } } } if (!theme.fonts || typeof theme.fonts !== 'object') { result.errors.push(`${context}: fonts is required and must be an object`); } else { if (!theme.fonts.family || typeof theme.fonts.family !== 'string') { result.errors.push(`${context}: fonts.family is required and must be a string`); } if (typeof theme.fonts.size !== 'number' || theme.fonts.size <= 0) { result.errors.push(`${context}: fonts.size must be a positive number`); } if (!['normal', 'bold'].includes(theme.fonts.weight)) { result.errors.push(`${context}: fonts.weight must be 'normal' or 'bold'`); } if (!['normal', 'italic'].includes(theme.fonts.style)) { result.errors.push(`${context}: fonts.style must be 'normal' or 'italic'`); } } if (!theme.borders || typeof theme.borders !== 'object') { result.errors.push(`${context}: borders is required and must be an object`); } else { if (!['line', 'bg', 'none'].includes(theme.borders.type)) { result.errors.push(`${context}: borders.type must be 'line', 'bg', or 'none'`); } if (!['solid', 'dashed', 'dotted'].includes(theme.borders.style)) { result.errors.push(`${context}: borders.style must be 'solid', 'dashed', or 'dotted'`); } } if (!theme.components || typeof theme.components !== 'object') { result.errors.push(`${context}: components is required and must be an object`); } else { for (const styleName of this.REQUIRED_COMPONENT_STYLES) { if (!theme.components[styleName]) { result.errors.push(`${context}: components.${styleName} is required`); } } } result.valid = result.errors.length === 0 && result.critical.length === 0; return result; } static validateLayoutConfig(layout, context = 'Layout') { const result = { valid: true, errors: [], warnings: [], critical: [] }; if (!layout.id || typeof layout.id !== 'string') { result.errors.push(`${context}: id is required and must be a string`); } else if (!/^[a-zA-Z0-9_-]+$/.test(layout.id)) { result.errors.push(`${context}: id must contain only alphanumeric characters, underscore, and dash`); } if (!layout.name || typeof layout.name !== 'string') { result.errors.push(`${context}: name is required and must be a string`); } if (typeof layout.isBuiltIn !== 'boolean') { result.errors.push(`${context}: isBuiltIn must be a boolean`); } if (typeof layout.responsive !== 'boolean') { result.errors.push(`${context}: responsive must be a boolean`); } if (!layout.grid || typeof layout.grid !== 'object') { result.errors.push(`${context}: grid is required and must be an object`); } else { const { rows, cols, cellWidth, cellHeight, padding } = layout.grid; if (typeof rows !== 'number' || rows <= 0) { result.errors.push(`${context}: grid.rows must be a positive number`); } if (typeof cols !== 'number' || cols <= 0) { result.errors.push(`${context}: grid.cols must be a positive number`); } if (typeof cellWidth !== 'number' || cellWidth <= 0) { result.errors.push(`${context}: grid.cellWidth must be a positive number`); } if (typeof cellHeight !== 'number' || cellHeight <= 0) { result.errors.push(`${context}: grid.cellHeight must be a positive number`); } if (typeof padding !== 'number' || padding < 0) { result.errors.push(`${context}: grid.padding must be a non-negative number`); } } if (!Array.isArray(layout.components)) { result.errors.push(`${context}: components must be an array`); } else { layout.components.forEach((component, index) => { const componentResult = this.validateComponentLayout(component, index); result.errors.push(...componentResult.errors.map(e => `${context}.${e}`)); result.warnings.push(...componentResult.warnings.map(w => `${context}.${w}`)); result.critical.push(...componentResult.critical.map(c => `${context}.${c}`)); }); } if (!layout.minTerminalSize || typeof layout.minTerminalSize !== 'object') { result.errors.push(`${context}: minTerminalSize is required and must be an object`); } else { if (typeof layout.minTerminalSize.width !== 'number' || layout.minTerminalSize.width < 60) { result.errors.push(`${context}: minTerminalSize.width must be at least 60`); } if (typeof layout.minTerminalSize.height !== 'number' || layout.minTerminalSize.height < 20) { result.errors.push(`${context}: minTerminalSize.height must be at least 20`); } } result.valid = result.errors.length === 0 && result.critical.length === 0; return result; } static validateUserPreferences(preferences) { const result = { valid: true, errors: [], warnings: [], critical: [] }; const booleanFields = [ 'autoSave', 'confirmActions', 'showHelp', 'keyboardShortcuts', 'soundEnabled', 'compactMode', 'showTimestamps' ]; for (const field of booleanFields) { if (typeof preferences[field] !== 'boolean') { result.errors.push(`preferences.${field} must be a boolean`); } } if (!['slow', 'normal', 'fast'].includes(preferences.animationSpeed)) { result.errors.push('preferences.animationSpeed must be "slow", "normal", or "fast"'); } if (typeof preferences.maxHistoryItems !== 'number' || preferences.maxHistoryItems < 10) { result.errors.push('preferences.maxHistoryItems must be a number >= 10'); } else if (preferences.maxHistoryItems > 10000) { result.warnings.push('preferences.maxHistoryItems > 10000 may impact memory usage'); } result.valid = result.errors.length === 0 && result.critical.length === 0; return result; } static isValidVersion(version) { const versionRegex = /^\d+\.\d+\.\d+(-[a-zA-Z0-9-.]+)?(\+[a-zA-Z0-9-.]+)?$/; return versionRegex.test(version); } static isValidColor(color) { if (/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(color)) { return true; } const namedColors = [ 'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'gray', 'grey', 'transparent', 'inherit', 'initial', 'unset' ]; if (namedColors.includes(color.toLowerCase())) { return true; } const rgbMatch = color.match(/^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/); if (rgbMatch && rgbMatch[1] && rgbMatch[2] && rgbMatch[3]) { const r = parseInt(rgbMatch[1]); const g = parseInt(rgbMatch[2]); const b = parseInt(rgbMatch[3]); return r <= 255 && g <= 255 && b <= 255; } const rgbaMatch = color.match(/^rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([01]?(?:\.\d+)?)\s*\)$/); if (rgbaMatch && rgbaMatch[1] && rgbaMatch[2] && rgbaMatch[3] && rgbaMatch[4] !== undefined) { const r = parseInt(rgbaMatch[1]); const g = parseInt(rgbaMatch[2]); const b = parseInt(rgbaMatch[3]); const a = parseFloat(rgbaMatch[4]); return r <= 255 && g <= 255 && b <= 255 && a >= 0 && a <= 1; } return false; } static createErrorMessage(result) { const messages = []; if (result.critical.length > 0) { messages.push('Critical errors:'); messages.push(...result.critical.map(e => ` • ${e}`)); } if (result.errors.length > 0) { messages.push('Errors:'); messages.push(...result.errors.map(e => ` • ${e}`)); } if (result.warnings.length > 0) { messages.push('Warnings:'); messages.push(...result.warnings.map(w => ` • ${w}`)); } return messages.join('\n'); } } exports.ConfigValidator = ConfigValidator; ConfigValidator.REQUIRED_THEME_COLORS = [ 'primary', 'secondary', 'background', 'foreground', 'accent', 'error', 'warning', 'success', 'info', 'muted', 'highlight', 'border', 'selection' ]; ConfigValidator.REQUIRED_COMPONENT_STYLES = [ 'header', 'content', 'status', 'border', 'scrollbar', 'selection' ]; ConfigValidator.VALID_COMPONENT_TYPES = [ 'stream-metrics', 'channel-status', 'system-resources', 'alert-panel', 'help-panel', 'status-bar', 'search-panel' ]; //# sourceMappingURL=config-validator.js.map