UNPKG

@eclipse-glsp/client

Version:

A sprotty-based client for GLSP

195 lines 8.79 kB
"use strict"; /******************************************************************************** * Copyright (c) 2023-2024 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 ********************************************************************************/ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.GLSPModelSource = exports.OptionalAction = exports.ServerAction = void 0; const sprotty_1 = require("@eclipse-glsp/sprotty"); const inversify_1 = require("inversify"); var ServerAction; (function (ServerAction) { function is(object) { return sprotty_1.Action.is(object) && '__receivedFromServer' in object && object.__receivedFromServer === true; } ServerAction.is = is; /** * Mark the given action as {@link ServerAction} by attaching the "__receivedFromServer" property * @param action The action that should be marked as server action */ function mark(action) { action.__receivedFromServer = true; } ServerAction.mark = mark; })(ServerAction || (exports.ServerAction = ServerAction = {})); var OptionalAction; (function (OptionalAction) { function is(object) { return sprotty_1.Action.is(object) && '__skipErrorIfNoHandler' in object && object.__skipErrorIfNoHandler === true; } OptionalAction.is = is; /** * Mark the given action as {@link OptionalAction} by attaching the "__skipErrorIfNoHandler" property * @param action The action that should be marked as optional action */ function mark(action) { action.__skipErrorIfNoHandler = true; return action; } OptionalAction.mark = mark; })(OptionalAction || (exports.OptionalAction = OptionalAction = {})); /** * Central component for enabling the client-server action flow with the help of an underlying {@link GLSPClient}. * Handles & forwards actions that are intended for the GLSP server. In addition, it handles {@link ActionMessage}s received * from the server and dispatches the corresponding actions locally. * * Note that in sprotty a {@link ModelSource} is serving the model to the event cycle and * is used to commit the local (i.e. client-side) model back to the source. * However, in GLSP the update flow is reversed meaning that changes to the source model are applied * on the server side and then an update is sent to the client. */ let GLSPModelSource = class GLSPModelSource extends sprotty_1.ModelSource { constructor() { super(...arguments); this.toDispose = new sprotty_1.DisposableCollection(); } get diagramType() { return this.options.diagramType; } get sourceUri() { return this.options.sourceUri; } /** * Configure forwarding of server-handled actions to the given {@link GLSPClient} and * handling of action received from the `GLSPClient` (i.e. server). It is expected that the * given GLSP client has already been initialized. * @param glspClient The GLSP to use. * @throws An error if the given `GLSPClient` has not been initialized yet or if the set of server handled * action kinds could not be derived from the initialize result */ configure(glspClient) { this.glspClient = glspClient; if (!glspClient.initializeResult) { throw new Error('Could not configure model source. The GLSP client is not initialized yet!'); } const initializeParams = this.createInitializeClientSessionParameters(glspClient.initializeResult); this.configureServeActions(glspClient.initializeResult); this.toDispose.push(glspClient.onActionMessage(message => this.messageReceived(message), this.clientId), sprotty_1.Disposable.create(() => glspClient.disposeClientSession(this.createDisposeClientSessionParameters()))); return glspClient.initializeClientSession(initializeParams); } createInitializeClientSessionParameters(_initializeResult) { const clientActionKinds = this.registry.getHandledActionKinds(); return { clientSessionId: this.clientId, clientActionKinds, diagramType: this.diagramType }; } createDisposeClientSessionParameters() { return { clientSessionId: this.clientId }; } configureServeActions(initializeResult) { const serverActions = initializeResult.serverActions[this.diagramType]; if ((serverActions === null || serverActions === void 0 ? void 0 : serverActions.length) === 0) { throw new Error(`No server-handled actions could be derived from the initialize result for diagramType: ${this.diagramType}!`); } serverActions.forEach(action => this.registry.register(action, this)); } messageReceived(message) { if (this.clientId !== message.clientId) { return; } const action = message.action; ServerAction.mark(action); this.logger.log(this, 'receiving', action); this.actionDispatcher.dispatch(action); } initialize(registry) { var _a; // Registering actions here is discouraged and it's recommended // to implemented dedicated action handlers. if (!this.clientId) { this.clientId = (_a = this.options.clientId) !== null && _a !== void 0 ? _a : this.viewerOptions.baseDiv; } this.registry = registry; } handle(action) { // Handling additional actions here is discouraged and it's recommended // to implemented dedicated action handlers. if (this.shouldForwardToServer(action)) { this.forwardToServer(action); } } forwardToServer(action) { const message = { clientId: this.clientId, action: action }; this.logger.log(this, 'sending', message); if (this.glspClient) { this.glspClient.sendActionMessage(message); } else { throw new Error('GLSPClient is not connected'); } } shouldForwardToServer(action) { return !ServerAction.is(action); } commitModel(newRoot) { /* In GLSP the model update flow is server-driven. i.e. changes to the graphical model are applied * on server-side an only the server can issue a model update. * The internal/local model should never be committed back to the model source i.e. GLSP server. * => no-op implementation that simply returns the `newRoot` */ this._currentRoot = newRoot; return newRoot; } get model() { return this._currentRoot; } dispose() { this.toDispose.dispose(); } }; exports.GLSPModelSource = GLSPModelSource; __decorate([ (0, inversify_1.inject)(sprotty_1.TYPES.ILogger), __metadata("design:type", Object) ], GLSPModelSource.prototype, "logger", void 0); __decorate([ (0, inversify_1.inject)(sprotty_1.TYPES.IDiagramOptions), __metadata("design:type", Object) ], GLSPModelSource.prototype, "options", void 0); __decorate([ (0, inversify_1.preDestroy)(), __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], GLSPModelSource.prototype, "dispose", null); exports.GLSPModelSource = GLSPModelSource = __decorate([ (0, inversify_1.injectable)() ], GLSPModelSource); //# sourceMappingURL=glsp-model-source.js.map