zele 0.2.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 (158) hide show
  1. package/README.md +38 -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 +28 -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 +114 -128
  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.d.ts +2 -0
  31. package/dist/commands/watch.js +73 -0
  32. package/dist/commands/watch.js.map +1 -0
  33. package/dist/db.js +12 -13
  34. package/dist/db.js.map +1 -1
  35. package/dist/generated/browser.d.ts +12 -27
  36. package/dist/generated/client.d.ts +13 -28
  37. package/dist/generated/client.js +1 -1
  38. package/dist/generated/commonInputTypes.d.ts +90 -26
  39. package/dist/generated/enums.d.ts +0 -4
  40. package/dist/generated/enums.js +0 -3
  41. package/dist/generated/enums.js.map +1 -1
  42. package/dist/generated/internal/class.d.ts +22 -55
  43. package/dist/generated/internal/class.js +12 -4
  44. package/dist/generated/internal/class.js.map +1 -1
  45. package/dist/generated/internal/prismaNamespace.d.ts +272 -511
  46. package/dist/generated/internal/prismaNamespace.js +54 -66
  47. package/dist/generated/internal/prismaNamespace.js.map +1 -1
  48. package/dist/generated/internal/prismaNamespaceBrowser.d.ts +60 -74
  49. package/dist/generated/internal/prismaNamespaceBrowser.js +50 -62
  50. package/dist/generated/internal/prismaNamespaceBrowser.js.map +1 -1
  51. package/dist/generated/models/Account.d.ts +1637 -0
  52. package/dist/generated/models/Account.js +2 -0
  53. package/dist/generated/models/Account.js.map +1 -0
  54. package/dist/generated/models/CalendarList.d.ts +1161 -0
  55. package/dist/generated/models/CalendarList.js +2 -0
  56. package/dist/generated/models/CalendarList.js.map +1 -0
  57. package/dist/generated/models/Label.d.ts +1161 -0
  58. package/dist/generated/models/Label.js +2 -0
  59. package/dist/generated/models/Label.js.map +1 -0
  60. package/dist/generated/models/Profile.d.ts +1269 -0
  61. package/dist/generated/models/Profile.js +2 -0
  62. package/dist/generated/models/Profile.js.map +1 -0
  63. package/dist/generated/models/SyncState.d.ts +1130 -0
  64. package/dist/generated/models/SyncState.js +2 -0
  65. package/dist/generated/models/SyncState.js.map +1 -0
  66. package/dist/generated/models/Thread.d.ts +1608 -0
  67. package/dist/generated/models/Thread.js +2 -0
  68. package/dist/generated/models/Thread.js.map +1 -0
  69. package/dist/generated/models.d.ts +6 -9
  70. package/dist/gmail-client.d.ts +119 -94
  71. package/dist/gmail-client.js +862 -315
  72. package/dist/gmail-client.js.map +1 -1
  73. package/dist/mail-tui.d.ts +1 -0
  74. package/dist/mail-tui.js +517 -0
  75. package/dist/mail-tui.js.map +1 -0
  76. package/dist/output.d.ts +6 -4
  77. package/dist/output.js +124 -17
  78. package/dist/output.js.map +1 -1
  79. package/package.json +39 -11
  80. package/schema.prisma +81 -113
  81. package/src/api-utils.ts +103 -5
  82. package/src/auth.ts +224 -143
  83. package/src/calendar-client.ts +196 -89
  84. package/src/cli.ts +32 -1
  85. package/src/commands/attachment.ts +18 -19
  86. package/src/commands/auth-cmd.ts +19 -9
  87. package/src/commands/calendar.ts +42 -85
  88. package/src/commands/draft.ts +19 -22
  89. package/src/commands/label.ts +21 -57
  90. package/src/commands/mail-actions.ts +11 -19
  91. package/src/commands/mail.ts +104 -149
  92. package/src/commands/profile.ts +12 -28
  93. package/src/commands/watch.ts +88 -0
  94. package/src/db.ts +13 -16
  95. package/src/generated/browser.ts +49 -0
  96. package/src/generated/client.ts +71 -0
  97. package/src/generated/commonInputTypes.ts +332 -0
  98. package/src/generated/enums.ts +17 -0
  99. package/src/generated/internal/class.ts +250 -0
  100. package/src/generated/internal/prismaNamespace.ts +1198 -0
  101. package/src/generated/internal/prismaNamespaceBrowser.ts +169 -0
  102. package/src/generated/models/Account.ts +1848 -0
  103. package/src/generated/models/CalendarList.ts +1331 -0
  104. package/src/generated/models/Label.ts +1331 -0
  105. package/src/generated/models/Profile.ts +1439 -0
  106. package/src/generated/models/SyncState.ts +1300 -0
  107. package/src/generated/models/Thread.ts +1787 -0
  108. package/src/generated/models.ts +17 -0
  109. package/src/gmail-client.test.ts +59 -0
  110. package/src/gmail-client.ts +1034 -422
  111. package/src/mail-tui.tsx +1061 -0
  112. package/src/output.test.ts +1093 -0
  113. package/src/output.ts +128 -20
  114. package/src/schema.sql +58 -68
  115. package/src/test-fixtures/email-html/safe-claude-event.html +28 -0
  116. package/src/test-fixtures/email-html/safe-product-announcement.html +25 -0
  117. package/src/test-fixtures/email-html/safe-tracked-links.html +27 -0
  118. package/src/test-fixtures/email-html-snapshots/safe-claude-event.html.md +9 -0
  119. package/src/test-fixtures/email-html-snapshots/safe-product-announcement.html.md +13 -0
  120. package/src/test-fixtures/email-html-snapshots/safe-tracked-links.html.md +7 -0
  121. package/AGENTS.md +0 -26
  122. package/CHANGELOG.md +0 -36
  123. package/dist/generated/models/accounts.d.ts +0 -2000
  124. package/dist/generated/models/accounts.js +0 -2
  125. package/dist/generated/models/accounts.js.map +0 -1
  126. package/dist/generated/models/calendar_events.d.ts +0 -1433
  127. package/dist/generated/models/calendar_events.js +0 -2
  128. package/dist/generated/models/calendar_events.js.map +0 -1
  129. package/dist/generated/models/calendar_lists.d.ts +0 -1131
  130. package/dist/generated/models/calendar_lists.js +0 -2
  131. package/dist/generated/models/calendar_lists.js.map +0 -1
  132. package/dist/generated/models/label_counts.d.ts +0 -1131
  133. package/dist/generated/models/label_counts.js +0 -2
  134. package/dist/generated/models/label_counts.js.map +0 -1
  135. package/dist/generated/models/labels.d.ts +0 -1131
  136. package/dist/generated/models/labels.js +0 -2
  137. package/dist/generated/models/labels.js.map +0 -1
  138. package/dist/generated/models/profiles.d.ts +0 -1131
  139. package/dist/generated/models/profiles.js +0 -2
  140. package/dist/generated/models/profiles.js.map +0 -1
  141. package/dist/generated/models/sync_states.d.ts +0 -1107
  142. package/dist/generated/models/sync_states.js +0 -2
  143. package/dist/generated/models/sync_states.js.map +0 -1
  144. package/dist/generated/models/thread_lists.d.ts +0 -1404
  145. package/dist/generated/models/thread_lists.js +0 -2
  146. package/dist/generated/models/thread_lists.js.map +0 -1
  147. package/dist/generated/models/threads.d.ts +0 -1247
  148. package/dist/generated/models/threads.js +0 -2
  149. package/dist/generated/models/threads.js.map +0 -1
  150. package/dist/gmail-cache.d.ts +0 -60
  151. package/dist/gmail-cache.js +0 -264
  152. package/dist/gmail-cache.js.map +0 -1
  153. package/docs/gogcli-gmail-implementation.md +0 -599
  154. package/scripts/test-device-code-clients.ts +0 -186
  155. package/scripts/test-micropython-scopes.ts +0 -72
  156. package/scripts/test-oauth-clients.ts +0 -257
  157. package/src/gmail-cache.ts +0 -339
  158. package/tsconfig.json +0 -16
