core-3nweb-client-lib 0.43.9 → 0.43.12
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 +32 -8
- package/build/api-defs/web3n.d.ts +2 -0
- package/build/core/asmail/inbox/index.js +1 -1
- package/build/core/asmail/inbox/msg-downloader.d.ts +2 -12
- package/build/core/asmail/inbox/msg-downloader.js +13 -46
- package/build/core/storage/synced/downloader.d.ts +6 -15
- package/build/core/storage/synced/downloader.js +25 -48
- package/build/core/storage/synced/obj-files.d.ts +4 -2
- package/build/core/storage/synced/obj-files.js +7 -7
- package/build/core/storage/synced/storage.d.ts +4 -2
- package/build/core/storage/synced/storage.js +2 -2
- package/build/core/storage/synced/upsyncer.d.ts +2 -4
- package/build/core/storage/synced/upsyncer.js +19 -13
- package/build/core-ipc/file.d.ts +10 -0
- package/build/core-ipc/file.js +23 -13
- package/build/core-ipc/fs.js +15 -8
- package/build/lib-client/3nstorage/storage-owner.js +36 -29
- package/build/lib-client/3nweb-signup.js +7 -7
- package/build/lib-client/asmail/recipient.js +14 -11
- package/build/lib-client/asmail/sender.js +24 -25
- package/build/lib-client/asmail/service-config.js +3 -6
- package/build/lib-client/cryptor/cryptor-wasm.js +1 -1
- package/build/lib-client/cryptor/cryptor.wasm +0 -0
- package/build/lib-client/fs-utils/files.js +4 -4
- package/build/lib-client/mailer-id/login.js +7 -7
- package/build/lib-client/mailer-id/provisioner.js +9 -7
- package/build/lib-client/objs-on-disk/file-writing-proc.d.ts +1 -1
- package/build/lib-client/objs-on-disk/obj-on-disk.d.ts +51 -3
- package/build/lib-client/objs-on-disk/obj-on-disk.js +414 -34
- package/build/lib-client/request-utils.d.ts +0 -7
- package/build/lib-client/request-utils.js +16 -11
- package/build/lib-client/service-locator.js +11 -8
- package/build/lib-client/user-with-mid-session.js +2 -6
- package/build/lib-client/user-with-pkl-session.js +25 -24
- package/build/lib-client/xsp-fs/common.d.ts +8 -3
- package/build/lib-client/xsp-fs/common.js +1 -1
- package/build/lib-client/xsp-fs/file.d.ts +3 -1
- package/build/lib-client/xsp-fs/file.js +4 -4
- package/build/lib-client/xsp-fs/folder-node.d.ts +1 -1
- package/build/lib-client/xsp-fs/folder-node.js +4 -4
- package/build/lib-client/xsp-fs/fs.d.ts +3 -1
- package/build/lib-client/xsp-fs/fs.js +4 -4
- package/build/lib-client/xsp-fs/node-in-fs.d.ts +6 -4
- package/build/lib-client/xsp-fs/node-in-fs.js +14 -9
- package/build/lib-common/buffer-utils.js +4 -1
- package/build/lib-common/exceptions/http.d.ts +11 -1
- package/build/lib-common/exceptions/http.js +10 -2
- package/build/lib-common/objs-on-disk/utils.d.ts +1 -1
- package/build/lib-common/processes/labelled-exec-pools.d.ts +1 -1
- package/build/lib-common/processes/labelled-exec-pools.js +8 -2
- package/build/protos/asmail.proto.js +545 -116
- package/build/protos/file.proto.js +485 -56
- package/build/protos/fs.proto.js +545 -116
- package/package.json +1 -1
- package/protos/file.proto +8 -2
- package/protos/fs.proto +3 -3
- /package/build/lib-common/objs-on-disk/{obj-file.d.ts → obj-version-file.d.ts} +0 -0
- /package/build/lib-common/objs-on-disk/{obj-file.js → obj-version-file.js} +0 -0
|
@@ -17,16 +17,12 @@
|
|
|
17
17
|
*/
|
|
18
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
19
|
exports.ServiceUser = void 0;
|
|
20
|
-
/**
|
|
21
|
-
* This defines a base class for some service's client that logs in with
|
|
22
|
-
* MailerId and uses respectively authenticated session.
|
|
23
|
-
*/
|
|
24
|
-
const request_utils_1 = require("../lib-client/request-utils");
|
|
25
20
|
const api = require("../lib-common/service-api/mailer-id/login");
|
|
26
21
|
const ws_utils_1 = require("./ws-utils");
|
|
27
22
|
const url_1 = require("url");
|
|
28
23
|
const login_1 = require("./mailer-id/login");
|
|
29
24
|
const assert_1 = require("../lib-common/assert");
|
|
25
|
+
const http_1 = require("../lib-common/exceptions/http");
|
|
30
26
|
class ServiceUser {
|
|
31
27
|
get serviceURI() {
|
|
32
28
|
return this.uri;
|
|
@@ -162,7 +158,7 @@ class ServiceUser {
|
|
|
162
158
|
this.sessionId = undefined;
|
|
163
159
|
}
|
|
164
160
|
else {
|
|
165
|
-
throw (0,
|
|
161
|
+
throw (0, http_1.makeUnexpectedStatusHTTPException)(rep);
|
|
166
162
|
}
|
|
167
163
|
}
|
|
168
164
|
async callEnsuringLogin(func) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*
|
|
3
|
-
Copyright (C) 2015 - 2017, 2020 - 2021 3NSoft Inc.
|
|
3
|
+
Copyright (C) 2015 - 2017, 2020 - 2021, 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
|
|
@@ -17,11 +17,7 @@
|
|
|
17
17
|
*/
|
|
18
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
19
|
exports.ServiceUser = void 0;
|
|
20
|
-
|
|
21
|
-
* This defines a base class for some service's client that logs in with
|
|
22
|
-
* Public Key Login process and uses respectively authenticated session.
|
|
23
|
-
*/
|
|
24
|
-
const request_utils_1 = require("./request-utils");
|
|
20
|
+
const http_1 = require("../lib-common/exceptions/http");
|
|
25
21
|
const buffer_utils_1 = require("../lib-common/buffer-utils");
|
|
26
22
|
const ecma_nacl_1 = require("ecma-nacl");
|
|
27
23
|
const session_encryptor_1 = require("../lib-common/session-encryptor");
|
|
@@ -82,40 +78,43 @@ class ServiceUser {
|
|
|
82
78
|
if (rep.status == loginApi.start.SC.ok) {
|
|
83
79
|
// set sessionid
|
|
84
80
|
if (!rep.data || (typeof rep.data.sessionId !== 'string')) {
|
|
85
|
-
throw (0,
|
|
81
|
+
throw (0, http_1.makeMalformedReplyHTTPException)(rep);
|
|
86
82
|
}
|
|
87
83
|
this.sessionId = rep.data.sessionId;
|
|
88
84
|
// set server public key
|
|
89
85
|
if (typeof rep.data.serverPubKey !== 'string') {
|
|
90
|
-
throw (0,
|
|
86
|
+
throw (0, http_1.makeMalformedReplyHTTPException)(rep, { message: 'serverPubKey string is missing.' });
|
|
91
87
|
}
|
|
92
88
|
try {
|
|
93
89
|
this.serverPubKey = buffer_utils_1.base64.open(rep.data.serverPubKey);
|
|
94
90
|
if (this.serverPubKey.length !== ecma_nacl_1.box.KEY_LENGTH) {
|
|
95
|
-
throw (0,
|
|
91
|
+
throw (0, http_1.makeMalformedReplyHTTPException)(rep, { message: `server's key has a wrong size.` });
|
|
96
92
|
}
|
|
97
93
|
}
|
|
98
94
|
catch (err) {
|
|
99
|
-
throw (0,
|
|
95
|
+
throw (0, http_1.makeMalformedReplyHTTPException)(rep, {
|
|
96
|
+
message: `bad serverPubKey string. Error: ${('string' === typeof err) ? err : err.message}`
|
|
97
|
+
});
|
|
100
98
|
}
|
|
101
99
|
// get encrypted session key from json body
|
|
102
100
|
if (typeof rep.data.sessionKey !== 'string') {
|
|
103
|
-
throw (0,
|
|
101
|
+
throw (0, http_1.makeMalformedReplyHTTPException)(rep, { message: 'sessionKey string is missing.' });
|
|
104
102
|
}
|
|
105
103
|
try {
|
|
106
104
|
this.encChallenge = buffer_utils_1.base64.open(rep.data.sessionKey);
|
|
107
|
-
if (this.encChallenge.length !==
|
|
108
|
-
(
|
|
109
|
-
throw (0, request_utils_1.makeException)(rep, `Malformed reply: byte chunk with session key has a wrong size.`);
|
|
105
|
+
if (this.encChallenge.length !== (ecma_nacl_1.secret_box.NONCE_LENGTH + ecma_nacl_1.secret_box.KEY_LENGTH)) {
|
|
106
|
+
throw (0, http_1.makeMalformedReplyHTTPException)(rep, { message: `byte chunk with session key has a wrong size.` });
|
|
110
107
|
}
|
|
111
108
|
}
|
|
112
109
|
catch (err) {
|
|
113
|
-
throw (0,
|
|
110
|
+
throw (0, http_1.makeMalformedReplyHTTPException)(rep, {
|
|
111
|
+
message: `bad sessionKey string. Error: ${(typeof err === 'string') ? err : err.message}`
|
|
112
|
+
});
|
|
114
113
|
}
|
|
115
114
|
// get key derivation parameters for a default key
|
|
116
115
|
if (!keyId) {
|
|
117
116
|
if (typeof rep.data.keyDerivParams !== 'object') {
|
|
118
|
-
throw (0,
|
|
117
|
+
throw (0, http_1.makeMalformedReplyHTTPException)(rep, { message: `keyDerivParams string is missing.` });
|
|
119
118
|
}
|
|
120
119
|
this.keyDerivationParams = rep.data.keyDerivParams;
|
|
121
120
|
}
|
|
@@ -124,11 +123,13 @@ class ServiceUser {
|
|
|
124
123
|
(rep.status === loginApi.start.SC.redirect)) {
|
|
125
124
|
const rd = rep.data;
|
|
126
125
|
if (!rd || ('string' !== typeof rd.redirect)) {
|
|
127
|
-
throw (0,
|
|
126
|
+
throw (0, http_1.makeMalformedReplyHTTPException)(rep);
|
|
128
127
|
}
|
|
129
128
|
// refuse second redirect
|
|
130
129
|
if (this.redirectedFrom !== undefined) {
|
|
131
|
-
throw (0,
|
|
130
|
+
throw (0, http_1.makeMalformedReplyHTTPException)(rep, {
|
|
131
|
+
message: `Redirected too many times. First redirect was from ${this.redirectedFrom} to ${this.serviceURI}. Second and forbidden redirect is to ${rd.redirect}`
|
|
132
|
+
});
|
|
132
133
|
}
|
|
133
134
|
// set params
|
|
134
135
|
this.redirectedFrom = this.serviceURI;
|
|
@@ -137,12 +138,12 @@ class ServiceUser {
|
|
|
137
138
|
return this.startSession(keyId);
|
|
138
139
|
}
|
|
139
140
|
else if (rep.status === loginApi.start.SC.unknownUser) {
|
|
140
|
-
const exc = (0,
|
|
141
|
+
const exc = (0, http_1.makeHTTPException)(rep.url, rep.method, rep.status, {});
|
|
141
142
|
exc.unknownUser = true;
|
|
142
143
|
throw exc;
|
|
143
144
|
}
|
|
144
145
|
else {
|
|
145
|
-
throw (0,
|
|
146
|
+
throw (0, http_1.makeUnexpectedStatusHTTPException)(rep);
|
|
146
147
|
}
|
|
147
148
|
}
|
|
148
149
|
openSessionKey(dhsharedKeyCalc) {
|
|
@@ -190,18 +191,18 @@ class ServiceUser {
|
|
|
190
191
|
this.serverVerificationBytes = undefined;
|
|
191
192
|
}
|
|
192
193
|
else {
|
|
193
|
-
const exc = (0,
|
|
194
|
+
const exc = (0, http_1.makeHTTPException)(rep.url, rep.method, rep.status, {});
|
|
194
195
|
exc.serverNotTrusted = true;
|
|
195
196
|
throw exc;
|
|
196
197
|
}
|
|
197
198
|
}
|
|
198
199
|
else if (rep.status === loginApi.complete.SC.authFailed) {
|
|
199
|
-
const exc = (0,
|
|
200
|
+
const exc = (0, http_1.makeHTTPException)(rep.url, rep.method, rep.status, {});
|
|
200
201
|
exc.cryptoResponseNotAccepted = true;
|
|
201
202
|
throw exc;
|
|
202
203
|
}
|
|
203
204
|
else {
|
|
204
|
-
throw (0,
|
|
205
|
+
throw (0, http_1.makeUnexpectedStatusHTTPException)(rep);
|
|
205
206
|
}
|
|
206
207
|
}
|
|
207
208
|
/**
|
|
@@ -245,7 +246,7 @@ class ServiceUser {
|
|
|
245
246
|
this.encryptor = undefined;
|
|
246
247
|
}
|
|
247
248
|
else {
|
|
248
|
-
throw (0,
|
|
249
|
+
throw (0, http_1.makeUnexpectedStatusHTTPException)(rep);
|
|
249
250
|
}
|
|
250
251
|
}
|
|
251
252
|
}
|
|
@@ -13,6 +13,7 @@ type OptionsToAdopteRemote = web3n.files.OptionsToAdopteRemote;
|
|
|
13
13
|
type FSSyncException = web3n.files.FSSyncException;
|
|
14
14
|
type FileException = web3n.files.FileException;
|
|
15
15
|
type UploadEvent = web3n.files.UploadEvent;
|
|
16
|
+
type DownloadEvent = web3n.files.DownloadEvent;
|
|
16
17
|
export type FSChangeSrc = web3n.files.FSChangeEvent['src'];
|
|
17
18
|
export interface Node {
|
|
18
19
|
objId: string;
|
|
@@ -40,7 +41,7 @@ export interface NodeEvent {
|
|
|
40
41
|
objId: ObjId;
|
|
41
42
|
parentObjId?: ObjId;
|
|
42
43
|
childObjId?: ObjId;
|
|
43
|
-
event: FolderEvent | FileEvent | RemoteEvent | UploadEvent;
|
|
44
|
+
event: FolderEvent | FileEvent | RemoteEvent | UploadEvent | DownloadEvent;
|
|
44
45
|
}
|
|
45
46
|
export interface Storage {
|
|
46
47
|
readonly type: StorageType;
|
|
@@ -93,6 +94,8 @@ export interface LocalObjStatus {
|
|
|
93
94
|
}
|
|
94
95
|
export declare function wrapStorageImplementation(impl: Storage): Storage;
|
|
95
96
|
export type StorageGetter = (type: StorageType, location?: string) => Storage;
|
|
97
|
+
export type DownloadEventSink = (event: DownloadEvent) => void;
|
|
98
|
+
export type UploadEventSink = (event: UploadEvent) => void;
|
|
96
99
|
export interface SyncedStorage extends Storage {
|
|
97
100
|
getObjSrcOfRemoteVersion(objId: ObjId, version: number): Promise<ObjSource>;
|
|
98
101
|
archiveVersionOnServer(objId: ObjId, version: number): Promise<void>;
|
|
@@ -103,8 +106,10 @@ export interface SyncedStorage extends Storage {
|
|
|
103
106
|
adoptRemote(objId: ObjId, opts: OptionsToAdopteRemote | undefined): Promise<number | undefined>;
|
|
104
107
|
updateStatusInfo(objId: ObjId): Promise<SyncStatus>;
|
|
105
108
|
isRemoteVersionOnDisk(objId: ObjId, version: number): Promise<'partial' | 'complete' | 'none'>;
|
|
106
|
-
|
|
107
|
-
|
|
109
|
+
startDownload(objId: ObjId, version: number, eventSink: DownloadEventSink): Promise<{
|
|
110
|
+
downloadTaskId: number;
|
|
111
|
+
} | undefined>;
|
|
112
|
+
startUpload(objId: ObjId, localVersion: number, uploadVersion: number, uploadHeader: UploadHeaderChange | undefined, createOnRemote: boolean, eventSink: UploadEventSink | undefined): Promise<{
|
|
108
113
|
uploadTaskId: number;
|
|
109
114
|
completion: Promise<void>;
|
|
110
115
|
}>;
|
|
@@ -117,7 +117,7 @@ function wrapSyncStorageImplementation(impl) {
|
|
|
117
117
|
wrap.getObjSrcOfRemoteVersion = impl.getObjSrcOfRemoteVersion.bind(impl);
|
|
118
118
|
wrap.archiveVersionOnServer = impl.archiveVersionOnServer.bind(impl);
|
|
119
119
|
wrap.isRemoteVersionOnDisk = impl.isRemoteVersionOnDisk.bind(impl);
|
|
120
|
-
wrap.
|
|
120
|
+
wrap.startDownload = impl.startDownload.bind(impl);
|
|
121
121
|
wrap.startUpload = impl.startUpload.bind(impl);
|
|
122
122
|
wrap.uploadObjRemoval = impl.uploadObjRemoval.bind(impl);
|
|
123
123
|
wrap.dropCachedLocalObjVersionsLessOrEqual = impl.dropCachedLocalObjVersionsLessOrEqual.bind(impl);
|
|
@@ -106,7 +106,9 @@ declare class S implements WritableFileSyncAPI {
|
|
|
106
106
|
status(skipServerCheck?: boolean): Promise<SyncStatus>;
|
|
107
107
|
updateStatusInfo(): Promise<SyncStatus>;
|
|
108
108
|
isRemoteVersionOnDisk(version: number): Promise<'complete' | 'partial' | 'none'>;
|
|
109
|
-
|
|
109
|
+
startDownload(version: number): Promise<{
|
|
110
|
+
downloadTaskId: number;
|
|
111
|
+
} | undefined>;
|
|
110
112
|
adoptRemote(opts?: OptionsToAdopteRemote): Promise<void>;
|
|
111
113
|
}
|
|
112
114
|
export {};
|
|
@@ -227,7 +227,7 @@ class S {
|
|
|
227
227
|
async startUpload(opts) {
|
|
228
228
|
this.n.ensureIsWritable();
|
|
229
229
|
const node = await this.n.getNode();
|
|
230
|
-
const startedUpload = await node.startUpload(opts);
|
|
230
|
+
const startedUpload = await node.startUpload(opts, true);
|
|
231
231
|
if (startedUpload) {
|
|
232
232
|
const { uploadTaskId, uploadVersion } = startedUpload;
|
|
233
233
|
return { uploadTaskId, uploadVersion };
|
|
@@ -239,7 +239,7 @@ class S {
|
|
|
239
239
|
async upload(opts) {
|
|
240
240
|
this.n.ensureIsWritable();
|
|
241
241
|
const node = await this.n.getNode();
|
|
242
|
-
const startedUpload = await node.startUpload(opts);
|
|
242
|
+
const startedUpload = await node.startUpload(opts, false);
|
|
243
243
|
if (!startedUpload) {
|
|
244
244
|
return;
|
|
245
245
|
}
|
|
@@ -261,9 +261,9 @@ class S {
|
|
|
261
261
|
const isOnDisk = await node.isSyncedVersionOnDisk(version);
|
|
262
262
|
return isOnDisk;
|
|
263
263
|
}
|
|
264
|
-
async
|
|
264
|
+
async startDownload(version) {
|
|
265
265
|
const node = await this.n.getNode();
|
|
266
|
-
await node.
|
|
266
|
+
return await node.startDownload(version);
|
|
267
267
|
}
|
|
268
268
|
async adoptRemote(opts) {
|
|
269
269
|
const node = await this.n.getNode();
|
|
@@ -144,7 +144,7 @@ export declare class FolderNode extends NodeInFS<FolderPersistance> {
|
|
|
144
144
|
private removeChildrenObjsInSyncedStorage;
|
|
145
145
|
private uploadRemovalOfObjs;
|
|
146
146
|
getParamsForLink(): LinkParameters<FolderLinkParams>;
|
|
147
|
-
startUpload(opts: OptionsToUploadLocal | undefined): Promise<{
|
|
147
|
+
startUpload(opts: OptionsToUploadLocal | undefined, emitEvents: boolean): Promise<{
|
|
148
148
|
uploadVersion: number;
|
|
149
149
|
completion: Promise<void>;
|
|
150
150
|
uploadTaskId: number;
|
|
@@ -244,7 +244,7 @@ class FolderNode extends node_in_fs_1.NodeInFS {
|
|
|
244
244
|
async listNonCurrent(flags) {
|
|
245
245
|
const src = await this.getObjSrcOfVersion(flags);
|
|
246
246
|
const { folderInfo } = await this.crypto.read(src);
|
|
247
|
-
const lst = Object.values(folderInfo)
|
|
247
|
+
const lst = Object.values(folderInfo.nodes)
|
|
248
248
|
.map(nodeInfoToListingEntry);
|
|
249
249
|
return { lst, version: src.version };
|
|
250
250
|
}
|
|
@@ -785,7 +785,7 @@ class FolderNode extends node_in_fs_1.NodeInFS {
|
|
|
785
785
|
};
|
|
786
786
|
return linkParams;
|
|
787
787
|
}
|
|
788
|
-
async startUpload(opts) {
|
|
788
|
+
async startUpload(opts, emitEvents) {
|
|
789
789
|
try {
|
|
790
790
|
const toUpload = await this.needUpload(opts);
|
|
791
791
|
if (!toUpload) {
|
|
@@ -793,10 +793,10 @@ class FolderNode extends node_in_fs_1.NodeInFS {
|
|
|
793
793
|
}
|
|
794
794
|
const { localVersion, createOnRemote, uploadVersion } = toUpload;
|
|
795
795
|
if (toUpload.createOnRemote) {
|
|
796
|
-
return await this.startUploadProcess(localVersion, createOnRemote, uploadVersion);
|
|
796
|
+
return await this.startUploadProcess(localVersion, createOnRemote, uploadVersion, emitEvents);
|
|
797
797
|
}
|
|
798
798
|
const removedNodes = await this.getNodesRemovedBetweenVersions(localVersion, uploadVersion - 1);
|
|
799
|
-
const { completion, uploadTaskId } = await this.startUploadProcess(localVersion, createOnRemote, uploadVersion);
|
|
799
|
+
const { completion, uploadTaskId } = await this.startUploadProcess(localVersion, createOnRemote, uploadVersion, emitEvents);
|
|
800
800
|
if (removedNodes.length > 0) {
|
|
801
801
|
// start upload of children's removal after folder's upload;
|
|
802
802
|
// we also don't await for chidren removal in returned completion
|
|
@@ -170,7 +170,9 @@ declare class S implements WritableFSSyncAPI {
|
|
|
170
170
|
status(path: string, skipServerCheck?: boolean): Promise<SyncStatus>;
|
|
171
171
|
updateStatusInfo(path: string): Promise<SyncStatus>;
|
|
172
172
|
isRemoteVersionOnDisk(path: string, version: number): Promise<'complete' | 'partial' | 'none'>;
|
|
173
|
-
|
|
173
|
+
startDownload(path: string, version: number): Promise<{
|
|
174
|
+
downloadTaskId: number;
|
|
175
|
+
} | undefined>;
|
|
174
176
|
adoptRemote(path: string, opts?: OptionsToAdopteRemote): Promise<void>;
|
|
175
177
|
private getFolderNode;
|
|
176
178
|
diffCurrentAndRemoteFolderVersions(path: string, remoteVersion?: number): Promise<FolderDiff | undefined>;
|
|
@@ -710,7 +710,7 @@ class S {
|
|
|
710
710
|
this.n.ensureIsWritable();
|
|
711
711
|
const node = await this.n.get(path);
|
|
712
712
|
try {
|
|
713
|
-
const startedUpload = await node.startUpload(opts);
|
|
713
|
+
const startedUpload = await node.startUpload(opts, true);
|
|
714
714
|
if (startedUpload) {
|
|
715
715
|
const { uploadTaskId, uploadVersion } = startedUpload;
|
|
716
716
|
return { uploadTaskId, uploadVersion };
|
|
@@ -728,7 +728,7 @@ class S {
|
|
|
728
728
|
this.n.ensureIsWritable();
|
|
729
729
|
const node = await this.n.get(path);
|
|
730
730
|
try {
|
|
731
|
-
const startedUpload = await node.startUpload(opts);
|
|
731
|
+
const startedUpload = await node.startUpload(opts, false);
|
|
732
732
|
if (!startedUpload) {
|
|
733
733
|
return;
|
|
734
734
|
}
|
|
@@ -765,10 +765,10 @@ class S {
|
|
|
765
765
|
throw (0, common_1.setPathInExc)(exc, path);
|
|
766
766
|
}
|
|
767
767
|
}
|
|
768
|
-
async
|
|
768
|
+
async startDownload(path, version) {
|
|
769
769
|
const node = await this.n.get(path);
|
|
770
770
|
try {
|
|
771
|
-
await node.
|
|
771
|
+
return await node.startDownload(version);
|
|
772
772
|
}
|
|
773
773
|
catch (exc) {
|
|
774
774
|
throw (0, common_1.setPathInExc)(exc, path);
|
|
@@ -3,7 +3,7 @@ import { Observable } from 'rxjs';
|
|
|
3
3
|
import { CommonAttrs, XAttrs } from './attrs';
|
|
4
4
|
import { Attrs, NodePersistance } from './node-persistence';
|
|
5
5
|
import { ObjSource } from 'xsp-files';
|
|
6
|
-
export type FSEvent = web3n.files.FolderEvent | web3n.files.FileEvent | web3n.files.UploadEvent;
|
|
6
|
+
export type FSEvent = web3n.files.FolderEvent | web3n.files.FileEvent | web3n.files.UploadEvent | web3n.files.DownloadEvent;
|
|
7
7
|
type RemoteEvent = web3n.files.RemoteEvent;
|
|
8
8
|
type XAttrsChanges = web3n.files.XAttrsChanges;
|
|
9
9
|
type SyncStatus = web3n.files.SyncStatus;
|
|
@@ -81,7 +81,9 @@ export declare abstract class NodeInFS<P extends NodePersistance> implements Nod
|
|
|
81
81
|
syncStatus(): Promise<SyncStatus>;
|
|
82
82
|
updateStatusInfo(): Promise<SyncStatus>;
|
|
83
83
|
isSyncedVersionOnDisk(version: number): Promise<'partial' | 'complete' | 'none'>;
|
|
84
|
-
|
|
84
|
+
startDownload(version: number): Promise<{
|
|
85
|
+
downloadTaskId: number;
|
|
86
|
+
} | undefined>;
|
|
85
87
|
protected abstract setCurrentStateFrom(src: ObjSource): Promise<void>;
|
|
86
88
|
adoptRemote(opts: OptionsToAdopteRemote | undefined): Promise<void>;
|
|
87
89
|
protected needUpload(opts: OptionsToUploadLocal | undefined): Promise<{
|
|
@@ -89,12 +91,12 @@ export declare abstract class NodeInFS<P extends NodePersistance> implements Nod
|
|
|
89
91
|
uploadVersion: number;
|
|
90
92
|
createOnRemote: boolean;
|
|
91
93
|
} | undefined>;
|
|
92
|
-
startUpload(opts: OptionsToUploadLocal | undefined): Promise<{
|
|
94
|
+
startUpload(opts: OptionsToUploadLocal | undefined, emitEvents: boolean): Promise<{
|
|
93
95
|
uploadVersion: number;
|
|
94
96
|
completion: Promise<void>;
|
|
95
97
|
uploadTaskId: number;
|
|
96
98
|
} | undefined>;
|
|
97
|
-
protected startUploadProcess(localVersion: number, createOnRemote: boolean, uploadVersion: number): Promise<{
|
|
99
|
+
protected startUploadProcess(localVersion: number, createOnRemote: boolean, uploadVersion: number, emitEvents: boolean): Promise<{
|
|
98
100
|
uploadVersion: number;
|
|
99
101
|
completion: Promise<void>;
|
|
100
102
|
uploadTaskId: number;
|
|
@@ -361,9 +361,12 @@ class NodeInFS {
|
|
|
361
361
|
const storage = this.syncedStorage();
|
|
362
362
|
return storage.isRemoteVersionOnDisk(this.objId, version);
|
|
363
363
|
}
|
|
364
|
-
async
|
|
364
|
+
async startDownload(version) {
|
|
365
365
|
const storage = this.syncedStorage();
|
|
366
|
-
return storage.
|
|
366
|
+
return storage.startDownload(this.objId, version, event => {
|
|
367
|
+
event.path = this.name;
|
|
368
|
+
this.broadcastEvent(event);
|
|
369
|
+
});
|
|
367
370
|
}
|
|
368
371
|
adoptRemote(opts) {
|
|
369
372
|
return this.doChange(true, async () => {
|
|
@@ -477,26 +480,28 @@ class NodeInFS {
|
|
|
477
480
|
}
|
|
478
481
|
return { createOnRemote: (uploadVersion === 1), localVersion, uploadVersion };
|
|
479
482
|
}
|
|
480
|
-
async startUpload(opts) {
|
|
483
|
+
async startUpload(opts, emitEvents) {
|
|
481
484
|
try {
|
|
482
485
|
const toUpload = await this.needUpload(opts);
|
|
483
486
|
if (!toUpload) {
|
|
484
487
|
return;
|
|
485
488
|
}
|
|
486
489
|
const { localVersion, createOnRemote, uploadVersion } = toUpload;
|
|
487
|
-
return await this.startUploadProcess(localVersion, createOnRemote, uploadVersion);
|
|
490
|
+
return await this.startUploadProcess(localVersion, createOnRemote, uploadVersion, emitEvents);
|
|
488
491
|
}
|
|
489
492
|
catch (exc) {
|
|
490
493
|
throw (0, common_1.setPathInExc)(exc, this.name);
|
|
491
494
|
}
|
|
492
495
|
}
|
|
493
|
-
async startUploadProcess(localVersion, createOnRemote, uploadVersion) {
|
|
496
|
+
async startUploadProcess(localVersion, createOnRemote, uploadVersion, emitEvents) {
|
|
494
497
|
const uploadHeader = await this.makeHeaderForUploadIfVersionChanges(localVersion, uploadVersion);
|
|
495
498
|
const storage = this.syncedStorage();
|
|
496
|
-
const { completion, uploadTaskId } = await storage.startUpload(this.objId, localVersion, uploadVersion, uploadHeader, createOnRemote,
|
|
497
|
-
event
|
|
498
|
-
|
|
499
|
-
|
|
499
|
+
const { completion, uploadTaskId } = await storage.startUpload(this.objId, localVersion, uploadVersion, uploadHeader, createOnRemote, (emitEvents ?
|
|
500
|
+
event => {
|
|
501
|
+
event.path = this.name;
|
|
502
|
+
this.broadcastEvent(event);
|
|
503
|
+
} :
|
|
504
|
+
undefined));
|
|
500
505
|
return {
|
|
501
506
|
completion: completion.then(() => this.doChange(true, async () => {
|
|
502
507
|
if (this.currentVersion === localVersion) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*
|
|
3
|
-
Copyright (C) 2016, 2018 - 2020 3NSoft Inc.
|
|
3
|
+
Copyright (C) 2016, 2018 - 2020, 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
|
|
@@ -97,6 +97,9 @@ var utf8;
|
|
|
97
97
|
})(utf8 || (exports.utf8 = utf8 = {}));
|
|
98
98
|
Object.freeze(utf8);
|
|
99
99
|
function joinByteArrs(arrs) {
|
|
100
|
+
if (arrs.length === 1) {
|
|
101
|
+
return arrs[0];
|
|
102
|
+
}
|
|
100
103
|
let totalLen = 0;
|
|
101
104
|
for (const arr of arrs) {
|
|
102
105
|
totalLen += arr.length;
|
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
export type ConnectException = web3n.HTTPConnectException;
|
|
2
2
|
export type HTTPException = web3n.HTTPException;
|
|
3
3
|
export declare function makeConnectionException(url: string | undefined, method: string | undefined, message?: string, cause?: any): ConnectException;
|
|
4
|
-
export declare function makeHTTPException(url: string, method: string, status: number,
|
|
4
|
+
export declare function makeHTTPException(url: string, method: string, status: number, params: Partial<HTTPException>): HTTPException;
|
|
5
|
+
export declare function makeMalformedReplyHTTPException({ url, method, status }: {
|
|
6
|
+
url: string;
|
|
7
|
+
method: string;
|
|
8
|
+
status: number;
|
|
9
|
+
}, params?: Partial<HTTPException>): HTTPException;
|
|
10
|
+
export declare function makeUnexpectedStatusHTTPException({ url, method, status }: {
|
|
11
|
+
url: string;
|
|
12
|
+
method: string;
|
|
13
|
+
status: number;
|
|
14
|
+
}, params?: Partial<HTTPException>): HTTPException;
|
|
@@ -17,11 +17,19 @@
|
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
exports.makeConnectionException = makeConnectionException;
|
|
19
19
|
exports.makeHTTPException = makeHTTPException;
|
|
20
|
+
exports.makeMalformedReplyHTTPException = makeMalformedReplyHTTPException;
|
|
21
|
+
exports.makeUnexpectedStatusHTTPException = makeUnexpectedStatusHTTPException;
|
|
20
22
|
const runtime_1 = require("./runtime");
|
|
21
23
|
function makeConnectionException(url, method, message, cause) {
|
|
22
24
|
return (0, runtime_1.makeRuntimeException)('connect', { connectType: 'http', url, method, cause, message }, {});
|
|
23
25
|
}
|
|
24
|
-
function makeHTTPException(url, method, status,
|
|
25
|
-
return (0, runtime_1.makeRuntimeException)('http-request', { url, method, status,
|
|
26
|
+
function makeHTTPException(url, method, status, params) {
|
|
27
|
+
return (0, runtime_1.makeRuntimeException)('http-request', { url, method, status, ...params }, {});
|
|
28
|
+
}
|
|
29
|
+
function makeMalformedReplyHTTPException({ url, method, status }, params) {
|
|
30
|
+
return (0, runtime_1.makeRuntimeException)('http-request', { url, method, status, ...params }, { malformedResponse: true });
|
|
31
|
+
}
|
|
32
|
+
function makeUnexpectedStatusHTTPException({ url, method, status }, params) {
|
|
33
|
+
return (0, runtime_1.makeRuntimeException)('http-request', { url, method, status, ...params }, { unexpectedStatus: true });
|
|
26
34
|
}
|
|
27
35
|
Object.freeze(exports);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Layout } from 'xsp-files';
|
|
2
2
|
import { DiffInfo } from '../service-api/3nstorage/owner';
|
|
3
|
-
import { ObjVersionFile } from './obj-file';
|
|
3
|
+
import { ObjVersionFile } from './obj-version-file';
|
|
4
4
|
import { Readable } from 'stream';
|
|
5
5
|
export declare function diffToLayout(diff: DiffInfo): Layout;
|
|
6
6
|
export interface ChunkWithHeader {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*
|
|
3
|
-
Copyright (C) 2022 3NSoft Inc.
|
|
3
|
+
Copyright (C) 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
|
|
@@ -52,9 +52,15 @@ class ProcessingPool {
|
|
|
52
52
|
}
|
|
53
53
|
let proc = undefined;
|
|
54
54
|
try {
|
|
55
|
-
|
|
55
|
+
let continueRun = false;
|
|
56
|
+
proc = task.process().then(done => {
|
|
57
|
+
continueRun = !done;
|
|
58
|
+
}, this.doOnError);
|
|
56
59
|
this.inProcess.add(proc);
|
|
57
60
|
await proc;
|
|
61
|
+
if (continueRun) {
|
|
62
|
+
this.queue.unshift(task);
|
|
63
|
+
}
|
|
58
64
|
}
|
|
59
65
|
catch (err) {
|
|
60
66
|
await this.doOnError(err);
|