internxt-crypto 0.0.14 → 1.0.0

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 (144) hide show
  1. package/README.md +44 -72
  2. package/dist/aes-B8TA-JKq.mjs +49 -0
  3. package/dist/aes-B8TA-JKq.mjs.map +1 -0
  4. package/dist/aes-CuW_SPl-.js +67 -0
  5. package/dist/aes-CuW_SPl-.js.map +1 -0
  6. package/dist/asymmetric-crypto.d.mts +8 -31
  7. package/dist/asymmetric-crypto.d.mts.map +1 -1
  8. package/dist/asymmetric-crypto.d.ts +8 -31
  9. package/dist/asymmetric-crypto.d.ts.map +1 -1
  10. package/dist/asymmetric-crypto.js +30 -7
  11. package/dist/asymmetric-crypto.js.map +1 -0
  12. package/dist/asymmetric-crypto.mjs +28 -2
  13. package/dist/asymmetric-crypto.mjs.map +1 -0
  14. package/dist/constants.d.mts +3 -10
  15. package/dist/constants.d.mts.map +1 -1
  16. package/dist/constants.d.ts +3 -10
  17. package/dist/constants.d.ts.map +1 -1
  18. package/dist/constants.js +3 -17
  19. package/dist/constants.js.map +1 -1
  20. package/dist/constants.mjs +3 -10
  21. package/dist/constants.mjs.map +1 -1
  22. package/dist/core-Bj26rNdA.js +227 -0
  23. package/dist/core-Bj26rNdA.js.map +1 -0
  24. package/dist/core-pEGygy6S.mjs +173 -0
  25. package/dist/core-pEGygy6S.mjs.map +1 -0
  26. package/dist/derive-key.d.mts +1 -74
  27. package/dist/derive-key.d.mts.map +1 -1
  28. package/dist/derive-key.d.ts +1 -74
  29. package/dist/derive-key.d.ts.map +1 -1
  30. package/dist/derive-key.js +3 -11
  31. package/dist/derive-key.mjs +2 -2
  32. package/dist/derive-password.d.mts +22 -0
  33. package/dist/derive-password.d.mts.map +1 -0
  34. package/dist/derive-password.d.ts +22 -0
  35. package/dist/derive-password.d.ts.map +1 -0
  36. package/dist/derive-password.js +5 -0
  37. package/dist/derive-password.mjs +3 -0
  38. package/dist/deriveKeysFromKey-C4McqO6_.js +47 -0
  39. package/dist/deriveKeysFromKey-C4McqO6_.js.map +1 -0
  40. package/dist/deriveKeysFromKey-DPU_h7wr.mjs +35 -0
  41. package/dist/deriveKeysFromKey-DPU_h7wr.mjs.map +1 -0
  42. package/dist/{deriveKeysFromPassword-BYaiSGKL.js → deriveKeysFromPassword-C7xAGGsh.js} +5 -172
  43. package/dist/deriveKeysFromPassword-C7xAGGsh.js.map +1 -0
  44. package/dist/{deriveKeysFromPassword-XIwzErlL.mjs → deriveKeysFromPassword-DXgSvTNC.mjs} +6 -125
  45. package/dist/deriveKeysFromPassword-DXgSvTNC.mjs.map +1 -0
  46. package/dist/email-crypto.d.mts +24 -46
  47. package/dist/email-crypto.d.mts.map +1 -1
  48. package/dist/email-crypto.d.ts +24 -46
  49. package/dist/email-crypto.d.ts.map +1 -1
  50. package/dist/email-crypto.js +121 -12
  51. package/dist/email-crypto.js.map +1 -0
  52. package/dist/email-crypto.mjs +115 -2
  53. package/dist/email-crypto.mjs.map +1 -0
  54. package/dist/email-search.d.mts.map +1 -1
  55. package/dist/email-search.d.ts.map +1 -1
  56. package/dist/email-search.js +25 -597
  57. package/dist/email-search.mjs +2 -573
  58. package/dist/{emailEncryptionKey-B9xHw1h_.mjs → emailEncryptionKey-BtSPYd9M.mjs} +22 -45
  59. package/dist/emailEncryptionKey-BtSPYd9M.mjs.map +1 -0
  60. package/dist/{emailEncryptionKey-CQNe5W_T.js → emailEncryptionKey-C4X1Bwy4.js} +22 -45
  61. package/dist/emailEncryptionKey-C4X1Bwy4.js.map +1 -0
  62. package/dist/{genID-3Er5IowC.mjs → genID-D08K7JPr.mjs} +4 -40
  63. package/dist/genID-D08K7JPr.mjs.map +1 -0
  64. package/dist/{genID-YJSl3YhL.js → genID-cWOPmspk.js} +2 -50
  65. package/dist/genID-cWOPmspk.js.map +1 -0
  66. package/dist/hash.d.mts +24 -36
  67. package/dist/hash.d.mts.map +1 -1
  68. package/dist/hash.d.ts +24 -36
  69. package/dist/hash.d.ts.map +1 -1
  70. package/dist/hash.js +88 -10
  71. package/dist/hash.js.map +1 -0
  72. package/dist/hash.mjs +82 -2
  73. package/dist/hash.mjs.map +1 -0
  74. package/dist/index.d.mts +9 -8
  75. package/dist/index.d.mts.map +1 -1
  76. package/dist/index.d.ts +9 -8
  77. package/dist/index.d.ts.map +1 -1
  78. package/dist/index.js +56 -79
  79. package/dist/index.mjs +13 -11
  80. package/dist/keystore-crypto.d.mts +6 -6
  81. package/dist/keystore-crypto.d.mts.map +1 -1
  82. package/dist/keystore-crypto.d.ts +6 -6
  83. package/dist/keystore-crypto.d.ts.map +1 -1
  84. package/dist/keystore-crypto.js +1 -1
  85. package/dist/keystore-crypto.mjs +1 -1
  86. package/dist/post-quantum-crypto.js +49 -4
  87. package/dist/post-quantum-crypto.js.map +1 -0
  88. package/dist/post-quantum-crypto.mjs +46 -2
  89. package/dist/post-quantum-crypto.mjs.map +1 -0
  90. package/dist/search-B9YM3XAA.mjs +587 -0
  91. package/dist/search-B9YM3XAA.mjs.map +1 -0
  92. package/dist/search-DUTm4-rN.js +731 -0
  93. package/dist/search-DUTm4-rN.js.map +1 -0
  94. package/dist/symmetric-crypto.d.mts +11 -40
  95. package/dist/symmetric-crypto.d.mts.map +1 -1
  96. package/dist/symmetric-crypto.d.ts +11 -40
  97. package/dist/symmetric-crypto.d.ts.map +1 -1
  98. package/dist/symmetric-crypto.js +2 -6
  99. package/dist/symmetric-crypto.mjs +2 -2
  100. package/dist/types.d.mts +13 -40
  101. package/dist/types.d.mts.map +1 -1
  102. package/dist/types.d.ts +13 -40
  103. package/dist/types.d.ts.map +1 -1
  104. package/dist/types.js.map +1 -1
  105. package/dist/types.mjs.map +1 -1
  106. package/dist/utils.d.mts +1 -19
  107. package/dist/utils.d.mts.map +1 -1
  108. package/dist/utils.d.ts +1 -19
  109. package/dist/utils.d.ts.map +1 -1
  110. package/dist/utils.js +1 -3
  111. package/dist/utils.mjs +2 -2
  112. package/dist/xwing-CQmQX6hn.mjs +16 -0
  113. package/dist/xwing-CQmQX6hn.mjs.map +1 -0
  114. package/dist/xwing-iRWVRtNE.js +34 -0
  115. package/dist/xwing-iRWVRtNE.js.map +1 -0
  116. package/package.json +3 -2
  117. package/dist/aes-DCb9dJqb.mjs +0 -161
  118. package/dist/aes-DCb9dJqb.mjs.map +0 -1
  119. package/dist/aes-DQo1MyCz.js +0 -203
  120. package/dist/aes-DQo1MyCz.js.map +0 -1
  121. package/dist/deriveKeysFromPassword-BYaiSGKL.js.map +0 -1
  122. package/dist/deriveKeysFromPassword-XIwzErlL.mjs.map +0 -1
  123. package/dist/email-search.js.map +0 -1
  124. package/dist/email-search.mjs.map +0 -1
  125. package/dist/emailEncryptionKey-B9xHw1h_.mjs.map +0 -1
  126. package/dist/emailEncryptionKey-CQNe5W_T.js.map +0 -1
  127. package/dist/emailKeys-C0KhtfNP.js +0 -572
  128. package/dist/emailKeys-C0KhtfNP.js.map +0 -1
  129. package/dist/emailKeys-D4lp9NRv.mjs +0 -488
  130. package/dist/emailKeys-D4lp9NRv.mjs.map +0 -1
  131. package/dist/genID-3Er5IowC.mjs.map +0 -1
  132. package/dist/genID-YJSl3YhL.js.map +0 -1
  133. package/dist/keys-BfcaiAOv.mjs +0 -90
  134. package/dist/keys-BfcaiAOv.mjs.map +0 -1
  135. package/dist/keys-CinT7kEY.js +0 -125
  136. package/dist/keys-CinT7kEY.js.map +0 -1
  137. package/dist/kyber768-SXnIo-Nw.mjs +0 -47
  138. package/dist/kyber768-SXnIo-Nw.mjs.map +0 -1
  139. package/dist/kyber768-WUVc2fIR.js +0 -65
  140. package/dist/kyber768-WUVc2fIR.js.map +0 -1
  141. package/dist/mac-BMb1F0dN.js +0 -170
  142. package/dist/mac-BMb1F0dN.js.map +0 -1
  143. package/dist/mac-ZpRlx8Fs.mjs +0 -116
  144. package/dist/mac-ZpRlx8Fs.mjs.map +0 -1
