FRE-592: Implement character database and relationship mapping
Add full character management system with enriched profiles (bio, traits, arcs, motivation, conflict, secrets), relationship mapping between characters with types and strength, character search/filter by role and arc type, and character statistics (scene count, dialogue, screen time). Includes database schema, tRPC router procedures, SolidJS components, API hooks, and unit tests. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
49
src/db/schema/characters.ts
Normal file
49
src/db/schema/characters.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
|
||||
import { scripts } from "./scripts";
|
||||
|
||||
export const characters = sqliteTable("characters", {
|
||||
id: integer("id").primaryKey({ autoIncrement: true }),
|
||||
scriptId: integer("script_id")
|
||||
.notNull()
|
||||
.references(() => scripts.id),
|
||||
name: text("name").notNull(),
|
||||
slug: text("slug").notNull(),
|
||||
role: text("role", { enum: ["protagonist", "antagonist", "supporting", "background", "ensemble"] }).notNull().default("supporting"),
|
||||
bio: text("bio"),
|
||||
description: text("description"),
|
||||
arc: text("arc"),
|
||||
arcType: text("arc_type", { enum: ["positive", "negative", "flat", "complex"] }),
|
||||
age: integer("age"),
|
||||
gender: text("gender"),
|
||||
voice: text("voice"),
|
||||
traits: text("traits"),
|
||||
motivation: text("motivation"),
|
||||
conflict: text("conflict"),
|
||||
secret: text("secret"),
|
||||
imageUrl: text("image_url"),
|
||||
createdAt: integer("created_at", { mode: "timestamp" }).$defaultFn(() => new Date()),
|
||||
updatedAt: integer("updated_at", { mode: "timestamp" }).$defaultFn(() => new Date()),
|
||||
});
|
||||
|
||||
export const characterRelationships = sqliteTable("character_relationships", {
|
||||
id: integer("id").primaryKey({ autoIncrement: true }),
|
||||
characterIdA: integer("character_a_id")
|
||||
.notNull()
|
||||
.references(() => characters.id),
|
||||
characterIdB: integer("character_b_id")
|
||||
.notNull()
|
||||
.references(() => characters.id),
|
||||
relationshipType: text("relationship_type", {
|
||||
enum: ["family", "romantic", "friendship", "rivalry", "mentor", "alliance", "conflict", "professional", "other"],
|
||||
}).notNull(),
|
||||
description: text("description"),
|
||||
strength: integer("strength").notNull().default(50),
|
||||
isAntagonistic: integer("is_antagonistic", { mode: "boolean" }).notNull().default(false),
|
||||
createdAt: integer("created_at", { mode: "timestamp" }).$defaultFn(() => new Date()),
|
||||
updatedAt: integer("updated_at", { mode: "timestamp" }).$defaultFn(() => new Date()),
|
||||
});
|
||||
|
||||
export type Character = typeof characters.$inferSelect;
|
||||
export type NewCharacter = typeof characters.$inferInsert;
|
||||
export type CharacterRelationship = typeof characterRelationships.$inferSelect;
|
||||
export type NewCharacterRelationship = typeof characterRelationships.$inferInsert;
|
||||
6
src/db/schema/index.ts
Normal file
6
src/db/schema/index.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export { users, type User, type NewUser } from "./users";
|
||||
export { projects, type Project, type NewProject } from "./projects";
|
||||
export { scripts, type Script, type NewScript } from "./scripts";
|
||||
export { characters, characterRelationships, type Character, type NewCharacter, type CharacterRelationship, type NewCharacterRelationship } from "./characters";
|
||||
export { scenes, sceneCharacters, type Scene, type NewScene, type SceneCharacter, type NewSceneCharacter } from "./scenes";
|
||||
export { revisions, revisionChanges, type Revision, type NewRevision, type RevisionChange, type NewRevisionChange } from "./revisions";
|
||||
Reference in New Issue
Block a user