@nmshd/runtime 2.0.0-alpha.5 → 2.0.0-alpha.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -115,6 +115,7 @@ const DatabaseSchemaUpgrader_1 = __webpack_require__(/*! ./DatabaseSchemaUpgrade
115
115
  const dataViews_1 = __webpack_require__(/*! ./dataViews */ "./dist/dataViews/index.js");
116
116
  const events_1 = __webpack_require__(/*! ./events */ "./dist/events/index.js");
117
117
  const extensibility_1 = __webpack_require__(/*! ./extensibility */ "./dist/extensibility/index.js");
118
+ const modules_1 = __webpack_require__(/*! ./modules */ "./dist/modules/index.js");
118
119
  const RuntimeLoggerFactory_1 = __webpack_require__(/*! ./RuntimeLoggerFactory */ "./dist/RuntimeLoggerFactory.js");
119
120
  const useCases_1 = __webpack_require__(/*! ./useCases */ "./dist/useCases/index.js");
120
121
  const SchemaRepository_1 = __webpack_require__(/*! ./useCases/common/SchemaRepository */ "./dist/useCases/common/SchemaRepository.js");
@@ -125,6 +126,9 @@ class Runtime {
125
126
  this.runtimeConfig = config;
126
127
  this._eventBus = new ts_utils_1.EventEmitter2EventBus();
127
128
  }
129
+ get anonymousServices() {
130
+ return this._anonymousServices;
131
+ }
128
132
  isLoggedIn() {
129
133
  return !!this._accountController;
130
134
  }
@@ -138,32 +142,18 @@ class Runtime {
138
142
  throw useCases_1.RuntimeErrors.startup.noActiveConsumptionController();
139
143
  return this._consumptionController;
140
144
  }
141
- getDataViewExpander() {
142
- if (!this._expander)
143
- throw useCases_1.RuntimeErrors.startup.noActiveExpander();
144
- return this._expander;
145
- }
146
145
  async login(accountController, consumptionController) {
147
146
  this._accountController = accountController;
148
- this._transportServices = typescript_ioc_1.Container.get(extensibility_1.TransportServices);
147
+ const transportServices = typescript_ioc_1.Container.get(extensibility_1.TransportServices);
149
148
  this._consumptionController = consumptionController;
150
- this._consumptionServices = typescript_ioc_1.Container.get(extensibility_1.ConsumptionServices);
151
- this._expander = typescript_ioc_1.Container.get(dataViews_1.DataViewExpander);
149
+ const consumptionServices = typescript_ioc_1.Container.get(extensibility_1.ConsumptionServices);
150
+ const dataViewExpander = typescript_ioc_1.Container.get(dataViews_1.DataViewExpander);
152
151
  await new DatabaseSchemaUpgrader_1.DatabaseSchemaUpgrader(accountController, consumptionController).upgradeSchemaVersion();
153
- return this;
152
+ return { transportServices, consumptionServices, dataViewExpander };
154
153
  }
155
154
  get modules() {
156
155
  return this._modules;
157
156
  }
158
- get transportServices() {
159
- return this._transportServices;
160
- }
161
- get consumptionServices() {
162
- return this._consumptionServices;
163
- }
164
- get anonymousServices() {
165
- return this._anonymousServices;
166
- }
167
157
  get eventBus() {
168
158
  return this._eventBus;
169
159
  }
