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.
Files changed (81) hide show
  1. package/build/api-defs/files.d.ts +56 -26
  2. package/build/core/asmail/config/index.d.ts +2 -2
  3. package/build/core/asmail/config/index.js +2 -2
  4. package/build/core/asmail/config/invitations-anon.d.ts +10 -24
  5. package/build/core/asmail/config/invitations-anon.js +43 -31
  6. package/build/core/asmail/config/published-intro-key.d.ts +11 -22
  7. package/build/core/asmail/config/published-intro-key.js +47 -38
  8. package/build/core/asmail/inbox/attachments/fs.d.ts +2 -1
  9. package/build/core/asmail/inbox/attachments/fs.js +4 -3
  10. package/build/core/asmail/inbox/index.js +2 -2
  11. package/build/core/asmail/index.d.ts +1 -1
  12. package/build/core/asmail/index.js +2 -2
  13. package/build/core/asmail/keyring/correspondent-keys.d.ts +2 -2
  14. package/build/core/asmail/keyring/correspondent-keys.js +1 -1
  15. package/build/core/asmail/keyring/index.d.ts +9 -29
  16. package/build/core/asmail/keyring/index.js +82 -69
  17. package/build/core/id-manager/index.d.ts +43 -0
  18. package/build/core/{id-manager.js → id-manager/index.js} +33 -114
  19. package/build/core/id-manager/key-storage.d.ts +21 -0
  20. package/build/core/id-manager/key-storage.js +96 -0
  21. package/build/core/index.js +22 -25
  22. package/build/core/sign-in.d.ts +1 -2
  23. package/build/core/sign-in.js +5 -14
  24. package/build/core/sign-up.d.ts +2 -0
  25. package/build/core/sign-up.js +2 -1
  26. package/build/core/storage/index.d.ts +4 -2
  27. package/build/core/storage/index.js +36 -57
  28. package/build/core/storage/local/storage.d.ts +1 -1
  29. package/build/core/storage/synced/obj-files-gc.d.ts +1 -4
  30. package/build/core/storage/synced/obj-files-gc.js +1 -18
  31. package/build/core/storage/synced/obj-files.d.ts +11 -1
  32. package/build/core/storage/synced/obj-files.js +59 -34
  33. package/build/core/storage/synced/obj-status.d.ts +19 -7
  34. package/build/core/storage/synced/obj-status.js +158 -83
  35. package/build/core/storage/synced/storage.d.ts +7 -2
  36. package/build/core/storage/synced/storage.js +38 -15
  37. package/build/core/storage/synced/upsyncer.d.ts +4 -4
  38. package/build/core/storage/synced/upsyncer.js +14 -9
  39. package/build/ipc-via-protobuf/file.d.ts +7 -0
  40. package/build/ipc-via-protobuf/file.js +60 -27
  41. package/build/ipc-via-protobuf/fs.js +55 -38
  42. package/build/lib-client/3nstorage/exceptions.d.ts +13 -1
  43. package/build/lib-client/3nstorage/exceptions.js +9 -3
  44. package/build/lib-client/3nstorage/service.d.ts +6 -2
  45. package/build/lib-client/3nstorage/service.js +33 -17
  46. package/build/lib-client/3nstorage/util/file-based-json.js +2 -1
  47. package/build/lib-client/3nstorage/util/for-arrays.d.ts +1 -0
  48. package/build/lib-client/3nstorage/util/for-arrays.js +32 -0
  49. package/build/lib-client/3nstorage/xsp-fs/common.d.ts +5 -4
  50. package/build/lib-client/3nstorage/xsp-fs/common.js +1 -0
  51. package/build/lib-client/3nstorage/xsp-fs/file-node.d.ts +5 -10
  52. package/build/lib-client/3nstorage/xsp-fs/file-node.js +43 -45
  53. package/build/lib-client/3nstorage/xsp-fs/file.d.ts +7 -6
  54. package/build/lib-client/3nstorage/xsp-fs/file.js +14 -20
  55. package/build/lib-client/3nstorage/xsp-fs/folder-node.d.ts +16 -5
  56. package/build/lib-client/3nstorage/xsp-fs/folder-node.js +238 -68
  57. package/build/lib-client/3nstorage/xsp-fs/fs.d.ts +18 -17
  58. package/build/lib-client/3nstorage/xsp-fs/fs.js +32 -37
  59. package/build/lib-client/3nstorage/xsp-fs/node-in-fs.d.ts +15 -11
  60. package/build/lib-client/3nstorage/xsp-fs/node-in-fs.js +72 -22
  61. package/build/lib-client/3nstorage/xsp-fs/xsp-payload-v1.js +1 -1
  62. package/build/lib-client/local-files/device-fs.js +11 -11
  63. package/build/lib-client/objs-on-disk/obj-on-disk.d.ts +5 -2
  64. package/build/lib-client/objs-on-disk/obj-on-disk.js +16 -1
  65. package/build/lib-client/user-with-mid-session.d.ts +2 -1
  66. package/build/lib-client/user-with-mid-session.js +7 -1
  67. package/build/lib-common/async-fs-node.js +8 -8
  68. package/build/lib-common/exceptions/file.d.ts +4 -2
  69. package/build/lib-common/exceptions/file.js +24 -58
  70. package/build/lib-common/ipc/generic-ipc.js +5 -4
  71. package/build/lib-common/objs-on-disk/file-layout.js +1 -1
  72. package/build/lib-common/objs-on-disk/utils.js +1 -1
  73. package/build/lib-common/service-api/3nstorage/owner.d.ts +8 -9
  74. package/build/lib-common/service-api/3nstorage/owner.js +2 -1
  75. package/build/protos/asmail.proto.js +5943 -4348
  76. package/build/protos/file.proto.js +874 -0
  77. package/build/protos/fs.proto.js +7014 -5419
  78. package/package.json +3 -2
  79. package/protos/file.proto +23 -7
  80. package/protos/fs.proto +27 -13
  81. package/build/core/id-manager.d.ts +0 -46
