OTOMY
DIGITAL PRODUCTS٦ يونيو ٢٠٢٦6 min

بناء API REST في 48 ساعة باستخدام Supabase Edge Functions

هل تظنّ أنّ بناء API REST متينة يستلزم أسابيع من التطوير؟ مع Supabase Edge Functions، تكفي 48 ساعة للانتقال من الفكرة إلى الإطلاق. إليك الدليل الشامل خطوة بخطوة.

M

بقلم

Melissa Slimani

بناء API REST في 48 ساعة باستخدام Supabase Edge Functions

لماذا تُغيّر Supabase Edge Functions قواعد اللعبة في بناء API REST؟

في Otomy، نرافق المؤسسات الصغيرة والمتوسطة في فرنسا والجزائر لبناء منتجات رقمية عالية الأداء. وملاحظة واحدة تتكرّر باستمرار: المؤسّسون يُهدرون أسابيع في تجهيز البنية التحتية الخلفية بينما كان بإمكانهم اختبار منتجهم في السوق منذ اليوم الأوّل.

تعتمد Supabase Edge Functions على Deno Deploy، وتُتيح كتابة دوال serverless بلغة TypeScript تُنشر فوريًا على شبكة CDN عالمية. وعند دمجها مع قاعدة بيانات PostgreSQL ونظام المصادقة والتخزين المدمجَين في Supabase، تحصل على بنية خلفية متكاملة في ساعات معدودة.

إليك كيف نبني API REST جاهزة للإنتاج في 48 ساعة — وليست مجرّد نموذج أوّلي هشّ.


الساعات 0–4: الهندسة المعمارية ونمذجة البيانات

قبل كتابة أيّ سطر برمجي، نُرسي الأساسات.

تحديد موارد الـ API

لنأخذ حالة واقعية: API لإدارة الطلبات لمتجر إلكتروني جزائري.

الموارد المحدَّدة:

  • /orders — عمليات CRUD كاملة
  • /products — قراءة فقط لعرض الكتالوج
  • /customers — إدارة حسابات العملاء
  • /webhooks — إشعارات نحو n8n أو Make

نمذجة قاعدة البيانات

في SQL Editor الخاصّ بـ Supabase:

CREATE TABLE products (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  name TEXT NOT NULL,
  price NUMERIC(10,2) NOT NULL,
  stock INTEGER DEFAULT 0,
  created_at TIMESTAMPTZ DEFAULT now()
);

CREATE TABLE orders (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  customer_id UUID REFERENCES auth.users(id),
  status TEXT DEFAULT 'pending' CHECK (status IN ('pending','confirmed','shipped','delivered')),
  total NUMERIC(10,2) NOT NULL,
  created_at TIMESTAMPTZ DEFAULT now()
);

CREATE TABLE order_items (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  order_id UUID REFERENCES orders(id) ON DELETE CASCADE,
  product_id UUID REFERENCES products(id),
  quantity INTEGER NOT NULL,
  unit_price NUMERIC(10,2) NOT NULL
);

نصيحة Otomy: فعِّل سياسات Row Level Security (RLS) فورًا. هذا أمر غير قابل للتفاوض في بيئة الإنتاج.


الساعات 4–16: تطوير Edge Functions

تهيئة المشروع

supabase init
supabase functions new orders-api

بنية Edge Function متوافقة مع REST

إليك النمط الذي نعتمده دائمًا لمعالجة عدّة طرق HTTP داخل دالة واحدة:

import { serve } from "https://deno.land/std@0.177.0/http/server.ts";
import { createClient } from "https://esm.sh/@supabase/supabase-js@2";

const corsHeaders = {
  "Access-Control-Allow-Origin": "*",
  "Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type",
};

serve(async (req) => {
  if (req.method === "OPTIONS") {
    return new Response("ok", { headers: corsHeaders });
  }

  const supabase = createClient(
    Deno.env.get("SUPABASE_URL")!,
    Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!
  );

  const url = new URL(req.url);
  const id = url.searchParams.get("id");

  try {
    switch (req.method) {
      case "GET": {
        const query = id
          ? supabase.from("orders").select("*, order_items(*)").eq("id", id).single()
          : supabase.from("orders").select("*, order_items(*)").order("created_at", { ascending: false });
        const { data, error } = await query;
        if (error) throw error;
        return new Response(JSON.stringify(data), {
          headers: { ...corsHeaders, "Content-Type": "application/json" },
        });
      }
      case "POST": {
        const body = await req.json();
        const { data, error } = await supabase.from("orders").insert(body).select().single();
        if (error) throw error;
        return new Response(JSON.stringify(data), {
          status: 201,
          headers: { ...corsHeaders, "Content-Type": "application/json" },
        });
      }
      case "PATCH": {
        if (!id) throw new Error("المعرّف مطلوب للتحديث");
        const body = await req.json();
        const { data, error } = await supabase.from("orders").update(body).eq("id", id).select().single();
        if (error) throw error;
        return new Response(JSON.stringify(data), {
          headers: { ...corsHeaders, "Content-Type": "application/json" },
        });
      }
      default:
        return new Response("طريقة غير مسموح بها", { status: 405, headers: corsHeaders });
    }
  } catch (err) {
    return new Response(JSON.stringify({ error: err.message }), {
      status: 400,
      headers: { ...corsHeaders, "Content-Type": "application/json" },
    });
  }
});

