@happyvertical/smrt-messages 0.55.4 → 0.55.7
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/AGENTS.md +10 -0
- package/dist/chunks/{AccountCollection-LHFMPeF7.js → AccountCollection-D0jYNESQ.js} +2 -2
- package/dist/chunks/{AccountCollection-LHFMPeF7.js.map → AccountCollection-D0jYNESQ.js.map} +1 -1
- package/dist/chunks/{Email-tafppJZ4.js → Email-hneqk2_l.js} +3 -3
- package/dist/chunks/{Email-tafppJZ4.js.map → Email-hneqk2_l.js.map} +1 -1
- package/dist/chunks/{EmailFolder-CLahyNFX.js → EmailFolder-CFd0haPW.js} +2 -2
- package/dist/chunks/{EmailFolder-CLahyNFX.js.map → EmailFolder-CFd0haPW.js.map} +1 -1
- package/dist/chunks/{Message-DZ1al6M1.js → Message-CSv9rJva.js} +4 -4
- package/dist/chunks/{Message-DZ1al6M1.js.map → Message-CSv9rJva.js.map} +1 -1
- package/dist/chunks/{MessageCollection-8eaZgS4_.js → MessageCollection-4yzuqVl4.js} +2 -2
- package/dist/chunks/{MessageCollection-8eaZgS4_.js.map → MessageCollection-4yzuqVl4.js.map} +1 -1
- package/dist/chunks/__smrt-register__-DyB0ALdL.js +6 -0
- package/dist/chunks/__smrt-register__-DyB0ALdL.js.map +1 -0
- package/dist/chunks/intake-snapshot-B03bDtSW.js +55 -0
- package/dist/chunks/intake-snapshot-B03bDtSW.js.map +1 -0
- package/dist/index.js +31 -9
- package/dist/index.js.map +1 -1
- package/dist/intake-snapshot.d.ts +27 -0
- package/dist/intake-snapshot.d.ts.map +1 -0
- package/dist/manifest.json +32 -1
- package/dist/models/EmailAccount.d.ts +10 -0
- package/dist/models/EmailAccount.d.ts.map +1 -1
- package/dist/smrt-knowledge.json +26 -5
- package/package.json +15 -15
- package/dist/chunks/__smrt-register__-DtlRO--l.js +0 -6
- package/dist/chunks/__smrt-register__-DtlRO--l.js.map +0 -1
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
//#region src/intake-snapshot.ts
|
|
2
|
+
var EmailIntakeSnapshotError = class extends Error {
|
|
3
|
+
constructor(category, message) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.category = category;
|
|
6
|
+
}
|
|
7
|
+
category;
|
|
8
|
+
name = "EmailIntakeSnapshotError";
|
|
9
|
+
};
|
|
10
|
+
function snapshotEmailForIntake(accountId, message, maxBytes) {
|
|
11
|
+
if (!Number.isSafeInteger(maxBytes) || maxBytes < 1) throw new EmailIntakeSnapshotError("limit", "Invalid email byte limit");
|
|
12
|
+
if (!message.date || !Number.isFinite(message.date.getTime())) throw new EmailIntakeSnapshotError("invalid", "Email capture date unavailable");
|
|
13
|
+
const body = {
|
|
14
|
+
accountId,
|
|
15
|
+
messageId: message.messageId || "",
|
|
16
|
+
threadId: message.threadId || "",
|
|
17
|
+
inReplyTo: message.inReplyTo || "",
|
|
18
|
+
subject: message.subject || "",
|
|
19
|
+
text: message.text || "",
|
|
20
|
+
html: message.html || "",
|
|
21
|
+
date: message.date.toISOString()
|
|
22
|
+
};
|
|
23
|
+
let size = 0;
|
|
24
|
+
const attachments = (message.attachments || []).map((attachment, index) => {
|
|
25
|
+
if (!(attachment.content instanceof Uint8Array)) throw new EmailIntakeSnapshotError("unavailable_bytes", "Email attachment bytes unavailable");
|
|
26
|
+
size += attachment.content.byteLength;
|
|
27
|
+
if (size > maxBytes) throw new EmailIntakeSnapshotError("limit", "Email byte limit exceeded");
|
|
28
|
+
return {
|
|
29
|
+
partId: String(index),
|
|
30
|
+
filename: attachment.filename || "",
|
|
31
|
+
mediaType: attachment.contentType,
|
|
32
|
+
bytes: attachment.content
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
size += Buffer.byteLength(JSON.stringify({
|
|
36
|
+
...body,
|
|
37
|
+
attachments: attachments.map(({ partId, filename, mediaType }) => ({
|
|
38
|
+
partId,
|
|
39
|
+
filename,
|
|
40
|
+
mediaType
|
|
41
|
+
}))
|
|
42
|
+
}));
|
|
43
|
+
if (size > maxBytes) throw new EmailIntakeSnapshotError("limit", "Email byte limit exceeded");
|
|
44
|
+
return {
|
|
45
|
+
...body,
|
|
46
|
+
attachments: attachments.map((attachment) => ({
|
|
47
|
+
...attachment,
|
|
48
|
+
bytes: Buffer.from(attachment.bytes)
|
|
49
|
+
}))
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
53
|
+
export { snapshotEmailForIntake };
|
|
54
|
+
|
|
55
|
+
//# sourceMappingURL=intake-snapshot-B03bDtSW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intake-snapshot-B03bDtSW.js","names":[],"sources":["../../src/intake-snapshot.ts"],"sourcesContent":["import type { EmailMessage } from '@happyvertical/email';\n\n/** Full-message byte snapshot for an already authorized, configured account. */\nexport interface EmailIntakeSnapshot {\n accountId: string;\n messageId: string;\n threadId: string;\n inReplyTo: string;\n subject: string;\n text: string;\n html: string;\n date: string;\n attachments: Array<{\n partId: string;\n filename: string;\n mediaType: string;\n bytes: Uint8Array;\n }>;\n}\n\n/** Safe machine-readable snapshot failure; never contains provider error details. */\nexport class EmailIntakeSnapshotError extends Error {\n override readonly name = 'EmailIntakeSnapshotError';\n constructor(\n public readonly category: 'invalid' | 'limit' | 'unavailable_bytes',\n message: string,\n ) {\n super(message);\n }\n}\n\n/** Copies actual provider bytes; missing bytes fail closed, never read provider-supplied paths. */\nexport function snapshotEmailForIntake(\n accountId: string,\n message: EmailMessage,\n maxBytes: number,\n): EmailIntakeSnapshot {\n if (!Number.isSafeInteger(maxBytes) || maxBytes < 1)\n throw new EmailIntakeSnapshotError('limit', 'Invalid email byte limit');\n if (!message.date || !Number.isFinite(message.date.getTime()))\n throw new EmailIntakeSnapshotError(\n 'invalid',\n 'Email capture date unavailable',\n );\n const body = {\n accountId,\n messageId: message.messageId || '',\n threadId: message.threadId || '',\n inReplyTo: message.inReplyTo || '',\n subject: message.subject || '',\n text: message.text || '',\n html: message.html || '',\n date: message.date.toISOString(),\n };\n let size = 0;\n const attachments = (message.attachments || []).map((attachment, index) => {\n if (!(attachment.content instanceof Uint8Array))\n throw new EmailIntakeSnapshotError(\n 'unavailable_bytes',\n 'Email attachment bytes unavailable',\n );\n size += attachment.content.byteLength;\n if (size > maxBytes)\n throw new EmailIntakeSnapshotError('limit', 'Email byte limit exceeded');\n return {\n partId: String(index),\n filename: attachment.filename || '',\n mediaType: attachment.contentType,\n bytes: attachment.content,\n };\n });\n // Match the message part preserved by EmailSourceAdapter, including JSON\n // delimiters, escaped/UTF-8 descriptors and the empty attachments array.\n size += Buffer.byteLength(\n JSON.stringify({\n ...body,\n attachments: attachments.map(({ partId, filename, mediaType }) => ({\n partId,\n filename,\n mediaType,\n })),\n }),\n );\n if (size > maxBytes)\n throw new EmailIntakeSnapshotError('limit', 'Email byte limit exceeded');\n return {\n ...body,\n attachments: attachments.map((attachment) => ({\n ...attachment,\n bytes: Buffer.from(attachment.bytes),\n })),\n };\n}\n"],"mappings":";AAqBO,IAAM,2BAAN,cAAuC,MAAM;CAElD,YACkB,UAChB,SACA;EACA,MAAM,OAAO;EAHG,KAAA,WAAA;CAIlB;CAJkB;CAFA,OAAO;AAO3B;AAGO,SAAS,uBACd,WACA,SACA,UACqB;CACrB,IAAI,CAAC,OAAO,cAAc,QAAQ,KAAK,WAAW,GAChD,MAAM,IAAI,yBAAyB,SAAS,0BAA0B;CACxE,IAAI,CAAC,QAAQ,QAAQ,CAAC,OAAO,SAAS,QAAQ,KAAK,QAAQ,CAAC,GAC1D,MAAM,IAAI,yBACR,WACA,gCACF;CACF,MAAM,OAAO;EACX;EACA,WAAW,QAAQ,aAAa;EAChC,UAAU,QAAQ,YAAY;EAC9B,WAAW,QAAQ,aAAa;EAChC,SAAS,QAAQ,WAAW;EAC5B,MAAM,QAAQ,QAAQ;EACtB,MAAM,QAAQ,QAAQ;EACtB,MAAM,QAAQ,KAAK,YAAY;CACjC;CACA,IAAI,OAAO;CACX,MAAM,eAAe,QAAQ,eAAe,CAAC,EAAA,CAAG,KAAK,YAAY,UAAU;EACzE,IAAI,EAAE,WAAW,mBAAmB,aAClC,MAAM,IAAI,yBACR,qBACA,oCACF;EACF,QAAQ,WAAW,QAAQ;EAC3B,IAAI,OAAO,UACT,MAAM,IAAI,yBAAyB,SAAS,2BAA2B;EACzE,OAAO;GACL,QAAQ,OAAO,KAAK;GACpB,UAAU,WAAW,YAAY;GACjC,WAAW,WAAW;GACtB,OAAO,WAAW;EACpB;CACF,CAAC;CAGD,QAAQ,OAAO,WACb,KAAK,UAAU;EACb,GAAG;EACH,aAAa,YAAY,KAAK,EAAE,QAAQ,UAAU,iBAAiB;GACjE;GACA;GACA;EACF,EAAE;CACJ,CAAC,CACH;CACA,IAAI,OAAO,UACT,MAAM,IAAI,yBAAyB,SAAS,2BAA2B;CACzE,OAAO;EACL,GAAG;EACH,aAAa,YAAY,KAAK,gBAAgB;GAC5C,GAAG;GACH,OAAO,OAAO,KAAK,WAAW,KAAK;EACrC,EAAE;CACJ;AACF"}
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { t as __exportAll } from "./chunks/rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import "./chunks/__smrt-register__-
|
|
2
|
+
import "./chunks/__smrt-register__-DyB0ALdL.js";
|
|
3
3
|
import { a as registerMessagingProvider, n as getMessagingProvider, o as ZulipSender, r as listMessagingProviders, s as TelegramSender, t as ensureBuiltinMessagingProvidersRegistered } from "./chunks/providers-4iLula-V.js";
|
|
4
|
-
import { r as Account, t as AccountCollection } from "./chunks/AccountCollection-
|
|
5
|
-
import { t as Message } from "./chunks/Message-
|
|
6
|
-
import { t as MessageCollection } from "./chunks/MessageCollection-
|
|
7
|
-
import { t as Email } from "./chunks/Email-
|
|
8
|
-
import { t as EmailFolder } from "./chunks/EmailFolder-
|
|
4
|
+
import { r as Account, t as AccountCollection } from "./chunks/AccountCollection-D0jYNESQ.js";
|
|
5
|
+
import { t as Message } from "./chunks/Message-CSv9rJva.js";
|
|
6
|
+
import { t as MessageCollection } from "./chunks/MessageCollection-4yzuqVl4.js";
|
|
7
|
+
import { t as Email } from "./chunks/Email-hneqk2_l.js";
|
|
8
|
+
import { t as EmailFolder } from "./chunks/EmailFolder-CFd0haPW.js";
|
|
9
9
|
import { t as SlackSender } from "./chunks/SlackSender-CjSvwY1K.js";
|
|
10
10
|
import { t as TweetSender } from "./chunks/TweetSender-CcLPNNi1.js";
|
|
11
11
|
import { SmrtCollection, SmrtObject, crossPackageRef, field, foreignKey, importOptionalDependency, isUniqueViolationError, smrt } from "@happyvertical/smrt-core";
|
|
@@ -98,7 +98,7 @@ var Attachment = class extends SmrtObject {
|
|
|
98
98
|
*/
|
|
99
99
|
async getMessage() {
|
|
100
100
|
if (!this.messageId) return null;
|
|
101
|
-
const { MessageCollection } = await import("./chunks/MessageCollection-
|
|
101
|
+
const { MessageCollection } = await import("./chunks/MessageCollection-4yzuqVl4.js").then((n) => n.n);
|
|
102
102
|
return await (await MessageCollection.create(this.options)).get({ id: this.messageId });
|
|
103
103
|
}
|
|
104
104
|
/**
|
|
@@ -622,6 +622,28 @@ var EmailAccount = class extends Account {
|
|
|
622
622
|
});
|
|
623
623
|
}
|
|
624
624
|
/**
|
|
625
|
+
* Read an immutable body/attachment-byte snapshot for an authorized intake host.
|
|
626
|
+
* Does not sync, acknowledge, mark read or advance mailbox checkpoints.
|
|
627
|
+
* Metadata-only providers fail explicitly; provider paths are never dereferenced.
|
|
628
|
+
*/
|
|
629
|
+
async readIntakeMessage(locator, maxBytes, imapIdentity) {
|
|
630
|
+
if (!this.id || !this.isActive || !locator) throw new Error("Email intake account unavailable");
|
|
631
|
+
const client = await this.createClient();
|
|
632
|
+
try {
|
|
633
|
+
await client.connect();
|
|
634
|
+
if (this.providerType === "imap") {
|
|
635
|
+
if (!imapIdentity?.folder || !imapIdentity.uid || !Number.isSafeInteger(imapIdentity.uidValidity)) throw new Error("IMAP intake requires folder and immutable UID identity");
|
|
636
|
+
if ((await client.selectFolder(imapIdentity.folder)).uidValidity !== imapIdentity.uidValidity) throw new Error("IMAP intake identity changed");
|
|
637
|
+
}
|
|
638
|
+
const message = await client.getMessage(locator);
|
|
639
|
+
if (this.providerType === "imap" && message.id !== imapIdentity?.uid) throw new Error("IMAP intake identity changed");
|
|
640
|
+
const { snapshotEmailForIntake } = await import("./chunks/intake-snapshot-B03bDtSW.js");
|
|
641
|
+
return snapshotEmailForIntake(this.id, message, maxBytes);
|
|
642
|
+
} finally {
|
|
643
|
+
await client.disconnect();
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
625
647
|
* Sync emails from the email server to the database
|
|
626
648
|
*/
|
|
627
649
|
async syncFrom(options = {}) {
|
|
@@ -648,7 +670,7 @@ var EmailAccount = class extends Account {
|
|
|
648
670
|
for (const folderName of foldersToSync) try {
|
|
649
671
|
let folder = await folderCollection.getByPath(accountId, folderName);
|
|
650
672
|
if (!folder) {
|
|
651
|
-
const { EmailFolder } = await import("./chunks/EmailFolder-
|
|
673
|
+
const { EmailFolder } = await import("./chunks/EmailFolder-CFd0haPW.js").then((n) => n.n);
|
|
652
674
|
folder = new EmailFolder({
|
|
653
675
|
...this.childOptions(),
|
|
654
676
|
accountId,
|
|
@@ -673,7 +695,7 @@ var EmailAccount = class extends Account {
|
|
|
673
695
|
result.messagesSkipped++;
|
|
674
696
|
continue;
|
|
675
697
|
}
|
|
676
|
-
const { Email } = await import("./chunks/Email-
|
|
698
|
+
const { Email } = await import("./chunks/Email-hneqk2_l.js").then((n) => n.n);
|
|
677
699
|
let email = existingEmail;
|
|
678
700
|
if (!email) {
|
|
679
701
|
email = new Email({
|