Socket
Socket
Sign inDemoInstall

@eclipse-emfcloud/modelserver-client

Package Overview
Dependencies
10
Maintainers
8
Versions
40
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.8.0-next.ccd36ac2 to 0.8.0-next.d7db15a.92

lib/utils/index.d.ts

18

lib/index.d.ts

@@ -1,2 +0,2 @@

/*********************************************************************************
/********************************************************************************
* Copyright (c) 2021-2022 STMicroelectronics and others.

@@ -10,18 +10,18 @@ *

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
export * from './model/base-model';
export * from './model/change-model';
export * from './model/command-model';
export * from './model/diagnostic';
export * from './model-server-client';
export * from './model-server-client-v2';
export * from './model-server-client-api-v1';
export * from './model-server-client-api-v2';
export * from './model-server-client-v2';
export * from './model-server-message';
export * from './model-server-notification';
export * from './model-server-paths';
export * from './model-server-message';
export * from './model/base-model';
export * from './model/change-model';
export * from './model/command-model';
export * from './model/diagnostic';
export * from './subscription-listener';
export * from './utils/model-server-utils';
export * from './utils/patch-utils';
export * from './utils/type-util';
export * from './utils/patch-utils';
//# sourceMappingURL=index.d.ts.map
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {

@@ -10,6 +14,6 @@ if (k2 === undefined) k2 = k;

var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p);
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
/*********************************************************************************
/********************************************************************************
* Copyright (c) 2021-2022 STMicroelectronics and others.

@@ -23,18 +27,18 @@ *

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
__exportStar(require("./model/base-model"), exports);
__exportStar(require("./model/change-model"), exports);
__exportStar(require("./model/command-model"), exports);
__exportStar(require("./model/diagnostic"), exports);
__exportStar(require("./model-server-client"), exports);
__exportStar(require("./model-server-client-v2"), exports);
__exportStar(require("./model-server-client-api-v1"), exports);
__exportStar(require("./model-server-client-api-v2"), exports);
__exportStar(require("./model-server-client-v2"), exports);
__exportStar(require("./model-server-message"), exports);
__exportStar(require("./model-server-notification"), exports);
__exportStar(require("./model-server-paths"), exports);
__exportStar(require("./model-server-message"), exports);
__exportStar(require("./model/base-model"), exports);
__exportStar(require("./model/change-model"), exports);
__exportStar(require("./model/command-model"), exports);
__exportStar(require("./model/diagnostic"), exports);
__exportStar(require("./subscription-listener"), exports);
__exportStar(require("./utils/model-server-utils"), exports);
__exportStar(require("./utils/patch-utils"), exports);
__exportStar(require("./utils/type-util"), exports);
__exportStar(require("./utils/patch-utils"), exports);
//# sourceMappingURL=index.js.map

@@ -1,2 +0,2 @@

/*********************************************************************************
/********************************************************************************
* Copyright (c) 2021-2022 STMicroelectronics and others.

@@ -10,3 +10,4 @@ *

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
import URI from 'urijs';
import { Model, ModelServerMessage } from './model-server-message';

@@ -31,3 +32,3 @@ import { ModelServerCommand } from './model/command-model';

*/
initialize(baseUrl: string, defaultFormat?: string): void | Promise<void>;
initialize(baseUrl: URI, defaultFormat?: string): void | Promise<void>;
/**

@@ -58,3 +59,3 @@ * Retrieves all available {@link Model}s of the current workspace as plain JSON objects.

*/
get(modeluri: string): Promise<AnyObject>;
get(modeluri: URI): Promise<AnyObject>;
/**

@@ -68,3 +69,3 @@ * Retrieves the {@link Model} for a given URI as typed JSON object

*/
get<M>(modeluri: string, typeGuard: TypeGuard<M>): Promise<M>;
get<M>(modeluri: URI, typeGuard: TypeGuard<M>): Promise<M>;
/**

@@ -77,3 +78,3 @@ * Retrieves the {@link Model} for a given URI in string representation derived from a given format (e.g. 'xml' or 'json').

*/
get(modeluri: string, format: string): Promise<string>;
get(modeluri: URI, format: string): Promise<string>;
/**

@@ -83,3 +84,3 @@ * Retrieves the URIs of all available {@link Model}s of the current workspace.

*/
getModelUris(): Promise<string[]>;
getModelUris(): Promise<URI[]>;
/**

@@ -92,3 +93,3 @@ * Retrieves a specific model (sub)element by its `id` as plain JSON object.

*/
getElementById(modeluri: string, elementid: string): Promise<AnyObject>;
getElementById(modeluri: URI, elementid: string): Promise<AnyObject>;
/**

@@ -103,3 +104,3 @@ * Retrieves a specific model (sub)element by its `id` as typed JSON object.

*/
getElementById<M>(modeluri: string, elementid: string, typeGuard: TypeGuard<M>): Promise<M>;
getElementById<M>(modeluri: URI, elementid: string, typeGuard: TypeGuard<M>): Promise<M>;
/**

@@ -113,3 +114,3 @@ * Retrieves a specific model (sub)element by its `id` in string representation derived from a given format (e.g. 'xml' or 'json').

*/
getElementById(modeluri: string, elementid: string, format: string): Promise<string>;
getElementById(modeluri: URI, elementid: string, format: string): Promise<string>;
/**

@@ -122,3 +123,3 @@ * Retrieves a specific model (sub)element by its `name` as plain JSON object.

*/
getElementByName(modeluri: string, elementname: string): Promise<AnyObject>;
getElementByName(modeluri: URI, elementname: string): Promise<AnyObject>;
/**

@@ -133,3 +134,3 @@ * Retrieves a specific model (sub)element by its `name` as typed JSON object.

*/
getElementByName<M>(modeluri: string, elementname: string, typeGuard: TypeGuard<M>, format?: string): Promise<M>;
getElementByName<M>(modeluri: URI, elementname: string, typeGuard: TypeGuard<M>, format?: string): Promise<M>;
/**

@@ -143,3 +144,3 @@ * Retrieves a specific model (sub)element by its `name` in string representation derived from a given format (e.g. 'xml' or 'json').

*/
getElementByName(modeluri: string, elementname: string, format: string): Promise<string>;
getElementByName(modeluri: URI, elementname: string, format: string): Promise<string>;
/**

@@ -150,3 +151,3 @@ * Deletes the {@link Model} with the given URI from the current workspace.

*/
delete(modeluri: string): Promise<boolean>;
delete(modeluri: URI): Promise<boolean>;
/**

@@ -157,3 +158,3 @@ * Closes (i.e. unloads) the model with the given URI from the current workspace. This discards all dirty changes.

*/
close(modeluri: string): Promise<boolean>;
close(modeluri: URI): Promise<boolean>;
/**

@@ -165,3 +166,3 @@ * Creates a new model object with the given URI and content object in the current workspace.

*/
create(modeluri: string, model: AnyObject | string): Promise<AnyObject>;
create(modeluri: URI, model: AnyObject | string): Promise<AnyObject>;
/**

@@ -176,3 +177,3 @@ * Creates a new model object with the given URI and content object in the current workspace.

*/
create<M>(modeluri: string, model: AnyObject | string, typeGuard: TypeGuard<M>): Promise<M>;
create<M>(modeluri: URI, model: AnyObject | string, typeGuard: TypeGuard<M>): Promise<M>;
/**

@@ -186,3 +187,3 @@ * Creates a new model object with the given URI and content string in the current workspace.

*/
create(modeluri: string, model: string, format: string): Promise<string>;
create(modeluri: URI, model: string, format: string): Promise<string>;
/**

@@ -195,3 +196,3 @@ * Updates an existing model with the given URI with the given content in the current workspace.

*/
update(modeluri: string, model: AnyObject | string): Promise<AnyObject>;
update(modeluri: URI, model: AnyObject | string): Promise<AnyObject>;
/**

@@ -207,3 +208,3 @@ * Updates an existing model with the given URI with the given content in the current workspace.

*/
update<M>(modeluri: string, model: string | string, typeGuard: TypeGuard<M>): Promise<M>;
update<M>(modeluri: URI, model: string | string, typeGuard: TypeGuard<M>): Promise<M>;
/**

@@ -217,3 +218,3 @@ * Updates an existing model with the given URI with the given content string in the current workspace.

*/
update(modeluri: string, model: string, format: string): Promise<AnyObject>;
update(modeluri: URI, model: string, format: string): Promise<AnyObject>;
/**

@@ -224,3 +225,3 @@ * Persists all `dirty` changes for the model with the given URI.

*/
save(modeluri: string): Promise<boolean>;
save(modeluri: URI): Promise<boolean>;
/**

@@ -236,3 +237,3 @@ * Saves (i.e. persists the dirty changes of) all models that are loaded in the current workspace.

*/
validate(modeluri: string): Promise<Diagnostic>;
validate(modeluri: URI): Promise<Diagnostic>;
/**

@@ -243,3 +244,3 @@ * Retrieves the EMF validation constraints for the model with the given URI

*/
getValidationConstraints(modeluri: string): Promise<string>;
getValidationConstraints(modeluri: URI): Promise<string>;
/**

@@ -252,3 +253,3 @@ * Retrieves the JSON schema representation of the Ecore model with the given URI.

*/
getTypeSchema(modeluri: string): Promise<string>;
getTypeSchema(modeluri: URI): Promise<string>;
/**

@@ -278,3 +279,3 @@ * Retrieves the JSONForms UI schema for the given EClass literal.

*/
edit(modeluri: string, command: ModelServerCommand): Promise<boolean>;
edit(modeluri: URI, command: ModelServerCommand): Promise<boolean>;
/**

@@ -285,3 +286,3 @@ * Can be used to undo the latest edit change (i.e. command execution) for the model with the given URI.

*/
undo(modeluri: string): Promise<string>;
undo(modeluri: URI): Promise<string>;
/**

@@ -292,3 +293,3 @@ * Can be used to redo the latest edit change (i.e. command execution) for the model with the given URI.

*/
redo(modeluri: string): Promise<string>;
redo(modeluri: URI): Promise<string>;
/**

@@ -300,10 +301,10 @@ * Can be used to subscribe for model server notifications for the model with the given URI. For subscription communication

*/
subscribe(modeluri: string, options?: SubscriptionOptions): void;
subscribe(modeluri: URI, options?: SubscriptionOptions): void;
/**
* Can be used to send arbitrary {@link ModelServerMessage}s to the model server via a subscription channel.
* @param modelUri The URI of the subscribed model.
* @param modeluri The URI of the subscribed model.
* @param message The model server message that should be sent.
* @returns A boolean indicating whether the message submission was successful.
*/
send(modelUri: string, message: ModelServerMessage): boolean;
send(modeluri: URI, message: ModelServerMessage): boolean;
/**

@@ -314,6 +315,6 @@ * Can be used to unsubscribe from model server notifications for the model with the given URI.

*/
unsubscribe(modelUri: string): boolean;
unsubscribe(modeluri: URI): boolean;
}
export declare namespace ModelServerClientApiV1 {
const API_ENDPOINT = "/api/v1";
const API_ENDPOINT = "api/v1";
}

@@ -337,4 +338,4 @@ /**

export interface ServerConfiguration {
workspaceRoot: string;
uiSchemaFolder?: string;
workspaceRoot: URI;
uiSchemaFolder?: URI;
}

@@ -341,0 +342,0 @@ /**

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ModelServerError = exports.ModelServerClientApiV1 = void 0;
/*********************************************************************************
* Copyright (c) 2021-2022 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 model_server_message_1 = require("./model-server-message");
var ModelServerClientApiV1;
(function (ModelServerClientApiV1) {
ModelServerClientApiV1.API_ENDPOINT = '/api/v1';
ModelServerClientApiV1.API_ENDPOINT = 'api/v1';
})(ModelServerClientApiV1 = exports.ModelServerClientApiV1 || (exports.ModelServerClientApiV1 = {}));

@@ -19,0 +9,0 @@ /**

@@ -1,2 +0,2 @@

/*********************************************************************************
/********************************************************************************
* Copyright (c) 2022 STMicroelectronics and others.

@@ -10,9 +10,10 @@ *

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
import { Operation } from 'fast-json-patch';
import { ServerConfiguration, SubscriptionOptions } from './model-server-client-api-v1';
import { Model, ModelServerMessage } from './model-server-message';
import URI from 'urijs';
import { ModelServerElement } from './model/base-model';
import { ModelServerCommand } from './model/command-model';
import { Diagnostic } from './model/diagnostic';
import { ServerConfiguration, SubscriptionOptions } from './model-server-client-api-v1';
import { Model, ModelServerMessage } from './model-server-message';
import { SubscriptionListener } from './subscription-listener';

@@ -33,6 +34,28 @@ import { AnyObject, TypeGuard } from './utils/type-util';

/** JSON formats supported by the V2 client API. */
export declare type JsonFormat = 'json' | 'json-v2';
export type JsonFormat = 'json' | 'json-v2';
/** Message formats supported by the V2 client API. */
export declare type Format = string;
export type Format = string;
/**
* Additional subscription options supported by API v2 model subscriptions.
*/
export interface SubscriptionOptionsV2 extends SubscriptionOptions {
/**
* The scheme to use in the `path` property of {@link Operation}s in the
* JSON Patches reported by API V2 queries. Supported values (case insensitive)
* include `'jsonPointer'` (the default for standard JSON Patches) and
* `'uriFragments'` (for a custom EMF-specific scheme based on the URI
* fragments of `EObject`s) .
*/
paths?: string;
}
/**
* A union type that represents all Patches or Commands supported by the model server:
* - Operation
* - Operation[] (Json Patch)
* - ModelPatch
* - ModelPatch[]
* - ModelServerCommand
*/
export type PatchOrCommand = Operation | Operation[] | ModelPatch | ModelPatch[] | ModelServerCommand;
/**
* Basic client API to interact with a model server that conforms to the Modelserver API Version 2.

@@ -44,3 +67,3 @@ */

* The given base url should point to the location of the model server API entry point.
* (e.g. `http://localhost:8081/api/v1/`). Once the initialization is completed the client is expected
* (e.g. `http://localhost:8081/api/v2/`). Once the initialization is completed the client is expected
* to be ready and should be able to handle REST requests to & responses from the model server.

@@ -52,3 +75,3 @@ * Any requests to the model server before the client has been initialized are expected to fail (i.e. throw an error)

*/
initialize(baseUrl: string, defaultFormat?: Format): void | Promise<void>;
initialize(baseUrl: URI, defaultFormat?: Format): void | Promise<void>;
/**

@@ -60,35 +83,47 @@ * Retrieves all available models of the current workspace.

getAll(format: Format): Promise<Model<string>[]>;
get(modeluri: string, format?: Format): Promise<AnyObject>;
get<M>(modeluri: string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
getModelUris(): Promise<string[]>;
getElementById(modeluri: string, elementid: string, format?: Format): Promise<AnyObject>;
getElementById<M>(modeluri: string, elementid: string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
getElementByName(modeluri: string, elementname: string, format?: Format): Promise<AnyObject>;
getElementByName<M>(modeluri: string, elementname: string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
delete(modeluri: string): Promise<boolean>;
close(modeluri: string): Promise<boolean>;
create(modeluri: string, model: AnyObject | string, format?: Format): Promise<AnyObject>;
create<M>(modeluri: string, model: AnyObject | string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
update(modeluri: string, model: AnyObject | string, format?: Format): Promise<AnyObject>;
update<M>(modeluri: string, model: AnyObject | string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
save(modeluri: string): Promise<boolean>;
get(modeluri: URI, format?: Format): Promise<AnyObject>;
get<M>(modeluri: URI, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
getModelUris(): Promise<URI[]>;
getElementById(modeluri: URI, elementid: string, format?: Format): Promise<AnyObject>;
getElementById<M>(modeluri: URI, elementid: string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
getElementByName(modeluri: URI, elementname: string, format?: Format): Promise<AnyObject>;
getElementByName<M>(modeluri: URI, elementname: string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
delete(modeluri: URI): Promise<boolean>;
close(modeluri: URI): Promise<boolean>;
create(modeluri: URI, model: AnyObject | string, format?: Format): Promise<AnyObject>;
create<M>(modeluri: URI, model: AnyObject | string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
update(modeluri: URI, model: AnyObject | string, format?: Format): Promise<AnyObject>;
update<M>(modeluri: URI, model: AnyObject | string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
save(modeluri: URI): Promise<boolean>;
saveAll(): Promise<boolean>;
validate(modeluri: string): Promise<Diagnostic>;
getValidationConstraints(modeluri: string): Promise<string>;
getTypeSchema(modeluri: string): Promise<string>;
validate(modeluri: URI): Promise<Diagnostic>;
getValidationConstraints(modeluri: URI): Promise<string>;
getTypeSchema(modeluri: URI): Promise<string>;
getUiSchema(schemaname: string): Promise<string>;
configureServer(configuration: ServerConfiguration): Promise<boolean>;
ping(): Promise<boolean>;
edit(modeluri: string, patch: Operation | Operation[], format?: Format): Promise<ModelUpdateResult>;
edit(modeluri: string, command: ModelServerCommand, format?: Format): Promise<ModelUpdateResult>;
undo(modeluri: string): Promise<ModelUpdateResult>;
redo(modeluri: string): Promise<ModelUpdateResult>;
subscribe(modeluri: string, listener: SubscriptionListener, options?: SubscriptionOptions): SubscriptionListener;
send(modelUri: string, message: ModelServerMessage): void;
unsubscribe(modelUri: string): void;
edit(modeluri: URI, patchOrCommand: PatchOrCommand, format?: Format): Promise<ModelUpdateResult>;
undo(modeluri: URI): Promise<ModelUpdateResult>;
redo(modeluri: URI): Promise<ModelUpdateResult>;
subscribe(modeluri: URI, listener: SubscriptionListener, options?: SubscriptionOptionsV2): SubscriptionListener;
send(modeluri: URI, message: ModelServerMessage): void;
unsubscribe(modeluri: URI): void;
}
export declare namespace ModelServerClientApiV2 {
const API_ENDPOINT = "/api/v2";
const API_ENDPOINT = "api/v2";
}
/**
* A patch affecting a specific model.
*/
export interface ModelPatch {
/**
* The uri of the patched model.
*/
modelUri: string;
/**
* The patch describing the changes applied to the model.
*/
patch: Operation[];
}
/**
* Result sent to client after requesting a model update.

@@ -110,5 +145,8 @@ */

* the original model unchanged.
* @param modeluri the uri of the model to patch. This can be used when the model is split in multiple
* resources, to identify the patch to apply. The modeluri should correspond to the oldModel object.
* It can be omitted when patching the main model (or in single-model cases).
* @return the patched model.
*/
patchModel?(oldModel: ModelServerElement, copy?: boolean): ModelServerElement;
patchModel?(oldModel: ModelServerElement, copy?: boolean, modeluri?: URI): ModelServerElement;
/**

@@ -119,3 +157,10 @@ * The Json Patch describing the changes that were applied to the model. Only present if

patch?: Operation[];
/**
* The list of Json Patches describing the changes that were applied to the models. Only present if
* the edit request was successful.
*
* The list contains one entry per modified model. Unmodified models will not contain any entry.
*/
allPatches?: ModelPatch[];
}
//# sourceMappingURL=model-server-client-api-v2.d.ts.map

@@ -18,4 +18,4 @@ "use strict";

