diff --git a/api/src/controllers/shows/logic.ts b/api/src/controllers/shows/logic.ts index d32740ed..311d3a16 100644 --- a/api/src/controllers/shows/logic.ts +++ b/api/src/controllers/shows/logic.ts @@ -2,11 +2,14 @@ import type { StaticDecode } from "@sinclair/typebox"; import { type SQL, and, eq, exists, sql } from "drizzle-orm"; import { db } from "~/db"; import { + entries, + entryVideoJoin, showStudioJoin, showTranslations, shows, studioTranslations, studios, + videos, } from "~/db/schema"; import { coalesce, @@ -28,6 +31,7 @@ import { keysetPaginate, sortToSql, } from "~/models/utils"; +import type { EmbeddedVideo } from "~/models/video"; export const showFilters: FilterDef = { genres: { @@ -120,7 +124,24 @@ const showRelations = { }, // only available for movies videos: () => { - throw new Error(); + const { guess, createdAt, updatedAt, ...videosCol } = getColumns(videos); + return db + .select({ + videos: coalesce( + jsonbAgg( + jsonbBuildObject({ + slug: entryVideoJoin.slug, + ...videosCol, + }), + ), + sql`'[]'::jsonb`, + ).as("videos"), + }) + .from(entryVideoJoin) + .where(eq(entryVideoJoin.entryPk, entries.pk)) + .leftJoin(entries, eq(entries.showPk, shows.pk)) + .leftJoin(videos, eq(videos.pk, entryVideoJoin.videoPk)) + .as("videos"); }, }; diff --git a/api/src/models/movie.ts b/api/src/models/movie.ts index dfd2bd3a..86ed58d6 100644 --- a/api/src/models/movie.ts +++ b/api/src/models/movie.ts @@ -14,7 +14,7 @@ import { TranslationRecord, } from "./utils"; import { Original } from "./utils/original"; -import { Video } from "./video"; +import { EmbeddedVideo } from "./video"; export const MovieStatus = t.UnionEnum(["unknown", "finished", "planned"]); export type MovieStatus = typeof MovieStatus.static; @@ -62,7 +62,7 @@ export const FullMovie = t.Intersect([ Movie, t.Object({ translations: t.Optional(TranslationRecord(MovieTranslation)), - videos: t.Optional(t.Array(Video)), + videos: t.Optional(t.Array(EmbeddedVideo)), studios: t.Optional(t.Array(Studio)), }), ]); diff --git a/api/tests/movies/get-movie.test.ts b/api/tests/movies/get-movie.test.ts index 4b5d6252..f9afa6fe 100644 --- a/api/tests/movies/get-movie.test.ts +++ b/api/tests/movies/get-movie.test.ts @@ -134,4 +134,35 @@ describe("Get movie", () => { expectStatus(resp, body).toBe(200); expect(body.isAvailable).toBe(false); }); + + it("with=translations", async () => { + const [resp, body] = await getMovie(bubble.slug, { + with: ["translations"], + }); + + expectStatus(resp, body).toBe(200); + expect(body.translations).toMatchObject({ + en: { name: bubble.translations.en.name }, + ja: { name: bubble.translations.ja.name }, + }); + }); + it("with=translations,videos", async () => { + const [resp, body] = await getMovie(bubble.slug, { + with: ["translations", "videos"], + }); + + expectStatus(resp, body).toBe(200); + expect(body.translations).toMatchObject({ + en: { name: bubble.translations.en.name }, + ja: { name: bubble.translations.ja.name }, + }); + expect(body.videos).toBeArrayOfSize(bubble.videos!.length); + expect(body.videos[0]).toMatchObject({ + path: bubbleVideo.path, + slug: bubbleVideo.slug, + version: bubbleVideo.version, + rendering: bubbleVideo.rendering, + part: bubbleVideo.part, + }); + }); });