From 2fdcfce804145f8c43cb35d574391c167a090bda Mon Sep 17 00:00:00 2001 From: Christomatt Date: Mon, 26 Jan 2026 11:20:32 +0100 Subject: [PATCH] feat(db): Add favicon support and improve remote followers uniqueness constraint - Add favicon_url column to nodes table for storing node instance favicons - Replace actor_url unique constraint with composite unique index on (user_id, actor_url) in remote_followers table - Update database schema and migration files to reflect new constraints - Improve data integrity by ensuring remote followers are unique per user and actor combination --- drizzle/0005_yummy_millenium_guard.sql | 3 + drizzle/meta/0005_snapshot.json | 3611 ++++++++++++++++++++++++ drizzle/meta/_journal.json | 7 + src/db/schema.ts | 5 +- 4 files changed, 3624 insertions(+), 2 deletions(-) create mode 100644 drizzle/0005_yummy_millenium_guard.sql create mode 100644 drizzle/meta/0005_snapshot.json diff --git a/drizzle/0005_yummy_millenium_guard.sql b/drizzle/0005_yummy_millenium_guard.sql new file mode 100644 index 0000000..aedcd54 --- /dev/null +++ b/drizzle/0005_yummy_millenium_guard.sql @@ -0,0 +1,3 @@ +ALTER TABLE "remote_followers" DROP CONSTRAINT "remote_followers_actor_url_unique";--> statement-breakpoint +ALTER TABLE "nodes" ADD COLUMN "favicon_url" text;--> statement-breakpoint +CREATE UNIQUE INDEX "remote_followers_user_actor_unique" ON "remote_followers" USING btree ("user_id","actor_url"); \ No newline at end of file diff --git a/drizzle/meta/0005_snapshot.json b/drizzle/meta/0005_snapshot.json new file mode 100644 index 0000000..5f10789 --- /dev/null +++ b/drizzle/meta/0005_snapshot.json @@ -0,0 +1,3611 @@ +{ + "id": "440d7707-5838-4c3a-a4ce-5b82353242d4", + "prevId": "3e8b2279-a62d-4851-9c43-81c2ed361d67", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.blocks": { + "name": "blocks", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "blocked_user_id": { + "name": "blocked_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "blocks_user_idx": { + "name": "blocks_user_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "blocks_blocked_user_idx": { + "name": "blocks_blocked_user_idx", + "columns": [ + { + "expression": "blocked_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "blocks_user_id_users_id_fk": { + "name": "blocks_user_id_users_id_fk", + "tableFrom": "blocks", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "blocks_blocked_user_id_users_id_fk": { + "name": "blocks_blocked_user_id_users_id_fk", + "tableFrom": "blocks", + "tableTo": "users", + "columnsFrom": [ + "blocked_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.bot_activity_logs": { + "name": "bot_activity_logs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "bot_id": { + "name": "bot_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "action": { + "name": "action", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "details": { + "name": "details", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "success": { + "name": "success", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "bot_activity_logs_bot_idx": { + "name": "bot_activity_logs_bot_idx", + "columns": [ + { + "expression": "bot_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "bot_activity_logs_action_idx": { + "name": "bot_activity_logs_action_idx", + "columns": [ + { + "expression": "action", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "bot_activity_logs_created_idx": { + "name": "bot_activity_logs_created_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "bot_activity_logs_bot_id_bots_id_fk": { + "name": "bot_activity_logs_bot_id_bots_id_fk", + "tableFrom": "bot_activity_logs", + "tableTo": "bots", + "columnsFrom": [ + "bot_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.bot_content_items": { + "name": "bot_content_items", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "source_id": { + "name": "source_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "external_id": { + "name": "external_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "published_at": { + "name": "published_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "fetched_at": { + "name": "fetched_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "is_processed": { + "name": "is_processed", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "processed_at": { + "name": "processed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "post_id": { + "name": "post_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "interest_score": { + "name": "interest_score", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "interest_reason": { + "name": "interest_reason", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "bot_content_items_source_idx": { + "name": "bot_content_items_source_idx", + "columns": [ + { + "expression": "source_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "bot_content_items_processed_idx": { + "name": "bot_content_items_processed_idx", + "columns": [ + { + "expression": "is_processed", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "bot_content_items_external_idx": { + "name": "bot_content_items_external_idx", + "columns": [ + { + "expression": "external_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "bot_content_items_source_id_bot_content_sources_id_fk": { + "name": "bot_content_items_source_id_bot_content_sources_id_fk", + "tableFrom": "bot_content_items", + "tableTo": "bot_content_sources", + "columnsFrom": [ + "source_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "bot_content_items_post_id_posts_id_fk": { + "name": "bot_content_items_post_id_posts_id_fk", + "tableFrom": "bot_content_items", + "tableTo": "posts", + "columnsFrom": [ + "post_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.bot_content_sources": { + "name": "bot_content_sources", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "bot_id": { + "name": "bot_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "subreddit": { + "name": "subreddit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "api_key_encrypted": { + "name": "api_key_encrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "source_config": { + "name": "source_config", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "keywords": { + "name": "keywords", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "last_fetch_at": { + "name": "last_fetch_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_error": { + "name": "last_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "consecutive_errors": { + "name": "consecutive_errors", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "bot_content_sources_bot_idx": { + "name": "bot_content_sources_bot_idx", + "columns": [ + { + "expression": "bot_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "bot_content_sources_type_idx": { + "name": "bot_content_sources_type_idx", + "columns": [ + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "bot_content_sources_bot_id_bots_id_fk": { + "name": "bot_content_sources_bot_id_bots_id_fk", + "tableFrom": "bot_content_sources", + "tableTo": "bots", + "columnsFrom": [ + "bot_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.bot_mentions": { + "name": "bot_mentions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "bot_id": { + "name": "bot_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "post_id": { + "name": "post_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "author_id": { + "name": "author_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "is_processed": { + "name": "is_processed", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "processed_at": { + "name": "processed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "response_post_id": { + "name": "response_post_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "is_remote": { + "name": "is_remote", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "remote_actor_url": { + "name": "remote_actor_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "bot_mentions_bot_idx": { + "name": "bot_mentions_bot_idx", + "columns": [ + { + "expression": "bot_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "bot_mentions_processed_idx": { + "name": "bot_mentions_processed_idx", + "columns": [ + { + "expression": "is_processed", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "bot_mentions_created_idx": { + "name": "bot_mentions_created_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "bot_mentions_bot_id_bots_id_fk": { + "name": "bot_mentions_bot_id_bots_id_fk", + "tableFrom": "bot_mentions", + "tableTo": "bots", + "columnsFrom": [ + "bot_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "bot_mentions_post_id_posts_id_fk": { + "name": "bot_mentions_post_id_posts_id_fk", + "tableFrom": "bot_mentions", + "tableTo": "posts", + "columnsFrom": [ + "post_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "bot_mentions_author_id_users_id_fk": { + "name": "bot_mentions_author_id_users_id_fk", + "tableFrom": "bot_mentions", + "tableTo": "users", + "columnsFrom": [ + "author_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "bot_mentions_response_post_id_posts_id_fk": { + "name": "bot_mentions_response_post_id_posts_id_fk", + "tableFrom": "bot_mentions", + "tableTo": "posts", + "columnsFrom": [ + "response_post_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.bot_rate_limits": { + "name": "bot_rate_limits", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "bot_id": { + "name": "bot_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "window_start": { + "name": "window_start", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "window_type": { + "name": "window_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "post_count": { + "name": "post_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "reply_count": { + "name": "reply_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "bot_rate_limits_bot_window_idx": { + "name": "bot_rate_limits_bot_window_idx", + "columns": [ + { + "expression": "bot_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "window_start", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "bot_rate_limits_bot_id_bots_id_fk": { + "name": "bot_rate_limits_bot_id_bots_id_fk", + "tableFrom": "bot_rate_limits", + "tableTo": "bots", + "columnsFrom": [ + "bot_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.bots": { + "name": "bots", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "owner_id": { + "name": "owner_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "personality_config": { + "name": "personality_config", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "llm_provider": { + "name": "llm_provider", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "llm_model": { + "name": "llm_model", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "llm_api_key_encrypted": { + "name": "llm_api_key_encrypted", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "schedule_config": { + "name": "schedule_config", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "autonomous_mode": { + "name": "autonomous_mode", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "is_suspended": { + "name": "is_suspended", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "suspension_reason": { + "name": "suspension_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "suspended_at": { + "name": "suspended_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_post_at": { + "name": "last_post_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "bots_user_id_idx": { + "name": "bots_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "bots_owner_id_idx": { + "name": "bots_owner_id_idx", + "columns": [ + { + "expression": "owner_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "bots_active_idx": { + "name": "bots_active_idx", + "columns": [ + { + "expression": "is_active", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "bots_user_id_users_id_fk": { + "name": "bots_user_id_users_id_fk", + "tableFrom": "bots", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "bots_owner_id_users_id_fk": { + "name": "bots_owner_id_users_id_fk", + "tableFrom": "bots", + "tableTo": "users", + "columnsFrom": [ + "owner_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.follows": { + "name": "follows", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "follower_id": { + "name": "follower_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "following_id": { + "name": "following_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "ap_id": { + "name": "ap_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "pending": { + "name": "pending", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "follows_follower_idx": { + "name": "follows_follower_idx", + "columns": [ + { + "expression": "follower_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "follows_following_idx": { + "name": "follows_following_idx", + "columns": [ + { + "expression": "following_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "follows_follower_id_users_id_fk": { + "name": "follows_follower_id_users_id_fk", + "tableFrom": "follows", + "tableTo": "users", + "columnsFrom": [ + "follower_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "follows_following_id_users_id_fk": { + "name": "follows_following_id_users_id_fk", + "tableFrom": "follows", + "tableTo": "users", + "columnsFrom": [ + "following_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "follows_ap_id_unique": { + "name": "follows_ap_id_unique", + "nullsNotDistinct": false, + "columns": [ + "ap_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.handle_registry": { + "name": "handle_registry", + "schema": "", + "columns": { + "handle": { + "name": "handle", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "did": { + "name": "did", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "node_domain": { + "name": "node_domain", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "registered_at": { + "name": "registered_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "handle_registry_updated_idx": { + "name": "handle_registry_updated_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.likes": { + "name": "likes", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "post_id": { + "name": "post_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "ap_id": { + "name": "ap_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "likes_user_post_idx": { + "name": "likes_user_post_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "post_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "likes_user_id_users_id_fk": { + "name": "likes_user_id_users_id_fk", + "tableFrom": "likes", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "likes_post_id_posts_id_fk": { + "name": "likes_post_id_posts_id_fk", + "tableFrom": "likes", + "tableTo": "posts", + "columnsFrom": [ + "post_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "likes_ap_id_unique": { + "name": "likes_ap_id_unique", + "nullsNotDistinct": false, + "columns": [ + "ap_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.media": { + "name": "media", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "post_id": { + "name": "post_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "alt_text": { + "name": "alt_text", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "mime_type": { + "name": "mime_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "width": { + "name": "width", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "height": { + "name": "height", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "media_user_idx": { + "name": "media_user_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "media_post_idx": { + "name": "media_post_idx", + "columns": [ + { + "expression": "post_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "media_user_id_users_id_fk": { + "name": "media_user_id_users_id_fk", + "tableFrom": "media", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "media_post_id_posts_id_fk": { + "name": "media_post_id_posts_id_fk", + "tableFrom": "media", + "tableTo": "posts", + "columnsFrom": [ + "post_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.muted_nodes": { + "name": "muted_nodes", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "node_domain": { + "name": "node_domain", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "muted_nodes_user_idx": { + "name": "muted_nodes_user_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "muted_nodes_domain_idx": { + "name": "muted_nodes_domain_idx", + "columns": [ + { + "expression": "node_domain", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "muted_nodes_user_id_users_id_fk": { + "name": "muted_nodes_user_id_users_id_fk", + "tableFrom": "muted_nodes", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.mutes": { + "name": "mutes", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "muted_user_id": { + "name": "muted_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "mutes_user_idx": { + "name": "mutes_user_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "mutes_muted_user_idx": { + "name": "mutes_muted_user_idx", + "columns": [ + { + "expression": "muted_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "mutes_user_id_users_id_fk": { + "name": "mutes_user_id_users_id_fk", + "tableFrom": "mutes", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mutes_muted_user_id_users_id_fk": { + "name": "mutes_muted_user_id_users_id_fk", + "tableFrom": "mutes", + "tableTo": "users", + "columnsFrom": [ + "muted_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.nodes": { + "name": "nodes", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "domain": { + "name": "domain", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "long_description": { + "name": "long_description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "rules": { + "name": "rules", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "banner_url": { + "name": "banner_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "logo_url": { + "name": "logo_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "favicon_url": { + "name": "favicon_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "accent_color": { + "name": "accent_color", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'#FFFFFF'" + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_nsfw": { + "name": "is_nsfw", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "nodes_domain_unique": { + "name": "nodes_domain_unique", + "nullsNotDistinct": false, + "columns": [ + "domain" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.notifications": { + "name": "notifications", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "actor_id": { + "name": "actor_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "post_id": { + "name": "post_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "read_at": { + "name": "read_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "notifications_user_idx": { + "name": "notifications_user_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "notifications_created_idx": { + "name": "notifications_created_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "notifications_user_id_users_id_fk": { + "name": "notifications_user_id_users_id_fk", + "tableFrom": "notifications", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "notifications_actor_id_users_id_fk": { + "name": "notifications_actor_id_users_id_fk", + "tableFrom": "notifications", + "tableTo": "users", + "columnsFrom": [ + "actor_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "notifications_post_id_posts_id_fk": { + "name": "notifications_post_id_posts_id_fk", + "tableFrom": "notifications", + "tableTo": "posts", + "columnsFrom": [ + "post_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.posts": { + "name": "posts", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "bot_id": { + "name": "bot_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "reply_to_id": { + "name": "reply_to_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "repost_of_id": { + "name": "repost_of_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "likes_count": { + "name": "likes_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "reposts_count": { + "name": "reposts_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "replies_count": { + "name": "replies_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "is_nsfw": { + "name": "is_nsfw", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "is_removed": { + "name": "is_removed", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "removed_at": { + "name": "removed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "removed_by": { + "name": "removed_by", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "removed_reason": { + "name": "removed_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ap_id": { + "name": "ap_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ap_url": { + "name": "ap_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "link_preview_url": { + "name": "link_preview_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "link_preview_title": { + "name": "link_preview_title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "link_preview_description": { + "name": "link_preview_description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "link_preview_image": { + "name": "link_preview_image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "posts_user_id_idx": { + "name": "posts_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "posts_bot_id_idx": { + "name": "posts_bot_id_idx", + "columns": [ + { + "expression": "bot_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "posts_created_at_idx": { + "name": "posts_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "posts_reply_to_idx": { + "name": "posts_reply_to_idx", + "columns": [ + { + "expression": "reply_to_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "posts_removed_idx": { + "name": "posts_removed_idx", + "columns": [ + { + "expression": "is_removed", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "posts_nsfw_idx": { + "name": "posts_nsfw_idx", + "columns": [ + { + "expression": "is_nsfw", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "posts_user_id_users_id_fk": { + "name": "posts_user_id_users_id_fk", + "tableFrom": "posts", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "posts_bot_id_bots_id_fk": { + "name": "posts_bot_id_bots_id_fk", + "tableFrom": "posts", + "tableTo": "bots", + "columnsFrom": [ + "bot_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "posts_removed_by_users_id_fk": { + "name": "posts_removed_by_users_id_fk", + "tableFrom": "posts", + "tableTo": "users", + "columnsFrom": [ + "removed_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "posts_ap_id_unique": { + "name": "posts_ap_id_unique", + "nullsNotDistinct": false, + "columns": [ + "ap_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.remote_followers": { + "name": "remote_followers", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "actor_url": { + "name": "actor_url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "inbox_url": { + "name": "inbox_url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "shared_inbox_url": { + "name": "shared_inbox_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "handle": { + "name": "handle", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "activity_id": { + "name": "activity_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "remote_followers_user_idx": { + "name": "remote_followers_user_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "remote_followers_actor_idx": { + "name": "remote_followers_actor_idx", + "columns": [ + { + "expression": "actor_url", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "remote_followers_user_actor_unique": { + "name": "remote_followers_user_actor_unique", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "actor_url", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "remote_followers_user_id_users_id_fk": { + "name": "remote_followers_user_id_users_id_fk", + "tableFrom": "remote_followers", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.remote_follows": { + "name": "remote_follows", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "follower_id": { + "name": "follower_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "target_handle": { + "name": "target_handle", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "target_actor_url": { + "name": "target_actor_url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "inbox_url": { + "name": "inbox_url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "activity_id": { + "name": "activity_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "display_name": { + "name": "display_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "bio": { + "name": "bio", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "avatar_url": { + "name": "avatar_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "remote_follows_follower_idx": { + "name": "remote_follows_follower_idx", + "columns": [ + { + "expression": "follower_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "remote_follows_target_idx": { + "name": "remote_follows_target_idx", + "columns": [ + { + "expression": "target_handle", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "remote_follows_follower_id_users_id_fk": { + "name": "remote_follows_follower_id_users_id_fk", + "tableFrom": "remote_follows", + "tableTo": "users", + "columnsFrom": [ + "follower_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.remote_posts": { + "name": "remote_posts", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "ap_id": { + "name": "ap_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "author_handle": { + "name": "author_handle", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "author_actor_url": { + "name": "author_actor_url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "author_display_name": { + "name": "author_display_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "author_avatar_url": { + "name": "author_avatar_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "published_at": { + "name": "published_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "link_preview_url": { + "name": "link_preview_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "link_preview_title": { + "name": "link_preview_title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "link_preview_description": { + "name": "link_preview_description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "link_preview_image": { + "name": "link_preview_image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "media_json": { + "name": "media_json", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "fetched_at": { + "name": "fetched_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "remote_posts_author_idx": { + "name": "remote_posts_author_idx", + "columns": [ + { + "expression": "author_handle", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "remote_posts_published_idx": { + "name": "remote_posts_published_idx", + "columns": [ + { + "expression": "published_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "remote_posts_ap_id_idx": { + "name": "remote_posts_ap_id_idx", + "columns": [ + { + "expression": "ap_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "remote_posts_ap_id_unique": { + "name": "remote_posts_ap_id_unique", + "nullsNotDistinct": false, + "columns": [ + "ap_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.reports": { + "name": "reports", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "reporter_id": { + "name": "reporter_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "target_type": { + "name": "target_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "target_id": { + "name": "target_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'open'" + }, + "resolved_at": { + "name": "resolved_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "resolved_by": { + "name": "resolved_by", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "resolution_note": { + "name": "resolution_note", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "reports_status_idx": { + "name": "reports_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "reports_target_idx": { + "name": "reports_target_idx", + "columns": [ + { + "expression": "target_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "target_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "reports_reporter_idx": { + "name": "reports_reporter_idx", + "columns": [ + { + "expression": "reporter_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "reports_reporter_id_users_id_fk": { + "name": "reports_reporter_id_users_id_fk", + "tableFrom": "reports", + "tableTo": "users", + "columnsFrom": [ + "reporter_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "reports_resolved_by_users_id_fk": { + "name": "reports_resolved_by_users_id_fk", + "tableFrom": "reports", + "tableTo": "users", + "columnsFrom": [ + "resolved_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sessions": { + "name": "sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "sessions_token_idx": { + "name": "sessions_token_idx", + "columns": [ + { + "expression": "token", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "sessions_user_idx": { + "name": "sessions_user_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "sessions_user_id_users_id_fk": { + "name": "sessions_user_id_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "sessions_token_unique": { + "name": "sessions_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.swarm_nodes": { + "name": "swarm_nodes", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "domain": { + "name": "domain", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "logo_url": { + "name": "logo_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "software_version": { + "name": "software_version", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_count": { + "name": "user_count", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "post_count": { + "name": "post_count", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "is_nsfw": { + "name": "is_nsfw", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "discovered_via": { + "name": "discovered_via", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "discovered_at": { + "name": "discovered_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "last_seen_at": { + "name": "last_seen_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "last_sync_at": { + "name": "last_sync_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "consecutive_failures": { + "name": "consecutive_failures", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "trust_score": { + "name": "trust_score", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 50 + }, + "capabilities": { + "name": "capabilities", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "swarm_nodes_domain_idx": { + "name": "swarm_nodes_domain_idx", + "columns": [ + { + "expression": "domain", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "swarm_nodes_active_idx": { + "name": "swarm_nodes_active_idx", + "columns": [ + { + "expression": "is_active", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "swarm_nodes_last_seen_idx": { + "name": "swarm_nodes_last_seen_idx", + "columns": [ + { + "expression": "last_seen_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "swarm_nodes_trust_idx": { + "name": "swarm_nodes_trust_idx", + "columns": [ + { + "expression": "trust_score", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "swarm_nodes_nsfw_idx": { + "name": "swarm_nodes_nsfw_idx", + "columns": [ + { + "expression": "is_nsfw", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "swarm_nodes_domain_unique": { + "name": "swarm_nodes_domain_unique", + "nullsNotDistinct": false, + "columns": [ + "domain" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.swarm_seeds": { + "name": "swarm_seeds", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "domain": { + "name": "domain", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "priority": { + "name": "priority", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 100 + }, + "is_enabled": { + "name": "is_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "last_contact_at": { + "name": "last_contact_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "consecutive_failures": { + "name": "consecutive_failures", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "swarm_seeds_enabled_idx": { + "name": "swarm_seeds_enabled_idx", + "columns": [ + { + "expression": "is_enabled", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "swarm_seeds_priority_idx": { + "name": "swarm_seeds_priority_idx", + "columns": [ + { + "expression": "priority", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "swarm_seeds_domain_unique": { + "name": "swarm_seeds_domain_unique", + "nullsNotDistinct": false, + "columns": [ + "domain" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.swarm_sync_log": { + "name": "swarm_sync_log", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "remote_domain": { + "name": "remote_domain", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "direction": { + "name": "direction", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "nodes_received": { + "name": "nodes_received", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "nodes_sent": { + "name": "nodes_sent", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "handles_received": { + "name": "handles_received", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "handles_sent": { + "name": "handles_sent", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "success": { + "name": "success", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "duration_ms": { + "name": "duration_ms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "swarm_sync_log_remote_idx": { + "name": "swarm_sync_log_remote_idx", + "columns": [ + { + "expression": "remote_domain", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "swarm_sync_log_created_idx": { + "name": "swarm_sync_log_created_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "did": { + "name": "did", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "handle": { + "name": "handle", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password_hash": { + "name": "password_hash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "display_name": { + "name": "display_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "bio": { + "name": "bio", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "avatar_url": { + "name": "avatar_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "header_url": { + "name": "header_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "private_key_encrypted": { + "name": "private_key_encrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "node_id": { + "name": "node_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "is_bot": { + "name": "is_bot", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "bot_owner_id": { + "name": "bot_owner_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "is_nsfw": { + "name": "is_nsfw", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "nsfw_enabled": { + "name": "nsfw_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "age_verified_at": { + "name": "age_verified_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "is_suspended": { + "name": "is_suspended", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "suspension_reason": { + "name": "suspension_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "suspended_at": { + "name": "suspended_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "is_silenced": { + "name": "is_silenced", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "silence_reason": { + "name": "silence_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "silenced_at": { + "name": "silenced_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "moved_to": { + "name": "moved_to", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "moved_from": { + "name": "moved_from", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "migrated_at": { + "name": "migrated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "followers_count": { + "name": "followers_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "following_count": { + "name": "following_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "posts_count": { + "name": "posts_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "website": { + "name": "website", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "users_handle_idx": { + "name": "users_handle_idx", + "columns": [ + { + "expression": "handle", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "users_did_idx": { + "name": "users_did_idx", + "columns": [ + { + "expression": "did", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "users_suspended_idx": { + "name": "users_suspended_idx", + "columns": [ + { + "expression": "is_suspended", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "users_silenced_idx": { + "name": "users_silenced_idx", + "columns": [ + { + "expression": "is_silenced", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "users_is_bot_idx": { + "name": "users_is_bot_idx", + "columns": [ + { + "expression": "is_bot", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "users_bot_owner_idx": { + "name": "users_bot_owner_idx", + "columns": [ + { + "expression": "bot_owner_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "users_nsfw_idx": { + "name": "users_nsfw_idx", + "columns": [ + { + "expression": "is_nsfw", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "users_node_id_nodes_id_fk": { + "name": "users_node_id_nodes_id_fk", + "tableFrom": "users", + "tableTo": "nodes", + "columnsFrom": [ + "node_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "users_bot_owner_id_users_id_fk": { + "name": "users_bot_owner_id_users_id_fk", + "tableFrom": "users", + "tableTo": "users", + "columnsFrom": [ + "bot_owner_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "users_did_unique": { + "name": "users_did_unique", + "nullsNotDistinct": false, + "columns": [ + "did" + ] + }, + "users_handle_unique": { + "name": "users_handle_unique", + "nullsNotDistinct": false, + "columns": [ + "handle" + ] + }, + "users_email_unique": { + "name": "users_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/drizzle/meta/_journal.json b/drizzle/meta/_journal.json index 0182dc9..61502ad 100644 --- a/drizzle/meta/_journal.json +++ b/drizzle/meta/_journal.json @@ -36,6 +36,13 @@ "when": 1769377790354, "tag": "0004_luxuriant_lockheed", "breakpoints": true + }, + { + "idx": 5, + "version": "7", + "when": 1769422771465, + "tag": "0005_yummy_millenium_guard", + "breakpoints": true } ] } \ No newline at end of file diff --git a/src/db/schema.ts b/src/db/schema.ts index 4373eb1..a47b6db 100644 --- a/src/db/schema.ts +++ b/src/db/schema.ts @@ -1,4 +1,4 @@ -import { pgTable, text, timestamp, uuid, integer, boolean, index, foreignKey } from 'drizzle-orm/pg-core'; +import { pgTable, text, timestamp, uuid, integer, boolean, index, foreignKey, uniqueIndex } from 'drizzle-orm/pg-core'; import { relations } from 'drizzle-orm'; // ============================================ @@ -252,7 +252,7 @@ export const remoteFollows = pgTable('remote_follows', { export const remoteFollowers = pgTable('remote_followers', { id: uuid('id').primaryKey().defaultRandom(), userId: uuid('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }), // Local user being followed - actorUrl: text('actor_url').notNull().unique(), // Remote actor URL (unique per local user) + actorUrl: text('actor_url').notNull(), // Remote actor URL inboxUrl: text('inbox_url').notNull(), // Remote user's inbox sharedInboxUrl: text('shared_inbox_url'), // Optional shared inbox handle: text('handle'), // Remote user's handle (e.g., user@mastodon.social) @@ -261,6 +261,7 @@ export const remoteFollowers = pgTable('remote_followers', { }, (table) => [ index('remote_followers_user_idx').on(table.userId), index('remote_followers_actor_idx').on(table.actorUrl), + uniqueIndex('remote_followers_user_actor_unique').on(table.userId, table.actorUrl), ]); // ============================================