import { Database, QueryResult, RunResult, SQLiteValue } from 'node-sqlite3-wasm'; import System from "../System.js"; export type SyncElementType = 'character' | 'world' | 'location' | 'spell'; export interface BookElementSeriesLink extends Record { series_id: string | null; } export default class SeriesSyncRepo { /** * Gets the series element ID linked to a book character. */ static getCharacterSeriesLink(userId: string, characterId: string, lang: 'fr' | 'en' = 'fr'): string | null { try { const db: Database = System.getDb(); const query: string = 'SELECT series_character_id AS series_id FROM book_characters WHERE character_id = ? AND user_id = ?'; const result: BookElementSeriesLink | undefined = db.get(query, [characterId, userId]) as BookElementSeriesLink | undefined; return result ? result.series_id : null; } catch (error: unknown) { if (error instanceof Error) { console.error(`DB Error: ${error.message}`); throw new Error(lang === 'fr' ? `Impossible de récupérer le lien série du personnage.` : `Unable to retrieve character series link.`); } throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred."); } } /** * Gets the series element ID linked to a book world. */ static getWorldSeriesLink(userId: string, worldId: string, lang: 'fr' | 'en' = 'fr'): string | null { try { const db: Database = System.getDb(); const query: string = 'SELECT series_world_id AS series_id FROM book_world WHERE world_id = ? AND user_id = ?'; const result: BookElementSeriesLink | undefined = db.get(query, [worldId, userId]) as BookElementSeriesLink | undefined; return result ? result.series_id : null; } catch (error: unknown) { if (error instanceof Error) { console.error(`DB Error: ${error.message}`); throw new Error(lang === 'fr' ? `Impossible de récupérer le lien série du monde.` : `Unable to retrieve world series link.`); } throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred."); } } /** * Gets the series element ID linked to a book location. */ static getLocationSeriesLink(userId: string, locationId: string, lang: 'fr' | 'en' = 'fr'): string | null { try { const db: Database = System.getDb(); const query: string = 'SELECT series_location_id AS series_id FROM book_location WHERE loc_id = ? AND user_id = ?'; const result: BookElementSeriesLink | undefined = db.get(query, [locationId, userId]) as BookElementSeriesLink | undefined; return result ? result.series_id : null; } catch (error: unknown) { if (error instanceof Error) { console.error(`DB Error: ${error.message}`); throw new Error(lang === 'fr' ? `Impossible de récupérer le lien série du lieu.` : `Unable to retrieve location series link.`); } throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred."); } } /** * Gets the series element ID linked to a book spell. */ static getSpellSeriesLink(userId: string, spellId: string, lang: 'fr' | 'en' = 'fr'): string | null { try { const db: Database = System.getDb(); const query: string = 'SELECT series_spell_id AS series_id FROM book_spells WHERE spell_id = ? AND user_id = ?'; const result: BookElementSeriesLink | undefined = db.get(query, [spellId, userId]) as BookElementSeriesLink | undefined; return result ? result.series_id : null; } catch (error: unknown) { if (error instanceof Error) { console.error(`DB Error: ${error.message}`); throw new Error(lang === 'fr' ? `Impossible de récupérer le lien série du sort.` : `Unable to retrieve spell series link.`); } throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred."); } } /** * Updates a field in series_characters table. */ static updateSeriesCharacterField(userId: string, seriesCharacterId: string, field: string, encryptedValue: string, lang: 'fr' | 'en' = 'fr'): boolean { const allowedFields: string[] = ['first_name', 'last_name', 'nickname', 'age', 'gender', 'species', 'nationality', 'status', 'title', 'category', 'role', 'biography', 'history', 'speech_pattern', 'catchphrase', 'residence', 'notes', 'color']; if (!allowedFields.includes(field)) { throw new Error(lang === 'fr' ? `Champ non autorisé: ${field}` : `Field not allowed: ${field}`); } try { const db: Database = System.getDb(); const query: string = `UPDATE series_characters SET ${field} = ?, last_update = ? WHERE character_id = ? AND user_id = ?`; const result: RunResult = db.run(query, [encryptedValue, System.timeStampInSeconds(), seriesCharacterId, userId]); return result.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 série.` : `Unable to update series character.`); } throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred."); } } /** * Updates a field in all book_characters linked to a series character. */ static updateLinkedBookCharactersField(userId: string, seriesCharacterId: string, field: string, encryptedValue: string, lang: 'fr' | 'en' = 'fr'): number { const allowedFields: string[] = ['first_name', 'last_name', 'nickname', 'age', 'gender', 'species', 'nationality', 'status', 'title', 'category', 'role', 'biography', 'history', 'speech_pattern', 'catchphrase', 'residence', 'notes', 'color']; if (!allowedFields.includes(field)) { throw new Error(lang === 'fr' ? `Champ non autorisé: ${field}` : `Field not allowed: ${field}`); } try { const db: Database = System.getDb(); const query: string = `UPDATE book_characters SET ${field} = ?, last_update = ? WHERE series_character_id = ? AND user_id = ?`; const result: RunResult = db.run(query, [encryptedValue, System.timeStampInSeconds(), seriesCharacterId, userId]); return result.changes; } catch (error: unknown) { if (error instanceof Error) { console.error(`DB Error: ${error.message}`); throw new Error(lang === 'fr' ? `Impossible de mettre à jour les personnages liés.` : `Unable to update linked characters.`); } throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred."); } } /** * Updates a field in series_worlds table. */ static updateSeriesWorldField(userId: string, seriesWorldId: string, field: string, encryptedValue: string, lang: 'fr' | 'en' = 'fr'): boolean { const allowedFields: string[] = ['name', 'history', 'politics', 'economy', 'religion', 'languages']; if (!allowedFields.includes(field)) { throw new Error(lang === 'fr' ? `Champ non autorisé: ${field}` : `Field not allowed: ${field}`); } try { const db: Database = System.getDb(); const query: string = `UPDATE series_worlds SET ${field} = ?, last_update = ? WHERE world_id = ? AND user_id = ?`; const result: RunResult = db.run(query, [encryptedValue, System.timeStampInSeconds(), seriesWorldId, userId]); return result.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 monde série.` : `Unable to update series world.`); } throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred."); } } /** * Updates a field in all book_world linked to a series world. */ static updateLinkedBookWorldsField(userId: string, seriesWorldId: string, field: string, encryptedValue: string, lang: 'fr' | 'en' = 'fr'): number { const allowedFields: string[] = ['name', 'history', 'politics', 'economy', 'religion', 'languages']; if (!allowedFields.includes(field)) { throw new Error(lang === 'fr' ? `Champ non autorisé: ${field}` : `Field not allowed: ${field}`); } try { const db: Database = System.getDb(); const query: string = `UPDATE book_world SET ${field} = ?, last_update = ? WHERE series_world_id = ? AND user_id = ?`; const result: RunResult = db.run(query, [encryptedValue, System.timeStampInSeconds(), seriesWorldId, userId]); return result.changes; } catch (error: unknown) { if (error instanceof Error) { console.error(`DB Error: ${error.message}`); throw new Error(lang === 'fr' ? `Impossible de mettre à jour les mondes liés.` : `Unable to update linked worlds.`); } throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred."); } } /** * Updates a field in series_locations table. */ static updateSeriesLocationField(userId: string, seriesLocationId: string, field: string, encryptedValue: string, lang: 'fr' | 'en' = 'fr'): boolean { const allowedFields: string[] = ['name']; if (!allowedFields.includes(field)) { throw new Error(lang === 'fr' ? `Champ non autorisé: ${field}` : `Field not allowed: ${field}`); } try { const db: Database = System.getDb(); const query: string = `UPDATE series_locations SET ${field} = ?, last_update = ? WHERE location_id = ? AND user_id = ?`; const result: RunResult = db.run(query, [encryptedValue, System.timeStampInSeconds(), seriesLocationId, userId]); return result.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 lieu série.` : `Unable to update series location.`); } throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred."); } } /** * Updates a field in all book_location linked to a series location. */ static updateLinkedBookLocationsField(userId: string, seriesLocationId: string, field: string, encryptedValue: string, lang: 'fr' | 'en' = 'fr'): number { const allowedFields: string[] = ['loc_name']; if (!allowedFields.includes(field)) { throw new Error(lang === 'fr' ? `Champ non autorisé: ${field}` : `Field not allowed: ${field}`); } try { const db: Database = System.getDb(); const query: string = `UPDATE book_location SET ${field} = ?, last_update = ? WHERE series_location_id = ? AND user_id = ?`; const result: RunResult = db.run(query, [encryptedValue, System.timeStampInSeconds(), seriesLocationId, userId]); return result.changes; } catch (error: unknown) { if (error instanceof Error) { console.error(`DB Error: ${error.message}`); throw new Error(lang === 'fr' ? `Impossible de mettre à jour les lieux liés.` : `Unable to update linked locations.`); } throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred."); } } /** * Updates a field in series_spells table. */ static updateSeriesSpellField(userId: string, seriesSpellId: string, field: string, encryptedValue: string, lang: 'fr' | 'en' = 'fr'): boolean { const allowedFields: string[] = ['name', 'description', 'type', 'level', 'range', 'duration', 'cost', 'effect', 'components', 'notes']; if (!allowedFields.includes(field)) { throw new Error(lang === 'fr' ? `Champ non autorisé: ${field}` : `Field not allowed: ${field}`); } try { const db: Database = System.getDb(); const query: string = `UPDATE series_spells SET ${field} = ?, last_update = ? WHERE spell_id = ? AND user_id = ?`; const result: RunResult = db.run(query, [encryptedValue, System.timeStampInSeconds(), seriesSpellId, userId]); return result.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 sort série.` : `Unable to update series spell.`); } throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred."); } } /** * Updates a field in all book_spells linked to a series spell. */ static updateLinkedBookSpellsField(userId: string, seriesSpellId: string, field: string, encryptedValue: string, lang: 'fr' | 'en' = 'fr'): number { const allowedFields: string[] = ['name', 'description', 'type', 'level', 'range', 'duration', 'cost', 'effect', 'components', 'notes']; if (!allowedFields.includes(field)) { throw new Error(lang === 'fr' ? `Champ non autorisé: ${field}` : `Field not allowed: ${field}`); } try { const db: Database = System.getDb(); const query: string = `UPDATE book_spells SET ${field} = ?, last_update = ? WHERE series_spell_id = ? AND user_id = ?`; const result: RunResult = db.run(query, [encryptedValue, System.timeStampInSeconds(), seriesSpellId, userId]); return result.changes; } catch (error: unknown) { if (error instanceof Error) { console.error(`DB Error: ${error.message}`); throw new Error(lang === 'fr' ? `Impossible de mettre à jour les sorts liés.` : `Unable to update linked spells.`); } throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred."); } } }