core-3nweb-client-lib 0.43.7 → 0.43.9

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 (39) hide show
  1. package/build/api-defs/files.d.ts +82 -4
  2. package/build/core/storage/synced/obj-files.d.ts +1 -0
  3. package/build/core/storage/synced/obj-files.js +16 -0
  4. package/build/core/storage/synced/obj-status.d.ts +1 -0
  5. package/build/core/storage/synced/obj-status.js +18 -0
  6. package/build/core/storage/synced/storage.d.ts +6 -2
  7. package/build/core/storage/synced/storage.js +12 -17
  8. package/build/core/storage/synced/upsyncer.d.ts +10 -1
  9. package/build/core/storage/synced/upsyncer.js +72 -9
  10. package/build/core-ipc/file.d.ts +27 -4
  11. package/build/core-ipc/file.js +90 -94
  12. package/build/core-ipc/fs.js +68 -132
  13. package/build/lib-client/fs-utils/files.js +6 -0
  14. package/build/lib-client/objs-on-disk/obj-on-disk.d.ts +1 -0
  15. package/build/lib-client/objs-on-disk/obj-on-disk.js +8 -1
  16. package/build/lib-client/xsp-fs/common.d.ts +13 -21
  17. package/build/lib-client/xsp-fs/common.js +4 -16
  18. package/build/lib-client/xsp-fs/file-node.d.ts +3 -2
  19. package/build/lib-client/xsp-fs/file-node.js +17 -11
  20. package/build/lib-client/xsp-fs/file.d.ts +5 -0
  21. package/build/lib-client/xsp-fs/file.js +26 -13
  22. package/build/lib-client/xsp-fs/folder-node.d.ts +7 -1
  23. package/build/lib-client/xsp-fs/folder-node.js +18 -10
  24. package/build/lib-client/xsp-fs/fs.d.ts +5 -0
  25. package/build/lib-client/xsp-fs/fs.js +33 -26
  26. package/build/lib-client/xsp-fs/link-node.d.ts +3 -0
  27. package/build/lib-client/xsp-fs/link-node.js +5 -1
  28. package/build/lib-client/xsp-fs/node-in-fs.d.ts +20 -6
  29. package/build/lib-client/xsp-fs/node-in-fs.js +69 -14
  30. package/build/lib-client/xsp-fs/node-persistence.d.ts +1 -0
  31. package/build/lib-client/xsp-fs/node-persistence.js +4 -0
  32. package/build/lib-common/big-endian.js +2 -2
  33. package/build/lib-common/processes/labelled-exec-pools.js +1 -3
  34. package/build/protos/asmail.proto.js +1614 -1588
  35. package/build/protos/file.proto.js +1258 -541
  36. package/build/protos/fs.proto.js +1459 -1433
  37. package/package.json +4 -4
  38. package/protos/file.proto +31 -15
  39. package/protos/fs.proto +13 -22
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  /*
3
- Copyright (C) 2018 - 2020, 2022 3NSoft Inc.
3
+ Copyright (C) 2018 - 2020, 2022, 2025 3NSoft Inc.
4
4
 
5
5
  This program is free software: you can redistribute it and/or modify it under
6
6
  the terms of the GNU General Public License as published by the Free Software
@@ -200,6 +200,13 @@ class ObjOnDisk {
200
200
  doesFileNeedDownload() {
201
201
  return (this.segsThatNeedDownload().length === 0);
202
202
  }
203
+ numOfBytesNeedingDownload() {
204
+ let totalLen = 0;
205
+ for (const { len } of this.segsThatNeedDownload()) {
206
+ totalLen += len;
207
+ }
208
+ return totalLen;
209
+ }
203
210
  async downloadMissingSections() {
204
211
  const needDownload = this.segsThatNeedDownload();
205
212
  for (const chunk of needDownload) {
@@ -1,9 +1,9 @@
1
- import { ScryptGenParams } from '../key-derivation';
2
- import { AsyncSBoxCryptor, Subscribe, ObjSource } from 'xsp-files';
3
- import { Observable } from 'rxjs';
4
- import { LogError } from '../logging/log-to-file';
5
- export { AsyncSBoxCryptor } from 'xsp-files';
6
- export { FolderInJSON } from './folder-node';
1
+ import type { ScryptGenParams } from '../key-derivation';
2
+ import type { AsyncSBoxCryptor, Subscribe, ObjSource } from 'xsp-files';
3
+ import type { Observable } from 'rxjs';
4
+ import type { LogError } from '../logging/log-to-file';
5
+ export type { AsyncSBoxCryptor } from 'xsp-files';
6
+ export type { FolderInJSON } from './folder-node';
7
7
  type StorageType = web3n.files.FSType;
8
8
  type FolderEvent = web3n.files.FolderEvent;
9
9
  type FileEvent = web3n.files.FileEvent;
@@ -12,6 +12,7 @@ type SyncStatus = web3n.files.SyncStatus;
12
12
  type OptionsToAdopteRemote = web3n.files.OptionsToAdopteRemote;
13
13
  type FSSyncException = web3n.files.FSSyncException;
14
14
  type FileException = web3n.files.FileException;
15
+ type UploadEvent = web3n.files.UploadEvent;
15
16
  export type FSChangeSrc = web3n.files.FSChangeEvent['src'];
16
17
  export interface Node {
17
18
  objId: string;
@@ -20,18 +21,6 @@ export interface Node {
20
21
  }
21
22
  export type NodeType = 'file' | 'link' | 'folder';
22
23
  export type ObjId = string | null;
23
- /**
24
- * This is a container for file system nodes.
25
- *
26
- * Current implementation performs two functions: container for nodes, and a
27
- * provider of node type, corresponding to given object.
28
- * The later function, used by synced storage for conflict resolution, takes
29
- * advantage of container not forgeting nodes, like cache may do.
30
- * So, at least for local storage's sake, this container may be refactored to
31
- * act more like cache, and even then we shouldn't forget about cascading keys
32
- * and a need to keep parent nodes in memory, while child nodes are in
33
- * use/cache.
34
- */
35
24
  export declare class NodesContainer {
36
25
  private nodes;
37
26
  private promises;
@@ -51,7 +40,7 @@ export interface NodeEvent {
51
40
  objId: ObjId;
52
41
  parentObjId?: ObjId;
53
42
  childObjId?: ObjId;
54
- event: FolderEvent | FileEvent | RemoteEvent;
43
+ event: FolderEvent | FileEvent | RemoteEvent | UploadEvent;
55
44
  }
56
45
  export interface Storage {
57
46
  readonly type: StorageType;
@@ -113,13 +102,16 @@ export interface SyncedStorage extends Storage {
113
102
  getRootKeyDerivParamsFromServer(): Promise<ScryptGenParams>;
114
103
  adoptRemote(objId: ObjId, opts: OptionsToAdopteRemote | undefined): Promise<number | undefined>;
115
104
  updateStatusInfo(objId: ObjId): Promise<SyncStatus>;
116
- isObjOnDisk(objId: ObjId): Promise<boolean>;
117
105
  isRemoteVersionOnDisk(objId: ObjId, version: number): Promise<'partial' | 'complete' | 'none'>;
118
106
  download(objId: ObjId, version: number): Promise<void>;
119
- upload(objId: ObjId, localVersion: number, uploadVersion: number, uploadHeader: UploadHeaderChange | undefined, createOnRemote: boolean): Promise<void>;
107
+ startUpload(objId: ObjId, localVersion: number, uploadVersion: number, uploadHeader: UploadHeaderChange | undefined, createOnRemote: boolean, eventSink: (event: UploadEvent) => void): Promise<{
108
+ uploadTaskId: number;
109
+ completion: Promise<void>;
110
+ }>;
120
111
  dropCachedLocalObjVersionsLessOrEqual(objId: ObjId, localVersion: number): void;
121
112
  uploadObjRemoval(objId: ObjId): Promise<void>;
122
113
  status(objId: ObjId): Promise<SyncedObjStatus>;
114
+ getNumOfBytesNeedingDownload(objId: ObjId, version: number): Promise<number | 'unknown'>;
123
115
  suspendNetworkActivity(): void;
124
116
  resumeNetworkActivity(): void;
125
117
  }
@@ -21,18 +21,6 @@ exports.wrapStorageImplementation = wrapStorageImplementation;
21
21
  exports.wrapSyncStorageImplementation = wrapSyncStorageImplementation;
22
22
  exports.isSyncedStorage = isSyncedStorage;
23
23
  exports.setPathInExc = setPathInExc;
24
- /**
25
- * This is a container for file system nodes.
26
- *
27
- * Current implementation performs two functions: container for nodes, and a
28
- * provider of node type, corresponding to given object.
29
- * The later function, used by synced storage for conflict resolution, takes
30
- * advantage of container not forgeting nodes, like cache may do.
31
- * So, at least for local storage's sake, this container may be refactored to
32
- * act more like cache, and even then we shouldn't forget about cascading keys
33
- * and a need to keep parent nodes in memory, while child nodes are in
34
- * use/cache.
35
- */
36
24
  class NodesContainer {
37
25
  constructor() {
38
26
  this.nodes = new Map();
@@ -125,23 +113,23 @@ function wrapSyncStorageImplementation(impl) {
125
113
  for (const [field, value] of Object.entries(storageWrap)) {
126
114
  wrap[field] = value;
127
115
  }
128
- wrap.getRootKeyDerivParamsFromServer =
129
- impl.getRootKeyDerivParamsFromServer.bind(impl);
116
+ wrap.getRootKeyDerivParamsFromServer = impl.getRootKeyDerivParamsFromServer.bind(impl);
130
117
  wrap.getObjSrcOfRemoteVersion = impl.getObjSrcOfRemoteVersion.bind(impl);
131
118
  wrap.archiveVersionOnServer = impl.archiveVersionOnServer.bind(impl);
132
119
  wrap.isRemoteVersionOnDisk = impl.isRemoteVersionOnDisk.bind(impl);
133
120
  wrap.download = impl.download.bind(impl);
134
- wrap.upload = impl.upload.bind(impl);
121
+ wrap.startUpload = impl.startUpload.bind(impl);
135
122
  wrap.uploadObjRemoval = impl.uploadObjRemoval.bind(impl);
136
123
  wrap.dropCachedLocalObjVersionsLessOrEqual = impl.dropCachedLocalObjVersionsLessOrEqual.bind(impl);
137
124
  wrap.adoptRemote = impl.adoptRemote.bind(impl);
138
125
  wrap.updateStatusInfo = impl.updateStatusInfo.bind(impl);
139
126
  wrap.suspendNetworkActivity = impl.suspendNetworkActivity.bind(impl);
140
127
  wrap.resumeNetworkActivity = impl.resumeNetworkActivity.bind(impl);
128
+ wrap.getNumOfBytesNeedingDownload = impl.getNumOfBytesNeedingDownload.bind(impl);
141
129
  return Object.freeze(wrap);
142
130
  }
143
131
  function isSyncedStorage(storage) {
144
- return !!storage.upload;
132
+ return !!storage.startUpload;
145
133
  }
146
134
  function setPathInExc(exc, path) {
147
135
  if ((exc.type === 'fs-sync') || (exc.type === 'file')) {
@@ -12,6 +12,7 @@ type FileByteSource = web3n.files.FileByteSource;
12
12
  type FileByteSink = web3n.files.FileByteSink;
13
13
  type XAttrsChanges = web3n.files.XAttrsChanges;
14
14
  type VersionedReadFlags = web3n.files.VersionedReadFlags;
15
+ type Stats = web3n.files.Stats;
15
16
  interface FileAttrs {
16
17
  attrs: CommonAttrs;
17
18
  size: number;
@@ -19,7 +20,7 @@ interface FileAttrs {
19
20
  }
20
21
  declare class FilePersistance extends NodePersistance {
21
22
  constructor(zNonce: Uint8Array, key: Uint8Array, cryptor: AsyncSBoxCryptor);
22
- getAttrs(objSrc: ObjSource): Promise<FileAttrs>;
23
+ getFileAttrs(objSrc: ObjSource): Promise<FileAttrs>;
23
24
  getFileSource(objSrc: ObjSource): Promise<FileByteSource>;
24
25
  readBytes(objSrc: ObjSource, start: number | undefined, end: number | undefined): Promise<Uint8Array | undefined>;
25
26
  saveBytes(bytes: Uint8Array | Uint8Array[], version: number, attrs: CommonAttrs, xattrs: XAttrs | undefined): Promise<Subscribe>;
@@ -42,7 +43,7 @@ export declare class FileNode extends NodeInFS<FilePersistance> {
42
43
  private static initWithAttrs;
43
44
  protected setCurrentStateFrom(src: ObjSource): Promise<void>;
44
45
  private setUpdatedState;
45
- get size(): number;
46
+ getStats(flags?: VersionedReadFlags): Promise<Stats>;
46
47
  readSrc(flags: VersionedReadFlags | undefined): Promise<{
47
48
  src: FileByteSource;
48
49
  version: number;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  /*
3
- Copyright (C) 2015 - 2020, 2022 3NSoft Inc.
3
+ Copyright (C) 2015 - 2020, 2022, 2025 3NSoft Inc.
4
4
 
5
5
  This program is free software: you can redistribute it and/or modify it under
6
6
  the terms of the GNU General Public License as published by the Free Software
@@ -29,19 +29,16 @@ const assert_1 = require("../../lib-common/assert");
29
29
  const attrs_1 = require("./attrs");
30
30
  const file_1 = require("../../lib-common/exceptions/file");
31
31
  const node_persistence_1 = require("./node-persistence");
32
- async function fileAttrsFrom(payload) {
33
- const attrs = payload.getAttrs();
34
- const xattrs = await payload.getXAttrs();
35
- return { attrs: attrs_1.CommonAttrs.fromAttrs(attrs), size: attrs.size, xattrs };
36
- }
37
32
  class FilePersistance extends node_persistence_1.NodePersistance {
38
33
  constructor(zNonce, key, cryptor) {
39
34
  super(zNonce, key, cryptor);
40
35
  Object.seal(this);
41
36
  }
42
- async getAttrs(objSrc) {
37
+ async getFileAttrs(objSrc) {
43
38
  const payload = await super.readonlyPayload(objSrc);
44
- return await fileAttrsFrom(payload);
39
+ const attrs = payload.getAttrs();
40
+ const xattrs = await payload.getXAttrs();
41
+ return { attrs: attrs_1.CommonAttrs.fromAttrs(attrs), size: attrs.size, xattrs };
45
42
  }
46
43
  async getFileSource(objSrc) {
47
44
  const payload = await this.readonlyPayload(objSrc);
@@ -122,15 +119,24 @@ class FileNode extends node_in_fs_1.NodeInFS {
122
119
  return file;
123
120
  }
124
121
  async setCurrentStateFrom(src) {
125
- const fileAttrs = await this.crypto.getAttrs(src);
122
+ const fileAttrs = await this.crypto.getFileAttrs(src);
126
123
  this.setUpdatedState(src.version, fileAttrs);
127
124
  }
128
125
  setUpdatedState(version, fileAttrs) {
129
126
  this.fileSize = fileAttrs.size;
130
127
  super.setUpdatedParams(version, fileAttrs.attrs, fileAttrs.xattrs);
131
128
  }
132
- get size() {
133
- return this.fileSize;
129
+ async getStats(flags) {
130
+ const { stats, attrs } = await this.getStatsAndSize(flags);
131
+ stats.size = (attrs ? attrs.size : this.fileSize);
132
+ if ((this.storage.type === 'synced')
133
+ || (this.storage.type === 'share')) {
134
+ const bytesNeedDownload = await this.syncedStorage().getNumOfBytesNeedingDownload(this.objId, stats.version);
135
+ if (typeof bytesNeedDownload === 'number') {
136
+ stats.bytesNeedDownload = bytesNeedDownload;
137
+ }
138
+ }
139
+ return stats;
134
140
  }
135
141
  async readSrc(flags) {
136
142
  const objSrc = await this.getObjSrcOfVersion(flags);
@@ -54,6 +54,7 @@ declare class V implements WritableFileVersionedAPI, N {
54
54
  constructor(name: string, node: FileNode | undefined, makeOrGetNode: (() => Promise<FileNode>) | undefined, writable: boolean, isInSyncedStorage: boolean);
55
55
  getNode(): Promise<FileNode>;
56
56
  ensureIsWritable(): void;
57
+ stat(flags?: VersionedReadFlags): Promise<Stats>;
57
58
  updateXAttrs(changes: XAttrsChanges): Promise<number>;
58
59
  getXAttr(xaName: string, flags?: VersionedReadFlags): Promise<{
59
60
  attr: any;
@@ -97,6 +98,10 @@ declare class V implements WritableFileVersionedAPI, N {
97
98
  declare class S implements WritableFileSyncAPI {
98
99
  private readonly n;
99
100
  constructor(n: N);
101
+ startUpload(opts?: OptionsToUploadLocal): Promise<{
102
+ uploadVersion: number;
103
+ uploadTaskId: number;
104
+ } | undefined>;
100
105
  upload(opts?: OptionsToUploadLocal): Promise<number | undefined>;
101
106
  status(skipServerCheck?: boolean): Promise<SyncStatus>;
102
107
  updateStatusInfo(): Promise<SyncStatus>;
@@ -54,18 +54,8 @@ class FileObject {
54
54
  linkParams.readonly = !this.writable;
55
55
  return linkParams;
56
56
  }
57
- async stat() {
58
- const node = await this.v.getNode();
59
- const attrs = node.getAttrs();
60
- const stat = {
61
- writable: this.writable,
62
- size: node.size,
63
- version: node.version,
64
- isFile: true,
65
- ctime: new Date(attrs.ctime),
66
- mtime: new Date(attrs.mtime),
67
- };
68
- return stat;
57
+ stat() {
58
+ return this.v.stat();
69
59
  }
70
60
  async updateXAttrs(changes) {
71
61
  await this.v.updateXAttrs(changes);
@@ -143,6 +133,12 @@ class V {
143
133
  throw new Error(`File is not writable`);
144
134
  }
145
135
  }
136
+ async stat(flags) {
137
+ const node = await this.getNode();
138
+ const stats = await node.getStats(flags);
139
+ stats.writable = this.writable;
140
+ return stats;
141
+ }
146
142
  async updateXAttrs(changes) {
147
143
  this.ensureIsWritable();
148
144
  const node = await this.getNode();
@@ -228,10 +224,27 @@ class S {
228
224
  this.n = n;
229
225
  Object.freeze(this);
230
226
  }
227
+ async startUpload(opts) {
228
+ this.n.ensureIsWritable();
229
+ const node = await this.n.getNode();
230
+ const startedUpload = await node.startUpload(opts);
231
+ if (startedUpload) {
232
+ const { uploadTaskId, uploadVersion } = startedUpload;
233
+ return { uploadTaskId, uploadVersion };
234
+ }
235
+ else {
236
+ return;
237
+ }
238
+ }
231
239
  async upload(opts) {
232
240
  this.n.ensureIsWritable();
233
241
  const node = await this.n.getNode();
234
- const uploadVersion = await node.upload(opts);
242
+ const startedUpload = await node.startUpload(opts);
243
+ if (!startedUpload) {
244
+ return;
245
+ }
246
+ const { uploadVersion, completion } = startedUpload;
247
+ await completion;
235
248
  return uploadVersion;
236
249
  }
237
250
  async status(skipServerCheck = false) {
@@ -13,6 +13,7 @@ type OptionsToAdopteRemote = web3n.files.OptionsToAdopteRemote;
13
13
  type OptionsToAdoptRemoteItem = web3n.files.OptionsToAdoptRemoteItem;
14
14
  type OptionsToUploadLocal = web3n.files.OptionsToUploadLocal;
15
15
  type VersionedReadFlags = web3n.files.VersionedReadFlags;
16
+ type Stats = web3n.files.Stats;
16
17
  export interface NodeInfo {
17
18
  /**
18
19
  * This is a usual file name.
@@ -74,6 +75,7 @@ export declare class FolderNode extends NodeInFS<FolderPersistance> {
74
75
  private static readNodeFromObjBytes;
75
76
  static rootFromLinkParams(storage: Storage, params: FolderLinkParams): Promise<FolderNode>;
76
77
  static rootFromJSON(storage: Storage, name: string | undefined, folderJson: FolderInJSON): FolderNode;
78
+ getStats(flags?: VersionedReadFlags): Promise<Stats>;
77
79
  protected setCurrentStateFrom(src: ObjSource): Promise<void>;
78
80
  adoptRemote(opts: OptionsToAdopteRemote | undefined): Promise<void>;
79
81
  private callRemoveObjOn;
@@ -142,7 +144,11 @@ export declare class FolderNode extends NodeInFS<FolderPersistance> {
142
144
  private removeChildrenObjsInSyncedStorage;
143
145
  private uploadRemovalOfObjs;
144
146
  getParamsForLink(): LinkParameters<FolderLinkParams>;
145
- upload(opts: OptionsToUploadLocal | undefined): Promise<number | undefined>;
147
+ startUpload(opts: OptionsToUploadLocal | undefined): Promise<{
148
+ uploadVersion: number;
149
+ completion: Promise<void>;
150
+ uploadTaskId: number;
151
+ } | undefined>;
146
152
  private uploadRemovalOf;
147
153
  private listRemovedInTreeToUploadRm;
148
154
  protected needUpload(opts: OptionsToUploadLocal | undefined): Promise<{
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  /*
3
- Copyright (C) 2015 - 2020, 2022 3NSoft Inc.
3
+ Copyright (C) 2015 - 2020, 2022, 2025 3NSoft Inc.
4
4
 
5
5
  This program is free software: you can redistribute it and/or modify it under
6
6
  the terms of the GNU General Public License as published by the Free Software
@@ -162,6 +162,10 @@ class FolderNode extends node_in_fs_1.NodeInFS {
162
162
  rf.setUpdatedParams(0, attrs, xattrs);
163
163
  return rf;
164
164
  }
165
+ async getStats(flags) {
166
+ const { stats } = await this.getStatsAndSize(flags);
167
+ return stats;
168
+ }
165
169
  async setCurrentStateFrom(src) {
166
170
  const { folderInfo, attrs, xattrs } = await this.crypto.read(src);
167
171
  this.currentState = folderInfo;
@@ -781,26 +785,30 @@ class FolderNode extends node_in_fs_1.NodeInFS {
781
785
  };
782
786
  return linkParams;
783
787
  }
784
- async upload(opts) {
788
+ async startUpload(opts) {
785
789
  try {
786
790
  const toUpload = await this.needUpload(opts);
787
791
  if (!toUpload) {
788
792
  return;
789
793
  }
794
+ const { localVersion, createOnRemote, uploadVersion } = toUpload;
790
795
  if (toUpload.createOnRemote) {
791
- return await super.upload(opts);
796
+ return await this.startUploadProcess(localVersion, createOnRemote, uploadVersion);
792
797
  }
793
- const storage = this.syncedStorage();
794
- const { localVersion, uploadVersion } = toUpload;
795
798
  const removedNodes = await this.getNodesRemovedBetweenVersions(localVersion, uploadVersion - 1);
796
- const uploadHeader = await this.uploadHeaderChange(localVersion, uploadVersion);
797
- await storage.upload(this.objId, localVersion, uploadVersion, uploadHeader, false);
799
+ const { completion, uploadTaskId } = await this.startUploadProcess(localVersion, createOnRemote, uploadVersion);
798
800
  if (removedNodes.length > 0) {
799
801
  // start upload of children's removal after folder's upload;
800
- // we also don't await for chidren removal
801
- this.uploadRemovalOf(removedNodes);
802
+ // we also don't await for chidren removal in returned completion
803
+ completion.then(() => this.uploadRemovalOf(removedNodes));
802
804
  }
803
- return uploadVersion;
805
+ return {
806
+ completion: completion.catch(exc => {
807
+ throw (0, common_1.setPathInExc)(exc, this.name);
808
+ }),
809
+ uploadTaskId,
810
+ uploadVersion
811
+ };
804
812
  }
805
813
  catch (exc) {
806
814
  throw (0, common_1.setPathInExc)(exc, this.name);
@@ -121,6 +121,7 @@ declare class V implements WritableFSVersionedAPI, N {
121
121
  getOrCreateFile(path: string, flags: FileFlags): Promise<FileNode>;
122
122
  get(path: string): Promise<NodeInFS<any>>;
123
123
  ensureIsWritable(): void;
124
+ stat(path: string, flags?: VersionedReadFlags): Promise<Stats>;
124
125
  updateXAttrs(path: string, changes: XAttrsChanges): Promise<number>;
125
126
  getXAttr(path: string, xaName: string, flags?: VersionedReadFlags): Promise<{
126
127
  attr: any;
@@ -161,6 +162,10 @@ declare class V implements WritableFSVersionedAPI, N {
161
162
  declare class S implements WritableFSSyncAPI {
162
163
  private readonly n;
163
164
  constructor(n: N);
165
+ startUpload(path: string, opts?: OptionsToUploadLocal): Promise<{
166
+ uploadVersion: number;
167
+ uploadTaskId: number;
168
+ } | undefined>;
164
169
  upload(path: string, opts?: OptionsToUploadLocal): Promise<number | undefined>;
165
170
  status(path: string, skipServerCheck?: boolean): Promise<SyncStatus>;
166
171
  updateStatusInfo(path: string): Promise<SyncStatus>;
@@ -204,31 +204,8 @@ class XspFS {
204
204
  throw exc;
205
205
  }
206
206
  }
207
- async stat(path) {
208
- const node = await this.v.get(path);
209
- const attrs = node.getAttrs();
210
- const stats = {
211
- ctime: new Date(attrs.ctime),
212
- mtime: new Date(attrs.mtime),
213
- version: node.version,
214
- writable: this.writable,
215
- };
216
- if (node.type === 'file') {
217
- stats.size = node.size;
218
- stats.isFile = true;
219
- return stats;
220
- }
221
- else if (node.type === 'folder') {
222
- stats.isFolder = true;
223
- return stats;
224
- }
225
- else if (node.type === 'link') {
226
- stats.isLink = true;
227
- return stats;
228
- }
229
- else {
230
- throw new Error(`Unknown type of fs node`);
231
- }
207
+ stat(path) {
208
+ return this.v.stat(path);
232
209
  }
233
210
  async updateXAttrs(path, changes) {
234
211
  await this.v.updateXAttrs(path, changes);
@@ -551,6 +528,12 @@ class V {
551
528
  throw new Error(`FS is not writable`);
552
529
  }
553
530
  }
531
+ async stat(path, flags) {
532
+ const node = await this.get(path);
533
+ const stats = await node.getStats(flags);
534
+ stats.writable = this.writable;
535
+ return stats;
536
+ }
554
537
  async updateXAttrs(path, changes) {
555
538
  this.ensureIsWritable();
556
539
  const node = await this.get(path);
@@ -723,11 +706,35 @@ class S {
723
706
  this.n = n;
724
707
  Object.freeze(this);
725
708
  }
709
+ async startUpload(path, opts) {
710
+ this.n.ensureIsWritable();
711
+ const node = await this.n.get(path);
712
+ try {
713
+ const startedUpload = await node.startUpload(opts);
714
+ if (startedUpload) {
715
+ const { uploadTaskId, uploadVersion } = startedUpload;
716
+ return { uploadTaskId, uploadVersion };
717
+ }
718
+ else {
719
+ return;
720
+ }
721
+ }
722
+ catch (exc) {
723
+ throw (0, common_1.setPathInExc)(exc, path);
724
+ }
725
+ ;
726
+ }
726
727
  async upload(path, opts) {
727
728
  this.n.ensureIsWritable();
728
729
  const node = await this.n.get(path);
729
730
  try {
730
- return await node.upload(opts);
731
+ const startedUpload = await node.startUpload(opts);
732
+ if (!startedUpload) {
733
+ return;
734
+ }
735
+ const { completion, uploadVersion } = startedUpload;
736
+ await completion;
737
+ return uploadVersion;
731
738
  }
732
739
  catch (exc) {
733
740
  throw (0, common_1.setPathInExc)(exc, path);
@@ -8,6 +8,8 @@ import { Storage, AsyncSBoxCryptor } from './common';
8
8
  import { ObjSource, Subscribe } from 'xsp-files';
9
9
  import { CommonAttrs, XAttrs } from './attrs';
10
10
  import { NodePersistance } from './node-persistence';
11
+ type VersionedReadFlags = web3n.files.VersionedReadFlags;
12
+ type Stats = web3n.files.Stats;
11
13
  declare class LinkPersistance extends NodePersistance {
12
14
  constructor(zNonce: Uint8Array, key: Uint8Array, cryptor: AsyncSBoxCryptor);
13
15
  read(src: ObjSource): Promise<{
@@ -25,6 +27,7 @@ export declare class LinkNode extends NodeInFS<LinkPersistance> {
25
27
  static makeForNew(storage: Storage, parentId: string, name: string, key: Uint8Array): Promise<LinkNode>;
26
28
  static makeForExisting(storage: Storage, parentId: string, name: string, objId: string, key: Uint8Array): Promise<LinkNode>;
27
29
  protected setCurrentStateFrom(src: ObjSource): Promise<void>;
30
+ getStats(flags?: VersionedReadFlags): Promise<Stats>;
28
31
  private setUpdatedState;
29
32
  save(params: LinkParameters<any>, changes?: XAttrsChanges): Promise<void>;
30
33
  private getLinkParams;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  /*
3
- Copyright (C) 2016 - 2018, 2020, 2022 3NSoft Inc.
3
+ Copyright (C) 2016 - 2018, 2020, 2022, 2025 3NSoft Inc.
4
4
 
5
5
  This program is free software: you can redistribute it and/or modify it under
6
6
  the terms of the GNU General Public License as published by the Free Software
@@ -103,6 +103,10 @@ class LinkNode extends node_in_fs_1.NodeInFS {
103
103
  const { params, attrs, xattrs } = await this.crypto.read(src);
104
104
  this.setUpdatedState(params, src.version, attrs, xattrs);
105
105
  }
106
+ async getStats(flags) {
107
+ const { stats } = await this.getStatsAndSize(flags);
108
+ return stats;
109
+ }
106
110
  setUpdatedState(params, version, attrs, xattrs) {
107
111
  this.linkParams = params;
108
112
  super.setUpdatedParams(version, attrs, xattrs);
@@ -1,15 +1,16 @@
1
- import { FSChangeSrc, Node, NodeType, Storage, SyncedStorage, UploadHeaderChange } 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
- import { NodePersistance } from './node-persistence';
4
+ import { Attrs, NodePersistance } from './node-persistence';
5
5
  import { ObjSource } from 'xsp-files';
6
- export type FSEvent = web3n.files.FolderEvent | web3n.files.FileEvent;
6
+ export type FSEvent = web3n.files.FolderEvent | web3n.files.FileEvent | web3n.files.UploadEvent;
7
7
  type RemoteEvent = web3n.files.RemoteEvent;
8
8
  type XAttrsChanges = web3n.files.XAttrsChanges;
9
9
  type SyncStatus = web3n.files.SyncStatus;
10
10
  type OptionsToAdopteRemote = web3n.files.OptionsToAdopteRemote;
11
11
  type OptionsToUploadLocal = web3n.files.OptionsToUploadLocal;
12
12
  type VersionedReadFlags = web3n.files.VersionedReadFlags;
13
+ type Stats = web3n.files.Stats;
13
14
  export declare abstract class NodeInFS<P extends NodePersistance> implements Node {
14
15
  protected readonly storage: Storage;
15
16
  readonly type: NodeType;
@@ -44,7 +45,11 @@ export declare abstract class NodeInFS<P extends NodePersistance> implements Nod
44
45
  lst: string[];
45
46
  version: number;
46
47
  }>;
47
- getAttrs(): CommonAttrs;
48
+ abstract getStats(flags?: VersionedReadFlags): Promise<Stats>;
49
+ protected getStatsAndSize(flags?: VersionedReadFlags): Promise<{
50
+ stats: Stats;
51
+ attrs?: Attrs;
52
+ }>;
48
53
  listVersions(): Promise<{
49
54
  current?: number;
50
55
  archived?: number[];
@@ -84,8 +89,17 @@ export declare abstract class NodeInFS<P extends NodePersistance> implements Nod
84
89
  uploadVersion: number;
85
90
  createOnRemote: boolean;
86
91
  } | undefined>;
87
- upload(opts: OptionsToUploadLocal | undefined): Promise<number | undefined>;
88
- protected uploadHeaderChange(localVersion: number, uploadVersion: number): Promise<UploadHeaderChange | undefined>;
92
+ startUpload(opts: OptionsToUploadLocal | undefined): Promise<{
93
+ uploadVersion: number;
94
+ completion: Promise<void>;
95
+ uploadTaskId: number;
96
+ } | undefined>;
97
+ protected startUploadProcess(localVersion: number, createOnRemote: boolean, uploadVersion: number): Promise<{
98
+ uploadVersion: number;
99
+ completion: Promise<void>;
100
+ uploadTaskId: number;
101
+ }>;
102
+ private makeHeaderForUploadIfVersionChanges;
89
103
  }
90
104
  export declare function shouldReadCurrentVersion(flags: VersionedReadFlags | undefined): boolean;
91
105
  export {};