@jait/gateway 0.1.497 → 0.1.499

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 (122) hide show
  1. package/dist/db/migrations.d.ts.map +1 -1
  2. package/dist/db/migrations.js +22 -0
  3. package/dist/db/migrations.js.map +1 -1
  4. package/dist/db/schema.d.ts +178 -0
  5. package/dist/db/schema.d.ts.map +1 -1
  6. package/dist/db/schema.js +15 -0
  7. package/dist/db/schema.js.map +1 -1
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +5 -0
  10. package/dist/index.js.map +1 -1
  11. package/dist/routes/chat.d.ts.map +1 -1
  12. package/dist/routes/chat.js +77 -7
  13. package/dist/routes/chat.js.map +1 -1
  14. package/dist/routes/email.d.ts +5 -0
  15. package/dist/routes/email.d.ts.map +1 -0
  16. package/dist/routes/email.js +202 -0
  17. package/dist/routes/email.js.map +1 -0
  18. package/dist/security/tool-profiles.d.ts.map +1 -1
  19. package/dist/security/tool-profiles.js +3 -0
  20. package/dist/security/tool-profiles.js.map +1 -1
  21. package/dist/server.d.ts +1 -0
  22. package/dist/server.d.ts.map +1 -1
  23. package/dist/server.js +4 -0
  24. package/dist/server.js.map +1 -1
  25. package/dist/services/email/gmail.d.ts +16 -0
  26. package/dist/services/email/gmail.d.ts.map +1 -0
  27. package/dist/services/email/gmail.js +170 -0
  28. package/dist/services/email/gmail.js.map +1 -0
  29. package/dist/services/email/index.d.ts +3 -0
  30. package/dist/services/email/index.d.ts.map +1 -0
  31. package/dist/services/email/index.js +2 -0
  32. package/dist/services/email/index.js.map +1 -0
  33. package/dist/services/email/oauth.d.ts +32 -0
  34. package/dist/services/email/oauth.d.ts.map +1 -0
  35. package/dist/services/email/oauth.js +105 -0
  36. package/dist/services/email/oauth.js.map +1 -0
  37. package/dist/services/email/outlook.d.ts +15 -0
  38. package/dist/services/email/outlook.d.ts.map +1 -0
  39. package/dist/services/email/outlook.js +142 -0
  40. package/dist/services/email/outlook.js.map +1 -0
  41. package/dist/services/email/service.d.ts +50 -0
  42. package/dist/services/email/service.d.ts.map +1 -0
  43. package/dist/services/email/service.js +277 -0
  44. package/dist/services/email/service.js.map +1 -0
  45. package/dist/services/email/types.d.ts +82 -0
  46. package/dist/services/email/types.d.ts.map +1 -0
  47. package/dist/services/email/types.js +3 -0
  48. package/dist/services/email/types.js.map +1 -0
  49. package/dist/tools/email-tools.d.ts +52 -0
  50. package/dist/tools/email-tools.d.ts.map +1 -0
  51. package/dist/tools/email-tools.js +237 -0
  52. package/dist/tools/email-tools.js.map +1 -0
  53. package/dist/tools/index.d.ts +3 -1
  54. package/dist/tools/index.d.ts.map +1 -1
  55. package/dist/tools/index.js +16 -2
  56. package/dist/tools/index.js.map +1 -1
  57. package/dist/tools/project-tools.d.ts +6 -0
  58. package/dist/tools/project-tools.d.ts.map +1 -1
  59. package/dist/tools/project-tools.js +82 -0
  60. package/dist/tools/project-tools.js.map +1 -1
  61. package/dist/tools/tool-names.d.ts +1 -0
  62. package/dist/tools/tool-names.d.ts.map +1 -1
  63. package/dist/tools/tool-names.js +1 -0
  64. package/dist/tools/tool-names.js.map +1 -1
  65. package/package.json +2 -2
  66. package/web-dist/assets/{_basePickBy-1ypMBiW_.js → _basePickBy-CzT63eI9.js} +1 -1
  67. package/web-dist/assets/{_baseUniq-DvjcbfPq.js → _baseUniq-C9jker1F.js} +1 -1
  68. package/web-dist/assets/{arc-ErevYm19.js → arc-DljFfWWm.js} +1 -1
  69. package/web-dist/assets/{architectureDiagram-2XIMDMQ5-D_WVp0kY.js → architectureDiagram-2XIMDMQ5-pEbMBiw_.js} +1 -1
  70. package/web-dist/assets/{blockDiagram-WCTKOSBZ-Bo6-xom-.js → blockDiagram-WCTKOSBZ-A_4J6Sb-.js} +1 -1
  71. package/web-dist/assets/{c4Diagram-IC4MRINW-D9M8EKu_.js → c4Diagram-IC4MRINW-COgCzBlY.js} +1 -1
  72. package/web-dist/assets/channel-xM6w002v.js +1 -0
  73. package/web-dist/assets/{chunk-4BX2VUAB-WH1KAVAb.js → chunk-4BX2VUAB-Bfy5mnZM.js} +1 -1
  74. package/web-dist/assets/{chunk-55IACEB6-D2a2qrrp.js → chunk-55IACEB6-BHbwUxN1.js} +1 -1
  75. package/web-dist/assets/{chunk-FMBD7UC4-28DcGMIY.js → chunk-FMBD7UC4-oWbyVk_l.js} +1 -1
  76. package/web-dist/assets/{chunk-JSJVCQXG-C1uNGWZs.js → chunk-JSJVCQXG-DICPKbbU.js} +1 -1
  77. package/web-dist/assets/{chunk-KX2RTZJC-V1qtcDEn.js → chunk-KX2RTZJC-S1AI6fsb.js} +1 -1
  78. package/web-dist/assets/{chunk-NQ4KR5QH-cug-v0rY.js → chunk-NQ4KR5QH-CC2BDuwQ.js} +1 -1
  79. package/web-dist/assets/{chunk-QZHKN3VN-CM17QePX.js → chunk-QZHKN3VN-BU0b1vSt.js} +1 -1
  80. package/web-dist/assets/{chunk-WL4C6EOR-DlYbqSTG.js → chunk-WL4C6EOR-BxRy9Kn0.js} +1 -1
  81. package/web-dist/assets/classDiagram-VBA2DB6C-BwiCmurD.js +1 -0
  82. package/web-dist/assets/classDiagram-v2-RAHNMMFH-BwiCmurD.js +1 -0
  83. package/web-dist/assets/clone-BXkaMZnK.js +1 -0
  84. package/web-dist/assets/{cose-bilkent-S5V4N54A-CVsGoDQL.js → cose-bilkent-S5V4N54A-C0lXwD6L.js} +1 -1
  85. package/web-dist/assets/{dagre-KLK3FWXG-DLQZVyW4.js → dagre-KLK3FWXG-DsCVwtnr.js} +1 -1
  86. package/web-dist/assets/{diagram-E7M64L7V-BF0y78lG.js → diagram-E7M64L7V-CRFZjLO4.js} +1 -1
  87. package/web-dist/assets/{diagram-IFDJBPK2-MuDqalfZ.js → diagram-IFDJBPK2-CxxDuheX.js} +1 -1
  88. package/web-dist/assets/{diagram-P4PSJMXO-e36wc7XG.js → diagram-P4PSJMXO-DdN9wKJP.js} +1 -1
  89. package/web-dist/assets/{erDiagram-INFDFZHY-B_i7tPHh.js → erDiagram-INFDFZHY-BxRMeXZf.js} +1 -1
  90. package/web-dist/assets/{flowDiagram-PKNHOUZH-fPB07Diy.js → flowDiagram-PKNHOUZH--76cPw_T.js} +1 -1
  91. package/web-dist/assets/{ganttDiagram-A5KZAMGK-q8EsM9Gb.js → ganttDiagram-A5KZAMGK-D81XRpy6.js} +1 -1
  92. package/web-dist/assets/{gitGraphDiagram-K3NZZRJ6-BiAyblPL.js → gitGraphDiagram-K3NZZRJ6-BWTqK6Hq.js} +1 -1
  93. package/web-dist/assets/{graph-DnNeq8po.js → graph-e1i_2mNj.js} +1 -1
  94. package/web-dist/assets/index-BU0ZMPd5.css +32 -0
  95. package/web-dist/assets/{index-Bk_qadgU.js → index-C_vS46mJ.js} +1 -1
  96. package/web-dist/assets/{index-BbmkMmHZ.js → index-_OeJ0-l0.js} +1 -1
  97. package/web-dist/assets/{index-CzRne9la.js → index-oEvNrdmq.js} +395 -373
  98. package/web-dist/assets/{infoDiagram-LFFYTUFH-C3TzSSln.js → infoDiagram-LFFYTUFH-BAvnH6OJ.js} +1 -1
  99. package/web-dist/assets/{ishikawaDiagram-PHBUUO56-szGd8_KC.js → ishikawaDiagram-PHBUUO56-DaNqVDUe.js} +1 -1
  100. package/web-dist/assets/{journeyDiagram-4ABVD52K-ByTvobTa.js → journeyDiagram-4ABVD52K-BjDRRfop.js} +1 -1
  101. package/web-dist/assets/{kanban-definition-K7BYSVSG-DoUUzwjw.js → kanban-definition-K7BYSVSG-Qw6LXlh0.js} +1 -1
  102. package/web-dist/assets/{layout-BzJ0RrG1.js → layout-BhFuErQG.js} +1 -1
  103. package/web-dist/assets/{linear-B5XYxmuh.js → linear-CVpOVEfb.js} +1 -1
  104. package/web-dist/assets/{mindmap-definition-YRQLILUH-FaHbvuby.js → mindmap-definition-YRQLILUH-HX2oEkzo.js} +1 -1
  105. package/web-dist/assets/{pieDiagram-SKSYHLDU-F0mNDNRX.js → pieDiagram-SKSYHLDU-eoDXKsir.js} +1 -1
  106. package/web-dist/assets/{quadrantDiagram-337W2JSQ-CSy2sGI7.js → quadrantDiagram-337W2JSQ-BMuqPJ4T.js} +1 -1
  107. package/web-dist/assets/{requirementDiagram-Z7DCOOCP-iXp1hJSy.js → requirementDiagram-Z7DCOOCP-DortKE8d.js} +1 -1
  108. package/web-dist/assets/{sankeyDiagram-WA2Y5GQK-BUFT8Ncy.js → sankeyDiagram-WA2Y5GQK-BdCE80-q.js} +1 -1
  109. package/web-dist/assets/{sequenceDiagram-2WXFIKYE-iWc1z5r5.js → sequenceDiagram-2WXFIKYE-CcYDmGFB.js} +1 -1
  110. package/web-dist/assets/{stateDiagram-RAJIS63D-Dmla9JkM.js → stateDiagram-RAJIS63D-CSTfSkb3.js} +1 -1
  111. package/web-dist/assets/stateDiagram-v2-FVOUBMTO-DBn-vddG.js +1 -0
  112. package/web-dist/assets/{timeline-definition-YZTLITO2-4XUMaeyN.js → timeline-definition-YZTLITO2-CluVwYjy.js} +1 -1
  113. package/web-dist/assets/{treemap-KZPCXAKY-BiXISVos.js → treemap-KZPCXAKY-Ds4wGITO.js} +1 -1
  114. package/web-dist/assets/{vennDiagram-LZ73GAT5-BHzH1mWp.js → vennDiagram-LZ73GAT5-DDk9o8W5.js} +1 -1
  115. package/web-dist/assets/{xychartDiagram-JWTSCODW-C1rAefFy.js → xychartDiagram-JWTSCODW-BWpgTsfS.js} +1 -1
  116. package/web-dist/index.html +2 -2
  117. package/web-dist/assets/channel-CzVoFm04.js +0 -1
  118. package/web-dist/assets/classDiagram-VBA2DB6C-CkMkzWkJ.js +0 -1
  119. package/web-dist/assets/classDiagram-v2-RAHNMMFH-CkMkzWkJ.js +0 -1
  120. package/web-dist/assets/clone-BrtlKZXp.js +0 -1
  121. package/web-dist/assets/index-C-Ol-PwZ.css +0 -32
  122. package/web-dist/assets/stateDiagram-v2-FVOUBMTO-DrmN0_X9.js +0 -1
