core-3nweb-client-lib 0.26.1 → 0.27.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.
Files changed (199) hide show
  1. package/build/api-defs/asmail.d.ts +1 -1
  2. package/build/api-defs/files.d.ts +278 -69
  3. package/build/core/app-files.js +7 -7
  4. package/build/core/asmail/config/common.js +2 -2
  5. package/build/core/asmail/config/index.js +2 -2
  6. package/build/core/asmail/config/published-intro-key.js +1 -1
  7. package/build/core/asmail/delivery/common.js +7 -7
  8. package/build/core/asmail/delivery/index.js +5 -5
  9. package/build/core/asmail/delivery/msg.js +4 -4
  10. package/build/core/asmail/delivery/per-recipient-wip.js +1 -1
  11. package/build/core/asmail/inbox/attachments/fs.js +5 -1
  12. package/build/core/asmail/inbox/cached-msgs.js +1 -1
  13. package/build/core/asmail/inbox/inbox-events.js +4 -4
  14. package/build/core/asmail/inbox/index.js +10 -10
  15. package/build/core/asmail/inbox/msg-downloader.js +1 -1
  16. package/build/core/asmail/inbox/msg-indexing.js +1 -1
  17. package/build/core/asmail/inbox/msg-on-disk.js +5 -5
  18. package/build/core/asmail/index.d.ts +3 -3
  19. package/build/core/asmail/index.js +13 -8
  20. package/build/core/asmail/key-verification.js +5 -5
  21. package/build/core/asmail/keyring/common.js +7 -6
  22. package/build/core/asmail/keyring/correspondent-keys.js +8 -7
  23. package/build/core/asmail/keyring/id-to-email-map.js +2 -1
  24. package/build/core/asmail/keyring/index.d.ts +7 -8
  25. package/build/core/asmail/keyring/index.js +15 -14
  26. package/build/core/asmail/keyring/keyring-storage.js +2 -1
  27. package/build/core/asmail/msg/opener.js +3 -3
  28. package/build/core/asmail/msg/packer.js +13 -13
  29. package/build/core/asmail/sending-params/own-params.js +2 -2
  30. package/build/core/asmail/sending-params/params-from-others.js +1 -1
  31. package/build/core/id-manager.js +6 -3
  32. package/build/core/index.d.ts +2 -1
  33. package/build/core/index.js +14 -14
  34. package/build/core/sign-in.js +5 -5
  35. package/build/core/sign-up.js +9 -9
  36. package/build/core/storage/common/json-saving.js +2 -2
  37. package/build/core/storage/common/obj-info-file.d.ts +12 -4
  38. package/build/core/storage/common/obj-info-file.js +66 -34
  39. package/build/core/storage/common/utils.d.ts +2 -0
  40. package/build/core/storage/common/utils.js +32 -0
  41. package/build/core/storage/index.d.ts +3 -17
  42. package/build/core/storage/index.js +56 -76
  43. package/build/core/storage/local/obj-files-gc.d.ts +2 -0
  44. package/build/core/storage/local/obj-files-gc.js +49 -37
  45. package/build/core/storage/local/obj-files.d.ts +4 -7
  46. package/build/core/storage/local/obj-files.js +7 -10
  47. package/build/core/storage/local/obj-status.d.ts +12 -6
  48. package/build/core/storage/local/obj-status.js +24 -9
  49. package/build/core/storage/local/storage.d.ts +9 -6
  50. package/build/core/storage/local/storage.js +29 -18
  51. package/build/core/storage/synced/downloader.js +1 -1
  52. package/build/core/storage/synced/obj-files-gc.d.ts +5 -1
  53. package/build/core/storage/synced/obj-files-gc.js +91 -37
  54. package/build/core/storage/synced/obj-files.d.ts +42 -36
  55. package/build/core/storage/synced/obj-files.js +178 -147
  56. package/build/core/storage/synced/obj-status.d.ts +87 -85
  57. package/build/core/storage/synced/obj-status.js +463 -259
  58. package/build/core/storage/synced/remote-events.d.ts +11 -12
  59. package/build/core/storage/synced/remote-events.js +73 -56
  60. package/build/core/storage/synced/storage.d.ts +18 -9
  61. package/build/core/storage/synced/storage.js +108 -48
  62. package/build/core/storage/synced/upload-header-file.d.ts +4 -0
  63. package/build/core/storage/synced/upload-header-file.js +64 -0
  64. package/build/core/storage/synced/upsyncer.d.ts +12 -7
  65. package/build/core/storage/synced/upsyncer.js +205 -280
  66. package/build/core/storage/system-folders/apps-data.d.ts +16 -0
  67. package/build/core/storage/system-folders/apps-data.js +110 -0
  68. package/build/core/storage/system-folders/index.d.ts +18 -0
  69. package/build/core/storage/system-folders/index.js +77 -0
  70. package/build/core-ipc/common-caps.js +3 -3
  71. package/build/core-ipc/generic.js +8 -8
  72. package/build/core-ipc/startup-caps.js +2 -2
  73. package/build/cryptors.js +6 -2
  74. package/build/ipc-via-protobuf/asmail-cap.js +58 -57
  75. package/build/ipc-via-protobuf/bytes.js +16 -17
  76. package/build/ipc-via-protobuf/connector-clients-side.d.ts +1 -0
  77. package/build/ipc-via-protobuf/connector-clients-side.js +14 -15
  78. package/build/ipc-via-protobuf/connector-services-side.js +10 -10
  79. package/build/ipc-via-protobuf/connector.js +4 -4
  80. package/build/ipc-via-protobuf/file.d.ts +48 -12
  81. package/build/ipc-via-protobuf/file.js +474 -126
  82. package/build/ipc-via-protobuf/fs.d.ts +8 -0
  83. package/build/ipc-via-protobuf/fs.js +577 -142
  84. package/build/ipc-via-protobuf/log-cap.js +2 -2
  85. package/build/ipc-via-protobuf/mailerid.js +3 -3
  86. package/build/ipc-via-protobuf/protobuf-msg.d.ts +1 -0
  87. package/build/ipc-via-protobuf/protobuf-msg.js +11 -7
  88. package/build/ipc-via-protobuf/startup-cap.js +21 -21
  89. package/build/ipc-via-protobuf/storage-cap.js +12 -12
  90. package/build/ipc.js +7 -2
  91. package/build/lib-client/3nstorage/exceptions.d.ts +3 -0
  92. package/build/lib-client/3nstorage/exceptions.js +13 -1
  93. package/build/lib-client/3nstorage/service.d.ts +16 -2
  94. package/build/lib-client/3nstorage/service.js +104 -38
  95. package/build/lib-client/3nstorage/util/file-based-json.d.ts +2 -1
  96. package/build/lib-client/3nstorage/util/file-based-json.js +1 -1
  97. package/build/lib-client/3nstorage/xsp-fs/attrs.js +17 -17
  98. package/build/lib-client/3nstorage/xsp-fs/common.d.ts +42 -18
  99. package/build/lib-client/3nstorage/xsp-fs/common.js +29 -19
  100. package/build/lib-client/3nstorage/xsp-fs/file-node.d.ts +1 -0
  101. package/build/lib-client/3nstorage/xsp-fs/file-node.js +17 -13
  102. package/build/lib-client/3nstorage/xsp-fs/file.d.ts +31 -6
  103. package/build/lib-client/3nstorage/xsp-fs/file.js +73 -25
  104. package/build/lib-client/3nstorage/xsp-fs/folder-node-serialization.js +4 -4
  105. package/build/lib-client/3nstorage/xsp-fs/folder-node.d.ts +24 -11
  106. package/build/lib-client/3nstorage/xsp-fs/folder-node.js +575 -179
  107. package/build/lib-client/3nstorage/xsp-fs/fs.d.ts +35 -4
  108. package/build/lib-client/3nstorage/xsp-fs/fs.js +231 -110
  109. package/build/lib-client/3nstorage/xsp-fs/link-node.d.ts +1 -0
  110. package/build/lib-client/3nstorage/xsp-fs/link-node.js +7 -2
  111. package/build/lib-client/3nstorage/xsp-fs/node-in-fs.d.ts +30 -24
  112. package/build/lib-client/3nstorage/xsp-fs/node-in-fs.js +229 -123
  113. package/build/lib-client/3nstorage/xsp-fs/node-persistence.d.ts +1 -1
  114. package/build/lib-client/3nstorage/xsp-fs/node-persistence.js +17 -18
  115. package/build/lib-client/3nstorage/xsp-fs/xsp-payload-v1.js +3 -3
  116. package/build/lib-client/3nstorage/xsp-fs/xsp-payload-v2.js +53 -53
  117. package/build/lib-client/3nweb-signup.js +4 -4
  118. package/build/lib-client/asmail/recipient.js +15 -15
  119. package/build/lib-client/asmail/sender.js +22 -22
  120. package/build/lib-client/asmail/service-config.js +3 -3
  121. package/build/lib-client/cryptor/cryptor-in-worker.js +18 -16
  122. package/build/lib-client/cryptor/cryptor-wasm.js +1 -1
  123. package/build/lib-client/cryptor/cryptor.js +4 -2
  124. package/build/lib-client/cryptor/cryptor.wasm +0 -0
  125. package/build/lib-client/cryptor/in-proc-js.js +1 -1
  126. package/build/lib-client/cryptor/in-proc-wasm.js +6 -6
  127. package/build/lib-client/cryptor/worker-js.js +2 -2
  128. package/build/lib-client/cryptor/worker-wasm.js +2 -2
  129. package/build/lib-client/files-select.js +1 -1
  130. package/build/lib-client/files.d.ts +1 -1
  131. package/build/lib-client/files.js +71 -6
  132. package/build/lib-client/fs-collection.js +1 -1
  133. package/build/lib-client/fs-sync-utils.d.ts +5 -0
  134. package/build/lib-client/fs-sync-utils.js +61 -0
  135. package/build/lib-client/fs-view.d.ts +14 -0
  136. package/build/lib-client/fs-view.js +33 -0
  137. package/build/lib-client/key-derivation.js +1 -1
  138. package/build/lib-client/local-files/dev-file-sink.js +9 -9
  139. package/build/lib-client/local-files/dev-file-src.js +2 -2
  140. package/build/lib-client/local-files/device-fs.d.ts +1 -1
  141. package/build/lib-client/local-files/device-fs.js +56 -54
  142. package/build/lib-client/logging/log-to-file.d.ts +1 -1
  143. package/build/lib-client/logging/log-to-file.js +7 -7
  144. package/build/lib-client/mailer-id/login.js +7 -7
  145. package/build/lib-client/mailer-id/provisioner.js +12 -12
  146. package/build/lib-client/objs-on-disk/file-writing-proc.js +3 -3
  147. package/build/lib-client/objs-on-disk/obj-folders.js +31 -31
  148. package/build/lib-client/objs-on-disk/obj-on-disk.d.ts +13 -2
  149. package/build/lib-client/objs-on-disk/obj-on-disk.js +24 -9
  150. package/build/lib-client/request-utils.d.ts +1 -0
  151. package/build/lib-client/request-utils.js +13 -13
  152. package/build/lib-client/server-events.d.ts +3 -3
  153. package/build/lib-client/server-events.js +9 -8
  154. package/build/lib-client/service-locator.js +10 -10
  155. package/build/lib-client/user-with-mid-session.js +7 -7
  156. package/build/lib-client/user-with-pkl-session.js +25 -25
  157. package/build/lib-client/ws-utils.js +2 -2
  158. package/build/lib-common/async-cryptor-wrap.js +4 -4
  159. package/build/lib-common/async-fs-node.d.ts +5 -3
  160. package/build/lib-common/async-fs-node.js +16 -16
  161. package/build/lib-common/byte-streaming/pipe.js +1 -1
  162. package/build/lib-common/byte-streaming/wrapping.js +13 -13
  163. package/build/lib-common/canonical-address.js +1 -1
  164. package/build/lib-common/exceptions/error.d.ts +1 -0
  165. package/build/lib-common/exceptions/error.js +7 -6
  166. package/build/lib-common/exceptions/file.js +4 -0
  167. package/build/lib-common/ipc/ws-ipc.js +2 -2
  168. package/build/lib-common/mid-sigs-NaCl-Ed.js +14 -14
  169. package/build/lib-common/objs-on-disk/file-layout.d.ts +19 -0
  170. package/build/lib-common/objs-on-disk/file-layout.js +130 -12
  171. package/build/lib-common/objs-on-disk/obj-file.d.ts +13 -2
  172. package/build/lib-common/objs-on-disk/obj-file.js +96 -35
  173. package/build/lib-common/objs-on-disk/utils.d.ts +1 -0
  174. package/build/lib-common/objs-on-disk/utils.js +3 -3
  175. package/build/lib-common/objs-on-disk/v1-obj-file-format.js +14 -14
  176. package/build/lib-common/processes/labelled-exec-pools.d.ts +1 -1
  177. package/build/lib-common/processes/labelled-exec-pools.js +1 -1
  178. package/build/lib-common/processes/pressure.js +2 -2
  179. package/build/lib-common/processes/synced.js +1 -1
  180. package/build/lib-common/processes/timeout.js +2 -2
  181. package/build/lib-common/random-node.js +7 -7
  182. package/build/lib-common/service-api/3nstorage/owner.d.ts +95 -35
  183. package/build/lib-common/service-api/3nstorage/owner.js +82 -40
  184. package/build/lib-common/service-api/asmail/delivery.js +2 -2
  185. package/build/lib-common/service-api/asmail/retrieval.js +1 -1
  186. package/build/lib-common/timed-cache.d.ts +1 -0
  187. package/build/lib-common/timed-non-weak-cache.d.ts +1 -0
  188. package/build/lib-common/timed-non-weak-cache.js +11 -0
  189. package/build/lib-common/utils-for-observables.js +4 -4
  190. package/build/lib-common/weak-cache.d.ts +1 -0
  191. package/build/lib-common/weak-cache.js +12 -1
  192. package/build/lib-index.d.ts +2 -1
  193. package/build/lib-index.js +10 -7
  194. package/build/protos/asmail.proto.js +12955 -7496
  195. package/build/protos/file.proto.js +4867 -2744
  196. package/build/protos/fs.proto.js +9227 -3768
  197. package/package.json +6 -5
  198. package/protos/file.proto +91 -19
  199. package/protos/fs.proto +107 -8