@@ -276,7 +266,6 @@ class Runtime {
276
266
  this.logger.info("Loading modules...");
277
267
  for (const moduleName in this.runtimeConfig.modules) {
278
268
  const moduleConfiguration = this.runtimeConfig.modules[moduleName];
279
- moduleConfiguration.name = moduleName;
280
269
  if (!moduleConfiguration.enabled) {
281
270
  this.logger.debug(`Skip loading module '${this.getModuleName(moduleConfiguration)}' because it is not enabled.`);
282
271
  continue;
@@ -285,10 +274,34 @@ class Runtime {
285
274
  this.logger.error(`Skip loading module '${this.getModuleName(moduleConfiguration)}' because has no location.`);
286
275
  continue;
287
276
  }
277
+ // load the builtin '@nmshd/runtime' modules based on their specifier after the colon
278
+ if (moduleConfiguration.location.startsWith("@nmshd/runtime:")) {
279
+ this.loadBuiltinModule(moduleConfiguration);
280
+ continue;
281
+ }
288
282
  await this.loadModule(moduleConfiguration);
289
283
  }
290
284
  this.eventBus.publish(new events_1.ModulesLoadedEvent());
291
285
  }
286
+ loadBuiltinModule(moduleConfiguration) {
287
+ const moduleSpecifier = moduleConfiguration.location.split(":")[1];
288
+ switch (moduleSpecifier) {
289
+ case "DeciderModule":
290
+ const deciderModule = new modules_1.DeciderModule(this, moduleConfiguration, this.loggerFactory.getLogger(modules_1.DeciderModule));
291
+ this.modules.add(deciderModule);
292
+ break;
293
+ case "RequestModule":
294
+ const requestModule = new modules_1.RequestModule(this, moduleConfiguration, this.loggerFactory.getLogger(modules_1.RequestModule));
295
+ this.modules.add(requestModule);
296
+ break;
297
+ case "MessageModule":
298
+ const messageModule = new modules_1.MessageModule(this, moduleConfiguration, this.loggerFactory.getLogger(modules_1.MessageModule));
299
+ this.modules.add(messageModule);
300
+ break;
301
+ default:
302
+ throw new Error(`Module ${moduleConfiguration.name} is not a builtin module.`);
303
+ }
304
+ }
292
305
  async initModules() {
293
306
  this.logger.info("Initializing modules...");
294
307
  for (const module of this.modules.toArray()) {
@@ -422,11 +435,11 @@ const content_1 = __webpack_require__(/*! @nmshd/content */ "@nmshd/content");
422
435
  const crypto_1 = __webpack_require__(/*! @nmshd/crypto */ "@nmshd/crypto");
423
436
  const transport_1 = __webpack_require__(/*! @nmshd/transport */ "@nmshd/transport");
424
437
  exports.buildInformation = {
425
- version: "2.0.0-alpha.5",
426
- build: "52",
427
- date: "2022-05-16T09:22:03+00:00",
428
- commit: "db9d9e60243e5497a469660a153f7f4f0b8fe1d6",
429
- dependencies: {"@js-soft/docdb-querytranslator":"1.0.1","@js-soft/logging-abstractions":"1.0.0","@js-soft/ts-serval":"2.0.3","@js-soft/ts-utils":"^1.1.2","@nmshd/consumption":"2.0.0-alpha.9","@nmshd/content":"2.0.0-alpha.13","@nmshd/crypto":"2.0.1","@nmshd/transport":"2.0.0-alpha.1","ajv":"^8.11.0","ajv-errors":"^3.0.0","ajv-formats":"^2.1.1","fluent-ts-validator":"3.0.3","json-stringify-safe":"^5.0.1","luxon":"^2.4.0","qrcode":"1.5.0","reflect-metadata":"0.1.13","ts-simple-nameof":"1.3.1","typescript-ioc":"3.2.2"},
438
+ version: "2.0.0-alpha.8",
439
+ build: "55",
440
+ date: "2022-05-18T09:52:15+00:00",
441
+ commit: "82eb44bc4e04cd801cd115997b8160c164fa4eb1",
442
+ dependencies: {"@js-soft/docdb-querytranslator":"1.0.1","@js-soft/logging-abstractions":"1.0.0","@js-soft/ts-serval":"2.0.3","@js-soft/ts-utils":"^1.1.2","@nmshd/consumption":"2.0.0-alpha.12","@nmshd/content":"2.0.0-alpha.14","@nmshd/crypto":"2.0.1","@nmshd/transport":"2.0.0-alpha.1","ajv":"^8.11.0","ajv-errors":"^3.0.0","ajv-formats":"^2.1.1","fluent-ts-validator":"3.0.3","json-stringify-safe":"^5.0.1","luxon":"^2.4.0","qrcode":"1.5.0","reflect-metadata":"0.1.13","ts-simple-nameof":"1.3.1","typescript-ioc":"3.2.2"},
430
443
  libraries: {
431
444
  serval: ts_serval_1.buildInformation,
432
445
  consumption: consumption_1.buildInformation,
@@ -3353,12 +3366,28 @@ __exportStar(__webpack_require__(/*! ./TransportServices */ "./dist/extensibilit
3353
3366
  Object.defineProperty(exports, "__esModule", ({ value: true }));
3354
3367
  exports.RuntimeModule = void 0;
3355
3368
  class RuntimeModule {
3369
+ constructor(runtime, configuration, logger) {
3370
+ this.runtime = runtime;
3371
+ this.configuration = configuration;
3372
+ this.logger = logger;
3373
+ this.registeredSubscriptions = [];
3374
+ }
3356
3375
  get name() {
3357
3376
  return this.configuration.name;
3358
3377
  }
3359
3378
  get displayName() {
3360
3379
  return this.configuration.displayName;
3361
3380
  }
3381
+ subscribeToEvent(event, handler) {
3382
+ const subscriptionId = this.runtime.eventBus.subscribe(event, handler);
3383
+ this.registeredSubscriptions.push({ id: subscriptionId, target: event });
3384
+ }
3385
+ unsubscribeFromAllEvents() {
3386
+ for (const subscription of this.registeredSubscriptions) {
3387
+ this.runtime.eventBus.unsubscribe(subscription.target, subscription.id);
3388
+ }
3389
+ this.registeredSubscriptions.splice(0);
3390
+ }
3362
3391
  }
3363
3392
  exports.RuntimeModule = RuntimeModule;
3364
3393
  //# sourceMappingURL=RuntimeModule.js.map
@@ -3447,6 +3476,45 @@ __exportStar(__webpack_require__(/*! ./useCases */ "./dist/useCases/index.js"),
3447
3476
 
3448
3477
  /***/ }),
3449
3478
 
3479
+ /***/ "./dist/modules/DeciderModule.js":
3480
+ /*!***************************************!*\
3481
+ !*** ./dist/modules/DeciderModule.js ***!
3482
+ \***************************************/
3483
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
3484
+
3485
+ "use strict";
3486
+
3487
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
3488
+ exports.DeciderModule = void 0;
3489
+ const consumption_1 = __webpack_require__(/*! @nmshd/consumption */ "@nmshd/consumption");
3490
+ const events_1 = __webpack_require__(/*! ../events */ "./dist/events/index.js");
3491
+ const extensibility_1 = __webpack_require__(/*! ../extensibility */ "./dist/extensibility/index.js");
3492
+ class DeciderModule extends extensibility_1.RuntimeModule {
3493
+ init() {
3494
+ // Nothing to do here
3495
+ }
3496
+ start() {
3497
+ this.subscribeToEvent(events_1.IncomingRequestStatusChangedEvent, this.handleIncomingRequestStatusChanged.bind(this));
3498
+ }
3499
+ async handleIncomingRequestStatusChanged(event) {
3500
+ if (event.data.newStatus !== consumption_1.ConsumptionRequestStatus.DecisionRequired)
3501
+ return;
3502
+ const services = this.runtime.getServices(event.eventTargetAddress);
3503
+ const requireManualDecisionResult = await services.consumptionServices.incomingRequests.requireManualDecision({ requestId: event.data.request.id });
3504
+ if (requireManualDecisionResult.isError) {
3505
+ this.logger.error(`Could not require manual decision for request ${event.data.request.id}`, requireManualDecisionResult.error);
3506
+ return;
3507
+ }
3508
+ }
3509
+ stop() {
3510
+ this.unsubscribeFromAllEvents();
3511
+ }
3512
+ }
3513
+ exports.DeciderModule = DeciderModule;
3514
+ //# sourceMappingURL=DeciderModule.js.map
3515
+
3516
+ /***/ }),
3517
+
3450
3518
  /***/ "./dist/modules/MessageModule.js":
3451
3519
  /*!***************************************!*\
3452
3520
  !*** ./dist/modules/MessageModule.js ***!
@@ -3456,6 +3524,7 @@ __exportStar(__webpack_require__(/*! ./useCases */ "./dist/useCases/index.js"),
3456
3524
  "use strict";
3457
3525
 
3458
3526
  Object.defineProperty(exports, "__esModule", ({ value: true }));
3527
+ exports.MessageModule = void 0;
3459
3528
  const content_1 = __webpack_require__(/*! @nmshd/content */ "@nmshd/content");
3460
3529
  const events_1 = __webpack_require__(/*! ../events */ "./dist/events/index.js");
3461
3530
  const MailReceivedEvent_1 = __webpack_require__(/*! ../events/consumption/MailReceivedEvent */ "./dist/events/consumption/MailReceivedEvent.js");
@@ -3467,7 +3536,7 @@ class MessageModule extends RuntimeModule_1.RuntimeModule {
3467
3536
  // Nothing to do here
3468
3537
  }
3469
3538
  start() {
3470
- this.messageReceivedSubscription = this.runtime.eventBus.subscribe(events_1.MessageReceivedEvent, this.handleMessageReceived);
3539
+ this.subscribeToEvent(events_1.MessageReceivedEvent, this.handleMessageReceived.bind(this));
3471
3540
  }
3472
3541
  async handleMessageReceived(messageReceivedEvent) {
3473
3542
  const message = messageReceivedEvent.data;
@@ -3492,7 +3561,8 @@ class MessageModule extends RuntimeModule_1.RuntimeModule {
3492
3561
  // Unknown type
3493
3562
  return;
3494
3563
  }
3495
- const result = await this.runtime.transportServices.relationships.getRelationshipByAddress({ address: message.createdBy });
3564
+ const services = this.runtime.getServices(messageReceivedEvent.eventTargetAddress);
3565
+ const result = await services.transportServices.relationships.getRelationshipByAddress({ address: message.createdBy });
3496
3566
  if (!result.isSuccess) {
3497
3567
  this.logger.error(`Could not find relationship for address '${message.createdBy}'.`, result.error);
3498
3568
  return;
@@ -3502,14 +3572,140 @@ class MessageModule extends RuntimeModule_1.RuntimeModule {
3502
3572
  this.logger.trace(`Published RelationshipEvent for ${message.id} to ${relationship.id}`);
3503
3573
  }
3504
3574
  stop() {
3505
- this.runtime.eventBus.unsubscribe(events_1.MessageReceivedEvent, this.messageReceivedSubscription);
3575
+ this.unsubscribeFromAllEvents();
3506
3576
  }
3507
3577
  }
3508
- exports["default"] = MessageModule;
3578
+ exports.MessageModule = MessageModule;
3509
3579
  //# sourceMappingURL=MessageModule.js.map
3510
3580
 
3511
3581
  /***/ }),
3512
3582
 
3583
+ /***/ "./dist/modules/RequestModule.js":
3584
+ /*!***************************************!*\
3585
+ !*** ./dist/modules/RequestModule.js ***!
3586
+ \***************************************/
3587
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
3588
+
3589
+ "use strict";
3590
+
3591
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
3592
+ exports.RequestModule = void 0;
3593
+ const consumption_1 = __webpack_require__(/*! @nmshd/consumption */ "@nmshd/consumption");
3594
+ const content_1 = __webpack_require__(/*! @nmshd/content */ "@nmshd/content");
3595
+ const events_1 = __webpack_require__(/*! ../events */ "./dist/events/index.js");
3596
+ const RuntimeModule_1 = __webpack_require__(/*! ../extensibility/modules/RuntimeModule */ "./dist/extensibility/modules/RuntimeModule.js");
3597
+ const types_1 = __webpack_require__(/*! ../types */ "./dist/types/index.js");
3598
+ class RequestModule extends RuntimeModule_1.RuntimeModule {
3599
+ init() {
3600
+ // Nothing to do here
3601
+ }
3602
+ start() {
3603
+ this.subscribeToEvent(events_1.PeerRelationshipTemplateLoadedEvent, this.handlePeerRelationshipTemplateLoaded.bind(this));
3604
+ this.subscribeToEvent(events_1.MessageReceivedEvent, this.handleMessageReceivedEvent.bind(this));
3605
+ this.subscribeToEvent(events_1.IncomingRequestStatusChangedEvent, this.handleIncomingRequestStatusChanged.bind(this));
3606
+ this.subscribeToEvent(events_1.RelationshipChangedEvent, this.handleRelationshipChangedEvent.bind(this));
3607
+ }
3608
+ async handlePeerRelationshipTemplateLoaded(event) {
3609
+ if (event.data.content["@type"] !== "RelationshipTemplateBody")
3610
+ return;
3611
+ const body = event.data.content;
3612
+ const request = body.onNewRelationship;
3613
+ const services = this.runtime.getServices(event.eventTargetAddress);
3614
+ await this.createIncomingRequest(services, request, event.data.id);
3615
+ }
3616
+ async handleMessageReceivedEvent(event) {
3617
+ if (event.data.content["@type"] !== "Request")
3618
+ return;
3619
+ // TODO: JSSNMSHDD-2896 (handle response)
3620
+ const request = event.data.content;
3621
+ const services = this.runtime.getServices(event.eventTargetAddress);
3622
+ await this.createIncomingRequest(services, request, event.data.id);
3623
+ }
3624
+ async createIncomingRequest(services, request, requestSourceId) {
3625
+ const receivedRequestResult = await services.consumptionServices.incomingRequests.received({ receivedRequest: request, requestSourceId });
3626
+ if (receivedRequestResult.isError) {
3627
+ this.logger.error(`Could not receive request ${request.id}`, receivedRequestResult.error);
3628
+ return;
3629
+ }
3630
+ const checkPrerequitesResult = await services.consumptionServices.incomingRequests.checkPrerequisites({ requestId: receivedRequestResult.value.id });
3631
+ if (checkPrerequitesResult.isError) {
3632
+ this.logger.error(`Could not check prerequisites for request ${request.id}`, checkPrerequitesResult.error);
3633
+ return;
3634
+ }
3635
+ }
3636
+ async handleIncomingRequestStatusChanged(event) {
3637
+ if (event.data.newStatus !== consumption_1.ConsumptionRequestStatus.Decided)
3638
+ return;
3639
+ switch (event.data.request.source.type) {
3640
+ case "RelationshipTemplate":
3641
+ await this.handleIncomingRequestCompletedForRelationship(event);
3642
+ break;
3643
+ default:
3644
+ throw new Error(`Cannot handle source.type '${event.data.request.source.type}'.`);
3645
+ }
3646
+ }
3647
+ async handleIncomingRequestCompletedForRelationship(event) {
3648
+ const templateId = event.data.request.source.reference;
3649
+ const services = this.runtime.getServices(event.eventTargetAddress);
3650
+ const templateResponse = await services.transportServices.relationshipTemplates.getRelationshipTemplate({ id: templateId });
3651
+ if (templateResponse.isError) {
3652
+ this.logger.error(`Could not find template with id '${templateId}'.`);
3653
+ // TODO: error state
3654
+ return;
3655
+ }
3656
+ const template = templateResponse.value;
3657
+ const creationChangeBody = content_1.RelationshipCreationChangeRequestBody.from({
3658
+ "@type": "RelationshipCreationChangeRequestBody",
3659
+ response: event.data.request.response.content,
3660
+ templateContentMetadata: template.content.metadata
3661
+ });
3662
+ const createRelationshipResponse = await services.transportServices.relationships.createRelationship({ templateId, content: creationChangeBody });
3663
+ if (createRelationshipResponse.isError) {
3664
+ this.logger.error(`Could not create relationship for templateId '${templateId}'.`);
3665
+ // TODO: error state
3666
+ return;
3667
+ }
3668
+ const requestId = event.data.request.id;
3669
+ const completeRequestResponse = await services.consumptionServices.incomingRequests.complete({
3670
+ requestId,
3671
+ responseSourceId: createRelationshipResponse.value.changes[0].id
3672
+ });
3673
+ if (completeRequestResponse.isError) {
3674
+ this.logger.error(`Could not complete the request '${requestId}'.`);
3675
+ return;
3676
+ }
3677
+ }
3678
+ async handleRelationshipChangedEvent(event) {
3679
+ // only trigger for new relationships that were created from an own template
3680
+ if (event.data.status !== types_1.RelationshipStatus.Pending || !event.data.template.isOwn)
3681
+ return;
3682
+ const services = this.runtime.getServices(event.eventTargetAddress);
3683
+ const createdRelationship = event.data;
3684
+ const template = createdRelationship.template;
3685
+ const templateId = template.id;
3686
+ // do not trigger for templates without the correct content type
3687
+ if (template.content["@type"] !== "RelationshipTemplateBody")
3688
+ return;
3689
+ const relationshipCreationChange = createdRelationship.changes[0];
3690
+ const relationshipChangeId = relationshipCreationChange.id;
3691
+ // do not trigger for creation changes without the correct content type
3692
+ if (relationshipCreationChange.request.content["@type"] !== "RelationshipCreationChangeRequestBody")
3693
+ return;
3694
+ const result = await services.consumptionServices.outgoingRequests.createAndCompleteFromRelationshipCreationChange({ templateId, relationshipChangeId });
3695
+ if (result.isError) {
3696
+ this.logger.error(`Could not create and complete request for templateId '${templateId}' and changeId '${relationshipChangeId}'.`, result.error);
3697
+ return;
3698
+ }
3699
+ }
3700
+ stop() {
3701
+ this.unsubscribeFromAllEvents();
3702
+ }
3703
+ }
3704
+ exports.RequestModule = RequestModule;
3705
+ //# sourceMappingURL=RequestModule.js.map
3706
+
3707
+ /***/ }),
3708
+
3513
3709
  /***/ "./dist/modules/index.js":
