@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/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/interfaces/ISecrets.ts","../src/config.ts","../src/interfaces/ITracing.ts","../src/interfaces/ILogger.ts","../src/interfaces/IMetrics.ts","../src/factory.ts","../src/testing.ts"],"sourcesContent":["/**\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","/**\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","/**\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","/**\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","/**\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","/**\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 * Testing Utilities for Platform Core\r\n *\r\n * This module provides utilities for testing applications that use platform-core.\r\n * Import from '@digilogiclabs/platform-core/testing' in your test files.\r\n */\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// MEMORY ADAPTERS (Always safe for testing)\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\nexport { MemoryDatabase } from './adapters/memory/MemoryDatabase';\r\nexport { MemoryCache } from './adapters/memory/MemoryCache';\r\nexport { MemoryStorage } from './adapters/memory/MemoryStorage';\r\nexport { MemoryEmail } from './adapters/memory/MemoryEmail';\r\nexport { MemoryQueue } from './adapters/memory/MemoryQueue';\r\nexport { ConsoleEmail } from './adapters/console/ConsoleEmail';\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// SECRETS (Testing implementations)\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\nexport { MemorySecrets, EnvSecrets } from './interfaces/ISecrets';\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// FACTORY (Creates in-memory platform)\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\nexport { createPlatform } from './factory';\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// LOGGER & METRICS (Testing implementations)\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\nexport { ConsoleLogger, NoopLogger } from './interfaces/ILogger';\r\nexport { MemoryMetrics, NoopMetrics } from './interfaces/IMetrics';\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// INTERFACES (For type checking)\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\nexport type {\r\n IDatabase,\r\n IQueryBuilder,\r\n QueryResult,\r\n ICache,\r\n IStorage,\r\n IEmail,\r\n IQueue,\r\n IPlatform,\r\n ILogger,\r\n IMetrics,\r\n ISecrets,\r\n Job,\r\n JobOptions,\r\n EmailMessage,\r\n StorageFile,\r\n} from './interfaces';\r\n\r\n// ═══════════════════════════════════════════════════════════════\r\n// TEST HELPERS\r\n// ═══════════════════════════════════════════════════════════════\r\n\r\nimport type { IDatabase, IPlatform } from './interfaces';\r\nimport { createPlatform } from './factory';\r\nimport { MemoryDatabase } from './adapters/memory/MemoryDatabase';\r\nimport { MemoryCache } from './adapters/memory/MemoryCache';\r\nimport { MemoryStorage } from './adapters/memory/MemoryStorage';\r\nimport { MemoryEmail } from './adapters/memory/MemoryEmail';\r\nimport { MemoryQueue } from './adapters/memory/MemoryQueue';\r\n\r\n/**\r\n * Create a fresh test platform with all memory adapters.\r\n * Each call creates a new isolated platform instance.\r\n */\r\nexport function createTestPlatform(): IPlatform {\r\n return createPlatform();\r\n}\r\n\r\n/**\r\n * Test platform with access to underlying adapters for assertions.\r\n * Allows direct inspection of emails sent, queue jobs, etc.\r\n */\r\nexport interface TestPlatformWithInternals extends IPlatform {\r\n /** Access underlying memory database */\r\n memoryDb: MemoryDatabase;\r\n /** Access underlying memory cache */\r\n memoryCache: MemoryCache;\r\n /** Access underlying memory storage */\r\n memoryStorage: MemoryStorage;\r\n /** Access underlying memory email (check sent emails) */\r\n memoryEmail: MemoryEmail;\r\n /** Access underlying memory queue (check queued jobs) */\r\n memoryQueue: MemoryQueue;\r\n}\r\n\r\n/**\r\n * Create a test platform with direct access to underlying adapters.\r\n * Useful for asserting on emails sent, jobs queued, etc.\r\n *\r\n * @example\r\n * ```typescript\r\n * const { platform, memoryEmail, memoryQueue } = createTestPlatformWithInternals();\r\n *\r\n * // Run your code that sends emails\r\n * await myService.sendWelcomeEmail(user);\r\n *\r\n * // Assert email was sent\r\n * const sentEmails = memoryEmail.getSentEmails();\r\n * expect(sentEmails).toHaveLength(1);\r\n * expect(sentEmails[0].to).toBe(user.email);\r\n * ```\r\n */\r\nexport function createTestPlatformWithInternals(): TestPlatformWithInternals {\r\n const memoryDb = new MemoryDatabase();\r\n const memoryCache = new MemoryCache();\r\n const memoryStorage = new MemoryStorage();\r\n const memoryEmail = new MemoryEmail();\r\n const memoryQueue = new MemoryQueue();\r\n\r\n const platform: IPlatform = {\r\n db: memoryDb,\r\n cache: memoryCache,\r\n storage: memoryStorage,\r\n email: memoryEmail,\r\n queue: memoryQueue,\r\n\r\n async healthCheck() {\r\n const [dbHealth, cacheHealth, storageHealth, emailHealth, queueHealth] = await Promise.all([\r\n memoryDb.healthCheck(),\r\n memoryCache.healthCheck(),\r\n memoryStorage.healthCheck(),\r\n memoryEmail.healthCheck(),\r\n memoryQueue.healthCheck(),\r\n ]);\r\n\r\n return {\r\n healthy: dbHealth && cacheHealth && storageHealth && emailHealth && queueHealth,\r\n 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 timestamp: Date.now(),\r\n };\r\n },\r\n\r\n async close() {\r\n await Promise.all([memoryDb.close(), memoryCache.close(), memoryQueue.close()]);\r\n },\r\n };\r\n\r\n return {\r\n ...platform,\r\n memoryDb,\r\n memoryCache,\r\n memoryStorage,\r\n memoryEmail,\r\n memoryQueue,\r\n };\r\n}\r\n\r\n/**\r\n * Seed test data into a memory database.\r\n *\r\n * @example\r\n * ```typescript\r\n * const platform = createTestPlatform();\r\n * await seedTestData(platform.db, 'users', [\r\n * { id: '1', name: 'Alice', email: 'alice@test.com' },\r\n * { id: '2', name: 'Bob', email: 'bob@test.com' },\r\n * ]);\r\n * ```\r\n */\r\nexport async function seedTestData<T extends Record<string, unknown>>(\r\n db: IDatabase,\r\n table: string,\r\n data: T[]\r\n): Promise<void> {\r\n for (const row of data) {\r\n await db.from(table).insert(row).execute();\r\n }\r\n}\r\n\r\n/**\r\n * Clear all data from a test platform.\r\n * Useful in beforeEach/afterEach hooks.\r\n */\r\nexport async function clearTestPlatform(platform: TestPlatformWithInternals): Promise<void> {\r\n platform.memoryDb.clear();\r\n platform.memoryCache.clear();\r\n platform.memoryStorage.clear();\r\n platform.memoryEmail.clear();\r\n platform.memoryQueue.clear();\r\n}\r\n\r\n/**\r\n * Wait for all pending queue jobs to complete.\r\n * Useful when testing async workflows.\r\n *\r\n * @param platform - Test platform with memory queue\r\n * @param timeoutMs - Maximum time to wait (default: 5000ms)\r\n */\r\nexport async function waitForQueueDrain(\r\n platform: TestPlatformWithInternals,\r\n timeoutMs: number = 5000\r\n): Promise<void> {\r\n const startTime = Date.now();\r\n\r\n while (Date.now() - startTime < timeoutMs) {\r\n const pendingJobs = platform.memoryQueue.getPendingJobs?.() ?? [];\r\n if (pendingJobs.length === 0) {\r\n return;\r\n }\r\n await new Promise((resolve) => setTimeout(resolve, 50));\r\n }\r\n\r\n throw new Error(`Queue did not drain within ${timeoutMs}ms`);\r\n}\r\n\r\n/**\r\n * Assert that an email was sent with specific properties.\r\n */\r\nexport function assertEmailSent(\r\n memoryEmail: MemoryEmail,\r\n expected: {\r\n to?: string;\r\n subject?: string | RegExp;\r\n bodyContains?: string;\r\n }\r\n): void {\r\n const emails = memoryEmail.getSentEmails();\r\n\r\n const matchesTo = (emailTo: string | string[] | undefined, expectedTo: string): boolean => {\r\n if (!emailTo) return false;\r\n if (Array.isArray(emailTo)) {\r\n return emailTo.some((addr) => addr === expectedTo || (typeof addr === 'object' && (addr as { email?: string }).email === expectedTo));\r\n }\r\n return emailTo === expectedTo || (typeof emailTo === 'object' && (emailTo as { email?: string }).email === expectedTo);\r\n };\r\n\r\n const found = emails.find((email) => {\r\n if (expected.to && !matchesTo(email.to as unknown as string | string[], expected.to)) return false;\r\n if (expected.subject) {\r\n if (typeof expected.subject === 'string' && email.subject !== expected.subject) return false;\r\n if (expected.subject instanceof RegExp && !expected.subject.test(email.subject)) return false;\r\n }\r\n if (expected.bodyContains) {\r\n const body = email.html || email.text || '';\r\n if (!body.includes(expected.bodyContains)) return false;\r\n }\r\n return true;\r\n });\r\n\r\n if (!found) {\r\n const emailSummary = emails.map((e) => ` - To: ${JSON.stringify(e.to)}, Subject: ${e.subject}`).join('\\n');\r\n throw new Error(\r\n `Expected email not found.\\nExpected: ${JSON.stringify(expected)}\\nSent emails:\\n${emailSummary || ' (none)'}`\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * Create a mock function that tracks calls.\r\n * Simple alternative to jest.fn() for test frameworks without built-in mocking.\r\n */\r\nexport function createMockFn<TArgs extends unknown[], TReturn>(\r\n implementation?: (...args: TArgs) => TReturn\r\n): {\r\n (...args: TArgs): TReturn;\r\n calls: TArgs[];\r\n callCount: number;\r\n lastCall: TArgs | undefined;\r\n reset: () => void;\r\n} {\r\n const calls: TArgs[] = [];\r\n\r\n const fn = function (...args: TArgs): TReturn {\r\n calls.push(args);\r\n return implementation?.(...args) as TReturn;\r\n };\r\n\r\n Object.defineProperty(fn, 'calls', {\r\n get: () => calls,\r\n });\r\n\r\n Object.defineProperty(fn, 'callCount', {\r\n get: () => calls.length,\r\n });\r\n\r\n Object.defineProperty(fn, 'lastCall', {\r\n get: () => calls[calls.length - 1],\r\n });\r\n\r\n fn.reset = () => {\r\n calls.length = 0;\r\n };\r\n\r\n return fn as typeof fn & {\r\n calls: TArgs[];\r\n callCount: number;\r\n lastCall: TArgs | undefined;\r\n reset: () => void;\r\n };\r\n}\r\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,152 @@
1
+ {
2
+ "name": "@digilogiclabs/platform-core",
3
+ "version": "1.0.0",
4
+ "description": "Vendor-agnostic infrastructure abstraction layer for DLL Platform",
5
+ "keywords": [
6
+ "platform",
7
+ "infrastructure",
8
+ "abstraction",
9
+ "database",
10
+ "cache",
11
+ "storage",
12
+ "email",
13
+ "queue"
14
+ ],
15
+ "author": "Digi Logic Labs",
16
+ "license": "MIT",
17
+ "main": "./dist/index.js",
18
+ "module": "./dist/index.mjs",
19
+ "types": "./dist/index.d.ts",
20
+ "bin": {
21
+ "platform-migrate": "./dist/migrate.js"
22
+ },
23
+ "exports": {
24
+ ".": {
25
+ "types": "./dist/index.d.ts",
26
+ "import": "./dist/index.mjs",
27
+ "require": "./dist/index.js"
28
+ },
29
+ "./testing": {
30
+ "types": "./dist/testing.d.ts",
31
+ "import": "./dist/testing.mjs",
32
+ "require": "./dist/testing.js"
33
+ },
34
+ "./migrations": {
35
+ "types": "./dist/migrations/index.d.ts",
36
+ "import": "./dist/migrations/index.mjs",
37
+ "require": "./dist/migrations/index.js"
38
+ }
39
+ },
40
+ "files": [
41
+ "dist",
42
+ "README.md"
43
+ ],
44
+ "dependencies": {
45
+ "zod": "^3.23.0"
46
+ },
47
+ "devDependencies": {
48
+ "@aws-sdk/client-s3": "^3.943.0",
49
+ "@aws-sdk/s3-request-presigner": "^3.943.0",
50
+ "@opentelemetry/api": "^1.9.0",
51
+ "@opentelemetry/core": "^1.29.0",
52
+ "@opentelemetry/exporter-trace-otlp-http": "^0.56.0",
53
+ "@opentelemetry/exporter-trace-otlp-grpc": "^0.56.0",
54
+ "@opentelemetry/resources": "^1.29.0",
55
+ "@opentelemetry/sdk-trace-base": "^1.29.0",
56
+ "@opentelemetry/sdk-trace-node": "^1.29.0",
57
+ "@opentelemetry/semantic-conventions": "^1.28.0",
58
+ "@supabase/supabase-js": "^2.86.2",
59
+ "@types/node": "^20.0.0",
60
+ "@types/nodemailer": "^6.4.0",
61
+ "@types/pg": "^8.0.0",
62
+ "@upstash/redis": "^1.35.7",
63
+ "bullmq": "^5.65.1",
64
+ "ioredis": "^5.4.0",
65
+ "nodemailer": "^6.9.0",
66
+ "pg": "^8.13.0",
67
+ "resend": "^6.5.2",
68
+ "tsup": "^8.0.0",
69
+ "typescript": "^5.7.0",
70
+ "vitest": "^2.0.0"
71
+ },
72
+ "peerDependencies": {
73
+ "@aws-sdk/client-s3": ">=3.0.0",
74
+ "@aws-sdk/s3-request-presigner": ">=3.0.0",
75
+ "@opentelemetry/api": ">=1.0.0",
76
+ "@opentelemetry/core": ">=1.0.0",
77
+ "@opentelemetry/exporter-trace-otlp-http": ">=0.40.0",
78
+ "@opentelemetry/exporter-trace-otlp-grpc": ">=0.40.0",
79
+ "@opentelemetry/resources": ">=1.0.0",
80
+ "@opentelemetry/sdk-trace-base": ">=1.0.0",
81
+ "@opentelemetry/sdk-trace-node": ">=1.0.0",
82
+ "@opentelemetry/semantic-conventions": ">=1.0.0",
83
+ "@supabase/supabase-js": ">=2.0.0",
84
+ "@upstash/redis": ">=1.0.0",
85
+ "bullmq": ">=5.0.0",
86
+ "ioredis": ">=5.0.0",
87
+ "nodemailer": ">=6.0.0",
88
+ "pg": ">=8.0.0",
89
+ "resend": ">=2.0.0"
90
+ },
91
+ "peerDependenciesMeta": {
92
+ "@opentelemetry/api": {
93
+ "optional": true
94
+ },
95
+ "@opentelemetry/core": {
96
+ "optional": true
97
+ },
98
+ "@opentelemetry/exporter-trace-otlp-http": {
99
+ "optional": true
100
+ },
101
+ "@opentelemetry/exporter-trace-otlp-grpc": {
102
+ "optional": true
103
+ },
104
+ "@opentelemetry/resources": {
105
+ "optional": true
106
+ },
107
+ "@opentelemetry/sdk-trace-base": {
108
+ "optional": true
109
+ },
110
+ "@opentelemetry/sdk-trace-node": {
111
+ "optional": true
112
+ },
113
+ "@opentelemetry/semantic-conventions": {
114
+ "optional": true
115
+ },
116
+ "@supabase/supabase-js": {
117
+ "optional": true
118
+ },
119
+ "@upstash/redis": {
120
+ "optional": true
121
+ },
122
+ "@aws-sdk/client-s3": {
123
+ "optional": true
124
+ },
125
+ "@aws-sdk/s3-request-presigner": {
126
+ "optional": true
127
+ },
128
+ "bullmq": {
129
+ "optional": true
130
+ },
131
+ "nodemailer": {
132
+ "optional": true
133
+ },
134
+ "resend": {
135
+ "optional": true
136
+ },
137
+ "ioredis": {
138
+ "optional": true
139
+ },
140
+ "pg": {
141
+ "optional": true
142
+ }
143
+ },
144
+ "scripts": {
145
+ "build": "tsup",
146
+ "dev": "tsup --watch",
147
+ "type-check": "tsc --noEmit",
148
+ "test": "vitest run",
149
+ "test:watch": "vitest",
150
+ "benchmark": "tsx benchmarks/benchmark.ts"
151
+ }
152
+ }