Compare commits
1 Commits
main
...
a6200605f8
| Author | SHA1 | Date | |
|---|---|---|---|
| a6200605f8 |
@ -28,11 +28,10 @@ Table medias {
|
||||
deletedAt DateTime
|
||||
createdAt DateTime [default: `now()`, not null]
|
||||
updatedAt DateTime [default: `now()`, not null]
|
||||
bannerPromotion hero_banner [not null]
|
||||
logs media_logs [not null]
|
||||
episodes episodes [not null]
|
||||
collections collections [not null]
|
||||
reviews movie_reviews [not null]
|
||||
inCollections CollectionMedia [not null]
|
||||
}
|
||||
|
||||
Table media_logs {
|
||||
@ -369,7 +368,7 @@ Table user_logs {
|
||||
Table collections {
|
||||
id String [pk]
|
||||
name String [not null]
|
||||
slug String [not null]
|
||||
medias medias [not null]
|
||||
owner users [not null]
|
||||
ownerId String [not null]
|
||||
accessStatus AccessStatus [not null, default: 'private']
|
||||
@ -379,24 +378,6 @@ Table collections {
|
||||
deletedAt DateTime
|
||||
createdAt DateTime [default: `now()`, not null]
|
||||
updatedAt DateTime [default: `now()`, not null]
|
||||
media_saved CollectionMedia [not null]
|
||||
|
||||
indexes {
|
||||
(slug, ownerId) [unique]
|
||||
}
|
||||
}
|
||||
|
||||
Table CollectionMedia {
|
||||
id String [pk]
|
||||
collection collections [not null]
|
||||
collectionId String [not null]
|
||||
media medias [not null]
|
||||
mediaId String [not null]
|
||||
savedAt DateTime [default: `now()`, not null]
|
||||
|
||||
indexes {
|
||||
(collectionId, mediaId) [unique]
|
||||
}
|
||||
}
|
||||
|
||||
Table watch_histories {
|
||||
@ -515,8 +496,12 @@ Table email_system_histories {
|
||||
Table hero_banner {
|
||||
id String [pk]
|
||||
orderPriority Int [unique]
|
||||
mediaId String [not null]
|
||||
media medias [not null]
|
||||
isClickable Boolean [not null, default: false]
|
||||
title String
|
||||
tags String[] [not null]
|
||||
description String
|
||||
buttonContent String
|
||||
buttonLink String
|
||||
imageUrl String
|
||||
startDate DateTime [not null]
|
||||
endDate DateTime [not null]
|
||||
@ -575,9 +560,9 @@ Table MediaCharacters {
|
||||
mediasId String [ref: > medias.id]
|
||||
}
|
||||
|
||||
Table CollectionMedia {
|
||||
incollectionsId String [ref: > CollectionMedia.id]
|
||||
media_savedId String [ref: > CollectionMedia.id]
|
||||
Table MediaCollections {
|
||||
collectionsId String [ref: > collections.id]
|
||||
mediasId String [ref: > medias.id]
|
||||
}
|
||||
|
||||
Table UserFavoriteGenres {
|
||||
@ -765,10 +750,6 @@ Ref: user_logs.sessionId > user_sessions.id
|
||||
|
||||
Ref: collections.ownerId > users.id
|
||||
|
||||
Ref: CollectionMedia.collectionId > collections.id
|
||||
|
||||
Ref: CollectionMedia.mediaId > medias.id
|
||||
|
||||
Ref: watch_histories.id > episodes.id
|
||||
|
||||
Ref: watch_histories.userId > users.id
|
||||
@ -799,8 +780,6 @@ Ref: email_system_accounts.createdBy > users.id
|
||||
|
||||
Ref: email_system_histories.userRelated > users.id
|
||||
|
||||
Ref: hero_banner.mediaId > medias.id
|
||||
|
||||
Ref: hero_banner.creatorId > users.id
|
||||
|
||||
Ref: system_notifications.createdBy > users.id
|
||||
|
||||
@ -7,9 +7,6 @@ CREATE TYPE "MediaType" AS ENUM ('TV', 'ONA', 'OVA', 'Movie', 'Special', 'Music'
|
||||
-- CreateEnum
|
||||
CREATE TYPE "Country" AS ENUM ('Japanese', 'English', 'Indonesia', 'Korea');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "Season" AS ENUM ('Winter', 'Spring', 'Summer', 'Fall');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "CharacterRole" AS ENUM ('Main', 'Supporting');
|
||||
|
||||
@ -75,8 +72,6 @@ CREATE TABLE "medias" (
|
||||
"deletedAt" TIMESTAMP(3),
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"season" "Season",
|
||||
"yearReleased" SMALLINT NOT NULL,
|
||||
|
||||
CONSTRAINT "medias_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
@ -211,8 +206,7 @@ CREATE TABLE "videos" (
|
||||
"id" UUID NOT NULL,
|
||||
"episodeId" UUID NOT NULL,
|
||||
"serviceId" UUID NOT NULL,
|
||||
"videoCode" VARCHAR(255) NOT NULL,
|
||||
"thumbnailCode" TEXT,
|
||||
"code" VARCHAR(255) NOT NULL,
|
||||
"pendingUpload" BOOLEAN NOT NULL DEFAULT true,
|
||||
"uploadedBy" UUID NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3),
|
||||
@ -372,7 +366,7 @@ CREATE TABLE "user_logs" (
|
||||
-- CreateTable
|
||||
CREATE TABLE "collections" (
|
||||
"id" UUID NOT NULL,
|
||||
"name" VARCHAR(115) NOT NULL,
|
||||
"name" VARCHAR(255) NOT NULL,
|
||||
"ownerId" UUID NOT NULL,
|
||||
"accessStatus" "AccessStatus" NOT NULL DEFAULT 'private',
|
||||
"password" VARCHAR(255),
|
||||
@ -380,21 +374,10 @@ CREATE TABLE "collections" (
|
||||
"deletedAt" TIMESTAMP(3),
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"slug" VARCHAR(115) NOT NULL,
|
||||
|
||||
CONSTRAINT "collections_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "CollectionMedia" (
|
||||
"id" UUID NOT NULL,
|
||||
"collectionId" UUID NOT NULL,
|
||||
"mediaId" UUID NOT NULL,
|
||||
"savedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "CollectionMedia_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "watch_histories" (
|
||||
"id" UUID NOT NULL,
|
||||
@ -514,21 +497,6 @@ CREATE TABLE "email_system_histories" (
|
||||
CONSTRAINT "email_system_histories_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "hero_banner" (
|
||||
"id" UUID NOT NULL,
|
||||
"orderPriority" INTEGER,
|
||||
"imageUrl" TEXT,
|
||||
"startDate" TIMESTAMP(3) NOT NULL,
|
||||
"endDate" TIMESTAMP(3) NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"creatorId" UUID NOT NULL,
|
||||
"mediaId" UUID NOT NULL,
|
||||
|
||||
CONSTRAINT "hero_banner_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "system_preferences" (
|
||||
"id" UUID NOT NULL,
|
||||
@ -602,6 +570,14 @@ CREATE TABLE "_MediaCharacters" (
|
||||
CONSTRAINT "_MediaCharacters_AB_pkey" PRIMARY KEY ("A","B")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "_MediaCollections" (
|
||||
"A" UUID NOT NULL,
|
||||
"B" UUID NOT NULL,
|
||||
|
||||
CONSTRAINT "_MediaCollections_AB_pkey" PRIMARY KEY ("A","B")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "_UserSelectedSharingCollention" (
|
||||
"A" UUID NOT NULL,
|
||||
@ -653,7 +629,7 @@ CREATE UNIQUE INDEX "lang_va_char_language_vaId_charId_key" ON "lang_va_char"("l
|
||||
CREATE UNIQUE INDEX "episodes_mediaId_episode_key" ON "episodes"("mediaId", "episode");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "videos_serviceId_videoCode_key" ON "videos"("serviceId", "videoCode");
|
||||
CREATE UNIQUE INDEX "videos_serviceId_code_key" ON "videos"("serviceId", "code");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "video_services_name_key" ON "video_services"("name");
|
||||
@ -676,12 +652,6 @@ CREATE UNIQUE INDEX "user_roles_name_key" ON "user_roles"("name");
|
||||
-- CreateIndex
|
||||
CREATE INDEX "user_sessions_userId_isAuthenticated_deletedAt_idx" ON "user_sessions"("userId", "isAuthenticated", "deletedAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "collections_slug_ownerId_key" ON "collections"("slug", "ownerId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "CollectionMedia_collectionId_mediaId_key" ON "CollectionMedia"("collectionId", "mediaId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "languages_code_key" ON "languages"("code");
|
||||
|
||||
@ -694,12 +664,6 @@ CREATE UNIQUE INDEX "email_system_accounts_email_key" ON "email_system_accounts"
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "email_system_accounts_username_key" ON "email_system_accounts"("username");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "hero_banner_orderPriority_key" ON "hero_banner"("orderPriority");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "system_preferences_key_key" ON "system_preferences"("key");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "_MediaStudios_B_index" ON "_MediaStudios"("B");
|
||||
|
||||
@ -712,21 +676,24 @@ CREATE INDEX "_UserFavoriteGenres_B_index" ON "_UserFavoriteGenres"("B");
|
||||
-- CreateIndex
|
||||
CREATE INDEX "_MediaCharacters_B_index" ON "_MediaCharacters"("B");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "_MediaCollections_B_index" ON "_MediaCollections"("B");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "_UserSelectedSharingCollention_B_index" ON "_UserSelectedSharingCollention"("B");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "medias" ADD CONSTRAINT "medias_uploadedBy_fkey" FOREIGN KEY ("uploadedBy") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "media_logs" ADD CONSTRAINT "media_logs_proposedBy_fkey" FOREIGN KEY ("proposedBy") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "media_logs" ADD CONSTRAINT "media_logs_approvedBy_fkey" FOREIGN KEY ("approvedBy") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "media_logs" ADD CONSTRAINT "media_logs_mediaId_fkey" FOREIGN KEY ("mediaId") REFERENCES "medias"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "media_logs" ADD CONSTRAINT "media_logs_proposedBy_fkey" FOREIGN KEY ("proposedBy") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "genres" ADD CONSTRAINT "genres_createdBy_fkey" FOREIGN KEY ("createdBy") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
@ -739,15 +706,15 @@ ALTER TABLE "characters" ADD CONSTRAINT "characters_creatorId_fkey" FOREIGN KEY
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "voice_actors" ADD CONSTRAINT "voice_actors_creatorId_fkey" FOREIGN KEY ("creatorId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "lang_va_char" ADD CONSTRAINT "lang_va_char_vaId_fkey" FOREIGN KEY ("vaId") REFERENCES "voice_actors"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "lang_va_char" ADD CONSTRAINT "lang_va_char_charId_fkey" FOREIGN KEY ("charId") REFERENCES "characters"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "lang_va_char" ADD CONSTRAINT "lang_va_char_creatorId_fkey" FOREIGN KEY ("creatorId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "lang_va_char" ADD CONSTRAINT "lang_va_char_vaId_fkey" FOREIGN KEY ("vaId") REFERENCES "voice_actors"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "episodes" ADD CONSTRAINT "episodes_mediaId_fkey" FOREIGN KEY ("mediaId") REFERENCES "medias"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
@ -755,13 +722,13 @@ ALTER TABLE "episodes" ADD CONSTRAINT "episodes_mediaId_fkey" FOREIGN KEY ("medi
|
||||
ALTER TABLE "episodes" ADD CONSTRAINT "episodes_uploadedBy_fkey" FOREIGN KEY ("uploadedBy") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "episode_likes" ADD CONSTRAINT "episode_likes_episodeId_fkey" FOREIGN KEY ("episodeId") REFERENCES "episodes"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
ALTER TABLE "episode_likes" ADD CONSTRAINT "episode_likes_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "episode_likes" ADD CONSTRAINT "episode_likes_sessionId_fkey" FOREIGN KEY ("sessionId") REFERENCES "user_sessions"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "episode_likes" ADD CONSTRAINT "episode_likes_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
ALTER TABLE "episode_likes" ADD CONSTRAINT "episode_likes_episodeId_fkey" FOREIGN KEY ("episodeId") REFERENCES "episodes"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "videos" ADD CONSTRAINT "videos_episodeId_fkey" FOREIGN KEY ("episodeId") REFERENCES "episodes"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
@ -775,23 +742,23 @@ ALTER TABLE "videos" ADD CONSTRAINT "videos_uploadedBy_fkey" FOREIGN KEY ("uploa
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "video_services" ADD CONSTRAINT "video_services_createdBy_fkey" FOREIGN KEY ("createdBy") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "user_preferences" ADD CONSTRAINT "user_preferences_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "user_preferences" ADD CONSTRAINT "user_preferences_langPreference_fkey" FOREIGN KEY ("langPreference") REFERENCES "languages"("code") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "user_preferences" ADD CONSTRAINT "user_preferences_serviceDefaultId_fkey" FOREIGN KEY ("serviceDefaultId") REFERENCES "video_services"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "user_preferences" ADD CONSTRAINT "user_preferences_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "user_roles" ADD CONSTRAINT "user_roles_createdBy_fkey" FOREIGN KEY ("createdBy") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "user_role_assignments" ADD CONSTRAINT "user_role_assignments_roleId_fkey" FOREIGN KEY ("roleId") REFERENCES "user_roles"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
ALTER TABLE "user_role_assignments" ADD CONSTRAINT "user_role_assignments_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "user_role_assignments" ADD CONSTRAINT "user_role_assignments_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
ALTER TABLE "user_role_assignments" ADD CONSTRAINT "user_role_assignments_roleId_fkey" FOREIGN KEY ("roleId") REFERENCES "user_roles"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "user_notifications" ADD CONSTRAINT "user_notifications_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
@ -800,35 +767,29 @@ ALTER TABLE "user_notifications" ADD CONSTRAINT "user_notifications_userId_fkey"
|
||||
ALTER TABLE "user_sessions" ADD CONSTRAINT "user_sessions_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "user_logs" ADD CONSTRAINT "user_logs_sessionId_fkey" FOREIGN KEY ("sessionId") REFERENCES "user_sessions"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
ALTER TABLE "user_logs" ADD CONSTRAINT "user_logs_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "user_logs" ADD CONSTRAINT "user_logs_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
ALTER TABLE "user_logs" ADD CONSTRAINT "user_logs_sessionId_fkey" FOREIGN KEY ("sessionId") REFERENCES "user_sessions"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "collections" ADD CONSTRAINT "collections_ownerId_fkey" FOREIGN KEY ("ownerId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "CollectionMedia" ADD CONSTRAINT "CollectionMedia_collectionId_fkey" FOREIGN KEY ("collectionId") REFERENCES "collections"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "CollectionMedia" ADD CONSTRAINT "CollectionMedia_mediaId_fkey" FOREIGN KEY ("mediaId") REFERENCES "medias"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "watch_histories" ADD CONSTRAINT "watch_histories_id_fkey" FOREIGN KEY ("id") REFERENCES "episodes"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "watch_histories" ADD CONSTRAINT "watch_histories_sessionId_fkey" FOREIGN KEY ("sessionId") REFERENCES "user_sessions"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "watch_histories" ADD CONSTRAINT "watch_histories_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "movie_reviews" ADD CONSTRAINT "movie_reviews_createdBy_fkey" FOREIGN KEY ("createdBy") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
ALTER TABLE "watch_histories" ADD CONSTRAINT "watch_histories_sessionId_fkey" FOREIGN KEY ("sessionId") REFERENCES "user_sessions"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "movie_reviews" ADD CONSTRAINT "movie_reviews_mediaId_fkey" FOREIGN KEY ("mediaId") REFERENCES "medias"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "movie_reviews" ADD CONSTRAINT "movie_reviews_createdBy_fkey" FOREIGN KEY ("createdBy") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "comments" ADD CONSTRAINT "comments_episodeId_fkey" FOREIGN KEY ("episodeId") REFERENCES "episodes"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
@ -845,10 +806,10 @@ ALTER TABLE "comment_likes" ADD CONSTRAINT "comment_likes_commentId_fkey" FOREIG
|
||||
ALTER TABLE "comment_likes" ADD CONSTRAINT "comment_likes_userLiked_fkey" FOREIGN KEY ("userLiked") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "comment_reports" ADD CONSTRAINT "comment_reports_approvedBy_fkey" FOREIGN KEY ("approvedBy") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
ALTER TABLE "comment_reports" ADD CONSTRAINT "comment_reports_userReporter_fkey" FOREIGN KEY ("userReporter") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "comment_reports" ADD CONSTRAINT "comment_reports_userReporter_fkey" FOREIGN KEY ("userReporter") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
ALTER TABLE "comment_reports" ADD CONSTRAINT "comment_reports_approvedBy_fkey" FOREIGN KEY ("approvedBy") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "languages" ADD CONSTRAINT "languages_craetedBy_fkey" FOREIGN KEY ("craetedBy") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
@ -859,12 +820,6 @@ ALTER TABLE "email_system_accounts" ADD CONSTRAINT "email_system_accounts_create
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "email_system_histories" ADD CONSTRAINT "email_system_histories_userRelated_fkey" FOREIGN KEY ("userRelated") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "hero_banner" ADD CONSTRAINT "hero_banner_creatorId_fkey" FOREIGN KEY ("creatorId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "hero_banner" ADD CONSTRAINT "hero_banner_mediaId_fkey" FOREIGN KEY ("mediaId") REFERENCES "medias"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "system_notifications" ADD CONSTRAINT "system_notifications_createdBy_fkey" FOREIGN KEY ("createdBy") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
@ -895,6 +850,12 @@ ALTER TABLE "_MediaCharacters" ADD CONSTRAINT "_MediaCharacters_A_fkey" FOREIGN
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_MediaCharacters" ADD CONSTRAINT "_MediaCharacters_B_fkey" FOREIGN KEY ("B") REFERENCES "medias"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_MediaCollections" ADD CONSTRAINT "_MediaCollections_A_fkey" FOREIGN KEY ("A") REFERENCES "collections"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_MediaCollections" ADD CONSTRAINT "_MediaCollections_B_fkey" FOREIGN KEY ("B") REFERENCES "medias"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_UserSelectedSharingCollention" ADD CONSTRAINT "_UserSelectedSharingCollention_A_fkey" FOREIGN KEY ("A") REFERENCES "collections"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
@ -0,0 +1,17 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `code` on the `videos` table. All the data in the column will be lost.
|
||||
- A unique constraint covering the columns `[serviceId,videoCode]` on the table `videos` will be added. If there are existing duplicate values, this will fail.
|
||||
- Added the required column `videoCode` to the `videos` table without a default value. This is not possible if the table is not empty.
|
||||
|
||||
*/
|
||||
-- DropIndex
|
||||
DROP INDEX "videos_serviceId_code_key";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "videos" RENAME COLUMN "code" TO "videoCode";
|
||||
|
||||
-- CreateIndex
|
||||
DROP INDEX IF EXISTS "videos_serviceId_code_key";
|
||||
CREATE UNIQUE INDEX "videos_serviceId_videoCode_key" ON "videos"("serviceId", "videoCode");
|
||||
@ -0,0 +1,2 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "videos" ADD COLUMN "thumbnailCode" TEXT;
|
||||
@ -0,0 +1,20 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "HeroBanner" (
|
||||
"id" UUID NOT NULL,
|
||||
"isClickable" BOOLEAN NOT NULL DEFAULT false,
|
||||
"title" VARCHAR(225),
|
||||
"description" TEXT,
|
||||
"buttonContent" VARCHAR(100),
|
||||
"buttonLink" TEXT,
|
||||
"imageUrl" TEXT,
|
||||
"startDate" TIMESTAMP(3) NOT NULL,
|
||||
"endDate" TIMESTAMP(3) NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"creatorId" UUID NOT NULL,
|
||||
|
||||
CONSTRAINT "HeroBanner_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "HeroBanner" ADD CONSTRAINT "HeroBanner_creatorId_fkey" FOREIGN KEY ("creatorId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
@ -0,0 +1,32 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the `HeroBanner` table. If the table is not empty, all the data it contains will be lost.
|
||||
|
||||
*/
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "HeroBanner" DROP CONSTRAINT "HeroBanner_creatorId_fkey";
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "HeroBanner";
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "hero_banner" (
|
||||
"id" UUID NOT NULL,
|
||||
"isClickable" BOOLEAN NOT NULL DEFAULT false,
|
||||
"title" VARCHAR(225),
|
||||
"description" TEXT,
|
||||
"buttonContent" VARCHAR(100),
|
||||
"buttonLink" TEXT,
|
||||
"imageUrl" TEXT,
|
||||
"startDate" TIMESTAMP(3) NOT NULL,
|
||||
"endDate" TIMESTAMP(3) NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"creatorId" UUID NOT NULL,
|
||||
|
||||
CONSTRAINT "hero_banner_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "hero_banner" ADD CONSTRAINT "hero_banner_creatorId_fkey" FOREIGN KEY ("creatorId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
@ -0,0 +1,11 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- A unique constraint covering the columns `[order]` on the table `hero_banner` will be added. If there are existing duplicate values, this will fail.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "hero_banner" ADD COLUMN "order" INTEGER;
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "hero_banner_order_key" ON "hero_banner"("order");
|
||||
@ -0,0 +1,16 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `order` on the `hero_banner` table. All the data in the column will be lost.
|
||||
- A unique constraint covering the columns `[orderPriority]` on the table `hero_banner` will be added. If there are existing duplicate values, this will fail.
|
||||
|
||||
*/
|
||||
-- DropIndex
|
||||
DROP INDEX "hero_banner_order_key";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "hero_banner" DROP COLUMN "order",
|
||||
ADD COLUMN "orderPriority" INTEGER;
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "hero_banner_orderPriority_key" ON "hero_banner"("orderPriority");
|
||||
@ -0,0 +1,2 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "hero_banner" ADD COLUMN "tags" TEXT[];
|
||||
@ -0,0 +1,8 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- A unique constraint covering the columns `[key]` on the table `system_preferences` will be added. If there are existing duplicate values, this will fail.
|
||||
|
||||
*/
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "system_preferences_key_key" ON "system_preferences"("key");
|
||||
@ -1,14 +0,0 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- The values [Winter,Spring,Summer,Fall] on the enum `Season` will be removed. If these variants are still used in the database, this will fail.
|
||||
|
||||
*/
|
||||
-- AlterEnum
|
||||
BEGIN;
|
||||
CREATE TYPE "Season_new" AS ENUM ('winter', 'spring', 'summer', 'fall');
|
||||
ALTER TABLE "medias" ALTER COLUMN "season" TYPE "Season_new" USING ("season"::text::"Season_new");
|
||||
ALTER TYPE "Season" RENAME TO "Season_old";
|
||||
ALTER TYPE "Season_new" RENAME TO "Season";
|
||||
DROP TYPE "public"."Season_old";
|
||||
COMMIT;
|
||||
@ -1,48 +1,58 @@
|
||||
// This is your Prisma schema file,
|
||||
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
||||
|
||||
// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
|
||||
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
|
||||
|
||||
|
||||
//// Prisma Configuration ////
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
}
|
||||
|
||||
generator dbml {
|
||||
provider = "prisma-dbml-generator"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
}
|
||||
|
||||
|
||||
//// Prisma Model ////
|
||||
|
||||
model Media {
|
||||
id String @id @db.Uuid
|
||||
title String
|
||||
title String @db.Text
|
||||
titleAlternative Json
|
||||
slug String @unique
|
||||
slug String @db.Text @unique
|
||||
malId Int? @unique
|
||||
pictureMedium String
|
||||
pictureLarge String
|
||||
pictureMedium String @db.Text
|
||||
pictureLarge String @db.Text
|
||||
genres Genre[] @relation("MediaGenres")
|
||||
country Country @default(JP)
|
||||
score Decimal @default(0.00) @db.Decimal(4, 2)
|
||||
score Decimal @db.Decimal(4, 2) @default(0.00)
|
||||
status String
|
||||
startAiring DateTime?
|
||||
endAiring DateTime?
|
||||
synopsis String
|
||||
synopsis String @db.Text
|
||||
ageRating String
|
||||
mediaType MediaType
|
||||
source String?
|
||||
studios Studio[] @relation("MediaStudios")
|
||||
characters Character[] @relation("MediaCharacters")
|
||||
onDraft Boolean @default(true)
|
||||
season Season?
|
||||
yearReleased Int @db.SmallInt
|
||||
uploader User @relation("UserUploadedMedias", fields: [uploadedBy], references: [id])
|
||||
uploadedBy String @db.Uuid
|
||||
deletedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
inCollections CollectionMedia[] @relation("CollectionMedia")
|
||||
episodes Episode[] @relation("MediaEpisodes")
|
||||
bannerPromotion HeroBanner[] @relation("MediaBannerPromotion")
|
||||
|
||||
logs MediaLog[] @relation("MediaLogs")
|
||||
uploader User @relation("UserUploadedMedias", fields: [uploadedBy], references: [id])
|
||||
episodes Episode[] @relation("MediaEpisodes")
|
||||
collections Collection[] @relation("MediaCollections")
|
||||
reviews MediaReview[] @relation("MediaReviews")
|
||||
characters Character[] @relation("MediaCharacters")
|
||||
genres Genre[] @relation("MediaGenres")
|
||||
studios Studio[] @relation("MediaStudios")
|
||||
|
||||
@@index([status, onDraft, deletedAt])
|
||||
@@index([mediaType])
|
||||
@ -55,29 +65,29 @@ model MediaLog {
|
||||
id String @id @db.Uuid
|
||||
status MediaOperation
|
||||
approval Boolean @default(false)
|
||||
proposer User @relation("UserProposedMedias", fields: [proposedBy], references: [id])
|
||||
proposedBy String @db.Uuid
|
||||
approver User @relation("UserApprovedMedias", fields: [approvedBy], references: [id])
|
||||
approvedBy String @db.Uuid
|
||||
media Media @relation("MediaLogs", fields: [mediaId], references: [id])
|
||||
mediaId String @db.Uuid
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
approver User @relation("UserApprovedMedias", fields: [approvedBy], references: [id])
|
||||
media Media @relation("MediaLogs", fields: [mediaId], references: [id])
|
||||
proposer User @relation("UserProposedMedias", fields: [proposedBy], references: [id])
|
||||
|
||||
@@map("media_logs")
|
||||
}
|
||||
|
||||
model Genre {
|
||||
id String @id @db.Uuid
|
||||
name String @db.VarChar(255)
|
||||
slug String @unique @db.VarChar(255)
|
||||
slug String @db.VarChar(255) @unique
|
||||
malId Int @unique
|
||||
malUrl String @db.VarChar(255)
|
||||
creator User @relation("UserCreatedGenres", fields: [createdBy], references: [id])
|
||||
createdBy String @db.Uuid
|
||||
deletedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
creator User @relation("UserCreatedGenres", fields: [createdBy], references: [id])
|
||||
|
||||
medias Media[] @relation("MediaGenres")
|
||||
user_favourite_genres UserPreference[] @relation("UserFavoriteGenres")
|
||||
|
||||
@ -87,36 +97,36 @@ model Genre {
|
||||
model Studio {
|
||||
id String @id @db.Uuid
|
||||
name String @db.VarChar(255)
|
||||
slug String @unique @db.VarChar(255)
|
||||
linkAbout String
|
||||
slug String @db.VarChar(255) @unique
|
||||
linkAbout String @db.Text
|
||||
malId Int @unique
|
||||
logoUrl String?
|
||||
logoUrl String? @db.Text
|
||||
creator User @relation("UserCreatedStudios", fields: [createdBy], references: [id])
|
||||
createdBy String @db.Uuid
|
||||
deletedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
creator User @relation("UserCreatedStudios", fields: [createdBy], references: [id])
|
||||
medias Media[] @relation("MediaStudios")
|
||||
|
||||
medias Media[] @relation("MediaStudios")
|
||||
@@map("studios")
|
||||
}
|
||||
|
||||
model Character {
|
||||
id String @id @db.Uuid
|
||||
id String @id@db.Uuid
|
||||
malId Int @unique
|
||||
name String
|
||||
role CharacterRole
|
||||
favorites Int @default(0)
|
||||
imageUrl String?
|
||||
smallImageUrl String?
|
||||
createdBy User @relation("UserCreatedCharacters", fields: [creatorId], references: [id])
|
||||
creatorId String @db.Uuid
|
||||
deletedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
createdBy User @relation("UserCreatedCharacters", fields: [creatorId], references: [id])
|
||||
voice_actors LangVAChar[] @relation("CharVALanguage")
|
||||
medias Media[] @relation("MediaCharacters")
|
||||
|
||||
medias Media[] @relation("MediaCharacters")
|
||||
voice_actors LangVAChar[] @relation("CharVALanguage")
|
||||
@@map("characters")
|
||||
}
|
||||
|
||||
@ -125,31 +135,31 @@ model VoiceActor {
|
||||
malId Int @unique
|
||||
name String
|
||||
birthday DateTime?
|
||||
description String?
|
||||
description String? @db.Text
|
||||
aboutUrl String?
|
||||
imageUrl String?
|
||||
websiteUrl String?
|
||||
createdBy User @relation("UserCreatedVoiceActors", fields: [creatorId], references: [id])
|
||||
creatorId String @db.Uuid
|
||||
deletedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
characters LangVAChar[] @relation("VACharLanguage")
|
||||
createdBy User @relation("UserCreatedVoiceActors", fields: [creatorId], references: [id])
|
||||
|
||||
characters LangVAChar[] @relation("VACharLanguage")
|
||||
@@map("voice_actors")
|
||||
}
|
||||
|
||||
model LangVAChar {
|
||||
id String @id @db.Uuid
|
||||
language String
|
||||
voiceActor VoiceActor @relation("VACharLanguage", fields: [vaId], references: [id])
|
||||
vaId String @db.Uuid
|
||||
character Character @relation("CharVALanguage", fields: [charId], references: [id])
|
||||
charId String @db.Uuid
|
||||
createdBy User @relation("UserCreatedLangVAChar", fields: [creatorId], references: [id])
|
||||
creatorId String @db.Uuid
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
character Character @relation("CharVALanguage", fields: [charId], references: [id])
|
||||
createdBy User @relation("UserCreatedLangVAChar", fields: [creatorId], references: [id])
|
||||
voiceActor VoiceActor @relation("VACharLanguage", fields: [vaId], references: [id])
|
||||
|
||||
@@unique([language, vaId, charId])
|
||||
@@map("lang_va_char")
|
||||
@ -157,25 +167,26 @@ model LangVAChar {
|
||||
|
||||
model Episode {
|
||||
id String @id @db.Uuid
|
||||
media Media @relation("MediaEpisodes", fields: [mediaId], references: [id])
|
||||
mediaId String @db.Uuid
|
||||
episode Int
|
||||
name String @db.VarChar(255)
|
||||
score Decimal @default(0.00) @db.Decimal(4, 2)
|
||||
pictureThumbnail String?
|
||||
score Decimal @db.Decimal(4,2) @default(0.00)
|
||||
pictureThumbnail String? @db.Text
|
||||
viewed BigInt @default(0)
|
||||
likes BigInt @default(0)
|
||||
dislikes BigInt @default(0)
|
||||
pendingUpload Boolean @default(true)
|
||||
uploader User @relation("UserEpisodes", fields: [uploadedBy], references: [id])
|
||||
uploadedBy String @db.Uuid
|
||||
deletedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
comments Comment[] @relation("EpisodeComments")
|
||||
|
||||
user_likes EpisodeLike[] @relation("EpisodeLikes")
|
||||
media Media @relation("MediaEpisodes", fields: [mediaId], references: [id])
|
||||
uploader User @relation("UserEpisodes", fields: [uploadedBy], references: [id])
|
||||
videos Video[] @relation("EpisodeVideos")
|
||||
user_histories WatchHistory? @relation("EpisodeWatchHistories")
|
||||
user_histories WatchHistory[] @relation("EpisodeWatchHistories")
|
||||
comments Comment[] @relation("EpisodeComments")
|
||||
|
||||
@@unique([mediaId, episode])
|
||||
@@map("episodes")
|
||||
@ -183,32 +194,31 @@ model Episode {
|
||||
|
||||
model EpisodeLike {
|
||||
id String @id @db.Uuid
|
||||
user User @relation("UserEpisodeLikes", fields: [userId], references: [id])
|
||||
userId String @db.Uuid
|
||||
session UserSession @relation("SessionEpisodeLikes", fields: [sessionId], references: [id])
|
||||
sessionId String @db.Uuid
|
||||
episode Episode @relation("EpisodeLikes", fields: [episodeId], references: [id])
|
||||
episodeId String @db.Uuid
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
episode Episode @relation("EpisodeLikes", fields: [episodeId], references: [id])
|
||||
session UserSession @relation("SessionEpisodeLikes", fields: [sessionId], references: [id])
|
||||
user User @relation("UserEpisodeLikes", fields: [userId], references: [id])
|
||||
|
||||
@@map("episode_likes")
|
||||
}
|
||||
|
||||
model Video {
|
||||
id String @id @db.Uuid
|
||||
episode Episode @relation("EpisodeVideos", fields: [episodeId], references: [id])
|
||||
episodeId String @db.Uuid
|
||||
service VideoService @relation("VideoServices", fields: [serviceId], references: [id])
|
||||
serviceId String @db.Uuid
|
||||
videoCode String @db.VarChar(255)
|
||||
thumbnailCode String?
|
||||
pendingUpload Boolean @default(true)
|
||||
uploader User @relation("UserVideos", fields: [uploadedBy], references: [id])
|
||||
uploadedBy String @db.Uuid
|
||||
deletedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
episode Episode @relation("EpisodeVideos", fields: [episodeId], references: [id])
|
||||
service VideoService @relation("VideoServices", fields: [serviceId], references: [id])
|
||||
uploader User @relation("UserVideos", fields: [uploadedBy], references: [id])
|
||||
|
||||
@@unique([serviceId, videoCode])
|
||||
@@map("videos")
|
||||
@ -216,21 +226,21 @@ model Video {
|
||||
|
||||
model VideoService {
|
||||
id String @id @db.Uuid
|
||||
name String @unique @db.VarChar(255)
|
||||
name String @db.VarChar(255) @unique
|
||||
domain String @db.VarChar(255)
|
||||
logo String?
|
||||
logo String? @db.Text
|
||||
hexColor String @db.VarChar(10)
|
||||
endpointVideo String
|
||||
endpointThumbnail String?
|
||||
endpointVideo String @db.Text
|
||||
endpointThumbnail String? @db.Text
|
||||
endpointDownload String?
|
||||
creator User @relation("UserVideoServices", fields: [createdBy], references: [id])
|
||||
createdBy String @db.Uuid
|
||||
deletedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
user_preferences UserPreference[] @relation("UserServiceDefault")
|
||||
creator User @relation("UserVideoServices", fields: [createdBy], references: [id])
|
||||
videos Video[] @relation("VideoServices")
|
||||
|
||||
videos Video[] @relation("VideoServices")
|
||||
user_preferences UserPreference[] @relation("UserServiceDefault")
|
||||
@@map("video_services")
|
||||
}
|
||||
|
||||
@ -238,87 +248,86 @@ model User {
|
||||
id String @id @db.Uuid
|
||||
name String @db.VarChar(255)
|
||||
username String @unique @db.VarChar(255)
|
||||
email String @unique
|
||||
password String
|
||||
email String @unique @db.Text
|
||||
password String @db.Text
|
||||
birthDate DateTime? @db.Date
|
||||
gender UserGender?
|
||||
phoneCC Int?
|
||||
phoneNumber Int?
|
||||
bioProfile String?
|
||||
avatar String?
|
||||
commentBackground String?
|
||||
assignedRoles UserRoleAssignment[]
|
||||
bioProfile String? @db.Text
|
||||
avatar String? @db.Text
|
||||
commentBackground String? @db.Text
|
||||
provider String? @db.VarChar(255)
|
||||
providerId String? @unique @db.VarChar(255)
|
||||
providerToken String?
|
||||
providerToken String? @db.Text
|
||||
providerPayload Json? @db.Json
|
||||
preference UserPreference?
|
||||
verifiedAt DateTime?
|
||||
disabledAt DateTime?
|
||||
deletedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
|
||||
medias Media[] @relation("UserUploadedMedias")
|
||||
media_proposeds MediaLog[] @relation("UserProposedMedias")
|
||||
media_approveds MediaLog[] @relation("UserApprovedMedias")
|
||||
genres Genre[] @relation("UserCreatedGenres")
|
||||
studios Studio[] @relation("UserCreatedStudios")
|
||||
characters Character[] @relation("UserCreatedCharacters")
|
||||
voice_actor VoiceActor[] @relation("UserCreatedVoiceActors")
|
||||
lang_va_char LangVAChar[] @relation("UserCreatedLangVAChar")
|
||||
episodes Episode[] @relation("UserEpisodes")
|
||||
episode_likes EpisodeLike[] @relation("UserEpisodeLikes")
|
||||
videos Video[] @relation("UserVideos")
|
||||
video_services VideoService[] @relation("UserVideoServices")
|
||||
create_roles UserRole[] @relation("UserCreateRoles")
|
||||
notifications UserNotification[] @relation("UserNotifications")
|
||||
sessions UserSession[] @relation("UserSession")
|
||||
logs UserLog[] @relation("UserLogs")
|
||||
collections Collection[] @relation("UserCollections")
|
||||
liked_comments CommentLike[] @relation("UserCommentLikes")
|
||||
approved_comments CommentReport[] @relation("ApprovedReportComments")
|
||||
reported_comments CommentReport[] @relation("UserReportComments")
|
||||
allowed_collections Collection[] @relation("UserSelectedSharingCollention")
|
||||
watch_histories WatchHistory[] @relation("UserWatchHistories")
|
||||
media_reviews MediaReview[] @relation("UserMediaReviews")
|
||||
comments Comment[] @relation("UserComments")
|
||||
liked_comments CommentLike[] @relation("UserCommentLikes")
|
||||
reported_comments CommentReport[] @relation("UserReportComments")
|
||||
approved_comments CommentReport[] @relation("ApprovedReportComments")
|
||||
create_languages Language[] @relation("UserCreateLanguages")
|
||||
user_create_email EmailSystemAccount[] @relation("UserCreateSystemAccount")
|
||||
user_emails EmailSystemHistory[] @relation("UserEmails")
|
||||
episode_likes EpisodeLike[] @relation("UserEpisodeLikes")
|
||||
episodes Episode[] @relation("UserEpisodes")
|
||||
genres Genre[] @relation("UserCreatedGenres")
|
||||
user_hero_banner HeroBanner[] @relation("UserHeroBanner")
|
||||
lang_va_char LangVAChar[] @relation("UserCreatedLangVAChar")
|
||||
create_languages Language[] @relation("UserCreateLanguages")
|
||||
media_approveds MediaLog[] @relation("UserApprovedMedias")
|
||||
media_proposeds MediaLog[] @relation("UserProposedMedias")
|
||||
medias Media[] @relation("UserUploadedMedias")
|
||||
media_reviews MediaReview[] @relation("UserMediaReviews")
|
||||
studios Studio[] @relation("UserCreatedStudios")
|
||||
sys_logs SystemLog[] @relation("UserSystemLogs")
|
||||
sys_notifications SystemNotification[] @relation("UserCreatorSystemNotifications")
|
||||
logs UserLog[] @relation("UserLogs")
|
||||
notifications UserNotification[] @relation("UserNotifications")
|
||||
preference UserPreference?
|
||||
assignedRoles UserRoleAssignment[]
|
||||
create_roles UserRole[] @relation("UserCreateRoles")
|
||||
sessions UserSession[] @relation("UserSession")
|
||||
video_services VideoService[] @relation("UserVideoServices")
|
||||
videos Video[] @relation("UserVideos")
|
||||
voice_actor VoiceActor[] @relation("UserCreatedVoiceActors")
|
||||
watch_histories WatchHistory[] @relation("UserWatchHistories")
|
||||
allowed_collections Collection[] @relation("UserSelectedSharingCollention")
|
||||
|
||||
sys_logs SystemLog[] @relation("UserSystemLogs")
|
||||
@@map("users")
|
||||
}
|
||||
|
||||
model UserPreference {
|
||||
id String @id @db.Uuid
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
userId String @unique @db.Uuid
|
||||
lang Language? @relation("UserPreferenceLang", fields: [langPreference], references: [code])
|
||||
langPreference String?
|
||||
adultFiltering AdultFiltering @default(hide)
|
||||
adultAlert AdultAlert @default(show)
|
||||
videoQuality VideoQuality @default(Q1080)
|
||||
serviceDefault VideoService? @relation("UserServiceDefault", fields: [serviceDefaultId], references: [id])
|
||||
serviceDefaultId String? @db.Uuid
|
||||
hideContries Country[]
|
||||
favoriteGenres Genre[] @relation("UserFavoriteGenres")
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
lang Language? @relation("UserPreferenceLang", fields: [langPreference], references: [code])
|
||||
serviceDefault VideoService? @relation("UserServiceDefault", fields: [serviceDefaultId], references: [id])
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
favoriteGenres Genre[] @relation("UserFavoriteGenres")
|
||||
|
||||
@@map("user_preferences")
|
||||
}
|
||||
|
||||
model UserRole {
|
||||
id String @id @db.Uuid
|
||||
name String @unique @db.VarChar(255)
|
||||
description String?
|
||||
name String @db.VarChar(255) @unique
|
||||
description String? @db.Text
|
||||
primaryColor String? @db.VarChar(10)
|
||||
secondaryColor String? @db.VarChar(10)
|
||||
pictureImage String?
|
||||
badgeImage String?
|
||||
pictureImage String? @db.Text
|
||||
badgeImage String? @db.Text
|
||||
isSuperadmin Boolean @default(false)
|
||||
canEditMedia Boolean @default(false)
|
||||
canManageMedia Boolean @default(false)
|
||||
@ -330,22 +339,24 @@ model UserRole {
|
||||
canManageUser Boolean @default(false)
|
||||
canEditSystem Boolean @default(false)
|
||||
canManageSystem Boolean @default(false)
|
||||
creator User @relation("UserCreateRoles", fields: [createdBy], references: [id])
|
||||
createdBy String @db.Uuid
|
||||
deletedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
assignedUser UserRoleAssignment[]
|
||||
creator User @relation("UserCreateRoles", fields: [createdBy], references: [id])
|
||||
|
||||
assignedUser UserRoleAssignment[]
|
||||
@@map("user_roles")
|
||||
}
|
||||
|
||||
model UserRoleAssignment {
|
||||
userId String @db.Uuid
|
||||
roleId String @db.Uuid
|
||||
assignmentAt DateTime @default(now())
|
||||
role UserRole @relation(fields: [roleId], references: [id])
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
userId String @db.Uuid
|
||||
|
||||
role UserRole @relation(fields: [roleId], references: [id])
|
||||
roleId String @db.Uuid
|
||||
|
||||
assignmentAt DateTime @default(now())
|
||||
|
||||
@@id([userId, roleId])
|
||||
@@map("user_role_assignments")
|
||||
@ -354,23 +365,23 @@ model UserRoleAssignment {
|
||||
model UserNotification {
|
||||
id String @id @db.Uuid
|
||||
title String @db.VarChar(255)
|
||||
content String
|
||||
picture String
|
||||
content String @db.Text
|
||||
picture String @db.Text
|
||||
state UserNotificationState
|
||||
ctaLink String
|
||||
ctaLink String @db.Text
|
||||
user User @relation("UserNotifications", fields: [userId], references: [id])
|
||||
userId String @db.Uuid
|
||||
isReaded Boolean @default(false)
|
||||
deletedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
user User @relation("UserNotifications", fields: [userId], references: [id])
|
||||
|
||||
@@map("user_notifications")
|
||||
}
|
||||
|
||||
model UserSession {
|
||||
id String @id @db.Uuid
|
||||
isAuthenticated Boolean @default(false)
|
||||
user User @relation("UserSession", fields: [userId], references: [id])
|
||||
userId String @db.Uuid
|
||||
deviceType String @db.VarChar(255)
|
||||
deviceOs String @db.VarChar(255)
|
||||
@ -382,9 +393,9 @@ model UserSession {
|
||||
deletedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
episode_likes EpisodeLike[] @relation("SessionEpisodeLikes")
|
||||
|
||||
logs UserLog[] @relation("UserSessionLogs")
|
||||
user User @relation("UserSession", fields: [userId], references: [id])
|
||||
episode_likes EpisodeLike[] @relation("SessionEpisodeLikes")
|
||||
watch_histories WatchHistory[] @relation("SessionWatchHistories")
|
||||
|
||||
@@index([userId, isAuthenticated, deletedAt])
|
||||
@ -394,138 +405,119 @@ model UserSession {
|
||||
model UserLog {
|
||||
id String @id @db.Uuid
|
||||
title String @db.VarChar(255)
|
||||
notes String
|
||||
notes String @db.Text
|
||||
user User @relation("UserLogs", fields: [userId], references: [id])
|
||||
userId String @db.Uuid
|
||||
session UserSession @relation("UserSessionLogs", fields: [sessionId], references: [id])
|
||||
sessionId String @db.Uuid
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
session UserSession @relation("UserSessionLogs", fields: [sessionId], references: [id])
|
||||
user User @relation("UserLogs", fields: [userId], references: [id])
|
||||
|
||||
@@map("user_logs")
|
||||
}
|
||||
|
||||
model Collection {
|
||||
id String @id @db.Uuid
|
||||
name String @db.VarChar(115)
|
||||
name String @db.VarChar(255)
|
||||
medias Media[] @relation("MediaCollections")
|
||||
owner User @relation("UserCollections", fields: [ownerId], references: [id])
|
||||
ownerId String @db.Uuid
|
||||
accessStatus AccessStatus @default(private)
|
||||
password String? @db.VarChar(255)
|
||||
usersAllowed User[] @relation("UserSelectedSharingCollention")
|
||||
accessScope AccessScope @default(viewer)
|
||||
deletedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
slug String @db.VarChar(115)
|
||||
media_saved CollectionMedia[] @relation("CollectionMedia")
|
||||
owner User @relation("UserCollections", fields: [ownerId], references: [id])
|
||||
usersAllowed User[] @relation("UserSelectedSharingCollention")
|
||||
|
||||
@@unique([slug, ownerId])
|
||||
@@map("collections")
|
||||
}
|
||||
|
||||
model CollectionMedia {
|
||||
id String @id @db.Uuid
|
||||
collectionId String @db.Uuid
|
||||
mediaId String @db.Uuid
|
||||
savedAt DateTime @default(now())
|
||||
collection Collection @relation("CollectionMedia", fields: [collectionId], references: [id])
|
||||
media Media @relation("CollectionMedia", fields: [mediaId], references: [id])
|
||||
|
||||
@@unique([collectionId, mediaId])
|
||||
}
|
||||
|
||||
model WatchHistory {
|
||||
id String @id @db.Uuid
|
||||
episode Episode @relation("EpisodeWatchHistories", fields: [id], references: [id])
|
||||
episodeId String @db.Uuid
|
||||
user User @relation("UserWatchHistories", fields: [userId], references: [id])
|
||||
userId String @db.Uuid
|
||||
session UserSession @relation("SessionWatchHistories", fields: [sessionId], references: [id])
|
||||
sessionId String @db.Uuid
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
episode Episode @relation("EpisodeWatchHistories", fields: [id], references: [id])
|
||||
session UserSession @relation("SessionWatchHistories", fields: [sessionId], references: [id])
|
||||
user User @relation("UserWatchHistories", fields: [userId], references: [id])
|
||||
|
||||
@@map("watch_histories")
|
||||
}
|
||||
|
||||
model MediaReview {
|
||||
id String @id @db.Uuid
|
||||
media Media @relation("MediaReviews", fields: [mediaId], references:[id])
|
||||
mediaId String @db.Uuid
|
||||
rating Int
|
||||
title String @db.VarChar(255)
|
||||
text String
|
||||
text String @db.Text
|
||||
reaction MediaReviewReaction
|
||||
creator User @relation("UserMediaReviews", fields: [createdBy], references: [id])
|
||||
createdBy String @db.Uuid
|
||||
deletedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
creator User @relation("UserMediaReviews", fields: [createdBy], references: [id])
|
||||
media Media @relation("MediaReviews", fields: [mediaId], references: [id])
|
||||
|
||||
@@map("movie_reviews")
|
||||
}
|
||||
|
||||
model Comment {
|
||||
id String @id @db.Uuid
|
||||
episode Episode @relation("EpisodeComments", fields: [episodeId], references: [id])
|
||||
episodeId String @db.Uuid
|
||||
text String
|
||||
text String @db.Text
|
||||
isParent Boolean @default(false)
|
||||
parent Comment? @relation("ParentReplyComments", fields: [parentId], references: [id])
|
||||
parentId String? @db.Uuid
|
||||
user User @relation("UserComments", fields: [userId], references: [id])
|
||||
userId String @db.Uuid
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
likes CommentLike[] @relation("CommentLikes")
|
||||
episode Episode @relation("EpisodeComments", fields: [episodeId], references: [id])
|
||||
parent Comment? @relation("ParentReplyComments", fields: [parentId], references: [id])
|
||||
replies Comment[] @relation("ParentReplyComments")
|
||||
user User @relation("UserComments", fields: [userId], references: [id])
|
||||
|
||||
replies Comment[] @relation("ParentReplyComments")
|
||||
likes CommentLike[] @relation("CommentLikes")
|
||||
@@map("comments")
|
||||
}
|
||||
|
||||
model CommentLike {
|
||||
id String @id @db.Uuid
|
||||
comment Comment @relation("CommentLikes", fields: [commentId], references: [id])
|
||||
commentId String @db.Uuid
|
||||
user User @relation("UserCommentLikes", fields: [userLiked], references: [id])
|
||||
userLiked String @db.Uuid
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
comment Comment @relation("CommentLikes", fields: [commentId], references: [id])
|
||||
user User @relation("UserCommentLikes", fields: [userLiked], references: [id])
|
||||
|
||||
@@map("comment_likes")
|
||||
}
|
||||
|
||||
model CommentReport {
|
||||
id String @id @db.Uuid
|
||||
reporter User @relation("UserReportComments", fields: [userReporter], references: [id])
|
||||
userReporter String @db.Uuid
|
||||
commentReported String @db.Uuid
|
||||
isSupervisorReport Boolean @default(false)
|
||||
reason ReportReason
|
||||
status ReportStatus
|
||||
description String @db.VarChar(255)
|
||||
approver User? @relation("ApprovedReportComments", fields: [approvedBy], references: [id])
|
||||
approvedBy String? @db.Uuid
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
approver User? @relation("ApprovedReportComments", fields: [approvedBy], references: [id])
|
||||
reporter User @relation("UserReportComments", fields: [userReporter], references: [id])
|
||||
|
||||
@@map("comment_reports")
|
||||
}
|
||||
|
||||
model Language {
|
||||
id String @id @db.Uuid
|
||||
name String @db.VarChar(255)
|
||||
code String @unique @db.VarChar(5)
|
||||
code String @db.VarChar(5) @unique
|
||||
countryFlag String @db.VarChar(10)
|
||||
fileLocation String
|
||||
fileLocation String @db.Text
|
||||
creator User @relation("UserCreateLanguages", fields: [craetedBy], references: [id])
|
||||
craetedBy String @db.Uuid
|
||||
deletedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
creator User @relation("UserCreateLanguages", fields: [craetedBy], references: [id])
|
||||
user_used UserPreference[] @relation("UserPreferenceLang")
|
||||
|
||||
user_used UserPreference[] @relation("UserPreferenceLang")
|
||||
@@map("languages")
|
||||
}
|
||||
|
||||
@ -539,56 +531,56 @@ model EmailSystemAccount {
|
||||
username String @unique @db.VarChar(255)
|
||||
password String @db.VarChar(255)
|
||||
purpose EmailPorpose
|
||||
creator User @relation("UserCreateSystemAccount", fields: [createdBy], references: [id])
|
||||
createdBy String @db.Uuid
|
||||
deletedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
creator User @relation("UserCreateSystemAccount", fields: [createdBy], references: [id])
|
||||
|
||||
@@map("email_system_accounts")
|
||||
}
|
||||
|
||||
model EmailSystemHistory {
|
||||
id String @id @db.Uuid
|
||||
purpose EmailPorpose
|
||||
fromEmail String
|
||||
toEmail String
|
||||
fromEmail String @db.Text
|
||||
toEmail String @db.Text
|
||||
user User @relation("UserEmails", fields: [userRelated], references: [id])
|
||||
userRelated String @db.Uuid
|
||||
title String @db.VarChar(255)
|
||||
htmlContent String
|
||||
htmlContent String @db.Text
|
||||
deletedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
user User @relation("UserEmails", fields: [userRelated], references: [id])
|
||||
|
||||
@@map("email_system_histories")
|
||||
}
|
||||
|
||||
model HeroBanner {
|
||||
id String @id @db.Uuid
|
||||
orderPriority Int? @unique
|
||||
imageUrl String?
|
||||
isClickable Boolean @default(false)
|
||||
title String? @db.VarChar(225)
|
||||
tags String[]
|
||||
description String? @db.Text
|
||||
buttonContent String? @db.VarChar(100)
|
||||
buttonLink String? @db.Text
|
||||
imageUrl String? @db.Text
|
||||
startDate DateTime
|
||||
endDate DateTime
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
creatorId String @db.Uuid
|
||||
mediaId String @db.Uuid
|
||||
createdBy User @relation("UserHeroBanner", fields: [creatorId], references: [id])
|
||||
media Media @relation("MediaBannerPromotion", fields: [mediaId], references: [id])
|
||||
|
||||
@@map("hero_banner")
|
||||
}
|
||||
|
||||
model SystemPreference {
|
||||
id String @id @db.Uuid
|
||||
key String @unique @db.VarChar(225)
|
||||
key String @db.VarChar(225) @unique
|
||||
value String @db.VarChar(225)
|
||||
description String
|
||||
description String @db.Text
|
||||
deletedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
|
||||
@@map("system_preferences")
|
||||
}
|
||||
|
||||
@ -596,30 +588,35 @@ model SystemNotification {
|
||||
id String @id @db.Uuid
|
||||
type TypeSystemNotification
|
||||
componentName String? @db.VarChar(255)
|
||||
popupImage String?
|
||||
popupImage String? @db.Text
|
||||
titleToast String? @db.VarChar(255)
|
||||
contentToast String?
|
||||
contentToast String? @db.Text
|
||||
creator User @relation("UserCreatorSystemNotifications", fields: [createdBy], references: [id])
|
||||
createdBy String @db.Uuid
|
||||
deletedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
creator User @relation("UserCreatorSystemNotifications", fields: [createdBy], references: [id])
|
||||
|
||||
@@map("system_notifications")
|
||||
}
|
||||
|
||||
model SystemLog {
|
||||
id String @id @db.Uuid
|
||||
title String @db.VarChar(255)
|
||||
notes String
|
||||
notes String @db.Text
|
||||
user User? @relation("UserSystemLogs", fields: [relatedUser], references: [id])
|
||||
relatedUser String? @db.Uuid
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
user User? @relation("UserSystemLogs", fields: [relatedUser], references: [id])
|
||||
|
||||
@@map("system_logs")
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//// Prisma Enum Values ////
|
||||
|
||||
// Media Enum
|
||||
enum MediaType {
|
||||
TV
|
||||
ONA
|
||||
@ -628,7 +625,6 @@ enum MediaType {
|
||||
Special
|
||||
Music
|
||||
}
|
||||
|
||||
enum Country {
|
||||
JP @map("Japanese")
|
||||
EN @map("English")
|
||||
@ -636,40 +632,35 @@ enum Country {
|
||||
KR @map("Korea")
|
||||
}
|
||||
|
||||
enum Season {
|
||||
winter
|
||||
spring
|
||||
summer
|
||||
fall
|
||||
}
|
||||
|
||||
// Character Enum
|
||||
enum CharacterRole {
|
||||
Main
|
||||
Supporting
|
||||
}
|
||||
|
||||
// MediaLog Enum
|
||||
enum MediaOperation {
|
||||
create
|
||||
update
|
||||
delete
|
||||
}
|
||||
|
||||
// User Enum
|
||||
enum UserGender {
|
||||
male
|
||||
female
|
||||
}
|
||||
|
||||
// UserPreference Enum
|
||||
enum AdultFiltering {
|
||||
hide
|
||||
show
|
||||
explicit
|
||||
}
|
||||
|
||||
enum AdultAlert {
|
||||
hide
|
||||
show
|
||||
}
|
||||
|
||||
enum VideoQuality {
|
||||
Q2160
|
||||
Q1440
|
||||
@ -681,18 +672,19 @@ enum VideoQuality {
|
||||
Q144
|
||||
}
|
||||
|
||||
// userNotification Enum
|
||||
enum UserNotificationState {
|
||||
info
|
||||
warning
|
||||
danger
|
||||
}
|
||||
|
||||
// CommentReport Enum
|
||||
enum ReportStatus {
|
||||
pending
|
||||
resolved
|
||||
rejected
|
||||
}
|
||||
|
||||
enum ReportReason {
|
||||
sexualize
|
||||
violent
|
||||
@ -704,18 +696,19 @@ enum ReportReason {
|
||||
other
|
||||
}
|
||||
|
||||
// Collection Enum
|
||||
enum AccessStatus {
|
||||
private
|
||||
selected
|
||||
protected
|
||||
public
|
||||
}
|
||||
|
||||
enum AccessScope {
|
||||
viewer
|
||||
editor
|
||||
}
|
||||
|
||||
// MediaReview Enum
|
||||
enum MediaReviewReaction {
|
||||
angry
|
||||
sad
|
||||
@ -727,6 +720,7 @@ enum MediaReviewReaction {
|
||||
disappointed
|
||||
}
|
||||
|
||||
// EmailSystemHistory Enum
|
||||
enum EmailPorpose {
|
||||
forgot_password
|
||||
account_activation
|
||||
@ -734,6 +728,7 @@ enum EmailPorpose {
|
||||
subscribtion
|
||||
}
|
||||
|
||||
// systemNotification Enum
|
||||
enum TypeSystemNotification {
|
||||
component
|
||||
popup
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { Context } from "elysia";
|
||||
import { UserHeaderInformation } from "./types";
|
||||
|
||||
export interface ClientInfoHeader {
|
||||
@ -9,14 +10,25 @@ export interface ClientInfoHeader {
|
||||
ip: string;
|
||||
}
|
||||
|
||||
export const getUserHeaderInformation = (clientInfo: string): UserHeaderInformation => {
|
||||
const clientInfoHeader = (JSON.parse(clientInfo) as ClientInfoHeader) ?? ("unknown" as string);
|
||||
export const getUserHeaderInformation = (
|
||||
ctx: Context,
|
||||
): UserHeaderInformation => {
|
||||
const clientInfoHeader =
|
||||
(JSON.parse(
|
||||
ctx.request.headers.get("x-client-info") as string,
|
||||
) as ClientInfoHeader) ?? ("unknown" as string);
|
||||
|
||||
const userHeaderInformation = {
|
||||
ip: clientInfoHeader.ip ?? "unknown",
|
||||
deviceType: clientInfoHeader.deviceType ?? "unknown",
|
||||
deviceOS: (clientInfoHeader.os ?? "unknown") + " " + (clientInfoHeader.osVersion ?? "unknown"),
|
||||
browser: (clientInfoHeader.browser ?? "unknown") + " " + (clientInfoHeader.browserVersion ?? "unknown"),
|
||||
deviceOS:
|
||||
(clientInfoHeader.os ?? "unknown") +
|
||||
" " +
|
||||
(clientInfoHeader.osVersion ?? "unknown"),
|
||||
browser:
|
||||
(clientInfoHeader.browser ?? "unknown") +
|
||||
" " +
|
||||
(clientInfoHeader.browserVersion ?? "unknown"),
|
||||
};
|
||||
|
||||
return userHeaderInformation;
|
||||
|
||||
@ -1,17 +1,14 @@
|
||||
import { Context, Static } from "elysia";
|
||||
import { Context } from "elysia";
|
||||
import { returnWriteResponse } from "../../../helpers/callback/httpResponse";
|
||||
import { githubCallbackService } from "../services/http/githubCallback.service";
|
||||
import { mainErrorHandler } from "../../../helpers/error/handler";
|
||||
import { getUserHeaderInformation } from "../../../helpers/http/userHeader/getUserHeaderInformation";
|
||||
import { githubCallbackSchema } from "../schemas/githubCallback.schema";
|
||||
|
||||
export const githubCallbackController = async (ctx: {
|
||||
set: Context["set"];
|
||||
query: Static<typeof githubCallbackSchema.query>;
|
||||
headers: Static<typeof githubCallbackSchema.headers>;
|
||||
}) => {
|
||||
export const githubCallbackController = async (
|
||||
ctx: Context & { query: { code: string; callbackURI: string } }
|
||||
) => {
|
||||
try {
|
||||
const userHeaderInfo = getUserHeaderInformation(ctx.headers["x-client-info"]);
|
||||
const userHeaderInfo = getUserHeaderInformation(ctx);
|
||||
|
||||
const authToken = await githubCallbackService(ctx.query, userHeaderInfo);
|
||||
return returnWriteResponse(ctx.set, 200, "Authenticated successfully!", {
|
||||
|
||||
@ -1,18 +1,21 @@
|
||||
import { Context, Static } from "elysia";
|
||||
import { Context } from "elysia";
|
||||
import { returnReadResponse } from "../../../helpers/callback/httpResponse";
|
||||
import { githubRequestService } from "../services/http/githubRequest.service";
|
||||
import { mainErrorHandler } from "../../../helpers/error/handler";
|
||||
import { githubRequestSchema } from "../schemas/githubRequest.schema";
|
||||
|
||||
export const githubRequestController = async (ctx: {
|
||||
set: Context["set"];
|
||||
query: Static<typeof githubRequestSchema.query>;
|
||||
}) => {
|
||||
export const githubRequestController = async (
|
||||
ctx: Context & { query: { callback?: string } },
|
||||
) => {
|
||||
try {
|
||||
const loginUrl = await githubRequestService(ctx.query.callback);
|
||||
return returnReadResponse(ctx.set, 200, "GitHub login URL created successfully.", {
|
||||
return returnReadResponse(
|
||||
ctx.set,
|
||||
200,
|
||||
"Login URL generated successfully",
|
||||
{
|
||||
endpointUrl: loginUrl,
|
||||
});
|
||||
},
|
||||
);
|
||||
} catch (error) {
|
||||
return mainErrorHandler(ctx.set, error);
|
||||
}
|
||||
|
||||
@ -1,20 +1,17 @@
|
||||
import { Context, Static } from "elysia";
|
||||
import { Context } from "elysia";
|
||||
import { returnReadResponse } from "../../../helpers/callback/httpResponse";
|
||||
import { mainErrorHandler } from "../../../helpers/error/handler";
|
||||
import { googleCallbackService } from "../services/http/googleCallback.service";
|
||||
import { getUserHeaderInformation } from "../../../helpers/http/userHeader/getUserHeaderInformation";
|
||||
import { googleCallbackSchema } from "../schemas/googleCallback.schema";
|
||||
|
||||
export const googleCallbackController = async (ctx: {
|
||||
set: Context["set"];
|
||||
query: Static<typeof googleCallbackSchema.query>;
|
||||
headers: Static<typeof googleCallbackSchema.headers>;
|
||||
}) => {
|
||||
export const googleCallbackController = async (
|
||||
ctx: Context & { query: { code: string; state: string; callbackURI: string } }
|
||||
) => {
|
||||
try {
|
||||
const userHeaderInfo = getUserHeaderInformation(ctx.headers["x-client-info"]);
|
||||
const userHeaderInfo = getUserHeaderInformation(ctx);
|
||||
|
||||
const authToken = await googleCallbackService(ctx.query, userHeaderInfo);
|
||||
return returnReadResponse(ctx.set, 200, "Authentication successful!", {
|
||||
return returnReadResponse(ctx.set, 200, "Authenticated successfully!", {
|
||||
authToken,
|
||||
});
|
||||
} catch (error) {
|
||||
|
||||
@ -1,16 +1,14 @@
|
||||
import { Context, Static } from "elysia";
|
||||
import { Context } from "elysia";
|
||||
import { mainErrorHandler } from "../../../helpers/error/handler";
|
||||
import { googleRequestService } from "../services/http/googleRequest.service";
|
||||
import { returnReadResponse } from "../../../helpers/callback/httpResponse";
|
||||
import { googleRequestSchema } from "../schemas/googleRequest.schema";
|
||||
|
||||
export const googleRequestController = async (ctx: {
|
||||
set: Context["set"];
|
||||
query: Static<typeof googleRequestSchema.query>;
|
||||
}) => {
|
||||
export const googleRequestController = async (
|
||||
ctx: Context & { query: { callback?: string } }
|
||||
) => {
|
||||
try {
|
||||
const loginUrl = await googleRequestService(ctx.query.callback);
|
||||
return returnReadResponse(ctx.set, 200, "Google login URL created successfully.", {
|
||||
return returnReadResponse(ctx.set, 200, "Google login url created!", {
|
||||
endpointUrl: loginUrl,
|
||||
});
|
||||
} catch (error) {
|
||||
|
||||
@ -9,19 +9,13 @@ import { tokenValidationController } from "./controllers/tokenValidation.control
|
||||
import { logoutController } from "./controllers/logout.controller";
|
||||
import { tokenValidationSchema } from "./schemas/tokenValidation.schema";
|
||||
import { getOauthProvidersSchema } from "./schemas/getOauthProviders.schema";
|
||||
import { getCallbackProviderUrlSchema } from "./schemas/getCallbackProviderUrl.schema";
|
||||
import { googleRequestSchema } from "./schemas/googleRequest.schema";
|
||||
import { googleCallbackSchema } from "./schemas/googleCallback.schema";
|
||||
import { githubRequestSchema } from "./schemas/githubRequest.schema";
|
||||
import { githubCallbackSchema } from "./schemas/githubCallback.schema";
|
||||
import { logoutSchema } from "./schemas/logout.schema";
|
||||
|
||||
export const authModule = new Elysia({ prefix: "/auth", tags: ["Authentication"] })
|
||||
.post("/token/validate", tokenValidationController, tokenValidationSchema)
|
||||
.get("/providers", getOauthProvidersController, getOauthProvidersSchema)
|
||||
.get("/providers/:name/callback", getCallbackProviderUrlController, getCallbackProviderUrlSchema)
|
||||
.get("/google", googleRequestController, googleRequestSchema)
|
||||
.get("/google/callback", googleCallbackController, googleCallbackSchema)
|
||||
.get("/github", githubRequestController, githubRequestSchema)
|
||||
.get("/github/callback", githubCallbackController, githubCallbackSchema)
|
||||
.post("/logout", logoutController, logoutSchema);
|
||||
.get("/providers/:name/callback", getCallbackProviderUrlController)
|
||||
.get("/github", githubRequestController)
|
||||
.get("/github/callback", githubCallbackController)
|
||||
.get("/google", googleRequestController)
|
||||
.get("/google/callback", googleCallbackController)
|
||||
.post("/logout", logoutController);
|
||||
|
||||
@ -1,45 +0,0 @@
|
||||
import { AppRouteSchema } from "../../../helpers/types/AppRouteSchema";
|
||||
|
||||
export const getCallbackProviderUrlSchema = {
|
||||
detail: {
|
||||
summary: "Get the callback URL of oauth provider",
|
||||
description:
|
||||
"After users have successfully completed the authentication process on the OAuth provider page, they will be redirected to the callback page on the frontend. This endpoint aims to obtain the actual endpoint for each OAuth response handler.",
|
||||
responses: {
|
||||
200: {
|
||||
description: "The callback URL on the provider has been found.",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
success: {
|
||||
type: "boolean",
|
||||
default: true,
|
||||
},
|
||||
status: {
|
||||
type: "number",
|
||||
default: 200,
|
||||
},
|
||||
message: {
|
||||
type: "string",
|
||||
default: "The callback URL on the provider has been found.",
|
||||
},
|
||||
data: {
|
||||
type: "object",
|
||||
properties: {
|
||||
callback_url: {
|
||||
type: "string",
|
||||
description: "The callback URL on the provider.",
|
||||
example: "auth/google/callback",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} satisfies AppRouteSchema;
|
||||
@ -1,3 +1,4 @@
|
||||
import { success } from "zod";
|
||||
import { AppRouteSchema } from "../../../helpers/types/AppRouteSchema";
|
||||
|
||||
export const getOauthProvidersSchema = {
|
||||
|
||||
@ -1,57 +0,0 @@
|
||||
import { t } from "elysia";
|
||||
import { AppRouteSchema } from "../../../helpers/types/AppRouteSchema";
|
||||
|
||||
export const githubCallbackSchema = {
|
||||
headers: t.Object({
|
||||
"x-client-info": t.String({
|
||||
examples: [
|
||||
'{"os":"Windows","osVersion":"10","browser":"Chrome","browserVersion":"89.0.4389.82","deviceType":"Desktop","ip":"192.168.1.1"}',
|
||||
],
|
||||
}),
|
||||
}),
|
||||
query: t.Object({
|
||||
code: t.String({ examples: ["4/0AY0e-xxxxxxxxx"] }),
|
||||
callbackURI: t.String({ examples: ["https://example.com/auth/github/callback"] }),
|
||||
}),
|
||||
detail: {
|
||||
summary: "GitHub OAuth callback endpoint",
|
||||
description:
|
||||
"Handles the callback from GitHub OAuth and processes the authentication response. This endpoint also processes the account provisioning if the user is logging in for the first time.",
|
||||
responses: {
|
||||
200: {
|
||||
description: "Authentication successful",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
success: {
|
||||
type: "boolean",
|
||||
example: true,
|
||||
},
|
||||
status: {
|
||||
type: "number",
|
||||
example: 200,
|
||||
},
|
||||
message: {
|
||||
type: "string",
|
||||
example: "Authentication successful",
|
||||
},
|
||||
data: {
|
||||
type: "object",
|
||||
properties: {
|
||||
authToken: {
|
||||
type: "string",
|
||||
description: "JWT token for authenticated user",
|
||||
example: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} satisfies AppRouteSchema;
|
||||
@ -1,54 +0,0 @@
|
||||
import { t } from "elysia";
|
||||
import { AppRouteSchema } from "../../../helpers/types/AppRouteSchema";
|
||||
|
||||
export const githubRequestSchema = {
|
||||
query: t.Object({
|
||||
callback: t.Optional(
|
||||
t.String({
|
||||
description: "The callback URL to redirect after GitHub authentication. It should be URL-encoded if provided.",
|
||||
}),
|
||||
),
|
||||
}),
|
||||
detail: {
|
||||
summary: "Initiate GitHub OAuth flow",
|
||||
description:
|
||||
"This endpoint initiates the GitHub OAuth flow by redirecting the user to GitHub's authentication page.",
|
||||
responses: {
|
||||
200: {
|
||||
description: "GitHub login URL created successfully.",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
success: {
|
||||
type: "boolean",
|
||||
default: true,
|
||||
},
|
||||
status: {
|
||||
type: "number",
|
||||
default: 200,
|
||||
},
|
||||
message: {
|
||||
type: "string",
|
||||
default: "GitHub login URL created successfully.",
|
||||
},
|
||||
data: {
|
||||
type: "object",
|
||||
properties: {
|
||||
endpointUrl: {
|
||||
type: "string",
|
||||
description: "The URL to redirect the user for GitHub authentication.",
|
||||
example:
|
||||
"https://github.com/login/oauth/authorize?client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&response_type=code&scope=user:email",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} satisfies AppRouteSchema;
|
||||
@ -1,58 +0,0 @@
|
||||
import { t } from "elysia";
|
||||
import { AppRouteSchema } from "../../../helpers/types/AppRouteSchema";
|
||||
|
||||
export const googleCallbackSchema = {
|
||||
headers: t.Object({
|
||||
"x-client-info": t.String({
|
||||
examples: [
|
||||
'{"os":"Windows","osVersion":"10","browser":"Chrome","browserVersion":"89.0.4389.82","deviceType":"Desktop","ip":"192.168.1.1"}',
|
||||
],
|
||||
}),
|
||||
}),
|
||||
query: t.Object({
|
||||
code: t.String({ examples: ["4/0AY0e-xxxxxxxxx"] }),
|
||||
state: t.String({ examples: ["random_state_string"] }),
|
||||
callbackURI: t.String({ examples: ["https://example.com/auth/google/callback"] }),
|
||||
}),
|
||||
detail: {
|
||||
summary: "Google OAuth callback endpoint",
|
||||
description:
|
||||
"Handles the callback from Google OAuth and processes the authentication response. This endpoint also processes the account provisioning if the user is logging in for the first time.",
|
||||
responses: {
|
||||
200: {
|
||||
description: "Authentication successful",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
success: {
|
||||
type: "boolean",
|
||||
example: true,
|
||||
},
|
||||
status: {
|
||||
type: "number",
|
||||
example: 200,
|
||||
},
|
||||
message: {
|
||||
type: "string",
|
||||
example: "Authentication successful",
|
||||
},
|
||||
data: {
|
||||
type: "object",
|
||||
properties: {
|
||||
authToken: {
|
||||
type: "string",
|
||||
description: "JWT token for authenticated user",
|
||||
example: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} satisfies AppRouteSchema;
|
||||
@ -1,54 +0,0 @@
|
||||
import { t } from "elysia";
|
||||
import { AppRouteSchema } from "../../../helpers/types/AppRouteSchema";
|
||||
|
||||
export const googleRequestSchema = {
|
||||
query: t.Object({
|
||||
callback: t.Optional(
|
||||
t.String({
|
||||
description: "The callback URL to redirect after Google authentication. It should be URL-encoded if provided.",
|
||||
}),
|
||||
),
|
||||
}),
|
||||
detail: {
|
||||
summary: "Initiate Google OAuth flow",
|
||||
description:
|
||||
"This endpoint initiates the Google OAuth flow by redirecting the user to Google's authentication page.",
|
||||
responses: {
|
||||
200: {
|
||||
description: "Google login URL created successfully.",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
success: {
|
||||
type: "boolean",
|
||||
default: true,
|
||||
},
|
||||
status: {
|
||||
type: "number",
|
||||
default: 200,
|
||||
},
|
||||
message: {
|
||||
type: "string",
|
||||
default: "Google login URL created successfully.",
|
||||
},
|
||||
data: {
|
||||
type: "object",
|
||||
properties: {
|
||||
endpointUrl: {
|
||||
type: "string",
|
||||
description: "The URL to redirect the user for Google authentication.",
|
||||
example:
|
||||
"https://accounts.google.com/o/oauth2/v2/auth?client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&response_type=code&scope=email%20profile",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} satisfies AppRouteSchema;
|
||||
@ -1,97 +0,0 @@
|
||||
import { AppRouteSchema } from "../../../helpers/types/AppRouteSchema";
|
||||
|
||||
export const logoutSchema = {
|
||||
detail: {
|
||||
summary: "Logout endpoint",
|
||||
description: "Logs out the authenticated user by invalidating their session or token.",
|
||||
responses: {
|
||||
200: {
|
||||
description: "Logout successful",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
success: {
|
||||
type: "boolean",
|
||||
example: true,
|
||||
},
|
||||
status: {
|
||||
type: "number",
|
||||
example: 200,
|
||||
},
|
||||
message: {
|
||||
type: "string",
|
||||
example: "Logout successful",
|
||||
},
|
||||
data: {
|
||||
type: "object",
|
||||
description: "Details about the logout operation. This only returned in development environment.",
|
||||
properties: {
|
||||
id: {
|
||||
type: "string",
|
||||
example: "123e4567-e89b-12d3-a456-426614174000",
|
||||
},
|
||||
isAuthenticated: {
|
||||
type: "boolean",
|
||||
example: false,
|
||||
},
|
||||
validUntil: {
|
||||
type: "string",
|
||||
format: "date-time",
|
||||
example: "2024-12-31T23:59:59Z",
|
||||
},
|
||||
userId: {
|
||||
type: "string",
|
||||
example: "user_12345",
|
||||
},
|
||||
deletedAt: {
|
||||
type: "string",
|
||||
format: "date-time",
|
||||
example: "2024-01-02T12:00:00Z",
|
||||
},
|
||||
createdAt: {
|
||||
type: "string",
|
||||
format: "date-time",
|
||||
example: "2024-01-01T12:00:00Z",
|
||||
},
|
||||
updatedAt: {
|
||||
type: "string",
|
||||
format: "date-time",
|
||||
example: "2024-01-02T12:00:00Z",
|
||||
},
|
||||
deviceType: {
|
||||
type: "string",
|
||||
example: "Desktop",
|
||||
},
|
||||
deviceOs: {
|
||||
type: "string",
|
||||
example: "Windows 10",
|
||||
},
|
||||
deviceIp: {
|
||||
type: "string",
|
||||
example: "192.168.1.1",
|
||||
},
|
||||
browser: {
|
||||
type: "string",
|
||||
example: "Chrome 89.0.4389.82",
|
||||
},
|
||||
isOnline: {
|
||||
type: "boolean",
|
||||
example: false,
|
||||
},
|
||||
lastOnline: {
|
||||
type: "string",
|
||||
format: "date-time",
|
||||
example: "2024-01-02T12:00:00Z",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} satisfies AppRouteSchema;
|
||||
@ -1,22 +0,0 @@
|
||||
import { Context, Static } from "elysia";
|
||||
import { returnWriteResponse } from "../../../helpers/callback/httpResponse";
|
||||
import { addItemToCollectionBySytemSchema } from "../schemas/addItemToCollectionBySytem.schema";
|
||||
import { addItemToCollectionBySystemService } from "../services/addItemToCollectionBySystem.service";
|
||||
import { mainErrorHandler } from "../../../helpers/error/handler";
|
||||
|
||||
export const addItemToCollectionBySytemController = async (ctx: {
|
||||
set: Context["set"];
|
||||
headers: Static<typeof addItemToCollectionBySytemSchema.headers>;
|
||||
body: Static<typeof addItemToCollectionBySytemSchema.body>;
|
||||
}) => {
|
||||
try {
|
||||
const savedItem = await addItemToCollectionBySystemService({
|
||||
cookie: ctx.headers.cookie,
|
||||
collectionName: ctx.body.name,
|
||||
mediaId: ctx.body.itemId,
|
||||
});
|
||||
return returnWriteResponse(ctx.set, 200, "Item added to collection successfully", savedItem);
|
||||
} catch (error) {
|
||||
return mainErrorHandler(ctx.set, error);
|
||||
}
|
||||
};
|
||||
@ -1,22 +0,0 @@
|
||||
import { Context, Static } from "elysia";
|
||||
import { mainErrorHandler } from "../../../helpers/error/handler";
|
||||
import { returnWriteResponse } from "../../../helpers/callback/httpResponse";
|
||||
import { removeItemFromCollectionBySystemService } from "../services/removeItemFromCollectionBySystem.service";
|
||||
import { removeItemFromCollectionBySytemSchema } from "../schemas/removeItemFromCollectionBySytem.schema";
|
||||
|
||||
export const removeItemFromCollectionBySytemController = async (ctx: {
|
||||
set: Context["set"];
|
||||
headers: Static<typeof removeItemFromCollectionBySytemSchema.headers>;
|
||||
body: Static<typeof removeItemFromCollectionBySytemSchema.body>;
|
||||
}) => {
|
||||
try {
|
||||
const removedItem = await removeItemFromCollectionBySystemService({
|
||||
cookie: ctx.headers.cookie,
|
||||
collectionName: ctx.body.name,
|
||||
mediaId: ctx.body.itemId,
|
||||
});
|
||||
return returnWriteResponse(ctx.set, 200, "Item removed from collection successfully", removedItem);
|
||||
} catch (error) {
|
||||
return mainErrorHandler(ctx.set, error);
|
||||
}
|
||||
};
|
||||
@ -1,9 +0,0 @@
|
||||
import Elysia from "elysia";
|
||||
import { addItemToCollectionBySytemController } from "./controllers/addItemToCollectionBySytem.controller";
|
||||
import { addItemToCollectionBySytemSchema } from "./schemas/addItemToCollectionBySytem.schema";
|
||||
import { removeItemFromCollectionBySytemController } from "./controllers/removeItemFromCollectionBySytem.controller";
|
||||
import { removeItemFromCollectionBySytemSchema } from "./schemas/removeItemFromCollectionBySytem.schema";
|
||||
|
||||
export const collectionModule = new Elysia({ prefix: "/collections", tags: ["Collections"] })
|
||||
.post("/sys", addItemToCollectionBySytemController, addItemToCollectionBySytemSchema)
|
||||
.delete("/sys", removeItemFromCollectionBySytemController, removeItemFromCollectionBySytemSchema);
|
||||
@ -1,31 +0,0 @@
|
||||
import slugify from "slugify";
|
||||
import { AppError } from "../../../helpers/error/instances/app";
|
||||
import { prisma } from "../../../utils/databases/prisma/connection";
|
||||
|
||||
export type DeleteUserCollectionBySystemPayload = {
|
||||
userId: string;
|
||||
collectionName: string;
|
||||
itemId: string;
|
||||
};
|
||||
|
||||
export const deleteItemInUserCollectionBySystemRepository = async (payload: DeleteUserCollectionBySystemPayload) => {
|
||||
try {
|
||||
return await prisma.collection.update({
|
||||
where: {
|
||||
slug_ownerId: {
|
||||
slug: slugify(payload.collectionName, { lower: true }),
|
||||
ownerId: payload.userId,
|
||||
},
|
||||
},
|
||||
data: {
|
||||
media_saved: {
|
||||
deleteMany: {
|
||||
mediaId: payload.itemId,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
throw new AppError(500, "Failed to remove item from collection", error);
|
||||
}
|
||||
};
|
||||
@ -1,60 +0,0 @@
|
||||
import slugify from "slugify";
|
||||
import { AppError } from "../../../helpers/error/instances/app";
|
||||
import { prisma } from "../../../utils/databases/prisma/connection";
|
||||
import { generateUUIDv7 } from "../../../helpers/databases/uuidv7";
|
||||
import { Prisma } from "@prisma/client";
|
||||
|
||||
export interface UpsertUserCollectionRepositoryPayload {
|
||||
userId: string;
|
||||
collectionName: string;
|
||||
mediaConnectId: string;
|
||||
}
|
||||
|
||||
export const upsertUserCollectionBySystemRepository = async (payload: UpsertUserCollectionRepositoryPayload) => {
|
||||
try {
|
||||
return await prisma.collection.upsert({
|
||||
where: {
|
||||
slug_ownerId: {
|
||||
slug: slugify(payload.collectionName, { lower: true }),
|
||||
ownerId: payload.userId,
|
||||
},
|
||||
},
|
||||
update: {
|
||||
media_saved: {
|
||||
create: {
|
||||
id: generateUUIDv7(),
|
||||
media: {
|
||||
connect: {
|
||||
id: payload.mediaConnectId,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
create: {
|
||||
id: generateUUIDv7(),
|
||||
name: payload.collectionName,
|
||||
slug: slugify(payload.collectionName, { lower: true }),
|
||||
owner: {
|
||||
connect: {
|
||||
id: payload.userId,
|
||||
},
|
||||
},
|
||||
media_saved: {
|
||||
create: {
|
||||
id: generateUUIDv7(),
|
||||
media: {
|
||||
connect: {
|
||||
id: payload.mediaConnectId,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === "P2002")
|
||||
throw new AppError(400, "Media item is already in the collection");
|
||||
throw new AppError(500, "Failed to upsert user collection");
|
||||
}
|
||||
};
|
||||
@ -1,33 +0,0 @@
|
||||
import { t } from "elysia";
|
||||
import { AppRouteSchema } from "../../../helpers/types/AppRouteSchema";
|
||||
|
||||
export const addItemToCollectionBySytemSchema = {
|
||||
headers: t.Object({
|
||||
cookie: t.String({ description: "Authentication token in cookie format, e.g., auth_token=your_jwt_token;" }),
|
||||
}),
|
||||
body: t.Object({
|
||||
name: t.String({ description: "Name of the collection to which the item will be added" }),
|
||||
itemId: t.String({ description: "ID of the item to be added to the collection", examples: ["12345"] }),
|
||||
}),
|
||||
detail: {
|
||||
summary: "Add an item to a collection",
|
||||
description: "Adds a specified item to a collection identified by its name.",
|
||||
responses: {
|
||||
200: {
|
||||
description: "The item was successfully added to the collection.",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
success: { type: "boolean", example: true },
|
||||
status: { type: "number", example: 200 },
|
||||
message: { type: "string", example: "Item added to collection successfully" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} satisfies AppRouteSchema;
|
||||
@ -1,33 +0,0 @@
|
||||
import { t } from "elysia";
|
||||
import { AppRouteSchema } from "../../../helpers/types/AppRouteSchema";
|
||||
|
||||
export const removeItemFromCollectionBySytemSchema = {
|
||||
headers: t.Object({
|
||||
cookie: t.String({ description: "Authentication token in cookie format, e.g., auth_token=your_jwt_token;" }),
|
||||
}),
|
||||
body: t.Object({
|
||||
name: t.String({ description: "Name of the collection to which the item will be added" }),
|
||||
itemId: t.String({ description: "ID of the item to be added to the collection", examples: ["12345"] }),
|
||||
}),
|
||||
detail: {
|
||||
summary: "Remove an item from a collection",
|
||||
description: "Removes a specified item from a collection identified by its name.",
|
||||
responses: {
|
||||
200: {
|
||||
description: "The item was successfully removed from the collection.",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
success: { type: "boolean", example: true },
|
||||
status: { type: "number", example: 200 },
|
||||
message: { type: "string", example: "Item removed from collection successfully" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} satisfies AppRouteSchema;
|
||||
@ -1,24 +0,0 @@
|
||||
import { parse } from "cookie";
|
||||
import { tokenValidationService } from "../../auth/services/http/tokenValidation.service";
|
||||
import { ErrorForwarder } from "../../../helpers/error/instances/forwarder";
|
||||
import { upsertUserCollectionBySystemRepository } from "../repositories/upsertUserCollectionBySystem.repository";
|
||||
|
||||
export type AddItemToCollectionPayload = {
|
||||
cookie: string;
|
||||
collectionName: string;
|
||||
mediaId: string;
|
||||
};
|
||||
|
||||
export const addItemToCollectionBySystemService = async (payload: AddItemToCollectionPayload) => {
|
||||
try {
|
||||
const { auth_token } = parse(payload.cookie);
|
||||
const userData = await tokenValidationService(auth_token as string);
|
||||
return await upsertUserCollectionBySystemRepository({
|
||||
userId: userData.user.id,
|
||||
collectionName: payload.collectionName,
|
||||
mediaConnectId: payload.mediaId,
|
||||
});
|
||||
} catch (error) {
|
||||
ErrorForwarder(error);
|
||||
}
|
||||
};
|
||||
@ -1,24 +0,0 @@
|
||||
import { parse } from "cookie";
|
||||
import { ErrorForwarder } from "../../../helpers/error/instances/forwarder";
|
||||
import { tokenValidationService } from "../../auth/services/http/tokenValidation.service";
|
||||
import { deleteItemInUserCollectionBySystemRepository } from "../repositories/deleteItemInUserCollectionBySystem.repository";
|
||||
|
||||
export type RemoveItemFromCollectionPayload = {
|
||||
cookie: string;
|
||||
collectionName: string;
|
||||
mediaId: string;
|
||||
};
|
||||
|
||||
export const removeItemFromCollectionBySystemService = async (payload: RemoveItemFromCollectionPayload) => {
|
||||
try {
|
||||
const { auth_token } = parse(payload.cookie);
|
||||
const { user } = await tokenValidationService(auth_token as string);
|
||||
return await deleteItemInUserCollectionBySystemRepository({
|
||||
userId: user.id,
|
||||
collectionName: payload.collectionName,
|
||||
itemId: payload.mediaId,
|
||||
});
|
||||
} catch (error) {
|
||||
ErrorForwarder(error);
|
||||
}
|
||||
};
|
||||
@ -1,14 +1,17 @@
|
||||
import { AppError } from "../../../../helpers/error/instances/app";
|
||||
import { ErrorForwarder } from "../../../../helpers/error/instances/forwarder";
|
||||
import { selectMediaIdFromSlugRepository } from "../../../media/repositories/SELECT/selectMediaIdFromSlug.repository";
|
||||
import { getMediaIdFromSlugRepository } from "../../../media/repositories/GET/getMediaIdFromSlug.repository";
|
||||
import { GetEpisodeDetailsParams } from "../../controllers/getEpisodeDetails.controller";
|
||||
import { getEpisodeDetailsRepository } from "../../repositories/GET/getEpisodeDetails.repository";
|
||||
|
||||
export const getEpisodeDetailsService = async (params: GetEpisodeDetailsParams) => {
|
||||
export const getEpisodeDetailsService = async (
|
||||
params: GetEpisodeDetailsParams,
|
||||
) => {
|
||||
try {
|
||||
if (!params.mediaSlug || !params.episode) throw new AppError(400, "Media slug and episode are required.");
|
||||
if (!params.mediaSlug || !params.episode)
|
||||
throw new AppError(400, "Media slug and episode are required.");
|
||||
|
||||
const mediaId = await selectMediaIdFromSlugRepository(params.mediaSlug);
|
||||
const mediaId = await getMediaIdFromSlugRepository(params.mediaSlug);
|
||||
if (!mediaId?.id) throw new AppError(404, "Media not found.");
|
||||
|
||||
const result = await getEpisodeDetailsRepository({
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
import { Context } from "elysia";
|
||||
import { returnWriteResponse } from "../../../helpers/callback/httpResponse";
|
||||
import { clearHeroBannerService } from "../services/clearHeroBanner.service";
|
||||
|
||||
export const clearHeroBannerController = async (ctx: { set: Context["set"] }) => {
|
||||
const cacheCleared = await clearHeroBannerService();
|
||||
return returnWriteResponse(ctx.set, 200, "Hero banner cache flushed successfully", cacheCleared);
|
||||
};
|
||||
@ -1,4 +0,0 @@
|
||||
import Elysia from "elysia";
|
||||
import { clearHeroBannerController } from "./controllers/clearHeroBanner.controller";
|
||||
|
||||
export const flushCacheModule = new Elysia({ prefix: "/flush-cache" }).put("/hero-banner", clearHeroBannerController);
|
||||
@ -1,12 +0,0 @@
|
||||
import { redisKey } from "../../../config/redis/key";
|
||||
import { AppError } from "../../../helpers/error/instances/app";
|
||||
import { redis } from "../../../utils/databases/redis/connection";
|
||||
|
||||
export const clearHeroBannerService = async () => {
|
||||
try {
|
||||
const cache = await redis.del(redisKey.find((key) => key.name === "HERO_BANNER")?.key || "");
|
||||
return cache > 0; // Returns true if cache was cleared, false if it was not found
|
||||
} catch (error) {
|
||||
throw new AppError(500, "Failed to clear hero banner cache", error);
|
||||
}
|
||||
};
|
||||
@ -1,16 +1,17 @@
|
||||
import { Context, Static } from "elysia";
|
||||
import { Context } from "elysia";
|
||||
import { mainErrorHandler } from "../../../helpers/error/handler";
|
||||
import { returnReadResponse } from "../../../helpers/callback/httpResponse";
|
||||
import { getActiveHeroBannerService } from "../services/getActiveHeroBanner.service";
|
||||
import { getActiveHeroBannerSchema } from "../schemas/getActiveHeroBanner.schema";
|
||||
|
||||
export const getActiveHeroBannerController = async (ctx: {
|
||||
set: Context["set"];
|
||||
header: Static<typeof getActiveHeroBannerSchema.headers>;
|
||||
}) => {
|
||||
export const getActiveHeroBannerController = async (ctx: Context) => {
|
||||
try {
|
||||
const response = await getActiveHeroBannerService({ cookie: ctx.header?.cookie });
|
||||
return returnReadResponse(ctx.set, 200, "Active hero banners fetched successfully", response);
|
||||
const response = await getActiveHeroBannerService();
|
||||
return returnReadResponse(
|
||||
ctx.set,
|
||||
200,
|
||||
"Active hero banners fetched successfully",
|
||||
response,
|
||||
);
|
||||
} catch (error) {
|
||||
return mainErrorHandler(ctx.set, error);
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { AppError } from "../../../../helpers/error/instances/app";
|
||||
import { prisma } from "../../../../utils/databases/prisma/connection";
|
||||
|
||||
export const findAllActiveHeroBannerRepository = async (userId?: string) => {
|
||||
export const findAllActiveHeroBannerRepository = async () => {
|
||||
try {
|
||||
return await prisma.heroBanner.findMany({
|
||||
where: {
|
||||
@ -20,36 +20,6 @@ export const findAllActiveHeroBannerRepository = async (userId?: string) => {
|
||||
startDate: "asc",
|
||||
},
|
||||
],
|
||||
select: {
|
||||
orderPriority: true,
|
||||
imageUrl: true,
|
||||
media: {
|
||||
select: {
|
||||
id: true,
|
||||
title: true,
|
||||
slug: true,
|
||||
pictureLarge: true,
|
||||
synopsis: true,
|
||||
genres: {
|
||||
select: {
|
||||
slug: true,
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
_count: {
|
||||
select: {
|
||||
inCollections: {
|
||||
where: {
|
||||
collection: {
|
||||
ownerId: userId,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
throw new AppError(500, "Failed to fetch active hero banners", error);
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
import { t } from "elysia";
|
||||
import { AppRouteSchema } from "../../../helpers/types/AppRouteSchema";
|
||||
|
||||
export const getActiveHeroBannerSchema = {
|
||||
headers: t.Object({
|
||||
cookie: t.Optional(t.String()),
|
||||
}),
|
||||
} satisfies AppRouteSchema;
|
||||
@ -1,44 +1,33 @@
|
||||
import { redisKey } from "../../../config/redis/key";
|
||||
import { AppError } from "../../../helpers/error/instances/app";
|
||||
import { ErrorForwarder } from "../../../helpers/error/instances/forwarder";
|
||||
import { tokenValidationService } from "../../auth/services/http/tokenValidation.service";
|
||||
import { redis } from "../../../utils/databases/redis/connection";
|
||||
import { findSystemPreferenceService } from "../../systemPreference/services/internal/findSystemPreference.service";
|
||||
import { findAllActiveHeroBannerRepository } from "../repositories/GET/findAllActiveHeroBanner.repository";
|
||||
|
||||
export const getActiveHeroBannerService = async ({ cookie }: { cookie?: string }) => {
|
||||
export const getActiveHeroBannerService = async () => {
|
||||
try {
|
||||
const userId = cookie ? (await tokenValidationService(cookie)).user.id : undefined;
|
||||
|
||||
// Check if Hero Banner is enabled in system preferences
|
||||
const isHeroBannerEnabled = await findSystemPreferenceService("HERO_BANNER_ENABLED", "boolean");
|
||||
if (!isHeroBannerEnabled) throw new AppError(403, "Hero Banner is disabled");
|
||||
const isHeroBannerEnabled = await findSystemPreferenceService(
|
||||
"HERO_BANNER_ENABLED",
|
||||
"boolean",
|
||||
);
|
||||
if (!isHeroBannerEnabled)
|
||||
throw new AppError(403, "Hero Banner is disabled");
|
||||
|
||||
// Don’t implement caching just yet; implement collection caching first, then implement banner caching.
|
||||
// Please note that currently, a database query is still required to check the collections.
|
||||
// // Try to get active banners from Redis cache
|
||||
// const cachedBanners = await redis.get(`${redisKey.filter((key) => key.name === "HERO_BANNER")[0].key}`);
|
||||
// if (cachedBanners) return JSON.parse(cachedBanners);
|
||||
// Try to get active banners from Redis cache
|
||||
const cachedBanners = await redis.get(
|
||||
`${redisKey.filter((key) => key.name === "HERO_BANNER")[0].key}`,
|
||||
);
|
||||
if (cachedBanners) return JSON.parse(cachedBanners);
|
||||
|
||||
// If not in cache, fetch from database and cache the result
|
||||
const activeBanners = await findAllActiveHeroBannerRepository(userId);
|
||||
const constructedBanners = activeBanners.map((banner) => ({
|
||||
id: banner.media.id,
|
||||
title: banner.media.title,
|
||||
slug: banner.media.slug,
|
||||
imageUrl: banner.imageUrl || banner.media.pictureLarge,
|
||||
synopsis: banner.media.synopsis,
|
||||
genres: banner.media.genres.map((genre) => ({
|
||||
slug: genre.slug,
|
||||
name: genre.name,
|
||||
})),
|
||||
isInCollection: banner.media._count.inCollections > 0,
|
||||
}));
|
||||
|
||||
// await redis.set(
|
||||
// `${redisKey.filter((key) => key.name === "HERO_BANNER")[0].key}`,
|
||||
// JSON.stringify(constructedBanners),
|
||||
// );
|
||||
|
||||
return constructedBanners;
|
||||
const activeBanners = await findAllActiveHeroBannerRepository();
|
||||
await redis.set(
|
||||
`${redisKey.filter((key) => key.name === "HERO_BANNER")[0].key}`,
|
||||
JSON.stringify(activeBanners),
|
||||
);
|
||||
return activeBanners;
|
||||
} catch (error) {
|
||||
ErrorForwarder(error);
|
||||
}
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { AppError } from "../../../helpers/error/instances/app";
|
||||
import { prisma } from "../../../utils/databases/prisma/connection";
|
||||
import { generateUUIDv7 } from "../../../helpers/databases/uuidv7";
|
||||
import { SystemAccountId } from "../../../config/account/system";
|
||||
import { Static } from "elysia";
|
||||
import { createHeroBannerSchema } from "../schemas/createHeroBanner.schema";
|
||||
import { Prisma } from "@prisma/client";
|
||||
|
||||
export const insertHeroBannerRepository = async (payload: Static<typeof createHeroBannerSchema.body>) => {
|
||||
export const insertHeroBannerRepository = async (
|
||||
payload: Omit<Prisma.HeroBannerCreateInput, "id" | "createdBy">,
|
||||
) => {
|
||||
try {
|
||||
return await prisma.heroBanner.create({
|
||||
data: {
|
||||
@ -16,9 +16,6 @@ export const insertHeroBannerRepository = async (payload: Static<typeof createHe
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === "P2002") {
|
||||
throw new AppError(400, "A hero banner with the order priority already exists", error);
|
||||
}
|
||||
throw new AppError(500, "Failed to insert hero banner", error);
|
||||
}
|
||||
};
|
||||
|
||||
@ -3,18 +3,45 @@ import { AppRouteSchema } from "../../../helpers/types/AppRouteSchema";
|
||||
|
||||
export const createHeroBannerSchema = {
|
||||
body: t.Object({
|
||||
orderPriority: t.Optional(
|
||||
t.Number({ description: "The priority order of the hero banner. Lower numbers indicate higher priority." }),
|
||||
),
|
||||
mediaId: t.String({ description: "The ID of the media associated with the hero banner" }),
|
||||
imageUrl: t.Optional(
|
||||
t.String({
|
||||
description:
|
||||
"The URL of the image used in the hero banner. If not provided, a thumbnail image of the media will be used.",
|
||||
isClickable: t.Optional(
|
||||
t.Boolean({
|
||||
description: "Indicates whether the hero banner is clickable",
|
||||
}),
|
||||
),
|
||||
startDate: t.Date({ description: "The start date for the hero banner in ISO 8601 format" }),
|
||||
endDate: t.Date({ description: "The end date for the hero banner in ISO 8601 format" }),
|
||||
title: t.Optional(
|
||||
t.String({
|
||||
description: "The title of the hero banner",
|
||||
}),
|
||||
),
|
||||
tags: t.Array(t.String(), {
|
||||
description: "An array of tags associated with the hero banner",
|
||||
}),
|
||||
description: t.Optional(
|
||||
t.String({
|
||||
description: "A brief description of the hero banner",
|
||||
}),
|
||||
),
|
||||
buttonContent: t.Optional(
|
||||
t.String({
|
||||
description: "The text content of the button on the hero banner",
|
||||
}),
|
||||
),
|
||||
buttonLink: t.Optional(
|
||||
t.String({
|
||||
description: "The URL that the button on the hero banner links to",
|
||||
}),
|
||||
),
|
||||
imageUrl: t.Optional(
|
||||
t.String({
|
||||
description: "The URL of the image used in the hero banner",
|
||||
}),
|
||||
),
|
||||
startDate: t.String({
|
||||
description: "The start date for the hero banner in ISO 8601 format",
|
||||
}),
|
||||
endDate: t.String({
|
||||
description: "The end date for the hero banner in ISO 8601 format",
|
||||
}),
|
||||
}),
|
||||
detail: {
|
||||
summary: "Create a new hero banner",
|
||||
@ -37,16 +64,17 @@ export const createHeroBannerSchema = {
|
||||
"The created hero banner object. This field is returned only if the environment is running in development mode.",
|
||||
properties: {
|
||||
id: { type: "string", description: "The ID of the created hero banner" },
|
||||
orderPriority: {
|
||||
type: "number",
|
||||
description: "The priority order of the hero banner. Lower numbers indicate higher priority.",
|
||||
},
|
||||
mediaId: { type: "string", description: "The ID of the media associated with the hero banner" },
|
||||
imageUrl: {
|
||||
type: "string",
|
||||
description:
|
||||
"The URL of the image used in the hero banner. If not provided, a thumbnail image of the media will be used.",
|
||||
isClickable: { type: "boolean", description: "Indicates whether the hero banner is clickable" },
|
||||
title: { type: "string", description: "The title of the hero banner" },
|
||||
tags: {
|
||||
type: "array",
|
||||
items: { type: "string" },
|
||||
description: "An array of tags associated with the hero banner",
|
||||
},
|
||||
description: { type: "string", description: "A brief description of the hero banner" },
|
||||
buttonContent: { type: "string", description: "The text content of the button on the hero banner" },
|
||||
buttonLink: { type: "string", description: "The URL that the button on the hero banner links to" },
|
||||
imageUrl: { type: "string", description: "The URL of the image used in the hero banner" },
|
||||
startDate: {
|
||||
type: "string",
|
||||
format: "date-time",
|
||||
|
||||
@ -1,20 +1,27 @@
|
||||
import { ErrorForwarder } from "../../../../helpers/error/instances/forwarder";
|
||||
import { MediaEpisodeInfoResponse } from "../../types/mediaEpisodeInfo.type";
|
||||
import { getMediaByMalIdRepository } from "../../../media/repositories/GET/getMediaByMalId.repository";
|
||||
import { AppError } from "../../../../helpers/error/instances/app";
|
||||
import { SystemAccountId } from "../../../../config/account/system";
|
||||
import { bulkInsertEpisodesRepository } from "../../repositories/bulkInsertEpisodes.repository";
|
||||
import { getEpisodeReferenceAPI } from "../../../../config/apis/jikan/episode.reference";
|
||||
import { selectMediaByMalIdRepository } from "../../../media/repositories/SELECT/selectMediaByMalId.repository";
|
||||
|
||||
export const bulkInsertEpisodeService = async (mal_id: number, page: number = 1) => {
|
||||
export const bulkInsertEpisodeService = async (
|
||||
mal_id: number,
|
||||
page: number = 1,
|
||||
) => {
|
||||
try {
|
||||
const episodeAPI = getEpisodeReferenceAPI(mal_id);
|
||||
const episodeData: MediaEpisodeInfoResponse = await fetch(
|
||||
`${episodeAPI.baseURL}${episodeAPI.getEpisodeList}?page=${page}`,
|
||||
).then((res) => res.json());
|
||||
|
||||
const mediaData = await selectMediaByMalIdRepository(mal_id);
|
||||
if (!mediaData) throw new AppError(404, `Media with Mal ID ${mal_id} not found in database`);
|
||||
const mediaData = await getMediaByMalIdRepository(mal_id);
|
||||
if (!mediaData)
|
||||
throw new AppError(
|
||||
404,
|
||||
`Media with Mal ID ${mal_id} not found in database`,
|
||||
);
|
||||
|
||||
const insertedEpisodeData = [];
|
||||
episodeData.data.forEach(async (episode) => {
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { Static } from "elysia";
|
||||
import { ErrorForwarder } from "../../../../helpers/error/instances/forwarder";
|
||||
import { CreateHeroBannerRequestBody } from "../../controllers/createHeroBanner.controller";
|
||||
import { insertHeroBannerRepository } from "../../repositories/insertHeroBanner.repository";
|
||||
import { createHeroBannerSchema } from "../../schemas/createHeroBanner.schema";
|
||||
|
||||
export const createHeroBannerService = async (payload: Static<typeof createHeroBannerSchema.body>) => {
|
||||
export const createHeroBannerService = async (
|
||||
payload: CreateHeroBannerRequestBody,
|
||||
) => {
|
||||
try {
|
||||
return await insertHeroBannerRepository(payload);
|
||||
} catch (error) {
|
||||
|
||||
@ -1,16 +1,19 @@
|
||||
import { Context, Static } from "elysia";
|
||||
import { Context } from "elysia";
|
||||
import { mainErrorHandler } from "../../../helpers/error/handler";
|
||||
import { getAllMediaService } from "../services/http/getAllMedia.service";
|
||||
import { returnReadResponse } from "../../../helpers/callback/httpResponse";
|
||||
import { getAllMediaSchema } from "../schemas/getAllMedia.schema";
|
||||
|
||||
export const getAllMediaController = async (ctx: {
|
||||
set: Context["set"];
|
||||
query: Static<typeof getAllMediaSchema.query>;
|
||||
}) => {
|
||||
export const getAllMediaController = async (
|
||||
ctx: Context & { query: { page: string } },
|
||||
) => {
|
||||
try {
|
||||
const mediaData = await getAllMediaService(ctx.query.page);
|
||||
return returnReadResponse(ctx.set, 200, "Media fetched successfully", mediaData);
|
||||
return returnReadResponse(
|
||||
ctx.set,
|
||||
200,
|
||||
"Media fetched successfully",
|
||||
mediaData,
|
||||
);
|
||||
} catch (error) {
|
||||
return mainErrorHandler(ctx.set, error);
|
||||
}
|
||||
|
||||
@ -1,17 +0,0 @@
|
||||
import { Context, Static } from "elysia";
|
||||
import { mainErrorHandler } from "../../../helpers/error/handler";
|
||||
import { getMediaBySlugSchema } from "../schemas/getMediaBySlug.schema";
|
||||
import { getMediaBySlugService } from "../services/http/getMediaBySlug.service";
|
||||
import { returnReadResponse } from "../../../helpers/callback/httpResponse";
|
||||
|
||||
export const getMediaBySlugController = async (ctx: {
|
||||
set: Context["set"];
|
||||
params: Static<typeof getMediaBySlugSchema.params>;
|
||||
}) => {
|
||||
try {
|
||||
const mediaData = await getMediaBySlugService(ctx.params.slug);
|
||||
return returnReadResponse(ctx.set, 200, "Media fetched successfully", mediaData);
|
||||
} catch (error) {
|
||||
return mainErrorHandler(ctx.set, error);
|
||||
}
|
||||
};
|
||||
@ -1,9 +1,7 @@
|
||||
import Elysia from "elysia";
|
||||
import { getAllMediaController } from "./controllers/getAllMedia.controller";
|
||||
import { getMediaBySlugController } from "./controllers/getMediaBySlug.controller";
|
||||
import { getMediaBySlugSchema } from "./schemas/getMediaBySlug.schema";
|
||||
import { getAllMediaSchema } from "./schemas/getAllMedia.schema";
|
||||
|
||||
export const mediaModule = new Elysia({ prefix: "/media", tags: ["Media"] })
|
||||
.get("/", getAllMediaController, getAllMediaSchema)
|
||||
.get("/:slug", getMediaBySlugController, getMediaBySlugSchema);
|
||||
export const mediaModule = new Elysia({ prefix: "/media" }).get(
|
||||
"/",
|
||||
getAllMediaController,
|
||||
);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { AppError } from "../../../../helpers/error/instances/app";
|
||||
import { mediaModel } from "../../model";
|
||||
|
||||
export const selectAllMediaRepository = async (page: number) => {
|
||||
export const getAllMediaRepository = async (page: number) => {
|
||||
try {
|
||||
const limit = 10;
|
||||
return await mediaModel.findMany({
|
||||
@ -1,7 +1,7 @@
|
||||
import { AppError } from "../../../../helpers/error/instances/app";
|
||||
import { mediaModel } from "../../model";
|
||||
|
||||
export const selectMediaByMalIdRepository = async (mal_id: number) => {
|
||||
export const getMediaByMalIdRepository = async (mal_id: number) => {
|
||||
try {
|
||||
return await mediaModel.findUnique({
|
||||
where: { malId: mal_id },
|
||||
@ -1,7 +1,7 @@
|
||||
import { AppError } from "../../../../helpers/error/instances/app";
|
||||
import { mediaModel } from "../../model";
|
||||
|
||||
export const selectMediaIdFromSlugRepository = async (slug: string) => {
|
||||
export const getMediaIdFromSlugRepository = async (slug: string) => {
|
||||
try {
|
||||
return await mediaModel.findUnique({
|
||||
where: { slug },
|
||||
@ -1,12 +0,0 @@
|
||||
import { AppError } from "../../../../helpers/error/instances/app";
|
||||
import { prisma } from "../../../../utils/databases/prisma/connection";
|
||||
|
||||
export const selectMediaBySlugRepository = async (slug: string) => {
|
||||
try {
|
||||
return await prisma.media.findUnique({
|
||||
where: { slug },
|
||||
});
|
||||
} catch (error) {
|
||||
throw new AppError(500, "Failed to fetch media by slug", error);
|
||||
}
|
||||
};
|
||||
@ -1,58 +0,0 @@
|
||||
import { t } from "elysia";
|
||||
import { AppRouteSchema } from "../../../helpers/types/AppRouteSchema";
|
||||
|
||||
export const getAllMediaSchema = {
|
||||
query: t.Object({
|
||||
page: t.String({ description: "The page number for pagination", default: "1" }),
|
||||
}),
|
||||
detail: {
|
||||
summary: "Fetch all media items with pagination",
|
||||
description:
|
||||
"Fetch a paginated list of all media items. The 'page' query parameter can be used to specify the page number for pagination.",
|
||||
responses: {
|
||||
200: {
|
||||
description: "Media items fetched successfully",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
success: { type: "boolean", example: true },
|
||||
status: { type: "number", example: 200 },
|
||||
message: { type: "string", example: "Media fetched successfully" },
|
||||
data: {
|
||||
type: "array",
|
||||
items: {
|
||||
type: "object",
|
||||
properties: {
|
||||
status: { type: "string", example: "Finished Airing" },
|
||||
id: { type: "string", example: "12345" },
|
||||
title: { type: "string", example: "Example Media Title" },
|
||||
slug: { type: "string", example: "example-media-title" },
|
||||
malId: { type: "number", example: 67890 },
|
||||
pictureMedium: { type: "string", example: "https://example.com/medium.jpg" },
|
||||
pictureLarge: { type: "string", example: "https://example.com/large.jpg" },
|
||||
country: { type: "string", example: "JP" },
|
||||
score: { type: "number", example: 8.5 },
|
||||
startAiring: { type: "string", format: "date-time", example: "2023-01-01T00:00:00Z" },
|
||||
endAiring: { type: "string", format: "date-time", example: "2023-12-31T23:59:59Z" },
|
||||
synopsis: { type: "string", example: "This is an example synopsis of the media item." },
|
||||
ageRating: { type: "string", example: "PG-13" },
|
||||
mediaType: { type: "string", example: "Anime" },
|
||||
source: { type: "string", example: "Manga" },
|
||||
onDraft: { type: "boolean", example: false },
|
||||
uploadedBy: { type: "string", example: "admin" },
|
||||
deletedAt: { type: "string", format: "date-time", nullable: true, example: null },
|
||||
createdAt: { type: "string", format: "date-time", example: "2023-01-01T00:00:00Z" },
|
||||
updatedAt: { type: "string", format: "date-time", example: "2023-01-02T00:00:00Z" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} satisfies AppRouteSchema;
|
||||
@ -1,29 +0,0 @@
|
||||
import { t } from "elysia";
|
||||
import { AppRouteSchema } from "../../../helpers/types/AppRouteSchema";
|
||||
|
||||
export const getMediaBySlugSchema = {
|
||||
params: t.Object({
|
||||
slug: t.String({ description: "The slug of the media to fetch" }),
|
||||
}),
|
||||
detail: {
|
||||
summary: "Fetch a media item by its slug",
|
||||
description: "Fetch the specified media item using its slug. This endpoint returns the media details if found.",
|
||||
responses: {
|
||||
200: {
|
||||
description: "Media item fetched successfully",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
success: { type: "boolean", example: true },
|
||||
status: { type: "number", example: 200 },
|
||||
message: { type: "string", example: "Media fetched successfully" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} satisfies AppRouteSchema;
|
||||
@ -1,11 +1,14 @@
|
||||
import { ErrorForwarder } from "../../../../helpers/error/instances/forwarder";
|
||||
import { selectAllMediaRepository } from "../../repositories/SELECT/selectAllMedia.repository";
|
||||
import { getAllMediaRepository } from "../../repositories/GET/getAllMedia.repository";
|
||||
|
||||
export const getAllMediaService = async (pagination: string) => {
|
||||
try {
|
||||
const page = /^\d+$/.test(pagination) && Number(pagination) > 0 ? Number(pagination) : 1;
|
||||
const page =
|
||||
/^\d+$/.test(pagination) && Number(pagination) > 0
|
||||
? Number(pagination)
|
||||
: 1;
|
||||
|
||||
return selectAllMediaRepository(page);
|
||||
return getAllMediaRepository(page);
|
||||
} catch (error) {
|
||||
ErrorForwarder(error);
|
||||
}
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
import { AppError } from "../../../../helpers/error/instances/app";
|
||||
import { ErrorForwarder } from "../../../../helpers/error/instances/forwarder";
|
||||
import { selectMediaBySlugRepository } from "../../repositories/SELECT/selectMediaBySlug.repository";
|
||||
|
||||
export const getMediaBySlugService = async (slug: string) => {
|
||||
try {
|
||||
const mediaData = await selectMediaBySlugRepository(slug);
|
||||
if (!mediaData) throw new AppError(404, "Media not found with the provided slug.");
|
||||
|
||||
return mediaData;
|
||||
} catch (error) {
|
||||
ErrorForwarder(error);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user