Tworzenie i konfiguracja elastycznych baz JSON oraz operacje na rekordach - przez API i przez publiczne metody (dla frontendów aplikacji Noe, bez autoryzacji).
Autoryzacja: Authorization: Bearer TOKEN (poza metodami publicznymi)
Content-Type: application/json; charset=utf-8
API Endpoints
| Metoda | Ścieżka | Opis |
|---|---|---|
| GET | /noe/dbs.json |
Lista baz |
| GET | /noe/dbs/:id.json |
Szczegóły bazy (:id = id lub code) |
| POST | /noe/dbs.json |
Utworzenie bazy |
| PATCH | /noe/dbs/:id.json |
Aktualizacja bazy |
| DELETE | /noe/dbs/:id.json |
Usunięcie bazy (z rekordami!) |
| PATCH | /noe/dbs/:id/replace.json |
Częściowa edycja pól fields/schema/public_methods
|
| GET | /noe/dbs/:db_id/records.json |
Lista rekordów |
| POST | /noe/dbs/:db_id/records.json |
Utworzenie rekordu (z table_name dla baz wielotabelowych) |
| PATCH | /noe/dbs/:db_id/records/:id.json |
Aktualizacja rekordu |
| DELETE | /noe/dbs/:db_id/records/:id.json |
Usunięcie rekordu |
| GET | /noe/dbs/:db_id/search.json |
Wyszukiwanie rekordów (table_name, q, search_in, filter[], fields, sort) |
| GET/POST | /noe/db/:db_code/:method_name |
Metody publiczne (bez autoryzacji, wg public_methods) |
Utworzenie bazy
POST /noe/dbs.json
{
"db": {
"name": "Todo",
"code": "todo",
"app_id": "uuid-aplikacji (opcjonalnie)",
"schema": {
"fields": {
"title": { "type": "string", "required": true },
"done": { "type": "integer" }
},
"indexes": {
"idx_str_1": "title",
"idx_int_1": "done"
}
}
}
}
| Pole | Typ | Wymagane | Opis |
|---|---|---|---|
name |
string | tak | Nazwa bazy |
code |
string | nie | Unikalny slug do URL-i (np. “todo” -> /noe/db/todo/...) |
app_id |
uuid | nie | Powiązana aplikacja Noe (widoczne w “Powiązaniach”) |
schema |
object | nie | Pola + mapowanie indeksów |
public_methods |
object | nie | Operacje wystawione bez autoryzacji (niżej) |
Typy pól w schema
string, text, integer, number, boolean, datetime, date, time
Indeksy (szybkie wyszukiwanie/filtrowanie)
| Indeks | Typ |
|---|---|
idx_str_1..3 |
string (max 255 znaków) |
idx_int_1..2 |
bigint |
idx_time_1..2 |
datetime |
Dwa sposoby definiowania indeksów:
-
"indexes": { "idx_str_1": "title" }- jawne mapowanie pole -> kolumna indeksu (starszy format) -
"indexed_fields": ["title", "done"]- lista pól, mapowanie naidx_*liczone automatycznie z typu pola (string/text ->idx_str_*, integer/number ->idx_int_*, date/time/datetime ->idx_time_*); pola, które nie mieszczą się w limicie kolumn, po prostu nie są indeksowane
Pola nieindeksowane też są przeszukiwalne (po data->>'pole' w JSONB), tylko wolniej - indeksuj to,
po czym naprawdę filtrujesz i sortujesz.
Baza wielotabelowa (tables)
tables)Jedna baza Noe może trzymać kilka “tabel” - każda z własnymi polami i własnymi indeksami.
Rekordy rozdziela kolumna table_name.
POST /noe/dbs.json
{
"db": {
"name": "Sklep",
"code": "sklep",
"schema": {
"tables": {
"users": {
"fields": {
"name": { "type": "string", "required": true },
"email": "string",
"age": "number"
},
"indexed_fields": ["name", "email"]
},
"orders": {
"fields": {
"order_number": "string",
"user_id": "number",
"total_amount": "number"
},
"indexed_fields": ["order_number", "user_id"]
}
}
}
}
}
Zasady:
-
"fields"przyjmuje skrót"email": "string"albo pełny zapis{ "type": "string", "required": true } - indeksy są liczone per tabela -
namewusersiorder_numberwordersoba trafiają doidx_str_1(to ta sama kolumna, ale rekordy różnych tabel nigdy się nie mieszają, bo zapytania są zawsze zawężone dotable_name). Każda tabela ma więc pełny limit: 3 stringi, 2 inty, 2 daty -
requiredobowiązuje tylko w obrębie swojej tabeli - pole wymagane wusersnie blokuje zapisu worders - typy pól są walidowane globalnie (ta sama lista typów co w bazie jednotabelowej)
- format jednotabelowy (
fields+indexes/indexed_fieldsna górnym poziomie) działa bez zmian; rekordy takiej bazy majątable_name=null - nie mieszaj formatów - albo
tables, albofieldsna górnym poziomie
Rekordy (prywatne - wymaga autoryzacji)
POST /noe/dbs/todo/records.json
{ "record": { "data": { "title": "Zadanie", "done": 0 } } }
W bazie wielotabelowej podaj table_name - decyduje, wg której tabeli rekord jest walidowany
i indeksowany:
POST /noe/dbs/sklep/records.json
{ "record": { "table_name": "orders", "data": { "order_number": "Z/2026/01", "user_id": 7 } } }
Aktualizacja: PATCH /noe/dbs/todo/records/:id.json z { "record": { "data": { "done": 1 } } }
(w bazie wielotabelowej przekaż też table_name, inaczej rekord wróci do tabeli null).
Wyszukiwanie: GET /noe/dbs/todo/search.json?q=fraza&sort=-created_at&filter[done]=0&limit=50.
Wyszukiwanie (/noe/dbs/:db_id/search.json)
/noe/dbs/:db_id/search.json)| Parametr | Opis |
|---|---|
table_name |
tabela w bazie wielotabelowej - wymagany, gdy schema ma tables
|
q |
szukana fraza; * i % działają jak wildcard (ab* -> ab%), bez nich szuka fragmentu |
search_in |
pola do przeszukania (lista po przecinku); domyślnie pola indeksowane, a przy braku schematu całe data
|
filter[pole] |
dokładne dopasowanie z konwersją typu ze schematu; wartość z */% przechodzi na ILIKE
|
sort |
pole sortowania, prefiks - = DESC (id, created_at, updated_at, pole indeksowane lub pole z data) |
fields |
które pola zwrócić (poza id, created_at, updated_at, które są zawsze) |
limit / offset
|
paginacja (limit 1-100, domyślnie 20) |
GET /noe/dbs/sklep/search.json?table_name=users&q=ali*&search_in=name&fields=name,email&sort=-created_at&limit=20
Odpowiedź to płaska tablica rekordów (bez total): [{ "id": ..., "created_at": ..., "updated_at": ..., "name": "Alice", ... }].
Brakujące lub nieznane table_name w bazie wielotabelowej daje 400 z listą dostępnych tabel:
{ "error": "table_name is required for multi-table database. Available: users, orders",
"available_tables": ["users", "orders"] }
Metody publiczne (bez autoryzacji)
public_methods na bazie wystawia operacje pod POST /noe/db/:db_code/:method_name - główny
sposób, w jaki frontendy aplikacji Noe czytają/zapisują dane (bez tokenów w kodzie appki).
| Operacja | Parametry |
|---|---|
list |
limit, offset
|
get |
id |
create |
{ "data": {...} } |
update |
{ "id": ..., "data": {...} } |
delete |
{ "id": ... } |
search |
q, limit, offset, sort, table_name
|
Konfiguracja per operacja (true = bez ograniczeń, albo obiekt):
| Opcja | Opis |
|---|---|
allowed_fields |
tylko te pola przejdą z requestu (reszta ignorowana) |
required_fields |
wymagane pola - błąd gdy brakuje |
default_values |
wartości dopisywane automatycznie (nadpisują brakujące) |
auto_fields |
pola wypełniane przez serwer - nie do podrobienia przez klienta |
allowed_params |
dozwolone parametry (dla search) |
scope_by |
filtrowanie wyników po polu (każdy widzi swoje rekordy) |
Zmienne w auto_fields: {ip} (adres IP), {cookie_key} (token per przeglądarka, cookie 1 mies.),
{user_id} / {user_name} (zalogowany użytkownik; puste bez sesji).
Przykład - publiczna lista + kontrolowany zapis:
{
"db": {
"public_methods": {
"list": { "scope_by": "user_ip" },
"create": {
"allowed_fields": ["title", "done"],
"required_fields": ["title"],
"default_values": { "done": 0 },
"auto_fields": { "user_ip": "{ip}", "author": "{user_name}" }
}
}
}
}
Uwagi:
-
auto_fieldsZAWSZE nadpisuje pole wartością serwera - jeśli rekordy zapisuje też backend (np. flow przez konektor), nie używaj auto_fields na polach, które backend ustawia sam - odpowiedzi list/get/create:
{ "id": ..., "data": {...}, "created_at": ..., "updated_at": ... }(list: tablica, najnowsze pierwsze); czas utworzenia rekordu =created_at -
scope_bydobiera zmienną zauto_fieldstego pola (IP albo cookie_key) -
bazy wielotabelowe:
table_nameprzechodzi tylko przez publicznesearch.list/get/create/update/deletenie znają tabel -createzapisze rekord ztable_name=null(bez walidacji i indeksów tabeli), alist/getwidzą rekordy ze wszystkich tabel wymieszane. Frontend appki, który ma czytać/pisać konkretną tabelę, korzystaj z prywatnego API rekordów (z tokenem), z publicznegosearchztable_name, albo trzymaj tabelę jako osobną bazę jednotabelową -
filter[pole]ifieldsobsługuje tylko prywatny/noe/dbs/:db_id/search.json- w publicznymsearchzostająq,sort,table_name,limit,offset
Replace API (częściowa edycja)
PATCH /noe/dbs/:id/replace.json
{ "field": "public_methods", "old_string": "\"list\": true", "new_string": "\"list\": { \"scope_by\": \"user_ip\" }" }
Dozwolone pola: fields, schema, public_methods. Opcja replace_all: true dla wielu wystąpień.
Powiązane
- noe_api - API aplikacji Noe (akcje, silniki, źródła)
- noe_app_example_weather - kompletny przykład: appka + baza z publicznymi metodami + flow + cron
- common_api - wspólne zasady API