core-3nweb-client-lib 0.44.2 → 0.44.3

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.
@@ -622,6 +622,12 @@ declare namespace web3n.files {
622
622
 
623
623
  interface ReadonlyFileSyncAPI {
624
624
 
625
+ /**
626
+ * When connection exception is caught, use this to await connection to continue.
627
+ * This returns a promise, resolvable when connected to storage server.
628
+ */
629
+ whenConnected(): Promise<void>;
630
+
625
631
  /**
626
632
  * Returns synchronization status of this object.
627
633
  * @param skipServerCheck is optional parameter to skip server check, that may be handy in offline
@@ -1404,6 +1410,12 @@ declare namespace web3n.files {
1404
1410
 
1405
1411
  interface ReadonlyFSSyncAPI {
1406
1412
 
1413
+ /**
1414
+ * When connection exception is caught, use this to await connection to continue.
1415
+ * This returns a promise, resolvable when connected to storage server.
1416
+ */
1417
+ whenConnected(): Promise<void>;
1418
+
1407
1419
  /**
1408
1420
  * Returns synchronization status of item at given path.
1409
1421
  * @param path
@@ -1481,7 +1493,7 @@ declare namespace web3n.files {
1481
1493
  */
1482
1494
  getRemoteFolderItem(path: string, remoteItemName: string, remoteVersion?: number): Promise<ReadonlyFS>;
1483
1495
 
1484
- // XXX method to work around demaged files
1496
+ // XXX method to work around damaged files
1485
1497
  // reloadFromServer(path: string): Promise<SyncStatus>;
1486
1498
 
1487
1499
  }
@@ -17,5 +17,6 @@ export declare class IdKeysStorage {
17
17
  };
18
18
  getSavedKey(): Promise<JsonKey | undefined>;
19
19
  private setStorageFS;
20
+ private ensureDataFolderIsUploaded;
20
21
  }
21
22
  export {};
@@ -72,9 +72,6 @@ class IdKeysStorage {
72
72
  this.fs = fs;
73
73
  if (keysToSave) {
74
74
  await this.fs.writeJSONFile(LOGIN_KEY_FILE_NAME, keysToSave);
75
- // XXX must add work with not-online condition
76
- await this.fs.v.sync.upload(LOGIN_KEY_FILE_NAME);
77
- await this.fs.v.sync.upload('');
78
75
  }
79
76
  else {
80
77
  try {
@@ -84,6 +81,24 @@ class IdKeysStorage {
84
81
  throw (0, error_1.errWithCause)(exc, `Fail expection read of login MailerId keys from the storage`);
85
82
  }
86
83
  }
84
+ this.ensureDataFolderIsUploaded();
85
+ }
86
+ async ensureDataFolderIsUploaded() {
87
+ try {
88
+ const fileStatus = await this.fs.v.sync.status(LOGIN_KEY_FILE_NAME, false);
89
+ if (fileStatus.state === 'unsynced') {
90
+ await this.fs.v.sync.upload(LOGIN_KEY_FILE_NAME);
91
+ }
92
+ const folderStatus = await this.fs.v.sync.status('', true);
93
+ if (folderStatus.state === 'unsynced') {
94
+ await this.fs.v.sync.upload('');
95
+ }
96
+ }
97
+ catch (exc) {
98
+ if (exc.type === 'connect') {
99
+ return this.fs.v.sync.whenConnected().then(() => this.ensureDataFolderIsUploaded());
100
+ }
101
+ }
87
102
  }
88
103
  }
89
104
  exports.IdKeysStorage = IdKeysStorage;
