@sailboat-computer/data-storage
Version:
Shared data storage library for sailboat computer v3
163 lines (136 loc) • 3.7 kB
text/typescript
/**
* Event Bus for Data Storage
*
* This module provides a simple event bus implementation for the data storage package.
*/
import { common } from '@sailboat-computer/sailboat-types';
// Define EventCategory constants
export const EventCategory = {
DATA: 'category_data' as common.EventCategory,
ALERT: 'category_alert' as common.EventCategory,
CONFIGURATION: 'category_configuration' as common.EventCategory,
SYSTEM: 'category_system' as common.EventCategory,
USER_ACTION: 'category_user_action' as common.EventCategory
};
export type EventCategoryType = common.EventCategory;
/**
* Event options
*/
export interface EventOptions {
/**
* Event category
*/
category: EventCategoryType;
/**
* Event priority
*/
priority: 'low' | 'normal' | 'high' | 'critical';
}
/**
* Event handler
*/
export type EventHandler = (data: any) => void | Promise<void>;
/**
* Event bus interface
*/
export interface EventBus {
/**
* Publish an event
*
* @param eventType - Event type
* @param data - Event data
* @param options - Event options
*/
publish(eventType: string, data: any, options?: EventOptions): Promise<void>;
/**
* Subscribe to an event
*
* @param eventType - Event type
* @param handler - Event handler
* @returns Subscription ID
*/
subscribe(eventType: string, handler: EventHandler): string;
/**
* Unsubscribe from an event
*
* @param subscriptionId - Subscription ID
*/
unsubscribe(subscriptionId: string): void;
}
/**
* In-memory event bus implementation
*/
export class InMemoryEventBus implements EventBus {
private subscriptions: Map<string, Map<string, EventHandler>> = new Map();
/**
* Publish an event
*
* @param eventType - Event type
* @param data - Event data
* @param options - Event options
*/
async publish(eventType: string, data: any, options?: EventOptions): Promise<void> {
const handlers = this.subscriptions.get(eventType);
if (!handlers) {
return;
}
const promises: Promise<void>[] = [];
for (const handler of handlers.values()) {
try {
const result = handler(data);
if (result instanceof Promise) {
promises.push(result);
}
} catch (error) {
console.error(`Error handling event ${eventType}:`, error);
}
}
if (promises.length > 0) {
await Promise.all(promises);
}
}
/**
* Subscribe to an event
*
* @param eventType - Event type
* @param handler - Event handler
* @returns Subscription ID
*/
subscribe(eventType: string, handler: EventHandler): string {
if (!this.subscriptions.has(eventType)) {
this.subscriptions.set(eventType, new Map());
}
const subscriptionId = `${eventType}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
this.subscriptions.get(eventType)!.set(subscriptionId, handler);
return subscriptionId;
}
/**
* Unsubscribe from an event
*
* @param subscriptionId - Subscription ID
*/
unsubscribe(subscriptionId: string): void {
const [eventType] = subscriptionId.split('-');
if (!eventType) {
return;
}
const handlers = this.subscriptions.get(eventType);
if (!handlers) {
return;
}
handlers.delete(subscriptionId);
if (handlers.size === 0) {
this.subscriptions.delete(eventType);
}
}
}
/**
* Create a new event bus
*
* @returns Event bus
*/
export function createEventBus(): EventBus {
return new InMemoryEventBus();
}
// Export singleton instance
export const eventBus = createEventBus();