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.
curl "https://storage.identify.uz/v1/<REF>/rest/v1/todos?select=id,title,done" \ -H "apikey: <ANON_KEY>"
# 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>"
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
curl "https://storage.identify.uz/v1/<REF>/rest/v1/articles?body=wfts.python%20tutorial" \ -H "apikey: <ANON_KEY>"
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).
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}]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"}]'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.
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}'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"}'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.
curl -X DELETE "https://storage.identify.uz/v1/<REF>/rest/v1/todos?id=eq.123" \ -H "apikey: <SERVICE_KEY>"
curl -X DELETE "https://storage.identify.uz/v1/<REF>/rest/v1/todos?user_id=eq.42&done=is.true" \ -H "apikey: <SERVICE_KEY>"
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.
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":"..."}}]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":"..."}]}]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.
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: 12curl -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'llanadiconst { data, error } = await db.rpc("add_numbers", { a: 10, b: 20 });
if (!error) console.log(data); // 30RLS (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.
{"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.