import { MigrateUpArgs, MigrateDownArgs, sql } from '@payloadcms/db-postgres' /** * Migration: Add YouTube Operations Hub Collections * * This migration creates: * - youtube_channels table with _locales and content_series array table * - youtube_content table with _locales and multiple array tables * - yt_tasks table with _locales and array tables for attachments/comments * - yt_notifications table with _locales * - Extends users table with youtubeRole enum * - Adds columns to payload_locked_documents_rels for all 4 collections */ export async function up({ db, payload, req }: MigrateUpArgs): Promise { // Create enums await db.execute(sql` DO $$ BEGIN CREATE TYPE "enum_users_youtube_role" AS ENUM ( 'none', 'viewer', 'editor', 'producer', 'creator', 'manager' ); EXCEPTION WHEN duplicate_object THEN null; END $$; `) await db.execute(sql` DO $$ BEGIN CREATE TYPE "enum_youtube_channels_language" AS ENUM ('de', 'en'); EXCEPTION WHEN duplicate_object THEN null; END $$; `) await db.execute(sql` DO $$ BEGIN CREATE TYPE "enum_youtube_channels_category" AS ENUM ('lifestyle', 'corporate', 'b2b'); EXCEPTION WHEN duplicate_object THEN null; END $$; `) await db.execute(sql` DO $$ BEGIN CREATE TYPE "enum_youtube_channels_status" AS ENUM ('active', 'planned', 'paused', 'archived'); EXCEPTION WHEN duplicate_object THEN null; END $$; `) await db.execute(sql` DO $$ BEGIN CREATE TYPE "enum_youtube_content_format" AS ENUM ('short', 'longform', 'premiere'); EXCEPTION WHEN duplicate_object THEN null; END $$; `) await db.execute(sql` DO $$ BEGIN CREATE TYPE "enum_youtube_content_status" AS ENUM ( 'idea', 'script_draft', 'script_review', 'script_approved', 'shoot_scheduled', 'shot', 'rough_cut', 'fine_cut', 'final_review', 'approved', 'upload_scheduled', 'published', 'tracked', 'discarded' ); EXCEPTION WHEN duplicate_object THEN null; END $$; `) await db.execute(sql` DO $$ BEGIN CREATE TYPE "enum_youtube_content_priority" AS ENUM ('urgent', 'high', 'normal', 'low'); EXCEPTION WHEN duplicate_object THEN null; END $$; `) await db.execute(sql` DO $$ BEGIN CREATE TYPE "enum_youtube_content_visibility" AS ENUM ('public', 'unlisted', 'private'); EXCEPTION WHEN duplicate_object THEN null; END $$; `) await db.execute(sql` DO $$ BEGIN CREATE TYPE "enum_yt_tasks_task_type" AS ENUM ( 'script_write', 'script_review', 'shoot_prep', 'shoot', 'edit', 'graphics', 'thumbnail', 'review', 'upload', 'track', 'comments', 'other' ); EXCEPTION WHEN duplicate_object THEN null; END $$; `) await db.execute(sql` DO $$ BEGIN CREATE TYPE "enum_yt_tasks_status" AS ENUM ( 'todo', 'in_progress', 'blocked', 'waiting_review', 'done', 'cancelled' ); EXCEPTION WHEN duplicate_object THEN null; END $$; `) await db.execute(sql` DO $$ BEGIN CREATE TYPE "enum_yt_tasks_priority" AS ENUM ('urgent', 'high', 'normal', 'low'); EXCEPTION WHEN duplicate_object THEN null; END $$; `) await db.execute(sql` DO $$ BEGIN CREATE TYPE "enum_yt_notifications_type" AS ENUM ( 'task_assigned', 'task_due', 'task_overdue', 'approval_required', 'approved', 'rejected', 'video_published', 'comment', 'mention', 'system' ); EXCEPTION WHEN duplicate_object THEN null; END $$; `) // Extend users table await db.execute(sql` ALTER TABLE "users" ADD COLUMN IF NOT EXISTS "youtube_role" "enum_users_youtube_role" DEFAULT 'none'; `) // Create YouTube Channels table await db.execute(sql` CREATE TABLE IF NOT EXISTS "youtube_channels" ( "id" serial PRIMARY KEY NOT NULL, "slug" varchar NOT NULL, "youtube_channel_id" varchar NOT NULL, "youtube_handle" varchar, "language" "enum_youtube_channels_language" NOT NULL, "category" "enum_youtube_channels_category" NOT NULL, "status" "enum_youtube_channels_status" DEFAULT 'active' NOT NULL, "branding_primary_color" varchar, "branding_secondary_color" varchar, "branding_logo_id" integer REFERENCES media(id) ON DELETE SET NULL, "branding_thumbnail_template_id" integer REFERENCES media(id) ON DELETE SET NULL, "publishing_schedule_default_days" jsonb, "publishing_schedule_default_time" varchar, "publishing_schedule_shorts_per_week" numeric DEFAULT 4, "publishing_schedule_longform_per_week" numeric DEFAULT 1, "current_metrics_subscriber_count" numeric, "current_metrics_total_views" numeric, "current_metrics_video_count" numeric, "current_metrics_last_synced_at" timestamp(3) with time zone, "updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL, "created_at" timestamp(3) with time zone DEFAULT now() NOT NULL, CONSTRAINT "youtube_channels_slug_unique" UNIQUE("slug") ); `) await db.execute(sql` CREATE TABLE IF NOT EXISTS "youtube_channels_locales" ( "name" varchar NOT NULL, "id" serial PRIMARY KEY NOT NULL, "_locale" varchar NOT NULL, "_parent_id" integer NOT NULL REFERENCES youtube_channels(id) ON DELETE CASCADE, CONSTRAINT "youtube_channels_locales_locale_parent_id_unique" UNIQUE("_locale", "_parent_id") ); `) await db.execute(sql` CREATE TABLE IF NOT EXISTS "youtube_channels_content_series" ( "id" serial PRIMARY KEY NOT NULL, "_order" integer NOT NULL, "_parent_id" integer NOT NULL REFERENCES youtube_channels(id) ON DELETE CASCADE, "slug" varchar NOT NULL, "color" varchar, "is_active" boolean DEFAULT true ); `) await db.execute(sql` CREATE TABLE IF NOT EXISTS "youtube_channels_content_series_locales" ( "name" varchar NOT NULL, "description" varchar, "id" serial PRIMARY KEY NOT NULL, "_locale" varchar NOT NULL, "_parent_id" integer NOT NULL REFERENCES youtube_channels_content_series(id) ON DELETE CASCADE, CONSTRAINT "youtube_channels_content_series_locales_unique" UNIQUE("_locale", "_parent_id") ); `) // Table for hasMany select field: publishingSchedule.defaultDays await db.execute(sql` CREATE TABLE IF NOT EXISTS "youtube_channels_publishing_schedule_default_days" ( "order" integer NOT NULL, "parent_id" integer NOT NULL REFERENCES youtube_channels(id) ON DELETE CASCADE, "value" varchar NOT NULL, "id" serial PRIMARY KEY NOT NULL ); `) await db.execute(sql` CREATE INDEX IF NOT EXISTS "youtube_channels_slug_idx" ON "youtube_channels" USING btree ("slug"); CREATE INDEX IF NOT EXISTS "youtube_channels_branding_logo_idx" ON "youtube_channels" USING btree ("branding_logo_id"); CREATE INDEX IF NOT EXISTS "youtube_channels_branding_thumbnail_template_idx" ON "youtube_channels" USING btree ("branding_thumbnail_template_id"); CREATE INDEX IF NOT EXISTS "youtube_channels_updated_at_idx" ON "youtube_channels" USING btree ("updated_at"); CREATE INDEX IF NOT EXISTS "youtube_channels_created_at_idx" ON "youtube_channels" USING btree ("created_at"); CREATE INDEX IF NOT EXISTS "youtube_channels_locales_locale_idx" ON "youtube_channels_locales" USING btree ("_locale"); CREATE INDEX IF NOT EXISTS "youtube_channels_locales_parent_idx" ON "youtube_channels_locales" USING btree ("_parent_id"); CREATE INDEX IF NOT EXISTS "youtube_channels_content_series_order_idx" ON "youtube_channels_content_series" USING btree ("_order"); CREATE INDEX IF NOT EXISTS "youtube_channels_content_series_parent_idx" ON "youtube_channels_content_series" USING btree ("_parent_id"); CREATE INDEX IF NOT EXISTS "youtube_channels_psd_order_idx" ON "youtube_channels_publishing_schedule_default_days" USING btree ("order"); CREATE INDEX IF NOT EXISTS "youtube_channels_psd_parent_idx" ON "youtube_channels_publishing_schedule_default_days" USING btree ("parent_id"); `) // Create YouTube Content table await db.execute(sql` CREATE TABLE IF NOT EXISTS "youtube_content" ( "id" serial PRIMARY KEY NOT NULL, "slug" varchar NOT NULL, "channel_id" integer NOT NULL REFERENCES youtube_channels(id) ON DELETE SET NULL, "content_series" varchar, "format" "enum_youtube_content_format" NOT NULL, "status" "enum_youtube_content_status" DEFAULT 'idea' NOT NULL, "priority" "enum_youtube_content_priority" DEFAULT 'normal', "assigned_to_id" integer REFERENCES users(id) ON DELETE SET NULL, "created_by_id" integer REFERENCES users(id) ON DELETE SET NULL, "script_url" varchar, "shoot_date" timestamp(3) with time zone, "edit_deadline" timestamp(3) with time zone, "review_deadline" timestamp(3) with time zone, "scheduled_publish_date" timestamp(3) with time zone, "actual_publish_date" timestamp(3) with time zone, "thumbnail_id" integer REFERENCES media(id) ON DELETE SET NULL, "thumbnail_alt_id" integer REFERENCES media(id) ON DELETE SET NULL, "video_file_id" integer REFERENCES media(id) ON DELETE SET NULL, "approvals_script_approval_approved" boolean DEFAULT false, "approvals_script_approval_approved_by_id" integer REFERENCES users(id) ON DELETE SET NULL, "approvals_script_approval_approved_at" timestamp(3) with time zone, "approvals_medical_approval_required" boolean DEFAULT false, "approvals_medical_approval_approved" boolean DEFAULT false, "approvals_medical_approval_approved_by_id" integer REFERENCES users(id) ON DELETE SET NULL, "approvals_medical_approval_approved_at" timestamp(3) with time zone, "approvals_legal_approval_approved" boolean DEFAULT false, "approvals_legal_approval_approved_by_id" integer REFERENCES users(id) ON DELETE SET NULL, "approvals_legal_approval_approved_at" timestamp(3) with time zone, "approvals_legal_approval_disclaimer_included" boolean DEFAULT false, "approvals_final_approval_approved" boolean DEFAULT false, "approvals_final_approval_approved_by_id" integer REFERENCES users(id) ON DELETE SET NULL, "approvals_final_approval_approved_at" timestamp(3) with time zone, "youtube_video_id" varchar, "youtube_url" varchar, "youtube_metadata_visibility" "enum_youtube_content_visibility" DEFAULT 'private', "youtube_metadata_chapters" varchar, "performance_views" numeric, "performance_likes" numeric, "performance_comments" numeric, "performance_shares" numeric, "performance_watch_time_minutes" numeric, "performance_avg_view_duration" numeric, "performance_avg_view_percentage" numeric, "performance_ctr" numeric, "performance_impressions" numeric, "performance_subscribers_gained" numeric, "performance_last_synced_at" timestamp(3) with time zone, "internal_notes" jsonb, "updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL, "created_at" timestamp(3) with time zone DEFAULT now() NOT NULL ); `) await db.execute(sql` CREATE TABLE IF NOT EXISTS "youtube_content_locales" ( "title" varchar NOT NULL, "description" varchar, "hook" varchar, "call_to_action" varchar, "script_content" jsonb, "approvals_script_approval_notes" varchar, "approvals_medical_approval_notes" varchar, "approvals_legal_approval_notes" varchar, "approvals_final_approval_notes" varchar, "youtube_metadata_youtube_title" varchar, "youtube_metadata_youtube_description" varchar, "youtube_metadata_pinned_comment" varchar, "id" serial PRIMARY KEY NOT NULL, "_locale" varchar NOT NULL, "_parent_id" integer NOT NULL REFERENCES youtube_content(id) ON DELETE CASCADE, CONSTRAINT "youtube_content_locales_locale_parent_id_unique" UNIQUE("_locale", "_parent_id") ); `) await db.execute(sql` CREATE TABLE IF NOT EXISTS "youtube_content_key_points" ( "id" serial PRIMARY KEY NOT NULL, "_order" integer NOT NULL, "_parent_id" integer NOT NULL REFERENCES youtube_content(id) ON DELETE CASCADE ); `) await db.execute(sql` CREATE TABLE IF NOT EXISTS "youtube_content_key_points_locales" ( "point" varchar, "id" serial PRIMARY KEY NOT NULL, "_locale" varchar NOT NULL, "_parent_id" integer NOT NULL REFERENCES youtube_content_key_points(id) ON DELETE CASCADE, CONSTRAINT "youtube_content_key_points_locales_unique" UNIQUE("_locale", "_parent_id") ); `) await db.execute(sql` CREATE TABLE IF NOT EXISTS "youtube_content_raw_footage" ( "id" serial PRIMARY KEY NOT NULL, "_order" integer NOT NULL, "_parent_id" integer NOT NULL REFERENCES youtube_content(id) ON DELETE CASCADE, "file_id" integer REFERENCES media(id) ON DELETE SET NULL, "description" varchar ); `) await db.execute(sql` CREATE TABLE IF NOT EXISTS "youtube_content_youtube_metadata_tags" ( "id" serial PRIMARY KEY NOT NULL, "_order" integer NOT NULL, "_parent_id" integer NOT NULL REFERENCES youtube_content(id) ON DELETE CASCADE, "tag" varchar ); `) await db.execute(sql` CREATE INDEX IF NOT EXISTS "youtube_content_slug_idx" ON "youtube_content" USING btree ("slug"); CREATE INDEX IF NOT EXISTS "youtube_content_channel_idx" ON "youtube_content" USING btree ("channel_id"); CREATE INDEX IF NOT EXISTS "youtube_content_assigned_to_idx" ON "youtube_content" USING btree ("assigned_to_id"); CREATE INDEX IF NOT EXISTS "youtube_content_created_by_idx" ON "youtube_content" USING btree ("created_by_id"); CREATE INDEX IF NOT EXISTS "youtube_content_status_idx" ON "youtube_content" USING btree ("status"); CREATE INDEX IF NOT EXISTS "youtube_content_thumbnail_idx" ON "youtube_content" USING btree ("thumbnail_id"); CREATE INDEX IF NOT EXISTS "youtube_content_thumbnail_alt_idx" ON "youtube_content" USING btree ("thumbnail_alt_id"); CREATE INDEX IF NOT EXISTS "youtube_content_video_file_idx" ON "youtube_content" USING btree ("video_file_id"); CREATE INDEX IF NOT EXISTS "youtube_content_scheduled_publish_idx" ON "youtube_content" USING btree ("scheduled_publish_date"); CREATE INDEX IF NOT EXISTS "youtube_content_updated_at_idx" ON "youtube_content" USING btree ("updated_at"); CREATE INDEX IF NOT EXISTS "youtube_content_created_at_idx" ON "youtube_content" USING btree ("created_at"); CREATE INDEX IF NOT EXISTS "youtube_content_locales_locale_idx" ON "youtube_content_locales" USING btree ("_locale"); CREATE INDEX IF NOT EXISTS "youtube_content_locales_parent_idx" ON "youtube_content_locales" USING btree ("_parent_id"); CREATE INDEX IF NOT EXISTS "youtube_content_key_points_order_idx" ON "youtube_content_key_points" USING btree ("_order"); CREATE INDEX IF NOT EXISTS "youtube_content_key_points_parent_idx" ON "youtube_content_key_points" USING btree ("_parent_id"); CREATE INDEX IF NOT EXISTS "youtube_content_raw_footage_order_idx" ON "youtube_content_raw_footage" USING btree ("_order"); CREATE INDEX IF NOT EXISTS "youtube_content_raw_footage_parent_idx" ON "youtube_content_raw_footage" USING btree ("_parent_id"); CREATE INDEX IF NOT EXISTS "youtube_content_youtube_metadata_tags_order_idx" ON "youtube_content_youtube_metadata_tags" USING btree ("_order"); CREATE INDEX IF NOT EXISTS "youtube_content_youtube_metadata_tags_parent_idx" ON "youtube_content_youtube_metadata_tags" USING btree ("_parent_id"); `) // Create YT Tasks table await db.execute(sql` CREATE TABLE IF NOT EXISTS "yt_tasks" ( "id" serial PRIMARY KEY NOT NULL, "video_id" integer REFERENCES youtube_content(id) ON DELETE SET NULL, "channel_id" integer REFERENCES youtube_channels(id) ON DELETE SET NULL, "task_type" "enum_yt_tasks_task_type" NOT NULL, "status" "enum_yt_tasks_status" DEFAULT 'todo' NOT NULL, "priority" "enum_yt_tasks_priority" DEFAULT 'normal', "assigned_to_id" integer NOT NULL REFERENCES users(id) ON DELETE SET NULL, "due_date" timestamp(3) with time zone, "completed_at" timestamp(3) with time zone, "completed_by_id" integer REFERENCES users(id) ON DELETE SET NULL, "updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL, "created_at" timestamp(3) with time zone DEFAULT now() NOT NULL ); `) await db.execute(sql` CREATE TABLE IF NOT EXISTS "yt_tasks_locales" ( "title" varchar NOT NULL, "description" varchar, "blocked_reason" varchar, "id" serial PRIMARY KEY NOT NULL, "_locale" varchar NOT NULL, "_parent_id" integer NOT NULL REFERENCES yt_tasks(id) ON DELETE CASCADE, CONSTRAINT "yt_tasks_locales_locale_parent_id_unique" UNIQUE("_locale", "_parent_id") ); `) await db.execute(sql` CREATE TABLE IF NOT EXISTS "yt_tasks_attachments" ( "id" serial PRIMARY KEY NOT NULL, "_order" integer NOT NULL, "_parent_id" integer NOT NULL REFERENCES yt_tasks(id) ON DELETE CASCADE, "file_id" integer REFERENCES media(id) ON DELETE SET NULL, "note" varchar ); `) await db.execute(sql` CREATE TABLE IF NOT EXISTS "yt_tasks_comments" ( "id" serial PRIMARY KEY NOT NULL, "_order" integer NOT NULL, "_parent_id" integer NOT NULL REFERENCES yt_tasks(id) ON DELETE CASCADE, "author_id" integer REFERENCES users(id) ON DELETE SET NULL, "content" varchar, "created_at" timestamp(3) with time zone ); `) await db.execute(sql` CREATE INDEX IF NOT EXISTS "yt_tasks_video_idx" ON "yt_tasks" USING btree ("video_id"); CREATE INDEX IF NOT EXISTS "yt_tasks_channel_idx" ON "yt_tasks" USING btree ("channel_id"); CREATE INDEX IF NOT EXISTS "yt_tasks_assigned_to_idx" ON "yt_tasks" USING btree ("assigned_to_id"); CREATE INDEX IF NOT EXISTS "yt_tasks_status_idx" ON "yt_tasks" USING btree ("status"); CREATE INDEX IF NOT EXISTS "yt_tasks_due_date_idx" ON "yt_tasks" USING btree ("due_date"); CREATE INDEX IF NOT EXISTS "yt_tasks_completed_by_idx" ON "yt_tasks" USING btree ("completed_by_id"); CREATE INDEX IF NOT EXISTS "yt_tasks_updated_at_idx" ON "yt_tasks" USING btree ("updated_at"); CREATE INDEX IF NOT EXISTS "yt_tasks_created_at_idx" ON "yt_tasks" USING btree ("created_at"); CREATE INDEX IF NOT EXISTS "yt_tasks_locales_locale_idx" ON "yt_tasks_locales" USING btree ("_locale"); CREATE INDEX IF NOT EXISTS "yt_tasks_locales_parent_idx" ON "yt_tasks_locales" USING btree ("_parent_id"); CREATE INDEX IF NOT EXISTS "yt_tasks_attachments_order_idx" ON "yt_tasks_attachments" USING btree ("_order"); CREATE INDEX IF NOT EXISTS "yt_tasks_attachments_parent_idx" ON "yt_tasks_attachments" USING btree ("_parent_id"); CREATE INDEX IF NOT EXISTS "yt_tasks_attachments_file_idx" ON "yt_tasks_attachments" USING btree ("file_id"); CREATE INDEX IF NOT EXISTS "yt_tasks_comments_order_idx" ON "yt_tasks_comments" USING btree ("_order"); CREATE INDEX IF NOT EXISTS "yt_tasks_comments_parent_idx" ON "yt_tasks_comments" USING btree ("_parent_id"); CREATE INDEX IF NOT EXISTS "yt_tasks_comments_author_idx" ON "yt_tasks_comments" USING btree ("author_id"); `) // Create YT Notifications table await db.execute(sql` CREATE TABLE IF NOT EXISTS "yt_notifications" ( "id" serial PRIMARY KEY NOT NULL, "recipient_id" integer NOT NULL REFERENCES users(id) ON DELETE CASCADE, "type" "enum_yt_notifications_type" NOT NULL, "link" varchar, "related_video_id" integer REFERENCES youtube_content(id) ON DELETE SET NULL, "related_task_id" integer REFERENCES yt_tasks(id) ON DELETE SET NULL, "read" boolean DEFAULT false, "read_at" timestamp(3) with time zone, "email_sent" boolean DEFAULT false, "updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL, "created_at" timestamp(3) with time zone DEFAULT now() NOT NULL ); `) await db.execute(sql` CREATE TABLE IF NOT EXISTS "yt_notifications_locales" ( "title" varchar NOT NULL, "message" varchar, "id" serial PRIMARY KEY NOT NULL, "_locale" varchar NOT NULL, "_parent_id" integer NOT NULL REFERENCES yt_notifications(id) ON DELETE CASCADE, CONSTRAINT "yt_notifications_locales_locale_parent_id_unique" UNIQUE("_locale", "_parent_id") ); `) await db.execute(sql` CREATE INDEX IF NOT EXISTS "yt_notifications_recipient_idx" ON "yt_notifications" USING btree ("recipient_id"); CREATE INDEX IF NOT EXISTS "yt_notifications_type_idx" ON "yt_notifications" USING btree ("type"); CREATE INDEX IF NOT EXISTS "yt_notifications_related_video_idx" ON "yt_notifications" USING btree ("related_video_id"); CREATE INDEX IF NOT EXISTS "yt_notifications_related_task_idx" ON "yt_notifications" USING btree ("related_task_id"); CREATE INDEX IF NOT EXISTS "yt_notifications_read_idx" ON "yt_notifications" USING btree ("read"); CREATE INDEX IF NOT EXISTS "yt_notifications_updated_at_idx" ON "yt_notifications" USING btree ("updated_at"); CREATE INDEX IF NOT EXISTS "yt_notifications_created_at_idx" ON "yt_notifications" USING btree ("created_at"); CREATE INDEX IF NOT EXISTS "yt_notifications_locales_locale_idx" ON "yt_notifications_locales" USING btree ("_locale"); CREATE INDEX IF NOT EXISTS "yt_notifications_locales_parent_idx" ON "yt_notifications_locales" USING btree ("_parent_id"); `) // Create users_rels table for youtubeChannels relationship await db.execute(sql` CREATE TABLE IF NOT EXISTS "users_rels" ( "id" serial PRIMARY KEY NOT NULL, "order" integer, "parent_id" integer NOT NULL REFERENCES users(id) ON DELETE CASCADE, "path" varchar NOT NULL, "youtube_channels_id" integer REFERENCES youtube_channels(id) ON DELETE CASCADE ); `) await db.execute(sql` CREATE INDEX IF NOT EXISTS "users_rels_order_idx" ON "users_rels" USING btree ("order"); CREATE INDEX IF NOT EXISTS "users_rels_parent_idx" ON "users_rels" USING btree ("parent_id"); CREATE INDEX IF NOT EXISTS "users_rels_path_idx" ON "users_rels" USING btree ("path"); CREATE INDEX IF NOT EXISTS "users_rels_youtube_channels_idx" ON "users_rels" USING btree ("youtube_channels_id"); `) // Add columns to payload_locked_documents_rels await db.execute(sql` ALTER TABLE "payload_locked_documents_rels" ADD COLUMN IF NOT EXISTS "youtube_channels_id" integer REFERENCES youtube_channels(id) ON DELETE CASCADE; `) await db.execute(sql` ALTER TABLE "payload_locked_documents_rels" ADD COLUMN IF NOT EXISTS "youtube_content_id" integer REFERENCES youtube_content(id) ON DELETE CASCADE; `) await db.execute(sql` ALTER TABLE "payload_locked_documents_rels" ADD COLUMN IF NOT EXISTS "yt_tasks_id" integer REFERENCES yt_tasks(id) ON DELETE CASCADE; `) await db.execute(sql` ALTER TABLE "payload_locked_documents_rels" ADD COLUMN IF NOT EXISTS "yt_notifications_id" integer REFERENCES yt_notifications(id) ON DELETE CASCADE; `) await db.execute(sql` CREATE INDEX IF NOT EXISTS "payload_locked_documents_rels_youtube_channels_idx" ON "payload_locked_documents_rels" USING btree ("youtube_channels_id"); `) await db.execute(sql` CREATE INDEX IF NOT EXISTS "payload_locked_documents_rels_youtube_content_idx" ON "payload_locked_documents_rels" USING btree ("youtube_content_id"); `) await db.execute(sql` CREATE INDEX IF NOT EXISTS "payload_locked_documents_rels_yt_tasks_idx" ON "payload_locked_documents_rels" USING btree ("yt_tasks_id"); `) await db.execute(sql` CREATE INDEX IF NOT EXISTS "payload_locked_documents_rels_yt_notifications_idx" ON "payload_locked_documents_rels" USING btree ("yt_notifications_id"); `) } export async function down({ db, payload, req }: MigrateDownArgs): Promise { // Remove indexes from system tables first await db.execute(sql`DROP INDEX IF EXISTS "payload_locked_documents_rels_youtube_channels_idx";`) await db.execute(sql`DROP INDEX IF EXISTS "payload_locked_documents_rels_youtube_content_idx";`) await db.execute(sql`DROP INDEX IF EXISTS "payload_locked_documents_rels_yt_tasks_idx";`) await db.execute(sql`DROP INDEX IF EXISTS "payload_locked_documents_rels_yt_notifications_idx";`) // Remove columns from system tables await db.execute(sql`ALTER TABLE "payload_locked_documents_rels" DROP COLUMN IF EXISTS "youtube_channels_id";`) await db.execute(sql`ALTER TABLE "payload_locked_documents_rels" DROP COLUMN IF EXISTS "youtube_content_id";`) await db.execute(sql`ALTER TABLE "payload_locked_documents_rels" DROP COLUMN IF EXISTS "yt_tasks_id";`) await db.execute(sql`ALTER TABLE "payload_locked_documents_rels" DROP COLUMN IF EXISTS "yt_notifications_id";`) // Drop users_rels table (created for youtubeChannels relationship) await db.execute(sql`DROP TABLE IF EXISTS "users_rels";`) // Drop YT Notifications tables await db.execute(sql`DROP TABLE IF EXISTS "yt_notifications_locales";`) await db.execute(sql`DROP TABLE IF EXISTS "yt_notifications";`) // Drop YT Tasks tables await db.execute(sql`DROP TABLE IF EXISTS "yt_tasks_comments";`) await db.execute(sql`DROP TABLE IF EXISTS "yt_tasks_attachments";`) await db.execute(sql`DROP TABLE IF EXISTS "yt_tasks_locales";`) await db.execute(sql`DROP TABLE IF EXISTS "yt_tasks";`) // Drop YouTube Content tables await db.execute(sql`DROP TABLE IF EXISTS "youtube_content_youtube_metadata_tags";`) await db.execute(sql`DROP TABLE IF EXISTS "youtube_content_raw_footage";`) await db.execute(sql`DROP TABLE IF EXISTS "youtube_content_key_points_locales";`) await db.execute(sql`DROP TABLE IF EXISTS "youtube_content_key_points";`) await db.execute(sql`DROP TABLE IF EXISTS "youtube_content_locales";`) await db.execute(sql`DROP TABLE IF EXISTS "youtube_content";`) // Drop YouTube Channels tables await db.execute(sql`DROP TABLE IF EXISTS "youtube_channels_publishing_schedule_default_days";`) await db.execute(sql`DROP TABLE IF EXISTS "youtube_channels_content_series_locales";`) await db.execute(sql`DROP TABLE IF EXISTS "youtube_channels_content_series";`) await db.execute(sql`DROP TABLE IF EXISTS "youtube_channels_locales";`) await db.execute(sql`DROP TABLE IF EXISTS "youtube_channels";`) // Remove users column await db.execute(sql`ALTER TABLE "users" DROP COLUMN IF EXISTS "youtube_role";`) // Drop enums await db.execute(sql`DROP TYPE IF EXISTS "enum_yt_notifications_type";`) await db.execute(sql`DROP TYPE IF EXISTS "enum_yt_tasks_priority";`) await db.execute(sql`DROP TYPE IF EXISTS "enum_yt_tasks_status";`) await db.execute(sql`DROP TYPE IF EXISTS "enum_yt_tasks_task_type";`) await db.execute(sql`DROP TYPE IF EXISTS "enum_youtube_content_visibility";`) await db.execute(sql`DROP TYPE IF EXISTS "enum_youtube_content_priority";`) await db.execute(sql`DROP TYPE IF EXISTS "enum_youtube_content_status";`) await db.execute(sql`DROP TYPE IF EXISTS "enum_youtube_content_format";`) await db.execute(sql`DROP TYPE IF EXISTS "enum_youtube_channels_status";`) await db.execute(sql`DROP TYPE IF EXISTS "enum_youtube_channels_category";`) await db.execute(sql`DROP TYPE IF EXISTS "enum_youtube_channels_language";`) await db.execute(sql`DROP TYPE IF EXISTS "enum_users_youtube_role";`) }