@vrtmrz/livesync-commonlib 0.1.13 → 0.1.14-canary.0

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/README.md CHANGED
@@ -20,6 +20,8 @@ Treat every `compat/*` subpath as a migration-only interface. A source-directory
20
20
 
21
21
  The package is ESM-only and declares Node 20 or later. Browser entry points are built with browser conditions, but the host remains responsible for checking the availability of browser capabilities such as the File System Access API.
22
22
 
23
+ Every non-root module entry is available both without an extension and with an explicit `.js` suffix. For example, `@vrtmrz/livesync-commonlib/context` and `@vrtmrz/livesync-commonlib/context.js` resolve to the same runtime module and declaration file. Existing extensionless imports remain supported; consumers and review tools which require explicit JavaScript specifiers may use the `.js` form.
24
+
23
25
  ## Package entry points
24
26
 
25
27
  | Entry point | Intended use | Current contract status |
@@ -33,6 +33,7 @@ export declare class LiveSyncCouchDBReplicator extends LiveSyncAbstractReplicato
33
33
  sendChunks(setting: RemoteDBSettings, remoteDB: PouchDB.Database<EntryDoc> | undefined, showResult: boolean, fromSeq?: number | string): Promise<boolean>;
34
34
  openOneShotReplication(setting: RemoteDBSettings, showResult: boolean, retrying: boolean, syncMode: "sync" | "pullOnly" | "pushOnly", ignoreCleanLock?: boolean): Promise<boolean>;
35
35
  private closeRemoteDatabase;
36
+ private withRemoteDatabase;
36
37
  replicateAllToServer(setting: RemoteDBSettings, showingNotice?: boolean): Promise<boolean>;
37
38
  replicateAllFromServer(setting: RemoteDBSettings, showingNotice?: boolean): Promise<boolean>;
38
39
  checkReplicationConnectivity(setting: RemoteDBSettings, keepAlive: boolean, skipCheck: boolean, showResult: boolean, ignoreCleanLock?: boolean): Promise<false | {
@@ -379,9 +379,12 @@ class LiveSyncCouchDBReplicator extends LiveSyncAbstractReplicator {
379
379
  );
380
380
  return false;
381
381
  }
382
- remoteDB = d.db;
382
+ return await this.withRemoteDatabase(d.db, async (db) => this.sendChunks(setting, db, showResult, fromSeq));
383
+ }
384
+ const connectivity = await this.checkReplicationConnectivity(setting, false, false, false, false);
385
+ if (connectivity !== false) {
386
+ await this.closeRemoteDatabase(connectivity.db);
383
387
  }
384
- await this.checkReplicationConnectivity(setting, false, false, false, false);
385
388
  Logger(`Bulk sending chunks to remote database...`, showResult ? LOG_LEVEL_NOTICE : LOG_LEVEL_INFO, "fetch");
386
389
  const remoteMilestone = await remoteDB.get(MILESTONE_DOCID);
387
390
  const remoteID = remoteMilestone?.created ?? 0;
@@ -628,6 +631,13 @@ ${sendingDocs}/(${sentDocsCount} done)`,
628
631
  Logger(ex, LOG_LEVEL_VERBOSE, "sync");
629
632
  }
630
633
  }
634
+ async withRemoteDatabase(db, task) {
635
+ try {
636
+ return await task(db);
637
+ } finally {
638
+ await this.closeRemoteDatabase(db);
639
+ }
640
+ }
631
641
  replicateAllToServer(setting, showingNotice) {
632
642
  return this.openOneShotReplication(setting, showingNotice ?? false, false, "pushOnly");
633
643
  }
@@ -763,58 +773,62 @@ ${sendingDocs}/(${sentDocsCount} done)`,
763
773
  Logger(this.translate("liveSyncReplicator.checkingLastSyncPoint"), LOG_LEVEL_NOTICE, "sync");
764
774
  }
765
775
  const { db, syncOption } = ret;
