core-3nweb-client-lib 0.43.6 → 0.43.8

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.
@@ -169,6 +169,7 @@ declare namespace web3n.files {
169
169
  local?: LocalVersion;
170
170
  remote?: SyncVersionsBranch;
171
171
  existsInSyncedParent?: boolean;
172
+ uploading?: UploadingState;
172
173
  }
173
174
 
174
175
  interface LocalVersion {
@@ -184,6 +185,24 @@ declare namespace web3n.files {
184
185
 
185
186
  type SyncState = 'synced' | 'behind' | 'unsynced' | 'conflicting';
186
187
 
188
+ interface UploadingState {
189
+ /**
190
+ * Local version that is uploaded to server.
191
+ * If it is an upload of object removal, version is -1.
192
+ */
193
+ localVersion: number;
194
+ /**
195
+ * New remote version that is uploaded to server.
196
+ * If it is an upload of object removal, version is -1.
197
+ */
198
+ remoteVersion: number;
199
+ /**
200
+ * Bytes left to upload.
201
+ */
202
+ bytesLeftToUpload: number;
203
+ uploadStarted: boolean;
204
+ }
205
+
187
206
  interface FileByteSource {
188
207
 
189
208
  /**
@@ -445,6 +464,12 @@ declare namespace web3n.files {
445
464
 
446
465
  interface ReadonlyFileVersionedAPI {
447
466
 
467
+ /**
468
+ * This returns a promise, resolvable to stats of the file.
469
+ * @param flags are optional flags to read archived or remote versions.
470
+ */
471
+ stat(flags?: VersionedReadFlags): Promise<Stats>;
472
+
448
473
  getXAttr(
449
474
  xaName: string, flags?: VersionedReadFlags
450
475
  ): Promise<{ attr: any; version: number; }>;
@@ -1063,6 +1088,14 @@ declare namespace web3n.files {
1063
1088
 
1064
1089
  interface ReadonlyFSVersionedAPI {
1065
1090
 
1091
+ /**
1092
+ * This returns a promise, resolvable to stats of an entity at a given
1093
+ * path.
1094
+ * @param path
1095
+ * @param flags are optional flags to read archived or remote versions.
1096
+ */
1097
+ stat(path: string, flags?: VersionedReadFlags): Promise<Stats>;
1098
+
1066
1099
  getXAttr(
1067
1100
  path: string, xaName: string, flags?: VersionedReadFlags
1068
1101
  ): Promise<{ attr: any; version: number; }>;
@@ -48,16 +48,37 @@ export interface RemovalUpload {
48
48
  export interface WholeVerOrderedUpload {
49
49
  type: 'ordered-whole';
50
50
  createObj?: boolean;
51
+ /**
52
+ * Header bytes that need to be uploaded. Undefined when header has been uploaded.
53
+ */
51
54
  header?: number;
55
+ /**
56
+ * Segments bytes left to upload.
57
+ */
52
58
  segsLeft: number;
59
+ /**
60
+ * Offset in segments, to which point bytes where uploaded.
61
+ */
53
62
  segsOfs: number;
63
+ /**
64
+ * Upload transaction id.
65
+ */
54
66
  transactionId?: string;
55
67
  }
56
68
  export interface DiffVerOrderedUpload {
57
69
  type: 'ordered-diff';
58
70
  diff: DiffInfo;
71
+ /**
72
+ * Header bytes that need to be uploaded. Undefined when header has been uploaded.
73
+ */
59
74
  header?: number;
75
+ /**
76
+ * New chunks of segments that should be uploaded.
77
+ */
60
78
  newSegsLeft: FiniteChunk[];
79
+ /**
80
+ * Upload transaction id.
81
+ */
61
82
  transactionId?: string;
62
83
  }
63
84
  export interface BytesSection {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  /*
3
- Copyright (C) 2016 - 2020, 2022 3NSoft Inc.
3
+ Copyright (C) 2016 - 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
@@ -494,7 +494,8 @@ class ObjStatus {
494
494
  state: this.stateIndicator,
495
495
  local: localVersionFromStatus(this.status.local),
496
496
  remote,
497
- synced
497
+ synced,
498
+ uploading: uploadInStatus(this.status.upload)
498
499
  };
499
500
  }
500
501
  neverUploaded() {
@@ -674,4 +675,46 @@ function skipNotFoundExc(exc) {
674
675
  throw exc;
675
676
  }
676
677
  }
678
+ function uploadInStatus(upload) {
679
+ if (!upload) {
680
+ return;
681
+ }
682
+ if (upload.type === 'new-version') {
683
+ const { needUpload } = upload;
684
+ if (!needUpload) {
685
+ return;
686
+ }
687
+ let bytesLeftToUpload = 0;
688
+ if (needUpload.type === 'ordered-whole') {
689
+ const { header, segsLeft } = needUpload;
690
+ if (header) {
691
+ bytesLeftToUpload += header;
692
+ }
693
+ bytesLeftToUpload += segsLeft;
694
+ }
695
+ else if (needUpload.type === 'ordered-diff') {
696
+ const { header, newSegsLeft } = needUpload;
697
+ if (header) {
698
+ bytesLeftToUpload += header;
699
+ }
700
+ for (const { len: chunkLen } of newSegsLeft) {
701
+ bytesLeftToUpload += chunkLen;
702
+ }
703
+ }
704
+ return {
705
+ localVersion: upload.localVersion,
706
+ remoteVersion: upload.uploadVersion,
707
+ bytesLeftToUpload,
708
+ uploadStarted: !!needUpload.transactionId
709
+ };
710
+ }
711
+ else {
712
+ return {
713
+ localVersion: -1,
714
+ remoteVersion: -1,
715
+ bytesLeftToUpload: 0,
716
+ uploadStarted: false
717
+ };
718
+ }
719
+ }
677
720
  Object.freeze(exports);
@@ -181,8 +181,7 @@ class UploadTask {
181
181
  }
182
182
  }
183
183
  async headerToUpload() {
184
- return (this.uploadHeader ?
185
- this.uploadHeader : await this.src.readHeader());
184
+ return (this.uploadHeader ? this.uploadHeader : await this.src.readHeader());
186
185
  }
187
186
  async startOrderedDiffUpload(upload) {
188
187
  const diff = buffer_utils_1.utf8.pack(JSON.stringify(upload.diff));
@@ -47,6 +47,10 @@ export interface VersionedReadFlagsMsg {
47
47
  }
48
48
  export declare function versionedReadFlagsFromMsg(msg: VersionedReadFlagsMsg | undefined): VersionedReadFlags | undefined;
49
49
  export declare function versionedReadFlagsToMsg(flags: VersionedReadFlags | undefined): VersionedReadFlagsMsg | undefined;
50
+ export declare namespace vStat {
51
+ function wrapService(fn: ReadonlyFileVersionedAPI['stat']): ExposedFn;
52
+ function makeCaller(caller: Caller, objPath: string[]): ReadonlyFileVersionedAPI['stat'];
53
+ }
50
54
  export declare namespace vGetXAttr {
51
55
  interface Reply {
52
56
  version: number;
@@ -16,7 +16,7 @@
16
16
  this program. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
18
  Object.defineProperty(exports, "__esModule", { value: true });
19
- exports.vListVersions = exports.vGetByteSink = exports.updateXAttrs = exports.vGetByteSource = exports.vReadJSON = exports.vReadTxt = exports.vReadBytes = exports.vListXAttrs = exports.vGetXAttr = exports.readBytes = exports.fileMsgType = void 0;
19
+ exports.vListVersions = exports.vGetByteSink = exports.updateXAttrs = exports.vGetByteSource = exports.vReadJSON = exports.vReadTxt = exports.vReadBytes = exports.vListXAttrs = exports.vGetXAttr = exports.vStat = exports.readBytes = exports.fileMsgType = void 0;
20
20
  exports.makeFileCaller = makeFileCaller;
21
21
  exports.exposeFileService = exposeFileService;
22
22
  exports.packStats = packStats;
@@ -75,6 +75,7 @@ function makeFileCaller(caller, fileMsg) {
75
75
  const vPath = (0, protobuf_msg_1.methodPathFor)(objPath, 'v');
76
76
  file.v = {
77
77
  getByteSource: vGetByteSource.makeCaller(caller, vPath),
78
+ stat: vStat.makeCaller(caller, vPath),
78
79
  getXAttr: vGetXAttr.makeCaller(caller, vPath),
79
80
  listXAttrs: vListXAttrs.makeCaller(caller, vPath),
80
81
  readBytes: vReadBytes.makeCaller(caller, vPath),
@@ -129,6 +130,7 @@ function exposeFileService(file, expServices) {
129
130
  if (file.v) {
130
131
  implExp.v = {
131
132
  getByteSource: vGetByteSource.wrapService(file.v.getByteSource, expServices),
133
+ stat: vStat.wrapService(file.v.stat),
132
134
  getXAttr: vGetXAttr.wrapService(file.v.getXAttr),
133
135
  listXAttrs: vListXAttrs.wrapService(file.v.listXAttrs),
134
136
  readBytes: vReadBytes.wrapService(file.v.readBytes),
@@ -171,7 +173,10 @@ function exposeFileService(file, expServices) {
171
173
  exports.fileMsgType = protobuf_type_1.ProtoType.for(file_proto_1.file.File);
172
174
  const statsMsgType = protobuf_type_1.ProtoType.for(file_proto_1.file.StatsMsg);
173
175
  function packStats(s) {
174
- const msg = {
176
+ return statsMsgType.pack(statsToMsg(s));
177
+ }
178
+ function statsToMsg(s) {
179
+ return {
175
180
  writable: s.writable,
176
181
  isFile: (0, protobuf_msg_1.toOptVal)(s.isFile),
177
182
  isFolder: (0, protobuf_msg_1.toOptVal)(s.isFolder),
@@ -181,10 +186,11 @@ function packStats(s) {
181
186
  size: (0, protobuf_msg_1.toOptVal)(s.size),
182
187
  version: (0, protobuf_msg_1.toOptVal)(s.version),
183
188
  };
184
- return statsMsgType.pack(msg);
185
189
  }
186
190
  function unpackStats(buf) {
187
- const m = statsMsgType.unpack(buf);
191
+ return msgToStats(statsMsgType.unpack(buf));
192
+ }
193
+ function msgToStats(m) {
188
194
  return {
189
195
  writable: m.writable,
190
196
  isFile: (0, protobuf_msg_1.valOfOpt)(m.isFile),
@@ -205,7 +211,8 @@ function syncStatusToMsg(s) {
205
211
  local: syncBranchToMsg(s.local),
206
212
  synced: syncBranchToMsg(s.synced),
207
213
  remote: syncBranchToMsg(s.remote),
208
- existsInSyncedParent: (0, protobuf_msg_1.toOptVal)(s.existsInSyncedParent)
214
+ existsInSyncedParent: (0, protobuf_msg_1.toOptVal)(s.existsInSyncedParent),
215
+ uploading: uploadingToMsg(s.uploading)
209
216
  };
210
217
  }
211
218
  function msgToSyncStatus(m) {
@@ -217,7 +224,8 @@ function msgToSyncStatus(m) {
217
224
  local: msgToSyncBranch(m.local),
218
225
  synced: msgToSyncBranch(m.synced),
219
226
  remote: msgToSyncBranch(m.remote),
220
- existsInSyncedParent: (0, protobuf_msg_1.valOfOpt)(m.existsInSyncedParent)
227
+ existsInSyncedParent: (0, protobuf_msg_1.valOfOpt)(m.existsInSyncedParent),
228
+ uploading: msgToUploading(m.uploading)
221
229
  };
222
230
  }
223
231
  function syncBranchToMsg(b) {
@@ -236,11 +244,28 @@ function msgToSyncBranch(m) {
236
244
  }
237
245
  return {
238
246
  latest: (0, protobuf_msg_1.valOfOptInt)(m.latest),
239
- archived: ((m.archived.length > 0) ?
240
- m.archived.map(protobuf_msg_1.fixInt) : undefined),
247
+ archived: ((m.archived.length > 0) ? m.archived.map(protobuf_msg_1.fixInt) : undefined),
241
248
  isArchived: (0, protobuf_msg_1.valOfOpt)(m.isArchived)
242
249
  };
243
250
  }
251
+ function uploadingToMsg(u) {
252
+ if (!u) {
253
+ return;
254
+ }
255
+ const { localVersion, remoteVersion, uploadStarted, bytesLeftToUpload } = u;
256
+ return { localVersion, remoteVersion, uploadStarted, bytesLeftToUpload };
257
+ }
258
+ function msgToUploading(u) {
259
+ if (!u) {
260
+ return;
261
+ }
262
+ return {
263
+ localVersion: (0, protobuf_msg_1.fixInt)(u.localVersion),
264
+ remoteVersion: (0, protobuf_msg_1.fixInt)(u.remoteVersion),
265
+ bytesLeftToUpload: (0, protobuf_msg_1.fixInt)(u.bytesLeftToUpload),
266
+ uploadStarted: u.uploadStarted
267
+ };
268
+ }
244
269
  const syncStatusMsgType = protobuf_type_1.ProtoType.for(file_proto_1.file.SyncStatusMsg);
245
270
  function packSyncStatus(s) {
246
271
  return syncStatusMsgType.pack(syncStatusToMsg(s));
@@ -556,6 +581,25 @@ function versionedReadFlagsToMsg(flags) {
556
581
  remoteVersion: (0, protobuf_msg_1.toOptVal)(flags.remoteVersion)
557
582
  };
558
583
  }
584
+ var vStat;
585
+ (function (vStat) {
586
+ function wrapService(fn) {
587
+ return buf => {
588
+ const promise = fn(unpackVersionedReadFlagsRequest(buf))
589
+ .then(packStats);
590
+ return { promise };
591
+ };
592
+ }
593
+ vStat.wrapService = wrapService;
594
+ function makeCaller(caller, objPath) {
595
+ const path = (0, protobuf_msg_1.methodPathFor)(objPath, 'stat');
596
+ return flags => caller
597
+ .startPromiseCall(path, packVersionedReadFlagsRequest(flags))
598
+ .then(unpackStats);
599
+ }
600
+ vStat.makeCaller = makeCaller;
601
+ })(vStat || (exports.vStat = vStat = {}));
602
+ Object.freeze(vStat);
559
603
  var vGetXAttr;
560
604
  (function (vGetXAttr) {
561
605
  const requestType = protobuf_type_1.ProtoType.for(file_proto_1.file.VersionedGetXAttrRequestBody);
@@ -83,6 +83,7 @@ function makeFSCaller(caller, fsMsg) {
83
83
  const vPath = (0, protobuf_msg_1.methodPathFor)(objPath, 'v');
84
84
  fs.v = {
85
85
  getByteSource: vGetByteSource.makeCaller(caller, vPath),
86
+ stat: vStat.makeCaller(caller, vPath),
86
87
  getXAttr: vGetXAttr.makeCaller(caller, vPath),
87
88
  listXAttrs: vListXAttrs.makeCaller(caller, vPath),
88
89
  listFolder: vListFolder.makeCaller(caller, vPath),
@@ -161,6 +162,7 @@ function exposeFSService(fs, expServices) {
161
162
  if (fs.v) {
162
163
  implExp.v = {
163
164
  getByteSource: vGetByteSource.wrapService(fs.v.getByteSource, expServices),
165
+ stat: vStat.wrapService(fs.v.stat),
164
166
  getXAttr: vGetXAttr.wrapService(fs.v.getXAttr),
165
167
  listXAttrs: vListXAttrs.wrapService(fs.v.listXAttrs),
166
168
  listFolder: vListFolder.wrapService(fs.v.listFolder),
@@ -1181,6 +1183,26 @@ function unpackRequestWithPathAndFlags(buf) {
1181
1183
  flags: file.versionedReadFlagsFromMsg(flags)
1182
1184
  };
1183
1185
  }
1186
+ var vStat;
1187
+ (function (vStat) {
1188
+ function wrapService(fn) {
1189
+ return buf => {
1190
+ const { path, flags } = unpackRequestWithPathAndFlags(buf);
1191
+ const promise = fn(path, flags)
1192
+ .then(file.packStats);
1193
+ return { promise };
1194
+ };
1195
+ }
1196
+ vStat.wrapService = wrapService;
1197
+ function makeCaller(caller, objPath) {
1198
+ const ipcPath = (0, protobuf_msg_1.methodPathFor)(objPath, 'stat');
1199
+ return (path, flags) => caller
1200
+ .startPromiseCall(ipcPath, packRequestWithPathAndFlags(path, flags))
1201
+ .then(file.unpackStats);
1202
+ }
1203
+ vStat.makeCaller = makeCaller;
1204
+ })(vStat || (vStat = {}));
1205
+ Object.freeze(vStat);
1184
1206
  var vGetXAttr;
1185
1207
  (function (vGetXAttr) {
1186
1208
  const requestType = protobuf_type_1.ProtoType.for(fs_proto_1.fs.VersionedGetXAttrRequestBody);
@@ -62,6 +62,7 @@ function wrapWritableFileVersionedAPI(vImpl) {
62
62
  return;
63
63
  }
64
64
  const w = {
65
+ stat: vImpl.stat.bind(vImpl),
65
66
  getXAttr: vImpl.getXAttr.bind(vImpl),
66
67
  listXAttrs: vImpl.listXAttrs.bind(vImpl),
67
68
  updateXAttrs: vImpl.updateXAttrs.bind(vImpl),
@@ -120,6 +121,7 @@ function wrapReadonlyFileVersionedAPI(vImpl) {
120
121
  return;
121
122
  }
122
123
  const w = {
124
+ stat: vImpl.stat.bind(vImpl),
123
125
  getXAttr: vImpl.getXAttr.bind(vImpl),
124
126
  listXAttrs: vImpl.listXAttrs.bind(vImpl),
125
127
  getByteSource: vImpl.getByteSource.bind(vImpl),
@@ -206,6 +208,7 @@ function wrapWritableFSVersionedAPI(vImpl) {
206
208
  return;
207
209
  }
208
210
  const w = {
211
+ stat: vImpl.stat.bind(vImpl),
209
212
  getXAttr: vImpl.getXAttr.bind(vImpl),
210
213
  listXAttrs: vImpl.listXAttrs.bind(vImpl),
211
214
  updateXAttrs: vImpl.updateXAttrs.bind(vImpl),
@@ -272,6 +275,7 @@ function wrapReadonlyFSVersionedAPI(vImpl) {
272
275
  return;
273
276
  }
274
277
  const w = {
278
+ stat: vImpl.stat.bind(vImpl),
275
279
  getXAttr: vImpl.getXAttr.bind(vImpl),
276
280
  listXAttrs: vImpl.listXAttrs.bind(vImpl),
277
281
  getByteSource: vImpl.getByteSource.bind(vImpl),
@@ -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,37 @@ 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
+ let attrs;
131
+ let version;
132
+ let size;
133
+ if ((0, node_in_fs_1.shouldReadCurrentVersion)(flags)) {
134
+ attrs = this.attrs;
135
+ version = this.version;
136
+ size = this.fileSize;
137
+ }
138
+ else {
139
+ const src = await this.getObjSrcOfVersion(flags);
140
+ const fileAttrs = await this.crypto.getFileAttrs(src);
141
+ attrs = fileAttrs.attrs;
142
+ version = src.version;
143
+ size = fileAttrs.size;
144
+ }
145
+ return {
146
+ ctime: new Date(attrs.ctime),
147
+ mtime: new Date(attrs.mtime),
148
+ version,
149
+ writable: false,
150
+ isFile: true,
151
+ size
152
+ };
134
153
  }
135
154
  async readSrc(flags) {
136
155
  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;
@@ -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();
@@ -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;
@@ -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,26 @@ 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
+ let attrs;
167
+ let version;
168
+ if ((0, node_in_fs_1.shouldReadCurrentVersion)(flags)) {
169
+ attrs = this.attrs;
170
+ version = this.version;
171
+ }
172
+ else {
173
+ const src = await this.getObjSrcOfVersion(flags);
174
+ attrs = await this.crypto.getAttrs(src);
175
+ version = src.version;
176
+ }
177
+ return {
178
+ ctime: new Date(attrs.ctime),
179
+ mtime: new Date(attrs.mtime),
180
+ version,
181
+ writable: false,
182
+ isFolder: true,
183
+ };
184
+ }
165
185
  async setCurrentStateFrom(src) {
166
186
  const { folderInfo, attrs, xattrs } = await this.crypto.read(src);
167
187
  this.currentState = folderInfo;
@@ -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;
@@ -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);
@@ -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;