@@ -1,22 +1,29 @@
1
1
  import { Observable } from 'rxjs';
2
- import { ObjId } from '../../../lib-client/3nstorage/xsp-fs/common';
2
+ import { ObjId, SyncedObjStatus } from '../../../lib-client/3nstorage/xsp-fs/common';
3
3
  import { InitDownloadParts } from '../../../lib-client/objs-on-disk/obj-on-disk';
4
4
  import { ObjSource, Subscribe } from 'xsp-files';
5
5
  import { Downloader } from './downloader';
6
6
  import { FileWrite } from '../../../lib-client/objs-on-disk/file-writing-proc';
7
7
  import { GC } from './obj-files-gc';
8
- import { UpSyncStatus } from './obj-status';
8
+ import { ObjStatus } from './obj-status';
9
9
  import { LogError } from '../../../lib-client/logging/log-to-file';
10
+ import { DiffInfo } from '../../../lib-common/service-api/3nstorage/owner';
11
+ import { FiniteChunk } from '../../../lib-common/objs-on-disk/file-layout';
12
+ import { StorageOwner as RemoteStorage } from '../../../lib-client/3nstorage/service';
13
+ import { UploadHeaderChange } from '../../../lib-client/3nstorage/xsp-fs/common';
14
+ export declare const UNSYNCED_FILE_NAME_EXT = "unsynced";
15
+ export declare const REMOTE_FILE_NAME_EXT = "v";
10
16
  export declare class ObjFiles {
11
17
  private readonly folders;
12
- private readonly downloader;
13
18
  private readonly logError;
14
19
  private readonly objs;
15
20
  private readonly sync;
21
+ private readonly downloader;
16
22
  private readonly gc;
17
23
  private constructor();
18
- static makeFor(path: string, downloader: Downloader, logError: LogError): Promise<ObjFiles>;
24
+ static makeFor(path: string, remote: RemoteStorage, logError: LogError): Promise<ObjFiles>;
19
25
  findObj(objId: ObjId): Promise<SyncedObj | undefined>;
26
+ getObjInCache(objId: ObjId): SyncedObj | undefined;
20
27
  private makeObj;
21
28
  private removeFailedNewObj;
22
29
  makeByDownloadingCurrentVersion(objId: ObjId): Promise<SyncedObj>;
@@ -24,7 +31,8 @@ export declare class ObjFiles {
24
31
  fileWrite$: Observable<FileWrite[]>;
25
32
  newObj: SyncedObj;
26
33
  }>;
27
- collectUnsyncedObjs(): Observable<ObjId>;
34
+ findUnsyncedObjs(): Observable<ObjId>;
35
+ scheduleGC(obj: SyncedObj): void;
28
36
  }
