|
| 1 | +import { z } from "zod"; |
| 2 | + |
| 3 | +/** |
| 4 | + * Allowed transform styles (sourced from env at runtime) |
| 5 | + */ |
| 6 | +const ALLOWED_STYLES = ["anime", "cinematic", "sketch", "watercolor"] as const; |
| 7 | + |
| 8 | +/** |
| 9 | + * Anime sub-styles |
| 10 | + */ |
| 11 | +const ANIME_SUB_STYLES = ["shonen", "shojo", "chibi", "mecha", "ghibli-inspired"] as const; |
| 12 | + |
| 13 | +/** |
| 14 | + * Outline thickness options |
| 15 | + */ |
| 16 | +const OUTLINE_THICKNESSES = ["thin", "medium", "bold"] as const; |
| 17 | + |
| 18 | +/** |
| 19 | + * Background style options |
| 20 | + */ |
| 21 | +const BACKGROUND_STYLES = ["original", "painted", "cel-shaded"] as const; |
| 22 | + |
| 23 | +/** |
| 24 | + * Anime transform options - matches the interface in app/lib/animeTransform.ts |
| 25 | + */ |
| 26 | +export const animeTransformOptionsSchema = z.object({ |
| 27 | + subStyle: z.enum(ANIME_SUB_STYLES), |
| 28 | + colorIntensity: z.number().min(0).max(100), |
| 29 | + outlineThickness: z.enum(OUTLINE_THICKNESSES), |
| 30 | + backgroundStyle: z.enum(BACKGROUND_STYLES), |
| 31 | +}); |
| 32 | + |
| 33 | +/** |
| 34 | + * Request body for POST /api/transform |
| 35 | + */ |
| 36 | +export const transformBodySchema = z.object({ |
| 37 | + clipId: z.string().min(1, "Clip ID is required"), |
| 38 | + style: z.enum(ALLOWED_STYLES), |
| 39 | + userId: z.string().optional(), |
| 40 | + transformOptions: animeTransformOptionsSchema.optional(), |
| 41 | +}); |
| 42 | + |
| 43 | +/** |
| 44 | + * Request body for POST /api/transform/batch |
| 45 | + */ |
| 46 | +export const transformBatchBodySchema = z.object({ |
| 47 | + clipIds: z.array(z.string().min(1)).min(1, "At least one clip ID is required"), |
| 48 | + style: z.enum(ALLOWED_STYLES), |
| 49 | + transformOptions: animeTransformOptionsSchema.optional(), |
| 50 | +}); |
| 51 | + |
| 52 | +/** |
| 53 | + * Request body for POST /api/transform/preview |
| 54 | + */ |
| 55 | +export const transformPreviewBodySchema = z.object({ |
| 56 | + clipId: z.string().min(1, "Clip ID is required"), |
| 57 | + style: z.enum(ALLOWED_STYLES), |
| 58 | + transformOptions: animeTransformOptionsSchema.optional(), |
| 59 | +}); |
| 60 | + |
| 61 | +export type AnimeTransformOptions = z.infer<typeof animeTransformOptionsSchema>; |
| 62 | +export type TransformBody = z.infer<typeof transformBodySchema>; |
| 63 | +export type TransformBatchBody = z.infer<typeof transformBatchBodySchema>; |
| 64 | +export type TransformPreviewBody = z.infer<typeof transformPreviewBodySchema>; |
0 commit comments