feat(sync): add sync subsystem: SyncManager, OpsServer sync handlers, Sync UI and state, provider groupFilter support, and realtime sync log streaming via TypedSocket

This commit is contained in:
2026-02-28 16:33:53 +00:00
parent 2f050744bc
commit f7e16aa350
30 changed files with 2983 additions and 21 deletions

View File

@@ -2,15 +2,60 @@
* Logging utilities for GitOps
*/
import type { ISyncLogEntry } from '../ts_interfaces/data/sync.ts';
type LogLevel = 'info' | 'success' | 'warn' | 'error' | 'debug';
const SYNC_LOG_MAX = 500;
class Logger {
private debugMode = false;
private syncLogBuffer: ISyncLogEntry[] = [];
private broadcastFn?: (entry: ISyncLogEntry) => void;
constructor() {
this.debugMode = Deno.args.includes('--debug') || Deno.env.get('DEBUG') === 'true';
}
/**
* Set the broadcast function used to push sync log entries to connected clients.
*/
setBroadcastFn(fn: (entry: ISyncLogEntry) => void): void {
this.broadcastFn = fn;
}
/**
* Log a sync-related message to both the console and the ring buffer.
* Also broadcasts to connected frontends via TypedSocket if available.
*/
syncLog(level: ISyncLogEntry['level'], message: string, source?: string): void {
// Also log to console
this.log(level, message);
const entry: ISyncLogEntry = {
timestamp: Date.now(),
level,
message,
source,
};
this.syncLogBuffer.push(entry);
if (this.syncLogBuffer.length > SYNC_LOG_MAX) {
this.syncLogBuffer.splice(0, this.syncLogBuffer.length - SYNC_LOG_MAX);
}
if (this.broadcastFn) {
this.broadcastFn(entry);
}
}
/**
* Get recent sync log entries.
*/
getSyncLogs(limit = 100): ISyncLogEntry[] {
return this.syncLogBuffer.slice(-limit);
}
log(level: LogLevel, message: string, ...args: unknown[]): void {
const prefix = this.getPrefix(level);
const formattedMessage = `${prefix} ${message}`;