holosphere 2.0.0-alpha6 → 2.0.0-alpha8
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.
- package/dist/cjs/holosphere.cjs +1 -1
- package/dist/esm/holosphere.js +1 -1
- package/dist/{index-NOravBLu.js → index-4XHHKe6S.js} +383 -102
- package/dist/index-4XHHKe6S.js.map +1 -0
- package/dist/{index-JFz-dW43.js → index-BjP1TXGz.js} +2 -2
- package/dist/{index-JFz-dW43.js.map → index-BjP1TXGz.js.map} +1 -1
- package/dist/{index-CmzkI7SI.cjs → index-CKffQDmQ.cjs} +2 -2
- package/dist/{index-CmzkI7SI.cjs.map → index-CKffQDmQ.cjs.map} +1 -1
- package/dist/index-Dz5kOZMI.cjs +5 -0
- package/dist/index-Dz5kOZMI.cjs.map +1 -0
- package/dist/{indexeddb-storage-C4HsulhA.cjs → indexeddb-storage-DD7EFBVc.cjs} +2 -2
- package/dist/{indexeddb-storage-C4HsulhA.cjs.map → indexeddb-storage-DD7EFBVc.cjs.map} +1 -1
- package/dist/{indexeddb-storage-OtSAVDZY.js → indexeddb-storage-lExjjFlV.js} +2 -2
- package/dist/{indexeddb-storage-OtSAVDZY.js.map → indexeddb-storage-lExjjFlV.js.map} +1 -1
- package/dist/{memory-storage-ChpcYvxA.js → memory-storage-C68adso2.js} +2 -2
- package/dist/{memory-storage-ChpcYvxA.js.map → memory-storage-C68adso2.js.map} +1 -1
- package/dist/{memory-storage-MD6ED00P.cjs → memory-storage-DD_6yyXT.cjs} +2 -2
- package/dist/{memory-storage-MD6ED00P.cjs.map → memory-storage-DD_6yyXT.cjs.map} +1 -1
- package/dist/{secp256k1-DcTYQrqC.cjs → secp256k1-DYELiqgx.cjs} +2 -2
- package/dist/{secp256k1-DcTYQrqC.cjs.map → secp256k1-DYELiqgx.cjs.map} +1 -1
- package/dist/{secp256k1-PfNOEI7a.js → secp256k1-OM8siPyy.js} +2 -2
- package/dist/{secp256k1-PfNOEI7a.js.map → secp256k1-OM8siPyy.js.map} +1 -1
- package/examples/holosphere-widget.js +1242 -0
- package/examples/widget-demo.html +274 -0
- package/examples/widget.html +703 -0
- package/package.json +3 -1
- package/src/cdn-entry.js +22 -0
- package/src/contracts/queries.js +16 -1
- package/src/core/holosphere.js +2 -2
- package/src/crypto/nostr-utils.js +36 -2
- package/src/federation/handshake.js +16 -4
- package/src/index.js +16 -2
- package/src/storage/backends/gundb-backend.js +293 -9
- package/src/storage/gun-async.js +14 -12
- package/src/storage/gun-auth.js +26 -18
- package/src/storage/gun-wrapper.js +75 -41
- package/src/storage/nostr-async.js +40 -25
- package/src/storage/unified-storage.js +31 -1
- package/vite.config.cdn.js +60 -0
- package/dist/index-BtKHqqet.cjs +0 -5
- package/dist/index-BtKHqqet.cjs.map +0 -1
- package/dist/index-NOravBLu.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getPublicKey as getPublicKey$2, finalizeEvent, SimplePool, nip19, nip04, verifyEvent as verifyEvent$1 } from "nostr-tools";
|
|
1
|
+
import { getPublicKey as getPublicKey$2, finalizeEvent, SimplePool, nip19, nip04, nip44, verifyEvent as verifyEvent$1 } from "nostr-tools";
|
|
2
2
|
import * as h3 from "h3-js";
|
|
3
3
|
import { latLngToCell, getResolution, cellToParent, cellToChildren, isValidCell } from "h3-js";
|
|
4
4
|
import Ajv from "ajv";
|
|
@@ -361,12 +361,12 @@ async function createPersistentStorage(namespace, options = {}) {
|
|
|
361
361
|
const isBrowser = typeof window !== "undefined" && typeof window.indexedDB !== "undefined";
|
|
362
362
|
typeof process !== "undefined" && process.versions && void 0;
|
|
363
363
|
if (isBrowser) {
|
|
364
|
-
const { IndexedDBStorage } = await import("./indexeddb-storage-
|
|
364
|
+
const { IndexedDBStorage } = await import("./indexeddb-storage-lExjjFlV.js");
|
|
365
365
|
const storage = new IndexedDBStorage();
|
|
366
366
|
await storage.init(namespace);
|
|
367
367
|
return storage;
|
|
368
368
|
} else {
|
|
369
|
-
const { MemoryStorage } = await import("./memory-storage-
|
|
369
|
+
const { MemoryStorage } = await import("./memory-storage-C68adso2.js");
|
|
370
370
|
const storage = new MemoryStorage();
|
|
371
371
|
await storage.init(namespace);
|
|
372
372
|
return storage;
|
|
@@ -1586,15 +1586,13 @@ async function gunMap(gunChain, timeout = 5e3) {
|
|
|
1586
1586
|
resolve({});
|
|
1587
1587
|
return;
|
|
1588
1588
|
}
|
|
1589
|
-
|
|
1590
|
-
const
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
settled = true;
|
|
1595
|
-
resolve({});
|
|
1596
|
-
return;
|
|
1589
|
+
for (const key of keys) {
|
|
1590
|
+
const rawItem = parentData[key];
|
|
1591
|
+
if (!rawItem) continue;
|
|
1592
|
+
if (typeof rawItem === "object" && rawItem["#"]) continue;
|
|
1593
|
+
items[key] = rawItem;
|
|
1597
1594
|
}
|
|
1595
|
+
expectedCount = keys.length;
|
|
1598
1596
|
gunChain.map().once((data, key) => {
|
|
1599
1597
|
if (settled || !data || key.startsWith("_")) return;
|
|
1600
1598
|
items[key] = data;
|
|
@@ -1630,8 +1628,16 @@ function buildGlobalPath(appname, tableName, key = null) {
|
|
|
1630
1628
|
function encodePathComponent$1(component) {
|
|
1631
1629
|
return encodeURIComponent(component).replace(/%2F/g, "/");
|
|
1632
1630
|
}
|
|
1631
|
+
function getGunPath(gun, path) {
|
|
1632
|
+
const parts = path.split("/").filter((p) => p.length > 0);
|
|
1633
|
+
let ref = gun;
|
|
1634
|
+
for (const part of parts) {
|
|
1635
|
+
ref = ref.get(part);
|
|
1636
|
+
}
|
|
1637
|
+
return ref;
|
|
1638
|
+
}
|
|
1633
1639
|
function serializeForGun(data) {
|
|
1634
|
-
return
|
|
1640
|
+
return JSON.stringify(data);
|
|
1635
1641
|
}
|
|
1636
1642
|
function deserializeFromGun(data) {
|
|
1637
1643
|
if (!data) {
|
|
@@ -1683,15 +1689,29 @@ function deserializeFromGun(data) {
|
|
|
1683
1689
|
async function write$2(gun, path, data) {
|
|
1684
1690
|
try {
|
|
1685
1691
|
const serialized = serializeForGun(data);
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1692
|
+
const parts = path.split("/").filter((p) => p.length > 0);
|
|
1693
|
+
console.log("[gun-wrapper] write:", { path, parts, dataId: data?.id });
|
|
1694
|
+
const ref = getGunPath(gun, path);
|
|
1695
|
+
console.log("[gun-wrapper] write ref soul:", ref?._.get);
|
|
1696
|
+
const ack = await gunPut(ref, serialized, 5e3);
|
|
1697
|
+
console.log("[gun-wrapper] write ack:", { ok: ack.ok, timeout: ack.timeout });
|
|
1698
|
+
if (ack.timeout) {
|
|
1699
|
+
console.warn("[gun-wrapper] write timed out (data may not be persisted):", path);
|
|
1700
|
+
}
|
|
1701
|
+
console.log("[gun-wrapper] write complete:", path);
|
|
1702
|
+
return { ok: true, timeout: ack.timeout || false };
|
|
1689
1703
|
} catch (error) {
|
|
1704
|
+
console.error("[gun-wrapper] write error:", error);
|
|
1690
1705
|
throw error;
|
|
1691
1706
|
}
|
|
1692
1707
|
}
|
|
1693
1708
|
async function read$2(gun, path) {
|
|
1694
|
-
const
|
|
1709
|
+
const parts = path.split("/").filter((p) => p.length > 0);
|
|
1710
|
+
console.log("[gun-wrapper] read:", { path, parts });
|
|
1711
|
+
const ref = getGunPath(gun, path);
|
|
1712
|
+
console.log("[gun-wrapper] read ref soul:", ref?._.get);
|
|
1713
|
+
const rawData = await gunPromise(ref, 2e3);
|
|
1714
|
+
console.log("[gun-wrapper] read rawData:", rawData ? typeof rawData === "string" ? rawData.substring(0, 100) : "object" : "null");
|
|
1695
1715
|
if (!rawData) {
|
|
1696
1716
|
return null;
|
|
1697
1717
|
}
|
|
@@ -1702,63 +1722,57 @@ async function read$2(gun, path) {
|
|
|
1702
1722
|
return data;
|
|
1703
1723
|
}
|
|
1704
1724
|
async function readAll$2(gun, path, timeout = 5e3) {
|
|
1725
|
+
const parts = path.split("/").filter((p) => p.length > 0);
|
|
1726
|
+
console.log("[gun-wrapper] readAll:", { path, parts });
|
|
1705
1727
|
return new Promise((resolve) => {
|
|
1706
1728
|
const output2 = /* @__PURE__ */ new Map();
|
|
1707
1729
|
let settled = false;
|
|
1708
1730
|
let expectedCount = 0;
|
|
1709
1731
|
let receivedCount = 0;
|
|
1710
|
-
const ref = gun
|
|
1732
|
+
const ref = getGunPath(gun, path);
|
|
1733
|
+
console.log("[gun-wrapper] readAll ref soul:", ref?._.get);
|
|
1711
1734
|
const tryResolve = () => {
|
|
1712
1735
|
if (settled) return;
|
|
1713
1736
|
if (expectedCount > 0 && receivedCount >= expectedCount) {
|
|
1714
1737
|
settled = true;
|
|
1738
|
+
console.log("[gun-wrapper] readAll resolved with", output2.size, "items");
|
|
1715
1739
|
resolve(Array.from(output2.values()));
|
|
1716
1740
|
}
|
|
1717
1741
|
};
|
|
1718
1742
|
const parseItem = (data) => {
|
|
1719
|
-
|
|
1720
|
-
let item = null;
|
|
1721
|
-
if (data._json && typeof data._json === "string") {
|
|
1722
|
-
try {
|
|
1723
|
-
item = JSON.parse(data._json);
|
|
1724
|
-
} catch (e) {
|
|
1725
|
-
}
|
|
1726
|
-
} else if (typeof data === "string") {
|
|
1727
|
-
try {
|
|
1728
|
-
item = JSON.parse(data);
|
|
1729
|
-
} catch (e) {
|
|
1730
|
-
}
|
|
1731
|
-
}
|
|
1732
|
-
return item;
|
|
1743
|
+
return deserializeFromGun(data);
|
|
1733
1744
|
};
|
|
1734
1745
|
ref.once((parentData) => {
|
|
1735
1746
|
if (settled) return;
|
|
1747
|
+
console.log("[gun-wrapper] readAll parentData:", parentData);
|
|
1748
|
+
console.log("[gun-wrapper] readAll parentData keys:", parentData ? Object.keys(parentData).filter((k) => k !== "_") : "null");
|
|
1749
|
+
console.log("[gun-wrapper] readAll parentData type:", typeof parentData);
|
|
1736
1750
|
if (!parentData) {
|
|
1737
1751
|
settled = true;
|
|
1752
|
+
console.log("[gun-wrapper] readAll: no parent data, returning empty");
|
|
1738
1753
|
resolve([]);
|
|
1739
1754
|
return;
|
|
1740
1755
|
}
|
|
1741
1756
|
const keys = Object.keys(parentData).filter((k) => k !== "_");
|
|
1757
|
+
console.log("[gun-wrapper] readAll keys:", keys);
|
|
1742
1758
|
if (keys.length === 0) {
|
|
1743
1759
|
settled = true;
|
|
1760
|
+
console.log("[gun-wrapper] readAll: no keys, returning empty");
|
|
1744
1761
|
resolve([]);
|
|
1745
1762
|
return;
|
|
1746
1763
|
}
|
|
1747
|
-
const referenceKeys = [];
|
|
1748
1764
|
for (const key of keys) {
|
|
1749
1765
|
const rawItem = parentData[key];
|
|
1750
1766
|
if (!rawItem) continue;
|
|
1751
1767
|
if (typeof rawItem === "object" && rawItem["#"]) {
|
|
1752
|
-
referenceKeys.push(key);
|
|
1753
1768
|
continue;
|
|
1754
1769
|
}
|
|
1755
1770
|
const item = parseItem(rawItem);
|
|
1756
1771
|
if (item && item.id && !item._deleted) {
|
|
1757
1772
|
output2.set(item.id, item);
|
|
1758
|
-
receivedCount++;
|
|
1759
1773
|
}
|
|
1760
1774
|
}
|
|
1761
|
-
expectedCount =
|
|
1775
|
+
expectedCount = keys.length;
|
|
1762
1776
|
if (expectedCount === 0) {
|
|
1763
1777
|
settled = true;
|
|
1764
1778
|
resolve(Array.from(output2.values()));
|
|
@@ -1770,13 +1784,10 @@ async function readAll$2(gun, path, timeout = 5e3) {
|
|
|
1770
1784
|
if (item && item.id && !item._deleted) {
|
|
1771
1785
|
if (!output2.has(item.id)) {
|
|
1772
1786
|
output2.set(item.id, item);
|
|
1773
|
-
receivedCount++;
|
|
1774
|
-
tryResolve();
|
|
1775
1787
|
}
|
|
1776
|
-
} else {
|
|
1777
|
-
receivedCount++;
|
|
1778
|
-
tryResolve();
|
|
1779
1788
|
}
|
|
1789
|
+
receivedCount++;
|
|
1790
|
+
tryResolve();
|
|
1780
1791
|
});
|
|
1781
1792
|
});
|
|
1782
1793
|
setTimeout(() => {
|
|
@@ -1788,7 +1799,7 @@ async function readAll$2(gun, path, timeout = 5e3) {
|
|
|
1788
1799
|
});
|
|
1789
1800
|
}
|
|
1790
1801
|
async function update$2(gun, path, updates) {
|
|
1791
|
-
const rawData = await gunPromise(gun
|
|
1802
|
+
const rawData = await gunPromise(getGunPath(gun, path));
|
|
1792
1803
|
if (!rawData) {
|
|
1793
1804
|
return false;
|
|
1794
1805
|
}
|
|
@@ -1799,7 +1810,8 @@ async function update$2(gun, path, updates) {
|
|
|
1799
1810
|
const merged = { ...existing, ...updates };
|
|
1800
1811
|
try {
|
|
1801
1812
|
const serialized = serializeForGun(merged);
|
|
1802
|
-
await gunPut(gun
|
|
1813
|
+
await gunPut(getGunPath(gun, path), serialized, 2e3);
|
|
1814
|
+
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
1803
1815
|
return true;
|
|
1804
1816
|
} catch (error) {
|
|
1805
1817
|
throw error;
|
|
@@ -1807,7 +1819,7 @@ async function update$2(gun, path, updates) {
|
|
|
1807
1819
|
}
|
|
1808
1820
|
async function deleteData$2(gun, path) {
|
|
1809
1821
|
try {
|
|
1810
|
-
const rawData = await gunPromise(gun
|
|
1822
|
+
const rawData = await gunPromise(getGunPath(gun, path));
|
|
1811
1823
|
if (!rawData) {
|
|
1812
1824
|
return true;
|
|
1813
1825
|
}
|
|
@@ -1817,7 +1829,8 @@ async function deleteData$2(gun, path) {
|
|
|
1817
1829
|
_deleted: true,
|
|
1818
1830
|
_deletedAt: Date.now()
|
|
1819
1831
|
};
|
|
1820
|
-
await gunPut(gun
|
|
1832
|
+
await gunPut(getGunPath(gun, path), serializeForGun(tombstone), 2e3);
|
|
1833
|
+
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
1821
1834
|
return true;
|
|
1822
1835
|
} catch (error) {
|
|
1823
1836
|
throw error;
|
|
@@ -1839,7 +1852,7 @@ function subscribe$2(gun, path, callback, options = {}) {
|
|
|
1839
1852
|
const pathParts = path.split("/");
|
|
1840
1853
|
const isPrefix = options.prefix !== void 0 ? options.prefix : pathParts.length <= 3;
|
|
1841
1854
|
if (isPrefix) {
|
|
1842
|
-
const ref = gun
|
|
1855
|
+
const ref = getGunPath(gun, path);
|
|
1843
1856
|
ref.map().on((data, key) => {
|
|
1844
1857
|
if (data && !key.startsWith("_")) {
|
|
1845
1858
|
const deserialized = deserializeFromGun(data);
|
|
@@ -1857,7 +1870,7 @@ function subscribe$2(gun, path, callback, options = {}) {
|
|
|
1857
1870
|
}
|
|
1858
1871
|
};
|
|
1859
1872
|
} else {
|
|
1860
|
-
const listener = gun
|
|
1873
|
+
const listener = getGunPath(gun, path).on((data, key) => {
|
|
1861
1874
|
if (data) {
|
|
1862
1875
|
const deserialized = deserializeFromGun(data);
|
|
1863
1876
|
if (deserialized && !deserialized._deleted) {
|
|
@@ -2924,21 +2937,25 @@ class GunAuth {
|
|
|
2924
2937
|
resolve([]);
|
|
2925
2938
|
return;
|
|
2926
2939
|
}
|
|
2927
|
-
|
|
2928
|
-
const
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2940
|
+
for (const key of keys) {
|
|
2941
|
+
const rawItem = parentData[key];
|
|
2942
|
+
if (!rawItem) continue;
|
|
2943
|
+
if (typeof rawItem === "object" && rawItem["#"]) continue;
|
|
2944
|
+
const parsed = parseItem(rawItem);
|
|
2945
|
+
if (parsed && !parsed._deleted && !seen.has(key)) {
|
|
2946
|
+
seen.add(key);
|
|
2947
|
+
results.push(parsed);
|
|
2948
|
+
}
|
|
2935
2949
|
}
|
|
2950
|
+
expectedCount = keys.length;
|
|
2936
2951
|
ref.map().once((data, key) => {
|
|
2937
|
-
if (settled || !data || key.startsWith("_")
|
|
2938
|
-
seen.
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2952
|
+
if (settled || !data || key.startsWith("_")) return;
|
|
2953
|
+
if (!seen.has(key)) {
|
|
2954
|
+
seen.add(key);
|
|
2955
|
+
const parsed = parseItem(data);
|
|
2956
|
+
if (parsed && !parsed._deleted) {
|
|
2957
|
+
results.push(parsed);
|
|
2958
|
+
}
|
|
2942
2959
|
}
|
|
2943
2960
|
receivedCount++;
|
|
2944
2961
|
tryResolve();
|
|
@@ -3210,24 +3227,44 @@ class GunDBBackend extends StorageBackend {
|
|
|
3210
3227
|
this.schemaValidator = null;
|
|
3211
3228
|
this.subscriptions = /* @__PURE__ */ new Map();
|
|
3212
3229
|
this.subscriptionCounter = 0;
|
|
3230
|
+
this.writeCache = /* @__PURE__ */ new Map();
|
|
3231
|
+
this.writeCacheTTL = 3e5;
|
|
3232
|
+
this.pendingWrites = /* @__PURE__ */ new Map();
|
|
3233
|
+
this.maxWriteRetries = 5;
|
|
3234
|
+
this.writeRetryInterval = 1e4;
|
|
3213
3235
|
}
|
|
3214
3236
|
async init() {
|
|
3215
3237
|
let Gun;
|
|
3216
3238
|
try {
|
|
3239
|
+
console.log("[gundb-backend] Importing Gun...");
|
|
3217
3240
|
const gunModule = await import("./browser-BSniCNqO.js").then((n2) => n2.b);
|
|
3218
3241
|
Gun = gunModule.default || gunModule;
|
|
3242
|
+
console.log("[gundb-backend] Gun imported:", typeof Gun);
|
|
3219
3243
|
} catch (error) {
|
|
3220
3244
|
throw new Error(
|
|
3221
3245
|
'GunDB backend requires the "gun" package. Install it with: npm install gun'
|
|
3222
3246
|
);
|
|
3223
3247
|
}
|
|
3248
|
+
const dataDir = this.config.dataDir || "radata";
|
|
3224
3249
|
const gunConfig = {
|
|
3225
3250
|
peers: this.config.peers || [],
|
|
3226
3251
|
radisk: this.config.radisk !== false,
|
|
3227
3252
|
localStorage: this.config.localStorage !== false,
|
|
3228
|
-
file:
|
|
3253
|
+
file: dataDir
|
|
3229
3254
|
};
|
|
3255
|
+
console.log("[gundb-backend] Gun config:", JSON.stringify(gunConfig));
|
|
3230
3256
|
this.gun = Gun(gunConfig);
|
|
3257
|
+
console.log("[gundb-backend] Gun instance created:", !!this.gun);
|
|
3258
|
+
try {
|
|
3259
|
+
const testKey = `_test_${Date.now()}`;
|
|
3260
|
+
this.gun.get(testKey).put({ test: true }, (ack) => {
|
|
3261
|
+
console.log("[gundb-backend] Gun test write ack:", ack);
|
|
3262
|
+
});
|
|
3263
|
+
console.log("[gundb-backend] Gun test write initiated");
|
|
3264
|
+
} catch (e) {
|
|
3265
|
+
console.error("[gundb-backend] Gun test write failed:", e.message);
|
|
3266
|
+
}
|
|
3267
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
3231
3268
|
try {
|
|
3232
3269
|
const SEA = Gun.SEA;
|
|
3233
3270
|
if (SEA) {
|
|
@@ -3253,6 +3290,88 @@ class GunDBBackend extends StorageBackend {
|
|
|
3253
3290
|
await this.schemaValidator.init();
|
|
3254
3291
|
}
|
|
3255
3292
|
// ============================================================================
|
|
3293
|
+
// WRITE CACHE (for immediate consistency)
|
|
3294
|
+
// ============================================================================
|
|
3295
|
+
/**
|
|
3296
|
+
* Add item to the local write cache for immediate consistency
|
|
3297
|
+
* @private
|
|
3298
|
+
*/
|
|
3299
|
+
_addToWriteCache(path, data) {
|
|
3300
|
+
if (!data || !data.id) return;
|
|
3301
|
+
const parentPath = path.substring(0, path.lastIndexOf("/"));
|
|
3302
|
+
if (!parentPath) return;
|
|
3303
|
+
if (!this.writeCache.has(parentPath)) {
|
|
3304
|
+
this.writeCache.set(parentPath, /* @__PURE__ */ new Map());
|
|
3305
|
+
}
|
|
3306
|
+
const pathCache = this.writeCache.get(parentPath);
|
|
3307
|
+
pathCache.set(data.id.toString(), {
|
|
3308
|
+
data,
|
|
3309
|
+
timestamp: Date.now()
|
|
3310
|
+
});
|
|
3311
|
+
}
|
|
3312
|
+
/**
|
|
3313
|
+
* Remove item from write cache (e.g., on delete)
|
|
3314
|
+
* @private
|
|
3315
|
+
*/
|
|
3316
|
+
_removeFromWriteCache(path, id2) {
|
|
3317
|
+
const parentPath = path.substring(0, path.lastIndexOf("/"));
|
|
3318
|
+
const pathCache = this.writeCache.get(parentPath);
|
|
3319
|
+
if (pathCache) {
|
|
3320
|
+
pathCache.delete(id2.toString());
|
|
3321
|
+
}
|
|
3322
|
+
}
|
|
3323
|
+
/**
|
|
3324
|
+
* Get cached writes for a path, filtering out expired entries
|
|
3325
|
+
* @private
|
|
3326
|
+
*/
|
|
3327
|
+
_getWriteCacheEntries(path) {
|
|
3328
|
+
const pathCache = this.writeCache.get(path);
|
|
3329
|
+
if (!pathCache) return [];
|
|
3330
|
+
const now = Date.now();
|
|
3331
|
+
const validEntries = [];
|
|
3332
|
+
for (const [id2, entry] of pathCache) {
|
|
3333
|
+
if (now - entry.timestamp < this.writeCacheTTL) {
|
|
3334
|
+
validEntries.push(entry.data);
|
|
3335
|
+
} else {
|
|
3336
|
+
pathCache.delete(id2);
|
|
3337
|
+
}
|
|
3338
|
+
}
|
|
3339
|
+
return validEntries;
|
|
3340
|
+
}
|
|
3341
|
+
/**
|
|
3342
|
+
* Merge cached writes with results from Gun
|
|
3343
|
+
* @private
|
|
3344
|
+
*/
|
|
3345
|
+
_mergeWithWriteCache(path, gunResults) {
|
|
3346
|
+
const cachedWrites = this._getWriteCacheEntries(path);
|
|
3347
|
+
if (cachedWrites.length === 0) return gunResults;
|
|
3348
|
+
const resultMap = /* @__PURE__ */ new Map();
|
|
3349
|
+
for (const item of gunResults) {
|
|
3350
|
+
if (item && item.id) {
|
|
3351
|
+
resultMap.set(item.id.toString(), item);
|
|
3352
|
+
}
|
|
3353
|
+
}
|
|
3354
|
+
for (const item of cachedWrites) {
|
|
3355
|
+
if (item && item.id && !item._deleted) {
|
|
3356
|
+
resultMap.set(item.id.toString(), item);
|
|
3357
|
+
} else if (item && item.id && item._deleted) {
|
|
3358
|
+
resultMap.delete(item.id.toString());
|
|
3359
|
+
}
|
|
3360
|
+
}
|
|
3361
|
+
return Array.from(resultMap.values());
|
|
3362
|
+
}
|
|
3363
|
+
/**
|
|
3364
|
+
* Clear write cache for a specific path or all paths
|
|
3365
|
+
* @param {string} [path] - Optional path to clear, clears all if not provided
|
|
3366
|
+
*/
|
|
3367
|
+
clearWriteCache(path = null) {
|
|
3368
|
+
if (path) {
|
|
3369
|
+
this.writeCache.delete(path);
|
|
3370
|
+
} else {
|
|
3371
|
+
this.writeCache.clear();
|
|
3372
|
+
}
|
|
3373
|
+
}
|
|
3374
|
+
// ============================================================================
|
|
3256
3375
|
// PATH BUILDING
|
|
3257
3376
|
// ============================================================================
|
|
3258
3377
|
buildPath(appName, holonId, lensName, key = null) {
|
|
@@ -3270,19 +3389,56 @@ class GunDBBackend extends StorageBackend {
|
|
|
3270
3389
|
if (pathParts.length >= 3) {
|
|
3271
3390
|
const lens = pathParts[2];
|
|
3272
3391
|
if (!this.isReference(data)) {
|
|
3273
|
-
const
|
|
3392
|
+
const result2 = await this.schemaValidator.validateData(
|
|
3274
3393
|
this.gun,
|
|
3275
3394
|
this.appName,
|
|
3276
3395
|
lens,
|
|
3277
3396
|
data
|
|
3278
3397
|
);
|
|
3279
|
-
if (!
|
|
3280
|
-
throw new Error(`Schema validation failed: ${JSON.stringify(
|
|
3398
|
+
if (!result2.valid) {
|
|
3399
|
+
throw new Error(`Schema validation failed: ${JSON.stringify(result2.errors)}`);
|
|
3281
3400
|
}
|
|
3282
3401
|
}
|
|
3283
3402
|
}
|
|
3284
3403
|
}
|
|
3285
|
-
|
|
3404
|
+
this._addToWriteCache(path, data);
|
|
3405
|
+
const result = await this._writeWithRetry(path, data);
|
|
3406
|
+
return result;
|
|
3407
|
+
}
|
|
3408
|
+
/**
|
|
3409
|
+
* Write to Gun with automatic retry on timeout
|
|
3410
|
+
* @private
|
|
3411
|
+
*/
|
|
3412
|
+
async _writeWithRetry(path, data, attempt = 0) {
|
|
3413
|
+
const result = await write$2(this.gun, path, data);
|
|
3414
|
+
if (result.timeout && attempt < this.maxWriteRetries) {
|
|
3415
|
+
this.pendingWrites.set(path, {
|
|
3416
|
+
data,
|
|
3417
|
+
retries: attempt + 1,
|
|
3418
|
+
lastAttempt: Date.now()
|
|
3419
|
+
});
|
|
3420
|
+
this._scheduleRetry(path);
|
|
3421
|
+
} else if (!result.timeout) {
|
|
3422
|
+
this.pendingWrites.delete(path);
|
|
3423
|
+
}
|
|
3424
|
+
return result;
|
|
3425
|
+
}
|
|
3426
|
+
/**
|
|
3427
|
+
* Schedule a background retry for a pending write
|
|
3428
|
+
* @private
|
|
3429
|
+
*/
|
|
3430
|
+
_scheduleRetry(path) {
|
|
3431
|
+
setTimeout(async () => {
|
|
3432
|
+
const pending = this.pendingWrites.get(path);
|
|
3433
|
+
if (!pending) return;
|
|
3434
|
+
if (pending.retries >= this.maxWriteRetries) {
|
|
3435
|
+
console.warn(`[gundb-backend] Max retries reached for: ${path}`);
|
|
3436
|
+
this.pendingWrites.delete(path);
|
|
3437
|
+
return;
|
|
3438
|
+
}
|
|
3439
|
+
console.log(`[gundb-backend] Retrying write (attempt ${pending.retries + 1}): ${path}`);
|
|
3440
|
+
await this._writeWithRetry(path, pending.data, pending.retries);
|
|
3441
|
+
}, this.writeRetryInterval);
|
|
3286
3442
|
}
|
|
3287
3443
|
async read(path, options = {}) {
|
|
3288
3444
|
const data = await read$2(this.gun, path);
|
|
@@ -3292,7 +3448,8 @@ class GunDBBackend extends StorageBackend {
|
|
|
3292
3448
|
return data;
|
|
3293
3449
|
}
|
|
3294
3450
|
async readAll(path, options = {}) {
|
|
3295
|
-
const
|
|
3451
|
+
const gunItems = await readAll$2(this.gun, path);
|
|
3452
|
+
const items = this._mergeWithWriteCache(path, gunItems);
|
|
3296
3453
|
if (options.resolveReferences) {
|
|
3297
3454
|
const resolved = [];
|
|
3298
3455
|
for (const item of items) {
|
|
@@ -3313,7 +3470,20 @@ class GunDBBackend extends StorageBackend {
|
|
|
3313
3470
|
return update$2(this.gun, path, updates);
|
|
3314
3471
|
}
|
|
3315
3472
|
async delete(path) {
|
|
3316
|
-
|
|
3473
|
+
const result = await deleteData$2(this.gun, path);
|
|
3474
|
+
const pathParts = path.split("/");
|
|
3475
|
+
const id2 = pathParts[pathParts.length - 1];
|
|
3476
|
+
if (id2) {
|
|
3477
|
+
const parentPath = path.substring(0, path.lastIndexOf("/"));
|
|
3478
|
+
if (!this.writeCache.has(parentPath)) {
|
|
3479
|
+
this.writeCache.set(parentPath, /* @__PURE__ */ new Map());
|
|
3480
|
+
}
|
|
3481
|
+
this.writeCache.get(parentPath).set(id2.toString(), {
|
|
3482
|
+
data: { id: id2, _deleted: true },
|
|
3483
|
+
timestamp: Date.now()
|
|
3484
|
+
});
|
|
3485
|
+
}
|
|
3486
|
+
return result;
|
|
3317
3487
|
}
|
|
3318
3488
|
async deleteAll(path) {
|
|
3319
3489
|
const items = await this.readAll(path);
|
|
@@ -3331,16 +3501,67 @@ class GunDBBackend extends StorageBackend {
|
|
|
3331
3501
|
// GLOBAL TABLE OPERATIONS
|
|
3332
3502
|
// ============================================================================
|
|
3333
3503
|
async writeGlobal(tableName, data) {
|
|
3334
|
-
|
|
3504
|
+
const path = this.buildGlobalPath(tableName, data.id);
|
|
3505
|
+
this._addToWriteCache(path, data);
|
|
3506
|
+
const result = await this._writeGlobalWithRetry(tableName, data);
|
|
3507
|
+
return result;
|
|
3508
|
+
}
|
|
3509
|
+
/**
|
|
3510
|
+
* Write to global table with automatic retry on timeout
|
|
3511
|
+
* @private
|
|
3512
|
+
*/
|
|
3513
|
+
async _writeGlobalWithRetry(tableName, data, attempt = 0) {
|
|
3514
|
+
const path = this.buildGlobalPath(tableName, data.id);
|
|
3515
|
+
const result = await writeGlobal$1(this.gun, this.appName, tableName, data);
|
|
3516
|
+
if (result.timeout && attempt < this.maxWriteRetries) {
|
|
3517
|
+
this.pendingWrites.set(path, {
|
|
3518
|
+
data: { tableName, data },
|
|
3519
|
+
isGlobal: true,
|
|
3520
|
+
retries: attempt + 1,
|
|
3521
|
+
lastAttempt: Date.now()
|
|
3522
|
+
});
|
|
3523
|
+
this._scheduleGlobalRetry(path, tableName);
|
|
3524
|
+
} else if (!result.timeout) {
|
|
3525
|
+
this.pendingWrites.delete(path);
|
|
3526
|
+
}
|
|
3527
|
+
return result;
|
|
3528
|
+
}
|
|
3529
|
+
/**
|
|
3530
|
+
* Schedule a background retry for a pending global write
|
|
3531
|
+
* @private
|
|
3532
|
+
*/
|
|
3533
|
+
_scheduleGlobalRetry(path, tableName) {
|
|
3534
|
+
setTimeout(async () => {
|
|
3535
|
+
const pending = this.pendingWrites.get(path);
|
|
3536
|
+
if (!pending || !pending.isGlobal) return;
|
|
3537
|
+
if (pending.retries >= this.maxWriteRetries) {
|
|
3538
|
+
console.warn(`[gundb-backend] Max retries reached for global: ${path}`);
|
|
3539
|
+
this.pendingWrites.delete(path);
|
|
3540
|
+
return;
|
|
3541
|
+
}
|
|
3542
|
+
console.log(`[gundb-backend] Retrying global write (attempt ${pending.retries + 1}): ${path}`);
|
|
3543
|
+
await this._writeGlobalWithRetry(tableName, pending.data.data, pending.retries);
|
|
3544
|
+
}, this.writeRetryInterval);
|
|
3335
3545
|
}
|
|
3336
3546
|
async readGlobal(tableName, key) {
|
|
3337
3547
|
return readGlobal$1(this.gun, this.appName, tableName, key);
|
|
3338
3548
|
}
|
|
3339
3549
|
async readAllGlobal(tableName, timeout = 5e3) {
|
|
3340
|
-
|
|
3550
|
+
const gunItems = await readAllGlobal(this.gun, this.appName, tableName, timeout);
|
|
3551
|
+
const path = this.buildGlobalPath(tableName);
|
|
3552
|
+
return this._mergeWithWriteCache(path, gunItems);
|
|
3341
3553
|
}
|
|
3342
3554
|
async deleteGlobal(tableName, key) {
|
|
3343
|
-
|
|
3555
|
+
const result = await deleteGlobal$1(this.gun, this.appName, tableName, key);
|
|
3556
|
+
const path = this.buildGlobalPath(tableName);
|
|
3557
|
+
if (!this.writeCache.has(path)) {
|
|
3558
|
+
this.writeCache.set(path, /* @__PURE__ */ new Map());
|
|
3559
|
+
}
|
|
3560
|
+
this.writeCache.get(path).set(key.toString(), {
|
|
3561
|
+
data: { id: key, _deleted: true },
|
|
3562
|
+
timestamp: Date.now()
|
|
3563
|
+
});
|
|
3564
|
+
return result;
|
|
3344
3565
|
}
|
|
3345
3566
|
async deleteAllGlobal(tableName) {
|
|
3346
3567
|
return deleteAllGlobal$1(this.gun, this.appName, tableName);
|
|
@@ -3611,6 +3832,7 @@ class GunDBBackend extends StorageBackend {
|
|
|
3611
3832
|
if (this.schemaValidator) {
|
|
3612
3833
|
this.schemaValidator.clearCache();
|
|
3613
3834
|
}
|
|
3835
|
+
this.writeCache.clear();
|
|
3614
3836
|
if (this.auth) {
|
|
3615
3837
|
this.auth.logout();
|
|
3616
3838
|
}
|
|
@@ -3646,7 +3868,7 @@ class GunDBBackend extends StorageBackend {
|
|
|
3646
3868
|
}
|
|
3647
3869
|
}
|
|
3648
3870
|
const name = "holosphere";
|
|
3649
|
-
const version$1 = "2.0.0-
|
|
3871
|
+
const version$1 = "2.0.0-alpha8";
|
|
3650
3872
|
const description = "Holonic geospatial communication infrastructure combining H3 hexagonal indexing with distributed P2P storage";
|
|
3651
3873
|
const type = "module";
|
|
3652
3874
|
const bin = {
|
|
@@ -3665,6 +3887,8 @@ const exports = {
|
|
|
3665
3887
|
const scripts = {
|
|
3666
3888
|
dev: "vite",
|
|
3667
3889
|
build: "vite build",
|
|
3890
|
+
"build:cdn": "vite build --config vite.config.cdn.js",
|
|
3891
|
+
"build:all": "npm run build && npm run build:cdn",
|
|
3668
3892
|
test: "vitest run",
|
|
3669
3893
|
"test:watch": "vitest",
|
|
3670
3894
|
"test:coverage": "vitest run --coverage",
|
|
@@ -3752,7 +3976,7 @@ let HoloSphere$1 = class HoloSphere {
|
|
|
3752
3976
|
* @param {string} config.backend - Storage backend: 'nostr' | 'gundb' | 'activitypub' (default: 'nostr')
|
|
3753
3977
|
* @param {string[]} config.relays - Nostr relay URLs (default from HOLOSPHERE_RELAYS env or ['wss://relay.holons.io', 'wss://relay.nostr.band'])
|
|
3754
3978
|
* @param {string} config.privateKey - Private key for signing (hex format, optional)
|
|
3755
|
-
* @param {string} config.logLevel - Log verbosity: ERROR|WARN|INFO|DEBUG (default: '
|
|
3979
|
+
* @param {string} config.logLevel - Log verbosity: ERROR|WARN|INFO|DEBUG (default: 'INFO')
|
|
3756
3980
|
* @param {boolean} config.hybridMode - Enable hybrid mode (local + relay queries) (default: true)
|
|
3757
3981
|
* @param {Object} config.gundb - GunDB-specific configuration
|
|
3758
3982
|
* @param {Object} config.activitypub - ActivityPub-specific configuration
|
|
@@ -3781,7 +4005,7 @@ let HoloSphere$1 = class HoloSphere {
|
|
|
3781
4005
|
backend: config.backend || "nostr",
|
|
3782
4006
|
relays: config.relays || getDefaultRelays(),
|
|
3783
4007
|
privateKey: config.privateKey || getEnv("HOLOSPHERE_PRIVATE_KEY"),
|
|
3784
|
-
logLevel: config.logLevel || getEnv("HOLOSPHERE_LOG_LEVEL") || "
|
|
4008
|
+
logLevel: config.logLevel || getEnv("HOLOSPHERE_LOG_LEVEL") || "INFO",
|
|
3785
4009
|
hybridMode: config.hybridMode !== false
|
|
3786
4010
|
// Enable by default
|
|
3787
4011
|
};
|
|
@@ -4413,20 +4637,23 @@ async function nostrGet(client, path, kind2 = 3e4, options = {}) {
|
|
|
4413
4637
|
if (!options.skipPersistent && client.persistentGet) {
|
|
4414
4638
|
const persistedEvent = await client.persistentGet(path);
|
|
4415
4639
|
if (persistedEvent && persistedEvent.content) {
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
|
|
4640
|
+
if (!authors.includes(persistedEvent.pubkey)) ;
|
|
4641
|
+
else {
|
|
4642
|
+
try {
|
|
4643
|
+
const data = JSON.parse(persistedEvent.content);
|
|
4644
|
+
if (data._deleted) {
|
|
4645
|
+
return null;
|
|
4646
|
+
}
|
|
4647
|
+
if (options.includeAuthor) {
|
|
4648
|
+
data._author = persistedEvent.pubkey;
|
|
4649
|
+
}
|
|
4650
|
+
if (client.refreshPathInBackground) {
|
|
4651
|
+
client.refreshPathInBackground(path, kind2, { authors, timeout });
|
|
4652
|
+
}
|
|
4653
|
+
return data;
|
|
4654
|
+
} catch (error) {
|
|
4655
|
+
console.warn("[nostrGet] Failed to parse persisted event:", error);
|
|
4426
4656
|
}
|
|
4427
|
-
return data;
|
|
4428
|
-
} catch (error) {
|
|
4429
|
-
console.warn("[nostrGet] Failed to parse persisted event:", error);
|
|
4430
4657
|
}
|
|
4431
4658
|
}
|
|
4432
4659
|
}
|
|
@@ -4460,10 +4687,11 @@ async function _executeNostrGet(client, path, kind2, authors, timeout, options)
|
|
|
4460
4687
|
// Increase limit to get events from all authors
|
|
4461
4688
|
};
|
|
4462
4689
|
const events = await client.query(filter, { timeout });
|
|
4463
|
-
|
|
4690
|
+
const authoredEvents = events.filter((event2) => authors.includes(event2.pubkey));
|
|
4691
|
+
if (authoredEvents.length === 0) {
|
|
4464
4692
|
return null;
|
|
4465
4693
|
}
|
|
4466
|
-
const event =
|
|
4694
|
+
const event = authoredEvents.sort((a, b2) => b2.created_at - a.created_at)[0];
|
|
4467
4695
|
try {
|
|
4468
4696
|
const data = JSON.parse(event.content);
|
|
4469
4697
|
if (data._deleted) {
|
|
@@ -4487,6 +4715,7 @@ async function nostrGetAll(client, pathPrefix, kind2 = 3e4, options = {}) {
|
|
|
4487
4715
|
const byPath = /* @__PURE__ */ new Map();
|
|
4488
4716
|
for (const event of persistedEvents) {
|
|
4489
4717
|
if (!event || !event.tags) continue;
|
|
4718
|
+
if (!authors.includes(event.pubkey)) continue;
|
|
4490
4719
|
const dTag = event.tags.find((t) => t[0] === "d");
|
|
4491
4720
|
if (!dTag || !dTag[1] || !dTag[1].startsWith(pathPrefix)) continue;
|
|
4492
4721
|
const path = dTag[1];
|
|
@@ -4541,7 +4770,9 @@ async function _executeNostrGetAll(client, pathPrefix, kind2, authors, timeout,
|
|
|
4541
4770
|
const events = await client.query(filter, { timeout });
|
|
4542
4771
|
const matching = events.filter((event) => {
|
|
4543
4772
|
const dTag = event.tags.find((t) => t[0] === "d");
|
|
4544
|
-
|
|
4773
|
+
const pathMatches = dTag && dTag[1] && dTag[1].startsWith(pathPrefix);
|
|
4774
|
+
const authorAllowed = authors.includes(event.pubkey);
|
|
4775
|
+
return pathMatches && authorAllowed;
|
|
4545
4776
|
});
|
|
4546
4777
|
const byPath = /* @__PURE__ */ new Map();
|
|
4547
4778
|
for (const event of matching) {
|
|
@@ -4577,7 +4808,9 @@ async function nostrGetAllHybrid(client, pathPrefix, kind2 = 3e4, options = {})
|
|
|
4577
4808
|
const events = await queryMethod.call(client, filter, { timeout });
|
|
4578
4809
|
const matching = events.filter((event) => {
|
|
4579
4810
|
const dTag = event.tags.find((t) => t[0] === "d");
|
|
4580
|
-
|
|
4811
|
+
const pathMatches = dTag && dTag[1] && dTag[1].startsWith(pathPrefix);
|
|
4812
|
+
const authorAllowed = authors.includes(event.pubkey);
|
|
4813
|
+
return pathMatches && authorAllowed;
|
|
4581
4814
|
});
|
|
4582
4815
|
const byPath = /* @__PURE__ */ new Map();
|
|
4583
4816
|
for (const event of matching) {
|
|
@@ -5003,30 +5236,45 @@ function buildPath(appName, holonId, lensName, key = null) {
|
|
|
5003
5236
|
return buildPath$1(appName, holonId, lensName, key);
|
|
5004
5237
|
}
|
|
5005
5238
|
async function write(client, path, data) {
|
|
5239
|
+
if (client.write && client.gun) {
|
|
5240
|
+
return client.write(path, data);
|
|
5241
|
+
}
|
|
5006
5242
|
if (client.gun) {
|
|
5007
5243
|
return write$2(client.gun, path, data);
|
|
5008
5244
|
}
|
|
5009
5245
|
return write$1(client, path, data);
|
|
5010
5246
|
}
|
|
5011
5247
|
async function read(client, path, options = {}) {
|
|
5248
|
+
if (client.read && client.gun) {
|
|
5249
|
+
return client.read(path, options);
|
|
5250
|
+
}
|
|
5012
5251
|
if (client.gun) {
|
|
5013
5252
|
return read$2(client.gun, path);
|
|
5014
5253
|
}
|
|
5015
5254
|
return read$1(client, path, options);
|
|
5016
5255
|
}
|
|
5017
5256
|
async function readAll(client, path, options = {}) {
|
|
5257
|
+
if (client.readAll && client.gun) {
|
|
5258
|
+
return client.readAll(path, options);
|
|
5259
|
+
}
|
|
5018
5260
|
if (client.gun) {
|
|
5019
5261
|
return readAll$2(client.gun, path);
|
|
5020
5262
|
}
|
|
5021
5263
|
return readAll$1(client, path, options);
|
|
5022
5264
|
}
|
|
5023
5265
|
async function update(client, path, updates) {
|
|
5266
|
+
if (client.update && client.gun) {
|
|
5267
|
+
return client.update(path, updates);
|
|
5268
|
+
}
|
|
5024
5269
|
if (client.gun) {
|
|
5025
5270
|
return update$2(client.gun, path, updates);
|
|
5026
5271
|
}
|
|
5027
5272
|
return update$1(client, path, updates);
|
|
5028
5273
|
}
|
|
5029
5274
|
async function deleteData(client, path) {
|
|
5275
|
+
if (client.delete && client.gun) {
|
|
5276
|
+
return client.delete(path);
|
|
5277
|
+
}
|
|
5030
5278
|
if (client.gun) {
|
|
5031
5279
|
return deleteData$2(client.gun, path);
|
|
5032
5280
|
}
|
|
@@ -5039,6 +5287,9 @@ async function deleteAll(client, path) {
|
|
|
5039
5287
|
return deleteAll$1(client, path);
|
|
5040
5288
|
}
|
|
5041
5289
|
function subscribe(client, path, callback, options = {}) {
|
|
5290
|
+
if (client.subscribe && client.gun) {
|
|
5291
|
+
return client.subscribe(path, callback, options);
|
|
5292
|
+
}
|
|
5042
5293
|
if (client.gun) {
|
|
5043
5294
|
return subscribe$2(client.gun, path, callback, options);
|
|
5044
5295
|
}
|
|
@@ -5543,7 +5794,7 @@ const sha256 = sha256$1;
|
|
|
5543
5794
|
let secp256k1 = null;
|
|
5544
5795
|
async function loadCrypto() {
|
|
5545
5796
|
if (!secp256k1) {
|
|
5546
|
-
const module2 = await import("./secp256k1-
|
|
5797
|
+
const module2 = await import("./secp256k1-OM8siPyy.js");
|
|
5547
5798
|
secp256k1 = module2.secp256k1;
|
|
5548
5799
|
}
|
|
5549
5800
|
return secp256k1;
|
|
@@ -6547,6 +6798,16 @@ async function encryptNIP04(privateKey, recipientPubKey, content) {
|
|
|
6547
6798
|
async function decryptNIP04(privateKey, senderPubKey, encryptedContent) {
|
|
6548
6799
|
return await nip04.decrypt(privateKey, senderPubKey, encryptedContent);
|
|
6549
6800
|
}
|
|
6801
|
+
function encryptNIP44(privateKey, recipientPubKey, content) {
|
|
6802
|
+
const privKeyBytes = hexToBytes(privateKey);
|
|
6803
|
+
const conversationKey = nip44.v2.utils.getConversationKey(privKeyBytes, recipientPubKey);
|
|
6804
|
+
return nip44.v2.encrypt(content, conversationKey);
|
|
6805
|
+
}
|
|
6806
|
+
function decryptNIP44(privateKey, senderPubKey, encryptedContent) {
|
|
6807
|
+
const privKeyBytes = hexToBytes(privateKey);
|
|
6808
|
+
const conversationKey = nip44.v2.utils.getConversationKey(privKeyBytes, senderPubKey);
|
|
6809
|
+
return nip44.v2.decrypt(encryptedContent, conversationKey);
|
|
6810
|
+
}
|
|
6550
6811
|
function createSignedEvent(kind2, content, tags, privateKey) {
|
|
6551
6812
|
const event = {
|
|
6552
6813
|
kind: kind2,
|
|
@@ -6600,7 +6861,9 @@ const nostrUtils = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePr
|
|
|
6600
6861
|
createDMEvent,
|
|
6601
6862
|
createSignedEvent,
|
|
6602
6863
|
decryptNIP04,
|
|
6864
|
+
decryptNIP44,
|
|
6603
6865
|
encryptNIP04,
|
|
6866
|
+
encryptNIP44,
|
|
6604
6867
|
generateNonce,
|
|
6605
6868
|
getPublicKey,
|
|
6606
6869
|
hexToBytes,
|
|
@@ -6662,7 +6925,7 @@ function createFederationResponse({
|
|
|
6662
6925
|
async function sendFederationRequest$1(client, privateKey, recipientPubKey, request) {
|
|
6663
6926
|
try {
|
|
6664
6927
|
const content = JSON.stringify(request);
|
|
6665
|
-
const encrypted =
|
|
6928
|
+
const encrypted = encryptNIP44(privateKey, recipientPubKey, content);
|
|
6666
6929
|
const event = createDMEvent(recipientPubKey, encrypted, privateKey);
|
|
6667
6930
|
if (client?.publish) {
|
|
6668
6931
|
await client.publish(event);
|
|
@@ -6680,7 +6943,7 @@ async function sendFederationRequest$1(client, privateKey, recipientPubKey, requ
|
|
|
6680
6943
|
async function sendFederationResponse(client, privateKey, recipientPubKey, response) {
|
|
6681
6944
|
try {
|
|
6682
6945
|
const content = JSON.stringify(response);
|
|
6683
|
-
const encrypted =
|
|
6946
|
+
const encrypted = encryptNIP44(privateKey, recipientPubKey, content);
|
|
6684
6947
|
const event = createDMEvent(recipientPubKey, encrypted, privateKey);
|
|
6685
6948
|
if (client?.publish) {
|
|
6686
6949
|
await client.publish(event);
|
|
@@ -6707,7 +6970,12 @@ function subscribeToFederationDMs(client, privateKey, publicKey, handlers) {
|
|
|
6707
6970
|
const pTag = event.tags?.find((t) => t[0] === "p");
|
|
6708
6971
|
if (!pTag || pTag[1] !== publicKey) return;
|
|
6709
6972
|
try {
|
|
6710
|
-
|
|
6973
|
+
let decrypted;
|
|
6974
|
+
try {
|
|
6975
|
+
decrypted = decryptNIP44(privateKey, event.pubkey, event.content);
|
|
6976
|
+
} catch (nip44Error) {
|
|
6977
|
+
decrypted = await decryptNIP04(privateKey, event.pubkey, event.content);
|
|
6978
|
+
}
|
|
6711
6979
|
const payload = JSON.parse(decrypted);
|
|
6712
6980
|
if (payload.type === "federation_request" && payload.version === "1.0") {
|
|
6713
6981
|
console.log("[Handshake] Received federation request from:", event.pubkey.substring(0, 8) + "...");
|
|
@@ -7027,7 +7295,7 @@ async function createSubscription(client, path, callback, options = {}) {
|
|
|
7027
7295
|
lastInvoke = now;
|
|
7028
7296
|
callback(resolvedData, key);
|
|
7029
7297
|
};
|
|
7030
|
-
const subscription = await subscribe(client, path, wrappedCallback, {});
|
|
7298
|
+
const subscription = await subscribe(client, path, wrappedCallback, { realtimeOnly });
|
|
7031
7299
|
return {
|
|
7032
7300
|
path,
|
|
7033
7301
|
unsubscribe: () => {
|
|
@@ -17177,7 +17445,7 @@ class ChainManager {
|
|
|
17177
17445
|
*/
|
|
17178
17446
|
async _loadEthers() {
|
|
17179
17447
|
if (!this.ethers) {
|
|
17180
|
-
const ethersModule = await import("./index-
|
|
17448
|
+
const ethersModule = await import("./index-BjP1TXGz.js");
|
|
17181
17449
|
this.ethers = ethersModule;
|
|
17182
17450
|
}
|
|
17183
17451
|
return this.ethers;
|
|
@@ -25946,7 +26214,7 @@ class ContractDeployer {
|
|
|
25946
26214
|
*/
|
|
25947
26215
|
async _loadEthers() {
|
|
25948
26216
|
if (!this.ethers) {
|
|
25949
|
-
this.ethers = await import("./index-
|
|
26217
|
+
this.ethers = await import("./index-BjP1TXGz.js");
|
|
25950
26218
|
}
|
|
25951
26219
|
return this.ethers;
|
|
25952
26220
|
}
|
|
@@ -26308,7 +26576,7 @@ class ContractOperations {
|
|
|
26308
26576
|
*/
|
|
26309
26577
|
async _loadEthers() {
|
|
26310
26578
|
if (!this.ethers) {
|
|
26311
|
-
this.ethers = await import("./index-
|
|
26579
|
+
this.ethers = await import("./index-BjP1TXGz.js");
|
|
26312
26580
|
}
|
|
26313
26581
|
return this.ethers;
|
|
26314
26582
|
}
|
|
@@ -35559,8 +35827,7 @@ const ContractABIs = {
|
|
|
35559
35827
|
Zoned: ZonedABI,
|
|
35560
35828
|
Appreciative: AppreciativeABI,
|
|
35561
35829
|
Bundle: BundleABI,
|
|
35562
|
-
Holons: HolonsABI
|
|
35563
|
-
TestToken: TestTokenABI
|
|
35830
|
+
Holons: HolonsABI
|
|
35564
35831
|
};
|
|
35565
35832
|
function formatEthNumber(wei) {
|
|
35566
35833
|
return Number(formatEther(wei));
|
|
@@ -37057,6 +37324,7 @@ class HoloSphereBase extends HoloSphere$1 {
|
|
|
37057
37324
|
data.id = `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
37058
37325
|
}
|
|
37059
37326
|
const path = buildPath(this.config.appName, holonId, lensName, data.id);
|
|
37327
|
+
this._log("DEBUG", "write", { holonId, lensName, dataId: data.id, path });
|
|
37060
37328
|
const existingData = await read(this.client, path);
|
|
37061
37329
|
if (existingData && existingData.hologram === true && existingData.target) {
|
|
37062
37330
|
const hologramStructureFields = ["hologram", "soul", "target", "id", "_meta"];
|
|
@@ -37152,8 +37420,15 @@ class HoloSphereBase extends HoloSphere$1 {
|
|
|
37152
37420
|
data.target.lensName,
|
|
37153
37421
|
data.target.dataId
|
|
37154
37422
|
);
|
|
37423
|
+
this._log("DEBUG", "resolving hologram", {
|
|
37424
|
+
hologramId: data.id,
|
|
37425
|
+
sourcePath,
|
|
37426
|
+
targetHolon: data.target.holonId,
|
|
37427
|
+
targetLens: data.target.lensName,
|
|
37428
|
+
targetDataId: data.target.dataId
|
|
37429
|
+
});
|
|
37155
37430
|
if (visited.has(sourcePath)) {
|
|
37156
|
-
|
|
37431
|
+
this._log("WARN", "Circular hologram reference detected", { sourcePath });
|
|
37157
37432
|
return null;
|
|
37158
37433
|
}
|
|
37159
37434
|
visited.add(sourcePath);
|
|
@@ -37163,6 +37438,7 @@ class HoloSphereBase extends HoloSphere$1 {
|
|
|
37163
37438
|
resolveOptions.includeAuthor = true;
|
|
37164
37439
|
}
|
|
37165
37440
|
const sourceData = await read(this.client, sourcePath, resolveOptions);
|
|
37441
|
+
this._log("DEBUG", "hologram source fetched", { found: !!sourceData, sourcePath });
|
|
37166
37442
|
if (sourceData) {
|
|
37167
37443
|
let resolvedSource = sourceData;
|
|
37168
37444
|
if (sourceData.hologram === true && sourceData.target) {
|
|
@@ -37220,13 +37496,18 @@ class HoloSphereBase extends HoloSphere$1 {
|
|
|
37220
37496
|
let result;
|
|
37221
37497
|
if (dataId) {
|
|
37222
37498
|
const path = buildPath(this.config.appName, holonId, lensName, dataId);
|
|
37499
|
+
this._log("DEBUG", "read", { holonId, lensName, dataId, path });
|
|
37223
37500
|
result = await read(this.client, path);
|
|
37501
|
+
this._log("DEBUG", "read result", { found: !!result, isHologram: result?.hologram === true });
|
|
37224
37502
|
} else {
|
|
37225
37503
|
const path = buildPath(this.config.appName, holonId, lensName);
|
|
37504
|
+
this._log("DEBUG", "readAll", { holonId, lensName, path });
|
|
37226
37505
|
result = await readAll(this.client, path);
|
|
37506
|
+
this._log("DEBUG", "readAll result", { count: Array.isArray(result) ? result.length : 0 });
|
|
37227
37507
|
}
|
|
37228
37508
|
const { resolveHolograms = true } = options;
|
|
37229
|
-
if (resolveHolograms) {
|
|
37509
|
+
if (resolveHolograms && result) {
|
|
37510
|
+
this._log("DEBUG", "resolving holograms", { itemCount: Array.isArray(result) ? result.length : 1 });
|
|
37230
37511
|
result = await this._resolveHolograms(result);
|
|
37231
37512
|
}
|
|
37232
37513
|
const endTime = Date.now();
|
|
@@ -37989,4 +38270,4 @@ export {
|
|
|
37989
38270
|
exists as y,
|
|
37990
38271
|
bytes as z
|
|
37991
38272
|
};
|
|
37992
|
-
//# sourceMappingURL=index-
|
|
38273
|
+
//# sourceMappingURL=index-4XHHKe6S.js.map
|