@eclipse-emfcloud/modelserver-node
Advanced tools
Comparing version 0.2.0-next.55b519b.29 to 0.2.0-next.781fe49.31
@@ -32,2 +32,3 @@ "use strict"; | ||
const trigger_provider_registry_1 = require("../trigger-provider-registry"); | ||
const promise_utils_1 = require("./promise-utils"); | ||
const web_socket_utils_1 = require("./web-socket-utils"); | ||
@@ -233,2 +234,3 @@ exports.UpstreamConnectionConfig = Symbol('UpstreamConnectionConfig'); | ||
this.rollback = this.rollback.bind(this); | ||
this.uuid = promise_utils_1.CompletablePromise.newPromise(); | ||
} | ||
@@ -242,3 +244,3 @@ /** | ||
open(closeCallback) { | ||
const result = new Promise((resolve, reject) => { | ||
const result = new Promise((resolveTransaction, reject) => { | ||
this.closeCallback = closeCallback; | ||
@@ -254,3 +256,8 @@ const wsURI = new URL(this.transactionURI); | ||
this.socket = socket; | ||
resolve(this); | ||
web_socket_utils_1.WebSocketMessageAcceptor.promise(this.socket, msg => typeof msg.data === 'string', modelserver_client_1.MessageDataMapper.asString) | ||
.then(uuid_ => { | ||
this.uuid.resolve(uuid_); | ||
resolveTransaction(this); | ||
}) | ||
.catch(this.uuid.reject); | ||
}; | ||
@@ -268,2 +275,10 @@ socket.onmessage = event => { | ||
} | ||
/** | ||
* Obtain the UUID of this transaction, when it has been received from the upstream server. | ||
* | ||
* @returns the UUID, when it is available | ||
*/ | ||
getUUID() { | ||
return this.uuid; | ||
} | ||
// Doc inherited from `Executor` interface | ||
@@ -323,6 +338,8 @@ async applyPatch(patch) { | ||
} | ||
sendExecuteMessage(body) { | ||
async sendExecuteMessage(body) { | ||
if (!this.socket) { | ||
return Promise.reject('Socket is closed.'); | ||
} | ||
// Make sure that we have first processed the transaction opening exchange | ||
await this.getUUID(); | ||
const { aggregatedUpdateResult: current } = this.peekNestedContext(); | ||
@@ -329,0 +346,0 @@ const result = web_socket_utils_1.WebSocketMessageAcceptor.promise(this.socket, message => true, // Need to accept and merge failed updates as well as successful |
@@ -11,4 +11,6 @@ /******************************************************************************** | ||
*******************************************************************************/ | ||
import { Diagnostic } from '@eclipse-emfcloud/modelserver-client'; | ||
/// <reference types="node" /> | ||
import { Diagnostic, ModelServerMessage } from '@eclipse-emfcloud/modelserver-client'; | ||
import { Logger } from '@eclipse-emfcloud/modelserver-plugin-ext'; | ||
import { EventEmitter } from 'events'; | ||
import * as WebSocket from 'ws'; | ||
@@ -20,3 +22,3 @@ import { UpstreamConnectionConfig } from '../client/model-server-client'; | ||
*/ | ||
interface SubscriptionQuery { | ||
export interface SubscriptionQuery { | ||
/** The model URI to subscribe to. */ | ||
@@ -34,2 +36,3 @@ modeluri: string; | ||
}; | ||
export declare type EventType = 'subscribed' | 'unsubscribed'; | ||
export declare class SubscriptionManager { | ||
@@ -40,8 +43,38 @@ protected readonly logger: Logger; | ||
protected readonly subscriptions: Map<Client, JSONSocket>; | ||
addSubscription(client: WebSocket, endpoint: string, params: SubscriptionQuery): void; | ||
protected readonly eventEmitter: EventEmitter; | ||
addSubscription(client: WebSocket, endpoint: string, params: SubscriptionQuery): JSONSocket; | ||
protected fireEvent(eventType: EventType, client: JSONSocket, params: SubscriptionQuery): void; | ||
addSubscribedListener(listener: (client: JSONSocket, params: SubscriptionQuery) => void): this; | ||
removeSubscribedListener(listener: (client: JSONSocket, params: SubscriptionQuery) => void): this; | ||
addUnsubscribedListener(listener: (client: JSONSocket, params: SubscriptionQuery) => void): this; | ||
removeUnsubscribedListener(listener: (client: JSONSocket, params: SubscriptionQuery) => void): this; | ||
/** | ||
* Retrieve subscribers on a model URI. If provided, the `filter` may be either | ||
* | ||
* - a `string` indicating a property of the subscription options that must have a truthy value, or | ||
* - a `function` that tests whether the subscription options match some arbitrary predicate | ||
* | ||
* @param modelURI the model URI for which to get subscribers | ||
* @param filter an optional subscriber filter, by options property or a generic predicate | ||
* @returns the matching subscriber sockets | ||
*/ | ||
protected getSubscribers(modelURI: string, filter?: keyof SubscriptionQuery | ((options: SubscriptionQuery) => boolean)): JSONSocket[]; | ||
/** | ||
* Query whether any subscribers are registered on a model URI. If provided, the `filter` may be either | ||
* | ||
* - a `string` indicating a property of the subscription options that must have a truthy value, or | ||
* - a `function` that tests whether the subscription options match some arbitrary predicate | ||
* | ||
* @param modelURI the model URI for which to get subscribers | ||
* @param filter an optional subscriber filter, by options property or a generic predicate | ||
* @returns whether any matching subscriptions exist | ||
*/ | ||
protected hasSubscribers(modelURI: string, filter?: keyof SubscriptionQuery | ((options: SubscriptionQuery) => boolean)): boolean; | ||
hasValidationSubscribers(modelURI: string): boolean; | ||
protected getValidationSubscribers(modelURI: string): JSONSocket[]; | ||
broadcastValidation(modelURI: string, results: Diagnostic): Promise<boolean>; | ||
sendValidation(client: JSONSocket, results: Diagnostic): Promise<boolean>; | ||
protected sendSubscriptionMessage(client: JSONSocket, message: ModelServerMessage<any>): Promise<boolean>; | ||
} | ||
export {}; | ||
//# sourceMappingURL=subscription-manager.d.ts.map |
@@ -37,2 +37,3 @@ "use strict"; | ||
const modelserver_plugin_ext_1 = require("@eclipse-emfcloud/modelserver-plugin-ext"); | ||
const events_1 = require("events"); | ||
const inversify_1 = require("inversify"); | ||
@@ -47,2 +48,3 @@ const qs_1 = require("qs"); | ||
this.subscriptions = new Map(); | ||
this.eventEmitter = new events_1.EventEmitter(); | ||
} | ||
@@ -66,3 +68,6 @@ addSubscription(client, endpoint, params) { | ||
// Clean-up on close | ||
const cleanupHandler = () => this.subscriptions.delete(downstream); | ||
const cleanupHandler = () => { | ||
this.subscriptions.delete(downstream); | ||
this.fireEvent('unsubscribed', downstream, params); | ||
}; | ||
downstream.onClose(cleanupHandler); | ||
@@ -79,8 +84,59 @@ upstream.onClose(cleanupHandler); | ||
} | ||
this.fireEvent('subscribed', downstream, params); | ||
return downstream; | ||
} | ||
fireEvent(eventType, client, params) { | ||
this.eventEmitter.emit(eventType, client, params); | ||
} | ||
addSubscribedListener(listener) { | ||
this.eventEmitter.on('subscribed', listener); | ||
return this; | ||
} | ||
removeSubscribedListener(listener) { | ||
this.eventEmitter.off('subscribed', listener); | ||
return this; | ||
} | ||
addUnsubscribedListener(listener) { | ||
this.eventEmitter.on('unsubscribed', listener); | ||
return this; | ||
} | ||
removeUnsubscribedListener(listener) { | ||
this.eventEmitter.off('unsubscribed', listener); | ||
return this; | ||
} | ||
/** | ||
* Retrieve subscribers on a model URI. If provided, the `filter` may be either | ||
* | ||
* - a `string` indicating a property of the subscription options that must have a truthy value, or | ||
* - a `function` that tests whether the subscription options match some arbitrary predicate | ||
* | ||
* @param modelURI the model URI for which to get subscribers | ||
* @param filter an optional subscriber filter, by options property or a generic predicate | ||
* @returns the matching subscriber sockets | ||
*/ | ||
getSubscribers(modelURI, filter) { | ||
return Array.from(this.subscriptions.keys()) | ||
.filter(client => client.options.modeluri === modelURI) | ||
.filter(subscriberFilter(filter)); | ||
} | ||
/** | ||
* Query whether any subscribers are registered on a model URI. If provided, the `filter` may be either | ||
* | ||
* - a `string` indicating a property of the subscription options that must have a truthy value, or | ||
* - a `function` that tests whether the subscription options match some arbitrary predicate | ||
* | ||
* @param modelURI the model URI for which to get subscribers | ||
* @param filter an optional subscriber filter, by options property or a generic predicate | ||
* @returns whether any matching subscriptions exist | ||
*/ | ||
hasSubscribers(modelURI, filter) { | ||
return Array.from(this.subscriptions.keys()) | ||
.filter(client => client.options.modeluri === modelURI) | ||
.some(subscriberFilter(filter)); | ||
} | ||
hasValidationSubscribers(modelURI) { | ||
return Array.from(this.subscriptions.keys()).some(client => { var _a; return ((_a = client.options) === null || _a === void 0 ? void 0 : _a.livevalidation) && client.options.modeluri === modelURI; }); | ||
return this.hasSubscribers(modelURI, 'livevalidation'); | ||
} | ||
getValidationSubscribers(modelURI) { | ||
return Array.from(this.subscriptions.keys()).filter(client => { var _a; return ((_a = client.options) === null || _a === void 0 ? void 0 : _a.livevalidation) && client.options.modeluri === modelURI; }); | ||
return this.getSubscribers(modelURI, 'livevalidation'); | ||
} | ||
@@ -92,3 +148,13 @@ async broadcastValidation(modelURI, results) { | ||
}; | ||
return Promise.all(this.getValidationSubscribers(modelURI).map(client => new Promise(resolve => { | ||
return Promise.all(this.getValidationSubscribers(modelURI).map(client => this.sendSubscriptionMessage(client, message))).then(sent => sent.every(each => each)); | ||
} | ||
async sendValidation(client, results) { | ||
const message = { | ||
type: modelserver_client_1.MessageType.validationResult, | ||
data: results | ||
}; | ||
return this.sendSubscriptionMessage(client, message); | ||
} | ||
async sendSubscriptionMessage(client, message) { | ||
return new Promise(resolve => { | ||
client.send(message, (error) => { | ||
@@ -103,3 +169,3 @@ if (error) { | ||
}); | ||
}))).then(sent => sent.every(each => each)); | ||
}); | ||
} | ||
@@ -120,2 +186,7 @@ }; | ||
exports.SubscriptionManager = SubscriptionManager; | ||
const subscriberFilter = filter => typeof filter === 'string' | ||
? client => { var _a; return !!((_a = client.options) === null || _a === void 0 ? void 0 : _a[filter]); } | ||
: typeof filter === 'function' | ||
? client => client.options && filter(client.options) | ||
: () => true; | ||
//# sourceMappingURL=subscription-manager.js.map |
@@ -14,2 +14,3 @@ /******************************************************************************** | ||
import { InternalModelServerClientApi } from '../client/model-server-client'; | ||
import { JSONSocket } from '../client/web-socket-utils'; | ||
import { ValidationProviderRegistry } from '../validation-provider-registry'; | ||
@@ -27,2 +28,3 @@ import { SubscriptionManager } from './subscription-manager'; | ||
protected readonly subscriptionManager: SubscriptionManager; | ||
initialize(): void; | ||
validate(modelURI: string): Promise<Diagnostic>; | ||
@@ -37,3 +39,4 @@ /** | ||
performLiveValidation(modelURI: string): Promise<boolean>; | ||
protected initializeLiveValidation(client: JSONSocket, modelURI: string): Promise<unknown>; | ||
} | ||
//# sourceMappingURL=validation-manager.d.ts.map |
@@ -36,2 +36,9 @@ "use strict"; | ||
let ValidationManager = ValidationManager_1 = class ValidationManager { | ||
initialize() { | ||
this.subscriptionManager.addSubscribedListener((client, params) => { | ||
if (params.livevalidation) { | ||
this.initializeLiveValidation(client, params.modeluri); | ||
} | ||
}); | ||
} | ||
async validate(modelURI) { | ||
@@ -70,2 +77,5 @@ const model = await this.modelServerClient.get(modelURI).then(asModelServerObject); | ||
} | ||
async initializeLiveValidation(client, modelURI) { | ||
return this.validate(modelURI).then(diagnostics => this.subscriptionManager.sendValidation(client, diagnostics)); | ||
} | ||
}; | ||
@@ -89,2 +99,8 @@ __decorate([ | ||
], ValidationManager.prototype, "subscriptionManager", void 0); | ||
__decorate([ | ||
(0, inversify_1.postConstruct)(), | ||
__metadata("design:type", Function), | ||
__metadata("design:paramtypes", []), | ||
__metadata("design:returntype", void 0) | ||
], ValidationManager.prototype, "initialize", null); | ||
ValidationManager = ValidationManager_1 = __decorate([ | ||
@@ -91,0 +107,0 @@ (0, inversify_1.injectable)() |
{ | ||
"name": "@eclipse-emfcloud/modelserver-node", | ||
"version": "0.2.0-next.55b519b.29+55b519b", | ||
"version": "0.2.0-next.781fe49.31+781fe49", | ||
"description": "Business Logic layer façade for the Model Server.", | ||
@@ -28,3 +28,3 @@ "license": "(EPL-2.0 OR MIT)", | ||
"dependencies": { | ||
"@eclipse-emfcloud/modelserver-plugin-ext": "0.2.0-next.55b519b.29+55b519b", | ||
"@eclipse-emfcloud/modelserver-plugin-ext": "0.2.0-next.781fe49.31+781fe49", | ||
"axios": "^0.24.0", | ||
@@ -62,3 +62,3 @@ "express": "^4.17.1", | ||
}, | ||
"gitHead": "55b519b108e4c09db3a33bd06ccccb9cf833af5f" | ||
"gitHead": "781fe498b9aae55aa92bb75032514b1044e47367" | ||
} |
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
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
Found 1 instance in 1 package
279296
87
3725