@vex-chat/libvex 6.2.3 → 6.3.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.
- package/dist/Client.d.ts +31 -2
- package/dist/Client.d.ts.map +1 -1
- package/dist/Client.js +134 -15
- package/dist/Client.js.map +1 -1
- package/dist/Storage.d.ts +5 -0
- package/dist/Storage.d.ts.map +1 -1
- package/dist/__tests__/harness/memory-storage.d.ts +1 -0
- package/dist/__tests__/harness/memory-storage.d.ts.map +1 -1
- package/dist/__tests__/harness/memory-storage.js +15 -0
- package/dist/__tests__/harness/memory-storage.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/retention.d.ts +26 -0
- package/dist/retention.d.ts.map +1 -0
- package/dist/retention.js +51 -0
- package/dist/retention.js.map +1 -0
- package/dist/storage/schema.d.ts +2 -0
- package/dist/storage/schema.d.ts.map +1 -1
- package/dist/storage/sqlite.d.ts +2 -0
- package/dist/storage/sqlite.d.ts.map +1 -1
- package/dist/storage/sqlite.js +54 -2
- package/dist/storage/sqlite.js.map +1 -1
- package/package.json +3 -3
- package/src/Client.ts +209 -20
- package/src/Storage.ts +7 -0
- package/src/__tests__/harness/memory-storage.ts +19 -0
- package/src/__tests__/retention.test.ts +39 -0
- package/src/index.ts +4 -0
- package/src/retention.ts +68 -0
- package/src/storage/schema.ts +2 -0
- package/src/storage/sqlite.ts +69 -2
package/src/storage/sqlite.ts
CHANGED
|
@@ -349,6 +349,7 @@ export class SqliteStorage extends EventEmitter implements Storage {
|
|
|
349
349
|
)
|
|
350
350
|
.execute();
|
|
351
351
|
await this.ensureSessionRatchetColumns();
|
|
352
|
+
await this.ensureRetentionHintColumn();
|
|
352
353
|
|
|
353
354
|
await this.db.schema
|
|
354
355
|
.createTable("preKeys")
|
|
@@ -416,6 +417,46 @@ export class SqliteStorage extends EventEmitter implements Storage {
|
|
|
416
417
|
|
|
417
418
|
// ── PreKeys / OneTimeKeys ────────────────────────────────────────────────
|
|
418
419
|
|
|
420
|
+
async pruneExpiredLocalMessages(
|
|
421
|
+
clientMaxRetentionDays: number,
|
|
422
|
+
): Promise<void> {
|
|
423
|
+
await this.untilReady();
|
|
424
|
+
if (this.closing) {
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
const cap = Math.min(
|
|
428
|
+
30,
|
|
429
|
+
Math.max(1, Math.round(clientMaxRetentionDays)),
|
|
430
|
+
);
|
|
431
|
+
const rows = await this.db
|
|
432
|
+
.selectFrom("messages")
|
|
433
|
+
.select(["mailID", "timestamp", "retentionHintDays"])
|
|
434
|
+
.execute();
|
|
435
|
+
const now = Date.now();
|
|
436
|
+
const msPerDay = 86_400_000;
|
|
437
|
+
const toDelete: string[] = [];
|
|
438
|
+
for (const r of rows) {
|
|
439
|
+
const hintDays = r.retentionHintDays ?? 30;
|
|
440
|
+
const maxDays = Math.min(30, cap, hintDays);
|
|
441
|
+
const ts = new Date(r.timestamp).getTime();
|
|
442
|
+
if (!Number.isFinite(ts)) {
|
|
443
|
+
continue;
|
|
444
|
+
}
|
|
445
|
+
if (now - ts > maxDays * msPerDay) {
|
|
446
|
+
toDelete.push(r.mailID);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
if (toDelete.length === 0) {
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
for (const mailID of toDelete) {
|
|
453
|
+
await this.db
|
|
454
|
+
.deleteFrom("messages")
|
|
455
|
+
.where("mailID", "=", mailID)
|
|
456
|
+
.execute();
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
419
460
|
async purgeHistory(): Promise<void> {
|
|
420
461
|
await this.db.deleteFrom("messages").execute();
|
|
421
462
|
}
|
|
@@ -489,6 +530,16 @@ export class SqliteStorage extends EventEmitter implements Storage {
|
|
|
489
530
|
nonce: message.nonce,
|
|
490
531
|
readerID: message.readerID,
|
|
491
532
|
recipient: message.recipient,
|
|
533
|
+
retentionHintDays:
|
|
534
|
+
message.retentionHintDays === undefined
|
|
535
|
+
? null
|
|
536
|
+
: Math.min(
|
|
537
|
+
30,
|
|
538
|
+
Math.max(
|
|
539
|
+
1,
|
|
540
|
+
Math.round(message.retentionHintDays),
|
|
541
|
+
),
|
|
542
|
+
),
|
|
492
543
|
sender: message.sender,
|
|
493
544
|
timestamp: message.timestamp,
|
|
494
545
|
})
|
|
@@ -638,7 +689,7 @@ export class SqliteStorage extends EventEmitter implements Storage {
|
|
|
638
689
|
}
|
|
639
690
|
const direction =
|
|
640
691
|
msg.direction === "incoming" ? "incoming" : "outgoing";
|
|
641
|
-
|
|
692
|
+
const rowMessage: Message = {
|
|
642
693
|
authorID: msg.authorID,
|
|
643
694
|
decrypted: decryptedFlag,
|
|
644
695
|
direction,
|
|
@@ -651,7 +702,11 @@ export class SqliteStorage extends EventEmitter implements Storage {
|
|
|
651
702
|
recipient: msg.recipient,
|
|
652
703
|
sender: msg.sender,
|
|
653
704
|
timestamp: msg.timestamp,
|
|
654
|
-
}
|
|
705
|
+
};
|
|
706
|
+
if (msg.retentionHintDays != null) {
|
|
707
|
+
rowMessage.retentionHintDays = msg.retentionHintDays;
|
|
708
|
+
}
|
|
709
|
+
out.push(rowMessage);
|
|
655
710
|
}
|
|
656
711
|
return out;
|
|
657
712
|
}
|
|
@@ -669,6 +724,18 @@ export class SqliteStorage extends EventEmitter implements Storage {
|
|
|
669
724
|
};
|
|
670
725
|
}
|
|
671
726
|
|
|
727
|
+
private async ensureRetentionHintColumn(): Promise<void> {
|
|
728
|
+
try {
|
|
729
|
+
await sql
|
|
730
|
+
.raw(
|
|
731
|
+
"ALTER TABLE messages ADD COLUMN retentionHintDays integer",
|
|
732
|
+
)
|
|
733
|
+
.execute(this.db);
|
|
734
|
+
} catch {
|
|
735
|
+
// Existing databases may already have this column.
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
|
|
672
739
|
private async ensureSessionRatchetColumns(): Promise<void> {
|
|
673
740
|
const add = async (
|
|
674
741
|
column: string,
|