(function (ModelServerClientApiV2) {
ModelServerClientApiV2.API_ENDPOINT = '/api/v2';
ModelServerClientApiV2.API_ENDPOINT = 'api/v2';
})(ModelServerClientApiV2 = exports.ModelServerClientApiV2 || (exports.ModelServerClientApiV2 = {}));
//# sourceMappingURL=model-server-client-api-v2.js.map
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {

@@ -17,8 +21,11 @@ if (k2 === undefined) k2 = k;

var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/*********************************************************************************
/********************************************************************************
* Copyright (c) 2022 STMicroelectronics and others.

@@ -32,5 +39,6 @@ *

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
const chai_1 = require("chai");
const fast_json_patch_1 = __importStar(require("fast-json-patch"));
const urijs_1 = __importDefault(require("urijs"));
const _1 = require(".");

@@ -40,3 +48,8 @@ const model_server_client_api_v2_1 = require("./model-server-client-api-v2");

let client;
const baseUrl = `http://localhost:8081${model_server_client_api_v2_1.ModelServerClientApiV2.API_ENDPOINT}`;
const baseUrl = new urijs_1.default({
protocol: 'http',
hostname: 'localhost',
port: '8081',
path: model_server_client_api_v2_1.ModelServerClientApiV2.API_ENDPOINT
});
const testUndoRedo = async (modeluri, originalModel, patchedModel) => {

@@ -47,10 +60,10 @@ // Expected: originalModel === undoModel === patchedUndoModel

const undoModel = await client.get(modeluri, _1.ModelServerObjectV2.is);
chai_1.expect(undoModel).to.deep.equal(originalModel);
(0, chai_1.expect)(undoModel).to.deep.equal(originalModel);
const patchedUndoModel = undoPatch.patchModel(patchedModel, true);
chai_1.expect(patchedUndoModel).to.deep.equal(originalModel);
(0, chai_1.expect)(patchedUndoModel).to.deep.equal(originalModel);
const redoPatch = await client.redo(modeluri);
const redoModel = await client.get(modeluri, _1.ModelServerObjectV2.is);
chai_1.expect(redoModel).to.deep.equal(patchedModel);
(0, chai_1.expect)(redoModel).to.deep.equal(patchedModel);
const patchedRedoModel = redoPatch.patchModel(patchedUndoModel, true);
chai_1.expect(patchedRedoModel).to.deep.equal(patchedModel);
(0, chai_1.expect)(patchedRedoModel).to.deep.equal(patchedModel);
// Restore initial state

@@ -65,32 +78,32 @@ await client.undo(modeluri);

it('edit with patch', async () => {
const modeluri = 'SuperBrewer3000.coffee';
const modeluri = new urijs_1.default('SuperBrewer3000.coffee');
const newName = 'Super Brewer 6000';
const machine = await client.get(modeluri, _1.ModelServerObjectV2.is);
const patch = _1.replace(modeluri, machine, 'name', newName);
const patch = (0, _1.replace)(modeluri, machine, 'name', newName);
await client.edit(modeluri, patch);
const model = await client.get(modeluri);
chai_1.expect(model.name).to.be.equal(newName);
(0, chai_1.expect)(model.name).to.be.equal(newName);
await testUndoRedo(modeluri, machine, model);
});
it('create with patch', async () => {
const modeluri = 'SuperBrewer3000.coffee';
const modeluri = new urijs_1.default('SuperBrewer3000.coffee');
const originalModel = await client.get(modeluri, _1.ModelServerObjectV2.is);
const newWorkflowName = 'New Test Workflow';
const initialWorkflowsCount = originalModel.workflows.length;
const patch = _1.create(modeluri, originalModel, 'workflows', 'http://www.eclipsesource.com/modelserver/example/coffeemodel#//Workflow', { name: newWorkflowName });
const patch = (0, _1.create)(modeluri, originalModel, 'workflows', 'http://www.eclipsesource.com/modelserver/example/coffeemodel#//Workflow', { name: newWorkflowName });
await client.edit(modeluri, patch);
const patchedModel = await client.get(modeluri);
const workflows = patchedModel.workflows;
chai_1.expect(workflows.length).to.be.equal(initialWorkflowsCount + 1);
(0, chai_1.expect)(workflows.length).to.be.equal(initialWorkflowsCount + 1);
const newWorkflow = patchedModel.workflows[initialWorkflowsCount];
chai_1.expect(newWorkflow.name).to.be.equal(newWorkflowName);
chai_1.expect(newWorkflow).to.have.property('$id');
chai_1.expect(newWorkflow.$id).to.be.a('string');
(0, chai_1.expect)(newWorkflow.name).to.be.equal(newWorkflowName);
(0, chai_1.expect)(newWorkflow).to.have.property('$id');
(0, chai_1.expect)(newWorkflow.$id).to.be.a('string');
await testUndoRedo(modeluri, originalModel, patchedModel);
});
it('add with patch', async () => {
const modeluri = 'SuperBrewer3000.coffee';
const modeluri = new urijs_1.default('SuperBrewer3000.coffee');
const initialModel = await client.get(modeluri, _1.ModelServerObjectV2.is);
// Add a second workflow to the model; we'll use it to move a Task from a workflow to the other
const createWorkflow = _1.create(modeluri, initialModel, 'workflows', 'http://www.eclipsesource.com/modelserver/example/coffeemodel#//Workflow', { name: 'New Workflow' });
const createWorkflow = (0, _1.create)(modeluri, initialModel, 'workflows', 'http://www.eclipsesource.com/modelserver/example/coffeemodel#//Workflow', { name: 'New Workflow' });
await client.edit(modeluri, createWorkflow);

@@ -100,3 +113,3 @@ const originalModel = await client.get(modeluri, _1.ModelServerObjectV2.is);

const targetWF = originalModel.workflows[1];
const patch = _1.add(modeluri, targetWF, 'nodes', sourceWF.nodes[0]);
const patch = (0, _1.add)(modeluri, targetWF, 'nodes', sourceWF.nodes[0]);
await client.edit(modeluri, patch);

@@ -106,34 +119,34 @@ const patchedModel = await client.get(modeluri);

const patchedTargetWF = patchedModel.workflows[1];
chai_1.expect(patchedSourceWF.nodes).to.be.undefined;
chai_1.expect(patchedTargetWF.nodes).to.be.an('array').of.length(1);
chai_1.expect(patchedTargetWF.nodes[0].name).to.be.equal(sourceWF.nodes[0].name); // Node was moved
(0, chai_1.expect)(patchedSourceWF.nodes).to.be.undefined;
(0, chai_1.expect)(patchedTargetWF.nodes).to.be.an('array').of.length(1);
(0, chai_1.expect)(patchedTargetWF.nodes[0].name).to.be.equal(sourceWF.nodes[0].name); // Node was moved
await testUndoRedo(modeluri, originalModel, patchedModel);
});
it('delete with patch - index based', async () => {
const modeluri = 'SuperBrewer3000.coffee';
const modeluri = new urijs_1.default('SuperBrewer3000.coffee');
const originalModel = await client.get(modeluri, _1.ModelServerObjectV2.is);
const parentWorkflow = originalModel.workflows[0];
chai_1.expect(parentWorkflow.nodes).to.be.an('array').that.is.not.empty;
const patch = _1.removeValueAt(modeluri, parentWorkflow, 'nodes', 0);
(0, chai_1.expect)(parentWorkflow.nodes).to.be.an('array').that.is.not.empty;
const patch = (0, _1.removeValueAt)(modeluri, parentWorkflow, 'nodes', 0);
await client.edit(modeluri, patch);
const patchedModel = await client.get(modeluri);
const patchedParentWorkflow = patchedModel.workflows[0];
chai_1.expect(patchedParentWorkflow.nodes).to.be.undefined;
(0, chai_1.expect)(patchedParentWorkflow.nodes).to.be.undefined;
await testUndoRedo(modeluri, originalModel, patchedModel);
});
it('delete with patch - object', async () => {
const modeluri = 'SuperBrewer3000.coffee';
const modeluri = new urijs_1.default('SuperBrewer3000.coffee');
const originalModel = await client.get(modeluri, _1.ModelServerObjectV2.is);
const parentWorkflow = originalModel.workflows[0];
chai_1.expect(parentWorkflow.nodes).to.be.an('array').that.is.not.empty;
(0, chai_1.expect)(parentWorkflow.nodes).to.be.an('array').that.is.not.empty;
const valueToRemove = parentWorkflow.nodes[0];
const patch = _1.removeObject(modeluri, valueToRemove);
const patch = (0, _1.removeObject)(modeluri, valueToRemove);
await client.edit(modeluri, patch);
const patchedModel = await client.get(modeluri);
const patchedParentWorkflow = patchedModel.workflows[0];
chai_1.expect(patchedParentWorkflow.nodes).to.be.undefined;
(0, chai_1.expect)(patchedParentWorkflow.nodes).to.be.undefined;
await testUndoRedo(modeluri, originalModel, patchedModel);
});
it('edit with command', async () => {
const modeluri = 'SuperBrewer3000.coffee';
const modeluri = new urijs_1.default('SuperBrewer3000.coffee');
const newName = 'Super Brewer 6000';

@@ -143,3 +156,3 @@ const originalModel = await client.get(modeluri, _1.ModelServerObjectV2.is);

eClass: originalModel.$type,
$ref: `SuperBrewer3000.coffee#${originalModel.$id}`
$ref: urijs_1.default.build({ path: 'SuperBrewer3000.coffee', fragment: originalModel.$id })
};

@@ -149,25 +162,25 @@ const command = new _1.SetCommand(owner, 'name', [newName]);

const model = await client.get(modeluri);
chai_1.expect(model.name).to.be.equal(newName);
(0, chai_1.expect)(model.name).to.be.equal(newName);
await testUndoRedo(modeluri, originalModel, model);
});
it('incremental patch update', async () => {
const modeluri = 'SuperBrewer3000.coffee';
const modeluri = new urijs_1.default('SuperBrewer3000.coffee');
const newName = 'Super Brewer 6000';
const machine = await client.get(modeluri, _1.ModelServerObjectV2.is);
const patch = _1.replace(modeluri, machine, 'name', newName);
const patch = (0, _1.replace)(modeluri, machine, 'name', newName);
const updateResult = await client.edit(modeluri, patch);
chai_1.expect(updateResult.success).to.be.true;
chai_1.expect(updateResult.patchModel).to.not.be.undefined;
chai_1.expect(updateResult.patch).to.not.be.undefined;
(0, chai_1.expect)(updateResult.success).to.be.true;
(0, chai_1.expect)(updateResult.patchModel).to.not.be.undefined;
(0, chai_1.expect)(updateResult.patch).to.not.be.undefined;
// Patch a copy of the model (machine), to make sure the original model is
// unchanged. We'll need it later to check undo/redo behavior.
const patchedMachine = updateResult.patchModel(machine, true);
chai_1.expect(patchedMachine.name).to.be.equal(newName);
(0, chai_1.expect)(patchedMachine.name).to.be.equal(newName);
// Check that the incremental update is consistent with the server version of the model
const newMachine = await client.get(modeluri, _1.ModelServerObjectV2.is);
chai_1.expect(newMachine).to.deep.equal(patchedMachine);
(0, chai_1.expect)(newMachine).to.deep.equal(patchedMachine);
await testUndoRedo(modeluri, machine, patchedMachine);
});
it('subscribe to changes', async () => {
const modeluri = 'SuperBrewer3000.coffee';
const modeluri = new urijs_1.default('SuperBrewer3000.coffee');
const newName = 'Super Brewer 6000';

@@ -177,3 +190,3 @@ const machine = await client.get(modeluri, _1.ModelServerObjectV2.is);

eClass: machine.$type,
$ref: `SuperBrewer3000.coffee#${machine.$id}`
$ref: urijs_1.default.build({ path: 'SuperBrewer3000.coffee', fragment: machine.$id })
};

@@ -195,9 +208,9 @@ const command = new _1.SetCommand(owner, 'name', [newName]);

const patch = notification.patch;
chai_1.expect(notification.modelUri).to.be.equal(modeluri);
chai_1.expect(patch.length).to.be.equal(1);
(0, chai_1.expect)(notification.modeluri.toString()).to.be.equal(modeluri.toString());
(0, chai_1.expect)(patch.length).to.be.equal(1);
const operation = patch[0];
chai_1.expect(_1.Operations.isReplace(operation, 'string')).to.be.equal(true);
chai_1.expect(operation.path).to.be.equal('/name');
(0, chai_1.expect)(_1.Operations.isReplace(operation, 'string')).to.be.equal(true);
(0, chai_1.expect)(operation.path).to.be.equal('/name');
if (_1.Operations.isReplace(operation, 'string')) {
chai_1.expect(operation.value).to.be.equal(newName);
(0, chai_1.expect)(operation.value).to.be.equal(newName);
}

@@ -208,3 +221,3 @@ await client.undo(modeluri);

it('subscribe to incremental updates', async () => {
const modeluri = 'SuperBrewer3000.coffee';
const modeluri = new urijs_1.default('SuperBrewer3000.coffee');
const newName = 'Super Brewer 6000';

@@ -214,3 +227,3 @@ const machine = await client.get(modeluri, _1.ModelServerObjectV2.is);

eClass: machine.$type,
$ref: `SuperBrewer3000.coffee#${machine.$id}`
$ref: urijs_1.default.build({ path: 'SuperBrewer3000.coffee', fragment: machine.$id })
};

@@ -237,3 +250,3 @@ const command = new _1.SetCommand(owner, 'name', [newName]);

// from the model server.
chai_1.expect(incrementalPatchedModel).to.deep.equal(patchedModel);
(0, chai_1.expect)(incrementalPatchedModel).to.deep.equal(patchedModel);
await client.undo(modeluri);

@@ -243,6 +256,6 @@ client.unsubscribe(modeluri);

it('pure Json Patch changes', async () => {
const modeluri = 'SuperBrewer3000.coffee';
const modeluri = new urijs_1.default('SuperBrewer3000.coffee');
const newName = 'Super Brewer 6000';
const machine = await client.get(modeluri, _1.ModelServerObjectV2.is);
const patchedMachine = fast_json_patch_1.deepClone(machine);
const patchedMachine = (0, fast_json_patch_1.deepClone)(machine);
// Directly change the model

@@ -255,38 +268,88 @@ patchedMachine.name = newName;

const model = await client.get(modeluri);
chai_1.expect(model.name).to.be.equal(newName);
chai_1.expect(model.children[1].processor.clockSpeed).to.be.equal(6);
(0, chai_1.expect)(model.name).to.be.equal(newName);
(0, chai_1.expect)(model.children[1].processor.clockSpeed).to.be.equal(6);
await testUndoRedo(modeluri, machine, model);
});
it('clear list with "remove" patch operation', async () => {
const modeluri = 'SuperBrewer3000.coffee';
const modeluri = new urijs_1.default('SuperBrewer3000.coffee');
const machine = await client.get(modeluri, _1.ModelServerObjectV2.is);
const initialWorkflowsSize = machine.workflows.length;
chai_1.expect(initialWorkflowsSize).to.not.be.equal(0);
const patch = [{
'op': 'remove',
'path': '/workflows'
}];
(0, chai_1.expect)(initialWorkflowsSize).to.not.be.equal(0);
const patch = [
{
op: 'remove',
path: '/workflows'
}
];
await client.edit(modeluri, patch);
const model = await client.get(modeluri);
const newWorkflows = model.workflows;
chai_1.expect(newWorkflows).to.be.undefined;
(0, chai_1.expect)(newWorkflows).to.be.undefined;
await testUndoRedo(modeluri, machine, model);
});
it('unset value with "remove" patch operation', async () => {
const modeluri = 'SuperBrewer3000.coffee';
const modeluri = new urijs_1.default('SuperBrewer3000.coffee');
const machine = await client.get(modeluri, _1.ModelServerObjectV2.is);
const initialValue = machine.children[1].processor.thermalDesignPower;
chai_1.expect(initialValue).to.not.be.oneOf([undefined, 0]);
const patch = [{
'op': 'remove',
'path': '/children/1/processor/thermalDesignPower'
}];
(0, chai_1.expect)(initialValue).to.not.be.oneOf([undefined, 0]);
const patch = [
{
op: 'remove',
path: '/children/1/processor/thermalDesignPower'
}
];
await client.edit(modeluri, patch);
const model = await client.get(modeluri);
const newValue = model.children[1].processor.thermalDesignPower;
chai_1.expect(newValue).to.be.oneOf([undefined, 0]); // Should be === 0, but default values are not converted to Json at the moment; so we also expect 'undefined'
(0, chai_1.expect)(newValue).to.be.oneOf([undefined, 0]); // Should be === 0, but default values are not converted to Json at the moment; so we also expect 'undefined'
await testUndoRedo(modeluri, machine, model);
});
it('check all patch replies', async () => {
const modeluri = new urijs_1.default('SuperBrewer3000.coffee');
const newName = 'Super Brewer 6000';
const machine = await client.get(modeluri, _1.ModelServerObjectV2.is);
const patchedMachine = (0, fast_json_patch_1.deepClone)(machine);
// Directly change the model
patchedMachine.name = newName;
patchedMachine.children[1].processor.clockSpeed = 6;
// Generate patch by diffing the original model and the patched one
const patch = fast_json_patch_1.default.compare(machine, patchedMachine);
const result = await client.edit(modeluri, patch);
(0, chai_1.expect)(result.success).to.be.true;
(0, chai_1.expect)(result.patch).to.not.be.undefined;
(0, chai_1.expect)(result.allPatches).to.not.be.undefined;
(0, chai_1.expect)(result.allPatches).to.be.an('array').of.length(1);
// Patch the main resource
const updatedMachineMainPatch = result.patchModel(machine, true);
(0, chai_1.expect)(patchedMachine).to.deep.equal(updatedMachineMainPatch);
// Patch the first resource
const updatedMachineFirstPatch = result.patchModel(machine, true, new urijs_1.default(result.allPatches[0].modelUri));
(0, chai_1.expect)(patchedMachine).to.deep.equal(updatedMachineFirstPatch);
await testUndoRedo(modeluri, machine, updatedMachineFirstPatch);
});
it('test model patches', async () => {
const modeluri = new urijs_1.default('SuperBrewer3000.coffee');
const newName = 'Super Brewer 6000';
const machine = await client.get(modeluri, _1.ModelServerObjectV2.is);
const patchedMachine = (0, fast_json_patch_1.deepClone)(machine);
// Directly change the model
patchedMachine.name = newName;
patchedMachine.children[1].processor.clockSpeed = 6;
// Generate patches by diffing the original model and the patched one
const patch = fast_json_patch_1.default.compare(machine, patchedMachine);
const result = await client.edit(modeluri, patch);
(0, chai_1.expect)(result.success).to.be.true;
(0, chai_1.expect)(result.patch).to.not.be.undefined;
(0, chai_1.expect)(result.allPatches).to.not.be.undefined;
(0, chai_1.expect)(result.allPatches).to.be.an('array').of.length(1);
// Patch the main resource
const updatedMachineMainPatch = result.patchModel(machine, true);
(0, chai_1.expect)(patchedMachine).to.deep.equal(updatedMachineMainPatch);
// Patch the first resource
const updatedMachineFirstPatch = result.patchModel(machine, true, new urijs_1.default(result.allPatches[0].modelUri));
(0, chai_1.expect)(patchedMachine).to.deep.equal(updatedMachineFirstPatch);
await testUndoRedo(modeluri, machine, updatedMachineFirstPatch);
});
});
});
//# sourceMappingURL=model-server-client-v2-integration.spec.js.map

@@ -1,3 +0,3 @@

/*********************************************************************************
* Copyright (c) 2022 STMicroelectronics and others.
/********************************************************************************
* Copyright (c) 2022-2023 STMicroelectronics and others.
*

@@ -10,10 +10,9 @@ * This program and the accompanying materials are made available under the

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
import { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
import { Operation } from 'fast-json-patch';
import WebSocket from 'isomorphic-ws';
import URI from 'urijs';
import { ServerConfiguration, SubscriptionOptions } from './model-server-client-api-v1';
import { Format, ModelServerClientApiV2, ModelUpdateResult } from './model-server-client-api-v2';
import { Format, ModelServerClientApiV2, ModelUpdateResult, PatchOrCommand } from './model-server-client-api-v2';
import { MessageDataMapper, Model, ModelServerMessage } from './model-server-message';
import { ModelServerCommand } from './model/command-model';
import { Diagnostic } from './model/diagnostic';

@@ -28,43 +27,41 @@ import { SubscriptionListener } from './subscription-listener';

protected openSockets: Map<string, WebSocket>;
protected _baseUrl: string;
protected _baseUrl: URI;
protected defaultFormat: Format;
initialize(baseUrl: string, defaultFormat?: Format): void | Promise<void>;
protected getAxiosConfig(baseURL: string): AxiosRequestConfig | undefined;
get(modeluri: string, format?: Format): Promise<AnyObject>;
get<M>(modeluri: string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
initialize(baseUrl: URI, defaultFormat?: Format): void | Promise<void>;
protected getAxiosConfig(baseURL: URI): AxiosRequestConfig | undefined;
get(modeluri: URI, format?: Format): Promise<AnyObject>;
get<M>(modeluri: URI, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
getAll(): Promise<Model[]>;
getAll<M>(typeGuard: TypeGuard<M>): Promise<Model<M>[]>;
getAll(format: Format): Promise<Model<string>[]>;
getModelUris(): Promise<string[]>;
getElementById(modeluri: string, elementid: string, format?: Format): Promise<AnyObject>;
getElementById<M>(modeluri: string, elementid: string, typeGuard: TypeGuard<M>): Promise<M>;
getElementByName(modeluri: string, elementname: string, format?: Format): Promise<AnyObject>;
getElementByName<M>(modeluri: string, elementname: string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
create(modeluri: string, model: AnyObject | string, format?: Format): Promise<AnyObject>;
create<M>(modeluri: string, model: AnyObject | string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
update(modeluri: string, model: AnyObject | string, format?: Format): Promise<AnyObject>;
update<M>(modeluri: string, model: string | string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
delete(modeluri: string): Promise<boolean>;
close(modeluri: string): Promise<boolean>;
save(modeluri: string): Promise<boolean>;
getModelUris(): Promise<URI[]>;
getElementById(modeluri: URI, elementid: string, format?: Format): Promise<AnyObject>;
getElementById<M>(modeluri: URI, elementid: string, typeGuard: TypeGuard<M>): Promise<M>;
getElementByName(modeluri: URI, elementname: string, format?: Format): Promise<AnyObject>;
getElementByName<M>(modeluri: URI, elementname: string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
create(modeluri: URI, model: AnyObject | string, format?: Format): Promise<AnyObject>;
create<M>(modeluri: URI, model: AnyObject | string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
update(modeluri: URI, model: AnyObject | string, format?: Format): Promise<AnyObject>;
update<M>(modeluri: URI, model: string | string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
delete(modeluri: URI): Promise<boolean>;
close(modeluri: URI): Promise<boolean>;
save(modeluri: URI): Promise<boolean>;
saveAll(): Promise<boolean>;
validate(modeluri: string): Promise<Diagnostic>;
getValidationConstraints(modeluri: string): Promise<string>;
getTypeSchema(modeluri: string): Promise<string>;
validate(modeluri: URI): Promise<Diagnostic>;
getValidationConstraints(modeluri: URI): Promise<string>;
getTypeSchema(modeluri: URI): Promise<string>;
getUiSchema(schemaname: string): Promise<string>;
configureServer(configuration: ServerConfiguration): Promise<boolean>;
ping(): Promise<boolean>;
edit(modeluri: string, patch: Operation): Promise<ModelUpdateResult>;
edit(modeluri: string, patch: Operation[]): Promise<ModelUpdateResult>;
edit(modeluri: string, command: ModelServerCommand): Promise<ModelUpdateResult>;
undo(modeluri: string): Promise<ModelUpdateResult>;
redo(modeluri: string): Promise<ModelUpdateResult>;
send(modelUri: string, message: ModelServerMessage): void;
subscribe(modeluri: string, listener: SubscriptionListener, options?: SubscriptionOptions): SubscriptionListener;
unsubscribe(modeluri: string): void;
protected createSubscriptionPath(modeluri: string, options: SubscriptionOptions): string;
protected doSubscribe(listener: SubscriptionListener, modelUri: string, path: string): void;
protected isSocketOpen(modelUri: string): boolean;
edit(modeluri: URI, patchOrCommand: PatchOrCommand, format?: string): Promise<ModelUpdateResult>;
undo(modeluri: URI): Promise<ModelUpdateResult>;
redo(modeluri: URI): Promise<ModelUpdateResult>;
send(modeluri: URI, message: ModelServerMessage): void;
subscribe(modeluri: URI, listener: SubscriptionListener, options?: SubscriptionOptions): SubscriptionListener;
unsubscribe(modeluri: URI): void;
protected createSubscriptionPath(modeluri: URI, options: SubscriptionOptions): URI;
protected doSubscribe(listener: SubscriptionListener, modeluri: URI, path: URI): void;
protected isSocketOpen(modeluri: URI): boolean;
protected process<T>(request: Promise<AxiosResponse<ModelServerMessage>>, mapper: MessageDataMapper<T>): Promise<T>;
}
//# sourceMappingURL=model-server-client-v2.d.ts.map
"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) {

@@ -7,4 +18,4 @@ return (mod && mod.__esModule) ? mod : { "default": mod };

exports.ModelServerClientV2 = void 0;
/*********************************************************************************
* Copyright (c) 2022 STMicroelectronics and others.
/********************************************************************************
* Copyright (c) 2022-2023 STMicroelectronics and others.
*

@@ -17,4 +28,5 @@ * This program and the accompanying materials are made available under the

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
const axios_1 = __importDefault(require("axios"));
const fast_json_patch_1 = require("fast-json-patch");
const isomorphic_ws_1 = __importDefault(require("isomorphic-ws"));

@@ -37,3 +49,3 @@ const model_server_client_api_v1_1 = require("./model-server-client-api-v1");

initialize(baseUrl, defaultFormat = model_server_client_api_v2_1.FORMAT_JSON_V2) {
this._baseUrl = baseUrl;
this._baseUrl = baseUrl.clone();
this.defaultFormat = defaultFormat;

@@ -43,3 +55,3 @@ this.restClient = axios_1.default.create(this.getAxiosConfig(baseUrl));

getAxiosConfig(baseURL) {
return { baseURL };
return { baseURL: baseURL.toString() };
}

@@ -49,6 +61,6 @@ get(modeluri, formatOrGuard, format) {

const typeGuard = formatOrGuard;
return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.MODEL_CRUD, { params: { modeluri, format } }), msg => model_server_message_1.MessageDataMapper.as(msg, typeGuard));
return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.MODEL_CRUD, { params: { modeluri: modeluri.toString(), format } }), msg => model_server_message_1.MessageDataMapper.as(msg, typeGuard));
}
format = formatOrGuard !== null && formatOrGuard !== void 0 ? formatOrGuard : this.defaultFormat;
return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.MODEL_CRUD, { params: { modeluri, format } }), model_server_message_1.MessageDataMapper.asObject);
return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.MODEL_CRUD, { params: { modeluri: modeluri.toString(), format } }), model_server_message_1.MessageDataMapper.asObject);
}

@@ -72,3 +84,3 @@ getAll(formatOrGuard) {

getModelUris() {
return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.MODEL_URIS), model_server_message_1.MessageDataMapper.asStringArray);
return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.MODEL_URIS), model_server_message_1.MessageDataMapper.asURIArray);
}

@@ -80,7 +92,7 @@ getElementById(modeluri, elementid, formatOrGuard, format) {

const typeGuard = formatOrGuard;
return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.MODEL_ELEMENT, { params: { modeluri, elementid, format } }), msg => model_server_message_1.MessageDataMapper.as(msg, typeGuard));
return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.MODEL_ELEMENT, { params: { modeluri: modeluri.toString(), elementid, format } }), msg => model_server_message_1.MessageDataMapper.as(msg, typeGuard));
}
format = formatOrGuard;
}
return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.MODEL_ELEMENT, { params: { modeluri, elementid, format } }), model_server_message_1.MessageDataMapper.asObject);
return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.MODEL_ELEMENT, { params: { modeluri: modeluri.toString(), elementid, format } }), model_server_message_1.MessageDataMapper.asObject);
}

@@ -92,7 +104,7 @@ getElementByName(modeluri, elementname, formatOrGuard, format) {

const typeGuard = formatOrGuard;
return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.MODEL_ELEMENT, { params: { modeluri, elementname, format } }), msg => model_server_message_1.MessageDataMapper.as(msg, typeGuard));
return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.MODEL_ELEMENT, { params: { modeluri: modeluri.toString(), elementname, format } }), msg => model_server_message_1.MessageDataMapper.as(msg, typeGuard));
}
format = formatOrGuard;
}
return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.MODEL_ELEMENT, { params: { modeluri, elementname, format } }), model_server_message_1.MessageDataMapper.asObject);
return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.MODEL_ELEMENT, { params: { modeluri: modeluri.toString(), elementname, format } }), model_server_message_1.MessageDataMapper.asObject);
}

@@ -104,7 +116,11 @@ create(modeluri, model, formatOrGuard, format) {

const typeGuard = formatOrGuard;
return this.process(this.restClient.post(model_server_paths_1.ModelServerPaths.MODEL_CRUD, type_util_1.encodeRequestBody(format)(model), { params: { modeluri, format } }), msg => model_server_message_1.MessageDataMapper.as(msg, typeGuard));
return this.process(this.restClient.post(model_server_paths_1.ModelServerPaths.MODEL_CRUD, (0, type_util_1.encodeRequestBody)(format)(model), {
params: { modeluri: modeluri.toString(), format }
}), msg => model_server_message_1.MessageDataMapper.as(msg, typeGuard));
}
format = formatOrGuard;
}
return this.process(this.restClient.post(model_server_paths_1.ModelServerPaths.MODEL_CRUD, type_util_1.encodeRequestBody(format)(model), { params: { modeluri, format } }), model_server_message_1.MessageDataMapper.asObject);
return this.process(this.restClient.post(model_server_paths_1.ModelServerPaths.MODEL_CRUD, (0, type_util_1.encodeRequestBody)(format)(model), {
params: { modeluri: modeluri.toString(), format }
}), model_server_message_1.MessageDataMapper.asObject);
}

@@ -116,16 +132,20 @@ update(modeluri, model, formatOrGuard, format) {

const typeGuard = formatOrGuard;
return this.process(this.restClient.put(model_server_paths_1.ModelServerPaths.MODEL_CRUD, type_util_1.encodeRequestBody(format)(model), { params: { modeluri, format } }), msg => model_server_message_1.MessageDataMapper.as(msg, typeGuard));
return this.process(this.restClient.put(model_server_paths_1.ModelServerPaths.MODEL_CRUD, (0, type_util_1.encodeRequestBody)(format)(model), {
params: { modeluri: modeluri.toString(), format }
}), msg => model_server_message_1.MessageDataMapper.as(msg, typeGuard));
}
format = formatOrGuard;
}
return this.process(this.restClient.put(model_server_paths_1.ModelServerPaths.MODEL_CRUD, type_util_1.encodeRequestBody(format)(model), { params: { modeluri, format } }), model_server_message_1.MessageDataMapper.asObject);
return this.process(this.restClient.put(model_server_paths_1.ModelServerPaths.MODEL_CRUD, (0, type_util_1.encodeRequestBody)(format)(model), {
params: { modeluri: modeluri.toString(), format }
}), model_server_message_1.MessageDataMapper.asObject);
}
delete(modeluri) {
return this.process(this.restClient.delete(model_server_paths_1.ModelServerPaths.MODEL_CRUD, { params: { modeluri } }), model_server_message_1.MessageDataMapper.isSuccess);
return this.process(this.restClient.delete(model_server_paths_1.ModelServerPaths.MODEL_CRUD, { params: { modeluri: modeluri.toString() } }), 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);
return this.process(this.restClient.post(model_server_paths_1.ModelServerPaths.CLOSE, undefined, { params: { modeluri: modeluri.toString() } }), 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);
return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.SAVE, { params: { modeluri: modeluri.toString() } }), model_server_message_1.MessageDataMapper.isSuccess);
}

@@ -136,9 +156,9 @@ saveAll() {

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));
return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.VALIDATION, { params: { modeluri: modeluri.toString() } }), 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);
return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.VALIDATION_CONSTRAINTS, { params: { modeluri: modeluri.toString() } }), 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);
return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.TYPE_SCHEMA, { params: { modeluri: modeluri.toString() } }), model_server_message_1.MessageDataMapper.asString);
}

@@ -149,6 +169,7 @@ getUiSchema(schemaname) {

configureServer(configuration) {
let { workspaceRoot, uiSchemaFolder } = configuration;
workspaceRoot = workspaceRoot.replace('file://', '');
uiSchemaFolder = uiSchemaFolder === null || uiSchemaFolder === void 0 ? void 0 : uiSchemaFolder.replace('file://', '');
return this.process(this.restClient.put(model_server_paths_1.ModelServerPaths.SERVER_CONFIGURE, { workspaceRoot, uiSchemaFolder }), model_server_message_1.MessageDataMapper.isSuccess);
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);
}

@@ -158,3 +179,3 @@ ping() {

}
edit(modeluri, patchOrCommand) {
edit(modeluri, patchOrCommand, format = this.defaultFormat) {
let patchMessage;

@@ -168,2 +189,3 @@ if (patchOrCommand instanceof command_model_1.ModelServerCommand) {

else {
// Operation[] and ModelPatch[] are treated in the same way; we don't need to distinguish both cases
const fullPatch = Array.isArray(patchOrCommand) ? patchOrCommand : [patchOrCommand];

@@ -174,15 +196,25 @@ patchMessage = {

};
if (fullPatch.length === 0) {
// No-op
return Promise.resolve({
success: true,
patchModel: (oldModel, copy, _modeluri) => (copy ? (0, fast_json_patch_1.deepClone)(oldModel) : oldModel),
patch: []
});
}
}
return this.process(this.restClient.patch(model_server_paths_1.ModelServerPaths.MODEL_CRUD, type_util_1.encodeRequestBody(this.defaultFormat)(patchMessage), { params: { modeluri, format: this.defaultFormat } }), model_server_message_1.MessageDataMapper.patchModel);
return this.process(this.restClient.patch(model_server_paths_1.ModelServerPaths.MODEL_CRUD, (0, type_util_1.encodeRequestBody)(format)(patchMessage), {
params: { modeluri: modeluri.toString(), format: format }
}), model_server_message_1.MessageDataMapper.patchModel);
}
undo(modeluri) {
return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.UNDO, { params: { modeluri } }), model_server_message_1.MessageDataMapper.patchModel);
return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.UNDO, { params: { modeluri: modeluri.toString() } }), model_server_message_1.MessageDataMapper.patchModel);
}
redo(modeluri) {
return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.REDO, { params: { modeluri } }), model_server_message_1.MessageDataMapper.patchModel);
return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.REDO, { params: { modeluri: modeluri.toString() } }), model_server_message_1.MessageDataMapper.patchModel);
}
send(modelUri, message) {
const openSocket = this.openSockets.get(modelUri);
send(modeluri, message) {
const openSocket = this.openSockets.get(modeluri.toString());
if (openSocket) {
openSocket.send(message);
openSocket.send(JSON.stringify(message));
}

@@ -192,6 +224,6 @@ }

if (this.isSocketOpen(modeluri)) {
const errorMsg = `${modeluri} : Cannot open new socket, already subscribed!'`;
const errorMsg = `${modeluri.toString()} : Cannot open new socket, already subscribed!'`;
console.warn(errorMsg);
if (options.errorWhenUnsuccessful) {
throw new Error('errorMsg');
throw new Error(errorMsg);
}

@@ -204,28 +236,29 @@ }

unsubscribe(modeluri) {
const openSocket = this.openSockets.get(modeluri);
const openSocket = this.openSockets.get(modeluri.toString());
if (openSocket) {
openSocket.close();
this.openSockets.delete(modeluri);
this.openSockets.delete(modeluri.toString());
}
}
createSubscriptionPath(modeluri, options) {
const queryParams = new URLSearchParams();
queryParams.append('modeluri', modeluri);
if (!options.format) {
options.format = this.defaultFormat;
}
Object.entries(options).forEach(entry => queryParams.append(entry[0], entry[1]));
queryParams.delete('errorWhenUnsuccessful');
return `${this._baseUrl}/${model_server_paths_1.ModelServerPaths.SUBSCRIPTION}?${queryParams.toString()}`.replace(/^(http|https):\/\//i, 'ws://');
const paramOptions = __rest(options, []);
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.trim());
socket.onopen = event => { var _a; return (_a = listener.onOpen) === null || _a === void 0 ? void 0 : _a.call(listener, modelUri, event); };
socket.onclose = event => { var _a; return (_a = listener.onClose) === null || _a === void 0 ? void 0 : _a.call(listener, modelUri, event); };
socket.onerror = event => { var _a; return (_a = listener.onError) === null || _a === void 0 ? void 0 : _a.call(listener, modelUri, event); };
socket.onmessage = event => { var _a; return (_a = listener.onMessage) === null || _a === void 0 ? void 0 : _a.call(listener, modelUri, event); };
this.openSockets.set(modelUri, socket);
doSubscribe(listener, modeluri, path) {
const socket = new isomorphic_ws_1.default(path.toString() /* .trim() */);
socket.onopen = event => { var _a; return (_a = listener.onOpen) === null || _a === void 0 ? void 0 : _a.call(listener, modeluri, event); };
socket.onclose = event => { var _a; return (_a = listener.onClose) === null || _a === void 0 ? void 0 : _a.call(listener, modeluri, event); };
socket.onerror = event => { var _a; return (_a = listener.onError) === null || _a === void 0 ? void 0 : _a.call(listener, modeluri, event); };
socket.onmessage = event => { var _a; return (_a = listener.onMessage) === null || _a === void 0 ? void 0 : _a.call(listener, modeluri, event); };
this.openSockets.set(modeluri.toString(), socket);
}
isSocketOpen(modelUri) {
return this.openSockets.get(modelUri) !== undefined;
isSocketOpen(modeluri) {
return this.openSockets.get(modeluri.toString()) !== undefined;
}

@@ -242,3 +275,3 @@ async process(request, mapper) {

catch (error) {
if (isAxiosError(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;

@@ -254,15 +287,12 @@ throw new model_server_client_api_v1_1.ModelServerError(message, error.code);

exports.ModelServerClientV2 = ModelServerClientV2;
function isAxiosError(error) {
return error !== undefined && error instanceof Error && 'isAxiosError' in error && error['isAxiosError'];
}
function mapModel(model, guard, toString = false) {
const { modelUri, content } = model;
const { modeluri, content } = model;
if (guard) {
return { modelUri, content: type_util_1.asType(content, guard) };
return { modeluri, content: (0, type_util_1.asType)(content, guard) };
}
else if (toString) {
return { modelUri, content: type_util_1.asString(content) };
return { modeluri, content: (0, type_util_1.asString)(content) };
}
return { modelUri, content: type_util_1.asObject(content) };
return { modeluri, content: (0, type_util_1.asObject)(content) };
}
//# sourceMappingURL=model-server-client-v2.js.map

@@ -6,3 +6,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
/*********************************************************************************
/********************************************************************************
* Copyright (c) 2022 STMicroelectronics and others.

@@ -16,3 +16,3 @@ *

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
const assert_1 = require("assert");

@@ -22,2 +22,3 @@ const chai_1 = require("chai");

const sinon_1 = require("sinon");
const urijs_1 = __importDefault(require("urijs"));
const model_server_client_api_v2_1 = require("./model-server-client-api-v2");

@@ -28,3 +29,8 @@ const model_server_client_v2_1 = require("./model-server-client-v2");

let client;
const baseUrl = `http://localhost:8081${model_server_client_api_v2_1.ModelServerClientApiV2.API_ENDPOINT}`;
const baseUrl = new urijs_1.default({
protocol: 'http',
hostname: 'localhost',
port: '8081',
path: model_server_client_api_v2_1.ModelServerClientApiV2.API_ENDPOINT
});
beforeEach(() => {

@@ -40,4 +46,16 @@ client = new model_server_client_v2_1.ModelServerClientV2();

const axios = client['restClient'];
chai_1.expect(axios.defaults.baseURL).to.be.equal(baseUrl);
(0, chai_1.expect)(axios.defaults.baseURL).to.be.equal(baseUrl.toString());
});
it('test createSubscriptionPath without trailing slash', () => {
client = new model_server_client_v2_1.ModelServerClientV2();
client.initialize(baseUrl);
const subscriptionPath = client['createSubscriptionPath'](new urijs_1.default('foo'), {});
(0, chai_1.expect)(subscriptionPath.toString()).to.be.equal('ws://localhost:8081/api/v2/subscribe?modeluri=foo&format=json-v2');
});
it('test createSubscriptionPath with trailing slash', () => {
client = new model_server_client_v2_1.ModelServerClientV2();
client.initialize(new urijs_1.default(`${baseUrl}/`));
const subscriptionPath = client['createSubscriptionPath'](new urijs_1.default('foo'), {});
(0, chai_1.expect)(subscriptionPath.toString()).to.be.equal('ws://localhost:8081/api/v2/subscribe?modeluri=foo&format=json-v2');
});
describe('test requests', () => {

@@ -50,8 +68,8 @@ it('getAll', done => {

let request = moxios_1.default.requests.at(0);
chai_1.expect(request.config.method).to.be.equal('get');
chai_1.expect(request.config.params).to.include({ format: model_server_client_api_v2_1.FORMAT_JSON_V2 });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_CRUD);
(0, chai_1.expect)(request.config.method).to.be.equal('get');
(0, chai_1.expect)(request.config.params).to.include({ format: model_server_client_api_v2_1.FORMAT_JSON_V2 });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_CRUD);
request = moxios_1.default.requests.at(1);
chai_1.expect(request.config.params).to.include({ format: model_server_client_api_v2_1.FORMAT_XMI });
(0, chai_1.expect)(request.config.params).to.include({ format: model_server_client_api_v2_1.FORMAT_XMI });
done();

@@ -64,6 +82,6 @@ });

const request = moxios_1.default.requests.mostRecent();
chai_1.expect(request.config.method).to.be.equal('get');
chai_1.expect(request.config.params).to.be.undefined;
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_URIS);
(0, chai_1.expect)(request.config.method).to.be.equal('get');
(0, chai_1.expect)(request.config.params).to.be.undefined;
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_URIS);
done();

@@ -73,3 +91,3 @@ });

it('getElementById', done => {
const modeluri = 'my/uri.model';
const modeluri = new urijs_1.default('my/uri.model');
const elementid = 'myElement';

@@ -80,8 +98,8 @@ client.getElementById(modeluri, elementid);

let request = moxios_1.default.requests.at(0);
chai_1.expect(request.config.method).to.be.equal('get');
chai_1.expect(request.config.params).to.include({ format: model_server_client_api_v2_1.FORMAT_JSON_V2, elementid, modeluri });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_ELEMENT);
(0, chai_1.expect)(request.config.method).to.be.equal('get');
(0, chai_1.expect)(request.config.params).to.include({ format: model_server_client_api_v2_1.FORMAT_JSON_V2, elementid, modeluri: modeluri.toString() });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_ELEMENT);
request = moxios_1.default.requests.at(1);
chai_1.expect(request.config.params).to.include({ format: model_server_client_api_v2_1.FORMAT_XMI, elementid, modeluri });
(0, chai_1.expect)(request.config.params).to.include({ format: model_server_client_api_v2_1.FORMAT_XMI, elementid, modeluri: modeluri.toString() });
done();

@@ -91,3 +109,3 @@ });

it('getElementByName', done => {
const modeluri = 'my/uri.model';
const modeluri = new urijs_1.default('my/uri.model');
const elementname = 'myElement';

@@ -98,8 +116,8 @@ client.getElementByName(modeluri, elementname);

let request = moxios_1.default.requests.at(0);
chai_1.expect(request.config.method).to.be.equal('get');
chai_1.expect(request.config.params).to.include({ format: model_server_client_api_v2_1.FORMAT_JSON_V2, elementname, modeluri });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_ELEMENT);
(0, chai_1.expect)(request.config.method).to.be.equal('get');
(0, chai_1.expect)(request.config.params).to.include({ format: model_server_client_api_v2_1.FORMAT_JSON_V2, elementname, modeluri: modeluri.toString() });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_ELEMENT);
request = moxios_1.default.requests.at(1);
chai_1.expect(request.config.params).to.include({ format: model_server_client_api_v2_1.FORMAT_XMI, elementname, modeluri });
(0, chai_1.expect)(request.config.params).to.include({ format: model_server_client_api_v2_1.FORMAT_XMI, elementname, modeluri: modeluri.toString() });
done();

@@ -109,10 +127,10 @@ });

it('delete', done => {
const modeluri = 'delete/me/please';
const modeluri = new urijs_1.default('delete/me/please');
client.delete(modeluri);
moxios_1.default.wait(() => {
const request = moxios_1.default.requests.mostRecent();
chai_1.expect(request.config.method).to.be.equal('delete');
chai_1.expect(request.config.params).to.include({ modeluri });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_CRUD);
(0, chai_1.expect)(request.config.method).to.be.equal('delete');
(0, chai_1.expect)(request.config.params).to.include({ modeluri: modeluri.toString() });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_CRUD);
done();

@@ -122,10 +140,10 @@ });

it('close', done => {
const modeluri = 'delete/me/please';
const modeluri = new urijs_1.default('delete/me/please');
client.close(modeluri);
moxios_1.default.wait(() => {
const request = moxios_1.default.requests.mostRecent();
chai_1.expect(request.config.method).to.be.equal('post');
chai_1.expect(request.config.params).to.include({ modeluri });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.CLOSE);
(0, chai_1.expect)(request.config.method).to.be.equal('post');
(0, chai_1.expect)(request.config.params).to.include({ modeluri: modeluri.toString() });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.CLOSE);
done();

@@ -135,3 +153,3 @@ });

it('create', done => {
const modeluri = 'delete/me/please';
const modeluri = new urijs_1.default('delete/me/please');
const model = { name: 'myModel', id: 'myModelId' };

@@ -143,9 +161,9 @@ const data = JSON.stringify(model);

let request = moxios_1.default.requests.at(0);
chai_1.expect(request.config.method).to.be.equal('post');
chai_1.expect(request.config.data).to.be.equal(JSON.stringify({ data }));
chai_1.expect(request.config.params).to.include({ format: model_server_client_api_v2_1.FORMAT_JSON_V2, modeluri });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_CRUD);
(0, chai_1.expect)(request.config.method).to.be.equal('post');
(0, chai_1.expect)(request.config.data).to.be.equal(JSON.stringify({ data }));
(0, chai_1.expect)(request.config.params).to.include({ format: model_server_client_api_v2_1.FORMAT_JSON_V2, modeluri: modeluri.toString() });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_CRUD);
request = moxios_1.default.requests.at(1);
chai_1.expect(request.config.params).to.include({ format: model_server_client_api_v2_1.FORMAT_XMI, modeluri });
(0, chai_1.expect)(request.config.params).to.include({ format: model_server_client_api_v2_1.FORMAT_XMI, modeluri: modeluri.toString() });
done();

@@ -155,3 +173,3 @@ });

it('update', done => {
const modeluri = 'delete/me/please';
const modeluri = new urijs_1.default('delete/me/please');
const model = { name: 'myModel', id: 'myModelId' };

@@ -163,9 +181,9 @@ const data = JSON.stringify(model);

let request = moxios_1.default.requests.at(0);
chai_1.expect(request.config.method).to.be.equal('put');
chai_1.expect(request.config.data).to.be.equal(JSON.stringify({ data }));
chai_1.expect(request.config.params).to.include({ format: model_server_client_api_v2_1.FORMAT_JSON_V2, modeluri });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_CRUD);
(0, chai_1.expect)(request.config.method).to.be.equal('put');
(0, chai_1.expect)(request.config.data).to.be.equal(JSON.stringify({ data }));
(0, chai_1.expect)(request.config.params).to.include({ format: model_server_client_api_v2_1.FORMAT_JSON_V2, modeluri: modeluri.toString() });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_CRUD);
request = moxios_1.default.requests.at(1);
chai_1.expect(request.config.params).to.include({ format: model_server_client_api_v2_1.FORMAT_XMI, modeluri });
(0, chai_1.expect)(request.config.params).to.include({ format: model_server_client_api_v2_1.FORMAT_XMI, modeluri: modeluri.toString() });
done();

@@ -175,10 +193,10 @@ });

it('save', done => {
const modeluri = 'save/me/please';
const modeluri = new urijs_1.default('save/me/please');
client.save(modeluri);
moxios_1.default.wait(() => {
const request = moxios_1.default.requests.mostRecent();
chai_1.expect(request.config.method).to.be.equal('get');
chai_1.expect(request.config.params).to.include({ modeluri });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.SAVE);
(0, chai_1.expect)(request.config.method).to.be.equal('get');
(0, chai_1.expect)(request.config.params).to.include({ modeluri: modeluri.toString() });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.SAVE);
done();

@@ -191,6 +209,6 @@ });

const request = moxios_1.default.requests.mostRecent();
chai_1.expect(request.config.method).to.be.equal('get');
chai_1.expect(request.config.params).to.be.undefined;
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.SAVE_ALL);
(0, chai_1.expect)(request.config.method).to.be.equal('get');
(0, chai_1.expect)(request.config.params).to.be.undefined;
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.SAVE_ALL);
done();

@@ -200,10 +218,10 @@ });

it('validate', done => {
const modeluri = 'validate/me/please';
const modeluri = new urijs_1.default('validate/me/please');
client.validate(modeluri);
moxios_1.default.wait(() => {
const request = moxios_1.default.requests.mostRecent();
chai_1.expect(request.config.method).to.be.equal('get');
chai_1.expect(request.config.params).to.include({ modeluri });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.VALIDATION);
(0, chai_1.expect)(request.config.method).to.be.equal('get');
(0, chai_1.expect)(request.config.params).to.include({ modeluri: modeluri.toString() });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.VALIDATION);
done();

@@ -213,10 +231,10 @@ });

it('getValidationConstraints', done => {
const modeluri = 'validate/me/please';
const modeluri = new urijs_1.default('validate/me/please');
client.getValidationConstraints(modeluri);
moxios_1.default.wait(() => {
const request = moxios_1.default.requests.mostRecent();
chai_1.expect(request.config.method).to.be.equal('get');
chai_1.expect(request.config.params).to.include({ modeluri });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.VALIDATION_CONSTRAINTS);
(0, chai_1.expect)(request.config.method).to.be.equal('get');
(0, chai_1.expect)(request.config.params).to.include({ modeluri: modeluri.toString() });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.VALIDATION_CONSTRAINTS);
done();

@@ -226,10 +244,10 @@ });

it('getTypeSchema', done => {
const modeluri = 'my/model/uri';
const modeluri = new urijs_1.default('my/model/uri');
client.getTypeSchema(modeluri);
moxios_1.default.wait(() => {
const request = moxios_1.default.requests.mostRecent();
chai_1.expect(request.config.method).to.be.equal('get');
chai_1.expect(request.config.params).to.include({ modeluri });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.TYPE_SCHEMA);
(0, chai_1.expect)(request.config.method).to.be.equal('get');
(0, chai_1.expect)(request.config.params).to.include({ modeluri: modeluri.toString() });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.TYPE_SCHEMA);
done();

@@ -243,6 +261,6 @@ });

const request = moxios_1.default.requests.mostRecent();
chai_1.expect(request.config.method).to.be.equal('get');
chai_1.expect(request.config.params).to.include({ schemaname });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.UI_SCHEMA);
(0, chai_1.expect)(request.config.method).to.be.equal('get');
(0, chai_1.expect)(request.config.params).to.include({ schemaname });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.UI_SCHEMA);
done();

@@ -253,4 +271,4 @@ });

const configuration = {
workspaceRoot: 'myRoot',
uiSchemaFolder: 'mySchemaFolder'
workspaceRoot: new urijs_1.default('myRoot'),
uiSchemaFolder: new urijs_1.default('mySchemaFolder')
};

@@ -260,7 +278,10 @@ client.configureServer(configuration);

const request = moxios_1.default.requests.mostRecent();
chai_1.expect(request.config.method).to.be.equal('put');
chai_1.expect(request.config.data).to.equal(JSON.stringify(configuration));
chai_1.expect(request.config.params).to.be.undefined;
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.SERVER_CONFIGURE);
(0, chai_1.expect)(request.config.method).to.be.equal('put');
(0, chai_1.expect)(request.config.data).to.equal(JSON.stringify({
workspaceRoot: configuration.workspaceRoot.toString(),
uiSchemaFolder: configuration.uiSchemaFolder.toString()
}));
(0, chai_1.expect)(request.config.params).to.be.undefined;
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.SERVER_CONFIGURE);
done();

@@ -273,6 +294,6 @@ });

const request = moxios_1.default.requests.mostRecent();
chai_1.expect(request.config.method).to.be.equal('get');
chai_1.expect(request.config.params).to.be.undefined;
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.SERVER_PING);
(0, chai_1.expect)(request.config.method).to.be.equal('get');
(0, chai_1.expect)(request.config.params).to.be.undefined;
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.SERVER_PING);
done();

@@ -282,3 +303,3 @@ });

it('edit', done => {
const modeluri = 'edit/me/please';
const modeluri = new urijs_1.default('edit/me/please');
const patch = [

@@ -298,7 +319,7 @@ {

const request = moxios_1.default.requests.at(0);
chai_1.expect(request.config.method).to.be.equal('patch');
chai_1.expect(request.config.data).to.be.equal(JSON.stringify({ data: expected }));
chai_1.expect(request.config.params).to.include({ format: model_server_client_api_v2_1.FORMAT_JSON_V2, modeluri });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_CRUD);
(0, chai_1.expect)(request.config.method).to.be.equal('patch');
(0, chai_1.expect)(request.config.data).to.be.equal(JSON.stringify({ data: expected }));
(0, chai_1.expect)(request.config.params).to.include({ format: model_server_client_api_v2_1.FORMAT_JSON_V2, modeluri: modeluri.toString() });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_CRUD);
done();

@@ -308,10 +329,10 @@ });

it('undo', done => {
const modeluri = 'undo/me/please';
const modeluri = new urijs_1.default('undo/me/please');
client.undo(modeluri);
moxios_1.default.wait(() => {
const request = moxios_1.default.requests.mostRecent();
chai_1.expect(request.config.method).to.be.equal('get');
chai_1.expect(request.config.params).to.be.include({ modeluri });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.UNDO);
(0, chai_1.expect)(request.config.method).to.be.equal('get');
(0, chai_1.expect)(request.config.params).to.be.include({ modeluri: modeluri.toString() });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.UNDO);
done();

@@ -321,10 +342,10 @@ });

it('redo', done => {
const modeluri = 'redo/me/please';
const modeluri = new urijs_1.default('redo/me/please');
client.redo(modeluri);
moxios_1.default.wait(() => {
const request = moxios_1.default.requests.mostRecent();
chai_1.expect(request.config.method).to.be.equal('get');
chai_1.expect(request.config.params).to.be.include({ modeluri });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.REDO);
(0, chai_1.expect)(request.config.method).to.be.equal('get');
(0, chai_1.expect)(request.config.params).to.be.include({ modeluri: modeluri.toString() });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.REDO);
done();

@@ -335,3 +356,3 @@ });

describe('test responses', () => {
it('ping ', done => {
it('ping', done => {
const expectedMsg = {

@@ -341,3 +362,3 @@ data: '',

};
const onFulfilled = sinon_1.spy();
const onFulfilled = (0, sinon_1.spy)();
client.ping().then(onFulfilled);

@@ -350,9 +371,9 @@ moxios_1.default.wait(async () => {

});
assert_1.strictEqual(onFulfilled.getCall(0).args[0], true);
(0, assert_1.strictEqual)(onFulfilled.getCall(0).args[0], true);
done();
});
});
it('ping ', done => {
it('getAll', done => {
const model1 = {
modelUri: 'path/to/model1',
modeluri: 'path/to/model1',
content: {

@@ -363,3 +384,3 @@ name: 'coffee'

const model2 = {
modelUri: 'path/to/model2',
modeluri: 'path/to/model2',
content: {

@@ -371,8 +392,8 @@ name: 'coffee'

data: {
[model1.modelUri]: model1.content,
[model2.modelUri]: model2.content
[model1.modeluri.toString()]: model1.content,
[model2.modeluri.toString()]: model2.content
},
type: 'success'
};
const onFulfilled = sinon_1.spy();
const onFulfilled = (0, sinon_1.spy)();
client.getAll().then(onFulfilled);

@@ -386,3 +407,4 @@ moxios_1.default.wait(async () => {

const result = onFulfilled.getCall(0).args[0];
chai_1.expect(result).to.deep.include.members([model2, model1]);
(0, chai_1.expect)(result).to.be.an('array').of.length(2);
(0, chai_1.expect)(result).to.deep.include.members([model1, model2]);
done();

@@ -389,0 +411,0 @@ });

@@ -1,3 +0,3 @@

/*********************************************************************************
* Copyright (c) 2021-2022 STMicroelectronics and others.
/********************************************************************************
* Copyright (c) 2021-2023 STMicroelectronics and others.
*

@@ -10,5 +10,6 @@ * This program and the accompanying materials are made available under the

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
import { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
import WebSocket from 'isomorphic-ws';
import URI from 'urijs';
import { ModelServerClientApiV1, ModelServerError, ServerConfiguration, SubscriptionOptions } from './model-server-client-api-v1';

@@ -26,44 +27,44 @@ import { Mapper, MessageDataMapper, Model, ModelServerMessage } from './model-server-message';

protected openSockets: Map<string, WebSocket>;
protected _baseUrl: string;
protected _baseUrl: URI;
protected defaultFormat: string;
initialize(baseUrl: string): void | Promise<void>;
protected getAxisConfig(baseURL: string): AxiosRequestConfig | undefined;
get(modeluri: string): Promise<AnyObject>;
get<M>(modeluri: string, typeGuard: TypeGuard<M>): Promise<M>;
get(modeluri: string, format: string): Promise<string>;
initialize(baseUrl: URI): void | Promise<void>;
protected getAxisConfig(baseURL: URI): AxiosRequestConfig | undefined;
get(modeluri: URI): Promise<AnyObject>;
get<M>(modeluri: URI, typeGuard: TypeGuard<M>): Promise<M>;
get(modeluri: URI, format: string): Promise<string>;
getAll(): Promise<Model[]>;
getAll<M>(typeGuard: TypeGuard<M>): Promise<Model<M>[]>;
getAll(format: string): Promise<Model<string>[]>;
getModelUris(): Promise<string[]>;
getElementById(modeluri: string, elementid: string): Promise<AnyObject>;
getElementById<M>(modeluri: string, elementid: string, typeGuard: TypeGuard<M>): Promise<M>;
getElementById(modeluri: string, elementid: string, format: string): Promise<string>;
getElementByName(modeluri: string, elementname: string): Promise<AnyObject>;
getElementByName<M>(modeluri: string, elementname: string, typeGuard: TypeGuard<M>, format?: string): Promise<M>;
getElementByName(modeluri: string, elementname: string, format: string): Promise<string>;
create(modeluri: string, model: AnyObject | string): Promise<AnyObject>;
create(modeluri: string, model: AnyObject | string, format: string): Promise<string>;
create<M>(modeluri: string, model: AnyObject | string, typeGuard: TypeGuard<M>): Promise<M>;
update(modeluri: string, model: AnyObject | string): Promise<AnyObject>;
update<M>(modeluri: string, model: string | string, typeGuard: TypeGuard<M>): Promise<M>;
update(modeluri: string, model: AnyObject | string, format: string): Promise<AnyObject>;
delete(modeluri: string): Promise<boolean>;
close(modeluri: string): Promise<boolean>;
save(modeluri: string): Promise<boolean>;
getModelUris(): Promise<URI[]>;
getElementById(modeluri: URI, elementid: string): Promise<AnyObject>;
getElementById<M>(modeluri: URI, elementid: string, typeGuard: TypeGuard<M>): Promise<M>;
getElementById(modeluri: URI, elementid: string, format: string): Promise<string>;
getElementByName(modeluri: URI, elementname: string): Promise<AnyObject>;
getElementByName<M>(modeluri: URI, elementname: string, typeGuard: TypeGuard<M>, format?: string): Promise<M>;
getElementByName(modeluri: URI, elementname: string, format: string): Promise<string>;
create(modeluri: URI, model: AnyObject | string): Promise<AnyObject>;
create(modeluri: URI, model: AnyObject | string, format: string): Promise<string>;
create<M>(modeluri: URI, model: AnyObject | string, typeGuard: TypeGuard<M>): Promise<M>;
update(modeluri: URI, model: AnyObject | string): Promise<AnyObject>;
update<M>(modeluri: URI, model: string | string, typeGuard: TypeGuard<M>): Promise<M>;
update(modeluri: URI, model: AnyObject | string, format: string): Promise<AnyObject>;
delete(modeluri: URI): Promise<boolean>;
close(modeluri: URI): Promise<boolean>;
save(modeluri: URI): Promise<boolean>;
saveAll(): Promise<boolean>;
validate(modeluri: string): Promise<Diagnostic>;
getValidationConstraints(modeluri: string): Promise<string>;
getTypeSchema(modeluri: string): Promise<string>;
validate(modeluri: URI): Promise<Diagnostic>;
getValidationConstraints(modeluri: URI): Promise<string>;
getTypeSchema(modeluri: URI): Promise<string>;
getUiSchema(schemaname: string): Promise<string>;
configureServer(configuration: ServerConfiguration): Promise<boolean>;
ping(): Promise<boolean>;
edit(modeluri: string, command: ModelServerCommand): Promise<boolean>;
undo(modeluri: string): Promise<string>;
redo(modeluri: string): Promise<string>;
send(modelUri: string, message: ModelServerMessage): boolean;
subscribe(modeluri: string, options?: SubscriptionOptions): void;
unsubscribe(modeluri: string): boolean;
protected createSubscriptionPath(modeluri: string, options: SubscriptionOptions): string;
protected doSubscribe(listener: SubscriptionListener, modelUri: string, path: string): void;
protected isSocketOpen(modelUri: string): boolean;
edit(modeluri: URI, command: ModelServerCommand): Promise<boolean>;
undo(modeluri: URI): Promise<string>;
redo(modeluri: URI): Promise<string>;
send(modeluri: URI, message: ModelServerMessage): boolean;
subscribe(modeluri: URI, options?: SubscriptionOptions): void;
unsubscribe(modeluri: URI): boolean;
protected createSubscriptionPath(modeluri: URI, options: SubscriptionOptions): URI;
protected doSubscribe(listener: SubscriptionListener, modeluri: URI, path: URI): void;
protected isSocketOpen(modeluri: URI): boolean;
protected process<T>(request: Promise<AxiosResponse<ModelServerMessage>>, mapper: MessageDataMapper<T>): Promise<T>;

@@ -70,0 +71,0 @@ protected processMessageAsData<M>(request: Promise<AxiosResponse<M>>): Promise<M>;

@@ -18,4 +18,4 @@ "use strict";

exports.ModelServerClient = void 0;
/*********************************************************************************
* Copyright (c) 2021-2022 STMicroelectronics and others.
/********************************************************************************
* Copyright (c) 2021-2023 STMicroelectronics and others.
*

@@ -28,3 +28,3 @@ * This program and the accompanying materials are made available under the

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
const axios_1 = __importDefault(require("axios"));

@@ -46,7 +46,7 @@ const isomorphic_ws_1 = __importDefault(require("isomorphic-ws"));

initialize(baseUrl) {
this._baseUrl = baseUrl;
this._baseUrl = baseUrl.clone();
this.restClient = axios_1.default.create(this.getAxisConfig(baseUrl));
}
getAxisConfig(baseURL) {
return { baseURL };
return { baseURL: baseURL.toString() };
}

@@ -75,3 +75,3 @@ get(modeluri, formatOrGuard) {

getModelUris() {
return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.MODEL_URIS), model_server_message_1.MessageDataMapper.asStringArray);
return this.process(this.restClient.get(model_server_paths_1.ModelServerPaths.MODEL_URIS), model_server_message_1.MessageDataMapper.asURIArray);
}

@@ -123,6 +123,7 @@ getElementById(modeluri, elementid, formatOrGuard) {

configureServer(configuration) {
let { workspaceRoot, uiSchemaFolder } = configuration;
workspaceRoot = workspaceRoot.replace('file://', '');
uiSchemaFolder = uiSchemaFolder === null || uiSchemaFolder === void 0 ? void 0 : uiSchemaFolder.replace('file://', '');
return this.process(this.restClient.put(model_server_paths_1.ModelServerPaths.SERVER_CONFIGURE, { workspaceRoot, uiSchemaFolder }), model_server_message_1.MessageDataMapper.isSuccess);
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);
}

@@ -141,4 +142,4 @@ ping() {

}
send(modelUri, message) {
const openSocket = this.openSockets.get(modelUri);
send(modeluri, message) {
const openSocket = this.openSockets.get(modeluri.toString());
if (openSocket) {

@@ -152,7 +153,7 @@ openSocket.send(JSON.stringify(message));

if (!options.listener) {
const errorMsg = `${modeluri} : Cannot subscribe. No listener is present!'`;
const errorMsg = `${modeluri.toString()} : Cannot subscribe. No listener is present!'`;
throw new Error(errorMsg);
}
if (this.isSocketOpen(modeluri)) {
const errorMsg = `${modeluri} : Cannot open new socket, already subscribed!'`;
const errorMsg = `${modeluri.toString()} : Cannot open new socket, already subscribed!'`;
console.warn(errorMsg);

@@ -167,6 +168,6 @@ if (options.errorWhenUnsuccessful) {

unsubscribe(modeluri) {
const openSocket = this.openSockets.get(modeluri);
const openSocket = this.openSockets.get(modeluri.toString());
if (openSocket) {
openSocket.close();
this.openSockets.delete(modeluri);
this.openSockets.delete(modeluri.toString());
return true;

@@ -179,24 +180,24 @@ }

const { listener } = options, paramOptions = __rest(options, ["listener"]);
const queryParams = new URLSearchParams();
queryParams.append('modeluri', modeluri);
if (!options.format) {
options.format = this.defaultFormat;
}
Object.entries(paramOptions).forEach(entry => queryParams.append(entry[0], entry[1]));
queryParams.delete('errorWhenUnsuccessful');
return `${this._baseUrl}${model_server_paths_1.ModelServerPaths.SUBSCRIPTION}?${queryParams.toString()}`.replace(/^(http|https):\/\//i, 'ws://');
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.trim());
socket.onopen = event => listener.onOpen(modelUri, event);
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);
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, socket);
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) !== undefined;
isSocketOpen(modeluri) {
return this.openSockets.get(modeluri.toString()) !== undefined;
}

@@ -226,3 +227,3 @@ async process(request, mapper) {

catch (error) {
if (isAxiosError(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;

@@ -238,5 +239,2 @@ throw new model_server_client_api_v1_1.ModelServerError(message, error.code);

exports.ModelServerClient = ModelServerClient;
function isAxiosError(error) {
return error !== undefined && error instanceof Error && 'isAxiosError' in error && error['isAxiosError'];
}
/**

@@ -259,11 +257,11 @@ * Creates a modelserver message data mapper that maps the response either to a generic JSON object, a specific typed object or string.

function mapModel(model, guard, toString = false) {
const { modelUri, content } = model;
const { modeluri, content } = model;
if (guard) {
return { modelUri, content: type_util_1.asType(content, guard) };
return { modeluri, content: (0, type_util_1.asType)(content, guard) };
}
else if (toString) {
return { modelUri, content: type_util_1.asString(content) };
return { modeluri, content: (0, type_util_1.asString)(content) };
}
return { modelUri, content: type_util_1.asObject(content) };
return { modeluri, content: (0, type_util_1.asObject)(content) };
}
//# sourceMappingURL=model-server-client.js.map

@@ -6,3 +6,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
/*********************************************************************************
/********************************************************************************
* Copyright (c) 2021-2022 STMicroelectronics and others.

@@ -16,3 +16,3 @@ *

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
const assert_1 = require("assert");

@@ -22,2 +22,3 @@ const chai_1 = require("chai");

const sinon_1 = require("sinon");
const urijs_1 = __importDefault(require("urijs"));
const model_server_client_1 = require("./model-server-client");

@@ -29,3 +30,8 @@ const model_server_client_api_v1_1 = require("./model-server-client-api-v1");

let client;
const baseUrl = `http://localhost:8081${model_server_client_api_v1_1.ModelServerClientApiV1.API_ENDPOINT}`;
const baseUrl = new urijs_1.default({
protocol: 'http',
hostname: 'localhost',
port: '8081',
path: model_server_client_api_v1_1.ModelServerClientApiV1.API_ENDPOINT
});
beforeEach(() => {

@@ -41,4 +47,16 @@ client = new model_server_client_1.ModelServerClient();

const axios = client['restClient'];
chai_1.expect(axios.defaults.baseURL).to.be.equal(baseUrl);
(0, chai_1.expect)(axios.defaults.baseURL).to.be.equal(baseUrl.toString());
});
it('test createSubscriptionPath without trailing slash', () => {
client = new model_server_client_1.ModelServerClient();
client.initialize(baseUrl);
const subscriptionPath = client['createSubscriptionPath'](new urijs_1.default('foo'), {});
(0, chai_1.expect)(subscriptionPath.toString()).to.be.equal('ws://localhost:8081/api/v1/subscribe?modeluri=foo&format=json');
});
it('test createSubscriptionPath with trailing slash', () => {
client = new model_server_client_1.ModelServerClient();
client.initialize(new urijs_1.default(`${baseUrl}/`));
const subscriptionPath = client['createSubscriptionPath'](new urijs_1.default('foo'), {});
(0, chai_1.expect)(subscriptionPath.toString()).to.be.equal('ws://localhost:8081/api/v1/subscribe?modeluri=foo&format=json');
});
describe('test requests', () => {

@@ -51,8 +69,8 @@ it('getAll', done => {

let request = moxios_1.default.requests.at(0);
chai_1.expect(request.config.method).to.be.equal('get');
chai_1.expect(request.config.params).to.include({ format: 'json' });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_CRUD);
(0, chai_1.expect)(request.config.method).to.be.equal('get');
(0, chai_1.expect)(request.config.params).to.include({ format: 'json' });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_CRUD);
request = moxios_1.default.requests.at(1);
chai_1.expect(request.config.params).to.include({ format: 'xml' });
(0, chai_1.expect)(request.config.params).to.include({ format: 'xml' });
done();

@@ -65,6 +83,6 @@ });

const request = moxios_1.default.requests.mostRecent();
chai_1.expect(request.config.method).to.be.equal('get');
chai_1.expect(request.config.params).to.be.undefined;
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_URIS);
(0, chai_1.expect)(request.config.method).to.be.equal('get');
(0, chai_1.expect)(request.config.params).to.be.undefined;
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_URIS);
done();

@@ -74,3 +92,3 @@ });

it('getElementById', done => {
const modeluri = 'my/uri.model';
const modeluri = new urijs_1.default('my/uri.model');
const elementid = 'myElement';

@@ -81,8 +99,8 @@ client.getElementById(modeluri, elementid);

let request = moxios_1.default.requests.at(0);
chai_1.expect(request.config.method).to.be.equal('get');
chai_1.expect(request.config.params).to.include({ format: 'json', elementid, modeluri });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_ELEMENT);
(0, chai_1.expect)(request.config.method).to.be.equal('get');
(0, chai_1.expect)(request.config.params).to.include({ format: 'json', elementid, modeluri });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_ELEMENT);
request = moxios_1.default.requests.at(1);
chai_1.expect(request.config.params).to.include({ format: 'xml', elementid, modeluri });
(0, chai_1.expect)(request.config.params).to.include({ format: 'xml', elementid, modeluri });
done();

@@ -92,3 +110,3 @@ });

it('getElementByName', done => {
const modeluri = 'my/uri.model';
const modeluri = new urijs_1.default('my/uri.model');
const elementname = 'myElement';

@@ -99,8 +117,8 @@ client.getElementByName(modeluri, elementname);

let request = moxios_1.default.requests.at(0);
chai_1.expect(request.config.method).to.be.equal('get');
chai_1.expect(request.config.params).to.include({ format: 'json', elementname, modeluri });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_ELEMENT);
(0, chai_1.expect)(request.config.method).to.be.equal('get');
(0, chai_1.expect)(request.config.params).to.include({ format: 'json', elementname, modeluri });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_ELEMENT);
request = moxios_1.default.requests.at(1);
chai_1.expect(request.config.params).to.include({ format: 'xml', elementname, modeluri });
(0, chai_1.expect)(request.config.params).to.include({ format: 'xml', elementname, modeluri });
done();

@@ -110,10 +128,10 @@ });

it('delete', done => {
const modeluri = 'delete/me/please';
const modeluri = new urijs_1.default('delete/me/please');
client.delete(modeluri);
moxios_1.default.wait(() => {
const request = moxios_1.default.requests.mostRecent();
chai_1.expect(request.config.method).to.be.equal('delete');
chai_1.expect(request.config.params).to.include({ modeluri });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_CRUD);
(0, chai_1.expect)(request.config.method).to.be.equal('delete');
(0, chai_1.expect)(request.config.params).to.include({ modeluri });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_CRUD);
done();

@@ -123,10 +141,10 @@ });

it('close', done => {
const modeluri = 'delete/me/please';
const modeluri = new urijs_1.default('delete/me/please');
client.close(modeluri);
moxios_1.default.wait(() => {
const request = moxios_1.default.requests.mostRecent();
chai_1.expect(request.config.method).to.be.equal('post');
chai_1.expect(request.config.params).to.include({ modeluri });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.CLOSE);
(0, chai_1.expect)(request.config.method).to.be.equal('post');
(0, chai_1.expect)(request.config.params).to.include({ modeluri });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.CLOSE);
done();

@@ -136,3 +154,3 @@ });

it('create', done => {
const modeluri = 'delete/me/please';
const modeluri = new urijs_1.default('delete/me/please');
const model = { name: 'myModel', id: 'myModelId' };

@@ -144,9 +162,9 @@ const data = JSON.stringify(model);

let request = moxios_1.default.requests.at(0);
chai_1.expect(request.config.method).to.be.equal('post');
chai_1.expect(request.config.data).to.be.equal(JSON.stringify({ data }));
chai_1.expect(request.config.params).to.include({ format: 'json', modeluri });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_CRUD);
(0, chai_1.expect)(request.config.method).to.be.equal('post');
(0, chai_1.expect)(request.config.data).to.be.equal(JSON.stringify({ data }));
(0, chai_1.expect)(request.config.params).to.include({ format: 'json', modeluri });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_CRUD);
request = moxios_1.default.requests.at(1);
chai_1.expect(request.config.params).to.include({ format: 'xml', modeluri });
(0, chai_1.expect)(request.config.params).to.include({ format: 'xml', modeluri });
done();

@@ -156,3 +174,3 @@ });

it('update', done => {
const modeluri = 'delete/me/please';
const modeluri = new urijs_1.default('delete/me/please');
const model = { name: 'myModel', id: 'myModelId' };

@@ -164,9 +182,9 @@ const data = JSON.stringify(model);

let request = moxios_1.default.requests.at(0);
chai_1.expect(request.config.method).to.be.equal('patch');
chai_1.expect(request.config.data).to.be.equal(JSON.stringify({ data }));
chai_1.expect(request.config.params).to.include({ format: 'json', modeluri });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_CRUD);
(0, chai_1.expect)(request.config.method).to.be.equal('patch');
(0, chai_1.expect)(request.config.data).to.be.equal(JSON.stringify({ data }));
(0, chai_1.expect)(request.config.params).to.include({ format: 'json', modeluri });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.MODEL_CRUD);
request = moxios_1.default.requests.at(1);
chai_1.expect(request.config.params).to.include({ format: 'xml', modeluri });
(0, chai_1.expect)(request.config.params).to.include({ format: 'xml', modeluri });
done();

@@ -176,10 +194,10 @@ });

it('save', done => {
const modeluri = 'save/me/please';
const modeluri = new urijs_1.default('save/me/please');
client.save(modeluri);
moxios_1.default.wait(() => {
const request = moxios_1.default.requests.mostRecent();
chai_1.expect(request.config.method).to.be.equal('get');
chai_1.expect(request.config.params).to.include({ modeluri });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.SAVE);
(0, chai_1.expect)(request.config.method).to.be.equal('get');
(0, chai_1.expect)(request.config.params).to.include({ modeluri });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.SAVE);
done();

@@ -192,6 +210,6 @@ });

const request = moxios_1.default.requests.mostRecent();
chai_1.expect(request.config.method).to.be.equal('get');
chai_1.expect(request.config.params).to.be.undefined;
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.SAVE_ALL);
(0, chai_1.expect)(request.config.method).to.be.equal('get');
(0, chai_1.expect)(request.config.params).to.be.undefined;
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.SAVE_ALL);
done();

@@ -201,10 +219,10 @@ });

it('validate', done => {
const modeluri = 'validate/me/please';
const modeluri = new urijs_1.default('validate/me/please');
client.validate(modeluri);
moxios_1.default.wait(() => {
const request = moxios_1.default.requests.mostRecent();
chai_1.expect(request.config.method).to.be.equal('get');
chai_1.expect(request.config.params).to.include({ modeluri });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.VALIDATION);
(0, chai_1.expect)(request.config.method).to.be.equal('get');
(0, chai_1.expect)(request.config.params).to.include({ modeluri });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.VALIDATION);
done();

@@ -214,10 +232,10 @@ });

it('getValidationConstraints', done => {
const modeluri = 'validate/me/please';
const modeluri = new urijs_1.default('validate/me/please');
client.getValidationConstraints(modeluri);
moxios_1.default.wait(() => {
const request = moxios_1.default.requests.mostRecent();
chai_1.expect(request.config.method).to.be.equal('get');
chai_1.expect(request.config.params).to.include({ modeluri });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.VALIDATION_CONSTRAINTS);
(0, chai_1.expect)(request.config.method).to.be.equal('get');
(0, chai_1.expect)(request.config.params).to.include({ modeluri });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.VALIDATION_CONSTRAINTS);
done();

@@ -227,10 +245,10 @@ });

it('getTypeSchema', done => {
const modeluri = 'my/model/uri';
const modeluri = new urijs_1.default('my/model/uri');
client.getTypeSchema(modeluri);
moxios_1.default.wait(() => {
const request = moxios_1.default.requests.mostRecent();
chai_1.expect(request.config.method).to.be.equal('get');
chai_1.expect(request.config.params).to.include({ modeluri });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.TYPE_SCHEMA);
(0, chai_1.expect)(request.config.method).to.be.equal('get');
(0, chai_1.expect)(request.config.params).to.include({ modeluri });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.TYPE_SCHEMA);
done();

@@ -244,6 +262,6 @@ });

const request = moxios_1.default.requests.mostRecent();
chai_1.expect(request.config.method).to.be.equal('get');
chai_1.expect(request.config.params).to.include({ schemaname });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.UI_SCHEMA);
(0, chai_1.expect)(request.config.method).to.be.equal('get');
(0, chai_1.expect)(request.config.params).to.include({ schemaname });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.UI_SCHEMA);
done();

@@ -254,4 +272,4 @@ });

const configuration = {
workspaceRoot: 'myRoot',
uiSchemaFolder: 'mySchemaFolder'
workspaceRoot: new urijs_1.default('myRoot'),
uiSchemaFolder: new urijs_1.default('mySchemaFolder')
};

@@ -261,7 +279,10 @@ client.configureServer(configuration);

const request = moxios_1.default.requests.mostRecent();
chai_1.expect(request.config.method).to.be.equal('put');
chai_1.expect(request.config.data).to.equal(JSON.stringify(configuration));
chai_1.expect(request.config.params).to.be.undefined;
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.SERVER_CONFIGURE);
(0, chai_1.expect)(request.config.method).to.be.equal('put');
(0, chai_1.expect)(request.config.data).to.equal(JSON.stringify({
workspaceRoot: configuration.workspaceRoot.toString(),
uiSchemaFolder: configuration.uiSchemaFolder.toString()
}));
(0, chai_1.expect)(request.config.params).to.be.undefined;
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.SERVER_CONFIGURE);
done();

@@ -274,6 +295,6 @@ });

const request = moxios_1.default.requests.mostRecent();
chai_1.expect(request.config.method).to.be.equal('get');
chai_1.expect(request.config.params).to.be.undefined;
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.SERVER_PING);
(0, chai_1.expect)(request.config.method).to.be.equal('get');
(0, chai_1.expect)(request.config.params).to.be.undefined;
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.SERVER_PING);
done();

@@ -283,3 +304,3 @@ });

it('edit', done => {
const modeluri = 'edit/me/please';
const modeluri = new urijs_1.default('edit/me/please');
const command = new command_model_1.SetCommand({

@@ -292,7 +313,7 @@ eClass: 'http://www.eclipsesource.com/modelserver/example/coffeemodel#//Workflow',

const request = moxios_1.default.requests.at(0);
chai_1.expect(request.config.method).to.be.equal('patch');
chai_1.expect(request.config.data).to.be.equal(JSON.stringify({ data: command }));
chai_1.expect(request.config.params).to.include({ format: 'json', modeluri });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.EDIT);
(0, chai_1.expect)(request.config.method).to.be.equal('patch');
(0, chai_1.expect)(request.config.data).to.be.equal(JSON.stringify({ data: command }));
(0, chai_1.expect)(request.config.params).to.include({ format: 'json', modeluri });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.EDIT);
done();

@@ -302,10 +323,10 @@ });

it('undo', done => {
const modeluri = 'undo/me/please';
const modeluri = new urijs_1.default('undo/me/please');
client.undo(modeluri);
moxios_1.default.wait(() => {
const request = moxios_1.default.requests.mostRecent();
chai_1.expect(request.config.method).to.be.equal('get');
chai_1.expect(request.config.params).to.be.include({ modeluri });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.UNDO);
(0, chai_1.expect)(request.config.method).to.be.equal('get');
(0, chai_1.expect)(request.config.params).to.be.include({ modeluri });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.UNDO);
done();

@@ -315,10 +336,10 @@ });

it('redo', done => {
const modeluri = 'redo/me/please';
const modeluri = new urijs_1.default('redo/me/please');
client.redo(modeluri);
moxios_1.default.wait(() => {
const request = moxios_1.default.requests.mostRecent();
chai_1.expect(request.config.method).to.be.equal('get');
chai_1.expect(request.config.params).to.be.include({ modeluri });
chai_1.expect(request.config.baseURL).to.be.equal(baseUrl);
chai_1.expect(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.REDO);
(0, chai_1.expect)(request.config.method).to.be.equal('get');
(0, chai_1.expect)(request.config.params).to.be.include({ modeluri });
(0, chai_1.expect)(request.config.baseURL).to.be.equal(baseUrl.toString());
(0, chai_1.expect)(request.config.url).to.be.equal(model_server_paths_1.ModelServerPaths.REDO);
done();

@@ -329,3 +350,3 @@ });

describe('test responses', () => {
it('ping ', done => {
it('ping', done => {
const expectedMsg = {

@@ -335,3 +356,3 @@ data: '',

};
const onFulfilled = sinon_1.spy();
const onFulfilled = (0, sinon_1.spy)();
client.ping().then(onFulfilled);

@@ -344,3 +365,3 @@ moxios_1.default.wait(async () => {

});
assert_1.strictEqual(onFulfilled.getCall(0).args[0], true);
(0, assert_1.strictEqual)(onFulfilled.getCall(0).args[0], true);
done();

@@ -351,3 +372,3 @@ });

const model1 = {
modelUri: 'path/to/model1',
modeluri: 'file:/path/to/model1',
content: {

@@ -358,3 +379,3 @@ name: 'coffee'

const model2 = {
modelUri: 'path/to/model2',
modeluri: 'file:/path/to/model2',
content: {

@@ -366,8 +387,8 @@ name: 'coffee'

data: {
[model1.modelUri]: model1.content,
[model2.modelUri]: model2.content
[model1.modeluri]: model1.content,
[model2.modeluri]: model2.content
},
type: 'success'
};
const onFulfilled = sinon_1.spy();
const onFulfilled = (0, sinon_1.spy)();
client.getAll().then(onFulfilled);

@@ -381,3 +402,4 @@ moxios_1.default.wait(async () => {

const result = onFulfilled.getCall(0).args[0];
chai_1.expect(result).to.deep.include.members([model2, model1]);
(0, chai_1.expect)(result).to.be.an('array').of.length(2);
(0, chai_1.expect)(result).to.deep.include.members([model1, model2]);
done();

@@ -384,0 +406,0 @@ });

@@ -0,1 +1,2 @@

import URI from 'urijs';
import { ModelUpdateResult } from './model-server-client-api-v2';

@@ -54,3 +55,3 @@ import * as Type from './utils/type-util';

/** The uri of the model. */
modelUri: string;
modeluri: string;
/** The model content. */

@@ -66,2 +67,3 @@ content: C;

function is(object: unknown): object is Model;
function toString(model: Model): string;
}

@@ -71,3 +73,3 @@ /**

*/
export declare type Mapper<M, D = unknown> = (message: M) => D;
export type Mapper<M, D = unknown> = (message: M) => D;
/**

@@ -80,3 +82,3 @@ * A Mapper which directly returns the message.

*/
export declare type MessageDataMapper<D = unknown> = (message: ModelServerMessage) => D;
export type MessageDataMapper<D = unknown> = (message: ModelServerMessage) => D;
/**

@@ -114,2 +116,9 @@ * A collection of utility functions to map the `data` property of a {@link ModelServerMessage} to a specific type.

/**
* Maps the {@link ModelServerMessage.data} property of the given message to a URI[].
* @param message The message to map.
* @returns The `data` property as `URI[]`.
* @throws {@link Error} if the 'data' property is not an URI array.
*/
function asURIArray(message: ModelServerMessage): URI[];
/**
* Maps the {@link ModelServerMessage.data} property of the given message to an {@link AnyObject}.

@@ -116,0 +125,0 @@ * @param message The message to map.

"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {

@@ -17,3 +21,3 @@ if (k2 === undefined) k2 = k;

var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);

@@ -33,3 +37,3 @@ return result;

* SPDX-License-Identifier: EPL-2.0 OR MIT
********************************************************************************/
*******************************************************************************/
const jsonpatch = __importStar(require("fast-json-patch"));

@@ -92,5 +96,9 @@ const fast_json_patch_1 = require("fast-json-patch");

function is(object) {
return Type.AnyObject.is(object) && Type.isString(object, 'modelUri') && Type.isObject(object, 'content');
return Type.AnyObject.is(object) && Type.isString(object, 'modeluri') && Type.isObject(object, 'content');
}
Model.is = is;
function toString(model) {
return JSON.stringify(model, undefined, 2);
}
Model.toString = toString;
})(Model = exports.Model || (exports.Model = {}));

@@ -100,3 +108,4 @@ /**

*/
exports.IdentityMapper = m => m;
const IdentityMapper = m => m;
exports.IdentityMapper = IdentityMapper;
/**

@@ -147,2 +156,12 @@ * A collection of utility functions to map the `data` property of a {@link ModelServerMessage} to a specific type.

/**
* Maps the {@link ModelServerMessage.data} property of the given message to a URI[].
* @param message The message to map.
* @returns The `data` property as `URI[]`.
* @throws {@link Error} if the 'data' property is not an URI array.
*/
function asURIArray(message) {
return Type.asURIArray(message.data);
}
MessageDataMapper.asURIArray = asURIArray;
/**
* Maps the {@link ModelServerMessage.data} property of the given message to an {@link AnyObject}.

@@ -193,10 +212,15 @@ * @param message The message to map.

const patch = data ? data.patch : undefined;
if (patch && patch_utils_1.Operations.isPatch(patch)) {
const allPatches = data ? data.allPatches : undefined;
if (patch || allPatches) {
return {
success: isSuccess(message),
patch,
patchModel: (oldModel, copy) => {
const modelToPatch = copy ? fast_json_patch_1.deepClone(oldModel) : oldModel;
return jsonpatch.applyPatch(modelToPatch, patch).newDocument;
}
patchModel: (oldModel, copy, modeluri) => {
const modelToPatch = copy ? (0, fast_json_patch_1.deepClone)(oldModel) : oldModel;
const patchToApply = modeluri ? getPatch(allPatches, modeluri) : patch_utils_1.Operations.isPatch(patch) ? patch : undefined;
return patchToApply
? jsonpatch.applyPatch(modelToPatch, patchToApply).newDocument
: modelToPatch;
},
allPatches
};

@@ -213,3 +237,7 @@ }

MessageDataMapper.patchModel = patchModel;
function getPatch(patches, modeluri) {
var _a;
return (_a = patches.find(mp => mp.modelUri === modeluri.toString())) === null || _a === void 0 ? void 0 : _a.patch;
}
})(MessageDataMapper = exports.MessageDataMapper || (exports.MessageDataMapper = {}));
//# sourceMappingURL=model-server-message.js.map

@@ -1,2 +0,2 @@

/*********************************************************************************
/********************************************************************************
* Copyright (c) 2021-2022 STMicroelectronics and others.

@@ -10,8 +10,9 @@ *

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
import { Operation } from 'fast-json-patch';
import * as URI from 'urijs';
import { ModelServerObjectV2 } from '.';
import { ModelServerMessage } from './model-server-message';
import { CommandExecutionResult } from './model/command-model';
import { Diagnostic } from './model/diagnostic';
import { ModelServerMessage } from './model-server-message';
import { AnyObject } from './utils/type-util';

@@ -23,3 +24,3 @@ /**

export interface ModelServerNotification {
modelUri: string;
modeluri: URI;
type: string;

@@ -119,3 +120,3 @@ }

*/
export declare type UnknownNotification = ModelServerNotification & ModelServerMessage;
export type UnknownNotification = ModelServerNotification & ModelServerMessage;
export declare namespace UnknownNotification {

@@ -122,0 +123,0 @@ function is(object?: unknown): object is UnknownNotification;

@@ -9,3 +9,3 @@ "use strict";

function is(object) {
return type_util_1.AnyObject.is(object) && type_util_1.isString(object, 'modelUri') && type_util_1.isString(object, 'type');
return type_util_1.AnyObject.is(object) && (0, type_util_1.isObject)(object, 'modeluri') && (0, type_util_1.isString)(object, 'type');
}

@@ -12,0 +12,0 @@ ModelServerNotification.is = is;

@@ -10,3 +10,3 @@ /********************************************************************************

* SPDX-License-Identifier: EPL-2.0 OR MIT
********************************************************************************/
*******************************************************************************/
/**

@@ -13,0 +13,0 @@ * Utility collection of all the available endpoint paths of a (default) modelserver.

@@ -13,3 +13,3 @@ "use strict";

* SPDX-License-Identifier: EPL-2.0 OR MIT
********************************************************************************/
*******************************************************************************/
/**

@@ -16,0 +16,0 @@ * Utility collection of all the available endpoint paths of a (default) modelserver.

@@ -1,2 +0,2 @@

export declare type DataValueType = boolean | number | string;
export type DataValueType = boolean | number | string;
export declare class ModelServerObject {

@@ -3,0 +3,0 @@ readonly eClass: string;

@@ -13,7 +13,7 @@ "use strict";

* SPDX-License-Identifier: EPL-2.0 OR MIT
********************************************************************************/
*******************************************************************************/
const type_util_1 = require("../utils/type-util");
class ModelServerObject {
static is(object) {
return type_util_1.AnyObject.is(object) && type_util_1.isString(object, 'eClass');
return type_util_1.AnyObject.is(object) && (0, type_util_1.isString)(object, 'eClass');
}

@@ -37,3 +37,3 @@ }

static is(object) {
return type_util_1.AnyObject.is(object) && type_util_1.isString(object, '$type');
return type_util_1.AnyObject.is(object) && (0, type_util_1.isString)(object, '$type');
}

@@ -47,3 +47,3 @@ }

static is(object) {
return type_util_1.AnyObject.is(object) && type_util_1.isString(object, '$type') && type_util_1.isString(object, '$id');
return type_util_1.AnyObject.is(object) && (0, type_util_1.isString)(object, '$type') && (0, type_util_1.isString)(object, '$id');
}

@@ -63,3 +63,3 @@ }

static is(object) {
return type_util_1.AnyObject.is(object) && type_util_1.isString(object, '$type') && type_util_1.isString(object, '$ref');
return type_util_1.AnyObject.is(object) && (0, type_util_1.isString)(object, '$type') && (0, type_util_1.isString)(object, '$ref');
}

@@ -66,0 +66,0 @@ }