@@ -19,10 +19,13 @@ export declare class RemoteEvents {
19
19
  private readonly connectionEvents;
20
20
  readonly connectionEvent$: Observable<StorageConnectionStatus>;
21
21
  private readonly wsProc;
22
+ private deferredConnection;
22
23
  constructor(remoteStorage: StorageOwner, files: ObjFiles, broadcastNodeEvent: Storage['broadcastNodeEvent'], logError: LogError);
23
24
  private makeProc;
24
25
  startListening(): void;
25
26
  close(): Promise<void>;
27
+ whenConnected(): Promise<void>;
28
+ private signalConnected;
26
29
  private absorbObjChange;
27
30
  private absorbObjRemoval;
28
31
  private absorbObjVersionArchival;
@@ -21,6 +21,7 @@ const rxjs_1 = require("rxjs");
21
21
  const owner_1 = require("../../../lib-common/service-api/3nstorage/owner");
22
22
  const operators_1 = require("rxjs/operators");
23
23
  const ws_ipc_1 = require("../../../lib-common/ipc/ws-ipc");
24
+ const deferred_1 = require("../../../lib-common/processes/deferred");
24
25
  function toStorageConnectionStatus(status, params) {
25
26
  return (0, ws_ipc_1.addToStatus)(status, {
26
27
  service: 'storage',
@@ -40,13 +41,25 @@ class RemoteEvents {
40
41
  this.logError = logError;
41
42
  this.connectionEvents = new rxjs_1.Subject();
42
43
  this.connectionEvent$ = this.connectionEvents.asObservable().pipe((0, operators_1.share)());
44
+ this.deferredConnection = (0, deferred_1.defer)();
43
45
  this.wsProc = new ws_ipc_1.WebSocketListening(SERVER_EVENTS_RESTART_WAIT_SECS, this.makeProc.bind(this));
44
46
  Object.seal(this);
45
47
  }
46
48
  makeProc() {
47
49
  return (0, rxjs_1.from)(this.remoteStorage.openEventSource().then(({ client, heartbeat }) => {
50
+ this.signalConnected();
48
51
  heartbeat.subscribe({
49
- next: ev => this.connectionEvents.next(toStorageConnectionStatus(ev))
52
+ next: ev => {
53
+ this.connectionEvents.next(toStorageConnectionStatus(ev));
54
+ if (ev.type === 'heartbeat') {
55
+ this.signalConnected();
56
+ }
57
+ else if ((ev.type === 'heartbeat-skip') || (ev.type === 'disconnected')) {
58
+ if (!this.deferredConnection) {
59
+ this.deferredConnection = (0, deferred_1.defer)();
60
+ }
61
+ }
62
+ }
50
63
  });
51
64
  return [
52
65
  this.absorbObjChange(client),
@@ -65,6 +78,16 @@ class RemoteEvents {
65
78
  this.connectionEvents.complete();
66
79
  this.wsProc.close();
67
80
  }
81
+ async whenConnected() {
82
+ var _a;
83
+ return (_a = this.deferredConnection) === null || _a === void 0 ? void 0 : _a.promise;
84
+ }
85
+ signalConnected() {
86
+ if (this.deferredConnection) {
87
+ this.deferredConnection.resolve();
88
+ this.deferredConnection = undefined;
89
+ }
90
+ }
68
91
  absorbObjChange(client) {
69
92
  return (new rxjs_1.Observable(obs => client.subscribe(owner_1.events.objChanged.EVENT_NAME, obs)))
70
93
  .pipe((0, operators_1.mergeMap)(async ({ newVer: newRemoteVersion, objId }) => {
@@ -62,5 +62,6 @@ export declare class SyncedStore implements ISyncedStorage {
62
62
  suspendNetworkActivity(): void;
63
63
  resumeNetworkActivity(): void;
64
64
  get connectionEvent$(): Observable<import("./remote-events").StorageConnectionStatus>;
65
+ whenConnected(): Promise<void>;
65
66
  }
66
67
  export {};
@@ -248,6 +248,9 @@ class SyncedStore {
248
248
  get connectionEvent$() {
249
249
  return this.remoteEvents.connectionEvent$;
250
250
  }
251
+ whenConnected() {
252
+ return this.remoteEvents.whenConnected();
253
+ }
251
254
  }
252
255
  exports.SyncedStore = SyncedStore;
253
256
  Object.freeze(SyncedStore.prototype);
@@ -151,6 +151,10 @@ export declare namespace vGetByteSink {
151
151
  function wrapService(fn: WritableFileVersionedAPI['getByteSink'], expServices: CoreSideServices): ExposedFn;
152
152
  function makeCaller(caller: Caller, objPath: string[]): WritableFileVersionedAPI['getByteSink'];
153
153
  }
154
+ export declare namespace vsWhenConnected {
155
+ function wrapService(fn: ReadonlyFileSyncAPI['whenConnected']): ExposedFn;
156
+ function makeCaller(caller: Caller, objPath: string[]): ReadonlyFileSyncAPI['whenConnected'];
157
+ }
154
158
  export declare namespace vsStartDownload {
155
159
  const replyType: ProtoType<{
156
160
  startedDownload?: {
@@ -16,7 +16,7 @@
16
16
  this program. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
18
  Object.defineProperty(exports, "__esModule", { value: true });
19
- exports.vsDiffCurrentAndRemoteVersions = exports.vListVersions = exports.vsUpload = exports.vsStartUpload = exports.vsStartDownload = exports.vGetByteSink = exports.updateXAttrs = exports.vGetByteSource = exports.vReadJSON = exports.vReadTxt = exports.vReadBytes = exports.vListXAttrs = exports.vGetXAttr = exports.vStat = exports.readBytes = exports.fileMsgType = void 0;
19
+ exports.vsDiffCurrentAndRemoteVersions = exports.vListVersions = exports.vsUpload = exports.vsStartUpload = exports.vsStartDownload = exports.vsWhenConnected = exports.vGetByteSink = exports.updateXAttrs = exports.vGetByteSource = exports.vReadJSON = exports.vReadTxt = exports.vReadBytes = exports.vListXAttrs = exports.vGetXAttr = exports.vStat = exports.readBytes = exports.fileMsgType = void 0;
20
20
  exports.makeFileCaller = makeFileCaller;
21
21
  exports.exposeFileService = exposeFileService;
22
22
  exports.packStats = packStats;
@@ -100,6 +100,7 @@ function makeFileCaller(caller, fileMsg) {
100
100
  if (fileMsg.isSynced) {
101
101
  const vsPath = (0, protobuf_msg_1.methodPathFor)(vPath, 'sync');
102
102
  file.v.sync = {
103
+ whenConnected: vsWhenConnected.makeCaller(caller, vsPath),
103
104
  status: vsStatus.makeCaller(caller, vsPath),
104
105
  isRemoteVersionOnDisk: vsIsRemoteVersionOnDisk.makeCaller(caller, vsPath),
105
106
  startDownload: vsStartDownload.makeCaller(caller, vsPath),
@@ -156,6 +157,7 @@ function exposeFileService(file, expServices) {
156
157
  }
157
158
  if (file.v.sync) {
158
159
  implExp.v.sync = {
160
+ whenConnected: vsWhenConnected.wrapService(file.v.sync.whenConnected),
159
161
  status: vsStatus.wrapService(file.v.sync.status),
160
162
  isRemoteVersionOnDisk: vsIsRemoteVersionOnDisk.wrapService(file.v.sync.isRemoteVersionOnDisk),
161
163
  startDownload: vsStartDownload.wrapService(file.v.sync.startDownload),
@@ -1084,6 +1086,25 @@ var vGetByteSink;
1084
1086
  vGetByteSink.makeCaller = makeCaller;
1085
1087
  })(vGetByteSink || (exports.vGetByteSink = vGetByteSink = {}));
1086
1088
  Object.freeze(vGetByteSink);
1089
+ var vsWhenConnected;
1090
+ (function (vsWhenConnected) {
1091
+ function wrapService(fn) {
1092
+ return buf => {
1093
+ const promise = fn();
1094
+ return { promise };
1095
+ };
1096
+ }
1097
+ vsWhenConnected.wrapService = wrapService;
1098
+ function makeCaller(caller, objPath) {
1099
+ const path = (0, protobuf_msg_1.methodPathFor)(objPath, 'whenConnected');
1100
+ return () => caller
1101
+ .startPromiseCall(path, undefined)
1102
+ .then(noop);
1103
+ }
1104
+ vsWhenConnected.makeCaller = makeCaller;
1105
+ })(vsWhenConnected || (exports.vsWhenConnected = vsWhenConnected = {}));
1106
+ Object.freeze(vsWhenConnected);
1107
+ function noop() { }
1087
1108
  var vsStatus;
1088
1109
  (function (vsStatus) {
1089
1110
  function wrapService(fn) {
@@ -101,6 +101,7 @@ function makeFSCaller(caller, fsMsg) {
101
101
  if (fsMsg.isSynced) {
102
102
  const vsPath = (0, protobuf_msg_1.methodPathFor)(vPath, 'sync');
103
103
  fs.v.sync = {
104
+ whenConnected: file.vsWhenConnected.makeCaller(caller, vsPath),
104
105
  status: vsStatus.makeCaller(caller, vsPath),
105
106
  isRemoteVersionOnDisk: vsIsRemoteVersionOnDisk.makeCaller(caller, vsPath),
106
107
  startDownload: vsDownload.makeCaller(caller, vsPath),
@@ -186,6 +187,7 @@ function exposeFSService(fs, expServices) {
186
187
  }
187
188
  if (fs.v.sync) {
188
189
  implExp.v.sync = {
190
+ whenConnected: file.vsWhenConnected.wrapService(fs.v.sync.whenConnected),
189
191
  status: vsStatus.wrapService(fs.v.sync.status),
190
192
  isRemoteVersionOnDisk: vsIsRemoteVersionOnDisk.wrapService(fs.v.sync.isRemoteVersionOnDisk),
191
193
  startDownload: vsDownload.wrapService(fs.v.sync.startDownload),