zele 0.3.0 → 0.3.5

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 (157) hide show
  1. package/README.md +1 -1
  2. package/bin/zele +27 -0
  3. package/dist/api-utils.d.ts +51 -2
  4. package/dist/api-utils.js +89 -3
  5. package/dist/api-utils.js.map +1 -1
  6. package/dist/auth.d.ts +27 -6
  7. package/dist/auth.js +185 -129
  8. package/dist/auth.js.map +1 -1
  9. package/dist/calendar-client.d.ts +16 -9
  10. package/dist/calendar-client.js +163 -59
  11. package/dist/calendar-client.js.map +1 -1
  12. package/dist/cli.js +26 -1
  13. package/dist/cli.js.map +1 -1
  14. package/dist/commands/attachment.js +17 -15
  15. package/dist/commands/attachment.js.map +1 -1
  16. package/dist/commands/auth-cmd.js +20 -9
  17. package/dist/commands/auth-cmd.js.map +1 -1
  18. package/dist/commands/calendar.js +67 -78
  19. package/dist/commands/calendar.js.map +1 -1
  20. package/dist/commands/draft.js +25 -18
  21. package/dist/commands/draft.js.map +1 -1
  22. package/dist/commands/label.js +33 -45
  23. package/dist/commands/label.js.map +1 -1
  24. package/dist/commands/mail-actions.js +11 -13
  25. package/dist/commands/mail-actions.js.map +1 -1
  26. package/dist/commands/mail.js +112 -126
  27. package/dist/commands/mail.js.map +1 -1
  28. package/dist/commands/profile.js +18 -21
  29. package/dist/commands/profile.js.map +1 -1
  30. package/dist/commands/watch.js +33 -261
  31. package/dist/commands/watch.js.map +1 -1
  32. package/dist/db.js +12 -13
  33. package/dist/db.js.map +1 -1
  34. package/dist/generated/browser.d.ts +12 -27
  35. package/dist/generated/client.d.ts +13 -28
  36. package/dist/generated/client.js +1 -1
  37. package/dist/generated/commonInputTypes.d.ts +90 -26
  38. package/dist/generated/enums.d.ts +0 -4
  39. package/dist/generated/enums.js +0 -3
  40. package/dist/generated/enums.js.map +1 -1
  41. package/dist/generated/internal/class.d.ts +22 -55
  42. package/dist/generated/internal/class.js +12 -4
  43. package/dist/generated/internal/class.js.map +1 -1
  44. package/dist/generated/internal/prismaNamespace.d.ts +272 -511
  45. package/dist/generated/internal/prismaNamespace.js +54 -66
  46. package/dist/generated/internal/prismaNamespace.js.map +1 -1
  47. package/dist/generated/internal/prismaNamespaceBrowser.d.ts +60 -74
  48. package/dist/generated/internal/prismaNamespaceBrowser.js +50 -62
  49. package/dist/generated/internal/prismaNamespaceBrowser.js.map +1 -1
  50. package/dist/generated/models/Account.d.ts +1637 -0
  51. package/dist/generated/models/Account.js +2 -0
  52. package/dist/generated/models/Account.js.map +1 -0
  53. package/dist/generated/models/CalendarList.d.ts +1161 -0
  54. package/dist/generated/models/CalendarList.js +2 -0
  55. package/dist/generated/models/CalendarList.js.map +1 -0
  56. package/dist/generated/models/Label.d.ts +1161 -0
  57. package/dist/generated/models/Label.js +2 -0
  58. package/dist/generated/models/Label.js.map +1 -0
  59. package/dist/generated/models/Profile.d.ts +1269 -0
  60. package/dist/generated/models/Profile.js +2 -0
  61. package/dist/generated/models/Profile.js.map +1 -0
  62. package/dist/generated/models/SyncState.d.ts +1130 -0
  63. package/dist/generated/models/SyncState.js +2 -0
  64. package/dist/generated/models/SyncState.js.map +1 -0
  65. package/dist/generated/models/Thread.d.ts +1608 -0
  66. package/dist/generated/models/Thread.js +2 -0
  67. package/dist/generated/models/Thread.js.map +1 -0
  68. package/dist/generated/models.d.ts +6 -9
  69. package/dist/gmail-client.d.ts +119 -94
  70. package/dist/gmail-client.js +862 -322
  71. package/dist/gmail-client.js.map +1 -1
  72. package/dist/mail-tui.d.ts +1 -0
  73. package/dist/mail-tui.js +517 -0
  74. package/dist/mail-tui.js.map +1 -0
  75. package/dist/output.d.ts +6 -0
  76. package/dist/output.js +124 -11
  77. package/dist/output.js.map +1 -1
  78. package/package.json +39 -11
  79. package/schema.prisma +81 -113
  80. package/src/api-utils.ts +103 -5
  81. package/src/auth.ts +224 -143
  82. package/src/calendar-client.ts +196 -89
  83. package/src/cli.ts +30 -1
  84. package/src/commands/attachment.ts +18 -19
  85. package/src/commands/auth-cmd.ts +19 -9
  86. package/src/commands/calendar.ts +42 -85
  87. package/src/commands/draft.ts +19 -22
  88. package/src/commands/label.ts +21 -57
  89. package/src/commands/mail-actions.ts +11 -19
  90. package/src/commands/mail.ts +102 -147
  91. package/src/commands/profile.ts +12 -28
  92. package/src/commands/watch.ts +37 -304
  93. package/src/db.ts +13 -16
  94. package/src/generated/browser.ts +49 -0
  95. package/src/generated/client.ts +71 -0
  96. package/src/generated/commonInputTypes.ts +332 -0
  97. package/src/generated/enums.ts +17 -0
  98. package/src/generated/internal/class.ts +250 -0
  99. package/src/generated/internal/prismaNamespace.ts +1198 -0
  100. package/src/generated/internal/prismaNamespaceBrowser.ts +169 -0
  101. package/src/generated/models/Account.ts +1848 -0
  102. package/src/generated/models/CalendarList.ts +1331 -0
  103. package/src/generated/models/Label.ts +1331 -0
  104. package/src/generated/models/Profile.ts +1439 -0
  105. package/src/generated/models/SyncState.ts +1300 -0
  106. package/src/generated/models/Thread.ts +1787 -0
  107. package/src/generated/models.ts +17 -0
  108. package/src/gmail-client.test.ts +59 -0
  109. package/src/gmail-client.ts +1034 -429
  110. package/src/mail-tui.tsx +1061 -0
  111. package/src/output.test.ts +1093 -0
  112. package/src/output.ts +128 -13
  113. package/src/schema.sql +58 -68
  114. package/src/test-fixtures/email-html/safe-claude-event.html +28 -0
  115. package/src/test-fixtures/email-html/safe-product-announcement.html +25 -0
  116. package/src/test-fixtures/email-html/safe-tracked-links.html +27 -0
  117. package/src/test-fixtures/email-html-snapshots/safe-claude-event.html.md +9 -0
  118. package/src/test-fixtures/email-html-snapshots/safe-product-announcement.html.md +13 -0
  119. package/src/test-fixtures/email-html-snapshots/safe-tracked-links.html.md +7 -0
  120. package/AGENTS.md +0 -26
  121. package/CHANGELOG.md +0 -43
  122. package/dist/generated/models/accounts.d.ts +0 -2000
  123. package/dist/generated/models/accounts.js +0 -2
  124. package/dist/generated/models/accounts.js.map +0 -1
  125. package/dist/generated/models/calendar_events.d.ts +0 -1433
  126. package/dist/generated/models/calendar_events.js +0 -2
  127. package/dist/generated/models/calendar_events.js.map +0 -1
  128. package/dist/generated/models/calendar_lists.d.ts +0 -1131
  129. package/dist/generated/models/calendar_lists.js +0 -2
  130. package/dist/generated/models/calendar_lists.js.map +0 -1
  131. package/dist/generated/models/label_counts.d.ts +0 -1131
  132. package/dist/generated/models/label_counts.js +0 -2
  133. package/dist/generated/models/label_counts.js.map +0 -1
  134. package/dist/generated/models/labels.d.ts +0 -1131
  135. package/dist/generated/models/labels.js +0 -2
  136. package/dist/generated/models/labels.js.map +0 -1
  137. package/dist/generated/models/profiles.d.ts +0 -1131
  138. package/dist/generated/models/profiles.js +0 -2
  139. package/dist/generated/models/profiles.js.map +0 -1
  140. package/dist/generated/models/sync_states.d.ts +0 -1107
  141. package/dist/generated/models/sync_states.js +0 -2
  142. package/dist/generated/models/sync_states.js.map +0 -1
  143. package/dist/generated/models/thread_lists.d.ts +0 -1404
  144. package/dist/generated/models/thread_lists.js +0 -2
  145. package/dist/generated/models/thread_lists.js.map +0 -1
  146. package/dist/generated/models/threads.d.ts +0 -1247
  147. package/dist/generated/models/threads.js +0 -2
  148. package/dist/generated/models/threads.js.map +0 -1
  149. package/dist/gmail-cache.d.ts +0 -60
  150. package/dist/gmail-cache.js +0 -264
  151. package/dist/gmail-cache.js.map +0 -1
  152. package/docs/gogcli-gmail-implementation.md +0 -599
  153. package/scripts/test-device-code-clients.ts +0 -186
  154. package/scripts/test-micropython-scopes.ts +0 -72
  155. package/scripts/test-oauth-clients.ts +0 -257
  156. package/src/gmail-cache.ts +0 -339
  157. package/tsconfig.json +0 -16
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=Thread.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Thread.js","sourceRoot":"","sources":["../../../src/generated/models/Thread.ts"],"names":[],"mappings":""}
@@ -1,10 +1,7 @@
1
- export type * from './models/accounts.js';
2
- export type * from './models/thread_lists.js';
3
- export type * from './models/threads.js';
4
- export type * from './models/labels.js';
5
- export type * from './models/label_counts.js';
6
- export type * from './models/profiles.js';
7
- export type * from './models/calendar_lists.js';
8
- export type * from './models/calendar_events.js';
9
- export type * from './models/sync_states.js';
1
+ export type * from './models/Account.js';
2
+ export type * from './models/Thread.js';
3
+ export type * from './models/Label.js';
4
+ export type * from './models/Profile.js';
5
+ export type * from './models/CalendarList.js';
6
+ export type * from './models/SyncState.js';
10
7
  export type * from './commonInputTypes.js';
