zen-fs-config 0.5.10 → 0.5.12

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/index.d.mts CHANGED
@@ -542,6 +542,11 @@ declare class ConfigRepo implements IConfigRepo {
542
542
  private updateTombstoneConfirmations;
543
543
  /**
544
544
  * GC: remove tombstones where all backends in backends.json have confirmed.
545
+ *
546
+ * Tombstones are deleted from ALL backends (local + replicas), not just
547
+ * the local IndexedDB. If we only deleted locally, the sync engine would
548
+ * see them as "created on target" and copy them back every cycle — causing
549
+ * an infinite loop of copy → GC → copy → GC.
545
550
  */
546
551
  private gcTombstones;
547
552
  /**
package/dist/index.d.ts CHANGED
@@ -542,6 +542,11 @@ declare class ConfigRepo implements IConfigRepo {
542
542
  private updateTombstoneConfirmations;
543
543
  /**
544
544
  * GC: remove tombstones where all backends in backends.json have confirmed.
545
+ *
546
+ * Tombstones are deleted from ALL backends (local + replicas), not just
547
+ * the local IndexedDB. If we only deleted locally, the sync engine would
548
+ * see them as "created on target" and copy them back every cycle — causing
549
+ * an infinite loop of copy → GC → copy → GC.
545
550
  */
546
551
  private gcTombstones;
547
552
  /**
package/dist/index.js CHANGED
@@ -977,6 +977,11 @@ var ConfigRepo = class {
977
977
  }
978
978
  /**
979
979
  * GC: remove tombstones where all backends in backends.json have confirmed.
980
+ *
981
+ * Tombstones are deleted from ALL backends (local + replicas), not just
982
+ * the local IndexedDB. If we only deleted locally, the sync engine would
983
+ * see them as "created on target" and copy them back every cycle — causing
984
+ * an infinite loop of copy → GC → copy → GC.
980
985
  */
981
986
  async gcTombstones() {
982
987
  const tombstones = await this.readTombstones();
@@ -989,9 +994,17 @@ var ConfigRepo = class {
989
994
  const tombstonePath = `${DELETIONS_DIR}/${tombstoneFileName(tombstone.path)}`;
990
995
  try {
991
996
  await this.cachedFS.unlink(tombstonePath);
992
- console.log(`[ConfigRepo] gcTombstones: removed ${tombstonePath} (all ${allBackendIds.length} backends confirmed)`);
993
997
  } catch {
994
998
  }
999
+ for (const [replicaId, replica] of this.replicaBackends) {
1000
+ if (await this.safeExists(replica.instance, tombstonePath)) {
1001
+ try {
1002
+ await replica.instance.unlink(tombstonePath);
1003
+ } catch {
1004
+ }
1005
+ }
1006
+ }
1007
+ console.log(`[ConfigRepo] gcTombstones: removed ${tombstonePath} (all ${allBackendIds.length} backends confirmed)`);
995
1008
  }
996
1009
  }
997
1010
  }
@@ -1839,7 +1852,11 @@ async function createConfigRepo(appId, options = {}) {
1839
1852
  await primaryInstance.mkdir(META_DIR);
1840
1853
  console.log(`[createConfigRepo] /.meta/ ready`);
1841
1854
  } catch (err) {
1842
- console.error(`[createConfigRepo] Failed to ensure /.meta/:`, err.message);
1855
+ const msg = err.message || "";
1856
+ if (msg.includes("File exists") || msg.includes("EEXIST") || err.code === "EEXIST") {
1857
+ } else {
1858
+ console.error(`[createConfigRepo] Failed to ensure /.meta/:`, err.message);
1859
+ }
1843
1860
  }
1844
1861
  try {
1845
1862
  const groupTypeBytes = new TextEncoder().encode("config-sync");
package/dist/index.mjs CHANGED
@@ -887,6 +887,11 @@ var ConfigRepo = class {
887
887
  }
888
888
  /**
889
889
  * GC: remove tombstones where all backends in backends.json have confirmed.
890
+ *
891
+ * Tombstones are deleted from ALL backends (local + replicas), not just
892
+ * the local IndexedDB. If we only deleted locally, the sync engine would
893
+ * see them as "created on target" and copy them back every cycle — causing
894
+ * an infinite loop of copy → GC → copy → GC.
890
895
  */
891
896
  async gcTombstones() {
892
897
  const tombstones = await this.readTombstones();
@@ -899,9 +904,17 @@ var ConfigRepo = class {
899
904
  const tombstonePath = `${DELETIONS_DIR}/${tombstoneFileName(tombstone.path)}`;
900
905
  try {
901
906
  await this.cachedFS.unlink(tombstonePath);
902
- console.log(`[ConfigRepo] gcTombstones: removed ${tombstonePath} (all ${allBackendIds.length} backends confirmed)`);
903
907
  } catch {
904
908
  }
909
+ for (const [replicaId, replica] of this.replicaBackends) {
910
+ if (await this.safeExists(replica.instance, tombstonePath)) {
911
+ try {
912
+ await replica.instance.unlink(tombstonePath);
913
+ } catch {
914
+ }
915
+ }
916
+ }
917
+ console.log(`[ConfigRepo] gcTombstones: removed ${tombstonePath} (all ${allBackendIds.length} backends confirmed)`);
905
918
  }
906
919
  }
907
920
  }
@@ -1749,7 +1762,11 @@ async function createConfigRepo(appId, options = {}) {
1749
1762
  await primaryInstance.mkdir(META_DIR);
1750
1763
  console.log(`[createConfigRepo] /.meta/ ready`);
1751
1764
  } catch (err) {
1752
- console.error(`[createConfigRepo] Failed to ensure /.meta/:`, err.message);
1765
+ const msg = err.message || "";
1766
+ if (msg.includes("File exists") || msg.includes("EEXIST") || err.code === "EEXIST") {
1767
+ } else {
1768
+ console.error(`[createConfigRepo] Failed to ensure /.meta/:`, err.message);
1769
+ }
1753
1770
  }
1754
1771
  try {
1755
1772
  const groupTypeBytes = new TextEncoder().encode("config-sync");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zen-fs-config",
3
- "version": "0.5.10",
3
+ "version": "0.5.12",
4
4
  "description": "Distributed config management library built on ZenFS, zen-fs-cache, and zen-fs-sync",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",