aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/server/schemas/index.ts
blob: 0227ebe8a80bf743646ecb4ad31369587ea62e64 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
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.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.uuid(),
	userId: z.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.uuid(),
	deckId: z.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.uuid(),
	cardId: z.uuid(),
	userId: z.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>;