@@ -42,17 +42,23 @@ class Core {
42
42
  this.closingProc = undefined;
43
43
  this.initForNewUser = async (u) => {
44
44
  // 1) init of id manager without setting fs
45
- const idManager = await id_manager_1.IdManager.initInOneStepWithoutStore(u.address, u.midSKey.default, this.makeResolver('mailerid'), () => this.makeNet(), this.logger.logError, this.logger.logWarning);
46
- if (!idManager) {
45
+ const stepTwo = await id_manager_1.IdManager.initWithoutStore(u.address, this.makeResolver('mailerid'), () => this.makeNet(), this.logger.logError, this.logger.logWarning);
46
+ if (!stepTwo) {
47
+ throw new Error(`MailerId server doesn't recognize identity ${u.address}`);
48
+ }
49
+ // 2) complete id manager login, without use of fs
50
+ const idManagerInit = await stepTwo(u.midSKey.default);
51
+ if (!idManagerInit) {
47
52
  throw new Error(`Failed to provision MailerId identity`);
48
53
  }
49
- // 2) setup storage
50
- const storesUp = await this.storages.initFromRemote(u.address, idManager.getSigner, u.storeSKey, this.makeNet, this.makeResolver('3nstorage'), this.logger.logError);
54
+ const { idManager, setupManagerStorage } = idManagerInit;
55
+ // 3) initialize all storages
56
+ const storesUp = await this.storages.initFreshForNewUser(u.address, idManager.getSigner, u.storeParams, u.storeSKey, this.makeNet, this.makeResolver('3nstorage'), this.logger.logError);
51
57
  if (!storesUp) {
52
58
  throw new Error(`Stores failed to initialize`);
53
59
  }
54
60
  // 3) give id manager fs, in which it will record labeled key(s)
55
- await idManager.setStorages(await this.storages.makeLocalFSForApp(MAILERID_APP_NAME), await this.storages.makeSyncedFSForApp(MAILERID_APP_NAME), [u.midSKey.labeled]);
61
+ await setupManagerStorage(await this.storages.makeSyncedFSForApp(MAILERID_APP_NAME), [u.midSKey.labeled]);
56
62
  return idManager;
57
63
  };
58
64
  this.initForExistingUserWithoutCache = async (address) => {
@@ -63,17 +69,18 @@ class Core {
63
69
  }
64
70
  return async (midLoginKey, storageKey) => {
65
71
  // 2) complete id manager login, without use of fs
66
- const idManager = await stepTwo(midLoginKey);
67
- if (!idManager) {
72
+ const idManagerInit = await stepTwo(midLoginKey);
73
+ if (!idManagerInit) {
68
74
  return;
69
75
  }
76
+ const { idManager, setupManagerStorage } = idManagerInit;
70
77
  // 3) initialize all storages
71
78
  const storeDone = await this.storages.initFromRemote(address, idManager.getSigner, storageKey, this.makeNet, this.makeResolver('3nstorage'), this.logger.logError);
72
79
  if (!storeDone) {
73
80
  return;
74
81
  }
75
82
  // 4) complete initialization of id manager
76
- await idManager.setStorages(await this.storages.makeLocalFSForApp(MAILERID_APP_NAME), await this.storages.makeSyncedFSForApp(MAILERID_APP_NAME));
83
+ await setupManagerStorage(await this.storages.makeSyncedFSForApp(MAILERID_APP_NAME));
77
84
  return idManager;
78
85
  };
79
86
  };
@@ -82,21 +89,12 @@ class Core {
82
89
  if (!completeStorageInit) {
83
90
  return;
84
91
  }
85
- const idManager = await id_manager_1.IdManager.initFromLocalStore(address, await this.storages.makeLocalFSForApp(MAILERID_APP_NAME), this.makeResolver('mailerid'), () => this.makeNet(), this.logger.logError, this.logger.logWarning);
86
- if (idManager) {
87
- const res = await completeStorageInit(idManager.getSigner);
88
- await idManager.setStorages(undefined, await this.storages.makeSyncedFSForApp(MAILERID_APP_NAME));
89
- return (res ? idManager : undefined);
92
+ const idManager = await id_manager_1.IdManager.initFromCachedStore(address, await this.storages.makeSyncedFSForApp(MAILERID_APP_NAME), this.makeResolver('mailerid'), () => this.makeNet(), this.logger.logError, this.logger.logWarning);
93
+ if (!idManager) {
94
+ return;
90
95
  }
91
- return async (midLoginKey) => {
92
- const idManager = await id_manager_1.IdManager.initInOneStepWithoutStore(address, midLoginKey, this.makeResolver('mailerid'), () => this.makeNet(), this.logger.logError, this.logger.logWarning);
93
- if (!idManager) {
94
- return;
95
- }
96
- const res = await completeStorageInit(idManager.getSigner);
97
- await idManager.setStorages(await this.storages.makeLocalFSForApp(MAILERID_APP_NAME), await this.storages.makeSyncedFSForApp(MAILERID_APP_NAME));
98
- return (res ? idManager : undefined);
99
- };
96
+ completeStorageInit(idManager.getSigner);
97
+ return idManager;
100
98
  };
101
99
  this.closeBroadcast = new rxjs_1.Subject();
102
100
  this.close$ = this.closeBroadcast.asObservable();
@@ -112,7 +110,7 @@ class Core {
112
110
  return core;
113
111
  }
114
112
  start() {
115
- const signUp = new sign_up_1.SignUp(this.signUpUrl, this.cryptor.cryptor, () => this.makeNet(), this.appDirs.getUsersOnDisk, this.logger.logError);
113
+ const signUp = new sign_up_1.SignUp(this.signUpUrl, this.cryptor.cryptor, this.makeNet.bind(this), this.appDirs.getUsersOnDisk, this.logger.logError);
116
114
  const signIn = new sign_in_1.SignIn(this.cryptor.cryptor, this.initForExistingUserWithoutCache, this.initForExistingUserWithCache, this.appDirs.getUsersOnDisk, this.logger.logError);
117
115
  const capsForStartup = {
118
116
  signUp: signUp.exposedService(),
@@ -227,8 +225,7 @@ function makeStoragePolicy(appDomain, requestedCAPs) {
227
225
  }
228
226
  else if (Array.isArray(capReq.appFS)) {
229
227
  const okDomains = capReq.appFS
230
- .filter(fsInfo => (fsInfo.domain === appDomain) ||
231
- fsInfo.domain.endsWith('.' + appDomain))
228
+ .filter(fsInfo => (fsInfo.domain === appDomain) || fsInfo.domain.endsWith('.' + appDomain))
232
229
  .map(fsInfo => (0, json_utils_1.copy)(fsInfo));
233
230
  policy = {
234
231
  canOpenAppFS: severalDomainsAppFSChecker(okDomains)
@@ -6,8 +6,7 @@ import { LogError } from '../lib-client/logging/log-to-file';
6
6
  export declare type GenerateKey = (derivParams: ScryptGenParams) => Promise<Uint8Array>;
7
7
  export declare type StartInitWithoutCache = (address: string) => Promise<CompleteInitWithoutCache | undefined>;
8
8
  export declare type CompleteInitWithoutCache = (midLoginKey: GenerateKey, storageKey: GenerateKey) => Promise<IdManager | undefined>;
9
- export declare type InitWithCache = (address: string, storageKey: GenerateKey) => Promise<IdManager | undefined | InitTwoWithCache>;
10
- export declare type InitTwoWithCache = (midLoginKey: GenerateKey) => Promise<IdManager | undefined>;
9
+ export declare type InitWithCache = (address: string, storageKey: GenerateKey) => Promise<IdManager | undefined>;
11
10
  declare type SignInService = web3n.startup.SignInService;
12
11
  export declare class SignIn {
13
12
  private cryptor;
@@ -45,7 +45,7 @@ class SignIn {
45
45
  const midKeyProgressCB = makeKeyGenProgressCB(0, 50, progressCB);
46
46
  const midKeyGen = async (params) => (await (0, key_derivation_1.deriveMidKeyPair)(this.cryptor, pass, params, midKeyProgressCB)).skey;
47
47
  const storeKeyProgressCB = makeKeyGenProgressCB(51, 100, progressCB);
48
- const storeKeyGen = (params) => (0, key_derivation_1.deriveStorageSKey)(this.cryptor, pass, params, storeKeyProgressCB);
48
+ const storeKeyGen = params => (0, key_derivation_1.deriveStorageSKey)(this.cryptor, pass, params, storeKeyProgressCB);
49
49
  const idManager = await this.completeInitWithoutCache(midKeyGen, storeKeyGen);
50
50
  if (!idManager) {
51
51
  return false;
@@ -63,23 +63,14 @@ class SignIn {
63
63
  try {
64
64
  const storeKeyProgressCB = makeKeyGenProgressCB(0, 99, progressCB);
65
65
  const storeKeyGen = params => (0, key_derivation_1.deriveStorageSKey)(this.cryptor, pass, params, storeKeyProgressCB);
66
- const res = await this.initWithCache(user, storeKeyGen);
67
- if (!res) {
68
- return false;
69
- }
70
- if (typeof res === 'object') {
71
- this.doneBroadcast.next(res);
66
+ const idManager = await this.initWithCache(user, storeKeyGen);
67
+ if (idManager) {
68
+ this.doneBroadcast.next(idManager);
72
69
  return true;
73
70
  }
74
- progressCB(49);
75
- const midKeyProgressCB = makeKeyGenProgressCB(50, 99, progressCB);
76
- const midKeyGen = async (params) => (await (0, key_derivation_1.deriveMidKeyPair)(this.cryptor, pass, params, midKeyProgressCB)).skey;
77
- const idManager = await res(midKeyGen);
78
- if (!idManager) {
71
+ else {
79
72
  return false;
80
73
  }
81
- this.doneBroadcast.next(idManager);
82
- return true;
83
74
  }
84
75
  catch (err) {
85
76
  throw await this.logAndWrap(err, 'Failing to start in a state with cache');
@@ -1,5 +1,6 @@
1
1
  import { NetClient } from '../lib-client/request-utils';
2
2
  import { JsonKey } from '../lib-common/jwkeys';
3
+ import * as keyDeriv from '../lib-client/key-derivation';
3
4
  import { GetUsersOnDisk } from './app-files';
4
5
  import { Cryptor } from '../lib-client/cryptor/cryptor';
5
6
  import { LogError } from '../lib-client/logging/log-to-file';
@@ -40,5 +41,6 @@ export interface CreatedUser {
40
41
  labeled: JsonKey;
41
42
  };
42
43
  storeSKey: Uint8Array;
44
+ storeParams: keyDeriv.ScryptGenParams;
43
45
  }
44
46
  export {};
@@ -96,7 +96,8 @@ class SignUp {
96
96
  default: this.mid.defaultSKey,
97
97
  labeled: this.mid.labeledSKey
98
98
  },
99
- storeSKey: this.store.skey
99
+ storeSKey: this.store.skey,
100
+ storeParams: this.store.params.kdParams
100
101
  });
101
102
  this.forgetKeys();
102
103
  return true;
@@ -2,6 +2,7 @@ import { GetSigner } from '../id-manager';
2
2
  import { GenerateKey } from '../sign-in';
3
3
  import { StorageGetter } from '../../lib-client/3nstorage/xsp-fs/common';
4
4
  import { ServiceLocator } from '../../lib-client/service-locator';
5
+ import { ScryptGenParams } from '../../lib-client/key-derivation';
5
6
  import { AsyncSBoxCryptor } from 'xsp-files';
6
7
  import { StoragePathForUser } from '../app-files';
7
8
  import { LogError } from '../../lib-client/logging/log-to-file';
@@ -30,8 +31,9 @@ export declare class Storages implements FactoryOfFSs {
30
31
  * This is a storage getter for links and linking in synced storage.
31
32
  */
32
33
  private storageGetterForSyncedStorage;
33
- startInitFromCache(user: string, keyGen: GenerateKey, makeNet: MakeNet, resolver: ServiceLocator, logError: LogError): Promise<((getSigner: GetSigner) => Promise<boolean>) | undefined>;
34
- initFromRemote(user: string, getSigner: GetSigner, keyOrGen: GenerateKey | Uint8Array, makeNet: MakeNet, resolver: ServiceLocator, logError: LogError): Promise<boolean>;
34
+ startInitFromCache(user: string, keyGen: GenerateKey, makeNet: MakeNet, resolver: ServiceLocator, logError: LogError): Promise<((getSigner: GetSigner) => void) | undefined>;
35
+ initFromRemote(user: string, getSigner: GetSigner, generateKey: GenerateKey, makeNet: MakeNet, resolver: ServiceLocator, logError: LogError): Promise<boolean>;
36
+ initFreshForNewUser(user: string, getSigner: GetSigner, params: ScryptGenParams, key: Uint8Array, makeNet: MakeNet, resolver: ServiceLocator, logError: LogError): Promise<boolean>;
35
37
  makeSyncedFSForApp(appFolder: string): Promise<WritableFS>;
36
38
  makeLocalFSForApp(appFolder: string): Promise<WritableFS>;
37
39
  getUserFS(type: StorageType): Promise<FSItem>;
@@ -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
- * This function tries to get key derivation parameters from cache on a disk.
90
- * If not found, it will ask storage server for it with a provided function.
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 newOrExisting(storage, key) {
129
- var _a, _b;
122
+ static async makeNew(storage, key) {
123
+ var _a;
130
124
  const s = new StorageAndFS(storage);
131
- try {
132
- s.rootFS = await fs_1.XspFS.fromExistingRoot(s.storage, key);
133
- if ((_a = s.rootFS.v) === null || _a === void 0 ? void 0 : _a.sync) {
134
- s.syncedAppDataRoots = await apps_data_1.AppDataFolders.make(s.rootFS);
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
- return async (getSigner) => {
282
- if (this.synced) {
283
- return true;
284
- }
285
- 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);
286
- this.synced = await StorageAndFS.existing(syncedStore, key);
287
- key.fill(0);
288
- if (!this.synced) {
289
- return false;
290
- }
291
- startObjProcs();
292
- return true;
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 initFromRemote(user, getSigner, keyOrGen, makeNet, resolver, logError) {
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
- // getting parameters records them locally on a disk
299
- const params = await getRootKeyDerivParams(storageDir, syncedStore.getRootKeyDerivParamsFromServer);
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)(file_1.Code.notFound, path);
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
- private readonly logError;
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>, remote: RemoteStorage);
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, remote) {
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
- findUnsyncedObjs(): Observable<ObjId>;
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,7 @@ export declare class SyncedObj {
81
88
  }>;
82
89
  syncStatus(): SyncedObjStatus;
83
90
  statusObj(): ObjStatus;
91
+ recordRemovalUploadAndGC(): Promise<void>;
92
+ isRemoteVersionOnDisk(version: number): Promise<'complete' | 'partial' | 'none'>;
93
+ downloadRemoteVersion(version: number): Promise<void>;
84
94
  }
@@ -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");
@@ -33,8 +32,15 @@ const obj_status_1 = require("./obj-status");
33
32
  const timed_cache_1 = require("../../../lib-common/timed-cache");
34
33
  const upload_header_file_1 = require("./upload-header-file");
35
34
  const utils_1 = require("../common/utils");
35
+ const exceptions_1 = require("../../../lib-client/3nstorage/exceptions");
36
36
  exports.UNSYNCED_FILE_NAME_EXT = 'unsynced';
37
37
  exports.REMOTE_FILE_NAME_EXT = 'v';
38
+ /**
39
+ * File system has nodes. Each node may have data in one or many objects of
40
+ * storage. SyncedObj allows to work with files of storage object, even when
41
+ * file system node no longer exists. ObjFiles is a holder and factory of
42
+ * SyncedObj's.
43
+ */
38
44
  class ObjFiles {
39
45
  constructor(folders, remote, logError) {
40
46
  this.folders = folders;
@@ -46,31 +52,32 @@ class ObjFiles {
46
52
  if (this.objs.get(obj.objId) === obj) {
47
53
  this.objs.delete(obj.objId);
48
54
  }
49
- }, objId => this.folders.removeFolderOf(objId), remote);
55
+ }, objId => this.folders.removeFolderOf(objId));
50
56
  Object.freeze(this);
51
57
  }
52
58
  static async makeFor(path, remote, logError) {
53
- const canMove = async (objId, objFolderPath) => {
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
- };
59
+ const canMove = (objId, objFolderPath) => objFiles.canMoveObjToDeeperCache(objId, objFolderPath);
70
60
  const folders = await obj_folders_1.ObjFolders.makeWithGenerations(path, canMove, logError);
71
61
  const objFiles = new ObjFiles(folders, remote, logError);
72
62
  return objFiles;
73
63
  }
64
+ async canMoveObjToDeeperCache(objId, objFolderPath) {
65
+ if (this.objs.has(objId)) {
66
+ return false;
67
+ }
68
+ const lst = await fs.readdir(objFolderPath);
69
+ for (const fName of lst) {
70
+ if (fName.endsWith(exports.UNSYNCED_FILE_NAME_EXT)) {
71
+ return false;
72
+ }
73
+ }
74
+ try {
75
+ return (await obj_status_1.ObjStatus.fileShowsObjNotInSyncedState(objFolderPath, objId));
76
+ }
77
+ catch (exc) {
78
+ return false;
79
+ }
80
+ }
74
81
  async findObj(objId) {
75
82
  let obj = this.objs.get(objId);
76
83
  if (obj) {
@@ -131,25 +138,23 @@ class ObjFiles {
131
138
  .pipe((0, utils_for_observables_1.flatTap)(undefined, err => this.removeFailedNewObj(newObj)));
132
139
  return { fileWrite$, newObj };
133
140
  }
134
- findUnsyncedObjs() {
141
+ findObjsToRemoveOnRemote() {
135
142
  return (0, rxjs_1.from)([undefined])
136
143
  .pipe(
137
144
  // listing recent folders, exactly once
138
145
  (0, operators_1.mergeMap)(() => this.folders.listRecent()),
139
146
  // flatten array and space it in time, to process folders one by one
140
- (0, operators_1.mergeMap)(objsAndPaths => objsAndPaths), (0, operators_1.filter)(({ objId }) => !this.objs.has(objId)), (0, operators_1.mergeMap)(async (objsAndPaths) => {
141
- await (0, sleep_1.sleep)(20);
142
- return objsAndPaths;
143
- }, 1),
144
- // check, emiting objId, if not synced, and undefined, if synced
145
- (0, operators_1.mergeMap)(({ path, objId }) => this.sync(objId, async () => {
146
- if (this.objs.has(objId)) {
147
- return;
147
+ (0, operators_1.mergeMap)(objsAndPaths => objsAndPaths), (0, operators_1.mergeMap)(async ({ objId, path }) => {
148
+ const obj = this.objs.get(objId);
149
+ if (obj) {
150
+ return (obj.statusObj().needsRemovalOnRemote() ?
151
+ objId : undefined);
148
152
  }
149
- const notSynced = await obj_status_1.ObjStatus.fileShowsObjNotInSyncedState(path, objId)
150
- .catch(notFoundOrReThrow).catch(this.logError);
151
- return (notSynced ? objId : undefined);
152
- })), (0, operators_1.filter)(objId => (objId !== undefined)));
153
+ else {
154
+ const needsRm = await obj_status_1.ObjStatus.fileShowsObjNeedsRemovalOnRemote(path, objId);
155
+ return (needsRm ? objId : undefined);
156
+ }
157
+ }, 1), (0, operators_1.filter)(objId => (objId !== undefined)));
153
158
  }
154
159
  scheduleGC(obj) {
155
160
  this.gc.scheduleCollection(obj);
@@ -334,9 +339,10 @@ class SyncedObj {
334
339
  this.remoteVers.set(uploadVersion, syncedVerObj);
335
340
  }
336
341
  else {
337
- await fs.rename(this.localVerPath(localVersion), remotePath);
342
+ const localPath = this.localVerPath(localVersion);
343
+ await fs.rename(localPath, remotePath);
338
344
  }
339
- await this.status.markLocalVersionSynced(localVersion, uploadVersion);
345
+ await this.status.recordUploadCompletion(localVersion, uploadVersion);
340
346
  this.scheduleSelfGC();
341
347
  }
342
348
  dropCachedLocalObjVersionsLessOrEqual(version) {
@@ -387,6 +393,25 @@ class SyncedObj {
387
393
  statusObj() {
388
394
  return this.status;
389
395
  }
396
+ async recordRemovalUploadAndGC() {
397
+ await this.status.recordRemoteRemovalCompletion();
398
+ this.scheduleSelfGC();
399
+ }
400
+ async isRemoteVersionOnDisk(version) {
401
+ if (!this.status.isAmongRemote(version)) {
402
+ throw (0, exceptions_1.makeObjVersionNotFoundExc)(this.objId, version);
403
+ }
404
+ const verPath = this.remoteVerPath(version);
405
+ if (!(await isOnDisk(verPath))) {
406
+ return 'none';
407
+ }
408
+ const objVer = await this.instanceOfRemoteObjVer(version);
409
+ return (objVer.doesFileNeedDownload() ? 'complete' : 'partial');
410
+ }
411
+ async downloadRemoteVersion(version) {
412
+ const objVer = await this.instanceOfRemoteObjVer(version);
413
+ await objVer.downloadMissingSections();
414
+ }
390
415
  }
391
416
  exports.SyncedObj = SyncedObj;
392
417
  Object.freeze(SyncedObj.prototype);