18 changed files with 624 additions and 74 deletions
@ -0,0 +1,83 @@
|
||||
--- |
||||
Language: Cpp |
||||
AccessModifierOffset: -2 |
||||
AlignAfterOpenBracket: Align |
||||
AlignConsecutiveAssignments: false |
||||
AlignConsecutiveDeclarations: false |
||||
AlignEscapedNewlines: Right |
||||
AlignOperands: true |
||||
AlignTrailingComments: true |
||||
AllowAllArgumentsOnNextLine: true |
||||
AllowAllConstructorInitializersOnNextLine: true |
||||
AllowAllParametersOfDeclarationOnNextLine: true |
||||
AllowShortBlocksOnASingleLine: false |
||||
AllowShortCaseLabelsOnASingleLine: false |
||||
AllowShortFunctionsOnASingleLine: Inline |
||||
AllowShortIfStatementsOnASingleLine: false |
||||
AllowShortLoopsOnASingleLine: false |
||||
AlwaysBreakAfterDefinitionReturnType: None |
||||
AlwaysBreakAfterReturnType: None |
||||
AlwaysBreakBeforeMultilineStrings: false |
||||
AlwaysBreakTemplateDeclarations: MultiLine |
||||
BinPackArguments: true |
||||
BinPackParameters: true |
||||
BreakBeforeBinaryOperators: NonAssignment |
||||
BreakBeforeBraces: Custom |
||||
BraceWrapping: |
||||
AfterClass: true |
||||
AfterControlStatement: false |
||||
AfterEnum: false |
||||
AfterFunction: true |
||||
AfterNamespace: false |
||||
AfterStruct: true |
||||
AfterUnion: false |
||||
AfterExternBlock: false |
||||
BeforeCatch: false |
||||
BeforeElse: false |
||||
IndentBraces: false |
||||
SplitEmptyFunction: false |
||||
SplitEmptyRecord: false |
||||
SplitEmptyNamespace: false |
||||
BreakBeforeInheritanceComma: false |
||||
BreakInheritanceList: BeforeColon |
||||
ColumnLimit: 80 |
||||
CompactNamespaces: false |
||||
ConstructorInitializerIndentWidth: 2 |
||||
ContinuationIndentWidth: 2 |
||||
Cpp11BracedListStyle: true |
||||
DerivePointerAlignment: false |
||||
DisableFormat: false |
||||
ExperimentalAutoDetectBinPacking: false |
||||
FixNamespaceComments: true |
||||
IndentCaseLabels: true |
||||
IndentPPDirectives: None |
||||
IndentWidth: 2 |
||||
IndentWrappedFunctionNames: false |
||||
KeepEmptyLinesAtTheStartOfBlocks: false |
||||
# LambdaBodyIndentation: Signature |
||||
MaxEmptyLinesToKeep: 1 |
||||
NamespaceIndentation: None |
||||
PointerAlignment: Left |
||||
ReflowComments: true |
||||
SortIncludes: false |
||||
SortUsingDeclarations: false |
||||
SpaceAfterCStyleCast: false |
||||
SpaceAfterLogicalNot: false |
||||
SpaceAfterTemplateKeyword: true |
||||
# SpaceAroundPointerQualifiers: Default |
||||
SpaceBeforeAssignmentOperators: true |
||||
SpaceBeforeCpp11BracedList: false |
||||
SpaceBeforeCtorInitializerColon: true |
||||
SpaceBeforeInheritanceColon: true |
||||
SpaceBeforeParens: ControlStatements |
||||
SpaceBeforeRangeBasedForLoopColon: true |
||||
SpaceInEmptyParentheses: false |
||||
SpacesBeforeTrailingComments: 1 |
||||
SpacesInAngles: false |
||||
SpacesInCStyleCastParentheses: false |
||||
SpacesInConditionalStatement: false |
||||
SpacesInContainerLiterals: true |
||||
SpacesInParentheses: false |
||||
SpacesInSquareBrackets: false |
||||
TabWidth: 8 |
||||
UseTab: Never |
||||
@ -1,25 +1,37 @@
|
||||
#include "App.h" |
||||
#include "autostore/AutoStore.h" |
||||
#include <iostream> |
||||
|
||||
namespace nxl |
||||
namespace nxl { |
||||
|
||||
std::condition_variable App::exitCv; |
||||
std::mutex App::mtx; |
||||
bool App::shouldExit = false; |
||||
|
||||
App::App(int argc, char** argv) |
||||
{ |
||||
App::App(int argc, char **argv) |
||||
{ |
||||
signal(SIGINT, App::handle_signal); |
||||
signal(SIGTERM, App::handle_signal); |
||||
} |
||||
|
||||
int App::exec() |
||||
{ |
||||
nxl::AutoStore autostore; |
||||
autostore.run(); |
||||
return 0; |
||||
} |
||||
|
||||
void App::handle_signal(int signum) |
||||
{ |
||||
std::cout << "\nCaught signal " << signum << ". Graceful shutdown." << std::endl; |
||||
exit(signum); |
||||
} |
||||
signal(SIGINT, App::handleSignal); |
||||
signal(SIGTERM, App::handleSignal); |
||||
} |
||||
|
||||
int App::exec() |
||||
{ |
||||
// TODO: start application services when implemented
|
||||
|
||||
std::unique_lock<std::mutex> lock(mtx); |
||||
exitCv.wait(lock, [] { return shouldExit; }); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
void App::handleSignal(int signum) |
||||
{ |
||||
std::cout << "\nCaught signal " << signum << ". Graceful shutdown." |
||||
<< std::endl; |
||||
{ |
||||
std::lock_guard<std::mutex> lock(mtx); |
||||
shouldExit = true; |
||||
} |
||||
exitCv.notify_one(); |
||||
} |
||||
|
||||
} // namespace nxl
|
||||
@ -1,16 +1,24 @@
|
||||
#pragma once |
||||
|
||||
#include <atomic> |
||||
#include <condition_variable> |
||||
#include <csignal> |
||||
#include <mutex> |
||||
#include <thread> |
||||
|
||||
namespace nxl |
||||
namespace nxl { |
||||
|
||||
class App |
||||
{ |
||||
class App |
||||
{ |
||||
public: |
||||
App(int argc, char **argv); |
||||
int exec(); |
||||
public: |
||||
App(int argc, char** argv); |
||||
int exec(); |
||||
|
||||
private: |
||||
static void handleSignal(int signum); |
||||
static std::condition_variable exitCv; |
||||
static std::mutex mtx; |
||||
static bool shouldExit; |
||||
}; |
||||
|
||||
private: |
||||
static void handle_signal(int signum); |
||||
}; |
||||
} |
||||
} // namespace nxl
|
||||
@ -1,11 +0,0 @@
|
||||
#pragma once |
||||
|
||||
namespace nxl |
||||
{ |
||||
class AutoStore |
||||
{ |
||||
public: |
||||
AutoStore(); |
||||
void run(); |
||||
}; |
||||
} // namespace nxl
|
||||
@ -0,0 +1,21 @@
|
||||
#pragma once |
||||
|
||||
#include <string> |
||||
#include <string_view> |
||||
#include <optional> |
||||
|
||||
namespace nxl { |
||||
namespace autostore { |
||||
namespace application { |
||||
|
||||
class IAuthService |
||||
{ |
||||
public: |
||||
virtual ~IAuthService() = default; |
||||
virtual std::string generateToken(std::string_view userId) = 0; |
||||
virtual std::optional<std::string> validateToken(std::string_view token) = 0; |
||||
}; |
||||
|
||||
} // namespace application
|
||||
} // namespace autostore
|
||||
} // namespace nxl
|
||||
@ -0,0 +1,26 @@
|
||||
#pragma once |
||||
|
||||
#include "domain/entities/Item.h" |
||||
#include <optional> |
||||
#include <string> |
||||
#include <string_view> |
||||
#include <vector> |
||||
|
||||
namespace nxl { |
||||
namespace autostore { |
||||
namespace application { |
||||
|
||||
class IItemRepository |
||||
{ |
||||
public: |
||||
virtual ~IItemRepository() = default; |
||||
virtual void save(const domain::Item& item) = 0; |
||||
virtual std::optional<domain::Item> findById(std::string_view id) = 0; |
||||
virtual std::vector<domain::Item> findByUser(std::string_view userId) = 0; |
||||
virtual std::vector<domain::Item> findAll() = 0; |
||||
virtual void remove(std::string_view id) = 0; |
||||
}; |
||||
|
||||
} // namespace application
|
||||
} // namespace autostore
|
||||
} // namespace nxl
|
||||
@ -0,0 +1,27 @@
|
||||
#pragma once |
||||
|
||||
#include "domain/entities/User.h" |
||||
#include <optional> |
||||
#include <string> |
||||
#include <string_view> |
||||
#include <vector> |
||||
|
||||
namespace nxl { |
||||
namespace autostore { |
||||
namespace application { |
||||
|
||||
class IUserRepository |
||||
{ |
||||
public: |
||||
virtual ~IUserRepository() = default; |
||||
virtual void save(const domain::User& user) = 0; |
||||
virtual std::optional<domain::User> findById(std::string_view id) = 0; |
||||
virtual std::optional<domain::User> |
||||
findByUsername(std::string_view username) = 0; |
||||
virtual std::vector<domain::User> findAll() = 0; |
||||
virtual void remove(std::string_view id) = 0; |
||||
}; |
||||
|
||||
} // namespace application
|
||||
} // namespace autostore
|
||||
} // namespace nxl
|
||||
@ -0,0 +1,21 @@
|
||||
#pragma once |
||||
|
||||
#include <string> |
||||
#include <chrono> |
||||
|
||||
namespace nxl { |
||||
namespace autostore { |
||||
namespace domain { |
||||
|
||||
struct Item |
||||
{ |
||||
std::string id; |
||||
std::string name; |
||||
std::chrono::system_clock::time_point expirationDate; |
||||
std::string orderUrl; |
||||
std::string userId; |
||||
}; |
||||
|
||||
} // namespace domain
|
||||
} // namespace autostore
|
||||
} // namespace nxl
|
||||
@ -0,0 +1,18 @@
|
||||
#pragma once |
||||
|
||||
#include <string> |
||||
|
||||
namespace nxl { |
||||
namespace autostore { |
||||
namespace domain { |
||||
|
||||
struct User |
||||
{ |
||||
std::string id; |
||||
std::string username; |
||||
std::string passwordHash; |
||||
}; |
||||
|
||||
} // namespace domain
|
||||
} // namespace autostore
|
||||
} // namespace nxl
|
||||
@ -0,0 +1,33 @@
|
||||
#pragma once |
||||
|
||||
#include "application/interfaces/IItemRepository.h" |
||||
#include <string> |
||||
#include <vector> |
||||
#include <mutex> |
||||
|
||||
namespace nxl { |
||||
namespace autostore { |
||||
namespace infrastructure { |
||||
|
||||
class FileItemRepository : public application::IItemRepository |
||||
{ |
||||
public: |
||||
explicit FileItemRepository(std::string_view dbPath); |
||||
void save(const domain::Item& item) override; |
||||
std::optional<domain::Item> findById(std::string_view id) override; |
||||
std::vector<domain::Item> findByUser(std::string_view userId) override; |
||||
std::vector<domain::Item> findAll() override; |
||||
void remove(std::string_view id) override; |
||||
|
||||
private: |
||||
void load(); |
||||
void persist(); |
||||
|
||||
std::string dbPath; |
||||
std::vector<domain::Item> items; |
||||
std::mutex mtx; |
||||
}; |
||||
|
||||
} // namespace infrastructure
|
||||
} // namespace autostore
|
||||
} // namespace nxl
|
||||
@ -0,0 +1,34 @@
|
||||
#pragma once |
||||
|
||||
#include "application/interfaces/IUserRepository.h" |
||||
#include <string> |
||||
#include <vector> |
||||
#include <mutex> |
||||
|
||||
namespace nxl { |
||||
namespace autostore { |
||||
namespace infrastructure { |
||||
|
||||
class FileUserRepository : public application::IUserRepository |
||||
{ |
||||
public: |
||||
explicit FileUserRepository(std::string_view dbPath); |
||||
void save(const domain::User& user) override; |
||||
std::optional<domain::User> findById(std::string_view id) override; |
||||
std::optional<domain::User> |
||||
findByUsername(std::string_view username) override; |
||||
std::vector<domain::User> findAll() override; |
||||
void remove(std::string_view id) override; |
||||
|
||||
private: |
||||
void load(); |
||||
void persist(); |
||||
|
||||
std::string dbPath; |
||||
std::vector<domain::User> users; |
||||
std::mutex mtx; |
||||
}; |
||||
|
||||
} // namespace infrastructure
|
||||
} // namespace autostore
|
||||
} // namespace nxl
|
||||
@ -1,15 +0,0 @@
|
||||
#include "autostore/AutoStore.h" |
||||
#include <iostream> |
||||
|
||||
namespace nxl |
||||
{ |
||||
AutoStore::AutoStore() |
||||
{ |
||||
std::cout << "AutoStore library initialized." << std::endl; |
||||
} |
||||
|
||||
void AutoStore::run() |
||||
{ |
||||
std::cout << "AutoStore library is running." << std::endl; |
||||
} |
||||
} // namespace nxl
|
||||
@ -0,0 +1,142 @@
|
||||
#include "infrastructure/repositories/FileItemRepository.h" |
||||
#include "nlohmann/json.hpp" |
||||
#include <fstream> |
||||
#include <algorithm> |
||||
#include <chrono> |
||||
#include <ctime> |
||||
#include <iterator> |
||||
|
||||
namespace nxl { |
||||
namespace autostore { |
||||
namespace infrastructure { |
||||
|
||||
namespace { |
||||
|
||||
// Helper functions for JSON serialization
|
||||
inline void itemToJson(nlohmann::json& j, const domain::Item& item) |
||||
{ |
||||
j = |
||||
nlohmann::json{{"id", item.id}, |
||||
{"name", item.name}, |
||||
{"expirationDate", |
||||
std::chrono::system_clock::to_time_t(item.expirationDate)}, |
||||
{"orderUrl", item.orderUrl}, |
||||
{"userId", item.userId}}; |
||||
} |
||||
|
||||
inline void jsonToItem(const nlohmann::json& j, domain::Item& item) |
||||
{ |
||||
j.at("id").get_to(item.id); |
||||
j.at("name").get_to(item.name); |
||||
std::time_t expirationTime; |
||||
j.at("expirationDate").get_to(expirationTime); |
||||
item.expirationDate = std::chrono::system_clock::from_time_t(expirationTime); |
||||
j.at("orderUrl").get_to(item.orderUrl); |
||||
j.at("userId").get_to(item.userId); |
||||
} |
||||
|
||||
// Helper functions for vector serialization
|
||||
inline nlohmann::json itemsToJson(const std::vector<domain::Item>& items) |
||||
{ |
||||
nlohmann::json j = nlohmann::json::array(); |
||||
for (const auto& item : items) { |
||||
nlohmann::json itemJson; |
||||
itemToJson(itemJson, item); |
||||
j.push_back(itemJson); |
||||
} |
||||
return j; |
||||
} |
||||
|
||||
inline std::vector<domain::Item> jsonToItems(const nlohmann::json& j) |
||||
{ |
||||
std::vector<domain::Item> items; |
||||
for (const auto& itemJson : j) { |
||||
domain::Item item; |
||||
jsonToItem(itemJson, item); |
||||
items.push_back(item); |
||||
} |
||||
return items; |
||||
} |
||||
|
||||
} // namespace
|
||||
|
||||
FileItemRepository::FileItemRepository(std::string_view dbPath) : dbPath(dbPath) |
||||
{ |
||||
load(); |
||||
} |
||||
|
||||
void FileItemRepository::save(const domain::Item& item) |
||||
{ |
||||
std::lock_guard<std::mutex> lock(mtx); |
||||
auto it = |
||||
std::find_if(items.begin(), items.end(), |
||||
[&](const domain::Item& i) { return i.id == item.id; }); |
||||
|
||||
if (it != items.end()) { |
||||
*it = item; |
||||
} else { |
||||
items.push_back(item); |
||||
} |
||||
persist(); |
||||
} |
||||
|
||||
std::optional<domain::Item> FileItemRepository::findById(std::string_view id) |
||||
{ |
||||
std::lock_guard<std::mutex> lock(mtx); |
||||
auto it = std::find_if(items.begin(), items.end(), |
||||
[&](const domain::Item& i) { return i.id == id; }); |
||||
|
||||
if (it != items.end()) { |
||||
return *it; |
||||
} |
||||
return std::nullopt; |
||||
} |
||||
|
||||
std::vector<domain::Item> |
||||
FileItemRepository::findByUser(std::string_view userId) |
||||
{ |
||||
std::lock_guard<std::mutex> lock(mtx); |
||||
std::vector<domain::Item> userItems; |
||||
std::copy_if(items.begin(), items.end(), std::back_inserter(userItems), |
||||
[&](const domain::Item& i) { return i.userId == userId; }); |
||||
return userItems; |
||||
} |
||||
|
||||
std::vector<domain::Item> FileItemRepository::findAll() |
||||
{ |
||||
std::lock_guard<std::mutex> lock(mtx); |
||||
return items; |
||||
} |
||||
|
||||
void FileItemRepository::remove(std::string_view id) |
||||
{ |
||||
std::lock_guard<std::mutex> lock(mtx); |
||||
items.erase(std::remove_if(items.begin(), items.end(), |
||||
[&](const domain::Item& i) { return i.id == id; }), |
||||
items.end()); |
||||
persist(); |
||||
} |
||||
|
||||
void FileItemRepository::load() |
||||
{ |
||||
std::lock_guard<std::mutex> lock(mtx); |
||||
std::ifstream file(dbPath); |
||||
if (file.is_open()) { |
||||
nlohmann::json j; |
||||
file >> j; |
||||
items = jsonToItems(j); |
||||
} |
||||
} |
||||
|
||||
void FileItemRepository::persist() |
||||
{ |
||||
std::ofstream file(dbPath); |
||||
if (file.is_open()) { |
||||
nlohmann::json j = itemsToJson(items); |
||||
file << j.dump(4); |
||||
} |
||||
} |
||||
|
||||
} // namespace infrastructure
|
||||
} // namespace autostore
|
||||
} // namespace nxl
|
||||
@ -0,0 +1,134 @@
|
||||
#include "infrastructure/repositories/FileUserRepository.h" |
||||
#include "nlohmann/json.hpp" |
||||
#include <fstream> |
||||
#include <algorithm> |
||||
|
||||
namespace nxl { |
||||
namespace autostore { |
||||
namespace infrastructure { |
||||
|
||||
namespace { |
||||
|
||||
// Helper functions for JSON serialization
|
||||
inline void userToJson(nlohmann::json& j, const domain::User& u) |
||||
{ |
||||
j = nlohmann::json{ |
||||
{"id", u.id}, {"username", u.username}, {"passwordHash", u.passwordHash}}; |
||||
} |
||||
|
||||
inline void jsonToUser(const nlohmann::json& j, domain::User& u) |
||||
{ |
||||
j.at("id").get_to(u.id); |
||||
j.at("username").get_to(u.username); |
||||
j.at("passwordHash").get_to(u.passwordHash); |
||||
} |
||||
|
||||
// Helper functions for vector serialization
|
||||
inline nlohmann::json usersToJson(const std::vector<domain::User>& users) |
||||
{ |
||||
nlohmann::json j = nlohmann::json::array(); |
||||
for (const auto& user : users) { |
||||
nlohmann::json userJson; |
||||
userToJson(userJson, user); |
||||
j.push_back(userJson); |
||||
} |
||||
return j; |
||||
} |
||||
|
||||
inline std::vector<domain::User> jsonToUsers(const nlohmann::json& j) |
||||
{ |
||||
std::vector<domain::User> users; |
||||
for (const auto& userJson : j) { |
||||
domain::User user; |
||||
jsonToUser(userJson, user); |
||||
users.push_back(user); |
||||
} |
||||
return users; |
||||
} |
||||
|
||||
} // namespace
|
||||
|
||||
FileUserRepository::FileUserRepository(std::string_view dbPath) : dbPath(dbPath) |
||||
{ |
||||
load(); |
||||
} |
||||
|
||||
void FileUserRepository::save(const domain::User& user) |
||||
{ |
||||
std::lock_guard<std::mutex> lock(mtx); |
||||
auto it = |
||||
std::find_if(users.begin(), users.end(), |
||||
[&](const domain::User& u) { return u.id == user.id; }); |
||||
|
||||
if (it != users.end()) { |
||||
*it = user; |
||||
} else { |
||||
users.push_back(user); |
||||
} |
||||
persist(); |
||||
} |
||||
|
||||
std::optional<domain::User> FileUserRepository::findById(std::string_view id) |
||||
{ |
||||
std::lock_guard<std::mutex> lock(mtx); |
||||
auto it = std::find_if(users.begin(), users.end(), |
||||
[&](const domain::User& u) { return u.id == id; }); |
||||
|
||||
if (it != users.end()) { |
||||
return *it; |
||||
} |
||||
return std::nullopt; |
||||
} |
||||
|
||||
std::optional<domain::User> |
||||
FileUserRepository::findByUsername(std::string_view username) |
||||
{ |
||||
std::lock_guard<std::mutex> lock(mtx); |
||||
auto it = |
||||
std::find_if(users.begin(), users.end(), |
||||
[&](const domain::User& u) { return u.username == username; }); |
||||
|
||||
if (it != users.end()) { |
||||
return *it; |
||||
} |
||||
return std::nullopt; |
||||
} |
||||
|
||||
std::vector<domain::User> FileUserRepository::findAll() |
||||
{ |
||||
std::lock_guard<std::mutex> lock(mtx); |
||||
return users; |
||||
} |
||||
|
||||
void FileUserRepository::remove(std::string_view id) |
||||
{ |
||||
std::lock_guard<std::mutex> lock(mtx); |
||||
users.erase(std::remove_if(users.begin(), users.end(), |
||||
[&](const domain::User& u) { return u.id == id; }), |
||||
users.end()); |
||||
persist(); |
||||
} |
||||
|
||||
void FileUserRepository::load() |
||||
{ |
||||
std::lock_guard<std::mutex> lock(mtx); |
||||
std::ifstream file(dbPath); |
||||
if (file.is_open()) { |
||||
nlohmann::json j; |
||||
file >> j; |
||||
users = jsonToUsers(j); |
||||
} |
||||
} |
||||
|
||||
void FileUserRepository::persist() |
||||
{ |
||||
std::ofstream file(dbPath); |
||||
if (file.is_open()) { |
||||
nlohmann::json j = usersToJson(users); |
||||
file << j.dump(4); |
||||
} |
||||
} |
||||
|
||||
} // namespace infrastructure
|
||||
} // namespace autostore
|
||||
} // namespace nxl
|
||||
Loading…
Reference in new issue