@eweser/db
Version:
eweser-db core database
114 lines (99 loc) • 3.46 kB
text/typescript
/* eslint-disable no-console -- this IS the logger implementation */
import type { EweDocument } from '@eweser/shared';
import type { Room } from './types.js';
import type { Database } from './index.js';
type EmittedEvents = Record<string | symbol, (...args: never[]) => void>;
type Listener = (...args: unknown[]) => void;
/** Minimal browser-compatible typed event emitter (no Node.js 'events' dependency). */
export class TypedEventEmitter<Events extends EmittedEvents> {
private _listeners: Map<string | symbol, Set<Listener>> = new Map();
on<K extends keyof Events>(event: K, listener: Events[K]): this {
const key = event as string | symbol;
if (!this._listeners.has(key)) this._listeners.set(key, new Set());
const listeners = this._listeners.get(key);
if (listeners) {
listeners.add(listener as unknown as Listener);
}
return this;
}
off<K extends keyof Events>(event: K, listener: Events[K]): this {
this._listeners
.get(event as string | symbol)
?.delete(listener as unknown as Listener);
return this;
}
emit<K extends keyof Events>(
event: K,
...args: Parameters<Events[K]>
): boolean {
const listeners = this._listeners.get(event as string | symbol);
if (!listeners || listeners.size === 0) return false;
listeners.forEach((l) => l(...(args as unknown[])));
return true;
}
once<K extends keyof Events>(event: K, listener: Events[K]): this {
const wrapper: Listener = (...args) => {
this.off(event, listener);
(listener as unknown as Listener)(...args);
};
return this.on(event, wrapper as unknown as Events[K]);
}
removeAllListeners<K extends keyof Events>(event?: K): this {
if (event !== undefined) {
this._listeners.delete(event as string | symbol);
} else {
this._listeners.clear();
}
return this;
}
}
export type RoomConnectionStatus = 'connected' | 'disconnected' | 'connecting';
export type DatabaseEvents = {
log: (level: number, ...args: unknown[]) => void;
debug: (...args: unknown[]) => void;
info: (...args: unknown[]) => void;
warn: (...args: unknown[]) => void;
error: (...args: unknown[]) => void;
roomLoaded: (room: Room<EweDocument>) => void;
roomRemoteLoaded: (room: Room<EweDocument>) => void;
roomsLoaded: (rooms: Room<EweDocument>[]) => void;
roomsRemotesLoaded: (rooms: Room<EweDocument>[]) => void;
roomConnectionChange: (
status: RoomConnectionStatus,
room: Room<EweDocument>
) => void;
onLoggedInChange: (loggedIn: boolean) => void;
onlineChange: (online: boolean) => void;
status: (status: {
db: Database;
online: boolean;
hasToken: boolean;
allRoomsCount: number;
connectedRoomsCount: number;
connectedRooms: string[];
connectingRoomsCount: number;
connectingRooms: string[];
}) => void;
registrySync: (
status: 'syncing' | 'success' | 'error',
error?: unknown
) => void;
initialized: () => void;
};
export type RoomEvents<T extends EweDocument> = {
roomConnectionChange: (status: RoomConnectionStatus, room: Room<T>) => void;
};
export const setupLogger = (db: Database) => {
db.on('log', (level, ...message) => {
switch (level) {
case 0:
return console.info(...message);
case 1:
return console.log(...message);
case 2:
return console.warn(...message);
case 3:
return console.error(...message);
}
});
};