import { getUserEncryptionKey } from "../keyManager.js"; import System from "../System.js"; import { ActChapter } from "./Act.js"; import IncidentRepository, { IncidentQuery } from "../repositories/incident.repository.js"; export interface IncidentStory { incidentTitle: string; incidentSummary: string; chapterSummary: string; chapterGoal: string; } export interface SyncedIncident { id: string; name: string; lastUpdate: number; } export interface IncidentProps { incidentId: string; title: string; summary: string; chapters?: ActChapter[]; } export default class Incident { /** * Creates a new incident for a book. * Encrypts the incident name and generates a hashed version for indexing. * @param userId - The unique identifier of the user creating the incident * @param bookId - The unique identifier of the book to add the incident to * @param name - The plain text name of the incident * @param lang - The language for error messages (defaults to 'fr') * @param existingIncidentId - Optional existing incident ID to use instead of generating a new one * @returns The unique identifier of the created incident */ public static addNewIncident( userId: string, bookId: string, name: string, lang: 'fr' | 'en' = 'fr', existingIncidentId?: string ): string { const userKey: string = getUserEncryptionKey(userId); const encryptedName: string = System.encryptDataWithUserKey(name, userKey); const hashedName: string = System.hashElement(name); const incidentId: string = existingIncidentId || System.createUniqueId(); return IncidentRepository.insertNewIncident(incidentId, userId, bookId, encryptedName, hashedName, lang); } /** * Retrieves all incidents for a specific book with their associated chapters. * Decrypts incident titles and summaries using the user's encryption key. * @param userId - The unique identifier of the user * @param bookId - The unique identifier of the book * @param actChapters - Array of chapters from acts to associate with incidents * @param lang - The language for error messages (defaults to 'fr') * @returns A promise resolving to an array of incident properties with decrypted data */ public static async getIncitentsIncidents( userId: string, bookId: string, actChapters: ActChapter[], lang: 'fr' | 'en' = 'fr' ): Promise { const incidentQueryResults: IncidentQuery[] = IncidentRepository.fetchAllIncitentIncidents(userId, bookId, lang); const incidents: IncidentProps[] = []; const userKey: string = getUserEncryptionKey(userId); if (incidentQueryResults.length > 0) { for (const incidentRecord of incidentQueryResults) { const associatedChapters: ActChapter[] = []; for (const chapter of actChapters) { if (chapter.incidentId === incidentRecord.incident_id) { associatedChapters.push(chapter); } } incidents.push({ incidentId: incidentRecord.incident_id, title: incidentRecord.title ? System.decryptDataWithUserKey(incidentRecord.title, userKey) : '', summary: incidentRecord.summary ? System.decryptDataWithUserKey(incidentRecord.summary, userKey) : '', chapters: associatedChapters }); } } return incidents; } /** * Removes an incident from a book. * @param userId - The unique identifier of the user * @param bookId - The unique identifier of the book * @param incidentId - The unique identifier of the incident to remove * @param lang - The language for error messages (defaults to 'fr') * @returns True if the incident was successfully deleted, false otherwise */ public static removeIncident( userId: string, bookId: string, incidentId: string, lang: 'fr' | 'en' = 'fr' ): boolean { return IncidentRepository.deleteIncident(userId, bookId, incidentId, lang); } }