@@ -1,339 +0,0 @@
1
- // Prisma-based cache for Gmail API responses.
2
- // Each cache entry is scoped to an account email. TTL-based expiry is checked
3
- // at read time. All methods are async (Prisma is async).
4
- // Single SQLite DB shared across all accounts via the Prisma singleton.
5
-
6
- import { getPrisma } from './db.js'
7
-
8
- // TTL constants in milliseconds
9
- export const TTL = {
10
- THREAD_LIST: 5 * 60 * 1000, // 5 minutes
11
- THREAD: 30 * 60 * 1000, // 30 minutes
12
- LABELS: 30 * 60 * 1000, // 30 minutes
13
- PROFILE: 24 * 60 * 60 * 1000, // 24 hours
14
- LABEL_COUNTS: 2 * 60 * 1000, // 2 minutes
15
- CALENDAR_LIST: 30 * 60 * 1000, // 30 minutes
16
- CALENDAR_EVENTS: 5 * 60 * 1000, // 5 minutes
17
- } as const
18
-
19
- function isExpired(createdAt: Date, ttlMs: number): boolean {
20
- return createdAt.getTime() + ttlMs < Date.now()
21
- }
22
-
23
- // ---------------------------------------------------------------------------
24
- // Thread list cache
25
- // ---------------------------------------------------------------------------
26
-
27
- export async function cacheThreadList(
28
- email: string,
29
- params: { folder?: string; query?: string; maxResults?: number; labelIds?: string[]; pageToken?: string },
30
- data: unknown,
31
- ): Promise<void> {
32
- const prisma = await getPrisma()
33
- const where = {
34
- email,
35
- folder: params.folder ?? '',
36
- query: params.query ?? '',
37
- label_ids: params.labelIds?.join(',') ?? '',
38
- page_token: params.pageToken ?? '',
39
- max_results: params.maxResults ?? 0,
40
- }
41
-
42
- await prisma.thread_lists.upsert({
43
- where: { email_folder_query_label_ids_page_token_max_results: where },
44
- create: { ...where, data: JSON.stringify(data), ttl_ms: TTL.THREAD_LIST },
45
- update: { data: JSON.stringify(data), ttl_ms: TTL.THREAD_LIST, created_at: new Date() },
46
- })
47
- }
48
-
49
- export async function getCachedThreadList<T = unknown>(
50
- email: string,
51
- params: { folder?: string; query?: string; maxResults?: number; labelIds?: string[]; pageToken?: string },
52
- ): Promise<T | undefined> {
53
- const prisma = await getPrisma()
54
- const row = await prisma.thread_lists.findUnique({
55
- where: {
56
- email_folder_query_label_ids_page_token_max_results: {
57
- email,
58
- folder: params.folder ?? '',
59
- query: params.query ?? '',
60
- label_ids: params.labelIds?.join(',') ?? '',
61
- page_token: params.pageToken ?? '',
62
- max_results: params.maxResults ?? 0,
63
- },
64
- },
65
- })
66
-
67
- if (!row || isExpired(row.created_at, row.ttl_ms)) return undefined
68
- return JSON.parse(row.data) as T
69
- }
70
-
71
- export async function invalidateThreadLists(email: string): Promise<void> {
72
- const prisma = await getPrisma()
73
- await prisma.thread_lists.deleteMany({ where: { email } })
74
- }
75
-
76
- // ---------------------------------------------------------------------------
77
- // Individual thread cache
78
- // ---------------------------------------------------------------------------
79
-
80
- export async function cacheThread(
81
- email: string,
82
- threadId: string,
83
- data: unknown,
84
- ): Promise<void> {
85
- const prisma = await getPrisma()
86
- await prisma.threads.upsert({
87
- where: { email_thread_id: { email, thread_id: threadId } },
88
- create: { email, thread_id: threadId, data: JSON.stringify(data), ttl_ms: TTL.THREAD },
89
- update: { data: JSON.stringify(data), ttl_ms: TTL.THREAD, created_at: new Date() },
90
- })
91
- }
92
-
93
- export async function getCachedThread<T = unknown>(
94
- email: string,
95
- threadId: string,
96
- ): Promise<T | undefined> {
97
- const prisma = await getPrisma()
98
- const row = await prisma.threads.findUnique({
99
- where: { email_thread_id: { email, thread_id: threadId } },
100
- })
101
-
102
- if (!row || isExpired(row.created_at, row.ttl_ms)) return undefined
103
- return JSON.parse(row.data) as T
104
- }
105
-
106
- export async function invalidateThread(email: string, threadId: string): Promise<void> {
107
- const prisma = await getPrisma()
108
- await prisma.threads.deleteMany({ where: { email, thread_id: threadId } })
109
- }
110
-
111
- export async function invalidateThreads(email: string, threadIds: string[]): Promise<void> {
112
- const prisma = await getPrisma()
113
- await prisma.threads.deleteMany({ where: { email, thread_id: { in: threadIds } } })
114
- }
115
-
116
- // ---------------------------------------------------------------------------
117
- // Labels cache
118
- // ---------------------------------------------------------------------------
119
-
120
- export async function cacheLabels(email: string, data: unknown): Promise<void> {
121
- const prisma = await getPrisma()
122
- await prisma.labels.upsert({
123
- where: { email },
124
- create: { email, data: JSON.stringify(data), ttl_ms: TTL.LABELS },
125
- update: { data: JSON.stringify(data), ttl_ms: TTL.LABELS, created_at: new Date() },
126
- })
127
- }
128
-
129
- export async function getCachedLabels<T = unknown>(email: string): Promise<T | undefined> {
130
- const prisma = await getPrisma()
131
- const row = await prisma.labels.findUnique({ where: { email } })
132
- if (!row || isExpired(row.created_at, row.ttl_ms)) return undefined
133
- return JSON.parse(row.data) as T
134
- }
135
-
136
- export async function invalidateLabels(email: string): Promise<void> {
137
- const prisma = await getPrisma()
138
- await prisma.labels.deleteMany({ where: { email } })
139
- }
140
-
141
- // ---------------------------------------------------------------------------
142
- // Label counts cache
143
- // ---------------------------------------------------------------------------
144
-
145
- export async function cacheLabelCounts(email: string, data: unknown): Promise<void> {
146
- const prisma = await getPrisma()
147
- await prisma.label_counts.upsert({
148
- where: { email },
149
- create: { email, data: JSON.stringify(data), ttl_ms: TTL.LABEL_COUNTS },
150
- update: { data: JSON.stringify(data), ttl_ms: TTL.LABEL_COUNTS, created_at: new Date() },
151
- })
152
- }
153
-
154
- export async function getCachedLabelCounts<T = unknown>(email: string): Promise<T | undefined> {
155
- const prisma = await getPrisma()
156
- const row = await prisma.label_counts.findUnique({ where: { email } })
157
- if (!row || isExpired(row.created_at, row.ttl_ms)) return undefined
158
- return JSON.parse(row.data) as T
159
- }
160
-
161
- export async function invalidateLabelCounts(email: string): Promise<void> {
162
- const prisma = await getPrisma()
163
- await prisma.label_counts.deleteMany({ where: { email } })
164
- }
165
-
166
- // ---------------------------------------------------------------------------
167
- // Profile cache
168
- // ---------------------------------------------------------------------------
169
-
170
- export async function cacheProfile(email: string, data: unknown): Promise<void> {
171
- const prisma = await getPrisma()
172
- await prisma.profiles.upsert({
173
- where: { email },
174
- create: { email, data: JSON.stringify(data), ttl_ms: TTL.PROFILE },
175
- update: { data: JSON.stringify(data), ttl_ms: TTL.PROFILE, created_at: new Date() },
176
- })
177
- }
178
-
179
- export async function getCachedProfile<T = unknown>(email: string): Promise<T | undefined> {
180
- const prisma = await getPrisma()
181
- const row = await prisma.profiles.findUnique({ where: { email } })
182
- if (!row || isExpired(row.created_at, row.ttl_ms)) return undefined
183
- return JSON.parse(row.data) as T
184
- }
185
-
186
- // ---------------------------------------------------------------------------
187
- // Sync state (persistent, no TTL)
188
- // ---------------------------------------------------------------------------
189
-
190
- export async function getLastHistoryId(email: string): Promise<string | undefined> {
191
- const prisma = await getPrisma()
192
- const row = await prisma.sync_states.findUnique({
193
- where: { email_key: { email, key: 'history_id' } },
194
- })
195
- return row?.value
196
- }
197
-
198
- export async function setLastHistoryId(email: string, historyId: string): Promise<void> {
199
- const prisma = await getPrisma()
200
- await prisma.sync_states.upsert({
201
- where: { email_key: { email, key: 'history_id' } },
202
- create: { email, key: 'history_id', value: historyId },
203
- update: { value: historyId },
204
- })
205
- }
206
-
207
- // ---------------------------------------------------------------------------
208
- // Calendar list cache
209
- // ---------------------------------------------------------------------------
210
-
211
- export async function cacheCalendarList(email: string, data: unknown): Promise<void> {
212
- const prisma = await getPrisma()
213
- await prisma.calendar_lists.upsert({
214
- where: { email },
215
- create: { email, data: JSON.stringify(data), ttl_ms: TTL.CALENDAR_LIST },
216
- update: { data: JSON.stringify(data), ttl_ms: TTL.CALENDAR_LIST, created_at: new Date() },
217
- })
218
- }
219
-
220
- export async function getCachedCalendarList<T = unknown>(email: string): Promise<T | undefined> {
221
- const prisma = await getPrisma()
222
- const row = await prisma.calendar_lists.findUnique({ where: { email } })
223
- if (!row || isExpired(row.created_at, row.ttl_ms)) return undefined
224
- return JSON.parse(row.data) as T
225
- }
226
-
227
- export async function invalidateCalendarLists(email: string): Promise<void> {
228
- const prisma = await getPrisma()
229
- await prisma.calendar_lists.deleteMany({ where: { email } })
230
- }
231
-
232
- // ---------------------------------------------------------------------------
233
- // Calendar events cache
234
- // ---------------------------------------------------------------------------
235
-
236
- export async function cacheCalendarEvents(
237
- email: string,
238
- params: { calendarId?: string; timeMin?: string; timeMax?: string; query?: string; maxResults?: number; pageToken?: string },
239
- data: unknown,
240
- ): Promise<void> {
241
- const prisma = await getPrisma()
242
- const where = {
243
- email,
244
- calendar_id: params.calendarId ?? '',
245
- time_min: params.timeMin ?? '',
246
- time_max: params.timeMax ?? '',
247
- query: params.query ?? '',
248
- max_results: params.maxResults ?? 0,
249
- page_token: params.pageToken ?? '',
250
- }
251
-
252
- await prisma.calendar_events.upsert({
253
- where: { email_calendar_id_time_min_time_max_query_max_results_page_token: where },
254
- create: { ...where, data: JSON.stringify(data), ttl_ms: TTL.CALENDAR_EVENTS },
255
- update: { data: JSON.stringify(data), ttl_ms: TTL.CALENDAR_EVENTS, created_at: new Date() },
256
- })
257
- }
258
-
259
- export async function getCachedCalendarEvents<T = unknown>(
260
- email: string,
261
- params: { calendarId?: string; timeMin?: string; timeMax?: string; query?: string; maxResults?: number; pageToken?: string },
262
- ): Promise<T | undefined> {
263
- const prisma = await getPrisma()
264
- const row = await prisma.calendar_events.findUnique({
265
- where: {
266
- email_calendar_id_time_min_time_max_query_max_results_page_token: {
267
- email,
268
- calendar_id: params.calendarId ?? '',
269
- time_min: params.timeMin ?? '',
270
- time_max: params.timeMax ?? '',
271
- query: params.query ?? '',
272
- max_results: params.maxResults ?? 0,
273
- page_token: params.pageToken ?? '',
274
- },
275
- },
276
- })
277
-
278
- if (!row || isExpired(row.created_at, row.ttl_ms)) return undefined
279
- return JSON.parse(row.data) as T
280
- }
281
-
282
- export async function invalidateCalendarEvents(email: string, calendarId?: string): Promise<void> {
283
- const prisma = await getPrisma()
284
- if (calendarId) {
285
- await prisma.calendar_events.deleteMany({ where: { email, calendar_id: calendarId } })
286
- } else {
287
- await prisma.calendar_events.deleteMany({ where: { email } })
288
- }
289
- }
290
-
291
- // ---------------------------------------------------------------------------
292
- // Housekeeping
293
- // ---------------------------------------------------------------------------
294
-
295
- export async function clearExpired(): Promise<void> {
296
- const prisma = await getPrisma()
297
- const now = Date.now()
298
- // Use raw SQL for the timestamp arithmetic across all cache tables
299
- await prisma.$executeRawUnsafe(
300
- `DELETE FROM thread_lists WHERE (strftime('%s', created_at) * 1000 + ttl_ms) < ?`,
301
- now,
302
- )
303
- await prisma.$executeRawUnsafe(
304
- `DELETE FROM threads WHERE (strftime('%s', created_at) * 1000 + ttl_ms) < ?`,
305
- now,
306
- )
307
- await prisma.$executeRawUnsafe(
308
- `DELETE FROM labels WHERE (strftime('%s', created_at) * 1000 + ttl_ms) < ?`,
309
- now,
310
- )
311
- await prisma.$executeRawUnsafe(
312
- `DELETE FROM label_counts WHERE (strftime('%s', created_at) * 1000 + ttl_ms) < ?`,
313
- now,
314
- )
315
- await prisma.$executeRawUnsafe(
316
- `DELETE FROM profiles WHERE (strftime('%s', created_at) * 1000 + ttl_ms) < ?`,
317
- now,
318
- )
319
- await prisma.$executeRawUnsafe(
320
- `DELETE FROM calendar_lists WHERE (strftime('%s', created_at) * 1000 + ttl_ms) < ?`,
321
- now,
322
- )
323
- await prisma.$executeRawUnsafe(
324
- `DELETE FROM calendar_events WHERE (strftime('%s', created_at) * 1000 + ttl_ms) < ?`,
325
- now,
326
- )
327
- }
328
-
329
- export async function clearAll(email: string): Promise<void> {
330
- const prisma = await getPrisma()
331
- await prisma.thread_lists.deleteMany({ where: { email } })
332
- await prisma.threads.deleteMany({ where: { email } })
333
- await prisma.labels.deleteMany({ where: { email } })
334
- await prisma.label_counts.deleteMany({ where: { email } })
335
- await prisma.profiles.deleteMany({ where: { email } })
336
- await prisma.sync_states.deleteMany({ where: { email } })
337
- await prisma.calendar_lists.deleteMany({ where: { email } })
338
- await prisma.calendar_events.deleteMany({ where: { email } })
339
- }
package/tsconfig.json DELETED
@@ -1,16 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2023",
4
- "module": "NodeNext",
5
- "moduleResolution": "NodeNext",
6
- "rootDir": "src",
7
- "outDir": "dist",
8
- "strict": true,
9
- "esModuleInterop": true,
10
- "skipLibCheck": true,
11
- "declaration": true,
12
- "sourceMap": true
13
- },
14
- "include": ["src"],
15
- "exclude": ["node_modules"]
16
- }