diff --git a/api/README.md b/api/README.md index df7a1dcf..6faa62eb 100644 --- a/api/README.md +++ b/api/README.md @@ -129,30 +129,19 @@ erDiagram guid staff_id PK, FK uint order type type "actor|director|writer|producer|music|other" + string character_name + string character_latin_name jsonb character_image } - - role_translations { - string language PK - string character_name - } - roles||--o{ role_translations : has - shows ||--|{ roles : has - staff { guid id PK string(256) slug UK + string name "NN" + string latin_name jsonb image datetime next_refresh jsonb external_id } - - staff_translations { - guid id PK,FK - string language PK - string name "NN" - } - staff ||--|{ staff_translations : has staff ||--|{ roles : has studios { diff --git a/api/src/db/schema/index.ts b/api/src/db/schema/index.ts index 4b5707eb..3488c4cc 100644 --- a/api/src/db/schema/index.ts +++ b/api/src/db/schema/index.ts @@ -2,4 +2,5 @@ export * from "./entries"; export * from "./seasons"; export * from "./shows"; export * from "./studios"; +export * from "./staff"; export * from "./videos"; diff --git a/api/src/db/schema/shows.ts b/api/src/db/schema/shows.ts index d00a5e6c..6729071f 100644 --- a/api/src/db/schema/shows.ts +++ b/api/src/db/schema/shows.ts @@ -16,6 +16,7 @@ import { import type { Image, Original } from "~/models/utils"; import { entries } from "./entries"; import { seasons } from "./seasons"; +import { roles } from "./staff"; import { showStudioJoin } from "./studios"; import { externalid, image, language, schema } from "./utils"; @@ -134,6 +135,7 @@ export const showsRelations = relations(shows, ({ many }) => ({ entries: many(entries, { relationName: "show_entries" }), seasons: many(seasons, { relationName: "show_seasons" }), studios: many(showStudioJoin, { relationName: "ssj_show" }), + staff: many(roles, { relationName: "show_roles" }), })); export const showsTrRelations = relations(showTranslations, ({ one }) => ({ show: one(shows, { diff --git a/api/src/db/schema/staff.ts b/api/src/db/schema/staff.ts new file mode 100644 index 00000000..351de0fb --- /dev/null +++ b/api/src/db/schema/staff.ts @@ -0,0 +1,76 @@ +import { relations, sql } from "drizzle-orm"; +import { + index, + integer, + jsonb, + primaryKey, + text, + timestamp, + uuid, + varchar, +} from "drizzle-orm/pg-core"; +import type { Character } from "~/models/staff"; +import { shows } from "./shows"; +import { externalid, image, schema } from "./utils"; + +export const roleKind = schema.enum("role_kind", [ + "actor", + "director", + "writter", + "producer", + "music", + "other", +]); + +export const staff = schema.table("staff", { + pk: integer().primaryKey().generatedAlwaysAsIdentity(), + id: uuid().notNull().unique().defaultRandom(), + slug: varchar({ length: 255 }).notNull().unique(), + name: text().notNull(), + latinName: text(), + image: image(), + externalId: externalid(), + + createdAt: timestamp({ withTimezone: true, mode: "string" }) + .notNull() + .defaultNow(), + updatedAt: timestamp({ withTimezone: true, mode: "string" }) + .notNull() + .$onUpdate(() => sql`now()`), +}); + +export const roles = schema.table( + "roles", + { + showPk: integer() + .notNull() + .references(() => shows.pk, { onDelete: "cascade" }), + staffPk: integer() + .notNull() + .references(() => staff.pk, { onDelete: "cascade" }), + kind: roleKind().notNull(), + order: integer().notNull(), + character: jsonb().$type(), + }, + (t) => [ + primaryKey({ columns: [t.showPk, t.staffPk] }), + index("role_kind").using("hash", t.kind), + index("role_order").on(t.order), + ], +); + +export const staffRelations = relations(staff, ({ many }) => ({ + roles: many(roles, { relationName: "staff_roles" }), +})); +export const rolesRelations = relations(roles, ({ one }) => ({ + staff: one(staff, { + relationName: "staff_roles", + fields: [roles.staffPk], + references: [staff.pk], + }), + show: one(shows, { + relationName: "show_roles", + fields: [roles.showPk], + references: [shows.pk], + }), +})); diff --git a/api/src/models/staff.ts b/api/src/models/staff.ts new file mode 100644 index 00000000..62737f51 --- /dev/null +++ b/api/src/models/staff.ts @@ -0,0 +1,34 @@ +import { t } from "elysia"; +import { DbMetadata, ExternalId, Image, Resource } from "./utils"; + +export const Character = t.Object({ + name: t.String(), + latinName: t.String(), + image: t.Nullable(Image), +}); +export type Character = typeof Character.static; + +export const Role = t.Object({ + kind: t.UnionEnum([ + "actor", + "director", + "writter", + "producer", + "music", + "other", + ]), + character: t.Nullable(Character), +}); +export type Role = typeof Role.static; + +export const Staff = t.Intersect([ + Resource(), + t.Object({ + name: t.String(), + latinName: t.String(), + image: t.Nullable(Image), + externalId: ExternalId(), + }), + DbMetadata, +]); +export type Staff = typeof Staff.static;