@remit/drizzle-sqlite-schema 0.0.1

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/schema.ts ADDED
@@ -0,0 +1,619 @@
1
+ import { index, integer, primaryKey, real, sqliteTable, text } from "drizzle-orm/sqlite-core";
2
+ import { generateBase36Id, nullableInteger, nullableText } from "./types.js";
3
+
4
+ export const accountExportRequests = sqliteTable(
5
+ "account_export_request",
6
+ {
7
+ accountExportRequestId: text("account_export_request_id").primaryKey().$defaultFn(() => generateBase36Id()),
8
+ accountConfigId: text("account_config_id").notNull(),
9
+ userId: text("user_id").notNull(),
10
+ state: text("state").$type<"Pending" | "Processing" | "Ready" | "Failed">().notNull().default("Pending"),
11
+ createdAt: integer("created_at", { mode: "number" }).notNull(),
12
+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
13
+ expiresAt: integer("expires_at", { mode: "number" }),
14
+ objectKey: nullableText("object_key"),
15
+ downloadUrl: nullableText("download_url"),
16
+ errorMessage: nullableText("error_message"),
17
+ },
18
+ (table) => [
19
+ index("account_export_request_by_account_config_id").on(table.accountConfigId, table.createdAt),
20
+ ],
21
+ );
22
+
23
+ export const accountConfigs = sqliteTable(
24
+ "account_config",
25
+ {
26
+ accountConfigId: text("account_config_id").primaryKey().$defaultFn(() => generateBase36Id()),
27
+ userId: text("user_id").notNull(),
28
+ name: nullableText("name"),
29
+ state: text("state").$type<"active" | "deleting">().notNull().default("active"),
30
+ deletedAt: integer("deleted_at", { mode: "number" }),
31
+ cascadeStartedAt: integer("cascade_started_at", { mode: "number" }),
32
+ createdAt: integer("created_at", { mode: "number" }).notNull(),
33
+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
34
+ },
35
+ (table) => [
36
+ index("account_config_by_user_id").on(table.userId, table.accountConfigId),
37
+ ],
38
+ );
39
+
40
+ export const accounts = sqliteTable(
41
+ "account",
42
+ {
43
+ accountId: text("account_id").primaryKey().$defaultFn(() => generateBase36Id()),
44
+ accountConfigId: text("account_config_id").notNull(),
45
+ username: text("username").notNull(),
46
+ email: text("email").notNull(),
47
+ authType: text("auth_type").$type<"password" | "oauthMicrosoft">().notNull().default("password"),
48
+ passwordHash: nullableText("password_hash"),
49
+ oauthRefreshTokenHash: nullableText("oauth_refresh_token_hash"),
50
+ oauthTokenUpdatedAt: integer("oauth_token_updated_at", { mode: "number" }),
51
+ imapHost: text("imap_host").notNull(),
52
+ imapPort: integer("imap_port").notNull(),
53
+ imapTls: integer("imap_tls", { mode: "boolean" }).notNull(),
54
+ imapStartTls: integer("imap_start_tls", { mode: "boolean" }).notNull(),
55
+ smtpEnabled: integer("smtp_enabled", { mode: "boolean" }).notNull().default(false),
56
+ smtpHost: text("smtp_host").notNull().default(""),
57
+ smtpPort: integer("smtp_port").notNull(),
58
+ smtpTls: integer("smtp_tls", { mode: "boolean" }).notNull().default(false),
59
+ smtpStartTls: integer("smtp_start_tls", { mode: "boolean" }).notNull().default(true),
60
+ smtpUsername: text("smtp_username").notNull().default(""),
61
+ smtpPasswordHash: nullableText("smtp_password_hash"),
62
+ isActive: integer("is_active", { mode: "boolean" }).notNull(),
63
+ connectionState: text("connection_state").$type<"not_authenticated" | "authenticated" | "selected" | "logout" | "reauth_required">().notNull(),
64
+ lastConnectedAt: integer("last_connected_at", { mode: "number" }),
65
+ lastSyncAt: integer("last_sync_at", { mode: "number" }),
66
+ lastError: nullableText("last_error"),
67
+ syncPhase: text("sync_phase").$type<"idle" | "discovering_mailboxes" | "syncing_inbox" | "syncing_others" | "complete" | "error">(),
68
+ mailboxCountTotal: nullableInteger("mailbox_count_total"),
69
+ mailboxCountSynced: nullableInteger("mailbox_count_synced"),
70
+ createdAt: integer("created_at", { mode: "number" }).notNull(),
71
+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
72
+ deletedAt: integer("deleted_at", { mode: "number" }),
73
+ },
74
+ (table) => [
75
+ index("account_by_account_config_id").on(table.accountConfigId, table.accountId),
76
+ ],
77
+ );
78
+
79
+ export const mailboxes = sqliteTable(
80
+ "mailbox",
81
+ {
82
+ mailboxId: text("mailbox_id").primaryKey().$defaultFn(() => generateBase36Id()),
83
+ accountId: text("account_id").notNull(),
84
+ namespaceType: text("namespace_type").$type<"personal" | "other_users" | "shared">().notNull().default("personal"),
85
+ namespacePrefix: text("namespace_prefix").notNull(),
86
+ hierarchyDelimiter: text("hierarchy_delimiter").notNull(),
87
+ fullPath: text("full_path").notNull(),
88
+ uidValidity: integer("uid_validity", { mode: "number" }).notNull(),
89
+ uidNext: integer("uid_next", { mode: "number" }).notNull(),
90
+ highestModseq: integer("highest_modseq", { mode: "number" }).notNull(),
91
+ messageCount: integer("message_count").notNull(),
92
+ unseenCount: integer("unseen_count").notNull(),
93
+ deletedCount: integer("deleted_count").notNull(),
94
+ totalSize: integer("total_size", { mode: "number" }).notNull(),
95
+ lastSyncUid: integer("last_sync_uid", { mode: "number" }).notNull(),
96
+ highWaterMarkUid: integer("high_water_mark_uid", { mode: "number" }).notNull(),
97
+ lastMessageSyncAt: integer("last_message_sync_at", { mode: "number" }).notNull(),
98
+ initialSyncCompletedAt: integer("initial_sync_completed_at", { mode: "number" }),
99
+ parentMailboxId: text("parent_mailbox_id").notNull().default("None"),
100
+ syncStatus: text("sync_status").$type<"synced" | "pending" | "failed" | "deleting">(),
101
+ cursorState: text("cursor_state").$type<"normal" | "cursor_invalid" | "rebuilding">().notNull().default("normal"),
102
+ oldPath: nullableText("old_path"),
103
+ specialUse: text("special_use", { mode: "json" }),
104
+ createdAt: integer("created_at", { mode: "number" }).notNull(),
105
+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
106
+ },
107
+ (table) => [
108
+ index("mailbox_by_account_id").on(table.accountId),
109
+ ],
110
+ );
111
+
112
+ export const filters = sqliteTable(
113
+ "filter",
114
+ {
115
+ filterId: text("filter_id").primaryKey().$defaultFn(() => generateBase36Id()),
116
+ accountConfigId: text("account_config_id").notNull(),
117
+ name: text("name").notNull(),
118
+ scope: text("scope").$type<"Standing" | "Temporary">().notNull(),
119
+ expiresAt: nullableText("expires_at"),
120
+ ttl: integer("ttl", { mode: "number" }),
121
+ state: text("state").$type<"Active" | "Expired">().notNull().default("Active"),
122
+ hasAnchor: integer("has_anchor", { mode: "boolean" }).notNull().default(false),
123
+ ruleChangedAt: integer("rule_changed_at", { mode: "number" }).notNull(),
124
+ matchOperator: text("match_operator").$type<"And" | "Or">().notNull().default("And"),
125
+ literalClauses: text("literal_clauses", { mode: "json" }).notNull(),
126
+ actionLabelId: text("action_label_id").notNull().default("None"),
127
+ actionMailboxId: text("action_mailbox_id").notNull().default("None"),
128
+ createdAt: integer("created_at", { mode: "number" }).notNull(),
129
+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
130
+ },
131
+ (table) => [
132
+ index("filter_by_account_and_state").on(table.accountConfigId, table.state, table.filterId),
133
+ index("filter_primary").on(table.accountConfigId, table.filterId),
134
+ ],
135
+ );
136
+
137
+ export const organizeJobRequests = sqliteTable(
138
+ "organize_job_request",
139
+ {
140
+ organizeJobId: text("organize_job_id").primaryKey().$defaultFn(() => generateBase36Id()),
141
+ accountConfigId: text("account_config_id").notNull(),
142
+ userId: text("user_id").notNull(),
143
+ state: text("state").$type<"Pending" | "Running" | "Complete" | "Failed">().notNull().default("Pending"),
144
+ anchorMessageId: text("anchor_message_id").notNull().default("None"),
145
+ matchOperator: text("match_operator").$type<"And" | "Or">().notNull().default("And"),
146
+ literalClauses: text("literal_clauses", { mode: "json" }).notNull(),
147
+ similarityThreshold: real("similarity_threshold").notNull(),
148
+ actionLabelId: text("action_label_id").notNull().default("None"),
149
+ actionMailboxId: text("action_mailbox_id").notNull().default("None"),
150
+ matchedCount: integer("matched_count").notNull(),
151
+ appliedCount: integer("applied_count").notNull(),
152
+ failedCount: integer("failed_count").notNull(),
153
+ errorMessage: text("error_message").notNull().default(""),
154
+ ttl: integer("ttl", { mode: "number" }).notNull(),
155
+ createdAt: integer("created_at", { mode: "number" }).notNull(),
156
+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
157
+ },
158
+ (table) => [
159
+ index("organize_job_request_by_account_config_id").on(table.accountConfigId, table.createdAt),
160
+ ],
161
+ );
162
+
163
+ export const threadMessages = sqliteTable(
164
+ "thread_message",
165
+ {
166
+ threadMessageId: text("thread_message_id").primaryKey().$defaultFn(() => generateBase36Id()),
167
+ threadId: text("thread_id").notNull(),
168
+ messageId: text("message_id").notNull(),
169
+ accountConfigId: text("account_config_id").notNull(),
170
+ mailboxId: text("mailbox_id").notNull(),
171
+ uid: integer("uid", { mode: "number" }).notNull(),
172
+ messageIdHeader: nullableText("message_id_header"),
173
+ inReplyTo: nullableText("in_reply_to"),
174
+ referenceOrder: integer("reference_order").notNull(),
175
+ fromEmail: nullableText("from_email"),
176
+ fromName: nullableText("from_name"),
177
+ subject: nullableText("subject"),
178
+ internalDate: integer("internal_date", { mode: "number" }).notNull(),
179
+ sentDate: integer("sent_date", { mode: "number" }).notNull(),
180
+ isRead: integer("is_read", { mode: "boolean" }).notNull(),
181
+ hasAttachment: integer("has_attachment", { mode: "boolean" }).notNull(),
182
+ star: text("star").$type<"none" | "yellow" | "orange" | "red" | "purple" | "blue" | "teal" | "green" | "yellow_bang" | "red_bang" | "purple_question" | "blue_info" | "orange_guillemet" | "green_check" | "yellow_check" | "blue_star">().notNull().default("none"),
183
+ hasStars: integer("has_stars", { mode: "boolean" }).notNull(),
184
+ isDeleted: integer("is_deleted", { mode: "boolean" }).notNull(),
185
+ snippet: nullableText("snippet"),
186
+ category: text("category").$type<"uncategorized" | "personal" | "newsletter" | "marketing" | "automated" | "transactional" | "social">().notNull().default("uncategorized"),
187
+ createdAt: integer("created_at", { mode: "number" }).notNull(),
188
+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
189
+ },
190
+ (table) => [
191
+ index("thread_message_by_mailbox_and_read_status").on(table.accountConfigId, table.mailboxId, table.isRead, table.sentDate),
192
+ index("thread_message_by_starred").on(table.accountConfigId, table.hasStars, table.sentDate),
193
+ index("thread_message_by_attachment").on(table.accountConfigId, table.hasAttachment, table.sentDate),
194
+ index("thread_message_by_mailbox_id").on(table.accountConfigId, table.mailboxId, table.sentDate),
195
+ index("thread_message_by_date").on(table.accountConfigId, table.sentDate),
196
+ index("thread_message_by_unread").on(table.accountConfigId, table.isRead, table.sentDate),
197
+ index("thread_message_by_message_id").on(table.messageId),
198
+ index("thread_message_by_thread_id").on(table.threadId, table.sentDate),
199
+ index("thread_message_primary").on(table.accountConfigId, table.threadMessageId),
200
+ ],
201
+ );
202
+
203
+ export const outboxMessages = sqliteTable(
204
+ "outbox_message",
205
+ {
206
+ outboxMessageId: text("outbox_message_id").primaryKey().$defaultFn(() => generateBase36Id()),
207
+ accountId: text("account_id").notNull(),
208
+ accountConfigId: text("account_config_id").notNull(),
209
+ fromAddress: text("from_address").notNull(),
210
+ fromName: nullableText("from_name"),
211
+ toAddresses: text("to_addresses", { mode: "json" }).notNull(),
212
+ ccAddresses: text("cc_addresses", { mode: "json" }).notNull(),
213
+ bccAddresses: text("bcc_addresses", { mode: "json" }).notNull(),
214
+ replyToAddress: nullableText("reply_to_address"),
215
+ subject: nullableText("subject"),
216
+ messageIdValue: text("message_id_value").notNull(),
217
+ inReplyTo: nullableText("in_reply_to"),
218
+ references: text("references", { mode: "json" }).notNull(),
219
+ textBody: nullableText("text_body"),
220
+ htmlBody: nullableText("html_body"),
221
+ status: text("status").$type<"draft" | "queued" | "sending" | "sent" | "failed" | "blocked">().notNull(),
222
+ lastError: nullableText("last_error"),
223
+ lastSmtpCode: nullableInteger("last_smtp_code"),
224
+ sentAt: integer("sent_at", { mode: "number" }),
225
+ smtpMessageId: nullableText("smtp_message_id"),
226
+ createdAt: integer("created_at", { mode: "number" }).notNull(),
227
+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
228
+ },
229
+ (table) => [
230
+ index("outbox_message_by_account_id").on(table.accountId, table.createdAt),
231
+ ],
232
+ );
233
+
234
+ export const addresses = sqliteTable(
235
+ "address",
236
+ {
237
+ addressId: text("address_id").primaryKey().$defaultFn(() => generateBase36Id()),
238
+ accountConfigId: text("account_config_id").notNull(),
239
+ displayName: nullableText("display_name"),
240
+ localPart: text("local_part").notNull(),
241
+ domain: text("domain").notNull(),
242
+ normalizedEmail: text("normalized_email").notNull(),
243
+ normalizedCompound: text("normalized_compound").notNull(),
244
+ flags: text("flags", { mode: "json" }).notNull(),
245
+ inboundCount: integer("inbound_count").notNull(),
246
+ outboundCount: integer("outbound_count").notNull(),
247
+ replyCount: integer("reply_count").notNull(),
248
+ lastInboundAt: integer("last_inbound_at", { mode: "number" }).notNull(),
249
+ lastOutboundAt: integer("last_outbound_at", { mode: "number" }),
250
+ lastReplyAt: integer("last_reply_at", { mode: "number" }).notNull(),
251
+ createdAt: integer("created_at", { mode: "number" }).notNull(),
252
+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
253
+ },
254
+ (table) => [
255
+ index("address_by_account_config_id").on(table.accountConfigId, table.normalizedCompound),
256
+ ],
257
+ );
258
+
259
+ export const messages = sqliteTable(
260
+ "message",
261
+ {
262
+ messageId: text("message_id").primaryKey().$defaultFn(() => generateBase36Id()),
263
+ mailboxId: text("mailbox_id").notNull(),
264
+ uid: integer("uid", { mode: "number" }).notNull(),
265
+ sequenceNumber: integer("sequence_number").notNull(),
266
+ rfc822Size: integer("rfc822_size", { mode: "number" }).notNull(),
267
+ internalDate: integer("internal_date", { mode: "number" }).notNull(),
268
+ messageIdHeader: nullableText("message_id_header"),
269
+ envelopeId: text("envelope_id").notNull(),
270
+ rootBodyPartId: text("root_body_part_id").notNull(),
271
+ bodyStorageKey: nullableText("body_storage_key"),
272
+ status: text("status").$type<"active" | "deleting" | "deleted" | "moving">().notNull().default("active"),
273
+ syncStatus: text("sync_status").$type<"synced" | "pending" | "failed">().notNull().default("synced"),
274
+ originalMailboxId: nullableText("original_mailbox_id"),
275
+ originalUid: integer("original_uid", { mode: "number" }),
276
+ category: text("category").$type<"uncategorized" | "personal" | "newsletter" | "marketing" | "automated" | "transactional" | "social">().notNull().default("uncategorized"),
277
+ authenticity: text("authenticity", { mode: "json" }),
278
+ authResult: text("auth_result", { mode: "json" }),
279
+ providerSpam: text("provider_spam", { mode: "json" }),
280
+ hasListUnsubscribe: integer("has_list_unsubscribe", { mode: "boolean" }).notNull().default(false),
281
+ movedByRemit: integer("moved_by_remit", { mode: "boolean" }).notNull().default(false),
282
+ placementVerdict: text("placement_verdict", { mode: "json" }),
283
+ createdAt: integer("created_at", { mode: "number" }).notNull(),
284
+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
285
+ },
286
+ (table) => [
287
+ index("message_by_mailbox_id").on(table.mailboxId, table.uid),
288
+ ],
289
+ );
290
+
291
+ export const bodyParts = sqliteTable(
292
+ "body_part",
293
+ {
294
+ bodyPartId: text("body_part_id").primaryKey().$defaultFn(() => generateBase36Id()),
295
+ messageId: text("message_id").notNull(),
296
+ parentBodyPartId: nullableText("parent_body_part_id"),
297
+ partPath: text("part_path").notNull(),
298
+ mediaType: text("media_type").$type<"TEXT" | "IMAGE" | "AUDIO" | "VIDEO" | "APPLICATION" | "MULTIPART" | "MESSAGE">().notNull(),
299
+ mediaSubtype: text("media_subtype").notNull(),
300
+ contentId: nullableText("content_id"),
301
+ contentDescription: nullableText("content_description"),
302
+ transferEncoding: text("transfer_encoding").$type<"7BIT" | "8BIT" | "BINARY" | "BASE64" | "QUOTED-PRINTABLE">().notNull(),
303
+ sizeOctets: integer("size_octets", { mode: "number" }).notNull(),
304
+ lineCount: nullableInteger("line_count"),
305
+ md5Hash: nullableText("md5_hash"),
306
+ disposition: text("disposition").$type<"inline" | "attachment">(),
307
+ dispositionFilename: nullableText("disposition_filename"),
308
+ language: nullableText("language"),
309
+ location: nullableText("location"),
310
+ isMultipart: integer("is_multipart", { mode: "boolean" }).notNull(),
311
+ multipartSubtype: text("multipart_subtype").$type<"mixed" | "alternative" | "digest" | "parallel" | "related" | "signed" | "encrypted" | "form-data" | "report">(),
312
+ createdAt: integer("created_at", { mode: "number" }).notNull(),
313
+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
314
+ },
315
+ (table) => [
316
+ index("body_part_by_message_id").on(table.messageId, table.bodyPartId),
317
+ ],
318
+ );
319
+
320
+ export const messageReferences = sqliteTable(
321
+ "message_reference",
322
+ {
323
+ messageReferenceId: text("message_reference_id").primaryKey().$defaultFn(() => generateBase36Id()),
324
+ messageId: text("message_id").notNull(),
325
+ envelopeId: text("envelope_id").notNull(),
326
+ messageIdValue: text("message_id_value").notNull(),
327
+ referenceType: text("reference_type").$type<"in_reply_to" | "references">().notNull(),
328
+ referenceOrder: integer("reference_order").notNull(),
329
+ createdAt: integer("created_at", { mode: "number" }).notNull(),
330
+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
331
+ },
332
+ (table) => [
333
+ index("message_reference_by_message_id").on(table.messageId, table.messageReferenceId),
334
+ ],
335
+ );
336
+
337
+ export const envelopeAddresses = sqliteTable(
338
+ "envelope_address",
339
+ {
340
+ envelopeAddressId: text("envelope_address_id").primaryKey().$defaultFn(() => generateBase36Id()),
341
+ messageId: text("message_id").notNull(),
342
+ addressId: text("address_id").notNull(),
343
+ displayName: nullableText("display_name"),
344
+ normalizedEmail: text("normalized_email").notNull(),
345
+ addressRole: text("address_role").$type<"from" | "sender" | "reply_to" | "to" | "cc" | "bcc">().notNull(),
346
+ addressOrder: integer("address_order").notNull(),
347
+ createdAt: integer("created_at", { mode: "number" }).notNull(),
348
+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
349
+ },
350
+ (table) => [
351
+ index("envelope_address_by_message_id").on(table.messageId, table.envelopeAddressId),
352
+ ],
353
+ );
354
+
355
+ export const accountSettings = sqliteTable(
356
+ "account_setting",
357
+ {
358
+ accountSettingId: text("account_setting_id").primaryKey().$defaultFn(() => generateBase36Id()),
359
+ accountConfigId: text("account_config_id").notNull(),
360
+ name: text("name").notNull(),
361
+ value: text("value", { mode: "json" }).notNull(),
362
+ createdAt: integer("created_at", { mode: "number" }).notNull(),
363
+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
364
+ },
365
+ (table) => [
366
+ index("account_setting_by_account_config_id").on(table.accountConfigId, table.name),
367
+ ],
368
+ );
369
+
370
+ export const mailboxAttributeEntries = sqliteTable(
371
+ "mailbox_attribute_entry",
372
+ {
373
+ mailboxAttributeId: text("mailbox_attribute_id").primaryKey().$defaultFn(() => generateBase36Id()),
374
+ mailboxId: text("mailbox_id").notNull(),
375
+ attributeName: text("attribute_name").$type<"\\NonExistent" | "\\Noinferiors" | "\\Noselect" | "\\HasChildren" | "\\HasNoChildren" | "\\Marked" | "\\Unmarked" | "\\Subscribed" | "\\Remote">().notNull(),
376
+ },
377
+ (table) => [
378
+ index("mailbox_attribute_entry_by_mailbox_id").on(table.mailboxId, table.mailboxAttributeId),
379
+ ],
380
+ );
381
+
382
+ export const mailboxSpecialUseEntries = sqliteTable(
383
+ "mailbox_special_use_entry",
384
+ {
385
+ mailboxSpecialUseId: text("mailbox_special_use_id").primaryKey().$defaultFn(() => generateBase36Id()),
386
+ mailboxId: text("mailbox_id").notNull(),
387
+ specialUse: text("special_use").$type<"All" | "Archive" | "Drafts" | "Flagged" | "Junk" | "Sent" | "Trash" | "Important">().notNull(),
388
+ },
389
+ (table) => [
390
+ index("mailbox_special_use_entry_by_mailbox_id").on(table.mailboxId, table.mailboxSpecialUseId),
391
+ ],
392
+ );
393
+
394
+ export const mailboxFlags = sqliteTable(
395
+ "mailbox_flag",
396
+ {
397
+ mailboxFlagId: text("mailbox_flag_id").primaryKey().$defaultFn(() => generateBase36Id()),
398
+ mailboxId: text("mailbox_id").notNull(),
399
+ flagName: text("flag_name").notNull(),
400
+ isPermanent: integer("is_permanent", { mode: "boolean" }).notNull(),
401
+ },
402
+ (table) => [
403
+ index("mailbox_flag_by_mailbox_id").on(table.mailboxId, table.mailboxFlagId),
404
+ ],
405
+ );
406
+
407
+ export const mailboxLocks = sqliteTable(
408
+ "mailbox_lock",
409
+ {
410
+ mailboxId: text("mailbox_id").notNull(),
411
+ eventName: text("event_name").notNull(),
412
+ accountId: text("account_id").notNull(),
413
+ lockId: text("lock_id").notNull(),
414
+ acquiredAt: integer("acquired_at", { mode: "number" }).notNull(),
415
+ lockedBy: text("locked_by").notNull(),
416
+ ttl: integer("ttl", { mode: "number" }).notNull(),
417
+ },
418
+ (table) => [
419
+ primaryKey({ name: "mailbox_lock_pk", columns: [table.mailboxId, table.eventName] }),
420
+ index("mailbox_lock_all_locks").on(table.acquiredAt),
421
+ index("mailbox_lock_by_account_id").on(table.accountId, table.mailboxId, table.eventName),
422
+ ],
423
+ );
424
+
425
+ export const messageFlags = sqliteTable(
426
+ "message_flag",
427
+ {
428
+ messageFlagId: text("message_flag_id").primaryKey().$defaultFn(() => generateBase36Id()),
429
+ messageId: text("message_id").notNull(),
430
+ flagName: text("flag_name").notNull(),
431
+ setAt: integer("set_at", { mode: "number" }).notNull(),
432
+ createdAt: integer("created_at", { mode: "number" }).notNull(),
433
+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
434
+ },
435
+ (table) => [
436
+ index("message_flag_by_message_id").on(table.messageId, table.messageFlagId),
437
+ ],
438
+ );
439
+
440
+ export const messagePlacementMoves = sqliteTable(
441
+ "message_placement_move",
442
+ {
443
+ messageId: text("message_id").primaryKey().$defaultFn(() => generateBase36Id()),
444
+ accountId: text("account_id").notNull(),
445
+ accountConfigId: text("account_config_id").notNull(),
446
+ sourceMailboxId: text("source_mailbox_id").notNull(),
447
+ destinationMailboxId: text("destination_mailbox_id").notNull(),
448
+ state: text("state").$type<"pending" | "queued" | "processing" | "processed">().notNull().default("pending"),
449
+ createdAt: integer("created_at", { mode: "number" }).notNull(),
450
+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
451
+ },
452
+ (table) => [
453
+ index("message_placement_move_by_account_id").on(table.accountId, table.messageId),
454
+ ],
455
+ );
456
+
457
+ export const messageFlagPushes = sqliteTable(
458
+ "message_flag_push",
459
+ {
460
+ messageId: text("message_id").notNull(),
461
+ flagName: text("flag_name").notNull(),
462
+ accountId: text("account_id").notNull(),
463
+ accountConfigId: text("account_config_id").notNull(),
464
+ mailboxId: text("mailbox_id").notNull(),
465
+ operation: text("operation").$type<"add" | "remove">().notNull(),
466
+ state: text("state").$type<"pending" | "queued" | "processing" | "processed">().notNull().default("pending"),
467
+ createdAt: integer("created_at", { mode: "number" }).notNull(),
468
+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
469
+ },
470
+ (table) => [
471
+ primaryKey({ name: "message_flag_push_pk", columns: [table.messageId, table.flagName] }),
472
+ index("message_flag_push_by_mailbox_id").on(table.mailboxId, table.messageId, table.flagName),
473
+ index("message_flag_push_by_account_id").on(table.accountId, table.messageId, table.flagName),
474
+ ],
475
+ );
476
+
477
+ export const envelopes = sqliteTable(
478
+ "envelope",
479
+ {
480
+ envelopeId: text("envelope_id").primaryKey().$defaultFn(() => generateBase36Id()),
481
+ messageId: text("message_id").notNull(),
482
+ dateValue: integer("date_value", { mode: "number" }).notNull(),
483
+ dateRaw: text("date_raw").notNull(),
484
+ subject: nullableText("subject"),
485
+ messageIdValue: nullableText("message_id_value"),
486
+ createdAt: integer("created_at", { mode: "number" }).notNull(),
487
+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
488
+ },
489
+ (table) => [
490
+ index("envelope_by_message_id").on(table.messageId, table.envelopeId),
491
+ ],
492
+ );
493
+
494
+ export const bodyPartParameters = sqliteTable(
495
+ "body_part_parameter",
496
+ {
497
+ bodyPartParameterId: text("body_part_parameter_id").primaryKey().$defaultFn(() => generateBase36Id()),
498
+ messageId: text("message_id").notNull(),
499
+ bodyPartId: text("body_part_id").notNull(),
500
+ parameterName: text("parameter_name").notNull(),
501
+ parameterValue: text("parameter_value").notNull(),
502
+ createdAt: integer("created_at", { mode: "number" }).notNull(),
503
+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
504
+ },
505
+ (table) => [
506
+ index("body_part_parameter_by_message_id").on(table.messageId, table.bodyPartParameterId),
507
+ ],
508
+ );
509
+
510
+ export const rawMessageStorages = sqliteTable(
511
+ "raw_message_storage",
512
+ {
513
+ rawStorageId: text("raw_storage_id").primaryKey().$defaultFn(() => generateBase36Id()),
514
+ messageId: text("message_id").notNull(),
515
+ storageType: text("storage_type").$type<"s3" | "filesystem" | "inline" | "database">().notNull(),
516
+ storageLocation: text("storage_location").notNull(),
517
+ storageKey: text("storage_key").notNull(),
518
+ sizeBytes: integer("size_bytes", { mode: "number" }).notNull(),
519
+ checksumSha256: text("checksum_sha256").notNull(),
520
+ contentEncoding: text("content_encoding").$type<"none" | "gzip" | "zstd">().notNull(),
521
+ storedAt: integer("stored_at", { mode: "number" }).notNull(),
522
+ expiresAt: integer("expires_at", { mode: "number" }),
523
+ createdAt: integer("created_at", { mode: "number" }).notNull(),
524
+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
525
+ },
526
+ (table) => [
527
+ index("raw_message_storage_by_message_id").on(table.messageId, table.rawStorageId),
528
+ ],
529
+ );
530
+
531
+ export const bodyPartStorages = sqliteTable(
532
+ "body_part_storage",
533
+ {
534
+ bodyPartStorageId: text("body_part_storage_id").primaryKey().$defaultFn(() => generateBase36Id()),
535
+ messageId: text("message_id").notNull(),
536
+ bodyPartId: text("body_part_id").notNull(),
537
+ storageType: text("storage_type").$type<"s3" | "filesystem" | "inline" | "database">().notNull(),
538
+ storageLocation: text("storage_location").notNull(),
539
+ storageKey: text("storage_key").notNull(),
540
+ decodedSizeBytes: integer("decoded_size_bytes", { mode: "number" }).notNull(),
541
+ checksumSha256: text("checksum_sha256").notNull(),
542
+ contentEncoding: text("content_encoding").$type<"none" | "gzip" | "zstd">().notNull(),
543
+ isDeduped: integer("is_deduped", { mode: "boolean" }).notNull(),
544
+ dedupHash: nullableText("dedup_hash"),
545
+ storedAt: integer("stored_at", { mode: "number" }).notNull(),
546
+ createdAt: integer("created_at", { mode: "number" }).notNull(),
547
+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
548
+ },
549
+ (table) => [
550
+ index("body_part_storage_by_message_id").on(table.messageId, table.bodyPartStorageId),
551
+ ],
552
+ );
553
+
554
+ export const bodyPartContents = sqliteTable(
555
+ "body_part_content",
556
+ {
557
+ bodyPartContentId: text("body_part_content_id").primaryKey().$defaultFn(() => generateBase36Id()),
558
+ messageId: text("message_id").notNull(),
559
+ bodyPartId: text("body_part_id").notNull(),
560
+ content: text("content").notNull(),
561
+ contentLength: integer("content_length", { mode: "number" }).notNull(),
562
+ createdAt: integer("created_at", { mode: "number" }).notNull(),
563
+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
564
+ },
565
+ (table) => [
566
+ index("body_part_content_by_message_id").on(table.messageId, table.bodyPartContentId),
567
+ ],
568
+ );
569
+
570
+ export const labels = sqliteTable(
571
+ "label",
572
+ {
573
+ labelId: text("label_id").primaryKey().$defaultFn(() => generateBase36Id()),
574
+ accountConfigId: text("account_config_id").notNull(),
575
+ name: text("name").notNull(),
576
+ normalizedName: text("normalized_name").notNull(),
577
+ color: text("color").$type<"Default" | "Red" | "Orange" | "Yellow" | "Green" | "Teal" | "Blue" | "Purple" | "Gray">().notNull().default("Default"),
578
+ createdAt: integer("created_at", { mode: "number" }).notNull(),
579
+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
580
+ },
581
+ (table) => [
582
+ index("label_by_normalized_name").on(table.accountConfigId, table.normalizedName),
583
+ index("label_primary").on(table.accountConfigId, table.labelId),
584
+ ],
585
+ );
586
+
587
+ export const messageLabels = sqliteTable(
588
+ "message_label",
589
+ {
590
+ messageLabelId: text("message_label_id").primaryKey().$defaultFn(() => generateBase36Id()),
591
+ messageId: text("message_id").notNull(),
592
+ labelId: text("label_id").notNull(),
593
+ accountConfigId: text("account_config_id").notNull(),
594
+ appliedByFilterId: nullableText("applied_by_filter_id"),
595
+ createdAt: integer("created_at", { mode: "number" }).notNull(),
596
+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
597
+ },
598
+ (table) => [
599
+ index("message_label_by_label_id").on(table.accountConfigId, table.labelId, table.createdAt),
600
+ index("message_label_by_message_id").on(table.messageId, table.labelId),
601
+ ],
602
+ );
603
+
604
+ export const filterAnchors = sqliteTable(
605
+ "filter_anchor",
606
+ {
607
+ accountConfigId: text("account_config_id").notNull(),
608
+ filterId: text("filter_id").notNull(),
609
+ anchorEmbedding: text("anchor_embedding", { mode: "json" }).notNull(),
610
+ anchorEmbeddingId: text("anchor_embedding_id").notNull(),
611
+ anchorSourceText: text("anchor_source_text").notNull(),
612
+ anchorMessageId: text("anchor_message_id").notNull(),
613
+ createdAt: integer("created_at", { mode: "number" }).notNull(),
614
+ updatedAt: integer("updated_at", { mode: "number" }).notNull(),
615
+ },
616
+ (table) => [
617
+ primaryKey({ name: "filter_anchor_pk", columns: [table.accountConfigId, table.filterId] }),
618
+ ],
619
+ );
package/tsconfig.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "module": "NodeNext",
5
+ "declaration": true,
6
+ "skipLibCheck": true,
7
+ "outDir": "dist"
8
+ },
9
+ "include": [
10
+ "*.ts"
11
+ ]
12
+ }