core-3nweb-client-lib 0.25.6 → 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 (215) hide show
  1. package/README.md +2 -2
  2. package/build/api-defs/asmail.d.ts +1 -1
  3. package/build/api-defs/files.d.ts +282 -70
  4. package/build/core/app-files.js +7 -7
  5. package/build/core/asmail/config/common.js +4 -4
  6. package/build/core/asmail/config/index.js +2 -2
  7. package/build/core/asmail/config/published-intro-key.js +1 -1
  8. package/build/core/asmail/delivery/common.js +7 -7
  9. package/build/core/asmail/delivery/index.js +7 -6
  10. package/build/core/asmail/delivery/msg.js +8 -7
  11. package/build/core/asmail/delivery/per-recipient-wip.js +3 -3
  12. package/build/core/asmail/inbox/attachments/fs.js +11 -1
  13. package/build/core/asmail/inbox/cached-msgs.js +3 -3
  14. package/build/core/asmail/inbox/inbox-events.js +5 -4
  15. package/build/core/asmail/inbox/index.js +12 -12
  16. package/build/core/asmail/inbox/msg-downloader.js +3 -3
  17. package/build/core/asmail/inbox/msg-indexing.js +4 -4
  18. package/build/core/asmail/inbox/msg-on-disk.js +7 -7
  19. package/build/core/asmail/index.d.ts +3 -3
  20. package/build/core/asmail/index.js +13 -8
  21. package/build/core/asmail/key-verification.js +5 -5
  22. package/build/core/asmail/keyring/common.js +7 -6
  23. package/build/core/asmail/keyring/correspondent-keys.js +8 -7
  24. package/build/core/asmail/keyring/id-to-email-map.js +2 -1
  25. package/build/core/asmail/keyring/index.d.ts +7 -8
  26. package/build/core/asmail/keyring/index.js +15 -14
  27. package/build/core/asmail/keyring/keyring-storage.js +4 -3
  28. package/build/core/asmail/msg/opener.js +3 -3
  29. package/build/core/asmail/msg/packer.js +13 -13
  30. package/build/core/asmail/sending-params/own-params.js +4 -4
  31. package/build/core/asmail/sending-params/params-from-others.js +3 -3
  32. package/build/core/id-manager.js +8 -5
  33. package/build/core/index.d.ts +2 -1
  34. package/build/core/index.js +14 -14
  35. package/build/core/sign-in.d.ts +5 -4
  36. package/build/core/sign-in.js +12 -14
  37. package/build/core/sign-up.d.ts +1 -0
  38. package/build/core/sign-up.js +15 -11
  39. package/build/core/storage/common/json-saving.d.ts +21 -0
  40. package/build/core/storage/common/json-saving.js +82 -0
  41. package/build/core/storage/common/obj-info-file.d.ts +51 -0
  42. package/build/core/storage/common/obj-info-file.js +153 -5
  43. package/build/core/storage/common/utils.d.ts +2 -0
  44. package/build/core/storage/common/utils.js +32 -0
  45. package/build/core/storage/index.d.ts +3 -17
  46. package/build/core/storage/index.js +57 -77
  47. package/build/core/storage/local/obj-files-gc.d.ts +2 -0
  48. package/build/core/storage/local/obj-files-gc.js +53 -39
  49. package/build/core/storage/local/obj-files.d.ts +6 -9
  50. package/build/core/storage/local/obj-files.js +16 -19
  51. package/build/core/storage/local/obj-status.d.ts +20 -30
  52. package/build/core/storage/local/obj-status.js +46 -113
  53. package/build/core/storage/local/storage.d.ts +15 -5
  54. package/build/core/storage/local/storage.js +37 -18
  55. package/build/core/storage/synced/downloader.js +7 -6
  56. package/build/core/storage/synced/obj-files-gc.d.ts +6 -1
  57. package/build/core/storage/synced/obj-files-gc.js +106 -13
  58. package/build/core/storage/synced/obj-files.d.ts +46 -47
  59. package/build/core/storage/synced/obj-files.js +207 -154
  60. package/build/core/storage/synced/obj-status.d.ts +103 -42
  61. package/build/core/storage/synced/obj-status.js +525 -137
  62. package/build/core/storage/synced/remote-events.d.ts +11 -12
  63. package/build/core/storage/synced/remote-events.js +80 -57
  64. package/build/core/storage/synced/storage.d.ts +24 -5
  65. package/build/core/storage/synced/storage.js +123 -38
  66. package/build/core/storage/synced/upload-header-file.d.ts +4 -0
  67. package/build/core/storage/synced/upload-header-file.js +64 -0
  68. package/build/core/storage/synced/upsyncer.d.ts +15 -9
  69. package/build/core/storage/synced/upsyncer.js +219 -246
  70. package/build/core/storage/system-folders/apps-data.d.ts +16 -0
  71. package/build/core/storage/system-folders/apps-data.js +110 -0
  72. package/build/core/storage/system-folders/index.d.ts +18 -0
  73. package/build/core/storage/system-folders/index.js +77 -0
  74. package/build/core-ipc/common-caps.js +3 -3
  75. package/build/core-ipc/generic.js +8 -8
  76. package/build/core-ipc/startup-caps.js +2 -2
  77. package/build/cryptors.js +6 -2
  78. package/build/ipc-via-protobuf/asmail-cap.js +67 -83
  79. package/build/ipc-via-protobuf/bytes.js +16 -17
  80. package/build/ipc-via-protobuf/connector-clients-side.d.ts +3 -0
  81. package/build/ipc-via-protobuf/connector-clients-side.js +62 -25
  82. package/build/ipc-via-protobuf/connector-services-side.js +10 -10
  83. package/build/ipc-via-protobuf/connector.js +4 -4
  84. package/build/ipc-via-protobuf/file.d.ts +48 -12
  85. package/build/ipc-via-protobuf/file.js +476 -120
  86. package/build/ipc-via-protobuf/fs.d.ts +8 -0
  87. package/build/ipc-via-protobuf/fs.js +592 -159
  88. package/build/ipc-via-protobuf/log-cap.js +2 -2
  89. package/build/ipc-via-protobuf/mailerid.js +3 -3
  90. package/build/ipc-via-protobuf/protobuf-msg.d.ts +1 -0
  91. package/build/ipc-via-protobuf/protobuf-msg.js +11 -7
  92. package/build/ipc-via-protobuf/startup-cap.js +23 -23
  93. package/build/ipc-via-protobuf/storage-cap.js +12 -12
  94. package/build/ipc.js +7 -2
  95. package/build/lib-client/3nstorage/exceptions.d.ts +12 -8
  96. package/build/lib-client/3nstorage/exceptions.js +31 -10
  97. package/build/lib-client/3nstorage/service.d.ts +16 -2
  98. package/build/lib-client/3nstorage/service.js +109 -39
  99. package/build/lib-client/3nstorage/util/file-based-json.d.ts +2 -1
  100. package/build/lib-client/3nstorage/util/file-based-json.js +1 -1
  101. package/build/lib-client/3nstorage/xsp-fs/attrs.js +17 -17
  102. package/build/lib-client/3nstorage/xsp-fs/common.d.ts +52 -14
  103. package/build/lib-client/3nstorage/xsp-fs/common.js +31 -16
  104. package/build/lib-client/3nstorage/xsp-fs/file-node.d.ts +1 -0
  105. package/build/lib-client/3nstorage/xsp-fs/file-node.js +18 -14
  106. package/build/lib-client/3nstorage/xsp-fs/file.d.ts +31 -6
  107. package/build/lib-client/3nstorage/xsp-fs/file.js +74 -23
  108. package/build/lib-client/3nstorage/xsp-fs/folder-node-serialization.js +4 -4
  109. package/build/lib-client/3nstorage/xsp-fs/folder-node.d.ts +24 -11
  110. package/build/lib-client/3nstorage/xsp-fs/folder-node.js +599 -189
  111. package/build/lib-client/3nstorage/xsp-fs/fs.d.ts +45 -9
  112. package/build/lib-client/3nstorage/xsp-fs/fs.js +326 -74
  113. package/build/lib-client/3nstorage/xsp-fs/link-node.d.ts +1 -0
  114. package/build/lib-client/3nstorage/xsp-fs/link-node.js +7 -2
  115. package/build/lib-client/3nstorage/xsp-fs/node-in-fs.d.ts +30 -20
  116. package/build/lib-client/3nstorage/xsp-fs/node-in-fs.js +239 -106
  117. package/build/lib-client/3nstorage/xsp-fs/node-persistence.d.ts +1 -1
  118. package/build/lib-client/3nstorage/xsp-fs/node-persistence.js +18 -19
  119. package/build/lib-client/3nstorage/xsp-fs/xsp-payload-v1.js +5 -5
  120. package/build/lib-client/3nstorage/xsp-fs/xsp-payload-v2.js +56 -56
  121. package/build/lib-client/3nweb-signup.js +4 -4
  122. package/build/lib-client/asmail/recipient.js +15 -15
  123. package/build/lib-client/asmail/sender.js +22 -22
  124. package/build/lib-client/asmail/service-config.js +3 -3
  125. package/build/lib-client/cryptor/cryptor-in-worker.js +19 -17
  126. package/build/lib-client/cryptor/cryptor-wasm.js +1 -1
  127. package/build/lib-client/cryptor/cryptor.js +4 -2
  128. package/build/lib-client/cryptor/cryptor.wasm +0 -0
  129. package/build/lib-client/cryptor/in-proc-js.js +1 -1
  130. package/build/lib-client/cryptor/in-proc-wasm.js +7 -7
  131. package/build/lib-client/cryptor/worker-js.js +2 -2
  132. package/build/lib-client/cryptor/worker-wasm.js +2 -2
  133. package/build/lib-client/files-select.js +1 -1
  134. package/build/lib-client/files.d.ts +1 -1
  135. package/build/lib-client/files.js +71 -4
  136. package/build/lib-client/fs-collection.js +3 -2
  137. package/build/lib-client/fs-sync-utils.d.ts +5 -0
  138. package/build/lib-client/fs-sync-utils.js +61 -0
  139. package/build/lib-client/fs-view.d.ts +14 -0
  140. package/build/lib-client/fs-view.js +33 -0
  141. package/build/lib-client/key-derivation.js +1 -1
  142. package/build/lib-client/local-files/dev-file-sink.js +9 -9
  143. package/build/lib-client/local-files/dev-file-src.js +2 -2
  144. package/build/lib-client/local-files/device-fs.d.ts +1 -1
  145. package/build/lib-client/local-files/device-fs.js +56 -54
  146. package/build/lib-client/logging/log-to-file.d.ts +1 -1
  147. package/build/lib-client/logging/log-to-file.js +11 -11
  148. package/build/lib-client/mailer-id/login.js +7 -7
  149. package/build/lib-client/mailer-id/provisioner.js +12 -12
  150. package/build/lib-client/objs-on-disk/file-writing-proc.js +5 -5
  151. package/build/lib-client/objs-on-disk/obj-folders.js +33 -33
  152. package/build/lib-client/objs-on-disk/obj-on-disk.d.ts +13 -2
  153. package/build/lib-client/objs-on-disk/obj-on-disk.js +24 -9
  154. package/build/lib-client/request-utils.d.ts +1 -0
  155. package/build/lib-client/request-utils.js +14 -14
  156. package/build/lib-client/server-events.d.ts +3 -3
  157. package/build/lib-client/server-events.js +12 -10
  158. package/build/lib-client/service-locator.js +10 -10
  159. package/build/lib-client/user-with-mid-session.js +7 -7
  160. package/build/lib-client/user-with-pkl-session.js +25 -25
  161. package/build/lib-client/ws-utils.js +3 -3
  162. package/build/lib-common/async-cryptor-wrap.js +4 -4
  163. package/build/lib-common/async-fs-node.d.ts +5 -3
  164. package/build/lib-common/async-fs-node.js +19 -18
  165. package/build/lib-common/byte-streaming/pipe.js +1 -1
  166. package/build/lib-common/byte-streaming/wrapping.js +17 -17
  167. package/build/lib-common/canonical-address.js +1 -1
  168. package/build/lib-common/exceptions/error.d.ts +1 -0
  169. package/build/lib-common/exceptions/error.js +7 -6
  170. package/build/lib-common/exceptions/file.js +10 -1
  171. package/build/lib-common/ipc/generic-ipc.js +2 -2
  172. package/build/lib-common/ipc/ws-ipc.js +2 -2
  173. package/build/lib-common/json-utils.js +2 -1
  174. package/build/lib-common/mid-sigs-NaCl-Ed.js +14 -14
  175. package/build/lib-common/objs-on-disk/file-layout.d.ts +19 -0
  176. package/build/lib-common/objs-on-disk/file-layout.js +130 -12
  177. package/build/lib-common/objs-on-disk/obj-file.d.ts +13 -2
  178. package/build/lib-common/objs-on-disk/obj-file.js +99 -37
  179. package/build/lib-common/objs-on-disk/utils.d.ts +1 -0
  180. package/build/lib-common/objs-on-disk/utils.js +4 -4
  181. package/build/lib-common/objs-on-disk/v1-obj-file-format.js +14 -14
  182. package/build/lib-common/processes/deferred.d.ts +6 -0
  183. package/build/lib-common/processes/deferred.js +30 -0
  184. package/build/lib-common/processes/labelled-exec-pools.d.ts +33 -0
  185. package/build/lib-common/processes/labelled-exec-pools.js +141 -0
  186. package/build/lib-common/processes/pressure.d.ts +7 -0
  187. package/build/lib-common/processes/pressure.js +56 -0
  188. package/build/lib-common/processes/sleep.d.ts +1 -0
  189. package/build/lib-common/processes/sleep.js +26 -0
  190. package/build/lib-common/{processes.d.ts → processes/synced.d.ts} +0 -40
  191. package/build/lib-common/{processes.js → processes/synced.js} +187 -204
  192. package/build/lib-common/processes/timeout.d.ts +1 -0
  193. package/build/lib-common/processes/timeout.js +51 -0
  194. package/build/lib-common/random-node.js +7 -7
  195. package/build/lib-common/service-api/3nstorage/owner.d.ts +100 -39
  196. package/build/lib-common/service-api/3nstorage/owner.js +85 -42
  197. package/build/lib-common/service-api/asmail/delivery.js +2 -2
  198. package/build/lib-common/service-api/asmail/retrieval.js +1 -1
  199. package/build/lib-common/timed-cache.d.ts +1 -0
  200. package/build/lib-common/timed-non-weak-cache.d.ts +1 -0
  201. package/build/lib-common/timed-non-weak-cache.js +11 -0
  202. package/build/lib-common/utils-for-observables.d.ts +15 -1
  203. package/build/lib-common/utils-for-observables.js +70 -19
  204. package/build/lib-common/weak-cache.d.ts +1 -0
  205. package/build/lib-common/weak-cache.js +12 -1
  206. package/build/lib-index.d.ts +2 -1
  207. package/build/lib-index.js +10 -7
  208. package/build/protos/asmail.proto.js +12912 -7127
  209. package/build/protos/file.proto.js +4848 -2399
  210. package/build/protos/fs.proto.js +9230 -3445
  211. package/package.json +8 -7
  212. package/protos/file.proto +91 -11
  213. package/protos/fs.proto +107 -8
  214. package/build/core/storage/synced/upsync-status.d.ts +0 -41
  215. package/build/core/storage/synced/upsync-status.js +0 -158
