Add models for guidelines, incidents, plot points, issues, acts, and world data
- Introduced new models: `GuideLine`, `Incident`, `PlotPoint`, `Issue`, `Act`, and `World` for managing book-related entities. - Integrated encryption/decryption for sensitive properties in all models using user-specific keys. - Added methods for CRUD operations and synchronization workflows with error handling and multilingual support. - Improved maintainability with JSDoc comments and streamlined queries.
This commit is contained in:
876
electron/database/models/Sync.ts
Normal file
876
electron/database/models/Sync.ts
Normal file
@@ -0,0 +1,876 @@
|
||||
import { getUserEncryptionKey } from "../keyManager.js";
|
||||
import System from "../System.js";
|
||||
import { BookSyncCompare, CompleteBook, SyncedBook } from "./Book.js";
|
||||
import BookRepo, { EritBooksTable, SyncedBookResult } from "../repositories/book.repository.js";
|
||||
import ChapterRepo, {
|
||||
BookChapterInfosTable,
|
||||
BookChaptersTable,
|
||||
SyncedChapterInfoResult,
|
||||
SyncedChapterResult
|
||||
} from "../repositories/chapter.repository.js";
|
||||
import PlotPointRepository, { BookPlotPointsTable, SyncedPlotPointResult } from "../repositories/plotpoint.repository.js";
|
||||
import IncidentRepository, { BookIncidentsTable, SyncedIncidentResult } from "../repositories/incident.repository.js";
|
||||
import ChapterContentRepository, {
|
||||
BookChapterContentTable,
|
||||
SyncedChapterContentResult
|
||||
} from "../repositories/chaptercontent.repository.js";
|
||||
import CharacterRepo, {
|
||||
BookCharactersAttributesTable,
|
||||
BookCharactersTable,
|
||||
SyncedCharacterAttributeResult,
|
||||
SyncedCharacterResult
|
||||
} from "../repositories/character.repository.js";
|
||||
import LocationRepo, {
|
||||
BookLocationTable,
|
||||
LocationElementTable,
|
||||
LocationSubElementTable,
|
||||
SyncedLocationElementResult,
|
||||
SyncedLocationResult,
|
||||
SyncedLocationSubElementResult
|
||||
} from "../repositories/location.repository.js";
|
||||
import WorldRepository, {
|
||||
BookWorldElementsTable,
|
||||
BookWorldTable,
|
||||
SyncedWorldElementResult,
|
||||
SyncedWorldResult
|
||||
} from "../repositories/world.repository.js";
|
||||
import ActRepository, {
|
||||
BookActSummariesTable,
|
||||
SyncedActSummaryResult
|
||||
} from "../repositories/act.repository.js";
|
||||
import GuidelineRepo, {
|
||||
BookAIGuideLineTable,
|
||||
BookGuideLineTable,
|
||||
SyncedAIGuideLineResult,
|
||||
SyncedGuideLineResult
|
||||
} from "../repositories/guideline.repository.js";
|
||||
import IssueRepository, { BookIssuesTable, SyncedIssueResult } from "../repositories/issue.repository.js";
|
||||
import { SyncedChapter, SyncedChapterContent, SyncedChapterInfo } from "./Chapter.js";
|
||||
import { SyncedCharacter, SyncedCharacterAttribute } from "./Character.js";
|
||||
import { SyncedLocation, SyncedLocationElement, SyncedLocationSubElement } from "./Location.js";
|
||||
import { SyncedWorld, SyncedWorldElement } from "./World.js";
|
||||
import { SyncedIncident } from "./Incident.js";
|
||||
import { SyncedPlotPoint } from "./PlotPoint.js";
|
||||
import { SyncedIssue } from "./Issue.js";
|
||||
import { SyncedActSummary } from "./Act.js";
|
||||
import { SyncedAIGuideLine, SyncedGuideLine } from "./GuideLine.js";
|
||||
|
||||
/**
|
||||
* Handles synchronization operations between local database and remote server.
|
||||
* Provides methods to fetch, compare, and sync book data including all related entities.
|
||||
*/
|
||||
export default class Sync {
|
||||
/**
|
||||
* Retrieves a complete book with all its associated entities for synchronization.
|
||||
* Decrypts all encrypted fields using the user's encryption key.
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param syncCompareData - Object containing IDs of entities to retrieve for sync comparison
|
||||
* @param lang - The language for error messages ('fr' or 'en')
|
||||
* @returns A promise resolving to a CompleteBook object with all decrypted data
|
||||
*/
|
||||
static async getCompleteSyncBook(userId: string, syncCompareData: BookSyncCompare, lang: "fr" | "en"): Promise<CompleteBook> {
|
||||
const userEncryptionKey: string = getUserEncryptionKey(userId);
|
||||
const decryptedBooks: EritBooksTable[] = [];
|
||||
const decryptedChapters: BookChaptersTable[] = [];
|
||||
const decryptedPlotPoints: BookPlotPointsTable[] = [];
|
||||
const decryptedIncidents: BookIncidentsTable[] = [];
|
||||
const decryptedChapterContents: BookChapterContentTable[] = [];
|
||||
const decryptedChapterInfos: BookChapterInfosTable[] = [];
|
||||
const decryptedCharacters: BookCharactersTable[] = [];
|
||||
const decryptedCharacterAttributes: BookCharactersAttributesTable[] = [];
|
||||
const decryptedLocations: BookLocationTable[] = [];
|
||||
const decryptedLocationElements: LocationElementTable[] = [];
|
||||
const decryptedLocationSubElements: LocationSubElementTable[] = [];
|
||||
const decryptedWorlds: BookWorldTable[] = [];
|
||||
const decryptedWorldElements: BookWorldElementsTable[] = [];
|
||||
const decryptedActSummaries: BookActSummariesTable[] = [];
|
||||
const decryptedGuideLines: BookGuideLineTable[] = [];
|
||||
const decryptedAIGuideLines: BookAIGuideLineTable[] = [];
|
||||
const decryptedIssues: BookIssuesTable[] = [];
|
||||
|
||||
const actSummaryIds: string[] = syncCompareData.actSummaries;
|
||||
const chapterIds: string[] = syncCompareData.chapters;
|
||||
const plotPointIds: string[] = syncCompareData.plotPoints;
|
||||
const incidentIds: string[] = syncCompareData.incidents;
|
||||
const chapterContentIds: string[] = syncCompareData.chapterContents;
|
||||
const chapterInfoIds: string[] = syncCompareData.chapterInfos;
|
||||
const characterIds: string[] = syncCompareData.characters;
|
||||
const characterAttributeIds: string[] = syncCompareData.characterAttributes;
|
||||
const locationIds: string[] = syncCompareData.locations;
|
||||
const locationElementIds: string[] = syncCompareData.locationElements;
|
||||
const locationSubElementIds: string[] = syncCompareData.locationSubElements;
|
||||
const worldIds: string[] = syncCompareData.worlds;
|
||||
const worldElementIds: string[] = syncCompareData.worldElements;
|
||||
const issueIds: string[] = syncCompareData.issues;
|
||||
|
||||
if (actSummaryIds && actSummaryIds.length > 0) {
|
||||
for (const actSummaryId of actSummaryIds) {
|
||||
const actSummaryResults: BookActSummariesTable[] = await ActRepository.fetchCompleteActSummaryById(actSummaryId, lang);
|
||||
if (actSummaryResults.length > 0) {
|
||||
const actSummaryRecord: BookActSummariesTable = actSummaryResults[0];
|
||||
decryptedActSummaries.push({
|
||||
...actSummaryRecord,
|
||||
summary: actSummaryRecord.summary ? System.decryptDataWithUserKey(actSummaryRecord.summary, userEncryptionKey) : null
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (chapterIds && chapterIds.length > 0) {
|
||||
for (const chapterId of chapterIds) {
|
||||
const chapterResults: BookChaptersTable[] = await ChapterRepo.fetchCompleteChapterById(chapterId, lang);
|
||||
if (chapterResults.length > 0) {
|
||||
const chapterRecord: BookChaptersTable = chapterResults[0];
|
||||
decryptedChapters.push({
|
||||
...chapterRecord,
|
||||
title: System.decryptDataWithUserKey(chapterRecord.title, userEncryptionKey)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (plotPointIds && plotPointIds.length > 0) {
|
||||
for (const plotPointId of plotPointIds) {
|
||||
const plotPointResults: BookPlotPointsTable[] = await PlotPointRepository.fetchCompletePlotPointById(plotPointId, lang);
|
||||
if (plotPointResults.length > 0) {
|
||||
const plotPointRecord: BookPlotPointsTable = plotPointResults[0];
|
||||
decryptedPlotPoints.push({
|
||||
...plotPointRecord,
|
||||
title: System.decryptDataWithUserKey(plotPointRecord.title, userEncryptionKey),
|
||||
summary: plotPointRecord.summary ? System.decryptDataWithUserKey(plotPointRecord.summary, userEncryptionKey) : null
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (incidentIds && incidentIds.length > 0) {
|
||||
for (const incidentId of incidentIds) {
|
||||
const incidentResults: BookIncidentsTable[] = await IncidentRepository.fetchCompleteIncidentById(incidentId, lang);
|
||||
if (incidentResults.length > 0) {
|
||||
const incidentRecord: BookIncidentsTable = incidentResults[0];
|
||||
decryptedIncidents.push({
|
||||
...incidentRecord,
|
||||
title: System.decryptDataWithUserKey(incidentRecord.title, userEncryptionKey),
|
||||
summary: incidentRecord.summary ? System.decryptDataWithUserKey(incidentRecord.summary, userEncryptionKey) : null
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (chapterContentIds && chapterContentIds.length > 0) {
|
||||
for (const chapterContentId of chapterContentIds) {
|
||||
const chapterContentResults: BookChapterContentTable[] = await ChapterContentRepository.fetchCompleteChapterContentById(chapterContentId, lang);
|
||||
if (chapterContentResults.length > 0) {
|
||||
const chapterContentRecord: BookChapterContentTable = chapterContentResults[0];
|
||||
decryptedChapterContents.push({
|
||||
...chapterContentRecord,
|
||||
content: chapterContentRecord.content ? JSON.parse(System.decryptDataWithUserKey(chapterContentRecord.content, userEncryptionKey)) : null
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (chapterInfoIds && chapterInfoIds.length > 0) {
|
||||
for (const chapterInfoId of chapterInfoIds) {
|
||||
const chapterInfoResults: BookChapterInfosTable[] = await ChapterRepo.fetchCompleteChapterInfoById(chapterInfoId, lang);
|
||||
if (chapterInfoResults.length > 0) {
|
||||
const chapterInfoRecord: BookChapterInfosTable = chapterInfoResults[0];
|
||||
decryptedChapterInfos.push({
|
||||
...chapterInfoRecord,
|
||||
summary: chapterInfoRecord.summary ? System.decryptDataWithUserKey(chapterInfoRecord.summary, userEncryptionKey) : null,
|
||||
goal: chapterInfoRecord.goal ? System.decryptDataWithUserKey(chapterInfoRecord.goal, userEncryptionKey) : null
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (characterIds && characterIds.length > 0) {
|
||||
for (const characterId of characterIds) {
|
||||
const characterResults: BookCharactersTable[] = await CharacterRepo.fetchCompleteCharacterById(characterId, lang);
|
||||
if (characterResults.length > 0) {
|
||||
const characterRecord: BookCharactersTable = characterResults[0];
|
||||
decryptedCharacters.push({
|
||||
...characterRecord,
|
||||
first_name: System.decryptDataWithUserKey(characterRecord.first_name, userEncryptionKey),
|
||||
last_name: characterRecord.last_name ? System.decryptDataWithUserKey(characterRecord.last_name, userEncryptionKey) : null,
|
||||
category: System.decryptDataWithUserKey(characterRecord.category, userEncryptionKey),
|
||||
title: characterRecord.title ? System.decryptDataWithUserKey(characterRecord.title, userEncryptionKey) : null,
|
||||
role: characterRecord.role ? System.decryptDataWithUserKey(characterRecord.role, userEncryptionKey) : null,
|
||||
biography: characterRecord.biography ? System.decryptDataWithUserKey(characterRecord.biography, userEncryptionKey) : null,
|
||||
history: characterRecord.history ? System.decryptDataWithUserKey(characterRecord.history, userEncryptionKey) : null
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (characterAttributeIds && characterAttributeIds.length > 0) {
|
||||
for (const characterAttributeId of characterAttributeIds) {
|
||||
const characterAttributeResults: BookCharactersAttributesTable[] = await CharacterRepo.fetchCompleteCharacterAttributeById(characterAttributeId, lang);
|
||||
if (characterAttributeResults.length > 0) {
|
||||
const characterAttributeRecord: BookCharactersAttributesTable = characterAttributeResults[0];
|
||||
decryptedCharacterAttributes.push({
|
||||
...characterAttributeRecord,
|
||||
attribute_name: System.decryptDataWithUserKey(characterAttributeRecord.attribute_name, userEncryptionKey),
|
||||
attribute_value: System.decryptDataWithUserKey(characterAttributeRecord.attribute_value, userEncryptionKey)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (locationIds && locationIds.length > 0) {
|
||||
for (const locationId of locationIds) {
|
||||
const locationResults: BookLocationTable[] = await LocationRepo.fetchCompleteLocationById(locationId, lang);
|
||||
if (locationResults.length > 0) {
|
||||
const locationRecord: BookLocationTable = locationResults[0];
|
||||
decryptedLocations.push({
|
||||
...locationRecord,
|
||||
loc_name: System.decryptDataWithUserKey(locationRecord.loc_name, userEncryptionKey)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (locationElementIds && locationElementIds.length > 0) {
|
||||
for (const locationElementId of locationElementIds) {
|
||||
const locationElementResults: LocationElementTable[] = await LocationRepo.fetchCompleteLocationElementById(locationElementId, lang);
|
||||
if (locationElementResults.length > 0) {
|
||||
const locationElementRecord: LocationElementTable = locationElementResults[0];
|
||||
decryptedLocationElements.push({
|
||||
...locationElementRecord,
|
||||
element_name: System.decryptDataWithUserKey(locationElementRecord.element_name, userEncryptionKey),
|
||||
element_description: locationElementRecord.element_description ? System.decryptDataWithUserKey(locationElementRecord.element_description, userEncryptionKey) : null
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (locationSubElementIds && locationSubElementIds.length > 0) {
|
||||
for (const locationSubElementId of locationSubElementIds) {
|
||||
const locationSubElementResults: LocationSubElementTable[] = await LocationRepo.fetchCompleteLocationSubElementById(locationSubElementId, lang);
|
||||
if (locationSubElementResults.length > 0) {
|
||||
const locationSubElementRecord: LocationSubElementTable = locationSubElementResults[0];
|
||||
decryptedLocationSubElements.push({
|
||||
...locationSubElementRecord,
|
||||
sub_elem_name: System.decryptDataWithUserKey(locationSubElementRecord.sub_elem_name, userEncryptionKey),
|
||||
sub_elem_description: locationSubElementRecord.sub_elem_description ? System.decryptDataWithUserKey(locationSubElementRecord.sub_elem_description, userEncryptionKey) : null
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (worldIds && worldIds.length > 0) {
|
||||
for (const worldId of worldIds) {
|
||||
const worldResults: BookWorldTable[] = await WorldRepository.fetchCompleteWorldById(worldId, lang);
|
||||
if (worldResults.length > 0) {
|
||||
const worldRecord: BookWorldTable = worldResults[0];
|
||||
decryptedWorlds.push({
|
||||
...worldRecord,
|
||||
name: System.decryptDataWithUserKey(worldRecord.name, userEncryptionKey),
|
||||
history: worldRecord.history ? System.decryptDataWithUserKey(worldRecord.history, userEncryptionKey) : null,
|
||||
politics: worldRecord.politics ? System.decryptDataWithUserKey(worldRecord.politics, userEncryptionKey) : null,
|
||||
economy: worldRecord.economy ? System.decryptDataWithUserKey(worldRecord.economy, userEncryptionKey) : null,
|
||||
religion: worldRecord.religion ? System.decryptDataWithUserKey(worldRecord.religion, userEncryptionKey) : null,
|
||||
languages: worldRecord.languages ? System.decryptDataWithUserKey(worldRecord.languages, userEncryptionKey) : null
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (worldElementIds && worldElementIds.length > 0) {
|
||||
for (const worldElementId of worldElementIds) {
|
||||
const worldElementResults: BookWorldElementsTable[] = await WorldRepository.fetchCompleteWorldElementById(worldElementId, lang);
|
||||
if (worldElementResults.length > 0) {
|
||||
const worldElementRecord: BookWorldElementsTable = worldElementResults[0];
|
||||
decryptedWorldElements.push({
|
||||
...worldElementRecord,
|
||||
name: System.decryptDataWithUserKey(worldElementRecord.name, userEncryptionKey),
|
||||
description: worldElementRecord.description ? System.decryptDataWithUserKey(worldElementRecord.description, userEncryptionKey) : null
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (issueIds && issueIds.length > 0) {
|
||||
for (const issueId of issueIds) {
|
||||
const issueResults: BookIssuesTable[] = await IssueRepository.fetchCompleteIssueById(issueId, lang);
|
||||
if (issueResults.length > 0) {
|
||||
const issueRecord: BookIssuesTable = issueResults[0];
|
||||
decryptedIssues.push({
|
||||
...issueRecord,
|
||||
name: System.decryptDataWithUserKey(issueRecord.name, userEncryptionKey)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const bookResults: EritBooksTable[] = await BookRepo.fetchCompleteBookById(syncCompareData.id, lang);
|
||||
if (bookResults.length > 0) {
|
||||
const bookRecord: EritBooksTable = bookResults[0];
|
||||
decryptedBooks.push({
|
||||
...bookRecord,
|
||||
title: System.decryptDataWithUserKey(bookRecord.title, userEncryptionKey),
|
||||
sub_title: bookRecord.sub_title ? System.decryptDataWithUserKey(bookRecord.sub_title, userEncryptionKey) : null,
|
||||
summary: bookRecord.summary ? System.decryptDataWithUserKey(bookRecord.summary, userEncryptionKey) : null,
|
||||
cover_image: bookRecord.cover_image ? System.decryptDataWithUserKey(bookRecord.cover_image, userEncryptionKey) : null
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
eritBooks: decryptedBooks,
|
||||
chapters: decryptedChapters,
|
||||
plotPoints: decryptedPlotPoints,
|
||||
incidents: decryptedIncidents,
|
||||
chapterContents: decryptedChapterContents,
|
||||
chapterInfos: decryptedChapterInfos,
|
||||
characters: decryptedCharacters,
|
||||
characterAttributes: decryptedCharacterAttributes,
|
||||
locations: decryptedLocations,
|
||||
locationElements: decryptedLocationElements,
|
||||
locationSubElements: decryptedLocationSubElements,
|
||||
worlds: decryptedWorlds,
|
||||
worldElements: decryptedWorldElements,
|
||||
actSummaries: decryptedActSummaries,
|
||||
guideLine: decryptedGuideLines,
|
||||
aiGuideLine: decryptedAIGuideLines,
|
||||
issues: decryptedIssues
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronizes a complete book from the server to the local client database.
|
||||
* Encrypts all data before storing and handles both insert and update operations.
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param completeBook - The complete book data received from the server
|
||||
* @param lang - The language for error messages ('fr' or 'en')
|
||||
* @returns A promise resolving to true if sync was successful, false otherwise
|
||||
*/
|
||||
static async syncBookFromServerToClient(userId: string, completeBook: CompleteBook, lang: "fr" | "en"): Promise<boolean> {
|
||||
const userEncryptionKey: string = getUserEncryptionKey(userId);
|
||||
|
||||
const serverActSummaries: BookActSummariesTable[] = completeBook.actSummaries;
|
||||
const serverChapters: BookChaptersTable[] = completeBook.chapters;
|
||||
const serverPlotPoints: BookPlotPointsTable[] = completeBook.plotPoints;
|
||||
const serverIncidents: BookIncidentsTable[] = completeBook.incidents;
|
||||
const serverChapterContents: BookChapterContentTable[] = completeBook.chapterContents;
|
||||
const serverChapterInfos: BookChapterInfosTable[] = completeBook.chapterInfos;
|
||||
const serverCharacters: BookCharactersTable[] = completeBook.characters;
|
||||
const serverCharacterAttributes: BookCharactersAttributesTable[] = completeBook.characterAttributes;
|
||||
const serverLocations: BookLocationTable[] = completeBook.locations;
|
||||
const serverLocationElements: LocationElementTable[] = completeBook.locationElements;
|
||||
const serverLocationSubElements: LocationSubElementTable[] = completeBook.locationSubElements;
|
||||
const serverWorlds: BookWorldTable[] = completeBook.worlds;
|
||||
const serverWorldElements: BookWorldElementsTable[] = completeBook.worldElements;
|
||||
const serverIssues: BookIssuesTable[] = completeBook.issues;
|
||||
|
||||
const bookId: string = completeBook.eritBooks.length > 0 ? completeBook.eritBooks[0].book_id : '';
|
||||
|
||||
if (serverChapters && serverChapters.length > 0) {
|
||||
for (const serverChapter of serverChapters) {
|
||||
const chapterExists: boolean = ChapterRepo.isChapterExist(userId, serverChapter.chapter_id, lang);
|
||||
const encryptedTitle: string = System.encryptDataWithUserKey(serverChapter.title, userEncryptionKey);
|
||||
if (chapterExists) {
|
||||
const updateSuccessful: boolean = ChapterRepo.updateChapter(userId, serverChapter.chapter_id, encryptedTitle, serverChapter.hashed_title, serverChapter.chapter_order, serverChapter.last_update, lang);
|
||||
if (!updateSuccessful) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
const insertSuccessful: boolean = ChapterRepo.insertSyncChapter(serverChapter.chapter_id, serverChapter.book_id, userId, encryptedTitle, serverChapter.hashed_title, serverChapter.words_count || 0, serverChapter.chapter_order, serverChapter.last_update, lang);
|
||||
if (!insertSuccessful) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (serverActSummaries && serverActSummaries.length > 0) {
|
||||
for (const serverActSummary of serverActSummaries) {
|
||||
const actSummaryExists: boolean = ActRepository.actSummarizeExist(userId, bookId, serverActSummary.act_index, lang);
|
||||
const encryptedSummary: string = System.encryptDataWithUserKey(serverActSummary.summary ? serverActSummary.summary : '', userEncryptionKey);
|
||||
if (actSummaryExists) {
|
||||
const updateSuccessful: boolean = ActRepository.updateActSummary(userId, bookId, serverActSummary.act_index, encryptedSummary, serverActSummary.last_update, lang);
|
||||
if (!updateSuccessful) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
const insertSuccessful: boolean = ActRepository.insertSyncActSummary(serverActSummary.act_sum_id, userId, bookId, serverActSummary.act_index, encryptedSummary, serverActSummary.last_update, lang);
|
||||
if (!insertSuccessful) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (serverPlotPoints && serverPlotPoints.length > 0) {
|
||||
for (const serverPlotPoint of serverPlotPoints) {
|
||||
const encryptedTitle: string = System.encryptDataWithUserKey(serverPlotPoint.title, userEncryptionKey);
|
||||
const encryptedSummary: string = System.encryptDataWithUserKey(serverPlotPoint.summary ? serverPlotPoint.summary : '', userEncryptionKey);
|
||||
const plotPointExists: boolean = PlotPointRepository.plotPointExist(userId, bookId, serverPlotPoint.plot_point_id, lang);
|
||||
if (plotPointExists) {
|
||||
const updateSuccessful: boolean = PlotPointRepository.updatePlotPoint(userId, bookId, serverPlotPoint.plot_point_id, encryptedTitle, serverPlotPoint.hashed_title, encryptedSummary, serverPlotPoint.last_update, lang);
|
||||
if (!updateSuccessful) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!serverPlotPoint.linked_incident_id) {
|
||||
return false;
|
||||
}
|
||||
const insertSuccessful: boolean = PlotPointRepository.insertSyncPlotPoint(serverPlotPoint.plot_point_id, encryptedTitle, serverPlotPoint.hashed_title, encryptedSummary, serverPlotPoint.linked_incident_id, serverPlotPoint.author_id, bookId, serverPlotPoint.last_update, lang);
|
||||
if (!insertSuccessful) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (serverIncidents && serverIncidents.length > 0) {
|
||||
for (const serverIncident of serverIncidents) {
|
||||
const encryptedTitle: string = System.encryptDataWithUserKey(serverIncident.title, userEncryptionKey);
|
||||
const encryptedSummary: string = System.encryptDataWithUserKey(serverIncident.summary ? serverIncident.summary : '', userEncryptionKey);
|
||||
const incidentExists: boolean = IncidentRepository.incidentExist(userId, bookId, serverIncident.incident_id, lang);
|
||||
if (incidentExists) {
|
||||
const updateSuccessful: boolean = IncidentRepository.updateIncident(userId, bookId, serverIncident.incident_id, encryptedTitle, serverIncident.hashed_title, encryptedSummary, serverIncident.last_update, lang);
|
||||
if (!updateSuccessful) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
const insertSuccessful: boolean = IncidentRepository.insertSyncIncident(serverIncident.incident_id, userId, bookId, encryptedTitle, serverIncident.hashed_title, encryptedSummary, serverIncident.last_update, lang);
|
||||
if (!insertSuccessful) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (serverChapterContents && serverChapterContents.length > 0) {
|
||||
for (const serverChapterContent of serverChapterContents) {
|
||||
const chapterContentExists: boolean = ChapterContentRepository.isChapterContentExist(userId, serverChapterContent.content_id, lang);
|
||||
const encryptedContent: string = System.encryptDataWithUserKey(serverChapterContent.content ? JSON.stringify(serverChapterContent.content) : '', userEncryptionKey);
|
||||
if (chapterContentExists) {
|
||||
const updateSuccessful: boolean = ChapterContentRepository.updateChapterContent(userId, serverChapterContent.chapter_id, serverChapterContent.version, encryptedContent, serverChapterContent.words_count, serverChapterContent.last_update);
|
||||
if (!updateSuccessful) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
const insertSuccessful: boolean = ChapterContentRepository.insertSyncChapterContent(serverChapterContent.content_id, serverChapterContent.chapter_id, userId, serverChapterContent.version, encryptedContent, serverChapterContent.words_count, serverChapterContent.time_on_it, serverChapterContent.last_update, lang);
|
||||
if (!insertSuccessful) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (serverChapterInfos && serverChapterInfos.length > 0) {
|
||||
for (const serverChapterInfo of serverChapterInfos) {
|
||||
const chapterInfoExists: boolean = ChapterRepo.isChapterInfoExist(userId, serverChapterInfo.chapter_id, lang);
|
||||
const encryptedSummary: string = System.encryptDataWithUserKey(serverChapterInfo.summary ? serverChapterInfo.summary : '', userEncryptionKey);
|
||||
const encryptedGoal: string = System.encryptDataWithUserKey(serverChapterInfo.goal ? serverChapterInfo.goal : '', userEncryptionKey);
|
||||
if (chapterInfoExists) {
|
||||
const updateSuccessful: boolean = ChapterRepo.updateChapterInfos(userId, serverChapterInfo.chapter_id, serverChapterInfo.act_id, bookId, serverChapterInfo.incident_id, serverChapterInfo.plot_point_id, encryptedSummary, encryptedGoal, serverChapterInfo.last_update, lang);
|
||||
if (!updateSuccessful) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
const insertSuccessful: boolean = ChapterRepo.insertSyncChapterInfo(serverChapterInfo.chapter_info_id, serverChapterInfo.chapter_id, serverChapterInfo.act_id, serverChapterInfo.incident_id, serverChapterInfo.plot_point_id, bookId, serverChapterInfo.author_id, encryptedSummary, encryptedGoal, serverChapterInfo.last_update, lang);
|
||||
if (!insertSuccessful) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (serverCharacters && serverCharacters.length > 0) {
|
||||
for (const serverCharacter of serverCharacters) {
|
||||
const characterExists: boolean = CharacterRepo.isCharacterExist(userId, serverCharacter.character_id, lang);
|
||||
const encryptedFirstName: string = System.encryptDataWithUserKey(serverCharacter.first_name, userEncryptionKey);
|
||||
const encryptedLastName: string = System.encryptDataWithUserKey(serverCharacter.last_name ? serverCharacter.last_name : '', userEncryptionKey);
|
||||
const encryptedCategory: string = System.encryptDataWithUserKey(serverCharacter.category, userEncryptionKey);
|
||||
const encryptedTitle: string = System.encryptDataWithUserKey(serverCharacter.title ? serverCharacter.title : '', userEncryptionKey);
|
||||
const encryptedRole: string = System.encryptDataWithUserKey(serverCharacter.role ? serverCharacter.role : '', userEncryptionKey);
|
||||
const encryptedImage: string = System.encryptDataWithUserKey(serverCharacter.image ? serverCharacter.image : '', userEncryptionKey);
|
||||
const encryptedBiography: string = System.encryptDataWithUserKey(serverCharacter.biography ? serverCharacter.biography : '', userEncryptionKey);
|
||||
const encryptedHistory: string = System.encryptDataWithUserKey(serverCharacter.history ? serverCharacter.history : '', userEncryptionKey);
|
||||
if (characterExists) {
|
||||
const updateSuccessful: boolean = CharacterRepo.updateCharacter(userId, serverCharacter.character_id, encryptedFirstName, encryptedLastName, encryptedTitle, encryptedCategory, encryptedImage, encryptedRole, encryptedBiography, encryptedHistory, serverCharacter.last_update);
|
||||
if (!updateSuccessful) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
const insertSuccessful: boolean = CharacterRepo.insertSyncCharacter(serverCharacter.character_id, bookId, userId, encryptedFirstName, encryptedLastName, encryptedCategory, encryptedTitle, encryptedImage, encryptedRole, encryptedBiography, encryptedHistory, serverCharacter.last_update, lang);
|
||||
if (!insertSuccessful) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (serverCharacterAttributes && serverCharacterAttributes.length > 0) {
|
||||
for (const serverCharacterAttribute of serverCharacterAttributes) {
|
||||
const characterAttributeExists: boolean = CharacterRepo.isCharacterAttributeExist(userId, serverCharacterAttribute.attr_id, lang);
|
||||
const encryptedAttributeName: string = System.encryptDataWithUserKey(serverCharacterAttribute.attribute_name, userEncryptionKey);
|
||||
const encryptedAttributeValue: string = System.encryptDataWithUserKey(serverCharacterAttribute.attribute_value, userEncryptionKey);
|
||||
if (characterAttributeExists) {
|
||||
const updateSuccessful: boolean = CharacterRepo.updateCharacterAttribute(userId, serverCharacterAttribute.attr_id, encryptedAttributeName, encryptedAttributeValue, serverCharacterAttribute.last_update, lang);
|
||||
if (!updateSuccessful) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
const insertSuccessful: boolean = CharacterRepo.insertSyncCharacterAttribute(serverCharacterAttribute.attr_id, serverCharacterAttribute.character_id, userId, encryptedAttributeName, encryptedAttributeValue, serverCharacterAttribute.last_update, lang);
|
||||
if (!insertSuccessful) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (serverLocations && serverLocations.length > 0) {
|
||||
for (const serverLocation of serverLocations) {
|
||||
const locationExists: boolean = LocationRepo.isLocationExist(userId, serverLocation.loc_id, lang);
|
||||
const encryptedLocationName: string = System.encryptDataWithUserKey(serverLocation.loc_name, userEncryptionKey);
|
||||
if (locationExists) {
|
||||
const updateSuccessful: boolean = LocationRepo.updateLocationSection(userId, serverLocation.loc_id, encryptedLocationName, serverLocation.loc_original_name, serverLocation.last_update, lang);
|
||||
if (!updateSuccessful) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
const insertSuccessful: boolean = LocationRepo.insertSyncLocation(serverLocation.loc_id, bookId, userId, encryptedLocationName, serverLocation.loc_original_name, serverLocation.last_update, lang);
|
||||
if (!insertSuccessful) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (serverLocationElements && serverLocationElements.length > 0) {
|
||||
for (const serverLocationElement of serverLocationElements) {
|
||||
const locationElementExists: boolean = LocationRepo.isLocationElementExist(userId, serverLocationElement.element_id, lang);
|
||||
const encryptedElementName: string = System.encryptDataWithUserKey(serverLocationElement.element_name, userEncryptionKey);
|
||||
const encryptedElementDescription: string = System.encryptDataWithUserKey(serverLocationElement.element_description ? serverLocationElement.element_description : '', userEncryptionKey);
|
||||
if (locationElementExists) {
|
||||
const updateSuccessful: boolean = LocationRepo.updateLocationElement(userId, serverLocationElement.element_id, encryptedElementName, serverLocationElement.original_name, encryptedElementDescription, serverLocationElement.last_update, lang);
|
||||
if (!updateSuccessful) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
const insertSuccessful: boolean = LocationRepo.insertSyncLocationElement(serverLocationElement.element_id, serverLocationElement.location, userId, encryptedElementName, serverLocationElement.original_name, encryptedElementDescription, serverLocationElement.last_update, lang);
|
||||
if (!insertSuccessful) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (serverLocationSubElements && serverLocationSubElements.length > 0) {
|
||||
for (const serverLocationSubElement of serverLocationSubElements) {
|
||||
const locationSubElementExists: boolean = LocationRepo.isLocationSubElementExist(userId, serverLocationSubElement.sub_element_id, lang);
|
||||
const encryptedSubElementName: string = System.encryptDataWithUserKey(serverLocationSubElement.sub_elem_name, userEncryptionKey);
|
||||
const encryptedSubElementDescription: string = System.encryptDataWithUserKey(serverLocationSubElement.sub_elem_description ? serverLocationSubElement.sub_elem_description : '', userEncryptionKey);
|
||||
if (locationSubElementExists) {
|
||||
const updateSuccessful: boolean = LocationRepo.updateLocationSubElement(userId, serverLocationSubElement.sub_element_id, encryptedSubElementName, serverLocationSubElement.original_name, encryptedSubElementDescription, serverLocationSubElement.last_update, lang);
|
||||
if (!updateSuccessful) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
const insertSuccessful: boolean = LocationRepo.insertSyncLocationSubElement(serverLocationSubElement.sub_element_id, serverLocationSubElement.element_id, userId, encryptedSubElementName, serverLocationSubElement.original_name, encryptedSubElementDescription, serverLocationSubElement.last_update, lang);
|
||||
if (!insertSuccessful) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (serverWorlds && serverWorlds.length > 0) {
|
||||
for (const serverWorld of serverWorlds) {
|
||||
const worldExists: boolean = WorldRepository.worldExist(userId, bookId, serverWorld.world_id, lang);
|
||||
const encryptedName: string = System.encryptDataWithUserKey(serverWorld.name, userEncryptionKey);
|
||||
const encryptedHistory: string = System.encryptDataWithUserKey(serverWorld.history ? serverWorld.history : '', userEncryptionKey);
|
||||
const encryptedPolitics: string = System.encryptDataWithUserKey(serverWorld.politics ? serverWorld.politics : '', userEncryptionKey);
|
||||
const encryptedEconomy: string = System.encryptDataWithUserKey(serverWorld.economy ? serverWorld.economy : '', userEncryptionKey);
|
||||
const encryptedReligion: string = System.encryptDataWithUserKey(serverWorld.religion ? serverWorld.religion : '', userEncryptionKey);
|
||||
const encryptedLanguages: string = System.encryptDataWithUserKey(serverWorld.languages ? serverWorld.languages : '', userEncryptionKey);
|
||||
if (worldExists) {
|
||||
const updateSuccessful: boolean = WorldRepository.updateWorld(userId, serverWorld.world_id, encryptedName, serverWorld.hashed_name, encryptedHistory, encryptedPolitics, encryptedEconomy, encryptedReligion, encryptedLanguages, serverWorld.last_update, lang);
|
||||
if (!updateSuccessful) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
const insertSuccessful: boolean = WorldRepository.insertSyncWorld(serverWorld.world_id, encryptedName, serverWorld.hashed_name, userId, bookId, encryptedHistory, encryptedPolitics, encryptedEconomy, encryptedReligion, encryptedLanguages, serverWorld.last_update, lang);
|
||||
if (!insertSuccessful) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (serverWorldElements && serverWorldElements.length > 0) {
|
||||
for (const serverWorldElement of serverWorldElements) {
|
||||
const worldElementExists: boolean = WorldRepository.worldElementExist(userId, serverWorldElement.world_id, serverWorldElement.element_id, lang);
|
||||
const encryptedName: string = System.encryptDataWithUserKey(serverWorldElement.name, userEncryptionKey);
|
||||
const encryptedDescription: string = System.encryptDataWithUserKey(serverWorldElement.description ? serverWorldElement.description : '', userEncryptionKey);
|
||||
if (worldElementExists) {
|
||||
const updateSuccessful: boolean = WorldRepository.updateWorldElement(userId, serverWorldElement.element_id, encryptedName, encryptedDescription, serverWorldElement.last_update, lang);
|
||||
if (!updateSuccessful) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
const insertSuccessful: boolean = WorldRepository.insertSyncWorldElement(serverWorldElement.element_id, serverWorldElement.world_id, userId, serverWorldElement.element_type, encryptedName, serverWorldElement.original_name, encryptedDescription, serverWorldElement.last_update, lang);
|
||||
if (!insertSuccessful) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (serverIssues && serverIssues.length > 0) {
|
||||
for (const serverIssue of serverIssues) {
|
||||
const issueExists: boolean = IssueRepository.issueExist(userId, bookId, serverIssue.issue_id, lang);
|
||||
const encryptedName: string = System.encryptDataWithUserKey(serverIssue.name, userEncryptionKey);
|
||||
if (issueExists) {
|
||||
const updateSuccessful: boolean = IssueRepository.updateIssue(userId, bookId, serverIssue.issue_id, encryptedName, serverIssue.hashed_issue_name, serverIssue.last_update, lang);
|
||||
if (!updateSuccessful) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
const insertSuccessful: boolean = IssueRepository.insertSyncIssue(serverIssue.issue_id, userId, bookId, encryptedName, serverIssue.hashed_issue_name, serverIssue.last_update, lang);
|
||||
if (!insertSuccessful) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all synced books for a user with their complete hierarchical data structure.
|
||||
* Fetches all related entities (chapters, characters, locations, etc.) and organizes them by book.
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param lang - The language for error messages ('fr' or 'en')
|
||||
* @returns A promise resolving to an array of SyncedBook objects with decrypted data
|
||||
*/
|
||||
static async getSyncedBooks(userId: string, lang: 'fr' | 'en'): Promise<SyncedBook[]> {
|
||||
const userEncryptionKey: string = getUserEncryptionKey(userId);
|
||||
|
||||
const [
|
||||
allBooks,
|
||||
allChapters,
|
||||
allChapterContents,
|
||||
allChapterInfos,
|
||||
allCharacters,
|
||||
allCharacterAttributes,
|
||||
allLocations,
|
||||
allLocationElements,
|
||||
allLocationSubElements,
|
||||
allWorlds,
|
||||
allWorldElements,
|
||||
allIncidents,
|
||||
allPlotPoints,
|
||||
allIssues,
|
||||
allActSummaries,
|
||||
allGuidelines,
|
||||
allAIGuidelines
|
||||
]: [
|
||||
SyncedBookResult[],
|
||||
SyncedChapterResult[],
|
||||
SyncedChapterContentResult[],
|
||||
SyncedChapterInfoResult[],
|
||||
SyncedCharacterResult[],
|
||||
SyncedCharacterAttributeResult[],
|
||||
SyncedLocationResult[],
|
||||
SyncedLocationElementResult[],
|
||||
SyncedLocationSubElementResult[],
|
||||
SyncedWorldResult[],
|
||||
SyncedWorldElementResult[],
|
||||
SyncedIncidentResult[],
|
||||
SyncedPlotPointResult[],
|
||||
SyncedIssueResult[],
|
||||
SyncedActSummaryResult[],
|
||||
SyncedGuideLineResult[],
|
||||
SyncedAIGuideLineResult[]
|
||||
] = await Promise.all([
|
||||
BookRepo.fetchSyncedBooks(userId, lang),
|
||||
ChapterRepo.fetchSyncedChapters(userId, lang),
|
||||
ChapterContentRepository.fetchSyncedChapterContents(userId, lang),
|
||||
ChapterRepo.fetchSyncedChapterInfos(userId, lang),
|
||||
CharacterRepo.fetchSyncedCharacters(userId, lang),
|
||||
CharacterRepo.fetchSyncedCharacterAttributes(userId, lang),
|
||||
LocationRepo.fetchSyncedLocations(userId, lang),
|
||||
LocationRepo.fetchSyncedLocationElements(userId, lang),
|
||||
LocationRepo.fetchSyncedLocationSubElements(userId, lang),
|
||||
WorldRepository.fetchSyncedWorlds(userId, lang),
|
||||
WorldRepository.fetchSyncedWorldElements(userId, lang),
|
||||
IncidentRepository.fetchSyncedIncidents(userId, lang),
|
||||
PlotPointRepository.fetchSyncedPlotPoints(userId, lang),
|
||||
IssueRepository.fetchSyncedIssues(userId, lang),
|
||||
ActRepository.fetchSyncedActSummaries(userId, lang),
|
||||
GuidelineRepo.fetchSyncedAIGuideLine(userId, lang),
|
||||
GuidelineRepo.fetchSyncedGuideLine(userId, lang)
|
||||
]);
|
||||
|
||||
return allBooks.map((bookRecord: SyncedBookResult): SyncedBook => {
|
||||
const currentBookId: string = bookRecord.book_id;
|
||||
|
||||
const bookChapters: SyncedChapter[] = allChapters
|
||||
.filter((chapterRecord: SyncedChapterResult): boolean => chapterRecord.book_id === currentBookId)
|
||||
.map((chapterRecord: SyncedChapterResult): SyncedChapter => {
|
||||
const currentChapterId: string = chapterRecord.chapter_id;
|
||||
|
||||
const chapterContents: SyncedChapterContent[] = allChapterContents
|
||||
.filter((contentRecord: SyncedChapterContentResult): boolean => contentRecord.chapter_id === currentChapterId)
|
||||
.map((contentRecord: SyncedChapterContentResult): SyncedChapterContent => ({
|
||||
id: contentRecord.content_id,
|
||||
lastUpdate: contentRecord.last_update
|
||||
}));
|
||||
|
||||
const chapterInfoRecord: SyncedChapterInfoResult | undefined = allChapterInfos.find((infoRecord: SyncedChapterInfoResult): boolean => infoRecord.chapter_id === currentChapterId);
|
||||
const chapterInfo: SyncedChapterInfo | null = chapterInfoRecord ? {
|
||||
id: chapterInfoRecord.chapter_info_id,
|
||||
lastUpdate: chapterInfoRecord.last_update
|
||||
} : null;
|
||||
|
||||
return {
|
||||
id: currentChapterId,
|
||||
name: System.decryptDataWithUserKey(chapterRecord.title, userEncryptionKey),
|
||||
lastUpdate: chapterRecord.last_update,
|
||||
contents: chapterContents,
|
||||
info: chapterInfo
|
||||
};
|
||||
});
|
||||
|
||||
const bookCharacters: SyncedCharacter[] = allCharacters
|
||||
.filter((characterRecord: SyncedCharacterResult): boolean => characterRecord.book_id === currentBookId)
|
||||
.map((characterRecord: SyncedCharacterResult): SyncedCharacter => {
|
||||
const currentCharacterId: string = characterRecord.character_id;
|
||||
|
||||
const characterAttributes: SyncedCharacterAttribute[] = allCharacterAttributes
|
||||
.filter((attributeRecord: SyncedCharacterAttributeResult): boolean => attributeRecord.character_id === currentCharacterId)
|
||||
.map((attributeRecord: SyncedCharacterAttributeResult): SyncedCharacterAttribute => ({
|
||||
id: attributeRecord.attr_id,
|
||||
name: System.decryptDataWithUserKey(attributeRecord.attribute_name, userEncryptionKey),
|
||||
lastUpdate: attributeRecord.last_update
|
||||
}));
|
||||
|
||||
return {
|
||||
id: currentCharacterId,
|
||||
name: System.decryptDataWithUserKey(characterRecord.first_name, userEncryptionKey),
|
||||
lastUpdate: characterRecord.last_update,
|
||||
attributes: characterAttributes
|
||||
};
|
||||
});
|
||||
|
||||
const bookLocations: SyncedLocation[] = allLocations
|
||||
.filter((locationRecord: SyncedLocationResult): boolean => locationRecord.book_id === currentBookId)
|
||||
.map((locationRecord: SyncedLocationResult): SyncedLocation => {
|
||||
const currentLocationId: string = locationRecord.loc_id;
|
||||
|
||||
const locationElements: SyncedLocationElement[] = allLocationElements
|
||||
.filter((elementRecord: SyncedLocationElementResult): boolean => elementRecord.location === currentLocationId)
|
||||
.map((elementRecord: SyncedLocationElementResult): SyncedLocationElement => {
|
||||
const currentElementId: string = elementRecord.element_id;
|
||||
|
||||
const locationSubElements: SyncedLocationSubElement[] = allLocationSubElements
|
||||
.filter((subElementRecord: SyncedLocationSubElementResult): boolean => subElementRecord.element_id === currentElementId)
|
||||
.map((subElementRecord: SyncedLocationSubElementResult): SyncedLocationSubElement => ({
|
||||
id: subElementRecord.sub_element_id,
|
||||
name: System.decryptDataWithUserKey(subElementRecord.sub_elem_name, userEncryptionKey),
|
||||
lastUpdate: subElementRecord.last_update
|
||||
}));
|
||||
|
||||
return {
|
||||
id: currentElementId,
|
||||
name: System.decryptDataWithUserKey(elementRecord.element_name, userEncryptionKey),
|
||||
lastUpdate: elementRecord.last_update,
|
||||
subElements: locationSubElements
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
id: currentLocationId,
|
||||
name: System.decryptDataWithUserKey(locationRecord.loc_name, userEncryptionKey),
|
||||
lastUpdate: locationRecord.last_update,
|
||||
elements: locationElements
|
||||
};
|
||||
});
|
||||
|
||||
const bookWorlds: SyncedWorld[] = allWorlds
|
||||
.filter((worldRecord: SyncedWorldResult): boolean => worldRecord.book_id === currentBookId)
|
||||
.map((worldRecord: SyncedWorldResult): SyncedWorld => {
|
||||
const currentWorldId: string = worldRecord.world_id;
|
||||
|
||||
const worldElements: SyncedWorldElement[] = allWorldElements
|
||||
.filter((worldElementRecord: SyncedWorldElementResult): boolean => worldElementRecord.world_id === currentWorldId)
|
||||
.map((worldElementRecord: SyncedWorldElementResult): SyncedWorldElement => ({
|
||||
id: worldElementRecord.element_id,
|
||||
name: System.decryptDataWithUserKey(worldElementRecord.name, userEncryptionKey),
|
||||
lastUpdate: worldElementRecord.last_update
|
||||
}));
|
||||
|
||||
return {
|
||||
id: currentWorldId,
|
||||
name: System.decryptDataWithUserKey(worldRecord.name, userEncryptionKey),
|
||||
lastUpdate: worldRecord.last_update,
|
||||
elements: worldElements
|
||||
};
|
||||
});
|
||||
|
||||
const bookIncidents: SyncedIncident[] = allIncidents
|
||||
.filter((incidentRecord: SyncedIncidentResult): boolean => incidentRecord.book_id === currentBookId)
|
||||
.map((incidentRecord: SyncedIncidentResult): SyncedIncident => ({
|
||||
id: incidentRecord.incident_id,
|
||||
name: System.decryptDataWithUserKey(incidentRecord.title, userEncryptionKey),
|
||||
lastUpdate: incidentRecord.last_update
|
||||
}));
|
||||
|
||||
const bookPlotPoints: SyncedPlotPoint[] = allPlotPoints
|
||||
.filter((plotPointRecord: SyncedPlotPointResult): boolean => plotPointRecord.book_id === currentBookId)
|
||||
.map((plotPointRecord: SyncedPlotPointResult): SyncedPlotPoint => ({
|
||||
id: plotPointRecord.plot_point_id,
|
||||
name: System.decryptDataWithUserKey(plotPointRecord.title, userEncryptionKey),
|
||||
lastUpdate: plotPointRecord.last_update
|
||||
}));
|
||||
|
||||
const bookIssues: SyncedIssue[] = allIssues
|
||||
.filter((issueRecord: SyncedIssueResult): boolean => issueRecord.book_id === currentBookId)
|
||||
.map((issueRecord: SyncedIssueResult): SyncedIssue => ({
|
||||
id: issueRecord.issue_id,
|
||||
name: System.decryptDataWithUserKey(issueRecord.name, userEncryptionKey),
|
||||
lastUpdate: issueRecord.last_update
|
||||
}));
|
||||
|
||||
const bookActSummaries: SyncedActSummary[] = allActSummaries
|
||||
.filter((actSummaryRecord: SyncedActSummaryResult): boolean => actSummaryRecord.book_id === currentBookId)
|
||||
.map((actSummaryRecord: SyncedActSummaryResult): SyncedActSummary => ({
|
||||
id: actSummaryRecord.act_sum_id,
|
||||
lastUpdate: actSummaryRecord.last_update
|
||||
}));
|
||||
|
||||
const guidelineRecord: SyncedGuideLineResult | undefined = allGuidelines.find((guidelineItem: SyncedGuideLineResult): boolean => guidelineItem.book_id === currentBookId);
|
||||
const bookGuideLine: SyncedGuideLine | null = guidelineRecord ? {
|
||||
lastUpdate: guidelineRecord.last_update
|
||||
} : null;
|
||||
|
||||
const aiGuidelineRecord: SyncedAIGuideLineResult | undefined = allAIGuidelines.find((aiGuidelineItem: SyncedAIGuideLineResult): boolean => aiGuidelineItem.book_id === currentBookId);
|
||||
const bookAIGuideLine: SyncedAIGuideLine | null = aiGuidelineRecord ? {
|
||||
lastUpdate: aiGuidelineRecord.last_update
|
||||
} : null;
|
||||
|
||||
return {
|
||||
id: currentBookId,
|
||||
type: bookRecord.type,
|
||||
title: System.decryptDataWithUserKey(bookRecord.title, userEncryptionKey),
|
||||
subTitle: bookRecord.sub_title ? System.decryptDataWithUserKey(bookRecord.sub_title, userEncryptionKey) : null,
|
||||
lastUpdate: bookRecord.last_update,
|
||||
chapters: bookChapters,
|
||||
characters: bookCharacters,
|
||||
locations: bookLocations,
|
||||
worlds: bookWorlds,
|
||||
incidents: bookIncidents,
|
||||
plotPoints: bookPlotPoints,
|
||||
issues: bookIssues,
|
||||
actSummaries: bookActSummaries,
|
||||
guideLine: bookGuideLine,
|
||||
aiGuideLine: bookAIGuideLine
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user