17 changed files with 403 additions and 76 deletions
@ -0,0 +1,45 @@
|
||||
#include "DiContainer.h" |
||||
#include "infrastructure/repositories/FileItemRepository.h" |
||||
#include "infrastructure/adapters/SystemClock.h" |
||||
#include "infrastructure/http/HttpOrderService.h" |
||||
#include "infrastructure/http/HttpServer.h" |
||||
#include "application/commands/AddItem.h" |
||||
#include "webapi/controllers/StoreController.h" |
||||
#include <filesystem> |
||||
|
||||
namespace nxl::autostore::di { |
||||
|
||||
DiContainer::DiContainer() |
||||
{ |
||||
registerDependencies(); |
||||
} |
||||
|
||||
void DiContainer::registerDependencies() |
||||
{ |
||||
// Register shared references
|
||||
|
||||
container.register_type<dingo::scope<dingo::shared>, |
||||
dingo::storage<infrastructure::FileItemRepository>, |
||||
dingo::interface<application::IItemRepository>>(); |
||||
|
||||
container.register_type<dingo::scope<dingo::shared>, |
||||
dingo::storage<infrastructure::SystemClock>, |
||||
dingo::interface<application::IClock>>(); |
||||
|
||||
container.register_type<dingo::scope<dingo::shared>, |
||||
dingo::storage<infrastructure::HttpOrderService>, |
||||
dingo::interface<application::IOrderService>>(); |
||||
|
||||
container.register_type<dingo::scope<dingo::shared>, |
||||
dingo::storage<infrastructure::HttpServer>>(); |
||||
|
||||
container.register_indexed_type<dingo::scope<dingo::shared>, |
||||
dingo::storage<application::AddItem>, |
||||
dingo::interface<application::AddItem>>( |
||||
std::string("AddItem")); |
||||
|
||||
// test:
|
||||
auto uc = container.resolve<application::AddItem>( |
||||
std::string("AddItem")); // throws on start
|
||||
} |
||||
} // namespace nxl::autostore::di
|
||||
@ -0,0 +1,102 @@
|
||||
#pragma once |
||||
|
||||
#include <dingo/container.h> |
||||
#include <dingo/factory/constructor.h> |
||||
#include <dingo/storage/external.h> |
||||
#include <dingo/storage/shared.h> |
||||
#include <dingo/index/unordered_map.h> |
||||
|
||||
#include <memory> |
||||
#include <string> |
||||
#include <filesystem> |
||||
#include <tuple> |
||||
|
||||
// Forward declarations
|
||||
namespace nxl::autostore { |
||||
class AutoStore; |
||||
} |
||||
|
||||
namespace nxl::autostore::infrastructure { |
||||
class FileItemRepository; |
||||
class SystemClock; |
||||
class HttpOrderService; |
||||
class HttpServer; |
||||
} // namespace nxl::autostore::infrastructure
|
||||
|
||||
namespace nxl::autostore::application { |
||||
class AddItem; |
||||
} |
||||
|
||||
namespace nxl::autostore::webapi { |
||||
class StoreController; |
||||
} |
||||
|
||||
namespace nxl::autostore::di { |
||||
|
||||
// Declare traits with std::string based index for named resolution
|
||||
struct container_traits : dingo::dynamic_container_traits |
||||
{ |
||||
using index_definition_type = |
||||
std::tuple<std::tuple<std::string, dingo::index_type::unordered_map>>; |
||||
}; |
||||
|
||||
/**
|
||||
* @brief Dependency Injection Container for AutoStore application |
||||
* |
||||
* This class wraps the dingo container and provides a simplified interface |
||||
* for registering and resolving dependencies in the AutoStore application. |
||||
*/ |
||||
class DiContainer |
||||
{ |
||||
public: |
||||
/**
|
||||
* @brief Construct a new DiContainer object |
||||
*/ |
||||
DiContainer(); |
||||
|
||||
/**
|
||||
* @brief Destroy the DiContainer object |
||||
*/ |
||||
~DiContainer() = default; |
||||
|
||||
/**
|
||||
* @brief Register all application dependencies |
||||
* |
||||
* @param dataPath Path to the data directory |
||||
* @param port HTTP server port |
||||
* @param host HTTP server host |
||||
*/ |
||||
void registerDependencies(); |
||||
|
||||
/**
|
||||
* @brief Resolve a dependency by type |
||||
* |
||||
* @tparam T Type to resolve |
||||
* @return Instance of the resolved type |
||||
*/ |
||||
template <typename T> T resolve() { return container.resolve<T>(); } |
||||
|
||||
/**
|
||||
* @brief Resolve a dependency by type as a shared pointer |
||||
* |
||||
* @tparam T Type to resolve |
||||
* @return Shared pointer to the resolved type |
||||
*/ |
||||
template <typename T> std::shared_ptr<T> resolveShared() |
||||
{ |
||||
return container.resolve<std::shared_ptr<T>>(); |
||||
} |
||||
|
||||
/**
|
||||
* @brief Resolve a dependency by type as a reference |
||||
* |
||||
* @tparam T Type to resolve |
||||
* @return Reference to the resolved type |
||||
*/ |
||||
template <typename T> T& resolveRef() { return container.resolve<T&>(); } |
||||
|
||||
private: |
||||
dingo::container<container_traits> container; |
||||
}; |
||||
|
||||
} // namespace nxl::autostore::di
|
||||
@ -0,0 +1,10 @@
|
||||
#pragma once |
||||
|
||||
#include "domain/entities/Item.h" |
||||
#include <functional> |
||||
|
||||
namespace nxl::autostore::application { |
||||
|
||||
using ItemPresenter = std::function<void(const domain::Item& item)>; |
||||
|
||||
} // namespace nxl::autostore::application
|
||||
@ -0,0 +1,32 @@
|
||||
#include "infrastructure/helpers/Jsend.h" |
||||
|
||||
namespace nxl::autostore::infrastructure { |
||||
|
||||
std::string Jsend::success(const nlohmann::json& data) |
||||
{ |
||||
nlohmann::json response; |
||||
response["status"] = "success"; |
||||
|
||||
if (!data.is_null()) { |
||||
response["data"] = data; |
||||
} |
||||
|
||||
return response.dump(); |
||||
} |
||||
|
||||
std::string Jsend::error(const std::string& message, int code, |
||||
const nlohmann::json& data) |
||||
{ |
||||
nlohmann::json response; |
||||
response["status"] = "error"; |
||||
response["message"] = message; |
||||
response["code"] = code; |
||||
|
||||
if (!data.is_null()) { |
||||
response["data"] = data; |
||||
} |
||||
|
||||
return response.dump(); |
||||
} |
||||
|
||||
} // namespace nxl::autostore::infrastructure
|
||||
@ -0,0 +1,20 @@
|
||||
#pragma once |
||||
|
||||
#include "nlohmann/json.hpp" |
||||
#include <string> |
||||
|
||||
namespace nxl::autostore::infrastructure { |
||||
|
||||
class Jsend |
||||
{ |
||||
public: |
||||
static std::string success(const nlohmann::json& data = nullptr); |
||||
static std::string error(const std::string& message, int code = 500, |
||||
const nlohmann::json& data = nullptr); |
||||
|
||||
private: |
||||
Jsend() = delete; |
||||
~Jsend() = delete; |
||||
}; |
||||
|
||||
} // namespace nxl::autostore::infrastructure
|
||||
@ -0,0 +1,76 @@
|
||||
#include "infrastructure/helpers/JsonItem.h" |
||||
#include <chrono> |
||||
#include <ctime> |
||||
#include <stdexcept> |
||||
#include <type_traits> |
||||
|
||||
namespace nxl::autostore::infrastructure { |
||||
domain::Item JsonItem::fromJson(const std::string& jsonBody) |
||||
{ |
||||
auto json = nlohmann::json::parse(jsonBody); |
||||
return fromJsonObj(json); |
||||
} |
||||
|
||||
domain::Item JsonItem::fromJsonObj(const nlohmann::json& j) |
||||
{ |
||||
domain::Item item; |
||||
item.id = j.value("id", ""); |
||||
item.name = j.value("name", ""); |
||||
item.orderUrl = j.value("orderUrl", ""); |
||||
item.userId = j.value("userId", "default-user"); |
||||
|
||||
if (j["expirationDate"].is_number()) { |
||||
// Handle numeric timestamp
|
||||
time_t timestamp = j["expirationDate"]; |
||||
item.expirationDate = std::chrono::system_clock::from_time_t(timestamp); |
||||
} else if (j["expirationDate"].is_string()) { |
||||
// Handle ISO 8601 string format
|
||||
std::string dateStr = j["expirationDate"]; |
||||
std::tm tm = {}; |
||||
std::istringstream ss(dateStr); |
||||
|
||||
// Parse the ISO 8601 format
|
||||
ss >> std::get_time(&tm, "%Y-%m-%dT%H:%M:%S"); |
||||
if (ss.fail()) { |
||||
throw std::runtime_error( |
||||
"Invalid format for expirationDate string. Expected ISO 8601 format " |
||||
"(YYYY-MM-DDTHH:MM:SS)."); |
||||
} |
||||
|
||||
// Convert to time_t
|
||||
time_t timestamp = std::mktime(&tm); |
||||
if (timestamp == -1) { |
||||
throw std::runtime_error( |
||||
"Failed to convert expirationDate to timestamp."); |
||||
} |
||||
|
||||
item.expirationDate = std::chrono::system_clock::from_time_t(timestamp); |
||||
} else { |
||||
throw std::runtime_error("Invalid type for expirationDate. Expected number " |
||||
"(Unix timestamp) or string (ISO 8601 format)."); |
||||
} |
||||
|
||||
if (item.name.empty()) { |
||||
throw std::runtime_error("Item name is required"); |
||||
} |
||||
|
||||
return item; |
||||
} |
||||
|
||||
std::string JsonItem::toJson(const domain::Item& item) |
||||
{ |
||||
return toJsonObj(item).dump(); |
||||
} |
||||
|
||||
nlohmann::json JsonItem::toJsonObj(const domain::Item& item) |
||||
{ |
||||
nlohmann::json j; |
||||
j["id"] = item.id; |
||||
j["name"] = item.name; |
||||
j["expirationDate"] = |
||||
std::chrono::system_clock::to_time_t(item.expirationDate); |
||||
j["orderUrl"] = item.orderUrl; |
||||
j["userId"] = item.userId; |
||||
return j; |
||||
} |
||||
} // namespace nxl::autostore::infrastructure
|
||||
@ -0,0 +1,22 @@
|
||||
#pragma once |
||||
|
||||
#include "domain/entities/Item.h" |
||||
#include "nlohmann/json.hpp" |
||||
#include <string> |
||||
|
||||
namespace nxl::autostore::infrastructure { |
||||
|
||||
class JsonItem |
||||
{ |
||||
public: |
||||
static domain::Item fromJson(const std::string& jsonBody); |
||||
static std::string toJson(const domain::Item& item); |
||||
static nlohmann::json toJsonObj(const domain::Item& item); |
||||
static domain::Item fromJsonObj(const nlohmann::json& j); |
||||
|
||||
private: |
||||
JsonItem() = delete; |
||||
~JsonItem() = delete; |
||||
}; |
||||
|
||||
} // namespace nxl::autostore::infrastructure
|
||||
@ -0,0 +1,36 @@
|
||||
#include "HttpOrderService.h" |
||||
#include <stdexcept> |
||||
#include <iostream> |
||||
|
||||
namespace nxl::autostore::infrastructure { |
||||
|
||||
HttpOrderService::HttpOrderService(const std::string& baseUrl) |
||||
: baseUrl(baseUrl) |
||||
{} |
||||
|
||||
void HttpOrderService::orderItem(const domain::Item& item) |
||||
{ |
||||
if (item.orderUrl.empty()) { |
||||
throw std::runtime_error("Order URL is empty for item: " + item.name); |
||||
} |
||||
|
||||
std::string payload = |
||||
R"({"itemName": ")" + item.name + R"(", "itemId": ")" + item.id + "\"}"; |
||||
sendPostRequest(item.orderUrl, payload); |
||||
} |
||||
|
||||
void HttpOrderService::sendPostRequest(const std::string& url, |
||||
const std::string& payload) |
||||
{ |
||||
// In a real implementation, this would use an HTTP client library
|
||||
// For now, we'll simulate the HTTP call
|
||||
std::cout << "POST request to: " << url << std::endl; |
||||
std::cout << "Payload: " << payload << std::endl; |
||||
|
||||
// Simulate HTTP error handling
|
||||
if (url.find("error") != std::string::npos) { |
||||
throw std::runtime_error("Failed to send order request to: " + url); |
||||
} |
||||
} |
||||
|
||||
} // namespace nxl::autostore::infrastructure
|
||||
@ -0,0 +1,20 @@
|
||||
#pragma once |
||||
|
||||
#include "application/interfaces/IOrderService.h" |
||||
#include "domain/entities/Item.h" |
||||
#include <string> |
||||
|
||||
namespace nxl::autostore::infrastructure { |
||||
|
||||
class HttpOrderService : public application::IOrderService |
||||
{ |
||||
public: |
||||
explicit HttpOrderService(const std::string& baseUrl = ""); |
||||
void orderItem(const domain::Item& item) override; |
||||
|
||||
private: |
||||
std::string baseUrl; |
||||
void sendPostRequest(const std::string& url, const std::string& payload); |
||||
}; |
||||
|
||||
} // namespace nxl::autostore::infrastructure
|
||||
@ -1,23 +1,21 @@
|
||||
#pragma once |
||||
|
||||
#include "application/commands/AddItem.h" |
||||
#include "domain/entities/Item.h" |
||||
#include <httplib.h> |
||||
#include <nlohmann/json.hpp> |
||||
#include "DiContainer.h" |
||||
#include <httplib.h> // TODO: forward declaration |
||||
|
||||
namespace nxl::autostore::webapi { |
||||
|
||||
class StoreController |
||||
{ |
||||
public: |
||||
StoreController(application::AddItem& addItemUseCase); |
||||
StoreController(di::DiContainer& diContainer); |
||||
|
||||
void registerRoutes(httplib::Server& server); |
||||
|
||||
private: |
||||
void addItem(const httplib::Request& req, httplib::Response& res); |
||||
|
||||
application::AddItem addItemUseCase; |
||||
di::DiContainer& diContainer; |
||||
}; |
||||
|
||||
} // namespace nxl::autostore::webapi
|
||||
Loading…
Reference in new issue