UNPKG

syncable-server

Version:
68 lines (67 loc) 3.72 kB
/// <reference types="socket.io" /> /// <reference types="node" /> import { EventEmitter } from 'events'; import { BroadcastChange, Change, ClientBroadcastChangeData, GeneralChange, QueuedBroadcastChange, Removal, Request, SnapshotsData, Subscription, Syncable } from 'syncable'; import { SyncableDefinition } from './definition'; import { ObjectQueue } from './object-queue'; export interface ResourceLock { release(): PromiseLike<void>; } export declare type Visibility = boolean | 'upon-request'; export interface SubscriptionInfo<TClientSession> { subscription: Subscription; changeEmitter: ObjectQueue<ClientBroadcastChangeData<BroadcastChange, TClientSession>>; visibleSet: Set<string>; valid: boolean; } export interface QueuedBroadcastChangeData<TSession> { change: QueuedBroadcastChange; session: TSession; } export interface Socket<TClientSession> extends SocketIO.Socket { subjectToSubscriptionInfoMap: Map<string, SubscriptionInfo<TClientSession>>; on(event: 'change', listener: (change: Change) => void): this; on(event: 'subscribe', listener: (subscription: Subscription) => void): this; on(event: 'request', listener: (request: Request) => void): this; on(event: 'close', listener: () => void): this; emit(event: 'subscribed', data: Subscription): boolean; emit(event: 'change', data: ClientBroadcastChangeData<BroadcastChange, TClientSession>): boolean; emit(event: 'snapshots', data: SnapshotsData): boolean; } export interface SocketServer<TClientSession> extends SocketIO.Server { on(event: 'connection' | 'connect', listener: (socket: Socket<TClientSession>) => void): SocketIO.Namespace; } export declare class ChangeEmitter<TClientSession> extends ObjectQueue<ClientBroadcastChangeData<BroadcastChange, TClientSession>> { private socket; constructor(socket: Socket<TClientSession>); protected emit(object: ClientBroadcastChangeData<BroadcastChange, TClientSession>): void; protected resolveChannel({change: {subject}}: ClientBroadcastChangeData<BroadcastChange, TClientSession>): string; } export declare abstract class Server<TSession, TClientSession> extends EventEmitter { private socketServer; private errorEmitter; private subjectToDefinitionMap; private subjectToSocketSetMap; constructor(socketServer: SocketServer<TClientSession>); register(subject: string, definition: SyncableDefinition<Syncable, Subscription, TSession, TClientSession, this>): void; spawnChange<T extends GeneralChange, U extends Syncable = Syncable>(change: T, session: TSession): Promise<U>; spawnChange(removal: Removal, session: TSession): Promise<void>; protected abstract getSession(socket: Socket<TClientSession>): TSession; protected abstract resolveClientSession(session: TSession): TClientSession; protected abstract lock(resource: string, ttl: number): Promise<ResourceLock>; protected abstract generateTimestamp(): Promise<number>; protected abstract queueChange(change: BroadcastChange, session: TSession): Promise<void>; private initChangeQueueListener(); private initSocketServer(); private initSubscription(info, socket); private loadAndEmitSnapshots(info, socket); private loadAndEmitUponRequest(request, socket); private loadAndEmitChanges(info, socket); private handleChangeFromQueue(change, session); } export interface Server<TSession, TClientSession> { on(event: 'change', listener: (data: QueuedBroadcastChangeData<TSession>) => void): this; on(event: 'error', listener: (error: any) => void): this; emit(event: 'change', data: QueuedBroadcastChangeData<TSession>): boolean; emit(event: 'error', error: any): boolean; }