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.
Files changed (42) hide show
  1. package/dist/cjs/holosphere.cjs +1 -1
  2. package/dist/esm/holosphere.js +1 -1
  3. package/dist/{index-NOravBLu.js → index-4XHHKe6S.js} +383 -102
  4. package/dist/index-4XHHKe6S.js.map +1 -0
  5. package/dist/{index-JFz-dW43.js → index-BjP1TXGz.js} +2 -2
  6. package/dist/{index-JFz-dW43.js.map → index-BjP1TXGz.js.map} +1 -1
  7. package/dist/{index-CmzkI7SI.cjs → index-CKffQDmQ.cjs} +2 -2
  8. package/dist/{index-CmzkI7SI.cjs.map → index-CKffQDmQ.cjs.map} +1 -1
  9. package/dist/index-Dz5kOZMI.cjs +5 -0
  10. package/dist/index-Dz5kOZMI.cjs.map +1 -0
  11. package/dist/{indexeddb-storage-C4HsulhA.cjs → indexeddb-storage-DD7EFBVc.cjs} +2 -2
  12. package/dist/{indexeddb-storage-C4HsulhA.cjs.map → indexeddb-storage-DD7EFBVc.cjs.map} +1 -1
  13. package/dist/{indexeddb-storage-OtSAVDZY.js → indexeddb-storage-lExjjFlV.js} +2 -2
  14. package/dist/{indexeddb-storage-OtSAVDZY.js.map → indexeddb-storage-lExjjFlV.js.map} +1 -1
  15. package/dist/{memory-storage-ChpcYvxA.js → memory-storage-C68adso2.js} +2 -2
  16. package/dist/{memory-storage-ChpcYvxA.js.map → memory-storage-C68adso2.js.map} +1 -1
  17. package/dist/{memory-storage-MD6ED00P.cjs → memory-storage-DD_6yyXT.cjs} +2 -2
  18. package/dist/{memory-storage-MD6ED00P.cjs.map → memory-storage-DD_6yyXT.cjs.map} +1 -1
  19. package/dist/{secp256k1-DcTYQrqC.cjs → secp256k1-DYELiqgx.cjs} +2 -2
  20. package/dist/{secp256k1-DcTYQrqC.cjs.map → secp256k1-DYELiqgx.cjs.map} +1 -1
  21. package/dist/{secp256k1-PfNOEI7a.js → secp256k1-OM8siPyy.js} +2 -2
  22. package/dist/{secp256k1-PfNOEI7a.js.map → secp256k1-OM8siPyy.js.map} +1 -1
  23. package/examples/holosphere-widget.js +1242 -0
  24. package/examples/widget-demo.html +274 -0
  25. package/examples/widget.html +703 -0
  26. package/package.json +3 -1
  27. package/src/cdn-entry.js +22 -0
  28. package/src/contracts/queries.js +16 -1
  29. package/src/core/holosphere.js +2 -2
  30. package/src/crypto/nostr-utils.js +36 -2
  31. package/src/federation/handshake.js +16 -4
  32. package/src/index.js +16 -2
  33. package/src/storage/backends/gundb-backend.js +293 -9
  34. package/src/storage/gun-async.js +14 -12
  35. package/src/storage/gun-auth.js +26 -18
  36. package/src/storage/gun-wrapper.js +75 -41
  37. package/src/storage/nostr-async.js +40 -25
  38. package/src/storage/unified-storage.js +31 -1
  39. package/vite.config.cdn.js +60 -0
  40. package/dist/index-BtKHqqet.cjs +0 -5
  41. package/dist/index-BtKHqqet.cjs.map +0 -1
  42. 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-OtSAVDZY.js");
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-ChpcYvxA.js");
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
- expectedCount = keys.filter((k) => {
1590
- const item = parentData[k];
1591
- return item && typeof item === "object" && item["#"];
1592
- }).length;
1593
- if (expectedCount === 0) {
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 { _json: JSON.stringify(data) };
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
- await gunPut(gun.get(path), serialized, 2e3);
1687
- await new Promise((resolve) => setTimeout(resolve, 50));
1688
- return true;
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 rawData = await gunPromise(gun.get(path), 2e3);
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.get(path);
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
- if (!data) return null;
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 = referenceKeys.length;
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.get(path));
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.get(path), serialized);
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.get(path));
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.get(path), serializeForGun(tombstone));
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.get(path);
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.get(path).on((data, key) => {
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
- expectedCount = keys.filter((k) => {
2928
- const item = parentData[k];
2929
- return item && typeof item === "object" && item["#"];
2930
- }).length;
2931
- if (expectedCount === 0) {
2932
- settled = true;
2933
- resolve([]);
2934
- return;
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("_") || seen.has(key)) return;
2938
- seen.add(key);
2939
- const parsed = parseItem(data);
2940
- if (parsed && !parsed._deleted) {
2941
- results.push(parsed);
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: this.config.dataDir
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 result = await this.schemaValidator.validateData(
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 (!result.valid) {
3280
- throw new Error(`Schema validation failed: ${JSON.stringify(result.errors)}`);
3398
+ if (!result2.valid) {
3399
+ throw new Error(`Schema validation failed: ${JSON.stringify(result2.errors)}`);
3281
3400
  }
3282
3401
  }
3283
3402
  }
3284
3403
  }
3285
- return write$2(this.gun, path, data);
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 items = await readAll$2(this.gun, path);
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
- return deleteData$2(this.gun, path);
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
- return writeGlobal$1(this.gun, this.appName, tableName, data);
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
- return readAllGlobal(this.gun, this.appName, tableName, timeout);
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
- return deleteGlobal$1(this.gun, this.appName, tableName, key);
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-alpha6";
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: 'WARN')
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") || "WARN",
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
- try {
4417
- const data = JSON.parse(persistedEvent.content);
4418
- if (data._deleted) {
4419
- return null;
4420
- }
4421
- if (options.includeAuthor) {
4422
- data._author = persistedEvent.pubkey;
4423
- }
4424
- if (client.refreshPathInBackground) {
4425
- client.refreshPathInBackground(path, kind2, { authors, timeout });
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
- if (events.length === 0) {
4690
+ const authoredEvents = events.filter((event2) => authors.includes(event2.pubkey));
4691
+ if (authoredEvents.length === 0) {
4464
4692
  return null;
4465
4693
  }
4466
- const event = events.sort((a, b2) => b2.created_at - a.created_at)[0];
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
- return dTag && dTag[1] && dTag[1].startsWith(pathPrefix);
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
- return dTag && dTag[1] && dTag[1].startsWith(pathPrefix);
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-PfNOEI7a.js");
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 = await encryptNIP04(privateKey, recipientPubKey, content);
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 = await encryptNIP04(privateKey, recipientPubKey, content);
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
- const decrypted = await decryptNIP04(privateKey, event.pubkey, event.content);
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-JFz-dW43.js");
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-JFz-dW43.js");
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-JFz-dW43.js");
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
- console.warn(`Circular hologram reference detected: ${sourcePath}`);
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-NOravBLu.js.map
38273
+ //# sourceMappingURL=index-4XHHKe6S.js.map