export function initializeAttachments(db) { db.exec(` CREATE TABLE IF NOT EXISTS attachments ( id TEXT PRIMARY KEY, username TEXT NOT NULL REFERENCES users(username) ON DELETE CASCADE ON UPDATE CASCADE, original_name TEXT NOT NULL, storage_key TEXT NOT NULL UNIQUE, mime_type TEXT NOT NULL, size_bytes INTEGER NOT NULL, width INTEGER NOT NULL, height INTEGER NOT NULL, status TEXT NOT NULL DEFAULT 'temporary' CHECK(status IN ('temporary','attached')), created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, vision_model TEXT, vision_analysis TEXT, vision_analyzed_at TEXT ); CREATE TABLE IF NOT EXISTS message_attachments ( message_id INTEGER NOT NULL REFERENCES chat_messages(id) ON DELETE CASCADE, attachment_id TEXT NOT NULL REFERENCES attachments(id) ON DELETE CASCADE, position INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(message_id, attachment_id) ); CREATE INDEX IF NOT EXISTS attachment_references ON message_attachments(attachment_id); CREATE TABLE IF NOT EXISTS upload_deletions (storage_key TEXT PRIMARY KEY); CREATE TRIGGER IF NOT EXISTS release_message_attachment AFTER DELETE ON message_attachments BEGIN DELETE FROM attachments WHERE id = OLD.attachment_id AND status = 'attached' AND NOT EXISTS (SELECT 1 FROM message_attachments WHERE attachment_id = OLD.attachment_id); END; CREATE TRIGGER IF NOT EXISTS queue_attachment_file_delete AFTER DELETE ON attachments BEGIN INSERT OR IGNORE INTO upload_deletions(storage_key) VALUES(OLD.storage_key); END; `); } export const attachmentMetadata = (row) => ({ id: row.id, type: "image", originalName: row.original_name, mimeType: row.mime_type, sizeBytes: row.size_bytes, width: row.width, height: row.height });