@@ -10,3 +10,3 @@ /********************************************************************************

* SPDX-License-Identifier: EPL-2.0 OR MIT
********************************************************************************/
*******************************************************************************/
import { ModelServerObject, ModelServerReferenceDescription } from './base-model';

@@ -13,0 +13,0 @@ export declare namespace ChangePackage {

@@ -13,3 +13,3 @@ "use strict";

* SPDX-License-Identifier: EPL-2.0 OR MIT
********************************************************************************/
*******************************************************************************/
const base_model_1 = require("./base-model");

@@ -16,0 +16,0 @@ var ChangePackage;

@@ -54,3 +54,3 @@ import { DataValueType, ModelServerObject, ModelServerReferenceDescription } from './base-model';

static readonly TYPE = "set";
constructor(owner: ModelServerReferenceDescription, feature: string, changedValues: DataValueType[] | ModelServerReferenceDescription[]);
constructor(owner: ModelServerReferenceDescription, feature: string, changedValues: DataValueType[] | ModelServerReferenceDescription[] | ModelServerObject[]);
static is(object?: unknown): object is ModelServerCommand;

@@ -57,0 +57,0 @@ }

@@ -13,3 +13,3 @@ "use strict";

* SPDX-License-Identifier: EPL-2.0 OR MIT
********************************************************************************/
*******************************************************************************/
const model_server_utils_1 = require("../utils/model-server-utils");

