All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 5s
110 lines
3.4 KiB
TypeScript
110 lines
3.4 KiB
TypeScript
import Database from 'better-sqlite3';
|
|
import { drizzle as sqliteDrizzle } from 'drizzle-orm/better-sqlite3';
|
|
import { drizzle as postgresDrizzle } from 'drizzle-orm/postgres-js';
|
|
import postgres from 'postgres';
|
|
import { words, examples, tags, wordTags, seeAlso } from '../src/lib/db/schema';
|
|
import 'dotenv/config';
|
|
|
|
const connectionString = process.env.DATABASE_URL || '';
|
|
|
|
if (!connectionString) {
|
|
console.error('DATABASE_URL environment variable is required');
|
|
process.exit(1);
|
|
}
|
|
|
|
async function migrate() {
|
|
console.log('Starting SQLite to PostgreSQL migration...\n');
|
|
|
|
// Connect to SQLite
|
|
const sqlite = new Database('./data.db');
|
|
const sqliteDb = sqliteDrizzle(sqlite);
|
|
|
|
// Connect to PostgreSQL
|
|
const pgClient = postgres(connectionString);
|
|
const pgDb = postgresDrizzle(pgClient, { schema: { words, examples, tags, wordTags, seeAlso } });
|
|
|
|
try {
|
|
// Migrate tags first
|
|
console.log('Migrating tags...');
|
|
const sqliteTags = sqlite.prepare('SELECT * FROM tags').all() as any[];
|
|
|
|
for (const tag of sqliteTags) {
|
|
await pgDb.insert(tags).values({
|
|
name: tag.name,
|
|
description: tag.description,
|
|
});
|
|
}
|
|
console.log(`✅ Migrated ${sqliteTags.length} tags\n`);
|
|
|
|
// Get tag ID mapping (SQLite ID -> PostgreSQL ID)
|
|
const pgTags = await pgDb.select().from(tags);
|
|
const tagIdMap = new Map<number, number>();
|
|
for (let i = 0; i < sqliteTags.length; i++) {
|
|
const sqliteTag = sqliteTags[i];
|
|
const pgTag = pgTags.find(t => t.name === sqliteTag.name);
|
|
if (pgTag) {
|
|
tagIdMap.set(sqliteTag.id, pgTag.id);
|
|
}
|
|
}
|
|
|
|
// Migrate words
|
|
console.log('Migrating words...');
|
|
const sqliteWords = sqlite.prepare('SELECT * FROM words').all() as any[];
|
|
|
|
for (const word of sqliteWords) {
|
|
const [insertedWord] = await pgDb.insert(words).values({
|
|
hindi: word.hindi,
|
|
english: word.english,
|
|
type: word.type,
|
|
gender: word.gender,
|
|
note: word.note,
|
|
}).returning();
|
|
|
|
// Migrate word_tags associations
|
|
const wordTagsData = sqlite.prepare('SELECT * FROM word_tags WHERE word_id = ?').all(word.id) as any[];
|
|
for (const wt of wordTagsData) {
|
|
const newTagId = tagIdMap.get(wt.tag_id);
|
|
if (newTagId) {
|
|
await pgDb.insert(wordTags).values({
|
|
wordId: insertedWord.id,
|
|
tagId: newTagId,
|
|
});
|
|
}
|
|
}
|
|
|
|
// Migrate examples
|
|
const examplesData = sqlite.prepare('SELECT * FROM examples WHERE word_id = ?').all(word.id) as any[];
|
|
for (const example of examplesData) {
|
|
await pgDb.insert(examples).values({
|
|
wordId: insertedWord.id,
|
|
hindi: example.hindi,
|
|
english: example.english,
|
|
note: example.note,
|
|
});
|
|
}
|
|
|
|
// Migrate see_also
|
|
const seeAlsoData = sqlite.prepare('SELECT * FROM see_also WHERE word_id = ?').all(word.id) as any[];
|
|
for (const sa of seeAlsoData) {
|
|
await pgDb.insert(seeAlso).values({
|
|
wordId: insertedWord.id,
|
|
reference: sa.reference,
|
|
note: sa.note,
|
|
});
|
|
}
|
|
}
|
|
console.log(`✅ Migrated ${sqliteWords.length} words with all relations\n`);
|
|
|
|
console.log('Migration complete! 🎉');
|
|
|
|
} catch (error) {
|
|
console.error('Migration failed:', error);
|
|
process.exit(1);
|
|
} finally {
|
|
sqlite.close();
|
|
await pgClient.end();
|
|
}
|
|
}
|
|
|
|
migrate();
|