@plyaz/db 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/typeGuards.ts","../src/service/EventEmitter.ts","../src/utils/databaseResultHelpers.ts","../src/utils/normalizeDetails.ts","../src/service/HealthManager.ts","../src/utils/ConfigMerger.ts","../src/service/DatabaseService.ts","../src/utils/pagination.ts","../src/utils/regex.ts","../src/adapters/drizzle/DrizzleAdapter.ts","../src/adapters/supabase/SupabaseAdapter.ts","../src/adapters/sql/SQLAdapter.ts","../src/adapters/mock/MockAdapter.ts","../src/factory/AdapterFactory.ts","../src/extensions/SoftDeleteExtension.ts","../src/extensions/AuditExtension.ts","../src/extensions/EncryptionExtension.ts","../src/extensions/CachingAdapter.ts","../src/extensions/ReadReplicaAdapter.ts","../src/factory/createDatabaseService.ts","../src/repository/BaseRepository.ts","../src/extensions/MultiWriteExtension.ts","../src/extensions/MultiReadExtension.ts","../src/advanced/read-replica/UseReplica.decorator.ts","../src/advanced/caching/RedisCache.ts","../src/advanced/caching/Cacheable.decorator.ts","../src/advanced/caching/CacheEvict.decorator.ts","../src/advanced/connection-pool/DynamicPool.ts","../src/advanced/monitoring/MetricsCollector.ts","../src/advanced/monitoring/AlertManager.ts","../src/advanced/backup/BackupService.ts","../src/advanced/multi-tenancy/TenantContext.ts","../src/advanced/multi-tenancy/TenantRepository.ts","../src/advanced/sharding/ShardKey.ts","../src/advanced/sharding/ShardRouter.ts","../src/builder/query/sql.ts","../src/builder/query/orm.ts","../src/security/sanitizers/html.sanitizer.ts","../src/security/serializers/DataValidation.ts","../src/migrations/MigrationManager.ts","../src/seeds/SeedManager.ts"],"names":["DatabaseError","DATABASE_ERROR_CODES","logger","DATABASE_EVENT_TYPE","NUMERIX","ADAPTERS","Pool","drizzle","sql","eq","idColumn","result","not","gt","gte","lt","lte","inArray","like","between","isNull","isNotNull","PgColumn","asc","desc","createClient","resolve","EXTENSION_SOURCE","AUDIT_OPERATION","ENCRYPTION_DEFAULTS","randomBytes","createCipheriv","createDecipheriv","ADAPTER_TYPES","DatabasePackageError","ERROR_CODES","success","SetMetadata","config","Redis","dynamicPoolDefaultConfig","DB_POOL_EVENTS","EventEmitter","ALERT_RULE_ID","ALERT_SEVERITY","ALERT_SOURCE","alert","promisify","exec","join","existsSync","unlinkSync","mkdirSync","readdirSync","readFileSync","AsyncLocalStorage","SanitizeHtmlPipe","sanitizeHtml","Injectable","DataValidationPipe","BadRequestException","path","fs","path2","fs2"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * @fileoverview Type Guard Utilities for @plyaz/db package\n *\n * This module provides type guard functions for runtime type checking throughout\n * the @plyaz/db package. These utilities replace direct typeof checks with\n * consistent, reusable type validation functions.\n *\n */\n\n/**\n * Type guard to check if a value is a string\n *\n * @param {unknown} value - The value to check\n * @returns {value is string} True if value is a string, false otherwise\n *\n * @example\n * ```typescript\n * import { isString } from '@plyaz/db/utils';\n *\n * if (isString(userInput)) {\n * // userInput is now typed as string\n * console.log(userInput.toLowerCase());\n * }\n * ```\n */\nexport function isString(value: unknown): value is string {\n return typeof value === \"string\";\n}\n\n/**\n * Type guard to check if a value is a non-empty string\n *\n * @param {unknown} value - The value to check\n * @returns {value is string} True if value is a non-empty string, false otherwise\n *\n * @example\n * ```typescript\n * import { isNonEmptyString } from '@plyaz/db/utils';\n *\n * if (isNonEmptyString(tableName)) {\n * // tableName is guaranteed to be a non-empty string\n * const query = `SELECT * FROM ${tableName}`;\n * }\n * ```\n */\nexport function isNonEmptyString(value: unknown): value is string {\n return isString(value) && value.length > 0;\n}\n\n/**\n * Type guard to check if a value is a number\n *\n * @param {unknown} value - The value to check\n * @returns {value is number} True if value is a number, false otherwise\n */\nexport function isNumber(value: unknown): value is number {\n return typeof value === \"number\";\n}\n\n/**\n * Type guard to check if a value is an object (not null, not array)\n *\n * @param {unknown} value - The value to check\n * @returns {value is object} True if value is an object, false otherwise\n */\nexport function isObject(value: unknown): value is object {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n","/**\n * @fileoverview DatabaseEventEmitter - Event management for database operations\n *\n * Provides a comprehensive event system for monitoring and reacting to database\n * operations. The DatabaseEventEmitter implements the Observer pattern to enable\n * decoupled monitoring of database activities, allowing multiple components to\n * subscribe to and react to various database events.\n *\n * **Application Flow Context:**\n * ```\n * Database Operations → DatabaseEventEmitter → Event Handlers\n * ↓ ↓ ↓\n * Query Execution → Event Emission → Logging\n * Transaction → Handler Dispatch → Monitoring\n * Health Changes → Error Handling → Alerting\n * ```\n *\n * **Supported Events:**\n * - **BeforeQuery**: Emitted before database queries\n * - **AfterQuery**: Emitted after successful queries\n * - **QueryError**: Emitted when queries fail\n * - **BeforeTransaction**: Emitted before transactions start\n * - **AfterTransaction**: Emitted after transactions complete\n * - **TransactionRollback**: Emitted when transactions rollback\n * - **HealthChange**: Emitted when database health status changes\n *\n * @example\n * ```typescript\n * // Event emitter setup\n * const eventEmitter = new DatabaseEventEmitter('drizzle');\n *\n * // Subscribe to query events\n * eventEmitter.on('BeforeQuery', (event) => {\n * console.log(`Executing ${event.operation} on ${event.table}`);\n * });\n *\n * eventEmitter.on('QueryError', (event) => {\n * console.error(`Query failed: ${event.error.message}`);\n * });\n *\n * // Emit events during database operations\n * eventEmitter.emitBeforeQuery('users', 'SELECT', { id: '123' });\n * ```\n *\n */\n\nimport type {\n AfterQueryEvent,\n AfterTransactionEvent,\n BeforeQueryEvent,\n BeforeTransactionEvent,\n DatabaseEvent,\n DatabaseOperationType,\n DBEventHandler,\n HealthChangeEvent,\n QueryErrorEvent,\n TransactionRollbackEvent,\n} from \"@plyaz/types\";\nimport type {\n EmitQueryErrorOptions,\n DatabaseExecutionContext,\n} from \"@plyaz/types/db\";\nimport { DATABASE_EVENT_TYPE } from \"@plyaz/types\";\nimport type { ADAPTERS } from \"@plyaz/types\";\nimport { logger } from \"@plyaz/logger\";\nimport { isString, isObject } from \"@utils/typeGuards\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\n\n/**\n * Event emitter for database events that implements the observer pattern.\n * This class manages event subscriptions and emissions for various database operations,\n * allowing decoupled monitoring of database activities.\n *\n * @class\n * @implements {DatabaseEventEmitter}\n */\nexport class DatabaseEventEmitter implements DatabaseEventEmitter {\n private readonly eventHandlers: Map<string, DBEventHandler<DatabaseEvent>[]> =\n new Map();\n\n constructor(private readonly adapter: ADAPTERS) {\n if (!adapter) {\n throw new DatabaseError(\n \"Database adapter is required for event emitter\",\n DATABASE_ERROR_CODES.CONFIG_REQUIRED,\n {\n context: { source: \"DatabaseEventEmitter.constructor\" },\n cause: new Error(\"Database adapter is required for event emitter\"),\n },\n );\n }\n }\n\n /**\n * Register an event handler for a specific event type\n */\n on<T extends DatabaseEvent>(\n eventType: T[\"type\"],\n handler: DBEventHandler<T>,\n ): void {\n try {\n if (!isString(eventType)) {\n throw new DatabaseError(\n \"Invalid event type\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"on\" },\n cause: new Error(\"Invalid event type\"),\n },\n );\n }\n\n if (!handler || typeof handler !== \"function\") {\n throw new DatabaseError(\n \"Invalid event handler\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"on\" },\n cause: new Error(\"Invalid event handler\"),\n },\n );\n }\n\n if (!this.eventHandlers.has(eventType)) {\n this.eventHandlers.set(eventType, []);\n }\n\n const handlers = this.eventHandlers.get(eventType);\n if (handlers) {\n handlers.push(handler as DBEventHandler<DatabaseEvent>);\n }\n } catch (error) {\n logger.error(\n `Failed to register event handler: ${(error as Error).message}`,\n );\n }\n }\n\n /**\n * Remove an event handler for a specific event type\n */\n off<T extends DatabaseEvent>(\n eventType: T[\"type\"],\n handler: DBEventHandler<T>,\n ): void {\n const handlers = this.eventHandlers.get(eventType);\n if (handlers) {\n const index = handlers.indexOf(handler as DBEventHandler<DatabaseEvent>);\n if (index !== -1) handlers.splice(index, 1);\n }\n }\n\n /**\n * Emit an event to all registered handlers\n */\n emit(event: DatabaseEvent): void {\n try {\n if (!isObject(event) || !event.type) {\n logger.error(\"Invalid event object\");\n return;\n }\n\n const handlers = this.eventHandlers.get(event.type as string);\n if (!handlers || handlers.length === 0) return;\n\n handlers.forEach((handler) => {\n try {\n const result = handler(event);\n if (result instanceof Promise) {\n result.catch((error) => {\n logger.error(\n `Async event handler error: ${(error as Error).message}`,\n );\n });\n }\n } catch (error) {\n logger.error(`Event handler error: ${(error as Error).message}`);\n }\n });\n } catch (error) {\n logger.error(`Failed to emit event: ${(error as Error).message}`);\n }\n }\n\n /**\n * Emit a before query event\n */\n emitBeforeQuery(\n table: string,\n operation: DatabaseOperationType,\n params?: Record<string, object>,\n context?: DatabaseExecutionContext,\n ): void {\n const event: BeforeQueryEvent = {\n type: DATABASE_EVENT_TYPE.BeforeQuery,\n timestamp: new Date(),\n adapter: this.adapter.toString(),\n table,\n operation,\n params,\n context,\n };\n this.emit(event);\n }\n\n /**\n * Emit an after query event\n */\n emitAfterQuery(\n table: string,\n operation: DatabaseOperationType,\n duration: number,\n affectedRows?: number,\n ): void {\n const event: AfterQueryEvent = {\n type: DATABASE_EVENT_TYPE.AfterQuery,\n timestamp: new Date(),\n adapter: this.adapter.toString(),\n table,\n operation,\n duration,\n affectedRows,\n };\n this.emit(event);\n }\n\n emitQueryError(options: EmitQueryErrorOptions): void {\n try {\n if (!isObject(options)) {\n logger.error(\"Invalid options for emitQueryError\");\n return;\n }\n\n const { table, operation, error, params, context } = options;\n\n if (!table || !operation || !error) {\n logger.error(\"Missing required fields for query error event\");\n return;\n }\n\n const event: QueryErrorEvent = {\n type: DATABASE_EVENT_TYPE.QueryError,\n timestamp: new Date(),\n adapter: this.adapter.toString(),\n table,\n operation,\n error,\n params,\n context,\n };\n\n this.emit(event);\n } catch (emitError) {\n logger.error(\n `Failed to emit query error event: ${(emitError as Error).message}`,\n );\n }\n }\n\n /**\n * Emit a before transaction event\n */\n emitBeforeTransaction(\n transactionId: string,\n context?: DatabaseExecutionContext,\n ): void {\n const event: BeforeTransactionEvent = {\n type: DATABASE_EVENT_TYPE.BeforeTransaction,\n timestamp: new Date(),\n adapter: this.adapter.toString(),\n transactionId,\n context,\n };\n this.emit(event);\n }\n\n /**\n * Emit an after transaction event\n */\n emitAfterTransaction(transactionId: string, duration: number): void {\n const event: AfterTransactionEvent = {\n type: DATABASE_EVENT_TYPE.AfterTransaction,\n timestamp: new Date(),\n adapter: this.adapter.toString(),\n transactionId,\n duration,\n };\n this.emit(event);\n }\n\n /**\n * Emit a transaction rollback event\n */\n emitTransactionRollback(transactionId: string, error?: Error): void {\n const event: TransactionRollbackEvent = {\n type: DATABASE_EVENT_TYPE.TransactionRollback,\n timestamp: new Date(),\n adapter: this.adapter.toString(),\n transactionId,\n error,\n };\n this.emit(event);\n }\n\n /**\n * Emit a health change event\n */\n emitHealthChange(\n previousStatus: boolean,\n currentStatus: boolean,\n details?: Record<string, string | number | boolean>,\n ): void {\n const event: HealthChangeEvent = {\n type: DATABASE_EVENT_TYPE.HealthChange,\n timestamp: new Date(),\n adapter: this.adapter.toString(),\n previousStatus,\n currentStatus,\n details,\n };\n this.emit(event as DatabaseEvent);\n }\n}\n","/**\n * @fileoverview Database Result Helper Functions for @plyaz/db package\n *\n * This module provides utility functions for creating standardized DatabaseResult objects\n * used throughout the @plyaz/db package. These helpers ensure consistent result formatting\n * across all database operations and adapters.\n *\n * Part of the @plyaz/db package - a TypeScript database abstraction layer with\n * support for multiple adapters (Drizzle, Supabase, SQL), extensions (audit, encryption,\n * soft delete), and advanced features (caching, read replicas, multi-tenancy).\n *\n */\n\nimport type { DatabaseResult } from \"@plyaz/types/db\";\n\n/**\n * Creates a successful DatabaseResult wrapper for operation results\n *\n * Used throughout all database adapters and extensions to wrap successful operation results\n * in a consistent format. This enables standardized error handling and result processing\n * across the entire @plyaz/db package.\n *\n * **Used by:**\n * - All database adapters (DrizzleAdapter, SupabaseAdapter, SQLAdapter)\n * - All extensions (AuditAdapter, EncryptionAdapter, SoftDeleteAdapter, etc.)\n * - DatabaseService for operation results\n * - Repository layer for consistent return types\n *\n * @template T - The type of the successful result value\n * @param {T} value - The successful result value to wrap\n * @returns {DatabaseResult<T>} A success result object with the value\n *\n * @example\n * ```typescript\n * import { success } from '@plyaz/db/utils';\n *\n * // In adapter methods\n * async findById<T>(table: string, id: string): Promise<DatabaseResult<T | null>> {\n * try {\n * const record = await this.db.select().from(table).where(eq(id));\n * return success(record[0] || null); // Wrap successful result\n * } catch (error) {\n * return failure(new DatabaseError('FIND_FAILED', error.message));\n * }\n * }\n *\n * // In service methods\n * const userResult = await userRepository.findById('user-123');\n * if (userResult.success) {\n * console.log('Found user:', userResult.value.name);\n * }\n * ```\n *\n */\nexport function success<T = null>(value: T = null as T): DatabaseResult<T> {\n return { success: true, value };\n}\n\n/**\n * Creates a failed DatabaseResult wrapper for operation errors\n * \n * Used throughout all database adapters and extensions to wrap error results\n * in a consistent format. This enables standardized error handling and result processing\n * across the entire @plyaz/db package.\n * \n * **Used by:**\n * - All database adapters for error cases\n * - All extensions for error propagation\n * - DatabaseService for operation failures\n * - Repository layer for consistent error handling\n * \n * @template T - The type that would have been returned on success\n * @param {Error} error - The error that occurred during the operation\n * @returns {DatabaseResult<T>} A failure result object with the error\n * \n * @example\n * ```typescript\n * import { failure } from '@plyaz/db/utils';\n * import { DatabaseError } from '@plyaz/errors';\nimport { DATABASE_ERROR_CODES } from '@plyaz/types/errors';\n * \n * // In adapter methods\n * async create<T>(table: string, data: T): Promise<DatabaseResult<T>> {\n * try {\n * const result = await this.db.insert(table).values(data).returning();\n * return success(result[0]);\n * } catch (error) {\n * return failure(new DatabaseError(\n * `Failed to create record: ${error.message}`));\n * }\n * }\n * \n * // In service layer error handling\n * const createResult = await userRepository.create(userData);\n * if (!createResult.success) {\n * logger.error('User creation failed:', createResult.error.message);\n * throw createResult.error;\n * }\n * ```\n * \n */\nexport function failure<T>(error: Error): DatabaseResult<T> {\n return { success: false, error };\n}\n","/**\n * @fileoverview Detail Normalization Utilities for @plyaz/db package\n *\n * This module provides utilities for normalizing various data types into consistent\n * string-based record formats. Used throughout the @plyaz/db package for standardizing\n * error details, health status information, and event metadata.\n *\n * Part of the @plyaz/db package - a TypeScript database abstraction layer with\n * support for multiple adapters (Drizzle, Supabase, SQL), extensions (audit, encryption,\n * soft delete), and advanced features (caching, read replicas, multi-tenancy).\n *\n */\n\nimport { isObject } from \"./typeGuards\";\n\n/**\n * Normalizes any input into a standardized Record<string, string> format\n *\n * Converts various data types into a consistent string-based record format\n * for use in error details, health status information, and event metadata.\n * Provides safe handling of different input types with fallback strategies.\n *\n * **Normalization Rules:**\n * - Objects: Converts all property values to strings while preserving keys\n * - Primitives: Wraps in { info: stringValue } format\n * - null/undefined: Returns undefined (no details)\n * - Arrays: Converts to { info: stringified array }\n * - Errors: Safely handles conversion failures\n *\n * **Used by:**\n * - HealthManager for health status details\n * - DatabaseEventEmitter for event metadata\n * - Error handling throughout adapter chain\n * - Audit logging for consistent detail formatting\n *\n * @param {unknown} details - Input details of any type to normalize\n * @returns {Record<string, string> | undefined} Normalized details as string record or undefined\n *\n * @example\n * ```typescript\n * import { normalizeDetails } from '@plyaz/db/utils';\n *\n * // Object normalization\n * const objDetails = normalizeDetails({\n * count: 42,\n * active: true,\n * name: 'test'\n * });\n * console.log(objDetails);\n * // { count: \"42\", active: \"true\", name: \"test\" }\n *\n * // Primitive normalization\n * const stringDetails = normalizeDetails(\"Connection timeout\");\n * console.log(stringDetails);\n * // { info: \"Connection timeout\" }\n *\n * // Number normalization\n * const numberDetails = normalizeDetails(404);\n * console.log(numberDetails);\n * // { info: \"404\" }\n *\n * // Null/undefined handling\n * const nullDetails = normalizeDetails(null);\n * console.log(nullDetails);\n * // undefined\n *\n * // Array normalization\n * const arrayDetails = normalizeDetails(['error1', 'error2']);\n * console.log(arrayDetails);\n * // { info: \"error1,error2\" }\n *\n * // Error object normalization\n * const errorDetails = normalizeDetails(new Error('Database error'));\n * console.log(errorDetails);\n * // { info: \"Error: Database error\" }\n * ```\n *\n * @example\n * ### Usage in Health Status\n * ```typescript\n * // In HealthManager.checkHealth()\n * const healthStatus = {\n * isHealthy: true,\n * responseTime: 150,\n * details: normalizeDetails({\n * adapter: 'drizzle',\n * connections: 5,\n * lastQuery: new Date()\n * })\n * };\n * // details: { adapter: \"drizzle\", connections: \"5\", lastQuery: \"2024-01-01T10:00:00.000Z\" }\n * ```\n *\n * @example\n * ### Usage in Error Handling\n * ```typescript\n * // In adapter error handling\n * catch (error) {\n * return failure(new DatabaseError(\n * 'QUERY_FAILED',\n * HTTP_STATUS.INTERNAL_SERVER_ERROR,\n * 'Query execution failed',\n * normalizeDetails({\n * query: sql,\n * params: queryParams,\n * originalError: error.message\n * })\n * ));\n * }\n * ```\n *\n */\nexport function normalizeDetails(\n details: unknown,\n): Record<string, string> | undefined {\n try {\n // Handle null, undefined, or falsy values\n // Return undefined to indicate no details available\n if (!details) return undefined;\n\n // Handle object types (but not arrays)\n // Convert all object property values to strings while preserving keys\n if (isObject(details)) {\n const mapped: Record<string, string> = {};\n\n // Iterate through object entries and convert values to strings\n for (const [key, value] of Object.entries(details)) {\n // Use String() for safe conversion of any value type\n mapped[key] = String(value);\n }\n return mapped;\n }\n\n // Handle primitives, arrays, and other non-object types\n // Wrap in standardized { info: value } format\n return { info: String(details) };\n } catch (error) {\n // Fallback error handling for extreme cases\n // Return error information if normalization fails\n return {\n error: \"Failed to normalize details\",\n reason: (error as Error).message,\n };\n }\n}\n","/**\n * @fileoverview Health Manager for @plyaz/db package\n *\n * This module provides the HealthManager class responsible for monitoring database\n * connection health, performing periodic health checks, and managing the lifecycle\n * of database connections. It provides a centralized way to track database status.\n *\n * Part of the @plyaz/db package - a TypeScript database abstraction layer with\n * support for multiple adapters (Drizzle, Supabase, SQL), extensions (audit, encryption,\n * soft delete), and advanced features (caching, read replicas, multi-tenancy).\n *\n */\n\nimport type {\n DatabaseAdapterType,\n DatabaseHealthStatus,\n DatabaseResult,\n HealthManagerConfig,\n} from \"@plyaz/types/db\";\nimport { success, failure } from \"@utils/databaseResultHelpers\";\nimport { normalizeDetails } from \"@utils/normalizeDetails\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\n\n/** Default number of consecutive failures before triggering failover */\nconst DEFAULT_FAILOVER_THRESHOLD = 3;\n\n/**\n * 🌡️ HEALTH MANAGER - Database Health Monitoring\n *\n * Manages database health checks and monitoring functionality for all database adapters.\n * This class is responsible for performing health checks on the database connection,\n * storing the last known health status, and providing methods to quickly check\n * the current health state of the database.\n *\n * **Application Flow Position:**\n * DatabaseService → **HealthManager** → Adapter.healthCheck() → Database\n *\n * **What this class does:**\n * 1. Initializes database connections on startup\n * 2. Performs periodic health checks via adapter.healthCheck()\n * 3. Caches last known health status for quick access\n * 4. Normalizes health details across different adapters\n * 5. Manages connection lifecycle (connect/disconnect)\n *\n * **Called by:** DatabaseService.healthCheck(), application health endpoints\n * **Calls:** DatabaseAdapter.healthCheck(), DatabaseAdapter.connect/disconnect\n * **Used for:** Application health monitoring, load balancer health checks\n *\n * @example\n * ```typescript\n * // Create health manager with adapter\n * const healthManager = new HealthManager(drizzleAdapter);\n *\n * // Initialize connection and perform initial health check\n * await healthManager.init();\n *\n * // Perform health check\n * const healthResult = await healthManager.checkHealth();\n * if (healthResult.success) {\n * console.log('Database is healthy:', healthResult.value);\n * }\n *\n * // Quick health status check (uses cached result)\n * const isHealthy = healthManager.isHealthy();\n *\n * // Get last known status without new check\n * const lastStatus = healthManager.getLastHealthStatus();\n *\n * // Cleanup on shutdown\n * await healthManager.shutdown();\n * ```\n *\n */\nexport class HealthManager {\n private lastHealthStatus: DatabaseHealthStatus | null = null;\n private initialized = false;\n private currentAdapter: DatabaseAdapterType;\n private primaryAdapter: DatabaseAdapterType;\n private backupAdapters: DatabaseAdapterType[];\n private consecutiveFailures = 0;\n private healthCheckInterval?: number;\n private failoverThreshold: number;\n private autoFailover: boolean;\n private healthCheckTimer?: globalThis.NodeJS.Timeout;\n\n constructor(config: DatabaseAdapterType | HealthManagerConfig) {\n // Support both old (single adapter) and new (config) constructors\n if (\"primary\" in config) {\n this.primaryAdapter = config.primary;\n this.currentAdapter = config.primary;\n this.backupAdapters = config.backups ?? [];\n this.healthCheckInterval = config.healthCheckInterval;\n this.failoverThreshold =\n config.failoverThreshold ?? DEFAULT_FAILOVER_THRESHOLD;\n this.autoFailover = config.autoFailover ?? false;\n } else {\n this.primaryAdapter = config;\n this.currentAdapter = config;\n this.backupAdapters = [];\n this.failoverThreshold = DEFAULT_FAILOVER_THRESHOLD;\n this.autoFailover = false;\n }\n }\n\n /**\n * Initializes the health manager by establishing database connection and performing initial health check\n *\n * Sets up the database connection and performs an initial health check to establish\n * baseline health status. This method should be called during application startup\n * to ensure the database is ready for operations.\n *\n * **Initialization Process:**\n * 1. Checks if already initialized (prevents double initialization)\n * 2. Calls adapter.connect() if available (establishes connection)\n * 3. Performs initial health check via checkHealth()\n * 4. Sets initialized flag to prevent re-initialization\n *\n * @returns {Promise<void>} Promise that resolves when initialization is complete\n *\n * @example\n * ```typescript\n * const healthManager = new HealthManager(adapter);\n *\n * // Initialize during application startup\n * await healthManager.init();\n * console.log('Health manager initialized');\n *\n * // Subsequent calls are no-ops\n * await healthManager.init(); // Does nothing, already initialized\n * ```\n *\n */\n async init(): Promise<void> {\n // Prevent double initialization\n if (this.initialized) return;\n\n // Establish database connection if adapter supports it\n if (typeof this.currentAdapter.initialize === \"function\") {\n await this.currentAdapter.initialize();\n }\n\n // Perform initial health check to establish baseline status\n await this.checkHealth();\n this.initialized = true;\n\n // Start periodic health checks if configured\n if (this.healthCheckInterval && this.healthCheckInterval > 0) {\n this.startPeriodicHealthChecks();\n }\n }\n\n /**\n * Performs a comprehensive health check on the database connection\n *\n * Executes a health check via the database adapter and normalizes the results\n * into a standardized health status format. Measures response time and handles\n * both successful and failed health checks gracefully.\n *\n * **Health Check Process:**\n * 1. Records start time for response time measurement\n * 2. Calls adapter.healthCheck() to test database connectivity\n * 3. Normalizes adapter-specific response into standard format\n * 4. Caches result as lastHealthStatus for quick access\n * 5. Returns standardized DatabaseResult with health information\n *\n * **Health Status Fields:**\n * - isHealthy: Boolean indicating if database is operational\n * - responseTime: Time in milliseconds for health check to complete\n * - details: Normalized adapter-specific details (connection info, errors, etc.)\n *\n * @returns {Promise<DatabaseResult<DatabaseHealthStatus>>} Promise resolving to health status result\n *\n * @example\n * ```typescript\n * // Perform health check\n * const healthResult = await healthManager.checkHealth();\n *\n * if (healthResult.success) {\n * const status = healthResult.value;\n * console.log(`Database healthy: ${status.isHealthy}`);\n * console.log(`Response time: ${status.responseTime}ms`);\n * console.log('Details:', status.details);\n * } else {\n * console.error('Health check failed:', healthResult.error.message);\n * }\n *\n * // Example healthy response:\n * // {\n * // success: true,\n * // value: {\n * // isHealthy: true,\n * // responseTime: 45,\n * // details: { adapter: \"drizzle\", connections: \"5\" }\n * // }\n * // }\n *\n * // Example unhealthy response:\n * // {\n * // success: true,\n * // value: {\n * // isHealthy: false,\n * // responseTime: 5000,\n * // details: { error: \"Connection timeout\" }\n * // }\n * // }\n * ```\n *\n */\n /**\n * Handle health check result and update internal state\n */\n private async handleHealthResult(isSuccess: boolean): Promise<void> {\n if (isSuccess) {\n this.consecutiveFailures = 0;\n return;\n }\n\n this.consecutiveFailures++;\n if (\n this.autoFailover &&\n this.consecutiveFailures >= this.failoverThreshold\n ) {\n await this.performFailover();\n }\n }\n\n /**\n * Create health status from check result\n */\n private createHealthStatus(\n result: DatabaseResult<DatabaseHealthStatus>,\n responseTime: number,\n ): DatabaseHealthStatus {\n return {\n isHealthy: result.success,\n responseTime,\n details: result.success\n ? normalizeDetails(result.value)\n : { error: result.error?.message ?? \"Unknown error\" },\n };\n }\n\n async checkHealth(): Promise<DatabaseResult<DatabaseHealthStatus>> {\n const startTime = Date.now();\n\n try {\n const result = await this.currentAdapter.healthCheck();\n const responseTime = Date.now() - startTime;\n\n const status = this.createHealthStatus(result, responseTime);\n this.lastHealthStatus = status;\n\n await this.handleHealthResult(result.success);\n\n return success(status);\n } catch (error) {\n const status: DatabaseHealthStatus = {\n isHealthy: false,\n responseTime: Date.now() - startTime,\n details: { error: (error as Error).message },\n };\n\n this.lastHealthStatus = status;\n await this.handleHealthResult(false);\n\n return failure(\n new DatabaseError(\n `Health check failed: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.FETCH_FAILED,\n {\n context: { source: \"checkHealth\" },\n cause: error as Error,\n },\n ),\n );\n }\n }\n /**\n * Get the last known health status\n */\n getLastHealthStatus(): DatabaseHealthStatus | null {\n return this.lastHealthStatus;\n }\n\n /**\n * Check if the database is currently healthy\n */\n isHealthy(): boolean {\n return this.lastHealthStatus?.isHealthy ?? false;\n }\n\n /**\n * Get the current active adapter\n */\n getCurrentAdapter(): DatabaseAdapterType {\n return this.currentAdapter;\n }\n\n /**\n * Try to initialize and verify health of a backup adapter\n */\n private async tryBackupAdapter(\n backup: DatabaseAdapterType,\n ): Promise<boolean> {\n if (typeof backup.initialize === \"function\") {\n const initResult = await backup.initialize();\n if (!initResult.success) return false;\n }\n\n const healthResult = await backup.healthCheck();\n return healthResult.success && (healthResult.value?.isHealthy ?? false);\n }\n\n /**\n * Switch to a healthy backup adapter\n */\n private async switchToBackup(backup: DatabaseAdapterType): Promise<void> {\n await this.currentAdapter.close();\n this.currentAdapter = backup;\n this.consecutiveFailures = 0;\n console.log(\"[HealthManager] Failover successful to backup adapter\");\n }\n\n /**\n * Perform failover to next available backup adapter\n */\n private async performFailover(): Promise<void> {\n if (this.backupAdapters.length === 0) {\n console.warn(\"[HealthManager] No backup adapters available for failover\");\n return;\n }\n\n for (const backup of this.backupAdapters) {\n try {\n const isHealthy = await this.tryBackupAdapter(backup);\n if (isHealthy) {\n await this.switchToBackup(backup);\n return;\n }\n } catch (error) {\n console.error(\n \"[HealthManager] Backup adapter health check failed:\",\n error,\n );\n }\n }\n\n console.error(\n \"[HealthManager] All backup adapters failed, staying with current adapter\",\n );\n }\n\n /**\n * Start periodic health checks\n */\n private startPeriodicHealthChecks(): void {\n if (this.healthCheckTimer) return;\n\n this.healthCheckTimer = setInterval(async () => {\n await this.checkHealth();\n }, this.healthCheckInterval);\n }\n\n /**\n * Stop periodic health checks\n */\n private stopPeriodicHealthChecks(): void {\n if (this.healthCheckTimer) {\n clearInterval(this.healthCheckTimer);\n this.healthCheckTimer = undefined;\n }\n }\n\n /**\n * Gracefully shut down the health manager\n */\n async shutdown(): Promise<void> {\n this.stopPeriodicHealthChecks();\n\n await this.currentAdapter.close();\n\n this.initialized = false;\n this.lastHealthStatus = null;\n }\n}\n","/**\n * @fileoverview Configuration Merger for @plyaz/db package\n *\n * This module provides the ConfigMerger utility class responsible for deep merging\n * database configurations. It handles merging global database service configuration\n * with per-operation overrides to create resolved configurations for the adapter chain.\n *\n * Part of the @plyaz/db package - a TypeScript database abstraction layer with\n * support for multiple adapters (Drizzle, Supabase, SQL), extensions (audit, encryption,\n * soft delete), and advanced features (caching, read replicas, multi-tenancy).\n */\n\nimport { NUMERIX } from \"@plyaz/config\";\nimport type {\n DatabaseServiceConfig,\n DBCacheConfig,\n DBEncryptionConfig,\n OperationConfig,\n ResolvedOperationConfig,\n SoftDeleteConfig,\n TimestampsConfig,\n} from \"@plyaz/types/db\";\n\n/**\n * CONFIG MERGER - Configuration Resolution Engine\n *\n * Utility class for deep merging database configurations.\n * Handles merging global database service configuration with per-operation overrides\n *\n * Application Flow Position:**\n * DatabaseService → **ConfigMerger** → Resolved Config → Adapter Chain\n *\n * **What this class does:**\n * 1. Receives global config (from createDatabaseService) and operation config (from method calls)\n * 2. Deep merges nested objects (encryption, softDelete, cache, etc.)\n * 3. Operation config takes precedence over global config\n * 4. Returns resolved configuration for adapter chain\n *\n * **Called by:** DatabaseService methods (get, create, update, delete, etc.)\n * **Calls:** Internal merge methods for each config section\n * **Returns to:** DatabaseService for delegation to adapter chain\n *\n * **Merge Strategy:**\n * - Operation config overrides global config\n * - Nested objects are deep merged (not replaced)\n * - Arrays use replace strategy for fields, concat for others\n * - Undefined values in operation config fall back to global defaults\n *\n * @example\n * ### Configuration Merging Flow\n * ```typescript\n * // Global config (from createDatabaseService)\n * const globalConfig = {\n * softDelete: { enabled: true, field: 'deletedAt' },\n * cache: { enabled: true, ttl: 300 }\n * };\n *\n * // Operation config (from method call)\n * const operationConfig = {\n * cache: { enabled: false },\n * includeSoftDeleted: true\n * };\n *\n * // ConfigMerger.mergeConfigs() produces:\n * const resolved = {\n * softDelete: { enabled: true, field: 'deletedAt' }, // From global\n * cache: { enabled: false, ttl: 300 }, // Merged\n * includeSoftDeleted: true, // From operation\n * skipAudit: false // Default\n * };\n * ```\n */\nexport class ConfigMerger {\n /**\n * Merges global database configuration with operation-specific overrides\n *\n * This is the main entry point for configuration resolution in the DatabaseService.\n * It performs deep merging of nested configuration objects while preserving type safety\n * and applying proper precedence rules.\n *\n * **Merge Precedence (highest to lowest):**\n * 1. Operation-specific config (method-level overrides)\n * 2. Global service config (from createDatabaseService)\n * 3. Default values (built-in fallbacks)\n *\n * **Configuration Sections Merged:**\n * - softDelete: Logical deletion settings\n * - encryption: Field-level encryption settings\n * - cache: Caching behavior and TTL\n * - timestamps: Automatic timestamp management\n * - Operation flags: skipAudit, includeSoftDeleted, etc.\n *\n * @param {DatabaseServiceConfig} global - Global database service configuration from createDatabaseService()\n * @param {OperationConfig} [operation] - Optional operation-specific configuration overrides\n * @returns {ResolvedOperationConfig} Fully resolved configuration with all defaults applied\n *\n * @example\n * ```typescript\n * // In DatabaseService.get() method\n * const resolvedConfig = ConfigMerger.mergeConfigs(\n * this.globalConfig, // From createDatabaseService\n * operationConfig // From method parameter\n * );\n *\n * // Example global config\n * const globalConfig = {\n * softDelete: { enabled: true, field: 'deletedAt' },\n * encryption: { enabled: true, fields: { users: ['ssn'] } },\n * cache: { enabled: true, ttl: 300 }\n * };\n *\n * // Example operation config (disable cache for this operation)\n * const operationConfig = {\n * cache: { enabled: false },\n * skipAudit: true\n * };\n *\n * // Resulting merged config\n * const result = {\n * softDelete: { enabled: true, field: 'deletedAt' }, // From global\n * encryption: { enabled: true, fields: { users: ['ssn'] } }, // From global\n * cache: { enabled: false, ttl: 300 }, // Merged (enabled overridden)\n * timestamps: undefined, // Not specified\n * skipAudit: true, // From operation\n * includeSoftDeleted: false, // Default\n * forceAdapter: undefined, // Not specified\n * timeout: 30000 // Default\n * };\n * ```\n *\n */\n static mergeConfigs(\n global: DatabaseServiceConfig,\n operation?: OperationConfig,\n ): ResolvedOperationConfig {\n if (!operation) {\n return this.convertGlobalToResolved(global);\n }\n\n return {\n softDelete: this.mergeSoftDeleteConfig(\n global.softDelete,\n operation.softDelete,\n ),\n encryption: this.mergeEncryptionConfig(\n global.encryption,\n operation.encryption,\n ),\n cache: this.mergeCacheConfig(global.cache, operation.cache),\n timestamps: this.mergeTimestampsConfig(\n global.timestamps,\n operation.timestamps,\n ),\n skipAudit: operation.skipAudit ?? false,\n includeSoftDeleted: operation.includeSoftDeleted ?? false,\n forceAdapter: operation.forceAdapter,\n timeout: operation.timeout ?? NUMERIX.THIRTY_THOUSAND,\n };\n }\n\n /**\n * Merges soft delete configuration with operation-specific overrides\n *\n * Handles deep merging of soft delete settings, allowing operation-level\n * overrides while preserving base configuration values.\n *\n * @private\n * @param {SoftDeleteConfig} [base] - Base soft delete configuration from global config\n * @param {Partial<SoftDeleteConfig>} [override] - Operation-specific soft delete overrides\n * @returns {SoftDeleteConfig | undefined} Merged soft delete configuration or undefined if neither provided\n *\n * @example\n * ```typescript\n * // Base config: { enabled: true, field: 'deletedAt', excludeTables: ['logs'] }\n * // Override: { enabled: false }\n * // Result: { enabled: false, field: 'deletedAt', excludeTables: ['logs'] }\n * ```\n *\n */\n private static mergeSoftDeleteConfig(\n base?: SoftDeleteConfig,\n override?: Partial<SoftDeleteConfig>,\n ): SoftDeleteConfig | undefined {\n // Return undefined if neither base nor override provided\n if (!base && !override) return undefined;\n // Return base config if no override provided\n if (!override) return base;\n // Return override as complete config if no base provided\n if (!base) return override as SoftDeleteConfig;\n\n // Deep merge: override takes precedence, base provides fallbacks\n return {\n enabled: override.enabled ?? base.enabled,\n field: override.field ?? base.field,\n excludeTables: override.excludeTables ?? base.excludeTables,\n };\n }\n\n /**\n * Merges encryption configuration with operation-specific overrides\n *\n * Handles deep merging of field-level encryption settings, allowing operation-level\n * overrides for encryption behavior while preserving base configuration.\n *\n * @private\n * @param {DBEncryptionConfig} [base] - Base encryption configuration from global config\n * @param {Partial<DBEncryptionConfig>} [override] - Operation-specific encryption overrides\n * @returns {DBEncryptionConfig | undefined} Merged encryption configuration or undefined if neither provided\n *\n * @example\n * ```typescript\n * // Base config: { enabled: true, key: 'base64key', fields: { users: ['ssn'] } }\n * // Override: { enabled: false }\n * // Result: { enabled: false, key: 'base64key', fields: { users: ['ssn'] } }\n * ```\n *\n */\n // eslint-disable-next-line complexity\n private static mergeEncryptionConfig(\n base?: DBEncryptionConfig,\n override?: Partial<DBEncryptionConfig>,\n ): DBEncryptionConfig | undefined {\n // Return undefined if neither base nor override provided\n if (!base && !override) return undefined;\n // Return base config if no override provided\n if (!override) return base;\n // Return override as complete config if no base provided\n if (!base) return override as DBEncryptionConfig;\n\n // Deep merge: override takes precedence, base provides fallbacks\n return {\n enabled: override.enabled ?? base.enabled,\n key: override.key ?? base.key,\n fields: override.fields ?? base.fields,\n algorithm: override.algorithm ?? base.algorithm,\n useDatabaseNative: override.useDatabaseNative ?? base.useDatabaseNative,\n };\n }\n\n /**\n * Merges cache configuration with operation-specific overrides\n * \n * Handles deep merging of caching settings, allowing operation-level\n * overrides for cache behavior (enable/disable, TTL changes, etc.).\n * \n * @private\n * @param {DBCacheConfig} [base] - Base cache configuration from global config\n * @param {Partial<DBCacheConfig>} [override] - Operation-specific cache overrides\n * @returns {DBCacheConfig | undefined} Merged cache configuration or undefined if neither provided\n * \n * @example\n * ```typescript\n * // Base config: { enabled: true, ttl: 300, provider: 'redis' }\n * // Override: { enabled: false }\n * // Result: { enabled: false, ttl: 300, provider: 'redis' }\n * ```\n * \n\n */\n // eslint-disable-next-line complexity\n private static mergeCacheConfig(\n base?: DBCacheConfig,\n override?: Partial<DBCacheConfig>,\n ): DBCacheConfig | undefined {\n // Return undefined if neither base nor override provided\n if (!base && !override) return undefined;\n // Return base config if no override provided\n if (!override) return base;\n // Return override as complete config if no base provided\n if (!base) return override as DBCacheConfig;\n\n // Deep merge: override takes precedence, base provides fallbacks\n return {\n enabled: override.enabled ?? base.enabled,\n ttl: override.ttl ?? base.ttl,\n provider: override.provider ?? base.provider,\n invalidation: override.invalidation ?? base.invalidation,\n };\n }\n\n /**\n * Merges timestamps configuration with operation-specific overrides\n *\n * Handles deep merging of automatic timestamp settings, allowing operation-level\n * overrides for timestamp field names and auto-update behavior.\n *\n * @private\n * @param {TimestampsConfig} [base] - Base timestamps configuration from global config\n * @param {Partial<TimestampsConfig>} [override] - Operation-specific timestamp overrides\n * @returns {TimestampsConfig | undefined} Merged timestamps configuration or undefined if neither provided\n *\n * @example\n * ```typescript\n * // Base config: { enabled: true, createdAtField: 'createdAt', updatedAtField: 'updatedAt' }\n * // Override: { autoUpdate: false }\n * // Result: { enabled: true, createdAtField: 'createdAt', updatedAtField: 'updatedAt', autoUpdate: false }\n * ```\n */\n // eslint-disable-next-line complexity\n private static mergeTimestampsConfig(\n base?: TimestampsConfig,\n override?: Partial<TimestampsConfig>,\n ): TimestampsConfig | undefined {\n // Return undefined if neither base nor override provided\n if (!base && !override) return undefined;\n // Return base config if no override provided\n if (!override) return base;\n // Return override as complete config if no base provided\n if (!base) return override as TimestampsConfig;\n\n // Deep merge: override takes precedence, base provides fallbacks\n return {\n enabled: override.enabled ?? base.enabled,\n createdAtField: override.createdAtField ?? base.createdAtField,\n updatedAtField: override.updatedAtField ?? base.updatedAtField,\n autoUpdate: override.autoUpdate ?? base.autoUpdate,\n };\n }\n\n /**\n * Converts global database service configuration to resolved operation configuration\n *\n * Used when no operation-specific overrides are provided. Applies default values\n * for operation-specific flags while preserving global configuration settings.\n *\n * @private\n * @param {DatabaseServiceConfig} global - Global database service configuration\n * @returns {ResolvedOperationConfig} Resolved configuration with defaults applied\n *\n * @example\n * ```typescript\n * // Global config: { softDelete: { enabled: true }, cache: { enabled: true, ttl: 300 } }\n * // Result: {\n * // softDelete: { enabled: true },\n * // cache: { enabled: true, ttl: 300 },\n * // skipAudit: false, // Default\n * // includeSoftDeleted: false, // Default\n * // timeout: 30000 // Default\n * // }\n * ```\n *\n */\n private static convertGlobalToResolved(\n global: DatabaseServiceConfig,\n ): ResolvedOperationConfig {\n return {\n // Preserve global configuration sections as-is\n softDelete: global?.softDelete,\n encryption: global?.encryption,\n cache: global?.cache,\n timestamps: global?.timestamps,\n // Apply default values for operation-specific flags\n skipAudit: false, // Default: enable audit logging\n includeSoftDeleted: false, // Default: exclude soft-deleted records\n timeout: NUMERIX.THIRTY_THOUSAND, // Default: 30 second timeout\n };\n }\n}\n","/**\n * @fileoverview Internal Database Service Implementation for @plyaz/db package\n *\n * This module provides the internal DatabaseService class that orchestrates all database\n * operations. It is NOT exported and is created internally by the createDatabaseService() factory.\n *\n * Part of the @plyaz/db package - a TypeScript database abstraction layer with\n * support for multiple adapters (Drizzle, Supabase, SQL), extensions (audit, encryption,\n * soft delete), and advanced features (caching, read replicas, multi-tenancy).\n *\n */\n\nimport { DatabaseEventEmitter } from \"./EventEmitter\";\nimport { HealthManager } from \"./HealthManager\";\nimport { ConfigMerger } from \"@utils/ConfigMerger\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport type {\n AuditContext,\n BatchUpdate,\n CreateInput,\n DatabaseAdapterType,\n DatabaseEvent,\n DatabaseEvents,\n DatabaseHealthStatus,\n DatabaseResult,\n DatabaseServiceConfig,\n DatabaseServiceInterface,\n Filter,\n OperationConfig,\n PaginatedResult,\n QueryOptions,\n ServiceStatus,\n TableName,\n TransactionFn,\n UpdateInput,\n} from \"@plyaz/types/db\";\nimport { ADAPTERS } from \"@plyaz/types/db\";\nimport { failure, success } from \"@utils/databaseResultHelpers\";\n\n/**\n * 🛠️ DATABASE SERVICE - Internal Service Layer\n *\n * Core service implementation that orchestrates all database operations.\n * NOT EXPORTED - created internally by createDatabaseService() factory.\n *\n * **Application Flow Position:**\n * createDatabaseService() → **DatabaseService** → Adapter Chain → Database\n *\n * **What this class does:**\n * 1. Stores global configuration from createDatabaseService()\n * 2. Receives calls from repositories via IDatabaseService interface\n * 3. Merges per-operation config with global config using ConfigMerger\n * 4. Fires before/after events (onBeforeWrite, onAfterWrite, etc.)\n * 5. Delegates to adapter chain with resolved configuration\n * 6. Returns results back to repositories\n *\n * **Called by:** Repository layer (BaseRepository, UserRepository, etc.)\n * **Calls:** ConfigMerger.mergeConfigs(), adapter chain methods, event handlers\n * **Delegates to:** Final wrapped adapter (ReadReplicaAdapter → AuditAdapter → ... → BaseAdapter)\n *\n * **Key Responsibilities:**\n * - Configuration merging and resolution\n * - Event system orchestration\n * - Audit context management\n * - Error handling and propagation\n * - Service status tracking\n *\n * @internal This class is not part of the public API\n */\nexport class DatabaseService implements DatabaseServiceInterface {\n private readonly globalConfig: DatabaseServiceConfig;\n public readonly adapter: DatabaseAdapterType;\n private readonly eventHandlers: DatabaseEvents | undefined;\n private readonly eventEmitter: DatabaseEventEmitter;\n private readonly healthManager: HealthManager;\n private readonly startTime: Date;\n private auditContext: AuditContext = {};\n\n constructor(config: {\n adapter: DatabaseAdapterType;\n globalConfig: DatabaseServiceConfig;\n eventHandlers?: DatabaseEvents;\n }) {\n this.globalConfig = config.globalConfig;\n this.adapter = config.adapter;\n this.eventHandlers = config.eventHandlers;\n this.startTime = new Date();\n\n const adapterType =\n (config.adapter?.constructor?.name?.toLowerCase() as ADAPTERS) ??\n ADAPTERS.SQL;\n this.eventEmitter = new DatabaseEventEmitter(adapterType);\n this.healthManager = new HealthManager(config.adapter);\n\n console.log(`DatabaseService initialized with ${adapterType} adapter`);\n }\n\n /**\n * 🔧 Prepare table name and configuration for operation\n *\n * Handles per-operation overrides for:\n * 1. Schema - prepends schema to table name (e.g., \"audit.logs\")\n * 2. ID Column - temporarily registers table with custom ID column\n *\n * Priority order:\n * - Operation config (highest) - per-query override\n * - TABLE_REGISTRY - global registration\n * - Default (lowest) - 'id' column, 'public' schema\n *\n * @param table Base table name\n * @param operationConfig Optional operation configuration with idColumn/schema\n * @returns Final table name to use (with schema prefix if applicable)\n *\n * @example\n * ```typescript\n * // With schema override\n * const tableName = this.prepareTable('logs', { schema: 'audit' });\n * // Returns: 'audit.logs'\n *\n * // With ID column override\n * const tableName = this.prepareTable('feature_flags', { idColumn: 'key' });\n * // Registers table with 'key' as ID column, returns: 'feature_flags'\n *\n * // With both\n * const tableName = this.prepareTable('users', { schema: 'backoffice', idColumn: 'user_id' });\n * // Returns: 'backoffice.users' with 'user_id' as ID column\n * ```\n */\n private prepareTable(\n table: TableName,\n operationConfig?: OperationConfig,\n ): string {\n let finalTableName = table;\n\n // Handle schema override\n if (operationConfig?.schema) {\n // If table already has schema prefix, replace it\n const tableWithoutSchema = table.includes(\".\")\n ? table.split(\".\")[1]\n : table;\n finalTableName = `${operationConfig.schema}.${tableWithoutSchema}`;\n }\n\n // Handle custom ID column override\n if (operationConfig?.idColumn) {\n // Temporarily register the table with the custom ID column\n // This allows the adapter to use the correct ID column for this operation\n this.adapter.registerTable(\n finalTableName,\n finalTableName,\n operationConfig.idColumn,\n );\n }\n\n return finalTableName;\n }\n\n /**\n * 🔍 Get a single record by ID\n *\n * **Flow:** Repository.findById() → **DatabaseService.get()** → ConfigMerger → Adapter Chain → Database\n *\n * **What happens:**\n * 1. Merges operation config with global config using ConfigMerger\n * 2. Fires onBeforeRead event (if configured)\n * 3. Delegates to adapter chain: ReadReplica → Audit → Cache → SoftDelete → Encryption → Base\n * 4. Fires onAfterRead event on success\n * 5. Returns result to repository\n *\n * **Called by:** BaseRepository.findById(), custom repository methods\n * **Calls:** ConfigMerger.mergeConfigs(), this.adapter.findById(), event handlers\n *\n * @param table Table name (from Tables enum)\n * @param id Record ID to retrieve\n * @param operationConfig Optional per-operation configuration overrides\n * @returns Promise resolving to the record or null if not found\n *\n * @example\n * ```typescript\n * // Called by UserRepository.findById()\n * const user = await this.db.get(Tables.USERS, 'user-123');\n *\n * // With operation config override\n * const user = await this.db.get(Tables.USERS, 'user-123', {\n * forceAdapter: 'primary', // Force primary DB\n * cache: { enabled: false } // Skip cache\n * });\n *\n * // With custom ID column (per-query override)\n * const flag = await this.db.get('feature_flags', 'my-flag-key', {\n * idColumn: 'key' // Use 'key' instead of 'id' as primary key\n * });\n *\n * // With custom schema\n * const auditLog = await this.db.get('logs', '123', {\n * schema: 'audit' // Query from audit.logs table\n * });\n *\n * // Combining multiple overrides\n * const backofficeUser = await this.db.get('users', 'admin-456', {\n * schema: 'backoffice',\n * idColumn: 'user_id',\n * forceAdapter: 'primary'\n * });\n * ```\n */\n async get<T extends Record<string, unknown>>(\n table: TableName,\n id: string,\n operationConfig?: OperationConfig,\n ): Promise<DatabaseResult<T | null>> {\n // Merge configs - operation config takes precedence\n ConfigMerger.mergeConfigs(this.globalConfig, operationConfig);\n\n // Prepare table with schema and ID column overrides\n const finalTable = this.prepareTable(table, operationConfig);\n\n try {\n // Fire before-read event if configured\n if (this.eventHandlers?.onBeforeRead) {\n await this.eventHandlers.onBeforeRead({\n type: \"beforeRead\",\n operation: \"READ\",\n table,\n timestamp: new Date(),\n });\n }\n\n // Delegate to adapter with resolved config\n const result = await this.adapter.findById<T>(finalTable, id);\n\n // Fire after-read event if configured and successful\n if (result.success && this.eventHandlers?.onAfterRead) {\n await this.eventHandlers.onAfterRead({\n type: \"afterRead\",\n operation: \"READ\",\n table,\n result: (result.value ?? {}) as Record<\n string,\n string | number | boolean | Date\n >,\n duration: 0, // TODO: Track duration\n timestamp: new Date(),\n });\n }\n\n return result;\n } catch (error) {\n return failure(\n new DatabaseError(\n `Get operation failed: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n {\n context: { source: \"get\" },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * List records with optional filtering, sorting, and pagination\n * Merges operation config with global config before delegating\n */\n async list<T extends Record<string, unknown>>(\n table: TableName,\n options?: QueryOptions<T>,\n operationConfig?: OperationConfig,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n ConfigMerger.mergeConfigs(this.globalConfig, operationConfig);\n\n if (this.eventHandlers?.onBeforeRead) {\n await this.eventHandlers.onBeforeRead({\n type: \"beforeRead\",\n operation: \"READ\",\n table,\n timestamp: new Date(),\n });\n }\n\n const result = await this.adapter.findMany<T>(table, options);\n\n if (result.success && this.eventHandlers?.onAfterRead) {\n await this.eventHandlers.onAfterRead({\n type: \"afterRead\",\n operation: \"READ\",\n table,\n result: (result.value ?? {}) as Record<\n string,\n string | number | boolean | Date\n >,\n duration: 0,\n timestamp: new Date(),\n });\n }\n\n return result;\n }\n\n /**\n * Create a new record\n * Merges operation config with global config before delegating\n */\n async create<T extends Record<string, unknown>>(\n table: TableName,\n input: CreateInput<T>,\n operationConfig?: OperationConfig,\n ): Promise<DatabaseResult<T>> {\n ConfigMerger.mergeConfigs(this.globalConfig, operationConfig);\n\n // Prepare table with schema and ID column overrides\n const finalTable = this.prepareTable(table, operationConfig);\n\n if (this.eventHandlers?.onBeforeWrite) {\n await this.eventHandlers.onBeforeWrite({\n type: \"beforeWrite\",\n operation: \"CREATE\",\n table,\n data: input as Record<string, string | number | boolean | Date>,\n timestamp: new Date(),\n });\n }\n\n const result = await this.adapter.create<T>(finalTable, input as T);\n\n if (result.success && this.eventHandlers?.onAfterWrite) {\n await this.eventHandlers.onAfterWrite({\n type: \"afterWrite\",\n operation: \"CREATE\",\n table,\n result: result.value as Record<\n string,\n string | number | boolean | Date\n >,\n duration: 0,\n timestamp: new Date(),\n });\n }\n\n return result;\n }\n\n /**\n * Update an existing record\n * Merges operation config with global config before delegating\n */\n async update<T extends Record<string, unknown>>(\n table: TableName,\n id: string,\n input: UpdateInput<T>,\n operationConfig?: OperationConfig,\n ): Promise<DatabaseResult<T>> {\n ConfigMerger.mergeConfigs(this.globalConfig, operationConfig);\n\n // Prepare table with schema and ID column overrides\n const finalTable = this.prepareTable(table, operationConfig);\n\n if (this.eventHandlers?.onBeforeWrite) {\n await this.eventHandlers.onBeforeWrite({\n type: \"beforeWrite\",\n operation: \"UPDATE\",\n table,\n data: input as Record<string, string | number | boolean | Date>,\n timestamp: new Date(),\n });\n }\n\n const result = await this.adapter.update<T>(\n finalTable,\n id,\n input as Partial<T>,\n );\n\n if (result.success && this.eventHandlers?.onAfterWrite) {\n await this.eventHandlers.onAfterWrite({\n type: \"afterWrite\",\n operation: \"UPDATE\",\n table,\n result: result.value as Record<\n string,\n string | number | boolean | Date\n >,\n duration: 0,\n timestamp: new Date(),\n });\n }\n\n return result;\n }\n\n /**\n * Delete a record\n * Merges operation config with global config before delegating\n */\n async delete(\n table: TableName,\n id: string,\n operationConfig?: OperationConfig,\n ): Promise<DatabaseResult<void>> {\n ConfigMerger.mergeConfigs(this.globalConfig, operationConfig);\n\n // Prepare table with schema and ID column overrides\n const finalTable = this.prepareTable(table, operationConfig);\n\n if (this.eventHandlers?.onBeforeWrite) {\n await this.eventHandlers.onBeforeWrite({\n type: \"beforeWrite\",\n operation: \"DELETE\",\n table,\n data: { id },\n timestamp: new Date(),\n });\n }\n\n const result = await this.adapter.delete(finalTable, id);\n\n if (result.success && this.eventHandlers?.onAfterWrite) {\n await this.eventHandlers.onAfterWrite({\n type: \"afterWrite\",\n operation: \"DELETE\",\n table,\n result: {},\n duration: 0,\n timestamp: new Date(),\n });\n }\n\n return result;\n }\n\n // Batch Operations\n async batchCreate<T extends Record<string, unknown>>(\n table: TableName,\n inputs: CreateInput<T>[],\n operationConfig?: OperationConfig,\n ): Promise<DatabaseResult<T[]>> {\n // TODO: Implement batch operations\n const results: T[] = [];\n for (const input of inputs) {\n const result = await this.create<T>(table, input, operationConfig);\n if (result.success && result.value) {\n results.push(result.value);\n } else {\n return failure(\n result.error ??\n new DatabaseError(\n \"Batch create failed\",\n DATABASE_ERROR_CODES.CREATE_FAILED,\n {\n context: { source: \"batchCreate\" },\n cause: new Error(\"Batch create failed\"),\n },\n ),\n );\n }\n }\n return success(results);\n }\n\n async batchUpdate<T extends Record<string, unknown>>(\n table: TableName,\n updates: BatchUpdate<T>[],\n operationConfig?: OperationConfig,\n ): Promise<DatabaseResult<T[]>> {\n const results: T[] = [];\n for (const update of updates) {\n const result = await this.update<T>(\n table,\n update.id,\n update.data,\n operationConfig,\n );\n if (result.success && result.value) {\n results.push(result.value);\n } else {\n return failure(\n result.error ??\n new DatabaseError(\n \"Batch update failed\",\n DATABASE_ERROR_CODES.UPDATE_FAILED,\n {\n context: { source: \"batchUpdate\" },\n cause: new Error(\"Batch update failed\"),\n },\n ),\n );\n }\n }\n return success(results);\n }\n\n async batchDelete(\n table: TableName,\n ids: string[],\n operationConfig?: OperationConfig,\n ): Promise<DatabaseResult<void>> {\n for (const id of ids) {\n const result = await this.delete(table, id, operationConfig);\n if (!result.success) {\n return failure(\n result.error ??\n new DatabaseError(\n \"Batch delete failed\",\n DATABASE_ERROR_CODES.DELETE_FAILED,\n {\n context: { source: \"batchDelete\" },\n cause: new Error(\"Batch delete failed\"),\n },\n ),\n );\n }\n }\n return success();\n }\n\n // Query Operations\n async query<T extends Record<string, unknown>>(\n table: TableName,\n query: QueryOptions<T>,\n operationConfig?: OperationConfig,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n return this.list<T>(table, query, operationConfig);\n }\n\n async count<T extends Record<string, unknown> = Record<string, unknown>>(\n table: TableName,\n filter?: Filter<T>,\n operationConfig?: OperationConfig,\n ): Promise<DatabaseResult<number>> {\n ConfigMerger.mergeConfigs(this.globalConfig, operationConfig);\n return this.adapter.count(table, filter);\n }\n\n // Transactions\n async transaction<T>(fn: TransactionFn<T>): Promise<DatabaseResult<T>> {\n return this.adapter.transaction(fn);\n }\n\n // Audit Context\n async setAuditContext(context: AuditContext): Promise<DatabaseResult<void>> {\n this.auditContext = { ...this.auditContext, ...context };\n return success();\n }\n\n // Event System\n on<T extends DatabaseEvent[\"type\"]>(\n event: T,\n handler: (\n event: Extract<DatabaseEvent, { type: T }>,\n ) => void | Promise<void>,\n ): void {\n this.eventEmitter.on(event, handler);\n }\n\n off<T extends DatabaseEvent[\"type\"]>(\n event: T,\n handler: (\n event: Extract<DatabaseEvent, { type: T }>,\n ) => void | Promise<void>,\n ): void {\n this.eventEmitter.off(event, handler);\n }\n\n // Health & Status\n async healthCheck(): Promise<DatabaseResult<DatabaseHealthStatus>> {\n return this.healthManager.checkHealth();\n }\n\n getStatus(): ServiceStatus {\n const uptime = Date.now() - this.startTime.getTime();\n return {\n isHealthy: true, // TODO: Get actual health status\n adapter: this.adapter.constructor.name,\n uptime,\n lastHealthCheck: new Date(),\n };\n }\n\n // Legacy methods for backward compatibility\n async findById<T extends Record<string, unknown>>(\n table: string,\n id: string,\n ): Promise<DatabaseResult<T | null>> {\n return this.get<T>(table, id);\n }\n\n async findMany<T extends Record<string, unknown>>(\n table: string,\n options?: QueryOptions<T>,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n return this.list<T>(table, options);\n }\n\n async initialize(): Promise<DatabaseResult<void>> {\n return success();\n }\n\n /**\n * Registers a table with the underlying adapter.\n *\n * @param name - Logical table name (e.g., 'users')\n * @param table - Physical table name or Drizzle table object\n * @param idColumn - ID column name (defaults to 'id')\n *\n * @example SQL Adapter\n * ```typescript\n * db.registerTable('users', 'users', 'id');\n * db.registerTable('feature_flags', 'feature_flags', 'key');\n * ```\n *\n * @example Drizzle Adapter (requires PgTable objects)\n * ```typescript\n * db.registerTable('users', usersTable, usersTable.id);\n * ```\n */\n registerTable<TTable = string, TIdColumn = string>(\n name: string,\n table?: TTable,\n idColumn?: TIdColumn,\n ): void {\n // Delegate to the adapter's registerTable method\n if (this.adapter && typeof this.adapter.registerTable === \"function\") {\n // For SQL adapter: if table is not provided, use name as table name\n const tableValue = table ?? name;\n this.adapter.registerTable(name, tableValue, idColumn);\n }\n }\n\n async exists(table: string, id: string): Promise<DatabaseResult<boolean>> {\n const result = await this.get(table, id);\n return success(result.success && result.value !== null);\n }\n\n private async fireBeforeReadEvent(table: TableName): Promise<void> {\n if (this.eventHandlers?.onBeforeRead) {\n await this.eventHandlers.onBeforeRead({\n type: \"beforeRead\",\n operation: \"READ\",\n table,\n timestamp: new Date(),\n });\n }\n }\n\n private async fireAfterReadEvent<T>(\n table: TableName,\n record: T | null,\n ): Promise<void> {\n if (this.eventHandlers?.onAfterRead) {\n await this.eventHandlers.onAfterRead({\n type: \"afterRead\",\n operation: \"READ\",\n table,\n result:\n (record as Record<string, string | number | boolean | Date>) ?? {},\n duration: 0,\n timestamp: new Date(),\n });\n }\n }\n\n async findOne<T extends Record<string, unknown>>(\n table: TableName,\n filter: Filter<T>,\n operationConfig?: OperationConfig,\n ): Promise<DatabaseResult<T | null>> {\n ConfigMerger.mergeConfigs(this.globalConfig, operationConfig);\n\n try {\n await this.fireBeforeReadEvent(table);\n\n const result = await this.adapter.findMany<T>(table, {\n filter,\n pagination: { limit: 1, offset: 0 },\n });\n\n if (!result.success) {\n return { success: false, error: result.error };\n }\n\n const firstRecord = result.value?.data[0] ?? null;\n await this.fireAfterReadEvent(table, firstRecord);\n\n return { success: true, value: firstRecord };\n } catch (error) {\n return failure(\n new DatabaseError(\n `Find one operation failed: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n {\n context: { source: \"findOne\" },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n async softDelete(\n table: TableName,\n id: string,\n operationConfig?: OperationConfig,\n ): Promise<DatabaseResult<void>> {\n ConfigMerger.mergeConfigs(this.globalConfig, {\n ...operationConfig,\n softDelete: { enabled: true },\n });\n\n try {\n if (this.eventHandlers?.onBeforeWrite) {\n await this.eventHandlers.onBeforeWrite({\n type: \"beforeWrite\",\n operation: \"DELETE\",\n table,\n data: { id, softDelete: true },\n timestamp: new Date(),\n });\n }\n\n const result = await this.adapter.delete(table, id);\n\n if (result.success && this.eventHandlers?.onAfterWrite) {\n await this.eventHandlers.onAfterWrite({\n type: \"afterWrite\",\n operation: \"DELETE\",\n table,\n result: { softDeleted: true },\n duration: 0,\n timestamp: new Date(),\n });\n }\n\n return result;\n } catch (error) {\n return failure(\n new DatabaseError(\n `Soft delete operation failed: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.DELETE_FAILED,\n {\n context: { source: \"softDelete\" },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n get events(): DatabaseEventEmitter {\n return this.eventEmitter;\n }\n\n /**\n * 🔌 Close the database connection\n *\n * Gracefully shuts down the database connection and releases all resources.\n * Should be called when the service is no longer needed.\n *\n * @returns Promise resolving to DatabaseResult indicating success or failure\n */\n async close(): Promise<DatabaseResult<void>> {\n try {\n if (this.adapter.close) {\n return await this.adapter.close();\n }\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to close database connection: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.DISCONNECT_FAILED,\n {\n context: { source: \"close\" },\n cause: error as Error,\n },\n ),\n );\n }\n }\n}\n","/**\n * @fileoverview Pagination Utilities for @plyaz/db package\n *\n * This module provides pagination calculation utilities used across all database adapters\n * to generate consistent pagination metadata for query results. Supports offset-based\n * pagination with page calculation and validation.\n *\n * Part of the @plyaz/db package - a TypeScript database abstraction layer with\n * support for multiple adapters (Drizzle, Supabase, SQL), extensions (audit, encryption,\n * soft delete), and advanced features (caching, read replicas, multi-tenancy).\n *\n * @module pagination\n */\n\nimport type { PaginationInfo, PaginationOptions } from \"@plyaz/types\";\nimport { isNumber } from \"./typeGuards\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\n\n/**\n * Validates pagination input parameters for safety and consistency\n *\n * Performs comprehensive validation of pagination parameters to prevent invalid\n * calculations and ensure consistent behavior across all database adapters.\n *\n * **Validation Rules:**\n * - Total must be a non-negative number (>= 0)\n * - Limit must be a positive number (> 0) if provided\n * - Offset must be a non-negative number (>= 0)\n *\n * @private\n * @param {number} total - Total number of items in the dataset\n * @param {number} [limit] - Optional maximum number of items per page\n * @param {number} [offset] - Optional number of items to skip (default: 0)\n * @throws {Error} If any parameter fails validation\n *\n * @example\n * ```typescript\n * // Valid inputs\n * validatePaginationInputs(100, 20, 0); // ✓ Valid\n * validatePaginationInputs(0, 10, 0); // ✓ Valid (empty dataset)\n * validatePaginationInputs(50); // ✓ Valid (no pagination)\n *\n * // Invalid inputs\n * validatePaginationInputs(-1, 10, 0); // ✗ Throws: negative total\n * validatePaginationInputs(100, 0, 0); // ✗ Throws: zero limit\n * validatePaginationInputs(100, 10, -5); // ✗ Throws: negative offset\n * ```\n *\n */\nfunction validatePaginationInputs(\n total: number,\n limit?: number,\n offset?: number,\n): void {\n // Total count validation\n // Must be non-negative to represent valid dataset size\n if (!isNumber(total) || total < 0) {\n throw new DatabaseError(\n \"Total must be a non-negative number\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"validatePaginationInputs\" },\n cause: new Error(\"Total must be a non-negative number\"),\n },\n );\n }\n\n // Limit validation (if provided)\n // Must be positive to create meaningful pages\n if (limit !== undefined && (!isNumber(limit) || limit <= 0)) {\n throw new DatabaseError(\n \"Limit must be a positive number\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"validatePaginationInputs\" },\n cause: new Error(\"Limit must be a positive number\"),\n },\n );\n }\n\n // Offset validation\n // Must be non-negative to represent valid starting position\n if (!isNumber(offset) || offset < 0) {\n throw new DatabaseError(\n \"Offset must be a non-negative number\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"validatePaginationInputs\" },\n cause: new Error(\"Offset must be a non-negative number\"),\n },\n );\n }\n}\n\n/**\n * Calculates comprehensive pagination metadata for database query results\n *\n * Generates pagination information used by all database adapters to provide\n * consistent pagination metadata in query results. Supports both paginated\n * and non-paginated queries with automatic page calculation.\n *\n * **Used by:**\n * - DrizzleAdapter.findMany() for ORM-based pagination\n * - SupabaseAdapter.findMany() for Supabase pagination\n * - SQLAdapter.findMany() for raw SQL pagination\n * - All repository methods that return paginated results\n *\n * **Calculation Logic:**\n * - Page numbers are 1-based (first page = 1)\n * - Current page = floor(offset / limit) + 1\n * - Total pages = ceil(total / limit)\n * - Handles edge cases (no limit, empty results, etc.)\n *\n * @param {number} total - Total number of items matching the query\n * @param {PaginationOptions} [options] - Optional pagination configuration\n * @param {number} [options.limit] - Maximum items per page\n * @param {number} [options.offset] - Number of items to skip (default: 0)\n * @returns {PaginationInfo} Complete pagination metadata object\n *\n * @example\n * ```typescript\n * import { calculatePagination } from '@plyaz/db/utils';\n *\n * // Standard pagination (page 2 of 20 items per page)\n * const pagination1 = calculatePagination(100, { limit: 20, offset: 20 });\n * console.log(pagination1);\n * // {\n * // page: 2,\n * // limit: 20,\n * // offset: 20,\n * // totalPages: 5\n * // }\n *\n * // First page\n * const pagination2 = calculatePagination(100, { limit: 20, offset: 0 });\n * console.log(pagination2);\n * // {\n * // page: 1,\n * // limit: 20,\n * // offset: 0,\n * // totalPages: 5\n * // }\n *\n * // No pagination (return all results)\n * const pagination3 = calculatePagination(100);\n * console.log(pagination3);\n * // {\n * // page: undefined,\n * // limit: undefined,\n * // offset: 0,\n * // totalPages: undefined\n * // }\n * ```\n *\n */\nexport function calculatePagination(\n total: number,\n options?: PaginationOptions,\n): PaginationInfo {\n const limit = options?.limit;\n const offset = options?.offset ?? 0;\n\n // Validate all inputs before calculation\n validatePaginationInputs(total, limit, offset);\n\n // Calculate current page (1-based indexing)\n // Only calculate if limit is provided and positive\n // Formula: floor(offset / limit) + 1\n // Example: offset=20, limit=10 → floor(20/10) + 1 = 3 (page 3)\n const page = limit && limit > 0 ? Math.floor(offset / limit) + 1 : undefined;\n\n // Calculate total number of pages\n // Only calculate if limit is provided and positive\n // Formula: ceil(total / limit)\n // Example: total=95, limit=10 → ceil(95/10) = 10 pages\n const totalPages = limit && limit > 0 ? Math.ceil(total / limit) : undefined;\n\n return {\n page,\n limit,\n offset,\n totalPages,\n };\n}\n","/**\n * @fileoverview Centralized Regex Patterns for @plyaz/db package\n *\n * This module contains all regex patterns used throughout the database package.\n * Centralizing regex patterns improves maintainability, reusability, and consistency.\n *\n * Part of the @plyaz/db package - a TypeScript database abstraction layer with\n * support for multiple adapters (Drizzle, Supabase, SQL), extensions (audit, encryption,\n * soft delete), and advanced features (caching, read replicas, multi-tenancy).\n *\n */\n\n/**\n * Database field and table name validation patterns\n * Used for SQL injection prevention and database identifier validation\n */\nexport const DATABASE_PATTERNS = {\n /**\n * Validates database field names (columns)\n * - Must start with letter (a-z, A-Z) or underscore (_)\n * - Can contain letters, numbers, and underscores\n * - Prevents SQL injection through field names\n *\n * Used in: validation.ts, sql.ts, DrizzleAdapter.ts, SQLAdapter.ts\n */\n FIELD_NAME: /^[a-zA-Z_][a-zA-Z0-9_]*$/,\n\n /**\n * Validates database table names\n * - Same rules as field names for consistency\n * - Follows SQL identifier naming conventions\n *\n * Used in: validation.ts, CacheEvict.decorator.ts\n */\n TABLE_NAME: /^[a-zA-Z_][a-zA-Z0-9_]*$/,\n} as const;\n\n/**\n * Cache key validation patterns\n * Used for validating cache keys and patterns in caching system\n */\nexport const CACHE_PATTERNS = {\n /**\n * Validates cache keys\n * - Allows letters, numbers, colons, underscores, and hyphens\n * - Used for Redis cache key validation\n *\n * Used in: CacheEvict.decorator.ts\n */\n CACHE_KEY: /^[a-zA-Z0-9:_-]+$/,\n\n /**\n * Validates cache patterns (with wildcards)\n * - Same as cache key but allows asterisk (*) for wildcards\n * - Used for cache pattern matching and eviction\n *\n * Used in: CacheEvict.decorator.ts\n */\n CACHE_PATTERN: /^[a-zA-Z0-9:_*-]+$/,\n} as const;\n\n/**\n * SQL query sanitization patterns\n * Used for cleaning and normalizing SQL queries for metrics and logging\n */\nexport const SQL_PATTERNS = {\n /**\n * Matches PostgreSQL parameter placeholders ($1, $2, etc.)\n * - Used to normalize parameterized queries for metrics\n *\n * Used in: MetricsCollector.ts\n */\n POSTGRES_PARAMS: /\\$\\d+/g,\n\n /**\n * Matches numeric values in SQL queries\n * - Used to replace numbers with placeholders for query normalization\n *\n * Used in: MetricsCollector.ts\n */\n NUMERIC_VALUES: /\\d+/g,\n\n /**\n * Matches string literals in SQL queries (single quotes)\n * - Used to replace string values with placeholders\n *\n * Used in: MetricsCollector.ts\n */\n STRING_LITERALS: /'[^']*'/g,\n} as const;\n\n/**\n * Input sanitization patterns\n * Used for cleaning user input and preventing injection attacks\n */\nexport const SANITIZATION_PATTERNS = {\n /**\n * Matches dangerous characters for SQL injection prevention\n * - Null byte, backspace, tab, newline, carriage return\n * - Single and double quotes, backslashes, percent signs\n *\n * Used in: validation.ts (sanitizeInput function)\n */\n DANGEROUS_CHARS: /[\\0\\b\\t\\n\\r\"'\\\\%]/g,\n\n /**\n * Matches shell metacharacters for command injection prevention\n * - Semicolon, ampersand, pipe, backtick, dollar, parentheses, etc.\n *\n * Used in: BackupService.ts (sanitizeCommand function)\n */\n SHELL_METACHARACTERS: /[;&|`$(){}[\\]<>\"'\\\\]/g,\n\n /**\n * Matches multiple whitespace characters\n * - Used to normalize whitespace in sanitized input\n *\n * Used in: BackupService.ts\n */\n MULTIPLE_WHITESPACE: /\\s+/g,\n\n /**\n * Matches line breaks and tabs\n * - Used to replace line breaks with spaces\n *\n * Used in: BackupService.ts\n */\n LINE_BREAKS_TABS: /[\\r\\n\\t]/g,\n\n /**\n * Matches Unicode control characters\n * - Uses Unicode property escape to match all control characters\n *\n * Used in: BackupService.ts\n */\n CONTROL_CHARACTERS: /[\\p{Cc}]/gu,\n} as const;\n\n/**\n * File and path patterns\n * Used for file operations and path validation\n */\nexport const FILE_PATTERNS = {\n /**\n * Matches colon and dot characters in timestamps\n * - Used to create filesystem-safe timestamps\n *\n * Used in: BackupService.ts (timestamp generation)\n */\n TIMESTAMP_CHARS: /[:.]/g,\n} as const;\n\n/**\n * Utility functions for common regex operations\n */\nexport const DB_REGEX = {\n /**\n * Tests if a string matches the database field name pattern\n * @param fieldName - The field name to validate\n * @returns True if valid database field name\n */\n isValidFieldName: (fieldName: string): boolean => {\n return DATABASE_PATTERNS.FIELD_NAME.test(fieldName);\n },\n\n /**\n * Tests if a string matches the database table name pattern\n * @param tableName - The table name to validate\n * @returns True if valid database table name\n */\n isValidTableName: (tableName: string): boolean => {\n return DATABASE_PATTERNS.TABLE_NAME.test(tableName);\n },\n\n /**\n * Tests if a string matches the cache key pattern\n * @param cacheKey - The cache key to validate\n * @returns True if valid cache key\n */\n isValidCacheKey: (cacheKey: string): boolean => {\n return CACHE_PATTERNS.CACHE_KEY.test(cacheKey);\n },\n\n /**\n * Tests if a string matches the cache pattern (with wildcards)\n * @param cachePattern - The cache pattern to validate\n * @returns True if valid cache pattern\n */\n isValidCachePattern: (cachePattern: string): boolean => {\n return CACHE_PATTERNS.CACHE_PATTERN.test(cachePattern);\n },\n\n /**\n * Normalizes SQL query by replacing parameters and values with placeholders\n * @param query - The SQL query to normalize\n * @returns Normalized query string\n */\n normalizeSqlQuery: (query: string): string => {\n return query\n .replace(SQL_PATTERNS.POSTGRES_PARAMS, \"?\")\n .replace(SQL_PATTERNS.NUMERIC_VALUES, \"?\")\n .replace(SQL_PATTERNS.STRING_LITERALS, \"?\");\n },\n\n /**\n * Sanitizes input by escaping dangerous characters\n * @param input - The input string to sanitize\n * @param escapeMap - Map of characters to their escaped equivalents\n * @returns Sanitized string\n */\n sanitizeDangerousChars: (\n input: string,\n escapeMap: Record<string, string>,\n ): string => {\n return input.replace(\n SANITIZATION_PATTERNS.DANGEROUS_CHARS,\n (char) => escapeMap[char] || char,\n );\n },\n\n /**\n * Creates filesystem-safe timestamp string\n * @param timestamp - ISO timestamp string\n * @returns Filesystem-safe timestamp\n */\n createSafeTimestamp: (timestamp: string): string => {\n return timestamp.replace(FILE_PATTERNS.TIMESTAMP_CHARS, \"-\");\n },\n\n /**\n * Sanitizes command string by removing shell metacharacters\n * @param command - Command string to sanitize\n * @returns Sanitized command string\n */\n sanitizeCommand: (command: string): string => {\n return command\n .replace(SANITIZATION_PATTERNS.SHELL_METACHARACTERS, \"\")\n .replace(SANITIZATION_PATTERNS.MULTIPLE_WHITESPACE, \" \")\n .trim();\n },\n\n /**\n * Sanitizes log message by normalizing whitespace and removing control characters\n * @param message - Log message to sanitize\n * @returns Sanitized log message\n */\n sanitizeLogMessage: (message: string): string => {\n return message\n .replace(SANITIZATION_PATTERNS.LINE_BREAKS_TABS, \" \")\n .replace(SANITIZATION_PATTERNS.CONTROL_CHARACTERS, \"\")\n .trim();\n },\n} as const;\n","import { drizzle } from \"drizzle-orm/node-postgres\";\nimport type { PoolClient } from \"pg\";\nimport { Pool } from \"pg\";\nimport type {\n Column,\n ColumnBaseConfig,\n ColumnDataType,\n SQL,\n SQLWrapper,\n} from \"drizzle-orm\";\nimport {\n eq,\n not,\n gte,\n gt,\n lte,\n lt,\n inArray,\n like,\n between,\n isNull,\n isNotNull,\n asc,\n desc,\n sql,\n} from \"drizzle-orm\";\nimport type { PgTable, PgSelectBase } from \"drizzle-orm/pg-core\";\nimport { PgColumn } from \"drizzle-orm/pg-core\";\nimport { calculatePagination } from \"@utils/pagination\";\nimport type {\n DrizzleAdapterConfig,\n DatabaseAdapterType,\n DatabaseResult,\n PaginatedResult,\n QueryOptions,\n DatabaseHealthStatus,\n Filter,\n Transaction,\n SortOptions,\n} from \"@plyaz/types/db\";\nimport { failure, success } from \"@utils/databaseResultHelpers\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { isNonEmptyString, isObject } from \"@utils/typeGuards\";\nimport { DATABASE_ERROR_CODES, type ErrorCodeValue } from \"@plyaz/types/errors\";\nimport { DB_REGEX } from \"@utils/regex\";\nimport type { BuildWhereClauseOptions } from \"@plyaz/types/db\";\n\n/** Minimum elements required for BETWEEN clause */\nconst BETWEEN_MIN_ELEMENTS = 2;\n\n/**\n * @class DrizzleAdapter\n * @implements {DatabaseAdapterType}\n * @classdesc\n * A PostgreSQL database adapter built on top of Drizzle ORM.\n * Provides generic CRUD operations, pagination, filtering, sorting,\n * and transactional support with a consistent result structure.\n */\nexport class DrizzleAdapter implements DatabaseAdapterType {\n private db: ReturnType<typeof drizzle>;\n private pool: Pool;\n private config: DrizzleAdapterConfig;\n private tableMap: Map<string, PgTable> = new Map();\n private idColumnMap: Map<string, PgColumn> = new Map();\n // String-based table registry for auto-registration (fallback when no PgTable schema)\n private stringTableMap: Map<string, string> = new Map();\n private stringIdColumnMap: Map<string, string> = new Map();\n private configIdColumns: Record<string, string>;\n\n /**\n * Creates a new DrizzleAdapter instance.\n * @param {DrizzleAdapterConfig} config - Configuration object for Drizzle and PostgreSQL connection.\n * @description\n * Initializes the adapter with the provided configuration, setting up the connection pool\n * and creating a Drizzle ORM instance. The configuration should include a connection string\n * and optional pool settings such as min/max connections and idle timeout.\n */\n constructor(config: DrizzleAdapterConfig) {\n this.config = config;\n this.pool = new Pool({\n connectionString: config.connectionString,\n ...config.pool,\n });\n this.db = drizzle(this.pool);\n // Store custom ID column mappings from config\n this.configIdColumns = config.tableIdColumns ?? {};\n }\n\n /**\n * Initializes the adapter by verifying database connectivity.\n * @returns {Promise<DatabaseResult<void>>} Success or failure result.\n * @description\n * Attempts to establish a connection to the database to verify that the adapter\n * can communicate with the database. This is typically called during application startup\n * to ensure the database is accessible before performing any operations.\n * Returns a success result if the connection is established, or a failure result with an error\n * if the connection cannot be established.\n */\n async initialize(): Promise<DatabaseResult<void>> {\n let client;\n try {\n client = await this.pool.connect();\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to initialize Drizzle adapter: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.INIT_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.initialize\",\n },\n cause: error as Error,\n },\n ),\n );\n } finally {\n if (client) {\n client.release();\n }\n }\n }\n\n /**\n * Opens a new connection to the database.\n * @returns {Promise<void>}\n * @description\n * Establishes a connection to the PostgreSQL database using the connection pool.\n * This method is called to ensure that a connection is available before performing database operations.\n * The connection pool manages the connections efficiently, reusing them when possible.\n */\n async connect(): Promise<void> {\n try {\n const client = await this.pool.connect();\n client.release();\n } catch (error) {\n throw new DatabaseError(\n `Failed to connect to database: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.CONNECT_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.connect\",\n },\n cause: error as Error,\n },\n );\n }\n }\n\n /**\n * Closes all open connections and shuts down the connection pool.\n * @returns {Promise<void>}\n * @description\n * Gracefully shuts down the connection pool, closing all active connections.\n * This method should be called when the adapter is no longer needed, typically during\n * application shutdown, to free up database resources and prevent connection leaks.\n */\n async disconnect(): Promise<void> {\n try {\n await this.pool.end();\n } catch (error) {\n throw new DatabaseError(\n `Failed to disconnect from database: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.DISCONNECT_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.disconnect\",\n },\n cause: error as Error,\n },\n );\n }\n }\n\n /**\n * Closes the database connection and cleanup resources.\n * @returns Promise resolving to DatabaseResult indicating success or failure.\n */\n async close(): Promise<DatabaseResult<void>> {\n try {\n await this.disconnect();\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to close connection: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.DISCONNECT_FAILED,\n ),\n );\n }\n }\n\n /**\n * Gets the underlying Drizzle client instance.\n * @returns {TClient} The internal Drizzle client.\n * @description\n * This method exposes the internal Drizzle client instance. Direct access is discouraged\n * to maintain abstraction and ensure all database operations go through the adapter’s\n * interface for error handling, logging, and event emission.\n */\n getClient<TClient extends object = object>(): TClient {\n return this.db as TClient;\n }\n\n /**\n * Executes a raw SQL query.\n * @template T - The expected type of the query result rows.\n * @param {string} sql - Raw SQL query string.\n * @param {T[]} [params] - Optional query parameters.\n * @returns {Promise<T[]>} Array of query result rows.\n * @throws {DatabaseError} When query execution fails.\n * @description\n * Executes a raw SQL query against the database, with optional parameterization.\n * This method is useful for complex queries that cannot be easily expressed using the ORM\n * or for database-specific operations. The method uses parameterized queries to prevent\n * SQL injection attacks. If the query execution fails, a DatabaseError is thrown.\n */\n async query<T>(sql: string, params?: T[]): Promise<T[]> {\n try {\n // Validate SQL to prevent injection\n if (!isNonEmptyString(sql)) {\n throw new DatabaseError(\n \"Invalid SQL query\",\n DATABASE_ERROR_CODES.INVALID_SQL,\n );\n }\n\n const result = await this.pool.query(sql, params);\n return result.rows as T[];\n } catch (error) {\n throw new DatabaseError(\n `Failed to execute query: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.query\",\n },\n cause: error as Error,\n },\n );\n }\n }\n\n /**\n * Registers a table and optional ID column for ORM operations.\n * @template TTable - Type representing the table structure (PgTable or string).\n * @template TIdColumn - Type representing the ID column (PgColumn or string).\n * @param {string} name - Logical name of the table.\n * @param {TTable} table - Drizzle table object (PgTable) or string table name.\n * @param {TIdColumn} [idColumn] - Optional primary key column (PgColumn or string).\n * @description\n * Registers a table with the adapter, allowing it to be referenced by a logical name\n * in subsequent operations. This is necessary for the adapter to perform ORM operations\n * on the table. The ID column can also be specified if it differs from the default 'id'.\n *\n * **Supports two modes:**\n * 1. **PgTable mode**: Pass Drizzle schema objects for type-safe ORM operations\n * 2. **String mode**: Pass string table names for raw SQL fallback (auto-registration)\n *\n * This registration enables the adapter to map logical table names to actual table objects\n * and ID columns, providing a layer of abstraction between the application and the database schema.\n */\n registerTable<TTable, TIdColumn>(\n name: string,\n table: TTable,\n idColumn?: TIdColumn,\n ): void {\n try {\n if (!isNonEmptyString(name)) {\n throw new DatabaseError(\n \"Invalid table name\",\n DATABASE_ERROR_CODES.INVALID_TABLE_NAME,\n );\n }\n\n // Check if table is a PgTable (Drizzle schema) or a string (raw SQL mode)\n if (typeof table === \"string\") {\n // String mode: register for raw SQL operations\n this.stringTableMap.set(name, table);\n if (idColumn && typeof idColumn === \"string\") {\n this.stringIdColumnMap.set(name, idColumn);\n }\n } else {\n // PgTable mode: register for Drizzle ORM operations\n this.tableMap.set(name, table as PgTable);\n if (idColumn) {\n this.idColumnMap.set(name, idColumn as TIdColumn as PgColumn);\n }\n }\n } catch (error) {\n throw new DatabaseError(\n `Failed to register table: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.TABLE_REGISTRATION_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.registerTable\",\n },\n cause: error as Error,\n },\n );\n }\n }\n\n /**\n * Execute raw SQL findById query\n */\n private async rawSqlFindById<T>(\n table: string,\n id: string,\n ): Promise<T | null> {\n const tableName = this.getStringTableName(table);\n const idColumn = this.getStringIdColumn(table);\n const sqlQuery = `SELECT * FROM \"${tableName}\" WHERE \"${idColumn}\" = $1 LIMIT 1`;\n const result = await this.pool.query(sqlQuery, [id]);\n return (result.rows[0] as T) || null;\n }\n\n /**\n * Finds a record by its primary ID.\n * @template T - The expected type of the record.\n * @param {string} table - Table name.\n * @param {string} id - Record ID.\n * @returns {Promise<DatabaseResult<T | null>>} Found record or null.\n * @description\n * Retrieves a single record from the specified table using its primary ID.\n * The method uses the registered table and ID column to construct the query.\n * If the record is found, it is returned in a success result. If no record is found,\n * null is returned in a success result. If an error occurs during the operation,\n * a failure result with an error message is returned.\n *\n * **Auto-registers tables**: If table is not registered with PgTable schema,\n * falls back to raw SQL mode (same behavior as SQLAdapter).\n */\n async findById<T>(\n table: string,\n id: string,\n ): Promise<DatabaseResult<T | null>> {\n try {\n // Check if we should use raw SQL mode\n if (this.isStringMode(table)) {\n return success(await this.rawSqlFindById<T>(table, id));\n }\n\n // Use Drizzle ORM mode\n const tableObj = this.getTable(table);\n const idColumn = this.getIdColumn(table);\n const result = await this.db\n .select()\n .from(tableObj)\n .where(eq(idColumn, id))\n .limit(1);\n return success((result[0] as T) || null);\n } catch (error) {\n // If error is USE_STRING_MODE, retry with raw SQL\n if (\n error instanceof DatabaseError &&\n error.message === \"USE_STRING_MODE\"\n ) {\n return this.handleStringModeFallback<T | null>(\n () => this.rawSqlFindById<T>(table, id),\n table,\n \"DrizzleAdapter.findById\",\n DATABASE_ERROR_CODES.FIND_BY_ID_FAILED,\n );\n }\n return failure(\n new DatabaseError(\n `Failed to find by id in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.FIND_BY_ID_FAILED,\n {\n context: { source: \"DrizzleAdapter.findById\" },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Handle USE_STRING_MODE fallback with error wrapping\n */\n private async handleStringModeFallback<T>(\n operation: () => Promise<T>,\n table: string,\n source: string,\n errorCode: ErrorCodeValue,\n ): Promise<DatabaseResult<T>> {\n try {\n return success(await operation());\n } catch (sqlError) {\n return failure(\n new DatabaseError(\n `Failed operation on table ${table}: ${(sqlError as Error).message}`,\n errorCode,\n {\n context: { source },\n cause: sqlError as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Retrieves multiple records with optional filtering, sorting, and pagination.\n * @template T - The expected type of the records.\n * @param {string} table - Table name.\n * @param {QueryOptions} [options] - Optional filter, sort, and pagination options.\n * @returns {Promise<DatabaseResult<PaginatedResult<T>>>} Paginated result set.\n * @description\n * Retrieves multiple records from the specified table with support for filtering,\n * sorting, and pagination. The method first applies any filters to narrow down the result set,\n * then applies sorting to order the results, and finally applies pagination to limit the number\n * of records returned. The result includes the data array, total count of matching records,\n * and pagination metadata such as current page, total pages, and next/previous cursors.\n * If an error occurs during the operation, a failure result with an error message is returned.\n *\n * **Auto-registers tables**: If table is not registered with PgTable schema,\n * falls back to raw SQL mode (same behavior as SQLAdapter).\n */\n\n // eslint-disable-next-line complexity\n async findMany<T extends Record<string, unknown>>(\n table: string,\n options?: QueryOptions<T>,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n try {\n // Check if we should use raw SQL mode\n if (this.isStringMode(table)) {\n return this.findManyRawSql<T>(table, options);\n }\n\n const tableObj = this.getTable(table);\n\n let query: PgSelectBase<\n string,\n Record<string, PgColumn>,\n \"single\",\n Record<string, \"not-null\">,\n false\n > = this.db.select().from(tableObj);\n\n // Apply sorting\n if (options?.sort) {\n query = this.applySorting(query as never, options.sort, tableObj);\n }\n // Apply filters\n if (options?.filter) {\n const whereClause = this.buildWhereClause(options.filter, tableObj);\n if (whereClause) {\n query = query.where(whereClause) as typeof query;\n }\n }\n\n // Get total count\n let countQuery = this.db\n .select({ count: sql<number>`count(*)::int`.as(\"count\") })\n .from(tableObj);\n if (options?.filter) {\n const whereClause = this.buildWhereClause(options.filter, tableObj);\n if (whereClause)\n countQuery = countQuery.where(whereClause) as typeof countQuery;\n }\n\n const countResult = await countQuery;\n const total = Number(countResult[0].count);\n\n // Apply pagination\n if (options?.pagination) {\n if (options.pagination.offset !== undefined) {\n query = query.offset(options.pagination.offset) as typeof query;\n }\n if (options.pagination.limit !== undefined) {\n query = query.limit(options.pagination.limit) as typeof query;\n }\n }\n\n const data = await query;\n return success({\n data: data as T[],\n total,\n pagination: calculatePagination(total, options?.pagination),\n });\n } catch (error) {\n // If error is USE_STRING_MODE, retry with raw SQL\n if (\n error instanceof DatabaseError &&\n error.message === \"USE_STRING_MODE\"\n ) {\n return this.findManyRawSql<T>(table, options);\n }\n return failure(\n new DatabaseError(\n `Failed to find many in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.FIND_MANY_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.findMany\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Raw SQL fallback for findMany when no PgTable schema is registered.\n * @private\n */\n // eslint-disable-next-line complexity\n private async findManyRawSql<T extends Record<string, unknown>>(\n table: string,\n options?: QueryOptions<T>,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n try {\n const tableName = this.getStringTableName(table);\n const params: unknown[] = [];\n let whereClause = \"\";\n let paramIndex = 1;\n\n // Build WHERE clause\n if (options?.filter) {\n const { field, operator, value } = options.filter;\n whereClause = this.buildSqlWhereClause({\n field,\n operator,\n value,\n params,\n startIndex: paramIndex,\n });\n paramIndex = params.length + 1;\n }\n\n // Count total\n const countSql = `SELECT COUNT(*) as total FROM \"${tableName}\"${whereClause}`;\n const countResult = await this.pool.query(countSql, params);\n const total = Number.parseInt(countResult.rows[0].total);\n\n // ORDER BY clause\n let orderClause = \"\";\n if (options?.sort?.length) {\n orderClause =\n \" ORDER BY \" +\n options.sort\n .map((s) => `\"${s.field}\" ${s.direction.toUpperCase()}`)\n .join(\", \");\n }\n\n // Build main query params (need to copy for separate query)\n const queryParams = [...params];\n\n // LIMIT & OFFSET\n let limitClause = \"\";\n if (options?.pagination?.limit) {\n limitClause += ` LIMIT $${paramIndex++}`;\n queryParams.push(options.pagination.limit);\n }\n if (options?.pagination?.offset) {\n limitClause += ` OFFSET $${paramIndex++}`;\n queryParams.push(options.pagination.offset);\n }\n\n // Final query\n const sqlQuery = `SELECT * FROM \"${tableName}\"${whereClause}${orderClause}${limitClause}`;\n const result = await this.pool.query(sqlQuery, queryParams);\n\n return success({\n data: result.rows as T[],\n total,\n pagination: calculatePagination(total, options?.pagination),\n });\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to find many in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.FIND_MANY_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.findManyRawSql\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Builds a SQL WHERE clause string for raw SQL queries.\n * @private\n */\n // eslint-disable-next-line complexity\n private buildSqlWhereClause(options: BuildWhereClauseOptions): string {\n const { field, operator, value, params, startIndex } = options;\n let clause = \"\";\n\n switch (operator) {\n case \"eq\":\n clause = ` WHERE \"${field}\" = $${startIndex}`;\n params.push(value);\n break;\n case \"ne\":\n clause = ` WHERE \"${field}\" != $${startIndex}`;\n params.push(value);\n break;\n case \"gt\":\n clause = ` WHERE \"${field}\" > $${startIndex}`;\n params.push(value);\n break;\n case \"gte\":\n clause = ` WHERE \"${field}\" >= $${startIndex}`;\n params.push(value);\n break;\n case \"lt\":\n clause = ` WHERE \"${field}\" < $${startIndex}`;\n params.push(value);\n break;\n case \"lte\":\n clause = ` WHERE \"${field}\" <= $${startIndex}`;\n params.push(value);\n break;\n case \"in\":\n if (Array.isArray(value)) {\n const placeholders = value\n .map((_, i) => `$${startIndex + i}`)\n .join(\", \");\n clause = ` WHERE \"${field}\" IN (${placeholders})`;\n params.push(...value);\n }\n break;\n case \"like\":\n clause = ` WHERE \"${field}\" LIKE $${startIndex}`;\n params.push(value);\n break;\n case \"between\":\n if (Array.isArray(value) && value.length >= BETWEEN_MIN_ELEMENTS) {\n clause = ` WHERE \"${field}\" BETWEEN $${startIndex} AND $${startIndex + 1}`;\n params.push(value[0], value[1]);\n }\n break;\n case \"isNull\":\n clause = ` WHERE \"${field}\" IS NULL`;\n break;\n case \"isNotNull\":\n clause = ` WHERE \"${field}\" IS NOT NULL`;\n break;\n default:\n break;\n }\n\n return clause;\n }\n\n /**\n * Inserts a new record into the specified table.\n * @template T - The expected type of the record.\n * @param {string} table - Table name.\n * @param {T} data - Record to insert.\n * @returns {Promise<DatabaseResult<T>>} Inserted record.\n * @description\n * Inserts a new record into the specified table using the provided data.\n * The method uses the registered table to construct the insert query.\n * After insertion, it returns the inserted record with any auto-generated fields\n * (like IDs) populated. If an error occurs during the operation,\n * a failure result with an error message is returned.\n *\n * **Auto-registers tables**: If table is not registered with PgTable schema,\n * falls back to raw SQL mode (same behavior as SQLAdapter).\n */\n async create<T>(table: string, data: T): Promise<DatabaseResult<T>> {\n try {\n // Check if we should use raw SQL mode\n if (this.isStringMode(table)) {\n return this.createRawSql<T>(table, data);\n }\n\n const tableObj = this.getTable(table);\n const result = await this.db\n .insert(tableObj)\n .values(data as Record<string, T>)\n .returning();\n return success(result[0] as T);\n } catch (error) {\n // If error is USE_STRING_MODE, retry with raw SQL\n if (\n error instanceof DatabaseError &&\n error.message === \"USE_STRING_MODE\"\n ) {\n return this.createRawSql<T>(table, data);\n }\n return failure(\n new DatabaseError(\n `Failed to create in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.CREATE_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.create\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Raw SQL fallback for create when no PgTable schema is registered.\n * @private\n */\n private async createRawSql<T>(\n table: string,\n data: T,\n ): Promise<DatabaseResult<T>> {\n try {\n const tableName = this.getStringTableName(table);\n const keys = Object.keys(data as Record<string, unknown>);\n const values = Object.values(data as Record<string, unknown>);\n const placeholders = values.map((_, i) => `$${i + 1}`).join(\", \");\n const escapedKeys = keys.map((k) => `\"${k}\"`).join(\", \");\n\n const sqlQuery = `INSERT INTO \"${tableName}\" (${escapedKeys}) VALUES (${placeholders}) RETURNING *`;\n const result = await this.pool.query(sqlQuery, values);\n\n return success(result.rows[0] as T);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to create in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.CREATE_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.createRawSql\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Updates an existing record by ID.\n * @template T - The expected type of the record.\n * @param {string} table - Table name.\n * @param {string} id - Record ID.\n * @param {Partial<T>} data - Partial object containing fields to update.\n * @returns {Promise<DatabaseResult<T>>} Updated record.\n * @description\n * Updates an existing record in the specified table using its primary ID.\n * Only the fields provided in the data object are updated, allowing for partial updates.\n * The method uses the registered table and ID column to construct the update query.\n * After updating, it returns the updated record. If an error occurs during the operation,\n * a failure result with an error message is returned.\n *\n * **Auto-registers tables**: If table is not registered with PgTable schema,\n * falls back to raw SQL mode (same behavior as SQLAdapter).\n */\n async update<T>(\n table: string,\n id: string,\n data: Partial<T>,\n ): Promise<DatabaseResult<T>> {\n try {\n // Check if we should use raw SQL mode\n if (this.isStringMode(table)) {\n return this.updateRawSql<T>(table, id, data);\n }\n\n const tableObj = this.getTable(table);\n const idColumn = this.getIdColumn(table);\n const result = await this.db\n .update(tableObj)\n .set(data as Record<string, T>)\n .where(eq(idColumn, id))\n .returning();\n return success(result[0] as T);\n } catch (error) {\n // If error is USE_STRING_MODE, retry with raw SQL\n if (\n error instanceof DatabaseError &&\n error.message === \"USE_STRING_MODE\"\n ) {\n return this.updateRawSql<T>(table, id, data);\n }\n return failure(\n new DatabaseError(\n `Failed to update in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.UPDATE_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.update\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Raw SQL fallback for update when no PgTable schema is registered.\n * @private\n */\n private async updateRawSql<T>(\n table: string,\n id: string,\n data: Partial<T>,\n ): Promise<DatabaseResult<T>> {\n try {\n const tableName = this.getStringTableName(table);\n const idColumn = this.getStringIdColumn(table);\n const keys = Object.keys(data as Record<string, unknown>);\n const values = Object.values(data as Record<string, unknown>);\n const setClause = keys.map((key, i) => `\"${key}\" = $${i + 1}`).join(\", \");\n\n const sqlQuery = `UPDATE \"${tableName}\" SET ${setClause} WHERE \"${idColumn}\" = $${keys.length + 1} RETURNING *`;\n const result = await this.pool.query(sqlQuery, [...values, id]);\n\n return success(result.rows[0] as T);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to update in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.UPDATE_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.updateRawSql\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Deletes a record by ID.\n * @param {string} table - Table name.\n * @param {string} id - Record ID.\n * @returns {Promise<DatabaseResult<void>>}\n * @description\n * Deletes a record from the specified table using its primary ID.\n * The method uses the registered table and ID column to construct the delete query.\n * If the operation is successful, it returns a success result with no value.\n * If an error occurs during the operation, a failure result with an error message is returned.\n *\n * **Auto-registers tables**: If table is not registered with PgTable schema,\n * falls back to raw SQL mode (same behavior as SQLAdapter).\n */\n async delete(table: string, id: string): Promise<DatabaseResult<void>> {\n try {\n // Check if we should use raw SQL mode\n if (this.isStringMode(table)) {\n return this.deleteRawSql(table, id);\n }\n\n const tableObj = this.getTable(table);\n const idColumn = this.getIdColumn(table);\n await this.db.delete(tableObj).where(eq(idColumn, id));\n return success();\n } catch (error) {\n // If error is USE_STRING_MODE, retry with raw SQL\n if (\n error instanceof DatabaseError &&\n error.message === \"USE_STRING_MODE\"\n ) {\n return this.deleteRawSql(table, id);\n }\n return failure(\n new DatabaseError(\n `Failed to delete from table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.DELETE_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.delete\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Raw SQL fallback for delete when no PgTable schema is registered.\n * @private\n */\n private async deleteRawSql(\n table: string,\n id: string,\n ): Promise<DatabaseResult<void>> {\n try {\n const tableName = this.getStringTableName(table);\n const idColumn = this.getStringIdColumn(table);\n const sqlQuery = `DELETE FROM \"${tableName}\" WHERE \"${idColumn}\" = $1`;\n await this.pool.query(sqlQuery, [id]);\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to delete from table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.DELETE_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.deleteRawSql\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Executes a transactional operation with rollback on failure.\n * @template T - The expected type of the transaction result.\n * @param {(trx: Transaction) => Promise<T>} callback - Function executed within a transaction.\n * @returns {Promise<DatabaseResult<T>>} Transaction result.\n * @description\n * Executes a callback function within a database transaction, providing atomicity.\n * If the callback function executes successfully, the transaction is committed.\n * If an error occurs during the execution of the callback function, the transaction\n * is rolled back, ensuring that no partial changes are applied to the database.\n * The method returns the result of the callback function if successful,\n * or a failure result with an error message if an error occurs.\n *\n * **Auto-registers tables**: Transaction operations use raw SQL mode for unregistered tables.\n */\n async transaction<T>(\n callback: (trx: Transaction) => Promise<T>,\n ): Promise<DatabaseResult<T>> {\n const client: PoolClient = await this.pool.connect();\n try {\n await client.query(\"BEGIN\");\n const trxDb = drizzle(client);\n\n // Transaction operations that support both PgTable and raw SQL modes\n const trx: Transaction = {\n findById: async <T>(table: string, id: string) => {\n // Use raw SQL for unregistered tables\n if (this.isStringMode(table)) {\n const tableName = this.getStringTableName(table);\n const idColumn = this.getStringIdColumn(table);\n const sqlQuery = `SELECT * FROM \"${tableName}\" WHERE \"${idColumn}\" = $1 LIMIT 1`;\n const result = await client.query(sqlQuery, [id]);\n return success((result.rows[0] as T) || null);\n }\n const tableObj = this.getTable(table);\n const idColumn = this.getIdColumn(table);\n const result = await trxDb\n .select()\n .from(tableObj)\n .where(eq(idColumn, id))\n .limit(1);\n return success((result[0] as T) || null);\n },\n create: async <T>(table: string, data: T) => {\n // Use raw SQL for unregistered tables\n if (this.isStringMode(table)) {\n const tableName = this.getStringTableName(table);\n const keys = Object.keys(data as Record<string, unknown>);\n const values = Object.values(data as Record<string, unknown>);\n const placeholders = values.map((_, i) => `$${i + 1}`).join(\", \");\n const escapedKeys = keys.map((k) => `\"${k}\"`).join(\", \");\n const sqlQuery = `INSERT INTO \"${tableName}\" (${escapedKeys}) VALUES (${placeholders}) RETURNING *`;\n const result = await client.query(sqlQuery, values);\n return success(result.rows[0] as T);\n }\n const tableObj = this.getTable(table);\n const result = await trxDb\n .insert(tableObj)\n .values(data as Record<string, T>)\n .returning();\n return success(result[0] as T);\n },\n update: async <T>(table: string, id: string, data: Partial<T>) => {\n // Use raw SQL for unregistered tables\n if (this.isStringMode(table)) {\n const tableName = this.getStringTableName(table);\n const idColumn = this.getStringIdColumn(table);\n const keys = Object.keys(data as Record<string, unknown>);\n const values = Object.values(data as Record<string, unknown>);\n const setClause = keys\n .map((key, i) => `\"${key}\" = $${i + 1}`)\n .join(\", \");\n const sqlQuery = `UPDATE \"${tableName}\" SET ${setClause} WHERE \"${idColumn}\" = $${keys.length + 1} RETURNING *`;\n const result = await client.query(sqlQuery, [...values, id]);\n return success(result.rows[0] as T);\n }\n const tableObj = this.getTable(table);\n const idColumn = this.getIdColumn(table);\n const result = await trxDb\n .update(tableObj)\n .set(data as Record<string, T>)\n .where(eq(idColumn, id))\n .returning();\n return success(result[0] as T);\n },\n delete: async (table: string, id: string) => {\n // Use raw SQL for unregistered tables\n if (this.isStringMode(table)) {\n const tableName = this.getStringTableName(table);\n const idColumn = this.getStringIdColumn(table);\n const sqlQuery = `DELETE FROM \"${tableName}\" WHERE \"${idColumn}\" = $1`;\n await client.query(sqlQuery, [id]);\n return success();\n }\n const tableObj = this.getTable(table);\n const idColumn = this.getIdColumn(table);\n await trxDb.delete(tableObj).where(eq(idColumn, id));\n return success();\n },\n commit: async () => {\n await client.query(\"COMMIT\");\n },\n rollback: async () => {\n await client.query(\"ROLLBACK\");\n },\n };\n\n const result = await callback(trx);\n await trx.commit();\n return success(result);\n } catch (error) {\n await client.query(\"ROLLBACK\");\n return failure(\n new DatabaseError(\n `Transaction failed: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.TRANSACTION_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.transaction\",\n },\n cause: error as Error,\n },\n ),\n );\n } finally {\n client.release();\n }\n }\n\n /**\n * Checks if a record exists by ID.\n * @param {string} table - Table name.\n * @param {string} id - Record ID.\n * @returns {Promise<DatabaseResult<boolean>>} True if exists, otherwise false.\n * @description\n * Checks if a record with the specified ID exists in the table.\n * The method uses the registered table and ID column to construct the query.\n * It returns a success result with a boolean value indicating whether the record exists.\n * If an error occurs during the operation, a failure result with an error message is returned.\n *\n * **Auto-registers tables**: If table is not registered with PgTable schema,\n * falls back to raw SQL mode (same behavior as SQLAdapter).\n */\n async exists(table: string, id: string): Promise<DatabaseResult<boolean>> {\n try {\n // Check if we should use raw SQL mode\n if (this.isStringMode(table)) {\n const tableName = this.getStringTableName(table);\n const idColumn = this.getStringIdColumn(table);\n const sqlQuery = `SELECT 1 FROM \"${tableName}\" WHERE \"${idColumn}\" = $1 LIMIT 1`;\n const result = await this.pool.query(sqlQuery, [id]);\n return success(result.rows.length > 0);\n }\n\n const tableObj = this.getTable(table);\n const idColumn = this.getIdColumn(table);\n const result = await this.db\n .select({ exists: sql`1` })\n .from(tableObj)\n .where(eq(idColumn, id))\n .limit(1);\n return success(!!result.length);\n } catch (error) {\n // If error is USE_STRING_MODE, retry with raw SQL\n if (\n error instanceof DatabaseError &&\n error.message === \"USE_STRING_MODE\"\n ) {\n const tableName = this.getStringTableName(table);\n const idColumn = this.getStringIdColumn(table);\n const sqlQuery = `SELECT 1 FROM \"${tableName}\" WHERE \"${idColumn}\" = $1 LIMIT 1`;\n const result = await this.pool.query(sqlQuery, [id]);\n return success(result.rows.length > 0);\n }\n return failure(\n new DatabaseError(\n `Failed to check existence in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.EXISTS_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.exists\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Counts records matching an optional filter.\n * @param {string} table - Table name.\n * @param {Filter} [filter] - Optional filter object.\n * @returns {Promise<DatabaseResult<number>>} Total count of matching records.\n * @description\n * Counts the number of records in the specified table that match the optional filter.\n * The method uses the registered table to construct the count query.\n * If a filter is provided, it is applied to narrow down the count to matching records.\n * It returns a success result with the count of matching records.\n * If an error occurs during the operation, a failure result with an error message is returned.\n *\n * **Auto-registers tables**: If table is not registered with PgTable schema,\n * falls back to raw SQL mode (same behavior as SQLAdapter).\n */\n async count<T extends Record<string, unknown> = Record<string, unknown>>(\n table: string,\n filter?: Filter<T>,\n ): Promise<DatabaseResult<number>> {\n try {\n // Check if we should use raw SQL mode\n if (this.isStringMode(table)) {\n return this.countRawSql(table, filter);\n }\n\n const tableObj = this.getTable(table);\n\n const baseQuery = this.db\n .select({ count: sql<number>`count(*)::int` })\n .from(tableObj);\n\n const query =\n filter && this.buildWhereClause(filter, tableObj)\n ? baseQuery.where(this.buildWhereClause(filter, tableObj) as SQL)\n : baseQuery;\n\n const result = await query;\n const countValue = result.length > 0 ? result[0].count : 0;\n\n return success(Number(countValue));\n } catch (error) {\n // If error is USE_STRING_MODE, retry with raw SQL\n if (\n error instanceof DatabaseError &&\n error.message === \"USE_STRING_MODE\"\n ) {\n return this.countRawSql(table, filter);\n }\n return failure(\n new DatabaseError(\n `Failed to count in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.COUNT_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.count\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Raw SQL fallback for count when no PgTable schema is registered.\n * @private\n */\n private async countRawSql<T extends Record<string, unknown>>(\n table: string,\n filter?: Filter<T>,\n ): Promise<DatabaseResult<number>> {\n try {\n const tableName = this.getStringTableName(table);\n const params: unknown[] = [];\n let whereClause = \"\";\n\n if (filter) {\n const { field, operator, value } = filter;\n whereClause = this.buildSqlWhereClause({\n field,\n operator,\n value,\n params,\n startIndex: 1,\n });\n }\n\n const sqlQuery = `SELECT COUNT(*) as count FROM \"${tableName}\"${whereClause}`;\n const result = await this.pool.query(sqlQuery, params);\n const rowCount = Number.parseInt(result.rows[0].count);\n return success(Number(rowCount));\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to count in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.COUNT_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.countRawSql\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Performs a health check on the database connection.\n * @returns {Promise<DatabaseResult<DatabaseHealthStatus>>} Health status with response time.\n * @description\n * Checks the health of the database connection by executing a simple query.\n * The method measures the response time of the query to determine the health status.\n * It returns a success result with a HealthStatus object indicating whether the database is healthy,\n * the response time of the health check, and any additional details.\n * If an error occurs during the operation, a failure result with an error message is returned.\n */\n async healthCheck(): Promise<DatabaseResult<DatabaseHealthStatus>> {\n const startTime = Date.now();\n try {\n await this.pool.query(\"SELECT 1\");\n const responseTime = Date.now() - startTime;\n return success({\n isHealthy: true,\n responseTime,\n details: { adapter: \"drizzle\" } as DatabaseHealthStatus[\"details\"],\n });\n } catch (error) {\n const responseTime = Date.now() - startTime;\n return success({\n isHealthy: false,\n responseTime,\n details: {\n adapter: \"drizzle\",\n error: (error as Error).message,\n } as DatabaseHealthStatus[\"details\"],\n });\n }\n }\n\n // --- Private Helpers ---\n\n /**\n * Checks if a table is registered in string mode (raw SQL fallback).\n * @private\n * @param {string} name - Table name.\n * @returns {boolean} True if table is registered in string mode.\n */\n private isStringMode(name: string): boolean {\n return this.stringTableMap.has(name) || !this.tableMap.has(name);\n }\n\n /**\n * Retrieves a registered table by name.\n * @private\n * @param {string} name - Table name.\n * @returns {PgTable} Table object.\n * @throws {DatabaseError} If table is not registered and cannot be auto-registered.\n * @description\n * Retrieves a table object that has been previously registered with the adapter.\n * If the table is not found in PgTable mode, it auto-registers in string mode\n * for raw SQL operations (same behavior as SQLAdapter).\n */\n private getTable(name: string): PgTable {\n try {\n if (!isNonEmptyString(name)) {\n throw new DatabaseError(\n \"Invalid table name\",\n DATABASE_ERROR_CODES.INVALID_TABLE_NAME,\n );\n }\n\n const table = this.tableMap.get(name);\n if (!table) {\n // Auto-register in string mode for raw SQL fallback\n if (!this.stringTableMap.has(name)) {\n this.stringTableMap.set(name, name);\n }\n // Return a placeholder - actual operations will use raw SQL\n throw new DatabaseError(\n \"USE_STRING_MODE\",\n DATABASE_ERROR_CODES.TABLE_NOT_REGISTERED,\n );\n }\n return table;\n } catch (error) {\n throw error instanceof DatabaseError\n ? error\n : new DatabaseError(\n \"Failed to get table\",\n DATABASE_ERROR_CODES.GET_TABLE_FAILED,\n );\n }\n }\n\n /**\n * Gets the string table name for raw SQL operations.\n * @private\n * @param {string} name - Logical table name.\n * @returns {string} Physical table name.\n */\n private getStringTableName(name: string): string {\n let tableName = this.stringTableMap.get(name);\n if (!tableName) {\n // Auto-register table with same name and check for custom ID column from config\n const customIdColumn = this.configIdColumns[name];\n if (customIdColumn) {\n this.stringIdColumnMap.set(name, customIdColumn);\n }\n this.stringTableMap.set(name, name);\n tableName = name;\n }\n return tableName;\n }\n\n /**\n * Gets the string ID column for raw SQL operations.\n * @private\n * @param {string} name - Logical table name.\n * @returns {string} ID column name (defaults to 'id').\n * @description\n * Retrieves the ID column for a table. Checks in this order:\n * 1. Runtime registered ID column (from registerTable calls)\n * 2. Config-provided ID column (from tableIdColumns in config)\n * 3. Default 'id' column\n */\n private getStringIdColumn(name: string): string {\n // Check runtime registered first\n const runtimeIdColumn = this.stringIdColumnMap.get(name);\n if (runtimeIdColumn) {\n return runtimeIdColumn;\n }\n\n // Check config-provided ID columns\n const configIdColumn = this.configIdColumns[name];\n if (configIdColumn) {\n return configIdColumn;\n }\n\n // Default to 'id'\n return \"id\";\n }\n\n /**\n * Retrieves the registered ID column for a table.\n * @private\n * @param {string} name - Table name.\n * @returns {PgColumn} ID column.\n * @throws {DatabaseError} If ID column is not registered.\n * @description\n * Retrieves the ID column that has been previously registered for a table.\n * This method is used internally by other methods to ensure that operations that require\n * the ID column can access it. If the ID column is not found, it throws a DatabaseError.\n */\n private getIdColumn(name: string): PgColumn {\n try {\n if (!isNonEmptyString(name)) {\n throw new DatabaseError(\n \"Invalid table name\",\n DATABASE_ERROR_CODES.INVALID_TABLE_NAME,\n );\n }\n\n const idColumn = this.idColumnMap.get(name);\n if (!idColumn) {\n throw new DatabaseError(\n \"ID column is not registered with the adapter\",\n DATABASE_ERROR_CODES.ID_COLUMN_NOT_REGISTERED,\n );\n }\n return idColumn;\n } catch (error) {\n throw error instanceof DatabaseError\n ? error\n : new DatabaseError(\n \"Failed to get ID column\",\n DATABASE_ERROR_CODES.GET_ID_COLUMN_FAILED,\n );\n }\n }\n\n /**\n * Builds a SQL `WHERE` clause based on filter operators.\n * @private\n * @param {Filter} filter - Filter definition.\n * @param {PgTable} table - Table to apply filter on.\n * @returns {SQL | undefined} SQL condition object.\n * @throws {DatabaseError} If column or operator is invalid.\n * @description\n * Builds a SQL WHERE clause based on the provided filter definition.\n * It supports various operators like equality, comparison, and null checks.\n * If the column specified in the filter does not exist in the table, or if the operator\n * is not supported, it throws a DatabaseError. The method returns an SQL object that\n * can be used in queries, or undefined if no valid clause can be constructed.\n */\n // eslint-disable-next-line complexity\n private buildWhereClause<T extends Record<string, unknown>>(\n filter: Filter<T>,\n table: PgTable,\n ): SQL | undefined {\n try {\n if (!isObject(filter)) {\n return undefined;\n }\n\n const { field, operator, value } = filter;\n\n // Validate field name\n if (!isNonEmptyString(field) || !DB_REGEX.isValidFieldName(field)) {\n throw new DatabaseError(\n \"Invalid field name\",\n DATABASE_ERROR_CODES.INVALID_FIELD_NAME,\n );\n }\n\n // Access column from table - field is validated at runtime\n const column = table[field as keyof typeof table] as Column<\n ColumnBaseConfig<ColumnDataType, string>\n >;\n if (!column) {\n throw new DatabaseError(\n \"Column does not exist in table\",\n DATABASE_ERROR_CODES.COLUMN_NOT_EXISTS,\n );\n }\n\n // Drizzle operators work with the column types directly\n switch (operator) {\n case \"eq\":\n return eq(column, value);\n case \"ne\":\n return not(eq(column, value));\n case \"gt\":\n return gt(column, value);\n case \"gte\":\n return gte(column, value);\n case \"lt\":\n return lt(column, value);\n case \"lte\":\n return lte(column, value);\n case \"in\":\n return inArray(column, value as unknown[]);\n case \"notIn\":\n return not(inArray(column, value as unknown[]));\n case \"like\":\n return like(column, value as string);\n case \"between\":\n return between(\n column,\n (value as [unknown, unknown])[0],\n (value as [unknown, unknown])[1],\n );\n case \"isNull\":\n return isNull(column);\n case \"isNotNull\":\n return isNotNull(column);\n default:\n throw new DatabaseError(\n \"Unsupported operator\",\n DATABASE_ERROR_CODES.UNSUPPORTED_OPERATOR,\n );\n }\n } catch (error) {\n throw new DatabaseError(\n \"Failed to build WHERE clause\",\n DATABASE_ERROR_CODES.BUILD_WHERE_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.buildWhereClause\",\n },\n cause: error as Error,\n },\n );\n }\n }\n\n /**\n * Applies sorting to a query using provided field and direction.\n * @private\n * @template TQuery - Type of the query builder.\n * @template TTable - Type of the table.\n * @param {TQuery} query - Drizzle query builder.\n * @param {SortOptions[]} sort - Array of sort conditions.\n * @param {TTable} table - Target table.\n * @returns {TQuery} Modified query with applied sorting.\n * @throws {DatabaseError} If field is invalid or missing.\n * @description\n * Applies sorting to a Drizzle query based on the provided sort options.\n * It supports sorting by multiple fields in ascending or descending order.\n * If a field specified in the sort options does not exist in the table, or is not a valid column,\n * it throws a DatabaseError. The method returns the modified query with the sorting applied.\n */\n private applySorting<\n T extends Record<string, unknown>,\n TQuery extends {\n orderBy: (...columns: (SQL | SQLWrapper | PgColumn)[]) => TQuery;\n },\n TTable extends PgTable,\n >(query: TQuery, sort: SortOptions<T>[], table: TTable): TQuery {\n return sort.reduce((q, { field, direction }) => {\n if (!Object.prototype.hasOwnProperty.call(table, field)) {\n throw new DatabaseError(\n `Column ${field} does not exist in table`,\n DATABASE_ERROR_CODES.COLUMN_NOT_EXISTS,\n );\n }\n\n const key = field as keyof TTable;\n const column = table[key];\n\n if (!(column instanceof PgColumn)) {\n throw new DatabaseError(\n `Field ${field} is not a valid column`,\n DATABASE_ERROR_CODES.INVALID_COLUMN,\n );\n }\n\n return direction === \"asc\"\n ? q.orderBy(asc(column))\n : q.orderBy(desc(column));\n }, query);\n }\n}\n","import type {\n DatabaseAdapterType,\n DatabaseResult,\n PaginatedResult,\n QueryOptions,\n Filter,\n DatabaseHealthStatus,\n Transaction,\n SupabaseAdapterConfig,\n} from \"@plyaz/types/db\";\nimport type { SupabaseClient } from \"@supabase/supabase-js\";\nimport { createClient } from \"@supabase/supabase-js\";\nimport { failure, success } from \"@utils/databaseResultHelpers\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\n\nimport { calculatePagination } from \"@utils/pagination\";\nimport { NUMERIX } from \"@plyaz/config\";\n\n/**\n * @class SupabaseAdapter\n * @implements {DatabaseAdapterType}\n * @classdesc\n * Supabase adapter implementation for database operations.\n *\n * This adapter provides an interface to interact with Supabase databases,\n * supporting CRUD operations, transactions, and health checks. It leverages\n * the Supabase JavaScript client to communicate with PostgreSQL databases through\n * Supabase's API. The adapter provides a consistent interface while abstracting\n * away the specifics of Supabase's API calls.\n */\nexport class SupabaseAdapter implements DatabaseAdapterType {\n private client: SupabaseClient;\n private config: SupabaseAdapterConfig;\n private tableMap: Map<string, string> = new Map();\n private idColumnMap: Map<string, string> = new Map();\n private configIdColumns: Record<string, string>;\n\n /**\n * Creates a new SupabaseAdapter instance.\n * @param {SupabaseAdapterConfig} config - Configuration for the Supabase adapter.\n * @description\n * Initializes the adapter with the provided configuration, setting up the Supabase client.\n * The configuration must include a Supabase URL and either a service key or an anonymous key.\n * The adapter maintains internal maps for table names and ID columns to provide a level of\n * abstraction over the database schema. If required configuration values are missing,\n * the constructor throws a DatabaseError.\n * @throws {DatabaseError} If Supabase URL or key is not provided in the configuration.\n */\n constructor(config: SupabaseAdapterConfig) {\n this.config = config;\n // Store custom ID column mappings from config\n this.configIdColumns = config.tableIdColumns ?? {};\n\n if (!config.supabaseUrl) {\n throw new DatabaseError(\n \"Supabase URL is required for Supabase adapter\",\n DATABASE_ERROR_CODES.CONFIG_REQUIRED,\n );\n }\n\n const key = config.supabaseServiceKey ?? config.supabaseAnonKey;\n\n if (!key) {\n throw new DatabaseError(\n \"Supabase key is required for Supabase adapter\",\n DATABASE_ERROR_CODES.CONFIG_REQUIRED,\n );\n }\n\n this.client = createClient(config.supabaseUrl, key, {\n auth: {\n persistSession: false,\n autoRefreshToken: false,\n },\n db: {\n schema: (config.schema ?? \"public\") as \"public\",\n },\n });\n }\n\n /**\n * Initializes the Supabase database adapter.\n * @returns {Promise<DatabaseResult<void>>} A promise resolving to a DatabaseResult indicating\n * whether the initialization was successful or failed.\n * @description\n * Validates the Supabase database connection by invoking a simple predefined RPC function (`version`).\n * This method is typically executed during application startup to ensure the adapter can\n * successfully communicate with the database before performing any operations.\n *\n * The method calls the `version` RPC to confirm connectivity. If the RPC function is not defined,\n * it is treated as a non-critical error and the connection is still considered valid. Any other\n * errors are reported as initialization failures.\n */\n async initialize(): Promise<DatabaseResult<void>> {\n try {\n // Verify the database connection by invoking the predefined `version` RPC function.\n const { error } = await this.client.rpc(\"version\");\n\n // If the `version` RPC function does not exist, consider it non-critical — connection is verified.\n if (\n error &&\n !error.message.includes('function \"version\" does not exist')\n ) {\n return failure(\n new DatabaseError(\n `Failed to initialize Supabase adapter: ${error.message}`,\n DATABASE_ERROR_CODES.INIT_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.initialize\",\n },\n cause: error,\n },\n ),\n );\n }\n\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to initialize Supabase adapter: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.INIT_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.initialize\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Connect to the database.\n * @returns {Promise<void>} Promise that resolves when connected.\n * @description\n * Supabase handles connections automatically, so this method is a no-op.\n * The Supabase client manages connections internally, establishing them as needed\n * and handling connection pooling. This method is included for interface compatibility\n * but does not perform any connection operations.\n */\n async connect(): Promise<void> {\n // Supabase handles connections automatically\n }\n\n /**\n * Disconnect from the database.\n * @returns {Promise<void>} Promise that resolves when disconnected.\n * @description\n * Supabase handles disconnections automatically, so this method is a no-op.\n * The Supabase client manages connections internally, closing them when appropriate.\n * This method is included for interface compatibility but does not perform any\n * disconnection operations.\n */\n async disconnect(): Promise<void> {\n // Supabase handles disconnections automatically\n }\n\n /**\n * Closes the database connection and cleanup resources.\n * Supabase handles connections automatically, so this just returns success.\n * @returns Promise resolving to DatabaseResult indicating success.\n */\n async close(): Promise<DatabaseResult<void>> {\n await this.disconnect();\n return success();\n }\n\n /**\n * Gets the underlying Supabase client instance.\n * @template TClient - The type of the Supabase client to return.\n * @returns {TClient} The Supabase client instance cast to the specified client type.\n * @description\n * This method provides access to the underlying Supabase client.\n * Although direct access is technically possible, it is discouraged to maintain\n * abstraction and ensure that all database operations go through the adapter’s\n * interface for consistent error handling, logging, and event management.\n */\n getClient<TClient extends object = object>(): TClient {\n return this.client as TClient;\n }\n\n /**\n * Execute a raw SQL query.\n * @template T - The expected type of the query result rows.\n * @param {string} sql - SQL query string.\n * @param {T[]} [params] - Query parameters.\n * @returns {Promise<T[]>} Promise resolving to query results.\n * @description\n * Executes a raw SQL query against the database using Supabase's RPC function.\n * This method is useful for complex queries that cannot be easily expressed using the adapter's\n * built-in methods or for database-specific operations. The method uses parameterized queries\n * to prevent SQL injection attacks. If the query execution fails, a DatabaseError is thrown.\n * Note that this requires a custom RPC function named 'exec_sql' to be set up in your Supabase project.\n */\n async query<T>(sql: string, params?: T[]): Promise<T[]> {\n try {\n const { data, error } = await this.client.rpc(\"exec_sql\", {\n sql,\n params,\n });\n if (error)\n throw new DatabaseError(\n `Failed to execute query: ${sql} - ${error.message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.query\",\n },\n cause: error,\n },\n );\n return data as T[];\n } catch (error) {\n throw new DatabaseError(\n `Failed to execute query: ${sql} - ${(error as Error).message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.query\",\n },\n cause: error as Error,\n },\n );\n }\n }\n\n /**\n * Register a table with the adapter.\n * @template TTable - Type representing the table structure.\n * @template TIdColumn - Type representing the ID column.\n * @param {string} name - Logical name for the table.\n * @param {TTable} [table] - Actual table name (defaults to logical name if not provided).\n * @param {TIdColumn} [idColumn] - Optional ID column name.\n * @description\n * Registers a table with the adapter, allowing it to be referenced by a logical name\n * in subsequent operations. This is necessary for the adapter to perform operations\n * on the table. The ID column can also be specified if it differs from the default 'id'.\n * This registration enables the adapter to map logical table names to actual table names\n * and ID columns, providing a layer of abstraction between the application and the database schema.\n * If no table name is provided, the logical name is used as the actual table name.\n */\n registerTable<TTable, TIdColumn>(\n name: string,\n table?: TTable,\n idColumn?: TIdColumn,\n ): void {\n this.tableMap.set(name, (table as string) || name);\n if (idColumn) {\n this.idColumnMap.set(name, idColumn as string);\n }\n }\n\n /**\n * Find a single record by ID.\n * @template T - The expected type of the record.\n * @param {string} table - Table name.\n * @param {string} id - Record ID.\n * @returns {Promise<DatabaseResult<T | null>>} Promise resolving to DatabaseResult containing the record or null.\n * @description\n * Retrieves a single record from the specified table using its primary ID.\n * The method uses Supabase's select method with a filter for the ID column and\n * the single() method to retrieve exactly one record. If the record is found,\n * it is returned in a success result. If no record is found (indicated by error code PGRST116),\n * null is returned in a success result. If an error occurs during the operation,\n * a failure result with an error message is returned.\n */\n async findById<T>(\n table: string,\n id: string,\n ): Promise<DatabaseResult<T | null>> {\n try {\n const tableName = this.getTableName(table);\n const idColumn = this.idColumnMap.get(table) ?? \"id\";\n const { data, error } = await this.client\n .from(tableName)\n .select(\"*\")\n .eq(idColumn, id)\n .single();\n\n if (error) {\n if (error.code === \"PGRST116\") {\n return success();\n }\n return failure(\n new DatabaseError(\n `Failed to find by id in table ${table}: ${error.message}`,\n DATABASE_ERROR_CODES.FIND_BY_ID_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.findById\",\n },\n cause: error,\n },\n ),\n );\n }\n\n return success(data as T);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to find by id in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.FIND_BY_ID_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.findById\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Find multiple records with filtering and pagination.\n * @template T - The expected type of the records.\n * @param {string} table - Table name.\n * @param {QueryOptions} [options] - Query options including filters, sorting, and pagination.\n * @returns {Promise<DatabaseResult<PaginatedResult<T>>>} Promise resolving to DatabaseResult containing paginated data.\n * @description\n * Retrieves multiple records from the specified table with support for filtering,\n * sorting, and pagination. The method first executes a count query to get the\n * total number of matching records, then executes the main query with the applied filters,\n * sorting, and pagination. The result includes the data array, total count of matching records,\n * and pagination metadata such as current page, total pages, and limit.\n * If an error occurs during the operation, a failure result with an error message is returned.\n */\n // eslint-disable-next-line complexity\n async findMany<T extends Record<string, unknown>>(\n table: string,\n options?: QueryOptions<T>,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n try {\n const tableName = this.getTableName(table);\n let query = this.client.from(tableName).select(\"*\");\n\n // Apply filters if provided\n if (options?.filter) {\n query = this.applyFilter(query, options.filter);\n }\n\n // Get total count for pagination\n let countQuery = this.client\n .from(tableName)\n .select(\"*\", { count: \"exact\", head: true });\n if (options?.filter) {\n countQuery = this.applyFilter(countQuery, options.filter);\n }\n const { count, error: countError } = await countQuery;\n\n if (countError) {\n return failure(\n new DatabaseError(\n `Failed to count records in table ${table}: ${countError.message}`,\n DATABASE_ERROR_CODES.COUNT_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.findMany\",\n },\n cause: countError,\n },\n ),\n );\n }\n\n // Apply sorting if provided\n if (options?.sort) {\n options.sort.forEach((sortOption) => {\n query = query.order(sortOption.field, {\n ascending: sortOption.direction === \"asc\",\n });\n });\n }\n\n // Apply pagination if provided\n if (options?.pagination) {\n if (options.pagination.offset !== undefined) {\n query = query.range(\n options.pagination.offset,\n options.pagination.offset +\n (options.pagination.limit ?? NUMERIX.TEN) -\n 1,\n );\n } else if (options.pagination.limit !== undefined) {\n query = query.limit(options.pagination.limit);\n }\n }\n\n const { data, error } = await query;\n\n if (error) {\n return failure(\n new DatabaseError(\n `Failed to find many in table ${table}: ${error.message}`,\n DATABASE_ERROR_CODES.FIND_MANY_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.findMany\",\n },\n cause: error,\n },\n ),\n );\n }\n\n const total = count ?? 0;\n\n return success({\n data: data as T[],\n total,\n pagination: calculatePagination(total, options?.pagination),\n });\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to find many in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.FIND_MANY_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.findMany\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Create a new record.\n * @template T - The expected type of the record.\n * @param {string} table - Table name.\n * @param {T} data - Record data to create.\n * @returns {Promise<DatabaseResult<T>>} Promise resolving to DatabaseResult containing the created record.\n * @description\n * Inserts a new record into the specified table using the provided data.\n * The method uses Supabase's insert method with the data and then chains a select()\n * and single() call to retrieve the inserted record with any auto-generated fields\n * (like IDs) populated. If the operation is successful, it returns the created record.\n * If an error occurs during the operation, a failure result with an error message is returned.\n */\n async create<T>(table: string, data: T): Promise<DatabaseResult<T>> {\n try {\n const tableName = this.getTableName(table);\n const { data: result, error } = await this.client\n .from(tableName)\n .insert(data)\n .select()\n .single();\n\n if (error) {\n return failure(\n new DatabaseError(\n `Failed to create in table ${table}: ${error.message}`,\n DATABASE_ERROR_CODES.CREATE_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.create\",\n },\n cause: error,\n },\n ),\n );\n }\n\n return success(result as T);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to create in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.CREATE_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.create\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Update an existing record.\n * @template T - The expected type of the record.\n * @param {string} table - Table name.\n * @param {string} id - Record ID.\n * @param {Partial<T>} data - Partial record data to update.\n * @returns {Promise<DatabaseResult<T>>} Promise resolving to DatabaseResult containing the updated record.\n * @description\n * Updates an existing record in the specified table using its primary ID.\n * Only the fields provided in the data object are updated, allowing for partial updates.\n * The method uses Supabase's update method with the data and a filter for the ID column,\n * then chains a select() and single() call to retrieve the updated record. If the operation\n * is successful, it returns the updated record. If an error occurs during the operation,\n * a failure result with an error message is returned.\n */\n async update<T>(\n table: string,\n id: string,\n data: Partial<T>,\n ): Promise<DatabaseResult<T>> {\n try {\n const tableName = this.getTableName(table);\n const idColumn = this.idColumnMap.get(table) ?? \"id\";\n const { data: result, error } = await this.client\n .from(tableName)\n .update(data)\n .eq(idColumn, id)\n .select()\n .single();\n\n if (error) {\n return failure(\n new DatabaseError(\n `Failed to update in table ${table}: ${error.message}`,\n DATABASE_ERROR_CODES.UPDATE_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.update\",\n },\n cause: error,\n },\n ),\n );\n }\n\n return success(result as T);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to update in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.UPDATE_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.update\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Delete a record.\n * @param {string} table - Table name.\n * @param {string} id - Record ID.\n * @returns {Promise<DatabaseResult<void>>} Promise resolving to DatabaseResult indicating success or failure.\n * @description\n * Deletes a record from the specified table using its primary ID.\n * The method uses Supabase's delete method with a filter for the ID column.\n * If the operation is successful, it returns a success result with no value.\n * If an error occurs during the operation, a failure result with an error message is returned.\n */\n async delete(table: string, id: string): Promise<DatabaseResult<void>> {\n try {\n const tableName = this.getTableName(table);\n const idColumn = this.idColumnMap.get(table) ?? \"id\";\n const { error } = await this.client\n .from(tableName)\n .delete()\n .eq(idColumn, id);\n\n if (error) {\n return failure(\n new DatabaseError(\n `Failed to delete from table ${table}: ${error.message}`,\n DATABASE_ERROR_CODES.DELETE_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.delete\",\n },\n cause: error,\n },\n ),\n );\n }\n\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to delete from table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.DELETE_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.delete\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Execute a transaction.\n * @template T - The expected type of the transaction result.\n * @param {(trx: Transaction) => Promise<T>} callback - Function containing transaction operations.\n * @returns {Promise<DatabaseResult<T>>} Promise resolving to DatabaseResult containing the transaction result.\n * @description\n * Executes a callback function within a database transaction, providing atomicity.\n * Note that Supabase doesn't support traditional multi-statement transactions in the same way\n * as direct database connections. This adapter simulates transactional behavior by executing\n * all operations through the same client, but does not provide true rollback capabilities.\n * If the callback function executes successfully, the transaction is considered committed.\n * If an error occurs during the execution of the callback function, a failure result with\n * an error message is returned, but any successful operations within the callback will not\n * be rolled back.\n */\n async transaction<T>(\n callback: (trx: Transaction) => Promise<T>,\n ): Promise<DatabaseResult<T>> {\n try {\n // Create a transaction object that uses the same client\n const trx: Transaction = {\n findById: async <T>(table: string, id: string) => {\n return this.findById<T>(table, id);\n },\n create: async <T>(table: string, data: T) => {\n return this.create<T>(table, data);\n },\n update: async <T>(table: string, id: string, data: Partial<T>) => {\n return this.update<T>(table, id, data);\n },\n delete: async (table: string, id: string) => {\n return this.delete(table, id);\n },\n commit: async () => {\n // No-op for Supabase\n },\n rollback: async () => {\n // No-op for Supabase\n },\n };\n\n const result = await callback(trx);\n return success(result);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Transaction failed: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.TRANSACTION_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.transaction\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Check if a record exists.\n * @param {string} table - Table name.\n * @param {string} id - Record ID.\n * @returns {Promise<DatabaseResult<boolean>>} Promise resolving to DatabaseResult containing boolean indicating existence.\n * @description\n * Checks if a record with the specified ID exists in the table.\n * The method constructs a SELECT query with a WHERE clause for the ID column\n * and a LIMIT of 1. It returns a success result with a boolean value indicating\n * whether the record exists. If an error occurs during the operation, a failure result\n * with an error message is returned.\n */\n async exists(table: string, id: string): Promise<DatabaseResult<boolean>> {\n try {\n const tableName = this.getTableName(table);\n const idColumn = this.idColumnMap.get(table) ?? \"id\";\n const { data, error } = await this.client\n .from(tableName)\n .select(idColumn)\n .eq(idColumn, id)\n .limit(1);\n\n if (error) {\n return failure(\n new DatabaseError(\n `Failed to check existence in table ${table}: ${error.message}`,\n DATABASE_ERROR_CODES.EXISTS_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.exists\",\n },\n cause: error,\n },\n ),\n );\n }\n return success((data && data.length > 0) || false);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to check existence in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.EXISTS_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.exists\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Count records matching a filter.\n * @param {string} table - Table name.\n * @param {Filter} [filter] - Filter conditions.\n * @returns {Promise<DatabaseResult<number>>} Promise resolving to DatabaseResult containing the count.\n * @description\n * Counts the number of records in the specified table that match the optional filter.\n * The method uses Supabase's select method with the count option set to 'exact'\n * and head set to true to return only the count. If a filter is provided,\n * it is applied to narrow down the count to matching records. It returns a success\n * result with the count of matching records. If an error occurs during the operation,\n * a failure result with an error message is returned.\n */\n async count<T extends Record<string, unknown> = Record<string, unknown>>(\n table: string,\n filter?: Filter<T>,\n ): Promise<DatabaseResult<number>> {\n try {\n const tableName = this.getTableName(table);\n let query = this.client\n .from(tableName)\n .select(\"*\", { count: \"exact\", head: true });\n\n if (filter) {\n query = this.applyFilter(query, filter);\n }\n\n const { count, error } = await query;\n\n if (error) {\n return failure(\n new DatabaseError(\n `Failed to count in table ${table}: ${error.message}`,\n DATABASE_ERROR_CODES.COUNT_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.count\",\n },\n cause: error,\n },\n ),\n );\n }\n return success(count ?? 0);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to count in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.COUNT_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.count\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Perform health check.\n * @returns {Promise<DatabaseResult<DatabaseHealthStatus>>} Promise resolving to DatabaseResult containing health status.\n * @description\n * Checks the health of the database connection by executing a simple RPC call.\n * The method measures the response time of the query to determine the health status.\n * It attempts to call a 'version' RPC function, ignoring errors related to the function\n * not existing but reporting other errors. It returns a success result with a DatabaseHealthStatus\n * object indicating whether the database is healthy, the response time of the health check,\n * and any additional details. If an error occurs during the operation, a failure result\n * with an error message is returned.\n */\n async healthCheck(): Promise<DatabaseResult<DatabaseHealthStatus>> {\n const startTime = Date.now();\n try {\n const { error } = await this.client.rpc(\"version\");\n const responseTime = Date.now() - startTime;\n\n if (\n error &&\n !error.message.includes('function \"version\" does not exist')\n ) {\n return success({\n isHealthy: false,\n responseTime,\n details: { adapter: \"supabase\", error: error.message },\n });\n }\n return success({\n isHealthy: true,\n responseTime,\n details: { adapter: \"supabase\" },\n });\n } catch (error) {\n const responseTime = Date.now() - startTime;\n return success({\n isHealthy: false,\n responseTime,\n details: { adapter: \"supabase\", error: (error as Error).message },\n });\n }\n }\n\n /**\n * Get the actual table name from the mapped table name.\n * @private\n * @param {string} name - Logical table name.\n * @returns {string} Actual table name.\n * @description\n * Retrieves the actual table name. If not registered, auto-registers it.\n * This enables seamless table operations without manual registration.\n */\n private getTableName(name: string): string {\n let tableName = this.tableMap.get(name);\n if (!tableName) {\n // Auto-register table with same name\n // Only set ID column from config if not already registered (runtime override takes precedence)\n const hasRuntimeIdColumn = this.idColumnMap.has(name);\n const customIdColumn = hasRuntimeIdColumn\n ? undefined\n : this.configIdColumns[name];\n this.registerTable(name, name, customIdColumn);\n tableName = name;\n }\n return tableName;\n }\n\n /**\n * Applies filter conditions to a Supabase query with comprehensive operator support\n *\n * Transforms generic Filter objects into Supabase-specific query methods while maintaining\n * type safety and preventing SQL injection through operator validation.\n *\n * **Supported Operators:**\n * - Equality: eq, ne (not equal)\n * - Comparison: gt, gte, lt, lte\n * - Pattern: like (with % wildcards)\n * - Membership: in, notIn (array values)\n * - Range: between (two-element array)\n * - Null checks: isNull, isNotNull\n *\n * **Security Features:**\n * - Validates field names against regex: /^[a-zA-Z_][a-zA-Z0-9_]*$/\n * - Validates operator against whitelist\n * - Type-checks array values for 'in', 'notIn', 'between' operators\n *\n * @private\n * @template Q - Type of the Supabase query builder\n * @param {Q} query - Supabase query builder instance to apply filters to\n * @param {Filter} filter - Filter conditions with field, operator, and value\n * @returns {Q} Modified query builder with filter conditions applied\n *\n * @throws {BaseError} SUPABASE_INVALID_FILTER - If 'in'/'notIn' value is not an array\n * @throws {BaseError} SUPABASE_INVALID_FILTER - If 'between' value is not a 2-element array\n * @throws {BaseError} SUPABASE_UNSUPPORTED_OPERATOR - If operator is not in whitelist\n *\n * @example\n * ```typescript\n * // Equality filter\n * const query1 = this.applyFilter(baseQuery, {\n * field: 'status',\n * operator: 'eq',\n * value: 'active'\n * });\n * // Generates: query.eq('status', 'active')\n *\n * // Range filter\n * const query2 = this.applyFilter(baseQuery, {\n * field: 'age',\n * operator: 'between',\n * value: [18, 65]\n * });\n * // Generates: query.gte('age', 18).lte('age', 65)\n *\n * // Array membership filter\n * const query3 = this.applyFilter(baseQuery, {\n * field: 'category',\n * operator: 'in',\n * value: ['tech', 'science', 'business']\n * });\n * // Generates: query.in('category', ['tech', 'science', 'business'])\n * ```\n *\n */\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private applyFilter<T extends object = object>(q: any, f: Filter<T>): any {\n const { field, operator, value } = f;\n\n const ops: Record<string, Function> = {\n eq: () => q.eq(field, value),\n ne: () => q.neq(field, value),\n gt: () => q.gt(field, value),\n gte: () => q.gte(field, value),\n lt: () => q.lt(field, value),\n lte: () => q.lte(field, value),\n like: () => q.like(field, value),\n isNull: () => q.is(field, null),\n isNotNull: () => q.isNot(field, null),\n in: () => {\n if (!Array.isArray(value))\n throw new DatabaseError(\n `'in' requires array`,\n DATABASE_ERROR_CODES.INVALID_FILTER,\n );\n return q.in(field, value);\n },\n notIn: () => {\n if (!Array.isArray(value))\n throw new DatabaseError(\n `'notIn' requires array`,\n DATABASE_ERROR_CODES.INVALID_FILTER,\n );\n return q.notIn(field, value);\n },\n between: () => {\n if (!Array.isArray(value) || value.length !== NUMERIX.TWO)\n throw new DatabaseError(\n `'between' requires [min,max]`,\n DATABASE_ERROR_CODES.INVALID_FILTER,\n );\n return q.gte(field, value[0]).lte(field, value[1]);\n },\n };\n\n if (!ops[operator])\n throw new DatabaseError(\n `Unsupported operator: ${operator}`,\n DATABASE_ERROR_CODES.UNSUPPORTED_OPERATOR,\n );\n return ops[operator]();\n }\n}\n","import type { PoolClient } from \"pg\";\nimport { Pool } from \"pg\";\nimport type {\n SQLAdapterConfig,\n Transaction,\n DatabaseResult,\n PaginatedResult,\n QueryOptions,\n DatabaseHealthStatus,\n Filter,\n DatabaseAdapterType,\n} from \"@plyaz/types/db\";\nimport { failure, success } from \"@utils/databaseResultHelpers\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport { calculatePagination } from \"@utils/pagination\";\nimport { isNonEmptyString, isObject } from \"@utils/typeGuards\";\nimport { DB_REGEX } from \"@utils/regex\";\n\n/**\n * @class SQLAdapter\n * @implements {DatabaseAdapterType}\n * @classdesc\n * Plain SQL adapter implementation for raw SQL queries.\n *\n * This adapter provides an interface to interact with SQL databases using raw SQL queries,\n * supporting CRUD operations, transactions, and health checks. It uses PostgreSQL's node-pg\n * driver for database connectivity and provides a simple, direct SQL interface without\n * ORM abstractions. This adapter is ideal for applications that require direct control\n * over SQL queries or need to leverage database-specific features.\n */\nexport class SQLAdapter implements DatabaseAdapterType {\n private pool: Pool;\n private config: SQLAdapterConfig;\n private tableMap: Map<string, string> = new Map();\n private idColumnMap: Map<string, string> = new Map();\n private configIdColumns: Record<string, string>;\n private defaultSchema: string;\n\n /**\n * Creates a new SQLAdapter instance.\n * @param {SQLAdapterConfig} config - Configuration for the SQL adapter.\n * @description\n * Initializes the adapter with the provided configuration, setting up the connection pool\n * for PostgreSQL database connections. The configuration should include a connection string\n * and optional pool settings such as min/max connections and idle timeout. The adapter\n * maintains internal maps for table names and ID columns to provide a level of abstraction\n * over the raw database schema.\n */\n constructor(config: SQLAdapterConfig) {\n this.config = config;\n this.defaultSchema = config.schema ?? \"public\";\n this.pool = new Pool({\n connectionString: config.connectionString,\n ...config.pool,\n });\n // Store custom ID column mappings from config\n this.configIdColumns = config.tableIdColumns ?? {};\n }\n\n /**\n * Get fully-qualified table name with schema\n */\n private getQualifiedTableName(table: string, schema?: string): string {\n const targetSchema = schema ?? this.defaultSchema;\n\n // If table already has schema prefix (e.g., \"tenant_acme.users\"), use as-is\n if (table.includes(\".\")) {\n return table;\n }\n\n // Apply schema prefix\n return `${targetSchema}.${table}`;\n }\n\n /**\n * Initialize the adapter.\n * @returns {Promise<DatabaseResult<void>>} Promise resolving to DatabaseResult indicating success or failure.\n * @description\n * Tests the database connection by attempting to establish a connection to the database.\n * This method is typically called during application startup to verify that the adapter\n * can communicate with the database before performing any operations. Returns a success\n * result if the connection is established, or a failure result with an error if the\n * connection cannot be established.\n */\n async initialize(): Promise<DatabaseResult<void>> {\n try {\n const client = await this.pool.connect();\n\n // Set search_path for the connection if schema is configured\n if (this.defaultSchema && this.defaultSchema !== \"public\") {\n await client.query(`SET search_path TO ${this.defaultSchema}, public`);\n }\n\n client.release();\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to initialize PlainSQL adapter: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.INIT_FAILED,\n {\n context: {\n source: \"SQLAdapter.initialize\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Connect to the database.\n * @returns {Promise<void>} Promise that resolves when connected.\n * @description\n * Establishes a connection to the PostgreSQL database using the connection pool.\n * This method is called to ensure that a connection is available before performing database operations.\n * The connection pool manages the connections efficiently, reusing them when possible.\n */\n async connect(): Promise<void> {\n await this.pool.connect();\n }\n\n /**\n * Disconnect from the database.\n * @returns {Promise<void>} Promise that resolves when disconnected.\n * @description\n * Gracefully shuts down the connection pool, closing all active connections.\n * This method should be called when the adapter is no longer needed, typically during\n * application shutdown, to free up database resources and prevent connection leaks.\n */\n async disconnect(): Promise<void> {\n await this.pool.end();\n }\n\n /**\n * Closes the database connection and cleanup resources.\n * @returns Promise resolving to DatabaseResult indicating success or failure.\n */\n async close(): Promise<DatabaseResult<void>> {\n try {\n await this.disconnect();\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to close connection: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.DISCONNECT_FAILED,\n ),\n );\n }\n }\n\n /**\n * Gets the underlying PostgreSQL client instance.\n * @template TClient - The type of the database client to return.\n * @returns {TClient} The PostgreSQL pool instance cast to the specified client type.\n * @description\n * This method provides access to the underlying PostgreSQL connection pool.\n * While direct access is technically possible, it is generally discouraged to\n * preserve abstraction and ensure all database operations go through the adapter’s\n * interface for consistent error handling, logging, and event management.\n */\n getClient<TClient extends object = object>(): TClient {\n return this.pool as TClient;\n }\n\n /**\n * Execute a raw SQL query.\n * @template T - The expected type of the query result rows.\n * @param {string} sql - SQL query string.\n * @param {T[]} [params] - Query parameters.\n * @returns {Promise<T[]>} Promise resolving to query results.\n * @description\n * Executes a raw SQL query against the database, with optional parameterization.\n * This method is useful for complex queries that cannot be easily expressed using the adapter's\n * built-in methods or for database-specific operations. The method uses parameterized queries\n * to prevent SQL injection attacks. If the query execution fails, a DatabaseError is thrown.\n */\n async query<T>(sql: string, params?: T[]): Promise<T[]> {\n try {\n const result = await this.pool.query(sql, params);\n return result.rows as T[];\n } catch (error) {\n throw new DatabaseError(\n `Failed to execute query: ${sql} - ${(error as Error).message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n {\n context: {\n source: \"SQLAdapter.query\",\n },\n cause: error as Error,\n },\n );\n }\n }\n\n /**\n * Register a table with the adapter.\n * @template TTable - Type representing the table structure.\n * @template TIdColumn - Type representing the ID column.\n * @param {string} name - Logical name for the table.\n * @param {TTable} [table] - Table name or object.\n * @param {TIdColumn} [idColumn] - Optional ID column name.\n * @description\n * Registers a table with the adapter, allowing it to be referenced by a logical name\n * in subsequent operations. This is necessary for the adapter to perform operations\n * on the table. The ID column can also be specified if it differs from the default 'id'.\n * This registration enables the adapter to map logical table names to actual table names\n * and ID columns, providing a layer of abstraction between the application and the database schema.\n */\n registerTable<TTable, TIdColumn>(\n name: string,\n table?: TTable,\n idColumn?: TIdColumn,\n ): void {\n this.tableMap.set(name, table as string);\n\n if (idColumn) {\n this.idColumnMap.set(name, idColumn as string);\n }\n }\n\n /**\n * Find a single record by ID.\n * @template T - The expected type of the record.\n * @param {string} table - Table name.\n * @param {string} id - Record ID.\n * @returns {Promise<DatabaseResult<T | null>>} Promise resolving to DatabaseResult containing the record or null.\n * @description\n * Retrieves a single record from the specified table using its primary ID.\n * The method constructs a SELECT query with a WHERE clause for the ID column.\n * If the record is found, it is returned in a success result. If no record is found,\n * null is returned in a success result. If an error occurs during the operation,\n * a failure result with an error message is returned.\n */\n async findById<T>(\n table: string,\n id: string,\n ): Promise<DatabaseResult<T | null>> {\n try {\n const validationError = this.validateBasicParams(table, id);\n if (validationError) return failure(validationError);\n\n const tableName = this.getTableName(table);\n const qualifiedTable = this.getQualifiedTableName(tableName);\n const idColumn = this.getIdColumn(table);\n const sql = `SELECT * FROM ${qualifiedTable} WHERE \"${idColumn}\" = $1`;\n const result = await this.pool.query(sql, [id]);\n\n if (!result?.rows) {\n return failure(\n new DatabaseError(\n \"Invalid query result\",\n DATABASE_ERROR_CODES.INVALID_RESULT,\n ),\n );\n }\n\n return success((result.rows?.[0] as T) ?? null);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to find record: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.FIND_BY_ID_FAILED,\n {\n context: {\n source: \"SQLAdapter.findById\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Find multiple records with filtering and pagination.\n * @template T - The expected type of the records.\n * @param {string} table - Table name.\n * @param {QueryOptions} [options] - Query options including filters, sorting, and pagination.\n * @returns {Promise<DatabaseResult<PaginatedResult<object>>>} Promise resolving to DatabaseResult containing paginated data.\n * @description\n * Retrieves multiple records from the specified table with support for filtering,\n * sorting, and pagination. The method constructs a SELECT query with optional WHERE,\n * ORDER BY, LIMIT, and OFFSET clauses. It first executes a COUNT query to get the\n * total number of matching records, then executes the main query with the applied filters,\n * sorting, and pagination. The result includes the data array, total count of matching records,\n * and pagination metadata such as current page, total pages, and offset.\n * If an error occurs during the operation, a failure result with an error message is returned.\n */\n /**\n * Finds multiple records from the specified table with optional filtering, sorting, and pagination.\n * @template TRecord - Type representing the shape of records returned.\n * @template TOptions - Query options type.\n * @template TParam - Type of query parameters (primitives).\n * @param {string} table - Name of the table to query.\n * @param {TOptions} [options] - Optional query options for filtering, sorting, and pagination.\n * @returns {Promise<DatabaseResult<PaginatedResult<TRecord>>>} - A promise resolving to a paginated result.\n * @throws {DatabaseError} - When query execution or initialization fails.\n */\n /**\n * Finds multiple records from the specified table with optional filtering, sorting, and pagination.\n * @template T - Type representing the shape of records returned.\n * @param {string} table - Name of the table to query.\n * @param {QueryOptions<object>} [options] - Optional query options for filtering, sorting, and pagination.\n * @returns {Promise<DatabaseResult<PaginatedResult<T>>>} - A promise resolving to a paginated result.\n * @throws {DatabaseError} - When query execution or initialization fails.\n */\n // eslint-disable-next-line complexity\n async findMany<T extends Record<string, unknown>>(\n table: string,\n options?: QueryOptions<T>,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n try {\n const tableName = this.getTableName(table);\n const qualifiedTable = this.getQualifiedTableName(tableName);\n const params: Object[] = [];\n let whereClause = \"\";\n let paramIndex = 1;\n\n // Build WHERE clause\n if (options?.filter) {\n whereClause = this.buildWhereClause(options.filter, params, paramIndex);\n paramIndex += params.length;\n }\n\n // Count total\n const countSql = `SELECT COUNT(*) as total FROM ${qualifiedTable}${whereClause}`;\n const countResult = await this.pool.query(countSql, params);\n\n if (!countResult.rows || countResult.rows.length === 0) {\n throw new DatabaseError(\n \"Count query returned no results\",\n DATABASE_ERROR_CODES.COUNT_NO_RESULTS,\n );\n }\n\n const total = Number.parseInt(countResult.rows[0].total);\n if (isNaN(total) || total < 0) {\n throw new DatabaseError(\n \"Invalid count result\",\n DATABASE_ERROR_CODES.INVALID_COUNT,\n );\n }\n\n // ORDER BY clause\n let orderClause = \"\";\n if (options?.sort?.length) {\n orderClause =\n \" ORDER BY \" +\n options.sort\n .map((s) => `${s.field} ${s.direction.toUpperCase()}`)\n .join(\", \");\n }\n\n // LIMIT & OFFSET\n let limitClause = \"\";\n if (options?.pagination?.limit) {\n limitClause += ` LIMIT $${paramIndex++}`;\n params.push(options.pagination.limit);\n }\n if (options?.pagination?.offset) {\n limitClause += ` OFFSET $${paramIndex++}`;\n params.push(options.pagination.offset);\n }\n\n // Final query\n const sql = `SELECT * FROM ${qualifiedTable}${whereClause}${orderClause}${limitClause}`;\n const result = await this.pool.query(sql, params);\n\n return success({\n data: result.rows as T[],\n total,\n pagination: calculatePagination(total, options?.pagination),\n });\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to find many in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.FIND_MANY_FAILED,\n {\n context: {\n source: \"SQLAdapter.findMany\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Create a new record.\n * @template T - The expected type of the record.\n * @param {string} table - Table name.\n * @param {T} data - Record data to create.\n * @returns {Promise<DatabaseResult<T>>} Promise resolving to DatabaseResult containing the created record.\n * @description\n * Inserts a new record into the specified table using the provided data.\n * The method constructs an INSERT query with column names and parameter placeholders\n * for the values. After insertion, it returns the inserted record with any auto-generated\n * fields (like IDs) populated using the RETURNING clause. If an error occurs during the operation,\n * a failure result with an error message is returned.\n */\n async create<T>(table: string, data: T): Promise<DatabaseResult<T>> {\n try {\n const validationError = this.validateCreateParams(table, data);\n if (validationError) return failure(validationError);\n\n const tableName = this.getTableName(table);\n const qualifiedTable = this.getQualifiedTableName(tableName);\n const keys = Object.keys(data as Record<string, T>);\n const values = Object.values(data as Record<string, T>);\n const placeholders = values.map((_, i) => `$${i + 1}`).join(\", \");\n const escapedKeys = keys.map((k) => `\"${k}\"`).join(\", \");\n\n const sql = `INSERT INTO ${qualifiedTable} (${escapedKeys}) VALUES (${placeholders}) RETURNING *`;\n const result = await this.pool.query(sql, values);\n\n if (!result?.rows?.length) {\n return failure(\n new DatabaseError(\n \"Insert operation failed\",\n DATABASE_ERROR_CODES.INSERT_FAILED,\n ),\n );\n }\n\n return success(result.rows[0] as T);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to create record: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.CREATE_FAILED,\n {\n context: {\n source: \"SQLAdapter.create\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Update an existing record.\n * @template T - The expected type of the record.\n * @param {string} table - Table name.\n * @param {string} id - Record ID.\n * @param {Partial<T>} data - Partial record data to update.\n * @returns {Promise<DatabaseResult<T>>} Promise resolving to DatabaseResult containing the updated record.\n * @description\n * Updates an existing record in the specified table using its primary ID.\n * Only the fields provided in the data object are updated, allowing for partial updates.\n * The method constructs an UPDATE query with a SET clause for the fields to update\n * and a WHERE clause for the ID. After updating, it returns the updated record using\n * the RETURNING clause. If an error occurs during the operation, a failure result with\n * an error message is returned.\n */\n async update<T>(\n table: string,\n id: string,\n data: Partial<T>,\n ): Promise<DatabaseResult<T>> {\n try {\n const validationError = this.validateUpdateParams(table, id, data);\n if (validationError) return failure(validationError);\n\n const tableName = this.getTableName(table);\n const qualifiedTable = this.getQualifiedTableName(tableName);\n const keys = Object.keys(data as Record<string, T>);\n const values = Object.values(data as Record<string, T>);\n const setClause = keys.map((key, i) => `\"${key}\" = $${i + 1}`).join(\", \");\n const idColumn = this.getIdColumn(table);\n\n const sql = `UPDATE ${qualifiedTable} SET ${setClause} WHERE \"${idColumn}\" = $${keys.length + 1} RETURNING *`;\n const result = await this.pool.query(sql, [...values, id]);\n\n if (!result.rows?.length) {\n return failure(\n new DatabaseError(\n \"Record not found or no changes made\",\n DATABASE_ERROR_CODES.UPDATE_NO_CHANGES,\n ),\n );\n }\n\n return success(result.rows[0] as T);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to update record: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.UPDATE_FAILED,\n {\n context: {\n source: \"SQLAdapter.update\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Delete a record.\n * @param {string} table - Table name.\n * @param {string} id - Record ID.\n * @returns {Promise<DatabaseResult<void>>} Promise resolving to DatabaseResult indicating success or failure.\n * @description\n * Deletes a record from the specified table using its primary ID.\n * The method constructs a DELETE query with a WHERE clause for the ID column.\n * If the operation is successful, it returns a success result with no value.\n * If an error occurs during the operation, a failure result with an error message is returned.\n */\n async delete(table: string, id: string): Promise<DatabaseResult<void>> {\n try {\n if (!table || !id) {\n return failure(\n new DatabaseError(\n \"Invalid parameters\",\n DATABASE_ERROR_CODES.INVALID_PARAMS,\n ),\n );\n }\n\n const tableName = this.getTableName(table);\n const qualifiedTable = this.getQualifiedTableName(tableName);\n const idColumn = this.getIdColumn(table);\n const sql = `DELETE FROM ${qualifiedTable} WHERE \"${idColumn}\" = $1`;\n const result = await this.pool.query(sql, [id]);\n\n if (!result) {\n return failure(\n new DatabaseError(\n \"Delete operation failed\",\n DATABASE_ERROR_CODES.DELETE_FAILED,\n ),\n );\n }\n\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to delete record: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.DELETE_FAILED,\n {\n context: {\n source: \"SQLAdapter.delete\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Execute a transaction.\n * @template T - The expected type of the transaction result.\n * @param {(trx: Transaction) => Promise<T>} callback - Function containing transaction operations.\n * @returns {Promise<DatabaseResult<T>>} Promise resolving to DatabaseResult containing the transaction result.\n * @description\n * Executes a callback function within a database transaction, providing atomicity.\n * If the callback function executes successfully, the transaction is committed.\n * If an error occurs during the execution of the callback function, the transaction\n * is rolled back, ensuring that no partial changes are applied to the database.\n * The method returns the result of the callback function if successful,\n * or a failure result with an error message if an error occurs.\n * The transaction object passed to the callback provides methods for performing\n * database operations within the transaction.\n */\n async transaction<T>(\n callback: (trx: Transaction) => Promise<T>,\n ): Promise<DatabaseResult<T>> {\n const client: PoolClient = await this.pool.connect();\n try {\n await client.query(\"BEGIN\");\n\n const trx: Transaction = {\n findById: async <T>(table: string, id: string) => {\n const tableName = this.getTableName(table);\n const qualifiedTable = this.getQualifiedTableName(tableName);\n const idColumn = this.getIdColumn(table);\n const sql = `SELECT * FROM ${qualifiedTable} WHERE \"${idColumn}\" = $1`;\n const result = await client.query(sql, [id]);\n return success((result.rows[0] as T) ?? null);\n },\n create: async <T>(table: string, data: T) => {\n const tableName = this.getTableName(table);\n const qualifiedTable = this.getQualifiedTableName(tableName);\n const keys = Object.keys(data as Record<string, T>);\n const values = Object.values(data as Record<string, T>);\n const placeholders = values.map((_, i) => `$${i + 1}`).join(\", \");\n const escapedKeys = keys.map((k) => `\"${k}\"`).join(\", \");\n\n const sql = `INSERT INTO ${qualifiedTable} (${escapedKeys}) VALUES (${placeholders}) RETURNING *`;\n const result = await client.query(sql, values);\n return success(result.rows[0] as T);\n },\n update: async <T>(table: string, id: string, data: Partial<T>) => {\n const tableName = this.getTableName(table);\n const qualifiedTable = this.getQualifiedTableName(tableName);\n const keys = Object.keys(data as Record<string, T>);\n const values = Object.values(data as Record<string, T>);\n const setClause = keys\n .map((key, i) => `\"${key}\" = $${i + 1}`)\n .join(\", \");\n const idColumn = this.getIdColumn(table);\n\n const sql = `UPDATE ${qualifiedTable} SET ${setClause} WHERE \"${idColumn}\" = $${keys.length + 1} RETURNING *`;\n const result = await client.query(sql, [...values, id]);\n return success(result.rows[0] as T);\n },\n delete: async (table: string, id: string) => {\n const tableName = this.getTableName(table);\n const qualifiedTable = this.getQualifiedTableName(tableName);\n const idColumn = this.getIdColumn(table);\n const sql = `DELETE FROM ${qualifiedTable} WHERE \"${idColumn}\" = $1`;\n await client.query(sql, [id]);\n return success();\n },\n commit: async () => {\n await client.query(\"COMMIT\");\n },\n rollback: async () => {\n await client.query(\"ROLLBACK\");\n },\n };\n\n const result = await callback(trx);\n await trx.commit();\n return success(result);\n } catch (error) {\n await client.query(\"ROLLBACK\");\n return failure(\n new DatabaseError(\n `Transaction failed: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.TRANSACTION_FAILED,\n {\n context: {\n source: \"SQLAdapter.transaction\",\n },\n cause: error as Error,\n },\n ),\n );\n } finally {\n client.release();\n }\n }\n\n /**\n * Check if a record exists.\n * @param {string} table - Table name.\n * @param {string} id - Record ID.\n * @returns {Promise<DatabaseResult<boolean>>} Promise resolving to DatabaseResult containing boolean indicating existence.\n * @description\n * Checks if a record with the specified ID exists in the table.\n * The method constructs a SELECT query with a WHERE clause for the ID column\n * and a LIMIT of 1. It returns a success result with a boolean value indicating\n * whether the record exists. If an error occurs during the operation, a failure result\n * with an error message is returned.\n */\n async exists(table: string, id: string): Promise<DatabaseResult<boolean>> {\n try {\n const tableName = this.getTableName(table);\n const qualifiedTable = this.getQualifiedTableName(tableName);\n const idColumn = this.getIdColumn(table);\n const sql = `SELECT 1 FROM ${qualifiedTable} WHERE \"${idColumn}\" = $1 LIMIT 1`;\n const result = await this.pool.query(sql, [id]);\n return success(result.rows.length > 0);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to check existence in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.EXISTS_FAILED,\n {\n context: {\n source: \"SQLAdapter.exists\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Count records matching a filter.\n * @param {string} table - Table name.\n * @param {Filter} [filter] - Filter conditions.\n * @returns {Promise<DatabaseResult<number>>} Promise resolving to DatabaseResult containing the count.\n * @description\n * Counts the number of records in the specified table that match the optional filter.\n * The method constructs a COUNT query with an optional WHERE clause based on the filter.\n * It returns a success result with the count of matching records.\n * If an error occurs during the operation, a failure result with an error message is returned.\n */\n async count<T extends Record<string, unknown> = Record<string, unknown>>(\n table: string,\n filter?: Filter<T>,\n ): Promise<DatabaseResult<number>> {\n try {\n const tableName = this.getTableName(table);\n const qualifiedTable = this.getQualifiedTableName(tableName);\n let whereClause = \"\";\n let params: object[] = [];\n\n if (filter) {\n whereClause = this.buildWhereClause(filter, params, 1);\n }\n\n const sql = `SELECT COUNT(*) as count FROM ${qualifiedTable}${whereClause}`;\n const result = await this.pool.query(sql, params);\n const rowCount = Number.parseInt(result.rows[0].count);\n return success(Number(rowCount));\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to count in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.COUNT_FAILED,\n {\n context: {\n source: \"SQLAdapter.count\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Perform health check.\n * @returns {Promise<DatabaseResult<DatabaseHealthStatus>>} Promise resolving to DatabaseResult containing health status.\n * @description\n * Checks the health of the database connection by executing a simple query.\n * The method measures the response time of the query to determine the health status.\n * It returns a success result with a HealthStatus object indicating whether the database is healthy,\n * the response time of the health check, and any additional details.\n * If an error occurs during the operation, a failure result with an error message is returned.\n */\n async healthCheck(): Promise<DatabaseResult<DatabaseHealthStatus>> {\n const startTime = Date.now();\n try {\n await this.pool.query(\"SELECT 1\");\n const responseTime = Date.now() - startTime;\n return success({\n isHealthy: true,\n responseTime,\n details: { adapter: \"sql\" },\n });\n } catch (error) {\n const responseTime = Date.now() - startTime;\n return success({\n isHealthy: false,\n responseTime,\n details: { adapter: \"sql\", error: (error as Error).message },\n });\n }\n }\n\n /**\n * Get the actual table name from the mapped table name.\n * @private\n * @param {string} name - Logical table name.\n * @returns {string} Actual table name.\n * @description\n * Retrieves the actual table name. If not registered, auto-registers it with\n * the same logical name as the physical table name. This enables seamless\n * table operations without manual registration (matching Supabase adapter behavior).\n */\n private getTableName(name: string): string {\n let tableName = this.tableMap.get(name);\n if (!tableName) {\n // Auto-register table with same name\n // Only set ID column from config if not already registered (runtime override takes precedence)\n const hasRuntimeIdColumn = this.idColumnMap.has(name);\n const customIdColumn = hasRuntimeIdColumn\n ? undefined\n : this.configIdColumns[name];\n this.registerTable(name, name, customIdColumn);\n tableName = name;\n }\n return tableName;\n }\n\n /**\n * Get the ID column for a table.\n * @private\n * @param {string} table - Logical table name.\n * @returns {string} ID column name (defaults to 'id').\n * @description\n * Retrieves the ID column for a table. Checks in this order:\n * 1. Runtime registered ID column (from registerTable calls)\n * 2. Config-provided ID column (from tableIdColumns in config)\n * 3. Default 'id' column\n */\n private getIdColumn(table: string): string {\n // Check runtime registered first\n const runtimeIdColumn = this.idColumnMap.get(table);\n if (runtimeIdColumn) {\n return runtimeIdColumn;\n }\n\n // Check config-provided ID columns\n const configIdColumn = this.configIdColumns[table];\n if (configIdColumn) {\n return configIdColumn;\n }\n\n // Default to 'id'\n return \"id\";\n }\n\n private validateBasicParams(table: string, id: string): DatabaseError | null {\n if (!table || !id) {\n return new DatabaseError(\n \"Invalid parameters\",\n DATABASE_ERROR_CODES.INVALID_PARAMS,\n );\n }\n return null;\n }\n\n private validateCreateParams<T>(\n table: string,\n data: T,\n ): DatabaseError | null {\n if (!isNonEmptyString(table) || !isObject(data)) {\n return new DatabaseError(\n \"Invalid parameters\",\n DATABASE_ERROR_CODES.INVALID_PARAMS,\n );\n }\n\n const keys = Object.keys(data as Record<string, T>);\n if (keys.length === 0) {\n return new DatabaseError(\n \"No data to insert\",\n DATABASE_ERROR_CODES.NO_DATA,\n );\n }\n\n for (const key of keys) {\n if (!DB_REGEX.isValidFieldName(key)) {\n return new DatabaseError(\n \"Invalid field name\",\n DATABASE_ERROR_CODES.INVALID_FIELD_NAME,\n );\n }\n }\n return null;\n }\n\n private validateUpdateParams<T>(\n table: string,\n id: string,\n data: Partial<T>,\n ): DatabaseError | null {\n if (!isNonEmptyString(table) || !isNonEmptyString(id) || !isObject(data)) {\n return new DatabaseError(\n \"Invalid parameters for update operation\",\n DATABASE_ERROR_CODES.INVALID_UPDATE_PARAMS,\n );\n }\n\n const keys = Object.keys(data as Record<string, T>);\n if (keys.length === 0) {\n return new DatabaseError(\n \"No fields to update\",\n DATABASE_ERROR_CODES.NO_UPDATE_FIELDS,\n );\n }\n\n for (const key of keys) {\n if (!DB_REGEX.isValidFieldName(key)) {\n return new DatabaseError(\n \"Invalid field name\",\n DATABASE_ERROR_CODES.INVALID_FIELD_NAME,\n );\n }\n }\n return null;\n }\n\n /**\n * Builds a SQL WHERE clause string from a provided filter definition.\n *\n * @private\n * @template TParams - Tuple type representing the parameter array.\n * @param {Filter} filter - The filter condition containing the field, operator, and value.\n * @param {TParams} params - Mutable array to collect SQL parameter values.\n * @param {number} startIndex - The starting index for SQL parameter placeholders (e.g., $1, $2, ...).\n * @returns {string} The constructed SQL WHERE clause string.\n * @throws {DatabaseError} If an unsupported operator is encountered or if the filter value type is invalid.\n *\n * @description\n * This method dynamically builds a SQL WHERE clause based on the provided `filter` object.\n * It supports operators such as:\n * - `eq`, `ne` (equality and inequality)\n * - `gt`, `gte`, `lt`, `lte` (comparison)\n * - `in` (membership in a list)\n * - `like` (pattern matching)\n * - `between` (range)\n * - `isNull`, `isNotNull` (null checks)\n *\n * The function safely constructs parameterized queries by adding each value\n * into the `params` array and referencing it via `$<index>` placeholders,\n * helping to prevent SQL injection attacks.\n */\n\n // eslint-disable-next-line complexity\n private buildWhereClause<\n T extends Record<string, unknown>,\n TParams extends object[],\n >(filter: Filter<T>, params: unknown[], startIndex: number): string {\n const { field, operator, value } = filter;\n let clause = \"\";\n\n switch (operator) {\n case \"eq\":\n clause = ` WHERE ${field} = $${startIndex}`;\n params.push(value);\n break;\n\n case \"ne\":\n clause = ` WHERE ${field} != $${startIndex}`;\n params.push(value);\n break;\n\n case \"gt\":\n clause = ` WHERE ${field} > $${startIndex}`;\n params.push(value);\n break;\n\n case \"gte\":\n clause = ` WHERE ${field} >= $${startIndex}`;\n params.push(value);\n break;\n\n case \"lt\":\n clause = ` WHERE ${field} < $${startIndex}`;\n params.push(value);\n break;\n\n case \"lte\":\n clause = ` WHERE ${field} <= $${startIndex}`;\n params.push(value);\n break;\n\n case \"in\": {\n if (Array.isArray(value)) {\n const arr = value as readonly TParams[];\n const placeholders = arr\n .map((_, i: number) => `$${startIndex + i}`)\n .join(\", \");\n clause = ` WHERE ${field} IN (${placeholders})`;\n params.push(...arr);\n } else {\n throw new DatabaseError(\n `Operator \"in\" requires an array value.`,\n DATABASE_ERROR_CODES.INVALID_IN_OPERATOR,\n );\n }\n break;\n }\n\n case \"like\":\n clause = ` WHERE ${field} LIKE $${startIndex}`;\n params.push(value as TParams);\n break;\n\n case \"between\": {\n if (Array.isArray(value)) {\n const [min, max] = value as [TParams[number], TParams[number]];\n clause = ` WHERE ${field} BETWEEN $${startIndex} AND $${startIndex + 1}`;\n params.push(min, max);\n } else {\n throw new DatabaseError(\n `Operator \"between\" requires a two-element array.`,\n DATABASE_ERROR_CODES.INVALID_BETWEEN_OPERATOR,\n );\n }\n break;\n }\n\n case \"isNull\":\n clause = ` WHERE ${field} IS NULL`;\n break;\n\n case \"isNotNull\":\n clause = ` WHERE ${field} IS NOT NULL`;\n break;\n\n default:\n throw new DatabaseError(\n `Unsupported operator: ${operator}`,\n DATABASE_ERROR_CODES.UNSUPPORTED_OPERATOR,\n );\n }\n\n return clause;\n }\n}\n","/**\n * MockAdapter - In-Memory Database Adapter for Testing\n *\n * Provides a lightweight, in-memory database adapter that mimics\n * the behavior of real database adapters without requiring an actual\n * database connection. Perfect for unit tests and integration tests.\n *\n * @example\n * ```typescript\n * const db = await createDatabaseService({\n * adapter: 'mock',\n * config: {\n * initialData: {\n * users: [{ id: '1', name: 'Test User', email: 'test@example.com' }],\n * campaigns: [{ id: '1', title: 'Test Campaign', creator_id: '1' }]\n * },\n * autoGenerateIds: true\n * }\n * });\n * ```\n */\n\nimport type {\n DatabaseAdapterType,\n DatabaseResult,\n PaginatedResult,\n QueryOptions,\n Transaction,\n DatabaseHealthStatus,\n Filter,\n DbMockAdapterConfig,\n} from \"@plyaz/types/db\";\n\nimport { success, failure } from \"../../utils/databaseResultHelpers\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport { calculatePagination } from \"../../utils/pagination\";\n\n/** Default pagination limit */\nconst DEFAULT_PAGINATION_LIMIT = 50;\n/** Base for random string generation */\nconst RANDOM_STRING_BASE = 36;\n/** Start index for substring in ID generation */\nconst ID_SUBSTRING_START = 2;\n/** End index for substring in ID generation */\nconst ID_SUBSTRING_END = 9;\n/** Required length for between filter values */\nconst BETWEEN_VALUES_LENGTH = 2;\n\n/** Type for table data storage */\ntype TableDataMap = Map<string, Record<string, unknown>>;\n\n/** Filter operator handler type */\ntype FilterOperatorHandler = (\n fieldValue: unknown,\n filterValue: unknown,\n) => boolean;\n\n/** Lookup map for filter operators */\nconst FILTER_OPERATORS: Record<string, FilterOperatorHandler> = {\n eq: (fieldValue, value) => fieldValue === value,\n ne: (fieldValue, value) => fieldValue !== value,\n gt: (fieldValue, value) => (fieldValue as number) > (value as number),\n gte: (fieldValue, value) => (fieldValue as number) >= (value as number),\n lt: (fieldValue, value) => (fieldValue as number) < (value as number),\n lte: (fieldValue, value) => (fieldValue as number) <= (value as number),\n in: (fieldValue, value) =>\n Array.isArray(value) && (value as unknown[]).includes(fieldValue),\n like: (fieldValue, value) =>\n String(fieldValue).toLowerCase().includes(String(value).toLowerCase()),\n between: (fieldValue, value) => {\n const betweenValues = value as [number, number];\n return (\n Array.isArray(betweenValues) &&\n betweenValues.length === BETWEEN_VALUES_LENGTH &&\n (fieldValue as number) >= betweenValues[0] &&\n (fieldValue as number) <= betweenValues[1]\n );\n },\n isNull: (fieldValue) => fieldValue === null || fieldValue === undefined,\n isNotNull: (fieldValue) => fieldValue !== null && fieldValue !== undefined,\n};\n\n/**\n * MockAdapter - In-memory database adapter for testing\n */\nexport class MockAdapter implements DatabaseAdapterType {\n private data: Map<string, Map<string, Record<string, unknown>>> = new Map();\n private config: DbMockAdapterConfig;\n private tableIdColumns: Map<string, string> = new Map();\n private defaultSchema: string;\n private isInitialized = false;\n private transactionDepth = 0;\n private transactionData: Map<\n string,\n Map<string, Record<string, unknown>>\n > | null = null;\n\n constructor(config: Partial<DbMockAdapterConfig> = {}) {\n this.config = {\n autoGenerateIds: true,\n latency: 0,\n failRate: 0,\n ...config,\n } as DbMockAdapterConfig;\n this.defaultSchema = config.schema ?? \"public\";\n\n // Initialize with provided data\n if (config.initialData) {\n this.initializeTableData(config.initialData);\n }\n\n // Register custom ID columns\n if (config.tableIdColumns) {\n for (const [table, idColumn] of Object.entries(config.tableIdColumns)) {\n this.tableIdColumns.set(table, idColumn);\n }\n }\n }\n\n async initialize(): Promise<DatabaseResult<void>> {\n await this.simulateLatency();\n if (this.shouldFail()) {\n return failure(\n new DatabaseError(\n \"Mock initialization failed\",\n DATABASE_ERROR_CODES.INIT_FAILED,\n ),\n );\n }\n\n this.isInitialized = true;\n return success();\n }\n\n async close(): Promise<DatabaseResult<void>> {\n await this.simulateLatency();\n this.data.clear();\n this.isInitialized = false;\n return success();\n }\n\n registerTable<TTable = string, TIdColumn = string>(\n name: string,\n table?: TTable,\n idColumn?: TIdColumn,\n ): void {\n if (idColumn && typeof idColumn === \"string\") {\n this.tableIdColumns.set(name, idColumn);\n }\n\n // Ensure table exists\n if (!this.data.has(name)) {\n this.data.set(name, new Map());\n }\n }\n\n async findById<T>(\n table: string,\n id: string,\n ): Promise<DatabaseResult<T | null>> {\n await this.simulateLatency();\n if (this.shouldFail()) {\n return failure(\n new DatabaseError(\n \"Mock findById failed\",\n DATABASE_ERROR_CODES.FIND_BY_ID_FAILED,\n ),\n );\n }\n\n const tableData = this.getTableData(table);\n const record = tableData.get(id);\n\n return success(record ? ({ ...record } as T) : null);\n }\n\n /**\n * Apply query options (filter, sort) to records\n */\n private applyQueryOptions<T extends Record<string, unknown>>(\n records: Record<string, unknown>[],\n options?: QueryOptions<T>,\n ): Record<string, unknown>[] {\n let result = records;\n if (options?.filter) {\n result = this.applyFilter(result, options.filter);\n }\n if (options?.sort) {\n result = this.applySort(result, options.sort);\n }\n return result;\n }\n\n /**\n * Get pagination params with defaults\n */\n private getPaginationParams<T extends object>(\n options?: QueryOptions<T>,\n ): {\n offset: number;\n limit: number;\n } {\n return {\n offset: options?.pagination?.offset ?? 0,\n limit: options?.pagination?.limit ?? DEFAULT_PAGINATION_LIMIT,\n };\n }\n\n /**\n * Apply pagination to records\n */\n private applyPagination(\n records: Record<string, unknown>[],\n offset: number,\n limit: number,\n ): Record<string, unknown>[] {\n return records.slice(offset, offset + limit);\n }\n\n async findMany<T extends Record<string, unknown>>(\n table: string,\n options?: QueryOptions<T>,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n await this.simulateLatency();\n if (this.shouldFail()) {\n return failure(\n new DatabaseError(\n \"Mock findMany failed\",\n DATABASE_ERROR_CODES.FIND_MANY_FAILED,\n ),\n );\n }\n\n const tableData = this.getTableData(table);\n const allRecords = Array.from(tableData.values());\n const filteredRecords = this.applyQueryOptions(allRecords, options);\n const total = filteredRecords.length;\n const { offset, limit } = this.getPaginationParams(options);\n const paginatedRecords = this.applyPagination(\n filteredRecords,\n offset,\n limit,\n );\n\n return success({\n data: paginatedRecords as T[],\n total,\n pagination: calculatePagination(total, options?.pagination),\n });\n }\n\n async create<T>(table: string, data: T): Promise<DatabaseResult<T>> {\n await this.simulateLatency();\n if (this.shouldFail()) {\n return failure(\n new DatabaseError(\n \"Mock create failed\",\n DATABASE_ERROR_CODES.CREATE_FAILED,\n ),\n );\n }\n\n const tableData = this.getTableData(table);\n const idColumn = this.getIdColumn(table);\n const record = { ...(data as Record<string, unknown>) };\n\n // Generate ID if needed\n if (!record[idColumn] && this.config.autoGenerateIds) {\n record[idColumn] = this.generateId();\n }\n\n const id = record[idColumn];\n if (!id) {\n return failure(\n new DatabaseError(\n \"Record must have an ID\",\n DATABASE_ERROR_CODES.CREATE_FAILED,\n ),\n );\n }\n\n // Add timestamps\n const now = new Date().toISOString();\n record.created_at ??= now;\n record.updated_at ??= now;\n\n tableData.set(String(id), record);\n\n return success(record as T);\n }\n\n async update<T>(\n table: string,\n id: string,\n data: Partial<T>,\n ): Promise<DatabaseResult<T>> {\n await this.simulateLatency();\n if (this.shouldFail()) {\n return failure(\n new DatabaseError(\n \"Mock update failed\",\n DATABASE_ERROR_CODES.UPDATE_FAILED,\n ),\n );\n }\n\n const tableData = this.getTableData(table);\n const existing = tableData.get(id);\n\n if (!existing) {\n return failure(\n new DatabaseError(\n \"Record not found\",\n DATABASE_ERROR_CODES.RECORD_NOT_FOUND,\n ),\n );\n }\n\n const updated = {\n ...existing,\n ...data,\n updated_at: new Date().toISOString(),\n };\n\n tableData.set(id, updated);\n\n return success(updated as T);\n }\n\n async delete(table: string, id: string): Promise<DatabaseResult<void>> {\n await this.simulateLatency();\n if (this.shouldFail()) {\n return failure(\n new DatabaseError(\n \"Mock delete failed\",\n DATABASE_ERROR_CODES.DELETE_FAILED,\n ),\n );\n }\n\n const tableData = this.getTableData(table);\n const existed = tableData.delete(id);\n\n if (!existed) {\n return failure(\n new DatabaseError(\n \"Record not found\",\n DATABASE_ERROR_CODES.RECORD_NOT_FOUND,\n ),\n );\n }\n\n return success();\n }\n\n async transaction<T>(\n callback: (trx: Transaction) => Promise<T>,\n ): Promise<DatabaseResult<T>> {\n await this.simulateLatency();\n\n // Create a snapshot of current data\n const snapshot = new Map<string, TableDataMap>();\n for (const [table, tableData] of this.data.entries()) {\n snapshot.set(table, new Map(tableData));\n }\n\n this.transactionDepth++;\n this.transactionData = snapshot;\n\n try {\n const trx: Transaction = {\n findById: async <T>(table: string, id: string) =>\n this.findById<T>(table, id),\n create: async <T>(table: string, data: T) =>\n this.create<T>(table, data),\n update: async <T>(table: string, id: string, data: Partial<T>) =>\n this.update<T>(table, id, data),\n delete: async (table: string, id: string) => this.delete(table, id),\n commit: async () => {\n /* no-op, auto-committed */\n },\n rollback: async () => {\n // Restore snapshot\n this.data = snapshot;\n },\n };\n\n const result = await callback(trx);\n\n // Transaction succeeded - commit is implicit\n this.transactionDepth--;\n this.transactionData = null;\n\n return success(result);\n } catch (error) {\n // Rollback on error\n this.data = snapshot;\n this.transactionDepth--;\n this.transactionData = null;\n\n return failure(\n new DatabaseError(\n `Transaction failed: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.TRANSACTION_FAILED,\n { cause: error as Error },\n ),\n );\n }\n }\n\n async exists(table: string, id: string): Promise<DatabaseResult<boolean>> {\n await this.simulateLatency();\n const tableData = this.getTableData(table);\n return success(tableData.has(id));\n }\n\n async count<T extends Record<string, unknown> = Record<string, unknown>>(\n table: string,\n filter?: Filter<T>,\n ): Promise<DatabaseResult<number>> {\n await this.simulateLatency();\n const tableData = this.getTableData(table);\n let records = Array.from(tableData.values());\n\n if (filter) {\n records = this.applyFilter(records, filter);\n }\n\n return success(records.length);\n }\n\n async healthCheck(): Promise<DatabaseResult<DatabaseHealthStatus>> {\n await this.simulateLatency();\n\n return success({\n isHealthy: this.isInitialized,\n responseTime: this.config.latency ?? 0,\n details: {\n adapter: \"mock\",\n tables: this.data.size,\n totalRecords: Array.from(this.data.values()).reduce(\n (sum, table) => sum + table.size,\n 0,\n ),\n } as DatabaseHealthStatus[\"details\"],\n });\n }\n\n // DatabaseAdapterType required methods\n\n async connect(): Promise<void> {\n await this.simulateLatency();\n // Mock adapter doesn't need actual connection\n }\n\n async disconnect(): Promise<void> {\n await this.close();\n }\n\n getClient(): object {\n return {\n type: \"mock\",\n data: this.data,\n config: this.config,\n };\n }\n\n async query<T>(): Promise<T[]> {\n await this.simulateLatency();\n // Mock adapter doesn't execute real SQL\n // This is a stub for compatibility\n return [] as T[];\n }\n\n // Utility methods\n\n /**\n * Get fully-qualified table name with schema\n */\n private getQualifiedTableName(table: string, schema?: string): string {\n const targetSchema = schema ?? this.defaultSchema;\n\n // If table already has schema prefix (e.g., \"tenant_acme.users\"), use as-is\n if (table.includes(\".\")) {\n return table;\n }\n\n // For 'public' schema or non-qualified tables, return table name as-is for simplicity\n // This maintains backwards compatibility with existing tests\n if (targetSchema === \"public\") {\n return table;\n }\n\n // Apply schema prefix for non-public schemas\n return `${targetSchema}.${table}`;\n }\n\n private initializeTableData(\n initialData: Record<string, Record<string, unknown>[]>,\n ): void {\n for (const [table, records] of Object.entries(initialData)) {\n const tableData = new Map<string, Record<string, unknown>>();\n const idColumn = this.getIdColumn(table);\n\n for (const record of records) {\n const id = record[idColumn];\n if (id) {\n tableData.set(String(id), { ...record });\n }\n }\n\n this.data.set(table, tableData);\n }\n }\n\n private getTableData(table: string): TableDataMap {\n // Handle schema-qualified table names\n const qualifiedTable = this.getQualifiedTableName(table);\n\n if (!this.data.has(qualifiedTable)) {\n this.data.set(qualifiedTable, new Map());\n }\n return this.data.get(qualifiedTable)!;\n }\n\n private getIdColumn(table: string): string {\n // Strip schema prefix if present to get base table name for ID column lookup\n const baseTable = table.includes(\".\") ? table.split(\".\")[1] : table;\n return this.tableIdColumns.get(baseTable) ?? \"id\";\n }\n\n private generateId(): string {\n return `mock-${Date.now()}-${Math.random().toString(RANDOM_STRING_BASE).substring(ID_SUBSTRING_START, ID_SUBSTRING_END)}`;\n }\n\n private async simulateLatency(): Promise<void> {\n if (this.config.latency && this.config.latency > 0) {\n await new Promise((resolve) => setTimeout(resolve, this.config.latency));\n }\n }\n\n private shouldFail(): boolean {\n if (!this.config.failRate || this.config.failRate <= 0) return false;\n return Math.random() < this.config.failRate;\n }\n\n private applyFilter<T extends Record<string, unknown>>(\n records: Record<string, unknown>[],\n filter: Filter<T>,\n ): Record<string, unknown>[] {\n const { field, operator, value } = filter;\n const handler = FILTER_OPERATORS[operator];\n\n return records.filter((record: Record<string, unknown>) => {\n const fieldValue = record[field];\n return handler ? handler(fieldValue, value) : true;\n });\n }\n\n private applySort(\n records: Record<string, unknown>[],\n sort: Array<{ field: string; direction: \"asc\" | \"desc\" }>,\n ): Record<string, unknown>[] {\n return records.sort((a, b) => {\n for (const { field, direction } of sort) {\n const aVal = a[field];\n const bVal = b[field];\n\n if (aVal === bVal) continue;\n\n const comparison =\n (aVal as string | number) < (bVal as string | number) ? -1 : 1;\n return direction === \"asc\" ? comparison : -comparison;\n }\n return 0;\n });\n }\n\n /**\n * Test utility: Clear all data\n */\n clearAll(): void {\n this.data.clear();\n }\n\n /**\n * Test utility: Get current data for inspection\n */\n getData(\n table?: string,\n ): Record<string, unknown>[] | Record<string, Record<string, unknown>[]> {\n if (table) {\n return Array.from(this.getTableData(table).values());\n }\n\n const result: Record<string, Record<string, unknown>[]> = {};\n for (const [tableName, tableData] of this.data.entries()) {\n result[tableName] = Array.from(tableData.values());\n }\n return result;\n }\n\n /**\n * Test utility: Set data directly\n */\n setData(table: string, records: Record<string, unknown>[]): void {\n const tableData = new Map<string, Record<string, unknown>>();\n const idColumn = this.getIdColumn(table);\n\n for (const record of records) {\n const id = record[idColumn];\n if (id) {\n tableData.set(String(id), { ...record });\n }\n }\n\n this.data.set(table, tableData);\n }\n}\n","/**\n * @fileoverview Adapter Factory for @plyaz/db package\n *\n * This module provides the AdapterFactory class responsible for creating database adapter instances\n * based on configuration. Supports multiple database adapters including Drizzle ORM, Supabase,\n * and raw SQL adapters.\n *\n * Part of the @plyaz/db package factory system that creates the complete adapter chain:\n * AdapterFactory → Base Adapter → Extension Wrappers → Final Adapter Chain\n *\n */\n\nimport { DrizzleAdapter } from \"@adapters/drizzle/DrizzleAdapter\";\nimport { SupabaseAdapter } from \"@adapters/supabase/SupabaseAdapter\";\nimport { SQLAdapter } from \"@adapters/sql/SQLAdapter\";\nimport { MockAdapter } from \"@adapters/mock/MockAdapter\";\nimport type {\n DatabaseAdapterType,\n DatabaseConfig,\n DrizzleAdapterConfig,\n SQLAdapterConfig,\n SupabaseAdapterConfig,\n DbMockAdapterConfig,\n} from \"@plyaz/types/db\";\nimport { ADAPTERS } from \"@plyaz/types/db\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\n\n/**\n * ADAPTER FACTORY - Database Adapter Creation\n *\n * Factory class responsible for creating database adapter instances based on configuration.\n * This is the first step in the adapter chain creation process.\n *\n * **Factory Pattern Implementation:**\n * - Takes adapter type and configuration as input\n * - Returns appropriate DatabaseAdapterType implementation\n * - Handles type safety and error cases\n * - Supports all available database adapters\n *\n * **Supported Adapters:**\n * - DrizzleAdapter: For Drizzle ORM integration\n * - SupabaseAdapter: For Supabase database integration\n * - SQLAdapter: For raw SQL database operations\n *\n * **Usage Flow:**\n * createDatabaseService() → **AdapterFactory.create()** → Base Adapter → Extension Wrappers\n *\n * @example\n * ```typescript\n * // Create Drizzle adapter\n * const drizzleAdapter = AdapterFactory.create(ADAPTERS.DRIZZLE, {\n * adapter: ADAPTERS.DRIZZLE,\n * connection: { host: 'localhost', port: 5432 },\n * database: 'myapp'\n * });\n *\n * // Create Supabase adapter\n * const supabaseAdapter = AdapterFactory.create(ADAPTERS.SUPABASE, {\n * adapter: ADAPTERS.SUPABASE,\n * url: 'https://project.supabase.co',\n * key: 'your-anon-key'\n * });\n * ```\n *\n */\nexport class AdapterFactory {\n /**\n * Creates a new database adapter instance based on the configuration\n *\n * This is the core factory method that instantiates the appropriate database adapter\n * based on the provided type and configuration. Uses TypeScript generics to ensure\n * type safety between adapter type and configuration.\n *\n * **Creation Process:**\n * 1. Validates input parameters (type and config)\n * 2. Uses switch statement to match adapter type\n * 3. Instantiates appropriate adapter class with type-safe config\n * 4. Returns DatabaseAdapterType interface implementation\n *\n * **Type Safety:**\n * - Generic T extends DatabaseConfig ensures config matches adapter type\n * - Type assertions (as DrizzleAdapterConfig) provide compile-time safety\n * - Runtime validation prevents invalid configurations\n *\n * @template T - Database configuration type that extends DatabaseConfig\n * @param {T[\"adapter\"]} type - Adapter type from ADAPTERS enum (drizzle, supabase, sql)\n * @param {T} config - Database configuration object matching the adapter type\n * @returns {DatabaseAdapterType} The appropriate adapter implementation\n *\n * @throws {Error} If adapter type is not provided\n * @throws {Error} If adapter configuration is not provided\n * @throws {Error} If unsupported adapter type is specified\n * @throws {Error} If adapter instantiation fails\n *\n * @example\n * ```typescript\n * // Create Drizzle adapter with PostgreSQL\n * const drizzleAdapter = AdapterFactory.create(ADAPTERS.DRIZZLE, {\n * adapter: ADAPTERS.DRIZZLE,\n * connection: {\n * host: 'localhost',\n * port: 5432,\n * database: 'myapp',\n * user: 'postgres',\n * password: 'password'\n * }\n * });\n *\n * // Create Supabase adapter\n * const supabaseAdapter = AdapterFactory.create(ADAPTERS.SUPABASE, {\n * adapter: ADAPTERS.SUPABASE,\n * url: 'https://xyzcompany.supabase.co',\n * key: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'\n * });\n *\n * // Create SQL adapter for custom database\n * const sqlAdapter = AdapterFactory.create(ADAPTERS.SQL, {\n * adapter: ADAPTERS.SQL,\n * connectionString: 'postgresql://user:pass@localhost:5432/db'\n * });\n * ```\n *\n */\n static create<T extends DatabaseConfig>(\n type: T[\"adapter\"],\n config: T,\n ): DatabaseAdapterType {\n try {\n // Input validation - ensure required parameters are provided\n // This prevents runtime errors from missing configuration\n if (!type) {\n throw new DatabaseError(\n \"Adapter type is required\",\n DATABASE_ERROR_CODES.CONFIG_REQUIRED,\n {\n context: { source: \"AdapterFactory.create\" },\n cause: new Error(\"Adapter type is required\"),\n },\n );\n }\n\n if (!config) {\n throw new DatabaseError(\n \"Adapter configuration is required\",\n DATABASE_ERROR_CODES.CONFIG_REQUIRED,\n {\n context: { source: \"AdapterFactory.create\" },\n cause: new Error(\"Adapter configuration is required\"),\n },\n );\n }\n\n // Adapter instantiation using switch statement for type safety\n // Each case handles a specific adapter type with appropriate configuration casting\n switch (type) {\n // Drizzle ORM adapter - for type-safe database operations\n case ADAPTERS.DRIZZLE:\n return new DrizzleAdapter(config as DrizzleAdapterConfig);\n\n // Supabase adapter - for Supabase backend-as-a-service integration\n case ADAPTERS.SUPABASE:\n return new SupabaseAdapter(config as SupabaseAdapterConfig);\n\n // SQL adapter - for raw SQL operations and custom database integrations\n case ADAPTERS.SQL:\n return new SQLAdapter(config as SQLAdapterConfig);\n\n // Mock adapter - for in-memory testing without real database\n case ADAPTERS.MOCK:\n return new MockAdapter(config as DbMockAdapterConfig);\n\n // Default case - handles unsupported or invalid adapter types\n default:\n throw new DatabaseError(\n `Unsupported adapter type: ${type}`,\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"AdapterFactory.create\" },\n cause: new Error(`Unsupported adapter type: ${type}`),\n },\n );\n }\n } catch (error) {\n // Error handling with context preservation\n // Wraps any instantiation errors with factory-specific context\n throw new DatabaseError(\n `Failed to create adapter: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.INIT_FAILED,\n {\n context: { source: \"AdapterFactory.create\" },\n cause: error as Error,\n },\n );\n }\n }\n}\n","/**\n * @fileoverview Soft Delete Extension for @plyaz/db package\n *\n * This module provides the SoftDeleteAdapter extension that implements logical deletion\n * instead of physical record removal. It automatically intercepts delete operations\n * and converts them to timestamp updates, while filtering queries to exclude soft-deleted records.\n *\n * Part of the @plyaz/db package - a TypeScript database abstraction layer with\n * support for multiple adapters (Drizzle, Supabase, SQL), extensions (audit, encryption,\n * soft delete), and advanced features (caching, read replicas, multi-tenancy).\n *\n */\n\nimport { logger } from \"@plyaz/logger\";\nimport type {\n DatabaseAdapterType,\n DatabaseResult,\n PaginatedResult,\n QueryOptions,\n Filter,\n DatabaseHealthStatus,\n Transaction,\n} from \"@plyaz/types/db\";\nimport { failure, success } from \"@utils/databaseResultHelpers\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\n\n/**\n * SOFT DELETE ADAPTER - Logical Deletion Layer\n *\n * Soft delete extension that implements logical deletion instead of physical removal.\n * Third layer in the adapter chain.\n *\n * **Adapter Chain Position:**\n * ReadReplica -> Audit -> Cache -> **SoftDelete** -> Encryption -> Base Adapter\n *\n * **What this adapter does:**\n * 1. Intercepts delete() operations sets deletedAt timestamp instead of removing\n * 2. Intercepts query/list operations adds \"WHERE deletedAt IS NULL\" filter\n * 3. Provides restore() method to undelete records\n * 4. Honors includeSoftDeleted flag from operation config\n *\n * **Called by:** CachingAdapter (or AuditAdapter if no caching)\n * **Calls:** EncryptionAdapter (or base adapter if no encryption)\n * **Provides:** restore(), permanentDelete() methods\n *\n * **Soft Delete Flow:**\n * - **Delete:** Sets deletedAt = NOW() instead of removing record\n * - **Queries:** Automatically filters WHERE deletedAt IS NULL\n * - **Restore:** Sets deletedAt = NULL to undelete\n *\n * @example\n * ### Configuration\n * ```typescript\n * softDelete: {\n * enabled: true,\n * field: 'deletedAt', // Custom field name\n * excludeTables: ['audit_logs'] // Tables that use hard delete\n * }\n * ```\n *\n * @example\n * ### Usage Flow\n * ```typescript\n * // Normal delete - sets deletedAt timestamp\n * await db.delete(Tables.USERS, 'user-123');\n *\n * // Query automatically excludes soft-deleted records\n * const activeUsers = await db.query(Tables.USERS, {});\n *\n * // Include soft-deleted records with operation config\n * const allUsers = await db.query(Tables.USERS, {}, {\n * includeSoftDeleted: true\n * });\n *\n * // Restore soft-deleted record\n * await db.restore(Tables.USERS, 'user-123');\n * ```\n */\nexport class SoftDeleteAdapter implements DatabaseAdapterType {\n /**\n * Creates a new SoftDeleteAdapter instance.\n *\n * **RESPONSIBILITY:** Wraps base adapter with soft delete functionality\n * **CONFIGURATION:** Sets up deletion field name and excluded tables\n *\n * @param baseAdapter - The underlying database adapter to wrap\n * @param config - Soft delete configuration options\n *\n * @example\n * ```typescript\n * const softDeleteAdapter = new SoftDeleteAdapter(baseAdapter, {\n * enabled: true,\n * field: 'deletedAt',\n * excludeTables: ['audit_logs', 'system_events']\n * });\n * ```\n */\n constructor(\n public baseAdapter: DatabaseAdapterType,\n private config: {\n enabled: boolean;\n field?: string;\n excludeTables?: string[];\n },\n ) {}\n\n /**\n * Initializes the soft delete adapter and underlying adapter.\n *\n * **RESPONSIBILITY:** Passes initialization to base adapter\n * **BEHAVIOR:** No additional initialization needed for soft delete\n *\n * @returns Promise resolving to initialization result\n *\n * @example\n * ```typescript\n * const result = await softDeleteAdapter.initialize();\n * if (result.success) {\n * console.log('Soft delete adapter initialized');\n * }\n * ```\n */\n async initialize(): Promise<DatabaseResult<void>> {\n return this.baseAdapter.initialize();\n }\n\n /**\n * Establishes database connection through base adapter.\n *\n * **RESPONSIBILITY:** Delegates connection to underlying adapter\n * **BEHAVIOR:** No additional connection logic needed\n *\n * @example\n * ```typescript\n * await softDeleteAdapter.connect();\n * console.log('Connected with soft delete support');\n * ```\n */\n async connect(): Promise<void> {\n return this.baseAdapter.connect();\n }\n\n /**\n * Closes database connection through base adapter.\n *\n * **RESPONSIBILITY:** Delegates disconnection to underlying adapter\n * **BEHAVIOR:** No additional cleanup needed for soft delete\n *\n * @example\n * ```typescript\n * await softDeleteAdapter.disconnect();\n * console.log('Disconnected gracefully');\n * ```\n */\n async disconnect(): Promise<void> {\n return this.baseAdapter.disconnect();\n }\n\n async close(): Promise<DatabaseResult<void>> {\n return this.baseAdapter.close();\n }\n\n /**\n * Gets the underlying database client.\n *\n * **RESPONSIBILITY:** Provides access to raw database client\n * **USE CASE:** For operations that bypass soft delete logic\n *\n * @returns Database client object\n *\n * @example\n * ```typescript\n * const client = softDeleteAdapter.getClient();\n * // Use for direct database operations if needed\n * ```\n */\n getClient(): object {\n return this.baseAdapter.getClient();\n }\n\n /**\n * Executes raw SQL query through base adapter.\n *\n * **RESPONSIBILITY:** Passes raw SQL to base adapter without modification\n * **BEHAVIOR:** Does not apply soft delete filtering to raw SQL\n * **NOTE:** Use findMany() for automatic soft delete filtering\n *\n * @param sql - SQL query string\n * @param params - Query parameters\n * @returns Query results\n *\n * @example\n * ```typescript\n * // Raw SQL bypasses soft delete filtering\n * const allUsers = await adapter.query(\n * 'SELECT * FROM users', // Includes soft-deleted records\n * []\n * );\n *\n * // Use findMany for automatic filtering\n * const activeUsers = await adapter.findMany('users'); // Excludes soft-deleted\n * ```\n */\n async query<T>(sql: string, params?: T[]): Promise<T[]> {\n return this.baseAdapter.query(sql, params);\n }\n\n /**\n * Registers a table schema with the base adapter.\n *\n * **RESPONSIBILITY:** Passes table registration to base adapter\n * **BEHAVIOR:** No additional registration logic needed\n *\n * @param name - Table name\n * @param table - Table schema\n * @param idColumn - Primary key column\n *\n * @example\n * ```typescript\n * softDeleteAdapter.registerTable('users', userSchema, 'id');\n * // Table now supports soft delete operations\n * ```\n */\n registerTable<T, U>(name: string, table: T, idColumn?: U): void {\n this.baseAdapter.registerTable(name, table, idColumn);\n }\n\n /**\n * Finds a record by ID with automatic soft delete filtering.\n *\n * **RESPONSIBILITY:** Retrieves single record, excluding soft-deleted by default\n * **FILTERING:** Automatically excludes records where deletedAt IS NOT NULL\n * **OVERRIDE:** Can include soft-deleted records with operation config\n *\n * @param table - Table name\n * @param id - Record ID\n * @returns Found record or null\n *\n * @example\n * ```typescript\n * // Excludes soft-deleted records by default\n * const user = await adapter.findById('users', 'user-123');\n * if (!user.value) {\n * console.log('User not found or soft-deleted');\n * }\n *\n * // Include soft-deleted records with config\n * const userIncludingDeleted = await adapter.findById('users', 'user-123', {\n * includeSoftDeleted: true\n * });\n * ```\n */\n async findById<T>(\n table: string,\n id: string,\n ): Promise<DatabaseResult<T | null>> {\n return this.baseAdapter.findById<T>(table, id);\n }\n\n async findMany<T extends Record<string, unknown>>(\n table: string,\n options?: QueryOptions<T>,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n if (!this.config.enabled || this.isExcluded(table)) {\n return this.baseAdapter.findMany<T>(table, options);\n }\n\n // Add soft delete filter unless includeSoftDeleted is true\n const modifiedOptions: QueryOptions<T> = { ...options };\n modifiedOptions.filter ??= {\n field: this.config.field ?? \"deletedAt\",\n operator: \"isNull\",\n value: null,\n } as Filter<T>;\n\n return this.baseAdapter.findMany<T>(table, modifiedOptions);\n }\n\n /**\n * Creates a new record through base adapter.\n *\n * **RESPONSIBILITY:** Passes creation to base adapter without modification\n * **BEHAVIOR:** New records have deletedAt = NULL by default\n *\n * @param table - Table name\n * @param data - Record data\n * @returns Created record\n *\n * @example\n * ```typescript\n * const result = await adapter.create('users', {\n * name: 'John Doe',\n * email: 'john@example.com'\n * // deletedAt will be NULL (not soft-deleted)\n * });\n *\n * if (result.success) {\n * console.log('User created:', result.value.id);\n * }\n * ```\n */\n async create<T extends Record<string, unknown>>(\n table: string,\n data: T,\n ): Promise<DatabaseResult<T>> {\n return this.baseAdapter.create<T>(table, data);\n }\n\n /**\n * Updates an existing record through base adapter.\n *\n * **RESPONSIBILITY:** Passes update to base adapter without modification\n * **BEHAVIOR:** Can update soft-deleted records (they remain soft-deleted)\n * **NOTE:** Use restore() to undelete records\n *\n * @param table - Table name\n * @param id - Record ID\n * @param data - Partial record data\n * @returns Updated record\n *\n * @example\n * ```typescript\n * // Update active record\n * const result = await adapter.update('users', 'user-123', {\n * name: 'Jane Doe'\n * });\n *\n * // Can also update soft-deleted records\n * const softDeletedUpdate = await adapter.update('users', 'deleted-user', {\n * email: 'newemail@example.com'\n * // Record remains soft-deleted after update\n * });\n * ```\n */\n async update<T>(\n table: string,\n id: string,\n data: Partial<T>,\n ): Promise<DatabaseResult<T>> {\n return this.baseAdapter.update<T>(table, id, data);\n }\n\n async delete(table: string, id: string): Promise<DatabaseResult<void>> {\n if (!this.config.enabled || this.isExcluded(table)) {\n return this.baseAdapter.delete(table, id);\n }\n\n // Soft delete: set deletedAt field\n const deleteField = this.config.field ?? \"deletedAt\";\n const updateData = { [deleteField]: new Date().toISOString() };\n\n try {\n logger.debug(`Soft deleting record ${id} from table ${table}`);\n await this.baseAdapter.update(table, id, updateData);\n return success();\n } catch (error) {\n logger.error(`Soft delete failed for ${table}:${id}`);\n return failure(\n new DatabaseError(\n `Soft delete failed: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.DELETE_FAILED,\n {\n context: { source: \"delete\" },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Executes operations within a transaction.\n *\n * **RESPONSIBILITY:** Passes transaction to base adapter\n * **BEHAVIOR:** Soft delete operations within transaction are atomic\n * **ROLLBACK:** Failed transactions rollback soft delete operations\n *\n * @param callback - Transaction callback function\n * @returns Transaction result\n *\n * @example\n * ```typescript\n * const result = await adapter.transaction(async (trx) => {\n * // Create user\n * const user = await trx.create('users', { name: 'John' });\n *\n * // Soft delete old user (sets deletedAt)\n * await trx.delete('users', 'old-user-id');\n *\n * return user;\n * });\n *\n * // If transaction fails, both operations are rolled back\n * ```\n */\n async transaction<T>(\n callback: (trx: Transaction) => Promise<T>,\n ): Promise<DatabaseResult<T>> {\n return this.baseAdapter.transaction(callback);\n }\n\n /**\n * Checks if a record exists, excluding soft-deleted records.\n *\n * **RESPONSIBILITY:** Verifies record existence with soft delete filtering\n * **BEHAVIOR:** Returns false for soft-deleted records by default\n * **FILTERING:** Automatically excludes records where deletedAt IS NOT NULL\n *\n * @param table - Table name\n * @param id - Record ID\n * @returns True if record exists and is not soft-deleted\n *\n * @example\n * ```typescript\n * // Check if active user exists\n * const userExists = await adapter.exists('users', 'user-123');\n * if (userExists.value) {\n * console.log('User exists and is active');\n * } else {\n * console.log('User not found or soft-deleted');\n * }\n *\n * // Soft-deleted records return false\n * await adapter.delete('users', 'user-123'); // Soft delete\n * const stillExists = await adapter.exists('users', 'user-123'); // false\n * ```\n */\n async exists(table: string, id: string): Promise<DatabaseResult<boolean>> {\n return this.baseAdapter.exists(table, id);\n }\n\n /**\n * Counts records in a table, excluding soft-deleted records.\n *\n * **RESPONSIBILITY:** Counts records with automatic soft delete filtering\n * **BEHAVIOR:** Excludes soft-deleted records from count by default\n * **FILTERING:** Automatically adds deletedAt IS NULL filter\n *\n * @param table - Table name\n * @param filter - Optional filter conditions\n * @returns Count of non-soft-deleted records\n *\n * @example\n * ```typescript\n * // Count active users only\n * const activeCount = await adapter.count('users');\n * console.log('Active users:', activeCount.value);\n *\n * // Count with additional filter\n * const premiumActiveUsers = await adapter.count('users', {\n * field: 'plan',\n * operator: 'eq',\n * value: 'premium'\n * });\n * // Returns count of premium users that are NOT soft-deleted\n * ```\n */\n async count<T extends Record<string, unknown> = Record<string, unknown>>(\n table: string,\n filter?: Filter<T>,\n ): Promise<DatabaseResult<number>> {\n return this.baseAdapter.count<T>(table, filter);\n }\n\n /**\n * Performs health check through base adapter.\n *\n * **RESPONSIBILITY:** Delegates health check to underlying adapter\n * **BEHAVIOR:** No additional health metrics for soft delete\n *\n * @returns Health status from base adapter\n *\n * @example\n * ```typescript\n * const health = await adapter.healthCheck();\n * if (health.success && health.value?.isHealthy) {\n * console.log('Database healthy with soft delete support');\n * }\n * ```\n */\n async healthCheck(): Promise<DatabaseResult<DatabaseHealthStatus>> {\n return this.baseAdapter.healthCheck();\n }\n\n /**\n * Restores a previously soft-deleted record by clearing the deletion timestamp\n *\n * Undeletes a record by setting the soft delete field (typically 'deletedAt') to null,\n * making it visible in queries again. This operation is only available when soft delete\n * is enabled in the configuration.\n *\n * **Restore Process:**\n * 1. Validates that soft delete is enabled\n * 2. Sets the deletion field to null via update operation\n * 3. Logs the restoration for audit purposes\n * 4. Returns success or failure result\n *\n * @param {string} table - Name of the table containing the record to restore\n * @param {string} id - Primary key ID of the record to restore\n * @returns {Promise<DatabaseResult<void>>} Promise resolving to success/failure result\n *\n * @example\n * ```typescript\n * // Restore a soft-deleted user\n * const restoreResult = await softDeleteAdapter.restore('users', 'user-123');\n * if (restoreResult.success) {\n * console.log('User restored successfully');\n * } else {\n * console.error('Restore failed:', restoreResult.error.message);\n * }\n *\n * // After restoration, the record will appear in queries again\n * const user = await adapter.findById('users', 'user-123');\n * // user will now be found (not null)\n * ```\n *\n * @throws {DatabaseError} SOFT_DELETE_NOT_ENABLED - If soft delete is not enabled in configuration\n * @throws {DatabaseError} SOFT_DELETE_RESTORE_FAILED - If the restore operation fails\n *\n */\n async restore(table: string, id: string): Promise<DatabaseResult<void>> {\n // Validate that soft delete is enabled before attempting restore\n if (!this.config.enabled) {\n return failure(\n new DatabaseError(\n \"Soft delete not enabled\",\n DATABASE_ERROR_CODES.CONFIG_REQUIRED,\n {\n context: { source: \"restore\" },\n cause: new Error(\"Soft delete not enabled\"),\n },\n ),\n );\n }\n\n // Get the configured deletion field name (default: 'deletedAt')\n const deleteField = this.config.field ?? \"deletedAt\";\n // Create update data to clear the deletion timestamp\n const updateData = { [deleteField]: null };\n\n try {\n // Update the record to clear the deletion timestamp\n await this.baseAdapter.update(table, id, updateData);\n logger.info(`Record restored successfully: ${table}:${id}`);\n return success();\n } catch (error) {\n logger.error(`Restore failed for ${table}:${id}`);\n return failure(\n new DatabaseError(\n `Restore failed: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.UPDATE_FAILED,\n {\n context: { source: \"restore\" },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Checks if a table is excluded from soft delete functionality.\n * \n * **RESPONSIBILITY:** Determines if table should use hard delete instead\n * **CONFIGURATION:** Based on excludeTables array in config\n * **USE CASE:** Some tables like audit logs need permanent deletion\n * \n * @private\n * @param table - Name of the table to check\n * @returns True if table is excluded from soft delete\n * \n * @example\n * ```typescript\n * // Configuration: { excludeTables: ['audit_logs', 'temp_data'] }\n * \n * this.isExcluded('users'); // false - uses soft delete\n * this.isExcluded('audit_logs'); // true - uses hard delete\n * this.isExcluded('t\n private isExcluded(table: string): boolean {\n return this.config.excludeTables?.includes(table) ?? false;\n }emp_data'); // true - uses hard delete\n * ```\n * \n */\n private isExcluded(table: string): boolean {\n // Check if table is in the excludeTables array, default to false if not configured\n return this.config.excludeTables?.includes(table) ?? false;\n }\n}\n","import { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport { logger } from \"@plyaz/logger\";\nimport type {\n DatabaseAdapterType,\n DatabaseResult,\n Filter,\n DatabaseHealthStatus,\n PaginatedResult,\n QueryOptions,\n Transaction,\n AuditContext,\n AuditEvent,\n} from \"@plyaz/types/db\";\nimport { AUDIT_OPERATION, EXTENSION_SOURCE } from \"@plyaz/types/db\";\n\n/** Minimum width for padded date parts (month, day) */\nconst DATE_PART_MIN_WIDTH = 2;\n\n/** Error source patterns for context-based matching */\nconst CONTEXT_SOURCE_PATTERNS: Array<{\n patterns: string[];\n source: EXTENSION_SOURCE;\n}> = [\n { patterns: [\"encrypt\"], source: EXTENSION_SOURCE.Encryption },\n {\n patterns: [\"softdelete\", \"soft_delete\"],\n source: EXTENSION_SOURCE.SoftDelete,\n },\n { patterns: [\"cach\"], source: EXTENSION_SOURCE.Caching },\n { patterns: [\"audit\"], source: EXTENSION_SOURCE.Audit },\n {\n patterns: [\"replica\", \"read_replica\"],\n source: EXTENSION_SOURCE.ReadReplica,\n },\n {\n patterns: [\"multi_write\", \"multiwrite\"],\n source: EXTENSION_SOURCE.MultiWrite,\n },\n];\n\n/** Error source patterns for message-based matching */\nconst MESSAGE_SOURCE_PATTERNS: Array<{\n patterns: string[];\n source: EXTENSION_SOURCE;\n}> = [\n { patterns: [\"encrypt\"], source: EXTENSION_SOURCE.Encryption },\n {\n patterns: [\"soft delete\", \"softdelete\"],\n source: EXTENSION_SOURCE.SoftDelete,\n },\n { patterns: [\"cache\", \"caching\"], source: EXTENSION_SOURCE.Caching },\n {\n patterns: [\"replica\", \"read replica\"],\n source: EXTENSION_SOURCE.ReadReplica,\n },\n {\n patterns: [\"multi-write\", \"multiwrite\"],\n source: EXTENSION_SOURCE.MultiWrite,\n },\n];\n\n/**\n * AUDIT ADAPTER - Compliance Logging Layer\n *\n * Audit extension that automatically logs all database operations for compliance.\n * Fifth layer in the adapter chain (second from outermost).\n *\n * **Adapter Chain Position:**\n * ReadReplica � **Audit** � Cache � SoftDelete � Encryption � Base Adapter\n *\n * **What this adapter does:**\n * 1. Captures before-state for update/delete operations\n * 2. Delegates to next adapter in chain\n * 3. Captures after-state and writes audit record to daily audit tables\n * 4. Calls onAuditAfterWrite event handler (if configured)\n * 5. Honors skipAudit flag from operation config\n *\n * **Called by:** ReadReplicaAdapter (or DatabaseService if no read replicas)\n * **Calls:** CachingAdapter (or next adapter in chain)\n * **Writes to:** Daily partitioned audit tables ({schema}.audit_log_yyyy_mm_dd)\n *\n * **Audit Flow:**\n * 1. **CREATE:** Records after-state only\n * 2. **UPDATE:** Records before-state, after-state, and changed fields\n * 3. **DELETE:** Records before-state only\n * 4. **SOFT_DELETE:** Records before/after state with deletedAt change\n *\n * **Audit Context:** Uses context from DatabaseService.setAuditContext()\n * - userId, requestId, ipAddress, userAgent\n *\n * @example\n * ### Configuration\n * ```typescript\n * audit: {\n * enabled: true,\n * retentionDays: 90,\n * excludeFields: ['password', 'token'],\n * excludeTables: ['temp_data'],\n * onAuditAfterWrite: async (event) => {\n * await complianceService.recordAudit(event);\n * }\n * }\n * ```\n *\n * @example\n * ### Audit Record Structure\n * ```typescript\n * // Written to audit_20241201 table\n * {\n * operation: 'UPDATE',\n * table: 'users',\n * recordId: 'user-123',\n * userId: 'admin-456',\n * requestId: 'req-789',\n * changes: {\n * before: { name: 'John Doe', email: 'john@old.com' },\n * after: { name: 'John Smith', email: 'john@new.com' },\n * fields: ['name', 'email']\n * },\n * timestamp: '2024-12-01T10:30:00Z',\n * ipAddress: '192.168.1.1',\n * userAgent: 'Mozilla/5.0...'\n * }\n * ```\n */\nexport class AuditAdapter implements DatabaseAdapterType {\n private auditContext: AuditContext = {};\n // Using shared logger instance from @plyaz/logger\n\n /** Cached schema-qualified table name */\n private auditSchema: string;\n /** Whether to use daily partitioned tables */\n private usePartitionedTables: boolean;\n\n /**\n * Creates a new AuditAdapter instance.\n *\n * **RESPONSIBILITY:** Wraps base adapter with audit logging functionality\n * **CONFIGURATION:** Sets up audit rules, retention, and event handlers\n *\n * @param baseAdapter - The underlying database adapter to wrap\n * @param config - Audit configuration options\n *\n * @example\n * ```typescript\n * const auditAdapter = new AuditAdapter(baseAdapter, {\n * enabled: true,\n * retentionDays: 180,\n * excludeFields: ['password', 'token'],\n * excludeTables: ['temp_data'],\n * schema: 'audit',\n * usePartitionedTables: true,\n * onAuditAfterWrite: async (event) => {\n * await complianceService.recordAudit(event);\n * }\n * });\n * ```\n */\n constructor(\n public baseAdapter: DatabaseAdapterType,\n private config: {\n enabled: boolean;\n retentionDays?: number;\n excludeFields?: string[];\n excludeTables?: string[];\n /** Database schema for audit tables (default: 'audit') */\n schema?: string;\n /** Use daily partitioned tables (audit_log_yyyy_mm_dd format) (default: true) */\n usePartitionedTables?: boolean;\n onAuditAfterWrite?: (event: AuditEvent) => void | Promise<void>;\n /** Encrypted fields config from encryption extension (for audit metadata) */\n encryptedFields?: Record<string, string[]>;\n },\n ) {\n this.auditSchema = config.schema ?? \"audit\";\n this.usePartitionedTables = config.usePartitionedTables ?? true;\n }\n\n /**\n * Initializes the audit adapter and underlying adapter.\n *\n * **RESPONSIBILITY:** Passes initialization to base adapter\n * **BEHAVIOR:** No additional initialization needed for audit\n *\n * @returns Promise resolving to initialization result\n *\n * @example\n * ```typescript\n * const result = await auditAdapter.initialize();\n * if (result.success) {\n * console.log('Audit adapter initialized');\n * }\n * ```\n */\n async initialize(): Promise<DatabaseResult<void>> {\n return this.baseAdapter.initialize();\n }\n\n /**\n * Establishes database connection through base adapter.\n *\n * **RESPONSIBILITY:** Delegates connection to underlying adapter\n * **BEHAVIOR:** No additional connection logic needed\n *\n * @example\n * ```typescript\n * await auditAdapter.connect();\n * console.log('Connected with audit support');\n * ```\n */\n async connect(): Promise<void> {\n return this.baseAdapter.connect();\n }\n\n /**\n * Closes database connection through base adapter.\n *\n * **RESPONSIBILITY:** Delegates disconnection to underlying adapter\n * **BEHAVIOR:** No additional cleanup needed for audit\n *\n * @example\n * ```typescript\n * await auditAdapter.disconnect();\n * console.log('Disconnected gracefully');\n * ```\n */\n async disconnect(): Promise<void> {\n return this.baseAdapter.disconnect();\n }\n\n async close(): Promise<DatabaseResult<void>> {\n return this.baseAdapter.close();\n }\n\n /**\n * Gets the underlying database client.\n *\n * **RESPONSIBILITY:** Provides access to raw database client\n * **USE CASE:** For operations that bypass audit logging\n *\n * @returns Database client object\n *\n * @example\n * ```typescript\n * const client = auditAdapter.getClient();\n * // Use for direct database operations if needed\n * ```\n */\n getClient(): object {\n return this.baseAdapter.getClient();\n }\n\n /**\n * Executes raw SQL query through base adapter.\n *\n * **RESPONSIBILITY:** Passes raw SQL to base adapter without audit logging\n * **BEHAVIOR:** Does not audit raw SQL operations\n * **NOTE:** Use CRUD methods for automatic audit logging\n *\n * @param sql - SQL query string\n * @param params - Query parameters\n * @returns Query results\n *\n * @example\n * ```typescript\n * // Raw SQL bypasses audit logging\n * const results = await adapter.query(\n * 'SELECT * FROM users WHERE status = $1',\n * ['active']\n * );\n *\n * // Use findMany for automatic audit logging\n * const users = await adapter.findMany('users', { filter: ... });\n * ```\n */\n async query<T>(sql: string, params?: T[]): Promise<T[]> {\n return this.baseAdapter.query(sql, params);\n }\n\n /**\n * Registers a table schema with the base adapter.\n *\n * **RESPONSIBILITY:** Passes table registration to base adapter\n * **BEHAVIOR:** No additional registration logic needed\n *\n * @param name - Table name\n * @param table - Table schema\n * @param idColumn - Primary key column\n *\n * @example\n * ```typescript\n * auditAdapter.registerTable('users', userSchema, 'id');\n * // Table now supports audited operations\n * ```\n */\n registerTable<T, U>(name: string, table: T, idColumn?: U): void {\n this.baseAdapter.registerTable(name, table, idColumn);\n }\n\n /**\n * Sets audit context for tracking user actions.\n *\n * **RESPONSIBILITY:** Stores context information for audit records\n * **CONTEXT:** userId, requestId, ipAddress, userAgent\n * **USAGE:** Called by DatabaseService.setAuditContext()\n *\n * @param context - Audit context information\n *\n * @example\n * ```typescript\n * // Usually called by middleware\n * auditAdapter.setAuditContext({\n * userId: 'user-123',\n * requestId: 'req-456',\n * ipAddress: '192.168.1.1',\n * userAgent: 'Mozilla/5.0...'\n * });\n *\n * // Subsequent operations will include this context in audit logs\n * await adapter.create('users', userData); // Audited with context\n * ```\n */\n setAuditContext(context: AuditContext): void {\n this.auditContext = { ...this.auditContext, ...context };\n }\n\n /**\n * Finds a record by ID without audit logging.\n *\n * **RESPONSIBILITY:** Retrieves single record without creating audit trail\n * **BEHAVIOR:** Read operations are not audited by default\n * **PERFORMANCE:** No audit overhead for read operations\n *\n * @param table - Table name\n * @param id - Record ID\n * @returns Found record or null\n *\n * @example\n * ```typescript\n * // Read operations don't create audit records\n * const user = await adapter.findById('users', 'user-123');\n * if (user.success && user.value) {\n * console.log('User found:', user.value.name);\n * }\n * ```\n */\n async findById<T>(\n table: string,\n id: string,\n ): Promise<DatabaseResult<T | null>> {\n return this.baseAdapter.findById<T>(table, id);\n }\n\n /**\n * Finds multiple records without audit logging.\n *\n * **RESPONSIBILITY:** Retrieves multiple records without creating audit trail\n * **BEHAVIOR:** Read operations are not audited by default\n * **PERFORMANCE:** No audit overhead for read operations\n *\n * @param table - Table name\n * @param options - Query options\n * @returns Paginated results\n *\n * @example\n * ```typescript\n * // Read operations don't create audit records\n * const users = await adapter.findMany('users', {\n * filter: { field: 'status', operator: 'eq', value: 'active' },\n * pagination: { page: 1, limit: 10 }\n * });\n *\n * console.log('Found users:', users.value?.data.length);\n * ```\n */\n async findMany<T extends Record<string, unknown>>(\n table: string,\n options?: QueryOptions<T>,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n return this.baseAdapter.findMany<T>(table, options);\n }\n\n async create<T extends Record<string, unknown>>(\n table: string,\n data: T,\n ): Promise<DatabaseResult<T>> {\n this.validateCreateParams(table, data);\n\n try {\n const result = await this.baseAdapter.create<T>(table, data);\n\n if (result.success && this.shouldAudit(table)) {\n await this.logAudit({\n operation: AUDIT_OPERATION.Create,\n table,\n recordId: (result.value as Record<string, string>)?.id,\n changes: {\n after: result.value as Record<\n string,\n string | number | boolean | Date\n >,\n encryptedFields: this.getEncryptedFields(table),\n },\n userId: this.auditContext.userId,\n requestId: this.auditContext.requestId,\n timestamp: new Date(),\n ipAddress: this.auditContext.ipAddress,\n userAgent: this.auditContext.userAgent,\n });\n }\n\n return result;\n } catch (error) {\n // Log the failure to audit before re-throwing\n if (this.shouldAudit(table)) {\n await this.logOperationFailure({\n operation: AUDIT_OPERATION.Create,\n table,\n data,\n error: error as Error,\n });\n }\n throw error;\n }\n }\n\n private validateCreateParams<T>(table: string, data: T): void {\n if (!table || !data) {\n throw new DatabaseError(\n \"Invalid parameters for create operation\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"validateCreateParams\" },\n cause: new Error(\"Invalid parameters for create operation\"),\n },\n );\n }\n }\n\n async update<T>(\n table: string,\n id: string,\n data: Partial<T>,\n ): Promise<DatabaseResult<T>> {\n // Get before state for audit (before any operation)\n const before = await this.baseAdapter.findById(table, id);\n\n try {\n const result = await this.baseAdapter.update<T>(table, id, data);\n\n if (result.success && this.shouldAudit(table)) {\n await this.logAudit({\n operation: AUDIT_OPERATION.Update,\n table,\n recordId: id,\n changes: {\n before: before.success\n ? (before.value as Record<\n string,\n string | number | boolean | Date\n >)\n : undefined,\n after: result.value as Record<\n string,\n string | number | boolean | Date\n >,\n fields: Object.keys(data),\n encryptedFields: this.getEncryptedFields(table),\n },\n userId: this.auditContext.userId,\n requestId: this.auditContext.requestId,\n timestamp: new Date(),\n ipAddress: this.auditContext.ipAddress,\n userAgent: this.auditContext.userAgent,\n });\n }\n\n return result;\n } catch (error) {\n // Log the failure to audit before re-throwing\n if (this.shouldAudit(table)) {\n await this.logOperationFailure({\n operation: AUDIT_OPERATION.Update,\n table,\n data,\n error: error as Error,\n recordId: id,\n beforeState: before.value,\n });\n }\n throw error;\n }\n }\n\n async delete(table: string, id: string): Promise<DatabaseResult<void>> {\n // Get before state for audit\n const before = await this.baseAdapter.findById(table, id);\n\n try {\n const result = await this.baseAdapter.delete(table, id);\n\n if (result.success && this.shouldAudit(table)) {\n await this.logAudit({\n operation: AUDIT_OPERATION.Delete,\n table,\n recordId: id,\n changes: {\n before: before.success\n ? (before.value as Record<\n string,\n string | number | boolean | Date\n >)\n : undefined,\n },\n userId: this.auditContext.userId,\n requestId: this.auditContext.requestId,\n timestamp: new Date(),\n ipAddress: this.auditContext.ipAddress,\n userAgent: this.auditContext.userAgent,\n });\n }\n\n return result;\n } catch (error) {\n // Log the failure to audit before re-throwing\n if (this.shouldAudit(table)) {\n await this.logOperationFailure({\n operation: AUDIT_OPERATION.Delete,\n table,\n data: null,\n error: error as Error,\n recordId: id,\n beforeState: before.value,\n });\n }\n throw error;\n }\n }\n\n /**\n * Logs operation failures to audit for compliance tracking.\n * Captures the before state, attempted changes, and error details.\n */\n private async logOperationFailure<T>(options: {\n operation: AUDIT_OPERATION;\n table: string;\n data: T | null;\n error: Error;\n recordId?: string;\n beforeState?: unknown;\n }): Promise<void> {\n const { operation, table, data, error, recordId, beforeState } = options;\n\n try {\n // Determine error source (which extension failed)\n const errorSource = this.getErrorSource(error);\n\n // Map operation to failed operation\n const failedOperation = this.getFailedOperation(operation);\n\n await this.logAudit({\n operation: failedOperation,\n table,\n recordId: recordId ?? (data as Record<string, string>)?.id,\n changes: {\n before: beforeState as\n | Record<string, string | number | boolean | Date>\n | undefined,\n attempted: data as\n | Record<string, string | number | boolean | Date>\n | undefined,\n failure: {\n source: errorSource,\n error_type: error.name,\n error_message: error.message,\n error_code: (error as DatabaseError).errorCode,\n },\n },\n userId: this.auditContext.userId,\n requestId: this.auditContext.requestId,\n timestamp: new Date(),\n ipAddress: this.auditContext.ipAddress,\n userAgent: this.auditContext.userAgent,\n });\n } catch (auditError) {\n // Log to console if audit write fails - don't suppress the original error\n logger.error(\n `Failed to log operation failure to audit: ${(auditError as Error).message}`,\n );\n }\n }\n\n /**\n * Maps a successful operation to its failed counterpart.\n */\n private getFailedOperation(operation: AUDIT_OPERATION): AUDIT_OPERATION {\n switch (operation) {\n case AUDIT_OPERATION.Create:\n return AUDIT_OPERATION.CreateFailed;\n case AUDIT_OPERATION.Update:\n return AUDIT_OPERATION.UpdateFailed;\n case AUDIT_OPERATION.Delete:\n return AUDIT_OPERATION.DeleteFailed;\n default:\n return operation;\n }\n }\n\n /**\n * Determines which extension/layer caused the error based on error details.\n */\n private getErrorSource(error: Error): EXTENSION_SOURCE {\n const errorMessage = error.message.toLowerCase();\n const dbError = error as DatabaseError;\n const errorContext = (\n dbError.context as { source?: string }\n )?.source?.toLowerCase();\n\n // Check error context first (most reliable)\n if (errorContext) {\n const contextSource = this.matchPatterns(\n errorContext,\n CONTEXT_SOURCE_PATTERNS,\n );\n if (contextSource) return contextSource;\n }\n\n // Fallback to error message analysis\n const messageSource = this.matchPatterns(\n errorMessage,\n MESSAGE_SOURCE_PATTERNS,\n );\n if (messageSource) return messageSource;\n\n return EXTENSION_SOURCE.DatabaseAdapter;\n }\n\n /**\n * Matches a text against a list of pattern groups.\n */\n private matchPatterns(\n text: string,\n patternGroups: Array<{ patterns: string[]; source: EXTENSION_SOURCE }>,\n ): EXTENSION_SOURCE | null {\n for (const { patterns, source } of patternGroups) {\n if (patterns.some((pattern) => text.includes(pattern))) {\n return source;\n }\n }\n return null;\n }\n\n /**\n * Gets the list of encrypted fields for a table.\n * Returns undefined if no fields are encrypted for this table.\n */\n private getEncryptedFields(table: string): string[] | undefined {\n return this.config.encryptedFields?.[table];\n }\n\n /**\n * Executes operations within a transaction with audit logging.\n *\n * **RESPONSIBILITY:** Passes transaction to base adapter\n * **BEHAVIOR:** Individual operations within transaction are audited\n * **ATOMICITY:** Audit records are part of the transaction\n *\n * @param callback - Transaction callback function\n * @returns Transaction result\n *\n * @example\n * ```typescript\n * const result = await adapter.transaction(async (trx) => {\n * // Each operation creates audit record within transaction\n * const user = await trx.create('users', { name: 'John' });\n * await trx.update('profiles', 'profile-1', { userId: user.id });\n * return user;\n * });\n *\n * // If transaction fails, audit records are also rolled back\n * ```\n */\n async transaction<T>(\n callback: (trx: Transaction) => Promise<T>,\n ): Promise<DatabaseResult<T>> {\n return this.baseAdapter.transaction(callback);\n }\n\n /**\n * Checks if a record exists without audit logging.\n *\n * **RESPONSIBILITY:** Verifies record existence without creating audit trail\n * **BEHAVIOR:** Read operations are not audited by default\n * **PERFORMANCE:** No audit overhead for existence checks\n *\n * @param table - Table name\n * @param id - Record ID\n * @returns True if record exists\n *\n * @example\n * ```typescript\n * // Existence checks don't create audit records\n * const userExists = await adapter.exists('users', 'user-123');\n * if (userExists.value) {\n * console.log('User exists');\n * }\n * ```\n */\n async exists(table: string, id: string): Promise<DatabaseResult<boolean>> {\n return this.baseAdapter.exists(table, id);\n }\n\n /**\n * Counts records without audit logging.\n *\n * **RESPONSIBILITY:** Counts records without creating audit trail\n * **BEHAVIOR:** Read operations are not audited by default\n * **PERFORMANCE:** No audit overhead for counting operations\n *\n * @param table - Table name\n * @param filter - Optional filter conditions\n * @returns Count of records\n *\n * @example\n * ```typescript\n * // Count operations don't create audit records\n * const activeUsers = await adapter.count('users', {\n * field: 'status',\n * operator: 'eq',\n * value: 'active'\n * });\n *\n * console.log('Active users:', activeUsers.value);\n * ```\n */\n async count<T extends Record<string, unknown> = Record<string, unknown>>(\n table: string,\n filter?: Filter<T>,\n ): Promise<DatabaseResult<number>> {\n return this.baseAdapter.count<T>(table, filter);\n }\n\n /**\n * Performs health check through base adapter.\n *\n * **RESPONSIBILITY:** Delegates health check to underlying adapter\n * **BEHAVIOR:** No additional health metrics for audit\n *\n * @returns Health status from base adapter\n *\n * @example\n * ```typescript\n * const health = await adapter.healthCheck();\n * if (health.success && health.value?.isHealthy) {\n * console.log('Database healthy with audit support');\n * }\n * ```\n */\n async healthCheck(): Promise<DatabaseResult<DatabaseHealthStatus>> {\n return this.baseAdapter.healthCheck();\n }\n\n /**\n * Determines if a table should be audited.\n *\n * **RESPONSIBILITY:** Checks if table is enabled for audit logging\n * **CONFIGURATION:** Based on enabled flag and excludeTables array\n *\n * @private\n * @param table - Table name to check\n * @returns True if table should be audited\n *\n * @example\n * ```typescript\n * // Configuration: { enabled: true, excludeTables: ['temp_data'] }\n *\n * this.shouldAudit('users'); // true - will be audited\n * this.shouldAudit('temp_data'); // false - excluded from audit\n * ```\n */\n private shouldAudit(table: string): boolean {\n if (!this.config.enabled) return false;\n return !(this.config.excludeTables?.includes(table) ?? false);\n }\n\n /**\n * Logs an audit event to the audit table and executes custom handlers.\n *\n * **RESPONSIBILITY:** Orchestrates audit record creation and event handling\n * **PROCESS:** Validates event → Writes to audit table → Executes custom handler\n *\n * @private\n * @param event - Audit event to log\n *\n * @example\n * ```typescript\n * // Internal usage after successful operation\n * await this.logAudit({\n * operation: 'CREATE',\n * table: 'users',\n * recordId: 'user-123',\n * changes: { after: userData },\n * userId: 'admin-456',\n * timestamp: new Date()\n * });\n * ```\n */\n private async logAudit(event: AuditEvent): Promise<void> {\n this.validateAuditEvent(event);\n\n await this.writeAuditRecord(event);\n await this.executeCustomHandler(event);\n }\n\n /**\n * Validates audit event has required fields.\n *\n * **RESPONSIBILITY:** Ensures audit event is properly formed\n * **VALIDATION:** Checks for required operation and table fields\n *\n * @private\n * @param event - Audit event to validate\n * @throws {DatabaseError} When event is invalid\n *\n * @example\n * ```typescript\n * // Internal validation before logging\n * this.validateAuditEvent({\n * operation: 'CREATE', // Required\n * table: 'users', // Required\n * recordId: 'user-123'\n * });\n * ```\n */\n private validateAuditEvent(event: AuditEvent): void {\n if (!event?.operation || !event?.table) {\n throw new DatabaseError(\n \"Invalid audit event\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"validateAuditEvent\" },\n cause: new Error(\"Invalid audit event\"),\n },\n );\n }\n }\n\n /**\n * Generates the audit table name based on configuration.\n *\n * **RESPONSIBILITY:** Determines the correct table name for audit records\n * **TABLE NAMING:**\n * - Partitioned: `{schema}.audit_log_yyyy_mm_dd` (e.g., audit.audit_log_2024_12_01)\n * - Non-partitioned: `{schema}.audit_logs` (e.g., audit.audit_logs)\n *\n * @private\n * @param timestamp - Timestamp to use for partition date\n * @returns Schema-qualified table name\n */\n private getAuditTableName(timestamp: Date): string {\n if (this.usePartitionedTables) {\n const year = timestamp.getFullYear();\n const month = String(timestamp.getMonth() + 1).padStart(\n DATE_PART_MIN_WIDTH,\n \"0\",\n );\n const day = String(timestamp.getDate()).padStart(\n DATE_PART_MIN_WIDTH,\n \"0\",\n );\n return `${this.auditSchema}.audit_log_${year}_${month}_${day}`;\n }\n return `${this.auditSchema}.audit_logs`;\n }\n\n /**\n * Writes audit record to daily audit table.\n *\n * **RESPONSIBILITY:** Persists audit event to database\n * **TABLE NAMING:** Uses daily partitioned tables (audit.audit_log_yyyy_mm_dd) by default\n * **STRUCTURE:** Converts event to database record format\n *\n * @private\n * @param event - Audit event to write\n * @throws {DatabaseError} When write operation fails\n *\n * @example\n * ```typescript\n * // Internal usage - writes to audit.audit_log_2024_12_01 table\n * await this.writeAuditRecord({\n * operation: 'UPDATE',\n * table: 'users',\n * recordId: 'user-123',\n * changes: { before: {...}, after: {...} },\n * timestamp: new Date('2024-12-01')\n * });\n * ```\n */\n private async writeAuditRecord(event: AuditEvent): Promise<void> {\n const tableName = this.getAuditTableName(event.timestamp);\n try {\n const auditResult = await this.baseAdapter.create(tableName, {\n operation: event.operation,\n table_name: event.table,\n record_id: event.recordId,\n user_id: event.userId,\n request_id: event.requestId,\n changes: event.changes,\n ip_address: event.ipAddress,\n user_agent: event.userAgent,\n timestamp: event.timestamp,\n });\n\n if (!auditResult.success) {\n throw new DatabaseError(\n \"Failed to write audit record\",\n DATABASE_ERROR_CODES.CREATE_FAILED,\n {\n context: { source: \"writeAuditRecord\" },\n cause:\n auditResult.error ?? new Error(\"Failed to write audit record\"),\n },\n );\n }\n } catch (error) {\n logger.error(`Audit write failed: ${(error as Error).message}`);\n throw new DatabaseError(\n \"Failed to write audit record\",\n DATABASE_ERROR_CODES.CREATE_FAILED,\n {\n context: { source: \"writeAuditRecord\" },\n cause: error as Error,\n },\n );\n }\n }\n\n /**\n * Executes custom audit event handler if configured.\n *\n * **RESPONSIBILITY:** Calls user-defined audit event handler\n * **ERROR HANDLING:** Logs handler errors without failing the operation\n * **USE CASE:** Integration with compliance systems, notifications\n *\n * @private\n * @param event - Audit event to handle\n *\n * @example\n * ```typescript\n * // Configuration with custom handler\n * {\n * onAuditAfterWrite: async (event) => {\n * await complianceService.recordAudit(event);\n * await notificationService.sendAuditAlert(event);\n * }\n * }\n *\n * // Handler is called after successful audit record write\n * ```\n */\n private async executeCustomHandler(event: AuditEvent): Promise<void> {\n if (this.config.onAuditAfterWrite) {\n try {\n await this.config.onAuditAfterWrite(event);\n } catch (handlerError) {\n logger.error(\n `Custom audit handler failed: ${(handlerError as Error).message}`,\n );\n }\n }\n }\n}\n","import { createCipheriv, createDecipheriv, randomBytes } from \"crypto\";\nimport {\n type DatabaseAdapterType,\n type DatabaseResult,\n type QueryOptions,\n type PaginatedResult,\n type Transaction,\n type Filter,\n type DatabaseHealthStatus,\n ENCRYPTION_DEFAULTS,\n} from \"@plyaz/types/db\";\nimport { isString, isObject } from \"@utils/typeGuards\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\n\n/**\n * ENCRYPTION ADAPTER — Field-Level Encryption Layer\n *\n * Encryption extension that automatically encrypts/decrypts specified fields.\n * Second layer in the adapter chain (after the base adapter).\n *\n * **Adapter Chain Position:**\n * ReadReplica → Audit → Cache → SoftDelete → **Encryption** → Base Adapter\n *\n * **What this adapter does:**\n * 1. Receives operations from SoftDeleteAdapter (or the next layer)\n * 2. Encrypts sensitive fields before write operations (create, update)\n * 3. Delegates to the base adapter with encrypted data\n * 4. Decrypts fields in response data after read operations\n * 5. Passes results back up the chain\n *\n * **Called by:** SoftDeleteAdapter (or CachingAdapter if no soft delete)\n * **Calls:** Base adapter methods (DrizzleAdapter, SupabaseAdapter, etc.)\n * **Wraps:** Base database adapter with transparent encryption\n *\n * **Encryption Flow:**\n * - **Writes:** Plain data → Encrypt fields → Store encrypted → Return decrypted\n * - **Reads:** Retrieve encrypted → Decrypt fields → Return plain data\n *\n * @example\n * ### Configuration\n * ```typescript\n * encryption: {\n * enabled: true,\n * key: process.env.ENCRYPTION_KEY,\n * fields: {\n * [Tables.USERS]: ['ssn', 'taxId'],\n * [Tables.PAYMENTS]: ['cardNumber', 'cvv']\n * }\n * }\n * ```\n *\n * @example\n * ### Transparent Usage\n * ```typescript\n * // Application code — encryption is transparent\n * await db.create(Tables.USERS, {\n * name: 'John Doe',\n * ssn: '123-45-6789' // Automatically encrypted before storage\n * });\n *\n * // Retrieved data is automatically decrypted\n * const user = await db.get(Tables.USERS, userId);\n * console.log(user.value.ssn); // '123-45-6789' (decrypted)\n * ```\n */\n\nexport class EncryptionAdapter implements DatabaseAdapterType {\n // Using shared logger instance from @plyaz/logger\n\n constructor(\n public baseAdapter: DatabaseAdapterType,\n private config: {\n enabled: boolean;\n key: string;\n fields: Record<string, string[]>;\n algorithm?: string;\n },\n ) {}\n\n async initialize(): Promise<DatabaseResult<void>> {\n return this.baseAdapter.initialize();\n }\n\n async connect(): Promise<void> {\n return this.baseAdapter.connect();\n }\n\n async disconnect(): Promise<void> {\n return this.baseAdapter.disconnect();\n }\n\n async close(): Promise<DatabaseResult<void>> {\n return this.baseAdapter.close();\n }\n\n getClient(): object {\n return this.baseAdapter.getClient();\n }\n\n async query<T>(sql: string, params?: T[]): Promise<T[]> {\n return this.baseAdapter.query(sql, params);\n }\n\n registerTable<T, U>(name: string, table: T, idColumn?: U): void {\n this.baseAdapter.registerTable(name, table, idColumn);\n }\n\n async findById<T>(\n table: string,\n id: string,\n ): Promise<DatabaseResult<T | null>> {\n const result = await this.baseAdapter.findById<T>(table, id);\n if (result.success && result.value) {\n result.value = this.decryptFields(table, result.value);\n }\n return result;\n }\n\n async findMany<T extends Record<string, unknown>>(\n table: string,\n options?: QueryOptions<T>,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n const result = await this.baseAdapter.findMany<T>(table, options);\n if (result.success && result.value) {\n result.value.data = result.value.data.map((item) =>\n this.decryptFields(table, item),\n );\n }\n return result;\n }\n\n async create<T extends Record<string, unknown>>(\n table: string,\n data: T,\n ): Promise<DatabaseResult<T>> {\n // Encryption is critical for compliance - fail if encryption fails\n // AuditAdapter (outer layer) will catch and log the failure\n const encryptedData = this.encryptFields(table, data);\n const result = await this.baseAdapter.create<T>(table, encryptedData);\n if (result.success && result.value) {\n result.value = this.decryptFields(table, result.value);\n }\n return result;\n }\n\n async update<T>(\n table: string,\n id: string,\n data: Partial<T>,\n ): Promise<DatabaseResult<T>> {\n // Encryption is critical for compliance - fail if encryption fails\n // AuditAdapter (outer layer) will catch and log the failure\n const encryptedData = this.encryptFields(table, data);\n const result = await this.baseAdapter.update<T>(table, id, encryptedData);\n if (result.success && result.value) {\n result.value = this.decryptFields(table, result.value);\n }\n return result;\n }\n\n async delete(table: string, id: string): Promise<DatabaseResult<void>> {\n return this.baseAdapter.delete(table, id);\n }\n\n async transaction<T>(\n callback: (trx: Transaction) => Promise<T>,\n ): Promise<DatabaseResult<T>> {\n return this.baseAdapter.transaction(callback);\n }\n\n async exists(table: string, id: string): Promise<DatabaseResult<boolean>> {\n return this.baseAdapter.exists(table, id);\n }\n\n async count<T extends Record<string, unknown> = Record<string, unknown>>(\n table: string,\n filter?: Filter<T>,\n ): Promise<DatabaseResult<number>> {\n return this.baseAdapter.count<T>(table, filter);\n }\n\n async healthCheck(): Promise<DatabaseResult<DatabaseHealthStatus>> {\n return this.baseAdapter.healthCheck();\n }\n\n private encryptFields<T extends Record<string, unknown>>(\n table: string,\n data: T,\n ): T {\n if (!this.shouldProcessFields(data, table)) return data;\n\n const fieldsToEncrypt = this.config.fields[table];\n const result = { ...data } as T;\n\n for (const field of fieldsToEncrypt) {\n this.encryptSingleField(result, field);\n }\n\n return result as T;\n }\n\n private shouldProcessFields<T>(data: T, table: string): boolean {\n return (\n this.config.enabled &&\n isObject(data) &&\n Boolean(this.config.fields[table])\n );\n }\n\n private encryptSingleField<T extends Record<string, unknown>>(\n result: T,\n field: string,\n ): void {\n if (result[field as keyof T]) {\n result[field as keyof T] = this.encrypt(\n String(result[field as keyof T]),\n ) as T[keyof T];\n }\n }\n\n private decryptFields<T extends Record<string, unknown>>(\n table: string,\n data: T,\n ): T {\n if (!this.shouldProcessFields(data, table)) return data;\n\n const fieldsToDecrypt = this.config.fields[table];\n const result = { ...data } as T;\n\n for (const field of fieldsToDecrypt) {\n this.decryptSingleField(result, field);\n }\n\n return result as T;\n }\n\n private decryptSingleField<T extends Record<string, unknown>>(\n result: T,\n field: string,\n ): void {\n if (result[field as keyof T]) {\n const fieldValue = String(result[field as keyof T]);\n // Check if the field value is encrypted (contains colons)\n // If not encrypted, return as-is (backwards compatibility with old data)\n if (this.isEncryptedValue(fieldValue)) {\n try {\n result[field as keyof T] = this.decrypt(fieldValue) as T[keyof T];\n } catch (error) {\n // Decryption failed - might be corrupted data or wrong key\n console.warn(\n `Failed to decrypt field ${field}, returning as-is:`,\n (error as Error).message,\n );\n }\n }\n }\n }\n\n private encrypt(text: string): string {\n this.validateEncryptionInput(text);\n\n const { iv, cipher } = this.createCipher();\n const encrypted = this.performEncryption(cipher, text);\n const authTag =\n (cipher as { getAuthTag?: () => Buffer }).getAuthTag?.() ??\n Buffer.alloc(0);\n\n return iv.toString(\"hex\") + \":\" + authTag.toString(\"hex\") + \":\" + encrypted;\n }\n\n private validateEncryptionInput(text: string): void {\n if (!isString(text)) {\n throw new DatabaseError(\n \"Invalid text for encryption\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"validateEncryptionInput\" },\n cause: new Error(\"Invalid text for encryption\"),\n },\n );\n }\n if (!this.config.key) {\n throw new DatabaseError(\n \"Encryption key is required\",\n DATABASE_ERROR_CODES.CONFIG_REQUIRED,\n {\n context: { source: \"validateEncryptionInput\" },\n cause: new Error(\"Encryption key is required\"),\n },\n );\n }\n }\n\n private createCipher(): {\n iv: Buffer;\n cipher: ReturnType<typeof createCipheriv>;\n } {\n const algorithm = this.config.algorithm ?? ENCRYPTION_DEFAULTS.ALGORITHM;\n const key = this.getKeyBuffer();\n const iv = randomBytes(ENCRYPTION_DEFAULTS.IV_LENGTH);\n const cipher = createCipheriv(algorithm, key, iv);\n return { iv, cipher };\n }\n\n private performEncryption(\n cipher: ReturnType<typeof createCipheriv>,\n text: string,\n ): string {\n let encrypted = cipher.update(text, \"utf8\", \"hex\");\n encrypted += cipher.final(\"hex\");\n return encrypted;\n }\n\n private decrypt(encryptedText: string): string {\n this.validateDecryptionInput(encryptedText);\n\n const parts = this.parseEncryptedText(encryptedText);\n const { iv, authTag, encrypted } = this.extractDecryptionParts(parts);\n const decipher = this.createDecipher(iv, authTag);\n\n return this.performDecryption(decipher, encrypted);\n }\n\n private validateDecryptionInput(encryptedText: string): void {\n if (!isString(encryptedText)) {\n throw new DatabaseError(\n \"Invalid encrypted text for decryption\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"validateDecryptionInput\" },\n cause: new Error(\"Invalid encrypted text for decryption\"),\n },\n );\n }\n if (!this.config.key) {\n throw new DatabaseError(\n \"Encryption key is required\",\n DATABASE_ERROR_CODES.CONFIG_REQUIRED,\n {\n context: { source: \"validateDecryptionInput\" },\n cause: new Error(\"Encryption key is required\"),\n },\n );\n }\n }\n\n private parseEncryptedText(encryptedText: string): string[] {\n const parts = encryptedText.split(\":\");\n if (parts.length !== ENCRYPTION_DEFAULTS.ENCRYPTED_PARTS_COUNT) {\n throw new DatabaseError(\n \"Invalid encrypted text format\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"parseEncryptedText\" },\n cause: new Error(\"Invalid encrypted text format\"),\n },\n );\n }\n return parts;\n }\n\n private extractDecryptionParts(parts: string[]): {\n iv: Buffer;\n authTag: Buffer;\n encrypted: string;\n } {\n const iv = Buffer.from(parts[0], \"hex\");\n const authTag = Buffer.from(parts[1], \"hex\");\n const encrypted = parts[2];\n return { iv, authTag, encrypted };\n }\n\n private createDecipher(\n iv: Buffer,\n authTag: Buffer,\n ): ReturnType<typeof createDecipheriv> {\n const algorithm = this.config.algorithm ?? ENCRYPTION_DEFAULTS.ALGORITHM;\n const key = this.getKeyBuffer();\n const decipher = createDecipheriv(algorithm, key, iv);\n\n if (authTag.length > 0) {\n (decipher as { setAuthTag?: (tag: Buffer) => void }).setAuthTag?.(\n authTag,\n );\n }\n\n return decipher;\n }\n\n private performDecryption(\n decipher: ReturnType<typeof createDecipheriv>,\n encrypted: string,\n ): string {\n let decrypted = decipher.update(encrypted, \"hex\", \"utf8\");\n decrypted += decipher.final(\"utf8\");\n return decrypted;\n }\n\n private isEncryptedValue(value: string): boolean {\n // Encrypted values have format: iv:authTag:encrypted (3 parts separated by colons)\n const parts = value.split(\":\");\n return parts.length === ENCRYPTION_DEFAULTS.ENCRYPTED_PARTS_COUNT;\n }\n\n private getKeyBuffer(): Buffer {\n // AES-256-GCM requires 32-byte key\n const AES_256_KEY_LENGTH = 32;\n const keyBuffer = Buffer.from(this.config.key, \"utf8\");\n\n if (keyBuffer.length !== AES_256_KEY_LENGTH) {\n throw new DatabaseError(\n `Encryption key must be exactly ${AES_256_KEY_LENGTH} bytes for AES-256, got ${keyBuffer.length}`,\n DATABASE_ERROR_CODES.CONFIG_REQUIRED,\n {\n context: { source: \"getKeyBuffer\" },\n cause: new Error(\"Invalid key length\"),\n },\n );\n }\n\n return keyBuffer;\n }\n}\n","import { NUMERIX } from \"@plyaz/config\";\nimport { logger } from \"@plyaz/logger\";\nimport type {\n DatabaseAdapterType,\n DatabaseResult,\n DBCacheConfig,\n Filter,\n DatabaseHealthStatus,\n PaginatedResult,\n QueryOptions,\n Transaction,\n} from \"@plyaz/types/db\";\n/**\n * CACHING ADAPTER - Query Result Caching Layer\n *\n * Caching extension that stores query results in memory for improved performance.\n * Third layer in the adapter chain.\n *\n * **Adapter Chain Position:**\n * ReadReplica → Audit → **Cache** → SoftDelete → Encryption → Base Adapter\n *\n * **What this adapter does:**\n * 1. Intercepts findById() operations → checks cache first, stores results\n * 2. Intercepts write operations → invalidates related cache entries\n * 3. Manages TTL-based cache expiration\n * 4. Honors cache configuration (enabled, ttl, invalidation strategy)\n *\n * **Called by:** AuditAdapter (or ReadReplicaAdapter if no audit)\n * **Calls:** SoftDeleteAdapter (or next adapter in chain)\n * **Cache Strategy:** In-memory Map with TTL expiration\n *\n * **Cache Flow:**\n * - **READ:** Check cache → Return if hit → Query DB → Cache result\n * - **WRITE:** Execute operation → Invalidate related cache entries\n *\n * @example\n * ### Configuration\n * ```typescript\n * cache: {\n * enabled: true,\n * ttl: 300, // 5 minutes\n * invalidation: 'write', // Invalidate on writes\n * maxSize: 1000 // Max cache entries\n * }\n * ```\n *\n * @example\n * ### Cache Behavior\n * ```typescript\n * // First call - cache miss, queries database\n * const user1 = await db.findById('users', 'user-123'); // DB query\n *\n * // Second call - cache hit, returns from memory\n * const user2 = await db.findById('users', 'user-123'); // Cache hit\n *\n * // Write operation invalidates cache\n * await db.update('users', 'user-123', { name: 'New Name' });\n *\n * // Next read - cache miss again, queries database\n * const user3 = await db.findById('users', 'user-123'); // DB query\n * ```\n */\nexport class CachingAdapter implements DatabaseAdapterType {\n private cache = new Map<\n string,\n {\n value:\n | Record<string, string | number | boolean | Date>\n | Record<string, string | number | boolean | Date>[];\n expiry: number;\n }\n >();\n\n /**\n * Creates a new CachingAdapter instance.\n *\n * **RESPONSIBILITY:** Wraps base adapter with caching functionality\n * **CONFIGURATION:** Sets up cache TTL, invalidation strategy, and size limits\n *\n * @param baseAdapter - The underlying database adapter to wrap\n * @param config - Cache configuration options\n *\n * @example\n * ```typescript\n * const cachingAdapter = new CachingAdapter(baseAdapter, {\n * enabled: true,\n * ttl: 300, // 5 minutes\n * invalidation: 'write', // Invalidate on writes\n * maxSize: 1000 // Max entries\n * });\n * ```\n */\n constructor(\n public baseAdapter: DatabaseAdapterType,\n private config: DBCacheConfig,\n ) {}\n\n /**\n * Initializes the caching adapter and underlying adapter.\n *\n * **RESPONSIBILITY:** Passes initialization to base adapter\n * **BEHAVIOR:** No additional initialization needed for caching\n *\n * @returns Promise resolving to initialization result\n *\n * @example\n * ```typescript\n * const result = await cachingAdapter.initialize();\n * if (result.success) {\n * console.log('Caching adapter initialized');\n * }\n * ```\n */\n async initialize(): Promise<DatabaseResult<void>> {\n return this.baseAdapter.initialize();\n }\n\n /**\n * Establishes database connection through base adapter.\n *\n * **RESPONSIBILITY:** Delegates connection to underlying adapter\n * **BEHAVIOR:** No additional connection logic needed\n *\n * @example\n * ```typescript\n * await cachingAdapter.connect();\n * console.log('Connected with caching support');\n * ```\n */\n async connect(): Promise<void> {\n return this.baseAdapter.connect();\n }\n\n /**\n * Closes database connection through base adapter.\n *\n * **RESPONSIBILITY:** Delegates disconnection to underlying adapter\n * **BEHAVIOR:** Cache is cleared on disconnect\n *\n * @example\n * ```typescript\n * await cachingAdapter.disconnect();\n * console.log('Disconnected and cache cleared');\n * ```\n */\n async disconnect(): Promise<void> {\n return this.baseAdapter.disconnect();\n }\n\n async close(): Promise<DatabaseResult<void>> {\n return this.baseAdapter.close();\n }\n\n /**\n * Gets the underlying database client.\n *\n * **RESPONSIBILITY:** Provides access to raw database client\n * **USE CASE:** For operations that bypass caching\n *\n * @returns Database client object\n *\n * @example\n * ```typescript\n * const client = cachingAdapter.getClient();\n * // Use for direct database operations if needed\n * ```\n */\n getClient(): object {\n return this.baseAdapter.getClient();\n }\n\n /**\n * Executes raw SQL query through base adapter.\n *\n * **RESPONSIBILITY:** Passes raw SQL to base adapter without caching\n * **BEHAVIOR:** Does not cache raw SQL results\n * **NOTE:** Use findById/findMany for automatic caching\n *\n * @param sql - SQL query string\n * @param params - Query parameters\n * @returns Query results\n *\n * @example\n * ```typescript\n * // Raw SQL bypasses caching\n * const results = await adapter.query(\n * 'SELECT * FROM users WHERE status = $1',\n * ['active']\n * );\n *\n * // Use findMany for automatic caching\n * const users = await adapter.findMany('users', { filter: ... });\n * ```\n */\n async query<T>(sql: string, params?: T[]): Promise<T[]> {\n return this.baseAdapter.query(sql, params);\n }\n\n /**\n * Registers a table schema with the base adapter.\n *\n * **RESPONSIBILITY:** Passes table registration to base adapter\n * **BEHAVIOR:** No additional registration logic needed\n *\n * @param name - Table name\n * @param table - Table schema\n * @param idColumn - Primary key column\n *\n * @example\n * ```typescript\n * cachingAdapter.registerTable('users', userSchema, 'id');\n * // Table now supports cached operations\n * ```\n */\n registerTable<T, U>(name: string, table: T, idColumn?: U): void {\n this.baseAdapter.registerTable(name, table, idColumn);\n }\n\n async findById<T>(\n table: string,\n id: string,\n ): Promise<DatabaseResult<T | null>> {\n if (!this.config.enabled) {\n return this.baseAdapter.findById<T>(table, id);\n }\n\n const cacheKey = `${table}:${id}`;\n const cached = this.getFromCache<T>(cacheKey);\n\n if (cached !== null) {\n logger.debug(`Cache hit for ${table}:${id}`);\n return { success: true, value: cached };\n }\n\n const result = await this.baseAdapter.findById<T>(table, id);\n\n if (result.success && result.value) {\n this.setCache(cacheKey, result.value);\n logger.debug(`Cache set for ${table}:${id}`);\n }\n\n return result;\n }\n\n /**\n * Finds multiple records without caching.\n *\n * **RESPONSIBILITY:** Retrieves multiple records, bypassing cache\n * **BEHAVIOR:** Complex queries are not cached currently\n * **FUTURE:** Could implement query result caching with cache keys\n *\n * @param table - Table name\n * @param options - Query options\n * @returns Paginated results\n *\n * @example\n * ```typescript\n * // Complex queries bypass cache (for now)\n * const users = await adapter.findMany('users', {\n * filter: { field: 'status', operator: 'eq', value: 'active' },\n * pagination: { page: 1, limit: 10 },\n * sort: { field: 'name', direction: 'asc' }\n * });\n *\n * // Always queries database directly\n * ```\n */\n async findMany<T extends Record<string, unknown>>(\n table: string,\n options?: QueryOptions<T>,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n // For now, skip caching for complex queries\n return this.baseAdapter.findMany<T>(table, options);\n }\n\n /**\n * Creates a new record with cache invalidation.\n *\n * **RESPONSIBILITY:** Creates record and invalidates related cache entries\n * **INVALIDATION:** Clears table cache on successful write\n * **STRATEGY:** Based on config.invalidation setting\n *\n * @param table - Table name\n * @param data - Record data\n * @returns Created record\n *\n * @example\n * ```typescript\n * // Create user - invalidates users table cache\n * const result = await adapter.create('users', {\n * name: 'John Doe',\n * email: 'john@example.com'\n * });\n *\n * if (result.success) {\n * console.log('User created:', result.value.id);\n * // All cached users:* entries are now invalid\n * }\n * ```\n */\n async create<T extends Record<string, unknown>>(\n table: string,\n data: T,\n ): Promise<DatabaseResult<T>> {\n const result = await this.baseAdapter.create<T>(table, data);\n\n if (result.success && this.config.invalidation === \"write\") {\n this.invalidateTable(table);\n }\n\n return result;\n }\n\n /**\n * Updates an existing record with cache invalidation.\n *\n * **RESPONSIBILITY:** Updates record and invalidates related cache entries\n * **INVALIDATION:** Clears specific record and table cache\n * **STRATEGY:** Invalidates both table:id and table:* patterns\n *\n * @param table - Table name\n * @param id - Record ID\n * @param data - Partial record data\n * @returns Updated record\n *\n * @example\n * ```typescript\n * // Update user - invalidates specific cache entry\n * const result = await adapter.update('users', 'user-123', {\n * name: 'Jane Doe'\n * });\n *\n * if (result.success) {\n * console.log('User updated:', result.value.name);\n * // Cache entries users:user-123 and users:* are invalidated\n * }\n * ```\n */\n async update<T>(\n table: string,\n id: string,\n data: Partial<T>,\n ): Promise<DatabaseResult<T>> {\n const result = await this.baseAdapter.update<T>(table, id, data);\n\n if (result.success && this.config.invalidation === \"write\") {\n this.invalidateTable(table);\n this.invalidateKey(`${table}:${id}`);\n }\n\n return result;\n }\n\n /**\n * Deletes a record with cache invalidation.\n *\n * **RESPONSIBILITY:** Deletes record and invalidates related cache entries\n * **INVALIDATION:** Clears specific record and table cache\n * **STRATEGY:** Removes both table:id and table:* patterns\n *\n * @param table - Table name\n * @param id - Record ID\n * @returns Deletion result\n *\n * @example\n * ```typescript\n * // Delete user - invalidates cache entries\n * const result = await adapter.delete('users', 'user-123');\n *\n * if (result.success) {\n * console.log('User deleted successfully');\n * // Cache entries users:user-123 and users:* are invalidated\n * }\n * ```\n */\n async delete(table: string, id: string): Promise<DatabaseResult<void>> {\n const result = await this.baseAdapter.delete(table, id);\n\n if (result.success && this.config.invalidation === \"write\") {\n this.invalidateTable(table);\n this.invalidateKey(`${table}:${id}`);\n }\n\n return result;\n }\n\n /**\n * Executes operations within a transaction.\n *\n * **RESPONSIBILITY:** Passes transaction to base adapter\n * **BEHAVIOR:** Cache invalidation happens per operation within transaction\n * **ATOMICITY:** Cache invalidation is not rolled back if transaction fails\n *\n * @param callback - Transaction callback function\n * @returns Transaction result\n *\n * @example\n * ```typescript\n * const result = await adapter.transaction(async (trx) => {\n * // Each operation invalidates cache independently\n * const user = await trx.create('users', { name: 'John' });\n * await trx.update('profiles', 'profile-1', { userId: user.id });\n * return user;\n * });\n *\n * // Cache invalidation happens even if transaction fails\n * ```\n */\n async transaction<T>(\n callback: (trx: Transaction) => Promise<T>,\n ): Promise<DatabaseResult<T>> {\n return this.baseAdapter.transaction(callback);\n }\n\n /**\n * Checks if a record exists without caching.\n *\n * **RESPONSIBILITY:** Verifies record existence, bypassing cache\n * **BEHAVIOR:** Existence checks are not cached currently\n * **PERFORMANCE:** Always queries database for existence\n *\n * @param table - Table name\n * @param id - Record ID\n * @returns True if record exists\n *\n * @example\n * ```typescript\n * // Existence checks bypass cache\n * const userExists = await adapter.exists('users', 'user-123');\n * if (userExists.value) {\n * console.log('User exists');\n * }\n *\n * // Always queries database directly\n * ```\n */\n async exists(table: string, id: string): Promise<DatabaseResult<boolean>> {\n return this.baseAdapter.exists(table, id);\n }\n\n /**\n * Counts records without caching.\n *\n * **RESPONSIBILITY:** Counts records, bypassing cache\n * **BEHAVIOR:** Count operations are not cached currently\n * **PERFORMANCE:** Always queries database for counts\n *\n * @param table - Table name\n * @param filter - Optional filter conditions\n * @returns Count of records\n *\n * @example\n * ```typescript\n * // Count operations bypass cache\n * const activeUsers = await adapter.count('users', {\n * field: 'status',\n * operator: 'eq',\n * value: 'active'\n * });\n *\n * console.log('Active users:', activeUsers.value);\n * // Always queries database directly\n * ```\n */\n async count<T extends Record<string, unknown> = Record<string, unknown>>(\n table: string,\n filter?: Filter<T>,\n ): Promise<DatabaseResult<number>> {\n return this.baseAdapter.count<T>(table, filter);\n }\n\n /**\n * Performs health check through base adapter.\n *\n * **RESPONSIBILITY:** Delegates health check to underlying adapter\n * **BEHAVIOR:** No additional health metrics for cache\n *\n * @returns Health status from base adapter\n *\n * @example\n * ```typescript\n * const health = await adapter.healthCheck();\n * if (health.success && health.value?.isHealthy) {\n * console.log('Database healthy with caching support');\n * }\n * ```\n */\n async healthCheck(): Promise<DatabaseResult<DatabaseHealthStatus>> {\n return this.baseAdapter.healthCheck();\n }\n\n /**\n * Retrieves value from cache with TTL validation.\n *\n * **RESPONSIBILITY:** Gets cached value and validates expiration\n * **TTL HANDLING:** Removes expired entries automatically\n * **RETURN:** Cached value or null if not found/expired\n *\n * @private\n * @param key - Cache key to retrieve\n * @returns Cached value or null\n *\n * @example\n * ```typescript\n * // Internal usage\n * const user = this.getFromCache<User>('users:user-123');\n * if (user) {\n * console.log('Cache hit:', user.name);\n * } else {\n * console.log('Cache miss or expired');\n * }\n * ```\n */\n private getFromCache<T>(key: string): T | null {\n const cached = this.cache.get(key);\n if (!cached) return null;\n\n if (Date.now() > cached.expiry) {\n this.cache.delete(key);\n return null;\n }\n\n return cached.value as T;\n }\n\n /**\n * Stores value in cache with TTL expiration.\n *\n * **RESPONSIBILITY:** Caches value with calculated expiration time\n * **TTL:** Uses config.ttl or default 5 minutes (300 seconds)\n * **EXPIRY:** Calculates absolute expiration timestamp\n *\n * @private\n * @param key - Cache key to store\n * @param value - Value to cache\n *\n * @example\n * ```typescript\n * // Internal usage after database query\n * this.setCache('users:user-123', userData);\n *\n * // Value will expire after TTL seconds\n * // Default: 5 minutes from now\n * ```\n */\n private setCache(\n key: string,\n value:\n | Record<string, string | number | boolean | Date>\n | Record<string, string | number | boolean | Date>[],\n ): void {\n const ttl = this.config.ttl ?? NUMERIX.THREE_HUNDERD; // Default 5 minutes\n const expiry = Date.now() + ttl * NUMERIX.THOUSAND;\n this.cache.set(key, { value, expiry });\n }\n\n /**\n * Removes specific key from cache.\n *\n * **RESPONSIBILITY:** Invalidates single cache entry\n * **USE CASE:** Called after record updates/deletes\n * **PATTERN:** Removes exact key match\n *\n * @private\n * @param key - Cache key to invalidate\n *\n * @example\n * ```typescript\n * // Internal usage after record update\n * this.invalidateKey('users:user-123');\n *\n * // Only users:user-123 is removed from cache\n * // Other users:* entries remain cached\n * ```\n */\n private invalidateKey(key: string): void {\n this.cache.delete(key);\n }\n\n /**\n * Removes all cache entries for a table.\n *\n * **RESPONSIBILITY:** Invalidates all entries matching table pattern\n * **USE CASE:** Called after any write operation to table\n * **PATTERN:** Removes all keys starting with 'table:'\n *\n * @private\n * @param table - Table name to invalidate\n *\n * @example\n * ```typescript\n * // Internal usage after any write to users table\n * this.invalidateTable('users');\n *\n * // Removes all cache entries:\n * // - users:user-123\n * // - users:user-456\n * // - users:admin-789\n * // But keeps: profiles:profile-1, posts:post-1, etc.\n * ```\n */\n private invalidateTable(table: string): void {\n for (const key of this.cache.keys()) {\n if (key.startsWith(`${table}:`)) {\n this.cache.delete(key);\n }\n }\n }\n}\n","import type {\n DatabaseAdapterType,\n DatabaseResult,\n QueryOptions,\n PaginatedResult,\n Transaction,\n Filter,\n DatabaseHealthStatus,\n ReadReplicaConfig,\n} from \"@plyaz/types/db\";\n\n/**\n * Read replica extension that routes read operations to replicas\n * This is the outermost wrapper in the adapter chain\n */\nexport class ReadReplicaAdapter implements DatabaseAdapterType {\n private currentReplicaIndex = 0;\n\n constructor(\n private primaryAdapter: DatabaseAdapterType,\n private config: ReadReplicaConfig,\n ) {}\n\n async initialize(): Promise<DatabaseResult<void>> {\n return this.primaryAdapter.initialize();\n }\n\n async connect(): Promise<void> {\n return this.primaryAdapter.connect();\n }\n\n async disconnect(): Promise<void> {\n return this.primaryAdapter.disconnect();\n }\n\n async close(): Promise<DatabaseResult<void>> {\n return this.primaryAdapter.close();\n }\n\n getClient(): object {\n return this.primaryAdapter.getClient();\n }\n\n async query<T>(sql: string, params?: T[]): Promise<T[]> {\n return this.primaryAdapter.query(sql, params);\n }\n\n registerTable<T, U>(name: string, table: T, idColumn?: U): void {\n this.primaryAdapter.registerTable(name, table, idColumn);\n }\n\n async findById<T>(\n table: string,\n id: string,\n ): Promise<DatabaseResult<T | null>> {\n // Route reads to replicas if available\n const adapter = this.getReadAdapter();\n return adapter.findById<T>(table, id);\n }\n\n async findMany<T extends Record<string, unknown>>(\n table: string,\n options?: QueryOptions<T>,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n // Route reads to replicas if available\n const adapter = this.getReadAdapter();\n return adapter.findMany<T>(table, options);\n }\n\n async create<T extends Record<string, unknown>>(\n table: string,\n data: T,\n ): Promise<DatabaseResult<T>> {\n // Always route writes to primary\n return this.primaryAdapter.create<T>(table, data);\n }\n\n async update<T>(\n table: string,\n id: string,\n data: Partial<T>,\n ): Promise<DatabaseResult<T>> {\n // Always route writes to primary\n return this.primaryAdapter.update<T>(table, id, data);\n }\n\n async delete(table: string, id: string): Promise<DatabaseResult<void>> {\n // Always route writes to primary\n return this.primaryAdapter.delete(table, id);\n }\n\n async transaction<T>(\n callback: (trx: Transaction) => Promise<T>,\n ): Promise<DatabaseResult<T>> {\n // Always route transactions to primary\n return this.primaryAdapter.transaction(callback);\n }\n\n async exists(table: string, id: string): Promise<DatabaseResult<boolean>> {\n // Route reads to replicas if available\n const adapter = this.getReadAdapter();\n return adapter.exists(table, id);\n }\n\n async count<T extends Record<string, unknown> = Record<string, unknown>>(\n table: string,\n filter?: Filter<T>,\n ): Promise<DatabaseResult<number>> {\n // Route reads to replicas if available\n const adapter = this.getReadAdapter();\n return adapter.count<T>(table, filter);\n }\n\n async healthCheck(): Promise<DatabaseResult<DatabaseHealthStatus>> {\n return this.primaryAdapter.healthCheck();\n }\n\n /**\n * Get the appropriate adapter for read operations\n * Routes to replicas using the configured strategy\n */\n private getReadAdapter(): DatabaseAdapterType {\n if (!this.config.enabled || this.config.replicas.length === 0) {\n return this.primaryAdapter;\n }\n\n switch (this.config.strategy) {\n case \"round-robin\": {\n const replica = this.config.replicas[this.currentReplicaIndex];\n this.currentReplicaIndex =\n (this.currentReplicaIndex + 1) % this.config.replicas.length;\n return replica;\n }\n\n case \"random\": {\n const randomIndex = Math.floor(\n Math.random() * this.config.replicas.length,\n );\n return this.config.replicas[randomIndex];\n }\n\n default:\n // Default to first replica\n return this.config.replicas[0];\n }\n }\n}\n","/**\n * DATABASE SERVICE FACTORY - Main Entry Point\n *\n * This file is responsible for creating fully configured database services with extension chains.\n * It implements the decorator pattern to wrap base adapters with feature extensions.\n *\n * **RESPONSIBILITIES:**\n * 1. Config Validation - Ensures valid configuration before proceeding\n * 2. Base Adapter Creation - Creates core database adapters (Drizzle/Supabase/SQL)\n * 3. Adapter Chain Building - Wraps adapters with extensions in correct order\n * 4. Service Assembly - Creates final DatabaseService with all components\n * 5. Initialization - Establishes database connections and readiness\n *\n * **ADAPTER CHAIN ORDER:**\n * Base → Encryption → SoftDelete → Caching → Audit → ReadReplica\n * (innermost to outermost - each wraps the previous)\n */\n\n// Core service and interfaces - Main building blocks\nimport { DatabaseService } from \"@service/DatabaseService\"; // Main service implementation\n\n// Factory and adapters - Core creation logic\nimport { AdapterFactory } from \"./AdapterFactory\"; // Creates base adapters\n\n// Extension adapters - Feature layers (imported in chain order)\nimport { SoftDeleteAdapter } from \"../extensions/SoftDeleteExtension\"; // Logical deletion (layer 2)\nimport { AuditAdapter } from \"../extensions/AuditExtension\"; // Operation logging (layer 4)\nimport { EncryptionAdapter } from \"../extensions/EncryptionExtension\"; // Data encryption (layer 1)\nimport { CachingAdapter } from \"../extensions/CachingAdapter\"; // Query caching (layer 3)\nimport { ReadReplicaAdapter } from \"../extensions/ReadReplicaAdapter\"; // Read/write splitting (layer 5)\n\n// External dependencies - Error handling and constants\nimport { DatabaseError } from \"@plyaz/errors\"; // Error classes\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport { ADAPTER_TYPES, ADAPTERS } from \"@plyaz/types/db\";\nimport type {\n DatabaseServiceInterface,\n SqlConfig,\n SupabaseConfig,\n DatabaseAdapterType,\n DatabaseConfig,\n DatabaseServiceConfig,\n DrizzleConfig,\n} from \"@plyaz/types/db\";\n\n/**\n * ADAPTER CHAIN BUILDER - Decorator Pattern Implementation\n *\n * **RESPONSIBILITY:** Wraps base adapter with extension layers in correct order\n * **PATTERN:** Decorator - each adapter wraps the previous, adding functionality\n * **ORDER:** Base → Encryption → SoftDelete → Caching → Audit → ReadReplica\n *\n * **WHY THIS ORDER:**\n * 1. Encryption (innermost) - Encrypts data before storage, decrypts after retrieval\n * 2. SoftDelete - Handles logical deletion, works on encrypted data\n * 3. Caching - Caches processed data (after encryption/soft-delete logic)\n * 4. Audit - Logs final operations (after all data processing)\n * 5. ReadReplica (outermost) - Routes requests to appropriate database\n *\n * @param baseAdapter - The core database adapter (Drizzle/Supabase/SQL)\n * @param config - Configuration specifying which extensions to enable\n * @returns Fully wrapped adapter with all enabled extensions\n *\n * @example\n * ```typescript\n * // Creates: AuditAdapter(CachingAdapter(EncryptionAdapter(DrizzleAdapter)))\n * const wrappedAdapter = buildAdapterChain(baseAdapter, {\n * encryption: { enabled: true, key: 'secret', fields: { users: ['ssn'] } },\n * softDelete: { enabled: true, field: 'deletedAt' },\n * audit: { enabled: true, retentionDays: 90 }\n * });\n * ```\n */\n// eslint-disable-next-line complexity\nfunction buildAdapterChain(\n baseAdapter: DatabaseAdapterType,\n config: DatabaseServiceConfig,\n): DatabaseAdapterType {\n let adapter: DatabaseAdapterType = baseAdapter;\n\n // Layer 1: Encryption (innermost after base)\n // RESPONSIBILITY: Encrypts sensitive fields before storage, decrypts on retrieval\n // WHEN: Always applied first to ensure data is encrypted at rest\n if (config.encryption?.enabled) {\n adapter = new EncryptionAdapter(adapter, config.encryption);\n }\n\n // Layer 2: Soft Delete\n // RESPONSIBILITY: Converts DELETE operations to UPDATE (sets deletedAt), filters soft-deleted records\n // WHEN: Applied after encryption so deletion logic works on encrypted data\n if (config.softDelete?.enabled) {\n adapter = new SoftDeleteAdapter(adapter, config.softDelete);\n }\n\n // Layer 3: Caching\n // RESPONSIBILITY: Stores query results in memory/Redis, invalidates on writes\n // WHEN: Applied after data processing to cache final processed results\n if (config.cache?.enabled) {\n adapter = new CachingAdapter(adapter, config.cache);\n }\n\n // Layer 4: Audit\n // RESPONSIBILITY: Logs all database operations for compliance and tracking\n // WHEN: Applied late in chain to capture final operation details\n if (config.audit?.enabled) {\n adapter = new AuditAdapter(adapter, {\n ...config.audit,\n // Pass encrypted fields config so audit can log which fields are encrypted at rest\n encryptedFields: config.encryption?.enabled\n ? config.encryption.fields\n : undefined,\n });\n }\n\n // Layer 5: Read Replica (outermost wrapper)\n // RESPONSIBILITY: Routes reads to replicas, writes to primary database\n // WHEN: Applied last to handle request routing before any processing\n if (config.readReplica?.enabled) {\n adapter = new ReadReplicaAdapter(adapter, {\n enabled: true,\n replicas: [], // TODO: Create replica adapters from config\n strategy: config.readReplica.strategy,\n fallbackToPrimary: config.readReplica.fallbackToPrimary,\n });\n }\n\n return adapter;\n}\n\n/**\n * CONFIG TRANSFORMER - Converts External to Internal Format\n *\n * **RESPONSIBILITY:** Transforms user-friendly config into internal adapter factory format\n * **WHY NEEDED:** External config is user-friendly, internal config is adapter-specific\n *\n * **TRANSFORMATIONS:**\n * - Maps adapter names to internal constants\n * - Extracts connection details from nested config\n * - Normalizes different config formats (connectionString vs url)\n * - Sets up adapter-specific options (pool, SSL, etc.)\n *\n * @param config - User-provided database service configuration\n * @returns Normalized configuration for AdapterFactory.create()\n */\nfunction createAdapterConfig(config: DatabaseServiceConfig): DatabaseConfig {\n // Drizzle Adapter Config - PostgreSQL with Drizzle ORM\n if (config.adapter === ADAPTER_TYPES.DRIZZLE) {\n const drizzleConfig = config.config as DrizzleConfig;\n return {\n adapter: ADAPTERS.DRIZZLE,\n // orm: ADAPTERS.SUPABASE,\n connectionString: drizzleConfig.connectionString ?? drizzleConfig.url, // Support both formats\n pool: drizzleConfig.poolSize\n ? { max: drizzleConfig.poolSize }\n : undefined, // Optional connection pooling\n tableIdColumns: drizzleConfig.tableIdColumns, // Custom ID column mappings\n };\n }\n\n // Supabase Adapter Config - Supabase API integration\n if (config.adapter === ADAPTER_TYPES.SUPABASE) {\n const supabaseConfig = config.config as SupabaseConfig;\n return {\n adapter: ADAPTERS.SUPABASE,\n // orm: ADAPTERS.SUPABASE, // Optional ORM choice\n supabaseUrl: supabaseConfig.supabaseUrl, // Supabase project URL\n supabaseAnonKey: supabaseConfig.supabaseAnonKey, // Public API key\n supabaseServiceKey: supabaseConfig.supabaseServiceKey, // Service role key (admin)\n schema: supabaseConfig.schema, // Database schema\n tableIdColumns: supabaseConfig.tableIdColumns, // Custom ID column mappings\n };\n }\n\n // Mock Adapter Config - In-memory testing database\n if (config.adapter === ADAPTER_TYPES.MOCK) {\n return {\n adapter: ADAPTERS.MOCK,\n ...config.config, // Pass through all mock config options\n };\n }\n\n // 🔧 Raw SQL Adapter Config - Direct SQL database connection\n const sqlConfig = config.config as SqlConfig;\n return {\n adapter: ADAPTERS.SQL,\n connectionString: sqlConfig.connectionString ?? sqlConfig.url, // Support both formats\n schema: sqlConfig.schema, // Default schema for all tables\n tableIdColumns: sqlConfig.tableIdColumns, // Custom ID column mappings\n };\n}\n\n/**\n * CONFIG VALIDATOR - Ensures Configuration Integrity\n *\n * **RESPONSIBILITY:** Validates user configuration before processing\n * **PREVENTS:** Runtime errors from invalid/missing configuration\n * **THROWS:** Descriptive validation errors for debugging\n *\n * **VALIDATION CHECKS:**\n * 1. Config object exists\n * 2. Adapter type is specified\n * 3. Adapter configuration is provided\n *\n * @param config - User-provided configuration to validate\n * @throws {DatabaseError} When configuration is invalid or incomplete\n */\nfunction validateConfig(config: DatabaseServiceConfig): void {\n // Check: Configuration object exists\n if (!config) {\n throw new DatabaseError(\n \"Database configuration is required\",\n DATABASE_ERROR_CODES.CONFIG_REQUIRED,\n {\n context: { source: \"validateConfig\" },\n cause: new Error(\"Database configuration is required\"),\n },\n );\n }\n\n // Check: Adapter type specified (drizzle/supabase/sql)\n if (!config.adapter) {\n throw new DatabaseError(\n \"Database adapter type is required\",\n DATABASE_ERROR_CODES.CONFIG_REQUIRED,\n {\n context: { source: \"validateConfig\" },\n cause: new Error(\"Database adapter type is required\"),\n },\n );\n }\n\n // Check: Adapter-specific configuration provided\n if (!config.config) {\n throw new DatabaseError(\n \"Adapter configuration is required\",\n DATABASE_ERROR_CODES.CONFIG_REQUIRED,\n {\n context: { source: \"validateConfig\" },\n cause: new Error(\"Adapter configuration is required\"),\n },\n );\n }\n}\n\n/**\n * MAIN FACTORY - Application Entry Point\n *\n * Creates a fully configured database service with extension chain.\n * This is the ONLY way applications should create database services.\n *\n * **Application Flow:**\n * 1. App calls createDatabaseService() at startup\n * 2. Factory validates config and creates base adapter (Drizzle/Supabase/etc.)\n * 3. Factory builds 6-layer adapter chain: Base → Encryption → SoftDelete → Cache → Audit → ReadReplica\n * 4. Factory creates DatabaseService with final wrapped adapter\n * 5. App uses returned DatabaseServiceInterface in repositories/services\n *\n * **What this function does:**\n * - Validates configuration using validateConfig()\n * - Creates base adapter via AdapterFactory.create()\n * - Builds decorator chain via buildAdapterChain()\n * - Initializes database connection\n * - Returns configured DatabaseService instance\n *\n * **Called by:** Application startup code (app.ts, main.ts)\n * **Calls:** validateConfig(), AdapterFactory.create(), buildAdapterChain(), DatabaseService constructor\n * **Returns to:** Application layer for injection into repositories\n *\n * @param config Complete database service configuration including adapter and extensions\n * @returns Promise resolving to configured DatabaseServiceInterface instance\n *\n * @throws {BaseError} When configuration is invalid or initialization fails\n *\n * @example\n * ### Basic Setup (app.ts)\n * ```typescript\n * import { createDatabaseService, Tables } from '@plyaz/db';\n *\n * // Called once at application startup\n * const db = await createDatabaseService({\n * adapter: 'drizzle',\n * config: { connectionString: process.env.DATABASE_URL }\n * });\n *\n * // Inject into services\n * const userService = new UserService(db);\n * ```\n *\n * @example\n * ### Production Configuration\n * ```typescript\n * const db = await createDatabaseService({\n * adapter: 'drizzle',\n * config: {\n * connectionString: process.env.DATABASE_URL,\n * poolSize: 20\n * },\n *\n * // Extensions applied in order: Base → Encryption → SoftDelete → Cache → Audit → ReadReplica\n * encryption: {\n * enabled: true,\n * key: process.env.ENCRYPTION_KEY,\n * fields: {\n * [Tables.USERS]: ['ssn', 'taxId'],\n * [Tables.PAYMENTS]: ['cardNumber', 'cvv']\n * }\n * },\n *\n * softDelete: {\n * enabled: true,\n * field: 'deletedAt'\n * },\n *\n * audit: {\n * enabled: true,\n * retentionDays: 90,\n * onAuditAfterWrite: async (event) => {\n * await complianceService.recordAudit(event);\n * }\n * },\n *\n * cache: {\n * enabled: true,\n * ttl: 300,\n * invalidation: 'write'\n * },\n *\n * events: {\n * onAfterWrite: async (event) => {\n * await notificationService.send(event);\n * }\n * }\n * });\n * ```\n *\n * @example\n * ### Testing Setup\n * ```typescript\n * // Use mock adapter for tests\n * const db = await createDatabaseService({\n * adapter: 'mock',\n * config: { logging: true }\n * });\n * ```\n */\nexport async function createDatabaseService(\n config: DatabaseServiceConfig,\n): Promise<DatabaseServiceInterface> {\n try {\n // STEP 1: Validate Configuration\n // RESPONSIBILITY: Ensure config is complete and valid before proceeding\n validateConfig(config);\n\n // STEP 2: Create Base Adapter\n // RESPONSIBILITY: Transform config and create core database adapter (Drizzle/Supabase/SQL)\n const adapterConfig = createAdapterConfig(config); // Transform to internal format\n const baseAdapter = AdapterFactory.create(\n adapterConfig.adapter,\n adapterConfig,\n ); // Create adapter\n\n // STEP 3: Build Adapter Chain\n // RESPONSIBILITY: Wrap base adapter with enabled extensions in correct order\n const finalAdapter = buildAdapterChain(baseAdapter, config);\n\n // STEP 4: Create Database Service\n // RESPONSIBILITY: Assemble final service with wrapped adapter and configuration\n const service = new DatabaseService({\n adapter: finalAdapter, // Fully wrapped adapter chain\n globalConfig: config, // Original configuration for reference\n eventHandlers: config.events, // Event handlers for notifications\n });\n\n // STEP 5: Initialize Database Connection\n // RESPONSIBILITY: Establish database connection and verify readiness\n const initResult = await baseAdapter.initialize();\n if (!initResult.success) {\n throw new DatabaseError(\n `Failed to initialize adapter: ${initResult.error?.message ?? \"Unknown error\"}`,\n DATABASE_ERROR_CODES.INIT_FAILED,\n {\n context: { source: \"createDatabaseService\" },\n cause: initResult.error ?? new Error(\"Failed to initialize adapter\"),\n },\n );\n }\n\n return service; // Return fully configured and initialized service\n } catch (error) {\n throw new DatabaseError(\n `Failed to create database service: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.INIT_FAILED,\n {\n context: { source: \"createDatabaseService\" },\n cause: error as Error,\n },\n );\n }\n}\n","/**\n * @fileoverview Base Repository for @plyaz/db package\n *\n * This module provides the BaseRepository abstract class that serves as the foundation\n * for all domain-specific repositories in the @plyaz/db package. It provides type-safe\n * CRUD operations and consistent interface patterns.\n *\n */\n\nimport type {\n DatabaseResult,\n PaginatedResult,\n QueryOptions,\n Filter,\n DatabaseServiceInterface,\n CreateInput,\n OperationConfig,\n} from \"@plyaz/types/db\";\n\n/**\n * BASE REPOSITORY - Repository Layer Foundation\n *\n * Base repository providing common CRUD operations for domain entities.\n * All domain-specific repositories extend this class for type-safe database operations.\n *\n * **Application Flow Position:**\n * Service Layer → **Repository Layer** → DatabaseService → Adapter Chain\n *\n * **What this class provides:**\n * - Type-safe CRUD operations for domain entities\n * - Consistent interface across all repositories\n * - Delegation to DatabaseService with proper table mapping\n * - Foundation for domain-specific repository methods\n * - Default operation config (adapter, schema, etc.) that can be overridden per-query\n *\n * **Called by:** Service layer (UserService, OrderService, etc.)\n * **Calls:** DatabaseService methods (get, create, update, delete, etc.)\n * **Extended by:** Domain repositories (UserRepository, OrderRepository, etc.)\n *\n * @template T The entity type this repository manages\n *\n * @example\n * ### Creating a Domain Repository\n * ```typescript\n * interface User {\n * id: string;\n * name: string;\n * email: string;\n * createdAt: Date;\n * }\n *\n * class UserRepository extends BaseRepository<User> {\n * constructor(db: DatabaseServiceInterface) {\n * super(db, Tables.USERS);\n * }\n *\n * // Domain-specific methods\n * async findByEmail(email: string) {\n * return this.findOne({ field: 'email', operator: 'eq', value: email });\n * }\n * }\n * ```\n *\n * @example\n * ### Repository with Default Adapter\n * ```typescript\n * // Analytics repository that always uses the 'analytics' adapter by default\n * class AnalyticsRepository extends BaseRepository<Event> {\n * constructor(db: DatabaseServiceInterface) {\n * super(db, 'events', { adapter: 'analytics', schema: 'analytics' });\n * }\n * }\n *\n * // All queries use analytics adapter by default\n * await analyticsRepo.findById('event-123'); // Uses 'analytics' adapter\n *\n * // But can still override per-query\n * await analyticsRepo.findById('event-123', { adapter: 'primary' });\n * ```\n *\n * @example\n * ### Usage in Service Layer\n * ```typescript\n * class UserService {\n * constructor(private userRepo: UserRepository) {}\n *\n * async getUserById(id: string) {\n * // Calls BaseRepository.findById() → DatabaseService.get()\n * return this.userRepo.findById(id);\n * }\n * }\n * ```\n */\nexport abstract class BaseRepository<T extends Record<string, unknown>> {\n protected readonly defaultConfig?: OperationConfig;\n\n constructor(\n protected readonly db: DatabaseServiceInterface,\n protected readonly tableName: string,\n defaultConfig?: OperationConfig,\n ) {\n this.defaultConfig = defaultConfig;\n }\n\n /**\n * Merges default repository config with per-operation config\n * Per-operation config takes precedence over default config\n */\n private mergeConfig(\n operationConfig?: OperationConfig,\n ): OperationConfig | undefined {\n if (!this.defaultConfig && !operationConfig) {\n return undefined;\n }\n return {\n ...this.defaultConfig,\n ...operationConfig,\n };\n }\n\n /**\n * Find a single entity by its primary key ID\n *\n * @param {string} id - The primary key ID of the entity to retrieve\n * @param {OperationConfig} [config] - Optional per-operation configuration (adapter selection, schema override, etc.)\n * @returns {Promise<DatabaseResult<T | null>>} Promise resolving to the entity or null if not found\n *\n * @example\n * ```typescript\n * const result = await userRepository.findById('user-123');\n * if (result.success && result.value) {\n * console.log('Found user:', result.value.name);\n * }\n *\n * // Use specific adapter for this query\n * const analyticsResult = await userRepository.findById('user-123', {\n * adapter: 'analytics'\n * });\n * ```\n */\n async findById(\n id: string,\n config?: OperationConfig,\n ): Promise<DatabaseResult<T | null>> {\n return this.db.get<T>(this.tableName, id, this.mergeConfig(config));\n }\n\n /**\n * Find multiple entities with optional filtering, sorting, and pagination\n *\n * @param {QueryOptions<T>} [options] - Optional query configuration with type-safe fields\n * @param {OperationConfig} [config] - Optional per-operation configuration (adapter selection, schema override, etc.)\n * @returns {Promise<DatabaseResult<PaginatedResult<T>>>} Promise resolving to paginated results\n *\n * @example\n * ```typescript\n * const result = await userRepository.findMany({\n * filter: { field: 'status', operator: 'eq', value: 'active' },\n * sort: [{ field: 'createdAt', direction: 'desc' }],\n * pagination: { limit: 20, offset: 0 }\n * });\n *\n * // Query from analytics database\n * const analyticsResult = await userRepository.findMany({}, {\n * adapter: 'analytics'\n * });\n * ```\n */\n async findMany(\n options?: QueryOptions<T>,\n config?: OperationConfig,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n return this.db.list<T>(this.tableName, options, this.mergeConfig(config));\n }\n\n /**\n * Create a new entity in the database\n *\n * @param {CreateInput<T>} data - The entity data to create (id is auto-generated)\n * @param {OperationConfig} [config] - Optional per-operation configuration (adapter selection, schema override, etc.)\n * @returns {Promise<DatabaseResult<T>>} Promise resolving to the created entity\n *\n * @example\n * ```typescript\n * const result = await userRepository.create({\n * name: 'John Doe',\n * email: 'john@example.com'\n * });\n *\n * // Create in specific database/schema\n * const result = await userRepository.create({\n * name: 'Jane Doe'\n * }, {\n * adapter: 'secondary',\n * schema: 'backoffice'\n * });\n * ```\n */\n async create(\n data: CreateInput<T>,\n config?: OperationConfig,\n ): Promise<DatabaseResult<T>> {\n return this.db.create<T>(this.tableName, data, this.mergeConfig(config));\n }\n\n /**\n * Update an existing entity by ID\n *\n * @param {string} id - The primary key ID of the entity to update\n * @param {Partial<T>} data - Partial entity data containing fields to update\n * @param {OperationConfig} [config] - Optional per-operation configuration (adapter selection, schema override, etc.)\n * @returns {Promise<DatabaseResult<T>>} Promise resolving to the updated entity\n *\n * @example\n * ```typescript\n * const result = await userRepository.update('user-123', {\n * email: 'newemail@example.com',\n * updatedAt: new Date()\n * });\n *\n * // Update in specific adapter with custom ID column\n * const result = await userRepository.update('flag-key', {\n * value: true\n * }, {\n * adapter: 'config',\n * idColumn: 'key'\n * });\n * ```\n */\n async update(\n id: string,\n data: Partial<T>,\n config?: OperationConfig,\n ): Promise<DatabaseResult<T>> {\n return this.db.update<T>(\n this.tableName,\n id,\n data,\n this.mergeConfig(config),\n );\n }\n\n /**\n * Delete an entity by ID (hard delete)\n *\n * @param {string} id - The primary key ID of the entity to delete\n * @param {OperationConfig} [config] - Optional per-operation configuration (adapter selection, schema override, etc.)\n * @returns {Promise<DatabaseResult<void>>} Promise resolving when deletion is complete\n *\n * @warning This is a permanent operation that cannot be undone\n * @see {@link softDelete} For recoverable deletion\n *\n * @example\n * ```typescript\n * const result = await userRepository.delete('user-123');\n *\n * // Delete from specific adapter\n * const result = await userRepository.delete('user-123', {\n * adapter: 'archive'\n * });\n * ```\n */\n async delete(\n id: string,\n config?: OperationConfig,\n ): Promise<DatabaseResult<void>> {\n return this.db.delete(this.tableName, id, this.mergeConfig(config));\n }\n\n /**\n * Count entities matching optional filter criteria\n *\n * @param {Filter<T>} [filter] - Optional filter conditions with type-safe fields\n * @param {OperationConfig} [config] - Optional per-operation configuration (adapter selection, schema override, etc.)\n * @returns {Promise<DatabaseResult<number>>} Promise resolving to the count\n *\n * @example\n * ```typescript\n * const totalResult = await userRepository.count();\n * const activeResult = await userRepository.count({\n * field: 'status', operator: 'eq', value: 'active'\n * });\n *\n * // Count in specific adapter\n * const archiveCount = await userRepository.count(undefined, {\n * adapter: 'archive'\n * });\n * ```\n */\n async count(\n filter?: Filter<T>,\n config?: OperationConfig,\n ): Promise<DatabaseResult<number>> {\n return this.db.count(this.tableName, filter, this.mergeConfig(config));\n }\n\n /**\n * Check if an entity exists by ID\n *\n * @param {string} id - The primary key ID to check\n * @param {OperationConfig} [config] - Optional per-operation configuration (adapter selection, schema override, etc.)\n * @returns {Promise<DatabaseResult<boolean>>} Promise resolving to existence status\n *\n * @example\n * ```typescript\n * const existsResult = await userRepository.exists('user-123');\n * if (existsResult.success && existsResult.value) {\n * console.log('User exists');\n * }\n *\n * // Check existence in specific adapter\n * const existsInArchive = await userRepository.exists('user-123', {\n * adapter: 'archive'\n * });\n * ```\n */\n async exists(\n id: string,\n config?: OperationConfig,\n ): Promise<DatabaseResult<boolean>> {\n const result = await this.db.get<T>(\n this.tableName,\n id,\n this.mergeConfig(config),\n );\n return {\n success: result.success,\n value: result.success && result.value !== null,\n error: result.error,\n };\n }\n\n /**\n * Find the first entity matching filter criteria\n *\n * @param {Filter<T>} filter - Filter conditions with type-safe fields\n * @param {OperationConfig} [config] - Optional per-operation configuration (adapter selection, schema override, etc.)\n * @returns {Promise<DatabaseResult<T | null>>} Promise resolving to first match or null\n *\n * @example\n * ```typescript\n * const result = await userRepository.findOne({\n * field: 'email', operator: 'eq', value: 'john@example.com'\n * });\n *\n * // Find in specific adapter\n * const archivedUser = await userRepository.findOne({\n * field: 'email', operator: 'eq', value: 'john@example.com'\n * }, {\n * adapter: 'archive',\n * includeSoftDeleted: true\n * });\n * ```\n */\n async findOne(\n filter: Filter<T>,\n config?: OperationConfig,\n ): Promise<DatabaseResult<T | null>> {\n return this.db.findOne<T>(this.tableName, filter, this.mergeConfig(config));\n }\n\n /**\n * Soft delete an entity by ID (recoverable deletion)\n *\n * @param {string} id - The primary key ID of the entity to soft delete\n * @param {OperationConfig} [config] - Optional per-operation configuration (adapter selection, schema override, etc.)\n * @returns {Promise<DatabaseResult<void>>} Promise resolving when soft deletion is complete\n *\n * @see {@link delete} For permanent deletion\n *\n * @example\n * ```typescript\n * const result = await userRepository.softDelete('user-123');\n * // User is hidden but can be recovered\n *\n * // Soft delete in specific adapter\n * const result = await userRepository.softDelete('user-123', {\n * adapter: 'primary',\n * skipAudit: false\n * });\n * ```\n */\n async softDelete(\n id: string,\n config?: OperationConfig,\n ): Promise<DatabaseResult<void>> {\n return this.db.softDelete(this.tableName, id, this.mergeConfig(config));\n }\n}\n","/**\n * MultiWriteExtension - Write to primary + multiple secondary adapters\n *\n * Decorator that wraps the base adapter to replicate writes across\n * multiple secondary adapters for redundancy, cross-region replication,\n * or analytics syncing.\n *\n * @example\n * ```typescript\n * const db = await createDatabaseService({\n * adapter: 'sql',\n * config: { connectionString: process.env.DATABASE_URL },\n *\n * multiWrite: {\n * enabled: true,\n * adapters: [\n * { adapter: 'supabase', config: { ... } },\n * { adapter: 'sql', config: { connectionString: process.env.ANALYTICS_DB } }\n * ],\n * mode: 'best-effort', // or 'strict'\n * onSecondaryFailure: 'log', // or 'warn', 'throw'\n * timeout: 5000\n * }\n * });\n * ```\n */\n\nimport type {\n DatabaseAdapterType,\n DatabaseResult,\n PaginatedResult,\n QueryOptions,\n Transaction,\n DatabaseHealthStatus,\n Filter,\n MultiWriteConfig,\n} from \"@plyaz/types/db\";\nimport { DatabasePackageError } from \"@plyaz/errors\";\nimport { ERROR_CODES } from \"@plyaz/types/errors\";\n\n/**\n * MultiWriteAdapter - Extension for multi-adapter write replication\n *\n * Decorates a base adapter to replicate all write operations (create, update, delete)\n * to multiple secondary adapters. Reads always go to the primary adapter.\n */\nexport class MultiWriteAdapter implements DatabaseAdapterType {\n public baseAdapter: DatabaseAdapterType;\n private config: Required<MultiWriteConfig>;\n\n constructor(baseAdapter: DatabaseAdapterType, config: MultiWriteConfig) {\n this.baseAdapter = baseAdapter;\n this.config = {\n mode: \"best-effort\",\n onSecondaryFailure: \"log\",\n timeout: 5000,\n ...config,\n };\n }\n\n async initialize(): Promise<DatabaseResult<void>> {\n return this.baseAdapter.initialize();\n }\n\n async close(): Promise<DatabaseResult<void>> {\n return this.baseAdapter.close();\n }\n\n async connect(): Promise<void> {\n await this.baseAdapter.connect();\n // Also connect all secondaries\n for (const secondary of this.config.adapters) {\n if (typeof secondary.connect === \"function\") {\n await secondary.connect();\n }\n }\n }\n\n async disconnect(): Promise<void> {\n await this.baseAdapter.disconnect();\n // Also disconnect all secondaries\n for (const secondary of this.config.adapters) {\n if (typeof secondary.disconnect === \"function\") {\n await secondary.disconnect();\n }\n }\n }\n\n getClient(): object {\n return this.baseAdapter.getClient();\n }\n\n async query<T>(sql: string, params?: unknown[]): Promise<T[]> {\n return this.baseAdapter.query<T>(sql, params as T[] | undefined);\n }\n\n registerTable<TTable = string, TIdColumn = string>(\n name: string,\n table?: TTable,\n idColumn?: TIdColumn,\n ): void {\n this.baseAdapter.registerTable(name, table, idColumn);\n\n // Also register on secondaries\n for (const secondary of this.config.adapters) {\n if (typeof secondary.registerTable === \"function\") {\n secondary.registerTable(name, table, idColumn);\n }\n }\n }\n\n // Read operations - always use primary\n async findById<T>(\n table: string,\n id: string,\n ): Promise<DatabaseResult<T | null>> {\n return this.baseAdapter.findById<T>(table, id);\n }\n\n async findMany<T extends Record<string, unknown>>(\n table: string,\n options?: QueryOptions<T>,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n return this.baseAdapter.findMany<T>(table, options);\n }\n\n async exists(table: string, id: string): Promise<DatabaseResult<boolean>> {\n return this.baseAdapter.exists(table, id);\n }\n\n async count<T extends Record<string, unknown> = Record<string, unknown>>(\n table: string,\n filter?: Filter<T>,\n ): Promise<DatabaseResult<number>> {\n return this.baseAdapter.count<T>(table, filter);\n }\n\n // Write operations - replicate to secondaries\n async create<T extends Record<string, unknown>>(\n table: string,\n data: T,\n ): Promise<DatabaseResult<T>> {\n // Write to primary first\n const primaryResult = await this.baseAdapter.create<T>(table, data);\n\n if (!primaryResult.success) {\n return primaryResult;\n }\n\n // Replicate to secondaries\n await this.replicateWrite(() =>\n Promise.all(\n this.config.adapters.map((adapter) => adapter.create(table, data)),\n ),\n );\n\n return primaryResult;\n }\n\n async update<T>(\n table: string,\n id: string,\n data: Partial<T>,\n ): Promise<DatabaseResult<T>> {\n // Write to primary first\n const primaryResult = await this.baseAdapter.update<T>(table, id, data);\n\n if (!primaryResult.success) {\n return primaryResult;\n }\n\n // Replicate to secondaries\n await this.replicateWrite(() =>\n Promise.all(\n this.config.adapters.map((adapter) => adapter.update(table, id, data)),\n ),\n );\n\n return primaryResult;\n }\n\n async delete(table: string, id: string): Promise<DatabaseResult<void>> {\n // Write to primary first\n const primaryResult = await this.baseAdapter.delete(table, id);\n\n if (!primaryResult.success) {\n return primaryResult;\n }\n\n // Replicate to secondaries\n await this.replicateWrite(() =>\n Promise.all(\n this.config.adapters.map((adapter) => adapter.delete(table, id)),\n ),\n );\n\n return primaryResult;\n }\n\n async transaction<T>(\n callback: (trx: Transaction) => Promise<T>,\n ): Promise<DatabaseResult<T>> {\n // Transactions only on primary (secondaries get individual operations)\n return this.baseAdapter.transaction(callback);\n }\n\n async healthCheck(): Promise<DatabaseResult<DatabaseHealthStatus>> {\n return this.baseAdapter.healthCheck();\n }\n\n /**\n * Replicate write operation to secondary adapters\n */\n private async replicateWrite(\n fn: () => Promise<DatabaseResult<unknown>[]>,\n ): Promise<void> {\n if (this.config.mode === \"strict\") {\n // Strict mode: Wait for all secondaries, throw on any failure\n const results = await Promise.allSettled([\n this.executeWithTimeout(fn(), this.config.timeout),\n ]);\n\n const failures = results.filter((r) => r.status === \"rejected\");\n if (failures.length > 0) {\n this.handleSecondaryFailure(failures);\n }\n } else {\n // Best-effort mode: Fire and forget (non-blocking)\n this.executeWithTimeout(fn(), this.config.timeout)\n .then((results) => {\n const failures = results.filter((r) => !r.success);\n if (failures.length > 0) {\n this.handleSecondaryFailure(\n failures.map((f) => ({\n status: \"rejected\" as const,\n reason: f.error,\n })),\n );\n }\n })\n .catch((error) => {\n this.handleSecondaryFailure([\n { status: \"rejected\" as const, reason: error },\n ]);\n });\n }\n }\n\n /**\n * Execute operation with timeout\n */\n private async executeWithTimeout<T>(\n promise: Promise<T>,\n timeoutMs: number,\n ): Promise<T> {\n return Promise.race([\n promise,\n new Promise<T>((_, reject) =>\n setTimeout(\n () => reject(new Error(\"Secondary write timeout\")),\n timeoutMs,\n ),\n ),\n ]);\n }\n\n /**\n * Handle secondary adapter failures\n */\n private handleSecondaryFailure(\n failures: PromiseSettledResult<unknown>[],\n ): void {\n const errorMessages = failures\n .map((f) =>\n f.status === \"rejected\" ? f.reason?.message : \"Unknown error\",\n )\n .join(\", \");\n\n const message = `Multi-write secondary failure: ${errorMessages}`;\n\n switch (this.config.onSecondaryFailure) {\n case \"log\":\n console.log(`[MultiWrite] ${message}`);\n break;\n case \"warn\":\n console.warn(`[MultiWrite] ${message}`);\n break;\n case \"throw\":\n throw new DatabasePackageError(message, ERROR_CODES.DB_UPDATE_FAILED);\n }\n }\n}\n","/**\n * MultiReadExtension - Read from primary + multiple read replicas\n *\n * Decorator that wraps the base adapter to distribute reads across\n * multiple read replicas using configurable load balancing strategies.\n * Supports automatic failover to primary on replica failure.\n *\n * @example\n * ```typescript\n * const db = await createDatabaseService({\n * adapter: 'sql',\n * config: { connectionString: process.env.DATABASE_URL },\n *\n * multiRead: {\n * enabled: true,\n * adapters: [\n * { adapter: 'sql', config: { connectionString: process.env.REPLICA1_URL } },\n * { adapter: 'sql', config: { connectionString: process.env.REPLICA2_URL } }\n * ],\n * strategy: 'round-robin', // or 'random', 'fastest', 'least-conn'\n * fallbackToPrimary: true,\n * healthCheckInterval: 30000\n * }\n * });\n * ```\n */\n\nimport type {\n DatabaseAdapterType,\n DatabaseResult,\n PaginatedResult,\n QueryOptions,\n Transaction,\n DatabaseHealthStatus,\n Filter,\n MultiReadConfig,\n ReplicaHealth,\n} from \"@plyaz/types/db\";\nimport { DatabasePackageError } from \"@plyaz/errors\";\nimport { ERROR_CODES } from \"@plyaz/types/errors\";\nimport { failure } from \"@utils/databaseResultHelpers\";\n\n/** Weight for existing average in EMA calculation */\nconst EMA_EXISTING_WEIGHT = 0.8;\n/** Weight for new value in EMA calculation */\nconst EMA_NEW_WEIGHT = 0.2;\n\n/**\n * MultiReadAdapter - Extension for multi-replica read distribution\n *\n * Decorates a base adapter to distribute read operations across multiple\n * read replicas. Writes always go to the primary adapter. Supports automatic\n * failover and health tracking.\n */\nexport class MultiReadAdapter implements DatabaseAdapterType {\n public baseAdapter: DatabaseAdapterType;\n private config: Required<MultiReadConfig>;\n private currentReadIndex = 0;\n private replicaHealth: Map<DatabaseAdapterType, ReplicaHealth> = new Map();\n private healthCheckTimer?: globalThis.NodeJS.Timeout;\n\n constructor(baseAdapter: DatabaseAdapterType, config: MultiReadConfig) {\n this.baseAdapter = baseAdapter;\n this.config = {\n strategy: \"round-robin\",\n fallbackToPrimary: true,\n healthCheckInterval: 30000,\n maxFailures: 3,\n ...config,\n };\n\n // Initialize health tracking\n this.initializeHealthTracking();\n\n // Start health checks\n if (this.config.adapters.length > 0) {\n this.startHealthChecks();\n }\n }\n\n async initialize(): Promise<DatabaseResult<void>> {\n return this.baseAdapter.initialize();\n }\n\n async close(): Promise<DatabaseResult<void>> {\n this.stopHealthChecks();\n return this.baseAdapter.close();\n }\n\n async connect(): Promise<void> {\n await this.baseAdapter.connect();\n // Also connect all replicas\n for (const replica of this.config.adapters) {\n if (typeof replica.connect === \"function\") {\n await replica.connect();\n }\n }\n }\n\n async disconnect(): Promise<void> {\n await this.baseAdapter.disconnect();\n // Also disconnect all replicas\n for (const replica of this.config.adapters) {\n if (typeof replica.disconnect === \"function\") {\n await replica.disconnect();\n }\n }\n }\n\n getClient(): object {\n return this.baseAdapter.getClient();\n }\n\n async query<T>(sql: string, params?: unknown[]): Promise<T[]> {\n return this.baseAdapter.query<T>(sql, params as T[] | undefined);\n }\n\n registerTable<TTable = string, TIdColumn = string>(\n name: string,\n table?: TTable,\n idColumn?: TIdColumn,\n ): void {\n this.baseAdapter.registerTable(name, table, idColumn);\n\n // Also register on replicas\n for (const replica of this.config.adapters) {\n if (typeof replica.registerTable === \"function\") {\n replica.registerTable(name, table, idColumn);\n }\n }\n }\n\n // Read operations - use replicas with load balancing\n async findById<T>(\n table: string,\n id: string,\n ): Promise<DatabaseResult<T | null>> {\n return this.readFromReplicas((adapter) => adapter.findById<T>(table, id));\n }\n\n async findMany<T extends Record<string, unknown>>(\n table: string,\n options?: QueryOptions<T>,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n return this.readFromReplicas((adapter) =>\n adapter.findMany<T>(table, options),\n );\n }\n\n async exists(table: string, id: string): Promise<DatabaseResult<boolean>> {\n return this.readFromReplicas((adapter) => adapter.exists(table, id));\n }\n\n async count<T extends Record<string, unknown> = Record<string, unknown>>(\n table: string,\n filter?: Filter<T>,\n ): Promise<DatabaseResult<number>> {\n return this.readFromReplicas((adapter) => adapter.count<T>(table, filter));\n }\n\n // Write operations - always use primary\n async create<T extends Record<string, unknown>>(\n table: string,\n data: T,\n ): Promise<DatabaseResult<T>> {\n return this.baseAdapter.create<T>(table, data);\n }\n\n async update<T>(\n table: string,\n id: string,\n data: Partial<T>,\n ): Promise<DatabaseResult<T>> {\n return this.baseAdapter.update<T>(table, id, data);\n }\n\n async delete(table: string, id: string): Promise<DatabaseResult<void>> {\n return this.baseAdapter.delete(table, id);\n }\n\n async transaction<T>(\n callback: (trx: Transaction) => Promise<T>,\n ): Promise<DatabaseResult<T>> {\n // Transactions only on primary\n return this.baseAdapter.transaction(callback);\n }\n\n async healthCheck(): Promise<DatabaseResult<DatabaseHealthStatus>> {\n return this.baseAdapter.healthCheck();\n }\n\n /**\n * Read from replica adapters using configured strategy\n */\n private async readFromReplicas<T>(\n fn: (adapter: DatabaseAdapterType) => Promise<DatabaseResult<T>>,\n ): Promise<DatabaseResult<T>> {\n const healthyReplicas = this.config.adapters.filter((adapter) =>\n this.isReplicaHealthy(adapter),\n );\n\n if (healthyReplicas.length === 0) {\n // No healthy replicas, fallback to primary\n if (this.config.fallbackToPrimary) {\n return fn(this.baseAdapter);\n }\n return failure(\n new DatabasePackageError(\n \"No healthy read replicas available\",\n ERROR_CODES.DB_CONNECTION_FAILED,\n ),\n );\n }\n\n // Select replica based on strategy\n const selectedReplica = this.selectReplica(healthyReplicas);\n const startTime = Date.now();\n\n try {\n const result = await fn(selectedReplica);\n\n // Update health metrics\n this.updateHealthMetrics(selectedReplica, true, Date.now() - startTime);\n\n if (result.success) {\n return result;\n }\n\n // Result failed, try fallback\n if (this.config.fallbackToPrimary) {\n this.updateHealthMetrics(\n selectedReplica,\n false,\n Date.now() - startTime,\n );\n return fn(this.baseAdapter);\n }\n\n return result;\n } catch (error) {\n // Replica failed, try fallback\n this.updateHealthMetrics(selectedReplica, false, Date.now() - startTime);\n\n if (this.config.fallbackToPrimary) {\n return fn(this.baseAdapter);\n }\n\n return failure(\n new DatabasePackageError(\n `Read from replica failed: ${(error as Error).message}`,\n ERROR_CODES.DB_QUERY_FAILED,\n { cause: error as Error },\n ),\n );\n }\n }\n\n /**\n * Select a replica based on load balancing strategy\n */\n private selectReplica(replicas: DatabaseAdapterType[]): DatabaseAdapterType {\n switch (this.config.strategy) {\n case \"round-robin\":\n this.currentReadIndex = (this.currentReadIndex + 1) % replicas.length;\n return replicas[this.currentReadIndex];\n\n case \"random\":\n return replicas[Math.floor(Math.random() * replicas.length)];\n\n case \"fastest\":\n // Select replica with lowest avg response time\n return replicas.reduce((fastest, current) => {\n const fastestHealth = this.replicaHealth.get(fastest);\n const currentHealth = this.replicaHealth.get(current);\n if (!fastestHealth || !currentHealth) return fastest;\n return currentHealth.avgResponseTime < fastestHealth.avgResponseTime\n ? current\n : fastest;\n });\n\n case \"least-conn\":\n // For now, same as fastest (would need connection tracking)\n return this.selectReplica(\n replicas.filter((r) => this.isReplicaHealthy(r)),\n );\n\n default:\n return replicas[0];\n }\n }\n\n /**\n * Initialize health tracking for all replicas\n */\n private initializeHealthTracking(): void {\n for (const adapter of this.config.adapters) {\n this.replicaHealth.set(adapter, {\n adapter,\n isHealthy: true,\n failureCount: 0,\n lastChecked: Date.now(),\n avgResponseTime: 0,\n });\n }\n }\n\n /**\n * Update health metrics for a replica\n */\n private updateHealthMetrics(\n adapter: DatabaseAdapterType,\n success: boolean,\n responseTime: number,\n ): void {\n const health = this.replicaHealth.get(adapter);\n if (!health) return;\n\n if (success) {\n health.failureCount = 0;\n health.isHealthy = true;\n health.avgResponseTime =\n health.avgResponseTime * EMA_EXISTING_WEIGHT +\n responseTime * EMA_NEW_WEIGHT; // EMA\n } else {\n health.failureCount++;\n if (health.failureCount >= this.config.maxFailures) {\n health.isHealthy = false;\n }\n }\n\n health.lastChecked = Date.now();\n }\n\n /**\n * Check if replica is healthy\n */\n private isReplicaHealthy(adapter: DatabaseAdapterType): boolean {\n const health = this.replicaHealth.get(adapter);\n return health?.isHealthy ?? true;\n }\n\n /**\n * Start health check interval\n */\n private startHealthChecks(): void {\n this.healthCheckTimer = setInterval(async () => {\n for (const adapter of this.config.adapters) {\n const startTime = Date.now();\n try {\n const result = await adapter.healthCheck();\n const responseTime = Date.now() - startTime;\n\n this.updateHealthMetrics(adapter, result.success, responseTime);\n } catch {\n this.updateHealthMetrics(adapter, false, Date.now() - startTime);\n }\n }\n }, this.config.healthCheckInterval);\n }\n\n /**\n * Stop health checks\n */\n private stopHealthChecks(): void {\n if (this.healthCheckTimer) {\n clearInterval(this.healthCheckTimer);\n this.healthCheckTimer = undefined;\n }\n }\n\n /**\n * Get health status of all replicas\n */\n getHealthStatus(): Record<string, ReplicaHealth> {\n const status: Record<string, ReplicaHealth> = {};\n let index = 0;\n\n for (const [, health] of this.replicaHealth.entries()) {\n status[`replica-${index++}`] = health;\n }\n\n return status;\n }\n\n /**\n * Cleanup resources\n */\n dispose(): void {\n this.stopHealthChecks();\n this.replicaHealth.clear();\n }\n}\n","import { SetMetadata } from \"@nestjs/common\";\nimport type { UseReplicaOptions } from \"@plyaz/types\";\n\nexport const USE_REPLICA_KEY = \"use_replica\";\n\n/**\n * Decorator to specify replica usage for database operations.\n *\n * @example\n * ```typescript\n * class UserService {\n * @UseReplica({ strategy: ReplicaStrategy.REPLICA })\n * async getUsers() {\n * // This will use a read replica\n * return this.db.findMany('users');\n * }\n *\n * @UseReplica({ strategy: ReplicaStrategy.PRIMARY })\n * async createUser(user: User) {\n * // This will use primary\n * return this.db.create('users', user);\n * }\n * }\n * ```\n */\nexport function UseReplica(options: UseReplicaOptions = {}): MethodDecorator {\n return (target, propertyKey, descriptor) => {\n SetMetadata(USE_REPLICA_KEY, options)(target, propertyKey, descriptor);\n };\n}\n","import { Redis } from \"ioredis\";\nimport { failure, success } from \"@utils/databaseResultHelpers\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport type { DatabaseResult } from \"@plyaz/types/db\";\nimport { NUMERIX } from \"@plyaz/config\";\n\n/**\n * Redis-based caching service for database query results.\n * Provides automatic serialization/deserialization, TTL management, and pattern-based invalidation.\n *\n * @example\n * ### Basic Usage\n * ```typescript\n * const cache = new RedisCache({\n * url: 'redis://localhost:6379',\n * defaultTTL: 3600 // 1 hour\n * });\n *\n * // Set a value\n * await cache.set('user:123', { id: 123, name: 'John' });\n *\n * // Get a value\n * const result = await cache.get('user:123');\n * if (result.success) {\n * console.log(result.value); // { id: 123, name: 'John' }\n * }\n *\n * // Delete a value\n * await cache.del('user:123');\n * ```\n *\n * @example\n * ### User Profile Caching\n * ```typescript\n * class UserProfileCache {\n * constructor(private cache: RedisCache) {}\n *\n * async getUserProfile(userId: string): Promise<DatabaseResult<UserProfile>> {\n * const cacheKey = `profile:${userId}`;\n *\n * // Try cache first\n * const cached = await this.cache.get<UserProfile>(cacheKey);\n * if (cached.success && cached.value) {\n * return cached;\n * }\n *\n * // Fetch from database\n * const profile = await this.db.findById('profiles', userId);\n *\n * // Cache the result\n * if (profile.success) {\n * await this.cache.set(cacheKey, profile.value, 1800); // 30 minutes\n * }\n *\n * return profile;\n * }\n *\n * async updateUserProfile(userId: string, data: Partial<UserProfile>): Promise<DatabaseResult<UserProfile>> {\n * const updated = await this.db.update('profiles', userId, data);\n *\n * // Invalidate cache on successful update\n * if (updated.success) {\n * await this.cache.del(`profile:${userId}`);\n * // Also invalidate related caches\n * await this.cache.invalidatePattern(`user:${userId}:*`);\n * }\n *\n * return updated;\n * }\n * }\n * ```\n *\n * @example\n * ### Product Catalog Caching\n * ```typescript\n * class ProductCatalogCache {\n * constructor(private cache: RedisCache) {}\n *\n * async getProductsByCategory(categoryId: string): Promise<DatabaseResult<Product[]>> {\n * const cacheKey = `products:category:${categoryId}`;\n *\n * const cached = await this.cache.get<Product[]>(cacheKey);\n * if (cached.success && cached.value) {\n * return cached;\n * }\n *\n * const products = await this.db.findMany('products', {\n * filter: { field: 'categoryId', operator: 'eq', value: categoryId }\n * });\n *\n * // Cache product lists longer (2 hours) as they change less frequently\n * if (products.success) {\n * await this.cache.set(cacheKey, products.value, 7200);\n * }\n *\n * return products;\n * }\n *\n * async updateProductStock(productId: string, quantity: number): Promise<DatabaseResult<void>> {\n * await this.db.update('inventory', productId, { quantity });\n *\n * // Invalidate product cache and related caches\n * await this.cache.del(`product:${productId}`);\n * await this.cache.invalidatePattern(`products:category:*`);\n * await this.cache.invalidatePattern(`inventory:low-stock`);\n * }\n * }\n * ```\n *\n * @example\n * ### Multi-tenant Caching\n * ```typescript\n * class MultiTenantCache {\n * constructor(private cache: RedisCache) {}\n *\n * async getTenantConfig(tenantId: string): Promise<DatabaseResult<TenantConfig>> {\n * const cacheKey = `tenant:${tenantId}:config`;\n *\n * const cached = await this.cache.get<TenantConfig>(cacheKey);\n * if (cached.success && cached.value) {\n * return cached;\n * }\n *\n * const config = await this.db.findById('tenant_configs', tenantId);\n *\n * // Cache configs longer (4 hours) as they rarely change\n * if (config.success) {\n * await this.cache.set(cacheKey, config.value, 14400);\n * }\n *\n * return config;\n * }\n *\n * async updateTenantSettings(tenantId: string): Promise<DatabaseResult<void>> {\n * await this.db.update('tenant_settings', tenantId, { updatedAt: new Date() });\n *\n * // Invalidate all tenant-related caches\n * await this.cache.invalidatePattern(`tenant:${tenantId}:*`);\n * }\n * }\n * ```\n *\n * @example\n * ### Analytics Data Caching\n * ```typescript\n * class AnalyticsCache {\n * constructor(private cache: RedisCache) {}\n *\n * async getDailyStats(date: string): Promise<DatabaseResult<DailyStats>> {\n * const cacheKey = `analytics:daily:${date}`;\n *\n * const cached = await this.cache.get<DailyStats>(cacheKey);\n * if (cached.success && cached.value) {\n * return cached;\n * }\n *\n * // Analytics queries are expensive, cache them longer\n * const stats = await this.db.findById('daily_stats', date);\n *\n * if (stats.success) {\n * // Cache for 6 hours as analytics data doesn't change frequently\n * await this.cache.set(cacheKey, stats.value, 21600);\n * }\n *\n * return stats;\n * }\n *\n * async recordMetric(metric: MetricData): Promise<DatabaseResult<void>> {\n * await this.db.create('metrics', metric);\n *\n * // Invalidate aggregated analytics caches\n * await this.cache.invalidatePattern('analytics:aggregated:*');\n * await this.cache.invalidatePattern('analytics:dashboard:*');\n * }\n * }\n * ```\n *\n * @example\n * ### Session Management\n * ```typescript\n * class SessionCache {\n * constructor(private cache: RedisCache) {}\n *\n * async getUserSession(sessionId: string): Promise<DatabaseResult<Session>> {\n * const cacheKey = `session:${sessionId}`;\n *\n * // Sessions are accessed frequently, cache them but with short TTL\n * const cached = await this.cache.get<Session>(cacheKey);\n * if (cached.success && cached.value) {\n * return cached;\n * }\n *\n * const session = await this.db.findById('sessions', sessionId);\n *\n * if (session.success) {\n * // Cache sessions for 15 minutes\n * await this.cache.set(cacheKey, session.value, 900);\n * }\n *\n * return session;\n * }\n *\n * async invalidateUserSessions(userId: string): Promise<DatabaseResult<void>> {\n * // Invalidate all sessions for a user (e.g., on logout or password change)\n * await this.cache.invalidatePattern(`session:user:${userId}:*`);\n * }\n * }\n * ```\n */\nexport class RedisCache {\n private redis: Redis;\n private defaultTTL: number;\n // Using shared logger instance from @plyaz/logger\n\n /**\n * Creates a new RedisCache instance.\n * @param config Redis configuration\n *\n * @example\n * ```typescript\n * // Basic configuration\n * const cache = new RedisCache({\n * url: 'redis://localhost:6379'\n * });\n *\n * // With custom default TTL\n * const cacheWithCustomTTL = new RedisCache({\n * url: 'redis://localhost:6379',\n * defaultTTL: 1800 // 30 minutes\n * });\n *\n * // Production configuration with options\n * const productionCache = new RedisCache({\n * url: 'redis://redis-cluster.example.com:6379',\n * defaultTTL: 3600,\n * // Additional Redis options can be passed here\n * });\n * ```\n */\n constructor(config: { url: string; defaultTTL?: number }) {\n this.redis = new Redis(config.url);\n this.defaultTTL = config.defaultTTL ?? NUMERIX.THIRTY_SIX_HUNDERD;\n }\n\n /**\n * Retrieves a value from cache by key.\n * Automatically handles JSON deserialization.\n *\n * @param key Cache key\n * @returns DatabaseResult containing cached value or null if not found\n *\n * @example\n * ```typescript\n * // Get user profile\n * const result = await cache.get<UserProfile>('profile:123');\n * if (result.success && result.value) {\n * console.log('User:', result.value.name);\n * } else {\n * console.log('Profile not found or cache error');\n * }\n *\n * // Get product list\n * const products = await cache.get<Product[]>('products:featured');\n * if (products.success && products.value) {\n * products.value.forEach(product => {\n * console.log(product.name, product.price);\n * });\n * }\n * ```\n */\n async get<T extends object>(key: string): Promise<DatabaseResult<T | null>> {\n try {\n const value = await this.redis.get(key);\n if (!value) {\n return success();\n }\n\n const parsed = JSON.parse(value);\n // Validate that parsed value is an object\n if (parsed && typeof parsed === \"object\") {\n return success(parsed as T);\n }\n\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n \"Cache get failed\",\n DATABASE_ERROR_CODES.CACHE_GET_FAILED,\n { context: { source: \"RedisCache.get\", key, cause: error } },\n ),\n );\n }\n }\n\n /**\n * Sets a value in cache with optional TTL.\n * Automatically handles JSON serialization.\n *\n * @param key Cache key\n * @param value Value to cache\n * @param ttl Time to live in seconds (uses default if not specified)\n * @returns DatabaseResult indicating operation success\n *\n * @example\n * ```typescript\n * // Cache with default TTL\n * await cache.set('user:123', { id: 123, name: 'John' });\n *\n * // Cache with custom TTL (5 minutes)\n * await cache.set('session:abc123', sessionData, 300);\n *\n * // Cache with long TTL for static data\n * await cache.set('config:app-settings', appSettings, 86400); // 24 hours\n *\n * // Cache with short TTL for frequently changing data\n * await cache.set('metrics:realtime', realtimeData, 60); // 1 minute\n * ```\n */\n async set<T extends object>(\n key: string,\n value: T,\n ttl?: number,\n ): Promise<DatabaseResult<null>> {\n try {\n const ttlValue = ttl ?? this.defaultTTL;\n await this.redis.set(key, JSON.stringify(value), \"EX\", ttlValue);\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n \"Cache set failed\",\n DATABASE_ERROR_CODES.CACHE_SET_FAILED,\n { context: { source: \"RedisCache.set\", key, cause: error } },\n ),\n );\n }\n }\n\n /**\n * Deletes a value from cache.\n *\n * @param key Cache key\n * @returns DatabaseResult indicating operation success\n *\n * @example\n * ```typescript\n * // Delete specific cache entry\n * await cache.del('user:123');\n *\n * // Delete session on logout\n * await cache.del(`session:${sessionId}`);\n *\n * // Delete cached configuration\n * await cache.del('config:feature-flags');\n * ```\n */\n async del(key: string): Promise<DatabaseResult<null>> {\n try {\n await this.redis.del(key);\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n \"Cache delete failed\",\n DATABASE_ERROR_CODES.CACHE_DELETE_FAILED,\n {\n context: {\n source: \"RedisCache.del\",\n key,\n cause: error,\n },\n },\n ),\n );\n }\n }\n\n /**\n * Invalidates all cache entries matching a pattern.\n * Useful for clearing related cache entries when data changes.\n *\n * @param pattern Redis key pattern (e.g., 'users:*')\n * @returns DatabaseResult indicating operation success\n *\n * @example\n * ```typescript\n * // Invalidate all user-related caches\n * await cache.invalidatePattern('users:*');\n *\n * // Invalidate all caches for a specific category\n * await cache.invalidatePattern('products:category:electronics:*');\n *\n * // Invalidate all session caches\n * await cache.invalidatePattern('session:*');\n *\n * // Invalidate all caches for a tenant\n * await cache.invalidatePattern(`tenant:${tenantId}:*`);\n *\n * // Invalidate all analytics caches\n * await cache.invalidatePattern('analytics:*');\n * ```\n */\n async invalidatePattern(pattern: string): Promise<DatabaseResult<null>> {\n try {\n const keys = await this.redis.keys(pattern);\n if (keys.length > 0) {\n await this.redis.del(...keys);\n }\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n \"Cache invalidate failed\",\n DATABASE_ERROR_CODES.CACHE_INVALIDATE_FAILED,\n {\n context: {\n source: \"RedisCache.invalidatePattern\",\n pattern,\n cause: error,\n },\n },\n ),\n );\n }\n }\n\n /**\n * Generates a cache key for database queries.\n * Creates consistent, URL-safe keys that include table, operation, and parameters.\n *\n * @param table Database table name\n * @param operation Database operation type\n * @param params Query parameters object\n * @returns Generated cache key\n *\n * @example\n * ```typescript\n * // Simple key generation\n * const key = cache.generateKey('users', 'findById', { id: '123' });\n * // Returns: 'db:users:findById:eyJpYXJhbTAiOiIxMjMifQ=='\n *\n * // Complex query key\n * const complexKey = cache.generateKey('products', 'findMany', {\n * filter: { field: 'category', operator: 'eq', value: 'electronics' },\n * sort: [{ field: 'price', direction: 'asc' }],\n * pagination: { limit: 20, offset: 0 }\n * });\n *\n * // User-specific key\n * const userKey = cache.generateKey('orders', 'findMany', {\n * filter: { field: 'userId', operator: 'eq', value: '123' }\n * });\n * ```\n */\n generateKey(\n table: string,\n operation: string,\n params: Record<string, string | number | boolean | null>,\n ): string {\n const paramsStr = JSON.stringify(params || {});\n return `db:${table}:${operation}:${Buffer.from(paramsStr).toString(\"base64\")}`;\n }\n\n /**\n * Performs a health check on the Redis connection.\n * Useful for monitoring and ensuring cache availability.\n *\n * @returns DatabaseResult with boolean indicating if Redis is healthy\n *\n * @example\n * ```typescript\n * // Check Redis health\n * const health = await cache.healthCheck();\n * if (health.success && health.value) {\n * console.log('Redis is healthy');\n * } else {\n * console.log('Redis health check failed:', health.error?.message);\n * // Implement fallback logic or alerting\n * }\n *\n * // Use in health check endpoint\n * app.get('/health', async (req, res) => {\n * const dbHealth = await db.healthCheck();\n * const cacheHealth = await cache.healthCheck();\n *\n * res.json({\n * database: dbHealth.success && dbHealth.value,\n * cache: cacheHealth.success && cacheHealth.value,\n * timestamp: new Date()\n * });\n * });\n * ```\n */\n async healthCheck(): Promise<DatabaseResult<boolean>> {\n try {\n await this.redis.ping();\n return success(true);\n } catch (error) {\n return failure(\n new DatabaseError(\n \"Redis health check failed\",\n DATABASE_ERROR_CODES.CACHE_HEALTH_CHECK_FAILED,\n {\n context: {\n source: \"RedisCache.healthCheck\",\n cause: error,\n },\n },\n ),\n );\n }\n }\n\n /**\n * Closes the Redis connection gracefully.\n * Should be called during application shutdown.\n *\n * @example\n * ```typescript\n * // In your application shutdown logic\n * async function shutdown() {\n * console.log('Shutting down cache...');\n * await cache.close();\n * console.log('Cache connection closed');\n *\n * // Close other connections...\n * process.exit(0);\n * }\n *\n * // Handle graceful shutdown\n * process.on('SIGTERM', shutdown);\n * process.on('SIGINT', shutdown);\n * ```\n */\n async close(): Promise<void> {\n await this.redis.quit();\n }\n}\n","import { isString } from \"@utils/typeGuards\";\nimport type { RedisCache } from \"./RedisCache\";\nimport type { CacheableOptions, DatabaseResult } from \"@plyaz/types/db\";\n\n/**\n * Decorator that caches the result of a method.\n * Automatically generates cache keys and handles TTL.\n *\n * @example\n * ### Basic Usage\n * ```typescript\n * class UserService {\n * constructor(private cache: RedisCache) {}\n *\n * @Cacheable({ ttl: 300 }) // Cache for 5 minutes\n * async getUserById(id: string): Promise<DatabaseResult<User>> {\n * // First call: executes query and caches result\n * // Subsequent calls: returns cached result for 5 minutes\n * return this.db.findById('users', id);\n * }\n * }\n * ```\n *\n * @example\n * ### Custom Cache Key\n * ```typescript\n * class ProductService {\n * constructor(private cache: RedisCache) {}\n *\n * @Cacheable({\n * key: 'featured-products',\n * ttl: 1800 // Cache for 30 minutes\n * })\n * async getFeaturedProducts(): Promise<DatabaseResult<Product[]>> {\n * // Uses custom cache key 'featured-products'\n * return this.db.findMany('products', {\n * filter: { field: 'featured', operator: 'eq', value: true }\n * });\n * }\n * }\n * ```\n *\n * @example\n * ### Conditional Caching\n * ```typescript\n * class OrderService {\n * constructor(private cache: RedisCache) {}\n *\n * @Cacheable({\n * ttl: 600,\n * condition: (result) => result.success && result.value?.length > 0\n * })\n * async getRecentOrders(): Promise<DatabaseResult<Order[]>> {\n * // Only caches successful responses with non-empty results\n * // Prevents caching empty arrays or error responses\n * return this.db.findMany('orders', {\n * sort: [{ field: 'createdAt', direction: 'desc' }],\n * pagination: { limit: 10 }\n * });\n * }\n * }\n * ```\n *\n * @example\n * ### User Profile Caching\n * ```typescript\n * class ProfileService {\n * constructor(private cache: RedisCache) {}\n *\n * @Cacheable({ ttl: 3600 }) // Cache for 1 hour\n * async getUserProfile(userId: string): Promise<DatabaseResult<Profile>> {\n * // User profiles change infrequently, perfect for caching\n * return this.db.findById('profiles', userId);\n * }\n *\n * @CacheEvict({ key: 'user-profile' })\n * async updateProfile(userId: string, data: Partial<Profile>): Promise<DatabaseResult<Profile>> {\n * // When profile is updated, evict the cached version\n * return this.db.update('profiles', userId, data);\n * }\n * }\n * ```\n *\n * @example\n * ### Analytics Data Caching\n * ```typescript\n * class AnalyticsService {\n * constructor(private cache: RedisCache) {}\n *\n * @Cacheable({\n * ttl: 7200, // Cache for 2 hours\n * key: 'daily-stats'\n * })\n * async getDailyStats(date: string): Promise<DatabaseResult<DailyStats>> {\n * // Analytics queries are expensive, cache them longer\n * return this.db.findById('daily_stats', date);\n * }\n * }\n * ```\n */\nexport function Cacheable(options: CacheableOptions = {}): MethodDecorator {\n return (\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n ) => {\n const originalMethod = descriptor.value;\n\n if (!originalMethod || typeof originalMethod !== \"function\") {\n throw new TypeError(\n \"Cacheable decorator can only be applied to methods.\",\n );\n }\n\n descriptor.value = async function (\n this: { cache?: RedisCache },\n ...args: [string, ...Array<string>]\n ): Promise<DatabaseResult<object>> {\n // Check if cache is available on the instance\n const cache = this.cache;\n if (!cache) {\n return originalMethod.apply(this, args);\n }\n\n // Generate cache key\n const table = args[0];\n const operation = String(propertyKey);\n const params = buildParamsObject(args);\n\n const cacheKey =\n options.key ?? cache.generateKey(table, operation, params);\n\n // Try to get from cache with explicit type\n const cachedResult = await cache.get<object>(cacheKey);\n if (cachedResult.success && cachedResult.value !== null) {\n return cachedResult as DatabaseResult<object>;\n }\n\n // Execute original method\n const result = await originalMethod.apply(this, args);\n\n // Cache result if successful and meets condition\n if (\n result.success &&\n (!options.condition || options.condition(result.value))\n ) {\n await cache.set(cacheKey, result.value, options.ttl);\n }\n\n return result as DatabaseResult<object>;\n };\n\n return descriptor;\n };\n}\n\n/**\n * Builds a parameters object from function arguments for cache key generation.\n * Converts all arguments to strings to ensure consistent cache keys.\n *\n * @param args Function arguments (first is table name, rest are parameters)\n * @returns Parameters object with indexed keys for cache key generation\n *\n * @example\n * ### Basic Usage\n * ```typescript\n * const params = buildParamsObject(['users', '123']);\n * // Returns: { param0: '123' }\n * ```\n *\n * @example\n * ### Multiple Parameters\n * ```typescript\n * const params = buildParamsObject(['products', 'electronics', 'active', { limit: 10 }]);\n * // Returns: { param0: 'electronics', param1: 'active', param2: '{\"limit\":10}' }\n * ```\n *\n * @example\n * ### Complex Objects\n * ```typescript\n * const filters = { category: 'books', priceRange: { min: 10, max: 50 } };\n * const params = buildParamsObject(['products', 'search', filters]);\n * // Returns: { param0: 'search', param1: '{\"category\":\"books\",\"priceRange\":{\"min\":10,\"max\":50}}' }\n * ```\n *\n * @example\n * ### Cache Key Generation\n * ```typescript\n * const cacheKey = cache.generateKey('users', 'findById', params);\n * // Results in: 'users:findById:param0-123'\n *\n * const complexKey = cache.generateKey('products', 'search', params);\n * // Results in: 'products:search:param0-electronics_param1-active_param2-{\"limit\":10}'\n * ```\n *\n * @example\n * ### Real-World Usage in Repository\n * ```typescript\n * class UserRepository {\n * async findUsers(filters: UserFilters): Promise<DatabaseResult<User[]>> {\n * const args = ['users', 'find', filters];\n * const params = buildParamsObject(args);\n * const cacheKey = this.cache.generateKey('users', 'find', params);\n *\n * // Check cache first\n * const cached = await this.cache.get(cacheKey);\n * if (cached.success && cached.value) {\n * return cached;\n * }\n *\n * // Execute query and cache result\n * const result = await this.db.findMany('users', { filter: filters });\n * await this.cache.set(cacheKey, result.value, 300);\n * return result;\n * }\n * }\n * ```\n */\nfunction buildParamsObject<T extends Record<string, string>>(\n args: [string, ...Array<string>],\n): T {\n // extract and skip the table name\n const [, ...params] = args;\n const result: Record<string, string> = {};\n\n params.forEach((arg, index) => {\n const key = `param${index}`;\n result[key] = isString(arg) ? arg : JSON.stringify(arg);\n });\n\n return result as T;\n}\n","import type { RedisCache } from \"./RedisCache\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport type { CacheEvictOptions } from \"@plyaz/types\";\nimport { DB_REGEX } from \"@utils/regex\";\nimport { isString } from \"@utils/typeGuards\";\n\n/**\n * Decorator that evicts cache entries when a method is called.\n * Useful for keeping cache in sync with database changes.\n *\n * @example\n * ### Basic User Update\n * ```typescript\n * class UserService {\n * constructor(private cache: RedisCache) {}\n *\n * @CacheEvict({ key: 'user:123' })\n * async updateUser(id: string, data: Partial<User>): Promise<DatabaseResult<User>> {\n * // When user is updated, evict their specific cache entry\n * // This ensures next read gets fresh data\n * return this.db.update('users', id, data);\n * }\n * }\n * ```\n *\n * @example\n * ### User Deletion with Pattern Eviction\n * ```typescript\n * class UserService {\n * constructor(private cache: RedisCache) {}\n *\n * @CacheEvict({ pattern: 'users:*' })\n * async deleteUser(id: string): Promise<DatabaseResult<void>> {\n * // When user is deleted, evict ALL user-related cache entries\n * // This includes user lists, profiles, permissions, etc.\n * return this.db.delete('users', id);\n * }\n * }\n * ```\n *\n * @example\n * ### Product Management with Multiple Eviction Strategies\n * ```typescript\n * class ProductService {\n * constructor(private cache: RedisCache) {}\n *\n * @CacheEvict({ key: (id: string) => `product:${id}` })\n * async updateProduct(id: string, data: Partial<Product>): Promise<DatabaseResult<Product>> {\n * // Evict specific product cache\n * return this.db.update('products', id, data);\n * }\n *\n * @CacheEvict({ pattern: 'products:category:*' })\n * async updateProductCategory(categoryId: string): Promise<DatabaseResult<void>> {\n * // When category is updated, evict all products in that category\n * return this.db.update('categories', categoryId, { updatedAt: new Date() });\n * }\n *\n * @CacheEvict({ pattern: 'products:featured' })\n * async updateFeaturedProducts(): Promise<DatabaseResult<void>> {\n * // Evict featured products cache when featured list changes\n * return this.db.query('REFRESH MATERIALIZED VIEW featured_products');\n * }\n * }\n * ```\n *\n * @example\n * ### Cache Invalidation on Data Changes\n * ```typescript\n * class OrderService {\n * constructor(private cache: RedisCache) {}\n *\n * @CacheEvict({ pattern: 'orders:user:*' })\n * async createOrder(userId: string, orderData: CreateOrderDto): Promise<DatabaseResult<Order>> {\n * // When new order is created, evict user's order history cache\n * return this.db.create('orders', { ...orderData, userId });\n * }\n *\n * @CacheEvict({ pattern: 'orders:stats:*' })\n * async updateOrderStatus(orderId: string, status: string): Promise<DatabaseResult<void>> {\n * // When order status changes, evict order statistics cache\n * return this.db.update('orders', orderId, { status });\n * }\n *\n * @CacheEvict({ allEntries: true })\n * async resetOrderData(): Promise<DatabaseResult<void>> {\n * // Clear all order-related cache during data reset\n * return this.db.query('TRUNCATE orders CASCADE');\n * }\n * }\n * ```\n *\n * @example\n * ### Profile Management with Related Cache Eviction\n * ```typescript\n * class ProfileService {\n * constructor(private cache: RedisCache) {}\n *\n * @CacheEvict({ key: (userId: string) => `profile:${userId}` })\n * async updateProfile(userId: string, data: Partial<Profile>): Promise<DatabaseResult<Profile>> {\n * // Evict user profile cache\n * return this.db.update('profiles', userId, data);\n * }\n *\n * @CacheEvict({ pattern: 'profile:preferences:*' })\n * async updatePreferences(userId: string, preferences: UserPreferences): Promise<DatabaseResult<void>> {\n * // Evict user preferences cache\n * return this.db.update('user_preferences', userId, preferences);\n * }\n *\n * @CacheEvict({ pattern: 'profile:activity:*' })\n * async logUserActivity(userId: string, activity: UserActivity): Promise<DatabaseResult<void>> {\n * // Evict user activity timeline cache\n * return this.db.create('user_activities', { userId, ...activity });\n * }\n * }\n * ```\n *\n * @example\n * ### E-commerce Inventory Management\n * ```typescript\n * class InventoryService {\n * constructor(private cache: RedisCache) {}\n *\n * @CacheEvict({ key: (productId: string) => `inventory:${productId}` })\n * async updateInventory(productId: string, quantity: number): Promise<DatabaseResult<void>> {\n * // Evict specific product inventory cache\n * return this.db.update('inventory', productId, { quantity });\n * }\n *\n * @CacheEvict({ pattern: 'inventory:category:*' })\n * async updateCategoryInventory(categoryId: string): Promise<DatabaseResult<void>> {\n * // Evict all inventory in category when category stock changes\n * return this.db.query('UPDATE inventory SET needs_restock = true WHERE category_id = $1', [categoryId]);\n * }\n *\n * @CacheEvict({ pattern: 'inventory:low-stock' })\n * async checkLowStockProducts(): Promise<DatabaseResult<Product[]>> {\n * // Evict low stock cache when checking (data may have changed)\n * return this.db.findMany('products', {\n * filter: { field: 'stock', operator: 'lt', value: 10 }\n * });\n * }\n * }\n * ```\n *\n * @example\n * ### Content Management System\n * ```typescript\n * class ContentService {\n * constructor(private cache: RedisCache) {}\n *\n * @CacheEvict({ key: (contentId: string) => `content:${contentId}` })\n * async updateContent(contentId: string, data: Partial<Content>): Promise<DatabaseResult<Content>> {\n * // Evict specific content cache\n * return this.db.update('contents', contentId, data);\n * }\n *\n * @CacheEvict({ pattern: 'content:author:*' })\n * async updateAuthorProfile(authorId: string): Promise<DatabaseResult<void>> {\n * // Evict all content by this author when profile changes\n * return this.db.update('authors', authorId, { updatedAt: new Date() });\n * }\n *\n * @CacheEvict({ pattern: 'content:published:*' })\n * async publishContent(contentId: string): Promise<DatabaseResult<void>> {\n * // Evict published content cache when new content is published\n * return this.db.update('contents', contentId, { status: 'published' });\n * }\n *\n * @CacheEvict({ pattern: 'content:tag:*' })\n * async updateContentTags(contentId: string, tags: string[]): Promise<DatabaseResult<void>> {\n * // Evict tag-based content caches when tags change\n * return this.db.update('content_tags', contentId, { tags });\n * }\n * }\n * ```\n *\n * @example\n * ### Dynamic Cache Key Generation\n * ```typescript\n * class CacheService {\n * constructor(private cache: RedisCache) {}\n *\n * @CacheEvict({ key: (userId: string, resourceId: string) => `user:${userId}:resource:${resourceId}` })\n * async updateUserResource(userId: string, resourceId: string, data: object): Promise<DatabaseResult<void>> {\n * // Evict specific user resource cache\n * return this.db.update('user_resources', { userId, resourceId, data });\n * }\n *\n * @CacheEvict({ pattern: (tenantId: string) => `tenant:${tenantId}:*` })\n * async updateTenantSettings(tenantId: string): Promise<DatabaseResult<void>> {\n * // Evict all tenant-specific cache entries\n * return this.db.update('tenants', tenantId, { settings: { updatedAt: new Date() } });\n * }\n * }\n * ```\n */\nfunction validateMethodArgs(args: [string, ...Array<string>]): void {\n if (!args || args.length === 0) {\n throw new DatabaseError(\n \"Method arguments are required\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: {\n source: \"CacheEvict.validateMethodArgs\",\n },\n },\n );\n }\n}\n\nfunction validateMethodResult(result: object): void {\n if (!result || typeof result !== \"object\") {\n throw new DatabaseError(\n \"Method result must be an object\",\n DATABASE_ERROR_CODES.INVALID_RESULT,\n {\n context: { source: \"CacheEvict.validateMethodResult\" },\n },\n );\n }\n}\n\nasync function handleCacheInvalidation(\n cache: RedisCache | undefined,\n options: CacheEvictOptions,\n args: [string, ...Array<string>],\n result: object | undefined,\n): Promise<void> {\n if (\n cache &&\n result &&\n typeof result === \"object\" &&\n \"success\" in result &&\n result.success\n ) {\n try {\n await invalidateCache(cache, options, args);\n } catch (cacheError) {\n console.error(\"Cache invalidation failed:\", cacheError);\n }\n }\n}\n\nexport function CacheEvict(options: CacheEvictOptions = {}): MethodDecorator {\n return (\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n ) => {\n const originalMethod = descriptor.value;\n\n if (!originalMethod || typeof originalMethod !== \"function\") {\n throw new DatabaseError(\n \"CacheEvict decorator can only be applied to methods\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: {\n source: \"CacheEvict.decorator\",\n },\n },\n );\n }\n\n descriptor.value = async function (\n this: { cache?: RedisCache },\n ...args: [string, ...Array<string>]\n ): Promise<object> {\n validateMethodArgs(args);\n\n let result;\n try {\n result = await originalMethod.apply(this, args);\n validateMethodResult(result);\n return result;\n } finally {\n await handleCacheInvalidation(this.cache, options, args, result);\n }\n };\n\n return descriptor;\n };\n}\n\n/**\n * Invalidates cache based on provided options.\n *\n * @param cache Redis cache instance\n * @param options Cache eviction options\n * @param args Method arguments\n *\n * @example\n * ### Evict Specific Key\n * ```typescript\n * // Evict a specific user cache entry\n * await invalidateCache(cache, { key: 'user:123' }, ['users', '123']);\n * ```\n *\n * @example\n * ### Evict by Pattern\n * ```typescript\n * // Evict all user-related cache entries\n * await invalidateCache(cache, { pattern: 'users:*' }, ['users']);\n *\n * // Evict all products in a category\n * await invalidateCache(cache, { pattern: 'products:category:electronics:*' }, ['products']);\n * ```\n *\n * @example\n * ### Evict All Entries\n * ```typescript\n * // Clear the entire cache (use carefully!)\n * await invalidateCache(cache, { allEntries: true }, []);\n * ```\n *\n * @example\n * ### Default Table-based Eviction\n * ```typescript\n * // Evict all cache entries for 'orders' table\n * await invalidateCache(cache, {}, ['orders', '123']);\n * // Results in evicting 'db:orders:*'\n * ```\n *\n * @example\n * ### Complex Eviction Strategy\n * ```typescript\n * class CacheManager {\n * async onUserUpdate(userId: string): Promise<void> {\n * // Evict user profile\n * await invalidateCache(cache, { key: `profile:${userId}` }, []);\n *\n * // Evict user's order history\n * await invalidateCache(cache, { pattern: `orders:user:${userId}:*` }, []);\n *\n * // Evict user permissions\n * await invalidateCache(cache, { pattern: `permissions:user:${userId}:*` }, []);\n * }\n *\n * async onProductUpdate(productId: string): Promise<void> {\n * // Evict product details\n * await invalidateCache(cache, { key: `product:${productId}` }, []);\n *\n * // Evict product category listings\n * await invalidateCache(cache, { pattern: `products:category:*` }, []);\n *\n * // Evict related product recommendations\n * await invalidateCache(cache, { pattern: `recommendations:product:${productId}:*` }, []);\n * }\n * }\n * ```\n *\n * @example\n * ### Bulk Operations\n * ```typescript\n * class BulkCacheManager {\n * async onCategoryUpdate(categoryId: string): Promise<void> {\n * const evictionStrategies = [\n * { pattern: `products:category:${categoryId}:*` },\n * { pattern: `category:${categoryId}:*` },\n * { pattern: `search:category:${categoryId}:*` }\n * ];\n *\n * // Execute all eviction strategies in parallel\n * await Promise.all(\n * evictionStrategies.map(strategy =>\n * invalidateCache(cache, strategy, ['products'])\n * )\n * );\n * }\n *\n * async onTenantUpdate(tenantId: string): Promise<void> {\n * // Evict all tenant-related cache entries\n * await invalidateCache(cache, { pattern: `tenant:${tenantId}:*` }, ['tenants']);\n *\n * // Evict all user sessions for this tenant\n * await invalidateCache(cache, { pattern: `sessions:tenant:${tenantId}:*` }, []);\n *\n * // Evict tenant-specific reports\n * await invalidateCache(cache, { pattern: `reports:tenant:${tenantId}:*` }, []);\n * }\n * }\n * ```\n *\n * @example\n * ### Multi-tenant Cache Invalidation\n * ```typescript\n * class MultiTenantCacheManager {\n * async onUserUpdateInTenant(tenantId: string, userId: string): Promise<void> {\n * // Evict user profile in tenant context\n * await invalidateCache(cache, { key: `tenant:${tenantId}:user:${userId}` }, []);\n *\n * // Evict user's data across all tenants\n * await invalidateCache(cache, { pattern: `user:${userId}:*` }, []);\n *\n * // Evict tenant's user list\n * await invalidateCache(cache, { pattern: `tenant:${tenantId}:users:*` }, []);\n * }\n *\n * async onGlobalDataUpdate(): Promise<void> {\n * // Clear all caches when global data changes\n * await invalidateCache(cache, { allEntries: true }, []);\n * }\n * }\n * ```\n */\nfunction isValidCacheKey(key: string): boolean {\n return isString(key) && DB_REGEX.isValidCacheKey(key);\n}\n\nfunction isValidCachePattern(pattern: string): boolean {\n return isString(pattern) && DB_REGEX.isValidCachePattern(pattern);\n}\n\nfunction isValidTableName(table: string): boolean {\n return isString(table) && DB_REGEX.isValidTableName(table);\n}\n\nasync function evictAllEntries(cache: RedisCache): Promise<void> {\n await cache.invalidatePattern(\"db:*\");\n}\n\nasync function evictByPattern(\n cache: RedisCache,\n pattern: string,\n): Promise<void> {\n if (isValidCachePattern(pattern)) {\n await cache.invalidatePattern(pattern);\n }\n}\n\nasync function evictByKey(cache: RedisCache, key: string): Promise<void> {\n if (isValidCacheKey(key)) {\n await cache.del(key);\n }\n}\n\nasync function evictByTable(cache: RedisCache, table: string): Promise<void> {\n if (isValidTableName(table)) {\n await cache.invalidatePattern(`db:${table}:*`);\n }\n}\n\nasync function invalidateCache(\n cache: RedisCache,\n options: CacheEvictOptions,\n args: [string, ...Array<string>],\n): Promise<void> {\n try {\n if (options.allEntries) {\n await evictAllEntries(cache);\n return;\n }\n\n if (options.pattern) {\n await evictByPattern(cache, options.pattern);\n return;\n }\n\n if (options.key) {\n await evictByKey(cache, options.key);\n return;\n }\n\n const table = args[0];\n if (table) {\n await evictByTable(cache, table);\n }\n } catch (error) {\n throw new DatabaseError(\n \"Cache eviction failed\",\n DATABASE_ERROR_CODES.CACHE_INVALIDATE_FAILED,\n {\n context: { source: \"CacheEvict.invalidateCache\", cause: error },\n },\n );\n }\n}\n","import { Pool } from \"pg\";\nimport type { PoolClient } from \"pg\";\nimport { failure, success } from \"@utils/databaseResultHelpers\";\nimport { logger } from \"@plyaz/logger\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport {\n type DatabaseResult,\n type DatabaseHealthStatus,\n type DynamicPoolConfig,\n type PoolMetrics,\n DB_POOL_EVENTS,\n} from \"@plyaz/types/db\";\nimport { NUMERIX } from \"@plyaz/config\";\nimport { dynamicPoolDefaultConfig } from \"@plyaz/config/db\";\n\n/**\n * Dynamic connection pool that automatically adjusts size based on load.\n * Provides detailed metrics and health monitoring.\n *\n * @example\n * ```typescript\n * const pool = new DynamicPool('postgres://localhost:5432/db', {\n * min: 2,\n * max: 20,\n * scaling: {\n * enabled: true,\n * scaleUpThreshold: 80,\n * scaleDownThreshold: 20,\n * scaleInterval: 30000,\n * maxScale: 5\n * }\n * });\n *\n * // Execute a query\n * const result = await pool.query('SELECT * FROM users');\n *\n * // Get pool metrics\n * const metrics = pool.getMetrics();\n * console.log(`Active connections: ${metrics.activeConnections}`);\n *\n * // Health check\n * const health = await pool.healthCheck();\n * console.log(`Pool healthy: ${health.value?.isHealthy}`);\n * ```\n *\n * @example\n * ### High-Traffic Application\n * ```typescript\n * class DatabasePool {\n * private pool: DynamicPool;\n *\n * constructor() {\n * this.pool = new DynamicPool(process.env.DATABASE_URL, {\n * min: 5,\n * max: 50,\n * scaling: {\n * enabled: true,\n * scaleUpThreshold: 75,\n * scaleDownThreshold: 25,\n * scaleInterval: 15000, // Check every 15 seconds\n * maxScale: 10\n * }\n * });\n * }\n *\n * async query<T>(sql: string, params: object[] = []): Promise<DatabaseResult<T[]>> {\n * return this.pool.query<T>(sql, params);\n * }\n *\n * async getHealthStatus(): Promise<DatabaseResult<HealthStatus>> {\n * return this.pool.healthCheck();\n * }\n *\n * async shutdown(): Promise<void> {\n * await this.pool.end();\n * }\n * }\n * ```\n *\n * @example\n * ### Connection Pool Monitoring\n * ```typescript\n * class PoolMonitor {\n * constructor(private pool: DynamicPool) {}\n *\n * async startMonitoring(): Promise<void> {\n * setInterval(() => {\n * const metrics = this.pool.getMetrics();\n * const utilization = metrics.totalConnections > 0\n * ? (metrics.activeConnections / metrics.totalConnections) * 100\n * : 0;\n *\n * console.log(`Pool Utilization: ${utilization.toFixed(1)}%`);\n * console.log(`Active: ${metrics.activeConnections}, Idle: ${metrics.idleConnections}`);\n * console.log(`Waiting: ${metrics.waitingRequests}`);\n *\n * // Alert if pool is under pressure\n * if (utilization > 90) {\n * console.warn('Pool utilization is very high!');\n * }\n * }, 30000); // Every 30 seconds\n * }\n * }\n * ```\n *\n * @example\n * ### Auto-scaling Configuration\n * ```typescript\n * const poolConfig: DynamicPoolConfig = {\n * min: 3,\n * max: 30,\n * idleTimeoutMillis: 60000, // 1 minute\n * acquireTimeoutMillis: 5000, // 5 seconds\n * scaling: {\n * enabled: true,\n * scaleUpThreshold: 80, // Scale up when 80% utilized\n * scaleDownThreshold: 20, // Scale down when 20% idle\n * scaleInterval: 10000, // Check every 10 seconds\n * maxScale: 5 // Add/remove up to 5 connections at once\n * }\n * };\n *\n * const pool = new DynamicPool('postgres://localhost:5432/myapp', poolConfig);\n * ```\n */\n\nexport class DynamicPool {\n private pool: Pool;\n private config: DynamicPoolConfig;\n private metrics = {\n totalConnections: 0,\n activeConnections: 0,\n idleConnections: 0,\n waitingRequests: 0,\n totalAcquired: 0,\n averageAcquisitionTime: 0,\n } as PoolMetrics;\n private scalingTimer?: ReturnType<typeof setInterval>;\n\n /**\n * Creates a new DynamicPool instance.\n * @param connectionString Database connection string\n * @param config Pool configuration options\n *\n * @example\n * ```typescript\n * // Basic configuration\n * const pool = new DynamicPool('postgres://localhost:5432/db');\n *\n * // Advanced configuration\n * const pool = new DynamicPool('postgres://localhost:5432/db', {\n * min: 5,\n * max: 25,\n * scaling: {\n * enabled: true,\n * scaleUpThreshold: 75,\n * scaleInterval: 20000\n * }\n * });\n * ```\n */\n constructor(\n connectionString: string,\n config: Partial<DynamicPoolConfig> = {},\n ) {\n this.config = {\n ...dynamicPoolDefaultConfig,\n ...config,\n };\n\n this.pool = new Pool({\n connectionString,\n min: this.config.min,\n max: this.config.max,\n idleTimeoutMillis: this.config.idleTimeoutMillis,\n });\n\n this.setupEventListeners();\n\n if (this.config.scaling.enabled) {\n this.startScalingTimer();\n }\n }\n\n /**\n * Sets up event listeners for the connection pool.\n */\n private setupEventListeners(): void {\n this.pool.on(DB_POOL_EVENTS.CONNECT, () => {\n this.metrics.totalConnections++;\n });\n\n this.pool.on(DB_POOL_EVENTS.ACQUIRE, (client: PoolClient) => {\n this.metrics.activeConnections++;\n this.metrics.idleConnections--;\n this.metrics.totalAcquired++;\n (client as PoolClient & { acquiredAt: number }).acquiredAt = Date.now();\n });\n\n // Fixed: Updated the release event listener to match the correct signature\n this.pool.on(\n DB_POOL_EVENTS.RELEASE,\n (err: Error | undefined, client: PoolClient) => {\n if (err) {\n logger.error(`Error on client release: ${err.message}`);\n }\n\n this.metrics.activeConnections--;\n this.metrics.idleConnections++;\n this.metrics.totalReleased++;\n\n // Update average acquisition time\n const acquiredAt = (client as PoolClient & { acquiredAt?: number })\n .acquiredAt;\n if (acquiredAt) {\n const acquisitionTime = Date.now() - acquiredAt;\n this.metrics.averageAcquisitionTime =\n (this.metrics.averageAcquisitionTime *\n (this.metrics.totalReleased - 1) +\n acquisitionTime) /\n this.metrics.totalReleased;\n }\n },\n );\n\n this.pool.on(DB_POOL_EVENTS.REMOVE, () => {\n this.metrics.totalConnections--;\n });\n }\n\n /**\n * Starts the auto-scaling timer.\n */\n private startScalingTimer(): void {\n this.scalingTimer = setInterval(() => {\n this.adjustPoolSize();\n }, this.config.scaling.scaleInterval);\n }\n\n /**\n * Adjusts pool size based on current load.\n */\n private adjustPoolSize(): void {\n const { activeConnections, idleConnections, totalConnections } =\n this.metrics;\n const { min, max, scaling } = this.config;\n\n const utilizationRate =\n totalConnections > 0\n ? (activeConnections / totalConnections) * NUMERIX.HUNDERD\n : 0;\n\n const idleRate =\n totalConnections > 0\n ? (idleConnections / totalConnections) * NUMERIX.HUNDERD\n : 0;\n\n // Scale up if utilization is high\n if (utilizationRate > scaling.scaleUpThreshold && totalConnections < max) {\n const scaleBy = Math.min(scaling.maxScale, max - totalConnections);\n this.adjustPoolCount(totalConnections + scaleBy);\n }\n\n // Scale down if idle rate is high\n if (idleRate > scaling.scaleDownThreshold && totalConnections > min) {\n const scaleBy = Math.min(scaling.maxScale, totalConnections - min);\n this.adjustPoolCount(totalConnections - scaleBy);\n }\n }\n\n /**\n * Adjusts the pool connection count.\n * @param newCount New connection count\n */\n private adjustPoolCount(newCount: number): void {\n // TODO: Implement dynamic pool scaling\n // Note: pg pool doesn't directly support scaling down at runtime\n // Current implementation logs the scaling action for monitoring\n\n const currentCount = this.pool.totalCount;\n const difference = newCount - currentCount;\n\n // Scaling up: pg pool will automatically create new connections as needed\n // when requests exceed current pool size (up to max limit)\n // No direct action needed - pool handles this automatically\n\n // Scaling down: pg pool doesn't support removing idle connections\n // They will naturally expire based on idleTimeoutMillis setting\n // Future implementation could force close idle connections\n\n // Log scaling decision for monitoring and debugging\n // In production, this could emit metrics or trigger alerts\n logger.debug(\n `Scale check: current=${currentCount}, target=${newCount}, difference=${difference}`,\n );\n }\n\n /**\n * Executes a database query with timing and error tracking.\n * @param sql SQL query string\n * @param params Query parameters\n * @returns Query result\n *\n * @example\n * ```typescript\n * // Simple query\n * const result = await pool.query('SELECT * FROM users');\n *\n * // Query with parameters\n * const result = await pool.query(\n * 'SELECT * FROM users WHERE id = $1 AND active = $2',\n * [123, true]\n * );\n *\n * // Query with type safety\n * const users = await pool.query<User>('SELECT * FROM users');\n * ```\n */\n async query<T extends object>(\n sql: string,\n params: object[] = [],\n ): Promise<DatabaseResult<T[]>> {\n const startTime = Date.now();\n try {\n // Validate SQL to prevent injection\n if (!sql || typeof sql !== \"string\") {\n throw new DatabaseError(\n \"Invalid SQL query\",\n DATABASE_ERROR_CODES.INVALID_SQL,\n {\n context: {\n source: \"DynamicPool.query\",\n },\n },\n );\n }\n\n const result = await this.pool.query(sql, params);\n return success(result.rows);\n } catch (error) {\n logger.error(`Database query failed: ${(error as Error).message}`);\n return failure(\n new DatabaseError(\n \"Database query failed\",\n DATABASE_ERROR_CODES.QUERY_FAILED,\n {\n context: {\n source: \"DynamicPool.query\",\n cause: error,\n },\n },\n ),\n );\n } finally {\n // Track slow queries\n const duration = Date.now() - startTime;\n if (duration > NUMERIX.THOUSAND) {\n // 1 second threshold\n const SQL_PREVIEW_LENGTH = 100;\n logger.warn(\n `Slow query detected: ${duration}ms - ${sql.substring(0, SQL_PREVIEW_LENGTH)}`,\n );\n }\n }\n }\n\n /**\n * Performs a health check on the connection pool.\n * @returns Health status with detailed metrics\n *\n * @example\n * ```typescript\n * const health = await pool.healthCheck();\n * if (health.success && health.value?.isHealthy) {\n * console.log('Pool is healthy');\n * console.log(`Response time: ${health.value.responseTime}ms`);\n * } else {\n * console.log('Pool health check failed');\n * }\n * ```\n */\n async healthCheck(): Promise<DatabaseResult<DatabaseHealthStatus>> {\n const startTime = Date.now();\n let client: PoolClient | null = null;\n\n try {\n client = await this.pool.connect();\n await client.query(\"SELECT 1\");\n\n const utilizationRate =\n this.metrics.totalConnections > 0\n ? (this.metrics.activeConnections / this.metrics.totalConnections) *\n NUMERIX.HUNDERD\n : 0;\n\n const responseTime = Date.now() - startTime;\n\n return success({\n isHealthy: true,\n responseTime,\n details: {\n ...this.metrics,\n utilizationRate,\n },\n });\n } catch (error) {\n const responseTime = Date.now() - startTime;\n logger.error(`Pool health check failed: ${(error as Error).message}`);\n\n return success({\n isHealthy: false,\n responseTime,\n details: {\n ...this.metrics,\n error: (error as Error).message,\n },\n });\n } finally {\n if (client) {\n client.release();\n }\n }\n }\n\n /**\n * Gets current pool metrics.\n * @returns Pool performance metrics\n *\n * @example\n * ```typescript\n * const metrics = pool.getMetrics();\n * console.log(`Total connections: ${metrics.totalConnections}`);\n * console.log(`Active connections: ${metrics.activeConnections}`);\n * console.log(`Idle connections: ${metrics.idleConnections}`);\n * console.log(`Average acquisition time: ${metrics.averageAcquisitionTime}ms`);\n *\n * // Calculate utilization rate\n * const utilizationRate = metrics.totalConnections > 0\n * ? (metrics.activeConnections / metrics.totalConnections) * 100\n * : 0;\n * console.log(`Utilization rate: ${utilizationRate.toFixed(1)}%`);\n * ```\n */\n getMetrics(): PoolMetrics {\n return { ...this.metrics };\n }\n\n /**\n * Closes all connections in the pool.\n *\n * @example\n * ```typescript\n * // Graceful shutdown\n * async function shutdown() {\n * console.log('Closing database connections...');\n * await pool.end();\n * console.log('Database connections closed');\n * }\n *\n * // Handle process signals\n * process.on('SIGTERM', shutdown);\n * process.on('SIGINT', shutdown);\n * ```\n */\n async end(): Promise<void> {\n try {\n if (this.scalingTimer) {\n clearInterval(this.scalingTimer);\n this.scalingTimer = undefined;\n }\n await this.pool.end();\n } catch (error) {\n logger.error(`Error closing pool: ${(error as Error).message}`);\n throw new DatabaseError(\n \"Failed to close connection pool\",\n DATABASE_ERROR_CODES.DISCONNECT_FAILED,\n {\n context: {\n source: \"DynamicPool.end\",\n cause: error,\n },\n },\n );\n }\n }\n}\n","import { NUMERIX } from \"@plyaz/config\";\nimport { logger } from \"@plyaz/logger\";\nimport type { PoolMetrics, QueryMetrics } from \"@plyaz/types\";\nimport { EventEmitter } from \"events\";\nimport { DB_REGEX } from \"@utils/regex\";\n\n/**\n * Collects and analyzes database performance metrics.\n * Provides insights into query performance, pool usage, and potential issues.\n *\n * @example\n * ```typescript\n * const collector = new MetricsCollector();\n *\n * // Record a query metric\n * collector.recordQuery({\n * query: 'SELECT * FROM users WHERE id = $1',\n * duration: 45,\n * timestamp: new Date(),\n * success: true,\n * table: 'users',\n * operation: 'findById'\n * });\n *\n * // Get top slow queries\n * const slowQueries = collector.getTopSlowQueries(10);\n *\n * // Detect N+1 queries\n * const nPlusOneQueries = collector.detectNPlusOneQueries();\n *\n * // Get query frequency\n * const frequency = collector.getQueryFrequency();\n * ```\n */\nexport class MetricsCollector extends EventEmitter {\n private queryMetrics: QueryMetrics[] = [];\n private poolMetrics: PoolMetrics[] = [];\n private alerts: string[] = [];\n private readonly logger = logger;\n\n private readonly SLOW_QUERY_THRESHOLD = 1000; // 1 second\n private readonly POOL_EXHAUSTION_THRESHOLD = 90; // 90%\n private readonly REPLICA_LAG_THRESHOLD = 5000; // 5 seconds\n private readonly DISK_SPACE_THRESHOLD = 20; // 20%\n\n /**\n * Records query execution metrics.\n * @param metrics Query execution metrics\n */\n recordQuery(metrics: QueryMetrics): void {\n this.queryMetrics.push(metrics);\n\n // Keep only last 1000 metrics\n if (this.queryMetrics.length > NUMERIX.THOUSAND) {\n this.queryMetrics = this.queryMetrics.slice(-NUMERIX.THOUSAND);\n }\n\n // Check for slow queries\n if (metrics.duration > this.SLOW_QUERY_THRESHOLD) {\n this.emitAlert(\n `Slow query detected: ${metrics.query} took ${metrics.duration}ms`,\n );\n }\n\n this.emit(\"queryRecorded\", metrics);\n }\n\n /**\n * Records connection pool metrics.\n * @param metrics Pool performance metrics\n */\n recordPoolMetrics(metrics: PoolMetrics): void {\n this.poolMetrics.push({\n ...metrics,\n timestamp: new Date(),\n } as PoolMetrics & { timestamp: Date });\n\n // Keep only last 100 metrics\n if (this.poolMetrics.length > NUMERIX.HUNDERD) {\n this.poolMetrics = this.poolMetrics.slice(-NUMERIX.HUNDERD);\n }\n\n // Check for pool exhaustion\n const utilizationRate =\n metrics.totalConnections > 0\n ? (metrics.activeConnections / metrics.totalConnections) *\n NUMERIX.HUNDERD\n : 0;\n\n if (utilizationRate > this.POOL_EXHAUSTION_THRESHOLD) {\n this.emitAlert(\n `Pool exhaustion detected: ${utilizationRate.toFixed(1)}% utilization`,\n );\n }\n\n this.emit(\"poolMetricsRecorded\", metrics);\n }\n\n /**\n * Gets the top slow queries.\n * @param limit Number of queries to return\n * @returns Array of slowest queries\n */\n getTopSlowQueries(limit: number = 10): QueryMetrics[] {\n return [...this.queryMetrics]\n .filter((m) => m.duration > this.SLOW_QUERY_THRESHOLD)\n .sort((a, b) => b.duration - a.duration)\n .slice(0, limit);\n }\n\n /**\n * Gets query frequency statistics.\n * @returns Object mapping normalized queries to frequency counts\n */\n getQueryFrequency(): Record<string, number> {\n const frequency: Record<string, number> = {};\n\n this.queryMetrics.forEach((metrics) => {\n const normalizedQuery = this.normalizeQuery(metrics.query);\n frequency[normalizedQuery] = (frequency[normalizedQuery] || 0) + 1;\n });\n\n return frequency;\n }\n\n /**\n * Detects potential N+1 query patterns.\n * @returns Array of suspicious queries with their execution counts\n */\n detectNPlusOneQueries(): { query: string; count: number }[] {\n const frequency = this.getQueryFrequency();\n const suspiciousQueries: { query: string; count: number }[] = [];\n\n Object.entries(frequency).forEach(([query, count]) => {\n if (count > NUMERIX.TEN && query.includes(\"WHERE id =\")) {\n suspiciousQueries.push({ query, count });\n }\n });\n\n return suspiciousQueries.sort((a, b) => b.count - a.count);\n }\n\n /**\n * Normalizes a query for frequency analysis.\n * @param query Original SQL query\n * @returns Normalized query string\n */\n private normalizeQuery(query: string): string {\n // Remove specific values to normalize similar queries\n return DB_REGEX.normalizeSqlQuery(query);\n }\n\n /**\n * Emits an alert event.\n * @param message Alert message\n */\n private emitAlert(message: string): void {\n this.alerts.push(message);\n\n this.emit(\"alert\", {\n message,\n timestamp: new Date(),\n severity: \"warning\",\n });\n }\n}\n","import { EventEmitter } from \"events\";\nimport { logger } from \"@plyaz/logger\";\nimport { NUMERIX } from \"@plyaz/config\";\nimport type { Alert, AlertRule, PoolMetrics, QueryMetrics } from \"@plyaz/types\";\nimport { ALERT_RULE_ID, ALERT_SEVERITY, ALERT_SOURCE } from \"@plyaz/types\";\n\n/**\n * Manages database alerts with configurable rules and automatic resolution.\n * Provides real-time alerting for various database issues.\n *\n * @example\n * ```typescript\n * const alertManager = new AlertManager();\n *\n * // Add custom alert rule\n * alertManager.addRule({\n * id: 'high-error-rate',\n * condition: (metrics) => (metrics.errorRate as number) > 5,\n * message: (metrics) => `High error rate: ${metrics.errorRate}%`,\n * severity: 'error',\n * source: 'database'\n * });\n *\n * // Evaluate metrics against rules\n * const metrics = { errorRate: 7.2, poolUtilization: 85 };\n * alertManager.evaluate(metrics);\n *\n * // Get active alerts\n * const activeAlerts = alertManager.getActiveAlerts();\n *\n * // Resolve an alert\n * alertManager.resolveAlert('alert-id');\n * ```\n */\nexport class AlertManager extends EventEmitter {\n private alerts: Map<string, Alert> = new Map();\n private alertRules: AlertRule[] = [];\n private readonly logger = logger;\n\n constructor() {\n super();\n this.setupDefaultRules();\n }\n\n /**\n * Sets up default alert rules for common database issues.\n */\n private setupDefaultRules(): void {\n // Pool exhaustion alert\n this.addRule({\n id: ALERT_RULE_ID.POOL_EXHAUSTION,\n condition: (metrics) => {\n const poolMetrics = metrics.pool as PoolMetrics | undefined;\n if (!poolMetrics) return false;\n\n const utilizationRate =\n poolMetrics.totalConnections > 0\n ? (poolMetrics.activeConnections / poolMetrics.totalConnections) *\n NUMERIX.HUNDERD\n : 0;\n return utilizationRate > NUMERIX.NINETY;\n },\n message: (metrics) => {\n const poolMetrics = metrics.pool as PoolMetrics;\n const utilizationRate =\n poolMetrics.totalConnections > 0\n ? (poolMetrics.activeConnections / poolMetrics.totalConnections) *\n NUMERIX.HUNDERD\n : 0;\n return `Pool exhaustion: ${utilizationRate.toFixed(1)}% utilization`;\n },\n severity: ALERT_SEVERITY.CRITICAL,\n source: ALERT_SOURCE.POOL,\n });\n\n // Slow query alert - Fixed to always return boolean\n this.addRule({\n id: ALERT_RULE_ID.SLOW_QUERY,\n condition: (metrics) => {\n const queryMetrics = metrics.query as QueryMetrics | undefined;\n // Fixed: Explicitly return boolean instead of boolean | undefined\n return (\n queryMetrics !== undefined && queryMetrics.duration > NUMERIX.THOUSAND\n );\n },\n message: (metrics) => {\n const queryMetrics = metrics.query as QueryMetrics;\n return `Slow query: ${queryMetrics.query} took ${queryMetrics.duration}ms`;\n },\n severity: ALERT_SEVERITY.WARNING,\n source: ALERT_SOURCE.DATABASE,\n });\n\n // Replica lag alert - Fixed to always return boolean\n this.addRule({\n id: ALERT_RULE_ID.REPLICA_LAG,\n condition: (metrics) => {\n const replicaMetrics = metrics.replica as { lag: number } | undefined;\n // Fixed: Explicitly return boolean instead of boolean | undefined\n return (\n replicaMetrics !== undefined &&\n replicaMetrics.lag > NUMERIX.FIVE_THOUSAND\n );\n },\n message: (metrics) => {\n const replicaMetrics = metrics.replica as { lag: number };\n return `Replica lag: ${replicaMetrics.lag}ms`;\n },\n severity: ALERT_SEVERITY.WARNING,\n source: ALERT_SOURCE.REPLICA,\n });\n }\n\n /**\n * Adds a custom alert rule.\n * @param rule Alert rule definition\n */\n addRule(rule: AlertRule): void {\n this.alertRules.push(rule);\n }\n\n /**\n * Evaluates metrics against all alert rules.\n * @param metrics Database and pool metrics\n */\n evaluate(metrics: Record<string, object>): void {\n this.alertRules.forEach((rule) => {\n if (rule.condition(metrics)) {\n this.triggerAlert(rule, metrics);\n }\n });\n }\n\n /**\n * Triggers an alert based on a rule.\n * @param rule Alert rule that was triggered\n * @param metrics Current metrics\n */\n private triggerAlert(rule: AlertRule, metrics: Record<string, object>): void {\n const alertId = `${rule.id}-${Date.now()}`;\n\n // Check if similar alert is already active\n const existingAlert = Array.from(this.alerts.values()).find(\n (alert) => !alert.resolved && alert.id.startsWith(rule.id),\n );\n\n if (existingAlert) {\n return; // Don't duplicate active alerts\n }\n\n const alert: Alert = {\n id: alertId,\n message: rule.message(metrics),\n severity: rule.severity,\n timestamp: new Date(),\n resolved: false,\n source: rule.source,\n };\n\n this.alerts.set(alertId, alert);\n this.emit(\"alert\", alert);\n\n // Database alert handled - using DatabaseError for proper error handling\n }\n\n /**\n * Marks an alert as resolved.\n * @param alertId ID of the alert to resolve\n */\n resolveAlert(alertId: string): void {\n const alert = this.alerts.get(alertId);\n if (alert && !alert.resolved) {\n alert.resolved = true;\n alert.resolvedAt = new Date();\n this.emit(\"alertResolved\", alert);\n }\n }\n\n /**\n * Gets all currently active (unresolved) alerts.\n * @returns Array of active alerts\n */\n getActiveAlerts(): Alert[] {\n return Array.from(this.alerts.values()).filter((alert) => !alert.resolved);\n }\n\n /**\n * Gets all alerts (both active and resolved).\n * @returns Array of all alerts\n */\n getAllAlerts(): Alert[] {\n return Array.from(this.alerts.values());\n }\n}\n","import { exec } from \"child_process\";\nimport { promisify } from \"util\";\nimport {\n readFileSync,\n existsSync,\n mkdirSync,\n readdirSync,\n unlinkSync,\n} from \"fs\";\nimport { join } from \"path\";\nimport { failure, success } from \"@utils/databaseResultHelpers\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport { logger } from \"@plyaz/logger\";\nimport type { BackupConfig, BackupInfo, DatabaseResult } from \"@plyaz/types/db\";\nimport { NUMERIX } from \"@plyaz/config\";\nimport { isString } from \"@utils/typeGuards\";\nimport { DB_REGEX } from \"@utils/regex\";\n\nconst execAsync = promisify(exec);\n\n/**\n * Manages database backups with compression, encryption, and cloud storage.\n * Provides automated scheduling and retention management.\n *\n * @example\n * ```typescript\n * const config = {\n * connectionString: 'postgres://user:pass@localhost:5432/db',\n * backupDir: './backups',\n * retentionDays: 30,\n * compression: true,\n * encryption: {\n * enabled: true,\n * key: 'encryption-key'\n * },\n * s3: {\n * enabled: true,\n * bucket: 'my-backup-bucket',\n * region: 'us-east-1',\n * accessKey: 'aws-access-key',\n * secretKey: 'aws-secret-key'\n * }\n * };\n *\n * const backupService = new BackupService(config);\n *\n * // Create a backup\n * const backup = await backupService.createBackup();\n * console.log(`Backup created: ${backup.value.filename}`);\n *\n * // List all backups\n * const backups = await backupService.listBackups();\n *\n * // Restore from backup\n * await backupService.restoreBackup(backup.value.id);\n *\n * // Clean up expired backups\n * await backupService.cleanupExpiredBackups();\n * ```\n */\nexport class BackupService {\n private config: BackupConfig;\n private backups: Map<string, BackupInfo> = new Map();\n\n /**\n * Creates a new BackupService instance.\n * @param config Backup configuration\n */\n constructor(config: BackupConfig) {\n this.config = config;\n logger.info(\n `Initializing BackupService - backupDir: ${config.backupDir}, retentionDays: ${config.retentionDays}`,\n );\n this.ensureBackupDir();\n this.loadExistingBackups();\n\n if (config.schedule) {\n this.scheduleBackups();\n }\n logger.info(\"BackupService initialized successfully\");\n }\n\n /**\n * Creates a new database backup.\n * @returns Information about the created backup\n */\n // I need to disable these ESLint rules because this function handles a complete\n // backup process (validation, creation, compression, encryption, upload) in sequence.\n // eslint-disable-next-line complexity, max-lines-per-function\n async createBackup(): Promise<DatabaseResult<BackupInfo>> {\n try {\n // Validate backup directory\n if (!this.isValidPath(this.config.backupDir)) {\n throw new DatabaseError(\n \"Invalid backup directory path\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n { context: { source: \"BackupService.createBackup\" } },\n );\n }\n\n const timestamp = DB_REGEX.createSafeTimestamp(new Date().toISOString());\n const filename = `backup-${timestamp}.sql`;\n const filepath = join(this.config.backupDir, filename);\n\n // Validate final filepath\n if (\n !this.isValidPath(filepath) ||\n !filepath.startsWith(this.config.backupDir)\n ) {\n throw new DatabaseError(\n \"Invalid backup file path\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n { context: { source: \"BackupService.createBackup\" } },\n );\n }\n\n logger.info(`Starting database backup - filename: ${filename}`);\n\n // Create backup using pg_dump with proper escaping\n const { stderr } = await execAsync(\n `pg_dump \"${this.escapeShellArg(this.config.connectionString)}\" > \"${this.escapeShellArg(filepath)}\"`,\n );\n\n if (stderr) {\n logger.error(`Backup creation failed - filename: ${filename}`);\n throw new DatabaseError(\n \"Database backup creation failed\",\n DATABASE_ERROR_CODES.CREATE_FAILED,\n { context: { source: \"BackupService.createBackup\", cause: stderr } },\n );\n }\n\n logger.info(\n `Database backup created successfully - filename: ${filename}`,\n );\n\n // Compress if enabled\n if (this.config.compression) {\n logger.info(\"Compressing backup file\");\n await this.compressFile(filepath);\n logger.info(\"Backup file compressed successfully\");\n }\n\n // Encrypt if enabled\n if (this.config.encryption?.enabled) {\n logger.info(\"Encrypting backup file\");\n await this.encryptFile(filepath);\n logger.info(\"Backup file encrypted successfully\");\n }\n\n let finalFilepath = filepath;\n if (this.config.compression) {\n finalFilepath = `${filepath}.gz`;\n }\n if (this.config.encryption?.enabled) {\n finalFilepath = `${finalFilepath}.enc`;\n }\n\n if (!existsSync(finalFilepath)) {\n throw new DatabaseError(\n \"Backup file was not created\",\n DATABASE_ERROR_CODES.CREATE_FAILED,\n { context: { source: \"BackupService.createBackup\" } },\n );\n }\n\n const backupInfo: BackupInfo = {\n id: this.generateBackupId(),\n filename: this.config.compression ? `${filename}.gz` : filename,\n size: this.getFileSize(finalFilepath),\n createdAt: new Date(),\n expiresAt: new Date(\n Date.now() +\n this.config.retentionDays *\n NUMERIX.TWENTY_FOUR *\n NUMERIX.SIXTY *\n NUMERIX.SIXTY *\n NUMERIX.THOUSAND,\n ),\n status: \"created\",\n location: \"local\",\n };\n\n this.backups.set(backupInfo.id, backupInfo);\n\n // Upload to S3 if enabled\n if (this.config.s3?.enabled) {\n logger.info(`Uploading backup to S3 - backupId: ${backupInfo.id}`);\n await this.uploadToS3(backupInfo);\n logger.info(\"Backup uploaded to S3 successfully\");\n }\n\n logger.info(\n `Backup process completed successfully - backupId: ${backupInfo.id}`,\n );\n return success(backupInfo);\n } catch (error) {\n logger.error(\n `Backup creation failed - error: ${(error as Error).message}`,\n );\n return failure(\n error instanceof DatabaseError\n ? error\n : new DatabaseError(\n \"Backup creation failed\",\n DATABASE_ERROR_CODES.CREATE_FAILED,\n {\n context: { source: \"BackupService.createBackup\", cause: error },\n },\n ),\n );\n }\n }\n\n /**\n * Restores database from a backup.\n * @param backupId ID of the backup to restore\n * @returns Operation result\n */\n // eslint-disable-next-line complexity\n async restoreBackup(backupId: string): Promise<DatabaseResult<null>> {\n try {\n if (!isString(backupId)) {\n return failure(\n new DatabaseError(\n \"Invalid backup ID\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n { context: { source: \"BackupService.restoreBackup\" } },\n ),\n );\n }\n\n logger.info(`Starting backup restore - backupId: ${backupId}`);\n const backup = this.backups.get(backupId);\n if (!backup) {\n logger.error(`Backup not found for restore - backupId: ${backupId}`);\n return failure(\n new DatabaseError(\n \"Backup not found\",\n DATABASE_ERROR_CODES.RECORD_NOT_FOUND,\n { context: { source: \"BackupService.restoreBackup\", backupId } },\n ),\n );\n }\n\n let filepath = join(this.config.backupDir, backup.filename);\n\n // Download from S3 if needed\n if (backup.location === \"s3\" && this.config.s3?.enabled) {\n try {\n filepath = await this.downloadFromS3(backup);\n } catch (error) {\n throw new DatabaseError(\n \"Failed to download backup from S3\",\n DATABASE_ERROR_CODES.FETCH_FAILED,\n {\n context: { source: \"BackupService.restoreBackup\", cause: error },\n },\n );\n }\n }\n\n // Validate file exists before processing\n if (!existsSync(filepath)) {\n throw new DatabaseError(\n \"Backup file not found\",\n DATABASE_ERROR_CODES.RECORD_NOT_FOUND,\n { context: { source: \"BackupService.restoreBackup\", filepath } },\n );\n }\n\n // Decrypt if needed\n if (this.config.encryption?.enabled) {\n await this.decryptFile(filepath);\n }\n\n // Decompress if needed\n if (this.config.compression) {\n await this.decompressFile(filepath);\n filepath = filepath.replace(\".gz\", \"\");\n }\n\n // Validate filepath before restore\n if (!this.isValidPath(filepath)) {\n throw new DatabaseError(\n \"Invalid file path for restore\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n { context: { source: \"BackupService.restoreBackup\", filepath } },\n );\n }\n\n // Restore using psql\n const { stderr } = await execAsync(\n `psql \"${this.escapeShellArg(this.config.connectionString)}\" < \"${this.escapeShellArg(filepath)}\"`,\n );\n\n if (stderr) {\n logger.error(`Database restore failed - backupId: ${backupId}`);\n throw new DatabaseError(\n \"Database restore failed\",\n DATABASE_ERROR_CODES.RESTORE_FAILED,\n { context: { source: \"BackupService.restoreBackup\", cause: stderr } },\n );\n }\n\n logger.info(\n `Database restore completed successfully - backupId: ${backupId}`,\n );\n return success();\n } catch (error) {\n logger.error(`Backup restore failed - backupId: ${backupId}`);\n return failure(\n error instanceof DatabaseError\n ? error\n : new DatabaseError(\n \"Backup restore failed\",\n DATABASE_ERROR_CODES.UPDATE_FAILED,\n {\n context: {\n source: \"BackupService.restoreBackup\",\n cause: error,\n },\n },\n ),\n );\n }\n }\n\n /**\n * Lists all available backups.\n * @returns Array of backup information\n */\n async listBackups(): Promise<DatabaseResult<BackupInfo[]>> {\n try {\n const backups = Array.from(this.backups.values());\n return success(\n backups.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime()),\n );\n } catch (error) {\n return failure(\n new DatabaseError(\n \"Failed to list backups\",\n DATABASE_ERROR_CODES.QUERY_FAILED,\n { context: { source: \"BackupService.listBackups\", cause: error } },\n ),\n );\n }\n }\n\n /**\n * Creates a scheduled backup.\n * @returns Information about the created backup\n */\n async scheduleBackup(): Promise<DatabaseResult<BackupInfo>> {\n return this.createBackup();\n }\n\n /**\n * Removes expired backups from storage.\n * @returns Operation result\n */\n async cleanupExpiredBackups(): Promise<DatabaseResult<null>> {\n try {\n const now = new Date();\n const expiredBackups = Array.from(this.backups.values()).filter(\n (backup) => backup.expiresAt < now,\n );\n\n logger.info(\n `Starting cleanup of expired backups - expiredCount: ${expiredBackups.length}`,\n );\n\n for (const backup of expiredBackups) {\n logger.info(\n `Deleting expired backup - backupId: ${backup.id}, filename: ${backup.filename}`,\n );\n await this.deleteBackup(backup.id);\n }\n\n logger.info(\n `Expired backups cleanup completed - deletedCount: ${expiredBackups.length}`,\n );\n return success();\n } catch (error) {\n logger.error(\"Backup cleanup failed\");\n return failure(\n new DatabaseError(\n \"Backup cleanup failed\",\n DATABASE_ERROR_CODES.DELETE_FAILED,\n {\n context: {\n source: \"BackupService.cleanupExpiredBackups\",\n cause: error,\n },\n },\n ),\n );\n }\n }\n\n /**\n * Deletes a specific backup.\n * @param backupId ID of the backup to delete\n */\n private async deleteBackup(backupId: string): Promise<void> {\n const backup = this.backups.get(backupId);\n if (!backup) return;\n\n const filepath = join(this.config.backupDir, backup.filename);\n\n // Delete local file\n if (existsSync(filepath)) {\n unlinkSync(filepath);\n }\n\n // Delete from S3 if needed\n if (backup.location === \"s3\" && this.config.s3?.enabled) {\n await this.deleteFromS3(backup);\n }\n\n this.backups.delete(backupId);\n }\n\n /**\n * Ensures backup directory exists.\n */\n private ensureBackupDir(): void {\n if (!existsSync(this.config.backupDir)) {\n logger.info(\n `Creating backup directory - backupDir: ${this.config.backupDir}`,\n );\n mkdirSync(this.config.backupDir, { recursive: true });\n logger.info(\"Backup directory created successfully\");\n }\n }\n\n /**\n * Loads existing backups from the backup directory.\n */\n private loadExistingBackups(): void {\n if (!existsSync(this.config.backupDir)) return;\n\n const files = readdirSync(this.config.backupDir);\n logger.info(\n `Loading existing backups - backupDir: ${this.config.backupDir}, fileCount: ${files.length}`,\n );\n\n files.forEach((file) => {\n const filepath = join(this.config.backupDir, file);\n const stats = readFileSync(filepath);\n\n const backup: BackupInfo = {\n id: this.generateBackupId(),\n filename: file,\n size: stats.byteLength,\n createdAt: new Date(),\n expiresAt: new Date(\n Date.now() +\n this.config.retentionDays *\n NUMERIX.TWENTY_FOUR *\n NUMERIX.SIXTY *\n NUMERIX.SIXTY *\n NUMERIX.THOUSAND,\n ),\n status: \"created\",\n location: \"local\",\n };\n\n this.backups.set(backup.id, backup);\n });\n\n logger.info(\n `Existing backups loaded successfully -loadedCount ${this.backups.size}`,\n );\n }\n\n /**\n * Generates a unique backup ID.\n * @returns Unique backup identifier\n */\n private generateBackupId(): string {\n return `backup-${Date.now()}-${Math.random()\n .toString(NUMERIX.THIRTY_SIX)\n .substring(NUMERIX.TWO, NUMERIX.NINE + NUMERIX.TWO)}`;\n }\n\n /**\n * Gets file size in bytes.\n * @param filepath Path to the file\n * @returns File size in bytes\n */\n private getFileSize(filepath: string): number {\n return readFileSync(filepath).byteLength;\n }\n\n /**\n * Compresses a file using gzip.\n * @param filepath Path to the file to compress\n */\n private async compressFile(filepath: string): Promise<void> {\n if (!this.isValidPath(filepath)) {\n throw new DatabaseError(\n \"Invalid file path for compression\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n { context: { source: \"BackupService.compressFile\", filepath } },\n );\n }\n await execAsync(`gzip \"${this.escapeShellArg(filepath)}\"`);\n }\n\n /**\n * Decompresses a gzipped file.\n * @param filepath Path to the gzipped file\n */\n private async decompressFile(filepath: string): Promise<void> {\n if (!this.isValidPath(filepath)) {\n throw new DatabaseError(\n \"Invalid file path for decompression\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n { context: { source: \"BackupService.decompressFile\", filepath } },\n );\n }\n await execAsync(`gunzip \"${this.escapeShellArg(filepath)}\"`);\n }\n\n /**\n * Encrypts a file using OpenSSL.\n * @param filepath Path to the file to encrypt\n */\n private async encryptFile(filepath: string): Promise<void> {\n if (!this.config.encryption?.enabled) return;\n\n if (!this.isValidPath(filepath)) {\n throw new DatabaseError(\n \"Invalid file path for encryption\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n { context: { source: \"BackupService.encryptFile\", filepath } },\n );\n }\n\n const outputPath = `${filepath}.enc`;\n await execAsync(\n `openssl enc -aes-256-cbc -salt -in \"${this.escapeShellArg(filepath)}\" -out \"${this.escapeShellArg(outputPath)}\" -pass pass:\"${this.escapeShellArg(this.config.encryption.key)}\"`,\n );\n unlinkSync(filepath);\n }\n\n /**\n * Decrypts a file using OpenSSL.\n * @param filepath Path to the encrypted file\n */\n private async decryptFile(filepath: string): Promise<void> {\n // TODO: Implement proper encryption/decryption with error handling\n // Current implementation uses OpenSSL command line tool\n if (!this.config.encryption?.enabled) return;\n\n try {\n // Decrypt the file using AES-256-CBC\n const outputPath = filepath.replace(\".enc\", \"\");\n if (!this.isValidPath(filepath) || !this.isValidPath(outputPath)) {\n throw new DatabaseError(\n \"Invalid file path for decryption\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n { context: { source: \"BackupService.decryptFile\", filepath } },\n );\n }\n\n await execAsync(\n `openssl enc -aes-256-cbc -d -in \"${this.escapeShellArg(filepath)}\" -out \"${this.escapeShellArg(outputPath)}\" -pass pass:\"${this.escapeShellArg(this.config.encryption.key)}\"`,\n );\n\n // Remove the encrypted file after successful decryption\n if (existsSync(filepath)) {\n unlinkSync(filepath);\n }\n } catch (error) {\n throw new DatabaseError(\n \"Failed to decrypt file\",\n DATABASE_ERROR_CODES.DECRYPTION_FAILED,\n {\n context: {\n source: \"BackupService.decryptFile\",\n filepath,\n cause: error,\n },\n },\n );\n }\n }\n\n /**\n * Uploads a backup to S3.\n * @param backup Backup information\n */\n private async uploadToS3(backup: BackupInfo): Promise<void> {\n if (!this.config.s3?.enabled) return;\n\n try {\n if (!backup?.filename) {\n throw new DatabaseError(\n \"Invalid backup information\",\n DATABASE_ERROR_CODES.INVALID_BACKUP_INFO,\n { context: { source: \"BackupService.uploadToS3\" } },\n );\n }\n\n backup.status = \"uploading\";\n\n // Validate backup file exists before upload\n const localPath = join(this.config.backupDir, backup.filename);\n if (!existsSync(localPath)) {\n throw new DatabaseError(\n \"Backup file not found for upload\",\n DATABASE_ERROR_CODES.BACKUP_FILE_NOT_FOUND,\n { context: { source: \"BackupService.uploadToS3\", localPath } },\n );\n }\n\n // Placeholder: Mark as uploaded\n backup.status = \"uploaded\";\n backup.location = \"s3\";\n } catch (error) {\n backup.status = \"failed\";\n throw new DatabaseError(\n \"Failed to upload backup to S3\",\n DATABASE_ERROR_CODES.S3_UPLOAD_FAILED,\n { context: { source: \"BackupService.uploadToS3\", cause: error } },\n );\n }\n }\n\n /**\n * Downloads a backup from S3.\n * @param backup Backup information\n * @returns Local path to downloaded file\n */\n private async downloadFromS3(backup: BackupInfo): Promise<string> {\n // TODO: Implement AWS S3 download using AWS SDK v3\n // Current implementation is a placeholder for development\n if (!this.config.s3?.enabled) {\n throw new DatabaseError(\n \"S3 is not configured\",\n DATABASE_ERROR_CODES.S3_NOT_CONFIGURED,\n { context: { source: \"BackupService.downloadFromS3\" } },\n );\n }\n\n try {\n const localPath = join(this.config.backupDir, backup.filename);\n\n // In real implementation:\n // 1. Initialize S3 client with credentials\n // 2. Download file from S3 bucket\n // 3. Save to local filesystem\n // 4. Verify file integrity\n\n // Placeholder: Return expected local path\n return localPath;\n } catch (error) {\n throw new DatabaseError(\n \"Failed to download backup from S3\",\n DATABASE_ERROR_CODES.S3_DOWNLOAD_FAILED,\n {\n context: {\n source: \"BackupService.downloadFromS3\",\n filename: backup.filename,\n cause: error,\n },\n },\n );\n }\n }\n\n /**\n * Deletes a backup from S3.\n * @param backup Backup information\n */\n private async deleteFromS3(backup: BackupInfo): Promise<void> {\n // TODO: Implement AWS S3 delete using AWS SDK v3\n // Current implementation is a placeholder for development\n if (!this.config.s3?.enabled) return;\n\n try {\n // In real implementation:\n // 1. Initialize S3 client with credentials\n // 2. Delete object from S3 bucket using backup key\n // 3. Handle deletion errors and retries\n // Placeholder: Log deletion action\n // In production, this would actually delete from S3\n } catch (error) {\n throw new DatabaseError(\n \"Failed to delete backup from S3\",\n DATABASE_ERROR_CODES.S3_DELETE_FAILED,\n {\n context: {\n source: \"BackupService.deleteFromS3\",\n filename: backup.filename,\n cause: error,\n },\n },\n );\n }\n }\n\n /**\n * Sets up scheduled backups using cron.\n */\n private scheduleBackups(): void {\n // TODO: Implement cron-based scheduling using node-cron\n // Current implementation is a placeholder for development\n if (!this.config.schedule) return;\n\n try {\n // In real implementation:\n // 1. Install and import node-cron package\n // 2. Parse cron expression from config.schedule\n // 3. Schedule recurring backup task\n // 4. Handle cron job errors and logging\n // Example implementation would be:\n // const cron = require('node-cron');\n // cron.schedule(this.config.schedule, async () => {\n // try {\n // await this.createBackup();\n // } catch (error) {\n // // Handle scheduled backup errors\n // }\n // });\n // Placeholder: Log scheduling setup\n } catch {\n throw new DatabaseError(\n \"Failed to setup backup schedule\",\n DATABASE_ERROR_CODES.SCHEDULE_SETUP_FAILED,\n { context: { source: \"BackupService.scheduleBackups\" } },\n );\n }\n }\n\n /**\n * Validates file paths to prevent path traversal attacks.\n * @param filepath Path to validate\n * @returns True if path is valid and safe\n */\n private isValidPath(filepath: string): boolean {\n // Check for null, undefined, or empty paths\n if (!isString(filepath)) {\n return false;\n }\n\n // Check for path traversal patterns\n const dangerousPatterns = [\n \"../\",\n \"..\\\\\", // Directory traversal\n \"~/\", // Home directory access\n \"/etc/\",\n \"/proc/\",\n \"/sys/\", // System directories\n \"C:\\\\Windows\\\\\",\n \"C:\\\\Program Files\\\\\", // Windows system directories\n ];\n\n const normalizedPath = filepath.toLowerCase();\n return !dangerousPatterns.some((pattern) =>\n normalizedPath.includes(pattern.toLowerCase()),\n );\n }\n\n /**\n * Escapes shell arguments to prevent command injection.\n * @param arg Argument to escape\n * @returns Escaped argument safe for shell execution\n */\n private escapeShellArg(arg: string): string {\n if (!isString(arg)) {\n throw new DatabaseError(\n \"Invalid shell argument\",\n DATABASE_ERROR_CODES.INVALID_SHELL_ARG,\n { context: { source: \"BackupService.escapeShellArg\" } },\n );\n }\n\n // Remove or escape dangerous characters\n return DB_REGEX.sanitizeCommand(arg);\n }\n\n /**\n * Sanitizes strings for safe logging to prevent log injection.\n * @param input String to sanitize\n * @returns Sanitized string safe for logging\n */\n private sanitizeForLog(input: string): string {\n if (!isString(input)) {\n return \"[invalid_input]\";\n }\n\n const MAX_LOG_LENGTH = 200;\n return DB_REGEX.sanitizeLogMessage(input).substring(0, MAX_LOG_LENGTH);\n }\n}\n","import { AsyncLocalStorage } from \"async_hooks\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport type { TenantInfo } from \"@plyaz/types\";\n\n/**\n * Manages tenant context throughout the application using AsyncLocalStorage.\n * Provides a way to isolate tenant-specific data and operations.\n *\n * @example\n * ```typescript\n * const tenant: TenantInfo = {\n * id: 'tenant-123',\n * name: 'Acme Corp',\n * schema: 'acme_corp'\n * };\n *\n * // Run code within tenant context\n * const result = await TenantContext.run(tenant, async () => {\n * // This code has access to the tenant context\n * const currentTenant = TenantContext.current();\n * console.log(`Running as tenant: ${currentTenant?.name}`);\n *\n * // Perform tenant-specific operations\n * return await userService.getUsers();\n * });\n *\n * // Access current tenant from anywhere\n * const current = TenantContext.current();\n * if (current) {\n * console.log(`Current tenant: ${current.name}`);\n * }\n * ```\n */\nexport class TenantContext {\n private static storage = new AsyncLocalStorage<TenantInfo>();\n\n /**\n * Runs a function within a specific tenant context.\n * @param tenant Tenant information\n * @param callback Function to execute within tenant context\n * @returns Result of the callback function\n */\n static run<T>(tenant: TenantInfo, callback: () => Promise<T>): Promise<T> {\n return this.storage.run(tenant, callback);\n }\n\n /**\n * Gets the current tenant context.\n * @returns Current tenant information or undefined if no context is set\n */\n static current(): TenantInfo | undefined {\n return this.storage.getStore();\n }\n\n /**\n * Gets the current tenant context or throws an error if none is set.\n * @returns Current tenant information\n * @throws Error if no tenant context is available\n */\n static requireCurrent(): TenantInfo {\n const tenant = this.current();\n if (!tenant) {\n throw new DatabaseError(\n \"No tenant context available\",\n DATABASE_ERROR_CODES.NO_TENANT_CONTEXT,\n {\n context: {\n source: \"TenantContext.requireCurrent\",\n },\n },\n );\n }\n return tenant;\n }\n}\n","import { TenantContext } from \"./TenantContext\";\nimport { failure } from \"@utils/databaseResultHelpers\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport type {\n DatabaseAdapterType,\n DatabaseResult,\n PaginatedResult,\n QueryOptions,\n TenantValidationContext,\n} from \"@plyaz/types/db\";\n\n/**\n * TENANT REPOSITORY - Multi-Tenant Database Operations\n *\n * Base repository that automatically handles tenant isolation for all database operations.\n * Ensures data security by automatically filtering records by tenant ID and validating access.\n *\n * **RESPONSIBILITIES:**\n * 1. Tenant Isolation - Automatically filters all queries by current tenant\n * 2. Access Control - Validates tenant access for all operations\n * 3. Auto-Assignment - Automatically assigns tenant ID on record creation\n * 4. Validation - Ensures all operations respect tenant boundaries\n *\n * **USAGE PATTERN:**\n * Extend this class for each entity that requires tenant isolation.\n *\n * @template TEntity - The entity type that includes a tenant ID field\n *\n * @example\n * ### Basic Implementation\n * ```typescript\n * interface User {\n * id: string;\n * name: string;\n * email: string;\n * tenantId: string; // Required for tenant isolation\n * }\n *\n * class UserRepository extends TenantRepository<User> {\n * constructor(adapter: DatabaseAdapterType) {\n * super(adapter, 'users');\n * }\n *\n * protected getTenantIdField(): keyof User {\n * return 'tenantId';\n * }\n *\n * // Custom methods with automatic tenant isolation\n * async findByEmail(email: string) {\n * return this.findMany({ filter: { field: 'email', operator: 'eq', value: email } });\n * }\n * }\n * ```\n *\n * @example\n * ### Usage with Tenant Context\n * ```typescript\n * // Set tenant context (usually in middleware)\n * TenantContext.set({ id: 'tenant-123', name: 'Acme Corp' });\n *\n * const userRepo = new UserRepository(adapter);\n *\n * // All operations automatically filtered by tenant\n * const users = await userRepo.findMany(); // Only returns users for tenant-123\n * const user = await userRepo.findById('user-456'); // Validates tenant access\n *\n * // New records automatically get tenant ID\n * const newUser = await userRepo.create({\n * name: 'John Doe',\n * email: 'john@example.com'\n * // tenantId automatically set to 'tenant-123'\n * });\n * ```\n */\n\nexport abstract class TenantRepository<\n TEntity extends Record<string, unknown>,\n> {\n /**\n * Creates a new tenant repository instance.\n *\n * @param adapter - Database adapter for operations\n * @param tableName - Name of the database table\n */\n constructor(\n protected adapter: DatabaseAdapterType,\n protected tableName: string,\n ) {}\n\n /**\n * ABSTRACT METHOD - Tenant ID Field Specification\n *\n * Must be implemented by subclasses to specify which field contains the tenant ID.\n * This field is used for automatic filtering and validation.\n *\n * @returns The key of the tenant ID field in the entity\n *\n * @example\n * ```typescript\n * protected getTenantIdField(): keyof User {\n * return 'tenantId'; // or 'organizationId', 'companyId', etc.\n * }\n * ```\n */\n protected abstract getTenantIdField(): keyof TEntity;\n\n /**\n * FIND BY ID - Tenant-Safe Record Retrieval\n *\n * Finds a single record by ID with automatic tenant access validation.\n * Only returns records that belong to the current tenant.\n *\n * **SECURITY:** Validates that the found record belongs to the current tenant\n * **BEHAVIOR:** Returns null if record doesn't exist or belongs to different tenant\n *\n * @param id - The unique identifier of the record to find\n * @returns Promise resolving to the record or null if not found/no access\n *\n * @throws {DatabaseError} When ID is invalid or access is denied\n *\n * @example\n * ```typescript\n * // Set tenant context\n * TenantContext.set({ id: 'tenant-123' });\n *\n * const userRepo = new UserRepository(adapter);\n *\n * // Find user - only returns if belongs to tenant-123\n * const result = await userRepo.findById('user-456');\n * if (result.success && result.value) {\n * console.log('User found:', result.value.name);\n * } else {\n * console.log('User not found or access denied');\n * }\n * ```\n */\n async findById(id: string): Promise<DatabaseResult<TEntity | null>> {\n try {\n if (!id || typeof id !== \"string\") {\n return failure(\n new DatabaseError(\n \"Invalid record ID\",\n DATABASE_ERROR_CODES.INVALID_ID,\n { context: { source: \"TenantRepository.findById\" } },\n ),\n );\n }\n\n const result = await this.adapter.findById<TEntity>(this.tableName, id);\n\n if (result.success && result.value) {\n try {\n this.validateTenantAccess(result.value);\n } catch (error) {\n return failure(\n new DatabaseError(\n \"Access denied to record from different tenant\",\n DATABASE_ERROR_CODES.ACCESS_DENIED,\n {\n context: { source: \"TenantRepository.findById\", cause: error },\n },\n ),\n );\n }\n }\n\n return result;\n } catch (error) {\n return failure(\n new DatabaseError(\n \"Failed to find record\",\n DATABASE_ERROR_CODES.FIND_BY_ID_FAILED,\n { context: { source: \"TenantRepository.findById\", cause: error } },\n ),\n );\n }\n }\n\n /**\n * FIND MANY - Tenant-Filtered Query\n *\n * Finds multiple records with automatic tenant filtering applied.\n * All results are guaranteed to belong to the current tenant.\n *\n * **SECURITY:** Automatically adds tenant filter to all queries\n * **PERFORMANCE:** Uses database-level filtering for efficiency\n *\n * @param options - Optional query options (filters, sorting, pagination)\n * @returns Promise resolving to paginated results for current tenant only\n *\n * @example\n * ```typescript\n * // Set tenant context\n * TenantContext.set({ id: 'tenant-123' });\n *\n * const userRepo = new UserRepository(adapter);\n *\n * // Get all users for current tenant\n * const allUsers = await userRepo.findMany();\n *\n * // Get active users with pagination\n * const activeUsers = await userRepo.findMany({\n * filter: { field: 'status', operator: 'eq', value: 'active' },\n * pagination: { page: 1, limit: 10 },\n * sort: { field: 'name', direction: 'asc' }\n * });\n *\n * // Results automatically filtered by tenantId = 'tenant-123'\n * ```\n */\n async findMany(\n options?: QueryOptions,\n ): Promise<DatabaseResult<PaginatedResult<TEntity>>> {\n const tenant = TenantContext.requireCurrent();\n\n const tenantFilter = {\n field: this.getTenantIdField() as keyof TEntity & string,\n operator: \"eq\" as const,\n value: tenant.id as TEntity[keyof TEntity],\n };\n\n const enhancedOptions: QueryOptions<TEntity> = {\n ...options,\n filter: tenantFilter,\n };\n\n return this.adapter.findMany<TEntity>(this.tableName, enhancedOptions);\n }\n\n /**\n * CREATE - Tenant-Safe Record Creation\n *\n * Creates a new record with automatic tenant ID assignment.\n * The tenant ID is automatically set from the current tenant context.\n *\n * **SECURITY:** Automatically assigns current tenant ID to new records\n * **CONVENIENCE:** No need to manually set tenant ID in application code\n *\n * @param entity - The entity data to create (tenant ID will be auto-assigned)\n * @returns Promise resolving to the created record with tenant ID\n *\n * @example\n * ```typescript\n * // Set tenant context\n * TenantContext.set({ id: 'tenant-123' });\n *\n * const userRepo = new UserRepository(adapter);\n *\n * // Create user - tenantId automatically set to 'tenant-123'\n * const result = await userRepo.create({\n * name: 'John Doe',\n * email: 'john@example.com',\n * status: 'active'\n * // No need to set tenantId - automatically assigned\n * });\n *\n * if (result.success) {\n * console.log('Created user:', result.value.id);\n * console.log('Tenant ID:', result.value.tenantId); // 'tenant-123'\n * }\n * ```\n */\n async create(entity: Omit<TEntity, \"id\">): Promise<DatabaseResult<TEntity>> {\n const tenant = TenantContext.requireCurrent();\n const tenantEntity = {\n ...entity,\n [this.getTenantIdField()]: tenant.id,\n } as TEntity;\n\n return this.adapter.create<TEntity>(this.tableName, tenantEntity);\n }\n\n /**\n * UPDATE - Tenant-Safe Record Update\n *\n * Updates an existing record with tenant access validation.\n * Only allows updates to records that belong to the current tenant.\n *\n * **SECURITY:** Validates tenant access before allowing updates\n * **SAFETY:** Prevents cross-tenant data modification\n *\n * @param id - The unique identifier of the record to update\n * @param entity - Partial entity data with fields to update\n * @returns Promise resolving to the updated record\n *\n * @throws {DatabaseError} When record not found, access denied, or invalid parameters\n *\n * @example\n * ```typescript\n * // Set tenant context\n * TenantContext.set({ id: 'tenant-123' });\n *\n * const userRepo = new UserRepository(adapter);\n *\n * // Update user - only works if user belongs to tenant-123\n * const result = await userRepo.update('user-456', {\n * name: 'Jane Doe',\n * email: 'jane@example.com'\n * });\n *\n * if (result.success) {\n * console.log('Updated user:', result.value.name);\n * } else {\n * console.log('Update failed:', result.error?.message);\n * }\n * ```\n */\n async update(\n id: string,\n entity: Partial<TEntity>,\n ): Promise<DatabaseResult<TEntity>> {\n try {\n if (!id || !entity || typeof entity !== \"object\") {\n return failure(\n new DatabaseError(\n \"Invalid parameters\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n { context: { source: \"TenantRepository.update\" } },\n ),\n );\n }\n\n const existing = await this.findById(id);\n if (!existing.success) {\n return failure(\n existing.error ??\n new DatabaseError(\n \"Failed to fetch record\",\n DATABASE_ERROR_CODES.FETCH_FAILED,\n { context: { source: \"TenantRepository.update\" } },\n ),\n );\n }\n if (!existing.value) {\n return failure(\n new DatabaseError(\n \"Record not found\",\n DATABASE_ERROR_CODES.RECORD_NOT_FOUND,\n {\n context: {\n source: \"TenantRepository.update\",\n },\n },\n ),\n );\n }\n\n return this.adapter.update<TEntity>(this.tableName, id, entity);\n } catch (error) {\n return failure(\n new DatabaseError(\n \"Failed to update record\",\n DATABASE_ERROR_CODES.UPDATE_FAILED,\n {\n context: {\n source: \"TenantRepository.update\",\n cause: error,\n },\n },\n ),\n );\n }\n }\n\n /**\n * DELETE - Tenant-Safe Record Deletion\n *\n * Deletes a record with tenant access validation.\n * Only allows deletion of records that belong to the current tenant.\n *\n * **SECURITY:** Validates tenant access before allowing deletion\n * **SAFETY:** Prevents cross-tenant data deletion\n *\n * @param id - The unique identifier of the record to delete\n * @returns Promise resolving to void on successful deletion\n *\n * @throws {DatabaseError} When record not found, access denied, or invalid ID\n *\n * @example\n * ```typescript\n * // Set tenant context\n * TenantContext.set({ id: 'tenant-123' });\n *\n * const userRepo = new UserRepository(adapter);\n *\n * // Delete user - only works if user belongs to tenant-123\n * const result = await userRepo.delete('user-456');\n *\n * if (result.success) {\n * console.log('User deleted successfully');\n * } else {\n * console.log('Delete failed:', result.error?.message);\n * }\n * ```\n */\n async delete(id: string): Promise<DatabaseResult<void>> {\n try {\n if (!id || typeof id !== \"string\") {\n return failure(\n new DatabaseError(\n \"Invalid record ID\",\n DATABASE_ERROR_CODES.INVALID_ID,\n {\n context: {\n source: \"TenantRepository.delete\",\n },\n },\n ),\n );\n }\n\n const existing = await this.findById(id);\n if (!existing.success) {\n return failure(\n existing.error ??\n new DatabaseError(\n \"Failed to fetch record\",\n DATABASE_ERROR_CODES.FETCH_FAILED,\n {\n context: {\n source: \"TenantRepository.delete\",\n },\n },\n ),\n );\n }\n if (!existing.value) {\n return failure(\n new DatabaseError(\n \"Record not found\",\n DATABASE_ERROR_CODES.RECORD_NOT_FOUND,\n {\n context: {\n source: \"TenantRepository.delete\",\n },\n },\n ),\n );\n }\n\n return this.adapter.delete(this.tableName, id);\n } catch (error) {\n return failure(\n new DatabaseError(\n \"Failed to delete record\",\n DATABASE_ERROR_CODES.DELETE_FAILED,\n {\n context: {\n source: \"TenantRepository.delete\",\n cause: error,\n },\n },\n ),\n );\n }\n }\n\n /**\n * Validates that the entity is a valid object.\n * @private\n * @param entity - The entity to validate\n * @throws {DatabaseError} When entity is invalid\n */\n private validateEntity(entity: TEntity): void {\n if (!entity || typeof entity !== \"object\") {\n throw new DatabaseError(\n \"Invalid entity\",\n DATABASE_ERROR_CODES.INVALID_ENTITY,\n {\n context: {\n source: \"TenantRepository.validateEntity\",\n },\n },\n );\n }\n }\n\n /**\n * Validates that tenant context exists and has an ID.\n * @private\n * @param tenant - The tenant context to validate\n * @throws {DatabaseError} When tenant context is invalid\n */\n\n private validateTenantContext(tenant: TenantValidationContext): void {\n if (!tenant?.id) {\n throw new DatabaseError(\n \"No tenant context available\",\n DATABASE_ERROR_CODES.NO_TENANT_CONTEXT,\n {\n context: {\n source: \"TenantRepository.validateTenantContext\",\n },\n },\n );\n }\n }\n\n /**\n * Validates that the entity has a tenant ID.\n * @private\n * @param tenantId - The tenant ID from the entity\n * @throws {DatabaseError} When tenant ID is missing\n */\n private validateEntityTenantId(tenantId: TEntity[keyof TEntity]): void {\n if (!tenantId) {\n throw new DatabaseError(\n \"Entity has no tenant ID\",\n DATABASE_ERROR_CODES.NO_TENANT_ID,\n {\n context: {\n source: \"TenantRepository.validateEntityTenantId\",\n },\n },\n );\n }\n }\n\n /**\n * Validates that the current tenant has access to the entity.\n * @private\n * @param entity - The entity to validate access for\n * @throws {DatabaseError} When access is denied\n */\n private validateTenantAccess(entity: TEntity): void {\n try {\n this.validateEntity(entity);\n\n const tenant = TenantContext.requireCurrent();\n this.validateTenantContext(tenant);\n\n const tenantId = entity[this.getTenantIdField()];\n this.validateEntityTenantId(tenantId);\n\n if (tenantId !== tenant.id) {\n throw new DatabaseError(\n \"Access denied to entity from different tenant\",\n DATABASE_ERROR_CODES.ACCESS_DENIED,\n {\n context: {\n source: \"TenantRepository.validateTenantAccess\",\n },\n },\n );\n }\n } catch (error) {\n throw new DatabaseError(\n \"Tenant validation failed\",\n DATABASE_ERROR_CODES.TENANT_VALIDATION_FAILED,\n {\n context: {\n source: \"TenantRepository.validateTenantAccess\",\n cause: error,\n },\n },\n );\n }\n }\n}\n","import { NUMERIX } from \"@plyaz/config\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport type { ShardKey } from \"@plyaz/types\";\n\n/**\n * Manages shard key definitions and calculations.\n * Provides utilities for determining which shard a record belongs to.\n *\n * @example\n * ```typescript\n * const shardKeyManager = new ShardKeyManager();\n *\n * // Register a shard key for users table\n * shardKeyManager.registerShardKey('users', {\n * name: 'user_shard',\n * type: 'hash',\n * columns: ['id'],\n * strategy: 'hash',\n * shardCount: 4\n * });\n *\n * // Calculate which shard a user belongs to\n * const shardId = shardKeyManager.calculateShard('users', { id: 'user-123' });\n * console.log(`User belongs to shard ${shardId}`);\n * ```\n */\nexport class ShardKeyManager {\n private shardKeys: Map<string, ShardKey> = new Map();\n\n /**\n * Registers a shard key for a table.\n * @param table Table name\n * @param shardKey Shard key configuration\n */\n registerShardKey(table: string, shardKey: ShardKey): void {\n this.shardKeys.set(table, shardKey);\n }\n\n /**\n * Gets the shard key configuration for a table.\n * @param table Table name\n * @returns Shard key configuration or undefined\n */\n getShardKey(table: string): ShardKey | undefined {\n return this.shardKeys.get(table);\n }\n\n /**\n * Calculates which shard a record belongs to.\n * @param table Table name\n * @param data Record data\n * @returns Shard ID (0-based)\n */\n calculateShard<T extends Record<string, string | number>>(\n table: string,\n data: T,\n ): number {\n const shardKey = this.getShardKey(table);\n if (!shardKey) {\n throw new DatabaseError(\n `No shard key defined for table: ${table}`,\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"calculateShard\" },\n cause: new Error(`No shard key defined for table: ${table}`),\n },\n );\n }\n\n const keyValue = this.extractKeyValue(data, shardKey);\n\n switch (shardKey.strategy) {\n case \"modulus\":\n return this.modulusShard(keyValue, shardKey.shardCount);\n case \"hash\":\n return this.hashShard(keyValue, shardKey.shardCount);\n case \"range\":\n return this.rangeShard(keyValue, shardKey);\n default:\n throw new DatabaseError(\n `Unknown sharding strategy: ${shardKey.strategy}`,\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"calculateShard\" },\n cause: new Error(`Unknown sharding strategy: ${shardKey.strategy}`),\n },\n );\n }\n }\n\n /**\n * Extracts the shard key value from record data.\n * @param data Record data\n * @param shardKey Shard key configuration\n * @returns Extracted key value\n */\n private extractKeyValue<T extends Record<string, string | number>>(\n data: T,\n shardKey: ShardKey,\n ): string | number {\n if (shardKey.columns.length === 1) {\n return data[shardKey.columns[0]];\n }\n\n return shardKey.columns.map((col) => data[col]).join(\"|\");\n }\n\n /**\n * Calculates shard ID using modulus strategy.\n * @param keyValue Key value\n * @param shardCount Number of shards\n * @returns Shard ID\n */\n private modulusShard(keyValue: string | number, shardCount: number): number {\n const numericKey =\n typeof keyValue === \"string\"\n ? this.hashString(keyValue)\n : Number(keyValue);\n\n return numericKey % shardCount;\n }\n\n /**\n * Calculates shard ID using hash strategy.\n * @param keyValue Key value\n * @param shardCount Number of shards\n * @returns Shard ID\n */\n private hashShard(keyValue: string | number, shardCount: number): number {\n const hash =\n typeof keyValue === \"string\"\n ? this.hashString(keyValue)\n : Number(keyValue);\n\n return Math.abs(hash) % shardCount;\n }\n\n /**\n * Calculates shard ID using range strategy.\n * @param keyValue Key value\n * @param shardKey Shard key configuration\n * @returns Shard ID\n */\n private rangeShard(keyValue: string | number, shardKey: ShardKey): number {\n // Implementation would depend on range configuration\n // This is a simplified version\n const numericKey =\n typeof keyValue === \"string\"\n ? this.hashString(keyValue)\n : Number(keyValue);\n\n return Math.floor(\n numericKey / (Number.MAX_SAFE_INTEGER / shardKey.shardCount),\n );\n }\n\n /**\n * Hashes a string to a numeric value.\n * @param str String to hash\n * @returns Hash value\n */\n private hashString(str: string): number {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n hash = (hash << NUMERIX.FIVE) - hash + char;\n hash = hash & hash; // Convert to 32-bit integer\n }\n return hash;\n }\n}\n","import { ShardKeyManager } from \"./ShardKey\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport type { ShardConfig, ShardKey } from \"@plyaz/types\";\n\n/**\n * Routes database operations to the appropriate shard based on shard keys.\n * Provides shard-aware routing and management capabilities.\n *\n * @example\n * ```typescript\n * const shardConfigs: ShardConfig[] = [\n * { id: 0, connectionString: 'postgres://shard0:5432/db', isPrimary: false },\n * { id: 1, connectionString: 'postgres://shard1:5432/db', isPrimary: false },\n * { id: 2, connectionString: 'postgres://shard2:5432/db', isPrimary: true }\n * ];\n *\n * const router = new ShardRouter(shardConfigs);\n *\n * // Route a record to the appropriate shard\n * const userData = { id: 'user-456', name: 'Jane' };\n * const shard = router.routeToShard('users', userData);\n * console.log(`User should be stored on shard ${shard.id}`);\n *\n * // Get a specific shard\n * const shard2 = router.getShardById(2);\n *\n * // Get all shards\n * const allShards = router.getAllShards();\n * ```\n */\nexport class ShardRouter {\n private shards: Map<number, ShardConfig> = new Map();\n private shardKeyManager: ShardKeyManager;\n\n /**\n * Creates a new ShardRouter instance.\n * @param shardConfigs Array of shard configurations\n */\n constructor(shardConfigs: ShardConfig[]) {\n this.shardKeyManager = new ShardKeyManager();\n\n shardConfigs.forEach((config) => {\n this.shards.set(config.id, config);\n });\n }\n\n /**\n * Determines which shard a record should be routed to.\n * @param table Table name\n * @param data Record data\n * @returns Shard configuration\n */\n routeToShard(\n table: string,\n data: Record<string, string | number | boolean | Date>,\n ): ShardConfig {\n const filteredData: Record<string, string | number> = {};\n for (const [key, value] of Object.entries(data)) {\n if (typeof value === \"string\" || typeof value === \"number\") {\n filteredData[key] = value;\n }\n }\n const shardId = this.shardKeyManager.calculateShard(table, filteredData);\n const shard = this.shards.get(shardId);\n\n if (!shard) {\n throw new DatabaseError(\n `Shard not found: ${shardId}`,\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"routeToShard\" },\n cause: new Error(`Shard not found: ${shardId}`),\n },\n );\n }\n\n return shard;\n }\n\n /**\n * Gets a shard configuration by ID.\n * @param shardId Shard ID\n * @returns Shard configuration or undefined\n */\n getShardById(shardId: number): ShardConfig | undefined {\n return this.shards.get(shardId);\n }\n\n /**\n * Gets all shard configurations.\n * @returns Array of all shard configurations\n */\n getAllShards(): ShardConfig[] {\n return Array.from(this.shards.values());\n }\n\n /**\n * Gets the primary shard configuration.\n * @returns Primary shard configuration or undefined\n */\n getPrimaryShard(): ShardConfig | undefined {\n return Array.from(this.shards.values()).find((shard) => shard.isPrimary);\n }\n\n /**\n * Registers a shard key for a table.\n * @param table Table name\n * @param shardKey Shard key configuration\n */\n registerShardKey(table: string, shardKey: ShardKey): void {\n this.shardKeyManager.registerShardKey(table, shardKey);\n }\n}\n","import { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport type { PaginationOptions, SortOptions, Filter } from \"@plyaz/types/db\";\nimport { DB_REGEX } from \"@utils/regex\";\n\n/**\n * SQL query builder utilities\n *\n * Provides safe, parameterized SQL query generation.\n * Works independently of any specific ORM or query engine.\n */\n\n/**\n * Builds a WHERE clause from filters\n * @param filters - Array of filter conditions\n * @returns WHERE clause string\n */\nexport function buildWhereClause<T extends object = object>(\n filters?: Filter[],\n): string {\n if (!filters || filters.length === 0) {\n return \"\";\n }\n\n try {\n const conditions: string[] = [];\n let paramIndex = 1;\n\n for (const filter of filters) {\n if (!filter.field || !filter.operator) {\n throw new DatabaseError(\n \"Invalid filter: field and operator are required\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"buildWhereClause\" },\n cause: new Error(\"Invalid filter: field and operator are required\"),\n },\n );\n }\n\n const condition = buildCondition<T>(filter, paramIndex);\n conditions.push(condition.clause);\n paramIndex = condition.paramCount;\n }\n\n const whereClause = conditions\n .map((cond, idx) => {\n if (idx === 0) return cond;\n const logical = (filters[idx]?.logical ?? \"and\").toUpperCase();\n if (![\"AND\", \"OR\"].includes(logical)) {\n throw new DatabaseError(\n `Invalid logical operator: ${logical}`,\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"buildWhereClause\" },\n cause: new Error(`Invalid logical operator: ${logical}`),\n },\n );\n }\n return `${logical} ${cond}`;\n })\n .join(\" \");\n\n return \" WHERE \" + whereClause;\n } catch (error) {\n throw new DatabaseError(\n `Failed to build WHERE clause: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n {\n context: { source: \"buildWhereClause\" },\n cause: error as Error,\n },\n );\n }\n}\n\n/**\n * Builds a single condition for a WHERE clause\n * @param filter - Filter condition\n * @param startIndex - Starting parameter index\n * @returns Object containing the condition clause and updated parameter count\n */\nfunction buildCondition<T>(\n filter: Filter,\n startIndex: number,\n): { clause: string; paramCount: number } {\n const { field, operator, value } = filter;\n let paramCount = startIndex;\n\n // Validate field name to prevent SQL injection\n if (!DB_REGEX.isValidFieldName(field)) {\n throw new DatabaseError(\n `Invalid field name: ${field}`,\n DATABASE_ERROR_CODES.INIT_FAILED,\n );\n }\n\n const operatorsMap: Record<string, () => string> = {\n eq: () => `\"${field}\" = $${paramCount++}`,\n ne: () => `\"${field}\" != $${paramCount++}`,\n gt: () => `\"${field}\" > $${paramCount++}`,\n gte: () => `\"${field}\" >= $${paramCount++}`,\n lt: () => `\"${field}\" < $${paramCount++}`,\n lte: () => `\"${field}\" <= $${paramCount++}`,\n in: () => {\n if (!Array.isArray(value)) {\n throw new DatabaseError(\n \"IN operator requires array value\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"buildCondition\" },\n cause: new Error(\"IN operator requires array value\"),\n },\n );\n }\n return `\"${field}\" IN (${(value as T[]).map(() => `$${paramCount++}`).join(\", \")})`;\n },\n notIn: () => {\n if (!Array.isArray(value)) {\n throw new DatabaseError(\n \"NOT IN operator requires array value\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"buildCondition\" },\n cause: new Error(\"NOT IN operator requires array value\"),\n },\n );\n }\n return `\"${field}\" NOT IN (${(value as T[]).map(() => `$${paramCount++}`).join(\", \")})`;\n },\n like: () => `\"${field}\" LIKE $${paramCount++}`,\n between: () => {\n const BETWEEN_ARRAY_LENGTH = 2;\n if (\n !Array.isArray(value) ||\n (value as unknown[]).length !== BETWEEN_ARRAY_LENGTH\n ) {\n throw new DatabaseError(\n \"BETWEEN operator requires array with exactly 2 values\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"buildCondition\" },\n cause: new Error(\n \"BETWEEN operator requires array with exactly 2 values\",\n ),\n },\n );\n }\n return `\"${field}\" BETWEEN $${paramCount++} AND $${paramCount++}`;\n },\n isNull: () => `\"${field}\" IS NULL`,\n isNotNull: () => `\"${field}\" IS NOT NULL`,\n };\n\n const clauseFn = operatorsMap[operator];\n if (!clauseFn) {\n throw new DatabaseError(\n `Unsupported operator: ${operator}`,\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"buildCondition\" },\n cause: new Error(`Unsupported operator: ${operator}`),\n },\n );\n }\n\n try {\n return { clause: clauseFn(), paramCount };\n } catch (error) {\n throw new DatabaseError(\n `Failed to build condition for field ${field}: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n DATABASE_ERROR_CODES.INIT_FAILED,\n );\n }\n}\n\n/**\n * Builds an ORDER BY clause from sort options\n * @param sortOptions - Array of sort options\n * @returns ORDER BY clause string\n */\nexport function buildOrderClause(sortOptions?: SortOptions[]): string {\n if (!sortOptions || sortOptions.length === 0) return \"\";\n\n try {\n const clauses = sortOptions.map((option) => {\n // Validate field name to prevent SQL injection\n if (!DB_REGEX.isValidFieldName(option.field)) {\n throw new DatabaseError(\n `Invalid field name: ${option.field}`,\n DATABASE_ERROR_CODES.INIT_FAILED,\n );\n }\n\n const direction = option.direction.toUpperCase();\n if (![\"ASC\", \"DESC\"].includes(direction)) {\n throw new DatabaseError(\n `Invalid sort direction: ${direction}`,\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"buildOrderClause\" },\n cause: new Error(`Invalid sort direction: ${direction}`),\n },\n );\n }\n\n return `\"${option.field}\" ${direction}`;\n });\n\n return \" ORDER BY \" + clauses.join(\", \");\n } catch (error) {\n throw new DatabaseError(\n `Failed to build ORDER BY clause: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n {\n context: { source: \"buildOrderClause\" },\n cause: error as Error,\n },\n );\n }\n}\n\n/**\n * Builds LIMIT and OFFSET clauses from pagination options\n * @param pagination - Pagination options\n * @returns Object containing the clause string and parameters\n */\nexport function buildPaginationClause<T>(pagination?: PaginationOptions): {\n clause: string;\n params: T[];\n} {\n if (!pagination) return { clause: \"\", params: [] };\n\n const params: T[] = [];\n let clause = \"\";\n\n const { limit, offset } = pagination;\n\n if (limit !== undefined) {\n clause += ` LIMIT $${params.length + 1}`;\n params.push(limit as T);\n }\n\n if (offset !== undefined) {\n clause += ` OFFSET $${params.length + 1}`;\n params.push(offset as T);\n }\n\n return { clause, params };\n}\n","/**\n * ORM Query builder utilities\n *\n * This module provides utilities for building ORM-specific queries.\n * Currently a placeholder for future ORM implementations.\n */\n\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\n\n/**\n * Builds a WHERE clause for ORM queries\n * @throws Error - Not implemented yet\n */\nexport function buildWhereClauseORM(): Error {\n throw new DatabaseError(\n \"Not implemented yet\",\n DATABASE_ERROR_CODES.UNKNOWN_ERROR,\n {\n context: { source: \"buildWhereClauseORM\" },\n cause: new Error(\"Not implemented yet\"),\n },\n );\n}\n\n/**\n * Builds an ORDER BY clause for ORM queries\n * @throws Error - Not implemented yet\n */\nexport function buildOrderClauseORM(): Error {\n throw new DatabaseError(\n \"Not implemented yet\",\n DATABASE_ERROR_CODES.UNKNOWN_ERROR,\n {\n context: { source: \"buildOrderClauseORM\" },\n cause: new Error(\"Not implemented yet\"),\n },\n );\n}\n\n/**\n * Builds pagination clauses for ORM queries\n * @throws Error - Not implemented yet\n */\nexport function buildPaginationClauseORM(): Error {\n throw new DatabaseError(\n \"Not implemented yet\",\n DATABASE_ERROR_CODES.UNKNOWN_ERROR,\n {\n context: { source: \"buildPaginationClauseORM\" },\n cause: new Error(\"Not implemented yet\"),\n },\n );\n}\n","import { PipeTransform, Injectable } from \"@nestjs/common\";\nimport sanitizeHtml from \"sanitize-html\";\nimport { isString, isObject } from \"@utils/typeGuards\";\n\n/**\n * A NestJS pipe that recursively sanitizes input data to remove any potentially unsafe HTML.\n *\n * This pipe can handle strings, arrays, and objects. It ensures that\n * all string values within the provided data are sanitized using the `sanitize-html` library.\n *\n */\n@Injectable()\nexport class SanitizeHtmlPipe implements PipeTransform {\n /**\n * Transforms and sanitizes the provided value.\n * - Strings are sanitized using `sanitize-html`.\n * - Arrays and objects are recursively sanitized.\n * - Other primitive types (e.g., numbers, booleans) are returned as-is.\n *\n * @template T\n * @param {T} value - The value to sanitize.\n * @returns {string | Record<string, unknown> | unknown[]} - The sanitized value.\n */\n transform<T>(value: T): string | Record<string, unknown> | unknown[] {\n if (isString(value)) {\n return this.sanitizeString(value);\n }\n\n if (Array.isArray(value)) {\n return value.map((v) => this.transform(v));\n }\n\n if (isObject(value)) {\n const result: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value)) {\n result[key] = this.transform(val);\n }\n return result;\n }\n\n return value as unknown[];\n }\n\n /**\n * Sanitizes a single string by removing all HTML tags and attributes,\n * allowing only safe URL schemes like `http`, `https`, and `mailto`.\n *\n * @param {string} str - The string to sanitize.\n * @returns {string} - The sanitized string.\n * @private\n */\n private sanitizeString(str: string): string {\n return sanitizeHtml(str, {\n allowedTags: [],\n allowedAttributes: {},\n allowedSchemes: [\"http\", \"https\", \"mailto\"],\n });\n }\n}\n","import { BadRequestException, Injectable, PipeTransform } from \"@nestjs/common\";\nimport { ZodType } from \"zod\";\nimport { SanitizeHtmlPipe } from \"../sanitizers/html.sanitizer\";\n\n/**\n * A NestJS pipe that combines input sanitization and validation.\n *\n * This pipe first sanitizes incoming data using {@link SanitizeHtmlPipe}\n * to remove any potentially unsafe HTML, and then validates the sanitized\n * data using a provided Zod schema.\n *\n * If validation fails, a `BadRequestException` is thrown.\n */\n@Injectable()\nexport class DataValidationPipe implements PipeTransform {\n private readonly sanitizeHtmlPipe = new SanitizeHtmlPipe();\n\n /**\n * Creates a new DataValidationPipe instance with the provided Zod schema.\n *\n * @param {ZodType} schema - The Zod schema used to validate sanitized data.\n */\n constructor(private schema: ZodType) {}\n\n /**\n * Sanitizes and validates incoming data.\n * - First, all string values are sanitized to remove unsafe HTML.\n * - Then, the sanitized data is validated against the provided Zod schema.\n *\n * Throws a `BadRequestException` if validation fails.\n *\n * @param {unknown} value - The incoming value to sanitize and validate.\n * @returns {unknown} - The sanitized and validated data.\n * @throws {BadRequestException} - If validation fails.\n */\n transform(value: unknown): unknown {\n const sanitizedValue = this.sanitizeHtmlPipe.transform(value);\n\n try {\n return this.schema.parse(sanitizedValue);\n } catch (error) {\n if (error instanceof Error) {\n throw new BadRequestException(`Validation failed: ${error.message}`);\n }\n throw new BadRequestException(`Invalid request data.`);\n }\n }\n}\n","/**\n * MigrationManager - Database schema migrations with version control\n *\n * Manages database schema migrations with support for versioning,\n * rollback, and migration history tracking. Automatically discovers\n * migration files from a specified directory and applies them in order.\n *\n * @example\n * ```typescript\n * const migrationManager = new MigrationManager({\n * adapter: sqlAdapter,\n * migrationsPath: './migrations', // default\n * tableName: 'schema_migrations' // default\n * });\n *\n * // Run all pending migrations\n * await migrationManager.up();\n *\n * // Rollback last migration\n * await migrationManager.down();\n *\n * // Get migration status\n * const status = await migrationManager.status();\n * ```\n */\n\nimport type {\n DatabaseAdapterType,\n DatabaseResult,\n Migration,\n MigrationFile,\n MigrationRecord,\n MigrationManagerConfig,\n MigrationStatus,\n} from \"@plyaz/types/db\";\nimport { success, failure } from \"../utils/databaseResultHelpers\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\n\n/**\n * MigrationManager - Handles database schema migrations\n *\n * Discovers migration files, tracks migration history, and applies\n * migrations in order with support for rollback.\n */\nexport class MigrationManager {\n private adapter: DatabaseAdapterType;\n private migrationsPath: string;\n private tableName: string;\n private schema: string;\n\n constructor(config: MigrationManagerConfig) {\n this.adapter = config.adapter;\n this.migrationsPath = path.resolve(config.migrationsPath ?? \"./migrations\");\n this.schema = config.schema ?? \"public\";\n // Prefix table name with schema if not 'public'\n this.tableName =\n this.schema !== \"public\"\n ? `${this.schema}.${config.tableName ?? \"schema_migrations\"}`\n : (config.tableName ?? \"schema_migrations\");\n }\n\n /**\n * Initialize migrations table if it doesn't exist\n */\n async initialize(): Promise<DatabaseResult<void>> {\n try {\n // Create migrations tracking table with file_path for traceability\n const createTableSQL = `\n CREATE TABLE IF NOT EXISTS ${this.tableName} (\n version VARCHAR(255) PRIMARY KEY,\n name VARCHAR(255) NOT NULL,\n file_path VARCHAR(500),\n applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n execution_time INTEGER NOT NULL\n )\n `;\n\n // Execute using adapter's raw query if available\n if (typeof this.adapter.query === \"function\") {\n await this.adapter.query(createTableSQL);\n\n // Add file_path column if it doesn't exist (for existing tables)\n await this.adapter\n .query(\n `\n DO $$\n BEGIN\n IF NOT EXISTS (\n SELECT 1 FROM information_schema.columns\n WHERE table_name = '${this.tableName.split(\".\").pop()}'\n AND column_name = 'file_path'\n ) THEN\n ALTER TABLE ${this.tableName} ADD COLUMN file_path VARCHAR(500);\n END IF;\n END $$;\n `,\n )\n .catch(() => {\n // Ignore if column already exists or syntax not supported\n });\n }\n\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to initialize migrations table: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.INIT_FAILED,\n { cause: error as Error },\n ),\n );\n }\n }\n\n /**\n * Discover migration files from migrations directory (including subdirectories)\n */\n private async discoverMigrations(): Promise<MigrationFile[]> {\n if (!fs.existsSync(this.migrationsPath)) {\n return [];\n }\n\n const migrations: MigrationFile[] = [];\n\n const scanDirectory = (dir: string): void => {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n\n if (entry.isDirectory()) {\n // Recursively scan subdirectories\n scanDirectory(fullPath);\n } else if (entry.isFile()) {\n // Match migration file pattern: {version}_{name}.{ts|js|sql}\n // Examples: 001_initial_schema.sql, 20231124_add_users_table.ts\n const match = entry.name.match(/^(\\d+)_(.+)\\.(ts|js|sql)$/);\n if (match) {\n const [, version, name] = match;\n migrations.push({\n filePath: fullPath,\n version,\n name: name.replace(/_/g, \" \"),\n });\n }\n }\n }\n };\n\n scanDirectory(this.migrationsPath);\n\n // Sort by version\n return migrations.sort((a, b) => a.version.localeCompare(b.version));\n }\n\n /**\n * Parse SQL content to extract UP and DOWN sections\n */\n private parseSqlSections(sql: string): {\n upSQL: string;\n downSQL: string | null;\n } {\n const hasUpMarker = sql.includes(\"-- UP\");\n const hasDownMarker = sql.includes(\"-- DOWN\");\n\n if (hasUpMarker && hasDownMarker) {\n const parts = sql.split(\"-- DOWN\");\n return {\n upSQL: parts[0].replace(\"-- UP\", \"\").trim(),\n downSQL: parts[1].trim(),\n };\n }\n\n if (hasDownMarker) {\n const parts = sql.split(\"-- DOWN\");\n return {\n upSQL: parts[0].trim(),\n downSQL: parts[1].trim(),\n };\n }\n\n return { upSQL: sql.trim(), downSQL: null };\n }\n\n /**\n * Load SQL migration from file\n */\n private loadSqlMigration(migrationFile: MigrationFile): Migration {\n const sql = fs.readFileSync(migrationFile.filePath, \"utf-8\");\n const { upSQL, downSQL } = this.parseSqlSections(sql);\n\n return {\n version: migrationFile.version,\n name: migrationFile.name,\n up: async (adapter: DatabaseAdapterType) => {\n if (typeof adapter.query === \"function\") {\n await adapter.query(upSQL);\n }\n },\n down: async (adapter: DatabaseAdapterType) => {\n if (downSQL && typeof adapter.query === \"function\") {\n await adapter.query(downSQL);\n } else {\n console.warn(\n `[Migrations] No DOWN migration for ${migrationFile.version}`,\n );\n }\n },\n };\n }\n\n /**\n * Load TypeScript/JavaScript migration from file\n */\n private async loadJsMigration(\n migrationFile: MigrationFile,\n ): Promise<Migration> {\n const importPath = migrationFile.filePath.startsWith(\"/\")\n ? migrationFile.filePath\n : new URL(`file:///${migrationFile.filePath.replace(/\\\\/g, \"/\")}`).href;\n\n const migrationModule = await import(importPath);\n return {\n version: migrationFile.version,\n name: migrationFile.name,\n up: migrationModule.up ?? migrationModule.default?.up,\n down: migrationModule.down ?? migrationModule.default?.down,\n };\n }\n\n /**\n * Load migration from file\n */\n private async loadMigration(\n migrationFile: MigrationFile,\n ): Promise<Migration> {\n const ext = path.extname(migrationFile.filePath);\n\n switch (ext) {\n case \".sql\":\n return this.loadSqlMigration(migrationFile);\n case \".ts\":\n case \".js\":\n return this.loadJsMigration(migrationFile);\n default:\n throw new DatabaseError(\n `Unsupported migration file extension: ${ext}`,\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n { cause: new Error(`Unsupported extension: ${ext}`) },\n );\n }\n }\n\n /**\n * Get applied migrations from database\n */\n private async getAppliedMigrations(): Promise<MigrationRecord[]> {\n try {\n if (typeof this.adapter.query === \"function\") {\n const result = await this.adapter.query<MigrationRecord>(\n `SELECT * FROM ${this.tableName} ORDER BY version ASC`,\n );\n // Handle both array results and postgres-style { rows: [] } results\n return Array.isArray(result)\n ? result\n : (result as unknown as { rows: MigrationRecord[] }).rows || [];\n }\n return [];\n } catch {\n // Table might not exist yet\n return [];\n }\n }\n\n /**\n * Record migration as applied\n */\n private async recordMigration(\n version: string,\n name: string,\n executionTime: number,\n filePath?: string,\n ): Promise<void> {\n if (typeof this.adapter.query === \"function\") {\n // Store relative path from migrations directory for portability\n const relativePath = filePath\n ? path.relative(this.migrationsPath, filePath)\n : null;\n\n await this.adapter.query(\n `INSERT INTO ${this.tableName} (version, name, file_path, execution_time) VALUES ($1, $2, $3, $4)`,\n [version, name, relativePath, executionTime],\n );\n }\n }\n\n /**\n * Remove migration record (for rollback)\n */\n private async unrecordMigration(version: string): Promise<void> {\n if (typeof this.adapter.query === \"function\") {\n await this.adapter.query(\n `DELETE FROM ${this.tableName} WHERE version = $1`,\n [version],\n );\n }\n }\n\n /**\n * Get migration status (applied and pending)\n */\n async status(): Promise<DatabaseResult<MigrationStatus>> {\n try {\n await this.initialize();\n\n const allMigrations = await this.discoverMigrations();\n const appliedMigrations = await this.getAppliedMigrations();\n const appliedVersions = new Set(appliedMigrations.map((m) => m.version));\n\n const pending = allMigrations\n .filter((m) => !appliedVersions.has(m.version))\n .map((m) => `${m.version}_${m.name}`);\n\n return success({\n applied: appliedMigrations,\n pending,\n });\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to get migration status: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n { cause: error as Error },\n ),\n );\n }\n }\n\n /**\n * Run all pending migrations\n */\n async up(targetVersion?: string): Promise<DatabaseResult<number>> {\n try {\n await this.initialize();\n\n const allMigrations = await this.discoverMigrations();\n const appliedMigrations = await this.getAppliedMigrations();\n const appliedVersions = new Set(appliedMigrations.map((m) => m.version));\n\n let applied = 0;\n\n for (const migrationFile of allMigrations) {\n // Skip if already applied\n if (appliedVersions.has(migrationFile.version)) {\n continue;\n }\n\n // Stop if we've reached target version\n if (targetVersion && migrationFile.version > targetVersion) {\n break;\n }\n\n console.log(\n `[Migrations] Applying ${migrationFile.version}_${migrationFile.name}...`,\n );\n\n const migration = await this.loadMigration(migrationFile);\n const startTime = Date.now();\n\n // Run migration in transaction if possible\n if (typeof this.adapter.transaction === \"function\") {\n await this.adapter.transaction(async () => {\n await migration.up(this.adapter);\n });\n } else {\n await migration.up(this.adapter);\n }\n\n const executionTime = Date.now() - startTime;\n\n // Record migration with file path for traceability\n await this.recordMigration(\n migration.version,\n migration.name,\n executionTime,\n migrationFile.filePath,\n );\n\n console.log(\n `[Migrations] Applied ${migration.version} in ${executionTime}ms`,\n );\n applied++;\n }\n\n return success(applied);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Migration failed: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n { cause: error as Error },\n ),\n );\n }\n }\n\n /**\n * Rollback last migration or rollback to specific version\n */\n async down(steps: number = 1): Promise<DatabaseResult<number>> {\n try {\n const appliedMigrations = await this.getAppliedMigrations();\n\n if (appliedMigrations.length === 0) {\n return success(0);\n }\n\n // Get migrations to rollback (in reverse order)\n const toRollback = appliedMigrations.slice(-steps).reverse();\n let rolledBack = 0;\n\n for (const appliedMigration of toRollback) {\n console.log(\n `[Migrations] Rolling back ${appliedMigration.version}_${appliedMigration.name}...`,\n );\n\n // Find migration file\n const allMigrations = await this.discoverMigrations();\n const migrationFile = allMigrations.find(\n (m) => m.version === appliedMigration.version,\n );\n\n if (!migrationFile) {\n console.warn(\n `[Migrations] Migration file not found for version ${appliedMigration.version}`,\n );\n continue;\n }\n\n const migration = await this.loadMigration(migrationFile);\n const startTime = Date.now();\n\n // Run rollback in transaction if possible\n if (typeof this.adapter.transaction === \"function\") {\n await this.adapter.transaction(async () => {\n await migration.down(this.adapter);\n });\n } else {\n await migration.down(this.adapter);\n }\n\n const executionTime = Date.now() - startTime;\n\n // Remove migration record\n await this.unrecordMigration(appliedMigration.version);\n\n console.log(\n `[Migrations] Rolled back ${appliedMigration.version} in ${executionTime}ms`,\n );\n rolledBack++;\n }\n\n return success(rolledBack);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Rollback failed: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n { cause: error as Error },\n ),\n );\n }\n }\n\n /**\n * Reset database (rollback all migrations)\n */\n async reset(): Promise<DatabaseResult<number>> {\n const appliedMigrations = await this.getAppliedMigrations();\n return this.down(appliedMigrations.length);\n }\n\n /**\n * Clear migration history (delete all records from tracking table)\n *\n * Use this to force fresh migrations in test/development environments\n * without rolling back actual database changes.\n *\n * @example\n * ```typescript\n * // Clear history and re-run all migrations\n * await migrationManager.clearHistory();\n * await migrationManager.up();\n * ```\n */\n async clearHistory(): Promise<DatabaseResult<void>> {\n try {\n if (typeof this.adapter.query === \"function\") {\n await this.adapter.query(`DELETE FROM ${this.tableName}`);\n }\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to clear migration history: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n { cause: error as Error },\n ),\n );\n }\n }\n}\n","/**\n * SeedManager - Database seeding for development and testing\n *\n * Manages database seeding with support for ordered execution,\n * seed history tracking, and idempotent seed operations.\n * Automatically discovers seed files from a specified directory.\n *\n * @example\n * ```typescript\n * const seedManager = new SeedManager({\n * adapter: sqlAdapter,\n * seedsPath: './seeds', // default\n * tableName: 'seed_history' // default\n * });\n *\n * // Run all seeds\n * await seedManager.run();\n *\n * // Run specific seed\n * await seedManager.run('users');\n *\n * // Clear all data (for testing)\n * await seedManager.reset();\n * ```\n */\n\nimport type {\n DatabaseAdapterType,\n DatabaseResult,\n Seed,\n SeedFile,\n SeedRecord,\n SeedManagerConfig,\n} from \"@plyaz/types/db\";\nimport { success, failure } from \"../utils/databaseResultHelpers\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\n\n/**\n * SeedManager - Handles database seeding operations\n *\n * Discovers seed files, tracks seed history, and executes\n * seeds in order with support for cleanup and reset.\n */\nexport class SeedManager {\n private adapter: DatabaseAdapterType;\n private seedsPath: string;\n private tableName: string;\n private schema: string;\n private skipExisting: boolean;\n\n constructor(config: SeedManagerConfig) {\n this.adapter = config.adapter;\n this.seedsPath = path.resolve(config.seedsPath ?? \"./seeds\");\n this.schema = config.schema ?? \"public\";\n // Prefix table name with schema if not 'public'\n this.tableName =\n this.schema !== \"public\"\n ? `${this.schema}.${config.tableName ?? \"seed_history\"}`\n : (config.tableName ?? \"seed_history\");\n this.skipExisting = config.skipExisting ?? false;\n }\n\n /**\n * Initialize seeds tracking table if it doesn't exist\n */\n async initialize(): Promise<DatabaseResult<void>> {\n try {\n // Create seeds tracking table with file_path for traceability\n const createTableSQL = `\n CREATE TABLE IF NOT EXISTS ${this.tableName} (\n name VARCHAR(255) PRIMARY KEY,\n file_path VARCHAR(500),\n run_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n execution_time INTEGER NOT NULL\n )\n `;\n\n // Execute using adapter's raw query if available\n if (typeof this.adapter.query === \"function\") {\n await this.adapter.query(createTableSQL);\n\n // Add file_path column if it doesn't exist (for existing tables)\n await this.adapter\n .query(\n `\n DO $$\n BEGIN\n IF NOT EXISTS (\n SELECT 1 FROM information_schema.columns\n WHERE table_name = '${this.tableName.split(\".\").pop()}'\n AND column_name = 'file_path'\n ) THEN\n ALTER TABLE ${this.tableName} ADD COLUMN file_path VARCHAR(500);\n END IF;\n END $$;\n `,\n )\n .catch(() => {\n // Ignore if column already exists or syntax not supported\n });\n }\n\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to initialize seeds table: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.INIT_FAILED,\n { cause: error as Error },\n ),\n );\n }\n }\n\n /**\n * Discover seed files from seeds directory\n */\n private async discoverSeeds(): Promise<SeedFile[]> {\n if (!fs.existsSync(this.seedsPath)) {\n return [];\n }\n\n const files = fs.readdirSync(this.seedsPath);\n const seeds: SeedFile[] = [];\n\n for (const file of files) {\n // Match seed file pattern: {order}_{name}.{ts|js}\n // Examples: 001_users.ts, 002_campaigns.js\n const match = file.match(/^(\\d+)_(.+)\\.(ts|js)$/);\n if (match) {\n const [, order, name] = match;\n seeds.push({\n filePath: path.join(this.seedsPath, file),\n order: Number.parseInt(order, 10),\n name,\n });\n }\n }\n\n // Sort by order\n return seeds.sort((a, b) => a.order - b.order);\n }\n\n /**\n * Load seed from file\n */\n private async loadSeed(seedFile: SeedFile): Promise<Seed> {\n // Convert Windows paths to file:// URLs for ESM imports\n const importPath = seedFile.filePath.startsWith(\"/\")\n ? seedFile.filePath\n : new URL(`file:///${seedFile.filePath.replace(/\\\\/g, \"/\")}`).href;\n\n const seedModule = await import(importPath);\n return {\n name: seedFile.name,\n run:\n seedModule.run ??\n seedModule.default?.run ??\n seedModule.seed ??\n seedModule.default,\n cleanup: seedModule.cleanup ?? seedModule.default?.cleanup,\n };\n }\n\n /**\n * Get executed seeds from database\n */\n private async getExecutedSeeds(): Promise<SeedRecord[]> {\n try {\n if (typeof this.adapter.query === \"function\") {\n const result = await this.adapter.query<SeedRecord>(\n `SELECT * FROM ${this.tableName} ORDER BY run_at ASC`,\n );\n // Handle both array results and postgres-style { rows: [] } results\n return Array.isArray(result)\n ? result\n : (result as unknown as { rows: SeedRecord[] }).rows || [];\n }\n return [];\n } catch {\n // Table might not exist yet\n return [];\n }\n }\n\n /**\n * Record seed as executed\n */\n private async recordSeed(\n name: string,\n executionTime: number,\n filePath?: string,\n ): Promise<void> {\n if (typeof this.adapter.query === \"function\") {\n // Store relative path from seeds directory for portability\n const relativePath = filePath\n ? path.relative(this.seedsPath, filePath)\n : null;\n\n await this.adapter.query(\n `INSERT INTO ${this.tableName} (name, file_path, execution_time) VALUES ($1, $2, $3)\n ON CONFLICT (name) DO UPDATE SET run_at = CURRENT_TIMESTAMP, file_path = $2, execution_time = $3`,\n [name, relativePath, executionTime],\n );\n }\n }\n\n /**\n * Remove seed record (for reset)\n */\n private async unrecordSeed(name: string): Promise<void> {\n if (typeof this.adapter.query === \"function\") {\n await this.adapter.query(\n `DELETE FROM ${this.tableName} WHERE name = $1`,\n [name],\n );\n }\n }\n\n /**\n * Execute a seed function with optional transaction support\n */\n private async executeSeed(seed: Seed): Promise<void> {\n if (typeof this.adapter.transaction === \"function\") {\n await this.adapter.transaction(async () => {\n await seed.run(this.adapter);\n });\n } else {\n await seed.run(this.adapter);\n }\n }\n\n /**\n * Check if a seed should be skipped and log if applicable\n */\n private shouldSkipSeed(\n seedFile: SeedFile,\n seedName: string | undefined,\n executedNames: Set<string>,\n ): boolean {\n if (seedName && seedFile.name !== seedName) return true;\n\n if (this.skipExisting && executedNames.has(seedFile.name)) {\n console.log(`[Seeds] Skipping ${seedFile.name} (already executed)`);\n return true;\n }\n\n return false;\n }\n\n /**\n * Run all seeds or a specific seed\n */\n async run(seedName?: string): Promise<DatabaseResult<number>> {\n try {\n await this.initialize();\n\n const allSeeds = await this.discoverSeeds();\n const executedSeeds = await this.getExecutedSeeds();\n const executedNames = new Set(executedSeeds.map((s) => s.name));\n\n let executed = 0;\n\n for (const seedFile of allSeeds) {\n if (this.shouldSkipSeed(seedFile, seedName, executedNames)) {\n continue;\n }\n\n console.log(`[Seeds] Running ${seedFile.name}...`);\n\n const seed = await this.loadSeed(seedFile);\n const startTime = Date.now();\n\n await this.executeSeed(seed);\n\n const executionTime = Date.now() - startTime;\n await this.recordSeed(seed.name, executionTime, seedFile.filePath);\n\n console.log(`[Seeds] Executed ${seed.name} in ${executionTime}ms`);\n executed++;\n\n if (seedName) break;\n }\n\n return success(executed);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Seed execution failed: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n { cause: error as Error },\n ),\n );\n }\n }\n\n /**\n * Execute cleanup function with optional transaction support\n */\n private async executeCleanup(seed: Seed): Promise<void> {\n if (!seed.cleanup) return;\n\n if (typeof this.adapter.transaction === \"function\") {\n await this.adapter.transaction(async () => {\n await seed.cleanup!(this.adapter);\n });\n } else {\n await seed.cleanup(this.adapter);\n }\n }\n\n /**\n * Reset all seeds (run cleanup functions)\n */\n async reset(): Promise<DatabaseResult<number>> {\n try {\n const allSeeds = await this.discoverSeeds();\n let cleaned = 0;\n\n // Run cleanup in reverse order\n for (const seedFile of allSeeds.reverse()) {\n console.log(`[Seeds] Cleaning up ${seedFile.name}...`);\n\n const seed = await this.loadSeed(seedFile);\n\n if (!seed.cleanup) {\n console.warn(`[Seeds] No cleanup function for ${seed.name}`);\n continue;\n }\n\n const startTime = Date.now();\n await this.executeCleanup(seed);\n const executionTime = Date.now() - startTime;\n\n await this.unrecordSeed(seed.name);\n\n console.log(`[Seeds] Cleaned ${seed.name} in ${executionTime}ms`);\n cleaned++;\n }\n\n return success(cleaned);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Seed cleanup failed: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n { cause: error as Error },\n ),\n );\n }\n }\n\n /**\n * Get seed execution status\n */\n async status(): Promise<\n DatabaseResult<{ executed: SeedRecord[]; pending: string[] }>\n > {\n try {\n await this.initialize();\n\n const allSeeds = await this.discoverSeeds();\n const executedSeeds = await this.getExecutedSeeds();\n const executedNames = new Set(executedSeeds.map((s) => s.name));\n\n const pending = allSeeds\n .filter((s) => !executedNames.has(s.name))\n .map((s) => s.name);\n\n return success({\n executed: executedSeeds,\n pending,\n });\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to get seed status: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n { cause: error as Error },\n ),\n );\n }\n }\n\n /**\n * Clear seed history (doesn't clean data, just removes tracking records)\n */\n async clearHistory(): Promise<DatabaseResult<void>> {\n try {\n if (typeof this.adapter.query === \"function\") {\n await this.adapter.query(`DELETE FROM ${this.tableName}`);\n }\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to clear seed history: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n { cause: error as Error },\n ),\n );\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/utils/typeGuards.ts","../src/service/EventEmitter.ts","../src/utils/databaseResultHelpers.ts","../src/utils/normalizeDetails.ts","../src/service/HealthManager.ts","../src/utils/ConfigMerger.ts","../src/service/DatabaseService.ts","../src/utils/pagination.ts","../src/utils/regex.ts","../src/adapters/drizzle/DrizzleAdapter.ts","../src/adapters/supabase/SupabaseAdapter.ts","../src/adapters/sql/SQLAdapter.ts","../src/adapters/mock/MockAdapter.ts","../src/factory/AdapterFactory.ts","../src/extensions/SoftDeleteExtension.ts","../src/extensions/AuditExtension.ts","../src/extensions/EncryptionExtension.ts","../src/extensions/CachingAdapter.ts","../src/extensions/ReadReplicaAdapter.ts","../src/factory/createDatabaseService.ts","../src/repository/BaseRepository.ts","../src/extensions/MultiWriteExtension.ts","../src/extensions/MultiReadExtension.ts","../src/advanced/read-replica/UseReplica.decorator.ts","../src/advanced/caching/RedisCache.ts","../src/advanced/caching/Cacheable.decorator.ts","../src/advanced/caching/CacheEvict.decorator.ts","../src/advanced/connection-pool/DynamicPool.ts","../src/advanced/monitoring/MetricsCollector.ts","../src/advanced/monitoring/AlertManager.ts","../src/advanced/backup/BackupService.ts","../src/advanced/multi-tenancy/TenantContext.ts","../src/advanced/multi-tenancy/TenantRepository.ts","../src/advanced/sharding/ShardKey.ts","../src/advanced/sharding/ShardRouter.ts","../src/builder/query/sql.ts","../src/builder/query/orm.ts","../src/security/sanitizers/html.sanitizer.ts","../src/security/serializers/DataValidation.ts","../src/migrations/MigrationManager.ts","../src/seeds/SeedManager.ts"],"names":["DatabaseError","DATABASE_ERROR_CODES","logger","DATABASE_EVENT_TYPE","NUMERIX","ADAPTERS","Pool","drizzle","sql","eq","idColumn","result","not","gt","gte","lt","lte","inArray","like","between","isNull","isNotNull","PgColumn","asc","desc","createClient","resolve","EXTENSION_SOURCE","AUDIT_OPERATION","ENCRYPTION_DEFAULTS","randomBytes","createCipheriv","createDecipheriv","ADAPTER_TYPES","DatabasePackageError","ERROR_CODES","success","SetMetadata","config","Redis","dynamicPoolDefaultConfig","DB_POOL_EVENTS","EventEmitter","ALERT_RULE_ID","ALERT_SEVERITY","ALERT_SOURCE","alert","promisify","exec","join","existsSync","unlinkSync","mkdirSync","readdirSync","readFileSync","AsyncLocalStorage","SanitizeHtmlPipe","sanitizeHtml","Injectable","DataValidationPipe","BadRequestException","path","fs","DESCRIPTION_MAX_LENGTH","FALLBACK_DESCRIPTION_LENGTH","PROGRESS_LOG_INTERVAL","ERROR_MESSAGE_MAX_LENGTH","path2","fs2"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * @fileoverview Type Guard Utilities for @plyaz/db package\n *\n * This module provides type guard functions for runtime type checking throughout\n * the @plyaz/db package. These utilities replace direct typeof checks with\n * consistent, reusable type validation functions.\n *\n */\n\n/**\n * Type guard to check if a value is a string\n *\n * @param {unknown} value - The value to check\n * @returns {value is string} True if value is a string, false otherwise\n *\n * @example\n * ```typescript\n * import { isString } from '@plyaz/db/utils';\n *\n * if (isString(userInput)) {\n * // userInput is now typed as string\n * console.log(userInput.toLowerCase());\n * }\n * ```\n */\nexport function isString(value: unknown): value is string {\n return typeof value === \"string\";\n}\n\n/**\n * Type guard to check if a value is a non-empty string\n *\n * @param {unknown} value - The value to check\n * @returns {value is string} True if value is a non-empty string, false otherwise\n *\n * @example\n * ```typescript\n * import { isNonEmptyString } from '@plyaz/db/utils';\n *\n * if (isNonEmptyString(tableName)) {\n * // tableName is guaranteed to be a non-empty string\n * const query = `SELECT * FROM ${tableName}`;\n * }\n * ```\n */\nexport function isNonEmptyString(value: unknown): value is string {\n return isString(value) && value.length > 0;\n}\n\n/**\n * Type guard to check if a value is a number\n *\n * @param {unknown} value - The value to check\n * @returns {value is number} True if value is a number, false otherwise\n */\nexport function isNumber(value: unknown): value is number {\n return typeof value === \"number\";\n}\n\n/**\n * Type guard to check if a value is an object (not null, not array)\n *\n * @param {unknown} value - The value to check\n * @returns {value is object} True if value is an object, false otherwise\n */\nexport function isObject(value: unknown): value is object {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n","/**\n * @fileoverview DatabaseEventEmitter - Event management for database operations\n *\n * Provides a comprehensive event system for monitoring and reacting to database\n * operations. The DatabaseEventEmitter implements the Observer pattern to enable\n * decoupled monitoring of database activities, allowing multiple components to\n * subscribe to and react to various database events.\n *\n * **Application Flow Context:**\n * ```\n * Database Operations → DatabaseEventEmitter → Event Handlers\n * ↓ ↓ ↓\n * Query Execution → Event Emission → Logging\n * Transaction → Handler Dispatch → Monitoring\n * Health Changes → Error Handling → Alerting\n * ```\n *\n * **Supported Events:**\n * - **BeforeQuery**: Emitted before database queries\n * - **AfterQuery**: Emitted after successful queries\n * - **QueryError**: Emitted when queries fail\n * - **BeforeTransaction**: Emitted before transactions start\n * - **AfterTransaction**: Emitted after transactions complete\n * - **TransactionRollback**: Emitted when transactions rollback\n * - **HealthChange**: Emitted when database health status changes\n *\n * @example\n * ```typescript\n * // Event emitter setup\n * const eventEmitter = new DatabaseEventEmitter('drizzle');\n *\n * // Subscribe to query events\n * eventEmitter.on('BeforeQuery', (event) => {\n * console.log(`Executing ${event.operation} on ${event.table}`);\n * });\n *\n * eventEmitter.on('QueryError', (event) => {\n * console.error(`Query failed: ${event.error.message}`);\n * });\n *\n * // Emit events during database operations\n * eventEmitter.emitBeforeQuery('users', 'SELECT', { id: '123' });\n * ```\n *\n */\n\nimport type {\n AfterQueryEvent,\n AfterTransactionEvent,\n BeforeQueryEvent,\n BeforeTransactionEvent,\n DatabaseEvent,\n DatabaseOperationType,\n DBEventHandler,\n HealthChangeEvent,\n QueryErrorEvent,\n TransactionRollbackEvent,\n} from \"@plyaz/types\";\nimport type {\n EmitQueryErrorOptions,\n DatabaseExecutionContext,\n} from \"@plyaz/types/db\";\nimport { DATABASE_EVENT_TYPE } from \"@plyaz/types\";\nimport type { ADAPTERS } from \"@plyaz/types\";\nimport { logger } from \"@plyaz/logger\";\nimport { isString, isObject } from \"@utils/typeGuards\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\n\n/**\n * Event emitter for database events that implements the observer pattern.\n * This class manages event subscriptions and emissions for various database operations,\n * allowing decoupled monitoring of database activities.\n *\n * @class\n * @implements {DatabaseEventEmitter}\n */\nexport class DatabaseEventEmitter implements DatabaseEventEmitter {\n private readonly eventHandlers: Map<string, DBEventHandler<DatabaseEvent>[]> =\n new Map();\n\n constructor(private readonly adapter: ADAPTERS) {\n if (!adapter) {\n throw new DatabaseError(\n \"Database adapter is required for event emitter\",\n DATABASE_ERROR_CODES.CONFIG_REQUIRED,\n {\n context: { source: \"DatabaseEventEmitter.constructor\" },\n cause: new Error(\"Database adapter is required for event emitter\"),\n },\n );\n }\n }\n\n /**\n * Register an event handler for a specific event type\n */\n on<T extends DatabaseEvent>(\n eventType: T[\"type\"],\n handler: DBEventHandler<T>,\n ): void {\n try {\n if (!isString(eventType)) {\n throw new DatabaseError(\n \"Invalid event type\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"on\" },\n cause: new Error(\"Invalid event type\"),\n },\n );\n }\n\n if (!handler || typeof handler !== \"function\") {\n throw new DatabaseError(\n \"Invalid event handler\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"on\" },\n cause: new Error(\"Invalid event handler\"),\n },\n );\n }\n\n if (!this.eventHandlers.has(eventType)) {\n this.eventHandlers.set(eventType, []);\n }\n\n const handlers = this.eventHandlers.get(eventType);\n if (handlers) {\n handlers.push(handler as DBEventHandler<DatabaseEvent>);\n }\n } catch (error) {\n logger.error(\n `Failed to register event handler: ${(error as Error).message}`,\n );\n }\n }\n\n /**\n * Remove an event handler for a specific event type\n */\n off<T extends DatabaseEvent>(\n eventType: T[\"type\"],\n handler: DBEventHandler<T>,\n ): void {\n const handlers = this.eventHandlers.get(eventType);\n if (handlers) {\n const index = handlers.indexOf(handler as DBEventHandler<DatabaseEvent>);\n if (index !== -1) handlers.splice(index, 1);\n }\n }\n\n /**\n * Emit an event to all registered handlers\n */\n emit(event: DatabaseEvent): void {\n try {\n if (!isObject(event) || !event.type) {\n logger.error(\"Invalid event object\");\n return;\n }\n\n const handlers = this.eventHandlers.get(event.type as string);\n if (!handlers || handlers.length === 0) return;\n\n handlers.forEach((handler) => {\n try {\n const result = handler(event);\n if (result instanceof Promise) {\n result.catch((error) => {\n logger.error(\n `Async event handler error: ${(error as Error).message}`,\n );\n });\n }\n } catch (error) {\n logger.error(`Event handler error: ${(error as Error).message}`);\n }\n });\n } catch (error) {\n logger.error(`Failed to emit event: ${(error as Error).message}`);\n }\n }\n\n /**\n * Emit a before query event\n */\n emitBeforeQuery(\n table: string,\n operation: DatabaseOperationType,\n params?: Record<string, object>,\n context?: DatabaseExecutionContext,\n ): void {\n const event: BeforeQueryEvent = {\n type: DATABASE_EVENT_TYPE.BeforeQuery,\n timestamp: new Date(),\n adapter: this.adapter.toString(),\n table,\n operation,\n params,\n context,\n };\n this.emit(event);\n }\n\n /**\n * Emit an after query event\n */\n emitAfterQuery(\n table: string,\n operation: DatabaseOperationType,\n duration: number,\n affectedRows?: number,\n ): void {\n const event: AfterQueryEvent = {\n type: DATABASE_EVENT_TYPE.AfterQuery,\n timestamp: new Date(),\n adapter: this.adapter.toString(),\n table,\n operation,\n duration,\n affectedRows,\n };\n this.emit(event);\n }\n\n emitQueryError(options: EmitQueryErrorOptions): void {\n try {\n if (!isObject(options)) {\n logger.error(\"Invalid options for emitQueryError\");\n return;\n }\n\n const { table, operation, error, params, context } = options;\n\n if (!table || !operation || !error) {\n logger.error(\"Missing required fields for query error event\");\n return;\n }\n\n const event: QueryErrorEvent = {\n type: DATABASE_EVENT_TYPE.QueryError,\n timestamp: new Date(),\n adapter: this.adapter.toString(),\n table,\n operation,\n error,\n params,\n context,\n };\n\n this.emit(event);\n } catch (emitError) {\n logger.error(\n `Failed to emit query error event: ${(emitError as Error).message}`,\n );\n }\n }\n\n /**\n * Emit a before transaction event\n */\n emitBeforeTransaction(\n transactionId: string,\n context?: DatabaseExecutionContext,\n ): void {\n const event: BeforeTransactionEvent = {\n type: DATABASE_EVENT_TYPE.BeforeTransaction,\n timestamp: new Date(),\n adapter: this.adapter.toString(),\n transactionId,\n context,\n };\n this.emit(event);\n }\n\n /**\n * Emit an after transaction event\n */\n emitAfterTransaction(transactionId: string, duration: number): void {\n const event: AfterTransactionEvent = {\n type: DATABASE_EVENT_TYPE.AfterTransaction,\n timestamp: new Date(),\n adapter: this.adapter.toString(),\n transactionId,\n duration,\n };\n this.emit(event);\n }\n\n /**\n * Emit a transaction rollback event\n */\n emitTransactionRollback(transactionId: string, error?: Error): void {\n const event: TransactionRollbackEvent = {\n type: DATABASE_EVENT_TYPE.TransactionRollback,\n timestamp: new Date(),\n adapter: this.adapter.toString(),\n transactionId,\n error,\n };\n this.emit(event);\n }\n\n /**\n * Emit a health change event\n */\n emitHealthChange(\n previousStatus: boolean,\n currentStatus: boolean,\n details?: Record<string, string | number | boolean>,\n ): void {\n const event: HealthChangeEvent = {\n type: DATABASE_EVENT_TYPE.HealthChange,\n timestamp: new Date(),\n adapter: this.adapter.toString(),\n previousStatus,\n currentStatus,\n details,\n };\n this.emit(event as DatabaseEvent);\n }\n}\n","/**\n * @fileoverview Database Result Helper Functions for @plyaz/db package\n *\n * This module provides utility functions for creating standardized DatabaseResult objects\n * used throughout the @plyaz/db package. These helpers ensure consistent result formatting\n * across all database operations and adapters.\n *\n * Part of the @plyaz/db package - a TypeScript database abstraction layer with\n * support for multiple adapters (Drizzle, Supabase, SQL), extensions (audit, encryption,\n * soft delete), and advanced features (caching, read replicas, multi-tenancy).\n *\n */\n\nimport type { DatabaseResult } from \"@plyaz/types/db\";\n\n/**\n * Creates a successful DatabaseResult wrapper for operation results\n *\n * Used throughout all database adapters and extensions to wrap successful operation results\n * in a consistent format. This enables standardized error handling and result processing\n * across the entire @plyaz/db package.\n *\n * **Used by:**\n * - All database adapters (DrizzleAdapter, SupabaseAdapter, SQLAdapter)\n * - All extensions (AuditAdapter, EncryptionAdapter, SoftDeleteAdapter, etc.)\n * - DatabaseService for operation results\n * - Repository layer for consistent return types\n *\n * @template T - The type of the successful result value\n * @param {T} value - The successful result value to wrap\n * @returns {DatabaseResult<T>} A success result object with the value\n *\n * @example\n * ```typescript\n * import { success } from '@plyaz/db/utils';\n *\n * // In adapter methods\n * async findById<T>(table: string, id: string): Promise<DatabaseResult<T | null>> {\n * try {\n * const record = await this.db.select().from(table).where(eq(id));\n * return success(record[0] || null); // Wrap successful result\n * } catch (error) {\n * return failure(new DatabaseError('FIND_FAILED', error.message));\n * }\n * }\n *\n * // In service methods\n * const userResult = await userRepository.findById('user-123');\n * if (userResult.success) {\n * console.log('Found user:', userResult.value.name);\n * }\n * ```\n *\n */\nexport function success<T = null>(value: T = null as T): DatabaseResult<T> {\n return { success: true, value };\n}\n\n/**\n * Creates a failed DatabaseResult wrapper for operation errors\n * \n * Used throughout all database adapters and extensions to wrap error results\n * in a consistent format. This enables standardized error handling and result processing\n * across the entire @plyaz/db package.\n * \n * **Used by:**\n * - All database adapters for error cases\n * - All extensions for error propagation\n * - DatabaseService for operation failures\n * - Repository layer for consistent error handling\n * \n * @template T - The type that would have been returned on success\n * @param {Error} error - The error that occurred during the operation\n * @returns {DatabaseResult<T>} A failure result object with the error\n * \n * @example\n * ```typescript\n * import { failure } from '@plyaz/db/utils';\n * import { DatabaseError } from '@plyaz/errors';\nimport { DATABASE_ERROR_CODES } from '@plyaz/types/errors';\n * \n * // In adapter methods\n * async create<T>(table: string, data: T): Promise<DatabaseResult<T>> {\n * try {\n * const result = await this.db.insert(table).values(data).returning();\n * return success(result[0]);\n * } catch (error) {\n * return failure(new DatabaseError(\n * `Failed to create record: ${error.message}`));\n * }\n * }\n * \n * // In service layer error handling\n * const createResult = await userRepository.create(userData);\n * if (!createResult.success) {\n * logger.error('User creation failed:', createResult.error.message);\n * throw createResult.error;\n * }\n * ```\n * \n */\nexport function failure<T>(error: Error): DatabaseResult<T> {\n return { success: false, error };\n}\n","/**\n * @fileoverview Detail Normalization Utilities for @plyaz/db package\n *\n * This module provides utilities for normalizing various data types into consistent\n * string-based record formats. Used throughout the @plyaz/db package for standardizing\n * error details, health status information, and event metadata.\n *\n * Part of the @plyaz/db package - a TypeScript database abstraction layer with\n * support for multiple adapters (Drizzle, Supabase, SQL), extensions (audit, encryption,\n * soft delete), and advanced features (caching, read replicas, multi-tenancy).\n *\n */\n\nimport { isObject } from \"./typeGuards\";\n\n/**\n * Normalizes any input into a standardized Record<string, string> format\n *\n * Converts various data types into a consistent string-based record format\n * for use in error details, health status information, and event metadata.\n * Provides safe handling of different input types with fallback strategies.\n *\n * **Normalization Rules:**\n * - Objects: Converts all property values to strings while preserving keys\n * - Primitives: Wraps in { info: stringValue } format\n * - null/undefined: Returns undefined (no details)\n * - Arrays: Converts to { info: stringified array }\n * - Errors: Safely handles conversion failures\n *\n * **Used by:**\n * - HealthManager for health status details\n * - DatabaseEventEmitter for event metadata\n * - Error handling throughout adapter chain\n * - Audit logging for consistent detail formatting\n *\n * @param {unknown} details - Input details of any type to normalize\n * @returns {Record<string, string> | undefined} Normalized details as string record or undefined\n *\n * @example\n * ```typescript\n * import { normalizeDetails } from '@plyaz/db/utils';\n *\n * // Object normalization\n * const objDetails = normalizeDetails({\n * count: 42,\n * active: true,\n * name: 'test'\n * });\n * console.log(objDetails);\n * // { count: \"42\", active: \"true\", name: \"test\" }\n *\n * // Primitive normalization\n * const stringDetails = normalizeDetails(\"Connection timeout\");\n * console.log(stringDetails);\n * // { info: \"Connection timeout\" }\n *\n * // Number normalization\n * const numberDetails = normalizeDetails(404);\n * console.log(numberDetails);\n * // { info: \"404\" }\n *\n * // Null/undefined handling\n * const nullDetails = normalizeDetails(null);\n * console.log(nullDetails);\n * // undefined\n *\n * // Array normalization\n * const arrayDetails = normalizeDetails(['error1', 'error2']);\n * console.log(arrayDetails);\n * // { info: \"error1,error2\" }\n *\n * // Error object normalization\n * const errorDetails = normalizeDetails(new Error('Database error'));\n * console.log(errorDetails);\n * // { info: \"Error: Database error\" }\n * ```\n *\n * @example\n * ### Usage in Health Status\n * ```typescript\n * // In HealthManager.checkHealth()\n * const healthStatus = {\n * isHealthy: true,\n * responseTime: 150,\n * details: normalizeDetails({\n * adapter: 'drizzle',\n * connections: 5,\n * lastQuery: new Date()\n * })\n * };\n * // details: { adapter: \"drizzle\", connections: \"5\", lastQuery: \"2024-01-01T10:00:00.000Z\" }\n * ```\n *\n * @example\n * ### Usage in Error Handling\n * ```typescript\n * // In adapter error handling\n * catch (error) {\n * return failure(new DatabaseError(\n * 'QUERY_FAILED',\n * HTTP_STATUS.INTERNAL_SERVER_ERROR,\n * 'Query execution failed',\n * normalizeDetails({\n * query: sql,\n * params: queryParams,\n * originalError: error.message\n * })\n * ));\n * }\n * ```\n *\n */\nexport function normalizeDetails(\n details: unknown,\n): Record<string, string> | undefined {\n try {\n // Handle null, undefined, or falsy values\n // Return undefined to indicate no details available\n if (!details) return undefined;\n\n // Handle object types (but not arrays)\n // Convert all object property values to strings while preserving keys\n if (isObject(details)) {\n const mapped: Record<string, string> = {};\n\n // Iterate through object entries and convert values to strings\n for (const [key, value] of Object.entries(details)) {\n // Use String() for safe conversion of any value type\n mapped[key] = String(value);\n }\n return mapped;\n }\n\n // Handle primitives, arrays, and other non-object types\n // Wrap in standardized { info: value } format\n return { info: String(details) };\n } catch (error) {\n // Fallback error handling for extreme cases\n // Return error information if normalization fails\n return {\n error: \"Failed to normalize details\",\n reason: (error as Error).message,\n };\n }\n}\n","/**\n * @fileoverview Health Manager for @plyaz/db package\n *\n * This module provides the HealthManager class responsible for monitoring database\n * connection health, performing periodic health checks, and managing the lifecycle\n * of database connections. It provides a centralized way to track database status.\n *\n * Part of the @plyaz/db package - a TypeScript database abstraction layer with\n * support for multiple adapters (Drizzle, Supabase, SQL), extensions (audit, encryption,\n * soft delete), and advanced features (caching, read replicas, multi-tenancy).\n *\n */\n\nimport type {\n DatabaseAdapterType,\n DatabaseHealthStatus,\n DatabaseResult,\n HealthManagerConfig,\n} from \"@plyaz/types/db\";\nimport { success, failure } from \"@utils/databaseResultHelpers\";\nimport { normalizeDetails } from \"@utils/normalizeDetails\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\n\n/** Default number of consecutive failures before triggering failover */\nconst DEFAULT_FAILOVER_THRESHOLD = 3;\n\n/**\n * 🌡️ HEALTH MANAGER - Database Health Monitoring\n *\n * Manages database health checks and monitoring functionality for all database adapters.\n * This class is responsible for performing health checks on the database connection,\n * storing the last known health status, and providing methods to quickly check\n * the current health state of the database.\n *\n * **Application Flow Position:**\n * DatabaseService → **HealthManager** → Adapter.healthCheck() → Database\n *\n * **What this class does:**\n * 1. Initializes database connections on startup\n * 2. Performs periodic health checks via adapter.healthCheck()\n * 3. Caches last known health status for quick access\n * 4. Normalizes health details across different adapters\n * 5. Manages connection lifecycle (connect/disconnect)\n *\n * **Called by:** DatabaseService.healthCheck(), application health endpoints\n * **Calls:** DatabaseAdapter.healthCheck(), DatabaseAdapter.connect/disconnect\n * **Used for:** Application health monitoring, load balancer health checks\n *\n * @example\n * ```typescript\n * // Create health manager with adapter\n * const healthManager = new HealthManager(drizzleAdapter);\n *\n * // Initialize connection and perform initial health check\n * await healthManager.init();\n *\n * // Perform health check\n * const healthResult = await healthManager.checkHealth();\n * if (healthResult.success) {\n * console.log('Database is healthy:', healthResult.value);\n * }\n *\n * // Quick health status check (uses cached result)\n * const isHealthy = healthManager.isHealthy();\n *\n * // Get last known status without new check\n * const lastStatus = healthManager.getLastHealthStatus();\n *\n * // Cleanup on shutdown\n * await healthManager.shutdown();\n * ```\n *\n */\nexport class HealthManager {\n private lastHealthStatus: DatabaseHealthStatus | null = null;\n private initialized = false;\n private currentAdapter: DatabaseAdapterType;\n private primaryAdapter: DatabaseAdapterType;\n private backupAdapters: DatabaseAdapterType[];\n private consecutiveFailures = 0;\n private healthCheckInterval?: number;\n private failoverThreshold: number;\n private autoFailover: boolean;\n private healthCheckTimer?: globalThis.NodeJS.Timeout;\n\n constructor(config: DatabaseAdapterType | HealthManagerConfig) {\n // Support both old (single adapter) and new (config) constructors\n if (\"primary\" in config) {\n this.primaryAdapter = config.primary;\n this.currentAdapter = config.primary;\n this.backupAdapters = config.backups ?? [];\n this.healthCheckInterval = config.healthCheckInterval;\n this.failoverThreshold =\n config.failoverThreshold ?? DEFAULT_FAILOVER_THRESHOLD;\n this.autoFailover = config.autoFailover ?? false;\n } else {\n this.primaryAdapter = config;\n this.currentAdapter = config;\n this.backupAdapters = [];\n this.failoverThreshold = DEFAULT_FAILOVER_THRESHOLD;\n this.autoFailover = false;\n }\n }\n\n /**\n * Initializes the health manager by establishing database connection and performing initial health check\n *\n * Sets up the database connection and performs an initial health check to establish\n * baseline health status. This method should be called during application startup\n * to ensure the database is ready for operations.\n *\n * **Initialization Process:**\n * 1. Checks if already initialized (prevents double initialization)\n * 2. Calls adapter.connect() if available (establishes connection)\n * 3. Performs initial health check via checkHealth()\n * 4. Sets initialized flag to prevent re-initialization\n *\n * @returns {Promise<void>} Promise that resolves when initialization is complete\n *\n * @example\n * ```typescript\n * const healthManager = new HealthManager(adapter);\n *\n * // Initialize during application startup\n * await healthManager.init();\n * console.log('Health manager initialized');\n *\n * // Subsequent calls are no-ops\n * await healthManager.init(); // Does nothing, already initialized\n * ```\n *\n */\n async init(): Promise<void> {\n // Prevent double initialization\n if (this.initialized) return;\n\n // Establish database connection if adapter supports it\n if (typeof this.currentAdapter.initialize === \"function\") {\n await this.currentAdapter.initialize();\n }\n\n // Perform initial health check to establish baseline status\n await this.checkHealth();\n this.initialized = true;\n\n // Start periodic health checks if configured\n if (this.healthCheckInterval && this.healthCheckInterval > 0) {\n this.startPeriodicHealthChecks();\n }\n }\n\n /**\n * Performs a comprehensive health check on the database connection\n *\n * Executes a health check via the database adapter and normalizes the results\n * into a standardized health status format. Measures response time and handles\n * both successful and failed health checks gracefully.\n *\n * **Health Check Process:**\n * 1. Records start time for response time measurement\n * 2. Calls adapter.healthCheck() to test database connectivity\n * 3. Normalizes adapter-specific response into standard format\n * 4. Caches result as lastHealthStatus for quick access\n * 5. Returns standardized DatabaseResult with health information\n *\n * **Health Status Fields:**\n * - isHealthy: Boolean indicating if database is operational\n * - responseTime: Time in milliseconds for health check to complete\n * - details: Normalized adapter-specific details (connection info, errors, etc.)\n *\n * @returns {Promise<DatabaseResult<DatabaseHealthStatus>>} Promise resolving to health status result\n *\n * @example\n * ```typescript\n * // Perform health check\n * const healthResult = await healthManager.checkHealth();\n *\n * if (healthResult.success) {\n * const status = healthResult.value;\n * console.log(`Database healthy: ${status.isHealthy}`);\n * console.log(`Response time: ${status.responseTime}ms`);\n * console.log('Details:', status.details);\n * } else {\n * console.error('Health check failed:', healthResult.error.message);\n * }\n *\n * // Example healthy response:\n * // {\n * // success: true,\n * // value: {\n * // isHealthy: true,\n * // responseTime: 45,\n * // details: { adapter: \"drizzle\", connections: \"5\" }\n * // }\n * // }\n *\n * // Example unhealthy response:\n * // {\n * // success: true,\n * // value: {\n * // isHealthy: false,\n * // responseTime: 5000,\n * // details: { error: \"Connection timeout\" }\n * // }\n * // }\n * ```\n *\n */\n /**\n * Handle health check result and update internal state\n */\n private async handleHealthResult(isSuccess: boolean): Promise<void> {\n if (isSuccess) {\n this.consecutiveFailures = 0;\n return;\n }\n\n this.consecutiveFailures++;\n if (\n this.autoFailover &&\n this.consecutiveFailures >= this.failoverThreshold\n ) {\n await this.performFailover();\n }\n }\n\n /**\n * Create health status from check result\n */\n private createHealthStatus(\n result: DatabaseResult<DatabaseHealthStatus>,\n responseTime: number,\n ): DatabaseHealthStatus {\n return {\n isHealthy: result.success,\n responseTime,\n details: result.success\n ? normalizeDetails(result.value)\n : { error: result.error?.message ?? \"Unknown error\" },\n };\n }\n\n async checkHealth(): Promise<DatabaseResult<DatabaseHealthStatus>> {\n const startTime = Date.now();\n\n try {\n const result = await this.currentAdapter.healthCheck();\n const responseTime = Date.now() - startTime;\n\n const status = this.createHealthStatus(result, responseTime);\n this.lastHealthStatus = status;\n\n await this.handleHealthResult(result.success);\n\n return success(status);\n } catch (error) {\n const status: DatabaseHealthStatus = {\n isHealthy: false,\n responseTime: Date.now() - startTime,\n details: { error: (error as Error).message },\n };\n\n this.lastHealthStatus = status;\n await this.handleHealthResult(false);\n\n return failure(\n new DatabaseError(\n `Health check failed: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.FETCH_FAILED,\n {\n context: { source: \"checkHealth\" },\n cause: error as Error,\n },\n ),\n );\n }\n }\n /**\n * Get the last known health status\n */\n getLastHealthStatus(): DatabaseHealthStatus | null {\n return this.lastHealthStatus;\n }\n\n /**\n * Check if the database is currently healthy\n */\n isHealthy(): boolean {\n return this.lastHealthStatus?.isHealthy ?? false;\n }\n\n /**\n * Get the current active adapter\n */\n getCurrentAdapter(): DatabaseAdapterType {\n return this.currentAdapter;\n }\n\n /**\n * Try to initialize and verify health of a backup adapter\n */\n private async tryBackupAdapter(\n backup: DatabaseAdapterType,\n ): Promise<boolean> {\n if (typeof backup.initialize === \"function\") {\n const initResult = await backup.initialize();\n if (!initResult.success) return false;\n }\n\n const healthResult = await backup.healthCheck();\n return healthResult.success && (healthResult.value?.isHealthy ?? false);\n }\n\n /**\n * Switch to a healthy backup adapter\n */\n private async switchToBackup(backup: DatabaseAdapterType): Promise<void> {\n await this.currentAdapter.close();\n this.currentAdapter = backup;\n this.consecutiveFailures = 0;\n console.log(\"[HealthManager] Failover successful to backup adapter\");\n }\n\n /**\n * Perform failover to next available backup adapter\n */\n private async performFailover(): Promise<void> {\n if (this.backupAdapters.length === 0) {\n console.warn(\"[HealthManager] No backup adapters available for failover\");\n return;\n }\n\n for (const backup of this.backupAdapters) {\n try {\n const isHealthy = await this.tryBackupAdapter(backup);\n if (isHealthy) {\n await this.switchToBackup(backup);\n return;\n }\n } catch (error) {\n console.error(\n \"[HealthManager] Backup adapter health check failed:\",\n error,\n );\n }\n }\n\n console.error(\n \"[HealthManager] All backup adapters failed, staying with current adapter\",\n );\n }\n\n /**\n * Start periodic health checks\n */\n private startPeriodicHealthChecks(): void {\n if (this.healthCheckTimer) return;\n\n this.healthCheckTimer = setInterval(async () => {\n await this.checkHealth();\n }, this.healthCheckInterval);\n }\n\n /**\n * Stop periodic health checks\n */\n private stopPeriodicHealthChecks(): void {\n if (this.healthCheckTimer) {\n clearInterval(this.healthCheckTimer);\n this.healthCheckTimer = undefined;\n }\n }\n\n /**\n * Gracefully shut down the health manager\n */\n async shutdown(): Promise<void> {\n this.stopPeriodicHealthChecks();\n\n await this.currentAdapter.close();\n\n this.initialized = false;\n this.lastHealthStatus = null;\n }\n}\n","/**\n * @fileoverview Configuration Merger for @plyaz/db package\n *\n * This module provides the ConfigMerger utility class responsible for deep merging\n * database configurations. It handles merging global database service configuration\n * with per-operation overrides to create resolved configurations for the adapter chain.\n *\n * Part of the @plyaz/db package - a TypeScript database abstraction layer with\n * support for multiple adapters (Drizzle, Supabase, SQL), extensions (audit, encryption,\n * soft delete), and advanced features (caching, read replicas, multi-tenancy).\n */\n\nimport { NUMERIX } from \"@plyaz/config\";\nimport type {\n DatabaseServiceConfig,\n DBCacheConfig,\n DBEncryptionConfig,\n OperationConfig,\n ResolvedOperationConfig,\n SoftDeleteConfig,\n TimestampsConfig,\n} from \"@plyaz/types/db\";\n\n/**\n * CONFIG MERGER - Configuration Resolution Engine\n *\n * Utility class for deep merging database configurations.\n * Handles merging global database service configuration with per-operation overrides\n *\n * Application Flow Position:**\n * DatabaseService → **ConfigMerger** → Resolved Config → Adapter Chain\n *\n * **What this class does:**\n * 1. Receives global config (from createDatabaseService) and operation config (from method calls)\n * 2. Deep merges nested objects (encryption, softDelete, cache, etc.)\n * 3. Operation config takes precedence over global config\n * 4. Returns resolved configuration for adapter chain\n *\n * **Called by:** DatabaseService methods (get, create, update, delete, etc.)\n * **Calls:** Internal merge methods for each config section\n * **Returns to:** DatabaseService for delegation to adapter chain\n *\n * **Merge Strategy:**\n * - Operation config overrides global config\n * - Nested objects are deep merged (not replaced)\n * - Arrays use replace strategy for fields, concat for others\n * - Undefined values in operation config fall back to global defaults\n *\n * @example\n * ### Configuration Merging Flow\n * ```typescript\n * // Global config (from createDatabaseService)\n * const globalConfig = {\n * softDelete: { enabled: true, field: 'deletedAt' },\n * cache: { enabled: true, ttl: 300 }\n * };\n *\n * // Operation config (from method call)\n * const operationConfig = {\n * cache: { enabled: false },\n * includeSoftDeleted: true\n * };\n *\n * // ConfigMerger.mergeConfigs() produces:\n * const resolved = {\n * softDelete: { enabled: true, field: 'deletedAt' }, // From global\n * cache: { enabled: false, ttl: 300 }, // Merged\n * includeSoftDeleted: true, // From operation\n * skipAudit: false // Default\n * };\n * ```\n */\nexport class ConfigMerger {\n /**\n * Merges global database configuration with operation-specific overrides\n *\n * This is the main entry point for configuration resolution in the DatabaseService.\n * It performs deep merging of nested configuration objects while preserving type safety\n * and applying proper precedence rules.\n *\n * **Merge Precedence (highest to lowest):**\n * 1. Operation-specific config (method-level overrides)\n * 2. Global service config (from createDatabaseService)\n * 3. Default values (built-in fallbacks)\n *\n * **Configuration Sections Merged:**\n * - softDelete: Logical deletion settings\n * - encryption: Field-level encryption settings\n * - cache: Caching behavior and TTL\n * - timestamps: Automatic timestamp management\n * - Operation flags: skipAudit, includeSoftDeleted, etc.\n *\n * @param {DatabaseServiceConfig} global - Global database service configuration from createDatabaseService()\n * @param {OperationConfig} [operation] - Optional operation-specific configuration overrides\n * @returns {ResolvedOperationConfig} Fully resolved configuration with all defaults applied\n *\n * @example\n * ```typescript\n * // In DatabaseService.get() method\n * const resolvedConfig = ConfigMerger.mergeConfigs(\n * this.globalConfig, // From createDatabaseService\n * operationConfig // From method parameter\n * );\n *\n * // Example global config\n * const globalConfig = {\n * softDelete: { enabled: true, field: 'deletedAt' },\n * encryption: { enabled: true, fields: { users: ['ssn'] } },\n * cache: { enabled: true, ttl: 300 }\n * };\n *\n * // Example operation config (disable cache for this operation)\n * const operationConfig = {\n * cache: { enabled: false },\n * skipAudit: true\n * };\n *\n * // Resulting merged config\n * const result = {\n * softDelete: { enabled: true, field: 'deletedAt' }, // From global\n * encryption: { enabled: true, fields: { users: ['ssn'] } }, // From global\n * cache: { enabled: false, ttl: 300 }, // Merged (enabled overridden)\n * timestamps: undefined, // Not specified\n * skipAudit: true, // From operation\n * includeSoftDeleted: false, // Default\n * forceAdapter: undefined, // Not specified\n * timeout: 30000 // Default\n * };\n * ```\n *\n */\n static mergeConfigs(\n global: DatabaseServiceConfig,\n operation?: OperationConfig,\n ): ResolvedOperationConfig {\n if (!operation) {\n return this.convertGlobalToResolved(global);\n }\n\n return {\n softDelete: this.mergeSoftDeleteConfig(\n global.softDelete,\n operation.softDelete,\n ),\n encryption: this.mergeEncryptionConfig(\n global.encryption,\n operation.encryption,\n ),\n cache: this.mergeCacheConfig(global.cache, operation.cache),\n timestamps: this.mergeTimestampsConfig(\n global.timestamps,\n operation.timestamps,\n ),\n skipAudit: operation.skipAudit ?? false,\n includeSoftDeleted: operation.includeSoftDeleted ?? false,\n forceAdapter: operation.forceAdapter,\n timeout: operation.timeout ?? NUMERIX.THIRTY_THOUSAND,\n };\n }\n\n /**\n * Merges soft delete configuration with operation-specific overrides\n *\n * Handles deep merging of soft delete settings, allowing operation-level\n * overrides while preserving base configuration values.\n *\n * @private\n * @param {SoftDeleteConfig} [base] - Base soft delete configuration from global config\n * @param {Partial<SoftDeleteConfig>} [override] - Operation-specific soft delete overrides\n * @returns {SoftDeleteConfig | undefined} Merged soft delete configuration or undefined if neither provided\n *\n * @example\n * ```typescript\n * // Base config: { enabled: true, field: 'deletedAt', excludeTables: ['logs'] }\n * // Override: { enabled: false }\n * // Result: { enabled: false, field: 'deletedAt', excludeTables: ['logs'] }\n * ```\n *\n */\n private static mergeSoftDeleteConfig(\n base?: SoftDeleteConfig,\n override?: Partial<SoftDeleteConfig>,\n ): SoftDeleteConfig | undefined {\n // Return undefined if neither base nor override provided\n if (!base && !override) return undefined;\n // Return base config if no override provided\n if (!override) return base;\n // Return override as complete config if no base provided\n if (!base) return override as SoftDeleteConfig;\n\n // Deep merge: override takes precedence, base provides fallbacks\n return {\n enabled: override.enabled ?? base.enabled,\n field: override.field ?? base.field,\n excludeTables: override.excludeTables ?? base.excludeTables,\n };\n }\n\n /**\n * Merges encryption configuration with operation-specific overrides\n *\n * Handles deep merging of field-level encryption settings, allowing operation-level\n * overrides for encryption behavior while preserving base configuration.\n *\n * @private\n * @param {DBEncryptionConfig} [base] - Base encryption configuration from global config\n * @param {Partial<DBEncryptionConfig>} [override] - Operation-specific encryption overrides\n * @returns {DBEncryptionConfig | undefined} Merged encryption configuration or undefined if neither provided\n *\n * @example\n * ```typescript\n * // Base config: { enabled: true, key: 'base64key', fields: { users: ['ssn'] } }\n * // Override: { enabled: false }\n * // Result: { enabled: false, key: 'base64key', fields: { users: ['ssn'] } }\n * ```\n *\n */\n // eslint-disable-next-line complexity\n private static mergeEncryptionConfig(\n base?: DBEncryptionConfig,\n override?: Partial<DBEncryptionConfig>,\n ): DBEncryptionConfig | undefined {\n // Return undefined if neither base nor override provided\n if (!base && !override) return undefined;\n // Return base config if no override provided\n if (!override) return base;\n // Return override as complete config if no base provided\n if (!base) return override as DBEncryptionConfig;\n\n // Deep merge: override takes precedence, base provides fallbacks\n return {\n enabled: override.enabled ?? base.enabled,\n key: override.key ?? base.key,\n fields: override.fields ?? base.fields,\n algorithm: override.algorithm ?? base.algorithm,\n useDatabaseNative: override.useDatabaseNative ?? base.useDatabaseNative,\n };\n }\n\n /**\n * Merges cache configuration with operation-specific overrides\n * \n * Handles deep merging of caching settings, allowing operation-level\n * overrides for cache behavior (enable/disable, TTL changes, etc.).\n * \n * @private\n * @param {DBCacheConfig} [base] - Base cache configuration from global config\n * @param {Partial<DBCacheConfig>} [override] - Operation-specific cache overrides\n * @returns {DBCacheConfig | undefined} Merged cache configuration or undefined if neither provided\n * \n * @example\n * ```typescript\n * // Base config: { enabled: true, ttl: 300, provider: 'redis' }\n * // Override: { enabled: false }\n * // Result: { enabled: false, ttl: 300, provider: 'redis' }\n * ```\n * \n\n */\n // eslint-disable-next-line complexity\n private static mergeCacheConfig(\n base?: DBCacheConfig,\n override?: Partial<DBCacheConfig>,\n ): DBCacheConfig | undefined {\n // Return undefined if neither base nor override provided\n if (!base && !override) return undefined;\n // Return base config if no override provided\n if (!override) return base;\n // Return override as complete config if no base provided\n if (!base) return override as DBCacheConfig;\n\n // Deep merge: override takes precedence, base provides fallbacks\n return {\n enabled: override.enabled ?? base.enabled,\n ttl: override.ttl ?? base.ttl,\n provider: override.provider ?? base.provider,\n invalidation: override.invalidation ?? base.invalidation,\n };\n }\n\n /**\n * Merges timestamps configuration with operation-specific overrides\n *\n * Handles deep merging of automatic timestamp settings, allowing operation-level\n * overrides for timestamp field names and auto-update behavior.\n *\n * @private\n * @param {TimestampsConfig} [base] - Base timestamps configuration from global config\n * @param {Partial<TimestampsConfig>} [override] - Operation-specific timestamp overrides\n * @returns {TimestampsConfig | undefined} Merged timestamps configuration or undefined if neither provided\n *\n * @example\n * ```typescript\n * // Base config: { enabled: true, createdAtField: 'createdAt', updatedAtField: 'updatedAt' }\n * // Override: { autoUpdate: false }\n * // Result: { enabled: true, createdAtField: 'createdAt', updatedAtField: 'updatedAt', autoUpdate: false }\n * ```\n */\n // eslint-disable-next-line complexity\n private static mergeTimestampsConfig(\n base?: TimestampsConfig,\n override?: Partial<TimestampsConfig>,\n ): TimestampsConfig | undefined {\n // Return undefined if neither base nor override provided\n if (!base && !override) return undefined;\n // Return base config if no override provided\n if (!override) return base;\n // Return override as complete config if no base provided\n if (!base) return override as TimestampsConfig;\n\n // Deep merge: override takes precedence, base provides fallbacks\n return {\n enabled: override.enabled ?? base.enabled,\n createdAtField: override.createdAtField ?? base.createdAtField,\n updatedAtField: override.updatedAtField ?? base.updatedAtField,\n autoUpdate: override.autoUpdate ?? base.autoUpdate,\n };\n }\n\n /**\n * Converts global database service configuration to resolved operation configuration\n *\n * Used when no operation-specific overrides are provided. Applies default values\n * for operation-specific flags while preserving global configuration settings.\n *\n * @private\n * @param {DatabaseServiceConfig} global - Global database service configuration\n * @returns {ResolvedOperationConfig} Resolved configuration with defaults applied\n *\n * @example\n * ```typescript\n * // Global config: { softDelete: { enabled: true }, cache: { enabled: true, ttl: 300 } }\n * // Result: {\n * // softDelete: { enabled: true },\n * // cache: { enabled: true, ttl: 300 },\n * // skipAudit: false, // Default\n * // includeSoftDeleted: false, // Default\n * // timeout: 30000 // Default\n * // }\n * ```\n *\n */\n private static convertGlobalToResolved(\n global: DatabaseServiceConfig,\n ): ResolvedOperationConfig {\n return {\n // Preserve global configuration sections as-is\n softDelete: global?.softDelete,\n encryption: global?.encryption,\n cache: global?.cache,\n timestamps: global?.timestamps,\n // Apply default values for operation-specific flags\n skipAudit: false, // Default: enable audit logging\n includeSoftDeleted: false, // Default: exclude soft-deleted records\n timeout: NUMERIX.THIRTY_THOUSAND, // Default: 30 second timeout\n };\n }\n}\n","/**\n * @fileoverview Internal Database Service Implementation for @plyaz/db package\n *\n * This module provides the internal DatabaseService class that orchestrates all database\n * operations. It is NOT exported and is created internally by the createDatabaseService() factory.\n *\n * Part of the @plyaz/db package - a TypeScript database abstraction layer with\n * support for multiple adapters (Drizzle, Supabase, SQL), extensions (audit, encryption,\n * soft delete), and advanced features (caching, read replicas, multi-tenancy).\n *\n */\n\nimport { DatabaseEventEmitter } from \"./EventEmitter\";\nimport { HealthManager } from \"./HealthManager\";\nimport { ConfigMerger } from \"@utils/ConfigMerger\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport type {\n AuditContext,\n BatchUpdate,\n CreateInput,\n DatabaseAdapterType,\n DatabaseEvent,\n DatabaseEvents,\n DatabaseHealthStatus,\n DatabaseResult,\n DatabaseServiceConfig,\n DatabaseServiceInterface,\n Filter,\n OperationConfig,\n PaginatedResult,\n QueryOptions,\n ServiceStatus,\n TableName,\n TransactionFn,\n UpdateInput,\n} from \"@plyaz/types/db\";\nimport { ADAPTERS } from \"@plyaz/types/db\";\nimport { failure, success } from \"@utils/databaseResultHelpers\";\n\n/**\n * 🛠️ DATABASE SERVICE - Internal Service Layer\n *\n * Core service implementation that orchestrates all database operations.\n * NOT EXPORTED - created internally by createDatabaseService() factory.\n *\n * **Application Flow Position:**\n * createDatabaseService() → **DatabaseService** → Adapter Chain → Database\n *\n * **What this class does:**\n * 1. Stores global configuration from createDatabaseService()\n * 2. Receives calls from repositories via IDatabaseService interface\n * 3. Merges per-operation config with global config using ConfigMerger\n * 4. Fires before/after events (onBeforeWrite, onAfterWrite, etc.)\n * 5. Delegates to adapter chain with resolved configuration\n * 6. Returns results back to repositories\n *\n * **Called by:** Repository layer (BaseRepository, UserRepository, etc.)\n * **Calls:** ConfigMerger.mergeConfigs(), adapter chain methods, event handlers\n * **Delegates to:** Final wrapped adapter (ReadReplicaAdapter → AuditAdapter → ... → BaseAdapter)\n *\n * **Key Responsibilities:**\n * - Configuration merging and resolution\n * - Event system orchestration\n * - Audit context management\n * - Error handling and propagation\n * - Service status tracking\n *\n * @internal This class is not part of the public API\n */\nexport class DatabaseService implements DatabaseServiceInterface {\n private readonly globalConfig: DatabaseServiceConfig;\n public readonly adapter: DatabaseAdapterType;\n private readonly eventHandlers: DatabaseEvents | undefined;\n private readonly eventEmitter: DatabaseEventEmitter;\n private readonly healthManager: HealthManager;\n private readonly startTime: Date;\n private auditContext: AuditContext = {};\n\n constructor(config: {\n adapter: DatabaseAdapterType;\n globalConfig: DatabaseServiceConfig;\n eventHandlers?: DatabaseEvents;\n }) {\n this.globalConfig = config.globalConfig;\n this.adapter = config.adapter;\n this.eventHandlers = config.eventHandlers;\n this.startTime = new Date();\n\n const adapterType =\n (config.adapter?.constructor?.name?.toLowerCase() as ADAPTERS) ??\n ADAPTERS.SQL;\n this.eventEmitter = new DatabaseEventEmitter(adapterType);\n this.healthManager = new HealthManager(config.adapter);\n\n console.log(`DatabaseService initialized with ${adapterType} adapter`);\n }\n\n /**\n * 🔧 Prepare table name and configuration for operation\n *\n * Handles per-operation overrides for:\n * 1. Schema - prepends schema to table name (e.g., \"audit.logs\")\n * 2. ID Column - temporarily registers table with custom ID column\n *\n * Priority order:\n * - Operation config (highest) - per-query override\n * - TABLE_REGISTRY - global registration\n * - Default (lowest) - 'id' column, 'public' schema\n *\n * @param table Base table name\n * @param operationConfig Optional operation configuration with idColumn/schema\n * @returns Final table name to use (with schema prefix if applicable)\n *\n * @example\n * ```typescript\n * // With schema override\n * const tableName = this.prepareTable('logs', { schema: 'audit' });\n * // Returns: 'audit.logs'\n *\n * // With ID column override\n * const tableName = this.prepareTable('feature_flags', { idColumn: 'key' });\n * // Registers table with 'key' as ID column, returns: 'feature_flags'\n *\n * // With both\n * const tableName = this.prepareTable('users', { schema: 'backoffice', idColumn: 'user_id' });\n * // Returns: 'backoffice.users' with 'user_id' as ID column\n * ```\n */\n private prepareTable(\n table: TableName,\n operationConfig?: OperationConfig,\n ): string {\n let finalTableName = table;\n\n // Handle schema override\n if (operationConfig?.schema) {\n // If table already has schema prefix, replace it\n const tableWithoutSchema = table.includes(\".\")\n ? table.split(\".\")[1]\n : table;\n finalTableName = `${operationConfig.schema}.${tableWithoutSchema}`;\n }\n\n // Handle custom ID column override\n if (operationConfig?.idColumn) {\n // Temporarily register the table with the custom ID column\n // This allows the adapter to use the correct ID column for this operation\n this.adapter.registerTable(\n finalTableName,\n finalTableName,\n operationConfig.idColumn,\n );\n }\n\n return finalTableName;\n }\n\n /**\n * 🔍 Get a single record by ID\n *\n * **Flow:** Repository.findById() → **DatabaseService.get()** → ConfigMerger → Adapter Chain → Database\n *\n * **What happens:**\n * 1. Merges operation config with global config using ConfigMerger\n * 2. Fires onBeforeRead event (if configured)\n * 3. Delegates to adapter chain: ReadReplica → Audit → Cache → SoftDelete → Encryption → Base\n * 4. Fires onAfterRead event on success\n * 5. Returns result to repository\n *\n * **Called by:** BaseRepository.findById(), custom repository methods\n * **Calls:** ConfigMerger.mergeConfigs(), this.adapter.findById(), event handlers\n *\n * @param table Table name (from Tables enum)\n * @param id Record ID to retrieve\n * @param operationConfig Optional per-operation configuration overrides\n * @returns Promise resolving to the record or null if not found\n *\n * @example\n * ```typescript\n * // Called by UserRepository.findById()\n * const user = await this.db.get(Tables.USERS, 'user-123');\n *\n * // With operation config override\n * const user = await this.db.get(Tables.USERS, 'user-123', {\n * forceAdapter: 'primary', // Force primary DB\n * cache: { enabled: false } // Skip cache\n * });\n *\n * // With custom ID column (per-query override)\n * const flag = await this.db.get('feature_flags', 'my-flag-key', {\n * idColumn: 'key' // Use 'key' instead of 'id' as primary key\n * });\n *\n * // With custom schema\n * const auditLog = await this.db.get('logs', '123', {\n * schema: 'audit' // Query from audit.logs table\n * });\n *\n * // Combining multiple overrides\n * const backofficeUser = await this.db.get('users', 'admin-456', {\n * schema: 'backoffice',\n * idColumn: 'user_id',\n * forceAdapter: 'primary'\n * });\n * ```\n */\n async get<T extends Record<string, unknown>>(\n table: TableName,\n id: string,\n operationConfig?: OperationConfig,\n ): Promise<DatabaseResult<T | null>> {\n // Merge configs - operation config takes precedence\n ConfigMerger.mergeConfigs(this.globalConfig, operationConfig);\n\n // Prepare table with schema and ID column overrides\n const finalTable = this.prepareTable(table, operationConfig);\n\n try {\n // Fire before-read event if configured\n if (this.eventHandlers?.onBeforeRead) {\n await this.eventHandlers.onBeforeRead({\n type: \"beforeRead\",\n operation: \"READ\",\n table,\n timestamp: new Date(),\n });\n }\n\n // Delegate to adapter with resolved config\n const result = await this.adapter.findById<T>(finalTable, id);\n\n // Fire after-read event if configured and successful\n if (result.success && this.eventHandlers?.onAfterRead) {\n await this.eventHandlers.onAfterRead({\n type: \"afterRead\",\n operation: \"READ\",\n table,\n result: (result.value ?? {}) as Record<\n string,\n string | number | boolean | Date\n >,\n duration: 0, // TODO: Track duration\n timestamp: new Date(),\n });\n }\n\n return result;\n } catch (error) {\n return failure(\n new DatabaseError(\n `Get operation failed: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n {\n context: { source: \"get\" },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * List records with optional filtering, sorting, and pagination\n * Merges operation config with global config before delegating\n */\n async list<T extends Record<string, unknown>>(\n table: TableName,\n options?: QueryOptions<T>,\n operationConfig?: OperationConfig,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n ConfigMerger.mergeConfigs(this.globalConfig, operationConfig);\n\n if (this.eventHandlers?.onBeforeRead) {\n await this.eventHandlers.onBeforeRead({\n type: \"beforeRead\",\n operation: \"READ\",\n table,\n timestamp: new Date(),\n });\n }\n\n const result = await this.adapter.findMany<T>(table, options);\n\n if (result.success && this.eventHandlers?.onAfterRead) {\n await this.eventHandlers.onAfterRead({\n type: \"afterRead\",\n operation: \"READ\",\n table,\n result: (result.value ?? {}) as Record<\n string,\n string | number | boolean | Date\n >,\n duration: 0,\n timestamp: new Date(),\n });\n }\n\n return result;\n }\n\n /**\n * Create a new record\n * Merges operation config with global config before delegating\n */\n async create<T extends Record<string, unknown>>(\n table: TableName,\n input: CreateInput<T>,\n operationConfig?: OperationConfig,\n ): Promise<DatabaseResult<T>> {\n ConfigMerger.mergeConfigs(this.globalConfig, operationConfig);\n\n // Prepare table with schema and ID column overrides\n const finalTable = this.prepareTable(table, operationConfig);\n\n if (this.eventHandlers?.onBeforeWrite) {\n await this.eventHandlers.onBeforeWrite({\n type: \"beforeWrite\",\n operation: \"CREATE\",\n table,\n data: input as Record<string, string | number | boolean | Date>,\n timestamp: new Date(),\n });\n }\n\n const result = await this.adapter.create<T>(finalTable, input as T);\n\n if (result.success && this.eventHandlers?.onAfterWrite) {\n await this.eventHandlers.onAfterWrite({\n type: \"afterWrite\",\n operation: \"CREATE\",\n table,\n result: result.value as Record<\n string,\n string | number | boolean | Date\n >,\n duration: 0,\n timestamp: new Date(),\n });\n }\n\n return result;\n }\n\n /**\n * Update an existing record\n * Merges operation config with global config before delegating\n */\n async update<T extends Record<string, unknown>>(\n table: TableName,\n id: string,\n input: UpdateInput<T>,\n operationConfig?: OperationConfig,\n ): Promise<DatabaseResult<T>> {\n ConfigMerger.mergeConfigs(this.globalConfig, operationConfig);\n\n // Prepare table with schema and ID column overrides\n const finalTable = this.prepareTable(table, operationConfig);\n\n if (this.eventHandlers?.onBeforeWrite) {\n await this.eventHandlers.onBeforeWrite({\n type: \"beforeWrite\",\n operation: \"UPDATE\",\n table,\n data: input as Record<string, string | number | boolean | Date>,\n timestamp: new Date(),\n });\n }\n\n const result = await this.adapter.update<T>(\n finalTable,\n id,\n input as Partial<T>,\n );\n\n if (result.success && this.eventHandlers?.onAfterWrite) {\n await this.eventHandlers.onAfterWrite({\n type: \"afterWrite\",\n operation: \"UPDATE\",\n table,\n result: result.value as Record<\n string,\n string | number | boolean | Date\n >,\n duration: 0,\n timestamp: new Date(),\n });\n }\n\n return result;\n }\n\n /**\n * Delete a record\n * Merges operation config with global config before delegating\n */\n async delete(\n table: TableName,\n id: string,\n operationConfig?: OperationConfig,\n ): Promise<DatabaseResult<void>> {\n ConfigMerger.mergeConfigs(this.globalConfig, operationConfig);\n\n // Prepare table with schema and ID column overrides\n const finalTable = this.prepareTable(table, operationConfig);\n\n if (this.eventHandlers?.onBeforeWrite) {\n await this.eventHandlers.onBeforeWrite({\n type: \"beforeWrite\",\n operation: \"DELETE\",\n table,\n data: { id },\n timestamp: new Date(),\n });\n }\n\n const result = await this.adapter.delete(finalTable, id);\n\n if (result.success && this.eventHandlers?.onAfterWrite) {\n await this.eventHandlers.onAfterWrite({\n type: \"afterWrite\",\n operation: \"DELETE\",\n table,\n result: {},\n duration: 0,\n timestamp: new Date(),\n });\n }\n\n return result;\n }\n\n // Batch Operations\n async batchCreate<T extends Record<string, unknown>>(\n table: TableName,\n inputs: CreateInput<T>[],\n operationConfig?: OperationConfig,\n ): Promise<DatabaseResult<T[]>> {\n // TODO: Implement batch operations\n const results: T[] = [];\n for (const input of inputs) {\n const result = await this.create<T>(table, input, operationConfig);\n if (result.success && result.value) {\n results.push(result.value);\n } else {\n return failure(\n result.error ??\n new DatabaseError(\n \"Batch create failed\",\n DATABASE_ERROR_CODES.CREATE_FAILED,\n {\n context: { source: \"batchCreate\" },\n cause: new Error(\"Batch create failed\"),\n },\n ),\n );\n }\n }\n return success(results);\n }\n\n async batchUpdate<T extends Record<string, unknown>>(\n table: TableName,\n updates: BatchUpdate<T>[],\n operationConfig?: OperationConfig,\n ): Promise<DatabaseResult<T[]>> {\n const results: T[] = [];\n for (const update of updates) {\n const result = await this.update<T>(\n table,\n update.id,\n update.data,\n operationConfig,\n );\n if (result.success && result.value) {\n results.push(result.value);\n } else {\n return failure(\n result.error ??\n new DatabaseError(\n \"Batch update failed\",\n DATABASE_ERROR_CODES.UPDATE_FAILED,\n {\n context: { source: \"batchUpdate\" },\n cause: new Error(\"Batch update failed\"),\n },\n ),\n );\n }\n }\n return success(results);\n }\n\n async batchDelete(\n table: TableName,\n ids: string[],\n operationConfig?: OperationConfig,\n ): Promise<DatabaseResult<void>> {\n for (const id of ids) {\n const result = await this.delete(table, id, operationConfig);\n if (!result.success) {\n return failure(\n result.error ??\n new DatabaseError(\n \"Batch delete failed\",\n DATABASE_ERROR_CODES.DELETE_FAILED,\n {\n context: { source: \"batchDelete\" },\n cause: new Error(\"Batch delete failed\"),\n },\n ),\n );\n }\n }\n return success();\n }\n\n // Query Operations\n async query<T extends Record<string, unknown>>(\n table: TableName,\n query: QueryOptions<T>,\n operationConfig?: OperationConfig,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n return this.list<T>(table, query, operationConfig);\n }\n\n async count<T extends Record<string, unknown> = Record<string, unknown>>(\n table: TableName,\n filter?: Filter<T>,\n operationConfig?: OperationConfig,\n ): Promise<DatabaseResult<number>> {\n ConfigMerger.mergeConfigs(this.globalConfig, operationConfig);\n return this.adapter.count(table, filter);\n }\n\n // Transactions\n async transaction<T>(fn: TransactionFn<T>): Promise<DatabaseResult<T>> {\n return this.adapter.transaction(fn);\n }\n\n // Audit Context\n async setAuditContext(context: AuditContext): Promise<DatabaseResult<void>> {\n this.auditContext = { ...this.auditContext, ...context };\n return success();\n }\n\n // Event System\n on<T extends DatabaseEvent[\"type\"]>(\n event: T,\n handler: (\n event: Extract<DatabaseEvent, { type: T }>,\n ) => void | Promise<void>,\n ): void {\n this.eventEmitter.on(event, handler);\n }\n\n off<T extends DatabaseEvent[\"type\"]>(\n event: T,\n handler: (\n event: Extract<DatabaseEvent, { type: T }>,\n ) => void | Promise<void>,\n ): void {\n this.eventEmitter.off(event, handler);\n }\n\n // Health & Status\n async healthCheck(): Promise<DatabaseResult<DatabaseHealthStatus>> {\n return this.healthManager.checkHealth();\n }\n\n getStatus(): ServiceStatus {\n const uptime = Date.now() - this.startTime.getTime();\n return {\n isHealthy: true, // TODO: Get actual health status\n adapter: this.adapter.constructor.name,\n uptime,\n lastHealthCheck: new Date(),\n };\n }\n\n // Legacy methods for backward compatibility\n async findById<T extends Record<string, unknown>>(\n table: string,\n id: string,\n ): Promise<DatabaseResult<T | null>> {\n return this.get<T>(table, id);\n }\n\n async findMany<T extends Record<string, unknown>>(\n table: string,\n options?: QueryOptions<T>,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n return this.list<T>(table, options);\n }\n\n async initialize(): Promise<DatabaseResult<void>> {\n return success();\n }\n\n /**\n * Registers a table with the underlying adapter.\n *\n * @param name - Logical table name (e.g., 'users')\n * @param table - Physical table name or Drizzle table object\n * @param idColumn - ID column name (defaults to 'id')\n *\n * @example SQL Adapter\n * ```typescript\n * db.registerTable('users', 'users', 'id');\n * db.registerTable('feature_flags', 'feature_flags', 'key');\n * ```\n *\n * @example Drizzle Adapter (requires PgTable objects)\n * ```typescript\n * db.registerTable('users', usersTable, usersTable.id);\n * ```\n */\n registerTable<TTable = string, TIdColumn = string>(\n name: string,\n table?: TTable,\n idColumn?: TIdColumn,\n ): void {\n // Delegate to the adapter's registerTable method\n if (this.adapter && typeof this.adapter.registerTable === \"function\") {\n // For SQL adapter: if table is not provided, use name as table name\n const tableValue = table ?? name;\n this.adapter.registerTable(name, tableValue, idColumn);\n }\n }\n\n async exists(table: string, id: string): Promise<DatabaseResult<boolean>> {\n const result = await this.get(table, id);\n return success(result.success && result.value !== null);\n }\n\n private async fireBeforeReadEvent(table: TableName): Promise<void> {\n if (this.eventHandlers?.onBeforeRead) {\n await this.eventHandlers.onBeforeRead({\n type: \"beforeRead\",\n operation: \"READ\",\n table,\n timestamp: new Date(),\n });\n }\n }\n\n private async fireAfterReadEvent<T>(\n table: TableName,\n record: T | null,\n ): Promise<void> {\n if (this.eventHandlers?.onAfterRead) {\n await this.eventHandlers.onAfterRead({\n type: \"afterRead\",\n operation: \"READ\",\n table,\n result:\n (record as Record<string, string | number | boolean | Date>) ?? {},\n duration: 0,\n timestamp: new Date(),\n });\n }\n }\n\n async findOne<T extends Record<string, unknown>>(\n table: TableName,\n filter: Filter<T>,\n operationConfig?: OperationConfig,\n ): Promise<DatabaseResult<T | null>> {\n ConfigMerger.mergeConfigs(this.globalConfig, operationConfig);\n\n try {\n await this.fireBeforeReadEvent(table);\n\n const result = await this.adapter.findMany<T>(table, {\n filter,\n pagination: { limit: 1, offset: 0 },\n });\n\n if (!result.success) {\n return { success: false, error: result.error };\n }\n\n const firstRecord = result.value?.data[0] ?? null;\n await this.fireAfterReadEvent(table, firstRecord);\n\n return { success: true, value: firstRecord };\n } catch (error) {\n return failure(\n new DatabaseError(\n `Find one operation failed: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n {\n context: { source: \"findOne\" },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n async softDelete(\n table: TableName,\n id: string,\n operationConfig?: OperationConfig,\n ): Promise<DatabaseResult<void>> {\n ConfigMerger.mergeConfigs(this.globalConfig, {\n ...operationConfig,\n softDelete: { enabled: true },\n });\n\n try {\n if (this.eventHandlers?.onBeforeWrite) {\n await this.eventHandlers.onBeforeWrite({\n type: \"beforeWrite\",\n operation: \"DELETE\",\n table,\n data: { id, softDelete: true },\n timestamp: new Date(),\n });\n }\n\n const result = await this.adapter.delete(table, id);\n\n if (result.success && this.eventHandlers?.onAfterWrite) {\n await this.eventHandlers.onAfterWrite({\n type: \"afterWrite\",\n operation: \"DELETE\",\n table,\n result: { softDeleted: true },\n duration: 0,\n timestamp: new Date(),\n });\n }\n\n return result;\n } catch (error) {\n return failure(\n new DatabaseError(\n `Soft delete operation failed: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.DELETE_FAILED,\n {\n context: { source: \"softDelete\" },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n get events(): DatabaseEventEmitter {\n return this.eventEmitter;\n }\n\n /**\n * 🔌 Close the database connection\n *\n * Gracefully shuts down the database connection and releases all resources.\n * Should be called when the service is no longer needed.\n *\n * @returns Promise resolving to DatabaseResult indicating success or failure\n */\n async close(): Promise<DatabaseResult<void>> {\n try {\n if (this.adapter.close) {\n return await this.adapter.close();\n }\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to close database connection: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.DISCONNECT_FAILED,\n {\n context: { source: \"close\" },\n cause: error as Error,\n },\n ),\n );\n }\n }\n}\n","/**\n * @fileoverview Pagination Utilities for @plyaz/db package\n *\n * This module provides pagination calculation utilities used across all database adapters\n * to generate consistent pagination metadata for query results. Supports offset-based\n * pagination with page calculation and validation.\n *\n * Part of the @plyaz/db package - a TypeScript database abstraction layer with\n * support for multiple adapters (Drizzle, Supabase, SQL), extensions (audit, encryption,\n * soft delete), and advanced features (caching, read replicas, multi-tenancy).\n *\n * @module pagination\n */\n\nimport type { PaginationInfo, PaginationOptions } from \"@plyaz/types\";\nimport { isNumber } from \"./typeGuards\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\n\n/**\n * Validates pagination input parameters for safety and consistency\n *\n * Performs comprehensive validation of pagination parameters to prevent invalid\n * calculations and ensure consistent behavior across all database adapters.\n *\n * **Validation Rules:**\n * - Total must be a non-negative number (>= 0)\n * - Limit must be a positive number (> 0) if provided\n * - Offset must be a non-negative number (>= 0)\n *\n * @private\n * @param {number} total - Total number of items in the dataset\n * @param {number} [limit] - Optional maximum number of items per page\n * @param {number} [offset] - Optional number of items to skip (default: 0)\n * @throws {Error} If any parameter fails validation\n *\n * @example\n * ```typescript\n * // Valid inputs\n * validatePaginationInputs(100, 20, 0); // ✓ Valid\n * validatePaginationInputs(0, 10, 0); // ✓ Valid (empty dataset)\n * validatePaginationInputs(50); // ✓ Valid (no pagination)\n *\n * // Invalid inputs\n * validatePaginationInputs(-1, 10, 0); // ✗ Throws: negative total\n * validatePaginationInputs(100, 0, 0); // ✗ Throws: zero limit\n * validatePaginationInputs(100, 10, -5); // ✗ Throws: negative offset\n * ```\n *\n */\nfunction validatePaginationInputs(\n total: number,\n limit?: number,\n offset?: number,\n): void {\n // Total count validation\n // Must be non-negative to represent valid dataset size\n if (!isNumber(total) || total < 0) {\n throw new DatabaseError(\n \"Total must be a non-negative number\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"validatePaginationInputs\" },\n cause: new Error(\"Total must be a non-negative number\"),\n },\n );\n }\n\n // Limit validation (if provided)\n // Must be positive to create meaningful pages\n if (limit !== undefined && (!isNumber(limit) || limit <= 0)) {\n throw new DatabaseError(\n \"Limit must be a positive number\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"validatePaginationInputs\" },\n cause: new Error(\"Limit must be a positive number\"),\n },\n );\n }\n\n // Offset validation\n // Must be non-negative to represent valid starting position\n if (!isNumber(offset) || offset < 0) {\n throw new DatabaseError(\n \"Offset must be a non-negative number\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"validatePaginationInputs\" },\n cause: new Error(\"Offset must be a non-negative number\"),\n },\n );\n }\n}\n\n/**\n * Calculates comprehensive pagination metadata for database query results\n *\n * Generates pagination information used by all database adapters to provide\n * consistent pagination metadata in query results. Supports both paginated\n * and non-paginated queries with automatic page calculation.\n *\n * **Used by:**\n * - DrizzleAdapter.findMany() for ORM-based pagination\n * - SupabaseAdapter.findMany() for Supabase pagination\n * - SQLAdapter.findMany() for raw SQL pagination\n * - All repository methods that return paginated results\n *\n * **Calculation Logic:**\n * - Page numbers are 1-based (first page = 1)\n * - Current page = floor(offset / limit) + 1\n * - Total pages = ceil(total / limit)\n * - Handles edge cases (no limit, empty results, etc.)\n *\n * @param {number} total - Total number of items matching the query\n * @param {PaginationOptions} [options] - Optional pagination configuration\n * @param {number} [options.limit] - Maximum items per page\n * @param {number} [options.offset] - Number of items to skip (default: 0)\n * @returns {PaginationInfo} Complete pagination metadata object\n *\n * @example\n * ```typescript\n * import { calculatePagination } from '@plyaz/db/utils';\n *\n * // Standard pagination (page 2 of 20 items per page)\n * const pagination1 = calculatePagination(100, { limit: 20, offset: 20 });\n * console.log(pagination1);\n * // {\n * // page: 2,\n * // limit: 20,\n * // offset: 20,\n * // totalPages: 5\n * // }\n *\n * // First page\n * const pagination2 = calculatePagination(100, { limit: 20, offset: 0 });\n * console.log(pagination2);\n * // {\n * // page: 1,\n * // limit: 20,\n * // offset: 0,\n * // totalPages: 5\n * // }\n *\n * // No pagination (return all results)\n * const pagination3 = calculatePagination(100);\n * console.log(pagination3);\n * // {\n * // page: undefined,\n * // limit: undefined,\n * // offset: 0,\n * // totalPages: undefined\n * // }\n * ```\n *\n */\nexport function calculatePagination(\n total: number,\n options?: PaginationOptions,\n): PaginationInfo {\n const limit = options?.limit;\n const offset = options?.offset ?? 0;\n\n // Validate all inputs before calculation\n validatePaginationInputs(total, limit, offset);\n\n // Calculate current page (1-based indexing)\n // Only calculate if limit is provided and positive\n // Formula: floor(offset / limit) + 1\n // Example: offset=20, limit=10 → floor(20/10) + 1 = 3 (page 3)\n const page = limit && limit > 0 ? Math.floor(offset / limit) + 1 : undefined;\n\n // Calculate total number of pages\n // Only calculate if limit is provided and positive\n // Formula: ceil(total / limit)\n // Example: total=95, limit=10 → ceil(95/10) = 10 pages\n const totalPages = limit && limit > 0 ? Math.ceil(total / limit) : undefined;\n\n return {\n page,\n limit,\n offset,\n totalPages,\n };\n}\n","/**\n * @fileoverview Centralized Regex Patterns for @plyaz/db package\n *\n * This module contains all regex patterns used throughout the database package.\n * Centralizing regex patterns improves maintainability, reusability, and consistency.\n *\n * Part of the @plyaz/db package - a TypeScript database abstraction layer with\n * support for multiple adapters (Drizzle, Supabase, SQL), extensions (audit, encryption,\n * soft delete), and advanced features (caching, read replicas, multi-tenancy).\n *\n */\n\n/**\n * Database field and table name validation patterns\n * Used for SQL injection prevention and database identifier validation\n */\nexport const DATABASE_PATTERNS = {\n /**\n * Validates database field names (columns)\n * - Must start with letter (a-z, A-Z) or underscore (_)\n * - Can contain letters, numbers, and underscores\n * - Prevents SQL injection through field names\n *\n * Used in: validation.ts, sql.ts, DrizzleAdapter.ts, SQLAdapter.ts\n */\n FIELD_NAME: /^[a-zA-Z_][a-zA-Z0-9_]*$/,\n\n /**\n * Validates database table names\n * - Same rules as field names for consistency\n * - Follows SQL identifier naming conventions\n *\n * Used in: validation.ts, CacheEvict.decorator.ts\n */\n TABLE_NAME: /^[a-zA-Z_][a-zA-Z0-9_]*$/,\n} as const;\n\n/**\n * Cache key validation patterns\n * Used for validating cache keys and patterns in caching system\n */\nexport const CACHE_PATTERNS = {\n /**\n * Validates cache keys\n * - Allows letters, numbers, colons, underscores, and hyphens\n * - Used for Redis cache key validation\n *\n * Used in: CacheEvict.decorator.ts\n */\n CACHE_KEY: /^[a-zA-Z0-9:_-]+$/,\n\n /**\n * Validates cache patterns (with wildcards)\n * - Same as cache key but allows asterisk (*) for wildcards\n * - Used for cache pattern matching and eviction\n *\n * Used in: CacheEvict.decorator.ts\n */\n CACHE_PATTERN: /^[a-zA-Z0-9:_*-]+$/,\n} as const;\n\n/**\n * SQL query sanitization patterns\n * Used for cleaning and normalizing SQL queries for metrics and logging\n */\nexport const SQL_PATTERNS = {\n /**\n * Matches PostgreSQL parameter placeholders ($1, $2, etc.)\n * - Used to normalize parameterized queries for metrics\n *\n * Used in: MetricsCollector.ts\n */\n POSTGRES_PARAMS: /\\$\\d+/g,\n\n /**\n * Matches numeric values in SQL queries\n * - Used to replace numbers with placeholders for query normalization\n *\n * Used in: MetricsCollector.ts\n */\n NUMERIC_VALUES: /\\d+/g,\n\n /**\n * Matches string literals in SQL queries (single quotes)\n * - Used to replace string values with placeholders\n *\n * Used in: MetricsCollector.ts\n */\n STRING_LITERALS: /'[^']*'/g,\n} as const;\n\n/**\n * Input sanitization patterns\n * Used for cleaning user input and preventing injection attacks\n */\nexport const SANITIZATION_PATTERNS = {\n /**\n * Matches dangerous characters for SQL injection prevention\n * - Null byte, backspace, tab, newline, carriage return\n * - Single and double quotes, backslashes, percent signs\n *\n * Used in: validation.ts (sanitizeInput function)\n */\n DANGEROUS_CHARS: /[\\0\\b\\t\\n\\r\"'\\\\%]/g,\n\n /**\n * Matches shell metacharacters for command injection prevention\n * - Semicolon, ampersand, pipe, backtick, dollar, parentheses, etc.\n *\n * Used in: BackupService.ts (sanitizeCommand function)\n */\n SHELL_METACHARACTERS: /[;&|`$(){}[\\]<>\"'\\\\]/g,\n\n /**\n * Matches multiple whitespace characters\n * - Used to normalize whitespace in sanitized input\n *\n * Used in: BackupService.ts\n */\n MULTIPLE_WHITESPACE: /\\s+/g,\n\n /**\n * Matches line breaks and tabs\n * - Used to replace line breaks with spaces\n *\n * Used in: BackupService.ts\n */\n LINE_BREAKS_TABS: /[\\r\\n\\t]/g,\n\n /**\n * Matches Unicode control characters\n * - Uses Unicode property escape to match all control characters\n *\n * Used in: BackupService.ts\n */\n CONTROL_CHARACTERS: /[\\p{Cc}]/gu,\n} as const;\n\n/**\n * File and path patterns\n * Used for file operations and path validation\n */\nexport const FILE_PATTERNS = {\n /**\n * Matches colon and dot characters in timestamps\n * - Used to create filesystem-safe timestamps\n *\n * Used in: BackupService.ts (timestamp generation)\n */\n TIMESTAMP_CHARS: /[:.]/g,\n} as const;\n\n/**\n * Utility functions for common regex operations\n */\nexport const DB_REGEX = {\n /**\n * Tests if a string matches the database field name pattern\n * @param fieldName - The field name to validate\n * @returns True if valid database field name\n */\n isValidFieldName: (fieldName: string): boolean => {\n return DATABASE_PATTERNS.FIELD_NAME.test(fieldName);\n },\n\n /**\n * Tests if a string matches the database table name pattern\n * @param tableName - The table name to validate\n * @returns True if valid database table name\n */\n isValidTableName: (tableName: string): boolean => {\n return DATABASE_PATTERNS.TABLE_NAME.test(tableName);\n },\n\n /**\n * Tests if a string matches the cache key pattern\n * @param cacheKey - The cache key to validate\n * @returns True if valid cache key\n */\n isValidCacheKey: (cacheKey: string): boolean => {\n return CACHE_PATTERNS.CACHE_KEY.test(cacheKey);\n },\n\n /**\n * Tests if a string matches the cache pattern (with wildcards)\n * @param cachePattern - The cache pattern to validate\n * @returns True if valid cache pattern\n */\n isValidCachePattern: (cachePattern: string): boolean => {\n return CACHE_PATTERNS.CACHE_PATTERN.test(cachePattern);\n },\n\n /**\n * Normalizes SQL query by replacing parameters and values with placeholders\n * @param query - The SQL query to normalize\n * @returns Normalized query string\n */\n normalizeSqlQuery: (query: string): string => {\n return query\n .replace(SQL_PATTERNS.POSTGRES_PARAMS, \"?\")\n .replace(SQL_PATTERNS.NUMERIC_VALUES, \"?\")\n .replace(SQL_PATTERNS.STRING_LITERALS, \"?\");\n },\n\n /**\n * Sanitizes input by escaping dangerous characters\n * @param input - The input string to sanitize\n * @param escapeMap - Map of characters to their escaped equivalents\n * @returns Sanitized string\n */\n sanitizeDangerousChars: (\n input: string,\n escapeMap: Record<string, string>,\n ): string => {\n return input.replace(\n SANITIZATION_PATTERNS.DANGEROUS_CHARS,\n (char) => escapeMap[char] || char,\n );\n },\n\n /**\n * Creates filesystem-safe timestamp string\n * @param timestamp - ISO timestamp string\n * @returns Filesystem-safe timestamp\n */\n createSafeTimestamp: (timestamp: string): string => {\n return timestamp.replace(FILE_PATTERNS.TIMESTAMP_CHARS, \"-\");\n },\n\n /**\n * Sanitizes command string by removing shell metacharacters\n * @param command - Command string to sanitize\n * @returns Sanitized command string\n */\n sanitizeCommand: (command: string): string => {\n return command\n .replace(SANITIZATION_PATTERNS.SHELL_METACHARACTERS, \"\")\n .replace(SANITIZATION_PATTERNS.MULTIPLE_WHITESPACE, \" \")\n .trim();\n },\n\n /**\n * Sanitizes log message by normalizing whitespace and removing control characters\n * @param message - Log message to sanitize\n * @returns Sanitized log message\n */\n sanitizeLogMessage: (message: string): string => {\n return message\n .replace(SANITIZATION_PATTERNS.LINE_BREAKS_TABS, \" \")\n .replace(SANITIZATION_PATTERNS.CONTROL_CHARACTERS, \"\")\n .trim();\n },\n} as const;\n","import { drizzle } from \"drizzle-orm/node-postgres\";\nimport type { PoolClient } from \"pg\";\nimport { Pool } from \"pg\";\nimport type {\n Column,\n ColumnBaseConfig,\n ColumnDataType,\n SQL,\n SQLWrapper,\n} from \"drizzle-orm\";\nimport {\n eq,\n not,\n gte,\n gt,\n lte,\n lt,\n inArray,\n like,\n between,\n isNull,\n isNotNull,\n asc,\n desc,\n sql,\n} from \"drizzle-orm\";\nimport type { PgTable, PgSelectBase } from \"drizzle-orm/pg-core\";\nimport { PgColumn } from \"drizzle-orm/pg-core\";\nimport { calculatePagination } from \"@utils/pagination\";\nimport type {\n DrizzleAdapterConfig,\n DatabaseAdapterType,\n DatabaseResult,\n PaginatedResult,\n QueryOptions,\n DatabaseHealthStatus,\n Filter,\n Transaction,\n SortOptions,\n} from \"@plyaz/types/db\";\nimport { failure, success } from \"@utils/databaseResultHelpers\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { isNonEmptyString, isObject } from \"@utils/typeGuards\";\nimport { DATABASE_ERROR_CODES, type ErrorCodeValue } from \"@plyaz/types/errors\";\nimport { DB_REGEX } from \"@utils/regex\";\nimport type { BuildWhereClauseOptions } from \"@plyaz/types/db\";\n\n/** Minimum elements required for BETWEEN clause */\nconst BETWEEN_MIN_ELEMENTS = 2;\n\n/**\n * @class DrizzleAdapter\n * @implements {DatabaseAdapterType}\n * @classdesc\n * A PostgreSQL database adapter built on top of Drizzle ORM.\n * Provides generic CRUD operations, pagination, filtering, sorting,\n * and transactional support with a consistent result structure.\n */\nexport class DrizzleAdapter implements DatabaseAdapterType {\n private db: ReturnType<typeof drizzle>;\n private pool: Pool;\n private config: DrizzleAdapterConfig;\n private tableMap: Map<string, PgTable> = new Map();\n private idColumnMap: Map<string, PgColumn> = new Map();\n // String-based table registry for auto-registration (fallback when no PgTable schema)\n private stringTableMap: Map<string, string> = new Map();\n private stringIdColumnMap: Map<string, string> = new Map();\n private configIdColumns: Record<string, string>;\n\n /**\n * Creates a new DrizzleAdapter instance.\n * @param {DrizzleAdapterConfig} config - Configuration object for Drizzle and PostgreSQL connection.\n * @description\n * Initializes the adapter with the provided configuration, setting up the connection pool\n * and creating a Drizzle ORM instance. The configuration should include a connection string\n * and optional pool settings such as min/max connections and idle timeout.\n */\n constructor(config: DrizzleAdapterConfig) {\n this.config = config;\n this.pool = new Pool({\n connectionString: config.connectionString,\n ...config.pool,\n });\n this.db = drizzle(this.pool);\n // Store custom ID column mappings from config\n this.configIdColumns = config.tableIdColumns ?? {};\n }\n\n /**\n * Initializes the adapter by verifying database connectivity.\n * @returns {Promise<DatabaseResult<void>>} Success or failure result.\n * @description\n * Attempts to establish a connection to the database to verify that the adapter\n * can communicate with the database. This is typically called during application startup\n * to ensure the database is accessible before performing any operations.\n * Returns a success result if the connection is established, or a failure result with an error\n * if the connection cannot be established.\n */\n async initialize(): Promise<DatabaseResult<void>> {\n let client;\n try {\n client = await this.pool.connect();\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to initialize Drizzle adapter: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.INIT_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.initialize\",\n },\n cause: error as Error,\n },\n ),\n );\n } finally {\n if (client) {\n client.release();\n }\n }\n }\n\n /**\n * Opens a new connection to the database.\n * @returns {Promise<void>}\n * @description\n * Establishes a connection to the PostgreSQL database using the connection pool.\n * This method is called to ensure that a connection is available before performing database operations.\n * The connection pool manages the connections efficiently, reusing them when possible.\n */\n async connect(): Promise<void> {\n try {\n const client = await this.pool.connect();\n client.release();\n } catch (error) {\n throw new DatabaseError(\n `Failed to connect to database: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.CONNECT_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.connect\",\n },\n cause: error as Error,\n },\n );\n }\n }\n\n /**\n * Closes all open connections and shuts down the connection pool.\n * @returns {Promise<void>}\n * @description\n * Gracefully shuts down the connection pool, closing all active connections.\n * This method should be called when the adapter is no longer needed, typically during\n * application shutdown, to free up database resources and prevent connection leaks.\n */\n async disconnect(): Promise<void> {\n try {\n await this.pool.end();\n } catch (error) {\n throw new DatabaseError(\n `Failed to disconnect from database: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.DISCONNECT_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.disconnect\",\n },\n cause: error as Error,\n },\n );\n }\n }\n\n /**\n * Closes the database connection and cleanup resources.\n * @returns Promise resolving to DatabaseResult indicating success or failure.\n */\n async close(): Promise<DatabaseResult<void>> {\n try {\n await this.disconnect();\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to close connection: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.DISCONNECT_FAILED,\n ),\n );\n }\n }\n\n /**\n * Gets the underlying Drizzle client instance.\n * @returns {TClient} The internal Drizzle client.\n * @description\n * This method exposes the internal Drizzle client instance. Direct access is discouraged\n * to maintain abstraction and ensure all database operations go through the adapter’s\n * interface for error handling, logging, and event emission.\n */\n getClient<TClient extends object = object>(): TClient {\n return this.db as TClient;\n }\n\n /**\n * Executes a raw SQL query.\n * @template T - The expected type of the query result rows.\n * @param {string} sql - Raw SQL query string.\n * @param {T[]} [params] - Optional query parameters.\n * @returns {Promise<T[]>} Array of query result rows.\n * @throws {DatabaseError} When query execution fails.\n * @description\n * Executes a raw SQL query against the database, with optional parameterization.\n * This method is useful for complex queries that cannot be easily expressed using the ORM\n * or for database-specific operations. The method uses parameterized queries to prevent\n * SQL injection attacks. If the query execution fails, a DatabaseError is thrown.\n */\n async query<T>(sql: string, params?: T[]): Promise<T[]> {\n try {\n // Validate SQL to prevent injection\n if (!isNonEmptyString(sql)) {\n throw new DatabaseError(\n \"Invalid SQL query\",\n DATABASE_ERROR_CODES.INVALID_SQL,\n );\n }\n\n const result = await this.pool.query(sql, params);\n return result.rows as T[];\n } catch (error) {\n throw new DatabaseError(\n `Failed to execute query: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.query\",\n },\n cause: error as Error,\n },\n );\n }\n }\n\n /**\n * Registers a table and optional ID column for ORM operations.\n * @template TTable - Type representing the table structure (PgTable or string).\n * @template TIdColumn - Type representing the ID column (PgColumn or string).\n * @param {string} name - Logical name of the table.\n * @param {TTable} table - Drizzle table object (PgTable) or string table name.\n * @param {TIdColumn} [idColumn] - Optional primary key column (PgColumn or string).\n * @description\n * Registers a table with the adapter, allowing it to be referenced by a logical name\n * in subsequent operations. This is necessary for the adapter to perform ORM operations\n * on the table. The ID column can also be specified if it differs from the default 'id'.\n *\n * **Supports two modes:**\n * 1. **PgTable mode**: Pass Drizzle schema objects for type-safe ORM operations\n * 2. **String mode**: Pass string table names for raw SQL fallback (auto-registration)\n *\n * This registration enables the adapter to map logical table names to actual table objects\n * and ID columns, providing a layer of abstraction between the application and the database schema.\n */\n registerTable<TTable, TIdColumn>(\n name: string,\n table: TTable,\n idColumn?: TIdColumn,\n ): void {\n try {\n if (!isNonEmptyString(name)) {\n throw new DatabaseError(\n \"Invalid table name\",\n DATABASE_ERROR_CODES.INVALID_TABLE_NAME,\n );\n }\n\n // Check if table is a PgTable (Drizzle schema) or a string (raw SQL mode)\n if (typeof table === \"string\") {\n // String mode: register for raw SQL operations\n this.stringTableMap.set(name, table);\n if (idColumn && typeof idColumn === \"string\") {\n this.stringIdColumnMap.set(name, idColumn);\n }\n } else {\n // PgTable mode: register for Drizzle ORM operations\n this.tableMap.set(name, table as PgTable);\n if (idColumn) {\n this.idColumnMap.set(name, idColumn as TIdColumn as PgColumn);\n }\n }\n } catch (error) {\n throw new DatabaseError(\n `Failed to register table: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.TABLE_REGISTRATION_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.registerTable\",\n },\n cause: error as Error,\n },\n );\n }\n }\n\n /**\n * Execute raw SQL findById query\n */\n private async rawSqlFindById<T>(\n table: string,\n id: string,\n ): Promise<T | null> {\n const tableName = this.getStringTableName(table);\n const idColumn = this.getStringIdColumn(table);\n const sqlQuery = `SELECT * FROM \"${tableName}\" WHERE \"${idColumn}\" = $1 LIMIT 1`;\n const result = await this.pool.query(sqlQuery, [id]);\n return (result.rows[0] as T) || null;\n }\n\n /**\n * Finds a record by its primary ID.\n * @template T - The expected type of the record.\n * @param {string} table - Table name.\n * @param {string} id - Record ID.\n * @returns {Promise<DatabaseResult<T | null>>} Found record or null.\n * @description\n * Retrieves a single record from the specified table using its primary ID.\n * The method uses the registered table and ID column to construct the query.\n * If the record is found, it is returned in a success result. If no record is found,\n * null is returned in a success result. If an error occurs during the operation,\n * a failure result with an error message is returned.\n *\n * **Auto-registers tables**: If table is not registered with PgTable schema,\n * falls back to raw SQL mode (same behavior as SQLAdapter).\n */\n async findById<T>(\n table: string,\n id: string,\n ): Promise<DatabaseResult<T | null>> {\n try {\n // Check if we should use raw SQL mode\n if (this.isStringMode(table)) {\n return success(await this.rawSqlFindById<T>(table, id));\n }\n\n // Use Drizzle ORM mode\n const tableObj = this.getTable(table);\n const idColumn = this.getIdColumn(table);\n const result = await this.db\n .select()\n .from(tableObj)\n .where(eq(idColumn, id))\n .limit(1);\n return success((result[0] as T) || null);\n } catch (error) {\n // If error is USE_STRING_MODE, retry with raw SQL\n if (\n error instanceof DatabaseError &&\n error.message === \"USE_STRING_MODE\"\n ) {\n return this.handleStringModeFallback<T | null>(\n () => this.rawSqlFindById<T>(table, id),\n table,\n \"DrizzleAdapter.findById\",\n DATABASE_ERROR_CODES.FIND_BY_ID_FAILED,\n );\n }\n return failure(\n new DatabaseError(\n `Failed to find by id in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.FIND_BY_ID_FAILED,\n {\n context: { source: \"DrizzleAdapter.findById\" },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Handle USE_STRING_MODE fallback with error wrapping\n */\n private async handleStringModeFallback<T>(\n operation: () => Promise<T>,\n table: string,\n source: string,\n errorCode: ErrorCodeValue,\n ): Promise<DatabaseResult<T>> {\n try {\n return success(await operation());\n } catch (sqlError) {\n return failure(\n new DatabaseError(\n `Failed operation on table ${table}: ${(sqlError as Error).message}`,\n errorCode,\n {\n context: { source },\n cause: sqlError as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Retrieves multiple records with optional filtering, sorting, and pagination.\n * @template T - The expected type of the records.\n * @param {string} table - Table name.\n * @param {QueryOptions} [options] - Optional filter, sort, and pagination options.\n * @returns {Promise<DatabaseResult<PaginatedResult<T>>>} Paginated result set.\n * @description\n * Retrieves multiple records from the specified table with support for filtering,\n * sorting, and pagination. The method first applies any filters to narrow down the result set,\n * then applies sorting to order the results, and finally applies pagination to limit the number\n * of records returned. The result includes the data array, total count of matching records,\n * and pagination metadata such as current page, total pages, and next/previous cursors.\n * If an error occurs during the operation, a failure result with an error message is returned.\n *\n * **Auto-registers tables**: If table is not registered with PgTable schema,\n * falls back to raw SQL mode (same behavior as SQLAdapter).\n */\n\n // eslint-disable-next-line complexity\n async findMany<T extends Record<string, unknown>>(\n table: string,\n options?: QueryOptions<T>,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n try {\n // Check if we should use raw SQL mode\n if (this.isStringMode(table)) {\n return this.findManyRawSql<T>(table, options);\n }\n\n const tableObj = this.getTable(table);\n\n let query: PgSelectBase<\n string,\n Record<string, PgColumn>,\n \"single\",\n Record<string, \"not-null\">,\n false\n > = this.db.select().from(tableObj);\n\n // Apply sorting\n if (options?.sort) {\n query = this.applySorting(query as never, options.sort, tableObj);\n }\n // Apply filters\n if (options?.filter) {\n const whereClause = this.buildWhereClause(options.filter, tableObj);\n if (whereClause) {\n query = query.where(whereClause) as typeof query;\n }\n }\n\n // Get total count\n let countQuery = this.db\n .select({ count: sql<number>`count(*)::int`.as(\"count\") })\n .from(tableObj);\n if (options?.filter) {\n const whereClause = this.buildWhereClause(options.filter, tableObj);\n if (whereClause)\n countQuery = countQuery.where(whereClause) as typeof countQuery;\n }\n\n const countResult = await countQuery;\n const total = Number(countResult[0].count);\n\n // Apply pagination\n if (options?.pagination) {\n if (options.pagination.offset !== undefined) {\n query = query.offset(options.pagination.offset) as typeof query;\n }\n if (options.pagination.limit !== undefined) {\n query = query.limit(options.pagination.limit) as typeof query;\n }\n }\n\n const data = await query;\n return success({\n data: data as T[],\n total,\n pagination: calculatePagination(total, options?.pagination),\n });\n } catch (error) {\n // If error is USE_STRING_MODE, retry with raw SQL\n if (\n error instanceof DatabaseError &&\n error.message === \"USE_STRING_MODE\"\n ) {\n return this.findManyRawSql<T>(table, options);\n }\n return failure(\n new DatabaseError(\n `Failed to find many in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.FIND_MANY_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.findMany\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Raw SQL fallback for findMany when no PgTable schema is registered.\n * @private\n */\n // eslint-disable-next-line complexity\n private async findManyRawSql<T extends Record<string, unknown>>(\n table: string,\n options?: QueryOptions<T>,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n try {\n const tableName = this.getStringTableName(table);\n const params: unknown[] = [];\n let whereClause = \"\";\n let paramIndex = 1;\n\n // Build WHERE clause\n if (options?.filter) {\n const { field, operator, value } = options.filter;\n whereClause = this.buildSqlWhereClause({\n field,\n operator,\n value,\n params,\n startIndex: paramIndex,\n });\n paramIndex = params.length + 1;\n }\n\n // Count total\n const countSql = `SELECT COUNT(*) as total FROM \"${tableName}\"${whereClause}`;\n const countResult = await this.pool.query(countSql, params);\n const total = Number.parseInt(countResult.rows[0].total);\n\n // ORDER BY clause\n let orderClause = \"\";\n if (options?.sort?.length) {\n orderClause =\n \" ORDER BY \" +\n options.sort\n .map((s) => `\"${s.field}\" ${s.direction.toUpperCase()}`)\n .join(\", \");\n }\n\n // Build main query params (need to copy for separate query)\n const queryParams = [...params];\n\n // LIMIT & OFFSET\n let limitClause = \"\";\n if (options?.pagination?.limit) {\n limitClause += ` LIMIT $${paramIndex++}`;\n queryParams.push(options.pagination.limit);\n }\n if (options?.pagination?.offset) {\n limitClause += ` OFFSET $${paramIndex++}`;\n queryParams.push(options.pagination.offset);\n }\n\n // Final query\n const sqlQuery = `SELECT * FROM \"${tableName}\"${whereClause}${orderClause}${limitClause}`;\n const result = await this.pool.query(sqlQuery, queryParams);\n\n return success({\n data: result.rows as T[],\n total,\n pagination: calculatePagination(total, options?.pagination),\n });\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to find many in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.FIND_MANY_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.findManyRawSql\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Builds a SQL WHERE clause string for raw SQL queries.\n * @private\n */\n // eslint-disable-next-line complexity\n private buildSqlWhereClause(options: BuildWhereClauseOptions): string {\n const { field, operator, value, params, startIndex } = options;\n let clause = \"\";\n\n switch (operator) {\n case \"eq\":\n clause = ` WHERE \"${field}\" = $${startIndex}`;\n params.push(value);\n break;\n case \"ne\":\n clause = ` WHERE \"${field}\" != $${startIndex}`;\n params.push(value);\n break;\n case \"gt\":\n clause = ` WHERE \"${field}\" > $${startIndex}`;\n params.push(value);\n break;\n case \"gte\":\n clause = ` WHERE \"${field}\" >= $${startIndex}`;\n params.push(value);\n break;\n case \"lt\":\n clause = ` WHERE \"${field}\" < $${startIndex}`;\n params.push(value);\n break;\n case \"lte\":\n clause = ` WHERE \"${field}\" <= $${startIndex}`;\n params.push(value);\n break;\n case \"in\":\n if (Array.isArray(value)) {\n const placeholders = value\n .map((_, i) => `$${startIndex + i}`)\n .join(\", \");\n clause = ` WHERE \"${field}\" IN (${placeholders})`;\n params.push(...value);\n }\n break;\n case \"like\":\n clause = ` WHERE \"${field}\" LIKE $${startIndex}`;\n params.push(value);\n break;\n case \"between\":\n if (Array.isArray(value) && value.length >= BETWEEN_MIN_ELEMENTS) {\n clause = ` WHERE \"${field}\" BETWEEN $${startIndex} AND $${startIndex + 1}`;\n params.push(value[0], value[1]);\n }\n break;\n case \"isNull\":\n clause = ` WHERE \"${field}\" IS NULL`;\n break;\n case \"isNotNull\":\n clause = ` WHERE \"${field}\" IS NOT NULL`;\n break;\n default:\n break;\n }\n\n return clause;\n }\n\n /**\n * Inserts a new record into the specified table.\n * @template T - The expected type of the record.\n * @param {string} table - Table name.\n * @param {T} data - Record to insert.\n * @returns {Promise<DatabaseResult<T>>} Inserted record.\n * @description\n * Inserts a new record into the specified table using the provided data.\n * The method uses the registered table to construct the insert query.\n * After insertion, it returns the inserted record with any auto-generated fields\n * (like IDs) populated. If an error occurs during the operation,\n * a failure result with an error message is returned.\n *\n * **Auto-registers tables**: If table is not registered with PgTable schema,\n * falls back to raw SQL mode (same behavior as SQLAdapter).\n */\n async create<T>(table: string, data: T): Promise<DatabaseResult<T>> {\n try {\n // Check if we should use raw SQL mode\n if (this.isStringMode(table)) {\n return this.createRawSql<T>(table, data);\n }\n\n const tableObj = this.getTable(table);\n const result = await this.db\n .insert(tableObj)\n .values(data as Record<string, T>)\n .returning();\n return success(result[0] as T);\n } catch (error) {\n // If error is USE_STRING_MODE, retry with raw SQL\n if (\n error instanceof DatabaseError &&\n error.message === \"USE_STRING_MODE\"\n ) {\n return this.createRawSql<T>(table, data);\n }\n return failure(\n new DatabaseError(\n `Failed to create in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.CREATE_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.create\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Raw SQL fallback for create when no PgTable schema is registered.\n * @private\n */\n private async createRawSql<T>(\n table: string,\n data: T,\n ): Promise<DatabaseResult<T>> {\n try {\n const tableName = this.getStringTableName(table);\n const keys = Object.keys(data as Record<string, unknown>);\n const values = Object.values(data as Record<string, unknown>);\n const placeholders = values.map((_, i) => `$${i + 1}`).join(\", \");\n const escapedKeys = keys.map((k) => `\"${k}\"`).join(\", \");\n\n const sqlQuery = `INSERT INTO \"${tableName}\" (${escapedKeys}) VALUES (${placeholders}) RETURNING *`;\n const result = await this.pool.query(sqlQuery, values);\n\n return success(result.rows[0] as T);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to create in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.CREATE_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.createRawSql\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Updates an existing record by ID.\n * @template T - The expected type of the record.\n * @param {string} table - Table name.\n * @param {string} id - Record ID.\n * @param {Partial<T>} data - Partial object containing fields to update.\n * @returns {Promise<DatabaseResult<T>>} Updated record.\n * @description\n * Updates an existing record in the specified table using its primary ID.\n * Only the fields provided in the data object are updated, allowing for partial updates.\n * The method uses the registered table and ID column to construct the update query.\n * After updating, it returns the updated record. If an error occurs during the operation,\n * a failure result with an error message is returned.\n *\n * **Auto-registers tables**: If table is not registered with PgTable schema,\n * falls back to raw SQL mode (same behavior as SQLAdapter).\n */\n async update<T>(\n table: string,\n id: string,\n data: Partial<T>,\n ): Promise<DatabaseResult<T>> {\n try {\n // Check if we should use raw SQL mode\n if (this.isStringMode(table)) {\n return this.updateRawSql<T>(table, id, data);\n }\n\n const tableObj = this.getTable(table);\n const idColumn = this.getIdColumn(table);\n const result = await this.db\n .update(tableObj)\n .set(data as Record<string, T>)\n .where(eq(idColumn, id))\n .returning();\n return success(result[0] as T);\n } catch (error) {\n // If error is USE_STRING_MODE, retry with raw SQL\n if (\n error instanceof DatabaseError &&\n error.message === \"USE_STRING_MODE\"\n ) {\n return this.updateRawSql<T>(table, id, data);\n }\n return failure(\n new DatabaseError(\n `Failed to update in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.UPDATE_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.update\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Raw SQL fallback for update when no PgTable schema is registered.\n * @private\n */\n private async updateRawSql<T>(\n table: string,\n id: string,\n data: Partial<T>,\n ): Promise<DatabaseResult<T>> {\n try {\n const tableName = this.getStringTableName(table);\n const idColumn = this.getStringIdColumn(table);\n const keys = Object.keys(data as Record<string, unknown>);\n const values = Object.values(data as Record<string, unknown>);\n const setClause = keys.map((key, i) => `\"${key}\" = $${i + 1}`).join(\", \");\n\n const sqlQuery = `UPDATE \"${tableName}\" SET ${setClause} WHERE \"${idColumn}\" = $${keys.length + 1} RETURNING *`;\n const result = await this.pool.query(sqlQuery, [...values, id]);\n\n return success(result.rows[0] as T);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to update in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.UPDATE_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.updateRawSql\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Deletes a record by ID.\n * @param {string} table - Table name.\n * @param {string} id - Record ID.\n * @returns {Promise<DatabaseResult<void>>}\n * @description\n * Deletes a record from the specified table using its primary ID.\n * The method uses the registered table and ID column to construct the delete query.\n * If the operation is successful, it returns a success result with no value.\n * If an error occurs during the operation, a failure result with an error message is returned.\n *\n * **Auto-registers tables**: If table is not registered with PgTable schema,\n * falls back to raw SQL mode (same behavior as SQLAdapter).\n */\n async delete(table: string, id: string): Promise<DatabaseResult<void>> {\n try {\n // Check if we should use raw SQL mode\n if (this.isStringMode(table)) {\n return this.deleteRawSql(table, id);\n }\n\n const tableObj = this.getTable(table);\n const idColumn = this.getIdColumn(table);\n await this.db.delete(tableObj).where(eq(idColumn, id));\n return success();\n } catch (error) {\n // If error is USE_STRING_MODE, retry with raw SQL\n if (\n error instanceof DatabaseError &&\n error.message === \"USE_STRING_MODE\"\n ) {\n return this.deleteRawSql(table, id);\n }\n return failure(\n new DatabaseError(\n `Failed to delete from table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.DELETE_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.delete\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Raw SQL fallback for delete when no PgTable schema is registered.\n * @private\n */\n private async deleteRawSql(\n table: string,\n id: string,\n ): Promise<DatabaseResult<void>> {\n try {\n const tableName = this.getStringTableName(table);\n const idColumn = this.getStringIdColumn(table);\n const sqlQuery = `DELETE FROM \"${tableName}\" WHERE \"${idColumn}\" = $1`;\n await this.pool.query(sqlQuery, [id]);\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to delete from table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.DELETE_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.deleteRawSql\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Executes a transactional operation with rollback on failure.\n * @template T - The expected type of the transaction result.\n * @param {(trx: Transaction) => Promise<T>} callback - Function executed within a transaction.\n * @returns {Promise<DatabaseResult<T>>} Transaction result.\n * @description\n * Executes a callback function within a database transaction, providing atomicity.\n * If the callback function executes successfully, the transaction is committed.\n * If an error occurs during the execution of the callback function, the transaction\n * is rolled back, ensuring that no partial changes are applied to the database.\n * The method returns the result of the callback function if successful,\n * or a failure result with an error message if an error occurs.\n *\n * **Auto-registers tables**: Transaction operations use raw SQL mode for unregistered tables.\n */\n async transaction<T>(\n callback: (trx: Transaction) => Promise<T>,\n ): Promise<DatabaseResult<T>> {\n const client: PoolClient = await this.pool.connect();\n try {\n await client.query(\"BEGIN\");\n const trxDb = drizzle(client);\n\n // Transaction operations that support both PgTable and raw SQL modes\n const trx: Transaction = {\n findById: async <T>(table: string, id: string) => {\n // Use raw SQL for unregistered tables\n if (this.isStringMode(table)) {\n const tableName = this.getStringTableName(table);\n const idColumn = this.getStringIdColumn(table);\n const sqlQuery = `SELECT * FROM \"${tableName}\" WHERE \"${idColumn}\" = $1 LIMIT 1`;\n const result = await client.query(sqlQuery, [id]);\n return success((result.rows[0] as T) || null);\n }\n const tableObj = this.getTable(table);\n const idColumn = this.getIdColumn(table);\n const result = await trxDb\n .select()\n .from(tableObj)\n .where(eq(idColumn, id))\n .limit(1);\n return success((result[0] as T) || null);\n },\n create: async <T>(table: string, data: T) => {\n // Use raw SQL for unregistered tables\n if (this.isStringMode(table)) {\n const tableName = this.getStringTableName(table);\n const keys = Object.keys(data as Record<string, unknown>);\n const values = Object.values(data as Record<string, unknown>);\n const placeholders = values.map((_, i) => `$${i + 1}`).join(\", \");\n const escapedKeys = keys.map((k) => `\"${k}\"`).join(\", \");\n const sqlQuery = `INSERT INTO \"${tableName}\" (${escapedKeys}) VALUES (${placeholders}) RETURNING *`;\n const result = await client.query(sqlQuery, values);\n return success(result.rows[0] as T);\n }\n const tableObj = this.getTable(table);\n const result = await trxDb\n .insert(tableObj)\n .values(data as Record<string, T>)\n .returning();\n return success(result[0] as T);\n },\n update: async <T>(table: string, id: string, data: Partial<T>) => {\n // Use raw SQL for unregistered tables\n if (this.isStringMode(table)) {\n const tableName = this.getStringTableName(table);\n const idColumn = this.getStringIdColumn(table);\n const keys = Object.keys(data as Record<string, unknown>);\n const values = Object.values(data as Record<string, unknown>);\n const setClause = keys\n .map((key, i) => `\"${key}\" = $${i + 1}`)\n .join(\", \");\n const sqlQuery = `UPDATE \"${tableName}\" SET ${setClause} WHERE \"${idColumn}\" = $${keys.length + 1} RETURNING *`;\n const result = await client.query(sqlQuery, [...values, id]);\n return success(result.rows[0] as T);\n }\n const tableObj = this.getTable(table);\n const idColumn = this.getIdColumn(table);\n const result = await trxDb\n .update(tableObj)\n .set(data as Record<string, T>)\n .where(eq(idColumn, id))\n .returning();\n return success(result[0] as T);\n },\n delete: async (table: string, id: string) => {\n // Use raw SQL for unregistered tables\n if (this.isStringMode(table)) {\n const tableName = this.getStringTableName(table);\n const idColumn = this.getStringIdColumn(table);\n const sqlQuery = `DELETE FROM \"${tableName}\" WHERE \"${idColumn}\" = $1`;\n await client.query(sqlQuery, [id]);\n return success();\n }\n const tableObj = this.getTable(table);\n const idColumn = this.getIdColumn(table);\n await trxDb.delete(tableObj).where(eq(idColumn, id));\n return success();\n },\n commit: async () => {\n await client.query(\"COMMIT\");\n },\n rollback: async () => {\n await client.query(\"ROLLBACK\");\n },\n };\n\n const result = await callback(trx);\n await trx.commit();\n return success(result);\n } catch (error) {\n await client.query(\"ROLLBACK\");\n return failure(\n new DatabaseError(\n `Transaction failed: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.TRANSACTION_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.transaction\",\n },\n cause: error as Error,\n },\n ),\n );\n } finally {\n client.release();\n }\n }\n\n /**\n * Checks if a record exists by ID.\n * @param {string} table - Table name.\n * @param {string} id - Record ID.\n * @returns {Promise<DatabaseResult<boolean>>} True if exists, otherwise false.\n * @description\n * Checks if a record with the specified ID exists in the table.\n * The method uses the registered table and ID column to construct the query.\n * It returns a success result with a boolean value indicating whether the record exists.\n * If an error occurs during the operation, a failure result with an error message is returned.\n *\n * **Auto-registers tables**: If table is not registered with PgTable schema,\n * falls back to raw SQL mode (same behavior as SQLAdapter).\n */\n async exists(table: string, id: string): Promise<DatabaseResult<boolean>> {\n try {\n // Check if we should use raw SQL mode\n if (this.isStringMode(table)) {\n const tableName = this.getStringTableName(table);\n const idColumn = this.getStringIdColumn(table);\n const sqlQuery = `SELECT 1 FROM \"${tableName}\" WHERE \"${idColumn}\" = $1 LIMIT 1`;\n const result = await this.pool.query(sqlQuery, [id]);\n return success(result.rows.length > 0);\n }\n\n const tableObj = this.getTable(table);\n const idColumn = this.getIdColumn(table);\n const result = await this.db\n .select({ exists: sql`1` })\n .from(tableObj)\n .where(eq(idColumn, id))\n .limit(1);\n return success(!!result.length);\n } catch (error) {\n // If error is USE_STRING_MODE, retry with raw SQL\n if (\n error instanceof DatabaseError &&\n error.message === \"USE_STRING_MODE\"\n ) {\n const tableName = this.getStringTableName(table);\n const idColumn = this.getStringIdColumn(table);\n const sqlQuery = `SELECT 1 FROM \"${tableName}\" WHERE \"${idColumn}\" = $1 LIMIT 1`;\n const result = await this.pool.query(sqlQuery, [id]);\n return success(result.rows.length > 0);\n }\n return failure(\n new DatabaseError(\n `Failed to check existence in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.EXISTS_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.exists\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Counts records matching an optional filter.\n * @param {string} table - Table name.\n * @param {Filter} [filter] - Optional filter object.\n * @returns {Promise<DatabaseResult<number>>} Total count of matching records.\n * @description\n * Counts the number of records in the specified table that match the optional filter.\n * The method uses the registered table to construct the count query.\n * If a filter is provided, it is applied to narrow down the count to matching records.\n * It returns a success result with the count of matching records.\n * If an error occurs during the operation, a failure result with an error message is returned.\n *\n * **Auto-registers tables**: If table is not registered with PgTable schema,\n * falls back to raw SQL mode (same behavior as SQLAdapter).\n */\n async count<T extends Record<string, unknown> = Record<string, unknown>>(\n table: string,\n filter?: Filter<T>,\n ): Promise<DatabaseResult<number>> {\n try {\n // Check if we should use raw SQL mode\n if (this.isStringMode(table)) {\n return this.countRawSql(table, filter);\n }\n\n const tableObj = this.getTable(table);\n\n const baseQuery = this.db\n .select({ count: sql<number>`count(*)::int` })\n .from(tableObj);\n\n const query =\n filter && this.buildWhereClause(filter, tableObj)\n ? baseQuery.where(this.buildWhereClause(filter, tableObj) as SQL)\n : baseQuery;\n\n const result = await query;\n const countValue = result.length > 0 ? result[0].count : 0;\n\n return success(Number(countValue));\n } catch (error) {\n // If error is USE_STRING_MODE, retry with raw SQL\n if (\n error instanceof DatabaseError &&\n error.message === \"USE_STRING_MODE\"\n ) {\n return this.countRawSql(table, filter);\n }\n return failure(\n new DatabaseError(\n `Failed to count in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.COUNT_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.count\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Raw SQL fallback for count when no PgTable schema is registered.\n * @private\n */\n private async countRawSql<T extends Record<string, unknown>>(\n table: string,\n filter?: Filter<T>,\n ): Promise<DatabaseResult<number>> {\n try {\n const tableName = this.getStringTableName(table);\n const params: unknown[] = [];\n let whereClause = \"\";\n\n if (filter) {\n const { field, operator, value } = filter;\n whereClause = this.buildSqlWhereClause({\n field,\n operator,\n value,\n params,\n startIndex: 1,\n });\n }\n\n const sqlQuery = `SELECT COUNT(*) as count FROM \"${tableName}\"${whereClause}`;\n const result = await this.pool.query(sqlQuery, params);\n const rowCount = Number.parseInt(result.rows[0].count);\n return success(Number(rowCount));\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to count in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.COUNT_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.countRawSql\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Performs a health check on the database connection.\n * @returns {Promise<DatabaseResult<DatabaseHealthStatus>>} Health status with response time.\n * @description\n * Checks the health of the database connection by executing a simple query.\n * The method measures the response time of the query to determine the health status.\n * It returns a success result with a HealthStatus object indicating whether the database is healthy,\n * the response time of the health check, and any additional details.\n * If an error occurs during the operation, a failure result with an error message is returned.\n */\n async healthCheck(): Promise<DatabaseResult<DatabaseHealthStatus>> {\n const startTime = Date.now();\n try {\n await this.pool.query(\"SELECT 1\");\n const responseTime = Date.now() - startTime;\n return success({\n isHealthy: true,\n responseTime,\n details: { adapter: \"drizzle\" } as DatabaseHealthStatus[\"details\"],\n });\n } catch (error) {\n const responseTime = Date.now() - startTime;\n return success({\n isHealthy: false,\n responseTime,\n details: {\n adapter: \"drizzle\",\n error: (error as Error).message,\n } as DatabaseHealthStatus[\"details\"],\n });\n }\n }\n\n // --- Private Helpers ---\n\n /**\n * Checks if a table is registered in string mode (raw SQL fallback).\n * @private\n * @param {string} name - Table name.\n * @returns {boolean} True if table is registered in string mode.\n */\n private isStringMode(name: string): boolean {\n return this.stringTableMap.has(name) || !this.tableMap.has(name);\n }\n\n /**\n * Retrieves a registered table by name.\n * @private\n * @param {string} name - Table name.\n * @returns {PgTable} Table object.\n * @throws {DatabaseError} If table is not registered and cannot be auto-registered.\n * @description\n * Retrieves a table object that has been previously registered with the adapter.\n * If the table is not found in PgTable mode, it auto-registers in string mode\n * for raw SQL operations (same behavior as SQLAdapter).\n */\n private getTable(name: string): PgTable {\n try {\n if (!isNonEmptyString(name)) {\n throw new DatabaseError(\n \"Invalid table name\",\n DATABASE_ERROR_CODES.INVALID_TABLE_NAME,\n );\n }\n\n const table = this.tableMap.get(name);\n if (!table) {\n // Auto-register in string mode for raw SQL fallback\n if (!this.stringTableMap.has(name)) {\n this.stringTableMap.set(name, name);\n }\n // Return a placeholder - actual operations will use raw SQL\n throw new DatabaseError(\n \"USE_STRING_MODE\",\n DATABASE_ERROR_CODES.TABLE_NOT_REGISTERED,\n );\n }\n return table;\n } catch (error) {\n throw error instanceof DatabaseError\n ? error\n : new DatabaseError(\n \"Failed to get table\",\n DATABASE_ERROR_CODES.GET_TABLE_FAILED,\n );\n }\n }\n\n /**\n * Gets the string table name for raw SQL operations.\n * @private\n * @param {string} name - Logical table name.\n * @returns {string} Physical table name.\n */\n private getStringTableName(name: string): string {\n let tableName = this.stringTableMap.get(name);\n if (!tableName) {\n // Auto-register table with same name and check for custom ID column from config\n const customIdColumn = this.configIdColumns[name];\n if (customIdColumn) {\n this.stringIdColumnMap.set(name, customIdColumn);\n }\n this.stringTableMap.set(name, name);\n tableName = name;\n }\n return tableName;\n }\n\n /**\n * Gets the string ID column for raw SQL operations.\n * @private\n * @param {string} name - Logical table name.\n * @returns {string} ID column name (defaults to 'id').\n * @description\n * Retrieves the ID column for a table. Checks in this order:\n * 1. Runtime registered ID column (from registerTable calls)\n * 2. Config-provided ID column (from tableIdColumns in config)\n * 3. Default 'id' column\n */\n private getStringIdColumn(name: string): string {\n // Check runtime registered first\n const runtimeIdColumn = this.stringIdColumnMap.get(name);\n if (runtimeIdColumn) {\n return runtimeIdColumn;\n }\n\n // Check config-provided ID columns\n const configIdColumn = this.configIdColumns[name];\n if (configIdColumn) {\n return configIdColumn;\n }\n\n // Default to 'id'\n return \"id\";\n }\n\n /**\n * Retrieves the registered ID column for a table.\n * @private\n * @param {string} name - Table name.\n * @returns {PgColumn} ID column.\n * @throws {DatabaseError} If ID column is not registered.\n * @description\n * Retrieves the ID column that has been previously registered for a table.\n * This method is used internally by other methods to ensure that operations that require\n * the ID column can access it. If the ID column is not found, it throws a DatabaseError.\n */\n private getIdColumn(name: string): PgColumn {\n try {\n if (!isNonEmptyString(name)) {\n throw new DatabaseError(\n \"Invalid table name\",\n DATABASE_ERROR_CODES.INVALID_TABLE_NAME,\n );\n }\n\n const idColumn = this.idColumnMap.get(name);\n if (!idColumn) {\n throw new DatabaseError(\n \"ID column is not registered with the adapter\",\n DATABASE_ERROR_CODES.ID_COLUMN_NOT_REGISTERED,\n );\n }\n return idColumn;\n } catch (error) {\n throw error instanceof DatabaseError\n ? error\n : new DatabaseError(\n \"Failed to get ID column\",\n DATABASE_ERROR_CODES.GET_ID_COLUMN_FAILED,\n );\n }\n }\n\n /**\n * Builds a SQL `WHERE` clause based on filter operators.\n * @private\n * @param {Filter} filter - Filter definition.\n * @param {PgTable} table - Table to apply filter on.\n * @returns {SQL | undefined} SQL condition object.\n * @throws {DatabaseError} If column or operator is invalid.\n * @description\n * Builds a SQL WHERE clause based on the provided filter definition.\n * It supports various operators like equality, comparison, and null checks.\n * If the column specified in the filter does not exist in the table, or if the operator\n * is not supported, it throws a DatabaseError. The method returns an SQL object that\n * can be used in queries, or undefined if no valid clause can be constructed.\n */\n // eslint-disable-next-line complexity\n private buildWhereClause<T extends Record<string, unknown>>(\n filter: Filter<T>,\n table: PgTable,\n ): SQL | undefined {\n try {\n if (!isObject(filter)) {\n return undefined;\n }\n\n const { field, operator, value } = filter;\n\n // Validate field name\n if (!isNonEmptyString(field) || !DB_REGEX.isValidFieldName(field)) {\n throw new DatabaseError(\n \"Invalid field name\",\n DATABASE_ERROR_CODES.INVALID_FIELD_NAME,\n );\n }\n\n // Access column from table - field is validated at runtime\n const column = table[field as keyof typeof table] as Column<\n ColumnBaseConfig<ColumnDataType, string>\n >;\n if (!column) {\n throw new DatabaseError(\n \"Column does not exist in table\",\n DATABASE_ERROR_CODES.COLUMN_NOT_EXISTS,\n );\n }\n\n // Drizzle operators work with the column types directly\n switch (operator) {\n case \"eq\":\n return eq(column, value);\n case \"ne\":\n return not(eq(column, value));\n case \"gt\":\n return gt(column, value);\n case \"gte\":\n return gte(column, value);\n case \"lt\":\n return lt(column, value);\n case \"lte\":\n return lte(column, value);\n case \"in\":\n return inArray(column, value as unknown[]);\n case \"notIn\":\n return not(inArray(column, value as unknown[]));\n case \"like\":\n return like(column, value as string);\n case \"between\":\n return between(\n column,\n (value as [unknown, unknown])[0],\n (value as [unknown, unknown])[1],\n );\n case \"isNull\":\n return isNull(column);\n case \"isNotNull\":\n return isNotNull(column);\n default:\n throw new DatabaseError(\n \"Unsupported operator\",\n DATABASE_ERROR_CODES.UNSUPPORTED_OPERATOR,\n );\n }\n } catch (error) {\n throw new DatabaseError(\n \"Failed to build WHERE clause\",\n DATABASE_ERROR_CODES.BUILD_WHERE_FAILED,\n {\n context: {\n source: \"DrizzleAdapter.buildWhereClause\",\n },\n cause: error as Error,\n },\n );\n }\n }\n\n /**\n * Applies sorting to a query using provided field and direction.\n * @private\n * @template TQuery - Type of the query builder.\n * @template TTable - Type of the table.\n * @param {TQuery} query - Drizzle query builder.\n * @param {SortOptions[]} sort - Array of sort conditions.\n * @param {TTable} table - Target table.\n * @returns {TQuery} Modified query with applied sorting.\n * @throws {DatabaseError} If field is invalid or missing.\n * @description\n * Applies sorting to a Drizzle query based on the provided sort options.\n * It supports sorting by multiple fields in ascending or descending order.\n * If a field specified in the sort options does not exist in the table, or is not a valid column,\n * it throws a DatabaseError. The method returns the modified query with the sorting applied.\n */\n private applySorting<\n T extends Record<string, unknown>,\n TQuery extends {\n orderBy: (...columns: (SQL | SQLWrapper | PgColumn)[]) => TQuery;\n },\n TTable extends PgTable,\n >(query: TQuery, sort: SortOptions<T>[], table: TTable): TQuery {\n return sort.reduce((q, { field, direction }) => {\n if (!Object.prototype.hasOwnProperty.call(table, field)) {\n throw new DatabaseError(\n `Column ${field} does not exist in table`,\n DATABASE_ERROR_CODES.COLUMN_NOT_EXISTS,\n );\n }\n\n const key = field as keyof TTable;\n const column = table[key];\n\n if (!(column instanceof PgColumn)) {\n throw new DatabaseError(\n `Field ${field} is not a valid column`,\n DATABASE_ERROR_CODES.INVALID_COLUMN,\n );\n }\n\n return direction === \"asc\"\n ? q.orderBy(asc(column))\n : q.orderBy(desc(column));\n }, query);\n }\n}\n","import type {\n DatabaseAdapterType,\n DatabaseResult,\n PaginatedResult,\n QueryOptions,\n Filter,\n DatabaseHealthStatus,\n Transaction,\n SupabaseAdapterConfig,\n} from \"@plyaz/types/db\";\nimport type { SupabaseClient } from \"@supabase/supabase-js\";\nimport { createClient } from \"@supabase/supabase-js\";\nimport { failure, success } from \"@utils/databaseResultHelpers\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\n\nimport { calculatePagination } from \"@utils/pagination\";\nimport { NUMERIX } from \"@plyaz/config\";\n\n/**\n * @class SupabaseAdapter\n * @implements {DatabaseAdapterType}\n * @classdesc\n * Supabase adapter implementation for database operations.\n *\n * This adapter provides an interface to interact with Supabase databases,\n * supporting CRUD operations, transactions, and health checks. It leverages\n * the Supabase JavaScript client to communicate with PostgreSQL databases through\n * Supabase's API. The adapter provides a consistent interface while abstracting\n * away the specifics of Supabase's API calls.\n */\nexport class SupabaseAdapter implements DatabaseAdapterType {\n private client: SupabaseClient;\n private config: SupabaseAdapterConfig;\n private tableMap: Map<string, string> = new Map();\n private idColumnMap: Map<string, string> = new Map();\n private configIdColumns: Record<string, string>;\n\n /**\n * Creates a new SupabaseAdapter instance.\n * @param {SupabaseAdapterConfig} config - Configuration for the Supabase adapter.\n * @description\n * Initializes the adapter with the provided configuration, setting up the Supabase client.\n * The configuration must include a Supabase URL and either a service key or an anonymous key.\n * The adapter maintains internal maps for table names and ID columns to provide a level of\n * abstraction over the database schema. If required configuration values are missing,\n * the constructor throws a DatabaseError.\n * @throws {DatabaseError} If Supabase URL or key is not provided in the configuration.\n */\n constructor(config: SupabaseAdapterConfig) {\n this.config = config;\n // Store custom ID column mappings from config\n this.configIdColumns = config.tableIdColumns ?? {};\n\n if (!config.supabaseUrl) {\n throw new DatabaseError(\n \"Supabase URL is required for Supabase adapter\",\n DATABASE_ERROR_CODES.CONFIG_REQUIRED,\n );\n }\n\n const key = config.supabaseServiceKey ?? config.supabaseAnonKey;\n\n if (!key) {\n throw new DatabaseError(\n \"Supabase key is required for Supabase adapter\",\n DATABASE_ERROR_CODES.CONFIG_REQUIRED,\n );\n }\n\n this.client = createClient(config.supabaseUrl, key, {\n auth: {\n persistSession: false,\n autoRefreshToken: false,\n },\n db: {\n schema: (config.schema ?? \"public\") as \"public\",\n },\n });\n }\n\n /**\n * Initializes the Supabase database adapter.\n * @returns {Promise<DatabaseResult<void>>} A promise resolving to a DatabaseResult indicating\n * whether the initialization was successful or failed.\n * @description\n * Validates the Supabase database connection by invoking a simple predefined RPC function (`version`).\n * This method is typically executed during application startup to ensure the adapter can\n * successfully communicate with the database before performing any operations.\n *\n * The method calls the `version` RPC to confirm connectivity. If the RPC function is not defined,\n * it is treated as a non-critical error and the connection is still considered valid. Any other\n * errors are reported as initialization failures.\n */\n async initialize(): Promise<DatabaseResult<void>> {\n try {\n // Verify the database connection by invoking the predefined `version` RPC function.\n const { error } = await this.client.rpc(\"version\");\n\n // If the `version` RPC function does not exist, consider it non-critical — connection is verified.\n if (\n error &&\n !error.message.includes('function \"version\" does not exist')\n ) {\n return failure(\n new DatabaseError(\n `Failed to initialize Supabase adapter: ${error.message}`,\n DATABASE_ERROR_CODES.INIT_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.initialize\",\n },\n cause: error,\n },\n ),\n );\n }\n\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to initialize Supabase adapter: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.INIT_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.initialize\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Connect to the database.\n * @returns {Promise<void>} Promise that resolves when connected.\n * @description\n * Supabase handles connections automatically, so this method is a no-op.\n * The Supabase client manages connections internally, establishing them as needed\n * and handling connection pooling. This method is included for interface compatibility\n * but does not perform any connection operations.\n */\n async connect(): Promise<void> {\n // Supabase handles connections automatically\n }\n\n /**\n * Disconnect from the database.\n * @returns {Promise<void>} Promise that resolves when disconnected.\n * @description\n * Supabase handles disconnections automatically, so this method is a no-op.\n * The Supabase client manages connections internally, closing them when appropriate.\n * This method is included for interface compatibility but does not perform any\n * disconnection operations.\n */\n async disconnect(): Promise<void> {\n // Supabase handles disconnections automatically\n }\n\n /**\n * Closes the database connection and cleanup resources.\n * Supabase handles connections automatically, so this just returns success.\n * @returns Promise resolving to DatabaseResult indicating success.\n */\n async close(): Promise<DatabaseResult<void>> {\n await this.disconnect();\n return success();\n }\n\n /**\n * Gets the underlying Supabase client instance.\n * @template TClient - The type of the Supabase client to return.\n * @returns {TClient} The Supabase client instance cast to the specified client type.\n * @description\n * This method provides access to the underlying Supabase client.\n * Although direct access is technically possible, it is discouraged to maintain\n * abstraction and ensure that all database operations go through the adapter’s\n * interface for consistent error handling, logging, and event management.\n */\n getClient<TClient extends object = object>(): TClient {\n return this.client as TClient;\n }\n\n /**\n * Execute a raw SQL query.\n * @template T - The expected type of the query result rows.\n * @param {string} sql - SQL query string.\n * @param {T[]} [params] - Query parameters.\n * @returns {Promise<T[]>} Promise resolving to query results.\n * @description\n * Executes a raw SQL query against the database using Supabase's RPC function.\n * This method is useful for complex queries that cannot be easily expressed using the adapter's\n * built-in methods or for database-specific operations. The method uses parameterized queries\n * to prevent SQL injection attacks. If the query execution fails, a DatabaseError is thrown.\n * Note that this requires a custom RPC function named 'exec_sql' to be set up in your Supabase project.\n */\n async query<T>(sql: string, params?: T[]): Promise<T[]> {\n try {\n const { data, error } = await this.client.rpc(\"exec_sql\", {\n sql,\n params,\n });\n if (error)\n throw new DatabaseError(\n `Failed to execute query: ${sql} - ${error.message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.query\",\n },\n cause: error,\n },\n );\n return data as T[];\n } catch (error) {\n throw new DatabaseError(\n `Failed to execute query: ${sql} - ${(error as Error).message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.query\",\n },\n cause: error as Error,\n },\n );\n }\n }\n\n /**\n * Register a table with the adapter.\n * @template TTable - Type representing the table structure.\n * @template TIdColumn - Type representing the ID column.\n * @param {string} name - Logical name for the table.\n * @param {TTable} [table] - Actual table name (defaults to logical name if not provided).\n * @param {TIdColumn} [idColumn] - Optional ID column name.\n * @description\n * Registers a table with the adapter, allowing it to be referenced by a logical name\n * in subsequent operations. This is necessary for the adapter to perform operations\n * on the table. The ID column can also be specified if it differs from the default 'id'.\n * This registration enables the adapter to map logical table names to actual table names\n * and ID columns, providing a layer of abstraction between the application and the database schema.\n * If no table name is provided, the logical name is used as the actual table name.\n */\n registerTable<TTable, TIdColumn>(\n name: string,\n table?: TTable,\n idColumn?: TIdColumn,\n ): void {\n this.tableMap.set(name, (table as string) || name);\n if (idColumn) {\n this.idColumnMap.set(name, idColumn as string);\n }\n }\n\n /**\n * Find a single record by ID.\n * @template T - The expected type of the record.\n * @param {string} table - Table name.\n * @param {string} id - Record ID.\n * @returns {Promise<DatabaseResult<T | null>>} Promise resolving to DatabaseResult containing the record or null.\n * @description\n * Retrieves a single record from the specified table using its primary ID.\n * The method uses Supabase's select method with a filter for the ID column and\n * the single() method to retrieve exactly one record. If the record is found,\n * it is returned in a success result. If no record is found (indicated by error code PGRST116),\n * null is returned in a success result. If an error occurs during the operation,\n * a failure result with an error message is returned.\n */\n async findById<T>(\n table: string,\n id: string,\n ): Promise<DatabaseResult<T | null>> {\n try {\n const tableName = this.getTableName(table);\n const idColumn = this.idColumnMap.get(table) ?? \"id\";\n const { data, error } = await this.client\n .from(tableName)\n .select(\"*\")\n .eq(idColumn, id)\n .single();\n\n if (error) {\n if (error.code === \"PGRST116\") {\n return success();\n }\n return failure(\n new DatabaseError(\n `Failed to find by id in table ${table}: ${error.message}`,\n DATABASE_ERROR_CODES.FIND_BY_ID_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.findById\",\n },\n cause: error,\n },\n ),\n );\n }\n\n return success(data as T);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to find by id in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.FIND_BY_ID_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.findById\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Find multiple records with filtering and pagination.\n * @template T - The expected type of the records.\n * @param {string} table - Table name.\n * @param {QueryOptions} [options] - Query options including filters, sorting, and pagination.\n * @returns {Promise<DatabaseResult<PaginatedResult<T>>>} Promise resolving to DatabaseResult containing paginated data.\n * @description\n * Retrieves multiple records from the specified table with support for filtering,\n * sorting, and pagination. The method first executes a count query to get the\n * total number of matching records, then executes the main query with the applied filters,\n * sorting, and pagination. The result includes the data array, total count of matching records,\n * and pagination metadata such as current page, total pages, and limit.\n * If an error occurs during the operation, a failure result with an error message is returned.\n */\n // eslint-disable-next-line complexity\n async findMany<T extends Record<string, unknown>>(\n table: string,\n options?: QueryOptions<T>,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n try {\n const tableName = this.getTableName(table);\n let query = this.client.from(tableName).select(\"*\");\n\n // Apply filters if provided\n if (options?.filter) {\n query = this.applyFilter(query, options.filter);\n }\n\n // Get total count for pagination\n let countQuery = this.client\n .from(tableName)\n .select(\"*\", { count: \"exact\", head: true });\n if (options?.filter) {\n countQuery = this.applyFilter(countQuery, options.filter);\n }\n const { count, error: countError } = await countQuery;\n\n if (countError) {\n return failure(\n new DatabaseError(\n `Failed to count records in table ${table}: ${countError.message}`,\n DATABASE_ERROR_CODES.COUNT_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.findMany\",\n },\n cause: countError,\n },\n ),\n );\n }\n\n // Apply sorting if provided\n if (options?.sort) {\n options.sort.forEach((sortOption) => {\n query = query.order(sortOption.field, {\n ascending: sortOption.direction === \"asc\",\n });\n });\n }\n\n // Apply pagination if provided\n if (options?.pagination) {\n if (options.pagination.offset !== undefined) {\n query = query.range(\n options.pagination.offset,\n options.pagination.offset +\n (options.pagination.limit ?? NUMERIX.TEN) -\n 1,\n );\n } else if (options.pagination.limit !== undefined) {\n query = query.limit(options.pagination.limit);\n }\n }\n\n const { data, error } = await query;\n\n if (error) {\n return failure(\n new DatabaseError(\n `Failed to find many in table ${table}: ${error.message}`,\n DATABASE_ERROR_CODES.FIND_MANY_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.findMany\",\n },\n cause: error,\n },\n ),\n );\n }\n\n const total = count ?? 0;\n\n return success({\n data: data as T[],\n total,\n pagination: calculatePagination(total, options?.pagination),\n });\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to find many in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.FIND_MANY_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.findMany\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Create a new record.\n * @template T - The expected type of the record.\n * @param {string} table - Table name.\n * @param {T} data - Record data to create.\n * @returns {Promise<DatabaseResult<T>>} Promise resolving to DatabaseResult containing the created record.\n * @description\n * Inserts a new record into the specified table using the provided data.\n * The method uses Supabase's insert method with the data and then chains a select()\n * and single() call to retrieve the inserted record with any auto-generated fields\n * (like IDs) populated. If the operation is successful, it returns the created record.\n * If an error occurs during the operation, a failure result with an error message is returned.\n */\n async create<T>(table: string, data: T): Promise<DatabaseResult<T>> {\n try {\n const tableName = this.getTableName(table);\n const { data: result, error } = await this.client\n .from(tableName)\n .insert(data)\n .select()\n .single();\n\n if (error) {\n return failure(\n new DatabaseError(\n `Failed to create in table ${table}: ${error.message}`,\n DATABASE_ERROR_CODES.CREATE_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.create\",\n },\n cause: error,\n },\n ),\n );\n }\n\n return success(result as T);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to create in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.CREATE_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.create\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Update an existing record.\n * @template T - The expected type of the record.\n * @param {string} table - Table name.\n * @param {string} id - Record ID.\n * @param {Partial<T>} data - Partial record data to update.\n * @returns {Promise<DatabaseResult<T>>} Promise resolving to DatabaseResult containing the updated record.\n * @description\n * Updates an existing record in the specified table using its primary ID.\n * Only the fields provided in the data object are updated, allowing for partial updates.\n * The method uses Supabase's update method with the data and a filter for the ID column,\n * then chains a select() and single() call to retrieve the updated record. If the operation\n * is successful, it returns the updated record. If an error occurs during the operation,\n * a failure result with an error message is returned.\n */\n async update<T>(\n table: string,\n id: string,\n data: Partial<T>,\n ): Promise<DatabaseResult<T>> {\n try {\n const tableName = this.getTableName(table);\n const idColumn = this.idColumnMap.get(table) ?? \"id\";\n const { data: result, error } = await this.client\n .from(tableName)\n .update(data)\n .eq(idColumn, id)\n .select()\n .single();\n\n if (error) {\n return failure(\n new DatabaseError(\n `Failed to update in table ${table}: ${error.message}`,\n DATABASE_ERROR_CODES.UPDATE_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.update\",\n },\n cause: error,\n },\n ),\n );\n }\n\n return success(result as T);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to update in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.UPDATE_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.update\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Delete a record.\n * @param {string} table - Table name.\n * @param {string} id - Record ID.\n * @returns {Promise<DatabaseResult<void>>} Promise resolving to DatabaseResult indicating success or failure.\n * @description\n * Deletes a record from the specified table using its primary ID.\n * The method uses Supabase's delete method with a filter for the ID column.\n * If the operation is successful, it returns a success result with no value.\n * If an error occurs during the operation, a failure result with an error message is returned.\n */\n async delete(table: string, id: string): Promise<DatabaseResult<void>> {\n try {\n const tableName = this.getTableName(table);\n const idColumn = this.idColumnMap.get(table) ?? \"id\";\n const { error } = await this.client\n .from(tableName)\n .delete()\n .eq(idColumn, id);\n\n if (error) {\n return failure(\n new DatabaseError(\n `Failed to delete from table ${table}: ${error.message}`,\n DATABASE_ERROR_CODES.DELETE_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.delete\",\n },\n cause: error,\n },\n ),\n );\n }\n\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to delete from table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.DELETE_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.delete\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Execute a transaction.\n * @template T - The expected type of the transaction result.\n * @param {(trx: Transaction) => Promise<T>} callback - Function containing transaction operations.\n * @returns {Promise<DatabaseResult<T>>} Promise resolving to DatabaseResult containing the transaction result.\n * @description\n * Executes a callback function within a database transaction, providing atomicity.\n * Note that Supabase doesn't support traditional multi-statement transactions in the same way\n * as direct database connections. This adapter simulates transactional behavior by executing\n * all operations through the same client, but does not provide true rollback capabilities.\n * If the callback function executes successfully, the transaction is considered committed.\n * If an error occurs during the execution of the callback function, a failure result with\n * an error message is returned, but any successful operations within the callback will not\n * be rolled back.\n */\n async transaction<T>(\n callback: (trx: Transaction) => Promise<T>,\n ): Promise<DatabaseResult<T>> {\n try {\n // Create a transaction object that uses the same client\n const trx: Transaction = {\n findById: async <T>(table: string, id: string) => {\n return this.findById<T>(table, id);\n },\n create: async <T>(table: string, data: T) => {\n return this.create<T>(table, data);\n },\n update: async <T>(table: string, id: string, data: Partial<T>) => {\n return this.update<T>(table, id, data);\n },\n delete: async (table: string, id: string) => {\n return this.delete(table, id);\n },\n commit: async () => {\n // No-op for Supabase\n },\n rollback: async () => {\n // No-op for Supabase\n },\n };\n\n const result = await callback(trx);\n return success(result);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Transaction failed: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.TRANSACTION_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.transaction\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Check if a record exists.\n * @param {string} table - Table name.\n * @param {string} id - Record ID.\n * @returns {Promise<DatabaseResult<boolean>>} Promise resolving to DatabaseResult containing boolean indicating existence.\n * @description\n * Checks if a record with the specified ID exists in the table.\n * The method constructs a SELECT query with a WHERE clause for the ID column\n * and a LIMIT of 1. It returns a success result with a boolean value indicating\n * whether the record exists. If an error occurs during the operation, a failure result\n * with an error message is returned.\n */\n async exists(table: string, id: string): Promise<DatabaseResult<boolean>> {\n try {\n const tableName = this.getTableName(table);\n const idColumn = this.idColumnMap.get(table) ?? \"id\";\n const { data, error } = await this.client\n .from(tableName)\n .select(idColumn)\n .eq(idColumn, id)\n .limit(1);\n\n if (error) {\n return failure(\n new DatabaseError(\n `Failed to check existence in table ${table}: ${error.message}`,\n DATABASE_ERROR_CODES.EXISTS_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.exists\",\n },\n cause: error,\n },\n ),\n );\n }\n return success((data && data.length > 0) || false);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to check existence in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.EXISTS_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.exists\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Count records matching a filter.\n * @param {string} table - Table name.\n * @param {Filter} [filter] - Filter conditions.\n * @returns {Promise<DatabaseResult<number>>} Promise resolving to DatabaseResult containing the count.\n * @description\n * Counts the number of records in the specified table that match the optional filter.\n * The method uses Supabase's select method with the count option set to 'exact'\n * and head set to true to return only the count. If a filter is provided,\n * it is applied to narrow down the count to matching records. It returns a success\n * result with the count of matching records. If an error occurs during the operation,\n * a failure result with an error message is returned.\n */\n async count<T extends Record<string, unknown> = Record<string, unknown>>(\n table: string,\n filter?: Filter<T>,\n ): Promise<DatabaseResult<number>> {\n try {\n const tableName = this.getTableName(table);\n let query = this.client\n .from(tableName)\n .select(\"*\", { count: \"exact\", head: true });\n\n if (filter) {\n query = this.applyFilter(query, filter);\n }\n\n const { count, error } = await query;\n\n if (error) {\n return failure(\n new DatabaseError(\n `Failed to count in table ${table}: ${error.message}`,\n DATABASE_ERROR_CODES.COUNT_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.count\",\n },\n cause: error,\n },\n ),\n );\n }\n return success(count ?? 0);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to count in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.COUNT_FAILED,\n {\n context: {\n source: \"SupabaseAdapter.count\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Perform health check.\n * @returns {Promise<DatabaseResult<DatabaseHealthStatus>>} Promise resolving to DatabaseResult containing health status.\n * @description\n * Checks the health of the database connection by executing a simple RPC call.\n * The method measures the response time of the query to determine the health status.\n * It attempts to call a 'version' RPC function, ignoring errors related to the function\n * not existing but reporting other errors. It returns a success result with a DatabaseHealthStatus\n * object indicating whether the database is healthy, the response time of the health check,\n * and any additional details. If an error occurs during the operation, a failure result\n * with an error message is returned.\n */\n async healthCheck(): Promise<DatabaseResult<DatabaseHealthStatus>> {\n const startTime = Date.now();\n try {\n const { error } = await this.client.rpc(\"version\");\n const responseTime = Date.now() - startTime;\n\n if (\n error &&\n !error.message.includes('function \"version\" does not exist')\n ) {\n return success({\n isHealthy: false,\n responseTime,\n details: { adapter: \"supabase\", error: error.message },\n });\n }\n return success({\n isHealthy: true,\n responseTime,\n details: { adapter: \"supabase\" },\n });\n } catch (error) {\n const responseTime = Date.now() - startTime;\n return success({\n isHealthy: false,\n responseTime,\n details: { adapter: \"supabase\", error: (error as Error).message },\n });\n }\n }\n\n /**\n * Get the actual table name from the mapped table name.\n * @private\n * @param {string} name - Logical table name.\n * @returns {string} Actual table name.\n * @description\n * Retrieves the actual table name. If not registered, auto-registers it.\n * This enables seamless table operations without manual registration.\n */\n private getTableName(name: string): string {\n let tableName = this.tableMap.get(name);\n if (!tableName) {\n // Auto-register table with same name\n // Only set ID column from config if not already registered (runtime override takes precedence)\n const hasRuntimeIdColumn = this.idColumnMap.has(name);\n const customIdColumn = hasRuntimeIdColumn\n ? undefined\n : this.configIdColumns[name];\n this.registerTable(name, name, customIdColumn);\n tableName = name;\n }\n return tableName;\n }\n\n /**\n * Applies filter conditions to a Supabase query with comprehensive operator support\n *\n * Transforms generic Filter objects into Supabase-specific query methods while maintaining\n * type safety and preventing SQL injection through operator validation.\n *\n * **Supported Operators:**\n * - Equality: eq, ne (not equal)\n * - Comparison: gt, gte, lt, lte\n * - Pattern: like (with % wildcards)\n * - Membership: in, notIn (array values)\n * - Range: between (two-element array)\n * - Null checks: isNull, isNotNull\n *\n * **Security Features:**\n * - Validates field names against regex: /^[a-zA-Z_][a-zA-Z0-9_]*$/\n * - Validates operator against whitelist\n * - Type-checks array values for 'in', 'notIn', 'between' operators\n *\n * @private\n * @template Q - Type of the Supabase query builder\n * @param {Q} query - Supabase query builder instance to apply filters to\n * @param {Filter} filter - Filter conditions with field, operator, and value\n * @returns {Q} Modified query builder with filter conditions applied\n *\n * @throws {BaseError} SUPABASE_INVALID_FILTER - If 'in'/'notIn' value is not an array\n * @throws {BaseError} SUPABASE_INVALID_FILTER - If 'between' value is not a 2-element array\n * @throws {BaseError} SUPABASE_UNSUPPORTED_OPERATOR - If operator is not in whitelist\n *\n * @example\n * ```typescript\n * // Equality filter\n * const query1 = this.applyFilter(baseQuery, {\n * field: 'status',\n * operator: 'eq',\n * value: 'active'\n * });\n * // Generates: query.eq('status', 'active')\n *\n * // Range filter\n * const query2 = this.applyFilter(baseQuery, {\n * field: 'age',\n * operator: 'between',\n * value: [18, 65]\n * });\n * // Generates: query.gte('age', 18).lte('age', 65)\n *\n * // Array membership filter\n * const query3 = this.applyFilter(baseQuery, {\n * field: 'category',\n * operator: 'in',\n * value: ['tech', 'science', 'business']\n * });\n * // Generates: query.in('category', ['tech', 'science', 'business'])\n * ```\n *\n */\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private applyFilter<T extends object = object>(q: any, f: Filter<T>): any {\n const { field, operator, value } = f;\n\n const ops: Record<string, Function> = {\n eq: () => q.eq(field, value),\n ne: () => q.neq(field, value),\n gt: () => q.gt(field, value),\n gte: () => q.gte(field, value),\n lt: () => q.lt(field, value),\n lte: () => q.lte(field, value),\n like: () => q.like(field, value),\n isNull: () => q.is(field, null),\n isNotNull: () => q.isNot(field, null),\n in: () => {\n if (!Array.isArray(value))\n throw new DatabaseError(\n `'in' requires array`,\n DATABASE_ERROR_CODES.INVALID_FILTER,\n );\n return q.in(field, value);\n },\n notIn: () => {\n if (!Array.isArray(value))\n throw new DatabaseError(\n `'notIn' requires array`,\n DATABASE_ERROR_CODES.INVALID_FILTER,\n );\n return q.notIn(field, value);\n },\n between: () => {\n if (!Array.isArray(value) || value.length !== NUMERIX.TWO)\n throw new DatabaseError(\n `'between' requires [min,max]`,\n DATABASE_ERROR_CODES.INVALID_FILTER,\n );\n return q.gte(field, value[0]).lte(field, value[1]);\n },\n };\n\n if (!ops[operator])\n throw new DatabaseError(\n `Unsupported operator: ${operator}`,\n DATABASE_ERROR_CODES.UNSUPPORTED_OPERATOR,\n );\n return ops[operator]();\n }\n}\n","import type { PoolClient } from \"pg\";\nimport { Pool } from \"pg\";\nimport type {\n SQLAdapterConfig,\n Transaction,\n DatabaseResult,\n PaginatedResult,\n QueryOptions,\n DatabaseHealthStatus,\n Filter,\n DatabaseAdapterType,\n} from \"@plyaz/types/db\";\nimport { failure, success } from \"@utils/databaseResultHelpers\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport { calculatePagination } from \"@utils/pagination\";\nimport { isNonEmptyString, isObject } from \"@utils/typeGuards\";\nimport { DB_REGEX } from \"@utils/regex\";\n\n/** Maximum characters of SQL to include in error messages */\nconst SQL_ERROR_TRUNCATE_LENGTH = 500;\n\n/**\n * @class SQLAdapter\n * @implements {DatabaseAdapterType}\n * @classdesc\n * Plain SQL adapter implementation for raw SQL queries.\n *\n * This adapter provides an interface to interact with SQL databases using raw SQL queries,\n * supporting CRUD operations, transactions, and health checks. It uses PostgreSQL's node-pg\n * driver for database connectivity and provides a simple, direct SQL interface without\n * ORM abstractions. This adapter is ideal for applications that require direct control\n * over SQL queries or need to leverage database-specific features.\n */\nexport class SQLAdapter implements DatabaseAdapterType {\n private pool: Pool;\n private config: SQLAdapterConfig;\n private tableMap: Map<string, string> = new Map();\n private idColumnMap: Map<string, string> = new Map();\n private configIdColumns: Record<string, string>;\n private defaultSchema: string;\n private showSqlInErrors: boolean;\n\n /**\n * Creates a new SQLAdapter instance.\n * @param {SQLAdapterConfig} config - Configuration for the SQL adapter.\n * @description\n * Initializes the adapter with the provided configuration, setting up the connection pool\n * for PostgreSQL database connections. The configuration should include a connection string\n * and optional pool settings such as min/max connections and idle timeout. The adapter\n * maintains internal maps for table names and ID columns to provide a level of abstraction\n * over the raw database schema.\n */\n constructor(config: SQLAdapterConfig) {\n this.config = config;\n this.defaultSchema = config.schema ?? \"public\";\n this.showSqlInErrors = config.showSqlInErrors ?? true;\n this.pool = new Pool({\n connectionString: config.connectionString,\n ...config.pool,\n });\n // Store custom ID column mappings from config\n this.configIdColumns = config.tableIdColumns ?? {};\n }\n\n /**\n * Get fully-qualified table name with schema\n */\n private getQualifiedTableName(table: string, schema?: string): string {\n const targetSchema = schema ?? this.defaultSchema;\n\n // If table already has schema prefix (e.g., \"tenant_acme.users\"), use as-is\n if (table.includes(\".\")) {\n return table;\n }\n\n // Apply schema prefix\n return `${targetSchema}.${table}`;\n }\n\n /**\n * Initialize the adapter.\n * @returns {Promise<DatabaseResult<void>>} Promise resolving to DatabaseResult indicating success or failure.\n * @description\n * Tests the database connection by attempting to establish a connection to the database.\n * This method is typically called during application startup to verify that the adapter\n * can communicate with the database before performing any operations. Returns a success\n * result if the connection is established, or a failure result with an error if the\n * connection cannot be established.\n */\n async initialize(): Promise<DatabaseResult<void>> {\n try {\n const client = await this.pool.connect();\n\n // Set search_path for the connection if schema is configured\n if (this.defaultSchema && this.defaultSchema !== \"public\") {\n await client.query(`SET search_path TO ${this.defaultSchema}, public`);\n }\n\n client.release();\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to initialize PlainSQL adapter: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.INIT_FAILED,\n {\n context: {\n source: \"SQLAdapter.initialize\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Connect to the database.\n * @returns {Promise<void>} Promise that resolves when connected.\n * @description\n * Establishes a connection to the PostgreSQL database using the connection pool.\n * This method is called to ensure that a connection is available before performing database operations.\n * The connection pool manages the connections efficiently, reusing them when possible.\n */\n async connect(): Promise<void> {\n await this.pool.connect();\n }\n\n /**\n * Disconnect from the database.\n * @returns {Promise<void>} Promise that resolves when disconnected.\n * @description\n * Gracefully shuts down the connection pool, closing all active connections.\n * This method should be called when the adapter is no longer needed, typically during\n * application shutdown, to free up database resources and prevent connection leaks.\n */\n async disconnect(): Promise<void> {\n await this.pool.end();\n }\n\n /**\n * Closes the database connection and cleanup resources.\n * @returns Promise resolving to DatabaseResult indicating success or failure.\n */\n async close(): Promise<DatabaseResult<void>> {\n try {\n await this.disconnect();\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to close connection: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.DISCONNECT_FAILED,\n ),\n );\n }\n }\n\n /**\n * Gets the underlying PostgreSQL client instance.\n * @template TClient - The type of the database client to return.\n * @returns {TClient} The PostgreSQL pool instance cast to the specified client type.\n * @description\n * This method provides access to the underlying PostgreSQL connection pool.\n * While direct access is technically possible, it is generally discouraged to\n * preserve abstraction and ensure all database operations go through the adapter’s\n * interface for consistent error handling, logging, and event management.\n */\n getClient<TClient extends object = object>(): TClient {\n return this.pool as TClient;\n }\n\n /**\n * Execute a raw SQL query.\n * @template T - The expected type of the query result rows.\n * @param {string} sql - SQL query string.\n * @param {T[]} [params] - Query parameters.\n * @returns {Promise<T[]>} Promise resolving to query results.\n * @description\n * Executes a raw SQL query against the database, with optional parameterization.\n * This method is useful for complex queries that cannot be easily expressed using the adapter's\n * built-in methods or for database-specific operations. The method uses parameterized queries\n * to prevent SQL injection attacks. If the query execution fails, a DatabaseError is thrown.\n */\n async query<T>(sql: string, params?: T[]): Promise<T[]> {\n try {\n const result = await this.pool.query(sql, params);\n return result.rows as T[];\n } catch (error) {\n // Optionally include SQL in error message for debugging (default: true)\n const truncatedSql = sql.slice(0, SQL_ERROR_TRUNCATE_LENGTH);\n const sqlSuffix = sql.length > SQL_ERROR_TRUNCATE_LENGTH ? \"...\" : \"\";\n const errorMessage = this.showSqlInErrors\n ? `SQL Error: ${(error as Error).message}\\n Query: ${truncatedSql}${sqlSuffix}`\n : `SQL Error: ${(error as Error).message}`;\n\n throw new DatabaseError(errorMessage, DATABASE_ERROR_CODES.QUERY_FAILED, {\n context: {\n source: \"SQLAdapter.query\",\n },\n cause: error as Error,\n });\n }\n }\n\n /**\n * Register a table with the adapter.\n * @template TTable - Type representing the table structure.\n * @template TIdColumn - Type representing the ID column.\n * @param {string} name - Logical name for the table.\n * @param {TTable} [table] - Table name or object.\n * @param {TIdColumn} [idColumn] - Optional ID column name.\n * @description\n * Registers a table with the adapter, allowing it to be referenced by a logical name\n * in subsequent operations. This is necessary for the adapter to perform operations\n * on the table. The ID column can also be specified if it differs from the default 'id'.\n * This registration enables the adapter to map logical table names to actual table names\n * and ID columns, providing a layer of abstraction between the application and the database schema.\n */\n registerTable<TTable, TIdColumn>(\n name: string,\n table?: TTable,\n idColumn?: TIdColumn,\n ): void {\n this.tableMap.set(name, table as string);\n\n if (idColumn) {\n this.idColumnMap.set(name, idColumn as string);\n }\n }\n\n /**\n * Find a single record by ID.\n * @template T - The expected type of the record.\n * @param {string} table - Table name.\n * @param {string} id - Record ID.\n * @returns {Promise<DatabaseResult<T | null>>} Promise resolving to DatabaseResult containing the record or null.\n * @description\n * Retrieves a single record from the specified table using its primary ID.\n * The method constructs a SELECT query with a WHERE clause for the ID column.\n * If the record is found, it is returned in a success result. If no record is found,\n * null is returned in a success result. If an error occurs during the operation,\n * a failure result with an error message is returned.\n */\n async findById<T>(\n table: string,\n id: string,\n ): Promise<DatabaseResult<T | null>> {\n try {\n const validationError = this.validateBasicParams(table, id);\n if (validationError) return failure(validationError);\n\n const tableName = this.getTableName(table);\n const qualifiedTable = this.getQualifiedTableName(tableName);\n const idColumn = this.getIdColumn(table);\n const sql = `SELECT * FROM ${qualifiedTable} WHERE \"${idColumn}\" = $1`;\n const result = await this.pool.query(sql, [id]);\n\n if (!result?.rows) {\n return failure(\n new DatabaseError(\n \"Invalid query result\",\n DATABASE_ERROR_CODES.INVALID_RESULT,\n ),\n );\n }\n\n return success((result.rows?.[0] as T) ?? null);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to find record: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.FIND_BY_ID_FAILED,\n {\n context: {\n source: \"SQLAdapter.findById\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Find multiple records with filtering and pagination.\n * @template T - The expected type of the records.\n * @param {string} table - Table name.\n * @param {QueryOptions} [options] - Query options including filters, sorting, and pagination.\n * @returns {Promise<DatabaseResult<PaginatedResult<object>>>} Promise resolving to DatabaseResult containing paginated data.\n * @description\n * Retrieves multiple records from the specified table with support for filtering,\n * sorting, and pagination. The method constructs a SELECT query with optional WHERE,\n * ORDER BY, LIMIT, and OFFSET clauses. It first executes a COUNT query to get the\n * total number of matching records, then executes the main query with the applied filters,\n * sorting, and pagination. The result includes the data array, total count of matching records,\n * and pagination metadata such as current page, total pages, and offset.\n * If an error occurs during the operation, a failure result with an error message is returned.\n */\n /**\n * Finds multiple records from the specified table with optional filtering, sorting, and pagination.\n * @template TRecord - Type representing the shape of records returned.\n * @template TOptions - Query options type.\n * @template TParam - Type of query parameters (primitives).\n * @param {string} table - Name of the table to query.\n * @param {TOptions} [options] - Optional query options for filtering, sorting, and pagination.\n * @returns {Promise<DatabaseResult<PaginatedResult<TRecord>>>} - A promise resolving to a paginated result.\n * @throws {DatabaseError} - When query execution or initialization fails.\n */\n /**\n * Finds multiple records from the specified table with optional filtering, sorting, and pagination.\n * @template T - Type representing the shape of records returned.\n * @param {string} table - Name of the table to query.\n * @param {QueryOptions<object>} [options] - Optional query options for filtering, sorting, and pagination.\n * @returns {Promise<DatabaseResult<PaginatedResult<T>>>} - A promise resolving to a paginated result.\n * @throws {DatabaseError} - When query execution or initialization fails.\n */\n // eslint-disable-next-line complexity\n async findMany<T extends Record<string, unknown>>(\n table: string,\n options?: QueryOptions<T>,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n try {\n const tableName = this.getTableName(table);\n const qualifiedTable = this.getQualifiedTableName(tableName);\n const params: Object[] = [];\n let whereClause = \"\";\n let paramIndex = 1;\n\n // Build WHERE clause\n if (options?.filter) {\n whereClause = this.buildWhereClause(options.filter, params, paramIndex);\n paramIndex += params.length;\n }\n\n // Count total\n const countSql = `SELECT COUNT(*) as total FROM ${qualifiedTable}${whereClause}`;\n const countResult = await this.pool.query(countSql, params);\n\n if (!countResult.rows || countResult.rows.length === 0) {\n throw new DatabaseError(\n \"Count query returned no results\",\n DATABASE_ERROR_CODES.COUNT_NO_RESULTS,\n );\n }\n\n const total = Number.parseInt(countResult.rows[0].total);\n if (isNaN(total) || total < 0) {\n throw new DatabaseError(\n \"Invalid count result\",\n DATABASE_ERROR_CODES.INVALID_COUNT,\n );\n }\n\n // ORDER BY clause\n let orderClause = \"\";\n if (options?.sort?.length) {\n orderClause =\n \" ORDER BY \" +\n options.sort\n .map((s) => `${s.field} ${s.direction.toUpperCase()}`)\n .join(\", \");\n }\n\n // LIMIT & OFFSET\n let limitClause = \"\";\n if (options?.pagination?.limit) {\n limitClause += ` LIMIT $${paramIndex++}`;\n params.push(options.pagination.limit);\n }\n if (options?.pagination?.offset) {\n limitClause += ` OFFSET $${paramIndex++}`;\n params.push(options.pagination.offset);\n }\n\n // Final query\n const sql = `SELECT * FROM ${qualifiedTable}${whereClause}${orderClause}${limitClause}`;\n const result = await this.pool.query(sql, params);\n\n return success({\n data: result.rows as T[],\n total,\n pagination: calculatePagination(total, options?.pagination),\n });\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to find many in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.FIND_MANY_FAILED,\n {\n context: {\n source: \"SQLAdapter.findMany\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Create a new record.\n * @template T - The expected type of the record.\n * @param {string} table - Table name.\n * @param {T} data - Record data to create.\n * @returns {Promise<DatabaseResult<T>>} Promise resolving to DatabaseResult containing the created record.\n * @description\n * Inserts a new record into the specified table using the provided data.\n * The method constructs an INSERT query with column names and parameter placeholders\n * for the values. After insertion, it returns the inserted record with any auto-generated\n * fields (like IDs) populated using the RETURNING clause. If an error occurs during the operation,\n * a failure result with an error message is returned.\n */\n async create<T>(table: string, data: T): Promise<DatabaseResult<T>> {\n try {\n const validationError = this.validateCreateParams(table, data);\n if (validationError) return failure(validationError);\n\n const tableName = this.getTableName(table);\n const qualifiedTable = this.getQualifiedTableName(tableName);\n const keys = Object.keys(data as Record<string, T>);\n const values = Object.values(data as Record<string, T>);\n const placeholders = values.map((_, i) => `$${i + 1}`).join(\", \");\n const escapedKeys = keys.map((k) => `\"${k}\"`).join(\", \");\n\n const sql = `INSERT INTO ${qualifiedTable} (${escapedKeys}) VALUES (${placeholders}) RETURNING *`;\n const result = await this.pool.query(sql, values);\n\n if (!result?.rows?.length) {\n return failure(\n new DatabaseError(\n \"Insert operation failed\",\n DATABASE_ERROR_CODES.INSERT_FAILED,\n ),\n );\n }\n\n return success(result.rows[0] as T);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to create record: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.CREATE_FAILED,\n {\n context: {\n source: \"SQLAdapter.create\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Update an existing record.\n * @template T - The expected type of the record.\n * @param {string} table - Table name.\n * @param {string} id - Record ID.\n * @param {Partial<T>} data - Partial record data to update.\n * @returns {Promise<DatabaseResult<T>>} Promise resolving to DatabaseResult containing the updated record.\n * @description\n * Updates an existing record in the specified table using its primary ID.\n * Only the fields provided in the data object are updated, allowing for partial updates.\n * The method constructs an UPDATE query with a SET clause for the fields to update\n * and a WHERE clause for the ID. After updating, it returns the updated record using\n * the RETURNING clause. If an error occurs during the operation, a failure result with\n * an error message is returned.\n */\n async update<T>(\n table: string,\n id: string,\n data: Partial<T>,\n ): Promise<DatabaseResult<T>> {\n try {\n const validationError = this.validateUpdateParams(table, id, data);\n if (validationError) return failure(validationError);\n\n const tableName = this.getTableName(table);\n const qualifiedTable = this.getQualifiedTableName(tableName);\n const keys = Object.keys(data as Record<string, T>);\n const values = Object.values(data as Record<string, T>);\n const setClause = keys.map((key, i) => `\"${key}\" = $${i + 1}`).join(\", \");\n const idColumn = this.getIdColumn(table);\n\n const sql = `UPDATE ${qualifiedTable} SET ${setClause} WHERE \"${idColumn}\" = $${keys.length + 1} RETURNING *`;\n const result = await this.pool.query(sql, [...values, id]);\n\n if (!result.rows?.length) {\n return failure(\n new DatabaseError(\n \"Record not found or no changes made\",\n DATABASE_ERROR_CODES.UPDATE_NO_CHANGES,\n ),\n );\n }\n\n return success(result.rows[0] as T);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to update record: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.UPDATE_FAILED,\n {\n context: {\n source: \"SQLAdapter.update\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Delete a record.\n * @param {string} table - Table name.\n * @param {string} id - Record ID.\n * @returns {Promise<DatabaseResult<void>>} Promise resolving to DatabaseResult indicating success or failure.\n * @description\n * Deletes a record from the specified table using its primary ID.\n * The method constructs a DELETE query with a WHERE clause for the ID column.\n * If the operation is successful, it returns a success result with no value.\n * If an error occurs during the operation, a failure result with an error message is returned.\n */\n async delete(table: string, id: string): Promise<DatabaseResult<void>> {\n try {\n if (!table || !id) {\n return failure(\n new DatabaseError(\n \"Invalid parameters\",\n DATABASE_ERROR_CODES.INVALID_PARAMS,\n ),\n );\n }\n\n const tableName = this.getTableName(table);\n const qualifiedTable = this.getQualifiedTableName(tableName);\n const idColumn = this.getIdColumn(table);\n const sql = `DELETE FROM ${qualifiedTable} WHERE \"${idColumn}\" = $1`;\n const result = await this.pool.query(sql, [id]);\n\n if (!result) {\n return failure(\n new DatabaseError(\n \"Delete operation failed\",\n DATABASE_ERROR_CODES.DELETE_FAILED,\n ),\n );\n }\n\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to delete record: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.DELETE_FAILED,\n {\n context: {\n source: \"SQLAdapter.delete\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Execute a transaction.\n * @template T - The expected type of the transaction result.\n * @param {(trx: Transaction) => Promise<T>} callback - Function containing transaction operations.\n * @returns {Promise<DatabaseResult<T>>} Promise resolving to DatabaseResult containing the transaction result.\n * @description\n * Executes a callback function within a database transaction, providing atomicity.\n * If the callback function executes successfully, the transaction is committed.\n * If an error occurs during the execution of the callback function, the transaction\n * is rolled back, ensuring that no partial changes are applied to the database.\n * The method returns the result of the callback function if successful,\n * or a failure result with an error message if an error occurs.\n * The transaction object passed to the callback provides methods for performing\n * database operations within the transaction.\n */\n async transaction<T>(\n callback: (trx: Transaction) => Promise<T>,\n ): Promise<DatabaseResult<T>> {\n const client: PoolClient = await this.pool.connect();\n try {\n await client.query(\"BEGIN\");\n\n const trx: Transaction = {\n findById: async <T>(table: string, id: string) => {\n const tableName = this.getTableName(table);\n const qualifiedTable = this.getQualifiedTableName(tableName);\n const idColumn = this.getIdColumn(table);\n const sql = `SELECT * FROM ${qualifiedTable} WHERE \"${idColumn}\" = $1`;\n const result = await client.query(sql, [id]);\n return success((result.rows[0] as T) ?? null);\n },\n create: async <T>(table: string, data: T) => {\n const tableName = this.getTableName(table);\n const qualifiedTable = this.getQualifiedTableName(tableName);\n const keys = Object.keys(data as Record<string, T>);\n const values = Object.values(data as Record<string, T>);\n const placeholders = values.map((_, i) => `$${i + 1}`).join(\", \");\n const escapedKeys = keys.map((k) => `\"${k}\"`).join(\", \");\n\n const sql = `INSERT INTO ${qualifiedTable} (${escapedKeys}) VALUES (${placeholders}) RETURNING *`;\n const result = await client.query(sql, values);\n return success(result.rows[0] as T);\n },\n update: async <T>(table: string, id: string, data: Partial<T>) => {\n const tableName = this.getTableName(table);\n const qualifiedTable = this.getQualifiedTableName(tableName);\n const keys = Object.keys(data as Record<string, T>);\n const values = Object.values(data as Record<string, T>);\n const setClause = keys\n .map((key, i) => `\"${key}\" = $${i + 1}`)\n .join(\", \");\n const idColumn = this.getIdColumn(table);\n\n const sql = `UPDATE ${qualifiedTable} SET ${setClause} WHERE \"${idColumn}\" = $${keys.length + 1} RETURNING *`;\n const result = await client.query(sql, [...values, id]);\n return success(result.rows[0] as T);\n },\n delete: async (table: string, id: string) => {\n const tableName = this.getTableName(table);\n const qualifiedTable = this.getQualifiedTableName(tableName);\n const idColumn = this.getIdColumn(table);\n const sql = `DELETE FROM ${qualifiedTable} WHERE \"${idColumn}\" = $1`;\n await client.query(sql, [id]);\n return success();\n },\n commit: async () => {\n await client.query(\"COMMIT\");\n },\n rollback: async () => {\n await client.query(\"ROLLBACK\");\n },\n };\n\n const result = await callback(trx);\n await trx.commit();\n return success(result);\n } catch (error) {\n await client.query(\"ROLLBACK\");\n return failure(\n new DatabaseError(\n `Transaction failed: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.TRANSACTION_FAILED,\n {\n context: {\n source: \"SQLAdapter.transaction\",\n },\n cause: error as Error,\n },\n ),\n );\n } finally {\n client.release();\n }\n }\n\n /**\n * Check if a record exists.\n * @param {string} table - Table name.\n * @param {string} id - Record ID.\n * @returns {Promise<DatabaseResult<boolean>>} Promise resolving to DatabaseResult containing boolean indicating existence.\n * @description\n * Checks if a record with the specified ID exists in the table.\n * The method constructs a SELECT query with a WHERE clause for the ID column\n * and a LIMIT of 1. It returns a success result with a boolean value indicating\n * whether the record exists. If an error occurs during the operation, a failure result\n * with an error message is returned.\n */\n async exists(table: string, id: string): Promise<DatabaseResult<boolean>> {\n try {\n const tableName = this.getTableName(table);\n const qualifiedTable = this.getQualifiedTableName(tableName);\n const idColumn = this.getIdColumn(table);\n const sql = `SELECT 1 FROM ${qualifiedTable} WHERE \"${idColumn}\" = $1 LIMIT 1`;\n const result = await this.pool.query(sql, [id]);\n return success(result.rows.length > 0);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to check existence in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.EXISTS_FAILED,\n {\n context: {\n source: \"SQLAdapter.exists\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Count records matching a filter.\n * @param {string} table - Table name.\n * @param {Filter} [filter] - Filter conditions.\n * @returns {Promise<DatabaseResult<number>>} Promise resolving to DatabaseResult containing the count.\n * @description\n * Counts the number of records in the specified table that match the optional filter.\n * The method constructs a COUNT query with an optional WHERE clause based on the filter.\n * It returns a success result with the count of matching records.\n * If an error occurs during the operation, a failure result with an error message is returned.\n */\n async count<T extends Record<string, unknown> = Record<string, unknown>>(\n table: string,\n filter?: Filter<T>,\n ): Promise<DatabaseResult<number>> {\n try {\n const tableName = this.getTableName(table);\n const qualifiedTable = this.getQualifiedTableName(tableName);\n let whereClause = \"\";\n let params: object[] = [];\n\n if (filter) {\n whereClause = this.buildWhereClause(filter, params, 1);\n }\n\n const sql = `SELECT COUNT(*) as count FROM ${qualifiedTable}${whereClause}`;\n const result = await this.pool.query(sql, params);\n const rowCount = Number.parseInt(result.rows[0].count);\n return success(Number(rowCount));\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to count in table ${table}: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.COUNT_FAILED,\n {\n context: {\n source: \"SQLAdapter.count\",\n },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Perform health check.\n * @returns {Promise<DatabaseResult<DatabaseHealthStatus>>} Promise resolving to DatabaseResult containing health status.\n * @description\n * Checks the health of the database connection by executing a simple query.\n * The method measures the response time of the query to determine the health status.\n * It returns a success result with a HealthStatus object indicating whether the database is healthy,\n * the response time of the health check, and any additional details.\n * If an error occurs during the operation, a failure result with an error message is returned.\n */\n async healthCheck(): Promise<DatabaseResult<DatabaseHealthStatus>> {\n const startTime = Date.now();\n try {\n await this.pool.query(\"SELECT 1\");\n const responseTime = Date.now() - startTime;\n return success({\n isHealthy: true,\n responseTime,\n details: { adapter: \"sql\" },\n });\n } catch (error) {\n const responseTime = Date.now() - startTime;\n return success({\n isHealthy: false,\n responseTime,\n details: { adapter: \"sql\", error: (error as Error).message },\n });\n }\n }\n\n /**\n * Get the actual table name from the mapped table name.\n * @private\n * @param {string} name - Logical table name.\n * @returns {string} Actual table name.\n * @description\n * Retrieves the actual table name. If not registered, auto-registers it with\n * the same logical name as the physical table name. This enables seamless\n * table operations without manual registration (matching Supabase adapter behavior).\n */\n private getTableName(name: string): string {\n let tableName = this.tableMap.get(name);\n if (!tableName) {\n // Auto-register table with same name\n // Only set ID column from config if not already registered (runtime override takes precedence)\n const hasRuntimeIdColumn = this.idColumnMap.has(name);\n const customIdColumn = hasRuntimeIdColumn\n ? undefined\n : this.configIdColumns[name];\n this.registerTable(name, name, customIdColumn);\n tableName = name;\n }\n return tableName;\n }\n\n /**\n * Get the ID column for a table.\n * @private\n * @param {string} table - Logical table name.\n * @returns {string} ID column name (defaults to 'id').\n * @description\n * Retrieves the ID column for a table. Checks in this order:\n * 1. Runtime registered ID column (from registerTable calls)\n * 2. Config-provided ID column (from tableIdColumns in config)\n * 3. Default 'id' column\n */\n private getIdColumn(table: string): string {\n // Check runtime registered first\n const runtimeIdColumn = this.idColumnMap.get(table);\n if (runtimeIdColumn) {\n return runtimeIdColumn;\n }\n\n // Check config-provided ID columns\n const configIdColumn = this.configIdColumns[table];\n if (configIdColumn) {\n return configIdColumn;\n }\n\n // Default to 'id'\n return \"id\";\n }\n\n private validateBasicParams(table: string, id: string): DatabaseError | null {\n if (!table || !id) {\n return new DatabaseError(\n \"Invalid parameters\",\n DATABASE_ERROR_CODES.INVALID_PARAMS,\n );\n }\n return null;\n }\n\n private validateCreateParams<T>(\n table: string,\n data: T,\n ): DatabaseError | null {\n if (!isNonEmptyString(table) || !isObject(data)) {\n return new DatabaseError(\n \"Invalid parameters\",\n DATABASE_ERROR_CODES.INVALID_PARAMS,\n );\n }\n\n const keys = Object.keys(data as Record<string, T>);\n if (keys.length === 0) {\n return new DatabaseError(\n \"No data to insert\",\n DATABASE_ERROR_CODES.NO_DATA,\n );\n }\n\n for (const key of keys) {\n if (!DB_REGEX.isValidFieldName(key)) {\n return new DatabaseError(\n \"Invalid field name\",\n DATABASE_ERROR_CODES.INVALID_FIELD_NAME,\n );\n }\n }\n return null;\n }\n\n private validateUpdateParams<T>(\n table: string,\n id: string,\n data: Partial<T>,\n ): DatabaseError | null {\n if (!isNonEmptyString(table) || !isNonEmptyString(id) || !isObject(data)) {\n return new DatabaseError(\n \"Invalid parameters for update operation\",\n DATABASE_ERROR_CODES.INVALID_UPDATE_PARAMS,\n );\n }\n\n const keys = Object.keys(data as Record<string, T>);\n if (keys.length === 0) {\n return new DatabaseError(\n \"No fields to update\",\n DATABASE_ERROR_CODES.NO_UPDATE_FIELDS,\n );\n }\n\n for (const key of keys) {\n if (!DB_REGEX.isValidFieldName(key)) {\n return new DatabaseError(\n \"Invalid field name\",\n DATABASE_ERROR_CODES.INVALID_FIELD_NAME,\n );\n }\n }\n return null;\n }\n\n /**\n * Builds a SQL WHERE clause string from a provided filter definition.\n *\n * @private\n * @template TParams - Tuple type representing the parameter array.\n * @param {Filter} filter - The filter condition containing the field, operator, and value.\n * @param {TParams} params - Mutable array to collect SQL parameter values.\n * @param {number} startIndex - The starting index for SQL parameter placeholders (e.g., $1, $2, ...).\n * @returns {string} The constructed SQL WHERE clause string.\n * @throws {DatabaseError} If an unsupported operator is encountered or if the filter value type is invalid.\n *\n * @description\n * This method dynamically builds a SQL WHERE clause based on the provided `filter` object.\n * It supports operators such as:\n * - `eq`, `ne` (equality and inequality)\n * - `gt`, `gte`, `lt`, `lte` (comparison)\n * - `in` (membership in a list)\n * - `like` (pattern matching)\n * - `between` (range)\n * - `isNull`, `isNotNull` (null checks)\n *\n * The function safely constructs parameterized queries by adding each value\n * into the `params` array and referencing it via `$<index>` placeholders,\n * helping to prevent SQL injection attacks.\n */\n\n // eslint-disable-next-line complexity\n private buildWhereClause<\n T extends Record<string, unknown>,\n TParams extends object[],\n >(filter: Filter<T>, params: unknown[], startIndex: number): string {\n const { field, operator, value } = filter;\n let clause = \"\";\n\n switch (operator) {\n case \"eq\":\n clause = ` WHERE ${field} = $${startIndex}`;\n params.push(value);\n break;\n\n case \"ne\":\n clause = ` WHERE ${field} != $${startIndex}`;\n params.push(value);\n break;\n\n case \"gt\":\n clause = ` WHERE ${field} > $${startIndex}`;\n params.push(value);\n break;\n\n case \"gte\":\n clause = ` WHERE ${field} >= $${startIndex}`;\n params.push(value);\n break;\n\n case \"lt\":\n clause = ` WHERE ${field} < $${startIndex}`;\n params.push(value);\n break;\n\n case \"lte\":\n clause = ` WHERE ${field} <= $${startIndex}`;\n params.push(value);\n break;\n\n case \"in\": {\n if (Array.isArray(value)) {\n const arr = value as readonly TParams[];\n const placeholders = arr\n .map((_, i: number) => `$${startIndex + i}`)\n .join(\", \");\n clause = ` WHERE ${field} IN (${placeholders})`;\n params.push(...arr);\n } else {\n throw new DatabaseError(\n `Operator \"in\" requires an array value.`,\n DATABASE_ERROR_CODES.INVALID_IN_OPERATOR,\n );\n }\n break;\n }\n\n case \"like\":\n clause = ` WHERE ${field} LIKE $${startIndex}`;\n params.push(value as TParams);\n break;\n\n case \"between\": {\n if (Array.isArray(value)) {\n const [min, max] = value as [TParams[number], TParams[number]];\n clause = ` WHERE ${field} BETWEEN $${startIndex} AND $${startIndex + 1}`;\n params.push(min, max);\n } else {\n throw new DatabaseError(\n `Operator \"between\" requires a two-element array.`,\n DATABASE_ERROR_CODES.INVALID_BETWEEN_OPERATOR,\n );\n }\n break;\n }\n\n case \"isNull\":\n clause = ` WHERE ${field} IS NULL`;\n break;\n\n case \"isNotNull\":\n clause = ` WHERE ${field} IS NOT NULL`;\n break;\n\n default:\n throw new DatabaseError(\n `Unsupported operator: ${operator}`,\n DATABASE_ERROR_CODES.UNSUPPORTED_OPERATOR,\n );\n }\n\n return clause;\n }\n}\n","/**\n * MockAdapter - In-Memory Database Adapter for Testing\n *\n * Provides a lightweight, in-memory database adapter that mimics\n * the behavior of real database adapters without requiring an actual\n * database connection. Perfect for unit tests and integration tests.\n *\n * @example\n * ```typescript\n * const db = await createDatabaseService({\n * adapter: 'mock',\n * config: {\n * initialData: {\n * users: [{ id: '1', name: 'Test User', email: 'test@example.com' }],\n * campaigns: [{ id: '1', title: 'Test Campaign', creator_id: '1' }]\n * },\n * autoGenerateIds: true\n * }\n * });\n * ```\n */\n\nimport type {\n DatabaseAdapterType,\n DatabaseResult,\n PaginatedResult,\n QueryOptions,\n Transaction,\n DatabaseHealthStatus,\n Filter,\n DbMockAdapterConfig,\n} from \"@plyaz/types/db\";\n\nimport { success, failure } from \"../../utils/databaseResultHelpers\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport { calculatePagination } from \"../../utils/pagination\";\n\n/** Default pagination limit */\nconst DEFAULT_PAGINATION_LIMIT = 50;\n/** Base for random string generation */\nconst RANDOM_STRING_BASE = 36;\n/** Start index for substring in ID generation */\nconst ID_SUBSTRING_START = 2;\n/** End index for substring in ID generation */\nconst ID_SUBSTRING_END = 9;\n/** Required length for between filter values */\nconst BETWEEN_VALUES_LENGTH = 2;\n\n/** Type for table data storage */\ntype TableDataMap = Map<string, Record<string, unknown>>;\n\n/** Filter operator handler type */\ntype FilterOperatorHandler = (\n fieldValue: unknown,\n filterValue: unknown,\n) => boolean;\n\n/** Lookup map for filter operators */\nconst FILTER_OPERATORS: Record<string, FilterOperatorHandler> = {\n eq: (fieldValue, value) => fieldValue === value,\n ne: (fieldValue, value) => fieldValue !== value,\n gt: (fieldValue, value) => (fieldValue as number) > (value as number),\n gte: (fieldValue, value) => (fieldValue as number) >= (value as number),\n lt: (fieldValue, value) => (fieldValue as number) < (value as number),\n lte: (fieldValue, value) => (fieldValue as number) <= (value as number),\n in: (fieldValue, value) =>\n Array.isArray(value) && (value as unknown[]).includes(fieldValue),\n like: (fieldValue, value) =>\n String(fieldValue).toLowerCase().includes(String(value).toLowerCase()),\n between: (fieldValue, value) => {\n const betweenValues = value as [number, number];\n return (\n Array.isArray(betweenValues) &&\n betweenValues.length === BETWEEN_VALUES_LENGTH &&\n (fieldValue as number) >= betweenValues[0] &&\n (fieldValue as number) <= betweenValues[1]\n );\n },\n isNull: (fieldValue) => fieldValue === null || fieldValue === undefined,\n isNotNull: (fieldValue) => fieldValue !== null && fieldValue !== undefined,\n};\n\n/**\n * MockAdapter - In-memory database adapter for testing\n */\nexport class MockAdapter implements DatabaseAdapterType {\n private data: Map<string, Map<string, Record<string, unknown>>> = new Map();\n private config: DbMockAdapterConfig;\n private tableIdColumns: Map<string, string> = new Map();\n private defaultSchema: string;\n private isInitialized = false;\n private transactionDepth = 0;\n private transactionData: Map<\n string,\n Map<string, Record<string, unknown>>\n > | null = null;\n\n constructor(config: Partial<DbMockAdapterConfig> = {}) {\n this.config = {\n autoGenerateIds: true,\n latency: 0,\n failRate: 0,\n ...config,\n } as DbMockAdapterConfig;\n this.defaultSchema = config.schema ?? \"public\";\n\n // Initialize with provided data\n if (config.initialData) {\n this.initializeTableData(config.initialData);\n }\n\n // Register custom ID columns\n if (config.tableIdColumns) {\n for (const [table, idColumn] of Object.entries(config.tableIdColumns)) {\n this.tableIdColumns.set(table, idColumn);\n }\n }\n }\n\n async initialize(): Promise<DatabaseResult<void>> {\n await this.simulateLatency();\n if (this.shouldFail()) {\n return failure(\n new DatabaseError(\n \"Mock initialization failed\",\n DATABASE_ERROR_CODES.INIT_FAILED,\n ),\n );\n }\n\n this.isInitialized = true;\n return success();\n }\n\n async close(): Promise<DatabaseResult<void>> {\n await this.simulateLatency();\n this.data.clear();\n this.isInitialized = false;\n return success();\n }\n\n registerTable<TTable = string, TIdColumn = string>(\n name: string,\n table?: TTable,\n idColumn?: TIdColumn,\n ): void {\n if (idColumn && typeof idColumn === \"string\") {\n this.tableIdColumns.set(name, idColumn);\n }\n\n // Ensure table exists\n if (!this.data.has(name)) {\n this.data.set(name, new Map());\n }\n }\n\n async findById<T>(\n table: string,\n id: string,\n ): Promise<DatabaseResult<T | null>> {\n await this.simulateLatency();\n if (this.shouldFail()) {\n return failure(\n new DatabaseError(\n \"Mock findById failed\",\n DATABASE_ERROR_CODES.FIND_BY_ID_FAILED,\n ),\n );\n }\n\n const tableData = this.getTableData(table);\n const record = tableData.get(id);\n\n return success(record ? ({ ...record } as T) : null);\n }\n\n /**\n * Apply query options (filter, sort) to records\n */\n private applyQueryOptions<T extends Record<string, unknown>>(\n records: Record<string, unknown>[],\n options?: QueryOptions<T>,\n ): Record<string, unknown>[] {\n let result = records;\n if (options?.filter) {\n result = this.applyFilter(result, options.filter);\n }\n if (options?.sort) {\n result = this.applySort(result, options.sort);\n }\n return result;\n }\n\n /**\n * Get pagination params with defaults\n */\n private getPaginationParams<T extends object>(\n options?: QueryOptions<T>,\n ): {\n offset: number;\n limit: number;\n } {\n return {\n offset: options?.pagination?.offset ?? 0,\n limit: options?.pagination?.limit ?? DEFAULT_PAGINATION_LIMIT,\n };\n }\n\n /**\n * Apply pagination to records\n */\n private applyPagination(\n records: Record<string, unknown>[],\n offset: number,\n limit: number,\n ): Record<string, unknown>[] {\n return records.slice(offset, offset + limit);\n }\n\n async findMany<T extends Record<string, unknown>>(\n table: string,\n options?: QueryOptions<T>,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n await this.simulateLatency();\n if (this.shouldFail()) {\n return failure(\n new DatabaseError(\n \"Mock findMany failed\",\n DATABASE_ERROR_CODES.FIND_MANY_FAILED,\n ),\n );\n }\n\n const tableData = this.getTableData(table);\n const allRecords = Array.from(tableData.values());\n const filteredRecords = this.applyQueryOptions(allRecords, options);\n const total = filteredRecords.length;\n const { offset, limit } = this.getPaginationParams(options);\n const paginatedRecords = this.applyPagination(\n filteredRecords,\n offset,\n limit,\n );\n\n return success({\n data: paginatedRecords as T[],\n total,\n pagination: calculatePagination(total, options?.pagination),\n });\n }\n\n async create<T>(table: string, data: T): Promise<DatabaseResult<T>> {\n await this.simulateLatency();\n if (this.shouldFail()) {\n return failure(\n new DatabaseError(\n \"Mock create failed\",\n DATABASE_ERROR_CODES.CREATE_FAILED,\n ),\n );\n }\n\n const tableData = this.getTableData(table);\n const idColumn = this.getIdColumn(table);\n const record = { ...(data as Record<string, unknown>) };\n\n // Generate ID if needed\n if (!record[idColumn] && this.config.autoGenerateIds) {\n record[idColumn] = this.generateId();\n }\n\n const id = record[idColumn];\n if (!id) {\n return failure(\n new DatabaseError(\n \"Record must have an ID\",\n DATABASE_ERROR_CODES.CREATE_FAILED,\n ),\n );\n }\n\n // Add timestamps\n const now = new Date().toISOString();\n record.created_at ??= now;\n record.updated_at ??= now;\n\n tableData.set(String(id), record);\n\n return success(record as T);\n }\n\n async update<T>(\n table: string,\n id: string,\n data: Partial<T>,\n ): Promise<DatabaseResult<T>> {\n await this.simulateLatency();\n if (this.shouldFail()) {\n return failure(\n new DatabaseError(\n \"Mock update failed\",\n DATABASE_ERROR_CODES.UPDATE_FAILED,\n ),\n );\n }\n\n const tableData = this.getTableData(table);\n const existing = tableData.get(id);\n\n if (!existing) {\n return failure(\n new DatabaseError(\n \"Record not found\",\n DATABASE_ERROR_CODES.RECORD_NOT_FOUND,\n ),\n );\n }\n\n const updated = {\n ...existing,\n ...data,\n updated_at: new Date().toISOString(),\n };\n\n tableData.set(id, updated);\n\n return success(updated as T);\n }\n\n async delete(table: string, id: string): Promise<DatabaseResult<void>> {\n await this.simulateLatency();\n if (this.shouldFail()) {\n return failure(\n new DatabaseError(\n \"Mock delete failed\",\n DATABASE_ERROR_CODES.DELETE_FAILED,\n ),\n );\n }\n\n const tableData = this.getTableData(table);\n const existed = tableData.delete(id);\n\n if (!existed) {\n return failure(\n new DatabaseError(\n \"Record not found\",\n DATABASE_ERROR_CODES.RECORD_NOT_FOUND,\n ),\n );\n }\n\n return success();\n }\n\n async transaction<T>(\n callback: (trx: Transaction) => Promise<T>,\n ): Promise<DatabaseResult<T>> {\n await this.simulateLatency();\n\n // Create a snapshot of current data\n const snapshot = new Map<string, TableDataMap>();\n for (const [table, tableData] of this.data.entries()) {\n snapshot.set(table, new Map(tableData));\n }\n\n this.transactionDepth++;\n this.transactionData = snapshot;\n\n try {\n const trx: Transaction = {\n findById: async <T>(table: string, id: string) =>\n this.findById<T>(table, id),\n create: async <T>(table: string, data: T) =>\n this.create<T>(table, data),\n update: async <T>(table: string, id: string, data: Partial<T>) =>\n this.update<T>(table, id, data),\n delete: async (table: string, id: string) => this.delete(table, id),\n commit: async () => {\n /* no-op, auto-committed */\n },\n rollback: async () => {\n // Restore snapshot\n this.data = snapshot;\n },\n };\n\n const result = await callback(trx);\n\n // Transaction succeeded - commit is implicit\n this.transactionDepth--;\n this.transactionData = null;\n\n return success(result);\n } catch (error) {\n // Rollback on error\n this.data = snapshot;\n this.transactionDepth--;\n this.transactionData = null;\n\n return failure(\n new DatabaseError(\n `Transaction failed: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.TRANSACTION_FAILED,\n { cause: error as Error },\n ),\n );\n }\n }\n\n async exists(table: string, id: string): Promise<DatabaseResult<boolean>> {\n await this.simulateLatency();\n const tableData = this.getTableData(table);\n return success(tableData.has(id));\n }\n\n async count<T extends Record<string, unknown> = Record<string, unknown>>(\n table: string,\n filter?: Filter<T>,\n ): Promise<DatabaseResult<number>> {\n await this.simulateLatency();\n const tableData = this.getTableData(table);\n let records = Array.from(tableData.values());\n\n if (filter) {\n records = this.applyFilter(records, filter);\n }\n\n return success(records.length);\n }\n\n async healthCheck(): Promise<DatabaseResult<DatabaseHealthStatus>> {\n await this.simulateLatency();\n\n return success({\n isHealthy: this.isInitialized,\n responseTime: this.config.latency ?? 0,\n details: {\n adapter: \"mock\",\n tables: this.data.size,\n totalRecords: Array.from(this.data.values()).reduce(\n (sum, table) => sum + table.size,\n 0,\n ),\n } as DatabaseHealthStatus[\"details\"],\n });\n }\n\n // DatabaseAdapterType required methods\n\n async connect(): Promise<void> {\n await this.simulateLatency();\n // Mock adapter doesn't need actual connection\n }\n\n async disconnect(): Promise<void> {\n await this.close();\n }\n\n getClient(): object {\n return {\n type: \"mock\",\n data: this.data,\n config: this.config,\n };\n }\n\n async query<T>(): Promise<T[]> {\n await this.simulateLatency();\n // Mock adapter doesn't execute real SQL\n // This is a stub for compatibility\n return [] as T[];\n }\n\n // Utility methods\n\n /**\n * Get fully-qualified table name with schema\n */\n private getQualifiedTableName(table: string, schema?: string): string {\n const targetSchema = schema ?? this.defaultSchema;\n\n // If table already has schema prefix (e.g., \"tenant_acme.users\"), use as-is\n if (table.includes(\".\")) {\n return table;\n }\n\n // For 'public' schema or non-qualified tables, return table name as-is for simplicity\n // This maintains backwards compatibility with existing tests\n if (targetSchema === \"public\") {\n return table;\n }\n\n // Apply schema prefix for non-public schemas\n return `${targetSchema}.${table}`;\n }\n\n private initializeTableData(\n initialData: Record<string, Record<string, unknown>[]>,\n ): void {\n for (const [table, records] of Object.entries(initialData)) {\n const tableData = new Map<string, Record<string, unknown>>();\n const idColumn = this.getIdColumn(table);\n\n for (const record of records) {\n const id = record[idColumn];\n if (id) {\n tableData.set(String(id), { ...record });\n }\n }\n\n this.data.set(table, tableData);\n }\n }\n\n private getTableData(table: string): TableDataMap {\n // Handle schema-qualified table names\n const qualifiedTable = this.getQualifiedTableName(table);\n\n if (!this.data.has(qualifiedTable)) {\n this.data.set(qualifiedTable, new Map());\n }\n return this.data.get(qualifiedTable)!;\n }\n\n private getIdColumn(table: string): string {\n // Strip schema prefix if present to get base table name for ID column lookup\n const baseTable = table.includes(\".\") ? table.split(\".\")[1] : table;\n return this.tableIdColumns.get(baseTable) ?? \"id\";\n }\n\n private generateId(): string {\n return `mock-${Date.now()}-${Math.random().toString(RANDOM_STRING_BASE).substring(ID_SUBSTRING_START, ID_SUBSTRING_END)}`;\n }\n\n private async simulateLatency(): Promise<void> {\n if (this.config.latency && this.config.latency > 0) {\n await new Promise((resolve) => setTimeout(resolve, this.config.latency));\n }\n }\n\n private shouldFail(): boolean {\n if (!this.config.failRate || this.config.failRate <= 0) return false;\n return Math.random() < this.config.failRate;\n }\n\n private applyFilter<T extends Record<string, unknown>>(\n records: Record<string, unknown>[],\n filter: Filter<T>,\n ): Record<string, unknown>[] {\n const { field, operator, value } = filter;\n const handler = FILTER_OPERATORS[operator];\n\n return records.filter((record: Record<string, unknown>) => {\n const fieldValue = record[field];\n return handler ? handler(fieldValue, value) : true;\n });\n }\n\n private applySort(\n records: Record<string, unknown>[],\n sort: Array<{ field: string; direction: \"asc\" | \"desc\" }>,\n ): Record<string, unknown>[] {\n return records.sort((a, b) => {\n for (const { field, direction } of sort) {\n const aVal = a[field];\n const bVal = b[field];\n\n if (aVal === bVal) continue;\n\n const comparison =\n (aVal as string | number) < (bVal as string | number) ? -1 : 1;\n return direction === \"asc\" ? comparison : -comparison;\n }\n return 0;\n });\n }\n\n /**\n * Test utility: Clear all data\n */\n clearAll(): void {\n this.data.clear();\n }\n\n /**\n * Test utility: Get current data for inspection\n */\n getData(\n table?: string,\n ): Record<string, unknown>[] | Record<string, Record<string, unknown>[]> {\n if (table) {\n return Array.from(this.getTableData(table).values());\n }\n\n const result: Record<string, Record<string, unknown>[]> = {};\n for (const [tableName, tableData] of this.data.entries()) {\n result[tableName] = Array.from(tableData.values());\n }\n return result;\n }\n\n /**\n * Test utility: Set data directly\n */\n setData(table: string, records: Record<string, unknown>[]): void {\n const tableData = new Map<string, Record<string, unknown>>();\n const idColumn = this.getIdColumn(table);\n\n for (const record of records) {\n const id = record[idColumn];\n if (id) {\n tableData.set(String(id), { ...record });\n }\n }\n\n this.data.set(table, tableData);\n }\n}\n","/**\n * @fileoverview Adapter Factory for @plyaz/db package\n *\n * This module provides the AdapterFactory class responsible for creating database adapter instances\n * based on configuration. Supports multiple database adapters including Drizzle ORM, Supabase,\n * and raw SQL adapters.\n *\n * Part of the @plyaz/db package factory system that creates the complete adapter chain:\n * AdapterFactory → Base Adapter → Extension Wrappers → Final Adapter Chain\n *\n */\n\nimport { DrizzleAdapter } from \"@adapters/drizzle/DrizzleAdapter\";\nimport { SupabaseAdapter } from \"@adapters/supabase/SupabaseAdapter\";\nimport { SQLAdapter } from \"@adapters/sql/SQLAdapter\";\nimport { MockAdapter } from \"@adapters/mock/MockAdapter\";\nimport type {\n DatabaseAdapterType,\n DatabaseConfig,\n DrizzleAdapterConfig,\n SQLAdapterConfig,\n SupabaseAdapterConfig,\n DbMockAdapterConfig,\n} from \"@plyaz/types/db\";\nimport { ADAPTERS } from \"@plyaz/types/db\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\n\n/**\n * ADAPTER FACTORY - Database Adapter Creation\n *\n * Factory class responsible for creating database adapter instances based on configuration.\n * This is the first step in the adapter chain creation process.\n *\n * **Factory Pattern Implementation:**\n * - Takes adapter type and configuration as input\n * - Returns appropriate DatabaseAdapterType implementation\n * - Handles type safety and error cases\n * - Supports all available database adapters\n *\n * **Supported Adapters:**\n * - DrizzleAdapter: For Drizzle ORM integration\n * - SupabaseAdapter: For Supabase database integration\n * - SQLAdapter: For raw SQL database operations\n *\n * **Usage Flow:**\n * createDatabaseService() → **AdapterFactory.create()** → Base Adapter → Extension Wrappers\n *\n * @example\n * ```typescript\n * // Create Drizzle adapter\n * const drizzleAdapter = AdapterFactory.create(ADAPTERS.DRIZZLE, {\n * adapter: ADAPTERS.DRIZZLE,\n * connection: { host: 'localhost', port: 5432 },\n * database: 'myapp'\n * });\n *\n * // Create Supabase adapter\n * const supabaseAdapter = AdapterFactory.create(ADAPTERS.SUPABASE, {\n * adapter: ADAPTERS.SUPABASE,\n * url: 'https://project.supabase.co',\n * key: 'your-anon-key'\n * });\n * ```\n *\n */\nexport class AdapterFactory {\n /**\n * Creates a new database adapter instance based on the configuration\n *\n * This is the core factory method that instantiates the appropriate database adapter\n * based on the provided type and configuration. Uses TypeScript generics to ensure\n * type safety between adapter type and configuration.\n *\n * **Creation Process:**\n * 1. Validates input parameters (type and config)\n * 2. Uses switch statement to match adapter type\n * 3. Instantiates appropriate adapter class with type-safe config\n * 4. Returns DatabaseAdapterType interface implementation\n *\n * **Type Safety:**\n * - Generic T extends DatabaseConfig ensures config matches adapter type\n * - Type assertions (as DrizzleAdapterConfig) provide compile-time safety\n * - Runtime validation prevents invalid configurations\n *\n * @template T - Database configuration type that extends DatabaseConfig\n * @param {T[\"adapter\"]} type - Adapter type from ADAPTERS enum (drizzle, supabase, sql)\n * @param {T} config - Database configuration object matching the adapter type\n * @returns {DatabaseAdapterType} The appropriate adapter implementation\n *\n * @throws {Error} If adapter type is not provided\n * @throws {Error} If adapter configuration is not provided\n * @throws {Error} If unsupported adapter type is specified\n * @throws {Error} If adapter instantiation fails\n *\n * @example\n * ```typescript\n * // Create Drizzle adapter with PostgreSQL\n * const drizzleAdapter = AdapterFactory.create(ADAPTERS.DRIZZLE, {\n * adapter: ADAPTERS.DRIZZLE,\n * connection: {\n * host: 'localhost',\n * port: 5432,\n * database: 'myapp',\n * user: 'postgres',\n * password: 'password'\n * }\n * });\n *\n * // Create Supabase adapter\n * const supabaseAdapter = AdapterFactory.create(ADAPTERS.SUPABASE, {\n * adapter: ADAPTERS.SUPABASE,\n * url: 'https://xyzcompany.supabase.co',\n * key: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'\n * });\n *\n * // Create SQL adapter for custom database\n * const sqlAdapter = AdapterFactory.create(ADAPTERS.SQL, {\n * adapter: ADAPTERS.SQL,\n * connectionString: 'postgresql://user:pass@localhost:5432/db'\n * });\n * ```\n *\n */\n static create<T extends DatabaseConfig>(\n type: T[\"adapter\"],\n config: T,\n ): DatabaseAdapterType {\n try {\n // Input validation - ensure required parameters are provided\n // This prevents runtime errors from missing configuration\n if (!type) {\n throw new DatabaseError(\n \"Adapter type is required\",\n DATABASE_ERROR_CODES.CONFIG_REQUIRED,\n {\n context: { source: \"AdapterFactory.create\" },\n cause: new Error(\"Adapter type is required\"),\n },\n );\n }\n\n if (!config) {\n throw new DatabaseError(\n \"Adapter configuration is required\",\n DATABASE_ERROR_CODES.CONFIG_REQUIRED,\n {\n context: { source: \"AdapterFactory.create\" },\n cause: new Error(\"Adapter configuration is required\"),\n },\n );\n }\n\n // Adapter instantiation using switch statement for type safety\n // Each case handles a specific adapter type with appropriate configuration casting\n switch (type) {\n // Drizzle ORM adapter - for type-safe database operations\n case ADAPTERS.DRIZZLE:\n return new DrizzleAdapter(config as DrizzleAdapterConfig);\n\n // Supabase adapter - for Supabase backend-as-a-service integration\n case ADAPTERS.SUPABASE:\n return new SupabaseAdapter(config as SupabaseAdapterConfig);\n\n // SQL adapter - for raw SQL operations and custom database integrations\n case ADAPTERS.SQL:\n return new SQLAdapter(config as SQLAdapterConfig);\n\n // Mock adapter - for in-memory testing without real database\n case ADAPTERS.MOCK:\n return new MockAdapter(config as DbMockAdapterConfig);\n\n // Default case - handles unsupported or invalid adapter types\n default:\n throw new DatabaseError(\n `Unsupported adapter type: ${type}`,\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"AdapterFactory.create\" },\n cause: new Error(`Unsupported adapter type: ${type}`),\n },\n );\n }\n } catch (error) {\n // Error handling with context preservation\n // Wraps any instantiation errors with factory-specific context\n throw new DatabaseError(\n `Failed to create adapter: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.INIT_FAILED,\n {\n context: { source: \"AdapterFactory.create\" },\n cause: error as Error,\n },\n );\n }\n }\n}\n","/**\n * @fileoverview Soft Delete Extension for @plyaz/db package\n *\n * This module provides the SoftDeleteAdapter extension that implements logical deletion\n * instead of physical record removal. It automatically intercepts delete operations\n * and converts them to timestamp updates, while filtering queries to exclude soft-deleted records.\n *\n * Part of the @plyaz/db package - a TypeScript database abstraction layer with\n * support for multiple adapters (Drizzle, Supabase, SQL), extensions (audit, encryption,\n * soft delete), and advanced features (caching, read replicas, multi-tenancy).\n *\n */\n\nimport { logger } from \"@plyaz/logger\";\nimport type {\n DatabaseAdapterType,\n DatabaseResult,\n PaginatedResult,\n QueryOptions,\n Filter,\n DatabaseHealthStatus,\n Transaction,\n} from \"@plyaz/types/db\";\nimport { failure, success } from \"@utils/databaseResultHelpers\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\n\n/**\n * SOFT DELETE ADAPTER - Logical Deletion Layer\n *\n * Soft delete extension that implements logical deletion instead of physical removal.\n * Third layer in the adapter chain.\n *\n * **Adapter Chain Position:**\n * ReadReplica -> Audit -> Cache -> **SoftDelete** -> Encryption -> Base Adapter\n *\n * **What this adapter does:**\n * 1. Intercepts delete() operations sets deletedAt timestamp instead of removing\n * 2. Intercepts query/list operations adds \"WHERE deletedAt IS NULL\" filter\n * 3. Provides restore() method to undelete records\n * 4. Honors includeSoftDeleted flag from operation config\n *\n * **Called by:** CachingAdapter (or AuditAdapter if no caching)\n * **Calls:** EncryptionAdapter (or base adapter if no encryption)\n * **Provides:** restore(), permanentDelete() methods\n *\n * **Soft Delete Flow:**\n * - **Delete:** Sets deletedAt = NOW() instead of removing record\n * - **Queries:** Automatically filters WHERE deletedAt IS NULL\n * - **Restore:** Sets deletedAt = NULL to undelete\n *\n * @example\n * ### Configuration\n * ```typescript\n * softDelete: {\n * enabled: true,\n * field: 'deletedAt', // Custom field name\n * excludeTables: ['audit_logs'] // Tables that use hard delete\n * }\n * ```\n *\n * @example\n * ### Usage Flow\n * ```typescript\n * // Normal delete - sets deletedAt timestamp\n * await db.delete(Tables.USERS, 'user-123');\n *\n * // Query automatically excludes soft-deleted records\n * const activeUsers = await db.query(Tables.USERS, {});\n *\n * // Include soft-deleted records with operation config\n * const allUsers = await db.query(Tables.USERS, {}, {\n * includeSoftDeleted: true\n * });\n *\n * // Restore soft-deleted record\n * await db.restore(Tables.USERS, 'user-123');\n * ```\n */\nexport class SoftDeleteAdapter implements DatabaseAdapterType {\n /**\n * Creates a new SoftDeleteAdapter instance.\n *\n * **RESPONSIBILITY:** Wraps base adapter with soft delete functionality\n * **CONFIGURATION:** Sets up deletion field name and excluded tables\n *\n * @param baseAdapter - The underlying database adapter to wrap\n * @param config - Soft delete configuration options\n *\n * @example\n * ```typescript\n * const softDeleteAdapter = new SoftDeleteAdapter(baseAdapter, {\n * enabled: true,\n * field: 'deletedAt',\n * excludeTables: ['audit_logs', 'system_events']\n * });\n * ```\n */\n constructor(\n public baseAdapter: DatabaseAdapterType,\n private config: {\n enabled: boolean;\n field?: string;\n excludeTables?: string[];\n },\n ) {}\n\n /**\n * Initializes the soft delete adapter and underlying adapter.\n *\n * **RESPONSIBILITY:** Passes initialization to base adapter\n * **BEHAVIOR:** No additional initialization needed for soft delete\n *\n * @returns Promise resolving to initialization result\n *\n * @example\n * ```typescript\n * const result = await softDeleteAdapter.initialize();\n * if (result.success) {\n * console.log('Soft delete adapter initialized');\n * }\n * ```\n */\n async initialize(): Promise<DatabaseResult<void>> {\n return this.baseAdapter.initialize();\n }\n\n /**\n * Establishes database connection through base adapter.\n *\n * **RESPONSIBILITY:** Delegates connection to underlying adapter\n * **BEHAVIOR:** No additional connection logic needed\n *\n * @example\n * ```typescript\n * await softDeleteAdapter.connect();\n * console.log('Connected with soft delete support');\n * ```\n */\n async connect(): Promise<void> {\n return this.baseAdapter.connect();\n }\n\n /**\n * Closes database connection through base adapter.\n *\n * **RESPONSIBILITY:** Delegates disconnection to underlying adapter\n * **BEHAVIOR:** No additional cleanup needed for soft delete\n *\n * @example\n * ```typescript\n * await softDeleteAdapter.disconnect();\n * console.log('Disconnected gracefully');\n * ```\n */\n async disconnect(): Promise<void> {\n return this.baseAdapter.disconnect();\n }\n\n async close(): Promise<DatabaseResult<void>> {\n return this.baseAdapter.close();\n }\n\n /**\n * Gets the underlying database client.\n *\n * **RESPONSIBILITY:** Provides access to raw database client\n * **USE CASE:** For operations that bypass soft delete logic\n *\n * @returns Database client object\n *\n * @example\n * ```typescript\n * const client = softDeleteAdapter.getClient();\n * // Use for direct database operations if needed\n * ```\n */\n getClient(): object {\n return this.baseAdapter.getClient();\n }\n\n /**\n * Executes raw SQL query through base adapter.\n *\n * **RESPONSIBILITY:** Passes raw SQL to base adapter without modification\n * **BEHAVIOR:** Does not apply soft delete filtering to raw SQL\n * **NOTE:** Use findMany() for automatic soft delete filtering\n *\n * @param sql - SQL query string\n * @param params - Query parameters\n * @returns Query results\n *\n * @example\n * ```typescript\n * // Raw SQL bypasses soft delete filtering\n * const allUsers = await adapter.query(\n * 'SELECT * FROM users', // Includes soft-deleted records\n * []\n * );\n *\n * // Use findMany for automatic filtering\n * const activeUsers = await adapter.findMany('users'); // Excludes soft-deleted\n * ```\n */\n async query<T>(sql: string, params?: T[]): Promise<T[]> {\n return this.baseAdapter.query(sql, params);\n }\n\n /**\n * Registers a table schema with the base adapter.\n *\n * **RESPONSIBILITY:** Passes table registration to base adapter\n * **BEHAVIOR:** No additional registration logic needed\n *\n * @param name - Table name\n * @param table - Table schema\n * @param idColumn - Primary key column\n *\n * @example\n * ```typescript\n * softDeleteAdapter.registerTable('users', userSchema, 'id');\n * // Table now supports soft delete operations\n * ```\n */\n registerTable<T, U>(name: string, table: T, idColumn?: U): void {\n this.baseAdapter.registerTable(name, table, idColumn);\n }\n\n /**\n * Finds a record by ID with automatic soft delete filtering.\n *\n * **RESPONSIBILITY:** Retrieves single record, excluding soft-deleted by default\n * **FILTERING:** Automatically excludes records where deletedAt IS NOT NULL\n * **OVERRIDE:** Can include soft-deleted records with operation config\n *\n * @param table - Table name\n * @param id - Record ID\n * @returns Found record or null\n *\n * @example\n * ```typescript\n * // Excludes soft-deleted records by default\n * const user = await adapter.findById('users', 'user-123');\n * if (!user.value) {\n * console.log('User not found or soft-deleted');\n * }\n *\n * // Include soft-deleted records with config\n * const userIncludingDeleted = await adapter.findById('users', 'user-123', {\n * includeSoftDeleted: true\n * });\n * ```\n */\n async findById<T>(\n table: string,\n id: string,\n ): Promise<DatabaseResult<T | null>> {\n return this.baseAdapter.findById<T>(table, id);\n }\n\n async findMany<T extends Record<string, unknown>>(\n table: string,\n options?: QueryOptions<T>,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n if (!this.config.enabled || this.isExcluded(table)) {\n return this.baseAdapter.findMany<T>(table, options);\n }\n\n // Add soft delete filter unless includeSoftDeleted is true\n const modifiedOptions: QueryOptions<T> = { ...options };\n modifiedOptions.filter ??= {\n field: this.config.field ?? \"deletedAt\",\n operator: \"isNull\",\n value: null,\n } as Filter<T>;\n\n return this.baseAdapter.findMany<T>(table, modifiedOptions);\n }\n\n /**\n * Creates a new record through base adapter.\n *\n * **RESPONSIBILITY:** Passes creation to base adapter without modification\n * **BEHAVIOR:** New records have deletedAt = NULL by default\n *\n * @param table - Table name\n * @param data - Record data\n * @returns Created record\n *\n * @example\n * ```typescript\n * const result = await adapter.create('users', {\n * name: 'John Doe',\n * email: 'john@example.com'\n * // deletedAt will be NULL (not soft-deleted)\n * });\n *\n * if (result.success) {\n * console.log('User created:', result.value.id);\n * }\n * ```\n */\n async create<T extends Record<string, unknown>>(\n table: string,\n data: T,\n ): Promise<DatabaseResult<T>> {\n return this.baseAdapter.create<T>(table, data);\n }\n\n /**\n * Updates an existing record through base adapter.\n *\n * **RESPONSIBILITY:** Passes update to base adapter without modification\n * **BEHAVIOR:** Can update soft-deleted records (they remain soft-deleted)\n * **NOTE:** Use restore() to undelete records\n *\n * @param table - Table name\n * @param id - Record ID\n * @param data - Partial record data\n * @returns Updated record\n *\n * @example\n * ```typescript\n * // Update active record\n * const result = await adapter.update('users', 'user-123', {\n * name: 'Jane Doe'\n * });\n *\n * // Can also update soft-deleted records\n * const softDeletedUpdate = await adapter.update('users', 'deleted-user', {\n * email: 'newemail@example.com'\n * // Record remains soft-deleted after update\n * });\n * ```\n */\n async update<T>(\n table: string,\n id: string,\n data: Partial<T>,\n ): Promise<DatabaseResult<T>> {\n return this.baseAdapter.update<T>(table, id, data);\n }\n\n async delete(table: string, id: string): Promise<DatabaseResult<void>> {\n if (!this.config.enabled || this.isExcluded(table)) {\n return this.baseAdapter.delete(table, id);\n }\n\n // Soft delete: set deletedAt field\n const deleteField = this.config.field ?? \"deletedAt\";\n const updateData = { [deleteField]: new Date().toISOString() };\n\n try {\n logger.debug(`Soft deleting record ${id} from table ${table}`);\n await this.baseAdapter.update(table, id, updateData);\n return success();\n } catch (error) {\n logger.error(`Soft delete failed for ${table}:${id}`);\n return failure(\n new DatabaseError(\n `Soft delete failed: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.DELETE_FAILED,\n {\n context: { source: \"delete\" },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Executes operations within a transaction.\n *\n * **RESPONSIBILITY:** Passes transaction to base adapter\n * **BEHAVIOR:** Soft delete operations within transaction are atomic\n * **ROLLBACK:** Failed transactions rollback soft delete operations\n *\n * @param callback - Transaction callback function\n * @returns Transaction result\n *\n * @example\n * ```typescript\n * const result = await adapter.transaction(async (trx) => {\n * // Create user\n * const user = await trx.create('users', { name: 'John' });\n *\n * // Soft delete old user (sets deletedAt)\n * await trx.delete('users', 'old-user-id');\n *\n * return user;\n * });\n *\n * // If transaction fails, both operations are rolled back\n * ```\n */\n async transaction<T>(\n callback: (trx: Transaction) => Promise<T>,\n ): Promise<DatabaseResult<T>> {\n return this.baseAdapter.transaction(callback);\n }\n\n /**\n * Checks if a record exists, excluding soft-deleted records.\n *\n * **RESPONSIBILITY:** Verifies record existence with soft delete filtering\n * **BEHAVIOR:** Returns false for soft-deleted records by default\n * **FILTERING:** Automatically excludes records where deletedAt IS NOT NULL\n *\n * @param table - Table name\n * @param id - Record ID\n * @returns True if record exists and is not soft-deleted\n *\n * @example\n * ```typescript\n * // Check if active user exists\n * const userExists = await adapter.exists('users', 'user-123');\n * if (userExists.value) {\n * console.log('User exists and is active');\n * } else {\n * console.log('User not found or soft-deleted');\n * }\n *\n * // Soft-deleted records return false\n * await adapter.delete('users', 'user-123'); // Soft delete\n * const stillExists = await adapter.exists('users', 'user-123'); // false\n * ```\n */\n async exists(table: string, id: string): Promise<DatabaseResult<boolean>> {\n return this.baseAdapter.exists(table, id);\n }\n\n /**\n * Counts records in a table, excluding soft-deleted records.\n *\n * **RESPONSIBILITY:** Counts records with automatic soft delete filtering\n * **BEHAVIOR:** Excludes soft-deleted records from count by default\n * **FILTERING:** Automatically adds deletedAt IS NULL filter\n *\n * @param table - Table name\n * @param filter - Optional filter conditions\n * @returns Count of non-soft-deleted records\n *\n * @example\n * ```typescript\n * // Count active users only\n * const activeCount = await adapter.count('users');\n * console.log('Active users:', activeCount.value);\n *\n * // Count with additional filter\n * const premiumActiveUsers = await adapter.count('users', {\n * field: 'plan',\n * operator: 'eq',\n * value: 'premium'\n * });\n * // Returns count of premium users that are NOT soft-deleted\n * ```\n */\n async count<T extends Record<string, unknown> = Record<string, unknown>>(\n table: string,\n filter?: Filter<T>,\n ): Promise<DatabaseResult<number>> {\n return this.baseAdapter.count<T>(table, filter);\n }\n\n /**\n * Performs health check through base adapter.\n *\n * **RESPONSIBILITY:** Delegates health check to underlying adapter\n * **BEHAVIOR:** No additional health metrics for soft delete\n *\n * @returns Health status from base adapter\n *\n * @example\n * ```typescript\n * const health = await adapter.healthCheck();\n * if (health.success && health.value?.isHealthy) {\n * console.log('Database healthy with soft delete support');\n * }\n * ```\n */\n async healthCheck(): Promise<DatabaseResult<DatabaseHealthStatus>> {\n return this.baseAdapter.healthCheck();\n }\n\n /**\n * Restores a previously soft-deleted record by clearing the deletion timestamp\n *\n * Undeletes a record by setting the soft delete field (typically 'deletedAt') to null,\n * making it visible in queries again. This operation is only available when soft delete\n * is enabled in the configuration.\n *\n * **Restore Process:**\n * 1. Validates that soft delete is enabled\n * 2. Sets the deletion field to null via update operation\n * 3. Logs the restoration for audit purposes\n * 4. Returns success or failure result\n *\n * @param {string} table - Name of the table containing the record to restore\n * @param {string} id - Primary key ID of the record to restore\n * @returns {Promise<DatabaseResult<void>>} Promise resolving to success/failure result\n *\n * @example\n * ```typescript\n * // Restore a soft-deleted user\n * const restoreResult = await softDeleteAdapter.restore('users', 'user-123');\n * if (restoreResult.success) {\n * console.log('User restored successfully');\n * } else {\n * console.error('Restore failed:', restoreResult.error.message);\n * }\n *\n * // After restoration, the record will appear in queries again\n * const user = await adapter.findById('users', 'user-123');\n * // user will now be found (not null)\n * ```\n *\n * @throws {DatabaseError} SOFT_DELETE_NOT_ENABLED - If soft delete is not enabled in configuration\n * @throws {DatabaseError} SOFT_DELETE_RESTORE_FAILED - If the restore operation fails\n *\n */\n async restore(table: string, id: string): Promise<DatabaseResult<void>> {\n // Validate that soft delete is enabled before attempting restore\n if (!this.config.enabled) {\n return failure(\n new DatabaseError(\n \"Soft delete not enabled\",\n DATABASE_ERROR_CODES.CONFIG_REQUIRED,\n {\n context: { source: \"restore\" },\n cause: new Error(\"Soft delete not enabled\"),\n },\n ),\n );\n }\n\n // Get the configured deletion field name (default: 'deletedAt')\n const deleteField = this.config.field ?? \"deletedAt\";\n // Create update data to clear the deletion timestamp\n const updateData = { [deleteField]: null };\n\n try {\n // Update the record to clear the deletion timestamp\n await this.baseAdapter.update(table, id, updateData);\n logger.info(`Record restored successfully: ${table}:${id}`);\n return success();\n } catch (error) {\n logger.error(`Restore failed for ${table}:${id}`);\n return failure(\n new DatabaseError(\n `Restore failed: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.UPDATE_FAILED,\n {\n context: { source: \"restore\" },\n cause: error as Error,\n },\n ),\n );\n }\n }\n\n /**\n * Checks if a table is excluded from soft delete functionality.\n * \n * **RESPONSIBILITY:** Determines if table should use hard delete instead\n * **CONFIGURATION:** Based on excludeTables array in config\n * **USE CASE:** Some tables like audit logs need permanent deletion\n * \n * @private\n * @param table - Name of the table to check\n * @returns True if table is excluded from soft delete\n * \n * @example\n * ```typescript\n * // Configuration: { excludeTables: ['audit_logs', 'temp_data'] }\n * \n * this.isExcluded('users'); // false - uses soft delete\n * this.isExcluded('audit_logs'); // true - uses hard delete\n * this.isExcluded('t\n private isExcluded(table: string): boolean {\n return this.config.excludeTables?.includes(table) ?? false;\n }emp_data'); // true - uses hard delete\n * ```\n * \n */\n private isExcluded(table: string): boolean {\n // Check if table is in the excludeTables array, default to false if not configured\n return this.config.excludeTables?.includes(table) ?? false;\n }\n}\n","import { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport { logger } from \"@plyaz/logger\";\nimport type {\n DatabaseAdapterType,\n DatabaseResult,\n Filter,\n DatabaseHealthStatus,\n PaginatedResult,\n QueryOptions,\n Transaction,\n AuditContext,\n AuditEvent,\n} from \"@plyaz/types/db\";\nimport { AUDIT_OPERATION, EXTENSION_SOURCE } from \"@plyaz/types/db\";\n\n/** Minimum width for padded date parts (month, day) */\nconst DATE_PART_MIN_WIDTH = 2;\n\n/** Error source patterns for context-based matching */\nconst CONTEXT_SOURCE_PATTERNS: Array<{\n patterns: string[];\n source: EXTENSION_SOURCE;\n}> = [\n { patterns: [\"encrypt\"], source: EXTENSION_SOURCE.Encryption },\n {\n patterns: [\"softdelete\", \"soft_delete\"],\n source: EXTENSION_SOURCE.SoftDelete,\n },\n { patterns: [\"cach\"], source: EXTENSION_SOURCE.Caching },\n { patterns: [\"audit\"], source: EXTENSION_SOURCE.Audit },\n {\n patterns: [\"replica\", \"read_replica\"],\n source: EXTENSION_SOURCE.ReadReplica,\n },\n {\n patterns: [\"multi_write\", \"multiwrite\"],\n source: EXTENSION_SOURCE.MultiWrite,\n },\n];\n\n/** Error source patterns for message-based matching */\nconst MESSAGE_SOURCE_PATTERNS: Array<{\n patterns: string[];\n source: EXTENSION_SOURCE;\n}> = [\n { patterns: [\"encrypt\"], source: EXTENSION_SOURCE.Encryption },\n {\n patterns: [\"soft delete\", \"softdelete\"],\n source: EXTENSION_SOURCE.SoftDelete,\n },\n { patterns: [\"cache\", \"caching\"], source: EXTENSION_SOURCE.Caching },\n {\n patterns: [\"replica\", \"read replica\"],\n source: EXTENSION_SOURCE.ReadReplica,\n },\n {\n patterns: [\"multi-write\", \"multiwrite\"],\n source: EXTENSION_SOURCE.MultiWrite,\n },\n];\n\n/**\n * AUDIT ADAPTER - Compliance Logging Layer\n *\n * Audit extension that automatically logs all database operations for compliance.\n * Fifth layer in the adapter chain (second from outermost).\n *\n * **Adapter Chain Position:**\n * ReadReplica � **Audit** � Cache � SoftDelete � Encryption � Base Adapter\n *\n * **What this adapter does:**\n * 1. Captures before-state for update/delete operations\n * 2. Delegates to next adapter in chain\n * 3. Captures after-state and writes audit record to daily audit tables\n * 4. Calls onAuditAfterWrite event handler (if configured)\n * 5. Honors skipAudit flag from operation config\n *\n * **Called by:** ReadReplicaAdapter (or DatabaseService if no read replicas)\n * **Calls:** CachingAdapter (or next adapter in chain)\n * **Writes to:** Daily partitioned audit tables ({schema}.audit_log_yyyy_mm_dd)\n *\n * **Audit Flow:**\n * 1. **CREATE:** Records after-state only\n * 2. **UPDATE:** Records before-state, after-state, and changed fields\n * 3. **DELETE:** Records before-state only\n * 4. **SOFT_DELETE:** Records before/after state with deletedAt change\n *\n * **Audit Context:** Uses context from DatabaseService.setAuditContext()\n * - userId, requestId, ipAddress, userAgent\n *\n * @example\n * ### Configuration\n * ```typescript\n * audit: {\n * enabled: true,\n * retentionDays: 90,\n * excludeFields: ['password', 'token'],\n * excludeTables: ['temp_data'],\n * onAuditAfterWrite: async (event) => {\n * await complianceService.recordAudit(event);\n * }\n * }\n * ```\n *\n * @example\n * ### Audit Record Structure\n * ```typescript\n * // Written to audit_20241201 table\n * {\n * operation: 'UPDATE',\n * table: 'users',\n * recordId: 'user-123',\n * userId: 'admin-456',\n * requestId: 'req-789',\n * changes: {\n * before: { name: 'John Doe', email: 'john@old.com' },\n * after: { name: 'John Smith', email: 'john@new.com' },\n * fields: ['name', 'email']\n * },\n * timestamp: '2024-12-01T10:30:00Z',\n * ipAddress: '192.168.1.1',\n * userAgent: 'Mozilla/5.0...'\n * }\n * ```\n */\nexport class AuditAdapter implements DatabaseAdapterType {\n private auditContext: AuditContext = {};\n // Using shared logger instance from @plyaz/logger\n\n /** Cached schema-qualified table name */\n private auditSchema: string;\n /** Whether to use daily partitioned tables */\n private usePartitionedTables: boolean;\n\n /**\n * Creates a new AuditAdapter instance.\n *\n * **RESPONSIBILITY:** Wraps base adapter with audit logging functionality\n * **CONFIGURATION:** Sets up audit rules, retention, and event handlers\n *\n * @param baseAdapter - The underlying database adapter to wrap\n * @param config - Audit configuration options\n *\n * @example\n * ```typescript\n * const auditAdapter = new AuditAdapter(baseAdapter, {\n * enabled: true,\n * retentionDays: 180,\n * excludeFields: ['password', 'token'],\n * excludeTables: ['temp_data'],\n * schema: 'audit',\n * usePartitionedTables: true,\n * onAuditAfterWrite: async (event) => {\n * await complianceService.recordAudit(event);\n * }\n * });\n * ```\n */\n constructor(\n public baseAdapter: DatabaseAdapterType,\n private config: {\n enabled: boolean;\n retentionDays?: number;\n excludeFields?: string[];\n excludeTables?: string[];\n /** Database schema for audit tables (default: 'audit') */\n schema?: string;\n /** Use daily partitioned tables (audit_log_yyyy_mm_dd format) (default: true) */\n usePartitionedTables?: boolean;\n onAuditAfterWrite?: (event: AuditEvent) => void | Promise<void>;\n /** Encrypted fields config from encryption extension (for audit metadata) */\n encryptedFields?: Record<string, string[]>;\n },\n ) {\n this.auditSchema = config.schema ?? \"audit\";\n this.usePartitionedTables = config.usePartitionedTables ?? true;\n }\n\n /**\n * Initializes the audit adapter and underlying adapter.\n *\n * **RESPONSIBILITY:** Passes initialization to base adapter\n * **BEHAVIOR:** No additional initialization needed for audit\n *\n * @returns Promise resolving to initialization result\n *\n * @example\n * ```typescript\n * const result = await auditAdapter.initialize();\n * if (result.success) {\n * console.log('Audit adapter initialized');\n * }\n * ```\n */\n async initialize(): Promise<DatabaseResult<void>> {\n return this.baseAdapter.initialize();\n }\n\n /**\n * Establishes database connection through base adapter.\n *\n * **RESPONSIBILITY:** Delegates connection to underlying adapter\n * **BEHAVIOR:** No additional connection logic needed\n *\n * @example\n * ```typescript\n * await auditAdapter.connect();\n * console.log('Connected with audit support');\n * ```\n */\n async connect(): Promise<void> {\n return this.baseAdapter.connect();\n }\n\n /**\n * Closes database connection through base adapter.\n *\n * **RESPONSIBILITY:** Delegates disconnection to underlying adapter\n * **BEHAVIOR:** No additional cleanup needed for audit\n *\n * @example\n * ```typescript\n * await auditAdapter.disconnect();\n * console.log('Disconnected gracefully');\n * ```\n */\n async disconnect(): Promise<void> {\n return this.baseAdapter.disconnect();\n }\n\n async close(): Promise<DatabaseResult<void>> {\n return this.baseAdapter.close();\n }\n\n /**\n * Gets the underlying database client.\n *\n * **RESPONSIBILITY:** Provides access to raw database client\n * **USE CASE:** For operations that bypass audit logging\n *\n * @returns Database client object\n *\n * @example\n * ```typescript\n * const client = auditAdapter.getClient();\n * // Use for direct database operations if needed\n * ```\n */\n getClient(): object {\n return this.baseAdapter.getClient();\n }\n\n /**\n * Executes raw SQL query through base adapter.\n *\n * **RESPONSIBILITY:** Passes raw SQL to base adapter without audit logging\n * **BEHAVIOR:** Does not audit raw SQL operations\n * **NOTE:** Use CRUD methods for automatic audit logging\n *\n * @param sql - SQL query string\n * @param params - Query parameters\n * @returns Query results\n *\n * @example\n * ```typescript\n * // Raw SQL bypasses audit logging\n * const results = await adapter.query(\n * 'SELECT * FROM users WHERE status = $1',\n * ['active']\n * );\n *\n * // Use findMany for automatic audit logging\n * const users = await adapter.findMany('users', { filter: ... });\n * ```\n */\n async query<T>(sql: string, params?: T[]): Promise<T[]> {\n return this.baseAdapter.query(sql, params);\n }\n\n /**\n * Registers a table schema with the base adapter.\n *\n * **RESPONSIBILITY:** Passes table registration to base adapter\n * **BEHAVIOR:** No additional registration logic needed\n *\n * @param name - Table name\n * @param table - Table schema\n * @param idColumn - Primary key column\n *\n * @example\n * ```typescript\n * auditAdapter.registerTable('users', userSchema, 'id');\n * // Table now supports audited operations\n * ```\n */\n registerTable<T, U>(name: string, table: T, idColumn?: U): void {\n this.baseAdapter.registerTable(name, table, idColumn);\n }\n\n /**\n * Sets audit context for tracking user actions.\n *\n * **RESPONSIBILITY:** Stores context information for audit records\n * **CONTEXT:** userId, requestId, ipAddress, userAgent\n * **USAGE:** Called by DatabaseService.setAuditContext()\n *\n * @param context - Audit context information\n *\n * @example\n * ```typescript\n * // Usually called by middleware\n * auditAdapter.setAuditContext({\n * userId: 'user-123',\n * requestId: 'req-456',\n * ipAddress: '192.168.1.1',\n * userAgent: 'Mozilla/5.0...'\n * });\n *\n * // Subsequent operations will include this context in audit logs\n * await adapter.create('users', userData); // Audited with context\n * ```\n */\n setAuditContext(context: AuditContext): void {\n this.auditContext = { ...this.auditContext, ...context };\n }\n\n /**\n * Finds a record by ID without audit logging.\n *\n * **RESPONSIBILITY:** Retrieves single record without creating audit trail\n * **BEHAVIOR:** Read operations are not audited by default\n * **PERFORMANCE:** No audit overhead for read operations\n *\n * @param table - Table name\n * @param id - Record ID\n * @returns Found record or null\n *\n * @example\n * ```typescript\n * // Read operations don't create audit records\n * const user = await adapter.findById('users', 'user-123');\n * if (user.success && user.value) {\n * console.log('User found:', user.value.name);\n * }\n * ```\n */\n async findById<T>(\n table: string,\n id: string,\n ): Promise<DatabaseResult<T | null>> {\n return this.baseAdapter.findById<T>(table, id);\n }\n\n /**\n * Finds multiple records without audit logging.\n *\n * **RESPONSIBILITY:** Retrieves multiple records without creating audit trail\n * **BEHAVIOR:** Read operations are not audited by default\n * **PERFORMANCE:** No audit overhead for read operations\n *\n * @param table - Table name\n * @param options - Query options\n * @returns Paginated results\n *\n * @example\n * ```typescript\n * // Read operations don't create audit records\n * const users = await adapter.findMany('users', {\n * filter: { field: 'status', operator: 'eq', value: 'active' },\n * pagination: { page: 1, limit: 10 }\n * });\n *\n * console.log('Found users:', users.value?.data.length);\n * ```\n */\n async findMany<T extends Record<string, unknown>>(\n table: string,\n options?: QueryOptions<T>,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n return this.baseAdapter.findMany<T>(table, options);\n }\n\n async create<T extends Record<string, unknown>>(\n table: string,\n data: T,\n ): Promise<DatabaseResult<T>> {\n this.validateCreateParams(table, data);\n\n try {\n const result = await this.baseAdapter.create<T>(table, data);\n\n if (result.success && this.shouldAudit(table)) {\n await this.logAudit({\n operation: AUDIT_OPERATION.Create,\n table,\n recordId: (result.value as Record<string, string>)?.id,\n changes: {\n after: result.value as Record<\n string,\n string | number | boolean | Date\n >,\n encryptedFields: this.getEncryptedFields(table),\n },\n userId: this.auditContext.userId,\n requestId: this.auditContext.requestId,\n timestamp: new Date(),\n ipAddress: this.auditContext.ipAddress,\n userAgent: this.auditContext.userAgent,\n });\n }\n\n return result;\n } catch (error) {\n // Log the failure to audit before re-throwing\n if (this.shouldAudit(table)) {\n await this.logOperationFailure({\n operation: AUDIT_OPERATION.Create,\n table,\n data,\n error: error as Error,\n });\n }\n throw error;\n }\n }\n\n private validateCreateParams<T>(table: string, data: T): void {\n if (!table || !data) {\n throw new DatabaseError(\n \"Invalid parameters for create operation\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"validateCreateParams\" },\n cause: new Error(\"Invalid parameters for create operation\"),\n },\n );\n }\n }\n\n async update<T>(\n table: string,\n id: string,\n data: Partial<T>,\n ): Promise<DatabaseResult<T>> {\n // Get before state for audit (before any operation)\n const before = await this.baseAdapter.findById(table, id);\n\n try {\n const result = await this.baseAdapter.update<T>(table, id, data);\n\n if (result.success && this.shouldAudit(table)) {\n await this.logAudit({\n operation: AUDIT_OPERATION.Update,\n table,\n recordId: id,\n changes: {\n before: before.success\n ? (before.value as Record<\n string,\n string | number | boolean | Date\n >)\n : undefined,\n after: result.value as Record<\n string,\n string | number | boolean | Date\n >,\n fields: Object.keys(data),\n encryptedFields: this.getEncryptedFields(table),\n },\n userId: this.auditContext.userId,\n requestId: this.auditContext.requestId,\n timestamp: new Date(),\n ipAddress: this.auditContext.ipAddress,\n userAgent: this.auditContext.userAgent,\n });\n }\n\n return result;\n } catch (error) {\n // Log the failure to audit before re-throwing\n if (this.shouldAudit(table)) {\n await this.logOperationFailure({\n operation: AUDIT_OPERATION.Update,\n table,\n data,\n error: error as Error,\n recordId: id,\n beforeState: before.value,\n });\n }\n throw error;\n }\n }\n\n async delete(table: string, id: string): Promise<DatabaseResult<void>> {\n // Get before state for audit\n const before = await this.baseAdapter.findById(table, id);\n\n try {\n const result = await this.baseAdapter.delete(table, id);\n\n if (result.success && this.shouldAudit(table)) {\n await this.logAudit({\n operation: AUDIT_OPERATION.Delete,\n table,\n recordId: id,\n changes: {\n before: before.success\n ? (before.value as Record<\n string,\n string | number | boolean | Date\n >)\n : undefined,\n },\n userId: this.auditContext.userId,\n requestId: this.auditContext.requestId,\n timestamp: new Date(),\n ipAddress: this.auditContext.ipAddress,\n userAgent: this.auditContext.userAgent,\n });\n }\n\n return result;\n } catch (error) {\n // Log the failure to audit before re-throwing\n if (this.shouldAudit(table)) {\n await this.logOperationFailure({\n operation: AUDIT_OPERATION.Delete,\n table,\n data: null,\n error: error as Error,\n recordId: id,\n beforeState: before.value,\n });\n }\n throw error;\n }\n }\n\n /**\n * Logs operation failures to audit for compliance tracking.\n * Captures the before state, attempted changes, and error details.\n */\n private async logOperationFailure<T>(options: {\n operation: AUDIT_OPERATION;\n table: string;\n data: T | null;\n error: Error;\n recordId?: string;\n beforeState?: unknown;\n }): Promise<void> {\n const { operation, table, data, error, recordId, beforeState } = options;\n\n try {\n // Determine error source (which extension failed)\n const errorSource = this.getErrorSource(error);\n\n // Map operation to failed operation\n const failedOperation = this.getFailedOperation(operation);\n\n await this.logAudit({\n operation: failedOperation,\n table,\n recordId: recordId ?? (data as Record<string, string>)?.id,\n changes: {\n before: beforeState as\n | Record<string, string | number | boolean | Date>\n | undefined,\n attempted: data as\n | Record<string, string | number | boolean | Date>\n | undefined,\n failure: {\n source: errorSource,\n error_type: error.name,\n error_message: error.message,\n error_code: (error as DatabaseError).errorCode,\n },\n },\n userId: this.auditContext.userId,\n requestId: this.auditContext.requestId,\n timestamp: new Date(),\n ipAddress: this.auditContext.ipAddress,\n userAgent: this.auditContext.userAgent,\n });\n } catch (auditError) {\n // Log to console if audit write fails - don't suppress the original error\n logger.error(\n `Failed to log operation failure to audit: ${(auditError as Error).message}`,\n );\n }\n }\n\n /**\n * Maps a successful operation to its failed counterpart.\n */\n private getFailedOperation(operation: AUDIT_OPERATION): AUDIT_OPERATION {\n switch (operation) {\n case AUDIT_OPERATION.Create:\n return AUDIT_OPERATION.CreateFailed;\n case AUDIT_OPERATION.Update:\n return AUDIT_OPERATION.UpdateFailed;\n case AUDIT_OPERATION.Delete:\n return AUDIT_OPERATION.DeleteFailed;\n default:\n return operation;\n }\n }\n\n /**\n * Determines which extension/layer caused the error based on error details.\n */\n private getErrorSource(error: Error): EXTENSION_SOURCE {\n const errorMessage = error.message.toLowerCase();\n const dbError = error as DatabaseError;\n const errorContext = (\n dbError.context as { source?: string }\n )?.source?.toLowerCase();\n\n // Check error context first (most reliable)\n if (errorContext) {\n const contextSource = this.matchPatterns(\n errorContext,\n CONTEXT_SOURCE_PATTERNS,\n );\n if (contextSource) return contextSource;\n }\n\n // Fallback to error message analysis\n const messageSource = this.matchPatterns(\n errorMessage,\n MESSAGE_SOURCE_PATTERNS,\n );\n if (messageSource) return messageSource;\n\n return EXTENSION_SOURCE.DatabaseAdapter;\n }\n\n /**\n * Matches a text against a list of pattern groups.\n */\n private matchPatterns(\n text: string,\n patternGroups: Array<{ patterns: string[]; source: EXTENSION_SOURCE }>,\n ): EXTENSION_SOURCE | null {\n for (const { patterns, source } of patternGroups) {\n if (patterns.some((pattern) => text.includes(pattern))) {\n return source;\n }\n }\n return null;\n }\n\n /**\n * Gets the list of encrypted fields for a table.\n * Returns undefined if no fields are encrypted for this table.\n */\n private getEncryptedFields(table: string): string[] | undefined {\n return this.config.encryptedFields?.[table];\n }\n\n /**\n * Executes operations within a transaction with audit logging.\n *\n * **RESPONSIBILITY:** Passes transaction to base adapter\n * **BEHAVIOR:** Individual operations within transaction are audited\n * **ATOMICITY:** Audit records are part of the transaction\n *\n * @param callback - Transaction callback function\n * @returns Transaction result\n *\n * @example\n * ```typescript\n * const result = await adapter.transaction(async (trx) => {\n * // Each operation creates audit record within transaction\n * const user = await trx.create('users', { name: 'John' });\n * await trx.update('profiles', 'profile-1', { userId: user.id });\n * return user;\n * });\n *\n * // If transaction fails, audit records are also rolled back\n * ```\n */\n async transaction<T>(\n callback: (trx: Transaction) => Promise<T>,\n ): Promise<DatabaseResult<T>> {\n return this.baseAdapter.transaction(callback);\n }\n\n /**\n * Checks if a record exists without audit logging.\n *\n * **RESPONSIBILITY:** Verifies record existence without creating audit trail\n * **BEHAVIOR:** Read operations are not audited by default\n * **PERFORMANCE:** No audit overhead for existence checks\n *\n * @param table - Table name\n * @param id - Record ID\n * @returns True if record exists\n *\n * @example\n * ```typescript\n * // Existence checks don't create audit records\n * const userExists = await adapter.exists('users', 'user-123');\n * if (userExists.value) {\n * console.log('User exists');\n * }\n * ```\n */\n async exists(table: string, id: string): Promise<DatabaseResult<boolean>> {\n return this.baseAdapter.exists(table, id);\n }\n\n /**\n * Counts records without audit logging.\n *\n * **RESPONSIBILITY:** Counts records without creating audit trail\n * **BEHAVIOR:** Read operations are not audited by default\n * **PERFORMANCE:** No audit overhead for counting operations\n *\n * @param table - Table name\n * @param filter - Optional filter conditions\n * @returns Count of records\n *\n * @example\n * ```typescript\n * // Count operations don't create audit records\n * const activeUsers = await adapter.count('users', {\n * field: 'status',\n * operator: 'eq',\n * value: 'active'\n * });\n *\n * console.log('Active users:', activeUsers.value);\n * ```\n */\n async count<T extends Record<string, unknown> = Record<string, unknown>>(\n table: string,\n filter?: Filter<T>,\n ): Promise<DatabaseResult<number>> {\n return this.baseAdapter.count<T>(table, filter);\n }\n\n /**\n * Performs health check through base adapter.\n *\n * **RESPONSIBILITY:** Delegates health check to underlying adapter\n * **BEHAVIOR:** No additional health metrics for audit\n *\n * @returns Health status from base adapter\n *\n * @example\n * ```typescript\n * const health = await adapter.healthCheck();\n * if (health.success && health.value?.isHealthy) {\n * console.log('Database healthy with audit support');\n * }\n * ```\n */\n async healthCheck(): Promise<DatabaseResult<DatabaseHealthStatus>> {\n return this.baseAdapter.healthCheck();\n }\n\n /**\n * Determines if a table should be audited.\n *\n * **RESPONSIBILITY:** Checks if table is enabled for audit logging\n * **CONFIGURATION:** Based on enabled flag and excludeTables array\n *\n * @private\n * @param table - Table name to check\n * @returns True if table should be audited\n *\n * @example\n * ```typescript\n * // Configuration: { enabled: true, excludeTables: ['temp_data'] }\n *\n * this.shouldAudit('users'); // true - will be audited\n * this.shouldAudit('temp_data'); // false - excluded from audit\n * ```\n */\n private shouldAudit(table: string): boolean {\n if (!this.config.enabled) return false;\n return !(this.config.excludeTables?.includes(table) ?? false);\n }\n\n /**\n * Logs an audit event to the audit table and executes custom handlers.\n *\n * **RESPONSIBILITY:** Orchestrates audit record creation and event handling\n * **PROCESS:** Validates event → Writes to audit table → Executes custom handler\n *\n * @private\n * @param event - Audit event to log\n *\n * @example\n * ```typescript\n * // Internal usage after successful operation\n * await this.logAudit({\n * operation: 'CREATE',\n * table: 'users',\n * recordId: 'user-123',\n * changes: { after: userData },\n * userId: 'admin-456',\n * timestamp: new Date()\n * });\n * ```\n */\n private async logAudit(event: AuditEvent): Promise<void> {\n this.validateAuditEvent(event);\n\n await this.writeAuditRecord(event);\n await this.executeCustomHandler(event);\n }\n\n /**\n * Validates audit event has required fields.\n *\n * **RESPONSIBILITY:** Ensures audit event is properly formed\n * **VALIDATION:** Checks for required operation and table fields\n *\n * @private\n * @param event - Audit event to validate\n * @throws {DatabaseError} When event is invalid\n *\n * @example\n * ```typescript\n * // Internal validation before logging\n * this.validateAuditEvent({\n * operation: 'CREATE', // Required\n * table: 'users', // Required\n * recordId: 'user-123'\n * });\n * ```\n */\n private validateAuditEvent(event: AuditEvent): void {\n if (!event?.operation || !event?.table) {\n throw new DatabaseError(\n \"Invalid audit event\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"validateAuditEvent\" },\n cause: new Error(\"Invalid audit event\"),\n },\n );\n }\n }\n\n /**\n * Generates the audit table name based on configuration.\n *\n * **RESPONSIBILITY:** Determines the correct table name for audit records\n * **TABLE NAMING:**\n * - Partitioned: `{schema}.audit_log_yyyy_mm_dd` (e.g., audit.audit_log_2024_12_01)\n * - Non-partitioned: `{schema}.audit_logs` (e.g., audit.audit_logs)\n *\n * @private\n * @param timestamp - Timestamp to use for partition date\n * @returns Schema-qualified table name\n */\n private getAuditTableName(timestamp: Date): string {\n if (this.usePartitionedTables) {\n const year = timestamp.getFullYear();\n const month = String(timestamp.getMonth() + 1).padStart(\n DATE_PART_MIN_WIDTH,\n \"0\",\n );\n const day = String(timestamp.getDate()).padStart(\n DATE_PART_MIN_WIDTH,\n \"0\",\n );\n return `${this.auditSchema}.audit_log_${year}_${month}_${day}`;\n }\n return `${this.auditSchema}.audit_logs`;\n }\n\n /**\n * Writes audit record to daily audit table.\n *\n * **RESPONSIBILITY:** Persists audit event to database\n * **TABLE NAMING:** Uses daily partitioned tables (audit.audit_log_yyyy_mm_dd) by default\n * **STRUCTURE:** Converts event to database record format\n *\n * @private\n * @param event - Audit event to write\n * @throws {DatabaseError} When write operation fails\n *\n * @example\n * ```typescript\n * // Internal usage - writes to audit.audit_log_2024_12_01 table\n * await this.writeAuditRecord({\n * operation: 'UPDATE',\n * table: 'users',\n * recordId: 'user-123',\n * changes: { before: {...}, after: {...} },\n * timestamp: new Date('2024-12-01')\n * });\n * ```\n */\n private async writeAuditRecord(event: AuditEvent): Promise<void> {\n const tableName = this.getAuditTableName(event.timestamp);\n try {\n const auditResult = await this.baseAdapter.create(tableName, {\n operation: event.operation,\n table_name: event.table,\n record_id: event.recordId,\n user_id: event.userId,\n request_id: event.requestId,\n changes: event.changes,\n ip_address: event.ipAddress,\n user_agent: event.userAgent,\n timestamp: event.timestamp,\n });\n\n if (!auditResult.success) {\n throw new DatabaseError(\n \"Failed to write audit record\",\n DATABASE_ERROR_CODES.CREATE_FAILED,\n {\n context: { source: \"writeAuditRecord\" },\n cause:\n auditResult.error ?? new Error(\"Failed to write audit record\"),\n },\n );\n }\n } catch (error) {\n logger.error(`Audit write failed: ${(error as Error).message}`);\n throw new DatabaseError(\n \"Failed to write audit record\",\n DATABASE_ERROR_CODES.CREATE_FAILED,\n {\n context: { source: \"writeAuditRecord\" },\n cause: error as Error,\n },\n );\n }\n }\n\n /**\n * Executes custom audit event handler if configured.\n *\n * **RESPONSIBILITY:** Calls user-defined audit event handler\n * **ERROR HANDLING:** Logs handler errors without failing the operation\n * **USE CASE:** Integration with compliance systems, notifications\n *\n * @private\n * @param event - Audit event to handle\n *\n * @example\n * ```typescript\n * // Configuration with custom handler\n * {\n * onAuditAfterWrite: async (event) => {\n * await complianceService.recordAudit(event);\n * await notificationService.sendAuditAlert(event);\n * }\n * }\n *\n * // Handler is called after successful audit record write\n * ```\n */\n private async executeCustomHandler(event: AuditEvent): Promise<void> {\n if (this.config.onAuditAfterWrite) {\n try {\n await this.config.onAuditAfterWrite(event);\n } catch (handlerError) {\n logger.error(\n `Custom audit handler failed: ${(handlerError as Error).message}`,\n );\n }\n }\n }\n}\n","import { createCipheriv, createDecipheriv, randomBytes } from \"crypto\";\nimport {\n type DatabaseAdapterType,\n type DatabaseResult,\n type QueryOptions,\n type PaginatedResult,\n type Transaction,\n type Filter,\n type DatabaseHealthStatus,\n ENCRYPTION_DEFAULTS,\n} from \"@plyaz/types/db\";\nimport { isString, isObject } from \"@utils/typeGuards\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\n\n/**\n * ENCRYPTION ADAPTER — Field-Level Encryption Layer\n *\n * Encryption extension that automatically encrypts/decrypts specified fields.\n * Second layer in the adapter chain (after the base adapter).\n *\n * **Adapter Chain Position:**\n * ReadReplica → Audit → Cache → SoftDelete → **Encryption** → Base Adapter\n *\n * **What this adapter does:**\n * 1. Receives operations from SoftDeleteAdapter (or the next layer)\n * 2. Encrypts sensitive fields before write operations (create, update)\n * 3. Delegates to the base adapter with encrypted data\n * 4. Decrypts fields in response data after read operations\n * 5. Passes results back up the chain\n *\n * **Called by:** SoftDeleteAdapter (or CachingAdapter if no soft delete)\n * **Calls:** Base adapter methods (DrizzleAdapter, SupabaseAdapter, etc.)\n * **Wraps:** Base database adapter with transparent encryption\n *\n * **Encryption Flow:**\n * - **Writes:** Plain data → Encrypt fields → Store encrypted → Return decrypted\n * - **Reads:** Retrieve encrypted → Decrypt fields → Return plain data\n *\n * @example\n * ### Configuration\n * ```typescript\n * encryption: {\n * enabled: true,\n * key: process.env.ENCRYPTION_KEY,\n * fields: {\n * [Tables.USERS]: ['ssn', 'taxId'],\n * [Tables.PAYMENTS]: ['cardNumber', 'cvv']\n * }\n * }\n * ```\n *\n * @example\n * ### Transparent Usage\n * ```typescript\n * // Application code — encryption is transparent\n * await db.create(Tables.USERS, {\n * name: 'John Doe',\n * ssn: '123-45-6789' // Automatically encrypted before storage\n * });\n *\n * // Retrieved data is automatically decrypted\n * const user = await db.get(Tables.USERS, userId);\n * console.log(user.value.ssn); // '123-45-6789' (decrypted)\n * ```\n */\n\nexport class EncryptionAdapter implements DatabaseAdapterType {\n // Using shared logger instance from @plyaz/logger\n\n constructor(\n public baseAdapter: DatabaseAdapterType,\n private config: {\n enabled: boolean;\n key: string;\n fields: Record<string, string[]>;\n algorithm?: string;\n },\n ) {}\n\n async initialize(): Promise<DatabaseResult<void>> {\n return this.baseAdapter.initialize();\n }\n\n async connect(): Promise<void> {\n return this.baseAdapter.connect();\n }\n\n async disconnect(): Promise<void> {\n return this.baseAdapter.disconnect();\n }\n\n async close(): Promise<DatabaseResult<void>> {\n return this.baseAdapter.close();\n }\n\n getClient(): object {\n return this.baseAdapter.getClient();\n }\n\n async query<T>(sql: string, params?: T[]): Promise<T[]> {\n return this.baseAdapter.query(sql, params);\n }\n\n registerTable<T, U>(name: string, table: T, idColumn?: U): void {\n this.baseAdapter.registerTable(name, table, idColumn);\n }\n\n async findById<T>(\n table: string,\n id: string,\n ): Promise<DatabaseResult<T | null>> {\n const result = await this.baseAdapter.findById<T>(table, id);\n if (result.success && result.value) {\n result.value = this.decryptFields(table, result.value);\n }\n return result;\n }\n\n async findMany<T extends Record<string, unknown>>(\n table: string,\n options?: QueryOptions<T>,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n const result = await this.baseAdapter.findMany<T>(table, options);\n if (result.success && result.value) {\n result.value.data = result.value.data.map((item) =>\n this.decryptFields(table, item),\n );\n }\n return result;\n }\n\n async create<T extends Record<string, unknown>>(\n table: string,\n data: T,\n ): Promise<DatabaseResult<T>> {\n // Encryption is critical for compliance - fail if encryption fails\n // AuditAdapter (outer layer) will catch and log the failure\n const encryptedData = this.encryptFields(table, data);\n const result = await this.baseAdapter.create<T>(table, encryptedData);\n if (result.success && result.value) {\n result.value = this.decryptFields(table, result.value);\n }\n return result;\n }\n\n async update<T>(\n table: string,\n id: string,\n data: Partial<T>,\n ): Promise<DatabaseResult<T>> {\n // Encryption is critical for compliance - fail if encryption fails\n // AuditAdapter (outer layer) will catch and log the failure\n const encryptedData = this.encryptFields(table, data);\n const result = await this.baseAdapter.update<T>(table, id, encryptedData);\n if (result.success && result.value) {\n result.value = this.decryptFields(table, result.value);\n }\n return result;\n }\n\n async delete(table: string, id: string): Promise<DatabaseResult<void>> {\n return this.baseAdapter.delete(table, id);\n }\n\n async transaction<T>(\n callback: (trx: Transaction) => Promise<T>,\n ): Promise<DatabaseResult<T>> {\n return this.baseAdapter.transaction(callback);\n }\n\n async exists(table: string, id: string): Promise<DatabaseResult<boolean>> {\n return this.baseAdapter.exists(table, id);\n }\n\n async count<T extends Record<string, unknown> = Record<string, unknown>>(\n table: string,\n filter?: Filter<T>,\n ): Promise<DatabaseResult<number>> {\n return this.baseAdapter.count<T>(table, filter);\n }\n\n async healthCheck(): Promise<DatabaseResult<DatabaseHealthStatus>> {\n return this.baseAdapter.healthCheck();\n }\n\n private encryptFields<T extends Record<string, unknown>>(\n table: string,\n data: T,\n ): T {\n if (!this.shouldProcessFields(data, table)) return data;\n\n const fieldsToEncrypt = this.config.fields[table];\n const result = { ...data } as T;\n\n for (const field of fieldsToEncrypt) {\n this.encryptSingleField(result, field);\n }\n\n return result as T;\n }\n\n private shouldProcessFields<T>(data: T, table: string): boolean {\n return (\n this.config.enabled &&\n isObject(data) &&\n Boolean(this.config.fields[table])\n );\n }\n\n private encryptSingleField<T extends Record<string, unknown>>(\n result: T,\n field: string,\n ): void {\n if (result[field as keyof T]) {\n result[field as keyof T] = this.encrypt(\n String(result[field as keyof T]),\n ) as T[keyof T];\n }\n }\n\n private decryptFields<T extends Record<string, unknown>>(\n table: string,\n data: T,\n ): T {\n if (!this.shouldProcessFields(data, table)) return data;\n\n const fieldsToDecrypt = this.config.fields[table];\n const result = { ...data } as T;\n\n for (const field of fieldsToDecrypt) {\n this.decryptSingleField(result, field);\n }\n\n return result as T;\n }\n\n private decryptSingleField<T extends Record<string, unknown>>(\n result: T,\n field: string,\n ): void {\n if (result[field as keyof T]) {\n const fieldValue = String(result[field as keyof T]);\n // Check if the field value is encrypted (contains colons)\n // If not encrypted, return as-is (backwards compatibility with old data)\n if (this.isEncryptedValue(fieldValue)) {\n try {\n result[field as keyof T] = this.decrypt(fieldValue) as T[keyof T];\n } catch (error) {\n // Decryption failed - might be corrupted data or wrong key\n console.warn(\n `Failed to decrypt field ${field}, returning as-is:`,\n (error as Error).message,\n );\n }\n }\n }\n }\n\n private encrypt(text: string): string {\n this.validateEncryptionInput(text);\n\n const { iv, cipher } = this.createCipher();\n const encrypted = this.performEncryption(cipher, text);\n const authTag =\n (cipher as { getAuthTag?: () => Buffer }).getAuthTag?.() ??\n Buffer.alloc(0);\n\n return iv.toString(\"hex\") + \":\" + authTag.toString(\"hex\") + \":\" + encrypted;\n }\n\n private validateEncryptionInput(text: string): void {\n if (!isString(text)) {\n throw new DatabaseError(\n \"Invalid text for encryption\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"validateEncryptionInput\" },\n cause: new Error(\"Invalid text for encryption\"),\n },\n );\n }\n if (!this.config.key) {\n throw new DatabaseError(\n \"Encryption key is required\",\n DATABASE_ERROR_CODES.CONFIG_REQUIRED,\n {\n context: { source: \"validateEncryptionInput\" },\n cause: new Error(\"Encryption key is required\"),\n },\n );\n }\n }\n\n private createCipher(): {\n iv: Buffer;\n cipher: ReturnType<typeof createCipheriv>;\n } {\n const algorithm = this.config.algorithm ?? ENCRYPTION_DEFAULTS.ALGORITHM;\n const key = this.getKeyBuffer();\n const iv = randomBytes(ENCRYPTION_DEFAULTS.IV_LENGTH);\n const cipher = createCipheriv(algorithm, key, iv);\n return { iv, cipher };\n }\n\n private performEncryption(\n cipher: ReturnType<typeof createCipheriv>,\n text: string,\n ): string {\n let encrypted = cipher.update(text, \"utf8\", \"hex\");\n encrypted += cipher.final(\"hex\");\n return encrypted;\n }\n\n private decrypt(encryptedText: string): string {\n this.validateDecryptionInput(encryptedText);\n\n const parts = this.parseEncryptedText(encryptedText);\n const { iv, authTag, encrypted } = this.extractDecryptionParts(parts);\n const decipher = this.createDecipher(iv, authTag);\n\n return this.performDecryption(decipher, encrypted);\n }\n\n private validateDecryptionInput(encryptedText: string): void {\n if (!isString(encryptedText)) {\n throw new DatabaseError(\n \"Invalid encrypted text for decryption\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"validateDecryptionInput\" },\n cause: new Error(\"Invalid encrypted text for decryption\"),\n },\n );\n }\n if (!this.config.key) {\n throw new DatabaseError(\n \"Encryption key is required\",\n DATABASE_ERROR_CODES.CONFIG_REQUIRED,\n {\n context: { source: \"validateDecryptionInput\" },\n cause: new Error(\"Encryption key is required\"),\n },\n );\n }\n }\n\n private parseEncryptedText(encryptedText: string): string[] {\n const parts = encryptedText.split(\":\");\n if (parts.length !== ENCRYPTION_DEFAULTS.ENCRYPTED_PARTS_COUNT) {\n throw new DatabaseError(\n \"Invalid encrypted text format\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"parseEncryptedText\" },\n cause: new Error(\"Invalid encrypted text format\"),\n },\n );\n }\n return parts;\n }\n\n private extractDecryptionParts(parts: string[]): {\n iv: Buffer;\n authTag: Buffer;\n encrypted: string;\n } {\n const iv = Buffer.from(parts[0], \"hex\");\n const authTag = Buffer.from(parts[1], \"hex\");\n const encrypted = parts[2];\n return { iv, authTag, encrypted };\n }\n\n private createDecipher(\n iv: Buffer,\n authTag: Buffer,\n ): ReturnType<typeof createDecipheriv> {\n const algorithm = this.config.algorithm ?? ENCRYPTION_DEFAULTS.ALGORITHM;\n const key = this.getKeyBuffer();\n const decipher = createDecipheriv(algorithm, key, iv);\n\n if (authTag.length > 0) {\n (decipher as { setAuthTag?: (tag: Buffer) => void }).setAuthTag?.(\n authTag,\n );\n }\n\n return decipher;\n }\n\n private performDecryption(\n decipher: ReturnType<typeof createDecipheriv>,\n encrypted: string,\n ): string {\n let decrypted = decipher.update(encrypted, \"hex\", \"utf8\");\n decrypted += decipher.final(\"utf8\");\n return decrypted;\n }\n\n private isEncryptedValue(value: string): boolean {\n // Encrypted values have format: iv:authTag:encrypted (3 parts separated by colons)\n const parts = value.split(\":\");\n return parts.length === ENCRYPTION_DEFAULTS.ENCRYPTED_PARTS_COUNT;\n }\n\n private getKeyBuffer(): Buffer {\n // AES-256-GCM requires 32-byte key\n const AES_256_KEY_LENGTH = 32;\n const keyBuffer = Buffer.from(this.config.key, \"utf8\");\n\n if (keyBuffer.length !== AES_256_KEY_LENGTH) {\n throw new DatabaseError(\n `Encryption key must be exactly ${AES_256_KEY_LENGTH} bytes for AES-256, got ${keyBuffer.length}`,\n DATABASE_ERROR_CODES.CONFIG_REQUIRED,\n {\n context: { source: \"getKeyBuffer\" },\n cause: new Error(\"Invalid key length\"),\n },\n );\n }\n\n return keyBuffer;\n }\n}\n","import { NUMERIX } from \"@plyaz/config\";\nimport { logger } from \"@plyaz/logger\";\nimport type {\n DatabaseAdapterType,\n DatabaseResult,\n DBCacheConfig,\n Filter,\n DatabaseHealthStatus,\n PaginatedResult,\n QueryOptions,\n Transaction,\n} from \"@plyaz/types/db\";\n/**\n * CACHING ADAPTER - Query Result Caching Layer\n *\n * Caching extension that stores query results in memory for improved performance.\n * Third layer in the adapter chain.\n *\n * **Adapter Chain Position:**\n * ReadReplica → Audit → **Cache** → SoftDelete → Encryption → Base Adapter\n *\n * **What this adapter does:**\n * 1. Intercepts findById() operations → checks cache first, stores results\n * 2. Intercepts write operations → invalidates related cache entries\n * 3. Manages TTL-based cache expiration\n * 4. Honors cache configuration (enabled, ttl, invalidation strategy)\n *\n * **Called by:** AuditAdapter (or ReadReplicaAdapter if no audit)\n * **Calls:** SoftDeleteAdapter (or next adapter in chain)\n * **Cache Strategy:** In-memory Map with TTL expiration\n *\n * **Cache Flow:**\n * - **READ:** Check cache → Return if hit → Query DB → Cache result\n * - **WRITE:** Execute operation → Invalidate related cache entries\n *\n * @example\n * ### Configuration\n * ```typescript\n * cache: {\n * enabled: true,\n * ttl: 300, // 5 minutes\n * invalidation: 'write', // Invalidate on writes\n * maxSize: 1000 // Max cache entries\n * }\n * ```\n *\n * @example\n * ### Cache Behavior\n * ```typescript\n * // First call - cache miss, queries database\n * const user1 = await db.findById('users', 'user-123'); // DB query\n *\n * // Second call - cache hit, returns from memory\n * const user2 = await db.findById('users', 'user-123'); // Cache hit\n *\n * // Write operation invalidates cache\n * await db.update('users', 'user-123', { name: 'New Name' });\n *\n * // Next read - cache miss again, queries database\n * const user3 = await db.findById('users', 'user-123'); // DB query\n * ```\n */\nexport class CachingAdapter implements DatabaseAdapterType {\n private cache = new Map<\n string,\n {\n value:\n | Record<string, string | number | boolean | Date>\n | Record<string, string | number | boolean | Date>[];\n expiry: number;\n }\n >();\n\n /**\n * Creates a new CachingAdapter instance.\n *\n * **RESPONSIBILITY:** Wraps base adapter with caching functionality\n * **CONFIGURATION:** Sets up cache TTL, invalidation strategy, and size limits\n *\n * @param baseAdapter - The underlying database adapter to wrap\n * @param config - Cache configuration options\n *\n * @example\n * ```typescript\n * const cachingAdapter = new CachingAdapter(baseAdapter, {\n * enabled: true,\n * ttl: 300, // 5 minutes\n * invalidation: 'write', // Invalidate on writes\n * maxSize: 1000 // Max entries\n * });\n * ```\n */\n constructor(\n public baseAdapter: DatabaseAdapterType,\n private config: DBCacheConfig,\n ) {}\n\n /**\n * Initializes the caching adapter and underlying adapter.\n *\n * **RESPONSIBILITY:** Passes initialization to base adapter\n * **BEHAVIOR:** No additional initialization needed for caching\n *\n * @returns Promise resolving to initialization result\n *\n * @example\n * ```typescript\n * const result = await cachingAdapter.initialize();\n * if (result.success) {\n * console.log('Caching adapter initialized');\n * }\n * ```\n */\n async initialize(): Promise<DatabaseResult<void>> {\n return this.baseAdapter.initialize();\n }\n\n /**\n * Establishes database connection through base adapter.\n *\n * **RESPONSIBILITY:** Delegates connection to underlying adapter\n * **BEHAVIOR:** No additional connection logic needed\n *\n * @example\n * ```typescript\n * await cachingAdapter.connect();\n * console.log('Connected with caching support');\n * ```\n */\n async connect(): Promise<void> {\n return this.baseAdapter.connect();\n }\n\n /**\n * Closes database connection through base adapter.\n *\n * **RESPONSIBILITY:** Delegates disconnection to underlying adapter\n * **BEHAVIOR:** Cache is cleared on disconnect\n *\n * @example\n * ```typescript\n * await cachingAdapter.disconnect();\n * console.log('Disconnected and cache cleared');\n * ```\n */\n async disconnect(): Promise<void> {\n return this.baseAdapter.disconnect();\n }\n\n async close(): Promise<DatabaseResult<void>> {\n return this.baseAdapter.close();\n }\n\n /**\n * Gets the underlying database client.\n *\n * **RESPONSIBILITY:** Provides access to raw database client\n * **USE CASE:** For operations that bypass caching\n *\n * @returns Database client object\n *\n * @example\n * ```typescript\n * const client = cachingAdapter.getClient();\n * // Use for direct database operations if needed\n * ```\n */\n getClient(): object {\n return this.baseAdapter.getClient();\n }\n\n /**\n * Executes raw SQL query through base adapter.\n *\n * **RESPONSIBILITY:** Passes raw SQL to base adapter without caching\n * **BEHAVIOR:** Does not cache raw SQL results\n * **NOTE:** Use findById/findMany for automatic caching\n *\n * @param sql - SQL query string\n * @param params - Query parameters\n * @returns Query results\n *\n * @example\n * ```typescript\n * // Raw SQL bypasses caching\n * const results = await adapter.query(\n * 'SELECT * FROM users WHERE status = $1',\n * ['active']\n * );\n *\n * // Use findMany for automatic caching\n * const users = await adapter.findMany('users', { filter: ... });\n * ```\n */\n async query<T>(sql: string, params?: T[]): Promise<T[]> {\n return this.baseAdapter.query(sql, params);\n }\n\n /**\n * Registers a table schema with the base adapter.\n *\n * **RESPONSIBILITY:** Passes table registration to base adapter\n * **BEHAVIOR:** No additional registration logic needed\n *\n * @param name - Table name\n * @param table - Table schema\n * @param idColumn - Primary key column\n *\n * @example\n * ```typescript\n * cachingAdapter.registerTable('users', userSchema, 'id');\n * // Table now supports cached operations\n * ```\n */\n registerTable<T, U>(name: string, table: T, idColumn?: U): void {\n this.baseAdapter.registerTable(name, table, idColumn);\n }\n\n async findById<T>(\n table: string,\n id: string,\n ): Promise<DatabaseResult<T | null>> {\n if (!this.config.enabled) {\n return this.baseAdapter.findById<T>(table, id);\n }\n\n const cacheKey = `${table}:${id}`;\n const cached = this.getFromCache<T>(cacheKey);\n\n if (cached !== null) {\n logger.debug(`Cache hit for ${table}:${id}`);\n return { success: true, value: cached };\n }\n\n const result = await this.baseAdapter.findById<T>(table, id);\n\n if (result.success && result.value) {\n this.setCache(cacheKey, result.value);\n logger.debug(`Cache set for ${table}:${id}`);\n }\n\n return result;\n }\n\n /**\n * Finds multiple records without caching.\n *\n * **RESPONSIBILITY:** Retrieves multiple records, bypassing cache\n * **BEHAVIOR:** Complex queries are not cached currently\n * **FUTURE:** Could implement query result caching with cache keys\n *\n * @param table - Table name\n * @param options - Query options\n * @returns Paginated results\n *\n * @example\n * ```typescript\n * // Complex queries bypass cache (for now)\n * const users = await adapter.findMany('users', {\n * filter: { field: 'status', operator: 'eq', value: 'active' },\n * pagination: { page: 1, limit: 10 },\n * sort: { field: 'name', direction: 'asc' }\n * });\n *\n * // Always queries database directly\n * ```\n */\n async findMany<T extends Record<string, unknown>>(\n table: string,\n options?: QueryOptions<T>,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n // For now, skip caching for complex queries\n return this.baseAdapter.findMany<T>(table, options);\n }\n\n /**\n * Creates a new record with cache invalidation.\n *\n * **RESPONSIBILITY:** Creates record and invalidates related cache entries\n * **INVALIDATION:** Clears table cache on successful write\n * **STRATEGY:** Based on config.invalidation setting\n *\n * @param table - Table name\n * @param data - Record data\n * @returns Created record\n *\n * @example\n * ```typescript\n * // Create user - invalidates users table cache\n * const result = await adapter.create('users', {\n * name: 'John Doe',\n * email: 'john@example.com'\n * });\n *\n * if (result.success) {\n * console.log('User created:', result.value.id);\n * // All cached users:* entries are now invalid\n * }\n * ```\n */\n async create<T extends Record<string, unknown>>(\n table: string,\n data: T,\n ): Promise<DatabaseResult<T>> {\n const result = await this.baseAdapter.create<T>(table, data);\n\n if (result.success && this.config.invalidation === \"write\") {\n this.invalidateTable(table);\n }\n\n return result;\n }\n\n /**\n * Updates an existing record with cache invalidation.\n *\n * **RESPONSIBILITY:** Updates record and invalidates related cache entries\n * **INVALIDATION:** Clears specific record and table cache\n * **STRATEGY:** Invalidates both table:id and table:* patterns\n *\n * @param table - Table name\n * @param id - Record ID\n * @param data - Partial record data\n * @returns Updated record\n *\n * @example\n * ```typescript\n * // Update user - invalidates specific cache entry\n * const result = await adapter.update('users', 'user-123', {\n * name: 'Jane Doe'\n * });\n *\n * if (result.success) {\n * console.log('User updated:', result.value.name);\n * // Cache entries users:user-123 and users:* are invalidated\n * }\n * ```\n */\n async update<T>(\n table: string,\n id: string,\n data: Partial<T>,\n ): Promise<DatabaseResult<T>> {\n const result = await this.baseAdapter.update<T>(table, id, data);\n\n if (result.success && this.config.invalidation === \"write\") {\n this.invalidateTable(table);\n this.invalidateKey(`${table}:${id}`);\n }\n\n return result;\n }\n\n /**\n * Deletes a record with cache invalidation.\n *\n * **RESPONSIBILITY:** Deletes record and invalidates related cache entries\n * **INVALIDATION:** Clears specific record and table cache\n * **STRATEGY:** Removes both table:id and table:* patterns\n *\n * @param table - Table name\n * @param id - Record ID\n * @returns Deletion result\n *\n * @example\n * ```typescript\n * // Delete user - invalidates cache entries\n * const result = await adapter.delete('users', 'user-123');\n *\n * if (result.success) {\n * console.log('User deleted successfully');\n * // Cache entries users:user-123 and users:* are invalidated\n * }\n * ```\n */\n async delete(table: string, id: string): Promise<DatabaseResult<void>> {\n const result = await this.baseAdapter.delete(table, id);\n\n if (result.success && this.config.invalidation === \"write\") {\n this.invalidateTable(table);\n this.invalidateKey(`${table}:${id}`);\n }\n\n return result;\n }\n\n /**\n * Executes operations within a transaction.\n *\n * **RESPONSIBILITY:** Passes transaction to base adapter\n * **BEHAVIOR:** Cache invalidation happens per operation within transaction\n * **ATOMICITY:** Cache invalidation is not rolled back if transaction fails\n *\n * @param callback - Transaction callback function\n * @returns Transaction result\n *\n * @example\n * ```typescript\n * const result = await adapter.transaction(async (trx) => {\n * // Each operation invalidates cache independently\n * const user = await trx.create('users', { name: 'John' });\n * await trx.update('profiles', 'profile-1', { userId: user.id });\n * return user;\n * });\n *\n * // Cache invalidation happens even if transaction fails\n * ```\n */\n async transaction<T>(\n callback: (trx: Transaction) => Promise<T>,\n ): Promise<DatabaseResult<T>> {\n return this.baseAdapter.transaction(callback);\n }\n\n /**\n * Checks if a record exists without caching.\n *\n * **RESPONSIBILITY:** Verifies record existence, bypassing cache\n * **BEHAVIOR:** Existence checks are not cached currently\n * **PERFORMANCE:** Always queries database for existence\n *\n * @param table - Table name\n * @param id - Record ID\n * @returns True if record exists\n *\n * @example\n * ```typescript\n * // Existence checks bypass cache\n * const userExists = await adapter.exists('users', 'user-123');\n * if (userExists.value) {\n * console.log('User exists');\n * }\n *\n * // Always queries database directly\n * ```\n */\n async exists(table: string, id: string): Promise<DatabaseResult<boolean>> {\n return this.baseAdapter.exists(table, id);\n }\n\n /**\n * Counts records without caching.\n *\n * **RESPONSIBILITY:** Counts records, bypassing cache\n * **BEHAVIOR:** Count operations are not cached currently\n * **PERFORMANCE:** Always queries database for counts\n *\n * @param table - Table name\n * @param filter - Optional filter conditions\n * @returns Count of records\n *\n * @example\n * ```typescript\n * // Count operations bypass cache\n * const activeUsers = await adapter.count('users', {\n * field: 'status',\n * operator: 'eq',\n * value: 'active'\n * });\n *\n * console.log('Active users:', activeUsers.value);\n * // Always queries database directly\n * ```\n */\n async count<T extends Record<string, unknown> = Record<string, unknown>>(\n table: string,\n filter?: Filter<T>,\n ): Promise<DatabaseResult<number>> {\n return this.baseAdapter.count<T>(table, filter);\n }\n\n /**\n * Performs health check through base adapter.\n *\n * **RESPONSIBILITY:** Delegates health check to underlying adapter\n * **BEHAVIOR:** No additional health metrics for cache\n *\n * @returns Health status from base adapter\n *\n * @example\n * ```typescript\n * const health = await adapter.healthCheck();\n * if (health.success && health.value?.isHealthy) {\n * console.log('Database healthy with caching support');\n * }\n * ```\n */\n async healthCheck(): Promise<DatabaseResult<DatabaseHealthStatus>> {\n return this.baseAdapter.healthCheck();\n }\n\n /**\n * Retrieves value from cache with TTL validation.\n *\n * **RESPONSIBILITY:** Gets cached value and validates expiration\n * **TTL HANDLING:** Removes expired entries automatically\n * **RETURN:** Cached value or null if not found/expired\n *\n * @private\n * @param key - Cache key to retrieve\n * @returns Cached value or null\n *\n * @example\n * ```typescript\n * // Internal usage\n * const user = this.getFromCache<User>('users:user-123');\n * if (user) {\n * console.log('Cache hit:', user.name);\n * } else {\n * console.log('Cache miss or expired');\n * }\n * ```\n */\n private getFromCache<T>(key: string): T | null {\n const cached = this.cache.get(key);\n if (!cached) return null;\n\n if (Date.now() > cached.expiry) {\n this.cache.delete(key);\n return null;\n }\n\n return cached.value as T;\n }\n\n /**\n * Stores value in cache with TTL expiration.\n *\n * **RESPONSIBILITY:** Caches value with calculated expiration time\n * **TTL:** Uses config.ttl or default 5 minutes (300 seconds)\n * **EXPIRY:** Calculates absolute expiration timestamp\n *\n * @private\n * @param key - Cache key to store\n * @param value - Value to cache\n *\n * @example\n * ```typescript\n * // Internal usage after database query\n * this.setCache('users:user-123', userData);\n *\n * // Value will expire after TTL seconds\n * // Default: 5 minutes from now\n * ```\n */\n private setCache(\n key: string,\n value:\n | Record<string, string | number | boolean | Date>\n | Record<string, string | number | boolean | Date>[],\n ): void {\n const ttl = this.config.ttl ?? NUMERIX.THREE_HUNDERD; // Default 5 minutes\n const expiry = Date.now() + ttl * NUMERIX.THOUSAND;\n this.cache.set(key, { value, expiry });\n }\n\n /**\n * Removes specific key from cache.\n *\n * **RESPONSIBILITY:** Invalidates single cache entry\n * **USE CASE:** Called after record updates/deletes\n * **PATTERN:** Removes exact key match\n *\n * @private\n * @param key - Cache key to invalidate\n *\n * @example\n * ```typescript\n * // Internal usage after record update\n * this.invalidateKey('users:user-123');\n *\n * // Only users:user-123 is removed from cache\n * // Other users:* entries remain cached\n * ```\n */\n private invalidateKey(key: string): void {\n this.cache.delete(key);\n }\n\n /**\n * Removes all cache entries for a table.\n *\n * **RESPONSIBILITY:** Invalidates all entries matching table pattern\n * **USE CASE:** Called after any write operation to table\n * **PATTERN:** Removes all keys starting with 'table:'\n *\n * @private\n * @param table - Table name to invalidate\n *\n * @example\n * ```typescript\n * // Internal usage after any write to users table\n * this.invalidateTable('users');\n *\n * // Removes all cache entries:\n * // - users:user-123\n * // - users:user-456\n * // - users:admin-789\n * // But keeps: profiles:profile-1, posts:post-1, etc.\n * ```\n */\n private invalidateTable(table: string): void {\n for (const key of this.cache.keys()) {\n if (key.startsWith(`${table}:`)) {\n this.cache.delete(key);\n }\n }\n }\n}\n","import type {\n DatabaseAdapterType,\n DatabaseResult,\n QueryOptions,\n PaginatedResult,\n Transaction,\n Filter,\n DatabaseHealthStatus,\n ReadReplicaConfig,\n} from \"@plyaz/types/db\";\n\n/**\n * Read replica extension that routes read operations to replicas\n * This is the outermost wrapper in the adapter chain\n */\nexport class ReadReplicaAdapter implements DatabaseAdapterType {\n private currentReplicaIndex = 0;\n\n constructor(\n private primaryAdapter: DatabaseAdapterType,\n private config: ReadReplicaConfig,\n ) {}\n\n async initialize(): Promise<DatabaseResult<void>> {\n return this.primaryAdapter.initialize();\n }\n\n async connect(): Promise<void> {\n return this.primaryAdapter.connect();\n }\n\n async disconnect(): Promise<void> {\n return this.primaryAdapter.disconnect();\n }\n\n async close(): Promise<DatabaseResult<void>> {\n return this.primaryAdapter.close();\n }\n\n getClient(): object {\n return this.primaryAdapter.getClient();\n }\n\n async query<T>(sql: string, params?: T[]): Promise<T[]> {\n return this.primaryAdapter.query(sql, params);\n }\n\n registerTable<T, U>(name: string, table: T, idColumn?: U): void {\n this.primaryAdapter.registerTable(name, table, idColumn);\n }\n\n async findById<T>(\n table: string,\n id: string,\n ): Promise<DatabaseResult<T | null>> {\n // Route reads to replicas if available\n const adapter = this.getReadAdapter();\n return adapter.findById<T>(table, id);\n }\n\n async findMany<T extends Record<string, unknown>>(\n table: string,\n options?: QueryOptions<T>,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n // Route reads to replicas if available\n const adapter = this.getReadAdapter();\n return adapter.findMany<T>(table, options);\n }\n\n async create<T extends Record<string, unknown>>(\n table: string,\n data: T,\n ): Promise<DatabaseResult<T>> {\n // Always route writes to primary\n return this.primaryAdapter.create<T>(table, data);\n }\n\n async update<T>(\n table: string,\n id: string,\n data: Partial<T>,\n ): Promise<DatabaseResult<T>> {\n // Always route writes to primary\n return this.primaryAdapter.update<T>(table, id, data);\n }\n\n async delete(table: string, id: string): Promise<DatabaseResult<void>> {\n // Always route writes to primary\n return this.primaryAdapter.delete(table, id);\n }\n\n async transaction<T>(\n callback: (trx: Transaction) => Promise<T>,\n ): Promise<DatabaseResult<T>> {\n // Always route transactions to primary\n return this.primaryAdapter.transaction(callback);\n }\n\n async exists(table: string, id: string): Promise<DatabaseResult<boolean>> {\n // Route reads to replicas if available\n const adapter = this.getReadAdapter();\n return adapter.exists(table, id);\n }\n\n async count<T extends Record<string, unknown> = Record<string, unknown>>(\n table: string,\n filter?: Filter<T>,\n ): Promise<DatabaseResult<number>> {\n // Route reads to replicas if available\n const adapter = this.getReadAdapter();\n return adapter.count<T>(table, filter);\n }\n\n async healthCheck(): Promise<DatabaseResult<DatabaseHealthStatus>> {\n return this.primaryAdapter.healthCheck();\n }\n\n /**\n * Get the appropriate adapter for read operations\n * Routes to replicas using the configured strategy\n */\n private getReadAdapter(): DatabaseAdapterType {\n if (!this.config.enabled || this.config.replicas.length === 0) {\n return this.primaryAdapter;\n }\n\n switch (this.config.strategy) {\n case \"round-robin\": {\n const replica = this.config.replicas[this.currentReplicaIndex];\n this.currentReplicaIndex =\n (this.currentReplicaIndex + 1) % this.config.replicas.length;\n return replica;\n }\n\n case \"random\": {\n const randomIndex = Math.floor(\n Math.random() * this.config.replicas.length,\n );\n return this.config.replicas[randomIndex];\n }\n\n default:\n // Default to first replica\n return this.config.replicas[0];\n }\n }\n}\n","/**\n * DATABASE SERVICE FACTORY - Main Entry Point\n *\n * This file is responsible for creating fully configured database services with extension chains.\n * It implements the decorator pattern to wrap base adapters with feature extensions.\n *\n * **RESPONSIBILITIES:**\n * 1. Config Validation - Ensures valid configuration before proceeding\n * 2. Base Adapter Creation - Creates core database adapters (Drizzle/Supabase/SQL)\n * 3. Adapter Chain Building - Wraps adapters with extensions in correct order\n * 4. Service Assembly - Creates final DatabaseService with all components\n * 5. Initialization - Establishes database connections and readiness\n *\n * **ADAPTER CHAIN ORDER:**\n * Base → Encryption → SoftDelete → Caching → Audit → ReadReplica\n * (innermost to outermost - each wraps the previous)\n */\n\n// Core service and interfaces - Main building blocks\nimport { DatabaseService } from \"@service/DatabaseService\"; // Main service implementation\n\n// Factory and adapters - Core creation logic\nimport { AdapterFactory } from \"./AdapterFactory\"; // Creates base adapters\n\n// Extension adapters - Feature layers (imported in chain order)\nimport { SoftDeleteAdapter } from \"../extensions/SoftDeleteExtension\"; // Logical deletion (layer 2)\nimport { AuditAdapter } from \"../extensions/AuditExtension\"; // Operation logging (layer 4)\nimport { EncryptionAdapter } from \"../extensions/EncryptionExtension\"; // Data encryption (layer 1)\nimport { CachingAdapter } from \"../extensions/CachingAdapter\"; // Query caching (layer 3)\nimport { ReadReplicaAdapter } from \"../extensions/ReadReplicaAdapter\"; // Read/write splitting (layer 5)\n\n// External dependencies - Error handling and constants\nimport { DatabaseError } from \"@plyaz/errors\"; // Error classes\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport { ADAPTER_TYPES, ADAPTERS } from \"@plyaz/types/db\";\nimport type {\n DatabaseServiceInterface,\n SqlConfig,\n SupabaseConfig,\n DatabaseAdapterType,\n DatabaseConfig,\n DatabaseServiceConfig,\n DrizzleConfig,\n} from \"@plyaz/types/db\";\n\n/**\n * ADAPTER CHAIN BUILDER - Decorator Pattern Implementation\n *\n * **RESPONSIBILITY:** Wraps base adapter with extension layers in correct order\n * **PATTERN:** Decorator - each adapter wraps the previous, adding functionality\n * **ORDER:** Base → Encryption → SoftDelete → Caching → Audit → ReadReplica\n *\n * **WHY THIS ORDER:**\n * 1. Encryption (innermost) - Encrypts data before storage, decrypts after retrieval\n * 2. SoftDelete - Handles logical deletion, works on encrypted data\n * 3. Caching - Caches processed data (after encryption/soft-delete logic)\n * 4. Audit - Logs final operations (after all data processing)\n * 5. ReadReplica (outermost) - Routes requests to appropriate database\n *\n * @param baseAdapter - The core database adapter (Drizzle/Supabase/SQL)\n * @param config - Configuration specifying which extensions to enable\n * @returns Fully wrapped adapter with all enabled extensions\n *\n * @example\n * ```typescript\n * // Creates: AuditAdapter(CachingAdapter(EncryptionAdapter(DrizzleAdapter)))\n * const wrappedAdapter = buildAdapterChain(baseAdapter, {\n * encryption: { enabled: true, key: 'secret', fields: { users: ['ssn'] } },\n * softDelete: { enabled: true, field: 'deletedAt' },\n * audit: { enabled: true, retentionDays: 90 }\n * });\n * ```\n */\n// eslint-disable-next-line complexity\nfunction buildAdapterChain(\n baseAdapter: DatabaseAdapterType,\n config: DatabaseServiceConfig,\n): DatabaseAdapterType {\n let adapter: DatabaseAdapterType = baseAdapter;\n\n // Layer 1: Encryption (innermost after base)\n // RESPONSIBILITY: Encrypts sensitive fields before storage, decrypts on retrieval\n // WHEN: Always applied first to ensure data is encrypted at rest\n if (config.encryption?.enabled) {\n adapter = new EncryptionAdapter(adapter, config.encryption);\n }\n\n // Layer 2: Soft Delete\n // RESPONSIBILITY: Converts DELETE operations to UPDATE (sets deletedAt), filters soft-deleted records\n // WHEN: Applied after encryption so deletion logic works on encrypted data\n if (config.softDelete?.enabled) {\n adapter = new SoftDeleteAdapter(adapter, config.softDelete);\n }\n\n // Layer 3: Caching\n // RESPONSIBILITY: Stores query results in memory/Redis, invalidates on writes\n // WHEN: Applied after data processing to cache final processed results\n if (config.cache?.enabled) {\n adapter = new CachingAdapter(adapter, config.cache);\n }\n\n // Layer 4: Audit\n // RESPONSIBILITY: Logs all database operations for compliance and tracking\n // WHEN: Applied late in chain to capture final operation details\n if (config.audit?.enabled) {\n adapter = new AuditAdapter(adapter, {\n ...config.audit,\n // Pass encrypted fields config so audit can log which fields are encrypted at rest\n encryptedFields: config.encryption?.enabled\n ? config.encryption.fields\n : undefined,\n });\n }\n\n // Layer 5: Read Replica (outermost wrapper)\n // RESPONSIBILITY: Routes reads to replicas, writes to primary database\n // WHEN: Applied last to handle request routing before any processing\n if (config.readReplica?.enabled) {\n adapter = new ReadReplicaAdapter(adapter, {\n enabled: true,\n replicas: [], // TODO: Create replica adapters from config\n strategy: config.readReplica.strategy,\n fallbackToPrimary: config.readReplica.fallbackToPrimary,\n });\n }\n\n return adapter;\n}\n\n/**\n * CONFIG TRANSFORMER - Converts External to Internal Format\n *\n * **RESPONSIBILITY:** Transforms user-friendly config into internal adapter factory format\n * **WHY NEEDED:** External config is user-friendly, internal config is adapter-specific\n *\n * **TRANSFORMATIONS:**\n * - Maps adapter names to internal constants\n * - Extracts connection details from nested config\n * - Normalizes different config formats (connectionString vs url)\n * - Sets up adapter-specific options (pool, SSL, etc.)\n *\n * @param config - User-provided database service configuration\n * @returns Normalized configuration for AdapterFactory.create()\n */\nfunction createAdapterConfig(config: DatabaseServiceConfig): DatabaseConfig {\n // Drizzle Adapter Config - PostgreSQL with Drizzle ORM\n if (config.adapter === ADAPTER_TYPES.DRIZZLE) {\n const drizzleConfig = config.config as DrizzleConfig;\n return {\n adapter: ADAPTERS.DRIZZLE,\n // orm: ADAPTERS.SUPABASE,\n connectionString: drizzleConfig.connectionString ?? drizzleConfig.url, // Support both formats\n pool: drizzleConfig.poolSize\n ? { max: drizzleConfig.poolSize }\n : undefined, // Optional connection pooling\n tableIdColumns: drizzleConfig.tableIdColumns, // Custom ID column mappings\n };\n }\n\n // Supabase Adapter Config - Supabase API integration\n if (config.adapter === ADAPTER_TYPES.SUPABASE) {\n const supabaseConfig = config.config as SupabaseConfig;\n return {\n adapter: ADAPTERS.SUPABASE,\n // orm: ADAPTERS.SUPABASE, // Optional ORM choice\n supabaseUrl: supabaseConfig.supabaseUrl, // Supabase project URL\n supabaseAnonKey: supabaseConfig.supabaseAnonKey, // Public API key\n supabaseServiceKey: supabaseConfig.supabaseServiceKey, // Service role key (admin)\n schema: supabaseConfig.schema, // Database schema\n tableIdColumns: supabaseConfig.tableIdColumns, // Custom ID column mappings\n };\n }\n\n // Mock Adapter Config - In-memory testing database\n if (config.adapter === ADAPTER_TYPES.MOCK) {\n return {\n adapter: ADAPTERS.MOCK,\n ...config.config, // Pass through all mock config options\n };\n }\n\n // 🔧 Raw SQL Adapter Config - Direct SQL database connection\n const sqlConfig = config.config as SqlConfig;\n return {\n adapter: ADAPTERS.SQL,\n connectionString: sqlConfig.connectionString ?? sqlConfig.url, // Support both formats\n schema: sqlConfig.schema, // Default schema for all tables\n tableIdColumns: sqlConfig.tableIdColumns, // Custom ID column mappings\n };\n}\n\n/**\n * CONFIG VALIDATOR - Ensures Configuration Integrity\n *\n * **RESPONSIBILITY:** Validates user configuration before processing\n * **PREVENTS:** Runtime errors from invalid/missing configuration\n * **THROWS:** Descriptive validation errors for debugging\n *\n * **VALIDATION CHECKS:**\n * 1. Config object exists\n * 2. Adapter type is specified\n * 3. Adapter configuration is provided\n *\n * @param config - User-provided configuration to validate\n * @throws {DatabaseError} When configuration is invalid or incomplete\n */\nfunction validateConfig(config: DatabaseServiceConfig): void {\n // Check: Configuration object exists\n if (!config) {\n throw new DatabaseError(\n \"Database configuration is required\",\n DATABASE_ERROR_CODES.CONFIG_REQUIRED,\n {\n context: { source: \"validateConfig\" },\n cause: new Error(\"Database configuration is required\"),\n },\n );\n }\n\n // Check: Adapter type specified (drizzle/supabase/sql)\n if (!config.adapter) {\n throw new DatabaseError(\n \"Database adapter type is required\",\n DATABASE_ERROR_CODES.CONFIG_REQUIRED,\n {\n context: { source: \"validateConfig\" },\n cause: new Error(\"Database adapter type is required\"),\n },\n );\n }\n\n // Check: Adapter-specific configuration provided\n if (!config.config) {\n throw new DatabaseError(\n \"Adapter configuration is required\",\n DATABASE_ERROR_CODES.CONFIG_REQUIRED,\n {\n context: { source: \"validateConfig\" },\n cause: new Error(\"Adapter configuration is required\"),\n },\n );\n }\n}\n\n/**\n * MAIN FACTORY - Application Entry Point\n *\n * Creates a fully configured database service with extension chain.\n * This is the ONLY way applications should create database services.\n *\n * **Application Flow:**\n * 1. App calls createDatabaseService() at startup\n * 2. Factory validates config and creates base adapter (Drizzle/Supabase/etc.)\n * 3. Factory builds 6-layer adapter chain: Base → Encryption → SoftDelete → Cache → Audit → ReadReplica\n * 4. Factory creates DatabaseService with final wrapped adapter\n * 5. App uses returned DatabaseServiceInterface in repositories/services\n *\n * **What this function does:**\n * - Validates configuration using validateConfig()\n * - Creates base adapter via AdapterFactory.create()\n * - Builds decorator chain via buildAdapterChain()\n * - Initializes database connection\n * - Returns configured DatabaseService instance\n *\n * **Called by:** Application startup code (app.ts, main.ts)\n * **Calls:** validateConfig(), AdapterFactory.create(), buildAdapterChain(), DatabaseService constructor\n * **Returns to:** Application layer for injection into repositories\n *\n * @param config Complete database service configuration including adapter and extensions\n * @returns Promise resolving to configured DatabaseServiceInterface instance\n *\n * @throws {BaseError} When configuration is invalid or initialization fails\n *\n * @example\n * ### Basic Setup (app.ts)\n * ```typescript\n * import { createDatabaseService, Tables } from '@plyaz/db';\n *\n * // Called once at application startup\n * const db = await createDatabaseService({\n * adapter: 'drizzle',\n * config: { connectionString: process.env.DATABASE_URL }\n * });\n *\n * // Inject into services\n * const userService = new UserService(db);\n * ```\n *\n * @example\n * ### Production Configuration\n * ```typescript\n * const db = await createDatabaseService({\n * adapter: 'drizzle',\n * config: {\n * connectionString: process.env.DATABASE_URL,\n * poolSize: 20\n * },\n *\n * // Extensions applied in order: Base → Encryption → SoftDelete → Cache → Audit → ReadReplica\n * encryption: {\n * enabled: true,\n * key: process.env.ENCRYPTION_KEY,\n * fields: {\n * [Tables.USERS]: ['ssn', 'taxId'],\n * [Tables.PAYMENTS]: ['cardNumber', 'cvv']\n * }\n * },\n *\n * softDelete: {\n * enabled: true,\n * field: 'deletedAt'\n * },\n *\n * audit: {\n * enabled: true,\n * retentionDays: 90,\n * onAuditAfterWrite: async (event) => {\n * await complianceService.recordAudit(event);\n * }\n * },\n *\n * cache: {\n * enabled: true,\n * ttl: 300,\n * invalidation: 'write'\n * },\n *\n * events: {\n * onAfterWrite: async (event) => {\n * await notificationService.send(event);\n * }\n * }\n * });\n * ```\n *\n * @example\n * ### Testing Setup\n * ```typescript\n * // Use mock adapter for tests\n * const db = await createDatabaseService({\n * adapter: 'mock',\n * config: { logging: true }\n * });\n * ```\n */\nexport async function createDatabaseService(\n config: DatabaseServiceConfig,\n): Promise<DatabaseServiceInterface> {\n try {\n // STEP 1: Validate Configuration\n // RESPONSIBILITY: Ensure config is complete and valid before proceeding\n validateConfig(config);\n\n // STEP 2: Create Base Adapter\n // RESPONSIBILITY: Transform config and create core database adapter (Drizzle/Supabase/SQL)\n const adapterConfig = createAdapterConfig(config); // Transform to internal format\n const baseAdapter = AdapterFactory.create(\n adapterConfig.adapter,\n adapterConfig,\n ); // Create adapter\n\n // STEP 3: Build Adapter Chain\n // RESPONSIBILITY: Wrap base adapter with enabled extensions in correct order\n const finalAdapter = buildAdapterChain(baseAdapter, config);\n\n // STEP 4: Create Database Service\n // RESPONSIBILITY: Assemble final service with wrapped adapter and configuration\n const service = new DatabaseService({\n adapter: finalAdapter, // Fully wrapped adapter chain\n globalConfig: config, // Original configuration for reference\n eventHandlers: config.events, // Event handlers for notifications\n });\n\n // STEP 5: Initialize Database Connection\n // RESPONSIBILITY: Establish database connection and verify readiness\n const initResult = await baseAdapter.initialize();\n if (!initResult.success) {\n throw new DatabaseError(\n `Failed to initialize adapter: ${initResult.error?.message ?? \"Unknown error\"}`,\n DATABASE_ERROR_CODES.INIT_FAILED,\n {\n context: { source: \"createDatabaseService\" },\n cause: initResult.error ?? new Error(\"Failed to initialize adapter\"),\n },\n );\n }\n\n return service; // Return fully configured and initialized service\n } catch (error) {\n throw new DatabaseError(\n `Failed to create database service: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.INIT_FAILED,\n {\n context: { source: \"createDatabaseService\" },\n cause: error as Error,\n },\n );\n }\n}\n","/**\n * @fileoverview Base Repository for @plyaz/db package\n *\n * This module provides the BaseRepository abstract class that serves as the foundation\n * for all domain-specific repositories in the @plyaz/db package. It provides type-safe\n * CRUD operations and consistent interface patterns.\n *\n */\n\nimport type {\n DatabaseResult,\n PaginatedResult,\n QueryOptions,\n Filter,\n DatabaseServiceInterface,\n CreateInput,\n OperationConfig,\n} from \"@plyaz/types/db\";\n\n/**\n * BASE REPOSITORY - Repository Layer Foundation\n *\n * Base repository providing common CRUD operations for domain entities.\n * All domain-specific repositories extend this class for type-safe database operations.\n *\n * **Application Flow Position:**\n * Service Layer → **Repository Layer** → DatabaseService → Adapter Chain\n *\n * **What this class provides:**\n * - Type-safe CRUD operations for domain entities\n * - Consistent interface across all repositories\n * - Delegation to DatabaseService with proper table mapping\n * - Foundation for domain-specific repository methods\n * - Default operation config (adapter, schema, etc.) that can be overridden per-query\n *\n * **Called by:** Service layer (UserService, OrderService, etc.)\n * **Calls:** DatabaseService methods (get, create, update, delete, etc.)\n * **Extended by:** Domain repositories (UserRepository, OrderRepository, etc.)\n *\n * @template T The entity type this repository manages\n *\n * @example\n * ### Creating a Domain Repository\n * ```typescript\n * interface User {\n * id: string;\n * name: string;\n * email: string;\n * createdAt: Date;\n * }\n *\n * class UserRepository extends BaseRepository<User> {\n * constructor(db: DatabaseServiceInterface) {\n * super(db, Tables.USERS);\n * }\n *\n * // Domain-specific methods\n * async findByEmail(email: string) {\n * return this.findOne({ field: 'email', operator: 'eq', value: email });\n * }\n * }\n * ```\n *\n * @example\n * ### Repository with Default Adapter\n * ```typescript\n * // Analytics repository that always uses the 'analytics' adapter by default\n * class AnalyticsRepository extends BaseRepository<Event> {\n * constructor(db: DatabaseServiceInterface) {\n * super(db, 'events', { adapter: 'analytics', schema: 'analytics' });\n * }\n * }\n *\n * // All queries use analytics adapter by default\n * await analyticsRepo.findById('event-123'); // Uses 'analytics' adapter\n *\n * // But can still override per-query\n * await analyticsRepo.findById('event-123', { adapter: 'primary' });\n * ```\n *\n * @example\n * ### Usage in Service Layer\n * ```typescript\n * class UserService {\n * constructor(private userRepo: UserRepository) {}\n *\n * async getUserById(id: string) {\n * // Calls BaseRepository.findById() → DatabaseService.get()\n * return this.userRepo.findById(id);\n * }\n * }\n * ```\n */\nexport abstract class BaseRepository<T extends Record<string, unknown>> {\n protected readonly defaultConfig?: OperationConfig;\n\n constructor(\n protected readonly db: DatabaseServiceInterface,\n protected readonly tableName: string,\n defaultConfig?: OperationConfig,\n ) {\n this.defaultConfig = defaultConfig;\n }\n\n /**\n * Get the table name for this repository\n *\n * Useful for transaction operations where you need the table name\n * to execute raw queries within a transaction context.\n *\n * @returns The table name this repository operates on\n */\n getTableName(): string {\n return this.tableName;\n }\n\n /**\n * Merges default repository config with per-operation config\n * Per-operation config takes precedence over default config\n */\n private mergeConfig(\n operationConfig?: OperationConfig,\n ): OperationConfig | undefined {\n if (!this.defaultConfig && !operationConfig) {\n return undefined;\n }\n return {\n ...this.defaultConfig,\n ...operationConfig,\n };\n }\n\n /**\n * Find a single entity by its primary key ID\n *\n * @param {string} id - The primary key ID of the entity to retrieve\n * @param {OperationConfig} [config] - Optional per-operation configuration (adapter selection, schema override, etc.)\n * @returns {Promise<DatabaseResult<T | null>>} Promise resolving to the entity or null if not found\n *\n * @example\n * ```typescript\n * const result = await userRepository.findById('user-123');\n * if (result.success && result.value) {\n * console.log('Found user:', result.value.name);\n * }\n *\n * // Use specific adapter for this query\n * const analyticsResult = await userRepository.findById('user-123', {\n * adapter: 'analytics'\n * });\n * ```\n */\n async findById(\n id: string,\n config?: OperationConfig,\n ): Promise<DatabaseResult<T | null>> {\n return this.db.get<T>(this.tableName, id, this.mergeConfig(config));\n }\n\n /**\n * Find multiple entities with optional filtering, sorting, and pagination\n *\n * @param {QueryOptions<T>} [options] - Optional query configuration with type-safe fields\n * @param {OperationConfig} [config] - Optional per-operation configuration (adapter selection, schema override, etc.)\n * @returns {Promise<DatabaseResult<PaginatedResult<T>>>} Promise resolving to paginated results\n *\n * @example\n * ```typescript\n * const result = await userRepository.findMany({\n * filter: { field: 'status', operator: 'eq', value: 'active' },\n * sort: [{ field: 'createdAt', direction: 'desc' }],\n * pagination: { limit: 20, offset: 0 }\n * });\n *\n * // Query from analytics database\n * const analyticsResult = await userRepository.findMany({}, {\n * adapter: 'analytics'\n * });\n * ```\n */\n async findMany(\n options?: QueryOptions<T>,\n config?: OperationConfig,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n return this.db.list<T>(this.tableName, options, this.mergeConfig(config));\n }\n\n /**\n * Create a new entity in the database\n *\n * @param {CreateInput<T>} data - The entity data to create (id is auto-generated)\n * @param {OperationConfig} [config] - Optional per-operation configuration (adapter selection, schema override, etc.)\n * @returns {Promise<DatabaseResult<T>>} Promise resolving to the created entity\n *\n * @example\n * ```typescript\n * const result = await userRepository.create({\n * name: 'John Doe',\n * email: 'john@example.com'\n * });\n *\n * // Create in specific database/schema\n * const result = await userRepository.create({\n * name: 'Jane Doe'\n * }, {\n * adapter: 'secondary',\n * schema: 'backoffice'\n * });\n * ```\n */\n async create(\n data: CreateInput<T>,\n config?: OperationConfig,\n ): Promise<DatabaseResult<T>> {\n return this.db.create<T>(this.tableName, data, this.mergeConfig(config));\n }\n\n /**\n * Update an existing entity by ID\n *\n * @param {string} id - The primary key ID of the entity to update\n * @param {Partial<T>} data - Partial entity data containing fields to update\n * @param {OperationConfig} [config] - Optional per-operation configuration (adapter selection, schema override, etc.)\n * @returns {Promise<DatabaseResult<T>>} Promise resolving to the updated entity\n *\n * @example\n * ```typescript\n * const result = await userRepository.update('user-123', {\n * email: 'newemail@example.com',\n * updatedAt: new Date()\n * });\n *\n * // Update in specific adapter with custom ID column\n * const result = await userRepository.update('flag-key', {\n * value: true\n * }, {\n * adapter: 'config',\n * idColumn: 'key'\n * });\n * ```\n */\n async update(\n id: string,\n data: Partial<T>,\n config?: OperationConfig,\n ): Promise<DatabaseResult<T>> {\n return this.db.update<T>(\n this.tableName,\n id,\n data,\n this.mergeConfig(config),\n );\n }\n\n /**\n * Delete an entity by ID (hard delete)\n *\n * @param {string} id - The primary key ID of the entity to delete\n * @param {OperationConfig} [config] - Optional per-operation configuration (adapter selection, schema override, etc.)\n * @returns {Promise<DatabaseResult<void>>} Promise resolving when deletion is complete\n *\n * @warning This is a permanent operation that cannot be undone\n * @see {@link softDelete} For recoverable deletion\n *\n * @example\n * ```typescript\n * const result = await userRepository.delete('user-123');\n *\n * // Delete from specific adapter\n * const result = await userRepository.delete('user-123', {\n * adapter: 'archive'\n * });\n * ```\n */\n async delete(\n id: string,\n config?: OperationConfig,\n ): Promise<DatabaseResult<void>> {\n return this.db.delete(this.tableName, id, this.mergeConfig(config));\n }\n\n /**\n * Count entities matching optional filter criteria\n *\n * @param {Filter<T>} [filter] - Optional filter conditions with type-safe fields\n * @param {OperationConfig} [config] - Optional per-operation configuration (adapter selection, schema override, etc.)\n * @returns {Promise<DatabaseResult<number>>} Promise resolving to the count\n *\n * @example\n * ```typescript\n * const totalResult = await userRepository.count();\n * const activeResult = await userRepository.count({\n * field: 'status', operator: 'eq', value: 'active'\n * });\n *\n * // Count in specific adapter\n * const archiveCount = await userRepository.count(undefined, {\n * adapter: 'archive'\n * });\n * ```\n */\n async count(\n filter?: Filter<T>,\n config?: OperationConfig,\n ): Promise<DatabaseResult<number>> {\n return this.db.count(this.tableName, filter, this.mergeConfig(config));\n }\n\n /**\n * Check if an entity exists by ID\n *\n * @param {string} id - The primary key ID to check\n * @param {OperationConfig} [config] - Optional per-operation configuration (adapter selection, schema override, etc.)\n * @returns {Promise<DatabaseResult<boolean>>} Promise resolving to existence status\n *\n * @example\n * ```typescript\n * const existsResult = await userRepository.exists('user-123');\n * if (existsResult.success && existsResult.value) {\n * console.log('User exists');\n * }\n *\n * // Check existence in specific adapter\n * const existsInArchive = await userRepository.exists('user-123', {\n * adapter: 'archive'\n * });\n * ```\n */\n async exists(\n id: string,\n config?: OperationConfig,\n ): Promise<DatabaseResult<boolean>> {\n const result = await this.db.get<T>(\n this.tableName,\n id,\n this.mergeConfig(config),\n );\n return {\n success: result.success,\n value: result.success && result.value !== null,\n error: result.error,\n };\n }\n\n /**\n * Find the first entity matching filter criteria\n *\n * @param {Filter<T>} filter - Filter conditions with type-safe fields\n * @param {OperationConfig} [config] - Optional per-operation configuration (adapter selection, schema override, etc.)\n * @returns {Promise<DatabaseResult<T | null>>} Promise resolving to first match or null\n *\n * @example\n * ```typescript\n * const result = await userRepository.findOne({\n * field: 'email', operator: 'eq', value: 'john@example.com'\n * });\n *\n * // Find in specific adapter\n * const archivedUser = await userRepository.findOne({\n * field: 'email', operator: 'eq', value: 'john@example.com'\n * }, {\n * adapter: 'archive',\n * includeSoftDeleted: true\n * });\n * ```\n */\n async findOne(\n filter: Filter<T>,\n config?: OperationConfig,\n ): Promise<DatabaseResult<T | null>> {\n return this.db.findOne<T>(this.tableName, filter, this.mergeConfig(config));\n }\n\n /**\n * Soft delete an entity by ID (recoverable deletion)\n *\n * @param {string} id - The primary key ID of the entity to soft delete\n * @param {OperationConfig} [config] - Optional per-operation configuration (adapter selection, schema override, etc.)\n * @returns {Promise<DatabaseResult<void>>} Promise resolving when soft deletion is complete\n *\n * @see {@link delete} For permanent deletion\n *\n * @example\n * ```typescript\n * const result = await userRepository.softDelete('user-123');\n * // User is hidden but can be recovered\n *\n * // Soft delete in specific adapter\n * const result = await userRepository.softDelete('user-123', {\n * adapter: 'primary',\n * skipAudit: false\n * });\n * ```\n */\n async softDelete(\n id: string,\n config?: OperationConfig,\n ): Promise<DatabaseResult<void>> {\n return this.db.softDelete(this.tableName, id, this.mergeConfig(config));\n }\n}\n","/**\n * MultiWriteExtension - Write to primary + multiple secondary adapters\n *\n * Decorator that wraps the base adapter to replicate writes across\n * multiple secondary adapters for redundancy, cross-region replication,\n * or analytics syncing.\n *\n * @example\n * ```typescript\n * const db = await createDatabaseService({\n * adapter: 'sql',\n * config: { connectionString: process.env.DATABASE_URL },\n *\n * multiWrite: {\n * enabled: true,\n * adapters: [\n * { adapter: 'supabase', config: { ... } },\n * { adapter: 'sql', config: { connectionString: process.env.ANALYTICS_DB } }\n * ],\n * mode: 'best-effort', // or 'strict'\n * onSecondaryFailure: 'log', // or 'warn', 'throw'\n * timeout: 5000\n * }\n * });\n * ```\n */\n\nimport type {\n DatabaseAdapterType,\n DatabaseResult,\n PaginatedResult,\n QueryOptions,\n Transaction,\n DatabaseHealthStatus,\n Filter,\n MultiWriteConfig,\n} from \"@plyaz/types/db\";\nimport { DatabasePackageError } from \"@plyaz/errors\";\nimport { ERROR_CODES } from \"@plyaz/types/errors\";\n\n/**\n * MultiWriteAdapter - Extension for multi-adapter write replication\n *\n * Decorates a base adapter to replicate all write operations (create, update, delete)\n * to multiple secondary adapters. Reads always go to the primary adapter.\n */\nexport class MultiWriteAdapter implements DatabaseAdapterType {\n public baseAdapter: DatabaseAdapterType;\n private config: Required<MultiWriteConfig>;\n\n constructor(baseAdapter: DatabaseAdapterType, config: MultiWriteConfig) {\n this.baseAdapter = baseAdapter;\n this.config = {\n mode: \"best-effort\",\n onSecondaryFailure: \"log\",\n timeout: 5000,\n ...config,\n };\n }\n\n async initialize(): Promise<DatabaseResult<void>> {\n return this.baseAdapter.initialize();\n }\n\n async close(): Promise<DatabaseResult<void>> {\n return this.baseAdapter.close();\n }\n\n async connect(): Promise<void> {\n await this.baseAdapter.connect();\n // Also connect all secondaries\n for (const secondary of this.config.adapters) {\n if (typeof secondary.connect === \"function\") {\n await secondary.connect();\n }\n }\n }\n\n async disconnect(): Promise<void> {\n await this.baseAdapter.disconnect();\n // Also disconnect all secondaries\n for (const secondary of this.config.adapters) {\n if (typeof secondary.disconnect === \"function\") {\n await secondary.disconnect();\n }\n }\n }\n\n getClient(): object {\n return this.baseAdapter.getClient();\n }\n\n async query<T>(sql: string, params?: unknown[]): Promise<T[]> {\n return this.baseAdapter.query<T>(sql, params as T[] | undefined);\n }\n\n registerTable<TTable = string, TIdColumn = string>(\n name: string,\n table?: TTable,\n idColumn?: TIdColumn,\n ): void {\n this.baseAdapter.registerTable(name, table, idColumn);\n\n // Also register on secondaries\n for (const secondary of this.config.adapters) {\n if (typeof secondary.registerTable === \"function\") {\n secondary.registerTable(name, table, idColumn);\n }\n }\n }\n\n // Read operations - always use primary\n async findById<T>(\n table: string,\n id: string,\n ): Promise<DatabaseResult<T | null>> {\n return this.baseAdapter.findById<T>(table, id);\n }\n\n async findMany<T extends Record<string, unknown>>(\n table: string,\n options?: QueryOptions<T>,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n return this.baseAdapter.findMany<T>(table, options);\n }\n\n async exists(table: string, id: string): Promise<DatabaseResult<boolean>> {\n return this.baseAdapter.exists(table, id);\n }\n\n async count<T extends Record<string, unknown> = Record<string, unknown>>(\n table: string,\n filter?: Filter<T>,\n ): Promise<DatabaseResult<number>> {\n return this.baseAdapter.count<T>(table, filter);\n }\n\n // Write operations - replicate to secondaries\n async create<T extends Record<string, unknown>>(\n table: string,\n data: T,\n ): Promise<DatabaseResult<T>> {\n // Write to primary first\n const primaryResult = await this.baseAdapter.create<T>(table, data);\n\n if (!primaryResult.success) {\n return primaryResult;\n }\n\n // Replicate to secondaries\n await this.replicateWrite(() =>\n Promise.all(\n this.config.adapters.map((adapter) => adapter.create(table, data)),\n ),\n );\n\n return primaryResult;\n }\n\n async update<T>(\n table: string,\n id: string,\n data: Partial<T>,\n ): Promise<DatabaseResult<T>> {\n // Write to primary first\n const primaryResult = await this.baseAdapter.update<T>(table, id, data);\n\n if (!primaryResult.success) {\n return primaryResult;\n }\n\n // Replicate to secondaries\n await this.replicateWrite(() =>\n Promise.all(\n this.config.adapters.map((adapter) => adapter.update(table, id, data)),\n ),\n );\n\n return primaryResult;\n }\n\n async delete(table: string, id: string): Promise<DatabaseResult<void>> {\n // Write to primary first\n const primaryResult = await this.baseAdapter.delete(table, id);\n\n if (!primaryResult.success) {\n return primaryResult;\n }\n\n // Replicate to secondaries\n await this.replicateWrite(() =>\n Promise.all(\n this.config.adapters.map((adapter) => adapter.delete(table, id)),\n ),\n );\n\n return primaryResult;\n }\n\n async transaction<T>(\n callback: (trx: Transaction) => Promise<T>,\n ): Promise<DatabaseResult<T>> {\n // Transactions only on primary (secondaries get individual operations)\n return this.baseAdapter.transaction(callback);\n }\n\n async healthCheck(): Promise<DatabaseResult<DatabaseHealthStatus>> {\n return this.baseAdapter.healthCheck();\n }\n\n /**\n * Replicate write operation to secondary adapters\n */\n private async replicateWrite(\n fn: () => Promise<DatabaseResult<unknown>[]>,\n ): Promise<void> {\n if (this.config.mode === \"strict\") {\n // Strict mode: Wait for all secondaries, throw on any failure\n const results = await Promise.allSettled([\n this.executeWithTimeout(fn(), this.config.timeout),\n ]);\n\n const failures = results.filter((r) => r.status === \"rejected\");\n if (failures.length > 0) {\n this.handleSecondaryFailure(failures);\n }\n } else {\n // Best-effort mode: Fire and forget (non-blocking)\n this.executeWithTimeout(fn(), this.config.timeout)\n .then((results) => {\n const failures = results.filter((r) => !r.success);\n if (failures.length > 0) {\n this.handleSecondaryFailure(\n failures.map((f) => ({\n status: \"rejected\" as const,\n reason: f.error,\n })),\n );\n }\n })\n .catch((error) => {\n this.handleSecondaryFailure([\n { status: \"rejected\" as const, reason: error },\n ]);\n });\n }\n }\n\n /**\n * Execute operation with timeout\n */\n private async executeWithTimeout<T>(\n promise: Promise<T>,\n timeoutMs: number,\n ): Promise<T> {\n return Promise.race([\n promise,\n new Promise<T>((_, reject) =>\n setTimeout(\n () => reject(new Error(\"Secondary write timeout\")),\n timeoutMs,\n ),\n ),\n ]);\n }\n\n /**\n * Handle secondary adapter failures\n */\n private handleSecondaryFailure(\n failures: PromiseSettledResult<unknown>[],\n ): void {\n const errorMessages = failures\n .map((f) =>\n f.status === \"rejected\" ? f.reason?.message : \"Unknown error\",\n )\n .join(\", \");\n\n const message = `Multi-write secondary failure: ${errorMessages}`;\n\n switch (this.config.onSecondaryFailure) {\n case \"log\":\n console.log(`[MultiWrite] ${message}`);\n break;\n case \"warn\":\n console.warn(`[MultiWrite] ${message}`);\n break;\n case \"throw\":\n throw new DatabasePackageError(message, ERROR_CODES.DB_UPDATE_FAILED);\n }\n }\n}\n","/**\n * MultiReadExtension - Read from primary + multiple read replicas\n *\n * Decorator that wraps the base adapter to distribute reads across\n * multiple read replicas using configurable load balancing strategies.\n * Supports automatic failover to primary on replica failure.\n *\n * @example\n * ```typescript\n * const db = await createDatabaseService({\n * adapter: 'sql',\n * config: { connectionString: process.env.DATABASE_URL },\n *\n * multiRead: {\n * enabled: true,\n * adapters: [\n * { adapter: 'sql', config: { connectionString: process.env.REPLICA1_URL } },\n * { adapter: 'sql', config: { connectionString: process.env.REPLICA2_URL } }\n * ],\n * strategy: 'round-robin', // or 'random', 'fastest', 'least-conn'\n * fallbackToPrimary: true,\n * healthCheckInterval: 30000\n * }\n * });\n * ```\n */\n\nimport type {\n DatabaseAdapterType,\n DatabaseResult,\n PaginatedResult,\n QueryOptions,\n Transaction,\n DatabaseHealthStatus,\n Filter,\n MultiReadConfig,\n ReplicaHealth,\n} from \"@plyaz/types/db\";\nimport { DatabasePackageError } from \"@plyaz/errors\";\nimport { ERROR_CODES } from \"@plyaz/types/errors\";\nimport { failure } from \"@utils/databaseResultHelpers\";\n\n/** Weight for existing average in EMA calculation */\nconst EMA_EXISTING_WEIGHT = 0.8;\n/** Weight for new value in EMA calculation */\nconst EMA_NEW_WEIGHT = 0.2;\n\n/**\n * MultiReadAdapter - Extension for multi-replica read distribution\n *\n * Decorates a base adapter to distribute read operations across multiple\n * read replicas. Writes always go to the primary adapter. Supports automatic\n * failover and health tracking.\n */\nexport class MultiReadAdapter implements DatabaseAdapterType {\n public baseAdapter: DatabaseAdapterType;\n private config: Required<MultiReadConfig>;\n private currentReadIndex = 0;\n private replicaHealth: Map<DatabaseAdapterType, ReplicaHealth> = new Map();\n private healthCheckTimer?: globalThis.NodeJS.Timeout;\n\n constructor(baseAdapter: DatabaseAdapterType, config: MultiReadConfig) {\n this.baseAdapter = baseAdapter;\n this.config = {\n strategy: \"round-robin\",\n fallbackToPrimary: true,\n healthCheckInterval: 30000,\n maxFailures: 3,\n ...config,\n };\n\n // Initialize health tracking\n this.initializeHealthTracking();\n\n // Start health checks\n if (this.config.adapters.length > 0) {\n this.startHealthChecks();\n }\n }\n\n async initialize(): Promise<DatabaseResult<void>> {\n return this.baseAdapter.initialize();\n }\n\n async close(): Promise<DatabaseResult<void>> {\n this.stopHealthChecks();\n return this.baseAdapter.close();\n }\n\n async connect(): Promise<void> {\n await this.baseAdapter.connect();\n // Also connect all replicas\n for (const replica of this.config.adapters) {\n if (typeof replica.connect === \"function\") {\n await replica.connect();\n }\n }\n }\n\n async disconnect(): Promise<void> {\n await this.baseAdapter.disconnect();\n // Also disconnect all replicas\n for (const replica of this.config.adapters) {\n if (typeof replica.disconnect === \"function\") {\n await replica.disconnect();\n }\n }\n }\n\n getClient(): object {\n return this.baseAdapter.getClient();\n }\n\n async query<T>(sql: string, params?: unknown[]): Promise<T[]> {\n return this.baseAdapter.query<T>(sql, params as T[] | undefined);\n }\n\n registerTable<TTable = string, TIdColumn = string>(\n name: string,\n table?: TTable,\n idColumn?: TIdColumn,\n ): void {\n this.baseAdapter.registerTable(name, table, idColumn);\n\n // Also register on replicas\n for (const replica of this.config.adapters) {\n if (typeof replica.registerTable === \"function\") {\n replica.registerTable(name, table, idColumn);\n }\n }\n }\n\n // Read operations - use replicas with load balancing\n async findById<T>(\n table: string,\n id: string,\n ): Promise<DatabaseResult<T | null>> {\n return this.readFromReplicas((adapter) => adapter.findById<T>(table, id));\n }\n\n async findMany<T extends Record<string, unknown>>(\n table: string,\n options?: QueryOptions<T>,\n ): Promise<DatabaseResult<PaginatedResult<T>>> {\n return this.readFromReplicas((adapter) =>\n adapter.findMany<T>(table, options),\n );\n }\n\n async exists(table: string, id: string): Promise<DatabaseResult<boolean>> {\n return this.readFromReplicas((adapter) => adapter.exists(table, id));\n }\n\n async count<T extends Record<string, unknown> = Record<string, unknown>>(\n table: string,\n filter?: Filter<T>,\n ): Promise<DatabaseResult<number>> {\n return this.readFromReplicas((adapter) => adapter.count<T>(table, filter));\n }\n\n // Write operations - always use primary\n async create<T extends Record<string, unknown>>(\n table: string,\n data: T,\n ): Promise<DatabaseResult<T>> {\n return this.baseAdapter.create<T>(table, data);\n }\n\n async update<T>(\n table: string,\n id: string,\n data: Partial<T>,\n ): Promise<DatabaseResult<T>> {\n return this.baseAdapter.update<T>(table, id, data);\n }\n\n async delete(table: string, id: string): Promise<DatabaseResult<void>> {\n return this.baseAdapter.delete(table, id);\n }\n\n async transaction<T>(\n callback: (trx: Transaction) => Promise<T>,\n ): Promise<DatabaseResult<T>> {\n // Transactions only on primary\n return this.baseAdapter.transaction(callback);\n }\n\n async healthCheck(): Promise<DatabaseResult<DatabaseHealthStatus>> {\n return this.baseAdapter.healthCheck();\n }\n\n /**\n * Read from replica adapters using configured strategy\n */\n private async readFromReplicas<T>(\n fn: (adapter: DatabaseAdapterType) => Promise<DatabaseResult<T>>,\n ): Promise<DatabaseResult<T>> {\n const healthyReplicas = this.config.adapters.filter((adapter) =>\n this.isReplicaHealthy(adapter),\n );\n\n if (healthyReplicas.length === 0) {\n // No healthy replicas, fallback to primary\n if (this.config.fallbackToPrimary) {\n return fn(this.baseAdapter);\n }\n return failure(\n new DatabasePackageError(\n \"No healthy read replicas available\",\n ERROR_CODES.DB_CONNECTION_FAILED,\n ),\n );\n }\n\n // Select replica based on strategy\n const selectedReplica = this.selectReplica(healthyReplicas);\n const startTime = Date.now();\n\n try {\n const result = await fn(selectedReplica);\n\n // Update health metrics\n this.updateHealthMetrics(selectedReplica, true, Date.now() - startTime);\n\n if (result.success) {\n return result;\n }\n\n // Result failed, try fallback\n if (this.config.fallbackToPrimary) {\n this.updateHealthMetrics(\n selectedReplica,\n false,\n Date.now() - startTime,\n );\n return fn(this.baseAdapter);\n }\n\n return result;\n } catch (error) {\n // Replica failed, try fallback\n this.updateHealthMetrics(selectedReplica, false, Date.now() - startTime);\n\n if (this.config.fallbackToPrimary) {\n return fn(this.baseAdapter);\n }\n\n return failure(\n new DatabasePackageError(\n `Read from replica failed: ${(error as Error).message}`,\n ERROR_CODES.DB_QUERY_FAILED,\n { cause: error as Error },\n ),\n );\n }\n }\n\n /**\n * Select a replica based on load balancing strategy\n */\n private selectReplica(replicas: DatabaseAdapterType[]): DatabaseAdapterType {\n switch (this.config.strategy) {\n case \"round-robin\":\n this.currentReadIndex = (this.currentReadIndex + 1) % replicas.length;\n return replicas[this.currentReadIndex];\n\n case \"random\":\n return replicas[Math.floor(Math.random() * replicas.length)];\n\n case \"fastest\":\n // Select replica with lowest avg response time\n return replicas.reduce((fastest, current) => {\n const fastestHealth = this.replicaHealth.get(fastest);\n const currentHealth = this.replicaHealth.get(current);\n if (!fastestHealth || !currentHealth) return fastest;\n return currentHealth.avgResponseTime < fastestHealth.avgResponseTime\n ? current\n : fastest;\n });\n\n case \"least-conn\":\n // For now, same as fastest (would need connection tracking)\n return this.selectReplica(\n replicas.filter((r) => this.isReplicaHealthy(r)),\n );\n\n default:\n return replicas[0];\n }\n }\n\n /**\n * Initialize health tracking for all replicas\n */\n private initializeHealthTracking(): void {\n for (const adapter of this.config.adapters) {\n this.replicaHealth.set(adapter, {\n adapter,\n isHealthy: true,\n failureCount: 0,\n lastChecked: Date.now(),\n avgResponseTime: 0,\n });\n }\n }\n\n /**\n * Update health metrics for a replica\n */\n private updateHealthMetrics(\n adapter: DatabaseAdapterType,\n success: boolean,\n responseTime: number,\n ): void {\n const health = this.replicaHealth.get(adapter);\n if (!health) return;\n\n if (success) {\n health.failureCount = 0;\n health.isHealthy = true;\n health.avgResponseTime =\n health.avgResponseTime * EMA_EXISTING_WEIGHT +\n responseTime * EMA_NEW_WEIGHT; // EMA\n } else {\n health.failureCount++;\n if (health.failureCount >= this.config.maxFailures) {\n health.isHealthy = false;\n }\n }\n\n health.lastChecked = Date.now();\n }\n\n /**\n * Check if replica is healthy\n */\n private isReplicaHealthy(adapter: DatabaseAdapterType): boolean {\n const health = this.replicaHealth.get(adapter);\n return health?.isHealthy ?? true;\n }\n\n /**\n * Start health check interval\n */\n private startHealthChecks(): void {\n this.healthCheckTimer = setInterval(async () => {\n for (const adapter of this.config.adapters) {\n const startTime = Date.now();\n try {\n const result = await adapter.healthCheck();\n const responseTime = Date.now() - startTime;\n\n this.updateHealthMetrics(adapter, result.success, responseTime);\n } catch {\n this.updateHealthMetrics(adapter, false, Date.now() - startTime);\n }\n }\n }, this.config.healthCheckInterval);\n }\n\n /**\n * Stop health checks\n */\n private stopHealthChecks(): void {\n if (this.healthCheckTimer) {\n clearInterval(this.healthCheckTimer);\n this.healthCheckTimer = undefined;\n }\n }\n\n /**\n * Get health status of all replicas\n */\n getHealthStatus(): Record<string, ReplicaHealth> {\n const status: Record<string, ReplicaHealth> = {};\n let index = 0;\n\n for (const [, health] of this.replicaHealth.entries()) {\n status[`replica-${index++}`] = health;\n }\n\n return status;\n }\n\n /**\n * Cleanup resources\n */\n dispose(): void {\n this.stopHealthChecks();\n this.replicaHealth.clear();\n }\n}\n","import { SetMetadata } from \"@nestjs/common\";\nimport type { UseReplicaOptions } from \"@plyaz/types\";\n\nexport const USE_REPLICA_KEY = \"use_replica\";\n\n/**\n * Decorator to specify replica usage for database operations.\n *\n * @example\n * ```typescript\n * class UserService {\n * @UseReplica({ strategy: ReplicaStrategy.REPLICA })\n * async getUsers() {\n * // This will use a read replica\n * return this.db.findMany('users');\n * }\n *\n * @UseReplica({ strategy: ReplicaStrategy.PRIMARY })\n * async createUser(user: User) {\n * // This will use primary\n * return this.db.create('users', user);\n * }\n * }\n * ```\n */\nexport function UseReplica(options: UseReplicaOptions = {}): MethodDecorator {\n return (target, propertyKey, descriptor) => {\n SetMetadata(USE_REPLICA_KEY, options)(target, propertyKey, descriptor);\n };\n}\n","import { Redis } from \"ioredis\";\nimport { failure, success } from \"@utils/databaseResultHelpers\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport type { DatabaseResult } from \"@plyaz/types/db\";\nimport { NUMERIX } from \"@plyaz/config\";\n\n/**\n * Redis-based caching service for database query results.\n * Provides automatic serialization/deserialization, TTL management, and pattern-based invalidation.\n *\n * @example\n * ### Basic Usage\n * ```typescript\n * const cache = new RedisCache({\n * url: 'redis://localhost:6379',\n * defaultTTL: 3600 // 1 hour\n * });\n *\n * // Set a value\n * await cache.set('user:123', { id: 123, name: 'John' });\n *\n * // Get a value\n * const result = await cache.get('user:123');\n * if (result.success) {\n * console.log(result.value); // { id: 123, name: 'John' }\n * }\n *\n * // Delete a value\n * await cache.del('user:123');\n * ```\n *\n * @example\n * ### User Profile Caching\n * ```typescript\n * class UserProfileCache {\n * constructor(private cache: RedisCache) {}\n *\n * async getUserProfile(userId: string): Promise<DatabaseResult<UserProfile>> {\n * const cacheKey = `profile:${userId}`;\n *\n * // Try cache first\n * const cached = await this.cache.get<UserProfile>(cacheKey);\n * if (cached.success && cached.value) {\n * return cached;\n * }\n *\n * // Fetch from database\n * const profile = await this.db.findById('profiles', userId);\n *\n * // Cache the result\n * if (profile.success) {\n * await this.cache.set(cacheKey, profile.value, 1800); // 30 minutes\n * }\n *\n * return profile;\n * }\n *\n * async updateUserProfile(userId: string, data: Partial<UserProfile>): Promise<DatabaseResult<UserProfile>> {\n * const updated = await this.db.update('profiles', userId, data);\n *\n * // Invalidate cache on successful update\n * if (updated.success) {\n * await this.cache.del(`profile:${userId}`);\n * // Also invalidate related caches\n * await this.cache.invalidatePattern(`user:${userId}:*`);\n * }\n *\n * return updated;\n * }\n * }\n * ```\n *\n * @example\n * ### Product Catalog Caching\n * ```typescript\n * class ProductCatalogCache {\n * constructor(private cache: RedisCache) {}\n *\n * async getProductsByCategory(categoryId: string): Promise<DatabaseResult<Product[]>> {\n * const cacheKey = `products:category:${categoryId}`;\n *\n * const cached = await this.cache.get<Product[]>(cacheKey);\n * if (cached.success && cached.value) {\n * return cached;\n * }\n *\n * const products = await this.db.findMany('products', {\n * filter: { field: 'categoryId', operator: 'eq', value: categoryId }\n * });\n *\n * // Cache product lists longer (2 hours) as they change less frequently\n * if (products.success) {\n * await this.cache.set(cacheKey, products.value, 7200);\n * }\n *\n * return products;\n * }\n *\n * async updateProductStock(productId: string, quantity: number): Promise<DatabaseResult<void>> {\n * await this.db.update('inventory', productId, { quantity });\n *\n * // Invalidate product cache and related caches\n * await this.cache.del(`product:${productId}`);\n * await this.cache.invalidatePattern(`products:category:*`);\n * await this.cache.invalidatePattern(`inventory:low-stock`);\n * }\n * }\n * ```\n *\n * @example\n * ### Multi-tenant Caching\n * ```typescript\n * class MultiTenantCache {\n * constructor(private cache: RedisCache) {}\n *\n * async getTenantConfig(tenantId: string): Promise<DatabaseResult<TenantConfig>> {\n * const cacheKey = `tenant:${tenantId}:config`;\n *\n * const cached = await this.cache.get<TenantConfig>(cacheKey);\n * if (cached.success && cached.value) {\n * return cached;\n * }\n *\n * const config = await this.db.findById('tenant_configs', tenantId);\n *\n * // Cache configs longer (4 hours) as they rarely change\n * if (config.success) {\n * await this.cache.set(cacheKey, config.value, 14400);\n * }\n *\n * return config;\n * }\n *\n * async updateTenantSettings(tenantId: string): Promise<DatabaseResult<void>> {\n * await this.db.update('tenant_settings', tenantId, { updatedAt: new Date() });\n *\n * // Invalidate all tenant-related caches\n * await this.cache.invalidatePattern(`tenant:${tenantId}:*`);\n * }\n * }\n * ```\n *\n * @example\n * ### Analytics Data Caching\n * ```typescript\n * class AnalyticsCache {\n * constructor(private cache: RedisCache) {}\n *\n * async getDailyStats(date: string): Promise<DatabaseResult<DailyStats>> {\n * const cacheKey = `analytics:daily:${date}`;\n *\n * const cached = await this.cache.get<DailyStats>(cacheKey);\n * if (cached.success && cached.value) {\n * return cached;\n * }\n *\n * // Analytics queries are expensive, cache them longer\n * const stats = await this.db.findById('daily_stats', date);\n *\n * if (stats.success) {\n * // Cache for 6 hours as analytics data doesn't change frequently\n * await this.cache.set(cacheKey, stats.value, 21600);\n * }\n *\n * return stats;\n * }\n *\n * async recordMetric(metric: MetricData): Promise<DatabaseResult<void>> {\n * await this.db.create('metrics', metric);\n *\n * // Invalidate aggregated analytics caches\n * await this.cache.invalidatePattern('analytics:aggregated:*');\n * await this.cache.invalidatePattern('analytics:dashboard:*');\n * }\n * }\n * ```\n *\n * @example\n * ### Session Management\n * ```typescript\n * class SessionCache {\n * constructor(private cache: RedisCache) {}\n *\n * async getUserSession(sessionId: string): Promise<DatabaseResult<Session>> {\n * const cacheKey = `session:${sessionId}`;\n *\n * // Sessions are accessed frequently, cache them but with short TTL\n * const cached = await this.cache.get<Session>(cacheKey);\n * if (cached.success && cached.value) {\n * return cached;\n * }\n *\n * const session = await this.db.findById('sessions', sessionId);\n *\n * if (session.success) {\n * // Cache sessions for 15 minutes\n * await this.cache.set(cacheKey, session.value, 900);\n * }\n *\n * return session;\n * }\n *\n * async invalidateUserSessions(userId: string): Promise<DatabaseResult<void>> {\n * // Invalidate all sessions for a user (e.g., on logout or password change)\n * await this.cache.invalidatePattern(`session:user:${userId}:*`);\n * }\n * }\n * ```\n */\nexport class RedisCache {\n private redis: Redis;\n private defaultTTL: number;\n // Using shared logger instance from @plyaz/logger\n\n /**\n * Creates a new RedisCache instance.\n * @param config Redis configuration\n *\n * @example\n * ```typescript\n * // Basic configuration\n * const cache = new RedisCache({\n * url: 'redis://localhost:6379'\n * });\n *\n * // With custom default TTL\n * const cacheWithCustomTTL = new RedisCache({\n * url: 'redis://localhost:6379',\n * defaultTTL: 1800 // 30 minutes\n * });\n *\n * // Production configuration with options\n * const productionCache = new RedisCache({\n * url: 'redis://redis-cluster.example.com:6379',\n * defaultTTL: 3600,\n * // Additional Redis options can be passed here\n * });\n * ```\n */\n constructor(config: { url: string; defaultTTL?: number }) {\n this.redis = new Redis(config.url);\n this.defaultTTL = config.defaultTTL ?? NUMERIX.THIRTY_SIX_HUNDERD;\n }\n\n /**\n * Retrieves a value from cache by key.\n * Automatically handles JSON deserialization.\n *\n * @param key Cache key\n * @returns DatabaseResult containing cached value or null if not found\n *\n * @example\n * ```typescript\n * // Get user profile\n * const result = await cache.get<UserProfile>('profile:123');\n * if (result.success && result.value) {\n * console.log('User:', result.value.name);\n * } else {\n * console.log('Profile not found or cache error');\n * }\n *\n * // Get product list\n * const products = await cache.get<Product[]>('products:featured');\n * if (products.success && products.value) {\n * products.value.forEach(product => {\n * console.log(product.name, product.price);\n * });\n * }\n * ```\n */\n async get<T extends object>(key: string): Promise<DatabaseResult<T | null>> {\n try {\n const value = await this.redis.get(key);\n if (!value) {\n return success();\n }\n\n const parsed = JSON.parse(value);\n // Validate that parsed value is an object\n if (parsed && typeof parsed === \"object\") {\n return success(parsed as T);\n }\n\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n \"Cache get failed\",\n DATABASE_ERROR_CODES.CACHE_GET_FAILED,\n { context: { source: \"RedisCache.get\", key, cause: error } },\n ),\n );\n }\n }\n\n /**\n * Sets a value in cache with optional TTL.\n * Automatically handles JSON serialization.\n *\n * @param key Cache key\n * @param value Value to cache\n * @param ttl Time to live in seconds (uses default if not specified)\n * @returns DatabaseResult indicating operation success\n *\n * @example\n * ```typescript\n * // Cache with default TTL\n * await cache.set('user:123', { id: 123, name: 'John' });\n *\n * // Cache with custom TTL (5 minutes)\n * await cache.set('session:abc123', sessionData, 300);\n *\n * // Cache with long TTL for static data\n * await cache.set('config:app-settings', appSettings, 86400); // 24 hours\n *\n * // Cache with short TTL for frequently changing data\n * await cache.set('metrics:realtime', realtimeData, 60); // 1 minute\n * ```\n */\n async set<T extends object>(\n key: string,\n value: T,\n ttl?: number,\n ): Promise<DatabaseResult<null>> {\n try {\n const ttlValue = ttl ?? this.defaultTTL;\n await this.redis.set(key, JSON.stringify(value), \"EX\", ttlValue);\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n \"Cache set failed\",\n DATABASE_ERROR_CODES.CACHE_SET_FAILED,\n { context: { source: \"RedisCache.set\", key, cause: error } },\n ),\n );\n }\n }\n\n /**\n * Deletes a value from cache.\n *\n * @param key Cache key\n * @returns DatabaseResult indicating operation success\n *\n * @example\n * ```typescript\n * // Delete specific cache entry\n * await cache.del('user:123');\n *\n * // Delete session on logout\n * await cache.del(`session:${sessionId}`);\n *\n * // Delete cached configuration\n * await cache.del('config:feature-flags');\n * ```\n */\n async del(key: string): Promise<DatabaseResult<null>> {\n try {\n await this.redis.del(key);\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n \"Cache delete failed\",\n DATABASE_ERROR_CODES.CACHE_DELETE_FAILED,\n {\n context: {\n source: \"RedisCache.del\",\n key,\n cause: error,\n },\n },\n ),\n );\n }\n }\n\n /**\n * Invalidates all cache entries matching a pattern.\n * Useful for clearing related cache entries when data changes.\n *\n * @param pattern Redis key pattern (e.g., 'users:*')\n * @returns DatabaseResult indicating operation success\n *\n * @example\n * ```typescript\n * // Invalidate all user-related caches\n * await cache.invalidatePattern('users:*');\n *\n * // Invalidate all caches for a specific category\n * await cache.invalidatePattern('products:category:electronics:*');\n *\n * // Invalidate all session caches\n * await cache.invalidatePattern('session:*');\n *\n * // Invalidate all caches for a tenant\n * await cache.invalidatePattern(`tenant:${tenantId}:*`);\n *\n * // Invalidate all analytics caches\n * await cache.invalidatePattern('analytics:*');\n * ```\n */\n async invalidatePattern(pattern: string): Promise<DatabaseResult<null>> {\n try {\n const keys = await this.redis.keys(pattern);\n if (keys.length > 0) {\n await this.redis.del(...keys);\n }\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n \"Cache invalidate failed\",\n DATABASE_ERROR_CODES.CACHE_INVALIDATE_FAILED,\n {\n context: {\n source: \"RedisCache.invalidatePattern\",\n pattern,\n cause: error,\n },\n },\n ),\n );\n }\n }\n\n /**\n * Generates a cache key for database queries.\n * Creates consistent, URL-safe keys that include table, operation, and parameters.\n *\n * @param table Database table name\n * @param operation Database operation type\n * @param params Query parameters object\n * @returns Generated cache key\n *\n * @example\n * ```typescript\n * // Simple key generation\n * const key = cache.generateKey('users', 'findById', { id: '123' });\n * // Returns: 'db:users:findById:eyJpYXJhbTAiOiIxMjMifQ=='\n *\n * // Complex query key\n * const complexKey = cache.generateKey('products', 'findMany', {\n * filter: { field: 'category', operator: 'eq', value: 'electronics' },\n * sort: [{ field: 'price', direction: 'asc' }],\n * pagination: { limit: 20, offset: 0 }\n * });\n *\n * // User-specific key\n * const userKey = cache.generateKey('orders', 'findMany', {\n * filter: { field: 'userId', operator: 'eq', value: '123' }\n * });\n * ```\n */\n generateKey(\n table: string,\n operation: string,\n params: Record<string, string | number | boolean | null>,\n ): string {\n const paramsStr = JSON.stringify(params || {});\n return `db:${table}:${operation}:${Buffer.from(paramsStr).toString(\"base64\")}`;\n }\n\n /**\n * Performs a health check on the Redis connection.\n * Useful for monitoring and ensuring cache availability.\n *\n * @returns DatabaseResult with boolean indicating if Redis is healthy\n *\n * @example\n * ```typescript\n * // Check Redis health\n * const health = await cache.healthCheck();\n * if (health.success && health.value) {\n * console.log('Redis is healthy');\n * } else {\n * console.log('Redis health check failed:', health.error?.message);\n * // Implement fallback logic or alerting\n * }\n *\n * // Use in health check endpoint\n * app.get('/health', async (req, res) => {\n * const dbHealth = await db.healthCheck();\n * const cacheHealth = await cache.healthCheck();\n *\n * res.json({\n * database: dbHealth.success && dbHealth.value,\n * cache: cacheHealth.success && cacheHealth.value,\n * timestamp: new Date()\n * });\n * });\n * ```\n */\n async healthCheck(): Promise<DatabaseResult<boolean>> {\n try {\n await this.redis.ping();\n return success(true);\n } catch (error) {\n return failure(\n new DatabaseError(\n \"Redis health check failed\",\n DATABASE_ERROR_CODES.CACHE_HEALTH_CHECK_FAILED,\n {\n context: {\n source: \"RedisCache.healthCheck\",\n cause: error,\n },\n },\n ),\n );\n }\n }\n\n /**\n * Closes the Redis connection gracefully.\n * Should be called during application shutdown.\n *\n * @example\n * ```typescript\n * // In your application shutdown logic\n * async function shutdown() {\n * console.log('Shutting down cache...');\n * await cache.close();\n * console.log('Cache connection closed');\n *\n * // Close other connections...\n * process.exit(0);\n * }\n *\n * // Handle graceful shutdown\n * process.on('SIGTERM', shutdown);\n * process.on('SIGINT', shutdown);\n * ```\n */\n async close(): Promise<void> {\n await this.redis.quit();\n }\n}\n","import { isString } from \"@utils/typeGuards\";\nimport type { RedisCache } from \"./RedisCache\";\nimport type { CacheableOptions, DatabaseResult } from \"@plyaz/types/db\";\n\n/**\n * Decorator that caches the result of a method.\n * Automatically generates cache keys and handles TTL.\n *\n * @example\n * ### Basic Usage\n * ```typescript\n * class UserService {\n * constructor(private cache: RedisCache) {}\n *\n * @Cacheable({ ttl: 300 }) // Cache for 5 minutes\n * async getUserById(id: string): Promise<DatabaseResult<User>> {\n * // First call: executes query and caches result\n * // Subsequent calls: returns cached result for 5 minutes\n * return this.db.findById('users', id);\n * }\n * }\n * ```\n *\n * @example\n * ### Custom Cache Key\n * ```typescript\n * class ProductService {\n * constructor(private cache: RedisCache) {}\n *\n * @Cacheable({\n * key: 'featured-products',\n * ttl: 1800 // Cache for 30 minutes\n * })\n * async getFeaturedProducts(): Promise<DatabaseResult<Product[]>> {\n * // Uses custom cache key 'featured-products'\n * return this.db.findMany('products', {\n * filter: { field: 'featured', operator: 'eq', value: true }\n * });\n * }\n * }\n * ```\n *\n * @example\n * ### Conditional Caching\n * ```typescript\n * class OrderService {\n * constructor(private cache: RedisCache) {}\n *\n * @Cacheable({\n * ttl: 600,\n * condition: (result) => result.success && result.value?.length > 0\n * })\n * async getRecentOrders(): Promise<DatabaseResult<Order[]>> {\n * // Only caches successful responses with non-empty results\n * // Prevents caching empty arrays or error responses\n * return this.db.findMany('orders', {\n * sort: [{ field: 'createdAt', direction: 'desc' }],\n * pagination: { limit: 10 }\n * });\n * }\n * }\n * ```\n *\n * @example\n * ### User Profile Caching\n * ```typescript\n * class ProfileService {\n * constructor(private cache: RedisCache) {}\n *\n * @Cacheable({ ttl: 3600 }) // Cache for 1 hour\n * async getUserProfile(userId: string): Promise<DatabaseResult<Profile>> {\n * // User profiles change infrequently, perfect for caching\n * return this.db.findById('profiles', userId);\n * }\n *\n * @CacheEvict({ key: 'user-profile' })\n * async updateProfile(userId: string, data: Partial<Profile>): Promise<DatabaseResult<Profile>> {\n * // When profile is updated, evict the cached version\n * return this.db.update('profiles', userId, data);\n * }\n * }\n * ```\n *\n * @example\n * ### Analytics Data Caching\n * ```typescript\n * class AnalyticsService {\n * constructor(private cache: RedisCache) {}\n *\n * @Cacheable({\n * ttl: 7200, // Cache for 2 hours\n * key: 'daily-stats'\n * })\n * async getDailyStats(date: string): Promise<DatabaseResult<DailyStats>> {\n * // Analytics queries are expensive, cache them longer\n * return this.db.findById('daily_stats', date);\n * }\n * }\n * ```\n */\nexport function Cacheable(options: CacheableOptions = {}): MethodDecorator {\n return (\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n ) => {\n const originalMethod = descriptor.value;\n\n if (!originalMethod || typeof originalMethod !== \"function\") {\n throw new TypeError(\n \"Cacheable decorator can only be applied to methods.\",\n );\n }\n\n descriptor.value = async function (\n this: { cache?: RedisCache },\n ...args: [string, ...Array<string>]\n ): Promise<DatabaseResult<object>> {\n // Check if cache is available on the instance\n const cache = this.cache;\n if (!cache) {\n return originalMethod.apply(this, args);\n }\n\n // Generate cache key\n const table = args[0];\n const operation = String(propertyKey);\n const params = buildParamsObject(args);\n\n const cacheKey =\n options.key ?? cache.generateKey(table, operation, params);\n\n // Try to get from cache with explicit type\n const cachedResult = await cache.get<object>(cacheKey);\n if (cachedResult.success && cachedResult.value !== null) {\n return cachedResult as DatabaseResult<object>;\n }\n\n // Execute original method\n const result = await originalMethod.apply(this, args);\n\n // Cache result if successful and meets condition\n if (\n result.success &&\n (!options.condition || options.condition(result.value))\n ) {\n await cache.set(cacheKey, result.value, options.ttl);\n }\n\n return result as DatabaseResult<object>;\n };\n\n return descriptor;\n };\n}\n\n/**\n * Builds a parameters object from function arguments for cache key generation.\n * Converts all arguments to strings to ensure consistent cache keys.\n *\n * @param args Function arguments (first is table name, rest are parameters)\n * @returns Parameters object with indexed keys for cache key generation\n *\n * @example\n * ### Basic Usage\n * ```typescript\n * const params = buildParamsObject(['users', '123']);\n * // Returns: { param0: '123' }\n * ```\n *\n * @example\n * ### Multiple Parameters\n * ```typescript\n * const params = buildParamsObject(['products', 'electronics', 'active', { limit: 10 }]);\n * // Returns: { param0: 'electronics', param1: 'active', param2: '{\"limit\":10}' }\n * ```\n *\n * @example\n * ### Complex Objects\n * ```typescript\n * const filters = { category: 'books', priceRange: { min: 10, max: 50 } };\n * const params = buildParamsObject(['products', 'search', filters]);\n * // Returns: { param0: 'search', param1: '{\"category\":\"books\",\"priceRange\":{\"min\":10,\"max\":50}}' }\n * ```\n *\n * @example\n * ### Cache Key Generation\n * ```typescript\n * const cacheKey = cache.generateKey('users', 'findById', params);\n * // Results in: 'users:findById:param0-123'\n *\n * const complexKey = cache.generateKey('products', 'search', params);\n * // Results in: 'products:search:param0-electronics_param1-active_param2-{\"limit\":10}'\n * ```\n *\n * @example\n * ### Real-World Usage in Repository\n * ```typescript\n * class UserRepository {\n * async findUsers(filters: UserFilters): Promise<DatabaseResult<User[]>> {\n * const args = ['users', 'find', filters];\n * const params = buildParamsObject(args);\n * const cacheKey = this.cache.generateKey('users', 'find', params);\n *\n * // Check cache first\n * const cached = await this.cache.get(cacheKey);\n * if (cached.success && cached.value) {\n * return cached;\n * }\n *\n * // Execute query and cache result\n * const result = await this.db.findMany('users', { filter: filters });\n * await this.cache.set(cacheKey, result.value, 300);\n * return result;\n * }\n * }\n * ```\n */\nfunction buildParamsObject<T extends Record<string, string>>(\n args: [string, ...Array<string>],\n): T {\n // extract and skip the table name\n const [, ...params] = args;\n const result: Record<string, string> = {};\n\n params.forEach((arg, index) => {\n const key = `param${index}`;\n result[key] = isString(arg) ? arg : JSON.stringify(arg);\n });\n\n return result as T;\n}\n","import type { RedisCache } from \"./RedisCache\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport type { CacheEvictOptions } from \"@plyaz/types\";\nimport { DB_REGEX } from \"@utils/regex\";\nimport { isString } from \"@utils/typeGuards\";\n\n/**\n * Decorator that evicts cache entries when a method is called.\n * Useful for keeping cache in sync with database changes.\n *\n * @example\n * ### Basic User Update\n * ```typescript\n * class UserService {\n * constructor(private cache: RedisCache) {}\n *\n * @CacheEvict({ key: 'user:123' })\n * async updateUser(id: string, data: Partial<User>): Promise<DatabaseResult<User>> {\n * // When user is updated, evict their specific cache entry\n * // This ensures next read gets fresh data\n * return this.db.update('users', id, data);\n * }\n * }\n * ```\n *\n * @example\n * ### User Deletion with Pattern Eviction\n * ```typescript\n * class UserService {\n * constructor(private cache: RedisCache) {}\n *\n * @CacheEvict({ pattern: 'users:*' })\n * async deleteUser(id: string): Promise<DatabaseResult<void>> {\n * // When user is deleted, evict ALL user-related cache entries\n * // This includes user lists, profiles, permissions, etc.\n * return this.db.delete('users', id);\n * }\n * }\n * ```\n *\n * @example\n * ### Product Management with Multiple Eviction Strategies\n * ```typescript\n * class ProductService {\n * constructor(private cache: RedisCache) {}\n *\n * @CacheEvict({ key: (id: string) => `product:${id}` })\n * async updateProduct(id: string, data: Partial<Product>): Promise<DatabaseResult<Product>> {\n * // Evict specific product cache\n * return this.db.update('products', id, data);\n * }\n *\n * @CacheEvict({ pattern: 'products:category:*' })\n * async updateProductCategory(categoryId: string): Promise<DatabaseResult<void>> {\n * // When category is updated, evict all products in that category\n * return this.db.update('categories', categoryId, { updatedAt: new Date() });\n * }\n *\n * @CacheEvict({ pattern: 'products:featured' })\n * async updateFeaturedProducts(): Promise<DatabaseResult<void>> {\n * // Evict featured products cache when featured list changes\n * return this.db.query('REFRESH MATERIALIZED VIEW featured_products');\n * }\n * }\n * ```\n *\n * @example\n * ### Cache Invalidation on Data Changes\n * ```typescript\n * class OrderService {\n * constructor(private cache: RedisCache) {}\n *\n * @CacheEvict({ pattern: 'orders:user:*' })\n * async createOrder(userId: string, orderData: CreateOrderDto): Promise<DatabaseResult<Order>> {\n * // When new order is created, evict user's order history cache\n * return this.db.create('orders', { ...orderData, userId });\n * }\n *\n * @CacheEvict({ pattern: 'orders:stats:*' })\n * async updateOrderStatus(orderId: string, status: string): Promise<DatabaseResult<void>> {\n * // When order status changes, evict order statistics cache\n * return this.db.update('orders', orderId, { status });\n * }\n *\n * @CacheEvict({ allEntries: true })\n * async resetOrderData(): Promise<DatabaseResult<void>> {\n * // Clear all order-related cache during data reset\n * return this.db.query('TRUNCATE orders CASCADE');\n * }\n * }\n * ```\n *\n * @example\n * ### Profile Management with Related Cache Eviction\n * ```typescript\n * class ProfileService {\n * constructor(private cache: RedisCache) {}\n *\n * @CacheEvict({ key: (userId: string) => `profile:${userId}` })\n * async updateProfile(userId: string, data: Partial<Profile>): Promise<DatabaseResult<Profile>> {\n * // Evict user profile cache\n * return this.db.update('profiles', userId, data);\n * }\n *\n * @CacheEvict({ pattern: 'profile:preferences:*' })\n * async updatePreferences(userId: string, preferences: UserPreferences): Promise<DatabaseResult<void>> {\n * // Evict user preferences cache\n * return this.db.update('user_preferences', userId, preferences);\n * }\n *\n * @CacheEvict({ pattern: 'profile:activity:*' })\n * async logUserActivity(userId: string, activity: UserActivity): Promise<DatabaseResult<void>> {\n * // Evict user activity timeline cache\n * return this.db.create('user_activities', { userId, ...activity });\n * }\n * }\n * ```\n *\n * @example\n * ### E-commerce Inventory Management\n * ```typescript\n * class InventoryService {\n * constructor(private cache: RedisCache) {}\n *\n * @CacheEvict({ key: (productId: string) => `inventory:${productId}` })\n * async updateInventory(productId: string, quantity: number): Promise<DatabaseResult<void>> {\n * // Evict specific product inventory cache\n * return this.db.update('inventory', productId, { quantity });\n * }\n *\n * @CacheEvict({ pattern: 'inventory:category:*' })\n * async updateCategoryInventory(categoryId: string): Promise<DatabaseResult<void>> {\n * // Evict all inventory in category when category stock changes\n * return this.db.query('UPDATE inventory SET needs_restock = true WHERE category_id = $1', [categoryId]);\n * }\n *\n * @CacheEvict({ pattern: 'inventory:low-stock' })\n * async checkLowStockProducts(): Promise<DatabaseResult<Product[]>> {\n * // Evict low stock cache when checking (data may have changed)\n * return this.db.findMany('products', {\n * filter: { field: 'stock', operator: 'lt', value: 10 }\n * });\n * }\n * }\n * ```\n *\n * @example\n * ### Content Management System\n * ```typescript\n * class ContentService {\n * constructor(private cache: RedisCache) {}\n *\n * @CacheEvict({ key: (contentId: string) => `content:${contentId}` })\n * async updateContent(contentId: string, data: Partial<Content>): Promise<DatabaseResult<Content>> {\n * // Evict specific content cache\n * return this.db.update('contents', contentId, data);\n * }\n *\n * @CacheEvict({ pattern: 'content:author:*' })\n * async updateAuthorProfile(authorId: string): Promise<DatabaseResult<void>> {\n * // Evict all content by this author when profile changes\n * return this.db.update('authors', authorId, { updatedAt: new Date() });\n * }\n *\n * @CacheEvict({ pattern: 'content:published:*' })\n * async publishContent(contentId: string): Promise<DatabaseResult<void>> {\n * // Evict published content cache when new content is published\n * return this.db.update('contents', contentId, { status: 'published' });\n * }\n *\n * @CacheEvict({ pattern: 'content:tag:*' })\n * async updateContentTags(contentId: string, tags: string[]): Promise<DatabaseResult<void>> {\n * // Evict tag-based content caches when tags change\n * return this.db.update('content_tags', contentId, { tags });\n * }\n * }\n * ```\n *\n * @example\n * ### Dynamic Cache Key Generation\n * ```typescript\n * class CacheService {\n * constructor(private cache: RedisCache) {}\n *\n * @CacheEvict({ key: (userId: string, resourceId: string) => `user:${userId}:resource:${resourceId}` })\n * async updateUserResource(userId: string, resourceId: string, data: object): Promise<DatabaseResult<void>> {\n * // Evict specific user resource cache\n * return this.db.update('user_resources', { userId, resourceId, data });\n * }\n *\n * @CacheEvict({ pattern: (tenantId: string) => `tenant:${tenantId}:*` })\n * async updateTenantSettings(tenantId: string): Promise<DatabaseResult<void>> {\n * // Evict all tenant-specific cache entries\n * return this.db.update('tenants', tenantId, { settings: { updatedAt: new Date() } });\n * }\n * }\n * ```\n */\nfunction validateMethodArgs(args: [string, ...Array<string>]): void {\n if (!args || args.length === 0) {\n throw new DatabaseError(\n \"Method arguments are required\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: {\n source: \"CacheEvict.validateMethodArgs\",\n },\n },\n );\n }\n}\n\nfunction validateMethodResult(result: object): void {\n if (!result || typeof result !== \"object\") {\n throw new DatabaseError(\n \"Method result must be an object\",\n DATABASE_ERROR_CODES.INVALID_RESULT,\n {\n context: { source: \"CacheEvict.validateMethodResult\" },\n },\n );\n }\n}\n\nasync function handleCacheInvalidation(\n cache: RedisCache | undefined,\n options: CacheEvictOptions,\n args: [string, ...Array<string>],\n result: object | undefined,\n): Promise<void> {\n if (\n cache &&\n result &&\n typeof result === \"object\" &&\n \"success\" in result &&\n result.success\n ) {\n try {\n await invalidateCache(cache, options, args);\n } catch (cacheError) {\n console.error(\"Cache invalidation failed:\", cacheError);\n }\n }\n}\n\nexport function CacheEvict(options: CacheEvictOptions = {}): MethodDecorator {\n return (\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n ) => {\n const originalMethod = descriptor.value;\n\n if (!originalMethod || typeof originalMethod !== \"function\") {\n throw new DatabaseError(\n \"CacheEvict decorator can only be applied to methods\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: {\n source: \"CacheEvict.decorator\",\n },\n },\n );\n }\n\n descriptor.value = async function (\n this: { cache?: RedisCache },\n ...args: [string, ...Array<string>]\n ): Promise<object> {\n validateMethodArgs(args);\n\n let result;\n try {\n result = await originalMethod.apply(this, args);\n validateMethodResult(result);\n return result;\n } finally {\n await handleCacheInvalidation(this.cache, options, args, result);\n }\n };\n\n return descriptor;\n };\n}\n\n/**\n * Invalidates cache based on provided options.\n *\n * @param cache Redis cache instance\n * @param options Cache eviction options\n * @param args Method arguments\n *\n * @example\n * ### Evict Specific Key\n * ```typescript\n * // Evict a specific user cache entry\n * await invalidateCache(cache, { key: 'user:123' }, ['users', '123']);\n * ```\n *\n * @example\n * ### Evict by Pattern\n * ```typescript\n * // Evict all user-related cache entries\n * await invalidateCache(cache, { pattern: 'users:*' }, ['users']);\n *\n * // Evict all products in a category\n * await invalidateCache(cache, { pattern: 'products:category:electronics:*' }, ['products']);\n * ```\n *\n * @example\n * ### Evict All Entries\n * ```typescript\n * // Clear the entire cache (use carefully!)\n * await invalidateCache(cache, { allEntries: true }, []);\n * ```\n *\n * @example\n * ### Default Table-based Eviction\n * ```typescript\n * // Evict all cache entries for 'orders' table\n * await invalidateCache(cache, {}, ['orders', '123']);\n * // Results in evicting 'db:orders:*'\n * ```\n *\n * @example\n * ### Complex Eviction Strategy\n * ```typescript\n * class CacheManager {\n * async onUserUpdate(userId: string): Promise<void> {\n * // Evict user profile\n * await invalidateCache(cache, { key: `profile:${userId}` }, []);\n *\n * // Evict user's order history\n * await invalidateCache(cache, { pattern: `orders:user:${userId}:*` }, []);\n *\n * // Evict user permissions\n * await invalidateCache(cache, { pattern: `permissions:user:${userId}:*` }, []);\n * }\n *\n * async onProductUpdate(productId: string): Promise<void> {\n * // Evict product details\n * await invalidateCache(cache, { key: `product:${productId}` }, []);\n *\n * // Evict product category listings\n * await invalidateCache(cache, { pattern: `products:category:*` }, []);\n *\n * // Evict related product recommendations\n * await invalidateCache(cache, { pattern: `recommendations:product:${productId}:*` }, []);\n * }\n * }\n * ```\n *\n * @example\n * ### Bulk Operations\n * ```typescript\n * class BulkCacheManager {\n * async onCategoryUpdate(categoryId: string): Promise<void> {\n * const evictionStrategies = [\n * { pattern: `products:category:${categoryId}:*` },\n * { pattern: `category:${categoryId}:*` },\n * { pattern: `search:category:${categoryId}:*` }\n * ];\n *\n * // Execute all eviction strategies in parallel\n * await Promise.all(\n * evictionStrategies.map(strategy =>\n * invalidateCache(cache, strategy, ['products'])\n * )\n * );\n * }\n *\n * async onTenantUpdate(tenantId: string): Promise<void> {\n * // Evict all tenant-related cache entries\n * await invalidateCache(cache, { pattern: `tenant:${tenantId}:*` }, ['tenants']);\n *\n * // Evict all user sessions for this tenant\n * await invalidateCache(cache, { pattern: `sessions:tenant:${tenantId}:*` }, []);\n *\n * // Evict tenant-specific reports\n * await invalidateCache(cache, { pattern: `reports:tenant:${tenantId}:*` }, []);\n * }\n * }\n * ```\n *\n * @example\n * ### Multi-tenant Cache Invalidation\n * ```typescript\n * class MultiTenantCacheManager {\n * async onUserUpdateInTenant(tenantId: string, userId: string): Promise<void> {\n * // Evict user profile in tenant context\n * await invalidateCache(cache, { key: `tenant:${tenantId}:user:${userId}` }, []);\n *\n * // Evict user's data across all tenants\n * await invalidateCache(cache, { pattern: `user:${userId}:*` }, []);\n *\n * // Evict tenant's user list\n * await invalidateCache(cache, { pattern: `tenant:${tenantId}:users:*` }, []);\n * }\n *\n * async onGlobalDataUpdate(): Promise<void> {\n * // Clear all caches when global data changes\n * await invalidateCache(cache, { allEntries: true }, []);\n * }\n * }\n * ```\n */\nfunction isValidCacheKey(key: string): boolean {\n return isString(key) && DB_REGEX.isValidCacheKey(key);\n}\n\nfunction isValidCachePattern(pattern: string): boolean {\n return isString(pattern) && DB_REGEX.isValidCachePattern(pattern);\n}\n\nfunction isValidTableName(table: string): boolean {\n return isString(table) && DB_REGEX.isValidTableName(table);\n}\n\nasync function evictAllEntries(cache: RedisCache): Promise<void> {\n await cache.invalidatePattern(\"db:*\");\n}\n\nasync function evictByPattern(\n cache: RedisCache,\n pattern: string,\n): Promise<void> {\n if (isValidCachePattern(pattern)) {\n await cache.invalidatePattern(pattern);\n }\n}\n\nasync function evictByKey(cache: RedisCache, key: string): Promise<void> {\n if (isValidCacheKey(key)) {\n await cache.del(key);\n }\n}\n\nasync function evictByTable(cache: RedisCache, table: string): Promise<void> {\n if (isValidTableName(table)) {\n await cache.invalidatePattern(`db:${table}:*`);\n }\n}\n\nasync function invalidateCache(\n cache: RedisCache,\n options: CacheEvictOptions,\n args: [string, ...Array<string>],\n): Promise<void> {\n try {\n if (options.allEntries) {\n await evictAllEntries(cache);\n return;\n }\n\n if (options.pattern) {\n await evictByPattern(cache, options.pattern);\n return;\n }\n\n if (options.key) {\n await evictByKey(cache, options.key);\n return;\n }\n\n const table = args[0];\n if (table) {\n await evictByTable(cache, table);\n }\n } catch (error) {\n throw new DatabaseError(\n \"Cache eviction failed\",\n DATABASE_ERROR_CODES.CACHE_INVALIDATE_FAILED,\n {\n context: { source: \"CacheEvict.invalidateCache\", cause: error },\n },\n );\n }\n}\n","import { Pool } from \"pg\";\nimport type { PoolClient } from \"pg\";\nimport { failure, success } from \"@utils/databaseResultHelpers\";\nimport { logger } from \"@plyaz/logger\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport {\n type DatabaseResult,\n type DatabaseHealthStatus,\n type DynamicPoolConfig,\n type PoolMetrics,\n DB_POOL_EVENTS,\n} from \"@plyaz/types/db\";\nimport { NUMERIX } from \"@plyaz/config\";\nimport { dynamicPoolDefaultConfig } from \"@plyaz/config/db\";\n\n/**\n * Dynamic connection pool that automatically adjusts size based on load.\n * Provides detailed metrics and health monitoring.\n *\n * @example\n * ```typescript\n * const pool = new DynamicPool('postgres://localhost:5432/db', {\n * min: 2,\n * max: 20,\n * scaling: {\n * enabled: true,\n * scaleUpThreshold: 80,\n * scaleDownThreshold: 20,\n * scaleInterval: 30000,\n * maxScale: 5\n * }\n * });\n *\n * // Execute a query\n * const result = await pool.query('SELECT * FROM users');\n *\n * // Get pool metrics\n * const metrics = pool.getMetrics();\n * console.log(`Active connections: ${metrics.activeConnections}`);\n *\n * // Health check\n * const health = await pool.healthCheck();\n * console.log(`Pool healthy: ${health.value?.isHealthy}`);\n * ```\n *\n * @example\n * ### High-Traffic Application\n * ```typescript\n * class DatabasePool {\n * private pool: DynamicPool;\n *\n * constructor() {\n * this.pool = new DynamicPool(process.env.DATABASE_URL, {\n * min: 5,\n * max: 50,\n * scaling: {\n * enabled: true,\n * scaleUpThreshold: 75,\n * scaleDownThreshold: 25,\n * scaleInterval: 15000, // Check every 15 seconds\n * maxScale: 10\n * }\n * });\n * }\n *\n * async query<T>(sql: string, params: object[] = []): Promise<DatabaseResult<T[]>> {\n * return this.pool.query<T>(sql, params);\n * }\n *\n * async getHealthStatus(): Promise<DatabaseResult<HealthStatus>> {\n * return this.pool.healthCheck();\n * }\n *\n * async shutdown(): Promise<void> {\n * await this.pool.end();\n * }\n * }\n * ```\n *\n * @example\n * ### Connection Pool Monitoring\n * ```typescript\n * class PoolMonitor {\n * constructor(private pool: DynamicPool) {}\n *\n * async startMonitoring(): Promise<void> {\n * setInterval(() => {\n * const metrics = this.pool.getMetrics();\n * const utilization = metrics.totalConnections > 0\n * ? (metrics.activeConnections / metrics.totalConnections) * 100\n * : 0;\n *\n * console.log(`Pool Utilization: ${utilization.toFixed(1)}%`);\n * console.log(`Active: ${metrics.activeConnections}, Idle: ${metrics.idleConnections}`);\n * console.log(`Waiting: ${metrics.waitingRequests}`);\n *\n * // Alert if pool is under pressure\n * if (utilization > 90) {\n * console.warn('Pool utilization is very high!');\n * }\n * }, 30000); // Every 30 seconds\n * }\n * }\n * ```\n *\n * @example\n * ### Auto-scaling Configuration\n * ```typescript\n * const poolConfig: DynamicPoolConfig = {\n * min: 3,\n * max: 30,\n * idleTimeoutMillis: 60000, // 1 minute\n * acquireTimeoutMillis: 5000, // 5 seconds\n * scaling: {\n * enabled: true,\n * scaleUpThreshold: 80, // Scale up when 80% utilized\n * scaleDownThreshold: 20, // Scale down when 20% idle\n * scaleInterval: 10000, // Check every 10 seconds\n * maxScale: 5 // Add/remove up to 5 connections at once\n * }\n * };\n *\n * const pool = new DynamicPool('postgres://localhost:5432/myapp', poolConfig);\n * ```\n */\n\nexport class DynamicPool {\n private pool: Pool;\n private config: DynamicPoolConfig;\n private metrics = {\n totalConnections: 0,\n activeConnections: 0,\n idleConnections: 0,\n waitingRequests: 0,\n totalAcquired: 0,\n averageAcquisitionTime: 0,\n } as PoolMetrics;\n private scalingTimer?: ReturnType<typeof setInterval>;\n\n /**\n * Creates a new DynamicPool instance.\n * @param connectionString Database connection string\n * @param config Pool configuration options\n *\n * @example\n * ```typescript\n * // Basic configuration\n * const pool = new DynamicPool('postgres://localhost:5432/db');\n *\n * // Advanced configuration\n * const pool = new DynamicPool('postgres://localhost:5432/db', {\n * min: 5,\n * max: 25,\n * scaling: {\n * enabled: true,\n * scaleUpThreshold: 75,\n * scaleInterval: 20000\n * }\n * });\n * ```\n */\n constructor(\n connectionString: string,\n config: Partial<DynamicPoolConfig> = {},\n ) {\n this.config = {\n ...dynamicPoolDefaultConfig,\n ...config,\n };\n\n this.pool = new Pool({\n connectionString,\n min: this.config.min,\n max: this.config.max,\n idleTimeoutMillis: this.config.idleTimeoutMillis,\n });\n\n this.setupEventListeners();\n\n if (this.config.scaling.enabled) {\n this.startScalingTimer();\n }\n }\n\n /**\n * Sets up event listeners for the connection pool.\n */\n private setupEventListeners(): void {\n this.pool.on(DB_POOL_EVENTS.CONNECT, () => {\n this.metrics.totalConnections++;\n });\n\n this.pool.on(DB_POOL_EVENTS.ACQUIRE, (client: PoolClient) => {\n this.metrics.activeConnections++;\n this.metrics.idleConnections--;\n this.metrics.totalAcquired++;\n (client as PoolClient & { acquiredAt: number }).acquiredAt = Date.now();\n });\n\n // Fixed: Updated the release event listener to match the correct signature\n this.pool.on(\n DB_POOL_EVENTS.RELEASE,\n (err: Error | undefined, client: PoolClient) => {\n if (err) {\n logger.error(`Error on client release: ${err.message}`);\n }\n\n this.metrics.activeConnections--;\n this.metrics.idleConnections++;\n this.metrics.totalReleased++;\n\n // Update average acquisition time\n const acquiredAt = (client as PoolClient & { acquiredAt?: number })\n .acquiredAt;\n if (acquiredAt) {\n const acquisitionTime = Date.now() - acquiredAt;\n this.metrics.averageAcquisitionTime =\n (this.metrics.averageAcquisitionTime *\n (this.metrics.totalReleased - 1) +\n acquisitionTime) /\n this.metrics.totalReleased;\n }\n },\n );\n\n this.pool.on(DB_POOL_EVENTS.REMOVE, () => {\n this.metrics.totalConnections--;\n });\n }\n\n /**\n * Starts the auto-scaling timer.\n */\n private startScalingTimer(): void {\n this.scalingTimer = setInterval(() => {\n this.adjustPoolSize();\n }, this.config.scaling.scaleInterval);\n }\n\n /**\n * Adjusts pool size based on current load.\n */\n private adjustPoolSize(): void {\n const { activeConnections, idleConnections, totalConnections } =\n this.metrics;\n const { min, max, scaling } = this.config;\n\n const utilizationRate =\n totalConnections > 0\n ? (activeConnections / totalConnections) * NUMERIX.HUNDERD\n : 0;\n\n const idleRate =\n totalConnections > 0\n ? (idleConnections / totalConnections) * NUMERIX.HUNDERD\n : 0;\n\n // Scale up if utilization is high\n if (utilizationRate > scaling.scaleUpThreshold && totalConnections < max) {\n const scaleBy = Math.min(scaling.maxScale, max - totalConnections);\n this.adjustPoolCount(totalConnections + scaleBy);\n }\n\n // Scale down if idle rate is high\n if (idleRate > scaling.scaleDownThreshold && totalConnections > min) {\n const scaleBy = Math.min(scaling.maxScale, totalConnections - min);\n this.adjustPoolCount(totalConnections - scaleBy);\n }\n }\n\n /**\n * Adjusts the pool connection count.\n * @param newCount New connection count\n */\n private adjustPoolCount(newCount: number): void {\n // TODO: Implement dynamic pool scaling\n // Note: pg pool doesn't directly support scaling down at runtime\n // Current implementation logs the scaling action for monitoring\n\n const currentCount = this.pool.totalCount;\n const difference = newCount - currentCount;\n\n // Scaling up: pg pool will automatically create new connections as needed\n // when requests exceed current pool size (up to max limit)\n // No direct action needed - pool handles this automatically\n\n // Scaling down: pg pool doesn't support removing idle connections\n // They will naturally expire based on idleTimeoutMillis setting\n // Future implementation could force close idle connections\n\n // Log scaling decision for monitoring and debugging\n // In production, this could emit metrics or trigger alerts\n logger.debug(\n `Scale check: current=${currentCount}, target=${newCount}, difference=${difference}`,\n );\n }\n\n /**\n * Executes a database query with timing and error tracking.\n * @param sql SQL query string\n * @param params Query parameters\n * @returns Query result\n *\n * @example\n * ```typescript\n * // Simple query\n * const result = await pool.query('SELECT * FROM users');\n *\n * // Query with parameters\n * const result = await pool.query(\n * 'SELECT * FROM users WHERE id = $1 AND active = $2',\n * [123, true]\n * );\n *\n * // Query with type safety\n * const users = await pool.query<User>('SELECT * FROM users');\n * ```\n */\n async query<T extends object>(\n sql: string,\n params: object[] = [],\n ): Promise<DatabaseResult<T[]>> {\n const startTime = Date.now();\n try {\n // Validate SQL to prevent injection\n if (!sql || typeof sql !== \"string\") {\n throw new DatabaseError(\n \"Invalid SQL query\",\n DATABASE_ERROR_CODES.INVALID_SQL,\n {\n context: {\n source: \"DynamicPool.query\",\n },\n },\n );\n }\n\n const result = await this.pool.query(sql, params);\n return success(result.rows);\n } catch (error) {\n logger.error(`Database query failed: ${(error as Error).message}`);\n return failure(\n new DatabaseError(\n \"Database query failed\",\n DATABASE_ERROR_CODES.QUERY_FAILED,\n {\n context: {\n source: \"DynamicPool.query\",\n cause: error,\n },\n },\n ),\n );\n } finally {\n // Track slow queries\n const duration = Date.now() - startTime;\n if (duration > NUMERIX.THOUSAND) {\n // 1 second threshold\n const SQL_PREVIEW_LENGTH = 100;\n logger.warn(\n `Slow query detected: ${duration}ms - ${sql.substring(0, SQL_PREVIEW_LENGTH)}`,\n );\n }\n }\n }\n\n /**\n * Performs a health check on the connection pool.\n * @returns Health status with detailed metrics\n *\n * @example\n * ```typescript\n * const health = await pool.healthCheck();\n * if (health.success && health.value?.isHealthy) {\n * console.log('Pool is healthy');\n * console.log(`Response time: ${health.value.responseTime}ms`);\n * } else {\n * console.log('Pool health check failed');\n * }\n * ```\n */\n async healthCheck(): Promise<DatabaseResult<DatabaseHealthStatus>> {\n const startTime = Date.now();\n let client: PoolClient | null = null;\n\n try {\n client = await this.pool.connect();\n await client.query(\"SELECT 1\");\n\n const utilizationRate =\n this.metrics.totalConnections > 0\n ? (this.metrics.activeConnections / this.metrics.totalConnections) *\n NUMERIX.HUNDERD\n : 0;\n\n const responseTime = Date.now() - startTime;\n\n return success({\n isHealthy: true,\n responseTime,\n details: {\n ...this.metrics,\n utilizationRate,\n },\n });\n } catch (error) {\n const responseTime = Date.now() - startTime;\n logger.error(`Pool health check failed: ${(error as Error).message}`);\n\n return success({\n isHealthy: false,\n responseTime,\n details: {\n ...this.metrics,\n error: (error as Error).message,\n },\n });\n } finally {\n if (client) {\n client.release();\n }\n }\n }\n\n /**\n * Gets current pool metrics.\n * @returns Pool performance metrics\n *\n * @example\n * ```typescript\n * const metrics = pool.getMetrics();\n * console.log(`Total connections: ${metrics.totalConnections}`);\n * console.log(`Active connections: ${metrics.activeConnections}`);\n * console.log(`Idle connections: ${metrics.idleConnections}`);\n * console.log(`Average acquisition time: ${metrics.averageAcquisitionTime}ms`);\n *\n * // Calculate utilization rate\n * const utilizationRate = metrics.totalConnections > 0\n * ? (metrics.activeConnections / metrics.totalConnections) * 100\n * : 0;\n * console.log(`Utilization rate: ${utilizationRate.toFixed(1)}%`);\n * ```\n */\n getMetrics(): PoolMetrics {\n return { ...this.metrics };\n }\n\n /**\n * Closes all connections in the pool.\n *\n * @example\n * ```typescript\n * // Graceful shutdown\n * async function shutdown() {\n * console.log('Closing database connections...');\n * await pool.end();\n * console.log('Database connections closed');\n * }\n *\n * // Handle process signals\n * process.on('SIGTERM', shutdown);\n * process.on('SIGINT', shutdown);\n * ```\n */\n async end(): Promise<void> {\n try {\n if (this.scalingTimer) {\n clearInterval(this.scalingTimer);\n this.scalingTimer = undefined;\n }\n await this.pool.end();\n } catch (error) {\n logger.error(`Error closing pool: ${(error as Error).message}`);\n throw new DatabaseError(\n \"Failed to close connection pool\",\n DATABASE_ERROR_CODES.DISCONNECT_FAILED,\n {\n context: {\n source: \"DynamicPool.end\",\n cause: error,\n },\n },\n );\n }\n }\n}\n","import { NUMERIX } from \"@plyaz/config\";\nimport { logger } from \"@plyaz/logger\";\nimport type { PoolMetrics, QueryMetrics } from \"@plyaz/types\";\nimport { EventEmitter } from \"events\";\nimport { DB_REGEX } from \"@utils/regex\";\n\n/**\n * Collects and analyzes database performance metrics.\n * Provides insights into query performance, pool usage, and potential issues.\n *\n * @example\n * ```typescript\n * const collector = new MetricsCollector();\n *\n * // Record a query metric\n * collector.recordQuery({\n * query: 'SELECT * FROM users WHERE id = $1',\n * duration: 45,\n * timestamp: new Date(),\n * success: true,\n * table: 'users',\n * operation: 'findById'\n * });\n *\n * // Get top slow queries\n * const slowQueries = collector.getTopSlowQueries(10);\n *\n * // Detect N+1 queries\n * const nPlusOneQueries = collector.detectNPlusOneQueries();\n *\n * // Get query frequency\n * const frequency = collector.getQueryFrequency();\n * ```\n */\nexport class MetricsCollector extends EventEmitter {\n private queryMetrics: QueryMetrics[] = [];\n private poolMetrics: PoolMetrics[] = [];\n private alerts: string[] = [];\n private readonly logger = logger;\n\n private readonly SLOW_QUERY_THRESHOLD = 1000; // 1 second\n private readonly POOL_EXHAUSTION_THRESHOLD = 90; // 90%\n private readonly REPLICA_LAG_THRESHOLD = 5000; // 5 seconds\n private readonly DISK_SPACE_THRESHOLD = 20; // 20%\n\n /**\n * Records query execution metrics.\n * @param metrics Query execution metrics\n */\n recordQuery(metrics: QueryMetrics): void {\n this.queryMetrics.push(metrics);\n\n // Keep only last 1000 metrics\n if (this.queryMetrics.length > NUMERIX.THOUSAND) {\n this.queryMetrics = this.queryMetrics.slice(-NUMERIX.THOUSAND);\n }\n\n // Check for slow queries\n if (metrics.duration > this.SLOW_QUERY_THRESHOLD) {\n this.emitAlert(\n `Slow query detected: ${metrics.query} took ${metrics.duration}ms`,\n );\n }\n\n this.emit(\"queryRecorded\", metrics);\n }\n\n /**\n * Records connection pool metrics.\n * @param metrics Pool performance metrics\n */\n recordPoolMetrics(metrics: PoolMetrics): void {\n this.poolMetrics.push({\n ...metrics,\n timestamp: new Date(),\n } as PoolMetrics & { timestamp: Date });\n\n // Keep only last 100 metrics\n if (this.poolMetrics.length > NUMERIX.HUNDERD) {\n this.poolMetrics = this.poolMetrics.slice(-NUMERIX.HUNDERD);\n }\n\n // Check for pool exhaustion\n const utilizationRate =\n metrics.totalConnections > 0\n ? (metrics.activeConnections / metrics.totalConnections) *\n NUMERIX.HUNDERD\n : 0;\n\n if (utilizationRate > this.POOL_EXHAUSTION_THRESHOLD) {\n this.emitAlert(\n `Pool exhaustion detected: ${utilizationRate.toFixed(1)}% utilization`,\n );\n }\n\n this.emit(\"poolMetricsRecorded\", metrics);\n }\n\n /**\n * Gets the top slow queries.\n * @param limit Number of queries to return\n * @returns Array of slowest queries\n */\n getTopSlowQueries(limit: number = 10): QueryMetrics[] {\n return [...this.queryMetrics]\n .filter((m) => m.duration > this.SLOW_QUERY_THRESHOLD)\n .sort((a, b) => b.duration - a.duration)\n .slice(0, limit);\n }\n\n /**\n * Gets query frequency statistics.\n * @returns Object mapping normalized queries to frequency counts\n */\n getQueryFrequency(): Record<string, number> {\n const frequency: Record<string, number> = {};\n\n this.queryMetrics.forEach((metrics) => {\n const normalizedQuery = this.normalizeQuery(metrics.query);\n frequency[normalizedQuery] = (frequency[normalizedQuery] || 0) + 1;\n });\n\n return frequency;\n }\n\n /**\n * Detects potential N+1 query patterns.\n * @returns Array of suspicious queries with their execution counts\n */\n detectNPlusOneQueries(): { query: string; count: number }[] {\n const frequency = this.getQueryFrequency();\n const suspiciousQueries: { query: string; count: number }[] = [];\n\n Object.entries(frequency).forEach(([query, count]) => {\n if (count > NUMERIX.TEN && query.includes(\"WHERE id =\")) {\n suspiciousQueries.push({ query, count });\n }\n });\n\n return suspiciousQueries.sort((a, b) => b.count - a.count);\n }\n\n /**\n * Normalizes a query for frequency analysis.\n * @param query Original SQL query\n * @returns Normalized query string\n */\n private normalizeQuery(query: string): string {\n // Remove specific values to normalize similar queries\n return DB_REGEX.normalizeSqlQuery(query);\n }\n\n /**\n * Emits an alert event.\n * @param message Alert message\n */\n private emitAlert(message: string): void {\n this.alerts.push(message);\n\n this.emit(\"alert\", {\n message,\n timestamp: new Date(),\n severity: \"warning\",\n });\n }\n}\n","import { EventEmitter } from \"events\";\nimport { logger } from \"@plyaz/logger\";\nimport { NUMERIX } from \"@plyaz/config\";\nimport type { Alert, AlertRule, PoolMetrics, QueryMetrics } from \"@plyaz/types\";\nimport { ALERT_RULE_ID, ALERT_SEVERITY, ALERT_SOURCE } from \"@plyaz/types\";\n\n/**\n * Manages database alerts with configurable rules and automatic resolution.\n * Provides real-time alerting for various database issues.\n *\n * @example\n * ```typescript\n * const alertManager = new AlertManager();\n *\n * // Add custom alert rule\n * alertManager.addRule({\n * id: 'high-error-rate',\n * condition: (metrics) => (metrics.errorRate as number) > 5,\n * message: (metrics) => `High error rate: ${metrics.errorRate}%`,\n * severity: 'error',\n * source: 'database'\n * });\n *\n * // Evaluate metrics against rules\n * const metrics = { errorRate: 7.2, poolUtilization: 85 };\n * alertManager.evaluate(metrics);\n *\n * // Get active alerts\n * const activeAlerts = alertManager.getActiveAlerts();\n *\n * // Resolve an alert\n * alertManager.resolveAlert('alert-id');\n * ```\n */\nexport class AlertManager extends EventEmitter {\n private alerts: Map<string, Alert> = new Map();\n private alertRules: AlertRule[] = [];\n private readonly logger = logger;\n\n constructor() {\n super();\n this.setupDefaultRules();\n }\n\n /**\n * Sets up default alert rules for common database issues.\n */\n private setupDefaultRules(): void {\n // Pool exhaustion alert\n this.addRule({\n id: ALERT_RULE_ID.POOL_EXHAUSTION,\n condition: (metrics) => {\n const poolMetrics = metrics.pool as PoolMetrics | undefined;\n if (!poolMetrics) return false;\n\n const utilizationRate =\n poolMetrics.totalConnections > 0\n ? (poolMetrics.activeConnections / poolMetrics.totalConnections) *\n NUMERIX.HUNDERD\n : 0;\n return utilizationRate > NUMERIX.NINETY;\n },\n message: (metrics) => {\n const poolMetrics = metrics.pool as PoolMetrics;\n const utilizationRate =\n poolMetrics.totalConnections > 0\n ? (poolMetrics.activeConnections / poolMetrics.totalConnections) *\n NUMERIX.HUNDERD\n : 0;\n return `Pool exhaustion: ${utilizationRate.toFixed(1)}% utilization`;\n },\n severity: ALERT_SEVERITY.CRITICAL,\n source: ALERT_SOURCE.POOL,\n });\n\n // Slow query alert - Fixed to always return boolean\n this.addRule({\n id: ALERT_RULE_ID.SLOW_QUERY,\n condition: (metrics) => {\n const queryMetrics = metrics.query as QueryMetrics | undefined;\n // Fixed: Explicitly return boolean instead of boolean | undefined\n return (\n queryMetrics !== undefined && queryMetrics.duration > NUMERIX.THOUSAND\n );\n },\n message: (metrics) => {\n const queryMetrics = metrics.query as QueryMetrics;\n return `Slow query: ${queryMetrics.query} took ${queryMetrics.duration}ms`;\n },\n severity: ALERT_SEVERITY.WARNING,\n source: ALERT_SOURCE.DATABASE,\n });\n\n // Replica lag alert - Fixed to always return boolean\n this.addRule({\n id: ALERT_RULE_ID.REPLICA_LAG,\n condition: (metrics) => {\n const replicaMetrics = metrics.replica as { lag: number } | undefined;\n // Fixed: Explicitly return boolean instead of boolean | undefined\n return (\n replicaMetrics !== undefined &&\n replicaMetrics.lag > NUMERIX.FIVE_THOUSAND\n );\n },\n message: (metrics) => {\n const replicaMetrics = metrics.replica as { lag: number };\n return `Replica lag: ${replicaMetrics.lag}ms`;\n },\n severity: ALERT_SEVERITY.WARNING,\n source: ALERT_SOURCE.REPLICA,\n });\n }\n\n /**\n * Adds a custom alert rule.\n * @param rule Alert rule definition\n */\n addRule(rule: AlertRule): void {\n this.alertRules.push(rule);\n }\n\n /**\n * Evaluates metrics against all alert rules.\n * @param metrics Database and pool metrics\n */\n evaluate(metrics: Record<string, object>): void {\n this.alertRules.forEach((rule) => {\n if (rule.condition(metrics)) {\n this.triggerAlert(rule, metrics);\n }\n });\n }\n\n /**\n * Triggers an alert based on a rule.\n * @param rule Alert rule that was triggered\n * @param metrics Current metrics\n */\n private triggerAlert(rule: AlertRule, metrics: Record<string, object>): void {\n const alertId = `${rule.id}-${Date.now()}`;\n\n // Check if similar alert is already active\n const existingAlert = Array.from(this.alerts.values()).find(\n (alert) => !alert.resolved && alert.id.startsWith(rule.id),\n );\n\n if (existingAlert) {\n return; // Don't duplicate active alerts\n }\n\n const alert: Alert = {\n id: alertId,\n message: rule.message(metrics),\n severity: rule.severity,\n timestamp: new Date(),\n resolved: false,\n source: rule.source,\n };\n\n this.alerts.set(alertId, alert);\n this.emit(\"alert\", alert);\n\n // Database alert handled - using DatabaseError for proper error handling\n }\n\n /**\n * Marks an alert as resolved.\n * @param alertId ID of the alert to resolve\n */\n resolveAlert(alertId: string): void {\n const alert = this.alerts.get(alertId);\n if (alert && !alert.resolved) {\n alert.resolved = true;\n alert.resolvedAt = new Date();\n this.emit(\"alertResolved\", alert);\n }\n }\n\n /**\n * Gets all currently active (unresolved) alerts.\n * @returns Array of active alerts\n */\n getActiveAlerts(): Alert[] {\n return Array.from(this.alerts.values()).filter((alert) => !alert.resolved);\n }\n\n /**\n * Gets all alerts (both active and resolved).\n * @returns Array of all alerts\n */\n getAllAlerts(): Alert[] {\n return Array.from(this.alerts.values());\n }\n}\n","import { exec } from \"child_process\";\nimport { promisify } from \"util\";\nimport {\n readFileSync,\n existsSync,\n mkdirSync,\n readdirSync,\n unlinkSync,\n} from \"fs\";\nimport { join } from \"path\";\nimport { failure, success } from \"@utils/databaseResultHelpers\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport { logger } from \"@plyaz/logger\";\nimport type { BackupConfig, BackupInfo, DatabaseResult } from \"@plyaz/types/db\";\nimport { NUMERIX } from \"@plyaz/config\";\nimport { isString } from \"@utils/typeGuards\";\nimport { DB_REGEX } from \"@utils/regex\";\n\nconst execAsync = promisify(exec);\n\n/**\n * Manages database backups with compression, encryption, and cloud storage.\n * Provides automated scheduling and retention management.\n *\n * @example\n * ```typescript\n * const config = {\n * connectionString: 'postgres://user:pass@localhost:5432/db',\n * backupDir: './backups',\n * retentionDays: 30,\n * compression: true,\n * encryption: {\n * enabled: true,\n * key: 'encryption-key'\n * },\n * s3: {\n * enabled: true,\n * bucket: 'my-backup-bucket',\n * region: 'us-east-1',\n * accessKey: 'aws-access-key',\n * secretKey: 'aws-secret-key'\n * }\n * };\n *\n * const backupService = new BackupService(config);\n *\n * // Create a backup\n * const backup = await backupService.createBackup();\n * console.log(`Backup created: ${backup.value.filename}`);\n *\n * // List all backups\n * const backups = await backupService.listBackups();\n *\n * // Restore from backup\n * await backupService.restoreBackup(backup.value.id);\n *\n * // Clean up expired backups\n * await backupService.cleanupExpiredBackups();\n * ```\n */\nexport class BackupService {\n private config: BackupConfig;\n private backups: Map<string, BackupInfo> = new Map();\n\n /**\n * Creates a new BackupService instance.\n * @param config Backup configuration\n */\n constructor(config: BackupConfig) {\n this.config = config;\n logger.info(\n `Initializing BackupService - backupDir: ${config.backupDir}, retentionDays: ${config.retentionDays}`,\n );\n this.ensureBackupDir();\n this.loadExistingBackups();\n\n if (config.schedule) {\n this.scheduleBackups();\n }\n logger.info(\"BackupService initialized successfully\");\n }\n\n /**\n * Creates a new database backup.\n * @returns Information about the created backup\n */\n // I need to disable these ESLint rules because this function handles a complete\n // backup process (validation, creation, compression, encryption, upload) in sequence.\n // eslint-disable-next-line complexity, max-lines-per-function\n async createBackup(): Promise<DatabaseResult<BackupInfo>> {\n try {\n // Validate backup directory\n if (!this.isValidPath(this.config.backupDir)) {\n throw new DatabaseError(\n \"Invalid backup directory path\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n { context: { source: \"BackupService.createBackup\" } },\n );\n }\n\n const timestamp = DB_REGEX.createSafeTimestamp(new Date().toISOString());\n const filename = `backup-${timestamp}.sql`;\n const filepath = join(this.config.backupDir, filename);\n\n // Validate final filepath\n if (\n !this.isValidPath(filepath) ||\n !filepath.startsWith(this.config.backupDir)\n ) {\n throw new DatabaseError(\n \"Invalid backup file path\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n { context: { source: \"BackupService.createBackup\" } },\n );\n }\n\n logger.info(`Starting database backup - filename: ${filename}`);\n\n // Create backup using pg_dump with proper escaping\n const { stderr } = await execAsync(\n `pg_dump \"${this.escapeShellArg(this.config.connectionString)}\" > \"${this.escapeShellArg(filepath)}\"`,\n );\n\n if (stderr) {\n logger.error(`Backup creation failed - filename: ${filename}`);\n throw new DatabaseError(\n \"Database backup creation failed\",\n DATABASE_ERROR_CODES.CREATE_FAILED,\n { context: { source: \"BackupService.createBackup\", cause: stderr } },\n );\n }\n\n logger.info(\n `Database backup created successfully - filename: ${filename}`,\n );\n\n // Compress if enabled\n if (this.config.compression) {\n logger.info(\"Compressing backup file\");\n await this.compressFile(filepath);\n logger.info(\"Backup file compressed successfully\");\n }\n\n // Encrypt if enabled\n if (this.config.encryption?.enabled) {\n logger.info(\"Encrypting backup file\");\n await this.encryptFile(filepath);\n logger.info(\"Backup file encrypted successfully\");\n }\n\n let finalFilepath = filepath;\n if (this.config.compression) {\n finalFilepath = `${filepath}.gz`;\n }\n if (this.config.encryption?.enabled) {\n finalFilepath = `${finalFilepath}.enc`;\n }\n\n if (!existsSync(finalFilepath)) {\n throw new DatabaseError(\n \"Backup file was not created\",\n DATABASE_ERROR_CODES.CREATE_FAILED,\n { context: { source: \"BackupService.createBackup\" } },\n );\n }\n\n const backupInfo: BackupInfo = {\n id: this.generateBackupId(),\n filename: this.config.compression ? `${filename}.gz` : filename,\n size: this.getFileSize(finalFilepath),\n createdAt: new Date(),\n expiresAt: new Date(\n Date.now() +\n this.config.retentionDays *\n NUMERIX.TWENTY_FOUR *\n NUMERIX.SIXTY *\n NUMERIX.SIXTY *\n NUMERIX.THOUSAND,\n ),\n status: \"created\",\n location: \"local\",\n };\n\n this.backups.set(backupInfo.id, backupInfo);\n\n // Upload to S3 if enabled\n if (this.config.s3?.enabled) {\n logger.info(`Uploading backup to S3 - backupId: ${backupInfo.id}`);\n await this.uploadToS3(backupInfo);\n logger.info(\"Backup uploaded to S3 successfully\");\n }\n\n logger.info(\n `Backup process completed successfully - backupId: ${backupInfo.id}`,\n );\n return success(backupInfo);\n } catch (error) {\n logger.error(\n `Backup creation failed - error: ${(error as Error).message}`,\n );\n return failure(\n error instanceof DatabaseError\n ? error\n : new DatabaseError(\n \"Backup creation failed\",\n DATABASE_ERROR_CODES.CREATE_FAILED,\n {\n context: { source: \"BackupService.createBackup\", cause: error },\n },\n ),\n );\n }\n }\n\n /**\n * Restores database from a backup.\n * @param backupId ID of the backup to restore\n * @returns Operation result\n */\n // eslint-disable-next-line complexity\n async restoreBackup(backupId: string): Promise<DatabaseResult<null>> {\n try {\n if (!isString(backupId)) {\n return failure(\n new DatabaseError(\n \"Invalid backup ID\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n { context: { source: \"BackupService.restoreBackup\" } },\n ),\n );\n }\n\n logger.info(`Starting backup restore - backupId: ${backupId}`);\n const backup = this.backups.get(backupId);\n if (!backup) {\n logger.error(`Backup not found for restore - backupId: ${backupId}`);\n return failure(\n new DatabaseError(\n \"Backup not found\",\n DATABASE_ERROR_CODES.RECORD_NOT_FOUND,\n { context: { source: \"BackupService.restoreBackup\", backupId } },\n ),\n );\n }\n\n let filepath = join(this.config.backupDir, backup.filename);\n\n // Download from S3 if needed\n if (backup.location === \"s3\" && this.config.s3?.enabled) {\n try {\n filepath = await this.downloadFromS3(backup);\n } catch (error) {\n throw new DatabaseError(\n \"Failed to download backup from S3\",\n DATABASE_ERROR_CODES.FETCH_FAILED,\n {\n context: { source: \"BackupService.restoreBackup\", cause: error },\n },\n );\n }\n }\n\n // Validate file exists before processing\n if (!existsSync(filepath)) {\n throw new DatabaseError(\n \"Backup file not found\",\n DATABASE_ERROR_CODES.RECORD_NOT_FOUND,\n { context: { source: \"BackupService.restoreBackup\", filepath } },\n );\n }\n\n // Decrypt if needed\n if (this.config.encryption?.enabled) {\n await this.decryptFile(filepath);\n }\n\n // Decompress if needed\n if (this.config.compression) {\n await this.decompressFile(filepath);\n filepath = filepath.replace(\".gz\", \"\");\n }\n\n // Validate filepath before restore\n if (!this.isValidPath(filepath)) {\n throw new DatabaseError(\n \"Invalid file path for restore\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n { context: { source: \"BackupService.restoreBackup\", filepath } },\n );\n }\n\n // Restore using psql\n const { stderr } = await execAsync(\n `psql \"${this.escapeShellArg(this.config.connectionString)}\" < \"${this.escapeShellArg(filepath)}\"`,\n );\n\n if (stderr) {\n logger.error(`Database restore failed - backupId: ${backupId}`);\n throw new DatabaseError(\n \"Database restore failed\",\n DATABASE_ERROR_CODES.RESTORE_FAILED,\n { context: { source: \"BackupService.restoreBackup\", cause: stderr } },\n );\n }\n\n logger.info(\n `Database restore completed successfully - backupId: ${backupId}`,\n );\n return success();\n } catch (error) {\n logger.error(`Backup restore failed - backupId: ${backupId}`);\n return failure(\n error instanceof DatabaseError\n ? error\n : new DatabaseError(\n \"Backup restore failed\",\n DATABASE_ERROR_CODES.UPDATE_FAILED,\n {\n context: {\n source: \"BackupService.restoreBackup\",\n cause: error,\n },\n },\n ),\n );\n }\n }\n\n /**\n * Lists all available backups.\n * @returns Array of backup information\n */\n async listBackups(): Promise<DatabaseResult<BackupInfo[]>> {\n try {\n const backups = Array.from(this.backups.values());\n return success(\n backups.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime()),\n );\n } catch (error) {\n return failure(\n new DatabaseError(\n \"Failed to list backups\",\n DATABASE_ERROR_CODES.QUERY_FAILED,\n { context: { source: \"BackupService.listBackups\", cause: error } },\n ),\n );\n }\n }\n\n /**\n * Creates a scheduled backup.\n * @returns Information about the created backup\n */\n async scheduleBackup(): Promise<DatabaseResult<BackupInfo>> {\n return this.createBackup();\n }\n\n /**\n * Removes expired backups from storage.\n * @returns Operation result\n */\n async cleanupExpiredBackups(): Promise<DatabaseResult<null>> {\n try {\n const now = new Date();\n const expiredBackups = Array.from(this.backups.values()).filter(\n (backup) => backup.expiresAt < now,\n );\n\n logger.info(\n `Starting cleanup of expired backups - expiredCount: ${expiredBackups.length}`,\n );\n\n for (const backup of expiredBackups) {\n logger.info(\n `Deleting expired backup - backupId: ${backup.id}, filename: ${backup.filename}`,\n );\n await this.deleteBackup(backup.id);\n }\n\n logger.info(\n `Expired backups cleanup completed - deletedCount: ${expiredBackups.length}`,\n );\n return success();\n } catch (error) {\n logger.error(\"Backup cleanup failed\");\n return failure(\n new DatabaseError(\n \"Backup cleanup failed\",\n DATABASE_ERROR_CODES.DELETE_FAILED,\n {\n context: {\n source: \"BackupService.cleanupExpiredBackups\",\n cause: error,\n },\n },\n ),\n );\n }\n }\n\n /**\n * Deletes a specific backup.\n * @param backupId ID of the backup to delete\n */\n private async deleteBackup(backupId: string): Promise<void> {\n const backup = this.backups.get(backupId);\n if (!backup) return;\n\n const filepath = join(this.config.backupDir, backup.filename);\n\n // Delete local file\n if (existsSync(filepath)) {\n unlinkSync(filepath);\n }\n\n // Delete from S3 if needed\n if (backup.location === \"s3\" && this.config.s3?.enabled) {\n await this.deleteFromS3(backup);\n }\n\n this.backups.delete(backupId);\n }\n\n /**\n * Ensures backup directory exists.\n */\n private ensureBackupDir(): void {\n if (!existsSync(this.config.backupDir)) {\n logger.info(\n `Creating backup directory - backupDir: ${this.config.backupDir}`,\n );\n mkdirSync(this.config.backupDir, { recursive: true });\n logger.info(\"Backup directory created successfully\");\n }\n }\n\n /**\n * Loads existing backups from the backup directory.\n */\n private loadExistingBackups(): void {\n if (!existsSync(this.config.backupDir)) return;\n\n const files = readdirSync(this.config.backupDir);\n logger.info(\n `Loading existing backups - backupDir: ${this.config.backupDir}, fileCount: ${files.length}`,\n );\n\n files.forEach((file) => {\n const filepath = join(this.config.backupDir, file);\n const stats = readFileSync(filepath);\n\n const backup: BackupInfo = {\n id: this.generateBackupId(),\n filename: file,\n size: stats.byteLength,\n createdAt: new Date(),\n expiresAt: new Date(\n Date.now() +\n this.config.retentionDays *\n NUMERIX.TWENTY_FOUR *\n NUMERIX.SIXTY *\n NUMERIX.SIXTY *\n NUMERIX.THOUSAND,\n ),\n status: \"created\",\n location: \"local\",\n };\n\n this.backups.set(backup.id, backup);\n });\n\n logger.info(\n `Existing backups loaded successfully -loadedCount ${this.backups.size}`,\n );\n }\n\n /**\n * Generates a unique backup ID.\n * @returns Unique backup identifier\n */\n private generateBackupId(): string {\n return `backup-${Date.now()}-${Math.random()\n .toString(NUMERIX.THIRTY_SIX)\n .substring(NUMERIX.TWO, NUMERIX.NINE + NUMERIX.TWO)}`;\n }\n\n /**\n * Gets file size in bytes.\n * @param filepath Path to the file\n * @returns File size in bytes\n */\n private getFileSize(filepath: string): number {\n return readFileSync(filepath).byteLength;\n }\n\n /**\n * Compresses a file using gzip.\n * @param filepath Path to the file to compress\n */\n private async compressFile(filepath: string): Promise<void> {\n if (!this.isValidPath(filepath)) {\n throw new DatabaseError(\n \"Invalid file path for compression\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n { context: { source: \"BackupService.compressFile\", filepath } },\n );\n }\n await execAsync(`gzip \"${this.escapeShellArg(filepath)}\"`);\n }\n\n /**\n * Decompresses a gzipped file.\n * @param filepath Path to the gzipped file\n */\n private async decompressFile(filepath: string): Promise<void> {\n if (!this.isValidPath(filepath)) {\n throw new DatabaseError(\n \"Invalid file path for decompression\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n { context: { source: \"BackupService.decompressFile\", filepath } },\n );\n }\n await execAsync(`gunzip \"${this.escapeShellArg(filepath)}\"`);\n }\n\n /**\n * Encrypts a file using OpenSSL.\n * @param filepath Path to the file to encrypt\n */\n private async encryptFile(filepath: string): Promise<void> {\n if (!this.config.encryption?.enabled) return;\n\n if (!this.isValidPath(filepath)) {\n throw new DatabaseError(\n \"Invalid file path for encryption\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n { context: { source: \"BackupService.encryptFile\", filepath } },\n );\n }\n\n const outputPath = `${filepath}.enc`;\n await execAsync(\n `openssl enc -aes-256-cbc -salt -in \"${this.escapeShellArg(filepath)}\" -out \"${this.escapeShellArg(outputPath)}\" -pass pass:\"${this.escapeShellArg(this.config.encryption.key)}\"`,\n );\n unlinkSync(filepath);\n }\n\n /**\n * Decrypts a file using OpenSSL.\n * @param filepath Path to the encrypted file\n */\n private async decryptFile(filepath: string): Promise<void> {\n // TODO: Implement proper encryption/decryption with error handling\n // Current implementation uses OpenSSL command line tool\n if (!this.config.encryption?.enabled) return;\n\n try {\n // Decrypt the file using AES-256-CBC\n const outputPath = filepath.replace(\".enc\", \"\");\n if (!this.isValidPath(filepath) || !this.isValidPath(outputPath)) {\n throw new DatabaseError(\n \"Invalid file path for decryption\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n { context: { source: \"BackupService.decryptFile\", filepath } },\n );\n }\n\n await execAsync(\n `openssl enc -aes-256-cbc -d -in \"${this.escapeShellArg(filepath)}\" -out \"${this.escapeShellArg(outputPath)}\" -pass pass:\"${this.escapeShellArg(this.config.encryption.key)}\"`,\n );\n\n // Remove the encrypted file after successful decryption\n if (existsSync(filepath)) {\n unlinkSync(filepath);\n }\n } catch (error) {\n throw new DatabaseError(\n \"Failed to decrypt file\",\n DATABASE_ERROR_CODES.DECRYPTION_FAILED,\n {\n context: {\n source: \"BackupService.decryptFile\",\n filepath,\n cause: error,\n },\n },\n );\n }\n }\n\n /**\n * Uploads a backup to S3.\n * @param backup Backup information\n */\n private async uploadToS3(backup: BackupInfo): Promise<void> {\n if (!this.config.s3?.enabled) return;\n\n try {\n if (!backup?.filename) {\n throw new DatabaseError(\n \"Invalid backup information\",\n DATABASE_ERROR_CODES.INVALID_BACKUP_INFO,\n { context: { source: \"BackupService.uploadToS3\" } },\n );\n }\n\n backup.status = \"uploading\";\n\n // Validate backup file exists before upload\n const localPath = join(this.config.backupDir, backup.filename);\n if (!existsSync(localPath)) {\n throw new DatabaseError(\n \"Backup file not found for upload\",\n DATABASE_ERROR_CODES.BACKUP_FILE_NOT_FOUND,\n { context: { source: \"BackupService.uploadToS3\", localPath } },\n );\n }\n\n // Placeholder: Mark as uploaded\n backup.status = \"uploaded\";\n backup.location = \"s3\";\n } catch (error) {\n backup.status = \"failed\";\n throw new DatabaseError(\n \"Failed to upload backup to S3\",\n DATABASE_ERROR_CODES.S3_UPLOAD_FAILED,\n { context: { source: \"BackupService.uploadToS3\", cause: error } },\n );\n }\n }\n\n /**\n * Downloads a backup from S3.\n * @param backup Backup information\n * @returns Local path to downloaded file\n */\n private async downloadFromS3(backup: BackupInfo): Promise<string> {\n // TODO: Implement AWS S3 download using AWS SDK v3\n // Current implementation is a placeholder for development\n if (!this.config.s3?.enabled) {\n throw new DatabaseError(\n \"S3 is not configured\",\n DATABASE_ERROR_CODES.S3_NOT_CONFIGURED,\n { context: { source: \"BackupService.downloadFromS3\" } },\n );\n }\n\n try {\n const localPath = join(this.config.backupDir, backup.filename);\n\n // In real implementation:\n // 1. Initialize S3 client with credentials\n // 2. Download file from S3 bucket\n // 3. Save to local filesystem\n // 4. Verify file integrity\n\n // Placeholder: Return expected local path\n return localPath;\n } catch (error) {\n throw new DatabaseError(\n \"Failed to download backup from S3\",\n DATABASE_ERROR_CODES.S3_DOWNLOAD_FAILED,\n {\n context: {\n source: \"BackupService.downloadFromS3\",\n filename: backup.filename,\n cause: error,\n },\n },\n );\n }\n }\n\n /**\n * Deletes a backup from S3.\n * @param backup Backup information\n */\n private async deleteFromS3(backup: BackupInfo): Promise<void> {\n // TODO: Implement AWS S3 delete using AWS SDK v3\n // Current implementation is a placeholder for development\n if (!this.config.s3?.enabled) return;\n\n try {\n // In real implementation:\n // 1. Initialize S3 client with credentials\n // 2. Delete object from S3 bucket using backup key\n // 3. Handle deletion errors and retries\n // Placeholder: Log deletion action\n // In production, this would actually delete from S3\n } catch (error) {\n throw new DatabaseError(\n \"Failed to delete backup from S3\",\n DATABASE_ERROR_CODES.S3_DELETE_FAILED,\n {\n context: {\n source: \"BackupService.deleteFromS3\",\n filename: backup.filename,\n cause: error,\n },\n },\n );\n }\n }\n\n /**\n * Sets up scheduled backups using cron.\n */\n private scheduleBackups(): void {\n // TODO: Implement cron-based scheduling using node-cron\n // Current implementation is a placeholder for development\n if (!this.config.schedule) return;\n\n try {\n // In real implementation:\n // 1. Install and import node-cron package\n // 2. Parse cron expression from config.schedule\n // 3. Schedule recurring backup task\n // 4. Handle cron job errors and logging\n // Example implementation would be:\n // const cron = require('node-cron');\n // cron.schedule(this.config.schedule, async () => {\n // try {\n // await this.createBackup();\n // } catch (error) {\n // // Handle scheduled backup errors\n // }\n // });\n // Placeholder: Log scheduling setup\n } catch {\n throw new DatabaseError(\n \"Failed to setup backup schedule\",\n DATABASE_ERROR_CODES.SCHEDULE_SETUP_FAILED,\n { context: { source: \"BackupService.scheduleBackups\" } },\n );\n }\n }\n\n /**\n * Validates file paths to prevent path traversal attacks.\n * @param filepath Path to validate\n * @returns True if path is valid and safe\n */\n private isValidPath(filepath: string): boolean {\n // Check for null, undefined, or empty paths\n if (!isString(filepath)) {\n return false;\n }\n\n // Check for path traversal patterns\n const dangerousPatterns = [\n \"../\",\n \"..\\\\\", // Directory traversal\n \"~/\", // Home directory access\n \"/etc/\",\n \"/proc/\",\n \"/sys/\", // System directories\n \"C:\\\\Windows\\\\\",\n \"C:\\\\Program Files\\\\\", // Windows system directories\n ];\n\n const normalizedPath = filepath.toLowerCase();\n return !dangerousPatterns.some((pattern) =>\n normalizedPath.includes(pattern.toLowerCase()),\n );\n }\n\n /**\n * Escapes shell arguments to prevent command injection.\n * @param arg Argument to escape\n * @returns Escaped argument safe for shell execution\n */\n private escapeShellArg(arg: string): string {\n if (!isString(arg)) {\n throw new DatabaseError(\n \"Invalid shell argument\",\n DATABASE_ERROR_CODES.INVALID_SHELL_ARG,\n { context: { source: \"BackupService.escapeShellArg\" } },\n );\n }\n\n // Remove or escape dangerous characters\n return DB_REGEX.sanitizeCommand(arg);\n }\n\n /**\n * Sanitizes strings for safe logging to prevent log injection.\n * @param input String to sanitize\n * @returns Sanitized string safe for logging\n */\n private sanitizeForLog(input: string): string {\n if (!isString(input)) {\n return \"[invalid_input]\";\n }\n\n const MAX_LOG_LENGTH = 200;\n return DB_REGEX.sanitizeLogMessage(input).substring(0, MAX_LOG_LENGTH);\n }\n}\n","import { AsyncLocalStorage } from \"async_hooks\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport type { TenantInfo } from \"@plyaz/types\";\n\n/**\n * Manages tenant context throughout the application using AsyncLocalStorage.\n * Provides a way to isolate tenant-specific data and operations.\n *\n * @example\n * ```typescript\n * const tenant: TenantInfo = {\n * id: 'tenant-123',\n * name: 'Acme Corp',\n * schema: 'acme_corp'\n * };\n *\n * // Run code within tenant context\n * const result = await TenantContext.run(tenant, async () => {\n * // This code has access to the tenant context\n * const currentTenant = TenantContext.current();\n * console.log(`Running as tenant: ${currentTenant?.name}`);\n *\n * // Perform tenant-specific operations\n * return await userService.getUsers();\n * });\n *\n * // Access current tenant from anywhere\n * const current = TenantContext.current();\n * if (current) {\n * console.log(`Current tenant: ${current.name}`);\n * }\n * ```\n */\nexport class TenantContext {\n private static storage = new AsyncLocalStorage<TenantInfo>();\n\n /**\n * Runs a function within a specific tenant context.\n * @param tenant Tenant information\n * @param callback Function to execute within tenant context\n * @returns Result of the callback function\n */\n static run<T>(tenant: TenantInfo, callback: () => Promise<T>): Promise<T> {\n return this.storage.run(tenant, callback);\n }\n\n /**\n * Gets the current tenant context.\n * @returns Current tenant information or undefined if no context is set\n */\n static current(): TenantInfo | undefined {\n return this.storage.getStore();\n }\n\n /**\n * Gets the current tenant context or throws an error if none is set.\n * @returns Current tenant information\n * @throws Error if no tenant context is available\n */\n static requireCurrent(): TenantInfo {\n const tenant = this.current();\n if (!tenant) {\n throw new DatabaseError(\n \"No tenant context available\",\n DATABASE_ERROR_CODES.NO_TENANT_CONTEXT,\n {\n context: {\n source: \"TenantContext.requireCurrent\",\n },\n },\n );\n }\n return tenant;\n }\n}\n","import { TenantContext } from \"./TenantContext\";\nimport { failure } from \"@utils/databaseResultHelpers\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport type {\n DatabaseAdapterType,\n DatabaseResult,\n PaginatedResult,\n QueryOptions,\n TenantValidationContext,\n} from \"@plyaz/types/db\";\n\n/**\n * TENANT REPOSITORY - Multi-Tenant Database Operations\n *\n * Base repository that automatically handles tenant isolation for all database operations.\n * Ensures data security by automatically filtering records by tenant ID and validating access.\n *\n * **RESPONSIBILITIES:**\n * 1. Tenant Isolation - Automatically filters all queries by current tenant\n * 2. Access Control - Validates tenant access for all operations\n * 3. Auto-Assignment - Automatically assigns tenant ID on record creation\n * 4. Validation - Ensures all operations respect tenant boundaries\n *\n * **USAGE PATTERN:**\n * Extend this class for each entity that requires tenant isolation.\n *\n * @template TEntity - The entity type that includes a tenant ID field\n *\n * @example\n * ### Basic Implementation\n * ```typescript\n * interface User {\n * id: string;\n * name: string;\n * email: string;\n * tenantId: string; // Required for tenant isolation\n * }\n *\n * class UserRepository extends TenantRepository<User> {\n * constructor(adapter: DatabaseAdapterType) {\n * super(adapter, 'users');\n * }\n *\n * protected getTenantIdField(): keyof User {\n * return 'tenantId';\n * }\n *\n * // Custom methods with automatic tenant isolation\n * async findByEmail(email: string) {\n * return this.findMany({ filter: { field: 'email', operator: 'eq', value: email } });\n * }\n * }\n * ```\n *\n * @example\n * ### Usage with Tenant Context\n * ```typescript\n * // Set tenant context (usually in middleware)\n * TenantContext.set({ id: 'tenant-123', name: 'Acme Corp' });\n *\n * const userRepo = new UserRepository(adapter);\n *\n * // All operations automatically filtered by tenant\n * const users = await userRepo.findMany(); // Only returns users for tenant-123\n * const user = await userRepo.findById('user-456'); // Validates tenant access\n *\n * // New records automatically get tenant ID\n * const newUser = await userRepo.create({\n * name: 'John Doe',\n * email: 'john@example.com'\n * // tenantId automatically set to 'tenant-123'\n * });\n * ```\n */\n\nexport abstract class TenantRepository<\n TEntity extends Record<string, unknown>,\n> {\n /**\n * Creates a new tenant repository instance.\n *\n * @param adapter - Database adapter for operations\n * @param tableName - Name of the database table\n */\n constructor(\n protected adapter: DatabaseAdapterType,\n protected tableName: string,\n ) {}\n\n /**\n * ABSTRACT METHOD - Tenant ID Field Specification\n *\n * Must be implemented by subclasses to specify which field contains the tenant ID.\n * This field is used for automatic filtering and validation.\n *\n * @returns The key of the tenant ID field in the entity\n *\n * @example\n * ```typescript\n * protected getTenantIdField(): keyof User {\n * return 'tenantId'; // or 'organizationId', 'companyId', etc.\n * }\n * ```\n */\n protected abstract getTenantIdField(): keyof TEntity;\n\n /**\n * FIND BY ID - Tenant-Safe Record Retrieval\n *\n * Finds a single record by ID with automatic tenant access validation.\n * Only returns records that belong to the current tenant.\n *\n * **SECURITY:** Validates that the found record belongs to the current tenant\n * **BEHAVIOR:** Returns null if record doesn't exist or belongs to different tenant\n *\n * @param id - The unique identifier of the record to find\n * @returns Promise resolving to the record or null if not found/no access\n *\n * @throws {DatabaseError} When ID is invalid or access is denied\n *\n * @example\n * ```typescript\n * // Set tenant context\n * TenantContext.set({ id: 'tenant-123' });\n *\n * const userRepo = new UserRepository(adapter);\n *\n * // Find user - only returns if belongs to tenant-123\n * const result = await userRepo.findById('user-456');\n * if (result.success && result.value) {\n * console.log('User found:', result.value.name);\n * } else {\n * console.log('User not found or access denied');\n * }\n * ```\n */\n async findById(id: string): Promise<DatabaseResult<TEntity | null>> {\n try {\n if (!id || typeof id !== \"string\") {\n return failure(\n new DatabaseError(\n \"Invalid record ID\",\n DATABASE_ERROR_CODES.INVALID_ID,\n { context: { source: \"TenantRepository.findById\" } },\n ),\n );\n }\n\n const result = await this.adapter.findById<TEntity>(this.tableName, id);\n\n if (result.success && result.value) {\n try {\n this.validateTenantAccess(result.value);\n } catch (error) {\n return failure(\n new DatabaseError(\n \"Access denied to record from different tenant\",\n DATABASE_ERROR_CODES.ACCESS_DENIED,\n {\n context: { source: \"TenantRepository.findById\", cause: error },\n },\n ),\n );\n }\n }\n\n return result;\n } catch (error) {\n return failure(\n new DatabaseError(\n \"Failed to find record\",\n DATABASE_ERROR_CODES.FIND_BY_ID_FAILED,\n { context: { source: \"TenantRepository.findById\", cause: error } },\n ),\n );\n }\n }\n\n /**\n * FIND MANY - Tenant-Filtered Query\n *\n * Finds multiple records with automatic tenant filtering applied.\n * All results are guaranteed to belong to the current tenant.\n *\n * **SECURITY:** Automatically adds tenant filter to all queries\n * **PERFORMANCE:** Uses database-level filtering for efficiency\n *\n * @param options - Optional query options (filters, sorting, pagination)\n * @returns Promise resolving to paginated results for current tenant only\n *\n * @example\n * ```typescript\n * // Set tenant context\n * TenantContext.set({ id: 'tenant-123' });\n *\n * const userRepo = new UserRepository(adapter);\n *\n * // Get all users for current tenant\n * const allUsers = await userRepo.findMany();\n *\n * // Get active users with pagination\n * const activeUsers = await userRepo.findMany({\n * filter: { field: 'status', operator: 'eq', value: 'active' },\n * pagination: { page: 1, limit: 10 },\n * sort: { field: 'name', direction: 'asc' }\n * });\n *\n * // Results automatically filtered by tenantId = 'tenant-123'\n * ```\n */\n async findMany(\n options?: QueryOptions,\n ): Promise<DatabaseResult<PaginatedResult<TEntity>>> {\n const tenant = TenantContext.requireCurrent();\n\n const tenantFilter = {\n field: this.getTenantIdField() as keyof TEntity & string,\n operator: \"eq\" as const,\n value: tenant.id as TEntity[keyof TEntity],\n };\n\n const enhancedOptions: QueryOptions<TEntity> = {\n ...options,\n filter: tenantFilter,\n };\n\n return this.adapter.findMany<TEntity>(this.tableName, enhancedOptions);\n }\n\n /**\n * CREATE - Tenant-Safe Record Creation\n *\n * Creates a new record with automatic tenant ID assignment.\n * The tenant ID is automatically set from the current tenant context.\n *\n * **SECURITY:** Automatically assigns current tenant ID to new records\n * **CONVENIENCE:** No need to manually set tenant ID in application code\n *\n * @param entity - The entity data to create (tenant ID will be auto-assigned)\n * @returns Promise resolving to the created record with tenant ID\n *\n * @example\n * ```typescript\n * // Set tenant context\n * TenantContext.set({ id: 'tenant-123' });\n *\n * const userRepo = new UserRepository(adapter);\n *\n * // Create user - tenantId automatically set to 'tenant-123'\n * const result = await userRepo.create({\n * name: 'John Doe',\n * email: 'john@example.com',\n * status: 'active'\n * // No need to set tenantId - automatically assigned\n * });\n *\n * if (result.success) {\n * console.log('Created user:', result.value.id);\n * console.log('Tenant ID:', result.value.tenantId); // 'tenant-123'\n * }\n * ```\n */\n async create(entity: Omit<TEntity, \"id\">): Promise<DatabaseResult<TEntity>> {\n const tenant = TenantContext.requireCurrent();\n const tenantEntity = {\n ...entity,\n [this.getTenantIdField()]: tenant.id,\n } as TEntity;\n\n return this.adapter.create<TEntity>(this.tableName, tenantEntity);\n }\n\n /**\n * UPDATE - Tenant-Safe Record Update\n *\n * Updates an existing record with tenant access validation.\n * Only allows updates to records that belong to the current tenant.\n *\n * **SECURITY:** Validates tenant access before allowing updates\n * **SAFETY:** Prevents cross-tenant data modification\n *\n * @param id - The unique identifier of the record to update\n * @param entity - Partial entity data with fields to update\n * @returns Promise resolving to the updated record\n *\n * @throws {DatabaseError} When record not found, access denied, or invalid parameters\n *\n * @example\n * ```typescript\n * // Set tenant context\n * TenantContext.set({ id: 'tenant-123' });\n *\n * const userRepo = new UserRepository(adapter);\n *\n * // Update user - only works if user belongs to tenant-123\n * const result = await userRepo.update('user-456', {\n * name: 'Jane Doe',\n * email: 'jane@example.com'\n * });\n *\n * if (result.success) {\n * console.log('Updated user:', result.value.name);\n * } else {\n * console.log('Update failed:', result.error?.message);\n * }\n * ```\n */\n async update(\n id: string,\n entity: Partial<TEntity>,\n ): Promise<DatabaseResult<TEntity>> {\n try {\n if (!id || !entity || typeof entity !== \"object\") {\n return failure(\n new DatabaseError(\n \"Invalid parameters\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n { context: { source: \"TenantRepository.update\" } },\n ),\n );\n }\n\n const existing = await this.findById(id);\n if (!existing.success) {\n return failure(\n existing.error ??\n new DatabaseError(\n \"Failed to fetch record\",\n DATABASE_ERROR_CODES.FETCH_FAILED,\n { context: { source: \"TenantRepository.update\" } },\n ),\n );\n }\n if (!existing.value) {\n return failure(\n new DatabaseError(\n \"Record not found\",\n DATABASE_ERROR_CODES.RECORD_NOT_FOUND,\n {\n context: {\n source: \"TenantRepository.update\",\n },\n },\n ),\n );\n }\n\n return this.adapter.update<TEntity>(this.tableName, id, entity);\n } catch (error) {\n return failure(\n new DatabaseError(\n \"Failed to update record\",\n DATABASE_ERROR_CODES.UPDATE_FAILED,\n {\n context: {\n source: \"TenantRepository.update\",\n cause: error,\n },\n },\n ),\n );\n }\n }\n\n /**\n * DELETE - Tenant-Safe Record Deletion\n *\n * Deletes a record with tenant access validation.\n * Only allows deletion of records that belong to the current tenant.\n *\n * **SECURITY:** Validates tenant access before allowing deletion\n * **SAFETY:** Prevents cross-tenant data deletion\n *\n * @param id - The unique identifier of the record to delete\n * @returns Promise resolving to void on successful deletion\n *\n * @throws {DatabaseError} When record not found, access denied, or invalid ID\n *\n * @example\n * ```typescript\n * // Set tenant context\n * TenantContext.set({ id: 'tenant-123' });\n *\n * const userRepo = new UserRepository(adapter);\n *\n * // Delete user - only works if user belongs to tenant-123\n * const result = await userRepo.delete('user-456');\n *\n * if (result.success) {\n * console.log('User deleted successfully');\n * } else {\n * console.log('Delete failed:', result.error?.message);\n * }\n * ```\n */\n async delete(id: string): Promise<DatabaseResult<void>> {\n try {\n if (!id || typeof id !== \"string\") {\n return failure(\n new DatabaseError(\n \"Invalid record ID\",\n DATABASE_ERROR_CODES.INVALID_ID,\n {\n context: {\n source: \"TenantRepository.delete\",\n },\n },\n ),\n );\n }\n\n const existing = await this.findById(id);\n if (!existing.success) {\n return failure(\n existing.error ??\n new DatabaseError(\n \"Failed to fetch record\",\n DATABASE_ERROR_CODES.FETCH_FAILED,\n {\n context: {\n source: \"TenantRepository.delete\",\n },\n },\n ),\n );\n }\n if (!existing.value) {\n return failure(\n new DatabaseError(\n \"Record not found\",\n DATABASE_ERROR_CODES.RECORD_NOT_FOUND,\n {\n context: {\n source: \"TenantRepository.delete\",\n },\n },\n ),\n );\n }\n\n return this.adapter.delete(this.tableName, id);\n } catch (error) {\n return failure(\n new DatabaseError(\n \"Failed to delete record\",\n DATABASE_ERROR_CODES.DELETE_FAILED,\n {\n context: {\n source: \"TenantRepository.delete\",\n cause: error,\n },\n },\n ),\n );\n }\n }\n\n /**\n * Validates that the entity is a valid object.\n * @private\n * @param entity - The entity to validate\n * @throws {DatabaseError} When entity is invalid\n */\n private validateEntity(entity: TEntity): void {\n if (!entity || typeof entity !== \"object\") {\n throw new DatabaseError(\n \"Invalid entity\",\n DATABASE_ERROR_CODES.INVALID_ENTITY,\n {\n context: {\n source: \"TenantRepository.validateEntity\",\n },\n },\n );\n }\n }\n\n /**\n * Validates that tenant context exists and has an ID.\n * @private\n * @param tenant - The tenant context to validate\n * @throws {DatabaseError} When tenant context is invalid\n */\n\n private validateTenantContext(tenant: TenantValidationContext): void {\n if (!tenant?.id) {\n throw new DatabaseError(\n \"No tenant context available\",\n DATABASE_ERROR_CODES.NO_TENANT_CONTEXT,\n {\n context: {\n source: \"TenantRepository.validateTenantContext\",\n },\n },\n );\n }\n }\n\n /**\n * Validates that the entity has a tenant ID.\n * @private\n * @param tenantId - The tenant ID from the entity\n * @throws {DatabaseError} When tenant ID is missing\n */\n private validateEntityTenantId(tenantId: TEntity[keyof TEntity]): void {\n if (!tenantId) {\n throw new DatabaseError(\n \"Entity has no tenant ID\",\n DATABASE_ERROR_CODES.NO_TENANT_ID,\n {\n context: {\n source: \"TenantRepository.validateEntityTenantId\",\n },\n },\n );\n }\n }\n\n /**\n * Validates that the current tenant has access to the entity.\n * @private\n * @param entity - The entity to validate access for\n * @throws {DatabaseError} When access is denied\n */\n private validateTenantAccess(entity: TEntity): void {\n try {\n this.validateEntity(entity);\n\n const tenant = TenantContext.requireCurrent();\n this.validateTenantContext(tenant);\n\n const tenantId = entity[this.getTenantIdField()];\n this.validateEntityTenantId(tenantId);\n\n if (tenantId !== tenant.id) {\n throw new DatabaseError(\n \"Access denied to entity from different tenant\",\n DATABASE_ERROR_CODES.ACCESS_DENIED,\n {\n context: {\n source: \"TenantRepository.validateTenantAccess\",\n },\n },\n );\n }\n } catch (error) {\n throw new DatabaseError(\n \"Tenant validation failed\",\n DATABASE_ERROR_CODES.TENANT_VALIDATION_FAILED,\n {\n context: {\n source: \"TenantRepository.validateTenantAccess\",\n cause: error,\n },\n },\n );\n }\n }\n}\n","import { NUMERIX } from \"@plyaz/config\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport type { ShardKey } from \"@plyaz/types\";\n\n/**\n * Manages shard key definitions and calculations.\n * Provides utilities for determining which shard a record belongs to.\n *\n * @example\n * ```typescript\n * const shardKeyManager = new ShardKeyManager();\n *\n * // Register a shard key for users table\n * shardKeyManager.registerShardKey('users', {\n * name: 'user_shard',\n * type: 'hash',\n * columns: ['id'],\n * strategy: 'hash',\n * shardCount: 4\n * });\n *\n * // Calculate which shard a user belongs to\n * const shardId = shardKeyManager.calculateShard('users', { id: 'user-123' });\n * console.log(`User belongs to shard ${shardId}`);\n * ```\n */\nexport class ShardKeyManager {\n private shardKeys: Map<string, ShardKey> = new Map();\n\n /**\n * Registers a shard key for a table.\n * @param table Table name\n * @param shardKey Shard key configuration\n */\n registerShardKey(table: string, shardKey: ShardKey): void {\n this.shardKeys.set(table, shardKey);\n }\n\n /**\n * Gets the shard key configuration for a table.\n * @param table Table name\n * @returns Shard key configuration or undefined\n */\n getShardKey(table: string): ShardKey | undefined {\n return this.shardKeys.get(table);\n }\n\n /**\n * Calculates which shard a record belongs to.\n * @param table Table name\n * @param data Record data\n * @returns Shard ID (0-based)\n */\n calculateShard<T extends Record<string, string | number>>(\n table: string,\n data: T,\n ): number {\n const shardKey = this.getShardKey(table);\n if (!shardKey) {\n throw new DatabaseError(\n `No shard key defined for table: ${table}`,\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"calculateShard\" },\n cause: new Error(`No shard key defined for table: ${table}`),\n },\n );\n }\n\n const keyValue = this.extractKeyValue(data, shardKey);\n\n switch (shardKey.strategy) {\n case \"modulus\":\n return this.modulusShard(keyValue, shardKey.shardCount);\n case \"hash\":\n return this.hashShard(keyValue, shardKey.shardCount);\n case \"range\":\n return this.rangeShard(keyValue, shardKey);\n default:\n throw new DatabaseError(\n `Unknown sharding strategy: ${shardKey.strategy}`,\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"calculateShard\" },\n cause: new Error(`Unknown sharding strategy: ${shardKey.strategy}`),\n },\n );\n }\n }\n\n /**\n * Extracts the shard key value from record data.\n * @param data Record data\n * @param shardKey Shard key configuration\n * @returns Extracted key value\n */\n private extractKeyValue<T extends Record<string, string | number>>(\n data: T,\n shardKey: ShardKey,\n ): string | number {\n if (shardKey.columns.length === 1) {\n return data[shardKey.columns[0]];\n }\n\n return shardKey.columns.map((col) => data[col]).join(\"|\");\n }\n\n /**\n * Calculates shard ID using modulus strategy.\n * @param keyValue Key value\n * @param shardCount Number of shards\n * @returns Shard ID\n */\n private modulusShard(keyValue: string | number, shardCount: number): number {\n const numericKey =\n typeof keyValue === \"string\"\n ? this.hashString(keyValue)\n : Number(keyValue);\n\n return numericKey % shardCount;\n }\n\n /**\n * Calculates shard ID using hash strategy.\n * @param keyValue Key value\n * @param shardCount Number of shards\n * @returns Shard ID\n */\n private hashShard(keyValue: string | number, shardCount: number): number {\n const hash =\n typeof keyValue === \"string\"\n ? this.hashString(keyValue)\n : Number(keyValue);\n\n return Math.abs(hash) % shardCount;\n }\n\n /**\n * Calculates shard ID using range strategy.\n * @param keyValue Key value\n * @param shardKey Shard key configuration\n * @returns Shard ID\n */\n private rangeShard(keyValue: string | number, shardKey: ShardKey): number {\n // Implementation would depend on range configuration\n // This is a simplified version\n const numericKey =\n typeof keyValue === \"string\"\n ? this.hashString(keyValue)\n : Number(keyValue);\n\n return Math.floor(\n numericKey / (Number.MAX_SAFE_INTEGER / shardKey.shardCount),\n );\n }\n\n /**\n * Hashes a string to a numeric value.\n * @param str String to hash\n * @returns Hash value\n */\n private hashString(str: string): number {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n hash = (hash << NUMERIX.FIVE) - hash + char;\n hash = hash & hash; // Convert to 32-bit integer\n }\n return hash;\n }\n}\n","import { ShardKeyManager } from \"./ShardKey\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport type { ShardConfig, ShardKey } from \"@plyaz/types\";\n\n/**\n * Routes database operations to the appropriate shard based on shard keys.\n * Provides shard-aware routing and management capabilities.\n *\n * @example\n * ```typescript\n * const shardConfigs: ShardConfig[] = [\n * { id: 0, connectionString: 'postgres://shard0:5432/db', isPrimary: false },\n * { id: 1, connectionString: 'postgres://shard1:5432/db', isPrimary: false },\n * { id: 2, connectionString: 'postgres://shard2:5432/db', isPrimary: true }\n * ];\n *\n * const router = new ShardRouter(shardConfigs);\n *\n * // Route a record to the appropriate shard\n * const userData = { id: 'user-456', name: 'Jane' };\n * const shard = router.routeToShard('users', userData);\n * console.log(`User should be stored on shard ${shard.id}`);\n *\n * // Get a specific shard\n * const shard2 = router.getShardById(2);\n *\n * // Get all shards\n * const allShards = router.getAllShards();\n * ```\n */\nexport class ShardRouter {\n private shards: Map<number, ShardConfig> = new Map();\n private shardKeyManager: ShardKeyManager;\n\n /**\n * Creates a new ShardRouter instance.\n * @param shardConfigs Array of shard configurations\n */\n constructor(shardConfigs: ShardConfig[]) {\n this.shardKeyManager = new ShardKeyManager();\n\n shardConfigs.forEach((config) => {\n this.shards.set(config.id, config);\n });\n }\n\n /**\n * Determines which shard a record should be routed to.\n * @param table Table name\n * @param data Record data\n * @returns Shard configuration\n */\n routeToShard(\n table: string,\n data: Record<string, string | number | boolean | Date>,\n ): ShardConfig {\n const filteredData: Record<string, string | number> = {};\n for (const [key, value] of Object.entries(data)) {\n if (typeof value === \"string\" || typeof value === \"number\") {\n filteredData[key] = value;\n }\n }\n const shardId = this.shardKeyManager.calculateShard(table, filteredData);\n const shard = this.shards.get(shardId);\n\n if (!shard) {\n throw new DatabaseError(\n `Shard not found: ${shardId}`,\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"routeToShard\" },\n cause: new Error(`Shard not found: ${shardId}`),\n },\n );\n }\n\n return shard;\n }\n\n /**\n * Gets a shard configuration by ID.\n * @param shardId Shard ID\n * @returns Shard configuration or undefined\n */\n getShardById(shardId: number): ShardConfig | undefined {\n return this.shards.get(shardId);\n }\n\n /**\n * Gets all shard configurations.\n * @returns Array of all shard configurations\n */\n getAllShards(): ShardConfig[] {\n return Array.from(this.shards.values());\n }\n\n /**\n * Gets the primary shard configuration.\n * @returns Primary shard configuration or undefined\n */\n getPrimaryShard(): ShardConfig | undefined {\n return Array.from(this.shards.values()).find((shard) => shard.isPrimary);\n }\n\n /**\n * Registers a shard key for a table.\n * @param table Table name\n * @param shardKey Shard key configuration\n */\n registerShardKey(table: string, shardKey: ShardKey): void {\n this.shardKeyManager.registerShardKey(table, shardKey);\n }\n}\n","import { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport type { PaginationOptions, SortOptions, Filter } from \"@plyaz/types/db\";\nimport { DB_REGEX } from \"@utils/regex\";\n\n/**\n * SQL query builder utilities\n *\n * Provides safe, parameterized SQL query generation.\n * Works independently of any specific ORM or query engine.\n */\n\n/**\n * Builds a WHERE clause from filters\n * @param filters - Array of filter conditions\n * @returns WHERE clause string\n */\nexport function buildWhereClause<T extends object = object>(\n filters?: Filter[],\n): string {\n if (!filters || filters.length === 0) {\n return \"\";\n }\n\n try {\n const conditions: string[] = [];\n let paramIndex = 1;\n\n for (const filter of filters) {\n if (!filter.field || !filter.operator) {\n throw new DatabaseError(\n \"Invalid filter: field and operator are required\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"buildWhereClause\" },\n cause: new Error(\"Invalid filter: field and operator are required\"),\n },\n );\n }\n\n const condition = buildCondition<T>(filter, paramIndex);\n conditions.push(condition.clause);\n paramIndex = condition.paramCount;\n }\n\n const whereClause = conditions\n .map((cond, idx) => {\n if (idx === 0) return cond;\n const logical = (filters[idx]?.logical ?? \"and\").toUpperCase();\n if (![\"AND\", \"OR\"].includes(logical)) {\n throw new DatabaseError(\n `Invalid logical operator: ${logical}`,\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"buildWhereClause\" },\n cause: new Error(`Invalid logical operator: ${logical}`),\n },\n );\n }\n return `${logical} ${cond}`;\n })\n .join(\" \");\n\n return \" WHERE \" + whereClause;\n } catch (error) {\n throw new DatabaseError(\n `Failed to build WHERE clause: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n {\n context: { source: \"buildWhereClause\" },\n cause: error as Error,\n },\n );\n }\n}\n\n/**\n * Builds a single condition for a WHERE clause\n * @param filter - Filter condition\n * @param startIndex - Starting parameter index\n * @returns Object containing the condition clause and updated parameter count\n */\nfunction buildCondition<T>(\n filter: Filter,\n startIndex: number,\n): { clause: string; paramCount: number } {\n const { field, operator, value } = filter;\n let paramCount = startIndex;\n\n // Validate field name to prevent SQL injection\n if (!DB_REGEX.isValidFieldName(field)) {\n throw new DatabaseError(\n `Invalid field name: ${field}`,\n DATABASE_ERROR_CODES.INIT_FAILED,\n );\n }\n\n const operatorsMap: Record<string, () => string> = {\n eq: () => `\"${field}\" = $${paramCount++}`,\n ne: () => `\"${field}\" != $${paramCount++}`,\n gt: () => `\"${field}\" > $${paramCount++}`,\n gte: () => `\"${field}\" >= $${paramCount++}`,\n lt: () => `\"${field}\" < $${paramCount++}`,\n lte: () => `\"${field}\" <= $${paramCount++}`,\n in: () => {\n if (!Array.isArray(value)) {\n throw new DatabaseError(\n \"IN operator requires array value\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"buildCondition\" },\n cause: new Error(\"IN operator requires array value\"),\n },\n );\n }\n return `\"${field}\" IN (${(value as T[]).map(() => `$${paramCount++}`).join(\", \")})`;\n },\n notIn: () => {\n if (!Array.isArray(value)) {\n throw new DatabaseError(\n \"NOT IN operator requires array value\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"buildCondition\" },\n cause: new Error(\"NOT IN operator requires array value\"),\n },\n );\n }\n return `\"${field}\" NOT IN (${(value as T[]).map(() => `$${paramCount++}`).join(\", \")})`;\n },\n like: () => `\"${field}\" LIKE $${paramCount++}`,\n between: () => {\n const BETWEEN_ARRAY_LENGTH = 2;\n if (\n !Array.isArray(value) ||\n (value as unknown[]).length !== BETWEEN_ARRAY_LENGTH\n ) {\n throw new DatabaseError(\n \"BETWEEN operator requires array with exactly 2 values\",\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"buildCondition\" },\n cause: new Error(\n \"BETWEEN operator requires array with exactly 2 values\",\n ),\n },\n );\n }\n return `\"${field}\" BETWEEN $${paramCount++} AND $${paramCount++}`;\n },\n isNull: () => `\"${field}\" IS NULL`,\n isNotNull: () => `\"${field}\" IS NOT NULL`,\n };\n\n const clauseFn = operatorsMap[operator];\n if (!clauseFn) {\n throw new DatabaseError(\n `Unsupported operator: ${operator}`,\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"buildCondition\" },\n cause: new Error(`Unsupported operator: ${operator}`),\n },\n );\n }\n\n try {\n return { clause: clauseFn(), paramCount };\n } catch (error) {\n throw new DatabaseError(\n `Failed to build condition for field ${field}: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n DATABASE_ERROR_CODES.INIT_FAILED,\n );\n }\n}\n\n/**\n * Builds an ORDER BY clause from sort options\n * @param sortOptions - Array of sort options\n * @returns ORDER BY clause string\n */\nexport function buildOrderClause(sortOptions?: SortOptions[]): string {\n if (!sortOptions || sortOptions.length === 0) return \"\";\n\n try {\n const clauses = sortOptions.map((option) => {\n // Validate field name to prevent SQL injection\n if (!DB_REGEX.isValidFieldName(option.field)) {\n throw new DatabaseError(\n `Invalid field name: ${option.field}`,\n DATABASE_ERROR_CODES.INIT_FAILED,\n );\n }\n\n const direction = option.direction.toUpperCase();\n if (![\"ASC\", \"DESC\"].includes(direction)) {\n throw new DatabaseError(\n `Invalid sort direction: ${direction}`,\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n {\n context: { source: \"buildOrderClause\" },\n cause: new Error(`Invalid sort direction: ${direction}`),\n },\n );\n }\n\n return `\"${option.field}\" ${direction}`;\n });\n\n return \" ORDER BY \" + clauses.join(\", \");\n } catch (error) {\n throw new DatabaseError(\n `Failed to build ORDER BY clause: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n {\n context: { source: \"buildOrderClause\" },\n cause: error as Error,\n },\n );\n }\n}\n\n/**\n * Builds LIMIT and OFFSET clauses from pagination options\n * @param pagination - Pagination options\n * @returns Object containing the clause string and parameters\n */\nexport function buildPaginationClause<T>(pagination?: PaginationOptions): {\n clause: string;\n params: T[];\n} {\n if (!pagination) return { clause: \"\", params: [] };\n\n const params: T[] = [];\n let clause = \"\";\n\n const { limit, offset } = pagination;\n\n if (limit !== undefined) {\n clause += ` LIMIT $${params.length + 1}`;\n params.push(limit as T);\n }\n\n if (offset !== undefined) {\n clause += ` OFFSET $${params.length + 1}`;\n params.push(offset as T);\n }\n\n return { clause, params };\n}\n","/**\n * ORM Query builder utilities\n *\n * This module provides utilities for building ORM-specific queries.\n * Currently a placeholder for future ORM implementations.\n */\n\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\n\n/**\n * Builds a WHERE clause for ORM queries\n * @throws Error - Not implemented yet\n */\nexport function buildWhereClauseORM(): Error {\n throw new DatabaseError(\n \"Not implemented yet\",\n DATABASE_ERROR_CODES.UNKNOWN_ERROR,\n {\n context: { source: \"buildWhereClauseORM\" },\n cause: new Error(\"Not implemented yet\"),\n },\n );\n}\n\n/**\n * Builds an ORDER BY clause for ORM queries\n * @throws Error - Not implemented yet\n */\nexport function buildOrderClauseORM(): Error {\n throw new DatabaseError(\n \"Not implemented yet\",\n DATABASE_ERROR_CODES.UNKNOWN_ERROR,\n {\n context: { source: \"buildOrderClauseORM\" },\n cause: new Error(\"Not implemented yet\"),\n },\n );\n}\n\n/**\n * Builds pagination clauses for ORM queries\n * @throws Error - Not implemented yet\n */\nexport function buildPaginationClauseORM(): Error {\n throw new DatabaseError(\n \"Not implemented yet\",\n DATABASE_ERROR_CODES.UNKNOWN_ERROR,\n {\n context: { source: \"buildPaginationClauseORM\" },\n cause: new Error(\"Not implemented yet\"),\n },\n );\n}\n","import { PipeTransform, Injectable } from \"@nestjs/common\";\nimport sanitizeHtml from \"sanitize-html\";\nimport { isString, isObject } from \"@utils/typeGuards\";\n\n/**\n * A NestJS pipe that recursively sanitizes input data to remove any potentially unsafe HTML.\n *\n * This pipe can handle strings, arrays, and objects. It ensures that\n * all string values within the provided data are sanitized using the `sanitize-html` library.\n *\n */\n@Injectable()\nexport class SanitizeHtmlPipe implements PipeTransform {\n /**\n * Transforms and sanitizes the provided value.\n * - Strings are sanitized using `sanitize-html`.\n * - Arrays and objects are recursively sanitized.\n * - Other primitive types (e.g., numbers, booleans) are returned as-is.\n *\n * @template T\n * @param {T} value - The value to sanitize.\n * @returns {string | Record<string, unknown> | unknown[]} - The sanitized value.\n */\n transform<T>(value: T): string | Record<string, unknown> | unknown[] {\n if (isString(value)) {\n return this.sanitizeString(value);\n }\n\n if (Array.isArray(value)) {\n return value.map((v) => this.transform(v));\n }\n\n if (isObject(value)) {\n const result: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value)) {\n result[key] = this.transform(val);\n }\n return result;\n }\n\n return value as unknown[];\n }\n\n /**\n * Sanitizes a single string by removing all HTML tags and attributes,\n * allowing only safe URL schemes like `http`, `https`, and `mailto`.\n *\n * @param {string} str - The string to sanitize.\n * @returns {string} - The sanitized string.\n * @private\n */\n private sanitizeString(str: string): string {\n return sanitizeHtml(str, {\n allowedTags: [],\n allowedAttributes: {},\n allowedSchemes: [\"http\", \"https\", \"mailto\"],\n });\n }\n}\n","import { BadRequestException, Injectable, PipeTransform } from \"@nestjs/common\";\nimport { ZodType } from \"zod\";\nimport { SanitizeHtmlPipe } from \"../sanitizers/html.sanitizer\";\n\n/**\n * A NestJS pipe that combines input sanitization and validation.\n *\n * This pipe first sanitizes incoming data using {@link SanitizeHtmlPipe}\n * to remove any potentially unsafe HTML, and then validates the sanitized\n * data using a provided Zod schema.\n *\n * If validation fails, a `BadRequestException` is thrown.\n */\n@Injectable()\nexport class DataValidationPipe implements PipeTransform {\n private readonly sanitizeHtmlPipe = new SanitizeHtmlPipe();\n\n /**\n * Creates a new DataValidationPipe instance with the provided Zod schema.\n *\n * @param {ZodType} schema - The Zod schema used to validate sanitized data.\n */\n constructor(private schema: ZodType) {}\n\n /**\n * Sanitizes and validates incoming data.\n * - First, all string values are sanitized to remove unsafe HTML.\n * - Then, the sanitized data is validated against the provided Zod schema.\n *\n * Throws a `BadRequestException` if validation fails.\n *\n * @param {unknown} value - The incoming value to sanitize and validate.\n * @returns {unknown} - The sanitized and validated data.\n * @throws {BadRequestException} - If validation fails.\n */\n transform(value: unknown): unknown {\n const sanitizedValue = this.sanitizeHtmlPipe.transform(value);\n\n try {\n return this.schema.parse(sanitizedValue);\n } catch (error) {\n if (error instanceof Error) {\n throw new BadRequestException(`Validation failed: ${error.message}`);\n }\n throw new BadRequestException(`Invalid request data.`);\n }\n }\n}\n","/**\n * MigrationManager - Database schema migrations with version control\n *\n * Manages database schema migrations with support for versioning,\n * rollback, and migration history tracking. Automatically discovers\n * migration files from a specified directory and applies them in order.\n *\n * @example\n * ```typescript\n * const migrationManager = new MigrationManager({\n * adapter: sqlAdapter,\n * migrationsPath: './migrations', // default\n * tableName: 'schema_migrations' // default\n * });\n *\n * // Run all pending migrations\n * await migrationManager.up();\n *\n * // Rollback last migration\n * await migrationManager.down();\n *\n * // Get migration status\n * const status = await migrationManager.status();\n * ```\n */\n\nimport type {\n DatabaseAdapterType,\n DatabaseResult,\n Migration,\n MigrationFile,\n MigrationRecord,\n MigrationManagerConfig,\n MigrationStatus,\n} from \"@plyaz/types/db\";\nimport { success, failure } from \"../utils/databaseResultHelpers\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\n\n/** Constants for statement description extraction */\nconst DESCRIPTION_MAX_LENGTH = 60;\nconst FALLBACK_DESCRIPTION_LENGTH = 50;\n\n/** Constants for progress logging */\nconst PROGRESS_LOG_INTERVAL = 10;\n\n/** Constants for error message truncation */\nconst ERROR_MESSAGE_MAX_LENGTH = 300;\n\n/**\n * MigrationManager - Handles database schema migrations\n *\n * Discovers migration files, tracks migration history, and applies\n * migrations in order with support for rollback.\n */\nexport class MigrationManager {\n private adapter: DatabaseAdapterType;\n private migrationsPath: string;\n private tableName: string;\n private schema: string;\n\n constructor(config: MigrationManagerConfig) {\n this.adapter = config.adapter;\n this.migrationsPath = path.resolve(config.migrationsPath ?? \"./migrations\");\n this.schema = config.schema ?? \"public\";\n // Prefix table name with schema if not 'public'\n this.tableName =\n this.schema !== \"public\"\n ? `${this.schema}.${config.tableName ?? \"schema_migrations\"}`\n : (config.tableName ?? \"schema_migrations\");\n }\n\n /**\n * Initialize migrations table if it doesn't exist\n */\n async initialize(): Promise<DatabaseResult<void>> {\n try {\n // Create migrations tracking table with file_path for traceability\n const createTableSQL = `\n CREATE TABLE IF NOT EXISTS ${this.tableName} (\n version VARCHAR(255) PRIMARY KEY,\n name VARCHAR(255) NOT NULL,\n file_path VARCHAR(500),\n applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n execution_time INTEGER NOT NULL\n )\n `;\n\n // Execute using adapter's raw query if available\n if (typeof this.adapter.query === \"function\") {\n await this.adapter.query(createTableSQL);\n\n // Add file_path column if it doesn't exist (for existing tables)\n await this.adapter\n .query(\n `\n DO $$\n BEGIN\n IF NOT EXISTS (\n SELECT 1 FROM information_schema.columns\n WHERE table_name = '${this.tableName.split(\".\").pop()}'\n AND column_name = 'file_path'\n ) THEN\n ALTER TABLE ${this.tableName} ADD COLUMN file_path VARCHAR(500);\n END IF;\n END $$;\n `,\n )\n .catch(() => {\n // Ignore if column already exists or syntax not supported\n });\n }\n\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to initialize migrations table: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.INIT_FAILED,\n { cause: error as Error },\n ),\n );\n }\n }\n\n /**\n * Discover migration files from migrations directory (including subdirectories)\n */\n private async discoverMigrations(): Promise<MigrationFile[]> {\n if (!fs.existsSync(this.migrationsPath)) {\n return [];\n }\n\n const migrations: MigrationFile[] = [];\n\n const scanDirectory = (dir: string): void => {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n\n if (entry.isDirectory()) {\n // Recursively scan subdirectories\n scanDirectory(fullPath);\n } else if (entry.isFile()) {\n // Match migration file pattern: {version}_{name}.{ts|js|sql}\n // Examples: 001_initial_schema.sql, 20231124_add_users_table.ts\n const match = entry.name.match(/^(\\d+)_(.+)\\.(ts|js|sql)$/);\n if (match) {\n const [, version, name] = match;\n migrations.push({\n filePath: fullPath,\n version,\n name: name.replace(/_/g, \" \"),\n });\n }\n }\n }\n };\n\n scanDirectory(this.migrationsPath);\n\n // Sort by version\n return migrations.sort((a, b) => a.version.localeCompare(b.version));\n }\n\n /**\n * Parse SQL content to extract UP and DOWN sections\n */\n private parseSqlSections(sql: string): {\n upSQL: string;\n downSQL: string | null;\n } {\n const hasUpMarker = sql.includes(\"-- UP\");\n const hasDownMarker = sql.includes(\"-- DOWN\");\n\n if (hasUpMarker && hasDownMarker) {\n const parts = sql.split(\"-- DOWN\");\n return {\n upSQL: parts[0].replace(\"-- UP\", \"\").trim(),\n downSQL: parts[1].trim(),\n };\n }\n\n if (hasDownMarker) {\n const parts = sql.split(\"-- DOWN\");\n return {\n upSQL: parts[0].trim(),\n downSQL: parts[1].trim(),\n };\n }\n\n return { upSQL: sql.trim(), downSQL: null };\n }\n\n /**\n * Process dollar-quoted string delimiters ($$ or $tag$)\n * Returns updated state for tracking if we're inside a dollar block\n */\n private processDollarDelimiters(\n line: string,\n inDollarBlock: boolean,\n dollarTag: string,\n ): { inDollarBlock: boolean; dollarTag: string } {\n const dollarMatch = line.match(/\\$([a-zA-Z_]*)\\$/g);\n if (!dollarMatch) return { inDollarBlock, dollarTag };\n\n let currentInBlock = inDollarBlock;\n let currentTag = dollarTag;\n\n for (const match of dollarMatch) {\n if (!currentInBlock) {\n currentInBlock = true;\n currentTag = match;\n } else if (match === currentTag) {\n currentInBlock = false;\n currentTag = \"\";\n }\n }\n\n return { inDollarBlock: currentInBlock, dollarTag: currentTag };\n }\n\n /**\n * Filter out comment-only statements\n */\n private isNonCommentStatement(statement: string): boolean {\n const withoutComments = statement.replace(/--.*$/gm, \"\").trim();\n return withoutComments.length > 0;\n }\n\n /**\n * Split SQL into individual statements for better error reporting\n * Handles $$ delimited blocks (functions, triggers) correctly\n */\n private splitSqlStatements(sql: string): string[] {\n const statements: string[] = [];\n let current = \"\";\n let inDollarBlock = false;\n let dollarTag = \"\";\n\n for (const line of sql.split(\"\\n\")) {\n const trimmedLine = line.trim();\n const isEmptyOrComment =\n trimmedLine === \"\" || trimmedLine.startsWith(\"--\");\n\n // Always append line to current statement\n current += line + \"\\n\";\n\n // Skip processing for empty lines and comments\n if (isEmptyOrComment) continue;\n\n // Update dollar block tracking\n const dollarState = this.processDollarDelimiters(\n line,\n inDollarBlock,\n dollarTag,\n );\n inDollarBlock = dollarState.inDollarBlock;\n dollarTag = dollarState.dollarTag;\n\n // Check for end of statement\n const isEndOfStatement = !inDollarBlock && trimmedLine.endsWith(\";\");\n if (isEndOfStatement && current.trim()) {\n statements.push(current.trim());\n current = \"\";\n }\n }\n\n // Add any remaining content\n if (current.trim()) {\n statements.push(current.trim());\n }\n\n return statements.filter((s) => this.isNonCommentStatement(s));\n }\n\n /**\n * Extract a short description from a SQL statement for logging\n */\n private getStatementDescription(statement: string): string {\n const firstLine =\n statement\n .split(\"\\n\")\n .find((l) => l.trim() && !l.trim().startsWith(\"--\"))\n ?.trim() ?? \"\";\n\n // Extract the type and name of the object being created/modified\n const patterns = [\n /^(CREATE\\s+(?:OR\\s+REPLACE\\s+)?(?:TABLE|INDEX|UNIQUE\\s+INDEX|TYPE|FUNCTION|TRIGGER|EXTENSION|SCHEMA|VIEW|POLICY))\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?([^\\s(]+)/i,\n /^(ALTER\\s+TABLE)\\s+([^\\s]+)/i,\n /^(DROP\\s+(?:TABLE|INDEX|TYPE|FUNCTION|TRIGGER|EXTENSION|SCHEMA|VIEW|POLICY))\\s+(?:IF\\s+EXISTS\\s+)?([^\\s(;]+)/i,\n /^(INSERT\\s+INTO)\\s+([^\\s(]+)/i,\n /^(COMMENT\\s+ON\\s+(?:TABLE|COLUMN|INDEX|FUNCTION|TYPE))\\s+([^\\s]+)/i,\n /^(GRANT|REVOKE)\\s+.+\\s+ON\\s+([^\\s]+)/i,\n ];\n\n for (const pattern of patterns) {\n const match = firstLine.match(pattern);\n if (match) {\n return `${match[1]} ${match[2]}`.slice(0, DESCRIPTION_MAX_LENGTH);\n }\n }\n\n const truncated = firstLine.slice(0, FALLBACK_DESCRIPTION_LENGTH);\n const suffix = firstLine.length > FALLBACK_DESCRIPTION_LENGTH ? \"...\" : \"\";\n return truncated + suffix;\n }\n\n /**\n * Execute SQL statements individually with better error reporting\n */\n private async executeSqlStatements(\n adapter: DatabaseAdapterType,\n sql: string,\n migrationVersion: string,\n ): Promise<void> {\n const statements = this.splitSqlStatements(sql);\n const total = statements.length;\n\n console.log(` → ${total} statements to execute`);\n\n for (let i = 0; i < statements.length; i++) {\n const statement = statements[i];\n const description = this.getStatementDescription(statement);\n\n try {\n await adapter.query!(statement);\n // Show progress at intervals or for significant operations\n const isInterval = (i + 1) % PROGRESS_LOG_INTERVAL === 0;\n const isLast = i === total - 1;\n const isSignificant = Boolean(\n description.match(/^(CREATE TABLE|CREATE FUNCTION|CREATE TRIGGER)/i),\n );\n if (isInterval || isLast || isSignificant) {\n console.log(` ✓ [${i + 1}/${total}] ${description}`);\n }\n } catch (error) {\n console.log(` ✗ [${i + 1}/${total}] ${description}`);\n\n // Extract clean error message\n const rawMessage = (error as Error).message;\n const errorMessage = rawMessage\n .replace(/^SQL Error:\\s*/i, \"\")\n .replace(/^Failed to execute query:.*?-\\s*/i, \"\")\n .slice(0, ERROR_MESSAGE_MAX_LENGTH);\n\n throw new DatabaseError(\n `Migration ${migrationVersion} failed at statement ${i + 1}/${total}:\\n` +\n ` Statement: ${description}\\n` +\n ` Error: ${errorMessage}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n { cause: error as Error },\n );\n }\n }\n }\n\n /**\n * Load SQL migration from file\n */\n private loadSqlMigration(migrationFile: MigrationFile): Migration {\n const sql = fs.readFileSync(migrationFile.filePath, \"utf-8\");\n const { upSQL, downSQL } = this.parseSqlSections(sql);\n\n return {\n version: migrationFile.version,\n name: migrationFile.name,\n up: async (adapter: DatabaseAdapterType) => {\n if (typeof adapter.query === \"function\") {\n await this.executeSqlStatements(\n adapter,\n upSQL,\n migrationFile.version,\n );\n }\n },\n down: async (adapter: DatabaseAdapterType) => {\n if (downSQL && typeof adapter.query === \"function\") {\n await this.executeSqlStatements(\n adapter,\n downSQL,\n migrationFile.version,\n );\n } else {\n console.warn(\n `[Migrations] No DOWN migration for ${migrationFile.version}`,\n );\n }\n },\n };\n }\n\n /**\n * Load TypeScript/JavaScript migration from file\n */\n private async loadJsMigration(\n migrationFile: MigrationFile,\n ): Promise<Migration> {\n const importPath = migrationFile.filePath.startsWith(\"/\")\n ? migrationFile.filePath\n : new URL(`file:///${migrationFile.filePath.replace(/\\\\/g, \"/\")}`).href;\n\n const migrationModule = await import(importPath);\n return {\n version: migrationFile.version,\n name: migrationFile.name,\n up: migrationModule.up ?? migrationModule.default?.up,\n down: migrationModule.down ?? migrationModule.default?.down,\n };\n }\n\n /**\n * Load migration from file\n */\n private async loadMigration(\n migrationFile: MigrationFile,\n ): Promise<Migration> {\n const ext = path.extname(migrationFile.filePath);\n\n switch (ext) {\n case \".sql\":\n return this.loadSqlMigration(migrationFile);\n case \".ts\":\n case \".js\":\n return this.loadJsMigration(migrationFile);\n default:\n throw new DatabaseError(\n `Unsupported migration file extension: ${ext}`,\n DATABASE_ERROR_CODES.INVALID_PARAMETERS,\n { cause: new Error(`Unsupported extension: ${ext}`) },\n );\n }\n }\n\n /**\n * Get applied migrations from database\n */\n private async getAppliedMigrations(): Promise<MigrationRecord[]> {\n try {\n if (typeof this.adapter.query === \"function\") {\n const result = await this.adapter.query<MigrationRecord>(\n `SELECT * FROM ${this.tableName} ORDER BY version ASC`,\n );\n // Handle both array results and postgres-style { rows: [] } results\n return Array.isArray(result)\n ? result\n : (result as unknown as { rows: MigrationRecord[] }).rows || [];\n }\n return [];\n } catch {\n // Table might not exist yet\n return [];\n }\n }\n\n /**\n * Record migration as applied\n */\n private async recordMigration(\n version: string,\n name: string,\n executionTime: number,\n filePath?: string,\n ): Promise<void> {\n if (typeof this.adapter.query === \"function\") {\n // Store relative path from migrations directory for portability\n const relativePath = filePath\n ? path.relative(this.migrationsPath, filePath)\n : null;\n\n await this.adapter.query(\n `INSERT INTO ${this.tableName} (version, name, file_path, execution_time) VALUES ($1, $2, $3, $4)`,\n [version, name, relativePath, executionTime],\n );\n }\n }\n\n /**\n * Remove migration record (for rollback)\n */\n private async unrecordMigration(version: string): Promise<void> {\n if (typeof this.adapter.query === \"function\") {\n await this.adapter.query(\n `DELETE FROM ${this.tableName} WHERE version = $1`,\n [version],\n );\n }\n }\n\n /**\n * Get migration status (applied and pending)\n */\n async status(): Promise<DatabaseResult<MigrationStatus>> {\n try {\n await this.initialize();\n\n const allMigrations = await this.discoverMigrations();\n const appliedMigrations = await this.getAppliedMigrations();\n const appliedVersions = new Set(appliedMigrations.map((m) => m.version));\n\n const pending = allMigrations\n .filter((m) => !appliedVersions.has(m.version))\n .map((m) => `${m.version}_${m.name}`);\n\n return success({\n applied: appliedMigrations,\n pending,\n });\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to get migration status: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n { cause: error as Error },\n ),\n );\n }\n }\n\n /**\n * Run all pending migrations\n */\n /* eslint-disable max-depth, complexity */\n async up(targetVersion?: string): Promise<DatabaseResult<number>> {\n try {\n await this.initialize();\n\n const allMigrations = await this.discoverMigrations();\n const appliedMigrations = await this.getAppliedMigrations();\n const appliedVersions = new Set(appliedMigrations.map((m) => m.version));\n\n let applied = 0;\n\n for (const migrationFile of allMigrations) {\n // Skip if already applied\n if (appliedVersions.has(migrationFile.version)) {\n continue;\n }\n\n // Stop if we've reached target version\n if (targetVersion && migrationFile.version > targetVersion) {\n break;\n }\n\n console.log(\n `[Migrations] Applying ${migrationFile.version}_${migrationFile.name}...`,\n );\n\n const migration = await this.loadMigration(migrationFile);\n const startTime = Date.now();\n\n // Run migration in transaction if possible\n if (typeof this.adapter.transaction === \"function\") {\n const txResult = await this.adapter.transaction(async () => {\n await migration.up(this.adapter);\n });\n // Check transaction result - transaction() returns failure() instead of throwing\n if (!txResult.success) {\n throw (\n txResult.error ??\n new DatabaseError(\n `Migration ${migration.version} failed`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n )\n );\n }\n } else {\n await migration.up(this.adapter);\n }\n\n const executionTime = Date.now() - startTime;\n\n // Record migration with file path for traceability\n await this.recordMigration(\n migration.version,\n migration.name,\n executionTime,\n migrationFile.filePath,\n );\n\n console.log(\n `[Migrations] Applied ${migration.version} in ${executionTime}ms`,\n );\n applied++;\n }\n\n return success(applied);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Migration failed: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n { cause: error as Error },\n ),\n );\n }\n }\n\n /**\n * Rollback last migration or rollback to specific version\n */\n async down(steps: number = 1): Promise<DatabaseResult<number>> {\n try {\n const appliedMigrations = await this.getAppliedMigrations();\n\n if (appliedMigrations.length === 0) {\n return success(0);\n }\n\n // Get migrations to rollback (in reverse order)\n const toRollback = appliedMigrations.slice(-steps).reverse();\n let rolledBack = 0;\n\n for (const appliedMigration of toRollback) {\n console.log(\n `[Migrations] Rolling back ${appliedMigration.version}_${appliedMigration.name}...`,\n );\n\n // Find migration file\n const allMigrations = await this.discoverMigrations();\n const migrationFile = allMigrations.find(\n (m) => m.version === appliedMigration.version,\n );\n\n if (!migrationFile) {\n console.warn(\n `[Migrations] Migration file not found for version ${appliedMigration.version}`,\n );\n continue;\n }\n\n const migration = await this.loadMigration(migrationFile);\n const startTime = Date.now();\n\n // Run rollback in transaction if possible\n if (typeof this.adapter.transaction === \"function\") {\n const txResult = await this.adapter.transaction(async () => {\n await migration.down(this.adapter);\n });\n // Check transaction result - transaction() returns failure() instead of throwing\n if (!txResult.success) {\n throw (\n txResult.error ??\n new DatabaseError(\n `Rollback ${appliedMigration.version} failed`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n )\n );\n }\n } else {\n await migration.down(this.adapter);\n }\n\n const executionTime = Date.now() - startTime;\n\n // Remove migration record\n await this.unrecordMigration(appliedMigration.version);\n\n console.log(\n `[Migrations] Rolled back ${appliedMigration.version} in ${executionTime}ms`,\n );\n rolledBack++;\n }\n\n return success(rolledBack);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Rollback failed: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n { cause: error as Error },\n ),\n );\n }\n }\n\n /**\n * Reset database (rollback all migrations)\n */\n async reset(): Promise<DatabaseResult<number>> {\n const appliedMigrations = await this.getAppliedMigrations();\n return this.down(appliedMigrations.length);\n }\n\n /**\n * Clear migration history (delete all records from tracking table)\n *\n * Use this to force fresh migrations in test/development environments\n * without rolling back actual database changes.\n *\n * @example\n * ```typescript\n * // Clear history and re-run all migrations\n * await migrationManager.clearHistory();\n * await migrationManager.up();\n * ```\n */\n async clearHistory(): Promise<DatabaseResult<void>> {\n try {\n if (typeof this.adapter.query === \"function\") {\n await this.adapter.query(`DELETE FROM ${this.tableName}`);\n }\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to clear migration history: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n { cause: error as Error },\n ),\n );\n }\n }\n}\n","/**\n * SeedManager - Database seeding for development and testing\n *\n * Manages database seeding with support for ordered execution,\n * seed history tracking, and idempotent seed operations.\n * Automatically discovers seed files from a specified directory.\n *\n * @example\n * ```typescript\n * const seedManager = new SeedManager({\n * adapter: sqlAdapter,\n * seedsPath: './seeds', // default\n * tableName: 'seed_history' // default\n * });\n *\n * // Run all seeds\n * await seedManager.run();\n *\n * // Run specific seed\n * await seedManager.run('users');\n *\n * // Clear all data (for testing)\n * await seedManager.reset();\n * ```\n */\n\nimport type {\n DatabaseAdapterType,\n DatabaseResult,\n Seed,\n SeedFile,\n SeedRecord,\n SeedManagerConfig,\n} from \"@plyaz/types/db\";\nimport { success, failure } from \"../utils/databaseResultHelpers\";\nimport { DatabaseError } from \"@plyaz/errors\";\nimport { DATABASE_ERROR_CODES } from \"@plyaz/types/errors\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\n\n/** Constants for statement description extraction */\nconst DESCRIPTION_MAX_LENGTH = 60;\nconst FALLBACK_DESCRIPTION_LENGTH = 50;\n\n/** Constants for progress logging */\nconst PROGRESS_LOG_INTERVAL = 10;\n\n/** Constants for error message truncation */\nconst ERROR_MESSAGE_MAX_LENGTH = 300;\n\n/**\n * SeedManager - Handles database seeding operations\n *\n * Discovers seed files, tracks seed history, and executes\n * seeds in order with support for cleanup and reset.\n */\nexport class SeedManager {\n private adapter: DatabaseAdapterType;\n private seedsPath: string;\n private tableName: string;\n private schema: string;\n private skipExisting: boolean;\n\n constructor(config: SeedManagerConfig) {\n this.adapter = config.adapter;\n this.seedsPath = path.resolve(config.seedsPath ?? \"./seeds\");\n this.schema = config.schema ?? \"public\";\n // Prefix table name with schema if not 'public'\n this.tableName =\n this.schema !== \"public\"\n ? `${this.schema}.${config.tableName ?? \"seed_history\"}`\n : (config.tableName ?? \"seed_history\");\n this.skipExisting = config.skipExisting ?? false;\n }\n\n /**\n * Initialize seeds tracking table if it doesn't exist\n */\n async initialize(): Promise<DatabaseResult<void>> {\n try {\n // Create seeds tracking table with file_path for traceability\n const createTableSQL = `\n CREATE TABLE IF NOT EXISTS ${this.tableName} (\n name VARCHAR(255) PRIMARY KEY,\n file_path VARCHAR(500),\n run_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n execution_time INTEGER NOT NULL\n )\n `;\n\n // Execute using adapter's raw query if available\n if (typeof this.adapter.query === \"function\") {\n await this.adapter.query(createTableSQL);\n\n // Add file_path column if it doesn't exist (for existing tables)\n await this.adapter\n .query(\n `\n DO $$\n BEGIN\n IF NOT EXISTS (\n SELECT 1 FROM information_schema.columns\n WHERE table_name = '${this.tableName.split(\".\").pop()}'\n AND column_name = 'file_path'\n ) THEN\n ALTER TABLE ${this.tableName} ADD COLUMN file_path VARCHAR(500);\n END IF;\n END $$;\n `,\n )\n .catch(() => {\n // Ignore if column already exists or syntax not supported\n });\n }\n\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to initialize seeds table: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.INIT_FAILED,\n { cause: error as Error },\n ),\n );\n }\n }\n\n /**\n * Discover seed files from seeds directory\n */\n private async discoverSeeds(): Promise<SeedFile[]> {\n if (!fs.existsSync(this.seedsPath)) {\n return [];\n }\n\n const files = fs.readdirSync(this.seedsPath);\n const seeds: SeedFile[] = [];\n\n for (const file of files) {\n // Match seed file pattern: {order}_{name}.{ts|js|sql}\n // Examples: 001_users.ts, 002_campaigns.js, 003_data.sql\n const match = file.match(/^(\\d+)_(.+)\\.(ts|js|sql)$/);\n if (match) {\n const [, order, name] = match;\n seeds.push({\n filePath: path.join(this.seedsPath, file),\n order: Number.parseInt(order, 10),\n name,\n });\n }\n }\n\n // Sort by order\n return seeds.sort((a, b) => a.order - b.order);\n }\n\n /**\n * Process dollar-quoted string delimiters ($$ or $tag$)\n */\n private processDollarDelimiters(\n line: string,\n inDollarBlock: boolean,\n dollarTag: string,\n ): { inDollarBlock: boolean; dollarTag: string } {\n const dollarMatch = line.match(/\\$([a-zA-Z_]*)\\$/g);\n if (!dollarMatch) return { inDollarBlock, dollarTag };\n\n let currentInBlock = inDollarBlock;\n let currentTag = dollarTag;\n\n for (const match of dollarMatch) {\n if (!currentInBlock) {\n currentInBlock = true;\n currentTag = match;\n } else if (match === currentTag) {\n currentInBlock = false;\n currentTag = \"\";\n }\n }\n\n return { inDollarBlock: currentInBlock, dollarTag: currentTag };\n }\n\n /**\n * Filter out comment-only statements\n */\n private isNonCommentStatement(statement: string): boolean {\n const withoutComments = statement.replace(/--.*$/gm, \"\").trim();\n return withoutComments.length > 0;\n }\n\n /**\n * Split SQL into individual statements for better error reporting\n */\n private splitSqlStatements(sql: string): string[] {\n const statements: string[] = [];\n let current = \"\";\n let inDollarBlock = false;\n let dollarTag = \"\";\n\n for (const line of sql.split(\"\\n\")) {\n const trimmedLine = line.trim();\n const isEmptyOrComment =\n trimmedLine === \"\" || trimmedLine.startsWith(\"--\");\n\n current += line + \"\\n\";\n if (isEmptyOrComment) continue;\n\n const dollarState = this.processDollarDelimiters(\n line,\n inDollarBlock,\n dollarTag,\n );\n inDollarBlock = dollarState.inDollarBlock;\n dollarTag = dollarState.dollarTag;\n\n if (!inDollarBlock && trimmedLine.endsWith(\";\") && current.trim()) {\n statements.push(current.trim());\n current = \"\";\n }\n }\n\n if (current.trim()) {\n statements.push(current.trim());\n }\n\n return statements.filter((s) => this.isNonCommentStatement(s));\n }\n\n /**\n * Extract a short description from a SQL statement for logging\n */\n private getStatementDescription(statement: string): string {\n const firstLine =\n statement\n .split(\"\\n\")\n .find((l) => l.trim() && !l.trim().startsWith(\"--\"))\n ?.trim() ?? \"\";\n\n const patterns = [\n /^(CREATE\\s+(?:OR\\s+REPLACE\\s+)?(?:TABLE|INDEX|UNIQUE\\s+INDEX|TYPE|FUNCTION|TRIGGER|EXTENSION|SCHEMA|VIEW|POLICY))\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?([^\\s(]+)/i,\n /^(ALTER\\s+TABLE)\\s+([^\\s]+)/i,\n /^(DROP\\s+(?:TABLE|INDEX|TYPE|FUNCTION|TRIGGER|EXTENSION|SCHEMA|VIEW|POLICY))\\s+(?:IF\\s+EXISTS\\s+)?([^\\s(;]+)/i,\n /^(INSERT\\s+INTO)\\s+([^\\s(]+)/i,\n /^(COMMENT\\s+ON\\s+(?:TABLE|COLUMN|INDEX|FUNCTION|TYPE))\\s+([^\\s]+)/i,\n /^(GRANT|REVOKE)\\s+.+\\s+ON\\s+([^\\s]+)/i,\n ];\n\n for (const pattern of patterns) {\n const match = firstLine.match(pattern);\n if (match) {\n return `${match[1]} ${match[2]}`.slice(0, DESCRIPTION_MAX_LENGTH);\n }\n }\n\n const truncated = firstLine.slice(0, FALLBACK_DESCRIPTION_LENGTH);\n const suffix = firstLine.length > FALLBACK_DESCRIPTION_LENGTH ? \"...\" : \"\";\n return truncated + suffix;\n }\n\n /**\n * Execute SQL statements individually with better error reporting\n */\n private async executeSqlStatements(\n sql: string,\n seedName: string,\n ): Promise<void> {\n const statements = this.splitSqlStatements(sql);\n const total = statements.length;\n\n console.log(` → ${total} statements to execute`);\n\n for (let i = 0; i < statements.length; i++) {\n const statement = statements[i];\n const description = this.getStatementDescription(statement);\n\n try {\n await this.adapter.query!(statement);\n const isInterval = (i + 1) % PROGRESS_LOG_INTERVAL === 0;\n const isLast = i === total - 1;\n const isSignificant = Boolean(description.match(/^(INSERT INTO)/i));\n if (isInterval || isLast || isSignificant) {\n console.log(` ✓ [${i + 1}/${total}] ${description}`);\n }\n } catch (error) {\n console.log(` ✗ [${i + 1}/${total}] ${description}`);\n\n const rawMessage = (error as Error).message;\n const errorMessage = rawMessage\n .replace(/^SQL Error:\\s*/i, \"\")\n .replace(/^Failed to execute query:.*?-\\s*/i, \"\")\n .slice(0, ERROR_MESSAGE_MAX_LENGTH);\n\n throw new DatabaseError(\n `Seed \"${seedName}\" failed at statement ${i + 1}/${total}:\\n` +\n ` Statement: ${description}\\n` +\n ` Error: ${errorMessage}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n { cause: error as Error },\n );\n }\n }\n }\n\n /**\n * Load SQL seed from file\n */\n private loadSqlSeed(seedFile: SeedFile): Seed {\n const sql = fs.readFileSync(seedFile.filePath, \"utf-8\");\n\n return {\n name: seedFile.name,\n run: async () => {\n if (typeof this.adapter.query === \"function\") {\n await this.executeSqlStatements(sql, seedFile.name);\n }\n },\n // SQL seeds don't have cleanup by default\n cleanup: undefined,\n };\n }\n\n /**\n * Load seed from file (supports .ts, .js, and .sql)\n */\n // eslint-disable-next-line complexity\n private async loadSeed(seedFile: SeedFile): Promise<Seed> {\n const ext = path.extname(seedFile.filePath);\n\n // Handle SQL seeds\n if (ext === \".sql\") {\n return this.loadSqlSeed(seedFile);\n }\n\n // Handle JS/TS seeds\n // Convert Windows paths to file:// URLs for ESM imports\n const importPath = seedFile.filePath.startsWith(\"/\")\n ? seedFile.filePath\n : new URL(`file:///${seedFile.filePath.replace(/\\\\/g, \"/\")}`).href;\n\n const seedModule = await import(importPath);\n return {\n name: seedFile.name,\n run:\n seedModule.run ??\n seedModule.default?.run ??\n seedModule.seed ??\n seedModule.default,\n cleanup: seedModule.cleanup ?? seedModule.default?.cleanup,\n };\n }\n\n /**\n * Get executed seeds from database\n */\n private async getExecutedSeeds(): Promise<SeedRecord[]> {\n try {\n if (typeof this.adapter.query === \"function\") {\n const result = await this.adapter.query<SeedRecord>(\n `SELECT * FROM ${this.tableName} ORDER BY run_at ASC`,\n );\n // Handle both array results and postgres-style { rows: [] } results\n return Array.isArray(result)\n ? result\n : (result as unknown as { rows: SeedRecord[] }).rows || [];\n }\n return [];\n } catch {\n // Table might not exist yet\n return [];\n }\n }\n\n /**\n * Record seed as executed\n */\n private async recordSeed(\n name: string,\n executionTime: number,\n filePath?: string,\n ): Promise<void> {\n if (typeof this.adapter.query === \"function\") {\n // Store relative path from seeds directory for portability\n const relativePath = filePath\n ? path.relative(this.seedsPath, filePath)\n : null;\n\n await this.adapter.query(\n `INSERT INTO ${this.tableName} (name, file_path, execution_time) VALUES ($1, $2, $3)\n ON CONFLICT (name) DO UPDATE SET run_at = CURRENT_TIMESTAMP, file_path = $2, execution_time = $3`,\n [name, relativePath, executionTime],\n );\n }\n }\n\n /**\n * Remove seed record (for reset)\n */\n private async unrecordSeed(name: string): Promise<void> {\n if (typeof this.adapter.query === \"function\") {\n await this.adapter.query(\n `DELETE FROM ${this.tableName} WHERE name = $1`,\n [name],\n );\n }\n }\n\n /**\n * Execute a seed function with optional transaction support\n */\n private async executeSeed(seed: Seed): Promise<void> {\n if (typeof this.adapter.transaction === \"function\") {\n const txResult = await this.adapter.transaction(async () => {\n await seed.run(this.adapter);\n });\n // Check transaction result - transaction() returns failure() instead of throwing\n if (!txResult.success) {\n throw (\n txResult.error ??\n new DatabaseError(\n `Seed ${seed.name} failed`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n )\n );\n }\n } else {\n await seed.run(this.adapter);\n }\n }\n\n /**\n * Check if a seed should be skipped and log if applicable\n */\n private shouldSkipSeed(\n seedFile: SeedFile,\n seedName: string | undefined,\n executedNames: Set<string>,\n ): boolean {\n if (seedName && seedFile.name !== seedName) return true;\n\n if (this.skipExisting && executedNames.has(seedFile.name)) {\n console.log(`[Seeds] Skipping ${seedFile.name} (already executed)`);\n return true;\n }\n\n return false;\n }\n\n /**\n * Run all seeds or a specific seed\n */\n async run(seedName?: string): Promise<DatabaseResult<number>> {\n try {\n await this.initialize();\n\n const allSeeds = await this.discoverSeeds();\n const executedSeeds = await this.getExecutedSeeds();\n const executedNames = new Set(executedSeeds.map((s) => s.name));\n\n let executed = 0;\n\n for (const seedFile of allSeeds) {\n if (this.shouldSkipSeed(seedFile, seedName, executedNames)) {\n continue;\n }\n\n console.log(`[Seeds] Running ${seedFile.name}...`);\n\n const seed = await this.loadSeed(seedFile);\n const startTime = Date.now();\n\n await this.executeSeed(seed);\n\n const executionTime = Date.now() - startTime;\n await this.recordSeed(seed.name, executionTime, seedFile.filePath);\n\n console.log(`[Seeds] Executed ${seed.name} in ${executionTime}ms`);\n executed++;\n\n if (seedName) break;\n }\n\n return success(executed);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Seed execution failed: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n { cause: error as Error },\n ),\n );\n }\n }\n\n /**\n * Execute cleanup function with optional transaction support\n */\n private async executeCleanup(seed: Seed): Promise<void> {\n if (!seed.cleanup) return;\n\n if (typeof this.adapter.transaction === \"function\") {\n const txResult = await this.adapter.transaction(async () => {\n await seed.cleanup!(this.adapter);\n });\n // Check transaction result - transaction() returns failure() instead of throwing\n if (!txResult.success) {\n throw (\n txResult.error ??\n new DatabaseError(\n `Seed cleanup for ${seed.name} failed`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n )\n );\n }\n } else {\n await seed.cleanup(this.adapter);\n }\n }\n\n /**\n * Reset all seeds (run cleanup functions)\n */\n async reset(): Promise<DatabaseResult<number>> {\n try {\n const allSeeds = await this.discoverSeeds();\n let cleaned = 0;\n\n // Run cleanup in reverse order\n for (const seedFile of allSeeds.reverse()) {\n console.log(`[Seeds] Cleaning up ${seedFile.name}...`);\n\n const seed = await this.loadSeed(seedFile);\n\n if (!seed.cleanup) {\n console.warn(`[Seeds] No cleanup function for ${seed.name}`);\n continue;\n }\n\n const startTime = Date.now();\n await this.executeCleanup(seed);\n const executionTime = Date.now() - startTime;\n\n await this.unrecordSeed(seed.name);\n\n console.log(`[Seeds] Cleaned ${seed.name} in ${executionTime}ms`);\n cleaned++;\n }\n\n return success(cleaned);\n } catch (error) {\n return failure(\n new DatabaseError(\n `Seed cleanup failed: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n { cause: error as Error },\n ),\n );\n }\n }\n\n /**\n * Get seed execution status\n */\n async status(): Promise<\n DatabaseResult<{ executed: SeedRecord[]; pending: string[] }>\n > {\n try {\n await this.initialize();\n\n const allSeeds = await this.discoverSeeds();\n const executedSeeds = await this.getExecutedSeeds();\n const executedNames = new Set(executedSeeds.map((s) => s.name));\n\n const pending = allSeeds\n .filter((s) => !executedNames.has(s.name))\n .map((s) => s.name);\n\n return success({\n executed: executedSeeds,\n pending,\n });\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to get seed status: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n { cause: error as Error },\n ),\n );\n }\n }\n\n /**\n * Clear seed history (doesn't clean data, just removes tracking records)\n */\n async clearHistory(): Promise<DatabaseResult<void>> {\n try {\n if (typeof this.adapter.query === \"function\") {\n await this.adapter.query(`DELETE FROM ${this.tableName}`);\n }\n return success();\n } catch (error) {\n return failure(\n new DatabaseError(\n `Failed to clear seed history: ${(error as Error).message}`,\n DATABASE_ERROR_CODES.QUERY_FAILED,\n { cause: error as Error },\n ),\n );\n }\n }\n}\n"]}