@@ -70,3 +70,3 @@ const base_model_1 = require("./base-model");

this.feature = feature;
if (model_server_utils_1.isNumberArray(toDelete)) {
if ((0, model_server_utils_1.isNumberArray)(toDelete)) {
this.indices = toDelete;

@@ -92,3 +92,3 @@ }

}
if (model_server_utils_1.isModelServerObjectArray(toAdd)) {
if ((0, model_server_utils_1.isModelServerObjectArray)(toAdd)) {
const objectValues = toAdd.map((o, i) => new base_model_1.ModelServerReferenceDescription(o.eClass, `//@objectsToAdd.${i}`));

@@ -113,5 +113,8 @@ this.objectsToAdd = toAdd;

this.feature = feature;
if (model_server_utils_1.isModelServerReferenceDescriptionArray(changedValues)) {
if ((0, model_server_utils_1.isModelServerReferenceDescriptionArray)(changedValues)) {
this.objectValues = changedValues;
}
else if ((0, model_server_utils_1.isModelServerObjectArray)(changedValues)) {
this.objectsToAdd = changedValues;
}
else {

@@ -118,0 +121,0 @@ this.dataValues = changedValues;

@@ -13,6 +13,3 @@ "use strict";

* SPDX-License-Identifier: EPL-2.0 OR MIT
*
* Contributors:
* Vincent HEMERY (CS GROUP - France) - initial API and implementation
********************************************************************************/
*******************************************************************************/
const type_util_1 = require("../utils/type-util");

@@ -38,9 +35,9 @@ /** The bit mask value for okay severity */

return (type_util_1.AnyObject.is(object) &&
type_util_1.isNumber(object, 'severity') &&
type_util_1.isString(object, 'message') &&
type_util_1.isString(object, 'source') &&
type_util_1.isNumber(object, 'code') &&
type_util_1.isArray(object, 'data') &&
type_util_1.isArray(object, 'children') &&
type_util_1.isString(object, 'id'));
(0, type_util_1.isNumber)(object, 'severity') &&
(0, type_util_1.isString)(object, 'message') &&
(0, type_util_1.isString)(object, 'source') &&
(0, type_util_1.isNumber)(object, 'code') &&
(0, type_util_1.isArray)(object, 'data') &&
(0, type_util_1.isArray)(object, 'children') &&
(0, type_util_1.isString)(object, 'id'));
}

@@ -147,5 +144,3 @@ Diagnostic.is = is;

const max = worstOf(diagnostics);
// Recompute IDs of the diagnostics because they are now in
// a new tree structure and their paths have changed.
return recomputeIDs({
return {
severity: max.severity,

@@ -158,3 +153,3 @@ message: `Diagnosis of ${nonOK.length} problems.`,

id: '/'
});
};
}

@@ -185,13 +180,3 @@ Diagnostic.merge = merge;

Diagnostic.worstOf = worstOf;
/**
* Assign IDs of the diagnostics in a tree according to the EMF
* path-structured URI fragment algorithm.
*/
function recomputeIDs(diagnostic, base = '/') {
var _a;
diagnostic.id = base;
(_a = diagnostic.children) === null || _a === void 0 ? void 0 : _a.forEach((child, i) => recomputeIDs(child, `${base}/@children.${i}`));
return diagnostic;
}
})(Diagnostic = exports.Diagnostic || (exports.Diagnostic = {}));
//# sourceMappingURL=diagnostic.js.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/*********************************************************************************
/********************************************************************************
* Copyright (c) 2022 STMicroelectronics and others.

@@ -12,3 +12,3 @@ *

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
const chai_1 = require("chai");

@@ -19,9 +19,9 @@ const diagnostic_1 = require("./diagnostic");

const ok = diagnostic_1.Diagnostic.ok();
chai_1.expect(ok.severity).to.be.equal(diagnostic_1.OK);
chai_1.expect(ok.source).to.be.empty;
chai_1.expect(ok.code).to.be.equal(0);
chai_1.expect(ok.children).to.be.empty;
chai_1.expect(ok.data).to.be.empty;
chai_1.expect(ok.exception).to.be.undefined;
chai_1.expect(ok.message).to.be.equal('OK');
(0, chai_1.expect)(ok.severity).to.be.equal(diagnostic_1.OK);
(0, chai_1.expect)(ok.source).to.be.empty;
(0, chai_1.expect)(ok.code).to.be.equal(0);
(0, chai_1.expect)(ok.children).to.be.empty;
(0, chai_1.expect)(ok.data).to.be.empty;
(0, chai_1.expect)(ok.exception).to.be.undefined;
(0, chai_1.expect)(ok.message).to.be.equal('OK');
});

@@ -31,3 +31,3 @@ describe('merge', () => {

const merged = diagnostic_1.Diagnostic.merge();
chai_1.expect(merged).to.be.eql(diagnostic_1.Diagnostic.ok());
(0, chai_1.expect)(merged).to.be.eql(diagnostic_1.Diagnostic.ok());
});

@@ -37,12 +37,12 @@ it('one arg', () => {

const merged = diagnostic_1.Diagnostic.merge(only);
chai_1.expect(merged).to.be.eql(only);
(0, chai_1.expect)(merged).to.be.eql(only);
});
it('several args', () => {
const warning = Object.assign(Object.assign({}, diag(diagnostic_1.WARNING, 'Not so bad.')), { source: 'a' });
const ok = Object.assign(Object.assign({}, diag(diagnostic_1.OK, 'It\'s okay.')), { source: 'b' });
const ok = Object.assign(Object.assign({}, diag(diagnostic_1.OK, "It's okay.")), { source: 'b' });
const error = Object.assign(Object.assign({}, diag(diagnostic_1.ERROR, 'Pretty bad.')), { source: 'c' });
const merged = diagnostic_1.Diagnostic.merge(warning, ok, error);
chai_1.expect(merged.severity).to.be.equal(diagnostic_1.ERROR);
chai_1.expect(merged.source).to.be.equal('c');
chai_1.expect(merged.children).to.be.eql([warning, error]);
(0, chai_1.expect)(merged.severity).to.be.equal(diagnostic_1.ERROR);
(0, chai_1.expect)(merged.source).to.be.equal('c');
(0, chai_1.expect)(merged.children).to.be.eql([warning, error]);
});

@@ -53,3 +53,3 @@ });

const worst = diagnostic_1.Diagnostic.worstOf([]);
chai_1.expect(worst).to.be.eql(diagnostic_1.Diagnostic.ok());
(0, chai_1.expect)(worst).to.be.eql(diagnostic_1.Diagnostic.ok());
});

@@ -59,10 +59,10 @@ it('one arg', () => {

const worst = diagnostic_1.Diagnostic.worstOf([only]);
chai_1.expect(worst).to.be.equal(only);
(0, chai_1.expect)(worst).to.be.equal(only);
});
it('several args', () => {
const warning = Object.assign(Object.assign({}, diag(diagnostic_1.WARNING, 'Not so bad.')), { source: 'a' });
const ok = Object.assign(Object.assign({}, diag(diagnostic_1.OK, 'It\'s okay.')), { source: 'b' });
const ok = Object.assign(Object.assign({}, diag(diagnostic_1.OK, "It's okay.")), { source: 'b' });
const error = Object.assign(Object.assign({}, diag(diagnostic_1.ERROR, 'Pretty bad.')), { source: 'c' });
const worst = diagnostic_1.Diagnostic.worstOf([warning, ok, error]);
chai_1.expect(worst).to.be.equal(error);
(0, chai_1.expect)(worst).to.be.equal(error);
});

@@ -69,0 +69,0 @@ });

import WebSocket from 'isomorphic-ws';
import URI from 'urijs';
import { CloseNotification, DirtyStateNotification, ErrorNotification, FullUpdateNotification, IncrementalUpdateNotification, IncrementalUpdateNotificationV2, ModelServerNotification, UnknownNotification, ValidationNotification } from './model-server-notification';

@@ -9,6 +10,6 @@ /**

export interface SubscriptionListener {
onOpen(modelUri: string, event: WebSocket.Event): void;
onClose(modelUri: string, event: WebSocket.CloseEvent): void;
onError(modelUri: string, event: WebSocket.ErrorEvent): void;
onMessage(modelUri: string, event: WebSocket.MessageEvent): void;
onOpen(modeluri: URI, event: WebSocket.Event): void;
onClose(modeluri: URI, event: WebSocket.CloseEvent): void;
onError(modeluri: URI, event: WebSocket.ErrorEvent): void;
onMessage(modeluri: URI, event: WebSocket.MessageEvent): void;
}

@@ -74,6 +75,6 @@ /**

constructor(notificationListener?: ModelServerNotificationListener);
onOpen(modelUri: string, _event: WebSocket.Event): void;
onClose(modelUri: string, event: WebSocket.CloseEvent): void;
onError(modelUri: string, event: WebSocket.ErrorEvent): void;
onMessage(modelUri: string, event: WebSocket.MessageEvent): void;
onOpen(modeluri: URI, _event: WebSocket.Event): void;
onClose(modeluri: URI, event: WebSocket.CloseEvent): void;
onError(modeluri: URI, event: WebSocket.ErrorEvent): void;
onMessage(modeluri: URI, event: WebSocket.MessageEvent): void;
}

@@ -90,3 +91,3 @@ /**

constructor(notificationListener?: ModelServerNotificationListenerV2);
onMessage(modelUri: string, event: WebSocket.MessageEvent): void;
onMessage(modeluri: URI, event: WebSocket.MessageEvent): void;
}

@@ -93,0 +94,0 @@ /**

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NotificationSubscriptionListenerV2 = exports.NotificationSubscriptionListener = void 0;
/*********************************************************************************
/********************************************************************************
* Copyright (c) 2021-2022 STMicroelectronics and others.

@@ -13,3 +13,3 @@ *

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
const fast_json_patch_1 = require("fast-json-patch");

@@ -29,15 +29,15 @@ const _1 = require(".");

}
onOpen(modelUri, _event) {
onOpen(modeluri, _event) {
var _a, _b;
(_b = (_a = this.notificationListener).onOpen) === null || _b === void 0 ? void 0 : _b.call(_a, { modelUri, type: model_server_message_1.MessageType.open });
(_b = (_a = this.notificationListener).onOpen) === null || _b === void 0 ? void 0 : _b.call(_a, { modeluri, type: model_server_message_1.MessageType.open });
}
onClose(modelUri, event) {
onClose(modeluri, event) {
var _a, _b;
(_b = (_a = this.notificationListener).onClose) === null || _b === void 0 ? void 0 : _b.call(_a, { modelUri, code: event.code, reason: event.reason, type: model_server_message_1.MessageType.close });
(_b = (_a = this.notificationListener).onClose) === null || _b === void 0 ? void 0 : _b.call(_a, { modeluri, code: event.code, reason: event.reason, type: model_server_message_1.MessageType.close });
}
onError(modelUri, event) {
onError(modeluri, event) {
var _a, _b;
(_b = (_a = this.notificationListener).onError) === null || _b === void 0 ? void 0 : _b.call(_a, { modelUri, error: event.error, type: model_server_message_1.MessageType.error });
(_b = (_a = this.notificationListener).onError) === null || _b === void 0 ? void 0 : _b.call(_a, { modeluri, error: event.error, type: model_server_message_1.MessageType.error });
}
onMessage(modelUri, event) {
onMessage(modeluri, event) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;

@@ -49,3 +49,3 @@ const message = JSON.parse(event.data.toString());

case model_server_message_1.MessageType.dirtyState: {
(_b = (_a = this.notificationListener).onDirtyStateChanged) === null || _b === void 0 ? void 0 : _b.call(_a, { modelUri, isDirty: model_server_message_1.MessageDataMapper.asBoolean(message), type });
(_b = (_a = this.notificationListener).onDirtyStateChanged) === null || _b === void 0 ? void 0 : _b.call(_a, { modeluri, isDirty: model_server_message_1.MessageDataMapper.asBoolean(message), type });
break;

@@ -55,7 +55,7 @@ }

case model_server_message_1.MessageType.success: {
(_d = (_c = this.notificationListener).onSuccess) === null || _d === void 0 ? void 0 : _d.call(_c, { modelUri, type });
(_d = (_c = this.notificationListener).onSuccess) === null || _d === void 0 ? void 0 : _d.call(_c, { modeluri, type });
break;
}
case model_server_message_1.MessageType.error: {
(_f = (_e = this.notificationListener).onError) === null || _f === void 0 ? void 0 : _f.call(_e, { modelUri, error: model_server_message_1.MessageDataMapper.asString(message), type });
(_f = (_e = this.notificationListener).onError) === null || _f === void 0 ? void 0 : _f.call(_e, { modeluri, error: model_server_message_1.MessageDataMapper.asString(message), type });
break;

@@ -65,3 +65,3 @@ }

(_h = (_g = this.notificationListener).onIncrementalUpdate) === null || _h === void 0 ? void 0 : _h.call(_g, {
modelUri,
modeluri,
result: model_server_message_1.MessageDataMapper.as(message, command_model_1.CommandExecutionResult.is),

@@ -73,11 +73,11 @@ type

case model_server_message_1.MessageType.fullUpdate: {
(_k = (_j = this.notificationListener).onFullUpdate) === null || _k === void 0 ? void 0 : _k.call(_j, { modelUri, model: model_server_message_1.MessageDataMapper.asObject(message), type });
(_k = (_j = this.notificationListener).onFullUpdate) === null || _k === void 0 ? void 0 : _k.call(_j, { modeluri, model: model_server_message_1.MessageDataMapper.asObject(message), type });
break;
}
case model_server_message_1.MessageType.validationResult: {
(_m = (_l = this.notificationListener).onValidation) === null || _m === void 0 ? void 0 : _m.call(_l, { modelUri, diagnostic: model_server_message_1.MessageDataMapper.as(message, diagnostic_1.Diagnostic.is), type });
(_m = (_l = this.notificationListener).onValidation) === null || _m === void 0 ? void 0 : _m.call(_l, { modeluri, diagnostic: model_server_message_1.MessageDataMapper.as(message, diagnostic_1.Diagnostic.is), type });
break;
}
default: {
(_p = (_o = this.notificationListener).onUnknown) === null || _p === void 0 ? void 0 : _p.call(_o, Object.assign(Object.assign({}, message), { modelUri }));
(_p = (_o = this.notificationListener).onUnknown) === null || _p === void 0 ? void 0 : _p.call(_o, Object.assign(Object.assign({}, message), { modeluri }));
}

@@ -101,3 +101,3 @@ }

}
onMessage(modelUri, event) {
onMessage(modeluri, event) {
var _a, _b;

@@ -112,7 +112,7 @@ const message = JSON.parse(event.data.toString());

type: message.type,
modelUri,
modeluri,
patch,
patchModel: (model, copy) => {
const modelToPatch = copy ? fast_json_patch_1.deepClone(model) : model;
return fast_json_patch_1.applyPatch(modelToPatch, patch).newDocument;
const modelToPatch = copy ? (0, fast_json_patch_1.deepClone)(model) : model;
return (0, fast_json_patch_1.applyPatch)(modelToPatch, patch).newDocument;
}

@@ -123,3 +123,3 @@ });

default: {
super.onMessage(modelUri, event);
super.onMessage(modeluri, event);
}

@@ -126,0 +126,0 @@ }

@@ -10,7 +10,7 @@ /********************************************************************************

* SPDX-License-Identifier: EPL-2.0 OR MIT
********************************************************************************/
*******************************************************************************/
import { DataValueType, ModelServerObject, ModelServerReferenceDescription } from '../model/base-model';
export declare function isNumberArray(array: Array<number | ModelServerReferenceDescription>): array is number[];
export declare function isModelServerObjectArray(array: Array<DataValueType | ModelServerObject>): array is ModelServerObject[];
export declare function isModelServerReferenceDescriptionArray(array: Array<DataValueType | ModelServerReferenceDescription>): array is ModelServerReferenceDescription[];
export declare function isModelServerReferenceDescriptionArray(array: Array<DataValueType | ModelServerReferenceDescription | ModelServerObject>): array is ModelServerReferenceDescription[];
//# sourceMappingURL=model-server-utils.d.ts.map

