UNPKG

netget

Version:

Rette Adepto/ Recibido Directamente.

230 lines (221 loc) 10.3 kB
// NetGetX_DeployMenu.cli.ts import inquirer from 'inquirer'; import chalk from 'chalk'; import { NetGetSync } from './lib/netgetSync.ts'; import fs from 'fs/promises'; import NetGetMainMenu from '../netget_MainMenu.cli.ts'; import { loadOrCreateXConfig } from '../NetGetX/config/xConfig.ts'; const xConfig = await loadOrCreateXConfig(); const sqliteDatabasePath: string = xConfig.sqliteDatabasePath; interface DeployConfig { localDbPath: string; remoteServer: string; remoteApiKey: string; projectsBasePath: string; timestamp?: number; } // Helper to load config async function loadConfig(configPath: string): Promise<DeployConfig | null> { try { const configFile = await fs.readFile(configPath || './deploy.config.json', 'utf8'); return JSON.parse(configFile); } catch (error: any) { console.error(chalk.red(`Failed to load config: ${error.message}`)); return null; } } // Helper to create NetGetSync instance async function createSyncInstance(configPath: string): Promise<NetGetSync | null> { const config = await loadConfig(configPath); if (!config) return null; return new NetGetSync({ localDbPath: config.localDbPath, remoteServer: config.remoteServer, remoteApiKey: config.remoteApiKey, projectsBasePath: config.projectsBasePath }); } export default async function netGetXDeployMenu(): Promise<void> { console.clear(); // ASCII art for "DEPLOY" (styled like NetGet art) console.log(` ██████ ╗██████╗ ███████╗██╗ ██████╗ ██╗ ██╗ ██ ██║██╔═══╝ ██╔══██║██║ ██║ ██║██║ ██║ ██ ██║█████╗ ██████╔╝██║ ██║ ██║╚████╔╝ ██ ██║██╔══╝ ██╔═══╝ ██║ ██║ ██║ ╚██╔╝ ██████╔╝███████╗██║ ╚██████ ╚██████╔╝ ██║ ╚═════╝ ╚══════╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ `); let exit = false; while (!exit) { const { option } = await inquirer.prompt({ type: 'list', name: 'option', message: 'NetGet Deploy Menu:', choices: [ '1. Initialize deployment config', '2. Compare local and remote', '3. Check remote server status', '4. Validate deployment config', '5. Sync local config to remote', '0. Back' ] }); switch (option) { case '1. Initialize deployment config': { const { output } = await inquirer.prompt({ type: 'input', name: 'output', message: 'Output config file:', default: './deploy.config.json' }); const config: DeployConfig = { localDbPath: sqliteDatabasePath, remoteServer: 'https://your-remote-server.com', remoteApiKey: 'your-api-key-here', projectsBasePath: '/var/www', timestamp: Date.now() }; if (await fs.readFile(output).then(() => true).catch(() => false)) { console.log(chalk.red(`File already exists: ${output}`)); break; } try { await fs.writeFile(output, JSON.stringify(config, null, 2)); console.log(chalk.green(`Configuration file created: ${output}`)); console.log(chalk.yellow('\nPlease edit the configuration file with your settings:')); console.log(` - remoteServer: Your remote NetGet server URL`); console.log(` - remoteApiKey: Your API key for authentication`); console.log(` - localDbPath: Path to your local NetGet database`); console.log(` - projectsBasePath: Base path for your projects`); } catch (error: any) { console.log(chalk.red(`Failed to create config: ${error.message}`)); } break; } case '2. Compare local and remote': { const { config } = await inquirer.prompt({ type: 'input', name: 'config', message: 'Config file path:', default: './deploy.config.json' }); const sync = await createSyncInstance(config); if (!sync) break; try { await sync.compare(); } catch (error: any) { console.log(chalk.red(`Compare failed: ${error.message}`)); } break; } case '3. Check remote server status': { const { config } = await inquirer.prompt({ type: 'input', name: 'config', message: 'Config file path:', default: './deploy.config.json' }); console.log(chalk.blue(`Reading configuration from: ${config}`)); const sync = await createSyncInstance(config); if (!sync) break; try { const health = await sync.checkRemoteHealth(); console.log(chalk.green('Remote Server Status:')); console.log(` Status: ${health.status}`); console.log(` Database: ${health.database}`); console.log(` Openresty: ${health.openresty}`); console.log(` Timestamp: ${health.timestamp}`); } catch (error: any) { console.log(chalk.red(`Check remote server status failed: ${error.message}`)); } break; } case '4. Validate deployment config': { const { config } = await inquirer.prompt({ type: 'input', name: 'config', message: 'Config file path:', default: './deploy.config.json' }); const loadedConfig = await loadConfig(config); if (!loadedConfig) break; console.log(chalk.blue('Validating configuration...\n')); const required: (keyof DeployConfig)[] = ['remoteServer', 'remoteApiKey', 'localDbPath']; const missing = required.filter(field => !loadedConfig[field]); if (missing.length > 0) { console.log(chalk.red(`Missing required fields: ${missing.join(', ')}`)); break; } try { await fs.access(loadedConfig.localDbPath); console.log(chalk.green('Local database accessible')); console.log(chalk.gray(`Path: ${loadedConfig.localDbPath}`)); } catch { console.log(chalk.red(`Local database not accessible: ${loadedConfig.localDbPath}`)); console.log(chalk.gray(`Path: ${loadedConfig.localDbPath}`)); break; } try { const sync = await createSyncInstance(config); if (sync) { await sync.checkRemoteHealth(); console.log(chalk.green('Remote server accessible')); console.log(chalk.gray(`URL: ${loadedConfig.remoteServer}`)); } } catch (error: any) { console.log(chalk.red(`Remote server not accessible: ${error.message}`)); console.log(chalk.gray(`URL: ${loadedConfig.remoteServer}`)); break; } console.log(chalk.green('\nConfiguration is valid!')); break; } case '5. Sync local config to remote': { const { config, includeProjects, domains } = await inquirer.prompt([ { type: 'input', name: 'config', message: 'Config file path:', default: './deploy.config.json' }, { type: 'confirm', name: 'includeProjects', message: 'Include project files in sync?', default: false }, { type: 'input', name: 'domains', message: 'Domains to sync (comma-separated, blank for all):', default: '' } ]); const sync = await createSyncInstance(config); if (!sync) break; try { const syncOptions = { includeProjects, domains: domains ? domains.split(',').map((d: string) => d.trim()) : null }; const result = await sync.sync(syncOptions); if (result.success) { console.log(chalk.green(`\nSync completed: ${result.syncedDomains} domains processed`)); } else { console.log(chalk.red(`\nSync failed: ${result.error}`)); } } catch (error: any) { console.log(chalk.red(`Sync failed: ${error.message}`)); } break; } case '0. Back': exit = true; await NetGetMainMenu(); break; default: break; } } }