REST API

storagedb REST API — PostgREST uslubidagi avtomatik CRUD, filtrlar, RLS va embedded joins. Har so'rov loyihaning database'ining RLS siyosatlarini avtomatik qo'llaydi.

Asosiy API Yo'li

storagedb REST API PostgREST standartini tadbiq etadi. Har jadvalni avtomatik REST CRUD endpointi orqali boshqara olasiz.

API URL formati: BASE/v1/<REF>/rest/v1/<TABLE>, bu yerda:

BASE = asosiy server (masalan https://storage.identify.uz)

<REF> = loyiha identifikatoriñiz (loyihani yaratganda beriladi)

<TABLE> = Postgres jadval nomi

Barcha so'rovlar tranzaksiyada bajariladi: rol o'rnatiladi, JWT claim'lari tayyyorlansa, keyin Postgres RLS avtomatik nazorat qiladi.

Kalitlar apikey: header'ida yuboriladi. anon_key = ommaviy (client-side), service_key = xizmat uchun (RLS'ni chetlab o'tadi).

GET — So'rovlar va Filtrlar

Jadvaldagi qatorlarni o'qiydi. Select parametri siz hamma ustunlarni qaytaradi.

select=col1,col2 — ma'lum ustunlar (vergul bilan ajratilgan). * yoki bo'sh = hamma ustun.

— Filtrlar: ?ustun=op.qiymat formatida. Operatorlar: eq (teng), neq (teng emas), gt (katta), gte (katta yoki teng), lt (kichik), lte (kichik yoki teng), like (shablon, * = %), ilike (case-insensitive), in.(a,b,c) (ro'yxatdan), is.null / is.true / is.false.

— JSON ustunlar: ?meta->>author=eq.Ali (JSON path → matn).

— Full-text qidiruv: ?body=fts.olma (to_tsquery), ?body=plfts.olma boshqa (plainto_tsquery), ?body=wfts.olma (websearch_to_tsquery).

— Inkor: ?views=not.gt.10 (NOT views > 10).

— OR gruhlari: ?or=(age.gt.18,age.lt.5) (age > 18 OR age < 5).

— Tartiblash: ?order=id.asc,name.desc (bir yoki ko'p ustun, .asc / .desc).

— Pagination: ?limit=10&offset=20 (40-49 qatorlar).

— Hisoblash: ?count=exact (aniq jami) yoki ?count=estimated (pg_class'dan tez estimat). Status 206 bo'lsa, hamma natijavta, 200 bo'lsa, limit ostida. Javob Content-Range: START-END/TOTAL header'i bilan keladi.

Asosiy SELECT
curl "https://storage.identify.uz/v1/<REF>/rest/v1/todos?select=id,title,done" \
  -H "apikey: <ANON_KEY>"
Filtrlar
# id > 5 va done = false
curl "https://storage.identify.uz/v1/<REF>/rest/v1/todos?id=gt.5&done=is.false&order=id.desc&limit=10" \
  -H "apikey: <ANON_KEY>"
Hisoblash + Pagination
curl -D - "https://storage.identify.uz/v1/<REF>/rest/v1/todos?limit=20&count=exact" \
  -H "apikey: <ANON_KEY>"
# Response header: Content-Range: 0-19/145
Full-text qidiruv
curl "https://storage.identify.uz/v1/<REF>/rest/v1/articles?body=wfts.python%20tutorial" \
  -H "apikey: <ANON_KEY>"
SDK: SELECT
import { createClient } from "@storagedb/client";

const db = createClient("https://storage.identify.uz/v1/<REF>", "<ANON_KEY>");

const { data, count } = await db.from("todos")
  .select("id,title,done", { count: "exact" })
  .eq("done", false)
  .order("id", { ascending: false })
  .limit(10);

POST — Inserting

Jadvallarga yangi qatorlar qo'shadi. Body JSON: bitta obyekt yoki massiv.

— Hozirda Prefer: return=representation avtomatik qo'llaniladi, shuning uchun yaratilgan qatorlar qaytaradi.

— Masallar: unique constraint (409), foreign key (409), not-null violation (400), check constraint (400).

Bitta qator qo'shish
curl -X POST "https://storage.identify.uz/v1/<REF>/rest/v1/todos" \
  -H "apikey: <SERVICE_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"title":"Buyurtma qilish","done":false}'
# Status: 201, Body: [{"id":123,"title":"Buyurtma qilish","done":false}]
Ko'p qatorlar qo'shish
curl -X POST "https://storage.identify.uz/v1/<REF>/rest/v1/todos" \
  -H "apikey: <SERVICE_KEY>" \
  -H "Content-Type: application/json" \
  -d '[{"title":"Vazifa 1"},{"title":"Vazifa 2"}]'
SDK: INSERT
const { data, error } = await db.from("todos")
  .insert({ title: "Yangi mexnat", done: false });

if (error) console.error(error);
else console.log("Yaratildi:", data);

PATCH/PUT — Update

Mavjud qatorlarni yangilaydi. URL'da filtrlar orqali qaysi qatorlarni o'zgartirasligini belgilayin.

— Body: JSON obyekt (qaysi ustunlarni o'zgartirasligini).

— Masalniki Filter kerak: ?id=eq.5 (id=5 bo'lgan qatorni yangilash).

— Hozir Prefer: return=representation avtomatik, shuning uchun yangilangan qatorlar qaytaradi.

Bitta qatorni yangilash
curl -X PATCH "https://storage.identify.uz/v1/<REF>/rest/v1/todos?id=eq.123" \
  -H "apikey: <SERVICE_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"done":true}'
Ko'p qatorni yangilash
curl -X PATCH "https://storage.identify.uz/v1/<REF>/rest/v1/todos?user_id=eq.42&done=is.false" \
  -H "apikey: <SERVICE_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"done":true,"updated_at":"2025-06-05T10:30:00Z"}'
SDK: UPDATE
const { data } = await db.from("todos")
  .update({ done: true, updated_at: new Date().toISOString() })
  .eq("id", 123);

DELETE — O'chirish

Qatorlarni o'chiradi. PATCH kabi filtrlar ishlaydi.

— Hozir Prefer: return=representation avtomatik, shuning uchun o'chirilgan qatorlar qaytaradi.

— Ehtiyot: filtr yo'q bo'lsa, hamma jadvali o'chiriladi.

Bitta qator o'chirish
curl -X DELETE "https://storage.identify.uz/v1/<REF>/rest/v1/todos?id=eq.123" \
  -H "apikey: <SERVICE_KEY>"
Shartli o'chirish
curl -X DELETE "https://storage.identify.uz/v1/<REF>/rest/v1/todos?user_id=eq.42&done=is.true" \
  -H "apikey: <SERVICE_KEY>"
SDK: DELETE
const { data } = await db.from("todos")
  .delete()
  .eq("id", 123);

Embedded Joins (Foreign Keys)

SELECT'da bog'liq jadvallarni aniqlash kerak. select=*,related_table(*) — FK orqali biriktirilgan qatorlarni JSON sifatida qo'shadi.

— To-one: bir qatar. Masalan, books.select='*,author(id,name)' — har kitob bilan muallif maʼlumotlari.

— To-many: qatorlar massivi. Masalan, users.select='*,posts(*)' — har foydalanuvchi bilan barcha postlari.

— Sistem FK'ni introspeksiya qiladi. Base jadvalning FKsi → one; reverse FK → many.

Kitoblar + Mualliflar (to-one)
curl "https://storage.identify.uz/v1/<REF>/rest/v1/books?select=*,author(id,name,email)" \
  -H "apikey: <ANON_KEY>"
# Response: [{"id":1,"title":"...","author":{"id":5,"name":"Ali","email":"..."}}]
Foydalanuvchilar + Postlar (to-many)
curl "https://storage.identify.uz/v1/<REF>/rest/v1/users?select=id,email,posts(id,title)" \
  -H "apikey: <ANON_KEY>"
# Response: [{"id":1,"email":"...","posts":[{"id":10,"title":"..."},{"id":11,"title":"..."}]}]
SDK: Embedded joins
const { data } = await db.from("books")
  .select("*,author(name,email)")
  .eq("author_id", 5);

RPC — Postgres Funksiyalari

Postgres'da yozilgan funksiyalarni chaqirish. Rol va JWT claim'lari shu sozlanadi, shuning uchun auth.uid() va auth.role() qayd etiladi.

— Endpoint: POST /v1/<REF>/rest/v1/rpc/<fn>.

— Body: JSON {param1: val1, param2: val2} — nomlangan parametrlar.

— Skalyar qaytarish (1 qator, 1 ustun) → qiymatni to'g'ridan-to'g'ri qaytaradi. Aks holda → qatorlar massivi.

Oddiy RPC (skalyar qaytarish)
curl -X POST "https://storage.identify.uz/v1/<REF>/rest/v1/rpc/add_numbers" \
  -H "apikey: <SERVICE_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"a":5,"b":7}'
# Response: 12
RLS bilan RPC
curl -X POST "https://storage.identify.uz/v1/<REF>/rest/v1/rpc/get_user_posts" \
  -H "apikey: <ANON_KEY>" \
  -H "Authorization: Bearer <JWT>" \
  -d '{}'
# auth.uid() foydalanuvchining JWT'sidan olinadi → RLS avtomatik qo'llanadi
SDK: RPC
const { data, error } = await db.rpc("add_numbers", { a: 10, b: 20 });
if (!error) console.log(data); // 30

RLS (Row-Level Security) — Avtomatik Himoya

Har so'rov RLS siyosatlari bilan amalga oshiriladi. Sistem barcha so'rovda:

— Rol o'rnatadi (anon, authenticated, yoki service_role).

— JWT claim'larini Postgres request.jwt.claims o'zgaruvchisiga qo'yadi.

— Faqat service_role RLS'ni chetlab o'tadi (BYPASSRLS).

— Masalan, create policy 'users_own' on todos for select using (auth.uid() = user_id) — foydalanuvchi faqat o'z todosu'ni ko'radi.

anon_key dan kelib chiqqan so'rovlar anon rolida bajariladi → RLS siyosatlariga asosiy cheklovlar.

Error Kodlari

Postgres xato kodlari HTTP statusga aylantiriladi:

— 400: Syntax error, undefined column, invalid type cast, not-null violation, check constraint.

— 403: insufficient_privilege (RLS — qo'llab-quvvatlanish yo'q)

— 404: undefined_table.

— 409: unique_violation, foreign_key_violation.

— 405: qo'llab-quvvatlanmaydigan HTTP metod.

— 500: Noma'lum xato.

Error javob
{"message":"permission denied for schema public","code":"42501"}

API Dokumentatsiya va Swagger

storagedb OpenAPI spetsifikatsiyasini avtomatik yaratadi. Har loyiha uchun Swagger UI mavjud.

— OpenAPI JSON: GET /v1/<REF>/openapi.json?apikey=<anon_key>.

— Swagger UI: /v1/<REF>/docs?apikey=<anon_key> — interaktiv, sinovga tayyor.