Add a flag to retrieve all translations

This commit is contained in:
Zoe Roux 2025-01-17 23:10:56 +01:00
parent 02ddd1401b
commit 956ab51e1b
4 changed files with 57 additions and 32 deletions

View File

@ -11,7 +11,12 @@ import {
} from "~/db/schema";
import { getColumns, sqlarr } from "~/db/schema/utils";
import { bubble } from "~/models/examples";
import { Movie, MovieStatus, MovieTranslation } from "~/models/movie";
import {
FullMovie,
Movie,
MovieStatus,
MovieTranslation,
} from "~/models/movie";
import {
Filter,
type Image,
@ -49,7 +54,7 @@ export const movies = new Elysia({ prefix: "/movies", tags: ["movies"] })
async ({
params: { id },
headers: { "accept-language": languages },
query: { preferOriginal },
query: { preferOriginal, with: relations },
error,
set,
}) => {
@ -86,7 +91,7 @@ export const movies = new Elysia({ prefix: "/movies", tags: ["movies"] })
isUuid(id) ? eq(shows.id, id) : eq(shows.slug, id),
),
with: {
translations: {
selectedTranslation: {
columns: {
pk: false,
},
@ -113,6 +118,13 @@ export const movies = new Elysia({ prefix: "/movies", tags: ["movies"] })
),
},
},
...(relations.includes("translations") && {
translations: {
columns: {
pk: false,
},
},
}),
},
});
@ -122,7 +134,7 @@ export const movies = new Elysia({ prefix: "/movies", tags: ["movies"] })
message: "Movie not found",
});
}
const translation = ret.translations[0];
const translation = ret.selectedTranslation[0];
if (!translation) {
return error(422, {
status: 422,
@ -140,6 +152,14 @@ export const movies = new Elysia({ prefix: "/movies", tags: ["movies"] })
...(ot.banner && { banner: ot.banner }),
...(ot.logo && { logo: ot.logo }),
}),
...(ret.translations && {
translations: Object.fromEntries(
ret.translations.map(
({ language, ...translation }) =>
[language, translation] as const,
),
),
}),
};
},
{
@ -162,6 +182,10 @@ export const movies = new Elysia({ prefix: "/movies", tags: ["movies"] })
`,
}),
),
with: t.Array(t.UnionEnum(["translations", "videos"]), {
default: [],
description: "Include related resources in the response.",
}),
}),
headers: t.Object({
"accept-language": t.String({
@ -174,13 +198,10 @@ export const movies = new Elysia({ prefix: "/movies", tags: ["movies"] })
}),
}),
response: {
200: { ...Movie, description: "Found" },
200: { ...FullMovie, description: "Found" },
404: {
...KError,
description: "No movie found with the given id or slug.",
examples: [
{ status: 404, message: "Movie not found", details: undefined },
],
},
422: {
...KError,
@ -189,12 +210,6 @@ export const movies = new Elysia({ prefix: "/movies", tags: ["movies"] })
unavailable.) Try with another languages or add * to the list of languages
to fallback to any language.
`,
examples: [
{
status: 422,
message: "Accept-Language header could not be satisfied.",
},
],
},
},
},
@ -227,9 +242,6 @@ export const movies = new Elysia({ prefix: "/movies", tags: ["movies"] })
404: {
...KError,
description: "No movie found with the given id or slug.",
examples: [
{ status: 404, message: "Movie not found", details: undefined },
],
},
},
},
@ -362,16 +374,6 @@ export const movies = new Elysia({ prefix: "/movies", tags: ["movies"] })
422: {
...KError,
description: "Invalid query parameters.",
examples: [
{
status: 422,
message:
"Invalid property: slug. Expected one of genres, rating, status, runtime, airDate, originalLanguage.",
details: {
in: "slug eq bubble",
},
},
],
},
},
},

View File

@ -110,6 +110,9 @@ export const showTranslations = schema.table(
);
export const showsRelations = relations(shows, ({ many, one }) => ({
selectedTranslation: many(showTranslations, {
relationName: "selectedTranslation",
}),
translations: many(showTranslations, { relationName: "showTranslations" }),
originalTranslation: one(showTranslations, {
relationName: "originalTranslation",
@ -123,6 +126,11 @@ export const showsTrRelations = relations(showTranslations, ({ one }) => ({
fields: [showTranslations.pk],
references: [shows.pk],
}),
selectedTranslation: one(shows, {
relationName: "selectedTranslation",
fields: [showTranslations.pk],
references: [shows.pk],
}),
originalTranslation: one(shows, {
relationName: "originalTranslation",
fields: [showTranslations.pk, showTranslations.language],

View File

@ -1,10 +1,15 @@
import { t } from "elysia";
export const KError = t.Object({
status: t.Integer(),
message: t.String(),
details: t.Optional(t.Any()),
});
export const KError = t.Object(
{
status: t.Integer(),
message: t.String(),
details: t.Optional(t.Any()),
},
{
examples: [{ status: 404, message: "Movie not found" }],
},
);
export type KError = typeof KError.static;
export class KErrorT extends Error {

View File

@ -9,6 +9,7 @@ import {
} from "./utils";
import { bubble, registerExamples } from "./examples";
import { bubbleImages } from "./examples/bubble";
import { Video } from "./video";
export const MovieStatus = t.UnionEnum(["unknown", "finished", "planned"]);
export type MovieStatus = typeof MovieStatus.static;
@ -58,6 +59,15 @@ export const Movie = t.Intersect([
]);
export type Movie = typeof Movie.static;
export const FullMovie = t.Intersect([
Movie,
t.Object({
translations: t.Optional(TranslationRecord(MovieTranslation)),
videos: t.Optional(t.Array(Video)),
}),
]);
export type FullMovie = typeof FullMovie.static;
export const SeedMovie = t.Intersect([
t.Omit(BaseMovie, ["id", "createdAt", "nextRefresh"]),
t.Object({