ملخص سريع
Supabase CLI يشغل حزمة Supabase كاملة على جهازك باستخدام Docker: PostgreSQL، والمصادقة (Auth)، والتخزين (Storage)، ودوال الحافة (Edge Functions). قم بتثبيته باستخدام brew install supabase/tap/supabase، ثم شغل supabase init و supabase start لإعداد بيئة محلية، وبعد ذلك استخدم supabase db push و supabase functions deploy للنشر إلى بيئة الإنتاج. إنها أسرع طريقة لبناء واختبار الواجهات الخلفية (backends) لـ Supabase دون الحاجة للتعامل مع السحابة.
مقدمة
يتم اكتشاف 73% من أخطاء الواجهة الخلفية في بيئة الإنتاج لأن المطورين يتخطون الاختبارات المحلية. باستخدام Supabase CLI، لم يعد هذا عذراً. تحصل على بيئة مكافئة تمامًا لبيئة الإنتاج تعمل على جهازك في أقل من 5 دقائق.
إليك المشكلة الحقيقية: معظم المطورين إما يختبرون مباشرة في بيئة الإنتاج (مخاطرة) أو يقضون ساعات في إعداد بيئات محلية لا تتطابق تمامًا مع السحابة (محبطة). يحل Supabase CLI كلتا المشكلتين. يوفر لك حزمة محلية قائمة على Docker تحاكي بيئة الإنتاج بدقة، لذا فإن ما يعمل محليًا سيعمل في بيئة الإنتاج.
اختبر واجهات Supabase API الخاصة بك باستخدام Apidog - مجانًا
بحلول نهاية هذا الدليل، ستكون قادرًا على:
- إعداد بيئة Supabase محلية كاملة في دقائق
- إدارة تغييرات مخطط قاعدة البيانات باستخدام ترحيلات (migrations) متحكم فيها بالإصدارات
- بناء واختبار دوال الحافة (Edge Functions) محليًا قبل النشر
- النشر إلى بيئة الإنتاج بأمر واحد
لماذا يفشل تطوير Supabase المحلي بدون CLI
إذا حاولت بناء تطبيق Supabase بدون CLI، فأنت تعرف المعاناة. إليك ثلاثة سيناريوهات تحدث باستمرار.
فخ "الاختبار في بيئة الإنتاج". تقوم بإجراء تغيير على المخطط مباشرة في لوحة تحكم Supabase. إنه يعمل. تدفع الواجهة الأمامية (frontend) الخاصة بك. بعد ثلاثة أيام، يقوم زميل في الفريق بسحب المستودع ويتعطل تطبيقه لأن قاعدة البيانات الخاصة به لا تحتوي على العمود الجديد.
عدم تطابق البيئة. تقوم بإعداد نسخة PostgreSQL محلية، وتُعيد إنشاء مخطط Supabase الخاص بك يدويًا، وتقضي ساعتين في تصحيح الأخطاء لمعرفة سبب اختلاف سلوك سياسات أمان مستوى الصفوف (Row Level Security) محليًا. لا تتصرف بشكل مختلف. لقد فاتتك سياسة.
مشكلة "يعمل على جهازي". تعمل دالة الحافة (Edge Function) الخاصة بك في محرر لوحة تحكم Supabase ولكنها تفشل في بيئة الإنتاج لأنك اختبرت بقيم ثابتة (hardcoded values) بدلاً من متغيرات بيئة حقيقية.
هذه ليست حالات استثنائية. انحراف المخطط (عدم تزامن قواعد البيانات المحلية والبعيدة) هو المشكلة الأولى المبلغ عنها للفرق التي تستخدم Supabase. يحل CLI المشاكل الثلاثة كلها:
- تحافظ الترحيلات (Migrations) على تغييرات المخطط متحكمًا فيها بالإصدارات وقابلة للتكرار
- تعكس حزمة Docker المحلية بيئة الإنتاج بدقة، بنفس إصدار PostgreSQL، ونفس محرك RLS
- يقوم تشغيل الدوال المحلية باختبار دوال الحافة (Edge Functions) باستخدام متغيرات بيئة حقيقية
كيف يعمل Supabase CLI
الحزمة المحلية
عند تشغيل supabase start، يقوم CLI بتشغيل حزمة Docker Compose بهذه الخدمات:
| الخدمة | المنفذ | الغرض |
|---|---|---|
| PostgreSQL | 54322 | قاعدة بياناتك |
| PostgREST | 54321 | واجهة REST API تلقائية التوليد |
| GoTrue | 54321/auth | خدمة المصادقة |
| Realtime | 54321/realtime | اشتراكات WebSocket |
| Storage | 54321/storage | تخزين الملفات |
| Studio | 54323 | لوحة تحكم مرئية |
| Inbucket | 54324 | اختبار البريد الإلكتروني (يلتقط جميع رسائل البريد الإلكتروني محليًا) |
| Edge Runtime | 54321/functions | مشغل دوال قائم على Deno |
هذه هي نفس الحزمة التي تعمل في Supabase Cloud. على جهازك.
التثبيت
نظام macOS:
brew install supabase/tap/supabase
نظام Windows (Scoop):
scoop bucket add supabase https://github.com/supabase/scoop-bucket.git
scoop install supabase
نظام Linux / npm:
npm install -g supabase
تحقق من عمله:
supabase --version
# supabase 1.x.x
supabase startإعداد المشروع
mkdir my-project && cd my-project
supabase init
يقوم هذا بإنشاء:
supabase/
├── config.toml # المنافذ، إعدادات المصادقة، تهيئة التخزين
├── seed.sql # بيانات التطوير تُحمّل عند كل إعادة تعيين لقاعدة البيانات
└── migrations/ # سجل إصدارات المخطط
بدء تشغيل الحزمة المحلية
supabase start
يقوم التشغيل الأول بتنزيل حوالي 1 جيجابايت من صور Docker. بعد ذلك، يستغرق التشغيل حوالي 10 ثوانٍ.
API URL: http://localhost:54321
DB URL: postgresql://postgres:postgres@localhost:54322/postgres
Studio: http://localhost:54323
anon key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
انسخ anon key إلى ملف .env.local الخاص بك. ستحتاج إليه لواجهتك الأمامية (frontend).
إدارة قاعدة البيانات باستخدام الترحيلات (migrations)
الترحيلات (Migrations) هي جوهر سير عمل CLI. يصبح كل تغيير في المخطط ملف SQL مُنظم بالإصدارات يتم تتبعه في Git. لا مزيد من السؤال "من غيّر قاعدة البيانات ومتى".
إنشاء أول ترحيل لك
supabase migration new create_posts_table
# Creates: supabase/migrations/20260324120000_create_posts_table.sql
عدّل الملف:
-- إنشاء جدول posts مع RLS من البداية
CREATE TABLE posts (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE NOT NULL,
title TEXT NOT NULL,
content TEXT,
published BOOLEAN DEFAULT false,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- تفعيل أمان مستوى الصفوف (Row Level Security)
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;
-- يمكن لأي شخص قراءة المنشورات المنشورة
CREATE POLICY "Anyone can read published posts"
ON posts FOR SELECT
USING (published = true);
-- يدير المستخدمون منشوراتهم الخاصة
CREATE POLICY "Users manage own posts"
ON posts FOR ALL
USING (auth.uid() = user_id);
-- تحديث updated_at تلقائيًا عند كل تغيير
CREATE OR REPLACE FUNCTION update_updated_at()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER posts_updated_at
BEFORE UPDATE ON posts
FOR EACH ROW EXECUTE FUNCTION update_updated_at();
طبّقه:
supabase migration up
توليد أنواع TypeScript
بعد كل تغيير في المخطط، أعد توليد أنواعك:
supabase gen types typescript --local > src/types/database.ts
تحصل واجهتك الأمامية على أمان كامل للأنواع:
import { Database } from '@/types/database'
type Post = Database['public']['Tables']['posts']['Row']
type NewPost = Database['public']['Tables']['posts']['Insert']
// الآن يكتشف محرر الأكواد أخطاء الأنواع قبل وقت التشغيل
const createPost = async (post: NewPost) => {
const { data, error } = await supabase
.from('posts')
.insert(post)
.select()
.single()
return data
}
تغذية بيانات التطوير
عدّل supabase/seed.sql:
-- مستخدمون للاختبار (يتجاوز المصادقة للتطوير المحلي)
INSERT INTO auth.users (id, email) VALUES
('00000000-0000-0000-0000-000000000001', 'alice@example.com'),
('00000000-0000-0000-0000-000000000002', 'bob@example.com');
-- منشورات للاختبار
INSERT INTO posts (user_id, title, content, published) VALUES
('00000000-0000-0000-0000-000000000001', 'Getting started with Supabase', 'Here is what I learned...', true),
('00000000-0000-0000-0000-000000000002', 'Draft: API design patterns', 'Work in progress...', false);
أعد الضبط وأعد التغذية في أي وقت:
supabase db reset
يقوم هذا بإسقاط كل شيء، وإعادة تشغيل جميع الترحيلات (migrations)، وتحميل بياناتك الأولية (seed data). قم بتشغيله كل صباح لتبدأ من جديد.
اختبار واجهات Supabase API باستخدام Apidog
بمجرد تشغيل Supabase المحلي الخاص بك، سيكون لديك واجهة REST API عاملة بالكامل على http://localhost:54321. يقوم Supabase بتوليد نقاط نهاية (endpoints) تلقائيًا لكل جدول عبر PostgREST. يصبح اختبار هذه النقاط يدويًا باستخدام curl مملًا بسرعة، خاصة عندما تحتاج إلى اختبار سياسات RLS برموز مستخدم مختلفة.
يتصل Apidog مباشرة بنسخة Supabase المحلية الخاصة بك. يمكنك:
- حفظ الطلبات كمجموعات قابلة لإعادة الاستخدام
- اختبار نفس نقطة النهاية (endpoint) كمستخدمين مختلفين عن طريق تبديل البيئات
- إضافة تأكيدات ("الاستجابة تحتوي على منشور واحد على الأقل") وتشغيلها كمجموعة اختبار
- مشاركة توثيق API مع فريقك تلقائيًا
إعداد Apidog مع Supabase المحلي:
- أنشئ مشروعًا جديدًا في Apidog
- عيّن عنوان URL الأساسي:
http://localhost:54321 - أضف متغير بيئة:
anon_key = مفتاحك المجهول المحلي - أضف رأس التخويل (Authorization header):
Bearer {{anon_key}}
اختبار نقطة النهاية للمنشورات (posts endpoint):
GET http://localhost:54321/rest/v1/posts?published=eq.true
Authorization: Bearer {{anon_key}}
apikey: {{anon_key}}
احفظ هذا كطلب، وأضف تأكيدًا بأن الاستجابة تحتوي على منشور واحد على الأقل، وقم بتشغيله في كل مرة تغير فيها سياسات RLS الخاصة بك. ستكتشف السياسات المعطلة قبل أن تصل إلى بيئة الإنتاج.
ابدأ اختبار واجهات Supabase API الخاصة بك باستخدام Apidog - مجانًا
دوال الحافة (Edge functions): البناء والاختبار محليًا
تعمل دوال الحافة (Edge Functions) على Deno عند الحافة، بالقرب من المستخدمين. إنها مثالية لـ webhooks، والمهام الخلفية، ونقاط نهاية API التي تتطلب منطقًا من جانب الخادم.
إنشاء دالة
supabase functions new send-welcome-email
يقوم هذا بإنشاء supabase/functions/send-welcome-email/index.ts:
import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
serve(async (req) => {
const { user_id } = await req.json()
// دور الخدمة يتجاوز RLS - استخدم بحذر
const supabase = createClient
Deno.env.get('SUPABASE_URL')!,
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
)
const { data: profile } = await supabase
.from('profiles')
.select('email, full_name')
.eq('id', user_id)
.single()
// منطق إرسال بريدك الإلكتروني هنا
console.log(`إرسال بريد ترحيب إلى ${profile?.email}`)
return new Response(
JSON.stringify({ success: true }),
{ headers: { 'Content-Type': 'application/json' } }
)
})
الاختبار محليًا مع إعادة التحميل السريع (hot reload)
supabase functions serve
يراقب خادم الدالة تغييرات الملفات ويعيد التحميل تلقائيًا. اختبره:
curl -X POST http://localhost:54321/functions/v1/send-welcome-email \
-H "Authorization: Bearer YOUR_ANON_KEY" \
-H "Content-Type: application/json" \
-d '{"user_id": "00000000-0000-0000-0000-000000000001"}'
النشر إلى بيئة الإنتاج
# نشر دالة واحدة
supabase functions deploy send-welcome-email
# نشر جميع الدوال
supabase functions deploy
تقنيات متقدمة ومناهج مثبتة
إدارة الأسرار
لا تقم أبدًا بتضمين مفاتيح API بشكل ثابت في دوالك. استخدم الأسرار:
# تعيين أسرار الإنتاج
supabase secrets set RESEND_API_KEY=re_xxx STRIPE_KEY=sk_live_xxx
# سرد جميع الأسرار
supabase secrets list
# إزالة سر
supabase secrets unset STRIPE_KEY
الوصول إليها في الدوال:
const resendKey = Deno.env.get('RESEND_API_KEY')
// لا تفعل أبدًا: const resendKey = 're_xxx'
تفريعات قاعدة البيانات
هل تعمل على تغيير كبير في المخطط؟ أنشئ فرعًا معزولًا:
supabase branches create feature-payments
supabase branches switch feature-payments
# قم بإجراء التغييرات، اختبر، ثم ادمج
supabase branches merge feature-payments
يحافظ هذا على نظافة قاعدة بيانات التطوير الرئيسية لديك بينما تقوم بالتجربة.
الأخطاء الشائعة التي يجب تجنبها
- تحرير قاعدة البيانات مباشرة في Studio. استخدم الترحيلات (migrations) دائمًا. التعديلات المباشرة لا يتم تتبعها ولن يراها زملاؤك في الفريق.
- التزام (commit) ملفات
.env. استخدمsupabase secrets setللإنتاج. أضف.env*إلى ملف.gitignoreالخاص بك. - تخطي
supabase db resetبعد السحب (pulling). عندما تسحب تغييرات زملائك في الفريق، يجب تشغيل ترحيلاتهم الجديدة محليًا. أعد الضبط لتطبيقها. - عدم إعادة توليد الأنواع بعد تغييرات المخطط. تصبح أنواع TypeScript الخاصة بك قديمة بمجرد إضافة عمود. اجعل توليد الأنواع جزءًا من سير عمل الترحيل (migration workflow) الخاص بك.
- نشر الدوال بدون اختبار محلي. قم دائمًا بتشغيل
supabase functions serveواختبر بطلبات حقيقية قبل النشر. - استخدام مفتاح دور الخدمة في كود الواجهة الأمامية. يتجاوز مفتاح دور الخدمة RLS. يجب أن يكون موجودًا فقط في دوال الحافة (Edge Functions) والكود من جانب الخادم، وليس أبدًا في متصفحك.
نصائح الأداء
# تخطى الخدمات التي لا تحتاجها لتوفير الذاكرة
supabase start --exclude-studio --exclude-inbucket
# تحقق مما يستهلك الموارد
docker stats
البدائل والمقارنات
| الميزة | Supabase CLI | Firebase CLI | PlanetScale CLI |
|---|---|---|---|
| قاعدة بيانات محلية | PostgreSQL كاملة | محاكي فقط | سحابي فقط |
| الترحيلات | ملفات SQL في Git | لا يوجد دعم أصلي | التفريعات |
| دوال الحافة | بيئة تشغيل Deno | دوال سحابية | غير متضمن |
| المصادقة محليًا | GoTrue كاملة | محاكي | غير متضمن |
| مفتوح المصدر | مفتوح بالكامل | خاص | خاص |
| توليد الأنواع | مدمج | يدوي | يدوي |
محاكي Firebase المحلي جيد للنماذج الأولية السريعة ولكنه لا يوفر لك نسخة PostgreSQL حقيقية. نموذج التفريعات (branching model) في PlanetScale ممتاز لتغييرات المخطط ولكنك دائمًا تعمل ضد السحابة. يفوز Supabase CLI للفرق التي ترغب في تجربة تطوير محلية مفتوحة المصدر بالكامل وقائمة على PostgreSQL.
حالات استخدام واقعية
تطبيق SaaS ببيانات متعددة المستأجرين. تدير شركة ناشئة في مجال التكنولوجيا المالية 47 ترحيلًا (migrations) عبر ثلاث بيئات (تطوير، تجريبي، إنتاج). يتم اختبار سياسات RLS محليًا بأدوار مستخدم مختلفة قبل وصول أي كود إلى الإنتاج. النتيجة: صفر حوادث إنتاج متعلقة بالمخطط في ستة أشهر.
معالجة طلبات التجارة الإلكترونية. يستخدم فريق التجارة الإلكترونية دوال الحافة (Edge Functions) لمعالجة webhooks الخاصة بـ Stripe. يختبرون حمولات الويب هوك (webhook payloads) محليًا باستخدام supabase functions serve مع أحداث اختبار Stripe حقيقية. انخفض وقت النشر من ساعتين إلى 15 دقيقة.
الواجهة الخلفية لتطبيق جوال. يقوم فريق React Native بتوليد أنواع TypeScript بعد كل ترحيل (migration) ويشاركها كحزمة npm داخلية. تظل الواجهة الأمامية والواجهة الخلفية متزامنتين تلقائيًا. لا مزيد من أسئلة "ما هي الحقول التي ترجعها نقطة النهاية هذه؟" في Slack.
الخلاصة
إليك ما يمكنك فعله الآن:
- إعداد بيئة Supabase محلية كاملة في دقائق
- استخدام الترحيلات (migrations) للتحكم بالإصدارات في كل تغيير بالمخطط
- اختبار دوال الحافة (Edge Functions) محليًا مع إعادة التحميل السريع (hot reload)
- توليد أنواع TypeScript تلقائيًا من مخططك
- النشر باستخدام
supabase db pushوsupabase functions deploy - اختبار واجهات برمجة التطبيقات (APIs) الخاصة بك باستخدام Apidog قبل النشر إلى الإنتاج
يؤتي سير العمل ثماره فورًا. ينشر فريقك بشكل أسرع، ويكتشف الأخطاء مبكرًا، ولن يتعامل أبدًا مع انحراف المخطط (schema drift) مرة أخرى.
خطواتك التالية:
- التثبيت:
brew install supabase/tap/supabase - شغل
supabase initفي مشروعك - أنشئ أول ترحيل لك
- أعد إعداد Apidog لاختبار نقاط النهاية المحلية الخاصة بك
- انشر إلى الإنتاج بثقة
اختبر واجهات Supabase API الخاصة بك باستخدام Apidog - مجانًا
الأسئلة الشائعة
هل أحتاج إلى Docker لاستخدام Supabase CLI؟نعم. يجب أن يكون Docker Desktop قيد التشغيل قبل supabase start. يستخدم CLI Docker Compose لتشغيل الحزمة الكاملة محليًا. إذا لم يكن Docker قيد التشغيل، فستحصل على خطأ "لا يمكن الاتصال بخادم Docker".
كيف أقوم بمزامنة قاعدة بياناتي المحلية مع بيئة الإنتاج؟استخدم supabase db pull لتوليد ترحيل من مخططك البعيد، ثم supabase db push لتطبيق الترحيلات المحلية على بيئة الإنتاج. قم بتشغيل supabase db reset محليًا بعد السحب للتأكد من تطابق بيئتك.
هل يمكنني استخدام Supabase CLI بدون حساب Supabase Cloud؟نعم. يمكنك استخدام CLI محليًا بالكامل للتطوير بدون حساب سحابي. تحتاج فقط إلى supabase login و supabase link عندما تكون جاهزًا للنشر إلى الإنتاج.
كيف أتعامل مع تعارضات الترحيلات (migration conflicts) في فريق؟اسحب أحدث تغييرات Git وقم بتشغيل supabase db reset قبل إنشاء ترحيلات جديدة. استخدم أسماء ترحيلات وصفية وتواصل مع فريقك عند إجراء تغييرات في المخطط تتسبب في تعطل.
ما الفرق بين supabase db push و supabase migration up؟ يطبق supabase migration up الترحيلات المعلقة على قاعدة بياناتك المحلية. يطبق supabase db push هذه الترحيلات على مشروعك البعيد (الإنتاجي). اختبر محليًا دائمًا أولاً.
هل يمكنني استخدام Supabase CLI مع مشروع موجود؟نعم. قم بتشغيل supabase link --project-ref YOUR_PROJECT_ID للربط بمشروع موجود، ثم supabase db pull لتوليد ترحيلات من مخططك البعيد الحالي.
كيف أختبر سياسات RLS محليًا؟استخدم Supabase Studio على http://localhost:54323 للتبديل بين أدوار المستخدمين، أو اختبر عبر API برموز JWT مختلفة. يسهّل Apidog ذلك: أنشئ بيئات متعددة برموز مستخدم مختلفة وشغل نفس الطلبات كمستخدمين مختلفين.
هل Supabase CLI مجاني؟نعم. CLI مجاني ومفتوح المصدر. التطوير المحلي لا يكلف شيئًا. تدفع مقابل موارد Supabase Cloud فقط عندما تنشر إلى الإنتاج.
