core-3nweb-client-lib 0.43.2 → 0.43.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.
- package/build/api-defs/files.d.ts +60 -0
- package/build/core/asmail/inbox/msg-indexing/sql-indexing.js +2 -2
- package/build/lib-client/ws-utils.js +13 -4
- package/build/lib-client/xsp-fs/folder-node.d.ts +1 -1
- package/build/lib-client/xsp-fs/folder-node.js +3 -3
- package/build/lib-client/xsp-fs/node-in-fs.d.ts +1 -1
- package/build/lib-client/xsp-fs/node-in-fs.js +55 -18
- package/build/lib-common/ipc/ws-ipc.js +1 -4
- package/package.json +3 -3
|
@@ -77,6 +77,7 @@ declare namespace web3n.files {
|
|
|
77
77
|
removedOnServer?: true;
|
|
78
78
|
versionMismatch?: true;
|
|
79
79
|
conflict?: true;
|
|
80
|
+
isBehind?: true;
|
|
80
81
|
notSynced?: true;
|
|
81
82
|
remoteIsArchived?: true;
|
|
82
83
|
remoteFolderItemNotFound?: true;
|
|
@@ -497,6 +498,9 @@ declare namespace web3n.files {
|
|
|
497
498
|
flags?: VersionedReadFlags
|
|
498
499
|
): Promise<{ current?: number; archived?: number[]; }>;
|
|
499
500
|
|
|
501
|
+
/**
|
|
502
|
+
* File from synced storage has this api
|
|
503
|
+
*/
|
|
500
504
|
sync?: ReadonlyFileSyncAPI;
|
|
501
505
|
|
|
502
506
|
}
|
|
@@ -567,6 +571,9 @@ declare namespace web3n.files {
|
|
|
567
571
|
|
|
568
572
|
archiveCurrent(version?: number): Promise<number>;
|
|
569
573
|
|
|
574
|
+
/**
|
|
575
|
+
* File from synced storage has this api
|
|
576
|
+
*/
|
|
570
577
|
sync?: WritableFileSyncAPI;
|
|
571
578
|
|
|
572
579
|
}
|
|
@@ -580,12 +587,24 @@ declare namespace web3n.files {
|
|
|
580
587
|
*/
|
|
581
588
|
status(skipServerCheck?: boolean): Promise<SyncStatus>;
|
|
582
589
|
|
|
590
|
+
/**
|
|
591
|
+
* Returns a state of on-disk cache.
|
|
592
|
+
* @param version
|
|
593
|
+
*/
|
|
583
594
|
isRemoteVersionOnDisk(
|
|
584
595
|
version: number
|
|
585
596
|
): Promise<'partial'|'complete'|'none'>;
|
|
586
597
|
|
|
598
|
+
/**
|
|
599
|
+
* This downloads bytes onto disk, skipping decryption, as file content isn't read here.
|
|
600
|
+
* @param version
|
|
601
|
+
*/
|
|
587
602
|
download(version: number): Promise<void>;
|
|
588
603
|
|
|
604
|
+
/**
|
|
605
|
+
* Adopts remote version.
|
|
606
|
+
* @param opts options let one to pass exact remote version, to trigger download.
|
|
607
|
+
*/
|
|
589
608
|
adoptRemote(opts?: OptionsToAdopteRemote): Promise<void>;
|
|
590
609
|
|
|
591
610
|
}
|
|
@@ -598,6 +617,10 @@ declare namespace web3n.files {
|
|
|
598
617
|
|
|
599
618
|
interface WritableFileSyncAPI extends ReadonlyFileSyncAPI {
|
|
600
619
|
|
|
620
|
+
/**
|
|
621
|
+
* Upload in conflicting and behind state of sync requires explicit upload version.
|
|
622
|
+
* @param opts
|
|
623
|
+
*/
|
|
601
624
|
upload(opts?: OptionsToUploadLocal): Promise<number|undefined>;
|
|
602
625
|
|
|
603
626
|
}
|
|
@@ -1106,6 +1129,9 @@ declare namespace web3n.files {
|
|
|
1106
1129
|
path: string
|
|
1107
1130
|
): Promise<{ current?: number; archived?: number[]; }>;
|
|
1108
1131
|
|
|
1132
|
+
/**
|
|
1133
|
+
* Folder/FS from synced storage has this api
|
|
1134
|
+
*/
|
|
1109
1135
|
sync?: ReadonlyFSSyncAPI;
|
|
1110
1136
|
|
|
1111
1137
|
}
|
|
@@ -1169,6 +1195,9 @@ declare namespace web3n.files {
|
|
|
1169
1195
|
|
|
1170
1196
|
archiveCurrent(path: string, version?: number): Promise<number>;
|
|
1171
1197
|
|
|
1198
|
+
/**
|
|
1199
|
+
* Folder/FS from synced storage has this api
|
|
1200
|
+
*/
|
|
1172
1201
|
sync?: WritableFSSyncAPI;
|
|
1173
1202
|
|
|
1174
1203
|
}
|
|
@@ -1183,14 +1212,33 @@ declare namespace web3n.files {
|
|
|
1183
1212
|
*/
|
|
1184
1213
|
status(path: string, skipServerCheck?: boolean): Promise<SyncStatus>;
|
|
1185
1214
|
|
|
1215
|
+
/**
|
|
1216
|
+
* Returns a state of on-disk cache of an item in fs.
|
|
1217
|
+
* @param version
|
|
1218
|
+
*/
|
|
1186
1219
|
isRemoteVersionOnDisk(
|
|
1187
1220
|
path: string, version: number
|
|
1188
1221
|
): Promise<'partial'|'complete'|'none'>;
|
|
1189
1222
|
|
|
1223
|
+
/**
|
|
1224
|
+
* This downloads bytes onto disk, skipping decryption, as item's content isn't read here.
|
|
1225
|
+
* @param path
|
|
1226
|
+
* @param version
|
|
1227
|
+
*/
|
|
1190
1228
|
download(path: string, version: number): Promise<void>;
|
|
1191
1229
|
|
|
1230
|
+
/**
|
|
1231
|
+
* Adopts remote version of fs object at given path
|
|
1232
|
+
* @param path
|
|
1233
|
+
* @param opts options let one to pass exact remote version, to trigger download.
|
|
1234
|
+
*/
|
|
1192
1235
|
adoptRemote(path: string, opts?: OptionsToAdopteRemote): Promise<void>;
|
|
1193
1236
|
|
|
1237
|
+
/**
|
|
1238
|
+
* Calculates diff between current local and remote states of folder at given path.
|
|
1239
|
+
* @param path
|
|
1240
|
+
* @param remoteVersion
|
|
1241
|
+
*/
|
|
1194
1242
|
diffCurrentAndRemoteFolderVersions(
|
|
1195
1243
|
path: string, remoteVersion?: number
|
|
1196
1244
|
): Promise<FolderDiff|undefined>;
|
|
@@ -1222,10 +1270,22 @@ declare namespace web3n.files {
|
|
|
1222
1270
|
|
|
1223
1271
|
interface WritableFSSyncAPI extends ReadonlyFSSyncAPI {
|
|
1224
1272
|
|
|
1273
|
+
/**
|
|
1274
|
+
* Upload in conflicting and behind state of sync requires explicit upload version.
|
|
1275
|
+
* @param path
|
|
1276
|
+
* @param opts
|
|
1277
|
+
*/
|
|
1225
1278
|
upload(
|
|
1226
1279
|
path: string, opts?: OptionsToUploadLocal
|
|
1227
1280
|
): Promise<number|undefined>;
|
|
1228
1281
|
|
|
1282
|
+
/**
|
|
1283
|
+
* This method is for resolving conflicts on folders.
|
|
1284
|
+
* It adopts some folder items, and not the whole folder state.
|
|
1285
|
+
* @param path
|
|
1286
|
+
* @param itemName
|
|
1287
|
+
* @param opts
|
|
1288
|
+
*/
|
|
1229
1289
|
adoptRemoteFolderItem(
|
|
1230
1290
|
path: string, itemName: string, opts?: OptionsToAdoptRemoteItem
|
|
1231
1291
|
): Promise<number>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*
|
|
3
|
-
Copyright (C) 2022 - 2023 3NSoft Inc.
|
|
3
|
+
Copyright (C) 2022 - 2023, 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
|
|
@@ -211,7 +211,7 @@ class SqliteFiles {
|
|
|
211
211
|
(0, file_1.ensureCorrectFS)(syncedFS, 'synced', true);
|
|
212
212
|
const files = new SqliteFiles(syncedFS);
|
|
213
213
|
const records = await files.makeRecords();
|
|
214
|
-
files.startSyncing();
|
|
214
|
+
// files.startSyncing();
|
|
215
215
|
return { files, records };
|
|
216
216
|
}
|
|
217
217
|
async makeRecords() {
|
|
@@ -28,8 +28,11 @@ function openSocket(url, sessionId) {
|
|
|
28
28
|
const headers = {};
|
|
29
29
|
headers[request_utils_1.SESSION_ID_HEADER] = sessionId;
|
|
30
30
|
const ws = new WebSocket(url, { headers, agent: https_1.globalAgent });
|
|
31
|
-
|
|
32
|
-
const initOnError = (err) =>
|
|
31
|
+
let opening = (0, deferred_1.defer)();
|
|
32
|
+
const initOnError = (err) => {
|
|
33
|
+
opening === null || opening === void 0 ? void 0 : opening.reject((0, http_1.makeConnectionException)(url, undefined, `WebSocket connection error: ${err.message}`));
|
|
34
|
+
opening = undefined;
|
|
35
|
+
};
|
|
33
36
|
const onNonOkReply = (req, res) => {
|
|
34
37
|
const errReply = {
|
|
35
38
|
url,
|
|
@@ -37,7 +40,8 @@ function openSocket(url, sessionId) {
|
|
|
37
40
|
status: res.statusCode,
|
|
38
41
|
data: undefined
|
|
39
42
|
};
|
|
40
|
-
opening.resolve(errReply);
|
|
43
|
+
opening === null || opening === void 0 ? void 0 : opening.resolve(errReply);
|
|
44
|
+
opening = undefined;
|
|
41
45
|
};
|
|
42
46
|
ws.on('error', initOnError);
|
|
43
47
|
ws.on('unexpected-response', onNonOkReply);
|
|
@@ -48,10 +52,15 @@ function openSocket(url, sessionId) {
|
|
|
48
52
|
status: 200,
|
|
49
53
|
data: ws
|
|
50
54
|
};
|
|
51
|
-
opening.resolve(okReply);
|
|
55
|
+
opening === null || opening === void 0 ? void 0 : opening.resolve(okReply);
|
|
56
|
+
opening = undefined;
|
|
52
57
|
ws.removeListener('error', initOnError);
|
|
53
58
|
ws.removeListener('unexpected-response', onNonOkReply);
|
|
54
59
|
});
|
|
60
|
+
ws.on('error', err => {
|
|
61
|
+
// XXX we need
|
|
62
|
+
console.error(`Error in ${ws.url} connection`, err);
|
|
63
|
+
});
|
|
55
64
|
return opening.promise;
|
|
56
65
|
}
|
|
57
66
|
Object.freeze(exports);
|
|
@@ -145,7 +145,7 @@ export declare class FolderNode extends NodeInFS<FolderPersistance> {
|
|
|
145
145
|
upload(opts: OptionsToUploadLocal | undefined): Promise<number | undefined>;
|
|
146
146
|
private uploadRemovalOf;
|
|
147
147
|
private listRemovedInTreeToUploadRm;
|
|
148
|
-
protected needUpload(
|
|
148
|
+
protected needUpload(opts: OptionsToUploadLocal | undefined): Promise<{
|
|
149
149
|
localVersion: number;
|
|
150
150
|
uploadVersion: number;
|
|
151
151
|
createOnRemote: boolean;
|
|
@@ -788,7 +788,7 @@ class FolderNode extends node_in_fs_1.NodeInFS {
|
|
|
788
788
|
}
|
|
789
789
|
async upload(opts) {
|
|
790
790
|
try {
|
|
791
|
-
const toUpload = await this.needUpload(opts
|
|
791
|
+
const toUpload = await this.needUpload(opts);
|
|
792
792
|
if (!toUpload) {
|
|
793
793
|
return;
|
|
794
794
|
}
|
|
@@ -848,8 +848,8 @@ class FolderNode extends node_in_fs_1.NodeInFS {
|
|
|
848
848
|
return node.objId;
|
|
849
849
|
}
|
|
850
850
|
}
|
|
851
|
-
async needUpload(
|
|
852
|
-
const toUpload = await super.needUpload(
|
|
851
|
+
async needUpload(opts) {
|
|
852
|
+
const toUpload = await super.needUpload(opts);
|
|
853
853
|
if (!toUpload) {
|
|
854
854
|
return;
|
|
855
855
|
}
|
|
@@ -77,7 +77,7 @@ export declare abstract class NodeInFS<P extends NodePersistance> implements Nod
|
|
|
77
77
|
download(version: number): Promise<void>;
|
|
78
78
|
protected abstract setCurrentStateFrom(src: ObjSource): Promise<void>;
|
|
79
79
|
adoptRemote(opts: OptionsToAdopteRemote | undefined): Promise<void>;
|
|
80
|
-
protected needUpload(
|
|
80
|
+
protected needUpload(opts: OptionsToUploadLocal | undefined): Promise<{
|
|
81
81
|
localVersion: number;
|
|
82
82
|
uploadVersion: number;
|
|
83
83
|
createOnRemote: boolean;
|
|
@@ -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
|
|
@@ -337,8 +337,10 @@ class NodeInFS {
|
|
|
337
337
|
}
|
|
338
338
|
});
|
|
339
339
|
}
|
|
340
|
-
async needUpload(
|
|
341
|
-
|
|
340
|
+
async needUpload(opts) {
|
|
341
|
+
var _a;
|
|
342
|
+
const { local, remote, synced, state } = await this.syncStatus();
|
|
343
|
+
let localVersion = opts === null || opts === void 0 ? void 0 : opts.localVersion;
|
|
342
344
|
if (localVersion) {
|
|
343
345
|
if (localVersion !== this.currentVersion) {
|
|
344
346
|
throw (0, exceptions_1.makeFSSyncException)(this.name, {
|
|
@@ -349,8 +351,8 @@ class NodeInFS {
|
|
|
349
351
|
}
|
|
350
352
|
if (!local || (local.latest !== localVersion)) {
|
|
351
353
|
throw (0, exceptions_1.makeFSSyncException)(this.name, {
|
|
352
|
-
|
|
353
|
-
message: `
|
|
354
|
+
versionNotFound: true,
|
|
355
|
+
message: `There is no local version ${localVersion} to upload`
|
|
354
356
|
});
|
|
355
357
|
}
|
|
356
358
|
}
|
|
@@ -360,38 +362,73 @@ class NodeInFS {
|
|
|
360
362
|
}
|
|
361
363
|
localVersion = this.currentVersion;
|
|
362
364
|
}
|
|
363
|
-
if (remote) {
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
365
|
+
if ((remote && !remote.latest) || (synced && !synced.latest)) {
|
|
366
|
+
throw (0, exceptions_1.makeFSSyncException)(this.name, {
|
|
367
|
+
versionMismatch: true,
|
|
368
|
+
removedOnServer: true
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
let uploadVersion = opts === null || opts === void 0 ? void 0 : opts.uploadVersion;
|
|
372
|
+
if (state === 'unsynced') {
|
|
373
|
+
if (uploadVersion) {
|
|
374
|
+
if (((synced === null || synced === void 0 ? void 0 : synced.latest) && ((synced.latest + 1) !== uploadVersion))) {
|
|
375
|
+
throw (0, exceptions_1.makeFSSyncException)(this.name, {
|
|
376
|
+
versionMismatch: true,
|
|
377
|
+
message: `Given uploadVersion is ${uploadVersion} is not a +1 increment over synced version ${(_a = synced.latest) !== null && _a !== void 0 ? _a : 0}, in unsynced state.`
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
382
|
+
uploadVersion = (synced === null || synced === void 0 ? void 0 : synced.latest) ? ((synced === null || synced === void 0 ? void 0 : synced.latest) + 1) : 1;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
else if (state === 'conflicting') {
|
|
386
|
+
if (uploadVersion) {
|
|
387
|
+
if (uploadVersion <= remote.latest) {
|
|
388
|
+
throw (0, exceptions_1.makeFSSyncException)(this.name, {
|
|
389
|
+
versionMismatch: true,
|
|
390
|
+
conflict: true,
|
|
391
|
+
message: `Given upload version ${uploadVersion} is not greater than remote version ${remote === null || remote === void 0 ? void 0 : remote.latest}.`
|
|
392
|
+
});
|
|
393
|
+
}
|
|
367
394
|
}
|
|
368
395
|
else {
|
|
369
396
|
throw (0, exceptions_1.makeFSSyncException)(this.name, {
|
|
370
397
|
versionMismatch: true,
|
|
371
|
-
|
|
398
|
+
conflict: true,
|
|
399
|
+
message: `Upload version is not given during upload from conflicting state.`
|
|
372
400
|
});
|
|
373
401
|
}
|
|
374
402
|
}
|
|
375
|
-
else if (
|
|
376
|
-
if (
|
|
377
|
-
|
|
378
|
-
|
|
403
|
+
else if (state === 'behind') {
|
|
404
|
+
if (uploadVersion) {
|
|
405
|
+
if (uploadVersion <= remote.latest) {
|
|
406
|
+
throw (0, exceptions_1.makeFSSyncException)(this.name, {
|
|
407
|
+
versionMismatch: true,
|
|
408
|
+
isBehind: true,
|
|
409
|
+
message: `Given upload version ${uploadVersion} is not greater than remote version ${remote === null || remote === void 0 ? void 0 : remote.latest}.`
|
|
410
|
+
});
|
|
411
|
+
}
|
|
379
412
|
}
|
|
380
413
|
else {
|
|
381
414
|
throw (0, exceptions_1.makeFSSyncException)(this.name, {
|
|
382
415
|
versionMismatch: true,
|
|
383
|
-
|
|
416
|
+
isBehind: true,
|
|
417
|
+
message: `Upload version is not given during upload when synced state is behind remote.`
|
|
384
418
|
});
|
|
385
419
|
}
|
|
386
420
|
}
|
|
421
|
+
else if (state === 'synced') {
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
387
424
|
else {
|
|
388
|
-
|
|
389
|
-
return { createOnRemote: true, localVersion, uploadVersion };
|
|
425
|
+
throw new Error(`Unrecognized sync state ${state}`);
|
|
390
426
|
}
|
|
427
|
+
return { createOnRemote: (uploadVersion === 1), localVersion, uploadVersion };
|
|
391
428
|
}
|
|
392
429
|
async upload(opts) {
|
|
393
430
|
try {
|
|
394
|
-
const toUpload = await this.needUpload(opts
|
|
431
|
+
const toUpload = await this.needUpload(opts);
|
|
395
432
|
if (!toUpload) {
|
|
396
433
|
return;
|
|
397
434
|
}
|
|
@@ -38,15 +38,12 @@ function makeJsonCommPoint(ws) {
|
|
|
38
38
|
const observers = new generic_ipc_1.MultiObserverWrap();
|
|
39
39
|
const { heartbeat, healthyBeat, otherBeat } = makeHeartbeat(ws.url);
|
|
40
40
|
ws.on('message', data => {
|
|
41
|
-
if (typeof data !== 'string') {
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
41
|
if (observers.done) {
|
|
45
42
|
return;
|
|
46
43
|
}
|
|
47
44
|
let env;
|
|
48
45
|
try {
|
|
49
|
-
env = JSON.parse(data);
|
|
46
|
+
env = JSON.parse(data.toString('utf8'));
|
|
50
47
|
}
|
|
51
48
|
catch (err) {
|
|
52
49
|
ws.close();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "core-3nweb-client-lib",
|
|
3
|
-
"version": "0.43.
|
|
3
|
+
"version": "0.43.4",
|
|
4
4
|
"description": "3NWeb client core library, embeddable into different environments",
|
|
5
5
|
"main": "build/lib-index.js",
|
|
6
6
|
"types": "build/lib-index.d.ts",
|
|
@@ -32,13 +32,13 @@
|
|
|
32
32
|
"protobufjs": "^7.0.1",
|
|
33
33
|
"punycode": "^2.1.1",
|
|
34
34
|
"rxjs": "^7.5.7",
|
|
35
|
-
"ws": "^
|
|
35
|
+
"ws": "^8.18.3",
|
|
36
36
|
"xsp-files": "^4.2.1"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@types/jasmine": "^3.9.1",
|
|
40
40
|
"@types/node": "^16.11.7",
|
|
41
|
-
"@types/ws": "^
|
|
41
|
+
"@types/ws": "^8.18.1",
|
|
42
42
|
"jasmine": "^3.9.0",
|
|
43
43
|
"protobufjs-cli": "^1.0.2",
|
|
44
44
|
"spec-3nweb-server": "^1.8.0",
|