Refactor BookRepo methods and improve error handling

- Add JSDoc comments for better maintainability and code clarity in `BookRepo` methods.
- Streamline query definitions using variables to improve readability.
- Consolidate error handling logic across all methods.
- Ensure multilingual support in error messages for consistent user feedback.
- Remove redundant error branches and simplify unknown error processing.
This commit is contained in:
natreex
2026-01-12 09:57:37 -05:00
parent 9ad2ee9692
commit d9bf089e32
12 changed files with 3202 additions and 1252 deletions

View File

@@ -1,4 +1,4 @@
import {Database, QueryResult, RunResult, SQLiteValue} from "node-sqlite3-wasm";
import { Database, QueryResult, RunResult, SQLiteValue } from "node-sqlite3-wasm";
import System from "@/electron/database/System";
export interface BookPlotPointsTable extends Record<string, SQLiteValue> {
@@ -27,13 +27,23 @@ export interface PlotPointQuery extends Record<string, SQLiteValue> {
}
export default class PlotPointRepository {
public static fetchAllPlotPoints(userId:string,bookId:string, lang: 'fr' | 'en'):PlotPointQuery[]{
/**
* Fetches all plot points for a specific book.
* @param userId - The ID of the user/author
* @param bookId - The ID of the book
* @param lang - The language for error messages ('fr' or 'en')
* @returns An array of plot points with their basic information
*/
public static fetchAllPlotPoints(userId: string, bookId: string, lang: 'fr' | 'en'): PlotPointQuery[] {
try {
const db: Database = System.getDb();
return db.all('SELECT plot_point_id, title, summary, linked_incident_id FROM book_plot_points WHERE author_id=? AND book_id=?', [userId, bookId]) as PlotPointQuery[];
} catch (e: unknown) {
if (e instanceof Error) {
console.error(`DB Error: ${e.message}`);
const query: string = 'SELECT plot_point_id, title, summary, linked_incident_id FROM book_plot_points WHERE author_id=? AND book_id=?';
const params: SQLiteValue[] = [userId, bookId];
const plotPoints: PlotPointQuery[] = db.all(query, params) as PlotPointQuery[];
return plotPoints;
} catch (error: unknown) {
if (error instanceof Error) {
console.error(`DB Error: ${error.message}`);
throw new Error(lang === 'fr' ? `Impossible de récupérer les points d'intrigue.` : `Unable to retrieve plot points.`);
} else {
console.error("An unknown error occurred.");
@@ -41,30 +51,46 @@ export default class PlotPointRepository {
}
}
}
/**
* Inserts a new plot point into the database.
* @param plotPointId - The unique ID for the new plot point
* @param userId - The ID of the user/author
* @param bookId - The ID of the book
* @param encryptedName - The encrypted title of the plot point
* @param hashedName - The hashed title for duplicate checking
* @param incidentId - The ID of the linked incident (can be empty string)
* @param lang - The language for error messages ('fr' or 'en')
* @returns The ID of the newly created plot point
*/
static insertNewPlotPoint(plotPointId: string, userId: string, bookId: string, encryptedName: string, hashedName: string, incidentId: string, lang: 'fr' | 'en'): string {
let existingResult: QueryResult | null;
let existingPlotPoint: QueryResult | null;
let insertResult: RunResult;
try {
const db: Database = System.getDb();
existingResult = db.get('SELECT plot_point_id FROM book_plot_points WHERE author_id=? AND book_id=? AND hashed_title=?', [userId, bookId, hashedName]);
} catch (e: unknown) {
if (e instanceof Error) {
console.error(`DB Error: ${e.message}`);
const checkQuery: string = 'SELECT plot_point_id FROM book_plot_points WHERE author_id=? AND book_id=? AND hashed_title=?';
const checkParams: SQLiteValue[] = [userId, bookId, hashedName];
existingPlotPoint = db.get(checkQuery, checkParams);
} 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 point d'intrigue.` : `Unable to verify plot point existence.`);
} else {
console.error("An unknown error occurred.");
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
if (existingResult !== null) {
if (existingPlotPoint !== null) {
throw new Error(lang === 'fr' ? `Ce point de l'intrigue existe déjà.` : `This plot point already exists.`);
}
try {
const db: Database = System.getDb();
insertResult = db.run('INSERT INTO book_plot_points (plot_point_id,title,hashed_title,author_id,book_id,linked_incident_id,last_update) VALUES (?,?,?,?,?,?,?)', [plotPointId, encryptedName, hashedName, userId, bookId, incidentId, System.timeStampInSeconds()]);
} catch (e: unknown) {
if (e instanceof Error) {
console.error(`DB Error: ${e.message}`);
const insertQuery: string = 'INSERT INTO book_plot_points (plot_point_id,title,hashed_title,author_id,book_id,linked_incident_id,last_update) VALUES (?,?,?,?,?,?,?)';
const insertParams: SQLiteValue[] = [plotPointId, encryptedName, hashedName, userId, bookId, incidentId, System.timeStampInSeconds()];
insertResult = db.run(insertQuery, insertParams);
} catch (error: unknown) {
if (error instanceof Error) {
console.error(`DB Error: ${error.message}`);
throw new Error(lang === 'fr' ? `Impossible d'ajouter le point d'intrigue.` : `Unable to add plot point.`);
} else {
console.error("An unknown error occurred.");
@@ -76,15 +102,24 @@ export default class PlotPointRepository {
}
return plotPointId;
}
static deletePlotPoint(userId: string, plotNumId: string, lang: 'fr' | 'en'): boolean {
/**
* Deletes a plot point from the database.
* @param userId - The ID of the user/author
* @param plotPointId - The ID of the plot point to delete
* @param lang - The language for error messages ('fr' or 'en')
* @returns True if the plot point was deleted, false otherwise
*/
static deletePlotPoint(userId: string, plotPointId: string, lang: 'fr' | 'en'): boolean {
try {
const db: Database = System.getDb();
const result: RunResult = db.run('DELETE FROM book_plot_points WHERE author_id=? AND plot_point_id=?', [userId, plotNumId]);
return result.changes > 0;
} catch (e: unknown) {
if (e instanceof Error) {
console.error(`DB Error: ${e.message}`);
const query: string = 'DELETE FROM book_plot_points WHERE author_id=? AND plot_point_id=?';
const params: SQLiteValue[] = [userId, plotPointId];
const deleteResult: RunResult = db.run(query, params);
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 point d'intrigue.` : `Unable to delete plot point.`);
} else {
console.error("An unknown error occurred.");
@@ -92,14 +127,29 @@ export default class PlotPointRepository {
}
}
}
public static updatePlotPoint(userId: string, bookId: string, plotPointId: string, encryptedPlotPointName: string, plotPointHashedName: string, plotPointSummary: string, lastUpdate:number, lang: 'fr' | 'en'): boolean {
/**
* Updates an existing plot point in the database.
* @param userId - The ID of the user/author
* @param bookId - The ID of the book
* @param plotPointId - The ID of the plot point to update
* @param encryptedPlotPointName - The new encrypted title
* @param plotPointHashedName - The new hashed title
* @param plotPointSummary - The new summary
* @param lastUpdate - The timestamp of the last update
* @param lang - The language for error messages ('fr' or 'en')
* @returns True if the plot point was updated, false otherwise
*/
public static updatePlotPoint(userId: string, bookId: string, plotPointId: string, encryptedPlotPointName: string, plotPointHashedName: string, plotPointSummary: string, lastUpdate: number, lang: 'fr' | 'en'): boolean {
try {
const db: Database = System.getDb();
const result: RunResult = db.run('UPDATE book_plot_points SET title=?, hashed_title=?, summary=?, last_update=? WHERE author_id=? AND book_id=? AND plot_point_id=?', [encryptedPlotPointName, plotPointHashedName, plotPointSummary, lastUpdate, userId, bookId, plotPointId]);
return result.changes > 0;
} catch (e: unknown) {
if (e instanceof Error) {
console.error(`DB Error: ${e.message}`);
const query: string = 'UPDATE book_plot_points SET title=?, hashed_title=?, summary=?, last_update=? WHERE author_id=? AND book_id=? AND plot_point_id=?';
const params: SQLiteValue[] = [encryptedPlotPointName, plotPointHashedName, plotPointSummary, lastUpdate, userId, bookId, plotPointId];
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 point d'intrigue.` : `Unable to update plot point.`);
} else {
console.error("An unknown error occurred.");
@@ -107,26 +157,47 @@ export default class PlotPointRepository {
}
}
}
/**
* Fetches all plot points for a book with complete information for synchronization.
* @param userId - The ID of the user/author
* @param bookId - The ID of the book
* @param lang - The language for error messages ('fr' or 'en')
* @returns An array of complete plot point records
*/
static async fetchBookPlotPoints(userId: string, bookId: string, lang: 'fr' | 'en'): Promise<BookPlotPointsTable[]> {
try {
const db: Database = System.getDb();
return db.all('SELECT plot_point_id, title, hashed_title, summary, linked_incident_id, author_id, book_id, last_update FROM book_plot_points WHERE author_id=? AND book_id=?', [userId, bookId]) as BookPlotPointsTable[];
} catch (e: unknown) {
if (e instanceof Error) {
console.error(`DB Error: ${e.message}`);
const query: string = 'SELECT plot_point_id, title, hashed_title, summary, linked_incident_id, author_id, book_id, last_update FROM book_plot_points WHERE author_id=? AND book_id=?';
const params: SQLiteValue[] = [userId, bookId];
const plotPoints: BookPlotPointsTable[] = db.all(query, params) as BookPlotPointsTable[];
return plotPoints;
} catch (error: unknown) {
if (error instanceof Error) {
console.error(`DB Error: ${error.message}`);
throw new Error(lang === 'fr' ? `Impossible de récupérer les points d'intrigue.` : `Unable to retrieve plot points.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
/**
* Fetches all synced plot points for a user across all books.
* @param userId - The ID of the user/author
* @param lang - The language for error messages ('fr' or 'en')
* @returns An array of synced plot point records with minimal information
*/
static fetchSyncedPlotPoints(userId: string, lang: 'fr' | 'en'): SyncedPlotPointResult[] {
try {
const db: Database = System.getDb();
return db.all('SELECT plot_point_id, book_id, title, last_update FROM book_plot_points WHERE author_id = ?', [userId]) as SyncedPlotPointResult[];
} catch (e: unknown) {
if (e instanceof Error) {
console.error(`DB Error: ${e.message}`);
const query: string = 'SELECT plot_point_id, book_id, title, last_update FROM book_plot_points WHERE author_id = ?';
const params: SQLiteValue[] = [userId];
const syncedPlotPoints: SyncedPlotPointResult[] = db.all(query, params) as SyncedPlotPointResult[];
return syncedPlotPoints;
} catch (error: unknown) {
if (error instanceof Error) {
console.error(`DB Error: ${error.message}`);
throw new Error(lang === 'fr' ? `Impossible de récupérer les points d'intrigue synchronisés.` : `Unable to retrieve synced plot points.`);
} else {
console.error("An unknown error occurred.");
@@ -134,53 +205,84 @@ export default class PlotPointRepository {
}
}
}
/**
* Inserts a plot point during synchronization from remote data.
* @param plotPointId - The unique ID of the plot point
* @param title - The encrypted title
* @param hashedTitle - The hashed title for duplicate checking
* @param summary - The encrypted summary (can be null)
* @param linkedIncidentId - The ID of the linked incident (can be null)
* @param authorId - The ID of the author
* @param bookId - The ID of the book
* @param lastUpdate - The timestamp of the last update
* @param lang - The language for error messages ('fr' or 'en')
* @returns True if the plot point was inserted, false otherwise
*/
static insertSyncPlotPoint(plotPointId: string, title: string, hashedTitle: string, summary: string | null, linkedIncidentId: string | null, authorId: string, bookId: string, lastUpdate: number, lang: 'fr' | 'en'): boolean {
try {
const db: Database = System.getDb();
const result: RunResult = db.run(
`INSERT INTO book_plot_points (plot_point_id, title, hashed_title, summary, linked_incident_id, author_id, book_id, last_update)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
[plotPointId, title, hashedTitle, summary, linkedIncidentId, authorId, bookId, lastUpdate]
);
return result.changes > 0;
} catch (e: unknown) {
if (e instanceof Error) {
console.error(`DB Error: ${e.message}`);
const query: string = `INSERT INTO book_plot_points (plot_point_id, title, hashed_title, summary, linked_incident_id, author_id, book_id, last_update)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`;
const params: SQLiteValue[] = [plotPointId, title, hashedTitle, summary, linkedIncidentId, authorId, bookId, 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 point d'intrigue.` : `Unable to insert plot point.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
static async fetchCompletePlotPointById(id: string, lang: "fr" | "en"):Promise<BookPlotPointsTable[]> {
/**
* Fetches complete plot point data by its ID.
* @param plotPointId - The ID of the plot point to retrieve
* @param lang - The language for error messages ('fr' or 'en')
* @returns An array containing the plot point data (empty if not found)
*/
static async fetchCompletePlotPointById(plotPointId: string, lang: "fr" | "en"): Promise<BookPlotPointsTable[]> {
try {
const db: Database = System.getDb();
return db.all(
`SELECT plot_point_id, title, hashed_title, summary, linked_incident_id, author_id, book_id, last_update
const query: string = `SELECT plot_point_id, title, hashed_title, summary, linked_incident_id, author_id, book_id, last_update
FROM book_plot_points
WHERE plot_point_id = ?`,
[id]
) as BookPlotPointsTable[];
} catch (e:unknown){
if (e instanceof Error) {
WHERE plot_point_id = ?`;
const params: SQLiteValue[] = [plotPointId];
const plotPoint: BookPlotPointsTable[] = db.all(query, params) as BookPlotPointsTable[];
return plotPoint;
} catch (error: unknown) {
if (error instanceof Error) {
throw new Error(lang === 'fr' ? `Impossible de récupérer le point d'intrigue complet.` : `Unable to retrieve complete plot point.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
static plotPointExist(userId: string, bookId: string, plot_point_id: string,lang: "fr" | "en"): boolean {
/**
* Checks if a plot point exists in the database.
* @param userId - The ID of the user/author
* @param bookId - The ID of the book
* @param plotPointId - The ID of the plot point to check
* @param lang - The language for error messages ('fr' or 'en')
* @returns True if the plot point exists, false otherwise
*/
static plotPointExist(userId: string, bookId: string, plotPointId: string, lang: "fr" | "en"): boolean {
try {
const db: Database = System.getDb();
const result:QueryResult|null = db.get('SELECT 1 FROM book_plot_points WHERE author_id =? AND book_id =? AND plot_point_id =?', [userId, bookId, plot_point_id]) || null;
return result !== null;
} catch (e: unknown) {
if (e instanceof Error) {
console.error(`DB Error: ${e.message}`);
const query: string = 'SELECT 1 FROM book_plot_points WHERE author_id =? AND book_id =? AND plot_point_id =?';
const params: SQLiteValue[] = [userId, bookId, plotPointId];
const existingPlotPoint: QueryResult | null = db.get(query, params) || null;
return existingPlotPoint !== 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 point de intrigue.` : `Unable to check plot point existence.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
}
}