Files
Perplexica/src/lib/session.ts

106 lines
2.6 KiB
TypeScript

import { EventEmitter } from 'stream';
import { applyPatch } from 'rfc6902';
import { Block } from './types';
const sessions =
(global as any)._sessionManagerSessions || new Map<string, SessionManager>();
if (process.env.NODE_ENV !== 'production') {
(global as any)._sessionManagerSessions = sessions;
}
class SessionManager {
private static sessions: Map<string, SessionManager> = sessions;
readonly id: string;
private blocks = new Map<string, Block>();
private events: { event: string; data: any }[] = [];
private emitter = new EventEmitter();
private TTL_MS = 30 * 60 * 1000;
constructor(id?: string) {
this.id = id ?? crypto.randomUUID();
setTimeout(() => {
SessionManager.sessions.delete(this.id);
}, this.TTL_MS);
}
static getSession(id: string): SessionManager | undefined {
return this.sessions.get(id);
}
static getAllSessions(): SessionManager[] {
return Array.from(this.sessions.values());
}
static createSession(): SessionManager {
const session = new SessionManager();
this.sessions.set(session.id, session);
return session;
}
removeAllListeners() {
this.emitter.removeAllListeners();
}
emit(event: string, data: any) {
this.emitter.emit(event, data);
this.events.push({ event, data });
}
emitBlock(block: Block) {
this.blocks.set(block.id, block);
this.emit('data', {
type: 'block',
block: block,
});
}
getBlock(blockId: string): Block | undefined {
return this.blocks.get(blockId);
}
updateBlock(blockId: string, patch: any[]) {
const block = this.blocks.get(blockId);
if (block) {
applyPatch(block, patch);
this.blocks.set(blockId, block);
this.emit('data', {
type: 'updateBlock',
blockId: blockId,
patch: patch,
});
}
}
getAllBlocks() {
return Array.from(this.blocks.values());
}
subscribe(listener: (event: string, data: any) => void): () => void {
const currentEventsLength = this.events.length;
const handler = (event: string) => (data: any) => listener(event, data);
const dataHandler = handler('data');
const endHandler = handler('end');
const errorHandler = handler('error');
this.emitter.on('data', dataHandler);
this.emitter.on('end', endHandler);
this.emitter.on('error', errorHandler);
for (let i = 0; i < currentEventsLength; i++) {
const { event, data } = this.events[i];
listener(event, data);
}
return () => {
this.emitter.off('data', dataHandler);
this.emitter.off('end', endHandler);
this.emitter.off('error', errorHandler);
};
}
}
export default SessionManager;