import { z } from "zod/v4"; import { Show } from "./show"; import { KImage } from "./utils/images"; import { zdate } from "./utils/utils"; const Base = z.object({ id: z.string(), slug: z.string(), order: z.number(), name: z.string().nullable(), description: z.string().nullable(), airDate: zdate().nullable(), runtime: z.number().nullable(), thumbnail: KImage.nullable(), content: z.enum(["story", "recap", "filler", "ova"]), createdAt: zdate(), updatedAt: zdate(), videos: z.array( z.object({ id: z.string(), slug: z.string(), path: z.string(), rendering: z.string(), part: z.int().nullable(), version: z.int(), }), ), progress: z.object({ percent: z.int().min(0).max(100), time: z.int().min(0), playedDate: zdate().nullable(), videoId: z.string().nullable(), }), }); export const Episode = Base.extend({ kind: z.literal("episode"), seasonNumber: z.int().gte(0), episodeNumber: z.int().gte(0), externalId: z.record( z.string(), z.array( z.object({ serieId: z.string(), season: z.int().nullable(), episode: z.int(), link: z.string().nullable(), label: z.string().optional().nullable(), }), ), ), }); export type Episode = z.infer; export const MovieEntry = Base.extend({ kind: z.literal("movie"), tagline: z.string().nullable(), poster: KImage.nullable(), externalId: z.record( z.string(), z.array( z.union([ z.object({ serieId: z.string(), season: z.int().nullable(), episode: z.int(), link: z.string().nullable(), label: z.string().optional().nullable(), }), z.object({ dataId: z.string(), link: z.string().nullable(), label: z.string().optional().nullable(), }), ]), ), ), }); export type MovieEntry = z.infer; export const Special = Base.extend({ kind: z.literal("special"), number: z.int(), externalId: z.record( z.string(), z.array( z.object({ serieId: z.string(), season: z.int().nullable(), episode: z.int(), link: z.string().nullable(), }), ), ), }); export type Special = z.infer; export const BaseEntry = z .discriminatedUnion("kind", [Episode, MovieEntry, Special]) .transform((x) => ({ ...x, href: x.videos.length ? `/watch/${x.videos[0].slug}` : null, })); export const Entry = BaseEntry.and( z.object({ get show() { return Show.optional(); }, }), ); export type Entry = z.infer;