用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/amo-tech-ai/medellin-spark --skill supabase-migration命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| name | supabase-migration |
| description | Safe database migration creation and management for Supabase PostgreSQL |
| version | 1.0.0 |
Create, test, and apply database migrations safely following project conventions.
YYYYMMDDHHMMSS_description.sql
Examples:
20251018120000_add_user_preferences.sql
20251018130000_enable_rls_on_comments.sql
/home/sk/template-copilot-kit-py/supabase/migrations/
Always use:
CREATE TABLE IF NOT EXISTSALTER TABLE ... ADD COLUMN IF NOT EXISTS (PostgreSQL 9.6+)DROP TABLE IF EXISTSDO $$ ... END $$; blocks for conditional logicNever use:
CREATE TABLE without IF NOT EXISTSALTER TABLE ADD COLUMN without IF NOT EXISTSEvery new table MUST include:
-- Enable RLS
ALTER TABLE table_name ENABLE ROW LEVEL SECURITY;
-- Basic policy (user owns record)
CREATE POLICY "Users can manage own records"
ON table_name
FOR ALL
TO authenticated
USING (profile_id = auth.uid())
WITH CHECK (profile_id = auth.uid());
Use profile_id, NOT user_id:
-- ✅ Correct
profile_id UUID REFERENCES profiles(id) ON DELETE CASCADE
-- ❌ Wrong
user_id UUID REFERENCES auth.users(id)
-- Migration: <description>
-- Created: YYYY-MM-DD
-- Status: <pending|applied|rolled-back>
BEGIN;
-- =============================================================================
-- TABLE CREATION
-- =============================================================================
CREATE TABLE IF NOT EXISTS table_name (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
profile_id UUID NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now(),
-- Additional columns
name TEXT NOT NULL,
status TEXT DEFAULT 'active'
);
-- =============================================================================
-- INDEXES
-- =============================================================================
CREATE INDEX IF NOT EXISTS idx_table_profile
ON table_name(profile_id);
CREATE INDEX IF NOT EXISTS idx_table_created
ON table_name(created_at DESC);
-- =============================================================================
-- RLS POLICIES
-- =============================================================================
ALTER TABLE table_name ENABLE ROW LEVEL SECURITY;
-- Drop existing policies (idempotent)
DROP POLICY IF "policy_name" table_name;
POLICY "Users manage own records"
table_name
authenticated
(profile_id auth.uid())
(profile_id auth.uid());
REPLACE update_updated_at()
$$
NEW.updated_at now();
;
;
$$ plpgsql;
IF trigger_update_updated_at table_name;
trigger_update_updated_at
BEFORE table_name
update_updated_at();
;
# Navigate to migrations folder
cd /home/sk/template-copilot-kit-py/supabase/migrations
# Create new migration (use current timestamp)
touch $(date +%Y%m%d%H%M%S)_description.sql
# Edit with idempotent SQL
nano <filename>.sql
# Option 1: Apply via Supabase CLI
supabase db push
# Option 2: Apply directly via MCP
# Use mcp__supabase__execute_sql with migration content
-- Check table created
SELECT tablename FROM pg_tables
WHERE tablename = 'your_table_name';
-- Verify RLS enabled
SELECT tablename, rowsecurity
FROM pg_tables
WHERE tablename = 'your_table_name';
-- Expected: rowsecurity = true
-- Check policies exist
SELECT schemaname, tablename, policyname
FROM pg_policies
WHERE tablename = 'your_table_name';
-- Test data insertion
INSERT INTO your_table_name (profile_id, name)
VALUES (auth.uid(), 'Test record')
RETURNING *;
# Create rollback migration
touch $(date +%Y%m%d%H%M%S)_rollback_previous_migration.sql
Rollback template:
BEGIN;
DROP TABLE IF EXISTS table_name CASCADE;
-- Remove any other changes
COMMIT;
-- Add column safely
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'presentations'
AND column_name = 'new_column'
) THEN
ALTER TABLE presentations
ADD COLUMN new_column TEXT;
END IF;
END $$;
CREATE OR REPLACE FUNCTION function_name(param1 TEXT)
RETURNS TABLE (id UUID, name TEXT) AS $$
BEGIN
RETURN QUERY
SELECT t.id, t.name
FROM table_name t
WHERE t.profile_id = auth.uid()
AND t.status = param1;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
-- Allow public read access to presentations
CREATE POLICY "Public presentations visible to all"
ON presentations
FOR SELECT
TO anon, authenticated
USING (is_public = true);
profile_id\dt table_nameSELECT rowsecurity FROM pg_tablesSELECT * FROM pg_policies# List applied migrations
supabase migration list
# Check current schema
supabase db diff
Error: "relation already exists"
IF NOT EXISTSIF NOT EXISTS to CREATE statementsError: "column already exists"
information_schema checkError: "violates foreign key constraint"
Error: "permission denied for table"
profile_id = auth.uid()profile_id)cd /home/sk/template-copilot-kit-py/supabase/migrations
touch $(date +%Y%m%d%H%M%S)_description.sql
supabase db push
SELECT tablename, rowsecurity
FROM pg_tables
WHERE schemaname = 'public';
SELECT tablename, policyname, cmd
FROM pg_policies
ORDER BY tablename;
File: 20251018120000_add_comments_table.sql
-- Migration: Add comments table for presentations
-- Created: 2025-10-18
-- Status: pending
BEGIN;
-- Table
CREATE TABLE IF NOT EXISTS comments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
presentation_id UUID NOT NULL REFERENCES presentations(id) ON DELETE CASCADE,
profile_id UUID NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
content TEXT NOT NULL,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);
-- Indexes
CREATE INDEX IF NOT EXISTS idx_comments_presentation
ON comments(presentation_id);
CREATE INDEX IF NOT EXISTS idx_comments_profile
ON comments(profile_id);
-- RLS
ALTER TABLE comments ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS "Users manage own comments" ON comments;
CREATE POLICY "Users manage own comments"
ON comments FOR ALL TO authenticated
USING (profile_id = auth.uid())
WITH CHECK (profile_id = auth.uid());
DROP POLICY IF "Public comments visible" comments;
POLICY "Public comments visible"
comments anon, authenticated
(
(
presentations
id comments.presentation_id
is_public
)
);
;
This skill ensures all migrations are safe, idempotent, and follow project security standards.