3514
3710
  /*!*******************************!*\
3515
3711
  !*** ./dist/modules/index.js ***!
@@ -3533,7 +3729,9 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
3533
3729
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
3534
3730
  };
3535
3731
  Object.defineProperty(exports, "__esModule", ({ value: true }));
3732
+ __exportStar(__webpack_require__(/*! ./DeciderModule */ "./dist/modules/DeciderModule.js"), exports);
3536
3733
  __exportStar(__webpack_require__(/*! ./MessageModule */ "./dist/modules/MessageModule.js"), exports);
3734
+ __exportStar(__webpack_require__(/*! ./RequestModule */ "./dist/modules/RequestModule.js"), exports);
3537
3735
  //# sourceMappingURL=index.js.map
3538
3736
 
3539
3737
  /***/ }),
@@ -9032,14 +9230,14 @@ let CreateAndCompleteOutgoingRequestFromRelationshipCreationChangeUseCase = clas
9032
9230
  }
9033
9231
  async executeInternal(request) {
9034
9232
  const template = await this.relationshipTemplateController.getRelationshipTemplate(transport_1.CoreId.from(request.templateId));
9233
+ if (!template) {
9234
+ return ts_utils_1.Result.fail(common_1.RuntimeErrors.general.recordNotFound(transport_1.RelationshipTemplate));
9235
+ }
9035
9236
  const relationships = await this.relationshipController.getRelationships({ "cache.changes.id": request.relationshipChangeId }); // eslint-disable-line @typescript-eslint/naming-convention
9036
9237
  if (relationships.length === 0) {
9037
9238
  return ts_utils_1.Result.fail(common_1.RuntimeErrors.general.recordNotFound(transport_1.RelationshipChange));
9038
9239
  }
9039
9240
  const relationship = relationships[0];
9040
- if (!template) {
9041
- return ts_utils_1.Result.fail(common_1.RuntimeErrors.general.recordNotFound(transport_1.RelationshipTemplate));
9042
- }
9043
9241
  const params = {
9044
9242
  template: template,
9045
9243
  creationChange: relationship.cache.creationChange