core-3nweb-client-lib 0.27.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.
- package/build/api-defs/files.d.ts +4 -7
- 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 +1 -1
- 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 +21 -23
- package/build/core/sign-in.d.ts +1 -2
- package/build/core/sign-in.js +4 -13
- 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 +9 -1
- package/build/core/storage/synced/obj-files.js +41 -33
- package/build/core/storage/synced/obj-status.d.ts +18 -7
- package/build/core/storage/synced/obj-status.js +148 -83
- package/build/core/storage/synced/storage.d.ts +7 -2
- package/build/core/storage/synced/storage.js +50 -10
- package/build/core/storage/synced/upsyncer.d.ts +4 -4
- package/build/core/storage/synced/upsyncer.js +12 -6
- 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 -1
- package/build/lib-client/3nstorage/service.js +31 -15
- 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.js +2 -2
- package/build/lib-client/3nstorage/xsp-fs/folder-node.d.ts +11 -5
- package/build/lib-client/3nstorage/xsp-fs/folder-node.js +232 -68
- package/build/lib-client/3nstorage/xsp-fs/fs.js +15 -19
- package/build/lib-client/3nstorage/xsp-fs/node-in-fs.d.ts +4 -9
- package/build/lib-client/3nstorage/xsp-fs/node-in-fs.js +16 -17
- package/build/lib-client/3nstorage/xsp-fs/xsp-payload-v1.js +1 -1
- package/build/lib-client/cryptor/cryptor-wasm.js +1 -1
- package/build/lib-client/cryptor/cryptor.wasm +0 -0
- package/build/lib-client/local-files/device-fs.js +11 -11
- 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/utils.js +1 -1
- package/build/lib-common/service-api/3nstorage/owner.d.ts +8 -5
- package/build/lib-common/service-api/3nstorage/owner.js +2 -1
- package/package.json +3 -2
- package/build/core/id-manager.d.ts +0 -46
|
@@ -85,20 +85,14 @@ async function readRootKeyDerivParamsFromCache(folder) {
|
|
|
85
85
|
throw (0, error_1.errWithCause)(err, `Can't read and parse content of obj status file ${KD_PARAMS_FILE_NAME} in folder ${folder}`);
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
* @param folder
|
|
92
|
-
* @param getFromServer
|
|
93
|
-
*/
|
|
94
|
-
async function getRootKeyDerivParams(folder, getFromServer) {
|
|
95
|
-
let params = await readRootKeyDerivParamsFromCache(folder);
|
|
96
|
-
if (!params) {
|
|
97
|
-
params = await getFromServer();
|
|
98
|
-
await fs.writeFile((0, path_1.join)(folder, KD_PARAMS_FILE_NAME), JSON.stringify(params), { encoding: 'utf8' });
|
|
99
|
-
}
|
|
88
|
+
async function getAndCacheRootKeyDerivParamsFromServer(folder, getFromServer) {
|
|
89
|
+
const params = await getFromServer();
|
|
90
|
+
await saveRootKeyDerivParamsToDisk(folder, params);
|
|
100
91
|
return params;
|
|
101
92
|
}
|
|
93
|
+
async function saveRootKeyDerivParamsToDisk(folder, params) {
|
|
94
|
+
await fs.writeFile((0, path_1.join)(folder, KD_PARAMS_FILE_NAME), JSON.stringify(params), { encoding: 'utf8' });
|
|
95
|
+
}
|
|
102
96
|
class StorageAndFS {
|
|
103
97
|
constructor(storage) {
|
|
104
98
|
this.storage = storage;
|
|
@@ -125,32 +119,15 @@ class StorageAndFS {
|
|
|
125
119
|
}
|
|
126
120
|
}
|
|
127
121
|
}
|
|
128
|
-
static async
|
|
129
|
-
var _a
|
|
122
|
+
static async makeNew(storage, key) {
|
|
123
|
+
var _a;
|
|
130
124
|
const s = new StorageAndFS(storage);
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
return s;
|
|
137
|
-
}
|
|
138
|
-
catch (err) {
|
|
139
|
-
if (err.objNotFound) {
|
|
140
|
-
s.rootFS = await fs_1.XspFS.makeNewRoot(s.storage, key);
|
|
141
|
-
await (0, system_folders_1.initSysFolders)(s.rootFS);
|
|
142
|
-
if ((_b = s.rootFS.v) === null || _b === void 0 ? void 0 : _b.sync) {
|
|
143
|
-
s.syncedAppDataRoots = await apps_data_1.AppDataFolders.make(s.rootFS);
|
|
144
|
-
}
|
|
145
|
-
return s;
|
|
146
|
-
}
|
|
147
|
-
else if (err.failedCipherVerification) {
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
else {
|
|
151
|
-
throw err;
|
|
152
|
-
}
|
|
125
|
+
s.rootFS = await fs_1.XspFS.makeNewRoot(s.storage, key);
|
|
126
|
+
await (0, system_folders_1.initSysFolders)(s.rootFS);
|
|
127
|
+
if ((_a = s.rootFS.v) === null || _a === void 0 ? void 0 : _a.sync) {
|
|
128
|
+
s.syncedAppDataRoots = await apps_data_1.AppDataFolders.make(s.rootFS);
|
|
153
129
|
}
|
|
130
|
+
return s;
|
|
154
131
|
}
|
|
155
132
|
/**
|
|
156
133
|
* This creates app data folder.
|
|
@@ -278,30 +255,32 @@ class Storages {
|
|
|
278
255
|
if (!this.local) {
|
|
279
256
|
return;
|
|
280
257
|
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
258
|
+
const { syncedStore, setupRemoteAndStartObjProcs } = await storage_1.SyncedStore.makeAndStartWithoutRemote((0, path_1.join)(storageDir, SYNCED_STORAGE_DIR), user, this.storageGetterForSyncedStorage, this.cryptor, () => resolver(user), makeNet(), logError);
|
|
259
|
+
this.synced = await StorageAndFS.existing(syncedStore, key);
|
|
260
|
+
key.fill(0);
|
|
261
|
+
if (!this.synced) {
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
return setupRemoteAndStartObjProcs;
|
|
265
|
+
}
|
|
266
|
+
async initFromRemote(user, getSigner, generateKey, makeNet, resolver, logError) {
|
|
267
|
+
const storageDir = this.storageDirForUser(user);
|
|
268
|
+
const { startObjProcs, syncedStore } = await storage_1.SyncedStore.makeAndStart((0, path_1.join)(storageDir, SYNCED_STORAGE_DIR), user, getSigner, this.storageGetterForSyncedStorage, this.cryptor, () => resolver(user), makeNet(), logError);
|
|
269
|
+
const params = await getAndCacheRootKeyDerivParamsFromServer(storageDir, syncedStore.getRootKeyDerivParamsFromServer);
|
|
270
|
+
const key = await generateKey(params);
|
|
271
|
+
this.synced = await StorageAndFS.existing(syncedStore, key);
|
|
272
|
+
this.local = await StorageAndFS.makeNew(await storage_2.LocalStorage.makeAndStart((0, path_1.join)(storageDir, LOCAL_STORAGE_DIR), this.storageGetterForLocalStorage, this.cryptor, logError), key);
|
|
273
|
+
key.fill(0);
|
|
274
|
+
startObjProcs();
|
|
275
|
+
return (!!this.synced && !!this.local);
|
|
294
276
|
}
|
|
295
|
-
async
|
|
277
|
+
async initFreshForNewUser(user, getSigner, params, key, makeNet, resolver, logError) {
|
|
296
278
|
const storageDir = this.storageDirForUser(user);
|
|
297
279
|
const { startObjProcs, syncedStore } = await storage_1.SyncedStore.makeAndStart((0, path_1.join)(storageDir, SYNCED_STORAGE_DIR), user, getSigner, this.storageGetterForSyncedStorage, this.cryptor, () => resolver(user), makeNet(), logError);
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
const key = ((typeof keyOrGen === 'function') ?
|
|
301
|
-
await keyOrGen(params) : keyOrGen);
|
|
302
|
-
this.synced = await StorageAndFS.newOrExisting(syncedStore, key);
|
|
303
|
-
this.local = await StorageAndFS.newOrExisting(await storage_2.LocalStorage.makeAndStart((0, path_1.join)(storageDir, LOCAL_STORAGE_DIR), this.storageGetterForLocalStorage, this.cryptor, logError), key);
|
|
280
|
+
this.synced = await StorageAndFS.makeNew(syncedStore, key);
|
|
281
|
+
this.local = await StorageAndFS.makeNew(await storage_2.LocalStorage.makeAndStart((0, path_1.join)(storageDir, LOCAL_STORAGE_DIR), this.storageGetterForLocalStorage, this.cryptor, logError), key);
|
|
304
282
|
key.fill(0);
|
|
283
|
+
await saveRootKeyDerivParamsToDisk(storageDir, params);
|
|
305
284
|
startObjProcs();
|
|
306
285
|
return (!!this.synced && !!this.local);
|
|
307
286
|
}
|
|
@@ -523,7 +502,7 @@ async function applyPolicyToFSCollection(c, policy, path) {
|
|
|
523
502
|
}
|
|
524
503
|
const nameAndItem = await (0, async_iter_1.asyncFind)(await c.entries(), async (v) => path.startsWith(v[0]));
|
|
525
504
|
if (!nameAndItem) {
|
|
526
|
-
throw (0, file_1.makeFileException)(
|
|
505
|
+
throw (0, file_1.makeFileException)('notFound', path);
|
|
527
506
|
}
|
|
528
507
|
const [name, item] = nameAndItem;
|
|
529
508
|
path = path.substring(name.length);
|
|
@@ -9,7 +9,7 @@ export declare class LocalStorage implements Storage {
|
|
|
9
9
|
private readonly files;
|
|
10
10
|
private readonly getStorages;
|
|
11
11
|
readonly cryptor: AsyncSBoxCryptor;
|
|
12
|
-
|
|
12
|
+
readonly logError: LogError;
|
|
13
13
|
readonly type = "local";
|
|
14
14
|
readonly versioned = true;
|
|
15
15
|
readonly nodes: NodesContainer;
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { SynchronizerOnObjId, SyncedObj } from './obj-files';
|
|
2
|
-
import { StorageOwner as RemoteStorage } from '../../../lib-client/3nstorage/service';
|
|
3
2
|
export declare class GC {
|
|
4
3
|
private readonly sync;
|
|
5
4
|
private readonly rmObjFromCache;
|
|
6
5
|
private readonly rmObjFolder;
|
|
7
|
-
private readonly remote;
|
|
8
6
|
private isStopped;
|
|
9
7
|
/**
|
|
10
8
|
* All gc steps are done in this process.
|
|
@@ -20,11 +18,10 @@ export declare class GC {
|
|
|
20
18
|
* with wip set.
|
|
21
19
|
*/
|
|
22
20
|
private scheduled;
|
|
23
|
-
constructor(sync: SynchronizerOnObjId, rmObjFromCache: (obj: SyncedObj) => void, rmObjFolder: (objId: string) => Promise<void
|
|
21
|
+
constructor(sync: SynchronizerOnObjId, rmObjFromCache: (obj: SyncedObj) => void, rmObjFolder: (objId: string) => Promise<void>);
|
|
24
22
|
scheduleCollection: (obj: SyncedObj) => void;
|
|
25
23
|
stop(): Promise<void>;
|
|
26
24
|
private objCollecting;
|
|
27
25
|
private collectIn;
|
|
28
|
-
private upsyncObjRemovalWhenNeeded;
|
|
29
26
|
private checkAndRemoveWholeObjFolder;
|
|
30
27
|
}
|
|
@@ -24,11 +24,10 @@ const path_1 = require("path");
|
|
|
24
24
|
const utils_1 = require("../common/utils");
|
|
25
25
|
const upload_header_file_1 = require("./upload-header-file");
|
|
26
26
|
class GC {
|
|
27
|
-
constructor(sync, rmObjFromCache, rmObjFolder
|
|
27
|
+
constructor(sync, rmObjFromCache, rmObjFolder) {
|
|
28
28
|
this.sync = sync;
|
|
29
29
|
this.rmObjFromCache = rmObjFromCache;
|
|
30
30
|
this.rmObjFolder = rmObjFolder;
|
|
31
|
-
this.remote = remote;
|
|
32
31
|
this.isStopped = false;
|
|
33
32
|
/**
|
|
34
33
|
* All gc steps are done in this process.
|
|
@@ -71,27 +70,11 @@ class GC {
|
|
|
71
70
|
this.isStopped = true;
|
|
72
71
|
}
|
|
73
72
|
async collectIn(obj) {
|
|
74
|
-
if (obj.statusObj().isArchived()) {
|
|
75
|
-
await this.upsyncObjRemovalWhenNeeded(obj);
|
|
76
|
-
}
|
|
77
73
|
const nonGarbage = obj.statusObj().getNonGarbageVersions();
|
|
78
74
|
if (!(await this.checkAndRemoveWholeObjFolder(obj, nonGarbage))) {
|
|
79
75
|
await removeGarbageFiles(obj, nonGarbage);
|
|
80
76
|
}
|
|
81
77
|
}
|
|
82
|
-
async upsyncObjRemovalWhenNeeded(obj) {
|
|
83
|
-
if (!needsUpsyncOfRemoval(obj)) {
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
try {
|
|
87
|
-
await this.remote.deleteObj(obj.objId);
|
|
88
|
-
}
|
|
89
|
-
catch (exc) {
|
|
90
|
-
// XXX will need to schedule other attempt to delete on remote
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
await obj.statusObj().recordSyncOfObjRemoval();
|
|
94
|
-
}
|
|
95
78
|
async checkAndRemoveWholeObjFolder(obj, { local, remote }) {
|
|
96
79
|
if (obj.objId
|
|
97
80
|
&& obj.statusObj().isArchived()
|
|
@@ -13,6 +13,12 @@ import { StorageOwner as RemoteStorage } from '../../../lib-client/3nstorage/ser
|
|
|
13
13
|
import { UploadHeaderChange } from '../../../lib-client/3nstorage/xsp-fs/common';
|
|
14
14
|
export declare const UNSYNCED_FILE_NAME_EXT = "unsynced";
|
|
15
15
|
export declare const REMOTE_FILE_NAME_EXT = "v";
|
|
16
|
+
/**
|
|
17
|
+
* File system has nodes. Each node may have data in one or many objects of
|
|
18
|
+
* storage. SyncedObj allows to work with files of storage object, even when
|
|
19
|
+
* file system node no longer exists. ObjFiles is a holder and factory of
|
|
20
|
+
* SyncedObj's.
|
|
21
|
+
*/
|
|
16
22
|
export declare class ObjFiles {
|
|
17
23
|
private readonly folders;
|
|
18
24
|
private readonly logError;
|
|
@@ -22,6 +28,7 @@ export declare class ObjFiles {
|
|
|
22
28
|
private readonly gc;
|
|
23
29
|
private constructor();
|
|
24
30
|
static makeFor(path: string, remote: RemoteStorage, logError: LogError): Promise<ObjFiles>;
|
|
31
|
+
private canMoveObjToDeeperCache;
|
|
25
32
|
findObj(objId: ObjId): Promise<SyncedObj | undefined>;
|
|
26
33
|
getObjInCache(objId: ObjId): SyncedObj | undefined;
|
|
27
34
|
private makeObj;
|
|
@@ -31,7 +38,7 @@ export declare class ObjFiles {
|
|
|
31
38
|
fileWrite$: Observable<FileWrite[]>;
|
|
32
39
|
newObj: SyncedObj;
|
|
33
40
|
}>;
|
|
34
|
-
|
|
41
|
+
findObjsToRemoveOnRemote(): Observable<ObjId>;
|
|
35
42
|
scheduleGC(obj: SyncedObj): void;
|
|
36
43
|
}
|
|
37
44
|
export declare type SynchronizerOnObjId = <T>(objId: ObjId, action: () => Promise<T>) => Promise<T>;
|
|
@@ -81,4 +88,5 @@ export declare class SyncedObj {
|
|
|
81
88
|
}>;
|
|
82
89
|
syncStatus(): SyncedObjStatus;
|
|
83
90
|
statusObj(): ObjStatus;
|
|
91
|
+
recordRemovalUploadAndGC(): Promise<void>;
|
|
84
92
|
}
|
|
@@ -19,7 +19,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
19
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");
|
|
@@ -35,6 +34,12 @@ const upload_header_file_1 = require("./upload-header-file");
|
|
|
35
34
|
const utils_1 = require("../common/utils");
|
|
36
35
|
exports.UNSYNCED_FILE_NAME_EXT = 'unsynced';
|
|
37
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
|
+
*/
|
|
38
43
|
class ObjFiles {
|
|
39
44
|
constructor(folders, remote, logError) {
|
|
40
45
|
this.folders = folders;
|
|
@@ -46,31 +51,32 @@ class ObjFiles {
|
|
|
46
51
|
if (this.objs.get(obj.objId) === obj) {
|
|
47
52
|
this.objs.delete(obj.objId);
|
|
48
53
|
}
|
|
49
|
-
}, objId => this.folders.removeFolderOf(objId)
|
|
54
|
+
}, objId => this.folders.removeFolderOf(objId));
|
|
50
55
|
Object.freeze(this);
|
|
51
56
|
}
|
|
52
57
|
static async makeFor(path, remote, logError) {
|
|
53
|
-
const canMove =
|
|
54
|
-
if (objFiles.objs.has(objId)) {
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
57
|
-
const lst = await fs.readdir(objFolderPath);
|
|
58
|
-
for (const fName of lst) {
|
|
59
|
-
if (fName.endsWith(exports.UNSYNCED_FILE_NAME_EXT)) {
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
try {
|
|
64
|
-
return (await obj_status_1.ObjStatus.fileShowsObjNotInSyncedState(objFolderPath, objId));
|
|
65
|
-
}
|
|
66
|
-
catch (exc) {
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
69
|
-
};
|
|
58
|
+
const canMove = (objId, objFolderPath) => objFiles.canMoveObjToDeeperCache(objId, objFolderPath);
|
|
70
59
|
const folders = await obj_folders_1.ObjFolders.makeWithGenerations(path, canMove, logError);
|
|
71
60
|
const objFiles = new ObjFiles(folders, remote, logError);
|
|
72
61
|
return objFiles;
|
|
73
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)) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
return (await obj_status_1.ObjStatus.fileShowsObjNotInSyncedState(objFolderPath, objId));
|
|
75
|
+
}
|
|
76
|
+
catch (exc) {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
74
80
|
async findObj(objId) {
|
|
75
81
|
let obj = this.objs.get(objId);
|
|
76
82
|
if (obj) {
|
|
@@ -131,25 +137,23 @@ class ObjFiles {
|
|
|
131
137
|
.pipe((0, utils_for_observables_1.flatTap)(undefined, err => this.removeFailedNewObj(newObj)));
|
|
132
138
|
return { fileWrite$, newObj };
|
|
133
139
|
}
|
|
134
|
-
|
|
140
|
+
findObjsToRemoveOnRemote() {
|
|
135
141
|
return (0, rxjs_1.from)([undefined])
|
|
136
142
|
.pipe(
|
|
137
143
|
// listing recent folders, exactly once
|
|
138
144
|
(0, operators_1.mergeMap)(() => this.folders.listRecent()),
|
|
139
145
|
// flatten array and space it in time, to process folders one by one
|
|
140
|
-
(0, operators_1.mergeMap)(objsAndPaths => objsAndPaths), (0, operators_1.
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
const needsRm = await obj_status_1.ObjStatus.fileShowsObjNeedsRemovalOnRemote(path, objId);
|
|
154
|
+
return (needsRm ? objId : undefined);
|
|
148
155
|
}
|
|
149
|
-
|
|
150
|
-
.catch(notFoundOrReThrow).catch(this.logError);
|
|
151
|
-
return (notSynced ? objId : undefined);
|
|
152
|
-
})), (0, operators_1.filter)(objId => (objId !== undefined)));
|
|
156
|
+
}, 1), (0, operators_1.filter)(objId => (objId !== undefined)));
|
|
153
157
|
}
|
|
154
158
|
scheduleGC(obj) {
|
|
155
159
|
this.gc.scheduleCollection(obj);
|
|
@@ -336,7 +340,7 @@ class SyncedObj {
|
|
|
336
340
|
else {
|
|
337
341
|
await fs.rename(this.localVerPath(localVersion), remotePath);
|
|
338
342
|
}
|
|
339
|
-
await this.status.
|
|
343
|
+
await this.status.recordUploadCompletion(localVersion, uploadVersion);
|
|
340
344
|
this.scheduleSelfGC();
|
|
341
345
|
}
|
|
342
346
|
dropCachedLocalObjVersionsLessOrEqual(version) {
|
|
@@ -387,6 +391,10 @@ class SyncedObj {
|
|
|
387
391
|
statusObj() {
|
|
388
392
|
return this.status;
|
|
389
393
|
}
|
|
394
|
+
async recordRemovalUploadAndGC() {
|
|
395
|
+
await this.status.recordRemoteRemovalCompletion();
|
|
396
|
+
this.scheduleSelfGC();
|
|
397
|
+
}
|
|
390
398
|
}
|
|
391
399
|
exports.SyncedObj = SyncedObj;
|
|
392
400
|
Object.freeze(SyncedObj.prototype);
|
|
@@ -18,11 +18,11 @@ export interface ObjStatusInfo {
|
|
|
18
18
|
local?: LocalVersions;
|
|
19
19
|
synced?: SyncMarker;
|
|
20
20
|
remote: VersionsOnServer;
|
|
21
|
+
upload?: UploadInfo;
|
|
21
22
|
}
|
|
22
23
|
export interface LocalVersions extends VersionsInfo {
|
|
23
24
|
isArchived?: boolean;
|
|
24
25
|
archived?: undefined;
|
|
25
|
-
upload?: UploadInfo;
|
|
26
26
|
}
|
|
27
27
|
export interface SyncMarker {
|
|
28
28
|
version?: number;
|
|
@@ -32,12 +32,19 @@ export interface SyncMarker {
|
|
|
32
32
|
export interface VersionsOnServer extends VersionsInfo {
|
|
33
33
|
isArchived?: boolean;
|
|
34
34
|
}
|
|
35
|
-
export
|
|
35
|
+
export declare type UploadInfo = NewVersionUpload | RemovalUpload;
|
|
36
|
+
export interface NewVersionUpload {
|
|
37
|
+
type: 'new-version';
|
|
36
38
|
localVersion: number;
|
|
37
39
|
uploadVersion: number;
|
|
38
40
|
baseVersion?: number;
|
|
39
41
|
needUpload?: WholeVerOrderedUpload | DiffVerOrderedUpload;
|
|
40
42
|
}
|
|
43
|
+
export interface RemovalUpload {
|
|
44
|
+
type: 'removal';
|
|
45
|
+
isPostponed: boolean;
|
|
46
|
+
localVersion?: number;
|
|
47
|
+
}
|
|
41
48
|
export interface WholeVerOrderedUpload {
|
|
42
49
|
type: 'ordered-whole';
|
|
43
50
|
createObj?: boolean;
|
|
@@ -74,20 +81,24 @@ export declare class ObjStatus implements SyncedObjStatus, UploadStatusRecorder
|
|
|
74
81
|
static makeNew(objFolder: string, objId: ObjId, logError: LogError): Promise<ObjStatus>;
|
|
75
82
|
static makeForDownloadedVersion(objFolder: string, objId: ObjId, version: number, currentRemote: number, logError: LogError): Promise<ObjStatus>;
|
|
76
83
|
static fileShowsObjNotInSyncedState(objFolder: string, objId: ObjId): Promise<boolean>;
|
|
84
|
+
static fileShowsObjNeedsRemovalOnRemote(objFolder: string, objId: ObjId): Promise<boolean>;
|
|
85
|
+
needsRemovalOnRemote(): boolean;
|
|
86
|
+
clearPostponeFlagInRemovalOnRemote(): Promise<boolean>;
|
|
77
87
|
private updateStateIndicator;
|
|
78
88
|
isArchived(): boolean;
|
|
79
89
|
getCurrentLocalOrSynced(): number;
|
|
80
90
|
getNonGarbageVersions(): NonGarbage;
|
|
81
91
|
removeCurrentVersion(): Promise<void>;
|
|
82
92
|
private triggerSaveProc;
|
|
83
|
-
recordUploadStart(info:
|
|
84
|
-
recordUploadInterimState(info:
|
|
85
|
-
recordUploadCancellation(info:
|
|
93
|
+
recordUploadStart(info: NewVersionUpload): Promise<void>;
|
|
94
|
+
recordUploadInterimState(info: NewVersionUpload): Promise<void>;
|
|
95
|
+
recordUploadCancellation(info: NewVersionUpload): Promise<void>;
|
|
96
|
+
recordUploadCompletion(localVersion: number, uploadVersion: number): Promise<void>;
|
|
86
97
|
recordArchVersionRemoval(version: number): Promise<void>;
|
|
87
98
|
recordVersionArchival(version: number): Promise<void>;
|
|
88
99
|
recordRemoteRemoval(): Promise<void>;
|
|
100
|
+
recordRemoteRemovalCompletion(): Promise<void>;
|
|
89
101
|
recordRemoteChange(version: number): Promise<void>;
|
|
90
|
-
recordSyncOfObjRemoval(): Promise<void>;
|
|
91
102
|
recordStatusFromServer({ archived, current }: RemoteObjStatus): Promise<void>;
|
|
92
103
|
/**
|
|
93
104
|
* When given object version is a diff on some base, this method returns
|
|
@@ -102,7 +113,6 @@ export declare class ObjStatus implements SyncedObjStatus, UploadStatusRecorder
|
|
|
102
113
|
localBases?: number[];
|
|
103
114
|
syncedBase?: number;
|
|
104
115
|
} | undefined;
|
|
105
|
-
markLocalVersionSynced(localVersion: number, uploadVersion: number): Promise<void>;
|
|
106
116
|
setLocalCurrentVersion(version: number, baseVer: number | undefined): Promise<void>;
|
|
107
117
|
listVersions(): {
|
|
108
118
|
current?: number;
|
|
@@ -113,6 +123,7 @@ export declare class ObjStatus implements SyncedObjStatus, UploadStatusRecorder
|
|
|
113
123
|
latestSyncedVersion(): number | undefined;
|
|
114
124
|
syncStatus(): SyncStatus;
|
|
115
125
|
neverUploaded(): boolean;
|
|
126
|
+
versionBeforeUnsyncedRemoval(): number | undefined;
|
|
116
127
|
adoptRemoteVersion(version?: number, dropLocalVer?: boolean): Promise<void>;
|
|
117
128
|
}
|
|
118
129
|
export declare function readAndCheckStatus(objFolder: string, objId: ObjId): Promise<ObjStatusInfo>;
|