mirror of
				https://github.com/zoriya/Kyoo.git
				synced 2025-10-31 10:37:13 -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 | erDiagram | ||||||
|     shows { |     shows { | ||||||
|         guid id PK |         guid id PK | ||||||
|         kind kind "serie|movie" |         kind kind "serie|movie|collection" | ||||||
|         string(128) slug UK |         string(128) slug UK | ||||||
|         genre[] genres |         genre[] genres | ||||||
|         int rating "From 0 to 100" |         int rating "From 0 to 100" | ||||||
| @ -20,6 +20,7 @@ erDiagram | |||||||
|         jsonb external_id |         jsonb external_id | ||||||
|         guid studio_id FK |         guid studio_id FK | ||||||
|         string original_language |         string original_language | ||||||
|  | 		guid collection_id FK | ||||||
|     } |     } | ||||||
|     show_translations { |     show_translations { | ||||||
|         guid id PK, FK |         guid id PK, FK | ||||||
| @ -37,6 +38,7 @@ erDiagram | |||||||
|     } |     } | ||||||
|     shows ||--|{ show_translations : has |     shows ||--|{ show_translations : has | ||||||
|     shows |o--|| entries : has |     shows |o--|| entries : has | ||||||
|  |     shows |o--|| shows : has_collection | ||||||
| 
 | 
 | ||||||
|     entries { |     entries { | ||||||
|         guid id PK |         guid id PK | ||||||
| @ -70,23 +72,6 @@ erDiagram | |||||||
|     } |     } | ||||||
|     video }|--|{ entries : for |     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 { |     seasons { | ||||||
|         guid id PK |         guid id PK | ||||||
|         string(256) slug UK |         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, | 			"when": 1738064522937, | ||||||
| 			"tag": "0008_entries", | 			"tag": "0008_entries", | ||||||
| 			"breakpoints": true | 			"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 { type SQL, and, eq, exists, sql } from "drizzle-orm"; | ||||||
| import { Elysia, t } from "elysia"; | import { Elysia, t } from "elysia"; | ||||||
|  | import { db } from "~/db"; | ||||||
| import { entries, entryVideoJoin, showTranslations, shows } from "~/db/schema"; | import { entries, entryVideoJoin, showTranslations, shows } from "~/db/schema"; | ||||||
| import { getColumns, sqlarr } from "~/db/utils"; | import { getColumns, sqlarr } from "~/db/utils"; | ||||||
| import { KError } from "~/models/error"; | import { KError } from "~/models/error"; | ||||||
| @ -25,7 +26,6 @@ import { | |||||||
| 	sortToSql, | 	sortToSql, | ||||||
| } from "~/models/utils"; | } from "~/models/utils"; | ||||||
| import { desc } from "~/models/utils/descriptions"; | import { desc } from "~/models/utils/descriptions"; | ||||||
| import { db } from "../db"; |  | ||||||
| 
 | 
 | ||||||
| const movieFilters: FilterDef = { | const movieFilters: FilterDef = { | ||||||
| 	genres: { | 	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 { db } from "~/db"; | ||||||
| import { showTranslations, shows } from "~/db/schema"; | import { showTranslations, shows } from "~/db/schema"; | ||||||
| import { conflictUpdateAllExcept } from "~/db/utils"; | import { conflictUpdateAllExcept } from "~/db/utils"; | ||||||
|  | import type { SeedCollection } from "~/models/collections"; | ||||||
| import type { SeedMovie } from "~/models/movie"; | import type { SeedMovie } from "~/models/movie"; | ||||||
| import type { SeedSerie } from "~/models/serie"; | import type { SeedSerie } from "~/models/serie"; | ||||||
| import { getYear } from "~/utils"; | import { getYear } from "~/utils"; | ||||||
| @ -12,7 +13,10 @@ type ShowTrans = typeof showTranslations.$inferInsert; | |||||||
| 
 | 
 | ||||||
| export const insertShow = async ( | export const insertShow = async ( | ||||||
| 	show: Show, | 	show: Show, | ||||||
| 	translations: SeedMovie["translations"] | SeedSerie["translations"], | 	translations: | ||||||
|  | 		| SeedMovie["translations"] | ||||||
|  | 		| SeedSerie["translations"] | ||||||
|  | 		| SeedCollection["translations"], | ||||||
| ) => { | ) => { | ||||||
| 	return await db.transaction(async (tx) => { | 	return await db.transaction(async (tx) => { | ||||||
| 		const ret = await insertBaseShow(tx, show); | 		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.
 | 	// if at this point ret is still undefined, we could not reconciliate.
 | ||||||
| 	// simply bail and let the caller handle this.
 | 	// simply bail and let the caller handle this.
 | ||||||
| 	const [{ id }] = await db | 	const [{ pk, id }] = await db | ||||||
| 		.select({ id: shows.id }) | 		.select({ pk: shows.pk, id: shows.id }) | ||||||
| 		.from(shows) | 		.from(shows) | ||||||
| 		.where(eq(shows.slug, show.slug)) | 		.where(eq(shows.slug, show.slug)) | ||||||
| 		.limit(1); | 		.limit(1); | ||||||
| 	return { | 	return { | ||||||
| 		status: 409 as const, | 		status: 409 as const, | ||||||
|  | 		pk, | ||||||
| 		id, | 		id, | ||||||
| 		slug: show.slug, | 		slug: show.slug, | ||||||
| 	}; | 	}; | ||||||
|  | |||||||
| @ -1,6 +1,7 @@ | |||||||
| import { t } from "elysia"; | import { t } from "elysia"; | ||||||
| import type { SeedMovie } from "~/models/movie"; | import type { SeedMovie } from "~/models/movie"; | ||||||
| import { getYear } from "~/utils"; | import { getYear } from "~/utils"; | ||||||
|  | import { insertCollection } from "./insert/collection"; | ||||||
| import { insertEntries } from "./insert/entries"; | import { insertEntries } from "./insert/entries"; | ||||||
| import { insertShow } from "./insert/shows"; | import { insertShow } from "./insert/shows"; | ||||||
| import { guessNextRefresh } from "./refresh"; | import { guessNextRefresh } from "./refresh"; | ||||||
| @ -11,6 +12,12 @@ export const SeedMovieResponse = t.Object({ | |||||||
| 	videos: t.Array( | 	videos: t.Array( | ||||||
| 		t.Object({ slug: t.String({ format: "slug", examples: ["bubble-v2"] }) }), | 		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; | export type SeedMovieResponse = typeof SeedMovieResponse.static; | ||||||
| 
 | 
 | ||||||
| @ -31,14 +38,21 @@ export const seedMovie = async ( | |||||||
| 		seed.slug = `random-${getYear(seed.airDate)}`; | 		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 nextRefresh = guessNextRefresh(bMovie.airDate ?? new Date()); | ||||||
| 
 | 
 | ||||||
|  | 	const col = await insertCollection(collection, { | ||||||
|  | 		kind: "movie", | ||||||
|  | 		nextRefresh, | ||||||
|  | 		...seed, | ||||||
|  | 	}); | ||||||
|  | 
 | ||||||
| 	const show = await insertShow( | 	const show = await insertShow( | ||||||
| 		{ | 		{ | ||||||
| 			kind: "movie", | 			kind: "movie", | ||||||
| 			startAir: bMovie.airDate, | 			startAir: bMovie.airDate, | ||||||
| 			nextRefresh, | 			nextRefresh, | ||||||
|  | 			collectionPk: col?.pk, | ||||||
| 			...bMovie, | 			...bMovie, | ||||||
| 		}, | 		}, | ||||||
| 		translations, | 		translations, | ||||||
| @ -65,5 +79,6 @@ export const seedMovie = async ( | |||||||
| 		id: show.id, | 		id: show.id, | ||||||
| 		slug: show.slug, | 		slug: show.slug, | ||||||
| 		videos: entry.videos, | 		videos: entry.videos, | ||||||
|  | 		collection: col, | ||||||
| 	}; | 	}; | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -1,6 +1,7 @@ | |||||||
| import { t } from "elysia"; | import { t } from "elysia"; | ||||||
| import type { SeedSerie } from "~/models/serie"; | import type { SeedSerie } from "~/models/serie"; | ||||||
| import { getYear } from "~/utils"; | import { getYear } from "~/utils"; | ||||||
|  | import { insertCollection } from "./insert/collection"; | ||||||
| import { insertEntries } from "./insert/entries"; | import { insertEntries } from "./insert/entries"; | ||||||
| import { insertSeasons } from "./insert/seasons"; | import { insertSeasons } from "./insert/seasons"; | ||||||
| import { insertShow } from "./insert/shows"; | import { insertShow } from "./insert/shows"; | ||||||
| @ -35,6 +36,15 @@ export const SeedSerieResponse = t.Object({ | |||||||
| 			slug: t.String({ format: "slug", examples: ["made-in-abyss-s1e1"] }), | 			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; | export type SeedSerieResponse = typeof SeedSerieResponse.static; | ||||||
| 
 | 
 | ||||||
| @ -55,13 +65,20 @@ export const seedSerie = async ( | |||||||
| 		seed.slug = `random-${getYear(seed.startAir)}`; | 		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 nextRefresh = guessNextRefresh(serie.startAir ?? new Date()); | ||||||
| 
 | 
 | ||||||
|  | 	const col = await insertCollection(collection, { | ||||||
|  | 		kind: "serie", | ||||||
|  | 		nextRefresh, | ||||||
|  | 		...seed, | ||||||
|  | 	}); | ||||||
|  | 
 | ||||||
| 	const show = await insertShow( | 	const show = await insertShow( | ||||||
| 		{ | 		{ | ||||||
| 			kind: "serie", | 			kind: "serie", | ||||||
| 			nextRefresh, | 			nextRefresh, | ||||||
|  | 			collectionPk: col?.pk, | ||||||
| 			...serie, | 			...serie, | ||||||
| 		}, | 		}, | ||||||
| 		translations, | 		translations, | ||||||
| @ -82,5 +99,6 @@ export const seedSerie = async ( | |||||||
| 		seasons: retSeasons, | 		seasons: retSeasons, | ||||||
| 		entries: retEntries, | 		entries: retEntries, | ||||||
| 		extras: retExtras, | 		extras: retExtras, | ||||||
|  | 		collection: col, | ||||||
| 	}; | 	}; | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -1,5 +1,6 @@ | |||||||
| import { relations, sql } from "drizzle-orm"; | import { relations, sql } from "drizzle-orm"; | ||||||
| import { | import { | ||||||
|  | 	type AnyPgColumn, | ||||||
| 	check, | 	check, | ||||||
| 	date, | 	date, | ||||||
| 	index, | 	index, | ||||||
| @ -16,7 +17,11 @@ import { entries } from "./entries"; | |||||||
| import { seasons } from "./seasons"; | import { seasons } from "./seasons"; | ||||||
| import { image, language, schema } from "./utils"; | 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", [ | export const showStatus = schema.enum("show_status", [ | ||||||
| 	"unknown", | 	"unknown", | ||||||
| 	"finished", | 	"finished", | ||||||
| @ -78,6 +83,10 @@ export const shows = schema.table( | |||||||
| 		endAir: date(), | 		endAir: date(), | ||||||
| 		originalLanguage: language(), | 		originalLanguage: language(), | ||||||
| 
 | 
 | ||||||
|  | 		collectionPk: integer().references((): AnyPgColumn => shows.pk, { | ||||||
|  | 			onDelete: "set null", | ||||||
|  | 		}), | ||||||
|  | 
 | ||||||
| 		externalId: externalid(), | 		externalId: externalid(), | ||||||
| 
 | 
 | ||||||
| 		createdAt: timestamp({ withTimezone: true, mode: "string" }) | 		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 { SeedMovie } from "~/models/movie"; | ||||||
| import type { Video } from "../video"; | import type { Video } from "~/models/video"; | ||||||
| 
 | 
 | ||||||
| export const duneVideo: Video = { | export const duneVideo: Video = { | ||||||
| 	id: "c9a0d02e-6b8e-4ac1-b431-45b022ec0708", | 	id: "c9a0d02e-6b8e-4ac1-b431-45b022ec0708", | ||||||
| @ -38,8 +38,8 @@ export const dune: SeedMovie = { | |||||||
| 	originalLanguage: "en", | 	originalLanguage: "en", | ||||||
| 	externalId: { | 	externalId: { | ||||||
| 		themoviedatabase: { | 		themoviedatabase: { | ||||||
| 			dataId: "496243", | 			dataId: "438631", | ||||||
| 			link: "https://www.themoviedb.org/movie/496243", | 			link: "https://www.themoviedb.org/movie/438631-dune", | ||||||
| 		}, | 		}, | ||||||
| 		imdb: { | 		imdb: { | ||||||
| 			dataId: "tt1160419", | 			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 "./bubble"; | ||||||
| export * from "./made-in-abyss"; | 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 { t } from "elysia"; | ||||||
| import type { Prettify } from "~/utils"; | import type { Prettify } from "~/utils"; | ||||||
|  | import { SeedCollection } from "./collections"; | ||||||
| import { bubble, registerExamples } from "./examples"; | import { bubble, registerExamples } from "./examples"; | ||||||
| import { bubbleImages } from "./examples/bubble"; | import { bubbleImages } from "./examples/bubble"; | ||||||
| import { | import { | ||||||
| @ -85,6 +86,7 @@ export const SeedMovie = t.Intersect([ | |||||||
| 			]), | 			]), | ||||||
| 		), | 		), | ||||||
| 		videos: t.Optional(t.Array(t.String({ format: "uuid" }))), | 		videos: t.Optional(t.Array(t.String({ format: "uuid" }))), | ||||||
|  | 		collection: t.Optional(SeedCollection), | ||||||
| 	}), | 	}), | ||||||
| ]); | ]); | ||||||
| export type SeedMovie = Prettify<typeof SeedMovie.static>; | export type SeedMovie = Prettify<typeof SeedMovie.static>; | ||||||
|  | |||||||
| @ -1,4 +1,6 @@ | |||||||
| import { t } from "elysia"; | import { t } from "elysia"; | ||||||
|  | import type { Prettify } from "~/utils"; | ||||||
|  | import { SeedCollection } from "./collections"; | ||||||
| import { SeedEntry, SeedExtra } from "./entry"; | import { SeedEntry, SeedExtra } from "./entry"; | ||||||
| import { bubbleImages, madeInAbyss, registerExamples } from "./examples"; | import { bubbleImages, madeInAbyss, registerExamples } from "./examples"; | ||||||
| import { SeedSeason } from "./season"; | import { SeedSeason } from "./season"; | ||||||
| @ -57,7 +59,7 @@ export const SerieTranslation = t.Object({ | |||||||
| export type SerieTranslation = typeof SerieTranslation.static; | export type SerieTranslation = typeof SerieTranslation.static; | ||||||
| 
 | 
 | ||||||
| export const Serie = t.Intersect([Resource(), SerieTranslation, BaseSerie]); | 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([ | export const SeedSerie = t.Intersect([ | ||||||
| 	t.Omit(BaseSerie, ["createdAt", "nextRefresh"]), | 	t.Omit(BaseSerie, ["createdAt", "nextRefresh"]), | ||||||
| @ -77,6 +79,7 @@ export const SeedSerie = t.Intersect([ | |||||||
| 		seasons: t.Array(SeedSeason), | 		seasons: t.Array(SeedSeason), | ||||||
| 		entries: t.Array(SeedEntry), | 		entries: t.Array(SeedEntry), | ||||||
| 		extras: t.Optional(t.Array(SeedExtra)), | 		extras: t.Optional(t.Array(SeedExtra)), | ||||||
|  | 		collection: t.Optional(SeedCollection), | ||||||
| 	}), | 	}), | ||||||
| ]); | ]); | ||||||
| export type SeedSerie = typeof SeedSerie.static; | 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