import { z } from "zod"; export const RoleSchema = z.enum(["admin", "user"]); export type Role = z.infer; export const UserSchema = z.object({ id: z.number().int().positive(), email: z.string().email(), name: z.string().nullable(), role: RoleSchema, createdAt: z.string() }); export type UserDto = z.infer; export const BootstrapAdminSchema = z.object({ email: z.string().email(), password: z.string().min(8), name: z.string().min(1).max(120).optional() }); export type BootstrapAdminDto = z.infer; export const LoginSchema = z.object({ email: z.string().email(), password: z.string().min(1) }); export type LoginDto = z.infer; export const AuthStatusSchema = z.object({ hasUsers: z.boolean(), initialAdminEmail: z.string().email(), initialAdminPasswordIsDefault: z.boolean() }); export type AuthStatusDto = z.infer; export const UpdateAccountSchema = z .object({ email: z.string().email().optional(), name: z.string().min(1).max(120).nullable().optional(), currentPassword: z.string().min(1), newPassword: z.string().min(8).optional() }) .refine((value) => value.email !== undefined || value.name !== undefined || value.newPassword !== undefined, { message: "At least one account field must be changed" }); export type UpdateAccountDto = z.infer; export const CreateUserSchema = z.object({ email: z.string().email(), password: z.string().min(8), name: z.string().min(1).max(120).optional(), role: RoleSchema.default("user") }); export type CreateUserDto = z.infer; export const UpdateUserSchema = z.object({ email: z.string().email().optional(), password: z.string().min(8).optional(), name: z.string().min(1).max(120).nullable().optional(), role: RoleSchema.optional() }); export type UpdateUserDto = z.infer; export const LibrarySchema = z.object({ id: z.number().int().positive(), name: z.string(), path: z.string(), enabled: z.boolean(), createdAt: z.string(), updatedAt: z.string() }); export type LibraryDto = z.infer; export const CreateLibrarySchema = z.object({ name: z.string().min(1).max(160), path: z.string().min(1), enabled: z.boolean().default(true) }); export type CreateLibraryDto = z.infer; export const UpdateLibrarySchema = z.object({ name: z.string().min(1).max(160).optional(), path: z.string().min(1).optional(), enabled: z.boolean().optional() }); export type UpdateLibraryDto = z.infer; export const BookSchema = z.object({ id: z.number().int().positive(), libraryId: z.number().int().positive(), title: z.string(), author: z.string().nullable(), description: z.string().nullable(), isbn: z.string().nullable(), language: z.string().nullable(), publisher: z.string().nullable(), publishedDate: z.string().nullable(), format: z.enum(["epub", "pdf"]), filePath: z.string(), coverPath: z.string().nullable(), fileSize: z.number().int().nonnegative(), fileMtime: z.string(), createdAt: z.string(), updatedAt: z.string() }); export type BookDto = z.infer; export const BookQuerySchema = z.object({ q: z.string().optional(), format: z.enum(["epub", "pdf"]).optional(), libraryId: z.coerce.number().int().positive().optional(), limit: z.coerce.number().int().min(1).max(100).default(50), offset: z.coerce.number().int().min(0).default(0) }); export type BookQueryDto = z.infer; export const ProgressSchema = z.object({ bookId: z.number().int().positive(), locator: z.string().min(1), percent: z.number().min(0).max(100), updatedAt: z.string() }); export type ProgressDto = z.infer; export const UpdateProgressSchema = z.object({ locator: z.string().min(1), percent: z.number().min(0).max(100) }); export type UpdateProgressDto = z.infer; export const JobSchema = z.object({ id: z.number().int().positive(), type: z.string(), status: z.enum(["queued", "running", "succeeded", "failed"]), detail: z.string().nullable(), error: z.string().nullable(), createdAt: z.string(), updatedAt: z.string() }); export type JobDto = z.infer;