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
JavaScript
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;
}