@@ -0,0 +1,170 @@
1
+ // Gmail mailbox client (Gmail REST API v1).
2
+ const BASE = "https://gmail.googleapis.com/gmail/v1/users/me";
3
+ // Map friendly folder names to Gmail system label ids; pass real label ids through.
4
+ const SYSTEM_LABELS = {
5
+ inbox: "INBOX", sent: "SENT", drafts: "DRAFT", draft: "DRAFT",
6
+ spam: "SPAM", trash: "TRASH", starred: "STARRED", important: "IMPORTANT", unread: "UNREAD",
7
+ };
8
+ function normalizeLabelId(folder) {
9
+ return SYSTEM_LABELS[folder.toLowerCase()] ?? folder;
10
+ }
11
+ function header(headers, name) {
12
+ return headers?.find((h) => h.name.toLowerCase() === name.toLowerCase())?.value ?? "";
13
+ }
14
+ function decodeBody(data) {
15
+ if (!data)
16
+ return "";
17
+ return Buffer.from(data.replace(/-/g, "+").replace(/_/g, "/"), "base64").toString("utf8");
18
+ }
19
+ /** Walk the MIME tree collecting the first text/plain and text/html bodies. */
20
+ function extractBodies(part, acc) {
21
+ if (!part)
22
+ return;
23
+ const mime = part.mimeType ?? "";
24
+ if (part.filename)
25
+ acc.attachments = true;
26
+ if (mime === "text/plain" && !acc.text)
27
+ acc.text = decodeBody(part.body?.data);
28
+ else if (mime === "text/html" && !acc.html)
29
+ acc.html = decodeBody(part.body?.data);
30
+ for (const child of part.parts ?? [])
31
+ extractBodies(child, acc);
32
+ }
33
+ export class GmailClient {
34
+ async gfetch(accessToken, path, init) {
35
+ const res = await fetch(`${BASE}${path}`, {
36
+ ...init,
37
+ headers: {
38
+ Authorization: `Bearer ${accessToken}`,
39
+ ...(init?.body ? { "Content-Type": "application/json" } : {}),
40
+ ...(init?.headers ?? {}),
41
+ },
42
+ });
43
+ const text = await res.text();
44
+ const data = text ? JSON.parse(text) : {};
45
+ if (!res.ok) {
46
+ const msg = data?.error?.message ?? `HTTP ${res.status}`;
47
+ throw new Error(`Gmail API error: ${msg}`);
48
+ }
49
+ return data;
50
+ }
51
+ summarize(m, labelNames) {
52
+ const h = m.payload?.headers;
53
+ const labelIds = m.labelIds ?? [];
54
+ return {
55
+ id: m.id,
56
+ threadId: m.threadId,
57
+ from: header(h, "From"),
58
+ to: header(h, "To"),
59
+ subject: header(h, "Subject"),
60
+ snippet: m.snippet ?? "",
61
+ date: header(h, "Date"),
62
+ unread: labelIds.includes("UNREAD"),
63
+ labels: labelIds
64
+ .filter((id) => !id.startsWith("CATEGORY_"))
65
+ .map((id) => labelNames.get(id) ?? id),
66
+ hasAttachments: false,
67
+ };
68
+ }
69
+ async labelMaps(accessToken) {
70
+ const data = (await this.gfetch(accessToken, "/labels"));
71
+ const byId = new Map();
72
+ const byName = new Map();
73
+ for (const l of data.labels ?? []) {
74
+ byId.set(l.id, l.name);
75
+ byName.set(l.name.toLowerCase(), l.id);
76
+ }
77
+ return { byId, byName };
78
+ }
79
+ async listMessages(accessToken, opts) {
80
+ const limit = Math.min(Math.max(opts.limit ?? 25, 1), 50);
81
+ const params = new URLSearchParams({ maxResults: String(limit) });
82
+ if (opts.query)
83
+ params.set("q", opts.query);
84
+ if (opts.folder && opts.folder.toLowerCase() !== "all") {
85
+ params.set("labelIds", normalizeLabelId(opts.folder));
86
+ }
87
+ const list = (await this.gfetch(accessToken, `/messages?${params.toString()}`));
88
+ const ids = (list.messages ?? []).map((x) => x.id);
89
+ if (ids.length === 0)
90
+ return [];
91
+ const { byId } = await this.labelMaps(accessToken);
92
+ const metas = await Promise.all(ids.map((id) => this.gfetch(accessToken, `/messages/${id}?format=metadata&metadataHeaders=From&metadataHeaders=To&metadataHeaders=Subject&metadataHeaders=Date`)));
93
+ return metas.map((m) => this.summarize(m, byId));
94
+ }
95
+ async getMessage(accessToken, id) {
96
+ const m = (await this.gfetch(accessToken, `/messages/${id}?format=full`));
97
+ const { byId } = await this.labelMaps(accessToken);
98
+ const summary = this.summarize(m, byId);
99
+ const bodies = { text: "", html: "", attachments: false };
100
+ extractBodies(m.payload, bodies);
101
+ return {
102
+ ...summary,
103
+ cc: header(m.payload?.headers, "Cc"),
104
+ bodyText: bodies.text,
105
+ bodyHtml: bodies.html,
106
+ hasAttachments: bodies.attachments,
107
+ };
108
+ }
109
+ async sendMessage(accessToken, input) {
110
+ const lines = [
111
+ `To: ${input.to}`,
112
+ input.cc ? `Cc: ${input.cc}` : "",
113
+ input.bcc ? `Bcc: ${input.bcc}` : "",
114
+ `Subject: ${input.subject}`,
115
+ "MIME-Version: 1.0",
116
+ `Content-Type: ${input.html ? "text/html" : "text/plain"}; charset=UTF-8`,
117
+ "",
118
+ input.body,
119
+ ].filter(Boolean);
120
+ const raw = Buffer.from(lines.join("\r\n"), "utf8").toString("base64url");
121
+ const body = { raw };
122
+ if (input.replyToMessageId) {
123
+ const orig = (await this.gfetch(accessToken, `/messages/${input.replyToMessageId}?format=metadata`));
124
+ if (orig.threadId)
125
+ body.threadId = orig.threadId;
126
+ }
127
+ const sent = (await this.gfetch(accessToken, "/messages/send", {
128
+ method: "POST",
129
+ body: JSON.stringify(body),
130
+ }));
131
+ return { id: sent.id };
132
+ }
133
+ async tagMessage(accessToken, id, add, remove) {
134
+ const { byName } = await this.labelMaps(accessToken);
135
+ const resolve = async (name) => {
136
+ const builtin = name.toUpperCase();
137
+ if (["INBOX", "UNREAD", "STARRED", "IMPORTANT", "SPAM", "TRASH"].includes(builtin))
138
+ return builtin;
139
+ const existing = byName.get(name.toLowerCase());
140
+ if (existing)
141
+ return existing;
142
+ const created = (await this.gfetch(accessToken, "/labels", {
143
+ method: "POST",
144
+ body: JSON.stringify({ name, labelListVisibility: "labelShow", messageListVisibility: "show" }),
145
+ }));
146
+ byName.set(name.toLowerCase(), created.id);
147
+ return created.id;
148
+ };
149
+ const addLabelIds = await Promise.all(add.map(resolve));
150
+ const removeLabelIds = await Promise.all(remove.map(resolve));
151
+ await this.gfetch(accessToken, `/messages/${id}/modify`, {
152
+ method: "POST",
153
+ body: JSON.stringify({ addLabelIds, removeLabelIds }),
154
+ });
155
+ }
156
+ async deleteMessage(accessToken, id) {
157
+ await this.gfetch(accessToken, `/messages/${id}/trash`, { method: "POST" });
158
+ }
159
+ async listFolders(accessToken) {
160
+ const data = (await this.gfetch(accessToken, "/labels"));
161
+ return (data.labels ?? [])
162
+ .filter((l) => !l.id.startsWith("CATEGORY_"))
163
+ .map((l) => ({ id: l.id, name: l.name }));
164
+ }
165
+ async getProfileEmail(accessToken) {
166
+ const data = (await this.gfetch(accessToken, "/profile"));
167
+ return data.emailAddress ?? "";
168
+ }
169
+ }
170
+ //# sourceMappingURL=gmail.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gmail.js","sourceRoot":"","sources":["../../../src/services/email/gmail.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { EmailService } from "./service.js";
2
+ export type { EmailAccount, EmailProvider, EmailMessageSummary, EmailMessageFull, EmailFolder, ListMessagesOptions, SendMessageInput, } from "./types.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/email/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,YAAY,EACV,YAAY,EACZ,aAAa,EACb,mBAAmB,EACnB,gBAAgB,EAChB,WAAW,EACX,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { EmailService } from "./service.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/services/email/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,32 @@
1
+ import type { EmailProvider, EmailTokens } from "./types.js";
2
+ export interface OAuthClientCredentials {
3
+ clientId: string;
4
+ clientSecret: string;
5
+ }
6
+ export type ClientCredentialResolver = (provider: EmailProvider) => OAuthClientCredentials | null;
7
+ export declare function envClientCredentials(provider: EmailProvider): OAuthClientCredentials | null;
8
+ /** PKCE verifier/challenge pair (S256). */
9
+ export declare function createPkce(): {
10
+ verifier: string;
11
+ challenge: string;
12
+ };
13
+ export declare function buildAuthorizeUrl(params: {
14
+ provider: EmailProvider;
15
+ credentials: OAuthClientCredentials;
16
+ redirectUri: string;
17
+ state: string;
18
+ codeChallenge: string;
19
+ }): string;
20
+ export declare function exchangeCode(params: {
21
+ provider: EmailProvider;
22
+ credentials: OAuthClientCredentials;
23
+ redirectUri: string;
24
+ code: string;
25
+ codeVerifier: string;
26
+ }): Promise<EmailTokens>;
27
+ export declare function refreshTokens(params: {
28
+ provider: EmailProvider;
29
+ credentials: OAuthClientCredentials;
30
+ refreshToken: string;
31
+ }): Promise<EmailTokens>;
32
+ //# sourceMappingURL=oauth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../../src/services/email/oauth.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAkC7D,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,wBAAwB,GAAG,CACrC,QAAQ,EAAE,aAAa,KACpB,sBAAsB,GAAG,IAAI,CAAC;AAEnC,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,aAAa,GAAG,sBAAsB,GAAG,IAAI,CAM3F;AAED,2CAA2C;AAC3C,wBAAgB,UAAU,IAAI;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAIpE;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE;IACxC,QAAQ,EAAE,aAAa,CAAC;IACxB,WAAW,EAAE,sBAAsB,CAAC;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;CACvB,GAAG,MAAM,CAcT;AA6BD,wBAAsB,YAAY,CAAC,MAAM,EAAE;IACzC,QAAQ,EAAE,aAAa,CAAC;IACxB,WAAW,EAAE,sBAAsB,CAAC;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,OAAO,CAAC,WAAW,CAAC,CAUvB;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE;IAC1C,QAAQ,EAAE,aAAa,CAAC;IACxB,WAAW,EAAE,sBAAsB,CAAC;IACpC,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,OAAO,CAAC,WAAW,CAAC,CAQvB"}
@@ -0,0 +1,105 @@
1
+ // OAuth2 (authorization-code) helpers for Gmail and Outlook.
2
+ //
3
+ // Client credentials are resolved (in priority order) from:
4
+ // 1. Per-user secrets (type "email-oauth-app", keys "<provider>-client-id" /
5
+ // "<provider>-client-secret") — lets the user configure apps from the UI.
6
+ // 2. Gateway environment variables.
7
+ //
8
+ // Gmail: GMAIL_OAUTH_CLIENT_ID / GMAIL_OAUTH_CLIENT_SECRET
9
+ // Outlook: OUTLOOK_OAUTH_CLIENT_ID / OUTLOOK_OAUTH_CLIENT_SECRET
10
+ import { createHash, randomBytes } from "node:crypto";
11
+ const PROVIDERS = {
12
+ gmail: {
13
+ authorizeUrl: "https://accounts.google.com/o/oauth2/v2/auth",
14
+ tokenUrl: "https://oauth2.googleapis.com/token",
15
+ scopes: [
16
+ "https://www.googleapis.com/auth/gmail.modify",
17
+ "https://www.googleapis.com/auth/gmail.send",
18
+ ],
19
+ // offline + consent are required to reliably receive a refresh token.
20
+ authorizeParams: { access_type: "offline", prompt: "consent" },
21
+ },
22
+ outlook: {
23
+ authorizeUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
24
+ tokenUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
25
+ scopes: [
26
+ "offline_access",
27
+ "https://graph.microsoft.com/Mail.ReadWrite",
28
+ "https://graph.microsoft.com/Mail.Send",
29
+ "https://graph.microsoft.com/User.Read",
30
+ ],
31
+ authorizeParams: { response_mode: "query" },
32
+ },
33
+ };
34
+ export function envClientCredentials(provider) {
35
+ const prefix = provider === "gmail" ? "GMAIL" : "OUTLOOK";
36
+ const clientId = process.env[`${prefix}_OAUTH_CLIENT_ID`]?.trim();
37
+ const clientSecret = process.env[`${prefix}_OAUTH_CLIENT_SECRET`]?.trim();
38
+ if (!clientId || !clientSecret)
39
+ return null;
40
+ return { clientId, clientSecret };
41
+ }
42
+ /** PKCE verifier/challenge pair (S256). */
43
+ export function createPkce() {
44
+ const verifier = randomBytes(32).toString("base64url");
45
+ const challenge = createHash("sha256").update(verifier).digest("base64url");
46
+ return { verifier, challenge };
47
+ }
48
+ export function buildAuthorizeUrl(params) {
49
+ const cfg = PROVIDERS[params.provider];
50
+ const url = new URL(cfg.authorizeUrl);
51
+ url.searchParams.set("client_id", params.credentials.clientId);
52
+ url.searchParams.set("redirect_uri", params.redirectUri);
53
+ url.searchParams.set("response_type", "code");
54
+ url.searchParams.set("scope", cfg.scopes.join(" "));
55
+ url.searchParams.set("state", params.state);
56
+ url.searchParams.set("code_challenge", params.codeChallenge);
57
+ url.searchParams.set("code_challenge_method", "S256");
58
+ for (const [k, v] of Object.entries(cfg.authorizeParams)) {
59
+ url.searchParams.set(k, v);
60
+ }
61
+ return url.toString();
62
+ }
63
+ function tokensFromResponse(data, fallbackRefresh) {
64
+ const expiresIn = typeof data["expires_in"] === "number" ? data["expires_in"] : 3600;
65
+ return {
66
+ accessToken: String(data["access_token"] ?? ""),
67
+ refreshToken: data["refresh_token"] ?? fallbackRefresh ?? null,
68
+ expiresAt: Date.now() + expiresIn * 1000,
69
+ scope: data["scope"],
70
+ };
71
+ }
72
+ async function postToken(provider, body) {
73
+ const res = await fetch(PROVIDERS[provider].tokenUrl, {
74
+ method: "POST",
75
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
76
+ body: new URLSearchParams(body).toString(),
77
+ });
78
+ const data = (await res.json().catch(() => ({})));
79
+ if (!res.ok) {
80
+ const detail = data["error_description"] ?? data["error"] ?? `HTTP ${res.status}`;
81
+ throw new Error(`OAuth token request failed: ${detail}`);
82
+ }
83
+ return data;
84
+ }
85
+ export async function exchangeCode(params) {
86
+ const data = await postToken(params.provider, {
87
+ client_id: params.credentials.clientId,
88
+ client_secret: params.credentials.clientSecret,
89
+ code: params.code,
90
+ redirect_uri: params.redirectUri,
91
+ grant_type: "authorization_code",
92
+ code_verifier: params.codeVerifier,
93
+ });
94
+ return tokensFromResponse(data);
95
+ }
96
+ export async function refreshTokens(params) {
97
+ const data = await postToken(params.provider, {
98
+ client_id: params.credentials.clientId,
99
+ client_secret: params.credentials.clientSecret,
100
+ refresh_token: params.refreshToken,
101
+ grant_type: "refresh_token",
102
+ });
103
+ return tokensFromResponse(data, params.refreshToken);
104
+ }
105
+ //# sourceMappingURL=oauth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../../src/services/email/oauth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { EmailFolder, EmailMessageFull, EmailMessageSummary, ListMessagesOptions, MailboxClient, SendMessageInput } from "./types.js";
2
+ export declare class OutlookClient implements MailboxClient {
3
+ private gfetch;
4
+ private summarize;
5
+ listMessages(accessToken: string, opts: ListMessagesOptions): Promise<EmailMessageSummary[]>;
6
+ getMessage(accessToken: string, id: string): Promise<EmailMessageFull>;
7
+ sendMessage(accessToken: string, input: SendMessageInput): Promise<{
8
+ id: string;
9
+ }>;
10
+ tagMessage(accessToken: string, id: string, add: string[], remove: string[]): Promise<void>;
11
+ deleteMessage(accessToken: string, id: string): Promise<void>;
12
+ listFolders(accessToken: string): Promise<EmailFolder[]>;
13
+ getProfileEmail(accessToken: string): Promise<string>;
14
+ }
15
+ //# sourceMappingURL=outlook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outlook.d.ts","sourceRoot":"","sources":["../../../src/services/email/outlook.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,WAAW,EACX,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACb,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAuCpB,qBAAa,aAAc,YAAW,aAAa;YACnC,MAAM;IAmBpB,OAAO,CAAC,SAAS;IAeX,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAsB5F,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAYtE,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IA8BlF,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAW3F,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK7D,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAOxD,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAO5D"}
@@ -0,0 +1,142 @@
1
+ // Outlook mailbox client (Microsoft Graph v1.0).
2
+ const BASE = "https://graph.microsoft.com/v1.0";
3
+ function fmtRecipient(r) {
4
+ const ea = r?.emailAddress;
5
+ if (!ea)
6
+ return "";
7
+ return ea.name ? `${ea.name} <${ea.address ?? ""}>` : ea.address ?? "";
8
+ }
9
+ function fmtRecipients(list) {
10
+ return (list ?? []).map(fmtRecipient).filter(Boolean).join(", ");
11
+ }
12
+ function toGraphRecipients(value) {
13
+ if (!value)
14
+ return [];
15
+ return value
16
+ .split(/[,;]/)
17
+ .map((s) => s.trim())
18
+ .filter(Boolean)
19
+ .map((address) => ({ emailAddress: { address } }));
20
+ }
21
+ export class OutlookClient {
22
+ async gfetch(accessToken, path, init) {
23
+ const res = await fetch(`${BASE}${path}`, {
24
+ ...init,
25
+ headers: {
26
+ Authorization: `Bearer ${accessToken}`,
27
+ ...(init?.body ? { "Content-Type": "application/json" } : {}),
28
+ ...(init?.headers ?? {}),
29
+ },
30
+ });
31
+ if (res.status === 204)
32
+ return {};
33
+ const text = await res.text();
34
+ const data = text ? JSON.parse(text) : {};
35
+ if (!res.ok) {
36
+ const msg = data?.error?.message ?? `HTTP ${res.status}`;
37
+ throw new Error(`Microsoft Graph error: ${msg}`);
38
+ }
39
+ return data;
40
+ }
41
+ summarize(m) {
42
+ return {
43
+ id: m.id,
44
+ threadId: m.conversationId,
45
+ from: fmtRecipient(m.from),
46
+ to: fmtRecipients(m.toRecipients),
47
+ subject: m.subject ?? "",
48
+ snippet: m.bodyPreview ?? "",
49
+ date: m.receivedDateTime ?? "",
50
+ unread: m.isRead === false,
51
+ labels: m.categories ?? [],
52
+ hasAttachments: m.hasAttachments ?? false,
53
+ };
54
+ }
55
+ async listMessages(accessToken, opts) {
56
+ const limit = Math.min(Math.max(opts.limit ?? 25, 1), 50);
57
+ const folder = opts.folder && opts.folder.toLowerCase() !== "all" ? opts.folder : "inbox";
58
+ const params = new URLSearchParams({
59
+ $top: String(limit),
60
+ $select: "id,conversationId,subject,bodyPreview,receivedDateTime,isRead,hasAttachments,categories,from,toRecipients",
61
+ });
62
+ let path;
63
+ if (opts.query) {
64
+ // $search cannot be combined with $orderby.
65
+ params.set("$search", `"${opts.query.replace(/"/g, "")}"`);
66
+ path = `/me/mailFolders/${folder}/messages?${params.toString()}`;
67
+ }
68
+ else {
69
+ params.set("$orderby", "receivedDateTime desc");
70
+ path = `/me/mailFolders/${folder}/messages?${params.toString()}`;
71
+ }
72
+ const data = (await this.gfetch(accessToken, path, {
73
+ headers: { ConsistencyLevel: "eventual" },
74
+ }));
75
+ return (data.value ?? []).map((m) => this.summarize(m));
76
+ }
77
+ async getMessage(accessToken, id) {
78
+ const m = (await this.gfetch(accessToken, `/me/messages/${id}`));
79
+ const summary = this.summarize(m);
80
+ const isHtml = (m.body?.contentType ?? "").toLowerCase() === "html";
81
+ return {
82
+ ...summary,
83
+ cc: fmtRecipients(m.ccRecipients),
84
+ bodyText: isHtml ? "" : m.body?.content ?? "",
85
+ bodyHtml: isHtml ? m.body?.content ?? "" : "",
86
+ };
87
+ }
88
+ async sendMessage(accessToken, input) {
89
+ if (input.replyToMessageId) {
90
+ await this.gfetch(accessToken, `/me/messages/${input.replyToMessageId}/reply`, {
91
+ method: "POST",
92
+ body: JSON.stringify({
93
+ message: {
94
+ toRecipients: input.to ? toGraphRecipients(input.to) : undefined,
95
+ ccRecipients: toGraphRecipients(input.cc),
96
+ },
97
+ comment: input.body,
98
+ }),
99
+ });
100
+ return { id: input.replyToMessageId };
101
+ }
102
+ await this.gfetch(accessToken, "/me/sendMail", {
103
+ method: "POST",
104
+ body: JSON.stringify({
105
+ message: {
106
+ subject: input.subject,
107
+ body: { contentType: input.html ? "HTML" : "Text", content: input.body },
108
+ toRecipients: toGraphRecipients(input.to),
109
+ ccRecipients: toGraphRecipients(input.cc),
110
+ bccRecipients: toGraphRecipients(input.bcc),
111
+ },
112
+ saveToSentItems: true,
113
+ }),
114
+ });
115
+ return { id: "" };
116
+ }
117
+ async tagMessage(accessToken, id, add, remove) {
118
+ const m = (await this.gfetch(accessToken, `/me/messages/${id}?$select=categories`));
119
+ const current = new Set(m.categories ?? []);
120
+ for (const c of add)
121
+ current.add(c);
122
+ for (const c of remove)
123
+ current.delete(c);
124
+ await this.gfetch(accessToken, `/me/messages/${id}`, {
125
+ method: "PATCH",
126
+ body: JSON.stringify({ categories: [...current] }),
127
+ });
128
+ }
129
+ async deleteMessage(accessToken, id) {
130
+ // DELETE moves the message to Deleted Items.
131
+ await this.gfetch(accessToken, `/me/messages/${id}`, { method: "DELETE" });
132
+ }
133
+ async listFolders(accessToken) {
134
+ const data = (await this.gfetch(accessToken, "/me/mailFolders?$top=50&$select=id,displayName,unreadItemCount"));
135
+ return (data.value ?? []).map((f) => ({ id: f.id, name: f.displayName, unreadCount: f.unreadItemCount }));
136
+ }
137
+ async getProfileEmail(accessToken) {
138
+ const data = (await this.gfetch(accessToken, "/me?$select=mail,userPrincipalName"));
139
+ return data.mail ?? data.userPrincipalName ?? "";
140
+ }
141
+ }
142
+ //# sourceMappingURL=outlook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outlook.js","sourceRoot":"","sources":["../../../src/services/email/outlook.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import type { JaitDB } from "../../db/connection.js";
2
+ import type { UserSecretService } from "../user-secrets.js";
3
+ import { type OAuthClientCredentials } from "./oauth.js";
4
+ import type { EmailAccount, EmailFolder, EmailMessageFull, EmailMessageSummary, EmailProvider, ListMessagesOptions, SendMessageInput } from "./types.js";
5
+ export declare class EmailService {
6
+ private readonly db;
7
+ private readonly secrets;
8
+ private readonly clients;
9
+ private readonly pending;
10
+ constructor(db: JaitDB, secrets: UserSecretService);
11
+ /** Resolve OAuth app credentials: per-user secret first, then env. */
12
+ resolveCredentials(provider: EmailProvider, userId: string | null): OAuthClientCredentials | null;
13
+ /** Which providers are ready to connect (have OAuth app credentials). */
14
+ configuredProviders(userId: string | null): Record<EmailProvider, boolean>;
15
+ saveAppCredentials(userId: string | null, provider: EmailProvider, creds: OAuthClientCredentials): void;
16
+ startConnect(params: {
17
+ userId: string | null;
18
+ provider: EmailProvider;
19
+ redirectUri: string;
20
+ }): {
21
+ authUrl: string;
22
+ };
23
+ completeConnect(params: {
24
+ code: string;
25
+ state: string;
26
+ }): Promise<EmailAccount>;
27
+ listAccounts(userId: string | null): EmailAccount[];
28
+ getAccount(userId: string | null, accountId: string): EmailAccount | null;
29
+ /** Resolve an account by id, or fall back to the user's first account. */
30
+ resolveAccount(userId: string | null, accountId?: string): EmailAccount;
31
+ disconnect(userId: string | null, accountId: string): boolean;
32
+ private upsertAccount;
33
+ private storeTokens;
34
+ private loadTokens;
35
+ private findTokenSecretId;
36
+ private validAccessToken;
37
+ listMessages(userId: string | null, accountId: string | undefined, opts: ListMessagesOptions): Promise<{
38
+ account: EmailAccount;
39
+ messages: EmailMessageSummary[];
40
+ }>;
41
+ getMessage(userId: string | null, accountId: string | undefined, id: string): Promise<EmailMessageFull>;
42
+ sendMessage(userId: string | null, accountId: string | undefined, input: SendMessageInput): Promise<{
43
+ id: string;
44
+ }>;
45
+ tagMessage(userId: string | null, accountId: string | undefined, id: string, add: string[], remove: string[]): Promise<void>;
46
+ deleteMessage(userId: string | null, accountId: string | undefined, id: string): Promise<void>;
47
+ listFolders(userId: string | null, accountId: string | undefined): Promise<EmailFolder[]>;
48
+ private gcPending;
49
+ }
50
+ //# sourceMappingURL=service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/services/email/service.ts"],"names":[],"mappings":"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"}