UNPKG

vibe-coder-mcp

Version:

Production-ready MCP server with complete agent integration, multi-transport support, and comprehensive development automation tools for AI-assisted workflows.

201 lines (200 loc) 6 kB
import logger from '../../../logger.js'; export class ResourceManager { resources = new Set(); disposed = false; register(resource) { if (this.disposed) { logger.warn('Attempting to register resource on disposed ResourceManager'); return; } this.resources.add(resource); } unregister(resource) { return this.resources.delete(resource); } getResourceCount() { return this.resources.size; } async dispose() { if (this.disposed) { return; } this.disposed = true; const errors = []; for (const resource of this.resources) { try { await this.disposeResource(resource); } catch (error) { errors.push(error); logger.warn('Error disposing resource', { error }); } } this.resources.clear(); if (errors.length > 0) { logger.warn(`Disposed ResourceManager with ${errors.length} errors`); } } async disposeResource(resource) { if (typeof resource === 'object' && resource !== null) { if ('_idleTimeout' in resource && !('_repeat' in resource)) { clearTimeout(resource); return; } if ('_repeat' in resource) { clearInterval(resource); return; } if ('_idleTimeout' in resource || '_repeat' in resource) { try { clearTimeout(resource); } catch { } try { clearInterval(resource); } catch { } return; } } if (typeof resource === 'function') { await resource(); return; } if (typeof resource === 'object' && resource !== null) { if ('dispose' in resource && typeof resource.dispose === 'function') { await resource.dispose(); } else if ('cleanup' in resource && typeof resource.cleanup === 'function') { await resource.cleanup(); } else if ('destroy' in resource && typeof resource.destroy === 'function') { await resource.destroy(); } else if ('close' in resource && typeof resource.close === 'function') { await resource.close(); } else if ('clear' in resource && typeof resource.clear === 'function') { resource.clear(); } } } isDisposed() { return this.disposed; } } export class DisposableService { resourceManager = new ResourceManager(); disposed = false; registerResource(resource) { this.resourceManager.register(resource); } unregisterResource(resource) { return this.resourceManager.unregister(resource); } createTimer(callback, delay, repeat = false) { const timer = repeat ? setInterval(callback, delay) : setTimeout(callback, delay); this.registerResource(timer); return timer; } async dispose() { if (this.disposed) { return; } this.disposed = true; try { await this.onDispose(); } catch (error) { logger.warn('Error in custom dispose logic', { error }); } await this.resourceManager.dispose(); } async cleanup() { await this.dispose(); } async destroy() { await this.dispose(); } isDisposed() { return this.disposed; } async onDispose() { } } export class DisposableWrapper { target; disposeMethod; disposed = false; constructor(target, disposeMethod = 'dispose') { this.target = target; this.disposeMethod = disposeMethod; } async dispose() { if (this.disposed) { return; } this.disposed = true; try { if (typeof this.disposeMethod === 'function') { await this.disposeMethod(); } else if (typeof this.disposeMethod === 'string' && this.target && typeof this.target[this.disposeMethod] === 'function') { await this.target[this.disposeMethod](); } } catch (error) { logger.warn('Error disposing wrapped object', { error }); } } isDisposed() { return this.disposed; } } export class GlobalDisposableRegistry { static disposables = new Set(); static register(disposable) { this.disposables.add(disposable); } static unregister(disposable) { return this.disposables.delete(disposable); } static async disposeAll() { const errors = []; for (const disposable of this.disposables) { try { await disposable.dispose(); } catch (error) { errors.push(error); logger.warn('Error disposing global resource', { error }); } } this.disposables.clear(); if (errors.length > 0) { logger.warn(`Disposed global registry with ${errors.length} errors`); } } static getCount() { return this.disposables.size; } static clear() { this.disposables.clear(); } } export function AutoDispose(target) { const originalConstructor = target; function newConstructor(...args) { const instance = new originalConstructor(...args); if (instance && typeof instance.dispose === 'function') { GlobalDisposableRegistry.register(instance); } return instance; } newConstructor.prototype = originalConstructor.prototype; return newConstructor; }