UNPKG

@signalapp/mock-server

Version:
117 lines (116 loc) 3.96 kB
"use strict"; // Copyright 2022 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Service = void 0; const assert_1 = __importDefault(require("assert")); const long_1 = __importDefault(require("long")); const debug_1 = __importDefault(require("debug")); const compiled_1 = require("../../../protos/compiled"); const debug = (0, debug_1.default)('mock:ws:service'); const WSMessage = compiled_1.signalservice.WebSocketMessage; class Service { ws; requests = new Map(); lastSentId = 0; constructor(ws) { this.ws = ws; this.ws = ws; this.ws.on('message', async (message) => { try { await this.onMessage(message); } catch (error) { (0, assert_1.default)(error instanceof Error); debug('onMessage error', error.stack); } }); this.ws.once('close', () => this.onClose()); } async send(verb, path, options) { const id = this.lastSentId++; const packet = WSMessage.encode({ type: WSMessage.Type.REQUEST, request: { ...options, verb, path, id: long_1.default.fromNumber(id), }, }).finish(); this.ws.send(packet); return await new Promise((resolve) => this.requests.set(id, resolve)); } async onMessage(raw) { if (!(raw instanceof Uint8Array)) { throw new Error('Unexpected input'); } const message = WSMessage.decode(raw); if (message.type === WSMessage.Type.RESPONSE) { const response = message.response; if (!response) { throw new Error('Expected response in message'); } if (!response.id) { throw new Error('Expected response.id'); } const id = parseInt(response.id.toString(), 10); if (isNaN(id)) { throw new Error(`Invalid response.id: ${response.id}`); } const resolve = this.requests.get(id); if (!resolve) { throw new Error(`Unexpected response: ${id}`); } resolve(response); } else if (message.type === WSMessage.Type.REQUEST) { const request = message.request; if (!request) { throw new Error('Expected request in message'); } if (!request.id) { throw new Error('Expected request.id'); } let response; try { response = await this.handleRequest(request); } catch (error) { (0, assert_1.default)(error instanceof Error); console.error('handleRequest error', error.stack); response = { status: 500, body: Buffer.from(JSON.stringify({ error: error.stack, })), }; } // Keepalive responses const packet = WSMessage.encode({ type: WSMessage.Type.RESPONSE, response: { ...response, id: request.id, }, }).finish(); this.ws.send(packet); } else { debug('unsupported message', message); } } onClose() { for (const [id, resolve] of this.requests.entries()) { resolve({ id: long_1.default.fromNumber(id), status: 500, message: 'WebSocket is gone', }); } } } exports.Service = Service;