From 9648d9e9be965496884a3049b6902665ed262aaf Mon Sep 17 00:00:00 2001 From: natreex Date: Wed, 26 Nov 2025 19:17:40 -0500 Subject: [PATCH] Upgrade database schema to version 2 and remove unused `meta_*` columns - Increment `SCHEMA_VERSION` to 2 in `schema.ts`. - Remove all `meta_*` columns from database tables. - Add migration logic to handle schema upgrades and clean up unused columns. - Modify database models and repository methods to exclude `meta_*` fields for stricter typings and improved structure. - Refactor and optimize query statements across repositories to align with new schema changes. --- components/leftbar/ScribeChapterComponent.tsx | 59 +++++++--- components/rightbar/ComposerRightBar.tsx | 1 - context/AlertProvider.tsx | 3 +- electron/database/database.service.ts | 7 +- electron/database/models/Book.ts | 2 - electron/database/models/Character.ts | 6 +- .../database/repositories/book.repository.ts | 33 ++---- .../repositories/chapter.repository.ts | 38 +++--- .../repositories/character.repository.ts | 10 +- .../repositories/location.repository.ts | 15 +-- .../database/repositories/user.repository.ts | 21 ++-- electron/database/schema.ts | 108 ++++++++++++++---- electron/ipc/chapter.ipc.ts | 6 +- 13 files changed, 178 insertions(+), 131 deletions(-) diff --git a/components/leftbar/ScribeChapterComponent.tsx b/components/leftbar/ScribeChapterComponent.tsx index c6bd1c2..419b8e4 100644 --- a/components/leftbar/ScribeChapterComponent.tsx +++ b/components/leftbar/ScribeChapterComponent.tsx @@ -11,10 +11,12 @@ import AlertBox from "@/components/AlertBox"; import {useTranslations} from "next-intl"; import InlineAddInput from "@/components/form/InlineAddInput"; import {LangContext} from "@/context/LangContext"; +import OfflineContext, {OfflineContextType} from "@/context/OfflineContext"; export default function ScribeChapterComponent() { const t = useTranslations(); - const {lang} = useContext(LangContext) + const {lang} = useContext(LangContext); + const {isCurrentlyOffline} = useContext(OfflineContext); const {book} = useContext(BookContext); const {chapter, setChapter} = useContext(ChapterContext); @@ -43,18 +45,16 @@ export default function ScribeChapterComponent() { useEffect((): void => { if (chapter?.chapterId && scrollContainerRef.current) { - // Small delay to ensure DOM is ready setTimeout(() => { const element = chapterRefs.current.get(chapter.chapterId); const container = scrollContainerRef.current; if (element && container) { - const containerRect = container.getBoundingClientRect(); - const elementRect = element.getBoundingClientRect(); + const containerRect:DOMRect = container.getBoundingClientRect(); + const elementRect:DOMRect = element.getBoundingClientRect(); - // Calculate relative position - const relativeTop = elementRect.top - containerRect.top + container.scrollTop; - const scrollPosition = relativeTop - (containerRect.height / 2) + (elementRect.height / 2); + const relativeTop:number = elementRect.top - containerRect.top + container.scrollTop; + const scrollPosition:number = relativeTop - (containerRect.height / 2) + (elementRect.height / 2); container.scrollTo({ top: Math.max(0, scrollPosition), @@ -72,7 +72,12 @@ export default function ScribeChapterComponent() { async function getChapterList(): Promise { try { - const response: ChapterListProps[] = await System.authGetQueryToServer(`book/chapters?id=${book?.bookId}`, userToken, lang); + let response: ChapterListProps[]|null; + if (isCurrentlyOffline()){ + response = await window.electron.invoke('db:book:chapters', book?.bookId) + } else { + response = await System.authGetQueryToServer(`book/chapters?id=${book?.bookId}`, userToken, lang); + } if (response) { setChapters(response); } @@ -88,11 +93,20 @@ export default function ScribeChapterComponent() { async function getChapter(chapterId: string): Promise { const version: number = chapter?.chapterContent.version ? chapter?.chapterContent.version : 2; try { - const response: ChapterProps = await System.authGetQueryToServer(`chapter/whole`, userToken, lang, { - bookid: book?.bookId, - id: chapterId, - version: version, - }); + let response: ChapterProps | null = null + if (isCurrentlyOffline()) { + response = await window.electron.invoke('db:chapter:whole', { + bookid: book?.bookId, + id: chapterId, + version: version, + }) + } else { + response = await System.authGetQueryToServer(`chapter/whole`, userToken, lang, { + bookid: book?.bookId, + id: chapterId, + version: version, + }); + } if (!response) { errorMessage(t("scribeChapterComponent.errorFetchChapter")); return; @@ -173,11 +187,20 @@ export default function ScribeChapterComponent() { } const chapterTitle: string = chapterOrder >= 0 ? newChapterName : book?.title as string; try { - const chapterId: string = await System.authPostToServer('chapter/add', { - bookId: book?.bookId, - chapterOrder: chapterOrder, - title: chapterTitle - }, userToken, lang); + let chapterId:string|null = null; + if (isCurrentlyOffline()){ + chapterId = await window.electron.invoke('db:chapter:create', { + bookId: book?.bookId, + chapterOrder: chapterOrder, + title: chapterTitle + }) + } else { + chapterId = await System.authPostToServer('chapter/add', { + bookId: book?.bookId, + chapterOrder: chapterOrder, + title: chapterTitle + }, userToken, lang); + } if (!chapterId) { errorMessage(t("scribeChapterComponent.errorChapterSubmit", {chapterName: newChapterName})); return; diff --git a/components/rightbar/ComposerRightBar.tsx b/components/rightbar/ComposerRightBar.tsx index f438d6b..4ec7ba8 100644 --- a/components/rightbar/ComposerRightBar.tsx +++ b/components/rightbar/ComposerRightBar.tsx @@ -16,7 +16,6 @@ import OfflineContext, {OfflineContextType} from "@/context/OfflineContext"; export default function ComposerRightBar() { const {book} = useContext(BookContext); - const {chapter} = useContext(ChapterContext); const t = useTranslations(); diff --git a/context/AlertProvider.tsx b/context/AlertProvider.tsx index 2abc819..acc8792 100644 --- a/context/AlertProvider.tsx +++ b/context/AlertProvider.tsx @@ -3,6 +3,7 @@ import type {Context, Dispatch, JSX, ReactNode, SetStateAction} from 'react'; import {createContext, useCallback, useState} from 'react'; import AlertStack from '@/components/AlertStack'; +import {cleanErrorMessage} from '@/lib/errors'; export type AlertType = 'success' | 'error' | 'info' | 'warning'; @@ -53,7 +54,7 @@ export function AlertProvider({children}: AlertProviderProps): JSX.Element { }, [addAlert]); const errorMessage: (message: string) => void = useCallback((message: string): void => { - addAlert('error', message); + addAlert('error', cleanErrorMessage(message)); }, [addAlert]); const infoMessage: (message: string) => void = useCallback((message: string): void => { diff --git a/electron/database/database.service.ts b/electron/database/database.service.ts index cb34a33..2194a72 100644 --- a/electron/database/database.service.ts +++ b/electron/database/database.service.ts @@ -1,7 +1,7 @@ import sqlite3 from 'node-sqlite3-wasm'; import path from 'path'; import { app } from 'electron'; -import { initializeSchema } from './schema.js'; +import { initializeSchema, runMigrations } from './schema.js'; // Type alias for compatibility export type Database = sqlite3.Database; @@ -36,9 +36,12 @@ export class DatabaseService { this.userEncryptionKey = encryptionKey; this.userId = userId; - // Initialize schema + // Initialize schema (creates tables if they don't exist) initializeSchema(this.db); + // Run migrations (updates existing tables if needed) + runMigrations(this.db); + console.log(`Database initialized for user ${userId} at ${dbPath}`); } diff --git a/electron/database/models/Book.ts b/electron/database/models/Book.ts index ebd07d0..570f25c 100644 --- a/electron/database/models/Book.ts +++ b/electron/database/models/Book.ts @@ -844,8 +844,6 @@ export default class Book { const decryptedChapters: any[] = []; for (const chapter of chapters) { - if (!chapter.meta_chapter) continue; - if (!chapter.meta_chapter_content) continue; decryptedChapters.push({ id: '', title: chapter.title ? System.decryptDataWithUserKey(chapter.title, userKey) : '', diff --git a/electron/database/models/Character.ts b/electron/database/models/Character.ts index 3c34620..eebcd71 100644 --- a/electron/database/models/Character.ts +++ b/electron/database/models/Character.ts @@ -206,11 +206,7 @@ export default class Character { const personnage: CompleteCharacterProps | undefined = completeCharactersMap.get(character.character_id); - if (!character.attr_meta) { - continue; - } - - if (!personnage) { + if (!character.attribute_name || !personnage) { continue; } const decryptedName: string = System.decryptDataWithUserKey(character.attribute_name, userKey); diff --git a/electron/database/repositories/book.repository.ts b/electron/database/repositories/book.repository.ts index a93479f..6b33ba2 100644 --- a/electron/database/repositories/book.repository.ts +++ b/electron/database/repositories/book.repository.ts @@ -15,7 +15,6 @@ export interface BookQuery extends Record { desired_word_count: number | null; words_count: number | null; cover_image: string | null; - book_meta: string | null; } export interface GuideLineQuery extends Record { @@ -29,7 +28,6 @@ export interface GuideLineQuery extends Record { pacing: string; intended_audience: string; key_messages: string; - meta_guide_line: string; } export interface PlotPointQuery extends Record { @@ -37,43 +35,32 @@ export interface PlotPointQuery extends Record { title: string; summary: string; linked_incident_id: string | null; - meta_plot: string; } export interface IncidentQuery extends Record { incident_id: string; title: string; summary: string; - meta_incident: string; } export interface IssueQuery extends Record { issue_id: string; name: string; - meta_issue: string; } export interface ActQuery extends Record { act_index: number; summary: string; - meta_acts: string; -} - -export interface MetaBookQuery extends Record { - book_meta: string; } export interface BookCoverQuery extends Record { cover_image: string; - book_meta: string; } export interface ChapterBookResult extends Record { title: string; chapter_order: number; - meta_chapter: string; content: string | null; - meta_chapter_content: string | null; } export interface WorldQuery extends Record { @@ -84,12 +71,10 @@ export interface WorldQuery extends Record { economy: string | null; religion: string | null; languages: string | null; - meta_world: string; element_id: string | null; element_name: string | null; element_description: string | null; element_type: number | null; - meta_element: string | null; } export interface WorldElementValue { @@ -118,7 +103,7 @@ export default class BookRepo { public static fetchBooks(userId: string, lang: 'fr' | 'en'): BookQuery[] { try { const db: Database = System.getDb(); - return db.all('SELECT book_id,type,author_id,`title`,`sub_title`,summary,serie_id,desired_release_date,desired_word_count,words_count,cover_image,`book_meta` FROM erit_books WHERE author_id = ? ORDER BY book_id DESC', [userId]) as BookQuery[]; + return db.all('SELECT book_id, type, author_id, title, sub_title, summary, serie_id, desired_release_date, desired_word_count, words_count, cover_image FROM erit_books WHERE author_id = ? ORDER BY book_id DESC', [userId]) as BookQuery[]; } catch (error: unknown) { if (error instanceof Error) { console.error(error.message); @@ -150,7 +135,7 @@ export default class BookRepo { let result: BookQuery; try { const db: Database = System.getDb(); - result = db.get('SELECT book_id, author_id, `title`, `summary`, `sub_title`, `cover_image`,`desired_release_date`, desired_word_count, `words_count`, book_meta FROM `erit_books` WHERE `book_id`=? AND author_id=?', [bookId, userId]) as BookQuery; + result = db.get('SELECT book_id, author_id, title, summary, sub_title, cover_image, desired_release_date, desired_word_count, words_count FROM erit_books WHERE book_id=? AND author_id=?', [bookId, userId]) as BookQuery; } catch (error: unknown) { if (error instanceof Error) { console.error(`DB Error: ${error.message}`); @@ -201,7 +186,7 @@ export default class BookRepo { public static fetchAllActs(userId: string, bookId: string, lang: 'fr' | 'en'): ActQuery[] { try { const db: Database = System.getDb(); - return db.all('SELECT `act_index`,`summary`,`meta_acts` FROM `book_act_summaries` WHERE `book_id`=? AND `user_id`=?', [bookId, userId]) as ActQuery[]; + return db.all('SELECT act_index, summary FROM book_act_summaries WHERE book_id=? AND user_id=?', [bookId, userId]) as ActQuery[]; } catch (e: unknown) { if (e instanceof Error) { console.error(`DB Error: ${e.message}`); @@ -215,7 +200,7 @@ export default class BookRepo { public static fetchAllIncitentIncidents(userId:string,bookId:string, lang: 'fr' | 'en'):IncidentQuery[]{ try { const db: Database = System.getDb(); - return db.all('SELECT incident_id,`title`,`summary`,`meta_incident` FROM `book_incidents` WHERE `author_id`=? AND `book_id`=?', [userId, bookId]) as IncidentQuery[]; + return db.all('SELECT incident_id, title, summary FROM book_incidents WHERE author_id=? AND book_id=?', [userId, bookId]) as IncidentQuery[]; } catch (e: unknown) { if (e instanceof Error) { console.error(`DB Error: ${e.message}`); @@ -229,7 +214,7 @@ export default class BookRepo { 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`,`meta_plot` FROM `book_plot_points` WHERE `author_id`=? AND `book_id`=?', [userId, bookId]) as PlotPointQuery[]; + 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}`); @@ -243,7 +228,7 @@ export default class BookRepo { public static fetchIssuesFromBook(userId:string,bookId:string, lang: 'fr' | 'en'):IssueQuery[]{ try { const db: Database = System.getDb(); - return db.all('SELECT issue_id,`name`,`meta_issue` FROM `book_issues` WHERE `author_id`=? AND `book_id`=?', [userId, bookId]) as IssueQuery[]; + return db.all('SELECT issue_id, name FROM book_issues WHERE author_id=? AND book_id=?', [userId, bookId]) as IssueQuery[]; } catch (e: unknown) { if (e instanceof Error) { console.error(`DB Error: ${e.message}`); @@ -278,7 +263,7 @@ export default class BookRepo { public static fetchBookCover(userId:string,bookId:string, lang: 'fr' | 'en'):BookCoverQuery{ try { const db: Database = System.getDb(); - return db.get('SELECT cover_image, book_meta FROM erit_books WHERE author_id=? AND book_id=?', [userId, bookId]) as BookCoverQuery; + return db.get('SELECT cover_image FROM erit_books WHERE author_id=? AND book_id=?', [userId, bookId]) as BookCoverQuery; } catch (e: unknown) { if (e instanceof Error) { console.error(`DB Error: ${e.message}`); @@ -529,7 +514,7 @@ export default class BookRepo { public static fetchWorlds(userId: string, bookId: string, lang: 'fr' | 'en'):WorldQuery[] { try { const db: Database = System.getDb(); - return db.all('SELECT world.world_id AS world_id, world.name AS world_name,world.history, world.politics, world.economy, world.religion, world.languages, world.meta_world, element.element_id AS element_id,element.name AS element_name, element.description AS element_description, element.element_type, element.meta_element FROM `book_world` AS world LEFT JOIN book_world_elements AS element ON world.world_id=element.world_id WHERE world.author_id=? AND world.book_id=?', [userId, bookId]) as WorldQuery[]; + return db.all('SELECT world.world_id AS world_id, world.name AS world_name, world.history, world.politics, world.economy, world.religion, world.languages, element.element_id AS element_id, element.name AS element_name, element.description AS element_description, element.element_type FROM book_world AS world LEFT JOIN book_world_elements AS element ON world.world_id=element.world_id WHERE world.author_id=? AND world.book_id=?', [userId, bookId]) as WorldQuery[]; } catch (e: unknown) { if (e instanceof Error) { console.error(`DB Error: ${e.message}`); @@ -709,7 +694,7 @@ export default class BookRepo { static fetchCompleteBookChapters(id: string, lang: 'fr' | 'en'): ChapterBookResult[] { try { const db: Database = System.getDb(); - const result = db.all('SELECT title, chapter_order, meta_chapter, content.content, content.meta_chapter_content FROM `book_chapters` AS chapter LEFT JOIN book_chapter_content AS content ON chapter.chapter_id = content.chapter_id AND content.version = (SELECT MAX(version) FROM book_chapter_content WHERE chapter_id = chapter.chapter_id AND version > 1) WHERE chapter.book_id = ? ORDER BY chapter.chapter_order', [id]) as ChapterBookResult[]; + const result = db.all('SELECT title, chapter_order, content.content FROM book_chapters AS chapter LEFT JOIN book_chapter_content AS content ON chapter.chapter_id = content.chapter_id AND content.version = (SELECT MAX(version) FROM book_chapter_content WHERE chapter_id = chapter.chapter_id AND version > 1) WHERE chapter.book_id = ? ORDER BY chapter.chapter_order', [id]) as ChapterBookResult[]; if (result.length === 0) { throw new Error(lang === 'fr' ? `Aucun chapitre trouvé.` : `No chapters found.`); } diff --git a/electron/database/repositories/chapter.repository.ts b/electron/database/repositories/chapter.repository.ts index 273fa58..f7df5fe 100644 --- a/electron/database/repositories/chapter.repository.ts +++ b/electron/database/repositories/chapter.repository.ts @@ -7,20 +7,17 @@ export interface ChapterContentQueryResult extends Record{ content: string; words_count: number; title: string; - content_meta: string; - meta_chapter: string; chapter_order: number; } export interface ContentQueryResult extends Record { - content: string, - meta_chapter_content: string, + content: string; } + export interface ChapterQueryResult extends Record{ chapter_id: string; title: string; - chapter_order:number; - meta_chapter: string; + chapter_order: number; } export interface ActChapterQuery extends Record{ @@ -28,38 +25,31 @@ export interface ActChapterQuery extends Record{ chapter_id: string; title: string; chapter_order: number; - meta_chapter: string; act_id: number; incident_id: string | null; plot_point_id: string | null; summary: string; goal: string; - meta_chapter_info: string; } export interface CompanionContentQueryResult extends Record{ version: number; content: string; words_count: number; - meta_chapter_content: string; } export interface ChapterStoryQueryResult extends Record{ chapter_info_id: number; act_id: number; - summary:string; - meta_acts:string; + summary: string; chapter_summary: string; chapter_goal: string; - meta_chapter_info: string; incident_id: number; incident_title: string; incident_summary: string; - meta_incident: string; plot_point_id: number; plot_title: string; plot_summary: string; - meta_plot: string; } export interface LastChapterResult extends Record{ @@ -88,7 +78,7 @@ export default class ChapterRepo{ let result: RunResult; try { const db: Database = System.getDb(); - result = db.run('INSERT INTO book_chapters (chapter_id,author_id, book_id, title, hashed_title, words_count, chapter_order) VALUES (?,?,?,?,?,?,?)', [chapterId, userId, bookId, title, hashedTitle, wordsCount, chapterOrder]); + result = db.run('INSERT INTO book_chapters (chapter_id, author_id, book_id, title, hashed_title, words_count, chapter_order) VALUES (?,?,?,?,?,?,?)', [chapterId, userId, bookId, title, hashedTitle, wordsCount, chapterOrder]); } catch (e: unknown) { if (e instanceof Error) { console.error(`DB Error: ${e.message}`); @@ -109,7 +99,7 @@ export default class ChapterRepo{ let result: ChapterContentQueryResult | null; try { const db: Database = System.getDb(); - const query: string = 'SELECT chapter.chapter_id as chapter_id,chapter.title as title, chapter.chapter_order, chapter.words_count, chapter.meta_chapter, content.content AS content, content.version as version, content.meta_chapter_content as content_meta FROM book_chapters AS chapter LEFT JOIN book_chapter_content AS content ON content.chapter_id = chapter.chapter_id AND content.version = ? WHERE chapter.chapter_id = ? AND chapter.author_id = ?'; + const query: string = 'SELECT chapter.chapter_id as chapter_id, chapter.title as title, chapter.chapter_order, chapter.words_count, content.content AS content, content.version as version FROM book_chapters AS chapter LEFT JOIN book_chapter_content AS content ON content.chapter_id = chapter.chapter_id AND content.version = ? WHERE chapter.chapter_id = ? AND chapter.author_id = ?'; result = db.get(query, [version, chapterId, userId]) as ChapterContentQueryResult | null; } catch (e: unknown) { if (e instanceof Error) { @@ -129,7 +119,7 @@ export default class ChapterRepo{ public static fetchLastChapterContent(userId: string, bookId: string, lang: 'fr' | 'en' = 'fr'): ChapterContentQueryResult[] { try { const db: Database = System.getDb(); - const query: string = `SELECT book_chapters.chapter_id as chapter_id, COALESCE(book_chapter_content.version, 2) AS version, COALESCE(book_chapter_content.content, '') AS content, COALESCE(book_chapter_content.words_count, 0) AS words_count, book_chapters.title, book_chapters.meta_chapter, book_chapters.chapter_order FROM book_chapters LEFT JOIN book_chapter_content ON book_chapters.chapter_id = book_chapter_content.chapter_id WHERE book_chapters.author_id = ? AND book_chapters.book_id = ? ORDER BY book_chapters.chapter_order DESC, book_chapter_content.version DESC LIMIT 1`; + const query: string = `SELECT book_chapters.chapter_id as chapter_id, COALESCE(book_chapter_content.version, 2) AS version, COALESCE(book_chapter_content.content, '') AS content, COALESCE(book_chapter_content.words_count, 0) AS words_count, book_chapters.title, book_chapters.chapter_order FROM book_chapters LEFT JOIN book_chapter_content ON book_chapters.chapter_id = book_chapter_content.chapter_id WHERE book_chapters.author_id = ? AND book_chapters.book_id = ? ORDER BY book_chapters.chapter_order DESC, book_chapter_content.version DESC LIMIT 1`; return db.all(query, [userId, bookId]) as ChapterContentQueryResult[]; } catch (e: unknown) { if (e instanceof Error) { @@ -144,7 +134,7 @@ export default class ChapterRepo{ public static fetchAllChapterForActs(userId:string,bookId:string, lang: 'fr' | 'en' = 'fr'):ActChapterQuery[]{ try { const db: Database = System.getDb(); - return db.all('SELECT ci.chapter_info_id AS chapter_info_id, ci.chapter_id AS chapter_id, chapter.title, chapter.chapter_order, chapter.meta_chapter, ci.act_id, ci.incident_id AS incident_id, ci.plot_point_id AS plot_point_id, ci.summary, ci.goal, ci.meta_chapter_info FROM `book_chapter_infos` AS ci INNER JOIN book_chapters AS chapter ON chapter.chapter_id = ci.chapter_id WHERE ci.book_id = ? AND ci.author_id = ?', [bookId, userId]) as ActChapterQuery[]; + return db.all('SELECT ci.chapter_info_id AS chapter_info_id, ci.chapter_id AS chapter_id, chapter.title, chapter.chapter_order, ci.act_id, ci.incident_id AS incident_id, ci.plot_point_id AS plot_point_id, ci.summary, ci.goal FROM book_chapter_infos AS ci INNER JOIN book_chapters AS chapter ON chapter.chapter_id = ci.chapter_id WHERE ci.book_id = ? AND ci.author_id = ?', [bookId, userId]) as ActChapterQuery[]; } catch (e: unknown) { if (e instanceof Error) { console.error(`DB Error: ${e.message}`); @@ -159,7 +149,7 @@ export default class ChapterRepo{ public static fetchAllChapterFromABook(userId: string, bookId: string, lang: 'fr' | 'en' = 'fr'): ChapterQueryResult[] { try { const db: Database = System.getDb(); - return db.all('SELECT chapter_id as chapter_id, title, chapter_order, meta_chapter FROM book_chapters WHERE book_id=? AND author_id=? ORDER BY chapter_order', [bookId, userId]) as ChapterQueryResult[]; + return db.all('SELECT chapter_id, title, chapter_order FROM book_chapters WHERE book_id=? AND author_id=? ORDER BY chapter_order', [bookId, userId]) as ChapterQueryResult[]; } catch (e: unknown) { if (e instanceof Error) { console.error(`DB Error: ${e.message}`); @@ -207,7 +197,7 @@ export default class ChapterRepo{ } try { const db: Database = System.getDb(); - result = db.run('INSERT INTO book_chapter_infos (chapter_info_id,chapter_id, act_id, book_id, author_id, incident_id, plot_point_id, summary, goal, meta_chapter_info) VALUES (?,?,?,?,?,?,?,?,?,?)', [chapterInfoId, chapterId, actId, bookId, userId, incidentId, plotId, '', '', '']); + result = db.run('INSERT INTO book_chapter_infos (chapter_info_id, chapter_id, act_id, book_id, author_id, incident_id, plot_point_id, summary, goal) VALUES (?,?,?,?,?,?,?,?,?)', [chapterInfoId, chapterId, actId, bookId, userId, incidentId, plotId, '', '']); } catch (e: unknown) { if (e instanceof Error) { console.error(`DB Error: ${e.message}`); @@ -302,7 +292,7 @@ export default class ChapterRepo{ static fetchCompanionContent(userId: string, chapterIdNum: string, versionNum: number, lang: 'fr' | 'en' = 'fr'): CompanionContentQueryResult[] { try { const db: Database = System.getDb(); - return db.all('SELECT version, content, words_count, meta_chapter_content FROM book_chapter_content WHERE author_id=? AND chapter_id=? AND version=?', [userId, chapterIdNum, versionNum]) as CompanionContentQueryResult[]; + return db.all('SELECT version, content, words_count FROM book_chapter_content WHERE author_id=? AND chapter_id=? AND version=?', [userId, chapterIdNum, versionNum]) as CompanionContentQueryResult[]; } catch (e: unknown) { if (e instanceof Error) { console.error(`DB Error: ${e.message}`); @@ -354,7 +344,7 @@ export default class ChapterRepo{ public static fetchChapterStory(userId: string, chapterId: string, lang: 'fr' | 'en' = 'fr'):ChapterStoryQueryResult[] { try { const db: Database = System.getDb(); - return db.all('SELECT chapter_info_id,chapter.act_id,act_sum.summary,act_sum.meta_acts,chapter.summary AS chapter_summary,chapter.goal AS chapter_goal,meta_chapter_info,chapter.incident_id,incident.title AS incident_title, incident.summary AS incident_summary,incident.meta_incident,chapter.plot_point_id,plot.title AS plot_title,plot.summary AS plot_summary,plot.meta_plot FROM `book_chapter_infos` AS chapter LEFT JOIN book_incidents AS incident ON chapter.incident_id=incident.incident_id LEFT JOIN book_plot_points AS plot ON chapter.plot_point_id=plot.plot_point_id LEFT JOIN book_act_summaries AS act_sum ON chapter.act_id=act_sum.act_sum_id AND chapter.book_id=act_sum.book_id WHERE chapter.chapter_id=? AND chapter.author_id=?', [chapterId, userId]) as ChapterStoryQueryResult[]; + return db.all('SELECT chapter_info_id, chapter.act_id, act_sum.summary, chapter.summary AS chapter_summary, chapter.goal AS chapter_goal, chapter.incident_id, incident.title AS incident_title, incident.summary AS incident_summary, chapter.plot_point_id, plot.title AS plot_title, plot.summary AS plot_summary FROM book_chapter_infos AS chapter LEFT JOIN book_incidents AS incident ON chapter.incident_id=incident.incident_id LEFT JOIN book_plot_points AS plot ON chapter.plot_point_id=plot.plot_point_id LEFT JOIN book_act_summaries AS act_sum ON chapter.act_id=act_sum.act_sum_id AND chapter.book_id=act_sum.book_id WHERE chapter.chapter_id=? AND chapter.author_id=?', [chapterId, userId]) as ChapterStoryQueryResult[]; } catch (e: unknown) { if (e instanceof Error) { console.error(`DB Error: ${e.message}`); @@ -370,7 +360,7 @@ export default class ChapterRepo{ let result: ContentQueryResult | null; try { const db: Database = System.getDb(); - result = db.get('SELECT content.content,content.meta_chapter_content FROM `book_chapters` as chapter INNER JOIN book_chapter_content AS content ON chapter.chapter_id=content.chapter_id WHERE chapter.chapter_order=? AND content.version=2 AND chapter.book_id=? AND chapter.author_id=?', [chapterOrder, bookId, userId]) as ContentQueryResult | null; + result = db.get('SELECT content.content FROM book_chapters as chapter INNER JOIN book_chapter_content AS content ON chapter.chapter_id=content.chapter_id WHERE chapter.chapter_order=? AND content.version=2 AND chapter.book_id=? AND chapter.author_id=?', [chapterOrder, bookId, userId]) as ContentQueryResult | null; } catch (e: unknown) { if (e instanceof Error) { console.error(`DB Error: ${e.message}`); @@ -390,7 +380,7 @@ export default class ChapterRepo{ let result: ContentQueryResult | null; try { const db: Database = System.getDb(); - result = db.get('SELECT content, meta_chapter_content FROM book_chapter_content WHERE author_id=? AND chapter_id=? AND version=?', [userId, chapterid, version]) as ContentQueryResult | null; + result = db.get('SELECT content FROM book_chapter_content WHERE author_id=? AND chapter_id=? AND version=?', [userId, chapterid, version]) as ContentQueryResult | null; } catch (e: unknown) { if (e instanceof Error) { console.error(`DB Error: ${e.message}`); diff --git a/electron/database/repositories/character.repository.ts b/electron/database/repositories/character.repository.ts index f1bf243..9ce550d 100644 --- a/electron/database/repositories/character.repository.ts +++ b/electron/database/repositories/character.repository.ts @@ -11,14 +11,12 @@ export interface CharacterResult extends Record { role: string; biography: string; history: string; - char_meta: string; } export interface AttributeResult extends Record { attr_id: string; attribute_name: string; attribute_value: string; - attr_meta: string; } export interface CompleteCharacterResult extends Record { @@ -30,10 +28,8 @@ export interface CompleteCharacterResult extends Record { role: string; biography: string; history: string; - char_meta: string; attribute_name: string; attribute_value: string; - attr_meta: string; } export default class CharacterRepo { @@ -41,7 +37,7 @@ export default class CharacterRepo { let result: CharacterResult[]; try { const db: Database = System.getDb(); - result = db.all('SELECT character_id,`first_name`,`last_name`,`title`,`category`,`image`,`role`,`biography`,`history`,`char_meta` FROM `book_characters` WHERE `book_id`=? AND user_id=?', [bookId, userId]) as CharacterResult[]; + result = db.all('SELECT character_id, first_name, last_name, title, category, image, role, biography, history FROM book_characters WHERE book_id=? AND user_id=?', [bookId, userId]) as CharacterResult[]; } catch (e: unknown) { if (e instanceof Error) { console.error(`DB Error: ${e.message}`); @@ -132,7 +128,7 @@ export default class CharacterRepo { let result: AttributeResult[]; try { const db: Database = System.getDb(); - result = db.all('SELECT attr_id, attribute_name, attribute_value, attr_meta FROM `book_characters_attributes` WHERE `character_id`=? AND `user_id`=?', [characterId, userId]) as AttributeResult[]; + result = db.all('SELECT attr_id, attribute_name, attribute_value FROM book_characters_attributes WHERE character_id=? AND user_id=?', [characterId, userId]) as AttributeResult[]; } catch (e: unknown) { if (e instanceof Error) { console.error(`DB Error: ${e.message}`); @@ -149,7 +145,7 @@ export default class CharacterRepo { let result: CompleteCharacterResult[]; try { const db: Database = System.getDb(); - let query: string = 'SELECT charac.`character_id`,`first_name`,`last_name`,`category`,`title`,`role`,`biography`,`history`,`char_meta`,`attribute_name`,`attribute_value`,attr_meta FROM book_characters AS charac LEFT JOIN book_characters_attributes AS attr ON charac.character_id=attr.character_id WHERE charac.user_id=? AND charac.book_id=?'; + let query: string = 'SELECT charac.character_id, first_name, last_name, category, title, role, biography, history, attribute_name, attribute_value FROM book_characters AS charac LEFT JOIN book_characters_attributes AS attr ON charac.character_id=attr.character_id WHERE charac.user_id=? AND charac.book_id=?'; let values: any[] = [userId, bookId]; if (tags && tags.length > 0) { const placeholders: string = tags.map((): string => '?').join(','); diff --git a/electron/database/repositories/location.repository.ts b/electron/database/repositories/location.repository.ts index a3bd84e..edc1401 100644 --- a/electron/database/repositories/location.repository.ts +++ b/electron/database/repositories/location.repository.ts @@ -4,35 +4,28 @@ import System from "../System.js"; export interface LocationQueryResult extends Record { loc_id: string; loc_name: string; - loc_meta: string; element_id: string; element_name: string; element_description: string; - element_meta: string; sub_element_id: string; sub_elem_name: string; sub_elem_description: string; - sub_elem_meta: string; } export interface LocationElementQueryResult extends Record { sub_element_id: string; sub_elem_name: string; sub_elem_description: string; - sub_elem_meta: string; element_id: string; element_name: string; element_description: string; - element_meta: string; } export interface LocationByTagResult extends Record { element_name: string; element_description: string; - element_meta: string; sub_elem_name: string; sub_elem_description: string; - sub_elem_meta: string; } export default class LocationRepo { @@ -40,7 +33,7 @@ export default class LocationRepo { let result: LocationQueryResult[]; try { const db: Database = System.getDb(); - const query = 'SELECT loc_id,loc_name, loc_meta, element.element_id AS element_id, element.element_name, element.element_description, element.element_meta, sub_elem.sub_element_id AS sub_element_id,sub_elem.sub_elem_name,sub_elem.sub_elem_description,sub_elem.sub_elem_meta FROM `book_location` AS location LEFT JOIN location_element AS element ON location.loc_id=element.location LEFT JOIN location_sub_element AS sub_elem ON element.element_id=sub_elem.element_id WHERE location.user_id=? AND location.book_id=?'; + const query = 'SELECT loc_id, loc_name, element.element_id AS element_id, element.element_name, element.element_description, sub_elem.sub_element_id AS sub_element_id, sub_elem.sub_elem_name, sub_elem.sub_elem_description FROM book_location AS location LEFT JOIN location_element AS element ON location.loc_id=element.location LEFT JOIN location_sub_element AS sub_elem ON element.element_id=sub_elem.element_id WHERE location.user_id=? AND location.book_id=?'; result = db.all(query, [userId, bookId]) as LocationQueryResult[]; } catch (e: unknown) { if (e instanceof Error) { @@ -217,7 +210,7 @@ export default class LocationRepo { let result: LocationElementQueryResult[]; try { const db: Database = System.getDb(); - const query = 'SELECT se.sub_element_id AS sub_element_id, se.sub_elem_name, se.sub_elem_description, se.sub_elem_meta, el.element_id AS element_id, el.element_name, el.element_description, el.element_meta FROM location_sub_element AS se RIGHT JOIN location_element AS el ON se.element_id = el.element_id LEFT JOIN book_location AS lo ON el.location = lo.loc_id WHERE lo.book_id = ? AND lo.user_id = ?'; + const query = 'SELECT se.sub_element_id AS sub_element_id, se.sub_elem_name, se.sub_elem_description, el.element_id AS element_id, el.element_name, el.element_description FROM location_sub_element AS se RIGHT JOIN location_element AS el ON se.element_id = el.element_id LEFT JOIN book_location AS lo ON el.location = lo.loc_id WHERE lo.book_id = ? AND lo.user_id = ?'; result = db.all(query, [bookId, userId]) as LocationElementQueryResult[]; } catch (e: unknown) { if (e instanceof Error) { @@ -242,10 +235,8 @@ export default class LocationRepo { const query: string = ` SELECT el.element_name, el.element_description, - el.element_meta, se.sub_elem_name, - se.sub_elem_description, - se.sub_elem_meta + se.sub_elem_description FROM location_element AS el LEFT JOIN location_sub_element AS se ON el.element_id = se.element_id WHERE el.user_id = ? diff --git a/electron/database/repositories/user.repository.ts b/electron/database/repositories/user.repository.ts index b0cf3c1..a732b46 100644 --- a/electron/database/repositories/user.repository.ts +++ b/electron/database/repositories/user.repository.ts @@ -9,12 +9,11 @@ export interface UserInfosQueryResponse extends Record { plateform: string; term_accepted: number; account_verified: number; - user_meta: string; author_name: string; - writing_lang: number, - writing_level: number, - rite_points: number, - user_group: number, + writing_lang: number; + writing_level: number; + rite_points: number; + user_group: number; } export interface CredentialResponse { @@ -35,10 +34,9 @@ interface UserResponse { export interface UserAccountQuery extends Record { first_name: string; last_name: string; - username: string + username: string; author_name: string; email: string; - user_meta: string; } export interface GuideTourResult extends Record { @@ -53,8 +51,8 @@ export default class UserRepo { const db: Database = System.getDb(); const query = `INSERT INTO erit_users (user_id, first_name, last_name, username, email, origin_email, origin_username, plateform, term_accepted, - account_verified, user_meta, reg_date) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`; + account_verified, reg_date) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`; const values: (string | null | number)[] = [ uuId, firstName, @@ -66,7 +64,6 @@ export default class UserRepo { 'desktop', // plateform 0, // term_accepted 1, // account_verified - '{}', // user_meta (JSON empty object) Date.now() // reg_date (current timestamp) ]; result = db.run(query, values); @@ -90,7 +87,7 @@ export default class UserRepo { let result; try { const db: Database = System.getDb(); - result = db.get('SELECT `first_name`, `last_name`, `username`, `email`, `plateform`, `term_accepted`, `account_verified`, user_meta, author_name, erite_points AS rite_points, user_group FROM `erit_users` WHERE user_id=?', [userId]); + result = db.get('SELECT first_name, last_name, username, email, plateform, term_accepted, account_verified, author_name, erite_points AS rite_points, user_group FROM erit_users WHERE user_id=?', [userId]); } catch (e: unknown) { if (e instanceof Error) { console.error(`DB Error: ${e.message}`); @@ -126,7 +123,7 @@ export default class UserRepo { let result; try { const db: Database = System.getDb(); - result = db.get('SELECT `first_name`, `last_name`, `username`,`author_name`, `email`,`user_meta` FROM `erit_users` WHERE user_id=?', [userId]); + result = db.get('SELECT first_name, last_name, username, author_name, email FROM erit_users WHERE user_id=?', [userId]); } catch (e: unknown) { if (e instanceof Error) { console.error(`DB Error: ${e.message}`); diff --git a/electron/database/schema.ts b/electron/database/schema.ts index efc04b0..e5cd2c7 100644 --- a/electron/database/schema.ts +++ b/electron/database/schema.ts @@ -8,7 +8,7 @@ type Database = sqlite3.Database; * Data is encrypted before storage and decrypted on retrieval */ -export const SCHEMA_VERSION = 1; +export const SCHEMA_VERSION = 2; /** * Initialize the local SQLite database with all required tables @@ -66,7 +66,6 @@ export function initializeSchema(db: Database): void { role TEXT NOT NULL, message TEXT NOT NULL, message_date INTEGER NOT NULL, - meta_message TEXT NOT NULL, synced INTEGER DEFAULT 0, FOREIGN KEY (conversation_id) REFERENCES ai_conversations(conversation_id) ON DELETE CASCADE ); @@ -88,7 +87,6 @@ export function initializeSchema(db: Database): void { user_id TEXT NOT NULL, act_index INTEGER NOT NULL, summary TEXT, - meta_acts TEXT NOT NULL, synced INTEGER DEFAULT 0, FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE ); @@ -108,7 +106,6 @@ export function initializeSchema(db: Database): void { tone TEXT, atmosphere TEXT, current_resume TEXT, - meta TEXT NOT NULL, synced INTEGER DEFAULT 0, PRIMARY KEY (user_id, book_id), FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE @@ -125,7 +122,6 @@ export function initializeSchema(db: Database): void { hashed_title TEXT, words_count INTEGER, chapter_order INTEGER, - meta_chapter TEXT NOT NULL, synced INTEGER DEFAULT 0, FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE ); @@ -140,7 +136,6 @@ export function initializeSchema(db: Database): void { version INTEGER NOT NULL DEFAULT 2, content TEXT NOT NULL, words_count INTEGER NOT NULL, - meta_chapter_content TEXT NOT NULL, time_on_it INTEGER NOT NULL DEFAULT 0, synced INTEGER DEFAULT 0, FOREIGN KEY (chapter_id) REFERENCES book_chapters(chapter_id) ON DELETE CASCADE @@ -159,7 +154,6 @@ export function initializeSchema(db: Database): void { author_id TEXT, summary TEXT NOT NULL, goal TEXT NOT NULL, - meta_chapter_info TEXT NOT NULL, synced INTEGER DEFAULT 0, FOREIGN KEY (chapter_id) REFERENCES book_chapters(chapter_id) ON DELETE CASCADE, FOREIGN KEY (incident_id) REFERENCES book_incidents(incident_id) ON DELETE CASCADE, @@ -181,7 +175,6 @@ export function initializeSchema(db: Database): void { role TEXT, biography TEXT, history TEXT, - char_meta TEXT NOT NULL, synced INTEGER DEFAULT 0, FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE ); @@ -195,7 +188,6 @@ export function initializeSchema(db: Database): void { user_id TEXT NOT NULL, attribute_name TEXT NOT NULL, attribute_value TEXT NOT NULL, - attr_meta TEXT NOT NULL, synced INTEGER DEFAULT 0, FOREIGN KEY (character_id) REFERENCES book_characters(character_id) ON DELETE CASCADE ); @@ -229,7 +221,6 @@ export function initializeSchema(db: Database): void { pacing TEXT NOT NULL, intended_audience TEXT NOT NULL, key_messages TEXT NOT NULL, - meta_guide_line TEXT NOT NULL, synced INTEGER DEFAULT 0, PRIMARY KEY (user_id, book_id), FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE @@ -245,7 +236,6 @@ export function initializeSchema(db: Database): void { title TEXT NOT NULL, hashed_title TEXT NOT NULL, summary TEXT, - meta_incident TEXT NOT NULL, synced INTEGER DEFAULT 0, FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE ); @@ -259,7 +249,6 @@ export function initializeSchema(db: Database): void { book_id TEXT NOT NULL, name TEXT NOT NULL, hashed_issue_name TEXT NOT NULL, - meta_issue TEXT NOT NULL, synced INTEGER DEFAULT 0, FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE ); @@ -273,7 +262,6 @@ export function initializeSchema(db: Database): void { user_id TEXT NOT NULL, loc_name TEXT NOT NULL, loc_original_name TEXT NOT NULL, - loc_meta TEXT NOT NULL, synced INTEGER DEFAULT 0, FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE ); @@ -289,7 +277,6 @@ export function initializeSchema(db: Database): void { linked_incident_id TEXT, author_id TEXT NOT NULL, book_id TEXT NOT NULL, - meta_plot TEXT NOT NULL, synced INTEGER DEFAULT 0, FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE ); @@ -308,7 +295,6 @@ export function initializeSchema(db: Database): void { economy TEXT, religion TEXT, languages TEXT, - meta_world TEXT NOT NULL, synced INTEGER DEFAULT 0, FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE ); @@ -324,7 +310,6 @@ export function initializeSchema(db: Database): void { name TEXT NOT NULL, original_name TEXT NOT NULL, description TEXT, - meta_element TEXT NOT NULL, synced INTEGER DEFAULT 0, FOREIGN KEY (world_id) REFERENCES book_world(world_id) ON DELETE CASCADE ); @@ -346,7 +331,6 @@ export function initializeSchema(db: Database): void { desired_word_count INTEGER, words_count INTEGER, cover_image TEXT, - book_meta TEXT, synced INTEGER DEFAULT 0 ); `); @@ -395,7 +379,6 @@ export function initializeSchema(db: Database): void { verify_code TEXT, reg_date INTEGER NOT NULL, account_verified INTEGER NOT NULL DEFAULT 0, - user_meta TEXT NOT NULL, erite_points INTEGER NOT NULL DEFAULT 100, stripe_customer_id TEXT, credits_balance REAL DEFAULT 0, @@ -412,7 +395,6 @@ export function initializeSchema(db: Database): void { element_name TEXT NOT NULL, original_name TEXT NOT NULL, element_description TEXT, - element_meta TEXT NOT NULL, synced INTEGER DEFAULT 0, FOREIGN KEY (location) REFERENCES book_location(loc_id) ON DELETE CASCADE ); @@ -427,7 +409,6 @@ export function initializeSchema(db: Database): void { sub_elem_name TEXT NOT NULL, original_name TEXT NOT NULL, sub_elem_description TEXT, - sub_elem_meta TEXT NOT NULL, synced INTEGER DEFAULT 0, FOREIGN KEY (element_id) REFERENCES location_element(element_id) ON DELETE CASCADE ); @@ -523,3 +504,90 @@ export function dropAllTables(db: Database): void { db.exec('PRAGMA foreign_keys = ON'); } + +/** + * Get current schema version from database + */ +function getDbSchemaVersion(db: Database): number { + try { + const result = db.get('SELECT version FROM _schema_version LIMIT 1') as { version: number } | undefined; + return result?.version ?? 0; + } catch { + return 0; + } +} + +/** + * Set schema version in database + */ +function setDbSchemaVersion(db: Database, version: number): void { + db.exec('CREATE TABLE IF NOT EXISTS _schema_version (version INTEGER PRIMARY KEY)'); + db.run('DELETE FROM _schema_version'); + db.run('INSERT INTO _schema_version (version) VALUES (?)', [version]); +} + +/** + * Check if a column exists in a table + */ +function columnExists(db: Database, tableName: string, columnName: string): boolean { + const columns = db.all(`PRAGMA table_info(${tableName})`) as { name: string }[]; + return columns.some(col => col.name === columnName); +} + +/** + * Safely drop a column if it exists + */ +function dropColumnIfExists(db: Database, tableName: string, columnName: string): void { + if (columnExists(db, tableName, columnName)) { + try { + db.exec(`ALTER TABLE ${tableName} DROP COLUMN ${columnName}`); + console.log(`[Migration] Dropped column ${columnName} from ${tableName}`); + } catch (e) { + console.error(`[Migration] Failed to drop column ${columnName} from ${tableName}:`, e); + } + } +} + +/** + * Run migrations to update schema from one version to another + */ +export function runMigrations(db: Database): void { + const currentVersion = getDbSchemaVersion(db); + + if (currentVersion >= SCHEMA_VERSION) { + return; + } + + console.log(`[Migration] Upgrading schema from version ${currentVersion} to ${SCHEMA_VERSION}`); + + // Migration 1 -> 2: Remove all meta_* columns + if (currentVersion < 2) { + console.log('[Migration] Running migration v2: Removing meta columns...'); + + dropColumnIfExists(db, 'ai_messages_history', 'meta_message'); + dropColumnIfExists(db, 'book_act_summaries', 'meta_acts'); + dropColumnIfExists(db, 'book_ai_guide_line', 'meta'); + dropColumnIfExists(db, 'book_chapters', 'meta_chapter'); + dropColumnIfExists(db, 'book_chapter_content', 'meta_chapter_content'); + dropColumnIfExists(db, 'book_chapter_infos', 'meta_chapter_info'); + dropColumnIfExists(db, 'book_characters', 'char_meta'); + dropColumnIfExists(db, 'book_characters_attributes', 'attr_meta'); + dropColumnIfExists(db, 'book_guide_line', 'meta_guide_line'); + dropColumnIfExists(db, 'book_incidents', 'meta_incident'); + dropColumnIfExists(db, 'book_issues', 'meta_issue'); + dropColumnIfExists(db, 'book_location', 'loc_meta'); + dropColumnIfExists(db, 'book_plot_points', 'meta_plot'); + dropColumnIfExists(db, 'book_world', 'meta_world'); + dropColumnIfExists(db, 'book_world_elements', 'meta_element'); + dropColumnIfExists(db, 'erit_books', 'book_meta'); + dropColumnIfExists(db, 'erit_users', 'user_meta'); + dropColumnIfExists(db, 'location_element', 'element_meta'); + dropColumnIfExists(db, 'location_sub_element', 'sub_elem_meta'); + + console.log('[Migration] Migration v2 completed'); + } + + // Update schema version + setDbSchemaVersion(db, SCHEMA_VERSION); + console.log(`[Migration] Schema updated to version ${SCHEMA_VERSION}`); +} diff --git a/electron/ipc/chapter.ipc.ts b/electron/ipc/chapter.ipc.ts index 5e267a0..d76310b 100644 --- a/electron/ipc/chapter.ipc.ts +++ b/electron/ipc/chapter.ipc.ts @@ -4,9 +4,9 @@ import Chapter from '../database/models/Chapter.js'; import type { ChapterProps, CompanionContent, ActStory } from '../database/models/Chapter.js'; interface GetWholeChapterData { - chapterId: string; + id: string; version: number; - bookId?: string; + bookid: string; } interface SaveChapterContentData { @@ -53,7 +53,7 @@ ipcMain.handle('db:book:chapters', createHandler( // GET /chapter/whole - Get whole chapter ipcMain.handle('db:chapter:whole', createHandler( function(userId: string, data: GetWholeChapterData, lang: 'fr' | 'en'): ChapterProps { - return Chapter.getWholeChapter(userId, data.chapterId, data.version, data.bookId, lang); + return Chapter.getWholeChapter(userId, data.id, data.version, data.bookid, lang); } ) );