Add database schema, encryption utilities, and local database service
- Implement `schema.ts` for SQLite schema creation, indexing, and sync metadata initialization. - Develop `encryption.ts` with AES-256-GCM encryption utilities for securing database data. - Add `database.service.ts` to manage CRUD operations with encryption support, user-specific databases, and schema initialization. - Integrate book, chapter, and character operations with encrypted content handling and sync preparation.
This commit is contained in:
174
electron/database/mappers/chapter.mapper.ts
Normal file
174
electron/database/mappers/chapter.mapper.ts
Normal file
@@ -0,0 +1,174 @@
|
||||
/**
|
||||
* TypeScript interfaces (copied from lib/models for type safety)
|
||||
*/
|
||||
|
||||
export interface ChapterContent {
|
||||
version: number;
|
||||
content: string;
|
||||
wordsCount: number;
|
||||
}
|
||||
|
||||
export interface ChapterProps {
|
||||
chapterId: string;
|
||||
chapterOrder: number;
|
||||
title: string;
|
||||
chapterContent: ChapterContent;
|
||||
}
|
||||
|
||||
export interface ActChapter {
|
||||
chapterInfoId: string;
|
||||
chapterId: string;
|
||||
title: string;
|
||||
chapterOrder: number;
|
||||
actId: number;
|
||||
incidentId?: string;
|
||||
plotPointId?: string;
|
||||
summary: string;
|
||||
goal: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Database row types (snake_case from SQLite)
|
||||
*/
|
||||
export interface DBChapter {
|
||||
chapter_id: string;
|
||||
book_id: string;
|
||||
author_id: string;
|
||||
title: string;
|
||||
hashed_title?: string;
|
||||
words_count?: number;
|
||||
chapter_order?: number;
|
||||
meta_chapter: string;
|
||||
synced?: number;
|
||||
}
|
||||
|
||||
export interface DBChapterContent {
|
||||
content_id: string;
|
||||
chapter_id: string;
|
||||
author_id: string;
|
||||
version: number;
|
||||
content: string;
|
||||
words_count: number;
|
||||
meta_chapter_content: string;
|
||||
time_on_it: number;
|
||||
synced?: number;
|
||||
}
|
||||
|
||||
export interface DBChapterInfo {
|
||||
chapter_info_id: string;
|
||||
chapter_id?: string;
|
||||
act_id?: number;
|
||||
incident_id?: string;
|
||||
plot_point_id?: string;
|
||||
book_id?: string;
|
||||
author_id?: string;
|
||||
summary: string;
|
||||
goal: string;
|
||||
meta_chapter_info: string;
|
||||
synced?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* MAPPERS: DB → TypeScript Interfaces
|
||||
*/
|
||||
|
||||
export function dbToChapter(dbChapter: DBChapter, dbContent?: DBChapterContent): ChapterProps {
|
||||
const chapterContent: ChapterContent = dbContent ? {
|
||||
version: dbContent.version,
|
||||
content: dbContent.content,
|
||||
wordsCount: dbContent.words_count
|
||||
} : {
|
||||
version: 2,
|
||||
content: '',
|
||||
wordsCount: 0
|
||||
};
|
||||
|
||||
return {
|
||||
chapterId: dbChapter.chapter_id,
|
||||
chapterOrder: dbChapter.chapter_order || 0,
|
||||
title: dbChapter.title,
|
||||
chapterContent
|
||||
};
|
||||
}
|
||||
|
||||
export function dbToChapterContent(dbContent: DBChapterContent): ChapterContent {
|
||||
return {
|
||||
version: dbContent.version,
|
||||
content: dbContent.content,
|
||||
wordsCount: dbContent.words_count
|
||||
};
|
||||
}
|
||||
|
||||
export function dbToActChapter(dbChapter: DBChapter, dbInfo: DBChapterInfo): ActChapter {
|
||||
return {
|
||||
chapterInfoId: dbInfo.chapter_info_id,
|
||||
chapterId: dbChapter.chapter_id,
|
||||
title: dbChapter.title,
|
||||
chapterOrder: dbChapter.chapter_order || 0,
|
||||
actId: dbInfo.act_id || 0,
|
||||
incidentId: dbInfo.incident_id,
|
||||
plotPointId: dbInfo.plot_point_id,
|
||||
summary: dbInfo.summary,
|
||||
goal: dbInfo.goal
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* MAPPERS: TypeScript Interfaces → DB
|
||||
*/
|
||||
|
||||
export function chapterToDb(chapter: ChapterProps, bookId: string, authorId: string, synced: number = 0): DBChapter {
|
||||
return {
|
||||
chapter_id: chapter.chapterId,
|
||||
book_id: bookId,
|
||||
author_id: authorId,
|
||||
title: chapter.title,
|
||||
hashed_title: '',
|
||||
words_count: chapter.chapterContent.wordsCount,
|
||||
chapter_order: chapter.chapterOrder,
|
||||
meta_chapter: '',
|
||||
synced
|
||||
};
|
||||
}
|
||||
|
||||
export function chapterContentToDb(
|
||||
content: ChapterContent,
|
||||
contentId: string,
|
||||
chapterId: string,
|
||||
authorId: string,
|
||||
timeOnIt: number = 0,
|
||||
synced: number = 0
|
||||
): DBChapterContent {
|
||||
return {
|
||||
content_id: contentId,
|
||||
chapter_id: chapterId,
|
||||
author_id: authorId,
|
||||
version: content.version,
|
||||
content: content.content,
|
||||
words_count: content.wordsCount,
|
||||
meta_chapter_content: '',
|
||||
time_on_it: timeOnIt,
|
||||
synced
|
||||
};
|
||||
}
|
||||
|
||||
export function actChapterToDbInfo(
|
||||
actChapter: ActChapter,
|
||||
bookId: string,
|
||||
authorId: string,
|
||||
synced: number = 0
|
||||
): DBChapterInfo {
|
||||
return {
|
||||
chapter_info_id: actChapter.chapterInfoId,
|
||||
chapter_id: actChapter.chapterId,
|
||||
act_id: actChapter.actId,
|
||||
incident_id: actChapter.incidentId,
|
||||
plot_point_id: actChapter.plotPointId,
|
||||
book_id: bookId,
|
||||
author_id: authorId,
|
||||
summary: actChapter.summary,
|
||||
goal: actChapter.goal,
|
||||
meta_chapter_info: '',
|
||||
synced
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user