okta-mcp-server
Version:
Model Context Protocol (MCP) server for Okta API operations with support for bulk operations and caching
141 lines • 4.04 kB
JavaScript
/**
* Type-safe event bus for event-driven architecture
*/
export class EventBus {
handlers = new Map();
asyncHandlers = new Map();
/**
* Subscribe to an event
*/
on(event, handler) {
if (!this.handlers.has(event)) {
this.handlers.set(event, new Set());
}
this.handlers.get(event).add(handler);
// Return unsubscribe function
return () => this.off(event, handler);
}
/**
* Subscribe to an event (alias for on)
*/
subscribe(event, handler) {
return this.on(event, handler);
}
/**
* Subscribe to an event once
*/
once(event, handler) {
const wrappedHandler = (data) => {
handler(data);
this.off(event, wrappedHandler);
};
return this.on(event, wrappedHandler);
}
/**
* Unsubscribe from an event
*/
off(event, handler) {
const handlers = this.handlers.get(event);
if (handlers) {
handlers.delete(handler);
if (handlers.size === 0) {
this.handlers.delete(event);
}
}
const asyncHandlers = this.asyncHandlers.get(event);
if (asyncHandlers) {
asyncHandlers.delete(handler);
if (asyncHandlers.size === 0) {
this.asyncHandlers.delete(event);
}
}
}
/**
* Emit an event synchronously
*/
emit(event, data) {
const handlers = this.handlers.get(event);
if (handlers) {
for (const handler of handlers) {
try {
handler(data);
}
catch (error) {
console.error(`Error in event handler for ${String(event)}:`, error);
}
}
}
}
/**
* Emit an event asynchronously
*/
async emitAsync(event, data) {
const handlers = this.handlers.get(event);
const asyncHandlers = this.asyncHandlers.get(event);
const allHandlers = [...(handlers || []), ...(asyncHandlers || [])];
if (allHandlers.length === 0) {
return;
}
await Promise.all(allHandlers.map(async (handler) => {
try {
await handler(data);
}
catch (error) {
console.error(`Error in async event handler for ${String(event)}:`, error);
}
}));
}
/**
* Register an async event handler
*/
onAsync(event, handler) {
if (!this.asyncHandlers.has(event)) {
this.asyncHandlers.set(event, new Set());
}
this.asyncHandlers.get(event).add(handler);
// Return unsubscribe function
return () => this.off(event, handler);
}
/**
* Wait for an event to occur
*/
waitFor(event, timeout) {
return new Promise((resolve, reject) => {
const timer = timeout
? setTimeout(() => {
unsubscribe();
reject(new Error(`Timeout waiting for event: ${String(event)}`));
}, timeout)
: null;
const unsubscribe = this.once(event, (data) => {
if (timer) {
clearTimeout(timer);
}
resolve(data);
});
});
}
/**
* Clear all event handlers
*/
clear() {
this.handlers.clear();
this.asyncHandlers.clear();
}
/**
* Get the number of handlers for an event
*/
listenerCount(event) {
const syncCount = this.handlers.get(event)?.size || 0;
const asyncCount = this.asyncHandlers.get(event)?.size || 0;
return syncCount + asyncCount;
}
/**
* Get all registered events
*/
eventNames() {
const events = new Set([...this.handlers.keys(), ...this.asyncHandlers.keys()]);
return Array.from(events);
}
}
//# sourceMappingURL=event-bus.js.map