@@ -0,0 +1,731 @@
1
+ const require_chunk = require('./chunk-EbLFQX5m.js');
2
+ const require_constants = require('./constants.js');
3
+ const require_genID = require('./genID-cWOPmspk.js');
4
+ const require_deriveKeysFromKey = require('./deriveKeysFromKey-C4McqO6_.js');
5
+ const require_core = require('./core-Bj26rNdA.js');
6
+ let idb = require("idb");
7
+ let flexsearch = require("flexsearch");
8
+
9
+ //#region src/email-search/indexedDB.ts
10
+ /**
11
+ * Returns IndexedDB database name for the given user
12
+ *
13
+ * @param userID - The user ID
14
+ * @returns The database name
15
+ */
16
+ const getDatabaseName = (userID) => {
17
+ return `ES:${userID}:DB`;
18
+ };
19
+ /**
20
+ * Opens IndexedDB database for the given user
21
+ *
22
+ * @param userID - The user ID
23
+ * @returns The database
24
+ */
25
+ const openDatabase = async (userID) => {
26
+ try {
27
+ return (0, idb.openDB)(getDatabaseName(userID), require_constants.DB_VERSION, { upgrade(db) {
28
+ if (!db.objectStoreNames.contains(require_constants.DB_LABEL)) db.createObjectStore(require_constants.DB_LABEL, { keyPath: "id" }).createIndex("byTime", "params.createdAt");
29
+ } });
30
+ } catch (error) {
31
+ throw new Error(`Cannot open a database for the user ${userID}`, { cause: error });
32
+ }
33
+ };
34
+ /**
35
+ * Closes the IndexedDB database
36
+ *
37
+ * @param esDB - The database
38
+ */
39
+ const closeDatabase = (esDB) => {
40
+ return esDB.close();
41
+ };
42
+ /**
43
+ * Deletes IndexedDB database for the given user
44
+ *
45
+ * @param userID - The user ID
46
+ * @returns The database
47
+ */
48
+ const deleteDatabase = async (userID) => {
49
+ return (0, idb.deleteDB)(getDatabaseName(userID));
50
+ };
51
+ /**
52
+ * Derives database encryption key for the given user
53
+ *
54
+ * @param userID - The user ID
55
+ * @returns The symmetric key for protecting database
56
+ */
57
+ const deriveIndexKey = async (baseKey) => {
58
+ return require_deriveKeysFromKey.deriveSymmetricKeyFromContext(require_constants.CONTEXT_INDEX, baseKey);
59
+ };
60
+ /**
61
+ * Encrypts the given email and stores it in the IndexedDB database
62
+ *
63
+ * @param newEmailToStore - The email for storing
64
+ * @param indexKey - The symmetric key for protecting database
65
+ * @param esDB - The database
66
+ */
67
+ const encryptAndStoreEmail = async (newEmailToStore, indexKey, esDB) => {
68
+ try {
69
+ const encryptedEmail = {
70
+ encEmailBody: await require_core.encryptEmailBodyWithKey(newEmailToStore.body, indexKey),
71
+ params: newEmailToStore.params,
72
+ id: newEmailToStore.id
73
+ };
74
+ await esDB.put(require_constants.DB_LABEL, encryptedEmail);
75
+ } catch (error) {
76
+ throw new Error("Cannot encrypt and add the given email to the database", { cause: error });
77
+ }
78
+ };
79
+ /**
80
+ * Encrypts the given set of emails and stores it in the IndexedDB database
81
+ *
82
+ * @param newEmailsToStore - The set of emails for storing
83
+ * @param indexKey - The symmetric key key for protecting database
84
+ * @param esDB - The database
85
+ */
86
+ const encryptAndStoreManyEmail = async (newEmailsToStore, indexKey, esDB) => {
87
+ try {
88
+ const encryptedEmails = await Promise.all(newEmailsToStore.map(async (email) => {
89
+ return {
90
+ encEmailBody: await require_core.encryptEmailBodyWithKey(email.body, indexKey),
91
+ params: email.params,
92
+ id: email.id
93
+ };
94
+ }));
95
+ const tr = esDB.transaction(require_constants.DB_LABEL, "readwrite");
96
+ await Promise.all([...encryptedEmails.map((encEmail) => tr.store.put(encEmail)), tr.done]);
97
+ } catch (error) {
98
+ throw new Error("Cannot encrypt and add emails to the database", { cause: error });
99
+ }
100
+ };
101
+ /**
102
+ * Decrypts the given email
103
+ *
104
+ * @param indexKey - The symmetric key key for protecting database
105
+ * @param encryptedEmail - The encrypted email
106
+ * @returns The decrypted email
107
+ */
108
+ const decryptEmail = async (indexKey, encryptedEmail) => {
109
+ try {
110
+ return {
111
+ body: await require_core.decryptEmailBody(encryptedEmail.encEmailBody, indexKey),
112
+ params: encryptedEmail.params,
113
+ id: encryptedEmail.id
114
+ };
115
+ } catch (error) {
116
+ throw new Error("Cannot decrypt the given email", { cause: error });
117
+ }
118
+ };
119
+ /**
120
+ * Fetches the email from the database and decrypts it
121
+ *
122
+ * @param emailID - The email identifier
123
+ * @param indexKey - The symmetric key key for protecting database
124
+ * @param encryptedEmail - The encrypted email
125
+ * @returns The decrypted email
126
+ */
127
+ const getAndDecryptEmail = async (emailID, indexKey, esDB) => {
128
+ try {
129
+ const encryptedEmail = await esDB.get(require_constants.DB_LABEL, emailID);
130
+ if (!encryptedEmail) throw new Error(`DB cannot find email with id ${emailID}`);
131
+ return decryptEmail(indexKey, encryptedEmail);
132
+ } catch (error) {
133
+ throw new Error(`Cannot fetch the email ${emailID} from the database`, { cause: error });
134
+ }
135
+ };
136
+ /**
137
+ * Fetches all email from the database and decrypts them
138
+ *
139
+ * @param indexKey - The symmetric key key for protecting database
140
+ * @param esDB - The database
141
+ * @returns The decrypted emails
142
+ */
143
+ const getAndDecryptAllEmails = async (indexKey, esDB) => {
144
+ try {
145
+ const encryptedEmails = await esDB.getAll(require_constants.DB_LABEL);
146
+ return (await Promise.all(encryptedEmails.map(async (encEmail) => {
147
+ return {
148
+ body: await require_core.decryptEmailBody(encEmail.encEmailBody, indexKey),
149
+ params: encEmail.params,
150
+ id: encEmail.id
151
+ };
152
+ }))).filter((email) => email !== null);
153
+ } catch (error) {
154
+ throw new Error("Cannot fetch and decrypt all emails from the database", { cause: error });
155
+ }
156
+ };
157
+ /**
158
+ * Deletes the email from the database
159
+ *
160
+ * @param emailID - The email identifier
161
+ * @param esDB - The database
162
+ */
163
+ const deleteEmail = async (emailID, esDB) => {
164
+ await esDB.delete(require_constants.DB_LABEL, emailID);
165
+ };
166
+ /**
167
+ * Returns the number of stored email
168
+ *
169
+ * @param esDB - The database
170
+ * @returns The number of stored emails
171
+ */
172
+ const getEmailCount = async (esDB) => {
173
+ return await esDB.count(require_constants.DB_LABEL);
174
+ };
175
+ /**
176
+ * Removes the given number of oldests emails from the database
177
+ *
178
+ * @param emailsToDelete - The number of emails to delete
179
+ * @param esDB - The database
180
+ */
181
+ const deleteOldestEmails = async (emailsToDelete, esDB) => {
182
+ try {
183
+ const tx = esDB.transaction(require_constants.DB_LABEL, "readwrite");
184
+ let cursor = await tx.store.index("byTime").openCursor();
185
+ let deletedCount = 0;
186
+ while (cursor && deletedCount < emailsToDelete) {
187
+ await cursor.delete();
188
+ deletedCount++;
189
+ cursor = await cursor.continue();
190
+ }
191
+ await tx.done;
192
+ } catch (error) {
193
+ throw new Error(`Cannot delete ${emailsToDelete} oldests emails from the database`, { cause: error });
194
+ }
195
+ };
196
+ /**
197
+ * Enforces the maximum email number in the database
198
+ *
199
+ * @param esDB - The database
200
+ * @param max - The maximum allowed number of emails
201
+ */
202
+ const enforceMaxEmailNumber = async (esDB, max) => {
203
+ try {
204
+ const currentCount = await getEmailCount(esDB);
205
+ if (currentCount <= max) return;
206
+ await deleteOldestEmails(currentCount - max, esDB);
207
+ } catch (error) {
208
+ throw new Error(`Cannot enforce the maximum of ${max} emails on the database`, { cause: error });
209
+ }
210
+ };
211
+ /**
212
+ * Fetches all emails from the database, decrypts them and sortes the results in the specified order
213
+ *
214
+ * @param esDB - The database
215
+ * @param indexKey - The symmetric key key for protecting database
216
+ * @param direction - The order of sorting. If 'next' - oldest first, if 'prev' - newest first
217
+ * @returns Decryped emails in the specified order
218
+ */
219
+ const fetchEmails = async (esDB, indexKey, direction) => {
220
+ try {
221
+ const index = esDB.transaction(require_constants.DB_LABEL, "readonly").store.index("byTime");
222
+ const encryptedEmails = [];
223
+ let cursor = await index.openCursor(null, direction);
224
+ while (cursor) {
225
+ encryptedEmails.push(cursor.value);
226
+ cursor = await cursor.continue();
227
+ }
228
+ return await Promise.all(encryptedEmails.map((encryptedEmail) => decryptEmail(indexKey, encryptedEmail)));
229
+ } catch (error) {
230
+ throw new Error("Cannot fetch emails from database", { cause: error });
231
+ }
232
+ };
233
+ /**
234
+ * Fetches all emails from the database, decrypts them and sortes the results based on the creation time (newest first)
235
+ *
236
+ * @param esDB - The database
237
+ * @param indexKey - The symmetric Uint8Array key for protecting database
238
+ * @returns The number of stored emails
239
+ */
240
+ const getAllEmailsSortedNewestFirst = async (esDB, indexKey) => {
241
+ return fetchEmails(esDB, indexKey, "prev");
242
+ };
243
+ /**
244
+ * Fetches all emails from the database, decrypts them and sortes the results based on the creation time (oldest first)
245
+ *
246
+ * @param esDB - The database
247
+ * @param indexKey - The symmetric key for protecting database
248
+ * @returns The number of stored emails
249
+ */
250
+ const getAllEmailsSortedOldestFirst = async (esDB, indexKey) => {
251
+ return fetchEmails(esDB, indexKey, "next");
252
+ };
253
+ /**
254
+ * Fetches a batch of emails from the database, decrypts them and sortes the results based on the creation time (newest first)
255
+ *
256
+ * @param esDB - The database
257
+ * @param indexKey - The symmetric key for protecting database
258
+ * @param batchSize - The size of the batch
259
+ * @param startCursor - The starting point (optional). If not given, starts from the beginning
260
+ * @returns The number of stored emails
261
+ */
262
+ const getEmailBatch = async (esDB, indexKey, batchSize, startCursor) => {
263
+ try {
264
+ const index = esDB.transaction(require_constants.DB_LABEL, "readonly").store.index("byTime");
265
+ const encryptedEmails = [];
266
+ let cursor;
267
+ if (startCursor) {
268
+ const range = IDBKeyRange.upperBound(startCursor, true);
269
+ cursor = await index.openCursor(range, "prev");
270
+ } else cursor = await index.openCursor(null, "prev");
271
+ let count = 0;
272
+ let nextCursor;
273
+ while (cursor && count < batchSize) {
274
+ encryptedEmails.push(cursor.value);
275
+ nextCursor = cursor.key;
276
+ count++;
277
+ cursor = await cursor.continue();
278
+ }
279
+ return {
280
+ emails: await Promise.all(encryptedEmails.map((encryptedEmail) => decryptEmail(indexKey, encryptedEmail))),
281
+ nextCursor: count === batchSize ? nextCursor : void 0
282
+ };
283
+ } catch (error) {
284
+ throw new Error(`Cannot fetch email batch of ${batchSize} from the database`, { cause: error });
285
+ }
286
+ };
287
+
288
+ //#endregion
289
+ //#region src/email-search/utils.ts
290
+ /**
291
+ * Converts an Email type into a Uint8Array array.
292
+ *
293
+ * @param email - The email.
294
+ * @returns The Uint8Array array representation of the Email type.
295
+ */
296
+ function emailToBinary(email) {
297
+ try {
298
+ return require_genID.UTF8ToUint8(JSON.stringify(email));
299
+ } catch (error) {
300
+ throw new Error("Failed to convert EmailBody to Uint8Array", { cause: error });
301
+ }
302
+ }
303
+
304
+ //#endregion
305
+ //#region src/email-search/mailCache.ts
306
+ /**
307
+ * Estimates the email size in the memory
308
+ *
309
+ * @param email - The email
310
+ * @returns The estimation of the email size
311
+ */
312
+ function sizeOfEmail(email) {
313
+ return emailToBinary(email).byteLength;
314
+ }
315
+ /**
316
+ * Creates an empty cache variable
317
+ *
318
+ * @returns The empty cache
319
+ */
320
+ function createEmptyCache() {
321
+ return {
322
+ esCache: /* @__PURE__ */ new Map(),
323
+ cacheSize: 0,
324
+ isCacheLimited: false,
325
+ isCacheReady: true
326
+ };
327
+ }
328
+ /**
329
+ * Fetches all emails from the database in batches and cahces them
330
+ *
331
+ * @param indexKey - The symmetric key for protecting database
332
+ * @param esCache - The cache to add emails too
333
+ * @param esDB - The database
334
+ */
335
+ const createCacheFromDB = async (indexKey, esDB) => {
336
+ const esCache = createEmptyCache();
337
+ esCache.isCacheReady = false;
338
+ try {
339
+ const count = await getEmailCount(esDB);
340
+ if (!count) {
341
+ esCache.isCacheReady = true;
342
+ return esCache;
343
+ }
344
+ if (count <= require_constants.MAX_EMAIL_PER_BATCH) addEmailsToCache(await getAllEmailsSortedNewestFirst(esDB, indexKey), esCache);
345
+ else {
346
+ let nextCursor = void 0;
347
+ let cacheFull = false;
348
+ while (!cacheFull) {
349
+ const { emails, nextCursor: newCursor } = await getEmailBatch(esDB, indexKey, require_constants.MAX_EMAIL_PER_BATCH, nextCursor);
350
+ if (!newCursor || !emails.length) break;
351
+ nextCursor = newCursor;
352
+ if (!addEmailsToCache(emails, esCache)) cacheFull = true;
353
+ }
354
+ }
355
+ return esCache;
356
+ } catch (error) {
357
+ throw new Error(`Email caching failed: ${error}`, { cause: error });
358
+ }
359
+ };
360
+ /**
361
+ * Gets an email from the cache
362
+ *
363
+ * @param emailID - The email identifier
364
+ * @param esCache - The email cache
365
+ * @returns The found email or throws an error
366
+ */
367
+ const getEmailFromCache = async (emailID, esCache) => {
368
+ const email = esCache.esCache.get(emailID);
369
+ if (!email) throw new Error(`Email not found in cache for ID: ${emailID}`);
370
+ return email;
371
+ };
372
+ /**
373
+ * Removes the email from cache
374
+ *
375
+ * @param emailID - The email identifier
376
+ * @param esCache - The email cache
377
+ */
378
+ const deleteEmailFromCache = async (emailID, esCache) => {
379
+ try {
380
+ const size = sizeOfEmail(await getEmailFromCache(emailID, esCache));
381
+ if (esCache.esCache.delete(emailID)) esCache.cacheSize -= size;
382
+ } catch (error) {
383
+ throw new Error(`Failed to delete email with ID ${emailID}`, { cause: error });
384
+ }
385
+ };
386
+ /**
387
+ * Adds emails to the cache
388
+ *
389
+ * @param emails - The emails to add
390
+ * @param esCache - The email cache
391
+ * @returns TRUE if all emails were added sucessfully, or FALSE and error reason.
392
+ */
393
+ function addEmailsToCache(emails, esCache) {
394
+ try {
395
+ for (const email of emails) {
396
+ const result = addEmailToCache(email, esCache);
397
+ if (!result.success) return result;
398
+ }
399
+ return { success: true };
400
+ } catch (error) {
401
+ throw new Error("Failed to add emails to the cache", { cause: error });
402
+ }
403
+ }
404
+ /**
405
+ * Adds email to the cache
406
+ *
407
+ * @param email - The email to add
408
+ * @param esCache - The email cache
409
+ * @returns TRUE if the email was added sucessfully, or FALSE and error reason.
410
+ */
411
+ const addEmailToCache = (email, esCache) => {
412
+ try {
413
+ if (esCache.esCache.has(email.id)) return {
414
+ success: false,
415
+ reason: "email already exists in cache"
416
+ };
417
+ const emailSize = sizeOfEmail(email);
418
+ if (esCache.cacheSize + emailSize > require_constants.MAX_CACHE_SIZE) {
419
+ esCache.isCacheLimited = true;
420
+ return {
421
+ success: false,
422
+ reason: "hit cache limit"
423
+ };
424
+ }
425
+ esCache.esCache.set(email.id, email);
426
+ esCache.cacheSize += emailSize;
427
+ return { success: true };
428
+ } catch (error) {
429
+ throw new Error("Failed to add email to the cache", { cause: error });
430
+ }
431
+ };
432
+
433
+ //#endregion
434
+ //#region src/email-search/search.ts
435
+ const SUBJECT_OPTIONS = {
436
+ preset: "match",
437
+ tokenize: "forward",
438
+ resolution: 9,
439
+ minlength: 2,
440
+ optimize: true,
441
+ fastupdate: true,
442
+ cache: true
443
+ };
444
+ const BODY_OPTIONS = {
445
+ ...SUBJECT_OPTIONS,
446
+ minlength: 3,
447
+ resolution: 6
448
+ };
449
+ const FROM_OPTIONS = {
450
+ ...SUBJECT_OPTIONS,
451
+ tokenize: "strict",
452
+ minlength: 1
453
+ };
454
+ const TO_OPTIONS = {
455
+ ...SUBJECT_OPTIONS,
456
+ tokenize: "strict",
457
+ minlength: 1
458
+ };
459
+ /**
460
+ * Creates new email search index
461
+ *
462
+ * @returns The email search index
463
+ */
464
+ const createSearchIndex = () => ({
465
+ subjectIndex: new flexsearch.Index(SUBJECT_OPTIONS),
466
+ bodyIndex: new flexsearch.Index(BODY_OPTIONS),
467
+ fromIndex: new flexsearch.Index(FROM_OPTIONS),
468
+ toIndex: new flexsearch.Index(TO_OPTIONS),
469
+ isReady: false
470
+ });
471
+ /**
472
+ * Adds the given email to the email search index
473
+ *
474
+ * @param email - The email to add
475
+ * @param searchIndex - The email search index
476
+ */
477
+ const addEmailToSearchIndex = (email, searchIndex) => {
478
+ try {
479
+ const emailId = email.id;
480
+ searchIndex.subjectIndex.add(emailId, email.body.subject);
481
+ searchIndex.bodyIndex.add(emailId, email.body.text);
482
+ const senderText = `${email.params.sender.name || ""} ${email.params.sender.email || ""}`.trim();
483
+ searchIndex.fromIndex.add(emailId, senderText);
484
+ const recipientsText = (email.params.recipients?.length ? email.params.recipients : [email.params.recipient]).map((recipient) => `${recipient.name || ""} ${recipient.email || ""}`.trim()).join(" ");
485
+ searchIndex.toIndex.add(emailId, recipientsText);
486
+ } catch (error) {
487
+ throw new Error("Failed to add email to the search index", { cause: error });
488
+ }
489
+ };
490
+ /**
491
+ * Removes the email from the email search index
492
+ *
493
+ * @param emailID - The email identifier
494
+ * @param searchIndex - The email search index
495
+ */
496
+ const removeEmailFromSearchIndex = (emailID, searchIndex) => {
497
+ try {
498
+ searchIndex.subjectIndex.remove(emailID);
499
+ searchIndex.bodyIndex.remove(emailID);
500
+ searchIndex.fromIndex.remove(emailID);
501
+ searchIndex.toIndex.remove(emailID);
502
+ } catch (error) {
503
+ throw new Error(`Failed to remove email with ID ${emailID} from the search index`, { cause: error });
504
+ }
505
+ };
506
+ /**
507
+ * Buils the email search index from the email cache
508
+ *
509
+ * @param esCache - The email cache
510
+ * @returns The email search index
511
+ */
512
+ const buildSearchIndexFromCache = async (esCache) => {
513
+ try {
514
+ const searchIndex = createSearchIndex();
515
+ searchIndex.isReady = false;
516
+ for (const email of esCache.esCache.values()) addEmailToSearchIndex(email, searchIndex);
517
+ searchIndex.isReady = true;
518
+ return searchIndex;
519
+ } catch (error) {
520
+ throw new Error("Failed build an email search index from the cache", { cause: error });
521
+ }
522
+ };
523
+ /**
524
+ * Searches in teh
525
+ *
526
+ * @param query - The string to search for
527
+ * @param esCache - The email cache
528
+ * @param searchIndex - The email search index
529
+ * @param opetions - The optional search limitations
530
+ * @returns The result of the email search (emails ans their corresponding result weights)
531
+ */
532
+ const searchEmails = async (query, esCache, searchIndex, options = {}) => {
533
+ try {
534
+ if (!searchIndex.isReady || !query.trim()) return [];
535
+ const { fields = [
536
+ "subject",
537
+ "body",
538
+ "from",
539
+ "to"
540
+ ], limit = 50, boost = {
541
+ subject: 3,
542
+ body: 1,
543
+ from: 2,
544
+ to: 2
545
+ } } = options;
546
+ const results = /* @__PURE__ */ new Map();
547
+ const searchPromises = fields.map(async (field) => {
548
+ let fieldResults;
549
+ switch (field) {
550
+ case "subject":
551
+ fieldResults = await searchIndex.subjectIndex.searchAsync(query);
552
+ break;
553
+ case "body":
554
+ fieldResults = await searchIndex.bodyIndex.searchAsync(query);
555
+ break;
556
+ case "from":
557
+ fieldResults = await searchIndex.fromIndex.searchAsync(query);
558
+ break;
559
+ case "to":
560
+ fieldResults = await searchIndex.toIndex.searchAsync(query);
561
+ break;
562
+ default: return;
563
+ }
564
+ const fieldBoost = boost[field] || 1;
565
+ fieldResults.forEach((emailId) => {
566
+ const currentScore = results.get(String(emailId)) || 0;
567
+ results.set(String(emailId), currentScore + fieldBoost);
568
+ });
569
+ });
570
+ await Promise.all(searchPromises);
571
+ const emailResults = [];
572
+ for (const [emailId, score] of results) {
573
+ const email = esCache.esCache.get(emailId);
574
+ if (email) emailResults.push({
575
+ email,
576
+ score
577
+ });
578
+ }
579
+ emailResults.sort((a, b) => (b.score || 0) - (a.score || 0));
580
+ return emailResults.slice(0, limit);
581
+ } catch (error) {
582
+ throw new Error("Email search failed", { cause: error });
583
+ }
584
+ };
585
+
586
+ //#endregion
587
+ Object.defineProperty(exports, 'addEmailToCache', {
588
+ enumerable: true,
589
+ get: function () {
590
+ return addEmailToCache;
591
+ }
592
+ });
593
+ Object.defineProperty(exports, 'addEmailToSearchIndex', {
594
+ enumerable: true,
595
+ get: function () {
596
+ return addEmailToSearchIndex;
597
+ }
598
+ });
599
+ Object.defineProperty(exports, 'addEmailsToCache', {
600
+ enumerable: true,
601
+ get: function () {
602
+ return addEmailsToCache;
603
+ }
604
+ });
605
+ Object.defineProperty(exports, 'buildSearchIndexFromCache', {
606
+ enumerable: true,
607
+ get: function () {
608
+ return buildSearchIndexFromCache;
609
+ }
610
+ });
611
+ Object.defineProperty(exports, 'closeDatabase', {
612
+ enumerable: true,
613
+ get: function () {
614
+ return closeDatabase;
615
+ }
616
+ });
617
+ Object.defineProperty(exports, 'createCacheFromDB', {
618
+ enumerable: true,
619
+ get: function () {
620
+ return createCacheFromDB;
621
+ }
622
+ });
623
+ Object.defineProperty(exports, 'deleteDatabase', {
624
+ enumerable: true,
625
+ get: function () {
626
+ return deleteDatabase;
627
+ }
628
+ });
629
+ Object.defineProperty(exports, 'deleteEmail', {
630
+ enumerable: true,
631
+ get: function () {
632
+ return deleteEmail;
633
+ }
634
+ });
635
+ Object.defineProperty(exports, 'deleteEmailFromCache', {
636
+ enumerable: true,
637
+ get: function () {
638
+ return deleteEmailFromCache;
639
+ }
640
+ });
641
+ Object.defineProperty(exports, 'deleteOldestEmails', {
642
+ enumerable: true,
643
+ get: function () {
644
+ return deleteOldestEmails;
645
+ }
646
+ });
647
+ Object.defineProperty(exports, 'deriveIndexKey', {
648
+ enumerable: true,
649
+ get: function () {
650
+ return deriveIndexKey;
651
+ }
652
+ });
653
+ Object.defineProperty(exports, 'encryptAndStoreEmail', {
654
+ enumerable: true,
655
+ get: function () {
656
+ return encryptAndStoreEmail;
657
+ }
658
+ });
659
+ Object.defineProperty(exports, 'encryptAndStoreManyEmail', {
660
+ enumerable: true,
661
+ get: function () {
662
+ return encryptAndStoreManyEmail;
663
+ }
664
+ });
665
+ Object.defineProperty(exports, 'enforceMaxEmailNumber', {
666
+ enumerable: true,
667
+ get: function () {
668
+ return enforceMaxEmailNumber;
669
+ }
670
+ });
671
+ Object.defineProperty(exports, 'getAllEmailsSortedNewestFirst', {
672
+ enumerable: true,
673
+ get: function () {
674
+ return getAllEmailsSortedNewestFirst;
675
+ }
676
+ });
677
+ Object.defineProperty(exports, 'getAllEmailsSortedOldestFirst', {
678
+ enumerable: true,
679
+ get: function () {
680
+ return getAllEmailsSortedOldestFirst;
681
+ }
682
+ });
683
+ Object.defineProperty(exports, 'getAndDecryptAllEmails', {
684
+ enumerable: true,
685
+ get: function () {
686
+ return getAndDecryptAllEmails;
687
+ }
688
+ });
689
+ Object.defineProperty(exports, 'getAndDecryptEmail', {
690
+ enumerable: true,
691
+ get: function () {
692
+ return getAndDecryptEmail;
693
+ }
694
+ });
695
+ Object.defineProperty(exports, 'getEmailBatch', {
696
+ enumerable: true,
697
+ get: function () {
698
+ return getEmailBatch;
699
+ }
700
+ });
701
+ Object.defineProperty(exports, 'getEmailCount', {
702
+ enumerable: true,
703
+ get: function () {
704
+ return getEmailCount;
705
+ }
706
+ });
707
+ Object.defineProperty(exports, 'getEmailFromCache', {
708
+ enumerable: true,
709
+ get: function () {
710
+ return getEmailFromCache;
711
+ }
712
+ });
713
+ Object.defineProperty(exports, 'openDatabase', {
714
+ enumerable: true,
715
+ get: function () {
716
+ return openDatabase;
717
+ }
718
+ });
719
+ Object.defineProperty(exports, 'removeEmailFromSearchIndex', {
720
+ enumerable: true,
721
+ get: function () {
722
+ return removeEmailFromSearchIndex;
723
+ }
724
+ });
725
+ Object.defineProperty(exports, 'searchEmails', {
726
+ enumerable: true,
727
+ get: function () {
728
+ return searchEmails;
729
+ }
730
+ });
731
+ //# sourceMappingURL=search-DUTm4-rN.js.map