225 lines
8.0 KiB
TypeScript
225 lines
8.0 KiB
TypeScript
import { z } from "zod";
|
|
|
|
export const RoleSchema = z.enum(["admin", "user"]);
|
|
export type Role = z.infer<typeof RoleSchema>;
|
|
|
|
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<typeof UserSchema>;
|
|
|
|
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<typeof BootstrapAdminSchema>;
|
|
|
|
export const LoginSchema = z.object({
|
|
email: z.string().email(),
|
|
password: z.string().min(1)
|
|
});
|
|
export type LoginDto = z.infer<typeof LoginSchema>;
|
|
|
|
export const AuthStatusSchema = z.object({
|
|
hasUsers: z.boolean(),
|
|
initialAdminEmail: z.string().email(),
|
|
initialAdminPasswordIsDefault: z.boolean()
|
|
});
|
|
export type AuthStatusDto = z.infer<typeof AuthStatusSchema>;
|
|
|
|
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<typeof UpdateAccountSchema>;
|
|
|
|
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<typeof CreateUserSchema>;
|
|
|
|
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<typeof UpdateUserSchema>;
|
|
|
|
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<typeof LibrarySchema>;
|
|
|
|
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<typeof CreateLibrarySchema>;
|
|
|
|
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<typeof UpdateLibrarySchema>;
|
|
|
|
export const SeriesSchema = z.object({
|
|
id: z.number().int().positive(),
|
|
title: z.string(),
|
|
normalizedTitle: z.string(),
|
|
description: z.string().nullable(),
|
|
publisher: z.string().nullable(),
|
|
createdAt: z.string(),
|
|
updatedAt: z.string()
|
|
});
|
|
export type SeriesDto = z.infer<typeof SeriesSchema>;
|
|
|
|
export const BookSchema = z.object({
|
|
id: z.number().int().positive(),
|
|
libraryId: z.number().int().positive(),
|
|
seriesId: z.number().int().positive().nullable().optional(),
|
|
title: z.string(),
|
|
author: z.string().nullable(),
|
|
description: z.string().nullable(),
|
|
isbn: z.string().nullable(),
|
|
isbn13: z.string().nullable(),
|
|
language: z.string().nullable(),
|
|
publisher: z.string().nullable(),
|
|
publishedDate: z.string().nullable(),
|
|
volumeNumber: z.number().int().nullable().optional(),
|
|
volumeLabel: z.string().nullable().optional(),
|
|
format: z.enum(["epub", "pdf", "cbz", "cbr"]),
|
|
filePath: z.string(),
|
|
coverPath: z.string().nullable(),
|
|
metadataStatus: z.enum(["enriched", "partial", "none"]).default("none"),
|
|
metadataProvenance: z.record(z.string(), z.string()).default({}),
|
|
series: SeriesSchema.nullable().optional(),
|
|
scanStatus: z.enum(["idle", "running", "succeeded", "failed"]).default("idle"),
|
|
enrichmentStatus: z.enum(["idle", "running", "succeeded", "failed"]).default("idle"),
|
|
fileSize: z.number().int().nonnegative(),
|
|
fileMtime: z.string(),
|
|
createdAt: z.string(),
|
|
updatedAt: z.string()
|
|
});
|
|
export type BookDto = z.infer<typeof BookSchema>;
|
|
|
|
export const BookQuerySchema = z.object({
|
|
q: z.string().optional(),
|
|
format: z.enum(["epub", "pdf", "cbz", "cbr"]).optional(),
|
|
libraryId: z.coerce.number().int().positive().optional(),
|
|
limit: z.coerce.number().int().min(1).max(100).optional(),
|
|
offset: z.coerce.number().int().min(0).default(0)
|
|
});
|
|
export type BookQueryDto = z.infer<typeof BookQuerySchema>;
|
|
|
|
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<typeof ProgressSchema>;
|
|
|
|
export const UpdateProgressSchema = z.object({
|
|
locator: z.string().min(1),
|
|
percent: z.number().min(0).max(100)
|
|
});
|
|
export type UpdateProgressDto = z.infer<typeof UpdateProgressSchema>;
|
|
|
|
export const ReaderPreferencesSchema = z.object({
|
|
mode: z.enum(["paged", "scrolled", "horizontal", "vertical"]).default("paged"),
|
|
fit: z.enum(["page", "width", "height", "auto"]).nullable().default(null),
|
|
updatedAt: z.string().optional()
|
|
});
|
|
export type ReaderPreferencesDto = z.infer<typeof ReaderPreferencesSchema>;
|
|
|
|
export const UpdateReaderPreferencesSchema = z.object({
|
|
mode: z.enum(["paged", "scrolled", "horizontal", "vertical"]).optional(),
|
|
fit: z.enum(["page", "width", "height", "auto"]).nullable().optional()
|
|
});
|
|
export type UpdateReaderPreferencesDto = z.infer<typeof UpdateReaderPreferencesSchema>;
|
|
|
|
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<typeof JobSchema>;
|
|
|
|
export const MetadataProviderIdSchema = z.enum(["local", "openlibrary", "googlebooks", "bnf", "mangadex", "comicvine"]);
|
|
export type MetadataProviderId = z.infer<typeof MetadataProviderIdSchema>;
|
|
|
|
export const MetadataSourceConfigSchema = z.object({
|
|
provider: MetadataProviderIdSchema,
|
|
enabled: z.boolean(),
|
|
priority: z.number().int().min(0),
|
|
hasApiKey: z.boolean().default(false)
|
|
});
|
|
export type MetadataSourceConfigDto = z.infer<typeof MetadataSourceConfigSchema>;
|
|
|
|
export const MetadataSourcesConfigSchema = z.object({
|
|
isbnPriorityEnabled: z.boolean(),
|
|
sources: z.array(MetadataSourceConfigSchema)
|
|
});
|
|
export type MetadataSourcesConfigDto = z.infer<typeof MetadataSourcesConfigSchema>;
|
|
|
|
export const UpdateMetadataSourceConfigSchema = z.object({
|
|
provider: MetadataProviderIdSchema.exclude(["local"]),
|
|
enabled: z.boolean(),
|
|
priority: z.number().int().min(1).max(100),
|
|
apiKey: z.string().min(1).nullable().optional()
|
|
});
|
|
export type UpdateMetadataSourceConfigDto = z.infer<typeof UpdateMetadataSourceConfigSchema>;
|
|
|
|
export const UpdateMetadataSourcesConfigSchema = z.object({
|
|
isbnPriorityEnabled: z.boolean().optional(),
|
|
sources: z.array(UpdateMetadataSourceConfigSchema).optional()
|
|
});
|
|
export type UpdateMetadataSourcesConfigDto = z.infer<typeof UpdateMetadataSourcesConfigSchema>;
|
|
|
|
export const AutomationFrequencySchema = z.enum(["disabled", "daily", "weekly"]);
|
|
export type AutomationFrequency = z.infer<typeof AutomationFrequencySchema>;
|
|
|
|
export const AutomationScheduleSchema = z.object({
|
|
frequency: AutomationFrequencySchema,
|
|
time: z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/).default("03:00"),
|
|
dayOfWeek: z.number().int().min(0).max(6).default(1)
|
|
});
|
|
export type AutomationScheduleDto = z.infer<typeof AutomationScheduleSchema>;
|
|
|
|
export const AutomationSettingsSchema = z.object({
|
|
watchLibraries: z.boolean(),
|
|
autoEnrichNewBooks: z.boolean(),
|
|
scanSchedule: AutomationScheduleSchema,
|
|
enrichSchedule: AutomationScheduleSchema
|
|
});
|
|
export type AutomationSettingsDto = z.infer<typeof AutomationSettingsSchema>;
|
|
|
|
export const UpdateAutomationSettingsSchema = AutomationSettingsSchema.partial();
|
|
export type UpdateAutomationSettingsDto = z.infer<typeof UpdateAutomationSettingsSchema>;
|