cms.c2sgmbh/src/migrations/20251216_073000_add_video_collections.ts
Martin Porwoll 913897c87c feat: add comprehensive video feature with collections, hooks, and tests
Video Feature Implementation:
- Add Videos and VideoCategories collections with multi-tenant support
- Extend VideoBlock with library/upload/embed sources and playback options
- Add featuredVideo group to Posts collection with processed embed URLs

Hooks & Validation:
- Add processFeaturedVideo hook for URL parsing and privacy mode embedding
- Add createSlugValidationHook for tenant-scoped slug uniqueness
- Add video-utils library (parseVideoUrl, generateEmbedUrl, formatDuration)

Testing:
- Add 84 unit tests for video-utils (URL parsing, duration, embed generation)
- Add 14 integration tests for Videos collection CRUD and slug validation

Database:
- Migration for videos, video_categories tables with locales
- Migration for Posts featuredVideo processed fields
- Update payload internal tables for new collections

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 10:48:33 +00:00

470 lines
23 KiB
TypeScript

import { MigrateUpArgs, MigrateDownArgs, sql } from '@payloadcms/db-postgres'
/**
* Migration: Add Video Collections
*
* Creates:
* - video_categories table (with locales)
* - videos table (with locales)
* - videos_tags (m:n)
* - videos_rels (for related videos/posts)
* - Extends posts table with featured_video fields
* - Extends pages_blocks_video_block with new fields
*/
export async function up({ db, payload, req }: MigrateUpArgs): Promise<void> {
await db.execute(sql`
-- ENUMS for videos collection (with DO...EXCEPTION for idempotency)
DO $$ BEGIN
CREATE TYPE "public"."enum_videos_source" AS ENUM('youtube', 'vimeo', 'upload', 'external');
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
CREATE TYPE "public"."enum_videos_video_type" AS ENUM('tutorial', 'product', 'testimonial', 'explainer', 'webinar', 'interview', 'event', 'trailer', 'other');
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
CREATE TYPE "public"."enum_videos_aspect_ratio" AS ENUM('16:9', '4:3', '1:1', '9:16', '21:9');
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
CREATE TYPE "public"."enum_videos_status" AS ENUM('draft', 'published', 'archived');
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
-- ENUMS for posts featured_video
DO $$ BEGIN
CREATE TYPE "public"."enum_posts_featured_video_source" AS ENUM('library', 'embed', 'upload');
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
-- ENUMS for video_block
DO $$ BEGIN
CREATE TYPE "public"."enum_pages_blocks_video_block_source_type" AS ENUM('embed', 'upload', 'library', 'external');
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
-- Add new values to existing aspect_ratio enum if they don't exist
DO $$ BEGIN
ALTER TYPE "public"."enum_pages_blocks_video_block_aspect_ratio" ADD VALUE IF NOT EXISTS '9:16';
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
ALTER TYPE "public"."enum_pages_blocks_video_block_aspect_ratio" ADD VALUE IF NOT EXISTS '21:9';
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
CREATE TYPE "public"."enum_pages_blocks_video_block_size" AS ENUM('full', 'large', 'medium', 'small');
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
CREATE TYPE "public"."enum_pages_blocks_video_block_alignment" AS ENUM('left', 'center', 'right');
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
CREATE TYPE "public"."enum_pages_blocks_video_block_style_rounded" AS ENUM('none', 'sm', 'md', 'lg', 'xl');
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
CREATE TYPE "public"."enum_pages_blocks_video_block_style_shadow" AS ENUM('none', 'sm', 'md', 'lg', 'xl');
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
-- ============================================================
-- VIDEO CATEGORIES TABLE
-- ============================================================
CREATE TABLE IF NOT EXISTS "video_categories" (
"id" serial PRIMARY KEY NOT NULL,
"tenant_id" integer,
"slug" varchar NOT NULL,
"icon" varchar,
"cover_image_id" integer,
"order" numeric DEFAULT 0,
"is_active" boolean DEFAULT true,
"updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL,
"created_at" timestamp(3) with time zone DEFAULT now() NOT NULL
);
CREATE TABLE IF NOT EXISTS "video_categories_locales" (
"name" varchar NOT NULL,
"description" varchar,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" integer NOT NULL
);
-- ============================================================
-- VIDEOS TABLE
-- ============================================================
CREATE TABLE IF NOT EXISTS "videos" (
"id" serial PRIMARY KEY NOT NULL,
"tenant_id" integer,
"slug" varchar NOT NULL,
"source" "enum_videos_source" DEFAULT 'youtube' NOT NULL,
"video_file_id" integer,
"embed_url" varchar,
"video_id" varchar,
"thumbnail_id" integer,
"duration" varchar,
"duration_seconds" numeric,
"category_id" integer,
"video_type" "enum_videos_video_type" DEFAULT 'other',
"playback_autoplay" boolean DEFAULT false,
"playback_muted" boolean DEFAULT false,
"playback_loop" boolean DEFAULT false,
"playback_controls" boolean DEFAULT true,
"playback_start_time" numeric,
"aspect_ratio" "enum_videos_aspect_ratio" DEFAULT '16:9',
"status" "enum_videos_status" DEFAULT 'draft',
"is_featured" boolean DEFAULT false,
"published_at" timestamp(3) with time zone,
"seo_meta_description" varchar,
"seo_og_image_id" integer,
"updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL,
"created_at" timestamp(3) with time zone DEFAULT now() NOT NULL
);
CREATE TABLE IF NOT EXISTS "videos_locales" (
"title" varchar NOT NULL,
"description" jsonb,
"excerpt" varchar,
"transcript" jsonb,
"seo_meta_title" varchar,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" integer NOT NULL
);
-- Videos Tags (m:n)
CREATE TABLE IF NOT EXISTS "videos_rels" (
"id" serial PRIMARY KEY NOT NULL,
"order" integer,
"parent_id" integer NOT NULL,
"path" varchar NOT NULL,
"tags_id" integer,
"videos_id" integer,
"posts_id" integer
);
-- ============================================================
-- POSTS FEATURED VIDEO COLUMNS
-- ============================================================
ALTER TABLE "posts" ADD COLUMN IF NOT EXISTS "featured_video_enabled" boolean DEFAULT false;
ALTER TABLE "posts" ADD COLUMN IF NOT EXISTS "featured_video_replace_image" boolean DEFAULT false;
ALTER TABLE "posts" ADD COLUMN IF NOT EXISTS "featured_video_source" "enum_posts_featured_video_source" DEFAULT 'library';
ALTER TABLE "posts" ADD COLUMN IF NOT EXISTS "featured_video_video_id" integer;
ALTER TABLE "posts" ADD COLUMN IF NOT EXISTS "featured_video_embed_url" varchar;
ALTER TABLE "posts" ADD COLUMN IF NOT EXISTS "featured_video_uploaded_video_id" integer;
ALTER TABLE "posts" ADD COLUMN IF NOT EXISTS "featured_video_autoplay" boolean DEFAULT false;
ALTER TABLE "posts" ADD COLUMN IF NOT EXISTS "featured_video_muted" boolean DEFAULT true;
-- ============================================================
-- PAGES BLOCKS VIDEO BLOCK - Extended columns
-- ============================================================
ALTER TABLE "pages_blocks_video_block" ADD COLUMN IF NOT EXISTS "source_type" "enum_pages_blocks_video_block_source_type" DEFAULT 'embed';
ALTER TABLE "pages_blocks_video_block" ADD COLUMN IF NOT EXISTS "video_from_library_id" integer;
ALTER TABLE "pages_blocks_video_block" ADD COLUMN IF NOT EXISTS "video_file_id" integer;
ALTER TABLE "pages_blocks_video_block" ADD COLUMN IF NOT EXISTS "thumbnail_id" integer;
ALTER TABLE "pages_blocks_video_block" ADD COLUMN IF NOT EXISTS "size" "enum_pages_blocks_video_block_size" DEFAULT 'full';
ALTER TABLE "pages_blocks_video_block" ADD COLUMN IF NOT EXISTS "alignment" "enum_pages_blocks_video_block_alignment" DEFAULT 'center';
ALTER TABLE "pages_blocks_video_block" ADD COLUMN IF NOT EXISTS "playback_autoplay" boolean DEFAULT false;
ALTER TABLE "pages_blocks_video_block" ADD COLUMN IF NOT EXISTS "playback_muted" boolean DEFAULT false;
ALTER TABLE "pages_blocks_video_block" ADD COLUMN IF NOT EXISTS "playback_loop" boolean DEFAULT false;
ALTER TABLE "pages_blocks_video_block" ADD COLUMN IF NOT EXISTS "playback_controls" boolean DEFAULT true;
ALTER TABLE "pages_blocks_video_block" ADD COLUMN IF NOT EXISTS "playback_playsinline" boolean DEFAULT true;
ALTER TABLE "pages_blocks_video_block" ADD COLUMN IF NOT EXISTS "playback_start_time" numeric;
ALTER TABLE "pages_blocks_video_block" ADD COLUMN IF NOT EXISTS "embed_options_show_related" boolean DEFAULT false;
ALTER TABLE "pages_blocks_video_block" ADD COLUMN IF NOT EXISTS "embed_options_privacy_mode" boolean DEFAULT true;
ALTER TABLE "pages_blocks_video_block" ADD COLUMN IF NOT EXISTS "style_rounded" "enum_pages_blocks_video_block_style_rounded" DEFAULT 'none';
ALTER TABLE "pages_blocks_video_block" ADD COLUMN IF NOT EXISTS "style_shadow" "enum_pages_blocks_video_block_style_shadow" DEFAULT 'none';
ALTER TABLE "pages_blocks_video_block" ADD COLUMN IF NOT EXISTS "style_border" boolean DEFAULT false;
-- ============================================================
-- INDEXES
-- ============================================================
CREATE INDEX IF NOT EXISTS "video_categories_tenant_idx" ON "video_categories" USING btree ("tenant_id");
CREATE INDEX IF NOT EXISTS "video_categories_slug_idx" ON "video_categories" USING btree ("slug");
CREATE INDEX IF NOT EXISTS "video_categories_created_at_idx" ON "video_categories" USING btree ("created_at");
CREATE UNIQUE INDEX IF NOT EXISTS "video_categories_locales_locale_parent_id_unique" ON "video_categories_locales" USING btree ("_locale","_parent_id");
CREATE INDEX IF NOT EXISTS "videos_tenant_idx" ON "videos" USING btree ("tenant_id");
CREATE INDEX IF NOT EXISTS "videos_slug_idx" ON "videos" USING btree ("slug");
CREATE INDEX IF NOT EXISTS "videos_source_idx" ON "videos" USING btree ("source");
CREATE INDEX IF NOT EXISTS "videos_category_idx" ON "videos" USING btree ("category_id");
CREATE INDEX IF NOT EXISTS "videos_status_idx" ON "videos" USING btree ("status");
CREATE INDEX IF NOT EXISTS "videos_is_featured_idx" ON "videos" USING btree ("is_featured");
CREATE INDEX IF NOT EXISTS "videos_published_at_idx" ON "videos" USING btree ("published_at");
CREATE INDEX IF NOT EXISTS "videos_created_at_idx" ON "videos" USING btree ("created_at");
CREATE UNIQUE INDEX IF NOT EXISTS "videos_locales_locale_parent_id_unique" ON "videos_locales" USING btree ("_locale","_parent_id");
CREATE INDEX IF NOT EXISTS "videos_rels_order_idx" ON "videos_rels" USING btree ("order");
CREATE INDEX IF NOT EXISTS "videos_rels_parent_idx" ON "videos_rels" USING btree ("parent_id");
CREATE INDEX IF NOT EXISTS "videos_rels_path_idx" ON "videos_rels" USING btree ("path");
CREATE INDEX IF NOT EXISTS "videos_rels_tags_idx" ON "videos_rels" USING btree ("tags_id");
CREATE INDEX IF NOT EXISTS "videos_rels_videos_idx" ON "videos_rels" USING btree ("videos_id");
CREATE INDEX IF NOT EXISTS "videos_rels_posts_idx" ON "videos_rels" USING btree ("posts_id");
-- ============================================================
-- FOREIGN KEYS
-- ============================================================
DO $$ BEGIN
ALTER TABLE "video_categories" ADD CONSTRAINT "video_categories_tenant_id_tenants_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE SET NULL ON UPDATE NO ACTION;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
ALTER TABLE "video_categories" ADD CONSTRAINT "video_categories_cover_image_id_media_id_fk" FOREIGN KEY ("cover_image_id") REFERENCES "public"."media"("id") ON DELETE SET NULL ON UPDATE NO ACTION;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
ALTER TABLE "video_categories_locales" ADD CONSTRAINT "video_categories_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."video_categories"("id") ON DELETE CASCADE ON UPDATE NO ACTION;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
ALTER TABLE "videos" ADD CONSTRAINT "videos_tenant_id_tenants_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE SET NULL ON UPDATE NO ACTION;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
ALTER TABLE "videos" ADD CONSTRAINT "videos_video_file_id_media_id_fk" FOREIGN KEY ("video_file_id") REFERENCES "public"."media"("id") ON DELETE SET NULL ON UPDATE NO ACTION;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
ALTER TABLE "videos" ADD CONSTRAINT "videos_thumbnail_id_media_id_fk" FOREIGN KEY ("thumbnail_id") REFERENCES "public"."media"("id") ON DELETE SET NULL ON UPDATE NO ACTION;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
ALTER TABLE "videos" ADD CONSTRAINT "videos_category_id_video_categories_id_fk" FOREIGN KEY ("category_id") REFERENCES "public"."video_categories"("id") ON DELETE SET NULL ON UPDATE NO ACTION;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
ALTER TABLE "videos" ADD CONSTRAINT "videos_seo_og_image_id_media_id_fk" FOREIGN KEY ("seo_og_image_id") REFERENCES "public"."media"("id") ON DELETE SET NULL ON UPDATE NO ACTION;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
ALTER TABLE "videos_locales" ADD CONSTRAINT "videos_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."videos"("id") ON DELETE CASCADE ON UPDATE NO ACTION;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
ALTER TABLE "videos_rels" ADD CONSTRAINT "videos_rels_parent_fk" FOREIGN KEY ("parent_id") REFERENCES "public"."videos"("id") ON DELETE CASCADE ON UPDATE NO ACTION;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
ALTER TABLE "videos_rels" ADD CONSTRAINT "videos_rels_tags_fk" FOREIGN KEY ("tags_id") REFERENCES "public"."tags"("id") ON DELETE CASCADE ON UPDATE NO ACTION;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
ALTER TABLE "videos_rels" ADD CONSTRAINT "videos_rels_videos_fk" FOREIGN KEY ("videos_id") REFERENCES "public"."videos"("id") ON DELETE CASCADE ON UPDATE NO ACTION;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
ALTER TABLE "videos_rels" ADD CONSTRAINT "videos_rels_posts_fk" FOREIGN KEY ("posts_id") REFERENCES "public"."posts"("id") ON DELETE CASCADE ON UPDATE NO ACTION;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
ALTER TABLE "posts" ADD CONSTRAINT "posts_featured_video_video_id_videos_id_fk" FOREIGN KEY ("featured_video_video_id") REFERENCES "public"."videos"("id") ON DELETE SET NULL ON UPDATE NO ACTION;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
ALTER TABLE "posts" ADD CONSTRAINT "posts_featured_video_uploaded_video_id_media_id_fk" FOREIGN KEY ("featured_video_uploaded_video_id") REFERENCES "public"."media"("id") ON DELETE SET NULL ON UPDATE NO ACTION;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
ALTER TABLE "pages_blocks_video_block" ADD CONSTRAINT "pages_blocks_video_block_video_from_library_id_videos_id_fk" FOREIGN KEY ("video_from_library_id") REFERENCES "public"."videos"("id") ON DELETE SET NULL ON UPDATE NO ACTION;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
ALTER TABLE "pages_blocks_video_block" ADD CONSTRAINT "pages_blocks_video_block_video_file_id_media_id_fk" FOREIGN KEY ("video_file_id") REFERENCES "public"."media"("id") ON DELETE SET NULL ON UPDATE NO ACTION;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
ALTER TABLE "pages_blocks_video_block" ADD CONSTRAINT "pages_blocks_video_block_thumbnail_id_media_id_fk" FOREIGN KEY ("thumbnail_id") REFERENCES "public"."media"("id") ON DELETE SET NULL ON UPDATE NO ACTION;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
-- ============================================================
-- PAYLOAD INTERNAL TABLES - Add columns for new collections
-- ============================================================
-- payload_locked_documents_rels
ALTER TABLE "payload_locked_documents_rels" ADD COLUMN IF NOT EXISTS "videos_id" integer;
ALTER TABLE "payload_locked_documents_rels" ADD COLUMN IF NOT EXISTS "video_categories_id" integer;
CREATE INDEX IF NOT EXISTS "payload_locked_documents_rels_videos_id_idx" ON "payload_locked_documents_rels" USING btree ("videos_id");
CREATE INDEX IF NOT EXISTS "payload_locked_documents_rels_video_categories_id_idx" ON "payload_locked_documents_rels" USING btree ("video_categories_id");
DO $$ BEGIN
ALTER TABLE "payload_locked_documents_rels" ADD CONSTRAINT "payload_locked_documents_rels_videos_fk" FOREIGN KEY ("videos_id") REFERENCES "public"."videos"("id") ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
ALTER TABLE "payload_locked_documents_rels" ADD CONSTRAINT "payload_locked_documents_rels_video_categories_fk" FOREIGN KEY ("video_categories_id") REFERENCES "public"."video_categories"("id") ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
-- payload_preferences_rels
ALTER TABLE "payload_preferences_rels" ADD COLUMN IF NOT EXISTS "videos_id" integer;
ALTER TABLE "payload_preferences_rels" ADD COLUMN IF NOT EXISTS "video_categories_id" integer;
CREATE INDEX IF NOT EXISTS "payload_preferences_rels_videos_id_idx" ON "payload_preferences_rels" USING btree ("videos_id");
CREATE INDEX IF NOT EXISTS "payload_preferences_rels_video_categories_id_idx" ON "payload_preferences_rels" USING btree ("video_categories_id");
DO $$ BEGIN
ALTER TABLE "payload_preferences_rels" ADD CONSTRAINT "payload_preferences_rels_videos_fk" FOREIGN KEY ("videos_id") REFERENCES "public"."videos"("id") ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
ALTER TABLE "payload_preferences_rels" ADD CONSTRAINT "payload_preferences_rels_video_categories_fk" FOREIGN KEY ("video_categories_id") REFERENCES "public"."video_categories"("id") ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
`);
}
export async function down({ db, payload, req }: MigrateDownArgs): Promise<void> {
await db.execute(sql`
-- Drop payload internal table columns first
ALTER TABLE "payload_preferences_rels" DROP CONSTRAINT IF EXISTS "payload_preferences_rels_video_categories_fk";
ALTER TABLE "payload_preferences_rels" DROP CONSTRAINT IF EXISTS "payload_preferences_rels_videos_fk";
ALTER TABLE "payload_locked_documents_rels" DROP CONSTRAINT IF EXISTS "payload_locked_documents_rels_video_categories_fk";
ALTER TABLE "payload_locked_documents_rels" DROP CONSTRAINT IF EXISTS "payload_locked_documents_rels_videos_fk";
DROP INDEX IF EXISTS "payload_preferences_rels_video_categories_id_idx";
DROP INDEX IF EXISTS "payload_preferences_rels_videos_id_idx";
DROP INDEX IF EXISTS "payload_locked_documents_rels_video_categories_id_idx";
DROP INDEX IF EXISTS "payload_locked_documents_rels_videos_id_idx";
ALTER TABLE "payload_preferences_rels" DROP COLUMN IF EXISTS "video_categories_id";
ALTER TABLE "payload_preferences_rels" DROP COLUMN IF EXISTS "videos_id";
ALTER TABLE "payload_locked_documents_rels" DROP COLUMN IF EXISTS "video_categories_id";
ALTER TABLE "payload_locked_documents_rels" DROP COLUMN IF EXISTS "videos_id";
-- Drop foreign keys
ALTER TABLE "pages_blocks_video_block" DROP CONSTRAINT IF EXISTS "pages_blocks_video_block_thumbnail_id_media_id_fk";
ALTER TABLE "pages_blocks_video_block" DROP CONSTRAINT IF EXISTS "pages_blocks_video_block_video_file_id_media_id_fk";
ALTER TABLE "pages_blocks_video_block" DROP CONSTRAINT IF EXISTS "pages_blocks_video_block_video_from_library_id_videos_id_fk";
ALTER TABLE "posts" DROP CONSTRAINT IF EXISTS "posts_featured_video_uploaded_video_id_media_id_fk";
ALTER TABLE "posts" DROP CONSTRAINT IF EXISTS "posts_featured_video_video_id_videos_id_fk";
ALTER TABLE "videos_rels" DROP CONSTRAINT IF EXISTS "videos_rels_posts_fk";
ALTER TABLE "videos_rels" DROP CONSTRAINT IF EXISTS "videos_rels_videos_fk";
ALTER TABLE "videos_rels" DROP CONSTRAINT IF EXISTS "videos_rels_tags_fk";
ALTER TABLE "videos_rels" DROP CONSTRAINT IF EXISTS "videos_rels_parent_fk";
ALTER TABLE "videos_locales" DROP CONSTRAINT IF EXISTS "videos_locales_parent_id_fk";
ALTER TABLE "videos" DROP CONSTRAINT IF EXISTS "videos_seo_og_image_id_media_id_fk";
ALTER TABLE "videos" DROP CONSTRAINT IF EXISTS "videos_category_id_video_categories_id_fk";
ALTER TABLE "videos" DROP CONSTRAINT IF EXISTS "videos_thumbnail_id_media_id_fk";
ALTER TABLE "videos" DROP CONSTRAINT IF EXISTS "videos_video_file_id_media_id_fk";
ALTER TABLE "videos" DROP CONSTRAINT IF EXISTS "videos_tenant_id_tenants_id_fk";
ALTER TABLE "video_categories_locales" DROP CONSTRAINT IF EXISTS "video_categories_locales_parent_id_fk";
ALTER TABLE "video_categories" DROP CONSTRAINT IF EXISTS "video_categories_cover_image_id_media_id_fk";
ALTER TABLE "video_categories" DROP CONSTRAINT IF EXISTS "video_categories_tenant_id_tenants_id_fk";
-- Drop video block extended columns
ALTER TABLE "pages_blocks_video_block" DROP COLUMN IF EXISTS "style_border";
ALTER TABLE "pages_blocks_video_block" DROP COLUMN IF EXISTS "style_shadow";
ALTER TABLE "pages_blocks_video_block" DROP COLUMN IF EXISTS "style_rounded";
ALTER TABLE "pages_blocks_video_block" DROP COLUMN IF EXISTS "embed_options_privacy_mode";
ALTER TABLE "pages_blocks_video_block" DROP COLUMN IF EXISTS "embed_options_show_related";
ALTER TABLE "pages_blocks_video_block" DROP COLUMN IF EXISTS "playback_start_time";
ALTER TABLE "pages_blocks_video_block" DROP COLUMN IF EXISTS "playback_playsinline";
ALTER TABLE "pages_blocks_video_block" DROP COLUMN IF EXISTS "playback_controls";
ALTER TABLE "pages_blocks_video_block" DROP COLUMN IF EXISTS "playback_loop";
ALTER TABLE "pages_blocks_video_block" DROP COLUMN IF EXISTS "playback_muted";
ALTER TABLE "pages_blocks_video_block" DROP COLUMN IF EXISTS "playback_autoplay";
ALTER TABLE "pages_blocks_video_block" DROP COLUMN IF EXISTS "alignment";
ALTER TABLE "pages_blocks_video_block" DROP COLUMN IF EXISTS "size";
ALTER TABLE "pages_blocks_video_block" DROP COLUMN IF EXISTS "thumbnail_id";
ALTER TABLE "pages_blocks_video_block" DROP COLUMN IF EXISTS "video_file_id";
ALTER TABLE "pages_blocks_video_block" DROP COLUMN IF EXISTS "video_from_library_id";
ALTER TABLE "pages_blocks_video_block" DROP COLUMN IF EXISTS "source_type";
-- Drop posts featured video columns
ALTER TABLE "posts" DROP COLUMN IF EXISTS "featured_video_muted";
ALTER TABLE "posts" DROP COLUMN IF EXISTS "featured_video_autoplay";
ALTER TABLE "posts" DROP COLUMN IF EXISTS "featured_video_uploaded_video_id";
ALTER TABLE "posts" DROP COLUMN IF EXISTS "featured_video_embed_url";
ALTER TABLE "posts" DROP COLUMN IF EXISTS "featured_video_video_id";
ALTER TABLE "posts" DROP COLUMN IF EXISTS "featured_video_source";
ALTER TABLE "posts" DROP COLUMN IF EXISTS "featured_video_replace_image";
ALTER TABLE "posts" DROP COLUMN IF EXISTS "featured_video_enabled";
-- Drop tables
DROP TABLE IF EXISTS "videos_rels";
DROP TABLE IF EXISTS "videos_locales";
DROP TABLE IF EXISTS "videos";
DROP TABLE IF EXISTS "video_categories_locales";
DROP TABLE IF EXISTS "video_categories";
-- Drop enums
DROP TYPE IF EXISTS "public"."enum_pages_blocks_video_block_style_shadow";
DROP TYPE IF EXISTS "public"."enum_pages_blocks_video_block_style_rounded";
DROP TYPE IF EXISTS "public"."enum_pages_blocks_video_block_alignment";
DROP TYPE IF EXISTS "public"."enum_pages_blocks_video_block_size";
DROP TYPE IF EXISTS "public"."enum_pages_blocks_video_block_aspect_ratio";
DROP TYPE IF EXISTS "public"."enum_pages_blocks_video_block_source_type";
DROP TYPE IF EXISTS "public"."enum_posts_featured_video_source";
DROP TYPE IF EXISTS "public"."enum_videos_status";
DROP TYPE IF EXISTS "public"."enum_videos_aspect_ratio";
DROP TYPE IF EXISTS "public"."enum_videos_video_type";
DROP TYPE IF EXISTS "public"."enum_videos_source";
`);
}