766
- this.syncStatus = "STARTED";
767
- this.maxPullSeq = Number(`${ret.info.update_seq}`.split("-")[0]);
768
- this.maxPushSeq = Number(`${(await localDB.info()).update_seq}`.split("-")[0]);
769
- this.updateInfo();
770
- const docArrivedOnStart = this.docArrived;
771
- const docSentOnStart = this.docSent;
772
- if (!retrying) {
773
- this.originalSetting = setting;
774
- }
775
- this.terminateSync();
776
- const syncHandler = localDB.sync(db, {
777
- ...syncOption
778
- });
779
- const syncMode = "sync";
780
- const syncResult = await this.processSync(
781
- syncHandler,
782
- showResult,
783
- docSentOnStart,
784
- docArrivedOnStart,
785
- syncMode,
786
- retrying
787
- );
788
- if (syncResult == "DONE") {
789
- return true;
790
- }
791
- if (syncResult == "FAILED") {
792
- return false;
793
- }
794
- if (syncResult == "NEED_RESURRECT") {
776
+ try {
777
+ this.syncStatus = "STARTED";
778
+ this.maxPullSeq = Number(`${ret.info.update_seq}`.split("-")[0]);
779
+ this.maxPushSeq = Number(`${(await localDB.info()).update_seq}`.split("-")[0]);
780
+ this.updateInfo();
781
+ const docArrivedOnStart = this.docArrived;
782
+ const docSentOnStart = this.docSent;
783
+ if (!retrying) {
784
+ this.originalSetting = setting;
785
+ }
795
786
  this.terminateSync();
796
- return async () => await this.openContinuousReplication(this.originalSetting, showResult, false);
797
- }
798
- if (syncResult == "NEED_RETRY") {
799
- const tempSetting = JSON.parse(JSON.stringify(setting));
800
- tempSetting.batch_size = Math.ceil(tempSetting.batch_size / 2) + 2;
801
- tempSetting.batches_limit = Math.ceil(tempSetting.batches_limit / 2) + 2;
802
- if (tempSetting.batch_size <= 5 && tempSetting.batches_limit <= 5) {
803
- Logger(
804
- this.translate("liveSyncReplicator.cantReplicateLowerValue"),
805
- showResult ? LOG_LEVEL_NOTICE : LOG_LEVEL_INFO
806
- );
787
+ const syncHandler = localDB.sync(db, {
788
+ ...syncOption
789
+ });
790
+ const syncMode = "sync";
791
+ const syncResult = await this.processSync(
792
+ syncHandler,
793
+ showResult,
794
+ docSentOnStart,
795
+ docArrivedOnStart,
796
+ syncMode,
797
+ retrying
798
+ );
799
+ if (syncResult == "DONE") {
800
+ return true;
801
+ }
802
+ if (syncResult == "FAILED") {
807
803
  return false;
808
- } else {
809
- Logger(
810
- this.translate("liveSyncReplicator.retryLowerBatchSize", {
811
- batch_size: tempSetting.batch_size.toString(),
812
- batches_limit: tempSetting.batches_limit.toString()
813
- }),
814
- showResult ? LOG_LEVEL_NOTICE : LOG_LEVEL_INFO
815
- );
816
- return async () => await this.openContinuousReplication(tempSetting, showResult, true);
817
804
  }
805
+ if (syncResult == "NEED_RESURRECT") {
806
+ this.terminateSync();
807
+ return async () => await this.openContinuousReplication(this.originalSetting, showResult, false);
808
+ }
809
+ if (syncResult == "NEED_RETRY") {
810
+ const tempSetting = JSON.parse(JSON.stringify(setting));
811
+ tempSetting.batch_size = Math.ceil(tempSetting.batch_size / 2) + 2;
812
+ tempSetting.batches_limit = Math.ceil(tempSetting.batches_limit / 2) + 2;
813
+ if (tempSetting.batch_size <= 5 && tempSetting.batches_limit <= 5) {
814
+ Logger(
815
+ this.translate("liveSyncReplicator.cantReplicateLowerValue"),
816
+ showResult ? LOG_LEVEL_NOTICE : LOG_LEVEL_INFO
817
+ );
818
+ return false;
819
+ } else {
820
+ Logger(
821
+ this.translate("liveSyncReplicator.retryLowerBatchSize", {
822
+ batch_size: tempSetting.batch_size.toString(),
823
+ batches_limit: tempSetting.batches_limit.toString()
824
+ }),
825
+ showResult ? LOG_LEVEL_NOTICE : LOG_LEVEL_INFO
826
+ );
827
+ return async () => await this.openContinuousReplication(tempSetting, showResult, true);
828
+ }
829
+ }
830
+ } finally {
831
+ await this.closeRemoteDatabase(db);
818
832
  }
819
833
  }
820
834
  return false;
@@ -839,12 +853,16 @@ ${sendingDocs}/(${sentDocsCount} done)`,
839
853
  const con = await this.connectRemoteCouchDBWithSetting(setting, this.isMobile(), true);
840
854
  if (typeof con == "string") return;
841
855
  try {
842
- await con.db.destroy();
843
- Logger(this.translate("liveSyncReplicator.remoteDbDestroyed"), LOG_LEVEL_NOTICE);
844
- await this.tryCreateRemoteDatabase(setting);
845
- } catch (ex) {
846
- Logger(this.translate("liveSyncReplicator.remoteDbDestroyError"), LOG_LEVEL_NOTICE);
847
- Logger(ex, LOG_LEVEL_NOTICE);
856
+ try {
857
+ await con.db.destroy();
858
+ Logger(this.translate("liveSyncReplicator.remoteDbDestroyed"), LOG_LEVEL_NOTICE);
859
+ await this.tryCreateRemoteDatabase(setting);
860
+ } catch (ex) {
861
+ Logger(this.translate("liveSyncReplicator.remoteDbDestroyError"), LOG_LEVEL_NOTICE);
862
+ Logger(ex, LOG_LEVEL_NOTICE);
863
+ }
864
+ } finally {
865
+ await this.closeRemoteDatabase(con.db);
848
866
  }
849
867
  clearHandlers();
850
868
  await this.ensurePBKDF2Salt(setting, true, false);
@@ -853,6 +871,7 @@ ${sendingDocs}/(${sentDocsCount} done)`,
853
871
  this.closeReplication();
854
872
  const con2 = await this.connectRemoteCouchDBWithSetting(setting, this.isMobile(), true);
855
873
  if (typeof con2 === "string") return;
874
+ await this.closeRemoteDatabase(con2.db);
856
875
  clearHandlers();
857
876
  await this.ensurePBKDF2Salt(setting, true, false);
858
877
  Logger(this.translate("liveSyncReplicator.remoteDbCreatedOrConnected"), LOG_LEVEL_NOTICE);
@@ -864,35 +883,37 @@ ${sendingDocs}/(${sentDocsCount} done)`,
864
883
  Logger(this.translate("liveSyncReplicator.couldNotConnectToURI", { uri, dbRet }), LOG_LEVEL_NOTICE);
865
884
  return;
866
885
  }
867
- if (!await checkRemoteVersion(dbRet.db, this.migrate.bind(this), VER)) {
868
- Logger(this.translate("liveSyncReplicator.remoteDbCorrupted"), LOG_LEVEL_NOTICE);
869
- return;
870
- }
871
- const defInitPoint = {
872
- _id: MILESTONE_DOCID,
873
- type: "milestoneinfo",
874
- created: Date.now(),
875
- locked,
876
- cleaned: lockByClean,
877
- accepted_nodes: [this.nodeid],
878
- node_chunk_info: { [this.nodeid]: currentVersionRange },
879
- node_info: {},
880
- tweak_values: {}
881
- };
882
- const remoteMilestone = {
883
- ...defInitPoint,
884
- ...await resolveWithIgnoreKnownError(dbRet.db.get(MILESTONE_DOCID), defInitPoint)
885
- };
886
- remoteMilestone.node_chunk_info = { ...defInitPoint.node_chunk_info, ...remoteMilestone.node_chunk_info };
887
- remoteMilestone.accepted_nodes = [this.nodeid];
888
- remoteMilestone.locked = locked;
889
- remoteMilestone.cleaned = remoteMilestone.cleaned || lockByClean;
890
- if (locked) {
891
- Logger(this.translate("liveSyncReplicator.lockRemoteDb"), LOG_LEVEL_NOTICE);
892
- } else {
893
- Logger(this.translate("liveSyncReplicator.unlockRemoteDb"), LOG_LEVEL_NOTICE);
894
- }
895
- await dbRet.db.put(remoteMilestone);
886
+ await this.withRemoteDatabase(dbRet.db, async (db) => {
887
+ if (!await checkRemoteVersion(db, this.migrate.bind(this), VER)) {
888
+ Logger(this.translate("liveSyncReplicator.remoteDbCorrupted"), LOG_LEVEL_NOTICE);
889
+ return;
890
+ }
891
+ const defInitPoint = {
892
+ _id: MILESTONE_DOCID,
893
+ type: "milestoneinfo",
894
+ created: Date.now(),
895
+ locked,
896
+ cleaned: lockByClean,
897
+ accepted_nodes: [this.nodeid],
898
+ node_chunk_info: { [this.nodeid]: currentVersionRange },
899
+ node_info: {},
900
+ tweak_values: {}
901
+ };
902
+ const remoteMilestone = {
903
+ ...defInitPoint,
904
+ ...await resolveWithIgnoreKnownError(db.get(MILESTONE_DOCID), defInitPoint)
905
+ };
906
+ remoteMilestone.node_chunk_info = { ...defInitPoint.node_chunk_info, ...remoteMilestone.node_chunk_info };
907
+ remoteMilestone.accepted_nodes = [this.nodeid];
908
+ remoteMilestone.locked = locked;
909
+ remoteMilestone.cleaned = remoteMilestone.cleaned || lockByClean;
910
+ if (locked) {
911
+ Logger(this.translate("liveSyncReplicator.lockRemoteDb"), LOG_LEVEL_NOTICE);
912
+ } else {
913
+ Logger(this.translate("liveSyncReplicator.unlockRemoteDb"), LOG_LEVEL_NOTICE);
914
+ }
915
+ await db.put(remoteMilestone);
916
+ });
896
917
  }
897
918
  async markRemoteResolved(setting) {
898
919
  const uri = setting.couchDB_URI.replace(/\/+$/, "") + (setting.couchDB_DBNAME == "" ? "" : "/" + setting.couchDB_DBNAME);
@@ -901,33 +922,35 @@ ${sendingDocs}/(${sentDocsCount} done)`,
901
922
  Logger(this.translate("liveSyncReplicator.couldNotConnectToURI", { uri, dbRet }), LOG_LEVEL_NOTICE);
902
923
  return;
903
924
  }
