{"version":3,"sources":["../src/index.ts","../src/FakeSignalrHub.ts","../src/ClientState.ts","../src/messageTypes.ts","../src/messagePack/BinaryMessageFormat.ts","../src/messagePack/parse.ts"],"sourcesContent":["export { FakeSignalrHub } from './FakeSignalrHub'\nexport type { ConnectionId } from '@fakehost/exchange'\n","import { HubMessage, IStreamResult, Subject } from '@microsoft/signalr'\nimport { MessagePackHubProtocol } from '@microsoft/signalr-protocol-msgpack'\nimport {\n    CloseConnectionOptions,\n    Connection,\n    ConnectionId,\n    Host,\n    ExchangeEvent,\n} from '@fakehost/exchange'\nimport { Observable } from 'rxjs'\nimport { ClientState } from './ClientState'\nimport { MessageType, InboundMessage, isHandshakeMessage } from './messageTypes'\nimport { parse } from './messagePack'\n\nconst protocol = new MessagePackHubProtocol()\n\ntype AllKeys<T = object> = {\n    [K in keyof T]: boolean\n}\n\ntype HubClients<T = object> = {\n    All: { [K in keyof T]: T[K] }\n    Others: { [K in keyof T]: T[K] }\n    Caller: { [K in keyof T]: T[K] }\n    Client: (clientId: ConnectionId) => { [K in keyof T]: T[K] }\n}\n\ntype ConnectionState<State = object> = {\n    id: ConnectionId\n    setState: <Key extends keyof State>(key: Key, value: State[Key]) => void\n    getState: <Key extends keyof State>(key: Key) => State[Key] | undefined\n    addEventHandler(event: 'disconnect', handler: () => void): void\n    removeEventHandler(event: 'disconnect', handler: () => void): void\n}\n\ntype SignalrInstanceThis<Receiver = object, State = object> = {\n    Clients: HubClients<Receiver>\n    Connection: ConnectionState<State>\n}\n\nconst TERMINATING_CHAR = String.fromCharCode(30)\n\ntype ConnectionEvents = 'disconnect'\n\ntype FormatTarget<Hub extends object, Receiver = object> =\n    | 'capitalize'\n    | undefined\n    | ((s: keyof Hub | keyof Receiver) => string)\n\nexport class FakeSignalrHub<\n    Hub extends object,\n    Receiver extends object = object,\n    State extends object = object,\n> {\n    // active client connections to this hub\n    private clients = new Map<ConnectionId, ClientState<State>>()\n    // methods from Hub. Not typed due to casing of methods (camelCase in ts vs PascalCase in C#)\n    private handlers = new Map<string, Handler>()\n    private host?: Host\n    private messageProtocol = new Map<ConnectionId, 'json' | 'messagepack' | string>()\n    private connectionEvents = new Map<`${ConnectionId}.${ConnectionEvents}`, Set<() => void>>()\n\n    constructor(\n        public readonly path: string,\n        private receivers: Partial<AllKeys<Receiver>> = {},\n        private format?: FormatTarget<Hub, Receiver>,\n    ) {}\n\n    disconnect(options?: CloseConnectionOptions) {\n        this.host?.disconnect({ path: this.path, ...options })\n    }\n\n    setHost(host: Host) {\n        this.host = host\n        this.host.on('connection', this.onConnection.bind(this))\n        this.host.on('disconnection', this.onDisconnection.bind(this))\n        this.host.on('message', e => {\n            // Message not for this hub\n            if (e.connection.url.pathname !== this.path) return\n\n            // Handle initial handshake\n            if (!this.messageProtocol.has(e.connection.id)) {\n                this.handleHandshake(e.connection, e.message)\n                return\n            }\n\n            const messages = this.deserialize(e.connection, e.message)\n            messages.forEach(message => this.onMessage.bind(this)(e.connection, message))\n        })\n\n        // TODO: off\n    }\n\n    /**\n     * There can be differences in casing between the client typescript and the server handler methods in C#.\n     * This method formats the target to match the casing of the server.\n     * @param s\n     * @returns\n     */\n    private formatTarget(s: keyof Hub | keyof Receiver): string {\n        if (this.format === 'capitalize' && typeof s === 'string') {\n            return capitalize(s)\n        } else if (typeof this.format === 'function') {\n            return this.format(s as keyof (Hub | Receiver))\n        } else {\n            return s as string\n        }\n    }\n\n    private onConnection({ connection }: ExchangeEvent<'connection'>) {\n        if (connection.url.pathname !== this.path) return\n        this.clients.set(connection.id, new ClientState(connection))\n    }\n\n    private onDisconnection({ connection }: ExchangeEvent<'disconnection'>) {\n        if (connection.url.pathname !== this.path) return\n        this.clients.get(connection.id)?.dispose()\n        this.clients.delete(connection.id)\n\n        const handlers = this.connectionEvents.get(`${connection.id}.disconnect`)\n        handlers?.forEach(handler => handler())\n        this.connectionEvents.delete(`${connection.id}.disconnect`)\n    }\n\n    private handleHandshake(connection: Connection, message: string | Buffer) {\n        const [parsed] = message\n            .toString()\n            .split(TERMINATING_CHAR)\n            .filter(Boolean)\n            .map(m => JSON.parse(m))\n\n        if (!isHandshakeMessage(parsed)) {\n            console.error('Expected initial handshake message, but none was received.')\n            connection.close({ code: 1002, reason: 'No handshake supplied' })\n            return\n        }\n\n        this.messageProtocol.set(connection.id, parsed.protocol)\n        connection.write(JSON.stringify({ type: 0 }) + TERMINATING_CHAR)\n    }\n\n    private serialize(connection: Connection, message: unknown) {\n        switch (this.messageProtocol.get(connection.id)) {\n            case 'json':\n                return JSON.stringify(message) + TERMINATING_CHAR\n            case 'messagepack':\n                return protocol.writeMessage(message as HubMessage) as Buffer\n            default:\n                throw new Error('Unknown connection mode')\n        }\n    }\n\n    private deserialize(\n        connection: Connection,\n        message: string | Buffer,\n    ): Array<InboundMessage<Hub>> {\n        switch (this.messageProtocol.get(connection.id)) {\n            case 'json': {\n                return message\n                    .toString()\n                    .split(TERMINATING_CHAR)\n                    .filter(Boolean)\n                    .map(m => JSON.parse(m))\n            }\n            case 'messagepack': {\n                return parse(message as Buffer)\n            }\n            default:\n                throw new Error('Unknown connection mode')\n        }\n    }\n\n    private async onMessage(connection: Connection, message: InboundMessage<Hub>) {\n        const connectionId = connection.id as ConnectionId\n        const client = this.clients.get(connectionId)\n        if (!client) return\n\n        switch (message.type) {\n            case MessageType.Invocation: {\n                const handler = this.handlers.get(message.target as string)\n                if (message.streamIds) {\n                    // starting a stream from the client -> service\n                    message.streamIds.forEach(async streamId => {\n                        const subject = new Subject<unknown>()\n                        client.subjects.set(streamId, subject)\n                        await handler?.apply(this.getSignalrInstance(connectionId), [subject])\n                    })\n                    return\n                }\n                try {\n                    const result = await handler?.apply(\n                        this.getSignalrInstance(connectionId),\n                        message.arguments ?? [],\n                    )\n                    return connection.write(\n                        this.serialize(connection, {\n                            type: MessageType.Completion,\n                            invocationId: message.invocationId,\n                            result,\n                        }),\n                    )\n                } catch (error: unknown) {\n                    return connection.write(\n                        this.serialize(connection, {\n                            type: MessageType.Completion,\n                            invocationId: message.invocationId,\n                            error: stringifyError(error),\n                        }),\n                    )\n                }\n            }\n            case MessageType.StreamInvocation: {\n                const handler = this.handlers.get(message.target as string)\n                const result: IStreamResult<unknown> | Observable<unknown> = await handler?.apply(\n                    this.getSignalrInstance(connectionId),\n                    message.arguments ?? [],\n                )\n                const subscription = result.subscribe({\n                    next: value => {\n                        connection.write(\n                            this.serialize(connection, {\n                                type: MessageType.StreamItem,\n                                invocationId: message.invocationId,\n                                item: value,\n                            }),\n                        )\n                    },\n                    error: error => {\n                        connection.write(\n                            this.serialize(connection, {\n                                type: MessageType.Completion,\n                                invocationId: message.invocationId,\n                                error: stringifyError(error),\n                            }),\n                        )\n                    },\n                    complete: () => {\n                        connection.write(\n                            this.serialize(connection, {\n                                type: MessageType.Completion,\n                                invocationId: message.invocationId,\n                            }),\n                        )\n                    },\n                })\n                client.subscriptions.set(message.invocationId, subscription)\n                return\n            }\n            case MessageType.StreamItem: {\n                const subject = client.subjects.get(message.invocationId)\n                return subject?.next(message.item)\n            }\n            case MessageType.CancelInvocation: {\n                client.cleanup(message.invocationId)\n                connection.write(\n                    this.serialize(connection, {\n                        type: MessageType.Completion,\n                        invocationId: message.invocationId,\n                    }),\n                )\n                return\n            }\n            case MessageType.Completion: {\n                client.cleanup(message.invocationId)\n                return\n            }\n            case MessageType.Ping:\n                return connection.write(this.serialize(connection, { type: MessageType.Ping }))\n            default:\n                console.warn('Not handled', message)\n        }\n    }\n\n    private getSignalrInstance(\n        currentConnectionId: ConnectionId,\n    ): SignalrInstanceThis<Receiver, State> {\n        const client = this.clients.get(currentConnectionId)\n        if (!client) {\n            throw new Error('Excepted a client but there was none')\n        }\n\n        const createClientSender = (\n            predicate: (connectionId: ConnectionId) => boolean,\n        ): Receiver => {\n            const result = Object.keys(this.receivers).reduce((acc, target) => {\n                acc[target] = (...args: unknown[]) => {\n                    Array.from(this.clients.entries())\n                        .filter(([connId]) => predicate(connId as ConnectionId))\n                        .forEach(([, client]) => {\n                            client.connection.write(\n                                this.serialize(client.connection, {\n                                    type: MessageType.Invocation,\n                                    target: this.formatTarget(target as keyof Receiver),\n                                    arguments: args,\n                                }),\n                            )\n                        })\n                }\n                return acc\n            }, {} as Record<string, (...args: unknown[]) => void>)\n            return result as Receiver\n        }\n\n        const signalrThis: SignalrInstanceThis<Receiver, State> = {\n            Connection: {\n                get id() {\n                    return client.connection.id\n                },\n                setState: (key, value) => {\n                    client.setState(key, value)\n                },\n                getState: key => {\n                    return client.state[key]\n                },\n                addEventHandler: (eventName, handler) => {\n                    const handlers =\n                        this.connectionEvents.get(`${currentConnectionId}.${eventName}`) ||\n                        new Set()\n                    handlers.add(handler)\n                    this.connectionEvents.set(`${currentConnectionId}.${eventName}`, handlers)\n                },\n                removeEventHandler: (eventName, handler) => {\n                    const handlers =\n                        this.connectionEvents.get(`${currentConnectionId}.${eventName}`) ||\n                        new Set()\n                    handlers.delete(handler)\n                    this.connectionEvents.set(`${currentConnectionId}.${eventName}`, handlers)\n                },\n            },\n            Clients: {\n                get All() {\n                    return createClientSender(() => true)\n                },\n                get Others() {\n                    return createClientSender(id => id !== client.connection.id)\n                },\n                get Caller() {\n                    return createClientSender(id => id === client.connection.id)\n                },\n                Client: (clientId: ConnectionId) => {\n                    return createClientSender(id => id === clientId)\n                },\n            },\n        }\n        return signalrThis\n    }\n\n    get thisInstance(): SignalrInstanceThis<Receiver, State> {\n        throw new Error('Not callable. Used only for type inference.')\n    }\n\n    register<Target extends keyof Hub>(target: Target, handler: Handler) {\n        this.handlers.set(this.formatTarget(target), handler)\n    }\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype Handler = (...args: any[]) => any\n\nconst capitalize = (key: string) => key.slice(0, 1).toUpperCase() + key.slice(1)\n\nconst stringifyError = (e: unknown) => {\n    if (typeof e === 'string') return e\n    if (e instanceof Error) return e.message\n    return JSON.stringify(e)\n}\n","import { Connection } from '@fakehost/exchange'\nimport { ISubscription, Subject } from '@microsoft/signalr'\nimport { Subscription } from 'rxjs'\nimport { InvocationId } from './messageTypes'\n\nexport class ClientState<T = object> {\n    public readonly state = {} as T\n    // streams service -> client\n    public readonly subscriptions = new Map<InvocationId, ISubscription<unknown> | Subscription>()\n    // streams client -> service\n    public readonly subjects = new Map<InvocationId, Subject<unknown>>()\n\n    constructor(public readonly connection: Connection) {}\n\n    private unsubscribe(id: InvocationId) {\n        const subscription = this.subscriptions.get(id)\n        if (!subscription) return\n        if ('unsubscribe' in subscription) {\n            subscription.unsubscribe()\n        } else {\n            subscription.dispose()\n        }\n    }\n\n    cleanup(id: InvocationId) {\n        const subject = this.subjects.get(id)\n        if (subject) {\n            subject.complete()\n            this.subjects.delete(id)\n        }\n        const subscription = this.subscriptions.get(id)\n        if (subscription) {\n            this.unsubscribe(id)\n            this.subscriptions.delete(id)\n        }\n    }\n\n    dispose() {\n        Array.from(this.subscriptions.keys()).forEach(id => this.unsubscribe(id))\n        this.subjects.forEach(subject => subject.complete())\n    }\n\n    setState(key: keyof T, value: T[keyof T]) {\n        this.state[key] = value\n    }\n}\n","export enum MessageType {\n    Invocation = 1,\n    StreamItem = 2,\n    Completion = 3,\n    StreamInvocation = 4,\n    CancelInvocation = 5,\n    Ping = 6,\n    Close = 7,\n}\n\nexport type InvocationId = string & { __invocationId: never }\n\nexport type HandshakeMessage = {\n    protocol: string\n    version: number\n}\n\nexport type InvocationMessage<Hub> = {\n    type: MessageType.Invocation\n    target: keyof Hub\n    invocationId: InvocationId\n    arguments?: unknown[]\n    streamIds?: InvocationId[]\n}\n\nexport type StreamItemMessage = {\n    type: MessageType.StreamItem\n    item?: unknown\n    invocationId: InvocationId\n}\n\nexport type Ping = {\n    type: MessageType.Ping\n}\n\nexport type CloseMessage = {\n    type: MessageType.Close\n    error?: string\n    allowReconnect?: boolean\n}\n\nexport type StreamInvocation<Hub> = {\n    type: MessageType.StreamInvocation\n    target: keyof Hub\n    invocationId: InvocationId\n    arguments?: unknown[]\n}\n\nexport type CancelInvocation = {\n    type: MessageType.CancelInvocation\n    invocationId: InvocationId\n}\n\nexport type CompleteInvocation = {\n    type: MessageType.Completion\n    error?: string\n    invocationId: InvocationId\n    result?: unknown\n}\n\nexport type InboundMessage<Hub> =\n    | CompleteInvocation\n    | InvocationMessage<Hub>\n    | StreamInvocation<Hub>\n    | StreamItemMessage\n    | CancelInvocation\n    | Ping\n    | CloseMessage\n\nexport const isHandshakeMessage = (\n    message: unknown | HandshakeMessage,\n): message is HandshakeMessage => {\n    return (message as HandshakeMessage).protocol !== undefined\n}\n","export class BinaryMessageFormat {\n    // The length prefix of binary messages is encoded as VarInt. Read the comment in\n    // the BinaryMessageParser.TryParseMessage for details.\n\n    public static write(output: Uint8Array): ArrayBuffer {\n        let size = output.byteLength || output.length\n        const lenBuffer = []\n        do {\n            let sizePart = size & 0x7f\n            size = size >> 7\n            if (size > 0) {\n                sizePart |= 0x80\n            }\n            lenBuffer.push(sizePart)\n        } while (size > 0)\n\n        size = output.byteLength || output.length\n\n        const buffer = new Uint8Array(lenBuffer.length + size)\n        buffer.set(lenBuffer, 0)\n        buffer.set(output, lenBuffer.length)\n        return buffer.buffer\n    }\n\n    public static parse(input: ArrayBuffer): Uint8Array[] {\n        const result: Uint8Array[] = []\n        const uint8Array = new Uint8Array(input)\n        const maxLengthPrefixSize = 5\n        const numBitsToShift = [0, 7, 14, 21, 28]\n\n        for (let offset = 0; offset < input.byteLength; ) {\n            let numBytes = 0\n            let size = 0\n            let byteRead\n            do {\n                byteRead = uint8Array[offset + numBytes]\n                size = size | ((byteRead & 0x7f) << numBitsToShift[numBytes])\n                numBytes++\n            } while (\n                numBytes < Math.min(maxLengthPrefixSize, input.byteLength - offset) &&\n                (byteRead & 0x80) !== 0\n            )\n\n            if ((byteRead & 0x80) !== 0 && numBytes < maxLengthPrefixSize) {\n                throw new Error('Cannot read message size.')\n            }\n\n            if (numBytes === maxLengthPrefixSize && byteRead > 7) {\n                throw new Error('Messages bigger than 2GB are not supported.')\n            }\n\n            if (uint8Array.byteLength >= offset + numBytes + size) {\n                // IE does not support .slice() so use subarray\n                result.push(\n                    uint8Array.slice\n                        ? uint8Array.slice(offset + numBytes, offset + numBytes + size)\n                        : uint8Array.subarray(offset + numBytes, offset + numBytes + size),\n                )\n            } else {\n                throw new Error('Incomplete message.')\n            }\n\n            offset = offset + numBytes + size\n        }\n\n        return result\n    }\n}\n","import { InboundMessage, MessageType } from '../messageTypes'\nimport { BinaryMessageFormat } from './BinaryMessageFormat'\nimport { Decoder } from '@msgpack/msgpack'\n\nexport const parse = <Hub extends object>(input: Buffer): Array<InboundMessage<Hub>> => {\n    const buffer = Buffer.from(input as Uint8Array)\n    const arrayBuffer = buffer.buffer.slice(\n        buffer.byteOffset,\n        buffer.byteOffset + buffer.byteLength,\n    )\n    const messages = BinaryMessageFormat.parse(arrayBuffer)\n\n    const hubMessages = new Array<InboundMessage<Hub>>()\n\n    for (const message of messages) {\n        const parsedMessage = parseMessage(message)\n        // Can be null for an unknown message. Unknown message is logged in parseMessage\n        if (parsedMessage) {\n            hubMessages.push(parsedMessage)\n        }\n    }\n\n    return hubMessages\n}\n\nconst parseMessage = <Hub extends object>(input: Uint8Array): InboundMessage<Hub> | null => {\n    if (input.length === 0) {\n        throw new Error('Invalid payload.')\n    }\n\n    const decoder = new Decoder()\n\n    const properties = decoder.decode(input) as any\n    if (properties.length === 0 || !(properties instanceof Array)) {\n        throw new Error('Invalid payload.')\n    }\n\n    const messageType = properties[0] as MessageType\n    switch (messageType) {\n        case MessageType.Invocation:\n            return {\n                type: MessageType.Invocation,\n                arguments: properties[4],\n                invocationId: properties[2],\n                streamIds: properties[5],\n                target: properties[3],\n            }\n        case MessageType.StreamItem:\n            return {\n                type: MessageType.StreamItem,\n                invocationId: properties[2],\n                item: properties[3],\n            }\n        case MessageType.Completion: {\n            const resultKind = properties[3]\n            return {\n                type: MessageType.Completion,\n                error: resultKind === 1 ? properties[4] : undefined,\n                invocationId: properties[2],\n                result: resultKind === 1 ? undefined : properties[4],\n            }\n        }\n        case MessageType.Ping:\n            return {\n                type: MessageType.Ping,\n            }\n        case MessageType.Close:\n            return {\n                type: MessageType.Close,\n                allowReconnect: properties.length >= 3 ? properties[2] : undefined,\n                error: properties[1],\n            }\n        case MessageType.CancelInvocation:\n            return {\n                type: MessageType.CancelInvocation,\n                invocationId: properties[2],\n            }\n        case MessageType.StreamInvocation:\n            return {\n                type: MessageType.StreamInvocation,\n                invocationId: properties[2],\n                target: properties[3],\n                arguments: properties[4],\n            }\n        default:\n            // Future protocol changes can add message types, old clients can ignore them\n            console.log(\"Unknown message type '\" + messageType + \"' ignored.\")\n            return null\n    }\n}\n\ntype MessageHeaders = Record<string, string>\n\n// const readHeaders = (properties: any): MessageHeaders => {\n//     const headers: MessageHeaders = properties[1] as MessageHeaders\n//     if (typeof headers !== 'object') {\n//         throw new Error('Invalid headers.')\n//     }\n//     return headers\n// }\n"],"mappings":"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","names":["client"]}