@@ -1,5 +1,7 @@
1
1
  import { type gmail_v1 } from '@googleapis/gmail';
2
2
  import type { OAuth2Client } from 'google-auth-library';
3
+ import { AuthError, ApiError, NotFoundError, EmptyThreadError, MissingDataError } from './api-utils.js';
4
+ import type { AccountId } from './auth.js';
3
5
  export interface Sender {
4
6
  name?: string;
5
7
  email: string;
@@ -25,6 +27,7 @@ export interface ParsedMessage {
25
27
  listUnsubscribe?: string;
26
28
  body: string;
27
29
  mimeType: string;
30
+ textBody: string | null;
28
31
  attachments: AttachmentMeta[];
29
32
  }
30
33
  export interface AttachmentMeta {
@@ -58,46 +61,60 @@ export interface ThreadListItem {
58
61
  }
59
62
  export interface ThreadListResult {
60
63
  threads: ThreadListItem[];
64
+ /** Raw Google gmail_v1.Schema$Thread metadata responses, parallel to threads[]. */
65
+ rawThreads: gmail_v1.Schema$Thread[];
61
66
  nextPageToken: string | null;
62
67
  resultSizeEstimate: number;
63
68
  }
69
+ /** Result from getThread() — includes both parsed data and the raw Google response. */
70
+ export interface ThreadResult {
71
+ parsed: ThreadData;
72
+ raw: gmail_v1.Schema$Thread;
73
+ }
74
+ export interface WatchEvent {
75
+ account: AccountId;
76
+ type: 'new_message';
77
+ message: ParsedMessage;
78
+ threadId: string;
79
+ }
64
80
  export declare class GmailClient {
65
81
  private gmail;
66
82
  private labelIdCache;
67
- constructor({ auth }: {
83
+ private account;
84
+ constructor({ auth, account }: {
68
85
  auth: OAuth2Client;
86
+ account?: AccountId;
69
87
  });
88
+ private get cacheEnabled();
89
+ private getCachedThread;
90
+ private cacheThreadData;
91
+ invalidateThreads(threadIds: string[]): Promise<void>;
92
+ invalidateThread(threadId: string): Promise<void>;
93
+ private getCachedLabels;
94
+ private cacheLabelsData;
95
+ invalidateLabels(): Promise<void>;
96
+ private getCachedProfile;
97
+ private cacheProfileData;
70
98
  listThreads({ query, folder, maxResults, labelIds, pageToken, }?: {
71
99
  query?: string;
72
100
  folder?: string;
73
101
  maxResults?: number;
74
102
  labelIds?: string[];
75
103
  pageToken?: string;
76
- }): Promise<ThreadListResult>;
104
+ }): Promise<ThreadListResult | AuthError | ApiError>;
77
105
  getThread({ threadId }: {
78
106
  threadId: string;
79
- }): Promise<{
80
- id: string;
81
- historyId: string | null;
82
- messages: ParsedMessage[];
83
- subject: string;
84
- snippet: string;
85
- from: Sender;
86
- date: string;
87
- labelIds: string[];
88
- hasUnread: boolean;
89
- messageCount: number;
90
- }>;
107
+ }): Promise<ThreadResult>;
91
108
  getMessage({ messageId, format, }: {
92
109
  messageId: string;
93
110
  format?: 'full' | 'metadata' | 'minimal' | 'raw';
94
111
  }): Promise<ParsedMessage | {
95
112
  id: string;
96
113
  raw: string;
97
- }>;
114
+ } | AuthError | ApiError>;
98
115
  getRawMessage({ messageId }: {
99
116
  messageId: string;
100
- }): Promise<string>;
117
+ }): Promise<string | MissingDataError | AuthError | ApiError>;
101
118
  sendMessage({ to, subject, body, cc, bcc, threadId, inReplyTo, references, attachments, fromEmail, }: {
102
119
  to: Array<{
103
120
  name?: string;
@@ -123,31 +140,32 @@ export declare class GmailClient {
123
140
  }>;
124
141
  fromEmail?: string;
125
142
  }): Promise<gmail_v1.Schema$Message>;
126
- createDraft({ to, subject, body, cc, bcc, threadId, fromEmail, attachments, }: {
127
- to: Array<{
128
- name?: string;
129
- email: string;
130
- }>;
131
- subject: string;
143
+ /**
144
+ * Reply to a thread. Handles reply-to resolution, reply-all CC computation,
145
+ * References/In-Reply-To headers, and subject prefixing.
146
+ */
147
+ replyToThread({ threadId, body, replyAll, cc, fromEmail, }: {
148
+ threadId: string;
132
149
  body: string;
150
+ replyAll?: boolean;
133
151
  cc?: Array<{
134
- name?: string;
135
152
  email: string;
136
153
  }>;
137
- bcc?: Array<{
138
- name?: string;
154
+ fromEmail?: string;
155
+ }): Promise<EmptyThreadError | AuthError | ApiError | gmail_v1.Schema$Message>;
156
+ /**
157
+ * Forward a thread. Fetches the last message, renders its body,
158
+ * builds the "Forwarded message" block, and sends.
159
+ */
160
+ forwardThread({ threadId, to, body, fromEmail, }: {
161
+ threadId: string;
162
+ to: Array<{
139
163
  email: string;
140
164
  }>;
141
- threadId?: string;
165
+ body?: string;
142
166
  fromEmail?: string;
143
- attachments?: Array<{
144
- filename: string;
145
- mimeType: string;
146
- content: Buffer;
147
- }>;
148
- }): Promise<gmail_v1.Schema$Draft>;
149
- updateDraft({ draftId, to, subject, body, cc, bcc, threadId, fromEmail, attachments, }: {
150
- draftId: string;
167
+ }): Promise<EmptyThreadError | gmail_v1.Schema$Message>;
168
+ createDraft({ to, subject, body, cc, bcc, threadId, fromEmail, attachments, }: {
151
169
  to: Array<{
152
170
  name?: string;
153
171
  email: string;
@@ -172,7 +190,7 @@ export declare class GmailClient {
172
190
  }): Promise<gmail_v1.Schema$Draft>;
173
191
  getDraft({ draftId }: {
174
192
  draftId: string;
175
- }): Promise<{
193
+ }): Promise<NotFoundError | AuthError | ApiError | {
176
194
  id: string;
177
195
  message: ParsedMessage;
178
196
  to: string[];
@@ -184,16 +202,16 @@ export declare class GmailClient {
184
202
  maxResults?: number;
185
203
  pageToken?: string;
186
204
  }): Promise<{
187
- drafts: {
205
+ drafts: Array<{
188
206
  id: string;
189
207
  threadId: string | null;
190
208
  subject: string;
191
209
  to: string[];
192
210
  date: string;
193
211
  snippet: string;
194
- }[];
212
+ }>;
195
213
  nextPageToken: string | null;
196
- }>;
214
+ } | AuthError | ApiError>;
197
215
  sendDraft({ draftId }: {
198
216
  draftId: string;
199
217
  }): Promise<gmail_v1.Schema$Message>;
@@ -202,21 +220,21 @@ export declare class GmailClient {
202
220
  }): Promise<void>;
203
221
  markAsRead({ threadIds }: {
204
222
  threadIds: string[];
205
- }): Promise<void>;
223
+ }): Promise<void | AuthError | ApiError>;
206
224
  markAsUnread({ threadIds }: {
207
225
  threadIds: string[];
208
- }): Promise<void>;
226
+ }): Promise<void | AuthError | ApiError>;
209
227
  star({ threadIds }: {
210
228
  threadIds: string[];
211
- }): Promise<void>;
229
+ }): Promise<void | AuthError | ApiError>;
212
230
  unstar({ threadIds }: {
213
231
  threadIds: string[];
214
- }): Promise<void>;
232
+ }): Promise<void | AuthError | ApiError>;
215
233
  modifyLabels({ threadIds, addLabelIds, removeLabelIds, }: {
216
234
  threadIds: string[];
217
235
  addLabelIds?: string[];
218
236
  removeLabelIds?: string[];
219
- }): Promise<void>;
237
+ }): Promise<void | AuthError | ApiError>;
220
238
  trash({ threadId }: {
221
239
  threadId: string;
222
240
  }): Promise<void>;