التحقّق من صحّة البيانات

استخدم مكتبة Zod للتحقّق من المدخلات:

import { z } from "https://deno.land/x/zod@v3.22.4/mod.ts";

const OrderSchema = z.object({
  customer_id: z.string().uuid(),
  total: z.number().positive(),
  items: z.array(z.object({
    product_id: z.string().uuid(),
    quantity: z.number().int().positive(),
    unit_price: z.number().positive(),
  })).min(1),
});

الساعات 16–30: المصادقة والأمان والتكاملات

تأمين الـ API بواسطة JWT

يُدير Supabase المصادقة بشكل أصيل. استخرج رمز JWT من كلّ طلب:

const authHeader = req.headers.get("Authorization");
const { data: { user }, error } = await supabase.auth.getUser(
  authHeader?.replace("Bearer ", "")
);
if (!user) return new Response("غير مصرَّح", { status: 401, headers: corsHeaders });

ربط n8n أو Make للأتمتة

بعد إنشاء كلّ طلب، أطلق سير عمل عبر webhook:

await fetch(Deno.env.get("N8N_WEBHOOK_URL")!, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ event: "order.created", data: newOrder }),
});

يمكن لهذا الـ webhook أن يُفعِّل في n8n: إرسال بريد تأكيد، إشعار Slack، تحديث المخزون، أو مزامنة مع نظام ERP.

تقييد معدّل الطلبات

خزِّن العدّادات في Supabase KV أو جدول مخصَّص للحدّ من الاستخدام المُفرط.


الساعات 30–42: الاختبارات والتوثيق

الاختبارات الآلية

deno test --allow-net --allow-env supabase/functions/tests/

اكتب اختبارات لكلّ نقطة نهاية. يمكنك الاستعانة بـ Claude AI لتوليد الحالات الحدّية بسرعة انطلاقًا من مخطّط Zod.

توثيق الـ API بمعيار OpenAPI

أنشئ مواصفة OpenAPI 3.0 وانشرها على واجهتك الأمامية عبر Vercel أو Netlify. مستهلكو الـ API سيقدّرون ذلك حقًّا.


الساعات 42–48: النشر والمراقبة

النشر في بيئة الإنتاج

supabase functions deploy orders-api --project-ref your-project-ref

هذا كلّ شيء. أصبحت الـ API REST مباشرة على الحافة (Edge)، بزمن استجابة أقلّ من 50 ميلي ثانية في معظم المناطق.

المراقبة

  • Supabase Dashboard: سجلّات فورية لـ Edge Functions
  • Logflare: مدمج أصلًا لتحليل السجلّات
  • Uptime Robot أو Better Stack: مراقبة التوافر

قائمة التحقّق النهائية قبل الإطلاق

  • ✅ تفعيل RLS على جميع الجداول
  • ✅ التحقّق عبر Zod لجميع المدخلات
  • ✅ مصادقة JWT مفعَّلة ومُتحقَّق منها
  • ✅ إعداد CORS (استبدل * بنطاقاتك الفعلية)
  • ✅ متغيّرات البيئة مخزَّنة كأسرار في Supabase
  • ✅ نجاح جميع الاختبارات الآلية
  • ✅ Webhooks لـ n8n/Make تعمل بشكل صحيح
  • ✅ توثيق OpenAPI منشور ومتاح

ماذا تحصل عليه في 48 ساعة؟

المكوِّن الأداة
قاعدة البيانات Supabase PostgreSQL
API serverless Supabase Edge Functions (Deno)
المصادقة Supabase Auth (JWT)
الأتمتة n8n / Make عبر webhooks
استضافة الواجهة الأمامية Vercel / Netlify
المراقبة Logflare + Better Stack

النتيجة: واجهة API REST متكاملة، آمنة، قابلة للتوسّع، منشورة عالميًا — دون إدارة خادم واحد.

في Otomy، هذا بالضبط هو النهج الذي نطبّقه مع المؤسسات الصغيرة والمتوسطة التي تريد إطلاق منتج رقمي بسرعة، سواء في فرنسا أو الجزائر. سرعة التنفيذ ليست عدوّة الجودة — بشرط اختيار الأدوات المناسبة.

OTOMY

هل تريد أتمتة عملك؟

احجز مكالمة مجانية — 30 دقيقة لتحديد ما يمكن أتمتته.