Cleanup swagger & add examples for entries

This commit is contained in:
Zoe Roux 2025-03-01 15:22:01 +01:00
parent 5e0ba7f630
commit fb7635ef56
8 changed files with 55 additions and 19 deletions

View File

@ -250,10 +250,10 @@ export const entriesH = new Elysia({ tags: ["series"] })
}, },
{ {
detail: { description: "Get extras of a serie" }, detail: { description: "Get extras of a serie" },
path: t.Object({ params: t.Object({
id: t.String({ id: t.String({
description: "The id or slug of the serie.", description: "The id or slug of the serie.",
examples: [madeInAbyss.slug], example: madeInAbyss.slug,
}), }),
}), }),
query: t.Object({ query: t.Object({

View File

@ -1,10 +1,10 @@
import { t } from "elysia"; import { t } from "elysia";
import type { Prettify } from "~/utils"; import type { Prettify } from "~/utils";
import { bubbleImages, madeInAbyss, registerExamples } from "../examples";
import { EpisodeId, Resource, SeedImage, TranslationRecord } from "../utils"; import { EpisodeId, Resource, SeedImage, TranslationRecord } from "../utils";
import { BaseEntry, EntryTranslation } from "./base-entry"; import { BaseEntry, EntryTranslation } from "./base-entry";
export const BaseEpisode = t.Intersect([ export const BaseEpisode = t.Intersect([
BaseEntry,
t.Object({ t.Object({
kind: t.Literal("episode"), kind: t.Literal("episode"),
order: t.Number({ minimum: 1, description: "Absolute playback order." }), order: t.Number({ minimum: 1, description: "Absolute playback order." }),
@ -12,9 +12,10 @@ export const BaseEpisode = t.Intersect([
episodeNumber: t.Number(), episodeNumber: t.Number(),
externalId: EpisodeId, externalId: EpisodeId,
}), }),
BaseEntry,
]); ]);
export const Episode = t.Intersect([Resource(), BaseEpisode, EntryTranslation]); export const Episode = t.Intersect([Resource(), EntryTranslation, BaseEpisode]);
export type Episode = Prettify<typeof Episode.static>; export type Episode = Prettify<typeof Episode.static>;
export const SeedEpisode = t.Intersect([ export const SeedEpisode = t.Intersect([
@ -26,3 +27,11 @@ export const SeedEpisode = t.Intersect([
}), }),
]); ]);
export type SeedEpisode = Prettify<typeof SeedEpisode.static>; export type SeedEpisode = Prettify<typeof SeedEpisode.static>;
const ep = madeInAbyss.entries.find((x) => x.kind === "episode")!;
registerExamples(Episode, {
...ep,
...ep.translations.en,
...bubbleImages,
slug: `${madeInAbyss.slug}-s${ep.seasonNumber}-e${ep.episodeNumber}`,
});

View File

@ -1,5 +1,6 @@
import { t } from "elysia"; import { t } from "elysia";
import { type Prettify, comment } from "~/utils"; import { type Prettify, comment } from "~/utils";
import { madeInAbyss, registerExamples } from "../examples";
import { SeedImage } from "../utils"; import { SeedImage } from "../utils";
import { Resource } from "../utils/resource"; import { Resource } from "../utils/resource";
import { BaseEntry } from "./base-entry"; import { BaseEntry } from "./base-entry";
@ -16,11 +17,11 @@ export type ExtraType = typeof ExtraType.static;
export const BaseExtra = t.Intersect( export const BaseExtra = t.Intersect(
[ [
t.Omit(BaseEntry, ["nextRefresh", "airDate"]),
t.Object({ t.Object({
kind: ExtraType, kind: ExtraType,
name: t.String(), name: t.String(),
}), }),
t.Omit(BaseEntry, ["nextRefresh", "airDate"]),
], ],
{ {
description: comment` description: comment`
@ -42,3 +43,5 @@ export const SeedExtra = t.Intersect([
}), }),
]); ]);
export type SeedExtra = Prettify<typeof SeedExtra.static>; export type SeedExtra = Prettify<typeof SeedExtra.static>;
registerExamples(Extra, madeInAbyss.extras[0]);

View File

@ -1,5 +1,6 @@
import { t } from "elysia"; import { t } from "elysia";
import { type Prettify, comment } from "~/utils"; import { type Prettify, comment } from "~/utils";
import { bubbleImages, madeInAbyss, registerExamples } from "../examples";
import { import {
ExternalId, ExternalId,
Image, Image,
@ -11,7 +12,6 @@ import { BaseEntry, EntryTranslation } from "./base-entry";
export const BaseMovieEntry = t.Intersect( export const BaseMovieEntry = t.Intersect(
[ [
BaseEntry,
t.Object({ t.Object({
kind: t.Literal("movie"), kind: t.Literal("movie"),
order: t.Number({ order: t.Number({
@ -20,6 +20,7 @@ export const BaseMovieEntry = t.Intersect(
}), }),
externalId: ExternalId, externalId: ExternalId,
}), }),
BaseEntry,
], ],
{ {
description: comment` description: comment`
@ -39,8 +40,8 @@ export const MovieEntryTranslation = t.Intersect([
export const MovieEntry = t.Intersect([ export const MovieEntry = t.Intersect([
Resource(), Resource(),
BaseMovieEntry,
MovieEntryTranslation, MovieEntryTranslation,
BaseMovieEntry,
]); ]);
export type MovieEntry = Prettify<typeof MovieEntry.static>; export type MovieEntry = Prettify<typeof MovieEntry.static>;
@ -59,3 +60,10 @@ export const SeedMovieEntry = t.Intersect([
}), }),
]); ]);
export type SeedMovieEntry = Prettify<typeof SeedMovieEntry.static>; export type SeedMovieEntry = Prettify<typeof SeedMovieEntry.static>;
const ep = madeInAbyss.entries.find((x) => x.kind === "movie")!;
registerExamples(MovieEntry, {
...ep,
...ep.translations.en,
...bubbleImages,
});

View File

@ -2,10 +2,10 @@ import { t } from "elysia";
import { type Prettify, comment } from "~/utils"; import { type Prettify, comment } from "~/utils";
import { EpisodeId, Resource, SeedImage, TranslationRecord } from "../utils"; import { EpisodeId, Resource, SeedImage, TranslationRecord } from "../utils";
import { BaseEntry, EntryTranslation } from "./base-entry"; import { BaseEntry, EntryTranslation } from "./base-entry";
import { bubbleImages, madeInAbyss, registerExamples } from "../examples";
export const BaseSpecial = t.Intersect( export const BaseSpecial = t.Intersect(
[ [
BaseEntry,
t.Object({ t.Object({
kind: t.Literal("special"), kind: t.Literal("special"),
order: t.Number({ order: t.Number({
@ -15,6 +15,7 @@ export const BaseSpecial = t.Intersect(
number: t.Number({ minimum: 1 }), number: t.Number({ minimum: 1 }),
externalId: EpisodeId, externalId: EpisodeId,
}), }),
BaseEntry,
], ],
{ {
description: comment` description: comment`
@ -24,7 +25,7 @@ export const BaseSpecial = t.Intersect(
}, },
); );
export const Special = t.Intersect([Resource(), BaseSpecial, EntryTranslation]); export const Special = t.Intersect([Resource(), EntryTranslation, BaseSpecial]);
export type Special = Prettify<typeof Special.static>; export type Special = Prettify<typeof Special.static>;
export const SeedSpecial = t.Intersect([ export const SeedSpecial = t.Intersect([
@ -36,3 +37,11 @@ export const SeedSpecial = t.Intersect([
}), }),
]); ]);
export type SeedSpecial = Prettify<typeof SeedSpecial.static>; export type SeedSpecial = Prettify<typeof SeedSpecial.static>;
const ep = madeInAbyss.entries.find((x) => x.kind === "special")!;
registerExamples(Special, {
...ep,
...ep.translations.en,
...bubbleImages,
slug: `${madeInAbyss.slug}-sp3`
});

View File

@ -84,7 +84,6 @@ export const madeInAbyss = {
}, },
seasons: [ seasons: [
{ {
slug: "made-in-abyss-s1",
seasonNumber: 1, seasonNumber: 1,
translations: { translations: {
en: { en: {
@ -108,7 +107,6 @@ export const madeInAbyss = {
}, },
}, },
{ {
slug: "made-in-abyss-s2",
seasonNumber: 2, seasonNumber: 2,
translations: { translations: {
en: { en: {

View File

@ -1,4 +1,5 @@
import { t } from "elysia"; import { t } from "elysia";
import type { Prettify } from "~/utils";
import { bubbleImages, madeInAbyss, registerExamples } from "./examples"; import { bubbleImages, madeInAbyss, registerExamples } from "./examples";
import { SeasonId } from "./utils/external-id"; import { SeasonId } from "./utils/external-id";
import { Image, SeedImage } from "./utils/image"; import { Image, SeedImage } from "./utils/image";
@ -26,13 +27,12 @@ export const SeasonTranslation = t.Object({
}); });
export type SeasonTranslation = typeof SeasonTranslation.static; export type SeasonTranslation = typeof SeasonTranslation.static;
export const Season = t.Intersect([Resource(), BaseSeason, SeasonTranslation]); export const Season = t.Intersect([Resource(), SeasonTranslation, BaseSeason]);
export type Season = typeof Season.static; export type Season = typeof Season.static;
export const SeedSeason = t.Intersect([ export const SeedSeason = t.Intersect([
t.Omit(BaseSeason, ["createdAt", "nextRefresh"]), t.Omit(BaseSeason, ["createdAt", "nextRefresh"]),
t.Object({ t.Object({
slug: t.String({ format: "slug", examples: ["made-in-abyss-s1"] }),
translations: TranslationRecord( translations: TranslationRecord(
t.Intersect([ t.Intersect([
t.Omit(SeasonTranslation, ["poster", "thumbnail", "banner"]), t.Omit(SeasonTranslation, ["poster", "thumbnail", "banner"]),
@ -45,10 +45,11 @@ export const SeedSeason = t.Intersect([
), ),
}), }),
]); ]);
export type SeedSeason = typeof SeedSeason.static; export type SeedSeason = Prettify<typeof SeedSeason.static>;
registerExamples(Season, { registerExamples(Season, {
...madeInAbyss.seasons[0], ...madeInAbyss.seasons[0],
...madeInAbyss.seasons[0].translations.en, ...madeInAbyss.seasons[0].translations.en,
...bubbleImages, ...bubbleImages,
slug: `${madeInAbyss.slug}-s1`,
}); });

View File

@ -22,6 +22,7 @@ export const Language = (props?: NonNullable<Parameters<typeof t.String>[0]>) =>
BCP 47 is also known as RFC 5646. It subsumes ISO 639 and is backward compatible with it. BCP 47 is also known as RFC 5646. It subsumes ISO 639 and is backward compatible with it.
`, `,
error: "Expected a valid (and NORMALIZED) bcp-47 language code.", error: "Expected a valid (and NORMALIZED) bcp-47 language code.",
examples: ["en-US"],
...props, ...props,
}), }),
) )
@ -39,9 +40,15 @@ export const TranslationRecord = <T extends TSchema>(
props?: Parameters<typeof t.Record<TString, T>>[2], props?: Parameters<typeof t.Record<TString, T>>[2],
) => ) =>
t t
.Transform(t.Record(t.String(), values, { minPropreties: 1, ...props })) .Transform(
// @ts-expect-error idk why the translations type can't get resolved so it's a pain to work t.Record(
// with without casting it t.String({
examples: ["en-US"],
}),
values,
{ minPropreties: 1, ...props },
),
)
.Decode((translations: Record<string, StaticDecode<T>>) => { .Decode((translations: Record<string, StaticDecode<T>>) => {
for (const lang of Object.keys(translations)) { for (const lang of Object.keys(translations)) {
try { try {
@ -91,10 +98,11 @@ export const AcceptLanguage = ({
comment` comment`
List of languages you want the data in. List of languages you want the data in.
This follows the [Accept-Language offical specification](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language). This follows the [Accept-Language offical specification](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language).
` + autoFallback ` +
(autoFallback
? comment` ? comment`
In this request, * is always implied (if no language could satisfy the request, kyoo will use any language available.) In this request, * is always implied (if no language could satisfy the request, kyoo will use any language available.)
` `
: "", : ""),
}); });