From 62e780e8bfea5063a062a17d266fa2feac23c6f4 Mon Sep 17 00:00:00 2001 From: Rushil Perera Date: Fri, 24 May 2024 14:56:34 -0400 Subject: [PATCH] fix: OpenAPI spec not generating properly Summary: Test Plan: --- src/controllers/search/index.ts | 5 ++++- src/controllers/title/index.ts | 4 ++-- src/types/schema.ts | 17 +++++++++++------ src/types/title/index.ts | 21 +++++++++++---------- 4 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/controllers/search/index.ts b/src/controllers/search/index.ts index c0c5504..0727ca4 100644 --- a/src/controllers/search/index.ts +++ b/src/controllers/search/index.ts @@ -17,7 +17,10 @@ const route = createRoute({ method: "get", path: "/", request: { - query: z.object({ query: z.string(), page: z.number().min(1).default(1) }), + query: z.object({ + query: z.string(), + page: z.number({ coerce: true }).int().min(1).default(1), + }), }, responses: { 200: { diff --git a/src/controllers/title/index.ts b/src/controllers/title/index.ts index d3a1d66..37a7ed1 100644 --- a/src/controllers/title/index.ts +++ b/src/controllers/title/index.ts @@ -2,7 +2,7 @@ import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi"; import { fetchFromMultipleSources } from "~/libs/fetchFromMultipleSources"; import { - AniListIdSchema, + AniListIdQuerySchema, ErrorResponseSchema, SuccessResponseSchema, } from "~/types/schema"; @@ -20,7 +20,7 @@ const route = createRoute({ method: "get", path: "/", request: { - query: z.object({ id: AniListIdSchema }), + query: z.object({ id: AniListIdQuerySchema }), headers: z.object({ "x-anilist-token": z.string().nullish() }), }, responses: { diff --git a/src/types/schema.ts b/src/types/schema.ts index 8075947..b1daac6 100644 --- a/src/types/schema.ts +++ b/src/types/schema.ts @@ -2,11 +2,13 @@ import { type ZodSchema, z } from "zod"; export const SuccessResponse = { success: true } as const; export const SuccessResponseSchema = (schema?: T) => { + const success = z.literal(true).openapi({ type: "boolean" }); + if (!schema) { - return z.object({ success: z.literal(true) }); + return z.object({ success }); } - return z.object({ success: z.literal(true), result: schema }); + return z.object({ success, result: schema }); }; export const PaginatedResponseSchema = (schema: T) => { @@ -18,9 +20,12 @@ export const PaginatedResponseSchema = (schema: T) => { }; export const ErrorResponseSchema = z.object({ - success: z.literal(false), + success: z.literal(false).openapi({ type: "boolean" }), }); -export const AniListIdSchema = z - .number({ coerce: true }) - .openapi({ type: "integer" }); +export const NullableNumberSchema = z.number().int().nullable(); + +export const AniListIdSchema = z.number().int().openapi({ format: "int64" }); +export const AniListIdQuerySchema = z + .string() + .openapi({ type: "integer", format: "int64" }); diff --git a/src/types/title/index.ts b/src/types/title/index.ts index f57f5e4..7f2d4e4 100644 --- a/src/types/title/index.ts +++ b/src/types/title/index.ts @@ -1,14 +1,15 @@ import { z } from "zod"; +import { NullableNumberSchema } from "../schema"; import { countryCodeSchema } from "./countryCodes"; export type Title = z.infer; export const Title = z.object({ nextAiringEpisode: z.nullable( z.object({ - episode: z.number(), - airingAt: z.number(), - timeUntilAiring: z.number(), + episode: z.number().int(), + airingAt: z.number().int().openapi({ format: "int64" }), + timeUntilAiring: z.number().int().openapi({ format: "int64" }), }), ), mediaListEntry: z.nullable( @@ -23,11 +24,11 @@ export const Title = z.object({ "REPEATING", ]), ), - progress: z.number().nullable(), - id: z.number(), + progress: NullableNumberSchema, + id: z.number().int(), }), ), - countryOfOrigin: z.optional(countryCodeSchema), + countryOfOrigin: countryCodeSchema, coverImage: z.nullable( z.object({ medium: z.nullable(z.string()).optional(), @@ -35,7 +36,7 @@ export const Title = z.object({ extraLarge: z.nullable(z.string()).optional(), }), ), - averageScore: z.number().nullable(), + averageScore: NullableNumberSchema, bannerImage: z.nullable(z.string()), status: z.nullable( z.enum([ @@ -47,7 +48,7 @@ export const Title = z.object({ ]), ), genres: z.nullable(z.array(z.nullable(z.string()))), - episodes: z.number().nullable(), + episodes: NullableNumberSchema, description: z.nullable(z.string()), title: z.nullable( z.object({ @@ -55,6 +56,6 @@ export const Title = z.object({ english: z.nullable(z.string()), }), ), - idMal: z.number().nullable(), - id: z.number().openapi({ type: "integer", format: "int64" }), + idMal: NullableNumberSchema, + id: z.number().int().openapi({ format: "int64" }), });