Multiple implementations of the same back-end application. The aim is to provide quick, side-by-side comparisons of different technologies (languages, frameworks, libraries) while preserving consistent business logic across all implementations.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

128 lines
4.7 KiB

#include "webapi/controllers/StoreController.h"
#include "infrastructure/helpers/JsonItem.h"
#include "infrastructure/helpers/Jsend.h"
#include "application/commands/AddItem.h"
#include "application/queries/ListItems.h"
#include "application/queries/GetItem.h"
#include "application/commands/DeleteItem.h"
#include "application/exceptions/AutoStoreExceptions.h"
#include <optional>
namespace nxl::autostore::webapi {
StoreController::StoreController(Context&& context)
: BaseController(std::move(context))
{}
std::vector<BaseController::RouteConfig> StoreController::getRoutes() const
{
return {{"/api/v1/items", "POST",
[this](const httplib::Request& req, httplib::Response& res) {
const_cast<StoreController*>(this)->addItem(req, res);
}},
{"/api/v1/items", "GET",
[this](const httplib::Request& req, httplib::Response& res) {
const_cast<StoreController*>(this)->listItems(req, res);
}},
{"/api/v1/items/(.*)", "GET",
[this](const httplib::Request& req, httplib::Response& res) {
const_cast<StoreController*>(this)->getItem(req, res);
}},
{"/api/v1/items/(.*)", "DELETE",
[this](const httplib::Request& req, httplib::Response& res) {
const_cast<StoreController*>(this)->deleteItem(req, res);
}}};
}
void StoreController::addItem(const httplib::Request& req,
httplib::Response& res)
{
try {
auto userId = extractUserId<Context, domain::User::Id_t>(req);
assertUserId(userId);
auto item = infrastructure::JsonItem::fromJson(req.body);
item.userId = userId.value();
auto itemId = getContext<Context>().addItemUc.execute(std::move(item));
nlohmann::json responseData = nlohmann::json::object();
responseData["id"] = itemId;
res.status = httplib::StatusCode::Created_201;
res.set_content(infrastructure::Jsend::success(responseData),
"application/json");
} catch (const std::exception& e) {
sendError(res, e.what(), httplib::StatusCode::InternalServerError_500);
}
}
void StoreController::listItems(const httplib::Request& req,
httplib::Response& res)
{
try {
auto userId = extractUserId<Context, domain::User::Id_t>(req);
assertUserId(userId);
auto items = getContext<Context>().listItemsUc.execute(userId.value());
nlohmann::json responseData = nlohmann::json::array();
for (const auto& item : items) {
responseData.push_back(infrastructure::JsonItem::toJsonObj(item));
}
res.status = httplib::StatusCode::OK_200;
res.set_content(infrastructure::Jsend::success(responseData),
"application/json");
} catch (const std::exception& e) {
sendError(res, e.what(), httplib::StatusCode::InternalServerError_500);
}
}
void StoreController::getItem(const httplib::Request& req,
httplib::Response& res)
{
try {
auto itemId = req.matches[1];
auto userId = extractUserId<Context, domain::User::Id_t>(req);
assertUserId(userId);
auto item = getContext<Context>().getItemUc.execute(itemId, userId.value());
auto responseData = infrastructure::JsonItem::toJsonObj(*item);
res.status = httplib::StatusCode::OK_200;
res.set_content(infrastructure::Jsend::success(responseData),
"application/json");
} catch (const nxl::autostore::application::ItemNotFoundException& e) {
sendError(res, e.what(), httplib::StatusCode::NotFound_404);
} catch (const std::exception& e) {
sendError(res, e.what(), httplib::StatusCode::InternalServerError_500);
}
}
void StoreController::deleteItem(const httplib::Request& req,
httplib::Response& res)
{
try {
auto itemId = req.matches[1];
auto userId = extractUserId<Context, domain::User::Id_t>(req);
assertUserId(userId);
getContext<Context>().deleteItemUc.execute(itemId, userId.value());
nlohmann::json responseData = nlohmann::json::object();
responseData["message"] = "Item deleted successfully";
res.status = httplib::StatusCode::NoContent_204;
// Actually, no content should follow 204 response
// res.set_content(infrastructure::Jsend::success(responseData),
// "application/json");
} catch (const nxl::autostore::application::ItemNotFoundException& e) {
sendError(res, e.what(), httplib::StatusCode::NotFound_404);
} catch (const std::exception& e) {
sendError(res, e.what(), httplib::StatusCode::InternalServerError_500);
}
}
void StoreController::assertUserId(
std::optional<domain::User::Id_t> userId) const
{
if (!userId) {
throw std::runtime_error("User ID not found in request");
}
}
} // namespace nxl::autostore::webapi