mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-06-23 15:30:34 -04:00
Add collections in v5 (#821)
This commit is contained in:
commit
9b1bd69eae
@ -8,7 +8,7 @@ The many-to-many relation between entries (episodes/movies) & videos is NOT a mi
|
||||
erDiagram
|
||||
shows {
|
||||
guid id PK
|
||||
kind kind "serie|movie"
|
||||
kind kind "serie|movie|collection"
|
||||
string(128) slug UK
|
||||
genre[] genres
|
||||
int rating "From 0 to 100"
|
||||
@ -20,6 +20,7 @@ erDiagram
|
||||
jsonb external_id
|
||||
guid studio_id FK
|
||||
string original_language
|
||||
guid collection_id FK
|
||||
}
|
||||
show_translations {
|
||||
guid id PK, FK
|
||||
@ -37,6 +38,7 @@ erDiagram
|
||||
}
|
||||
shows ||--|{ show_translations : has
|
||||
shows |o--|| entries : has
|
||||
shows |o--|| shows : has_collection
|
||||
|
||||
entries {
|
||||
guid id PK
|
||||
@ -70,23 +72,6 @@ erDiagram
|
||||
}
|
||||
video }|--|{ entries : for
|
||||
|
||||
collections {
|
||||
guid id PK
|
||||
string(256) slug UK
|
||||
datetime added_date
|
||||
datetime next_refresh
|
||||
}
|
||||
|
||||
collection_translations {
|
||||
guid id PK, FK
|
||||
string language PK
|
||||
string name "NN"
|
||||
jsonb poster
|
||||
jsonb thumbnail
|
||||
}
|
||||
collections ||--|{ collection_translations : has
|
||||
collections |o--|{ shows : has
|
||||
|
||||
seasons {
|
||||
guid id PK
|
||||
string(256) slug UK
|
||||
|
3
api/drizzle/0009_collections.sql
Normal file
3
api/drizzle/0009_collections.sql
Normal file
@ -0,0 +1,3 @@
|
||||
ALTER TYPE "kyoo"."show_kind" ADD VALUE 'collection';--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."shows" ADD COLUMN "collection_pk" integer;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."shows" ADD CONSTRAINT "shows_collection_pk_shows_pk_fk" FOREIGN KEY ("collection_pk") REFERENCES "kyoo"."shows"("pk") ON DELETE set null ON UPDATE no action;
|
969
api/drizzle/meta/0009_snapshot.json
Normal file
969
api/drizzle/meta/0009_snapshot.json
Normal file
@ -0,0 +1,969 @@
|
||||
{
|
||||
"id": "7a04670c-5fb9-4535-b6be-dc291b8b0b09",
|
||||
"prevId": "5c17dd71-409a-4c80-870d-f12386676738",
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"tables": {
|
||||
"kyoo.entries": {
|
||||
"name": "entries",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "entries_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"show_pk": {
|
||||
"name": "show_pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"order": {
|
||||
"name": "order",
|
||||
"type": "real",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"season_number": {
|
||||
"name": "season_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"episode_number": {
|
||||
"name": "episode_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"kind": {
|
||||
"name": "kind",
|
||||
"type": "entry_type",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"extra_kind": {
|
||||
"name": "extra_kind",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"air_date": {
|
||||
"name": "air_date",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"runtime": {
|
||||
"name": "runtime",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnail": {
|
||||
"name": "thumbnail",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"entries_show_pk_shows_pk_fk": {
|
||||
"name": "entries_show_pk_shows_pk_fk",
|
||||
"tableFrom": "entries",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["show_pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"entries_id_unique": {
|
||||
"name": "entries_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"entries_slug_unique": {
|
||||
"name": "entries_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
},
|
||||
"entries_showPk_seasonNumber_episodeNumber_unique": {
|
||||
"name": "entries_showPk_seasonNumber_episodeNumber_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["show_pk", "season_number", "episode_number"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"order_positive": {
|
||||
"name": "order_positive",
|
||||
"value": "\"kyoo\".\"entries\".\"order\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.entry_translations": {
|
||||
"name": "entry_translations",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"tagline": {
|
||||
"name": "tagline",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"poster": {
|
||||
"name": "poster",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"entry_translations_pk_entries_pk_fk": {
|
||||
"name": "entry_translations_pk_entries_pk_fk",
|
||||
"tableFrom": "entry_translations",
|
||||
"tableTo": "entries",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"entry_translations_pk_language_pk": {
|
||||
"name": "entry_translations_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.season_translations": {
|
||||
"name": "season_translations",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"poster": {
|
||||
"name": "poster",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnail": {
|
||||
"name": "thumbnail",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"banner": {
|
||||
"name": "banner",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"season_translations_pk_seasons_pk_fk": {
|
||||
"name": "season_translations_pk_seasons_pk_fk",
|
||||
"tableFrom": "season_translations",
|
||||
"tableTo": "seasons",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"season_translations_pk_language_pk": {
|
||||
"name": "season_translations_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.seasons": {
|
||||
"name": "seasons",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "seasons_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"show_pk": {
|
||||
"name": "show_pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"season_number": {
|
||||
"name": "season_number",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"start_air": {
|
||||
"name": "start_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"end_air": {
|
||||
"name": "end_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"show_fk": {
|
||||
"name": "show_fk",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "show_pk",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "hash",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"seasons_show_pk_shows_pk_fk": {
|
||||
"name": "seasons_show_pk_shows_pk_fk",
|
||||
"tableFrom": "seasons",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["show_pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"seasons_id_unique": {
|
||||
"name": "seasons_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"seasons_slug_unique": {
|
||||
"name": "seasons_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
},
|
||||
"seasons_showPk_seasonNumber_unique": {
|
||||
"name": "seasons_showPk_seasonNumber_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["show_pk", "season_number"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.show_translations": {
|
||||
"name": "show_translations",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"tagline": {
|
||||
"name": "tagline",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"aliases": {
|
||||
"name": "aliases",
|
||||
"type": "text[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"tags": {
|
||||
"name": "tags",
|
||||
"type": "text[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"poster": {
|
||||
"name": "poster",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnail": {
|
||||
"name": "thumbnail",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"banner": {
|
||||
"name": "banner",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"logo": {
|
||||
"name": "logo",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"trailer_url": {
|
||||
"name": "trailer_url",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"name_trgm": {
|
||||
"name": "name_trgm",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "\"name\" gin_trgm_ops",
|
||||
"asc": true,
|
||||
"isExpression": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "gin",
|
||||
"with": {}
|
||||
},
|
||||
"tags": {
|
||||
"name": "tags",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "tags",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"show_translations_pk_shows_pk_fk": {
|
||||
"name": "show_translations_pk_shows_pk_fk",
|
||||
"tableFrom": "show_translations",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"show_translations_pk_language_pk": {
|
||||
"name": "show_translations_pk_language_pk",
|
||||
"columns": ["pk", "language"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.shows": {
|
||||
"name": "shows",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "shows_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"kind": {
|
||||
"name": "kind",
|
||||
"type": "show_kind",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"genres": {
|
||||
"name": "genres",
|
||||
"type": "genres[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"rating": {
|
||||
"name": "rating",
|
||||
"type": "smallint",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"runtime": {
|
||||
"name": "runtime",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"status": {
|
||||
"name": "status",
|
||||
"type": "show_status",
|
||||
"typeSchema": "kyoo",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"start_air": {
|
||||
"name": "start_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"end_air": {
|
||||
"name": "end_air",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"original_language": {
|
||||
"name": "original_language",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"collection_pk": {
|
||||
"name": "collection_pk",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"external_id": {
|
||||
"name": "external_id",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"next_refresh": {
|
||||
"name": "next_refresh",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"kind": {
|
||||
"name": "kind",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "kind",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "hash",
|
||||
"with": {}
|
||||
},
|
||||
"rating": {
|
||||
"name": "rating",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "rating",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
},
|
||||
"startAir": {
|
||||
"name": "startAir",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "start_air",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"shows_collection_pk_shows_pk_fk": {
|
||||
"name": "shows_collection_pk_shows_pk_fk",
|
||||
"tableFrom": "shows",
|
||||
"tableTo": "shows",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["collection_pk"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "set null",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"shows_id_unique": {
|
||||
"name": "shows_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"shows_slug_unique": {
|
||||
"name": "shows_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"rating_valid": {
|
||||
"name": "rating_valid",
|
||||
"value": "\"kyoo\".\"shows\".\"rating\" between 0 and 100"
|
||||
},
|
||||
"runtime_valid": {
|
||||
"name": "runtime_valid",
|
||||
"value": "\"kyoo\".\"shows\".\"runtime\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.entry_video_join": {
|
||||
"name": "entry_video_join",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"entry": {
|
||||
"name": "entry",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"video": {
|
||||
"name": "video",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"entry_video_join_entry_entries_pk_fk": {
|
||||
"name": "entry_video_join_entry_entries_pk_fk",
|
||||
"tableFrom": "entry_video_join",
|
||||
"tableTo": "entries",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["entry"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"entry_video_join_video_videos_pk_fk": {
|
||||
"name": "entry_video_join_video_videos_pk_fk",
|
||||
"tableFrom": "entry_video_join",
|
||||
"tableTo": "videos",
|
||||
"schemaTo": "kyoo",
|
||||
"columnsFrom": ["video"],
|
||||
"columnsTo": ["pk"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"entry_video_join_entry_video_pk": {
|
||||
"name": "entry_video_join_entry_video_pk",
|
||||
"columns": ["entry", "video"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {
|
||||
"entry_video_join_slug_unique": {
|
||||
"name": "entry_video_join_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["slug"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"kyoo.videos": {
|
||||
"name": "videos",
|
||||
"schema": "kyoo",
|
||||
"columns": {
|
||||
"pk": {
|
||||
"name": "pk",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"identity": {
|
||||
"type": "always",
|
||||
"name": "videos_pk_seq",
|
||||
"schema": "kyoo",
|
||||
"increment": "1",
|
||||
"startWith": "1",
|
||||
"minValue": "1",
|
||||
"maxValue": "2147483647",
|
||||
"cache": "1",
|
||||
"cycle": false
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"path": {
|
||||
"name": "path",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"rendering": {
|
||||
"name": "rendering",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"part": {
|
||||
"name": "part",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"version": {
|
||||
"name": "version",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": 1
|
||||
},
|
||||
"guess": {
|
||||
"name": "guess",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'::jsonb"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"videos_id_unique": {
|
||||
"name": "videos_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["id"]
|
||||
},
|
||||
"videos_path_unique": {
|
||||
"name": "videos_path_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": ["path"]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"part_pos": {
|
||||
"name": "part_pos",
|
||||
"value": "\"kyoo\".\"videos\".\"part\" >= 0"
|
||||
},
|
||||
"version_pos": {
|
||||
"name": "version_pos",
|
||||
"value": "\"kyoo\".\"videos\".\"version\" >= 0"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
}
|
||||
},
|
||||
"enums": {
|
||||
"kyoo.entry_type": {
|
||||
"name": "entry_type",
|
||||
"schema": "kyoo",
|
||||
"values": ["unknown", "episode", "movie", "special", "extra"]
|
||||
},
|
||||
"kyoo.genres": {
|
||||
"name": "genres",
|
||||
"schema": "kyoo",
|
||||
"values": [
|
||||
"action",
|
||||
"adventure",
|
||||
"animation",
|
||||
"comedy",
|
||||
"crime",
|
||||
"documentary",
|
||||
"drama",
|
||||
"family",
|
||||
"fantasy",
|
||||
"history",
|
||||
"horror",
|
||||
"music",
|
||||
"mystery",
|
||||
"romance",
|
||||
"science-fiction",
|
||||
"thriller",
|
||||
"war",
|
||||
"western",
|
||||
"kids",
|
||||
"reality",
|
||||
"politics",
|
||||
"soap",
|
||||
"talk"
|
||||
]
|
||||
},
|
||||
"kyoo.show_kind": {
|
||||
"name": "show_kind",
|
||||
"schema": "kyoo",
|
||||
"values": ["serie", "movie", "collection"]
|
||||
},
|
||||
"kyoo.show_status": {
|
||||
"name": "show_status",
|
||||
"schema": "kyoo",
|
||||
"values": ["unknown", "finished", "airing", "planned"]
|
||||
}
|
||||
},
|
||||
"schemas": {
|
||||
"kyoo": "kyoo"
|
||||
},
|
||||
"sequences": {},
|
||||
"roles": {},
|
||||
"policies": {},
|
||||
"views": {},
|
||||
"_meta": {
|
||||
"columns": {},
|
||||
"schemas": {},
|
||||
"tables": {}
|
||||
}
|
||||
}
|
@ -64,6 +64,13 @@
|
||||
"when": 1738064522937,
|
||||
"tag": "0008_entries",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 9,
|
||||
"version": "7",
|
||||
"when": 1740872363604,
|
||||
"tag": "0009_collections",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { type SQL, and, eq, exists, sql } from "drizzle-orm";
|
||||
import { Elysia, t } from "elysia";
|
||||
import { db } from "~/db";
|
||||
import { entries, entryVideoJoin, showTranslations, shows } from "~/db/schema";
|
||||
import { getColumns, sqlarr } from "~/db/utils";
|
||||
import { KError } from "~/models/error";
|
||||
@ -25,7 +26,6 @@ import {
|
||||
sortToSql,
|
||||
} from "~/models/utils";
|
||||
import { desc } from "~/models/utils/descriptions";
|
||||
import { db } from "../db";
|
||||
|
||||
const movieFilters: FilterDef = {
|
||||
genres: {
|
||||
|
69
api/src/controllers/seed/insert/collection.ts
Normal file
69
api/src/controllers/seed/insert/collection.ts
Normal file
@ -0,0 +1,69 @@
|
||||
import { sql } from "drizzle-orm";
|
||||
import { db } from "~/db";
|
||||
import { showTranslations, shows } from "~/db/schema";
|
||||
import { conflictUpdateAllExcept } from "~/db/utils";
|
||||
import type { SeedCollection } from "~/models/collections";
|
||||
import type { SeedMovie } from "~/models/movie";
|
||||
import type { SeedSerie } from "~/models/serie";
|
||||
import { processOptImage } from "../images";
|
||||
|
||||
type ShowTrans = typeof showTranslations.$inferInsert;
|
||||
|
||||
export const insertCollection = async (
|
||||
collection: SeedCollection | undefined,
|
||||
show: (({ kind: "movie" } & SeedMovie) | ({ kind: "serie" } & SeedSerie)) & {
|
||||
nextRefresh: string;
|
||||
},
|
||||
) => {
|
||||
if (!collection) return null;
|
||||
const { translations, ...col } = collection;
|
||||
|
||||
return await db.transaction(async (tx) => {
|
||||
const [ret] = await tx
|
||||
.insert(shows)
|
||||
.values({
|
||||
kind: "collection",
|
||||
status: "unknown",
|
||||
startAir: show.kind === "movie" ? show.airDate : show.startAir,
|
||||
endAir: show.kind === "movie" ? show.airDate : show.endAir,
|
||||
nextRefresh: show.nextRefresh,
|
||||
...col,
|
||||
})
|
||||
.onConflictDoUpdate({
|
||||
target: shows.slug,
|
||||
set: {
|
||||
...conflictUpdateAllExcept(shows, [
|
||||
"pk",
|
||||
"id",
|
||||
"slug",
|
||||
"createdAt",
|
||||
"startAir",
|
||||
"endAir",
|
||||
]),
|
||||
startAir: sql`least(${shows.startAir}, excluded.start_air)`,
|
||||
endAir: sql`greatest(${shows.endAir}, excluded.end_air)`,
|
||||
},
|
||||
})
|
||||
.returning({ pk: shows.pk, id: shows.id, slug: shows.slug });
|
||||
|
||||
const trans: ShowTrans[] = Object.entries(translations).map(
|
||||
([lang, tr]) => ({
|
||||
pk: ret.pk,
|
||||
language: lang,
|
||||
...tr,
|
||||
poster: processOptImage(tr.poster),
|
||||
thumbnail: processOptImage(tr.thumbnail),
|
||||
logo: processOptImage(tr.logo),
|
||||
banner: processOptImage(tr.banner),
|
||||
}),
|
||||
);
|
||||
await tx
|
||||
.insert(showTranslations)
|
||||
.values(trans)
|
||||
.onConflictDoUpdate({
|
||||
target: [showTranslations.pk, showTranslations.language],
|
||||
set: conflictUpdateAllExcept(showTranslations, ["pk", "language"]),
|
||||
});
|
||||
return ret;
|
||||
});
|
||||
};
|
@ -2,6 +2,7 @@ import { eq, sql } from "drizzle-orm";
|
||||
import { db } from "~/db";
|
||||
import { showTranslations, shows } from "~/db/schema";
|
||||
import { conflictUpdateAllExcept } from "~/db/utils";
|
||||
import type { SeedCollection } from "~/models/collections";
|
||||
import type { SeedMovie } from "~/models/movie";
|
||||
import type { SeedSerie } from "~/models/serie";
|
||||
import { getYear } from "~/utils";
|
||||
@ -12,7 +13,10 @@ type ShowTrans = typeof showTranslations.$inferInsert;
|
||||
|
||||
export const insertShow = async (
|
||||
show: Show,
|
||||
translations: SeedMovie["translations"] | SeedSerie["translations"],
|
||||
translations:
|
||||
| SeedMovie["translations"]
|
||||
| SeedSerie["translations"]
|
||||
| SeedCollection["translations"],
|
||||
) => {
|
||||
return await db.transaction(async (tx) => {
|
||||
const ret = await insertBaseShow(tx, show);
|
||||
@ -77,13 +81,14 @@ async function insertBaseShow(
|
||||
|
||||
// if at this point ret is still undefined, we could not reconciliate.
|
||||
// simply bail and let the caller handle this.
|
||||
const [{ id }] = await db
|
||||
.select({ id: shows.id })
|
||||
const [{ pk, id }] = await db
|
||||
.select({ pk: shows.pk, id: shows.id })
|
||||
.from(shows)
|
||||
.where(eq(shows.slug, show.slug))
|
||||
.limit(1);
|
||||
return {
|
||||
status: 409 as const,
|
||||
pk,
|
||||
id,
|
||||
slug: show.slug,
|
||||
};
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { t } from "elysia";
|
||||
import type { SeedMovie } from "~/models/movie";
|
||||
import { getYear } from "~/utils";
|
||||
import { insertCollection } from "./insert/collection";
|
||||
import { insertEntries } from "./insert/entries";
|
||||
import { insertShow } from "./insert/shows";
|
||||
import { guessNextRefresh } from "./refresh";
|
||||
@ -11,6 +12,12 @@ export const SeedMovieResponse = t.Object({
|
||||
videos: t.Array(
|
||||
t.Object({ slug: t.String({ format: "slug", examples: ["bubble-v2"] }) }),
|
||||
),
|
||||
collection: t.Nullable(
|
||||
t.Object({
|
||||
id: t.String({ format: "uuid" }),
|
||||
slug: t.String({ format: "slug", examples: ["sawano-collection"] }),
|
||||
}),
|
||||
),
|
||||
});
|
||||
export type SeedMovieResponse = typeof SeedMovieResponse.static;
|
||||
|
||||
@ -31,14 +38,21 @@ export const seedMovie = async (
|
||||
seed.slug = `random-${getYear(seed.airDate)}`;
|
||||
}
|
||||
|
||||
const { translations, videos, ...bMovie } = seed;
|
||||
const { translations, videos, collection, ...bMovie } = seed;
|
||||
const nextRefresh = guessNextRefresh(bMovie.airDate ?? new Date());
|
||||
|
||||
const col = await insertCollection(collection, {
|
||||
kind: "movie",
|
||||
nextRefresh,
|
||||
...seed,
|
||||
});
|
||||
|
||||
const show = await insertShow(
|
||||
{
|
||||
kind: "movie",
|
||||
startAir: bMovie.airDate,
|
||||
nextRefresh,
|
||||
collectionPk: col?.pk,
|
||||
...bMovie,
|
||||
},
|
||||
translations,
|
||||
@ -65,5 +79,6 @@ export const seedMovie = async (
|
||||
id: show.id,
|
||||
slug: show.slug,
|
||||
videos: entry.videos,
|
||||
collection: col,
|
||||
};
|
||||
};
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { t } from "elysia";
|
||||
import type { SeedSerie } from "~/models/serie";
|
||||
import { getYear } from "~/utils";
|
||||
import { insertCollection } from "./insert/collection";
|
||||
import { insertEntries } from "./insert/entries";
|
||||
import { insertSeasons } from "./insert/seasons";
|
||||
import { insertShow } from "./insert/shows";
|
||||
@ -35,6 +36,15 @@ export const SeedSerieResponse = t.Object({
|
||||
slug: t.String({ format: "slug", examples: ["made-in-abyss-s1e1"] }),
|
||||
}),
|
||||
),
|
||||
collection: t.Nullable(
|
||||
t.Object({
|
||||
id: t.String({ format: "uuid" }),
|
||||
slug: t.String({
|
||||
format: "slug",
|
||||
examples: ["made-in-abyss-collection"],
|
||||
}),
|
||||
}),
|
||||
),
|
||||
});
|
||||
export type SeedSerieResponse = typeof SeedSerieResponse.static;
|
||||
|
||||
@ -55,13 +65,20 @@ export const seedSerie = async (
|
||||
seed.slug = `random-${getYear(seed.startAir)}`;
|
||||
}
|
||||
|
||||
const { translations, seasons, entries, extras, ...serie } = seed;
|
||||
const { translations, seasons, entries, extras, collection, ...serie } = seed;
|
||||
const nextRefresh = guessNextRefresh(serie.startAir ?? new Date());
|
||||
|
||||
const col = await insertCollection(collection, {
|
||||
kind: "serie",
|
||||
nextRefresh,
|
||||
...seed,
|
||||
});
|
||||
|
||||
const show = await insertShow(
|
||||
{
|
||||
kind: "serie",
|
||||
nextRefresh,
|
||||
collectionPk: col?.pk,
|
||||
...serie,
|
||||
},
|
||||
translations,
|
||||
@ -82,5 +99,6 @@ export const seedSerie = async (
|
||||
seasons: retSeasons,
|
||||
entries: retEntries,
|
||||
extras: retExtras,
|
||||
collection: col,
|
||||
};
|
||||
};
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { relations, sql } from "drizzle-orm";
|
||||
import {
|
||||
type AnyPgColumn,
|
||||
check,
|
||||
date,
|
||||
index,
|
||||
@ -16,7 +17,11 @@ import { entries } from "./entries";
|
||||
import { seasons } from "./seasons";
|
||||
import { image, language, schema } from "./utils";
|
||||
|
||||
export const showKind = schema.enum("show_kind", ["serie", "movie"]);
|
||||
export const showKind = schema.enum("show_kind", [
|
||||
"serie",
|
||||
"movie",
|
||||
"collection",
|
||||
]);
|
||||
export const showStatus = schema.enum("show_status", [
|
||||
"unknown",
|
||||
"finished",
|
||||
@ -78,6 +83,10 @@ export const shows = schema.table(
|
||||
endAir: date(),
|
||||
originalLanguage: language(),
|
||||
|
||||
collectionPk: integer().references((): AnyPgColumn => shows.pk, {
|
||||
onDelete: "set null",
|
||||
}),
|
||||
|
||||
externalId: externalid(),
|
||||
|
||||
createdAt: timestamp({ withTimezone: true, mode: "string" })
|
||||
|
83
api/src/models/collections.ts
Normal file
83
api/src/models/collections.ts
Normal file
@ -0,0 +1,83 @@
|
||||
import { t } from "elysia";
|
||||
import type { Prettify } from "elysia/dist/types";
|
||||
import { bubbleImages, duneCollection, registerExamples } from "./examples";
|
||||
import {
|
||||
ExternalId,
|
||||
Genre,
|
||||
Image,
|
||||
Resource,
|
||||
SeedImage,
|
||||
TranslationRecord,
|
||||
} from "./utils";
|
||||
|
||||
const BaseCollection = t.Object({
|
||||
genres: t.Array(Genre),
|
||||
rating: t.Nullable(t.Integer({ minimum: 0, maximum: 100 })),
|
||||
startAir: t.Nullable(
|
||||
t.String({
|
||||
format: "date",
|
||||
descrpition: "Date of the first item of the collection",
|
||||
}),
|
||||
),
|
||||
endAir: t.Nullable(
|
||||
t.String({
|
||||
format: "date",
|
||||
descrpition: "Date of the last item of the collection",
|
||||
}),
|
||||
),
|
||||
|
||||
createdAt: t.String({ format: "date-time" }),
|
||||
nextRefresh: t.String({ format: "date-time" }),
|
||||
|
||||
externalId: ExternalId,
|
||||
});
|
||||
|
||||
export const CollectionTranslation = t.Object({
|
||||
name: t.String(),
|
||||
description: t.Nullable(t.String()),
|
||||
tagline: t.Nullable(t.String()),
|
||||
aliases: t.Array(t.String()),
|
||||
tags: t.Array(t.String()),
|
||||
|
||||
poster: t.Nullable(Image),
|
||||
thumbnail: t.Nullable(Image),
|
||||
banner: t.Nullable(Image),
|
||||
logo: t.Nullable(Image),
|
||||
});
|
||||
|
||||
export const Collection = t.Intersect([
|
||||
Resource(),
|
||||
CollectionTranslation,
|
||||
BaseCollection,
|
||||
]);
|
||||
export type Collection = Prettify<typeof Collection.static>;
|
||||
|
||||
export const SeedCollection = t.Intersect([
|
||||
t.Omit(BaseCollection, ["startAir", "endAir", "createdAt", "nextRefresh"]),
|
||||
t.Object({
|
||||
slug: t.String({ format: "slug" }),
|
||||
translations: TranslationRecord(
|
||||
t.Intersect([
|
||||
t.Omit(CollectionTranslation, [
|
||||
"poster",
|
||||
"thumbnail",
|
||||
"banner",
|
||||
"logo",
|
||||
]),
|
||||
t.Object({
|
||||
poster: t.Nullable(SeedImage),
|
||||
thumbnail: t.Nullable(SeedImage),
|
||||
banner: t.Nullable(SeedImage),
|
||||
logo: t.Nullable(SeedImage),
|
||||
}),
|
||||
]),
|
||||
),
|
||||
}),
|
||||
]);
|
||||
export type SeedCollection = Prettify<typeof SeedCollection.static>;
|
||||
|
||||
registerExamples(Collection, {
|
||||
...duneCollection,
|
||||
...duneCollection.translations.en,
|
||||
...bubbleImages,
|
||||
});
|
@ -1,5 +1,5 @@
|
||||
import type { SeedMovie } from "../movie";
|
||||
import type { Video } from "../video";
|
||||
import type { SeedMovie } from "~/models/movie";
|
||||
import type { Video } from "~/models/video";
|
||||
|
||||
export const duneVideo: Video = {
|
||||
id: "c9a0d02e-6b8e-4ac1-b431-45b022ec0708",
|
||||
@ -38,8 +38,8 @@ export const dune: SeedMovie = {
|
||||
originalLanguage: "en",
|
||||
externalId: {
|
||||
themoviedatabase: {
|
||||
dataId: "496243",
|
||||
link: "https://www.themoviedb.org/movie/496243",
|
||||
dataId: "438631",
|
||||
link: "https://www.themoviedb.org/movie/438631-dune",
|
||||
},
|
||||
imdb: {
|
||||
dataId: "tt1160419",
|
||||
|
29
api/src/models/examples/dune-collection.ts
Normal file
29
api/src/models/examples/dune-collection.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import type { SeedCollection } from "~/models/collections";
|
||||
|
||||
export const duneCollection: SeedCollection = {
|
||||
slug: "dune-collection",
|
||||
translations: {
|
||||
en: {
|
||||
name: " Dune Collection",
|
||||
tagline: "A mythic and emotionally charged hero's journey.",
|
||||
description:
|
||||
"The saga of Paul Atreides and his rise to power on the deadly planet Arrakis.",
|
||||
aliases: [],
|
||||
tags: ["sci-fi", "adventure", "drama", "action", "epic"],
|
||||
poster:
|
||||
"https://image.tmdb.org/t/p/original/wD57HqZ6fXwwDdfQLo4hXLRwGV1.jpg",
|
||||
thumbnail:
|
||||
"https://image.tmdb.org/t/p/original/k2ocXnNkmvE6rJomRkExIStFq3v.jpg",
|
||||
banner: null,
|
||||
logo: "https://image.tmdb.org/t/p/original/5nDsd3u1c6kDphbtIqkHseLg7HL.png",
|
||||
},
|
||||
},
|
||||
genres: ["adventure", "science-fiction"],
|
||||
rating: 80,
|
||||
externalId: {
|
||||
themoviedatabase: {
|
||||
dataId: "726871",
|
||||
link: "https://www.themoviedb.org/collection/726871-dune-collection",
|
||||
},
|
||||
},
|
||||
};
|
@ -32,3 +32,7 @@ export const registerExamples = <T extends TSchema>(
|
||||
|
||||
export * from "./bubble";
|
||||
export * from "./made-in-abyss";
|
||||
export * from "./dune-1984";
|
||||
export * from "./dune-2021";
|
||||
export * from "./dune-collection";
|
||||
export * from "./others";
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { t } from "elysia";
|
||||
import type { Prettify } from "~/utils";
|
||||
import { SeedCollection } from "./collections";
|
||||
import { bubble, registerExamples } from "./examples";
|
||||
import { bubbleImages } from "./examples/bubble";
|
||||
import {
|
||||
@ -85,6 +86,7 @@ export const SeedMovie = t.Intersect([
|
||||
]),
|
||||
),
|
||||
videos: t.Optional(t.Array(t.String({ format: "uuid" }))),
|
||||
collection: t.Optional(SeedCollection),
|
||||
}),
|
||||
]);
|
||||
export type SeedMovie = Prettify<typeof SeedMovie.static>;
|
||||
|
@ -1,4 +1,6 @@
|
||||
import { t } from "elysia";
|
||||
import type { Prettify } from "~/utils";
|
||||
import { SeedCollection } from "./collections";
|
||||
import { SeedEntry, SeedExtra } from "./entry";
|
||||
import { bubbleImages, madeInAbyss, registerExamples } from "./examples";
|
||||
import { SeedSeason } from "./season";
|
||||
@ -57,7 +59,7 @@ export const SerieTranslation = t.Object({
|
||||
export type SerieTranslation = typeof SerieTranslation.static;
|
||||
|
||||
export const Serie = t.Intersect([Resource(), SerieTranslation, BaseSerie]);
|
||||
export type Serie = typeof Serie.static;
|
||||
export type Serie = Prettify<typeof Serie.static>;
|
||||
|
||||
export const SeedSerie = t.Intersect([
|
||||
t.Omit(BaseSerie, ["createdAt", "nextRefresh"]),
|
||||
@ -77,6 +79,7 @@ export const SeedSerie = t.Intersect([
|
||||
seasons: t.Array(SeedSeason),
|
||||
entries: t.Array(SeedEntry),
|
||||
extras: t.Optional(t.Array(SeedExtra)),
|
||||
collection: t.Optional(SeedCollection),
|
||||
}),
|
||||
]);
|
||||
export type SeedSerie = typeof SeedSerie.static;
|
||||
|
24
api/tests/collection/seed-collection.test.ts
Normal file
24
api/tests/collection/seed-collection.test.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { beforeAll, describe, expect, it } from "bun:test";
|
||||
import { createMovie } from "tests/helpers";
|
||||
import { expectStatus } from "tests/utils";
|
||||
import { db } from "~/db";
|
||||
import { shows } from "~/db/schema";
|
||||
import { dune } from "~/models/examples/dune-2021";
|
||||
import { duneCollection } from "~/models/examples/dune-collection";
|
||||
|
||||
beforeAll(async () => {
|
||||
await db.delete(shows);
|
||||
});
|
||||
|
||||
describe("Collection seeding", () => {
|
||||
it("Can create a movie with a collection", async () => {
|
||||
const [resp, body] = await createMovie({
|
||||
...dune,
|
||||
collection: duneCollection,
|
||||
});
|
||||
expectStatus(resp, body).toBe(201);
|
||||
expect(body.id).toBeString();
|
||||
expect(body.slug).toBe("dune");
|
||||
expect(body.collection.slug).toBe("dune-collection");
|
||||
});
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user