{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "database-schema-viewer",
  "title": "Database Schema Viewer",
  "type": "registry:page",
  "files": [
    {
      "path": "packages/registry-vue/blocks/database-schema-viewer/DatabaseSchemaViewer.vue",
      "content": "<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport type { HTMLAttributes } from 'vue'\nimport {\n  ArrowRight,\n  Check,\n  Clock,\n  Code2,\n  Copy,\n  Database,\n  Download,\n  HardDrive,\n  Key,\n  Layers,\n  Link2,\n  Search,\n  Table2,\n} from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card } from '@/components/ui/card'\nimport { Input } from '@/components/ui/input'\nimport { Separator } from '@/components/ui/separator'\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'\n\ninterface ColumnDefinition {\n  name: string\n  type: string\n  nullable: boolean\n  defaultValue: string | null\n  isPrimaryKey?: boolean\n  isForeignKey?: boolean\n  foreignKeyRef?: string\n  description?: string\n}\n\ninterface ForeignKeyDefinition {\n  name: string\n  column: string\n  foreignTable: string\n  foreignColumn: string\n  onDelete: 'CASCADE' | 'RESTRICT' | 'SET NULL' | 'NO ACTION'\n  onUpdate: 'CASCADE' | 'RESTRICT' | 'SET NULL' | 'NO ACTION'\n}\n\ninterface IndexDefinition {\n  name: string\n  type: 'B-Tree' | 'GIN' | 'GiST' | 'Hash'\n  columns: string[]\n  size: string\n  isUnique?: boolean\n  isPrimary?: boolean\n}\n\ninterface TableSchema {\n  name: string\n  schema: string\n  rowCount: number\n  rowCountFormatted: string\n  size: string\n  primaryKey: string\n  lastAnalyzed: string\n  description: string\n  columns: ColumnDefinition[]\n  foreignKeys: ForeignKeyDefinition[]\n  indexes: IndexDefinition[]\n  ddl: string\n}\n\nconst props = defineProps<{\n  class?: HTMLAttributes['class']\n}>()\n\nconst searchQuery = ref('')\nconst selectedTableName = ref('orders')\nconst activeTab = ref('columns')\nconst copiedDDL = ref(false)\nconst exportedAll = ref(false)\n\nconst tables: TableSchema[] = [\n  {\n    name: 'users',\n    schema: 'public',\n    rowCount: 42850,\n    rowCountFormatted: '42,850 rows',\n    size: '18.4 MB',\n    primaryKey: 'id (UUID)',\n    lastAnalyzed: '12 mins ago',\n    description: 'User accounts, authentication identities, role assignments, and profile metadata.',\n    columns: [\n      {\n        name: 'id',\n        type: 'uuid',\n        nullable: false,\n        defaultValue: 'gen_random_uuid()',\n        isPrimaryKey: true,\n        description: 'Unique identifier for the user',\n      },\n      {\n        name: 'email',\n        type: 'varchar(255)',\n        nullable: false,\n        defaultValue: null,\n        description: 'Verified primary contact email',\n      },\n      {\n        name: 'encrypted_password',\n        type: 'varchar(255)',\n        nullable: false,\n        defaultValue: null,\n        description: 'Bcrypt hashed password digest',\n      },\n      {\n        name: 'full_name',\n        type: 'varchar(100)',\n        nullable: true,\n        defaultValue: null,\n        description: 'Display name or legal identity',\n      },\n      {\n        name: 'role',\n        type: 'varchar(32)',\n        nullable: false,\n        defaultValue: \"'member'\",\n        description: 'System authorization role',\n      },\n      {\n        name: 'avatar_url',\n        type: 'text',\n        nullable: true,\n        defaultValue: null,\n        description: 'Remote profile avatar image URL',\n      },\n      {\n        name: 'is_verified',\n        type: 'boolean',\n        nullable: false,\n        defaultValue: 'false',\n        description: 'Email verification status flag',\n      },\n      {\n        name: 'created_at',\n        type: 'timestamptz',\n        nullable: false,\n        defaultValue: 'CURRENT_TIMESTAMP',\n        description: 'Account creation timestamp',\n      },\n      {\n        name: 'updated_at',\n        type: 'timestamptz',\n        nullable: false,\n        defaultValue: 'CURRENT_TIMESTAMP',\n        description: 'Last record modification timestamp',\n      },\n    ],\n    foreignKeys: [],\n    indexes: [\n      { name: 'users_pkey', type: 'B-Tree', columns: ['id'], size: '1.2 MB', isPrimary: true, isUnique: true },\n      { name: 'idx_users_email', type: 'B-Tree', columns: ['email'], size: '940 KB', isUnique: true },\n      { name: 'idx_users_role_created', type: 'B-Tree', columns: ['role', 'created_at DESC'], size: '1.8 MB' },\n    ],\n    ddl: `CREATE TABLE public.users (\n  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n  email varchar(255) NOT NULL UNIQUE,\n  encrypted_password varchar(255) NOT NULL,\n  full_name varchar(100),\n  role varchar(32) NOT NULL DEFAULT 'member',\n  avatar_url text,\n  is_verified boolean NOT NULL DEFAULT false,\n  created_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  updated_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  CONSTRAINT chk_users_role CHECK (role IN ('admin', 'member', 'viewer'))\n);`,\n  },\n  {\n    name: 'orders',\n    schema: 'public',\n    rowCount: 148290,\n    rowCountFormatted: '148,290 rows',\n    size: '64.2 MB',\n    primaryKey: 'id (UUID)',\n    lastAnalyzed: '2 mins ago',\n    description: 'Customer transactional purchase orders, fulfillment status, and payment totals.',\n    columns: [\n      {\n        name: 'id',\n        type: 'uuid',\n        nullable: false,\n        defaultValue: 'gen_random_uuid()',\n        isPrimaryKey: true,\n        description: 'Unique order identifier',\n      },\n      {\n        name: 'order_number',\n        type: 'varchar(48)',\n        nullable: false,\n        defaultValue: null,\n        description: 'Human-readable sequential invoice reference',\n      },\n      {\n        name: 'user_id',\n        type: 'uuid',\n        nullable: false,\n        defaultValue: null,\n        isForeignKey: true,\n        foreignKeyRef: 'users.id',\n        description: 'Purchaser account reference',\n      },\n      {\n        name: 'status',\n        type: 'varchar(32)',\n        nullable: false,\n        defaultValue: \"'pending'\",\n        description: 'Order lifecycle stage',\n      },\n      {\n        name: 'total_amount',\n        type: 'numeric(10,2)',\n        nullable: false,\n        defaultValue: '0.00',\n        description: 'Grand total charged in base currency',\n      },\n      {\n        name: 'currency',\n        type: 'varchar(3)',\n        nullable: false,\n        defaultValue: \"'USD'\",\n        description: 'ISO 4217 three-letter currency code',\n      },\n      {\n        name: 'billing_address',\n        type: 'jsonb',\n        nullable: true,\n        defaultValue: \"'{}'::jsonb\",\n        description: 'Structured billing snapshot',\n      },\n      {\n        name: 'shipping_address',\n        type: 'jsonb',\n        nullable: true,\n        defaultValue: \"'{}'::jsonb\",\n        description: 'Structured destination address',\n      },\n      {\n        name: 'shipped_at',\n        type: 'timestamptz',\n        nullable: true,\n        defaultValue: null,\n        description: 'Carrier pickup confirmation date',\n      },\n      {\n        name: 'created_at',\n        type: 'timestamptz',\n        nullable: false,\n        defaultValue: 'CURRENT_TIMESTAMP',\n        description: 'Checkout completion timestamp',\n      },\n      {\n        name: 'updated_at',\n        type: 'timestamptz',\n        nullable: false,\n        defaultValue: 'CURRENT_TIMESTAMP',\n        description: 'Order state mutation timestamp',\n      },\n    ],\n    foreignKeys: [\n      {\n        name: 'fk_orders_user_id',\n        column: 'user_id',\n        foreignTable: 'users',\n        foreignColumn: 'id',\n        onDelete: 'CASCADE',\n        onUpdate: 'CASCADE',\n      },\n    ],\n    indexes: [\n      { name: 'orders_pkey', type: 'B-Tree', columns: ['id'], size: '4.8 MB', isPrimary: true, isUnique: true },\n      { name: 'idx_orders_user_id', type: 'B-Tree', columns: ['user_id'], size: '3.4 MB' },\n      { name: 'idx_orders_status_created', type: 'B-Tree', columns: ['status', 'created_at DESC'], size: '5.1 MB' },\n      { name: 'idx_orders_number_unique', type: 'B-Tree', columns: ['order_number'], size: '3.2 MB', isUnique: true },\n    ],\n    ddl: `CREATE TABLE public.orders (\n  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n  order_number varchar(48) NOT NULL UNIQUE,\n  user_id uuid NOT NULL REFERENCES public.users(id) ON DELETE CASCADE ON UPDATE CASCADE,\n  status varchar(32) NOT NULL DEFAULT 'pending',\n  total_amount numeric(10,2) NOT NULL DEFAULT 0.00,\n  currency varchar(3) NOT NULL DEFAULT 'USD',\n  billing_address jsonb DEFAULT '{}'::jsonb,\n  shipping_address jsonb DEFAULT '{}'::jsonb,\n  shipped_at timestamptz,\n  created_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  updated_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP\n);`,\n  },\n  {\n    name: 'order_items',\n    schema: 'public',\n    rowCount: 384120,\n    rowCountFormatted: '384,120 rows',\n    size: '112.5 MB',\n    primaryKey: 'id (UUID)',\n    lastAnalyzed: '8 mins ago',\n    description: 'Granular line items and unit pricing linked to purchase orders.',\n    columns: [\n      {\n        name: 'id',\n        type: 'uuid',\n        nullable: false,\n        defaultValue: 'gen_random_uuid()',\n        isPrimaryKey: true,\n        description: 'Line item primary key',\n      },\n      {\n        name: 'order_id',\n        type: 'uuid',\n        nullable: false,\n        defaultValue: null,\n        isForeignKey: true,\n        foreignKeyRef: 'orders.id',\n        description: 'Parent order reference',\n      },\n      {\n        name: 'product_id',\n        type: 'uuid',\n        nullable: false,\n        defaultValue: null,\n        isForeignKey: true,\n        foreignKeyRef: 'products.id',\n        description: 'Catalog item reference',\n      },\n      { name: 'quantity', type: 'integer', nullable: false, defaultValue: '1', description: 'Units purchased' },\n      {\n        name: 'unit_price',\n        type: 'numeric(10,2)',\n        nullable: false,\n        defaultValue: '0.00',\n        description: 'Unit price captured at purchase',\n      },\n      {\n        name: 'discount_amount',\n        type: 'numeric(10,2)',\n        nullable: false,\n        defaultValue: '0.00',\n        description: 'Item level discount applied',\n      },\n      {\n        name: 'created_at',\n        type: 'timestamptz',\n        nullable: false,\n        defaultValue: 'CURRENT_TIMESTAMP',\n        description: 'Record insertion timestamp',\n      },\n    ],\n    foreignKeys: [\n      {\n        name: 'fk_order_items_order_id',\n        column: 'order_id',\n        foreignTable: 'orders',\n        foreignColumn: 'id',\n        onDelete: 'CASCADE',\n        onUpdate: 'CASCADE',\n      },\n      {\n        name: 'fk_order_items_product_id',\n        column: 'product_id',\n        foreignTable: 'products',\n        foreignColumn: 'id',\n        onDelete: 'RESTRICT',\n        onUpdate: 'CASCADE',\n      },\n    ],\n    indexes: [\n      { name: 'order_items_pkey', type: 'B-Tree', columns: ['id'], size: '12.1 MB', isPrimary: true, isUnique: true },\n      { name: 'idx_order_items_order_id', type: 'B-Tree', columns: ['order_id'], size: '8.9 MB' },\n      { name: 'idx_order_items_product_id', type: 'B-Tree', columns: ['product_id'], size: '8.4 MB' },\n    ],\n    ddl: `CREATE TABLE public.order_items (\n  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n  order_id uuid NOT NULL REFERENCES public.orders(id) ON DELETE CASCADE ON UPDATE CASCADE,\n  product_id uuid NOT NULL REFERENCES public.products(id) ON DELETE RESTRICT ON UPDATE CASCADE,\n  quantity integer NOT NULL DEFAULT 1,\n  unit_price numeric(10,2) NOT NULL DEFAULT 0.00,\n  discount_amount numeric(10,2) NOT NULL DEFAULT 0.00,\n  created_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP\n);`,\n  },\n  {\n    name: 'products',\n    schema: 'public',\n    rowCount: 12400,\n    rowCountFormatted: '12,400 rows',\n    size: '9.8 MB',\n    primaryKey: 'id (UUID)',\n    lastAnalyzed: '45 mins ago',\n    description: 'Catalog products, SKU identifiers, real-time inventory counts, and price tiers.',\n    columns: [\n      {\n        name: 'id',\n        type: 'uuid',\n        nullable: false,\n        defaultValue: 'gen_random_uuid()',\n        isPrimaryKey: true,\n        description: 'Product primary key',\n      },\n      {\n        name: 'sku',\n        type: 'varchar(64)',\n        nullable: false,\n        defaultValue: null,\n        description: 'Stock keeping unit barcode index',\n      },\n      { name: 'name', type: 'varchar(255)', nullable: false, defaultValue: null, description: 'Public product title' },\n      {\n        name: 'description',\n        type: 'text',\n        nullable: true,\n        defaultValue: null,\n        description: 'Detailed marketing specifications',\n      },\n      { name: 'price', type: 'numeric(10,2)', nullable: false, defaultValue: '0.00', description: 'Base retail price' },\n      {\n        name: 'stock_quantity',\n        type: 'integer',\n        nullable: false,\n        defaultValue: '0',\n        description: 'Available warehouse stock',\n      },\n      {\n        name: 'is_active',\n        type: 'boolean',\n        nullable: false,\n        defaultValue: 'true',\n        description: 'Visibility in storefront',\n      },\n      {\n        name: 'metadata',\n        type: 'jsonb',\n        nullable: true,\n        defaultValue: \"'{}'::jsonb\",\n        description: 'Custom attributes and tags',\n      },\n      {\n        name: 'created_at',\n        type: 'timestamptz',\n        nullable: false,\n        defaultValue: 'CURRENT_TIMESTAMP',\n        description: 'Product onboarding timestamp',\n      },\n      {\n        name: 'updated_at',\n        type: 'timestamptz',\n        nullable: false,\n        defaultValue: 'CURRENT_TIMESTAMP',\n        description: 'Last catalog revision',\n      },\n    ],\n    foreignKeys: [],\n    indexes: [\n      { name: 'products_pkey', type: 'B-Tree', columns: ['id'], size: '380 KB', isPrimary: true, isUnique: true },\n      { name: 'idx_products_sku', type: 'B-Tree', columns: ['sku'], size: '290 KB', isUnique: true },\n      { name: 'idx_products_is_active', type: 'B-Tree', columns: ['is_active'], size: '180 KB' },\n    ],\n    ddl: `CREATE TABLE public.products (\n  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n  sku varchar(64) NOT NULL UNIQUE,\n  name varchar(255) NOT NULL,\n  description text,\n  price numeric(10,2) NOT NULL DEFAULT 0.00,\n  stock_quantity integer NOT NULL DEFAULT 0,\n  is_active boolean NOT NULL DEFAULT true,\n  metadata jsonb DEFAULT '{}'::jsonb,\n  created_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  updated_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP\n);`,\n  },\n  {\n    name: 'subscriptions',\n    schema: 'public',\n    rowCount: 19850,\n    rowCountFormatted: '19,850 rows',\n    size: '14.1 MB',\n    primaryKey: 'id (UUID)',\n    lastAnalyzed: '18 mins ago',\n    description: 'Recurring billing contracts, subscription plans, and renewal period bounds.',\n    columns: [\n      {\n        name: 'id',\n        type: 'uuid',\n        nullable: false,\n        defaultValue: 'gen_random_uuid()',\n        isPrimaryKey: true,\n        description: 'Subscription contract ID',\n      },\n      {\n        name: 'user_id',\n        type: 'uuid',\n        nullable: false,\n        defaultValue: null,\n        isForeignKey: true,\n        foreignKeyRef: 'users.id',\n        description: 'Subscriber user ID',\n      },\n      {\n        name: 'plan_tier',\n        type: 'varchar(32)',\n        nullable: false,\n        defaultValue: \"'starter'\",\n        description: 'SaaS plan designation',\n      },\n      {\n        name: 'status',\n        type: 'varchar(32)',\n        nullable: false,\n        defaultValue: \"'active'\",\n        description: 'Lifecycle status',\n      },\n      {\n        name: 'current_period_start',\n        type: 'timestamptz',\n        nullable: false,\n        defaultValue: 'CURRENT_TIMESTAMP',\n        description: 'Current billing window start',\n      },\n      {\n        name: 'current_period_end',\n        type: 'timestamptz',\n        nullable: false,\n        defaultValue: null,\n        description: 'Next scheduled billing date',\n      },\n      {\n        name: 'cancel_at_period_end',\n        type: 'boolean',\n        nullable: false,\n        defaultValue: 'false',\n        description: 'Cancellation intent at renewal',\n      },\n      {\n        name: 'created_at',\n        type: 'timestamptz',\n        nullable: false,\n        defaultValue: 'CURRENT_TIMESTAMP',\n        description: 'Initial signup timestamp',\n      },\n    ],\n    foreignKeys: [\n      {\n        name: 'fk_subscriptions_user_id',\n        column: 'user_id',\n        foreignTable: 'users',\n        foreignColumn: 'id',\n        onDelete: 'CASCADE',\n        onUpdate: 'CASCADE',\n      },\n    ],\n    indexes: [\n      { name: 'subscriptions_pkey', type: 'B-Tree', columns: ['id'], size: '620 KB', isPrimary: true, isUnique: true },\n      { name: 'idx_subscriptions_user_id', type: 'B-Tree', columns: ['user_id'], size: '540 KB' },\n      { name: 'idx_subscriptions_status', type: 'B-Tree', columns: ['status'], size: '410 KB' },\n    ],\n    ddl: `CREATE TABLE public.subscriptions (\n  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n  user_id uuid NOT NULL REFERENCES public.users(id) ON DELETE CASCADE ON UPDATE CASCADE,\n  plan_tier varchar(32) NOT NULL DEFAULT 'starter',\n  status varchar(32) NOT NULL DEFAULT 'active',\n  current_period_start timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  current_period_end timestamptz NOT NULL,\n  cancel_at_period_end boolean NOT NULL DEFAULT false,\n  created_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP\n);`,\n  },\n  {\n    name: 'audit_logs',\n    schema: 'public',\n    rowCount: 920400,\n    rowCountFormatted: '920,400 rows',\n    size: '201.0 MB',\n    primaryKey: 'id (UUID)',\n    lastAnalyzed: '1 min ago',\n    description: 'Immutable security event stream, compliance audit records, and state change captures.',\n    columns: [\n      {\n        name: 'id',\n        type: 'uuid',\n        nullable: false,\n        defaultValue: 'gen_random_uuid()',\n        isPrimaryKey: true,\n        description: 'Event ledger entry identifier',\n      },\n      {\n        name: 'actor_id',\n        type: 'uuid',\n        nullable: true,\n        defaultValue: null,\n        isForeignKey: true,\n        foreignKeyRef: 'users.id',\n        description: 'Initiating user account reference',\n      },\n      {\n        name: 'action',\n        type: 'varchar(64)',\n        nullable: false,\n        defaultValue: null,\n        description: 'Standardized action identifier',\n      },\n      {\n        name: 'entity_type',\n        type: 'varchar(64)',\n        nullable: false,\n        defaultValue: null,\n        description: 'Target entity namespace',\n      },\n      {\n        name: 'entity_id',\n        type: 'varchar(128)',\n        nullable: false,\n        defaultValue: null,\n        description: 'Target entity unique identifier',\n      },\n      { name: 'ip_address', type: 'inet', nullable: true, defaultValue: null, description: 'Client network IP' },\n      {\n        name: 'payload',\n        type: 'jsonb',\n        nullable: true,\n        defaultValue: \"'{}'::jsonb\",\n        description: 'Full before/after state diff',\n      },\n      {\n        name: 'created_at',\n        type: 'timestamptz',\n        nullable: false,\n        defaultValue: 'CURRENT_TIMESTAMP',\n        description: 'Exact audit record timestamp',\n      },\n    ],\n    foreignKeys: [\n      {\n        name: 'fk_audit_logs_actor_id',\n        column: 'actor_id',\n        foreignTable: 'users',\n        foreignColumn: 'id',\n        onDelete: 'SET NULL',\n        onUpdate: 'CASCADE',\n      },\n    ],\n    indexes: [\n      { name: 'audit_logs_pkey', type: 'B-Tree', columns: ['id'], size: '28.4 MB', isPrimary: true, isUnique: true },\n      { name: 'idx_audit_logs_actor_id', type: 'B-Tree', columns: ['actor_id'], size: '19.2 MB' },\n      {\n        name: 'idx_audit_logs_action_created',\n        type: 'B-Tree',\n        columns: ['action', 'created_at DESC'],\n        size: '32.6 MB',\n      },\n      { name: 'idx_audit_logs_entity', type: 'B-Tree', columns: ['entity_type', 'entity_id'], size: '24.1 MB' },\n    ],\n    ddl: `CREATE TABLE public.audit_logs (\n  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n  actor_id uuid REFERENCES public.users(id) ON DELETE SET NULL ON UPDATE CASCADE,\n  action varchar(64) NOT NULL,\n  entity_type varchar(64) NOT NULL,\n  entity_id varchar(128) NOT NULL,\n  ip_address inet,\n  payload jsonb DEFAULT '{}'::jsonb,\n  created_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP\n);`,\n  },\n]\n\nconst filteredTables = computed(() => {\n  const query = searchQuery.value.trim().toLowerCase()\n  if (!query) return tables\n  return tables.filter(\n    (table) =>\n      table.name.toLowerCase().includes(query) ||\n      table.description.toLowerCase().includes(query) ||\n      table.columns.some((col) => col.name.toLowerCase().includes(query)),\n  )\n})\n\nconst activeTable = computed(() => {\n  return tables.find((t) => t.name === selectedTableName.value) ?? tables[0]\n})\n\nfunction formatRowCount(count: number): string {\n  if (count >= 1_000_000) return `${(count / 1_000_000).toFixed(1)}M`\n  if (count >= 1_000) return `${(count / 1_000).toFixed(1)}k`\n  return String(count)\n}\n\nfunction copyToClipboard(text: string) {\n  if (typeof navigator !== 'undefined' && navigator.clipboard) {\n    navigator.clipboard.writeText(text)\n    copiedDDL.value = true\n    setTimeout(() => {\n      copiedDDL.value = false\n    }, 2000)\n  }\n}\n\nfunction exportAllDDL() {\n  const allSql = tables.map((t) => `-- Table: ${t.name}\\n${t.ddl}`).join('\\n\\n')\n  if (typeof navigator !== 'undefined' && navigator.clipboard) {\n    navigator.clipboard.writeText(allSql)\n    exportedAll.value = true\n    setTimeout(() => {\n      exportedAll.value = false\n    }, 2000)\n  }\n}\n</script>\n\n<template>\n  <div\n    data-slot=\"database-schema-viewer\"\n    :class=\"\n      cn('bg-background text-foreground border-border w-full overflow-hidden rounded-xl border shadow-xs', props.class)\n    \"\n  >\n    <!-- Top Database Header -->\n    <header class=\"border-border bg-card/60 border-b px-4 py-3.5 sm:px-6\">\n      <div class=\"flex flex-col gap-4 md:flex-row md:items-center md:justify-between\">\n        <div class=\"flex flex-wrap items-center gap-3\">\n          <div class=\"bg-primary/10 text-primary flex size-9 items-center justify-center rounded-lg\">\n            <Database class=\"size-4.5\" />\n          </div>\n          <div class=\"flex flex-col\">\n            <div class=\"flex flex-wrap items-center gap-2\">\n              <span class=\"font-mono text-sm font-semibold tracking-tight\">production-cluster-pg16</span>\n              <span class=\"bg-success flex size-2 rounded-full\" title=\"Connected & Synced\" />\n              <Badge variant=\"secondary\" class=\"font-mono text-xs font-normal\">PostgreSQL 16.2</Badge>\n            </div>\n            <span class=\"text-muted-foreground text-xs\">18 tables · 420 MB</span>\n          </div>\n        </div>\n\n        <div class=\"flex flex-wrap items-center gap-2\">\n          <div class=\"relative w-full sm:w-60\">\n            <Search class=\"text-muted-foreground absolute top-1/2 left-2.5 size-3.5 -translate-y-1/2\" />\n            <Input v-model=\"searchQuery\" placeholder=\"Search tables or columns...\" class=\"h-8 pl-8 text-xs\" />\n          </div>\n          <Button\n            aria-label=\"Download attachment\"\n            variant=\"outline\"\n            size=\"sm\"\n            class=\"h-8 shrink-0 gap-1.5 text-xs\"\n            @click=\"exportAllDDL\"\n          >\n            <Check v-if=\"exportedAll\" class=\"text-success size-3.5\" />\n            <Download v-else class=\"size-3.5\" />\n            {{ exportedAll ? 'DDL Copied!' : 'Export DDL' }}\n          </Button>\n        </div>\n      </div>\n    </header>\n\n    <!-- Two-Column Inspector Body -->\n    <div class=\"grid grid-cols-1 md:grid-cols-[240px_1fr] lg:grid-cols-[260px_1fr]\">\n      <!-- Left Sidebar: Tables List -->\n      <aside class=\"border-border bg-muted/20 border-r p-3 sm:p-4\">\n        <div class=\"mb-2.5 flex items-center justify-between gap-x-2 px-1\">\n          <span class=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\">Database Tables</span>\n          <Badge variant=\"secondary\" class=\"h-5 px-1.5 font-mono text-xs\">{{ filteredTables.length }}</Badge>\n        </div>\n\n        <div class=\"space-y-1\">\n          <button\n            v-for=\"table in filteredTables\"\n            :key=\"table.name\"\n            type=\"button\"\n            :class=\"\n              cn(\n                'flex w-full items-center justify-between rounded-lg px-2.5 py-2 text-left text-xs transition-colors',\n                selectedTableName === table.name\n                  ? 'bg-primary/10 text-primary border-primary/20 border font-medium shadow-xs'\n                  : 'text-muted-foreground hover:bg-muted/70 hover:text-foreground border border-transparent',\n              )\n            \"\n            @click=\"selectedTableName = table.name\"\n          >\n            <div class=\"flex min-w-0 items-center gap-2\">\n              <Table2 class=\"size-3.5 shrink-0 opacity-70\" />\n              <span class=\"truncate font-mono\">{{ table.name }}</span>\n            </div>\n            <span class=\"bg-muted text-muted-foreground ml-2 shrink-0 rounded-full px-1.5 py-0.5 font-mono text-xs\">\n              {{ formatRowCount(table.rowCount) }}\n            </span>\n          </button>\n\n          <div v-if=\"filteredTables.length === 0\" class=\"text-muted-foreground py-6 text-center text-xs\">\n            No matching tables found\n          </div>\n        </div>\n\n        <Separator class=\"my-4\" />\n\n        <div class=\"border-border/70 bg-card space-y-1.5 rounded-lg border p-3 text-xs\">\n          <div class=\"text-muted-foreground flex items-center justify-between gap-x-2\">\n            <span>Encoding:</span>\n            <span class=\"text-foreground font-mono\">UTF8</span>\n          </div>\n          <div class=\"text-muted-foreground flex items-center justify-between gap-x-2\">\n            <span>Collation:</span>\n            <span class=\"text-foreground font-mono\">en_US.utf8</span>\n          </div>\n          <div class=\"text-muted-foreground flex items-center justify-between gap-x-2\">\n            <span>Default Schema:</span>\n            <span class=\"text-foreground font-mono\">public</span>\n          </div>\n        </div>\n      </aside>\n\n      <!-- Right Main Panel: Table Detail Inspector -->\n      <main class=\"bg-card/30 min-w-0 space-y-5 p-4 sm:p-6\">\n        <!-- Active Table Header & Stats -->\n        <div class=\"border-border space-y-3 border-b pb-2\">\n          <div class=\"flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between\">\n            <div class=\"space-y-1\">\n              <div class=\"flex flex-wrap items-center gap-2\">\n                <span class=\"text-muted-foreground font-mono text-sm\">public.</span>\n                <h2 class=\"text-foreground font-mono text-xl font-bold tracking-tight break-all\">\n                  {{ activeTable.name }}\n                </h2>\n                <Badge variant=\"outline\" class=\"font-mono text-xs font-normal\">BASE TABLE</Badge>\n              </div>\n              <p class=\"text-muted-foreground text-xs\">{{ activeTable.description }}</p>\n            </div>\n\n            <Button\n              variant=\"outline\"\n              size=\"sm\"\n              class=\"h-8 shrink-0 gap-1.5 self-start text-xs sm:self-auto\"\n              @click=\"copyToClipboard(activeTable.ddl)\"\n            >\n              <Check v-if=\"copiedDDL\" class=\"text-success size-3.5\" />\n              <Copy v-else class=\"size-3.5\" />\n              {{ copiedDDL ? 'Copied DDL' : 'Copy Table DDL' }}\n            </Button>\n          </div>\n\n          <!-- Metadata Stat Badges -->\n          <div class=\"flex flex-wrap items-center gap-2 pt-1\">\n            <div\n              class=\"border-border bg-card text-muted-foreground inline-flex items-center gap-1.5 rounded-md border px-2.5 py-1 text-xs\"\n            >\n              <Table2 class=\"text-foreground/70 size-3.5\" />\n              <span>Rows:</span>\n              <span class=\"text-foreground font-mono font-medium\">{{ activeTable.rowCountFormatted }}</span>\n            </div>\n\n            <div\n              class=\"border-border bg-card text-muted-foreground inline-flex items-center gap-1.5 rounded-md border px-2.5 py-1 text-xs\"\n            >\n              <Key class=\"text-warning size-3.5\" />\n              <span>Primary Key:</span>\n              <span class=\"text-foreground font-mono font-medium\">{{ activeTable.primaryKey }}</span>\n            </div>\n\n            <div\n              class=\"border-border bg-card text-muted-foreground inline-flex items-center gap-1.5 rounded-md border px-2.5 py-1 text-xs\"\n            >\n              <HardDrive class=\"text-foreground/70 size-3.5\" />\n              <span>Table Size:</span>\n              <span class=\"text-foreground font-mono font-medium\">{{ activeTable.size }}</span>\n            </div>\n\n            <div\n              class=\"border-border bg-card text-muted-foreground inline-flex items-center gap-1.5 rounded-md border px-2.5 py-1 text-xs\"\n            >\n              <Clock class=\"text-foreground/70 size-3.5\" />\n              <span>Last Analyzed:</span>\n              <span class=\"text-foreground font-medium\">{{ activeTable.lastAnalyzed }}</span>\n            </div>\n          </div>\n        </div>\n\n        <!-- View Tabs Navigation -->\n        <Tabs v-model=\"activeTab\" default-value=\"columns\" class=\"w-full\">\n          <TabsList class=\"grid h-9 w-full grid-cols-2 p-1 md:grid-cols-4\">\n            <TabsTrigger value=\"columns\" class=\"gap-1.5 text-xs\">\n              <Table2 class=\"size-3.5\" />\n              <span>Columns</span>\n              <span class=\"bg-muted py-0.2 rounded-full px-1.5 font-mono text-xs\">{{\n                activeTable.columns.length\n              }}</span>\n            </TabsTrigger>\n            <TabsTrigger value=\"foreign-keys\" class=\"gap-1.5 text-xs\">\n              <Link2 class=\"size-3.5\" />\n              <span>Foreign Keys</span>\n              <span class=\"bg-muted py-0.2 rounded-full px-1.5 font-mono text-xs\">{{\n                activeTable.foreignKeys.length\n              }}</span>\n            </TabsTrigger>\n            <TabsTrigger value=\"indexes\" class=\"gap-1.5 text-xs\">\n              <Layers class=\"size-3.5\" />\n              <span>Indexes</span>\n              <span class=\"bg-muted py-0.2 rounded-full px-1.5 font-mono text-xs\">{{\n                activeTable.indexes.length\n              }}</span>\n            </TabsTrigger>\n            <TabsTrigger value=\"ddl\" class=\"gap-1.5 text-xs\">\n              <Code2 class=\"size-3.5\" />\n              <span>SQL DDL Preview</span>\n            </TabsTrigger>\n          </TabsList>\n\n          <!-- Tab 1: Columns List -->\n          <TabsContent value=\"columns\" class=\"mt-4\">\n            <Card class=\"border-border overflow-hidden border shadow-none\">\n              <div class=\"overflow-x-auto\">\n                <Table>\n                  <TableHeader>\n                    <TableRow class=\"bg-muted/40 hover:bg-muted/40\">\n                      <TableHead class=\"text-xs font-semibold\">Column Name</TableHead>\n                      <TableHead class=\"text-xs font-semibold\">Data Type</TableHead>\n                      <TableHead class=\"text-xs font-semibold\">Nullable</TableHead>\n                      <TableHead class=\"text-xs font-semibold\">Default Value</TableHead>\n                      <TableHead class=\"text-xs font-semibold\">Constraints</TableHead>\n                      <TableHead class=\"text-xs font-semibold\">Description</TableHead>\n                    </TableRow>\n                  </TableHeader>\n                  <TableBody>\n                    <TableRow v-for=\"col in activeTable.columns\" :key=\"col.name\" class=\"text-xs\">\n                      <TableCell class=\"font-mono font-medium\">\n                        <div class=\"flex items-center gap-1.5\">\n                          <Key v-if=\"col.isPrimaryKey\" class=\"text-warning size-3.5 shrink-0\" />\n                          <Link2 v-else-if=\"col.isForeignKey\" class=\"text-info size-3.5 shrink-0\" />\n                          <span :class=\"cn(col.isPrimaryKey && 'text-warning font-semibold')\">\n                            {{ col.name }}\n                          </span>\n                        </div>\n                      </TableCell>\n                      <TableCell>\n                        <Badge variant=\"secondary\" class=\"font-mono text-xs font-normal\">\n                          {{ col.type }}\n                        </Badge>\n                      </TableCell>\n                      <TableCell>\n                        <Badge v-if=\"!col.nullable\" variant=\"outline\" class=\"text-muted-foreground text-xs\">\n                          NOT NULL\n                        </Badge>\n                        <span v-else class=\"text-muted-foreground\">NULL</span>\n                      </TableCell>\n                      <TableCell class=\"text-muted-foreground font-mono\">\n                        {{ col.defaultValue ?? '—' }}\n                      </TableCell>\n                      <TableCell>\n                        <div class=\"flex flex-wrap items-center gap-1\">\n                          <Badge v-if=\"col.isPrimaryKey\" class=\"border-warning/30 bg-warning/15 text-warning text-xs\">\n                            PK\n                          </Badge>\n                          <Badge v-if=\"col.isForeignKey\" variant=\"secondary\" class=\"gap-1 font-mono text-xs\">\n                            FK &rarr; {{ col.foreignKeyRef }}\n                          </Badge>\n                          <span v-if=\"!col.isPrimaryKey && !col.isForeignKey\" class=\"text-muted-foreground\">—</span>\n                        </div>\n                      </TableCell>\n                      <TableCell class=\"text-muted-foreground max-w-[200px] truncate\">\n                        {{ col.description ?? '—' }}\n                      </TableCell>\n                    </TableRow>\n                  </TableBody>\n                </Table>\n              </div>\n            </Card>\n          </TabsContent>\n\n          <!-- Tab 2: Foreign Keys & Relations -->\n          <TabsContent value=\"foreign-keys\" class=\"mt-4 space-y-3\">\n            <div v-if=\"activeTable.foreignKeys.length > 0\" class=\"space-y-3\">\n              <Card\n                v-for=\"fk in activeTable.foreignKeys\"\n                :key=\"fk.name\"\n                class=\"border-border space-y-3 border p-4 shadow-none\"\n              >\n                <div class=\"border-border flex flex-wrap items-center justify-between gap-2 border-b pb-2\">\n                  <div class=\"flex flex-wrap items-center gap-2\">\n                    <Link2 class=\"text-info size-4\" />\n                    <span class=\"text-foreground font-mono text-xs font-semibold\">{{ fk.name }}</span>\n                  </div>\n                  <Badge variant=\"secondary\" class=\"font-mono text-xs\">Many-to-One (N:1)</Badge>\n                </div>\n\n                <div\n                  class=\"bg-muted/40 border-border/60 flex flex-col justify-between gap-3 rounded-lg border p-3 sm:flex-row sm:items-center\"\n                >\n                  <div class=\"flex flex-wrap items-center gap-2\">\n                    <span class=\"text-muted-foreground text-xs\">Source:</span>\n                    <Badge variant=\"outline\" class=\"font-mono text-xs\"> {{ activeTable.name }}.{{ fk.column }} </Badge>\n                  </div>\n\n                  <ArrowRight class=\"text-muted-foreground hidden size-4 sm:block\" />\n\n                  <div class=\"flex flex-wrap items-center gap-2\">\n                    <span class=\"text-muted-foreground text-xs\">References:</span>\n                    <Badge variant=\"default\" class=\"font-mono text-xs\">\n                      {{ fk.foreignTable }}.{{ fk.foreignColumn }}\n                    </Badge>\n                  </div>\n                </div>\n\n                <div class=\"grid grid-cols-1 gap-2 pt-1 text-xs sm:grid-cols-2\">\n                  <div\n                    class=\"border-border/50 bg-card flex items-center justify-between gap-x-2 rounded-md border px-2.5 py-1.5\"\n                  >\n                    <span class=\"text-muted-foreground\">On Delete Action:</span>\n                    <Badge variant=\"secondary\" class=\"font-mono text-xs\">{{ fk.onDelete }}</Badge>\n                  </div>\n                  <div\n                    class=\"border-border/50 bg-card flex items-center justify-between gap-x-2 rounded-md border px-2.5 py-1.5\"\n                  >\n                    <span class=\"text-muted-foreground\">On Update Action:</span>\n                    <Badge variant=\"secondary\" class=\"font-mono text-xs\">{{ fk.onUpdate }}</Badge>\n                  </div>\n                </div>\n              </Card>\n            </div>\n\n            <Card v-else class=\"border-border border border-dashed p-8 text-center\">\n              <div class=\"flex flex-col items-center justify-center space-y-2\">\n                <div class=\"bg-muted text-muted-foreground flex size-10 items-center justify-center rounded-full\">\n                  <Link2 class=\"size-5\" />\n                </div>\n                <h3 class=\"text-sm font-semibold\">No Outbound Foreign Keys</h3>\n                <p class=\"text-muted-foreground max-w-sm text-xs\">\n                  Table <span class=\"font-mono font-medium\">{{ activeTable.name }}</span> has no outbound relations. It\n                  acts as an independent entity or is referenced by downstream child tables.\n                </p>\n              </div>\n            </Card>\n          </TabsContent>\n\n          <!-- Tab 3: Indexes & Constraints -->\n          <TabsContent value=\"indexes\" class=\"mt-4\">\n            <Card class=\"border-border overflow-hidden border shadow-none\">\n              <div class=\"overflow-x-auto\">\n                <Table>\n                  <TableHeader>\n                    <TableRow class=\"bg-muted/40 hover:bg-muted/40\">\n                      <TableHead class=\"text-xs font-semibold\">Index Name</TableHead>\n                      <TableHead class=\"text-xs font-semibold\">Method</TableHead>\n                      <TableHead class=\"text-xs font-semibold\">Indexed Columns</TableHead>\n                      <TableHead class=\"text-xs font-semibold\">Index Size</TableHead>\n                      <TableHead class=\"text-xs font-semibold\">Constraint Type</TableHead>\n                    </TableRow>\n                  </TableHeader>\n                  <TableBody>\n                    <TableRow v-for=\"idx in activeTable.indexes\" :key=\"idx.name\" class=\"text-xs\">\n                      <TableCell class=\"font-mono font-medium\">\n                        <div class=\"flex items-center gap-1.5\">\n                          <Layers class=\"text-muted-foreground size-3.5 shrink-0\" />\n                          <span>{{ idx.name }}</span>\n                        </div>\n                      </TableCell>\n                      <TableCell>\n                        <Badge variant=\"secondary\" class=\"font-mono text-xs\">\n                          {{ idx.type }}\n                        </Badge>\n                      </TableCell>\n                      <TableCell class=\"text-foreground font-mono\">\n                        {{ idx.columns.join(', ') }}\n                      </TableCell>\n                      <TableCell class=\"text-muted-foreground font-mono\">\n                        {{ idx.size }}\n                      </TableCell>\n                      <TableCell>\n                        <Badge v-if=\"idx.isPrimary\" class=\"border-warning/30 bg-warning/15 text-warning text-xs\">\n                          PRIMARY KEY\n                        </Badge>\n                        <Badge v-else-if=\"idx.isUnique\" variant=\"secondary\" class=\"text-xs\"> UNIQUE </Badge>\n                        <Badge v-else variant=\"outline\" class=\"text-muted-foreground text-xs\"> INDEX </Badge>\n                      </TableCell>\n                    </TableRow>\n                  </TableBody>\n                </Table>\n              </div>\n            </Card>\n          </TabsContent>\n\n          <!-- Tab 4: SQL DDL Preview -->\n          <TabsContent value=\"ddl\" class=\"mt-4\">\n            <div class=\"border-border bg-muted/40 overflow-hidden rounded-lg border\">\n              <div class=\"border-border bg-card flex items-center justify-between gap-x-2 border-b px-4 py-2.5\">\n                <div class=\"flex flex-wrap items-center gap-2\">\n                  <Code2 class=\"text-primary size-4\" />\n                  <span class=\"text-foreground font-mono text-xs font-medium\">{{ activeTable.name }}.sql</span>\n                  <Badge variant=\"secondary\" class=\"font-mono text-xs\">PostgreSQL DDL</Badge>\n                </div>\n                <Button variant=\"ghost\" size=\"sm\" class=\"h-7 gap-1 text-xs\" @click=\"copyToClipboard(activeTable.ddl)\">\n                  <Check v-if=\"copiedDDL\" class=\"text-success size-3\" />\n                  <Copy v-else class=\"size-3\" />\n                  {{ copiedDDL ? 'Copied' : 'Copy' }}\n                </Button>\n              </div>\n\n              <div\n                class=\"overflow-x-auto bg-neutral-950 p-4 font-mono text-xs leading-relaxed text-neutral-100 dark:bg-neutral-950\"\n              >\n                <pre class=\"whitespace-pre\"><code>{{ activeTable.ddl }}</code></pre>\n              </div>\n            </div>\n          </TabsContent>\n        </Tabs>\n      </main>\n    </div>\n  </div>\n</template>\n",
      "type": "registry:page",
      "target": "~/app/components/blocks/DatabaseSchemaViewer.vue"
    }
  ],
  "dependencies": [
    "lucide-vue-next"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/vue/badge.json",
    "https://uipkge.dev/r/vue/button.json",
    "https://uipkge.dev/r/vue/card.json",
    "https://uipkge.dev/r/vue/input.json",
    "https://uipkge.dev/r/vue/separator.json",
    "https://uipkge.dev/r/vue/table.json",
    "https://uipkge.dev/r/vue/tabs.json"
  ],
  "description": "Visual database schema inspector and SQL query previewer with cluster health header, table navigation sidebar with row counts, columns metadata table (data types, nullability, defaults, PK/FK indicators), foreign keys diagram, B-Tree indexes, and syntax-styled DDL preview with copy actions.",
  "categories": [
    "devops",
    "app"
  ]
}