@@ -13,3 +13,3 @@ "use strict";

* SPDX-License-Identifier: EPL-2.0 OR MIT
********************************************************************************/
*******************************************************************************/
const base_model_1 = require("../model/base-model");

@@ -16,0 +16,0 @@ function isNumberArray(array) {

@@ -1,2 +0,2 @@

/*********************************************************************************
/********************************************************************************
* Copyright (c) 2022 STMicroelectronics and others.

@@ -10,4 +10,5 @@ *

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
import { AddOperation, Operation, RemoveOperation, ReplaceOperation } from 'fast-json-patch';
import URI from 'urijs';
import { ModelServerObjectV2, ModelServerReferenceDescriptionV2 } from '../model/base-model';

@@ -30,3 +31,3 @@ import { AnyObject, TypeGuard } from './type-util';

*/
export declare function replace<T>(modeluri: string, object: ModelServerObjectV2, feature: string, value: T): ReplaceOperation<T>;
export declare function replace<T>(modeluri: URI, object: ModelServerObjectV2, feature: string, value: T): ReplaceOperation<T>;
/**

@@ -41,3 +42,3 @@ * Create an AddOperation, to create a new object of the specified type, in the specified parent.

*/
export declare function create(modeluri: string, parent: ModelServerObjectV2, feature: string, $type: string, attributes?: AnyObject): AddOperation<TypeDefinition>;
export declare function create(modeluri: URI, parent: ModelServerObjectV2, feature: string, $type: string, attributes?: AnyObject): AddOperation<TypeDefinition>;
/**

@@ -51,3 +52,3 @@ * Create an AddOperation, to add an existing object of the specified type, in the specified parent.

*/
export declare function add(modeluri: string, parent: ModelServerObjectV2, feature: string, value: ModelServerObjectV2 | ModelServerReferenceDescriptionV2): AddOperation<ModelServerObjectV2>;
export declare function add(modeluri: URI, parent: ModelServerObjectV2, feature: string, value: ModelServerObjectV2 | ModelServerReferenceDescriptionV2): AddOperation<ModelServerObjectV2>;
/**

@@ -59,3 +60,3 @@ * Create a RemoveOperation, to delete an object from the model.

*/
export declare function deleteElement(modeluri: string, object: ModelServerObjectV2): RemoveOperation;
export declare function deleteElement(modeluri: URI, object: ModelServerObjectV2): RemoveOperation;
/**

@@ -68,3 +69,3 @@ * Create a RemoveOperation, to remove a value from a list.

*/
export declare function removeValueAt(modeluri: string, object: ModelServerObjectV2, feature: string, index: number): RemoveOperation;
export declare function removeValueAt(modeluri: URI, object: ModelServerObjectV2, feature: string, index: number): RemoveOperation;
/**

@@ -77,3 +78,3 @@ * Create a RemoveOperation, to remove a value from a list.

*/
export declare function removeValue(modeluri: string, object: ModelServerObjectV2, feature: string, value: AnyObject): RemoveOperation | undefined;
export declare function removeValue(modeluri: URI, object: ModelServerObjectV2, feature: string, value: AnyObject): RemoveOperation | undefined;
/**

@@ -84,3 +85,3 @@ * Create a RemoveOperation, to delete an object from the model.

*/
export declare function removeObject(modeluri: string, objectToRemove: ModelServerObjectV2): RemoveOperation;
export declare function removeObject(modeluri: URI, objectToRemove: ModelServerObjectV2): RemoveOperation;
/**

@@ -87,0 +88,0 @@ * Utility functions for working with JSON Patch operations.

@@ -133,3 +133,3 @@ "use strict";

const id = base_model_1.ModelServerReferenceDescriptionV2.is(object) ? object.$ref : object.$id;
return `${modeluri}#${id}`;
return modeluri.clone().fragment(id).toString();
}

@@ -136,0 +136,0 @@ /**

@@ -1,2 +0,2 @@

/*********************************************************************************
/********************************************************************************
* Copyright (c) 2021-2022 STMicroelectronics and others.

@@ -10,3 +10,4 @@ *

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
import URI from 'urijs';
import { Format } from '../model-server-client-api-v2';

@@ -19,3 +20,3 @@ import { Model } from '../model-server-message';

*/
export declare type AnyObject = Record<PropertyKey, unknown>;
export type AnyObject = Record<PropertyKey, unknown>;
export declare namespace AnyObject {

@@ -34,3 +35,3 @@ /**

*/
export declare type TypeGuard<T> = (object: unknown) => object is T;
export type TypeGuard<T> = (object: unknown) => object is T;
/**

@@ -100,4 +101,23 @@ * Validates whether the given object as a property of type `string` with the given key.

export declare function asModelArray(object: unknown): Model[];
/**
* Validates whether the given object is a (deferred) instance of an URI object.
* @param object The object that should be validated
* @returns `true` if the object is an instance of URI
*/
export declare function isURI(object: unknown): object is URI;
/**
* Maps the given object to an `URI` object.
* @param obj The object to map
* @returns The object as `URI`
*/
export declare function asURI(obj: unknown): URI;
/**
* Maps the given object to a `string` array.
* @param object The object to map
* @returns The object as `URI` array
* @throws {@link Error} if the given object is not an array
*/
export declare function asURIArray(object: unknown): URI[];
/** Protocol of a message encoder. */
export declare type Encoder<T = unknown> = (object: string | AnyObject) => T | string;
export type Encoder<T = unknown> = (object: string | AnyObject) => T | string;
/**

@@ -104,0 +124,0 @@ * Obtain a message encoder for the request body.

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.encode = exports.encodeRequestBody = exports.asModelArray = exports.asType = exports.asObject = exports.asStringArray = exports.asString = exports.isArray = exports.isObject = exports.isNumber = exports.isBoolean = exports.isString = exports.AnyObject = void 0;
/*********************************************************************************
/********************************************************************************
* Copyright (c) 2021-2022 STMicroelectronics and others.

@@ -13,4 +11,11 @@ *

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.encode = exports.encodeRequestBody = exports.asURIArray = exports.asURI = exports.isURI = exports.asModelArray = exports.asType = exports.asObject = exports.asStringArray = exports.asString = exports.isArray = exports.isObject = exports.isNumber = exports.isBoolean = exports.isString = exports.AnyObject = void 0;
const urijs_1 = __importDefault(require("urijs"));
const model_server_client_api_v2_1 = require("../model-server-client-api-v2");
const model_server_message_1 = require("../model-server-message");
var AnyObject;

@@ -88,2 +93,15 @@ (function (AnyObject) {

}
if (model_server_message_1.Model.is(object)) {
return model_server_message_1.Model.toString(object);
}
if (Array.isArray(object) && object.every(model_server_message_1.Model.is)) {
return object.map(e => model_server_message_1.Model.toString(e)).toString();
}
if (isURI(object)) {
return asURI(object).toString();
}
if (Array.isArray(object) && object.every(isURI)) {
const uriArray = object.map(e => asURI(e).toString());
return JSON.stringify(uriArray, undefined, 2);
}
return JSON.stringify(object, undefined, 2);

@@ -134,3 +152,3 @@ }

if (AnyObject.is(object)) {
return Object.entries(object).map(entry => ({ modelUri: entry[0], content: entry[1] }));
return Object.entries(object).map(entry => ({ modeluri: entry[0], content: entry[1] }));
}

@@ -141,2 +159,40 @@ throw new Error('Cannot map to Model[]. The given object is no defined or of type "object"!');

/**
* Validates whether the given object is a (deferred) instance of an URI object.
* @param object The object that should be validated
* @returns `true` if the object is an instance of URI
*/
function isURI(object) {
return AnyObject.is(object) && isObject(object, '_parts') && isBoolean(object, '_deferred_build') && isString(object, '_string');
}
exports.isURI = isURI;
/**
* Maps the given object to an `URI` object.
* @param obj The object to map
* @returns The object as `URI`
*/
function asURI(obj) {
if (typeof obj === 'string') {
return new urijs_1.default(obj);
}
// reconstruct if URI object was deferred
if (isURI(obj)) {
return new urijs_1.default(obj._parts);
}
throw new Error('Cannot map to URI. Given parameter is not an URI!');
}
exports.asURI = asURI;
/**
* Maps the given object to a `string` array.
* @param object The object to map
* @returns The object as `URI` array
* @throws {@link Error} if the given object is not an array
*/
function asURIArray(object) {
if (Array.isArray(object)) {
return object.map(asURI);
}
throw new Error('Cannot map to URI[]. Given parameter is not an array!');
}
exports.asURIArray = asURIArray;
/**
* Obtain a message encoder for the request body.

@@ -208,3 +264,3 @@ *

function findProperty(object, name, visited = new Set()) {
return traverse(object, (target, props) => props.includes(name) ? true : undefined);
return traverse(object, (target, props) => (props.includes(name) ? true : undefined));
}

@@ -259,2 +315,8 @@ /**

function traverse(object, fn, visited = new Set()) {
// Only traverse into objects. Null, undefined, strings, numbers, booleans are primitive values in JSON and functions don't exist.
// eslint-disable-next-line no-null/no-null
if (typeof object !== 'object' || object === null) {
// JSON uses null
return false;
}
if (visited.has(object)) {

@@ -261,0 +323,0 @@ return false;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/*********************************************************************************
/********************************************************************************
* Copyright (c) 2022 STMicroelectronics and others.

@@ -12,3 +12,3 @@ *

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
const chai_1 = require("chai");

@@ -18,49 +18,79 @@ const type_util_1 = require("./type-util");

describe('encode', () => {
const emptyArray = [];
const tags = ['high-prio', 'red'];
// eslint-disable-next-line no-null/no-null
const nada = null; // JSON uses null
const emptyObj = {};
it('JSON v1 as JSON v1', () => {
const object = { eClass: 'Foo', name: 'test', nested: [{ eClass: 'Nested', name: 'inner', tags: ['high-prio', 'red'] }] };
const encoded = type_util_1.encode('json')(object);
chai_1.expect(encoded).to.be.equal(encoded);
const object = { eClass: 'Foo', name: 'test', nested: [{ eClass: 'Nested', name: 'inner', tags, emptyArray, nada, emptyObj }] };
const encoded = (0, type_util_1.encode)('json')(object);
(0, chai_1.expect)(encoded).to.be.equal(encoded);
});
it('JSON v1 as JSON v2', () => {
const object = { eClass: 'Foo', name: 'test', nested: [{ eClass: 'Nested', name: 'inner', tags: ['high-prio', 'red'] }] };
const expected = { $type: 'Foo', name: 'test', nested: [{ $type: 'Nested', name: 'inner', tags: ['high-prio', 'red'] }] };
const encoded = type_util_1.encode('json-v2')(object);
chai_1.expect(encoded).to.be.eql(expected);
const object = { eClass: 'Foo', name: 'test', nested: [{ eClass: 'Nested', name: 'inner', tags, emptyArray, nada, emptyObj }] };
const expected = { $type: 'Foo', name: 'test', nested: [{ $type: 'Nested', name: 'inner', tags, emptyArray, nada, emptyObj }] };
const encoded = (0, type_util_1.encode)('json-v2')(object);
(0, chai_1.expect)(encoded).to.be.eql(expected);
});
it('JSON v2 as JSON v1', () => {
const object = { $type: 'Foo', name: 'test', nested: [{ $type: 'Nested', name: 'inner', tags: ['high-prio', 'red'] }] };
const expected = { eClass: 'Foo', name: 'test', nested: [{ eClass: 'Nested', name: 'inner', tags: ['high-prio', 'red'] }] };
const encoded = type_util_1.encode('json')(object);
chai_1.expect(encoded).to.be.eql(expected);
const object = { $type: 'Foo', name: 'test', nested: [{ $type: 'Nested', name: 'inner', tags, emptyArray, nada, emptyObj }] };
const expected = {
eClass: 'Foo',
name: 'test',
nested: [{ eClass: 'Nested', name: 'inner', tags, emptyArray, nada, emptyObj }]
};
const encoded = (0, type_util_1.encode)('json')(object);
(0, chai_1.expect)(encoded).to.be.eql(expected);
});
it('JSON v2 as JSON v2', () => {
const object = { $type: 'Foo', name: 'test', nested: [{ $type: 'Nested', name: 'inner', tags: ['high-prio', 'red'] }] };
const encoded = type_util_1.encode('json-v2')(object);
chai_1.expect(encoded).to.be.equal(encoded);
const object = { $type: 'Foo', name: 'test', nested: [{ $type: 'Nested', name: 'inner', tags, emptyArray, nada, emptyObj }] };
const encoded = (0, type_util_1.encode)('json-v2')(object);
(0, chai_1.expect)(encoded).to.be.equal(encoded);
});
});
describe('encode string', () => {
const emptyArray = [];
const tags = ['high-prio', 'red'];
// eslint-disable-next-line no-null/no-null
const nada = null; // JSON uses null
const emptyObj = {};
it('JSON v1 as JSON v1', () => {
const object = JSON.stringify({ eClass: 'Foo', name: 'test', nested: { eClass: 'Nested', name: 'inner', tags: ['high-prio', 'red'] } });
const encoded = type_util_1.encode('json')(object);
chai_1.expect(encoded).to.be.equal(encoded);
const object = JSON.stringify({
eClass: 'Foo',
name: 'test',
nested: { eClass: 'Nested', name: 'inner', tags, emptyArray, nada, emptyObj }
});
const encoded = (0, type_util_1.encode)('json')(object);
(0, chai_1.expect)(encoded).to.be.equal(encoded);
});
it('JSON v1 as JSON v2', () => {
const object = JSON.stringify({ eClass: 'Foo', name: 'test', nested: { eClass: 'Nested', name: 'inner', tags: ['high-prio', 'red'] } });
const expected = { $type: 'Foo', name: 'test', nested: { $type: 'Nested', name: 'inner', tags: ['high-prio', 'red'] } };
const encoded = type_util_1.encode('json-v2')(object);
chai_1.expect(encoded).to.be.a('string');
chai_1.expect(JSON.parse(encoded)).to.be.eql(expected);
const object = JSON.stringify({
eClass: 'Foo',
name: 'test',
nested: { eClass: 'Nested', name: 'inner', tags, emptyArray, nada, emptyObj }
});
const expected = { $type: 'Foo', name: 'test', nested: { $type: 'Nested', name: 'inner', tags, emptyArray, nada, emptyObj } };
const encoded = (0, type_util_1.encode)('json-v2')(object);
(0, chai_1.expect)(encoded).to.be.a('string');
(0, chai_1.expect)(JSON.parse(encoded)).to.be.eql(expected);
});
it('JSON v2 as JSON v1', () => {
const object = JSON.stringify({ $type: 'Foo', name: 'test', nested: { $type: 'Nested', name: 'inner', tags: ['high-prio', 'red'] } });
const expected = { eClass: 'Foo', name: 'test', nested: { eClass: 'Nested', name: 'inner', tags: ['high-prio', 'red'] } };
const encoded = type_util_1.encode('json')(object);
chai_1.expect(encoded).to.be.a('string');
chai_1.expect(JSON.parse(encoded)).to.be.eql(expected);
const object = JSON.stringify({
$type: 'Foo',
name: 'test',
nested: { $type: 'Nested', name: 'inner', tags, emptyArray, nada, emptyObj }
});
const expected = { eClass: 'Foo', name: 'test', nested: { eClass: 'Nested', name: 'inner', tags, emptyArray, nada, emptyObj } };
const encoded = (0, type_util_1.encode)('json')(object);
(0, chai_1.expect)(encoded).to.be.a('string');
(0, chai_1.expect)(JSON.parse(encoded)).to.be.eql(expected);
});
it('JSON v2 as JSON v2', () => {
const object = JSON.stringify({ $type: 'Foo', name: 'test', nested: { $type: 'Nested', name: 'inner', tags: ['high-prio', 'red'] } });
const encoded = type_util_1.encode('json-v2')(object);
chai_1.expect(encoded).to.be.equal(encoded);
const object = JSON.stringify({
$type: 'Foo',
name: 'test',
nested: { $type: 'Nested', name: 'inner', tags, emptyArray, nada, emptyObj }
});
const encoded = (0, type_util_1.encode)('json-v2')(object);
(0, chai_1.expect)(encoded).to.be.equal(encoded);
});

@@ -67,0 +97,0 @@ });

@@ -17,3 +17,3 @@ {

"bugs": "https://github.com/eclipse-emfcloud/emfcloud-modelserver-theia/issues",
"version": "0.8.0-next.ccd36ac2",
"version": "0.8.0-next.d7db15a.92+d7db15a",
"files": [

@@ -32,2 +32,7 @@ "lib",

"url": "https://projects.eclipse.org/projects/ecd.emfcloud"
},
{
"name": "Vincent HEMERY (CS GROUP - France)",
"email": "vincent.hemery@csgroup.eu",
"url": "https://www.csgroup.eu/"
}

@@ -44,9 +49,13 @@ ],

"isomorphic-ws": "^4.0.1",
"ws": "^7.4.6"
"urijs": "^1.19.11",
"ws": "^7.1.2"
},
"devDependencies": {
"@types/moxios": "^0.4.14",
"@types/moxios": "0.4.14",
"@types/urijs": "^1.19.19",
"@types/ws": "8.2.2",
"ignore-styles": "^5.0.1",
"moxios": "^0.4.0",
"typescript": "^3.9.2"
"rimraf": "^3.0.2",
"typescript": "^4.6.3"
},

@@ -57,6 +66,8 @@ "scripts": {

"build": "tsc && yarn run lint",
"lint": "eslint -c ../../.eslintrc.js --ext .ts ./src",
"lint": "eslint --ext .ts,.tsx ./src",
"watch": "tsc -w",
"test": "mocha --config ../../configs/.mocharc.json \"./src/**/*.spec.?(ts|tsx)\""
}
"test": "mocha --config ../../configs/.mocharc.json",
"test:ci": "mocha --config ../../configs/.mocharc.ci.json"
},
"gitHead": "d7db15adeee0a747f9ebb9ff2e5264a8a3ac974c"
}

@@ -1,2 +0,2 @@

/*********************************************************************************
/********************************************************************************
* Copyright (c) 2021-2022 STMicroelectronics and others.

@@ -10,17 +10,17 @@ *

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
export * from './model/base-model';
export * from './model/change-model';
export * from './model/command-model';
export * from './model/diagnostic';
export * from './model-server-client';
export * from './model-server-client-v2';
export * from './model-server-client-api-v1';
export * from './model-server-client-api-v2';
export * from './model-server-client-v2';
export * from './model-server-message';
export * from './model-server-notification';
export * from './model-server-paths';
export * from './model-server-message';
export * from './model/base-model';
export * from './model/change-model';
export * from './model/command-model';
export * from './model/diagnostic';
export * from './subscription-listener';
export * from './utils/model-server-utils';
export * from './utils/patch-utils';
export * from './utils/type-util';
export * from './utils/patch-utils';

@@ -1,2 +0,2 @@

/*********************************************************************************
/********************************************************************************
* Copyright (c) 2021-2022 STMicroelectronics and others.

@@ -10,3 +10,5 @@ *

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
import URI from 'urijs';
import { MessageDataMapper, Model, ModelServerMessage } from './model-server-message';

@@ -32,3 +34,3 @@ import { ModelServerCommand } from './model/command-model';

*/
initialize(baseUrl: string, defaultFormat?: string): void | Promise<void>;
initialize(baseUrl: URI, defaultFormat?: string): void | Promise<void>;

@@ -61,3 +63,3 @@ /**

*/
get(modeluri: string,): Promise<AnyObject>;
get(modeluri: URI): Promise<AnyObject>;
/**

@@ -71,3 +73,3 @@ * Retrieves the {@link Model} for a given URI as typed JSON object

*/
get<M>(modeluri: string, typeGuard: TypeGuard<M>,): Promise<M>;
get<M>(modeluri: URI, typeGuard: TypeGuard<M>): Promise<M>;
/**

@@ -80,3 +82,3 @@ * Retrieves the {@link Model} for a given URI in string representation derived from a given format (e.g. 'xml' or 'json').

*/
get(modeluri: string, format: string): Promise<string>;
get(modeluri: URI, format: string): Promise<string>;

@@ -87,3 +89,3 @@ /**

*/
getModelUris(): Promise<string[]>;
getModelUris(): Promise<URI[]>;

@@ -97,3 +99,3 @@ /**

*/
getElementById(modeluri: string, elementid: string): Promise<AnyObject>;
getElementById(modeluri: URI, elementid: string): Promise<AnyObject>;
/**

@@ -108,3 +110,3 @@ * Retrieves a specific model (sub)element by its `id` as typed JSON object.

*/
getElementById<M>(modeluri: string, elementid: string, typeGuard: TypeGuard<M>): Promise<M>;
getElementById<M>(modeluri: URI, elementid: string, typeGuard: TypeGuard<M>): Promise<M>;
/**

@@ -118,3 +120,3 @@ * Retrieves a specific model (sub)element by its `id` in string representation derived from a given format (e.g. 'xml' or 'json').

*/
getElementById(modeluri: string, elementid: string, format: string): Promise<string>;
getElementById(modeluri: URI, elementid: string, format: string): Promise<string>;

@@ -128,3 +130,3 @@ /**

*/
getElementByName(modeluri: string, elementname: string): Promise<AnyObject>;
getElementByName(modeluri: URI, elementname: string): Promise<AnyObject>;
/**

@@ -139,3 +141,3 @@ * Retrieves a specific model (sub)element by its `name` as typed JSON object.

*/
getElementByName<M>(modeluri: string, elementname: string, typeGuard: TypeGuard<M>, format?: string): Promise<M>;
getElementByName<M>(modeluri: URI, elementname: string, typeGuard: TypeGuard<M>, format?: string): Promise<M>;
/**

@@ -149,3 +151,3 @@ * Retrieves a specific model (sub)element by its `name` in string representation derived from a given format (e.g. 'xml' or 'json').

*/
getElementByName(modeluri: string, elementname: string, format: string): Promise<string>;
getElementByName(modeluri: URI, elementname: string, format: string): Promise<string>;

@@ -157,3 +159,3 @@ /**

*/
delete(modeluri: string): Promise<boolean>;
delete(modeluri: URI): Promise<boolean>;

@@ -165,3 +167,3 @@ /**

*/
close(modeluri: string): Promise<boolean>;
close(modeluri: URI): Promise<boolean>;

@@ -174,3 +176,3 @@ /**

*/
create(modeluri: string, model: AnyObject | string): Promise<AnyObject>;
create(modeluri: URI, model: AnyObject | string): Promise<AnyObject>;
/**

@@ -185,3 +187,3 @@ * Creates a new model object with the given URI and content object in the current workspace.

*/
create<M>(modeluri: string, model: AnyObject | string, typeGuard: TypeGuard<M>): Promise<M>;
create<M>(modeluri: URI, model: AnyObject | string, typeGuard: TypeGuard<M>): Promise<M>;
/**

@@ -195,3 +197,3 @@ * Creates a new model object with the given URI and content string in the current workspace.

*/
create(modeluri: string, model: string, format: string): Promise<string>;
create(modeluri: URI, model: string, format: string): Promise<string>;

@@ -205,3 +207,3 @@ /**

*/
update(modeluri: string, model: AnyObject | string): Promise<AnyObject>;
update(modeluri: URI, model: AnyObject | string): Promise<AnyObject>;
/**

@@ -217,3 +219,3 @@ * Updates an existing model with the given URI with the given content in the current workspace.

*/
update<M>(modeluri: string, model: string | string, typeGuard: TypeGuard<M>): Promise<M>;
update<M>(modeluri: URI, model: string | string, typeGuard: TypeGuard<M>): Promise<M>;
/**

@@ -227,3 +229,3 @@ * Updates an existing model with the given URI with the given content string in the current workspace.

*/
update(modeluri: string, model: string, format: string): Promise<AnyObject>;
update(modeluri: URI, model: string, format: string): Promise<AnyObject>;

@@ -235,3 +237,3 @@ /**

*/
save(modeluri: string): Promise<boolean>;
save(modeluri: URI): Promise<boolean>;

@@ -249,3 +251,3 @@ /**

*/
validate(modeluri: string): Promise<Diagnostic>;
validate(modeluri: URI): Promise<Diagnostic>;

@@ -257,3 +259,3 @@ /**

*/
getValidationConstraints(modeluri: string): Promise<string>;
getValidationConstraints(modeluri: URI): Promise<string>;

@@ -267,3 +269,3 @@ /**

*/
getTypeSchema(modeluri: string): Promise<string>;
getTypeSchema(modeluri: URI): Promise<string>;

@@ -297,3 +299,3 @@ /**

*/
edit(modeluri: string, command: ModelServerCommand): Promise<boolean>;
edit(modeluri: URI, command: ModelServerCommand): Promise<boolean>;

@@ -305,3 +307,3 @@ /**

*/
undo(modeluri: string): Promise<string>;
undo(modeluri: URI): Promise<string>;

@@ -313,3 +315,3 @@ /**

*/
redo(modeluri: string): Promise<string>;
redo(modeluri: URI): Promise<string>;

@@ -322,11 +324,11 @@ /**

*/
subscribe(modeluri: string, options?: SubscriptionOptions): void;
subscribe(modeluri: URI, options?: SubscriptionOptions): void;
/**
* Can be used to send arbitrary {@link ModelServerMessage}s to the model server via a subscription channel.
* @param modelUri The URI of the subscribed model.
* @param modeluri The URI of the subscribed model.
* @param message The model server message that should be sent.
* @returns A boolean indicating whether the message submission was successful.
*/
send(modelUri: string, message: ModelServerMessage): boolean;
send(modeluri: URI, message: ModelServerMessage): boolean;

@@ -338,7 +340,7 @@ /**

*/
unsubscribe(modelUri: string): boolean;
unsubscribe(modeluri: URI): boolean;
}
export namespace ModelServerClientApiV1 {
export const API_ENDPOINT = '/api/v1';
export const API_ENDPOINT = 'api/v1';
}

@@ -364,4 +366,4 @@

export interface ServerConfiguration {
workspaceRoot: string;
uiSchemaFolder?: string;
workspaceRoot: URI;
uiSchemaFolder?: URI;
}

@@ -368,0 +370,0 @@

@@ -1,2 +0,2 @@

/*********************************************************************************
/********************************************************************************
* Copyright (c) 2022 STMicroelectronics and others.

@@ -10,10 +10,11 @@ *

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
import { Operation } from 'fast-json-patch';
import URI from 'urijs';
import { ServerConfiguration, SubscriptionOptions } from './model-server-client-api-v1';
import { Model, ModelServerMessage } from './model-server-message';
import { ModelServerElement } from './model/base-model';
import { ModelServerCommand } from './model/command-model';
import { Diagnostic } from './model/diagnostic';
import { ServerConfiguration, SubscriptionOptions } from './model-server-client-api-v1';
import { Model, ModelServerMessage } from './model-server-message';
import { SubscriptionListener } from './subscription-listener';

@@ -44,2 +45,26 @@ import { AnyObject, TypeGuard } from './utils/type-util';

/**
* Additional subscription options supported by API v2 model subscriptions.
*/
export interface SubscriptionOptionsV2 extends SubscriptionOptions {
/**
* The scheme to use in the `path` property of {@link Operation}s in the
* JSON Patches reported by API V2 queries. Supported values (case insensitive)
* include `'jsonPointer'` (the default for standard JSON Patches) and
* `'uriFragments'` (for a custom EMF-specific scheme based on the URI
* fragments of `EObject`s) .
*/
paths?: string;
}
/**
* A union type that represents all Patches or Commands supported by the model server:
* - Operation
* - Operation[] (Json Patch)
* - ModelPatch
* - ModelPatch[]
* - ModelServerCommand
*/
export type PatchOrCommand = Operation | Operation[] | ModelPatch | ModelPatch[] | ModelServerCommand;
/**
* Basic client API to interact with a model server that conforms to the Modelserver API Version 2.

@@ -51,3 +76,3 @@ */

* The given base url should point to the location of the model server API entry point.
* (e.g. `http://localhost:8081/api/v1/`). Once the initialization is completed the client is expected
* (e.g. `http://localhost:8081/api/v2/`). Once the initialization is completed the client is expected
* to be ready and should be able to handle REST requests to & responses from the model server.

@@ -59,3 +84,3 @@ * Any requests to the model server before the client has been initialized are expected to fail (i.e. throw an error)

*/
initialize(baseUrl: string, defaultFormat?: Format): void | Promise<void>;
initialize(baseUrl: URI, defaultFormat?: Format): void | Promise<void>;

