Upgrade database schema to version 2 and remove unused meta_* columns
- Increment `SCHEMA_VERSION` to 2 in `schema.ts`. - Remove all `meta_*` columns from database tables. - Add migration logic to handle schema upgrades and clean up unused columns. - Modify database models and repository methods to exclude `meta_*` fields for stricter typings and improved structure. - Refactor and optimize query statements across repositories to align with new schema changes.
This commit is contained in:
@@ -8,7 +8,7 @@ type Database = sqlite3.Database;
|
||||
* Data is encrypted before storage and decrypted on retrieval
|
||||
*/
|
||||
|
||||
export const SCHEMA_VERSION = 1;
|
||||
export const SCHEMA_VERSION = 2;
|
||||
|
||||
/**
|
||||
* Initialize the local SQLite database with all required tables
|
||||
@@ -66,7 +66,6 @@ export function initializeSchema(db: Database): void {
|
||||
role TEXT NOT NULL,
|
||||
message TEXT NOT NULL,
|
||||
message_date INTEGER NOT NULL,
|
||||
meta_message TEXT NOT NULL,
|
||||
synced INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (conversation_id) REFERENCES ai_conversations(conversation_id) ON DELETE CASCADE
|
||||
);
|
||||
@@ -88,7 +87,6 @@ export function initializeSchema(db: Database): void {
|
||||
user_id TEXT NOT NULL,
|
||||
act_index INTEGER NOT NULL,
|
||||
summary TEXT,
|
||||
meta_acts TEXT NOT NULL,
|
||||
synced INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
|
||||
);
|
||||
@@ -108,7 +106,6 @@ export function initializeSchema(db: Database): void {
|
||||
tone TEXT,
|
||||
atmosphere TEXT,
|
||||
current_resume TEXT,
|
||||
meta TEXT NOT NULL,
|
||||
synced INTEGER DEFAULT 0,
|
||||
PRIMARY KEY (user_id, book_id),
|
||||
FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
|
||||
@@ -125,7 +122,6 @@ export function initializeSchema(db: Database): void {
|
||||
hashed_title TEXT,
|
||||
words_count INTEGER,
|
||||
chapter_order INTEGER,
|
||||
meta_chapter TEXT NOT NULL,
|
||||
synced INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
|
||||
);
|
||||
@@ -140,7 +136,6 @@ export function initializeSchema(db: Database): void {
|
||||
version INTEGER NOT NULL DEFAULT 2,
|
||||
content TEXT NOT NULL,
|
||||
words_count INTEGER NOT NULL,
|
||||
meta_chapter_content TEXT NOT NULL,
|
||||
time_on_it INTEGER NOT NULL DEFAULT 0,
|
||||
synced INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (chapter_id) REFERENCES book_chapters(chapter_id) ON DELETE CASCADE
|
||||
@@ -159,7 +154,6 @@ export function initializeSchema(db: Database): void {
|
||||
author_id TEXT,
|
||||
summary TEXT NOT NULL,
|
||||
goal TEXT NOT NULL,
|
||||
meta_chapter_info TEXT NOT NULL,
|
||||
synced INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (chapter_id) REFERENCES book_chapters(chapter_id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (incident_id) REFERENCES book_incidents(incident_id) ON DELETE CASCADE,
|
||||
@@ -181,7 +175,6 @@ export function initializeSchema(db: Database): void {
|
||||
role TEXT,
|
||||
biography TEXT,
|
||||
history TEXT,
|
||||
char_meta TEXT NOT NULL,
|
||||
synced INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
|
||||
);
|
||||
@@ -195,7 +188,6 @@ export function initializeSchema(db: Database): void {
|
||||
user_id TEXT NOT NULL,
|
||||
attribute_name TEXT NOT NULL,
|
||||
attribute_value TEXT NOT NULL,
|
||||
attr_meta TEXT NOT NULL,
|
||||
synced INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (character_id) REFERENCES book_characters(character_id) ON DELETE CASCADE
|
||||
);
|
||||
@@ -229,7 +221,6 @@ export function initializeSchema(db: Database): void {
|
||||
pacing TEXT NOT NULL,
|
||||
intended_audience TEXT NOT NULL,
|
||||
key_messages TEXT NOT NULL,
|
||||
meta_guide_line TEXT NOT NULL,
|
||||
synced INTEGER DEFAULT 0,
|
||||
PRIMARY KEY (user_id, book_id),
|
||||
FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
|
||||
@@ -245,7 +236,6 @@ export function initializeSchema(db: Database): void {
|
||||
title TEXT NOT NULL,
|
||||
hashed_title TEXT NOT NULL,
|
||||
summary TEXT,
|
||||
meta_incident TEXT NOT NULL,
|
||||
synced INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
|
||||
);
|
||||
@@ -259,7 +249,6 @@ export function initializeSchema(db: Database): void {
|
||||
book_id TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
hashed_issue_name TEXT NOT NULL,
|
||||
meta_issue TEXT NOT NULL,
|
||||
synced INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
|
||||
);
|
||||
@@ -273,7 +262,6 @@ export function initializeSchema(db: Database): void {
|
||||
user_id TEXT NOT NULL,
|
||||
loc_name TEXT NOT NULL,
|
||||
loc_original_name TEXT NOT NULL,
|
||||
loc_meta TEXT NOT NULL,
|
||||
synced INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
|
||||
);
|
||||
@@ -289,7 +277,6 @@ export function initializeSchema(db: Database): void {
|
||||
linked_incident_id TEXT,
|
||||
author_id TEXT NOT NULL,
|
||||
book_id TEXT NOT NULL,
|
||||
meta_plot TEXT NOT NULL,
|
||||
synced INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
|
||||
);
|
||||
@@ -308,7 +295,6 @@ export function initializeSchema(db: Database): void {
|
||||
economy TEXT,
|
||||
religion TEXT,
|
||||
languages TEXT,
|
||||
meta_world TEXT NOT NULL,
|
||||
synced INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
|
||||
);
|
||||
@@ -324,7 +310,6 @@ export function initializeSchema(db: Database): void {
|
||||
name TEXT NOT NULL,
|
||||
original_name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
meta_element TEXT NOT NULL,
|
||||
synced INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (world_id) REFERENCES book_world(world_id) ON DELETE CASCADE
|
||||
);
|
||||
@@ -346,7 +331,6 @@ export function initializeSchema(db: Database): void {
|
||||
desired_word_count INTEGER,
|
||||
words_count INTEGER,
|
||||
cover_image TEXT,
|
||||
book_meta TEXT,
|
||||
synced INTEGER DEFAULT 0
|
||||
);
|
||||
`);
|
||||
@@ -395,7 +379,6 @@ export function initializeSchema(db: Database): void {
|
||||
verify_code TEXT,
|
||||
reg_date INTEGER NOT NULL,
|
||||
account_verified INTEGER NOT NULL DEFAULT 0,
|
||||
user_meta TEXT NOT NULL,
|
||||
erite_points INTEGER NOT NULL DEFAULT 100,
|
||||
stripe_customer_id TEXT,
|
||||
credits_balance REAL DEFAULT 0,
|
||||
@@ -412,7 +395,6 @@ export function initializeSchema(db: Database): void {
|
||||
element_name TEXT NOT NULL,
|
||||
original_name TEXT NOT NULL,
|
||||
element_description TEXT,
|
||||
element_meta TEXT NOT NULL,
|
||||
synced INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (location) REFERENCES book_location(loc_id) ON DELETE CASCADE
|
||||
);
|
||||
@@ -427,7 +409,6 @@ export function initializeSchema(db: Database): void {
|
||||
sub_elem_name TEXT NOT NULL,
|
||||
original_name TEXT NOT NULL,
|
||||
sub_elem_description TEXT,
|
||||
sub_elem_meta TEXT NOT NULL,
|
||||
synced INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (element_id) REFERENCES location_element(element_id) ON DELETE CASCADE
|
||||
);
|
||||
@@ -523,3 +504,90 @@ export function dropAllTables(db: Database): void {
|
||||
|
||||
db.exec('PRAGMA foreign_keys = ON');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current schema version from database
|
||||
*/
|
||||
function getDbSchemaVersion(db: Database): number {
|
||||
try {
|
||||
const result = db.get('SELECT version FROM _schema_version LIMIT 1') as { version: number } | undefined;
|
||||
return result?.version ?? 0;
|
||||
} catch {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set schema version in database
|
||||
*/
|
||||
function setDbSchemaVersion(db: Database, version: number): void {
|
||||
db.exec('CREATE TABLE IF NOT EXISTS _schema_version (version INTEGER PRIMARY KEY)');
|
||||
db.run('DELETE FROM _schema_version');
|
||||
db.run('INSERT INTO _schema_version (version) VALUES (?)', [version]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a column exists in a table
|
||||
*/
|
||||
function columnExists(db: Database, tableName: string, columnName: string): boolean {
|
||||
const columns = db.all(`PRAGMA table_info(${tableName})`) as { name: string }[];
|
||||
return columns.some(col => col.name === columnName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely drop a column if it exists
|
||||
*/
|
||||
function dropColumnIfExists(db: Database, tableName: string, columnName: string): void {
|
||||
if (columnExists(db, tableName, columnName)) {
|
||||
try {
|
||||
db.exec(`ALTER TABLE ${tableName} DROP COLUMN ${columnName}`);
|
||||
console.log(`[Migration] Dropped column ${columnName} from ${tableName}`);
|
||||
} catch (e) {
|
||||
console.error(`[Migration] Failed to drop column ${columnName} from ${tableName}:`, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run migrations to update schema from one version to another
|
||||
*/
|
||||
export function runMigrations(db: Database): void {
|
||||
const currentVersion = getDbSchemaVersion(db);
|
||||
|
||||
if (currentVersion >= SCHEMA_VERSION) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`[Migration] Upgrading schema from version ${currentVersion} to ${SCHEMA_VERSION}`);
|
||||
|
||||
// Migration 1 -> 2: Remove all meta_* columns
|
||||
if (currentVersion < 2) {
|
||||
console.log('[Migration] Running migration v2: Removing meta columns...');
|
||||
|
||||
dropColumnIfExists(db, 'ai_messages_history', 'meta_message');
|
||||
dropColumnIfExists(db, 'book_act_summaries', 'meta_acts');
|
||||
dropColumnIfExists(db, 'book_ai_guide_line', 'meta');
|
||||
dropColumnIfExists(db, 'book_chapters', 'meta_chapter');
|
||||
dropColumnIfExists(db, 'book_chapter_content', 'meta_chapter_content');
|
||||
dropColumnIfExists(db, 'book_chapter_infos', 'meta_chapter_info');
|
||||
dropColumnIfExists(db, 'book_characters', 'char_meta');
|
||||
dropColumnIfExists(db, 'book_characters_attributes', 'attr_meta');
|
||||
dropColumnIfExists(db, 'book_guide_line', 'meta_guide_line');
|
||||
dropColumnIfExists(db, 'book_incidents', 'meta_incident');
|
||||
dropColumnIfExists(db, 'book_issues', 'meta_issue');
|
||||
dropColumnIfExists(db, 'book_location', 'loc_meta');
|
||||
dropColumnIfExists(db, 'book_plot_points', 'meta_plot');
|
||||
dropColumnIfExists(db, 'book_world', 'meta_world');
|
||||
dropColumnIfExists(db, 'book_world_elements', 'meta_element');
|
||||
dropColumnIfExists(db, 'erit_books', 'book_meta');
|
||||
dropColumnIfExists(db, 'erit_users', 'user_meta');
|
||||
dropColumnIfExists(db, 'location_element', 'element_meta');
|
||||
dropColumnIfExists(db, 'location_sub_element', 'sub_elem_meta');
|
||||
|
||||
console.log('[Migration] Migration v2 completed');
|
||||
}
|
||||
|
||||
// Update schema version
|
||||
setDbSchemaVersion(db, SCHEMA_VERSION);
|
||||
console.log(`[Migration] Schema updated to version ${SCHEMA_VERSION}`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user