Skip to main content
Glama
watcher.ts2.93 kB
/** * @fileOverview: File system watcher with debounced synchronization to cloud service * @module: ConnectorWatcher * @keyFunctions: * - start(): Initialize file system watching with ignore pattern filtering * - stop(): Clean up watcher and cancel pending operations * - onChange(): Handle file change events with debouncing * - flush(): Execute debounced synchronization to cloud service * @dependencies: * - fs: File system watching and change detection * - path: Path manipulation and resolution * - projectIdentifier: Ignore pattern loading and file filtering * - fileSyncClient: Cloud service synchronization * - logger: Logging utilities for watcher events * @context: Provides intelligent file system monitoring with debounced synchronization, preventing excessive API calls while ensuring timely cloud service updates */ import * as fs from 'fs'; import * as path from 'path'; import { loadIgnorePatterns, shouldIgnoreFile } from '../local/projectIdentifier'; import { syncProject } from './fileSyncClient'; import { logger } from '../utils/logger'; export interface WatcherOptions { baseDir: string; debounceMs?: number; } export class ConnectorWatcher { private baseDir: string; private debounceMs: number; private pending = false; private timer: NodeJS.Timeout | null = null; private running = false; private watcher: fs.FSWatcher | null = null; private ignorePatterns: string[] = []; constructor(options: WatcherOptions) { this.baseDir = path.resolve(options.baseDir); this.debounceMs = options.debounceMs ?? 1500; } async start(): Promise<void> { if (this.running) return; this.ignorePatterns = await loadIgnorePatterns(this.baseDir); this.watcher = fs.watch(this.baseDir, { recursive: true }, (event, filename) => { if (!filename) return; const rel = filename.replace(/\\/g, '/'); if (shouldIgnoreFile(rel, this.ignorePatterns)) return; this.onChange(); }); this.running = true; logger.info('🔭 Connector watcher started', { baseDir: this.baseDir }); } stop(): void { if (!this.running) return; this.watcher?.close(); this.watcher = null; this.running = false; if (this.timer) clearTimeout(this.timer); this.timer = null; this.pending = false; logger.info('🛑 Connector watcher stopped'); } private onChange(): void { this.pending = true; if (this.timer) clearTimeout(this.timer); this.timer = setTimeout(() => this.flush(), this.debounceMs); } private async flush(): Promise<void> { if (!this.pending) return; this.pending = false; try { const result = await syncProject(this.baseDir); logger.info('☁️ Debounced sync complete', result); } catch (error) { logger.warn('⚠️ Debounced sync failed', { error: error instanceof Error ? error.message : String(error), }); } } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sbarron/AmbianceMCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server