@@ -69,32 +94,32 @@ /**

get(modeluri: string, format?: Format): Promise<AnyObject>;
get<M>(modeluri: string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
get(modeluri: URI, format?: Format): Promise<AnyObject>;
get<M>(modeluri: URI, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
getModelUris(): Promise<string[]>;
getModelUris(): Promise<URI[]>;
getElementById(modeluri: string, elementid: string, format?: Format): Promise<AnyObject>;
getElementById<M>(modeluri: string, elementid: string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
getElementById(modeluri: URI, elementid: string, format?: Format): Promise<AnyObject>;
getElementById<M>(modeluri: URI, elementid: string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
getElementByName(modeluri: string, elementname: string, format?: Format): Promise<AnyObject>;
getElementByName<M>(modeluri: string, elementname: string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
getElementByName(modeluri: URI, elementname: string, format?: Format): Promise<AnyObject>;
getElementByName<M>(modeluri: URI, elementname: string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
delete(modeluri: string): Promise<boolean>;
delete(modeluri: URI): Promise<boolean>;
close(modeluri: string): Promise<boolean>;
close(modeluri: URI): Promise<boolean>;
create(modeluri: string, model: AnyObject | string, format?: Format): Promise<AnyObject>;
create<M>(modeluri: string, model: AnyObject | string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
create(modeluri: URI, model: AnyObject | string, format?: Format): Promise<AnyObject>;
create<M>(modeluri: URI, model: AnyObject | string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
update(modeluri: string, model: AnyObject | string, format?: Format): Promise<AnyObject>;
update<M>(modeluri: string, model: AnyObject | string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
update(modeluri: URI, model: AnyObject | string, format?: Format): Promise<AnyObject>;
update<M>(modeluri: URI, model: AnyObject | string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
save(modeluri: string): Promise<boolean>;
save(modeluri: URI): Promise<boolean>;
saveAll(): Promise<boolean>;
validate(modeluri: string): Promise<Diagnostic>;
validate(modeluri: URI): Promise<Diagnostic>;
getValidationConstraints(modeluri: string): Promise<string>;
getValidationConstraints(modeluri: URI): Promise<string>;
getTypeSchema(modeluri: string): Promise<string>;
getTypeSchema(modeluri: URI): Promise<string>;

@@ -107,25 +132,38 @@ getUiSchema(schemaname: string): Promise<string>;

edit(modeluri: string, patch: Operation | Operation[], format?: Format): Promise<ModelUpdateResult>;
edit(modeluri: string, command: ModelServerCommand, format?: Format): Promise<ModelUpdateResult>;
edit(modeluri: URI, patchOrCommand: PatchOrCommand, format?: Format): Promise<ModelUpdateResult>;
undo(modeluri: string): Promise<ModelUpdateResult>;
undo(modeluri: URI): Promise<ModelUpdateResult>;
redo(modeluri: string): Promise<ModelUpdateResult>;
redo(modeluri: URI): Promise<ModelUpdateResult>;
// WebSocket connection
subscribe(modeluri: string, listener: SubscriptionListener, options?: SubscriptionOptions): SubscriptionListener;
subscribe(modeluri: URI, listener: SubscriptionListener, options?: SubscriptionOptionsV2): SubscriptionListener;
send(modelUri: string, message: ModelServerMessage): void;
unsubscribe(modelUri: string): void;
send(modeluri: URI, message: ModelServerMessage): void;
unsubscribe(modeluri: URI): void;
}
export namespace ModelServerClientApiV2 {
export const API_ENDPOINT = '/api/v2';
export const API_ENDPOINT = 'api/v2';
}
/**
* A patch affecting a specific model.
*/
export interface ModelPatch {
/**
* The uri of the patched model.
*/
modelUri: string;
/**
* The patch describing the changes applied to the model.
*/
patch: Operation[];
}
/**
* Result sent to client after requesting a model update.
*/
export interface ModelUpdateResult {
/**

@@ -145,5 +183,8 @@ * True if the edit request was successful, false otherwise.

* the original model unchanged.
* @param modeluri the uri of the model to patch. This can be used when the model is split in multiple
* resources, to identify the patch to apply. The modeluri should correspond to the oldModel object.
* It can be omitted when patching the main model (or in single-model cases).
* @return the patched model.
*/
patchModel?(oldModel: ModelServerElement, copy?: boolean): ModelServerElement;
patchModel?(oldModel: ModelServerElement, copy?: boolean, modeluri?: URI): ModelServerElement;

@@ -155,2 +196,10 @@ /**

patch?: Operation[];
/**
* The list of Json Patches describing the changes that were applied to the models. Only present if
* the edit request was successful.
*
* The list contains one entry per modified model. Unmodified models will not contain any entry.
*/
allPatches?: ModelPatch[];
}

@@ -1,2 +0,2 @@

/*********************************************************************************
/********************************************************************************
* Copyright (c) 2022 STMicroelectronics and others.

@@ -10,5 +10,6 @@ *

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
import { expect } from 'chai';
import jsonpatch, { deepClone, Operation } from 'fast-json-patch';
import URI from 'urijs';

@@ -34,5 +35,14 @@ import {

let client: ModelServerClientV2;
const baseUrl = `http://localhost:8081${ModelServerClientApiV2.API_ENDPOINT}`;
const baseUrl = new URI({
protocol: 'http',
hostname: 'localhost',
port: '8081',
path: ModelServerClientApiV2.API_ENDPOINT
});
const testUndoRedo: (modeluri: string, originalModel: any, patchedModel: any) => void = async (modeluri, originalModel, patchedModel) => {
const testUndoRedo: (modeluri: URI, originalModel: any, patchedModel: any) => Promise<void> = async (
modeluri,
originalModel,
patchedModel
) => {
// Expected: originalModel === undoModel === patchedUndoModel

@@ -65,3 +75,3 @@ // Expected: patchedModel === redoModel === patchedRedoModel

it('edit with patch', async () => {
const modeluri = 'SuperBrewer3000.coffee';
const modeluri = new URI('SuperBrewer3000.coffee');
const newName = 'Super Brewer 6000';

@@ -78,3 +88,3 @@ const machine = await client.get(modeluri, ModelServerObjectV2.is);

it('create with patch', async () => {
const modeluri = 'SuperBrewer3000.coffee';
const modeluri = new URI('SuperBrewer3000.coffee');
const originalModel = await client.get(modeluri, ModelServerObjectV2.is);

@@ -84,3 +94,9 @@ const newWorkflowName = 'New Test Workflow';

const patch = create(modeluri, originalModel, 'workflows', 'http://www.eclipsesource.com/modelserver/example/coffeemodel#//Workflow', {name: newWorkflowName});
const patch = create(
modeluri,
originalModel,
'workflows',
'http://www.eclipsesource.com/modelserver/example/coffeemodel#//Workflow',
{ name: newWorkflowName }
);
await client.edit(modeluri, patch);

@@ -101,7 +117,13 @@ const patchedModel = await client.get(modeluri);

it('add with patch', async () => {
const modeluri = 'SuperBrewer3000.coffee';
const modeluri = new URI('SuperBrewer3000.coffee');
const initialModel = await client.get(modeluri, ModelServerObjectV2.is);
// Add a second workflow to the model; we'll use it to move a Task from a workflow to the other
const createWorkflow = create(modeluri, initialModel, 'workflows', 'http://www.eclipsesource.com/modelserver/example/coffeemodel#//Workflow', {name: 'New Workflow'});
const createWorkflow = create(
modeluri,
initialModel,
'workflows',
'http://www.eclipsesource.com/modelserver/example/coffeemodel#//Workflow',
{ name: 'New Workflow' }
);
await client.edit(modeluri, createWorkflow);

@@ -127,3 +149,3 @@ const originalModel = await client.get(modeluri, ModelServerObjectV2.is);

it('delete with patch - index based', async () => {
const modeluri = 'SuperBrewer3000.coffee';
const modeluri = new URI('SuperBrewer3000.coffee');
const originalModel = await client.get(modeluri, ModelServerObjectV2.is);

@@ -144,3 +166,3 @@

it('delete with patch - object', async () => {
const modeluri = 'SuperBrewer3000.coffee';
const modeluri = new URI('SuperBrewer3000.coffee');
const originalModel = await client.get(modeluri, ModelServerObjectV2.is);

@@ -163,3 +185,3 @@

it('edit with command', async () => {
const modeluri = 'SuperBrewer3000.coffee';
const modeluri = new URI('SuperBrewer3000.coffee');
const newName = 'Super Brewer 6000';

@@ -169,3 +191,3 @@ const originalModel = await client.get(modeluri, ModelServerObjectV2.is);

eClass: originalModel.$type,
$ref: `SuperBrewer3000.coffee#${originalModel.$id}`
$ref: URI.build({ path: 'SuperBrewer3000.coffee', fragment: originalModel.$id })
};

@@ -181,3 +203,3 @@ const command = new SetCommand(owner, 'name', [newName]);

it('incremental patch update', async () => {
const modeluri = 'SuperBrewer3000.coffee';
const modeluri = new URI('SuperBrewer3000.coffee');
const newName = 'Super Brewer 6000';

@@ -204,3 +226,3 @@ const machine = await client.get(modeluri, ModelServerObjectV2.is);

it('subscribe to changes', async () => {
const modeluri = 'SuperBrewer3000.coffee';
const modeluri = new URI('SuperBrewer3000.coffee');
const newName = 'Super Brewer 6000';

@@ -210,3 +232,3 @@ const machine = await client.get(modeluri, ModelServerObjectV2.is);

eClass: machine.$type,
$ref: `SuperBrewer3000.coffee#${machine.$id}`
$ref: URI.build({ path: 'SuperBrewer3000.coffee', fragment: machine.$id })
};

@@ -234,3 +256,3 @@ const command = new SetCommand(owner, 'name', [newName]);

expect(notification.modelUri).to.be.equal(modeluri);
expect(notification.modeluri.toString()).to.be.equal(modeluri.toString());
expect(patch.length).to.be.equal(1);

@@ -249,3 +271,3 @@ const operation = patch[0];

it('subscribe to incremental updates', async () => {
const modeluri = 'SuperBrewer3000.coffee';
const modeluri = new URI('SuperBrewer3000.coffee');
const newName = 'Super Brewer 6000';

@@ -255,3 +277,3 @@ const machine = await client.get(modeluri, ModelServerObjectV2.is);

eClass: machine.$type,
$ref: `SuperBrewer3000.coffee#${machine.$id}`
$ref: URI.build({ path: 'SuperBrewer3000.coffee', fragment: machine.$id })
};

@@ -292,3 +314,3 @@ const command = new SetCommand(owner, 'name', [newName]);

it('pure Json Patch changes', async () => {
const modeluri = 'SuperBrewer3000.coffee';
const modeluri = new URI('SuperBrewer3000.coffee');
const newName = 'Super Brewer 6000';

@@ -315,3 +337,3 @@ const machine = await client.get(modeluri, ModelServerObjectV2.is);

it('clear list with "remove" patch operation', async () => {
const modeluri = 'SuperBrewer3000.coffee';
const modeluri = new URI('SuperBrewer3000.coffee');
const machine = await client.get(modeluri, ModelServerObjectV2.is);

@@ -322,6 +344,8 @@

const patch: Operation[] = [{
'op': 'remove',
'path': '/workflows'
}];
const patch: Operation[] = [
{
op: 'remove',
path: '/workflows'
}
];

@@ -338,3 +362,3 @@ await client.edit(modeluri, patch);

it('unset value with "remove" patch operation', async () => {
const modeluri = 'SuperBrewer3000.coffee';
const modeluri = new URI('SuperBrewer3000.coffee');
const machine = await client.get(modeluri, ModelServerObjectV2.is);

@@ -345,6 +369,8 @@

const patch: Operation[] = [{
'op': 'remove',
'path': '/children/1/processor/thermalDesignPower'
}];
const patch: Operation[] = [
{
op: 'remove',
path: '/children/1/processor/thermalDesignPower'
}
];

@@ -359,4 +385,67 @@ await client.edit(modeluri, patch);

});
it('check all patch replies', async () => {
const modeluri = new URI('SuperBrewer3000.coffee');
const newName = 'Super Brewer 6000';
const machine = await client.get(modeluri, ModelServerObjectV2.is);
const patchedMachine = deepClone(machine);
// Directly change the model
patchedMachine.name = newName;
patchedMachine.children[1].processor.clockSpeed = 6;
// Generate patch by diffing the original model and the patched one
const patch = jsonpatch.compare(machine, patchedMachine);
const result = await client.edit(modeluri, patch);
expect(result.success).to.be.true;
expect(result.patch).to.not.be.undefined;
expect(result.allPatches).to.not.be.undefined;
expect(result.allPatches).to.be.an('array').of.length(1);
// Patch the main resource
const updatedMachineMainPatch = result.patchModel!(machine, true);
expect(patchedMachine).to.deep.equal(updatedMachineMainPatch);
// Patch the first resource
const updatedMachineFirstPatch = result.patchModel!(machine, true, new URI(result.allPatches![0].modelUri));
expect(patchedMachine).to.deep.equal(updatedMachineFirstPatch);
await testUndoRedo(modeluri, machine, updatedMachineFirstPatch);
});
it('test model patches', async () => {
const modeluri = new URI('SuperBrewer3000.coffee');
const newName = 'Super Brewer 6000';
const machine = await client.get(modeluri, ModelServerObjectV2.is);
const patchedMachine = deepClone(machine);
// Directly change the model
patchedMachine.name = newName;
patchedMachine.children[1].processor.clockSpeed = 6;
// Generate patches by diffing the original model and the patched one
const patch = jsonpatch.compare(machine, patchedMachine);
const result = await client.edit(modeluri, patch);
expect(result.success).to.be.true;
expect(result.patch).to.not.be.undefined;
expect(result.allPatches).to.not.be.undefined;
expect(result.allPatches).to.be.an('array').of.length(1);
// Patch the main resource
const updatedMachineMainPatch = result.patchModel!(machine, true);
expect(patchedMachine).to.deep.equal(updatedMachineMainPatch);
// Patch the first resource
const updatedMachineFirstPatch = result.patchModel!(machine, true, new URI(result.allPatches![0].modelUri));
expect(patchedMachine).to.deep.equal(updatedMachineFirstPatch);
await testUndoRedo(modeluri, machine, updatedMachineFirstPatch);
});
});
});

@@ -1,2 +0,2 @@

/*********************************************************************************
/********************************************************************************
* Copyright (c) 2022 STMicroelectronics and others.

@@ -10,3 +10,3 @@ *

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
import { strictEqual } from 'assert';

@@ -17,2 +17,3 @@ import { expect } from 'chai';

import { spy } from 'sinon';
import URI from 'urijs';

@@ -27,3 +28,8 @@ import { ServerConfiguration } from './model-server-client-api-v1';

let client: ModelServerClientV2;
const baseUrl = `http://localhost:8081${ModelServerClientApiV2.API_ENDPOINT}`;
const baseUrl = new URI({
protocol: 'http',
hostname: 'localhost',
port: '8081',
path: ModelServerClientApiV2.API_ENDPOINT
});

@@ -42,4 +48,16 @@ beforeEach(() => {

const axios = client['restClient'];
expect(axios.defaults.baseURL).to.be.equal(baseUrl);
expect(axios.defaults.baseURL).to.be.equal(baseUrl.toString());
});
it('test createSubscriptionPath without trailing slash', () => {
client = new ModelServerClientV2();
client.initialize(baseUrl);
const subscriptionPath = client['createSubscriptionPath'](new URI('foo'), {});
expect(subscriptionPath.toString()).to.be.equal('ws://localhost:8081/api/v2/subscribe?modeluri=foo&format=json-v2');
});
it('test createSubscriptionPath with trailing slash', () => {
client = new ModelServerClientV2();
client.initialize(new URI(`${baseUrl}/`));
const subscriptionPath = client['createSubscriptionPath'](new URI('foo'), {});
expect(subscriptionPath.toString()).to.be.equal('ws://localhost:8081/api/v2/subscribe?modeluri=foo&format=json-v2');
});

@@ -55,3 +73,3 @@ describe('test requests', () => {

expect(request.config.params).to.include({ format: FORMAT_JSON_V2 });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.MODEL_CRUD);

@@ -70,3 +88,3 @@ request = moxios.requests.at(1);

expect(request.config.params).to.be.undefined;
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.MODEL_URIS);

@@ -78,3 +96,3 @@ done();

it('getElementById', done => {
const modeluri = 'my/uri.model';
const modeluri = new URI('my/uri.model');
const elementid = 'myElement';

@@ -88,7 +106,7 @@

expect(request.config.method).to.be.equal('get');
expect(request.config.params).to.include({ format: FORMAT_JSON_V2, elementid, modeluri });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.params).to.include({ format: FORMAT_JSON_V2, elementid, modeluri: modeluri.toString() });
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.MODEL_ELEMENT);
request = moxios.requests.at(1);
expect(request.config.params).to.include({ format: FORMAT_XMI, elementid, modeluri });
expect(request.config.params).to.include({ format: FORMAT_XMI, elementid, modeluri: modeluri.toString() });
done();

@@ -99,3 +117,3 @@ });

it('getElementByName', done => {
const modeluri = 'my/uri.model';
const modeluri = new URI('my/uri.model');
const elementname = 'myElement';

@@ -109,7 +127,7 @@

expect(request.config.method).to.be.equal('get');
expect(request.config.params).to.include({ format: FORMAT_JSON_V2, elementname, modeluri });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.params).to.include({ format: FORMAT_JSON_V2, elementname, modeluri: modeluri.toString() });
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.MODEL_ELEMENT);
request = moxios.requests.at(1);
expect(request.config.params).to.include({ format: FORMAT_XMI, elementname, modeluri });
expect(request.config.params).to.include({ format: FORMAT_XMI, elementname, modeluri: modeluri.toString() });
done();

@@ -120,3 +138,3 @@ });

it('delete', done => {
const modeluri = 'delete/me/please';
const modeluri = new URI('delete/me/please');
client.delete(modeluri);

@@ -126,4 +144,4 @@ moxios.wait(() => {

expect(request.config.method).to.be.equal('delete');
expect(request.config.params).to.include({ modeluri });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.params).to.include({ modeluri: modeluri.toString() });
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.MODEL_CRUD);

@@ -135,3 +153,3 @@ done();

it('close', done => {
const modeluri = 'delete/me/please';
const modeluri = new URI('delete/me/please');
client.close(modeluri);

@@ -141,4 +159,4 @@ moxios.wait(() => {

expect(request.config.method).to.be.equal('post');
expect(request.config.params).to.include({ modeluri });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.params).to.include({ modeluri: modeluri.toString() });
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.CLOSE);

@@ -150,3 +168,3 @@ done();

it('create', done => {
const modeluri = 'delete/me/please';
const modeluri = new URI('delete/me/please');
const model = { name: 'myModel', id: 'myModelId' };

@@ -161,7 +179,7 @@ const data = JSON.stringify(model);

expect(request.config.data).to.be.equal(JSON.stringify({ data }));
expect(request.config.params).to.include({ format: FORMAT_JSON_V2, modeluri });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.params).to.include({ format: FORMAT_JSON_V2, modeluri: modeluri.toString() });
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.MODEL_CRUD);
request = moxios.requests.at(1);
expect(request.config.params).to.include({ format: FORMAT_XMI, modeluri });
expect(request.config.params).to.include({ format: FORMAT_XMI, modeluri: modeluri.toString() });
done();

@@ -172,3 +190,3 @@ });

it('update', done => {
const modeluri = 'delete/me/please';
const modeluri = new URI('delete/me/please');
const model = { name: 'myModel', id: 'myModelId' };

@@ -183,7 +201,7 @@ const data = JSON.stringify(model);

expect(request.config.data).to.be.equal(JSON.stringify({ data }));
expect(request.config.params).to.include({ format: FORMAT_JSON_V2, modeluri });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.params).to.include({ format: FORMAT_JSON_V2, modeluri: modeluri.toString() });
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.MODEL_CRUD);
request = moxios.requests.at(1);
expect(request.config.params).to.include({ format: FORMAT_XMI, modeluri });
expect(request.config.params).to.include({ format: FORMAT_XMI, modeluri: modeluri.toString() });
done();

@@ -194,3 +212,3 @@ });

it('save', done => {
const modeluri = 'save/me/please';
const modeluri = new URI('save/me/please');
client.save(modeluri);

@@ -200,4 +218,4 @@ moxios.wait(() => {

expect(request.config.method).to.be.equal('get');
expect(request.config.params).to.include({ modeluri });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.params).to.include({ modeluri: modeluri.toString() });
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.SAVE);

@@ -214,3 +232,3 @@ done();

expect(request.config.params).to.be.undefined;
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.SAVE_ALL);

@@ -222,3 +240,3 @@ done();

it('validate', done => {
const modeluri = 'validate/me/please';
const modeluri = new URI('validate/me/please');
client.validate(modeluri);

@@ -228,4 +246,4 @@ moxios.wait(() => {

expect(request.config.method).to.be.equal('get');
expect(request.config.params).to.include({ modeluri });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.params).to.include({ modeluri: modeluri.toString() });
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.VALIDATION);

@@ -237,3 +255,3 @@ done();

it('getValidationConstraints', done => {
const modeluri = 'validate/me/please';
const modeluri = new URI('validate/me/please');
client.getValidationConstraints(modeluri);

@@ -243,4 +261,4 @@ moxios.wait(() => {

expect(request.config.method).to.be.equal('get');
expect(request.config.params).to.include({ modeluri });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.params).to.include({ modeluri: modeluri.toString() });
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.VALIDATION_CONSTRAINTS);

@@ -252,3 +270,3 @@ done();

it('getTypeSchema', done => {
const modeluri = 'my/model/uri';
const modeluri = new URI('my/model/uri');
client.getTypeSchema(modeluri);

@@ -258,4 +276,4 @@ moxios.wait(() => {

expect(request.config.method).to.be.equal('get');
expect(request.config.params).to.include({ modeluri });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.params).to.include({ modeluri: modeluri.toString() });
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.TYPE_SCHEMA);

@@ -273,3 +291,3 @@ done();

expect(request.config.params).to.include({ schemaname });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.UI_SCHEMA);

@@ -282,4 +300,4 @@ done();

const configuration: ServerConfiguration = {
workspaceRoot: 'myRoot',
uiSchemaFolder: 'mySchemaFolder'
workspaceRoot: new URI('myRoot'),
uiSchemaFolder: new URI('mySchemaFolder')
};

@@ -290,5 +308,10 @@ client.configureServer(configuration);

expect(request.config.method).to.be.equal('put');
expect(request.config.data).to.equal(JSON.stringify(configuration));
expect(request.config.data).to.equal(
JSON.stringify({
workspaceRoot: configuration.workspaceRoot.toString(),
uiSchemaFolder: configuration.uiSchemaFolder!.toString()
})
);
expect(request.config.params).to.be.undefined;
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.SERVER_CONFIGURE);

@@ -305,3 +328,3 @@ done();

expect(request.config.params).to.be.undefined;
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.SERVER_PING);

@@ -313,3 +336,3 @@ done();

it('edit', done => {
const modeluri = 'edit/me/please';
const modeluri = new URI('edit/me/please');
const patch: Operation[] = [

@@ -332,4 +355,4 @@ {

expect(request.config.data).to.be.equal(JSON.stringify({ data: expected }));
expect(request.config.params).to.include({ format: FORMAT_JSON_V2, modeluri });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.params).to.include({ format: FORMAT_JSON_V2, modeluri: modeluri.toString() });
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.MODEL_CRUD);

@@ -341,3 +364,3 @@ done();

it('undo', done => {
const modeluri = 'undo/me/please';
const modeluri = new URI('undo/me/please');
client.undo(modeluri);

@@ -347,4 +370,4 @@ moxios.wait(() => {

expect(request.config.method).to.be.equal('get');
expect(request.config.params).to.be.include({ modeluri });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.params).to.be.include({ modeluri: modeluri.toString() });
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.UNDO);

@@ -356,3 +379,3 @@ done();

it('redo', done => {
const modeluri = 'redo/me/please';
const modeluri = new URI('redo/me/please');
client.redo(modeluri);

@@ -362,4 +385,4 @@ moxios.wait(() => {

expect(request.config.method).to.be.equal('get');
expect(request.config.params).to.be.include({ modeluri });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.params).to.be.include({ modeluri: modeluri.toString() });
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.REDO);

@@ -372,3 +395,3 @@ done();

describe('test responses', () => {
it('ping ', done => {
it('ping', done => {
const expectedMsg: ModelServerMessage = {

@@ -391,5 +414,5 @@ data: '',

it('ping ', done => {
it('getAll', done => {
const model1: Model = {
modelUri: 'path/to/model1',
modeluri: 'path/to/model1',
content: {

@@ -400,3 +423,3 @@ name: 'coffee'

const model2: Model = {
modelUri: 'path/to/model2',
modeluri: 'path/to/model2',
content: {

@@ -408,4 +431,4 @@ name: 'coffee'

data: {
[model1.modelUri]: model1.content,
[model2.modelUri]: model2.content
[model1.modeluri.toString()]: model1.content,
[model2.modeluri.toString()]: model2.content
},

@@ -423,3 +446,4 @@ type: 'success'

const result = onFulfilled.getCall(0).args[0];
expect(result).to.deep.include.members([model2, model1]);
expect(result).to.be.an('array').of.length(2);
expect(result).to.deep.include.members([model1, model2]);
done();

@@ -426,0 +450,0 @@ });

@@ -1,3 +0,3 @@

/*********************************************************************************
* Copyright (c) 2022 STMicroelectronics and others.
/********************************************************************************
* Copyright (c) 2022-2023 STMicroelectronics and others.
*

@@ -10,9 +10,10 @@ * This program and the accompanying materials are made available under the

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
import axios, { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
import { Operation } from 'fast-json-patch';
*******************************************************************************/
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
import { deepClone } from 'fast-json-patch';
import WebSocket from 'isomorphic-ws';
import URI from 'urijs';
import { ModelServerError, ServerConfiguration, SubscriptionOptions } from './model-server-client-api-v1';
import { Format, FORMAT_JSON_V2, ModelServerClientApiV2, ModelUpdateResult } from './model-server-client-api-v2';
import { Format, FORMAT_JSON_V2, ModelServerClientApiV2, ModelUpdateResult, PatchOrCommand } from './model-server-client-api-v2';
import { MessageDataMapper, Model, ModelServerMessage } from './model-server-message';

@@ -31,7 +32,7 @@ import { ModelServerPaths } from './model-server-paths';