904
- if (!await checkRemoteVersion(dbRet.db, this.migrate.bind(this), VER)) {
905
- Logger(this.translate("liveSyncReplicator.remoteDbCorrupted"), LOG_LEVEL_NOTICE);
906
- return;
907
- }
908
- const defInitPoint = {
909
- _id: MILESTONE_DOCID,
910
- type: "milestoneinfo",
911
- created: Date.now(),
912
- locked: false,
913
- accepted_nodes: [this.nodeid],
914
- node_info: {},
915
- node_chunk_info: { [this.nodeid]: currentVersionRange },
916
- tweak_values: {}
917
- };
918
- const remoteMilestone = {
919
- ...defInitPoint,
920
- ...await resolveWithIgnoreKnownError(dbRet.db.get(MILESTONE_DOCID), defInitPoint)
921
- };
922
- remoteMilestone.node_chunk_info = { ...defInitPoint.node_chunk_info, ...remoteMilestone.node_chunk_info };
923
- remoteMilestone.accepted_nodes = Array.from(/* @__PURE__ */ new Set([...remoteMilestone.accepted_nodes, this.nodeid]));
924
- Logger(this.translate("liveSyncReplicator.markDeviceResolved"), LOG_LEVEL_NOTICE);
925
- const result = await dbRet.db.put(remoteMilestone);
926
- if (result.ok) {
927
- Logger(this.translate("liveSyncReplicator.remoteDbMarkedResolved"), LOG_LEVEL_VERBOSE);
928
- } else {
929
- Logger(this.translate("liveSyncReplicator.couldNotMarkResolveRemoteDb"), LOG_LEVEL_NOTICE);
930
- }
925
+ await this.withRemoteDatabase(dbRet.db, async (db) => {
926
+ if (!await checkRemoteVersion(db, this.migrate.bind(this), VER)) {
927
+ Logger(this.translate("liveSyncReplicator.remoteDbCorrupted"), LOG_LEVEL_NOTICE);
928
+ return;
929
+ }
930
+ const defInitPoint = {
931
+ _id: MILESTONE_DOCID,
932
+ type: "milestoneinfo",
933
+ created: Date.now(),
934
+ locked: false,
935
+ accepted_nodes: [this.nodeid],
936
+ node_info: {},
937
+ node_chunk_info: { [this.nodeid]: currentVersionRange },
938
+ tweak_values: {}
939
+ };
940
+ const remoteMilestone = {
941
+ ...defInitPoint,
942
+ ...await resolveWithIgnoreKnownError(db.get(MILESTONE_DOCID), defInitPoint)
943
+ };
944
+ remoteMilestone.node_chunk_info = { ...defInitPoint.node_chunk_info, ...remoteMilestone.node_chunk_info };
945
+ remoteMilestone.accepted_nodes = Array.from(/* @__PURE__ */ new Set([...remoteMilestone.accepted_nodes, this.nodeid]));
946
+ Logger(this.translate("liveSyncReplicator.markDeviceResolved"), LOG_LEVEL_NOTICE);
947
+ const result = await db.put(remoteMilestone);
948
+ if (result.ok) {
949
+ Logger(this.translate("liveSyncReplicator.remoteDbMarkedResolved"), LOG_LEVEL_VERBOSE);
950
+ } else {
951
+ Logger(this.translate("liveSyncReplicator.couldNotMarkResolveRemoteDb"), LOG_LEVEL_NOTICE);
952
+ }
953
+ });
931
954
  }
