From de2dfd834079cfbb2635a74d950126c543bbdcd6 Mon Sep 17 00:00:00 2001 From: JohnDoe6345789 Date: Fri, 26 Dec 2025 01:36:45 +0000 Subject: [PATCH] code: dbal,operations,hpp (4 files) --- dbal/cpp/src/entities/package_operations.hpp | 288 ------------------ dbal/cpp/src/entities/page_operations.hpp | 221 -------------- dbal/cpp/src/entities/user_operations.hpp | 245 --------------- .../core/entities/package/delete-package.ts | 22 +- 4 files changed, 12 insertions(+), 764 deletions(-) delete mode 100644 dbal/cpp/src/entities/package_operations.hpp delete mode 100644 dbal/cpp/src/entities/page_operations.hpp delete mode 100644 dbal/cpp/src/entities/user_operations.hpp diff --git a/dbal/cpp/src/entities/package_operations.hpp b/dbal/cpp/src/entities/package_operations.hpp deleted file mode 100644 index 270f5db19..000000000 --- a/dbal/cpp/src/entities/package_operations.hpp +++ /dev/null @@ -1,288 +0,0 @@ -/** - * @file package_operations.hpp - * @brief Package entity CRUD operations - * - * Single-responsibility module for Package entity operations. - */ -#ifndef DBAL_PACKAGE_OPERATIONS_HPP -#define DBAL_PACKAGE_OPERATIONS_HPP - -#include "dbal/types.hpp" -#include "dbal/errors.hpp" -#include "../store/in_memory_store.hpp" -#include "../validation/package_validation.hpp" - -namespace dbal { -namespace entities { - -/** - * Create a new package in the store - */ -inline Result createPackage(InMemoryStore& store, const CreatePackageInput& input) { - if (!validation::isValidPackageName(input.name)) { - return Error::validationError("Package name must be 1-255 characters"); - } - if (!validation::isValidSemver(input.version)) { - return Error::validationError("Version must be valid semver"); - } - if (input.author.empty()) { - return Error::validationError("author is required"); - } - - std::string key = validation::packageKey(input.name, input.version); - if (store.package_keys.find(key) != store.package_keys.end()) { - return Error::conflict("Package name+version already exists: " + key); - } - - Package package; - package.id = store.generateId("package", ++store.package_counter); - package.name = input.name; - package.version = input.version; - package.description = input.description; - package.author = input.author; - package.manifest = input.manifest; - package.is_installed = input.is_installed; - package.installed_at = input.installed_at; - package.installed_by = input.installed_by; - package.created_at = std::chrono::system_clock::now(); - package.updated_at = package.created_at; - - store.packages[package.id] = package; - store.package_keys[key] = package.id; - - return Result(package); -} - -/** - * Get a package by ID - */ -inline Result getPackage(InMemoryStore& store, const std::string& id) { - if (id.empty()) { - return Error::validationError("Package ID cannot be empty"); - } - - auto it = store.packages.find(id); - if (it == store.packages.end()) { - return Error::notFound("Package not found: " + id); - } - - return Result(it->second); -} - -/** - * Update an existing package - */ -inline Result updatePackage(InMemoryStore& store, const std::string& id, const UpdatePackageInput& input) { - if (id.empty()) { - return Error::validationError("Package ID cannot be empty"); - } - - auto it = store.packages.find(id); - if (it == store.packages.end()) { - return Error::notFound("Package not found: " + id); - } - - Package& package = it->second; - - std::string next_name = input.name.value_or(package.name); - std::string next_version = input.version.value_or(package.version); - - if (!validation::isValidPackageName(next_name)) { - return Error::validationError("Package name must be 1-255 characters"); - } - if (!validation::isValidSemver(next_version)) { - return Error::validationError("Version must be valid semver"); - } - - std::string current_key = validation::packageKey(package.name, package.version); - std::string next_key = validation::packageKey(next_name, next_version); - - if (next_key != current_key) { - auto key_it = store.package_keys.find(next_key); - if (key_it != store.package_keys.end() && key_it->second != id) { - return Error::conflict("Package name+version already exists: " + next_key); - } - store.package_keys.erase(current_key); - store.package_keys[next_key] = id; - } - - package.name = next_name; - package.version = next_version; - - if (input.description.has_value()) { - package.description = input.description.value(); - } - - if (input.author.has_value()) { - if (input.author.value().empty()) { - return Error::validationError("author is required"); - } - package.author = input.author.value(); - } - - if (input.manifest.has_value()) { - package.manifest = input.manifest.value(); - } - - if (input.is_installed.has_value()) { - package.is_installed = input.is_installed.value(); - } - - if (input.installed_at.has_value()) { - package.installed_at = input.installed_at.value(); - } - - if (input.installed_by.has_value()) { - if (input.installed_by.value().empty()) { - return Error::validationError("installed_by is required"); - } - package.installed_by = input.installed_by.value(); - } - - package.updated_at = std::chrono::system_clock::now(); - - return Result(package); -} - -/** - * Delete a package by ID - */ -inline Result deletePackage(InMemoryStore& store, const std::string& id) { - if (id.empty()) { - return Error::validationError("Package ID cannot be empty"); - } - - auto it = store.packages.find(id); - if (it == store.packages.end()) { - return Error::notFound("Package not found: " + id); - } - - store.package_keys.erase(validation::packageKey(it->second.name, it->second.version)); - store.packages.erase(it); - - return Result(true); -} - -/** - * List packages with filtering and pagination - */ -inline Result> listPackages(InMemoryStore& store, const ListOptions& options) { - std::vector packages; - - for (const auto& [id, package] : store.packages) { - bool matches = true; - - if (options.filter.find("name") != options.filter.end()) { - if (package.name != options.filter.at("name")) matches = false; - } - - if (options.filter.find("version") != options.filter.end()) { - if (package.version != options.filter.at("version")) matches = false; - } - - if (options.filter.find("author") != options.filter.end()) { - if (package.author != options.filter.at("author")) matches = false; - } - - if (options.filter.find("is_installed") != options.filter.end()) { - bool filter_installed = options.filter.at("is_installed") == "true"; - if (package.is_installed != filter_installed) matches = false; - } - - if (matches) { - packages.push_back(package); - } - } - - if (options.sort.find("name") != options.sort.end()) { - std::sort(packages.begin(), packages.end(), [](const Package& a, const Package& b) { - return a.name < b.name; - }); - } else if (options.sort.find("created_at") != options.sort.end()) { - std::sort(packages.begin(), packages.end(), [](const Package& a, const Package& b) { - return a.created_at < b.created_at; - }); - } - - int start = (options.page - 1) * options.limit; - int end = std::min(start + options.limit, static_cast(packages.size())); - - if (start < static_cast(packages.size())) { - return Result>(std::vector(packages.begin() + start, packages.begin() + end)); - } - - return Result>(std::vector()); -} - -/** - * Batch create multiple packages - */ -inline Result batchCreatePackages(InMemoryStore& store, const std::vector& inputs) { - if (inputs.empty()) { - return Result(0); - } - - std::vector created_ids; - for (const auto& input : inputs) { - auto result = createPackage(store, input); - if (result.isError()) { - // Rollback on error - for (const auto& id : created_ids) { - auto it = store.packages.find(id); - if (it != store.packages.end()) { - store.package_keys.erase(validation::packageKey(it->second.name, it->second.version)); - store.packages.erase(it); - } - } - return result.error(); - } - created_ids.push_back(result.value().id); - } - - return Result(static_cast(created_ids.size())); -} - -/** - * Batch update multiple packages - */ -inline Result batchUpdatePackages(InMemoryStore& store, const std::vector& updates) { - if (updates.empty()) { - return Result(0); - } - - int updated = 0; - for (const auto& item : updates) { - auto result = updatePackage(store, item.id, item.data); - if (result.isError()) { - return result.error(); - } - updated++; - } - - return Result(updated); -} - -/** - * Batch delete multiple packages - */ -inline Result batchDeletePackages(InMemoryStore& store, const std::vector& ids) { - if (ids.empty()) { - return Result(0); - } - - int deleted = 0; - for (const auto& id : ids) { - auto result = deletePackage(store, id); - if (result.isError()) { - return result.error(); - } - deleted++; - } - - return Result(deleted); -} - -} // namespace entities -} // namespace dbal - -#endif diff --git a/dbal/cpp/src/entities/page_operations.hpp b/dbal/cpp/src/entities/page_operations.hpp deleted file mode 100644 index 3a73df6a2..000000000 --- a/dbal/cpp/src/entities/page_operations.hpp +++ /dev/null @@ -1,221 +0,0 @@ -/** - * @file page_operations.hpp - * @brief PageView entity CRUD operations - * - * Single-responsibility module for PageView entity operations. - */ -#ifndef DBAL_PAGE_OPERATIONS_HPP -#define DBAL_PAGE_OPERATIONS_HPP - -#include "dbal/types.hpp" -#include "dbal/errors.hpp" -#include "../store/in_memory_store.hpp" -#include "../validation/page_validation.hpp" - -namespace dbal { -namespace entities { - -/** - * Create a new page in the store - */ -inline Result createPage(InMemoryStore& store, const CreatePageInput& input) { - // Validation - if (!validation::isValidSlug(input.slug)) { - return Error::validationError("Invalid slug format (lowercase, alphanumeric, hyphens only)"); - } - if (input.title.empty() || input.title.length() > 200) { - return Error::validationError("Title must be between 1 and 200 characters"); - } - if (input.level < 0 || input.level > 5) { - return Error::validationError("Level must be between 0 and 5"); - } - - // Check for duplicate slug - if (store.page_slugs.find(input.slug) != store.page_slugs.end()) { - return Error::conflict("Page with slug already exists: " + input.slug); - } - - // Create page - PageView page; - page.id = store.generateId("page", ++store.page_counter); - page.slug = input.slug; - page.title = input.title; - page.description = input.description; - page.level = input.level; - page.layout = input.layout; - page.is_active = input.is_active; - page.created_at = std::chrono::system_clock::now(); - page.updated_at = page.created_at; - - store.pages[page.id] = page; - store.page_slugs[page.slug] = page.id; - - return Result(page); -} - -/** - * Get a page by ID - */ -inline Result getPage(InMemoryStore& store, const std::string& id) { - if (id.empty()) { - return Error::validationError("Page ID cannot be empty"); - } - - auto it = store.pages.find(id); - if (it == store.pages.end()) { - return Error::notFound("Page not found: " + id); - } - - return Result(it->second); -} - -/** - * Get a page by slug - */ -inline Result getPageBySlug(InMemoryStore& store, const std::string& slug) { - if (slug.empty()) { - return Error::validationError("Slug cannot be empty"); - } - - auto it = store.page_slugs.find(slug); - if (it == store.page_slugs.end()) { - return Error::notFound("Page not found with slug: " + slug); - } - - return getPage(store, it->second); -} - -/** - * Update an existing page - */ -inline Result updatePage(InMemoryStore& store, const std::string& id, const UpdatePageInput& input) { - if (id.empty()) { - return Error::validationError("Page ID cannot be empty"); - } - - auto it = store.pages.find(id); - if (it == store.pages.end()) { - return Error::notFound("Page not found: " + id); - } - - PageView& page = it->second; - std::string old_slug = page.slug; - - // Validate and update fields - if (input.slug.has_value()) { - if (!validation::isValidSlug(input.slug.value())) { - return Error::validationError("Invalid slug format"); - } - // Check for slug conflict - auto slug_it = store.page_slugs.find(input.slug.value()); - if (slug_it != store.page_slugs.end() && slug_it->second != id) { - return Error::conflict("Slug already exists: " + input.slug.value()); - } - // Update slug mapping - store.page_slugs.erase(old_slug); - store.page_slugs[input.slug.value()] = id; - page.slug = input.slug.value(); - } - - if (input.title.has_value()) { - if (input.title.value().empty() || input.title.value().length() > 200) { - return Error::validationError("Title must be between 1 and 200 characters"); - } - page.title = input.title.value(); - } - - if (input.description.has_value()) { - page.description = input.description.value(); - } - - if (input.level.has_value()) { - if (input.level.value() < 0 || input.level.value() > 5) { - return Error::validationError("Level must be between 0 and 5"); - } - page.level = input.level.value(); - } - - if (input.layout.has_value()) { - page.layout = input.layout.value(); - } - - if (input.is_active.has_value()) { - page.is_active = input.is_active.value(); - } - - page.updated_at = std::chrono::system_clock::now(); - - return Result(page); -} - -/** - * Delete a page by ID - */ -inline Result deletePage(InMemoryStore& store, const std::string& id) { - if (id.empty()) { - return Error::validationError("Page ID cannot be empty"); - } - - auto it = store.pages.find(id); - if (it == store.pages.end()) { - return Error::notFound("Page not found: " + id); - } - - // Remove slug mapping - store.page_slugs.erase(it->second.slug); - store.pages.erase(it); - - return Result(true); -} - -/** - * List pages with filtering and pagination - */ -inline Result> listPages(InMemoryStore& store, const ListOptions& options) { - std::vector pages; - - for (const auto& [id, page] : store.pages) { - // Apply filters - bool matches = true; - - if (options.filter.find("is_active") != options.filter.end()) { - bool filter_active = options.filter.at("is_active") == "true"; - if (page.is_active != filter_active) matches = false; - } - - if (options.filter.find("level") != options.filter.end()) { - int filter_level = std::stoi(options.filter.at("level")); - if (page.level != filter_level) matches = false; - } - - if (matches) { - pages.push_back(page); - } - } - - // Apply sorting - if (options.sort.find("title") != options.sort.end()) { - std::sort(pages.begin(), pages.end(), [](const PageView& a, const PageView& b) { - return a.title < b.title; - }); - } else if (options.sort.find("created_at") != options.sort.end()) { - std::sort(pages.begin(), pages.end(), [](const PageView& a, const PageView& b) { - return a.created_at < b.created_at; - }); - } - - // Apply pagination - int start = (options.page - 1) * options.limit; - int end = std::min(start + options.limit, static_cast(pages.size())); - - if (start < static_cast(pages.size())) { - return Result>(std::vector(pages.begin() + start, pages.begin() + end)); - } - - return Result>(std::vector()); -} - -} // namespace entities -} // namespace dbal - -#endif diff --git a/dbal/cpp/src/entities/user_operations.hpp b/dbal/cpp/src/entities/user_operations.hpp deleted file mode 100644 index 170fb2335..000000000 --- a/dbal/cpp/src/entities/user_operations.hpp +++ /dev/null @@ -1,245 +0,0 @@ -/** - * @file user_operations.hpp - * @brief User entity CRUD operations - * - * Single-responsibility module for User entity operations. - * Follows the small-function-file pattern from the Next.js frontend. - */ -#ifndef DBAL_USER_OPERATIONS_HPP -#define DBAL_USER_OPERATIONS_HPP - -#include "dbal/types.hpp" -#include "dbal/errors.hpp" -#include "../store/in_memory_store.hpp" -#include "../validation/user_validation.hpp" - -namespace dbal { -namespace entities { - -/** - * Create a new user in the store - */ -inline Result createUser(InMemoryStore& store, const CreateUserInput& input) { - // Validation - if (!validation::isValidUsername(input.username)) { - return Error::validationError("Invalid username format (alphanumeric, underscore, hyphen only)"); - } - if (!validation::isValidEmail(input.email)) { - return Error::validationError("Invalid email format"); - } - - // Check for duplicate username - for (const auto& [id, user] : store.users) { - if (user.username == input.username) { - return Error::conflict("Username already exists: " + input.username); - } - if (user.email == input.email) { - return Error::conflict("Email already exists: " + input.email); - } - } - - // Create user - User user; - user.id = store.generateId("user", ++store.user_counter); - user.username = input.username; - user.email = input.email; - user.role = input.role; - user.created_at = std::chrono::system_clock::now(); - user.updated_at = user.created_at; - - store.users[user.id] = user; - - return Result(user); -} - -/** - * Get a user by ID - */ -inline Result getUser(InMemoryStore& store, const std::string& id) { - if (id.empty()) { - return Error::validationError("User ID cannot be empty"); - } - - auto it = store.users.find(id); - if (it == store.users.end()) { - return Error::notFound("User not found: " + id); - } - - return Result(it->second); -} - -/** - * Update an existing user - */ -inline Result updateUser(InMemoryStore& store, const std::string& id, const UpdateUserInput& input) { - if (id.empty()) { - return Error::validationError("User ID cannot be empty"); - } - - auto it = store.users.find(id); - if (it == store.users.end()) { - return Error::notFound("User not found: " + id); - } - - User& user = it->second; - - // Validate and check conflicts - if (input.username.has_value()) { - if (!validation::isValidUsername(input.username.value())) { - return Error::validationError("Invalid username format"); - } - // Check for username conflict - for (const auto& [uid, u] : store.users) { - if (uid != id && u.username == input.username.value()) { - return Error::conflict("Username already exists: " + input.username.value()); - } - } - user.username = input.username.value(); - } - - if (input.email.has_value()) { - if (!validation::isValidEmail(input.email.value())) { - return Error::validationError("Invalid email format"); - } - // Check for email conflict - for (const auto& [uid, u] : store.users) { - if (uid != id && u.email == input.email.value()) { - return Error::conflict("Email already exists: " + input.email.value()); - } - } - user.email = input.email.value(); - } - - if (input.role.has_value()) { - user.role = input.role.value(); - } - - user.updated_at = std::chrono::system_clock::now(); - - return Result(user); -} - -/** - * Delete a user by ID - */ -inline Result deleteUser(InMemoryStore& store, const std::string& id) { - if (id.empty()) { - return Error::validationError("User ID cannot be empty"); - } - - auto it = store.users.find(id); - if (it == store.users.end()) { - return Error::notFound("User not found: " + id); - } - - store.users.erase(it); - return Result(true); -} - -/** - * List users with filtering and pagination - */ -inline Result> listUsers(InMemoryStore& store, const ListOptions& options) { - std::vector users; - - for (const auto& [id, user] : store.users) { - // Apply filters if provided - bool matches = true; - - if (options.filter.find("role") != options.filter.end()) { - std::string role_str = options.filter.at("role"); - if (role_str == "admin" && user.role != UserRole::Admin) matches = false; - if (role_str == "user" && user.role != UserRole::User) matches = false; - } - - if (matches) { - users.push_back(user); - } - } - - // Apply sorting - if (options.sort.find("username") != options.sort.end()) { - std::sort(users.begin(), users.end(), [](const User& a, const User& b) { - return a.username < b.username; - }); - } - - // Apply pagination - int start = (options.page - 1) * options.limit; - int end = std::min(start + options.limit, static_cast(users.size())); - - if (start < static_cast(users.size())) { - return Result>(std::vector(users.begin() + start, users.begin() + end)); - } - - return Result>(std::vector()); -} - -/** - * Batch create multiple users - */ -inline Result batchCreateUsers(InMemoryStore& store, const std::vector& inputs) { - if (inputs.empty()) { - return Result(0); - } - - std::vector created_ids; - for (const auto& input : inputs) { - auto result = createUser(store, input); - if (result.isError()) { - // Rollback on error - for (const auto& id : created_ids) { - store.users.erase(id); - } - return result.error(); - } - created_ids.push_back(result.value().id); - } - - return Result(static_cast(created_ids.size())); -} - -/** - * Batch update multiple users - */ -inline Result batchUpdateUsers(InMemoryStore& store, const std::vector& updates) { - if (updates.empty()) { - return Result(0); - } - - int updated = 0; - for (const auto& item : updates) { - auto result = updateUser(store, item.id, item.data); - if (result.isError()) { - return result.error(); - } - updated++; - } - - return Result(updated); -} - -/** - * Batch delete multiple users - */ -inline Result batchDeleteUsers(InMemoryStore& store, const std::vector& ids) { - if (ids.empty()) { - return Result(0); - } - - int deleted = 0; - for (const auto& id : ids) { - auto result = deleteUser(store, id); - if (result.isError()) { - return result.error(); - } - deleted++; - } - - return Result(deleted); -} - -} // namespace entities -} // namespace dbal - -#endif diff --git a/dbal/ts/src/core/entities/package/delete-package.ts b/dbal/ts/src/core/entities/package/delete-package.ts index 678c77298..f15ce3838 100644 --- a/dbal/ts/src/core/entities/package/delete-package.ts +++ b/dbal/ts/src/core/entities/package/delete-package.ts @@ -2,24 +2,26 @@ * @file delete-package.ts * @description Delete package operation */ -import type { Result } from '../types'; -import type { InMemoryStore } from '../store/in-memory-store'; +import type { Result } from '../../types' +import type { InMemoryStore } from '../../store/in-memory-store' +import { validateId } from '../../validation/validate-id' /** * Delete a package by ID */ -export async function deletePackage(store: InMemoryStore, id: string): Promise> { - if (!id) { - return { success: false, error: { code: 'VALIDATION_ERROR', message: 'ID required' } }; +export const deletePackage = async (store: InMemoryStore, id: string): Promise> => { + const idErrors = validateId(id) + if (idErrors.length > 0) { + return { success: false, error: { code: 'VALIDATION_ERROR', message: idErrors[0] } } } - const pkg = store.packages.get(id); + const pkg = store.packages.get(id) if (!pkg) { - return { success: false, error: { code: 'NOT_FOUND', message: `Package not found: ${id}` } }; + return { success: false, error: { code: 'NOT_FOUND', message: `Package not found: ${id}` } } } - store.packageIds.delete(pkg.packageId); - store.packages.delete(id); + store.packages.delete(id) + store.packageKeys.delete(`${pkg.name}@${pkg.version}`) - return { success: true, data: true }; + return { success: true, data: true } }