Files
ERitors-Scribe-Desktop/electron/database/repositories/series-character.repo.ts
natreex 209dc6f85a Remove CharacterComponent and CharacterDetail components
- Deleted `CharacterComponent` and `CharacterDetail` files from the project.
- Refactored related logic to improve code maintainability and reduce redundancy.
2026-02-05 14:12:08 -05:00

542 lines
32 KiB
TypeScript

import {Database, QueryResult, RunResult, SQLiteValue} from 'node-sqlite3-wasm';
import System from "../System.js";
export interface SeriesCharacterResult extends Record<string, SQLiteValue> {
character_id: string;
first_name: string;
last_name: string;
nickname: string | null;
age: string | null;
gender: string | null;
species: string | null;
nationality: string | null;
status: string | null;
title: string;
category: string;
image: string;
role: string;
biography: string;
history: string;
speech_pattern: string | null;
catchphrase: string | null;
residence: string | null;
notes: string | null;
color: string | null;
}
export interface SeriesCharacterAttributeResult extends Record<string, SQLiteValue> {
attr_id: string;
attribute_name: string;
attribute_value: string;
}
export interface SeriesCharactersTableResult extends Record<string, SQLiteValue> {
character_id: string;
series_id: string;
user_id: string;
first_name: string;
last_name: string | null;
nickname: string | null;
age: string | null;
gender: string | null;
species: string | null;
nationality: string | null;
status: string | null;
title: string | null;
category: string;
image: string | null;
role: string | null;
biography: string | null;
history: string | null;
speech_pattern: string | null;
catchphrase: string | null;
residence: string | null;
notes: string | null;
color: string | null;
last_update: number;
}
export interface SeriesCharacterAttributesTableResult extends Record<string, SQLiteValue> {
attr_id: string;
character_id: string;
user_id: string;
attribute_name: string;
attribute_value: string;
last_update: number;
}
export interface SyncedSeriesCharacterResult extends Record<string, SQLiteValue> {
character_id: string;
series_id: string;
first_name: string;
last_update: number;
}
export interface SyncedSeriesCharacterAttributeResult extends Record<string, SQLiteValue> {
attr_id: string;
character_id: string;
attribute_name: string;
last_update: number;
}
export default class SeriesCharacterRepo {
/**
* Fetches all characters for a specific series owned by the user.
* @param userId - The unique identifier of the user
* @param seriesId - The unique identifier of the series
* @param lang - The language for error messages ('fr' or 'en')
* @returns An array of character results
*/
public static fetchCharacters(userId: string, seriesId: string, lang: 'fr' | 'en' = 'fr'): SeriesCharacterResult[] {
try {
const db: Database = System.getDb();
const query: string = 'SELECT character_id, first_name, last_name, nickname, age, gender, species, nationality, status, title, category, image, role, biography, history, speech_pattern, catchphrase, residence, notes, color FROM series_characters WHERE series_id = ? AND user_id = ?';
return db.all(query, [seriesId, userId]) as SeriesCharacterResult[];
} catch (error: unknown) {
if (error instanceof Error) {
console.error(`DB Error: ${error.message}`);
throw new Error(lang === 'fr' ? `Impossible de récupérer les personnages de la série.` : `Unable to retrieve series characters.`);
} else {
console.error("An unknown error occurred.");
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
/**
* Adds a new character to a series.
*/
public static addNewCharacter(userId: string, characterId: string, encryptedName: string, encryptedLastName: string | null, encryptedNickname: string | null, encryptedAge: string | null, encryptedGender: string | null, encryptedSpecies: string | null, encryptedNationality: string | null, encryptedStatus: string | null, encryptedTitle: string | null, encryptedCategory: string | null, encryptedImage: string | null, encryptedRole: string | null, encryptedBiography: string | null, encryptedHistory: string | null, encryptedSpeechPattern: string | null, encryptedCatchphrase: string | null, encryptedResidence: string | null, encryptedNotes: string | null, encryptedColor: string | null, seriesId: string, lang: 'fr' | 'en' = 'fr'): string {
let insertResult: RunResult;
try {
const db: Database = System.getDb();
const query: string = 'INSERT INTO series_characters (character_id, series_id, user_id, first_name, last_name, nickname, age, gender, species, nationality, status, category, title, image, role, biography, history, speech_pattern, catchphrase, residence, notes, color, last_update) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
const params: SQLiteValue[] = [characterId, seriesId, userId, encryptedName, encryptedLastName, encryptedNickname, encryptedAge, encryptedGender, encryptedSpecies, encryptedNationality, encryptedStatus, encryptedCategory, encryptedTitle, encryptedImage, encryptedRole, encryptedBiography, encryptedHistory, encryptedSpeechPattern, encryptedCatchphrase, encryptedResidence, encryptedNotes, encryptedColor, System.timeStampInSeconds()];
insertResult = db.run(query, params);
} catch (error: unknown) {
if (error instanceof Error) {
console.error(`DB Error: ${error.message}`);
throw new Error(lang === 'fr' ? `Impossible d'ajouter le personnage.` : `Unable to add character.`);
} else {
console.error("An unknown error occurred.");
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
if (!insertResult || insertResult.changes === 0) {
throw new Error(lang === 'fr' ? `Une erreur s'est produite lors de l'ajout du personnage.` : `Error adding character.`);
}
return characterId;
}
/**
* Inserts a new attribute for a series character.
*/
static insertAttribute(attributeId: string, characterId: string, userId: string, type: string, name: string, lang: 'fr' | 'en' = 'fr'): string {
let insertResult: RunResult;
try {
const db: Database = System.getDb();
const query: string = 'INSERT INTO series_characters_attributes (attr_id, character_id, user_id, attribute_name, attribute_value, last_update) VALUES (?, ?, ?, ?, ?, ?)';
const params: SQLiteValue[] = [attributeId, characterId, userId, type, name, System.timeStampInSeconds()];
insertResult = db.run(query, params);
} catch (error: unknown) {
if (error instanceof Error) {
console.error(`DB Error: ${error.message}`);
throw new Error(lang === 'fr' ? `Impossible d'ajouter l'attribut.` : `Unable to add attribute.`);
} else {
console.error("An unknown error occurred.");
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
if (!insertResult || insertResult.changes === 0) {
throw new Error(lang === 'fr' ? `Une erreur s'est produite lors de l'ajout de l'attribut.` : `Error adding attribute.`);
}
return attributeId;
}
/**
* Updates an existing series character's information.
*/
static updateCharacter(userId: string, characterId: string, encryptedName: string, encryptedLastName: string | null, encryptedNickname: string | null, encryptedAge: string | null, encryptedGender: string | null, encryptedSpecies: string | null, encryptedNationality: string | null, encryptedStatus: string | null, encryptedTitle: string | null, encryptedCategory: string | null, encryptedImage: string | null, encryptedRole: string | null, encryptedBiography: string | null, encryptedHistory: string | null, encryptedSpeechPattern: string | null, encryptedCatchphrase: string | null, encryptedResidence: string | null, encryptedNotes: string | null, encryptedColor: string | null, lang: 'fr' | 'en' = 'fr'): boolean {
try {
const db: Database = System.getDb();
const query: string = 'UPDATE series_characters SET first_name = ?, last_name = ?, nickname = ?, age = ?, gender = ?, species = ?, nationality = ?, status = ?, title = ?, category = ?, image = ?, role = ?, biography = ?, history = ?, speech_pattern = ?, catchphrase = ?, residence = ?, notes = ?, color = ?, last_update = ? WHERE character_id = ? AND user_id = ?';
const params: SQLiteValue[] = [encryptedName, encryptedLastName, encryptedNickname, encryptedAge, encryptedGender, encryptedSpecies, encryptedNationality, encryptedStatus, encryptedTitle, encryptedCategory, encryptedImage, encryptedRole, encryptedBiography, encryptedHistory, encryptedSpeechPattern, encryptedCatchphrase, encryptedResidence, encryptedNotes, encryptedColor, System.timeStampInSeconds(), characterId, userId];
const updateResult: RunResult = db.run(query, params);
return updateResult.changes > 0;
} catch (error: unknown) {
if (error instanceof Error) {
console.error(`DB Error: ${error.message}`);
throw new Error(lang === 'fr' ? `Impossible de mettre à jour le personnage.` : `Unable to update character.`);
} else {
console.error("An unknown error occurred.");
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
/**
* Deletes a series character and all its related data via CASCADE.
*/
static deleteCharacter(userId: string, characterId: string, lang: 'fr' | 'en' = 'fr'): boolean {
try {
const db: Database = System.getDb();
// Delete attributes first
db.run('DELETE FROM series_characters_attributes WHERE character_id = ? AND user_id = ?', [characterId, userId]);
// Delete character
const query: string = 'DELETE FROM series_characters WHERE character_id = ? AND user_id = ?';
const deleteResult: RunResult = db.run(query, [characterId, userId]);
return deleteResult.changes > 0;
} catch (error: unknown) {
if (error instanceof Error) {
console.error(`DB Error: ${error.message}`);
throw new Error(lang === 'fr' ? `Impossible de supprimer le personnage.` : `Unable to delete character.`);
} else {
console.error("An unknown error occurred.");
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
/**
* Deletes an attribute from a series character.
*/
static deleteAttribute(userId: string, attributeId: string, lang: 'fr' | 'en' = 'fr'): boolean {
try {
const db: Database = System.getDb();
const query: string = 'DELETE FROM series_characters_attributes WHERE attr_id = ? AND user_id = ?';
const deleteResult: RunResult = db.run(query, [attributeId, userId]);
return deleteResult.changes > 0;
} catch (error: unknown) {
if (error instanceof Error) {
console.error(`DB Error: ${error.message}`);
throw new Error(lang === 'fr' ? `Impossible de supprimer l'attribut.` : `Unable to delete attribute.`);
} else {
console.error("An unknown error occurred.");
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
/**
* Fetches all attributes for a specific series character.
*/
static fetchAttributes(characterId: string, userId: string, lang: 'fr' | 'en' = 'fr'): SeriesCharacterAttributeResult[] {
try {
const db: Database = System.getDb();
const query: string = 'SELECT attr_id, attribute_name, attribute_value FROM series_characters_attributes WHERE character_id = ? AND user_id = ?';
const attributes: SeriesCharacterAttributeResult[] = db.all(query, [characterId, userId]) as SeriesCharacterAttributeResult[];
return attributes;
} catch (error: unknown) {
if (error instanceof Error) {
console.error(`DB Error: ${error.message}`);
throw new Error(lang === 'fr' ? `Impossible de récupérer les attributs.` : `Unable to retrieve attributes.`);
} else {
console.error("An unknown error occurred.");
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
/**
* Checks if a series character exists.
*/
static isCharacterExist(userId: string, characterId: string, lang: 'fr' | 'en' = 'fr'): boolean {
try {
const db: Database = System.getDb();
const query: string = 'SELECT 1 FROM series_characters WHERE character_id = ? AND user_id = ?';
const result: QueryResult | null = db.get(query, [characterId, userId]);
return result !== null;
} catch (error: unknown) {
if (error instanceof Error) {
console.error(`DB Error: ${error.message}`);
throw new Error(lang === 'fr' ? `Impossible de vérifier l'existence du personnage.` : `Unable to check character existence.`);
} else {
console.error("An unknown error occurred.");
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
/**
* Fetches all characters for a series for sync.
*/
static fetchSeriesCharactersTable(userId: string, seriesId: string, lang: 'fr' | 'en' = 'fr'): SeriesCharactersTableResult[] {
try {
const db: Database = System.getDb();
const query: string = 'SELECT character_id, series_id, user_id, first_name, last_name, nickname, age, gender, species, nationality, status, title, category, image, role, biography, history, speech_pattern, catchphrase, residence, notes, color, last_update FROM series_characters WHERE series_id = ? AND user_id = ?';
const characters: SeriesCharactersTableResult[] = db.all(query, [seriesId, userId]) as SeriesCharactersTableResult[];
return characters;
} catch (error: unknown) {
if (error instanceof Error) {
console.error(`DB Error: ${error.message}`);
throw new Error(lang === 'fr' ? `Impossible de récupérer les personnages pour sync.` : `Unable to retrieve characters for sync.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
/**
* Fetches all attributes for a character for sync.
*/
static fetchSeriesCharacterAttributesTable(userId: string, characterId: string, lang: 'fr' | 'en' = 'fr'): SeriesCharacterAttributesTableResult[] {
try {
const db: Database = System.getDb();
const query: string = 'SELECT attr_id, character_id, user_id, attribute_name, attribute_value, last_update FROM series_characters_attributes WHERE character_id = ? AND user_id = ?';
const attributes: SeriesCharacterAttributesTableResult[] = db.all(query, [characterId, userId]) as SeriesCharacterAttributesTableResult[];
return attributes;
} catch (error: unknown) {
if (error instanceof Error) {
console.error(`DB Error: ${error.message}`);
throw new Error(lang === 'fr' ? `Impossible de récupérer les attributs pour sync.` : `Unable to retrieve attributes for sync.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
/**
* Fetches all series characters for a user for sync comparison.
*/
static fetchSyncedSeriesCharacters(userId: string, lang: 'fr' | 'en' = 'fr'): SyncedSeriesCharacterResult[] {
try {
const db: Database = System.getDb();
const query: string = 'SELECT character_id, series_id, first_name, last_update FROM series_characters WHERE user_id = ?';
const characters: SyncedSeriesCharacterResult[] = db.all(query, [userId]) as SyncedSeriesCharacterResult[];
return characters;
} catch (error: unknown) {
if (error instanceof Error) {
console.error(`DB Error: ${error.message}`);
throw new Error(lang === 'fr' ? `Impossible de récupérer les personnages de série pour sync.` : `Unable to retrieve series characters for sync.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
/**
* Fetches all series character attributes for a user for sync comparison.
*/
static fetchSyncedSeriesCharacterAttributes(userId: string, lang: 'fr' | 'en' = 'fr'): SyncedSeriesCharacterAttributeResult[] {
try {
const db: Database = System.getDb();
const query: string = 'SELECT attr_id, character_id, attribute_name, last_update FROM series_characters_attributes WHERE user_id = ?';
const attributes: SyncedSeriesCharacterAttributeResult[] = db.all(query, [userId]) as SyncedSeriesCharacterAttributeResult[];
return attributes;
} catch (error: unknown) {
if (error instanceof Error) {
console.error(`DB Error: ${error.message}`);
throw new Error(lang === 'fr' ? `Impossible de récupérer les attributs de personnage pour sync.` : `Unable to retrieve character attributes for sync.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
/**
* Fetches a complete character by ID for sync.
*/
static fetchCompleteCharacterById(characterId: string, lang: 'fr' | 'en' = 'fr'): SeriesCharactersTableResult[] {
try {
const db: Database = System.getDb();
const query: string = 'SELECT character_id, series_id, user_id, first_name, last_name, nickname, age, gender, species, nationality, status, title, category, image, role, biography, history, speech_pattern, catchphrase, residence, notes, color, last_update FROM series_characters WHERE character_id = ?';
const characters: SeriesCharactersTableResult[] = db.all(query, [characterId]) as SeriesCharactersTableResult[];
return characters;
} catch (error: unknown) {
if (error instanceof Error) {
console.error(`DB Error: ${error.message}`);
throw new Error(lang === 'fr' ? `Impossible de récupérer le personnage complet.` : `Unable to retrieve complete character.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
/**
* Fetches a complete character attribute by ID for sync.
*/
static fetchCompleteAttributeById(attrId: string, lang: 'fr' | 'en' = 'fr'): SeriesCharacterAttributesTableResult[] {
try {
const db: Database = System.getDb();
const query: string = 'SELECT attr_id, character_id, user_id, attribute_name, attribute_value, last_update FROM series_characters_attributes WHERE attr_id = ?';
const attributes: SeriesCharacterAttributesTableResult[] = db.all(query, [attrId]) as SeriesCharacterAttributesTableResult[];
return attributes;
} catch (error: unknown) {
if (error instanceof Error) {
console.error(`DB Error: ${error.message}`);
throw new Error(lang === 'fr' ? `Impossible de récupérer l'attribut complet.` : `Unable to retrieve complete attribute.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
/**
* Inserts a series character for sync.
*/
static insertSyncSeriesCharacter(characterId: string, seriesId: string, userId: string, firstName: string, lastName: string | null, nickname: string | null, age: string | null, gender: string | null, species: string | null, nationality: string | null, status: string | null, category: string, title: string | null, image: string | null, role: string | null, biography: string | null, history: string | null, speechPattern: string | null, catchphrase: string | null, residence: string | null, notes: string | null, color: string | null, lastUpdate: number, lang: 'fr' | 'en' = 'fr'): boolean {
try {
const db: Database = System.getDb();
const query: string = 'INSERT INTO series_characters (character_id, series_id, user_id, first_name, last_name, nickname, age, gender, species, nationality, status, category, title, image, role, biography, history, speech_pattern, catchphrase, residence, notes, color, last_update) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(character_id) DO UPDATE SET first_name = excluded.first_name, last_name = excluded.last_name, nickname = excluded.nickname, age = excluded.age, gender = excluded.gender, species = excluded.species, nationality = excluded.nationality, status = excluded.status, category = excluded.category, title = excluded.title, image = excluded.image, role = excluded.role, biography = excluded.biography, history = excluded.history, speech_pattern = excluded.speech_pattern, catchphrase = excluded.catchphrase, residence = excluded.residence, notes = excluded.notes, color = excluded.color, last_update = excluded.last_update';
const params: SQLiteValue[] = [characterId, seriesId, userId, firstName, lastName, nickname, age, gender, species, nationality, status, category, title, image, role, biography, history, speechPattern, catchphrase, residence, notes, color, lastUpdate];
const insertResult: RunResult = db.run(query, params);
return insertResult.changes > 0;
} catch (error: unknown) {
if (error instanceof Error) {
console.error(`DB Error: ${error.message}`);
throw new Error(lang === 'fr' ? `Impossible d'insérer le personnage pour sync.` : `Unable to insert character for sync.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
/**
* Updates a series character for sync.
*/
static updateSyncSeriesCharacter(userId: string, characterId: string, firstName: string, lastName: string | null, nickname: string | null, age: string | null, gender: string | null, species: string | null, nationality: string | null, status: string | null, category: string, title: string | null, image: string | null, role: string | null, biography: string | null, history: string | null, speechPattern: string | null, catchphrase: string | null, residence: string | null, notes: string | null, color: string | null, lastUpdate: number, lang: 'fr' | 'en' = 'fr'): boolean {
try {
const db: Database = System.getDb();
const query: string = 'UPDATE series_characters SET first_name = ?, last_name = ?, nickname = ?, age = ?, gender = ?, species = ?, nationality = ?, status = ?, category = ?, title = ?, image = ?, role = ?, biography = ?, history = ?, speech_pattern = ?, catchphrase = ?, residence = ?, notes = ?, color = ?, last_update = ? WHERE character_id = ? AND user_id = ?';
const params: SQLiteValue[] = [firstName, lastName, nickname, age, gender, species, nationality, status, category, title, image, role, biography, history, speechPattern, catchphrase, residence, notes, color, lastUpdate, characterId, userId];
const updateResult: RunResult = db.run(query, params);
return updateResult.changes > 0;
} catch (error: unknown) {
if (error instanceof Error) {
console.error(`DB Error: ${error.message}`);
throw new Error(lang === 'fr' ? `Impossible de mettre à jour le personnage pour sync.` : `Unable to update character for sync.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
/**
* Inserts a series character attribute for sync.
*/
static insertSyncSeriesCharacterAttribute(attrId: string, characterId: string, userId: string, attributeName: string, attributeValue: string, lastUpdate: number, lang: 'fr' | 'en' = 'fr'): boolean {
try {
const db: Database = System.getDb();
const query: string = 'INSERT INTO series_characters_attributes (attr_id, character_id, user_id, attribute_name, attribute_value, last_update) VALUES (?, ?, ?, ?, ?, ?) ON CONFLICT(attr_id) DO UPDATE SET attribute_name = excluded.attribute_name, attribute_value = excluded.attribute_value, last_update = excluded.last_update';
const params: SQLiteValue[] = [attrId, characterId, userId, attributeName, attributeValue, lastUpdate];
const insertResult: RunResult = db.run(query, params);
return insertResult.changes > 0;
} catch (error: unknown) {
if (error instanceof Error) {
console.error(`DB Error: ${error.message}`);
throw new Error(lang === 'fr' ? `Impossible d'insérer l'attribut pour sync.` : `Unable to insert attribute for sync.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
/**
* Checks if a series character attribute exists.
*/
static isAttributeExist(userId: string, attrId: string, lang: 'fr' | 'en' = 'fr'): boolean {
try {
const db: Database = System.getDb();
const query: string = 'SELECT 1 FROM series_characters_attributes WHERE attr_id = ? AND user_id = ?';
const result: QueryResult | null = db.get(query, [attrId, userId]);
return result !== null;
} catch (error: unknown) {
if (error instanceof Error) {
console.error(`DB Error: ${error.message}`);
throw new Error(lang === 'fr' ? `Impossible de vérifier l'existence de l'attribut.` : `Unable to check attribute existence.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
/**
* Updates a series character attribute for sync.
*/
static updateSyncSeriesCharacterAttribute(userId: string, attrId: string, attributeName: string, attributeValue: string, lastUpdate: number, lang: 'fr' | 'en' = 'fr'): boolean {
try {
const db: Database = System.getDb();
const query: string = 'UPDATE series_characters_attributes SET attribute_name = ?, attribute_value = ?, last_update = ? WHERE attr_id = ? AND user_id = ?';
const params: SQLiteValue[] = [attributeName, attributeValue, lastUpdate, attrId, userId];
const updateResult: RunResult = db.run(query, params);
return updateResult.changes > 0;
} catch (error: unknown) {
if (error instanceof Error) {
console.error(`DB Error: ${error.message}`);
throw new Error(lang === 'fr' ? `Impossible de mettre à jour l'attribut pour sync.` : `Unable to update attribute for sync.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
static fetchCharactersTableForSync(seriesId: string, lang: 'fr' | 'en' = 'fr'): SeriesCharactersTableResult[] {
try {
const db: Database = System.getDb();
const query: string = 'SELECT character_id, series_id, user_id, first_name, last_name, nickname, age, gender, species, nationality, status, title, category, image, role, biography, history, speech_pattern, catchphrase, residence, notes, color, last_update FROM series_characters WHERE series_id = ?';
return db.all(query, [seriesId]) as SeriesCharactersTableResult[];
} catch (error: unknown) {
if (error instanceof Error) {
console.error(`DB Error: ${error.message}`);
throw new Error(lang === 'fr' ? `Impossible de récupérer les personnages pour sync.` : `Unable to retrieve characters for sync.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
static fetchCharacterAttributesTableForSync(seriesId: string, lang: 'fr' | 'en' = 'fr'): SeriesCharacterAttributesTableResult[] {
try {
const db: Database = System.getDb();
const query: string = 'SELECT sca.attr_id, sca.character_id, sca.user_id, sca.attribute_name, sca.attribute_value, sca.last_update FROM series_characters_attributes sca INNER JOIN series_characters sc ON sca.character_id = sc.character_id WHERE sc.series_id = ?';
return db.all(query, [seriesId]) as SeriesCharacterAttributesTableResult[];
} catch (error: unknown) {
if (error instanceof Error) {
console.error(`DB Error: ${error.message}`);
throw new Error(lang === 'fr' ? `Impossible de récupérer les attributs pour sync.` : `Unable to retrieve attributes for sync.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
/**
* Fetches all characters for a series (alias for fetchCharacters that returns full table result).
*/
static fetchSeriesCharacters(userId: string, seriesId: string, lang: 'fr' | 'en' = 'fr'): SeriesCharactersTableResult[] {
return this.fetchSeriesCharactersTable(userId, seriesId, lang);
}
/**
* Fetches all character attributes for a series by series ID.
*/
static fetchSeriesCharacterAttributesBySeriesId(userId: string, seriesId: string, lang: 'fr' | 'en' = 'fr'): SeriesCharacterAttributesTableResult[] {
try {
const db: Database = System.getDb();
const query: string = 'SELECT sca.attr_id, sca.character_id, sca.user_id, sca.attribute_name, sca.attribute_value, sca.last_update FROM series_characters_attributes sca INNER JOIN series_characters sc ON sca.character_id = sc.character_id WHERE sc.series_id = ? AND sc.user_id = ?';
return db.all(query, [seriesId, userId]) as SeriesCharacterAttributesTableResult[];
} catch (error: unknown) {
if (error instanceof Error) {
console.error(`DB Error: ${error.message}`);
throw new Error(lang === 'fr' ? `Impossible de récupérer les attributs par série.` : `Unable to retrieve attributes by series.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
/**
* Checks if a series character exists (alias for isCharacterExist).
*/
static seriesCharacterExists(userId: string, characterId: string, lang: 'fr' | 'en' = 'fr'): boolean {
return this.isCharacterExist(userId, characterId, lang);
}
/**
* Checks if a series character attribute exists (alias for isAttributeExist).
*/
static seriesCharacterAttributeExists(userId: string, attrId: string, lang: 'fr' | 'en' = 'fr'): boolean {
return this.isAttributeExist(userId, attrId, lang);
}
}