30 lines
1.3 KiB
TypeScript
30 lines
1.3 KiB
TypeScript
import { z } from "zod";
|
|
|
|
export const melodyStatusSchema = z.enum(["DRAFT", "PUBLISHED", "ARCHIVED"]);
|
|
const audioPath = z.string().trim().regex(/^\/api\/uploads\/audios\/[^/]+$/, "Use an uploaded audio path.");
|
|
const imagePath = z.string().trim().regex(/^\/api\/uploads\/images\/[^/]+$/, "Use an uploaded image path.");
|
|
|
|
export const melodySchema = z.object({
|
|
slug: z
|
|
.string()
|
|
.trim()
|
|
.min(1, "Slug is required.")
|
|
.max(100, "Slug must be 100 characters or fewer.")
|
|
.regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, "Use lowercase letters, numbers, and hyphens only."),
|
|
titleAr: z.string().trim().min(1, "Arabic title is required.").max(160),
|
|
titleEn: z.string().trim().min(1, "English title is required.").max(160),
|
|
descAr: z.string().trim().max(4000).optional(),
|
|
descEn: z.string().trim().max(4000).optional(),
|
|
audioFile: audioPath,
|
|
coverImage: z.union([z.literal(""), imagePath]).optional(),
|
|
durationSec: z.number().int().min(0).max(86400).nullable(),
|
|
isDownloadable: z.boolean(),
|
|
status: melodyStatusSchema,
|
|
isFeatured: z.boolean(),
|
|
sortOrder: z.number().int().min(0).max(9999),
|
|
categoryId: z.string().cuid("Choose a valid melody category."),
|
|
});
|
|
|
|
export const melodyIdSchema = z.string().cuid("Invalid melody id.");
|
|
export type MelodyInput = z.infer<typeof melodySchema>;
|