UNPKG

dragon-ui-claude

Version:

🐲 Ultra-fast, cross-platform Claude Code Max usage dashboard with dragon-inspired design, advanced background services, and multi-currency support

215 lines (185 loc) 6.92 kB
#!/usr/bin/env node import { spawn } from 'child_process'; import path from 'path'; import fs from 'fs'; import { fileURLToPath } from 'url'; // Get the package root directory (ES module equivalent of __dirname) const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const packageRoot = path.dirname(__dirname); // Check for CLI mode if (process.argv.includes('--cli')) { console.log('🐲 Starting Dragon UI CLI...'); // Import and start CLI mode import(path.join(packageRoot, 'cli', 'index.cjs')) .then(() => { // CLI module handles everything }) .catch(error => { console.error('❌ Failed to start CLI mode:', error.message); process.exit(1); }); } else { console.log('🐲 Starting Dragon UI - Claude Code Max Usage Dashboard...'); // Check if better-sqlite3 needs rebuilding const needsRebuild = checkIfRebuildNeeded(); if (needsRebuild) { console.log('🔧 Rebuilding native modules for Electron...'); rebuildNativeModules(() => { checkAndStart(); }); } else { checkAndStart(); } } function checkIfRebuildNeeded() { try { // Check if better-sqlite3 exists const sqlitePath = path.join(packageRoot, 'node_modules', 'better-sqlite3'); if (!fs.existsSync(sqlitePath)) { console.log('📦 better-sqlite3 not found, no rebuild needed'); return false; // Module not installed } console.log('🔍 Checking if native modules need rebuilding...'); // Check for rebuild cache file (use OS temp directory if package root is not writable) let cacheFile = path.join(packageRoot, '.dragon-ui-rebuild-cache'); let cacheDir = packageRoot; // Check if we can write to package root (might be restricted in global installs) try { fs.accessSync(packageRoot, fs.constants.W_OK); } catch (error) { // Use OS temp directory if package root is not writable const os = require('os'); cacheDir = os.tmpdir(); cacheFile = path.join(cacheDir, '.dragon-ui-rebuild-cache'); } const electronPackageJson = path.join(packageRoot, 'node_modules', 'electron', 'package.json'); if (fs.existsSync(cacheFile) && fs.existsSync(electronPackageJson)) { try { const cacheData = JSON.parse(fs.readFileSync(cacheFile, 'utf8')); const electronPkg = JSON.parse(fs.readFileSync(electronPackageJson, 'utf8')); // Check if electron version matches cached version if (cacheData.electronVersion === electronPkg.version) { // Check if better-sqlite3 binary exists const bindingPath = path.join(sqlitePath, 'build', 'Release', 'better_sqlite3.node'); if (fs.existsSync(bindingPath)) { console.log('✅ Native modules are up to date'); return false; } else { console.log('🔧 Binary missing, rebuild needed'); } } else { console.log('🔄 Electron version changed, rebuild needed'); } } catch (error) { console.log('⚠️ Cache file corrupted, will rebuild'); } } // Rebuild needed console.log('🔧 Native modules need rebuilding'); return true; } catch (error) { console.log('⚠️ Error checking rebuild status:', error.message); return true; // Rebuild on any error } } function rebuildNativeModules(callback) { const rebuildProcess = spawn('npx', ['electron-rebuild', '-f'], { cwd: packageRoot, stdio: 'inherit', shell: true }); rebuildProcess.on('close', (code) => { if (code === 0) { console.log('✅ Native modules rebuilt successfully!'); // Create cache file to avoid unnecessary rebuilds try { const electronPackageJson = path.join(packageRoot, 'node_modules', 'electron', 'package.json'); if (fs.existsSync(electronPackageJson)) { const electronPkg = JSON.parse(fs.readFileSync(electronPackageJson, 'utf8')); const cacheData = { timestamp: new Date().toISOString(), electronVersion: electronPkg.version }; // Use the same cache file logic as in checkIfRebuildNeeded let cacheFile = path.join(packageRoot, '.dragon-ui-rebuild-cache'); try { fs.accessSync(packageRoot, fs.constants.W_OK); } catch (error) { const os = require('os'); cacheFile = path.join(os.tmpdir(), '.dragon-ui-rebuild-cache'); } fs.writeFileSync(cacheFile, JSON.stringify(cacheData, null, 2)); console.log('💾 Rebuild cache updated'); } } catch (error) { console.log('⚠️ Could not create rebuild cache:', error.message); } callback(); } else { console.error('❌ Failed to rebuild native modules!'); console.log('💡 Try running: npm install --global electron-rebuild'); process.exit(1); } }); rebuildProcess.on('error', (err) => { console.error('❌ Rebuild failed:', err.message); console.log('💡 Installing electron-rebuild...'); // Try to install electron-rebuild const installProcess = spawn('npm', ['install', '-g', 'electron-rebuild'], { cwd: packageRoot, stdio: 'inherit', shell: true }); installProcess.on('close', (installCode) => { if (installCode === 0) { rebuildNativeModules(callback); } else { console.error('❌ Failed to install electron-rebuild'); process.exit(1); } }); }); } function checkAndStart() { const distPath = path.join(packageRoot, 'dist'); if (!fs.existsSync(distPath)) { console.log('📦 Building Dragon UI for first time...'); // Run build first const buildProcess = spawn('npm', ['run', 'build'], { cwd: packageRoot, stdio: 'inherit', shell: true }); buildProcess.on('close', (code) => { if (code === 0) { console.log('✅ Build completed successfully!'); startElectron(); } else { console.error('❌ Build failed!'); process.exit(1); } }); } else { startElectron(); } function startElectron() { console.log('🚀 Launching Dragon UI...'); // Find the local electron executable const electronPath = path.join(packageRoot, 'node_modules', '.bin', 'electron'); const electronCmd = process.platform === 'win32' ? `${electronPath}.cmd` : electronPath; // Start Electron app const electronProcess = spawn(electronCmd, ['.'], { cwd: packageRoot, stdio: 'inherit', shell: true }); electronProcess.on('close', (code) => { console.log(`🐲 Dragon UI closed with code ${code}`); }); electronProcess.on('error', (err) => { console.error('❌ Failed to start Dragon UI:', err.message); console.log('💡 Electron path:', electronCmd); }); } }