29
37
  export declare type SynchronizerOnObjId = <T>(objId: ObjId, action: () => Promise<T>) => Promise<T>;
30
38
  export declare class SyncedObj {
@@ -33,46 +41,44 @@ export declare class SyncedObj {
33
41
  private readonly status;
34
42
  private readonly downloader;
35
43
  private readonly scheduleGC;
36
- /**
37
- * These versions are what simple programs see. It is a local opinion about
38
- * object's versions. Versions here can be either synced, or unsynced.
39
- */
40
- private readonly verObjs;
41
- /**
42
- * These are conflicting versions, coming from a server. Of course, universal
43
- * truth is spread by server, but in situations of parallel changes, local
44
- * version allows things to work, while conflicting version from server
45
- * should be adopted by conflict resolution process. In other words, these
46
- * versions are not for common use.
47
- */
48
- private readonly remoteConflictVerObjs;
44
+ private readonly remoteVers;
45
+ private readonly localVers;
49
46
  private constructor();
50
47
  static forExistingObj(objId: ObjId, objFolder: string, downloader: Downloader, scheduleGC: GC['scheduleCollection'], logError: LogError): Promise<SyncedObj>;
51
48
  static forDownloadedObj(objId: ObjId, objFolder: string, downloader: Downloader, scheduleGC: GC['scheduleCollection'], version: number, parts: InitDownloadParts, logError: LogError): Promise<SyncedObj>;
52
49
  static forNewObj(objId: ObjId, objFolder: string, downloader: Downloader, scheduleGC: GC['scheduleCollection'], logError: LogError): Promise<SyncedObj>;
53
- sync(): UpSyncStatus;
54
50
  scheduleSelfGC(): void;
55
- private path;
56
- getObjSrc(version: number): Promise<ObjSource>;
57
- private objSegsGetterFromDisk;
58
- getRemoteConflictObjVersion(version: number): Promise<ObjSource>;
59
- private conflictObjSegsGetterFromDisk;
51
+ private localVerPath;
52
+ private remoteVerPath;
53
+ getObjSrcFromLocalAndSyncedBranch(version: number): Promise<ObjSource>;
54
+ getObjSrcFromRemoteAndSyncedBranch(version: number): Promise<ObjSource>;
55
+ private instanceOfLocalObjVer;
56
+ private instanceOfRemoteObjVer;
57
+ private readonly localAndSyncedObjSegsGetterFromDisk;
58
+ private readonly remoteObjSegsGetterFromDisk;
60
59
  saveNewVersion(version: number, encSub: Subscribe): Promise<{
61
60
  fileWrite$: Observable<FileWrite[]>;
62
61
  baseVer?: number;
63
62
  }>;
64
- isArchived(): boolean;
65
- getCurrentVersionOrThrow(): number;
66
- isRemoteVersionGreaterOrEqualTo(newRemoteVersion: number): boolean;
67
- isDeletedOnRemote(): boolean;
63
+ combineLocalBaseIfPresent(version: number): Promise<number | undefined>;
64
+ saveUploadHeaderFile(uploadHeader: UploadHeaderChange): Promise<void>;
68
65
  private setUnsyncedCurrentVersion;
69
- markVersionSynced(version: number): Promise<void>;
70
- setRemoteVersion(version: number): Promise<void>;
71
- setDeletedOnRemote(): Promise<void>;
66
+ /**
67
+ * This renames/moves version file from local to remote.
68
+ * Removes upload info from status, updating enumerations of local and
69
+ * synced versions.
70
+ */
71
+ recordUploadCompletion(localVersion: number, uploadVersion: number, headerChange: {
72
+ newHeader: Uint8Array;
73
+ originalHeader: Uint8Array;
74
+ } | undefined): Promise<void>;
75
+ dropCachedLocalObjVersionsLessOrEqual(version: number): void;
76
+ removeLocalVersionFilesLessThan(version: number): Promise<void>;
72
77
  removeCurrentVersion(): Promise<void>;
73
- getNonGarbageVersions(): {
74
- gcMaxVer?: number;
75
- nonGarbage: Set<number>;
76
- };
77
- isStatusFileSaved(): boolean;
78
+ diffForUploadOf(version: number): Promise<{
79
+ diff: DiffInfo;
80
+ newSegsPackOrder: FiniteChunk[];
81
+ }>;
82
+ syncStatus(): SyncedObjStatus;
83
+ statusObj(): ObjStatus;
78
84
  }
@@ -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.SyncedObj = exports.ObjFiles = void 0;
19
+ exports.SyncedObj = exports.ObjFiles = exports.REMOTE_FILE_NAME_EXT = exports.UNSYNCED_FILE_NAME_EXT = void 0;
20
20
  const rxjs_1 = require("rxjs");
21
21
  const synced_1 = require("../../../lib-common/processes/synced");
22
22
  const sleep_1 = require("../../../lib-common/processes/sleep");
@@ -24,51 +24,51 @@ const obj_folders_1 = require("../../../lib-client/objs-on-disk/obj-folders");
24
24
  const fs = require("../../../lib-common/async-fs-node");
25
25
  const obj_on_disk_1 = require("../../../lib-client/objs-on-disk/obj-on-disk");
26
26
  const path_1 = require("path");
27
+ const downloader_1 = require("./downloader");
27
28
  const assert_1 = require("../../../lib-common/assert");
28
29
  const operators_1 = require("rxjs/operators");
29
30
  const utils_for_observables_1 = require("../../../lib-common/utils-for-observables");
30
31
  const obj_files_gc_1 = require("./obj-files-gc");
31
32
  const obj_status_1 = require("./obj-status");
32
33
  const timed_cache_1 = require("../../../lib-common/timed-cache");
33
- const UNSYNCED_FILE_NAME_EXT = 'unsynced';
34
- const SYNCED_FILE_NAME_EXT = 'v';
35
- const REMOTE_FILE_NAME_EXT = 'remote';
34
+ const upload_header_file_1 = require("./upload-header-file");
35
+ const utils_1 = require("../common/utils");
36
+ exports.UNSYNCED_FILE_NAME_EXT = 'unsynced';
37
+ exports.REMOTE_FILE_NAME_EXT = 'v';
36
38
  class ObjFiles {
37
- constructor(folders, downloader, logError) {
39
+ constructor(folders, remote, logError) {
38
40
  this.folders = folders;
39
- this.downloader = downloader;
40
41
  this.logError = logError;
41
- this.objs = timed_cache_1.makeTimedCache(60 * 1000);
42
+ this.objs = (0, timed_cache_1.makeTimedCache)(60 * 1000);
42
43
  this.sync = makeSynchronizer();
44
+ this.downloader = new downloader_1.Downloader(remote);
43
45
  this.gc = new obj_files_gc_1.GC(this.sync, obj => {
44
46
  if (this.objs.get(obj.objId) === obj) {
45
47
  this.objs.delete(obj.objId);
46
48
  }
47
- }, objId => this.folders.removeFolderOf(objId));
49
+ }, objId => this.folders.removeFolderOf(objId), remote);
48
50
  Object.freeze(this);
49
51
  }
50
- static async makeFor(path, downloader, logError) {
51
- const folders = await obj_folders_1.ObjFolders.makeWithGenerations(path, async (objId, objFolderPath) => {
52
+ static async makeFor(path, remote, logError) {
53
+ const canMove = async (objId, objFolderPath) => {
52
54
  if (objFiles.objs.has(objId)) {
53
55
  return false;
54
56
  }
55
57
  const lst = await fs.readdir(objFolderPath);
56
58
  for (const fName of lst) {
57
- if (fName.endsWith(UNSYNCED_FILE_NAME_EXT)) {
59
+ if (fName.endsWith(exports.UNSYNCED_FILE_NAME_EXT)) {
58
60
  return false;
59
61
  }
60
- if (fName === obj_status_1.STATUS_FILE_NAME) {
61
- if (!objFiles.objs.has(objId)) {
62
- const status = await obj_status_1.readAndCheckStatus(objFolderPath, objId).catch(noop);
63
- if (status && status.syncTasks) {
64
- return false;
65
- }
66
- }
67
- }
68
62
  }
69
- return true;
70
- }, logError);
71
- const objFiles = new ObjFiles(folders, downloader, logError);
63
+ try {
64
+ return (await obj_status_1.ObjStatus.fileShowsObjNotInSyncedState(objFolderPath, objId));
65
+ }
66
+ catch (exc) {
67
+ return false;
68
+ }
69
+ };
70
+ const folders = await obj_folders_1.ObjFolders.makeWithGenerations(path, canMove, logError);
71
+ const objFiles = new ObjFiles(folders, remote, logError);
72
72
  return objFiles;
73
73
  }
74
74
  async findObj(objId) {
@@ -86,12 +86,15 @@ class ObjFiles {
86
86
  return obj;
87
87
  });
88
88
  }
89
+ getObjInCache(objId) {
90
+ return this.objs.get(objId);
91
+ }
89
92
  makeObj(objId, download) {
90
93
  return this.sync(objId, async () => {
91
94
  const folder = await this.folders.getFolderAccessFor(objId, true);
92
95
  let obj;
93
96
  if (download) {
94
- assert_1.assert(typeof download.version === 'number');
97
+ (0, assert_1.assert)(typeof download.version === 'number');
95
98
  obj = await SyncedObj.forDownloadedObj(objId, folder, this.downloader, this.gc.scheduleCollection, download.version, download.parts, this.logError);
96
99
  }
97
100
  else {
@@ -112,6 +115,10 @@ class ObjFiles {
112
115
  return;
113
116
  });
114
117
  }
118
+ // XXX we'll need getting archived version.
119
+ // Getting current may be changed to grub info about all obj versions.
120
+ // As currently this.makeByDownloadingCurrentVersion() makes assumptions.
121
+ // Should it be a pattern: version not in status -> get info first.
115
122
  async makeByDownloadingCurrentVersion(objId) {
116
123
  // initial download implicitly checks existence of obj on server
117
124
  const download = await this.downloader.getCurrentObjVersion(objId);
@@ -121,28 +128,31 @@ class ObjFiles {
121
128
  async saveFirstVersion(objId, encSub) {
122
129
  const newObj = await this.makeObj(objId);
123
130
  const fileWrite$ = (await newObj.saveNewVersion(1, encSub)).fileWrite$
124
- .pipe(utils_for_observables_1.flatTap(undefined, err => this.removeFailedNewObj(newObj)));
131
+ .pipe((0, utils_for_observables_1.flatTap)(undefined, err => this.removeFailedNewObj(newObj)));
125
132
  return { fileWrite$, newObj };
126
133
  }
127
- collectUnsyncedObjs() {
128
- return rxjs_1.from([undefined])
134
+ findUnsyncedObjs() {
135
+ return (0, rxjs_1.from)([undefined])
129
136
  .pipe(
130
137
  // listing recent folders, exactly once
131
- operators_1.mergeMap(() => this.folders.listRecent()),
138
+ (0, operators_1.mergeMap)(() => this.folders.listRecent()),
132
139
  // flatten array and space it in time, to process folders one by one
133
- operators_1.mergeMap(objsAndPaths => objsAndPaths), operators_1.filter(({ objId }) => !this.objs.has(objId)), operators_1.mergeMap(async (objsAndPaths) => {
134
- await sleep_1.sleep(20);
140
+ (0, operators_1.mergeMap)(objsAndPaths => objsAndPaths), (0, operators_1.filter)(({ objId }) => !this.objs.has(objId)), (0, operators_1.mergeMap)(async (objsAndPaths) => {
141
+ await (0, sleep_1.sleep)(20);
135
142
  return objsAndPaths;
136
143
  }, 1),
137
144
  // check, emiting objId, if not synced, and undefined, if synced
138
- operators_1.mergeMap(({ path, objId }) => this.sync(objId, async () => {
145
+ (0, operators_1.mergeMap)(({ path, objId }) => this.sync(objId, async () => {
139
146
  if (this.objs.has(objId)) {
140
147
  return;
141
148
  }
142
149
  const notSynced = await obj_status_1.ObjStatus.fileShowsObjNotInSyncedState(path, objId)
143
150
  .catch(notFoundOrReThrow).catch(this.logError);
144
151
  return (notSynced ? objId : undefined);
145
- })), operators_1.filter(objId => (objId !== undefined)));
152
+ })), (0, operators_1.filter)(objId => (objId !== undefined)));
153
+ }
154
+ scheduleGC(obj) {
155
+ this.gc.scheduleCollection(obj);
146
156
  }
147
157
  }
148
158
  exports.ObjFiles = ObjFiles;
@@ -175,47 +185,26 @@ class SyncedObj {
175
185
  this.status = status;
176
186
  this.downloader = downloader;
177
187
  this.scheduleGC = scheduleGC;
178
- /**
179
- * These versions are what simple programs see. It is a local opinion about
180
- * object's versions. Versions here can be either synced, or unsynced.
181
- */
182
- this.verObjs = timed_cache_1.makeTimedCache(60 * 1000);
183
- /**
184
- * These are conflicting versions, coming from a server. Of course, universal
185
- * truth is spread by server, but in situations of parallel changes, local
186
- * version allows things to work, while conflicting version from server
187
- * should be adopted by conflict resolution process. In other words, these
188
- * versions are not for common use.
189
- */
190
- this.remoteConflictVerObjs = timed_cache_1.makeTimedCache(60 * 1000);
191
- this.objSegsGetterFromDisk = async (ver, ofs, len) => {
192
- let obj = this.verObjs.get(ver);
193
- if (!obj) {
194
- const fPath = this.path(ver, this.status.isVersionSynced(ver));
195
- try {
196
- obj = await obj_on_disk_1.ObjOnDisk.forExistingFile(this.objId, ver, fPath, this.downloader, this.objSegsGetterFromDisk);
197
- this.verObjs.set(ver, obj);
198
- }
199
- catch (exc) {
200
- // when file doesn't exist on a disk, we just pass a chunk
201
- if (!exc.notFound) {
202
- throw exc;
203
- }
204
- return [{ type: 'new', thisVerOfs: ofs, len }];
205
- }
188
+ this.remoteVers = (0, timed_cache_1.makeTimedCache)(60 * 1000);
189
+ this.localVers = (0, timed_cache_1.makeTimedCache)(60 * 1000);
190
+ this.localAndSyncedObjSegsGetterFromDisk = async (v, ofs, len) => {
191
+ const latestSynced = this.status.latestSyncedVersion();
192
+ if (latestSynced && (latestSynced >= v)) {
193
+ return this.remoteObjSegsGetterFromDisk(v, ofs, len);
206
194
  }
207
- return obj.readSegsOnlyFromDisk(ofs, len);
208
- };
209
- this.conflictObjSegsGetterFromDisk = async (version, ofs, len) => {
210
- if (this.status.syncedVersionGreaterOrEqual(version)) {
211
- return this.objSegsGetterFromDisk(version, ofs, len);
195
+ let objVer = this.localVers.get(v);
196
+ if (!objVer) {
197
+ objVer = await obj_on_disk_1.ObjOnDisk.forExistingFile(this.objId, v, this.localVerPath(v), this.downloader, this.localAndSyncedObjSegsGetterFromDisk);
198
+ this.localVers.set(v, objVer);
212
199
  }
213
- let obj = this.remoteConflictVerObjs.get(version);
214
- if (!obj) {
215
- const fPath = this.path(version, true);
200
+ return objVer.readSegsOnlyFromDisk(ofs, len);
201
+ };
202
+ this.remoteObjSegsGetterFromDisk = async (v, ofs, len) => {
203
+ let objVer = this.remoteVers.get(v);
204
+ if (!objVer) {
216
205
  try {
217
- obj = await obj_on_disk_1.ObjOnDisk.forExistingFile(this.objId, version, fPath, this.downloader, this.conflictObjSegsGetterFromDisk);
218
- this.remoteConflictVerObjs.set(version, obj);
206
+ objVer = await obj_on_disk_1.ObjOnDisk.forExistingFile(this.objId, v, this.remoteVerPath(v), this.downloader, this.remoteObjSegsGetterFromDisk);
207
+ this.remoteVers.set(v, objVer);
219
208
  }
220
209
  catch (exc) {
221
210
  // when file doesn't exist on a disk, we just pass a chunk
@@ -225,7 +214,7 @@ class SyncedObj {
225
214
  return [{ type: 'new', thisVerOfs: ofs, len }];
226
215
  }
227
216
  }
228
- return obj.readSegsOnlyFromDisk(ofs, len);
217
+ return objVer.readSegsOnlyFromDisk(ofs, len);
229
218
  };
230
219
  Object.freeze(this);
231
220
  }
@@ -234,126 +223,169 @@ class SyncedObj {
234
223
  return new SyncedObj(objId, objFolder, status, downloader, scheduleGC);
235
224
  }
236
225
  static async forDownloadedObj(objId, objFolder, downloader, scheduleGC, version, parts, logError) {
237
- // XXX let's note that given version is used to be current on server
226
+ // XXX let's note that given version is also passed as current on server
238
227
  const status = await obj_status_1.ObjStatus.makeForDownloadedVersion(objFolder, objId, version, version, logError);
239
228
  const obj = new SyncedObj(objId, objFolder, status, downloader, scheduleGC);
240
- const fPath = obj.path(version, true);
241
- const objVer = await obj_on_disk_1.ObjOnDisk.createFileForExistingVersion(obj.objId, version, fPath, obj.downloader, obj.objSegsGetterFromDisk, parts);
242
- obj.verObjs.set(version, objVer);
229
+ const fPath = obj.remoteVerPath(version);
230
+ const objVer = await obj_on_disk_1.ObjOnDisk.createFileForExistingVersion(obj.objId, version, fPath, obj.downloader, obj.remoteObjSegsGetterFromDisk, parts);
231
+ obj.remoteVers.set(version, objVer);
243
232
  return obj;
244
233
  }
245
234
  static async forNewObj(objId, objFolder, downloader, scheduleGC, logError) {
246
235
  const status = await obj_status_1.ObjStatus.makeNew(objFolder, objId, logError);
247
236
  return new SyncedObj(objId, objFolder, status, downloader, scheduleGC);
248
237
  }
249
- sync() {
250
- return this.status;
251
- }
252
238
  scheduleSelfGC() {
253
239
  this.scheduleGC(this);
254
240
  }
255
- path(version, synced, remote) {
256
- const fileExt = (synced ?
257
- SYNCED_FILE_NAME_EXT :
258
- (remote ? REMOTE_FILE_NAME_EXT : UNSYNCED_FILE_NAME_EXT));
259
- const fName = `${version}.${fileExt}`;
260
- return path_1.join(this.objFolder, fName);
241
+ localVerPath(version) {
242
+ return (0, path_1.join)(this.objFolder, `${version}.${exports.UNSYNCED_FILE_NAME_EXT}`);
243
+ }
244
+ remoteVerPath(version) {
245
+ return (0, path_1.join)(this.objFolder, `${version}.${exports.REMOTE_FILE_NAME_EXT}`);
261
246
  }
262
- async getObjSrc(version) {
263
- let objVer = this.verObjs.get(version);
247
+ async getObjSrcFromLocalAndSyncedBranch(version) {
248
+ const latestSynced = this.status.latestSyncedVersion();
249
+ const objVer = await ((latestSynced && (latestSynced >= version)) ?
250
+ this.instanceOfRemoteObjVer(version) :
251
+ this.instanceOfLocalObjVer(version));
252
+ return objVer.getSrc();
253
+ }
254
+ async getObjSrcFromRemoteAndSyncedBranch(version) {
255
+ const objVer = await this.instanceOfRemoteObjVer(version);
256
+ return objVer.getSrc();
257
+ }
258
+ async instanceOfLocalObjVer(version) {
259
+ let objVer = this.localVers.get(version);
264
260
  if (objVer) {
265
- return objVer.getSrc();
266
- }
267
- const isSynced = this.status.isVersionSynced(version);
268
- const fPath = this.path(version, isSynced);
269
- if (isSynced) {
270
- objVer = ((await isOnDisk(fPath)) ?
271
- await obj_on_disk_1.ObjOnDisk.forExistingFile(this.objId, version, fPath, this.downloader, this.objSegsGetterFromDisk) :
272
- await obj_on_disk_1.ObjOnDisk.createFileForExistingVersion(this.objId, version, fPath, this.downloader, this.objSegsGetterFromDisk));
261
+ return objVer;
273
262
  }
274
- else {
275
- objVer = await obj_on_disk_1.ObjOnDisk.forExistingFile(this.objId, version, fPath, this.downloader, this.objSegsGetterFromDisk);
276
- }
277
- const src = objVer.getSrc();
278
- this.verObjs.set(version, objVer);
279
- return src;
263
+ const fPath = this.localVerPath(version);
264
+ objVer = await obj_on_disk_1.ObjOnDisk.forExistingFile(this.objId, version, fPath, this.downloader, this.localAndSyncedObjSegsGetterFromDisk);
265
+ this.localVers.set(version, objVer);
266
+ return objVer;
280
267
  }
281
- async getRemoteConflictObjVersion(version) {
282
- if (this.status.syncedVersionGreaterOrEqual(version)) {
283
- return this.getObjSrc(version);
284
- }
285
- let obj = this.remoteConflictVerObjs.get(version);
286
- if (obj) {
287
- return obj.getSrc();
268
+ async instanceOfRemoteObjVer(version) {
269
+ let objVer = this.remoteVers.get(version);
270
+ if (objVer) {
271
+ return objVer;
288
272
  }
289
- const fPath = this.path(version, true);
290
- obj = ((await isOnDisk(fPath)) ?
291
- await obj_on_disk_1.ObjOnDisk.forExistingFile(this.objId, version, fPath, this.downloader, this.conflictObjSegsGetterFromDisk) :
292
- await obj_on_disk_1.ObjOnDisk.createFileForExistingVersion(this.objId, version, fPath, this.downloader, this.conflictObjSegsGetterFromDisk));
293
- const src = obj.getSrc();
294
- this.verObjs.set(version, obj);
295
- return src;
273
+ const fPath = this.remoteVerPath(version);
274
+ objVer = ((await isOnDisk(fPath)) ?
275
+ await obj_on_disk_1.ObjOnDisk.forExistingFile(this.objId, version, fPath, this.downloader, this.remoteObjSegsGetterFromDisk) :
276
+ await obj_on_disk_1.ObjOnDisk.createFileForExistingVersion(this.objId, version, fPath, this.downloader, this.remoteObjSegsGetterFromDisk));
277
+ this.remoteVers.set(version, objVer);
278
+ return objVer;
296
279
  }
297
280
  async saveNewVersion(version, encSub) {
298
- if (this.verObjs.has(version)) {
281
+ if (this.localVers.has(version)) {
299
282
  throw new Error(`Version ${version} already exists in object ${this.objId}`);
300
283
  }
301
- const fPath = this.path(version, false);
302
- const { obj, write$ } = await obj_on_disk_1.ObjOnDisk.createFileForWriteOfNewVersion(this.objId, version, fPath, encSub, this.downloader, this.objSegsGetterFromDisk);
303
- this.verObjs.set(version, obj);
304
- const fileWrite$ = write$.pipe(operators_1.tap({
284
+ const fPath = this.localVerPath(version);
285
+ const { obj, write$ } = await obj_on_disk_1.ObjOnDisk.createFileForWriteOfNewVersion(this.objId, version, fPath, encSub, this.downloader, this.localAndSyncedObjSegsGetterFromDisk);
286
+ this.localVers.set(version, obj);
287
+ const fileWrite$ = write$.pipe((0, operators_1.tap)({
305
288
  error: err => {
306
- if (this.verObjs.get(version) === obj) {
307
- this.verObjs.delete(version);
289
+ if (this.localVers.get(version) === obj) {
290
+ this.localVers.delete(version);
308
291
  }
309
292
  }
310
- }), utils_for_observables_1.flatTap(undefined, undefined, () => this.setUnsyncedCurrentVersion(version, obj.getBaseVersion())));
293
+ }), (0, utils_for_observables_1.flatTap)(undefined, undefined, () => this.setUnsyncedCurrentVersion(version, obj.getBaseVersion())));
311
294
  return { fileWrite$, baseVer: obj.getBaseVersion() };
312
295
  }
313
- isArchived() {
314
- return this.status.isArchived();
315
- }
316
- getCurrentVersionOrThrow() {
317
- return this.status.getCurrentVersionOrThrow();
318
- }
319
- isRemoteVersionGreaterOrEqualTo(newRemoteVersion) {
320
- return this.status.isRemoteVersionGreaterOrEqualTo(newRemoteVersion);
296
+ async combineLocalBaseIfPresent(version) {
297
+ const bases = this.status.baseOfLocalVersion(version);
298
+ if (!bases) {
299
+ return;
300
+ }
301
+ const { localBases, syncedBase } = bases;
302
+ if (localBases) {
303
+ const objVer = await this.instanceOfLocalObjVer(version);
304
+ for (const localBase of localBases) {
305
+ await objVer.absorbImmediateBaseVersion(localBase, this.localVerPath(localBase));
306
+ this.status.absorbLocalVersionBase(version, localBase);
307
+ }
308
+ }
309
+ return syncedBase;
321
310
  }
322
- isDeletedOnRemote() {
323
- return this.status.isDeletedOnRemote();
311
+ async saveUploadHeaderFile(uploadHeader) {
312
+ await (0, upload_header_file_1.saveUploadHeaderFile)(this.objFolder, uploadHeader);
324
313
  }
325
314
  async setUnsyncedCurrentVersion(version, baseVersion) {
326
- await this.status.setUnsyncedCurrentVersion(version, baseVersion);
315
+ await this.status.setLocalCurrentVersion(version, baseVersion);
327
316
  if (version > 1) {
328
317
  this.scheduleSelfGC();
329
318
  }
330
319
  }
331
- async markVersionSynced(version) {
332
- const verObj = this.verObjs.get(version);
320
+ /**
321
+ * This renames/moves version file from local to remote.
322
+ * Removes upload info from status, updating enumerations of local and
323
+ * synced versions.
324
+ */
325
+ async recordUploadCompletion(localVersion, uploadVersion, headerChange) {
326
+ const verObj = this.localVers.get(localVersion);
327
+ const remotePath = this.remoteVerPath(uploadVersion);
333
328
  if (verObj) {
334
- await verObj.moveFile(this.path(version, true));
329
+ const syncedVerObj = await verObj.moveFileAndProxyThis(remotePath, (headerChange ? {
330
+ newHeader: headerChange.newHeader,
331
+ originalHeader: headerChange.originalHeader,
332
+ version: uploadVersion
333
+ } : undefined));
334
+ this.remoteVers.set(uploadVersion, syncedVerObj);
335
335
  }
336
336
  else {
337
- await fs.rename(this.path(version, false), this.path(version, true));
337
+ await fs.rename(this.localVerPath(localVersion), remotePath);
338
338
  }
339
- await this.status.markVersionSynced(version);
339
+ await this.status.markLocalVersionSynced(localVersion, uploadVersion);
340
340
  this.scheduleSelfGC();
341
341
  }
342
- async setRemoteVersion(version) {
343
- await this.status.setRemoteVersion(version);
342
+ dropCachedLocalObjVersionsLessOrEqual(version) {
343
+ for (const version of this.localVers.keys()) {
344
+ if (version <= version) {
345
+ this.localVers.delete(version);
346
+ }
347
+ }
344
348
  }
345
- async setDeletedOnRemote() {
346
- await this.status.setDeletedOnRemote();
349
+ async removeLocalVersionFilesLessThan(version) {
350
+ const lst = await fs.readdir(this.objFolder).catch(utils_1.noop);
351
+ if (!lst) {
352
+ return;
353
+ }
354
+ const rmProcs = [];
355
+ for (const f of lst) {
356
+ if (!f.endsWith(exports.UNSYNCED_FILE_NAME_EXT)) {
357
+ continue;
358
+ }
359
+ const verStr = f.slice(0, f.length - 1 - exports.UNSYNCED_FILE_NAME_EXT.length);
360
+ const ver = parseInt(verStr);
361
+ if (isNaN(ver) || (ver > version)) {
362
+ continue;
363
+ }
364
+ rmProcs.push(fs.unlink((0, path_1.join)(this.objFolder, f)).catch(utils_1.noop));
365
+ }
366
+ if (rmProcs.length > 0) {
367
+ await Promise.all(rmProcs);
368
+ }
347
369
  }
348
370
  async removeCurrentVersion() {
349
- await this.status.removeCurrentVersion(this.verObjs);
371
+ await this.status.removeCurrentVersion();
372
+ // note that gc is tasked with removing current obj version on server
350
373
  this.scheduleSelfGC();
351
374
  }
352
- getNonGarbageVersions() {
353
- return this.status.getNonGarbageVersions();
375
+ async diffForUploadOf(version) {
376
+ const objVer = await this.instanceOfLocalObjVer(version);
377
+ if (objVer.getBaseVersion()) {
378
+ return objVer.diffFromBase();
379
+ }
380
+ else {
381
+ throw new Error(`Version ${version} is not a diff version`);
382
+ }
354
383
  }
355
- isStatusFileSaved() {
356
- return this.status.isFileSaved();
384
+ syncStatus() {
385
+ return this.status;
386
+ }
387
+ statusObj() {
388
+ return this.status;
357
389
  }
358
390
  }
359
391
  exports.SyncedObj = SyncedObj;
@@ -368,5 +400,4 @@ async function isOnDisk(path) {
368
400
  throw exc;
369
401
  }));
370
402
  }
371
- function noop() { }
372
403
  Object.freeze(exports);