932
955
  connectRemoteCouchDBWithSetting(settings, isMobile, performSetup = false, skipInfo = false) {
933
956
  if (settings.encrypt && settings.passphrase == "" && !settings.permitEmptyPassphrase) {
@@ -976,14 +999,19 @@ ${sendingDocs}/(${sentDocsCount} done)`,
976
999
  * @throws {Error} Other errors that may occur during the fetch operation.
977
1000
  */
978
1001
  async fetchRemoteDocument(settings, id, db) {
1002
+ const ownsConnection = db === void 0;
1003
+ const connDB = db ?? await this._ensureConnection(settings);
979
1004
  try {
980
- const connDB = db ?? await this._ensureConnection(settings);
981
1005
  return await connDB.get(id);
982
1006
  } catch (ex) {
983
1007
  if (ex && ex.status == 404) {
984
1008
  return false;
985
1009
  }
986
1010
  throw ex;
1011
+ } finally {
1012
+ if (ownsConnection) {
1013
+ await this.closeRemoteDatabase(connDB);
1014
+ }
987
1015
  }
988
1016
  }
989
1017
  /**
@@ -995,8 +1023,15 @@ ${sendingDocs}/(${sentDocsCount} done)`,
995
1023
  * @throws {Error} If the document could not be put.
996
1024
  */
997
1025
  async putRemoteDocument(settings, doc, db) {
1026
+ const ownsConnection = db === void 0;
998
1027
  const connDB = db ?? await this._ensureConnection(settings, true);
999
- return await connDB.put(doc);
1028
+ try {
1029
+ return await connDB.put(doc);
1030
+ } finally {
1031
+ if (ownsConnection) {
1032
+ await this.closeRemoteDatabase(connDB);
1033
+ }
1034
+ }
1000
1035
  }
1001
1036
  async fetchRemoteChunks(missingChunks, showResult) {
1002
1037
  const ret = await this.connectRemoteCouchDBWithSetting(this.currentSettings, this.isMobile(), false, true);
@@ -1008,19 +1043,23 @@ ${sendingDocs}/(${sentDocsCount} done)`,
1008
1043
  );
1009
1044
  return false;
1010
1045
  }
1011
- const remoteChunks = await ret.db.allDocs({ keys: missingChunks, include_docs: true });
1012
- const errorRows = remoteChunks.rows.filter((e) => "error" in e);
1013
- if (errorRows.length > 0) {
1014
- Logger(
1015
- `Some requested chunks were not found in the remote database.`,
1016
- showResult ? LOG_LEVEL_NOTICE : LOG_LEVEL_INFO,
1017
- "fetch"
1018
- );
1019
- Logger(`Requested chunks: ${missingChunks.join(",")}`, LOG_LEVEL_VERBOSE);
1020
- Logger(`Error chunks: ${errorRows.map((e) => e.key).join(",")}`, LOG_LEVEL_VERBOSE);
1021
- }
1022
- const remoteChunkItems = remoteChunks.rows.filter((e) => !("error" in e)).map((e) => e.doc).filter((e) => e !== void 0);
1023
- return remoteChunkItems;
1046
+ return await this.withRemoteDatabase(ret.db, async (db) => {
1047
+ const remoteChunks = await db.allDocs({ keys: missingChunks, include_docs: true });
1048
+ const errorRows = remoteChunks.rows.filter((e) => "error" in e);
1049
+ if (errorRows.length > 0) {
1050
+ Logger(
1051
+ `Some requested chunks were not found in the remote database.`,
1052
+ showResult ? LOG_LEVEL_NOTICE : LOG_LEVEL_INFO,
1053
+ "fetch"
1054
+ );
1055
+ Logger(`Requested chunks: ${missingChunks.join(",")}`, LOG_LEVEL_VERBOSE);
1056
+ Logger(
1057
+ `Error chunks: ${errorRows.map((e) => e.key).join(",")}`,
1058
+ LOG_LEVEL_VERBOSE
1059
+ );
1060
+ }
1061
+ return remoteChunks.rows.filter((e) => !("error" in e)).map((e) => e.doc).filter((e) => e !== void 0);
1062
+ });
1024
1063
  }
1025
1064
  async tryConnectRemote(setting, showResult = true) {
1026
1065
  const db = await this.connectRemoteCouchDBWithSetting(setting, this.isMobile(), true);
@@ -1035,8 +1074,10 @@ ${sendingDocs}/(${sentDocsCount} done)`,
1035
1074
  );
1036
1075
  return false;
1037
1076
  }
1038
- Logger(`Connected to ${db.info.db_name} successfully`, LOG_LEVEL_NOTICE);
1039
- return true;
1077
+ return await this.withRemoteDatabase(db.db, async () => {
1078
+ Logger(`Connected to ${db.info.db_name} successfully`, LOG_LEVEL_NOTICE);
1079
+ return true;
1080
+ });
1040
1081
  }
