diff options
| author | nsfisis <nsfisis@gmail.com> | 2025-12-06 17:05:21 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2025-12-06 17:37:04 +0900 |
| commit | 811458427593a4172a2cd535cc768db375350dca (patch) | |
| tree | 6c4f46c96b6f29392dc19d591e39e03c187033a1 /src/server/schemas/index.ts | |
| parent | 9736a8981fbd6c6defbd67517ca23904fc844629 (diff) | |
| download | kioku-811458427593a4172a2cd535cc768db375350dca.tar.gz kioku-811458427593a4172a2cd535cc768db375350dca.tar.zst kioku-811458427593a4172a2cd535cc768db375350dca.zip | |
feat(dev): change architecture and directory structure
Diffstat (limited to 'src/server/schemas/index.ts')
| -rw-r--r-- | src/server/schemas/index.ts | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/src/server/schemas/index.ts b/src/server/schemas/index.ts new file mode 100644 index 0000000..05b926a --- /dev/null +++ b/src/server/schemas/index.ts @@ -0,0 +1,140 @@ +import { z } from "zod"; + +// Card states for FSRS algorithm +export const cardStateSchema = z.union([ + z.literal(0), // New + z.literal(1), // Learning + z.literal(2), // Review + z.literal(3), // Relearning +]); + +// Rating values for reviews +export const ratingSchema = z.union([ + z.literal(1), // Again + z.literal(2), // Hard + z.literal(3), // Good + z.literal(4), // Easy +]); + +// User schema +export const userSchema = z.object({ + id: z.string().uuid(), + username: z.string().min(1).max(255), + passwordHash: z.string(), + createdAt: z.coerce.date(), + updatedAt: z.coerce.date(), +}); + +// User creation input schema +export const createUserSchema = z.object({ + username: z.string().min(1).max(255), + password: z.string().min(15).max(255), +}); + +// Login input schema +export const loginSchema = z.object({ + username: z.string().min(1), + password: z.string().min(1), +}); + +// Refresh token input schema +export const refreshTokenSchema = z.object({ + refreshToken: z.string().min(1), +}); + +// Deck schema +export const deckSchema = z.object({ + id: z.string().uuid(), + userId: z.string().uuid(), + name: z.string().min(1).max(255), + description: z.string().max(1000).nullable(), + newCardsPerDay: z.number().int().min(0).default(20), + createdAt: z.coerce.date(), + updatedAt: z.coerce.date(), + deletedAt: z.coerce.date().nullable(), + syncVersion: z.number().int().min(0), +}); + +// Deck creation input schema +export const createDeckSchema = z.object({ + name: z.string().min(1).max(255), + description: z.string().max(1000).nullable().optional(), + newCardsPerDay: z.number().int().min(0).default(20), +}); + +// Deck update input schema +export const updateDeckSchema = z.object({ + name: z.string().min(1).max(255).optional(), + description: z.string().max(1000).nullable().optional(), + newCardsPerDay: z.number().int().min(0).optional(), +}); + +// Card schema +export const cardSchema = z.object({ + id: z.string().uuid(), + deckId: z.string().uuid(), + front: z.string().min(1), + back: z.string().min(1), + + // FSRS fields + state: cardStateSchema, + due: z.coerce.date(), + stability: z.number().min(0), + difficulty: z.number().min(0).max(10), + elapsedDays: z.number().int().min(0), + scheduledDays: z.number().int().min(0), + reps: z.number().int().min(0), + lapses: z.number().int().min(0), + lastReview: z.coerce.date().nullable(), + + createdAt: z.coerce.date(), + updatedAt: z.coerce.date(), + deletedAt: z.coerce.date().nullable(), + syncVersion: z.number().int().min(0), +}); + +// Card creation input schema +export const createCardSchema = z.object({ + front: z.string().min(1), + back: z.string().min(1), +}); + +// Card update input schema +export const updateCardSchema = z.object({ + front: z.string().min(1).optional(), + back: z.string().min(1).optional(), +}); + +// ReviewLog schema +export const reviewLogSchema = z.object({ + id: z.string().uuid(), + cardId: z.string().uuid(), + userId: z.string().uuid(), + rating: ratingSchema, + state: cardStateSchema, + scheduledDays: z.number().int().min(0), + elapsedDays: z.number().int().min(0), + reviewedAt: z.coerce.date(), + durationMs: z.number().int().min(0).nullable(), + syncVersion: z.number().int().min(0), +}); + +// Submit review input schema +export const submitReviewSchema = z.object({ + rating: ratingSchema, + durationMs: z.number().int().min(0).nullable().optional(), +}); + +// Inferred types from schemas +export type UserSchema = z.infer<typeof userSchema>; +export type CreateUserSchema = z.infer<typeof createUserSchema>; +export type LoginSchema = z.infer<typeof loginSchema>; +export type RefreshTokenSchema = z.infer<typeof refreshTokenSchema>; +export type DeckSchema = z.infer<typeof deckSchema>; +export type CreateDeckSchema = z.infer<typeof createDeckSchema>; +export type UpdateDeckSchema = z.infer<typeof updateDeckSchema>; +export type CardSchema = z.infer<typeof cardSchema>; +export type CreateCardSchema = z.infer<typeof createCardSchema>; +export type UpdateCardSchema = z.infer<typeof updateCardSchema>; +export type ReviewLogSchema = z.infer<typeof reviewLogSchema>; +export type SubmitReviewSchema = z.infer<typeof submitReviewSchema>; |
