@happyvertical/smrt-messages 0.32.1 → 0.33.0

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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/__smrt-register__.ts","../src/models/Account.ts","../src/collections/AccountCollection.ts","../src/models/Attachment.ts","../src/collections/AttachmentCollection.ts","../src/models/Message.ts","../src/collections/MessageCollection.ts","../src/models/EmailAccount.ts","../src/collections/EmailAccountCollection.ts","../src/models/EmailAttachment.ts","../src/collections/EmailAttachmentCollection.ts","../src/models/Email.ts","../src/collections/EmailCollection.ts","../src/models/EmailFolder.ts","../src/collections/EmailFolderCollection.ts","../src/models/Blacklist.ts","../src/collections/BlacklistCollection.ts","../src/models/Whitelist.ts","../src/collections/WhitelistCollection.ts","../src/models/SlackAccount.ts","../src/models/SlackMessage.ts","../src/models/Tweet.ts","../src/models/TwitterAccount.ts","../src/senders/EmailSender.ts","../src/senders/SlackSender.ts","../src/senders/TweetSender.ts"],"sourcesContent":["/**\n * Self-registers this package's build-time manifest before any @smrt() decorator\n * in the package fires. Fixes issue #1132: in consumer runtimes (tsx, SvelteKit\n * SSR, plain `vite dev`) the decorator's synchronous manifest lookup previously\n * missed because no step populated the global manifest cache — classes got\n * registered with zero fields and `save()` / `toJSON()` silently dropped every\n * declared property.\n *\n * Import this module as the first statement in `src/index.ts` so its top-level\n * side effect runs ahead of any class module's @smrt() decorator.\n *\n * Silent no-op in dev/test, where the vitest plugin already populates manifests\n * via a different path. Only needs to succeed in the published dist output.\n *\n * @see https://github.com/happyvertical/smrt/issues/1132\n */\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\n\n// `new URL('./manifest.json', import.meta.url)` resolves at runtime to the\n// manifest sitting next to this module's compiled output. Vite warns at build\n// time that it cannot pre-resolve the URL; that is the intended behavior —\n// the URL must resolve to dist/manifest.json at runtime, not be inlined.\nObjectRegistry.registerPackageManifest(\n new URL('./manifest.json', import.meta.url),\n);\n","/**\n * Account model - Base class for all messaging account types (STI)\n *\n * Common fields shared across email, Slack, Twitter accounts, etc.\n */\n\nimport { field, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type { AccountOptions, MessageSenderInterface } from '../types';\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class Account extends SmrtObject {\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n name = '';\n providerType = '';\n // credentialSecretId stores the Secret's NAME (keyed by name + tenant\n // context in smrt-secrets), NOT its primary-key id — see setCredentials()/\n // getCredentials() which call secretService.store/retrieve by name. So it is\n // deliberately NOT a @crossPackageRef id FK.\n credentialSecretId: string | null = null;\n isActive = true;\n lastSyncAt: Date | null = null;\n // JSON. Sensitive (#1540): may hold a plaintext credential fallback, so it is\n // excluded from generated API/MCP responses and rejected as a `where` filter\n // key.\n @field({ sensitive: true })\n settings = ''; // JSON\n\n // Timestamps\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: AccountOptions = {}) {\n super(options);\n\n if (options.tenantId !== undefined) this.tenantId = options.tenantId as any;\n if (options.name !== undefined) this.name = options.name;\n if (options.providerType !== undefined)\n this.providerType = options.providerType;\n if (options.credentialSecretId !== undefined)\n this.credentialSecretId = options.credentialSecretId || null;\n if (options.isActive !== undefined) this.isActive = options.isActive;\n if (options.lastSyncAt !== undefined)\n this.lastSyncAt = options.lastSyncAt || null;\n if (options.settings !== undefined) this.settings = options.settings;\n if (options.createdAt) this.createdAt = options.createdAt;\n if (options.updatedAt) this.updatedAt = options.updatedAt;\n }\n\n /**\n * Get settings as parsed object\n */\n getSettings(): Record<string, any> {\n if (!this.settings) return {};\n try {\n return JSON.parse(this.settings);\n } catch {\n return {};\n }\n }\n\n /**\n * Set settings from object\n */\n setSettings(settings: Record<string, any>): void {\n this.settings = JSON.stringify(settings);\n }\n\n /**\n * Activate account\n */\n async activate(): Promise<void> {\n this.isActive = true;\n this.updatedAt = new Date();\n await this.save();\n }\n\n /**\n * Deactivate account\n */\n async deactivate(): Promise<void> {\n this.isActive = false;\n this.updatedAt = new Date();\n await this.save();\n }\n\n /**\n * Store credentials securely using smrt-secrets\n */\n async setCredentials(\n credentials: Record<string, any>,\n options: {\n description?: string;\n category?: string;\n } = {},\n ): Promise<void> {\n const { SecretService } = await import('@happyvertical/smrt-secrets');\n const secretService = await SecretService.create({ db: this.db });\n\n const secretName = `account-${this.id}`;\n const secretValue = JSON.stringify(credentials);\n\n if (this.credentialSecretId) {\n await secretService.store(this.credentialSecretId, secretValue, {\n description: options.description || `Credentials for ${this.name}`,\n category: options.category || 'messaging',\n });\n } else {\n await secretService.store(secretName, secretValue, {\n description: options.description || `Credentials for ${this.name}`,\n category: options.category || 'messaging',\n });\n\n this.credentialSecretId = secretName;\n this.updatedAt = new Date();\n await this.save();\n }\n }\n\n /**\n * Create a sender for this account.\n * Subclasses must override to return a concrete sender.\n */\n async createSender(): Promise<MessageSenderInterface> {\n throw new Error(\n `createSender() not implemented for account type '${this.providerType}'`,\n );\n }\n\n /**\n * Retrieve stored credentials\n */\n async getCredentials(): Promise<Record<string, any> | null> {\n if (!this.credentialSecretId) {\n return this.getSettings();\n }\n\n const { SecretService } = await import('@happyvertical/smrt-secrets');\n const secretService = await SecretService.create({ db: this.db });\n\n try {\n const secret = await secretService.retrieve(this.credentialSecretId);\n return JSON.parse(secret.value);\n } catch {\n return null;\n }\n }\n}\n","/**\n * AccountCollection - Unified collection for polymorphic account queries\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { Account } from '../models/Account';\nimport type { AccountSearchFilters } from '../types';\n\nexport class AccountCollection extends SmrtCollection<Account> {\n static readonly _itemClass = Account;\n\n /**\n * Get active accounts\n */\n async getActive(): Promise<Account[]> {\n return await this.list({ where: { isActive: true } });\n }\n\n /**\n * Get inactive accounts\n */\n async getInactive(): Promise<Account[]> {\n return await this.list({ where: { isActive: false } });\n }\n\n /**\n * Get accounts by provider type\n */\n async getByProviderType(providerType: string): Promise<Account[]> {\n return await this.list({ where: { providerType } });\n }\n\n /**\n * Get accounts by STI type.\n *\n * Accepts either the full discriminator (e.g. \"@happyvertical/smrt-messages:EmailAccount\")\n * or the short type name (e.g. \"EmailAccount\").\n */\n async getByType(accountType: string): Promise<Account[]> {\n if (accountType.includes(':') || accountType.startsWith('@')) {\n return await this.list({ where: { _meta_type: accountType } });\n }\n const allAccounts = await this.list({});\n return allAccounts.filter((a) => {\n const metaType = (a as any)._meta_type || '';\n return metaType.endsWith(`:${accountType}`);\n });\n }\n\n /**\n * Search accounts with filters\n */\n async search(\n query: string,\n filters?: AccountSearchFilters,\n ): Promise<Account[]> {\n let accounts = await this.list({});\n\n if (query) {\n const lowerQuery = query.toLowerCase();\n accounts = accounts.filter((a) =>\n a.name?.toLowerCase().includes(lowerQuery),\n );\n }\n\n if (filters) {\n if (filters.providerType) {\n accounts = accounts.filter(\n (a) => a.providerType === filters.providerType,\n );\n }\n if (filters.isActive !== undefined) {\n accounts = accounts.filter((a) => a.isActive === filters.isActive);\n }\n if (filters.accountType) {\n accounts = accounts.filter((a) => {\n const metaType = (a as any)._meta_type || '';\n return metaType.includes(filters.accountType as string);\n });\n }\n }\n\n return accounts;\n }\n\n /**\n * Get account statistics\n */\n async getStats(): Promise<{\n total: number;\n active: number;\n inactive: number;\n byType: Record<string, number>;\n }> {\n const accounts = await this.list({});\n const byType: Record<string, number> = {};\n\n for (const account of accounts) {\n const metaType = (account as any)._meta_type || 'Unknown';\n const shortType = metaType.split(':').pop() || metaType;\n byType[shortType] = (byType[shortType] || 0) + 1;\n }\n\n return {\n total: accounts.length,\n active: accounts.filter((a) => a.isActive).length,\n inactive: accounts.filter((a) => !a.isActive).length,\n byType,\n };\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Tenant Helper Methods\n // ─────────────────────────────────────────────────────────────────────────\n\n async findByTenant(tenantId: string): Promise<Account[]> {\n return this.list({ where: { tenantId } });\n }\n\n async findGlobal(): Promise<Account[]> {\n return this.list({ where: { tenantId: null } });\n }\n\n async findWithGlobals(tenantId: string): Promise<Account[]> {\n return this.query(\n `SELECT * FROM ${this.tableName} WHERE tenant_id = ? OR tenant_id IS NULL`,\n [tenantId],\n );\n }\n}\n","/**\n * Attachment model - Generalized attachment for any message type\n *\n * Uses messageId instead of emailId for cross-type support.\n */\n\nimport { foreignKey, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type { AttachmentOptions } from '../types';\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n api: { include: ['list', 'get', 'create', 'delete'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class Attachment extends SmrtObject {\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n @foreignKey('Message')\n messageId = '';\n filename = '';\n contentType = '';\n size = 0;\n contentId = ''; // For inline images (<img src=\"cid:...\">)\n contentDisposition: 'attachment' | 'inline' = 'attachment';\n filePath = ''; // External file storage path\n sourceUrl = ''; // For non-email attachments (media URLs, etc.)\n\n // Timestamps\n createdAt = new Date();\n\n constructor(options: AttachmentOptions = {}) {\n super(options);\n\n if (options.tenantId !== undefined) this.tenantId = options.tenantId as any;\n if (options.messageId !== undefined) this.messageId = options.messageId;\n if (options.filename !== undefined) this.filename = options.filename;\n if (options.contentType !== undefined)\n this.contentType = options.contentType;\n if (options.size !== undefined) this.size = options.size;\n if (options.contentId !== undefined) this.contentId = options.contentId;\n if (options.contentDisposition !== undefined)\n this.contentDisposition = options.contentDisposition;\n if (options.filePath !== undefined) this.filePath = options.filePath;\n if (options.sourceUrl !== undefined) this.sourceUrl = options.sourceUrl;\n if (options.createdAt) this.createdAt = options.createdAt;\n }\n\n /**\n * Get the message this attachment belongs to\n */\n async getMessage() {\n if (!this.messageId) return null;\n\n const { MessageCollection } = await import(\n '../collections/MessageCollection'\n );\n const collection = await (MessageCollection as any).create(this.options);\n\n return await collection.get({ id: this.messageId });\n }\n\n /**\n * Check if attachment is an image\n */\n isImage(): boolean {\n return this.contentType.startsWith('image/');\n }\n\n /**\n * Check if attachment is a PDF\n */\n isPdf(): boolean {\n return this.contentType === 'application/pdf';\n }\n\n /**\n * Check if attachment is inline (embedded in message body)\n */\n isInline(): boolean {\n return this.contentDisposition === 'inline';\n }\n\n /**\n * Get file extension from filename\n */\n getExtension(): string {\n if (!this.filename) return '';\n const parts = this.filename.split('.');\n return parts.length > 1 ? parts[parts.length - 1].toLowerCase() : '';\n }\n\n /**\n * Get human-readable file size\n */\n getFormattedSize(): string {\n const units = ['B', 'KB', 'MB', 'GB'];\n let size = this.size;\n let unitIndex = 0;\n\n while (size >= 1024 && unitIndex < units.length - 1) {\n size /= 1024;\n unitIndex++;\n }\n\n return `${size.toFixed(1)} ${units[unitIndex]}`;\n }\n\n /**\n * Check if file is stored externally\n */\n hasExternalFile(): boolean {\n return !!this.filePath;\n }\n\n /**\n * Read file content (if stored externally)\n */\n async readContent(): Promise<Buffer | null> {\n if (!this.filePath) return null;\n\n try {\n const { getFilesystem } = await import('@happyvertical/files');\n const files = await getFilesystem({ type: 'local' });\n const data = await files.read(this.filePath);\n return data instanceof Buffer ? data : Buffer.from(data);\n } catch {\n return null;\n }\n }\n}\n","/**\n * AttachmentCollection - Generalized attachment collection using messageId\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { Attachment } from '../models/Attachment';\n\nexport class AttachmentCollection extends SmrtCollection<Attachment> {\n static readonly _itemClass = Attachment;\n\n /**\n * Get attachments for a message\n */\n async getByMessage(messageId: string): Promise<Attachment[]> {\n return await this.list({ where: { messageId } });\n }\n\n /**\n * Get attachments by content type\n */\n async getByContentType(contentType: string): Promise<Attachment[]> {\n return await this.list({ where: { contentType } });\n }\n\n /**\n * Get image attachments\n */\n async getImages(messageId?: string): Promise<Attachment[]> {\n const attachments = messageId\n ? await this.getByMessage(messageId)\n : await this.list({});\n\n return attachments.filter((a) => a.isImage());\n }\n\n /**\n * Get PDF attachments\n */\n async getPdfs(messageId?: string): Promise<Attachment[]> {\n const attachments = messageId\n ? await this.getByMessage(messageId)\n : await this.list({});\n\n return attachments.filter((a) => a.isPdf());\n }\n\n /**\n * Get inline attachments (embedded in message body)\n */\n async getInline(messageId: string): Promise<Attachment[]> {\n const attachments = await this.getByMessage(messageId);\n return attachments.filter((a) => a.isInline());\n }\n\n /**\n * Get regular attachments (not inline)\n */\n async getRegular(messageId: string): Promise<Attachment[]> {\n const attachments = await this.getByMessage(messageId);\n return attachments.filter((a) => !a.isInline());\n }\n\n /**\n * Get attachments with external files\n */\n async getWithExternalFiles(): Promise<Attachment[]> {\n const attachments = await this.list({});\n return attachments.filter((a) => a.hasExternalFile());\n }\n\n /**\n * Get total size of attachments for a message\n */\n async getTotalSize(messageId: string): Promise<number> {\n const attachments = await this.getByMessage(messageId);\n return attachments.reduce((sum, a) => sum + a.size, 0);\n }\n\n /**\n * Get largest attachments\n */\n async getLargest(limit = 10): Promise<Attachment[]> {\n const attachments = await this.list({});\n return attachments.sort((a, b) => b.size - a.size).slice(0, limit);\n }\n\n /**\n * Search attachments by filename\n */\n async searchByFilename(query: string): Promise<Attachment[]> {\n const attachments = await this.list({});\n const lowerQuery = query.toLowerCase();\n\n return attachments.filter((a) =>\n a.filename?.toLowerCase().includes(lowerQuery),\n );\n }\n\n /**\n * Get attachments by extension\n */\n async getByExtension(extension: string): Promise<Attachment[]> {\n const attachments = await this.list({});\n const lowerExt = extension.toLowerCase().replace(/^\\./, '');\n\n return attachments.filter((a) => a.getExtension() === lowerExt);\n }\n\n /**\n * Get attachment statistics\n */\n async getStats(): Promise<{\n total: number;\n totalSize: number;\n byType: Record<string, number>;\n inline: number;\n regular: number;\n }> {\n const attachments = await this.list({});\n\n const byType: Record<string, number> = {};\n for (const attachment of attachments) {\n const type = attachment.contentType.split('/')[0] || 'other';\n byType[type] = (byType[type] || 0) + 1;\n }\n\n return {\n total: attachments.length,\n totalSize: attachments.reduce((sum, a) => sum + a.size, 0),\n byType,\n inline: attachments.filter((a) => a.isInline()).length,\n regular: attachments.filter((a) => !a.isInline()).length,\n };\n }\n\n /**\n * Delete all attachments for a message\n */\n async deleteByMessage(messageId: string): Promise<number> {\n const attachments = await this.getByMessage(messageId);\n let count = 0;\n\n for (const attachment of attachments) {\n await attachment.delete();\n count++;\n }\n\n return count;\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Tenant Helper Methods\n // ─────────────────────────────────────────────────────────────────────────\n\n async findByTenant(tenantId: string): Promise<Attachment[]> {\n return this.list({ where: { tenantId } });\n }\n\n async findGlobal(): Promise<Attachment[]> {\n return this.list({ where: { tenantId: null } });\n }\n\n async findWithGlobals(tenantId: string): Promise<Attachment[]> {\n return this.query(\n `SELECT * FROM ${this.tableName} WHERE tenant_id = ? OR tenant_id IS NULL`,\n [tenantId],\n );\n }\n}\n","/**\n * Message model - Base class for all message types (STI)\n *\n * Common fields shared across email, tweets, slack messages, etc.\n */\n\nimport { foreignKey, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type {\n MessageOptions,\n MessageSendResult,\n SendMessageOptions,\n SendStatus,\n} from '../types';\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class Message extends SmrtObject {\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n @foreignKey('Account')\n accountId = '';\n threadId = '';\n subject = '';\n body = ''; // Normalized plain text\n fromAddress = '';\n fromName = '';\n toAddresses = ''; // JSON array of {address, name}\n date: Date | null = null;\n isRead = false;\n isFlagged = false;\n hasAttachments = false;\n size = 0;\n metadata = ''; // JSON extension bag\n\n // Send lifecycle fields\n sendStatus: SendStatus = 'draft';\n sentAt: Date | null = null;\n sendError = '';\n retryCount = 0;\n maxRetries = 3;\n scheduledSendAt: Date | null = null;\n @foreignKey('Message')\n inReplyToMessageId = '';\n\n // Timestamps\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: MessageOptions = {}) {\n super(options);\n\n if (options.tenantId !== undefined) this.tenantId = options.tenantId as any;\n if (options.accountId !== undefined) this.accountId = options.accountId;\n if (options.threadId !== undefined) this.threadId = options.threadId;\n if (options.subject !== undefined) this.subject = options.subject;\n if (options.body !== undefined) this.body = options.body;\n if (options.fromAddress !== undefined)\n this.fromAddress = options.fromAddress;\n if (options.fromName !== undefined) this.fromName = options.fromName;\n if (options.toAddresses !== undefined)\n this.toAddresses = options.toAddresses;\n if (options.date !== undefined) this.date = options.date || null;\n if (options.isRead !== undefined) this.isRead = options.isRead;\n if (options.isFlagged !== undefined) this.isFlagged = options.isFlagged;\n if (options.hasAttachments !== undefined)\n this.hasAttachments = options.hasAttachments;\n if (options.size !== undefined) this.size = options.size;\n if (options.metadata !== undefined) this.metadata = options.metadata;\n if (options.sendStatus !== undefined) this.sendStatus = options.sendStatus;\n if (options.sentAt !== undefined) this.sentAt = options.sentAt || null;\n if (options.sendError !== undefined) this.sendError = options.sendError;\n if (options.retryCount !== undefined) this.retryCount = options.retryCount;\n if (options.maxRetries !== undefined) this.maxRetries = options.maxRetries;\n if (options.scheduledSendAt !== undefined)\n this.scheduledSendAt = options.scheduledSendAt || null;\n if (options.inReplyToMessageId !== undefined)\n this.inReplyToMessageId = options.inReplyToMessageId;\n if (options.createdAt) this.createdAt = options.createdAt;\n if (options.updatedAt) this.updatedAt = options.updatedAt;\n }\n\n /**\n * Get to addresses as parsed array\n */\n getToAddresses(): Array<{ address: string; name?: string }> {\n if (!this.toAddresses) return [];\n try {\n return JSON.parse(this.toAddresses);\n } catch {\n return [];\n }\n }\n\n /**\n * Set to addresses from array\n */\n setToAddresses(addresses: Array<{ address: string; name?: string }>): void {\n this.toAddresses = JSON.stringify(addresses);\n }\n\n /**\n * Get metadata as parsed object\n */\n getMetadata(): Record<string, any> {\n if (!this.metadata) return {};\n try {\n return JSON.parse(this.metadata);\n } catch {\n return {};\n }\n }\n\n /**\n * Set metadata from object\n */\n setMetadata(data: Record<string, any>): void {\n this.metadata = JSON.stringify(data);\n }\n\n /**\n * Mark message as read\n */\n async markRead(): Promise<void> {\n this.isRead = true;\n this.updatedAt = new Date();\n await this.save();\n }\n\n /**\n * Mark message as unread\n */\n async markUnread(): Promise<void> {\n this.isRead = false;\n this.updatedAt = new Date();\n await this.save();\n }\n\n /**\n * Toggle flagged status\n */\n async toggleFlagged(): Promise<void> {\n this.isFlagged = !this.isFlagged;\n this.updatedAt = new Date();\n await this.save();\n }\n\n /**\n * Check if message is unread\n */\n isUnread(): boolean {\n return !this.isRead;\n }\n\n /**\n * Get a short preview of the message body\n */\n getPreview(maxLength = 200): string {\n const text = this.body || '';\n if (text.length <= maxLength) return text;\n return `${text.slice(0, maxLength)}...`;\n }\n\n /**\n * Get the account for this message\n */\n async getAccount() {\n if (!this.accountId) return null;\n\n const { AccountCollection } = await import(\n '../collections/AccountCollection'\n );\n const collection = await (AccountCollection as any).create(this.options);\n\n return await collection.get({ id: this.accountId });\n }\n\n /**\n * Get messages in the same thread\n */\n async getThreadMessages(): Promise<Message[]> {\n if (!this.threadId) return [this];\n\n const { MessageCollection } = await import(\n '../collections/MessageCollection'\n );\n const collection = await (MessageCollection as any).create(this.options);\n\n return await collection.list({ where: { threadId: this.threadId } });\n }\n\n /**\n * Get attachments for this message\n */\n async getAttachments() {\n const { AttachmentCollection } = await import(\n '../collections/AttachmentCollection'\n );\n const collection = await (AttachmentCollection as any).create(this.options);\n\n return await collection.list({ where: { messageId: this.id } });\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Send Lifecycle\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * Send this message via its account's sender\n */\n async send(options?: SendMessageOptions): Promise<MessageSendResult> {\n // Entry guard: a message that is already in flight or delivered must not be\n // sent again. Catches same-instance double-clicks before any work happens.\n if (this.sendStatus === 'sending' || this.sendStatus === 'sent') {\n return {\n success: false,\n error: `Cannot send: message is already '${this.sendStatus}'`,\n sentAt: new Date(),\n };\n }\n\n // Resolve account\n const account = await this.getAccount();\n if (!account) {\n const result: MessageSendResult = {\n success: false,\n error: 'No account associated with this message',\n sentAt: new Date(),\n };\n this.sendStatus = 'failed';\n this.sendError = result.error ?? '';\n this.updatedAt = new Date();\n await this.save();\n return result;\n }\n\n // Get sender from account\n const sender = await (account as any).createSender();\n\n // Claim the send. For a persisted row, do a compare-and-set so only one\n // concurrent sender wins: flip send_status to 'sending' atomically, gated on\n // the status we observed. If no row matched, another sender already claimed\n // it — abort without delivering (prevents duplicate sends). For an unsaved\n // draft there is no row yet, so the in-memory transition + save() (INSERT)\n // serves as the claim.\n const claimFromStatus = this.sendStatus;\n if (this.isPersisted && this.id) {\n const claim = await this.db.update(\n this.tableName,\n { id: this.id, send_status: claimFromStatus },\n { send_status: 'sending', updated_at: new Date() },\n );\n if (!claim || claim.affected < 1) {\n return {\n success: false,\n error: 'Cannot send: message is already being sent',\n sentAt: new Date(),\n };\n }\n this.sendStatus = 'sending';\n this.updatedAt = new Date();\n } else {\n this.sendStatus = 'sending';\n this.updatedAt = new Date();\n await this.save();\n }\n\n try {\n const result = await sender.send(this, options);\n\n if (result.success) {\n this.sendStatus = 'sent';\n this.sentAt = result.sentAt;\n this.sendError = '';\n } else {\n this.sendStatus = 'failed';\n this.sendError = result.error ?? 'Send failed';\n }\n\n this.updatedAt = new Date();\n await this.save();\n return result;\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n this.sendStatus = 'failed';\n this.sendError = errorMessage;\n this.updatedAt = new Date();\n await this.save();\n\n return {\n success: false,\n error: errorMessage,\n sentAt: new Date(),\n };\n }\n }\n\n /**\n * Retry sending a failed message\n */\n async retrySend(options?: SendMessageOptions): Promise<MessageSendResult> {\n if (this.sendStatus !== 'failed') {\n return {\n success: false,\n error: `Cannot retry: message status is '${this.sendStatus}', expected 'failed'`,\n sentAt: new Date(),\n };\n }\n\n if (this.retryCount >= this.maxRetries) {\n return {\n success: false,\n error: `Retry budget exhausted (${this.retryCount}/${this.maxRetries})`,\n sentAt: new Date(),\n };\n }\n\n this.retryCount++;\n this.updatedAt = new Date();\n await this.save();\n\n return this.send(options);\n }\n\n /**\n * Options for a derived draft (reply/forward) built from this message. Carries\n * the DB connection + tenant context from `this.options`, but strips this\n * message's own identity fields. When this message was hydrated from the DB,\n * `this.options` holds the row's `id`/`slug`/`context`/`_skipLoad`; spreading\n * those into a new draft would make `draft.save()` upsert onto the natural-key\n * conflict columns (`slug`/`context`/`_meta_type`) and overwrite the ORIGINAL\n * message instead of inserting a new row. See EmailAccount.childOptions().\n */\n protected draftOptions(): Record<string, unknown> {\n const rest = { ...(this.options as Record<string, unknown>) };\n delete rest.id;\n delete rest.slug;\n delete rest.context;\n delete rest._skipLoad;\n return rest;\n }\n\n /**\n * Create a reply to this message (returns unsaved draft)\n */\n createReply(_options?: { replyAll?: boolean }): Message {\n const reply = new (this.constructor as typeof Message)({\n ...this.draftOptions(),\n id: undefined,\n accountId: this.accountId,\n threadId: this.threadId || this.id || '',\n subject: this.subject.startsWith('Re:')\n ? this.subject\n : `Re: ${this.subject}`,\n toAddresses: JSON.stringify([\n { address: this.fromAddress, name: this.fromName },\n ]),\n fromAddress: '',\n fromName: '',\n body: this.buildQuotedBody(),\n inReplyToMessageId: this.id || '',\n sendStatus: 'draft',\n isRead: true,\n date: null,\n createdAt: undefined,\n updatedAt: undefined,\n });\n\n return reply;\n }\n\n /**\n * Create a forward of this message (returns unsaved draft)\n */\n createForward(): Message {\n const forward = new (this.constructor as typeof Message)({\n ...this.draftOptions(),\n id: undefined,\n accountId: this.accountId,\n threadId: '',\n subject: this.subject.startsWith('Fwd:')\n ? this.subject\n : `Fwd: ${this.subject}`,\n toAddresses: '[]',\n fromAddress: '',\n fromName: '',\n body: this.buildQuotedBody(),\n hasAttachments: this.hasAttachments,\n inReplyToMessageId: '',\n sendStatus: 'draft',\n isRead: true,\n date: null,\n createdAt: undefined,\n updatedAt: undefined,\n });\n\n return forward;\n }\n\n /**\n * Build quoted body for reply/forward\n */\n protected buildQuotedBody(): string {\n const dateStr = this.date ? this.date.toLocaleString() : 'unknown date';\n const from = this.fromName\n ? `${this.fromName} <${this.fromAddress}>`\n : this.fromAddress;\n\n const quotedLines = (this.body || '')\n .split('\\n')\n .map((line) => `> ${line}`)\n .join('\\n');\n\n return `\\n\\nOn ${dateStr}, ${from} wrote:\\n${quotedLines}`;\n }\n}\n","/**\n * MessageCollection - Unified collection for polymorphic message queries\n *\n * Queries the messages table with STI, returning correct subclass instances.\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { Message } from '../models/Message';\nimport type { MessageSearchFilters } from '../types';\n\nexport class MessageCollection extends SmrtCollection<Message> {\n static readonly _itemClass = Message;\n\n /**\n * Search messages with filters\n */\n async search(\n query: string,\n filters?: MessageSearchFilters,\n ): Promise<Message[]> {\n let messages = await this.list({});\n\n // Filter by query\n if (query) {\n const lowerQuery = query.toLowerCase();\n messages = messages.filter(\n (m) =>\n m.subject?.toLowerCase().includes(lowerQuery) ||\n m.body?.toLowerCase().includes(lowerQuery) ||\n m.fromAddress?.toLowerCase().includes(lowerQuery) ||\n m.fromName?.toLowerCase().includes(lowerQuery),\n );\n }\n\n // Apply filters\n if (filters) {\n if (filters.accountIds && filters.accountIds.length > 0) {\n messages = messages.filter((m) =>\n filters.accountIds?.includes(m.accountId),\n );\n }\n if (filters.messageType) {\n messages = messages.filter((m) => {\n const metaType = (m as any)._meta_type || '';\n return metaType.includes(filters.messageType as string);\n });\n }\n if (filters.from) {\n const fromLower = filters.from.toLowerCase();\n messages = messages.filter(\n (m) =>\n m.fromAddress?.toLowerCase().includes(fromLower) ||\n m.fromName?.toLowerCase().includes(fromLower),\n );\n }\n if (filters.to) {\n const toLower = filters.to.toLowerCase();\n messages = messages.filter((m) =>\n m.toAddresses?.toLowerCase().includes(toLower),\n );\n }\n if (filters.isRead !== undefined) {\n messages = messages.filter((m) => m.isRead === filters.isRead);\n }\n if (filters.isFlagged !== undefined) {\n messages = messages.filter((m) => m.isFlagged === filters.isFlagged);\n }\n if (filters.sinceDate) {\n messages = messages.filter(\n (m) => m.date && m.date >= (filters.sinceDate as Date),\n );\n }\n if (filters.beforeDate) {\n messages = messages.filter(\n (m) => m.date && m.date < (filters.beforeDate as Date),\n );\n }\n if (filters.query) {\n const q = filters.query.toLowerCase();\n messages = messages.filter(\n (m) =>\n m.subject?.toLowerCase().includes(q) ||\n m.body?.toLowerCase().includes(q),\n );\n }\n }\n\n return messages;\n }\n\n /**\n * Get messages by multiple accounts\n */\n async getByAccounts(accountIds: string[]): Promise<Message[]> {\n const allMessages = await this.list({});\n return allMessages.filter((m) => accountIds.includes(m.accountId));\n }\n\n /**\n * Get messages by STI type.\n *\n * Accepts either the full discriminator (e.g. \"@happyvertical/smrt-messages:Email\")\n * or the short type name (e.g. \"Email\").\n */\n async getByType(messageType: string): Promise<Message[]> {\n if (messageType.includes(':') || messageType.startsWith('@')) {\n return await this.list({ where: { _meta_type: messageType } });\n }\n const allMessages = await this.list({});\n return allMessages.filter((m) => {\n const metaType = (m as any)._meta_type || '';\n return metaType.endsWith(`:${messageType}`);\n });\n }\n\n /**\n * Get unread messages\n */\n async getUnread(accountId?: string): Promise<Message[]> {\n const where: Record<string, any> = { isRead: false };\n if (accountId) {\n where.accountId = accountId;\n }\n return await this.list({ where });\n }\n\n /**\n * Get flagged messages\n */\n async getFlagged(accountId?: string): Promise<Message[]> {\n const where: Record<string, any> = { isFlagged: true };\n if (accountId) {\n where.accountId = accountId;\n }\n return await this.list({ where });\n }\n\n /**\n * Get recent messages\n */\n async getRecent(limit = 20, accountId?: string): Promise<Message[]> {\n const allMessages = await this.list({\n where: accountId ? { accountId } : undefined,\n });\n\n return allMessages\n .sort((a, b) => {\n const dateA = a.date?.getTime() || 0;\n const dateB = b.date?.getTime() || 0;\n return dateB - dateA;\n })\n .slice(0, limit);\n }\n\n /**\n * Get messages by thread\n */\n async getByThread(threadId: string): Promise<Message[]> {\n return await this.list({ where: { threadId } });\n }\n\n /**\n * Mark multiple messages as read\n */\n async markAllRead(messageIds: string[]): Promise<void> {\n for (const id of messageIds) {\n const message = await this.get({ id });\n if (message) {\n await message.markRead();\n }\n }\n }\n\n /**\n * Get message statistics for an account\n */\n async getAccountStats(accountId: string): Promise<{\n total: number;\n unread: number;\n flagged: number;\n byType: Record<string, number>;\n }> {\n const messages = await this.list({ where: { accountId } });\n const byType: Record<string, number> = {};\n\n for (const msg of messages) {\n const metaType = (msg as any)._meta_type || 'Unknown';\n const shortType = metaType.split(':').pop() || metaType;\n byType[shortType] = (byType[shortType] || 0) + 1;\n }\n\n return {\n total: messages.length,\n unread: messages.filter((m) => !m.isRead).length,\n flagged: messages.filter((m) => m.isFlagged).length,\n byType,\n };\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Send / Draft Queries\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * Get draft messages\n */\n async getDrafts(accountId?: string): Promise<Message[]> {\n const where: Record<string, any> = { sendStatus: 'draft' };\n if (accountId) where.accountId = accountId;\n return await this.list({ where });\n }\n\n /**\n * Get sent messages\n */\n async getSent(accountId?: string): Promise<Message[]> {\n const where: Record<string, any> = { sendStatus: 'sent' };\n if (accountId) where.accountId = accountId;\n return await this.list({ where });\n }\n\n /**\n * Get scheduled messages\n */\n async getScheduled(accountId?: string): Promise<Message[]> {\n const where: Record<string, any> = { sendStatus: 'scheduled' };\n if (accountId) where.accountId = accountId;\n return await this.list({ where });\n }\n\n /**\n * Get messages that failed to send\n */\n async getFailedSends(accountId?: string): Promise<Message[]> {\n const where: Record<string, any> = { sendStatus: 'failed' };\n if (accountId) where.accountId = accountId;\n return await this.list({ where });\n }\n\n /**\n * Get outbox (pending + sending + scheduled)\n */\n async getOutbox(accountId?: string): Promise<Message[]> {\n const allMessages = await this.list({\n where: accountId ? { accountId } : undefined,\n });\n return allMessages.filter(\n (m) =>\n m.sendStatus === 'pending' ||\n m.sendStatus === 'sending' ||\n m.sendStatus === 'scheduled',\n );\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Tenant Helper Methods\n // ─────────────────────────────────────────────────────────────────────────\n\n async findByTenant(tenantId: string): Promise<Message[]> {\n return this.list({ where: { tenantId } });\n }\n\n async findGlobal(): Promise<Message[]> {\n return this.list({ where: { tenantId: null } });\n }\n\n async findWithGlobals(tenantId: string): Promise<Message[]> {\n return this.query(\n `SELECT * FROM ${this.tableName} WHERE tenant_id = ? OR tenant_id IS NULL`,\n [tenantId],\n );\n }\n}\n","/**\n * EmailAccount model - Email account extending the Account STI base\n *\n * Retains email-specific fields and sync capability.\n */\n\nimport { smrt } from '@happyvertical/smrt-core';\nimport type {\n EmailAccountOptions,\n MessageSenderInterface,\n ProviderType,\n SyncOptions,\n SyncResult,\n} from '../types';\nimport { Account } from './Account';\n\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class EmailAccount extends Account {\n email = '';\n syncIntervalMinutes = 60;\n\n constructor(options: EmailAccountOptions = {}) {\n super(options);\n\n if (options.email !== undefined) this.email = options.email;\n if (options.providerType !== undefined)\n this.providerType = options.providerType;\n if (options.syncIntervalMinutes !== undefined)\n this.syncIntervalMinutes = options.syncIntervalMinutes;\n }\n\n /**\n * Options for child rows (folders/emails) created during sync: carries the DB\n * connection + tenant context from this account, but strips this account's own\n * identity fields. When this account was hydrated from the DB, `this.options`\n * holds the account row's `id`/`slug`/`_skipLoad`; spreading those into a new\n * child would make every synced row inherit the account's primary key and\n * upsert over each other.\n */\n private childOptions(): Record<string, unknown> {\n const rest = { ...(this.options as Record<string, unknown>) };\n delete rest.id;\n delete rest.slug;\n delete rest._skipLoad;\n return rest;\n }\n\n /**\n * Create a sender for this email account\n */\n override async createSender(): Promise<MessageSenderInterface> {\n const client = await this.createClient();\n await client.connect();\n const { EmailSender } = await import('../senders/EmailSender');\n return new EmailSender(client, this);\n }\n\n /**\n * Create an EmailClient from stored settings\n * Retrieves credentials from smrt-secrets if credentialSecretId is set\n */\n async createClient() {\n const { getEmailClient } = await import('@happyvertical/email');\n let settings: Record<string, any>;\n\n // Use secrets integration if available\n if (this.credentialSecretId) {\n const { SecretService } = await import('@happyvertical/smrt-secrets');\n const secretService = await SecretService.create({ db: this.db });\n\n const secret = await secretService.retrieve(this.credentialSecretId);\n settings = JSON.parse(secret.value);\n } else {\n // Fallback to plain-text settings (DEPRECATED)\n settings = this.getSettings();\n }\n\n return await getEmailClient({\n type: this.providerType as ProviderType,\n ...settings,\n } as any);\n }\n\n /**\n * Sync emails from the email server to the database\n */\n async syncFrom(options: SyncOptions = {}): Promise<SyncResult> {\n const startTime = Date.now();\n const result: SyncResult = {\n folders: [],\n messagesProcessed: 0,\n messagesDownloaded: 0,\n messagesSkipped: 0,\n errors: [],\n duration: 0,\n };\n\n try {\n // Create email client\n const client = await this.createClient();\n await client.connect();\n\n // Get folders to sync\n const foldersToSync = options.folders || ['INBOX'];\n result.folders = foldersToSync;\n\n // Import collections\n const { EmailCollection } = await import(\n '../collections/EmailCollection'\n );\n const { EmailFolderCollection } = await import(\n '../collections/EmailFolderCollection'\n );\n\n const emailCollection = await (EmailCollection as any).create(\n this.options,\n );\n const folderCollection = await (EmailFolderCollection as any).create(\n this.options,\n );\n\n for (const folderName of foldersToSync) {\n try {\n // Ensure folder exists in database\n const accountId = this.id ?? '';\n let folder = await folderCollection.getByPath(accountId, folderName);\n\n if (!folder) {\n // Create folder record\n const { EmailFolder } = await import('./EmailFolder');\n folder = new EmailFolder({\n ...this.childOptions(),\n accountId,\n name: folderName,\n path: folderName,\n });\n // initialize() binds the DB connection; without it save() throws\n // \"Database accessed before initialization\" and sync persists nothing.\n await folder.initialize();\n await folder.save();\n }\n\n // Fetch messages from server\n const fetchOptions: Record<string, any> = {\n folder: folderName,\n limit: options.batchSize || 100,\n };\n\n if (options.since) {\n fetchOptions.since = options.since;\n }\n if (options.before) {\n fetchOptions.before = options.before;\n }\n\n const messages = await client.fetch(fetchOptions);\n\n for (const msg of messages) {\n result.messagesProcessed++;\n\n try {\n // Check if message already exists\n const existingEmail = await emailCollection.getByMessageId(\n this.id,\n msg.messageId || '',\n );\n\n if (existingEmail && !options.fullSync) {\n result.messagesSkipped++;\n continue;\n }\n\n // Create or update email record\n const { Email } = await import('./Email');\n let email = existingEmail;\n if (!email) {\n email = new Email({\n ...this.childOptions(),\n accountId,\n });\n // Bind the DB connection before save() (existingEmail is already\n // initialized via the query that loaded it).\n await email.initialize();\n }\n\n // Update fields\n email.messageId = msg.messageId || '';\n email.threadId = msg.threadId || '';\n email.inReplyTo = msg.inReplyTo || '';\n email.fromAddress = msg.from?.address || '';\n email.fromName = msg.from?.name || '';\n email.toAddresses = JSON.stringify(msg.to || []);\n email.ccAddresses = JSON.stringify(msg.cc || []);\n email.bccAddresses = JSON.stringify(msg.bcc || []);\n email.replyToAddress = msg.replyTo?.address || '';\n email.replyToName = msg.replyTo?.name || '';\n email.subject = msg.subject || '';\n email.date = msg.date || null;\n email.textBody = msg.text || '';\n email.htmlBody = msg.html || '';\n email.body = msg.text || '';\n email.folderId = folder.id;\n email.folderPath = folderName;\n email.labels = JSON.stringify(msg.labels || []);\n email.flags = JSON.stringify(msg.flags || []);\n email.hasAttachments =\n (msg.attachments && msg.attachments.length > 0) || false;\n email.size = msg.size || 0;\n email.headers = JSON.stringify(msg.headers || {});\n email.updatedAt = new Date();\n\n await email.save();\n result.messagesDownloaded++;\n\n // Report progress\n if (options.onProgress) {\n options.onProgress({\n folder: folderName,\n processed: result.messagesProcessed,\n total: messages.length,\n downloaded: result.messagesDownloaded,\n skipped: result.messagesSkipped,\n errors: result.errors.length,\n });\n }\n } catch (error) {\n const err =\n error instanceof Error ? error : new Error(String(error));\n result.errors.push(err);\n if (options.onError) {\n options.onError(err, msg);\n }\n }\n }\n\n // Update folder counts\n folder.messageCount = await emailCollection.countByFolder(folder.id);\n folder.unreadCount = await emailCollection.countUnreadByFolder(\n folder.id,\n );\n await folder.save();\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n result.errors.push(err);\n if (options.onError) {\n options.onError(err);\n }\n }\n }\n\n // Update last sync time\n this.lastSyncAt = new Date();\n this.updatedAt = new Date();\n await this.save();\n\n await client.disconnect();\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n result.errors.push(err);\n if (options.onError) {\n options.onError(err);\n }\n }\n\n result.duration = Date.now() - startTime;\n return result;\n }\n\n /**\n * Get all folders for this account\n */\n async getFolders() {\n const { EmailFolderCollection } = await import(\n '../collections/EmailFolderCollection'\n );\n const collection = await (EmailFolderCollection as any).create(\n this.options,\n );\n\n return await collection.list({ where: { accountId: this.id } });\n }\n\n /**\n * Get all emails for this account\n */\n async getEmails(limit?: number) {\n const { EmailCollection } = await import('../collections/EmailCollection');\n const collection = await (EmailCollection as any).create(this.options);\n\n const options: Record<string, any> = { where: { accountId: this.id } };\n if (limit) {\n options.limit = limit;\n }\n\n return await collection.list(options);\n }\n\n /**\n * Get unread email count\n */\n async getUnreadCount(): Promise<number> {\n const { EmailCollection } = await import('../collections/EmailCollection');\n const collection = await (EmailCollection as any).create(this.options);\n\n return await collection.countUnreadByAccount(this.id);\n }\n\n /**\n * Store credentials securely using smrt-secrets (email-specific)\n */\n override async setCredentials(\n credentials: Record<string, any>,\n options: {\n description?: string;\n category?: string;\n } = {},\n ): Promise<void> {\n const { SecretService } = await import('@happyvertical/smrt-secrets');\n const secretService = await SecretService.create({ db: this.db });\n\n const secretName = `email-account-${this.id}`;\n const secretValue = JSON.stringify(credentials);\n\n if (this.credentialSecretId) {\n await secretService.store(this.credentialSecretId, secretValue, {\n description: options.description || `IMAP credentials for ${this.name}`,\n category: options.category || 'email',\n });\n } else {\n await secretService.store(secretName, secretValue, {\n description: options.description || `IMAP credentials for ${this.name}`,\n category: options.category || 'email',\n });\n\n this.credentialSecretId = secretName;\n this.updatedAt = new Date();\n await this.save();\n }\n }\n\n /**\n * Sync all active email accounts (for job runner)\n *\n * NOTE: This is a class-wide operation, not per-instance. It syncs ALL active\n * accounts, ignoring `this` instance. It exists as an instance method because\n * the TaskRunner dispatches via `objectType: 'EmailAccount', method: 'syncAll'`\n * which requires an instance method signature.\n */\n async syncAll(\n args?: Record<string, unknown>,\n ): Promise<Map<string, { success: boolean; error?: Error }>> {\n const { EmailAccountCollection } = await import(\n '../collections/EmailAccountCollection'\n );\n const collection = await (EmailAccountCollection as any).create({\n db: this.db,\n });\n return collection.syncAll(args);\n }\n\n /**\n * Migrate from plain-text settings to secrets\n */\n async migrateToSecrets(): Promise<void> {\n if (this.credentialSecretId) {\n return;\n }\n\n const settings = this.getSettings();\n if (Object.keys(settings).length === 0) {\n return;\n }\n\n await this.setCredentials(settings, {\n description: `Migrated IMAP credentials for ${this.name}`,\n });\n }\n}\n","/**\n * EmailAccountCollection - Collection manager for EmailAccount objects\n *\n * Extends AccountCollection with email-specific query methods.\n */\n\nimport { EmailAccount } from '../models/EmailAccount';\nimport type { EmailAccountSearchFilters, ProviderType } from '../types';\nimport { AccountCollection } from './AccountCollection';\n\nexport class EmailAccountCollection extends AccountCollection {\n static override readonly _itemClass = EmailAccount;\n\n /**\n * Get account by email address\n */\n async getByEmail(email: string): Promise<EmailAccount | null> {\n const accounts = await this.list({ where: { email } });\n return (accounts[0] as EmailAccount) || null;\n }\n\n /**\n * Get accounts by email provider type\n */\n async getByEmailProviderType(\n providerType: ProviderType,\n ): Promise<EmailAccount[]> {\n return (await this.list({ where: { providerType } })) as EmailAccount[];\n }\n\n /**\n * Get active email accounts\n */\n override async getActive(): Promise<EmailAccount[]> {\n return (await this.list({ where: { isActive: true } })) as EmailAccount[];\n }\n\n /**\n * Get inactive email accounts\n */\n override async getInactive(): Promise<EmailAccount[]> {\n return (await this.list({ where: { isActive: false } })) as EmailAccount[];\n }\n\n /**\n * Get accounts that need syncing\n */\n async getNeedingSync(maxAgeMinutes = 60): Promise<EmailAccount[]> {\n const allAccounts = await this.getActive();\n const cutoffTime = new Date(Date.now() - maxAgeMinutes * 60 * 1000);\n\n return allAccounts.filter(\n (account) => !account.lastSyncAt || account.lastSyncAt < cutoffTime,\n ) as EmailAccount[];\n }\n\n /**\n * Search email accounts with filters.\n * Alias: `search()` for backward compatibility.\n */\n override async search(\n query: string,\n filters?: EmailAccountSearchFilters,\n ): Promise<EmailAccount[]> {\n return this.searchEmailAccounts(query, filters);\n }\n\n /**\n * Get accounts by email provider type.\n * Alias: `getByProviderType()` for backward compatibility.\n */\n override async getByProviderType(\n providerType: string,\n ): Promise<EmailAccount[]> {\n return this.getByEmailProviderType(providerType as ProviderType);\n }\n\n /**\n * Get email account statistics.\n * Alias: `getStats()` for backward compatibility.\n */\n override async getStats(): Promise<{\n total: number;\n active: number;\n inactive: number;\n byType: Record<string, number>;\n }> {\n const stats = await this.getEmailStats();\n return {\n total: stats.total,\n active: stats.active,\n inactive: stats.inactive,\n byType: stats.byProvider as unknown as Record<string, number>,\n };\n }\n\n /**\n * Search email accounts with filters\n */\n async searchEmailAccounts(\n query: string,\n filters?: EmailAccountSearchFilters,\n ): Promise<EmailAccount[]> {\n let accounts = (await this.list({})) as EmailAccount[];\n\n // Filter by query\n if (query) {\n const lowerQuery = query.toLowerCase();\n accounts = accounts.filter(\n (a) =>\n a.name?.toLowerCase().includes(lowerQuery) ||\n a.email?.toLowerCase().includes(lowerQuery),\n );\n }\n\n // Apply filters\n if (filters) {\n if (filters.providerType) {\n accounts = accounts.filter(\n (a) => a.providerType === filters.providerType,\n );\n }\n if (filters.email) {\n const emailLower = filters.email.toLowerCase();\n accounts = accounts.filter((a) =>\n a.email?.toLowerCase().includes(emailLower),\n );\n }\n if (filters.isActive !== undefined) {\n accounts = accounts.filter((a) => a.isActive === filters.isActive);\n }\n }\n\n return accounts;\n }\n\n /**\n * Sync all active email accounts\n */\n async syncAll(\n options?: Record<string, any>,\n ): Promise<Map<string, { success: boolean; error?: Error }>> {\n const results = new Map<string, { success: boolean; error?: Error }>();\n const accounts = await this.getActive();\n\n for (const account of accounts) {\n const ea = account as EmailAccount;\n const accountId = ea.id ?? ea.email ?? 'unknown';\n try {\n await ea.syncFrom(options);\n results.set(accountId, { success: true });\n } catch (error) {\n results.set(accountId, {\n success: false,\n error: error instanceof Error ? error : new Error(String(error)),\n });\n }\n }\n\n return results;\n }\n\n /**\n * Get total unread count across all email accounts\n */\n async getTotalUnreadCount(): Promise<number> {\n const accounts = await this.getActive();\n let total = 0;\n\n for (const account of accounts) {\n total += await (account as EmailAccount).getUnreadCount();\n }\n\n return total;\n }\n\n /**\n * Get email account statistics\n */\n async getEmailStats(): Promise<{\n total: number;\n active: number;\n inactive: number;\n byProvider: Record<ProviderType, number>;\n }> {\n const accounts = (await this.list({})) as EmailAccount[];\n\n const byProvider: Record<ProviderType, number> = {\n smtp: 0,\n imap: 0,\n pop3: 0,\n gmail: 0,\n };\n\n for (const account of accounts) {\n const pt = account.providerType as ProviderType;\n if (pt in byProvider) {\n byProvider[pt]++;\n }\n }\n\n return {\n total: accounts.length,\n active: accounts.filter((a) => a.isActive).length,\n inactive: accounts.filter((a) => !a.isActive).length,\n byProvider,\n };\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Tenant Helper Methods\n // ─────────────────────────────────────────────────────────────────────────\n\n override async findByTenant(tenantId: string): Promise<EmailAccount[]> {\n return this.list({ where: { tenantId } }) as Promise<EmailAccount[]>;\n }\n\n override async findGlobal(): Promise<EmailAccount[]> {\n return this.list({ where: { tenantId: null } }) as Promise<EmailAccount[]>;\n }\n\n override async findWithGlobals(tenantId: string): Promise<EmailAccount[]> {\n return this.query(\n `SELECT * FROM ${this.tableName} WHERE tenant_id = ? OR tenant_id IS NULL`,\n [tenantId],\n ) as Promise<EmailAccount[]>;\n }\n}\n","/**\n * EmailAttachment - Backward-compatible alias for Attachment\n *\n * @deprecated Use Attachment instead. EmailAttachment is preserved for backward compatibility.\n */\n\nimport type { EmailAttachmentOptions } from '../types';\nimport { Attachment } from './Attachment';\n\n/**\n * @deprecated Use Attachment instead\n */\nexport class EmailAttachment extends Attachment {\n /**\n * Legacy emailId field — maps to messageId\n */\n get emailId(): string {\n return this.messageId;\n }\n\n set emailId(value: string) {\n this.messageId = value;\n }\n\n constructor(options: EmailAttachmentOptions = {}) {\n // Map emailId to messageId for backward compat\n const mappedOptions = {\n ...options,\n messageId: options.emailId || options.messageId || '',\n };\n super(mappedOptions);\n }\n\n /**\n * Get the email this attachment belongs to\n * @deprecated Use getMessage() instead\n */\n async getEmail() {\n if (!this.messageId) return null;\n\n const { EmailCollection } = await import('../collections/EmailCollection');\n const collection = await (EmailCollection as any).create(this.options);\n\n return await collection.get({ id: this.messageId });\n }\n}\n","/**\n * EmailAttachmentCollection - Backward-compatible collection for EmailAttachment\n *\n * @deprecated Use AttachmentCollection instead\n */\n\nimport { EmailAttachment } from '../models/EmailAttachment';\nimport { AttachmentCollection } from './AttachmentCollection';\n\n/**\n * @deprecated Use AttachmentCollection instead\n */\nexport class EmailAttachmentCollection extends AttachmentCollection {\n static override readonly _itemClass = EmailAttachment;\n\n /**\n * Get attachments for an email\n * @deprecated Use getByMessage() instead\n */\n async getByEmail(emailId: string): Promise<EmailAttachment[]> {\n return (await this.getByMessage(emailId)) as EmailAttachment[];\n }\n\n /**\n * Get image attachments\n */\n override async getImages(emailId?: string): Promise<EmailAttachment[]> {\n return (await super.getImages(emailId)) as EmailAttachment[];\n }\n\n /**\n * Get PDF attachments\n */\n override async getPdfs(emailId?: string): Promise<EmailAttachment[]> {\n return (await super.getPdfs(emailId)) as EmailAttachment[];\n }\n\n /**\n * Get inline attachments\n */\n override async getInline(emailId: string): Promise<EmailAttachment[]> {\n return (await super.getInline(emailId)) as EmailAttachment[];\n }\n\n /**\n * Get regular attachments\n */\n override async getRegular(emailId: string): Promise<EmailAttachment[]> {\n return (await super.getRegular(emailId)) as EmailAttachment[];\n }\n\n /**\n * Delete all attachments for an email\n * @deprecated Use deleteByMessage() instead\n */\n async deleteByEmail(emailId: string): Promise<number> {\n return await this.deleteByMessage(emailId);\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Tenant Helper Methods\n // ─────────────────────────────────────────────────────────────────────────\n\n override async findByTenant(tenantId: string): Promise<EmailAttachment[]> {\n return this.list({ where: { tenantId } }) as Promise<EmailAttachment[]>;\n }\n\n override async findGlobal(): Promise<EmailAttachment[]> {\n return this.list({ where: { tenantId: null } }) as Promise<\n EmailAttachment[]\n >;\n }\n\n override async findWithGlobals(tenantId: string): Promise<EmailAttachment[]> {\n return this.query(\n `SELECT * FROM ${this.tableName} WHERE tenant_id = ? OR tenant_id IS NULL`,\n [tenantId],\n ) as Promise<EmailAttachment[]>;\n }\n}\n","/**\n * Email model - Email message extending the Message STI base\n *\n * Retains all email-specific fields (RFC 822 compliance, folders, etc.)\n * while inheriting common message fields from Message.\n */\n\nimport { smrt } from '@happyvertical/smrt-core';\nimport type { EmailOptions } from '../types';\nimport { Message } from './Message';\n\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class Email extends Message {\n // RFC 822 fields\n messageId = ''; // RFC 822 Message-ID header\n inReplyTo = '';\n\n // Additional recipients\n ccAddresses = '';\n bccAddresses = '';\n replyToAddress = '';\n replyToName = '';\n\n // Email-specific content\n textBody = '';\n htmlBody = '';\n\n // Location\n folderId = '';\n folderPath = '';\n labels = ''; // JSON array (Gmail)\n flags = ''; // JSON array (IMAP)\n\n // Email-specific status flags\n isAnswered = false;\n isDraft = false;\n\n // Raw data\n rawMessage = '';\n headers = ''; // JSON object\n\n constructor(options: EmailOptions = {}) {\n super(options);\n\n if (options.messageId !== undefined) this.messageId = options.messageId;\n if (options.inReplyTo !== undefined) this.inReplyTo = options.inReplyTo;\n if (options.ccAddresses !== undefined)\n this.ccAddresses = options.ccAddresses;\n if (options.bccAddresses !== undefined)\n this.bccAddresses = options.bccAddresses;\n if (options.replyToAddress !== undefined)\n this.replyToAddress = options.replyToAddress;\n if (options.replyToName !== undefined)\n this.replyToName = options.replyToName;\n if (options.textBody !== undefined) this.textBody = options.textBody;\n if (options.htmlBody !== undefined) this.htmlBody = options.htmlBody;\n if (options.folderId !== undefined) this.folderId = options.folderId;\n if (options.folderPath !== undefined) this.folderPath = options.folderPath;\n if (options.labels !== undefined) this.labels = options.labels;\n if (options.flags !== undefined) this.flags = options.flags;\n if (options.isAnswered !== undefined) this.isAnswered = options.isAnswered;\n if (options.isDraft !== undefined) this.isDraft = options.isDraft;\n if (options.rawMessage !== undefined) this.rawMessage = options.rawMessage;\n if (options.headers !== undefined) this.headers = options.headers;\n\n // Populate base body from textBody for unified access\n if (options.textBody && !options.body) {\n this.body = options.textBody;\n }\n }\n\n /**\n * Get CC addresses as parsed array\n */\n getCcAddresses(): Array<{ address: string; name?: string }> {\n if (!this.ccAddresses) return [];\n try {\n return JSON.parse(this.ccAddresses);\n } catch {\n return [];\n }\n }\n\n /**\n * Get BCC addresses as parsed array\n */\n getBccAddresses(): Array<{ address: string; name?: string }> {\n if (!this.bccAddresses) return [];\n try {\n return JSON.parse(this.bccAddresses);\n } catch {\n return [];\n }\n }\n\n /**\n * Get labels as parsed array\n */\n getLabels(): string[] {\n if (!this.labels) return [];\n try {\n return JSON.parse(this.labels);\n } catch {\n return [];\n }\n }\n\n /**\n * Set labels from array\n */\n setLabels(labels: string[]): void {\n this.labels = JSON.stringify(labels);\n }\n\n /**\n * Get flags as parsed array\n */\n getFlags(): string[] {\n if (!this.flags) return [];\n try {\n return JSON.parse(this.flags);\n } catch {\n return [];\n }\n }\n\n /**\n * Set flags from array\n */\n setFlags(flags: string[]): void {\n this.flags = JSON.stringify(flags);\n }\n\n /**\n * Get headers as parsed object\n */\n getHeaders(): Record<string, string | string[]> {\n if (!this.headers) return {};\n try {\n return JSON.parse(this.headers);\n } catch {\n return {};\n }\n }\n\n /**\n * Set headers from object\n */\n setHeaders(headers: Record<string, string | string[]>): void {\n this.headers = JSON.stringify(headers);\n }\n\n /**\n * Get the email account (typed as EmailAccount)\n */\n override async getAccount() {\n if (!this.accountId) return null;\n\n const { EmailAccountCollection } = await import(\n '../collections/EmailAccountCollection'\n );\n const collection = await (EmailAccountCollection as any).create(\n this.options,\n );\n\n return await collection.get({ id: this.accountId });\n }\n\n /**\n * Get the folder\n */\n async getFolder() {\n if (!this.folderId) return null;\n\n const { EmailFolderCollection } = await import(\n '../collections/EmailFolderCollection'\n );\n const collection = await (EmailFolderCollection as any).create(\n this.options,\n );\n\n return await collection.get({ id: this.folderId });\n }\n\n /**\n * Get emails in the same thread\n */\n async getThreadEmails(): Promise<Email[]> {\n if (!this.threadId) return [this];\n\n const { EmailCollection } = await import('../collections/EmailCollection');\n const collection = await (EmailCollection as any).create(this.options);\n\n return await collection.list({ where: { threadId: this.threadId } });\n }\n\n /**\n * Get a short preview of the email body\n */\n override getPreview(maxLength = 200): string {\n const body = this.textBody || this.htmlBody?.replace(/<[^>]*>/g, '') || '';\n if (body.length <= maxLength) return body;\n return `${body.slice(0, maxLength)}...`;\n }\n\n /**\n * Get References header values as array\n */\n getReferences(): string[] {\n const headers = this.getHeaders();\n const refs = headers.references;\n if (!refs) return [];\n if (Array.isArray(refs)) return refs;\n return refs.split(/\\s+/).filter(Boolean);\n }\n\n /**\n * Create a reply to this email with RFC 822 threading\n */\n override createReply(options?: { replyAll?: boolean }): Email {\n const reply = new Email({\n ...this.draftOptions(),\n id: undefined,\n accountId: this.accountId,\n threadId: this.threadId || this.id || undefined,\n subject: this.subject.startsWith('Re:')\n ? this.subject\n : `Re: ${this.subject}`,\n fromAddress: '',\n fromName: '',\n inReplyToMessageId: this.id || undefined,\n sendStatus: 'draft',\n isRead: true,\n isDraft: true,\n date: null,\n createdAt: undefined,\n updatedAt: undefined,\n\n // RFC 822 threading\n inReplyTo: this.messageId,\n\n // To: original sender\n toAddresses: JSON.stringify([\n { address: this.fromAddress, name: this.fromName },\n ]),\n });\n\n // RFC 822 References: original references + original Message-ID\n const refs = [...this.getReferences()];\n if (this.messageId && !refs.includes(this.messageId)) {\n refs.push(this.messageId);\n }\n reply.setHeaders({ references: refs.join(' ') });\n\n // Reply-All: add original To/CC as CC (excluding self)\n if (options?.replyAll) {\n const allRecipients = [\n ...this.getToAddresses(),\n ...this.getCcAddresses(),\n ];\n // Remove original sender (already in To:) and any duplicates\n const seen = new Set([this.fromAddress.toLowerCase()]);\n const ccAddresses = allRecipients.filter((r) => {\n const addr = r.address.toLowerCase();\n if (seen.has(addr)) return false;\n seen.add(addr);\n return true;\n });\n reply.ccAddresses = JSON.stringify(ccAddresses);\n }\n\n reply.body = this.buildQuotedBody();\n reply.textBody = reply.body;\n\n return reply;\n }\n\n /**\n * Create a forward of this email\n */\n override createForward(): Email {\n const forwardBody = this.buildForwardBody();\n\n const forward = new Email({\n ...this.draftOptions(),\n id: undefined,\n accountId: this.accountId,\n threadId: '',\n subject: this.subject.startsWith('Fwd:')\n ? this.subject\n : `Fwd: ${this.subject}`,\n toAddresses: '[]',\n ccAddresses: '[]',\n bccAddresses: '[]',\n fromAddress: '',\n fromName: '',\n body: forwardBody,\n textBody: forwardBody,\n hasAttachments: this.hasAttachments,\n inReplyToMessageId: '',\n inReplyTo: '',\n sendStatus: 'draft',\n isDraft: true,\n isRead: true,\n date: null,\n createdAt: undefined,\n updatedAt: undefined,\n });\n\n return forward;\n }\n\n /**\n * Build email-specific quoted body for replies\n */\n protected override buildQuotedBody(): string {\n const dateStr = this.date ? this.date.toLocaleString() : 'unknown date';\n const from = this.fromName\n ? `${this.fromName} <${this.fromAddress}>`\n : this.fromAddress;\n\n const bodyText = this.textBody || this.body || '';\n const quotedLines = bodyText\n .split('\\n')\n .map((line) => `> ${line}`)\n .join('\\n');\n\n return `\\n\\nOn ${dateStr}, ${from} wrote:\\n${quotedLines}`;\n }\n\n /**\n * Build forwarded message body\n */\n private buildForwardBody(): string {\n const dateStr = this.date ? this.date.toLocaleString() : 'unknown date';\n const from = this.fromName\n ? `${this.fromName} <${this.fromAddress}>`\n : this.fromAddress;\n\n const toStr = this.getToAddresses()\n .map((r) => (r.name ? `${r.name} <${r.address}>` : r.address))\n .join(', ');\n\n const bodyText = this.textBody || this.body || '';\n\n return [\n '',\n '',\n '---------- Forwarded message ----------',\n `From: ${from}`,\n `Date: ${dateStr}`,\n `Subject: ${this.subject}`,\n `To: ${toStr}`,\n '',\n bodyText,\n ].join('\\n');\n }\n}\n","/**\n * EmailCollection - Collection manager for Email objects\n *\n * Extends MessageCollection with email-specific query methods.\n * STI framework auto-filters to Email instances.\n */\n\nimport { Email } from '../models/Email';\nimport type { EmailSearchFilters } from '../types';\nimport { MessageCollection } from './MessageCollection';\n\nexport class EmailCollection extends MessageCollection {\n static override readonly _itemClass = Email;\n\n /**\n * Get email by RFC 822 Message-ID\n */\n async getByMessageId(\n accountId: string,\n messageId: string,\n ): Promise<Email | null> {\n const emails = await this.list({\n where: { accountId, messageId },\n limit: 1,\n });\n return (emails[0] as Email) || null;\n }\n\n /**\n * Get emails by account\n */\n async getByAccount(accountId: string): Promise<Email[]> {\n return (await this.list({ where: { accountId } })) as Email[];\n }\n\n /**\n * Get emails by folder\n */\n async getByFolder(folderId: string): Promise<Email[]> {\n return (await this.list({ where: { folderId } })) as Email[];\n }\n\n /**\n * Get emails by thread\n */\n override async getByThread(threadId: string): Promise<Email[]> {\n return (await this.list({ where: { threadId } })) as Email[];\n }\n\n /**\n * Get unread emails\n */\n override async getUnread(accountId?: string): Promise<Email[]> {\n const where: Record<string, any> = { isRead: false };\n if (accountId) {\n where.accountId = accountId;\n }\n return (await this.list({ where })) as Email[];\n }\n\n /**\n * Get flagged emails\n */\n override async getFlagged(accountId?: string): Promise<Email[]> {\n const where: Record<string, any> = { isFlagged: true };\n if (accountId) {\n where.accountId = accountId;\n }\n return (await this.list({ where })) as Email[];\n }\n\n /**\n * Get emails with attachments\n */\n async getWithAttachments(accountId?: string): Promise<Email[]> {\n const where: Record<string, any> = { hasAttachments: true };\n if (accountId) {\n where.accountId = accountId;\n }\n return (await this.list({ where })) as Email[];\n }\n\n /**\n * Get recent emails\n */\n override async getRecent(limit = 20, accountId?: string): Promise<Email[]> {\n const allEmails = (await this.list({\n where: accountId ? { accountId } : undefined,\n })) as Email[];\n\n return allEmails\n .sort((a, b) => {\n const dateA = a.date?.getTime() || 0;\n const dateB = b.date?.getTime() || 0;\n return dateB - dateA;\n })\n .slice(0, limit);\n }\n\n /**\n * Count emails in a folder\n */\n async countByFolder(folderId: string): Promise<number> {\n const emails = await this.list({ where: { folderId } });\n return emails.length;\n }\n\n /**\n * Count unread emails in a folder\n */\n async countUnreadByFolder(folderId: string): Promise<number> {\n const emails = await this.list({ where: { folderId, isRead: false } });\n return emails.length;\n }\n\n /**\n * Count unread emails for an account\n */\n async countUnreadByAccount(accountId: string): Promise<number> {\n const emails = await this.list({ where: { accountId, isRead: false } });\n return emails.length;\n }\n\n /**\n * Search emails with email-specific filters.\n * Alias: `search()` for backward compatibility.\n */\n override async search(\n query: string,\n filters?: EmailSearchFilters,\n ): Promise<Email[]> {\n return this.searchEmails(query, filters);\n }\n\n /**\n * Search emails with email-specific filters\n */\n async searchEmails(\n query: string,\n filters?: EmailSearchFilters,\n ): Promise<Email[]> {\n let emails = (await this.list({})) as Email[];\n\n // Filter by query\n if (query) {\n const lowerQuery = query.toLowerCase();\n emails = emails.filter(\n (e) =>\n e.subject?.toLowerCase().includes(lowerQuery) ||\n e.textBody?.toLowerCase().includes(lowerQuery) ||\n e.fromAddress?.toLowerCase().includes(lowerQuery) ||\n e.fromName?.toLowerCase().includes(lowerQuery),\n );\n }\n\n // Apply filters\n if (filters) {\n if (filters.accountId) {\n emails = emails.filter((e) => e.accountId === filters.accountId);\n }\n if (filters.folderId) {\n emails = emails.filter((e) => e.folderId === filters.folderId);\n }\n if (filters.threadId) {\n emails = emails.filter((e) => e.threadId === filters.threadId);\n }\n if (filters.from) {\n const fromLower = filters.from.toLowerCase();\n emails = emails.filter(\n (e) =>\n e.fromAddress?.toLowerCase().includes(fromLower) ||\n e.fromName?.toLowerCase().includes(fromLower),\n );\n }\n if (filters.to) {\n const toLower = filters.to.toLowerCase();\n emails = emails.filter((e) =>\n e.toAddresses?.toLowerCase().includes(toLower),\n );\n }\n if (filters.subject) {\n const subjectLower = filters.subject.toLowerCase();\n emails = emails.filter((e) =>\n e.subject?.toLowerCase().includes(subjectLower),\n );\n }\n if (filters.isRead !== undefined) {\n emails = emails.filter((e) => e.isRead === filters.isRead);\n }\n if (filters.isFlagged !== undefined) {\n emails = emails.filter((e) => e.isFlagged === filters.isFlagged);\n }\n if (filters.hasAttachments !== undefined) {\n emails = emails.filter(\n (e) => e.hasAttachments === filters.hasAttachments,\n );\n }\n if (filters.sincDate) {\n emails = emails.filter(\n (e) => e.date && e.date >= (filters.sincDate as Date),\n );\n }\n if (filters.beforeDate) {\n emails = emails.filter(\n (e) => e.date && e.date < (filters.beforeDate as Date),\n );\n }\n }\n\n return emails;\n }\n\n /**\n * Mark all emails in a folder as read\n */\n async markFolderRead(folderId: string): Promise<void> {\n const emails = (await this.getUnread()) as Email[];\n const folderEmails = emails.filter((e) => e.folderId === folderId);\n\n for (const email of folderEmails) {\n await email.markRead();\n }\n }\n\n /**\n * Delete emails by folder\n */\n async deleteByFolder(folderId: string): Promise<number> {\n const emails = await this.getByFolder(folderId);\n let count = 0;\n\n for (const email of emails) {\n await email.delete();\n count++;\n }\n\n return count;\n }\n\n /**\n * Get email statistics for an account\n */\n override async getAccountStats(accountId: string): Promise<{\n total: number;\n unread: number;\n flagged: number;\n withAttachments: number;\n byType: Record<string, number>;\n }> {\n const emails = await this.getByAccount(accountId);\n\n return {\n total: emails.length,\n unread: emails.filter((e) => !e.isRead).length,\n flagged: emails.filter((e) => e.isFlagged).length,\n withAttachments: emails.filter((e) => e.hasAttachments).length,\n byType: { Email: emails.length },\n };\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Tenant Helper Methods\n // ─────────────────────────────────────────────────────────────────────────\n\n override async findByTenant(tenantId: string): Promise<Email[]> {\n return this.list({ where: { tenantId } }) as Promise<Email[]>;\n }\n\n override async findGlobal(): Promise<Email[]> {\n return this.list({ where: { tenantId: null } }) as Promise<Email[]>;\n }\n\n override async findWithGlobals(tenantId: string): Promise<Email[]> {\n return this.query(\n `SELECT * FROM ${this.tableName} WHERE tenant_id = ? OR tenant_id IS NULL`,\n [tenantId],\n ) as Promise<Email[]>;\n }\n}\n","/**\n * EmailFolder model - Folder/label tracking\n */\n\nimport { foreignKey, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type { EmailFolderOptions } from '../types';\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class EmailFolder extends SmrtObject {\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n @foreignKey('Account')\n accountId = '';\n name = '';\n path = '';\n delimiter = '/';\n specialUse = ''; // '\\\\Inbox', '\\\\Sent', '\\\\Drafts', etc.\n messageCount = 0;\n unreadCount = 0;\n subscribed = true;\n\n // Timestamps\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: EmailFolderOptions = {}) {\n super(options);\n\n if (options.tenantId !== undefined) this.tenantId = options.tenantId as any;\n if (options.accountId !== undefined) this.accountId = options.accountId;\n if (options.name !== undefined) this.name = options.name;\n if (options.path !== undefined) this.path = options.path;\n if (options.delimiter !== undefined) this.delimiter = options.delimiter;\n if (options.specialUse !== undefined) this.specialUse = options.specialUse;\n if (options.messageCount !== undefined)\n this.messageCount = options.messageCount;\n if (options.unreadCount !== undefined)\n this.unreadCount = options.unreadCount;\n if (options.subscribed !== undefined) this.subscribed = options.subscribed;\n if (options.createdAt) this.createdAt = options.createdAt;\n if (options.updatedAt) this.updatedAt = options.updatedAt;\n }\n\n /**\n * Get the email account\n */\n async getAccount() {\n if (!this.accountId) return null;\n\n const { EmailAccountCollection } = await import(\n '../collections/EmailAccountCollection'\n );\n const collection = await (EmailAccountCollection as any).create(\n this.options,\n );\n\n return await collection.get({ id: this.accountId });\n }\n\n /**\n * Get all emails in this folder\n */\n async getEmails(limit?: number) {\n const { EmailCollection } = await import('../collections/EmailCollection');\n const collection = await (EmailCollection as any).create(this.options);\n\n const options: Record<string, any> = { where: { folderId: this.id } };\n if (limit) {\n options.limit = limit;\n }\n\n return await collection.list(options);\n }\n\n /**\n * Get unread emails in this folder\n */\n async getUnreadEmails(limit?: number) {\n const { EmailCollection } = await import('../collections/EmailCollection');\n const collection = await (EmailCollection as any).create(this.options);\n\n const options: Record<string, any> = {\n where: { folderId: this.id, isRead: false },\n };\n if (limit) {\n options.limit = limit;\n }\n\n return await collection.list(options);\n }\n\n /**\n * Update message counts from database\n */\n async refreshCounts(): Promise<void> {\n const { EmailCollection } = await import('../collections/EmailCollection');\n const collection = await (EmailCollection as any).create(this.options);\n\n this.messageCount = await collection.countByFolder(this.id);\n this.unreadCount = await collection.countUnreadByFolder(this.id);\n this.updatedAt = new Date();\n await this.save();\n }\n\n /**\n * Check if this is the inbox folder\n */\n isInbox(): boolean {\n return this.specialUse === '\\\\Inbox' || this.path.toLowerCase() === 'inbox';\n }\n\n /**\n * Check if this is the sent folder\n */\n isSent(): boolean {\n return this.specialUse === '\\\\Sent' || this.path.toLowerCase() === 'sent';\n }\n\n /**\n * Check if this is the drafts folder\n */\n isDrafts(): boolean {\n return (\n this.specialUse === '\\\\Drafts' || this.path.toLowerCase() === 'drafts'\n );\n }\n\n /**\n * Check if this is the trash folder\n */\n isTrash(): boolean {\n return this.specialUse === '\\\\Trash' || this.path.toLowerCase() === 'trash';\n }\n\n /**\n * Check if this is the spam/junk folder\n */\n isSpam(): boolean {\n return (\n this.specialUse === '\\\\Junk' ||\n this.path.toLowerCase() === 'spam' ||\n this.path.toLowerCase() === 'junk'\n );\n }\n\n /**\n * Check if this is a system folder\n */\n isSystemFolder(): boolean {\n return !!this.specialUse;\n }\n\n /**\n * Subscribe to folder\n */\n async subscribe(): Promise<void> {\n this.subscribed = true;\n this.updatedAt = new Date();\n await this.save();\n }\n\n /**\n * Unsubscribe from folder\n */\n async unsubscribe(): Promise<void> {\n this.subscribed = false;\n this.updatedAt = new Date();\n await this.save();\n }\n}\n","/**\n * EmailFolderCollection - Collection manager for EmailFolder objects\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { EmailFolder } from '../models/EmailFolder';\nimport type { EmailFolderSearchFilters } from '../types';\n\nexport class EmailFolderCollection extends SmrtCollection<EmailFolder> {\n static readonly _itemClass = EmailFolder;\n\n /**\n * Get folder by path for an account\n */\n async getByPath(\n accountId: string,\n path: string,\n ): Promise<EmailFolder | null> {\n const folders = await this.list({ where: { accountId, path } });\n return folders[0] || null;\n }\n\n /**\n * Get folders by account\n */\n async getByAccount(accountId: string): Promise<EmailFolder[]> {\n return await this.list({ where: { accountId } });\n }\n\n /**\n * Get inbox folder for an account\n */\n async getInbox(accountId: string): Promise<EmailFolder | null> {\n const folders = await this.getByAccount(accountId);\n return folders.find((f) => f.isInbox()) || null;\n }\n\n /**\n * Get sent folder for an account\n */\n async getSent(accountId: string): Promise<EmailFolder | null> {\n const folders = await this.getByAccount(accountId);\n return folders.find((f) => f.isSent()) || null;\n }\n\n /**\n * Get drafts folder for an account\n */\n async getDrafts(accountId: string): Promise<EmailFolder | null> {\n const folders = await this.getByAccount(accountId);\n return folders.find((f) => f.isDrafts()) || null;\n }\n\n /**\n * Get trash folder for an account\n */\n async getTrash(accountId: string): Promise<EmailFolder | null> {\n const folders = await this.getByAccount(accountId);\n return folders.find((f) => f.isTrash()) || null;\n }\n\n /**\n * Get spam folder for an account\n */\n async getSpam(accountId: string): Promise<EmailFolder | null> {\n const folders = await this.getByAccount(accountId);\n return folders.find((f) => f.isSpam()) || null;\n }\n\n /**\n * Get system folders for an account\n */\n async getSystemFolders(accountId: string): Promise<EmailFolder[]> {\n const folders = await this.getByAccount(accountId);\n return folders.filter((f) => f.isSystemFolder());\n }\n\n /**\n * Get user-created folders for an account\n */\n async getUserFolders(accountId: string): Promise<EmailFolder[]> {\n const folders = await this.getByAccount(accountId);\n return folders.filter((f) => !f.isSystemFolder());\n }\n\n /**\n * Get subscribed folders\n */\n async getSubscribed(accountId?: string): Promise<EmailFolder[]> {\n const where: Record<string, any> = { subscribed: true };\n if (accountId) {\n where.accountId = accountId;\n }\n return await this.list({ where });\n }\n\n /**\n * Get folders with unread messages\n */\n async getWithUnread(accountId?: string): Promise<EmailFolder[]> {\n const folders = accountId\n ? await this.getByAccount(accountId)\n : await this.list({});\n\n return folders.filter((f) => f.unreadCount > 0);\n }\n\n /**\n * Search folders with filters\n */\n async search(\n query: string,\n filters?: EmailFolderSearchFilters,\n ): Promise<EmailFolder[]> {\n let folders = await this.list({});\n\n // Filter by query\n if (query) {\n const lowerQuery = query.toLowerCase();\n folders = folders.filter(\n (f) =>\n f.name?.toLowerCase().includes(lowerQuery) ||\n f.path?.toLowerCase().includes(lowerQuery),\n );\n }\n\n // Apply filters\n if (filters) {\n if (filters.accountId) {\n folders = folders.filter((f) => f.accountId === filters.accountId);\n }\n if (filters.specialUse) {\n folders = folders.filter((f) => f.specialUse === filters.specialUse);\n }\n if (filters.subscribed !== undefined) {\n folders = folders.filter((f) => f.subscribed === filters.subscribed);\n }\n }\n\n return folders;\n }\n\n /**\n * Refresh counts for all folders in an account\n */\n async refreshAllCounts(accountId: string): Promise<void> {\n const folders = await this.getByAccount(accountId);\n\n for (const folder of folders) {\n await folder.refreshCounts();\n }\n }\n\n /**\n * Get folder statistics for an account\n */\n async getAccountStats(accountId: string): Promise<{\n totalFolders: number;\n totalMessages: number;\n totalUnread: number;\n systemFolders: number;\n userFolders: number;\n }> {\n const folders = await this.getByAccount(accountId);\n\n return {\n totalFolders: folders.length,\n totalMessages: folders.reduce((sum, f) => sum + f.messageCount, 0),\n totalUnread: folders.reduce((sum, f) => sum + f.unreadCount, 0),\n systemFolders: folders.filter((f) => f.isSystemFolder()).length,\n userFolders: folders.filter((f) => !f.isSystemFolder()).length,\n };\n }\n\n /**\n * Create standard system folders for an account\n */\n async createSystemFolders(accountId: string): Promise<void> {\n const standardFolders = [\n { name: 'INBOX', path: 'INBOX', specialUse: '\\\\Inbox' },\n { name: 'Sent', path: 'Sent', specialUse: '\\\\Sent' },\n { name: 'Drafts', path: 'Drafts', specialUse: '\\\\Drafts' },\n { name: 'Trash', path: 'Trash', specialUse: '\\\\Trash' },\n { name: 'Spam', path: 'Spam', specialUse: '\\\\Junk' },\n ];\n\n for (const folderData of standardFolders) {\n const existing = await this.getByPath(accountId, folderData.path);\n if (!existing) {\n // Create through the collection so the DB connection is bound; a bare\n // `new EmailFolder(...)` + save() throws \"Database accessed before\n // initialization\" under per-instance DB injection.\n const folder = await this.create({\n accountId,\n ...folderData,\n });\n await folder.save();\n }\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Tenant Helper Methods\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * Find all email folders belonging to a specific tenant\n */\n async findByTenant(tenantId: string): Promise<EmailFolder[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global email folders (no tenant)\n */\n async findGlobal(): Promise<EmailFolder[]> {\n return this.list({ where: { tenantId: null } });\n }\n\n /**\n * Find email folders for a tenant including global folders\n */\n async findWithGlobals(tenantId: string): Promise<EmailFolder[]> {\n return this.query(\n `SELECT * FROM ${this.tableName} WHERE tenant_id = ? OR tenant_id IS NULL`,\n [tenantId],\n );\n }\n}\n","import { SmrtObject, smrt } from '@happyvertical/smrt-core';\n\n/**\n * Blacklist - Block entries for email filtering\n *\n * Supports three pattern types:\n * - email: Exact email address (spam@example.com)\n * - domain: Entire domain (*@spam.com)\n * - regex: Custom regex pattern\n */\n@smrt({\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n cli: true,\n tenantScoped: true,\n})\nexport class Blacklist extends SmrtObject {\n pattern: string = '';\n type: 'email' | 'domain' | 'regex' = 'email';\n reason: string = '';\n autoArchive: boolean = true;\n\n constructor(options: any = {}) {\n super(options);\n\n if (options.pattern !== undefined) {\n this.pattern = options.pattern;\n }\n if (options.type !== undefined) {\n this.type = options.type;\n }\n }\n\n /**\n * Check if an email address matches this blacklist entry\n */\n matches(email: string): boolean {\n const normalizedEmail = email.toLowerCase().trim();\n\n switch (this.type) {\n case 'email':\n return normalizedEmail === this.pattern.toLowerCase().trim();\n\n case 'domain': {\n const domain = normalizedEmail.split('@')[1];\n return domain === this.pattern.toLowerCase().trim();\n }\n\n case 'regex': {\n const pattern = this.pattern.trim();\n if (!pattern) {\n return false;\n }\n try {\n const regex = new RegExp(pattern, 'i');\n return regex.test(normalizedEmail);\n } catch {\n return false;\n }\n }\n\n default:\n return false;\n }\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { Blacklist } from '../models/Blacklist.js';\n\nexport class BlacklistCollection extends SmrtCollection<Blacklist> {\n static readonly _itemClass = Blacklist;\n\n /**\n * Check if an email is blacklisted\n */\n async isBlacklisted(email: string): Promise<boolean> {\n const entries = await this.list({});\n\n for (const entry of entries) {\n if (entry.matches(email)) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Get the matching blacklist entry for an email\n */\n async getMatchingEntry(email: string): Promise<Blacklist | null> {\n const entries = await this.list({});\n\n for (const entry of entries) {\n if (entry.matches(email)) {\n return entry;\n }\n }\n\n return null;\n }\n}\n","import { SmrtObject, smrt } from '@happyvertical/smrt-core';\n\n/**\n * Whitelist - Allow-only entries for email filtering\n *\n * Supports three pattern types:\n * - email: Exact email address (user@example.com)\n * - domain: Entire domain (*@example.com)\n * - regex: Custom regex pattern\n */\n@smrt({\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n cli: true,\n tenantScoped: true,\n})\nexport class Whitelist extends SmrtObject {\n pattern: string = '';\n type: 'email' | 'domain' | 'regex' = 'email';\n category: string | null = null;\n description: string = '';\n\n constructor(options: any = {}) {\n super(options);\n\n if (options.pattern !== undefined) {\n this.pattern = options.pattern;\n }\n if (options.type !== undefined) {\n this.type = options.type;\n }\n }\n\n /**\n * Check if an email address matches this whitelist entry\n */\n matches(email: string): boolean {\n const normalizedEmail = email.toLowerCase().trim();\n\n switch (this.type) {\n case 'email':\n return normalizedEmail === this.pattern.toLowerCase().trim();\n\n case 'domain': {\n const domain = normalizedEmail.split('@')[1];\n return domain === this.pattern.toLowerCase().trim();\n }\n\n case 'regex': {\n const pattern = this.pattern.trim();\n if (!pattern) {\n return false;\n }\n try {\n const regex = new RegExp(pattern, 'i');\n return regex.test(normalizedEmail);\n } catch {\n return false;\n }\n }\n\n default:\n return false;\n }\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { Whitelist } from '../models/Whitelist.js';\n\nexport class WhitelistCollection extends SmrtCollection<Whitelist> {\n static readonly _itemClass = Whitelist;\n\n /**\n * Check if an email is whitelisted for a specific category\n */\n async isWhitelisted(email: string, category?: string): Promise<boolean> {\n const entries = await this.list({});\n\n for (const entry of entries) {\n if (!entry.matches(email)) {\n continue;\n }\n\n if (!category) {\n return true;\n }\n\n if (entry.category === category || entry.category === null) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Get the matching whitelist entry for an email\n */\n async getMatchingEntry(email: string): Promise<Whitelist | null> {\n const entries = await this.list({});\n\n for (const entry of entries) {\n if (entry.matches(email)) {\n return entry;\n }\n }\n\n return null;\n }\n\n /**\n * Get whitelist entries by category\n */\n async getByCategory(category: string): Promise<Whitelist[]> {\n return await this.list({\n where: { category },\n });\n }\n}\n","/**\n * SlackAccount model - Slack workspace account extending the Account STI base\n */\n\nimport { smrt } from '@happyvertical/smrt-core';\nimport type { MessageSenderInterface, SlackAccountOptions } from '../types';\nimport { Account } from './Account';\n\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class SlackAccount extends Account {\n workspaceId = '';\n workspaceName = '';\n botUserId = '';\n\n constructor(options: SlackAccountOptions = {}) {\n super(options);\n\n if (options.workspaceId !== undefined)\n this.workspaceId = options.workspaceId;\n if (options.workspaceName !== undefined)\n this.workspaceName = options.workspaceName;\n if (options.botUserId !== undefined) this.botUserId = options.botUserId;\n\n // Default provider type\n if (!this.providerType) this.providerType = 'slack';\n }\n\n /**\n * Create a sender for this Slack account\n */\n override async createSender(): Promise<MessageSenderInterface> {\n const { SlackSender } = await import('../senders/SlackSender');\n return new SlackSender(this);\n }\n}\n","/**\n * SlackMessage model - Slack message extending the Message STI base\n */\n\nimport { smrt } from '@happyvertical/smrt-core';\nimport type { SlackMessageOptions } from '../types';\nimport { Message } from './Message';\n\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get', 'create'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class SlackMessage extends Message {\n channelId = '';\n channelName = '';\n slackTs = ''; // Slack message timestamp (unique ID)\n slackThreadTs = ''; // Thread parent timestamp\n reactions = ''; // JSON array of {name, count, users[]}\n isEdited = false;\n messageType = ''; // 'message', 'bot_message', etc.\n blocks = ''; // JSON - Slack Block Kit blocks\n\n constructor(options: SlackMessageOptions = {}) {\n super(options);\n\n if (options.channelId !== undefined) this.channelId = options.channelId;\n if (options.channelName !== undefined)\n this.channelName = options.channelName;\n if (options.slackTs !== undefined) this.slackTs = options.slackTs;\n if (options.slackThreadTs !== undefined)\n this.slackThreadTs = options.slackThreadTs;\n if (options.reactions !== undefined) this.reactions = options.reactions;\n if (options.isEdited !== undefined) this.isEdited = options.isEdited;\n if (options.messageType !== undefined)\n this.messageType = options.messageType;\n if (options.blocks !== undefined) this.blocks = options.blocks;\n }\n\n /**\n * Get reactions as parsed array\n */\n getReactions(): Array<{ name: string; count: number; users?: string[] }> {\n if (!this.reactions) return [];\n try {\n return JSON.parse(this.reactions);\n } catch {\n return [];\n }\n }\n\n /**\n * Get blocks as parsed array\n */\n getBlocks(): any[] {\n if (!this.blocks) return [];\n try {\n return JSON.parse(this.blocks);\n } catch {\n return [];\n }\n }\n\n /**\n * Check if message is in a thread\n */\n isInThread(): boolean {\n return !!this.slackThreadTs && this.slackThreadTs !== this.slackTs;\n }\n\n /**\n * Get total reaction count\n */\n getTotalReactions(): number {\n return this.getReactions().reduce((sum, r) => sum + r.count, 0);\n }\n}\n","/**\n * Tweet model - Twitter/X message extending the Message STI base\n */\n\nimport { smrt } from '@happyvertical/smrt-core';\nimport type { TweetOptions } from '../types';\nimport { Message } from './Message';\n\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get', 'create'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class Tweet extends Message {\n tweetId = '';\n retweetCount = 0;\n likeCount = 0;\n replyCount = 0;\n isRetweet = false;\n isReply = false;\n mediaUrls = ''; // JSON array\n hashtags = ''; // JSON array\n mentions = ''; // JSON array\n\n constructor(options: TweetOptions = {}) {\n super(options);\n\n if (options.tweetId !== undefined) this.tweetId = options.tweetId;\n if (options.retweetCount !== undefined)\n this.retweetCount = options.retweetCount;\n if (options.likeCount !== undefined) this.likeCount = options.likeCount;\n if (options.replyCount !== undefined) this.replyCount = options.replyCount;\n if (options.isRetweet !== undefined) this.isRetweet = options.isRetweet;\n if (options.isReply !== undefined) this.isReply = options.isReply;\n if (options.mediaUrls !== undefined) this.mediaUrls = options.mediaUrls;\n if (options.hashtags !== undefined) this.hashtags = options.hashtags;\n if (options.mentions !== undefined) this.mentions = options.mentions;\n }\n\n /**\n * Get media URLs as parsed array\n */\n getMediaUrls(): string[] {\n if (!this.mediaUrls) return [];\n try {\n return JSON.parse(this.mediaUrls);\n } catch {\n return [];\n }\n }\n\n /**\n * Get hashtags as parsed array\n */\n getHashtags(): string[] {\n if (!this.hashtags) return [];\n try {\n return JSON.parse(this.hashtags);\n } catch {\n return [];\n }\n }\n\n /**\n * Get mentions as parsed array\n */\n getMentions(): string[] {\n if (!this.mentions) return [];\n try {\n return JSON.parse(this.mentions);\n } catch {\n return [];\n }\n }\n\n /**\n * Get total engagement count\n */\n getEngagement(): number {\n return this.retweetCount + this.likeCount + this.replyCount;\n }\n}\n","/**\n * TwitterAccount model - Twitter/X account extending the Account STI base\n */\n\nimport { smrt } from '@happyvertical/smrt-core';\nimport type { MessageSenderInterface, TwitterAccountOptions } from '../types';\nimport { Account } from './Account';\n\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class TwitterAccount extends Account {\n handle = '';\n twitterUserId = '';\n\n constructor(options: TwitterAccountOptions = {}) {\n super(options);\n\n if (options.handle !== undefined) this.handle = options.handle;\n if (options.twitterUserId !== undefined)\n this.twitterUserId = options.twitterUserId;\n\n // Default provider type\n if (!this.providerType) this.providerType = 'twitter';\n }\n\n /**\n * Create a sender for this Twitter account\n */\n override async createSender(): Promise<MessageSenderInterface> {\n const { TweetSender } = await import('../senders/TweetSender');\n return new TweetSender(this);\n }\n}\n","/**\n * EmailSender — sends email messages via the SDK EmailClient\n */\n\nimport type { EmailClient } from '@happyvertical/email';\nimport type { Email } from '../models/Email';\nimport type { EmailAccount } from '../models/EmailAccount';\nimport type {\n MessageSenderInterface,\n MessageSendResult,\n SendMessageOptions,\n} from '../types';\n\nexport class EmailSender implements MessageSenderInterface {\n readonly providerType = 'email';\n private client: EmailClient;\n private account: EmailAccount;\n\n constructor(client: EmailClient, account: EmailAccount) {\n this.client = client;\n this.account = account;\n }\n\n isReady(): boolean {\n return this.client.isConnected();\n }\n\n async send(\n message: Email,\n _options?: SendMessageOptions,\n ): Promise<MessageSendResult> {\n const toAddresses = message.getToAddresses();\n const ccAddresses = message.getCcAddresses();\n const bccAddresses = message.getBccAddresses();\n\n const emailMessage = {\n from: {\n name: message.fromName || this.account.name,\n address: message.fromAddress || this.account.email,\n },\n to: toAddresses.map((r) => ({\n name: r.name,\n address: r.address,\n })),\n cc:\n ccAddresses.length > 0\n ? ccAddresses.map((r) => ({ name: r.name, address: r.address }))\n : undefined,\n bcc:\n bccAddresses.length > 0\n ? bccAddresses.map((r) => ({ name: r.name, address: r.address }))\n : undefined,\n subject: message.subject,\n text: message.textBody || message.body,\n html: message.htmlBody || undefined,\n inReplyTo: message.inReplyTo || undefined,\n };\n\n try {\n const result = await this.client.send(emailMessage);\n\n return {\n success: true,\n providerMessageId: result.messageId,\n accepted: result.accepted,\n rejected: result.rejected,\n providerResponse: { response: result.response },\n sentAt: new Date(),\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n sentAt: new Date(),\n };\n }\n }\n}\n","/**\n * SlackSender — sends Slack messages via the SDK MessageClient\n */\n\nimport type { SlackAccount } from '../models/SlackAccount';\nimport type { SlackMessage } from '../models/SlackMessage';\nimport type {\n MessageSenderInterface,\n MessageSendResult,\n SendMessageOptions,\n} from '../types';\n\nexport class SlackSender implements MessageSenderInterface {\n readonly providerType = 'slack';\n private account: SlackAccount;\n\n constructor(account: SlackAccount) {\n this.account = account;\n }\n\n isReady(): boolean {\n return this.account.isActive;\n }\n\n async send(\n message: SlackMessage,\n _options?: SendMessageOptions,\n ): Promise<MessageSendResult> {\n const { getMessageClient } = await import('@happyvertical/messages');\n\n const credentials = await this.account.getCredentials();\n if (!credentials?.botToken) {\n return {\n success: false,\n error: 'No botToken found in account credentials',\n sentAt: new Date(),\n };\n }\n\n const client = await getMessageClient({\n type: 'slack',\n botToken: credentials.botToken,\n });\n\n try {\n await client.connect();\n\n const result = await client.send(\n {\n from: { id: this.account.botUserId, name: this.account.name },\n channelId: message.channelId,\n content: message.body,\n },\n {\n replyTo: message.slackThreadTs || undefined,\n },\n );\n\n await client.disconnect();\n\n return {\n success: result.success,\n providerMessageId: result.messageId,\n providerResponse: result.providerResponse,\n sentAt: result.timestamp,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n sentAt: new Date(),\n };\n }\n }\n}\n","/**\n * TweetSender — sends tweets via the SDK MessageClient\n */\n\nimport type { Tweet } from '../models/Tweet';\nimport type { TwitterAccount } from '../models/TwitterAccount';\nimport type {\n MessageSenderInterface,\n MessageSendResult,\n SendMessageOptions,\n} from '../types';\n\nexport class TweetSender implements MessageSenderInterface {\n readonly providerType = 'twitter';\n private account: TwitterAccount;\n\n constructor(account: TwitterAccount) {\n this.account = account;\n }\n\n isReady(): boolean {\n return this.account.isActive;\n }\n\n async send(\n message: Tweet,\n _options?: SendMessageOptions,\n ): Promise<MessageSendResult> {\n const { getMessageClient } = await import('@happyvertical/messages');\n\n const credentials = await this.account.getCredentials();\n if (\n !credentials?.apiKey ||\n !credentials?.apiSecret ||\n !credentials?.accessToken ||\n !credentials?.accessSecret\n ) {\n return {\n success: false,\n error: 'Missing Twitter API credentials in account',\n sentAt: new Date(),\n };\n }\n\n const client = await getMessageClient({\n type: 'twitter',\n apiKey: credentials.apiKey,\n apiSecret: credentials.apiSecret,\n accessToken: credentials.accessToken,\n accessSecret: credentials.accessSecret,\n });\n\n try {\n const sendOptions: Record<string, string> = {};\n if (message.isReply && message.inReplyToMessageId) {\n sendOptions.replyTo = message.inReplyToMessageId;\n }\n\n const result = await client.send(\n {\n from: { id: this.account.twitterUserId, name: this.account.handle },\n content: message.body,\n },\n sendOptions.replyTo ? { replyTo: sendOptions.replyTo } : undefined,\n );\n\n return {\n success: result.success,\n providerMessageId: result.messageId,\n providerResponse: result.providerResponse,\n sentAt: result.timestamp,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n sentAt: new Date(),\n };\n }\n }\n}\n"],"names":["__decorateClass","tenantId","MessageCollection","AccountCollection","AttachmentCollection","EmailSender","EmailCollection","EmailFolderCollection","EmailFolder","Email","EmailAccountCollection","SlackSender","TweetSender"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/__smrt-register__.ts","../src/models/Account.ts","../src/collections/tenant-global-queries.ts","../src/collections/AccountCollection.ts","../src/models/Attachment.ts","../src/collections/AttachmentCollection.ts","../src/models/Message.ts","../src/collections/MessageCollection.ts","../src/models/EmailAccount.ts","../src/collections/EmailAccountCollection.ts","../src/models/EmailAttachment.ts","../src/collections/EmailAttachmentCollection.ts","../src/models/Email.ts","../src/collections/EmailCollection.ts","../src/models/EmailFolder.ts","../src/collections/EmailFolderCollection.ts","../src/models/Blacklist.ts","../src/collections/BlacklistCollection.ts","../src/models/Whitelist.ts","../src/collections/WhitelistCollection.ts","../src/models/SlackAccount.ts","../src/models/SlackMessage.ts","../src/models/Tweet.ts","../src/models/TwitterAccount.ts","../src/senders/EmailSender.ts","../src/senders/SlackSender.ts","../src/senders/TweetSender.ts"],"sourcesContent":["/**\n * Self-registers this package's build-time manifest before any @smrt() decorator\n * in the package fires. Fixes issue #1132: in consumer runtimes (tsx, SvelteKit\n * SSR, plain `vite dev`) the decorator's synchronous manifest lookup previously\n * missed because no step populated the global manifest cache — classes got\n * registered with zero fields and `save()` / `toJSON()` silently dropped every\n * declared property.\n *\n * Import this module as the first statement in `src/index.ts` so its top-level\n * side effect runs ahead of any class module's @smrt() decorator.\n *\n * Silent no-op in dev/test, where the vitest plugin already populates manifests\n * via a different path. Only needs to succeed in the published dist output.\n *\n * @see https://github.com/happyvertical/smrt/issues/1132\n */\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\n\n// `new URL('./manifest.json', import.meta.url)` resolves at runtime to the\n// manifest sitting next to this module's compiled output. Vite warns at build\n// time that it cannot pre-resolve the URL; that is the intended behavior —\n// the URL must resolve to dist/manifest.json at runtime, not be inlined.\nObjectRegistry.registerPackageManifest(\n new URL('./manifest.json', import.meta.url),\n);\n","/**\n * Account model - Base class for all messaging account types (STI)\n *\n * Common fields shared across email, Slack, Twitter accounts, etc.\n */\n\nimport { field, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type { AccountOptions, MessageSenderInterface } from '../types';\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class Account extends SmrtObject {\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n name = '';\n providerType = '';\n // credentialSecretId stores the Secret's NAME (keyed by name + tenant\n // context in smrt-secrets), NOT its primary-key id — see setCredentials()/\n // getCredentials() which call secretService.store/retrieve by name. So it is\n // deliberately NOT a @crossPackageRef id FK.\n credentialSecretId: string | null = null;\n isActive = true;\n lastSyncAt: Date | null = null;\n // JSON. Sensitive (#1540): may hold a plaintext credential fallback, so it is\n // excluded from generated API/MCP responses and rejected as a `where` filter\n // key.\n @field({ sensitive: true })\n settings = ''; // JSON\n\n // Timestamps\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: AccountOptions = {}) {\n super(options);\n\n if (options.tenantId !== undefined) this.tenantId = options.tenantId as any;\n if (options.name !== undefined) this.name = options.name;\n if (options.providerType !== undefined)\n this.providerType = options.providerType;\n if (options.credentialSecretId !== undefined)\n this.credentialSecretId = options.credentialSecretId || null;\n if (options.isActive !== undefined) this.isActive = options.isActive;\n if (options.lastSyncAt !== undefined)\n this.lastSyncAt = options.lastSyncAt || null;\n if (options.settings !== undefined) this.settings = options.settings;\n if (options.createdAt) this.createdAt = options.createdAt;\n if (options.updatedAt) this.updatedAt = options.updatedAt;\n }\n\n /**\n * Get settings as parsed object\n */\n getSettings(): Record<string, any> {\n if (!this.settings) return {};\n try {\n return JSON.parse(this.settings);\n } catch {\n return {};\n }\n }\n\n /**\n * Set settings from object\n */\n setSettings(settings: Record<string, any>): void {\n this.settings = JSON.stringify(settings);\n }\n\n /**\n * Activate account\n */\n async activate(): Promise<void> {\n this.isActive = true;\n this.updatedAt = new Date();\n await this.save();\n }\n\n /**\n * Deactivate account\n */\n async deactivate(): Promise<void> {\n this.isActive = false;\n this.updatedAt = new Date();\n await this.save();\n }\n\n /**\n * Store credentials securely using smrt-secrets\n */\n async setCredentials(\n credentials: Record<string, any>,\n options: {\n description?: string;\n category?: string;\n } = {},\n ): Promise<void> {\n const { SecretService } = await import('@happyvertical/smrt-secrets');\n const secretService = await SecretService.create({ db: this.db });\n\n const secretName = `account-${this.id}`;\n const secretValue = JSON.stringify(credentials);\n\n if (this.credentialSecretId) {\n await secretService.store(this.credentialSecretId, secretValue, {\n description: options.description || `Credentials for ${this.name}`,\n category: options.category || 'messaging',\n });\n } else {\n await secretService.store(secretName, secretValue, {\n description: options.description || `Credentials for ${this.name}`,\n category: options.category || 'messaging',\n });\n\n this.credentialSecretId = secretName;\n this.updatedAt = new Date();\n await this.save();\n }\n }\n\n /**\n * Create a sender for this account.\n * Subclasses must override to return a concrete sender.\n */\n async createSender(): Promise<MessageSenderInterface> {\n throw new Error(\n `createSender() not implemented for account type '${this.providerType}'`,\n );\n }\n\n /**\n * Retrieve stored credentials\n */\n async getCredentials(): Promise<Record<string, any> | null> {\n if (!this.credentialSecretId) {\n return this.getSettings();\n }\n\n const { SecretService } = await import('@happyvertical/smrt-secrets');\n const secretService = await SecretService.create({ db: this.db });\n\n try {\n const secret = await secretService.retrieve(this.credentialSecretId);\n return JSON.parse(secret.value);\n } catch {\n return null;\n }\n }\n}\n","/**\n * Raw-SQL helpers for the messages collections' tenant/global lookups (#1596).\n *\n * The messages models are tenant-scoped: the STI bases (Message / Account /\n * Attachment) and EmailFolder carry `@TenantScoped`, and the STI children\n * (Email / EmailAccount) plus the CTI EmailAttachment now inherit that\n * recognition automatically through `@happyvertical/smrt-tenancy` (#1596).\n *\n * Under an active tenant context the interceptor rejects BOTH an explicit\n * `tenant_id IS NULL` filter routed through `list({ where: { tenantId: null } })`\n * (flagged as an isolation violation) AND unflagged raw SQL on a tenant-scoped\n * class. So the \"global\" and \"tenant + globals\" helpers must run raw with\n * `{ allowRawOnTenantScoped: true }` and carry the tenant predicate themselves.\n *\n * The bypass disables the interceptor's isolation guard, so `queryWithGlobals`\n * re-implements it (`assertTenantReadAllowed`): a caller under tenant-A must not\n * read tenant-B's rows by passing tenant-B's id (e.g. straight from untrusted\n * params). A system / super-admin-bypass context keeps the deliberate\n * cross-tenant capability for admin paths.\n *\n * STI **child** collections (`EmailCollection`, `EmailAccountCollection`) pass\n * their qualified `_meta_type` so the shared table never returns sibling\n * subtypes; STI **base** collections (`MessageCollection`, `AccountCollection`)\n * and CTI collections (`AttachmentCollection`, `EmailAttachmentCollection`,\n * `EmailFolderCollection`) pass none. Mirrors the images precedent\n * (`packages/images/src/images.ts`, #1407/#1400).\n */\n\nimport type { SmrtCollection } from '@happyvertical/smrt-core';\nimport {\n getCurrentTenant,\n isSuperAdminBypass,\n TenantIsolationError,\n} from '@happyvertical/smrt-tenancy';\n\n/**\n * Fail closed when an active tenant context requests a different tenant's rows.\n *\n * @param tenantId - The tenant id the caller asked for.\n * @param label - `Class.method` identifier for the error message.\n * @throws {TenantIsolationError} when a non-bypass tenant context is active and\n * does not match `tenantId`.\n */\nexport function assertTenantReadAllowed(tenantId: string, label: string): void {\n const tenantContext = getCurrentTenant();\n if (\n tenantContext &&\n !isSuperAdminBypass() &&\n tenantContext.tenantId !== tenantId\n ) {\n throw new TenantIsolationError(\n `Tenant isolation violation in ${label}: context tenant is ` +\n `'${tenantContext.tenantId}' but query requested '${tenantId}'`,\n { tenantId: tenantContext.tenantId, attemptedTenantId: tenantId },\n );\n }\n}\n\n/**\n * Return all global (tenant-less) rows for a tenant-scoped collection.\n *\n * @param collection - The tenant-scoped collection to query.\n * @param metaType - Qualified STI `_meta_type` to scope to (STI child\n * collections); omit for STI base / CTI collections.\n */\nexport async function queryGlobal<T>(\n collection: SmrtCollection<any>,\n metaType?: string,\n): Promise<T[]> {\n const where = metaType\n ? 'WHERE _meta_type = ? AND tenant_id IS NULL'\n : 'WHERE tenant_id IS NULL';\n const params = metaType ? [metaType] : [];\n return (await collection.query(\n `SELECT * FROM ${collection.tableName} ${where}`,\n params,\n { allowRawOnTenantScoped: true },\n )) as T[];\n}\n\n/**\n * Return a tenant's rows plus all global rows for a tenant-scoped collection.\n *\n * Fails closed (`assertTenantReadAllowed`) before issuing the bypassed query.\n *\n * @param collection - The tenant-scoped collection to query.\n * @param tenantId - The tenant id to include alongside globals.\n * @param label - `Class.method` identifier for the isolation error message.\n * @param metaType - Qualified STI `_meta_type` to scope to (STI child\n * collections); omit for STI base / CTI collections.\n */\nexport async function queryWithGlobals<T>(\n collection: SmrtCollection<any>,\n tenantId: string,\n label: string,\n metaType?: string,\n): Promise<T[]> {\n assertTenantReadAllowed(tenantId, label);\n const where = metaType\n ? 'WHERE _meta_type = ? AND (tenant_id = ? OR tenant_id IS NULL)'\n : 'WHERE tenant_id = ? OR tenant_id IS NULL';\n const params = metaType ? [metaType, tenantId] : [tenantId];\n return (await collection.query(\n `SELECT * FROM ${collection.tableName} ${where}`,\n params,\n { allowRawOnTenantScoped: true },\n )) as T[];\n}\n","/**\n * AccountCollection - Unified collection for polymorphic account queries\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { Account } from '../models/Account';\nimport type { AccountSearchFilters } from '../types';\nimport { queryGlobal, queryWithGlobals } from './tenant-global-queries';\n\nexport class AccountCollection extends SmrtCollection<Account> {\n static readonly _itemClass = Account;\n\n /**\n * Get active accounts\n */\n async getActive(): Promise<Account[]> {\n return await this.list({ where: { isActive: true } });\n }\n\n /**\n * Get inactive accounts\n */\n async getInactive(): Promise<Account[]> {\n return await this.list({ where: { isActive: false } });\n }\n\n /**\n * Get accounts by provider type\n */\n async getByProviderType(providerType: string): Promise<Account[]> {\n return await this.list({ where: { providerType } });\n }\n\n /**\n * Get accounts by STI type.\n *\n * Accepts either the full discriminator (e.g. \"@happyvertical/smrt-messages:EmailAccount\")\n * or the short type name (e.g. \"EmailAccount\").\n */\n async getByType(accountType: string): Promise<Account[]> {\n if (accountType.includes(':') || accountType.startsWith('@')) {\n return await this.list({ where: { _meta_type: accountType } });\n }\n const allAccounts = await this.list({});\n return allAccounts.filter((a) => {\n const metaType = (a as any)._meta_type || '';\n return metaType.endsWith(`:${accountType}`);\n });\n }\n\n /**\n * Search accounts with filters\n */\n async search(\n query: string,\n filters?: AccountSearchFilters,\n ): Promise<Account[]> {\n let accounts = await this.list({});\n\n if (query) {\n const lowerQuery = query.toLowerCase();\n accounts = accounts.filter((a) =>\n a.name?.toLowerCase().includes(lowerQuery),\n );\n }\n\n if (filters) {\n if (filters.providerType) {\n accounts = accounts.filter(\n (a) => a.providerType === filters.providerType,\n );\n }\n if (filters.isActive !== undefined) {\n accounts = accounts.filter((a) => a.isActive === filters.isActive);\n }\n if (filters.accountType) {\n accounts = accounts.filter((a) => {\n const metaType = (a as any)._meta_type || '';\n return metaType.includes(filters.accountType as string);\n });\n }\n }\n\n return accounts;\n }\n\n /**\n * Get account statistics\n */\n async getStats(): Promise<{\n total: number;\n active: number;\n inactive: number;\n byType: Record<string, number>;\n }> {\n const accounts = await this.list({});\n const byType: Record<string, number> = {};\n\n for (const account of accounts) {\n const metaType = (account as any)._meta_type || 'Unknown';\n const shortType = metaType.split(':').pop() || metaType;\n byType[shortType] = (byType[shortType] || 0) + 1;\n }\n\n return {\n total: accounts.length,\n active: accounts.filter((a) => a.isActive).length,\n inactive: accounts.filter((a) => !a.isActive).length,\n byType,\n };\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Tenant Helper Methods\n // ─────────────────────────────────────────────────────────────────────────\n\n async findByTenant(tenantId: string): Promise<Account[]> {\n return this.list({ where: { tenantId } });\n }\n\n // Account is the @TenantScoped STI base — see MessageCollection. Route through\n // the raw helpers; no `_meta_type` so the base returns ALL account subtypes.\n async findGlobal(): Promise<Account[]> {\n return queryGlobal<Account>(this);\n }\n\n async findWithGlobals(tenantId: string): Promise<Account[]> {\n return queryWithGlobals<Account>(this, tenantId, 'Account.findWithGlobals');\n }\n}\n","/**\n * Attachment model - Generalized attachment for any message type\n *\n * Uses messageId instead of emailId for cross-type support.\n */\n\nimport { foreignKey, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type { AttachmentOptions } from '../types';\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n api: { include: ['list', 'get', 'create', 'delete'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class Attachment extends SmrtObject {\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n @foreignKey('Message')\n messageId = '';\n filename = '';\n contentType = '';\n size = 0;\n contentId = ''; // For inline images (<img src=\"cid:...\">)\n contentDisposition: 'attachment' | 'inline' = 'attachment';\n filePath = ''; // External file storage path\n sourceUrl = ''; // For non-email attachments (media URLs, etc.)\n\n // Timestamps\n createdAt = new Date();\n\n constructor(options: AttachmentOptions = {}) {\n super(options);\n\n if (options.tenantId !== undefined) this.tenantId = options.tenantId as any;\n if (options.messageId !== undefined) this.messageId = options.messageId;\n if (options.filename !== undefined) this.filename = options.filename;\n if (options.contentType !== undefined)\n this.contentType = options.contentType;\n if (options.size !== undefined) this.size = options.size;\n if (options.contentId !== undefined) this.contentId = options.contentId;\n if (options.contentDisposition !== undefined)\n this.contentDisposition = options.contentDisposition;\n if (options.filePath !== undefined) this.filePath = options.filePath;\n if (options.sourceUrl !== undefined) this.sourceUrl = options.sourceUrl;\n if (options.createdAt) this.createdAt = options.createdAt;\n }\n\n /**\n * Get the message this attachment belongs to\n */\n async getMessage() {\n if (!this.messageId) return null;\n\n const { MessageCollection } = await import(\n '../collections/MessageCollection'\n );\n const collection = await (MessageCollection as any).create(this.options);\n\n return await collection.get({ id: this.messageId });\n }\n\n /**\n * Check if attachment is an image\n */\n isImage(): boolean {\n return this.contentType.startsWith('image/');\n }\n\n /**\n * Check if attachment is a PDF\n */\n isPdf(): boolean {\n return this.contentType === 'application/pdf';\n }\n\n /**\n * Check if attachment is inline (embedded in message body)\n */\n isInline(): boolean {\n return this.contentDisposition === 'inline';\n }\n\n /**\n * Get file extension from filename\n */\n getExtension(): string {\n if (!this.filename) return '';\n const parts = this.filename.split('.');\n return parts.length > 1 ? parts[parts.length - 1].toLowerCase() : '';\n }\n\n /**\n * Get human-readable file size\n */\n getFormattedSize(): string {\n const units = ['B', 'KB', 'MB', 'GB'];\n let size = this.size;\n let unitIndex = 0;\n\n while (size >= 1024 && unitIndex < units.length - 1) {\n size /= 1024;\n unitIndex++;\n }\n\n return `${size.toFixed(1)} ${units[unitIndex]}`;\n }\n\n /**\n * Check if file is stored externally\n */\n hasExternalFile(): boolean {\n return !!this.filePath;\n }\n\n /**\n * Read file content (if stored externally)\n */\n async readContent(): Promise<Buffer | null> {\n if (!this.filePath) return null;\n\n try {\n const { getFilesystem } = await import('@happyvertical/files');\n const files = await getFilesystem({ type: 'local' });\n const data = await files.read(this.filePath);\n return data instanceof Buffer ? data : Buffer.from(data);\n } catch {\n return null;\n }\n }\n}\n","/**\n * AttachmentCollection - Generalized attachment collection using messageId\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { Attachment } from '../models/Attachment';\nimport { queryGlobal, queryWithGlobals } from './tenant-global-queries';\n\nexport class AttachmentCollection extends SmrtCollection<Attachment> {\n static readonly _itemClass = Attachment;\n\n /**\n * Get attachments for a message\n */\n async getByMessage(messageId: string): Promise<Attachment[]> {\n return await this.list({ where: { messageId } });\n }\n\n /**\n * Get attachments by content type\n */\n async getByContentType(contentType: string): Promise<Attachment[]> {\n return await this.list({ where: { contentType } });\n }\n\n /**\n * Get image attachments\n */\n async getImages(messageId?: string): Promise<Attachment[]> {\n const attachments = messageId\n ? await this.getByMessage(messageId)\n : await this.list({});\n\n return attachments.filter((a) => a.isImage());\n }\n\n /**\n * Get PDF attachments\n */\n async getPdfs(messageId?: string): Promise<Attachment[]> {\n const attachments = messageId\n ? await this.getByMessage(messageId)\n : await this.list({});\n\n return attachments.filter((a) => a.isPdf());\n }\n\n /**\n * Get inline attachments (embedded in message body)\n */\n async getInline(messageId: string): Promise<Attachment[]> {\n const attachments = await this.getByMessage(messageId);\n return attachments.filter((a) => a.isInline());\n }\n\n /**\n * Get regular attachments (not inline)\n */\n async getRegular(messageId: string): Promise<Attachment[]> {\n const attachments = await this.getByMessage(messageId);\n return attachments.filter((a) => !a.isInline());\n }\n\n /**\n * Get attachments with external files\n */\n async getWithExternalFiles(): Promise<Attachment[]> {\n const attachments = await this.list({});\n return attachments.filter((a) => a.hasExternalFile());\n }\n\n /**\n * Get total size of attachments for a message\n */\n async getTotalSize(messageId: string): Promise<number> {\n const attachments = await this.getByMessage(messageId);\n return attachments.reduce((sum, a) => sum + a.size, 0);\n }\n\n /**\n * Get largest attachments\n */\n async getLargest(limit = 10): Promise<Attachment[]> {\n const attachments = await this.list({});\n return attachments.sort((a, b) => b.size - a.size).slice(0, limit);\n }\n\n /**\n * Search attachments by filename\n */\n async searchByFilename(query: string): Promise<Attachment[]> {\n const attachments = await this.list({});\n const lowerQuery = query.toLowerCase();\n\n return attachments.filter((a) =>\n a.filename?.toLowerCase().includes(lowerQuery),\n );\n }\n\n /**\n * Get attachments by extension\n */\n async getByExtension(extension: string): Promise<Attachment[]> {\n const attachments = await this.list({});\n const lowerExt = extension.toLowerCase().replace(/^\\./, '');\n\n return attachments.filter((a) => a.getExtension() === lowerExt);\n }\n\n /**\n * Get attachment statistics\n */\n async getStats(): Promise<{\n total: number;\n totalSize: number;\n byType: Record<string, number>;\n inline: number;\n regular: number;\n }> {\n const attachments = await this.list({});\n\n const byType: Record<string, number> = {};\n for (const attachment of attachments) {\n const type = attachment.contentType.split('/')[0] || 'other';\n byType[type] = (byType[type] || 0) + 1;\n }\n\n return {\n total: attachments.length,\n totalSize: attachments.reduce((sum, a) => sum + a.size, 0),\n byType,\n inline: attachments.filter((a) => a.isInline()).length,\n regular: attachments.filter((a) => !a.isInline()).length,\n };\n }\n\n /**\n * Delete all attachments for a message\n */\n async deleteByMessage(messageId: string): Promise<number> {\n const attachments = await this.getByMessage(messageId);\n let count = 0;\n\n for (const attachment of attachments) {\n await attachment.delete();\n count++;\n }\n\n return count;\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Tenant Helper Methods\n // ─────────────────────────────────────────────────────────────────────────\n\n async findByTenant(tenantId: string): Promise<Attachment[]> {\n return this.list({ where: { tenantId } });\n }\n\n // Attachment is @TenantScoped (CTI, own `attachments` table). Under an active\n // tenant context list({ tenantId: null }) throws and unflagged raw SQL is\n // blocked (#1596); route through the raw helpers.\n async findGlobal(): Promise<Attachment[]> {\n return queryGlobal<Attachment>(this);\n }\n\n async findWithGlobals(tenantId: string): Promise<Attachment[]> {\n return queryWithGlobals<Attachment>(\n this,\n tenantId,\n 'Attachment.findWithGlobals',\n );\n }\n}\n","/**\n * Message model - Base class for all message types (STI)\n *\n * Common fields shared across email, tweets, slack messages, etc.\n */\n\nimport { foreignKey, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type {\n MessageOptions,\n MessageSendResult,\n SendMessageOptions,\n SendStatus,\n} from '../types';\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class Message extends SmrtObject {\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n @foreignKey('Account')\n accountId = '';\n threadId = '';\n subject = '';\n body = ''; // Normalized plain text\n fromAddress = '';\n fromName = '';\n toAddresses = ''; // JSON array of {address, name}\n date: Date | null = null;\n isRead = false;\n isFlagged = false;\n hasAttachments = false;\n size = 0;\n metadata = ''; // JSON extension bag\n\n // Send lifecycle fields\n sendStatus: SendStatus = 'draft';\n sentAt: Date | null = null;\n sendError = '';\n retryCount = 0;\n maxRetries = 3;\n scheduledSendAt: Date | null = null;\n @foreignKey('Message')\n inReplyToMessageId = '';\n\n // Timestamps\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: MessageOptions = {}) {\n super(options);\n\n if (options.tenantId !== undefined) this.tenantId = options.tenantId as any;\n if (options.accountId !== undefined) this.accountId = options.accountId;\n if (options.threadId !== undefined) this.threadId = options.threadId;\n if (options.subject !== undefined) this.subject = options.subject;\n if (options.body !== undefined) this.body = options.body;\n if (options.fromAddress !== undefined)\n this.fromAddress = options.fromAddress;\n if (options.fromName !== undefined) this.fromName = options.fromName;\n if (options.toAddresses !== undefined)\n this.toAddresses = options.toAddresses;\n if (options.date !== undefined) this.date = options.date || null;\n if (options.isRead !== undefined) this.isRead = options.isRead;\n if (options.isFlagged !== undefined) this.isFlagged = options.isFlagged;\n if (options.hasAttachments !== undefined)\n this.hasAttachments = options.hasAttachments;\n if (options.size !== undefined) this.size = options.size;\n if (options.metadata !== undefined) this.metadata = options.metadata;\n if (options.sendStatus !== undefined) this.sendStatus = options.sendStatus;\n if (options.sentAt !== undefined) this.sentAt = options.sentAt || null;\n if (options.sendError !== undefined) this.sendError = options.sendError;\n if (options.retryCount !== undefined) this.retryCount = options.retryCount;\n if (options.maxRetries !== undefined) this.maxRetries = options.maxRetries;\n if (options.scheduledSendAt !== undefined)\n this.scheduledSendAt = options.scheduledSendAt || null;\n if (options.inReplyToMessageId !== undefined)\n this.inReplyToMessageId = options.inReplyToMessageId;\n if (options.createdAt) this.createdAt = options.createdAt;\n if (options.updatedAt) this.updatedAt = options.updatedAt;\n }\n\n /**\n * Get to addresses as parsed array\n */\n getToAddresses(): Array<{ address: string; name?: string }> {\n if (!this.toAddresses) return [];\n try {\n return JSON.parse(this.toAddresses);\n } catch {\n return [];\n }\n }\n\n /**\n * Set to addresses from array\n */\n setToAddresses(addresses: Array<{ address: string; name?: string }>): void {\n this.toAddresses = JSON.stringify(addresses);\n }\n\n /**\n * Get metadata as parsed object\n */\n getMetadata(): Record<string, any> {\n if (!this.metadata) return {};\n try {\n return JSON.parse(this.metadata);\n } catch {\n return {};\n }\n }\n\n /**\n * Set metadata from object\n */\n setMetadata(data: Record<string, any>): void {\n this.metadata = JSON.stringify(data);\n }\n\n /**\n * Mark message as read\n */\n async markRead(): Promise<void> {\n this.isRead = true;\n this.updatedAt = new Date();\n await this.save();\n }\n\n /**\n * Mark message as unread\n */\n async markUnread(): Promise<void> {\n this.isRead = false;\n this.updatedAt = new Date();\n await this.save();\n }\n\n /**\n * Toggle flagged status\n */\n async toggleFlagged(): Promise<void> {\n this.isFlagged = !this.isFlagged;\n this.updatedAt = new Date();\n await this.save();\n }\n\n /**\n * Check if message is unread\n */\n isUnread(): boolean {\n return !this.isRead;\n }\n\n /**\n * Get a short preview of the message body\n */\n getPreview(maxLength = 200): string {\n const text = this.body || '';\n if (text.length <= maxLength) return text;\n return `${text.slice(0, maxLength)}...`;\n }\n\n /**\n * Get the account for this message\n */\n async getAccount() {\n if (!this.accountId) return null;\n\n const { AccountCollection } = await import(\n '../collections/AccountCollection'\n );\n const collection = await (AccountCollection as any).create(this.options);\n\n return await collection.get({ id: this.accountId });\n }\n\n /**\n * Get messages in the same thread\n */\n async getThreadMessages(): Promise<Message[]> {\n if (!this.threadId) return [this];\n\n const { MessageCollection } = await import(\n '../collections/MessageCollection'\n );\n const collection = await (MessageCollection as any).create(this.options);\n\n return await collection.list({ where: { threadId: this.threadId } });\n }\n\n /**\n * Get attachments for this message\n */\n async getAttachments() {\n const { AttachmentCollection } = await import(\n '../collections/AttachmentCollection'\n );\n const collection = await (AttachmentCollection as any).create(this.options);\n\n return await collection.list({ where: { messageId: this.id } });\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Send Lifecycle\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * Send this message via its account's sender\n */\n async send(options?: SendMessageOptions): Promise<MessageSendResult> {\n // Entry guard: a message that is already in flight or delivered must not be\n // sent again. Catches same-instance double-clicks before any work happens.\n if (this.sendStatus === 'sending' || this.sendStatus === 'sent') {\n return {\n success: false,\n error: `Cannot send: message is already '${this.sendStatus}'`,\n sentAt: new Date(),\n };\n }\n\n // Resolve account\n const account = await this.getAccount();\n if (!account) {\n const result: MessageSendResult = {\n success: false,\n error: 'No account associated with this message',\n sentAt: new Date(),\n };\n this.sendStatus = 'failed';\n this.sendError = result.error ?? '';\n this.updatedAt = new Date();\n await this.save();\n return result;\n }\n\n // Get sender from account\n const sender = await (account as any).createSender();\n\n // Claim the send. For a persisted row, do a compare-and-set so only one\n // concurrent sender wins: flip send_status to 'sending' atomically, gated on\n // the status we observed. If no row matched, another sender already claimed\n // it — abort without delivering (prevents duplicate sends). For an unsaved\n // draft there is no row yet, so the in-memory transition + save() (INSERT)\n // serves as the claim.\n const claimFromStatus = this.sendStatus;\n if (this.isPersisted && this.id) {\n const claim = await this.db.update(\n this.tableName,\n { id: this.id, send_status: claimFromStatus },\n { send_status: 'sending', updated_at: new Date() },\n );\n if (!claim || claim.affected < 1) {\n return {\n success: false,\n error: 'Cannot send: message is already being sent',\n sentAt: new Date(),\n };\n }\n this.sendStatus = 'sending';\n this.updatedAt = new Date();\n } else {\n this.sendStatus = 'sending';\n this.updatedAt = new Date();\n await this.save();\n }\n\n try {\n const result = await sender.send(this, options);\n\n if (result.success) {\n this.sendStatus = 'sent';\n this.sentAt = result.sentAt;\n this.sendError = '';\n } else {\n this.sendStatus = 'failed';\n this.sendError = result.error ?? 'Send failed';\n }\n\n this.updatedAt = new Date();\n await this.save();\n return result;\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n this.sendStatus = 'failed';\n this.sendError = errorMessage;\n this.updatedAt = new Date();\n await this.save();\n\n return {\n success: false,\n error: errorMessage,\n sentAt: new Date(),\n };\n }\n }\n\n /**\n * Retry sending a failed message\n */\n async retrySend(options?: SendMessageOptions): Promise<MessageSendResult> {\n if (this.sendStatus !== 'failed') {\n return {\n success: false,\n error: `Cannot retry: message status is '${this.sendStatus}', expected 'failed'`,\n sentAt: new Date(),\n };\n }\n\n if (this.retryCount >= this.maxRetries) {\n return {\n success: false,\n error: `Retry budget exhausted (${this.retryCount}/${this.maxRetries})`,\n sentAt: new Date(),\n };\n }\n\n this.retryCount++;\n this.updatedAt = new Date();\n await this.save();\n\n return this.send(options);\n }\n\n /**\n * Options for a derived draft (reply/forward) built from this message. Carries\n * the DB connection + tenant context from `this.options`, but strips this\n * message's own identity fields. When this message was hydrated from the DB,\n * `this.options` holds the row's `id`/`slug`/`context`/`_skipLoad`; spreading\n * those into a new draft would make `draft.save()` upsert onto the natural-key\n * conflict columns (`slug`/`context`/`_meta_type`) and overwrite the ORIGINAL\n * message instead of inserting a new row. See EmailAccount.childOptions().\n */\n protected draftOptions(): Record<string, unknown> {\n const rest = { ...(this.options as Record<string, unknown>) };\n delete rest.id;\n delete rest.slug;\n delete rest.context;\n delete rest._skipLoad;\n return rest;\n }\n\n /**\n * Create a reply to this message (returns unsaved draft)\n */\n createReply(_options?: { replyAll?: boolean }): Message {\n const reply = new (this.constructor as typeof Message)({\n ...this.draftOptions(),\n id: undefined,\n accountId: this.accountId,\n threadId: this.threadId || this.id || '',\n subject: this.subject.startsWith('Re:')\n ? this.subject\n : `Re: ${this.subject}`,\n toAddresses: JSON.stringify([\n { address: this.fromAddress, name: this.fromName },\n ]),\n fromAddress: '',\n fromName: '',\n body: this.buildQuotedBody(),\n inReplyToMessageId: this.id || '',\n sendStatus: 'draft',\n isRead: true,\n date: null,\n createdAt: undefined,\n updatedAt: undefined,\n });\n\n return reply;\n }\n\n /**\n * Create a forward of this message (returns unsaved draft)\n */\n createForward(): Message {\n const forward = new (this.constructor as typeof Message)({\n ...this.draftOptions(),\n id: undefined,\n accountId: this.accountId,\n threadId: '',\n subject: this.subject.startsWith('Fwd:')\n ? this.subject\n : `Fwd: ${this.subject}`,\n toAddresses: '[]',\n fromAddress: '',\n fromName: '',\n body: this.buildQuotedBody(),\n hasAttachments: this.hasAttachments,\n inReplyToMessageId: '',\n sendStatus: 'draft',\n isRead: true,\n date: null,\n createdAt: undefined,\n updatedAt: undefined,\n });\n\n return forward;\n }\n\n /**\n * Build quoted body for reply/forward\n */\n protected buildQuotedBody(): string {\n const dateStr = this.date ? this.date.toLocaleString() : 'unknown date';\n const from = this.fromName\n ? `${this.fromName} <${this.fromAddress}>`\n : this.fromAddress;\n\n const quotedLines = (this.body || '')\n .split('\\n')\n .map((line) => `> ${line}`)\n .join('\\n');\n\n return `\\n\\nOn ${dateStr}, ${from} wrote:\\n${quotedLines}`;\n }\n}\n","/**\n * MessageCollection - Unified collection for polymorphic message queries\n *\n * Queries the messages table with STI, returning correct subclass instances.\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { Message } from '../models/Message';\nimport type { MessageSearchFilters } from '../types';\nimport { queryGlobal, queryWithGlobals } from './tenant-global-queries';\n\nexport class MessageCollection extends SmrtCollection<Message> {\n static readonly _itemClass = Message;\n\n /**\n * Search messages with filters\n */\n async search(\n query: string,\n filters?: MessageSearchFilters,\n ): Promise<Message[]> {\n let messages = await this.list({});\n\n // Filter by query\n if (query) {\n const lowerQuery = query.toLowerCase();\n messages = messages.filter(\n (m) =>\n m.subject?.toLowerCase().includes(lowerQuery) ||\n m.body?.toLowerCase().includes(lowerQuery) ||\n m.fromAddress?.toLowerCase().includes(lowerQuery) ||\n m.fromName?.toLowerCase().includes(lowerQuery),\n );\n }\n\n // Apply filters\n if (filters) {\n if (filters.accountIds && filters.accountIds.length > 0) {\n messages = messages.filter((m) =>\n filters.accountIds?.includes(m.accountId),\n );\n }\n if (filters.messageType) {\n messages = messages.filter((m) => {\n const metaType = (m as any)._meta_type || '';\n return metaType.includes(filters.messageType as string);\n });\n }\n if (filters.from) {\n const fromLower = filters.from.toLowerCase();\n messages = messages.filter(\n (m) =>\n m.fromAddress?.toLowerCase().includes(fromLower) ||\n m.fromName?.toLowerCase().includes(fromLower),\n );\n }\n if (filters.to) {\n const toLower = filters.to.toLowerCase();\n messages = messages.filter((m) =>\n m.toAddresses?.toLowerCase().includes(toLower),\n );\n }\n if (filters.isRead !== undefined) {\n messages = messages.filter((m) => m.isRead === filters.isRead);\n }\n if (filters.isFlagged !== undefined) {\n messages = messages.filter((m) => m.isFlagged === filters.isFlagged);\n }\n if (filters.sinceDate) {\n messages = messages.filter(\n (m) => m.date && m.date >= (filters.sinceDate as Date),\n );\n }\n if (filters.beforeDate) {\n messages = messages.filter(\n (m) => m.date && m.date < (filters.beforeDate as Date),\n );\n }\n if (filters.query) {\n const q = filters.query.toLowerCase();\n messages = messages.filter(\n (m) =>\n m.subject?.toLowerCase().includes(q) ||\n m.body?.toLowerCase().includes(q),\n );\n }\n }\n\n return messages;\n }\n\n /**\n * Get messages by multiple accounts\n */\n async getByAccounts(accountIds: string[]): Promise<Message[]> {\n const allMessages = await this.list({});\n return allMessages.filter((m) => accountIds.includes(m.accountId));\n }\n\n /**\n * Get messages by STI type.\n *\n * Accepts either the full discriminator (e.g. \"@happyvertical/smrt-messages:Email\")\n * or the short type name (e.g. \"Email\").\n */\n async getByType(messageType: string): Promise<Message[]> {\n if (messageType.includes(':') || messageType.startsWith('@')) {\n return await this.list({ where: { _meta_type: messageType } });\n }\n const allMessages = await this.list({});\n return allMessages.filter((m) => {\n const metaType = (m as any)._meta_type || '';\n return metaType.endsWith(`:${messageType}`);\n });\n }\n\n /**\n * Get unread messages\n */\n async getUnread(accountId?: string): Promise<Message[]> {\n const where: Record<string, any> = { isRead: false };\n if (accountId) {\n where.accountId = accountId;\n }\n return await this.list({ where });\n }\n\n /**\n * Get flagged messages\n */\n async getFlagged(accountId?: string): Promise<Message[]> {\n const where: Record<string, any> = { isFlagged: true };\n if (accountId) {\n where.accountId = accountId;\n }\n return await this.list({ where });\n }\n\n /**\n * Get recent messages\n */\n async getRecent(limit = 20, accountId?: string): Promise<Message[]> {\n const allMessages = await this.list({\n where: accountId ? { accountId } : undefined,\n });\n\n return allMessages\n .sort((a, b) => {\n const dateA = a.date?.getTime() || 0;\n const dateB = b.date?.getTime() || 0;\n return dateB - dateA;\n })\n .slice(0, limit);\n }\n\n /**\n * Get messages by thread\n */\n async getByThread(threadId: string): Promise<Message[]> {\n return await this.list({ where: { threadId } });\n }\n\n /**\n * Mark multiple messages as read\n */\n async markAllRead(messageIds: string[]): Promise<void> {\n for (const id of messageIds) {\n const message = await this.get({ id });\n if (message) {\n await message.markRead();\n }\n }\n }\n\n /**\n * Get message statistics for an account\n */\n async getAccountStats(accountId: string): Promise<{\n total: number;\n unread: number;\n flagged: number;\n byType: Record<string, number>;\n }> {\n const messages = await this.list({ where: { accountId } });\n const byType: Record<string, number> = {};\n\n for (const msg of messages) {\n const metaType = (msg as any)._meta_type || 'Unknown';\n const shortType = metaType.split(':').pop() || metaType;\n byType[shortType] = (byType[shortType] || 0) + 1;\n }\n\n return {\n total: messages.length,\n unread: messages.filter((m) => !m.isRead).length,\n flagged: messages.filter((m) => m.isFlagged).length,\n byType,\n };\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Send / Draft Queries\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * Get draft messages\n */\n async getDrafts(accountId?: string): Promise<Message[]> {\n const where: Record<string, any> = { sendStatus: 'draft' };\n if (accountId) where.accountId = accountId;\n return await this.list({ where });\n }\n\n /**\n * Get sent messages\n */\n async getSent(accountId?: string): Promise<Message[]> {\n const where: Record<string, any> = { sendStatus: 'sent' };\n if (accountId) where.accountId = accountId;\n return await this.list({ where });\n }\n\n /**\n * Get scheduled messages\n */\n async getScheduled(accountId?: string): Promise<Message[]> {\n const where: Record<string, any> = { sendStatus: 'scheduled' };\n if (accountId) where.accountId = accountId;\n return await this.list({ where });\n }\n\n /**\n * Get messages that failed to send\n */\n async getFailedSends(accountId?: string): Promise<Message[]> {\n const where: Record<string, any> = { sendStatus: 'failed' };\n if (accountId) where.accountId = accountId;\n return await this.list({ where });\n }\n\n /**\n * Get outbox (pending + sending + scheduled)\n */\n async getOutbox(accountId?: string): Promise<Message[]> {\n const allMessages = await this.list({\n where: accountId ? { accountId } : undefined,\n });\n return allMessages.filter(\n (m) =>\n m.sendStatus === 'pending' ||\n m.sendStatus === 'sending' ||\n m.sendStatus === 'scheduled',\n );\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Tenant Helper Methods\n // ─────────────────────────────────────────────────────────────────────────\n\n async findByTenant(tenantId: string): Promise<Message[]> {\n return this.list({ where: { tenantId } });\n }\n\n // Message is the @TenantScoped STI base, so an explicit `tenant_id IS NULL`\n // filter via list() throws and unflagged raw SQL is blocked under an active\n // tenant context (#1596). Route through the raw helpers — no `_meta_type`\n // scope so the base collection still returns ALL message subtypes.\n async findGlobal(): Promise<Message[]> {\n return queryGlobal<Message>(this);\n }\n\n async findWithGlobals(tenantId: string): Promise<Message[]> {\n return queryWithGlobals<Message>(this, tenantId, 'Message.findWithGlobals');\n }\n}\n","/**\n * EmailAccount model - Email account extending the Account STI base\n *\n * Retains email-specific fields and sync capability.\n */\n\nimport { smrt } from '@happyvertical/smrt-core';\nimport type {\n EmailAccountOptions,\n MessageSenderInterface,\n ProviderType,\n SyncOptions,\n SyncResult,\n} from '../types';\nimport { Account } from './Account';\n\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class EmailAccount extends Account {\n email = '';\n syncIntervalMinutes = 60;\n\n constructor(options: EmailAccountOptions = {}) {\n super(options);\n\n if (options.email !== undefined) this.email = options.email;\n if (options.providerType !== undefined)\n this.providerType = options.providerType;\n if (options.syncIntervalMinutes !== undefined)\n this.syncIntervalMinutes = options.syncIntervalMinutes;\n }\n\n /**\n * Options for child rows (folders/emails) created during sync: carries the DB\n * connection + tenant context from this account, but strips this account's own\n * identity fields. When this account was hydrated from the DB, `this.options`\n * holds the account row's `id`/`slug`/`_skipLoad`; spreading those into a new\n * child would make every synced row inherit the account's primary key and\n * upsert over each other.\n */\n private childOptions(): Record<string, unknown> {\n const rest = { ...(this.options as Record<string, unknown>) };\n delete rest.id;\n delete rest.slug;\n delete rest._skipLoad;\n return rest;\n }\n\n /**\n * Create a sender for this email account\n */\n override async createSender(): Promise<MessageSenderInterface> {\n const client = await this.createClient();\n await client.connect();\n const { EmailSender } = await import('../senders/EmailSender');\n return new EmailSender(client, this);\n }\n\n /**\n * Create an EmailClient from stored settings\n * Retrieves credentials from smrt-secrets if credentialSecretId is set\n */\n async createClient() {\n const { getEmailClient } = await import('@happyvertical/email');\n let settings: Record<string, any>;\n\n // Use secrets integration if available\n if (this.credentialSecretId) {\n const { SecretService } = await import('@happyvertical/smrt-secrets');\n const secretService = await SecretService.create({ db: this.db });\n\n const secret = await secretService.retrieve(this.credentialSecretId);\n settings = JSON.parse(secret.value);\n } else {\n // Fallback to plain-text settings (DEPRECATED)\n settings = this.getSettings();\n }\n\n return await getEmailClient({\n type: this.providerType as ProviderType,\n ...settings,\n } as any);\n }\n\n /**\n * Sync emails from the email server to the database\n */\n async syncFrom(options: SyncOptions = {}): Promise<SyncResult> {\n const startTime = Date.now();\n const result: SyncResult = {\n folders: [],\n messagesProcessed: 0,\n messagesDownloaded: 0,\n messagesSkipped: 0,\n errors: [],\n duration: 0,\n };\n\n try {\n // Create email client\n const client = await this.createClient();\n await client.connect();\n\n // Get folders to sync\n const foldersToSync = options.folders || ['INBOX'];\n result.folders = foldersToSync;\n\n // Import collections\n const { EmailCollection } = await import(\n '../collections/EmailCollection'\n );\n const { EmailFolderCollection } = await import(\n '../collections/EmailFolderCollection'\n );\n\n const emailCollection = await (EmailCollection as any).create(\n this.options,\n );\n const folderCollection = await (EmailFolderCollection as any).create(\n this.options,\n );\n\n for (const folderName of foldersToSync) {\n try {\n // Ensure folder exists in database\n const accountId = this.id ?? '';\n let folder = await folderCollection.getByPath(accountId, folderName);\n\n if (!folder) {\n // Create folder record\n const { EmailFolder } = await import('./EmailFolder');\n folder = new EmailFolder({\n ...this.childOptions(),\n accountId,\n name: folderName,\n path: folderName,\n });\n // initialize() binds the DB connection; without it save() throws\n // \"Database accessed before initialization\" and sync persists nothing.\n await folder.initialize();\n await folder.save();\n }\n\n // Fetch messages from server\n const fetchOptions: Record<string, any> = {\n folder: folderName,\n limit: options.batchSize || 100,\n };\n\n if (options.since) {\n fetchOptions.since = options.since;\n }\n if (options.before) {\n fetchOptions.before = options.before;\n }\n\n const messages = await client.fetch(fetchOptions);\n\n for (const msg of messages) {\n result.messagesProcessed++;\n\n try {\n // Check if message already exists\n const existingEmail = await emailCollection.getByMessageId(\n this.id,\n msg.messageId || '',\n );\n\n if (existingEmail && !options.fullSync) {\n result.messagesSkipped++;\n continue;\n }\n\n // Create or update email record\n const { Email } = await import('./Email');\n let email = existingEmail;\n if (!email) {\n email = new Email({\n ...this.childOptions(),\n accountId,\n });\n // Bind the DB connection before save() (existingEmail is already\n // initialized via the query that loaded it).\n await email.initialize();\n }\n\n // Update fields\n email.messageId = msg.messageId || '';\n email.threadId = msg.threadId || '';\n email.inReplyTo = msg.inReplyTo || '';\n email.fromAddress = msg.from?.address || '';\n email.fromName = msg.from?.name || '';\n email.toAddresses = JSON.stringify(msg.to || []);\n email.ccAddresses = JSON.stringify(msg.cc || []);\n email.bccAddresses = JSON.stringify(msg.bcc || []);\n email.replyToAddress = msg.replyTo?.address || '';\n email.replyToName = msg.replyTo?.name || '';\n email.subject = msg.subject || '';\n email.date = msg.date || null;\n email.textBody = msg.text || '';\n email.htmlBody = msg.html || '';\n email.body = msg.text || '';\n email.folderId = folder.id;\n email.folderPath = folderName;\n email.labels = JSON.stringify(msg.labels || []);\n email.flags = JSON.stringify(msg.flags || []);\n email.hasAttachments =\n (msg.attachments && msg.attachments.length > 0) || false;\n email.size = msg.size || 0;\n email.headers = JSON.stringify(msg.headers || {});\n email.updatedAt = new Date();\n\n await email.save();\n result.messagesDownloaded++;\n\n // Report progress\n if (options.onProgress) {\n options.onProgress({\n folder: folderName,\n processed: result.messagesProcessed,\n total: messages.length,\n downloaded: result.messagesDownloaded,\n skipped: result.messagesSkipped,\n errors: result.errors.length,\n });\n }\n } catch (error) {\n const err =\n error instanceof Error ? error : new Error(String(error));\n result.errors.push(err);\n if (options.onError) {\n options.onError(err, msg);\n }\n }\n }\n\n // Update folder counts\n folder.messageCount = await emailCollection.countByFolder(folder.id);\n folder.unreadCount = await emailCollection.countUnreadByFolder(\n folder.id,\n );\n await folder.save();\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n result.errors.push(err);\n if (options.onError) {\n options.onError(err);\n }\n }\n }\n\n // Update last sync time\n this.lastSyncAt = new Date();\n this.updatedAt = new Date();\n await this.save();\n\n await client.disconnect();\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n result.errors.push(err);\n if (options.onError) {\n options.onError(err);\n }\n }\n\n result.duration = Date.now() - startTime;\n return result;\n }\n\n /**\n * Get all folders for this account\n */\n async getFolders() {\n const { EmailFolderCollection } = await import(\n '../collections/EmailFolderCollection'\n );\n const collection = await (EmailFolderCollection as any).create(\n this.options,\n );\n\n return await collection.list({ where: { accountId: this.id } });\n }\n\n /**\n * Get all emails for this account\n */\n async getEmails(limit?: number) {\n const { EmailCollection } = await import('../collections/EmailCollection');\n const collection = await (EmailCollection as any).create(this.options);\n\n const options: Record<string, any> = { where: { accountId: this.id } };\n if (limit) {\n options.limit = limit;\n }\n\n return await collection.list(options);\n }\n\n /**\n * Get unread email count\n */\n async getUnreadCount(): Promise<number> {\n const { EmailCollection } = await import('../collections/EmailCollection');\n const collection = await (EmailCollection as any).create(this.options);\n\n return await collection.countUnreadByAccount(this.id);\n }\n\n /**\n * Store credentials securely using smrt-secrets (email-specific)\n */\n override async setCredentials(\n credentials: Record<string, any>,\n options: {\n description?: string;\n category?: string;\n } = {},\n ): Promise<void> {\n const { SecretService } = await import('@happyvertical/smrt-secrets');\n const secretService = await SecretService.create({ db: this.db });\n\n const secretName = `email-account-${this.id}`;\n const secretValue = JSON.stringify(credentials);\n\n if (this.credentialSecretId) {\n await secretService.store(this.credentialSecretId, secretValue, {\n description: options.description || `IMAP credentials for ${this.name}`,\n category: options.category || 'email',\n });\n } else {\n await secretService.store(secretName, secretValue, {\n description: options.description || `IMAP credentials for ${this.name}`,\n category: options.category || 'email',\n });\n\n this.credentialSecretId = secretName;\n this.updatedAt = new Date();\n await this.save();\n }\n }\n\n /**\n * Sync all active email accounts (for job runner)\n *\n * NOTE: This is a class-wide operation, not per-instance. It syncs ALL active\n * accounts, ignoring `this` instance. It exists as an instance method because\n * the TaskRunner dispatches via `objectType: 'EmailAccount', method: 'syncAll'`\n * which requires an instance method signature.\n */\n async syncAll(\n args?: Record<string, unknown>,\n ): Promise<Map<string, { success: boolean; error?: Error }>> {\n const { EmailAccountCollection } = await import(\n '../collections/EmailAccountCollection'\n );\n const collection = await (EmailAccountCollection as any).create({\n db: this.db,\n });\n return collection.syncAll(args);\n }\n\n /**\n * Migrate from plain-text settings to secrets\n */\n async migrateToSecrets(): Promise<void> {\n if (this.credentialSecretId) {\n return;\n }\n\n const settings = this.getSettings();\n if (Object.keys(settings).length === 0) {\n return;\n }\n\n await this.setCredentials(settings, {\n description: `Migrated IMAP credentials for ${this.name}`,\n });\n }\n}\n","/**\n * EmailAccountCollection - Collection manager for EmailAccount objects\n *\n * Extends AccountCollection with email-specific query methods.\n */\n\nimport { EmailAccount } from '../models/EmailAccount';\nimport type { EmailAccountSearchFilters, ProviderType } from '../types';\nimport { AccountCollection } from './AccountCollection';\nimport { queryGlobal, queryWithGlobals } from './tenant-global-queries';\n\n/**\n * Qualified STI discriminator for EmailAccount rows in the shared `accounts`\n * table. Raw SQL on this tenant-scoped child collection must scope by\n * `_meta_type` so it never returns sibling Account subtypes (base Account,\n * TwitterAccount, SlackAccount). See `findGlobal` / `findWithGlobals`. (#1596)\n */\nconst EMAIL_ACCOUNT_META_TYPE = '@happyvertical/smrt-messages:EmailAccount';\n\nexport class EmailAccountCollection extends AccountCollection {\n static override readonly _itemClass = EmailAccount;\n\n /**\n * Get account by email address\n */\n async getByEmail(email: string): Promise<EmailAccount | null> {\n const accounts = await this.list({ where: { email } });\n return (accounts[0] as EmailAccount) || null;\n }\n\n /**\n * Get accounts by email provider type\n */\n async getByEmailProviderType(\n providerType: ProviderType,\n ): Promise<EmailAccount[]> {\n return (await this.list({ where: { providerType } })) as EmailAccount[];\n }\n\n /**\n * Get active email accounts\n */\n override async getActive(): Promise<EmailAccount[]> {\n return (await this.list({ where: { isActive: true } })) as EmailAccount[];\n }\n\n /**\n * Get inactive email accounts\n */\n override async getInactive(): Promise<EmailAccount[]> {\n return (await this.list({ where: { isActive: false } })) as EmailAccount[];\n }\n\n /**\n * Get accounts that need syncing\n */\n async getNeedingSync(maxAgeMinutes = 60): Promise<EmailAccount[]> {\n const allAccounts = await this.getActive();\n const cutoffTime = new Date(Date.now() - maxAgeMinutes * 60 * 1000);\n\n return allAccounts.filter(\n (account) => !account.lastSyncAt || account.lastSyncAt < cutoffTime,\n ) as EmailAccount[];\n }\n\n /**\n * Search email accounts with filters.\n * Alias: `search()` for backward compatibility.\n */\n override async search(\n query: string,\n filters?: EmailAccountSearchFilters,\n ): Promise<EmailAccount[]> {\n return this.searchEmailAccounts(query, filters);\n }\n\n /**\n * Get accounts by email provider type.\n * Alias: `getByProviderType()` for backward compatibility.\n */\n override async getByProviderType(\n providerType: string,\n ): Promise<EmailAccount[]> {\n return this.getByEmailProviderType(providerType as ProviderType);\n }\n\n /**\n * Get email account statistics.\n * Alias: `getStats()` for backward compatibility.\n */\n override async getStats(): Promise<{\n total: number;\n active: number;\n inactive: number;\n byType: Record<string, number>;\n }> {\n const stats = await this.getEmailStats();\n return {\n total: stats.total,\n active: stats.active,\n inactive: stats.inactive,\n byType: stats.byProvider as unknown as Record<string, number>,\n };\n }\n\n /**\n * Search email accounts with filters\n */\n async searchEmailAccounts(\n query: string,\n filters?: EmailAccountSearchFilters,\n ): Promise<EmailAccount[]> {\n let accounts = (await this.list({})) as EmailAccount[];\n\n // Filter by query\n if (query) {\n const lowerQuery = query.toLowerCase();\n accounts = accounts.filter(\n (a) =>\n a.name?.toLowerCase().includes(lowerQuery) ||\n a.email?.toLowerCase().includes(lowerQuery),\n );\n }\n\n // Apply filters\n if (filters) {\n if (filters.providerType) {\n accounts = accounts.filter(\n (a) => a.providerType === filters.providerType,\n );\n }\n if (filters.email) {\n const emailLower = filters.email.toLowerCase();\n accounts = accounts.filter((a) =>\n a.email?.toLowerCase().includes(emailLower),\n );\n }\n if (filters.isActive !== undefined) {\n accounts = accounts.filter((a) => a.isActive === filters.isActive);\n }\n }\n\n return accounts;\n }\n\n /**\n * Sync all active email accounts\n */\n async syncAll(\n options?: Record<string, any>,\n ): Promise<Map<string, { success: boolean; error?: Error }>> {\n const results = new Map<string, { success: boolean; error?: Error }>();\n const accounts = await this.getActive();\n\n for (const account of accounts) {\n const ea = account as EmailAccount;\n const accountId = ea.id ?? ea.email ?? 'unknown';\n try {\n await ea.syncFrom(options);\n results.set(accountId, { success: true });\n } catch (error) {\n results.set(accountId, {\n success: false,\n error: error instanceof Error ? error : new Error(String(error)),\n });\n }\n }\n\n return results;\n }\n\n /**\n * Get total unread count across all email accounts\n */\n async getTotalUnreadCount(): Promise<number> {\n const accounts = await this.getActive();\n let total = 0;\n\n for (const account of accounts) {\n total += await (account as EmailAccount).getUnreadCount();\n }\n\n return total;\n }\n\n /**\n * Get email account statistics\n */\n async getEmailStats(): Promise<{\n total: number;\n active: number;\n inactive: number;\n byProvider: Record<ProviderType, number>;\n }> {\n const accounts = (await this.list({})) as EmailAccount[];\n\n const byProvider: Record<ProviderType, number> = {\n smtp: 0,\n imap: 0,\n pop3: 0,\n gmail: 0,\n };\n\n for (const account of accounts) {\n const pt = account.providerType as ProviderType;\n if (pt in byProvider) {\n byProvider[pt]++;\n }\n }\n\n return {\n total: accounts.length,\n active: accounts.filter((a) => a.isActive).length,\n inactive: accounts.filter((a) => !a.isActive).length,\n byProvider,\n };\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Tenant Helper Methods\n // ─────────────────────────────────────────────────────────────────────────\n\n override async findByTenant(tenantId: string): Promise<EmailAccount[]> {\n return this.list({ where: { tenantId } }) as Promise<EmailAccount[]>;\n }\n\n // EmailAccount inherits Account's @TenantScoped recognition (#1596); see\n // EmailCollection for why these route through the raw helpers scoped to the\n // EmailAccount `_meta_type`.\n override async findGlobal(): Promise<EmailAccount[]> {\n return queryGlobal<EmailAccount>(this, EMAIL_ACCOUNT_META_TYPE);\n }\n\n override async findWithGlobals(tenantId: string): Promise<EmailAccount[]> {\n return queryWithGlobals<EmailAccount>(\n this,\n tenantId,\n 'EmailAccount.findWithGlobals',\n EMAIL_ACCOUNT_META_TYPE,\n );\n }\n}\n","/**\n * EmailAttachment - Backward-compatible alias for Attachment\n *\n * @deprecated Use Attachment instead. EmailAttachment is preserved for backward compatibility.\n */\n\nimport type { EmailAttachmentOptions } from '../types';\nimport { Attachment } from './Attachment';\n\n/**\n * @deprecated Use Attachment instead\n */\nexport class EmailAttachment extends Attachment {\n /**\n * Legacy emailId field — maps to messageId\n */\n get emailId(): string {\n return this.messageId;\n }\n\n set emailId(value: string) {\n this.messageId = value;\n }\n\n constructor(options: EmailAttachmentOptions = {}) {\n // Map emailId to messageId for backward compat\n const mappedOptions = {\n ...options,\n messageId: options.emailId || options.messageId || '',\n };\n super(mappedOptions);\n }\n\n /**\n * Get the email this attachment belongs to\n * @deprecated Use getMessage() instead\n */\n async getEmail() {\n if (!this.messageId) return null;\n\n const { EmailCollection } = await import('../collections/EmailCollection');\n const collection = await (EmailCollection as any).create(this.options);\n\n return await collection.get({ id: this.messageId });\n }\n}\n","/**\n * EmailAttachmentCollection - Backward-compatible collection for EmailAttachment\n *\n * @deprecated Use AttachmentCollection instead\n */\n\nimport { EmailAttachment } from '../models/EmailAttachment';\nimport { AttachmentCollection } from './AttachmentCollection';\nimport { queryGlobal, queryWithGlobals } from './tenant-global-queries';\n\n/**\n * @deprecated Use AttachmentCollection instead\n */\nexport class EmailAttachmentCollection extends AttachmentCollection {\n static override readonly _itemClass = EmailAttachment;\n\n /**\n * Get attachments for an email\n * @deprecated Use getByMessage() instead\n */\n async getByEmail(emailId: string): Promise<EmailAttachment[]> {\n return (await this.getByMessage(emailId)) as EmailAttachment[];\n }\n\n /**\n * Get image attachments\n */\n override async getImages(emailId?: string): Promise<EmailAttachment[]> {\n return (await super.getImages(emailId)) as EmailAttachment[];\n }\n\n /**\n * Get PDF attachments\n */\n override async getPdfs(emailId?: string): Promise<EmailAttachment[]> {\n return (await super.getPdfs(emailId)) as EmailAttachment[];\n }\n\n /**\n * Get inline attachments\n */\n override async getInline(emailId: string): Promise<EmailAttachment[]> {\n return (await super.getInline(emailId)) as EmailAttachment[];\n }\n\n /**\n * Get regular attachments\n */\n override async getRegular(emailId: string): Promise<EmailAttachment[]> {\n return (await super.getRegular(emailId)) as EmailAttachment[];\n }\n\n /**\n * Delete all attachments for an email\n * @deprecated Use deleteByMessage() instead\n */\n async deleteByEmail(emailId: string): Promise<number> {\n return await this.deleteByMessage(emailId);\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Tenant Helper Methods\n // ─────────────────────────────────────────────────────────────────────────\n\n override async findByTenant(tenantId: string): Promise<EmailAttachment[]> {\n return this.list({ where: { tenantId } }) as Promise<EmailAttachment[]>;\n }\n\n // EmailAttachment is a CTI subclass of the @TenantScoped Attachment (own\n // `email_attachments` table, no `_meta_type`) and inherits its recognition\n // (#1596); route global / cross-global lookups through the raw helpers.\n override async findGlobal(): Promise<EmailAttachment[]> {\n return queryGlobal<EmailAttachment>(this);\n }\n\n override async findWithGlobals(tenantId: string): Promise<EmailAttachment[]> {\n return queryWithGlobals<EmailAttachment>(\n this,\n tenantId,\n 'EmailAttachment.findWithGlobals',\n );\n }\n}\n","/**\n * Email model - Email message extending the Message STI base\n *\n * Retains all email-specific fields (RFC 822 compliance, folders, etc.)\n * while inheriting common message fields from Message.\n */\n\nimport { smrt } from '@happyvertical/smrt-core';\nimport type { EmailOptions } from '../types';\nimport { Message } from './Message';\n\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class Email extends Message {\n // RFC 822 fields\n messageId = ''; // RFC 822 Message-ID header\n inReplyTo = '';\n\n // Additional recipients\n ccAddresses = '';\n bccAddresses = '';\n replyToAddress = '';\n replyToName = '';\n\n // Email-specific content\n textBody = '';\n htmlBody = '';\n\n // Location\n folderId = '';\n folderPath = '';\n labels = ''; // JSON array (Gmail)\n flags = ''; // JSON array (IMAP)\n\n // Email-specific status flags\n isAnswered = false;\n isDraft = false;\n\n // Raw data\n rawMessage = '';\n headers = ''; // JSON object\n\n constructor(options: EmailOptions = {}) {\n super(options);\n\n if (options.messageId !== undefined) this.messageId = options.messageId;\n if (options.inReplyTo !== undefined) this.inReplyTo = options.inReplyTo;\n if (options.ccAddresses !== undefined)\n this.ccAddresses = options.ccAddresses;\n if (options.bccAddresses !== undefined)\n this.bccAddresses = options.bccAddresses;\n if (options.replyToAddress !== undefined)\n this.replyToAddress = options.replyToAddress;\n if (options.replyToName !== undefined)\n this.replyToName = options.replyToName;\n if (options.textBody !== undefined) this.textBody = options.textBody;\n if (options.htmlBody !== undefined) this.htmlBody = options.htmlBody;\n if (options.folderId !== undefined) this.folderId = options.folderId;\n if (options.folderPath !== undefined) this.folderPath = options.folderPath;\n if (options.labels !== undefined) this.labels = options.labels;\n if (options.flags !== undefined) this.flags = options.flags;\n if (options.isAnswered !== undefined) this.isAnswered = options.isAnswered;\n if (options.isDraft !== undefined) this.isDraft = options.isDraft;\n if (options.rawMessage !== undefined) this.rawMessage = options.rawMessage;\n if (options.headers !== undefined) this.headers = options.headers;\n\n // Populate base body from textBody for unified access\n if (options.textBody && !options.body) {\n this.body = options.textBody;\n }\n }\n\n /**\n * Get CC addresses as parsed array\n */\n getCcAddresses(): Array<{ address: string; name?: string }> {\n if (!this.ccAddresses) return [];\n try {\n return JSON.parse(this.ccAddresses);\n } catch {\n return [];\n }\n }\n\n /**\n * Get BCC addresses as parsed array\n */\n getBccAddresses(): Array<{ address: string; name?: string }> {\n if (!this.bccAddresses) return [];\n try {\n return JSON.parse(this.bccAddresses);\n } catch {\n return [];\n }\n }\n\n /**\n * Get labels as parsed array\n */\n getLabels(): string[] {\n if (!this.labels) return [];\n try {\n return JSON.parse(this.labels);\n } catch {\n return [];\n }\n }\n\n /**\n * Set labels from array\n */\n setLabels(labels: string[]): void {\n this.labels = JSON.stringify(labels);\n }\n\n /**\n * Get flags as parsed array\n */\n getFlags(): string[] {\n if (!this.flags) return [];\n try {\n return JSON.parse(this.flags);\n } catch {\n return [];\n }\n }\n\n /**\n * Set flags from array\n */\n setFlags(flags: string[]): void {\n this.flags = JSON.stringify(flags);\n }\n\n /**\n * Get headers as parsed object\n */\n getHeaders(): Record<string, string | string[]> {\n if (!this.headers) return {};\n try {\n return JSON.parse(this.headers);\n } catch {\n return {};\n }\n }\n\n /**\n * Set headers from object\n */\n setHeaders(headers: Record<string, string | string[]>): void {\n this.headers = JSON.stringify(headers);\n }\n\n /**\n * Get the email account (typed as EmailAccount)\n */\n override async getAccount() {\n if (!this.accountId) return null;\n\n const { EmailAccountCollection } = await import(\n '../collections/EmailAccountCollection'\n );\n const collection = await (EmailAccountCollection as any).create(\n this.options,\n );\n\n return await collection.get({ id: this.accountId });\n }\n\n /**\n * Get the folder\n */\n async getFolder() {\n if (!this.folderId) return null;\n\n const { EmailFolderCollection } = await import(\n '../collections/EmailFolderCollection'\n );\n const collection = await (EmailFolderCollection as any).create(\n this.options,\n );\n\n return await collection.get({ id: this.folderId });\n }\n\n /**\n * Get emails in the same thread\n */\n async getThreadEmails(): Promise<Email[]> {\n if (!this.threadId) return [this];\n\n const { EmailCollection } = await import('../collections/EmailCollection');\n const collection = await (EmailCollection as any).create(this.options);\n\n return await collection.list({ where: { threadId: this.threadId } });\n }\n\n /**\n * Get a short preview of the email body\n */\n override getPreview(maxLength = 200): string {\n const body = this.textBody || this.htmlBody?.replace(/<[^>]*>/g, '') || '';\n if (body.length <= maxLength) return body;\n return `${body.slice(0, maxLength)}...`;\n }\n\n /**\n * Get References header values as array\n */\n getReferences(): string[] {\n const headers = this.getHeaders();\n const refs = headers.references;\n if (!refs) return [];\n if (Array.isArray(refs)) return refs;\n return refs.split(/\\s+/).filter(Boolean);\n }\n\n /**\n * Create a reply to this email with RFC 822 threading\n */\n override createReply(options?: { replyAll?: boolean }): Email {\n const reply = new Email({\n ...this.draftOptions(),\n id: undefined,\n accountId: this.accountId,\n threadId: this.threadId || this.id || undefined,\n subject: this.subject.startsWith('Re:')\n ? this.subject\n : `Re: ${this.subject}`,\n fromAddress: '',\n fromName: '',\n inReplyToMessageId: this.id || undefined,\n sendStatus: 'draft',\n isRead: true,\n isDraft: true,\n date: null,\n createdAt: undefined,\n updatedAt: undefined,\n\n // RFC 822 threading\n inReplyTo: this.messageId,\n\n // To: original sender\n toAddresses: JSON.stringify([\n { address: this.fromAddress, name: this.fromName },\n ]),\n });\n\n // RFC 822 References: original references + original Message-ID\n const refs = [...this.getReferences()];\n if (this.messageId && !refs.includes(this.messageId)) {\n refs.push(this.messageId);\n }\n reply.setHeaders({ references: refs.join(' ') });\n\n // Reply-All: add original To/CC as CC (excluding self)\n if (options?.replyAll) {\n const allRecipients = [\n ...this.getToAddresses(),\n ...this.getCcAddresses(),\n ];\n // Remove original sender (already in To:) and any duplicates\n const seen = new Set([this.fromAddress.toLowerCase()]);\n const ccAddresses = allRecipients.filter((r) => {\n const addr = r.address.toLowerCase();\n if (seen.has(addr)) return false;\n seen.add(addr);\n return true;\n });\n reply.ccAddresses = JSON.stringify(ccAddresses);\n }\n\n reply.body = this.buildQuotedBody();\n reply.textBody = reply.body;\n\n return reply;\n }\n\n /**\n * Create a forward of this email\n */\n override createForward(): Email {\n const forwardBody = this.buildForwardBody();\n\n const forward = new Email({\n ...this.draftOptions(),\n id: undefined,\n accountId: this.accountId,\n threadId: '',\n subject: this.subject.startsWith('Fwd:')\n ? this.subject\n : `Fwd: ${this.subject}`,\n toAddresses: '[]',\n ccAddresses: '[]',\n bccAddresses: '[]',\n fromAddress: '',\n fromName: '',\n body: forwardBody,\n textBody: forwardBody,\n hasAttachments: this.hasAttachments,\n inReplyToMessageId: '',\n inReplyTo: '',\n sendStatus: 'draft',\n isDraft: true,\n isRead: true,\n date: null,\n createdAt: undefined,\n updatedAt: undefined,\n });\n\n return forward;\n }\n\n /**\n * Build email-specific quoted body for replies\n */\n protected override buildQuotedBody(): string {\n const dateStr = this.date ? this.date.toLocaleString() : 'unknown date';\n const from = this.fromName\n ? `${this.fromName} <${this.fromAddress}>`\n : this.fromAddress;\n\n const bodyText = this.textBody || this.body || '';\n const quotedLines = bodyText\n .split('\\n')\n .map((line) => `> ${line}`)\n .join('\\n');\n\n return `\\n\\nOn ${dateStr}, ${from} wrote:\\n${quotedLines}`;\n }\n\n /**\n * Build forwarded message body\n */\n private buildForwardBody(): string {\n const dateStr = this.date ? this.date.toLocaleString() : 'unknown date';\n const from = this.fromName\n ? `${this.fromName} <${this.fromAddress}>`\n : this.fromAddress;\n\n const toStr = this.getToAddresses()\n .map((r) => (r.name ? `${r.name} <${r.address}>` : r.address))\n .join(', ');\n\n const bodyText = this.textBody || this.body || '';\n\n return [\n '',\n '',\n '---------- Forwarded message ----------',\n `From: ${from}`,\n `Date: ${dateStr}`,\n `Subject: ${this.subject}`,\n `To: ${toStr}`,\n '',\n bodyText,\n ].join('\\n');\n }\n}\n","/**\n * EmailCollection - Collection manager for Email objects\n *\n * Extends MessageCollection with email-specific query methods.\n * STI framework auto-filters to Email instances.\n */\n\nimport { Email } from '../models/Email';\nimport type { EmailSearchFilters } from '../types';\nimport { MessageCollection } from './MessageCollection';\nimport { queryGlobal, queryWithGlobals } from './tenant-global-queries';\n\n/**\n * Qualified STI discriminator for Email rows in the shared `messages` table.\n * Raw SQL on this tenant-scoped child collection must scope by `_meta_type` so\n * it never returns sibling Message subtypes (base Message, Tweet, SlackMessage).\n * See `findGlobal` / `findWithGlobals`. (#1596)\n */\nconst EMAIL_META_TYPE = '@happyvertical/smrt-messages:Email';\n\nexport class EmailCollection extends MessageCollection {\n static override readonly _itemClass = Email;\n\n /**\n * Get email by RFC 822 Message-ID\n */\n async getByMessageId(\n accountId: string,\n messageId: string,\n ): Promise<Email | null> {\n const emails = await this.list({\n where: { accountId, messageId },\n limit: 1,\n });\n return (emails[0] as Email) || null;\n }\n\n /**\n * Get emails by account\n */\n async getByAccount(accountId: string): Promise<Email[]> {\n return (await this.list({ where: { accountId } })) as Email[];\n }\n\n /**\n * Get emails by folder\n */\n async getByFolder(folderId: string): Promise<Email[]> {\n return (await this.list({ where: { folderId } })) as Email[];\n }\n\n /**\n * Get emails by thread\n */\n override async getByThread(threadId: string): Promise<Email[]> {\n return (await this.list({ where: { threadId } })) as Email[];\n }\n\n /**\n * Get unread emails\n */\n override async getUnread(accountId?: string): Promise<Email[]> {\n const where: Record<string, any> = { isRead: false };\n if (accountId) {\n where.accountId = accountId;\n }\n return (await this.list({ where })) as Email[];\n }\n\n /**\n * Get flagged emails\n */\n override async getFlagged(accountId?: string): Promise<Email[]> {\n const where: Record<string, any> = { isFlagged: true };\n if (accountId) {\n where.accountId = accountId;\n }\n return (await this.list({ where })) as Email[];\n }\n\n /**\n * Get emails with attachments\n */\n async getWithAttachments(accountId?: string): Promise<Email[]> {\n const where: Record<string, any> = { hasAttachments: true };\n if (accountId) {\n where.accountId = accountId;\n }\n return (await this.list({ where })) as Email[];\n }\n\n /**\n * Get recent emails\n */\n override async getRecent(limit = 20, accountId?: string): Promise<Email[]> {\n const allEmails = (await this.list({\n where: accountId ? { accountId } : undefined,\n })) as Email[];\n\n return allEmails\n .sort((a, b) => {\n const dateA = a.date?.getTime() || 0;\n const dateB = b.date?.getTime() || 0;\n return dateB - dateA;\n })\n .slice(0, limit);\n }\n\n /**\n * Count emails in a folder\n */\n async countByFolder(folderId: string): Promise<number> {\n const emails = await this.list({ where: { folderId } });\n return emails.length;\n }\n\n /**\n * Count unread emails in a folder\n */\n async countUnreadByFolder(folderId: string): Promise<number> {\n const emails = await this.list({ where: { folderId, isRead: false } });\n return emails.length;\n }\n\n /**\n * Count unread emails for an account\n */\n async countUnreadByAccount(accountId: string): Promise<number> {\n const emails = await this.list({ where: { accountId, isRead: false } });\n return emails.length;\n }\n\n /**\n * Search emails with email-specific filters.\n * Alias: `search()` for backward compatibility.\n */\n override async search(\n query: string,\n filters?: EmailSearchFilters,\n ): Promise<Email[]> {\n return this.searchEmails(query, filters);\n }\n\n /**\n * Search emails with email-specific filters\n */\n async searchEmails(\n query: string,\n filters?: EmailSearchFilters,\n ): Promise<Email[]> {\n let emails = (await this.list({})) as Email[];\n\n // Filter by query\n if (query) {\n const lowerQuery = query.toLowerCase();\n emails = emails.filter(\n (e) =>\n e.subject?.toLowerCase().includes(lowerQuery) ||\n e.textBody?.toLowerCase().includes(lowerQuery) ||\n e.fromAddress?.toLowerCase().includes(lowerQuery) ||\n e.fromName?.toLowerCase().includes(lowerQuery),\n );\n }\n\n // Apply filters\n if (filters) {\n if (filters.accountId) {\n emails = emails.filter((e) => e.accountId === filters.accountId);\n }\n if (filters.folderId) {\n emails = emails.filter((e) => e.folderId === filters.folderId);\n }\n if (filters.threadId) {\n emails = emails.filter((e) => e.threadId === filters.threadId);\n }\n if (filters.from) {\n const fromLower = filters.from.toLowerCase();\n emails = emails.filter(\n (e) =>\n e.fromAddress?.toLowerCase().includes(fromLower) ||\n e.fromName?.toLowerCase().includes(fromLower),\n );\n }\n if (filters.to) {\n const toLower = filters.to.toLowerCase();\n emails = emails.filter((e) =>\n e.toAddresses?.toLowerCase().includes(toLower),\n );\n }\n if (filters.subject) {\n const subjectLower = filters.subject.toLowerCase();\n emails = emails.filter((e) =>\n e.subject?.toLowerCase().includes(subjectLower),\n );\n }\n if (filters.isRead !== undefined) {\n emails = emails.filter((e) => e.isRead === filters.isRead);\n }\n if (filters.isFlagged !== undefined) {\n emails = emails.filter((e) => e.isFlagged === filters.isFlagged);\n }\n if (filters.hasAttachments !== undefined) {\n emails = emails.filter(\n (e) => e.hasAttachments === filters.hasAttachments,\n );\n }\n if (filters.sincDate) {\n emails = emails.filter(\n (e) => e.date && e.date >= (filters.sincDate as Date),\n );\n }\n if (filters.beforeDate) {\n emails = emails.filter(\n (e) => e.date && e.date < (filters.beforeDate as Date),\n );\n }\n }\n\n return emails;\n }\n\n /**\n * Mark all emails in a folder as read\n */\n async markFolderRead(folderId: string): Promise<void> {\n const emails = (await this.getUnread()) as Email[];\n const folderEmails = emails.filter((e) => e.folderId === folderId);\n\n for (const email of folderEmails) {\n await email.markRead();\n }\n }\n\n /**\n * Delete emails by folder\n */\n async deleteByFolder(folderId: string): Promise<number> {\n const emails = await this.getByFolder(folderId);\n let count = 0;\n\n for (const email of emails) {\n await email.delete();\n count++;\n }\n\n return count;\n }\n\n /**\n * Get email statistics for an account\n */\n override async getAccountStats(accountId: string): Promise<{\n total: number;\n unread: number;\n flagged: number;\n withAttachments: number;\n byType: Record<string, number>;\n }> {\n const emails = await this.getByAccount(accountId);\n\n return {\n total: emails.length,\n unread: emails.filter((e) => !e.isRead).length,\n flagged: emails.filter((e) => e.isFlagged).length,\n withAttachments: emails.filter((e) => e.hasAttachments).length,\n byType: { Email: emails.length },\n };\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Tenant Helper Methods\n // ─────────────────────────────────────────────────────────────────────────\n\n override async findByTenant(tenantId: string): Promise<Email[]> {\n return this.list({ where: { tenantId } }) as Promise<Email[]>;\n }\n\n // Now that Email inherits Message's @TenantScoped recognition (#1596), an\n // explicit `tenant_id IS NULL` filter via list() throws and unflagged raw SQL\n // is blocked under an active tenant context — so route global / cross-global\n // lookups through the shared raw helpers, scoped to the Email `_meta_type`.\n override async findGlobal(): Promise<Email[]> {\n return queryGlobal<Email>(this, EMAIL_META_TYPE);\n }\n\n override async findWithGlobals(tenantId: string): Promise<Email[]> {\n return queryWithGlobals<Email>(\n this,\n tenantId,\n 'Email.findWithGlobals',\n EMAIL_META_TYPE,\n );\n }\n}\n","/**\n * EmailFolder model - Folder/label tracking\n */\n\nimport { foreignKey, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type { EmailFolderOptions } from '../types';\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class EmailFolder extends SmrtObject {\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n @foreignKey('Account')\n accountId = '';\n name = '';\n path = '';\n delimiter = '/';\n specialUse = ''; // '\\\\Inbox', '\\\\Sent', '\\\\Drafts', etc.\n messageCount = 0;\n unreadCount = 0;\n subscribed = true;\n\n // Timestamps\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: EmailFolderOptions = {}) {\n super(options);\n\n if (options.tenantId !== undefined) this.tenantId = options.tenantId as any;\n if (options.accountId !== undefined) this.accountId = options.accountId;\n if (options.name !== undefined) this.name = options.name;\n if (options.path !== undefined) this.path = options.path;\n if (options.delimiter !== undefined) this.delimiter = options.delimiter;\n if (options.specialUse !== undefined) this.specialUse = options.specialUse;\n if (options.messageCount !== undefined)\n this.messageCount = options.messageCount;\n if (options.unreadCount !== undefined)\n this.unreadCount = options.unreadCount;\n if (options.subscribed !== undefined) this.subscribed = options.subscribed;\n if (options.createdAt) this.createdAt = options.createdAt;\n if (options.updatedAt) this.updatedAt = options.updatedAt;\n }\n\n /**\n * Get the email account\n */\n async getAccount() {\n if (!this.accountId) return null;\n\n const { EmailAccountCollection } = await import(\n '../collections/EmailAccountCollection'\n );\n const collection = await (EmailAccountCollection as any).create(\n this.options,\n );\n\n return await collection.get({ id: this.accountId });\n }\n\n /**\n * Get all emails in this folder\n */\n async getEmails(limit?: number) {\n const { EmailCollection } = await import('../collections/EmailCollection');\n const collection = await (EmailCollection as any).create(this.options);\n\n const options: Record<string, any> = { where: { folderId: this.id } };\n if (limit) {\n options.limit = limit;\n }\n\n return await collection.list(options);\n }\n\n /**\n * Get unread emails in this folder\n */\n async getUnreadEmails(limit?: number) {\n const { EmailCollection } = await import('../collections/EmailCollection');\n const collection = await (EmailCollection as any).create(this.options);\n\n const options: Record<string, any> = {\n where: { folderId: this.id, isRead: false },\n };\n if (limit) {\n options.limit = limit;\n }\n\n return await collection.list(options);\n }\n\n /**\n * Update message counts from database\n */\n async refreshCounts(): Promise<void> {\n const { EmailCollection } = await import('../collections/EmailCollection');\n const collection = await (EmailCollection as any).create(this.options);\n\n this.messageCount = await collection.countByFolder(this.id);\n this.unreadCount = await collection.countUnreadByFolder(this.id);\n this.updatedAt = new Date();\n await this.save();\n }\n\n /**\n * Check if this is the inbox folder\n */\n isInbox(): boolean {\n return this.specialUse === '\\\\Inbox' || this.path.toLowerCase() === 'inbox';\n }\n\n /**\n * Check if this is the sent folder\n */\n isSent(): boolean {\n return this.specialUse === '\\\\Sent' || this.path.toLowerCase() === 'sent';\n }\n\n /**\n * Check if this is the drafts folder\n */\n isDrafts(): boolean {\n return (\n this.specialUse === '\\\\Drafts' || this.path.toLowerCase() === 'drafts'\n );\n }\n\n /**\n * Check if this is the trash folder\n */\n isTrash(): boolean {\n return this.specialUse === '\\\\Trash' || this.path.toLowerCase() === 'trash';\n }\n\n /**\n * Check if this is the spam/junk folder\n */\n isSpam(): boolean {\n return (\n this.specialUse === '\\\\Junk' ||\n this.path.toLowerCase() === 'spam' ||\n this.path.toLowerCase() === 'junk'\n );\n }\n\n /**\n * Check if this is a system folder\n */\n isSystemFolder(): boolean {\n return !!this.specialUse;\n }\n\n /**\n * Subscribe to folder\n */\n async subscribe(): Promise<void> {\n this.subscribed = true;\n this.updatedAt = new Date();\n await this.save();\n }\n\n /**\n * Unsubscribe from folder\n */\n async unsubscribe(): Promise<void> {\n this.subscribed = false;\n this.updatedAt = new Date();\n await this.save();\n }\n}\n","/**\n * EmailFolderCollection - Collection manager for EmailFolder objects\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { EmailFolder } from '../models/EmailFolder';\nimport type { EmailFolderSearchFilters } from '../types';\nimport { queryGlobal, queryWithGlobals } from './tenant-global-queries';\n\nexport class EmailFolderCollection extends SmrtCollection<EmailFolder> {\n static readonly _itemClass = EmailFolder;\n\n /**\n * Get folder by path for an account\n */\n async getByPath(\n accountId: string,\n path: string,\n ): Promise<EmailFolder | null> {\n const folders = await this.list({ where: { accountId, path } });\n return folders[0] || null;\n }\n\n /**\n * Get folders by account\n */\n async getByAccount(accountId: string): Promise<EmailFolder[]> {\n return await this.list({ where: { accountId } });\n }\n\n /**\n * Get inbox folder for an account\n */\n async getInbox(accountId: string): Promise<EmailFolder | null> {\n const folders = await this.getByAccount(accountId);\n return folders.find((f) => f.isInbox()) || null;\n }\n\n /**\n * Get sent folder for an account\n */\n async getSent(accountId: string): Promise<EmailFolder | null> {\n const folders = await this.getByAccount(accountId);\n return folders.find((f) => f.isSent()) || null;\n }\n\n /**\n * Get drafts folder for an account\n */\n async getDrafts(accountId: string): Promise<EmailFolder | null> {\n const folders = await this.getByAccount(accountId);\n return folders.find((f) => f.isDrafts()) || null;\n }\n\n /**\n * Get trash folder for an account\n */\n async getTrash(accountId: string): Promise<EmailFolder | null> {\n const folders = await this.getByAccount(accountId);\n return folders.find((f) => f.isTrash()) || null;\n }\n\n /**\n * Get spam folder for an account\n */\n async getSpam(accountId: string): Promise<EmailFolder | null> {\n const folders = await this.getByAccount(accountId);\n return folders.find((f) => f.isSpam()) || null;\n }\n\n /**\n * Get system folders for an account\n */\n async getSystemFolders(accountId: string): Promise<EmailFolder[]> {\n const folders = await this.getByAccount(accountId);\n return folders.filter((f) => f.isSystemFolder());\n }\n\n /**\n * Get user-created folders for an account\n */\n async getUserFolders(accountId: string): Promise<EmailFolder[]> {\n const folders = await this.getByAccount(accountId);\n return folders.filter((f) => !f.isSystemFolder());\n }\n\n /**\n * Get subscribed folders\n */\n async getSubscribed(accountId?: string): Promise<EmailFolder[]> {\n const where: Record<string, any> = { subscribed: true };\n if (accountId) {\n where.accountId = accountId;\n }\n return await this.list({ where });\n }\n\n /**\n * Get folders with unread messages\n */\n async getWithUnread(accountId?: string): Promise<EmailFolder[]> {\n const folders = accountId\n ? await this.getByAccount(accountId)\n : await this.list({});\n\n return folders.filter((f) => f.unreadCount > 0);\n }\n\n /**\n * Search folders with filters\n */\n async search(\n query: string,\n filters?: EmailFolderSearchFilters,\n ): Promise<EmailFolder[]> {\n let folders = await this.list({});\n\n // Filter by query\n if (query) {\n const lowerQuery = query.toLowerCase();\n folders = folders.filter(\n (f) =>\n f.name?.toLowerCase().includes(lowerQuery) ||\n f.path?.toLowerCase().includes(lowerQuery),\n );\n }\n\n // Apply filters\n if (filters) {\n if (filters.accountId) {\n folders = folders.filter((f) => f.accountId === filters.accountId);\n }\n if (filters.specialUse) {\n folders = folders.filter((f) => f.specialUse === filters.specialUse);\n }\n if (filters.subscribed !== undefined) {\n folders = folders.filter((f) => f.subscribed === filters.subscribed);\n }\n }\n\n return folders;\n }\n\n /**\n * Refresh counts for all folders in an account\n */\n async refreshAllCounts(accountId: string): Promise<void> {\n const folders = await this.getByAccount(accountId);\n\n for (const folder of folders) {\n await folder.refreshCounts();\n }\n }\n\n /**\n * Get folder statistics for an account\n */\n async getAccountStats(accountId: string): Promise<{\n totalFolders: number;\n totalMessages: number;\n totalUnread: number;\n systemFolders: number;\n userFolders: number;\n }> {\n const folders = await this.getByAccount(accountId);\n\n return {\n totalFolders: folders.length,\n totalMessages: folders.reduce((sum, f) => sum + f.messageCount, 0),\n totalUnread: folders.reduce((sum, f) => sum + f.unreadCount, 0),\n systemFolders: folders.filter((f) => f.isSystemFolder()).length,\n userFolders: folders.filter((f) => !f.isSystemFolder()).length,\n };\n }\n\n /**\n * Create standard system folders for an account\n */\n async createSystemFolders(accountId: string): Promise<void> {\n const standardFolders = [\n { name: 'INBOX', path: 'INBOX', specialUse: '\\\\Inbox' },\n { name: 'Sent', path: 'Sent', specialUse: '\\\\Sent' },\n { name: 'Drafts', path: 'Drafts', specialUse: '\\\\Drafts' },\n { name: 'Trash', path: 'Trash', specialUse: '\\\\Trash' },\n { name: 'Spam', path: 'Spam', specialUse: '\\\\Junk' },\n ];\n\n for (const folderData of standardFolders) {\n const existing = await this.getByPath(accountId, folderData.path);\n if (!existing) {\n // Create through the collection so the DB connection is bound; a bare\n // `new EmailFolder(...)` + save() throws \"Database accessed before\n // initialization\" under per-instance DB injection.\n const folder = await this.create({\n accountId,\n ...folderData,\n });\n await folder.save();\n }\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Tenant Helper Methods\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * Find all email folders belonging to a specific tenant\n */\n async findByTenant(tenantId: string): Promise<EmailFolder[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global email folders (no tenant).\n *\n * EmailFolder is @TenantScoped (CTI, own `email_folders` table). Under an\n * active tenant context list({ tenantId: null }) throws and unflagged raw SQL\n * is blocked (#1596); route through the raw helpers.\n */\n async findGlobal(): Promise<EmailFolder[]> {\n return queryGlobal<EmailFolder>(this);\n }\n\n /**\n * Find email folders for a tenant including global folders.\n */\n async findWithGlobals(tenantId: string): Promise<EmailFolder[]> {\n return queryWithGlobals<EmailFolder>(\n this,\n tenantId,\n 'EmailFolder.findWithGlobals',\n );\n }\n}\n","import { SmrtObject, smrt } from '@happyvertical/smrt-core';\n\n/**\n * Blacklist - Block entries for email filtering\n *\n * Supports three pattern types:\n * - email: Exact email address (spam@example.com)\n * - domain: Entire domain (*@spam.com)\n * - regex: Custom regex pattern\n */\n@smrt({\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n cli: true,\n tenantScoped: true,\n})\nexport class Blacklist extends SmrtObject {\n pattern: string = '';\n type: 'email' | 'domain' | 'regex' = 'email';\n reason: string = '';\n autoArchive: boolean = true;\n\n constructor(options: any = {}) {\n super(options);\n\n if (options.pattern !== undefined) {\n this.pattern = options.pattern;\n }\n if (options.type !== undefined) {\n this.type = options.type;\n }\n }\n\n /**\n * Check if an email address matches this blacklist entry\n */\n matches(email: string): boolean {\n const normalizedEmail = email.toLowerCase().trim();\n\n switch (this.type) {\n case 'email':\n return normalizedEmail === this.pattern.toLowerCase().trim();\n\n case 'domain': {\n const domain = normalizedEmail.split('@')[1];\n return domain === this.pattern.toLowerCase().trim();\n }\n\n case 'regex': {\n const pattern = this.pattern.trim();\n if (!pattern) {\n return false;\n }\n try {\n const regex = new RegExp(pattern, 'i');\n return regex.test(normalizedEmail);\n } catch {\n return false;\n }\n }\n\n default:\n return false;\n }\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { Blacklist } from '../models/Blacklist.js';\n\nexport class BlacklistCollection extends SmrtCollection<Blacklist> {\n static readonly _itemClass = Blacklist;\n\n /**\n * Check if an email is blacklisted\n */\n async isBlacklisted(email: string): Promise<boolean> {\n const entries = await this.list({});\n\n for (const entry of entries) {\n if (entry.matches(email)) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Get the matching blacklist entry for an email\n */\n async getMatchingEntry(email: string): Promise<Blacklist | null> {\n const entries = await this.list({});\n\n for (const entry of entries) {\n if (entry.matches(email)) {\n return entry;\n }\n }\n\n return null;\n }\n}\n","import { SmrtObject, smrt } from '@happyvertical/smrt-core';\n\n/**\n * Whitelist - Allow-only entries for email filtering\n *\n * Supports three pattern types:\n * - email: Exact email address (user@example.com)\n * - domain: Entire domain (*@example.com)\n * - regex: Custom regex pattern\n */\n@smrt({\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n cli: true,\n tenantScoped: true,\n})\nexport class Whitelist extends SmrtObject {\n pattern: string = '';\n type: 'email' | 'domain' | 'regex' = 'email';\n category: string | null = null;\n description: string = '';\n\n constructor(options: any = {}) {\n super(options);\n\n if (options.pattern !== undefined) {\n this.pattern = options.pattern;\n }\n if (options.type !== undefined) {\n this.type = options.type;\n }\n }\n\n /**\n * Check if an email address matches this whitelist entry\n */\n matches(email: string): boolean {\n const normalizedEmail = email.toLowerCase().trim();\n\n switch (this.type) {\n case 'email':\n return normalizedEmail === this.pattern.toLowerCase().trim();\n\n case 'domain': {\n const domain = normalizedEmail.split('@')[1];\n return domain === this.pattern.toLowerCase().trim();\n }\n\n case 'regex': {\n const pattern = this.pattern.trim();\n if (!pattern) {\n return false;\n }\n try {\n const regex = new RegExp(pattern, 'i');\n return regex.test(normalizedEmail);\n } catch {\n return false;\n }\n }\n\n default:\n return false;\n }\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { Whitelist } from '../models/Whitelist.js';\n\nexport class WhitelistCollection extends SmrtCollection<Whitelist> {\n static readonly _itemClass = Whitelist;\n\n /**\n * Check if an email is whitelisted for a specific category\n */\n async isWhitelisted(email: string, category?: string): Promise<boolean> {\n const entries = await this.list({});\n\n for (const entry of entries) {\n if (!entry.matches(email)) {\n continue;\n }\n\n if (!category) {\n return true;\n }\n\n if (entry.category === category || entry.category === null) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Get the matching whitelist entry for an email\n */\n async getMatchingEntry(email: string): Promise<Whitelist | null> {\n const entries = await this.list({});\n\n for (const entry of entries) {\n if (entry.matches(email)) {\n return entry;\n }\n }\n\n return null;\n }\n\n /**\n * Get whitelist entries by category\n */\n async getByCategory(category: string): Promise<Whitelist[]> {\n return await this.list({\n where: { category },\n });\n }\n}\n","/**\n * SlackAccount model - Slack workspace account extending the Account STI base\n */\n\nimport { smrt } from '@happyvertical/smrt-core';\nimport type { MessageSenderInterface, SlackAccountOptions } from '../types';\nimport { Account } from './Account';\n\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class SlackAccount extends Account {\n workspaceId = '';\n workspaceName = '';\n botUserId = '';\n\n constructor(options: SlackAccountOptions = {}) {\n super(options);\n\n if (options.workspaceId !== undefined)\n this.workspaceId = options.workspaceId;\n if (options.workspaceName !== undefined)\n this.workspaceName = options.workspaceName;\n if (options.botUserId !== undefined) this.botUserId = options.botUserId;\n\n // Default provider type\n if (!this.providerType) this.providerType = 'slack';\n }\n\n /**\n * Create a sender for this Slack account\n */\n override async createSender(): Promise<MessageSenderInterface> {\n const { SlackSender } = await import('../senders/SlackSender');\n return new SlackSender(this);\n }\n}\n","/**\n * SlackMessage model - Slack message extending the Message STI base\n */\n\nimport { smrt } from '@happyvertical/smrt-core';\nimport type { SlackMessageOptions } from '../types';\nimport { Message } from './Message';\n\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get', 'create'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class SlackMessage extends Message {\n channelId = '';\n channelName = '';\n slackTs = ''; // Slack message timestamp (unique ID)\n slackThreadTs = ''; // Thread parent timestamp\n reactions = ''; // JSON array of {name, count, users[]}\n isEdited = false;\n messageType = ''; // 'message', 'bot_message', etc.\n blocks = ''; // JSON - Slack Block Kit blocks\n\n constructor(options: SlackMessageOptions = {}) {\n super(options);\n\n if (options.channelId !== undefined) this.channelId = options.channelId;\n if (options.channelName !== undefined)\n this.channelName = options.channelName;\n if (options.slackTs !== undefined) this.slackTs = options.slackTs;\n if (options.slackThreadTs !== undefined)\n this.slackThreadTs = options.slackThreadTs;\n if (options.reactions !== undefined) this.reactions = options.reactions;\n if (options.isEdited !== undefined) this.isEdited = options.isEdited;\n if (options.messageType !== undefined)\n this.messageType = options.messageType;\n if (options.blocks !== undefined) this.blocks = options.blocks;\n }\n\n /**\n * Get reactions as parsed array\n */\n getReactions(): Array<{ name: string; count: number; users?: string[] }> {\n if (!this.reactions) return [];\n try {\n return JSON.parse(this.reactions);\n } catch {\n return [];\n }\n }\n\n /**\n * Get blocks as parsed array\n */\n getBlocks(): any[] {\n if (!this.blocks) return [];\n try {\n return JSON.parse(this.blocks);\n } catch {\n return [];\n }\n }\n\n /**\n * Check if message is in a thread\n */\n isInThread(): boolean {\n return !!this.slackThreadTs && this.slackThreadTs !== this.slackTs;\n }\n\n /**\n * Get total reaction count\n */\n getTotalReactions(): number {\n return this.getReactions().reduce((sum, r) => sum + r.count, 0);\n }\n}\n","/**\n * Tweet model - Twitter/X message extending the Message STI base\n */\n\nimport { smrt } from '@happyvertical/smrt-core';\nimport type { TweetOptions } from '../types';\nimport { Message } from './Message';\n\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get', 'create'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class Tweet extends Message {\n tweetId = '';\n retweetCount = 0;\n likeCount = 0;\n replyCount = 0;\n isRetweet = false;\n isReply = false;\n mediaUrls = ''; // JSON array\n hashtags = ''; // JSON array\n mentions = ''; // JSON array\n\n constructor(options: TweetOptions = {}) {\n super(options);\n\n if (options.tweetId !== undefined) this.tweetId = options.tweetId;\n if (options.retweetCount !== undefined)\n this.retweetCount = options.retweetCount;\n if (options.likeCount !== undefined) this.likeCount = options.likeCount;\n if (options.replyCount !== undefined) this.replyCount = options.replyCount;\n if (options.isRetweet !== undefined) this.isRetweet = options.isRetweet;\n if (options.isReply !== undefined) this.isReply = options.isReply;\n if (options.mediaUrls !== undefined) this.mediaUrls = options.mediaUrls;\n if (options.hashtags !== undefined) this.hashtags = options.hashtags;\n if (options.mentions !== undefined) this.mentions = options.mentions;\n }\n\n /**\n * Get media URLs as parsed array\n */\n getMediaUrls(): string[] {\n if (!this.mediaUrls) return [];\n try {\n return JSON.parse(this.mediaUrls);\n } catch {\n return [];\n }\n }\n\n /**\n * Get hashtags as parsed array\n */\n getHashtags(): string[] {\n if (!this.hashtags) return [];\n try {\n return JSON.parse(this.hashtags);\n } catch {\n return [];\n }\n }\n\n /**\n * Get mentions as parsed array\n */\n getMentions(): string[] {\n if (!this.mentions) return [];\n try {\n return JSON.parse(this.mentions);\n } catch {\n return [];\n }\n }\n\n /**\n * Get total engagement count\n */\n getEngagement(): number {\n return this.retweetCount + this.likeCount + this.replyCount;\n }\n}\n","/**\n * TwitterAccount model - Twitter/X account extending the Account STI base\n */\n\nimport { smrt } from '@happyvertical/smrt-core';\nimport type { MessageSenderInterface, TwitterAccountOptions } from '../types';\nimport { Account } from './Account';\n\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class TwitterAccount extends Account {\n handle = '';\n twitterUserId = '';\n\n constructor(options: TwitterAccountOptions = {}) {\n super(options);\n\n if (options.handle !== undefined) this.handle = options.handle;\n if (options.twitterUserId !== undefined)\n this.twitterUserId = options.twitterUserId;\n\n // Default provider type\n if (!this.providerType) this.providerType = 'twitter';\n }\n\n /**\n * Create a sender for this Twitter account\n */\n override async createSender(): Promise<MessageSenderInterface> {\n const { TweetSender } = await import('../senders/TweetSender');\n return new TweetSender(this);\n }\n}\n","/**\n * EmailSender — sends email messages via the SDK EmailClient\n */\n\nimport type { EmailClient } from '@happyvertical/email';\nimport type { Email } from '../models/Email';\nimport type { EmailAccount } from '../models/EmailAccount';\nimport type {\n MessageSenderInterface,\n MessageSendResult,\n SendMessageOptions,\n} from '../types';\n\nexport class EmailSender implements MessageSenderInterface {\n readonly providerType = 'email';\n private client: EmailClient;\n private account: EmailAccount;\n\n constructor(client: EmailClient, account: EmailAccount) {\n this.client = client;\n this.account = account;\n }\n\n isReady(): boolean {\n return this.client.isConnected();\n }\n\n async send(\n message: Email,\n _options?: SendMessageOptions,\n ): Promise<MessageSendResult> {\n const toAddresses = message.getToAddresses();\n const ccAddresses = message.getCcAddresses();\n const bccAddresses = message.getBccAddresses();\n\n const emailMessage = {\n from: {\n name: message.fromName || this.account.name,\n address: message.fromAddress || this.account.email,\n },\n to: toAddresses.map((r) => ({\n name: r.name,\n address: r.address,\n })),\n cc:\n ccAddresses.length > 0\n ? ccAddresses.map((r) => ({ name: r.name, address: r.address }))\n : undefined,\n bcc:\n bccAddresses.length > 0\n ? bccAddresses.map((r) => ({ name: r.name, address: r.address }))\n : undefined,\n subject: message.subject,\n text: message.textBody || message.body,\n html: message.htmlBody || undefined,\n inReplyTo: message.inReplyTo || undefined,\n };\n\n try {\n const result = await this.client.send(emailMessage);\n\n return {\n success: true,\n providerMessageId: result.messageId,\n accepted: result.accepted,\n rejected: result.rejected,\n providerResponse: { response: result.response },\n sentAt: new Date(),\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n sentAt: new Date(),\n };\n }\n }\n}\n","/**\n * SlackSender — sends Slack messages via the SDK MessageClient\n */\n\nimport type { SlackAccount } from '../models/SlackAccount';\nimport type { SlackMessage } from '../models/SlackMessage';\nimport type {\n MessageSenderInterface,\n MessageSendResult,\n SendMessageOptions,\n} from '../types';\n\nexport class SlackSender implements MessageSenderInterface {\n readonly providerType = 'slack';\n private account: SlackAccount;\n\n constructor(account: SlackAccount) {\n this.account = account;\n }\n\n isReady(): boolean {\n return this.account.isActive;\n }\n\n async send(\n message: SlackMessage,\n _options?: SendMessageOptions,\n ): Promise<MessageSendResult> {\n const { getMessageClient } = await import('@happyvertical/messages');\n\n const credentials = await this.account.getCredentials();\n if (!credentials?.botToken) {\n return {\n success: false,\n error: 'No botToken found in account credentials',\n sentAt: new Date(),\n };\n }\n\n const client = await getMessageClient({\n type: 'slack',\n botToken: credentials.botToken,\n });\n\n try {\n await client.connect();\n\n const result = await client.send(\n {\n from: { id: this.account.botUserId, name: this.account.name },\n channelId: message.channelId,\n content: message.body,\n },\n {\n replyTo: message.slackThreadTs || undefined,\n },\n );\n\n await client.disconnect();\n\n return {\n success: result.success,\n providerMessageId: result.messageId,\n providerResponse: result.providerResponse,\n sentAt: result.timestamp,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n sentAt: new Date(),\n };\n }\n }\n}\n","/**\n * TweetSender — sends tweets via the SDK MessageClient\n */\n\nimport type { Tweet } from '../models/Tweet';\nimport type { TwitterAccount } from '../models/TwitterAccount';\nimport type {\n MessageSenderInterface,\n MessageSendResult,\n SendMessageOptions,\n} from '../types';\n\nexport class TweetSender implements MessageSenderInterface {\n readonly providerType = 'twitter';\n private account: TwitterAccount;\n\n constructor(account: TwitterAccount) {\n this.account = account;\n }\n\n isReady(): boolean {\n return this.account.isActive;\n }\n\n async send(\n message: Tweet,\n _options?: SendMessageOptions,\n ): Promise<MessageSendResult> {\n const { getMessageClient } = await import('@happyvertical/messages');\n\n const credentials = await this.account.getCredentials();\n if (\n !credentials?.apiKey ||\n !credentials?.apiSecret ||\n !credentials?.accessToken ||\n !credentials?.accessSecret\n ) {\n return {\n success: false,\n error: 'Missing Twitter API credentials in account',\n sentAt: new Date(),\n };\n }\n\n const client = await getMessageClient({\n type: 'twitter',\n apiKey: credentials.apiKey,\n apiSecret: credentials.apiSecret,\n accessToken: credentials.accessToken,\n accessSecret: credentials.accessSecret,\n });\n\n try {\n const sendOptions: Record<string, string> = {};\n if (message.isReply && message.inReplyToMessageId) {\n sendOptions.replyTo = message.inReplyToMessageId;\n }\n\n const result = await client.send(\n {\n from: { id: this.account.twitterUserId, name: this.account.handle },\n content: message.body,\n },\n sendOptions.replyTo ? { replyTo: sendOptions.replyTo } : undefined,\n );\n\n return {\n success: result.success,\n providerMessageId: result.messageId,\n providerResponse: result.providerResponse,\n sentAt: result.timestamp,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n sentAt: new Date(),\n };\n }\n }\n}\n"],"names":["__decorateClass","tenantId","MessageCollection","AccountCollection","AttachmentCollection","EmailSender","EmailCollection","EmailFolderCollection","EmailFolder","Email","EmailAccountCollection","SlackSender","TweetSender"],"mappings":"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"}