Initial commit: YouTube Studio Flow (backend, frontend, infrastructure, docs)
This commit is contained in:
@@ -0,0 +1,347 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "PrivacyStatus" AS ENUM ('PUBLIC', 'PRIVATE', 'UNLISTED');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "LintStatus" AS ENUM ('OK', 'WARNING', 'ERROR');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "BlockType" AS ENUM ('STATIC', 'VARIABLE', 'CONDITIONAL', 'REPEATABLE', 'GLOBAL', 'CAMPAIGN', 'COLLABORATOR');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "LintSeverity" AS ENUM ('INFO', 'WARNING', 'ERROR');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "BulkJobStatus" AS ENUM ('PENDING', 'DRY_RUN', 'CONFIRMED', 'RUNNING', 'DONE', 'FAILED', 'ROLLED_BACK');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "UserRole" AS ENUM ('ADMIN', 'EDITOR', 'REVIEWER', 'READONLY');
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Video" (
|
||||
"id" TEXT NOT NULL,
|
||||
"youtubeVideoId" TEXT NOT NULL,
|
||||
"channelId" TEXT NOT NULL,
|
||||
"title" TEXT NOT NULL,
|
||||
"renderedDescription" TEXT,
|
||||
"tags" TEXT[],
|
||||
"categoryId" TEXT,
|
||||
"privacyStatus" "PrivacyStatus" NOT NULL DEFAULT 'PRIVATE',
|
||||
"publishedAt" TIMESTAMP(3),
|
||||
"scheduledAt" TIMESTAMP(3),
|
||||
"templateId" TEXT,
|
||||
"lintStatus" "LintStatus" NOT NULL DEFAULT 'OK',
|
||||
"lastSyncedAt" TIMESTAMP(3),
|
||||
"lastSyncedHash" TEXT,
|
||||
"remoteConflict" BOOLEAN NOT NULL DEFAULT false,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "Video_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "VideoConfig" (
|
||||
"id" TEXT NOT NULL,
|
||||
"videoId" TEXT NOT NULL,
|
||||
"templateId" TEXT,
|
||||
"blockOrder" JSONB NOT NULL,
|
||||
"blockOverrides" JSONB NOT NULL,
|
||||
"variableValues" JSONB NOT NULL,
|
||||
"collaboratorIds" JSONB NOT NULL,
|
||||
"version" INTEGER NOT NULL DEFAULT 1,
|
||||
"renderHash" TEXT,
|
||||
"renderedAt" TIMESTAMP(3),
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "VideoConfig_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "DescriptionBlock" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"type" "BlockType" NOT NULL,
|
||||
"content" TEXT NOT NULL,
|
||||
"language" TEXT NOT NULL DEFAULT 'de',
|
||||
"campaignId" TEXT,
|
||||
"version" INTEGER NOT NULL DEFAULT 1,
|
||||
"active" BOOLEAN NOT NULL DEFAULT true,
|
||||
"tags" TEXT[],
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "DescriptionBlock_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "BlockVersion" (
|
||||
"id" TEXT NOT NULL,
|
||||
"blockId" TEXT NOT NULL,
|
||||
"version" INTEGER NOT NULL,
|
||||
"contentSnapshot" JSONB NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"createdBy" TEXT,
|
||||
|
||||
CONSTRAINT "BlockVersion_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Template" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"defaultBlocks" JSONB NOT NULL,
|
||||
"rules" JSONB NOT NULL,
|
||||
"variables" JSONB NOT NULL,
|
||||
"version" INTEGER NOT NULL DEFAULT 1,
|
||||
"active" BOOLEAN NOT NULL DEFAULT true,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "Template_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "TemplateVersion" (
|
||||
"id" TEXT NOT NULL,
|
||||
"templateId" TEXT NOT NULL,
|
||||
"version" INTEGER NOT NULL,
|
||||
"snapshot" JSONB NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "TemplateVersion_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Collaborator" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"youtubeHandle" TEXT NOT NULL,
|
||||
"twitchLink" TEXT,
|
||||
"aliases" TEXT[],
|
||||
"active" BOOLEAN NOT NULL DEFAULT true,
|
||||
"notes" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "Collaborator_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "VideoCollaborator" (
|
||||
"videoId" TEXT NOT NULL,
|
||||
"collaboratorId" TEXT NOT NULL,
|
||||
"role" TEXT,
|
||||
"sortOrder" INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
CONSTRAINT "VideoCollaborator_pkey" PRIMARY KEY ("videoId","collaboratorId")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "SavedView" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"isGlobal" BOOLEAN NOT NULL DEFAULT false,
|
||||
"ownerId" TEXT,
|
||||
"queryJson" JSONB NOT NULL,
|
||||
"columnsJson" JSONB NOT NULL,
|
||||
"sortJson" JSONB,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "SavedView_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "LintResult" (
|
||||
"id" TEXT NOT NULL,
|
||||
"videoId" TEXT NOT NULL,
|
||||
"ruleCode" TEXT NOT NULL,
|
||||
"severity" "LintSeverity" NOT NULL,
|
||||
"targetField" TEXT,
|
||||
"message" TEXT NOT NULL,
|
||||
"fixSuggestion" TEXT,
|
||||
"resolvedAt" TIMESTAMP(3),
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "LintResult_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "BulkJob" (
|
||||
"id" TEXT NOT NULL,
|
||||
"type" TEXT NOT NULL,
|
||||
"initiatedBy" TEXT NOT NULL,
|
||||
"filterSnapshot" JSONB NOT NULL,
|
||||
"targetIds" TEXT[],
|
||||
"status" "BulkJobStatus" NOT NULL DEFAULT 'PENDING',
|
||||
"dryRunResult" JSONB,
|
||||
"rollbackData" JSONB,
|
||||
"totalCount" INTEGER NOT NULL,
|
||||
"successCount" INTEGER NOT NULL DEFAULT 0,
|
||||
"errorCount" INTEGER NOT NULL DEFAULT 0,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"completedAt" TIMESTAMP(3),
|
||||
|
||||
CONSTRAINT "BulkJob_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "BulkJobItem" (
|
||||
"id" TEXT NOT NULL,
|
||||
"bulkJobId" TEXT NOT NULL,
|
||||
"videoId" TEXT NOT NULL,
|
||||
"beforeSnapshot" JSONB,
|
||||
"afterSnapshot" JSONB,
|
||||
"status" TEXT NOT NULL DEFAULT 'pending',
|
||||
"errorMessage" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "BulkJobItem_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Campaign" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"startAt" TIMESTAMP(3) NOT NULL,
|
||||
"endAt" TIMESTAMP(3),
|
||||
"status" TEXT NOT NULL DEFAULT 'active',
|
||||
"notes" TEXT,
|
||||
|
||||
CONSTRAINT "Campaign_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "ImportJob" (
|
||||
"id" TEXT NOT NULL,
|
||||
"type" TEXT NOT NULL,
|
||||
"sourceName" TEXT NOT NULL,
|
||||
"mappingJson" JSONB,
|
||||
"validationReport" JSONB,
|
||||
"commitStatus" TEXT NOT NULL DEFAULT 'pending',
|
||||
"createdBy" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"committedAt" TIMESTAMP(3),
|
||||
|
||||
CONSTRAINT "ImportJob_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "ExportJob" (
|
||||
"id" TEXT NOT NULL,
|
||||
"type" TEXT NOT NULL,
|
||||
"scopeJson" JSONB NOT NULL,
|
||||
"fileReference" TEXT,
|
||||
"createdBy" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "ExportJob_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "QuotaLog" (
|
||||
"id" TEXT NOT NULL,
|
||||
"datePt" TIMESTAMP(3) NOT NULL,
|
||||
"units" INTEGER NOT NULL,
|
||||
"operation" TEXT NOT NULL,
|
||||
"entityId" TEXT,
|
||||
"videoId" TEXT,
|
||||
"bulkJobId" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "QuotaLog_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "AuditLog" (
|
||||
"id" TEXT NOT NULL,
|
||||
"actorId" TEXT NOT NULL,
|
||||
"entityType" TEXT NOT NULL,
|
||||
"entityId" TEXT NOT NULL,
|
||||
"action" TEXT NOT NULL,
|
||||
"beforeJson" JSONB,
|
||||
"afterJson" JSONB,
|
||||
"requestId" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "AuditLog_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "User" (
|
||||
"id" TEXT NOT NULL,
|
||||
"email" TEXT NOT NULL,
|
||||
"name" TEXT,
|
||||
"googleId" TEXT NOT NULL,
|
||||
"role" "UserRole" NOT NULL DEFAULT 'EDITOR',
|
||||
"youtubeAccessToken" TEXT,
|
||||
"youtubeRefreshToken" TEXT,
|
||||
"youtubeTokenExpiry" TIMESTAMP(3),
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Video_youtubeVideoId_key" ON "Video"("youtubeVideoId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "VideoConfig_videoId_key" ON "VideoConfig"("videoId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LintResult_videoId_severity_idx" ON "LintResult"("videoId", "severity");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LintResult_ruleCode_idx" ON "LintResult"("ruleCode");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "QuotaLog_datePt_idx" ON "QuotaLog"("datePt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "AuditLog_entityType_entityId_idx" ON "AuditLog"("entityType", "entityId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "AuditLog_createdAt_idx" ON "AuditLog"("createdAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "User_googleId_key" ON "User"("googleId");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Video" ADD CONSTRAINT "Video_templateId_fkey" FOREIGN KEY ("templateId") REFERENCES "Template"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "VideoConfig" ADD CONSTRAINT "VideoConfig_videoId_fkey" FOREIGN KEY ("videoId") REFERENCES "Video"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "DescriptionBlock" ADD CONSTRAINT "DescriptionBlock_campaignId_fkey" FOREIGN KEY ("campaignId") REFERENCES "Campaign"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "BlockVersion" ADD CONSTRAINT "BlockVersion_blockId_fkey" FOREIGN KEY ("blockId") REFERENCES "DescriptionBlock"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "TemplateVersion" ADD CONSTRAINT "TemplateVersion_templateId_fkey" FOREIGN KEY ("templateId") REFERENCES "Template"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "VideoCollaborator" ADD CONSTRAINT "VideoCollaborator_videoId_fkey" FOREIGN KEY ("videoId") REFERENCES "Video"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "VideoCollaborator" ADD CONSTRAINT "VideoCollaborator_collaboratorId_fkey" FOREIGN KEY ("collaboratorId") REFERENCES "Collaborator"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LintResult" ADD CONSTRAINT "LintResult_videoId_fkey" FOREIGN KEY ("videoId") REFERENCES "Video"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "BulkJobItem" ADD CONSTRAINT "BulkJobItem_bulkJobId_fkey" FOREIGN KEY ("bulkJobId") REFERENCES "BulkJob"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "BulkJobItem" ADD CONSTRAINT "BulkJobItem_videoId_fkey" FOREIGN KEY ("videoId") REFERENCES "Video"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "QuotaLog" ADD CONSTRAINT "QuotaLog_videoId_fkey" FOREIGN KEY ("videoId") REFERENCES "Video"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
Reference in New Issue
Block a user