@burdenoff/be-sdk 2026.722.3 → 2026.725.1
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.
- package/dist/auth/index.d.ts +2 -2
- package/dist/cache/index.d.ts +1 -1
- package/dist/cache/index.js +1 -1
- package/dist/{chunk-MXLCLLCI.js → chunk-EJPRCENB.js} +118 -83
- package/dist/chunk-EJPRCENB.js.map +1 -0
- package/dist/{chunk-PQJ6MN4U.js → chunk-ESLJ2732.js} +3 -3
- package/dist/{chunk-PQJ6MN4U.js.map → chunk-ESLJ2732.js.map} +1 -1
- package/dist/{chunk-WM5COTOD.js → chunk-F5SGJ6VS.js} +118 -4
- package/dist/chunk-F5SGJ6VS.js.map +1 -0
- package/dist/{chunk-I3ZYYDNN.js → chunk-IIYIO2GG.js} +83 -11
- package/dist/chunk-IIYIO2GG.js.map +1 -0
- package/dist/{chunk-KKJPFKO5.js → chunk-QMDYY6GJ.js} +2 -2
- package/dist/{chunk-KKJPFKO5.js.map → chunk-QMDYY6GJ.js.map} +1 -1
- package/dist/{chunk-YQ6FYE37.js → chunk-RIH3XRBX.js} +4 -3
- package/dist/chunk-RIH3XRBX.js.map +1 -0
- package/dist/{chunk-YCKM7FS7.js → chunk-WCJIZR5Q.js} +123 -10
- package/dist/chunk-WCJIZR5Q.js.map +1 -0
- package/dist/{chunk-JCBYU5BE.js → chunk-YH6PCW6L.js} +3 -3
- package/dist/{chunk-JCBYU5BE.js.map → chunk-YH6PCW6L.js.map} +1 -1
- package/dist/{chunk-U77L54IQ.js → chunk-ZVZ4RAIH.js} +3 -3
- package/dist/{chunk-U77L54IQ.js.map → chunk-ZVZ4RAIH.js.map} +1 -1
- package/dist/export/index.js +3 -3
- package/dist/feature-flags/index.d.ts +9 -1
- package/dist/feature-flags/index.js +2 -1
- package/dist/gateway/index.js +2 -2
- package/dist/gateway/security/index.js +1 -1
- package/dist/{index-D0tR4rjy.d.ts → index-ELt2ADCe.d.ts} +19 -2
- package/dist/{index-CgTMsars.d.ts → index-N8DMWKzw.d.ts} +4 -0
- package/dist/{index-lcW5eSTp.d.ts → index-PJZzGd8r.d.ts} +19 -2
- package/dist/{index-42_fqdmi.d.ts → index-m4sVVdZ6.d.ts} +3 -2
- package/dist/index.d.ts +6 -6
- package/dist/index.js +10 -10
- package/dist/init/index.js +3 -3
- package/dist/platform/index.d.ts +1 -1
- package/dist/platform/index.js +1 -1
- package/dist/prisma/index.d.ts +2 -2
- package/dist/prisma/index.js +2 -2
- package/dist/server/index.d.ts +3 -3
- package/dist/server/index.js +1 -1
- package/dist/{types-DVG_lcsL.d.ts → types-BeDCdzH9.d.ts} +2 -2
- package/dist/{workspace-extension-TquhDEKU.d.ts → workspace-extension-DxQw6N3b.d.ts} +9 -1
- package/package.json +1 -1
- package/dist/chunk-I3ZYYDNN.js.map +0 -1
- package/dist/chunk-MXLCLLCI.js.map +0 -1
- package/dist/chunk-WM5COTOD.js.map +0 -1
- package/dist/chunk-YCKM7FS7.js.map +0 -1
- package/dist/chunk-YQ6FYE37.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cache/index.ts","../src/cache/implementations/memory/MemoryCacheProvider.ts","../src/cache/implementations/valkey/ValkeyGlideProvider.ts","../src/cache/factory/CacheFactory.ts","../src/cache/types/config.ts"],"names":["MemoryCacheProvider","cache","Map","namespace","defaultTTL","maxSize","enableLogging","connected","stats","hits","misses","sets","deletes","evictions","config","startCleanupInterval","connect","Promise","resolve","logger","info","disconnect","clear","isConnected","healthCheck","status","timestamp","Date","toISOString","latencyMs","details","provider","cacheSize","size","getStatistics","totalOperations","hitRate","memoryUsed","keyCount","buildKey","key","isExpired","expiresAt","now","evictIfNeeded","firstKey","keys","next","value","delete","cleanup","cleaned","entries","debug","setInterval","get","_options","cacheKey","cached","set","entry","data","options","ttlSeconds","ttl","metadata","deleted","has","remaining","Math","floor","expire","mget","result","mset","mdel","matchPattern","pattern","includes","parts","split","position","i","length","part","index","indexOf","lastPart","endsWith","clearPattern","searchPattern","matchedKeys","prefix","push","replace","limitedKeys","limit","slice","nextCursor","totalCount","cleared","Array","from","startsWith","increment","amount","current","newValue","decrement","getOrSet","fetcher","invalidateTags","tags","totalDeleted","tag","readPositiveIntEnv","name","fallback","raw","process","env","parsed","parseInt","Number","isFinite","CONNECT_RETRY_COOLDOWN_MS","CONNECT_ATTEMPT_TIMEOUT_MS","CONNECTION_TIMEOUT_MS","REQUEST_TIMEOUT_MS","MAX_CONSECUTIVE_OP_FAILURES","COOLDOWN_LOG_INTERVAL_MS","isConnectionLevelError","error","Error","message","toLowerCase","test","ValkeyGlideProvider","client","clusterScanCursor","clientIsCluster","connectPromise","lastConnectFailureAt","consecutiveOpFailures","lastCooldownLogAt","dbNamespaceSuffixApplied","errors","serverReportsCluster","scanClusterKeys","clusterClient","cursor","batch","scan","match","count","isFinished","getKeys","ensureConnected","sinceFailureMs","finally","withConnectBudget","pending","timer","timeout","_","reject","setTimeout","String","race","then","close","catch","undefined","clearTimeout","glideModule","importError","GlideClient","default","GlideClusterClient","ClusterScanCursor","host","port","password","username","useTLSFromUrl","databaseFromUrl","url","rawUrl","URL","hostname","decodeURIComponent","dbMatch","exec","pathname","isAzureManagedRedis","warn","addresses","clusterNodes","baseClientConfig","useTLS","credentials","clientName","databaseId","db","requestTimeout","connectionBackoff","numberOfRetries","maxReconnectAttempts","factor","reconnectTimeWait","exponentBase","readFrom","advancedConfiguration","connectionTimeout","cluster","createClient","periodicChecks","duration_in_sec","refreshTopologyFromInitialNodes","standaloneClient","registerDisposable","normalized","shutdownName","dispose","unregisterDisposable","recordOpSuccess","noteOpError","resetClientForReconnect","logOpError","what","dead","startTime","ping","memoryRegex","memoryMatch","dbsize","JSON","parse","stringify","expiry","type","del","exists","cacheKeys","map","values","requested","found","keyValuePairs","Object","cleanKeys","incrBy","decrBy","CacheFactory","instances","parseBoolean","trim","parseClusterNodes","nodes","node","filter","Boolean","rawPort","resolvePort","layerPort","genericPort","defaultPort","createCache","keyPrefix","tls","enabled","createCacheFromEnv","envType","getInstance","instanceKey","closeInstance","closeAll","promises","all","createCacheForLayer","layer","serviceName","envPrefix","toUpperCase","defaults","DEFAULT_LAYER_RESOURCES","valkeyUrl","resolvedPort","getInstanceForLayer","CacheProviderType","getCache","getValkeyClient","valkeyConfig","VALKEY","closeAllCaches"],"mappings":"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","file":"chunk-I3ZYYDNN.js","sourcesContent":["/**\n * Cache - Public API\n *\n * This module provides a complete abstraction over caching systems (Valkey, Memory, etc.)\n * allowing the application to cache data without direct dependency on any specific caching implementation.\n *\n * Usage:\n *\n * // Create cache from environment variables (workspaces-backend)\n * import { createCache } from '@burdenoff/be-sdk/cache';\n *\n * const cache = createCache('my-module');\n * await cache.connect();\n *\n * // Set value\n * await cache.set('user:123', { name: 'John', email: 'john@example.com' }, { ttl: 3600 });\n *\n * // Get value\n * const user = await cache.get<User>('user:123');\n *\n * // Delete value\n * await cache.delete('user:123');\n *\n * // Disconnect when done\n * await cache.disconnect();\n */\n// Import factory for use in convenience functions\nimport { CacheFactory } from './factory/CacheFactory.js';\nimport type { ICacheProvider } from './interfaces/ICacheProvider.js';\n// Re-export for convenience\nimport type { CacheConfig, ValkeyCacheConfig } from './types/config.js';\nimport { CacheProviderType } from './types/config.js';\n\n// Export interfaces\nexport type { ICache } from './interfaces/ICache.js';\nexport type { ICacheProvider } from './interfaces/ICacheProvider.js';\n\n// Export types\nexport type { CacheEntry, CacheOptions, BatchCacheOptions, PatternOptions, PatternResult } from './types/cache.js';\n\nexport type {\n BaseCacheConfig,\n ValkeyCacheConfig,\n MemoryCacheConfig,\n MemcachedCacheConfig,\n CacheConfig,\n CacheHealthCheckResult,\n CacheStatistics,\n CacheProviderTypeLiteral,\n} from './types/config.js';\n\nexport { CacheProviderType } from './types/config.js';\n\n// Export factory\nexport { CacheFactory } from './factory/CacheFactory.js';\n\n// Export implementations (in case direct access is needed)\nexport { ValkeyGlideProvider } from './implementations/valkey/ValkeyGlideProvider.js';\nexport type { ValkeyGlideConfig } from './implementations/valkey/ValkeyGlideProvider.js';\nexport { MemoryCacheProvider } from './implementations/memory/MemoryCacheProvider.js';\n\n/**\n * Create a cache instance from environment configuration\n * Convenience function for creating a cache without manual config\n *\n * @param namespace - Cache namespace (e.g., 'analytics', 'files', 'users')\n * @returns Cache provider instance\n */\nexport function createCache(namespace: string = 'default'): ICacheProvider {\n return CacheFactory.createCacheFromEnv(namespace);\n}\n\n/**\n * Get or create a singleton cache instance\n * Convenience function for getting/creating a singleton cache\n *\n * @param namespace - Cache namespace\n * @param config - Optional cache configuration\n * @returns Singleton cache provider instance\n */\nexport function getCache(namespace: string = 'default', config?: CacheConfig): ICacheProvider {\n return CacheFactory.getInstance(namespace, config);\n}\n\n/**\n * Valkey Glide client interface for raw Valkey operations\n */\nexport interface ValkeyGlideClient {\n get(key: string): Promise<string | null>;\n set(key: string, value: string, options?: { EX?: number }): Promise<string | null>;\n del(keys: string[]): Promise<number>;\n exists(keys: string[]): Promise<number>;\n ttl(key: string): Promise<number>;\n expire(key: string, seconds: number): Promise<boolean>;\n mget(keys: string[]): Promise<(string | null)[]>;\n mset(keyValuePairs: Record<string, string>): Promise<string | null>;\n keys(pattern: string): Promise<string[]>;\n incrBy(key: string, amount: number): Promise<number>;\n decrBy(key: string, amount: number): Promise<number>;\n ping(): Promise<string>;\n info(section?: string): Promise<string>;\n dbsize(): Promise<number>;\n close(): Promise<void>;\n // Additional list operations\n lpush(key: string, ...values: string[]): Promise<number>;\n rpush(key: string, ...values: string[]): Promise<number>;\n lpop(key: string): Promise<string | null>;\n rpop(key: string): Promise<string | null>;\n lrange(key: string, start: number, stop: number): Promise<string[]>;\n llen(key: string): Promise<number>;\n // Additional set operations\n sadd(key: string, ...members: string[]): Promise<number>;\n srem(key: string, ...members: string[]): Promise<number>;\n smembers(key: string): Promise<string[]>;\n sismember(key: string, member: string): Promise<boolean>;\n // Additional hash operations\n hset(key: string, field: string, value: string): Promise<number>;\n hget(key: string, field: string): Promise<string | null>;\n hdel(key: string, ...fields: string[]): Promise<number>;\n hgetall(key: string): Promise<Record<string, string>>;\n // Pub/Sub operations\n publish(channel: string, message: string): Promise<number>;\n}\n\n/**\n * Get direct access to Valkey client via @valkey/valkey-glide\n * Useful for cases where you need raw Valkey operations beyond caching\n *\n * @param config - Optional Valkey configuration. If not provided, uses environment variables\n * @returns ValkeyGlideClient instance from @valkey/valkey-glide\n *\n * @example\n * ```typescript\n * import { getValkeyClient } from '@burdenoff/be-sdk';\n *\n * const valkey = await getValkeyClient();\n * await valkey.lpush('mylist', 'value');\n * ```\n */\nexport async function getValkeyClient(config?: ValkeyCacheConfig): Promise<ValkeyGlideClient> {\n const glideModule = await import('@valkey/valkey-glide');\n const GlideClient = glideModule.GlideClient || glideModule.default;\n\n const valkeyConfig: ValkeyCacheConfig = config || {\n type: CacheProviderType.VALKEY,\n // Fall back to REDIS_URL when VALKEY_URL is unset/empty (see CacheFactory).\n url: process.env['VALKEY_URL'] || process.env['REDIS_URL'],\n host: process.env['VALKEY_HOST'] || 'localhost',\n port: process.env['VALKEY_PORT'] ? parseInt(process.env['VALKEY_PORT'], 10) : 6379,\n password: process.env['VALKEY_PASSWORD'],\n db: process.env['VALKEY_DB'] ? parseInt(process.env['VALKEY_DB'], 10) : 0,\n username: process.env['VALKEY_USERNAME'],\n };\n\n // Parse URL if provided\n let host = valkeyConfig.host || 'localhost';\n let port = valkeyConfig.port || 6379;\n\n if (valkeyConfig.url) {\n const url = new URL(valkeyConfig.url.replace('valkey://', 'redis://'));\n host = url.hostname;\n port = parseInt(url.port || '6379', 10);\n }\n\n // Create Glide client\n const createClient = GlideClient as {\n createClient: (config: {\n addresses: Array<{ host: string; port: number }>;\n useTLS?: boolean;\n credentials?: { password?: string; username?: string };\n clientName?: string;\n readFrom?: string;\n }) => Promise<ValkeyGlideClient>;\n };\n\n return createClient.createClient({\n addresses: [{ host, port }],\n useTLS: valkeyConfig.useTLS,\n credentials: valkeyConfig.password\n ? {\n password: valkeyConfig.password,\n username: valkeyConfig.username,\n }\n : undefined,\n clientName: valkeyConfig.name || 'valkey-glide-client',\n readFrom: 'primary',\n });\n}\n\n/**\n * Close all cache connections\n * Call this during application shutdown\n */\nexport async function closeAllCaches(): Promise<void> {\n await CacheFactory.closeAll();\n}\n","/**\n * Memory Cache Provider\n * In-memory cache implementation (for testing and fallback)\n */\nimport { logger } from '../../../logger/index.js';\n\nimport type { ICacheProvider } from '../../interfaces/ICacheProvider.js';\nimport type {\n BatchCacheOptions,\n CacheEntry,\n CacheOptions,\n CacheStatistics,\n CacheHealthCheckResult,\n MemoryCacheConfig,\n PatternOptions,\n PatternResult,\n} from '../../types/index.js';\n\n/**\n * Memory cache provider implementation (LRU-based)\n */\nexport class MemoryCacheProvider implements ICacheProvider {\n private cache: Map<string, { entry: CacheEntry<unknown>; expiresAt: number }> = new Map();\n private readonly namespace: string;\n private readonly defaultTTL: number;\n private readonly maxSize: number;\n private readonly enableLogging: boolean;\n private connected: boolean = false;\n\n // Statistics\n private stats = {\n hits: 0,\n misses: 0,\n sets: 0,\n deletes: 0,\n evictions: 0,\n };\n\n constructor(config: MemoryCacheConfig, namespace: string = 'default') {\n this.namespace = namespace;\n this.defaultTTL = config.defaultTTL || 300; // 5 minutes default\n this.maxSize = config.maxSize || 1000; // Max 1000 entries by default\n this.enableLogging = config.enableLogging ?? false;\n\n // Start cleanup interval for expired entries\n this.startCleanupInterval();\n }\n\n /**\n * Connect (no-op for memory cache)\n */\n async connect(): Promise<void> {\n await Promise.resolve();\n this.connected = true;\n if (this.enableLogging) {\n logger.info(`[MemoryCacheProvider:${this.namespace}] Connected (in-memory)`);\n }\n }\n\n /**\n * Disconnect (cleanup)\n */\n async disconnect(): Promise<void> {\n await Promise.resolve();\n this.connected = false;\n this.cache.clear();\n if (this.enableLogging) {\n logger.info(`[MemoryCacheProvider:${this.namespace}] Disconnected`);\n }\n }\n\n /**\n * Check if connected\n */\n isConnected(): boolean {\n return this.connected;\n }\n\n /**\n * Health check\n */\n async healthCheck(): Promise<CacheHealthCheckResult> {\n await Promise.resolve();\n return {\n status: 'healthy',\n timestamp: new Date().toISOString(),\n connected: this.connected,\n latencyMs: 0,\n details: {\n provider: 'memory',\n cacheSize: this.cache.size,\n maxSize: this.maxSize,\n },\n };\n }\n\n /**\n * Get statistics\n */\n async getStatistics(): Promise<CacheStatistics> {\n await Promise.resolve();\n const totalOperations = this.stats.hits + this.stats.misses;\n const hitRate = totalOperations > 0 ? this.stats.hits / totalOperations : 0;\n\n // Calculate approximate memory usage (rough estimate)\n const memoryUsed = this.cache.size * 500; // Assume ~500 bytes per entry\n\n return {\n hits: this.stats.hits,\n misses: this.stats.misses,\n hitRate,\n keyCount: this.cache.size,\n memoryUsed,\n totalOperations,\n details: {\n sets: this.stats.sets,\n deletes: this.stats.deletes,\n evictions: this.stats.evictions,\n maxSize: this.maxSize,\n },\n };\n }\n\n /**\n * Build cache key with namespace\n */\n private buildKey(key: string): string {\n return `${this.namespace}:${key}`;\n }\n\n /**\n * Check if entry is expired\n */\n private isExpired(expiresAt: number): boolean {\n return Date.now() > expiresAt;\n }\n\n /**\n * Evict LRU entry if cache is full\n */\n private evictIfNeeded(): void {\n if (this.cache.size >= this.maxSize) {\n // Evict the first (oldest) entry (simple LRU)\n const firstKey = this.cache.keys().next().value;\n if (firstKey) {\n this.cache.delete(firstKey);\n this.stats.evictions++;\n }\n }\n }\n\n /**\n * Cleanup expired entries\n */\n private cleanup(): void {\n let cleaned = 0;\n\n for (const [key, value] of this.cache.entries()) {\n if (this.isExpired(value.expiresAt)) {\n this.cache.delete(key);\n cleaned++;\n }\n }\n\n if (cleaned > 0 && this.enableLogging) {\n logger.debug(`[MemoryCacheProvider:${this.namespace}] Cleaned up ${cleaned} expired entries`);\n }\n }\n\n /**\n * Start cleanup interval\n */\n private startCleanupInterval(): void {\n setInterval(() => this.cleanup(), 60000); // Cleanup every minute\n }\n\n /**\n * Get value from cache\n */\n async get<T>(key: string, _options?: CacheOptions): Promise<T | null> {\n await Promise.resolve();\n const cacheKey = this.buildKey(key);\n const cached = this.cache.get(cacheKey);\n\n if (!cached) {\n this.stats.misses++;\n if (this.enableLogging) {\n logger.debug(`[MemoryCacheProvider:${this.namespace}] Cache miss`, { key });\n }\n return null;\n }\n\n // Check if expired\n if (this.isExpired(cached.expiresAt)) {\n this.cache.delete(cacheKey);\n this.stats.misses++;\n if (this.enableLogging) {\n logger.debug(`[MemoryCacheProvider:${this.namespace}] Cache miss (expired)`, { key });\n }\n return null;\n }\n\n this.stats.hits++;\n if (this.enableLogging) {\n logger.debug(`[MemoryCacheProvider:${this.namespace}] Cache hit`, { key });\n }\n\n // Move to end (LRU)\n this.cache.delete(cacheKey);\n this.cache.set(cacheKey, cached);\n\n return cached.entry.data as T;\n }\n\n /**\n * Set value in cache\n */\n async set<T>(key: string, value: T, options?: CacheOptions): Promise<boolean> {\n await Promise.resolve();\n const cacheKey = this.buildKey(key);\n const ttlSeconds = options?.ttl || this.defaultTTL;\n\n this.evictIfNeeded();\n\n const entry: CacheEntry<T> = {\n data: value,\n timestamp: Date.now(),\n ttl: ttlSeconds,\n metadata: options?.metadata,\n };\n\n this.cache.set(cacheKey, {\n entry: entry,\n expiresAt: Date.now() + ttlSeconds * 1000,\n });\n\n this.stats.sets++;\n if (this.enableLogging) {\n logger.debug(`[MemoryCacheProvider:${this.namespace}] Cache set`, {\n key,\n ttl: ttlSeconds,\n });\n }\n\n return true;\n }\n\n /**\n * Delete value from cache\n */\n async delete(key: string): Promise<boolean> {\n await Promise.resolve();\n const cacheKey = this.buildKey(key);\n const deleted = this.cache.delete(cacheKey);\n\n if (deleted) {\n this.stats.deletes++;\n if (this.enableLogging) {\n logger.debug(`[MemoryCacheProvider:${this.namespace}] Cache delete`, { key });\n }\n }\n\n return deleted;\n }\n\n /**\n * Check if key exists\n */\n async has(key: string): Promise<boolean> {\n await Promise.resolve();\n const cacheKey = this.buildKey(key);\n const cached = this.cache.get(cacheKey);\n\n if (!cached) {\n return false;\n }\n\n // Check if expired\n if (this.isExpired(cached.expiresAt)) {\n this.cache.delete(cacheKey);\n return false;\n }\n\n return true;\n }\n\n /**\n * Get TTL for key\n */\n async ttl(key: string): Promise<number> {\n await Promise.resolve();\n const cacheKey = this.buildKey(key);\n const cached = this.cache.get(cacheKey);\n\n if (!cached) {\n return -2; // Key doesn't exist\n }\n\n const remaining = Math.floor((cached.expiresAt - Date.now()) / 1000);\n\n if (remaining <= 0) {\n this.cache.delete(cacheKey);\n return -2;\n }\n\n return remaining;\n }\n\n /**\n * Update TTL for key\n */\n async expire(key: string, ttl: number): Promise<boolean> {\n await Promise.resolve();\n const cacheKey = this.buildKey(key);\n const cached = this.cache.get(cacheKey);\n\n if (!cached) {\n return false;\n }\n\n cached.expiresAt = Date.now() + ttl * 1000;\n cached.entry.ttl = ttl;\n\n return true;\n }\n\n /**\n * Get multiple values (batch operation)\n */\n async mget<T>(keys: string[], _options?: BatchCacheOptions): Promise<Map<string, T>> {\n const result = new Map<string, T>();\n\n for (const key of keys) {\n const value = await this.get<T>(key);\n if (value !== null) {\n result.set(key, value);\n }\n }\n\n return result;\n }\n\n /**\n * Set multiple values (batch operation)\n */\n async mset<T>(entries: Map<string, T>, options?: BatchCacheOptions): Promise<boolean> {\n for (const [key, value] of entries) {\n await this.set(key, value, options);\n }\n\n return true;\n }\n\n /**\n * Delete multiple keys (batch operation)\n */\n async mdel(keys: string[]): Promise<number> {\n let deleted = 0;\n\n for (const key of keys) {\n const result = await this.delete(key);\n if (result) {\n deleted++;\n }\n }\n\n return deleted;\n }\n\n /**\n * Match key against pattern (supports * wildcard)\n */\n private matchPattern(key: string, pattern: string): boolean {\n // Simple wildcard matching without regex\n if (!pattern.includes('*')) {\n return key === pattern;\n }\n\n const parts = pattern.split('*');\n let position = 0;\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n if (!part || part === '') continue;\n\n const index = key.indexOf(part, position);\n if (index === -1) return false;\n if (i === 0 && index !== 0) return false;\n position = index + part.length;\n }\n\n const lastPart = parts[parts.length - 1];\n return !lastPart || lastPart === '' || key.endsWith(lastPart);\n }\n\n /**\n * Clear keys by pattern\n */\n async clearPattern(pattern: string): Promise<number> {\n await Promise.resolve();\n const searchPattern = this.buildKey(pattern);\n let deleted = 0;\n\n for (const key of this.cache.keys()) {\n if (this.matchPattern(key, searchPattern)) {\n this.cache.delete(key);\n deleted++;\n }\n }\n\n if (this.enableLogging) {\n logger.debug(`[MemoryCacheProvider:${this.namespace}] Pattern cleared`, {\n pattern,\n deleted,\n });\n }\n\n return deleted;\n }\n\n /**\n * Get keys by pattern\n */\n async keys(options: PatternOptions): Promise<PatternResult> {\n await Promise.resolve();\n const searchPattern = this.buildKey(options.pattern);\n const matchedKeys: string[] = [];\n const prefix = `${this.namespace}:`;\n\n for (const key of this.cache.keys()) {\n if (this.matchPattern(key, searchPattern)) {\n matchedKeys.push(key.replace(prefix, ''));\n }\n }\n\n // Apply limit if specified\n const limitedKeys = options.limit ? matchedKeys.slice(0, options.limit) : matchedKeys;\n\n return {\n keys: limitedKeys,\n nextCursor: null,\n totalCount: matchedKeys.length,\n };\n }\n\n /**\n * Clear all keys in namespace\n */\n async clear(): Promise<boolean> {\n await Promise.resolve();\n const prefix = `${this.namespace}:`;\n let cleared = 0;\n\n for (const key of Array.from(this.cache.keys())) {\n if (key.startsWith(prefix)) {\n this.cache.delete(key);\n cleared++;\n }\n }\n\n if (this.enableLogging) {\n logger.info(`[MemoryCacheProvider:${this.namespace}] Cleared ${cleared} keys`);\n }\n\n return true;\n }\n\n /**\n * Increment numeric value\n */\n async increment(key: string, amount: number = 1): Promise<number> {\n const current = await this.get<number>(key);\n const newValue = (current || 0) + amount;\n await this.set(key, newValue);\n return newValue;\n }\n\n /**\n * Decrement numeric value\n */\n async decrement(key: string, amount: number = 1): Promise<number> {\n const current = await this.get<number>(key);\n const newValue = (current || 0) - amount;\n await this.set(key, newValue);\n return newValue;\n }\n\n /**\n * Get or set value\n */\n async getOrSet<T>(key: string, fetcher: () => Promise<T>, options?: CacheOptions): Promise<T> {\n const cached = await this.get<T>(key, options);\n if (cached !== null) {\n return cached;\n }\n\n const value = await fetcher();\n await this.set(key, value, options);\n\n return value;\n }\n\n /**\n * Invalidate by tags\n */\n async invalidateTags(tags: string[]): Promise<number> {\n let totalDeleted = 0;\n\n for (const tag of tags) {\n const pattern = `*:tag:${tag}:*`;\n const deleted = await this.clearPattern(pattern);\n totalDeleted += deleted;\n }\n\n return totalDeleted;\n }\n}\n","/**\n * Valkey Glide Cache Provider\n *\n * Implements ICacheProvider using @valkey/valkey-glide client.\n * Provides a modern, high-performance Valkey/Redis client implementation.\n *\n * @module cache/implementations/valkey/ValkeyGlideProvider\n * @category Cache\n *\n * @example\n * ```typescript\n * import { ValkeyGlideProvider } from '@burdenoff/be-sdk/cache';\n *\n * const cache = new ValkeyGlideProvider({\n * type: 'valkey-glide',\n * url: 'valkey://localhost:6379',\n * defaultTTL: 300,\n * }, 'my-namespace');\n *\n * await cache.connect();\n * await cache.set('key', 'value', { ttl: 60 });\n * const value = await cache.get('key');\n * ```\n */\n\nimport { logger } from '../../../logger/index.js';\nimport { registerDisposable, unregisterDisposable, type ShutdownDisposable } from '../../../lifecycle/index.js';\nimport type { ICacheProvider } from '../../interfaces/ICacheProvider.js';\nimport type {\n BatchCacheOptions,\n CacheEntry,\n CacheOptions,\n CacheStatistics,\n CacheHealthCheckResult,\n PatternOptions,\n PatternResult,\n} from '../../types/index.js';\n\n/**\n * Valkey Glide configuration\n */\nexport interface ValkeyGlideConfig {\n /**\n * Cache provider type\n */\n type: 'valkey-glide';\n\n /**\n * Valkey server URL\n * @example 'valkey://localhost:6379' or 'redis://localhost:6379'\n */\n url?: string;\n\n /**\n * Valkey host\n * @default 'localhost'\n */\n host?: string;\n\n /**\n * Valkey port\n * @default 6379\n */\n port?: number;\n\n /**\n * Password for authentication\n */\n password?: string;\n\n /**\n * Username for authentication\n */\n username?: string;\n\n /**\n * Database number\n * @default 0\n */\n db?: number;\n\n /**\n * Key prefix for all keys\n * @default 'cache'\n */\n keyPrefix?: string;\n\n /**\n * Default TTL in seconds\n * @default 300 (5 minutes)\n */\n defaultTTL?: number;\n\n /**\n * Enable logging\n * @default NODE_ENV === 'development'\n */\n enableLogging?: boolean;\n\n /**\n * Connection timeout in milliseconds\n * @default 10000\n */\n connectionTimeout?: number;\n\n /**\n * Max reconnect attempts\n * @default -1 (infinite)\n */\n maxReconnectAttempts?: number;\n\n /**\n * Reconnect time wait in milliseconds\n * @default 2000\n */\n reconnectTimeWait?: number;\n\n /**\n * Client name for identification\n */\n name?: string;\n\n /**\n * Use TLS for connection\n * @default false\n */\n useTLS?: boolean;\n\n /**\n * Force Valkey Cluster mode. If unset, the provider auto-detects cluster mode.\n */\n cluster?: boolean;\n\n /**\n * Seed nodes for Valkey Cluster topology discovery.\n */\n clusterNodes?: Array<{ host: string; port: number }>;\n}\n\n/**\n * Valkey Glide TimeUnit enum (mirror of @valkey/valkey-glide's TimeUnit).\n * We re-declare locally so this file has zero compile-time dependency on the\n * peer-dep types — the enum values are ABI-stable Redis expiry tokens\n * (\"EX\", \"PX\", \"EXAT\", \"PXAT\", \"KEEPTTL\") so the runtime client accepts them\n * regardless of whether the peer package is installed.\n */\nconst enum GlideTimeUnit {\n Seconds = 'EX',\n Milliseconds = 'PX',\n UnixSeconds = 'EXAT',\n UnixMilliseconds = 'PXAT',\n KeepExisting = 'KEEPTTL',\n}\n\n/**\n * Valkey Glide set()-options shape. The real client takes\n * `{ expiry: { type: TimeUnit, count: number } }` and silently ignores the\n * legacy `{ EX: number }` shape — that silent drop caused rate-limit\n * counters to persist forever (no TTL on the key). See\n * node_modules/@valkey/valkey-glide/build-ts/BaseClient.d.ts `set(...)`.\n */\ninterface GlideSetOptions {\n expiry?: 'persist' | { type: GlideTimeUnit; count: number; duration?: number };\n conditionalSet?: 'onlyIfExists' | 'onlyIfDoesNotExist' | 'onlyIfEqual';\n returnOldValue?: boolean;\n}\n\ninterface GlideAddress {\n host: string;\n port: number;\n}\n\ninterface GlideCreateClientConfig {\n addresses: GlideAddress[];\n useTLS?: boolean;\n credentials?: { password?: string; username?: string };\n clientName?: string;\n readFrom?: string;\n databaseId?: number;\n // Per-command ceiling (incl. any reconnection during the request). See\n // REQUEST_TIMEOUT_MS — this is what stops a mid-reconnect command from hanging.\n requestTimeout?: number;\n // Reconnection backoff for an established client that drops its connection.\n // GLIDE waits `factor * (exponentBase ^ N)` between attempt N, then keeps\n // using the last (capped) delay. Without this GLIDE uses its built-in\n // default; wiring it lets a transient drop recover smoothly instead of\n // churning. See @valkey/valkey-glide BaseClientConfiguration.connectionBackoff.\n connectionBackoff?: { numberOfRetries: number; factor: number; exponentBase: number };\n periodicChecks?: { duration_in_sec?: number };\n // GLIDE 2.x reads `connectionTimeout` HERE (AdvancedBaseClientConfiguration),\n // not at the top level — a top-level value is silently dropped.\n advancedConfiguration?: { refreshTopologyFromInitialNodes?: boolean; connectionTimeout?: number };\n}\n\n/**\n * Read a positive-integer override from the environment, falling back to a\n * default. Every timeout below is env-tunable so an operator can adapt to a\n * given Redis/network profile without a code change.\n */\nfunction readPositiveIntEnv(name: string, fallback: number): number {\n const raw = process.env[name];\n if (!raw) return fallback;\n const parsed = parseInt(raw, 10);\n return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;\n}\n\n/**\n * After a failed connect, fail subsequent ops fast (treated as a cache miss by\n * callers) for this cooldown instead of issuing a fresh `createClient` on every\n * operation. Per-operation connect hammering is what turned a brief Redis\n * hiccup into thousands of \"Failed to connect\" log lines/min and a\n * self-amplifying reconnect storm across the platform.\n */\nconst CONNECT_RETRY_COOLDOWN_MS = readPositiveIntEnv('VALKEY_CONNECT_RETRY_COOLDOWN_MS', 8000);\n\n/**\n * Hard wall-clock budget for a single request-path connect attempt. GLIDE's\n * `connectionBackoff` (exponential, seeded by `reconnectTimeWait`) means a\n * `createClient` against an unreachable/misconfigured endpoint can stay pending\n * for tens of seconds. Because cache ops run inline in resolvers — often while a\n * Postgres connection is checked out — a connect that hangs that long starves\n * the event loop and saturates the pg pool, surfacing as 10s \"connect timeout\"\n * 500s. Bounding the attempt turns any connect stall into a fast cache-miss +\n * an armed circuit-breaker instead of a request-blocking hang.\n *\n * Sized to sit just above {@link CONNECTION_TIMEOUT_MS} so GLIDE's own (cleaner,\n * typed) connect timeout normally fires first, with this race as the backstop\n * for when GLIDE ignores it. The previous 2.5s default was too tight for a cold\n * TLS handshake to Azure Managed Redis, so a healthy-but-slow connect tripped\n * the circuit-breaker and produced the observed connect flapping.\n */\nconst CONNECT_ATTEMPT_TIMEOUT_MS = readPositiveIntEnv('VALKEY_CONNECT_ATTEMPT_TIMEOUT_MS', 4500);\n\n/**\n * GLIDE's own per-connect budget (initial connect AND every internal\n * reconnect), passed via `advancedConfiguration.connectionTimeout`. In GLIDE 2.x\n * a TOP-LEVEL `connectionTimeout` is silently ignored — it must live under\n * `advancedConfiguration` — so connects previously ran with GLIDE's built-in\n * default. Overridable per instance via config.connectionTimeout.\n */\nconst CONNECTION_TIMEOUT_MS = readPositiveIntEnv('VALKEY_CONNECTION_TIMEOUT_MS', 4000);\n\n/**\n * GLIDE `requestTimeout`: the hard ceiling for a single command, which per\n * GLIDE's docs \"encompasses sending the request, awaiting a response, AND any\n * required reconnection or retries.\" This is the fix for the cache HANG: without\n * it, a `get`/`set` issued while the socket is dropping or GLIDE is mid-reconnect\n * waits GLIDE's effectively-unbounded default, blocking the calling resolver\n * (and any pg connection it holds) — which upstream surfaced as RBAC checks\n * exceeding the gateway's 5s budget and fail-closing. With it, such a command\n * throws TimeoutError fast and the provider returns a cache miss.\n */\nconst REQUEST_TIMEOUT_MS = readPositiveIntEnv('VALKEY_REQUEST_TIMEOUT_MS', 2000);\n\n/**\n * Consecutive connection-level operation failures after which the provider tears\n * its client down and lets the next op build a fresh one. GLIDE reconnects a\n * dropped socket on its own indefinitely, but a client whose TLS/keepalive state\n * wedges (observed against Azure Managed Redis: connect flaps, redis-cli to the\n * same endpoint is healthy) would otherwise stay broken until the process\n * restarts — which is why a pod restart used to be the only fix. A brand-new\n * client means a new socket + TLS session, which recovers where the wedged one\n * could not.\n */\nconst MAX_CONSECUTIVE_OP_FAILURES = readPositiveIntEnv('VALKEY_MAX_CONSECUTIVE_OP_FAILURES', 3);\n\n/**\n * Minimum interval between logged cooldown fast-fails, per provider instance.\n * While the connect circuit-breaker is armed, EVERY cache op fast-fails with\n * the same \"connect in cooldown\" error; logging each one at error level buried\n * prod logs in dozens of identical stack traces per second (observed on\n * global-tenant-svc) and drowned out the one log line that matters — the\n * underlying connect failure. Real (non-cooldown) op errors are never throttled.\n */\nconst COOLDOWN_LOG_INTERVAL_MS = readPositiveIntEnv('VALKEY_COOLDOWN_LOG_INTERVAL_MS', 30000);\n\n/**\n * True when an error indicates the connection (not the command) is the problem,\n * so it should count toward the client-teardown threshold. Matches GLIDE's error\n * class names (ClosingError / ConnectionError / TimeoutError) and, as a fallback\n * for wrapped/plain errors, connection-shaped messages. Deliberately excludes\n * the provider's own \"connect in cooldown\" fast-fail (that is the breaker\n * already working, not a fresh failure) and the connect-budget message.\n */\nfunction isConnectionLevelError(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n const name = error.name;\n if (name === 'ClosingError' || name === 'ConnectionError' || name === 'TimeoutError') {\n return true;\n }\n const message = error.message.toLowerCase();\n if (message.includes('cooldown') || message.includes('budget')) {\n return false;\n }\n return /connection|closing|closed|timed out|timeout|disconnect|socket|econnreset|broken pipe|not connected/.test(\n message\n );\n}\n\ninterface GlideClientFactory {\n createClient(config: GlideCreateClientConfig): Promise<ValkeyGlideClient>;\n}\n\ninterface ClusterScanCursorLike {\n getCursor(): string;\n isFinished(): boolean;\n}\n\ntype ClusterScanCursorConstructor = new (newCursor?: string | undefined | null) => ClusterScanCursorLike;\n\ninterface ValkeyGlideModule {\n GlideClient?: GlideClientFactory;\n GlideClusterClient?: GlideClientFactory;\n ClusterScanCursor?: ClusterScanCursorConstructor;\n default?: GlideClientFactory;\n}\n\n/**\n * Valkey Glide client interface (minimal type definition)\n * This is a simplified interface - full types come from @valkey/valkey-glide\n */\ninterface ValkeyGlideClient {\n get(key: string): Promise<string | null>;\n set(key: string, value: string, options?: GlideSetOptions): Promise<string | null>;\n del(keys: string[]): Promise<number>;\n exists(keys: string[]): Promise<number>;\n ttl(key: string): Promise<number>;\n expire(key: string, seconds: number): Promise<boolean>;\n mget(keys: string[]): Promise<(string | null)[]>;\n mset(keyValuePairs: Record<string, string>): Promise<string | null>;\n keys?(pattern: string): Promise<string[]>;\n incrBy(key: string, amount: number): Promise<number>;\n decrBy(key: string, amount: number): Promise<number>;\n ping(): Promise<string>;\n info(section?: string): Promise<string>;\n dbsize(): Promise<number>;\n close(): Promise<void>;\n}\n\ninterface ValkeyGlideClusterClient extends ValkeyGlideClient {\n scan(\n cursor: ClusterScanCursorLike,\n options?: { match?: string; count?: number }\n ): Promise<[ClusterScanCursorLike, string[]]>;\n}\n\n/**\n * Valkey Glide cache provider implementation\n */\nexport class ValkeyGlideProvider implements ICacheProvider, ShutdownDisposable {\n private client: ValkeyGlideClient | null = null;\n private clusterScanCursor: ClusterScanCursorConstructor | null = null;\n private clientIsCluster = false;\n private connected = false;\n // Single in-flight connect promise so concurrent first-time `get/set` calls\n // share one connect attempt instead of racing into N parallel `createClient`\n // invocations. Reset to `null` after connect resolves/rejects so the next\n // call after an explicit disconnect() (or a connect failure) can retry.\n private connectPromise: Promise<void> | null = null;\n // Timestamp (ms) of the last failed connect attempt; 0 when the last attempt\n // succeeded. Drives the connect circuit-breaker in ensureConnected().\n private lastConnectFailureAt = 0;\n // Count of consecutive connection-level operation failures on an already-\n // \"connected\" client, tracked across every command (any success resets it,\n // any op's connection error increments it). When it reaches\n // MAX_CONSECUTIVE_OP_FAILURES the wedged client is torn down so the next op\n // rebuilds a fresh one instead of reusing a socket GLIDE's internal reconnect\n // cannot recover. See noteOpError().\n private consecutiveOpFailures = 0;\n // Timestamp (ms) of the last logged cooldown fast-fail; throttles the\n // per-op \"connect in cooldown\" logging to once per COOLDOWN_LOG_INTERVAL_MS.\n private lastCooldownLogAt = 0;\n private readonly config: ValkeyGlideConfig;\n // Mutable: when a URL like `…/4` lands on Azure Managed Redis we fold the\n // DB index into the namespace at connect time to preserve per-service\n // isolation on the forced-DB-0 connection. Appended exactly once across the\n // instance's lifetime, guarded by `dbNamespaceSuffixApplied` (connect() can\n // run repeatedly now that the self-heal path rebuilds the client).\n private namespace: string;\n // Set once the Azure DB-index `:db{N}` suffix has been folded into\n // `namespace`, so reconnects do not re-append it.\n private dbNamespaceSuffixApplied = false;\n private readonly defaultTTL: number;\n private readonly enableLogging: boolean;\n\n // Statistics\n private stats = {\n hits: 0,\n misses: 0,\n sets: 0,\n deletes: 0,\n errors: 0,\n };\n\n constructor(config: ValkeyGlideConfig, namespace: string = 'default') {\n this.config = config;\n this.namespace = namespace;\n this.defaultTTL = config.defaultTTL || 300;\n this.enableLogging = config.enableLogging ?? process.env['NODE_ENV'] === 'development';\n }\n\n private async serverReportsCluster(client: ValkeyGlideClient): Promise<boolean> {\n try {\n const info = await client.info('cluster');\n return /(?:^|\\n)cluster_enabled:1(?:\\r?\\n|$)/.test(info);\n } catch {\n return false;\n }\n }\n\n private async scanClusterKeys(pattern: string): Promise<string[]> {\n if (!this.client || !this.clientIsCluster || !this.clusterScanCursor) {\n return [];\n }\n\n const clusterClient = this.client as ValkeyGlideClusterClient;\n let cursor: ClusterScanCursorLike = new this.clusterScanCursor();\n const keys: string[] = [];\n\n do {\n const [nextCursor, batch] = await clusterClient.scan(cursor, { match: pattern, count: 1000 });\n keys.push(...batch);\n cursor = nextCursor;\n } while (!cursor.isFinished());\n\n return keys;\n }\n\n private async getKeys(pattern: string): Promise<string[]> {\n const client = await this.ensureConnected();\n\n if (this.clientIsCluster) {\n return this.scanClusterKeys(pattern);\n }\n\n if (!client.keys) {\n throw new Error('KEYS command is not available on this Valkey client');\n }\n\n return client.keys(pattern);\n }\n\n /**\n * Connect to Valkey server using @valkey/valkey-glide\n */\n /**\n * Lazy-connect helper used by every public operation so callers can just do\n * `const cache = createCache('x'); await cache.set(...)` without an explicit\n * `await cache.connect()`. Multiple concurrent ops share the same in-flight\n * connect promise.\n */\n private async ensureConnected(): Promise<ValkeyGlideClient> {\n if (!(this.connected && this.client)) {\n // Circuit-breaker: if a recent connect attempt failed and none is\n // currently in flight, fail fast (the caller treats the rejection as a\n // cache miss and falls through to its source) instead of starting yet\n // another createClient. This caps connect attempts at ~1 per cooldown\n // per instance during an outage rather than one per cache operation.\n if (!this.connectPromise && this.lastConnectFailureAt > 0) {\n const sinceFailureMs = Date.now() - this.lastConnectFailureAt;\n if (sinceFailureMs < CONNECT_RETRY_COOLDOWN_MS) {\n throw new Error('Valkey connect in cooldown after a recent failure');\n }\n }\n if (!this.connectPromise) {\n this.connectPromise = this.connect().finally(() => {\n this.connectPromise = null;\n });\n }\n await this.connectPromise;\n }\n if (!this.client) {\n throw new Error('Valkey client connect failed');\n }\n return this.client;\n }\n\n /**\n * Race a GLIDE `createClient` promise against {@link CONNECT_ATTEMPT_TIMEOUT_MS}\n * so a stalled connect can never block the calling resolver (and the pg\n * connection it may be holding) longer than the budget. On timeout the\n * underlying connect is abandoned but not left dangling: if it later resolves\n * we close the orphaned client to avoid leaking a socket. The thrown error\n * propagates to `connect()`'s catch, which arms the circuit-breaker so\n * subsequent ops fast-fail (cache miss) during the cooldown.\n */\n private async withConnectBudget<C extends { close: () => Promise<void> }>(pending: Promise<C>): Promise<C> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<never>((_, reject) => {\n timer = setTimeout(\n () => reject(new Error(`Valkey connect exceeded ${String(CONNECT_ATTEMPT_TIMEOUT_MS)}ms budget`)),\n CONNECT_ATTEMPT_TIMEOUT_MS\n );\n });\n try {\n return await Promise.race([pending, timeout]);\n } catch (error) {\n // Abandon the slow connect, but reclaim it if it eventually succeeds so a\n // late-arriving socket does not leak.\n void pending.then(\n (client) => {\n void client.close().catch(() => undefined);\n },\n () => undefined\n );\n throw error;\n } finally {\n if (timer) {\n clearTimeout(timer);\n }\n }\n }\n\n async connect(): Promise<void> {\n if (this.connected && this.client) {\n return;\n }\n\n try {\n // Dynamically import @valkey/valkey-glide\n let glideModule: ValkeyGlideModule;\n try {\n glideModule = (await import('@valkey/valkey-glide')) as ValkeyGlideModule;\n } catch (importError) {\n // Make a missing driver unmistakable. This exact condition silently\n // disabled the cache across the ENTIRE prod fleet: valkey-glide used to\n // be an optional peer dependency no service actually declared, so\n // production images shipped without it, this import threw a bundler\n // ResolveMessage (not an Error — it serialized to an EMPTY log line),\n // and every cache op degraded to a DB hit behind a generic \"Failed to\n // connect\". valkey-glide is now a regular dependency of the SDK, so\n // hitting this indicates a broken install/bundle.\n throw new Error(\n `@valkey/valkey-glide is not installed — the Valkey cache is DISABLED and every ` +\n `cache op degrades to a miss (import failed: ${importError instanceof Error ? importError.message : String(importError)})`\n );\n }\n const GlideClient = glideModule.GlideClient || glideModule.default;\n const GlideClusterClient = glideModule.GlideClusterClient;\n this.clusterScanCursor = glideModule.ClusterScanCursor ?? null;\n\n if (!GlideClient) {\n throw new Error('Valkey GLIDE standalone client is unavailable');\n }\n\n // Parse URL if provided\n let host = this.config.host || 'localhost';\n let port = this.config.port || 6379;\n let password = this.config.password;\n let username = this.config.username;\n // Auto-detect TLS from URL scheme. `rediss://` (Redis-over-TLS) and\n // `valkeys://` are the canonical \"TLS-required\" schemes — Azure Managed\n // Redis on port 10000 only accepts TLS, so missing this flag manifests as\n // a connect timeout (plaintext handshake on a TLS-only socket).\n let useTLSFromUrl: boolean | undefined;\n let databaseFromUrl: number | undefined;\n\n if (this.config.url) {\n const rawUrl = this.config.url;\n useTLSFromUrl = /^(rediss|valkeys):\\/\\//i.test(rawUrl);\n const url = new URL(rawUrl.replace(/^valkey:\\/\\//i, 'redis://').replace(/^valkeys:\\/\\//i, 'rediss://'));\n host = url.hostname;\n port = parseInt(url.port || '6379', 10);\n if (!password && url.password) {\n try {\n password = decodeURIComponent(url.password);\n } catch {\n password = url.password;\n }\n }\n if (!username && url.username) {\n try {\n username = decodeURIComponent(url.username);\n } catch {\n username = url.username;\n }\n }\n // Pull DB number from path (e.g. `/0`, `/1`).\n //\n // Azure Managed Redis Balanced/B0 only exposes DB 0. If the URL pins\n // a non-zero DB index, glide's CLIENT SETINFO + SELECT chain fails\n // on every connect with `ERR DB index is out of range`. Detect the\n // Azure hostname and force DB 0 — also fold the original DB # into\n // the per-instance namespace so two services pointed at the same\n // managed-redis with different `/N` paths stay isolated by key.\n const dbMatch = /^\\/(\\d+)$/.exec(url.pathname);\n if (dbMatch && dbMatch[1]) {\n databaseFromUrl = parseInt(dbMatch[1], 10);\n const isAzureManagedRedis = /\\.redis\\.azure\\.net$/i.test(host);\n if (isAzureManagedRedis && databaseFromUrl > 0) {\n // Suffix the namespace with `:db{N}` so two services that used to\n // rely on the URL's DB index for isolation keep getting disjoint\n // keysets on the shared DB 0. Idempotent: connect() now runs more\n // than once per instance (the self-heal teardown rebuilds the\n // client), so guard against re-appending `:db{N}` on every\n // reconnect — otherwise the namespace grows to `ns:db4:db4:db4…`\n // and each rebuild silently orphans the previous keyset.\n if (!this.dbNamespaceSuffixApplied) {\n logger.warn(\n `[ValkeyGlideProvider] Azure Managed Redis only supports DB 0; ` +\n `ignoring /${String(databaseFromUrl)} in URL and folding it into namespace.`\n );\n this.namespace = `${this.namespace}:db${String(databaseFromUrl)}`;\n this.dbNamespaceSuffixApplied = true;\n }\n databaseFromUrl = 0;\n }\n }\n }\n\n const addresses = this.config.clusterNodes?.length ? this.config.clusterNodes : [{ host, port }];\n const baseClientConfig: GlideCreateClientConfig = {\n addresses,\n useTLS: this.config.useTLS ?? useTLSFromUrl,\n credentials:\n password || username\n ? {\n password,\n username,\n }\n : undefined,\n clientName: this.config.name || `valkey-glide-${this.namespace}`,\n databaseId: this.config.db ?? databaseFromUrl,\n // Bound every command (incl. reconnection during the request) so a\n // dropped/reconnecting socket fails fast to a cache miss instead of\n // hanging the calling resolver. THE fix for the \"glide hangs\" failure.\n requestTimeout: REQUEST_TIMEOUT_MS,\n // Honour the configured reconnect tuning. Previously\n // maxReconnectAttempts/reconnectTimeWait were read into config but never\n // handed to GLIDE, so the client used its built-in default backoff. A\n // dropped connection now recovers on an exponential schedule seeded by\n // reconnectTimeWait, capped after numberOfRetries attempts.\n connectionBackoff: {\n numberOfRetries:\n this.config.maxReconnectAttempts && this.config.maxReconnectAttempts > 0\n ? this.config.maxReconnectAttempts\n : 5,\n factor: this.config.reconnectTimeWait ?? 1000,\n exponentBase: 2,\n },\n readFrom: 'primary',\n // GLIDE 2.x reads connectionTimeout from advancedConfiguration; a\n // top-level value is ignored. Bounds the initial connect and every\n // internal reconnect.\n advancedConfiguration: { connectionTimeout: this.config.connectionTimeout ?? CONNECTION_TIMEOUT_MS },\n };\n\n if (this.config.cluster === true) {\n if (!GlideClusterClient) {\n throw new Error('Valkey GLIDE cluster client is unavailable');\n }\n this.client = await this.withConnectBudget(\n GlideClusterClient.createClient({\n ...baseClientConfig,\n periodicChecks: { duration_in_sec: 30 },\n advancedConfiguration: { ...baseClientConfig.advancedConfiguration, refreshTopologyFromInitialNodes: true },\n })\n );\n this.clientIsCluster = true;\n } else {\n const standaloneClient = await this.withConnectBudget(GlideClient.createClient(baseClientConfig));\n if (this.config.cluster !== false && (await this.serverReportsCluster(standaloneClient))) {\n if (!GlideClusterClient) {\n throw new Error('Valkey server is clustered but GLIDE cluster client is unavailable');\n }\n await standaloneClient.close();\n this.client = await this.withConnectBudget(\n GlideClusterClient.createClient({\n ...baseClientConfig,\n periodicChecks: { duration_in_sec: 30 },\n advancedConfiguration: {\n ...baseClientConfig.advancedConfiguration,\n refreshTopologyFromInitialNodes: true,\n },\n })\n );\n this.clientIsCluster = true;\n } else {\n this.client = standaloneClient;\n this.clientIsCluster = false;\n }\n }\n\n this.connected = true;\n // Clear the circuit-breaker — a healthy connect re-opens the gate.\n this.lastConnectFailureAt = 0;\n // A fresh, working client — reset the op-failure teardown counter.\n this.consecutiveOpFailures = 0;\n // Close this client on graceful shutdown (unregistered again in disconnect()).\n registerDisposable(this);\n\n if (this.enableLogging) {\n logger.info(`[ValkeyGlideProvider:${this.namespace}] Connected to Valkey`, {\n host,\n port,\n cluster: this.clientIsCluster,\n });\n }\n } catch (error) {\n this.stats.errors++;\n // Arm the circuit-breaker so the next ops fail fast instead of each\n // re-attempting connect (which produced the platform-wide connect storm).\n this.lastConnectFailureAt = Date.now();\n // Normalize non-Error throwables (e.g. a bundler ResolveMessage) so the\n // root cause is never an empty log line.\n const normalized = error instanceof Error ? error : new Error(String(error));\n logger.error(`[ValkeyGlideProvider:${this.namespace}] Failed to connect:`, normalized);\n throw normalized;\n }\n }\n\n /**\n * Disconnect from Valkey server\n */\n /** Label for the graceful-shutdown registry. */\n get shutdownName(): string {\n return `valkey-cache:${this.namespace}`;\n }\n\n /** Close the client on graceful shutdown. */\n dispose(): Promise<void> {\n return this.disconnect();\n }\n\n async disconnect(): Promise<void> {\n unregisterDisposable(this);\n if (this.client) {\n await this.client.close();\n this.client = null;\n this.clientIsCluster = false;\n this.connected = false;\n // Clear the circuit-breaker so an explicit disconnect→connect cycle\n // (e.g. a deliberate reconnect) is never blocked by a stale cooldown.\n this.lastConnectFailureAt = 0;\n\n if (this.enableLogging) {\n logger.info(`[ValkeyGlideProvider:${this.namespace}] Disconnected`);\n }\n }\n }\n\n /**\n * A command completed — the connection is proven alive, so clear the\n * teardown counter. Called from every command's success path.\n */\n private recordOpSuccess(): void {\n if (this.consecutiveOpFailures !== 0) {\n this.consecutiveOpFailures = 0;\n }\n }\n\n /**\n * Record an operation error and, if the client looks wedged (enough\n * consecutive connection-level failures), tear it down so the next op builds a\n * fresh one. Non-connection errors (bad command, serialization) are ignored so\n * they never trip the teardown.\n */\n private noteOpError(error: unknown): void {\n if (!isConnectionLevelError(error)) {\n return;\n }\n this.consecutiveOpFailures += 1;\n if (this.consecutiveOpFailures >= MAX_CONSECUTIVE_OP_FAILURES) {\n this.resetClientForReconnect();\n }\n }\n\n /**\n * Log an operation error, throttling the breaker's own cooldown fast-fail.\n * While the connect circuit-breaker is armed every op fails with the same\n * \"connect in cooldown\" error; those are expected (the op has already\n * degraded to a cache miss) and are summarized at most once per\n * COOLDOWN_LOG_INTERVAL_MS instead of stack-traced per call. Any other error\n * logs at error level unthrottled.\n */\n private logOpError(what: string, error: unknown): void {\n if (error instanceof Error && error.message.includes('connect in cooldown')) {\n const now = Date.now();\n if (now - this.lastCooldownLogAt < COOLDOWN_LOG_INTERVAL_MS) {\n return;\n }\n this.lastCooldownLogAt = now;\n logger.warn(\n `[ValkeyGlideProvider:${this.namespace}] Valkey unavailable (connect circuit-breaker armed); ` +\n `ops are degrading to cache misses. Further cooldown fast-fails are suppressed for ` +\n `${String(COOLDOWN_LOG_INTERVAL_MS)}ms — see the preceding \"Failed to connect\" log for the root cause.`\n );\n return;\n }\n logger.error(`[ValkeyGlideProvider:${this.namespace}] ${what}:`, error);\n }\n\n /**\n * Drop the current client so the next ensureConnected() creates a new one.\n * Arms the connect circuit-breaker so ops fast-fail (cache miss) during the\n * cooldown rather than racing a fresh connect on every call, and closes the\n * dead client in the background so its socket is not leaked.\n */\n private resetClientForReconnect(): void {\n const dead = this.client;\n this.client = null;\n this.connected = false;\n this.consecutiveOpFailures = 0;\n this.lastConnectFailureAt = Date.now();\n logger.warn(\n `[ValkeyGlideProvider:${this.namespace}] Tearing down wedged client after ` +\n `${String(MAX_CONSECUTIVE_OP_FAILURES)} consecutive connection failures; rebuilding on next op`\n );\n if (dead) {\n void dead.close().catch(() => undefined);\n }\n }\n\n /**\n * Check if connected\n */\n isConnected(): boolean {\n return this.connected && this.client !== null;\n }\n\n /**\n * Health check\n */\n async healthCheck(): Promise<CacheHealthCheckResult> {\n const startTime = Date.now();\n\n try {\n if (!this.client) {\n return {\n status: 'unhealthy',\n timestamp: new Date().toISOString(),\n connected: false,\n error: 'Not connected',\n };\n }\n\n const result = await this.client.ping();\n const latencyMs = Date.now() - startTime;\n\n if (result === 'PONG') {\n return {\n status: 'healthy',\n timestamp: new Date().toISOString(),\n connected: true,\n latencyMs,\n };\n }\n\n return {\n status: 'unhealthy',\n timestamp: new Date().toISOString(),\n connected: false,\n error: 'Unexpected ping response',\n };\n } catch (error) {\n return {\n status: 'unhealthy',\n timestamp: new Date().toISOString(),\n connected: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n latencyMs: Date.now() - startTime,\n };\n }\n }\n\n /**\n * Get statistics\n */\n async getStatistics(): Promise<CacheStatistics> {\n const totalOperations = this.stats.hits + this.stats.misses;\n const hitRate = totalOperations > 0 ? this.stats.hits / totalOperations : 0;\n\n try {\n const client = await this.ensureConnected();\n\n const info = await client.info('memory');\n const memoryRegex = /used_memory:(\\d+)/;\n const memoryMatch = memoryRegex.exec(info);\n const memoryUsed = memoryMatch && memoryMatch[1] ? parseInt(memoryMatch[1], 10) : undefined;\n\n const keyCount = await client.dbsize();\n this.recordOpSuccess();\n\n return {\n hits: this.stats.hits,\n misses: this.stats.misses,\n hitRate,\n keyCount,\n memoryUsed,\n totalOperations,\n details: {\n sets: this.stats.sets,\n deletes: this.stats.deletes,\n errors: this.stats.errors,\n },\n };\n } catch (error) {\n this.noteOpError(error);\n this.logOpError('Failed to get statistics', error);\n return {\n hits: this.stats.hits,\n misses: this.stats.misses,\n hitRate,\n totalOperations,\n details: {\n sets: this.stats.sets,\n deletes: this.stats.deletes,\n errors: this.stats.errors,\n },\n };\n }\n }\n\n /**\n * Build cache key with namespace\n */\n private buildKey(key: string): string {\n return `${this.namespace}:${key}`;\n }\n\n /**\n * Get value from cache\n */\n async get<T>(key: string, _options?: CacheOptions): Promise<T | null> {\n try {\n const client = await this.ensureConnected();\n\n const cacheKey = this.buildKey(key);\n const value = await client.get(cacheKey);\n this.recordOpSuccess();\n\n if (value === null) {\n this.stats.misses++;\n if (this.enableLogging) {\n logger.debug(`[ValkeyGlideProvider:${this.namespace}] Cache miss`, { key });\n }\n return null;\n }\n\n this.stats.hits++;\n if (this.enableLogging) {\n logger.debug(`[ValkeyGlideProvider:${this.namespace}] Cache hit`, { key });\n }\n\n const entry: CacheEntry<T> = JSON.parse(value);\n return entry.data;\n } catch (error) {\n this.stats.errors++;\n this.noteOpError(error);\n this.logOpError('Error getting cache key', error);\n return null;\n }\n }\n\n /**\n * Set value in cache\n */\n async set<T>(key: string, value: T, options?: CacheOptions): Promise<boolean> {\n try {\n const client = await this.ensureConnected();\n\n const cacheKey = this.buildKey(key);\n const ttlSeconds = options?.ttl || this.defaultTTL;\n\n const entry: CacheEntry<T> = {\n data: value,\n timestamp: Date.now(),\n ttl: ttlSeconds,\n metadata: options?.metadata,\n };\n\n // Valkey Glide expects `{ expiry: { type: TimeUnit.Seconds, count } }`\n // and silently ignores the legacy `{ EX }` shape — passing EX meant\n // keys were written with no TTL, which wedged rate-limit counters\n // (e.g. APP_TOKEN_GENERATION bucket filling up permanently).\n await client.set(cacheKey, JSON.stringify(entry), {\n expiry: { type: GlideTimeUnit.Seconds, count: ttlSeconds },\n });\n this.recordOpSuccess();\n\n this.stats.sets++;\n if (this.enableLogging) {\n logger.debug(`[ValkeyGlideProvider:${this.namespace}] Cache set`, {\n key,\n ttl: ttlSeconds,\n });\n }\n\n return true;\n } catch (error) {\n this.stats.errors++;\n this.noteOpError(error);\n this.logOpError('Error setting cache key', error);\n return false;\n }\n }\n\n /**\n * Delete value from cache\n */\n async delete(key: string): Promise<boolean> {\n try {\n const client = await this.ensureConnected();\n\n const cacheKey = this.buildKey(key);\n const result = await client.del([cacheKey]);\n this.recordOpSuccess();\n\n this.stats.deletes++;\n if (this.enableLogging) {\n logger.debug(`[ValkeyGlideProvider:${this.namespace}] Cache delete`, {\n key,\n deleted: result > 0,\n });\n }\n\n return result > 0;\n } catch (error) {\n this.stats.errors++;\n this.noteOpError(error);\n this.logOpError('Error deleting cache key', error);\n return false;\n }\n }\n\n /**\n * Check if key exists\n */\n async has(key: string): Promise<boolean> {\n try {\n const client = await this.ensureConnected();\n\n const cacheKey = this.buildKey(key);\n const exists = await client.exists([cacheKey]);\n this.recordOpSuccess();\n return exists === 1;\n } catch (error) {\n this.stats.errors++;\n this.noteOpError(error);\n this.logOpError('Error checking cache key', error);\n return false;\n }\n }\n\n /**\n * Get TTL for key\n */\n async ttl(key: string): Promise<number> {\n try {\n const client = await this.ensureConnected();\n\n const cacheKey = this.buildKey(key);\n const result = await client.ttl(cacheKey);\n this.recordOpSuccess();\n return result;\n } catch (error) {\n this.stats.errors++;\n this.noteOpError(error);\n this.logOpError('Error getting TTL', error);\n return -2;\n }\n }\n\n /**\n * Update TTL for key\n */\n async expire(key: string, ttl: number): Promise<boolean> {\n try {\n const client = await this.ensureConnected();\n\n const cacheKey = this.buildKey(key);\n const result = await client.expire(cacheKey, ttl);\n this.recordOpSuccess();\n return result;\n } catch (error) {\n this.stats.errors++;\n this.noteOpError(error);\n this.logOpError('Error setting expiration', error);\n return false;\n }\n }\n\n /**\n * Get multiple values (batch operation)\n */\n async mget<T>(keys: string[], _options?: BatchCacheOptions): Promise<Map<string, T>> {\n const result = new Map<string, T>();\n\n if (keys.length === 0) {\n return result;\n }\n\n try {\n const client = await this.ensureConnected();\n\n const cacheKeys = keys.map((key) => this.buildKey(key));\n const values = await client.mget(cacheKeys);\n this.recordOpSuccess();\n\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i];\n if (!key) continue;\n\n if (values[i] !== null) {\n const entry: CacheEntry<T> = JSON.parse(values[i]!);\n result.set(key, entry.data);\n this.stats.hits++;\n } else {\n this.stats.misses++;\n }\n }\n\n if (this.enableLogging) {\n logger.debug(`[ValkeyGlideProvider:${this.namespace}] Batch get`, {\n requested: keys.length,\n found: result.size,\n });\n }\n\n return result;\n } catch (error) {\n this.stats.errors++;\n this.noteOpError(error);\n this.logOpError('Error in batch get', error);\n return result;\n }\n }\n\n /**\n * Set multiple values (batch operation)\n */\n async mset<T>(entries: Map<string, T>, options?: BatchCacheOptions): Promise<boolean> {\n if (entries.size === 0) {\n return true;\n }\n\n try {\n const client = await this.ensureConnected();\n\n const ttlSeconds = options?.ttl || this.defaultTTL;\n const keyValuePairs: Record<string, string> = {};\n\n for (const [key, value] of entries) {\n const cacheKey = this.buildKey(key);\n const entry: CacheEntry<T> = {\n data: value,\n timestamp: Date.now(),\n ttl: ttlSeconds,\n metadata: options?.metadata,\n };\n keyValuePairs[cacheKey] = JSON.stringify(entry);\n }\n\n await client.mset(keyValuePairs);\n this.recordOpSuccess();\n\n // Set TTL for each key (mset doesn't support TTL directly)\n for (const cacheKey of Object.keys(keyValuePairs)) {\n await client.expire(cacheKey, ttlSeconds);\n }\n\n this.stats.sets += entries.size;\n if (this.enableLogging) {\n logger.debug(`[ValkeyGlideProvider:${this.namespace}] Batch set`, {\n count: entries.size,\n ttl: ttlSeconds,\n });\n }\n\n return true;\n } catch (error) {\n this.stats.errors++;\n this.noteOpError(error);\n this.logOpError('Error in batch set', error);\n return false;\n }\n }\n\n /**\n * Delete multiple keys (batch operation)\n */\n async mdel(keys: string[]): Promise<number> {\n if (keys.length === 0) {\n return 0;\n }\n\n try {\n const client = await this.ensureConnected();\n\n const cacheKeys = keys.map((key) => this.buildKey(key));\n const result = await client.del(cacheKeys);\n this.recordOpSuccess();\n\n this.stats.deletes += result;\n if (this.enableLogging) {\n logger.debug(`[ValkeyGlideProvider:${this.namespace}] Batch delete`, {\n requested: keys.length,\n deleted: result,\n });\n }\n\n return result;\n } catch (error) {\n this.stats.errors++;\n this.noteOpError(error);\n this.logOpError('Error in batch delete', error);\n return 0;\n }\n }\n\n /**\n * Clear keys by pattern\n */\n async clearPattern(pattern: string): Promise<number> {\n try {\n const client = await this.ensureConnected();\n\n const searchPattern = this.buildKey(pattern);\n const keys = await this.getKeys(searchPattern);\n this.recordOpSuccess();\n\n if (keys.length === 0) {\n return 0;\n }\n\n const result = await client.del(keys);\n\n if (this.enableLogging) {\n logger.debug(`[ValkeyGlideProvider:${this.namespace}] Pattern cleared`, {\n pattern,\n deleted: result,\n });\n }\n\n return result;\n } catch (error) {\n this.stats.errors++;\n this.noteOpError(error);\n this.logOpError('Error clearing pattern', error);\n return 0;\n }\n }\n\n /**\n * Get keys by pattern\n */\n async keys(options: PatternOptions): Promise<PatternResult> {\n try {\n await this.ensureConnected();\n\n const searchPattern = this.buildKey(options.pattern);\n const keys = await this.getKeys(searchPattern);\n this.recordOpSuccess();\n\n const prefix = `${this.namespace}:`;\n const cleanKeys = keys.map((key) => key.replace(prefix, ''));\n\n const limitedKeys = options.limit ? cleanKeys.slice(0, options.limit) : cleanKeys;\n\n return {\n keys: limitedKeys,\n nextCursor: null,\n totalCount: cleanKeys.length,\n };\n } catch (error) {\n this.stats.errors++;\n this.noteOpError(error);\n this.logOpError('Error getting keys', error);\n return {\n keys: [],\n nextCursor: null,\n totalCount: 0,\n };\n }\n }\n\n /**\n * Clear all keys in namespace\n */\n async clear(): Promise<boolean> {\n try {\n const client = await this.ensureConnected();\n\n const pattern = this.buildKey('*');\n const keys = await this.getKeys(pattern);\n this.recordOpSuccess();\n\n if (keys.length > 0) {\n await client.del(keys);\n if (this.enableLogging) {\n logger.info(`[ValkeyGlideProvider:${this.namespace}] Cleared ${keys.length} keys`);\n }\n }\n\n return true;\n } catch (error) {\n this.stats.errors++;\n this.noteOpError(error);\n this.logOpError('Error clearing cache', error);\n return false;\n }\n }\n\n /**\n * Increment numeric value\n */\n async increment(key: string, amount: number = 1): Promise<number> {\n try {\n const client = await this.ensureConnected();\n\n const cacheKey = this.buildKey(key);\n const result = await client.incrBy(cacheKey, amount);\n this.recordOpSuccess();\n return result;\n } catch (error) {\n this.stats.errors++;\n this.noteOpError(error);\n this.logOpError('Error incrementing', error);\n throw error;\n }\n }\n\n /**\n * Decrement numeric value\n */\n async decrement(key: string, amount: number = 1): Promise<number> {\n try {\n const client = await this.ensureConnected();\n\n const cacheKey = this.buildKey(key);\n const result = await client.decrBy(cacheKey, amount);\n this.recordOpSuccess();\n return result;\n } catch (error) {\n this.stats.errors++;\n this.noteOpError(error);\n this.logOpError('Error decrementing', error);\n throw error;\n }\n }\n\n /**\n * Get or set value\n */\n async getOrSet<T>(key: string, fetcher: () => Promise<T>, options?: CacheOptions): Promise<T> {\n const cached = await this.get<T>(key, options);\n if (cached !== null) {\n return cached;\n }\n\n const value = await fetcher();\n await this.set(key, value, options);\n\n return value;\n }\n\n /**\n * Invalidate by tags\n */\n async invalidateTags(tags: string[]): Promise<number> {\n try {\n let totalDeleted = 0;\n\n for (const tag of tags) {\n const pattern = `*:tag:${tag}:*`;\n const deleted = await this.clearPattern(pattern);\n totalDeleted += deleted;\n }\n\n if (this.enableLogging) {\n logger.debug(`[ValkeyGlideProvider:${this.namespace}] Tags invalidated`, {\n tags,\n deleted: totalDeleted,\n });\n }\n\n return totalDeleted;\n } catch (error) {\n this.stats.errors++;\n this.logOpError('Error invalidating tags', error);\n return 0;\n }\n }\n}\n","/**\n * Cache Factory\n * Creates appropriate cache provider instances based on configuration\n */\nimport { logger } from '../../logger/index.js';\nimport type { ServiceLayer } from '../../types/layer.js';\nimport { DEFAULT_LAYER_RESOURCES } from '../../types/layer.js';\n\nimport { MemoryCacheProvider } from '../implementations/memory/MemoryCacheProvider.js';\nimport { ValkeyGlideProvider } from '../implementations/valkey/ValkeyGlideProvider.js';\nimport type { ICacheProvider } from '../interfaces/ICacheProvider.js';\nimport type { CacheConfig, CacheProviderTypeLiteral } from '../types/config.js';\n\n/**\n * Factory for creating cache instances\n */\nexport class CacheFactory {\n private static instances: Map<string, ICacheProvider> = new Map();\n\n private static parseBoolean(value: string | undefined): boolean | undefined {\n if (value === undefined) return undefined;\n const normalized = value.trim().toLowerCase();\n if (['1', 'true', 'yes', 'on'].includes(normalized)) return true;\n if (['0', 'false', 'no', 'off'].includes(normalized)) return false;\n return undefined;\n }\n\n private static parseClusterNodes(value: string | undefined): Array<{ host: string; port: number }> | undefined {\n if (!value) return undefined;\n\n const nodes = value\n .split(',')\n .map((node) => node.trim())\n .filter(Boolean)\n .map((node) => {\n const [host, rawPort] = node\n .replace(/^redis:\\/\\//, '')\n .replace(/^valkey:\\/\\//, '')\n .split(':');\n if (!host) return null;\n return { host, port: rawPort ? parseInt(rawPort, 10) : 6379 };\n })\n .filter((node): node is { host: string; port: number } => node !== null && Number.isFinite(node.port));\n\n return nodes.length > 0 ? nodes : undefined;\n }\n\n /**\n * Resolve port from multiple environment variable sources\n * @param layerPort - Layer-specific port environment variable value\n * @param genericPort - Generic port environment variable value\n * @param defaultPort - Default port if none provided\n * @returns Resolved port number\n */\n private static resolvePort(\n layerPort: string | undefined,\n genericPort: string | undefined,\n defaultPort: number = 6379\n ): number {\n if (layerPort) {\n return parseInt(layerPort, 10);\n }\n if (genericPort) {\n return parseInt(genericPort, 10);\n }\n return defaultPort;\n }\n\n /**\n * Create a cache provider based on configuration\n */\n static createCache(config: CacheConfig, namespace: string = 'default'): ICacheProvider {\n logger.info('[CacheFactory] Creating cache provider', {\n type: config.type,\n namespace,\n });\n\n switch (config.type) {\n case 'valkey':\n case 'redis': // Backwards compatibility - redis maps to valkey\n return new ValkeyGlideProvider(\n {\n type: 'valkey-glide',\n url: config.url,\n host: config.host,\n port: config.port,\n password: config.password,\n username: config.username,\n db: config.db,\n keyPrefix: config.keyPrefix,\n defaultTTL: config.defaultTTL,\n enableLogging: config.enableLogging,\n maxReconnectAttempts: config.maxReconnectAttempts,\n reconnectTimeWait: config.reconnectTimeWait,\n connectionTimeout: config.connectionTimeout,\n name: config.name,\n useTLS: config.tls?.enabled,\n cluster: config.cluster,\n clusterNodes: config.clusterNodes,\n },\n namespace\n );\n\n case 'memory':\n return new MemoryCacheProvider(config, namespace);\n\n // Future implementations can be added here\n // case 'memcached':\n // return new MemcachedCacheProvider(config as MemcachedCacheConfig, namespace);\n\n default:\n throw new Error(`Unsupported cache provider type: ${config.type}`);\n }\n }\n\n /**\n * Create a cache from environment variables\n */\n static createCacheFromEnv(namespace: string = 'default'): ICacheProvider {\n const envType = process.env['CACHE_PROVIDER_TYPE'] as CacheProviderTypeLiteral | undefined;\n // Default to valkey, but treat 'redis' as 'valkey' for backwards compatibility\n const type = envType === 'memory' ? 'memory' : 'valkey';\n\n const config: CacheConfig =\n type === 'valkey'\n ? {\n type: 'valkey',\n // Fall back to REDIS_URL when VALKEY_URL is unset/empty. Prod KV\n // provisioning populates the canonical REDIS_URL (a `rediss://…`\n // Azure Managed Redis string) for every service but has, for some\n // services, left VALKEY_URL blank. Without this fallback the cache\n // silently connected to localhost:6379 — a connect that hangs on\n // GLIDE's reconnect backoff long enough to starve the event loop and\n // saturate the pg pool (10s \"connect timeout\" 500s). This mirrors the\n // precedence already used by gateway/security/valkey.ts.\n url: process.env['VALKEY_URL'] || process.env['REDIS_URL'],\n host: process.env['VALKEY_HOST'] || 'localhost',\n port: process.env['VALKEY_PORT'] ? parseInt(process.env['VALKEY_PORT'], 10) : 6379,\n password: process.env['VALKEY_PASSWORD'],\n db: process.env['VALKEY_DB'] ? parseInt(process.env['VALKEY_DB'], 10) : 0,\n username: process.env['VALKEY_USERNAME'],\n keyPrefix: process.env['CACHE_KEY_PREFIX'] || 'cache',\n defaultTTL: process.env['CACHE_DEFAULT_TTL'] ? parseInt(process.env['CACHE_DEFAULT_TTL'], 10) : 300,\n enableLogging: process.env['CACHE_ENABLE_LOGGING'] === 'true',\n maxReconnectAttempts: process.env['VALKEY_MAX_RECONNECT_ATTEMPTS']\n ? parseInt(process.env['VALKEY_MAX_RECONNECT_ATTEMPTS'], 10)\n : -1,\n reconnectTimeWait: process.env['VALKEY_RECONNECT_TIME_WAIT']\n ? parseInt(process.env['VALKEY_RECONNECT_TIME_WAIT'], 10)\n : 2000,\n connectionTimeout: process.env['VALKEY_CONNECTION_TIMEOUT']\n ? parseInt(process.env['VALKEY_CONNECTION_TIMEOUT'], 10)\n : 10000,\n name: process.env['CACHE_CLIENT_NAME'] || `cache-${namespace}`,\n cluster: CacheFactory.parseBoolean(process.env['VALKEY_CLUSTER'] || process.env['CACHE_CLUSTER']),\n clusterNodes: CacheFactory.parseClusterNodes(\n process.env['VALKEY_CLUSTER_NODES'] || process.env['CACHE_CLUSTER_NODES']\n ),\n }\n : {\n type: 'memory',\n maxSize: process.env['CACHE_MAX_SIZE'] ? parseInt(process.env['CACHE_MAX_SIZE'], 10) : 1000,\n defaultTTL: process.env['CACHE_DEFAULT_TTL'] ? parseInt(process.env['CACHE_DEFAULT_TTL'], 10) : 300,\n enableLogging: process.env['CACHE_ENABLE_LOGGING'] === 'true',\n keyPrefix: process.env['CACHE_KEY_PREFIX'] || 'cache',\n };\n\n return CacheFactory.createCache(config, namespace);\n }\n\n /**\n * Get or create a singleton cache instance for a namespace\n */\n static getInstance(namespace: string = 'default', config?: CacheConfig): ICacheProvider {\n const instanceKey = `${config?.type || 'default'}:${namespace}`;\n\n if (!CacheFactory.instances.has(instanceKey)) {\n const cache = config ? CacheFactory.createCache(config, namespace) : CacheFactory.createCacheFromEnv(namespace);\n CacheFactory.instances.set(instanceKey, cache);\n }\n\n return CacheFactory.instances.get(instanceKey)!;\n }\n\n /**\n * Close a specific cache instance\n */\n static async closeInstance(namespace: string): Promise<void> {\n for (const [key, cache] of CacheFactory.instances.entries()) {\n if (key.endsWith(`:${namespace}`)) {\n await cache.disconnect();\n CacheFactory.instances.delete(key);\n logger.info('[CacheFactory] Closed cache instance', { namespace });\n }\n }\n }\n\n /**\n * Close all cache instances\n * Call this during application shutdown\n */\n static async closeAll(): Promise<void> {\n const promises = Array.from(CacheFactory.instances.values()).map(async (cache) => cache.disconnect());\n await Promise.all(promises);\n CacheFactory.instances.clear();\n logger.info('[CacheFactory] All cache instances closed');\n }\n\n // ========================================================================\n // Layer-Aware Factory Methods\n // ========================================================================\n\n /**\n * Create a cache provider for a specific layer\n *\n * @param layer - Service layer ('wspace' or 'global')\n * @param serviceName - Service name for identification\n * @param namespace - Cache namespace (default: 'default')\n * @returns Cache provider configured for the layer\n *\n * @example\n * ```typescript\n * const cache = CacheFactory.createCacheForLayer('wspace', 'wspace-tags-svc');\n * await cache.connect();\n * await cache.set('key', { data: 'value' });\n * ```\n */\n static createCacheForLayer(layer: ServiceLayer, serviceName: string, namespace: string = 'default'): ICacheProvider {\n const envPrefix = layer.toUpperCase();\n const defaults = DEFAULT_LAYER_RESOURCES[layer];\n\n // Build Valkey URL from layer-specific or generic env vars. REDIS_URL is the\n // canonical platform-wide cache/event URL (see gateway/security/valkey.ts);\n // fall back to it before the per-layer default so a service with REDIS_URL\n // set but VALKEY_URL blank still reaches the real Azure Managed Redis.\n const url =\n process.env[`${envPrefix}_VALKEY_URL`] ||\n process.env['VALKEY_URL'] ||\n process.env['REDIS_URL'] ||\n defaults.valkeyUrl;\n\n // Resolve port with fallback chain\n const resolvedPort = CacheFactory.resolvePort(process.env[`${envPrefix}_VALKEY_PORT`], process.env['VALKEY_PORT']);\n\n const config: CacheConfig = {\n type: 'valkey',\n url,\n host: process.env[`${envPrefix}_VALKEY_HOST`] || process.env['VALKEY_HOST'] || 'localhost',\n port: resolvedPort,\n password: process.env['VALKEY_PASSWORD'],\n db: process.env['VALKEY_DB'] ? parseInt(process.env['VALKEY_DB'], 10) : 0,\n username: process.env['VALKEY_USERNAME'],\n keyPrefix: process.env['CACHE_KEY_PREFIX'] || `${layer}-cache`,\n defaultTTL: process.env['CACHE_DEFAULT_TTL'] ? parseInt(process.env['CACHE_DEFAULT_TTL'], 10) : 300,\n enableLogging: process.env['CACHE_ENABLE_LOGGING'] === 'true',\n maxReconnectAttempts: process.env['VALKEY_MAX_RECONNECT_ATTEMPTS']\n ? parseInt(process.env['VALKEY_MAX_RECONNECT_ATTEMPTS'], 10)\n : -1,\n reconnectTimeWait: process.env['VALKEY_RECONNECT_TIME_WAIT']\n ? parseInt(process.env['VALKEY_RECONNECT_TIME_WAIT'], 10)\n : 2000,\n connectionTimeout: process.env['VALKEY_CONNECTION_TIMEOUT']\n ? parseInt(process.env['VALKEY_CONNECTION_TIMEOUT'], 10)\n : 10000,\n name: serviceName,\n cluster: CacheFactory.parseBoolean(\n process.env[`${envPrefix}_VALKEY_CLUSTER`] || process.env['VALKEY_CLUSTER'] || process.env['CACHE_CLUSTER']\n ),\n clusterNodes: CacheFactory.parseClusterNodes(\n process.env[`${envPrefix}_VALKEY_CLUSTER_NODES`] ||\n process.env['VALKEY_CLUSTER_NODES'] ||\n process.env['CACHE_CLUSTER_NODES']\n ),\n };\n\n logger.info('[CacheFactory] Creating layer cache', {\n layer,\n serviceName,\n namespace,\n url: config.url,\n });\n\n return CacheFactory.createCache(config, namespace);\n }\n\n /**\n * Get or create a singleton cache instance for a layer\n *\n * @param layer - Service layer ('wspace' or 'global')\n * @param serviceName - Service name for identification\n * @param namespace - Cache namespace (default: 'default')\n * @returns Singleton cache provider for the layer\n */\n static getInstanceForLayer(layer: ServiceLayer, serviceName: string, namespace: string = 'default'): ICacheProvider {\n const instanceKey = `${layer}:${serviceName}:${namespace}`;\n\n if (!CacheFactory.instances.has(instanceKey)) {\n const cache = CacheFactory.createCacheForLayer(layer, serviceName, namespace);\n CacheFactory.instances.set(instanceKey, cache);\n }\n\n return CacheFactory.instances.get(instanceKey)!;\n }\n}\n","/**\n * Cache Configuration Types\n */\n\n/**\n * Cache provider type enum\n */\nexport enum CacheProviderType {\n VALKEY = 'valkey',\n MEMORY = 'memory',\n MEMCACHED = 'memcached',\n}\n\n/**\n * Cache provider type string literal\n */\nexport type CacheProviderTypeLiteral = 'valkey' | 'redis' | 'memory' | 'memcached';\n\n/**\n * Base configuration for cache\n */\nexport interface BaseCacheConfig {\n /** Cache provider type */\n type: CacheProviderType | CacheProviderTypeLiteral;\n /** Connection URL or host */\n url?: string;\n /** Cache key prefix */\n keyPrefix?: string;\n /** Default TTL in seconds */\n defaultTTL?: number;\n /** Enable debug logging */\n enableLogging?: boolean;\n /** Maximum reconnection attempts (-1 for infinite) */\n maxReconnectAttempts?: number;\n /** Time to wait between reconnection attempts (ms) */\n reconnectTimeWait?: number;\n /** Connection timeout (ms) */\n connectionTimeout?: number;\n /** Client name/identifier */\n name?: string;\n}\n\n/**\n * Valkey-specific configuration\n * Compatible with Redis protocol (Valkey is a Redis fork)\n */\nexport interface ValkeyCacheConfig extends BaseCacheConfig {\n type: CacheProviderType.VALKEY | 'valkey' | 'redis';\n /** Valkey host */\n host?: string;\n /** Valkey port */\n port?: number;\n /** Valkey password */\n password?: string;\n /** Valkey database number */\n db?: number;\n /** Valkey username */\n username?: string;\n /** Use TLS for connection (simple boolean flag) */\n useTLS?: boolean;\n /** TLS configuration (detailed) */\n tls?: {\n enabled: boolean;\n cert?: string;\n key?: string;\n ca?: string;\n };\n /** Enable cluster mode */\n cluster?: boolean;\n /** Cluster nodes (if cluster mode enabled) */\n clusterNodes?: Array<{ host: string; port: number }>;\n /** Sentinel configuration */\n sentinel?: {\n enabled: boolean;\n sentinels: Array<{ host: string; port: number }>;\n name: string;\n };\n}\n\n/**\n * Memory cache-specific configuration\n */\nexport interface MemoryCacheConfig extends BaseCacheConfig {\n type: CacheProviderType.MEMORY | 'memory';\n /** Maximum number of items in cache */\n maxSize?: number;\n /** Eviction strategy */\n evictionStrategy?: 'lru' | 'lfu' | 'fifo';\n}\n\n/**\n * Memcached-specific configuration\n */\nexport interface MemcachedCacheConfig extends BaseCacheConfig {\n type: CacheProviderType.MEMCACHED | 'memcached';\n /** Memcached servers */\n servers?: string[];\n}\n\n/**\n * Union type for all cache configurations\n */\nexport type CacheConfig = ValkeyCacheConfig | MemoryCacheConfig | MemcachedCacheConfig;\n\n/**\n * Health check result\n */\nexport interface CacheHealthCheckResult {\n /** Overall health status */\n status: 'healthy' | 'unhealthy' | 'degraded';\n /** Timestamp of health check */\n timestamp: string;\n /** Connection status */\n connected?: boolean;\n /** Latency in milliseconds */\n latencyMs?: number;\n /** Additional details */\n details?: Record<string, unknown>;\n /** Error message if unhealthy */\n error?: string;\n}\n\n/**\n * Cache statistics\n */\nexport interface CacheStatistics {\n /** Total cache hits */\n hits?: number;\n /** Total cache misses */\n misses?: number;\n /** Hit rate (0-1) */\n hitRate?: number;\n /** Total number of keys */\n keyCount?: number;\n /** Total memory used (bytes) */\n memoryUsed?: number;\n /** Total cache operations */\n totalOperations?: number;\n /** Average operation time (ms) */\n avgOperationTimeMs?: number;\n /** Last activity timestamp */\n lastActivity?: string | null;\n /** Custom metrics */\n details?: Record<string, unknown>;\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/prisma/workspace-extension.ts"],"names":["workspaceContextStore","AsyncLocalStorage","fallbackContext","setWorkspaceContext","context","enterWith","getWorkspaceContext","getStore","withWorkspaceContext","fn","run","withWorkspaceContextSync","defaultConfig","enabled","enableReadIsolation","enableDeleteIsolation","enableUpdateWhereIsolation","populateContextJson","populateCreatedBy","populateUpdatedBy","populateTenantId","excludeModels","excludeModelsFromReadIsolation","strictMode","allowedUnguardedOperations","debug","enableApplicationNameTagging","enableRlsGucTagging","hasField","data","field","injectCreateFields","wsCtx","config","injected","workspaceId","tenantId","actorId","onBehalfOf","contextJson","buildContextJsonFromWorkspaceContext","injectUpdateFields","injectWhereClause","where","organizationId","projectId","appId","Object","keys","length","undefined","injectWhereWorkspaceId","ctx","stripSkipFlag","args","cleaned","isExcludedFromReadIsolation","model","includes","enforceStrictMode","operation","opKey","Error","taggedContexts","WeakSet","maybeTagConnection","rawPrisma","has","add","safeSvc","process","env","replace","safeWs","tag","$executeRawUnsafe","delete","rlsTaggedContexts","maybeSetRlsGuc","addWorkspaceExtension","baseClient","fullConfig","logger","info","prismaClient","$extends","query","$allModels","create","_skipWorkspaceInjection","injectedData","injectedKeys","filter","k","join","createMany","dataArray","Array","isArray","map","item","createManyAndReturn","update","injectedWhere","injectedDataKeys","whereChanged","updateMany","upsert","injectedCreate","injectedUpdate","findMany","findFirst","findFirstOrThrow","findUnique","findUniqueOrThrow","count","aggregate","groupBy","deleteMany"],"mappings":"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","file":"chunk-MXLCLLCI.js","sourcesContent":["/**\n * Prisma Workspace Extension\n *\n * Automatically injects workspaceId into ALL Prisma operations using\n * request-scoped context from AsyncLocalStorage:\n *\n * **Write operations** (create, createMany, update, upsert):\n * - Auto-populates `workspaceId`, `tenantId`, `createdBy`, `updatedBy`, `context` JSON\n *\n * **Read operations** (findMany, findFirst, findUnique, count, aggregate, groupBy):\n * - Auto-injects `workspaceId` into the `where` clause for workspace isolation\n *\n * **Delete operations** (delete, deleteMany):\n * - Auto-injects `workspaceId` into the `where` clause to prevent cross-workspace deletion\n *\n * **Update where clause** (update, updateMany):\n * - Auto-injects `workspaceId` into the `where` clause to prevent cross-workspace updates\n *\n * **How it works:**\n * 1. The GraphQL server's buildContext extracts workspaceId from x-workspace-id header\n * 2. The workspace context store (AsyncLocalStorage) holds the current request's workspace info\n * 3. This Prisma extension intercepts ALL operations and auto-injects workspaceId\n *\n * **What gets auto-populated on writes:**\n * - `workspaceId` field (String or String?) - set from context if not explicitly provided\n * - `context` field (Json) - merged with workspace/actor info if not explicitly provided\n * - `tenantId` field (String or String?) - set from context if not explicitly provided\n * - `createdBy` / `updatedBy` fields - set from actor context if not explicitly provided\n *\n * **What gets auto-injected on reads/updates/deletes:**\n * - `workspaceId` in the `where` clause - ensures queries only access data within the workspace\n *\n * **Opt-out:**\n * - Explicitly providing `workspaceId` in the where/data will override auto-injection\n * - Pass `_skipWorkspaceInjection: true` in the query args to skip entirely\n * - Set `enableReadIsolation: false` in config to disable read-side injection only\n * - Add model names to `excludeModels` to skip specific models\n *\n * @module prisma/workspace-extension\n * @category Database\n */\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport { logger } from '../logger/index.js';\nimport type { InputJsonValue } from './context.js';\n\n// ============================================================================\n// Workspace Context Store (AsyncLocalStorage)\n// ============================================================================\n\n/**\n * Workspace context for the current request scope\n */\nexport interface WorkspaceContext {\n /** Workspace ID (from x-workspace-id header) */\n workspaceId?: string;\n /** Tenant ID (from x-tenant-id header or derived from workspace) */\n tenantId?: string;\n /** Actor ID (user/service/app performing the operation) */\n actorId?: string;\n /** Actor type (user, app, service, super_admin) */\n actorType?: string;\n /** Organization ID */\n organizationId?: string;\n /** Project ID */\n projectId?: string;\n /** App ID */\n appId?: string;\n /** On behalf of actor ID (for consent-based delegation) */\n onBehalfOf?: string;\n}\n\n/**\n * AsyncLocalStorage for workspace context\n * This is separate from the SDK's general ContextManager to allow\n * fine-grained control over workspace-specific context propagation.\n */\nconst workspaceContextStore = new AsyncLocalStorage<WorkspaceContext>();\n\n/**\n * Fallback context for environments where AsyncLocalStorage.enterWith()\n * doesn't propagate across async boundaries (e.g., Bun + GraphQL Yoga).\n *\n * IMPORTANT: This is NOT request-isolated — it's a module-level singleton.\n * It works for single-request-at-a-time scenarios but could race under\n * concurrent requests. The ALS is the primary mechanism; this is a fallback.\n */\nlet fallbackContext: WorkspaceContext | undefined;\n\n/**\n * Set workspace context for the current async scope.\n * Call this in your GraphQL context builder or middleware.\n *\n * Uses AsyncLocalStorage.enterWith() as the primary mechanism,\n * with a module-level fallback for runtimes where enterWith()\n * doesn't propagate through all async chains (e.g., Bun).\n *\n * @param context - The workspace context for this request\n *\n * @example\n * ```typescript\n * // In your server's buildContext:\n * import { setWorkspaceContext } from '@burdenoff/be-sdk/prisma';\n *\n * buildContext: async (defaultContext) => {\n * setWorkspaceContext({\n * workspaceId: defaultContext.workspace?.id,\n * tenantId: defaultContext.tenant?.id,\n * actorId: defaultContext.actor?.id,\n * actorType: defaultContext.actor?.type,\n * organizationId: defaultContext.organization?.id,\n * });\n * return defaultContext;\n * }\n * ```\n */\nexport function setWorkspaceContext(context: WorkspaceContext): void {\n workspaceContextStore.enterWith(context);\n fallbackContext = context;\n}\n\n/**\n * Get the current workspace context from AsyncLocalStorage.\n * Falls back to module-level context if ALS returns undefined\n * (can happen in Bun where enterWith() doesn't propagate through\n * some async chains like GraphQL Yoga's execution pipeline).\n *\n * @returns The current workspace context, or undefined if not set\n */\nexport function getWorkspaceContext(): WorkspaceContext | undefined {\n return workspaceContextStore.getStore() ?? fallbackContext;\n}\n\n/**\n * Run a function with a specific workspace context.\n * The context is isolated to this execution and its children.\n *\n * @param context - The workspace context\n * @param fn - The function to run\n * @returns The result of the function\n *\n * @example\n * ```typescript\n * const result = await withWorkspaceContext(\n * { workspaceId: 'ws-123', actorId: 'user-456' },\n * async () => {\n * // All Prisma operations in here will auto-inject workspaceId\n * return await prisma.tag.create({ data: { name: 'test' } });\n * }\n * );\n * ```\n */\nexport async function withWorkspaceContext<T>(context: WorkspaceContext, fn: () => Promise<T>): Promise<T> {\n return workspaceContextStore.run(context, fn);\n}\n\n/**\n * Run a synchronous function with a specific workspace context.\n */\nexport function withWorkspaceContextSync<T>(context: WorkspaceContext, fn: () => T): T {\n return workspaceContextStore.run(context, fn);\n}\n\n// ============================================================================\n// Extension Configuration\n// ============================================================================\n\n/**\n * Configuration for the workspace extension\n */\nexport interface WorkspaceExtensionConfig {\n /**\n * Enable automatic workspaceId injection on create/update\n * @default true\n */\n enabled?: boolean;\n\n /**\n * Enable automatic workspaceId injection on read operations\n * (findMany, findFirst, findUnique, findFirstOrThrow, findUniqueOrThrow,\n * count, aggregate, groupBy)\n *\n * When enabled, every read query automatically includes `workspaceId`\n * in the `where` clause, preventing cross-workspace data leakage.\n *\n * @default true\n */\n enableReadIsolation?: boolean;\n\n /**\n * Enable automatic workspaceId injection on delete operations\n * (delete, deleteMany)\n *\n * When enabled, every delete operation automatically includes `workspaceId`\n * in the `where` clause, preventing cross-workspace deletion.\n *\n * @default true\n */\n enableDeleteIsolation?: boolean;\n\n /**\n * Enable automatic workspaceId injection into update/updateMany `where` clauses.\n *\n * When enabled, update operations automatically include `workspaceId`\n * in the `where` clause in addition to the `data` injection,\n * preventing cross-workspace updates.\n *\n * @default true\n */\n enableUpdateWhereIsolation?: boolean;\n\n /**\n * Automatically populate the `context` JSON field with workspace/actor info\n * @default true\n */\n populateContextJson?: boolean;\n\n /**\n * Automatically populate `createdBy` field on create operations\n * @default true\n */\n populateCreatedBy?: boolean;\n\n /**\n * Automatically populate `updatedBy` field on update operations\n * @default true\n */\n populateUpdatedBy?: boolean;\n\n /**\n * Automatically populate `tenantId` field from context\n * @default false (tenantId is typically derived from workspaceId at the DB level)\n */\n populateTenantId?: boolean;\n\n /**\n * Models to exclude from auto-injection (both reads and writes).\n * Use this for models that intentionally don't have workspaceId.\n *\n * Common exclusions: system tables, infra tables, global reference data.\n *\n * @default []\n */\n excludeModels?: string[];\n\n /**\n * Models to exclude from read isolation only.\n * These models will still get write-side injection (workspaceId on create)\n * but reads will NOT have workspaceId auto-injected into `where`.\n *\n * Use this for child/join tables where workspace scoping is inherited\n * through parent relations, or for models queried by ID that don't\n * have a workspaceId column.\n *\n * @default []\n */\n excludeModelsFromReadIsolation?: string[];\n\n /**\n * When true, throws an error if workspaceId is missing from context\n * for any non-excluded model operation. This prevents silent\n * workspace-unscoped queries that could leak data across workspaces.\n *\n * When false, operations without workspace context proceed without\n * workspaceId injection (legacy behavior).\n *\n * @default true\n */\n strictMode?: boolean;\n\n /**\n * Operations that are allowed without workspace context even in strict mode.\n * Use `Model.operation` format (e.g., `['Workspace.create', 'RevokedToken.findMany']`).\n *\n * Valid operation names: create, createMany, createManyAndReturn, update, updateMany,\n * upsert, findMany, findFirst, findFirstOrThrow, findUnique, findUniqueOrThrow,\n * count, aggregate, groupBy, delete, deleteMany.\n *\n * @default []\n */\n allowedUnguardedOperations?: string[];\n\n /**\n * Log injection events (useful for debugging)\n * @default false\n */\n debug?: boolean;\n\n /**\n * Tag the PostgreSQL connection with workspace attribution for pg_stat_activity visibility.\n *\n * When enabled, the first DB operation per workspace context sets:\n * `application_name = 'svc=<SERVICE_NAME>;ws=<workspaceId>'`\n *\n * This makes workspace-level query attribution visible in pg_stat_activity,\n * pg_locks, auto_explain, and monitoring tools without any schema changes.\n * Subsequent operations in the same request are deduplicated via WeakSet,\n * costing ~0 overhead after the first round-trip per request context.\n *\n * NOTE: This is a session-level SET so attribution may drift across ops\n * that reuse the same pooled connection from different requests. Use for\n * aggregate observability, not per-query forensics.\n *\n * @default false\n */\n enableApplicationNameTagging?: boolean;\n\n /**\n * Set the `app.workspace_id` GUC for Row Level Security enforcement.\n *\n * When enabled, the first DB operation per workspace context executes:\n * `SET app.workspace_id = '<workspaceId>'`\n *\n * RLS policies using `current_setting('app.workspace_id', true)` then filter\n * rows by workspace, providing a defense-in-depth backstop to the application-\n * layer workspaceId injection in the WHERE clause.\n *\n * Pair with migrations that run per table:\n * `ALTER TABLE t ENABLE ROW LEVEL SECURITY;`\n * `CREATE POLICY ws_isolation ON t\n * USING (workspace_id = current_setting('app.workspace_id', true))\n * WITH CHECK (workspace_id = current_setting('app.workspace_id', true));`\n *\n * Fail-closed semantics: if the GUC is unset (NULL from missing_ok=true),\n * `workspace_id = NULL` is always false, so RLS returns no rows — leaking\n * nothing rather than everything.\n *\n * NOTE: Uses session-level SET (safe without a pooler or with session-mode\n * pooling). Upgrade to SET LOCAL inside `$transaction` when PgBouncer\n * transaction-mode pooling is enabled (Phase 3b).\n *\n * @default false\n */\n enableRlsGucTagging?: boolean;\n}\n\n/**\n * Default configuration\n */\nconst defaultConfig: Required<WorkspaceExtensionConfig> = {\n enabled: true,\n enableReadIsolation: true,\n enableDeleteIsolation: true,\n enableUpdateWhereIsolation: true,\n populateContextJson: true,\n populateCreatedBy: true,\n populateUpdatedBy: true,\n populateTenantId: false,\n excludeModels: [],\n excludeModelsFromReadIsolation: [],\n strictMode: true,\n allowedUnguardedOperations: [],\n debug: false,\n enableApplicationNameTagging: false,\n enableRlsGucTagging: false,\n};\n\n// ============================================================================\n// Data Injection Helpers\n// ============================================================================\n\n/**\n * Check if a field exists in the data object (including being set to null/undefined explicitly)\n */\nfunction hasField(data: Record<string, unknown>, field: string): boolean {\n return field in data;\n}\n\n/**\n * Inject workspace-related fields into create data\n */\nfunction injectCreateFields(\n data: Record<string, unknown>,\n wsCtx: WorkspaceContext,\n config: Required<WorkspaceExtensionConfig>\n): Record<string, unknown> {\n const injected = { ...data };\n\n // Inject workspaceId if not already provided\n if (wsCtx.workspaceId && !hasField(injected, 'workspaceId')) {\n injected['workspaceId'] = wsCtx.workspaceId;\n }\n\n // Inject tenantId if configured and not already provided\n if (config.populateTenantId && wsCtx.tenantId && !hasField(injected, 'tenantId')) {\n injected['tenantId'] = wsCtx.tenantId;\n }\n\n // Inject createdBy if configured and not already provided\n if (config.populateCreatedBy && wsCtx.actorId && !hasField(injected, 'createdBy')) {\n injected['createdBy'] = wsCtx.actorId;\n }\n\n // Inject updatedBy on create as well (initial value)\n if (config.populateUpdatedBy && wsCtx.actorId && !hasField(injected, 'updatedBy')) {\n injected['updatedBy'] = wsCtx.actorId;\n }\n\n // Inject onBehalfOf (for consent-based delegation tracking)\n // If onBehalfOf is in context (from consent), use it; otherwise defaults to actorId (self-action)\n if (wsCtx.onBehalfOf && !hasField(injected, 'onBehalfOf')) {\n injected['onBehalfOf'] = wsCtx.onBehalfOf;\n } else if (wsCtx.actorId && !hasField(injected, 'onBehalfOf')) {\n // Default to actorId if no delegation (self-action)\n injected['onBehalfOf'] = wsCtx.actorId;\n }\n\n // Populate context JSON field\n if (config.populateContextJson && !hasField(injected, 'context')) {\n const contextJson = buildContextJsonFromWorkspaceContext(wsCtx);\n if (contextJson) {\n injected['context'] = contextJson;\n }\n }\n\n return injected;\n}\n\n/**\n * Inject workspace-related fields into update data\n */\nfunction injectUpdateFields(\n data: Record<string, unknown>,\n wsCtx: WorkspaceContext,\n config: Required<WorkspaceExtensionConfig>\n): Record<string, unknown> {\n const injected = { ...data };\n\n // Inject updatedBy if configured and not already provided\n if (config.populateUpdatedBy && wsCtx.actorId && !hasField(injected, 'updatedBy')) {\n injected['updatedBy'] = wsCtx.actorId;\n }\n\n // Note: We intentionally do NOT auto-inject workspaceId on updates\n // because updates target existing records (workspaceId is immutable after creation)\n // and changing it would be a data integrity issue.\n\n return injected;\n}\n\n/**\n * Inject workspaceId into a where clause.\n * Only injects if workspaceId is available in context and not already present in where.\n *\n * For operations that may not have a where clause (e.g., findMany without filters),\n * creates a new where object with just workspaceId.\n */\nfunction injectWhereClause(\n where: Record<string, unknown> | undefined,\n wsCtx: WorkspaceContext\n): Record<string, unknown> | undefined {\n if (!wsCtx.workspaceId) return where;\n\n if (!where) {\n // No where clause exists, create one with just workspaceId\n return { workspaceId: wsCtx.workspaceId };\n }\n\n // Only inject if not already present\n if (!hasField(where, 'workspaceId')) {\n return { ...where, workspaceId: wsCtx.workspaceId };\n }\n\n return where;\n}\n\n/**\n * Build context JSON from workspace context\n */\nfunction buildContextJsonFromWorkspaceContext(wsCtx: WorkspaceContext): InputJsonValue | undefined {\n const context: Record<string, string> = {};\n\n if (wsCtx.workspaceId) context['workspaceId'] = wsCtx.workspaceId;\n if (wsCtx.actorId) context['userId'] = wsCtx.actorId;\n if (wsCtx.organizationId) context['organizationId'] = wsCtx.organizationId;\n if (wsCtx.projectId) context['projectId'] = wsCtx.projectId;\n if (wsCtx.appId) context['appId'] = wsCtx.appId;\n\n return Object.keys(context).length > 0 ? context : undefined;\n}\n\n/**\n * Inject workspaceId into where clause for read/update/delete operations.\n * This is a utility function exported for services that want to manually\n * add workspace scoping to their queries.\n *\n * @param where - The existing where clause\n * @param wsCtx - The workspace context (or auto-detected from AsyncLocalStorage)\n * @returns The where clause with workspaceId injected if not already present\n *\n * @example\n * ```typescript\n * import { injectWhereWorkspaceId, getWorkspaceContext } from '@burdenoff/be-sdk/prisma';\n *\n * const wsCtx = getWorkspaceContext();\n * const where = injectWhereWorkspaceId({ status: 'ACTIVE' }, wsCtx);\n * // Result: { status: 'ACTIVE', workspaceId: 'ws-123' }\n * ```\n */\nexport function injectWhereWorkspaceId(\n where: Record<string, unknown> | undefined,\n wsCtx?: WorkspaceContext\n): Record<string, unknown> | undefined {\n const ctx = wsCtx ?? getWorkspaceContext();\n if (!where || !ctx?.workspaceId) return where;\n\n // Only inject if not already present\n if (!hasField(where, 'workspaceId')) {\n return { ...where, workspaceId: ctx.workspaceId };\n }\n\n return where;\n}\n\n/**\n * Remove the _skipWorkspaceInjection flag from args before passing to Prisma.\n * Using a dedicated function avoids ESLint unused-variable warnings from destructuring.\n */\nfunction stripSkipFlag<T extends Record<string, unknown>>(args: T): Omit<T, '_skipWorkspaceInjection'> {\n const cleaned = { ...args };\n delete (cleaned as Record<string, unknown>)['_skipWorkspaceInjection'];\n return cleaned;\n}\n\n/**\n * Check if a model should be excluded from read isolation.\n * A model is excluded if it's in excludeModels OR excludeModelsFromReadIsolation.\n */\nfunction isExcludedFromReadIsolation(model: string, config: Required<WorkspaceExtensionConfig>): boolean {\n return config.excludeModels.includes(model) || config.excludeModelsFromReadIsolation.includes(model);\n}\n\n// ============================================================================\n// Strict Mode Enforcement\n// ============================================================================\n\n/**\n * Enforce strict mode: throw if workspace context is missing and the operation\n * is not explicitly allowed to run without it.\n *\n * @returns true if the operation should proceed without workspace injection (non-strict or allowed)\n * @throws Error if strict mode is enabled and the operation is not allowed\n */\nfunction enforceStrictMode(\n model: string,\n operation: string,\n wsCtx: WorkspaceContext | undefined,\n config: Required<WorkspaceExtensionConfig>\n): void {\n // If workspace context has a workspaceId, nothing to enforce\n if (wsCtx?.workspaceId) return;\n\n // If strict mode is off, allow silently\n if (!config.strictMode) return;\n\n // Check if this specific operation is allowed without workspace context\n const opKey = `${model}.${operation}`;\n if (config.allowedUnguardedOperations.includes(opKey)) return;\n\n // Strict mode violation — throw\n throw new Error(\n `[WorkspaceExtension] Workspace context required for ${model}.${operation}. ` +\n `No workspaceId found in request context. To bypass, either: ` +\n `(1) add \"${model}\" to excludeModels, ` +\n `(2) add \"${opKey}\" to allowedUnguardedOperations, or ` +\n `(3) pass _skipWorkspaceInjection: true in the query args.`\n );\n}\n\n// ============================================================================\n// Prisma Extension\n// ============================================================================\n\n/**\n * Standard args shape for operations with a `where` clause\n */\ninterface WhereArgs {\n where?: Record<string, unknown>;\n _skipWorkspaceInjection?: boolean;\n [key: string]: unknown;\n}\n\n/**\n * Standard handler params from Prisma $extends\n */\ninterface ExtensionHandlerParams<TArgs> {\n model: string;\n args: TArgs;\n query: (args: unknown) => Promise<unknown>;\n}\n\n/**\n * Add workspace extension to a Prisma client.\n *\n * This extension provides comprehensive workspace isolation by automatically\n * injecting workspaceId into ALL Prisma operations:\n *\n * **Writes**: Auto-populates workspaceId, tenantId, createdBy, updatedBy, context JSON\n * **Reads**: Auto-injects workspaceId into where clause (findMany, findFirst, etc.)\n * **Updates**: Auto-injects workspaceId into where clause + updatedBy into data\n * **Deletes**: Auto-injects workspaceId into where clause\n *\n * **Chain order matters**: Apply this extension AFTER the graph extension\n * (handled automatically by createDatabaseClient).\n *\n * @param baseClient - The Prisma client to extend\n * @param config - Extension configuration\n * @returns Extended Prisma client with workspace auto-injection\n *\n * @example\n * ```typescript\n * import { PrismaClient } from './generated/prisma/client.js';\n * import { addWorkspaceExtension } from '@burdenoff/be-sdk/prisma';\n *\n * const baseClient = new PrismaClient({ adapter });\n * const client = addWorkspaceExtension(baseClient, {\n * populateContextJson: true,\n * populateCreatedBy: true,\n * enableReadIsolation: true,\n * debug: process.env.NODE_ENV === 'development',\n * excludeModels: ['CircuitBreakerState', 'SchedulerState'],\n * excludeModelsFromReadIsolation: ['Permission', 'RbacResourceType'],\n * });\n * ```\n */\n// ============================================================================\n// Connection Tagging (Phase 0.2)\n// ============================================================================\n\n/** Minimal Prisma raw-exec surface needed for SET application_name */\ntype RawPrismaForTagging = {\n $executeRawUnsafe: (query: string, ...values: unknown[]) => Promise<number>;\n};\n\n/**\n * WeakSet of contexts that have already had the connection tagged this request.\n * WorkspaceContext objects live only for the duration of a request, so entries\n * are automatically GC'd when the context goes out of scope — no manual cleanup.\n */\nconst taggedContexts = new WeakSet<WorkspaceContext>();\n\n/**\n * Tag the current Postgres connection with workspace attribution (once per context).\n * Sets `application_name = 'svc=<name>;ws=<workspaceId>'` at the session level.\n * Non-fatal: tagging failures are swallowed so the main operation still proceeds.\n *\n * @internal Exported for unit testing only — do not call from product code.\n */\nexport async function maybeTagConnection(rawPrisma: RawPrismaForTagging, wsCtx: WorkspaceContext): Promise<void> {\n if (taggedContexts.has(wsCtx)) return;\n taggedContexts.add(wsCtx);\n // Strip non-safe chars; workspace IDs are UUIDs/CUIDs, service names are kebab-case\n const safeSvc = (process.env['SERVICE_NAME'] ?? 'svc').replace(/[^a-zA-Z0-9\\-_]/g, '');\n const safeWs = (wsCtx.workspaceId ?? '').replace(/[^a-zA-Z0-9\\-_]/g, '');\n const tag = `svc=${safeSvc};ws=${safeWs}`;\n try {\n await rawPrisma.$executeRawUnsafe(`SET application_name = '${tag}'`);\n } catch {\n // Retry on the next operation if this one failed\n taggedContexts.delete(wsCtx);\n }\n}\n\n// ============================================================================\n// RLS GUC Tagging (Phase 3)\n// ============================================================================\n\n/**\n * WeakSet of contexts that have already had the RLS GUC set this request.\n */\nconst rlsTaggedContexts = new WeakSet<WorkspaceContext>();\n\n/**\n * Set `app.workspace_id` GUC for RLS enforcement (once per context, session-level).\n *\n * When set, RLS policies using `current_setting('app.workspace_id', true)` filter\n * rows to the current workspace. Non-fatal: failures are swallowed and retried on\n * the next operation via WeakSet entry removal.\n *\n * @internal Exported for unit testing only — do not call from product code.\n */\nexport async function maybeSetRlsGuc(rawPrisma: RawPrismaForTagging, wsCtx: WorkspaceContext): Promise<void> {\n if (rlsTaggedContexts.has(wsCtx)) return;\n rlsTaggedContexts.add(wsCtx);\n // Allow alphanumeric, hyphens, underscores — CUID/UUID safe, prevents SQL injection\n const safeWs = (wsCtx.workspaceId ?? '').replace(/[^a-zA-Z0-9\\-_]/g, '');\n try {\n await rawPrisma.$executeRawUnsafe(`SET app.workspace_id = '${safeWs}'`);\n } catch {\n // Retry on the next operation if this one failed\n rlsTaggedContexts.delete(wsCtx);\n }\n}\n\nexport function addWorkspaceExtension<T>(baseClient: T, config?: WorkspaceExtensionConfig): T {\n const fullConfig: Required<WorkspaceExtensionConfig> = {\n ...defaultConfig,\n ...config,\n };\n\n if (!fullConfig.enabled) {\n logger.info('[WorkspaceExtension] Extension disabled by configuration');\n return baseClient;\n }\n\n // Capture the unwrapped client for connection tagging (pre-extension, avoids recursion)\n const rawPrisma = baseClient as unknown as RawPrismaForTagging;\n\n // Type assertion for Prisma client $extends\n const prismaClient = baseClient as { $extends: (args: unknown) => T };\n\n logger.info('[WorkspaceExtension] Workspace extension enabled', {\n populateContextJson: fullConfig.populateContextJson,\n populateCreatedBy: fullConfig.populateCreatedBy,\n populateUpdatedBy: fullConfig.populateUpdatedBy,\n populateTenantId: fullConfig.populateTenantId,\n enableReadIsolation: fullConfig.enableReadIsolation,\n enableDeleteIsolation: fullConfig.enableDeleteIsolation,\n enableUpdateWhereIsolation: fullConfig.enableUpdateWhereIsolation,\n strictMode: fullConfig.strictMode,\n excludeModels: fullConfig.excludeModels,\n excludeModelsFromReadIsolation: fullConfig.excludeModelsFromReadIsolation,\n allowedUnguardedOperations: fullConfig.allowedUnguardedOperations,\n enableApplicationNameTagging: fullConfig.enableApplicationNameTagging,\n enableRlsGucTagging: fullConfig.enableRlsGucTagging,\n });\n\n return prismaClient.$extends({\n query: {\n $allModels: {\n // ================================================================\n // WRITE OPERATIONS - inject workspaceId into data\n // ================================================================\n\n async create({\n model,\n args,\n query,\n }: ExtensionHandlerParams<{\n data: Record<string, unknown>;\n _skipWorkspaceInjection?: boolean;\n [key: string]: unknown;\n }>) {\n // Skip if model is excluded or injection is explicitly skipped\n if (fullConfig.excludeModels.includes(model) || args._skipWorkspaceInjection) {\n return query(stripSkipFlag(args));\n }\n\n const wsCtx = getWorkspaceContext();\n enforceStrictMode(model, 'create', wsCtx, fullConfig);\n if (!wsCtx?.workspaceId) {\n return query(args);\n }\n\n if (fullConfig.enableApplicationNameTagging) {\n await maybeTagConnection(rawPrisma, wsCtx);\n }\n if (fullConfig.enableRlsGucTagging) {\n await maybeSetRlsGuc(rawPrisma, wsCtx);\n }\n\n // Inject fields into data\n const injectedData = injectCreateFields(args.data, wsCtx, fullConfig);\n\n if (fullConfig.debug) {\n const injectedKeys = Object.keys(injectedData).filter((k) => !(k in args.data));\n if (injectedKeys.length > 0) {\n logger.debug(`[WorkspaceExtension] ${model}.create - injected: ${injectedKeys.join(', ')}`, {\n workspaceId: wsCtx.workspaceId,\n actorId: wsCtx.actorId,\n });\n }\n }\n\n return query({\n ...stripSkipFlag(args),\n data: injectedData,\n });\n },\n\n async createMany({\n model,\n args,\n query,\n }: ExtensionHandlerParams<{\n data: Record<string, unknown> | Record<string, unknown>[];\n _skipWorkspaceInjection?: boolean;\n [key: string]: unknown;\n }>) {\n if (fullConfig.excludeModels.includes(model) || args._skipWorkspaceInjection) {\n return query(stripSkipFlag(args));\n }\n\n const wsCtx = getWorkspaceContext();\n enforceStrictMode(model, 'createMany', wsCtx, fullConfig);\n if (!wsCtx?.workspaceId) {\n return query(args);\n }\n\n if (fullConfig.enableApplicationNameTagging) {\n await maybeTagConnection(rawPrisma, wsCtx);\n }\n if (fullConfig.enableRlsGucTagging) {\n await maybeSetRlsGuc(rawPrisma, wsCtx);\n }\n\n // Handle both single object and array\n const dataArray = Array.isArray(args.data) ? args.data : [args.data];\n const injectedData = dataArray.map((item) => injectCreateFields(item, wsCtx, fullConfig));\n\n return query({\n ...stripSkipFlag(args),\n data: Array.isArray(args.data) ? injectedData : injectedData[0],\n });\n },\n\n async createManyAndReturn({\n model,\n args,\n query,\n }: ExtensionHandlerParams<{\n data: Record<string, unknown> | Record<string, unknown>[];\n _skipWorkspaceInjection?: boolean;\n [key: string]: unknown;\n }>) {\n if (fullConfig.excludeModels.includes(model) || args._skipWorkspaceInjection) {\n return query(stripSkipFlag(args));\n }\n\n const wsCtx = getWorkspaceContext();\n enforceStrictMode(model, 'createManyAndReturn', wsCtx, fullConfig);\n if (!wsCtx?.workspaceId) {\n return query(args);\n }\n\n if (fullConfig.enableApplicationNameTagging) {\n await maybeTagConnection(rawPrisma, wsCtx);\n }\n if (fullConfig.enableRlsGucTagging) {\n await maybeSetRlsGuc(rawPrisma, wsCtx);\n }\n\n const dataArray = Array.isArray(args.data) ? args.data : [args.data];\n const injectedData = dataArray.map((item) => injectCreateFields(item, wsCtx, fullConfig));\n\n return query({\n ...stripSkipFlag(args),\n data: Array.isArray(args.data) ? injectedData : injectedData[0],\n });\n },\n\n // ================================================================\n // UPDATE OPERATIONS - inject updatedBy into data + workspaceId into where\n // ================================================================\n\n async update({\n model,\n args,\n query,\n }: ExtensionHandlerParams<{\n data: Record<string, unknown>;\n where?: Record<string, unknown>;\n _skipWorkspaceInjection?: boolean;\n [key: string]: unknown;\n }>) {\n if (fullConfig.excludeModels.includes(model) || args._skipWorkspaceInjection) {\n return query(stripSkipFlag(args));\n }\n\n const wsCtx = getWorkspaceContext();\n enforceStrictMode(model, 'update', wsCtx, fullConfig);\n if (!wsCtx?.workspaceId) {\n return query(args);\n }\n\n if (fullConfig.enableApplicationNameTagging) {\n await maybeTagConnection(rawPrisma, wsCtx);\n }\n if (fullConfig.enableRlsGucTagging) {\n await maybeSetRlsGuc(rawPrisma, wsCtx);\n }\n\n const injectedData = injectUpdateFields(args.data, wsCtx, fullConfig);\n\n // Inject workspaceId into where clause for update isolation\n let injectedWhere = args.where;\n if (fullConfig.enableUpdateWhereIsolation && !isExcludedFromReadIsolation(model, fullConfig)) {\n injectedWhere = injectWhereClause(args.where, wsCtx);\n }\n\n if (fullConfig.debug) {\n const injectedDataKeys = Object.keys(injectedData).filter((k) => !(k in args.data));\n const whereChanged = injectedWhere !== args.where;\n if (injectedDataKeys.length > 0 || whereChanged) {\n logger.debug(\n `[WorkspaceExtension] ${model}.update - injected data: ${injectedDataKeys.join(', ')}${whereChanged ? ', where: workspaceId' : ''}`\n );\n }\n }\n\n return query({\n ...stripSkipFlag(args),\n data: injectedData,\n where: injectedWhere,\n });\n },\n\n async updateMany({\n model,\n args,\n query,\n }: ExtensionHandlerParams<{\n data: Record<string, unknown>;\n where?: Record<string, unknown>;\n _skipWorkspaceInjection?: boolean;\n [key: string]: unknown;\n }>) {\n if (fullConfig.excludeModels.includes(model) || args._skipWorkspaceInjection) {\n return query(stripSkipFlag(args));\n }\n\n const wsCtx = getWorkspaceContext();\n enforceStrictMode(model, 'updateMany', wsCtx, fullConfig);\n if (!wsCtx?.workspaceId) {\n return query(args);\n }\n\n if (fullConfig.enableApplicationNameTagging) {\n await maybeTagConnection(rawPrisma, wsCtx);\n }\n if (fullConfig.enableRlsGucTagging) {\n await maybeSetRlsGuc(rawPrisma, wsCtx);\n }\n\n const injectedData = injectUpdateFields(args.data, wsCtx, fullConfig);\n\n // Inject workspaceId into where clause for update isolation\n let injectedWhere = args.where;\n if (fullConfig.enableUpdateWhereIsolation && !isExcludedFromReadIsolation(model, fullConfig)) {\n injectedWhere = injectWhereClause(args.where, wsCtx);\n }\n\n return query({\n ...stripSkipFlag(args),\n data: injectedData,\n where: injectedWhere,\n });\n },\n\n async upsert({\n model,\n args,\n query,\n }: ExtensionHandlerParams<{\n create: Record<string, unknown>;\n update: Record<string, unknown>;\n where?: Record<string, unknown>;\n _skipWorkspaceInjection?: boolean;\n [key: string]: unknown;\n }>) {\n if (fullConfig.excludeModels.includes(model) || args._skipWorkspaceInjection) {\n return query(stripSkipFlag(args));\n }\n\n const wsCtx = getWorkspaceContext();\n enforceStrictMode(model, 'upsert', wsCtx, fullConfig);\n if (!wsCtx?.workspaceId) {\n return query(args);\n }\n\n if (fullConfig.enableApplicationNameTagging) {\n await maybeTagConnection(rawPrisma, wsCtx);\n }\n if (fullConfig.enableRlsGucTagging) {\n await maybeSetRlsGuc(rawPrisma, wsCtx);\n }\n\n const injectedCreate = injectCreateFields(args.create, wsCtx, fullConfig);\n const injectedUpdate = injectUpdateFields(args.update, wsCtx, fullConfig);\n\n // Inject workspaceId into where clause for upsert isolation\n let injectedWhere = args.where;\n if (fullConfig.enableUpdateWhereIsolation && !isExcludedFromReadIsolation(model, fullConfig)) {\n injectedWhere = injectWhereClause(args.where, wsCtx);\n }\n\n return query({\n ...stripSkipFlag(args),\n create: injectedCreate,\n update: injectedUpdate,\n where: injectedWhere,\n });\n },\n\n // ================================================================\n // READ OPERATIONS - inject workspaceId into where clause\n // ================================================================\n\n async findMany({ model, args, query }: ExtensionHandlerParams<WhereArgs>) {\n if (\n !fullConfig.enableReadIsolation ||\n isExcludedFromReadIsolation(model, fullConfig) ||\n args._skipWorkspaceInjection\n ) {\n return query(stripSkipFlag(args));\n }\n\n const wsCtx = getWorkspaceContext();\n enforceStrictMode(model, 'findMany', wsCtx, fullConfig);\n if (!wsCtx?.workspaceId) {\n return query(args);\n }\n\n if (fullConfig.enableApplicationNameTagging) {\n await maybeTagConnection(rawPrisma, wsCtx);\n }\n if (fullConfig.enableRlsGucTagging) {\n await maybeSetRlsGuc(rawPrisma, wsCtx);\n }\n\n const injectedWhere = injectWhereClause(args.where, wsCtx);\n\n if (fullConfig.debug) {\n logger.debug(`[WorkspaceExtension] ${model}.findMany - injected workspaceId into where`, {\n workspaceId: wsCtx.workspaceId,\n });\n }\n\n return query({\n ...stripSkipFlag(args),\n where: injectedWhere,\n });\n },\n\n async findFirst({ model, args, query }: ExtensionHandlerParams<WhereArgs>) {\n if (\n !fullConfig.enableReadIsolation ||\n isExcludedFromReadIsolation(model, fullConfig) ||\n args._skipWorkspaceInjection\n ) {\n return query(stripSkipFlag(args));\n }\n\n const wsCtx = getWorkspaceContext();\n enforceStrictMode(model, 'findFirst', wsCtx, fullConfig);\n if (!wsCtx?.workspaceId) {\n return query(args);\n }\n\n if (fullConfig.enableApplicationNameTagging) {\n await maybeTagConnection(rawPrisma, wsCtx);\n }\n if (fullConfig.enableRlsGucTagging) {\n await maybeSetRlsGuc(rawPrisma, wsCtx);\n }\n\n const injectedWhere = injectWhereClause(args.where, wsCtx);\n\n if (fullConfig.debug) {\n logger.debug(`[WorkspaceExtension] ${model}.findFirst - injected workspaceId into where`, {\n workspaceId: wsCtx.workspaceId,\n });\n }\n\n return query({\n ...stripSkipFlag(args),\n where: injectedWhere,\n });\n },\n\n async findFirstOrThrow({ model, args, query }: ExtensionHandlerParams<WhereArgs>) {\n if (\n !fullConfig.enableReadIsolation ||\n isExcludedFromReadIsolation(model, fullConfig) ||\n args._skipWorkspaceInjection\n ) {\n return query(stripSkipFlag(args));\n }\n\n const wsCtx = getWorkspaceContext();\n enforceStrictMode(model, 'findFirstOrThrow', wsCtx, fullConfig);\n if (!wsCtx?.workspaceId) {\n return query(args);\n }\n\n if (fullConfig.enableApplicationNameTagging) {\n await maybeTagConnection(rawPrisma, wsCtx);\n }\n if (fullConfig.enableRlsGucTagging) {\n await maybeSetRlsGuc(rawPrisma, wsCtx);\n }\n\n const injectedWhere = injectWhereClause(args.where, wsCtx);\n\n if (fullConfig.debug) {\n logger.debug(`[WorkspaceExtension] ${model}.findFirstOrThrow - injected workspaceId into where`, {\n workspaceId: wsCtx.workspaceId,\n });\n }\n\n return query({\n ...stripSkipFlag(args),\n where: injectedWhere,\n });\n },\n\n async findUnique({ model, args, query }: ExtensionHandlerParams<WhereArgs>) {\n if (\n !fullConfig.enableReadIsolation ||\n isExcludedFromReadIsolation(model, fullConfig) ||\n args._skipWorkspaceInjection\n ) {\n return query(stripSkipFlag(args));\n }\n\n const wsCtx = getWorkspaceContext();\n enforceStrictMode(model, 'findUnique', wsCtx, fullConfig);\n if (!wsCtx?.workspaceId) {\n return query(args);\n }\n\n if (fullConfig.enableApplicationNameTagging) {\n await maybeTagConnection(rawPrisma, wsCtx);\n }\n if (fullConfig.enableRlsGucTagging) {\n await maybeSetRlsGuc(rawPrisma, wsCtx);\n }\n\n // For findUnique, the where clause uses unique fields.\n // We inject workspaceId only if the where clause is a plain object\n // (compound unique keys with workspaceId are common and already include it).\n const injectedWhere = injectWhereClause(args.where, wsCtx);\n\n if (fullConfig.debug) {\n logger.debug(`[WorkspaceExtension] ${model}.findUnique - injected workspaceId into where`, {\n workspaceId: wsCtx.workspaceId,\n });\n }\n\n return query({\n ...stripSkipFlag(args),\n where: injectedWhere,\n });\n },\n\n async findUniqueOrThrow({ model, args, query }: ExtensionHandlerParams<WhereArgs>) {\n if (\n !fullConfig.enableReadIsolation ||\n isExcludedFromReadIsolation(model, fullConfig) ||\n args._skipWorkspaceInjection\n ) {\n return query(stripSkipFlag(args));\n }\n\n const wsCtx = getWorkspaceContext();\n enforceStrictMode(model, 'findUniqueOrThrow', wsCtx, fullConfig);\n if (!wsCtx?.workspaceId) {\n return query(args);\n }\n\n if (fullConfig.enableApplicationNameTagging) {\n await maybeTagConnection(rawPrisma, wsCtx);\n }\n if (fullConfig.enableRlsGucTagging) {\n await maybeSetRlsGuc(rawPrisma, wsCtx);\n }\n\n const injectedWhere = injectWhereClause(args.where, wsCtx);\n\n if (fullConfig.debug) {\n logger.debug(`[WorkspaceExtension] ${model}.findUniqueOrThrow - injected workspaceId into where`, {\n workspaceId: wsCtx.workspaceId,\n });\n }\n\n return query({\n ...stripSkipFlag(args),\n where: injectedWhere,\n });\n },\n\n async count({ model, args, query }: ExtensionHandlerParams<WhereArgs>) {\n if (\n !fullConfig.enableReadIsolation ||\n isExcludedFromReadIsolation(model, fullConfig) ||\n args._skipWorkspaceInjection\n ) {\n return query(stripSkipFlag(args));\n }\n\n const wsCtx = getWorkspaceContext();\n enforceStrictMode(model, 'count', wsCtx, fullConfig);\n if (!wsCtx?.workspaceId) {\n return query(args);\n }\n\n if (fullConfig.enableApplicationNameTagging) {\n await maybeTagConnection(rawPrisma, wsCtx);\n }\n if (fullConfig.enableRlsGucTagging) {\n await maybeSetRlsGuc(rawPrisma, wsCtx);\n }\n\n const injectedWhere = injectWhereClause(args.where, wsCtx);\n\n if (fullConfig.debug) {\n logger.debug(`[WorkspaceExtension] ${model}.count - injected workspaceId into where`, {\n workspaceId: wsCtx.workspaceId,\n });\n }\n\n return query({\n ...stripSkipFlag(args),\n where: injectedWhere,\n });\n },\n\n async aggregate({ model, args, query }: ExtensionHandlerParams<WhereArgs>) {\n if (\n !fullConfig.enableReadIsolation ||\n isExcludedFromReadIsolation(model, fullConfig) ||\n args._skipWorkspaceInjection\n ) {\n return query(stripSkipFlag(args));\n }\n\n const wsCtx = getWorkspaceContext();\n enforceStrictMode(model, 'aggregate', wsCtx, fullConfig);\n if (!wsCtx?.workspaceId) {\n return query(args);\n }\n\n if (fullConfig.enableApplicationNameTagging) {\n await maybeTagConnection(rawPrisma, wsCtx);\n }\n if (fullConfig.enableRlsGucTagging) {\n await maybeSetRlsGuc(rawPrisma, wsCtx);\n }\n\n const injectedWhere = injectWhereClause(args.where, wsCtx);\n\n if (fullConfig.debug) {\n logger.debug(`[WorkspaceExtension] ${model}.aggregate - injected workspaceId into where`, {\n workspaceId: wsCtx.workspaceId,\n });\n }\n\n return query({\n ...stripSkipFlag(args),\n where: injectedWhere,\n });\n },\n\n async groupBy({ model, args, query }: ExtensionHandlerParams<WhereArgs>) {\n if (\n !fullConfig.enableReadIsolation ||\n isExcludedFromReadIsolation(model, fullConfig) ||\n args._skipWorkspaceInjection\n ) {\n return query(stripSkipFlag(args));\n }\n\n const wsCtx = getWorkspaceContext();\n enforceStrictMode(model, 'groupBy', wsCtx, fullConfig);\n if (!wsCtx?.workspaceId) {\n return query(args);\n }\n\n if (fullConfig.enableApplicationNameTagging) {\n await maybeTagConnection(rawPrisma, wsCtx);\n }\n if (fullConfig.enableRlsGucTagging) {\n await maybeSetRlsGuc(rawPrisma, wsCtx);\n }\n\n const injectedWhere = injectWhereClause(args.where, wsCtx);\n\n if (fullConfig.debug) {\n logger.debug(`[WorkspaceExtension] ${model}.groupBy - injected workspaceId into where`, {\n workspaceId: wsCtx.workspaceId,\n });\n }\n\n return query({\n ...stripSkipFlag(args),\n where: injectedWhere,\n });\n },\n\n // ================================================================\n // DELETE OPERATIONS - inject workspaceId into where clause\n // ================================================================\n\n async delete({ model, args, query }: ExtensionHandlerParams<WhereArgs>) {\n if (\n !fullConfig.enableDeleteIsolation ||\n isExcludedFromReadIsolation(model, fullConfig) ||\n args._skipWorkspaceInjection\n ) {\n return query(stripSkipFlag(args));\n }\n\n const wsCtx = getWorkspaceContext();\n enforceStrictMode(model, 'delete', wsCtx, fullConfig);\n if (!wsCtx?.workspaceId) {\n return query(args);\n }\n\n if (fullConfig.enableApplicationNameTagging) {\n await maybeTagConnection(rawPrisma, wsCtx);\n }\n if (fullConfig.enableRlsGucTagging) {\n await maybeSetRlsGuc(rawPrisma, wsCtx);\n }\n\n const injectedWhere = injectWhereClause(args.where, wsCtx);\n\n if (fullConfig.debug) {\n logger.debug(`[WorkspaceExtension] ${model}.delete - injected workspaceId into where`, {\n workspaceId: wsCtx.workspaceId,\n });\n }\n\n return query({\n ...stripSkipFlag(args),\n where: injectedWhere,\n });\n },\n\n async deleteMany({ model, args, query }: ExtensionHandlerParams<WhereArgs>) {\n if (\n !fullConfig.enableDeleteIsolation ||\n isExcludedFromReadIsolation(model, fullConfig) ||\n args._skipWorkspaceInjection\n ) {\n return query(stripSkipFlag(args));\n }\n\n const wsCtx = getWorkspaceContext();\n enforceStrictMode(model, 'deleteMany', wsCtx, fullConfig);\n if (!wsCtx?.workspaceId) {\n return query(args);\n }\n\n if (fullConfig.enableApplicationNameTagging) {\n await maybeTagConnection(rawPrisma, wsCtx);\n }\n if (fullConfig.enableRlsGucTagging) {\n await maybeSetRlsGuc(rawPrisma, wsCtx);\n }\n\n const injectedWhere = injectWhereClause(args.where, wsCtx);\n\n if (fullConfig.debug) {\n logger.debug(`[WorkspaceExtension] ${model}.deleteMany - injected workspaceId into where`, {\n workspaceId: wsCtx.workspaceId,\n });\n }\n\n return query({\n ...stripSkipFlag(args),\n where: injectedWhere,\n });\n },\n },\n },\n });\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/feature-flags/index.ts","../src/feature-flags/provider.ts"],"names":["EVALUATE_QUERY","readPositiveIntEnv","name","fallback","raw","process","env","parsed","parseInt","Number","isFinite","FeatureFlagProvider","gatewayUrl","cacheTtlMs","failureTtlMs","requestTimeoutMs","serviceToken","serviceName","defaultActorType","cache","Map","config","cacheTtlSeconds","failureTtlSeconds","resolveBoolean","flagKey","defaultValue","context","evaluation","getEvaluation","value","reason","flagType","Boolean","variant","undefined","errorCode","resolveString","String","resolveNumber","resolveObject","isEnabled","result","workspaceId","actorType","actorId","evaluateAll","keys","evaluations","fetchEvaluations","key","set","invalidateCache","cacheKey","buildCacheKey","delete","clear","get","cached","expiresAt","Date","now","bearerToken","signServiceJwt","response","fetch","method","signal","AbortSignal","timeout","headers","Authorization","ContextManager","getCfAccessHeaders","body","JSON","stringify","query","variables","input","ok","rememberFailure","json","errors","data","evaluateFeatureFlags","ctx"],"mappings":"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","file":"chunk-WM5COTOD.js","sourcesContent":["/**\n * Feature Flags Module\n *\n * In-house feature flag evaluation for Burdenoff backend services.\n * Compatible with OpenFeature specification concepts.\n *\n * @module feature-flags\n * @category FeatureFlags\n *\n * @example\n * ```typescript\n * import { FeatureFlagProvider } from '@burdenoff/be-sdk/feature-flags';\n *\n * // Create provider (typically done once at service startup)\n * const provider = new FeatureFlagProvider({\n * gatewayUrl: process.env.GLOBAL_INT_GATEWAY_URL || 'http://global-int-gateway:4000/global/graphql',\n * cacheTtlSeconds: 60,\n * });\n *\n * // Check a boolean flag\n * const ctx = { actorId: 'user-123', actorType: 'user' as const, workspaceId: 'ws-456' };\n * const isEnabled = await provider.isEnabled('calendar.recurring-events', ctx);\n *\n * // Resolve with full details\n * const details = await provider.resolveBoolean('calendar.recurring-events', true, ctx);\n * console.log(details.value); // true\n * console.log(details.reason); // 'TARGETING_MATCH'\n * console.log(details.variant); // 'user-opted-in'\n * ```\n */\n\nexport { FeatureFlagProvider } from './provider.js';\nexport type {\n EvaluationContext,\n FeatureFlagProviderConfig,\n FlagEvaluation,\n FlagType,\n ResolutionDetails,\n} from './types.js';\n","/**\n * Burdenoff Feature Flags Server Provider\n *\n * Server-side feature flag provider for backend services.\n * Evaluates flags via the global-tenant-svc GraphQL API through the internal gateway.\n * Supports in-memory caching with configurable TTL.\n *\n * @module feature-flags/provider\n * @category FeatureFlags\n *\n * @example\n * ```typescript\n * import { FeatureFlagProvider } from '@burdenoff/be-sdk/feature-flags';\n *\n * const provider = new FeatureFlagProvider({\n * gatewayUrl: 'http://global-int-gateway:4000/global/graphql',\n * cacheTtlSeconds: 60,\n * });\n *\n * const isEnabled = await provider.resolveBoolean('calendar.recurring-events', false, {\n * actorId: 'user-123',\n * actorType: 'user',\n * workspaceId: 'ws-456',\n * });\n *\n * console.log(isEnabled.value); // true or false\n * console.log(isEnabled.reason); // 'TARGETING_MATCH', 'DEFAULT', etc.\n * ```\n */\n\nimport { ContextManager } from '../context/index.js';\nimport { signServiceJwt } from '../gateway/service-jwt.js';\nimport type { EvaluationContext, FeatureFlagProviderConfig, FlagEvaluation, ResolutionDetails } from './types.js';\n\ninterface CacheEntry {\n evaluations: Map<string, FlagEvaluation>;\n expiresAt: number;\n}\n\nconst EVALUATE_QUERY = `\n query EvaluateFeatureFlags($input: EvaluateFeatureFlagsInput!) {\n evaluateFeatureFlags(input: $input) {\n evaluations {\n key\n value\n variant\n reason\n flagType\n errorCode\n }\n }\n }\n`;\n\n/**\n * Burdenoff Feature Flag Server Provider\n *\n * Evaluates feature flags by querying the global-tenant-svc through\n * the internal gateway. Results are cached in-memory per workspace+actor\n * combination with a configurable TTL.\n */\nfunction readPositiveIntEnv(name: string, fallback: number): number {\n const raw = process.env[name];\n if (!raw) return fallback;\n const parsed = parseInt(raw, 10);\n return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;\n}\n\nexport class FeatureFlagProvider {\n private readonly gatewayUrl: string;\n private readonly cacheTtlMs: number;\n private readonly failureTtlMs: number;\n private readonly requestTimeoutMs: number;\n private readonly serviceToken?: string;\n private readonly serviceName: string;\n private readonly defaultActorType: string;\n\n /** In-memory cache keyed by `${workspaceId}:${actorId}` */\n private readonly cache = new Map<string, CacheEntry>();\n\n constructor(config: FeatureFlagProviderConfig) {\n this.gatewayUrl = config.gatewayUrl;\n this.cacheTtlMs = (config.cacheTtlSeconds ?? 60) * 1000;\n // Hard per-request ceiling. Without it an unreachable gateway (NSG\n // silent-drop on the cross-environment path) left the fetch hanging for\n // the kernel's ~130s TCP connect timeout — stalling every flag-gated\n // request, and killing services that await a flag at BOOT (their ACA\n // startup probe expired → ActivationFailed).\n this.requestTimeoutMs = config.requestTimeoutMs ?? readPositiveIntEnv('FEATURE_FLAG_REQUEST_TIMEOUT_MS', 3000);\n // Negative cache so a broken gateway costs at most one timeout per\n // window instead of one per evaluation.\n this.failureTtlMs = (config.failureTtlSeconds ?? readPositiveIntEnv('FEATURE_FLAG_FAILURE_TTL_SECONDS', 15)) * 1000;\n this.serviceToken = config.serviceToken;\n this.serviceName = config.serviceName ?? process.env['SERVICE_NAME'] ?? 'burdenoff-be-sdk';\n this.defaultActorType = config.defaultActorType ?? 'service';\n }\n\n // =========================================================================\n // Public Resolution Methods (OpenFeature-compatible interface)\n // =========================================================================\n\n /**\n * Resolve a boolean feature flag\n *\n * @param flagKey - The flag key (e.g. \"calendar.recurring-events\")\n * @param defaultValue - Default value if resolution fails\n * @param context - Evaluation context with actor and workspace info\n * @returns Resolution details with the resolved boolean value\n */\n async resolveBoolean(\n flagKey: string,\n defaultValue: boolean,\n context: EvaluationContext\n ): Promise<ResolutionDetails<boolean>> {\n const evaluation = await this.getEvaluation(flagKey, context);\n if (!evaluation) {\n return {\n value: defaultValue,\n reason: 'DEFAULT',\n flagType: 'BOOLEAN',\n };\n }\n\n return {\n value: Boolean(evaluation.value),\n variant: evaluation.variant ?? undefined,\n reason: evaluation.reason,\n flagType: evaluation.flagType,\n errorCode: evaluation.errorCode ?? undefined,\n };\n }\n\n /**\n * Resolve a string feature flag\n */\n async resolveString(\n flagKey: string,\n defaultValue: string,\n context: EvaluationContext\n ): Promise<ResolutionDetails<string>> {\n const evaluation = await this.getEvaluation(flagKey, context);\n if (!evaluation) {\n return {\n value: defaultValue,\n reason: 'DEFAULT',\n flagType: 'STRING',\n };\n }\n\n return {\n value: String(evaluation.value),\n variant: evaluation.variant ?? undefined,\n reason: evaluation.reason,\n flagType: evaluation.flagType,\n errorCode: evaluation.errorCode ?? undefined,\n };\n }\n\n /**\n * Resolve a number feature flag\n */\n async resolveNumber(\n flagKey: string,\n defaultValue: number,\n context: EvaluationContext\n ): Promise<ResolutionDetails<number>> {\n const evaluation = await this.getEvaluation(flagKey, context);\n if (!evaluation) {\n return {\n value: defaultValue,\n reason: 'DEFAULT',\n flagType: 'NUMBER',\n };\n }\n\n return {\n value: Number(evaluation.value),\n variant: evaluation.variant ?? undefined,\n reason: evaluation.reason,\n flagType: evaluation.flagType,\n errorCode: evaluation.errorCode ?? undefined,\n };\n }\n\n /**\n * Resolve an object (JSON) feature flag\n */\n async resolveObject<T extends Record<string, unknown>>(\n flagKey: string,\n defaultValue: T,\n context: EvaluationContext\n ): Promise<ResolutionDetails<T>> {\n const evaluation = await this.getEvaluation(flagKey, context);\n if (!evaluation) {\n return {\n value: defaultValue,\n reason: 'DEFAULT',\n flagType: 'JSON',\n };\n }\n\n return {\n value: evaluation.value as T,\n variant: evaluation.variant ?? undefined,\n reason: evaluation.reason,\n flagType: evaluation.flagType,\n errorCode: evaluation.errorCode ?? undefined,\n };\n }\n\n // =========================================================================\n // Convenience Methods\n // =========================================================================\n\n /**\n * Quick boolean check — returns just the value.\n * Defaults to `true` (default-allow philosophy) if the flag is not found.\n *\n * @example\n * ```typescript\n * if (await provider.isEnabled('calendar.recurring-events', ctx)) {\n * // Feature is enabled\n * }\n * ```\n */\n async isEnabled(flagKey: string, context?: EvaluationContext): Promise<boolean> {\n const result = await this.resolveBoolean(\n flagKey,\n true,\n context ?? { workspaceId: 'system', actorType: 'service', actorId: 'boot' }\n );\n return result.value;\n }\n\n /**\n * Bulk evaluate multiple flags at once.\n * Returns a map of key -> ResolutionDetails.\n */\n async evaluateAll(context: EvaluationContext, keys?: string[]): Promise<Map<string, ResolutionDetails<unknown>>> {\n const evaluations = await this.fetchEvaluations(context, keys);\n const result = new Map<string, ResolutionDetails<unknown>>();\n\n for (const [key, evaluation] of evaluations) {\n result.set(key, {\n value: evaluation.value,\n variant: evaluation.variant ?? undefined,\n reason: evaluation.reason,\n flagType: evaluation.flagType,\n errorCode: evaluation.errorCode ?? undefined,\n });\n }\n\n return result;\n }\n\n /**\n * Invalidate the cache for a specific workspace+actor combination,\n * or all cache entries if no context is provided.\n */\n invalidateCache(context?: EvaluationContext): void {\n if (context) {\n const cacheKey = this.buildCacheKey(context);\n this.cache.delete(cacheKey);\n } else {\n this.cache.clear();\n }\n }\n\n // =========================================================================\n // Private Methods\n // =========================================================================\n\n /**\n * Get a single flag evaluation, fetching from cache or API\n */\n private async getEvaluation(flagKey: string, context: EvaluationContext | undefined): Promise<FlagEvaluation | null> {\n try {\n const evaluations = await this.fetchEvaluations(context);\n return evaluations.get(flagKey) ?? null;\n } catch {\n return null;\n }\n }\n\n /**\n * Fetch flag evaluations — uses cache if available, otherwise calls the API\n */\n private async fetchEvaluations(\n context: EvaluationContext | undefined,\n keys?: string[]\n ): Promise<Map<string, FlagEvaluation>> {\n const cacheKey = this.buildCacheKey(context);\n const cached = this.cache.get(cacheKey);\n\n if (cached && cached.expiresAt > Date.now()) {\n return cached.evaluations;\n }\n\n // Without a workspace context there's nothing the backend can evaluate\n // against — fall through to caller defaults instead of hitting the API.\n if (!context?.workspaceId) {\n return new Map();\n }\n\n // Cross-layer flag evaluation transits the global PUBLIC gateway, which\n // strips raw actor headers unless the request carries a valid JWT. Use an\n // explicit serviceToken if provided, otherwise mint a short-lived `service`\n // actor JWT (no-op when SERVICE_JWT_SECRET is unset → falls back to header\n // context for same-env/internal-gateway evaluation).\n const bearerToken = this.serviceToken ?? (await signServiceJwt(this.serviceName)) ?? undefined;\n\n // Fetch from API\n try {\n const response = await fetch(this.gatewayUrl, {\n method: 'POST',\n // Bounded: an unreachable gateway must cost milliseconds-to-seconds,\n // never the kernel's TCP connect timeout. On abort the catch below\n // negative-caches and callers fall back to their defaults.\n signal: AbortSignal.timeout(this.requestTimeoutMs),\n headers: {\n 'Content-Type': 'application/json',\n ...(context.actorId && { 'x-actor-id': context.actorId }),\n 'x-actor-type': context.actorType ?? this.defaultActorType,\n 'x-workspace-id': context.workspaceId,\n ...(bearerToken && { Authorization: `Bearer ${bearerToken}` }),\n // Re-present the inbound CF Access service token when the flag check\n // runs against a CF-Access-gated public gateway (alpha). No-op when\n // request context carries no CF creds (local dev, production).\n ...ContextManager.getCfAccessHeaders(),\n },\n body: JSON.stringify({\n query: EVALUATE_QUERY,\n variables: {\n input: {\n workspaceId: context.workspaceId,\n keys: keys ?? null,\n },\n },\n }),\n });\n\n if (!response.ok) {\n // Return empty map on error — default-allow handled by callers\n return this.rememberFailure(cacheKey);\n }\n\n const json = (await response.json()) as {\n data?: {\n evaluateFeatureFlags?: {\n evaluations?: FlagEvaluation[];\n };\n };\n errors?: Array<{ message: string }>;\n };\n\n if (json.errors || !json.data?.evaluateFeatureFlags?.evaluations) {\n return this.rememberFailure(cacheKey);\n }\n\n const evaluations = new Map<string, FlagEvaluation>();\n for (const evaluation of json.data.evaluateFeatureFlags.evaluations) {\n evaluations.set(evaluation.key, evaluation);\n }\n\n // Cache the results\n this.cache.set(cacheKey, {\n evaluations,\n expiresAt: Date.now() + this.cacheTtlMs,\n });\n\n return evaluations;\n } catch {\n // On network error/timeout, return empty map (default-allow handled by\n // callers) and negative-cache so the next evaluations in the window\n // skip the doomed request entirely.\n return this.rememberFailure(cacheKey);\n }\n }\n\n /**\n * Negative-cache a failed fetch: remember an empty evaluation set for\n * `failureTtlMs` so a broken/unreachable gateway costs at most one request\n * timeout per window instead of one per flag evaluation.\n */\n private rememberFailure(cacheKey: string): Map<string, FlagEvaluation> {\n const evaluations = new Map<string, FlagEvaluation>();\n this.cache.set(cacheKey, {\n evaluations,\n expiresAt: Date.now() + this.failureTtlMs,\n });\n return evaluations;\n }\n\n /**\n * Build a cache key from the evaluation context.\n *\n * Safe against undefined/null context — callers like isEnabled() may\n * pass no context during service boot (e.g. checking a default-allow\n * feature flag at startup before the first request builds a real\n * actor context). Without the guard, isEnabled(flag) used to throw\n * \"undefined is not an object (evaluating 'context.workspaceId')\"\n * and crash the svc at startServer().\n */\n private buildCacheKey(context: EvaluationContext | undefined): string {\n const ctx = context ?? ({} as EvaluationContext);\n return `${ctx.workspaceId ?? 'system'}:${ctx.actorId ?? 'anonymous'}:${ctx.actorType ?? 'user'}`;\n }\n}\n"]}
|