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:
222
electron/database/mappers/world.mapper.ts
Normal file
222
electron/database/mappers/world.mapper.ts
Normal file
@@ -0,0 +1,222 @@
|
||||
/**
|
||||
* TypeScript interfaces (copied from lib/models for type safety)
|
||||
*/
|
||||
|
||||
export interface WorldElement {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
export interface WorldProps {
|
||||
id: string;
|
||||
name: string;
|
||||
history: string;
|
||||
politics: string;
|
||||
economy: string;
|
||||
religion: string;
|
||||
languages: string;
|
||||
laws?: WorldElement[];
|
||||
biomes?: WorldElement[];
|
||||
issues?: WorldElement[];
|
||||
customs?: WorldElement[];
|
||||
kingdoms?: WorldElement[];
|
||||
climate?: WorldElement[];
|
||||
resources?: WorldElement[];
|
||||
wildlife?: WorldElement[];
|
||||
arts?: WorldElement[];
|
||||
ethnicGroups?: WorldElement[];
|
||||
socialClasses?: WorldElement[];
|
||||
importantCharacters?: WorldElement[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Database row types (snake_case from SQLite)
|
||||
*/
|
||||
export interface DBWorld {
|
||||
world_id: string;
|
||||
name: string;
|
||||
hashed_name: string;
|
||||
author_id: string;
|
||||
book_id: string;
|
||||
history?: string;
|
||||
politics?: string;
|
||||
economy?: string;
|
||||
religion?: string;
|
||||
languages?: string;
|
||||
meta_world: string;
|
||||
synced?: number;
|
||||
}
|
||||
|
||||
export interface DBWorldElement {
|
||||
element_id: string;
|
||||
world_id: string;
|
||||
user_id: string;
|
||||
element_type: number; // Type identifier for different element categories
|
||||
name: string;
|
||||
original_name: string;
|
||||
description?: string;
|
||||
meta_element: string;
|
||||
synced?: number;
|
||||
}
|
||||
|
||||
// Element type constants
|
||||
export enum WorldElementType {
|
||||
LAW = 1,
|
||||
BIOME = 2,
|
||||
ISSUE = 3,
|
||||
CUSTOM = 4,
|
||||
KINGDOM = 5,
|
||||
CLIMATE = 6,
|
||||
RESOURCE = 7,
|
||||
WILDLIFE = 8,
|
||||
ART = 9,
|
||||
ETHNIC_GROUP = 10,
|
||||
SOCIAL_CLASS = 11,
|
||||
IMPORTANT_CHARACTER = 12
|
||||
}
|
||||
|
||||
/**
|
||||
* MAPPERS: DB → TypeScript Interfaces
|
||||
*/
|
||||
|
||||
export function dbToWorld(dbWorld: DBWorld, elements: DBWorldElement[] = []): WorldProps {
|
||||
// Group elements by type
|
||||
const laws: WorldElement[] = [];
|
||||
const biomes: WorldElement[] = [];
|
||||
const issues: WorldElement[] = [];
|
||||
const customs: WorldElement[] = [];
|
||||
const kingdoms: WorldElement[] = [];
|
||||
const climate: WorldElement[] = [];
|
||||
const resources: WorldElement[] = [];
|
||||
const wildlife: WorldElement[] = [];
|
||||
const arts: WorldElement[] = [];
|
||||
const ethnicGroups: WorldElement[] = [];
|
||||
const socialClasses: WorldElement[] = [];
|
||||
const importantCharacters: WorldElement[] = [];
|
||||
|
||||
for (const elem of elements) {
|
||||
const worldElement: WorldElement = {
|
||||
id: elem.element_id,
|
||||
name: elem.name,
|
||||
description: elem.description || ''
|
||||
};
|
||||
|
||||
switch (elem.element_type) {
|
||||
case WorldElementType.LAW:
|
||||
laws.push(worldElement);
|
||||
break;
|
||||
case WorldElementType.BIOME:
|
||||
biomes.push(worldElement);
|
||||
break;
|
||||
case WorldElementType.ISSUE:
|
||||
issues.push(worldElement);
|
||||
break;
|
||||
case WorldElementType.CUSTOM:
|
||||
customs.push(worldElement);
|
||||
break;
|
||||
case WorldElementType.KINGDOM:
|
||||
kingdoms.push(worldElement);
|
||||
break;
|
||||
case WorldElementType.CLIMATE:
|
||||
climate.push(worldElement);
|
||||
break;
|
||||
case WorldElementType.RESOURCE:
|
||||
resources.push(worldElement);
|
||||
break;
|
||||
case WorldElementType.WILDLIFE:
|
||||
wildlife.push(worldElement);
|
||||
break;
|
||||
case WorldElementType.ART:
|
||||
arts.push(worldElement);
|
||||
break;
|
||||
case WorldElementType.ETHNIC_GROUP:
|
||||
ethnicGroups.push(worldElement);
|
||||
break;
|
||||
case WorldElementType.SOCIAL_CLASS:
|
||||
socialClasses.push(worldElement);
|
||||
break;
|
||||
case WorldElementType.IMPORTANT_CHARACTER:
|
||||
importantCharacters.push(worldElement);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
id: dbWorld.world_id,
|
||||
name: dbWorld.name,
|
||||
history: dbWorld.history || '',
|
||||
politics: dbWorld.politics || '',
|
||||
economy: dbWorld.economy || '',
|
||||
religion: dbWorld.religion || '',
|
||||
languages: dbWorld.languages || '',
|
||||
laws,
|
||||
biomes,
|
||||
issues,
|
||||
customs,
|
||||
kingdoms,
|
||||
climate,
|
||||
resources,
|
||||
wildlife,
|
||||
arts,
|
||||
ethnicGroups,
|
||||
socialClasses,
|
||||
importantCharacters
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* MAPPERS: TypeScript Interfaces → DB
|
||||
*/
|
||||
|
||||
export function worldToDb(world: WorldProps, authorId: string, bookId: string, synced: number = 0): DBWorld {
|
||||
return {
|
||||
world_id: world.id,
|
||||
name: world.name,
|
||||
hashed_name: '',
|
||||
author_id: authorId,
|
||||
book_id: bookId,
|
||||
history: world.history,
|
||||
politics: world.politics,
|
||||
economy: world.economy,
|
||||
religion: world.religion,
|
||||
languages: world.languages,
|
||||
meta_world: '',
|
||||
synced
|
||||
};
|
||||
}
|
||||
|
||||
export function worldElementsToDb(world: WorldProps, userId: string, synced: number = 0): DBWorldElement[] {
|
||||
const elements: DBWorldElement[] = [];
|
||||
|
||||
const addElements = (type: WorldElementType, elems: WorldElement[]) => {
|
||||
for (const elem of elems) {
|
||||
elements.push({
|
||||
element_id: elem.id,
|
||||
world_id: world.id,
|
||||
user_id: userId,
|
||||
element_type: type,
|
||||
name: elem.name,
|
||||
original_name: elem.name,
|
||||
description: elem.description,
|
||||
meta_element: '',
|
||||
synced
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
addElements(WorldElementType.LAW, world.laws || []);
|
||||
addElements(WorldElementType.BIOME, world.biomes || []);
|
||||
addElements(WorldElementType.ISSUE, world.issues || []);
|
||||
addElements(WorldElementType.CUSTOM, world.customs || []);
|
||||
addElements(WorldElementType.KINGDOM, world.kingdoms || []);
|
||||
addElements(WorldElementType.CLIMATE, world.climate || []);
|
||||
addElements(WorldElementType.RESOURCE, world.resources || []);
|
||||
addElements(WorldElementType.WILDLIFE, world.wildlife || []);
|
||||
addElements(WorldElementType.ART, world.arts || []);
|
||||
addElements(WorldElementType.ETHNIC_GROUP, world.ethnicGroups || []);
|
||||
addElements(WorldElementType.SOCIAL_CLASS, world.socialClasses || []);
|
||||
addElements(WorldElementType.IMPORTANT_CHARACTER, world.importantCharacters || []);
|
||||
|
||||
return elements;
|
||||
}
|
||||
Reference in New Issue
Block a user