mal api schema impl

This commit is contained in:
2026-02-05 14:26:27 -08:00
parent db9383ec34
commit b2bb1439ee

View File

@@ -1,87 +1,81 @@
/*
import { z } from "zod";
query Parameters
status
string
export const MalAnimeListStatusEnum = z.enum([
"watching",
"completed",
"on_hold",
"dropped",
"plan_to_watch",
]);
export type MalAnimeListStatus = z.infer<typeof MalAnimeListStatusEnum>;
Filters returned anime list by these statuses.
export const MalAnimeListSortEnum = z.enum([
"list_score",
"list_updated_at",
"anime_title",
"anime_start_date",
"anime_id",
]);
export type MalAnimeListSort = z.infer<typeof MalAnimeListSortEnum>;
To return all anime, don't specify this field.
const NumericQueryParamSchema = z
.union([z.number(), z.string()])
.transform((v) => (typeof v === "string" ? Number(v) : v));
Valid values:
export const MalAnimeListQuerySchema = z
.object({
status: MalAnimeListStatusEnum.optional(),
sort: MalAnimeListSortEnum.optional(),
limit: NumericQueryParamSchema.pipe(
z.number().int().min(1).max(1000),
).optional(),
offset: NumericQueryParamSchema.pipe(z.number().int().min(0)).optional(),
})
.strict();
export type MalAnimeListQuery = z.infer<typeof MalAnimeListQuerySchema>;
watching
completed
on_hold
dropped
plan_to_watch
export const MalAnimeEntry = z
.object({
id: z.number().int().positive(),
title: z.string(),
main_picture: z
.object({
medium: z.string(),
large: z.string(),
})
.strict()
.optional(),
})
.strict();
sort
string
export const MalAnimeListEntry = z
.object({
status: MalAnimeListStatusEnum,
score: z.number().int().min(0).max(10),
num_episodes_watched: z.number().int().min(0),
is_rewatching: z.boolean(),
updated_at: z.iso.datetime(),
start_date: z.iso.date().optional(),
finish_date: z.iso.date().optional(),
})
.strict();
Valid values:
Value Order
list_score Descending
list_updated_at Descending
anime_title Ascending
anime_start_date Descending
anime_id (Under Development) Ascending
limit
integer
Default: 100
The maximum value is 1000.
offset
integer
Default: 0
*/
/*
sample response
{
"data": [
{
"node": {
"id": 31646,
"title": "3-gatsu no Lion",
"main_picture": {
"medium": "https://cdn.myanimelist.net/images/anime/3/82899.jpg",
"large": "https://cdn.myanimelist.net/images/anime/3/82899l.jpg"
}
},
"list_status": {
"status": "watching",
"score": 0,
"num_episodes_watched": 2,
"is_rewatching": false,
"updated_at": "2025-07-17T00:57:26+00:00",
"start_date": "2025-07-16"
}
},
{
"node": {
"id": 38101,
"title": "5-toubun no Hanayome",
"main_picture": {
"medium": "https://cdn.myanimelist.net/images/anime/1819/97947.jpg",
"large": "https://cdn.myanimelist.net/images/anime/1819/97947l.jpg"
}
},
"list_status": {
"status": "completed",
"score": 0,
"num_episodes_watched": 12,
"is_rewatching": false,
"updated_at": "2019-06-02T09:12:42+00:00",
"start_date": "2019-05-31",
"finish_date": "2019-06-02"
}
}
],
"paging": {
"next": "https://api.myanimelist.net/v2/users/CaZzzer/animelist?offset=2&fields=list_status&limit=2"
}
}
*/
export const MalAnimeListResponseSchema = z
.object({
data: z.array(
z
.object({
node: MalAnimeEntry,
list_status: MalAnimeListEntry,
})
.strict(),
),
paging: z
.object({
next: z.string().optional(),
previous: z.string().optional(),
})
.strict(),
})
.strict();
export type MalAnimeListResponse = z.infer<typeof MalAnimeListResponseSchema>;