core-3nweb-client-lib 0.50.2 → 0.50.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/asmail.d.ts +2 -0
- package/build/core/asmail/inbox/inbox-events.js +7 -10
- package/build/core/asmail/inbox/index.js +10 -3
- package/build/core/asmail/inbox/msg-downloader.d.ts +1 -1
- package/build/core/asmail/inbox/msg-downloader.js +15 -2
- package/build/core/asmail/inbox/msg-indexing/dataset/v1/sql-db.js +1 -1
- package/build/lib-client/asmail/recipient.d.ts +2 -1
- package/build/lib-client/asmail/recipient.js +18 -2
- package/build/lib-common/service-api/asmail/retrieval.d.ts +2 -1
- package/build/lib-common/service-api/asmail/retrieval.js +15 -10
- package/package.json +1 -1
|
@@ -87,16 +87,13 @@ class InboxEvents {
|
|
|
87
87
|
async whenConnected() {
|
|
88
88
|
return this.msgReceiver.connectedState.whenStateIsSet();
|
|
89
89
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
// await this.rmMsg(msgId).catch(noop);
|
|
98
|
-
await this.logError(err, `Cannot get message ${msgId}`);
|
|
99
|
-
}
|
|
90
|
+
getMessage(msgId) {
|
|
91
|
+
return this.getMsg(msgId).catch(async (exc) => {
|
|
92
|
+
if ((exc.type === 'connect') || (exc.type === 'inbox')) {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
await this.logError(exc, `Cannot get message ${msgId}`);
|
|
96
|
+
});
|
|
100
97
|
}
|
|
101
98
|
subscribe(event, observer) {
|
|
102
99
|
if (event === 'message') {
|
|
@@ -83,7 +83,7 @@ async function makeInboxOnServer(cachePath, syncedFS, localFS, r) {
|
|
|
83
83
|
if (msgOnDisk) {
|
|
84
84
|
return msgOnDisk;
|
|
85
85
|
}
|
|
86
|
-
const meta = await downloader.getMsgMeta(msgId);
|
|
86
|
+
const meta = await downloader.getMsgMeta(msgId, false);
|
|
87
87
|
return await cache.addMsg(msgId, meta);
|
|
88
88
|
}
|
|
89
89
|
function checkerOfMidKeyCerts(deliveryTS) {
|
|
@@ -201,7 +201,9 @@ async function makeInboxOnServer(cachePath, syncedFS, localFS, r) {
|
|
|
201
201
|
}
|
|
202
202
|
await Promise.all(msgIds.map(msgId => startCachingAndAddKeyToIndex(msgId)
|
|
203
203
|
.catch(async (exc) => {
|
|
204
|
-
|
|
204
|
+
if (!exc.incompleteDelivery && !exc.msgNotFound) {
|
|
205
|
+
await logError(exc, `Failed to start caching message ${msgId}`);
|
|
206
|
+
}
|
|
205
207
|
})));
|
|
206
208
|
return index.listMsgs(fromTS);
|
|
207
209
|
});
|
|
@@ -220,7 +222,12 @@ async function makeInboxOnServer(cachePath, syncedFS, localFS, r) {
|
|
|
220
222
|
return [];
|
|
221
223
|
}
|
|
222
224
|
// cache and index these
|
|
223
|
-
await Promise.all(msgIds.map(msgId => startCachingAndAddKeyToIndex(msgId)
|
|
225
|
+
await Promise.all(msgIds.map(msgId => startCachingAndAddKeyToIndex(msgId)
|
|
226
|
+
.catch(async (exc) => {
|
|
227
|
+
if (!exc.incompleteDelivery && !exc.msgNotFound) {
|
|
228
|
+
await logError(exc, `Failed to start caching message ${msgId}`);
|
|
229
|
+
}
|
|
230
|
+
})));
|
|
224
231
|
// get info's from index, focusing on specific messages only
|
|
225
232
|
return (await index.listMsgs(fromTS)).filter(({ msgId }) => msgIds.includes(msgId));
|
|
226
233
|
}
|
|
@@ -5,7 +5,7 @@ export declare class MsgDownloader {
|
|
|
5
5
|
private readonly msgReceiver;
|
|
6
6
|
private readonly runner;
|
|
7
7
|
constructor(msgReceiver: MailRecipient);
|
|
8
|
-
getMsgMeta(msgId: string): Promise<MsgMeta>;
|
|
8
|
+
getMsgMeta(msgId: string, allowIncomplete: boolean): Promise<MsgMeta>;
|
|
9
9
|
getObjDownloader(msgId: string): ObjDownloader;
|
|
10
10
|
private getLayoutWithHeaderAndFirstSegs;
|
|
11
11
|
private getSegs;
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
*/
|
|
18
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
19
|
exports.MsgDownloader = void 0;
|
|
20
|
+
const recipient_1 = require("../../../lib-client/asmail/recipient");
|
|
20
21
|
const obj_on_disk_1 = require("../../../lib-client/objs-on-disk/obj-on-disk");
|
|
21
22
|
const MAX_GETTING_CHUNK = 512 * 1024;
|
|
22
23
|
const DOWNLOAD_START_CHUNK = 128 * 1024;
|
|
@@ -26,8 +27,19 @@ class MsgDownloader {
|
|
|
26
27
|
this.runner = new obj_on_disk_1.DownloadsRunner();
|
|
27
28
|
Object.freeze(this);
|
|
28
29
|
}
|
|
29
|
-
getMsgMeta(msgId) {
|
|
30
|
-
return this.msgReceiver.getMsgMeta(msgId)
|
|
30
|
+
async getMsgMeta(msgId, allowIncomplete) {
|
|
31
|
+
return await this.msgReceiver.getMsgMeta(msgId, allowIncomplete)
|
|
32
|
+
.catch(async (exc) => {
|
|
33
|
+
if (exc.incompleteDelivery) {
|
|
34
|
+
// cleanout old incomplete messages
|
|
35
|
+
const deliveryStart = exc.deliveryStart;
|
|
36
|
+
if (!(Math.abs(Date.now() - deliveryStart) < 12 * 60 * 60 * 1000)) {
|
|
37
|
+
await this.msgReceiver.removeMsg(msgId).catch(noop);
|
|
38
|
+
throw (0, recipient_1.makeMsgNotFoundException)(msgId);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
throw exc;
|
|
42
|
+
});
|
|
31
43
|
}
|
|
32
44
|
getObjDownloader(msgId) {
|
|
33
45
|
return {
|
|
@@ -52,4 +64,5 @@ class MsgDownloader {
|
|
|
52
64
|
exports.MsgDownloader = MsgDownloader;
|
|
53
65
|
Object.freeze(MsgDownloader.prototype);
|
|
54
66
|
Object.freeze(MsgDownloader);
|
|
67
|
+
function noop() { }
|
|
55
68
|
Object.freeze(exports);
|
|
@@ -192,7 +192,7 @@ async function setMsgIndexInfoIntoAttrOf(dbFile, info) {
|
|
|
192
192
|
});
|
|
193
193
|
}
|
|
194
194
|
function dbFileName(shardTS) {
|
|
195
|
-
return (shardTS ?
|
|
195
|
+
return (shardTS ? `${shardTS}${DB_EXT}` : LATEST_DB);
|
|
196
196
|
}
|
|
197
197
|
function shardTSFromFileName(fName) {
|
|
198
198
|
if (fName.endsWith(DB_EXT)) {
|
|
@@ -5,6 +5,7 @@ import { SubscribingClient } from '../../lib-common/ipc/ws-ipc';
|
|
|
5
5
|
type InboxException = web3n.asmail.InboxException;
|
|
6
6
|
type Observer<T> = web3n.Observer<T>;
|
|
7
7
|
export declare function makeMsgNotFoundException(msgId: string): InboxException;
|
|
8
|
+
export declare function makeMsgIncompleteException(msgId: string, deliveryStart: number): InboxException;
|
|
8
9
|
export declare function makeFailToDecryptMsgException(msgId: string): InboxException;
|
|
9
10
|
export declare function makeObjNotFoundException(msgId: string, objId: string): InboxException;
|
|
10
11
|
export declare function makeMsgIsBrokenException(msgId: string): InboxException;
|
|
@@ -12,7 +13,7 @@ export declare class MailRecipient extends ServiceUser {
|
|
|
12
13
|
constructor(user: string, getSigner: IGetMailerIdSigner, mainUrlGetter: () => Promise<string>, net: NetClient);
|
|
13
14
|
getNet(): NetClient;
|
|
14
15
|
listMsgs(fromTS: number | undefined): Promise<api.listMsgs.Reply>;
|
|
15
|
-
getMsgMeta(msgId: string): Promise<api.MsgMeta>;
|
|
16
|
+
getMsgMeta(msgId: string, allowIncomplete: boolean): Promise<api.MsgMeta>;
|
|
16
17
|
/**
|
|
17
18
|
* This method returns either first part of message object, or a whole of it,
|
|
18
19
|
* depending on a given limit for segments. Returned promise resolves to a
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
19
|
exports.MailRecipient = void 0;
|
|
20
20
|
exports.makeMsgNotFoundException = makeMsgNotFoundException;
|
|
21
|
+
exports.makeMsgIncompleteException = makeMsgIncompleteException;
|
|
21
22
|
exports.makeFailToDecryptMsgException = makeFailToDecryptMsgException;
|
|
22
23
|
exports.makeObjNotFoundException = makeObjNotFoundException;
|
|
23
24
|
exports.makeMsgIsBrokenException = makeMsgIsBrokenException;
|
|
@@ -38,6 +39,17 @@ function makeMsgNotFoundException(msgId) {
|
|
|
38
39
|
};
|
|
39
40
|
return exc;
|
|
40
41
|
}
|
|
42
|
+
function makeMsgIncompleteException(msgId, deliveryStart) {
|
|
43
|
+
const exc = {
|
|
44
|
+
runtimeException: true,
|
|
45
|
+
type: 'inbox',
|
|
46
|
+
msgId,
|
|
47
|
+
incompleteDelivery: true,
|
|
48
|
+
deliveryStart,
|
|
49
|
+
stack: (0, runtime_1.getStackHere)(1)
|
|
50
|
+
};
|
|
51
|
+
return exc;
|
|
52
|
+
}
|
|
41
53
|
function makeFailToDecryptMsgException(msgId) {
|
|
42
54
|
const exc = {
|
|
43
55
|
runtimeException: true,
|
|
@@ -98,14 +110,18 @@ class MailRecipient extends user_with_mid_session_1.ServiceUser {
|
|
|
98
110
|
throw (0, http_1.makeUnexpectedStatusHTTPException)(rep);
|
|
99
111
|
}
|
|
100
112
|
}
|
|
101
|
-
async getMsgMeta(msgId) {
|
|
113
|
+
async getMsgMeta(msgId, allowIncomplete) {
|
|
102
114
|
const rep = await this.doBodylessSessionRequest({
|
|
103
115
|
appPath: api.msgMetadata.genUrlEnd(msgId),
|
|
104
116
|
method: 'GET',
|
|
105
117
|
responseType: 'json'
|
|
106
118
|
});
|
|
107
119
|
if (rep.status === api.msgMetadata.SC.ok) {
|
|
108
|
-
|
|
120
|
+
if (!rep.data.deliveryCompletion && !allowIncomplete) {
|
|
121
|
+
const { deliveryStart } = rep.data;
|
|
122
|
+
throw makeMsgIncompleteException(msgId, deliveryStart);
|
|
123
|
+
}
|
|
124
|
+
const { meta, errMsg } = api.sanitizedMeta(rep.data, allowIncomplete);
|
|
109
125
|
if (!meta) {
|
|
110
126
|
throw (0, http_1.makeMalformedReplyHTTPException)(rep, {
|
|
111
127
|
message: `Malformed message metadata in a server response: ${errMsg}`
|
|
@@ -74,8 +74,9 @@ export declare namespace msgMetadata {
|
|
|
74
74
|
* This function returns either a checked version of given meta object, if it
|
|
75
75
|
* passes as message meta, or undefined, otherwise.
|
|
76
76
|
* @param meta is an object that is expected to be message meta
|
|
77
|
+
* @param allowIncomplete
|
|
77
78
|
*/
|
|
78
|
-
export declare function sanitizedMeta(meta: MsgMeta): {
|
|
79
|
+
export declare function sanitizedMeta(meta: MsgMeta, allowIncomplete: boolean): {
|
|
79
80
|
meta?: MsgMeta;
|
|
80
81
|
errMsg?: string;
|
|
81
82
|
};
|
|
@@ -94,21 +94,26 @@ Object.freeze(msgMetadata);
|
|
|
94
94
|
* This function returns either a checked version of given meta object, if it
|
|
95
95
|
* passes as message meta, or undefined, otherwise.
|
|
96
96
|
* @param meta is an object that is expected to be message meta
|
|
97
|
+
* @param allowIncomplete
|
|
97
98
|
*/
|
|
98
|
-
function sanitizedMeta(meta) {
|
|
99
|
+
function sanitizedMeta(meta, allowIncomplete) {
|
|
99
100
|
if (typeof meta !== 'object') {
|
|
100
101
|
return { errMsg: `is not a json object: ${JSON.stringify(meta)}` };
|
|
101
102
|
}
|
|
102
|
-
if (typeof meta.objs
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
103
|
+
if (typeof meta.objs === 'object') {
|
|
104
|
+
for (const objId of Object.keys(meta.objs)) {
|
|
105
|
+
const st = meta.objs[objId];
|
|
106
|
+
if (typeof st.size.header !== 'number') {
|
|
107
|
+
return { errMsg: `obj's header is not a number in: ${JSON.stringify(meta)}` };
|
|
108
|
+
}
|
|
109
|
+
if (st.completed && (st.size.segments === undefined)) {
|
|
110
|
+
return { errMsg: `obj's segments is not a number in: ${JSON.stringify(meta)}` };
|
|
111
|
+
}
|
|
109
112
|
}
|
|
110
|
-
|
|
111
|
-
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
if (!allowIncomplete) {
|
|
116
|
+
return { errMsg: `objs field is not an object in: ${JSON.stringify(meta)}` };
|
|
112
117
|
}
|
|
113
118
|
}
|
|
114
119
|
// TODO add more checks and return new object instead of a given one
|