zen-fs-config 0.5.9 → 0.5.10
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 +11 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +50 -10
- package/dist/index.mjs +50 -10
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -515,8 +515,19 @@ declare class ConfigRepo implements IConfigRepo {
|
|
|
515
515
|
/**
|
|
516
516
|
* Before sync: for each tombstone, delete the actual file on all replicas.
|
|
517
517
|
* This prevents bi-directional sync from copying the file back.
|
|
518
|
+
*
|
|
519
|
+
* Before calling unlink() on each backend, we check exists() first.
|
|
520
|
+
* This avoids sending wasteful DELETE requests (or GET-then-404) to
|
|
521
|
+
* remote backends when the file was already removed on a previous cycle.
|
|
522
|
+
* Local backends (IndexedDB) are cheap to check, so the guard is
|
|
523
|
+
* effectively free for them.
|
|
518
524
|
*/
|
|
519
525
|
private processTombstones;
|
|
526
|
+
/**
|
|
527
|
+
* Safe existence check — returns false on any error instead of throwing.
|
|
528
|
+
* Used by processTombstones to avoid unnecessary unlink() calls.
|
|
529
|
+
*/
|
|
530
|
+
private safeExists;
|
|
520
531
|
/** Public wrapper for processTombstones — used by createConfigRepo. */
|
|
521
532
|
processTombstonesPublic(): Promise<void>;
|
|
522
533
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -515,8 +515,19 @@ declare class ConfigRepo implements IConfigRepo {
|
|
|
515
515
|
/**
|
|
516
516
|
* Before sync: for each tombstone, delete the actual file on all replicas.
|
|
517
517
|
* This prevents bi-directional sync from copying the file back.
|
|
518
|
+
*
|
|
519
|
+
* Before calling unlink() on each backend, we check exists() first.
|
|
520
|
+
* This avoids sending wasteful DELETE requests (or GET-then-404) to
|
|
521
|
+
* remote backends when the file was already removed on a previous cycle.
|
|
522
|
+
* Local backends (IndexedDB) are cheap to check, so the guard is
|
|
523
|
+
* effectively free for them.
|
|
518
524
|
*/
|
|
519
525
|
private processTombstones;
|
|
526
|
+
/**
|
|
527
|
+
* Safe existence check — returns false on any error instead of throwing.
|
|
528
|
+
* Used by processTombstones to avoid unnecessary unlink() calls.
|
|
529
|
+
*/
|
|
530
|
+
private safeExists;
|
|
520
531
|
/** Public wrapper for processTombstones — used by createConfigRepo. */
|
|
521
532
|
processTombstonesPublic(): Promise<void>;
|
|
522
533
|
/**
|
package/dist/index.js
CHANGED
|
@@ -861,37 +861,77 @@ var ConfigRepo = class {
|
|
|
861
861
|
/**
|
|
862
862
|
* Before sync: for each tombstone, delete the actual file on all replicas.
|
|
863
863
|
* This prevents bi-directional sync from copying the file back.
|
|
864
|
+
*
|
|
865
|
+
* Before calling unlink() on each backend, we check exists() first.
|
|
866
|
+
* This avoids sending wasteful DELETE requests (or GET-then-404) to
|
|
867
|
+
* remote backends when the file was already removed on a previous cycle.
|
|
868
|
+
* Local backends (IndexedDB) are cheap to check, so the guard is
|
|
869
|
+
* effectively free for them.
|
|
864
870
|
*/
|
|
865
871
|
async processTombstones() {
|
|
866
872
|
const tombstones = await this.readTombstones();
|
|
867
873
|
if (tombstones.length === 0) return;
|
|
868
|
-
|
|
874
|
+
let processed = 0;
|
|
875
|
+
let alreadyDeleted = 0;
|
|
869
876
|
for (const tombstone of tombstones) {
|
|
870
877
|
const tVersionPath = versionPathFor(tombstone.path);
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
878
|
+
const existedOnPrimary = await this.safeExists(this.cachedFS, tombstone.path);
|
|
879
|
+
console.log(`[ConfigRepo] tombstone check: ${tombstone.path} on primary \u2192 ${existedOnPrimary ? "EXISTS" : "not found"}`);
|
|
880
|
+
if (existedOnPrimary) {
|
|
881
|
+
try {
|
|
882
|
+
await this.cachedFS.unlink(tombstone.path);
|
|
883
|
+
processed++;
|
|
884
|
+
} catch {
|
|
885
|
+
}
|
|
874
886
|
}
|
|
875
|
-
if (tVersionPath) {
|
|
887
|
+
if (tVersionPath && await this.safeExists(this.cachedFS, tVersionPath)) {
|
|
876
888
|
try {
|
|
877
889
|
await this.cachedFS.unlink(tVersionPath);
|
|
878
890
|
} catch {
|
|
879
891
|
}
|
|
880
892
|
}
|
|
881
893
|
for (const [replicaId, replica] of this.replicaBackends) {
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
894
|
+
const existed = await this.safeExists(replica.instance, tombstone.path);
|
|
895
|
+
console.log(`[ConfigRepo] tombstone check: ${tombstone.path} on ${replicaId} \u2192 ${existed ? "EXISTS" : "not found"}`);
|
|
896
|
+
if (existed) {
|
|
897
|
+
try {
|
|
898
|
+
await replica.instance.unlink(tombstone.path);
|
|
899
|
+
console.log(`[ConfigRepo] tombstone ${tombstone.path}: deleted on ${replicaId}`);
|
|
900
|
+
processed++;
|
|
901
|
+
} catch {
|
|
902
|
+
alreadyDeleted++;
|
|
903
|
+
}
|
|
904
|
+
} else {
|
|
905
|
+
alreadyDeleted++;
|
|
885
906
|
}
|
|
886
|
-
if (tVersionPath) {
|
|
907
|
+
if (tVersionPath && await this.safeExists(replica.instance, tVersionPath)) {
|
|
887
908
|
try {
|
|
888
909
|
await replica.instance.unlink(tVersionPath);
|
|
889
910
|
} catch {
|
|
890
911
|
}
|
|
891
912
|
}
|
|
892
|
-
console.log(`[ConfigRepo] tombstone ${tombstone.path}: deleted on ${replicaId}`);
|
|
893
913
|
}
|
|
894
914
|
}
|
|
915
|
+
if (processed > 0 || alreadyDeleted > 0) {
|
|
916
|
+
console.log(`[ConfigRepo] processTombstones: ${tombstones.length} tombstone(s), ${processed} deleted, ${alreadyDeleted} already gone`);
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
/**
|
|
920
|
+
* Safe existence check — returns false on any error instead of throwing.
|
|
921
|
+
* Used by processTombstones to avoid unnecessary unlink() calls.
|
|
922
|
+
*/
|
|
923
|
+
async safeExists(fs, path) {
|
|
924
|
+
try {
|
|
925
|
+
if (typeof fs.exists === "function") {
|
|
926
|
+
const result = await fs.exists(path);
|
|
927
|
+
return result;
|
|
928
|
+
}
|
|
929
|
+
await fs.stat(path);
|
|
930
|
+
return true;
|
|
931
|
+
} catch (err) {
|
|
932
|
+
console.log(`[ConfigRepo] safeExists(${path}): threw ${err?.code ?? err?.status ?? ""} ${err?.message ?? err}`);
|
|
933
|
+
return false;
|
|
934
|
+
}
|
|
895
935
|
}
|
|
896
936
|
/** Public wrapper for processTombstones — used by createConfigRepo. */
|
|
897
937
|
async processTombstonesPublic() {
|
package/dist/index.mjs
CHANGED
|
@@ -771,37 +771,77 @@ var ConfigRepo = class {
|
|
|
771
771
|
/**
|
|
772
772
|
* Before sync: for each tombstone, delete the actual file on all replicas.
|
|
773
773
|
* This prevents bi-directional sync from copying the file back.
|
|
774
|
+
*
|
|
775
|
+
* Before calling unlink() on each backend, we check exists() first.
|
|
776
|
+
* This avoids sending wasteful DELETE requests (or GET-then-404) to
|
|
777
|
+
* remote backends when the file was already removed on a previous cycle.
|
|
778
|
+
* Local backends (IndexedDB) are cheap to check, so the guard is
|
|
779
|
+
* effectively free for them.
|
|
774
780
|
*/
|
|
775
781
|
async processTombstones() {
|
|
776
782
|
const tombstones = await this.readTombstones();
|
|
777
783
|
if (tombstones.length === 0) return;
|
|
778
|
-
|
|
784
|
+
let processed = 0;
|
|
785
|
+
let alreadyDeleted = 0;
|
|
779
786
|
for (const tombstone of tombstones) {
|
|
780
787
|
const tVersionPath = versionPathFor(tombstone.path);
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
788
|
+
const existedOnPrimary = await this.safeExists(this.cachedFS, tombstone.path);
|
|
789
|
+
console.log(`[ConfigRepo] tombstone check: ${tombstone.path} on primary \u2192 ${existedOnPrimary ? "EXISTS" : "not found"}`);
|
|
790
|
+
if (existedOnPrimary) {
|
|
791
|
+
try {
|
|
792
|
+
await this.cachedFS.unlink(tombstone.path);
|
|
793
|
+
processed++;
|
|
794
|
+
} catch {
|
|
795
|
+
}
|
|
784
796
|
}
|
|
785
|
-
if (tVersionPath) {
|
|
797
|
+
if (tVersionPath && await this.safeExists(this.cachedFS, tVersionPath)) {
|
|
786
798
|
try {
|
|
787
799
|
await this.cachedFS.unlink(tVersionPath);
|
|
788
800
|
} catch {
|
|
789
801
|
}
|
|
790
802
|
}
|
|
791
803
|
for (const [replicaId, replica] of this.replicaBackends) {
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
804
|
+
const existed = await this.safeExists(replica.instance, tombstone.path);
|
|
805
|
+
console.log(`[ConfigRepo] tombstone check: ${tombstone.path} on ${replicaId} \u2192 ${existed ? "EXISTS" : "not found"}`);
|
|
806
|
+
if (existed) {
|
|
807
|
+
try {
|
|
808
|
+
await replica.instance.unlink(tombstone.path);
|
|
809
|
+
console.log(`[ConfigRepo] tombstone ${tombstone.path}: deleted on ${replicaId}`);
|
|
810
|
+
processed++;
|
|
811
|
+
} catch {
|
|
812
|
+
alreadyDeleted++;
|
|
813
|
+
}
|
|
814
|
+
} else {
|
|
815
|
+
alreadyDeleted++;
|
|
795
816
|
}
|
|
796
|
-
if (tVersionPath) {
|
|
817
|
+
if (tVersionPath && await this.safeExists(replica.instance, tVersionPath)) {
|
|
797
818
|
try {
|
|
798
819
|
await replica.instance.unlink(tVersionPath);
|
|
799
820
|
} catch {
|
|
800
821
|
}
|
|
801
822
|
}
|
|
802
|
-
console.log(`[ConfigRepo] tombstone ${tombstone.path}: deleted on ${replicaId}`);
|
|
803
823
|
}
|
|
804
824
|
}
|
|
825
|
+
if (processed > 0 || alreadyDeleted > 0) {
|
|
826
|
+
console.log(`[ConfigRepo] processTombstones: ${tombstones.length} tombstone(s), ${processed} deleted, ${alreadyDeleted} already gone`);
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
/**
|
|
830
|
+
* Safe existence check — returns false on any error instead of throwing.
|
|
831
|
+
* Used by processTombstones to avoid unnecessary unlink() calls.
|
|
832
|
+
*/
|
|
833
|
+
async safeExists(fs, path) {
|
|
834
|
+
try {
|
|
835
|
+
if (typeof fs.exists === "function") {
|
|
836
|
+
const result = await fs.exists(path);
|
|
837
|
+
return result;
|
|
838
|
+
}
|
|
839
|
+
await fs.stat(path);
|
|
840
|
+
return true;
|
|
841
|
+
} catch (err) {
|
|
842
|
+
console.log(`[ConfigRepo] safeExists(${path}): threw ${err?.code ?? err?.status ?? ""} ${err?.message ?? err}`);
|
|
843
|
+
return false;
|
|
844
|
+
}
|
|
805
845
|
}
|
|
806
846
|
/** Public wrapper for processTombstones — used by createConfigRepo. */
|
|
807
847
|
async processTombstonesPublic() {
|