@hexlet/frontend-flight-booking-server
v0.4.0
Published
Hexlet-provided backend for the flight booking diploma project. Implements the contract/ OpenAPI in-memory.
Readme
@hexlet/frontend-flight-booking-server
Готовый бэкенд для проекта «Бронирование авиабилетов»: писать его не нужно — вы подключаете пакет к своему фронтенду и работаете против настоящего API.
- Fastify 5 (TypeScript). In-memory: города и рейсы сидятся при старте, брони живут в памяти и сбрасываются при перезапуске.
- Реализует контракт
contract/openapi.yaml, который едет вместе с пакетом.
Запуск
npx frontend-flight-booking-server start # API на :8080
npx frontend-flight-booking-server start -p 3000 # другой порт
npx frontend-flight-booking-server start -s ./dist # + отдавать собранный SPA из ./distС флагом -s сервер раздаёт вашу сборку по / и API по /api — фронтенд и API оказываются на
одном origin. Если порт не задан, берётся PORT из окружения (так его передаёт большинство
хостингов), иначе 8080.
Контракт API
Контракт — TypeSpec main.tsp и сгенерированный из него openapi.yaml — лежит в каталоге
contract/ пакета. Получить его в свой проект:
npx frontend-flight-booking-server contract # скопирует openapi.yaml + main.tsp в ./contract
npx frontend-flight-booking-server contract api-spec # в указанный каталогЛибо прочитать напрямую: node_modules/@hexlet/frontend-flight-booking-server/contract/openapi.yaml.
openapi.yaml — источник правды по эндпоинтам, телам запросов/ответов и кодам.
Эндпоинты (/api)
| Метод | Путь | |
|---|---|---|
| GET | /api/cities | справочник городов |
| GET | /api/flights?origin=&destination=&date=&passengers= | поиск рейсов (нет совпадений → 200 [], невалидно → 400) |
| GET | /api/flights/{id} | рейс по id (404, если нет) |
| POST | /api/bookings | создать бронь → 201 + code; пустой passengers/неизвестный flightId → 400 |
| GET | /api/bookings/{code}?lastName= | просмотр (неверная фамилия → 404) |
| POST | /api/bookings/{code}/cancel | отмена ({"lastName": "…"} в теле) → бронь со status:"cancelled" |
Ошибки — { "code": "validation_error" | "not_found", "message": "..." }. totalPrice считается на
сервере (price × passengers). Идентификация брони — код + фамилия любого пассажира
(case-insensitive).
