cms.c2sgmbh/src/migrations/20260113_180000_add_community_phase1.ts
Martin Porwoll 358920f442 feat(Community): add Community Management Phase 1
- Add 5 new collections: SocialPlatforms, SocialAccounts,
  CommunityInteractions, CommunityTemplates, CommunityRules
- Add communityRole field to Users collection
- Add YouTube API client for comment sync
- Add Claude AI service for sentiment analysis
- Add API endpoints: /api/community/sync-comments, /api/community/reply
- Add communityAccess.ts for role-based access control
- Add migrations for all new tables and community_role enum fix

Fix: Make audit hooks non-blocking to prevent user save timeout

Dependencies: @anthropic-ai/sdk, googleapis

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 16:13:03 +00:00

444 lines
23 KiB
TypeScript

import { MigrateUpArgs, MigrateDownArgs, sql } from '@payloadcms/db-postgres'
/**
* Migration: Community Phase 1
*
* Creates all Community Management collections:
* - social_platforms
* - social_accounts
* - community_templates (before interactions, as it's referenced)
* - community_interactions
* - community_rules
*
* Also adds communityRole to users table.
*/
export async function up({ db }: MigrateUpArgs): Promise<void> {
// Step 1: Add user column
await db.execute(sql`
ALTER TABLE "users"
ADD COLUMN IF NOT EXISTS "community_role" varchar DEFAULT 'none';
`)
// Step 2: Create social_platforms (no dependencies)
await db.execute(sql`
CREATE TABLE IF NOT EXISTS "social_platforms" (
"id" serial PRIMARY KEY NOT NULL,
"name" varchar NOT NULL,
"slug" varchar NOT NULL UNIQUE,
"icon" varchar,
"color" varchar,
"is_active" boolean DEFAULT true,
"api_status" varchar DEFAULT 'disconnected',
"api_config_api_type" varchar,
"api_config_base_url" varchar,
"api_config_auth_type" varchar,
"rate_limits_requests_per_minute" numeric,
"rate_limits_requests_per_day" numeric,
"rate_limits_quota_units_per_day" numeric,
"updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL,
"created_at" timestamp(3) with time zone DEFAULT now() NOT NULL
);
CREATE INDEX IF NOT EXISTS "social_platforms_slug_idx" ON "social_platforms" USING btree ("slug");
CREATE INDEX IF NOT EXISTS "social_platforms_is_active_idx" ON "social_platforms" USING btree ("is_active");
CREATE INDEX IF NOT EXISTS "social_platforms_updated_at_idx" ON "social_platforms" USING btree ("updated_at");
CREATE INDEX IF NOT EXISTS "social_platforms_created_at_idx" ON "social_platforms" USING btree ("created_at");
`)
// Step 3: Create social_platforms array tables
await db.execute(sql`
CREATE TABLE IF NOT EXISTS "social_platforms_api_config_scopes" (
"id" serial PRIMARY KEY NOT NULL,
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL REFERENCES social_platforms(id) ON DELETE CASCADE,
"scope" varchar
);
CREATE INDEX IF NOT EXISTS "social_platforms_api_config_scopes_order_idx" ON "social_platforms_api_config_scopes" USING btree ("_order");
CREATE INDEX IF NOT EXISTS "social_platforms_api_config_scopes_parent_idx" ON "social_platforms_api_config_scopes" USING btree ("_parent_id");
CREATE TABLE IF NOT EXISTS "social_platforms_interaction_types" (
"id" serial PRIMARY KEY NOT NULL,
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL REFERENCES social_platforms(id) ON DELETE CASCADE,
"type" varchar NOT NULL,
"label" varchar NOT NULL,
"icon" varchar,
"can_reply" boolean DEFAULT true
);
CREATE INDEX IF NOT EXISTS "social_platforms_interaction_types_order_idx" ON "social_platforms_interaction_types" USING btree ("_order");
CREATE INDEX IF NOT EXISTS "social_platforms_interaction_types_parent_idx" ON "social_platforms_interaction_types" USING btree ("_parent_id");
`)
// Step 4: Create social_accounts (depends on social_platforms, youtube_channels)
await db.execute(sql`
CREATE TABLE IF NOT EXISTS "social_accounts" (
"id" serial PRIMARY KEY NOT NULL,
"platform_id" integer REFERENCES social_platforms(id) ON DELETE SET NULL,
"linked_channel_id" integer REFERENCES youtube_channels(id) ON DELETE SET NULL,
"display_name" varchar NOT NULL,
"account_handle" varchar,
"external_id" varchar,
"account_url" varchar,
"is_active" boolean DEFAULT true,
"credentials_access_token" varchar,
"credentials_refresh_token" varchar,
"credentials_token_expires_at" timestamp(3) with time zone,
"credentials_api_key" varchar,
"stats_followers" numeric,
"stats_total_posts" numeric,
"stats_last_synced_at" timestamp(3) with time zone,
"sync_settings_auto_sync_enabled" boolean DEFAULT true,
"sync_settings_sync_interval_minutes" numeric DEFAULT 15,
"sync_settings_sync_comments" boolean DEFAULT true,
"sync_settings_sync_d_ms" 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
);
CREATE INDEX IF NOT EXISTS "social_accounts_platform_idx" ON "social_accounts" USING btree ("platform_id");
CREATE INDEX IF NOT EXISTS "social_accounts_linked_channel_idx" ON "social_accounts" USING btree ("linked_channel_id");
CREATE INDEX IF NOT EXISTS "social_accounts_is_active_idx" ON "social_accounts" USING btree ("is_active");
CREATE INDEX IF NOT EXISTS "social_accounts_updated_at_idx" ON "social_accounts" USING btree ("updated_at");
CREATE INDEX IF NOT EXISTS "social_accounts_created_at_idx" ON "social_accounts" USING btree ("created_at");
`)
// Step 5: Create community_templates FIRST (before interactions, as it's referenced)
await db.execute(sql`
CREATE TABLE IF NOT EXISTS "community_templates" (
"id" serial PRIMARY KEY NOT NULL,
"category" varchar NOT NULL,
"channel_id" integer REFERENCES youtube_channels(id) ON DELETE SET NULL,
"requires_review" boolean DEFAULT false,
"is_active" boolean DEFAULT true,
"usage_count" numeric DEFAULT 0,
"example_output" text,
"updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL,
"created_at" timestamp(3) with time zone DEFAULT now() NOT NULL
);
CREATE INDEX IF NOT EXISTS "community_templates_category_idx" ON "community_templates" USING btree ("category");
CREATE INDEX IF NOT EXISTS "community_templates_channel_idx" ON "community_templates" USING btree ("channel_id");
CREATE INDEX IF NOT EXISTS "community_templates_is_active_idx" ON "community_templates" USING btree ("is_active");
CREATE INDEX IF NOT EXISTS "community_templates_updated_at_idx" ON "community_templates" USING btree ("updated_at");
CREATE INDEX IF NOT EXISTS "community_templates_created_at_idx" ON "community_templates" USING btree ("created_at");
`)
// Step 6: Create community_templates related tables
await db.execute(sql`
CREATE TABLE IF NOT EXISTS "community_templates_locales" (
"name" varchar NOT NULL,
"template" text NOT NULL,
"id" serial PRIMARY KEY NOT NULL,
"_locale" varchar NOT NULL,
"_parent_id" integer NOT NULL REFERENCES community_templates(id) ON DELETE CASCADE,
CONSTRAINT "community_templates_locales_locale_parent_id_unique" UNIQUE("_locale", "_parent_id")
);
CREATE INDEX IF NOT EXISTS "community_templates_locales_locale_idx" ON "community_templates_locales" USING btree ("_locale");
CREATE INDEX IF NOT EXISTS "community_templates_locales_parent_idx" ON "community_templates_locales" USING btree ("_parent_id");
CREATE TABLE IF NOT EXISTS "community_templates_variables" (
"id" serial PRIMARY KEY NOT NULL,
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL REFERENCES community_templates(id) ON DELETE CASCADE,
"variable" varchar NOT NULL,
"description" varchar,
"default_value" varchar
);
CREATE INDEX IF NOT EXISTS "community_templates_variables_order_idx" ON "community_templates_variables" USING btree ("_order");
CREATE INDEX IF NOT EXISTS "community_templates_variables_parent_idx" ON "community_templates_variables" USING btree ("_parent_id");
CREATE TABLE IF NOT EXISTS "community_templates_auto_suggest_keywords" (
"id" serial PRIMARY KEY NOT NULL,
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL REFERENCES community_templates(id) ON DELETE CASCADE,
"keyword" varchar NOT NULL
);
CREATE INDEX IF NOT EXISTS "community_templates_auto_suggest_keywords_order_idx" ON "community_templates_auto_suggest_keywords" USING btree ("_order");
CREATE INDEX IF NOT EXISTS "community_templates_auto_suggest_keywords_parent_idx" ON "community_templates_auto_suggest_keywords" USING btree ("_parent_id");
CREATE TABLE IF NOT EXISTS "community_templates_rels" (
"id" serial PRIMARY KEY NOT NULL,
"order" integer,
"parent_id" integer NOT NULL REFERENCES community_templates(id) ON DELETE CASCADE,
"path" varchar NOT NULL,
"social_platforms_id" integer REFERENCES social_platforms(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS "community_templates_rels_order_idx" ON "community_templates_rels" USING btree ("order");
CREATE INDEX IF NOT EXISTS "community_templates_rels_parent_idx" ON "community_templates_rels" USING btree ("parent_id");
CREATE INDEX IF NOT EXISTS "community_templates_rels_path_idx" ON "community_templates_rels" USING btree ("path");
CREATE INDEX IF NOT EXISTS "community_templates_rels_social_platforms_idx" ON "community_templates_rels" USING btree ("social_platforms_id");
`)
// Step 7: Create community_interactions (now community_templates exists)
await db.execute(sql`
CREATE TABLE IF NOT EXISTS "community_interactions" (
"id" serial PRIMARY KEY NOT NULL,
"platform_id" integer REFERENCES social_platforms(id) ON DELETE SET NULL,
"social_account_id" integer REFERENCES social_accounts(id) ON DELETE SET NULL,
"linked_content_id" integer REFERENCES youtube_content(id) ON DELETE SET NULL,
"type" varchar NOT NULL,
"external_id" varchar NOT NULL UNIQUE,
"parent_interaction_id" integer,
"author_name" varchar,
"author_handle" varchar,
"author_profile_url" varchar,
"author_avatar_url" varchar,
"author_is_verified" boolean DEFAULT false,
"author_is_subscriber" boolean DEFAULT false,
"author_is_member" boolean DEFAULT false,
"author_subscriber_count" numeric,
"message" text NOT NULL,
"message_html" text,
"published_at" timestamp(3) with time zone NOT NULL,
"analysis_sentiment" varchar,
"analysis_sentiment_score" numeric,
"analysis_confidence" numeric,
"analysis_language" varchar,
"analysis_suggested_template_id" integer REFERENCES community_templates(id) ON DELETE SET NULL,
"analysis_suggested_reply" text,
"analysis_analyzed_at" timestamp(3) with time zone,
"flags_is_medical_question" boolean DEFAULT false,
"flags_requires_escalation" boolean DEFAULT false,
"flags_is_spam" boolean DEFAULT false,
"flags_is_from_influencer" boolean DEFAULT false,
"status" varchar DEFAULT 'new' NOT NULL,
"priority" varchar DEFAULT 'normal' NOT NULL,
"assigned_to_id" integer REFERENCES users(id) ON DELETE SET NULL,
"response_deadline" timestamp(3) with time zone,
"response_text" text,
"response_used_template_id" integer REFERENCES community_templates(id) ON DELETE SET NULL,
"response_sent_at" timestamp(3) with time zone,
"response_sent_by_id" integer REFERENCES users(id) ON DELETE SET NULL,
"response_external_reply_id" varchar,
"engagement_likes" numeric DEFAULT 0,
"engagement_replies" numeric DEFAULT 0,
"engagement_is_hearted" boolean DEFAULT false,
"engagement_is_pinned" boolean DEFAULT false,
"internal_notes" text,
"updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL,
"created_at" timestamp(3) with time zone DEFAULT now() NOT NULL
);
`)
// Step 8: Add self-reference for parent_interaction after table exists
await db.execute(sql`
ALTER TABLE "community_interactions"
ADD CONSTRAINT "community_interactions_parent_fk"
FOREIGN KEY ("parent_interaction_id") REFERENCES community_interactions(id) ON DELETE SET NULL;
`)
// Step 9: Create indexes for community_interactions
await db.execute(sql`
CREATE INDEX IF NOT EXISTS "community_interactions_platform_idx" ON "community_interactions" USING btree ("platform_id");
CREATE INDEX IF NOT EXISTS "community_interactions_social_account_idx" ON "community_interactions" USING btree ("social_account_id");
CREATE INDEX IF NOT EXISTS "community_interactions_linked_content_idx" ON "community_interactions" USING btree ("linked_content_id");
CREATE INDEX IF NOT EXISTS "community_interactions_external_id_idx" ON "community_interactions" USING btree ("external_id");
CREATE INDEX IF NOT EXISTS "community_interactions_parent_idx" ON "community_interactions" USING btree ("parent_interaction_id");
CREATE INDEX IF NOT EXISTS "community_interactions_status_idx" ON "community_interactions" USING btree ("status");
CREATE INDEX IF NOT EXISTS "community_interactions_priority_idx" ON "community_interactions" USING btree ("priority");
CREATE INDEX IF NOT EXISTS "community_interactions_assigned_to_idx" ON "community_interactions" USING btree ("assigned_to_id");
CREATE INDEX IF NOT EXISTS "community_interactions_updated_at_idx" ON "community_interactions" USING btree ("updated_at");
CREATE INDEX IF NOT EXISTS "community_interactions_created_at_idx" ON "community_interactions" USING btree ("created_at");
`)
// Step 10: Create community_interactions array tables
await db.execute(sql`
CREATE TABLE IF NOT EXISTS "community_interactions_attachments" (
"id" serial PRIMARY KEY NOT NULL,
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL REFERENCES community_interactions(id) ON DELETE CASCADE,
"type" varchar,
"url" varchar
);
CREATE INDEX IF NOT EXISTS "community_interactions_attachments_order_idx" ON "community_interactions_attachments" USING btree ("_order");
CREATE INDEX IF NOT EXISTS "community_interactions_attachments_parent_idx" ON "community_interactions_attachments" USING btree ("_parent_id");
CREATE TABLE IF NOT EXISTS "community_interactions_analysis_topics" (
"id" serial PRIMARY KEY NOT NULL,
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL REFERENCES community_interactions(id) ON DELETE CASCADE,
"topic" varchar
);
CREATE INDEX IF NOT EXISTS "community_interactions_analysis_topics_order_idx" ON "community_interactions_analysis_topics" USING btree ("_order");
CREATE INDEX IF NOT EXISTS "community_interactions_analysis_topics_parent_idx" ON "community_interactions_analysis_topics" USING btree ("_parent_id");
`)
// Step 11: Create community_rules
await db.execute(sql`
CREATE TABLE IF NOT EXISTS "community_rules" (
"id" serial PRIMARY KEY NOT NULL,
"name" varchar NOT NULL,
"priority" numeric DEFAULT 100 NOT NULL,
"is_active" boolean DEFAULT true,
"description" text,
"channel_id" integer REFERENCES youtube_channels(id) ON DELETE SET NULL,
"trigger_type" varchar NOT NULL,
"trigger_influencer_min_followers" numeric DEFAULT 10000,
"stats_times_triggered" numeric DEFAULT 0,
"stats_last_triggered_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
);
CREATE INDEX IF NOT EXISTS "community_rules_name_idx" ON "community_rules" USING btree ("name");
CREATE INDEX IF NOT EXISTS "community_rules_priority_idx" ON "community_rules" USING btree ("priority");
CREATE INDEX IF NOT EXISTS "community_rules_is_active_idx" ON "community_rules" USING btree ("is_active");
CREATE INDEX IF NOT EXISTS "community_rules_channel_idx" ON "community_rules" USING btree ("channel_id");
CREATE INDEX IF NOT EXISTS "community_rules_updated_at_idx" ON "community_rules" USING btree ("updated_at");
CREATE INDEX IF NOT EXISTS "community_rules_created_at_idx" ON "community_rules" USING btree ("created_at");
`)
// Step 12: Create community_rules array tables
await db.execute(sql`
CREATE TABLE IF NOT EXISTS "community_rules_trigger_keywords" (
"id" serial PRIMARY KEY NOT NULL,
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL REFERENCES community_rules(id) ON DELETE CASCADE,
"keyword" varchar NOT NULL,
"match_type" varchar DEFAULT 'contains'
);
CREATE INDEX IF NOT EXISTS "community_rules_trigger_keywords_order_idx" ON "community_rules_trigger_keywords" USING btree ("_order");
CREATE INDEX IF NOT EXISTS "community_rules_trigger_keywords_parent_idx" ON "community_rules_trigger_keywords" USING btree ("_parent_id");
CREATE TABLE IF NOT EXISTS "community_rules_actions" (
"id" serial PRIMARY KEY NOT NULL,
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL REFERENCES community_rules(id) ON DELETE CASCADE,
"action" varchar NOT NULL,
"value" varchar,
"target_user_id" integer REFERENCES users(id) ON DELETE SET NULL,
"target_template_id" integer REFERENCES community_templates(id) ON DELETE SET NULL
);
CREATE INDEX IF NOT EXISTS "community_rules_actions_order_idx" ON "community_rules_actions" USING btree ("_order");
CREATE INDEX IF NOT EXISTS "community_rules_actions_parent_idx" ON "community_rules_actions" USING btree ("_parent_id");
CREATE INDEX IF NOT EXISTS "community_rules_actions_target_user_idx" ON "community_rules_actions" USING btree ("target_user_id");
CREATE INDEX IF NOT EXISTS "community_rules_actions_target_template_idx" ON "community_rules_actions" USING btree ("target_template_id");
CREATE TABLE IF NOT EXISTS "community_rules_rels" (
"id" serial PRIMARY KEY NOT NULL,
"order" integer,
"parent_id" integer NOT NULL REFERENCES community_rules(id) ON DELETE CASCADE,
"path" varchar NOT NULL,
"social_platforms_id" integer REFERENCES social_platforms(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS "community_rules_rels_order_idx" ON "community_rules_rels" USING btree ("order");
CREATE INDEX IF NOT EXISTS "community_rules_rels_parent_idx" ON "community_rules_rels" USING btree ("parent_id");
CREATE INDEX IF NOT EXISTS "community_rules_rels_path_idx" ON "community_rules_rels" USING btree ("path");
CREATE INDEX IF NOT EXISTS "community_rules_rels_social_platforms_idx" ON "community_rules_rels" USING btree ("social_platforms_id");
CREATE TABLE IF NOT EXISTS "community_rules_trigger_sentiment_values" (
"id" serial PRIMARY KEY NOT NULL,
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL REFERENCES community_rules(id) ON DELETE CASCADE,
"value" varchar
);
CREATE INDEX IF NOT EXISTS "community_rules_trigger_sentiment_values_order_idx" ON "community_rules_trigger_sentiment_values" USING btree ("_order");
CREATE INDEX IF NOT EXISTS "community_rules_trigger_sentiment_values_parent_idx" ON "community_rules_trigger_sentiment_values" USING btree ("_parent_id");
`)
// Step 13: Update system table
await db.execute(sql`
ALTER TABLE "payload_locked_documents_rels"
ADD COLUMN IF NOT EXISTS "social_platforms_id" integer REFERENCES social_platforms(id) ON DELETE CASCADE;
ALTER TABLE "payload_locked_documents_rels"
ADD COLUMN IF NOT EXISTS "social_accounts_id" integer REFERENCES social_accounts(id) ON DELETE CASCADE;
ALTER TABLE "payload_locked_documents_rels"
ADD COLUMN IF NOT EXISTS "community_interactions_id" integer REFERENCES community_interactions(id) ON DELETE CASCADE;
ALTER TABLE "payload_locked_documents_rels"
ADD COLUMN IF NOT EXISTS "community_templates_id" integer REFERENCES community_templates(id) ON DELETE CASCADE;
ALTER TABLE "payload_locked_documents_rels"
ADD COLUMN IF NOT EXISTS "community_rules_id" integer REFERENCES community_rules(id) ON DELETE CASCADE;
CREATE INDEX IF NOT EXISTS "payload_locked_documents_rels_social_platforms_idx"
ON "payload_locked_documents_rels" USING btree ("social_platforms_id");
CREATE INDEX IF NOT EXISTS "payload_locked_documents_rels_social_accounts_idx"
ON "payload_locked_documents_rels" USING btree ("social_accounts_id");
CREATE INDEX IF NOT EXISTS "payload_locked_documents_rels_community_interactions_idx"
ON "payload_locked_documents_rels" USING btree ("community_interactions_id");
CREATE INDEX IF NOT EXISTS "payload_locked_documents_rels_community_templates_idx"
ON "payload_locked_documents_rels" USING btree ("community_templates_id");
CREATE INDEX IF NOT EXISTS "payload_locked_documents_rels_community_rules_idx"
ON "payload_locked_documents_rels" USING btree ("community_rules_id");
`)
// Step 14: Seed YouTube Platform
await db.execute(sql`
INSERT INTO "social_platforms" ("name", "slug", "icon", "color", "is_active", "api_status", "api_config_api_type", "api_config_base_url", "api_config_auth_type", "rate_limits_quota_units_per_day")
VALUES ('YouTube', 'youtube', '📺', '#FF0000', true, 'development', 'youtube_v3', 'https://www.googleapis.com/youtube/v3', 'oauth2', 10000)
ON CONFLICT (slug) DO NOTHING;
`)
}
export async function down({ db }: MigrateDownArgs): Promise<void> {
// Drop in reverse order of creation
await db.execute(sql`
DROP INDEX IF EXISTS "payload_locked_documents_rels_community_rules_idx";
DROP INDEX IF EXISTS "payload_locked_documents_rels_community_templates_idx";
DROP INDEX IF EXISTS "payload_locked_documents_rels_community_interactions_idx";
DROP INDEX IF EXISTS "payload_locked_documents_rels_social_accounts_idx";
DROP INDEX IF EXISTS "payload_locked_documents_rels_social_platforms_idx";
ALTER TABLE "payload_locked_documents_rels" DROP COLUMN IF EXISTS "community_rules_id";
ALTER TABLE "payload_locked_documents_rels" DROP COLUMN IF EXISTS "community_templates_id";
ALTER TABLE "payload_locked_documents_rels" DROP COLUMN IF EXISTS "community_interactions_id";
ALTER TABLE "payload_locked_documents_rels" DROP COLUMN IF EXISTS "social_accounts_id";
ALTER TABLE "payload_locked_documents_rels" DROP COLUMN IF EXISTS "social_platforms_id";
`)
await db.execute(sql`
DROP TABLE IF EXISTS "community_rules_trigger_sentiment_values";
DROP TABLE IF EXISTS "community_rules_rels";
DROP TABLE IF EXISTS "community_rules_actions";
DROP TABLE IF EXISTS "community_rules_trigger_keywords";
DROP TABLE IF EXISTS "community_rules";
`)
await db.execute(sql`
DROP TABLE IF EXISTS "community_interactions_analysis_topics";
DROP TABLE IF EXISTS "community_interactions_attachments";
ALTER TABLE "community_interactions" DROP CONSTRAINT IF EXISTS "community_interactions_parent_fk";
DROP TABLE IF EXISTS "community_interactions";
`)
await db.execute(sql`
DROP TABLE IF EXISTS "community_templates_rels";
DROP TABLE IF EXISTS "community_templates_auto_suggest_keywords";
DROP TABLE IF EXISTS "community_templates_variables";
DROP TABLE IF EXISTS "community_templates_locales";
DROP TABLE IF EXISTS "community_templates";
`)
await db.execute(sql`
DROP TABLE IF EXISTS "social_accounts";
`)
await db.execute(sql`
DROP TABLE IF EXISTS "social_platforms_interaction_types";
DROP TABLE IF EXISTS "social_platforms_api_config_scopes";
DROP TABLE IF EXISTS "social_platforms";
`)
await db.execute(sql`
ALTER TABLE "users" DROP COLUMN IF EXISTS "community_role";
`)
}