UNPKG

@git.zone/cli

Version:

A comprehensive CLI tool for enhancing and managing local development workflows with gitzone utilities, focusing on project setup, version control, code formatting, and template management.

433 lines (351 loc) 13.3 kB
import * as plugins from './mod.plugins.js'; import * as helpers from './helpers.js'; import { ServiceManager } from './classes.servicemanager.js'; import { GlobalRegistry } from './classes.globalregistry.js'; import { logger } from '../gitzone.logging.js'; export const run = async (argvArg: any) => { const isGlobal = argvArg.g || argvArg.global; const command = argvArg._[1] || 'help'; // Handle global commands first if (isGlobal) { await handleGlobalCommand(command); return; } // Local project commands const serviceManager = new ServiceManager(); await serviceManager.init(); const service = argvArg._[2] || 'all'; switch (command) { case 'start': await handleStart(serviceManager, service); break; case 'stop': await handleStop(serviceManager, service); break; case 'restart': await handleRestart(serviceManager, service); break; case 'status': await serviceManager.showStatus(); break; case 'config': if (service === 'services' || argvArg._[2] === 'services') { await handleConfigureServices(serviceManager); } else { await serviceManager.showConfig(); } break; case 'compass': await serviceManager.showCompassConnection(); break; case 'logs': const lines = parseInt(argvArg._[3]) || 20; await serviceManager.showLogs(service, lines); break; case 'remove': await handleRemove(serviceManager); break; case 'clean': await handleClean(serviceManager); break; case 'reconfigure': await serviceManager.reconfigure(); break; case 'help': default: showHelp(); break; } }; async function handleStart(serviceManager: ServiceManager, service: string) { helpers.printHeader('Starting Services'); switch (service) { case 'mongo': case 'mongodb': await serviceManager.startMongoDB(); break; case 'minio': case 's3': await serviceManager.startMinIO(); break; case 'elasticsearch': case 'es': await serviceManager.startElasticsearch(); break; case 'all': case '': await serviceManager.startAll(); break; default: logger.log('error', `Unknown service: ${service}`); logger.log('note', 'Use: mongo, s3, elasticsearch, or all'); break; } } async function handleStop(serviceManager: ServiceManager, service: string) { helpers.printHeader('Stopping Services'); switch (service) { case 'mongo': case 'mongodb': await serviceManager.stopMongoDB(); break; case 'minio': case 's3': await serviceManager.stopMinIO(); break; case 'elasticsearch': case 'es': await serviceManager.stopElasticsearch(); break; case 'all': case '': await serviceManager.stopAll(); break; default: logger.log('error', `Unknown service: ${service}`); logger.log('note', 'Use: mongo, s3, elasticsearch, or all'); break; } } async function handleRestart(serviceManager: ServiceManager, service: string) { helpers.printHeader('Restarting Services'); switch (service) { case 'mongo': case 'mongodb': await serviceManager.stopMongoDB(); await plugins.smartdelay.delayFor(2000); await serviceManager.startMongoDB(); break; case 'minio': case 's3': await serviceManager.stopMinIO(); await plugins.smartdelay.delayFor(2000); await serviceManager.startMinIO(); break; case 'elasticsearch': case 'es': await serviceManager.stopElasticsearch(); await plugins.smartdelay.delayFor(2000); await serviceManager.startElasticsearch(); break; case 'all': case '': await serviceManager.stopAll(); await plugins.smartdelay.delayFor(2000); await serviceManager.startAll(); break; default: logger.log('error', `Unknown service: ${service}`); break; } } async function handleRemove(serviceManager: ServiceManager) { helpers.printHeader('Removing Containers'); logger.log('note', '⚠️ This will remove containers but preserve data'); const shouldContinue = await plugins.smartinteract.SmartInteract.getCliConfirmation('Continue?', false); if (shouldContinue) { await serviceManager.removeContainers(); } else { logger.log('note', 'Cancelled'); } } async function handleClean(serviceManager: ServiceManager) { helpers.printHeader('Clean All'); logger.log('error', '⚠️ WARNING: This will remove all containers and data!'); logger.log('error', 'This action cannot be undone!'); const smartinteraction = new plugins.smartinteract.SmartInteract(); const confirmAnswer = await smartinteraction.askQuestion({ name: 'confirm', type: 'input', message: 'Type "yes" to confirm:', default: 'no' }); if (confirmAnswer.value === 'yes') { await serviceManager.removeContainers(); console.log(); await serviceManager.cleanData(); logger.log('ok', 'All cleaned ✓'); } else { logger.log('note', 'Cancelled'); } } async function handleConfigureServices(serviceManager: ServiceManager) { helpers.printHeader('Configure Services'); await serviceManager.configureServices(); } function showHelp() { helpers.printHeader('GitZone Services Manager'); logger.log('ok', 'Usage: gitzone services [command] [options]'); console.log(); logger.log('note', 'Commands:'); logger.log('info', ' start [service] Start services (mongo|s3|elasticsearch|all)'); logger.log('info', ' stop [service] Stop services (mongo|s3|elasticsearch|all)'); logger.log('info', ' restart [service] Restart services (mongo|s3|elasticsearch|all)'); logger.log('info', ' status Show service status'); logger.log('info', ' config Show current configuration'); logger.log('info', ' config services Configure which services are enabled'); logger.log('info', ' compass Show MongoDB Compass connection string'); logger.log('info', ' logs [service] Show logs (mongo|s3|elasticsearch|all) [lines]'); logger.log('info', ' reconfigure Reassign ports and restart services'); logger.log('info', ' remove Remove all containers'); logger.log('info', ' clean Remove all containers and data ⚠️'); logger.log('info', ' help Show this help message'); console.log(); logger.log('note', 'Available Services:'); logger.log('info', ' • MongoDB (mongo) - Document database'); logger.log('info', ' • MinIO (s3) - S3-compatible object storage'); logger.log('info', ' • Elasticsearch (elasticsearch) - Search and analytics engine'); console.log(); logger.log('note', 'Features:'); logger.log('info', ' • Auto-creates .nogit/env.json with smart defaults'); logger.log('info', ' • Random ports (20000-30000) for MongoDB/MinIO to avoid conflicts'); logger.log('info', ' • Elasticsearch uses standard port 9200'); logger.log('info', ' • Project-specific containers for multi-project support'); logger.log('info', ' • Preserves custom configuration values'); logger.log('info', ' • MongoDB Compass connection support'); console.log(); logger.log('note', 'Examples:'); logger.log('info', ' gitzone services start # Start all services'); logger.log('info', ' gitzone services start mongo # Start only MongoDB'); logger.log('info', ' gitzone services start elasticsearch # Start only Elasticsearch'); logger.log('info', ' gitzone services stop # Stop all services'); logger.log('info', ' gitzone services status # Check service status'); logger.log('info', ' gitzone services config # Show configuration'); logger.log('info', ' gitzone services compass # Get MongoDB Compass connection'); logger.log('info', ' gitzone services logs elasticsearch # Show Elasticsearch logs'); console.log(); logger.log('note', 'Global Commands (-g/--global):'); logger.log('info', ' list -g List all registered projects'); logger.log('info', ' status -g Show status across all projects'); logger.log('info', ' stop -g Stop all containers across all projects'); logger.log('info', ' cleanup -g Remove stale registry entries'); console.log(); logger.log('note', 'Global Examples:'); logger.log('info', ' gitzone services list -g # List all registered projects'); logger.log('info', ' gitzone services status -g # Show global container status'); logger.log('info', ' gitzone services stop -g # Stop all (prompts for confirmation)'); } // ==================== Global Command Handlers ==================== async function handleGlobalCommand(command: string) { const globalRegistry = GlobalRegistry.getInstance(); switch (command) { case 'list': await handleGlobalList(globalRegistry); break; case 'status': await handleGlobalStatus(globalRegistry); break; case 'stop': await handleGlobalStop(globalRegistry); break; case 'cleanup': await handleGlobalCleanup(globalRegistry); break; case 'help': default: showHelp(); break; } } async function handleGlobalList(globalRegistry: GlobalRegistry) { helpers.printHeader('Registered Projects (Global)'); const projects = await globalRegistry.getAllProjects(); const projectPaths = Object.keys(projects); if (projectPaths.length === 0) { logger.log('note', 'No projects registered'); return; } for (const path of projectPaths) { const project = projects[path]; const lastActive = new Date(project.lastActive).toLocaleString(); console.log(); logger.log('ok', `📁 ${project.projectName}`); logger.log('info', ` Path: ${project.projectPath}`); logger.log('info', ` Services: ${project.enabledServices.join(', ')}`); logger.log('info', ` Last Active: ${lastActive}`); } } async function handleGlobalStatus(globalRegistry: GlobalRegistry) { helpers.printHeader('Global Service Status'); const statuses = await globalRegistry.getGlobalStatus(); if (statuses.length === 0) { logger.log('note', 'No projects registered'); return; } let runningCount = 0; let totalContainers = 0; for (const project of statuses) { console.log(); logger.log('ok', `📁 ${project.projectName}`); logger.log('info', ` Path: ${project.projectPath}`); if (project.containers.length === 0) { logger.log('note', ' No containers configured'); continue; } for (const container of project.containers) { totalContainers++; const statusIcon = container.status === 'running' ? '🟢' : container.status === 'exited' ? '🟡' : '⚪'; if (container.status === 'running') runningCount++; logger.log('info', ` ${statusIcon} ${container.name}: ${container.status}`); } } console.log(); logger.log('note', `Summary: ${runningCount}/${totalContainers} containers running across ${statuses.length} project(s)`); } async function handleGlobalStop(globalRegistry: GlobalRegistry) { helpers.printHeader('Stop All Containers (Global)'); const statuses = await globalRegistry.getGlobalStatus(); // Count running containers let runningCount = 0; for (const project of statuses) { for (const container of project.containers) { if (container.status === 'running') runningCount++; } } if (runningCount === 0) { logger.log('note', 'No running containers found'); return; } logger.log('note', `Found ${runningCount} running container(s) across ${statuses.length} project(s)`); console.log(); // Show what will be stopped for (const project of statuses) { const runningContainers = project.containers.filter(c => c.status === 'running'); if (runningContainers.length > 0) { logger.log('info', `${project.projectName}:`); for (const container of runningContainers) { logger.log('info', ` • ${container.name}`); } } } console.log(); const shouldContinue = await plugins.smartinteract.SmartInteract.getCliConfirmation( 'Stop all containers?', false ); if (!shouldContinue) { logger.log('note', 'Cancelled'); return; } logger.log('note', 'Stopping all containers...'); const result = await globalRegistry.stopAll(); if (result.stopped.length > 0) { logger.log('ok', `Stopped: ${result.stopped.join(', ')}`); } if (result.failed.length > 0) { logger.log('error', `Failed to stop: ${result.failed.join(', ')}`); } } async function handleGlobalCleanup(globalRegistry: GlobalRegistry) { helpers.printHeader('Cleanup Registry (Global)'); logger.log('note', 'Checking for stale registry entries...'); const removed = await globalRegistry.cleanup(); if (removed.length === 0) { logger.log('ok', 'No stale entries found'); return; } logger.log('ok', `Removed ${removed.length} stale entr${removed.length === 1 ? 'y' : 'ies'}:`); for (const path of removed) { logger.log('info', ` • ${path}`); } }