@twin.org/federated-catalogue-service 0.0.2-next.3 → 0.0.2-next.5

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.
@@ -12,8 +12,6 @@ var identityModels = require('@twin.org/identity-models');
12
12
  var crypto = require('@twin.org/crypto');
13
13
  var standardsW3cDid = require('@twin.org/standards-w3c-did');
14
14
 
15
- // Copyright 2024 IOTA Stiftung.
16
- // SPDX-License-Identifier: Apache-2.0.
17
15
  /**
18
16
  * Data Resource Entry.
19
17
  */
@@ -71,6 +69,10 @@ exports.DataResourceEntry = class DataResourceEntry {
71
69
  * Evidences
72
70
  */
73
71
  evidence;
72
+ /**
73
+ * Extended data of a Data Resource entry.
74
+ */
75
+ extraData;
74
76
  };
75
77
  __decorate([
76
78
  entity.property({ type: "string", isPrimary: true }),
@@ -124,12 +126,14 @@ __decorate([
124
126
  entity.property({ type: "array" }),
125
127
  __metadata("design:type", Array)
126
128
  ], exports.DataResourceEntry.prototype, "evidence", void 0);
129
+ __decorate([
130
+ entity.property({ type: "object", optional: true }),
131
+ __metadata("design:type", Object)
132
+ ], exports.DataResourceEntry.prototype, "extraData", void 0);
127
133
  exports.DataResourceEntry = __decorate([
128
134
  entity.entity()
129
135
  ], exports.DataResourceEntry);
130
136
 
131
- // Copyright 2024 IOTA Stiftung.
132
- // SPDX-License-Identifier: Apache-2.0.
133
137
  /**
134
138
  * Data Space Connector Entry.
135
139
  */
@@ -194,6 +198,10 @@ exports.DataSpaceConnectorEntry = class DataSpaceConnectorEntry {
194
198
  * Evidences
195
199
  */
196
200
  evidence;
201
+ /**
202
+ * Extended data of a DS Connector entry.
203
+ */
204
+ extraData;
197
205
  };
198
206
  __decorate([
199
207
  entity.property({ type: "string", isPrimary: true }),
@@ -255,12 +263,14 @@ __decorate([
255
263
  entity.property({ type: "array" }),
256
264
  __metadata("design:type", Array)
257
265
  ], exports.DataSpaceConnectorEntry.prototype, "evidence", void 0);
266
+ __decorate([
267
+ entity.property({ type: "object", optional: true }),
268
+ __metadata("design:type", Object)
269
+ ], exports.DataSpaceConnectorEntry.prototype, "extraData", void 0);
258
270
  exports.DataSpaceConnectorEntry = __decorate([
259
271
  entity.entity()
260
272
  ], exports.DataSpaceConnectorEntry);
261
273
 
262
- // Copyright 2024 IOTA Stiftung.
263
- // SPDX-License-Identifier: Apache-2.0.
264
274
  /**
265
275
  * Participant entry.
266
276
  */
@@ -301,6 +311,10 @@ exports.ParticipantEntry = class ParticipantEntry {
301
311
  * Evidences
302
312
  */
303
313
  evidence;
314
+ /**
315
+ * Extended data of a Participant entry.
316
+ */
317
+ extraData;
304
318
  };
305
319
  __decorate([
306
320
  entity.property({ type: "string", isPrimary: true }),
@@ -338,12 +352,14 @@ __decorate([
338
352
  entity.property({ type: "array" }),
339
353
  __metadata("design:type", Array)
340
354
  ], exports.ParticipantEntry.prototype, "evidence", void 0);
355
+ __decorate([
356
+ entity.property({ type: "object", optional: true }),
357
+ __metadata("design:type", Object)
358
+ ], exports.ParticipantEntry.prototype, "extraData", void 0);
341
359
  exports.ParticipantEntry = __decorate([
342
360
  entity.entity()
343
361
  ], exports.ParticipantEntry);
344
362
 
345
- // Copyright 2024 IOTA Stiftung.
346
- // SPDX-License-Identifier: Apache-2.0.
347
363
  /**
348
364
  * Service Offering Entry.
349
365
  */
@@ -396,6 +412,10 @@ exports.ServiceOfferingEntry = class ServiceOfferingEntry {
396
412
  * Evidences
397
413
  */
398
414
  evidence;
415
+ /**
416
+ * Extended data of a Service Offering entry.
417
+ */
418
+ extraData;
399
419
  };
400
420
  __decorate([
401
421
  entity.property({ type: "string", isPrimary: true }),
@@ -418,7 +438,7 @@ __decorate([
418
438
  __metadata("design:type", String)
419
439
  ], exports.ServiceOfferingEntry.prototype, "providedBy", void 0);
420
440
  __decorate([
421
- entity.property({ type: "object" }),
441
+ entity.property({ type: "object", optional: true }),
422
442
  __metadata("design:type", Object)
423
443
  ], exports.ServiceOfferingEntry.prototype, "endpoint", void 0);
424
444
  __decorate([
@@ -445,6 +465,10 @@ __decorate([
445
465
  entity.property({ type: "array" }),
446
466
  __metadata("design:type", Array)
447
467
  ], exports.ServiceOfferingEntry.prototype, "evidence", void 0);
468
+ __decorate([
469
+ entity.property({ type: "object", optional: true }),
470
+ __metadata("design:type", Object)
471
+ ], exports.ServiceOfferingEntry.prototype, "extraData", void 0);
448
472
  exports.ServiceOfferingEntry = __decorate([
449
473
  entity.entity()
450
474
  ], exports.ServiceOfferingEntry);
@@ -1047,7 +1071,7 @@ async function complianceCredentialPresentation(baseRouteName, httpRequestContex
1047
1071
  */
1048
1072
  async function participantList(httpRequestContext, factoryServiceName, request) {
1049
1073
  const service = core.ComponentFactory.get(factoryServiceName);
1050
- const itemsAndCursor = await service.queryParticipants(request?.query?.id, request?.query?.registrationNumber, request?.query?.lrnType, request?.query?.cursor, core.Coerce.integer(request?.query?.pageSize));
1074
+ const itemsAndCursor = await service.queryParticipants(request?.query?.id, request?.query?.registrationNumber, request?.query?.lrnType, request?.query?.cursor, core.Coerce.integer(request?.query?.limit));
1051
1075
  return {
1052
1076
  body: itemsAndCursor
1053
1077
  };
@@ -1101,7 +1125,7 @@ async function serviceOfferingCredentialPresentation(baseRouteName, httpRequestC
1101
1125
  */
1102
1126
  async function serviceOfferingList(httpRequestContext, factoryServiceName, request) {
1103
1127
  const service = core.ComponentFactory.get(factoryServiceName);
1104
- const itemsAndCursor = await service.queryServiceOfferings(request?.query?.id, request?.query?.providedBy, request?.query?.cursor, core.Coerce.integer(request?.query?.pageSize));
1128
+ const itemsAndCursor = await service.queryServiceOfferings(request?.query?.id, request?.query?.providedBy, request?.query?.cursor, core.Coerce.integer(request?.query?.limit));
1105
1129
  return {
1106
1130
  body: itemsAndCursor
1107
1131
  };
@@ -1155,7 +1179,7 @@ async function dataResourceCredentialPresentation(baseRouteName, httpRequestCont
1155
1179
  */
1156
1180
  async function dataResourceList(httpRequestContext, factoryServiceName, request) {
1157
1181
  const service = core.ComponentFactory.get(factoryServiceName);
1158
- const itemsAndCursor = await service.queryDataResources(request?.query?.id, request?.query?.producedBy, request?.query?.cursor, core.Coerce.integer(request?.query?.pageSize));
1182
+ const itemsAndCursor = await service.queryDataResources(request?.query?.id, request?.query?.producedBy, request?.query?.cursor, core.Coerce.integer(request?.query?.limit));
1159
1183
  return {
1160
1184
  body: itemsAndCursor
1161
1185
  };
@@ -1206,7 +1230,7 @@ async function dataSpaceConnectorCredentialPresentation(baseRouteName, httpReque
1206
1230
  */
1207
1231
  async function dataSpaceConnectorList(httpRequestContext, factoryServiceName, request) {
1208
1232
  const service = core.ComponentFactory.get(factoryServiceName);
1209
- const itemsAndCursor = await service.queryDataSpaceConnectors(request?.query?.id, request?.query?.maintainedBy, request?.query?.cursor, core.Coerce.integer(request?.query?.pageSize));
1233
+ const itemsAndCursor = await service.queryDataSpaceConnectors(request?.query?.id, request?.query?.maintainedBy, request?.query?.cursor, core.Coerce.integer(request?.query?.limit));
1210
1234
  return {
1211
1235
  body: itemsAndCursor
1212
1236
  };
@@ -1234,9 +1258,9 @@ async function dataSpaceConnectorGet(httpRequestContext, factoryServiceName, req
1234
1258
  */
1235
1259
  class ComplianceCredentialVerificationService {
1236
1260
  /**
1237
- * Class name
1261
+ * Runtime name for the class.
1238
1262
  */
1239
- CLASS_NAME = "ComplianceCredentialVerificationService";
1263
+ static CLASS_NAME = "ComplianceCredentialVerificationService";
1240
1264
  /**
1241
1265
  * Resolver component.
1242
1266
  * @internal
@@ -1367,10 +1391,10 @@ class ComplianceCredentialVerificationService {
1367
1391
  */
1368
1392
  async verifyEvidence(evidence) {
1369
1393
  // The credential associated to the evidence has to be retrieved, then verified
1370
- core.Guards.object(this.CLASS_NAME, "IComplianceEvidence", evidence);
1394
+ core.Guards.object(ComplianceCredentialVerificationService.CLASS_NAME, "IComplianceEvidence", evidence);
1371
1395
  const credentialUrl = evidence.id;
1372
1396
  this._logger?.log({
1373
- source: this.CLASS_NAME,
1397
+ source: ComplianceCredentialVerificationService.CLASS_NAME,
1374
1398
  level: "info",
1375
1399
  message: "verifyingEvidenceCredential",
1376
1400
  ts: Date.now(),
@@ -1378,10 +1402,10 @@ class ComplianceCredentialVerificationService {
1378
1402
  credentialUrl
1379
1403
  }
1380
1404
  });
1381
- const credentialResponse = await web.FetchHelper.fetch(this.CLASS_NAME, credentialUrl, "GET", undefined, { cacheTtlMs: this._subResourceCacheTtlMs });
1405
+ const credentialResponse = await web.FetchHelper.fetch(ComplianceCredentialVerificationService.CLASS_NAME, credentialUrl, "GET", undefined, { cacheTtlMs: this._subResourceCacheTtlMs });
1382
1406
  if (!credentialResponse.ok) {
1383
1407
  this._logger?.log({
1384
- source: this.CLASS_NAME,
1408
+ source: ComplianceCredentialVerificationService.CLASS_NAME,
1385
1409
  level: "error",
1386
1410
  message: "credentialCannotBeRetrieved",
1387
1411
  ts: Date.now(),
@@ -1412,7 +1436,7 @@ class ComplianceCredentialVerificationService {
1412
1436
  hashToCheck = core.Converter.bytesToBase64(crypto.Sha512.sum512(core.Converter.utf8ToBytes(canonicalized)));
1413
1437
  }
1414
1438
  else {
1415
- throw new core.UnprocessableError(this.CLASS_NAME, "unknownHashingAlgorithm", { hashingAlg });
1439
+ throw new core.UnprocessableError(ComplianceCredentialVerificationService.CLASS_NAME, "unknownHashingAlgorithm", { hashingAlg });
1416
1440
  }
1417
1441
  if (hashToCheck !== hash) {
1418
1442
  return {
@@ -1422,7 +1446,7 @@ class ComplianceCredentialVerificationService {
1422
1446
  }
1423
1447
  const { id } = identityModels.DocumentHelper.parseId(proof.verificationMethod);
1424
1448
  const documentId = theCredential.issuer ?? id;
1425
- core.Guards.stringValue(this.CLASS_NAME, "documentId", documentId);
1449
+ core.Guards.stringValue(ComplianceCredentialVerificationService.CLASS_NAME, "documentId", documentId);
1426
1450
  let verified = false;
1427
1451
  try {
1428
1452
  const document = await this._resolver.identityResolve(documentId);
@@ -1431,7 +1455,7 @@ class ComplianceCredentialVerificationService {
1431
1455
  }
1432
1456
  catch (error) {
1433
1457
  this._logger?.log({
1434
- source: this.CLASS_NAME,
1458
+ source: ComplianceCredentialVerificationService.CLASS_NAME,
1435
1459
  level: "error",
1436
1460
  message: "credentialVerificationError",
1437
1461
  ts: Date.now(),
@@ -1446,7 +1470,7 @@ class ComplianceCredentialVerificationService {
1446
1470
  };
1447
1471
  }
1448
1472
  this._logger?.log({
1449
- source: this.CLASS_NAME,
1473
+ source: ComplianceCredentialVerificationService.CLASS_NAME,
1450
1474
  level: "info",
1451
1475
  message: "credentialEvidenceVerified",
1452
1476
  ts: Date.now(),
@@ -1467,15 +1491,15 @@ class ComplianceCredentialVerificationService {
1467
1491
  * Service for performing logging operations to a connector.
1468
1492
  */
1469
1493
  class FederatedCatalogueService {
1494
+ /**
1495
+ * Runtime name for the class.
1496
+ */
1497
+ static CLASS_NAME = "FederatedCatalogueService";
1470
1498
  /**
1471
1499
  * Fields to skip when persisting entries to the Catalogue
1472
1500
  * @internal
1473
1501
  */
1474
1502
  static _FIELDS_TO_SKIP = ["@context", "type"];
1475
- /**
1476
- * Runtime name for the class.
1477
- */
1478
- CLASS_NAME = "FederatedCatalogueService";
1479
1503
  /**
1480
1504
  * The identity resolver used to dereference DIDs.
1481
1505
  * @internal
@@ -1517,12 +1541,10 @@ class FederatedCatalogueService {
1517
1541
  */
1518
1542
  constructor(options) {
1519
1543
  this._logging = core.ComponentFactory.getIfExists(options?.loggingComponentType ?? "logging");
1520
- this._entityStorageParticipants = entityStorageModels.EntityStorageConnectorFactory.get(options.participantEntityStorageType ?? core.StringHelper.kebabCase("ParticipantEntry"));
1521
- this._entityStorageServiceOfferings = entityStorageModels.EntityStorageConnectorFactory.get(options.serviceOfferingEntityStorageType ??
1522
- core.StringHelper.kebabCase("ServiceOfferingEntry"));
1523
- this._entityStorageDataResources = entityStorageModels.EntityStorageConnectorFactory.get(options.dataResourceEntityStorageType ?? core.StringHelper.kebabCase("DataResourceEntry"));
1524
- this._entityStorageDataSpaceConnectors = entityStorageModels.EntityStorageConnectorFactory.get(options.dataSpaceConnectorStorageType ??
1525
- core.StringHelper.kebabCase("DataSpaceConnectorEntry"));
1544
+ this._entityStorageParticipants = entityStorageModels.EntityStorageConnectorFactory.get(options.participantEntityStorageType ?? "participant-entry");
1545
+ this._entityStorageServiceOfferings = entityStorageModels.EntityStorageConnectorFactory.get(options.serviceOfferingEntityStorageType ?? "service-offering-entry");
1546
+ this._entityStorageDataResources = entityStorageModels.EntityStorageConnectorFactory.get(options.dataResourceEntityStorageType ?? "data-resource-entry");
1547
+ this._entityStorageDataSpaceConnectors = entityStorageModels.EntityStorageConnectorFactory.get(options.dataSpaceConnectorStorageType ?? "data-space-connector-entry");
1526
1548
  this._resolver = core.ComponentFactory.get(options.identityResolverComponentType ?? "identity-resolver");
1527
1549
  this._complianceCredentialVerifier = new ComplianceCredentialVerificationService(options.config.clearingHouseApproverList, this._resolver, options.config.subResourceCacheTtlMs, this._logging);
1528
1550
  standardsSchemaOrg.SchemaOrgDataTypes.registerRedirects();
@@ -1533,32 +1555,34 @@ class FederatedCatalogueService {
1533
1555
  * @returns The Id of the Participant (DID usually).
1534
1556
  */
1535
1557
  async registerComplianceCredential(credentialJwt) {
1536
- core.Guards.string(this.CLASS_NAME, "credentialJwt", credentialJwt);
1558
+ core.Guards.string(FederatedCatalogueService.CLASS_NAME, "credentialJwt", credentialJwt);
1537
1559
  // This will raise exceptions as it has been coded reusing code from Gaia-X
1538
1560
  const complianceCredential = await this.decodeJwt(credentialJwt);
1539
1561
  const result = await this._complianceCredentialVerifier.verify(complianceCredential);
1540
1562
  if (!result.verified) {
1541
1563
  this._logging?.log({
1542
1564
  level: "error",
1543
- source: this.CLASS_NAME,
1565
+ source: FederatedCatalogueService.CLASS_NAME,
1544
1566
  ts: Date.now(),
1545
1567
  message: "complianceCredentialNotVerified",
1546
1568
  data: { result }
1547
1569
  });
1548
- throw new core.UnprocessableError(this.CLASS_NAME, "complianceCredentialNotVerified", {
1570
+ throw new core.UnprocessableError(FederatedCatalogueService.CLASS_NAME, "complianceCredentialNotVerified", {
1549
1571
  reason: result.verificationFailureReason
1550
1572
  });
1551
1573
  }
1552
1574
  const targetCredential = result.credentials.find(credential => credential.credentialSubject.type === standardsGaiaX.GaiaXTypes.LegalPerson);
1553
1575
  if (core.Is.undefined(targetCredential)) {
1554
- throw new core.UnprocessableError(this.CLASS_NAME, "noEvidence");
1576
+ throw new core.UnprocessableError(FederatedCatalogueService.CLASS_NAME, "noEvidence");
1555
1577
  }
1556
- const participantEntry = this.extractParticipantEntry(complianceCredential, targetCredential);
1578
+ const { participantEntry, extraData } = this.extractParticipantEntry(complianceCredential, targetCredential);
1557
1579
  const theEntry = core.ObjectHelper.omit(participantEntry, FederatedCatalogueService._FIELDS_TO_SKIP);
1558
- await this._entityStorageParticipants.set(theEntry);
1580
+ const extended = theEntry;
1581
+ extended.extraData = extraData;
1582
+ await this._entityStorageParticipants.set(extended);
1559
1583
  await this._logging?.log({
1560
1584
  level: "info",
1561
- source: this.CLASS_NAME,
1585
+ source: FederatedCatalogueService.CLASS_NAME,
1562
1586
  ts: Date.now(),
1563
1587
  message: "complianceCredentialVerified",
1564
1588
  data: {
@@ -1573,13 +1597,13 @@ class FederatedCatalogueService {
1573
1597
  * @param id The identity of the participant.
1574
1598
  * @param legalRegistrationNumber The legal registration number.
1575
1599
  * @param lrnType The legal registration number type (EORI, VATID, GLEIF, KENYA_PIN, etc.)
1576
- * @param cursor The cursor to request the next page of entities.
1577
- * @param pageSize The maximum number of entities in a page.
1600
+ * @param cursor The cursor to request the next chunk of entities.
1601
+ * @param limit Limit the number of entities to return.
1578
1602
  * @returns All the entities for the storage matching the conditions,
1579
1603
  * and a cursor which can be used to request more entities.
1580
1604
  * @throws NotImplementedError if the implementation does not support retrieval.
1581
1605
  */
1582
- async queryParticipants(id, legalRegistrationNumber, lrnType, cursor, pageSize) {
1606
+ async queryParticipants(id, legalRegistrationNumber, lrnType, cursor, limit) {
1583
1607
  const conditions = [];
1584
1608
  if (core.Is.stringValue(id)) {
1585
1609
  const condition = {
@@ -1605,15 +1629,16 @@ class FederatedCatalogueService {
1605
1629
  };
1606
1630
  conditions.push(condition);
1607
1631
  }
1608
- const entries = await this._entityStorageParticipants.query({ conditions }, undefined, undefined, cursor, pageSize);
1632
+ const entries = await this._entityStorageParticipants.query({ conditions }, undefined, undefined, cursor, limit);
1609
1633
  const itemList = entries.entities.map(entry => {
1610
1634
  entry.type = standardsGaiaX.GaiaXTypes.LegalPerson;
1611
1635
  return entry;
1612
1636
  });
1637
+ const { finalItemList, extraDataLdContext } = this.normalizeExtraData(itemList);
1613
1638
  const result = {
1614
- "@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST,
1639
+ "@context": dataJsonLd.JsonLdProcessor.combineContexts(federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST, extraDataLdContext),
1615
1640
  type: standardsSchemaOrg.SchemaOrgTypes.ItemList,
1616
- itemListElement: itemList,
1641
+ itemListElement: finalItemList,
1617
1642
  nextItem: entries.cursor
1618
1643
  };
1619
1644
  return dataJsonLd.JsonLdProcessor.compact(result, result["@context"]);
@@ -1626,7 +1651,7 @@ class FederatedCatalogueService {
1626
1651
  * @throws NotFoundError if not found.
1627
1652
  */
1628
1653
  async getEntry(entryType, entryId) {
1629
- core.Guards.stringValue(this.CLASS_NAME, "entryId", entryId);
1654
+ core.Guards.stringValue(FederatedCatalogueService.CLASS_NAME, "entryId", entryId);
1630
1655
  let itemsAndCursor;
1631
1656
  switch (entryType) {
1632
1657
  case standardsGaiaX.GaiaXTypes.LegalPerson:
@@ -1643,17 +1668,19 @@ class FederatedCatalogueService {
1643
1668
  itemsAndCursor = await this.queryDataResources(entryId);
1644
1669
  break;
1645
1670
  default:
1646
- throw new core.GeneralError(this.CLASS_NAME, "unknownEntryType", { entryType });
1671
+ throw new core.GeneralError(FederatedCatalogueService.CLASS_NAME, "unknownEntryType", {
1672
+ entryType
1673
+ });
1647
1674
  }
1648
1675
  if (core.Is.arrayValue(itemsAndCursor?.itemListElement)) {
1649
1676
  const entry = {
1650
1677
  ...itemsAndCursor.itemListElement[0],
1651
- "@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY
1678
+ "@context": dataJsonLd.JsonLdProcessor.combineContexts(federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY, itemsAndCursor["@context"])
1652
1679
  };
1653
1680
  const result = await dataJsonLd.JsonLdProcessor.compact(entry, entry["@context"]);
1654
1681
  return result;
1655
1682
  }
1656
- throw new core.NotFoundError(this.CLASS_NAME, "entryNotFound", entryId);
1683
+ throw new core.NotFoundError(FederatedCatalogueService.CLASS_NAME, "entryNotFound", entryId);
1657
1684
  }
1658
1685
  /**
1659
1686
  * Registers a compliance Credential concerning a Data Space Connector.
@@ -1661,19 +1688,19 @@ class FederatedCatalogueService {
1661
1688
  * @returns The identifier of the Data Space Connector registered.
1662
1689
  */
1663
1690
  async registerDataSpaceConnectorCredential(credentialJwt) {
1664
- core.Guards.string(this.CLASS_NAME, "credentialJwt", credentialJwt);
1691
+ core.Guards.string(FederatedCatalogueService.CLASS_NAME, "credentialJwt", credentialJwt);
1665
1692
  // This will raise exceptions as it has been coded reusing code from Gaia-X
1666
1693
  const complianceCredential = await this.decodeJwt(credentialJwt);
1667
1694
  const result = await this._complianceCredentialVerifier.verify(complianceCredential);
1668
1695
  if (!result.verified) {
1669
1696
  this._logging?.log({
1670
1697
  level: "error",
1671
- source: this.CLASS_NAME,
1698
+ source: FederatedCatalogueService.CLASS_NAME,
1672
1699
  ts: Date.now(),
1673
1700
  message: "complianceCredentialNotVerified",
1674
1701
  data: { result }
1675
1702
  });
1676
- throw new core.UnprocessableError(this.CLASS_NAME, "complianceCredentialNotVerified", {
1703
+ throw new core.UnprocessableError(FederatedCatalogueService.CLASS_NAME, "complianceCredentialNotVerified", {
1677
1704
  reason: result.verificationFailureReason
1678
1705
  });
1679
1706
  }
@@ -1685,21 +1712,25 @@ class FederatedCatalogueService {
1685
1712
  });
1686
1713
  const dataResourceCredentials = result.credentials.filter(credential => credential.credentialSubject.type === standardsGaiaX.GaiaXTypes.DataResource);
1687
1714
  if (core.Is.undefined(targetCredential)) {
1688
- throw new core.UnprocessableError(this.CLASS_NAME, "noEvidence");
1715
+ throw new core.UnprocessableError(FederatedCatalogueService.CLASS_NAME, "noEvidence");
1689
1716
  }
1690
1717
  await this.checkParticipantExists(targetCredential.issuer);
1691
- const dataSpaceConnectorEntry = this.extractDataSpaceConnectorEntry(complianceCredential, result.credentials[0]);
1718
+ const { dataSpaceConnectorEntry, extraData } = this.extractDataSpaceConnectorEntry(complianceCredential, result.credentials[0]);
1692
1719
  const theEntry = core.ObjectHelper.omit(dataSpaceConnectorEntry, FederatedCatalogueService._FIELDS_TO_SKIP);
1693
- await this._entityStorageDataSpaceConnectors.set(theEntry);
1720
+ const extended = theEntry;
1721
+ extended.extraData = extraData;
1722
+ await this._entityStorageDataSpaceConnectors.set(extended);
1694
1723
  for (const dataResourceCredential of dataResourceCredentials) {
1695
1724
  await this.checkParticipantExists(dataResourceCredential.issuer);
1696
- const dataResourceEntry = this.extractDataResourceEntry(complianceCredential, dataResourceCredential);
1697
- const drEntry = core.ObjectHelper.omit(dataResourceEntry, FederatedCatalogueService._FIELDS_TO_SKIP);
1698
- await this._entityStorageDataResources.set(drEntry);
1725
+ const { dataResourceEntry, extraData: extraDataResourceData } = this.extractDataResourceEntry(complianceCredential, dataResourceCredential);
1726
+ const finalDataResourceEntry = core.ObjectHelper.omit(dataResourceEntry, FederatedCatalogueService._FIELDS_TO_SKIP);
1727
+ const extendedDataResourceEntry = finalDataResourceEntry;
1728
+ extendedDataResourceEntry.extraData = extraDataResourceData;
1729
+ await this._entityStorageDataResources.set(extendedDataResourceEntry);
1699
1730
  }
1700
1731
  await this._logging?.log({
1701
1732
  level: "info",
1702
- source: this.CLASS_NAME,
1733
+ source: FederatedCatalogueService.CLASS_NAME,
1703
1734
  ts: Date.now(),
1704
1735
  message: "complianceCredentialVerified",
1705
1736
  data: {
@@ -1715,36 +1746,38 @@ class FederatedCatalogueService {
1715
1746
  * @returns The list of Data Resources created.
1716
1747
  */
1717
1748
  async registerDataResourceCredential(credentialJwt) {
1718
- core.Guards.string(this.CLASS_NAME, "credentialJwt", credentialJwt);
1749
+ core.Guards.string(FederatedCatalogueService.CLASS_NAME, "credentialJwt", credentialJwt);
1719
1750
  const complianceCredential = await this.decodeJwt(credentialJwt);
1720
1751
  const result = await this._complianceCredentialVerifier.verify(complianceCredential);
1721
1752
  if (!result.verified) {
1722
1753
  this._logging?.log({
1723
1754
  level: "error",
1724
- source: this.CLASS_NAME,
1755
+ source: FederatedCatalogueService.CLASS_NAME,
1725
1756
  ts: Date.now(),
1726
1757
  message: "complianceCredentialNotVerified",
1727
1758
  data: { result }
1728
1759
  });
1729
- throw new core.UnprocessableError(this.CLASS_NAME, "complianceCredentialNotVerified", {
1760
+ throw new core.UnprocessableError(FederatedCatalogueService.CLASS_NAME, "complianceCredentialNotVerified", {
1730
1761
  reason: result.verificationFailureReason
1731
1762
  });
1732
1763
  }
1733
1764
  const dataResourceCredentials = result.credentials.filter(credential => credential.credentialSubject.type === standardsGaiaX.GaiaXTypes.DataResource);
1734
1765
  if (dataResourceCredentials.length === 0) {
1735
- throw new core.UnprocessableError(this.CLASS_NAME, "noEvidence");
1766
+ throw new core.UnprocessableError(FederatedCatalogueService.CLASS_NAME, "noEvidence");
1736
1767
  }
1737
1768
  const dataResourceIds = [];
1738
1769
  for (const dataResourceCredential of dataResourceCredentials) {
1739
1770
  await this.checkParticipantExists(dataResourceCredential.issuer);
1740
- const dataResourceEntry = this.extractDataResourceEntry(complianceCredential, dataResourceCredential);
1771
+ const { dataResourceEntry, extraData } = this.extractDataResourceEntry(complianceCredential, dataResourceCredential);
1741
1772
  const theEntry = core.ObjectHelper.omit(dataResourceEntry, FederatedCatalogueService._FIELDS_TO_SKIP);
1742
- await this._entityStorageDataResources.set(theEntry);
1773
+ const extended = theEntry;
1774
+ extended.extraData = extraData;
1775
+ await this._entityStorageDataResources.set(extended);
1743
1776
  dataResourceIds.push(dataResourceEntry.id);
1744
1777
  }
1745
1778
  await this._logging?.log({
1746
1779
  level: "info",
1747
- source: this.CLASS_NAME,
1780
+ source: FederatedCatalogueService.CLASS_NAME,
1748
1781
  ts: Date.now(),
1749
1782
  message: "complianceCredentialVerified",
1750
1783
  data: {
@@ -1758,13 +1791,13 @@ class FederatedCatalogueService {
1758
1791
  * Query the federated catalogue.
1759
1792
  * @param id The identity of the participant.
1760
1793
  * @param maintainer The DS Connector maintainer.
1761
- * @param cursor The cursor to request the next page of entities.
1762
- * @param pageSize The maximum number of entities in a page.
1794
+ * @param cursor The cursor to request the next chunk of entities.
1795
+ * @param limit Limit the number of entities to return.
1763
1796
  * @returns All the entities for the storage matching the conditions,
1764
1797
  * and a cursor which can be used to request more entities.
1765
1798
  * @throws NotImplementedError if the implementation does not support retrieval.
1766
1799
  */
1767
- async queryDataSpaceConnectors(id, maintainer, cursor, pageSize) {
1800
+ async queryDataSpaceConnectors(id, maintainer, cursor, limit) {
1768
1801
  const conditions = [];
1769
1802
  if (core.Is.stringValue(id)) {
1770
1803
  const condition = {
@@ -1782,7 +1815,7 @@ class FederatedCatalogueService {
1782
1815
  };
1783
1816
  conditions.push(condition);
1784
1817
  }
1785
- const entries = await this._entityStorageDataSpaceConnectors.query({ conditions }, undefined, undefined, cursor, pageSize);
1818
+ const entries = await this._entityStorageDataSpaceConnectors.query({ conditions }, undefined, undefined, cursor, limit);
1786
1819
  const itemList = entries.entities.map(entry => {
1787
1820
  entry.type = [
1788
1821
  standardsGaiaX.GaiaXTypes.DataExchangeComponent,
@@ -1790,10 +1823,11 @@ class FederatedCatalogueService {
1790
1823
  ];
1791
1824
  return entry;
1792
1825
  });
1826
+ const { finalItemList, extraDataLdContext } = this.normalizeExtraData(itemList);
1793
1827
  const result = {
1794
- "@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST,
1828
+ "@context": dataJsonLd.JsonLdProcessor.combineContexts(federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST, extraDataLdContext),
1795
1829
  type: standardsSchemaOrg.SchemaOrgTypes.ItemList,
1796
- itemListElement: itemList,
1830
+ itemListElement: finalItemList,
1797
1831
  nextItem: entries.cursor
1798
1832
  };
1799
1833
  return dataJsonLd.JsonLdProcessor.compact(result, result["@context"]);
@@ -1804,44 +1838,48 @@ class FederatedCatalogueService {
1804
1838
  * @returns Nothing.
1805
1839
  */
1806
1840
  async registerServiceOfferingCredential(credentialJwt) {
1807
- core.Guards.string(this.CLASS_NAME, "credentialJwt", credentialJwt);
1841
+ core.Guards.string(FederatedCatalogueService.CLASS_NAME, "credentialJwt", credentialJwt);
1808
1842
  // This will raise exceptions as it has been coded reusing code from Gaia-X
1809
1843
  const sdComplianceCredential = await this.decodeJwt(credentialJwt);
1810
1844
  const result = await this._complianceCredentialVerifier.verify(sdComplianceCredential);
1811
1845
  if (!result.verified) {
1812
1846
  this._logging?.log({
1813
1847
  level: "error",
1814
- source: this.CLASS_NAME,
1848
+ source: FederatedCatalogueService.CLASS_NAME,
1815
1849
  ts: Date.now(),
1816
1850
  message: "complianceCredentialNotVerified",
1817
1851
  data: { result }
1818
1852
  });
1819
- throw new core.UnprocessableError(this.CLASS_NAME, "complianceCredentialNotVerified", {
1853
+ throw new core.UnprocessableError(FederatedCatalogueService.CLASS_NAME, "complianceCredentialNotVerified", {
1820
1854
  reason: result.verificationFailureReason
1821
1855
  });
1822
1856
  }
1823
1857
  const serviceOfferingCredentials = result.credentials.filter(credential => credential.credentialSubject.type === standardsGaiaX.GaiaXTypes.ServiceOffering);
1824
1858
  const dataResourceCredentials = result.credentials.filter(credential => credential.credentialSubject.type === standardsGaiaX.GaiaXTypes.DataResource);
1825
1859
  if (serviceOfferingCredentials.length === 0) {
1826
- throw new core.UnprocessableError(this.CLASS_NAME, "noEvidence");
1860
+ throw new core.UnprocessableError(FederatedCatalogueService.CLASS_NAME, "noEvidence");
1827
1861
  }
1828
1862
  const serviceOfferingIds = [];
1829
1863
  for (const serviceOfferingCredential of serviceOfferingCredentials) {
1830
1864
  const serviceIssuer = serviceOfferingCredential.issuer;
1831
1865
  await this.checkParticipantExists(serviceIssuer);
1832
- const serviceOfferingEntry = this.extractServiceOfferingEntry(sdComplianceCredential, serviceOfferingCredential);
1866
+ const { serviceOfferingEntry, extraData } = this.extractServiceOfferingEntry(sdComplianceCredential, serviceOfferingCredential);
1833
1867
  const theEntry = core.ObjectHelper.omit(serviceOfferingEntry, FederatedCatalogueService._FIELDS_TO_SKIP);
1834
- await this._entityStorageServiceOfferings.set(theEntry);
1868
+ const extended = theEntry;
1869
+ extended.extraData = extraData;
1870
+ await this._entityStorageServiceOfferings.set(extended);
1835
1871
  serviceOfferingIds.push(serviceOfferingEntry.id);
1836
1872
  }
1837
1873
  for (const dataResourceCredential of dataResourceCredentials) {
1838
1874
  await this.checkParticipantExists(dataResourceCredential.issuer);
1839
- const dataResourceEntry = this.extractDataResourceEntry(sdComplianceCredential, dataResourceCredential);
1840
- await this._entityStorageDataResources.set(dataResourceEntry);
1875
+ const { dataResourceEntry, extraData } = this.extractDataResourceEntry(sdComplianceCredential, dataResourceCredential);
1876
+ const extended = core.ObjectHelper.omit(dataResourceEntry, FederatedCatalogueService._FIELDS_TO_SKIP);
1877
+ extended.extraData = extraData;
1878
+ await this._entityStorageDataResources.set(extended);
1841
1879
  }
1842
1880
  await this._logging?.log({
1843
1881
  level: "info",
1844
- source: this.CLASS_NAME,
1882
+ source: FederatedCatalogueService.CLASS_NAME,
1845
1883
  ts: Date.now(),
1846
1884
  message: "complianceCredentialVerified",
1847
1885
  data: {
@@ -1855,13 +1893,13 @@ class FederatedCatalogueService {
1855
1893
  * Query the federated catalogue.
1856
1894
  * @param id Service Id.
1857
1895
  * @param providedBy The identity of the participant.
1858
- * @param cursor The cursor to request the next page of entities.
1859
- * @param pageSize The maximum number of entities in a page.
1896
+ * @param cursor The cursor to request the next chunk of entities.
1897
+ * @param limit Limit the number of entities to return.
1860
1898
  * @returns All the entities for the storage matching the conditions,
1861
1899
  * and a cursor which can be used to request more entities.
1862
1900
  * @throws NotImplementedError if the implementation does not support retrieval.
1863
1901
  */
1864
- async queryServiceOfferings(id, providedBy, cursor, pageSize) {
1902
+ async queryServiceOfferings(id, providedBy, cursor, limit) {
1865
1903
  const conditions = [];
1866
1904
  if (core.Is.stringValue(providedBy)) {
1867
1905
  const condition = {
@@ -1879,15 +1917,16 @@ class FederatedCatalogueService {
1879
1917
  };
1880
1918
  conditions.push(condition);
1881
1919
  }
1882
- const entries = await this._entityStorageServiceOfferings.query({ conditions }, undefined, undefined, cursor, pageSize);
1920
+ const entries = await this._entityStorageServiceOfferings.query({ conditions }, undefined, undefined, cursor, limit);
1883
1921
  const itemList = entries.entities.map(entry => {
1884
1922
  entry.type = standardsGaiaX.GaiaXTypes.ServiceOffering;
1885
1923
  return entry;
1886
1924
  });
1925
+ const { finalItemList, extraDataLdContext } = this.normalizeExtraData(itemList);
1887
1926
  const result = {
1888
- "@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST,
1927
+ "@context": dataJsonLd.JsonLdProcessor.combineContexts(federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST, extraDataLdContext),
1889
1928
  type: standardsSchemaOrg.SchemaOrgTypes.ItemList,
1890
- itemListElement: itemList,
1929
+ itemListElement: finalItemList,
1891
1930
  nextItem: entries.cursor
1892
1931
  };
1893
1932
  return dataJsonLd.JsonLdProcessor.compact(result, result["@context"]);
@@ -1896,13 +1935,13 @@ class FederatedCatalogueService {
1896
1935
  * Query the federated catalogue.
1897
1936
  * @param id The identity of the DataResource.
1898
1937
  * @param producedBy The identity of the participant.
1899
- * @param cursor The cursor to request the next page of entities.
1900
- * @param pageSize The maximum number of entities in a page.
1938
+ * @param cursor The cursor to request the next chunk of entities.
1939
+ * @param limit Limit the number of entities to return.
1901
1940
  * @returns All the entities for the storage matching the conditions,
1902
1941
  * and a cursor which can be used to request more entities.
1903
1942
  * @throws NotImplementedError if the implementation does not support retrieval.
1904
1943
  */
1905
- async queryDataResources(id, producedBy, cursor, pageSize) {
1944
+ async queryDataResources(id, producedBy, cursor, limit) {
1906
1945
  const conditions = [];
1907
1946
  if (core.Is.stringValue(producedBy)) {
1908
1947
  const condition = {
@@ -1920,23 +1959,44 @@ class FederatedCatalogueService {
1920
1959
  };
1921
1960
  conditions.push(condition);
1922
1961
  }
1923
- const entries = await this._entityStorageDataResources.query({ conditions }, undefined, undefined, cursor, pageSize);
1962
+ const entries = await this._entityStorageDataResources.query({ conditions }, undefined, undefined, cursor, limit);
1924
1963
  const itemList = entries.entities.map(entry => {
1925
1964
  entry.type = standardsGaiaX.GaiaXTypes.DataResource;
1926
1965
  return entry;
1927
1966
  });
1967
+ const { finalItemList, extraDataLdContext } = this.normalizeExtraData(itemList);
1928
1968
  const result = {
1929
- "@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST,
1969
+ "@context": dataJsonLd.JsonLdProcessor.combineContexts(federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST, extraDataLdContext),
1930
1970
  type: standardsSchemaOrg.SchemaOrgTypes.ItemList,
1931
- itemListElement: itemList,
1971
+ itemListElement: finalItemList,
1932
1972
  nextItem: entries.cursor
1933
1973
  };
1934
1974
  return dataJsonLd.JsonLdProcessor.compact(result, result["@context"]);
1935
1975
  }
1976
+ /**
1977
+ * Normalizes the extra data adding it to each entry.
1978
+ * @param itemList The item list.
1979
+ * @returns the final item list plus the additional LD Context
1980
+ * @internal
1981
+ */
1982
+ normalizeExtraData(itemList) {
1983
+ let extraDataLdContext;
1984
+ const finalItemList = itemList.map(entry => {
1985
+ const extraData = core.ObjectHelper.extractProperty(entry, "extraData", true);
1986
+ if (!core.Is.undefined(extraData?.["@context"])) {
1987
+ const ldContext = extraData["@context"];
1988
+ extraDataLdContext = dataJsonLd.JsonLdProcessor.combineContexts(extraDataLdContext, ldContext);
1989
+ return core.ObjectHelper.merge(entry, extraData);
1990
+ }
1991
+ return entry;
1992
+ });
1993
+ return { finalItemList, extraDataLdContext };
1994
+ }
1936
1995
  /**
1937
1996
  * Decodes the JWT.
1938
1997
  * @param jwt JWT.
1939
1998
  * @returns Decoded.
1999
+ * @internal
1940
2000
  */
1941
2001
  async decodeJwt(jwt) {
1942
2002
  const { payload } = await identityModels.VerificationHelper.verifyJwt(this._resolver, jwt);
@@ -1946,6 +2006,7 @@ class FederatedCatalogueService {
1946
2006
  * Returns the trusted Issuer id.
1947
2007
  * @param complianceCredential The compliance credential.
1948
2008
  * @returns The trusted issuer.
2009
+ * @internal
1949
2010
  */
1950
2011
  getTrustedIssuerId(complianceCredential) {
1951
2012
  const trustedIssuerId = core.Is.object(complianceCredential.issuer)
@@ -1958,16 +2019,18 @@ class FederatedCatalogueService {
1958
2019
  * @param complianceCredential Compliance credential
1959
2020
  * @param participantCredential The Participant credential extracted.
1960
2021
  * @returns Participant Entry to be saved on the Database.
2022
+ * @internal
1961
2023
  */
1962
2024
  extractParticipantEntry(complianceCredential, participantCredential) {
1963
2025
  const participantData = participantCredential.credentialSubject;
1964
- core.Guards.objectValue(this.CLASS_NAME, "participantData", participantData);
2026
+ core.Guards.objectValue(FederatedCatalogueService.CLASS_NAME, "participantData", participantData);
1965
2027
  const evidences = [];
1966
2028
  for (const evidence of complianceCredential.evidence) {
1967
2029
  evidences.push(evidence.id);
1968
2030
  }
2031
+ const { data, extraData } = this.extractExtraData(participantData, entity.EntitySchemaFactory.get("ParticipantEntry"));
1969
2032
  const result = {
1970
- ...participantData,
2033
+ ...data,
1971
2034
  "@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY,
1972
2035
  issuer: this.getTrustedIssuerId(complianceCredential),
1973
2036
  validFrom: complianceCredential.validFrom,
@@ -1975,18 +2038,20 @@ class FederatedCatalogueService {
1975
2038
  dateCreated: new Date().toISOString(),
1976
2039
  evidence: evidences
1977
2040
  };
1978
- return result;
2041
+ return { participantEntry: result, extraData };
1979
2042
  }
1980
2043
  /**
1981
2044
  * Extracts Data Space Connector description entry from the credentials.
1982
2045
  * @param complianceCredential Compliance Credential.
1983
2046
  * @param dataSpaceConnectorCredential Evidence Credential.
1984
2047
  * @returns Service Description Entry to be saved on the Database.
2048
+ * @internal
1985
2049
  */
1986
2050
  extractDataSpaceConnectorEntry(complianceCredential, dataSpaceConnectorCredential) {
1987
2051
  const credentialData = dataSpaceConnectorCredential.credentialSubject;
1988
- core.Guards.objectValue(this.CLASS_NAME, "credentialData", credentialData);
1989
- const { offeredResource, ...deStructuredData } = credentialData;
2052
+ core.Guards.objectValue(FederatedCatalogueService.CLASS_NAME, "credentialData", credentialData);
2053
+ const { extraData, data } = this.extractExtraData(credentialData, entity.EntitySchemaFactory.get("DataSpaceConnectorEntry"));
2054
+ const { offeredResource, ...deStructuredData } = data;
1990
2055
  const result = {
1991
2056
  ...deStructuredData,
1992
2057
  "@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY,
@@ -1997,18 +2062,20 @@ class FederatedCatalogueService {
1997
2062
  dateCreated: new Date().toISOString(),
1998
2063
  evidence: [dataSpaceConnectorCredential.id]
1999
2064
  };
2000
- return result;
2065
+ return { dataSpaceConnectorEntry: result, extraData };
2001
2066
  }
2002
2067
  /**
2003
2068
  * Extracts service offering entry from the credentials.
2004
2069
  * @param complianceCredential The Compliance Credential.
2005
2070
  * @param serviceOfferingCredential Service Offering credential (evidence).
2006
2071
  * @returns Service Offering Entry to be saved on the Database.
2072
+ * @internal
2007
2073
  */
2008
2074
  extractServiceOfferingEntry(complianceCredential, serviceOfferingCredential) {
2009
2075
  const credentialData = serviceOfferingCredential.credentialSubject;
2010
- core.Guards.objectValue(this.CLASS_NAME, "credentialData", credentialData);
2011
- const { providedBy, aggregationOfResources, servicePolicy, ...deStructuredData } = credentialData;
2076
+ core.Guards.objectValue(FederatedCatalogueService.CLASS_NAME, "credentialData", credentialData);
2077
+ const { data, extraData } = this.extractExtraData(credentialData, entity.EntitySchemaFactory.get("ServiceOfferingEntry"));
2078
+ const { providedBy, aggregationOfResources, servicePolicy, ...deStructuredData } = data;
2012
2079
  const result = {
2013
2080
  ...deStructuredData,
2014
2081
  "@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY,
@@ -2021,18 +2088,20 @@ class FederatedCatalogueService {
2021
2088
  evidence: [serviceOfferingCredential.id],
2022
2089
  servicePolicy: core.ArrayHelper.fromObjectOrArray(servicePolicy)
2023
2090
  };
2024
- return result;
2091
+ return { serviceOfferingEntry: result, extraData };
2025
2092
  }
2026
2093
  /**
2027
2094
  * Extracts data resource entry from the credentials.
2028
2095
  * @param complianceCredential The Compliance Credential.
2029
2096
  * @param dataResourceCredential Data Resource credential.
2030
2097
  * @returns DataResource Entry to be saved on the Database.
2098
+ * @internal
2031
2099
  */
2032
2100
  extractDataResourceEntry(complianceCredential, dataResourceCredential) {
2033
2101
  const credentialData = dataResourceCredential.credentialSubject;
2034
- core.Guards.objectValue(this.CLASS_NAME, "credentialData", credentialData);
2035
- const { producedBy, copyrightOwnedBy, exposedThrough, resourcePolicy, ...deStructuredData } = credentialData;
2102
+ core.Guards.objectValue(FederatedCatalogueService.CLASS_NAME, "credentialData", credentialData);
2103
+ const { data, extraData } = this.extractExtraData(credentialData, entity.EntitySchemaFactory.get("DataResourceEntry"));
2104
+ const { producedBy, copyrightOwnedBy, exposedThrough, resourcePolicy, ...deStructuredData } = data;
2036
2105
  let producedByValue = producedBy;
2037
2106
  if (core.Is.object(producedByValue)) {
2038
2107
  producedByValue = producedByValue.id;
@@ -2054,27 +2123,50 @@ class FederatedCatalogueService {
2054
2123
  evidence: [dataResourceCredential.id],
2055
2124
  resourcePolicy: core.ArrayHelper.fromObjectOrArray(resourcePolicy)
2056
2125
  };
2057
- return result;
2126
+ return { dataResourceEntry: result, extraData };
2058
2127
  }
2059
2128
  /**
2060
2129
  * Checks whether the Participant exists.
2061
2130
  * @param participantId The Participant identifier
2131
+ * @internal
2062
2132
  */
2063
2133
  async checkParticipantExists(participantId) {
2064
2134
  const participantData = await this._entityStorageParticipants.get(participantId);
2065
2135
  if (!participantData) {
2066
2136
  this._logging?.log({
2067
2137
  level: "error",
2068
- source: this.CLASS_NAME,
2138
+ source: FederatedCatalogueService.CLASS_NAME,
2069
2139
  ts: Date.now(),
2070
2140
  message: "providerIsNotParticipant",
2071
2141
  data: { providedBy: participantId }
2072
2142
  });
2073
- throw new core.UnprocessableError(this.CLASS_NAME, "providerIsNotParticipant", {
2143
+ throw new core.UnprocessableError(FederatedCatalogueService.CLASS_NAME, "providerIsNotParticipant", {
2074
2144
  providedBy: participantId
2075
2145
  });
2076
2146
  }
2077
2147
  }
2148
+ /**
2149
+ * Extracts extra data from an object.
2150
+ * @param originalData The original data to extract from
2151
+ * @param schema The entity storage that is used to store
2152
+ * @returns The extraData and the data.
2153
+ * @internal
2154
+ */
2155
+ extractExtraData(originalData, schema) {
2156
+ const entityProperties = schema.properties ?? [];
2157
+ // Type and @context is also an extra known property
2158
+ const knownProperties = entityProperties.map(property => property.property).concat(["type", "@context"]);
2159
+ const splitObjects = core.ObjectHelper.split(originalData, knownProperties);
2160
+ return {
2161
+ data: splitObjects.picked,
2162
+ extraData: core.Is.objectValue(splitObjects.omitted)
2163
+ ? {
2164
+ "@context": originalData["@context"],
2165
+ ...splitObjects.omitted
2166
+ }
2167
+ : undefined
2168
+ };
2169
+ }
2078
2170
  }
2079
2171
 
2080
2172
  const restEntryPoints = [