core-3nweb-client-lib 0.27.0 → 0.27.4
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.
- package/build/api-defs/files.d.ts +56 -26
- package/build/core/asmail/config/index.d.ts +2 -2
- package/build/core/asmail/config/index.js +2 -2
- package/build/core/asmail/config/invitations-anon.d.ts +10 -24
- package/build/core/asmail/config/invitations-anon.js +43 -31
- package/build/core/asmail/config/published-intro-key.d.ts +11 -22
- package/build/core/asmail/config/published-intro-key.js +47 -38
- package/build/core/asmail/inbox/attachments/fs.d.ts +2 -1
- package/build/core/asmail/inbox/attachments/fs.js +4 -3
- package/build/core/asmail/inbox/index.js +2 -2
- package/build/core/asmail/index.d.ts +1 -1
- package/build/core/asmail/index.js +2 -2
- package/build/core/asmail/keyring/correspondent-keys.d.ts +2 -2
- package/build/core/asmail/keyring/correspondent-keys.js +1 -1
- package/build/core/asmail/keyring/index.d.ts +9 -29
- package/build/core/asmail/keyring/index.js +82 -69
- package/build/core/id-manager/index.d.ts +43 -0
- package/build/core/{id-manager.js → id-manager/index.js} +33 -114
- package/build/core/id-manager/key-storage.d.ts +21 -0
- package/build/core/id-manager/key-storage.js +96 -0
- package/build/core/index.js +22 -25
- package/build/core/sign-in.d.ts +1 -2
- package/build/core/sign-in.js +5 -14
- package/build/core/sign-up.d.ts +2 -0
- package/build/core/sign-up.js +2 -1
- package/build/core/storage/index.d.ts +4 -2
- package/build/core/storage/index.js +36 -57
- package/build/core/storage/local/storage.d.ts +1 -1
- package/build/core/storage/synced/obj-files-gc.d.ts +1 -4
- package/build/core/storage/synced/obj-files-gc.js +1 -18
- package/build/core/storage/synced/obj-files.d.ts +11 -1
- package/build/core/storage/synced/obj-files.js +59 -34
- package/build/core/storage/synced/obj-status.d.ts +19 -7
- package/build/core/storage/synced/obj-status.js +158 -83
- package/build/core/storage/synced/storage.d.ts +7 -2
- package/build/core/storage/synced/storage.js +38 -15
- package/build/core/storage/synced/upsyncer.d.ts +4 -4
- package/build/core/storage/synced/upsyncer.js +14 -9
- package/build/ipc-via-protobuf/file.d.ts +7 -0
- package/build/ipc-via-protobuf/file.js +60 -27
- package/build/ipc-via-protobuf/fs.js +55 -38
- package/build/lib-client/3nstorage/exceptions.d.ts +13 -1
- package/build/lib-client/3nstorage/exceptions.js +9 -3
- package/build/lib-client/3nstorage/service.d.ts +6 -2
- package/build/lib-client/3nstorage/service.js +33 -17
- package/build/lib-client/3nstorage/util/file-based-json.js +2 -1
- package/build/lib-client/3nstorage/util/for-arrays.d.ts +1 -0
- package/build/lib-client/3nstorage/util/for-arrays.js +32 -0
- package/build/lib-client/3nstorage/xsp-fs/common.d.ts +5 -4
- package/build/lib-client/3nstorage/xsp-fs/common.js +1 -0
- package/build/lib-client/3nstorage/xsp-fs/file-node.d.ts +5 -10
- package/build/lib-client/3nstorage/xsp-fs/file-node.js +43 -45
- package/build/lib-client/3nstorage/xsp-fs/file.d.ts +7 -6
- package/build/lib-client/3nstorage/xsp-fs/file.js +14 -20
- package/build/lib-client/3nstorage/xsp-fs/folder-node.d.ts +16 -5
- package/build/lib-client/3nstorage/xsp-fs/folder-node.js +238 -68
- package/build/lib-client/3nstorage/xsp-fs/fs.d.ts +18 -17
- package/build/lib-client/3nstorage/xsp-fs/fs.js +32 -37
- package/build/lib-client/3nstorage/xsp-fs/node-in-fs.d.ts +15 -11
- package/build/lib-client/3nstorage/xsp-fs/node-in-fs.js +72 -22
- package/build/lib-client/3nstorage/xsp-fs/xsp-payload-v1.js +1 -1
- package/build/lib-client/local-files/device-fs.js +11 -11
- package/build/lib-client/objs-on-disk/obj-on-disk.d.ts +5 -2
- package/build/lib-client/objs-on-disk/obj-on-disk.js +16 -1
- package/build/lib-client/user-with-mid-session.d.ts +2 -1
- package/build/lib-client/user-with-mid-session.js +7 -1
- package/build/lib-common/async-fs-node.js +8 -8
- package/build/lib-common/exceptions/file.d.ts +4 -2
- package/build/lib-common/exceptions/file.js +24 -58
- package/build/lib-common/ipc/generic-ipc.js +5 -4
- package/build/lib-common/objs-on-disk/file-layout.js +1 -1
- package/build/lib-common/objs-on-disk/utils.js +1 -1
- package/build/lib-common/service-api/3nstorage/owner.d.ts +8 -9
- package/build/lib-common/service-api/3nstorage/owner.js +2 -1
- package/build/protos/asmail.proto.js +5943 -4348
- package/build/protos/file.proto.js +874 -0
- package/build/protos/fs.proto.js +7014 -5419
- package/package.json +3 -2
- package/protos/file.proto +23 -7
- package/protos/fs.proto +27 -13
- package/build/core/id-manager.d.ts +0 -46
|
@@ -37,6 +37,7 @@ const folder_node_serialization_1 = require("./folder-node-serialization");
|
|
|
37
37
|
const attrs_1 = require("./attrs");
|
|
38
38
|
const node_persistence_1 = require("./node-persistence");
|
|
39
39
|
const assert_1 = require("../../../lib-common/assert");
|
|
40
|
+
const for_arrays_1 = require("../util/for-arrays");
|
|
40
41
|
function jsonToInfoAndAttrs(json) {
|
|
41
42
|
const folderInfo = {
|
|
42
43
|
nodes: (0, json_utils_1.copy)(json.nodes)
|
|
@@ -62,6 +63,14 @@ class FolderPersistance extends node_persistence_1.NodePersistance {
|
|
|
62
63
|
const folderInfo = (0, folder_node_serialization_1.parseFolderInfo)(content);
|
|
63
64
|
return { folderInfo, xattrs, attrs: attrs_1.CommonAttrs.fromAttrs(attrs) };
|
|
64
65
|
}
|
|
66
|
+
static async readFolderContent(objId, key, src, cryptor) {
|
|
67
|
+
if (objId === null) {
|
|
68
|
+
throw new Error("Missing objId for non-root folder");
|
|
69
|
+
}
|
|
70
|
+
const zNonce = (0, xsp_files_1.idToHeaderNonce)(objId);
|
|
71
|
+
const { folderInfo } = await (new FolderPersistance(zNonce, key, cryptor)).read(src);
|
|
72
|
+
return folderInfo;
|
|
73
|
+
}
|
|
65
74
|
}
|
|
66
75
|
Object.freeze(FolderPersistance.prototype);
|
|
67
76
|
Object.freeze(FolderPersistance);
|
|
@@ -84,7 +93,7 @@ class FolderNode extends node_in_fs_1.NodeInFS {
|
|
|
84
93
|
(0, assert_1.assert)(!objId && !parentId, `Root folder must have both objId and parent as nulls.`);
|
|
85
94
|
}
|
|
86
95
|
else if (objId === null) {
|
|
87
|
-
new Error("Missing objId for non-root folder");
|
|
96
|
+
throw new Error("Missing objId for non-root folder");
|
|
88
97
|
}
|
|
89
98
|
this.crypto = new FolderPersistance(zNonce, key, storage.cryptor);
|
|
90
99
|
if (setNewAttrs) {
|
|
@@ -198,7 +207,16 @@ class FolderNode extends node_in_fs_1.NodeInFS {
|
|
|
198
207
|
return;
|
|
199
208
|
}
|
|
200
209
|
for (const objToRm of objsToRm) {
|
|
201
|
-
|
|
210
|
+
const nodeToRm = await this.getOrMakeChildNodeForInfo(objToRm);
|
|
211
|
+
this.callRemoveObjOn('sync', nodeToRm);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
callRemoveObjOn(src, node) {
|
|
215
|
+
if (node.type === 'folder') {
|
|
216
|
+
node.removeFolderObj(src);
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
node.removeNonFolderObj(src);
|
|
202
220
|
}
|
|
203
221
|
}
|
|
204
222
|
list() {
|
|
@@ -206,19 +224,33 @@ class FolderNode extends node_in_fs_1.NodeInFS {
|
|
|
206
224
|
.map(nodeInfoToListingEntry);
|
|
207
225
|
return { lst, version: this.version };
|
|
208
226
|
}
|
|
227
|
+
async listNonCurrent(flags) {
|
|
228
|
+
const src = await this.getObjSrcOfVersion(flags);
|
|
229
|
+
const { folderInfo } = await this.crypto.read(src);
|
|
230
|
+
const lst = Object.values(folderInfo)
|
|
231
|
+
.map(nodeInfoToListingEntry);
|
|
232
|
+
return { lst, version: src.version };
|
|
233
|
+
}
|
|
209
234
|
async childExistsInSyncedVersion(childObjId) {
|
|
210
|
-
const
|
|
211
|
-
if (
|
|
235
|
+
const { state, synced } = await this.syncStatus();
|
|
236
|
+
if (state === 'synced') {
|
|
212
237
|
return true;
|
|
213
238
|
}
|
|
214
|
-
if (!
|
|
239
|
+
if (!(synced === null || synced === void 0 ? void 0 : synced.latest)) {
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
const storage = this.syncedStorage();
|
|
243
|
+
try {
|
|
244
|
+
const syncedContent = await storage.getObjSrc(this.objId, synced.latest);
|
|
245
|
+
const { folderInfo } = await this.crypto.read(syncedContent);
|
|
246
|
+
const childIsInSynced = !!Object.values(folderInfo.nodes)
|
|
247
|
+
.find(({ objId }) => (objId === childObjId));
|
|
248
|
+
return childIsInSynced;
|
|
249
|
+
}
|
|
250
|
+
catch (exc) {
|
|
251
|
+
storage.logError(exc, `Exception thrown in checking whether child node's obj is present in synced version.`);
|
|
215
252
|
return false;
|
|
216
253
|
}
|
|
217
|
-
// XXX FolderNode.childExistsInSyncedVersion() should implement check in synced version
|
|
218
|
-
return false;
|
|
219
|
-
}
|
|
220
|
-
listFolders() {
|
|
221
|
-
return Object.keys(this.currentState.nodes).filter(name => !!this.currentState.nodes[name].isFolder);
|
|
222
254
|
}
|
|
223
255
|
getNodeInfo(name, undefOnMissing = false) {
|
|
224
256
|
const fj = this.currentState.nodes[name];
|
|
@@ -229,7 +261,7 @@ class FolderNode extends node_in_fs_1.NodeInFS {
|
|
|
229
261
|
return;
|
|
230
262
|
}
|
|
231
263
|
else {
|
|
232
|
-
throw (0, file_1.makeFileException)(
|
|
264
|
+
throw (0, file_1.makeFileException)('notFound', name);
|
|
233
265
|
}
|
|
234
266
|
}
|
|
235
267
|
hasChild(childName, throwIfMissing = false) {
|
|
@@ -242,13 +274,13 @@ class FolderNode extends node_in_fs_1.NodeInFS {
|
|
|
242
274
|
}
|
|
243
275
|
if (type) {
|
|
244
276
|
if ((type === 'file') && !childInfo.isFile) {
|
|
245
|
-
throw (0, file_1.makeFileException)(
|
|
277
|
+
throw (0, file_1.makeFileException)('notFile', childInfo.name);
|
|
246
278
|
}
|
|
247
279
|
else if ((type === 'folder') && !childInfo.isFolder) {
|
|
248
|
-
throw (0, file_1.makeFileException)(
|
|
280
|
+
throw (0, file_1.makeFileException)('notDirectory', childInfo.name);
|
|
249
281
|
}
|
|
250
282
|
else if ((type === 'link') && !childInfo.isLink) {
|
|
251
|
-
throw (0, file_1.makeFileException)(
|
|
283
|
+
throw (0, file_1.makeFileException)('notLink', childInfo.name);
|
|
252
284
|
}
|
|
253
285
|
}
|
|
254
286
|
return this.getOrMakeChildNodeForInfo(childInfo);
|
|
@@ -314,7 +346,7 @@ class FolderNode extends node_in_fs_1.NodeInFS {
|
|
|
314
346
|
};
|
|
315
347
|
return { event, childObjId: childInfo.objId };
|
|
316
348
|
}).catch(noop);
|
|
317
|
-
const fileExc = (0, file_1.makeFileException)(
|
|
349
|
+
const fileExc = (0, file_1.makeFileException)('notFound', childInfo.name, exc);
|
|
318
350
|
fileExc.inconsistentStateOfFS = true;
|
|
319
351
|
throw fileExc;
|
|
320
352
|
}
|
|
@@ -421,7 +453,7 @@ class FolderNode extends node_in_fs_1.NodeInFS {
|
|
|
421
453
|
// do check for concurrent creation of a node
|
|
422
454
|
if (this.getNodeInfo(name, true)) {
|
|
423
455
|
if (exclusive) {
|
|
424
|
-
throw (0, file_1.makeFileException)(
|
|
456
|
+
throw (0, file_1.makeFileException)('alreadyExists', name);
|
|
425
457
|
}
|
|
426
458
|
else if (type === 'folder') {
|
|
427
459
|
return (await this.getNode('folder', name));
|
|
@@ -494,7 +526,7 @@ class FolderNode extends node_in_fs_1.NodeInFS {
|
|
|
494
526
|
// explicitly do not wait on a result of child's delete, cause if it fails
|
|
495
527
|
// we just get traceable garbage, yet, the rest of a live/non-deleted tree
|
|
496
528
|
// stays consistent
|
|
497
|
-
|
|
529
|
+
this.callRemoveObjOn('local', f);
|
|
498
530
|
}
|
|
499
531
|
changeChildName(initName, newName) {
|
|
500
532
|
return this.doTransition(async (state, version) => {
|
|
@@ -519,7 +551,7 @@ class FolderNode extends node_in_fs_1.NodeInFS {
|
|
|
519
551
|
}
|
|
520
552
|
async moveChildTo(childName, dst, nameInDst) {
|
|
521
553
|
if (dst.hasChild(nameInDst)) {
|
|
522
|
-
throw (0, file_1.makeFileException)(
|
|
554
|
+
throw (0, file_1.makeFileException)('alreadyExists', nameInDst);
|
|
523
555
|
}
|
|
524
556
|
if (dst === this) {
|
|
525
557
|
// In this case we only need to change child's name
|
|
@@ -574,7 +606,7 @@ class FolderNode extends node_in_fs_1.NodeInFS {
|
|
|
574
606
|
// existing folder at this point
|
|
575
607
|
if (path.length === 1) {
|
|
576
608
|
if (exclusiveCreate) {
|
|
577
|
-
throw (0, file_1.makeFileException)(
|
|
609
|
+
throw (0, file_1.makeFileException)('alreadyExists', path[0]);
|
|
578
610
|
}
|
|
579
611
|
else {
|
|
580
612
|
return f;
|
|
@@ -631,22 +663,91 @@ class FolderNode extends node_in_fs_1.NodeInFS {
|
|
|
631
663
|
}
|
|
632
664
|
return content;
|
|
633
665
|
}
|
|
634
|
-
async
|
|
635
|
-
const childrenNodes = await this.
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
666
|
+
async removeFolderObj(src, passIdsForRmUpload = false) {
|
|
667
|
+
const childrenNodes = await this.doChange(true, async () => {
|
|
668
|
+
const childrenNodes = await this.getAllNodes();
|
|
669
|
+
await this.removeThisNodeAsLeaf(src);
|
|
670
|
+
return childrenNodes;
|
|
671
|
+
});
|
|
672
|
+
if (childrenNodes.length === 0) {
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
675
|
+
if (this.isInSyncedStorage) {
|
|
676
|
+
if (passIdsForRmUpload) {
|
|
677
|
+
return this.removeChildrenObjsInSyncedStorage(childrenNodes, src, true);
|
|
678
|
+
}
|
|
679
|
+
else {
|
|
680
|
+
this.removeChildrenObjsInSyncedStorage(childrenNodes, src, false);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
else {
|
|
684
|
+
this.callRemoveObjOnAll(src, childrenNodes);
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
callRemoveObjOnAll(src, nodes) {
|
|
688
|
+
for (const f of nodes) {
|
|
689
|
+
this.callRemoveObjOn(src, f);
|
|
648
690
|
}
|
|
649
691
|
}
|
|
692
|
+
async removeChildrenObjsInSyncedStorage(childrenNodes, src, passIdsForRmUpload) {
|
|
693
|
+
let uploadRmsHere;
|
|
694
|
+
let collectedIds;
|
|
695
|
+
if (passIdsForRmUpload) {
|
|
696
|
+
collectedIds = [];
|
|
697
|
+
uploadRmsHere = false;
|
|
698
|
+
}
|
|
699
|
+
else {
|
|
700
|
+
try {
|
|
701
|
+
const status = await this.syncedStorage().status(this.objId);
|
|
702
|
+
if (status.neverUploaded()) {
|
|
703
|
+
collectedIds = [];
|
|
704
|
+
uploadRmsHere = true;
|
|
705
|
+
}
|
|
706
|
+
else {
|
|
707
|
+
collectedIds = undefined;
|
|
708
|
+
uploadRmsHere = false;
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
catch (exc) {
|
|
712
|
+
if (exc.objNotFound) {
|
|
713
|
+
collectedIds = [];
|
|
714
|
+
uploadRmsHere = true;
|
|
715
|
+
}
|
|
716
|
+
else {
|
|
717
|
+
throw exc;
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
if (!collectedIds) {
|
|
722
|
+
this.callRemoveObjOnAll(src, childrenNodes);
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
725
|
+
await Promise.allSettled(childrenNodes.map(async (child) => {
|
|
726
|
+
const status = await this.syncedStorage().status(child.objId);
|
|
727
|
+
if (!status.neverUploaded()) {
|
|
728
|
+
collectedIds.push(child.objId);
|
|
729
|
+
}
|
|
730
|
+
if (child.type === 'folder') {
|
|
731
|
+
const ids = await child.removeFolderObj(src, passIdsForRmUpload);
|
|
732
|
+
if (ids) {
|
|
733
|
+
collectedIds.push(...ids);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
else {
|
|
737
|
+
await child.removeNonFolderObj(src);
|
|
738
|
+
}
|
|
739
|
+
}));
|
|
740
|
+
if (uploadRmsHere) {
|
|
741
|
+
await this.uploadRemovalOfObjs(collectedIds);
|
|
742
|
+
}
|
|
743
|
+
else {
|
|
744
|
+
return collectedIds;
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
async uploadRemovalOfObjs(objsToRm) {
|
|
748
|
+
objsToRm.sort(); // shuffle order
|
|
749
|
+
await Promise.allSettled(objsToRm.map(objToRm => this.syncedStorage().uploadObjRemoval(objToRm)));
|
|
750
|
+
}
|
|
650
751
|
getParamsForLink() {
|
|
651
752
|
if ((this.storage.type !== 'synced') && (this.storage.type !== 'local')) {
|
|
652
753
|
throw new Error(`Creating link parameters to object in ${this.storage.type} file system, is not implemented.`);
|
|
@@ -664,24 +765,72 @@ class FolderNode extends node_in_fs_1.NodeInFS {
|
|
|
664
765
|
return linkParams;
|
|
665
766
|
}
|
|
666
767
|
async upload(opts) {
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
768
|
+
try {
|
|
769
|
+
const toUpload = await this.needUpload(opts === null || opts === void 0 ? void 0 : opts.localVersion);
|
|
770
|
+
if (!toUpload) {
|
|
771
|
+
return;
|
|
772
|
+
}
|
|
773
|
+
if (toUpload.createOnRemote) {
|
|
774
|
+
await super.upload(opts);
|
|
775
|
+
return;
|
|
776
|
+
}
|
|
777
|
+
const storage = this.syncedStorage();
|
|
778
|
+
const { localVersion, uploadVersion } = toUpload;
|
|
779
|
+
const removedNodes = await this.getNodesRemovedBetweenVersions(localVersion, uploadVersion - 1);
|
|
780
|
+
const uploadHeader = await this.uploadHeaderChange(localVersion, uploadVersion);
|
|
781
|
+
await storage.upload(this.objId, localVersion, uploadVersion, uploadHeader, false);
|
|
782
|
+
if (removedNodes.length > 0) {
|
|
783
|
+
// start upload of children's removal after folder's upload;
|
|
784
|
+
// we also don't await for chidren removal
|
|
785
|
+
this.uploadRemovalOf(removedNodes);
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
catch (exc) {
|
|
789
|
+
throw (0, common_1.setPathInExc)(exc, this.name);
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
async uploadRemovalOf(removedNodes) {
|
|
793
|
+
const rmObjs = [];
|
|
794
|
+
for (const node of removedNodes) {
|
|
795
|
+
(0, for_arrays_1.appendArray)(rmObjs, await this.listRemovedInTreeToUploadRm(node));
|
|
796
|
+
}
|
|
797
|
+
await this.uploadRemovalOfObjs(rmObjs);
|
|
798
|
+
}
|
|
799
|
+
async listRemovedInTreeToUploadRm(node) {
|
|
800
|
+
const storage = this.syncedStorage();
|
|
801
|
+
let versionBeforeRm;
|
|
802
|
+
try {
|
|
803
|
+
const status = await storage.status(node.objId);
|
|
804
|
+
versionBeforeRm = status.versionBeforeUnsyncedRemoval();
|
|
805
|
+
if (!versionBeforeRm) {
|
|
806
|
+
return;
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
catch (exc) {
|
|
810
|
+
if (exc.objNotFound
|
|
811
|
+
|| exc.notFound) {
|
|
812
|
+
return;
|
|
813
|
+
}
|
|
814
|
+
throw exc;
|
|
815
|
+
}
|
|
816
|
+
if (node.isFolder) {
|
|
817
|
+
const objs = [node.objId];
|
|
818
|
+
const src = await storage.getObjSrc(node.objId, versionBeforeRm, true);
|
|
819
|
+
const folderContent = await FolderPersistance.readFolderContent(node.objId, node.key, src, storage.cryptor);
|
|
820
|
+
for (const child of Object.values(folderContent.nodes)) {
|
|
821
|
+
(0, for_arrays_1.appendArray)(objs, await this.listRemovedInTreeToUploadRm(child));
|
|
822
|
+
}
|
|
823
|
+
return objs;
|
|
824
|
+
}
|
|
825
|
+
else {
|
|
826
|
+
return node.objId;
|
|
827
|
+
}
|
|
676
828
|
}
|
|
677
829
|
async needUpload(localVersion) {
|
|
678
830
|
const toUpload = await super.needUpload(localVersion);
|
|
679
831
|
if (!toUpload) {
|
|
680
832
|
return;
|
|
681
833
|
}
|
|
682
|
-
// XXX can put the following into private ensureAllChildrenUploaded(),
|
|
683
|
-
// but it also need to get a consistent state, while current one can
|
|
684
|
-
// be broken by simultaneous change in folder.
|
|
685
834
|
const storage = this.syncedStorage();
|
|
686
835
|
if (toUpload.localVersion === this.version) {
|
|
687
836
|
for (const { objId, name } of Object.values(this.currentState.nodes)) {
|
|
@@ -693,10 +842,29 @@ class FolderNode extends node_in_fs_1.NodeInFS {
|
|
|
693
842
|
}
|
|
694
843
|
}
|
|
695
844
|
else {
|
|
696
|
-
throw
|
|
845
|
+
throw (0, exceptions_1.makeFSSyncException)(this.name, {
|
|
846
|
+
versionMismatch: true,
|
|
847
|
+
localVersion: toUpload.localVersion,
|
|
848
|
+
message: `Local version has concurrently changed from ${toUpload.localVersion} to current ${this.version}`
|
|
849
|
+
});
|
|
697
850
|
}
|
|
698
851
|
return toUpload;
|
|
699
852
|
}
|
|
853
|
+
async getNodesRemovedBetweenVersions(newVer, syncedVer) {
|
|
854
|
+
const storage = this.syncedStorage();
|
|
855
|
+
let stateToUpload;
|
|
856
|
+
if (this.version === newVer) {
|
|
857
|
+
stateToUpload = this.currentState;
|
|
858
|
+
}
|
|
859
|
+
else {
|
|
860
|
+
const localVerSrc = await storage.getObjSrcOfRemoteVersion(this.objId, newVer);
|
|
861
|
+
({ folderInfo: stateToUpload } = await this.crypto.read(localVerSrc));
|
|
862
|
+
}
|
|
863
|
+
const syncedVerSrc = await storage.getObjSrcOfRemoteVersion(this.objId, syncedVer);
|
|
864
|
+
const { folderInfo: syncedState } = await this.crypto.read(syncedVerSrc);
|
|
865
|
+
const { removedNodes } = identifyChanges(syncedState.nodes, stateToUpload.nodes);
|
|
866
|
+
return removedNodes;
|
|
867
|
+
}
|
|
700
868
|
async adoptRemoteFolderItem(itemName, opts) {
|
|
701
869
|
if (opts === null || opts === void 0 ? void 0 : opts.localVersion) {
|
|
702
870
|
if (this.version !== opts.localVersion) {
|
|
@@ -741,10 +909,12 @@ class FolderNode extends node_in_fs_1.NodeInFS {
|
|
|
741
909
|
return await this.addRemoteChild(remoteChildNode);
|
|
742
910
|
}
|
|
743
911
|
else if (localNodeToRm.objId === remoteChildNode.objId) {
|
|
744
|
-
|
|
912
|
+
(0, assert_1.assert)(typeOfNode(localNodeToRm) === typeOfNode(remoteChildNode));
|
|
913
|
+
// XXX
|
|
914
|
+
throw new Error(`Adaptation of changing keys needs implementation`);
|
|
745
915
|
}
|
|
746
916
|
else {
|
|
747
|
-
return await this.replaceLocalChildWithRemote(
|
|
917
|
+
return await this.replaceLocalChildWithRemote(remoteChildNode);
|
|
748
918
|
}
|
|
749
919
|
}
|
|
750
920
|
async addRemoteChild(remoteChildNode) {
|
|
@@ -761,25 +931,14 @@ class FolderNode extends node_in_fs_1.NodeInFS {
|
|
|
761
931
|
};
|
|
762
932
|
return { event, childObjId: remoteChildNode.objId };
|
|
763
933
|
});
|
|
764
|
-
// XXX child should update sync info, and adopt change.
|
|
765
934
|
return newVersion;
|
|
766
935
|
}
|
|
767
|
-
async
|
|
936
|
+
async replaceLocalChildWithRemote(remoteChildNode) {
|
|
937
|
+
let origChildNode;
|
|
768
938
|
let newVersion;
|
|
769
939
|
await this.doTransition(async (state, version) => {
|
|
770
940
|
newVersion = version;
|
|
771
|
-
state.nodes[remoteChildNode.name]
|
|
772
|
-
return [];
|
|
773
|
-
});
|
|
774
|
-
// XXX child should update sync info, and adopt change, cause changed key
|
|
775
|
-
// requires changed cypher.
|
|
776
|
-
return newVersion;
|
|
777
|
-
}
|
|
778
|
-
async replaceLocalChildWithRemote(origChildNode, remoteChildNode) {
|
|
779
|
-
let newVersion;
|
|
780
|
-
await this.doTransition(async (state, version) => {
|
|
781
|
-
newVersion = version;
|
|
782
|
-
const presentNode = state.nodes[remoteChildNode.name];
|
|
941
|
+
origChildNode = state.nodes[remoteChildNode.name];
|
|
783
942
|
state.nodes[remoteChildNode.name] = remoteChildNode;
|
|
784
943
|
const additionEvent = {
|
|
785
944
|
type: 'entry-addition',
|
|
@@ -799,12 +958,9 @@ class FolderNode extends node_in_fs_1.NodeInFS {
|
|
|
799
958
|
{ event: additionEvent, childObjId: remoteChildNode.objId }
|
|
800
959
|
];
|
|
801
960
|
});
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
// - if only local, should be removed,
|
|
806
|
-
// - else should update sync info, and adopt both removal and change.
|
|
807
|
-
(await this.getOrMakeChildNodeForInfo(origChildNode)).removeObj('sync');
|
|
961
|
+
const origChild = await this.getOrMakeChildNodeForInfo(origChildNode);
|
|
962
|
+
const removalsToUpload = (await this.removeChildrenObjsInSyncedStorage([origChild], 'sync', true));
|
|
963
|
+
this.uploadRemovalOfObjs(removalsToUpload);
|
|
808
964
|
return newVersion;
|
|
809
965
|
}
|
|
810
966
|
async diffCurrentAndRemote(remoteVersion) {
|
|
@@ -907,6 +1063,20 @@ function nodeToListingEntry({ name, type }) {
|
|
|
907
1063
|
return { name };
|
|
908
1064
|
}
|
|
909
1065
|
}
|
|
1066
|
+
function typeOfNode(nodeInfo) {
|
|
1067
|
+
if (nodeInfo.isFolder) {
|
|
1068
|
+
return 'folder';
|
|
1069
|
+
}
|
|
1070
|
+
else if (nodeInfo.isFile) {
|
|
1071
|
+
return 'file';
|
|
1072
|
+
}
|
|
1073
|
+
else if (nodeInfo.isLink) {
|
|
1074
|
+
return 'link';
|
|
1075
|
+
}
|
|
1076
|
+
else {
|
|
1077
|
+
throw new Error(`Unknown type of node info`);
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
910
1080
|
function addToTransitionState(state, f, key) {
|
|
911
1081
|
const nodeInfo = {
|
|
912
1082
|
name: f.name,
|
|
@@ -21,6 +21,7 @@ declare type FSCollection = web3n.files.FSCollection;
|
|
|
21
21
|
declare type FileFlags = web3n.files.FileFlags;
|
|
22
22
|
declare type FileByteSource = web3n.files.FileByteSource;
|
|
23
23
|
declare type FileByteSink = web3n.files.FileByteSink;
|
|
24
|
+
declare type VersionedReadFlags = web3n.files.VersionedReadFlags;
|
|
24
25
|
declare type XAttrsChanges = web3n.files.XAttrsChanges;
|
|
25
26
|
declare type WritableFSSyncAPI = web3n.files.WritableFSSyncAPI;
|
|
26
27
|
declare type SyncStatus = web3n.files.SyncStatus;
|
|
@@ -39,7 +40,7 @@ export declare class XspFS implements WritableFS {
|
|
|
39
40
|
private constructor();
|
|
40
41
|
private storage;
|
|
41
42
|
readonlySubRoot(path: string): Promise<ReadonlyFS>;
|
|
42
|
-
writableSubRoot(path: string, flags?: web3n.files.
|
|
43
|
+
writableSubRoot(path: string, flags?: web3n.files.VersionedFileWriteFlags): Promise<WritableFS>;
|
|
43
44
|
/**
|
|
44
45
|
* This creates in a root object in a given storage, returning fs object
|
|
45
46
|
* representing created root.
|
|
@@ -88,7 +89,7 @@ export declare class XspFS implements WritableFS {
|
|
|
88
89
|
watchFile(path: string, observer: Observer<FileEvent>): () => void;
|
|
89
90
|
watchTree(path: string, depth: number | undefined, observer: Observer<FolderEvent | FileEvent>): () => void;
|
|
90
91
|
readonlyFile(path: string): Promise<ReadonlyFile>;
|
|
91
|
-
writableFile(path: string, flags?: web3n.files.
|
|
92
|
+
writableFile(path: string, flags?: web3n.files.VersionedFileWriteFlags): Promise<WritableFile>;
|
|
92
93
|
copyFile(src: string, dst: string, overwrite?: boolean): Promise<void>;
|
|
93
94
|
saveFile(file: File, dst: string, overwrite?: boolean): Promise<void>;
|
|
94
95
|
listFolder(folder: string): Promise<ListingEntry[]>;
|
|
@@ -96,10 +97,10 @@ export declare class XspFS implements WritableFS {
|
|
|
96
97
|
readTxtFile(path: string): Promise<string>;
|
|
97
98
|
readBytes(path: string, start?: number, end?: number): Promise<Uint8Array | undefined>;
|
|
98
99
|
getByteSource(path: string): Promise<FileByteSource>;
|
|
99
|
-
writeJSONFile(path: string, json: any, flags?: web3n.files.
|
|
100
|
-
writeTxtFile(path: string, txt: string, flags?: web3n.files.
|
|
101
|
-
writeBytes(path: string, bytes: Uint8Array, flags?: web3n.files.
|
|
102
|
-
getByteSink(path: string, flags?: web3n.files.
|
|
100
|
+
writeJSONFile(path: string, json: any, flags?: web3n.files.VersionedFileWriteFlags): Promise<void>;
|
|
101
|
+
writeTxtFile(path: string, txt: string, flags?: web3n.files.VersionedFileWriteFlags): Promise<void>;
|
|
102
|
+
writeBytes(path: string, bytes: Uint8Array, flags?: web3n.files.VersionedFileWriteFlags): Promise<void>;
|
|
103
|
+
getByteSink(path: string, flags?: web3n.files.VersionedFileWriteFlags): Promise<FileByteSink>;
|
|
103
104
|
}
|
|
104
105
|
interface N {
|
|
105
106
|
get(path: string): Promise<NodeInFS<any>>;
|
|
@@ -121,38 +122,38 @@ declare class V implements WritableFSVersionedAPI, N {
|
|
|
121
122
|
get(path: string): Promise<NodeInFS<any>>;
|
|
122
123
|
ensureIsWritable(): void;
|
|
123
124
|
updateXAttrs(path: string, changes: XAttrsChanges): Promise<number>;
|
|
124
|
-
getXAttr(path: string, xaName: string): Promise<{
|
|
125
|
+
getXAttr(path: string, xaName: string, flags?: VersionedReadFlags): Promise<{
|
|
125
126
|
attr: any;
|
|
126
127
|
version: number;
|
|
127
128
|
}>;
|
|
128
|
-
listXAttrs(path: string): Promise<{
|
|
129
|
+
listXAttrs(path: string, flags?: VersionedReadFlags): Promise<{
|
|
129
130
|
lst: string[];
|
|
130
131
|
version: number;
|
|
131
132
|
}>;
|
|
132
|
-
listFolder(path: string): Promise<{
|
|
133
|
+
listFolder(path: string, flags?: VersionedReadFlags): Promise<{
|
|
133
134
|
lst: ListingEntry[];
|
|
134
135
|
version: number;
|
|
135
136
|
}>;
|
|
136
|
-
writeBytes(path: string, bytes: Uint8Array, flags?: web3n.files.
|
|
137
|
-
readBytes(path: string, start?: number, end?: number): Promise<{
|
|
137
|
+
writeBytes(path: string, bytes: Uint8Array, flags?: web3n.files.VersionedFileWriteFlags): Promise<number>;
|
|
138
|
+
readBytes(path: string, start?: number, end?: number, flags?: VersionedReadFlags): Promise<{
|
|
138
139
|
bytes: Uint8Array | undefined;
|
|
139
140
|
version: number;
|
|
140
141
|
}>;
|
|
141
|
-
writeTxtFile(path: string, txt: string, flags?: web3n.files.
|
|
142
|
-
readTxtFile(path: string): Promise<{
|
|
142
|
+
writeTxtFile(path: string, txt: string, flags?: web3n.files.VersionedFileWriteFlags): Promise<number>;
|
|
143
|
+
readTxtFile(path: string, flags?: VersionedReadFlags): Promise<{
|
|
143
144
|
txt: string;
|
|
144
145
|
version: number;
|
|
145
146
|
}>;
|
|
146
|
-
writeJSONFile(path: string, json: any, flags?: web3n.files.
|
|
147
|
-
readJSONFile<T>(path: string): Promise<{
|
|
147
|
+
writeJSONFile(path: string, json: any, flags?: web3n.files.VersionedFileWriteFlags): Promise<number>;
|
|
148
|
+
readJSONFile<T>(path: string, flags?: VersionedReadFlags): Promise<{
|
|
148
149
|
json: T;
|
|
149
150
|
version: number;
|
|
150
151
|
}>;
|
|
151
|
-
getByteSink(path: string, flags?: web3n.files.
|
|
152
|
+
getByteSink(path: string, flags?: web3n.files.VersionedFileWriteFlags): Promise<{
|
|
152
153
|
sink: FileByteSink;
|
|
153
154
|
version: number;
|
|
154
155
|
}>;
|
|
155
|
-
getByteSource(path: string): Promise<{
|
|
156
|
+
getByteSource(path: string, flags?: VersionedReadFlags): Promise<{
|
|
156
157
|
src: FileByteSource;
|
|
157
158
|
version: number;
|
|
158
159
|
}>;
|