1041
1082
  async resetRemoteTweakSettings(setting) {
1042
1083
  const uri = setting.couchDB_URI.replace(/\/+$/, "") + (setting.couchDB_DBNAME == "" ? "" : "/" + setting.couchDB_DBNAME);
@@ -1045,19 +1086,21 @@ ${sendingDocs}/(${sentDocsCount} done)`,
1045
1086
  Logger(this.translate("liveSyncReplicator.couldNotConnectToURI", { uri, dbRet }), LOG_LEVEL_NOTICE);
1046
1087
  return;
1047
1088
  }
1048
- if (!await checkRemoteVersion(dbRet.db, this.migrate.bind(this), VER)) {
1049
- Logger(this.translate("liveSyncReplicator.remoteDbCorrupted"), LOG_LEVEL_NOTICE);
1050
- return;
1051
- }
1052
- try {
1053
- const remoteMilestone = await dbRet.db.get(MILESTONE_DOCID);
1054
- remoteMilestone.tweak_values = {};
1055
- await dbRet.db.put(remoteMilestone);
1056
- Logger(`tweak values on the remote database have been cleared`, LOG_LEVEL_VERBOSE);
1057
- } catch (ex) {
1058
- Logger(`Could not retrieve remote milestone`, LOG_LEVEL_NOTICE);
1059
- throw ex;
1060
- }
1089
+ await this.withRemoteDatabase(dbRet.db, async (db) => {
1090
+ if (!await checkRemoteVersion(db, this.migrate.bind(this), VER)) {
1091
+ Logger(this.translate("liveSyncReplicator.remoteDbCorrupted"), LOG_LEVEL_NOTICE);
1092
+ return;
1093
+ }
1094
+ try {
1095
+ const remoteMilestone = await db.get(MILESTONE_DOCID);
1096
+ remoteMilestone.tweak_values = {};
1097
+ await db.put(remoteMilestone);
1098
+ Logger(`tweak values on the remote database have been cleared`, LOG_LEVEL_VERBOSE);
1099
+ } catch (ex) {
1100
+ Logger(`Could not retrieve remote milestone`, LOG_LEVEL_NOTICE);
1101
+ throw ex;
1102
+ }
1103
+ });
1061
1104
  }
1062
1105
  async setPreferredRemoteTweakSettings(setting) {
1063
1106
  const uri = setting.couchDB_URI.replace(/\/+$/, "") + (setting.couchDB_DBNAME == "" ? "" : "/" + setting.couchDB_DBNAME);
@@ -1066,19 +1109,21 @@ ${sendingDocs}/(${sentDocsCount} done)`,
1066
1109
  Logger(this.translate("liveSyncReplicator.couldNotConnectToURI", { uri, dbRet }), LOG_LEVEL_NOTICE);
1067
1110
  return;
1068
1111
  }
