mirror of
https://github.com/ItzCrazyKns/Perplexica.git
synced 2025-10-20 22:38:14 +00:00
123 lines
3.5 KiB
TypeScript
123 lines
3.5 KiB
TypeScript
import Database from 'better-sqlite3';
|
|
import path from 'path';
|
|
import fs from 'fs';
|
|
|
|
const DATA_DIR = process.env.DATA_DIR || process.cwd();
|
|
const dbPath = path.join(DATA_DIR, './data/db.sqlite');
|
|
|
|
const db = new Database(dbPath);
|
|
|
|
const migrationsFolder = path.join(DATA_DIR, 'drizzle');
|
|
|
|
db.exec(`
|
|
CREATE TABLE IF NOT EXISTS ran_migrations (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
name TEXT NOT NULL UNIQUE,
|
|
run_on DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
`);
|
|
|
|
function sanitizeSql(content: string) {
|
|
return content
|
|
.split(/\r?\n/)
|
|
.filter(
|
|
(l) => !l.trim().startsWith('-->') && !l.includes('statement-breakpoint'),
|
|
)
|
|
.join('\n');
|
|
}
|
|
|
|
fs.readdirSync(migrationsFolder)
|
|
.filter((f) => f.endsWith('.sql'))
|
|
.sort()
|
|
.forEach((file) => {
|
|
const filePath = path.join(migrationsFolder, file);
|
|
let content = fs.readFileSync(filePath, 'utf-8');
|
|
content = sanitizeSql(content);
|
|
|
|
const migrationName = file.split('_')[0] || file;
|
|
|
|
const already = db
|
|
.prepare('SELECT 1 FROM ran_migrations WHERE name = ?')
|
|
.get(migrationName);
|
|
if (already) {
|
|
console.log(`Skipping already-applied migration: ${file}`);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
if (migrationName === '0001') {
|
|
const messages = db
|
|
.prepare(
|
|
'SELECT id, type, metadata, content, chatId, messageId FROM messages',
|
|
)
|
|
.all();
|
|
|
|
db.exec(`
|
|
CREATE TABLE IF NOT EXISTS messages_with_sources (
|
|
id INTEGER PRIMARY KEY,
|
|
type TEXT NOT NULL,
|
|
chatId TEXT NOT NULL,
|
|
createdAt TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
messageId TEXT NOT NULL,
|
|
content TEXT,
|
|
sources TEXT DEFAULT '[]'
|
|
);
|
|
`);
|
|
|
|
const insertMessage = db.prepare(`
|
|
INSERT INTO messages_with_sources (type, chatId, createdAt, messageId, content, sources)
|
|
VALUES (?, ?, ?, ?, ?, ?)
|
|
`);
|
|
|
|
messages.forEach((msg: any) => {
|
|
while (typeof msg.metadata === 'string') {
|
|
msg.metadata = JSON.parse(msg.metadata || '{}');
|
|
}
|
|
if (msg.type === 'user') {
|
|
insertMessage.run(
|
|
'user',
|
|
msg.chatId,
|
|
msg.metadata['createdAt'],
|
|
msg.messageId,
|
|
msg.content,
|
|
'[]',
|
|
);
|
|
} else if (msg.type === 'assistant') {
|
|
insertMessage.run(
|
|
'assistant',
|
|
msg.chatId,
|
|
msg.metadata['createdAt'],
|
|
msg.messageId,
|
|
msg.content,
|
|
'[]',
|
|
);
|
|
const sources = msg.metadata['sources'] || '[]';
|
|
if (sources && sources.length > 0) {
|
|
insertMessage.run(
|
|
'source',
|
|
msg.chatId,
|
|
msg.metadata['createdAt'],
|
|
`${msg.messageId}-source`,
|
|
'',
|
|
JSON.stringify(sources),
|
|
);
|
|
}
|
|
}
|
|
});
|
|
|
|
db.exec('DROP TABLE messages;');
|
|
db.exec('ALTER TABLE messages_with_sources RENAME TO messages;');
|
|
} else {
|
|
db.exec(content);
|
|
}
|
|
|
|
db.prepare('INSERT OR IGNORE INTO ran_migrations (name) VALUES (?)').run(
|
|
migrationName,
|
|
);
|
|
console.log(`Applied migration: ${file}`);
|
|
} catch (err) {
|
|
console.error(`Failed to apply migration ${file}:`, err);
|
|
throw err;
|
|
}
|
|
});
|