protected openSockets: Map<string, WebSocket> = new Map();
protected _baseUrl: string;
protected _baseUrl: URI;
protected defaultFormat: Format = FORMAT_JSON_V2;
initialize(baseUrl: string, defaultFormat: Format = FORMAT_JSON_V2): void | Promise<void> {
this._baseUrl = baseUrl;
initialize(baseUrl: URI, defaultFormat: Format = FORMAT_JSON_V2): void | Promise<void> {
this._baseUrl = baseUrl.clone();
this.defaultFormat = defaultFormat;

@@ -41,17 +42,21 @@ this.restClient = axios.create(this.getAxiosConfig(baseUrl));

protected getAxiosConfig(baseURL: string): AxiosRequestConfig | undefined {
return { baseURL };
protected getAxiosConfig(baseURL: URI): AxiosRequestConfig | undefined {
return { baseURL: baseURL.toString() };
}
get(modeluri: string, format?: Format): Promise<AnyObject>;
get<M>(modeluri: string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
get<M>(modeluri: string, formatOrGuard?: FormatOrGuard<M>, format?: Format): Promise<AnyObject | M> {
get(modeluri: URI, format?: Format): Promise<AnyObject>;
get<M>(modeluri: URI, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
get<M>(modeluri: URI, formatOrGuard?: FormatOrGuard<M>, format?: Format): Promise<AnyObject | M> {
if (typeof formatOrGuard === 'function') {
const typeGuard = formatOrGuard;
return this.process(this.restClient.get(ModelServerPaths.MODEL_CRUD, { params: { modeluri, format } }), msg =>
MessageDataMapper.as(msg, typeGuard)
return this.process(
this.restClient.get(ModelServerPaths.MODEL_CRUD, { params: { modeluri: modeluri.toString(), format } }),
msg => MessageDataMapper.as(msg, typeGuard)
);
}
format = formatOrGuard ?? this.defaultFormat;
return this.process(this.restClient.get(ModelServerPaths.MODEL_CRUD, { params: { modeluri, format } }), MessageDataMapper.asObject);
return this.process(
this.restClient.get(ModelServerPaths.MODEL_CRUD, { params: { modeluri: modeluri.toString(), format } }),
MessageDataMapper.asObject
);
}

@@ -79,9 +84,9 @@

getModelUris(): Promise<string[]> {
return this.process(this.restClient.get(ModelServerPaths.MODEL_URIS), MessageDataMapper.asStringArray);
getModelUris(): Promise<URI[]> {
return this.process(this.restClient.get(ModelServerPaths.MODEL_URIS), MessageDataMapper.asURIArray);
}
getElementById(modeluri: string, elementid: string, format?: Format): Promise<AnyObject>;
getElementById<M>(modeluri: string, elementid: string, typeGuard: TypeGuard<M>): Promise<M>;
getElementById<M>(modeluri: string, elementid: string, formatOrGuard?: FormatOrGuard<M>, format?: string): Promise<AnyObject | M> {
getElementById(modeluri: URI, elementid: string, format?: Format): Promise<AnyObject>;
getElementById<M>(modeluri: URI, elementid: string, typeGuard: TypeGuard<M>): Promise<M>;
getElementById<M>(modeluri: URI, elementid: string, formatOrGuard?: FormatOrGuard<M>, format?: string): Promise<AnyObject | M> {
format = format ?? this.defaultFormat;

@@ -91,4 +96,5 @@ if (formatOrGuard) {

const typeGuard = formatOrGuard;
return this.process(this.restClient.get(ModelServerPaths.MODEL_ELEMENT, { params: { modeluri, elementid, format } }), msg =>
MessageDataMapper.as(msg, typeGuard)
return this.process(
this.restClient.get(ModelServerPaths.MODEL_ELEMENT, { params: { modeluri: modeluri.toString(), elementid, format } }),
msg => MessageDataMapper.as(msg, typeGuard)
);

@@ -99,3 +105,3 @@ }

return this.process(
this.restClient.get(ModelServerPaths.MODEL_ELEMENT, { params: { modeluri, elementid, format } }),
this.restClient.get(ModelServerPaths.MODEL_ELEMENT, { params: { modeluri: modeluri.toString(), elementid, format } }),
MessageDataMapper.asObject

@@ -105,5 +111,5 @@ );

getElementByName(modeluri: string, elementname: string, format?: Format): Promise<AnyObject>;
getElementByName<M>(modeluri: string, elementname: string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
getElementByName<M>(modeluri: string, elementname: string, formatOrGuard?: FormatOrGuard<M>, format?: Format): Promise<AnyObject | M> {
getElementByName(modeluri: URI, elementname: string, format?: Format): Promise<AnyObject>;
getElementByName<M>(modeluri: URI, elementname: string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
getElementByName<M>(modeluri: URI, elementname: string, formatOrGuard?: FormatOrGuard<M>, format?: Format): Promise<AnyObject | M> {
format = format ?? this.defaultFormat;

@@ -114,3 +120,3 @@ if (formatOrGuard) {

return this.process(
this.restClient.get(ModelServerPaths.MODEL_ELEMENT, { params: { modeluri, elementname, format } }),
this.restClient.get(ModelServerPaths.MODEL_ELEMENT, { params: { modeluri: modeluri.toString(), elementname, format } }),
msg => MessageDataMapper.as(msg, typeGuard)

@@ -122,3 +128,3 @@ );

return this.process(
this.restClient.get(ModelServerPaths.MODEL_ELEMENT, { params: { modeluri, elementname, format } }),
this.restClient.get(ModelServerPaths.MODEL_ELEMENT, { params: { modeluri: modeluri.toString(), elementname, format } }),
MessageDataMapper.asObject

@@ -128,5 +134,5 @@ );

create(modeluri: string, model: AnyObject | string, format?: Format): Promise<AnyObject>;
create<M>(modeluri: string, model: AnyObject | string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
create<M>(modeluri: string, model: AnyObject | string, formatOrGuard?: FormatOrGuard<M>, format?: Format): Promise<AnyObject | M> {
create(modeluri: URI, model: AnyObject | string, format?: Format): Promise<AnyObject>;
create<M>(modeluri: URI, model: AnyObject | string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
create<M>(modeluri: URI, model: AnyObject | string, formatOrGuard?: FormatOrGuard<M>, format?: Format): Promise<AnyObject | M> {
format = format ?? this.defaultFormat;

@@ -137,3 +143,5 @@ if (formatOrGuard) {

return this.process(
this.restClient.post(ModelServerPaths.MODEL_CRUD, encodeRequestBody(format)(model), { params: { modeluri, format } }),
this.restClient.post(ModelServerPaths.MODEL_CRUD, encodeRequestBody(format)(model), {
params: { modeluri: modeluri.toString(), format }
}),
msg => MessageDataMapper.as(msg, typeGuard)

@@ -145,3 +153,5 @@ );

return this.process(
this.restClient.post(ModelServerPaths.MODEL_CRUD, encodeRequestBody(format)(model), { params: { modeluri, format } }),
this.restClient.post(ModelServerPaths.MODEL_CRUD, encodeRequestBody(format)(model), {
params: { modeluri: modeluri.toString(), format }
}),
MessageDataMapper.asObject

@@ -151,6 +161,6 @@ );

update(modeluri: string, model: AnyObject | string, format?: Format): Promise<AnyObject>;
update<M>(modeluri: string, model: string | string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
update(modeluri: URI, model: AnyObject | string, format?: Format): Promise<AnyObject>;
update<M>(modeluri: URI, model: string | string, typeGuard: TypeGuard<M>, format?: Format): Promise<M>;
update<M>(
modeluri: string,
modeluri: URI,
model: AnyObject | string,

@@ -165,3 +175,5 @@ formatOrGuard?: FormatOrGuard<M>,

return this.process(
this.restClient.put(ModelServerPaths.MODEL_CRUD, encodeRequestBody(format)(model), { params: { modeluri, format } }),
this.restClient.put(ModelServerPaths.MODEL_CRUD, encodeRequestBody(format)(model), {
params: { modeluri: modeluri.toString(), format }
}),
msg => MessageDataMapper.as(msg, typeGuard)

@@ -173,3 +185,5 @@ );

return this.process(
this.restClient.put(ModelServerPaths.MODEL_CRUD, encodeRequestBody(format)(model), { params: { modeluri, format } }),
this.restClient.put(ModelServerPaths.MODEL_CRUD, encodeRequestBody(format)(model), {
params: { modeluri: modeluri.toString(), format }
}),
MessageDataMapper.asObject

@@ -179,12 +193,21 @@ );

delete(modeluri: string): Promise<boolean> {
return this.process(this.restClient.delete(ModelServerPaths.MODEL_CRUD, { params: { modeluri } }), MessageDataMapper.isSuccess);
delete(modeluri: URI): Promise<boolean> {
return this.process(
this.restClient.delete(ModelServerPaths.MODEL_CRUD, { params: { modeluri: modeluri.toString() } }),
MessageDataMapper.isSuccess
);
}
close(modeluri: string): Promise<boolean> {
return this.process(this.restClient.post(ModelServerPaths.CLOSE, undefined, { params: { modeluri } }), MessageDataMapper.isSuccess);
close(modeluri: URI): Promise<boolean> {
return this.process(
this.restClient.post(ModelServerPaths.CLOSE, undefined, { params: { modeluri: modeluri.toString() } }),
MessageDataMapper.isSuccess
);
}
save(modeluri: string): Promise<boolean> {
return this.process(this.restClient.get(ModelServerPaths.SAVE, { params: { modeluri } }), MessageDataMapper.isSuccess);
save(modeluri: URI): Promise<boolean> {
return this.process(
this.restClient.get(ModelServerPaths.SAVE, { params: { modeluri: modeluri.toString() } }),
MessageDataMapper.isSuccess
);
}

@@ -196,4 +219,4 @@

validate(modeluri: string): Promise<Diagnostic> {
return this.process(this.restClient.get(ModelServerPaths.VALIDATION, { params: { modeluri } }), response =>
validate(modeluri: URI): Promise<Diagnostic> {
return this.process(this.restClient.get(ModelServerPaths.VALIDATION, { params: { modeluri: modeluri.toString() } }), response =>
MessageDataMapper.as(response, Diagnostic.is)

@@ -203,5 +226,5 @@ );

getValidationConstraints(modeluri: string): Promise<string> {
getValidationConstraints(modeluri: URI): Promise<string> {
return this.process(
this.restClient.get(ModelServerPaths.VALIDATION_CONSTRAINTS, { params: { modeluri } }),
this.restClient.get(ModelServerPaths.VALIDATION_CONSTRAINTS, { params: { modeluri: modeluri.toString() } }),
MessageDataMapper.asString

@@ -211,4 +234,7 @@ );

getTypeSchema(modeluri: string): Promise<string> {
return this.process(this.restClient.get(ModelServerPaths.TYPE_SCHEMA, { params: { modeluri } }), MessageDataMapper.asString);
getTypeSchema(modeluri: URI): Promise<string> {
return this.process(
this.restClient.get(ModelServerPaths.TYPE_SCHEMA, { params: { modeluri: modeluri.toString() } }),
MessageDataMapper.asString
);
}

@@ -221,7 +247,7 @@

configureServer(configuration: ServerConfiguration): Promise<boolean> {
let { workspaceRoot, uiSchemaFolder } = configuration;
workspaceRoot = workspaceRoot.replace('file://', '');
uiSchemaFolder = uiSchemaFolder?.replace('file://', '');
return this.process(
this.restClient.put(ModelServerPaths.SERVER_CONFIGURE, { workspaceRoot, uiSchemaFolder }),
this.restClient.put(ModelServerPaths.SERVER_CONFIGURE, {
workspaceRoot: configuration.workspaceRoot.toString(),
uiSchemaFolder: configuration.uiSchemaFolder?.toString()
}),
MessageDataMapper.isSuccess

@@ -235,6 +261,3 @@ );

edit(modeluri: string, patch: Operation): Promise<ModelUpdateResult>;
edit(modeluri: string, patch: Operation[]): Promise<ModelUpdateResult>;
edit(modeluri: string, command: ModelServerCommand): Promise<ModelUpdateResult>;
edit(modeluri: string, patchOrCommand: Operation | Operation[] | ModelServerCommand): Promise<ModelUpdateResult> {
edit(modeluri: URI, patchOrCommand: PatchOrCommand, format = this.defaultFormat): Promise<ModelUpdateResult> {
let patchMessage: any;

@@ -247,2 +270,3 @@ if (patchOrCommand instanceof ModelServerCommand) {

} else {
// Operation[] and ModelPatch[] are treated in the same way; we don't need to distinguish both cases
const fullPatch = Array.isArray(patchOrCommand) ? patchOrCommand : [patchOrCommand];

@@ -253,9 +277,15 @@ patchMessage = {

};
if (fullPatch.length === 0) {
// No-op
return Promise.resolve({
success: true,
patchModel: (oldModel, copy, _modeluri) => (copy ? deepClone(oldModel) : oldModel),
patch: []
});
}
}
return this.process(
this.restClient.patch(
ModelServerPaths.MODEL_CRUD,
encodeRequestBody(this.defaultFormat)(patchMessage),
{ params: { modeluri, format: this.defaultFormat } }
),
this.restClient.patch(ModelServerPaths.MODEL_CRUD, encodeRequestBody(format)(patchMessage), {
params: { modeluri: modeluri.toString(), format: format }
}),
MessageDataMapper.patchModel

@@ -265,23 +295,29 @@ );

undo(modeluri: string): Promise<ModelUpdateResult> {
return this.process(this.restClient.get(ModelServerPaths.UNDO, { params: { modeluri } }), MessageDataMapper.patchModel);
undo(modeluri: URI): Promise<ModelUpdateResult> {
return this.process(
this.restClient.get(ModelServerPaths.UNDO, { params: { modeluri: modeluri.toString() } }),
MessageDataMapper.patchModel
);
}
redo(modeluri: string): Promise<ModelUpdateResult> {
return this.process(this.restClient.get(ModelServerPaths.REDO, { params: { modeluri } }), MessageDataMapper.patchModel);
redo(modeluri: URI): Promise<ModelUpdateResult> {
return this.process(
this.restClient.get(ModelServerPaths.REDO, { params: { modeluri: modeluri.toString() } }),
MessageDataMapper.patchModel
);
}
send(modelUri: string, message: ModelServerMessage): void {
const openSocket = this.openSockets.get(modelUri);
send(modeluri: URI, message: ModelServerMessage): void {
const openSocket = this.openSockets.get(modeluri.toString());
if (openSocket) {
openSocket.send(message);
openSocket.send(JSON.stringify(message));
}
}
subscribe(modeluri: string, listener: SubscriptionListener, options: SubscriptionOptions = {}): SubscriptionListener {
subscribe(modeluri: URI, listener: SubscriptionListener, options: SubscriptionOptions = {}): SubscriptionListener {
if (this.isSocketOpen(modeluri)) {
const errorMsg = `${modeluri} : Cannot open new socket, already subscribed!'`;
const errorMsg = `${modeluri.toString()} : Cannot open new socket, already subscribed!'`;
console.warn(errorMsg);
if (options.errorWhenUnsuccessful) {
throw new Error('errorMsg');
throw new Error(errorMsg);
}

@@ -294,32 +330,33 @@ }

unsubscribe(modeluri: string): void {
const openSocket = this.openSockets.get(modeluri);
unsubscribe(modeluri: URI): void {
const openSocket = this.openSockets.get(modeluri.toString());
if (openSocket) {
openSocket.close();
this.openSockets.delete(modeluri);
this.openSockets.delete(modeluri.toString());
}
}
protected createSubscriptionPath(modeluri: string, options: SubscriptionOptions): string {
const queryParams = new URLSearchParams();
queryParams.append('modeluri', modeluri);
if (!options.format) {
options.format = this.defaultFormat;
}
Object.entries(options).forEach(entry => queryParams.append(entry[0], entry[1]));
queryParams.delete('errorWhenUnsuccessful');
return `${this._baseUrl}/${ModelServerPaths.SUBSCRIPTION}?${queryParams.toString()}`.replace(/^(http|https):\/\//i, 'ws://');
protected createSubscriptionPath(modeluri: URI, options: SubscriptionOptions): URI {
const { ...paramOptions } = options;
const subscriptionUri = this._baseUrl.clone();
subscriptionUri.protocol('ws');
subscriptionUri.segment(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;
}
protected doSubscribe(listener: SubscriptionListener, modelUri: string, path: string): void {
const socket = new WebSocket(path.trim());
socket.onopen = event => listener.onOpen?.(modelUri, event);
socket.onclose = event => listener.onClose?.(modelUri, event);
socket.onerror = event => listener.onError?.(modelUri, event);
socket.onmessage = event => listener.onMessage?.(modelUri, event);
this.openSockets.set(modelUri, socket);
protected doSubscribe(listener: SubscriptionListener, modeluri: URI, path: URI): void {
const socket = new WebSocket(path.toString() /* .trim() */);
socket.onopen = event => listener.onOpen?.(modeluri, event);
socket.onclose = event => listener.onClose?.(modeluri, event);
socket.onerror = event => listener.onError?.(modeluri, event);
socket.onmessage = event => listener.onMessage?.(modeluri, event);
this.openSockets.set(modeluri.toString(), socket);
}
protected isSocketOpen(modelUri: string): boolean {
return this.openSockets.get(modelUri) !== undefined;
protected isSocketOpen(modeluri: URI): boolean {
return this.openSockets.get(modeluri.toString()) !== undefined;
}

@@ -335,3 +372,3 @@

} catch (error) {
if (isAxiosError(error)) {
if (axios.isAxiosError(error)) {
const message = error.response?.data ? error.response.data : error.message;

@@ -346,6 +383,2 @@ throw new ModelServerError(message, error.code);

function isAxiosError(error: any): error is AxiosError {
return error !== undefined && error instanceof Error && 'isAxiosError' in error && error['isAxiosError'];
}
/**

@@ -358,9 +391,9 @@ * Helper type for method overloads where on parameter could either be

function mapModel<M>(model: Model, guard?: TypeGuard<M>, toString = false): Model<AnyObject | M | string> {
const { modelUri, content } = model;
const { modeluri, content } = model;
if (guard) {
return { modelUri, content: asType(content, guard) };
return { modeluri, content: asType(content, guard) };
} else if (toString) {
return { modelUri, content: asString(content) };
return { modeluri, content: asString(content) };
}
return { modelUri, content: asObject(content) };
return { modeluri, content: asObject(content) };
}

@@ -1,2 +0,2 @@

/*********************************************************************************
/********************************************************************************
* Copyright (c) 2021-2022 STMicroelectronics and others.

@@ -10,3 +10,3 @@ *

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
import { strictEqual } from 'assert';

@@ -16,2 +16,3 @@ import { expect } from 'chai';

import { spy } from 'sinon';
import URI from 'urijs';

@@ -26,3 +27,8 @@ import { ModelServerClient } from './model-server-client';

let client: ModelServerClient;
const baseUrl = `http://localhost:8081${ModelServerClientApiV1.API_ENDPOINT}`;
const baseUrl = new URI({
protocol: 'http',
hostname: 'localhost',
port: '8081',
path: ModelServerClientApiV1.API_ENDPOINT
});

@@ -41,4 +47,16 @@ beforeEach(() => {

const axios = client['restClient'];
expect(axios.defaults.baseURL).to.be.equal(baseUrl);
expect(axios.defaults.baseURL).to.be.equal(baseUrl.toString());
});
it('test createSubscriptionPath without trailing slash', () => {
client = new ModelServerClient();
client.initialize(baseUrl);
const subscriptionPath = client['createSubscriptionPath'](new URI('foo'), {});
expect(subscriptionPath.toString()).to.be.equal('ws://localhost:8081/api/v1/subscribe?modeluri=foo&format=json');
});
it('test createSubscriptionPath with trailing slash', () => {
client = new ModelServerClient();
client.initialize(new URI(`${baseUrl}/`));
const subscriptionPath = client['createSubscriptionPath'](new URI('foo'), {});
expect(subscriptionPath.toString()).to.be.equal('ws://localhost:8081/api/v1/subscribe?modeluri=foo&format=json');
});

@@ -54,3 +72,3 @@ describe('test requests', () => {

expect(request.config.params).to.include({ format: 'json' });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.MODEL_CRUD);

@@ -69,3 +87,3 @@ request = moxios.requests.at(1);

expect(request.config.params).to.be.undefined;
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.MODEL_URIS);

@@ -77,3 +95,3 @@ done();

it('getElementById', done => {
const modeluri = 'my/uri.model';
const modeluri = new URI('my/uri.model');
const elementid = 'myElement';

@@ -88,3 +106,3 @@

expect(request.config.params).to.include({ format: 'json', elementid, modeluri });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.MODEL_ELEMENT);

@@ -98,3 +116,3 @@ request = moxios.requests.at(1);

it('getElementByName', done => {
const modeluri = 'my/uri.model';
const modeluri = new URI('my/uri.model');
const elementname = 'myElement';

@@ -109,3 +127,3 @@

expect(request.config.params).to.include({ format: 'json', elementname, modeluri });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.MODEL_ELEMENT);

@@ -119,3 +137,3 @@ request = moxios.requests.at(1);

it('delete', done => {
const modeluri = 'delete/me/please';
const modeluri = new URI('delete/me/please');
client.delete(modeluri);

@@ -126,3 +144,3 @@ moxios.wait(() => {

expect(request.config.params).to.include({ modeluri });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.MODEL_CRUD);

@@ -134,3 +152,3 @@ done();

it('close', done => {
const modeluri = 'delete/me/please';
const modeluri = new URI('delete/me/please');
client.close(modeluri);

@@ -141,3 +159,3 @@ moxios.wait(() => {

expect(request.config.params).to.include({ modeluri });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.CLOSE);

@@ -149,3 +167,3 @@ done();

it('create', done => {
const modeluri = 'delete/me/please';
const modeluri = new URI('delete/me/please');
const model = { name: 'myModel', id: 'myModelId' };

@@ -161,3 +179,3 @@ const data = JSON.stringify(model);

expect(request.config.params).to.include({ format: 'json', modeluri });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.MODEL_CRUD);

@@ -171,3 +189,3 @@ request = moxios.requests.at(1);

it('update', done => {
const modeluri = 'delete/me/please';
const modeluri = new URI('delete/me/please');
const model = { name: 'myModel', id: 'myModelId' };

@@ -183,3 +201,3 @@ const data = JSON.stringify(model);

expect(request.config.params).to.include({ format: 'json', modeluri });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.MODEL_CRUD);

@@ -193,3 +211,3 @@ request = moxios.requests.at(1);

it('save', done => {
const modeluri = 'save/me/please';
const modeluri = new URI('save/me/please');
client.save(modeluri);

@@ -200,3 +218,3 @@ moxios.wait(() => {

expect(request.config.params).to.include({ modeluri });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.SAVE);

@@ -213,3 +231,3 @@ done();

expect(request.config.params).to.be.undefined;
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.SAVE_ALL);

@@ -221,3 +239,3 @@ done();

it('validate', done => {
const modeluri = 'validate/me/please';
const modeluri = new URI('validate/me/please');
client.validate(modeluri);

@@ -228,3 +246,3 @@ moxios.wait(() => {

expect(request.config.params).to.include({ modeluri });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.VALIDATION);

@@ -236,3 +254,3 @@ done();

it('getValidationConstraints', done => {
const modeluri = 'validate/me/please';
const modeluri = new URI('validate/me/please');
client.getValidationConstraints(modeluri);

@@ -243,3 +261,3 @@ moxios.wait(() => {

expect(request.config.params).to.include({ modeluri });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.VALIDATION_CONSTRAINTS);

@@ -251,3 +269,3 @@ done();

it('getTypeSchema', done => {
const modeluri = 'my/model/uri';
const modeluri = new URI('my/model/uri');
client.getTypeSchema(modeluri);

@@ -258,3 +276,3 @@ moxios.wait(() => {

expect(request.config.params).to.include({ modeluri });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.TYPE_SCHEMA);

@@ -272,3 +290,3 @@ done();

expect(request.config.params).to.include({ schemaname });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.UI_SCHEMA);

@@ -281,4 +299,4 @@ done();

const configuration: ServerConfiguration = {
workspaceRoot: 'myRoot',
uiSchemaFolder: 'mySchemaFolder'
workspaceRoot: new URI('myRoot'),
uiSchemaFolder: new URI('mySchemaFolder')
};

@@ -289,5 +307,10 @@ client.configureServer(configuration);

expect(request.config.method).to.be.equal('put');
expect(request.config.data).to.equal(JSON.stringify(configuration));
expect(request.config.data).to.equal(
JSON.stringify({
workspaceRoot: configuration.workspaceRoot.toString(),
uiSchemaFolder: configuration.uiSchemaFolder!.toString()
})
);
expect(request.config.params).to.be.undefined;
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.SERVER_CONFIGURE);

@@ -304,3 +327,3 @@ done();

expect(request.config.params).to.be.undefined;
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.SERVER_PING);

@@ -312,3 +335,3 @@ done();

it('edit', done => {
const modeluri = 'edit/me/please';
const modeluri = new URI('edit/me/please');
const command = new SetCommand(

@@ -330,3 +353,3 @@ {

expect(request.config.params).to.include({ format: 'json', modeluri });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.EDIT);

@@ -338,3 +361,3 @@ done();

it('undo', done => {
const modeluri = 'undo/me/please';
const modeluri = new URI('undo/me/please');
client.undo(modeluri);

@@ -345,3 +368,3 @@ moxios.wait(() => {

expect(request.config.params).to.be.include({ modeluri });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.UNDO);

@@ -353,3 +376,3 @@ done();

it('redo', done => {
const modeluri = 'redo/me/please';
const modeluri = new URI('redo/me/please');
client.redo(modeluri);

@@ -360,3 +383,3 @@ moxios.wait(() => {

expect(request.config.params).to.be.include({ modeluri });
expect(request.config.baseURL).to.be.equal(baseUrl);
expect(request.config.baseURL).to.be.equal(baseUrl.toString());
expect(request.config.url).to.be.equal(ModelServerPaths.REDO);

@@ -369,3 +392,3 @@ done();

describe('test responses', () => {
it('ping ', done => {
it('ping', done => {
const expectedMsg: ModelServerMessage = {

@@ -390,3 +413,3 @@ data: '',

const model1: Model = {
modelUri: 'path/to/model1',
modeluri: 'file:/path/to/model1',
content: {

@@ -397,3 +420,3 @@ name: 'coffee'

const model2: Model = {
modelUri: 'path/to/model2',
modeluri: 'file:/path/to/model2',
content: {

@@ -405,4 +428,4 @@ name: 'coffee'

data: {
[model1.modelUri]: model1.content,
[model2.modelUri]: model2.content
[model1.modeluri]: model1.content,
[model2.modeluri]: model2.content
},

@@ -420,3 +443,4 @@ type: 'success'

const result = onFulfilled.getCall(0).args[0];
expect(result).to.deep.include.members([model2, model1]);
expect(result).to.be.an('array').of.length(2);
expect(result).to.deep.include.members([model1, model2]);
done();

@@ -423,0 +447,0 @@ });

@@ -1,3 +0,3 @@

/*********************************************************************************
* Copyright (c) 2021-2022 STMicroelectronics and others.
/********************************************************************************
* Copyright (c) 2021-2023 STMicroelectronics and others.
*

@@ -10,12 +10,8 @@ * This program and the accompanying materials are made available under the

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
import axios, { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
*******************************************************************************/
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
import WebSocket from 'isomorphic-ws';
import URI from 'urijs';
import {
ModelServerClientApiV1,
ModelServerError,
ServerConfiguration,
SubscriptionOptions
} from './model-server-client-api-v1';
import { ModelServerClientApiV1, ModelServerError, ServerConfiguration, SubscriptionOptions } from './model-server-client-api-v1';
import { IdentityMapper, Mapper, MessageDataMapper, Model, ModelServerMessage } from './model-server-message';

@@ -34,18 +30,18 @@ import { ModelServerPaths } from './model-server-paths';

protected openSockets: Map<string, WebSocket> = new Map();
protected _baseUrl: string;
protected _baseUrl: URI;
protected defaultFormat = 'json';
initialize(baseUrl: string): void | Promise<void> {
this._baseUrl = baseUrl;
initialize(baseUrl: URI): void | Promise<void> {
this._baseUrl = baseUrl.clone();
this.restClient = axios.create(this.getAxisConfig(baseUrl));
}
protected getAxisConfig(baseURL: string): AxiosRequestConfig | undefined {
return { baseURL };
protected getAxisConfig(baseURL: URI): AxiosRequestConfig | undefined {
return { baseURL: baseURL.toString() };
}
get(modeluri: string,): Promise<AnyObject>;
get<M>(modeluri: string, typeGuard: TypeGuard<M>,): Promise<M>;
get(modeluri: string, format: string): Promise<string>;
get<M>(modeluri: string, formatOrGuard?: FormatOrGuard<M>): Promise<AnyObject | M | string> {
get(modeluri: URI): Promise<AnyObject>;
get<M>(modeluri: URI, typeGuard: TypeGuard<M>): Promise<M>;
get(modeluri: URI, format: string): Promise<string>;
get<M>(modeluri: URI, formatOrGuard?: FormatOrGuard<M>): Promise<AnyObject | M | string> {
const format = typeof formatOrGuard === 'string' ? formatOrGuard : this.defaultFormat;

@@ -77,63 +73,51 @@ const mapper = createMapper<M>(formatOrGuard);

getModelUris(): Promise<string[]> {
return this.process(this.restClient.get(ModelServerPaths.MODEL_URIS), MessageDataMapper.asStringArray);
getModelUris(): Promise<URI[]> {
return this.process(this.restClient.get(ModelServerPaths.MODEL_URIS), MessageDataMapper.asURIArray);
}
getElementById(modeluri: string, elementid: string): Promise<AnyObject>;
getElementById<M>(modeluri: string, elementid: string, typeGuard: TypeGuard<M>): Promise<M>;
getElementById(modeluri: string, elementid: string, format: string): Promise<string>;
getElementById<M>(modeluri: string, elementid: string, formatOrGuard?: FormatOrGuard<M>): Promise<AnyObject | M | string> {
getElementById(modeluri: URI, elementid: string): Promise<AnyObject>;
getElementById<M>(modeluri: URI, elementid: string, typeGuard: TypeGuard<M>): Promise<M>;
getElementById(modeluri: URI, elementid: string, format: string): Promise<string>;
getElementById<M>(modeluri: URI, elementid: string, formatOrGuard?: FormatOrGuard<M>): Promise<AnyObject | M | string> {
const format = typeof formatOrGuard === 'string' ? formatOrGuard : this.defaultFormat;
const mapper = createMapper<M>(formatOrGuard);
return this.process(
this.restClient.get(ModelServerPaths.MODEL_ELEMENT, { params: { modeluri, elementid, format } }),
mapper
);
return this.process(this.restClient.get(ModelServerPaths.MODEL_ELEMENT, { params: { modeluri, elementid, format } }), mapper);
}
getElementByName(modeluri: string, elementname: string): Promise<AnyObject>;
getElementByName<M>(modeluri: string, elementname: string, typeGuard: TypeGuard<M>, format?: string): Promise<M>;
getElementByName(modeluri: string, elementname: string, format: string): Promise<string>;
getElementByName<M>(modeluri: string, elementname: string, formatOrGuard?: FormatOrGuard<M>): Promise<AnyObject | M | string> {
getElementByName(modeluri: URI, elementname: string): Promise<AnyObject>;
getElementByName<M>(modeluri: URI, elementname: string, typeGuard: TypeGuard<M>, format?: string): Promise<M>;
getElementByName(modeluri: URI, elementname: string, format: string): Promise<string>;
getElementByName<M>(modeluri: URI, elementname: string, formatOrGuard?: FormatOrGuard<M>): Promise<AnyObject | M | string> {
const format = typeof formatOrGuard === 'string' ? formatOrGuard : this.defaultFormat;
const mapper = createMapper<M>(formatOrGuard);
return this.process(
this.restClient.get(ModelServerPaths.MODEL_ELEMENT, { params: { modeluri, elementname, format } }),
mapper
);
return this.process(this.restClient.get(ModelServerPaths.MODEL_ELEMENT, { params: { modeluri, elementname, format } }), mapper);
}
create(modeluri: string, model: AnyObject | string): Promise<AnyObject>;
create(modeluri: string, model: AnyObject | string, format: string): Promise<string>;
create<M>(modeluri: string, model: AnyObject | string, typeGuard: TypeGuard<M>): Promise<M>;
create<M>(modeluri: string, model: AnyObject | string, formatOrGuard?: FormatOrGuard<M>): Promise<AnyObject | M | string> {
create(modeluri: URI, model: AnyObject | string): Promise<AnyObject>;
create(modeluri: URI, model: AnyObject | string, format: string): Promise<string>;
create<M>(modeluri: URI, model: AnyObject | string, typeGuard: TypeGuard<M>): Promise<M>;
create<M>(modeluri: URI, model: AnyObject | string, formatOrGuard?: FormatOrGuard<M>): Promise<AnyObject | M | string> {
const format = typeof formatOrGuard === 'string' ? formatOrGuard : this.defaultFormat;
const mapper = createMapper<M>(formatOrGuard);
return this.process(
this.restClient.post(ModelServerPaths.MODEL_CRUD, { data: model }, { params: { modeluri, format } }),
mapper
);
return this.process(this.restClient.post(ModelServerPaths.MODEL_CRUD, { data: model }, { params: { modeluri, format } }), mapper);
}
update(modeluri: string, model: AnyObject | string): Promise<AnyObject>;
update<M>(modeluri: string, model: string | string, typeGuard: TypeGuard<M>): Promise<M>;
update(modeluri: string, model: AnyObject | string, format: string): Promise<AnyObject>;
update<M>(modeluri: string, model: AnyObject | string, formatOrGuard?: FormatOrGuard<M>): Promise<AnyObject | M | string> {
update(modeluri: URI, model: AnyObject | string): Promise<AnyObject>;
update<M>(modeluri: URI, model: string | string, typeGuard: TypeGuard<M>): Promise<M>;
update(modeluri: URI, model: AnyObject | string, format: string): Promise<AnyObject>;
update<M>(modeluri: URI, model: AnyObject | string, formatOrGuard?: FormatOrGuard<M>): Promise<AnyObject | M | string> {
const format = typeof formatOrGuard === 'string' ? formatOrGuard : this.defaultFormat;
const mapper = createMapper<M>(formatOrGuard);
return this.process(
this.restClient.patch(ModelServerPaths.MODEL_CRUD, { data: model }, { params: { modeluri, format } }),
mapper
);
return this.process(this.restClient.patch(ModelServerPaths.MODEL_CRUD, { data: model }, { params: { modeluri, format } }), mapper);
}
delete(modeluri: string): Promise<boolean> {
delete(modeluri: URI): Promise<boolean> {
return this.process(this.restClient.delete(ModelServerPaths.MODEL_CRUD, { params: { modeluri } }), MessageDataMapper.isSuccess);
}
close(modeluri: string): Promise<boolean> {
close(modeluri: URI): Promise<boolean> {
return this.process(this.restClient.post(ModelServerPaths.CLOSE, undefined, { params: { modeluri } }), MessageDataMapper.isSuccess);
}
save(modeluri: string): Promise<boolean> {
save(modeluri: URI): Promise<boolean> {
return this.process(this.restClient.get(ModelServerPaths.SAVE, { params: { modeluri } }), MessageDataMapper.isSuccess);

@@ -146,3 +130,3 @@ }

validate(modeluri: string): Promise<Diagnostic> {
validate(modeluri: URI): Promise<Diagnostic> {
return this.process(this.restClient.get(ModelServerPaths.VALIDATION, { params: { modeluri } }), response =>

@@ -153,3 +137,3 @@ MessageDataMapper.as(response, Diagnostic.is)

getValidationConstraints(modeluri: string): Promise<string> {
getValidationConstraints(modeluri: URI): Promise<string> {
return this.process(

@@ -161,3 +145,3 @@ this.restClient.get(ModelServerPaths.VALIDATION_CONSTRAINTS, { params: { modeluri } }),

getTypeSchema(modeluri: string): Promise<string> {
getTypeSchema(modeluri: URI): Promise<string> {
return this.process(this.restClient.get(ModelServerPaths.TYPE_SCHEMA, { params: { modeluri } }), MessageDataMapper.asString);

@@ -171,7 +155,7 @@ }

configureServer(configuration: ServerConfiguration): Promise<boolean> {
let { workspaceRoot, uiSchemaFolder } = configuration;
workspaceRoot = workspaceRoot.replace('file://', '');
uiSchemaFolder = uiSchemaFolder?.replace('file://', '');
return this.process(
this.restClient.put(ModelServerPaths.SERVER_CONFIGURE, { workspaceRoot, uiSchemaFolder }),
this.restClient.put(ModelServerPaths.SERVER_CONFIGURE, {
workspaceRoot: configuration.workspaceRoot.toString(),
uiSchemaFolder: configuration.uiSchemaFolder?.toString()
}),
MessageDataMapper.isSuccess

@@ -185,3 +169,3 @@ );

edit(modeluri: string, command: ModelServerCommand): Promise<boolean> {
edit(modeluri: URI, command: ModelServerCommand): Promise<boolean> {
return this.process(

@@ -193,12 +177,12 @@ this.restClient.patch(ModelServerPaths.EDIT, { data: command }, { params: { modeluri, format: this.defaultFormat } }),

undo(modeluri: string): Promise<string> {
undo(modeluri: URI): Promise<string> {
return this.process(this.restClient.get(ModelServerPaths.UNDO, { params: { modeluri } }), MessageDataMapper.asString);
}
redo(modeluri: string): Promise<string> {
redo(modeluri: URI): Promise<string> {
return this.process(this.restClient.get(ModelServerPaths.REDO, { params: { modeluri } }), MessageDataMapper.asString);
}
send(modelUri: string, message: ModelServerMessage): boolean {
const openSocket = this.openSockets.get(modelUri);
send(modeluri: URI, message: ModelServerMessage): boolean {
const openSocket = this.openSockets.get(modeluri.toString());
if (openSocket) {

@@ -211,9 +195,9 @@ openSocket.send(JSON.stringify(message));

subscribe(modeluri: string, options: SubscriptionOptions = {}): void {
subscribe(modeluri: URI, options: SubscriptionOptions = {}): void {
if (!options.listener) {
const errorMsg = `${modeluri} : Cannot subscribe. No listener is present!'`;
const errorMsg = `${modeluri.toString()} : Cannot subscribe. No listener is present!'`;
throw new Error(errorMsg);
}
if (this.isSocketOpen(modeluri)) {
const errorMsg = `${modeluri} : Cannot open new socket, already subscribed!'`;
const errorMsg = `${modeluri.toString()} : Cannot open new socket, already subscribed!'`;
console.warn(errorMsg);

@@ -228,7 +212,7 @@ if (options.errorWhenUnsuccessful) {

unsubscribe(modeluri: string): boolean {
const openSocket = this.openSockets.get(modeluri);
unsubscribe(modeluri: URI): boolean {
const openSocket = this.openSockets.get(modeluri.toString());
if (openSocket) {
openSocket.close();
this.openSockets.delete(modeluri);
this.openSockets.delete(modeluri.toString());
return true;

@@ -239,30 +223,30 @@ }

protected createSubscriptionPath(modeluri: string, options: SubscriptionOptions): string {
protected createSubscriptionPath(modeluri: URI, options: SubscriptionOptions): URI {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { listener, ...paramOptions } = options;
const queryParams = new URLSearchParams();
queryParams.append('modeluri', modeluri);
if (!options.format) {
options.format = this.defaultFormat;
}
Object.entries(paramOptions).forEach(entry => queryParams.append(entry[0], entry[1]));
queryParams.delete('errorWhenUnsuccessful');
return `${this._baseUrl}${ModelServerPaths.SUBSCRIPTION}?${queryParams.toString()}`.replace(/^(http|https):\/\//i, 'ws://');
const subscriptionUri = this._baseUrl.clone();
subscriptionUri.protocol('ws');
subscriptionUri.segment(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;
}
protected doSubscribe(listener: SubscriptionListener, modelUri: string, path: string): void {
const socket = new WebSocket(path.trim());
socket.onopen = event => listener.onOpen(modelUri, event);
protected doSubscribe(listener: SubscriptionListener, modeluri: URI, path: URI): void {
const socket = new WebSocket(path.toString() /* .trim() */);
socket.onopen = event => listener.onOpen(modeluri, event);
socket.onclose = event => {
listener.onClose(modelUri, event);
this.openSockets.delete(modelUri);
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, socket);
socket.onerror = event => listener.onError(modeluri, event);
socket.onmessage = event => listener.onMessage(modeluri, event);
this.openSockets.set(modeluri.toString(), socket);
}
protected isSocketOpen(modelUri: string): boolean {
return this.openSockets.get(modelUri) !== undefined;
protected isSocketOpen(modeluri: URI): boolean {
return this.openSockets.get(modeluri.toString()) !== undefined;
}

@@ -297,3 +281,3 @@

} catch (error) {
if (isAxiosError(error)) {
if (axios.isAxiosError(error)) {
const message = error.response?.data ? error.response.data : error.message;

@@ -308,6 +292,2 @@ throw new ModelServerError(message, error.code);

function isAxiosError(error: any): error is AxiosError {
return error !== undefined && error instanceof Error && 'isAxiosError' in error && error['isAxiosError'];
}
/**

@@ -333,13 +313,12 @@ * Helper type for method overloads where on parameter could either be

return msg => MessageDataMapper.asObject(msg);
}
function mapModel<M>(model: Model, guard?: TypeGuard<M>, toString = false): Model<AnyObject | M | string> {
const { modelUri, content } = model;
const { modeluri, content } = model;
if (guard) {
return { modelUri, content: asType(content, guard) };
return { modeluri, content: asType(content, guard) };
} else if (toString) {
return { modelUri, content: asString(content) };
return { modeluri, content: asString(content) };
}
return { modelUri, content: asObject(content) };
return { modeluri, content: asObject(content) };
}

@@ -10,7 +10,8 @@ /********************************************************************************

* SPDX-License-Identifier: EPL-2.0 OR MIT
********************************************************************************/
*******************************************************************************/
import * as jsonpatch from 'fast-json-patch';
import { deepClone } from 'fast-json-patch';
import { deepClone, Operation } from 'fast-json-patch';
import URI from 'urijs';
import { ModelUpdateResult } from './model-server-client-api-v2';
import { ModelPatch, ModelUpdateResult } from './model-server-client-api-v2';
import { ModelServerElement } from './model/base-model';

@@ -83,3 +84,3 @@ import { Operations } from './utils/patch-utils';

/** The uri of the model. */
modelUri: string;
modeluri: string;
/** The model content. */

@@ -96,4 +97,8 @@ content: C;

export function is(object: unknown): object is Model {
return Type.AnyObject.is(object) && Type.isString(object, 'modelUri') && Type.isObject(object, 'content');
return Type.AnyObject.is(object) && Type.isString(object, 'modeluri') && Type.isObject(object, 'content');
}
export function toString(model: Model): string {
return JSON.stringify(model, undefined, 2);
}
}

@@ -160,2 +165,12 @@

/**
* Maps the {@link ModelServerMessage.data} property of the given message to a URI[].
* @param message The message to map.
* @returns The `data` property as `URI[]`.
* @throws {@link Error} if the 'data' property is not an URI array.
*/
export function asURIArray(message: ModelServerMessage): URI[] {
return Type.asURIArray(message.data);
}
/**
* Maps the {@link ModelServerMessage.data} property of the given message to an {@link AnyObject}.

@@ -203,13 +218,18 @@ * @param message The message to map.

export function patchModel(message: ModelServerMessage): ModelUpdateResult {
if (isSuccess(message)){
if (isSuccess(message)) {
const data = message.data as any;
const patch = data ? data.patch : undefined;
if (patch && Operations.isPatch(patch)) {
const allPatches = data ? data.allPatches : undefined;
if (patch || allPatches) {
return {
success: isSuccess(message),
patch,
patchModel: (oldModel, copy) => {
patchModel: (oldModel, copy, modeluri) => {
const modelToPatch = copy ? deepClone(oldModel) : oldModel;
return jsonpatch.applyPatch(modelToPatch, patch).newDocument as ModelServerElement;
}
const patchToApply = modeluri ? getPatch(allPatches, modeluri) : Operations.isPatch(patch) ? patch : undefined;
return patchToApply
? (jsonpatch.applyPatch(modelToPatch, patchToApply).newDocument as ModelServerElement)
: modelToPatch;
},
allPatches
};

@@ -220,5 +240,9 @@ } else {

} else {
return {success: false };
return { success: false };
}
}
function getPatch(patches: ModelPatch[], modeluri: URI): Operation[] | undefined {
return patches.find(mp => mp.modelUri === modeluri.toString())?.patch;
}
}

@@ -1,2 +0,2 @@

/*********************************************************************************
/********************************************************************************
* Copyright (c) 2021-2022 STMicroelectronics and others.

@@ -10,10 +10,11 @@ *

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
import { Operation } from 'fast-json-patch';
import * as URI from 'urijs';
import { MessageType, ModelServerObjectV2 } from '.';
import { ModelServerMessage } from './model-server-message';
import { CommandExecutionResult } from './model/command-model';
import { Diagnostic } from './model/diagnostic';
import { AnyObject, isString } from './utils/type-util';
import { ModelServerMessage } from './model-server-message';
import { AnyObject, isObject, isString } from './utils/type-util';

@@ -25,3 +26,3 @@ /**

export interface ModelServerNotification {
modelUri: string;
modeluri: URI;
type: string;

@@ -32,3 +33,3 @@ }

export function is(object?: unknown): object is ModelServerNotification {
return AnyObject.is(object) && isString(object, 'modelUri') && isString(object, 'type');
return AnyObject.is(object) && isObject(object, 'modeluri') && isString(object, 'type');
}

@@ -35,0 +36,0 @@ }

@@ -10,3 +10,3 @@ /********************************************************************************

* SPDX-License-Identifier: EPL-2.0 OR MIT
********************************************************************************/
*******************************************************************************/
/**

@@ -16,3 +16,2 @@ * Utility collection of all the available endpoint paths of a (default) modelserver.

export namespace ModelServerPaths {
/** Endpoint to retrieve the uris of all available models in the workspace */

@@ -57,3 +56,2 @@ export const MODEL_URIS = 'modeluris';

export const VALIDATION_CONSTRAINTS = 'validation/constraints';
}

@@ -10,3 +10,3 @@ /********************************************************************************

* SPDX-License-Identifier: EPL-2.0 OR MIT
********************************************************************************/
*******************************************************************************/
import { AnyObject, isString } from '../utils/type-util';

@@ -13,0 +13,0 @@

@@ -10,3 +10,3 @@ /********************************************************************************

* SPDX-License-Identifier: EPL-2.0 OR MIT
********************************************************************************/
*******************************************************************************/
import { ModelServerObject, ModelServerReferenceDescription } from './base-model';

@@ -13,0 +13,0 @@

@@ -10,8 +10,4 @@ /********************************************************************************

* SPDX-License-Identifier: EPL-2.0 OR MIT
********************************************************************************/
import {
isModelServerObjectArray,
isModelServerReferenceDescriptionArray,
isNumberArray
} from '../utils/model-server-utils';
*******************************************************************************/
import { isModelServerObjectArray, isModelServerReferenceDescriptionArray, isNumberArray } from '../utils/model-server-utils';
import { DataValueType, ModelServerObject, ModelServerReferenceDescription } from './base-model';

@@ -141,3 +137,3 @@ import { ChangeDescription } from './change-model';

public feature: string,
changedValues: DataValueType[] | ModelServerReferenceDescription[]
changedValues: DataValueType[] | ModelServerReferenceDescription[] | ModelServerObject[]
) {

@@ -147,2 +143,4 @@ super(SetCommand.TYPE);

this.objectValues = changedValues;
} else if (isModelServerObjectArray(changedValues)) {
this.objectsToAdd = changedValues;
} else {

@@ -173,3 +171,3 @@ this.dataValues = changedValues;

constructor(public type: string, public source: ModelServerCommand, public changeDescription: ChangeDescription) { }
constructor(public type: string, public source: ModelServerCommand, public changeDescription: ChangeDescription) {}

@@ -176,0 +174,0 @@ static is(object?: unknown): object is CommandExecutionResult {

@@ -1,2 +0,2 @@

/*********************************************************************************
/********************************************************************************
* Copyright (c) 2022 STMicroelectronics and others.

@@ -10,8 +10,8 @@ *

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
import { expect } from 'chai';
import { Diagnostic, ERROR, OK, WARNING } from './diagnostic';
describe('tests for Diagnostic', () => {
it('ok', () => {

@@ -43,3 +43,3 @@ const ok = Diagnostic.ok();

const warning = { ...diag(WARNING, 'Not so bad.'), source: 'a' };
const ok = { ...diag(OK, 'It\'s okay.'), source: 'b' };
const ok = { ...diag(OK, "It's okay."), source: 'b' };
const error = { ...diag(ERROR, 'Pretty bad.'), source: 'c' };

@@ -67,3 +67,3 @@ const merged = Diagnostic.merge(warning, ok, error);

const warning = { ...diag(WARNING, 'Not so bad.'), source: 'a' };
const ok = { ...diag(OK, 'It\'s okay.'), source: 'b' };
const ok = { ...diag(OK, "It's okay."), source: 'b' };
const error = { ...diag(ERROR, 'Pretty bad.'), source: 'c' };

@@ -70,0 +70,0 @@ const worst = Diagnostic.worstOf([warning, ok, error]);

@@ -10,6 +10,3 @@ /********************************************************************************

* SPDX-License-Identifier: EPL-2.0 OR MIT
*
* Contributors:
* Vincent HEMERY (CS GROUP - France) - initial API and implementation
********************************************************************************/
*******************************************************************************/
import { AnyObject, isArray, isNumber, isString } from '../utils/type-util';

@@ -176,5 +173,3 @@

// Recompute IDs of the diagnostics because they are now in
// a new tree structure and their paths have changed.
return recomputeIDs({
return {
severity: max.severity,

@@ -187,3 +182,3 @@ message: `Diagnosis of ${nonOK.length} problems.`,

id: '/'
});
};
}

@@ -216,14 +211,2 @@

}
/**
* Assign IDs of the diagnostics in a tree according to the EMF
* path-structured URI fragment algorithm.
*/
function recomputeIDs(diagnostic: Diagnostic, base = '/'): Diagnostic {
diagnostic.id = base;
diagnostic.children?.forEach((child, i) => recomputeIDs(child, `${base}/@children.${i}`));
return diagnostic;
}
}

@@ -1,2 +0,2 @@

/*********************************************************************************
/********************************************************************************
* Copyright (c) 2021-2022 STMicroelectronics and others.

@@ -10,5 +10,6 @@ *

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
import { applyPatch, deepClone } from 'fast-json-patch';
import WebSocket from 'isomorphic-ws';
import URI from 'urijs';

@@ -37,6 +38,6 @@ import { Operations } from '.';

export interface SubscriptionListener {
onOpen(modelUri: string, event: WebSocket.Event): void;
onClose(modelUri: string, event: WebSocket.CloseEvent): void;
onError(modelUri: string, event: WebSocket.ErrorEvent): void;
onMessage(modelUri: string, event: WebSocket.MessageEvent): void;
onOpen(modeluri: URI, event: WebSocket.Event): void;
onClose(modeluri: URI, event: WebSocket.CloseEvent): void;
onError(modeluri: URI, event: WebSocket.ErrorEvent): void;
onMessage(modeluri: URI, event: WebSocket.MessageEvent): void;
}

@@ -110,17 +111,17 @@

export class NotificationSubscriptionListener implements SubscriptionListener {
constructor(protected notificationListener: ModelServerNotificationListener = {}) { }
constructor(protected notificationListener: ModelServerNotificationListener = {}) {}
onOpen(modelUri: string, _event: WebSocket.Event): void {
this.notificationListener.onOpen?.({ modelUri, type: MessageType.open });
onOpen(modeluri: URI, _event: WebSocket.Event): void {
this.notificationListener.onOpen?.({ modeluri, type: MessageType.open });
}
onClose(modelUri: string, event: WebSocket.CloseEvent): void {
this.notificationListener.onClose?.({ modelUri, code: event.code, reason: event.reason, type: MessageType.close });
onClose(modeluri: URI, event: WebSocket.CloseEvent): void {
this.notificationListener.onClose?.({ modeluri, code: event.code, reason: event.reason, type: MessageType.close });
}
onError(modelUri: string, event: WebSocket.ErrorEvent): void {
this.notificationListener.onError?.({ modelUri, error: event.error, type: MessageType.error });
onError(modeluri: URI, event: WebSocket.ErrorEvent): void {
this.notificationListener.onError?.({ modeluri, error: event.error, type: MessageType.error });
}
onMessage(modelUri: string, event: WebSocket.MessageEvent): void {
onMessage(modeluri: URI, event: WebSocket.MessageEvent): void {
const message = JSON.parse(event.data.toString());

@@ -131,3 +132,3 @@ if (ModelServerMessage.is(message)) {

case MessageType.dirtyState: {
this.notificationListener.onDirtyStateChanged?.({ modelUri, isDirty: MessageDataMapper.asBoolean(message), type });
this.notificationListener.onDirtyStateChanged?.({ modeluri, isDirty: MessageDataMapper.asBoolean(message), type });
break;

@@ -137,7 +138,7 @@ }

case MessageType.success: {
this.notificationListener.onSuccess?.({ modelUri, type });
this.notificationListener.onSuccess?.({ modeluri, type });
break;
}
case MessageType.error: {
this.notificationListener.onError?.({ modelUri, error: MessageDataMapper.asString(message), type });
this.notificationListener.onError?.({ modeluri, error: MessageDataMapper.asString(message), type });
break;

@@ -147,3 +148,3 @@ }

this.notificationListener.onIncrementalUpdate?.({
modelUri,
modeluri,
result: MessageDataMapper.as(message, CommandExecutionResult.is),

@@ -155,11 +156,11 @@ type

case MessageType.fullUpdate: {
this.notificationListener.onFullUpdate?.({ modelUri, model: MessageDataMapper.asObject(message), type });
this.notificationListener.onFullUpdate?.({ modeluri, model: MessageDataMapper.asObject(message), type });
break;
}
case MessageType.validationResult: {
this.notificationListener.onValidation?.({ modelUri, diagnostic: MessageDataMapper.as(message, Diagnostic.is), type });
this.notificationListener.onValidation?.({ modeluri, diagnostic: MessageDataMapper.as(message, Diagnostic.is), type });
break;
}
default: {
this.notificationListener.onUnknown?.({ ...message, modelUri });
this.notificationListener.onUnknown?.({ ...message, modeluri });
}

@@ -183,3 +184,3 @@ }

onMessage(modelUri: string, event: WebSocket.MessageEvent): void {
onMessage(modeluri: URI, event: WebSocket.MessageEvent): void {
const message = JSON.parse(event.data.toString());

@@ -193,3 +194,3 @@ if (ModelServerMessage.is(message)) {

type: message.type,
modelUri,
modeluri,
patch,

@@ -204,3 +205,3 @@ patchModel: (model, copy) => {

default: {
super.onMessage(modelUri, event);
super.onMessage(modeluri, event);
}

@@ -207,0 +208,0 @@ }

@@ -10,3 +10,3 @@ /********************************************************************************

* SPDX-License-Identifier: EPL-2.0 OR MIT
********************************************************************************/
*******************************************************************************/
import { DataValueType, ModelServerObject, ModelServerReferenceDescription } from '../model/base-model';

@@ -23,5 +23,5 @@

export function isModelServerReferenceDescriptionArray(
array: Array<DataValueType | ModelServerReferenceDescription>
array: Array<DataValueType | ModelServerReferenceDescription | ModelServerObject>
): array is ModelServerReferenceDescription[] {
return array.every(ModelServerReferenceDescription.is);
}

@@ -1,2 +0,2 @@

/*********************************************************************************
/********************************************************************************
* Copyright (c) 2022 STMicroelectronics and others.

@@ -10,4 +10,5 @@ *

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
import { AddOperation, Operation, RemoveOperation, ReplaceOperation } from 'fast-json-patch';
import URI from 'urijs';

@@ -45,3 +46,3 @@ import { ModelServerObjectV2, ModelServerReferenceDescriptionV2 } from '../model/base-model';

*/
export function replace<T>(modeluri: string, object: ModelServerObjectV2, feature: string, value: T): ReplaceOperation<T> {
export function replace<T>(modeluri: URI, object: ModelServerObjectV2, feature: string, value: T): ReplaceOperation<T> {
return {

@@ -63,3 +64,9 @@ op: REPLACE,

*/
export function create(modeluri: string, parent: ModelServerObjectV2, feature: string, $type: string, attributes?: AnyObject): AddOperation<TypeDefinition> {
export function create(
modeluri: URI,
parent: ModelServerObjectV2,
feature: string,
$type: string,
attributes?: AnyObject
): AddOperation<TypeDefinition> {
return {

@@ -83,4 +90,8 @@ op: ADD,

*/
export function add(modeluri: string, parent: ModelServerObjectV2, feature: string,
value: ModelServerObjectV2 | ModelServerReferenceDescriptionV2): AddOperation<ModelServerObjectV2> {
export function add(
modeluri: URI,
parent: ModelServerObjectV2,
feature: string,
value: ModelServerObjectV2 | ModelServerReferenceDescriptionV2
): AddOperation<ModelServerObjectV2> {
return {

@@ -102,3 +113,3 @@ op: ADD,

*/
export function deleteElement(modeluri: string, object: ModelServerObjectV2): RemoveOperation {
export function deleteElement(modeluri: URI, object: ModelServerObjectV2): RemoveOperation {
return {

@@ -117,3 +128,3 @@ op: REMOVE,

*/
export function removeValueAt(modeluri: string, object: ModelServerObjectV2, feature: string, index: number): RemoveOperation {
export function removeValueAt(modeluri: URI, object: ModelServerObjectV2, feature: string, index: number): RemoveOperation {
return {

@@ -132,3 +143,3 @@ op: REMOVE,

*/
export function removeValue(modeluri: string, object: ModelServerObjectV2, feature: string, value: AnyObject): RemoveOperation | undefined {
export function removeValue(modeluri: URI, object: ModelServerObjectV2, feature: string, value: AnyObject): RemoveOperation | undefined {
const index = findIndex(object, feature, value);

@@ -146,3 +157,3 @@ if (index >= 0) {

*/
export function removeObject(modeluri: string, objectToRemove: ModelServerObjectV2): RemoveOperation {
export function removeObject(modeluri: URI, objectToRemove: ModelServerObjectV2): RemoveOperation {
return {

@@ -164,5 +175,5 @@ op: REMOVE,

*/
function getObjectPath(modeluri: string, object: ModelServerObjectV2 | ModelServerReferenceDescriptionV2): string {
function getObjectPath(modeluri: URI, object: ModelServerObjectV2 | ModelServerReferenceDescriptionV2): string {
const id = ModelServerReferenceDescriptionV2.is(object) ? object.$ref : object.$id;
return `${modeluri}#${id}`;
return modeluri.clone().fragment(id).toString();
}

@@ -182,3 +193,3 @@

*/
function getPropertyPath(modeluri: string, object: ModelServerObjectV2, feature: string, index?: number): string {
function getPropertyPath(modeluri: URI, object: ModelServerObjectV2, feature: string, index?: number): string {
const indexSuffix = index === undefined ? '' : `/${index}`;

@@ -200,3 +211,2 @@ return `${getObjectPath(modeluri, object)}/${feature}${indexSuffix}`;

export namespace Operations {
/**

@@ -203,0 +213,0 @@ * Tests is the given object is a Json Patch {@link Operation}

@@ -1,2 +0,2 @@

/*********************************************************************************
/********************************************************************************
* Copyright (c) 2022 STMicroelectronics and others.

@@ -10,11 +10,17 @@ *

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
import { expect } from 'chai';
import { encode } from './type-util';
describe('tests for type-util', () => {
describe('encode', () => {
const emptyArray: any[] = [];
const tags = ['high-prio', 'red'];
// eslint-disable-next-line no-null/no-null
const nada = null; // JSON uses null
const emptyObj = {};
describe('encode', () => {
it('JSON v1 as JSON v1', () => {
const object = { eClass: 'Foo', name: 'test', nested: [{ eClass: 'Nested', name: 'inner', tags: ['high-prio', 'red']}]};
const object = { eClass: 'Foo', name: 'test', nested: [{ eClass: 'Nested', name: 'inner', tags, emptyArray, nada, emptyObj }] };
const encoded = encode('json')(object);

@@ -25,4 +31,4 @@ expect(encoded).to.be.equal(encoded);

it('JSON v1 as JSON v2', () => {
const object = { eClass: 'Foo', name: 'test', nested: [{ eClass: 'Nested', name: 'inner', tags: ['high-prio', 'red']}]};
const expected = { $type: 'Foo', name: 'test', nested: [{ $type: 'Nested', name: 'inner', tags: ['high-prio', 'red']}]};
const object = { eClass: 'Foo', name: 'test', nested: [{ eClass: 'Nested', name: 'inner', tags, emptyArray, nada, emptyObj }] };
const expected = { $type: 'Foo', name: 'test', nested: [{ $type: 'Nested', name: 'inner', tags, emptyArray, nada, emptyObj }] };
const encoded = encode('json-v2')(object);

@@ -33,4 +39,8 @@ expect(encoded).to.be.eql(expected);

it('JSON v2 as JSON v1', () => {
const object = { $type: 'Foo', name: 'test', nested: [{ $type: 'Nested', name: 'inner', tags: ['high-prio', 'red']}]};
const expected = { eClass: 'Foo', name: 'test', nested: [{ eClass: 'Nested', name: 'inner', tags: ['high-prio', 'red']}]};
const object = { $type: 'Foo', name: 'test', nested: [{ $type: 'Nested', name: 'inner', tags, emptyArray, nada, emptyObj }] };
const expected = {
eClass: 'Foo',
name: 'test',
nested: [{ eClass: 'Nested', name: 'inner', tags, emptyArray, nada, emptyObj }]
};
const encoded = encode('json')(object);

@@ -41,3 +51,3 @@ expect(encoded).to.be.eql(expected);

it('JSON v2 as JSON v2', () => {
const object = { $type: 'Foo', name: 'test', nested: [{ $type: 'Nested', name: 'inner', tags: ['high-prio', 'red']}]};
const object = { $type: 'Foo', name: 'test', nested: [{ $type: 'Nested', name: 'inner', tags, emptyArray, nada, emptyObj }] };
const encoded = encode('json-v2')(object);

@@ -49,4 +59,14 @@ expect(encoded).to.be.equal(encoded);

describe('encode string', () => {
const emptyArray: any[] = [];
const tags = ['high-prio', 'red'];
// eslint-disable-next-line no-null/no-null
const nada = null; // JSON uses null
const emptyObj = {};
it('JSON v1 as JSON v1', () => {
const object = JSON.stringify({ eClass: 'Foo', name: 'test', nested: { eClass: 'Nested', name: 'inner', tags: ['high-prio', 'red']}});
const object = JSON.stringify({
eClass: 'Foo',
name: 'test',
nested: { eClass: 'Nested', name: 'inner', tags, emptyArray, nada, emptyObj }
});
const encoded = encode('json')(object);

@@ -57,4 +77,8 @@ expect(encoded).to.be.equal(encoded);

it('JSON v1 as JSON v2', () => {
const object = JSON.stringify({ eClass: 'Foo', name: 'test', nested: { eClass: 'Nested', name: 'inner', tags: ['high-prio', 'red']}});
const expected = { $type: 'Foo', name: 'test', nested: { $type: 'Nested', name: 'inner', tags: ['high-prio', 'red']}};
const object = JSON.stringify({
eClass: 'Foo',
name: 'test',
nested: { eClass: 'Nested', name: 'inner', tags, emptyArray, nada, emptyObj }
});
const expected = { $type: 'Foo', name: 'test', nested: { $type: 'Nested', name: 'inner', tags, emptyArray, nada, emptyObj } };
const encoded = encode('json-v2')(object);

@@ -66,4 +90,8 @@ expect(encoded).to.be.a('string');

it('JSON v2 as JSON v1', () => {
const object = JSON.stringify({ $type: 'Foo', name: 'test', nested: { $type: 'Nested', name: 'inner', tags: ['high-prio', 'red']}});
const expected = { eClass: 'Foo', name: 'test', nested: { eClass: 'Nested', name: 'inner', tags: ['high-prio', 'red']}};
const object = JSON.stringify({
$type: 'Foo',
name: 'test',
nested: { $type: 'Nested', name: 'inner', tags, emptyArray, nada, emptyObj }
});
const expected = { eClass: 'Foo', name: 'test', nested: { eClass: 'Nested', name: 'inner', tags, emptyArray, nada, emptyObj } };
const encoded = encode('json')(object);

@@ -75,3 +103,7 @@ expect(encoded).to.be.a('string');

it('JSON v2 as JSON v2', () => {
const object = JSON.stringify({ $type: 'Foo', name: 'test', nested: { $type: 'Nested', name: 'inner', tags: ['high-prio', 'red']}});
const object = JSON.stringify({
$type: 'Foo',
name: 'test',
nested: { $type: 'Nested', name: 'inner', tags, emptyArray, nada, emptyObj }
});
const encoded = encode('json-v2')(object);

@@ -78,0 +110,0 @@ expect(encoded).to.be.equal(encoded);

@@ -1,2 +0,2 @@

/*********************************************************************************
/********************************************************************************
* Copyright (c) 2021-2022 STMicroelectronics and others.

@@ -10,3 +10,6 @@ *

* SPDX-License-Identifier: EPL-2.0 OR MIT
*********************************************************************************/
*******************************************************************************/
import URI from 'urijs';
import { Format, FORMAT_JSON_V1, FORMAT_JSON_V2, FORMAT_XMI, JsonFormat } from '../model-server-client-api-v2';

@@ -100,2 +103,15 @@ import { Model } from '../model-server-message';

}
if (Model.is(object)) {
return Model.toString(object);
}
if (Array.isArray(object) && object.every(Model.is)) {
return object.map(e => Model.toString(e)).toString();
}
if (isURI(object)) {
return asURI(object).toString();
}
if (Array.isArray(object) && object.every(isURI)) {
const uriArray = object.map(e => asURI(e).toString());
return JSON.stringify(uriArray, undefined, 2);
}
return JSON.stringify(object, undefined, 2);

@@ -146,3 +162,3 @@ }

if (AnyObject.is(object)) {
return Object.entries(object).map(entry => ({ modelUri: entry[0], content: entry[1] }));
return Object.entries(object).map(entry => ({ modeluri: entry[0], content: entry[1] }));
}

@@ -153,2 +169,39 @@

/**
* Validates whether the given object is a (deferred) instance of an URI object.
* @param object The object that should be validated
* @returns `true` if the object is an instance of URI
*/
export function isURI(object: unknown): object is URI {
return AnyObject.is(object) && isObject(object, '_parts') && isBoolean(object, '_deferred_build') && isString(object, '_string');
}
/**
* Maps the given object to an `URI` object.
* @param obj The object to map
* @returns The object as `URI`
*/
export function asURI(obj: unknown): URI {
if (typeof obj === 'string') {
return new URI(obj);
}
// reconstruct if URI object was deferred
if (isURI(obj)) {
return new URI((obj as any)._parts);
}
throw new Error('Cannot map to URI. Given parameter is not an URI!');
}
/**
* Maps the given object to a `string` array.
* @param object The object to map
* @returns The object as `URI` array
* @throws {@link Error} if the given object is not an array
*/
export function asURIArray(object: unknown): URI[] {
if (Array.isArray(object)) {
return object.map(asURI);
}
throw new Error('Cannot map to URI[]. Given parameter is not an array!');
}
/** Protocol of a message encoder. */

@@ -231,3 +284,3 @@ export type Encoder<T = unknown> = (object: string | AnyObject) => T | string;

function findProperty(object: any, name: string, visited = new Set()): boolean {
return traverse(object, (target, props) => props.includes(name) ? true : undefined);
return traverse(object, (target, props) => (props.includes(name) ? true : undefined));
}

@@ -290,2 +343,8 @@

function traverse<T>(object: any, fn: (target: any, props: string[]) => T | undefined, visited = new Set()): boolean {
// Only traverse into objects. Null, undefined, strings, numbers, booleans are primitive values in JSON and functions don't exist.
// eslint-disable-next-line no-null/no-null
if (typeof object !== 'object' || object === null) {
// JSON uses null
return false;
}
if (visited.has(object)) {

@@ -292,0 +351,0 @@ return false;

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc