import * as plugins from '../plugins.ts'; import { logger } from '../logging.ts'; import { ConnectionManager } from './connectionmanager.ts'; import { ActionLog } from './actionlog.ts'; import { SyncManager } from './syncmanager.ts'; import { ManagedSecretsManager } from './managedsecrets.manager.ts'; import { OpsServer } from '../opsserver/index.ts'; import { StorageManager } from '../storage/index.ts'; import { CacheDb, CacheCleaner, CachedProject, CachedSecret, SecretsScanService } from '../cache/index.ts'; import { resolvePaths } from '../paths.ts'; /** * Main GitOps application orchestrator */ export class GitopsApp { public storageManager: StorageManager; public smartSecret: plugins.smartsecret.SmartSecret; public connectionManager: ConnectionManager; public actionLog: ActionLog; public opsServer: OpsServer; public cacheDb: CacheDb; public cacheCleaner: CacheCleaner; public syncManager!: SyncManager; public managedSecretsManager!: ManagedSecretsManager; public secretsScanService!: SecretsScanService; private scanIntervalId: number | null = null; private paths: ReturnType; constructor() { const paths = resolvePaths(); this.paths = paths; this.storageManager = new StorageManager({ backend: 'filesystem', fsPath: paths.defaultStoragePath, }); this.smartSecret = new plugins.smartsecret.SmartSecret({ service: 'gitops' }); this.connectionManager = new ConnectionManager(this.storageManager, this.smartSecret); this.actionLog = new ActionLog(this.storageManager); this.cacheDb = CacheDb.getInstance({ storagePath: paths.defaultTsmDbPath, dbName: 'gitops_cache', }); this.cacheCleaner = new CacheCleaner(this.cacheDb); this.cacheCleaner.registerClass(CachedProject); this.cacheCleaner.registerClass(CachedSecret); this.opsServer = new OpsServer(this); } async start(port = 3000): Promise { logger.info('Initializing GitOps...'); // Start CacheDb await this.cacheDb.start(); // Initialize connection manager (loads saved connections) await this.connectionManager.init(); // Initialize managed secrets manager this.managedSecretsManager = new ManagedSecretsManager( this.storageManager, this.smartSecret, this.connectionManager, ); await this.managedSecretsManager.init(); // Initialize sync manager this.syncManager = new SyncManager( this.storageManager, this.connectionManager, this.actionLog, ); await this.syncManager.init(); // Initialize secrets scan service with 24h auto-scan this.secretsScanService = new SecretsScanService(this.connectionManager); const SCAN_INTERVAL_MS = 24 * 60 * 60 * 1000; // 24 hours this.scanIntervalId = setInterval(() => { this.secretsScanService.fullScan().catch((err) => { logger.error(`Scheduled secrets scan failed: ${err}`); }); }, SCAN_INTERVAL_MS); Deno.unrefTimer(this.scanIntervalId); // Fire-and-forget initial scan (doesn't block startup) this.secretsScanService.fullScan().catch((err) => { logger.error(`Initial secrets scan failed: ${err}`); }); // Start CacheCleaner this.cacheCleaner.start(); // Start OpsServer await this.opsServer.start(port); logger.success('GitOps initialized successfully'); } async stop(): Promise { logger.info('Shutting down GitOps...'); if (this.scanIntervalId !== null) { clearInterval(this.scanIntervalId); this.scanIntervalId = null; } await this.syncManager.stop(); await this.opsServer.stop(); this.cacheCleaner.stop(); await this.cacheDb.stop(); logger.success('GitOps shutdown complete'); } }