core-3nweb-client-lib 0.26.0 → 0.27.1

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 +204 -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 +3 -0
  77. package/build/ipc-via-protobuf/connector-clients-side.js +61 -24
  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 +15 -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 -39
  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
@@ -82,7 +82,7 @@ class LinkNode extends node_in_fs_1.NodeInFS {
82
82
  if (!name || !objId || !parentId) {
83
83
  throw new Error("Bad link parameter(s) given");
84
84
  }
85
- this.crypto = new LinkPersistance(xsp_files_1.idToHeaderNonce(this.objId), key, this.storage.cryptor);
85
+ this.crypto = new LinkPersistance((0, xsp_files_1.idToHeaderNonce)(this.objId), key, this.storage.cryptor);
86
86
  Object.seal(this);
87
87
  }
88
88
  static async makeForNew(storage, parentId, name, key) {
@@ -92,12 +92,17 @@ class LinkNode extends node_in_fs_1.NodeInFS {
92
92
  return link;
93
93
  }
94
94
  static async makeForExisting(storage, parentId, name, objId, key) {
95
- const src = await storage.getObj(objId);
95
+ const src = await storage.getObjSrc(objId);
96
96
  const link = new LinkNode(storage, name, objId, src.version, parentId, key);
97
97
  const { params, attrs, xattrs } = await link.crypto.read(src);
98
98
  link.setUpdatedState(params, src.version, attrs, xattrs);
99
+ link.setCurrentStateFrom(src);
99
100
  return link;
100
101
  }
102
+ async setCurrentStateFrom(src) {
103
+ const { params, attrs, xattrs } = await this.crypto.read(src);
104
+ this.setUpdatedState(params, src.version, attrs, xattrs);
105
+ }
101
106
  setUpdatedState(params, version, attrs, xattrs) {
102
107
  this.linkParams = params;
103
108
  super.setUpdatedParams(version, attrs, xattrs);
@@ -1,11 +1,14 @@
1
- import { Node, NodeType, Storage, RemoteEvent } from './common';
1
+ import { FSChangeSrc, Node, NodeType, Storage, SyncedStorage } from './common';
2
2
  import { Observable } from 'rxjs';
3
3
  import { CommonAttrs, XAttrs } from './attrs';
4
4
  import { NodePersistance } from './node-persistence';
5
- import { UpSyncTaskInfo } from '../../../core/storage/synced/obj-status';
5
+ import { ObjSource } from 'xsp-files';
6
6
  export declare type FSEvent = web3n.files.FolderEvent | web3n.files.FileEvent;
7
+ declare type RemoteEvent = web3n.files.RemoteEvent;
7
8
  declare type XAttrsChanges = web3n.files.XAttrsChanges;
8
- declare type Stats = web3n.files.Stats;
9
+ declare type SyncStatus = web3n.files.SyncStatus;
10
+ declare type OptionsToAdopteRemote = web3n.files.OptionsToAdopteRemote;
11
+ declare type OptionsToUploadLocal = web3n.files.OptionsToUploadLocal;
9
12
  export declare abstract class NodeInFS<P extends NodePersistance> implements Node {
10
13
  protected readonly storage: Storage;
11
14
  readonly type: NodeType;
@@ -19,7 +22,7 @@ export declare abstract class NodeInFS<P extends NodePersistance> implements Nod
19
22
  private writeProc;
20
23
  get version(): number;
21
24
  protected setCurrentVersion(newVersion: number): void;
22
- private remoteEvents;
25
+ readonly isInSyncedStorage: boolean;
23
26
  protected constructor(storage: Storage, type: NodeType, name: string, objId: string, currentVersion: number, parentId: string | undefined);
24
27
  private updatedXAttrs;
25
28
  protected setUpdatedParams(version: number, attrs: CommonAttrs | undefined, xattrs: XAttrs | undefined): void;
@@ -32,17 +35,18 @@ export declare abstract class NodeInFS<P extends NodePersistance> implements Nod
32
35
  getXAttr(xaName: string): any;
33
36
  listXAttrs(): string[];
34
37
  getAttrs(): CommonAttrs;
35
- processRemoteEvent(event: RemoteEvent): Promise<void>;
36
- private bufferRemoteEvent;
37
- private getBufferedEvent;
38
- localDelete(): Promise<void>;
39
- broadcastUpSyncEvent(task: UpSyncTaskInfo): void;
38
+ listVersions(): Promise<{
39
+ current?: number;
40
+ archived?: number[];
41
+ }>;
42
+ archiveCurrent(version?: number): Promise<number>;
43
+ removeObj(src?: FSChangeSrc): Promise<void>;
40
44
  /**
41
45
  * This non-synchronized method deletes object from storage, and detaches
42
46
  * this node from storage. Make sure to call it inside access synchronization
43
47
  * construct.
44
48
  */
45
- protected delete(remoteEvent?: boolean): Promise<void>;
49
+ protected delete(src: FSChangeSrc): Promise<void>;
46
50
  /**
47
51
  * This method runs node changing function in an exclusive manner.
48
52
  * Returned promise resolves to whatever change function returns.
@@ -56,24 +60,26 @@ export declare abstract class NodeInFS<P extends NodePersistance> implements Nod
56
60
  * new current version, when change has been successful.
57
61
  */
58
62
  protected doChange<T>(awaitPrevChange: boolean, change: () => Promise<T>): Promise<T>;
59
- /**
60
- * This method is called on conflict with remote version. This method
61
- * is called at ordered point in time requiring no further synchronization.
62
- * @param remoteVersion is an object version on server
63
- */
64
- protected doOnConflict(remoteVersion: number): Promise<void>;
65
- /**
66
- * This non-synchronized method resolves conflict with remote version.
67
- * @param remoteVersion
68
- */
69
- protected doOnExternalChange(remoteVersion: number): Promise<void>;
70
- protected broadcastEvent(event: FSEvent, complete?: boolean): void;
63
+ protected broadcastEvent(event: FSEvent, complete?: boolean, childObjId?: string): void;
71
64
  /**
72
65
  * This is a lazily initialized field, when there is an external entity
73
66
  * that wants to see this node's events.
74
67
  */
75
68
  private events;
76
- get event$(): Observable<FSEvent>;
77
- sync(): Promise<Stats['sync']>;
69
+ get event$(): Observable<FSEvent | RemoteEvent>;
70
+ protected syncedStorage(): SyncedStorage;
71
+ syncStatus(): Promise<SyncStatus>;
72
+ updateStatusInfo(): Promise<SyncStatus>;
73
+ isSyncedVersionOnDisk(version: number): Promise<'partial' | 'complete' | 'none'>;
74
+ download(version: number): Promise<void>;
75
+ protected abstract setCurrentStateFrom(src: ObjSource): Promise<void>;
76
+ adoptRemote(opts: OptionsToAdopteRemote | undefined): Promise<void>;
77
+ protected needUpload(localVersion: number | undefined): Promise<{
78
+ localVersion: number;
79
+ uploadVersion: number;
80
+ createOnRemote: boolean;
81
+ } | undefined>;
82
+ upload(opts: OptionsToUploadLocal | undefined): Promise<void>;
83
+ private uploadHeaderChange;
78
84
  }
79
85
  export {};
@@ -22,8 +22,10 @@ exports.NodeInFS = void 0;
22
22
  * reliance set.
23
23
  */
24
24
  const synced_1 = require("../../../lib-common/processes/synced");
25
+ const common_1 = require("./common");
25
26
  const file_1 = require("../../../lib-common/exceptions/file");
26
27
  const error_1 = require("../../../lib-common/exceptions/error");
28
+ const exceptions_1 = require("../exceptions");
27
29
  const rxjs_1 = require("rxjs");
28
30
  const operators_1 = require("rxjs/operators");
29
31
  const attrs_1 = require("./attrs");
@@ -39,12 +41,12 @@ class NodeInFS {
39
41
  this.attrs = undefined;
40
42
  this.xattrs = undefined;
41
43
  this.writeProc = undefined;
42
- this.remoteEvents = undefined;
43
44
  /**
44
45
  * This is a lazily initialized field, when there is an external entity
45
46
  * that wants to see this node's events.
46
47
  */
47
48
  this.events = undefined;
49
+ this.isInSyncedStorage = (0, common_1.isSyncedStorage)(this.storage);
48
50
  }
49
51
  get version() {
50
52
  return this.currentVersion;
@@ -80,7 +82,7 @@ class NodeInFS {
80
82
  }
81
83
  return this.doChange(true, async () => {
82
84
  const { xattrs, newVersion } = this.getParamsForUpdate(changes);
83
- const base = await this.storage.getObj(this.objId);
85
+ const base = await this.storage.getObjSrc(this.objId);
84
86
  const sub = await this.crypto.writeXAttrs(xattrs, newVersion, base);
85
87
  await this.storage.saveObj(this.objId, newVersion, sub);
86
88
  this.setUpdatedParams(newVersion, undefined, xattrs);
@@ -96,87 +98,59 @@ class NodeInFS {
96
98
  getAttrs() {
97
99
  return this.attrs;
98
100
  }
99
- async processRemoteEvent(event) {
100
- this.bufferRemoteEvent(event);
101
- return this.doChange(true, async () => {
102
- const event = this.getBufferedEvent();
103
- if (!event) {
104
- return;
105
- }
106
- if (event.type === 'remote-change') {
107
- // TODO
108
- // uploader should show if there is process for this obj uploads with version
109
- // in the event, and if so, wait for completion of that process to either ignore
110
- // remote event, or to set conflict, or whatever
111
- // XXX should we use here synced storage methods here?
112
- // This method is called only in synced storage.
113
- // XXX detect if there is a conflict
114
- // need obj status info here
115
- // if (conflict) {
116
- // await this.doOnConflict();
117
- // } else {
118
- // await this.doOnExternalChange();
119
- // }
101
+ async listVersions() {
102
+ return (await this.storage.status(this.objId)).listVersions();
103
+ }
104
+ async archiveCurrent(version) {
105
+ if (this.isInSyncedStorage) {
106
+ const storage = this.syncedStorage();
107
+ const status = await storage.status(this.objId);
108
+ const { state, synced } = status.syncStatus();
109
+ if (state !== 'synced') {
110
+ throw (0, exceptions_1.makeFSSyncException)(this.name, { notSynced: true });
120
111
  }
121
- else if (event.type === 'remote-delete') {
122
- await this.delete(true);
112
+ if (version) {
113
+ if (synced.latest !== version) {
114
+ throw (0, exceptions_1.makeFSSyncException)(this.name, { versionMismatch: true });
115
+ }
123
116
  }
124
117
  else {
125
- throw new Error(`Unknown remote bufferred event type ${JSON.stringify(event)}`);
118
+ version = synced.latest;
126
119
  }
127
- });
128
- }
129
- bufferRemoteEvent(event) {
130
- if (!this.remoteEvents) {
131
- this.remoteEvents = [];
132
- }
133
- this.remoteEvents.push(event);
134
- if (this.remoteEvents.length > 1) {
135
- // XXX attempt to compress events
136
- }
137
- }
138
- getBufferedEvent() {
139
- if (!this.remoteEvents) {
140
- return;
120
+ await storage.archiveVersionOnServer(this.objId, version);
121
+ await status.archiveCurrentVersion();
122
+ return version;
141
123
  }
142
- const event = this.remoteEvents.shift();
143
- if (this.remoteEvents.length === 0) {
144
- this.remoteEvents = undefined;
124
+ else {
125
+ if (version) {
126
+ if (this.currentVersion !== version) {
127
+ throw (0, file_1.makeFileException)(file_1.Code.versionMismatch, this.name);
128
+ }
129
+ }
130
+ else {
131
+ version = this.currentVersion;
132
+ }
133
+ const status = await this.storage.status(this.objId);
134
+ await status.archiveCurrentVersion();
135
+ return version;
145
136
  }
146
- return event;
147
137
  }
148
- localDelete() {
149
- return this.doChange(true, () => this.delete());
150
- }
151
- broadcastUpSyncEvent(task) {
152
- if (task.type === 'upload') {
153
- this.broadcastEvent({
154
- type: 'sync-upload',
155
- path: this.name,
156
- current: this.version,
157
- uploaded: task.version
158
- });
159
- }
138
+ removeObj(src = 'local') {
139
+ return this.doChange(true, () => this.delete(src));
160
140
  }
161
141
  /**
162
142
  * This non-synchronized method deletes object from storage, and detaches
163
143
  * this node from storage. Make sure to call it inside access synchronization
164
144
  * construct.
165
145
  */
166
- async delete(remoteEvent) {
167
- if (remoteEvent) {
168
- // XXX
169
- throw Error(`Removal from remote side is not implemented, yet.`);
170
- }
171
- else {
172
- await this.storage.removeObj(this.objId);
173
- }
146
+ async delete(src) {
147
+ await this.storage.removeObj(this.objId);
174
148
  this.storage.nodes.delete(this);
175
149
  this.currentVersion = -1;
176
150
  const event = {
177
151
  type: 'removed',
178
152
  path: this.name,
179
- isRemote: remoteEvent
153
+ src
180
154
  };
181
155
  this.broadcastEvent(event, true);
182
156
  }
@@ -197,90 +171,222 @@ class NodeInFS {
197
171
  this.writeProc = new synced_1.SingleProc();
198
172
  }
199
173
  if (!awaitPrevChange && this.writeProc.isProcessing()) {
200
- throw file_1.makeFileException(file_1.Code.concurrentUpdate, this.name + ` type ${this.type}`);
174
+ throw (0, file_1.makeFileException)(file_1.Code.concurrentUpdate, this.name + ` type ${this.type}`);
201
175
  }
202
- const res = await this.writeProc.startOrChain(() => {
176
+ const res = await this.writeProc.startOrChain(async () => {
203
177
  if (this.currentVersion < 0) {
204
- throw file_1.makeFileException(file_1.Code.notFound, this.name, `Object is marked removed`);
178
+ throw (0, file_1.makeFileException)(file_1.Code.notFound, this.name, `Object is marked removed`);
179
+ }
180
+ try {
181
+ const res = await change();
182
+ return res;
205
183
  }
206
- return change()
207
- .catch((exc) => {
184
+ catch (exc) {
208
185
  if (!exc.runtimeException) {
209
- throw error_1.errWithCause(exc, `Cannot save changes to ${this.type} ${this.name}, version ${this.version}`);
186
+ throw (0, error_1.errWithCause)(exc, `Cannot save changes to ${this.type} ${this.name}, version ${this.version}`);
210
187
  }
211
188
  if (exc.type === 'storage') {
212
189
  if (exc.concurrentTransaction) {
213
- throw file_1.makeFileException(file_1.Code.concurrentUpdate, this.name, exc);
190
+ throw (0, file_1.makeFileException)(file_1.Code.concurrentUpdate, this.name, exc);
214
191
  }
215
192
  else if (exc.objNotFound) {
216
- throw file_1.makeFileException(file_1.Code.notFound, this.name, exc);
193
+ throw (0, file_1.makeFileException)(file_1.Code.notFound, this.name, exc);
217
194
  }
218
195
  }
219
- throw file_1.makeFileException(file_1.Code.ioError, this.name, exc);
220
- });
196
+ else if ((exc.type === 'file')
197
+ || (exc.type === 'fs-sync')) {
198
+ throw exc;
199
+ }
200
+ throw (0, file_1.makeFileException)(file_1.Code.ioError, this.name, exc);
201
+ }
221
202
  });
222
203
  return res;
223
204
  }
224
- /**
225
- * This method is called on conflict with remote version. This method
226
- * is called at ordered point in time requiring no further synchronization.
227
- * @param remoteVersion is an object version on server
228
- */
229
- async doOnConflict(remoteVersion) {
230
- // XXX
231
- throw new Error('Unimplemented, yet');
232
- // OLD CODE BELOW
233
- // if (remoteVersion < this.version) { return; }
234
- // await (this.storage as SyncedStorage).setCurrentSyncedVersion(
235
- // this.objId, remoteVersion);
236
- // this.setCurrentVersion(remoteVersion);
237
- }
238
- /**
239
- * This non-synchronized method resolves conflict with remote version.
240
- * @param remoteVersion
241
- */
242
- async doOnExternalChange(remoteVersion) {
243
- if (remoteVersion <= this.version) {
244
- return;
245
- }
246
- const src = await this.storage.getObj(this.objId);
247
- const newVersion = src.version;
248
- if (newVersion <= this.version) {
249
- return;
205
+ broadcastEvent(event, complete, childObjId) {
206
+ if (this.events && complete) {
207
+ this.events.sink.next(event);
208
+ this.events.sink.complete();
209
+ this.events = undefined;
250
210
  }
251
- this.setCurrentVersion(newVersion);
252
- const event = {
253
- type: 'file-change',
254
- path: this.name,
255
- isRemote: true
256
- };
257
- this.broadcastEvent(event);
211
+ this.storage.broadcastNodeEvent(this.objId, this.parentId, childObjId, event);
258
212
  }
259
- broadcastEvent(event, complete) {
260
- this.storage.broadcastNodeEvent(this.objId, this.parentId, event);
213
+ get event$() {
261
214
  if (!this.events) {
262
- return;
215
+ const sink = new rxjs_1.Subject();
216
+ const out = sink.asObservable().pipe((0, operators_1.share)());
217
+ const storeSub = this.storage.getNodeEvents()
218
+ .pipe((0, operators_1.filter)(({ objId }) => (this.objId === objId)), (0, operators_1.map)(({ event }) => copyWithPathIfRemoteEvent(event, this.name)))
219
+ .subscribe({
220
+ next: event => sink.next(event),
221
+ complete: () => {
222
+ var _a;
223
+ sink.complete();
224
+ if (((_a = this.events) === null || _a === void 0 ? void 0 : _a.sink) === sink) {
225
+ this.events = undefined;
226
+ }
227
+ },
228
+ error: err => {
229
+ var _a;
230
+ sink.error(err);
231
+ if (((_a = this.events) === null || _a === void 0 ? void 0 : _a.sink) === sink) {
232
+ this.events = undefined;
233
+ }
234
+ }
235
+ });
236
+ this.events = { sink, out, storeSub };
263
237
  }
264
- this.events.next(event);
265
- if (complete) {
266
- this.events.complete();
267
- this.events = undefined;
238
+ return this.events.out;
239
+ }
240
+ syncedStorage() {
241
+ if (!this.isInSyncedStorage) {
242
+ throw new Error(`Storage is not synced`);
268
243
  }
244
+ return this.storage;
269
245
  }
270
- get event$() {
271
- if (!this.events) {
272
- this.events = new rxjs_1.Subject();
246
+ async syncStatus() {
247
+ const storage = this.syncedStorage();
248
+ const status = (await storage.status(this.objId)).syncStatus();
249
+ if (this.parentId) {
250
+ const parent = storage.nodes.get(this.parentId);
251
+ if (parent) {
252
+ status.existsInSyncedParent =
253
+ await parent.childExistsInSyncedVersion(this.objId);
254
+ }
255
+ }
256
+ return status;
257
+ }
258
+ async updateStatusInfo() {
259
+ const storage = this.syncedStorage();
260
+ const status = await storage.updateStatusInfo(this.objId);
261
+ return await this.syncStatus();
262
+ }
263
+ isSyncedVersionOnDisk(version) {
264
+ const storage = this.syncedStorage();
265
+ return storage.isRemoteVersionOnDisk(this.objId, version);
266
+ }
267
+ async download(version) {
268
+ const storage = this.syncedStorage();
269
+ return storage.download(this.objId, version);
270
+ }
271
+ adoptRemote(opts) {
272
+ return this.doChange(true, async () => {
273
+ const storage = this.syncedStorage();
274
+ try {
275
+ const adopted = await storage.adoptRemote(this.objId, opts);
276
+ if (!adopted) {
277
+ return;
278
+ }
279
+ const src = await this.storage.getObjSrc(this.objId, adopted);
280
+ await this.setCurrentStateFrom(src);
281
+ const event = {
282
+ type: 'file-change',
283
+ src: 'sync',
284
+ path: this.name,
285
+ newVersion: this.version
286
+ };
287
+ this.broadcastEvent(event);
288
+ }
289
+ catch (exc) {
290
+ throw (0, common_1.setPathInExc)(exc, this.name);
291
+ }
292
+ });
293
+ }
294
+ async needUpload(localVersion) {
295
+ const { local, remote, synced } = await this.syncStatus();
296
+ if (localVersion) {
297
+ if (localVersion !== this.currentVersion) {
298
+ throw (0, exceptions_1.makeFSSyncException)(this.name, {
299
+ versionMismatch: true,
300
+ localVersion: this.currentVersion,
301
+ message: `Given local version ${localVersion} is not equal to current version ${this.currentVersion}`
302
+ });
303
+ }
304
+ if (!local || (local.latest !== localVersion)) {
305
+ throw (0, exceptions_1.makeFSSyncException)(this.name, {
306
+ versionMismatch: true,
307
+ message: `No local version ${localVersion} to upload`
308
+ });
309
+ }
310
+ }
311
+ else {
312
+ if (!local || !this.currentVersion) {
313
+ return;
314
+ }
315
+ localVersion = this.currentVersion;
316
+ }
317
+ if (remote) {
318
+ if (remote.latest) {
319
+ const uploadVersion = remote.latest + 1;
320
+ return { createOnRemote: false, localVersion, uploadVersion };
321
+ }
322
+ else {
323
+ throw (0, exceptions_1.makeFSSyncException)(this.name, {
324
+ versionMismatch: true,
325
+ removedOnServer: true
326
+ });
327
+ }
328
+ }
329
+ else if (synced) {
330
+ if (synced.latest) {
331
+ const uploadVersion = synced.latest + 1;
332
+ return { createOnRemote: false, localVersion, uploadVersion };
333
+ }
334
+ else {
335
+ throw (0, exceptions_1.makeFSSyncException)(this.name, {
336
+ versionMismatch: true,
337
+ removedOnServer: true
338
+ });
339
+ }
340
+ }
341
+ else {
342
+ const uploadVersion = 1;
343
+ return { createOnRemote: true, localVersion, uploadVersion };
273
344
  }
274
- return this.events.asObservable().pipe(operators_1.share());
275
345
  }
276
- async sync() {
277
- if ((this.storage.type === 'synced')
278
- || (this.storage.type === 'share')) {
279
- return this.storage.getObjSyncInfo(this.objId);
346
+ async upload(opts) {
347
+ try {
348
+ const toUpload = await this.needUpload(opts === null || opts === void 0 ? void 0 : opts.localVersion);
349
+ if (!toUpload) {
350
+ return;
351
+ }
352
+ const { localVersion, createOnRemote, uploadVersion } = toUpload;
353
+ const uploadHeader = ((localVersion === uploadVersion) ? undefined :
354
+ await this.uploadHeaderChange(localVersion, uploadVersion));
355
+ const storage = this.syncedStorage();
356
+ await storage.upload(this.objId, localVersion, uploadVersion, uploadHeader, createOnRemote);
357
+ await this.doChange(true, async () => {
358
+ storage.dropCachedLocalObjVersionsLessOrEqual(this.objId, localVersion);
359
+ if (this.currentVersion === localVersion) {
360
+ this.currentVersion = uploadVersion;
361
+ }
362
+ });
363
+ }
364
+ catch (exc) {
365
+ throw (0, common_1.setPathInExc)(exc, this.name);
280
366
  }
281
367
  }
368
+ async uploadHeaderChange(localVersion, uploadVersion) {
369
+ const currentSrc = await this.storage.getObjSrc(this.objId, localVersion);
370
+ const localHeader = await currentSrc.readHeader();
371
+ const uploadHeader = await this.crypto.reencryptHeader(localHeader, uploadVersion);
372
+ return { localHeader, localVersion, uploadHeader, uploadVersion };
373
+ }
282
374
  }
283
375
  exports.NodeInFS = NodeInFS;
284
376
  Object.freeze(NodeInFS.prototype);
285
377
  Object.freeze(NodeInFS);
378
+ function copyWithPathIfRemoteEvent(e, path) {
379
+ switch (e.type) {
380
+ case 'remote-change':
381
+ return { type: e.type, path, newVersion: e.newVersion };
382
+ case 'remote-removal':
383
+ return { type: e.type, path };
384
+ case 'remote-version-archival':
385
+ return { type: e.type, path, archivedVersion: e.archivedVersion };
386
+ case 'remote-arch-ver-removal':
387
+ return { type: e.type, path, removedArchVer: e.removedArchVer };
388
+ default:
389
+ return e;
390
+ }
391
+ }
286
392
  Object.freeze(exports);
@@ -32,7 +32,7 @@ export declare abstract class NodePersistance {
32
32
  sinkPromise: Promise<FileByteSink>;
33
33
  sub: Subscribe;
34
34
  }>;
35
- reencryptHeader: (initHeader: Uint8Array, newVersion: number) => Promise<Uint8Array>;
35
+ reencryptHeader(initHeader: Uint8Array, newVersion: number): Promise<Uint8Array>;
36
36
  }
37
37
  declare type FileByteSource = web3n.files.FileByteSource;
38
38
  declare type FileByteSink = web3n.files.FileByteSink;
@@ -28,7 +28,6 @@ const random = require("../../../lib-common/random-node");
28
28
  const pv1 = require("./xsp-payload-v1");
29
29
  const pv2 = require("./xsp-payload-v2");
30
30
  const SEG_SIZE = 16; // in 256-byte blocks = 4K in bytes
31
- const EMPTY_BYTE_ARR = new Uint8Array(0);
32
31
  /**
33
32
  * This does reading and writing, keeping keys. This and extending objects are
34
33
  * used in file system nodes as thematic place with persistence functionality.
@@ -38,14 +37,6 @@ class NodePersistance {
38
37
  this.zerothHeaderNonce = zerothHeaderNonce;
39
38
  this.key = key;
40
39
  this.cryptor = cryptor;
41
- this.reencryptHeader = async (initHeader, newVersion) => {
42
- if (!this.key) {
43
- throw new Error("Cannot use wiped object.");
44
- }
45
- const headerContent = await this.cryptor.formatWN.open(initHeader, this.key);
46
- const n = xsp_files_1.calculateNonce(this.zerothHeaderNonce, newVersion);
47
- return this.cryptor.formatWN.pack(headerContent, n, this.key);
48
- };
49
40
  }
50
41
  wipe() {
51
42
  if (this.key) {
@@ -57,7 +48,7 @@ class NodePersistance {
57
48
  }
58
49
  compareKey(keyB64) {
59
50
  const k = buffer_utils_1.base64.open(keyB64);
60
- return xsp_files_1.compareVectors(k, this.key);
51
+ return (0, xsp_files_1.compareVectors)(k, this.key);
61
52
  }
62
53
  fileKeyInBase64() {
63
54
  if (!this.key) {
@@ -69,13 +60,13 @@ class NodePersistance {
69
60
  if (!this.key) {
70
61
  throw new Error("Cannot use wiped object.");
71
62
  }
72
- return xsp_files_1.makeSegmentsWriter(this.key, this.zerothHeaderNonce, version, { type: 'new', segSize: SEG_SIZE, payloadFormat: 2 }, random.bytes, this.cryptor);
63
+ return (0, xsp_files_1.makeSegmentsWriter)(this.key, this.zerothHeaderNonce, version, { type: 'new', segSize: SEG_SIZE, payloadFormat: 2 }, random.bytes, this.cryptor);
73
64
  }
74
65
  async segWriterWithBase(newVersion, base) {
75
66
  if (!this.key) {
76
67
  throw new Error("Cannot use wiped object.");
77
68
  }
78
- return xsp_files_1.makeSegmentsWriter(this.key, this.zerothHeaderNonce, newVersion, { type: 'update', base, payloadFormat: 2 }, random.bytes, this.cryptor);
69
+ return (0, xsp_files_1.makeSegmentsWriter)(this.key, this.zerothHeaderNonce, newVersion, { type: 'update', base, payloadFormat: 2 }, random.bytes, this.cryptor);
79
70
  }
80
71
  async decryptedByteSrc(src) {
81
72
  if (!this.key) {
@@ -83,10 +74,10 @@ class NodePersistance {
83
74
  }
84
75
  const version = src.version;
85
76
  const header = await src.readHeader();
86
- const segReader = await xsp_files_1.makeSegmentsReader(this.key, this.zerothHeaderNonce, version, header, this.cryptor);
77
+ const segReader = await (0, xsp_files_1.makeSegmentsReader)(this.key, this.zerothHeaderNonce, version, header, this.cryptor);
87
78
  return {
88
79
  version,
89
- byteSrc: xsp_files_1.makeDecryptedByteSource(src.segSrc, segReader),
80
+ byteSrc: (0, xsp_files_1.makeDecryptedByteSource)(src.segSrc, segReader),
90
81
  payloadFormat: segReader.payloadFormat
91
82
  };
92
83
  }
@@ -123,7 +114,7 @@ class NodePersistance {
123
114
  async writeWhole(content, newVersion, attrs, xattrs) {
124
115
  const bytes = (Array.isArray(content) ? content : [content]);
125
116
  const segWriter = await this.segWriter(newVersion);
126
- const { sink, sub } = xsp_files_1.makeEncryptingByteSink(segWriter);
117
+ const { sink, sub } = (0, xsp_files_1.makeEncryptingByteSink)(segWriter);
127
118
  return (obs, backpressure) => {
128
119
  // sub must be called before payload creation that uses sink
129
120
  const unsub = sub(obs, backpressure);
@@ -134,7 +125,7 @@ class NodePersistance {
134
125
  }
135
126
  async writeXAttrs(xattrs, newVersion, base) {
136
127
  const segWriter = await this.segWriterWithBase(newVersion, base);
137
- const { sink, sub } = xsp_files_1.makeEncryptingByteSink(segWriter);
128
+ const { sink, sub } = (0, xsp_files_1.makeEncryptingByteSink)(segWriter);
138
129
  return (obs, backpressure) => {
139
130
  // sub must be called before payload creation that uses sink
140
131
  const unsub = sub(obs, backpressure);
@@ -147,8 +138,8 @@ class NodePersistance {
147
138
  const segWriter = await (base ?
148
139
  this.segWriterWithBase(newVersion, base) :
149
140
  this.segWriter(newVersion));
150
- const { sink, sub } = xsp_files_1.makeEncryptingByteSink(segWriter);
151
- const defSink = deferred_1.defer();
141
+ const { sink, sub } = (0, xsp_files_1.makeEncryptingByteSink)(segWriter);
142
+ const defSink = (0, deferred_1.defer)();
152
143
  return {
153
144
  sinkPromise: defSink.promise,
154
145
  sub: (obs, backpressure) => {
@@ -174,6 +165,14 @@ class NodePersistance {
174
165
  }
175
166
  };
176
167
  }
168
+ async reencryptHeader(initHeader, newVersion) {
169
+ if (!this.key) {
170
+ throw new Error("Cannot use wiped object.");
171
+ }
172
+ const headerContent = await this.cryptor.formatWN.open(initHeader, this.key);
173
+ const n = (0, xsp_files_1.calculateNonce)(this.zerothHeaderNonce, newVersion);
174
+ return this.cryptor.formatWN.pack(headerContent, n, this.key);
175
+ }
177
176
  }
178
177
  exports.NodePersistance = NodePersistance;
179
178
  Object.freeze(NodePersistance.prototype);