From edba47aed86a7ad86e26299214a5e862f7dcd918 Mon Sep 17 00:00:00 2001 From: ItzCrazyKns <95534749+ItzCrazyKns@users.noreply.github.com> Date: Fri, 26 Dec 2025 14:51:24 +0530 Subject: [PATCH] feat(db): add migration scripts --- drizzle/0002_daffy_wrecker.sql | 16 +--- src/lib/db/migrate.ts | 155 +++++++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+), 15 deletions(-) diff --git a/drizzle/0002_daffy_wrecker.sql b/drizzle/0002_daffy_wrecker.sql index 78b66854..1520a657 100644 --- a/drizzle/0002_daffy_wrecker.sql +++ b/drizzle/0002_daffy_wrecker.sql @@ -1,15 +1 @@ -PRAGMA foreign_keys=OFF;--> statement-breakpoint -CREATE TABLE `__new_messages` ( - `id` integer PRIMARY KEY NOT NULL, - `messageId` text NOT NULL, - `chatId` text NOT NULL, - `backendId` text NOT NULL, - `query` text NOT NULL, - `createdAt` text NOT NULL, - `responseBlocks` text DEFAULT '[]', - `status` text DEFAULT 'answering' -); ---> statement-breakpoint -DROP TABLE `messages`;--> statement-breakpoint -ALTER TABLE `__new_messages` RENAME TO `messages`;--> statement-breakpoint -PRAGMA foreign_keys=ON; \ No newline at end of file +/* do nothing */ \ No newline at end of file diff --git a/src/lib/db/migrate.ts b/src/lib/db/migrate.ts index 5e2c3743..e0efb7c9 100644 --- a/src/lib/db/migrate.ts +++ b/src/lib/db/migrate.ts @@ -45,6 +45,7 @@ fs.readdirSync(migrationsFolder) const already = db .prepare('SELECT 1 FROM ran_migrations WHERE name = ?') .get(migrationName); + if (already) { console.log(`Skipping already-applied migration: ${file}`); return; @@ -113,6 +114,160 @@ fs.readdirSync(migrationsFolder) db.exec('DROP TABLE messages;'); db.exec('ALTER TABLE messages_with_sources RENAME TO messages;'); + } else if (migrationName === '0002') { + /* Migrate chat */ + db.exec(` + CREATE TABLE IF NOT EXISTS chats_new ( + id TEXT PRIMARY KEY, + title TEXT NOT NULL, + createdAt TEXT NOT NULL, + sources TEXT DEFAULT '[]', + files TEXT DEFAULT '[]' + ); + `); + + const chats = db + .prepare('SELECT id, title, createdAt, files FROM chats') + .all(); + + const insertChat = db.prepare(` + INSERT INTO chats_new (id, title, createdAt, sources, files) + VALUES (?, ?, ?, ?, ?) + `); + + chats.forEach((chat: any) => { + let files = chat.files; + while (typeof files === 'string') { + files = JSON.parse(files || '[]'); + } + + insertChat.run( + chat.id, + chat.title, + chat.createdAt, + '["web"]', + JSON.stringify(files), + ); + }); + + db.exec('DROP TABLE chats;'); + db.exec('ALTER TABLE chats_new RENAME TO chats;'); + + /* Migrate messages */ + + db.exec(` + CREATE TABLE IF NOT EXISTS messages_new ( + id INTEGER PRIMARY KEY, + messageId TEXT NOT NULL, + chatId TEXT NOT NULL, + backendId TEXT NOT NULL, + query TEXT NOT NULL, + createdAt TEXT NOT NULL, + responseBlocks TEXT DEFAULT '[]', + status TEXT DEFAULT 'answering' + ); + `); + + const messages = db + .prepare( + 'SELECT id, messageId, chatId, type, content, createdAt, sources FROM messages ORDER BY id ASC', + ) + .all(); + + const insertMessage = db.prepare(` + INSERT INTO messages_new (messageId, chatId, backendId, query, createdAt, responseBlocks, status) + VALUES (?, ?, ?, ?, ?, ?, ?) + `); + + let currentMessageData: { + sources?: any[]; + response?: string; + query?: string; + messageId?: string; + chatId?: string; + createdAt?: string; + } = {}; + let lastCompleted = true; + + messages.forEach((msg: any) => { + if (msg.type === 'user' && lastCompleted) { + currentMessageData = {}; + currentMessageData.messageId = msg.messageId; + currentMessageData.chatId = msg.chatId; + currentMessageData.query = msg.content; + currentMessageData.createdAt = msg.createdAt; + lastCompleted = false; + } else if (msg.type === 'source' && !lastCompleted) { + let sources = msg.sources; + + while (typeof sources === 'string') { + sources = JSON.parse(sources || '[]'); + } + + currentMessageData.sources = sources; + } else if (msg.type === 'assistant' && !lastCompleted) { + currentMessageData.response = msg.content; + insertMessage.run( + currentMessageData.messageId, + currentMessageData.chatId, + `${currentMessageData.messageId}-backend`, + currentMessageData.query, + currentMessageData.createdAt, + JSON.stringify([ + { + id: crypto.randomUUID(), + type: 'text', + data: currentMessageData.response || '', + }, + ...(currentMessageData.sources && + currentMessageData.sources.length > 0 + ? [ + { + id: crypto.randomUUID(), + type: 'source', + data: currentMessageData.sources, + }, + ] + : []), + ]), + 'completed', + ); + + lastCompleted = true; + } else if (msg.type === 'user' && !lastCompleted) { + /* Message wasn't completed so we'll just create the record with empty response */ + insertMessage.run( + currentMessageData.messageId, + currentMessageData.chatId, + `${currentMessageData.messageId}-backend`, + currentMessageData.query, + currentMessageData.createdAt, + JSON.stringify([ + { + id: crypto.randomUUID(), + type: 'text', + data: '', + }, + ...(currentMessageData.sources && + currentMessageData.sources.length > 0 + ? [ + { + id: crypto.randomUUID(), + type: 'source', + data: currentMessageData.sources, + }, + ] + : []), + ]), + 'completed', + ); + + lastCompleted = true; + } + }); + + db.exec('DROP TABLE messages;'); + db.exec('ALTER TABLE messages_new RENAME TO messages;'); } else { // Execute each statement separately statements.forEach((stmt) => {