@digilogiclabs/platform-core 1.0.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters/postgres/PostgresDatabase.ts","../src/adapters/supabase/SupabaseDatabase.ts","../src/adapters/redis/RedisCache.ts","../src/adapters/upstash/UpstashCache.ts","../src/adapters/supabase-storage/SupabaseStorage.ts","../src/adapters/s3/S3Storage.ts","../src/adapters/smtp/SmtpEmail.ts","../src/adapters/resend/ResendEmail.ts","../src/adapters/bullmq/BullMQQueue.ts","../src/adapters/opentelemetry/OpenTelemetryTracing.ts","../src/interfaces/IHealth.ts","../src/interfaces/ILogger.ts","../src/interfaces/IMetrics.ts","../src/interfaces/ISecrets.ts","../src/interfaces/ITracing.ts","../src/config.ts","../src/adapters/memory/MemoryDatabase.ts","../src/adapters/memory/MemoryCache.ts","../src/adapters/memory/MemoryStorage.ts","../src/adapters/memory/MemoryEmail.ts","../src/adapters/memory/MemoryQueue.ts","../src/adapters/console/ConsoleEmail.ts","../src/factory.ts","../src/middleware/chain.ts","../src/middleware/builtin.ts","../src/hooks/registry.ts","../src/resilience/retry.ts","../src/resilience/circuit-breaker.ts","../src/resilience/timeout.ts","../src/resilience/bulkhead.ts","../src/resilience/fallback.ts","../src/http/health.ts","../src/http/metrics.ts","../src/adapters/supabase/index.ts","../src/adapters/postgres/index.ts","../src/adapters/upstash/index.ts","../src/adapters/redis/index.ts","../src/adapters/s3/index.ts","../src/adapters/supabase-storage/index.ts","../src/adapters/resend/index.ts","../src/adapters/smtp/index.ts","../src/adapters/bullmq/index.ts","../src/migrations/Migrator.ts","../src/migrations/helpers.ts"],"sourcesContent":["/**\r\n * PostgreSQL Direct Database Adapter\r\n *\r\n * Production implementation using pg (node-postgres) for direct PostgreSQL connections.\r\n * Provides true ACID transaction support, connection pooling, and prepared statements.\r\n *\r\n * This adapter is vendor-agnostic - works with any PostgreSQL-compatible database:\r\n * - PostgreSQL (self-hosted or managed)\r\n * - Amazon RDS PostgreSQL\r\n * - Azure Database for PostgreSQL\r\n * - Google Cloud SQL for PostgreSQL\r\n * - CockroachDB (PostgreSQL wire protocol)\r\n * - YugabyteDB\r\n * - Neon, Supabase (direct connection, not REST)\r\n */\r\n\r\nimport type { Pool, PoolClient, PoolConfig, QueryResult as PgQueryResult } from 'pg';\r\nimport { IDatabase, IQueryBuilder, QueryResult } from '../../interfaces/IDatabase';\r\n\r\nexport interface PostgresConfig {\r\n /** Connection string (postgresql://user:pass@host:port/database) */\r\n connectionString?: string;\r\n\r\n /** Host name */\r\n host?: string;\r\n\r\n /** Port number */\r\n port?: number;\r\n\r\n /** Database name */\r\n database?: string;\r\n\r\n /** Username */\r\n user?: string;\r\n\r\n /** Password */\r\n password?: string;\r\n\r\n /** SSL configuration */\r\n ssl?: boolean | { rejectUnauthorized?: boolean; ca?: string };\r\n\r\n /** Maximum number of connections in pool */\r\n max?: number;\r\n\r\n /** Idle timeout in milliseconds */\r\n idleTimeoutMillis?: number;\r\n\r\n /** Connection timeout in milliseconds */\r\n connectionTimeoutMillis?: number;\r\n\r\n /** Statement timeout in milliseconds (0 = no limit) */\r\n statementTimeout?: number;\r\n\r\n /** Query timeout in milliseconds (0 = no limit) */\r\n queryTimeout?: number;\r\n\r\n /** Application name for connection identification */\r\n applicationName?: string;\r\n}\r\n\r\n/**\r\n * Convert our config to pg pool config\r\n */\r\nfunction toPoolConfig(config: PostgresConfig): PoolConfig {\r\n const poolConfig: PoolConfig = {};\r\n\r\n if (config.connectionString) {\r\n poolConfig.connectionString = config.connectionString;\r\n } else {\r\n poolConfig.host = config.host;\r\n poolConfig.port = config.port;\r\n poolConfig.database = config.database;\r\n poolConfig.user = config.user;\r\n poolConfig.password = config.password;\r\n }\r\n\r\n if (config.ssl !== undefined) {\r\n poolConfig.ssl = config.ssl;\r\n }\r\n\r\n poolConfig.max = config.max ?? 10;\r\n poolConfig.idleTimeoutMillis = config.idleTimeoutMillis ?? 30000;\r\n poolConfig.connectionTimeoutMillis = config.connectionTimeoutMillis ?? 10000;\r\n poolConfig.application_name = config.applicationName ?? 'platform-core';\r\n\r\n // Statement timeout\r\n if (config.statementTimeout) {\r\n poolConfig.statement_timeout = config.statementTimeout;\r\n }\r\n\r\n // Query timeout\r\n if (config.queryTimeout) {\r\n poolConfig.query_timeout = config.queryTimeout;\r\n }\r\n\r\n return poolConfig;\r\n}\r\n\r\nexport class PostgresDatabase implements IDatabase {\r\n private pool: Pool;\r\n private config: PostgresConfig;\r\n\r\n constructor(pool: Pool, config: PostgresConfig = {}) {\r\n this.pool = pool;\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Create a PostgresDatabase from configuration\r\n */\r\n static async create(config: PostgresConfig): Promise<PostgresDatabase> {\r\n // Dynamic import to keep pg as optional peer dependency\r\n const { Pool } = await import('pg');\r\n const poolConfig = toPoolConfig(config);\r\n const pool = new Pool(poolConfig);\r\n\r\n // Test connection\r\n const client = await pool.connect();\r\n client.release();\r\n\r\n return new PostgresDatabase(pool, config);\r\n }\r\n\r\n /**\r\n * Create from environment variables\r\n */\r\n static async fromEnv(): Promise<PostgresDatabase> {\r\n const config: PostgresConfig = {\r\n connectionString: process.env.DATABASE_URL,\r\n host: process.env.POSTGRES_HOST ?? process.env.PGHOST,\r\n port: parseInt(process.env.POSTGRES_PORT ?? process.env.PGPORT ?? '5432', 10),\r\n database: process.env.POSTGRES_DATABASE ?? process.env.PGDATABASE,\r\n user: process.env.POSTGRES_USER ?? process.env.PGUSER,\r\n password: process.env.POSTGRES_PASSWORD ?? process.env.PGPASSWORD,\r\n max: parseInt(process.env.POSTGRES_POOL_MAX ?? '10', 10),\r\n ssl:\r\n process.env.POSTGRES_SSL === 'true'\r\n ? { rejectUnauthorized: process.env.POSTGRES_SSL_REJECT_UNAUTHORIZED !== 'false' }\r\n : undefined,\r\n applicationName: process.env.POSTGRES_APP_NAME ?? 'platform-core',\r\n };\r\n\r\n return PostgresDatabase.create(config);\r\n }\r\n\r\n from<T = unknown>(table: string): IQueryBuilder<T> {\r\n return new PostgresQueryBuilder<T>(this.pool, table);\r\n }\r\n\r\n async raw<T = unknown>(sql: string, params?: unknown[]): Promise<QueryResult<T>> {\r\n try {\r\n const result: PgQueryResult = await this.pool.query(sql, params);\r\n return {\r\n data: result.rows as T[],\r\n count: result.rowCount ?? undefined,\r\n };\r\n } catch (error) {\r\n return {\r\n data: [],\r\n error: error instanceof Error ? error : new Error(String(error)),\r\n };\r\n }\r\n }\r\n\r\n /**\r\n * Execute a function within a database transaction.\r\n * Provides true ACID guarantees - either all operations succeed or all are rolled back.\r\n */\r\n async transaction<T>(fn: (tx: IDatabase) => Promise<T>): Promise<T> {\r\n const client = await this.pool.connect();\r\n\r\n try {\r\n await client.query('BEGIN');\r\n\r\n // Create a transaction-scoped database instance\r\n const txDatabase = new TransactionDatabase(client);\r\n\r\n const result = await fn(txDatabase);\r\n\r\n await client.query('COMMIT');\r\n return result;\r\n } catch (error) {\r\n await client.query('ROLLBACK');\r\n throw error;\r\n } finally {\r\n client.release();\r\n }\r\n }\r\n\r\n async healthCheck(): Promise<boolean> {\r\n try {\r\n const result = await this.pool.query('SELECT 1 as health');\r\n return result.rows.length > 0;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n async close(): Promise<void> {\r\n await this.pool.end();\r\n }\r\n\r\n /**\r\n * Get pool statistics for monitoring\r\n */\r\n getPoolStats(): {\r\n totalCount: number;\r\n idleCount: number;\r\n waitingCount: number;\r\n } {\r\n return {\r\n totalCount: this.pool.totalCount,\r\n idleCount: this.pool.idleCount,\r\n waitingCount: this.pool.waitingCount,\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Transaction-scoped database that uses a single client connection\r\n */\r\nclass TransactionDatabase implements IDatabase {\r\n constructor(private client: PoolClient) {}\r\n\r\n from<T = unknown>(table: string): IQueryBuilder<T> {\r\n return new PostgresQueryBuilder<T>(this.client, table);\r\n }\r\n\r\n async raw<T = unknown>(sql: string, params?: unknown[]): Promise<QueryResult<T>> {\r\n try {\r\n const result = await this.client.query(sql, params);\r\n return {\r\n data: result.rows as T[],\r\n count: result.rowCount ?? undefined,\r\n };\r\n } catch (error) {\r\n return {\r\n data: [],\r\n error: error instanceof Error ? error : new Error(String(error)),\r\n };\r\n }\r\n }\r\n\r\n async transaction<T>(fn: (tx: IDatabase) => Promise<T>): Promise<T> {\r\n // Nested transaction using savepoint\r\n const savepointName = `sp_${Date.now()}_${Math.random().toString(36).slice(2)}`;\r\n\r\n try {\r\n await this.client.query(`SAVEPOINT ${savepointName}`);\r\n const result = await fn(this);\r\n await this.client.query(`RELEASE SAVEPOINT ${savepointName}`);\r\n return result;\r\n } catch (error) {\r\n await this.client.query(`ROLLBACK TO SAVEPOINT ${savepointName}`);\r\n throw error;\r\n }\r\n }\r\n\r\n async healthCheck(): Promise<boolean> {\r\n try {\r\n await this.client.query('SELECT 1');\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n async close(): Promise<void> {\r\n // Transaction database doesn't own the client, so don't close\r\n }\r\n}\r\n\r\n/**\r\n * PostgreSQL Query Builder\r\n */\r\nclass PostgresQueryBuilder<T = unknown> implements IQueryBuilder<T> {\r\n private client: Pool | PoolClient;\r\n private tableName: string;\r\n private _select: string[] = ['*'];\r\n private _where: Array<{ column: string; operator: string; value: unknown }> = [];\r\n private _whereIn: Array<{ column: string; values: unknown[] }> = [];\r\n private _orderBy: { column: string; direction: 'asc' | 'desc' } | null = null;\r\n private _limit: number | null = null;\r\n private _offset: number = 0;\r\n private _insertData: Partial<T>[] | null = null;\r\n private _updateData: Partial<T> | null = null;\r\n private _deleteFlag: boolean = false;\r\n private _returning: string[] = ['*'];\r\n\r\n constructor(client: Pool | PoolClient, tableName: string) {\r\n this.client = client;\r\n this.tableName = this.escapeIdentifier(tableName);\r\n }\r\n\r\n select(columns?: string | string[]): IQueryBuilder<T> {\r\n if (columns) {\r\n this._select = Array.isArray(columns) ? columns : [columns];\r\n }\r\n return this;\r\n }\r\n\r\n insert(data: Partial<T> | Partial<T>[]): IQueryBuilder<T> {\r\n this._insertData = Array.isArray(data) ? data : [data];\r\n return this;\r\n }\r\n\r\n update(data: Partial<T>): IQueryBuilder<T> {\r\n this._updateData = data;\r\n return this;\r\n }\r\n\r\n delete(): IQueryBuilder<T> {\r\n this._deleteFlag = true;\r\n return this;\r\n }\r\n\r\n where(column: string, operator: string, value: unknown): IQueryBuilder<T> {\r\n this._where.push({ column, operator, value });\r\n return this;\r\n }\r\n\r\n whereIn(column: string, values: unknown[]): IQueryBuilder<T> {\r\n this._whereIn.push({ column, values });\r\n return this;\r\n }\r\n\r\n orderBy(column: string, direction: 'asc' | 'desc' = 'asc'): IQueryBuilder<T> {\r\n this._orderBy = { column, direction };\r\n return this;\r\n }\r\n\r\n limit(count: number): IQueryBuilder<T> {\r\n this._limit = count;\r\n return this;\r\n }\r\n\r\n offset(count: number): IQueryBuilder<T> {\r\n this._offset = count;\r\n return this;\r\n }\r\n\r\n async single(): Promise<{ data: T | null; error?: Error }> {\r\n this._limit = 1;\r\n const result = await this.execute();\r\n\r\n if (result.error) {\r\n return { data: null, error: result.error };\r\n }\r\n\r\n return { data: result.data[0] ?? null };\r\n }\r\n\r\n async execute(): Promise<QueryResult<T>> {\r\n try {\r\n if (this._insertData) {\r\n return await this.executeInsert();\r\n }\r\n\r\n if (this._updateData) {\r\n return await this.executeUpdate();\r\n }\r\n\r\n if (this._deleteFlag) {\r\n return await this.executeDelete();\r\n }\r\n\r\n return await this.executeSelect();\r\n } catch (error) {\r\n return {\r\n data: [],\r\n error: error instanceof Error ? error : new Error(String(error)),\r\n };\r\n }\r\n }\r\n\r\n private async executeSelect(): Promise<QueryResult<T>> {\r\n const params: unknown[] = [];\r\n let paramIndex = 1;\r\n\r\n // Build SELECT clause\r\n const selectClause = this._select.map((col) => this.escapeIdentifier(col)).join(', ');\r\n let sql = `SELECT ${selectClause} FROM ${this.tableName}`;\r\n\r\n // Build WHERE clause\r\n const whereClauses: string[] = [];\r\n\r\n for (const { column, operator, value } of this._where) {\r\n whereClauses.push(`${this.escapeIdentifier(column)} ${this.mapOperator(operator)} $${paramIndex++}`);\r\n params.push(value);\r\n }\r\n\r\n for (const { column, values } of this._whereIn) {\r\n const placeholders = values.map(() => `$${paramIndex++}`).join(', ');\r\n whereClauses.push(`${this.escapeIdentifier(column)} IN (${placeholders})`);\r\n params.push(...values);\r\n }\r\n\r\n if (whereClauses.length > 0) {\r\n sql += ` WHERE ${whereClauses.join(' AND ')}`;\r\n }\r\n\r\n // Build ORDER BY\r\n if (this._orderBy) {\r\n sql += ` ORDER BY ${this.escapeIdentifier(this._orderBy.column)} ${this._orderBy.direction.toUpperCase()}`;\r\n }\r\n\r\n // Build LIMIT and OFFSET\r\n if (this._limit !== null) {\r\n sql += ` LIMIT $${paramIndex++}`;\r\n params.push(this._limit);\r\n }\r\n\r\n if (this._offset > 0) {\r\n sql += ` OFFSET $${paramIndex++}`;\r\n params.push(this._offset);\r\n }\r\n\r\n const result = await this.client.query(sql, params);\r\n return {\r\n data: result.rows as T[],\r\n count: result.rowCount ?? undefined,\r\n };\r\n }\r\n\r\n private async executeInsert(): Promise<QueryResult<T>> {\r\n if (!this._insertData || this._insertData.length === 0) {\r\n return { data: [] };\r\n }\r\n\r\n const params: unknown[] = [];\r\n let paramIndex = 1;\r\n\r\n // Get all unique columns from the data\r\n const columns = new Set<string>();\r\n for (const row of this._insertData) {\r\n Object.keys(row as object).forEach((key) => columns.add(key));\r\n }\r\n const columnList = Array.from(columns);\r\n\r\n // Build column list\r\n const columnClause = columnList.map((col) => this.escapeIdentifier(col)).join(', ');\r\n\r\n // Build values\r\n const valueRows: string[] = [];\r\n for (const row of this._insertData) {\r\n const rowValues: string[] = [];\r\n for (const col of columnList) {\r\n rowValues.push(`$${paramIndex++}`);\r\n params.push((row as Record<string, unknown>)[col] ?? null);\r\n }\r\n valueRows.push(`(${rowValues.join(', ')})`);\r\n }\r\n\r\n const sql = `INSERT INTO ${this.tableName} (${columnClause}) VALUES ${valueRows.join(', ')} RETURNING ${this._returning.join(', ')}`;\r\n\r\n const result = await this.client.query(sql, params);\r\n return {\r\n data: result.rows as T[],\r\n count: result.rowCount ?? undefined,\r\n };\r\n }\r\n\r\n private async executeUpdate(): Promise<QueryResult<T>> {\r\n if (!this._updateData) {\r\n return { data: [] };\r\n }\r\n\r\n const params: unknown[] = [];\r\n let paramIndex = 1;\r\n\r\n // Build SET clause\r\n const setClauses: string[] = [];\r\n for (const [key, value] of Object.entries(this._updateData as object)) {\r\n setClauses.push(`${this.escapeIdentifier(key)} = $${paramIndex++}`);\r\n params.push(value);\r\n }\r\n\r\n let sql = `UPDATE ${this.tableName} SET ${setClauses.join(', ')}`;\r\n\r\n // Build WHERE clause\r\n const whereClauses: string[] = [];\r\n\r\n for (const { column, operator, value } of this._where) {\r\n whereClauses.push(`${this.escapeIdentifier(column)} ${this.mapOperator(operator)} $${paramIndex++}`);\r\n params.push(value);\r\n }\r\n\r\n for (const { column, values } of this._whereIn) {\r\n const placeholders = values.map(() => `$${paramIndex++}`).join(', ');\r\n whereClauses.push(`${this.escapeIdentifier(column)} IN (${placeholders})`);\r\n params.push(...values);\r\n }\r\n\r\n if (whereClauses.length > 0) {\r\n sql += ` WHERE ${whereClauses.join(' AND ')}`;\r\n }\r\n\r\n sql += ` RETURNING ${this._returning.join(', ')}`;\r\n\r\n const result = await this.client.query(sql, params);\r\n return {\r\n data: result.rows as T[],\r\n count: result.rowCount ?? undefined,\r\n };\r\n }\r\n\r\n private async executeDelete(): Promise<QueryResult<T>> {\r\n const params: unknown[] = [];\r\n let paramIndex = 1;\r\n\r\n let sql = `DELETE FROM ${this.tableName}`;\r\n\r\n // Build WHERE clause\r\n const whereClauses: string[] = [];\r\n\r\n for (const { column, operator, value } of this._where) {\r\n whereClauses.push(`${this.escapeIdentifier(column)} ${this.mapOperator(operator)} $${paramIndex++}`);\r\n params.push(value);\r\n }\r\n\r\n for (const { column, values } of this._whereIn) {\r\n const placeholders = values.map(() => `$${paramIndex++}`).join(', ');\r\n whereClauses.push(`${this.escapeIdentifier(column)} IN (${placeholders})`);\r\n params.push(...values);\r\n }\r\n\r\n if (whereClauses.length > 0) {\r\n sql += ` WHERE ${whereClauses.join(' AND ')}`;\r\n }\r\n\r\n sql += ` RETURNING ${this._returning.join(', ')}`;\r\n\r\n const result = await this.client.query(sql, params);\r\n return {\r\n data: result.rows as T[],\r\n count: result.rowCount ?? undefined,\r\n };\r\n }\r\n\r\n private escapeIdentifier(identifier: string): string {\r\n // Handle special cases\r\n if (identifier === '*') return '*';\r\n\r\n // Handle schema.table notation\r\n if (identifier.includes('.')) {\r\n return identifier\r\n .split('.')\r\n .map((part) => `\"${part.replace(/\"/g, '\"\"')}\"`)\r\n .join('.');\r\n }\r\n\r\n // Escape identifier with double quotes\r\n return `\"${identifier.replace(/\"/g, '\"\"')}\"`;\r\n }\r\n\r\n private mapOperator(operator: string): string {\r\n switch (operator.toLowerCase()) {\r\n case '=':\r\n case '==':\r\n return '=';\r\n case '!=':\r\n case '<>':\r\n return '<>';\r\n case '<':\r\n return '<';\r\n case '<=':\r\n return '<=';\r\n case '>':\r\n return '>';\r\n case '>=':\r\n return '>=';\r\n case 'like':\r\n return 'LIKE';\r\n case 'ilike':\r\n return 'ILIKE';\r\n case 'is':\r\n return 'IS';\r\n case 'is not':\r\n return 'IS NOT';\r\n default:\r\n return '=';\r\n }\r\n }\r\n}\r\n","/**\r\n * Supabase Database Adapter\r\n * Production implementation using Supabase as the database provider\r\n */\r\n\r\nimport type { SupabaseClient } from '@supabase/supabase-js';\r\nimport { IDatabase, IQueryBuilder, QueryResult } from '../../interfaces/IDatabase';\r\n\r\nexport interface SupabaseDatabaseConfig {\r\n url: string;\r\n anonKey: string;\r\n serviceRoleKey?: string;\r\n}\r\n\r\nexport class SupabaseDatabase implements IDatabase {\r\n private client: SupabaseClient;\r\n\r\n constructor(client: SupabaseClient) {\r\n this.client = client;\r\n }\r\n\r\n from<T = unknown>(table: string): IQueryBuilder<T> {\r\n return new SupabaseQueryBuilder<T>(this.client, table);\r\n }\r\n\r\n async raw<T = unknown>(sql: string, params?: unknown[]): Promise<QueryResult<T>> {\r\n // Supabase RPC for raw SQL requires a database function\r\n // This is a limitation - prefer using from() for queries\r\n console.warn('SupabaseDatabase.raw() requires an RPC function. Consider using from() instead.');\r\n return { data: [] };\r\n }\r\n\r\n async transaction<T>(fn: (tx: IDatabase) => Promise<T>): Promise<T> {\r\n // Supabase REST API doesn't support true transactions\r\n // Operations run sequentially but not atomically\r\n console.warn('Supabase REST API does not support true transactions. Operations are not atomic.');\r\n return fn(this);\r\n }\r\n\r\n async healthCheck(): Promise<boolean> {\r\n try {\r\n // Try a simple query to check connectivity\r\n const { error } = await this.client.from('_health_check').select('*').limit(1);\r\n // Table may not exist, but connection worked if no network error\r\n // PGRST116 = table not found, which is OK for health check\r\n return !error || error.code === 'PGRST116';\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n async close(): Promise<void> {\r\n // Supabase client doesn't need explicit closing\r\n }\r\n}\r\n\r\nclass SupabaseQueryBuilder<T = unknown> implements IQueryBuilder<T> {\r\n private client: SupabaseClient;\r\n private tableName: string;\r\n private _select: string = '*';\r\n private _where: Array<{ column: string; operator: string; value: unknown }> = [];\r\n private _whereIn: Array<{ column: string; values: unknown[] }> = [];\r\n private _orderBy: { column: string; direction: 'asc' | 'desc' } | null = null;\r\n private _limit: number | null = null;\r\n private _offset: number = 0;\r\n private _insertData: Partial<T>[] | null = null;\r\n private _updateData: Partial<T> | null = null;\r\n private _deleteFlag: boolean = false;\r\n\r\n constructor(client: SupabaseClient, tableName: string) {\r\n this.client = client;\r\n this.tableName = tableName;\r\n }\r\n\r\n select(columns?: string | string[]): IQueryBuilder<T> {\r\n if (columns) {\r\n this._select = Array.isArray(columns) ? columns.join(', ') : columns;\r\n }\r\n return this;\r\n }\r\n\r\n insert(data: Partial<T> | Partial<T>[]): IQueryBuilder<T> {\r\n this._insertData = Array.isArray(data) ? data : [data];\r\n return this;\r\n }\r\n\r\n update(data: Partial<T>): IQueryBuilder<T> {\r\n this._updateData = data;\r\n return this;\r\n }\r\n\r\n delete(): IQueryBuilder<T> {\r\n this._deleteFlag = true;\r\n return this;\r\n }\r\n\r\n where(column: string, operator: string, value: unknown): IQueryBuilder<T> {\r\n this._where.push({ column, operator, value });\r\n return this;\r\n }\r\n\r\n whereIn(column: string, values: unknown[]): IQueryBuilder<T> {\r\n this._whereIn.push({ column, values });\r\n return this;\r\n }\r\n\r\n orderBy(column: string, direction: 'asc' | 'desc' = 'asc'): IQueryBuilder<T> {\r\n this._orderBy = { column, direction };\r\n return this;\r\n }\r\n\r\n limit(count: number): IQueryBuilder<T> {\r\n this._limit = count;\r\n return this;\r\n }\r\n\r\n offset(count: number): IQueryBuilder<T> {\r\n this._offset = count;\r\n return this;\r\n }\r\n\r\n async single(): Promise<{ data: T | null; error?: Error }> {\r\n const query = this.buildSelectQuery().limit(1).single();\r\n const { data, error } = await query;\r\n\r\n if (error && error.code !== 'PGRST116') {\r\n return { data: null, error: new Error(error.message) };\r\n }\r\n\r\n return { data: data as T | null };\r\n }\r\n\r\n async execute(): Promise<QueryResult<T>> {\r\n // Handle insert\r\n if (this._insertData) {\r\n const { data, error } = await this.client\r\n .from(this.tableName)\r\n .insert(this._insertData as Record<string, unknown>[])\r\n .select();\r\n\r\n if (error) {\r\n return { data: [], error: new Error(error.message) };\r\n }\r\n return { data: (data || []) as T[] };\r\n }\r\n\r\n // Handle update\r\n if (this._updateData) {\r\n let query = this.client\r\n .from(this.tableName)\r\n .update(this._updateData as Record<string, unknown>);\r\n\r\n query = this.applyFilters(query);\r\n const { data, error } = await query.select();\r\n\r\n if (error) {\r\n return { data: [], error: new Error(error.message) };\r\n }\r\n return { data: (data || []) as T[], count: data?.length };\r\n }\r\n\r\n // Handle delete\r\n if (this._deleteFlag) {\r\n let query = this.client.from(this.tableName).delete();\r\n query = this.applyFilters(query);\r\n const { data, error } = await query.select();\r\n\r\n if (error) {\r\n return { data: [], error: new Error(error.message) };\r\n }\r\n return { data: (data || []) as T[], count: data?.length };\r\n }\r\n\r\n // Handle select\r\n const query = this.buildSelectQuery();\r\n const { data, error, count } = await query;\r\n\r\n if (error) {\r\n return { data: [], error: new Error(error.message) };\r\n }\r\n\r\n return { data: (data || []) as T[], count: count ?? undefined };\r\n }\r\n\r\n private buildSelectQuery() {\r\n let query = this.client.from(this.tableName).select(this._select);\r\n\r\n // Apply where conditions\r\n query = this.applyFilters(query);\r\n\r\n // Apply ordering\r\n if (this._orderBy) {\r\n query = query.order(this._orderBy.column, { ascending: this._orderBy.direction === 'asc' });\r\n }\r\n\r\n // Apply pagination\r\n if (this._limit !== null) {\r\n query = query.limit(this._limit);\r\n }\r\n\r\n if (this._offset > 0) {\r\n query = query.range(this._offset, this._offset + (this._limit || 1000) - 1);\r\n }\r\n\r\n return query;\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n private applyFilters(query: any): any {\r\n let result = query;\r\n\r\n // Apply where conditions\r\n for (const { column, operator, value } of this._where) {\r\n result = this.applyOperator(result, column, operator, value);\r\n }\r\n\r\n // Apply whereIn conditions\r\n for (const { column, values } of this._whereIn) {\r\n result = result.in(column, values);\r\n }\r\n\r\n return result;\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n private applyOperator(query: any, column: string, operator: string, value: unknown): any {\r\n switch (operator) {\r\n case '=':\r\n case '==':\r\n return query.eq(column, value);\r\n case '!=':\r\n case '<>':\r\n return query.neq(column, value);\r\n case '<':\r\n return query.lt(column, value);\r\n case '<=':\r\n return query.lte(column, value);\r\n case '>':\r\n return query.gt(column, value);\r\n case '>=':\r\n return query.gte(column, value);\r\n case 'like':\r\n return query.like(column, value as string);\r\n case 'ilike':\r\n return query.ilike(column, value as string);\r\n case 'is':\r\n return query.is(column, value);\r\n case 'is not':\r\n return query.not(column, 'is', value);\r\n default:\r\n return query.eq(column, value);\r\n }\r\n }\r\n}\r\n","/**\r\n * Redis Direct Cache Adapter\r\n *\r\n * Production implementation using ioredis for direct Redis connections.\r\n * Provides lower latency than REST-based solutions, true pub/sub support,\r\n * and full Redis command set.\r\n *\r\n * This adapter is vendor-agnostic - works with any Redis-compatible server:\r\n * - Redis (self-hosted or managed)\r\n * - Amazon ElastiCache for Redis\r\n * - Azure Cache for Redis\r\n * - Google Cloud Memorystore for Redis\r\n * - Redis Enterprise\r\n * - KeyDB\r\n * - DragonflyDB\r\n */\r\n\r\nimport type { Redis as IORedis, RedisOptions as IORedisOptions } from 'ioredis';\r\nimport { ICache } from '../../interfaces/ICache';\r\n\r\nexport interface RedisConfig {\r\n /** Connection URL (redis://user:pass@host:port/db) */\r\n url?: string;\r\n\r\n /** Host name */\r\n host?: string;\r\n\r\n /** Port number */\r\n port?: number;\r\n\r\n /** Password */\r\n password?: string;\r\n\r\n /** Database number (0-15) */\r\n db?: number;\r\n\r\n /** Username (Redis 6+) */\r\n username?: string;\r\n\r\n /** Connection name for identification */\r\n name?: string;\r\n\r\n /** Key prefix for namespacing */\r\n keyPrefix?: string;\r\n\r\n /** Enable TLS */\r\n tls?: boolean | { rejectUnauthorized?: boolean; ca?: string };\r\n\r\n /** Connection timeout in milliseconds */\r\n connectTimeout?: number;\r\n\r\n /** Command timeout in milliseconds */\r\n commandTimeout?: number;\r\n\r\n /** Keep alive timeout */\r\n keepAlive?: number;\r\n\r\n /** Max retries per request */\r\n maxRetriesPerRequest?: number;\r\n\r\n /** Enable auto-reconnect */\r\n autoReconnect?: boolean;\r\n\r\n /** Lazy connect (don't connect until first command) */\r\n lazyConnect?: boolean;\r\n\r\n /** Enable offline queue */\r\n enableOfflineQueue?: boolean;\r\n\r\n /** Sentinel configuration for HA */\r\n sentinel?: {\r\n sentinels: Array<{ host: string; port: number }>;\r\n name: string;\r\n password?: string;\r\n };\r\n\r\n /** Cluster configuration */\r\n cluster?: {\r\n nodes: Array<{ host: string; port: number }>;\r\n options?: {\r\n scaleReads?: 'master' | 'slave' | 'all';\r\n maxRedirections?: number;\r\n };\r\n };\r\n}\r\n\r\n/**\r\n * Convert our config to ioredis options\r\n */\r\nfunction toIORedisOptions(config: RedisConfig): IORedisOptions | string {\r\n if (config.url) {\r\n return config.url;\r\n }\r\n\r\n const options: IORedisOptions = {};\r\n\r\n if (config.host) options.host = config.host;\r\n if (config.port) options.port = config.port;\r\n if (config.password) options.password = config.password;\r\n if (config.db !== undefined) options.db = config.db;\r\n if (config.username) options.username = config.username;\r\n if (config.name) options.name = config.name;\r\n if (config.keyPrefix) options.keyPrefix = config.keyPrefix;\r\n if (config.connectTimeout) options.connectTimeout = config.connectTimeout;\r\n if (config.commandTimeout) options.commandTimeout = config.commandTimeout;\r\n if (config.keepAlive) options.keepAlive = config.keepAlive;\r\n if (config.maxRetriesPerRequest !== undefined) {\r\n options.maxRetriesPerRequest = config.maxRetriesPerRequest;\r\n }\r\n if (config.lazyConnect) options.lazyConnect = config.lazyConnect;\r\n if (config.enableOfflineQueue !== undefined) {\r\n options.enableOfflineQueue = config.enableOfflineQueue;\r\n }\r\n\r\n // TLS configuration\r\n if (config.tls) {\r\n if (typeof config.tls === 'boolean') {\r\n options.tls = {};\r\n } else {\r\n options.tls = {\r\n rejectUnauthorized: config.tls.rejectUnauthorized,\r\n ca: config.tls.ca ? [config.tls.ca] : undefined,\r\n };\r\n }\r\n }\r\n\r\n return options;\r\n}\r\n\r\nexport class RedisCache implements ICache {\r\n private client: IORedis;\r\n private subscriberClient: IORedis | null = null;\r\n private config: RedisConfig;\r\n private subscriptions: Map<string, Set<(message: string) => void>> = new Map();\r\n\r\n constructor(client: IORedis, config: RedisConfig = {}) {\r\n this.client = client;\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Create a RedisCache from configuration\r\n */\r\n static async create(config: RedisConfig): Promise<RedisCache> {\r\n // Dynamic import to keep ioredis as optional peer dependency\r\n const { default: Redis } = await import('ioredis');\r\n\r\n let client: IORedis;\r\n\r\n if (config.cluster) {\r\n // Cluster mode\r\n const { Cluster } = await import('ioredis');\r\n client = new Cluster(config.cluster.nodes, {\r\n scaleReads: config.cluster.options?.scaleReads ?? 'master',\r\n maxRedirections: config.cluster.options?.maxRedirections ?? 16,\r\n redisOptions: {\r\n password: config.password,\r\n ...(config.tls ? { tls: typeof config.tls === 'boolean' ? {} : config.tls } : {}),\r\n },\r\n }) as unknown as IORedis;\r\n } else if (config.sentinel) {\r\n // Sentinel mode (HA)\r\n client = new Redis({\r\n sentinels: config.sentinel.sentinels,\r\n name: config.sentinel.name,\r\n password: config.password,\r\n sentinelPassword: config.sentinel.password,\r\n ...(config.tls ? { tls: typeof config.tls === 'boolean' ? {} : config.tls } : {}),\r\n });\r\n } else {\r\n // Standard mode\r\n const options = toIORedisOptions(config);\r\n client = typeof options === 'string' ? new Redis(options) : new Redis(options);\r\n }\r\n\r\n // Wait for connection (unless lazy connect)\r\n if (!config.lazyConnect) {\r\n await new Promise<void>((resolve, reject) => {\r\n if (client.status === 'ready') {\r\n resolve();\r\n } else {\r\n client.once('ready', resolve);\r\n client.once('error', reject);\r\n }\r\n });\r\n }\r\n\r\n return new RedisCache(client, config);\r\n }\r\n\r\n /**\r\n * Create from environment variables\r\n */\r\n static async fromEnv(): Promise<RedisCache> {\r\n const config: RedisConfig = {\r\n url: process.env.REDIS_URL,\r\n host: process.env.REDIS_HOST,\r\n port: parseInt(process.env.REDIS_PORT ?? '6379', 10),\r\n password: process.env.REDIS_PASSWORD,\r\n db: process.env.REDIS_DB ? parseInt(process.env.REDIS_DB, 10) : undefined,\r\n keyPrefix: process.env.REDIS_KEY_PREFIX,\r\n tls: process.env.REDIS_TLS === 'true',\r\n };\r\n\r\n return RedisCache.create(config);\r\n }\r\n\r\n async get<T = unknown>(key: string): Promise<T | null> {\r\n const value = await this.client.get(key);\r\n if (value === null) {\r\n return null;\r\n }\r\n\r\n try {\r\n return JSON.parse(value) as T;\r\n } catch {\r\n // If not JSON, return as string (cast to T)\r\n return value as unknown as T;\r\n }\r\n }\r\n\r\n async set<T = unknown>(key: string, value: T, ttl?: number): Promise<void> {\r\n const serialized = typeof value === 'string' ? value : JSON.stringify(value);\r\n\r\n if (ttl) {\r\n await this.client.setex(key, ttl, serialized);\r\n } else {\r\n await this.client.set(key, serialized);\r\n }\r\n }\r\n\r\n async delete(key: string): Promise<void> {\r\n await this.client.del(key);\r\n }\r\n\r\n async exists(key: string): Promise<boolean> {\r\n const result = await this.client.exists(key);\r\n return result > 0;\r\n }\r\n\r\n async deletePattern(pattern: string): Promise<number> {\r\n const keys: string[] = [];\r\n let cursor = '0';\r\n\r\n // Use SCAN for safe iteration in production\r\n do {\r\n const result = await this.client.scan(cursor, 'MATCH', pattern, 'COUNT', 100);\r\n cursor = result[0];\r\n keys.push(...result[1]);\r\n } while (cursor !== '0');\r\n\r\n if (keys.length === 0) {\r\n return 0;\r\n }\r\n\r\n // Delete in batches for efficiency\r\n const batchSize = 1000;\r\n let deleted = 0;\r\n\r\n for (let i = 0; i < keys.length; i += batchSize) {\r\n const batch = keys.slice(i, i + batchSize);\r\n deleted += await this.client.del(...batch);\r\n }\r\n\r\n return deleted;\r\n }\r\n\r\n async mget<T = unknown>(keys: string[]): Promise<(T | null)[]> {\r\n if (keys.length === 0) {\r\n return [];\r\n }\r\n\r\n const values = await this.client.mget(...keys);\r\n\r\n return values.map((value) => {\r\n if (value === null) {\r\n return null;\r\n }\r\n\r\n try {\r\n return JSON.parse(value) as T;\r\n } catch {\r\n return value as unknown as T;\r\n }\r\n });\r\n }\r\n\r\n async mset<T = unknown>(entries: Array<{ key: string; value: T; ttl?: number }>): Promise<void> {\r\n if (entries.length === 0) {\r\n return;\r\n }\r\n\r\n // Group entries by TTL\r\n const noTtl: Array<{ key: string; value: T }> = [];\r\n const withTtl: Array<{ key: string; value: T; ttl: number }> = [];\r\n\r\n for (const entry of entries) {\r\n if (entry.ttl) {\r\n withTtl.push(entry as { key: string; value: T; ttl: number });\r\n } else {\r\n noTtl.push(entry);\r\n }\r\n }\r\n\r\n // Use pipeline for atomicity and performance\r\n const pipeline = this.client.pipeline();\r\n\r\n // MSET for entries without TTL\r\n if (noTtl.length > 0) {\r\n const args: string[] = [];\r\n for (const entry of noTtl) {\r\n args.push(entry.key);\r\n args.push(typeof entry.value === 'string' ? entry.value : JSON.stringify(entry.value));\r\n }\r\n pipeline.mset(...args);\r\n }\r\n\r\n // SETEX for entries with TTL\r\n for (const entry of withTtl) {\r\n const value = typeof entry.value === 'string' ? entry.value : JSON.stringify(entry.value);\r\n pipeline.setex(entry.key, entry.ttl, value);\r\n }\r\n\r\n await pipeline.exec();\r\n }\r\n\r\n async incr(key: string, by: number = 1): Promise<number> {\r\n return await this.client.incrby(key, by);\r\n }\r\n\r\n async publish(channel: string, message: string): Promise<void> {\r\n await this.client.publish(channel, message);\r\n }\r\n\r\n async subscribe(channel: string, callback: (message: string) => void): Promise<() => void> {\r\n // Create a dedicated subscriber client if needed\r\n if (!this.subscriberClient) {\r\n const { default: Redis } = await import('ioredis');\r\n const options = toIORedisOptions(this.config);\r\n this.subscriberClient =\r\n typeof options === 'string' ? new Redis(options) : new Redis(options);\r\n\r\n // Set up message handler\r\n this.subscriberClient.on('message', (ch: string, message: string) => {\r\n const callbacks = this.subscriptions.get(ch);\r\n if (callbacks) {\r\n for (const cb of callbacks) {\r\n try {\r\n cb(message);\r\n } catch (error) {\r\n console.error(`Error in subscription callback for channel ${ch}:`, error);\r\n }\r\n }\r\n }\r\n });\r\n }\r\n\r\n // Track subscription\r\n if (!this.subscriptions.has(channel)) {\r\n this.subscriptions.set(channel, new Set());\r\n await this.subscriberClient.subscribe(channel);\r\n }\r\n this.subscriptions.get(channel)!.add(callback);\r\n\r\n // Return unsubscribe function\r\n return async () => {\r\n const callbacks = this.subscriptions.get(channel);\r\n if (callbacks) {\r\n callbacks.delete(callback);\r\n if (callbacks.size === 0) {\r\n this.subscriptions.delete(channel);\r\n await this.subscriberClient?.unsubscribe(channel);\r\n }\r\n }\r\n };\r\n }\r\n\r\n async healthCheck(): Promise<boolean> {\r\n try {\r\n const result = await this.client.ping();\r\n return result === 'PONG';\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n async close(): Promise<void> {\r\n if (this.subscriberClient) {\r\n await this.subscriberClient.quit();\r\n this.subscriberClient = null;\r\n }\r\n await this.client.quit();\r\n this.subscriptions.clear();\r\n }\r\n\r\n /**\r\n * Get connection info for monitoring\r\n */\r\n getConnectionInfo(): {\r\n status: string;\r\n host?: string;\r\n port?: number;\r\n } {\r\n return {\r\n status: this.client.status,\r\n host: this.config.host,\r\n port: this.config.port,\r\n };\r\n }\r\n\r\n /**\r\n * Execute arbitrary Redis command\r\n */\r\n async command<T = unknown>(command: string, ...args: unknown[]): Promise<T> {\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n return await (this.client as any).call(command, ...args);\r\n }\r\n\r\n /**\r\n * Get TTL of a key\r\n */\r\n async ttl(key: string): Promise<number> {\r\n return await this.client.ttl(key);\r\n }\r\n\r\n /**\r\n * Set expiry on an existing key\r\n */\r\n async expire(key: string, seconds: number): Promise<boolean> {\r\n const result = await this.client.expire(key, seconds);\r\n return result === 1;\r\n }\r\n\r\n /**\r\n * Get all keys matching a pattern (use with caution in production)\r\n */\r\n async keys(pattern: string): Promise<string[]> {\r\n const keys: string[] = [];\r\n let cursor = '0';\r\n\r\n do {\r\n const result = await this.client.scan(cursor, 'MATCH', pattern, 'COUNT', 100);\r\n cursor = result[0];\r\n keys.push(...result[1]);\r\n } while (cursor !== '0');\r\n\r\n return keys;\r\n }\r\n}\r\n","/**\r\n * Upstash Redis Cache Adapter\r\n * Production implementation using Upstash Redis REST API\r\n */\r\n\r\nimport type { Redis } from '@upstash/redis';\r\nimport { ICache } from '../../interfaces/ICache';\r\n\r\nexport interface UpstashCacheConfig {\r\n url: string;\r\n token: string;\r\n}\r\n\r\nexport class UpstashCache implements ICache {\r\n private client: Redis;\r\n\r\n constructor(client: Redis) {\r\n this.client = client;\r\n }\r\n\r\n async get<T = unknown>(key: string): Promise<T | null> {\r\n const value = await this.client.get<T>(key);\r\n return value ?? null;\r\n }\r\n\r\n async set<T = unknown>(key: string, value: T, ttl?: number): Promise<void> {\r\n if (ttl) {\r\n await this.client.set(key, value, { ex: ttl });\r\n } else {\r\n await this.client.set(key, value);\r\n }\r\n }\r\n\r\n async delete(key: string): Promise<void> {\r\n await this.client.del(key);\r\n }\r\n\r\n async exists(key: string): Promise<boolean> {\r\n const result = await this.client.exists(key);\r\n return result > 0;\r\n }\r\n\r\n async deletePattern(pattern: string): Promise<number> {\r\n // Upstash SCAN + DEL for pattern deletion\r\n const keys: string[] = [];\r\n let cursor: string | number = 0;\r\n\r\n do {\r\n const result: [string | number, string[]] = await this.client.scan(cursor, { match: pattern, count: 100 });\r\n cursor = result[0];\r\n keys.push(...result[1]);\r\n } while (cursor !== 0 && cursor !== '0');\r\n\r\n if (keys.length === 0) {\r\n return 0;\r\n }\r\n\r\n const deleted = await this.client.del(...keys);\r\n return deleted;\r\n }\r\n\r\n async mget<T = unknown>(keys: string[]): Promise<(T | null)[]> {\r\n if (keys.length === 0) {\r\n return [];\r\n }\r\n const results = await this.client.mget<(T | null)[]>(...keys);\r\n return results;\r\n }\r\n\r\n async mset<T = unknown>(entries: Array<{ key: string; value: T; ttl?: number }>): Promise<void> {\r\n if (entries.length === 0) {\r\n return;\r\n }\r\n\r\n // Use pipeline for better performance\r\n const pipeline = this.client.pipeline();\r\n\r\n for (const entry of entries) {\r\n if (entry.ttl) {\r\n pipeline.set(entry.key, entry.value, { ex: entry.ttl });\r\n } else {\r\n pipeline.set(entry.key, entry.value);\r\n }\r\n }\r\n\r\n await pipeline.exec();\r\n }\r\n\r\n async incr(key: string, by: number = 1): Promise<number> {\r\n return await this.client.incrby(key, by);\r\n }\r\n\r\n async publish(channel: string, message: string): Promise<void> {\r\n await this.client.publish(channel, message);\r\n }\r\n\r\n async subscribe(channel: string, callback: (message: string) => void): Promise<() => void> {\r\n // Upstash REST API doesn't support subscriptions natively\r\n // Would need WebSocket or polling implementation\r\n console.warn(\r\n 'UpstashCache.subscribe() is not supported via REST API. ' +\r\n 'Use a direct Redis connection or implement polling for pub/sub functionality.'\r\n );\r\n return () => {};\r\n }\r\n\r\n async healthCheck(): Promise<boolean> {\r\n try {\r\n const result = await this.client.ping();\r\n return result === 'PONG';\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n async close(): Promise<void> {\r\n // Upstash REST client doesn't need explicit closing\r\n }\r\n}\r\n","/**\r\n * Supabase Storage Adapter\r\n *\r\n * Production implementation using Supabase Storage for file management.\r\n * Provides vendor-agnostic file storage via Supabase's storage buckets.\r\n *\r\n * Features:\r\n * - Simple bucket-based file storage\r\n * - Automatic public URL generation\r\n * - Signed URL support for private files\r\n * - Built-in CDN caching\r\n */\r\n\r\nimport type { SupabaseClient } from '@supabase/supabase-js';\r\nimport { IStorage, StorageFile, UploadOptions } from '../../interfaces/IStorage';\r\n\r\nexport interface SupabaseStorageConfig {\r\n /** Supabase project URL */\r\n url: string;\r\n\r\n /** Supabase API key (anon or service role) */\r\n apiKey: string;\r\n\r\n /** Default bucket name */\r\n bucket: string;\r\n\r\n /** Whether the bucket is public */\r\n publicBucket?: boolean;\r\n\r\n /** Default signed URL expiry in seconds */\r\n signedUrlExpiry?: number;\r\n}\r\n\r\nexport class SupabaseStorage implements IStorage {\r\n private client: SupabaseClient;\r\n private bucket: string;\r\n private publicBucket: boolean;\r\n private signedUrlExpiry: number;\r\n\r\n constructor(client: SupabaseClient, config: { bucket: string; publicBucket?: boolean; signedUrlExpiry?: number }) {\r\n this.client = client;\r\n this.bucket = config.bucket;\r\n this.publicBucket = config.publicBucket ?? false;\r\n this.signedUrlExpiry = config.signedUrlExpiry ?? 3600;\r\n }\r\n\r\n /**\r\n * Create a SupabaseStorage adapter from configuration\r\n */\r\n static async create(config: SupabaseStorageConfig): Promise<SupabaseStorage> {\r\n const { createClient } = await import('@supabase/supabase-js');\r\n const client = createClient(config.url, config.apiKey);\r\n\r\n return new SupabaseStorage(client, {\r\n bucket: config.bucket,\r\n publicBucket: config.publicBucket,\r\n signedUrlExpiry: config.signedUrlExpiry,\r\n });\r\n }\r\n\r\n /**\r\n * Create from environment variables\r\n */\r\n static async fromEnv(): Promise<SupabaseStorage> {\r\n const url = process.env.SUPABASE_URL;\r\n const apiKey = process.env.SUPABASE_SERVICE_ROLE_KEY ?? process.env.SUPABASE_ANON_KEY;\r\n const bucket = process.env.SUPABASE_STORAGE_BUCKET ?? 'uploads';\r\n\r\n if (!url || !apiKey) {\r\n throw new Error('SUPABASE_URL and SUPABASE_ANON_KEY are required');\r\n }\r\n\r\n return SupabaseStorage.create({\r\n url,\r\n apiKey,\r\n bucket,\r\n publicBucket: process.env.SUPABASE_STORAGE_PUBLIC === 'true',\r\n signedUrlExpiry: process.env.SUPABASE_SIGNED_URL_EXPIRY\r\n ? parseInt(process.env.SUPABASE_SIGNED_URL_EXPIRY, 10)\r\n : undefined,\r\n });\r\n }\r\n\r\n async upload(key: string, data: Buffer | Blob | ReadableStream, options?: UploadOptions): Promise<{ url: string }> {\r\n // Convert ReadableStream to Buffer if needed\r\n let content: Buffer | Blob;\r\n if (data instanceof ReadableStream) {\r\n const chunks: Uint8Array[] = [];\r\n const reader = data.getReader();\r\n while (true) {\r\n const { done, value } = await reader.read();\r\n if (done) break;\r\n chunks.push(value);\r\n }\r\n content = Buffer.concat(chunks);\r\n } else {\r\n content = data;\r\n }\r\n\r\n const { data: uploadData, error } = await this.client.storage.from(this.bucket).upload(key, content, {\r\n contentType: options?.contentType,\r\n upsert: true,\r\n });\r\n\r\n if (error) {\r\n throw new Error(`Failed to upload file: ${error.message}`);\r\n }\r\n\r\n const url = await this.getUrl(key);\r\n return { url };\r\n }\r\n\r\n async download(path: string): Promise<Buffer> {\r\n const { data, error } = await this.client.storage.from(this.bucket).download(path);\r\n\r\n if (error) {\r\n throw new Error(`Failed to download file: ${error.message}`);\r\n }\r\n\r\n // Convert Blob to Buffer\r\n const arrayBuffer = await data.arrayBuffer();\r\n return Buffer.from(arrayBuffer);\r\n }\r\n\r\n async delete(path: string): Promise<void> {\r\n const { error } = await this.client.storage.from(this.bucket).remove([path]);\r\n\r\n if (error) {\r\n throw new Error(`Failed to delete file: ${error.message}`);\r\n }\r\n }\r\n\r\n async deleteMany(paths: string[]): Promise<void> {\r\n const { error } = await this.client.storage.from(this.bucket).remove(paths);\r\n\r\n if (error) {\r\n throw new Error(`Failed to delete files: ${error.message}`);\r\n }\r\n }\r\n\r\n async getMetadata(path: string): Promise<StorageFile | null> {\r\n // Supabase doesn't have a direct getMetadata method, so we need to list and find\r\n const dir = this.getDirectory(path);\r\n const filename = this.getFilename(path);\r\n\r\n const { data, error } = await this.client.storage.from(this.bucket).list(dir, {\r\n limit: 1000,\r\n search: filename,\r\n });\r\n\r\n if (error || !data) {\r\n return null;\r\n }\r\n\r\n const file = data.find((f) => f.name === filename);\r\n if (!file || !file.id) {\r\n return null;\r\n }\r\n\r\n return {\r\n key: path,\r\n size: (file.metadata?.size as number) ?? 0,\r\n contentType: file.metadata?.mimetype as string | undefined,\r\n lastModified: file.updated_at ? new Date(file.updated_at) : undefined,\r\n };\r\n }\r\n\r\n async exists(path: string): Promise<boolean> {\r\n const { data, error } = await this.client.storage.from(this.bucket).list(this.getDirectory(path), {\r\n limit: 1,\r\n search: this.getFilename(path),\r\n });\r\n\r\n if (error) {\r\n return false;\r\n }\r\n\r\n return data.some((file) => file.name === this.getFilename(path));\r\n }\r\n\r\n async list(prefix?: string): Promise<StorageFile[]> {\r\n const folder = prefix ?? '';\r\n const { data, error } = await this.client.storage.from(this.bucket).list(folder, {\r\n limit: 1000,\r\n });\r\n\r\n if (error) {\r\n throw new Error(`Failed to list files: ${error.message}`);\r\n }\r\n\r\n const files: StorageFile[] = [];\r\n\r\n for (const item of data) {\r\n if (item.id) {\r\n // It's a file (folders don't have an id)\r\n const filePath = folder ? `${folder}/${item.name}` : item.name;\r\n files.push({\r\n key: filePath,\r\n size: (item.metadata?.size as number) ?? 0,\r\n contentType: item.metadata?.mimetype as string | undefined,\r\n lastModified: item.updated_at ? new Date(item.updated_at) : undefined,\r\n });\r\n }\r\n }\r\n\r\n return files;\r\n }\r\n\r\n async getSignedUrl(path: string, expiresIn?: number): Promise<string> {\r\n const { data, error } = await this.client.storage\r\n .from(this.bucket)\r\n .createSignedUrl(path, expiresIn ?? this.signedUrlExpiry);\r\n\r\n if (error) {\r\n throw new Error(`Failed to create signed URL: ${error.message}`);\r\n }\r\n\r\n return data.signedUrl;\r\n }\r\n\r\n async healthCheck(): Promise<boolean> {\r\n try {\r\n // Try to list files (limited to 1) to verify access\r\n const { error } = await this.client.storage.from(this.bucket).list('', { limit: 1 });\r\n return !error;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Get URL for a file (public URL or signed URL based on bucket config)\r\n */\r\n private async getUrl(path: string): Promise<string> {\r\n if (this.publicBucket) {\r\n const { data } = this.client.storage.from(this.bucket).getPublicUrl(path);\r\n return data.publicUrl;\r\n }\r\n\r\n return this.getSignedUrl(path);\r\n }\r\n\r\n /**\r\n * Get directory from path\r\n */\r\n private getDirectory(path: string): string {\r\n const lastSlash = path.lastIndexOf('/');\r\n return lastSlash > 0 ? path.substring(0, lastSlash) : '';\r\n }\r\n\r\n /**\r\n * Get filename from path\r\n */\r\n private getFilename(path: string): string {\r\n const lastSlash = path.lastIndexOf('/');\r\n return lastSlash > 0 ? path.substring(lastSlash + 1) : path;\r\n }\r\n\r\n /**\r\n * Get storage bucket info\r\n */\r\n getBucketInfo(): { bucket: string; publicBucket: boolean } {\r\n return {\r\n bucket: this.bucket,\r\n publicBucket: this.publicBucket,\r\n };\r\n }\r\n\r\n /**\r\n * Copy file to new location\r\n */\r\n async copy(sourcePath: string, destPath: string): Promise<{ key: string; url: string }> {\r\n const { data, error } = await this.client.storage.from(this.bucket).copy(sourcePath, destPath);\r\n\r\n if (error) {\r\n throw new Error(`Failed to copy file: ${error.message}`);\r\n }\r\n\r\n return {\r\n key: destPath,\r\n url: await this.getUrl(destPath),\r\n };\r\n }\r\n\r\n /**\r\n * Move file to new location\r\n */\r\n async move(sourcePath: string, destPath: string): Promise<{ key: string; url: string }> {\r\n const { data, error } = await this.client.storage.from(this.bucket).move(sourcePath, destPath);\r\n\r\n if (error) {\r\n throw new Error(`Failed to move file: ${error.message}`);\r\n }\r\n\r\n return {\r\n key: destPath,\r\n url: await this.getUrl(destPath),\r\n };\r\n }\r\n}\r\n","/**\r\n * S3 Storage Adapter\r\n * Production implementation using AWS S3 (compatible with MinIO, R2, etc.)\r\n */\r\n\r\nimport type { S3Client } from '@aws-sdk/client-s3';\r\nimport type { getSignedUrl as GetSignedUrlFn } from '@aws-sdk/s3-request-presigner';\r\nimport { IStorage, StorageFile, UploadOptions } from '../../interfaces/IStorage';\r\n\r\nexport interface S3StorageConfig {\r\n endpoint?: string;\r\n region: string;\r\n accessKeyId: string;\r\n secretAccessKey: string;\r\n bucket: string;\r\n forcePathStyle?: boolean;\r\n publicUrl?: string;\r\n}\r\n\r\nexport class S3Storage implements IStorage {\r\n private client: S3Client;\r\n private bucket: string;\r\n private publicUrl?: string;\r\n private signedUrlFn: typeof GetSignedUrlFn;\r\n\r\n constructor(\r\n client: S3Client,\r\n bucket: string,\r\n getSignedUrlFn: typeof GetSignedUrlFn,\r\n publicUrl?: string\r\n ) {\r\n this.client = client;\r\n this.bucket = bucket;\r\n this.signedUrlFn = getSignedUrlFn;\r\n this.publicUrl = publicUrl;\r\n }\r\n\r\n async upload(\r\n key: string,\r\n data: Buffer | Blob | ReadableStream,\r\n options?: UploadOptions\r\n ): Promise<{ url: string }> {\r\n // Convert Blob to Buffer if needed\r\n let body: Buffer | ReadableStream;\r\n if (data instanceof Blob) {\r\n body = Buffer.from(await data.arrayBuffer());\r\n } else {\r\n body = data;\r\n }\r\n\r\n const { PutObjectCommand: PutCmd } = await import('@aws-sdk/client-s3');\r\n\r\n await this.client.send(\r\n new PutCmd({\r\n Bucket: this.bucket,\r\n Key: key,\r\n Body: body as Buffer,\r\n ContentType: options?.contentType,\r\n Metadata: options?.metadata,\r\n ACL: options?.public ? 'public-read' : undefined,\r\n })\r\n );\r\n\r\n // Return the URL\r\n const url = this.publicUrl\r\n ? `${this.publicUrl}/${key}`\r\n : await this.createSignedUrl(key);\r\n\r\n return { url };\r\n }\r\n\r\n async download(key: string): Promise<Buffer> {\r\n const { GetObjectCommand: GetCmd } = await import('@aws-sdk/client-s3');\r\n\r\n const response = await this.client.send(\r\n new GetCmd({\r\n Bucket: this.bucket,\r\n Key: key,\r\n })\r\n );\r\n\r\n const stream = response.Body;\r\n if (!stream) {\r\n throw new Error('Empty response body');\r\n }\r\n\r\n // Convert stream to buffer\r\n const chunks: Uint8Array[] = [];\r\n for await (const chunk of stream as AsyncIterable<Uint8Array>) {\r\n chunks.push(chunk);\r\n }\r\n return Buffer.concat(chunks);\r\n }\r\n\r\n async getSignedUrl(key: string, expiresIn: number = 3600): Promise<string> {\r\n return this.createSignedUrl(key, expiresIn);\r\n }\r\n\r\n private async createSignedUrl(key: string, expiresIn: number = 3600): Promise<string> {\r\n const { GetObjectCommand: GetCmd } = await import('@aws-sdk/client-s3');\r\n\r\n const command = new GetCmd({\r\n Bucket: this.bucket,\r\n Key: key,\r\n });\r\n\r\n return this.signedUrlFn(this.client, command, { expiresIn });\r\n }\r\n\r\n async delete(key: string): Promise<void> {\r\n const { DeleteObjectCommand: DeleteCmd } = await import('@aws-sdk/client-s3');\r\n\r\n await this.client.send(\r\n new DeleteCmd({\r\n Bucket: this.bucket,\r\n Key: key,\r\n })\r\n );\r\n }\r\n\r\n async deleteMany(keys: string[]): Promise<void> {\r\n if (keys.length === 0) {\r\n return;\r\n }\r\n\r\n const { DeleteObjectsCommand: DeleteManyCmd } = await import('@aws-sdk/client-s3');\r\n\r\n await this.client.send(\r\n new DeleteManyCmd({\r\n Bucket: this.bucket,\r\n Delete: {\r\n Objects: keys.map((key) => ({ Key: key })),\r\n },\r\n })\r\n );\r\n }\r\n\r\n async list(prefix?: string): Promise<StorageFile[]> {\r\n const { ListObjectsV2Command: ListCmd } = await import('@aws-sdk/client-s3');\r\n\r\n const files: StorageFile[] = [];\r\n let continuationToken: string | undefined;\r\n\r\n do {\r\n const response = await this.client.send(\r\n new ListCmd({\r\n Bucket: this.bucket,\r\n Prefix: prefix,\r\n ContinuationToken: continuationToken,\r\n })\r\n );\r\n\r\n if (response.Contents) {\r\n for (const item of response.Contents) {\r\n files.push({\r\n key: item.Key!,\r\n size: item.Size!,\r\n lastModified: item.LastModified,\r\n etag: item.ETag,\r\n });\r\n }\r\n }\r\n\r\n continuationToken = response.NextContinuationToken;\r\n } while (continuationToken);\r\n\r\n return files;\r\n }\r\n\r\n async exists(key: string): Promise<boolean> {\r\n try {\r\n const { HeadObjectCommand: HeadCmd } = await import('@aws-sdk/client-s3');\r\n\r\n await this.client.send(\r\n new HeadCmd({\r\n Bucket: this.bucket,\r\n Key: key,\r\n })\r\n );\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n async getMetadata(key: string): Promise<StorageFile | null> {\r\n try {\r\n const { HeadObjectCommand: HeadCmd } = await import('@aws-sdk/client-s3');\r\n\r\n const response = await this.client.send(\r\n new HeadCmd({\r\n Bucket: this.bucket,\r\n Key: key,\r\n })\r\n );\r\n\r\n return {\r\n key,\r\n size: response.ContentLength!,\r\n contentType: response.ContentType,\r\n lastModified: response.LastModified,\r\n etag: response.ETag,\r\n };\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n async healthCheck(): Promise<boolean> {\r\n try {\r\n const { ListObjectsV2Command: ListCmd } = await import('@aws-sdk/client-s3');\r\n\r\n await this.client.send(\r\n new ListCmd({\r\n Bucket: this.bucket,\r\n MaxKeys: 1,\r\n })\r\n );\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n}\r\n","/**\r\n * SMTP Email Adapter\r\n *\r\n * Production implementation using nodemailer for direct SMTP connections.\r\n * Provides vendor-agnostic email sending via standard SMTP protocol.\r\n *\r\n * Compatible with any SMTP server:\r\n * - Self-hosted mail servers (Postfix, Sendmail)\r\n * - Gmail SMTP\r\n * - Amazon SES (SMTP interface)\r\n * - SendGrid SMTP\r\n * - Mailgun SMTP\r\n * - Microsoft 365 SMTP\r\n * - Any standard SMTP relay\r\n */\r\n\r\nimport type { Transporter } from 'nodemailer';\r\nimport type SMTPTransport from 'nodemailer/lib/smtp-transport';\r\nimport { IEmail, EmailMessage, EmailResult, EmailAddress } from '../../interfaces/IEmail';\r\n\r\nexport interface SmtpConfig {\r\n /** SMTP host */\r\n host: string;\r\n\r\n /** SMTP port (typically 25, 465, or 587) */\r\n port: number;\r\n\r\n /** Use TLS/SSL */\r\n secure?: boolean;\r\n\r\n /** SMTP username */\r\n username?: string;\r\n\r\n /** SMTP password */\r\n password?: string;\r\n\r\n /** Default from address */\r\n from?: string;\r\n\r\n /** Connection timeout in milliseconds */\r\n connectionTimeout?: number;\r\n\r\n /** Socket timeout in milliseconds */\r\n socketTimeout?: number;\r\n\r\n /** Enable debug logging */\r\n debug?: boolean;\r\n\r\n /** Reject unauthorized certificates */\r\n rejectUnauthorized?: boolean;\r\n}\r\n\r\n/**\r\n * Convert EmailAddress to string format for nodemailer\r\n */\r\nfunction formatAddress(address: EmailAddress | string | undefined): string | undefined {\r\n if (!address) return undefined;\r\n if (typeof address === 'string') return address;\r\n return address.name ? `${address.name} <${address.email}>` : address.email;\r\n}\r\n\r\n/**\r\n * Convert EmailAddress or EmailAddress[] to nodemailer format\r\n */\r\nfunction formatRecipients(addresses: EmailAddress | EmailAddress[]): string | string[] {\r\n if (Array.isArray(addresses)) {\r\n return addresses.map((addr) => formatAddress(addr)!);\r\n }\r\n return formatAddress(addresses)!;\r\n}\r\n\r\nexport class SmtpEmail implements IEmail {\r\n private transporter: Transporter<SMTPTransport.SentMessageInfo> | null = null;\r\n private config: SmtpConfig;\r\n\r\n constructor(config: SmtpConfig) {\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Create an SmtpEmail adapter from configuration\r\n */\r\n static async create(config: SmtpConfig): Promise<SmtpEmail> {\r\n const adapter = new SmtpEmail(config);\r\n await adapter.initialize();\r\n return adapter;\r\n }\r\n\r\n /**\r\n * Create from environment variables\r\n */\r\n static async fromEnv(): Promise<SmtpEmail> {\r\n const config: SmtpConfig = {\r\n host: process.env.SMTP_HOST ?? 'localhost',\r\n port: parseInt(process.env.SMTP_PORT ?? '587', 10),\r\n secure: process.env.SMTP_SECURE === 'true',\r\n username: process.env.SMTP_USERNAME ?? process.env.SMTP_USER,\r\n password: process.env.SMTP_PASSWORD ?? process.env.SMTP_PASS,\r\n from: process.env.EMAIL_FROM ?? process.env.SMTP_FROM,\r\n debug: process.env.SMTP_DEBUG === 'true',\r\n };\r\n\r\n return SmtpEmail.create(config);\r\n }\r\n\r\n /**\r\n * Initialize the SMTP transporter\r\n */\r\n private async initialize(): Promise<void> {\r\n const nodemailer = await import('nodemailer');\r\n\r\n const options: SMTPTransport.Options = {\r\n host: this.config.host,\r\n port: this.config.port,\r\n secure: this.config.secure ?? this.config.port === 465,\r\n connectionTimeout: this.config.connectionTimeout ?? 10000,\r\n socketTimeout: this.config.socketTimeout ?? 30000,\r\n debug: this.config.debug,\r\n logger: this.config.debug,\r\n };\r\n\r\n // Authentication\r\n if (this.config.username && this.config.password) {\r\n options.auth = {\r\n user: this.config.username,\r\n pass: this.config.password,\r\n };\r\n }\r\n\r\n // TLS options\r\n if (this.config.rejectUnauthorized !== undefined) {\r\n options.tls = {\r\n rejectUnauthorized: this.config.rejectUnauthorized,\r\n };\r\n }\r\n\r\n this.transporter = nodemailer.createTransport(options);\r\n }\r\n\r\n async send(message: EmailMessage): Promise<EmailResult> {\r\n if (!this.transporter) {\r\n await this.initialize();\r\n }\r\n\r\n try {\r\n const mailOptions = {\r\n from: formatAddress(message.from) ?? this.config.from,\r\n to: formatRecipients(message.to),\r\n subject: message.subject,\r\n text: message.text,\r\n html: message.html,\r\n replyTo: formatAddress(message.replyTo),\r\n attachments: message.attachments?.map((att) => ({\r\n filename: att.filename,\r\n content: att.content,\r\n contentType: att.contentType,\r\n })),\r\n headers: message.headers,\r\n };\r\n\r\n const result = await this.transporter!.sendMail(mailOptions);\r\n\r\n return {\r\n id: result.messageId ?? `smtp_${Date.now()}`,\r\n success: true,\r\n };\r\n } catch (error) {\r\n return {\r\n id: `smtp_error_${Date.now()}`,\r\n success: false,\r\n error: error instanceof Error ? error : new Error(String(error)),\r\n };\r\n }\r\n }\r\n\r\n async sendBatch(messages: EmailMessage[]): Promise<EmailResult[]> {\r\n // Send sequentially to avoid overwhelming SMTP server\r\n const results: EmailResult[] = [];\r\n for (const msg of messages) {\r\n const result = await this.send(msg);\r\n results.push(result);\r\n }\r\n return results;\r\n }\r\n\r\n async healthCheck(): Promise<boolean> {\r\n if (!this.transporter) {\r\n try {\r\n await this.initialize();\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n try {\r\n await this.transporter!.verify();\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Close the transporter and release connections\r\n */\r\n async close(): Promise<void> {\r\n if (this.transporter) {\r\n this.transporter.close();\r\n this.transporter = null;\r\n }\r\n }\r\n\r\n /**\r\n * Get transporter info for debugging\r\n */\r\n getTransporterInfo(): { host: string; port: number; secure: boolean } {\r\n return {\r\n host: this.config.host,\r\n port: this.config.port,\r\n secure: this.config.secure ?? false,\r\n };\r\n }\r\n}\r\n","/**\r\n * Resend Email Adapter\r\n * Production implementation using Resend for transactional emails\r\n */\r\n\r\nimport type { Resend } from 'resend';\r\nimport { IEmail, EmailMessage, EmailResult, EmailAddress } from '../../interfaces/IEmail';\r\n\r\nexport interface ResendEmailConfig {\r\n apiKey: string;\r\n defaultFrom?: string;\r\n}\r\n\r\nexport class ResendEmail implements IEmail {\r\n private client: Resend;\r\n private defaultFrom: string;\r\n\r\n constructor(client: Resend, defaultFrom?: string) {\r\n this.client = client;\r\n this.defaultFrom = defaultFrom || 'noreply@example.com';\r\n }\r\n\r\n async send(message: EmailMessage): Promise<EmailResult> {\r\n try {\r\n const to = this.formatAddresses(message.to);\r\n const from = message.from\r\n ? this.formatAddress(message.from)\r\n : this.defaultFrom;\r\n\r\n // Build email options - use type assertion for complex Resend types\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n const emailOptions: any = {\r\n from,\r\n to,\r\n subject: message.subject,\r\n };\r\n\r\n if (message.html) emailOptions.html = message.html;\r\n if (message.text) emailOptions.text = message.text;\r\n if (message.replyTo) emailOptions.replyTo = this.formatAddress(message.replyTo);\r\n if (message.headers) emailOptions.headers = message.headers;\r\n if (message.tags) emailOptions.tags = message.tags.map((tag) => ({ name: tag, value: tag }));\r\n if (message.attachments) {\r\n emailOptions.attachments = message.attachments.map((a) => ({\r\n filename: a.filename,\r\n content: typeof a.content === 'string' ? a.content : a.content.toString('base64'),\r\n contentType: a.contentType,\r\n }));\r\n }\r\n\r\n const { data, error } = await this.client.emails.send(emailOptions);\r\n\r\n if (error) {\r\n return {\r\n id: '',\r\n success: false,\r\n error: new Error(error.message),\r\n };\r\n }\r\n\r\n return {\r\n id: data?.id || '',\r\n success: true,\r\n };\r\n } catch (err) {\r\n return {\r\n id: '',\r\n success: false,\r\n error: err instanceof Error ? err : new Error('Unknown error'),\r\n };\r\n }\r\n }\r\n\r\n async sendBatch(messages: EmailMessage[]): Promise<EmailResult[]> {\r\n // Resend has batch send but we'll use sequential for reliability\r\n const results: EmailResult[] = [];\r\n\r\n for (const message of messages) {\r\n const result = await this.send(message);\r\n results.push(result);\r\n\r\n // Basic rate limiting - 100ms between emails\r\n await new Promise((resolve) => setTimeout(resolve, 100));\r\n }\r\n\r\n return results;\r\n }\r\n\r\n async healthCheck(): Promise<boolean> {\r\n try {\r\n // Check connectivity by listing domains\r\n const { error } = await this.client.domains.list();\r\n return !error;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n private formatAddress(address: EmailAddress): string {\r\n if (address.name) {\r\n return `${address.name} <${address.email}>`;\r\n }\r\n return address.email;\r\n }\r\n\r\n private formatAddresses(addresses: EmailAddress | EmailAddress[]): string[] {\r\n const list = Array.isArray(addresses) ? addresses : [addresses];\r\n return list.map((addr) => this.formatAddress(addr));\r\n }\r\n}\r\n","/**\r\n * BullMQ Queue Adapter\r\n * Production queue implementation using BullMQ (Redis-backed)\r\n */\r\n\r\nimport type { IQueue, Job, JobOptions } from '../../interfaces/IQueue';\r\n\r\nexport interface BullMQConfig {\r\n /** Redis connection URL */\r\n redisUrl?: string;\r\n /** Redis host */\r\n host?: string;\r\n /** Redis port */\r\n port?: number;\r\n /** Redis password */\r\n password?: string;\r\n /** Redis database number */\r\n db?: number;\r\n /** Queue name */\r\n queueName: string;\r\n /** Default job options */\r\n defaultJobOptions?: JobOptions;\r\n}\r\n\r\n// Internal types to avoid BullMQ's complex generic constraints\r\ninterface BullMQJobInternal {\r\n id?: string;\r\n name: string;\r\n data: unknown;\r\n attemptsMade: number;\r\n progress: number | object;\r\n timestamp: number;\r\n remove(): Promise<void>;\r\n}\r\n\r\ninterface BullMQQueueInternal {\r\n add(name: string, data: unknown, opts?: object): Promise<BullMQJobInternal>;\r\n addBulk(jobs: Array<{ name: string; data: unknown; opts?: object }>): Promise<BullMQJobInternal[]>;\r\n getJob(id: string): Promise<BullMQJobInternal | undefined>;\r\n getWaitingCount(): Promise<number>;\r\n getActiveCount(): Promise<number>;\r\n getCompletedCount(): Promise<number>;\r\n getFailedCount(): Promise<number>;\r\n getDelayedCount(): Promise<number>;\r\n pause(): Promise<void>;\r\n resume(): Promise<void>;\r\n close(): Promise<void>;\r\n}\r\n\r\ninterface BullMQWorkerInternal {\r\n on(event: string, handler: (...args: unknown[]) => void): void;\r\n close(): Promise<void>;\r\n}\r\n\r\n/**\r\n * BullMQ Queue Adapter\r\n * Requires: pnpm add bullmq ioredis\r\n */\r\nexport class BullMQQueue<T = unknown> implements IQueue<T> {\r\n private queue: BullMQQueueInternal | null = null;\r\n private worker: BullMQWorkerInternal | null = null;\r\n private config: BullMQConfig;\r\n private initialized = false;\r\n\r\n constructor(config: BullMQConfig) {\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Initialize the queue (called lazily on first use)\r\n */\r\n private async ensureInitialized(): Promise<void> {\r\n if (this.initialized) return;\r\n\r\n const { Queue } = await import('bullmq');\r\n\r\n const connection = this.getConnectionConfig();\r\n\r\n this.queue = new Queue(this.config.queueName, {\r\n connection,\r\n defaultJobOptions: this.config.defaultJobOptions ? {\r\n attempts: this.config.defaultJobOptions.attempts,\r\n backoff: this.config.defaultJobOptions.backoff,\r\n delay: this.config.defaultJobOptions.delay,\r\n priority: this.config.defaultJobOptions.priority,\r\n removeOnComplete: this.config.defaultJobOptions.removeOnComplete,\r\n removeOnFail: this.config.defaultJobOptions.removeOnFail,\r\n } : undefined,\r\n }) as unknown as BullMQQueueInternal;\r\n\r\n this.initialized = true;\r\n }\r\n\r\n private getConnectionConfig() {\r\n if (this.config.redisUrl) {\r\n return { url: this.config.redisUrl };\r\n }\r\n return {\r\n host: this.config.host || 'localhost',\r\n port: this.config.port || 6379,\r\n password: this.config.password,\r\n db: this.config.db,\r\n };\r\n }\r\n\r\n async add(name: string, data: T, options?: JobOptions): Promise<Job<T>> {\r\n await this.ensureInitialized();\r\n\r\n const bullmqJob = await this.queue!.add(name, data, {\r\n attempts: options?.attempts,\r\n backoff: options?.backoff,\r\n delay: options?.delay,\r\n priority: options?.priority,\r\n removeOnComplete: options?.removeOnComplete,\r\n removeOnFail: options?.removeOnFail,\r\n });\r\n\r\n return this.mapJob(bullmqJob);\r\n }\r\n\r\n async addBulk(jobs: Array<{ name: string; data: T; options?: JobOptions }>): Promise<Job<T>[]> {\r\n await this.ensureInitialized();\r\n\r\n const bullmqJobs = await this.queue!.addBulk(\r\n jobs.map(job => ({\r\n name: job.name,\r\n data: job.data,\r\n opts: job.options ? {\r\n attempts: job.options.attempts,\r\n backoff: job.options.backoff,\r\n delay: job.options.delay,\r\n priority: job.options.priority,\r\n removeOnComplete: job.options.removeOnComplete,\r\n removeOnFail: job.options.removeOnFail,\r\n } : undefined,\r\n }))\r\n );\r\n\r\n return bullmqJobs.map(job => this.mapJob(job));\r\n }\r\n\r\n process(handler: (job: Job<T>) => Promise<unknown>): void {\r\n // Start worker asynchronously\r\n this.startWorker(handler).catch(err => {\r\n console.error('Failed to start BullMQ worker:', err);\r\n });\r\n }\r\n\r\n private async startWorker(handler: (job: Job<T>) => Promise<unknown>): Promise<void> {\r\n const { Worker } = await import('bullmq');\r\n\r\n const connection = this.getConnectionConfig();\r\n\r\n const worker = new Worker(\r\n this.config.queueName,\r\n async (bullmqJob) => {\r\n const job = this.mapJob(bullmqJob as unknown as BullMQJobInternal);\r\n return handler(job);\r\n },\r\n { connection }\r\n );\r\n\r\n this.worker = worker as unknown as BullMQWorkerInternal;\r\n\r\n worker.on('completed', () => {\r\n // Job completed successfully\r\n });\r\n\r\n worker.on('failed', (job, err) => {\r\n console.error(`Job ${job?.id} failed:`, err);\r\n });\r\n }\r\n\r\n async getJob(id: string): Promise<Job<T> | null> {\r\n await this.ensureInitialized();\r\n\r\n const bullmqJob = await this.queue!.getJob(id);\r\n if (!bullmqJob) return null;\r\n\r\n return this.mapJob(bullmqJob);\r\n }\r\n\r\n async removeJob(id: string): Promise<void> {\r\n await this.ensureInitialized();\r\n\r\n const job = await this.queue!.getJob(id);\r\n if (job) {\r\n await job.remove();\r\n }\r\n }\r\n\r\n async pause(): Promise<void> {\r\n await this.ensureInitialized();\r\n await this.queue!.pause();\r\n }\r\n\r\n async resume(): Promise<void> {\r\n await this.ensureInitialized();\r\n await this.queue!.resume();\r\n }\r\n\r\n async getStats(): Promise<{\r\n waiting: number;\r\n active: number;\r\n completed: number;\r\n failed: number;\r\n delayed: number;\r\n }> {\r\n await this.ensureInitialized();\r\n\r\n const [waiting, active, completed, failed, delayed] = await Promise.all([\r\n this.queue!.getWaitingCount(),\r\n this.queue!.getActiveCount(),\r\n this.queue!.getCompletedCount(),\r\n this.queue!.getFailedCount(),\r\n this.queue!.getDelayedCount(),\r\n ]);\r\n\r\n return { waiting, active, completed, failed, delayed };\r\n }\r\n\r\n async healthCheck(): Promise<boolean> {\r\n try {\r\n await this.ensureInitialized();\r\n // Try to get queue stats as a health check\r\n await this.queue!.getWaitingCount();\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n async close(): Promise<void> {\r\n if (this.worker) {\r\n await this.worker.close();\r\n this.worker = null;\r\n }\r\n if (this.queue) {\r\n await this.queue.close();\r\n this.queue = null;\r\n }\r\n this.initialized = false;\r\n }\r\n\r\n private mapJob(bullmqJob: BullMQJobInternal): Job<T> {\r\n return {\r\n id: bullmqJob.id || '',\r\n name: bullmqJob.name,\r\n data: bullmqJob.data as T,\r\n attemptsMade: bullmqJob.attemptsMade,\r\n progress: typeof bullmqJob.progress === 'number' ? bullmqJob.progress : 0,\r\n timestamp: bullmqJob.timestamp,\r\n };\r\n }\r\n}\r\n","/**\r\n * OpenTelemetry Tracing Adapter\r\n *\r\n * Production-ready distributed tracing using OpenTelemetry SDK.\r\n * Exports traces to OTLP-compatible backends (Jaeger, Grafana Tempo, etc.)\r\n */\r\n\r\nimport type {\r\n ITracing,\r\n ISpan,\r\n SpanOptions,\r\n SpanContext,\r\n SpanStatus,\r\n SpanKind,\r\n} from '../../interfaces/ITracing';\r\n\r\n// OpenTelemetry types (dynamically imported)\r\ntype OtelSpan = import('@opentelemetry/api').Span;\r\ntype OtelTracer = import('@opentelemetry/api').Tracer;\r\ntype OtelSpanKind = import('@opentelemetry/api').SpanKind;\r\ntype OtelSpanStatusCode = import('@opentelemetry/api').SpanStatusCode;\r\ntype NodeTracerProvider = import('@opentelemetry/sdk-trace-node').NodeTracerProvider;\r\ntype OTLPTraceExporter = import('@opentelemetry/exporter-trace-otlp-http').OTLPTraceExporter;\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// CONFIGURATION\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\nexport interface OpenTelemetryConfig {\r\n /** Service name for traces */\r\n serviceName: string;\r\n\r\n /** Service version */\r\n serviceVersion?: string;\r\n\r\n /** Environment (dev, staging, production) */\r\n environment?: string;\r\n\r\n /** OTLP endpoint (e.g., http://localhost:4318/v1/traces) */\r\n endpoint?: string;\r\n\r\n /** Exporter type */\r\n exporterType?: 'otlp-http' | 'otlp-grpc' | 'console';\r\n\r\n /** Sampling rate (0.0 to 1.0) */\r\n sampleRate?: number;\r\n\r\n /** Additional resource attributes */\r\n resourceAttributes?: Record<string, string>;\r\n}\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// SPAN WRAPPER\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\nclass OpenTelemetrySpan implements ISpan {\r\n private _name: string;\r\n private otelSpan: OtelSpan;\r\n private spanContext: SpanContext;\r\n private SpanStatusCode: typeof OtelSpanStatusCode;\r\n\r\n constructor(\r\n name: string,\r\n otelSpan: OtelSpan,\r\n SpanStatusCode: typeof OtelSpanStatusCode\r\n ) {\r\n this._name = name;\r\n this.otelSpan = otelSpan;\r\n this.SpanStatusCode = SpanStatusCode;\r\n\r\n const ctx = otelSpan.spanContext();\r\n this.spanContext = {\r\n traceId: ctx.traceId,\r\n spanId: ctx.spanId,\r\n traceFlags: ctx.traceFlags,\r\n traceState: ctx.traceState?.serialize(),\r\n };\r\n }\r\n\r\n get name(): string {\r\n return this._name;\r\n }\r\n\r\n get context(): SpanContext {\r\n return this.spanContext;\r\n }\r\n\r\n get isRecording(): boolean {\r\n return this.otelSpan.isRecording();\r\n }\r\n\r\n setAttribute(key: string, value: string | number | boolean): this {\r\n this.otelSpan.setAttribute(key, value);\r\n return this;\r\n }\r\n\r\n setAttributes(attributes: Record<string, string | number | boolean>): this {\r\n this.otelSpan.setAttributes(attributes);\r\n return this;\r\n }\r\n\r\n addEvent(name: string, attributes?: Record<string, string | number | boolean>): this {\r\n this.otelSpan.addEvent(name, attributes);\r\n return this;\r\n }\r\n\r\n setStatus(status: SpanStatus): this {\r\n let code: OtelSpanStatusCode;\r\n switch (status.code) {\r\n case 'ok':\r\n code = this.SpanStatusCode.OK;\r\n break;\r\n case 'error':\r\n code = this.SpanStatusCode.ERROR;\r\n break;\r\n default:\r\n code = this.SpanStatusCode.UNSET;\r\n }\r\n this.otelSpan.setStatus({ code, message: status.message });\r\n return this;\r\n }\r\n\r\n recordException(exception: Error, attributes?: Record<string, string | number | boolean>): this {\r\n this.otelSpan.recordException(exception, attributes);\r\n this.setStatus({ code: 'error', message: exception.message });\r\n return this;\r\n }\r\n\r\n updateName(name: string): this {\r\n this._name = name;\r\n this.otelSpan.updateName(name);\r\n return this;\r\n }\r\n\r\n end(endTime?: number): void {\r\n this.otelSpan.end(endTime);\r\n }\r\n}\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// OPENTELEMETRY TRACING ADAPTER\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\nexport class OpenTelemetryTracing implements ITracing {\r\n private tracer: OtelTracer;\r\n private provider: NodeTracerProvider;\r\n private currentSpan: OpenTelemetrySpan | undefined;\r\n private api: typeof import('@opentelemetry/api');\r\n private SpanStatusCode: typeof OtelSpanStatusCode;\r\n private OtelSpanKind: typeof OtelSpanKind;\r\n\r\n private constructor(\r\n tracer: OtelTracer,\r\n provider: NodeTracerProvider,\r\n api: typeof import('@opentelemetry/api'),\r\n SpanStatusCode: typeof OtelSpanStatusCode,\r\n OtelSpanKind: typeof OtelSpanKind\r\n ) {\r\n this.tracer = tracer;\r\n this.provider = provider;\r\n this.api = api;\r\n this.SpanStatusCode = SpanStatusCode;\r\n this.OtelSpanKind = OtelSpanKind;\r\n }\r\n\r\n /**\r\n * Create an OpenTelemetry tracing instance\r\n */\r\n static async create(config: OpenTelemetryConfig): Promise<OpenTelemetryTracing> {\r\n // Dynamic imports for optional dependencies\r\n const api = await import('@opentelemetry/api');\r\n const { NodeTracerProvider } = await import('@opentelemetry/sdk-trace-node');\r\n const { Resource } = await import('@opentelemetry/resources');\r\n const { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION, ATTR_DEPLOYMENT_ENVIRONMENT_NAME } = await import(\r\n '@opentelemetry/semantic-conventions'\r\n );\r\n const { BatchSpanProcessor, ConsoleSpanExporter } = await import('@opentelemetry/sdk-trace-base');\r\n\r\n // Build resource attributes\r\n const resourceAttributes: Record<string, string> = {\r\n [ATTR_SERVICE_NAME]: config.serviceName,\r\n ...config.resourceAttributes,\r\n };\r\n\r\n if (config.serviceVersion) {\r\n resourceAttributes[ATTR_SERVICE_VERSION] = config.serviceVersion;\r\n }\r\n\r\n if (config.environment) {\r\n resourceAttributes[ATTR_DEPLOYMENT_ENVIRONMENT_NAME] = config.environment;\r\n }\r\n\r\n // Create provider with resource\r\n const provider = new NodeTracerProvider({\r\n resource: new Resource(resourceAttributes),\r\n });\r\n\r\n // Create exporter based on configuration\r\n let exporter;\r\n switch (config.exporterType) {\r\n case 'otlp-grpc': {\r\n const { OTLPTraceExporter } = await import('@opentelemetry/exporter-trace-otlp-grpc');\r\n exporter = new OTLPTraceExporter({\r\n url: config.endpoint,\r\n });\r\n break;\r\n }\r\n case 'console':\r\n exporter = new ConsoleSpanExporter();\r\n break;\r\n case 'otlp-http':\r\n default: {\r\n const { OTLPTraceExporter } = await import('@opentelemetry/exporter-trace-otlp-http');\r\n exporter = new OTLPTraceExporter({\r\n url: config.endpoint || 'http://localhost:4318/v1/traces',\r\n });\r\n break;\r\n }\r\n }\r\n\r\n // Add batch processor\r\n provider.addSpanProcessor(new BatchSpanProcessor(exporter));\r\n\r\n // Register provider\r\n provider.register();\r\n\r\n // Get tracer\r\n const tracer = api.trace.getTracer(config.serviceName, config.serviceVersion);\r\n\r\n return new OpenTelemetryTracing(\r\n tracer,\r\n provider,\r\n api,\r\n api.SpanStatusCode,\r\n api.SpanKind\r\n );\r\n }\r\n\r\n private mapSpanKind(kind?: SpanKind): OtelSpanKind {\r\n switch (kind) {\r\n case 'server':\r\n return this.OtelSpanKind.SERVER;\r\n case 'client':\r\n return this.OtelSpanKind.CLIENT;\r\n case 'producer':\r\n return this.OtelSpanKind.PRODUCER;\r\n case 'consumer':\r\n return this.OtelSpanKind.CONSUMER;\r\n case 'internal':\r\n default:\r\n return this.OtelSpanKind.INTERNAL;\r\n }\r\n }\r\n\r\n startSpan(name: string, options?: SpanOptions): ISpan {\r\n const otelSpan = this.tracer.startSpan(name, {\r\n kind: this.mapSpanKind(options?.kind),\r\n attributes: options?.attributes,\r\n startTime: options?.startTime,\r\n });\r\n\r\n const span = new OpenTelemetrySpan(name, otelSpan, this.SpanStatusCode);\r\n this.currentSpan = span;\r\n\r\n return span;\r\n }\r\n\r\n getCurrentSpan(): ISpan | undefined {\r\n const activeSpan = this.api.trace.getActiveSpan();\r\n if (activeSpan) {\r\n return new OpenTelemetrySpan('', activeSpan, this.SpanStatusCode);\r\n }\r\n return this.currentSpan;\r\n }\r\n\r\n withSpan<T>(name: string, fn: (span: ISpan) => T, options?: SpanOptions): T {\r\n const span = this.startSpan(name, options);\r\n const otelSpan = this.tracer.startSpan(name, {\r\n kind: this.mapSpanKind(options?.kind),\r\n attributes: options?.attributes,\r\n });\r\n\r\n return this.api.context.with(this.api.trace.setSpan(this.api.context.active(), otelSpan), () => {\r\n try {\r\n const result = fn(span);\r\n span.setStatus({ code: 'ok' });\r\n return result;\r\n } catch (error) {\r\n span.recordException(error instanceof Error ? error : new Error(String(error)));\r\n throw error;\r\n } finally {\r\n span.end();\r\n otelSpan.end();\r\n }\r\n });\r\n }\r\n\r\n async withSpanAsync<T>(name: string, fn: (span: ISpan) => Promise<T>, options?: SpanOptions): Promise<T> {\r\n const span = this.startSpan(name, options);\r\n const otelSpan = this.tracer.startSpan(name, {\r\n kind: this.mapSpanKind(options?.kind),\r\n attributes: options?.attributes,\r\n });\r\n\r\n return this.api.context.with(this.api.trace.setSpan(this.api.context.active(), otelSpan), async () => {\r\n try {\r\n const result = await fn(span);\r\n span.setStatus({ code: 'ok' });\r\n return result;\r\n } catch (error) {\r\n span.recordException(error instanceof Error ? error : new Error(String(error)));\r\n throw error;\r\n } finally {\r\n span.end();\r\n otelSpan.end();\r\n }\r\n });\r\n }\r\n\r\n instrument<TArgs extends unknown[], TReturn>(\r\n name: string,\r\n fn: (...args: TArgs) => TReturn,\r\n options?: SpanOptions\r\n ): (...args: TArgs) => TReturn {\r\n return (...args: TArgs) => this.withSpan(name, () => fn(...args), options);\r\n }\r\n\r\n instrumentAsync<TArgs extends unknown[], TReturn>(\r\n name: string,\r\n fn: (...args: TArgs) => Promise<TReturn>,\r\n options?: SpanOptions\r\n ): (...args: TArgs) => Promise<TReturn> {\r\n return (...args: TArgs) => this.withSpanAsync(name, () => fn(...args), options);\r\n }\r\n\r\n extractContext(headers: Record<string, string | string[] | undefined>): SpanContext | undefined {\r\n // Use W3C Trace Context propagation\r\n const traceparent = headers['traceparent'];\r\n if (!traceparent || typeof traceparent !== 'string') return undefined;\r\n\r\n // Parse W3C Trace Context format: version-traceId-spanId-flags\r\n const parts = traceparent.split('-');\r\n if (parts.length !== 4 || parts[0] !== '00') return undefined;\r\n\r\n const traceId = parts[1];\r\n const spanId = parts[2];\r\n const traceFlags = parseInt(parts[3]!, 16);\r\n\r\n if (!traceId || traceId.length !== 32 || !spanId || spanId.length !== 16) {\r\n return undefined;\r\n }\r\n\r\n return {\r\n traceId,\r\n spanId,\r\n traceFlags,\r\n traceState: headers['tracestate'] as string | undefined,\r\n };\r\n }\r\n\r\n injectContext(headers: Record<string, string>): void {\r\n const activeSpan = this.api.trace.getActiveSpan();\r\n if (activeSpan) {\r\n const ctx = activeSpan.spanContext();\r\n headers['traceparent'] = `00-${ctx.traceId}-${ctx.spanId}-${ctx.traceFlags.toString(16).padStart(2, '0')}`;\r\n if (ctx.traceState) {\r\n headers['tracestate'] = ctx.traceState.serialize();\r\n }\r\n } else if (this.currentSpan) {\r\n const ctx = this.currentSpan.context;\r\n headers['traceparent'] = `00-${ctx.traceId}-${ctx.spanId}-${ctx.traceFlags.toString(16).padStart(2, '0')}`;\r\n if (ctx.traceState) {\r\n headers['tracestate'] = ctx.traceState;\r\n }\r\n }\r\n }\r\n\r\n async healthCheck(): Promise<boolean> {\r\n // OpenTelemetry is considered healthy if the provider is registered\r\n return true;\r\n }\r\n\r\n async flush(): Promise<void> {\r\n await this.provider.forceFlush();\r\n }\r\n\r\n async close(): Promise<void> {\r\n await this.provider.shutdown();\r\n }\r\n}\r\n","/**\r\n * Health Check Interface\r\n * Standardizes health check behavior across all adapters\r\n */\r\n\r\n/**\r\n * Result of a single health check\r\n */\r\nexport interface HealthCheckResult {\r\n /** Overall health status */\r\n status: 'healthy' | 'degraded' | 'unhealthy';\r\n /** Time taken to perform the check in milliseconds */\r\n latencyMs: number;\r\n /** When the check was performed */\r\n timestamp: Date;\r\n /** Optional message with details */\r\n message?: string;\r\n /** Additional details about the health check */\r\n details?: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Aggregated health result for the entire platform\r\n */\r\nexport interface PlatformHealthResult {\r\n /** Overall platform status */\r\n status: 'healthy' | 'degraded' | 'unhealthy';\r\n /** When the check was performed */\r\n timestamp: Date;\r\n /** Individual service health results */\r\n services: {\r\n database: HealthCheckResult;\r\n cache: HealthCheckResult;\r\n storage: HealthCheckResult;\r\n email: HealthCheckResult;\r\n queue: HealthCheckResult;\r\n };\r\n /** Summary counts */\r\n summary: {\r\n total: number;\r\n healthy: number;\r\n degraded: number;\r\n unhealthy: number;\r\n };\r\n}\r\n\r\n/**\r\n * Interface for services that support health checks\r\n */\r\nexport interface IHealth {\r\n /**\r\n * Perform a health check on the service\r\n * @returns Promise resolving to health check result\r\n */\r\n healthCheck(): Promise<HealthCheckResult>;\r\n}\r\n\r\n/**\r\n * Interface for services that support simple boolean health checks\r\n * (Legacy support - prefer IHealth for new implementations)\r\n */\r\nexport interface IHealthCheckable {\r\n /**\r\n * Simple health check returning boolean\r\n * @returns Promise resolving to true if healthy\r\n */\r\n healthCheck(): Promise<boolean>;\r\n}\r\n\r\n/**\r\n * Helper to convert boolean health check to HealthCheckResult\r\n */\r\nexport function toHealthCheckResult(\r\n healthy: boolean,\r\n latencyMs: number,\r\n message?: string\r\n): HealthCheckResult {\r\n return {\r\n status: healthy ? 'healthy' : 'unhealthy',\r\n latencyMs,\r\n timestamp: new Date(),\r\n message,\r\n };\r\n}\r\n\r\n/**\r\n * Helper to perform a timed health check\r\n */\r\nexport async function timedHealthCheck<T>(\r\n fn: () => Promise<T>,\r\n successCheck: (result: T) => boolean = () => true\r\n): Promise<HealthCheckResult> {\r\n const start = Date.now();\r\n try {\r\n const result = await fn();\r\n const healthy = successCheck(result);\r\n return {\r\n status: healthy ? 'healthy' : 'degraded',\r\n latencyMs: Date.now() - start,\r\n timestamp: new Date(),\r\n };\r\n } catch (error) {\r\n return {\r\n status: 'unhealthy',\r\n latencyMs: Date.now() - start,\r\n timestamp: new Date(),\r\n message: error instanceof Error ? error.message : 'Unknown error',\r\n };\r\n }\r\n}\r\n","/**\r\n * Logger Interface\r\n * Standardizes logging across the platform\r\n */\r\n\r\n/**\r\n * Log levels in order of severity\r\n */\r\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error';\r\n\r\n/**\r\n * Metadata that can be attached to log entries\r\n */\r\nexport interface LogMeta {\r\n /** Error object if logging an error */\r\n error?: Error;\r\n /** Duration in milliseconds (for timing operations) */\r\n duration?: number;\r\n /** Request ID for tracing */\r\n requestId?: string;\r\n /** User ID if applicable */\r\n userId?: string;\r\n /** Any additional key-value pairs */\r\n [key: string]: unknown;\r\n}\r\n\r\n/**\r\n * A structured log entry\r\n */\r\nexport interface LogEntry {\r\n /** Log level */\r\n level: LogLevel;\r\n /** Log message */\r\n message: string;\r\n /** When the log was created */\r\n timestamp: Date;\r\n /** Optional metadata */\r\n meta?: LogMeta;\r\n /** Logger context (e.g., service name) */\r\n context?: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Logger interface for structured logging\r\n */\r\nexport interface ILogger {\r\n /**\r\n * Log a debug message (for development/troubleshooting)\r\n */\r\n debug(message: string, meta?: LogMeta): void;\r\n\r\n /**\r\n * Log an informational message\r\n */\r\n info(message: string, meta?: LogMeta): void;\r\n\r\n /**\r\n * Log a warning message\r\n */\r\n warn(message: string, meta?: LogMeta): void;\r\n\r\n /**\r\n * Log an error message\r\n */\r\n error(message: string, meta?: LogMeta): void;\r\n\r\n /**\r\n * Create a child logger with additional context\r\n * @param context Additional context to include in all logs from this child\r\n */\r\n child(context: Record<string, unknown>): ILogger;\r\n}\r\n\r\n/**\r\n * Configuration options for loggers\r\n */\r\nexport interface LoggerConfig {\r\n /** Minimum level to log */\r\n level?: LogLevel;\r\n /** Whether to pretty print (for development) */\r\n pretty?: boolean;\r\n /** Service name to include in logs */\r\n service?: string;\r\n /** Environment name */\r\n environment?: string;\r\n}\r\n\r\n/**\r\n * Console logger implementation (for development)\r\n */\r\nexport class ConsoleLogger implements ILogger {\r\n private context: Record<string, unknown>;\r\n private level: LogLevel;\r\n\r\n private static levelPriority: Record<LogLevel, number> = {\r\n debug: 0,\r\n info: 1,\r\n warn: 2,\r\n error: 3,\r\n };\r\n\r\n constructor(config: LoggerConfig = {}) {\r\n this.context = {\r\n service: config.service,\r\n environment: config.environment,\r\n };\r\n this.level = config.level || 'info';\r\n }\r\n\r\n private shouldLog(level: LogLevel): boolean {\r\n return ConsoleLogger.levelPriority[level] >= ConsoleLogger.levelPriority[this.level];\r\n }\r\n\r\n private log(level: LogLevel, message: string, meta?: LogMeta): void {\r\n if (!this.shouldLog(level)) return;\r\n\r\n const entry: LogEntry = {\r\n level,\r\n message,\r\n timestamp: new Date(),\r\n meta,\r\n context: this.context,\r\n };\r\n\r\n const prefix = `[${entry.timestamp.toISOString()}] [${level.toUpperCase()}]`;\r\n const contextStr = Object.keys(this.context).length > 0\r\n ? ` [${Object.entries(this.context).map(([k, v]) => `${k}=${v}`).join(' ')}]`\r\n : '';\r\n\r\n switch (level) {\r\n case 'debug':\r\n console.debug(`${prefix}${contextStr} ${message}`, meta || '');\r\n break;\r\n case 'info':\r\n console.info(`${prefix}${contextStr} ${message}`, meta || '');\r\n break;\r\n case 'warn':\r\n console.warn(`${prefix}${contextStr} ${message}`, meta || '');\r\n break;\r\n case 'error':\r\n console.error(`${prefix}${contextStr} ${message}`, meta || '');\r\n if (meta?.error) {\r\n console.error(meta.error);\r\n }\r\n break;\r\n }\r\n }\r\n\r\n debug(message: string, meta?: LogMeta): void {\r\n this.log('debug', message, meta);\r\n }\r\n\r\n info(message: string, meta?: LogMeta): void {\r\n this.log('info', message, meta);\r\n }\r\n\r\n warn(message: string, meta?: LogMeta): void {\r\n this.log('warn', message, meta);\r\n }\r\n\r\n error(message: string, meta?: LogMeta): void {\r\n this.log('error', message, meta);\r\n }\r\n\r\n child(context: Record<string, unknown>): ILogger {\r\n const childLogger = new ConsoleLogger({ level: this.level });\r\n childLogger.context = { ...this.context, ...context };\r\n return childLogger;\r\n }\r\n}\r\n\r\n/**\r\n * No-op logger for testing or when logging is disabled\r\n */\r\nexport class NoopLogger implements ILogger {\r\n debug(): void {}\r\n info(): void {}\r\n warn(): void {}\r\n error(): void {}\r\n child(): ILogger {\r\n return this;\r\n }\r\n}\r\n","/**\r\n * Metrics Interface\r\n *\r\n * Provides observability through counters, gauges, histograms, and timers.\r\n */\r\n\r\n/**\r\n * Tags for metrics (key-value pairs for dimensions)\r\n */\r\nexport type MetricTags = Record<string, string | number | boolean>;\r\n\r\n/**\r\n * Metrics interface for observability\r\n */\r\nexport interface IMetrics {\r\n /**\r\n * Increment a counter by a value (default 1)\r\n *\r\n * @example\r\n * metrics.increment('api.requests', 1, { method: 'GET', path: '/users' })\r\n */\r\n increment(name: string, value?: number, tags?: MetricTags): void;\r\n\r\n /**\r\n * Decrement a counter by a value (default 1)\r\n *\r\n * @example\r\n * metrics.decrement('active.connections', 1, { server: 'api-1' })\r\n */\r\n decrement(name: string, value?: number, tags?: MetricTags): void;\r\n\r\n /**\r\n * Set a gauge to a specific value\r\n *\r\n * @example\r\n * metrics.gauge('queue.size', 42, { queue: 'emails' })\r\n */\r\n gauge(name: string, value: number, tags?: MetricTags): void;\r\n\r\n /**\r\n * Record a value in a histogram (for distributions)\r\n *\r\n * @example\r\n * metrics.histogram('response.size', 1024, { endpoint: '/api/users' })\r\n */\r\n histogram(name: string, value: number, tags?: MetricTags): void;\r\n\r\n /**\r\n * Record a timing value in milliseconds\r\n *\r\n * @example\r\n * metrics.timing('db.query.duration', 42, { table: 'users' })\r\n */\r\n timing(name: string, value: number, tags?: MetricTags): void;\r\n\r\n /**\r\n * Start a timer and return a function to stop it\r\n *\r\n * @example\r\n * const stop = metrics.startTimer('api.request.duration', { method: 'GET' })\r\n * // ... do work ...\r\n * stop() // Records the duration\r\n */\r\n startTimer(name: string, tags?: MetricTags): () => void;\r\n\r\n /**\r\n * Record a distribution value (similar to histogram but for Datadog)\r\n *\r\n * @example\r\n * metrics.distribution('payment.amount', 99.99, { currency: 'USD' })\r\n */\r\n distribution?(name: string, value: number, tags?: MetricTags): void;\r\n\r\n /**\r\n * Record a set value (count unique elements)\r\n *\r\n * @example\r\n * metrics.set('unique.users', 'user-123')\r\n */\r\n set?(name: string, value: string | number, tags?: MetricTags): void;\r\n\r\n /**\r\n * Flush all pending metrics to the backend\r\n */\r\n flush(): Promise<void>;\r\n\r\n /**\r\n * Close the metrics client\r\n */\r\n close(): Promise<void>;\r\n}\r\n\r\n/**\r\n * Memory-based metrics implementation for testing\r\n */\r\nexport class MemoryMetrics implements IMetrics {\r\n private counters: Map<string, { value: number; tags: MetricTags }[]> = new Map();\r\n private gauges: Map<string, { value: number; tags: MetricTags; timestamp: number }> = new Map();\r\n private histograms: Map<string, { values: number[]; tags: MetricTags }[]> = new Map();\r\n private timings: Map<string, { values: number[]; tags: MetricTags }[]> = new Map();\r\n private sets: Map<string, Set<string | number>> = new Map();\r\n\r\n increment(name: string, value = 1, tags: MetricTags = {}): void {\r\n const key = this.createKey(name, tags);\r\n const existing = this.counters.get(key);\r\n\r\n if (existing && existing[0]) {\r\n existing[0].value += value;\r\n } else {\r\n this.counters.set(key, [{ value, tags }]);\r\n }\r\n }\r\n\r\n decrement(name: string, value = 1, tags: MetricTags = {}): void {\r\n this.increment(name, -value, tags);\r\n }\r\n\r\n gauge(name: string, value: number, tags: MetricTags = {}): void {\r\n const key = this.createKey(name, tags);\r\n this.gauges.set(key, { value, tags, timestamp: Date.now() });\r\n }\r\n\r\n histogram(name: string, value: number, tags: MetricTags = {}): void {\r\n const key = this.createKey(name, tags);\r\n const existing = this.histograms.get(key);\r\n\r\n if (existing && existing[0]) {\r\n existing[0].values.push(value);\r\n } else {\r\n this.histograms.set(key, [{ values: [value], tags }]);\r\n }\r\n }\r\n\r\n timing(name: string, value: number, tags: MetricTags = {}): void {\r\n const key = this.createKey(name, tags);\r\n const existing = this.timings.get(key);\r\n\r\n if (existing && existing[0]) {\r\n existing[0].values.push(value);\r\n } else {\r\n this.timings.set(key, [{ values: [value], tags }]);\r\n }\r\n }\r\n\r\n startTimer(name: string, tags: MetricTags = {}): () => void {\r\n const start = Date.now();\r\n return () => {\r\n const duration = Date.now() - start;\r\n this.timing(name, duration, tags);\r\n };\r\n }\r\n\r\n distribution(name: string, value: number, tags: MetricTags = {}): void {\r\n this.histogram(name, value, tags);\r\n }\r\n\r\n set(name: string, value: string | number, tags: MetricTags = {}): void {\r\n const key = this.createKey(name, tags);\r\n let existing = this.sets.get(key);\r\n\r\n if (!existing) {\r\n existing = new Set();\r\n this.sets.set(key, existing);\r\n }\r\n\r\n existing.add(value);\r\n }\r\n\r\n async flush(): Promise<void> {\r\n // No-op for memory implementation\r\n }\r\n\r\n async close(): Promise<void> {\r\n // No-op for memory implementation\r\n }\r\n\r\n // ═══════════════════════════════════════════════════════════════\r\n // Test helpers\r\n // ═══════════════════════════════════════════════════════════════\r\n\r\n /**\r\n * Get counter value\r\n */\r\n getCounter(name: string, tags: MetricTags = {}): number {\r\n const key = this.createKey(name, tags);\r\n const data = this.counters.get(key);\r\n return data?.[0]?.value ?? 0;\r\n }\r\n\r\n /**\r\n * Get gauge value\r\n */\r\n getGauge(name: string, tags: MetricTags = {}): number | undefined {\r\n const key = this.createKey(name, tags);\r\n return this.gauges.get(key)?.value;\r\n }\r\n\r\n /**\r\n * Get histogram values\r\n */\r\n getHistogram(name: string, tags: MetricTags = {}): number[] {\r\n const key = this.createKey(name, tags);\r\n return this.histograms.get(key)?.[0]?.values ?? [];\r\n }\r\n\r\n /**\r\n * Get timing values\r\n */\r\n getTiming(name: string, tags: MetricTags = {}): number[] {\r\n const key = this.createKey(name, tags);\r\n return this.timings.get(key)?.[0]?.values ?? [];\r\n }\r\n\r\n /**\r\n * Get set size\r\n */\r\n getSetSize(name: string, tags: MetricTags = {}): number {\r\n const key = this.createKey(name, tags);\r\n return this.sets.get(key)?.size ?? 0;\r\n }\r\n\r\n /**\r\n * Get all metrics as a summary\r\n */\r\n getSummary(): MetricsSummary {\r\n const summary: MetricsSummary = {\r\n counters: {},\r\n gauges: {},\r\n histograms: {},\r\n timings: {},\r\n sets: {},\r\n };\r\n\r\n for (const [key, data] of this.counters) {\r\n const first = data[0];\r\n if (first) {\r\n summary.counters[key] = first.value;\r\n }\r\n }\r\n\r\n for (const [key, data] of this.gauges) {\r\n summary.gauges[key] = data.value;\r\n }\r\n\r\n for (const [key, data] of this.histograms) {\r\n const first = data[0];\r\n if (first) {\r\n const values = first.values;\r\n summary.histograms[key] = {\r\n count: values.length,\r\n sum: values.reduce((a, b) => a + b, 0),\r\n min: Math.min(...values),\r\n max: Math.max(...values),\r\n avg: values.length > 0 ? values.reduce((a, b) => a + b, 0) / values.length : 0,\r\n };\r\n }\r\n }\r\n\r\n for (const [key, data] of this.timings) {\r\n const first = data[0];\r\n if (first) {\r\n const values = first.values;\r\n summary.timings[key] = {\r\n count: values.length,\r\n sum: values.reduce((a, b) => a + b, 0),\r\n min: Math.min(...values),\r\n max: Math.max(...values),\r\n avg: values.length > 0 ? values.reduce((a, b) => a + b, 0) / values.length : 0,\r\n p50: this.percentile(values, 50),\r\n p95: this.percentile(values, 95),\r\n p99: this.percentile(values, 99),\r\n };\r\n }\r\n }\r\n\r\n for (const [key, data] of this.sets) {\r\n summary.sets[key] = data.size;\r\n }\r\n\r\n return summary;\r\n }\r\n\r\n /**\r\n * Reset all metrics\r\n */\r\n reset(): void {\r\n this.counters.clear();\r\n this.gauges.clear();\r\n this.histograms.clear();\r\n this.timings.clear();\r\n this.sets.clear();\r\n }\r\n\r\n private createKey(name: string, tags: MetricTags): string {\r\n const tagStr = Object.entries(tags)\r\n .sort(([a], [b]) => a.localeCompare(b))\r\n .map(([k, v]) => `${k}:${v}`)\r\n .join(',');\r\n return tagStr ? `${name}|${tagStr}` : name;\r\n }\r\n\r\n private percentile(values: number[], p: number): number {\r\n if (values.length === 0) return 0;\r\n\r\n const sorted = [...values].sort((a, b) => a - b);\r\n const index = Math.ceil((p / 100) * sorted.length) - 1;\r\n const safeIndex = Math.max(0, index);\r\n return sorted[safeIndex] ?? 0;\r\n }\r\n}\r\n\r\n/**\r\n * No-op metrics implementation\r\n */\r\nexport class NoopMetrics implements IMetrics {\r\n increment(): void {}\r\n decrement(): void {}\r\n gauge(): void {}\r\n histogram(): void {}\r\n timing(): void {}\r\n startTimer(): () => void {\r\n return () => {};\r\n }\r\n distribution(): void {}\r\n set(): void {}\r\n async flush(): Promise<void> {}\r\n async close(): Promise<void> {}\r\n}\r\n\r\n/**\r\n * Summary of all metrics\r\n */\r\nexport interface MetricsSummary {\r\n counters: Record<string, number>;\r\n gauges: Record<string, number>;\r\n histograms: Record<string, HistogramStats>;\r\n timings: Record<string, TimingStats>;\r\n sets: Record<string, number>;\r\n}\r\n\r\n/**\r\n * Histogram statistics\r\n */\r\nexport interface HistogramStats {\r\n count: number;\r\n sum: number;\r\n min: number;\r\n max: number;\r\n avg: number;\r\n}\r\n\r\n/**\r\n * Timing statistics\r\n */\r\nexport interface TimingStats extends HistogramStats {\r\n p50: number;\r\n p95: number;\r\n p99: number;\r\n}\r\n\r\n/**\r\n * Create a scoped metrics instance with a prefix\r\n */\r\nexport function createScopedMetrics(\r\n metrics: IMetrics,\r\n prefix: string,\r\n defaultTags: MetricTags = {}\r\n): IMetrics {\r\n const prefixedName = (name: string) => `${prefix}.${name}`;\r\n const mergedTags = (tags?: MetricTags) => ({ ...defaultTags, ...tags });\r\n\r\n return {\r\n increment(name, value, tags) {\r\n metrics.increment(prefixedName(name), value, mergedTags(tags));\r\n },\r\n decrement(name, value, tags) {\r\n metrics.decrement(prefixedName(name), value, mergedTags(tags));\r\n },\r\n gauge(name, value, tags) {\r\n metrics.gauge(prefixedName(name), value, mergedTags(tags));\r\n },\r\n histogram(name, value, tags) {\r\n metrics.histogram(prefixedName(name), value, mergedTags(tags));\r\n },\r\n timing(name, value, tags) {\r\n metrics.timing(prefixedName(name), value, mergedTags(tags));\r\n },\r\n startTimer(name, tags) {\r\n return metrics.startTimer(prefixedName(name), mergedTags(tags));\r\n },\r\n distribution(name, value, tags) {\r\n metrics.distribution?.(prefixedName(name), value, mergedTags(tags));\r\n },\r\n set(name, value, tags) {\r\n metrics.set?.(prefixedName(name), value, mergedTags(tags));\r\n },\r\n flush: () => metrics.flush(),\r\n close: () => metrics.close(),\r\n };\r\n}\r\n","/**\r\n * Secrets Management Interface\r\n *\r\n * Provides a vendor-agnostic abstraction for secrets management.\r\n * Supports various backends: Environment variables, HashiCorp Vault,\r\n * AWS Secrets Manager, Azure Key Vault, GCP Secret Manager, etc.\r\n */\r\n\r\n/**\r\n * Secret metadata\r\n */\r\nexport interface SecretMetadata {\r\n /** Secret version or ETag */\r\n version?: string;\r\n\r\n /** Creation timestamp */\r\n createdAt?: Date;\r\n\r\n /** Last updated timestamp */\r\n updatedAt?: Date;\r\n\r\n /** Expiration timestamp */\r\n expiresAt?: Date;\r\n\r\n /** Custom tags/labels */\r\n tags?: Record<string, string>;\r\n}\r\n\r\n/**\r\n * Secret with metadata\r\n */\r\nexport interface Secret<T = string> {\r\n /** Secret key/name */\r\n key: string;\r\n\r\n /** Secret value */\r\n value: T;\r\n\r\n /** Secret metadata */\r\n metadata?: SecretMetadata;\r\n}\r\n\r\n/**\r\n * Options for getting secrets\r\n */\r\nexport interface GetSecretOptions {\r\n /** Specific version to retrieve */\r\n version?: string;\r\n\r\n /** Include metadata in response */\r\n includeMetadata?: boolean;\r\n\r\n /** Cache TTL in seconds (0 = no cache) */\r\n cacheTtl?: number;\r\n}\r\n\r\n/**\r\n * Options for setting secrets\r\n */\r\nexport interface SetSecretOptions {\r\n /** Expiration timestamp */\r\n expiresAt?: Date;\r\n\r\n /** Custom tags/labels */\r\n tags?: Record<string, string>;\r\n\r\n /** Description */\r\n description?: string;\r\n}\r\n\r\n/**\r\n * Options for rotating secrets\r\n */\r\nexport interface RotateSecretOptions {\r\n /** Custom rotation function */\r\n rotationFn?: () => Promise<string>;\r\n\r\n /** Rotation period in days */\r\n rotationPeriodDays?: number;\r\n\r\n /** Keep previous version count */\r\n keepPreviousVersions?: number;\r\n}\r\n\r\n/**\r\n * Result of a rotation operation\r\n */\r\nexport interface RotationResult {\r\n /** New secret value */\r\n newValue: string;\r\n\r\n /** Previous secret value (for rollback) */\r\n previousValue?: string;\r\n\r\n /** New version identifier */\r\n newVersion: string;\r\n\r\n /** Previous version identifier */\r\n previousVersion?: string;\r\n}\r\n\r\n/**\r\n * Secrets Management Interface\r\n */\r\nexport interface ISecrets {\r\n /**\r\n * Get a secret value by key\r\n */\r\n get(key: string, options?: GetSecretOptions): Promise<string | null>;\r\n\r\n /**\r\n * Get a secret with metadata\r\n */\r\n getWithMetadata(key: string, options?: GetSecretOptions): Promise<Secret | null>;\r\n\r\n /**\r\n * Get multiple secrets at once\r\n */\r\n mget(keys: string[]): Promise<Map<string, string | null>>;\r\n\r\n /**\r\n * Set a secret value\r\n */\r\n set(key: string, value: string, options?: SetSecretOptions): Promise<void>;\r\n\r\n /**\r\n * Delete a secret\r\n */\r\n delete(key: string): Promise<void>;\r\n\r\n /**\r\n * Check if a secret exists\r\n */\r\n exists(key: string): Promise<boolean>;\r\n\r\n /**\r\n * List all secret keys (optionally filtered by prefix)\r\n */\r\n list(prefix?: string): Promise<string[]>;\r\n\r\n /**\r\n * Rotate a secret (generate new value)\r\n */\r\n rotate(key: string, options?: RotateSecretOptions): Promise<RotationResult>;\r\n\r\n /**\r\n * Get all versions of a secret\r\n */\r\n getVersions(key: string): Promise<SecretMetadata[]>;\r\n\r\n /**\r\n * Health check\r\n */\r\n healthCheck(): Promise<boolean>;\r\n}\r\n\r\n/**\r\n * Environment Variables Secrets Adapter\r\n * Simple implementation using process.env - suitable for development\r\n * and containerized deployments with injected secrets\r\n */\r\nexport class EnvSecrets implements ISecrets {\r\n private prefix: string;\r\n private cache: Map<string, { value: string; expiresAt: number }> = new Map();\r\n\r\n constructor(options: { prefix?: string } = {}) {\r\n this.prefix = options.prefix ?? '';\r\n }\r\n\r\n private getEnvKey(key: string): string {\r\n const normalizedKey = key.toUpperCase().replace(/[.-]/g, '_');\r\n return this.prefix ? `${this.prefix}_${normalizedKey}` : normalizedKey;\r\n }\r\n\r\n async get(key: string, options?: GetSecretOptions): Promise<string | null> {\r\n // Check cache first\r\n if (options?.cacheTtl) {\r\n const cached = this.cache.get(key);\r\n if (cached && cached.expiresAt > Date.now()) {\r\n return cached.value;\r\n }\r\n }\r\n\r\n const envKey = this.getEnvKey(key);\r\n const value = process.env[envKey] ?? null;\r\n\r\n // Cache if requested\r\n if (value && options?.cacheTtl) {\r\n this.cache.set(key, {\r\n value,\r\n expiresAt: Date.now() + options.cacheTtl * 1000,\r\n });\r\n }\r\n\r\n return value;\r\n }\r\n\r\n async getWithMetadata(key: string, options?: GetSecretOptions): Promise<Secret | null> {\r\n const value = await this.get(key, options);\r\n if (value === null) {\r\n return null;\r\n }\r\n\r\n return {\r\n key,\r\n value,\r\n metadata: {\r\n // Environment variables don't have native metadata\r\n createdAt: undefined,\r\n updatedAt: undefined,\r\n },\r\n };\r\n }\r\n\r\n async mget(keys: string[]): Promise<Map<string, string | null>> {\r\n const result = new Map<string, string | null>();\r\n for (const key of keys) {\r\n result.set(key, await this.get(key));\r\n }\r\n return result;\r\n }\r\n\r\n async set(key: string, value: string, _options?: SetSecretOptions): Promise<void> {\r\n const envKey = this.getEnvKey(key);\r\n process.env[envKey] = value;\r\n\r\n // Update cache\r\n this.cache.delete(key);\r\n }\r\n\r\n async delete(key: string): Promise<void> {\r\n const envKey = this.getEnvKey(key);\r\n delete process.env[envKey];\r\n this.cache.delete(key);\r\n }\r\n\r\n async exists(key: string): Promise<boolean> {\r\n const envKey = this.getEnvKey(key);\r\n return process.env[envKey] !== undefined;\r\n }\r\n\r\n async list(prefix?: string): Promise<string[]> {\r\n const keys: string[] = [];\r\n const envPrefix = this.prefix ? `${this.prefix}_` : '';\r\n const searchPrefix = prefix\r\n ? `${envPrefix}${prefix.toUpperCase().replace(/[.-]/g, '_')}`\r\n : envPrefix;\r\n\r\n for (const key of Object.keys(process.env)) {\r\n if (key.startsWith(searchPrefix || '')) {\r\n // Convert back to normalized key format\r\n const normalizedKey = key\r\n .slice(envPrefix.length)\r\n .toLowerCase()\r\n .replace(/_/g, '-');\r\n keys.push(normalizedKey);\r\n }\r\n }\r\n\r\n return keys;\r\n }\r\n\r\n async rotate(key: string, options?: RotateSecretOptions): Promise<RotationResult> {\r\n const previousValue = await this.get(key);\r\n\r\n // Generate new value\r\n const newValue = options?.rotationFn\r\n ? await options.rotationFn()\r\n : this.generateSecureValue();\r\n\r\n await this.set(key, newValue);\r\n\r\n return {\r\n newValue,\r\n previousValue: previousValue ?? undefined,\r\n newVersion: 'current',\r\n previousVersion: previousValue ? 'previous' : undefined,\r\n };\r\n }\r\n\r\n async getVersions(_key: string): Promise<SecretMetadata[]> {\r\n // Environment variables don't support versioning\r\n return [];\r\n }\r\n\r\n async healthCheck(): Promise<boolean> {\r\n // Environment is always available\r\n return true;\r\n }\r\n\r\n private generateSecureValue(length: number = 32): string {\r\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*';\r\n let result = '';\r\n const randomValues = new Uint32Array(length);\r\n crypto.getRandomValues(randomValues);\r\n for (let i = 0; i < length; i++) {\r\n result += chars[randomValues[i]! % chars.length];\r\n }\r\n return result;\r\n }\r\n\r\n /**\r\n * Clear the internal cache\r\n */\r\n clearCache(): void {\r\n this.cache.clear();\r\n }\r\n}\r\n\r\n/**\r\n * Memory-based Secrets Adapter\r\n * For testing purposes only - stores secrets in memory\r\n */\r\nexport class MemorySecrets implements ISecrets {\r\n private secrets: Map<string, Secret> = new Map();\r\n private versions: Map<string, SecretMetadata[]> = new Map();\r\n\r\n async get(key: string, _options?: GetSecretOptions): Promise<string | null> {\r\n const secret = this.secrets.get(key);\r\n if (!secret) {\r\n return null;\r\n }\r\n\r\n // Check expiration\r\n if (secret.metadata?.expiresAt && secret.metadata.expiresAt < new Date()) {\r\n await this.delete(key);\r\n return null;\r\n }\r\n\r\n return secret.value;\r\n }\r\n\r\n async getWithMetadata(key: string, options?: GetSecretOptions): Promise<Secret | null> {\r\n const value = await this.get(key, options);\r\n if (value === null) {\r\n return null;\r\n }\r\n\r\n return this.secrets.get(key) ?? null;\r\n }\r\n\r\n async mget(keys: string[]): Promise<Map<string, string | null>> {\r\n const result = new Map<string, string | null>();\r\n for (const key of keys) {\r\n result.set(key, await this.get(key));\r\n }\r\n return result;\r\n }\r\n\r\n async set(key: string, value: string, options?: SetSecretOptions): Promise<void> {\r\n const now = new Date();\r\n const version = `v${Date.now()}`;\r\n\r\n // Store version history\r\n const currentSecret = this.secrets.get(key);\r\n if (currentSecret?.metadata) {\r\n const history = this.versions.get(key) ?? [];\r\n history.push(currentSecret.metadata);\r\n this.versions.set(key, history);\r\n }\r\n\r\n this.secrets.set(key, {\r\n key,\r\n value,\r\n metadata: {\r\n version,\r\n createdAt: currentSecret?.metadata?.createdAt ?? now,\r\n updatedAt: now,\r\n expiresAt: options?.expiresAt,\r\n tags: options?.tags,\r\n },\r\n });\r\n }\r\n\r\n async delete(key: string): Promise<void> {\r\n this.secrets.delete(key);\r\n this.versions.delete(key);\r\n }\r\n\r\n async exists(key: string): Promise<boolean> {\r\n return this.secrets.has(key);\r\n }\r\n\r\n async list(prefix?: string): Promise<string[]> {\r\n const keys: string[] = [];\r\n for (const key of this.secrets.keys()) {\r\n if (!prefix || key.startsWith(prefix)) {\r\n keys.push(key);\r\n }\r\n }\r\n return keys;\r\n }\r\n\r\n async rotate(key: string, options?: RotateSecretOptions): Promise<RotationResult> {\r\n const currentSecret = this.secrets.get(key);\r\n const previousValue = currentSecret?.value;\r\n const previousVersion = currentSecret?.metadata?.version;\r\n\r\n // Generate new value\r\n const newValue = options?.rotationFn\r\n ? await options.rotationFn()\r\n : this.generateSecureValue();\r\n\r\n await this.set(key, newValue);\r\n const newVersion = this.secrets.get(key)?.metadata?.version ?? 'unknown';\r\n\r\n return {\r\n newValue,\r\n previousValue,\r\n newVersion,\r\n previousVersion,\r\n };\r\n }\r\n\r\n async getVersions(key: string): Promise<SecretMetadata[]> {\r\n const current = this.secrets.get(key)?.metadata;\r\n const history = this.versions.get(key) ?? [];\r\n\r\n if (current) {\r\n return [...history, current];\r\n }\r\n\r\n return history;\r\n }\r\n\r\n async healthCheck(): Promise<boolean> {\r\n return true;\r\n }\r\n\r\n private generateSecureValue(length: number = 32): string {\r\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*';\r\n let result = '';\r\n for (let i = 0; i < length; i++) {\r\n result += chars[Math.floor(Math.random() * chars.length)];\r\n }\r\n return result;\r\n }\r\n\r\n /**\r\n * Clear all secrets (for testing)\r\n */\r\n clear(): void {\r\n this.secrets.clear();\r\n this.versions.clear();\r\n }\r\n\r\n /**\r\n * Get count of secrets (for testing)\r\n */\r\n get size(): number {\r\n return this.secrets.size;\r\n }\r\n}\r\n","/**\r\n * Distributed Tracing Interface\r\n *\r\n * Provides vendor-agnostic distributed tracing for observability.\r\n * Supports OpenTelemetry, Jaeger, Zipkin, and custom implementations.\r\n */\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// TYPES\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\nexport type SpanKind = 'internal' | 'server' | 'client' | 'producer' | 'consumer';\r\n\r\nexport type SpanStatusCode = 'unset' | 'ok' | 'error';\r\n\r\nexport interface SpanStatus {\r\n code: SpanStatusCode;\r\n message?: string;\r\n}\r\n\r\nexport interface SpanContext {\r\n traceId: string;\r\n spanId: string;\r\n traceFlags: number;\r\n traceState?: string;\r\n}\r\n\r\nexport interface SpanOptions {\r\n /** Type of span */\r\n kind?: SpanKind;\r\n\r\n /** Initial attributes */\r\n attributes?: Record<string, string | number | boolean>;\r\n\r\n /** Parent span (for manual context propagation) */\r\n parent?: ISpan;\r\n\r\n /** Links to other spans */\r\n links?: SpanContext[];\r\n\r\n /** Start time (defaults to now) */\r\n startTime?: number;\r\n}\r\n\r\nexport interface SpanEvent {\r\n name: string;\r\n timestamp: number;\r\n attributes?: Record<string, string | number | boolean>;\r\n}\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// SPAN INTERFACE\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\nexport interface ISpan {\r\n /** Span name */\r\n readonly name: string;\r\n\r\n /** Span context (trace ID, span ID) */\r\n readonly context: SpanContext;\r\n\r\n /** Whether the span is recording */\r\n readonly isRecording: boolean;\r\n\r\n /**\r\n * Set a single attribute\r\n */\r\n setAttribute(key: string, value: string | number | boolean): this;\r\n\r\n /**\r\n * Set multiple attributes\r\n */\r\n setAttributes(attributes: Record<string, string | number | boolean>): this;\r\n\r\n /**\r\n * Add an event to the span\r\n */\r\n addEvent(name: string, attributes?: Record<string, string | number | boolean>): this;\r\n\r\n /**\r\n * Set the span status\r\n */\r\n setStatus(status: SpanStatus): this;\r\n\r\n /**\r\n * Record an exception\r\n */\r\n recordException(exception: Error, attributes?: Record<string, string | number | boolean>): this;\r\n\r\n /**\r\n * Update the span name\r\n */\r\n updateName(name: string): this;\r\n\r\n /**\r\n * End the span (required to export)\r\n */\r\n end(endTime?: number): void;\r\n}\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// TRACING INTERFACE\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\nexport interface ITracing {\r\n /**\r\n * Create and start a new span\r\n */\r\n startSpan(name: string, options?: SpanOptions): ISpan;\r\n\r\n /**\r\n * Get the currently active span\r\n */\r\n getCurrentSpan(): ISpan | undefined;\r\n\r\n /**\r\n * Execute a function within a span context\r\n */\r\n withSpan<T>(name: string, fn: (span: ISpan) => T, options?: SpanOptions): T;\r\n\r\n /**\r\n * Execute an async function within a span context\r\n */\r\n withSpanAsync<T>(name: string, fn: (span: ISpan) => Promise<T>, options?: SpanOptions): Promise<T>;\r\n\r\n /**\r\n * Instrument a function with automatic span creation\r\n */\r\n instrument<TArgs extends unknown[], TReturn>(\r\n name: string,\r\n fn: (...args: TArgs) => TReturn,\r\n options?: SpanOptions\r\n ): (...args: TArgs) => TReturn;\r\n\r\n /**\r\n * Instrument an async function with automatic span creation\r\n */\r\n instrumentAsync<TArgs extends unknown[], TReturn>(\r\n name: string,\r\n fn: (...args: TArgs) => Promise<TReturn>,\r\n options?: SpanOptions\r\n ): (...args: TArgs) => Promise<TReturn>;\r\n\r\n /**\r\n * Extract trace context from headers (for incoming requests)\r\n */\r\n extractContext(headers: Record<string, string | string[] | undefined>): SpanContext | undefined;\r\n\r\n /**\r\n * Inject trace context into headers (for outgoing requests)\r\n */\r\n injectContext(headers: Record<string, string>): void;\r\n\r\n /**\r\n * Check if tracing is enabled and healthy\r\n */\r\n healthCheck(): Promise<boolean>;\r\n\r\n /**\r\n * Flush pending spans to the exporter\r\n */\r\n flush(): Promise<void>;\r\n\r\n /**\r\n * Shutdown the tracer\r\n */\r\n close(): Promise<void>;\r\n}\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// TRACING CONFIGURATION\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\nexport interface TracingConfig {\r\n /** Enable tracing */\r\n enabled: boolean;\r\n\r\n /** Service name for traces */\r\n serviceName: string;\r\n\r\n /** Service version */\r\n serviceVersion?: string;\r\n\r\n /** Environment (dev, staging, production) */\r\n environment?: string;\r\n\r\n /** Sampling rate (0.0 to 1.0) */\r\n sampleRate?: number;\r\n\r\n /** Exporter type */\r\n exporter?: 'console' | 'otlp' | 'jaeger' | 'zipkin' | 'none';\r\n\r\n /** Exporter endpoint */\r\n endpoint?: string;\r\n\r\n /** Additional resource attributes */\r\n resourceAttributes?: Record<string, string>;\r\n\r\n /** Propagation format */\r\n propagation?: 'w3c' | 'b3' | 'jaeger';\r\n}\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// MEMORY TRACING (For Testing)\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\nclass MemorySpan implements ISpan {\r\n readonly name: string;\r\n readonly context: SpanContext;\r\n readonly isRecording: boolean = true;\r\n\r\n private _attributes: Record<string, string | number | boolean> = {};\r\n private _events: SpanEvent[] = [];\r\n private _status: SpanStatus = { code: 'unset' };\r\n private _endTime?: number;\r\n private _startTime: number;\r\n\r\n constructor(name: string, traceId: string, parentSpanId?: string) {\r\n this.name = name;\r\n this._startTime = Date.now();\r\n this.context = {\r\n traceId,\r\n spanId: this.generateSpanId(),\r\n traceFlags: 1,\r\n };\r\n }\r\n\r\n private generateSpanId(): string {\r\n return Math.random().toString(16).substring(2, 18).padStart(16, '0');\r\n }\r\n\r\n setAttribute(key: string, value: string | number | boolean): this {\r\n this._attributes[key] = value;\r\n return this;\r\n }\r\n\r\n setAttributes(attributes: Record<string, string | number | boolean>): this {\r\n Object.assign(this._attributes, attributes);\r\n return this;\r\n }\r\n\r\n addEvent(name: string, attributes?: Record<string, string | number | boolean>): this {\r\n this._events.push({ name, timestamp: Date.now(), attributes });\r\n return this;\r\n }\r\n\r\n setStatus(status: SpanStatus): this {\r\n this._status = status;\r\n return this;\r\n }\r\n\r\n recordException(exception: Error, attributes?: Record<string, string | number | boolean>): this {\r\n this.addEvent('exception', {\r\n 'exception.type': exception.name,\r\n 'exception.message': exception.message,\r\n 'exception.stacktrace': exception.stack || '',\r\n ...attributes,\r\n });\r\n this.setStatus({ code: 'error', message: exception.message });\r\n return this;\r\n }\r\n\r\n updateName(name: string): this {\r\n (this as { name: string }).name = name;\r\n return this;\r\n }\r\n\r\n end(endTime?: number): void {\r\n this._endTime = endTime ?? Date.now();\r\n }\r\n\r\n // Testing helpers\r\n getAttributes(): Record<string, string | number | boolean> {\r\n return { ...this._attributes };\r\n }\r\n\r\n getEvents(): SpanEvent[] {\r\n return [...this._events];\r\n }\r\n\r\n getStatus(): SpanStatus {\r\n return { ...this._status };\r\n }\r\n\r\n getDuration(): number | undefined {\r\n return this._endTime ? this._endTime - this._startTime : undefined;\r\n }\r\n\r\n isEnded(): boolean {\r\n return this._endTime !== undefined;\r\n }\r\n}\r\n\r\nexport class MemoryTracing implements ITracing {\r\n private spans: MemorySpan[] = [];\r\n private currentSpan: MemorySpan | undefined;\r\n private traceId: string;\r\n\r\n constructor() {\r\n this.traceId = this.generateTraceId();\r\n }\r\n\r\n private generateTraceId(): string {\r\n return Math.random().toString(16).substring(2, 34).padStart(32, '0');\r\n }\r\n\r\n startSpan(name: string, options?: SpanOptions): ISpan {\r\n const span = new MemorySpan(name, this.traceId, this.currentSpan?.context.spanId);\r\n\r\n if (options?.attributes) {\r\n span.setAttributes(options.attributes);\r\n }\r\n\r\n this.spans.push(span);\r\n this.currentSpan = span;\r\n\r\n return span;\r\n }\r\n\r\n getCurrentSpan(): ISpan | undefined {\r\n return this.currentSpan;\r\n }\r\n\r\n withSpan<T>(name: string, fn: (span: ISpan) => T, options?: SpanOptions): T {\r\n const span = this.startSpan(name, options);\r\n try {\r\n const result = fn(span);\r\n span.setStatus({ code: 'ok' });\r\n return result;\r\n } catch (error) {\r\n span.recordException(error instanceof Error ? error : new Error(String(error)));\r\n throw error;\r\n } finally {\r\n span.end();\r\n }\r\n }\r\n\r\n async withSpanAsync<T>(name: string, fn: (span: ISpan) => Promise<T>, options?: SpanOptions): Promise<T> {\r\n const span = this.startSpan(name, options);\r\n try {\r\n const result = await fn(span);\r\n span.setStatus({ code: 'ok' });\r\n return result;\r\n } catch (error) {\r\n span.recordException(error instanceof Error ? error : new Error(String(error)));\r\n throw error;\r\n } finally {\r\n span.end();\r\n }\r\n }\r\n\r\n instrument<TArgs extends unknown[], TReturn>(\r\n name: string,\r\n fn: (...args: TArgs) => TReturn,\r\n options?: SpanOptions\r\n ): (...args: TArgs) => TReturn {\r\n return (...args: TArgs) => this.withSpan(name, () => fn(...args), options);\r\n }\r\n\r\n instrumentAsync<TArgs extends unknown[], TReturn>(\r\n name: string,\r\n fn: (...args: TArgs) => Promise<TReturn>,\r\n options?: SpanOptions\r\n ): (...args: TArgs) => Promise<TReturn> {\r\n return (...args: TArgs) => this.withSpanAsync(name, () => fn(...args), options);\r\n }\r\n\r\n extractContext(headers: Record<string, string | string[] | undefined>): SpanContext | undefined {\r\n const traceparent = headers['traceparent'];\r\n if (!traceparent || typeof traceparent !== 'string') return undefined;\r\n\r\n // Parse W3C Trace Context format: version-traceId-spanId-flags\r\n const parts = traceparent.split('-');\r\n if (parts.length !== 4) return undefined;\r\n\r\n return {\r\n traceId: parts[1]!,\r\n spanId: parts[2]!,\r\n traceFlags: parseInt(parts[3]!, 16),\r\n };\r\n }\r\n\r\n injectContext(headers: Record<string, string>): void {\r\n if (this.currentSpan) {\r\n const ctx = this.currentSpan.context;\r\n headers['traceparent'] = `00-${ctx.traceId}-${ctx.spanId}-${ctx.traceFlags.toString(16).padStart(2, '0')}`;\r\n }\r\n }\r\n\r\n async healthCheck(): Promise<boolean> {\r\n return true;\r\n }\r\n\r\n async flush(): Promise<void> {\r\n // No-op for memory implementation\r\n }\r\n\r\n async close(): Promise<void> {\r\n this.spans = [];\r\n this.currentSpan = undefined;\r\n }\r\n\r\n // Testing helpers\r\n getSpans(): MemorySpan[] {\r\n return [...this.spans];\r\n }\r\n\r\n getCompletedSpans(): MemorySpan[] {\r\n return this.spans.filter((s) => s.isEnded());\r\n }\r\n\r\n clear(): void {\r\n this.spans = [];\r\n this.currentSpan = undefined;\r\n this.traceId = this.generateTraceId();\r\n }\r\n}\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// NOOP TRACING (Disabled)\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\nclass NoopSpan implements ISpan {\r\n readonly name: string = '';\r\n readonly context: SpanContext = { traceId: '', spanId: '', traceFlags: 0 };\r\n readonly isRecording: boolean = false;\r\n\r\n setAttribute(): this {\r\n return this;\r\n }\r\n setAttributes(): this {\r\n return this;\r\n }\r\n addEvent(): this {\r\n return this;\r\n }\r\n setStatus(): this {\r\n return this;\r\n }\r\n recordException(): this {\r\n return this;\r\n }\r\n updateName(): this {\r\n return this;\r\n }\r\n end(): void {}\r\n}\r\n\r\nexport class NoopTracing implements ITracing {\r\n private noopSpan = new NoopSpan();\r\n\r\n startSpan(): ISpan {\r\n return this.noopSpan;\r\n }\r\n\r\n getCurrentSpan(): ISpan | undefined {\r\n return undefined;\r\n }\r\n\r\n withSpan<T>(_name: string, fn: (span: ISpan) => T): T {\r\n return fn(this.noopSpan);\r\n }\r\n\r\n async withSpanAsync<T>(_name: string, fn: (span: ISpan) => Promise<T>): Promise<T> {\r\n return fn(this.noopSpan);\r\n }\r\n\r\n instrument<TArgs extends unknown[], TReturn>(\r\n _name: string,\r\n fn: (...args: TArgs) => TReturn\r\n ): (...args: TArgs) => TReturn {\r\n return fn;\r\n }\r\n\r\n instrumentAsync<TArgs extends unknown[], TReturn>(\r\n _name: string,\r\n fn: (...args: TArgs) => Promise<TReturn>\r\n ): (...args: TArgs) => Promise<TReturn> {\r\n return fn;\r\n }\r\n\r\n extractContext(): SpanContext | undefined {\r\n return undefined;\r\n }\r\n\r\n injectContext(): void {}\r\n\r\n async healthCheck(): Promise<boolean> {\r\n return true;\r\n }\r\n\r\n async flush(): Promise<void> {}\r\n\r\n async close(): Promise<void> {}\r\n}\r\n","/**\n * Platform Configuration\n * Comprehensive Zod schema for all platform options with validation\n */\n\nimport { z } from 'zod';\n\n// ═══════════════════════════════════════════════════════════════\n// PROVIDER SCHEMAS\n// ═══════════════════════════════════════════════════════════════\n\nexport const DatabaseProviderSchema = z.enum(['memory', 'postgres', 'supabase']);\nexport const CacheProviderSchema = z.enum(['memory', 'redis', 'upstash']);\nexport const StorageProviderSchema = z.enum(['memory', 's3', 'minio', 'r2', 'supabase']);\nexport const EmailProviderSchema = z.enum(['memory', 'console', 'smtp', 'resend']);\nexport const QueueProviderSchema = z.enum(['memory', 'bullmq']);\nexport const TracingProviderSchema = z.enum(['noop', 'memory', 'otlp']);\nexport const LogLevelSchema = z.enum(['debug', 'info', 'warn', 'error']);\n\n// ═══════════════════════════════════════════════════════════════\n// SERVICE CONFIGURATION SCHEMAS\n// ═══════════════════════════════════════════════════════════════\n\nexport const DatabaseConfigSchema = z\n .object({\n provider: DatabaseProviderSchema.default('memory'),\n url: z.string().optional().describe('PostgreSQL connection URL'),\n connectionString: z.string().optional().describe('PostgreSQL connection string (alias for url)'),\n supabaseUrl: z.string().url().optional().describe('Supabase project URL'),\n supabaseAnonKey: z.string().optional().describe('Supabase anonymous key'),\n supabaseServiceRoleKey: z.string().optional().describe('Supabase service role key'),\n poolSize: z.number().int().min(1).max(100).default(10).describe('Connection pool size'),\n connectionTimeout: z.number().int().min(1000).max(60000).default(5000).describe('Connection timeout in ms'),\n ssl: z.union([z.boolean(), z.object({ rejectUnauthorized: z.boolean().optional() })]).optional().describe('SSL configuration'),\n })\n .refine(\n (data) => {\n if (data.provider === 'supabase') {\n return data.supabaseUrl && data.supabaseAnonKey;\n }\n if (data.provider === 'postgres') {\n return data.url || data.connectionString;\n }\n return true;\n },\n {\n message: 'Supabase requires supabaseUrl and supabaseAnonKey; PostgreSQL requires url or connectionString',\n }\n );\n\nexport const CacheConfigSchema = z\n .object({\n provider: CacheProviderSchema.default('memory'),\n url: z.string().url().optional().describe('Redis connection URL'),\n upstashUrl: z.string().url().optional().describe('Upstash REST URL'),\n upstashToken: z.string().optional().describe('Upstash REST token'),\n defaultTTL: z.number().int().min(0).default(3600).describe('Default TTL in seconds'),\n keyPrefix: z.string().default('').describe('Prefix for all cache keys'),\n maxRetries: z.number().int().min(0).max(10).default(3).describe('Max retries for cache operations'),\n })\n .refine(\n (data) => {\n if (data.provider === 'upstash') {\n return data.upstashUrl && data.upstashToken;\n }\n if (data.provider === 'redis') {\n return data.url;\n }\n return true;\n },\n {\n message: 'Upstash requires upstashUrl and upstashToken; Redis requires url',\n }\n );\n\nexport const StorageConfigSchema = z\n .object({\n provider: StorageProviderSchema.default('memory'),\n endpoint: z.string().url().optional().describe('S3-compatible endpoint URL'),\n region: z.string().default('us-east-1').describe('AWS region'),\n accessKey: z.string().optional().describe('AWS access key ID'),\n secretKey: z.string().optional().describe('AWS secret access key'),\n bucket: z.string().optional().describe('S3 bucket name'),\n publicUrl: z.string().url().optional().describe('Public URL for accessing files'),\n forcePathStyle: z.boolean().default(false).describe('Use path-style URLs (required for MinIO)'),\n signedUrlExpiry: z.number().int().min(60).max(604800).default(3600).describe('Signed URL expiry in seconds'),\n })\n .refine(\n (data) => {\n if (['s3', 'minio', 'r2'].includes(data.provider)) {\n return data.accessKey && data.secretKey && data.bucket;\n }\n return true;\n },\n {\n message: 'S3/MinIO/R2 requires accessKey, secretKey, and bucket',\n }\n );\n\nexport const EmailConfigSchema = z\n .object({\n provider: EmailProviderSchema.default('memory'),\n host: z.string().optional().describe('SMTP host'),\n port: z.number().int().min(1).max(65535).optional().describe('SMTP port'),\n secure: z.boolean().default(false).describe('Use TLS for SMTP'),\n username: z.string().optional().describe('SMTP username'),\n password: z.string().optional().describe('SMTP password'),\n apiKey: z.string().optional().describe('Resend API key'),\n from: z\n .string()\n .email()\n .or(z.string().regex(/^.+\\s<.+@.+>$/))\n .optional()\n .describe('Default from address'),\n replyTo: z.string().email().optional().describe('Default reply-to address'),\n rateLimitPerSecond: z.number().int().min(1).max(100).default(10).describe('Max emails per second'),\n })\n .refine(\n (data) => {\n if (data.provider === 'smtp') {\n return data.host && data.port;\n }\n if (data.provider === 'resend') {\n return data.apiKey;\n }\n return true;\n },\n {\n message: 'SMTP requires host and port; Resend requires apiKey',\n }\n );\n\nexport const QueueConfigSchema = z\n .object({\n provider: QueueProviderSchema.default('memory'),\n redisUrl: z.string().url().optional().describe('Redis connection URL for BullMQ'),\n queueName: z.string().default('platform-jobs').describe('Default queue name'),\n concurrency: z.number().int().min(1).max(100).default(5).describe('Worker concurrency'),\n maxRetries: z.number().int().min(0).max(10).default(3).describe('Max job retries'),\n retryDelay: z.number().int().min(0).default(1000).describe('Retry delay in ms'),\n removeOnComplete: z.boolean().default(true).describe('Remove completed jobs'),\n removeOnFail: z.boolean().default(false).describe('Remove failed jobs'),\n })\n .refine(\n (data) => {\n if (data.provider === 'bullmq') {\n return data.redisUrl;\n }\n return true;\n },\n {\n message: 'BullMQ requires redisUrl',\n }\n );\n\n// ═══════════════════════════════════════════════════════════════\n// RESILIENCE CONFIGURATION SCHEMAS\n// ═══════════════════════════════════════════════════════════════\n\nexport const RetryConfigSchema = z.object({\n enabled: z.boolean().default(true).describe('Enable retry for failed operations'),\n maxAttempts: z.number().int().min(1).max(10).default(3).describe('Maximum retry attempts'),\n baseDelay: z.number().int().min(0).max(10000).default(100).describe('Base delay in ms'),\n maxDelay: z.number().int().min(0).max(60000).default(5000).describe('Maximum delay in ms'),\n backoffMultiplier: z.number().min(1).max(5).default(2).describe('Exponential backoff multiplier'),\n jitter: z.boolean().default(true).describe('Add jitter to retry delays'),\n});\n\nexport const CircuitBreakerConfigSchema = z.object({\n enabled: z.boolean().default(true).describe('Enable circuit breaker'),\n failureThreshold: z.number().int().min(1).max(100).default(5).describe('Failures before opening circuit'),\n resetTimeout: z.number().int().min(1000).max(300000).default(30000).describe('Reset timeout in ms'),\n halfOpenRequests: z.number().int().min(1).max(10).default(3).describe('Requests allowed in half-open state'),\n monitorInterval: z.number().int().min(1000).max(60000).default(10000).describe('Health monitor interval in ms'),\n});\n\nexport const TimeoutConfigSchema = z.object({\n enabled: z.boolean().default(true).describe('Enable operation timeouts'),\n default: z.number().int().min(100).max(300000).default(30000).describe('Default timeout in ms'),\n database: z.number().int().min(100).max(300000).default(10000).describe('Database operation timeout'),\n cache: z.number().int().min(100).max(60000).default(5000).describe('Cache operation timeout'),\n storage: z.number().int().min(100).max(600000).default(60000).describe('Storage operation timeout'),\n email: z.number().int().min(100).max(120000).default(30000).describe('Email operation timeout'),\n queue: z.number().int().min(100).max(60000).default(10000).describe('Queue operation timeout'),\n});\n\nexport const BulkheadConfigSchema = z.object({\n enabled: z.boolean().default(false).describe('Enable bulkhead isolation'),\n maxConcurrent: z.number().int().min(1).max(1000).default(10).describe('Maximum concurrent operations'),\n maxQueued: z.number().int().min(0).max(10000).default(100).describe('Maximum queued operations'),\n timeout: z.number().int().min(0).max(300000).default(30000).describe('Queue timeout in ms'),\n});\n\nexport const ResilienceConfigSchema = z.object({\n retry: RetryConfigSchema.default({}),\n circuitBreaker: CircuitBreakerConfigSchema.default({}),\n timeout: TimeoutConfigSchema.default({}),\n bulkhead: BulkheadConfigSchema.default({}),\n});\n\n// ═══════════════════════════════════════════════════════════════\n// OBSERVABILITY CONFIGURATION SCHEMAS\n// ═══════════════════════════════════════════════════════════════\n\nexport const LoggingConfigSchema = z.object({\n level: LogLevelSchema.default('info').describe('Minimum log level'),\n format: z.enum(['json', 'pretty']).default('json').describe('Log output format'),\n includeTimestamp: z.boolean().default(true).describe('Include timestamp in logs'),\n includeCorrelationId: z.boolean().default(true).describe('Include correlation ID in logs'),\n redactKeys: z\n .array(z.string())\n .default(['password', 'token', 'secret', 'apiKey', 'authorization'])\n .describe('Keys to redact from logs'),\n});\n\nexport const MetricsConfigSchema = z.object({\n enabled: z.boolean().default(false).describe('Enable metrics collection'),\n prefix: z.string().default('platform').describe('Metric name prefix'),\n defaultTags: z.record(z.string()).default({}).describe('Default tags for all metrics'),\n flushInterval: z.number().int().min(1000).max(60000).default(10000).describe('Flush interval in ms'),\n histogramBuckets: z\n .array(z.number())\n .default([5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000])\n .describe('Histogram bucket boundaries in ms'),\n});\n\nexport const TracingConfigSchema = z.object({\n enabled: z.boolean().default(false).describe('Enable distributed tracing'),\n provider: TracingProviderSchema.default('noop').describe('Tracing provider'),\n serviceName: z.string().optional().describe('Service name for traces'),\n serviceVersion: z.string().optional().describe('Service version'),\n environment: z.string().optional().describe('Environment (dev, staging, production)'),\n sampleRate: z.number().min(0).max(1).default(1).describe('Trace sampling rate'),\n propagateContext: z.boolean().default(true).describe('Propagate trace context to downstream services'),\n endpoint: z.string().url().optional().describe('OTLP exporter endpoint'),\n exporterType: z.enum(['otlp-http', 'otlp-grpc', 'console']).default('otlp-http').describe('Exporter type'),\n});\n\nexport const ObservabilityConfigSchema = z.object({\n logging: LoggingConfigSchema.default({}),\n metrics: MetricsConfigSchema.default({}),\n tracing: TracingConfigSchema.default({}),\n});\n\n// ═══════════════════════════════════════════════════════════════\n// MIDDLEWARE CONFIGURATION SCHEMA\n// ═══════════════════════════════════════════════════════════════\n\nexport const MiddlewareConfigSchema = z.object({\n enabled: z.boolean().default(true).describe('Enable middleware chain'),\n logging: z.boolean().default(true).describe('Enable logging middleware'),\n metrics: z.boolean().default(false).describe('Enable metrics middleware'),\n slowQuery: z\n .object({\n enabled: z.boolean().default(true),\n thresholdMs: z.number().int().min(1).default(1000),\n })\n .default({}),\n cache: z\n .object({\n enabled: z.boolean().default(false),\n defaultTTL: z.number().int().min(0).default(300),\n })\n .default({}),\n});\n\n// ═══════════════════════════════════════════════════════════════\n// MAIN PLATFORM CONFIGURATION SCHEMA\n// ═══════════════════════════════════════════════════════════════\n\nexport const PlatformConfigSchema = z.object({\n // Service configurations\n database: DatabaseConfigSchema.default({ provider: 'memory' }),\n cache: CacheConfigSchema.default({ provider: 'memory' }),\n storage: StorageConfigSchema.default({ provider: 'memory' }),\n email: EmailConfigSchema.default({ provider: 'memory' }),\n queue: QueueConfigSchema.default({ provider: 'memory' }),\n\n // Resilience configuration\n resilience: ResilienceConfigSchema.default({}),\n\n // Observability configuration\n observability: ObservabilityConfigSchema.default({}),\n\n // Middleware configuration\n middleware: MiddlewareConfigSchema.default({}),\n});\n\nexport type PlatformConfig = z.infer<typeof PlatformConfigSchema>;\nexport type DatabaseConfig = z.infer<typeof DatabaseConfigSchema>;\nexport type CacheConfig = z.infer<typeof CacheConfigSchema>;\nexport type StorageConfig = z.infer<typeof StorageConfigSchema>;\nexport type EmailConfig = z.infer<typeof EmailConfigSchema>;\nexport type QueueConfig = z.infer<typeof QueueConfigSchema>;\nexport type ResilienceConfig = z.infer<typeof ResilienceConfigSchema>;\nexport type ObservabilityConfig = z.infer<typeof ObservabilityConfigSchema>;\nexport type TracingConfig = z.infer<typeof TracingConfigSchema>;\nexport type MiddlewareConfig = z.infer<typeof MiddlewareConfigSchema>;\n\n// ═══════════════════════════════════════════════════════════════\n// CONFIGURATION LOADING\n// ═══════════════════════════════════════════════════════════════\n\n/**\n * Load configuration from environment variables\n */\nexport function loadConfig(): PlatformConfig {\n return PlatformConfigSchema.parse({\n database: {\n provider: process.env.PLATFORM_DB_PROVIDER || process.env.DATABASE_PROVIDER || 'memory',\n url: process.env.DATABASE_URL,\n supabaseUrl: process.env.SUPABASE_URL,\n supabaseAnonKey: process.env.SUPABASE_ANON_KEY,\n supabaseServiceRoleKey: process.env.SUPABASE_SERVICE_ROLE_KEY,\n poolSize: process.env.DATABASE_POOL_SIZE ? parseInt(process.env.DATABASE_POOL_SIZE) : undefined,\n connectionTimeout: process.env.DATABASE_TIMEOUT ? parseInt(process.env.DATABASE_TIMEOUT) : undefined,\n },\n cache: {\n provider: process.env.PLATFORM_CACHE_PROVIDER || process.env.CACHE_PROVIDER || 'memory',\n url: process.env.REDIS_URL,\n upstashUrl: process.env.UPSTASH_REDIS_REST_URL,\n upstashToken: process.env.UPSTASH_REDIS_REST_TOKEN,\n defaultTTL: process.env.CACHE_DEFAULT_TTL ? parseInt(process.env.CACHE_DEFAULT_TTL) : undefined,\n keyPrefix: process.env.CACHE_KEY_PREFIX,\n },\n storage: {\n provider: process.env.PLATFORM_STORAGE_PROVIDER || process.env.STORAGE_PROVIDER || 'memory',\n endpoint: process.env.S3_ENDPOINT,\n region: process.env.S3_REGION || process.env.AWS_REGION || 'us-east-1',\n accessKey: process.env.S3_ACCESS_KEY_ID || process.env.AWS_ACCESS_KEY_ID,\n secretKey: process.env.S3_SECRET_ACCESS_KEY || process.env.AWS_SECRET_ACCESS_KEY,\n bucket: process.env.S3_BUCKET,\n publicUrl: process.env.S3_PUBLIC_URL,\n forcePathStyle: process.env.S3_FORCE_PATH_STYLE === 'true',\n signedUrlExpiry: process.env.S3_SIGNED_URL_EXPIRY ? parseInt(process.env.S3_SIGNED_URL_EXPIRY) : undefined,\n },\n email: {\n provider: process.env.PLATFORM_EMAIL_PROVIDER || process.env.EMAIL_PROVIDER || 'memory',\n host: process.env.SMTP_HOST,\n port: process.env.SMTP_PORT ? parseInt(process.env.SMTP_PORT) : undefined,\n secure: process.env.SMTP_SECURE === 'true',\n username: process.env.SMTP_USERNAME,\n password: process.env.SMTP_PASSWORD,\n apiKey: process.env.RESEND_API_KEY,\n from: process.env.EMAIL_FROM,\n replyTo: process.env.EMAIL_REPLY_TO,\n },\n queue: {\n provider: process.env.PLATFORM_QUEUE_PROVIDER || process.env.QUEUE_PROVIDER || 'memory',\n redisUrl: process.env.REDIS_URL,\n queueName: process.env.QUEUE_NAME,\n concurrency: process.env.QUEUE_CONCURRENCY ? parseInt(process.env.QUEUE_CONCURRENCY) : undefined,\n maxRetries: process.env.QUEUE_MAX_RETRIES ? parseInt(process.env.QUEUE_MAX_RETRIES) : undefined,\n },\n resilience: {\n retry: {\n enabled: process.env.RESILIENCE_RETRY_ENABLED !== 'false',\n maxAttempts: process.env.RESILIENCE_RETRY_MAX_ATTEMPTS\n ? parseInt(process.env.RESILIENCE_RETRY_MAX_ATTEMPTS)\n : undefined,\n baseDelay: process.env.RESILIENCE_RETRY_BASE_DELAY\n ? parseInt(process.env.RESILIENCE_RETRY_BASE_DELAY)\n : undefined,\n maxDelay: process.env.RESILIENCE_RETRY_MAX_DELAY\n ? parseInt(process.env.RESILIENCE_RETRY_MAX_DELAY)\n : undefined,\n },\n circuitBreaker: {\n enabled: process.env.RESILIENCE_CIRCUIT_BREAKER_ENABLED !== 'false',\n failureThreshold: process.env.RESILIENCE_CIRCUIT_BREAKER_THRESHOLD\n ? parseInt(process.env.RESILIENCE_CIRCUIT_BREAKER_THRESHOLD)\n : undefined,\n resetTimeout: process.env.RESILIENCE_CIRCUIT_BREAKER_RESET_TIMEOUT\n ? parseInt(process.env.RESILIENCE_CIRCUIT_BREAKER_RESET_TIMEOUT)\n : undefined,\n },\n timeout: {\n enabled: process.env.RESILIENCE_TIMEOUT_ENABLED !== 'false',\n default: process.env.RESILIENCE_TIMEOUT_DEFAULT\n ? parseInt(process.env.RESILIENCE_TIMEOUT_DEFAULT)\n : undefined,\n },\n },\n observability: {\n logging: {\n level: (process.env.LOG_LEVEL as 'debug' | 'info' | 'warn' | 'error') || 'info',\n format: (process.env.LOG_FORMAT as 'json' | 'pretty') || 'json',\n },\n metrics: {\n enabled: process.env.METRICS_ENABLED === 'true',\n prefix: process.env.METRICS_PREFIX,\n },\n tracing: {\n enabled: process.env.TRACING_ENABLED === 'true',\n provider: (process.env.TRACING_PROVIDER as 'noop' | 'memory' | 'otlp') || 'noop',\n serviceName: process.env.SERVICE_NAME || process.env.OTEL_SERVICE_NAME,\n serviceVersion: process.env.SERVICE_VERSION,\n environment: process.env.NODE_ENV,\n sampleRate: process.env.TRACING_SAMPLE_RATE ? parseFloat(process.env.TRACING_SAMPLE_RATE) : undefined,\n endpoint: process.env.OTEL_EXPORTER_OTLP_ENDPOINT || process.env.TRACING_ENDPOINT,\n exporterType: (process.env.OTEL_EXPORTER_TYPE as 'otlp-http' | 'otlp-grpc' | 'console') || 'otlp-http',\n },\n },\n middleware: {\n enabled: process.env.MIDDLEWARE_ENABLED !== 'false',\n logging: process.env.MIDDLEWARE_LOGGING !== 'false',\n metrics: process.env.MIDDLEWARE_METRICS === 'true',\n slowQuery: {\n enabled: process.env.MIDDLEWARE_SLOW_QUERY !== 'false',\n thresholdMs: process.env.MIDDLEWARE_SLOW_QUERY_THRESHOLD\n ? parseInt(process.env.MIDDLEWARE_SLOW_QUERY_THRESHOLD)\n : undefined,\n },\n },\n });\n}\n\n/**\n * Validate configuration object\n * @throws ZodError if validation fails\n */\nexport function validateConfig(config: unknown): PlatformConfig {\n return PlatformConfigSchema.parse(config);\n}\n\n/**\n * Safely validate configuration, returning errors instead of throwing\n */\nexport function safeValidateConfig(config: unknown): {\n success: boolean;\n data?: PlatformConfig;\n errors?: z.ZodError;\n} {\n const result = PlatformConfigSchema.safeParse(config);\n if (result.success) {\n return { success: true, data: result.data };\n }\n return { success: false, errors: result.error };\n}\n\n/**\n * Get configuration with defaults applied\n */\nexport function getDefaultConfig(): PlatformConfig {\n return PlatformConfigSchema.parse({});\n}\n","/**\n * Memory Database Adapter\n * In-memory implementation for testing\n */\n\nimport { IDatabase, IQueryBuilder, QueryResult } from '../../interfaces/IDatabase';\n\nexport class MemoryDatabase implements IDatabase {\n private tables: Map<string, unknown[]> = new Map();\n\n from<T = unknown>(table: string): IQueryBuilder<T> {\n if (!this.tables.has(table)) {\n this.tables.set(table, []);\n }\n return new MemoryQueryBuilder<T>(this.tables, table);\n }\n\n async raw<T = unknown>(sql: string, params?: unknown[]): Promise<QueryResult<T>> {\n // Basic implementation - just return empty for now\n console.warn('MemoryDatabase.raw() is a stub implementation');\n return { data: [] };\n }\n\n async transaction<T>(fn: (tx: IDatabase) => Promise<T>): Promise<T> {\n // Memory adapter doesn't need real transactions\n return fn(this);\n }\n\n async healthCheck(): Promise<boolean> {\n return true;\n }\n\n async close(): Promise<void> {\n this.tables.clear();\n }\n\n /**\n * Clear all data (for testing)\n */\n clear(): void {\n this.tables.clear();\n }\n\n /**\n * Get table data (for testing)\n */\n getTable<T = unknown>(tableName: string): T[] {\n return (this.tables.get(tableName) as T[]) ?? [];\n }\n}\n\nclass MemoryQueryBuilder<T = unknown> implements IQueryBuilder<T> {\n private tables: Map<string, unknown[]>;\n private tableName: string;\n private _select: string[] = ['*'];\n private _where: Array<{ column: string; operator: string; value: unknown }> = [];\n private _orderBy: { column: string; direction: 'asc' | 'desc' } | null = null;\n private _limit: number | null = null;\n private _offset: number = 0;\n private _insertData: Partial<T>[] | null = null;\n private _updateData: Partial<T> | null = null;\n private _deleteFlag: boolean = false;\n\n constructor(tables: Map<string, unknown[]>, tableName: string) {\n this.tables = tables;\n this.tableName = tableName;\n }\n\n select(columns?: string | string[]): IQueryBuilder<T> {\n if (columns) {\n this._select = Array.isArray(columns) ? columns : [columns];\n }\n return this;\n }\n\n insert(data: Partial<T> | Partial<T>[]): IQueryBuilder<T> {\n this._insertData = Array.isArray(data) ? data : [data];\n return this;\n }\n\n update(data: Partial<T>): IQueryBuilder<T> {\n this._updateData = data;\n return this;\n }\n\n delete(): IQueryBuilder<T> {\n this._deleteFlag = true;\n return this;\n }\n\n where(column: string, operator: string, value: unknown): IQueryBuilder<T> {\n this._where.push({ column, operator, value });\n return this;\n }\n\n whereIn(column: string, values: unknown[]): IQueryBuilder<T> {\n this._where.push({ column, operator: 'in', value: values });\n return this;\n }\n\n orderBy(column: string, direction: 'asc' | 'desc' = 'asc'): IQueryBuilder<T> {\n this._orderBy = { column, direction };\n return this;\n }\n\n limit(count: number): IQueryBuilder<T> {\n this._limit = count;\n return this;\n }\n\n offset(count: number): IQueryBuilder<T> {\n this._offset = count;\n return this;\n }\n\n async single(): Promise<{ data: T | null; error?: Error }> {\n const result = await this.execute();\n return { data: result.data[0] || null };\n }\n\n async execute(): Promise<QueryResult<T>> {\n const table = this.tables.get(this.tableName) as T[] || [];\n\n // Handle insert\n if (this._insertData) {\n const newItems = this._insertData.map((item, i) => ({\n id: `mem_${Date.now()}_${i}`,\n ...item,\n created_at: new Date().toISOString(),\n }));\n this.tables.set(this.tableName, [...table, ...newItems]);\n return { data: newItems as T[] };\n }\n\n // Handle delete\n if (this._deleteFlag) {\n const filtered = table.filter(item => !this.matchesWhere(item));\n const deleted = table.filter(item => this.matchesWhere(item));\n this.tables.set(this.tableName, filtered);\n return { data: deleted, count: deleted.length };\n }\n\n // Handle update\n if (this._updateData) {\n const updated: T[] = [];\n const newTable = table.map(item => {\n if (this.matchesWhere(item)) {\n const updatedItem = { ...item, ...this._updateData, updated_at: new Date().toISOString() };\n updated.push(updatedItem as T);\n return updatedItem;\n }\n return item;\n });\n this.tables.set(this.tableName, newTable);\n return { data: updated, count: updated.length };\n }\n\n // Handle select\n let result = table.filter(item => this.matchesWhere(item));\n\n // Sort\n if (this._orderBy) {\n const { column, direction } = this._orderBy;\n result.sort((a, b) => {\n const aVal = (a as Record<string, unknown>)[column] as string | number | null;\n const bVal = (b as Record<string, unknown>)[column] as string | number | null;\n if (aVal === null || aVal === undefined) return direction === 'asc' ? 1 : -1;\n if (bVal === null || bVal === undefined) return direction === 'asc' ? -1 : 1;\n const cmp = aVal < bVal ? -1 : aVal > bVal ? 1 : 0;\n return direction === 'asc' ? cmp : -cmp;\n });\n }\n\n // Pagination\n if (this._offset > 0 || this._limit !== null) {\n const start = this._offset;\n const end = this._limit !== null ? start + this._limit : undefined;\n result = result.slice(start, end);\n }\n\n return { data: result, count: result.length };\n }\n\n private matchesWhere(item: T): boolean {\n if (this._where.length === 0) return true;\n \n return this._where.every(({ column, operator, value }) => {\n const itemValue = (item as Record<string, unknown>)[column];\n \n switch (operator) {\n case '=':\n case '==':\n return itemValue === value;\n case '!=':\n case '<>':\n return itemValue !== value;\n case '>':\n return (itemValue as number) > (value as number);\n case '>=':\n return (itemValue as number) >= (value as number);\n case '<':\n return (itemValue as number) < (value as number);\n case '<=':\n return (itemValue as number) <= (value as number);\n case 'in':\n return Array.isArray(value) && value.includes(itemValue);\n case 'like':\n return String(itemValue).includes(String(value).replace(/%/g, ''));\n default:\n return itemValue === value;\n }\n });\n }\n}\n","/**\n * Memory Cache Adapter\n * In-memory implementation for testing\n */\n\nimport { ICache } from '../../interfaces/ICache';\n\ninterface CacheEntry<T> {\n value: T;\n expiresAt: number | null;\n}\n\nexport class MemoryCache implements ICache {\n private store: Map<string, CacheEntry<unknown>> = new Map();\n private subscriptions: Map<string, Set<(message: string) => void>> = new Map();\n\n async get<T = unknown>(key: string): Promise<T | null> {\n const entry = this.store.get(key);\n if (!entry) return null;\n \n if (entry.expiresAt && Date.now() > entry.expiresAt) {\n this.store.delete(key);\n return null;\n }\n \n return entry.value as T;\n }\n\n async set<T = unknown>(key: string, value: T, ttl?: number): Promise<void> {\n const expiresAt = ttl ? Date.now() + ttl * 1000 : null;\n this.store.set(key, { value, expiresAt });\n }\n\n async delete(key: string): Promise<void> {\n this.store.delete(key);\n }\n\n async exists(key: string): Promise<boolean> {\n const value = await this.get(key);\n return value !== null;\n }\n\n async deletePattern(pattern: string): Promise<number> {\n const regex = new RegExp('^' + pattern.replace(/\\*/g, '.*') + '$');\n let count = 0;\n \n for (const key of this.store.keys()) {\n if (regex.test(key)) {\n this.store.delete(key);\n count++;\n }\n }\n \n return count;\n }\n\n async mget<T = unknown>(keys: string[]): Promise<(T | null)[]> {\n return Promise.all(keys.map(key => this.get<T>(key)));\n }\n\n async mset<T = unknown>(entries: Array<{ key: string; value: T; ttl?: number }>): Promise<void> {\n await Promise.all(entries.map(({ key, value, ttl }) => this.set(key, value, ttl)));\n }\n\n async incr(key: string, by: number = 1): Promise<number> {\n const current = await this.get<number>(key) || 0;\n const newValue = current + by;\n await this.set(key, newValue);\n return newValue;\n }\n\n async publish(channel: string, message: string): Promise<void> {\n const subscribers = this.subscriptions.get(channel);\n if (subscribers) {\n subscribers.forEach(callback => callback(message));\n }\n }\n\n async subscribe(channel: string, callback: (message: string) => void): Promise<() => void> {\n if (!this.subscriptions.has(channel)) {\n this.subscriptions.set(channel, new Set());\n }\n \n this.subscriptions.get(channel)!.add(callback);\n \n return () => {\n this.subscriptions.get(channel)?.delete(callback);\n };\n }\n\n async healthCheck(): Promise<boolean> {\n return true;\n }\n\n async close(): Promise<void> {\n this.store.clear();\n this.subscriptions.clear();\n }\n\n /**\n * Clear all cached data (for testing)\n */\n clear(): void {\n this.store.clear();\n this.subscriptions.clear();\n }\n\n /**\n * Get number of cached items (for testing)\n */\n get size(): number {\n return this.store.size;\n }\n}\n","// Memory Storage - stub implementation\nimport { IStorage, StorageFile, UploadOptions } from \"../../interfaces/IStorage\";\n\nexport class MemoryStorage implements IStorage {\n private files = new Map<string, { data: Buffer; contentType?: string }>();\n \n async upload(key: string, data: Buffer | Blob | ReadableStream, options?: UploadOptions) { \n this.files.set(key, { data: Buffer.from(\"mock\"), contentType: options?.contentType }); \n return { url: \"memory://\" + key }; \n }\n async download(key: string) { return this.files.get(key)?.data || Buffer.from(\"\"); }\n async getSignedUrl(key: string) { return \"memory://\" + key; }\n async delete(key: string) { this.files.delete(key); }\n async deleteMany(keys: string[]) { keys.forEach(k => this.files.delete(k)); }\n async list(prefix?: string): Promise<StorageFile[]> { return []; }\n async exists(key: string) { return this.files.has(key); }\n async getMetadata(key: string) { return null; }\n async healthCheck() { return true; }\n\n /**\n * Clear all files (for testing)\n */\n clear(): void {\n this.files.clear();\n }\n\n /**\n * Get number of stored files (for testing)\n */\n get size(): number {\n return this.files.size;\n }\n}\n","// Memory Email - stub implementation\nimport { IEmail, EmailMessage, EmailResult } from \"../../interfaces/IEmail\";\n\nexport class MemoryEmail implements IEmail {\n private sentEmails: EmailMessage[] = [];\n \n async send(message: EmailMessage): Promise<EmailResult> {\n this.sentEmails.push(message);\n return { id: \"mem_\" + this.sentEmails.length, success: true };\n }\n \n async sendBatch(messages: EmailMessage[]): Promise<EmailResult[]> {\n return Promise.all(messages.map(m => this.send(m)));\n }\n \n async healthCheck() { return true; }\n \n // Test helpers\n getSentEmails(): EmailMessage[] { return this.sentEmails; }\n\n /**\n * Clear sent emails (for testing)\n */\n clear(): void {\n this.sentEmails = [];\n }\n\n /**\n * Get number of sent emails (for testing)\n */\n get size(): number {\n return this.sentEmails.length;\n }\n}\n","// Memory Queue - stub implementation\nimport { IQueue, Job, JobOptions } from \"../../interfaces/IQueue\";\n\nexport class MemoryQueue<T = unknown> implements IQueue<T> {\n private jobs: Job<T>[] = [];\n private handlers: Array<(job: Job<T>) => Promise<unknown>> = [];\n \n async add(name: string, data: T, options?: JobOptions): Promise<Job<T>> {\n const job: Job<T> = { id: \"job_\" + this.jobs.length, name, data, attemptsMade: 0, progress: 0, timestamp: Date.now() };\n this.jobs.push(job);\n this.handlers.forEach(h => h(job));\n return job;\n }\n \n async addBulk(jobs: Array<{ name: string; data: T; options?: JobOptions }>) {\n return Promise.all(jobs.map(j => this.add(j.name, j.data, j.options)));\n }\n \n process(handler: (job: Job<T>) => Promise<unknown>) { this.handlers.push(handler); }\n async getJob(id: string) { return this.jobs.find(j => j.id === id) || null; }\n async removeJob(id: string) { this.jobs = this.jobs.filter(j => j.id !== id); }\n async pause() {}\n async resume() {}\n async getStats() { return { waiting: 0, active: 0, completed: this.jobs.length, failed: 0, delayed: 0 }; }\n async healthCheck() { return true; }\n async close() { this.jobs = []; }\n\n /**\n * Clear all jobs (for testing)\n */\n clear(): void {\n this.jobs = [];\n this.handlers = [];\n }\n\n /**\n * Get all jobs (for testing)\n */\n getJobs(): Job<T>[] {\n return this.jobs;\n }\n\n /**\n * Get pending jobs (for testing)\n */\n getPendingJobs(): Job<T>[] {\n return this.jobs.filter(j => j.progress < 100);\n }\n\n /**\n * Get number of jobs (for testing)\n */\n get size(): number {\n return this.jobs.length;\n }\n}\n","/**\r\n * Console Email Adapter\r\n * Development implementation that logs emails to console instead of sending\r\n */\r\n\r\nimport { IEmail, EmailMessage, EmailResult, EmailAddress } from '../../interfaces/IEmail';\r\n\r\nexport class ConsoleEmail implements IEmail {\r\n private sentEmails: EmailMessage[] = [];\r\n\r\n async send(message: EmailMessage): Promise<EmailResult> {\r\n const id = `console_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;\r\n\r\n console.log('\\n' + '='.repeat(60));\r\n console.log('📧 EMAIL SENT (Console Adapter)');\r\n console.log('='.repeat(60));\r\n console.log(`ID: ${id}`);\r\n console.log(`To: ${this.formatAddresses(message.to)}`);\r\n console.log(`From: ${message.from ? this.formatAddress(message.from) : '(default)'}`);\r\n console.log(`Subject: ${message.subject}`);\r\n\r\n if (message.replyTo) {\r\n console.log(`Reply-To: ${this.formatAddress(message.replyTo)}`);\r\n }\r\n\r\n if (message.tags && message.tags.length > 0) {\r\n console.log(`Tags: ${message.tags.join(', ')}`);\r\n }\r\n\r\n if (message.attachments && message.attachments.length > 0) {\r\n console.log(`Attachments: ${message.attachments.map((a) => a.filename).join(', ')}`);\r\n }\r\n\r\n console.log('-'.repeat(60));\r\n\r\n if (message.text) {\r\n console.log('TEXT BODY:');\r\n console.log(message.text.slice(0, 500) + (message.text.length > 500 ? '\\n...(truncated)' : ''));\r\n }\r\n\r\n if (message.html) {\r\n console.log('HTML BODY: [HTML content - ' + message.html.length + ' chars]');\r\n }\r\n\r\n console.log('='.repeat(60) + '\\n');\r\n\r\n this.sentEmails.push(message);\r\n\r\n return {\r\n id,\r\n success: true,\r\n };\r\n }\r\n\r\n async sendBatch(messages: EmailMessage[]): Promise<EmailResult[]> {\r\n const results: EmailResult[] = [];\r\n\r\n for (const message of messages) {\r\n results.push(await this.send(message));\r\n }\r\n\r\n return results;\r\n }\r\n\r\n async healthCheck(): Promise<boolean> {\r\n return true;\r\n }\r\n\r\n /**\r\n * Get all sent emails (for testing)\r\n */\r\n getSentEmails(): EmailMessage[] {\r\n return [...this.sentEmails];\r\n }\r\n\r\n /**\r\n * Clear sent emails (for testing)\r\n */\r\n clearSentEmails(): void {\r\n this.sentEmails = [];\r\n }\r\n\r\n private formatAddress(address: EmailAddress): string {\r\n if (address.name) {\r\n return `${address.name} <${address.email}>`;\r\n }\r\n return address.email;\r\n }\r\n\r\n private formatAddresses(addresses: EmailAddress | EmailAddress[]): string {\r\n const list = Array.isArray(addresses) ? addresses : [addresses];\r\n return list.map((addr) => this.formatAddress(addr)).join(', ');\r\n }\r\n}\r\n","/**\n * Platform Factory\n * Create a platform instance with configured adapters\n */\n\nimport { IPlatform, PlatformHealthStatus, IDatabase, ICache, IStorage, IEmail, IQueue, ILogger, IMetrics, ITracing } from './interfaces';\nimport { PlatformConfig, loadConfig } from './config';\n\n// Memory adapters (always available)\nimport { MemoryDatabase } from './adapters/memory/MemoryDatabase';\nimport { MemoryCache } from './adapters/memory/MemoryCache';\nimport { MemoryStorage } from './adapters/memory/MemoryStorage';\nimport { MemoryEmail } from './adapters/memory/MemoryEmail';\nimport { MemoryQueue } from './adapters/memory/MemoryQueue';\n\n// Console adapters\nimport { ConsoleEmail } from './adapters/console/ConsoleEmail';\n\n// Tracing adapters (always available)\nimport { MemoryTracing, NoopTracing } from './interfaces/ITracing';\n\n// Logger and Metrics (always available)\nimport { ConsoleLogger, NoopLogger } from './interfaces/ILogger';\nimport { MemoryMetrics, NoopMetrics } from './interfaces/IMetrics';\n\n/**\n * Create a database adapter based on configuration\n */\nasync function createDatabaseAdapter(config: PlatformConfig): Promise<IDatabase> {\n switch (config.database.provider) {\n case 'postgres': {\n const connectionString = config.database.connectionString || config.database.url || process.env.DATABASE_URL;\n if (!connectionString) {\n throw new Error('PostgreSQL requires DATABASE_URL, url, or connectionString configuration');\n }\n const { PostgresDatabase } = await import('./adapters/postgres/PostgresDatabase');\n return PostgresDatabase.create({\n connectionString,\n max: config.database.poolSize,\n ssl: config.database.ssl,\n connectionTimeoutMillis: config.database.connectionTimeout,\n });\n }\n case 'supabase': {\n if (!config.database.supabaseUrl || !config.database.supabaseAnonKey) {\n throw new Error('Supabase requires SUPABASE_URL and SUPABASE_ANON_KEY environment variables');\n }\n const { createClient } = await import('@supabase/supabase-js');\n const { SupabaseDatabase } = await import('./adapters/supabase/SupabaseDatabase');\n const client = createClient(\n config.database.supabaseUrl,\n config.database.supabaseServiceRoleKey || config.database.supabaseAnonKey\n );\n return new SupabaseDatabase(client);\n }\n case 'memory':\n default:\n return new MemoryDatabase();\n }\n}\n\n/**\n * Create a cache adapter based on configuration\n */\nasync function createCacheAdapter(config: PlatformConfig): Promise<ICache> {\n switch (config.cache.provider) {\n case 'redis': {\n const url = config.cache.url || process.env.REDIS_URL;\n if (!url) {\n throw new Error('Redis requires REDIS_URL or cache.url configuration');\n }\n const { RedisCache } = await import('./adapters/redis/RedisCache');\n return RedisCache.create({\n url,\n keyPrefix: config.cache.keyPrefix,\n });\n }\n case 'upstash': {\n if (!config.cache.upstashUrl || !config.cache.upstashToken) {\n throw new Error('Upstash requires UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN environment variables');\n }\n const { Redis } = await import('@upstash/redis');\n const { UpstashCache } = await import('./adapters/upstash/UpstashCache');\n const client = new Redis({\n url: config.cache.upstashUrl,\n token: config.cache.upstashToken,\n });\n return new UpstashCache(client);\n }\n case 'memory':\n default:\n return new MemoryCache();\n }\n}\n\n/**\n * Create a storage adapter based on configuration\n */\nasync function createStorageAdapter(config: PlatformConfig): Promise<IStorage> {\n switch (config.storage.provider) {\n case 'supabase': {\n const url = config.database.supabaseUrl || process.env.SUPABASE_URL;\n const apiKey = config.database.supabaseServiceRoleKey || config.database.supabaseAnonKey || process.env.SUPABASE_ANON_KEY;\n const bucket = config.storage.bucket || process.env.SUPABASE_STORAGE_BUCKET || 'uploads';\n\n if (!url || !apiKey) {\n throw new Error('Supabase storage requires SUPABASE_URL and SUPABASE_ANON_KEY');\n }\n\n const { SupabaseStorage } = await import('./adapters/supabase-storage/SupabaseStorage');\n return SupabaseStorage.create({\n url,\n apiKey,\n bucket,\n publicBucket: config.storage.publicUrl !== undefined,\n signedUrlExpiry: config.storage.signedUrlExpiry,\n });\n }\n case 's3':\n case 'minio':\n case 'r2': {\n if (!config.storage.accessKey || !config.storage.secretKey || !config.storage.bucket) {\n throw new Error('S3 requires S3_ACCESS_KEY, S3_SECRET_KEY, and S3_BUCKET environment variables');\n }\n const { S3Client } = await import('@aws-sdk/client-s3');\n const { getSignedUrl } = await import('@aws-sdk/s3-request-presigner');\n const { S3Storage } = await import('./adapters/s3/S3Storage');\n\n const client = new S3Client({\n endpoint: config.storage.endpoint,\n region: config.storage.region || 'us-east-1',\n credentials: {\n accessKeyId: config.storage.accessKey,\n secretAccessKey: config.storage.secretKey,\n },\n forcePathStyle: config.storage.forcePathStyle || config.storage.provider === 'minio',\n });\n\n return new S3Storage(client, config.storage.bucket, getSignedUrl, config.storage.publicUrl);\n }\n case 'memory':\n default:\n return new MemoryStorage();\n }\n}\n\n/**\n * Create an email adapter based on configuration\n */\nasync function createEmailAdapter(config: PlatformConfig): Promise<IEmail> {\n switch (config.email.provider) {\n case 'smtp': {\n if (!config.email.host || !config.email.port) {\n throw new Error('SMTP requires host and port configuration (SMTP_HOST, SMTP_PORT)');\n }\n const { SmtpEmail } = await import('./adapters/smtp/SmtpEmail');\n return SmtpEmail.create({\n host: config.email.host,\n port: config.email.port,\n secure: config.email.secure,\n username: config.email.username,\n password: config.email.password,\n from: config.email.from,\n });\n }\n case 'resend': {\n if (!config.email.apiKey) {\n throw new Error('Resend requires RESEND_API_KEY environment variable');\n }\n const { Resend } = await import('resend');\n const { ResendEmail } = await import('./adapters/resend/ResendEmail');\n const client = new Resend(config.email.apiKey);\n return new ResendEmail(client, config.email.from);\n }\n case 'console':\n return new ConsoleEmail();\n case 'memory':\n default:\n return new MemoryEmail();\n }\n}\n\n/**\n * Create a queue adapter based on configuration\n */\nasync function createQueueAdapter(config: PlatformConfig): Promise<IQueue> {\n switch (config.queue.provider) {\n case 'bullmq': {\n if (!config.queue.redisUrl && !config.cache.url) {\n throw new Error('BullMQ requires REDIS_URL environment variable');\n }\n const { BullMQQueue } = await import('./adapters/bullmq/BullMQQueue');\n return new BullMQQueue({\n redisUrl: config.queue.redisUrl || config.cache.url,\n queueName: 'platform-jobs',\n });\n }\n case 'memory':\n default:\n return new MemoryQueue();\n }\n}\n\n/**\n * Create a tracing adapter based on configuration\n */\nasync function createTracingAdapter(config: PlatformConfig): Promise<ITracing> {\n const tracingConfig = config.observability.tracing;\n\n // If tracing is disabled, return noop\n if (!tracingConfig.enabled) {\n return new NoopTracing();\n }\n\n switch (tracingConfig.provider) {\n case 'otlp': {\n // OpenTelemetry adapter - dynamically imported\n const { OpenTelemetryTracing } = await import('./adapters/opentelemetry/OpenTelemetryTracing');\n return OpenTelemetryTracing.create({\n serviceName: tracingConfig.serviceName || 'unknown-service',\n serviceVersion: tracingConfig.serviceVersion,\n environment: tracingConfig.environment,\n endpoint: tracingConfig.endpoint,\n exporterType: tracingConfig.exporterType,\n sampleRate: tracingConfig.sampleRate,\n });\n }\n case 'memory':\n return new MemoryTracing();\n case 'noop':\n default:\n return new NoopTracing();\n }\n}\n\n/**\n * Create a logger based on configuration\n */\nfunction createLogger(config: PlatformConfig): ILogger {\n if (!config.observability.logging) {\n return new NoopLogger();\n }\n\n return new ConsoleLogger({\n level: config.observability.logging.level,\n service: config.observability.tracing.serviceName,\n environment: config.observability.tracing.environment,\n });\n}\n\n/**\n * Create a metrics collector based on configuration\n */\nfunction createMetrics(config: PlatformConfig): IMetrics {\n if (!config.observability.metrics.enabled) {\n return new NoopMetrics();\n }\n\n // MemoryMetrics is a simple in-memory implementation\n // Production metrics would use a dedicated backend (Prometheus, StatsD, etc.)\n return new MemoryMetrics();\n}\n\n/**\n * Create a platform instance (async version)\n */\nexport async function createPlatformAsync(config?: Partial<PlatformConfig>): Promise<IPlatform> {\n const finalConfig = config ? deepMerge(loadConfig(), config) : loadConfig();\n\n const [db, cache, storage, email, queue, tracing] = await Promise.all([\n createDatabaseAdapter(finalConfig),\n createCacheAdapter(finalConfig),\n createStorageAdapter(finalConfig),\n createEmailAdapter(finalConfig),\n createQueueAdapter(finalConfig),\n createTracingAdapter(finalConfig),\n ]);\n\n const logger = createLogger(finalConfig);\n const metrics = createMetrics(finalConfig);\n\n return createPlatformFromAdapters(db, cache, storage, email, queue, logger, metrics, tracing);\n}\n\n/**\n * Create a platform instance (sync version - uses memory adapters only)\n * For production adapters, use createPlatformAsync\n */\nexport function createPlatform(config?: Partial<PlatformConfig>): IPlatform {\n const finalConfig = config ? deepMerge(loadConfig(), config) : loadConfig();\n\n // Check if any production adapters are requested\n const hasProductionAdapters =\n finalConfig.database.provider !== 'memory' ||\n finalConfig.cache.provider !== 'memory' ||\n finalConfig.storage.provider !== 'memory' ||\n (finalConfig.email.provider !== 'memory' && finalConfig.email.provider !== 'console') ||\n finalConfig.observability.tracing.provider === 'otlp';\n\n if (hasProductionAdapters) {\n console.warn(\n 'createPlatform() is synchronous and cannot initialize production adapters. ' +\n 'Use createPlatformAsync() for production adapters, or use memory/console adapters.'\n );\n }\n\n // Create sync-compatible adapters\n const db = new MemoryDatabase();\n const cache = new MemoryCache();\n const storage = new MemoryStorage();\n const email = finalConfig.email.provider === 'console' ? new ConsoleEmail() : new MemoryEmail();\n const queue = new MemoryQueue();\n const logger = createLogger(finalConfig);\n const metrics = createMetrics(finalConfig);\n const tracing = finalConfig.observability.tracing.provider === 'memory'\n ? new MemoryTracing()\n : new NoopTracing();\n\n return createPlatformFromAdapters(db, cache, storage, email, queue, logger, metrics, tracing);\n}\n\n/**\n * Create platform object from adapters\n */\nfunction createPlatformFromAdapters(\n db: IDatabase,\n cache: ICache,\n storage: IStorage,\n email: IEmail,\n queue: IQueue,\n logger: ILogger,\n metrics: IMetrics,\n tracing: ITracing\n): IPlatform {\n return {\n db,\n cache,\n storage,\n email,\n queue,\n logger,\n metrics,\n tracing,\n\n async healthCheck(): Promise<PlatformHealthStatus> {\n const [dbHealth, cacheHealth, storageHealth, emailHealth, queueHealth, tracingHealth] = await Promise.all([\n db.healthCheck(),\n cache.healthCheck(),\n storage.healthCheck(),\n email.healthCheck(),\n queue.healthCheck(),\n tracing.healthCheck(),\n ]);\n\n return {\n healthy: dbHealth && cacheHealth && storageHealth && emailHealth && queueHealth && tracingHealth,\n services: {\n database: dbHealth,\n cache: cacheHealth,\n storage: storageHealth,\n email: emailHealth,\n queue: queueHealth,\n tracing: tracingHealth,\n },\n timestamp: Date.now(),\n };\n },\n\n async close(): Promise<void> {\n await Promise.all([db.close(), cache.close(), queue.close(), tracing.close()]);\n },\n };\n}\n\n/**\n * Deep merge two objects\n */\nfunction deepMerge<T extends Record<string, unknown>>(target: T, source: Partial<T>): T {\n const result = { ...target };\n\n for (const key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n const sourceValue = source[key];\n const targetValue = target[key];\n\n if (\n sourceValue !== undefined &&\n typeof sourceValue === 'object' &&\n sourceValue !== null &&\n !Array.isArray(sourceValue) &&\n typeof targetValue === 'object' &&\n targetValue !== null &&\n !Array.isArray(targetValue)\n ) {\n result[key] = deepMerge(\n targetValue as Record<string, unknown>,\n sourceValue as Record<string, unknown>\n ) as T[Extract<keyof T, string>];\n } else if (sourceValue !== undefined) {\n result[key] = sourceValue as T[Extract<keyof T, string>];\n }\n }\n }\n\n return result;\n}\n","/**\r\n * Middleware Chain Implementation\r\n */\r\n\r\nimport { randomUUID } from 'crypto';\r\nimport type { Middleware, MiddlewareChain, MiddlewareChainOptions, MiddlewareContext } from './types';\r\nimport { NoopLogger } from '../interfaces/ILogger';\r\nimport type { ILogger } from '../interfaces/ILogger';\r\n\r\n/**\r\n * Create a new middleware chain\r\n */\r\nexport function createMiddlewareChain(options: MiddlewareChainOptions = {}): MiddlewareChain {\r\n const middlewares: Middleware[] = [];\r\n const logger = options.logger ?? new NoopLogger();\r\n const generateCorrelationId = options.generateCorrelationId ?? (() => randomUUID());\r\n\r\n function sortMiddleware(): void {\r\n middlewares.sort((a, b) => (a.priority ?? 100) - (b.priority ?? 100));\r\n }\r\n\r\n const chain: MiddlewareChain = {\r\n use<TArgs = unknown, TResult = unknown>(middleware: Middleware<TArgs, TResult>): MiddlewareChain {\r\n // Remove existing middleware with same name\r\n const existingIndex = middlewares.findIndex((m) => m.name === middleware.name);\r\n if (existingIndex !== -1) {\r\n middlewares.splice(existingIndex, 1);\r\n }\r\n\r\n middlewares.push(middleware as Middleware);\r\n sortMiddleware();\r\n return chain;\r\n },\r\n\r\n remove(name: string): MiddlewareChain {\r\n const index = middlewares.findIndex((m) => m.name === name);\r\n if (index !== -1) {\r\n middlewares.splice(index, 1);\r\n }\r\n return chain;\r\n },\r\n\r\n async execute<TArgs, TResult>(\r\n partialCtx: Omit<MiddlewareContext<TArgs, TResult>, 'metadata' | 'skip' | 'cachedResult'>,\r\n operation: () => Promise<TResult>\r\n ): Promise<TResult> {\r\n const ctx: MiddlewareContext<TArgs, TResult> = {\r\n ...partialCtx,\r\n metadata: new Map(),\r\n skip: false,\r\n cachedResult: undefined,\r\n };\r\n\r\n // Execute before hooks\r\n for (const middleware of middlewares) {\r\n if (middleware.before) {\r\n try {\r\n await middleware.before(ctx);\r\n } catch (err) {\r\n const error = err instanceof Error ? err : new Error(String(err));\r\n logger.error(`Middleware ${middleware.name} before hook failed`, {\r\n error,\r\n operation: ctx.operation,\r\n });\r\n }\r\n }\r\n\r\n if (ctx.skip) {\r\n break;\r\n }\r\n }\r\n\r\n // Return cached result if set\r\n if (ctx.cachedResult !== undefined) {\r\n ctx.result = ctx.cachedResult;\r\n ctx.duration = Date.now() - ctx.startTime;\r\n\r\n // Still run after hooks for cached results\r\n for (const middleware of middlewares) {\r\n if (middleware.after) {\r\n try {\r\n await middleware.after(ctx);\r\n } catch (err) {\r\n const error = err instanceof Error ? err : new Error(String(err));\r\n logger.error(`Middleware ${middleware.name} after hook failed`, {\r\n error,\r\n operation: ctx.operation,\r\n });\r\n }\r\n }\r\n }\r\n\r\n return ctx.cachedResult;\r\n }\r\n\r\n // Execute the actual operation\r\n try {\r\n const result = await operation();\r\n ctx.result = result;\r\n ctx.duration = Date.now() - ctx.startTime;\r\n\r\n // Execute after hooks\r\n for (const middleware of middlewares) {\r\n if (middleware.after) {\r\n try {\r\n await middleware.after(ctx);\r\n } catch (err) {\r\n const error = err instanceof Error ? err : new Error(String(err));\r\n logger.error(`Middleware ${middleware.name} after hook failed`, {\r\n error,\r\n operation: ctx.operation,\r\n });\r\n }\r\n }\r\n }\r\n\r\n return result;\r\n } catch (err) {\r\n ctx.error = err instanceof Error ? err : new Error(String(err));\r\n ctx.duration = Date.now() - ctx.startTime;\r\n\r\n // Execute error hooks\r\n for (const middleware of middlewares) {\r\n if (middleware.onError) {\r\n try {\r\n await middleware.onError(ctx, ctx.error);\r\n } catch (hookErr) {\r\n const error = hookErr instanceof Error ? hookErr : new Error(String(hookErr));\r\n logger.error(`Middleware ${middleware.name} onError hook failed`, {\r\n error,\r\n operation: ctx.operation,\r\n });\r\n }\r\n }\r\n }\r\n\r\n throw ctx.error;\r\n }\r\n },\r\n\r\n getMiddleware(): Middleware[] {\r\n return [...middlewares];\r\n },\r\n };\r\n\r\n return chain;\r\n}\r\n\r\n/**\r\n * Create a context for middleware execution\r\n */\r\nexport function createMiddlewareContext<TArgs = unknown, TResult = unknown>(\r\n service: MiddlewareContext['service'],\r\n operation: string,\r\n args: TArgs,\r\n logger: ILogger,\r\n options: {\r\n correlationId?: string;\r\n tenantId?: string;\r\n } = {}\r\n): Omit<MiddlewareContext<TArgs, TResult>, 'metadata' | 'skip' | 'cachedResult'> {\r\n return {\r\n service,\r\n operation,\r\n args,\r\n logger,\r\n startTime: Date.now(),\r\n correlationId: options.correlationId ?? randomUUID(),\r\n tenantId: options.tenantId,\r\n };\r\n}\r\n","/**\r\n * Built-in Middleware Implementations\r\n */\r\n\r\nimport type { Middleware, MiddlewareContext } from './types';\r\nimport type { ILogger } from '../interfaces/ILogger';\r\nimport type { IMetrics } from '../interfaces/IMetrics';\r\n\r\n/**\r\n * Logging middleware - logs all operations with timing\r\n */\r\nexport function createLoggingMiddleware(logger: ILogger): Middleware {\r\n return {\r\n name: 'logging',\r\n priority: 10,\r\n\r\n before(ctx: MiddlewareContext): void {\r\n logger.debug(`Starting ${ctx.service}.${ctx.operation}`, {\r\n correlationId: ctx.correlationId,\r\n tenantId: ctx.tenantId,\r\n args: sanitizeArgs(ctx.args),\r\n });\r\n },\r\n\r\n after(ctx: MiddlewareContext): void {\r\n logger.info(`Completed ${ctx.service}.${ctx.operation}`, {\r\n correlationId: ctx.correlationId,\r\n duration: ctx.duration,\r\n success: true,\r\n });\r\n },\r\n\r\n onError(ctx: MiddlewareContext, error: Error): void {\r\n logger.error(`Failed ${ctx.service}.${ctx.operation}`, {\r\n correlationId: ctx.correlationId,\r\n duration: ctx.duration,\r\n error,\r\n });\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Metrics middleware - records timing and counters\r\n */\r\nexport function createMetricsMiddleware(metrics: IMetrics): Middleware {\r\n return {\r\n name: 'metrics',\r\n priority: 20,\r\n\r\n after(ctx: MiddlewareContext): void {\r\n metrics.timing(`platform.${ctx.service}.duration`, ctx.duration ?? 0, {\r\n operation: ctx.operation,\r\n success: 'true',\r\n });\r\n\r\n metrics.increment(`platform.${ctx.service}.requests`, 1, {\r\n operation: ctx.operation,\r\n status: 'success',\r\n });\r\n },\r\n\r\n onError(ctx: MiddlewareContext): void {\r\n metrics.timing(`platform.${ctx.service}.duration`, ctx.duration ?? 0, {\r\n operation: ctx.operation,\r\n success: 'false',\r\n });\r\n\r\n metrics.increment(`platform.${ctx.service}.requests`, 1, {\r\n operation: ctx.operation,\r\n status: 'error',\r\n });\r\n\r\n metrics.increment(`platform.${ctx.service}.errors`, 1, {\r\n operation: ctx.operation,\r\n });\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Slow query logging middleware\r\n */\r\nexport function createSlowQueryMiddleware(\r\n logger: ILogger,\r\n thresholdMs: number = 1000\r\n): Middleware {\r\n return {\r\n name: 'slow-query',\r\n priority: 15,\r\n\r\n after(ctx: MiddlewareContext): void {\r\n if (ctx.duration && ctx.duration > thresholdMs) {\r\n logger.warn(`Slow operation detected: ${ctx.service}.${ctx.operation}`, {\r\n correlationId: ctx.correlationId,\r\n duration: ctx.duration,\r\n threshold: thresholdMs,\r\n args: sanitizeArgs(ctx.args),\r\n });\r\n }\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Tenant isolation middleware - ensures tenant context is set\r\n */\r\nexport function createTenantMiddleware(\r\n options: {\r\n required?: boolean;\r\n headerName?: string;\r\n } = {}\r\n): Middleware {\r\n const { required = false } = options;\r\n\r\n return {\r\n name: 'tenant',\r\n priority: 5,\r\n\r\n before(ctx: MiddlewareContext): void {\r\n if (required && !ctx.tenantId) {\r\n throw new Error('Tenant context required but not provided');\r\n }\r\n\r\n if (ctx.tenantId) {\r\n ctx.metadata.set('tenantId', ctx.tenantId);\r\n }\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Request ID middleware - ensures correlation ID exists\r\n */\r\nexport function createRequestIdMiddleware(): Middleware {\r\n return {\r\n name: 'request-id',\r\n priority: 1,\r\n\r\n before(ctx: MiddlewareContext): void {\r\n ctx.metadata.set('correlationId', ctx.correlationId);\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Timeout middleware - enforces operation timeout\r\n */\r\nexport function createTimeoutMiddleware(timeoutMs: number): Middleware {\r\n return {\r\n name: 'timeout',\r\n priority: 2,\r\n\r\n before(ctx: MiddlewareContext): void {\r\n ctx.metadata.set('timeout', timeoutMs);\r\n ctx.metadata.set('timeoutStart', Date.now());\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Cache middleware - caches results of read operations\r\n */\r\nexport function createCacheMiddleware(\r\n cache: { get: (key: string) => Promise<unknown>; set: (key: string, value: unknown, ttl?: number) => Promise<void> },\r\n options: {\r\n ttl?: number;\r\n keyPrefix?: string;\r\n cacheableOperations?: string[];\r\n } = {}\r\n): Middleware {\r\n const {\r\n ttl = 300,\r\n keyPrefix = 'middleware:cache:',\r\n cacheableOperations = ['get', 'query', 'find', 'list'],\r\n } = options;\r\n\r\n function isCacheable(operation: string): boolean {\r\n return cacheableOperations.some((op) => operation.toLowerCase().includes(op));\r\n }\r\n\r\n function getCacheKey(ctx: MiddlewareContext): string {\r\n const argsHash = JSON.stringify(ctx.args);\r\n return `${keyPrefix}${ctx.service}:${ctx.operation}:${argsHash}`;\r\n }\r\n\r\n return {\r\n name: 'cache',\r\n priority: 50,\r\n\r\n async before(ctx: MiddlewareContext): Promise<void> {\r\n if (!isCacheable(ctx.operation)) return;\r\n\r\n const key = getCacheKey(ctx);\r\n const cached = await cache.get(key);\r\n\r\n if (cached !== null) {\r\n ctx.cachedResult = cached;\r\n ctx.metadata.set('cacheHit', true);\r\n ctx.logger.debug('Cache hit', { key, operation: ctx.operation });\r\n } else {\r\n ctx.metadata.set('cacheHit', false);\r\n }\r\n },\r\n\r\n async after(ctx: MiddlewareContext): Promise<void> {\r\n if (!isCacheable(ctx.operation)) return;\r\n if (ctx.metadata.get('cacheHit')) return;\r\n\r\n const key = getCacheKey(ctx);\r\n await cache.set(key, ctx.result, ttl);\r\n ctx.logger.debug('Cache set', { key, operation: ctx.operation, ttl });\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Rate Limiting Error\r\n */\r\nexport class RateLimitError extends Error {\r\n override readonly name = 'RateLimitError';\r\n readonly retryAfter: number;\r\n readonly limit: number;\r\n readonly remaining: number;\r\n readonly resetAt: Date;\r\n\r\n constructor(\r\n message: string,\r\n options: { retryAfter: number; limit: number; remaining: number; resetAt: Date }\r\n ) {\r\n super(message);\r\n this.retryAfter = options.retryAfter;\r\n this.limit = options.limit;\r\n this.remaining = options.remaining;\r\n this.resetAt = options.resetAt;\r\n }\r\n}\r\n\r\n/**\r\n * Rate limit info for responses\r\n */\r\nexport interface RateLimitInfo {\r\n limit: number;\r\n remaining: number;\r\n resetAt: Date;\r\n}\r\n\r\n/**\r\n * Rate limiter storage interface\r\n */\r\nexport interface RateLimiterStorage {\r\n /**\r\n * Get current count and increment\r\n * Returns: [currentCount, resetAt timestamp]\r\n */\r\n increment(key: string, windowMs: number): Promise<[number, number]>;\r\n\r\n /**\r\n * Get current state without incrementing\r\n */\r\n get(key: string): Promise<{ count: number; resetAt: number } | null>;\r\n}\r\n\r\n/**\r\n * In-memory rate limiter storage\r\n */\r\nexport class MemoryRateLimiterStorage implements RateLimiterStorage {\r\n private windows: Map<string, { count: number; resetAt: number }> = new Map();\r\n private cleanupInterval: NodeJS.Timeout | null = null;\r\n\r\n constructor(options: { cleanupIntervalMs?: number } = {}) {\r\n const cleanupIntervalMs = options.cleanupIntervalMs ?? 60000;\r\n\r\n // Periodic cleanup of expired windows\r\n this.cleanupInterval = setInterval(() => {\r\n const now = Date.now();\r\n for (const [key, window] of this.windows) {\r\n if (window.resetAt < now) {\r\n this.windows.delete(key);\r\n }\r\n }\r\n }, cleanupIntervalMs);\r\n\r\n // Prevent interval from keeping process alive\r\n if (this.cleanupInterval.unref) {\r\n this.cleanupInterval.unref();\r\n }\r\n }\r\n\r\n async increment(key: string, windowMs: number): Promise<[number, number]> {\r\n const now = Date.now();\r\n let window = this.windows.get(key);\r\n\r\n // Check if window expired\r\n if (!window || window.resetAt < now) {\r\n window = { count: 0, resetAt: now + windowMs };\r\n this.windows.set(key, window);\r\n }\r\n\r\n window.count++;\r\n return [window.count, window.resetAt];\r\n }\r\n\r\n async get(key: string): Promise<{ count: number; resetAt: number } | null> {\r\n const window = this.windows.get(key);\r\n if (!window || window.resetAt < Date.now()) {\r\n return null;\r\n }\r\n return window;\r\n }\r\n\r\n /**\r\n * Clear all windows (for testing)\r\n */\r\n clear(): void {\r\n this.windows.clear();\r\n }\r\n\r\n /**\r\n * Stop cleanup interval\r\n */\r\n stop(): void {\r\n if (this.cleanupInterval) {\r\n clearInterval(this.cleanupInterval);\r\n this.cleanupInterval = null;\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Rate limiting algorithm types\r\n */\r\nexport type RateLimitAlgorithm = 'fixed-window' | 'sliding-window' | 'token-bucket';\r\n\r\n/**\r\n * Rate limiting options\r\n */\r\nexport interface RateLimitOptions {\r\n /** Maximum requests per window */\r\n limit: number;\r\n\r\n /** Time window in milliseconds */\r\n windowMs: number;\r\n\r\n /** Storage backend (defaults to memory) */\r\n storage?: RateLimiterStorage;\r\n\r\n /** Key generator function */\r\n keyGenerator?: (ctx: MiddlewareContext) => string;\r\n\r\n /** Skip rate limiting for certain requests */\r\n skip?: (ctx: MiddlewareContext) => boolean;\r\n\r\n /** Handler for rate limit exceeded */\r\n onRateLimited?: (ctx: MiddlewareContext, info: RateLimitInfo) => void;\r\n\r\n /** Whether to throw error or just log (defaults to throw) */\r\n throwOnLimit?: boolean;\r\n\r\n /** Custom message for rate limit error */\r\n message?: string;\r\n\r\n /** Headers to set with rate limit info */\r\n setHeaders?: boolean;\r\n}\r\n\r\n/**\r\n * Rate limiting middleware\r\n * Prevents abuse by limiting request frequency\r\n */\r\nexport function createRateLimitMiddleware(options: RateLimitOptions): Middleware {\r\n const {\r\n limit,\r\n windowMs,\r\n storage = new MemoryRateLimiterStorage(),\r\n keyGenerator = defaultKeyGenerator,\r\n skip,\r\n onRateLimited,\r\n throwOnLimit = true,\r\n message = 'Too many requests, please try again later',\r\n } = options;\r\n\r\n return {\r\n name: 'rate-limit',\r\n priority: 3, // Run early, after request-id and timeout\r\n\r\n async before(ctx: MiddlewareContext): Promise<void> {\r\n // Check if we should skip\r\n if (skip?.(ctx)) {\r\n ctx.metadata.set('rateLimitSkipped', true);\r\n return;\r\n }\r\n\r\n const key = `ratelimit:${keyGenerator(ctx)}`;\r\n const [count, resetAtMs] = await storage.increment(key, windowMs);\r\n const resetAt = new Date(resetAtMs);\r\n const remaining = Math.max(0, limit - count);\r\n const retryAfter = Math.ceil((resetAtMs - Date.now()) / 1000);\r\n\r\n // Store rate limit info in metadata for headers\r\n const info: RateLimitInfo = { limit, remaining, resetAt };\r\n ctx.metadata.set('rateLimit', info);\r\n\r\n if (count > limit) {\r\n onRateLimited?.(ctx, info);\r\n\r\n ctx.logger.warn('Rate limit exceeded', {\r\n correlationId: ctx.correlationId,\r\n tenantId: ctx.tenantId,\r\n key,\r\n count,\r\n limit,\r\n resetAt,\r\n });\r\n\r\n if (throwOnLimit) {\r\n throw new RateLimitError(message, { retryAfter, limit, remaining, resetAt });\r\n }\r\n }\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Default key generator - uses tenant, service, and operation\r\n */\r\nfunction defaultKeyGenerator(ctx: MiddlewareContext): string {\r\n const parts = [ctx.service, ctx.operation];\r\n\r\n if (ctx.tenantId) {\r\n parts.unshift(ctx.tenantId);\r\n }\r\n\r\n return parts.join(':');\r\n}\r\n\r\n/**\r\n * Create an IP-based rate limiter key generator\r\n */\r\nexport function createIpKeyGenerator(\r\n getIp: (ctx: MiddlewareContext) => string | undefined\r\n): (ctx: MiddlewareContext) => string {\r\n return (ctx: MiddlewareContext) => {\r\n const ip = getIp(ctx) ?? 'unknown';\r\n return `ip:${ip}:${ctx.service}:${ctx.operation}`;\r\n };\r\n}\r\n\r\n/**\r\n * Create a user-based rate limiter key generator\r\n */\r\nexport function createUserKeyGenerator(\r\n getUserId: (ctx: MiddlewareContext) => string | undefined\r\n): (ctx: MiddlewareContext) => string {\r\n return (ctx: MiddlewareContext) => {\r\n const userId = getUserId(ctx) ?? 'anonymous';\r\n return `user:${userId}:${ctx.service}:${ctx.operation}`;\r\n };\r\n}\r\n\r\n/**\r\n * Sliding window rate limiter options\r\n */\r\nexport interface SlidingWindowRateLimitOptions extends Omit<RateLimitOptions, 'algorithm'> {\r\n /** Number of sub-windows (more = more accurate, more memory) */\r\n precision?: number;\r\n}\r\n\r\n/**\r\n * Token bucket rate limiter options\r\n */\r\nexport interface TokenBucketOptions {\r\n /** Bucket capacity (max tokens) */\r\n capacity: number;\r\n\r\n /** Token refill rate per second */\r\n refillRate: number;\r\n\r\n /** Storage backend */\r\n storage?: RateLimiterStorage;\r\n\r\n /** Key generator function */\r\n keyGenerator?: (ctx: MiddlewareContext) => string;\r\n\r\n /** Skip rate limiting for certain requests */\r\n skip?: (ctx: MiddlewareContext) => boolean;\r\n\r\n /** Whether to throw error or just log */\r\n throwOnLimit?: boolean;\r\n\r\n /** Custom message for rate limit error */\r\n message?: string;\r\n}\r\n\r\n/**\r\n * Pre-configured rate limit presets\r\n */\r\nexport const RateLimitPresets = {\r\n /** Standard API rate limit: 100 req/min */\r\n standard: { limit: 100, windowMs: 60 * 1000 },\r\n\r\n /** Strict rate limit: 10 req/min */\r\n strict: { limit: 10, windowMs: 60 * 1000 },\r\n\r\n /** Relaxed rate limit: 1000 req/min */\r\n relaxed: { limit: 1000, windowMs: 60 * 1000 },\r\n\r\n /** Burst protection: 50 req/sec */\r\n burst: { limit: 50, windowMs: 1000 },\r\n\r\n /** Auth rate limit: 5 attempts/15 min */\r\n auth: { limit: 5, windowMs: 15 * 60 * 1000 },\r\n\r\n /** Expensive operations: 10 req/hour */\r\n expensive: { limit: 10, windowMs: 60 * 60 * 1000 },\r\n} as const;\r\n\r\n/**\r\n * Sanitize args for logging (remove sensitive data)\r\n */\r\nfunction sanitizeArgs(args: unknown): unknown {\r\n if (args === null || args === undefined) return args;\r\n\r\n if (typeof args !== 'object') return args;\r\n\r\n if (Array.isArray(args)) {\r\n return args.map(sanitizeArgs);\r\n }\r\n\r\n const sanitized: Record<string, unknown> = {};\r\n const sensitiveKeys = ['password', 'token', 'secret', 'key', 'authorization', 'credential'];\r\n\r\n for (const [key, value] of Object.entries(args as Record<string, unknown>)) {\r\n if (sensitiveKeys.some((sk) => key.toLowerCase().includes(sk))) {\r\n sanitized[key] = '[REDACTED]';\r\n } else if (typeof value === 'object' && value !== null) {\r\n sanitized[key] = sanitizeArgs(value);\r\n } else {\r\n sanitized[key] = value;\r\n }\r\n }\r\n\r\n return sanitized;\r\n}\r\n","/**\r\n * Hook Registry Implementation\r\n */\r\n\r\nimport type { PlatformHooks, HookRegistry } from './types';\r\nimport type { ILogger } from '../interfaces/ILogger';\r\nimport { NoopLogger } from '../interfaces/ILogger';\r\n\r\n/**\r\n * Create a hook registry\r\n */\r\nexport function createHookRegistry(logger: ILogger = new NoopLogger()): HookRegistry {\r\n let hooks: PlatformHooks = {};\r\n\r\n const registry: HookRegistry = {\r\n register(newHooks: Partial<PlatformHooks>): void {\r\n hooks = { ...hooks, ...newHooks };\r\n logger.debug('Hooks registered', {\r\n hookNames: Object.keys(newHooks),\r\n });\r\n },\r\n\r\n clear(): void {\r\n hooks = {};\r\n logger.debug('Hooks cleared');\r\n },\r\n\r\n async execute<K extends keyof PlatformHooks>(\r\n hookName: K,\r\n ...args: Parameters<NonNullable<PlatformHooks[K]>>\r\n ): Promise<void> {\r\n const hook = hooks[hookName];\r\n\r\n if (!hook) {\r\n return;\r\n }\r\n\r\n try {\r\n // @ts-expect-error - TypeScript can't infer the correct function signature\r\n await hook(...args);\r\n } catch (err) {\r\n const error = err instanceof Error ? err : new Error(String(err));\r\n logger.error(`Hook ${String(hookName)} failed`, {\r\n error,\r\n hookName: String(hookName),\r\n });\r\n // Don't throw - hooks should not break the main flow\r\n }\r\n },\r\n\r\n getHooks(): PlatformHooks {\r\n return { ...hooks };\r\n },\r\n };\r\n\r\n return registry;\r\n}\r\n\r\n/**\r\n * Compose multiple hook registries\r\n */\r\nexport function composeHookRegistries(...registries: HookRegistry[]): HookRegistry {\r\n const logger = new NoopLogger();\r\n\r\n return {\r\n register(hooks: Partial<PlatformHooks>): void {\r\n registries.forEach((r) => r.register(hooks));\r\n },\r\n\r\n clear(): void {\r\n registries.forEach((r) => r.clear());\r\n },\r\n\r\n async execute<K extends keyof PlatformHooks>(\r\n hookName: K,\r\n ...args: Parameters<NonNullable<PlatformHooks[K]>>\r\n ): Promise<void> {\r\n for (const registry of registries) {\r\n await registry.execute(hookName, ...args);\r\n }\r\n },\r\n\r\n getHooks(): PlatformHooks {\r\n return registries.reduce((acc, r) => ({ ...acc, ...r.getHooks() }), {} as PlatformHooks);\r\n },\r\n };\r\n}\r\n","/**\r\n * Retry Pattern Implementation\r\n *\r\n * Provides configurable retry logic with exponential backoff and jitter.\r\n */\r\n\r\nimport type { ILogger } from '../interfaces/ILogger';\r\nimport { NoopLogger } from '../interfaces/ILogger';\r\n\r\n/**\r\n * Options for retry behavior\r\n */\r\nexport interface RetryOptions {\r\n /**\r\n * Maximum number of retry attempts\r\n * @default 3\r\n */\r\n maxAttempts: number;\r\n\r\n /**\r\n * Initial delay between retries in milliseconds\r\n * @default 100\r\n */\r\n baseDelay: number;\r\n\r\n /**\r\n * Maximum delay between retries in milliseconds\r\n * @default 10000\r\n */\r\n maxDelay: number;\r\n\r\n /**\r\n * Multiplier for exponential backoff\r\n * @default 2\r\n */\r\n backoffMultiplier: number;\r\n\r\n /**\r\n * Whether to add random jitter to delays\r\n * @default true\r\n */\r\n jitter: boolean;\r\n\r\n /**\r\n * Maximum jitter in milliseconds\r\n * @default 100\r\n */\r\n maxJitter: number;\r\n\r\n /**\r\n * Function to determine if error is retryable\r\n * @default All errors are retryable\r\n */\r\n retryIf?: (error: Error) => boolean;\r\n\r\n /**\r\n * Function to determine if error is non-retryable\r\n * Takes precedence over retryIf\r\n */\r\n abortIf?: (error: Error) => boolean;\r\n\r\n /**\r\n * Callback on each retry attempt\r\n */\r\n onRetry?: (error: Error, attempt: number, delay: number) => void;\r\n\r\n /**\r\n * Logger for retry operations\r\n */\r\n logger?: ILogger;\r\n}\r\n\r\n/**\r\n * Default retry options\r\n */\r\nexport const DEFAULT_RETRY_OPTIONS: RetryOptions = {\r\n maxAttempts: 3,\r\n baseDelay: 100,\r\n maxDelay: 10000,\r\n backoffMultiplier: 2,\r\n jitter: true,\r\n maxJitter: 100,\r\n};\r\n\r\n/**\r\n * Result of a retry operation\r\n */\r\nexport interface RetryResult<T> {\r\n /** Whether the operation succeeded */\r\n success: boolean;\r\n\r\n /** The result if successful */\r\n result?: T;\r\n\r\n /** The final error if all attempts failed */\r\n error?: Error;\r\n\r\n /** Number of attempts made */\r\n attempts: number;\r\n\r\n /** Total time spent in milliseconds */\r\n totalTime: number;\r\n}\r\n\r\n/**\r\n * Sleep for specified milliseconds\r\n */\r\nfunction sleep(ms: number): Promise<void> {\r\n return new Promise((resolve) => setTimeout(resolve, ms));\r\n}\r\n\r\n/**\r\n * Calculate delay for a given attempt\r\n */\r\nfunction calculateDelay(attempt: number, options: RetryOptions): number {\r\n // Exponential backoff\r\n let delay = options.baseDelay * Math.pow(options.backoffMultiplier, attempt - 1);\r\n\r\n // Cap at max delay\r\n delay = Math.min(delay, options.maxDelay);\r\n\r\n // Add jitter\r\n if (options.jitter) {\r\n const jitter = Math.random() * options.maxJitter;\r\n delay += jitter;\r\n }\r\n\r\n return Math.floor(delay);\r\n}\r\n\r\n/**\r\n * Execute a function with retry logic\r\n */\r\nexport async function withRetry<T>(\r\n fn: () => Promise<T>,\r\n options: Partial<RetryOptions> = {}\r\n): Promise<T> {\r\n const opts: RetryOptions = { ...DEFAULT_RETRY_OPTIONS, ...options };\r\n const logger = opts.logger ?? new NoopLogger();\r\n\r\n let lastError: Error | undefined;\r\n let delay = opts.baseDelay;\r\n\r\n for (let attempt = 1; attempt <= opts.maxAttempts; attempt++) {\r\n try {\r\n return await fn();\r\n } catch (error) {\r\n lastError = error instanceof Error ? error : new Error(String(error));\r\n\r\n // Check if error is non-retryable\r\n if (opts.abortIf?.(lastError)) {\r\n logger.debug('Retry aborted - non-retryable error', {\r\n attempt,\r\n error: lastError,\r\n });\r\n throw lastError;\r\n }\r\n\r\n // Check if error is retryable\r\n if (opts.retryIf && !opts.retryIf(lastError)) {\r\n logger.debug('Retry aborted - error not retryable', {\r\n attempt,\r\n error: lastError,\r\n });\r\n throw lastError;\r\n }\r\n\r\n // If this was the last attempt, throw\r\n if (attempt >= opts.maxAttempts) {\r\n logger.warn('All retry attempts exhausted', {\r\n attempts: attempt,\r\n error: lastError,\r\n });\r\n throw lastError;\r\n }\r\n\r\n // Calculate delay for next attempt\r\n delay = calculateDelay(attempt, opts);\r\n\r\n logger.debug('Retrying operation', {\r\n attempt,\r\n maxAttempts: opts.maxAttempts,\r\n delay,\r\n error: lastError,\r\n });\r\n\r\n // Call retry callback\r\n opts.onRetry?.(lastError, attempt, delay);\r\n\r\n // Wait before next attempt\r\n await sleep(delay);\r\n }\r\n }\r\n\r\n // This should never happen, but TypeScript needs it\r\n throw lastError ?? new Error('Retry failed with no error');\r\n}\r\n\r\n/**\r\n * Execute with retry and return detailed result\r\n */\r\nexport async function withRetryResult<T>(\r\n fn: () => Promise<T>,\r\n options: Partial<RetryOptions> = {}\r\n): Promise<RetryResult<T>> {\r\n const opts: RetryOptions = { ...DEFAULT_RETRY_OPTIONS, ...options };\r\n const startTime = Date.now();\r\n\r\n let attempts = 0;\r\n let lastError: Error | undefined;\r\n let delay = opts.baseDelay;\r\n\r\n for (let attempt = 1; attempt <= opts.maxAttempts; attempt++) {\r\n attempts = attempt;\r\n\r\n try {\r\n const result = await fn();\r\n return {\r\n success: true,\r\n result,\r\n attempts,\r\n totalTime: Date.now() - startTime,\r\n };\r\n } catch (error) {\r\n lastError = error instanceof Error ? error : new Error(String(error));\r\n\r\n if (opts.abortIf?.(lastError)) {\r\n break;\r\n }\r\n\r\n if (opts.retryIf && !opts.retryIf(lastError)) {\r\n break;\r\n }\r\n\r\n if (attempt >= opts.maxAttempts) {\r\n break;\r\n }\r\n\r\n delay = calculateDelay(attempt, opts);\r\n opts.onRetry?.(lastError, attempt, delay);\r\n await sleep(delay);\r\n }\r\n }\r\n\r\n return {\r\n success: false,\r\n error: lastError,\r\n attempts,\r\n totalTime: Date.now() - startTime,\r\n };\r\n}\r\n\r\n/**\r\n * Create a retryable version of a function\r\n */\r\nexport function retryable<TArgs extends unknown[], TResult>(\r\n fn: (...args: TArgs) => Promise<TResult>,\r\n options: Partial<RetryOptions> = {}\r\n): (...args: TArgs) => Promise<TResult> {\r\n return (...args: TArgs) => withRetry(() => fn(...args), options);\r\n}\r\n\r\n/**\r\n * Common retry predicates\r\n */\r\nexport const RetryPredicates = {\r\n /**\r\n * Retry on network errors\r\n */\r\n networkErrors: (error: Error): boolean => {\r\n const networkErrorCodes = [\r\n 'ECONNRESET',\r\n 'ECONNREFUSED',\r\n 'ETIMEDOUT',\r\n 'ENOTFOUND',\r\n 'EAI_AGAIN',\r\n 'EHOSTUNREACH',\r\n 'ENETUNREACH',\r\n ];\r\n\r\n const errorCode = (error as NodeJS.ErrnoException).code;\r\n if (errorCode && networkErrorCodes.includes(errorCode)) {\r\n return true;\r\n }\r\n\r\n // Check for common network error messages\r\n const message = error.message.toLowerCase();\r\n return (\r\n message.includes('network') ||\r\n message.includes('timeout') ||\r\n message.includes('connection') ||\r\n message.includes('socket')\r\n );\r\n },\r\n\r\n /**\r\n * Retry on HTTP 5xx errors\r\n */\r\n serverErrors: (error: Error): boolean => {\r\n const statusCode = (error as Error & { statusCode?: number }).statusCode;\r\n return statusCode !== undefined && statusCode >= 500 && statusCode < 600;\r\n },\r\n\r\n /**\r\n * Retry on HTTP 429 (rate limit) errors\r\n */\r\n rateLimitErrors: (error: Error): boolean => {\r\n const statusCode = (error as Error & { statusCode?: number }).statusCode;\r\n return statusCode === 429;\r\n },\r\n\r\n /**\r\n * Retry on database deadlock errors\r\n */\r\n deadlockErrors: (error: Error): boolean => {\r\n const message = error.message.toLowerCase();\r\n return message.includes('deadlock') || message.includes('lock wait timeout');\r\n },\r\n\r\n /**\r\n * Never retry on authentication errors\r\n */\r\n authenticationErrors: (error: Error): boolean => {\r\n const statusCode = (error as Error & { statusCode?: number }).statusCode;\r\n return statusCode === 401 || statusCode === 403;\r\n },\r\n\r\n /**\r\n * Never retry on validation errors\r\n */\r\n validationErrors: (error: Error): boolean => {\r\n const statusCode = (error as Error & { statusCode?: number }).statusCode;\r\n return statusCode === 400 || statusCode === 422;\r\n },\r\n};\r\n\r\n/**\r\n * Common retry configurations\r\n */\r\nexport const RetryConfigs = {\r\n /**\r\n * Fast retry for quick failures\r\n */\r\n fast: {\r\n maxAttempts: 3,\r\n baseDelay: 50,\r\n maxDelay: 500,\r\n backoffMultiplier: 2,\r\n } as Partial<RetryOptions>,\r\n\r\n /**\r\n * Standard retry configuration\r\n */\r\n standard: {\r\n maxAttempts: 3,\r\n baseDelay: 100,\r\n maxDelay: 5000,\r\n backoffMultiplier: 2,\r\n } as Partial<RetryOptions>,\r\n\r\n /**\r\n * Aggressive retry for critical operations\r\n */\r\n aggressive: {\r\n maxAttempts: 5,\r\n baseDelay: 200,\r\n maxDelay: 30000,\r\n backoffMultiplier: 2,\r\n } as Partial<RetryOptions>,\r\n\r\n /**\r\n * Conservative retry for rate-limited APIs\r\n */\r\n rateLimited: {\r\n maxAttempts: 3,\r\n baseDelay: 1000,\r\n maxDelay: 60000,\r\n backoffMultiplier: 3,\r\n jitter: true,\r\n maxJitter: 500,\r\n } as Partial<RetryOptions>,\r\n\r\n /**\r\n * Database retry configuration\r\n */\r\n database: {\r\n maxAttempts: 3,\r\n baseDelay: 100,\r\n maxDelay: 5000,\r\n backoffMultiplier: 2,\r\n retryIf: (error: Error) =>\r\n RetryPredicates.networkErrors(error) || RetryPredicates.deadlockErrors(error),\r\n abortIf: RetryPredicates.validationErrors,\r\n } as Partial<RetryOptions>,\r\n};\r\n","/**\r\n * Circuit Breaker Pattern Implementation\r\n *\r\n * Prevents cascading failures by temporarily blocking calls to a failing service.\r\n */\r\n\r\nimport type { ILogger } from '../interfaces/ILogger';\r\nimport { NoopLogger } from '../interfaces/ILogger';\r\n\r\n/**\r\n * Circuit breaker states\r\n */\r\nexport type CircuitState = 'closed' | 'open' | 'half-open';\r\n\r\n/**\r\n * Options for circuit breaker behavior\r\n */\r\nexport interface CircuitBreakerOptions {\r\n /**\r\n * Name of the circuit (for logging)\r\n */\r\n name: string;\r\n\r\n /**\r\n * Number of failures before opening the circuit\r\n * @default 5\r\n */\r\n failureThreshold: number;\r\n\r\n /**\r\n * Time in milliseconds before attempting to close the circuit\r\n * @default 30000\r\n */\r\n resetTimeout: number;\r\n\r\n /**\r\n * Number of successful requests needed in half-open state to close the circuit\r\n * @default 3\r\n */\r\n successThreshold: number;\r\n\r\n /**\r\n * Time window in milliseconds for counting failures\r\n * @default 60000\r\n */\r\n failureWindow: number;\r\n\r\n /**\r\n * Function to determine if error should trip the circuit\r\n * @default All errors trip the circuit\r\n */\r\n shouldTrip?: (error: Error) => boolean;\r\n\r\n /**\r\n * Callback when circuit state changes\r\n */\r\n onStateChange?: (from: CircuitState, to: CircuitState) => void;\r\n\r\n /**\r\n * Callback when circuit opens\r\n */\r\n onOpen?: (failures: number, lastError: Error) => void;\r\n\r\n /**\r\n * Callback when circuit closes\r\n */\r\n onClose?: () => void;\r\n\r\n /**\r\n * Callback when request is rejected due to open circuit\r\n */\r\n onReject?: (state: CircuitState) => void;\r\n\r\n /**\r\n * Logger for circuit breaker events\r\n */\r\n logger?: ILogger;\r\n}\r\n\r\n/**\r\n * Default circuit breaker options\r\n */\r\nexport const DEFAULT_CIRCUIT_BREAKER_OPTIONS: Omit<CircuitBreakerOptions, 'name'> = {\r\n failureThreshold: 5,\r\n resetTimeout: 30000,\r\n successThreshold: 3,\r\n failureWindow: 60000,\r\n};\r\n\r\n/**\r\n * Error thrown when circuit is open\r\n */\r\nexport class CircuitOpenError extends Error {\r\n override readonly name = 'CircuitOpenError';\r\n readonly circuitName: string;\r\n readonly state: CircuitState;\r\n readonly nextAttemptAt: Date;\r\n\r\n constructor(circuitName: string, state: CircuitState, resetTimeout: number) {\r\n super(`Circuit \"${circuitName}\" is ${state}. Retry after ${resetTimeout}ms.`);\r\n this.circuitName = circuitName;\r\n this.state = state;\r\n this.nextAttemptAt = new Date(Date.now() + resetTimeout);\r\n }\r\n}\r\n\r\n/**\r\n * Circuit breaker statistics\r\n */\r\nexport interface CircuitBreakerStats {\r\n state: CircuitState;\r\n failures: number;\r\n successes: number;\r\n lastFailure?: Date;\r\n lastSuccess?: Date;\r\n lastStateChange?: Date;\r\n totalRequests: number;\r\n rejectedRequests: number;\r\n}\r\n\r\n/**\r\n * Circuit breaker implementation\r\n */\r\nexport class CircuitBreaker {\r\n private state: CircuitState = 'closed';\r\n private failures: number = 0;\r\n private successes: number = 0;\r\n private failureTimestamps: number[] = [];\r\n private lastFailure?: Date;\r\n private lastSuccess?: Date;\r\n private lastStateChange?: Date;\r\n private lastOpenedAt?: Date;\r\n private totalRequests: number = 0;\r\n private rejectedRequests: number = 0;\r\n private lastError?: Error;\r\n private readonly options: CircuitBreakerOptions;\r\n private readonly logger: ILogger;\r\n\r\n constructor(options: CircuitBreakerOptions) {\r\n this.options = {\r\n ...DEFAULT_CIRCUIT_BREAKER_OPTIONS,\r\n ...options,\r\n };\r\n this.logger = options.logger ?? new NoopLogger();\r\n }\r\n\r\n /**\r\n * Execute a function with circuit breaker protection\r\n */\r\n async execute<T>(fn: () => Promise<T>): Promise<T> {\r\n this.totalRequests++;\r\n\r\n // Check if circuit allows the request\r\n if (!this.canExecute()) {\r\n this.rejectedRequests++;\r\n this.options.onReject?.(this.state);\r\n\r\n throw new CircuitOpenError(\r\n this.options.name,\r\n this.state,\r\n this.getRemainingTimeout()\r\n );\r\n }\r\n\r\n try {\r\n const result = await fn();\r\n this.onSuccess();\r\n return result;\r\n } catch (error) {\r\n this.onFailure(error instanceof Error ? error : new Error(String(error)));\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Check if circuit allows execution\r\n */\r\n canExecute(): boolean {\r\n switch (this.state) {\r\n case 'closed':\r\n return true;\r\n\r\n case 'open':\r\n // Check if reset timeout has passed\r\n if (this.shouldAttemptReset()) {\r\n this.transitionTo('half-open');\r\n return true;\r\n }\r\n return false;\r\n\r\n case 'half-open':\r\n // Allow limited requests in half-open state\r\n return true;\r\n\r\n default:\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Record a successful execution\r\n */\r\n private onSuccess(): void {\r\n this.lastSuccess = new Date();\r\n this.successes++;\r\n\r\n switch (this.state) {\r\n case 'half-open':\r\n // Check if we've had enough successes to close\r\n if (this.successes >= this.options.successThreshold) {\r\n this.transitionTo('closed');\r\n }\r\n break;\r\n\r\n case 'closed':\r\n // Reset failure count on success\r\n this.failures = 0;\r\n this.failureTimestamps = [];\r\n break;\r\n }\r\n }\r\n\r\n /**\r\n * Record a failed execution\r\n */\r\n private onFailure(error: Error): void {\r\n // Check if this error should trip the circuit\r\n if (this.options.shouldTrip && !this.options.shouldTrip(error)) {\r\n return;\r\n }\r\n\r\n this.lastError = error;\r\n this.lastFailure = new Date();\r\n this.failures++;\r\n\r\n const now = Date.now();\r\n this.failureTimestamps.push(now);\r\n\r\n // Remove old failures outside the window\r\n const windowStart = now - this.options.failureWindow;\r\n this.failureTimestamps = this.failureTimestamps.filter((ts) => ts > windowStart);\r\n\r\n switch (this.state) {\r\n case 'closed':\r\n // Check if we've hit the failure threshold\r\n if (this.failureTimestamps.length >= this.options.failureThreshold) {\r\n this.transitionTo('open');\r\n this.options.onOpen?.(this.failures, error);\r\n }\r\n break;\r\n\r\n case 'half-open':\r\n // Any failure in half-open state reopens the circuit\r\n this.transitionTo('open');\r\n this.options.onOpen?.(this.failures, error);\r\n break;\r\n }\r\n }\r\n\r\n /**\r\n * Transition to a new state\r\n */\r\n private transitionTo(newState: CircuitState): void {\r\n const oldState = this.state;\r\n\r\n if (oldState === newState) return;\r\n\r\n this.state = newState;\r\n this.lastStateChange = new Date();\r\n\r\n this.logger.info(`Circuit \"${this.options.name}\" state change`, {\r\n from: oldState,\r\n to: newState,\r\n failures: this.failures,\r\n successes: this.successes,\r\n });\r\n\r\n this.options.onStateChange?.(oldState, newState);\r\n\r\n switch (newState) {\r\n case 'open':\r\n this.lastOpenedAt = new Date();\r\n this.successes = 0;\r\n break;\r\n\r\n case 'half-open':\r\n this.successes = 0;\r\n break;\r\n\r\n case 'closed':\r\n this.failures = 0;\r\n this.failureTimestamps = [];\r\n this.successes = 0;\r\n this.options.onClose?.();\r\n break;\r\n }\r\n }\r\n\r\n /**\r\n * Check if reset timeout has passed\r\n */\r\n private shouldAttemptReset(): boolean {\r\n if (!this.lastOpenedAt) return true;\r\n\r\n const elapsed = Date.now() - this.lastOpenedAt.getTime();\r\n return elapsed >= this.options.resetTimeout;\r\n }\r\n\r\n /**\r\n * Get remaining time until reset attempt\r\n */\r\n private getRemainingTimeout(): number {\r\n if (!this.lastOpenedAt) return 0;\r\n\r\n const elapsed = Date.now() - this.lastOpenedAt.getTime();\r\n return Math.max(0, this.options.resetTimeout - elapsed);\r\n }\r\n\r\n /**\r\n * Get current circuit state\r\n */\r\n getState(): CircuitState {\r\n return this.state;\r\n }\r\n\r\n /**\r\n * Get circuit breaker statistics\r\n */\r\n getStats(): CircuitBreakerStats {\r\n return {\r\n state: this.state,\r\n failures: this.failures,\r\n successes: this.successes,\r\n lastFailure: this.lastFailure,\r\n lastSuccess: this.lastSuccess,\r\n lastStateChange: this.lastStateChange,\r\n totalRequests: this.totalRequests,\r\n rejectedRequests: this.rejectedRequests,\r\n };\r\n }\r\n\r\n /**\r\n * Manually reset the circuit to closed state\r\n */\r\n reset(): void {\r\n this.transitionTo('closed');\r\n }\r\n\r\n /**\r\n * Manually trip the circuit to open state\r\n */\r\n trip(): void {\r\n this.transitionTo('open');\r\n }\r\n\r\n /**\r\n * Check if circuit is open\r\n */\r\n isOpen(): boolean {\r\n return this.state === 'open';\r\n }\r\n\r\n /**\r\n * Check if circuit is closed\r\n */\r\n isClosed(): boolean {\r\n return this.state === 'closed';\r\n }\r\n\r\n /**\r\n * Check if circuit is half-open\r\n */\r\n isHalfOpen(): boolean {\r\n return this.state === 'half-open';\r\n }\r\n}\r\n\r\n/**\r\n * Create a circuit breaker\r\n */\r\nexport function createCircuitBreaker(options: CircuitBreakerOptions): CircuitBreaker {\r\n return new CircuitBreaker(options);\r\n}\r\n\r\n/**\r\n * Circuit breaker registry for managing multiple circuits\r\n */\r\nexport class CircuitBreakerRegistry {\r\n private circuits: Map<string, CircuitBreaker> = new Map();\r\n private readonly logger: ILogger;\r\n private readonly defaultOptions: Partial<CircuitBreakerOptions>;\r\n\r\n constructor(\r\n options: {\r\n logger?: ILogger;\r\n defaults?: Partial<CircuitBreakerOptions>;\r\n } = {}\r\n ) {\r\n this.logger = options.logger ?? new NoopLogger();\r\n this.defaultOptions = options.defaults ?? {};\r\n }\r\n\r\n /**\r\n * Get or create a circuit breaker\r\n */\r\n get(name: string, options?: Partial<CircuitBreakerOptions>): CircuitBreaker {\r\n let circuit = this.circuits.get(name);\r\n\r\n if (!circuit) {\r\n circuit = new CircuitBreaker({\r\n ...DEFAULT_CIRCUIT_BREAKER_OPTIONS,\r\n ...this.defaultOptions,\r\n ...options,\r\n name,\r\n logger: options?.logger ?? this.logger,\r\n });\r\n this.circuits.set(name, circuit);\r\n }\r\n\r\n return circuit;\r\n }\r\n\r\n /**\r\n * Execute with a named circuit breaker\r\n */\r\n async execute<T>(\r\n name: string,\r\n fn: () => Promise<T>,\r\n options?: Partial<CircuitBreakerOptions>\r\n ): Promise<T> {\r\n const circuit = this.get(name, options);\r\n return circuit.execute(fn);\r\n }\r\n\r\n /**\r\n * Get all circuit statistics\r\n */\r\n getAllStats(): Record<string, CircuitBreakerStats> {\r\n const stats: Record<string, CircuitBreakerStats> = {};\r\n\r\n for (const [name, circuit] of this.circuits) {\r\n stats[name] = circuit.getStats();\r\n }\r\n\r\n return stats;\r\n }\r\n\r\n /**\r\n * Reset all circuits\r\n */\r\n resetAll(): void {\r\n for (const circuit of this.circuits.values()) {\r\n circuit.reset();\r\n }\r\n }\r\n\r\n /**\r\n * Clear all circuits\r\n */\r\n clear(): void {\r\n this.circuits.clear();\r\n }\r\n}\r\n","/**\r\n * Timeout Pattern Implementation\r\n *\r\n * Enforces time limits on operations to prevent hanging.\r\n */\r\n\r\n/**\r\n * Error thrown when operation times out\r\n */\r\nexport class TimeoutError extends Error {\r\n override readonly name = 'TimeoutError';\r\n readonly operation: string;\r\n readonly timeout: number;\r\n\r\n constructor(operation: string, timeout: number) {\r\n super(`Operation \"${operation}\" timed out after ${timeout}ms`);\r\n this.operation = operation;\r\n this.timeout = timeout;\r\n }\r\n}\r\n\r\n/**\r\n * Options for timeout behavior\r\n */\r\nexport interface TimeoutOptions {\r\n /**\r\n * Timeout in milliseconds\r\n */\r\n timeout: number;\r\n\r\n /**\r\n * Operation name (for error messages)\r\n */\r\n operation?: string;\r\n\r\n /**\r\n * Whether to abort the operation on timeout (if supported)\r\n */\r\n abortOnTimeout?: boolean;\r\n}\r\n\r\n/**\r\n * Execute a function with a timeout\r\n */\r\nexport async function withTimeout<T>(\r\n fn: () => Promise<T>,\r\n options: TimeoutOptions | number\r\n): Promise<T> {\r\n const opts: TimeoutOptions =\r\n typeof options === 'number' ? { timeout: options } : options;\r\n\r\n const { timeout, operation = 'unknown', abortOnTimeout = false } = opts;\r\n\r\n return new Promise<T>((resolve, reject) => {\r\n let timeoutId: NodeJS.Timeout | undefined;\r\n let settled = false;\r\n\r\n // Create abort controller if needed\r\n const abortController = abortOnTimeout ? new AbortController() : undefined;\r\n\r\n // Set up timeout\r\n timeoutId = setTimeout(() => {\r\n if (!settled) {\r\n settled = true;\r\n abortController?.abort();\r\n reject(new TimeoutError(operation, timeout));\r\n }\r\n }, timeout);\r\n\r\n // Execute the function\r\n fn()\r\n .then((result) => {\r\n if (!settled) {\r\n settled = true;\r\n clearTimeout(timeoutId);\r\n resolve(result);\r\n }\r\n })\r\n .catch((error) => {\r\n if (!settled) {\r\n settled = true;\r\n clearTimeout(timeoutId);\r\n reject(error);\r\n }\r\n });\r\n });\r\n}\r\n\r\n/**\r\n * Create a timeout-wrapped version of a function\r\n */\r\nexport function withTimeoutWrapper<TArgs extends unknown[], TResult>(\r\n fn: (...args: TArgs) => Promise<TResult>,\r\n options: TimeoutOptions | number\r\n): (...args: TArgs) => Promise<TResult> {\r\n return (...args: TArgs) =>\r\n withTimeout(() => fn(...args), options);\r\n}\r\n\r\n/**\r\n * Race a promise against a timeout\r\n */\r\nexport async function raceTimeout<T>(\r\n promise: Promise<T>,\r\n timeout: number,\r\n operation?: string\r\n): Promise<T> {\r\n const timeoutPromise = new Promise<never>((_, reject) => {\r\n setTimeout(() => {\r\n reject(new TimeoutError(operation ?? 'promise', timeout));\r\n }, timeout);\r\n });\r\n\r\n return Promise.race([promise, timeoutPromise]);\r\n}\r\n\r\n/**\r\n * Default timeouts for different operations\r\n */\r\nexport const DefaultTimeouts = {\r\n /** Quick operations like cache lookups */\r\n fast: 1000,\r\n\r\n /** Standard database queries */\r\n database: 5000,\r\n\r\n /** API calls to external services */\r\n api: 10000,\r\n\r\n /** File uploads/downloads */\r\n storage: 30000,\r\n\r\n /** Email sending */\r\n email: 15000,\r\n\r\n /** Long-running background jobs */\r\n job: 300000,\r\n};\r\n","/**\r\n * Bulkhead Pattern Implementation\r\n *\r\n * Isolates failures by limiting concurrent operations.\r\n */\r\n\r\nimport type { ILogger } from '../interfaces/ILogger';\r\nimport { NoopLogger } from '../interfaces/ILogger';\r\n\r\n/**\r\n * Options for bulkhead behavior\r\n */\r\nexport interface BulkheadOptions {\r\n /**\r\n * Name of the bulkhead (for logging)\r\n */\r\n name: string;\r\n\r\n /**\r\n * Maximum concurrent executions allowed\r\n * @default 10\r\n */\r\n maxConcurrent: number;\r\n\r\n /**\r\n * Maximum queue size for waiting requests\r\n * @default 100\r\n */\r\n maxQueue: number;\r\n\r\n /**\r\n * Timeout for queued requests in milliseconds\r\n * @default 30000\r\n */\r\n queueTimeout: number;\r\n\r\n /**\r\n * Callback when execution is rejected\r\n */\r\n onReject?: (reason: 'concurrent' | 'queue' | 'timeout') => void;\r\n\r\n /**\r\n * Logger for bulkhead events\r\n */\r\n logger?: ILogger;\r\n}\r\n\r\n/**\r\n * Default bulkhead options\r\n */\r\nexport const DEFAULT_BULKHEAD_OPTIONS: Omit<BulkheadOptions, 'name'> = {\r\n maxConcurrent: 10,\r\n maxQueue: 100,\r\n queueTimeout: 30000,\r\n};\r\n\r\n/**\r\n * Error thrown when bulkhead rejects a request\r\n */\r\nexport class BulkheadRejectedError extends Error {\r\n override readonly name = 'BulkheadRejectedError';\r\n readonly bulkheadName: string;\r\n readonly reason: 'concurrent' | 'queue' | 'timeout';\r\n\r\n constructor(bulkheadName: string, reason: 'concurrent' | 'queue' | 'timeout') {\r\n const messages = {\r\n concurrent: `Bulkhead \"${bulkheadName}\" rejected: max concurrent limit reached`,\r\n queue: `Bulkhead \"${bulkheadName}\" rejected: queue is full`,\r\n timeout: `Bulkhead \"${bulkheadName}\" rejected: queue timeout exceeded`,\r\n };\r\n super(messages[reason]);\r\n this.bulkheadName = bulkheadName;\r\n this.reason = reason;\r\n }\r\n}\r\n\r\n/**\r\n * Bulkhead statistics\r\n */\r\nexport interface BulkheadStats {\r\n activeCalls: number;\r\n queuedCalls: number;\r\n maxConcurrent: number;\r\n maxQueue: number;\r\n totalExecutions: number;\r\n rejectedCalls: number;\r\n availableSlots: number;\r\n availableQueueSlots: number;\r\n}\r\n\r\n/**\r\n * Queued request\r\n */\r\ninterface QueuedRequest<T> {\r\n fn: () => Promise<T>;\r\n resolve: (value: T) => void;\r\n reject: (error: Error) => void;\r\n enqueuedAt: number;\r\n timeoutId?: NodeJS.Timeout;\r\n}\r\n\r\n/**\r\n * Bulkhead implementation\r\n */\r\nexport class Bulkhead {\r\n private activeCalls = 0;\r\n private queue: QueuedRequest<unknown>[] = [];\r\n private totalExecutions = 0;\r\n private rejectedCalls = 0;\r\n private readonly options: Required<Omit<BulkheadOptions, 'onReject' | 'logger'>> &\r\n Pick<BulkheadOptions, 'onReject'>;\r\n private readonly logger: ILogger;\r\n\r\n constructor(options: BulkheadOptions) {\r\n this.options = {\r\n ...DEFAULT_BULKHEAD_OPTIONS,\r\n ...options,\r\n };\r\n this.logger = options.logger ?? new NoopLogger();\r\n }\r\n\r\n /**\r\n * Execute a function with bulkhead protection\r\n */\r\n async execute<T>(fn: () => Promise<T>): Promise<T> {\r\n this.totalExecutions++;\r\n\r\n // Check if we can execute immediately\r\n if (this.activeCalls < this.options.maxConcurrent) {\r\n return this.runExecution(fn);\r\n }\r\n\r\n // Check if queue is full\r\n if (this.queue.length >= this.options.maxQueue) {\r\n this.rejectedCalls++;\r\n this.options.onReject?.('queue');\r\n throw new BulkheadRejectedError(this.options.name, 'queue');\r\n }\r\n\r\n // Queue the request\r\n return this.queueExecution(fn);\r\n }\r\n\r\n /**\r\n * Run an execution immediately\r\n */\r\n private async runExecution<T>(fn: () => Promise<T>): Promise<T> {\r\n this.activeCalls++;\r\n\r\n try {\r\n const result = await fn();\r\n return result;\r\n } finally {\r\n this.activeCalls--;\r\n this.processQueue();\r\n }\r\n }\r\n\r\n /**\r\n * Queue a request for later execution\r\n */\r\n private queueExecution<T>(fn: () => Promise<T>): Promise<T> {\r\n return new Promise<T>((resolve, reject) => {\r\n const request: QueuedRequest<T> = {\r\n fn,\r\n resolve,\r\n reject,\r\n enqueuedAt: Date.now(),\r\n };\r\n\r\n // Set up timeout\r\n request.timeoutId = setTimeout(() => {\r\n const index = this.queue.indexOf(request as QueuedRequest<unknown>);\r\n if (index !== -1) {\r\n this.queue.splice(index, 1);\r\n this.rejectedCalls++;\r\n this.options.onReject?.('timeout');\r\n reject(new BulkheadRejectedError(this.options.name, 'timeout'));\r\n }\r\n }, this.options.queueTimeout);\r\n\r\n this.queue.push(request as QueuedRequest<unknown>);\r\n\r\n this.logger.debug(`Request queued in bulkhead \"${this.options.name}\"`, {\r\n queueSize: this.queue.length,\r\n activeCalls: this.activeCalls,\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Process queued requests\r\n */\r\n private processQueue(): void {\r\n while (this.activeCalls < this.options.maxConcurrent && this.queue.length > 0) {\r\n const request = this.queue.shift();\r\n if (!request) break;\r\n\r\n // Clear timeout\r\n if (request.timeoutId) {\r\n clearTimeout(request.timeoutId);\r\n }\r\n\r\n // Run the execution\r\n this.activeCalls++;\r\n\r\n request\r\n .fn()\r\n .then((result) => {\r\n request.resolve(result);\r\n })\r\n .catch((error) => {\r\n request.reject(error);\r\n })\r\n .finally(() => {\r\n this.activeCalls--;\r\n this.processQueue();\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Get bulkhead statistics\r\n */\r\n getStats(): BulkheadStats {\r\n return {\r\n activeCalls: this.activeCalls,\r\n queuedCalls: this.queue.length,\r\n maxConcurrent: this.options.maxConcurrent,\r\n maxQueue: this.options.maxQueue,\r\n totalExecutions: this.totalExecutions,\r\n rejectedCalls: this.rejectedCalls,\r\n availableSlots: Math.max(0, this.options.maxConcurrent - this.activeCalls),\r\n availableQueueSlots: Math.max(0, this.options.maxQueue - this.queue.length),\r\n };\r\n }\r\n\r\n /**\r\n * Check if bulkhead is at capacity\r\n */\r\n isAtCapacity(): boolean {\r\n return this.activeCalls >= this.options.maxConcurrent;\r\n }\r\n\r\n /**\r\n * Check if queue is full\r\n */\r\n isQueueFull(): boolean {\r\n return this.queue.length >= this.options.maxQueue;\r\n }\r\n\r\n /**\r\n * Drain the queue (reject all pending)\r\n */\r\n drain(): void {\r\n for (const request of this.queue) {\r\n if (request.timeoutId) {\r\n clearTimeout(request.timeoutId);\r\n }\r\n request.reject(new BulkheadRejectedError(this.options.name, 'queue'));\r\n }\r\n this.queue = [];\r\n }\r\n}\r\n\r\n/**\r\n * Create a bulkhead\r\n */\r\nexport function createBulkhead(options: BulkheadOptions): Bulkhead {\r\n return new Bulkhead(options);\r\n}\r\n\r\n/**\r\n * Bulkhead registry for managing multiple bulkheads\r\n */\r\nexport class BulkheadRegistry {\r\n private bulkheads: Map<string, Bulkhead> = new Map();\r\n private readonly logger: ILogger;\r\n private readonly defaultOptions: Partial<BulkheadOptions>;\r\n\r\n constructor(\r\n options: {\r\n logger?: ILogger;\r\n defaults?: Partial<BulkheadOptions>;\r\n } = {}\r\n ) {\r\n this.logger = options.logger ?? new NoopLogger();\r\n this.defaultOptions = options.defaults ?? {};\r\n }\r\n\r\n /**\r\n * Get or create a bulkhead\r\n */\r\n get(name: string, options?: Partial<BulkheadOptions>): Bulkhead {\r\n let bulkhead = this.bulkheads.get(name);\r\n\r\n if (!bulkhead) {\r\n bulkhead = new Bulkhead({\r\n ...DEFAULT_BULKHEAD_OPTIONS,\r\n ...this.defaultOptions,\r\n ...options,\r\n name,\r\n logger: options?.logger ?? this.logger,\r\n });\r\n this.bulkheads.set(name, bulkhead);\r\n }\r\n\r\n return bulkhead;\r\n }\r\n\r\n /**\r\n * Execute with a named bulkhead\r\n */\r\n async execute<T>(\r\n name: string,\r\n fn: () => Promise<T>,\r\n options?: Partial<BulkheadOptions>\r\n ): Promise<T> {\r\n const bulkhead = this.get(name, options);\r\n return bulkhead.execute(fn);\r\n }\r\n\r\n /**\r\n * Get all bulkhead statistics\r\n */\r\n getAllStats(): Record<string, BulkheadStats> {\r\n const stats: Record<string, BulkheadStats> = {};\r\n\r\n for (const [name, bulkhead] of this.bulkheads) {\r\n stats[name] = bulkhead.getStats();\r\n }\r\n\r\n return stats;\r\n }\r\n\r\n /**\r\n * Drain all bulkheads\r\n */\r\n drainAll(): void {\r\n for (const bulkhead of this.bulkheads.values()) {\r\n bulkhead.drain();\r\n }\r\n }\r\n\r\n /**\r\n * Clear all bulkheads\r\n */\r\n clear(): void {\r\n this.drainAll();\r\n this.bulkheads.clear();\r\n }\r\n}\r\n","/**\r\n * Fallback Pattern Implementation\r\n *\r\n * Provides fallback strategies when primary operations fail.\r\n */\r\n\r\nimport type { ILogger } from '../interfaces/ILogger';\r\nimport { NoopLogger } from '../interfaces/ILogger';\r\n\r\n/**\r\n * Fallback options\r\n */\r\nexport interface FallbackOptions<T> {\r\n /**\r\n * Static fallback value\r\n */\r\n value?: T;\r\n\r\n /**\r\n * Fallback function (called with the error)\r\n */\r\n fallbackFn?: (error: Error) => T | Promise<T>;\r\n\r\n /**\r\n * Cache the fallback result\r\n */\r\n cache?: boolean;\r\n\r\n /**\r\n * Cache TTL in milliseconds\r\n */\r\n cacheTTL?: number;\r\n\r\n /**\r\n * Callback when fallback is used\r\n */\r\n onFallback?: (error: Error, fallbackValue: T) => void;\r\n\r\n /**\r\n * Errors to ignore (not trigger fallback)\r\n */\r\n ignoreErrors?: (error: Error) => boolean;\r\n\r\n /**\r\n * Logger for fallback events\r\n */\r\n logger?: ILogger;\r\n}\r\n\r\n/**\r\n * Result of a fallback operation\r\n */\r\nexport interface FallbackResult<T> {\r\n /** The result value */\r\n value: T;\r\n\r\n /** Whether fallback was used */\r\n usedFallback: boolean;\r\n\r\n /** The original error (if fallback was used) */\r\n error?: Error;\r\n\r\n /** Whether the value came from cache */\r\n cached?: boolean;\r\n}\r\n\r\n/**\r\n * Execute with fallback\r\n */\r\nexport async function withFallback<T>(\r\n fn: () => Promise<T>,\r\n options: FallbackOptions<T>\r\n): Promise<T> {\r\n const logger = options.logger ?? new NoopLogger();\r\n\r\n try {\r\n return await fn();\r\n } catch (error) {\r\n const err = error instanceof Error ? error : new Error(String(error));\r\n\r\n // Check if we should ignore this error\r\n if (options.ignoreErrors?.(err)) {\r\n throw err;\r\n }\r\n\r\n logger.warn('Operation failed, using fallback', {\r\n error: err,\r\n });\r\n\r\n // Get fallback value\r\n let fallbackValue: T;\r\n\r\n if (options.fallbackFn) {\r\n fallbackValue = await options.fallbackFn(err);\r\n } else if (options.value !== undefined) {\r\n fallbackValue = options.value;\r\n } else {\r\n // No fallback defined, rethrow\r\n throw err;\r\n }\r\n\r\n options.onFallback?.(err, fallbackValue);\r\n\r\n return fallbackValue;\r\n }\r\n}\r\n\r\n/**\r\n * Execute with fallback and return detailed result\r\n */\r\nexport async function withFallbackResult<T>(\r\n fn: () => Promise<T>,\r\n options: FallbackOptions<T>\r\n): Promise<FallbackResult<T>> {\r\n const logger = options.logger ?? new NoopLogger();\r\n\r\n try {\r\n const value = await fn();\r\n return {\r\n value,\r\n usedFallback: false,\r\n };\r\n } catch (error) {\r\n const err = error instanceof Error ? error : new Error(String(error));\r\n\r\n if (options.ignoreErrors?.(err)) {\r\n throw err;\r\n }\r\n\r\n logger.warn('Operation failed, using fallback', {\r\n error: err,\r\n });\r\n\r\n let fallbackValue: T;\r\n\r\n if (options.fallbackFn) {\r\n fallbackValue = await options.fallbackFn(err);\r\n } else if (options.value !== undefined) {\r\n fallbackValue = options.value;\r\n } else {\r\n throw err;\r\n }\r\n\r\n options.onFallback?.(err, fallbackValue);\r\n\r\n return {\r\n value: fallbackValue,\r\n usedFallback: true,\r\n error: err,\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Create a cached fallback\r\n */\r\nexport function createCachedFallback<T>(\r\n options: {\r\n getValue: () => Promise<T>;\r\n cacheTTL?: number;\r\n logger?: ILogger;\r\n }\r\n): () => Promise<T> {\r\n const { getValue, cacheTTL = 60000 } = options;\r\n const logger = options.logger ?? new NoopLogger();\r\n\r\n let cachedValue: T | undefined;\r\n let cachedAt: number | undefined;\r\n let refreshing = false;\r\n\r\n return async (): Promise<T> => {\r\n // Return cached value if valid\r\n if (cachedValue !== undefined && cachedAt !== undefined) {\r\n const age = Date.now() - cachedAt;\r\n if (age < cacheTTL) {\r\n return cachedValue;\r\n }\r\n\r\n // Cache expired, try to refresh in background\r\n if (!refreshing) {\r\n refreshing = true;\r\n getValue()\r\n .then((value) => {\r\n cachedValue = value;\r\n cachedAt = Date.now();\r\n })\r\n .catch((err) => {\r\n const error = err instanceof Error ? err : new Error(String(err));\r\n logger.warn('Failed to refresh cached fallback', {\r\n error,\r\n });\r\n })\r\n .finally(() => {\r\n refreshing = false;\r\n });\r\n }\r\n\r\n // Return stale cache while refreshing\r\n return cachedValue;\r\n }\r\n\r\n // No cache, get fresh value\r\n const value = await getValue();\r\n cachedValue = value;\r\n cachedAt = Date.now();\r\n return value;\r\n };\r\n}\r\n\r\n/**\r\n * Fallback chain - try multiple fallbacks in order\r\n */\r\nexport async function withFallbackChain<T>(\r\n primary: () => Promise<T>,\r\n fallbacks: Array<() => Promise<T>>,\r\n options: {\r\n logger?: ILogger;\r\n onFallback?: (index: number, error: Error) => void;\r\n } = {}\r\n): Promise<T> {\r\n const logger = options.logger ?? new NoopLogger();\r\n const allFns = [primary, ...fallbacks];\r\n\r\n for (let i = 0; i < allFns.length; i++) {\r\n try {\r\n const fn = allFns[i];\r\n if (!fn) continue;\r\n return await fn();\r\n } catch (error) {\r\n const err = error instanceof Error ? error : new Error(String(error));\r\n\r\n if (i < allFns.length - 1) {\r\n logger.warn(`Fallback ${i} failed, trying next`, {\r\n index: i,\r\n error: err,\r\n });\r\n options.onFallback?.(i, err);\r\n } else {\r\n // Last fallback failed\r\n throw err;\r\n }\r\n }\r\n }\r\n\r\n // This should never happen\r\n throw new Error('All fallbacks exhausted');\r\n}\r\n\r\n/**\r\n * Common fallback strategies\r\n */\r\nexport const FallbackStrategies = {\r\n /**\r\n * Return empty array\r\n */\r\n emptyArray: <T>(): FallbackOptions<T[]> => ({\r\n value: [],\r\n }),\r\n\r\n /**\r\n * Return null\r\n */\r\n nullable: <T>(): FallbackOptions<T | null> => ({\r\n value: null,\r\n }),\r\n\r\n /**\r\n * Return default value\r\n */\r\n defaultValue: <T>(value: T): FallbackOptions<T> => ({\r\n value,\r\n }),\r\n\r\n /**\r\n * Return cached value from a cache function\r\n */\r\n fromCache: <T>(\r\n getCached: () => Promise<T | null>,\r\n defaultValue: T\r\n ): FallbackOptions<T> => ({\r\n fallbackFn: async () => {\r\n const cached = await getCached();\r\n return cached ?? defaultValue;\r\n },\r\n }),\r\n\r\n /**\r\n * Degrade gracefully with partial data\r\n */\r\n degrade: <T>(\r\n getDegraded: (error: Error) => T\r\n ): FallbackOptions<T> => ({\r\n fallbackFn: getDegraded,\r\n }),\r\n};\r\n","/**\r\n * Health Check HTTP Endpoints\r\n *\r\n * Provides standardized health check endpoints for Kubernetes probes\r\n * and monitoring systems.\r\n *\r\n * Endpoints:\r\n * - /health/live - Liveness probe (is the process alive?)\r\n * - /health/ready - Readiness probe (can it serve traffic?)\r\n * - /health/startup - Startup probe (has it finished initializing?)\r\n * - /health - Detailed health status for dashboards\r\n */\r\n\r\nimport { IPlatform, PlatformHealthStatus } from '../interfaces';\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// TYPES\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\nexport type HealthStatus = 'healthy' | 'degraded' | 'unhealthy';\r\n\r\nexport interface LivenessResponse {\r\n status: 'ok' | 'error';\r\n}\r\n\r\nexport interface ReadinessResponse {\r\n status: 'ok' | 'error';\r\n checks: {\r\n database: boolean;\r\n cache: boolean;\r\n storage: boolean;\r\n email: boolean;\r\n queue: boolean;\r\n };\r\n}\r\n\r\nexport interface StartupResponse {\r\n status: 'ok' | 'error';\r\n ready: boolean;\r\n}\r\n\r\nexport interface ServiceHealth {\r\n status: HealthStatus;\r\n latencyMs?: number;\r\n message?: string;\r\n lastChecked?: string;\r\n}\r\n\r\nexport interface DetailedHealthResponse {\r\n status: HealthStatus;\r\n version: string;\r\n environment: string;\r\n uptime: number;\r\n uptimeFormatted: string;\r\n timestamp: string;\r\n services: {\r\n database: ServiceHealth;\r\n cache: ServiceHealth;\r\n storage: ServiceHealth;\r\n email: ServiceHealth;\r\n queue: ServiceHealth;\r\n };\r\n system?: {\r\n memoryUsage: {\r\n heapUsed: number;\r\n heapTotal: number;\r\n external: number;\r\n rss: number;\r\n };\r\n cpuUsage?: {\r\n user: number;\r\n system: number;\r\n };\r\n };\r\n}\r\n\r\nexport interface HealthEndpoints {\r\n /**\r\n * Liveness probe - is the process alive?\r\n * Returns 200 if alive, 503 if dead.\r\n * K8s will restart the pod if this fails.\r\n */\r\n live(): Promise<LivenessResponse>;\r\n\r\n /**\r\n * Readiness probe - can it serve traffic?\r\n * Returns 200 if ready, 503 if not ready.\r\n * K8s will remove from load balancer if this fails.\r\n */\r\n ready(): Promise<ReadinessResponse>;\r\n\r\n /**\r\n * Startup probe - has it finished initializing?\r\n * Returns 200 when startup is complete.\r\n * K8s waits for this before starting liveness/readiness probes.\r\n */\r\n startup(): Promise<StartupResponse>;\r\n\r\n /**\r\n * Detailed health status for monitoring dashboards.\r\n * Includes service-level health, latencies, and system metrics.\r\n */\r\n detailed(): Promise<DetailedHealthResponse>;\r\n\r\n /**\r\n * Mark startup as complete (call after initialization)\r\n */\r\n markStartupComplete(): void;\r\n\r\n /**\r\n * Get raw health status for custom integrations\r\n */\r\n getRawStatus(): Promise<PlatformHealthStatus>;\r\n}\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// IMPLEMENTATION\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\nexport interface HealthEndpointsOptions {\r\n /** Application version */\r\n version?: string;\r\n\r\n /** Environment name */\r\n environment?: string;\r\n\r\n /** Include system metrics in detailed response */\r\n includeSystemMetrics?: boolean;\r\n\r\n /** Custom health checks to include */\r\n customChecks?: Record<string, () => Promise<boolean>>;\r\n\r\n /** Timeout for individual health checks (ms) */\r\n checkTimeout?: number;\r\n}\r\n\r\nexport function createHealthEndpoints(\r\n platform: IPlatform,\r\n options: HealthEndpointsOptions = {}\r\n): HealthEndpoints {\r\n const {\r\n version = process.env.npm_package_version || process.env.APP_VERSION || 'unknown',\r\n environment = process.env.NODE_ENV || 'development',\r\n includeSystemMetrics = true,\r\n customChecks = {},\r\n checkTimeout = 5000,\r\n } = options;\r\n\r\n const startTime = Date.now();\r\n let startupComplete = false;\r\n let lastHealthCheck: PlatformHealthStatus | null = null;\r\n let lastCheckTime = 0;\r\n\r\n // Cache health check results for 1 second to avoid hammering services\r\n const CACHE_TTL = 1000;\r\n\r\n async function getCachedHealth(): Promise<PlatformHealthStatus> {\r\n const now = Date.now();\r\n if (lastHealthCheck && now - lastCheckTime < CACHE_TTL) {\r\n return lastHealthCheck;\r\n }\r\n\r\n lastHealthCheck = await withTimeout(platform.healthCheck(), checkTimeout);\r\n lastCheckTime = now;\r\n return lastHealthCheck;\r\n }\r\n\r\n async function checkServiceWithLatency(\r\n checkFn: () => Promise<boolean>\r\n ): Promise<ServiceHealth> {\r\n const start = Date.now();\r\n try {\r\n const healthy = await withTimeout(checkFn(), checkTimeout);\r\n return {\r\n status: healthy ? 'healthy' : 'unhealthy',\r\n latencyMs: Date.now() - start,\r\n lastChecked: new Date().toISOString(),\r\n };\r\n } catch (error) {\r\n return {\r\n status: 'unhealthy',\r\n latencyMs: Date.now() - start,\r\n message: error instanceof Error ? error.message : 'Unknown error',\r\n lastChecked: new Date().toISOString(),\r\n };\r\n }\r\n }\r\n\r\n function formatUptime(ms: number): string {\r\n const seconds = Math.floor(ms / 1000);\r\n const minutes = Math.floor(seconds / 60);\r\n const hours = Math.floor(minutes / 60);\r\n const days = Math.floor(hours / 24);\r\n\r\n if (days > 0) return `${days}d ${hours % 24}h ${minutes % 60}m`;\r\n if (hours > 0) return `${hours}h ${minutes % 60}m ${seconds % 60}s`;\r\n if (minutes > 0) return `${minutes}m ${seconds % 60}s`;\r\n return `${seconds}s`;\r\n }\r\n\r\n function getSystemMetrics() {\r\n if (!includeSystemMetrics) return undefined;\r\n\r\n const memoryUsage = process.memoryUsage();\r\n\r\n return {\r\n memoryUsage: {\r\n heapUsed: memoryUsage.heapUsed,\r\n heapTotal: memoryUsage.heapTotal,\r\n external: memoryUsage.external,\r\n rss: memoryUsage.rss,\r\n },\r\n };\r\n }\r\n\r\n return {\r\n async live(): Promise<LivenessResponse> {\r\n // Liveness is simple - if we can respond, we're alive\r\n return { status: 'ok' };\r\n },\r\n\r\n async ready(): Promise<ReadinessResponse> {\r\n try {\r\n const health = await getCachedHealth();\r\n\r\n // Run custom checks\r\n const customResults: Record<string, boolean> = {};\r\n for (const [name, check] of Object.entries(customChecks)) {\r\n try {\r\n customResults[name] = await withTimeout(check(), checkTimeout);\r\n } catch {\r\n customResults[name] = false;\r\n }\r\n }\r\n\r\n const allCustomHealthy = Object.values(customResults).every(Boolean);\r\n\r\n return {\r\n status: health.healthy && allCustomHealthy ? 'ok' : 'error',\r\n checks: {\r\n database: health.services.database,\r\n cache: health.services.cache,\r\n storage: health.services.storage,\r\n email: health.services.email,\r\n queue: health.services.queue,\r\n ...customResults,\r\n },\r\n };\r\n } catch {\r\n return {\r\n status: 'error',\r\n checks: {\r\n database: false,\r\n cache: false,\r\n storage: false,\r\n email: false,\r\n queue: false,\r\n },\r\n };\r\n }\r\n },\r\n\r\n async startup(): Promise<StartupResponse> {\r\n if (startupComplete) {\r\n return { status: 'ok', ready: true };\r\n }\r\n\r\n // Check if all services are ready\r\n try {\r\n const health = await getCachedHealth();\r\n if (health.healthy) {\r\n startupComplete = true;\r\n return { status: 'ok', ready: true };\r\n }\r\n } catch {\r\n // Not ready yet\r\n }\r\n\r\n return { status: 'error', ready: false };\r\n },\r\n\r\n async detailed(): Promise<DetailedHealthResponse> {\r\n const uptime = Date.now() - startTime;\r\n\r\n // Get individual service health with latencies\r\n const [dbHealth, cacheHealth, storageHealth, emailHealth, queueHealth] = await Promise.all([\r\n checkServiceWithLatency(() => platform.db.healthCheck()),\r\n checkServiceWithLatency(() => platform.cache.healthCheck()),\r\n checkServiceWithLatency(() => platform.storage.healthCheck()),\r\n checkServiceWithLatency(() => platform.email.healthCheck()),\r\n checkServiceWithLatency(() => platform.queue.healthCheck()),\r\n ]);\r\n\r\n const services = {\r\n database: dbHealth,\r\n cache: cacheHealth,\r\n storage: storageHealth,\r\n email: emailHealth,\r\n queue: queueHealth,\r\n };\r\n\r\n // Determine overall status\r\n const statuses = Object.values(services).map((s) => s.status);\r\n let overallStatus: HealthStatus = 'healthy';\r\n\r\n if (statuses.some((s) => s === 'unhealthy')) {\r\n overallStatus = 'unhealthy';\r\n } else if (statuses.some((s) => s === 'degraded')) {\r\n overallStatus = 'degraded';\r\n }\r\n\r\n return {\r\n status: overallStatus,\r\n version,\r\n environment,\r\n uptime,\r\n uptimeFormatted: formatUptime(uptime),\r\n timestamp: new Date().toISOString(),\r\n services,\r\n system: getSystemMetrics(),\r\n };\r\n },\r\n\r\n markStartupComplete(): void {\r\n startupComplete = true;\r\n },\r\n\r\n async getRawStatus(): Promise<PlatformHealthStatus> {\r\n return getCachedHealth();\r\n },\r\n };\r\n}\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// HELPERS\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\nasync function withTimeout<T>(promise: Promise<T>, timeoutMs: number): Promise<T> {\r\n let timeoutHandle: ReturnType<typeof setTimeout>;\r\n\r\n const timeoutPromise = new Promise<never>((_, reject) => {\r\n timeoutHandle = setTimeout(() => {\r\n reject(new Error(`Health check timed out after ${timeoutMs}ms`));\r\n }, timeoutMs);\r\n });\r\n\r\n try {\r\n return await Promise.race([promise, timeoutPromise]);\r\n } finally {\r\n clearTimeout(timeoutHandle!);\r\n }\r\n}\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// HTTP HANDLER FACTORIES\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\n/**\r\n * Create Express-compatible health route handlers\r\n */\r\nexport function createExpressHealthHandlers(endpoints: HealthEndpoints) {\r\n return {\r\n live: async (_req: unknown, res: { status: (code: number) => { json: (data: unknown) => void } }) => {\r\n const result = await endpoints.live();\r\n res.status(result.status === 'ok' ? 200 : 503).json(result);\r\n },\r\n\r\n ready: async (_req: unknown, res: { status: (code: number) => { json: (data: unknown) => void } }) => {\r\n const result = await endpoints.ready();\r\n res.status(result.status === 'ok' ? 200 : 503).json(result);\r\n },\r\n\r\n startup: async (_req: unknown, res: { status: (code: number) => { json: (data: unknown) => void } }) => {\r\n const result = await endpoints.startup();\r\n res.status(result.status === 'ok' ? 200 : 503).json(result);\r\n },\r\n\r\n detailed: async (_req: unknown, res: { status: (code: number) => { json: (data: unknown) => void } }) => {\r\n const result = await endpoints.detailed();\r\n const statusCode = result.status === 'healthy' ? 200 : result.status === 'degraded' ? 200 : 503;\r\n res.status(statusCode).json(result);\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Create a simple HTTP server for health checks (standalone, no framework)\r\n */\r\nexport async function createHealthServer(\r\n endpoints: HealthEndpoints,\r\n port: number = 8080\r\n): Promise<{ close: () => Promise<void> }> {\r\n const http = await import('http');\r\n\r\n const server = http.createServer(async (req, res) => {\r\n const url = req.url || '/';\r\n\r\n res.setHeader('Content-Type', 'application/json');\r\n\r\n try {\r\n let result: unknown;\r\n let statusCode = 200;\r\n\r\n switch (url) {\r\n case '/health/live':\r\n case '/healthz':\r\n result = await endpoints.live();\r\n statusCode = (result as LivenessResponse).status === 'ok' ? 200 : 503;\r\n break;\r\n\r\n case '/health/ready':\r\n case '/readyz':\r\n result = await endpoints.ready();\r\n statusCode = (result as ReadinessResponse).status === 'ok' ? 200 : 503;\r\n break;\r\n\r\n case '/health/startup':\r\n case '/startupz':\r\n result = await endpoints.startup();\r\n statusCode = (result as StartupResponse).status === 'ok' ? 200 : 503;\r\n break;\r\n\r\n case '/health':\r\n case '/':\r\n result = await endpoints.detailed();\r\n const detailed = result as DetailedHealthResponse;\r\n statusCode = detailed.status === 'healthy' ? 200 : detailed.status === 'degraded' ? 200 : 503;\r\n break;\r\n\r\n default:\r\n res.writeHead(404);\r\n res.end(JSON.stringify({ error: 'Not found' }));\r\n return;\r\n }\r\n\r\n res.writeHead(statusCode);\r\n res.end(JSON.stringify(result));\r\n } catch (error) {\r\n res.writeHead(500);\r\n res.end(JSON.stringify({ error: 'Internal server error' }));\r\n }\r\n });\r\n\r\n return new Promise((resolve) => {\r\n server.listen(port, () => {\r\n resolve({\r\n close: () =>\r\n new Promise<void>((res) => {\r\n server.close(() => res());\r\n }),\r\n });\r\n });\r\n });\r\n}\r\n","/**\r\n * Prometheus Metrics HTTP Endpoint\r\n *\r\n * Provides a /metrics endpoint that exports metrics in Prometheus text format.\r\n * This enables scraping by Prometheus, Grafana Agent, or other compatible systems.\r\n *\r\n * @example\r\n * ```typescript\r\n * import { createMetricsEndpoint } from '@digilogiclabs/platform-core';\r\n *\r\n * const metricsEndpoint = createMetricsEndpoint(platform.metrics, {\r\n * prefix: 'myapp',\r\n * defaultLabels: { service: 'api', environment: 'production' },\r\n * });\r\n *\r\n * // Get Prometheus format output\r\n * const prometheusText = metricsEndpoint.getPrometheusMetrics();\r\n *\r\n * // Or use the built-in server\r\n * const server = await createMetricsServer(metricsEndpoint, 9090);\r\n * ```\r\n */\r\n\r\nimport { IMetrics, MemoryMetrics, MetricsSummary } from '../interfaces/IMetrics';\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// TYPES\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\nexport interface MetricsEndpointOptions {\r\n /** Prefix for all metric names */\r\n prefix?: string;\r\n\r\n /** Default labels to add to all metrics */\r\n defaultLabels?: Record<string, string>;\r\n\r\n /** Include process metrics (memory, cpu, etc.) */\r\n includeProcessMetrics?: boolean;\r\n\r\n /** Include Node.js event loop metrics */\r\n includeEventLoopMetrics?: boolean;\r\n\r\n /** Histogram buckets for timing metrics */\r\n histogramBuckets?: number[];\r\n}\r\n\r\nexport interface MetricsEndpoint {\r\n /**\r\n * Get metrics in Prometheus text exposition format\r\n */\r\n getPrometheusMetrics(): string;\r\n\r\n /**\r\n * Get metrics as JSON (for debugging)\r\n */\r\n getJsonMetrics(): MetricsSummary;\r\n\r\n /**\r\n * Record a custom metric\r\n */\r\n recordMetric(type: 'counter' | 'gauge' | 'histogram', name: string, value: number, labels?: Record<string, string>): void;\r\n}\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// PROMETHEUS FORMAT HELPERS\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\nfunction sanitizeMetricName(name: string): string {\r\n // Prometheus metric names must match [a-zA-Z_:][a-zA-Z0-9_:]*\r\n return name\r\n .replace(/[.-]/g, '_')\r\n .replace(/[^a-zA-Z0-9_:]/g, '')\r\n .replace(/^([0-9])/, '_$1');\r\n}\r\n\r\nfunction formatLabels(labels: Record<string, string>): string {\r\n const entries = Object.entries(labels);\r\n if (entries.length === 0) return '';\r\n\r\n const formatted = entries\r\n .map(([key, value]) => `${sanitizeMetricName(key)}=\"${escapeLabel(value)}\"`)\r\n .join(',');\r\n\r\n return `{${formatted}}`;\r\n}\r\n\r\nfunction escapeLabel(value: string): string {\r\n return value\r\n .replace(/\\\\/g, '\\\\\\\\')\r\n .replace(/\"/g, '\\\\\"')\r\n .replace(/\\n/g, '\\\\n');\r\n}\r\n\r\nfunction parseMetricKey(key: string): { name: string; labels: Record<string, string> } {\r\n const pipeIndex = key.indexOf('|');\r\n if (pipeIndex === -1) {\r\n return { name: key, labels: {} };\r\n }\r\n\r\n const name = key.substring(0, pipeIndex);\r\n const labelString = key.substring(pipeIndex + 1);\r\n\r\n const labels: Record<string, string> = {};\r\n for (const pair of labelString.split(',')) {\r\n const colonIndex = pair.indexOf(':');\r\n if (colonIndex !== -1) {\r\n const labelKey = pair.substring(0, colonIndex);\r\n const labelValue = pair.substring(colonIndex + 1);\r\n labels[labelKey] = labelValue;\r\n }\r\n }\r\n\r\n return { name, labels };\r\n}\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// PROCESS METRICS COLLECTOR\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\ninterface ProcessMetrics {\r\n memoryHeapUsed: number;\r\n memoryHeapTotal: number;\r\n memoryExternal: number;\r\n memoryRss: number;\r\n uptimeSeconds: number;\r\n cpuUserSeconds?: number;\r\n cpuSystemSeconds?: number;\r\n}\r\n\r\nfunction collectProcessMetrics(): ProcessMetrics {\r\n const memoryUsage = process.memoryUsage();\r\n\r\n return {\r\n memoryHeapUsed: memoryUsage.heapUsed,\r\n memoryHeapTotal: memoryUsage.heapTotal,\r\n memoryExternal: memoryUsage.external,\r\n memoryRss: memoryUsage.rss,\r\n uptimeSeconds: process.uptime(),\r\n };\r\n}\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// IMPLEMENTATION\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\nexport function createMetricsEndpoint(\r\n metrics: IMetrics,\r\n options: MetricsEndpointOptions = {}\r\n): MetricsEndpoint {\r\n const {\r\n prefix = '',\r\n defaultLabels = {},\r\n includeProcessMetrics = true,\r\n histogramBuckets = [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10],\r\n } = options;\r\n\r\n const prefixName = (name: string) => (prefix ? `${prefix}_${name}` : name);\r\n\r\n function buildPrometheusOutput(summary: MetricsSummary): string {\r\n const lines: string[] = [];\r\n\r\n // Process metrics\r\n if (includeProcessMetrics) {\r\n const processMetrics = collectProcessMetrics();\r\n const processLabels = formatLabels(defaultLabels);\r\n\r\n lines.push('# HELP process_heap_bytes Node.js heap memory usage in bytes');\r\n lines.push('# TYPE process_heap_bytes gauge');\r\n lines.push(`process_heap_bytes${processLabels} ${processMetrics.memoryHeapUsed}`);\r\n\r\n lines.push('# HELP process_heap_total_bytes Node.js total heap size in bytes');\r\n lines.push('# TYPE process_heap_total_bytes gauge');\r\n lines.push(`process_heap_total_bytes${processLabels} ${processMetrics.memoryHeapTotal}`);\r\n\r\n lines.push('# HELP process_memory_rss_bytes Process resident set size in bytes');\r\n lines.push('# TYPE process_memory_rss_bytes gauge');\r\n lines.push(`process_memory_rss_bytes${processLabels} ${processMetrics.memoryRss}`);\r\n\r\n lines.push('# HELP process_uptime_seconds Process uptime in seconds');\r\n lines.push('# TYPE process_uptime_seconds counter');\r\n lines.push(`process_uptime_seconds${processLabels} ${processMetrics.uptimeSeconds}`);\r\n\r\n lines.push('');\r\n }\r\n\r\n // Counters\r\n for (const [key, value] of Object.entries(summary.counters)) {\r\n const { name, labels } = parseMetricKey(key);\r\n const metricName = sanitizeMetricName(prefixName(name));\r\n const allLabels = { ...defaultLabels, ...labels };\r\n const labelStr = formatLabels(allLabels);\r\n\r\n lines.push(`# HELP ${metricName} Counter metric`);\r\n lines.push(`# TYPE ${metricName} counter`);\r\n lines.push(`${metricName}${labelStr} ${value}`);\r\n lines.push('');\r\n }\r\n\r\n // Gauges\r\n for (const [key, value] of Object.entries(summary.gauges)) {\r\n const { name, labels } = parseMetricKey(key);\r\n const metricName = sanitizeMetricName(prefixName(name));\r\n const allLabels = { ...defaultLabels, ...labels };\r\n const labelStr = formatLabels(allLabels);\r\n\r\n lines.push(`# HELP ${metricName} Gauge metric`);\r\n lines.push(`# TYPE ${metricName} gauge`);\r\n lines.push(`${metricName}${labelStr} ${value}`);\r\n lines.push('');\r\n }\r\n\r\n // Histograms (with buckets)\r\n for (const [key, stats] of Object.entries(summary.histograms)) {\r\n const { name, labels } = parseMetricKey(key);\r\n const metricName = sanitizeMetricName(prefixName(name));\r\n const allLabels = { ...defaultLabels, ...labels };\r\n\r\n lines.push(`# HELP ${metricName} Histogram metric`);\r\n lines.push(`# TYPE ${metricName} histogram`);\r\n\r\n // Note: MemoryMetrics doesn't track individual values for histogram buckets,\r\n // so we output summary statistics instead\r\n const labelStr = formatLabels(allLabels);\r\n lines.push(`${metricName}_count${labelStr} ${stats.count}`);\r\n lines.push(`${metricName}_sum${labelStr} ${stats.sum}`);\r\n lines.push('');\r\n }\r\n\r\n // Timings (as histograms with percentiles as summary)\r\n for (const [key, stats] of Object.entries(summary.timings)) {\r\n const { name, labels } = parseMetricKey(key);\r\n const metricName = sanitizeMetricName(prefixName(name) + '_seconds');\r\n const allLabels = { ...defaultLabels, ...labels };\r\n\r\n lines.push(`# HELP ${metricName} Timing histogram (converted to seconds)`);\r\n lines.push(`# TYPE ${metricName} summary`);\r\n\r\n // Convert milliseconds to seconds for Prometheus convention\r\n const sumSeconds = stats.sum / 1000;\r\n const p50Seconds = stats.p50 / 1000;\r\n const p95Seconds = stats.p95 / 1000;\r\n const p99Seconds = stats.p99 / 1000;\r\n\r\n const p50Labels = { ...allLabels, quantile: '0.5' };\r\n const p95Labels = { ...allLabels, quantile: '0.95' };\r\n const p99Labels = { ...allLabels, quantile: '0.99' };\r\n\r\n lines.push(`${metricName}${formatLabels(p50Labels)} ${p50Seconds}`);\r\n lines.push(`${metricName}${formatLabels(p95Labels)} ${p95Seconds}`);\r\n lines.push(`${metricName}${formatLabels(p99Labels)} ${p99Seconds}`);\r\n lines.push(`${metricName}_count${formatLabels(allLabels)} ${stats.count}`);\r\n lines.push(`${metricName}_sum${formatLabels(allLabels)} ${sumSeconds}`);\r\n lines.push('');\r\n }\r\n\r\n // Sets (as gauge with cardinality)\r\n for (const [key, value] of Object.entries(summary.sets)) {\r\n const { name, labels } = parseMetricKey(key);\r\n const metricName = sanitizeMetricName(prefixName(name) + '_cardinality');\r\n const allLabels = { ...defaultLabels, ...labels };\r\n const labelStr = formatLabels(allLabels);\r\n\r\n lines.push(`# HELP ${metricName} Set cardinality (unique values)`);\r\n lines.push(`# TYPE ${metricName} gauge`);\r\n lines.push(`${metricName}${labelStr} ${value}`);\r\n lines.push('');\r\n }\r\n\r\n return lines.join('\\n');\r\n }\r\n\r\n return {\r\n getPrometheusMetrics(): string {\r\n // Get summary from MemoryMetrics if available\r\n if (metrics instanceof MemoryMetrics) {\r\n const summary = metrics.getSummary();\r\n return buildPrometheusOutput(summary);\r\n }\r\n\r\n // For other implementations, return just process metrics\r\n if (includeProcessMetrics) {\r\n const processMetrics = collectProcessMetrics();\r\n const processLabels = formatLabels(defaultLabels);\r\n\r\n return [\r\n '# HELP process_heap_bytes Node.js heap memory usage in bytes',\r\n '# TYPE process_heap_bytes gauge',\r\n `process_heap_bytes${processLabels} ${processMetrics.memoryHeapUsed}`,\r\n '',\r\n '# HELP process_heap_total_bytes Node.js total heap size in bytes',\r\n '# TYPE process_heap_total_bytes gauge',\r\n `process_heap_total_bytes${processLabels} ${processMetrics.memoryHeapTotal}`,\r\n '',\r\n '# HELP process_memory_rss_bytes Process resident set size in bytes',\r\n '# TYPE process_memory_rss_bytes gauge',\r\n `process_memory_rss_bytes${processLabels} ${processMetrics.memoryRss}`,\r\n '',\r\n '# HELP process_uptime_seconds Process uptime in seconds',\r\n '# TYPE process_uptime_seconds counter',\r\n `process_uptime_seconds${processLabels} ${processMetrics.uptimeSeconds}`,\r\n '',\r\n ].join('\\n');\r\n }\r\n\r\n return '';\r\n },\r\n\r\n getJsonMetrics(): MetricsSummary {\r\n if (metrics instanceof MemoryMetrics) {\r\n return metrics.getSummary();\r\n }\r\n\r\n return {\r\n counters: {},\r\n gauges: {},\r\n histograms: {},\r\n timings: {},\r\n sets: {},\r\n };\r\n },\r\n\r\n recordMetric(\r\n type: 'counter' | 'gauge' | 'histogram',\r\n name: string,\r\n value: number,\r\n labels: Record<string, string> = {}\r\n ): void {\r\n switch (type) {\r\n case 'counter':\r\n metrics.increment(name, value, labels);\r\n break;\r\n case 'gauge':\r\n metrics.gauge(name, value, labels);\r\n break;\r\n case 'histogram':\r\n metrics.histogram(name, value, labels);\r\n break;\r\n }\r\n },\r\n };\r\n}\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// HTTP HANDLER FACTORIES\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\n/**\r\n * Create Express-compatible metrics handler\r\n */\r\nexport function createExpressMetricsHandler(endpoint: MetricsEndpoint) {\r\n return (_req: unknown, res: {\r\n setHeader: (name: string, value: string) => void;\r\n status: (code: number) => { send: (data: string) => void }\r\n }) => {\r\n res.setHeader('Content-Type', 'text/plain; version=0.0.4; charset=utf-8');\r\n res.status(200).send(endpoint.getPrometheusMetrics());\r\n };\r\n}\r\n\r\n/**\r\n * Create a standalone HTTP server for metrics (no framework required)\r\n */\r\nexport async function createMetricsServer(\r\n endpoint: MetricsEndpoint,\r\n port: number = 9090\r\n): Promise<{ close: () => Promise<void>; port: number }> {\r\n const http = await import('http');\r\n\r\n const server = http.createServer((req, res) => {\r\n const url = req.url || '/';\r\n\r\n if (url === '/metrics' || url === '/') {\r\n res.setHeader('Content-Type', 'text/plain; version=0.0.4; charset=utf-8');\r\n res.writeHead(200);\r\n res.end(endpoint.getPrometheusMetrics());\r\n } else if (url === '/metrics.json') {\r\n res.setHeader('Content-Type', 'application/json');\r\n res.writeHead(200);\r\n res.end(JSON.stringify(endpoint.getJsonMetrics(), null, 2));\r\n } else {\r\n res.writeHead(404);\r\n res.end('Not found');\r\n }\r\n });\r\n\r\n return new Promise((resolve) => {\r\n server.listen(port, () => {\r\n resolve({\r\n port,\r\n close: () =>\r\n new Promise<void>((res) => {\r\n server.close(() => res());\r\n }),\r\n });\r\n });\r\n });\r\n}\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// COMBINED HEALTH + METRICS SERVER\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\nimport type { HealthEndpoints, DetailedHealthResponse, LivenessResponse, ReadinessResponse, StartupResponse } from './health';\r\n\r\n/**\r\n * Create a combined server that serves both health and metrics endpoints\r\n *\r\n * Endpoints:\r\n * - /health/live, /healthz - Liveness probe\r\n * - /health/ready, /readyz - Readiness probe\r\n * - /health/startup, /startupz - Startup probe\r\n * - /health - Detailed health\r\n * - /metrics - Prometheus metrics\r\n * - /metrics.json - JSON metrics (debugging)\r\n */\r\nexport async function createObservabilityServer(\r\n healthEndpoints: HealthEndpoints,\r\n metricsEndpoint: MetricsEndpoint,\r\n port: number = 8080\r\n): Promise<{ close: () => Promise<void>; port: number }> {\r\n const http = await import('http');\r\n\r\n const server = http.createServer(async (req, res) => {\r\n const url = req.url || '/';\r\n\r\n try {\r\n // Metrics endpoints\r\n if (url === '/metrics') {\r\n res.setHeader('Content-Type', 'text/plain; version=0.0.4; charset=utf-8');\r\n res.writeHead(200);\r\n res.end(metricsEndpoint.getPrometheusMetrics());\r\n return;\r\n }\r\n\r\n if (url === '/metrics.json') {\r\n res.setHeader('Content-Type', 'application/json');\r\n res.writeHead(200);\r\n res.end(JSON.stringify(metricsEndpoint.getJsonMetrics(), null, 2));\r\n return;\r\n }\r\n\r\n // Health endpoints\r\n res.setHeader('Content-Type', 'application/json');\r\n\r\n let result: unknown;\r\n let statusCode = 200;\r\n\r\n switch (url) {\r\n case '/health/live':\r\n case '/healthz':\r\n result = await healthEndpoints.live();\r\n statusCode = (result as LivenessResponse).status === 'ok' ? 200 : 503;\r\n break;\r\n\r\n case '/health/ready':\r\n case '/readyz':\r\n result = await healthEndpoints.ready();\r\n statusCode = (result as ReadinessResponse).status === 'ok' ? 200 : 503;\r\n break;\r\n\r\n case '/health/startup':\r\n case '/startupz':\r\n result = await healthEndpoints.startup();\r\n statusCode = (result as StartupResponse).status === 'ok' ? 200 : 503;\r\n break;\r\n\r\n case '/health':\r\n case '/':\r\n result = await healthEndpoints.detailed();\r\n const detailed = result as DetailedHealthResponse;\r\n statusCode = detailed.status === 'healthy' ? 200 : detailed.status === 'degraded' ? 200 : 503;\r\n break;\r\n\r\n default:\r\n res.writeHead(404);\r\n res.end(JSON.stringify({ error: 'Not found' }));\r\n return;\r\n }\r\n\r\n res.writeHead(statusCode);\r\n res.end(JSON.stringify(result));\r\n } catch (error) {\r\n res.setHeader('Content-Type', 'application/json');\r\n res.writeHead(500);\r\n res.end(JSON.stringify({ error: 'Internal server error' }));\r\n }\r\n });\r\n\r\n return new Promise((resolve) => {\r\n server.listen(port, () => {\r\n resolve({\r\n port,\r\n close: () =>\r\n new Promise<void>((res) => {\r\n server.close(() => res());\r\n }),\r\n });\r\n });\r\n });\r\n}\r\n","export { SupabaseDatabase, type SupabaseDatabaseConfig } from './SupabaseDatabase';\r\n","/**\r\n * PostgreSQL Database Adapter\r\n *\r\n * Direct PostgreSQL connection with true transaction support.\r\n */\r\n\r\nexport { PostgresDatabase, type PostgresConfig } from './PostgresDatabase';\r\n","export { UpstashCache, type UpstashCacheConfig } from './UpstashCache';\r\n","/**\r\n * Redis Direct Cache Adapter\r\n *\r\n * Direct Redis connection with full feature support including pub/sub.\r\n */\r\n\r\nexport { RedisCache, type RedisConfig } from './RedisCache';\r\n","export { S3Storage, type S3StorageConfig } from './S3Storage';\r\n","/**\r\n * Supabase Storage Adapter\r\n *\r\n * File storage via Supabase Storage buckets.\r\n */\r\n\r\nexport { SupabaseStorage, type SupabaseStorageConfig } from './SupabaseStorage';\r\n","export { ResendEmail, type ResendEmailConfig } from './ResendEmail';\r\n","/**\r\n * SMTP Email Adapter\r\n *\r\n * Standard SMTP email sending via nodemailer.\r\n */\r\n\r\nexport { SmtpEmail, type SmtpConfig } from './SmtpEmail';\r\n","export { BullMQQueue, type BullMQConfig } from './BullMQQueue';\r\n","/**\r\n * Database Migrator\r\n *\r\n * Enterprise-grade database migration system supporting:\r\n * - PostgreSQL (primary)\r\n * - Memory database (for testing)\r\n * - Transaction-safe migrations\r\n * - Concurrent execution locking\r\n * - Checksum validation\r\n * - Dry-run mode\r\n */\r\n\r\nimport type {\r\n IMigrator,\r\n Migration,\r\n MigrationRecord,\r\n MigrationResult,\r\n MigrationStatus,\r\n MigratorConfig,\r\n IMigrationDatabase,\r\n} from '../interfaces/IMigration';\r\n\r\nconst DEFAULT_CONFIG: Required<Omit<MigratorConfig, 'migrationsDir'>> & { migrationsDir?: string } = {\r\n tableName: '_migrations',\r\n schema: 'public',\r\n lockTimeout: 60,\r\n validateChecksums: true,\r\n migrationsDir: undefined,\r\n};\r\n\r\n/**\r\n * Generate a checksum for migration content\r\n */\r\nfunction generateChecksum(content: string): string {\r\n // Simple hash for checksum - in production you might use crypto\r\n let hash = 0;\r\n for (let i = 0; i < content.length; i++) {\r\n const char = content.charCodeAt(i);\r\n hash = (hash << 5) - hash + char;\r\n hash = hash & hash; // Convert to 32-bit integer\r\n }\r\n return Math.abs(hash).toString(16).padStart(8, '0');\r\n}\r\n\r\n/**\r\n * Sort migrations by version\r\n */\r\nfunction sortMigrations(migrations: Migration[]): Migration[] {\r\n return [...migrations].sort((a, b) => a.version.localeCompare(b.version));\r\n}\r\n\r\nexport class Migrator implements IMigrator {\r\n private db: IMigrationDatabase;\r\n private config: Required<Omit<MigratorConfig, 'migrationsDir'>> & { migrationsDir?: string };\r\n private migrations: Migration[] = [];\r\n private initialized = false;\r\n private locked = false;\r\n\r\n constructor(db: IMigrationDatabase, config: MigratorConfig = {}) {\r\n this.db = db;\r\n this.config = { ...DEFAULT_CONFIG, ...config };\r\n }\r\n\r\n /**\r\n * Get the fully qualified migration table name\r\n */\r\n private get tableName(): string {\r\n return `\"${this.config.schema}\".\"${this.config.tableName}\"`;\r\n }\r\n\r\n /**\r\n * Get the lock table name\r\n */\r\n private get lockTableName(): string {\r\n return `\"${this.config.schema}\".\"${this.config.tableName}_lock\"`;\r\n }\r\n\r\n /**\r\n * Initialize migration tracking tables\r\n */\r\n private async initialize(): Promise<void> {\r\n if (this.initialized) return;\r\n\r\n // Create schema if not exists\r\n await this.db.raw(`CREATE SCHEMA IF NOT EXISTS \"${this.config.schema}\"`);\r\n\r\n // Create migrations tracking table\r\n await this.db.raw(`\r\n CREATE TABLE IF NOT EXISTS ${this.tableName} (\r\n version VARCHAR(255) PRIMARY KEY,\r\n name VARCHAR(255) NOT NULL,\r\n applied_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,\r\n execution_time INTEGER NOT NULL,\r\n checksum VARCHAR(64)\r\n )\r\n `);\r\n\r\n // Create lock table for concurrent safety\r\n await this.db.raw(`\r\n CREATE TABLE IF NOT EXISTS ${this.lockTableName} (\r\n id INTEGER PRIMARY KEY DEFAULT 1,\r\n locked_at TIMESTAMP WITH TIME ZONE,\r\n locked_by VARCHAR(255),\r\n CONSTRAINT single_row CHECK (id = 1)\r\n )\r\n `);\r\n\r\n // Insert initial lock row if not exists\r\n await this.db.raw(`\r\n INSERT INTO ${this.lockTableName} (id, locked_at, locked_by)\r\n VALUES (1, NULL, NULL)\r\n ON CONFLICT (id) DO NOTHING\r\n `);\r\n\r\n this.initialized = true;\r\n }\r\n\r\n /**\r\n * Acquire migration lock\r\n */\r\n async lock(): Promise<boolean> {\r\n await this.initialize();\r\n\r\n const lockId = `${process.pid}-${Date.now()}`;\r\n const lockTimeout = new Date(Date.now() - this.config.lockTimeout * 1000);\r\n\r\n // Try to acquire lock (only if not locked or lock expired)\r\n const result = await this.db.raw<{ locked_at: Date | null }>(\r\n `\r\n UPDATE ${this.lockTableName}\r\n SET locked_at = CURRENT_TIMESTAMP, locked_by = $1\r\n WHERE id = 1 AND (locked_at IS NULL OR locked_at < $2)\r\n RETURNING locked_at\r\n `,\r\n [lockId, lockTimeout]\r\n );\r\n\r\n if (result.data.length > 0) {\r\n this.locked = true;\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Release migration lock\r\n */\r\n async unlock(): Promise<void> {\r\n if (!this.locked) return;\r\n\r\n await this.db.raw(\r\n `\r\n UPDATE ${this.lockTableName}\r\n SET locked_at = NULL, locked_by = NULL\r\n WHERE id = 1\r\n `\r\n );\r\n\r\n this.locked = false;\r\n }\r\n\r\n /**\r\n * Add migrations to the migrator\r\n */\r\n addMigrations(migrations: Migration[]): void {\r\n for (const migration of migrations) {\r\n // Generate checksum if not provided\r\n if (!migration.checksum) {\r\n const content =\r\n typeof migration.up === 'string' ? migration.up : migration.up.toString();\r\n migration.checksum = generateChecksum(content);\r\n }\r\n\r\n // Avoid duplicates\r\n if (!this.migrations.find((m) => m.version === migration.version)) {\r\n this.migrations.push(migration);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Load migrations from directory\r\n * Expects files named: {version}_{name}.ts or {version}_{name}.sql\r\n */\r\n async loadMigrations(dir: string): Promise<void> {\r\n // Dynamic import for Node.js file system\r\n const { readdir, readFile } = await import('fs/promises');\r\n const { join } = await import('path');\r\n\r\n const files = await readdir(dir);\r\n const migrationFiles = files.filter(\r\n (f) => f.match(/^\\d+_.*\\.(ts|js|sql)$/)\r\n );\r\n\r\n for (const file of migrationFiles) {\r\n const filePath = join(dir, file);\r\n const [version, ...nameParts] = file.replace(/\\.(ts|js|sql)$/, '').split('_');\r\n const name = nameParts.join('_');\r\n\r\n if (file.endsWith('.sql')) {\r\n // SQL file - parse UP and DOWN sections\r\n const content = await readFile(filePath, 'utf-8');\r\n const [up, down] = this.parseSqlMigration(content);\r\n\r\n this.addMigrations([\r\n {\r\n version: version!,\r\n name,\r\n up,\r\n down,\r\n },\r\n ]);\r\n } else {\r\n // TypeScript/JavaScript file - import the module\r\n const module = await import(filePath);\r\n this.addMigrations([\r\n {\r\n version: version!,\r\n name,\r\n up: module.up,\r\n down: module.down,\r\n transactional: module.transactional,\r\n },\r\n ]);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Parse SQL migration file with -- UP and -- DOWN sections\r\n */\r\n private parseSqlMigration(content: string): [string, string] {\r\n const upMatch = content.match(/--\\s*UP\\s*\\n([\\s\\S]*?)(?=--\\s*DOWN|$)/i);\r\n const downMatch = content.match(/--\\s*DOWN\\s*\\n([\\s\\S]*?)$/i);\r\n\r\n const up = upMatch?.[1]?.trim() ?? content.trim();\r\n const down = downMatch?.[1]?.trim() ?? '';\r\n\r\n return [up, down];\r\n }\r\n\r\n /**\r\n * Get current migration status\r\n */\r\n async status(): Promise<MigrationStatus> {\r\n await this.initialize();\r\n\r\n // Get applied migrations\r\n const result = await this.db.raw<{\r\n version: string;\r\n name: string;\r\n applied_at: Date;\r\n execution_time: number;\r\n checksum: string | null;\r\n }>(\r\n `SELECT version, name, applied_at, execution_time, checksum\r\n FROM ${this.tableName}\r\n ORDER BY version ASC`\r\n );\r\n\r\n const applied: MigrationRecord[] = result.data.map((row) => ({\r\n version: row.version,\r\n name: row.name,\r\n appliedAt: new Date(row.applied_at),\r\n executionTime: row.execution_time,\r\n checksum: row.checksum ?? undefined,\r\n }));\r\n\r\n const appliedVersions = new Set(applied.map((m) => m.version));\r\n const sortedMigrations = sortMigrations(this.migrations);\r\n\r\n const pending = sortedMigrations.filter(\r\n (m) => !appliedVersions.has(m.version)\r\n );\r\n\r\n return {\r\n applied,\r\n pending,\r\n currentVersion: applied.length > 0 ? applied[applied.length - 1]!.version : null,\r\n latestVersion:\r\n sortedMigrations.length > 0\r\n ? sortedMigrations[sortedMigrations.length - 1]!.version\r\n : null,\r\n };\r\n }\r\n\r\n /**\r\n * Run all pending migrations (or up to a specific version)\r\n */\r\n async up(options: { dryRun?: boolean; to?: string } = {}): Promise<MigrationResult[]> {\r\n const { dryRun = false, to } = options;\r\n const results: MigrationResult[] = [];\r\n\r\n if (!dryRun) {\r\n const acquired = await this.lock();\r\n if (!acquired) {\r\n throw new Error('Could not acquire migration lock. Another migration may be in progress.');\r\n }\r\n }\r\n\r\n try {\r\n const status = await this.status();\r\n let pending = status.pending;\r\n\r\n // Filter to specific version if requested\r\n if (to) {\r\n const targetIndex = pending.findIndex((m) => m.version === to);\r\n if (targetIndex === -1) {\r\n throw new Error(`Target version ${to} not found in pending migrations`);\r\n }\r\n pending = pending.slice(0, targetIndex + 1);\r\n }\r\n\r\n for (const migration of pending) {\r\n const result = await this.runMigration(migration, 'up', dryRun);\r\n results.push(result);\r\n\r\n if (!result.success) {\r\n break; // Stop on first failure\r\n }\r\n }\r\n } finally {\r\n if (!dryRun) {\r\n await this.unlock();\r\n }\r\n }\r\n\r\n return results;\r\n }\r\n\r\n /**\r\n * Rollback migrations\r\n */\r\n async down(options: { dryRun?: boolean; steps?: number } = {}): Promise<MigrationResult[]> {\r\n const { dryRun = false, steps = 1 } = options;\r\n const results: MigrationResult[] = [];\r\n\r\n if (!dryRun) {\r\n const acquired = await this.lock();\r\n if (!acquired) {\r\n throw new Error('Could not acquire migration lock. Another migration may be in progress.');\r\n }\r\n }\r\n\r\n try {\r\n const status = await this.status();\r\n\r\n // Get the last N applied migrations (in reverse order)\r\n const toRollback = status.applied.slice(-steps).reverse();\r\n\r\n for (const record of toRollback) {\r\n const migration = this.migrations.find((m) => m.version === record.version);\r\n if (!migration) {\r\n throw new Error(\r\n `Migration ${record.version} was applied but is not registered. Cannot rollback.`\r\n );\r\n }\r\n\r\n const result = await this.runMigration(migration, 'down', dryRun);\r\n results.push(result);\r\n\r\n if (!result.success) {\r\n break;\r\n }\r\n }\r\n } finally {\r\n if (!dryRun) {\r\n await this.unlock();\r\n }\r\n }\r\n\r\n return results;\r\n }\r\n\r\n /**\r\n * Rollback all migrations and re-run them\r\n */\r\n async reset(options: { dryRun?: boolean } = {}): Promise<MigrationResult[]> {\r\n const status = await this.status();\r\n const downResults = await this.down({\r\n dryRun: options.dryRun,\r\n steps: status.applied.length,\r\n });\r\n\r\n // Only proceed with up if all downs succeeded\r\n if (downResults.every((r) => r.success)) {\r\n const upResults = await this.up({ dryRun: options.dryRun });\r\n return [...downResults, ...upResults];\r\n }\r\n\r\n return downResults;\r\n }\r\n\r\n /**\r\n * Migrate to a specific version\r\n */\r\n async goto(version: string, options: { dryRun?: boolean } = {}): Promise<MigrationResult[]> {\r\n const status = await this.status();\r\n const currentVersion = status.currentVersion;\r\n const results: MigrationResult[] = [];\r\n\r\n // If already at target, nothing to do\r\n if (currentVersion === version) {\r\n return results;\r\n }\r\n\r\n // Determine direction\r\n const isUp = !currentVersion || version > currentVersion;\r\n\r\n if (isUp) {\r\n return this.up({ ...options, to: version });\r\n } else {\r\n // Find how many steps down we need to go\r\n const currentIndex = status.applied.findIndex((m) => m.version === currentVersion);\r\n const targetIndex = status.applied.findIndex((m) => m.version === version);\r\n\r\n if (targetIndex === -1) {\r\n throw new Error(`Target version ${version} not found in applied migrations`);\r\n }\r\n\r\n const steps = currentIndex - targetIndex;\r\n return this.down({ ...options, steps });\r\n }\r\n }\r\n\r\n /**\r\n * Run a single migration\r\n */\r\n private async runMigration(\r\n migration: Migration,\r\n direction: 'up' | 'down',\r\n dryRun: boolean\r\n ): Promise<MigrationResult> {\r\n const startTime = Date.now();\r\n const action = direction === 'up' ? migration.up : migration.down;\r\n\r\n try {\r\n if (dryRun) {\r\n // Just simulate - don't actually run\r\n return {\r\n migration,\r\n success: true,\r\n executionTime: 0,\r\n dryRun: true,\r\n };\r\n }\r\n\r\n const transactional = migration.transactional !== false;\r\n const runAction = async (db: IMigrationDatabase) => {\r\n if (typeof action === 'string') {\r\n const result = await db.raw(action);\r\n if (result.error) {\r\n throw result.error;\r\n }\r\n } else {\r\n await action(db);\r\n }\r\n };\r\n\r\n if (transactional) {\r\n await this.db.transaction(async (tx) => {\r\n await runAction(tx);\r\n });\r\n } else {\r\n await runAction(this.db);\r\n }\r\n\r\n const executionTime = Date.now() - startTime;\r\n\r\n // Update tracking table\r\n if (direction === 'up') {\r\n await this.db.raw(\r\n `INSERT INTO ${this.tableName} (version, name, execution_time, checksum)\r\n VALUES ($1, $2, $3, $4)`,\r\n [migration.version, migration.name, executionTime, migration.checksum]\r\n );\r\n } else {\r\n await this.db.raw(\r\n `DELETE FROM ${this.tableName} WHERE version = $1`,\r\n [migration.version]\r\n );\r\n }\r\n\r\n return {\r\n migration,\r\n success: true,\r\n executionTime,\r\n dryRun: false,\r\n };\r\n } catch (error) {\r\n return {\r\n migration,\r\n success: false,\r\n executionTime: Date.now() - startTime,\r\n error: error instanceof Error ? error : new Error(String(error)),\r\n dryRun: false,\r\n };\r\n }\r\n }\r\n\r\n /**\r\n * Create a new migration file\r\n */\r\n async create(name: string): Promise<string> {\r\n const { writeFile, mkdir } = await import('fs/promises');\r\n const { join } = await import('path');\r\n\r\n if (!this.config.migrationsDir) {\r\n throw new Error('migrationsDir must be configured to create migrations');\r\n }\r\n\r\n // Ensure directory exists\r\n await mkdir(this.config.migrationsDir, { recursive: true });\r\n\r\n // Generate version timestamp\r\n const now = new Date();\r\n const version = [\r\n now.getFullYear(),\r\n String(now.getMonth() + 1).padStart(2, '0'),\r\n String(now.getDate()).padStart(2, '0'),\r\n String(now.getHours()).padStart(2, '0'),\r\n String(now.getMinutes()).padStart(2, '0'),\r\n String(now.getSeconds()).padStart(2, '0'),\r\n ].join('');\r\n\r\n const safeName = name.replace(/[^a-zA-Z0-9_]/g, '_').toLowerCase();\r\n const fileName = `${version}_${safeName}.sql`;\r\n const filePath = join(this.config.migrationsDir, fileName);\r\n\r\n const template = `-- Migration: ${name}\r\n-- Version: ${version}\r\n-- Created: ${now.toISOString()}\r\n\r\n-- UP\r\n-- Add your forward migration SQL here\r\n\r\n\r\n-- DOWN\r\n-- Add your rollback migration SQL here\r\n\r\n`;\r\n\r\n await writeFile(filePath, template, 'utf-8');\r\n\r\n return filePath;\r\n }\r\n\r\n /**\r\n * Validate migration integrity\r\n */\r\n async validate(): Promise<{ valid: boolean; errors: string[] }> {\r\n const errors: string[] = [];\r\n const status = await this.status();\r\n\r\n if (!this.config.validateChecksums) {\r\n return { valid: true, errors };\r\n }\r\n\r\n for (const applied of status.applied) {\r\n const migration = this.migrations.find((m) => m.version === applied.version);\r\n\r\n if (!migration) {\r\n errors.push(\r\n `Migration ${applied.version} (${applied.name}) was applied but is not registered`\r\n );\r\n continue;\r\n }\r\n\r\n if (applied.checksum && migration.checksum !== applied.checksum) {\r\n errors.push(\r\n `Migration ${applied.version} (${applied.name}) has been modified since it was applied`\r\n );\r\n }\r\n }\r\n\r\n return {\r\n valid: errors.length === 0,\r\n errors,\r\n };\r\n }\r\n}\r\n","/**\r\n * Migration Helper Functions\r\n *\r\n * Utilities for creating migrations in a type-safe and convenient way.\r\n */\r\n\r\nimport type { Migration, IMigrationDatabase } from '../interfaces/IMigration';\r\n\r\n/**\r\n * Create a SQL-based migration\r\n *\r\n * @example\r\n * ```typescript\r\n * export default sqlMigration({\r\n * version: '20240101000000',\r\n * name: 'create_users',\r\n * up: `\r\n * CREATE TABLE users (\r\n * id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\r\n * email VARCHAR(255) UNIQUE NOT NULL,\r\n * created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()\r\n * )\r\n * `,\r\n * down: `DROP TABLE users`\r\n * });\r\n * ```\r\n */\r\nexport function sqlMigration(migration: {\r\n version: string;\r\n name: string;\r\n up: string;\r\n down: string;\r\n transactional?: boolean;\r\n}): Migration {\r\n return {\r\n version: migration.version,\r\n name: migration.name,\r\n up: migration.up,\r\n down: migration.down,\r\n transactional: migration.transactional,\r\n };\r\n}\r\n\r\n/**\r\n * Create a function-based migration for complex logic\r\n *\r\n * @example\r\n * ```typescript\r\n * export default createMigration({\r\n * version: '20240102000000',\r\n * name: 'seed_initial_data',\r\n * up: async (db) => {\r\n * await db.raw(`INSERT INTO users (email) VALUES ('admin@example.com')`);\r\n * await db.raw(`INSERT INTO settings (key, value) VALUES ('version', '1.0.0')`);\r\n * },\r\n * down: async (db) => {\r\n * await db.raw(`DELETE FROM settings WHERE key = 'version'`);\r\n * await db.raw(`DELETE FROM users WHERE email = 'admin@example.com'`);\r\n * }\r\n * });\r\n * ```\r\n */\r\nexport function createMigration(migration: {\r\n version: string;\r\n name: string;\r\n up: (db: IMigrationDatabase) => Promise<void>;\r\n down: (db: IMigrationDatabase) => Promise<void>;\r\n transactional?: boolean;\r\n}): Migration {\r\n return {\r\n version: migration.version,\r\n name: migration.name,\r\n up: migration.up,\r\n down: migration.down,\r\n transactional: migration.transactional,\r\n };\r\n}\r\n\r\n/**\r\n * Type-safe migration definition with inference\r\n * Useful for defining migrations in separate files\r\n *\r\n * @example\r\n * ```typescript\r\n * // migrations/20240101000000_create_users.ts\r\n * export const migration = defineMigration({\r\n * version: '20240101000000',\r\n * name: 'create_users',\r\n * up: 'CREATE TABLE users (...)',\r\n * down: 'DROP TABLE users'\r\n * });\r\n *\r\n * // Or with functions\r\n * export const migration = defineMigration({\r\n * version: '20240102000000',\r\n * name: 'complex_migration',\r\n * up: async (db) => { ... },\r\n * down: async (db) => { ... }\r\n * });\r\n * ```\r\n */\r\nexport function defineMigration<\r\n T extends {\r\n version: string;\r\n name: string;\r\n up: string | ((db: IMigrationDatabase) => Promise<void>);\r\n down: string | ((db: IMigrationDatabase) => Promise<void>);\r\n transactional?: boolean;\r\n }\r\n>(migration: T): Migration {\r\n return migration;\r\n}\r\n\r\n/**\r\n * Generate a version timestamp for new migrations\r\n *\r\n * @example\r\n * ```typescript\r\n * const version = generateVersion(); // '20240315143052'\r\n * ```\r\n */\r\nexport function generateVersion(): string {\r\n const now = new Date();\r\n return [\r\n now.getFullYear(),\r\n String(now.getMonth() + 1).padStart(2, '0'),\r\n String(now.getDate()).padStart(2, '0'),\r\n String(now.getHours()).padStart(2, '0'),\r\n String(now.getMinutes()).padStart(2, '0'),\r\n String(now.getSeconds()).padStart(2, '0'),\r\n ].join('');\r\n}\r\n\r\n/**\r\n * Common SQL snippets for migrations\r\n */\r\nexport const SQL = {\r\n /**\r\n * Create updated_at trigger function (PostgreSQL)\r\n */\r\n createUpdatedAtFunction: `\r\n CREATE OR REPLACE FUNCTION update_updated_at_column()\r\n RETURNS TRIGGER AS $$\r\n BEGIN\r\n NEW.updated_at = CURRENT_TIMESTAMP;\r\n RETURN NEW;\r\n END;\r\n $$ language 'plpgsql';\r\n `,\r\n\r\n /**\r\n * Create an updated_at trigger for a table\r\n */\r\n createUpdatedAtTrigger: (tableName: string) => `\r\n CREATE TRIGGER update_${tableName}_updated_at\r\n BEFORE UPDATE ON \"${tableName}\"\r\n FOR EACH ROW\r\n EXECUTE FUNCTION update_updated_at_column();\r\n `,\r\n\r\n /**\r\n * Drop an updated_at trigger\r\n */\r\n dropUpdatedAtTrigger: (tableName: string) => `\r\n DROP TRIGGER IF EXISTS update_${tableName}_updated_at ON \"${tableName}\";\r\n `,\r\n\r\n /**\r\n * Standard timestamp columns\r\n */\r\n timestampColumns: `\r\n created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL,\r\n updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL\r\n `,\r\n\r\n /**\r\n * UUID primary key with default\r\n */\r\n uuidPrimaryKey: `id UUID PRIMARY KEY DEFAULT gen_random_uuid()`,\r\n\r\n /**\r\n * Enable UUID extension\r\n */\r\n enableUuidExtension: `CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\"`,\r\n\r\n /**\r\n * Enable pgcrypto for gen_random_uuid()\r\n */\r\n enablePgCrypto: `CREATE EXTENSION IF NOT EXISTS \"pgcrypto\"`,\r\n};\r\n"],"mappings":"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","names":["data","error","query","PostgresDatabase","SupabaseDatabase","RedisCache","UpstashCache","SupabaseStorage","S3Storage","SmtpEmail","ResendEmail","BullMQQueue","OpenTelemetryTracing","value","withTimeout"]}