1069
- if (!await checkRemoteVersion(dbRet.db, this.migrate.bind(this), VER)) {
1070
- Logger(this.translate("liveSyncReplicator.remoteDbCorrupted"), LOG_LEVEL_NOTICE);
1071
- return;
1072
- }
1073
- try {
1074
- const remoteMilestone = await dbRet.db.get(MILESTONE_DOCID);
1075
- remoteMilestone.tweak_values[DEVICE_ID_PREFERRED] = extractObject(TweakValuesTemplate, { ...setting });
1076
- await dbRet.db.put(remoteMilestone);
1077
- Logger(`Preferred tweak values has been registered`, LOG_LEVEL_VERBOSE);
1078
- } catch (ex) {
1079
- Logger(`Could not retrieve remote milestone`, LOG_LEVEL_NOTICE);
1080
- throw ex;
1081
- }
1112
+ await this.withRemoteDatabase(dbRet.db, async (db) => {
1113
+ if (!await checkRemoteVersion(db, this.migrate.bind(this), VER)) {
1114
+ Logger(this.translate("liveSyncReplicator.remoteDbCorrupted"), LOG_LEVEL_NOTICE);
1115
+ return;
1116
+ }
1117
+ try {
1118
+ const remoteMilestone = await db.get(MILESTONE_DOCID);
1119
+ remoteMilestone.tweak_values[DEVICE_ID_PREFERRED] = extractObject(TweakValuesTemplate, { ...setting });
1120
+ await db.put(remoteMilestone);
1121
+ Logger(`Preferred tweak values has been registered`, LOG_LEVEL_VERBOSE);
1122
+ } catch (ex) {
1123
+ Logger(`Could not retrieve remote milestone`, LOG_LEVEL_NOTICE);
1124
+ throw ex;
1125
+ }
1126
+ });
1082
1127
  }
