From 5bb62819796bcd3b5e945662c23299eb8db71e34 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Wed, 31 Dec 2025 00:33:44 +0900 Subject: feat(db): add Note feature database schema MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add database tables and Zod validation schemas for Anki-compatible Note concept as outlined in the roadmap Phase 1: - note_types: defines note structure (templates, reversibility) - note_field_types: defines fields within a note type - notes: container for field values belonging to a deck - note_field_values: actual field content for notes - cards: add nullable note_id and is_reversed columns Includes migration file and comprehensive test coverage for all new Zod validation schemas. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- src/server/schemas/index.ts | 107 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) (limited to 'src/server/schemas/index.ts') diff --git a/src/server/schemas/index.ts b/src/server/schemas/index.ts index 0227ebe..d2a8fb0 100644 --- a/src/server/schemas/index.ts +++ b/src/server/schemas/index.ts @@ -105,6 +105,98 @@ export const updateCardSchema = z.object({ back: z.string().min(1).optional(), }); +// Field type schema +export const fieldTypeSchema = z.literal("text"); + +// NoteType schema +export const noteTypeSchema = z.object({ + id: z.uuid(), + userId: z.uuid(), + name: z.string().min(1).max(255), + frontTemplate: z.string().min(1), + backTemplate: z.string().min(1), + isReversible: z.boolean(), + createdAt: z.coerce.date(), + updatedAt: z.coerce.date(), + deletedAt: z.coerce.date().nullable(), + syncVersion: z.number().int().min(0), +}); + +// NoteType creation input schema +export const createNoteTypeSchema = z.object({ + name: z.string().min(1).max(255), + frontTemplate: z.string().min(1), + backTemplate: z.string().min(1), + isReversible: z.boolean().default(false), +}); + +// NoteType update input schema +export const updateNoteTypeSchema = z.object({ + name: z.string().min(1).max(255).optional(), + frontTemplate: z.string().min(1).optional(), + backTemplate: z.string().min(1).optional(), + isReversible: z.boolean().optional(), +}); + +// NoteFieldType schema +export const noteFieldTypeSchema = z.object({ + id: z.uuid(), + noteTypeId: z.uuid(), + name: z.string().min(1).max(255), + order: z.number().int().min(0), + fieldType: fieldTypeSchema, + createdAt: z.coerce.date(), + updatedAt: z.coerce.date(), + deletedAt: z.coerce.date().nullable(), + syncVersion: z.number().int().min(0), +}); + +// NoteFieldType creation input schema +export const createNoteFieldTypeSchema = z.object({ + name: z.string().min(1).max(255), + order: z.number().int().min(0), + fieldType: fieldTypeSchema.default("text"), +}); + +// NoteFieldType update input schema +export const updateNoteFieldTypeSchema = z.object({ + name: z.string().min(1).max(255).optional(), + order: z.number().int().min(0).optional(), +}); + +// Note schema +export const noteSchema = z.object({ + id: z.uuid(), + deckId: z.uuid(), + noteTypeId: z.uuid(), + createdAt: z.coerce.date(), + updatedAt: z.coerce.date(), + deletedAt: z.coerce.date().nullable(), + syncVersion: z.number().int().min(0), +}); + +// Note creation input schema (fields is a map of fieldTypeId -> value) +export const createNoteSchema = z.object({ + noteTypeId: z.uuid(), + fields: z.record(z.uuid(), z.string()), +}); + +// Note update input schema +export const updateNoteSchema = z.object({ + fields: z.record(z.uuid(), z.string()), +}); + +// NoteFieldValue schema +export const noteFieldValueSchema = z.object({ + id: z.uuid(), + noteId: z.uuid(), + noteFieldTypeId: z.uuid(), + value: z.string(), + createdAt: z.coerce.date(), + updatedAt: z.coerce.date(), + syncVersion: z.number().int().min(0), +}); + // ReviewLog schema export const reviewLogSchema = z.object({ id: z.uuid(), @@ -138,3 +230,18 @@ export type CreateCardSchema = z.infer; export type UpdateCardSchema = z.infer; export type ReviewLogSchema = z.infer; export type SubmitReviewSchema = z.infer; +export type FieldTypeSchema = z.infer; +export type NoteTypeSchema = z.infer; +export type CreateNoteTypeSchema = z.infer; +export type UpdateNoteTypeSchema = z.infer; +export type NoteFieldTypeSchema = z.infer; +export type CreateNoteFieldTypeSchema = z.infer< + typeof createNoteFieldTypeSchema +>; +export type UpdateNoteFieldTypeSchema = z.infer< + typeof updateNoteFieldTypeSchema +>; +export type NoteSchema = z.infer; +export type CreateNoteSchema = z.infer; +export type UpdateNoteSchema = z.infer; +export type NoteFieldValueSchema = z.infer; -- cgit v1.2.3-70-g09d2