@eclipse-emfcloud/modelserver-client
Version:
Typescript rest client to interact with an EMF.cloud modelserver
255 lines • 12.7 kB
JavaScript
;
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