1083
1128
  async getRemotePreferredTweakValues(setting) {
1084
1129
  const uri = setting.couchDB_URI.replace(/\/+$/, "") + (setting.couchDB_DBNAME == "" ? "" : "/" + setting.couchDB_DBNAME);
@@ -1100,56 +1145,58 @@ ${sendingDocs}/(${sentDocsCount} done)`,
1100
1145
  error: new Error(dbRet)
1101
1146
  };
1102
1147
  }
1103
- try {
1104
- if (!await checkRemoteVersion(dbRet.db, this.migrate.bind(this), VER)) {
1105
- const error = new Error("The remote database version is not compatible");
1106
- Logger(this.translate("liveSyncReplicator.remoteDbCorrupted"), LOG_LEVEL_NOTICE);
1148
+ return await this.withRemoteDatabase(dbRet.db, async (db) => {
1149
+ try {
1150
+ if (!await checkRemoteVersion(db, this.migrate.bind(this), VER)) {
1151
+ const error = new Error("The remote database version is not compatible");
1152
+ Logger(this.translate("liveSyncReplicator.remoteDbCorrupted"), LOG_LEVEL_NOTICE);
1153
+ return {
1154
+ status: RemotePreferredTweakStatuses.UNAVAILABLE,
1155
+ error
1156
+ };
1157
+ }
1158
+ } catch (ex) {
1159
+ Logger(`Could not check the remote database version`, LOG_LEVEL_NOTICE);
1160
+ Logger(ex, LOG_LEVEL_VERBOSE);
1107
1161
  return {
1108
1162
  status: RemotePreferredTweakStatuses.UNAVAILABLE,
1109
- error
1163
+ error: ex
1110
1164
  };
1111
1165
  }
1112
- } catch (ex) {
1113
- Logger(`Could not check the remote database version`, LOG_LEVEL_NOTICE);
1114
- Logger(ex, LOG_LEVEL_VERBOSE);
1115
- return {
1116
- status: RemotePreferredTweakStatuses.UNAVAILABLE,
1117
- error: ex
1118
- };
1119
- }
1120
- try {
1121
- const remoteMilestone = await dbRet.db.get(MILESTONE_DOCID);
1122
- if (!remoteMilestone) {
1123
- return {
1124
- status: RemotePreferredTweakStatuses.NOT_CONFIGURED,
1125
- reason: RemotePreferredTweakNotConfiguredReasons.MILESTONE_MISSING
1126
- };
1127
- }
1128
- const preferred = remoteMilestone.tweak_values?.[DEVICE_ID_PREFERRED];
1129
- if (!preferred) {
1166
+ try {
1167
+ const remoteMilestone = await db.get(MILESTONE_DOCID);
1168
+ if (!remoteMilestone) {
1169
+ return {
1170
+ status: RemotePreferredTweakStatuses.NOT_CONFIGURED,
1171
+ reason: RemotePreferredTweakNotConfiguredReasons.MILESTONE_MISSING
1172
+ };
1173
+ }
1174
+ const preferred = remoteMilestone.tweak_values?.[DEVICE_ID_PREFERRED];
1175
+ if (!preferred) {
1176
+ return {
1177
+ status: RemotePreferredTweakStatuses.NOT_CONFIGURED,
1178
+ reason: RemotePreferredTweakNotConfiguredReasons.PREFERRED_VALUES_MISSING
1179
+ };
1180
+ }
1130
1181
  return {
1131
- status: RemotePreferredTweakStatuses.NOT_CONFIGURED,
1132
- reason: RemotePreferredTweakNotConfiguredReasons.PREFERRED_VALUES_MISSING
1182
+ status: RemotePreferredTweakStatuses.AVAILABLE,
1183
+ values: preferred
1133
1184
  };
1134
- }
1135
- return {
1136
- status: RemotePreferredTweakStatuses.AVAILABLE,
1137
- values: preferred
1138
- };
1139
- } catch (ex) {
1140
- if (isErrorOfMissingDoc(ex)) {
1185
+ } catch (ex) {
1186
+ if (isErrorOfMissingDoc(ex)) {
1187
+ return {
1188
+ status: RemotePreferredTweakStatuses.NOT_CONFIGURED,
1189
+ reason: RemotePreferredTweakNotConfiguredReasons.MILESTONE_MISSING
1190
+ };
1191
+ }
1192
+ Logger(`Could not retrieve remote milestone`, LOG_LEVEL_NOTICE);
1193
+ Logger(ex, LOG_LEVEL_VERBOSE);
1141
1194
  return {
1142
- status: RemotePreferredTweakStatuses.NOT_CONFIGURED,
1143
- reason: RemotePreferredTweakNotConfiguredReasons.MILESTONE_MISSING
1195
+ status: RemotePreferredTweakStatuses.UNAVAILABLE,
1196
+ error: ex
1144
1197
  };
1145
1198
  }
1146
- Logger(`Could not retrieve remote milestone`, LOG_LEVEL_NOTICE);
1147
- Logger(ex, LOG_LEVEL_VERBOSE);
1148
- return {
1149
- status: RemotePreferredTweakStatuses.UNAVAILABLE,
1150
- error: ex
1151
- };
1152
- }
1199
+ });
1153
1200
  }
1154
1201
  async compactRemote(setting) {
1155
1202
  const uri = setting.couchDB_URI.replace(/\/+$/, "") + (setting.couchDB_DBNAME == "" ? "" : "/" + setting.couchDB_DBNAME);
@@ -1158,8 +1205,7 @@ ${sendingDocs}/(${sentDocsCount} done)`,
1158
1205
  Logger(this.translate("liveSyncReplicator.couldNotConnectToURI", { uri, dbRet }), LOG_LEVEL_NOTICE);
1159
1206
  return false;
1160
1207
  }
