UNPKG

@eclipse-glsp/protocol

Version:

The protocol definition for client-server communication in GLSP

157 lines 6.01 kB
"use strict"; /******************************************************************************** * Copyright (c) 2023 STMicroelectronics and others. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0. * * This Source Code may also be made available under the following Secondary * Licenses when the conditions for such availability set forth in the Eclipse * Public License v. 2.0 are satisfied: GNU General Public License, version 2 * with the GNU Classpath Exception which is available at * https://www.gnu.org/software/classpath/license.html. * * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ Object.defineProperty(exports, "__esModule", { value: true }); exports.listen = exports.createWebSocketConnection = exports.WebSocketMessageWriter = exports.WebSocketMessageReader = exports.wrap = void 0; // based on https://github.com/TypeFox/monaco-languageclient/blob/vwj-2.0.1/packages/vscode-ws-jsonrpc/src/socket/reader.ts /* -------------------------------------------------------------------------------------------- * Copyright (c) 2018-2022 TypeFox GmbH (http://www.typefox.io). All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. * ------------------------------------------------------------------------------------------ */ const vscode_jsonrpc_1 = require("vscode-jsonrpc"); /** * Creates a {@link WebSocketWrapper} for the given plain WebSocket * @param socket The socket to wrap */ function wrap(socket) { return { send: content => socket.send(content), onMessage: cb => (socket.onmessage = event => cb(event.data)), onClose: cb => (socket.onclose = event => cb(event.code, event.reason)), onError: cb => (socket.onerror = event => { if ('error' in event) { cb(event.error); } }), dispose: () => socket.close() }; } exports.wrap = wrap; /** * A `vscode-jsonrpc` {@link MessageReader} that reads messages from an underlying {@link WebSocketWrapper}. */ class WebSocketMessageReader extends vscode_jsonrpc_1.AbstractMessageReader { constructor(socket) { super(); this.socket = socket; this.state = 'initial'; this.eventQueue = []; this.socket.onMessage(message => this.handleMessage(message)); this.socket.onError(error => this.fireError(error)); this.socket.onClose(() => this.fireClose()); } listen(callback) { if (this.state === 'initial') { this.state = 'listening'; this.callback = callback; this.eventQueue.forEach(event => { if (event.message) { this.handleMessage(event.message); } else if (event.error) { this.fireError(event.error); } else { this.fireClose(); } }); this.eventQueue = []; } return vscode_jsonrpc_1.Disposable.create(() => { this.callback = undefined; this.eventQueue = []; }); } handleMessage(message) { if (this.state === 'initial') { this.eventQueue.push({ message }); } else if (this.state === 'listening') { const data = JSON.parse(message); this.callback(data); } } fireError(error) { if (this.state === 'initial') { this.eventQueue.push({ error }); } else if (this.state === 'listening') { super.fireError(error); } } fireClose() { if (this.state === 'initial') { this.eventQueue.push({}); } else if (this.state === 'listening') { super.fireClose(); } this.state = 'closed'; } } exports.WebSocketMessageReader = WebSocketMessageReader; /** * A `vscode-jsonrpc` {@link MessageReader} that writes messages to an underlying {@link WebSocketWrapper}. */ class WebSocketMessageWriter extends vscode_jsonrpc_1.AbstractMessageWriter { constructor(socket) { super(); this.socket = socket; this.errorCount = 0; } end() { /** no-op */ } async write(msg) { try { const content = JSON.stringify(msg); this.socket.send(content); } catch (e) { this.errorCount++; this.fireError(e, msg, this.errorCount); } } } exports.WebSocketMessageWriter = WebSocketMessageWriter; /** * Create a `vscode-jsonrpc` {@link MessageConnection} on top of a given {@link WebSocketWrapper}. */ function createWebSocketConnection(socket, logger) { const reader = new WebSocketMessageReader(socket); const writer = new WebSocketMessageWriter(socket); return (0, vscode_jsonrpc_1.createMessageConnection)(reader, writer, logger); } exports.createWebSocketConnection = createWebSocketConnection; /** * Creates a new {@link MessageConnection} on top of the given websocket on open. * @param webSocket The target webSocket * @param onConnection Optional callback that is invoked after the connection has been created * @param logger Optional connection logger * @returns A promise of the created connection */ function listen(webSocket, onConnection, logger) { return new Promise(resolve => { webSocket.onopen = () => { const socket = wrap(webSocket); const connection = createWebSocketConnection(socket, logger); onConnection === null || onConnection === void 0 ? void 0 : onConnection(connection); resolve(connection); }; }); } exports.listen = listen; //# sourceMappingURL=websocket-connection.js.map