UNPKG

@eclipse-glsp/protocol

Version:

The protocol definition for client-server communication in GLSP

191 lines 7.62 kB
"use strict"; /******************************************************************************** * Copyright (c) 2023 EclipseSource 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.BaseGLSPClient = exports.GLOBAL_HANDLER_ID = void 0; const sprotty_protocol_1 = require("sprotty-protocol"); const vscode_jsonrpc_1 = require("vscode-jsonrpc"); const array_util_1 = require("../utils/array-util"); const event_1 = require("../utils/event"); const glsp_client_1 = require("./glsp-client"); exports.GLOBAL_HANDLER_ID = '*'; /** * A simple {@link GLSPClient} implementation for use cases where the client & server are running * in the same context/process without a communication layer (like json-rpc) between. The client * directly communicates with a given {@link GLSPServer} instance. */ class BaseGLSPClient { get onServerInitialized() { return this.onServerInitializedEmitter.event; } get onCurrentStateChanged() { return this.onCurrentStateChangedEmitter.event; } set state(state) { if (this._state !== state) { this._state = state; this.onCurrentStateChangedEmitter.fire(state); } } get state() { return this._state; } get checkedServer() { this.checkState(); if (!this._server) { throw new Error(`No server is configured for GLSPClient with id '${this.id}'`); } return this._server; } get initializeResult() { return this._initializeResult; } constructor(options) { this.options = options; this.serverDeferred = new sprotty_protocol_1.Deferred(); this.onStartDeferred = new sprotty_protocol_1.Deferred(); this.onStopDeferred = new sprotty_protocol_1.Deferred(); this.startupTimeout = 1500; this.actionMessageHandlers = new Map([[exports.GLOBAL_HANDLER_ID, []]]); this.onServerInitializedEmitter = new event_1.Emitter(); this.onCurrentStateChangedEmitter = new event_1.Emitter(); this.state = glsp_client_1.ClientState.Initial; this.proxy = this.createProxy(); } createProxy() { return { process: message => { var _a; const handlers = (_a = this.actionMessageHandlers.get(message.clientId)) !== null && _a !== void 0 ? _a : this.actionMessageHandlers.get(exports.GLOBAL_HANDLER_ID); if (!handlers) { console.warn('No ActionMessageHandler is configured- Cannot process server message', message); return; } handlers.forEach(handler => handler(message)); } }; } configureServer(server) { if (this.state === glsp_client_1.ClientState.Running) { throw new Error('Could not configure new server. The GLSPClient is already running'); } this.serverDeferred.resolve(server); } start() { if (this.state === glsp_client_1.ClientState.Running || this.state === glsp_client_1.ClientState.Starting) { return this.onStartDeferred.promise; } this.state = glsp_client_1.ClientState.Starting; const timeOut = new Promise((_, reject) => setTimeout(() => { reject(new Error('Could not start client. No server is configured')); }, this.startupTimeout)); Promise.race([this.serverDeferred.promise, timeOut]) .then(server => { this._server = server; this.state = glsp_client_1.ClientState.Running; this.onStartDeferred.resolve(); }) .catch(error => { this.state = glsp_client_1.ClientState.StartFailed; this.onStartDeferred.reject(error); }); return this.onStartDeferred.promise; } async initializeServer(params) { if (this.initializeResult) { return this.initializeResult; } else if (this.pendingServerInitialize) { return this.pendingServerInitialize; } const initializeDeferred = new sprotty_protocol_1.Deferred(); try { this.pendingServerInitialize = initializeDeferred.promise; this._initializeResult = await this.checkedServer.initialize(params); this.onServerInitializedEmitter.fire(this._initializeResult); initializeDeferred.resolve(this._initializeResult); this.pendingServerInitialize = undefined; } catch (error) { initializeDeferred.reject(error); this._initializeResult = undefined; this.pendingServerInitialize = undefined; } return initializeDeferred.promise; } initializeClientSession(params) { return this.checkedServer.initializeClientSession(params); } disposeClientSession(params) { return this.checkedServer.disposeClientSession(params); } shutdownServer() { this.checkedServer.shutdown(); } async stop() { if (this.state === glsp_client_1.ClientState.Stopped || this.state === glsp_client_1.ClientState.Stopping) { return this.onStop(); } this.state = glsp_client_1.ClientState.Stopping; try { if (this._server) { this._server.shutdown(); } } finally { this.state = glsp_client_1.ClientState.Stopped; this.onStopDeferred.resolve(); } } sendActionMessage(message) { this.checkedServer.process(message); } onActionMessage(handler, clientId) { if (!clientId) { (0, array_util_1.distinctAdd)(this.actionMessageHandlers.get(exports.GLOBAL_HANDLER_ID), handler); return vscode_jsonrpc_1.Disposable.create(() => (0, array_util_1.remove)(this.actionMessageHandlers.get(exports.GLOBAL_HANDLER_ID), handler)); } if (!this.actionMessageHandlers.has(clientId)) { this.actionMessageHandlers.set(clientId, [handler]); } else { (0, array_util_1.distinctAdd)(this.actionMessageHandlers.get(clientId), handler); } return vscode_jsonrpc_1.Disposable.create(() => (0, array_util_1.remove)(this.actionMessageHandlers.get(clientId), handler)); } get currentState() { return this.state; } onStart() { return this.onStartDeferred.promise; } onStop() { return this.onStopDeferred.promise; } get id() { return this.options.id; } checkState() { if (this.state !== glsp_client_1.ClientState.Running) { throw new Error(`Client with id '${this.id}' is not in 'Running' state`); } } setStartupTimeout(ms) { this.startupTimeout = ms; } } exports.BaseGLSPClient = BaseGLSPClient; //# sourceMappingURL=base-glsp-client.js.map