Introduce series management functionality and repository updates
- Added `series-world.repo.ts` to handle database operations related to series worlds and their elements. - Implemented `series-sync.repo.ts` for managing synchronization between books and series. - Expanded `spell.ipc.ts` data models to include `seriesSpellId` for spell synchronization. - Refactored `insertSpellTag` method in `spelltag.repo.ts` for improved error handling and logic clarity.
This commit is contained in:
@@ -13,7 +13,7 @@ type Database = sqlite3.Database;
|
||||
// MIGRATIONS
|
||||
// =============================================================================
|
||||
|
||||
const schemaVersion = 2;
|
||||
const schemaVersion = 3;
|
||||
|
||||
/**
|
||||
* DEV ONLY - S'exécute à chaque refresh, pas besoin de version
|
||||
@@ -137,6 +137,55 @@ function migrateFromOldSystem(db: Database): void {
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_spells_book ON book_spells(book_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_spells_user ON book_spells(user_id)`);
|
||||
|
||||
// Create series tables (v3)
|
||||
db.exec(`CREATE TABLE IF NOT EXISTS book_series (series_id TEXT PRIMARY KEY, user_id TEXT NOT NULL, name TEXT NOT NULL, hashed_name TEXT NOT NULL, description TEXT, cover_image TEXT, last_update INTEGER DEFAULT 0, FOREIGN KEY (user_id) REFERENCES erit_users(user_id) ON DELETE CASCADE);`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_book_series_user ON book_series(user_id)`);
|
||||
|
||||
db.exec(`CREATE TABLE IF NOT EXISTS series_books (series_id TEXT NOT NULL, book_id TEXT NOT NULL, book_order INTEGER NOT NULL DEFAULT 1, last_update INTEGER DEFAULT 0, PRIMARY KEY (series_id, book_id), FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE, FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE);`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_books_book ON series_books(book_id)`);
|
||||
|
||||
db.exec(`CREATE TABLE IF NOT EXISTS series_characters (character_id TEXT PRIMARY KEY, series_id TEXT NOT NULL, user_id TEXT NOT NULL, first_name TEXT NOT NULL, last_name TEXT, nickname TEXT, age TEXT, gender TEXT, species TEXT, nationality TEXT, status TEXT, category TEXT NOT NULL, title TEXT, image TEXT, role TEXT, biography TEXT, history TEXT, speech_pattern TEXT, catchphrase TEXT, residence TEXT, notes TEXT, color TEXT, last_update INTEGER DEFAULT 0, FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE);`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_characters_series ON series_characters(series_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_characters_user ON series_characters(user_id)`);
|
||||
|
||||
db.exec(`CREATE TABLE IF NOT EXISTS series_characters_attributes (attr_id TEXT PRIMARY KEY, character_id TEXT NOT NULL, user_id TEXT NOT NULL, attribute_name TEXT NOT NULL, attribute_value TEXT NOT NULL, last_update INTEGER DEFAULT 0, FOREIGN KEY (character_id) REFERENCES series_characters(character_id) ON DELETE CASCADE);`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_char_attrs_character ON series_characters_attributes(character_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_char_attrs_user ON series_characters_attributes(user_id)`);
|
||||
|
||||
db.exec(`CREATE TABLE IF NOT EXISTS series_worlds (world_id TEXT PRIMARY KEY, series_id TEXT NOT NULL, user_id TEXT NOT NULL, name TEXT NOT NULL, hashed_name TEXT NOT NULL, history TEXT, politics TEXT, economy TEXT, religion TEXT, languages TEXT, last_update INTEGER DEFAULT 0, FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE);`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_worlds_series ON series_worlds(series_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_worlds_user ON series_worlds(user_id)`);
|
||||
|
||||
db.exec(`CREATE TABLE IF NOT EXISTS series_world_elements (element_id TEXT PRIMARY KEY, world_id TEXT NOT NULL, user_id TEXT NOT NULL, element_type INTEGER NOT NULL, name TEXT NOT NULL, original_name TEXT NOT NULL, description TEXT, last_update INTEGER DEFAULT 0, FOREIGN KEY (world_id) REFERENCES series_worlds(world_id) ON DELETE CASCADE);`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_world_elements_world ON series_world_elements(world_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_world_elements_user ON series_world_elements(user_id)`);
|
||||
|
||||
db.exec(`CREATE TABLE IF NOT EXISTS series_locations (loc_id TEXT PRIMARY KEY, series_id TEXT NOT NULL, user_id TEXT NOT NULL, loc_name TEXT NOT NULL, loc_original_name TEXT NOT NULL, last_update INTEGER DEFAULT 0, FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE);`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_locations_series ON series_locations(series_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_locations_user ON series_locations(user_id)`);
|
||||
|
||||
db.exec(`CREATE TABLE IF NOT EXISTS series_location_elements (element_id TEXT PRIMARY KEY, location_id TEXT NOT NULL, user_id TEXT NOT NULL, element_name TEXT NOT NULL, original_name TEXT NOT NULL, element_description TEXT, last_update INTEGER DEFAULT 0, FOREIGN KEY (location_id) REFERENCES series_locations(loc_id) ON DELETE CASCADE);`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_loc_elements_location ON series_location_elements(location_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_loc_elements_user ON series_location_elements(user_id)`);
|
||||
|
||||
db.exec(`CREATE TABLE IF NOT EXISTS series_location_sub_elements (sub_element_id TEXT PRIMARY KEY, element_id TEXT NOT NULL, user_id TEXT NOT NULL, sub_elem_name TEXT NOT NULL, original_name TEXT NOT NULL, sub_elem_description TEXT, last_update INTEGER DEFAULT 0, FOREIGN KEY (element_id) REFERENCES series_location_elements(element_id) ON DELETE CASCADE);`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_loc_sub_elements_element ON series_location_sub_elements(element_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_loc_sub_elements_user ON series_location_sub_elements(user_id)`);
|
||||
|
||||
db.exec(`CREATE TABLE IF NOT EXISTS series_spells (spell_id TEXT PRIMARY KEY, series_id TEXT NOT NULL, user_id TEXT NOT NULL, name TEXT NOT NULL, name_hash TEXT NOT NULL, description TEXT NOT NULL, appearance TEXT NOT NULL, tags TEXT, power_level TEXT, components TEXT, limitations TEXT, notes TEXT, last_update INTEGER DEFAULT 0, FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE);`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_spells_series ON series_spells(series_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_spells_user ON series_spells(user_id)`);
|
||||
|
||||
db.exec(`CREATE TABLE IF NOT EXISTS series_spell_tags (tag_id TEXT PRIMARY KEY, series_id TEXT NOT NULL, user_id TEXT NOT NULL, name TEXT NOT NULL, hashed_name TEXT NOT NULL, color TEXT, last_update INTEGER DEFAULT 0, FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE);`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_spell_tags_series ON series_spell_tags(series_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_spell_tags_user ON series_spell_tags(user_id)`);
|
||||
|
||||
// Add series_*_id columns to existing book tables (v3)
|
||||
addColumn(db, 'book_characters', 'series_character_id', 'TEXT DEFAULT NULL');
|
||||
addColumn(db, 'book_world', 'series_world_id', 'TEXT DEFAULT NULL');
|
||||
addColumn(db, 'book_location', 'series_location_id', 'TEXT DEFAULT NULL');
|
||||
addColumn(db, 'book_spells', 'series_spell_id', 'TEXT DEFAULT NULL');
|
||||
|
||||
// Drop old schema version table
|
||||
db.exec('DROP TABLE IF EXISTS _schema_version');
|
||||
}
|
||||
@@ -236,6 +285,70 @@ export function runMigrations(db: Database): void {
|
||||
addColumn(db, 'book_characters', 'color', 'TEXT DEFAULT NULL');
|
||||
}
|
||||
|
||||
// v3 - Add series tables and series_*_id columns to existing book tables
|
||||
if (currentVersion < 3) {
|
||||
// Create series tables first (order matters for foreign keys)
|
||||
|
||||
// Book Series (main series table)
|
||||
db.exec(`CREATE TABLE IF NOT EXISTS book_series (series_id TEXT PRIMARY KEY, user_id TEXT NOT NULL, name TEXT NOT NULL, hashed_name TEXT NOT NULL, description TEXT, cover_image TEXT, last_update INTEGER DEFAULT 0, FOREIGN KEY (user_id) REFERENCES erit_users(user_id) ON DELETE CASCADE);`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_book_series_user ON book_series(user_id)`);
|
||||
|
||||
// Series Books (link series to books with order)
|
||||
db.exec(`CREATE TABLE IF NOT EXISTS series_books (series_id TEXT NOT NULL, book_id TEXT NOT NULL, book_order INTEGER NOT NULL DEFAULT 1, last_update INTEGER DEFAULT 0, PRIMARY KEY (series_id, book_id), FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE, FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE);`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_books_book ON series_books(book_id)`);
|
||||
|
||||
// Series Characters
|
||||
db.exec(`CREATE TABLE IF NOT EXISTS series_characters (character_id TEXT PRIMARY KEY, series_id TEXT NOT NULL, user_id TEXT NOT NULL, first_name TEXT NOT NULL, last_name TEXT, nickname TEXT, age TEXT, gender TEXT, species TEXT, nationality TEXT, status TEXT, category TEXT NOT NULL, title TEXT, image TEXT, role TEXT, biography TEXT, history TEXT, speech_pattern TEXT, catchphrase TEXT, residence TEXT, notes TEXT, color TEXT, last_update INTEGER DEFAULT 0, FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE);`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_characters_series ON series_characters(series_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_characters_user ON series_characters(user_id)`);
|
||||
|
||||
// Series Characters Attributes
|
||||
db.exec(`CREATE TABLE IF NOT EXISTS series_characters_attributes (attr_id TEXT PRIMARY KEY, character_id TEXT NOT NULL, user_id TEXT NOT NULL, attribute_name TEXT NOT NULL, attribute_value TEXT NOT NULL, last_update INTEGER DEFAULT 0, FOREIGN KEY (character_id) REFERENCES series_characters(character_id) ON DELETE CASCADE);`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_char_attrs_character ON series_characters_attributes(character_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_char_attrs_user ON series_characters_attributes(user_id)`);
|
||||
|
||||
// Series Worlds
|
||||
db.exec(`CREATE TABLE IF NOT EXISTS series_worlds (world_id TEXT PRIMARY KEY, series_id TEXT NOT NULL, user_id TEXT NOT NULL, name TEXT NOT NULL, hashed_name TEXT NOT NULL, history TEXT, politics TEXT, economy TEXT, religion TEXT, languages TEXT, last_update INTEGER DEFAULT 0, FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE);`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_worlds_series ON series_worlds(series_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_worlds_user ON series_worlds(user_id)`);
|
||||
|
||||
// Series World Elements
|
||||
db.exec(`CREATE TABLE IF NOT EXISTS series_world_elements (element_id TEXT PRIMARY KEY, world_id TEXT NOT NULL, user_id TEXT NOT NULL, element_type INTEGER NOT NULL, name TEXT NOT NULL, original_name TEXT NOT NULL, description TEXT, last_update INTEGER DEFAULT 0, FOREIGN KEY (world_id) REFERENCES series_worlds(world_id) ON DELETE CASCADE);`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_world_elements_world ON series_world_elements(world_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_world_elements_user ON series_world_elements(user_id)`);
|
||||
|
||||
// Series Locations
|
||||
db.exec(`CREATE TABLE IF NOT EXISTS series_locations (loc_id TEXT PRIMARY KEY, series_id TEXT NOT NULL, user_id TEXT NOT NULL, loc_name TEXT NOT NULL, loc_original_name TEXT NOT NULL, last_update INTEGER DEFAULT 0, FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE);`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_locations_series ON series_locations(series_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_locations_user ON series_locations(user_id)`);
|
||||
|
||||
// Series Location Elements
|
||||
db.exec(`CREATE TABLE IF NOT EXISTS series_location_elements (element_id TEXT PRIMARY KEY, location_id TEXT NOT NULL, user_id TEXT NOT NULL, element_name TEXT NOT NULL, original_name TEXT NOT NULL, element_description TEXT, last_update INTEGER DEFAULT 0, FOREIGN KEY (location_id) REFERENCES series_locations(loc_id) ON DELETE CASCADE);`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_loc_elements_location ON series_location_elements(location_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_loc_elements_user ON series_location_elements(user_id)`);
|
||||
|
||||
// Series Location Sub Elements
|
||||
db.exec(`CREATE TABLE IF NOT EXISTS series_location_sub_elements (sub_element_id TEXT PRIMARY KEY, element_id TEXT NOT NULL, user_id TEXT NOT NULL, sub_elem_name TEXT NOT NULL, original_name TEXT NOT NULL, sub_elem_description TEXT, last_update INTEGER DEFAULT 0, FOREIGN KEY (element_id) REFERENCES series_location_elements(element_id) ON DELETE CASCADE);`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_loc_sub_elements_element ON series_location_sub_elements(element_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_loc_sub_elements_user ON series_location_sub_elements(user_id)`);
|
||||
|
||||
// Series Spells
|
||||
db.exec(`CREATE TABLE IF NOT EXISTS series_spells (spell_id TEXT PRIMARY KEY, series_id TEXT NOT NULL, user_id TEXT NOT NULL, name TEXT NOT NULL, name_hash TEXT NOT NULL, description TEXT NOT NULL, appearance TEXT NOT NULL, tags TEXT, power_level TEXT, components TEXT, limitations TEXT, notes TEXT, last_update INTEGER DEFAULT 0, FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE);`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_spells_series ON series_spells(series_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_spells_user ON series_spells(user_id)`);
|
||||
|
||||
// Series Spell Tags
|
||||
db.exec(`CREATE TABLE IF NOT EXISTS series_spell_tags (tag_id TEXT PRIMARY KEY, series_id TEXT NOT NULL, user_id TEXT NOT NULL, name TEXT NOT NULL, hashed_name TEXT NOT NULL, color TEXT, last_update INTEGER DEFAULT 0, FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE);`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_spell_tags_series ON series_spell_tags(series_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_spell_tags_user ON series_spell_tags(user_id)`);
|
||||
|
||||
// Add series_*_id columns to existing book tables
|
||||
addColumn(db, 'book_characters', 'series_character_id', 'TEXT DEFAULT NULL');
|
||||
addColumn(db, 'book_world', 'series_world_id', 'TEXT DEFAULT NULL');
|
||||
addColumn(db, 'book_location', 'series_location_id', 'TEXT DEFAULT NULL');
|
||||
addColumn(db, 'book_spells', 'series_spell_id', 'TEXT DEFAULT NULL');
|
||||
}
|
||||
|
||||
setDbVersion(db, schemaVersion);
|
||||
}
|
||||
|
||||
@@ -391,8 +504,10 @@ export function initializeSchema(db: Database): void {
|
||||
residence TEXT,
|
||||
notes TEXT,
|
||||
color TEXT,
|
||||
series_character_id TEXT,
|
||||
last_update INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
|
||||
FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (series_character_id) REFERENCES series_characters(character_id) ON DELETE SET NULL
|
||||
);
|
||||
`);
|
||||
|
||||
@@ -478,8 +593,10 @@ export function initializeSchema(db: Database): void {
|
||||
user_id TEXT NOT NULL,
|
||||
loc_name TEXT NOT NULL,
|
||||
loc_original_name TEXT NOT NULL,
|
||||
series_location_id TEXT,
|
||||
last_update INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
|
||||
FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (series_location_id) REFERENCES series_locations(loc_id) ON DELETE SET NULL
|
||||
);
|
||||
`);
|
||||
|
||||
@@ -511,8 +628,10 @@ export function initializeSchema(db: Database): void {
|
||||
economy TEXT,
|
||||
religion TEXT,
|
||||
languages TEXT,
|
||||
series_world_id TEXT,
|
||||
last_update INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
|
||||
FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (series_world_id) REFERENCES series_worlds(world_id) ON DELETE SET NULL
|
||||
);
|
||||
`);
|
||||
|
||||
@@ -696,11 +815,195 @@ export function initializeSchema(db: Database): void {
|
||||
components TEXT,
|
||||
limitations TEXT,
|
||||
notes TEXT,
|
||||
series_spell_id TEXT,
|
||||
last_update INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (series_spell_id) REFERENCES series_spells(spell_id) ON DELETE SET NULL
|
||||
);
|
||||
`);
|
||||
|
||||
// =============================================================================
|
||||
// SERIES TABLES
|
||||
// =============================================================================
|
||||
|
||||
// Book Series (main series table)
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS book_series (
|
||||
series_id TEXT PRIMARY KEY,
|
||||
user_id TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
hashed_name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
cover_image TEXT,
|
||||
last_update INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (user_id) REFERENCES erit_users(user_id) ON DELETE CASCADE
|
||||
);
|
||||
`);
|
||||
|
||||
// Series Books (link series to books with order)
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS series_books (
|
||||
series_id TEXT NOT NULL,
|
||||
book_id TEXT NOT NULL,
|
||||
book_order INTEGER NOT NULL DEFAULT 1,
|
||||
last_update INTEGER DEFAULT 0,
|
||||
PRIMARY KEY (series_id, book_id),
|
||||
FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
|
||||
);
|
||||
`);
|
||||
|
||||
// Series Characters
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS series_characters (
|
||||
character_id TEXT PRIMARY KEY,
|
||||
series_id TEXT NOT NULL,
|
||||
user_id TEXT NOT NULL,
|
||||
first_name TEXT NOT NULL,
|
||||
last_name TEXT,
|
||||
nickname TEXT,
|
||||
age TEXT,
|
||||
gender TEXT,
|
||||
species TEXT,
|
||||
nationality TEXT,
|
||||
status TEXT,
|
||||
category TEXT NOT NULL,
|
||||
title TEXT,
|
||||
image TEXT,
|
||||
role TEXT,
|
||||
biography TEXT,
|
||||
history TEXT,
|
||||
speech_pattern TEXT,
|
||||
catchphrase TEXT,
|
||||
residence TEXT,
|
||||
notes TEXT,
|
||||
color TEXT,
|
||||
last_update INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE
|
||||
);
|
||||
`);
|
||||
|
||||
// Series Characters Attributes
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS series_characters_attributes (
|
||||
attr_id TEXT PRIMARY KEY,
|
||||
character_id TEXT NOT NULL,
|
||||
user_id TEXT NOT NULL,
|
||||
attribute_name TEXT NOT NULL,
|
||||
attribute_value TEXT NOT NULL,
|
||||
last_update INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (character_id) REFERENCES series_characters(character_id) ON DELETE CASCADE
|
||||
);
|
||||
`);
|
||||
|
||||
// Series Worlds
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS series_worlds (
|
||||
world_id TEXT PRIMARY KEY,
|
||||
series_id TEXT NOT NULL,
|
||||
user_id TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
hashed_name TEXT NOT NULL,
|
||||
history TEXT,
|
||||
politics TEXT,
|
||||
economy TEXT,
|
||||
religion TEXT,
|
||||
languages TEXT,
|
||||
last_update INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE
|
||||
);
|
||||
`);
|
||||
|
||||
// Series World Elements
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS series_world_elements (
|
||||
element_id TEXT PRIMARY KEY,
|
||||
world_id TEXT NOT NULL,
|
||||
user_id TEXT NOT NULL,
|
||||
element_type INTEGER NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
original_name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
last_update INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (world_id) REFERENCES series_worlds(world_id) ON DELETE CASCADE
|
||||
);
|
||||
`);
|
||||
|
||||
// Series Locations
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS series_locations (
|
||||
loc_id TEXT PRIMARY KEY,
|
||||
series_id TEXT NOT NULL,
|
||||
user_id TEXT NOT NULL,
|
||||
loc_name TEXT NOT NULL,
|
||||
loc_original_name TEXT NOT NULL,
|
||||
last_update INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE
|
||||
);
|
||||
`);
|
||||
|
||||
// Series Location Elements
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS series_location_elements (
|
||||
element_id TEXT PRIMARY KEY,
|
||||
location_id TEXT NOT NULL,
|
||||
user_id TEXT NOT NULL,
|
||||
element_name TEXT NOT NULL,
|
||||
original_name TEXT NOT NULL,
|
||||
element_description TEXT,
|
||||
last_update INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (location_id) REFERENCES series_locations(loc_id) ON DELETE CASCADE
|
||||
);
|
||||
`);
|
||||
|
||||
// Series Location Sub Elements
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS series_location_sub_elements (
|
||||
sub_element_id TEXT PRIMARY KEY,
|
||||
element_id TEXT NOT NULL,
|
||||
user_id TEXT NOT NULL,
|
||||
sub_elem_name TEXT NOT NULL,
|
||||
original_name TEXT NOT NULL,
|
||||
sub_elem_description TEXT,
|
||||
last_update INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (element_id) REFERENCES series_location_elements(element_id) ON DELETE CASCADE
|
||||
);
|
||||
`);
|
||||
|
||||
// Series Spells
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS series_spells (
|
||||
spell_id TEXT PRIMARY KEY,
|
||||
series_id TEXT NOT NULL,
|
||||
user_id TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
name_hash TEXT NOT NULL,
|
||||
description TEXT NOT NULL,
|
||||
appearance TEXT NOT NULL,
|
||||
tags TEXT,
|
||||
power_level TEXT,
|
||||
components TEXT,
|
||||
limitations TEXT,
|
||||
notes TEXT,
|
||||
last_update INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE
|
||||
);
|
||||
`);
|
||||
|
||||
// Series Spell Tags
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS series_spell_tags (
|
||||
tag_id TEXT PRIMARY KEY,
|
||||
series_id TEXT NOT NULL,
|
||||
user_id TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
hashed_name TEXT NOT NULL,
|
||||
color TEXT,
|
||||
last_update INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (series_id) REFERENCES book_series(series_id) ON DELETE CASCADE
|
||||
);
|
||||
`);
|
||||
|
||||
// Create indexes for better performance
|
||||
createIndexes(db);
|
||||
}
|
||||
@@ -724,6 +1027,28 @@ function createIndexes(db: Database): void {
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_spell_tags_user ON book_spell_tags(user_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_spells_book ON book_spells(book_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_spells_user ON book_spells(user_id)`);
|
||||
|
||||
// Series tables indexes
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_book_series_user ON book_series(user_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_books_book ON series_books(book_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_characters_series ON series_characters(series_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_characters_user ON series_characters(user_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_char_attrs_character ON series_characters_attributes(character_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_char_attrs_user ON series_characters_attributes(user_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_worlds_series ON series_worlds(series_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_worlds_user ON series_worlds(user_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_world_elements_world ON series_world_elements(world_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_world_elements_user ON series_world_elements(user_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_locations_series ON series_locations(series_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_locations_user ON series_locations(user_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_loc_elements_location ON series_location_elements(location_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_loc_elements_user ON series_location_elements(user_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_loc_sub_elements_element ON series_location_sub_elements(element_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_loc_sub_elements_user ON series_location_sub_elements(user_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_spells_series ON series_spells(series_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_spells_user ON series_spells(user_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_spell_tags_series ON series_spell_tags(series_id)`);
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_series_spell_tags_user ON series_spell_tags(user_id)`);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user