You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lib/src/http/routing/SocketRouteBuilder.ts

54 lines
1.9 KiB

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<TState extends JSONState> = {
eventClass: Instantiable<StateEvent<TState>>,
handler: Constructable<(state: TState) => Awaitable<void>>,
}
export class SocketRouteBuilder {
public static get(): SocketRouteBuilder {
return new SocketRouteBuilder()
}
protected handlers: Collection<SocketEventHandler<any>> = new Collection()
protected connectionCallback?: Constructable<(ws: WebSocketBus) => Awaitable<void>>
connected<TKey extends any>(
key: TypedDependencyKey<TKey>,
selector: (x: TKey) => (ws: WebSocketBus) => Awaitable<void>,
): this {
this.connectionCallback = constructable<TKey>(key)
.tap(inst => Function.prototype.bind.call(selector(inst), inst as any) as ((ws: WebSocketBus) => Awaitable<void>))
return this
}
event<TState extends JSONState, TKey extends any>(
eventClass: Instantiable<StateEvent<TState>>,
key: TypedDependencyKey<TKey>,
selector: (x: TKey) => (state: TState) => Awaitable<void>,
): this {
const handler = constructable<TKey>(key)
.tap(inst => Function.prototype.bind.call(selector(inst), inst as any) as ((state: TState) => Awaitable<void>))
this.handlers.push({
eventClass,
handler,
})
return this
}
async build(request: Request, ws: WebSocketBus): Promise<void> {
await this.handlers.promiseMap(handler => {
ws.subscribe(handler.eventClass, handler.handler.apply(request))
})
if ( this.connectionCallback ) {
await this.connectionCallback.apply(request)(ws)
}
}
}