import { ConnectionClosed } from "./Common" import { IConnection } from "./IConnection" import { Connection } from "./Connection" interface InvocationDescriptor { readonly Id: string; readonly Method: string; readonly Arguments: Array; } interface InvocationResultDescriptor { readonly Id: string; readonly Error: string; readonly Result: any; } export { Connection } from "./Connection" export class HubConnection { private connection: IConnection; private callbacks: Map void>; private methods: Map void>; private id: number; static create(url: string, queryString?: string): HubConnection { return new this(new Connection(url, queryString)) } constructor(connection: IConnection); constructor(url: string, queryString?: string); constructor(connectionOrUrl: IConnection | string, queryString?: string) { this.connection = typeof connectionOrUrl === "string" ? new Connection(connectionOrUrl, queryString) : connectionOrUrl; this.connection.onDataReceived = data => { this.onDataReceived(data); }; this.callbacks = new Map void>(); this.methods = new Map void>(); this.id = 0; } private onDataReceived(data: any) { // TODO: separate JSON parsing // Can happen if a poll request was cancelled if (!data) { return; } var descriptor = JSON.parse(data); if (descriptor.Method === undefined) { let invocationResult: InvocationResultDescriptor = descriptor; let callback = this.callbacks[invocationResult.Id]; if (callback != null) { callback(invocationResult); this.callbacks.delete(invocationResult.Id); } } else { let invocation: InvocationDescriptor = descriptor; let method = this.methods[invocation.Method]; if (method != null) { // TODO: bind? args? method.apply(this, invocation.Arguments); } } } start(transportName? :string): Promise { return this.connection.start(transportName); } stop(): void { return this.connection.stop(); } invoke(methodName: string, ...args: any[]): Promise { let id = this.id; this.id++; let invocationDescriptor: InvocationDescriptor = { "Id": id.toString(), "Method": methodName, "Arguments": args }; let p = new Promise((resolve, reject) => { this.callbacks[id] = (invocationResult: InvocationResultDescriptor) => { if (invocationResult.Error != null) { reject(new Error(invocationResult.Error)); } else { resolve(invocationResult.Result); } }; //TODO: separate conversion to enable different data formats this.connection.send(JSON.stringify(invocationDescriptor)) .catch(e => { // TODO: remove callback reject(e); }); }); return p; } on(methodName: string, method: (...args: any[]) => void) { this.methods[methodName] = method; } set onClosed(callback: ConnectionClosed) { this.connection.onClosed = callback; } }