mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-25 22:34:56 +00:00
code: dbal,operations,hpp (5 files)
This commit is contained in:
@@ -1,56 +0,0 @@
|
||||
/**
|
||||
* @file lua_script_operations.hpp
|
||||
* @brief LuaScript entity CRUD operations
|
||||
*
|
||||
* Single-responsibility module for LuaScript entity operations.
|
||||
*/
|
||||
#ifndef DBAL_LUA_SCRIPT_OPERATIONS_HPP
|
||||
#define DBAL_LUA_SCRIPT_OPERATIONS_HPP
|
||||
|
||||
#include "dbal/types.hpp"
|
||||
#include "dbal/errors.hpp"
|
||||
#include "../store/in_memory_store.hpp"
|
||||
#include "lua_script/index.hpp"
|
||||
|
||||
namespace dbal {
|
||||
namespace entities {
|
||||
|
||||
/**
|
||||
* Create a new Lua script in the store
|
||||
*/
|
||||
inline Result<LuaScript> createLuaScript(InMemoryStore& store, const CreateLuaScriptInput& input) {
|
||||
return lua_script::create(store, input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Lua script by ID
|
||||
*/
|
||||
inline Result<LuaScript> getLuaScript(InMemoryStore& store, const std::string& id) {
|
||||
return lua_script::get(store, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an existing Lua script
|
||||
*/
|
||||
inline Result<LuaScript> updateLuaScript(InMemoryStore& store, const std::string& id, const UpdateLuaScriptInput& input) {
|
||||
return lua_script::update(store, id, input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a Lua script by ID
|
||||
*/
|
||||
inline Result<bool> deleteLuaScript(InMemoryStore& store, const std::string& id) {
|
||||
return lua_script::remove(store, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* List Lua scripts with filtering and pagination
|
||||
*/
|
||||
inline Result<std::vector<LuaScript>> listLuaScripts(InMemoryStore& store, const ListOptions& options) {
|
||||
return lua_script::list(store, options);
|
||||
}
|
||||
|
||||
} // namespace entities
|
||||
} // namespace dbal
|
||||
|
||||
#endif
|
||||
@@ -1,210 +0,0 @@
|
||||
/**
|
||||
* @file session_operations.hpp
|
||||
* @brief Session entity CRUD operations
|
||||
*
|
||||
* Single-responsibility module for Session entity operations.
|
||||
*/
|
||||
#ifndef DBAL_SESSION_OPERATIONS_HPP
|
||||
#define DBAL_SESSION_OPERATIONS_HPP
|
||||
|
||||
#include "dbal/types.hpp"
|
||||
#include "dbal/errors.hpp"
|
||||
#include "../store/in_memory_store.hpp"
|
||||
|
||||
namespace dbal {
|
||||
namespace entities {
|
||||
|
||||
/**
|
||||
* Create a new session in the store
|
||||
*/
|
||||
inline Result<Session> createSession(InMemoryStore& store, const CreateSessionInput& input) {
|
||||
if (input.user_id.empty()) {
|
||||
return Error::validationError("user_id is required");
|
||||
}
|
||||
if (input.token.empty()) {
|
||||
return Error::validationError("token is required");
|
||||
}
|
||||
|
||||
if (store.users.find(input.user_id) == store.users.end()) {
|
||||
return Error::validationError("User not found: " + input.user_id);
|
||||
}
|
||||
if (store.session_tokens.find(input.token) != store.session_tokens.end()) {
|
||||
return Error::conflict("Session token already exists: " + input.token);
|
||||
}
|
||||
|
||||
Session session;
|
||||
session.id = store.generateId("session", ++store.session_counter);
|
||||
session.user_id = input.user_id;
|
||||
session.token = input.token;
|
||||
session.expires_at = input.expires_at;
|
||||
session.created_at = std::chrono::system_clock::now();
|
||||
session.last_activity = session.created_at;
|
||||
|
||||
store.sessions[session.id] = session;
|
||||
store.session_tokens[session.token] = session.id;
|
||||
|
||||
return Result<Session>(session);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a session by ID (cleans expired sessions)
|
||||
*/
|
||||
inline Result<Session> getSession(InMemoryStore& store, const std::string& id) {
|
||||
if (id.empty()) {
|
||||
return Error::validationError("Session ID cannot be empty");
|
||||
}
|
||||
|
||||
auto it = store.sessions.find(id);
|
||||
if (it == store.sessions.end()) {
|
||||
return Error::notFound("Session not found: " + id);
|
||||
}
|
||||
|
||||
auto now = std::chrono::system_clock::now();
|
||||
if (it->second.expires_at <= now) {
|
||||
store.session_tokens.erase(it->second.token);
|
||||
store.sessions.erase(it);
|
||||
return Error::notFound("Session expired: " + id);
|
||||
}
|
||||
|
||||
return Result<Session>(it->second);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an existing session
|
||||
*/
|
||||
inline Result<Session> updateSession(InMemoryStore& store, const std::string& id, const UpdateSessionInput& input) {
|
||||
if (id.empty()) {
|
||||
return Error::validationError("Session ID cannot be empty");
|
||||
}
|
||||
|
||||
auto it = store.sessions.find(id);
|
||||
if (it == store.sessions.end()) {
|
||||
return Error::notFound("Session not found: " + id);
|
||||
}
|
||||
|
||||
Session& session = it->second;
|
||||
|
||||
if (input.user_id.has_value()) {
|
||||
if (input.user_id.value().empty()) {
|
||||
return Error::validationError("user_id is required");
|
||||
}
|
||||
if (store.users.find(input.user_id.value()) == store.users.end()) {
|
||||
return Error::validationError("User not found: " + input.user_id.value());
|
||||
}
|
||||
session.user_id = input.user_id.value();
|
||||
}
|
||||
|
||||
if (input.token.has_value()) {
|
||||
if (input.token.value().empty()) {
|
||||
return Error::validationError("token is required");
|
||||
}
|
||||
auto token_it = store.session_tokens.find(input.token.value());
|
||||
if (token_it != store.session_tokens.end() && token_it->second != id) {
|
||||
return Error::conflict("Session token already exists: " + input.token.value());
|
||||
}
|
||||
store.session_tokens.erase(session.token);
|
||||
store.session_tokens[input.token.value()] = id;
|
||||
session.token = input.token.value();
|
||||
}
|
||||
|
||||
if (input.expires_at.has_value()) {
|
||||
session.expires_at = input.expires_at.value();
|
||||
}
|
||||
|
||||
if (input.last_activity.has_value()) {
|
||||
session.last_activity = input.last_activity.value();
|
||||
}
|
||||
|
||||
return Result<Session>(session);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a session by ID
|
||||
*/
|
||||
inline Result<bool> deleteSession(InMemoryStore& store, const std::string& id) {
|
||||
if (id.empty()) {
|
||||
return Error::validationError("Session ID cannot be empty");
|
||||
}
|
||||
|
||||
auto it = store.sessions.find(id);
|
||||
if (it == store.sessions.end()) {
|
||||
return Error::notFound("Session not found: " + id);
|
||||
}
|
||||
|
||||
store.session_tokens.erase(it->second.token);
|
||||
store.sessions.erase(it);
|
||||
|
||||
return Result<bool>(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean expired sessions from store
|
||||
*/
|
||||
inline void cleanExpiredSessions(InMemoryStore& store) {
|
||||
auto now = std::chrono::system_clock::now();
|
||||
std::vector<std::string> expired_sessions;
|
||||
|
||||
for (const auto& [id, session] : store.sessions) {
|
||||
if (session.expires_at <= now) {
|
||||
expired_sessions.push_back(id);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& id : expired_sessions) {
|
||||
auto expired_it = store.sessions.find(id);
|
||||
if (expired_it != store.sessions.end()) {
|
||||
store.session_tokens.erase(expired_it->second.token);
|
||||
store.sessions.erase(expired_it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List sessions with filtering and pagination
|
||||
*/
|
||||
inline Result<std::vector<Session>> listSessions(InMemoryStore& store, const ListOptions& options) {
|
||||
// Clean expired sessions first
|
||||
cleanExpiredSessions(store);
|
||||
|
||||
std::vector<Session> sessions;
|
||||
|
||||
for (const auto& [id, session] : store.sessions) {
|
||||
bool matches = true;
|
||||
|
||||
if (options.filter.find("user_id") != options.filter.end()) {
|
||||
if (session.user_id != options.filter.at("user_id")) matches = false;
|
||||
}
|
||||
|
||||
if (options.filter.find("token") != options.filter.end()) {
|
||||
if (session.token != options.filter.at("token")) matches = false;
|
||||
}
|
||||
|
||||
if (matches) {
|
||||
sessions.push_back(session);
|
||||
}
|
||||
}
|
||||
|
||||
if (options.sort.find("created_at") != options.sort.end()) {
|
||||
std::sort(sessions.begin(), sessions.end(), [](const Session& a, const Session& b) {
|
||||
return a.created_at < b.created_at;
|
||||
});
|
||||
} else if (options.sort.find("expires_at") != options.sort.end()) {
|
||||
std::sort(sessions.begin(), sessions.end(), [](const Session& a, const Session& b) {
|
||||
return a.expires_at < b.expires_at;
|
||||
});
|
||||
}
|
||||
|
||||
int start = (options.page - 1) * options.limit;
|
||||
int end = std::min(start + options.limit, static_cast<int>(sessions.size()));
|
||||
|
||||
if (start < static_cast<int>(sessions.size())) {
|
||||
return Result<std::vector<Session>>(std::vector<Session>(sessions.begin() + start, sessions.begin() + end));
|
||||
}
|
||||
|
||||
return Result<std::vector<Session>>(std::vector<Session>());
|
||||
}
|
||||
|
||||
} // namespace entities
|
||||
} // namespace dbal
|
||||
|
||||
#endif
|
||||
@@ -1,203 +0,0 @@
|
||||
/**
|
||||
* @file workflow_operations.hpp
|
||||
* @brief Workflow entity CRUD operations
|
||||
*
|
||||
* Single-responsibility module for Workflow entity operations.
|
||||
*/
|
||||
#ifndef DBAL_WORKFLOW_OPERATIONS_HPP
|
||||
#define DBAL_WORKFLOW_OPERATIONS_HPP
|
||||
|
||||
#include "dbal/types.hpp"
|
||||
#include "dbal/errors.hpp"
|
||||
#include "../store/in_memory_store.hpp"
|
||||
#include "../validation/workflow_validation.hpp"
|
||||
|
||||
namespace dbal {
|
||||
namespace entities {
|
||||
|
||||
/**
|
||||
* Create a new workflow in the store
|
||||
*/
|
||||
inline Result<Workflow> createWorkflow(InMemoryStore& store, const CreateWorkflowInput& input) {
|
||||
if (!validation::isValidWorkflowName(input.name)) {
|
||||
return Error::validationError("Workflow name must be 1-255 characters");
|
||||
}
|
||||
if (!validation::isValidWorkflowTrigger(input.trigger)) {
|
||||
return Error::validationError("Trigger must be one of manual, schedule, event, webhook");
|
||||
}
|
||||
if (input.created_by.empty()) {
|
||||
return Error::validationError("created_by is required");
|
||||
}
|
||||
|
||||
if (store.workflow_names.find(input.name) != store.workflow_names.end()) {
|
||||
return Error::conflict("Workflow name already exists: " + input.name);
|
||||
}
|
||||
|
||||
Workflow workflow;
|
||||
workflow.id = store.generateId("workflow", ++store.workflow_counter);
|
||||
workflow.name = input.name;
|
||||
workflow.description = input.description;
|
||||
workflow.trigger = input.trigger;
|
||||
workflow.trigger_config = input.trigger_config;
|
||||
workflow.steps = input.steps;
|
||||
workflow.is_active = input.is_active;
|
||||
workflow.created_by = input.created_by;
|
||||
workflow.created_at = std::chrono::system_clock::now();
|
||||
workflow.updated_at = workflow.created_at;
|
||||
|
||||
store.workflows[workflow.id] = workflow;
|
||||
store.workflow_names[workflow.name] = workflow.id;
|
||||
|
||||
return Result<Workflow>(workflow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a workflow by ID
|
||||
*/
|
||||
inline Result<Workflow> getWorkflow(InMemoryStore& store, const std::string& id) {
|
||||
if (id.empty()) {
|
||||
return Error::validationError("Workflow ID cannot be empty");
|
||||
}
|
||||
|
||||
auto it = store.workflows.find(id);
|
||||
if (it == store.workflows.end()) {
|
||||
return Error::notFound("Workflow not found: " + id);
|
||||
}
|
||||
|
||||
return Result<Workflow>(it->second);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an existing workflow
|
||||
*/
|
||||
inline Result<Workflow> updateWorkflow(InMemoryStore& store, const std::string& id, const UpdateWorkflowInput& input) {
|
||||
if (id.empty()) {
|
||||
return Error::validationError("Workflow ID cannot be empty");
|
||||
}
|
||||
|
||||
auto it = store.workflows.find(id);
|
||||
if (it == store.workflows.end()) {
|
||||
return Error::notFound("Workflow not found: " + id);
|
||||
}
|
||||
|
||||
Workflow& workflow = it->second;
|
||||
std::string old_name = workflow.name;
|
||||
|
||||
if (input.name.has_value()) {
|
||||
if (!validation::isValidWorkflowName(input.name.value())) {
|
||||
return Error::validationError("Workflow name must be 1-255 characters");
|
||||
}
|
||||
auto name_it = store.workflow_names.find(input.name.value());
|
||||
if (name_it != store.workflow_names.end() && name_it->second != id) {
|
||||
return Error::conflict("Workflow name already exists: " + input.name.value());
|
||||
}
|
||||
store.workflow_names.erase(old_name);
|
||||
store.workflow_names[input.name.value()] = id;
|
||||
workflow.name = input.name.value();
|
||||
}
|
||||
|
||||
if (input.description.has_value()) {
|
||||
workflow.description = input.description.value();
|
||||
}
|
||||
|
||||
if (input.trigger.has_value()) {
|
||||
if (!validation::isValidWorkflowTrigger(input.trigger.value())) {
|
||||
return Error::validationError("Trigger must be one of manual, schedule, event, webhook");
|
||||
}
|
||||
workflow.trigger = input.trigger.value();
|
||||
}
|
||||
|
||||
if (input.trigger_config.has_value()) {
|
||||
workflow.trigger_config = input.trigger_config.value();
|
||||
}
|
||||
|
||||
if (input.steps.has_value()) {
|
||||
workflow.steps = input.steps.value();
|
||||
}
|
||||
|
||||
if (input.is_active.has_value()) {
|
||||
workflow.is_active = input.is_active.value();
|
||||
}
|
||||
|
||||
if (input.created_by.has_value()) {
|
||||
if (input.created_by.value().empty()) {
|
||||
return Error::validationError("created_by is required");
|
||||
}
|
||||
workflow.created_by = input.created_by.value();
|
||||
}
|
||||
|
||||
workflow.updated_at = std::chrono::system_clock::now();
|
||||
|
||||
return Result<Workflow>(workflow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a workflow by ID
|
||||
*/
|
||||
inline Result<bool> deleteWorkflow(InMemoryStore& store, const std::string& id) {
|
||||
if (id.empty()) {
|
||||
return Error::validationError("Workflow ID cannot be empty");
|
||||
}
|
||||
|
||||
auto it = store.workflows.find(id);
|
||||
if (it == store.workflows.end()) {
|
||||
return Error::notFound("Workflow not found: " + id);
|
||||
}
|
||||
|
||||
store.workflow_names.erase(it->second.name);
|
||||
store.workflows.erase(it);
|
||||
|
||||
return Result<bool>(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* List workflows with filtering and pagination
|
||||
*/
|
||||
inline Result<std::vector<Workflow>> listWorkflows(InMemoryStore& store, const ListOptions& options) {
|
||||
std::vector<Workflow> workflows;
|
||||
|
||||
for (const auto& [id, workflow] : store.workflows) {
|
||||
bool matches = true;
|
||||
|
||||
if (options.filter.find("is_active") != options.filter.end()) {
|
||||
bool filter_active = options.filter.at("is_active") == "true";
|
||||
if (workflow.is_active != filter_active) matches = false;
|
||||
}
|
||||
|
||||
if (options.filter.find("trigger") != options.filter.end()) {
|
||||
if (workflow.trigger != options.filter.at("trigger")) matches = false;
|
||||
}
|
||||
|
||||
if (options.filter.find("created_by") != options.filter.end()) {
|
||||
if (workflow.created_by != options.filter.at("created_by")) matches = false;
|
||||
}
|
||||
|
||||
if (matches) {
|
||||
workflows.push_back(workflow);
|
||||
}
|
||||
}
|
||||
|
||||
if (options.sort.find("name") != options.sort.end()) {
|
||||
std::sort(workflows.begin(), workflows.end(), [](const Workflow& a, const Workflow& b) {
|
||||
return a.name < b.name;
|
||||
});
|
||||
} else if (options.sort.find("created_at") != options.sort.end()) {
|
||||
std::sort(workflows.begin(), workflows.end(), [](const Workflow& a, const Workflow& b) {
|
||||
return a.created_at < b.created_at;
|
||||
});
|
||||
}
|
||||
|
||||
int start = (options.page - 1) * options.limit;
|
||||
int end = std::min(start + options.limit, static_cast<int>(workflows.size()));
|
||||
|
||||
if (start < static_cast<int>(workflows.size())) {
|
||||
return Result<std::vector<Workflow>>(std::vector<Workflow>(workflows.begin() + start, workflows.begin() + end));
|
||||
}
|
||||
|
||||
return Result<std::vector<Workflow>>(std::vector<Workflow>());
|
||||
}
|
||||
|
||||
} // namespace entities
|
||||
} // namespace dbal
|
||||
|
||||
#endif
|
||||
@@ -21,4 +21,4 @@ export { createPackageOperations } from './package-operations';
|
||||
export { createSessionOperations } from './session-operations';
|
||||
|
||||
// Validation utilities
|
||||
export * from './validation';
|
||||
export * from '../validation';
|
||||
|
||||
@@ -2,39 +2,48 @@
|
||||
* @file list-packages.ts
|
||||
* @description List packages with filtering and pagination
|
||||
*/
|
||||
import type { Package, ListOptions, Result } from '../types';
|
||||
import type { InMemoryStore } from '../store/in-memory-store';
|
||||
import type { ListOptions, Package, Result } from '../../types'
|
||||
import type { InMemoryStore } from '../../store/in-memory-store'
|
||||
|
||||
/**
|
||||
* List packages with filtering and pagination
|
||||
*/
|
||||
export async function listPackages(
|
||||
export const listPackages = async (
|
||||
store: InMemoryStore,
|
||||
options: ListOptions = {}
|
||||
): Promise<Result<Package[]>> {
|
||||
const { filter = {}, sort = {}, page = 1, limit = 20 } = options;
|
||||
): Promise<Result<Package[]>> => {
|
||||
const { filter = {}, sort = {}, page = 1, limit = 20 } = options
|
||||
|
||||
let packages = Array.from(store.packages.values());
|
||||
let packages = Array.from(store.packages.values())
|
||||
|
||||
// Apply filters
|
||||
if (filter.isActive !== undefined) {
|
||||
packages = packages.filter((p) => p.isActive === filter.isActive);
|
||||
if (filter.name !== undefined) {
|
||||
packages = packages.filter((pkg) => pkg.name === filter.name)
|
||||
}
|
||||
|
||||
if (filter.version !== undefined) {
|
||||
packages = packages.filter((pkg) => pkg.version === filter.version)
|
||||
}
|
||||
|
||||
if (filter.author !== undefined) {
|
||||
packages = packages.filter((pkg) => pkg.author === filter.author)
|
||||
}
|
||||
|
||||
if (filter.isInstalled !== undefined) {
|
||||
packages = packages.filter((pkg) => pkg.isInstalled === filter.isInstalled)
|
||||
}
|
||||
|
||||
// Apply sorting
|
||||
if (sort.name) {
|
||||
packages.sort((a, b) => (sort.name === 'asc' ? a.name.localeCompare(b.name) : b.name.localeCompare(a.name)));
|
||||
packages.sort((a, b) =>
|
||||
sort.name === 'asc' ? a.name.localeCompare(b.name) : b.name.localeCompare(a.name)
|
||||
)
|
||||
} else if (sort.createdAt) {
|
||||
packages.sort((a, b) =>
|
||||
sort.createdAt === 'asc'
|
||||
? a.createdAt.getTime() - b.createdAt.getTime()
|
||||
: b.createdAt.getTime() - a.createdAt.getTime()
|
||||
);
|
||||
sort.createdAt === 'asc' ? a.createdAt.getTime() - b.createdAt.getTime() : b.createdAt.getTime() - a.createdAt.getTime()
|
||||
)
|
||||
}
|
||||
|
||||
// Apply pagination
|
||||
const start = (page - 1) * limit;
|
||||
const paginated = packages.slice(start, start + limit);
|
||||
const start = (page - 1) * limit
|
||||
const paginated = packages.slice(start, start + limit)
|
||||
|
||||
return { success: true, data: paginated };
|
||||
return { success: true, data: paginated }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user