Files
flashcards/packages/shared/src/schemas.ts

130 lines
4.5 KiB
TypeScript

import { z } from 'zod';
export const lessonCreateSchema = z.object({
parentId: z.number().int().nullable().optional(),
name: z.string().min(1).max(200),
description: z.string().max(2000).optional().nullable(),
bidirectional: z.boolean().optional(),
});
export const lessonUpdateSchema = lessonCreateSchema.partial();
export const lessonMoveSchema = z.object({
parentId: z.number().int().nullable(),
position: z.number().int().min(0),
});
export const cardCreateSchema = z.object({
question: z.string().min(1).max(2000),
answer: z.string().min(1).max(2000),
hint: z.string().max(2000).optional().nullable(),
});
export const cardUpdateSchema = cardCreateSchema.partial();
export const sessionStartSchema = z.object({
lessonId: z.number().int().positive(),
maxCards: z.number().int().min(1).max(500).nullable().optional(),
shuffle: z.boolean().optional(),
direction: z.enum(['forward', 'backward', 'both']).optional(),
});
export const attemptCreateSchema = z.object({
cardId: z.number().int().positive(),
direction: z.enum(['forward', 'backward']),
result: z.enum(['correct', 'incorrect']),
timeToAnswerMs: z.number().int().min(0).nullable().optional(),
});
export type LessonCreateInput = z.infer<typeof lessonCreateSchema>;
export type LessonUpdateInput = z.infer<typeof lessonUpdateSchema>;
export type LessonMoveInput = z.infer<typeof lessonMoveSchema>;
export type CardCreateInput = z.infer<typeof cardCreateSchema>;
export type CardUpdateInput = z.infer<typeof cardUpdateSchema>;
export type SessionStartInput = z.infer<typeof sessionStartSchema>;
export type AttemptCreateInput = z.infer<typeof attemptCreateSchema>;
export const emailSchema = z.string().email().max(320).transform((v) => v.trim().toLowerCase());
export const registerSchema = z.object({
email: emailSchema,
displayName: z.string().trim().min(1).max(120),
password: z.string().min(8).max(200),
});
export const loginSchema = z.object({
email: emailSchema,
password: z.string().min(1).max(200),
});
export const forgotPasswordSchema = z.object({ email: emailSchema });
export const resetPasswordSchema = z.object({
token: z.string().min(20).max(200),
password: z.string().min(8).max(200),
});
export const verifyEmailSchema = z.object({
token: z.string().min(20).max(200),
});
export const resendVerificationSchema = z.object({ email: emailSchema });
export const profileUpdateSchema = z.object({
displayName: z.string().trim().min(1).max(120).optional(),
email: emailSchema.optional(),
});
export const changePasswordSchema = z.object({
currentPassword: z.string().min(1).max(200),
newPassword: z.string().min(8).max(200),
});
export const acceptInviteSchema = z.object({
token: z.string().min(20).max(200),
displayName: z.string().trim().min(1).max(120),
password: z.string().min(8).max(200),
});
export const inviteUserSchema = z.object({
email: emailSchema,
role: z.enum(['user', 'sysadmin']).default('user'),
});
export const adminUserUpdateSchema = z.object({
displayName: z.string().trim().min(1).max(120).optional(),
role: z.enum(['user', 'sysadmin']).optional(),
isActive: z.boolean().optional(),
});
export type RegisterInput = z.infer<typeof registerSchema>;
export type LoginInput = z.infer<typeof loginSchema>;
export type ForgotPasswordInput = z.infer<typeof forgotPasswordSchema>;
export type ResetPasswordInput = z.infer<typeof resetPasswordSchema>;
export type VerifyEmailInput = z.infer<typeof verifyEmailSchema>;
export type ResendVerificationInput = z.infer<typeof resendVerificationSchema>;
export type ProfileUpdateInput = z.infer<typeof profileUpdateSchema>;
export type ChangePasswordInput = z.infer<typeof changePasswordSchema>;
export type AcceptInviteInput = z.infer<typeof acceptInviteSchema>;
export type InviteUserInput = z.infer<typeof inviteUserSchema>;
export type AdminUserUpdateInput = z.infer<typeof adminUserUpdateSchema>;
export const lessonVisibilityUpdateSchema = z.object({
visibility: z.enum(['private', 'shared']),
});
export const adminLessonCuratedSchema = z.object({
isCurated: z.boolean(),
});
export const marketplaceQuerySchema = z.object({
q: z.string().trim().max(120).optional(),
curated: z.enum(['true', 'false']).optional(),
limit: z.coerce.number().int().min(1).max(100).optional(),
offset: z.coerce.number().int().min(0).optional(),
});
export type LessonVisibilityUpdateInput = z.infer<typeof lessonVisibilityUpdateSchema>;
export type AdminLessonCuratedInput = z.infer<typeof adminLessonCuratedSchema>;
export type MarketplaceQuery = z.infer<typeof marketplaceQuerySchema>;