import {StateEvent, WebSocketBus} from '../../support/bus' import {constructable, Constructable, Instantiable, TypedDependencyKey} from '../../di' import {Awaitable, Collection, JSONState} from '../../util' import {Request} from '../lifecycle/Request' export type SocketEventHandler = { eventClass: Instantiable>, handler: Constructable<(state: TState) => Awaitable>, } export class SocketRouteBuilder { public static get(): SocketRouteBuilder { return new SocketRouteBuilder() } protected handlers: Collection> = new Collection() protected connectionCallback?: Constructable<(ws: WebSocketBus) => Awaitable> connected( key: TypedDependencyKey, selector: (x: TKey) => (ws: WebSocketBus) => Awaitable, ): this { this.connectionCallback = constructable(key) .tap(inst => Function.prototype.bind.call(selector(inst), inst as any) as ((ws: WebSocketBus) => Awaitable)) return this } event( eventClass: Instantiable>, key: TypedDependencyKey, selector: (x: TKey) => (state: TState) => Awaitable, ): this { const handler = constructable(key) .tap(inst => Function.prototype.bind.call(selector(inst), inst as any) as ((state: TState) => Awaitable)) this.handlers.push({ eventClass, handler, }) return this } async build(request: Request, ws: WebSocketBus): Promise { await this.handlers.promiseMap(handler => { ws.subscribe(handler.eventClass, handler.handler.apply(request)) }) if ( this.connectionCallback ) { await this.connectionCallback.apply(request)(ws) } } }