Supabase uyumlu backend platformumuz pgapi üzerinde yeni bir proje açmak, tabloyu RLS ile korumak ve supabase-js ile bağlanmak adım adım.
pgapi, kendi sunucumuzda işlettiğimiz, çok projeli ve Supabase uyumlu bir backend platformu. Her projenin kendi PostgreSQL veritabanı, kimlik doğrulaması, REST ve GraphQL API’si, dosya deposu, gerçek zamanlı kanalları ve Edge Functions katmanı var. Bu yazıda yeni bir uygulamanın backend’ini baştan sona nasıl kurduğumuzu gösteriyoruz.
Kısa cevap: proje oluşturulur, şema migration dosyalarıyla yazılır, her tabloya satır düzeyinde güvenlik (RLS) politikası eklenir, TypeScript tipleri üretilir ve uygulama resmi supabase-js istemcisiyle bağlanır. Uygulama kodu Supabase’e bağlanıyormuş gibi yazılır; değişen tek şey proje adresidir.
1. Proje oluşturmak
Proje panelden ya da komut satırından açılır. Örnek proje kimliğimiz magaza:
pgapi create magaza Magaza_uygulamasi https://magaza.com
pgapi init-project magaza
init-project, repoya supabase/ klasörünü, örnek ortam dosyasını ve proje belgelerini yerleştirir. Projenin API adresi https://pgapi.venus.tr/magaza olur.
2. Şemayı migration ile yazmak
Veritabanı değişiklikleri elle değil, sürüm kontrolündeki SQL dosyalarıyla yapılır. supabase/migrations/ altına bir dosya:
create table public.products (
id bigint generated always as identity primary key,
name text not null,
price numeric(10,2) not null check (price >= 0),
owner_id uuid not null default auth.uid() references auth.users(id),
created_at timestamptz not null default now()
);
alter table public.products enable row level security;
create policy "Ürünleri herkes okur"
on public.products for select
using (true);
create policy "Kendi ürününü ekler"
on public.products for insert
with check (owner_id = auth.uid());
create policy "Kendi ürününü günceller"
on public.products for update
using (owner_id = auth.uid());
Ardından:
pgapi migrate magaza
pgapi types magaza > src/types/database.ts
RLS bizim için pazarlık konusu değil: public şemasındaki her tablo, açık politikalarla korunur. Politikası olmayan bir tablo, anonim anahtarla hiçbir satır döndürmez.
3. Uygulamadan bağlanmak
Tarayıcı ya da mobil uygulama yalnızca proje adresini ve anonim anahtarı bilir:
import { createClient } from '@supabase/supabase-js';
import type { Database } from './types/database';
const supabase = createClient<Database>('https://pgapi.venus.tr/magaza', import.meta.env.PUBLIC_ANON_KEY);
await supabase.auth.signInWithPassword({ email, password });
const { data } = await supabase.from('products').select('id, name, price');
Dosya yükleme, gerçek zamanlı dinleme ve fonksiyon çağrısı aynı istemciyle yapılır:
await supabase.storage.from('images').upload(`${user.id}/kapak.png`, file);
supabase
.channel('orders')
.on('postgres_changes', { event: 'INSERT', schema: 'public', table: 'orders' }, console.log)
.subscribe();
await supabase.functions.invoke('checkout', { body: { cartId } });
4. Sunucu tarafında kalması gerekenler
service_role anahtarı, JWT gizli anahtarı ve veritabanı bağlantı adresi yalnızca sunucu tarafında, ortam değişkenlerinde tutulur. Tarayıcıya giden kodda yalnızca anonim anahtar bulunur; yetkiyi RLS politikaları belirler. .env dosyaları repoya girmez.
5. Zamanlanmış işler ve webhook’lar
Gece raporu, abonelik yenileme hatırlatması ya da bir dış servise bildirim gibi işler için ayrı bir sunucu gerekmez. pg_cron ve pg_net ile veritabanının içinden yazılır:
select cron.schedule('gece-raporu', '0 3 * * *', $$
select net.http_post(
url := 'https://pgapi.venus.tr/magaza/functions/v1/gece-raporu',
headers := '{"Content-Type": "application/json"}'::jsonb
);
$$);
Özet
pgapi ile bir uygulamanın backend’i; migration dosyaları, RLS politikaları ve resmi Supabase istemcisiyle kurulur. Uygulama kodu taşınabilir kalır, altyapının arkasında ise onu kuran ve izleyen ekip durur. Ayrıntılar için backend platformu sayfamıza bakabilirsiniz.