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