@@ -225,25 +243,17 @@ export declare class GmailClient {
225
243
  }): Promise<void>;
226
244
  archive({ threadIds }: {
227
245
  threadIds: string[];
228
- }): Promise<void>;
229
- deleteMessage({ messageId }: {
230
- messageId: string;
231
- }): Promise<void>;
246
+ }): Promise<void | AuthError | ApiError>;
247
+ /** Invalidate thread cache after a thread mutation. */
248
+ private invalidateAfterThreadMutation;
232
249
  /** Moves all spam threads to trash. Does not permanently delete. */
233
250
  trashAllSpam(): Promise<{
234
251
  count: number;
235
- }>;
252
+ } | AuthError | ApiError>;
236
253
  listLabels(): Promise<{
237
- id: string;
238
- name: string;
239
- type: "system" | "user";
240
- messageListVisibility: string | null;
241
- labelListVisibility: string | null;
242
- color: {
243
- backgroundColor: string;
244
- textColor: string;
245
- } | null;
246
- }[]>;
254
+ parsed: ReturnType<typeof GmailClient.parseRawLabels>;
255
+ raw: gmail_v1.Schema$Label[];
256
+ } | AuthError | ApiError>;
247
257
  getLabel({ labelId }: {
248
258
  labelId: string;
249
259
  }): Promise<{
@@ -269,45 +279,58 @@ export declare class GmailClient {
269
279
  id: string;
270
280
  name: string;
271
281
  }>;
272
- updateLabel({ labelId, name, color, }: {
273
- labelId: string;
274
- name?: string;
275
- color?: {
276
- backgroundColor: string;
277
- textColor: string;
278
- };
279
- }): Promise<void>;
280
282
  deleteLabel({ labelId }: {
281
283
  labelId: string;
282
284
  }): Promise<void>;
283
285
  getLabelCounts(): Promise<{
284
- label: string;
285
- count: number;
286
- }[]>;
286
+ parsed: Array<{
287
+ label: string;
288
+ count: number;
289
+ }>;
290
+ raw: gmail_v1.Schema$Label[];
291
+ archiveEstimate: number | null;
292
+ } | AuthError | ApiError>;
287
293
  getAttachment({ messageId, attachmentId, }: {
288
294
  messageId: string;
289
295
  attachmentId: string;
290
296
  }): Promise<string>;
