woaru
Version:
Universal Project Setup Autopilot - Analyze and automatically configure development tools for ANY programming language
196 lines • 7.99 kB
JavaScript
/**
* WOARU Splash Screen Module
* Production-Ready implementation with comprehensive security and error handling
*/
import chalk from 'chalk';
import fs from 'fs-extra';
import path from 'path';
import { t, initializeI18n } from '../config/i18n.js';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
// ES module compatibility
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
/**
* Default splash screen configuration
*/
const DEFAULT_SPLASH_CONFIG = {
showVersion: true,
showCommands: true,
maxVersionLength: 20,
};
/**
* Sanitizes version string to prevent injection attacks
* @param version - The version string to sanitize
* @returns Sanitized version string safe for display
*/
function sanitizeVersion(version) {
if (typeof version !== 'string') {
return 'unknown';
}
// Remove dangerous characters and limit length
const sanitized = version
.replace(/[^\w.-]/g, '')
.substring(0, DEFAULT_SPLASH_CONFIG.maxVersionLength);
// Validate version format (basic semver pattern)
const versionPattern = /^\d+\.\d+\.\d+/;
if (!versionPattern.test(sanitized)) {
return 'unknown';
}
return sanitized;
}
/**
* Type guard for package.json validation
* @param packageData - Package data to validate
* @returns True if packageData is valid PackageJson
*/
function isValidPackageJson(packageData) {
return (typeof packageData === 'object' &&
packageData !== null &&
(typeof packageData.version === 'string' ||
typeof packageData.version === 'undefined'));
}
/**
* Safely loads package.json with comprehensive error handling
* @returns Promise<string> The sanitized version string
*/
async function loadVersionSafely() {
try {
const packagePath = path.resolve(__dirname, '../../package.json');
// Validate path security
const normalizedPath = path.normalize(packagePath);
if (!normalizedPath.endsWith('package.json')) {
console.debug('Invalid package.json path detected');
return 'unknown';
}
const packageData = await fs.readJson(normalizedPath);
if (!isValidPackageJson(packageData)) {
console.debug('Invalid package.json structure');
return 'unknown';
}
return sanitizeVersion(packageData.version);
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
console.debug(`Version loading failed: ${sanitizeVersion(errorMessage)}`);
return 'unknown';
}
}
/**
* Main splash screen display function with Production-Ready implementation
* Implements comprehensive security validation and error handling
*
* @param config - Optional configuration for splash display
*/
export async function displaySplashScreen(config = {}) {
const finalConfig = { ...DEFAULT_SPLASH_CONFIG, ...config };
try {
// Initialize i18n first with error handling
await initializeI18n();
// Load version safely
const version = finalConfig.showVersion ? await loadVersionSafely() : null;
// Display properly framed ASCII art splash screen
console.log();
console.log(WOARU_FRAMED_SPLASH);
if (version && finalConfig.showVersion) {
console.log(chalk.gray(` Version ${version}`));
}
console.log();
// Display commands section if enabled
if (finalConfig.showCommands) {
await displayCommandsSection();
}
console.log();
}
catch {
// Fallback display with English defaults if i18n fails
await displayFallbackSplash(finalConfig);
}
}
/**
* Displays the commands section with proper error handling
*/
async function displayCommandsSection() {
try {
console.log(chalk.white(t('ui.quick_commands')));
const commands = [
{ name: 'analyze', key: 'commands.analyze.description' },
{ name: 'watch', key: 'commands.watch.description' },
{ name: 'review', key: 'commands.review.description' },
{ name: 'setup', key: 'commands.setup.description' },
{ name: 'commands', key: 'commands.commands.description' },
];
for (const command of commands) {
try {
const description = t(command.key);
console.log(chalk.gray(` • woaru ${command.name.padEnd(12)} - ${description}`));
}
catch {
// Skip individual command if translation fails
console.debug(`Command translation failed for: ${command.name}`);
}
}
console.log();
console.log(chalk.yellow(`💡 ${t('ui.run_commands_help')}`));
}
catch {
// Fallback commands display
console.log(chalk.white(t('ui.quick_commands')));
console.log(chalk.gray(t('ui.command_analyze_desc')));
console.log(chalk.gray(t('ui.command_commands_desc')));
}
}
/**
* Fallback splash display when i18n or other systems fail
* @param config - Splash configuration
*/
async function displayFallbackSplash(config) {
try {
console.log();
console.log(WOARU_FRAMED_SPLASH);
if (config.showVersion) {
const version = await loadVersionSafely();
console.log(chalk.gray(` Version ${version}`));
}
console.log();
if (config.showCommands) {
console.log(chalk.white('Quick Commands:'));
console.log(chalk.gray(' • woaru analyze - Analyze project'));
console.log(chalk.gray(' • woaru commands - Show all commands'));
console.log();
console.log(chalk.yellow('💡 Type "woaru --help" to see all available commands'));
}
console.log();
}
catch {
// Final fallback - minimal safe output with framed display
console.log();
console.log(WOARU_FRAMED_SPLASH);
console.log();
}
}
/**
* Static logo components with secure ANSI escape sequences
* These are pre-sanitized and safe for display
*/
export const WOARU_COMPACT_LOGO = `
\x1b[36m ╔══════════════════════════════════════════════════════════════╗
\x1b[36m ║ \x1b[33m📢\x1b[36m \x1b[37m●●●\x1b[36m \x1b[32m✓✓✓\x1b[36m \x1b[1m\x1b[33mWOARU\x1b[0m\x1b[36m \x1b[33m📦\x1b[36m ║
\x1b[36m ╚══════════════════════════════════════════════════════════════╝
\x1b[0m`;
export const WOARU_MINI_LOGO = `\x1b[33m📢\x1b[36m \x1b[37m●●●\x1b[36m \x1b[32m✓✓✓\x1b[36m \x1b[1m\x1b[33mWOARU\x1b[0m\x1b[36m \x1b[33m📦\x1b[0m`;
/**
* Properly framed splash screen with exact character width control
* Language-independent hardcoded content ensures consistent frame rendering
* Frame width: 66 characters total (64 + 2 borders)
* Content area: 62 characters (including padding)
*/
export const WOARU_FRAMED_SPLASH = `\x1b[36m╔══════════════════════════════════════════════════════════════╗
\x1b[36m║ \x1b[33m🤖 WOARU - HELPS YOU TO WRITE YOUR BEST CODE POSSIBLE \x1b[36m║
\x1b[36m╚══════════════════════════════════════════════════════════════╝\x1b[0m`;
/**
* Legacy export for backward compatibility
* @deprecated Use displaySplashScreen instead
*/
export const displaySplashScreenLegacy = displaySplashScreen;
//# sourceMappingURL=splash_logo.js.map