1161
- const ret = await dbRet.db.compact({ interval: 1e3 });
1162
- return ret.ok;
1208
+ return await this.withRemoteDatabase(dbRet.db, async (db) => (await db.compact({ interval: 1e3 })).ok);
1163
1209
  }
1164
1210
  async getRemoteStatus(setting) {
1165
1211
  const dbRet = await this.connectRemoteCouchDBWithSetting(setting, this.isMobile(), true);
@@ -1168,11 +1214,13 @@ ${sendingDocs}/(${sentDocsCount} done)`,
1168
1214
  Logger(this.translate("liveSyncReplicator.couldNotConnectToURI", { uri, dbRet }), LOG_LEVEL_NOTICE);
1169
1215
  return false;
1170
1216
  }
1171
- const info = await dbRet.db.info();
1172
- return {
1173
- ...info,
1174
- estimatedSize: info?.sizes?.file || 0
1175
- };
1217
+ return await this.withRemoteDatabase(dbRet.db, async (db) => {
1218
+ const info = await db.info();
1219
+ return {
1220
+ ...info,
1221
+ estimatedSize: info?.sizes?.file || 0
1222
+ };
1223
+ });
1176
1224
  }
1177
1225
  async countCompromisedChunks(setting = this.currentSettings) {
1178
1226
  const dbRet = await this.connectRemoteCouchDBWithSetting(setting, this.isMobile(), true);
@@ -1181,8 +1229,7 @@ ${sendingDocs}/(${sentDocsCount} done)`,
1181
1229
  Logger(this.translate("liveSyncReplicator.couldNotConnectToURI", { uri, dbRet }), LOG_LEVEL_NOTICE);
1182
1230
  return false;
1183
1231
  }
1184
- const compromised = await countCompromisedChunks(dbRet.db);
1185
- return compromised;
1232
+ return await this.withRemoteDatabase(dbRet.db, countCompromisedChunks);
1186
1233
  }
1187
1234
  async getConnectedDeviceList(setting = this.currentSettings) {
1188
1235
  const dbRet = await this.connectRemoteCouchDBWithSetting(setting, this.isMobile(), true);
@@ -1191,14 +1238,16 @@ ${sendingDocs}/(${sentDocsCount} done)`,
1191
1238
  Logger(this.translate("liveSyncReplicator.couldNotConnectToURI", { uri, dbRet }), LOG_LEVEL_NOTICE);
1192
1239
  return false;
1193
1240
  }
1194
- const milestoneDoc = await dbRet.db.get(MILESTONE_DOCID);
1195
- if (!milestoneDoc) {
1196
- Logger("Could not retrieve remote milestone", LOG_LEVEL_NOTICE);
1197
- return false;
1198
- }
1199
- const nodeInfo = milestoneDoc.node_info;
1200
- const acceptedNodes = milestoneDoc.accepted_nodes || [];
1201
- return { node_info: nodeInfo, accepted_nodes: acceptedNodes };
1241
+ return await this.withRemoteDatabase(dbRet.db, async (db) => {
1242
+ const milestoneDoc = await db.get(MILESTONE_DOCID);
1243
+ if (!milestoneDoc) {
1244
+ Logger("Could not retrieve remote milestone", LOG_LEVEL_NOTICE);
1245
+ return false;
1246
+ }
1247
+ const nodeInfo = milestoneDoc.node_info;
1248
+ const acceptedNodes = milestoneDoc.accepted_nodes || [];
1249
+ return { node_info: nodeInfo, accepted_nodes: acceptedNodes };
1250
+ });
1202
1251
  }
1203
1252
  }
1204
1253
  export {