Standaryzacja API
Nazewnictwo endpointów
- zakładając przypadek, w którym domena nie posiada prefixu ‘api’, powinien być to pierwszy człon endpointu,
- kolejny człon powinien zawierać informację dotyczą wersjonowania, przykładowo ‘v1’, ‘v2’,
- następny człon powinien zawierać informację o dostępności, tj. ‘external’ dla dostępu publicznego lub ‘internal’ dla dostępu wewnętrznego,
- następna powinna być nazwa zasobu, w liczbie mnogiej, np. ‘users’, ‘events’,
- kolejnym członem powinna być wywoływana funkcjonalość, np. ‘register’, ‘login’,
- indeksowanie zasobów powinno się odbywać po jednym, ustalonym przez członków projektu kluczu
Przykładowy routing:
- api.eventownik.pl/v1/internal/events/:id
- api.eventownik.pl/v1/external/events/:id
Lista endpointów projektu Eventownika:
Ogólny format odpowiedzi
- formatem odpowiedzi powinien być obiekt umieszczony w obiekcie data/data[],
- wszystkie atrybuty paginacji oraz całkowita liczba rekordów powinna znajdować się w obiekcie metadata,
- metody post/put powinny zwracać zaktualizowany obiekt,
- metoda delete powinna zwracać no content,
- w przypadku, gdy usuwany obiekt nie istnieje powinien zostać wywołany NotFoundError
- odpowiedzi nie powinny zawierać zbędnych informacji, typu : {“message” : “X … successfully.”}, czy też zduplikowany status code
Przykładowy format odpowiedzi:
data: [{ "id": 1, "email": "example@example.com", "created_at": "2025-08-07T12:34:56.000" }, { "id": 2, "email": "example2@example.com", "created_at": "2025-08-07T12:40:00.000" } ],metadata: { "page": 0, "per_page" : 10, "total" : 2}Ogólny format błędów
- do walidacji danych jak i zwracania odpowiedzi błędu, wykorzystujemy domyślną dla NestJS paczkę class-validator,
- błędy powinny być oznaczone odpowiednim status codem
Format parametrów metody ‘GET’
Paginacja
- ?page=<number> - numer strony (domyślnie 0)
- ?perPage=<number> - liczba obiektów na stronę (opcjonalne, w przypadku gdy wartość nie została podana, wykorzystywana jest domyślna wartość 10 elementów na stronę)
Sortowanie
- ?sort[<column>]=asc/desc, (domyślnie ascending)
Filtrowanie
- filter[<column>]=<value>
- filter[<column>][gt/gte/lt/lte]=<value> (typu numerycznego/daty)
- filter[<column>][not/like]=<value>
- filter[<column1>]=<value1>>…&filter[<columnN>]=<valueN> - dla wielu filtrów
- filter[<column1>]=<value1>,<value2> - dla filtrowania typu IN ( z możliwością podania kilku kolumn, w takim przypadku warunek filtrowania jest spełniony, gdy istnieje dowolna z podanych wartości w dowolnej z podanych kolumn)
Relacje
- ?join=<relation_name>
- ?join=<relation_name1>,…,<relation_nameN> - dla wielu relacji
Select
- ?select=<column>
- ?select=<column1>,…,<columnN>
Domyślnie operacja select bez podania nazw kolumn zwróci wszystkie kolumny z danej tabeli. Alternatywnie, istnieje opcja wykluczenia kolumn.
Przykładowe użycie wykluczenia:
- ?select=-<column1>,…,-<columnN>
Przykład wykorzystania parametrów
Endpoint: api.eventownik.pl/v1/internal/events/:eventId/participants?page=1&perPage=20&sort[name]=asc&filter[name][like]=Jakub
Autoryzacja
- w późniejszej fazie projektu, planowana jest implementacja Solvro Auth
Pozostałe nagłówki
- accept: application/json,
- request-id w celu implementacji tracing’u
Serializacja i formatowanie danych
-
Daty powinny być zwracane w standardzie ISO 8601 bez stref czasowych,
przykład daty: 2012-01-01T00:00:00,
-
Zasoby oraz jego atrybuty powinny być zwracane w snake_case’ie
Dokumentacja
Do tworzenia dokumentacji API wykorzystujemy Swaggera. Dokumentacja Swaggera dla NestJS
- Grupowanie endpointów za pomocą ‘@ApiTags’ powinno odzwierciedlać faktyczny routing,
- Dla skomplikowanych/niejednoznacznych odpowiedzi zaleca się dodanie opisu (descriptions),
- Dokumentacja powinna obejmować wszystkie możliwe odpowiedzi (dla powtarzalnych odpowiedzi można zastosować dekorator dla całego kontrolera),
- Za pomocą CLI, jesteśmy w stanie automatycznie generować annotacje dla modeli/DTO, domyślnie generowane są tylko dla konkretnych plików, tj. ‘.dto.ts’, ‘.entity.ts’,
- Dla projektu powinno zostać wybrane estetyczne oraz przejrzyste UI (lub stworzone przez zespół)
Testy
Do przeprowadzania testów korzystamy z domyślnych dla NestJS pakietów: Jest oraz Supertest.
- Przede wszystkim, należy skupić się, aby testy powstawały równolegle z rozwojem aplikacji,
- Testy powinny obejmować, zarówno “scenariusze” pomyślne/zgodne z założeniem działania aplikacji, jak i te zakończone niepowodzeniem, w celu sprawdzenia obsługi błędów,
- Testy powinny sprawdzać istotne funkcjonalności aplikacji - nie należy się kierować wysokim pokryciem kodu,
- Podział testów: a. jednostkowe - jedynie dla złożonych funkcjonalności, b. integracyjne - powinny stanowić większość testów, c. e2e - tworzone przez zespół frontendowy
Obsługa plików
Do obsługi plików, wykorzystujemy domyślny dla NestJS pakiet ‘multer’, obsługuje on dane przesyłane w formacie ‘multipart/form-data’.
Zalecane jest również wykorzystanie walidacji metadanych pliku podczas przesyłania, przykładowo dla:
- liczby przesyłanych plików,
- typu przesyłanego pliku (domyślnie dla NestJS jest to mimetype),
- maksymalnego rozmiaru pliku
Natomiast same pliki będą przechowywane na hostowanym przez nas systemie S3 (MinIO).