@@ -16,196 +16,584 @@
16
16
  this program. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
18
  Object.defineProperty(exports, "__esModule", { value: true });
19
- exports.ObjStatus = void 0;
20
- const processes_1 = require("../../../lib-common/processes");
21
- const fs = require("../../../lib-common/async-fs-node");
19
+ exports.readAndCheckStatus = exports.ObjStatus = exports.STATUS_FILE_NAME = void 0;
22
20
  const path_1 = require("path");
23
21
  const exceptions_1 = require("../../../lib-client/3nstorage/exceptions");
22
+ const json_saving_1 = require("../common/json-saving");
24
23
  const obj_info_file_1 = require("../common/obj-info-file");
25
- const STATUS_FILE_NAME = 'status';
24
+ const assert_1 = require("../../../lib-common/assert");
25
+ function makeVersions() {
26
+ return {
27
+ baseToDiff: {},
28
+ diffToBase: {},
29
+ };
30
+ }
31
+ function makeObjStatusInfo(objId) {
32
+ return {
33
+ objId,
34
+ remote: makeVersions()
35
+ };
36
+ }
37
+ function syncStateOf({ local, synced, remote }) {
38
+ const syncedIsCurrent = isSyncedCurrentWithRemote(synced, remote);
39
+ if (local) {
40
+ switch (syncedIsCurrent) {
41
+ case undefined:
42
+ case true:
43
+ return ((local.isArchived && (synced === null || synced === void 0 ? void 0 : synced.isArchived)) ?
44
+ 'synced' : 'unsynced');
45
+ case false:
46
+ return 'conflicting';
47
+ }
48
+ }
49
+ else {
50
+ switch (syncedIsCurrent) {
51
+ case undefined:
52
+ return 'unsynced';
53
+ case true:
54
+ return 'synced';
55
+ case false:
56
+ return 'behind';
57
+ }
58
+ }
59
+ }
60
+ function isSyncedCurrentWithRemote(synced, remote) {
61
+ if (synced) {
62
+ return ((synced.version === remote.current)
63
+ && (synced.isArchived === remote.isArchived));
64
+ }
65
+ else {
66
+ return (isRemoteEmpty(remote) ? undefined : false);
67
+ }
68
+ }
69
+ function isRemoteEmpty(remote) {
70
+ return (0, obj_info_file_1.isEmptyVersions)(remote) && !remote.isArchived;
71
+ }
72
+ function nonGarbageWithMaxVer(v) {
73
+ return {
74
+ gcMaxVer: v.current,
75
+ nonGarbage: (0, obj_info_file_1.nonGarbageVersionsIn)(v)
76
+ };
77
+ }
78
+ function identifyNonGarbage(status) {
79
+ var _a;
80
+ let local = undefined;
81
+ let uploadVersion = undefined;
82
+ if (status.local) {
83
+ local = nonGarbageWithMaxVer(status.local);
84
+ if (status.local.upload) {
85
+ const { localVersion } = status.local.upload;
86
+ if (status.local.current !== localVersion) {
87
+ (0, obj_info_file_1.addWithBasesTo)(local.nonGarbage, localVersion, status.local);
88
+ }
89
+ uploadVersion = status.local.upload.uploadVersion;
90
+ }
91
+ }
92
+ const remote = nonGarbageWithMaxVer(status.remote);
93
+ if ((_a = status.synced) === null || _a === void 0 ? void 0 : _a.version) {
94
+ remote.nonGarbage.add(status.synced.version);
95
+ if (status.synced.base) {
96
+ (0, obj_info_file_1.addWithBasesTo)(remote.nonGarbage, status.synced.base, status.remote);
97
+ }
98
+ }
99
+ return { local, remote, uploadVersion };
100
+ }
101
+ exports.STATUS_FILE_NAME = 'status';
26
102
  class ObjStatus {
27
- constructor(objFolder, status) {
103
+ constructor(objFolder, status, logError) {
28
104
  this.objFolder = objFolder;
29
105
  this.status = status;
30
- this.saveProc = new processes_1.DeduppedRunner(() => this.saveFile());
31
- Object.freeze(this);
106
+ this.logError = logError;
107
+ this.saveProc = new json_saving_1.JSONSavingProc((0, path_1.join)(this.objFolder, exports.STATUS_FILE_NAME), () => this.status);
108
+ this.updateStateIndicator();
109
+ Object.seal(this);
32
110
  }
33
- static async readFrom(objFolder, objId) {
111
+ static async readFrom(objFolder, objId, logError) {
34
112
  const status = await readAndCheckStatus(objFolder, objId);
35
- return new ObjStatus(objFolder, status);
113
+ return new ObjStatus(objFolder, status, logError);
36
114
  }
37
- static async makeNew(objFolder, objId) {
38
- const status = {
39
- objId,
40
- syncState: 'unsynced',
41
- versions: {}
42
- };
43
- const s = new ObjStatus(objFolder, status);
44
- await s.saveProc.trigger();
115
+ static async makeNew(objFolder, objId, logError) {
116
+ const status = makeObjStatusInfo(objId);
117
+ const s = new ObjStatus(objFolder, status, logError);
118
+ await s.triggerSaveProc();
45
119
  return s;
46
120
  }
47
- static async makeForDownloadedVersion(objFolder, objId, version) {
48
- const status = {
49
- objId,
50
- syncState: 'synced',
51
- versions: {
52
- current: version
53
- }
54
- };
55
- const s = new ObjStatus(objFolder, status);
56
- await s.saveProc.trigger();
121
+ static async makeForDownloadedVersion(objFolder, objId, version, currentRemote, logError) {
122
+ const status = makeObjStatusInfo(objId);
123
+ status.remote.current = currentRemote;
124
+ status.synced = { version: currentRemote };
125
+ if (currentRemote > version) {
126
+ status.remote.archived = [version];
127
+ }
128
+ else if (currentRemote !== version) {
129
+ throw new Error(`Downloaded version can't be greater than current remote`);
130
+ }
131
+ const s = new ObjStatus(objFolder, status, logError);
132
+ await s.triggerSaveProc();
57
133
  return s;
58
134
  }
59
135
  static async fileShowsObjNotInSyncedState(objFolder, objId) {
60
136
  const status = await readAndCheckStatus(objFolder, objId);
61
- return (status.syncState !== 'synced');
137
+ return (syncStateOf(status) !== 'synced');
62
138
  }
63
- async saveFile() {
64
- await fs.writeFile(path_1.join(this.objFolder, STATUS_FILE_NAME), JSON.stringify(this.status), { encoding: 'utf8' });
139
+ updateStateIndicator() {
140
+ this.stateIndicator = syncStateOf(this.status);
65
141
  }
66
142
  isArchived() {
67
- return !!this.status.isArchived;
143
+ var _a;
144
+ return !!((_a = this.status.local) === null || _a === void 0 ? void 0 : _a.isArchived);
68
145
  }
69
- getCurrentVersionOrThrow() {
70
- if (typeof this.status.versions.current !== 'number') {
71
- throw new Error(`Object ${this.status.objId} has no current version.`);
146
+ getCurrentLocalOrSynced() {
147
+ var _a, _b;
148
+ const state = this.stateIndicator;
149
+ const current = (((state === 'unsynced') || (state === 'conflicting')) ?
150
+ (_a = this.status.local) === null || _a === void 0 ? void 0 : _a.current : (_b = this.status.synced) === null || _b === void 0 ? void 0 : _b.version);
151
+ if (current) {
152
+ return current;
153
+ }
154
+ else {
155
+ throw (0, exceptions_1.makeStorageException)({
156
+ objNotFound: true,
157
+ message: 'Current version is not found'
158
+ });
72
159
  }
73
- return this.status.versions.current;
74
160
  }
75
- isRemoteVersionGreaterOrEqualTo(newRemoteVersion) {
76
- return ((typeof this.status.versions.remote === 'number') ?
77
- (this.status.versions.remote >= newRemoteVersion) : false);
161
+ getNonGarbageVersions() {
162
+ return identifyNonGarbage(this.status);
78
163
  }
79
- isDeletedOnRemote() {
80
- return !!this.status.deletedOnRemote;
164
+ async removeCurrentVersion() {
165
+ let { local, synced } = this.status;
166
+ if ((synced === null || synced === void 0 ? void 0 : synced.isArchived) || (local === null || local === void 0 ? void 0 : local.isArchived)) {
167
+ return;
168
+ }
169
+ if (local) {
170
+ (0, obj_info_file_1.rmCurrentVersionIn)(local);
171
+ }
172
+ else {
173
+ local = makeVersions();
174
+ }
175
+ local.isArchived = true;
176
+ this.updateStateIndicator();
177
+ ;
178
+ await this.triggerSaveProc().catch((exc) => {
179
+ var _a;
180
+ if (exc.notFound && ((_a = this.status.local) === null || _a === void 0 ? void 0 : _a.isArchived)) {
181
+ return;
182
+ }
183
+ else {
184
+ throw exc;
185
+ }
186
+ });
187
+ }
188
+ async triggerSaveProc(captureErrors = false, logErr = false) {
189
+ try {
190
+ await this.saveProc.trigger();
191
+ }
192
+ catch (exc) {
193
+ if (captureErrors) {
194
+ if (logErr) {
195
+ await this.logError(exc);
196
+ }
197
+ }
198
+ else {
199
+ throw exc;
200
+ }
201
+ }
202
+ }
203
+ recordUploadStart(info) {
204
+ (0, assert_1.assert)(!!this.status.local);
205
+ const local = this.status.local;
206
+ if (local.upload) {
207
+ throw (0, exceptions_1.makeFSSyncException)('obj-status', {
208
+ alreadyUploading: true,
209
+ message: `Status already has upload of version ${local.upload.uploadVersion} and can't start another upload with version ${info.uploadVersion}`
210
+ });
211
+ }
212
+ if (info.localVersion === local.current) {
213
+ local.upload = info;
214
+ }
215
+ else {
216
+ throw (0, exceptions_1.makeFSSyncException)('obj-status', {
217
+ localVersion: info.localVersion,
218
+ versionNotFound: true
219
+ });
220
+ }
221
+ return this.triggerSaveProc();
81
222
  }
82
- syncedVersionGreaterOrEqual(version) {
83
- return ((typeof this.status.versions.latestSynced !== 'number') ?
84
- false : (version <= this.status.versions.latestSynced));
223
+ recordUploadInterimState(info) {
224
+ (0, assert_1.assert)(!!this.status.local);
225
+ const local = this.status.local;
226
+ (0, assert_1.assert)(!!local.upload &&
227
+ (local.upload.uploadVersion === info.uploadVersion));
228
+ local.upload = info;
229
+ return this.triggerSaveProc();
85
230
  }
86
- async removeCurrentVersion(verObjs) {
87
- this.status.isArchived = true;
88
- if (this.status.versions.current) {
89
- verObjs.delete(this.status.versions.current);
90
- rmNonArchVersionsIn(this.status, this.status.versions.current);
91
- delete this.status.versions.current;
231
+ recordUploadCancellation(info) {
232
+ (0, assert_1.assert)(!!this.status.local);
233
+ const local = this.status.local;
234
+ (0, assert_1.assert)(!!local.upload &&
235
+ (local.upload.uploadVersion === info.uploadVersion));
236
+ local.upload = undefined;
237
+ return this.triggerSaveProc();
238
+ }
239
+ async recordArchVersionRemoval(version) {
240
+ if ((0, obj_info_file_1.rmArchVersionFrom)(this.status.remote, version)) {
241
+ return this.triggerSaveProc();
92
242
  }
93
- await this.saveProc.trigger();
94
243
  }
95
- async setDeletedOnRemote() {
96
- this.status.deletedOnRemote = true;
97
- await this.saveProc.trigger();
244
+ async recordVersionArchival(version) {
245
+ if ((0, obj_info_file_1.addArchived)(this.status.remote, version)) {
246
+ return this.triggerSaveProc();
247
+ }
98
248
  }
99
- async setRemoteVersion(version) {
100
- if (this.status.versions.remote >= version) {
249
+ async recordRemoteRemoval() {
250
+ const { local, synced, remote } = this.status;
251
+ if ((local === null || local === void 0 ? void 0 : local.isArchived) || (synced === null || synced === void 0 ? void 0 : synced.isArchived)) {
101
252
  return;
102
253
  }
103
- this.status.versions.remote = version;
104
- if (this.status.syncState === 'synced') {
105
- if (this.status.versions.current < this.status.versions.remote) {
106
- this.status.syncState = 'behind';
254
+ remote.isArchived = true;
255
+ (0, obj_info_file_1.rmCurrentVersionIn)(remote);
256
+ this.updateStateIndicator();
257
+ return this.triggerSaveProc();
258
+ }
259
+ async recordRemoteChange(version) {
260
+ const { local, synced, remote } = this.status;
261
+ if (((local === null || local === void 0 ? void 0 : local.upload) && (local.upload.uploadVersion === version))
262
+ || ((synced === null || synced === void 0 ? void 0 : synced.version) && (synced.version >= version))) {
263
+ return;
264
+ }
265
+ remote.current = version;
266
+ this.updateStateIndicator();
267
+ return this.triggerSaveProc();
268
+ }
269
+ recordSyncOfObjRemoval() {
270
+ this.status.local = undefined;
271
+ (0, obj_info_file_1.rmCurrentVersionIn)(this.status.remote);
272
+ this.status.remote.isArchived = true;
273
+ if (this.status.synced) {
274
+ this.status.synced.isArchived = true;
275
+ this.status.synced.version = undefined;
276
+ if (this.status.synced.base) {
277
+ (0, obj_info_file_1.rmNonArchVersionsIn)(this.status.remote, this.status.synced.base);
278
+ this.status.synced.base = undefined;
107
279
  }
108
280
  }
109
- else if (this.status.syncState === 'unsynced') {
110
- this.status.syncState = 'conflicting';
281
+ else {
282
+ this.status.synced = { isArchived: true };
111
283
  }
112
- await this.saveProc.trigger();
113
- }
114
- async setSyncedCurrentVersion(version) {
115
- this.status.versions.current = version;
116
- this.status.syncState = 'synced';
117
- this.status.versions.latestSynced = version;
118
- await this.saveProc.trigger();
284
+ this.updateStateIndicator();
285
+ return this.triggerSaveProc();
119
286
  }
120
- async setUnsyncedCurrentVersion(version) {
121
- // XXX should this code be like that from commented
122
- // setNewCurrentVersionAfterWriteIn, or should we use that function
123
- // reused by GC.
124
- this.status.versions.current = version;
125
- this.status.syncState = 'unsynced';
126
- await this.saveProc.trigger();
287
+ async recordStatusFromServer({ archived, current }) {
288
+ const remote = this.status.remote;
289
+ let changedCurrent = false;
290
+ if (current) {
291
+ if (!remote.current) {
292
+ remote.current = current;
293
+ changedCurrent = true;
294
+ }
295
+ else if (remote.current < current) {
296
+ (0, obj_info_file_1.rmCurrentVersionIn)(remote);
297
+ remote.current = current;
298
+ changedCurrent = true;
299
+ }
300
+ }
301
+ else if (remote.current) {
302
+ (0, obj_info_file_1.rmCurrentVersionIn)(remote);
303
+ remote.isArchived = true;
304
+ changedCurrent = true;
305
+ }
306
+ const rmArchived = removeArchVersionsNotInList(remote, archived);
307
+ const addedArchived = addArchVersionsFromList(remote, archived);
308
+ if (rmArchived || addedArchived || changedCurrent) {
309
+ this.updateStateIndicator();
310
+ await this.triggerSaveProc();
311
+ }
127
312
  }
128
313
  /**
129
- * This method ignores remote conflicting versions.
130
- * @param version
314
+ * When given object version is a diff on some base, this method returns
315
+ * a whole trace of local base versions up to synced one.
316
+ * Local bases, if present, are return in an array with highest version
317
+ * first.
318
+ * This returns undefined, when given object version is not a diff.
319
+ * @param version that is local, for which we want to get base versions, if
320
+ * it is a diff version.
131
321
  */
132
- isVersionSynced(version) {
133
- if (this.status.versions.current === undefined) {
134
- return false;
322
+ baseOfLocalVersion(version) {
323
+ (0, assert_1.assert)(!!this.status.local);
324
+ const local = this.status.local;
325
+ (0, assert_1.assert)((0, obj_info_file_1.isVersionIn)(version, local));
326
+ let base = local.diffToBase[version];
327
+ if (!base) {
328
+ return;
135
329
  }
136
- if (this.status.syncState == 'synced') {
137
- return true;
330
+ if ((0, obj_info_file_1.isVersionIn)(base, this.status.remote)) {
331
+ return { syncedBase: base };
138
332
  }
139
- if (this.status.versions.latestSynced === undefined) {
140
- return false;
333
+ const localBases = [];
334
+ do {
335
+ localBases.push(base);
336
+ base = local.diffToBase[base];
337
+ } while (base);
338
+ const lastBase = localBases[localBases.length - 1];
339
+ if ((0, obj_info_file_1.isVersionIn)(lastBase, this.status.remote)) {
340
+ return {
341
+ localBases: localBases.slice(0, localBases.length - 1),
342
+ syncedBase: lastBase
343
+ };
141
344
  }
142
- return (this.status.versions.latestSynced >= version);
345
+ else {
346
+ return { localBases };
347
+ }
348
+ }
349
+ markLocalVersionSynced(localVersion, uploadVersion) {
350
+ const { local, synced, remote } = this.status;
351
+ (0, assert_1.assert)(!!(local === null || local === void 0 ? void 0 : local.upload) &&
352
+ ((local === null || local === void 0 ? void 0 : local.upload.uploadVersion) === uploadVersion));
353
+ const syncedBase = local.upload.baseVersion;
354
+ if (!remote.current || (remote.current <= uploadVersion)) {
355
+ (0, obj_info_file_1.setCurrentVersionIn)(remote, uploadVersion, syncedBase);
356
+ }
357
+ if (synced) {
358
+ synced.version = uploadVersion;
359
+ if (synced.base && (synced.base !== syncedBase)) {
360
+ (0, obj_info_file_1.rmNonArchVersionsIn)(remote, synced.base);
361
+ }
362
+ synced.base = syncedBase;
363
+ }
364
+ else {
365
+ this.status.synced = { version: uploadVersion, base: syncedBase };
366
+ }
367
+ if (local.current === localVersion) {
368
+ this.status.local = undefined;
369
+ }
370
+ else {
371
+ local.upload = undefined;
372
+ }
373
+ this.updateStateIndicator();
374
+ return this.triggerSaveProc();
375
+ }
376
+ async setLocalCurrentVersion(version, baseVer) {
377
+ if (!this.status.local) {
378
+ this.status.local = makeVersions();
379
+ }
380
+ (0, obj_info_file_1.setCurrentVersionIn)(this.status.local, version, baseVer);
381
+ this.updateStateIndicator();
382
+ await this.triggerSaveProc();
383
+ }
384
+ listVersions() {
385
+ var _a;
386
+ const { local, synced, remote } = this.status;
387
+ switch (this.stateIndicator) {
388
+ case 'unsynced':
389
+ case 'conflicting':
390
+ (0, assert_1.assert)(!!local);
391
+ return {
392
+ current: local.current,
393
+ archived: ((synced === null || synced === void 0 ? void 0 : synced.version) ?
394
+ versionsToBranch(remote, synced.version, false).archived :
395
+ undefined)
396
+ };
397
+ case 'synced':
398
+ case 'behind':
399
+ (0, assert_1.assert)(!!synced);
400
+ return {
401
+ current: synced.version,
402
+ archived: ((synced === null || synced === void 0 ? void 0 : synced.version) ?
403
+ versionsToBranch(remote, synced.version, false).archived :
404
+ (_a = remote.archived) === null || _a === void 0 ? void 0 : _a.slice())
405
+ };
406
+ default:
407
+ throw new Error(`Unimplemented state ${this.stateIndicator}`);
408
+ }
409
+ }
410
+ async archiveCurrentVersion() {
411
+ const { synced, remote } = this.status;
412
+ (0, assert_1.assert)(!!(synced === null || synced === void 0 ? void 0 : synced.version));
413
+ (0, obj_info_file_1.addArchived)(remote, synced.version);
414
+ await this.triggerSaveProc();
415
+ }
416
+ absorbLocalVersionBase(version, localBase) {
417
+ (0, assert_1.assert)(!!this.status.local);
418
+ const local = this.status.local;
419
+ (0, assert_1.assert)(local.diffToBase[version] === localBase);
420
+ const lowerBase = local.diffToBase[localBase];
421
+ if (localBase) {
422
+ local.diffToBase[version] = lowerBase;
423
+ local.baseToDiff[lowerBase] = version;
424
+ }
425
+ else {
426
+ delete local.diffToBase[version];
427
+ }
428
+ delete local.diffToBase[localBase];
429
+ delete local.baseToDiff[localBase];
430
+ return this.triggerSaveProc();
431
+ }
432
+ latestSyncedVersion() {
433
+ var _a;
434
+ return (_a = this.status.synced) === null || _a === void 0 ? void 0 : _a.version;
435
+ }
436
+ syncStatus() {
437
+ const { remote, synced } = splitVersionsIntoBranches(this.status.remote, this.status.synced);
438
+ return {
439
+ state: this.stateIndicator,
440
+ local: localVersionFromStatus(this.status.local),
441
+ remote,
442
+ synced
443
+ };
444
+ }
445
+ neverUploaded() {
446
+ const synced = this.status.synced;
447
+ return (!(synced === null || synced === void 0 ? void 0 : synced.version) && !(synced === null || synced === void 0 ? void 0 : synced.isArchived));
448
+ }
449
+ async adoptRemoteVersion(version, dropLocalVer = false) {
450
+ var _a;
451
+ const { local, remote } = this.status;
452
+ if (this.stateIndicator !== 'behind') {
453
+ if (this.stateIndicator === 'synced') {
454
+ return;
455
+ }
456
+ else if (!dropLocalVer) {
457
+ throw (0, exceptions_1.makeFSSyncException)('', {
458
+ localVersion: local === null || local === void 0 ? void 0 : local.current,
459
+ remoteVersion: remote.current,
460
+ conflict: true,
461
+ message: `Can't adopt remote version in '${this.stateIndicator}' state`
462
+ });
463
+ }
464
+ }
465
+ if (version) {
466
+ if ((remote.current === version)
467
+ || ((_a = remote.archived) === null || _a === void 0 ? void 0 : _a.includes(version))) {
468
+ this.status.synced = { version, base: remote.diffToBase[version] };
469
+ }
470
+ else {
471
+ throw (0, exceptions_1.makeFSSyncException)('', {
472
+ remoteVersion: remote.current,
473
+ versionNotFound: true,
474
+ message: `Remote version ${version} is not in status info`
475
+ });
476
+ }
477
+ }
478
+ else if (remote.current) {
479
+ version = remote.current;
480
+ this.status.synced = { version, base: remote.diffToBase[version] };
481
+ }
482
+ else {
483
+ throw (0, exceptions_1.makeFSSyncException)('', {
484
+ versionMismatch: true,
485
+ message: `Current remote version is not set in status info`
486
+ });
487
+ }
488
+ if (local) {
489
+ this.status.local = undefined;
490
+ }
491
+ this.updateStateIndicator();
492
+ await this.triggerSaveProc();
143
493
  }
144
494
  }
145
495
  exports.ObjStatus = ObjStatus;
146
496
  Object.freeze(ObjStatus.prototype);
147
497
  Object.freeze(ObjStatus);
148
498
  async function readAndCheckStatus(objFolder, objId) {
149
- const status = await obj_info_file_1.readJSONInfoFileIn(objFolder, STATUS_FILE_NAME);
499
+ const status = await (0, obj_info_file_1.readJSONInfoFileIn)(objFolder, exports.STATUS_FILE_NAME);
150
500
  if (!status) {
151
- throw exceptions_1.makeStorageException({
501
+ throw (0, exceptions_1.makeStorageException)({
152
502
  message: `Obj status file is not found in obj folder ${objFolder}`
153
503
  });
154
504
  }
155
505
  // XXX we may do some checks and sanitization here
156
506
  if (objId !== status.objId) {
157
- throw exceptions_1.makeStorageException({ message: `Invalid objId in status file for obj ${objId}, in folder ${objFolder}.\nInvalid content:\n${JSON.stringify(status, null, 2)}` });
507
+ throw (0, exceptions_1.makeStorageException)({
508
+ message: `Invalid objId in status file for obj ${objId}, in folder ${objFolder}.\nInvalid content:\n${JSON.stringify(status, null, 2)}`
509
+ });
158
510
  }
159
511
  return status;
160
512
  }
161
- function rmNonArchVersionsIn(status, ver) {
162
- // XXX this is an analog of a function in local storage obj-files
163
- // Should code be structured the same way?
164
- if (!status.versions.archived
165
- || !status.versions.archived.includes(ver)) {
166
- return;
167
- }
168
- // XXX code below is from local
169
- //
170
- // if (status.baseToDiff[ver]) { return; }
171
- // const base = status.diffToBase[ver];
172
- // if (typeof base !== 'number') { return; }
173
- // delete status.diffToBase[ver];
174
- // const diffs = status.baseToDiff[base];
175
- // if (!diffs) { return; }
176
- // const diffInd = diffs.indexOf(ver);
177
- // if (diffInd < 0) { return; }
178
- // diffs.splice(diffInd, 1);
179
- // if (diffs.length === 0) {
180
- // delete status.baseToDiff[base];
181
- // rmNonArchVersionsIn(status, base);
182
- // }
513
+ exports.readAndCheckStatus = readAndCheckStatus;
514
+ function localVersionFromStatus(tagged) {
515
+ return (tagged ? {
516
+ latest: tagged.current,
517
+ isArchived: tagged.isArchived
518
+ } : undefined);
519
+ }
520
+ function splitVersionsIntoBranches(remote, synced) {
521
+ if (synced) {
522
+ if (isSyncedCurrentWithRemote(synced, remote)) {
523
+ return {
524
+ synced: versionsToBranch(remote)
525
+ };
526
+ }
527
+ else {
528
+ (0, assert_1.assert)(!!synced.version);
529
+ return {
530
+ synced: versionsToBranch(remote, synced.version, false),
531
+ remote: versionsToBranch(remote, synced.version, true)
532
+ };
533
+ }
534
+ }
535
+ else {
536
+ return (isRemoteEmpty(remote) ? {} : {
537
+ remote: versionsToBranch(remote)
538
+ });
539
+ }
540
+ }
541
+ function versionsToBranch({ current, archived, isArchived }, splitVersion, aboveSplit) {
542
+ if (splitVersion) {
543
+ let splitArchived = undefined;
544
+ if (archived) {
545
+ const indAboveSplit = archived.findIndex(v => (v > splitVersion));
546
+ if (aboveSplit) {
547
+ if (indAboveSplit >= 0) {
548
+ splitArchived = archived.slice(indAboveSplit);
549
+ }
550
+ }
551
+ else {
552
+ if (indAboveSplit > 0) {
553
+ splitArchived = archived.slice(0, indAboveSplit);
554
+ }
555
+ else {
556
+ splitArchived = archived.slice();
557
+ }
558
+ }
559
+ }
560
+ return {
561
+ archived: splitArchived,
562
+ latest: (aboveSplit ? current : splitVersion),
563
+ isArchived: isArchived
564
+ };
565
+ }
566
+ else {
567
+ return {
568
+ archived: archived === null || archived === void 0 ? void 0 : archived.slice(),
569
+ latest: current,
570
+ isArchived: isArchived
571
+ };
572
+ }
573
+ }
574
+ function removeArchVersionsNotInList(remote, versionsToKeep) {
575
+ let isAnythingChanged = false;
576
+ if (remote.archived) {
577
+ for (const v of remote.archived) {
578
+ if (!(versionsToKeep === null || versionsToKeep === void 0 ? void 0 : versionsToKeep.includes(v))) {
579
+ (0, obj_info_file_1.rmArchVersionFrom)(remote, v);
580
+ isAnythingChanged = true;
581
+ }
582
+ }
583
+ }
584
+ return isAnythingChanged;
585
+ }
586
+ function addArchVersionsFromList(remote, existingVersions) {
587
+ var _a;
588
+ if (!existingVersions) {
589
+ return false;
590
+ }
591
+ let isAnythingChanged = false;
592
+ for (const v of existingVersions) {
593
+ if (!((_a = remote.archived) === null || _a === void 0 ? void 0 : _a.includes(v))) {
594
+ (0, obj_info_file_1.addArchived)(remote, v);
595
+ }
596
+ }
597
+ return isAnythingChanged;
183
598
  }
184
- // export function setNewCurrentVersionAfterWriteIn(
185
- // status: ObjStatusInfo, newVersion: number, baseVer: number|undefined
186
- // ): void {
187
- // if (status.isArchived) { return; }
188
- // if (status.syncState === 'synced') {
189
- // status.syncState = 'unsynced';
190
- // }
191
- // if (baseVer !== undefined) {
192
- // // base->diff links should be added before removals
193
- // addBaseToDiffLinkInStatus(status, newVersion, baseVer);
194
- // }
195
- // if (status.versions.current) {
196
- // rmNonArchVersionsIn(status, status.versions.current);
197
- // }
198
- // status.versions.current = newVersion;
199
- // }
200
- // export function addConflictingRemoteVersionTo(
201
- // status: ObjStatusInfo, conflictVersion: number
202
- // ): void {
203
- // if (!status.versions.conflictingRemote) {
204
- // status.versions.conflictingRemote = [];
205
- // }
206
- // const conflicts = status.versions.conflictingRemote;
207
- // if (conflicts.find(v => v >= conflictVersion)) { return; }
208
- // status.syncState = 'conflicting';
209
- // status.versions.conflictingRemote.push(conflictVersion);
210
- // }
211
599
  Object.freeze(exports);