@startinblox/core 2.0.6-beta.5 → 2.0.6-beta.7
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.
|
@@ -278,12 +278,13 @@ let __tla = (async () => {
|
|
|
278
278
|
protocol: "dataspace-protocol-http",
|
|
279
279
|
policy: {
|
|
280
280
|
"@context": "http://www.w3.org/ns/odrl.jsonld",
|
|
281
|
-
|
|
282
|
-
"@type": "Offer",
|
|
283
|
-
assigner: counterPartyId || "provider",
|
|
281
|
+
...policy,
|
|
282
|
+
"@type": policy["@type"] || "Offer",
|
|
283
|
+
assigner: policy.assigner || counterPartyId || "provider",
|
|
284
284
|
target: policy.target
|
|
285
285
|
}
|
|
286
286
|
};
|
|
287
|
+
console.log("[DataspaceConnectorStore] Contract negotiation request:", JSON.stringify(negotiationRequest, null, 2));
|
|
287
288
|
const response = await this.fetchAuthn(this.config.contractNegotiationEndpoint, {
|
|
288
289
|
method: "POST",
|
|
289
290
|
headers: this.headers,
|
|
@@ -589,6 +590,86 @@ let __tla = (async () => {
|
|
|
589
590
|
}
|
|
590
591
|
return await this.fetchWithEDRToken(edrDataAddress, additionalPath);
|
|
591
592
|
}
|
|
593
|
+
async fetchProtectedResource(resourceUrl, consumerParticipantId, providerConnectorUrl, existingAgreementId, maxNegotiationRetries = 30, negotiationRetryDelay = 2e3) {
|
|
594
|
+
console.log(`\u{1F510} Requesting protected resource: ${resourceUrl}`);
|
|
595
|
+
if (existingAgreementId) {
|
|
596
|
+
console.log(`\u{1F4DC} Using existing agreement: ${existingAgreementId}`);
|
|
597
|
+
return await this._fetchWithAgreement(resourceUrl, consumerParticipantId, providerConnectorUrl, existingAgreementId);
|
|
598
|
+
}
|
|
599
|
+
const initialResponse = await fetch(resourceUrl, {
|
|
600
|
+
method: "GET",
|
|
601
|
+
headers: {
|
|
602
|
+
"DSP-PARTICIPANT-ID": consumerParticipantId,
|
|
603
|
+
"DSP-CONSUMER-CONNECTORURL": providerConnectorUrl,
|
|
604
|
+
Accept: "application/json"
|
|
605
|
+
},
|
|
606
|
+
mode: "cors"
|
|
607
|
+
});
|
|
608
|
+
if (initialResponse.ok) {
|
|
609
|
+
const data = await initialResponse.json();
|
|
610
|
+
console.log("\u2705 Resource accessed successfully (no agreement required)");
|
|
611
|
+
return data;
|
|
612
|
+
}
|
|
613
|
+
if (initialResponse.status !== 449) {
|
|
614
|
+
const errorText = await initialResponse.text();
|
|
615
|
+
throw new Error(`Unexpected response: ${initialResponse.status} ${initialResponse.statusText} - ${errorText}`);
|
|
616
|
+
}
|
|
617
|
+
const agreementId = await this._handlePolicyDiscovery(initialResponse, providerConnectorUrl, maxNegotiationRetries, negotiationRetryDelay);
|
|
618
|
+
console.log("\u{1F504} Retrying resource request with agreement...");
|
|
619
|
+
return await this._fetchWithAgreement(resourceUrl, consumerParticipantId, providerConnectorUrl, agreementId);
|
|
620
|
+
}
|
|
621
|
+
async _handlePolicyDiscovery(initialResponse, providerConnectorUrl, maxNegotiationRetries, negotiationRetryDelay) {
|
|
622
|
+
console.log("\u{1F4CB} Contract negotiation required (449 response)");
|
|
623
|
+
const errorResponse = await initialResponse.json();
|
|
624
|
+
const suggestedPolicies = errorResponse.suggested_policies;
|
|
625
|
+
if (!suggestedPolicies || suggestedPolicies.length === 0) {
|
|
626
|
+
throw new Error("No suggested policies returned in 449 response");
|
|
627
|
+
}
|
|
628
|
+
const bestPolicy = suggestedPolicies.reduce((best, current) => {
|
|
629
|
+
return current.openness_score > best.openness_score ? current : best;
|
|
630
|
+
});
|
|
631
|
+
console.log(`\u{1F4DC} Selected policy: ${bestPolicy.policy_id} (openness: ${bestPolicy.openness_score})`);
|
|
632
|
+
console.log("\u{1F91D} Initiating contract negotiation...");
|
|
633
|
+
const negotiationId = await this.negotiateContract(providerConnectorUrl, errorResponse.asset_id, bestPolicy.policy, errorResponse.participant_id);
|
|
634
|
+
console.log(`\u{1F4DD} Negotiation initiated: ${negotiationId}`);
|
|
635
|
+
for (let attempt = 1; attempt <= maxNegotiationRetries; attempt++) {
|
|
636
|
+
await new Promise((resolve) => setTimeout(resolve, negotiationRetryDelay));
|
|
637
|
+
const status = await this._getNegotiationStatus(negotiationId);
|
|
638
|
+
console.log(`\u23F3 Negotiation status (${attempt}/${maxNegotiationRetries}): ${status.state}`);
|
|
639
|
+
if (status.state === "FINALIZED") {
|
|
640
|
+
const agreement = await this.getContractAgreement(negotiationId);
|
|
641
|
+
if (!agreement) {
|
|
642
|
+
throw new Error(`Failed to retrieve contract agreement for negotiation ${negotiationId}`);
|
|
643
|
+
}
|
|
644
|
+
console.log(`\u2705 Agreement obtained: ${agreement["@id"]}`);
|
|
645
|
+
return agreement["@id"];
|
|
646
|
+
}
|
|
647
|
+
if (status.state === "TERMINATED") {
|
|
648
|
+
throw new Error(`Negotiation terminated: ${status.errorDetail || "Unknown reason"}`);
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
throw new Error(`Negotiation ${negotiationId} failed or timed out after ${maxNegotiationRetries} attempts`);
|
|
652
|
+
}
|
|
653
|
+
async _fetchWithAgreement(resourceUrl, consumerParticipantId, providerConnectorUrl, agreementId) {
|
|
654
|
+
console.log(`\u{1F510} Requesting protected resource: ${resourceUrl} (with agreement)`);
|
|
655
|
+
const response = await fetch(resourceUrl, {
|
|
656
|
+
method: "GET",
|
|
657
|
+
headers: {
|
|
658
|
+
"DSP-PARTICIPANT-ID": consumerParticipantId,
|
|
659
|
+
"DSP-CONSUMER-CONNECTORURL": providerConnectorUrl,
|
|
660
|
+
"DSP-AGREEMENT-ID": agreementId,
|
|
661
|
+
Accept: "application/json"
|
|
662
|
+
},
|
|
663
|
+
mode: "cors"
|
|
664
|
+
});
|
|
665
|
+
if (!response.ok) {
|
|
666
|
+
const errorText = await response.text();
|
|
667
|
+
throw new Error(`Failed to access protected resource: ${response.status} ${response.statusText} - ${errorText}`);
|
|
668
|
+
}
|
|
669
|
+
const data = await response.json();
|
|
670
|
+
console.log("\u2705 Resource accessed successfully");
|
|
671
|
+
return data;
|
|
672
|
+
}
|
|
592
673
|
async fetchThroughDataspace(resourceId) {
|
|
593
674
|
try {
|
|
594
675
|
const catalog = await this.getCatalog();
|
|
@@ -1273,6 +1354,190 @@ let __tla = (async () => {
|
|
|
1273
1354
|
};
|
|
1274
1355
|
__publicField(_DataspaceConnectorStoreAdapter, "store");
|
|
1275
1356
|
let DataspaceConnectorStoreAdapter = _DataspaceConnectorStoreAdapter;
|
|
1357
|
+
const _LocalStorageCacheMetadataManager = class _LocalStorageCacheMetadataManager {
|
|
1358
|
+
constructor(endpoint, ttlMs = _LocalStorageCacheMetadataManager.DEFAULT_TTL_MS) {
|
|
1359
|
+
this.endpoint = endpoint;
|
|
1360
|
+
this.ttlMs = ttlMs;
|
|
1361
|
+
this.cleanupOldCacheFormat();
|
|
1362
|
+
}
|
|
1363
|
+
cleanupOldCacheFormat() {
|
|
1364
|
+
try {
|
|
1365
|
+
const endpointHash = this.endpoint.replace(/[^a-zA-Z0-9]/g, "");
|
|
1366
|
+
const oldKey = `fc-cache-meta-${endpointHash}`;
|
|
1367
|
+
if (localStorage.getItem(oldKey)) {
|
|
1368
|
+
localStorage.removeItem(oldKey);
|
|
1369
|
+
}
|
|
1370
|
+
} catch (error2) {
|
|
1371
|
+
console.warn("[LocalStorageCache] Error cleaning up old cache format:", error2);
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
getStorageKey() {
|
|
1375
|
+
const endpointHash = this.endpoint.replace(/[^a-zA-Z0-9]/g, "");
|
|
1376
|
+
return `${_LocalStorageCacheMetadataManager.STORAGE_KEY_PREFIX}-${endpointHash}`;
|
|
1377
|
+
}
|
|
1378
|
+
getCacheData() {
|
|
1379
|
+
try {
|
|
1380
|
+
const key = this.getStorageKey();
|
|
1381
|
+
const data = localStorage.getItem(key);
|
|
1382
|
+
if (!data) {
|
|
1383
|
+
return null;
|
|
1384
|
+
}
|
|
1385
|
+
const parsed = JSON.parse(data);
|
|
1386
|
+
const items = /* @__PURE__ */ new Map();
|
|
1387
|
+
if (parsed.items) {
|
|
1388
|
+
for (const [hash, metadata] of Object.entries(parsed.items)) {
|
|
1389
|
+
items.set(hash, metadata);
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
return {
|
|
1393
|
+
version: parsed.version,
|
|
1394
|
+
lastFetchTimestamp: parsed.lastFetchTimestamp,
|
|
1395
|
+
cacheExpirationTimestamp: parsed.cacheExpirationTimestamp,
|
|
1396
|
+
resource: parsed.resource,
|
|
1397
|
+
items
|
|
1398
|
+
};
|
|
1399
|
+
} catch (error2) {
|
|
1400
|
+
console.error("[LocalStorageCache] Error reading cache data:", error2);
|
|
1401
|
+
return null;
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
getCacheMetadata() {
|
|
1405
|
+
return this.getCacheData();
|
|
1406
|
+
}
|
|
1407
|
+
setCacheData(cacheData) {
|
|
1408
|
+
try {
|
|
1409
|
+
const key = this.getStorageKey();
|
|
1410
|
+
const itemsObj = {};
|
|
1411
|
+
cacheData.items.forEach((value, hash) => {
|
|
1412
|
+
itemsObj[hash] = value;
|
|
1413
|
+
});
|
|
1414
|
+
const data = JSON.stringify({
|
|
1415
|
+
version: cacheData.version,
|
|
1416
|
+
lastFetchTimestamp: cacheData.lastFetchTimestamp,
|
|
1417
|
+
cacheExpirationTimestamp: cacheData.cacheExpirationTimestamp,
|
|
1418
|
+
resource: cacheData.resource,
|
|
1419
|
+
items: itemsObj
|
|
1420
|
+
});
|
|
1421
|
+
localStorage.setItem(key, data);
|
|
1422
|
+
return true;
|
|
1423
|
+
} catch (error2) {
|
|
1424
|
+
console.error("[LocalStorageCache] Error writing cache data:", error2);
|
|
1425
|
+
return false;
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
setCacheMetadata(cacheData) {
|
|
1429
|
+
return this.setCacheData(cacheData);
|
|
1430
|
+
}
|
|
1431
|
+
isCacheValid() {
|
|
1432
|
+
const cacheData = this.getCacheData();
|
|
1433
|
+
if (!cacheData) {
|
|
1434
|
+
return false;
|
|
1435
|
+
}
|
|
1436
|
+
if (cacheData.version !== _LocalStorageCacheMetadataManager.CACHE_VERSION) {
|
|
1437
|
+
console.log("[LocalStorageCache] Cache version mismatch, invalidating");
|
|
1438
|
+
return false;
|
|
1439
|
+
}
|
|
1440
|
+
const now = Date.now();
|
|
1441
|
+
if (now > cacheData.cacheExpirationTimestamp) {
|
|
1442
|
+
console.log("[LocalStorageCache] Cache TTL expired");
|
|
1443
|
+
return false;
|
|
1444
|
+
}
|
|
1445
|
+
return true;
|
|
1446
|
+
}
|
|
1447
|
+
getResource() {
|
|
1448
|
+
const cacheData = this.getCacheData();
|
|
1449
|
+
return (cacheData == null ? void 0 : cacheData.resource) || null;
|
|
1450
|
+
}
|
|
1451
|
+
getKnownHashes() {
|
|
1452
|
+
const cacheData = this.getCacheData();
|
|
1453
|
+
if (!cacheData) {
|
|
1454
|
+
return /* @__PURE__ */ new Set();
|
|
1455
|
+
}
|
|
1456
|
+
return new Set(cacheData.items.keys());
|
|
1457
|
+
}
|
|
1458
|
+
getItemMetadata(sdHash) {
|
|
1459
|
+
const cacheData = this.getCacheData();
|
|
1460
|
+
if (!cacheData) {
|
|
1461
|
+
return null;
|
|
1462
|
+
}
|
|
1463
|
+
return cacheData.items.get(sdHash) || null;
|
|
1464
|
+
}
|
|
1465
|
+
updateCache(resource, items) {
|
|
1466
|
+
const now = Date.now();
|
|
1467
|
+
let cacheData = this.getCacheData();
|
|
1468
|
+
if (!cacheData || !this.isCacheValid()) {
|
|
1469
|
+
cacheData = {
|
|
1470
|
+
version: _LocalStorageCacheMetadataManager.CACHE_VERSION,
|
|
1471
|
+
lastFetchTimestamp: now,
|
|
1472
|
+
cacheExpirationTimestamp: now + this.ttlMs,
|
|
1473
|
+
resource,
|
|
1474
|
+
items: /* @__PURE__ */ new Map()
|
|
1475
|
+
};
|
|
1476
|
+
} else {
|
|
1477
|
+
cacheData.resource = resource;
|
|
1478
|
+
}
|
|
1479
|
+
for (const item of items) {
|
|
1480
|
+
cacheData.items.set(item.sdHash, {
|
|
1481
|
+
...item,
|
|
1482
|
+
cachedAt: now
|
|
1483
|
+
});
|
|
1484
|
+
}
|
|
1485
|
+
cacheData.lastFetchTimestamp = now;
|
|
1486
|
+
return this.setCacheData(cacheData);
|
|
1487
|
+
}
|
|
1488
|
+
removeItems(sdHashes) {
|
|
1489
|
+
var _a2;
|
|
1490
|
+
const cacheData = this.getCacheData();
|
|
1491
|
+
if (!cacheData) {
|
|
1492
|
+
return false;
|
|
1493
|
+
}
|
|
1494
|
+
for (const hash of sdHashes) {
|
|
1495
|
+
cacheData.items.delete(hash);
|
|
1496
|
+
}
|
|
1497
|
+
if ((_a2 = cacheData.resource) == null ? void 0 : _a2["ldp:contains"]) {
|
|
1498
|
+
const resourceIdsToRemove = /* @__PURE__ */ new Set();
|
|
1499
|
+
for (const hash of sdHashes) {
|
|
1500
|
+
const meta = cacheData.items.get(hash);
|
|
1501
|
+
if (meta) {
|
|
1502
|
+
resourceIdsToRemove.add(meta.resourceId);
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
cacheData.resource["ldp:contains"] = cacheData.resource["ldp:contains"].filter((item) => !resourceIdsToRemove.has(item["@id"]));
|
|
1506
|
+
}
|
|
1507
|
+
return this.setCacheData(cacheData);
|
|
1508
|
+
}
|
|
1509
|
+
clear() {
|
|
1510
|
+
try {
|
|
1511
|
+
const key = this.getStorageKey();
|
|
1512
|
+
localStorage.removeItem(key);
|
|
1513
|
+
return true;
|
|
1514
|
+
} catch (error2) {
|
|
1515
|
+
console.error("[LocalStorageCache] Error clearing cache data:", error2);
|
|
1516
|
+
return false;
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
getCacheStats() {
|
|
1520
|
+
const cacheData = this.getCacheData();
|
|
1521
|
+
if (!cacheData) {
|
|
1522
|
+
return {
|
|
1523
|
+
itemCount: 0,
|
|
1524
|
+
lastFetch: null,
|
|
1525
|
+
expiresAt: null,
|
|
1526
|
+
isValid: false
|
|
1527
|
+
};
|
|
1528
|
+
}
|
|
1529
|
+
return {
|
|
1530
|
+
itemCount: cacheData.items.size,
|
|
1531
|
+
lastFetch: new Date(cacheData.lastFetchTimestamp),
|
|
1532
|
+
expiresAt: new Date(cacheData.cacheExpirationTimestamp),
|
|
1533
|
+
isValid: this.isCacheValid()
|
|
1534
|
+
};
|
|
1535
|
+
}
|
|
1536
|
+
};
|
|
1537
|
+
__publicField(_LocalStorageCacheMetadataManager, "STORAGE_KEY_PREFIX", "fc-cache-data");
|
|
1538
|
+
__publicField(_LocalStorageCacheMetadataManager, "CACHE_VERSION", "2.0.0");
|
|
1539
|
+
__publicField(_LocalStorageCacheMetadataManager, "DEFAULT_TTL_MS", 2 * 60 * 60 * 1e3);
|
|
1540
|
+
let LocalStorageCacheMetadataManager = _LocalStorageCacheMetadataManager;
|
|
1276
1541
|
class FederatedCatalogueAPIWrapper {
|
|
1277
1542
|
constructor(options, fcBaseUrl) {
|
|
1278
1543
|
__publicField(this, "fcBaseUrl");
|
|
@@ -1400,6 +1665,8 @@ let __tla = (async () => {
|
|
|
1400
1665
|
__publicField(this, "cache");
|
|
1401
1666
|
__publicField(this, "session");
|
|
1402
1667
|
__publicField(this, "fcApi");
|
|
1668
|
+
__publicField(this, "metadataManager");
|
|
1669
|
+
__publicField(this, "enableCaching");
|
|
1403
1670
|
this.cfg = cfg;
|
|
1404
1671
|
if (!this.cfg.login) {
|
|
1405
1672
|
throw new Error("Login must be provided for FederatedCatalogueStore");
|
|
@@ -1414,6 +1681,31 @@ let __tla = (async () => {
|
|
|
1414
1681
|
this.fcApi = null;
|
|
1415
1682
|
}
|
|
1416
1683
|
this.cache = new InMemoryCacheManager();
|
|
1684
|
+
this.enableCaching = this.cfg.enableLocalStorageMetadata === true;
|
|
1685
|
+
if (this.enableCaching && this.cfg.endpoint) {
|
|
1686
|
+
const cacheTTL = this.cfg.cacheTTL || 2 * 60 * 60 * 1e3;
|
|
1687
|
+
this.metadataManager = new LocalStorageCacheMetadataManager(this.cfg.endpoint, cacheTTL);
|
|
1688
|
+
this.handlePageReload();
|
|
1689
|
+
} else {
|
|
1690
|
+
this.metadataManager = null;
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
handlePageReload() {
|
|
1694
|
+
var _a2, _b;
|
|
1695
|
+
try {
|
|
1696
|
+
const SESSION_KEY = "fc-session-id";
|
|
1697
|
+
let sessionId = sessionStorage.getItem(SESSION_KEY);
|
|
1698
|
+
if (!sessionId) {
|
|
1699
|
+
sessionId = `session-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
1700
|
+
sessionStorage.setItem(SESSION_KEY, sessionId);
|
|
1701
|
+
(_a2 = this.metadataManager) == null ? void 0 : _a2.clear();
|
|
1702
|
+
}
|
|
1703
|
+
const stats = (_b = this.metadataManager) == null ? void 0 : _b.getCacheStats();
|
|
1704
|
+
if (stats) {
|
|
1705
|
+
}
|
|
1706
|
+
} catch (error2) {
|
|
1707
|
+
console.warn("[FederatedCatalogueStore] Error handling page reload:", error2);
|
|
1708
|
+
}
|
|
1417
1709
|
}
|
|
1418
1710
|
resolveTargetType(args) {
|
|
1419
1711
|
if (typeof args === "string") return args;
|
|
@@ -1423,27 +1715,178 @@ let __tla = (async () => {
|
|
|
1423
1715
|
return "";
|
|
1424
1716
|
}
|
|
1425
1717
|
async getData(args) {
|
|
1718
|
+
var _a2;
|
|
1426
1719
|
const targetType = this.resolveTargetType(args);
|
|
1427
1720
|
if (!this.fcApi) {
|
|
1428
1721
|
throw new Error("Federated API not initialized, returning empty data.");
|
|
1429
1722
|
}
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1723
|
+
const cacheIsValid = this.enableCaching && ((_a2 = this.metadataManager) == null ? void 0 : _a2.isCacheValid());
|
|
1724
|
+
const hasCached = this.hasCachedData();
|
|
1725
|
+
if (cacheIsValid && hasCached) {
|
|
1726
|
+
return await this.getDeltaUpdatedData(targetType);
|
|
1727
|
+
}
|
|
1728
|
+
if (cacheIsValid && !hasCached && this.metadataManager) {
|
|
1729
|
+
this.metadataManager.clear();
|
|
1730
|
+
}
|
|
1731
|
+
return await this.getFullData(targetType);
|
|
1732
|
+
}
|
|
1733
|
+
hasCachedData() {
|
|
1734
|
+
try {
|
|
1735
|
+
if (!this.metadataManager) {
|
|
1736
|
+
return false;
|
|
1737
|
+
}
|
|
1738
|
+
const resource = this.metadataManager.getResource();
|
|
1739
|
+
const hasResourceData = !!((resource == null ? void 0 : resource["ldp:contains"]) && resource["ldp:contains"].length > 0);
|
|
1740
|
+
const metadataItemCount = this.metadataManager.getCacheStats().itemCount || 0;
|
|
1741
|
+
return hasResourceData && metadataItemCount > 0;
|
|
1742
|
+
} catch (error2) {
|
|
1743
|
+
console.error("[FederatedCatalogueStore] Error checking cached data:", error2);
|
|
1744
|
+
return false;
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
async getDeltaUpdatedData(targetType) {
|
|
1748
|
+
if (!this.fcApi || !this.metadataManager) {
|
|
1749
|
+
return await this.getFullData(targetType);
|
|
1750
|
+
}
|
|
1751
|
+
try {
|
|
1752
|
+
const apiList = await this.fcApi.getAllSelfDescriptions();
|
|
1753
|
+
if (!apiList || !apiList.items) {
|
|
1754
|
+
console.warn("[FederatedCatalogueStore] No items returned from API");
|
|
1755
|
+
return await this.getFullData(targetType);
|
|
1756
|
+
}
|
|
1757
|
+
const resource = this.metadataManager.getResource();
|
|
1758
|
+
if (!resource) {
|
|
1759
|
+
return await this.getFullData(targetType);
|
|
1760
|
+
}
|
|
1761
|
+
if (!resource["@id"]) {
|
|
1762
|
+
resource["@id"] = targetType;
|
|
1763
|
+
}
|
|
1764
|
+
if (!resource["ldp:contains"]) {
|
|
1765
|
+
resource["ldp:contains"] = [];
|
|
1766
|
+
}
|
|
1767
|
+
const knownHashes = this.metadataManager.getKnownHashes();
|
|
1768
|
+
const items = (apiList == null ? void 0 : apiList.items) || [];
|
|
1769
|
+
if (!Array.isArray(items)) {
|
|
1770
|
+
console.warn("[FederatedCatalogueStore] apiList.items is not an array");
|
|
1771
|
+
return resource;
|
|
1772
|
+
}
|
|
1773
|
+
const apiHashes = new Set(items.map((item) => item.meta.sdHash));
|
|
1774
|
+
const newHashes = [];
|
|
1775
|
+
const updatedHashes = [];
|
|
1776
|
+
const deletedHashes = [];
|
|
1777
|
+
for (const item of items) {
|
|
1778
|
+
const hash = item.meta.sdHash;
|
|
1779
|
+
if (!knownHashes.has(hash)) {
|
|
1780
|
+
newHashes.push(hash);
|
|
1781
|
+
} else {
|
|
1782
|
+
const cachedMeta = this.metadataManager.getItemMetadata(hash);
|
|
1783
|
+
if (cachedMeta) {
|
|
1784
|
+
if (item.meta.uploadDatetime > cachedMeta.uploadDatetime || item.meta.statusDatetime > cachedMeta.statusDatetime) {
|
|
1785
|
+
updatedHashes.push(hash);
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
1790
|
+
for (const hash of knownHashes) {
|
|
1791
|
+
if (!apiHashes.has(hash)) {
|
|
1792
|
+
deletedHashes.push(hash);
|
|
1793
|
+
}
|
|
1794
|
+
}
|
|
1795
|
+
const toFetch = [
|
|
1796
|
+
...newHashes,
|
|
1797
|
+
...updatedHashes
|
|
1798
|
+
];
|
|
1799
|
+
const newMetadata = [];
|
|
1800
|
+
if (toFetch.length > 0) {
|
|
1801
|
+
for (const hash of toFetch) {
|
|
1802
|
+
try {
|
|
1803
|
+
const sd = await this.fcApi.getSelfDescriptionByHash(hash);
|
|
1804
|
+
if (sd) {
|
|
1805
|
+
const mappedResource = this.mapSourceToDestination(sd, {
|
|
1806
|
+
temsServiceBase: this.cfg.temsServiceBase,
|
|
1807
|
+
temsCategoryBase: this.cfg.temsCategoryBase,
|
|
1808
|
+
temsImageBase: this.cfg.temsImageBase,
|
|
1809
|
+
temsProviderBase: this.cfg.temsProviderBase
|
|
1810
|
+
});
|
|
1811
|
+
if (updatedHashes.includes(hash)) {
|
|
1812
|
+
const index = resource["ldp:contains"].findIndex((r) => r["@id"] === mappedResource["@id"]);
|
|
1813
|
+
if (index !== -1) {
|
|
1814
|
+
resource["ldp:contains"].splice(index, 1);
|
|
1815
|
+
}
|
|
1816
|
+
}
|
|
1817
|
+
resource["ldp:contains"].push(mappedResource);
|
|
1818
|
+
const apiItem = apiList.items.find((i) => i.meta.sdHash === hash);
|
|
1819
|
+
if (apiItem) {
|
|
1820
|
+
newMetadata.push({
|
|
1821
|
+
sdHash: hash,
|
|
1822
|
+
uploadDatetime: apiItem.meta.uploadDatetime,
|
|
1823
|
+
statusDatetime: apiItem.meta.statusDatetime,
|
|
1824
|
+
cachedAt: Date.now(),
|
|
1825
|
+
resourceId: mappedResource["@id"]
|
|
1826
|
+
});
|
|
1827
|
+
}
|
|
1828
|
+
}
|
|
1829
|
+
} catch (error2) {
|
|
1830
|
+
console.error(`[FederatedCatalogueStore] Error fetching hash ${hash}:`, error2);
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
if (deletedHashes.length > 0) {
|
|
1835
|
+
this.metadataManager.removeItems(deletedHashes);
|
|
1836
|
+
}
|
|
1837
|
+
if (newMetadata.length > 0) {
|
|
1838
|
+
this.metadataManager.updateCache(resource, newMetadata);
|
|
1839
|
+
}
|
|
1840
|
+
document.dispatchEvent(new CustomEvent("save", {
|
|
1841
|
+
detail: {
|
|
1842
|
+
resource: {
|
|
1843
|
+
"@id": resource == null ? void 0 : resource["@id"]
|
|
1844
|
+
}
|
|
1845
|
+
},
|
|
1846
|
+
bubbles: true
|
|
1847
|
+
}));
|
|
1848
|
+
return resource;
|
|
1849
|
+
} catch (error2) {
|
|
1850
|
+
console.error("[FederatedCatalogueStore] Delta update failed, falling back to full fetch:", error2);
|
|
1851
|
+
return await this.getFullData(targetType);
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
async getFullData(targetType) {
|
|
1855
|
+
if (!this.fcApi) {
|
|
1856
|
+
throw new Error("Federated API not initialized");
|
|
1857
|
+
}
|
|
1858
|
+
const resource = await this.initLocalDataSourceContainer(targetType);
|
|
1859
|
+
const dataset2 = await this.fcApi.getAllSelfDescriptions();
|
|
1860
|
+
const newMetadata = [];
|
|
1861
|
+
if ((dataset2 == null ? void 0 : dataset2.items) && Array.isArray(dataset2.items)) {
|
|
1862
|
+
for (const item of dataset2.items) {
|
|
1863
|
+
const sd = await this.fcApi.getSelfDescriptionByHash(item.meta.sdHash);
|
|
1436
1864
|
if (sd) {
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1865
|
+
try {
|
|
1866
|
+
const mappedResource = this.mapSourceToDestination(sd, {
|
|
1867
|
+
temsServiceBase: this.cfg.temsServiceBase,
|
|
1868
|
+
temsCategoryBase: this.cfg.temsCategoryBase,
|
|
1869
|
+
temsImageBase: this.cfg.temsImageBase,
|
|
1870
|
+
temsProviderBase: this.cfg.temsProviderBase
|
|
1871
|
+
});
|
|
1872
|
+
resource["ldp:contains"].push(mappedResource);
|
|
1873
|
+
if (this.enableCaching) {
|
|
1874
|
+
newMetadata.push({
|
|
1875
|
+
sdHash: item.meta.sdHash,
|
|
1876
|
+
uploadDatetime: item.meta.uploadDatetime,
|
|
1877
|
+
statusDatetime: item.meta.statusDatetime,
|
|
1878
|
+
cachedAt: Date.now(),
|
|
1879
|
+
resourceId: mappedResource["@id"]
|
|
1880
|
+
});
|
|
1881
|
+
}
|
|
1882
|
+
} catch (error2) {
|
|
1883
|
+
console.error("[FederatedCatalogueStore] Error mapping resource:", error2);
|
|
1884
|
+
}
|
|
1444
1885
|
}
|
|
1445
1886
|
}
|
|
1446
|
-
|
|
1887
|
+
}
|
|
1888
|
+
if (this.enableCaching && this.metadataManager && newMetadata.length > 0) {
|
|
1889
|
+
this.metadataManager.updateCache(resource, newMetadata);
|
|
1447
1890
|
}
|
|
1448
1891
|
document.dispatchEvent(new CustomEvent("save", {
|
|
1449
1892
|
detail: {
|
|
@@ -1548,8 +1991,39 @@ let __tla = (async () => {
|
|
|
1548
1991
|
bubbles: true
|
|
1549
1992
|
}));
|
|
1550
1993
|
}
|
|
1994
|
+
stripUrnPrefix(id, prefix) {
|
|
1995
|
+
if (id == null ? void 0 : id.startsWith(prefix)) {
|
|
1996
|
+
return id.substring(prefix.length);
|
|
1997
|
+
}
|
|
1998
|
+
return id;
|
|
1999
|
+
}
|
|
2000
|
+
stripTemsUrnFromPolicy(obj) {
|
|
2001
|
+
if (obj === null || obj === void 0) {
|
|
2002
|
+
return obj;
|
|
2003
|
+
}
|
|
2004
|
+
if (typeof obj === "string") {
|
|
2005
|
+
return this.stripUrnPrefix(obj, "urn:tems:");
|
|
2006
|
+
}
|
|
2007
|
+
if (Array.isArray(obj)) {
|
|
2008
|
+
return obj.map((item) => this.stripTemsUrnFromPolicy(item));
|
|
2009
|
+
}
|
|
2010
|
+
if (typeof obj === "object") {
|
|
2011
|
+
const result = {};
|
|
2012
|
+
for (const key in obj) {
|
|
2013
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
2014
|
+
if (key === "@id") {
|
|
2015
|
+
result[key] = this.stripUrnPrefix(obj[key], "urn:tems:");
|
|
2016
|
+
} else {
|
|
2017
|
+
result[key] = this.stripTemsUrnFromPolicy(obj[key]);
|
|
2018
|
+
}
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
2021
|
+
return result;
|
|
2022
|
+
}
|
|
2023
|
+
return obj;
|
|
2024
|
+
}
|
|
1551
2025
|
mapSourceToDestination(src, opts) {
|
|
1552
|
-
var _a2, _b, _c, _d, _e, _f, _g, _h;
|
|
2026
|
+
var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
1553
2027
|
const vc = src.verifiableCredential;
|
|
1554
2028
|
const cs = vc.credentialSubject;
|
|
1555
2029
|
let catInfo;
|
|
@@ -1560,9 +2034,16 @@ let __tla = (async () => {
|
|
|
1560
2034
|
usedKey = "service";
|
|
1561
2035
|
type = "tems:Service";
|
|
1562
2036
|
} else if (cs["dcat:dataset"] && cs["dcat:dataset"].length > 0) {
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
2037
|
+
const dataset2 = cs["dcat:dataset"][0];
|
|
2038
|
+
if (dataset2["dcat:service"]) {
|
|
2039
|
+
catInfo = dataset2["dcat:service"];
|
|
2040
|
+
usedKey = "nested-service";
|
|
2041
|
+
type = "tems:Service";
|
|
2042
|
+
} else {
|
|
2043
|
+
catInfo = dataset2;
|
|
2044
|
+
usedKey = "dataset";
|
|
2045
|
+
type = "tems:DataOffer";
|
|
2046
|
+
}
|
|
1566
2047
|
} else {
|
|
1567
2048
|
throw new Error("Expected either credentialSubject['dcat:service'] or a non-empty array in ['dcat:dataset']");
|
|
1568
2049
|
}
|
|
@@ -1571,7 +2052,7 @@ let __tla = (async () => {
|
|
|
1571
2052
|
const serviceId = `${opts.temsServiceBase}${encodeURIComponent(slug)}/`;
|
|
1572
2053
|
const creation_date = vc.issuanceDate;
|
|
1573
2054
|
const update_date = vc.expirationDate;
|
|
1574
|
-
const name = catInfo["dcterms:title"];
|
|
2055
|
+
const name = catInfo["dcterms:title"] || catInfo["dct:title"];
|
|
1575
2056
|
const description = catInfo["rdfs:comment"];
|
|
1576
2057
|
const keywords = catInfo["dcat:keyword"] || [];
|
|
1577
2058
|
const long_description = keywords.length > 0 ? `Keywords: ${keywords.join(", ")}` : "";
|
|
@@ -1611,19 +2092,24 @@ let __tla = (async () => {
|
|
|
1611
2092
|
const contact_url = catInfo["dcat:endpointDescription"] || "";
|
|
1612
2093
|
const documentation_url = contact_url || "";
|
|
1613
2094
|
let service_url = catInfo["dcat:endpointURL"] || "";
|
|
2095
|
+
if (!service_url) {
|
|
2096
|
+
console.warn("[FederatedCatalogueStore] dcat:endpointURL is missing from dcat:service. Available fields:", Object.keys(catInfo));
|
|
2097
|
+
}
|
|
1614
2098
|
if (service_url.includes("demo.isan.org")) service_url = new URL(service_url).origin;
|
|
1615
2099
|
let providerRef;
|
|
1616
2100
|
if (usedKey === "service") {
|
|
1617
2101
|
providerRef = ((_d = cs["gax-core:operatedBy"]) == null ? void 0 : _d["@id"]) || "";
|
|
2102
|
+
} else if (usedKey === "nested-service") {
|
|
2103
|
+
providerRef = ((_e = cs["gax-core:operatedBy"]) == null ? void 0 : _e["@id"]) || ((_f = cs["gax-core:offeredBy"]) == null ? void 0 : _f["@id"]) || "";
|
|
1618
2104
|
} else {
|
|
1619
|
-
providerRef = ((
|
|
2105
|
+
providerRef = ((_g = cs["gax-core:offeredBy"]) == null ? void 0 : _g["@id"]) || "";
|
|
1620
2106
|
}
|
|
1621
2107
|
const providerSlug = providerRef.split(":").pop() + String(Math.random()) || "0";
|
|
1622
|
-
const providerLogo = ((
|
|
2108
|
+
const providerLogo = ((_i = (_h = catInfo["dcterms:creator"]) == null ? void 0 : _h["foaf:thumbnail"]) == null ? void 0 : _i["rdf:resource"]) || "";
|
|
1623
2109
|
const provider = {
|
|
1624
2110
|
"@id": `${opts.temsProviderBase}${encodeURIComponent(providerSlug)}/`,
|
|
1625
2111
|
"@type": "tems:Provider",
|
|
1626
|
-
name: ((
|
|
2112
|
+
name: ((_j = catInfo["dcterms:creator"]) == null ? void 0 : _j["foaf:name"]) || "",
|
|
1627
2113
|
image: {
|
|
1628
2114
|
"@id": `${opts.temsImageBase}${encodeURIComponent(providerLogo.split("/").pop() || "0")}/`,
|
|
1629
2115
|
"@type": "tems:Image",
|
|
@@ -1633,6 +2119,23 @@ let __tla = (async () => {
|
|
|
1633
2119
|
}
|
|
1634
2120
|
};
|
|
1635
2121
|
const data_offers = [];
|
|
2122
|
+
const counterPartyAddress = cs["dcat:endpointURL"];
|
|
2123
|
+
const counterPartyId = cs["dspace:participantId"];
|
|
2124
|
+
const assetId = this.stripUrnPrefix(cs["@id"], "urn:uuid:");
|
|
2125
|
+
let datasetId;
|
|
2126
|
+
let policy;
|
|
2127
|
+
if (cs["dcat:dataset"] && cs["dcat:dataset"].length > 0) {
|
|
2128
|
+
const dataset2 = cs["dcat:dataset"][0];
|
|
2129
|
+
if (dataset2["@id"]) {
|
|
2130
|
+
datasetId = this.stripUrnPrefix(dataset2["@id"], "urn:uuid:");
|
|
2131
|
+
}
|
|
2132
|
+
if (dataset2["odrl:hasPolicy"]) {
|
|
2133
|
+
policy = this.stripTemsUrnFromPolicy(JSON.parse(JSON.stringify(dataset2["odrl:hasPolicy"])));
|
|
2134
|
+
if (datasetId) {
|
|
2135
|
+
policy.target = datasetId;
|
|
2136
|
+
}
|
|
2137
|
+
}
|
|
2138
|
+
}
|
|
1636
2139
|
const dest = {
|
|
1637
2140
|
"@id": serviceId,
|
|
1638
2141
|
creation_date,
|
|
@@ -1656,7 +2159,22 @@ let __tla = (async () => {
|
|
|
1656
2159
|
url: service_url,
|
|
1657
2160
|
provider,
|
|
1658
2161
|
data_offers,
|
|
1659
|
-
"@type": type
|
|
2162
|
+
"@type": type,
|
|
2163
|
+
...counterPartyAddress && {
|
|
2164
|
+
counterPartyAddress
|
|
2165
|
+
},
|
|
2166
|
+
...counterPartyId && {
|
|
2167
|
+
counterPartyId
|
|
2168
|
+
},
|
|
2169
|
+
...assetId && {
|
|
2170
|
+
assetId
|
|
2171
|
+
},
|
|
2172
|
+
...datasetId && {
|
|
2173
|
+
datasetId
|
|
2174
|
+
},
|
|
2175
|
+
...policy && {
|
|
2176
|
+
policy
|
|
2177
|
+
}
|
|
1660
2178
|
};
|
|
1661
2179
|
return dest;
|
|
1662
2180
|
}
|
|
@@ -28570,7 +29088,7 @@ sh:property [
|
|
|
28570
29088
|
this.searchProvider = new SolidIndexingSearchProvider(this.getData.bind(this));
|
|
28571
29089
|
}
|
|
28572
29090
|
async initGetter() {
|
|
28573
|
-
const { CustomGetter } = await import("./custom-getter-
|
|
29091
|
+
const { CustomGetter } = await import("./custom-getter-DFIdqwHu.js");
|
|
28574
29092
|
return CustomGetter;
|
|
28575
29093
|
}
|
|
28576
29094
|
async getData(id, context2, parentId, localData, forceFetch, serverPagination, serverSearch, headers, bypassLoadingList) {
|
|
@@ -28921,7 +29439,17 @@ sh:property [
|
|
|
28921
29439
|
if (window.sibStore) {
|
|
28922
29440
|
return window.sibStore;
|
|
28923
29441
|
}
|
|
28924
|
-
const
|
|
29442
|
+
const storeOptions = {};
|
|
29443
|
+
const sibAuth = document.querySelector("sib-auth");
|
|
29444
|
+
if (sibAuth) {
|
|
29445
|
+
const sibAuthDefined = customElements.whenDefined(sibAuth.localName);
|
|
29446
|
+
storeOptions.session = sibAuthDefined.then(() => sibAuth.session);
|
|
29447
|
+
storeOptions.fetchMethod = sibAuthDefined.then(() => sibAuth.getFetch());
|
|
29448
|
+
}
|
|
29449
|
+
const store2 = new LdpStore({
|
|
29450
|
+
..._cfg == null ? void 0 : _cfg.options,
|
|
29451
|
+
...storeOptions
|
|
29452
|
+
});
|
|
28925
29453
|
window.sibStore = store2;
|
|
28926
29454
|
return store2;
|
|
28927
29455
|
}
|