291
- getMessageAttachments({ messageId }: {
292
- messageId: string;
293
- }): Promise<{
294
- filename: string;
295
- mimeType: string;
296
- size: number;
297
- attachmentId: string;
298
- data: string;
299
- }[]>;
300
297
  getProfile(): Promise<{
301
298
  emailAddress: string;
302
299
  messagesTotal: number;
303
300
  threadsTotal: number;
304
301
  historyId: string;
305
- }>;
306
- getEmailAliases(): Promise<{
302
+ } | AuthError | ApiError>;
303
+ /** Parse a raw gmail_v1.Schema$Thread (format: full) into ThreadData. */
304
+ static parseRawThread(raw: gmail_v1.Schema$Thread): ThreadData;
305
+ /** Parse a raw gmail_v1.Schema$Message into ParsedMessage. */
306
+ static parseRawMessage(message: gmail_v1.Schema$Message): ParsedMessage;
307
+ /** Parse raw gmail_v1.Schema$Thread (format: metadata) into ThreadListItem. */
308
+ static parseRawThreadListItem(raw: gmail_v1.Schema$Thread): ThreadListItem;
309
+ /** Parse raw gmail_v1.Schema$Label[] from labels.list into our label objects. */
310
+ static parseRawLabels(rawLabels: gmail_v1.Schema$Label[]): {
311
+ id: string;
312
+ name: string;
313
+ type: "system" | "user";
314
+ messageListVisibility: string | null;
315
+ labelListVisibility: string | null;
316
+ color: {
317
+ backgroundColor: string;
318
+ textColor: string;
319
+ } | null;
320
+ }[];
321
+ /** Parse raw gmail_v1.Schema$Label[] (with counts) into label count objects. */
322
+ static parseRawLabelCounts(rawLabels: gmail_v1.Schema$Label[], archiveEstimate: number | null): {
323
+ label: string;
324
+ count: number;
325
+ }[];
326
+ private static extractBodyStatic;
327
+ private static findBodyPartStatic;
328
+ private static extractAttachmentMetaStatic;
329
+ getEmailAliases(): Promise<Array<{
307
330
  email: string;
308
331
  name?: string;
309
332
  primary: boolean;
310
- }[]>;
333
+ }> | AuthError | ApiError>;
311
334
  listHistory({ startHistoryId, labelId, historyTypes, }: {
312
335
  startHistoryId: string;
313
336
  labelId?: string;
@@ -315,21 +338,23 @@ export declare class GmailClient {
315
338
  }): Promise<{
316
339
  history: gmail_v1.Schema$History[];
317
340
  historyId: string;
318
- }>;
319
- watch({ topicName, labelIds, }: {
320
- topicName: string;
321
- labelIds?: string[];
322
- }): Promise<{
323
- historyId: string;
324
- expiration: string;
325
- }>;
326
- stopWatch(): Promise<void>;
341
+ } | AuthError | ApiError>;
342
+ /**
343
+ * Poll for new messages using the Gmail History API.
344
+ * Yields WatchEvent objects as new messages arrive.
345
+ * Handles history seeding, expiry re-seeding, and client-side query filtering.
346
+ * Persists historyId in the DB so it survives across CLI invocations.
347
+ */
348
+ watchInbox({ folder, intervalMs, query, once, }?: {
349
+ folder?: string;
350
+ intervalMs?: number;
351
+ query?: string;
352
+ once?: boolean;
353
+ }): AsyncGenerator<WatchEvent>;
354
+ /** Single poll tick from pre-fetched history — yields WatchEvents for new messages. */
355
+ private pollOnceFromHistory;
327
356
  private parseMessage;
328
357
  private parseThreadListItem;
329
- private extractBody;
330
- private findBodyPart;
331
- private extractAttachmentMeta;
332
- private findAttachmentParts;
333
358
  private buildMimeMessage;
334
359
  /** Look up a label ID by name. Returns null if not found (never creates). */
335
360
  private lookupLabelId;