UNPKG

@eclipse-emfcloud/modelserver-client

Version:

Typescript rest client to interact with an EMF.cloud modelserver

255 lines 12.7 kB
"use strict"; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ModelServerClient = void 0; /******************************************************************************** * Copyright (c) 2021-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 * https://www.eclipse.org/legal/epl-2.0, or the MIT License which is * available at https://opensource.org/licenses/MIT. * * SPDX-License-Identifier: EPL-2.0 OR MIT *******************************************************************************/ const axios_1 = __importDefault(require("axios")); const isomorphic_ws_1 = __importDefault(require("isomorphic-ws")); const model_server_client_api_v1_1 = require("./model-server-client-api-v1"); const model_server_message_1 = require("./model-server-message"); const model_server_paths_1 = require("./model-server-paths"); const diagnostic_1 = require("./model/diagnostic"); const type_util_1 = require("./utils/type-util"); /** * A client to interact with a model server. */ class ModelServerClient { constructor() { this.openSockets = new Map(); this.defaultFormat = 'json'; } initialize(baseUrl) { this._baseUrl = baseUrl.clone(); this.restClient = axios_1.default.create(this.getAxisConfig(baseUrl)); } getAxisConfig(baseURL) { return { baseURL: baseURL.toString() }; } get(modeluri, formatOrGuard) { const format = typeof formatOrGuard === 'string' ? formatOrGuard : this.defaultFormat; const mapper = createMapper(formatOrGuard); return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.MODEL_CRUD, { params: { modeluri, format } }), mapper); } getAll(formatOrGuard) { let modelMapper; let format = 'json'; if (typeof formatOrGuard === 'string') { format = formatOrGuard; modelMapper = (model) => mapModel(model, undefined, true); } else if (typeof formatOrGuard === 'function') { modelMapper = (model) => mapModel(model, formatOrGuard); } else { modelMapper = (model) => mapModel(model); } const messageMapper = (message) => model_server_message_1.MessageDataMapper.asModelArray(message).map(modelMapper); return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.MODEL_CRUD, { params: { format } }), messageMapper); } getModelUris() { return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.MODEL_URIS), model_server_message_1.MessageDataMapper.asURIArray); } getElementById(modeluri, elementid, formatOrGuard) { const format = typeof formatOrGuard === 'string' ? formatOrGuard : this.defaultFormat; const mapper = createMapper(formatOrGuard); return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.MODEL_ELEMENT, { params: { modeluri, elementid, format } }), mapper); } getElementByName(modeluri, elementname, formatOrGuard) { const format = typeof formatOrGuard === 'string' ? formatOrGuard : this.defaultFormat; const mapper = createMapper(formatOrGuard); return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.MODEL_ELEMENT, { params: { modeluri, elementname, format } }), mapper); } create(modeluri, model, formatOrGuard) { const format = typeof formatOrGuard === 'string' ? formatOrGuard : this.defaultFormat; const mapper = createMapper(formatOrGuard); return this.process(this.restClient.post(model_server_paths_1.ModelServerPaths.MODEL_CRUD, { data: model }, { params: { modeluri, format } }), mapper); } update(modeluri, model, formatOrGuard) { const format = typeof formatOrGuard === 'string' ? formatOrGuard : this.defaultFormat; const mapper = createMapper(formatOrGuard); return this.process(this.restClient.patch(model_server_paths_1.ModelServerPaths.MODEL_CRUD, { data: model }, { params: { modeluri, format } }), mapper); } delete(modeluri) { return this.process(this.restClient.delete(model_server_paths_1.ModelServerPaths.MODEL_CRUD, { params: { modeluri } }), model_server_message_1.MessageDataMapper.isSuccess); } close(modeluri) { return this.process(this.restClient.post(model_server_paths_1.ModelServerPaths.CLOSE, undefined, { params: { modeluri } }), model_server_message_1.MessageDataMapper.isSuccess); } save(modeluri) { return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.SAVE, { params: { modeluri } }), model_server_message_1.MessageDataMapper.isSuccess); } saveAll() { return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.SAVE_ALL), model_server_message_1.MessageDataMapper.isSuccess); } validate(modeluri) { return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.VALIDATION, { params: { modeluri } }), response => model_server_message_1.MessageDataMapper.as(response, diagnostic_1.Diagnostic.is)); } getValidationConstraints(modeluri) { return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.VALIDATION_CONSTRAINTS, { params: { modeluri } }), model_server_message_1.MessageDataMapper.asString); } getTypeSchema(modeluri) { return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.TYPE_SCHEMA, { params: { modeluri } }), model_server_message_1.MessageDataMapper.asString); } getUiSchema(schemaname) { return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.UI_SCHEMA, { params: { schemaname } }), model_server_message_1.MessageDataMapper.asString); } configureServer(configuration) { var _a; return this.process(this.restClient.put(model_server_paths_1.ModelServerPaths.SERVER_CONFIGURE, { workspaceRoot: configuration.workspaceRoot.toString(), uiSchemaFolder: (_a = configuration.uiSchemaFolder) === null || _a === void 0 ? void 0 : _a.toString() }), model_server_message_1.MessageDataMapper.isSuccess); } ping() { return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.SERVER_PING), model_server_message_1.MessageDataMapper.isSuccess); } edit(modeluri, command) { return this.process(this.restClient.patch(model_server_paths_1.ModelServerPaths.EDIT, { data: command }, { params: { modeluri, format: this.defaultFormat } }), model_server_message_1.MessageDataMapper.isSuccess); } undo(modeluri) { return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.UNDO, { params: { modeluri } }), model_server_message_1.MessageDataMapper.asString); } redo(modeluri) { return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.REDO, { params: { modeluri } }), model_server_message_1.MessageDataMapper.asString); } send(modeluri, message) { const openSocket = this.openSockets.get(modeluri.toString()); if (openSocket) { openSocket.send(JSON.stringify(message)); return true; } return false; } subscribe(modeluri, options = {}) { if (!options.listener) { const errorMsg = `${modeluri.toString()} : Cannot subscribe. No listener is present!'`; throw new Error(errorMsg); } if (this.isSocketOpen(modeluri)) { const errorMsg = `${modeluri.toString()} : Cannot open new socket, already subscribed!'`; console.warn(errorMsg); if (options.errorWhenUnsuccessful) { throw new Error(errorMsg); } } const path = this.createSubscriptionPath(modeluri, options); this.doSubscribe(options.listener, modeluri, path); } unsubscribe(modeluri) { const openSocket = this.openSockets.get(modeluri.toString()); if (openSocket) { openSocket.close(); this.openSockets.delete(modeluri.toString()); return true; } return false; } createSubscriptionPath(modeluri, options) { // eslint-disable-next-line @typescript-eslint/no-unused-vars const { listener } = options, paramOptions = __rest(options, ["listener"]); const subscriptionUri = this._baseUrl.clone(); subscriptionUri.protocol('ws'); subscriptionUri.segment(model_server_paths_1.ModelServerPaths.SUBSCRIPTION); subscriptionUri.addQuery('modeluri', modeluri); subscriptionUri.addQuery('format', options.format || this.defaultFormat); Object.entries(paramOptions).forEach(entry => subscriptionUri.addQuery(entry[0], entry[1])); subscriptionUri.removeQuery('errorWhenUnsuccessful'); return subscriptionUri; } doSubscribe(listener, modeluri, path) { const socket = new isomorphic_ws_1.default(path.toString() /* .trim() */); socket.onopen = event => listener.onOpen(modeluri, event); socket.onclose = event => { listener.onClose(modeluri, event); this.openSockets.delete(modeluri.toString()); }; socket.onerror = event => listener.onError(modeluri, event); socket.onmessage = event => listener.onMessage(modeluri, event); this.openSockets.set(modeluri.toString(), socket); } isSocketOpen(modeluri) { return this.openSockets.get(modeluri.toString()) !== undefined; } async process(request, mapper) { const errorResponse = (data) => { if (data.type === 'error') { return new model_server_client_api_v1_1.ModelServerError(data); } return undefined; }; return this.processGeneric(request, mapper, errorResponse); } async processMessageAsData(request) { return this.processGeneric(request, model_server_message_1.IdentityMapper, () => undefined); } async processGeneric(request, mapper, erroResponse) { var _a; try { const response = await request; const modelServerError = erroResponse(response.data); if (modelServerError) { throw modelServerError; } return mapper(response.data); } catch (error) { if (axios_1.default.isAxiosError(error)) { const message = ((_a = error.response) === null || _a === void 0 ? void 0 : _a.data) ? error.response.data : error.message; throw new model_server_client_api_v1_1.ModelServerError(message, error.code); } else { throw error; } } } } exports.ModelServerClient = ModelServerClient; /** * Creates a modelserver message data mapper that maps the response either to a generic JSON object, a specific typed object or string. * The actual mapper is derived from the input parameters. * @param guard * @param toString */ function createMapper(formatOrGuard) { if (typeof formatOrGuard === 'string') { return msg => model_server_message_1.MessageDataMapper.asString(msg); } else if (typeof formatOrGuard === 'function') { const typeGuard = formatOrGuard; return msg => model_server_message_1.MessageDataMapper.as(msg, typeGuard); } return msg => model_server_message_1.MessageDataMapper.asObject(msg); } function mapModel(model, guard, toString = false) { const { modeluri, content } = model; if (guard) { return { modeluri, content: (0, type_util_1.asType)(content, guard) }; } else if (toString) { return { modeluri, content: (0, type_util_1.asString)(content) }; } return { modeluri, content: (0, type_util_1.asObject)(content) }; } //# sourceMappingURL=model-server-client.js.map