import { defineNuxtModule } from '@nuxt/kit' import { Database } from "bun:sqlite"; interface Schema { type: string; name: string; tbl_name: string; sql: string; } interface Structure { cid: number; name: string; type: string; [key: string]: number | string | null; } export default defineNuxtModule({ setup (options, nuxt) { nuxt.hook('build:done', () => { console.log("Building database"); const template = new Database(nuxt.options.runtimeConfig.templateFile); const schema = template.query(`SELECT * FROM sqlite_schema WHERE type = 'table'`).all() as Schema[]; const structure = template.query(`SELECT * FROM pragma_table_info(?1)`); const db = new Database(nuxt.options.runtimeConfig.dbFile); db.exec(`PRAGMA foreign_keys = OFF; PRAGMA defer_foreign_keys = OFF;`); const oldSchema = db.query(`SELECT * FROM sqlite_schema WHERE type = 'table'`).all() as Schema[]; const oldStructure = db.query(`SELECT * FROM pragma_table_info(?1)`); (db.transaction((tables: Schema[], oldTables: Schema[]) => { for(const table of tables) { const oldIdx = oldTables.findIndex(e => e.name === table.name); if(table.name === 'sqlite_sequence') { oldTables.splice(oldIdx, 1); continue; } const columns = structure.all(table.name) as Structure[]; const oldColumns = oldStructure.all(table.name) as Structure[]; if(oldIdx !== -1) { oldTables.splice(oldIdx, 1); const filteredColumns = oldColumns.filter(e => columns.find(f => e.name === f.name)).map(e => `"${e.name}"`).join(', ') db.exec(table.sql.replace(`CREATE TABLE "${table.name}"`, `CREATE TABLE "${table.name}_new"`)); db.exec(`INSERT INTO ${table.name}_new (${filteredColumns}) SELECT ${filteredColumns} FROM ${table.name}`); db.exec(`DROP TABLE ${table.name}`); db.exec(`ALTER TABLE ${table.name}_new RENAME TO ${table.name}`); } else { db.exec(table.sql); } } for(const table of oldTables) { db.exec(`DROP TABLE ${table.name}`); } })).immediate(schema, oldSchema); db.exec(`PRAGMA foreign_keys = ON; PRAGMA foreign_keys = ON;`); db.close(); template.close(); }); } })