@teracrafts/flagkit 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types/flag.ts","../src/core/cache.ts","../src/types/context.ts","../src/core/context-manager.ts","../src/utils/platform.ts","../src/errors/error-codes.ts","../src/errors/error-sanitizer.ts","../src/errors/flagkit-error.ts","../src/http/circuit-breaker.ts","../src/http/retry.ts","../src/utils/security.ts","../src/http/http-client.ts","../src/core/polling-manager.ts","../src/core/streaming-manager.ts","../src/types/events.ts","../src/utils/validators.ts","../src/core/event-queue.ts","../src/utils/logger.ts","../src/utils/version.ts","../src/client.ts","../src/flagkit.ts","../src/storage/local-storage.ts","../src/storage/memory-storage.ts","../src/storage/encrypted-storage.ts","../src/index.ts"],"names":["createDefaultResult","flagKey","defaultValue","reason","DEFAULT_CACHE_CONFIG","FlagCache","config","key","entry","flag","ttl","now","flags","deleted","size","valid","validCount","staleCount","oldestKey","oldestTime","data","mergeContexts","base","override","stripPrivateAttributes","context","privateAttributes","rest","result","attr","customKey","ContextManager","logger","userId","attributes","evaluationContext","merged","detectPlatform","isBrowser","isNode","getSDKUserAgent","sdkVersion","platform","nodeVersion","generateSessionId","c","r","getCurrentTimestamp","ErrorCodes","RETRYABLE_ERROR_CODES","isRetryableCode","code","SANITIZATION_PATTERNS","globalSanitizationConfig","getGlobalSanitizationConfig","sanitizeErrorMessage","message","sanitized","pattern","replacement","freshPattern","sanitizeErrorDetails","details","value","FlagKitError","_FlagKitError","options","errorDef","rawMessage","sanitizationConfig","sanitizedMessage","json","InitializationError","_InitializationError","AuthenticationError","_AuthenticationError","NetworkError","_NetworkError","EvaluationError","_EvaluationError","SecurityError","_SecurityError","createErrorFromResponse","statusCode","body","retryAfter","requestId","isFlagKitError","error","isRetryableError","CircuitState","DEFAULT_CIRCUIT_BREAKER_CONFIG","CircuitOpenError","_CircuitOpenError","timeUntilReset","CircuitBreaker","operation","newState","previousState","DEFAULT_RETRY_CONFIG","calculateBackoff","attempt","exponentialDelay","cappedDelay","jitter","sleep","ms","resolve","withRetry","resolvedConfig","operationName","shouldRetry","onRetry","lastError","delay","parseRetryAfter","seconds","date","retryAt","PII_PATTERNS","isPotentialPIIField","fieldName","lowerName","detectPotentialPII","prefix","piiFields","fullPath","nestedPII","checkForPotentialPII","dataType","warnIfPotentialPII","isServerKey","apiKey","isClientKey","warnIfServerKeyInBrowser","DEFAULT_SECURITY_CONFIG","getKeyId","arrayBufferToHex","buffer","b","hmacSHA256WebCrypto","encoder","keyData","messageData","cryptoKey","signature","hmacSHA256Node","hmac","generateHMACSHA256","signPayload","timestamp","ts","payload","createRequestSignature","verifySignedPayload","signedPayload","maxAgeMs","age","expectedSignature","isProductionEnvironment","canonicalizeObject","obj","sortObjectKeys","sorted","keys","verifyBootstrapSignature","bootstrap","maxAge","canonicalFlags","constantTimeEqual","a","i","SDK_VERSION","BASE_URL","getBaseUrl","localPort","HttpClient","path","signingHeaders","bodyString","method","headers","timeout","skipRetry","skipCircuitBreaker","url","doRequest","requestHeaders","withKeyRotation","withCircuitBreaker","controller","timeoutId","response","responseHeaders","usageMetrics","normalizedPath","custom","apiUsage","evalUsage","rateLimitWarning","subscriptionStatus","metrics","parsed","apiKeyId","beaconPayload","blob","sent","DEFAULT_POLLING_CONFIG","PollingManager","DEFAULT_STREAMING_CONFIG","StreamingManager","tokenResponse","tokenUrl","delayMs","token","streamUrl","event","_event","errorData","baseDelay","backoff","checkInterval","timeSinceLastHeartbeat","state","DEFAULT_EVENT_QUEUE_CONFIG","API_KEY_PREFIXES","isValidApiKey","validateOptions","isValidFlagKey","isValidContext","ctx","isValidEventType","eventType","isValidEventData","EventQueue","id","eventData","events","requeue","_eventType","LOG_LEVEL_VALUES","ConsoleLogger","level","formatted","NoopLogger","createLogger","parseVersion","version","trimmed","match","major","minor","patch","compareVersions","parsedA","parsedB","isVersionLessThan","FlagKitClient","flagKitError","results","bootstrapFlags","cacheKeys","bootstrapKeys","piiResult","since","expectedType","cached","stale","_context","minMs","maxMs","bootstrapValue","bootstrapConfig","errorMessage","flagState","interval","baseUrl","metadata","FlagKit","_FlagKit","client","LocalStorage","testKey","MemoryStorage","ENCRYPTION_VERSION","IV_LENGTH","TAG_LENGTH","SALT","EncryptedStorage","keyMaterial","nodeCrypto","plaintext","iv","plaintextData","ciphertext","ciphertextArray","tag","encryptedData","cipher","encrypted","decoder","decipher","array","binary","base64","index_default"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Flag value types supported by FlagKit\n */\nexport type FlagType = 'boolean' | 'string' | 'number' | 'json';\n\n/**\n * Possible flag value\n */\nexport type FlagValue = boolean | string | number | Record<string, unknown>;\n\n/**\n * Reasons for an evaluation result\n */\nexport type EvaluationReason =\n | 'FLAG_NOT_FOUND'\n | 'FLAG_DISABLED'\n | 'ENVIRONMENT_NOT_CONFIGURED'\n | 'FALLTHROUGH'\n | 'RULE_MATCH'\n | 'SEGMENT_MATCH'\n | 'DEFAULT'\n | 'EVALUATION_ERROR'\n | 'CACHED'\n | 'STALE_CACHE'\n | 'BOOTSTRAP'\n | 'OFFLINE';\n\n/**\n * State of a feature flag returned from the API\n */\nexport interface FlagState {\n /** Unique flag key */\n key: string;\n\n /** Current flag value */\n value: FlagValue;\n\n /** Whether the flag is enabled */\n enabled: boolean;\n\n /** Flag version number */\n version: number;\n\n /** Type of the flag value */\n flagType: FlagType;\n\n /** Last modification timestamp */\n lastModified: string;\n}\n\n/**\n * Result of a flag evaluation\n */\nexport interface EvaluationResult<T = FlagValue> {\n /** The flag key that was evaluated */\n flagKey: string;\n\n /** The resolved flag value */\n value: T;\n\n /** Whether the flag is enabled */\n enabled: boolean;\n\n /** Reason for the evaluation result */\n reason: EvaluationReason;\n\n /** Variation ID if applicable */\n variationId?: string;\n\n /** Rule ID that matched */\n ruleId?: string;\n\n /** Segment ID that matched */\n segmentId?: string;\n\n /** Flag version at time of evaluation */\n version: number;\n\n /** Timestamp of evaluation */\n timestamp: Date;\n}\n\n/**\n * API response for SDK initialization\n */\nexport interface InitResponse {\n flags: FlagState[];\n environment: string;\n environmentId: string;\n projectId: string;\n organizationId: string;\n serverTime: string;\n pollingIntervalSeconds: number;\n streamingUrl: string | null;\n metadata: {\n /** Minimum SDK version required (older versions may not work) */\n sdkVersionMin?: string;\n /** Recommended SDK version for optimal experience */\n sdkVersionRecommended?: string;\n /** Latest available SDK version */\n sdkVersionLatest?: string;\n /** Deprecation warning message from server */\n deprecationWarning?: string | null;\n features: {\n streaming: boolean;\n localEval: boolean;\n experiments: boolean;\n segments: boolean;\n };\n };\n}\n\n/**\n * API response for flag evaluation\n */\nexport interface EvaluateResponse {\n flagKey: string;\n value: FlagValue;\n enabled: boolean;\n reason: EvaluationReason;\n variationId?: string;\n ruleId?: string;\n segmentId?: string;\n version: number;\n timestamp: string;\n}\n\n/**\n * API response for batch evaluation\n */\nexport interface BatchEvaluateResponse {\n flags: Record<string, EvaluateResponse>;\n evaluatedAt: string;\n}\n\n/**\n * API response for polling updates\n */\nexport interface UpdatesResponse {\n flags: FlagState[];\n checkedAt: string;\n since: string;\n}\n\n/**\n * Create an evaluation result from an API response\n */\nexport function createEvaluationResult<T extends FlagValue>(\n response: EvaluateResponse\n): EvaluationResult<T> {\n return {\n flagKey: response.flagKey,\n value: response.value as T,\n enabled: response.enabled,\n reason: response.reason,\n variationId: response.variationId,\n ruleId: response.ruleId,\n segmentId: response.segmentId,\n version: response.version,\n timestamp: new Date(response.timestamp),\n };\n}\n\n/**\n * Create a default evaluation result when using fallback\n */\nexport function createDefaultResult<T extends FlagValue>(\n flagKey: string,\n defaultValue: T,\n reason: EvaluationReason\n): EvaluationResult<T> {\n return {\n flagKey,\n value: defaultValue,\n enabled: false,\n reason,\n version: 0,\n timestamp: new Date(),\n };\n}\n","import type { FlagState } from '../types/flag';\nimport type { Logger } from '../utils/logger';\n\n/**\n * Cache entry with metadata\n */\nexport interface CacheEntry {\n /** The flag state */\n flag: FlagState;\n\n /** Unix timestamp when fetched */\n fetchedAt: number;\n\n /** Unix timestamp when entry expires */\n expiresAt: number;\n}\n\n/**\n * Cache configuration\n */\nexport interface CacheConfig {\n /** Time-to-live in milliseconds. Default: 300000 (5 minutes) */\n ttl: number;\n\n /** Maximum number of entries. Default: 1000 */\n maxSize: number;\n\n /** Logger instance */\n logger?: Logger;\n}\n\n/**\n * Default cache configuration\n */\nexport const DEFAULT_CACHE_CONFIG: Omit<CacheConfig, 'logger'> = {\n ttl: 300000,\n maxSize: 1000,\n};\n\n/**\n * In-memory cache for flag states with TTL support\n */\nexport class FlagCache {\n private readonly cache = new Map<string, CacheEntry>();\n private readonly config: CacheConfig;\n private readonly logger?: Logger;\n\n constructor(config?: Partial<CacheConfig>) {\n this.config = { ...DEFAULT_CACHE_CONFIG, ...config };\n this.logger = config?.logger;\n }\n\n /**\n * Get a flag from cache\n * @returns The cached flag state or null if not found/expired\n */\n get(key: string): FlagState | null {\n const entry = this.cache.get(key);\n\n if (!entry) {\n return null;\n }\n\n // Check if expired\n if (Date.now() > entry.expiresAt) {\n this.cache.delete(key);\n this.logger?.debug(`Cache miss (expired): ${key}`);\n return null;\n }\n\n this.logger?.debug(`Cache hit: ${key}`);\n return entry.flag;\n }\n\n /**\n * Get a cache entry with metadata\n */\n getEntry(key: string): CacheEntry | null {\n const entry = this.cache.get(key);\n\n if (!entry) {\n return null;\n }\n\n return entry;\n }\n\n /**\n * Check if a cached entry is stale (expired but still available)\n */\n isStale(key: string): boolean {\n const entry = this.cache.get(key);\n if (!entry) {\n return false;\n }\n return Date.now() > entry.expiresAt;\n }\n\n /**\n * Get a stale value (even if expired)\n * Useful for fallback when network is unavailable\n */\n getStale(key: string): FlagState | null {\n const entry = this.cache.get(key);\n return entry?.flag ?? null;\n }\n\n /**\n * Set a flag in cache\n */\n set(key: string, flag: FlagState, ttl?: number): void {\n // Enforce max size\n if (this.cache.size >= this.config.maxSize && !this.cache.has(key)) {\n this.evictOldest();\n }\n\n const now = Date.now();\n const entry: CacheEntry = {\n flag,\n fetchedAt: now,\n expiresAt: now + (ttl ?? this.config.ttl),\n };\n\n this.cache.set(key, entry);\n this.logger?.debug(`Cache set: ${key}`, { ttl: ttl ?? this.config.ttl });\n }\n\n /**\n * Set multiple flags in cache\n */\n setMany(flags: FlagState[], ttl?: number): void {\n for (const flag of flags) {\n this.set(flag.key, flag, ttl);\n }\n }\n\n /**\n * Delete a flag from cache\n */\n delete(key: string): boolean {\n const deleted = this.cache.delete(key);\n if (deleted) {\n this.logger?.debug(`Cache delete: ${key}`);\n }\n return deleted;\n }\n\n /**\n * Clear all entries from cache\n */\n clear(): void {\n const size = this.cache.size;\n this.cache.clear();\n this.logger?.debug(`Cache cleared: ${size} entries removed`);\n }\n\n /**\n * Get all cached flag keys\n */\n getAllKeys(): string[] {\n return Array.from(this.cache.keys());\n }\n\n /**\n * Get all valid (non-expired) flags\n */\n getAllValid(): FlagState[] {\n const now = Date.now();\n const valid: FlagState[] = [];\n\n for (const [key, entry] of this.cache.entries()) {\n if (now <= entry.expiresAt) {\n valid.push(entry.flag);\n } else {\n // Clean up expired entry\n this.cache.delete(key);\n }\n }\n\n return valid;\n }\n\n /**\n * Get all flags including stale ones\n */\n getAll(): FlagState[] {\n return Array.from(this.cache.values()).map((entry) => entry.flag);\n }\n\n /**\n * Check if flag exists in cache (valid or stale)\n */\n has(key: string): boolean {\n return this.cache.has(key);\n }\n\n /**\n * Get cache statistics\n */\n getStats(): {\n size: number;\n validCount: number;\n staleCount: number;\n maxSize: number;\n } {\n const now = Date.now();\n let validCount = 0;\n let staleCount = 0;\n\n for (const entry of this.cache.values()) {\n if (now <= entry.expiresAt) {\n validCount++;\n } else {\n staleCount++;\n }\n }\n\n return {\n size: this.cache.size,\n validCount,\n staleCount,\n maxSize: this.config.maxSize,\n };\n }\n\n /**\n * Evict the oldest entry from cache\n */\n private evictOldest(): void {\n let oldestKey: string | null = null;\n let oldestTime = Infinity;\n\n for (const [key, entry] of this.cache.entries()) {\n if (entry.fetchedAt < oldestTime) {\n oldestTime = entry.fetchedAt;\n oldestKey = key;\n }\n }\n\n if (oldestKey) {\n this.cache.delete(oldestKey);\n this.logger?.debug(`Cache evicted oldest: ${oldestKey}`);\n }\n }\n\n /**\n * Export cache data for persistence\n */\n export(): Record<string, CacheEntry> {\n const data: Record<string, CacheEntry> = {};\n for (const [key, entry] of this.cache.entries()) {\n data[key] = entry;\n }\n return data;\n }\n\n /**\n * Import cache data from persistence\n */\n import(data: Record<string, CacheEntry>): void {\n for (const [key, entry] of Object.entries(data)) {\n // Only import non-expired entries\n if (Date.now() <= entry.expiresAt) {\n this.cache.set(key, entry);\n }\n }\n this.logger?.debug(`Cache imported: ${this.cache.size} entries`);\n }\n}\n","/**\n * Evaluation context containing user and environment attributes\n * Used for targeting rules and personalization\n */\nexport interface EvaluationContext {\n /** Unique user identifier */\n userId?: string;\n\n /** Alternative user key (e.g., email hash) */\n userKey?: string;\n\n /** User email address */\n email?: string;\n\n /** User display name */\n name?: string;\n\n /** Whether the user is anonymous */\n anonymous?: boolean;\n\n /** ISO country code (e.g., \"US\", \"GB\") */\n country?: string;\n\n /** User IP address */\n ip?: string;\n\n /** Browser/device user agent string */\n userAgent?: string;\n\n /** Custom attributes for targeting */\n custom?: Record<string, unknown>;\n\n /** List of attribute names that should not be sent to the server */\n privateAttributes?: string[];\n}\n\n/**\n * Context with all attributes resolved for sending to API\n */\nexport interface ResolvedContext {\n userId?: string;\n userKey?: string;\n email?: string;\n name?: string;\n anonymous?: boolean;\n country?: string;\n ip?: string;\n userAgent?: string;\n custom?: Record<string, unknown>;\n}\n\n/**\n * Merge two contexts, with the second taking precedence\n */\nexport function mergeContexts(\n base: EvaluationContext | null | undefined,\n override: EvaluationContext | null | undefined\n): EvaluationContext | undefined {\n if (!base && !override) return undefined;\n if (!base) return override ?? undefined;\n if (!override) return base;\n\n return {\n ...base,\n ...override,\n custom: {\n ...base.custom,\n ...override.custom,\n },\n privateAttributes: [\n ...(base.privateAttributes ?? []),\n ...(override.privateAttributes ?? []),\n ],\n };\n}\n\n/**\n * Strip private attributes from context before sending to server\n */\nexport function stripPrivateAttributes(\n context: EvaluationContext\n): ResolvedContext {\n const { privateAttributes, ...rest } = context;\n const result: ResolvedContext = { ...rest };\n\n if (privateAttributes && privateAttributes.length > 0) {\n for (const attr of privateAttributes) {\n if (attr.startsWith('custom.') && result.custom) {\n const customKey = attr.slice(7);\n delete result.custom[customKey];\n } else if (attr in result) {\n delete result[attr as keyof ResolvedContext];\n }\n }\n }\n\n return result;\n}\n","import type { EvaluationContext, ResolvedContext } from '../types/context';\nimport { mergeContexts, stripPrivateAttributes } from '../types/context';\nimport type { Logger } from '../utils/logger';\n\n/**\n * Manages global and per-evaluation context\n */\nexport class ContextManager {\n private globalContext: EvaluationContext | null = null;\n private readonly logger?: Logger;\n\n constructor(logger?: Logger) {\n this.logger = logger;\n }\n\n /**\n * Set the global context\n */\n setContext(context: EvaluationContext): void {\n this.globalContext = context;\n this.logger?.debug('Global context set', {\n userId: context.userId,\n anonymous: context.anonymous,\n });\n }\n\n /**\n * Get the current global context\n */\n getContext(): EvaluationContext | null {\n return this.globalContext;\n }\n\n /**\n * Clear the global context\n */\n clearContext(): void {\n this.globalContext = null;\n this.logger?.debug('Global context cleared');\n }\n\n /**\n * Identify a user (sets userId and optional attributes)\n */\n identify(userId: string, attributes?: Partial<EvaluationContext>): void {\n this.globalContext = {\n ...this.globalContext,\n ...attributes,\n userId,\n anonymous: false,\n };\n this.logger?.debug('User identified', { userId });\n }\n\n /**\n * Reset to anonymous state\n */\n reset(): void {\n this.globalContext = {\n anonymous: true,\n };\n this.logger?.debug('Context reset to anonymous');\n }\n\n /**\n * Resolve context by merging global and evaluation context\n * Returns context with private attributes stripped\n */\n resolveContext(evaluationContext?: EvaluationContext): ResolvedContext | undefined {\n const merged = mergeContexts(this.globalContext, evaluationContext);\n\n if (!merged) {\n return undefined;\n }\n\n return stripPrivateAttributes(merged);\n }\n\n /**\n * Get raw merged context (with private attributes)\n */\n getMergedContext(evaluationContext?: EvaluationContext): EvaluationContext | undefined {\n return mergeContexts(this.globalContext, evaluationContext);\n }\n\n /**\n * Check if a user is identified\n */\n isIdentified(): boolean {\n return !!this.globalContext?.userId && !this.globalContext.anonymous;\n }\n\n /**\n * Check if user is anonymous\n */\n isAnonymous(): boolean {\n return !this.globalContext || this.globalContext.anonymous === true;\n }\n\n /**\n * Get current user ID if identified\n */\n getUserId(): string | undefined {\n return this.globalContext?.userId;\n }\n}\n","/**\n * Platform detection utilities for browser/Node.js environment\n */\n\n/**\n * Platform types\n */\nexport type Platform = 'browser' | 'node' | 'unknown';\n\n/**\n * Detect the current platform\n */\nexport function detectPlatform(): Platform {\n // Check for browser environment\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n return 'browser';\n }\n\n // Check for Node.js environment\n if (\n typeof process !== 'undefined' &&\n process.versions &&\n process.versions.node\n ) {\n return 'node';\n }\n\n return 'unknown';\n}\n\n/**\n * Check if running in browser\n */\nexport function isBrowser(): boolean {\n return detectPlatform() === 'browser';\n}\n\n/**\n * Check if running in Node.js\n */\nexport function isNode(): boolean {\n return detectPlatform() === 'node';\n}\n\n/**\n * Check if navigator.onLine is available and device is online\n */\nexport function isOnline(): boolean {\n if (isBrowser() && typeof navigator !== 'undefined') {\n return navigator.onLine;\n }\n // Assume online in Node.js (will be detected by network errors)\n return true;\n}\n\n/**\n * Get the user agent string if available\n */\nexport function getUserAgent(): string | undefined {\n if (isBrowser() && typeof navigator !== 'undefined') {\n return navigator.userAgent;\n }\n return undefined;\n}\n\n/**\n * Get the SDK user agent header value\n */\nexport function getSDKUserAgent(sdkVersion: string): string {\n const platform = detectPlatform();\n\n if (platform === 'browser') {\n return `FlagKit-JS/${sdkVersion} (Browser)`;\n }\n\n if (platform === 'node') {\n const nodeVersion =\n typeof process !== 'undefined' ? process.version : 'unknown';\n return `FlagKit-JS/${sdkVersion} (Node.js/${nodeVersion})`;\n }\n\n return `FlagKit-JS/${sdkVersion} (Unknown)`;\n}\n\n/**\n * Generate a unique session ID\n */\nexport function generateSessionId(): string {\n // Use crypto.randomUUID if available (modern browsers and Node.js 19+)\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n\n // Fallback for older environments\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\n/**\n * Get the current timestamp in ISO format\n */\nexport function getCurrentTimestamp(): string {\n return new Date().toISOString();\n}\n","/**\n * FlagKit SDK Error Codes\n * Based on the error specification at docs/spec/errors.spec.md\n */\n\n/**\n * Error categories with their numeric ranges\n */\nexport const ErrorCategory = {\n INIT: 1000,\n AUTH: 1100,\n EVAL: 1200,\n NETWORK: 1300,\n CACHE: 1400,\n EVENT: 1500,\n CONFIG: 1600,\n SECURITY: 1700,\n STREAMING: 1800,\n INTERNAL: 1900,\n} as const;\n\n/**\n * All error codes with their numeric values and default messages\n */\nexport const ErrorCodes = {\n // Initialization Errors (1000-1099)\n INIT_FAILED: {\n code: 'INIT_FAILED',\n numericCode: 1000,\n message: 'SDK initialization failed',\n recoverable: false,\n },\n INIT_TIMEOUT: {\n code: 'INIT_TIMEOUT',\n numericCode: 1001,\n message: 'Initialization timed out',\n recoverable: true,\n },\n INIT_INVALID_CONFIG: {\n code: 'INIT_INVALID_CONFIG',\n numericCode: 1002,\n message: 'Invalid SDK configuration',\n recoverable: false,\n },\n INIT_MISSING_API_KEY: {\n code: 'INIT_MISSING_API_KEY',\n numericCode: 1003,\n message: 'API key is required',\n recoverable: false,\n },\n INIT_INVALID_BASE_URL: {\n code: 'INIT_INVALID_BASE_URL',\n numericCode: 1004,\n message: 'Invalid base URL format',\n recoverable: false,\n },\n INIT_ALREADY_INITIALIZED: {\n code: 'INIT_ALREADY_INITIALIZED',\n numericCode: 1005,\n message: 'SDK already initialized',\n recoverable: false,\n },\n\n // Authentication Errors (1100-1199)\n AUTH_INVALID_KEY: {\n code: 'AUTH_INVALID_KEY',\n numericCode: 1100,\n message: 'Invalid API key',\n recoverable: false,\n },\n AUTH_EXPIRED_KEY: {\n code: 'AUTH_EXPIRED_KEY',\n numericCode: 1101,\n message: 'API key has expired',\n recoverable: false,\n },\n AUTH_REVOKED_KEY: {\n code: 'AUTH_REVOKED_KEY',\n numericCode: 1102,\n message: 'API key has been revoked',\n recoverable: false,\n },\n AUTH_INSUFFICIENT_PERMISSIONS: {\n code: 'AUTH_INSUFFICIENT_PERMISSIONS',\n numericCode: 1103,\n message: 'API key lacks required permissions',\n recoverable: false,\n },\n AUTH_RATE_LIMITED: {\n code: 'AUTH_RATE_LIMITED',\n numericCode: 1104,\n message: 'Rate limit exceeded',\n recoverable: true,\n },\n AUTH_PROJECT_MISMATCH: {\n code: 'AUTH_PROJECT_MISMATCH',\n numericCode: 1105,\n message: 'API key not valid for this project',\n recoverable: false,\n },\n AUTH_ENVIRONMENT_MISMATCH: {\n code: 'AUTH_ENVIRONMENT_MISMATCH',\n numericCode: 1106,\n message: 'API key not valid for this environment',\n recoverable: false,\n },\n AUTH_IP_RESTRICTED: {\n code: 'AUTH_IP_RESTRICTED',\n numericCode: 1107,\n message: 'IP address not allowed for this API key',\n recoverable: false,\n },\n AUTH_ORGANIZATION_REQUIRED: {\n code: 'AUTH_ORGANIZATION_REQUIRED',\n numericCode: 1108,\n message: 'Organization context missing from token',\n recoverable: false,\n },\n AUTH_SUBSCRIPTION_SUSPENDED: {\n code: 'AUTH_SUBSCRIPTION_SUSPENDED',\n numericCode: 1109,\n message: 'Subscription is suspended',\n recoverable: false,\n },\n\n // Evaluation Errors (1200-1299)\n EVAL_FLAG_NOT_FOUND: {\n code: 'EVAL_FLAG_NOT_FOUND',\n numericCode: 1200,\n message: 'Flag does not exist',\n recoverable: false,\n },\n EVAL_FLAG_DISABLED: {\n code: 'EVAL_FLAG_DISABLED',\n numericCode: 1201,\n message: 'Flag is disabled',\n recoverable: false,\n },\n EVAL_TYPE_MISMATCH: {\n code: 'EVAL_TYPE_MISMATCH',\n numericCode: 1202,\n message: 'Flag value type mismatch',\n recoverable: false,\n },\n EVAL_INVALID_CONTEXT: {\n code: 'EVAL_INVALID_CONTEXT',\n numericCode: 1203,\n message: 'Invalid evaluation context',\n recoverable: false,\n },\n EVAL_RULE_ERROR: {\n code: 'EVAL_RULE_ERROR',\n numericCode: 1204,\n message: 'Error evaluating targeting rule',\n recoverable: true,\n },\n EVAL_SEGMENT_ERROR: {\n code: 'EVAL_SEGMENT_ERROR',\n numericCode: 1205,\n message: 'Error evaluating segment',\n recoverable: true,\n },\n EVAL_DEFAULT_USED: {\n code: 'EVAL_DEFAULT_USED',\n numericCode: 1206,\n message: 'Using default value',\n recoverable: false,\n },\n EVAL_CACHED_VALUE: {\n code: 'EVAL_CACHED_VALUE',\n numericCode: 1207,\n message: 'Using cached value',\n recoverable: false,\n },\n EVAL_STALE_VALUE: {\n code: 'EVAL_STALE_VALUE',\n numericCode: 1208,\n message: 'Using stale cached value',\n recoverable: false,\n },\n\n // Network Errors (1300-1399)\n NETWORK_ERROR: {\n code: 'NETWORK_ERROR',\n numericCode: 1300,\n message: 'Network request failed',\n recoverable: true,\n },\n NETWORK_TIMEOUT: {\n code: 'NETWORK_TIMEOUT',\n numericCode: 1301,\n message: 'Request timed out',\n recoverable: true,\n },\n NETWORK_DNS_ERROR: {\n code: 'NETWORK_DNS_ERROR',\n numericCode: 1302,\n message: 'DNS resolution failed',\n recoverable: true,\n },\n NETWORK_CONNECTION_REFUSED: {\n code: 'NETWORK_CONNECTION_REFUSED',\n numericCode: 1303,\n message: 'Connection refused',\n recoverable: true,\n },\n NETWORK_SSL_ERROR: {\n code: 'NETWORK_SSL_ERROR',\n numericCode: 1304,\n message: 'SSL/TLS error',\n recoverable: false,\n },\n NETWORK_OFFLINE: {\n code: 'NETWORK_OFFLINE',\n numericCode: 1305,\n message: 'Device is offline',\n recoverable: true,\n },\n NETWORK_SERVER_ERROR: {\n code: 'NETWORK_SERVER_ERROR',\n numericCode: 1306,\n message: 'Server error',\n recoverable: true,\n },\n NETWORK_INVALID_RESPONSE: {\n code: 'NETWORK_INVALID_RESPONSE',\n numericCode: 1307,\n message: 'Invalid server response',\n recoverable: true,\n },\n NETWORK_SERVICE_UNAVAILABLE: {\n code: 'NETWORK_SERVICE_UNAVAILABLE',\n numericCode: 1308,\n message: 'Service unavailable',\n recoverable: true,\n },\n\n // Cache Errors (1400-1499)\n CACHE_READ_ERROR: {\n code: 'CACHE_READ_ERROR',\n numericCode: 1400,\n message: 'Failed to read from cache',\n recoverable: true,\n },\n CACHE_WRITE_ERROR: {\n code: 'CACHE_WRITE_ERROR',\n numericCode: 1401,\n message: 'Failed to write to cache',\n recoverable: true,\n },\n CACHE_EXPIRED: {\n code: 'CACHE_EXPIRED',\n numericCode: 1402,\n message: 'Cache has expired',\n recoverable: true,\n },\n CACHE_CORRUPT: {\n code: 'CACHE_CORRUPT',\n numericCode: 1403,\n message: 'Cache data is corrupted',\n recoverable: true,\n },\n CACHE_STORAGE_FULL: {\n code: 'CACHE_STORAGE_FULL',\n numericCode: 1404,\n message: 'Storage quota exceeded',\n recoverable: true,\n },\n\n // Event Errors (1500-1599)\n EVENT_SEND_FAILED: {\n code: 'EVENT_SEND_FAILED',\n numericCode: 1500,\n message: 'Failed to send event',\n recoverable: true,\n },\n EVENT_INVALID_TYPE: {\n code: 'EVENT_INVALID_TYPE',\n numericCode: 1501,\n message: 'Invalid event type',\n recoverable: false,\n },\n EVENT_INVALID_DATA: {\n code: 'EVENT_INVALID_DATA',\n numericCode: 1502,\n message: 'Invalid event data',\n recoverable: false,\n },\n EVENT_QUEUE_FULL: {\n code: 'EVENT_QUEUE_FULL',\n numericCode: 1503,\n message: 'Event queue is full',\n recoverable: true,\n },\n EVENT_BATCH_PARTIAL: {\n code: 'EVENT_BATCH_PARTIAL',\n numericCode: 1504,\n message: 'Some events failed to send',\n recoverable: true,\n },\n\n // Configuration Errors (1600-1699)\n CONFIG_INVALID_OPTION: {\n code: 'CONFIG_INVALID_OPTION',\n numericCode: 1600,\n message: 'Invalid configuration option',\n recoverable: false,\n },\n CONFIG_MISSING_REQUIRED: {\n code: 'CONFIG_MISSING_REQUIRED',\n numericCode: 1601,\n message: 'Missing required configuration',\n recoverable: false,\n },\n CONFIG_TYPE_ERROR: {\n code: 'CONFIG_TYPE_ERROR',\n numericCode: 1602,\n message: 'Configuration type mismatch',\n recoverable: false,\n },\n CONFIG_DEPRECATED: {\n code: 'CONFIG_DEPRECATED',\n numericCode: 1603,\n message: 'Configuration option deprecated',\n recoverable: false,\n },\n\n // Security Errors (1700-1799)\n SECURITY_ERROR: {\n code: 'SECURITY_ERROR',\n numericCode: 1700,\n message: 'Security violation detected',\n recoverable: false,\n },\n SECURITY_PII_DETECTED: {\n code: 'SECURITY_PII_DETECTED',\n numericCode: 1701,\n message: 'PII detected in data without privateAttributes',\n recoverable: false,\n },\n SECURITY_LOCAL_PORT_IN_PRODUCTION: {\n code: 'SECURITY_LOCAL_PORT_IN_PRODUCTION',\n numericCode: 1702,\n message: 'localPort cannot be used in production',\n recoverable: false,\n },\n SECURITY_KEY_ROTATION_FAILED: {\n code: 'SECURITY_KEY_ROTATION_FAILED',\n numericCode: 1703,\n message: 'Key rotation failed - both primary and secondary keys rejected',\n recoverable: false,\n },\n SECURITY_BOOTSTRAP_VERIFICATION_FAILED: {\n code: 'SECURITY_BOOTSTRAP_VERIFICATION_FAILED',\n numericCode: 1704,\n message: 'Bootstrap data signature verification failed',\n recoverable: false,\n },\n\n // Streaming Errors (1800-1899)\n STREAMING_TOKEN_INVALID: {\n code: 'STREAMING_TOKEN_INVALID',\n numericCode: 1800,\n message: 'Stream token is invalid',\n recoverable: true,\n },\n STREAMING_TOKEN_EXPIRED: {\n code: 'STREAMING_TOKEN_EXPIRED',\n numericCode: 1801,\n message: 'Stream token has expired',\n recoverable: true,\n },\n STREAMING_SUBSCRIPTION_SUSPENDED: {\n code: 'STREAMING_SUBSCRIPTION_SUSPENDED',\n numericCode: 1802,\n message: 'Organization subscription suspended',\n recoverable: false,\n },\n STREAMING_CONNECTION_LIMIT: {\n code: 'STREAMING_CONNECTION_LIMIT',\n numericCode: 1803,\n message: 'Too many concurrent streaming connections',\n recoverable: true,\n },\n STREAMING_UNAVAILABLE: {\n code: 'STREAMING_UNAVAILABLE',\n numericCode: 1804,\n message: 'Streaming service not available',\n recoverable: true,\n },\n\n // Internal Errors (1900-1999)\n INTERNAL_ERROR: {\n code: 'INTERNAL_ERROR',\n numericCode: 1900,\n message: 'Internal SDK error',\n recoverable: false,\n },\n INTERNAL_STATE_ERROR: {\n code: 'INTERNAL_STATE_ERROR',\n numericCode: 1901,\n message: 'Invalid internal state',\n recoverable: false,\n },\n UNKNOWN_ERROR: {\n code: 'UNKNOWN_ERROR',\n numericCode: 1999,\n message: 'Unknown error occurred',\n recoverable: false,\n },\n} as const;\n\nexport type ErrorCode = keyof typeof ErrorCodes;\n\n/**\n * Error codes that can be retried\n */\nexport const RETRYABLE_ERROR_CODES: ErrorCode[] = [\n 'INIT_TIMEOUT',\n 'AUTH_RATE_LIMITED',\n 'EVAL_RULE_ERROR',\n 'EVAL_SEGMENT_ERROR',\n 'NETWORK_ERROR',\n 'NETWORK_TIMEOUT',\n 'NETWORK_DNS_ERROR',\n 'NETWORK_CONNECTION_REFUSED',\n 'NETWORK_OFFLINE',\n 'NETWORK_SERVER_ERROR',\n 'NETWORK_INVALID_RESPONSE',\n 'NETWORK_SERVICE_UNAVAILABLE',\n 'CACHE_READ_ERROR',\n 'CACHE_WRITE_ERROR',\n 'CACHE_EXPIRED',\n 'CACHE_CORRUPT',\n 'CACHE_STORAGE_FULL',\n 'EVENT_SEND_FAILED',\n 'EVENT_QUEUE_FULL',\n 'EVENT_BATCH_PARTIAL',\n 'STREAMING_TOKEN_INVALID',\n 'STREAMING_TOKEN_EXPIRED',\n 'STREAMING_CONNECTION_LIMIT',\n 'STREAMING_UNAVAILABLE',\n];\n\n/**\n * Check if an error code is retryable\n */\nexport function isRetryableCode(code: ErrorCode): boolean {\n return RETRYABLE_ERROR_CODES.includes(code);\n}\n","/**\n * Error message sanitization utility\n *\n * Removes sensitive information from error messages to prevent\n * information leakage in logs, error reports, and user-facing messages.\n */\n\nimport type { ErrorSanitizationOptions } from '../types/config';\n\n/**\n * Pattern definition for sanitization\n */\ninterface SanitizationPattern {\n /** Regular expression to match sensitive data */\n pattern: RegExp;\n /** Replacement string */\n replacement: string;\n}\n\n/**\n * Default sanitization patterns for common sensitive data types\n */\nexport const SANITIZATION_PATTERNS: SanitizationPattern[] = [\n // Unix paths (e.g., /home/user/project/file.ts)\n { pattern: /\\/(?:[\\w.-]+\\/)+[\\w.-]+/g, replacement: '[PATH]' },\n // Windows paths (e.g., C:\\Users\\name\\project\\file.ts, C:\\Program Files\\App\\config.ini)\n { pattern: /[A-Za-z]:\\\\(?:[\\w\\s.-]+\\\\)+[\\w.-]*/g, replacement: '[PATH]' },\n // IPv4 addresses\n { pattern: /\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b/g, replacement: '[IP]' },\n // SDK keys (sdk_abc123...)\n { pattern: /sdk_[a-zA-Z0-9_-]{8,}/g, replacement: 'sdk_[REDACTED]' },\n // Server keys (srv_abc123...)\n { pattern: /srv_[a-zA-Z0-9_-]{8,}/g, replacement: 'srv_[REDACTED]' },\n // CLI keys (cli_abc123...)\n { pattern: /cli_[a-zA-Z0-9_-]{8,}/g, replacement: 'cli_[REDACTED]' },\n // Email addresses (including plus addressing like user+tag@example.com)\n { pattern: /[\\w.+-]+@[\\w.-]+\\.\\w+/g, replacement: '[EMAIL]' },\n // PostgreSQL connection strings\n { pattern: /postgres:\\/\\/[^\\s]+/gi, replacement: '[CONNECTION_STRING]' },\n // MySQL connection strings\n { pattern: /mysql:\\/\\/[^\\s]+/gi, replacement: '[CONNECTION_STRING]' },\n // MongoDB connection strings\n { pattern: /mongodb:\\/\\/[^\\s]+/gi, replacement: '[CONNECTION_STRING]' },\n // Redis connection strings\n { pattern: /redis:\\/\\/[^\\s]+/gi, replacement: '[CONNECTION_STRING]' },\n];\n\n/**\n * Global sanitization configuration\n * This can be set by the SDK client during initialization\n */\nlet globalSanitizationConfig: ErrorSanitizationOptions = {\n enabled: true,\n preserveOriginal: false,\n};\n\n/**\n * Set the global sanitization configuration\n * @param config - Sanitization options\n */\nexport function setGlobalSanitizationConfig(config: ErrorSanitizationOptions): void {\n globalSanitizationConfig = { ...globalSanitizationConfig, ...config };\n}\n\n/**\n * Get the current global sanitization configuration\n * @returns Current sanitization options\n */\nexport function getGlobalSanitizationConfig(): ErrorSanitizationOptions {\n return { ...globalSanitizationConfig };\n}\n\n/**\n * Reset the global sanitization configuration to defaults\n */\nexport function resetGlobalSanitizationConfig(): void {\n globalSanitizationConfig = {\n enabled: true,\n preserveOriginal: false,\n };\n}\n\n/**\n * Sanitize an error message by removing sensitive information\n *\n * @param message - The error message to sanitize\n * @param config - Optional sanitization configuration (uses global config if not provided)\n * @returns Sanitized message, or original if sanitization is disabled\n *\n * @example\n * ```typescript\n * sanitizeErrorMessage('Failed to load /home/user/config.json');\n * // Returns: 'Failed to load [PATH]'\n *\n * sanitizeErrorMessage('Connection to 192.168.1.100 failed');\n * // Returns: 'Connection to [IP] failed'\n *\n * sanitizeErrorMessage('Invalid key: sdk_abc123def456');\n * // Returns: 'Invalid key: sdk_[REDACTED]'\n * ```\n */\nexport function sanitizeErrorMessage(\n message: string,\n config?: ErrorSanitizationOptions\n): string {\n const effectiveConfig = config ?? globalSanitizationConfig;\n\n // If sanitization is disabled, return original message\n if (effectiveConfig.enabled === false) {\n return message;\n }\n\n let sanitized = message;\n\n // Apply all sanitization patterns\n for (const { pattern, replacement } of SANITIZATION_PATTERNS) {\n // Create a new RegExp to reset lastIndex for global patterns\n const freshPattern = new RegExp(pattern.source, pattern.flags);\n sanitized = sanitized.replace(freshPattern, replacement);\n }\n\n return sanitized;\n}\n\n/**\n * Sanitize error details object by removing sensitive information from string values\n *\n * @param details - The error details object to sanitize\n * @param config - Optional sanitization configuration\n * @returns Sanitized details object\n */\nexport function sanitizeErrorDetails(\n details: Record<string, unknown>,\n config?: ErrorSanitizationOptions\n): Record<string, unknown> {\n const effectiveConfig = config ?? globalSanitizationConfig;\n\n if (effectiveConfig.enabled === false) {\n return details;\n }\n\n const sanitized: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(details)) {\n if (typeof value === 'string') {\n sanitized[key] = sanitizeErrorMessage(value, config);\n } else if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n sanitized[key] = sanitizeErrorDetails(value as Record<string, unknown>, config);\n } else {\n sanitized[key] = value;\n }\n }\n\n return sanitized;\n}\n","import { ErrorCodes, type ErrorCode, isRetryableCode } from './error-codes';\nimport {\n sanitizeErrorMessage,\n sanitizeErrorDetails,\n getGlobalSanitizationConfig,\n} from './error-sanitizer';\nimport type { ErrorSanitizationOptions } from '../types/config';\n\n/**\n * Error details for additional context\n */\nexport interface ErrorDetails {\n [key: string]: unknown;\n}\n\n/**\n * Extended options for FlagKitError constructor\n */\nexport interface FlagKitErrorOptions {\n statusCode?: number;\n details?: ErrorDetails;\n retryAfter?: number;\n requestId?: string;\n cause?: Error;\n /** Override sanitization for this specific error */\n sanitization?: ErrorSanitizationOptions;\n}\n\n/**\n * Base error class for all FlagKit SDK errors\n */\nexport class FlagKitError extends Error {\n /** Error code string (e.g., \"NETWORK_TIMEOUT\") */\n readonly code: ErrorCode;\n\n /** Numeric error code (e.g., 1301) */\n readonly numericCode: number;\n\n /** HTTP status code if applicable */\n readonly statusCode?: number;\n\n /** Additional error details */\n readonly details?: ErrorDetails;\n\n /** Whether the operation can be retried */\n readonly recoverable: boolean;\n\n /** Seconds to wait before retrying (from Retry-After header) */\n readonly retryAfter?: number;\n\n /** Server request ID for debugging */\n readonly requestId?: string;\n\n /** Timestamp when error occurred */\n readonly timestamp: Date;\n\n /** Original unsanitized message (only set when preserveOriginal is true) */\n readonly originalMessage?: string;\n\n constructor(code: ErrorCode, message?: string, options?: FlagKitErrorOptions) {\n const errorDef = ErrorCodes[code];\n const rawMessage = message ?? errorDef.message;\n\n // Determine sanitization config (option override > global config)\n const sanitizationConfig = options?.sanitization ?? getGlobalSanitizationConfig();\n\n // Sanitize the message\n const sanitizedMessage = sanitizeErrorMessage(rawMessage, sanitizationConfig);\n\n super(sanitizedMessage, { cause: options?.cause });\n\n this.name = 'FlagKitError';\n this.code = code;\n this.numericCode = errorDef.numericCode;\n this.recoverable = isRetryableCode(code);\n this.statusCode = options?.statusCode;\n this.retryAfter = options?.retryAfter;\n this.requestId = options?.requestId;\n this.timestamp = new Date();\n\n // Sanitize details if provided\n this.details = options?.details\n ? sanitizeErrorDetails(options.details, sanitizationConfig)\n : undefined;\n\n // Preserve original message if configured (useful for debugging)\n if (sanitizationConfig.preserveOriginal && rawMessage !== sanitizedMessage) {\n this.originalMessage = rawMessage;\n }\n\n // Maintain proper prototype chain\n Object.setPrototypeOf(this, FlagKitError.prototype);\n }\n\n /**\n * Create a string representation of the error\n */\n toString(): string {\n return `[${this.code}] ${this.message}`;\n }\n\n /**\n * Convert error to JSON for logging/serialization\n */\n toJSON(): Record<string, unknown> {\n const json: Record<string, unknown> = {\n name: this.name,\n code: this.code,\n numericCode: this.numericCode,\n message: this.message,\n statusCode: this.statusCode,\n details: this.details,\n recoverable: this.recoverable,\n retryAfter: this.retryAfter,\n requestId: this.requestId,\n timestamp: this.timestamp.toISOString(),\n };\n\n // Include original message if preserved (for debugging)\n if (this.originalMessage) {\n json.originalMessage = this.originalMessage;\n }\n\n return json;\n }\n}\n\n/**\n * Initialization error - SDK cannot start\n */\nexport class InitializationError extends FlagKitError {\n constructor(\n code: Extract<\n ErrorCode,\n | 'INIT_FAILED'\n | 'INIT_TIMEOUT'\n | 'INIT_INVALID_CONFIG'\n | 'INIT_MISSING_API_KEY'\n | 'INIT_INVALID_BASE_URL'\n | 'INIT_ALREADY_INITIALIZED'\n >,\n message?: string,\n options?: {\n details?: ErrorDetails;\n cause?: Error;\n }\n ) {\n super(code, message, options);\n this.name = 'InitializationError';\n Object.setPrototypeOf(this, InitializationError.prototype);\n }\n}\n\n/**\n * Authentication error - API key issues\n */\nexport class AuthenticationError extends FlagKitError {\n constructor(\n code: Extract<\n ErrorCode,\n | 'AUTH_INVALID_KEY'\n | 'AUTH_EXPIRED_KEY'\n | 'AUTH_REVOKED_KEY'\n | 'AUTH_INSUFFICIENT_PERMISSIONS'\n | 'AUTH_RATE_LIMITED'\n | 'AUTH_PROJECT_MISMATCH'\n | 'AUTH_ENVIRONMENT_MISMATCH'\n >,\n message?: string,\n options?: {\n statusCode?: number;\n details?: ErrorDetails;\n retryAfter?: number;\n requestId?: string;\n }\n ) {\n super(code, message, options);\n this.name = 'AuthenticationError';\n Object.setPrototypeOf(this, AuthenticationError.prototype);\n }\n}\n\n/**\n * Network error - connectivity issues\n */\nexport class NetworkError extends FlagKitError {\n constructor(\n code: Extract<\n ErrorCode,\n | 'NETWORK_ERROR'\n | 'NETWORK_TIMEOUT'\n | 'NETWORK_DNS_ERROR'\n | 'NETWORK_CONNECTION_REFUSED'\n | 'NETWORK_SSL_ERROR'\n | 'NETWORK_OFFLINE'\n | 'NETWORK_SERVER_ERROR'\n | 'NETWORK_INVALID_RESPONSE'\n >,\n message?: string,\n options?: {\n statusCode?: number;\n details?: ErrorDetails;\n retryAfter?: number;\n requestId?: string;\n cause?: Error;\n }\n ) {\n super(code, message, options);\n this.name = 'NetworkError';\n Object.setPrototypeOf(this, NetworkError.prototype);\n }\n}\n\n/**\n * Evaluation error - flag evaluation issues\n */\nexport class EvaluationError extends FlagKitError {\n constructor(\n code: Extract<\n ErrorCode,\n | 'EVAL_FLAG_NOT_FOUND'\n | 'EVAL_FLAG_DISABLED'\n | 'EVAL_TYPE_MISMATCH'\n | 'EVAL_INVALID_CONTEXT'\n | 'EVAL_RULE_ERROR'\n | 'EVAL_SEGMENT_ERROR'\n | 'EVAL_DEFAULT_USED'\n | 'EVAL_CACHED_VALUE'\n | 'EVAL_STALE_VALUE'\n >,\n message?: string,\n options?: {\n details?: ErrorDetails;\n }\n ) {\n super(code, message, options);\n this.name = 'EvaluationError';\n Object.setPrototypeOf(this, EvaluationError.prototype);\n }\n}\n\n/**\n * Security error - security violations\n */\nexport class SecurityError extends FlagKitError {\n constructor(\n code: Extract<\n ErrorCode,\n | 'SECURITY_ERROR'\n | 'SECURITY_PII_DETECTED'\n | 'SECURITY_LOCAL_PORT_IN_PRODUCTION'\n | 'SECURITY_KEY_ROTATION_FAILED'\n | 'SECURITY_BOOTSTRAP_VERIFICATION_FAILED'\n >,\n message?: string,\n options?: {\n details?: ErrorDetails;\n }\n ) {\n super(code, message, options);\n this.name = 'SecurityError';\n Object.setPrototypeOf(this, SecurityError.prototype);\n }\n}\n\n/**\n * Create an error from an HTTP response\n */\nexport function createErrorFromResponse(\n statusCode: number,\n body?: { error?: string; message?: string; code?: string; requestId?: string },\n retryAfter?: number\n): FlagKitError {\n const requestId = body?.requestId;\n const message = body?.message ?? body?.error;\n\n switch (statusCode) {\n case 400:\n return new FlagKitError('EVAL_INVALID_CONTEXT', message, {\n statusCode,\n requestId,\n });\n case 401:\n return new AuthenticationError('AUTH_INVALID_KEY', message, {\n statusCode,\n requestId,\n });\n case 403:\n return new AuthenticationError('AUTH_INSUFFICIENT_PERMISSIONS', message, {\n statusCode,\n requestId,\n });\n case 404:\n return new EvaluationError('EVAL_FLAG_NOT_FOUND', message);\n case 429:\n return new AuthenticationError('AUTH_RATE_LIMITED', message, {\n statusCode,\n retryAfter,\n requestId,\n });\n default:\n if (statusCode >= 500) {\n return new NetworkError('NETWORK_SERVER_ERROR', message, {\n statusCode,\n retryAfter,\n requestId,\n });\n }\n return new FlagKitError('UNKNOWN_ERROR', message, {\n statusCode,\n requestId,\n });\n }\n}\n\n/**\n * Check if an error is a FlagKitError\n */\nexport function isFlagKitError(error: unknown): error is FlagKitError {\n return error instanceof FlagKitError;\n}\n\n/**\n * Check if an error is retryable\n */\nexport function isRetryableError(error: unknown): boolean {\n if (error instanceof FlagKitError) {\n return error.recoverable;\n }\n return false;\n}\n","import type { Logger } from '../utils/logger';\n\n/**\n * Circuit breaker states\n */\nexport enum CircuitState {\n /** Normal operation - requests are allowed */\n CLOSED = 'CLOSED',\n\n /** Circuit is open - requests are rejected */\n OPEN = 'OPEN',\n\n /** Testing recovery - limited requests allowed */\n HALF_OPEN = 'HALF_OPEN',\n}\n\n/**\n * Circuit breaker configuration\n */\nexport interface CircuitBreakerConfig {\n /** Number of failures before opening circuit. Default: 5 */\n failureThreshold: number;\n\n /** Time in ms before attempting recovery. Default: 30000 */\n resetTimeout: number;\n\n /** Number of successful requests in half-open to close circuit. Default: 1 */\n successThreshold: number;\n}\n\n/**\n * Default circuit breaker configuration\n */\nexport const DEFAULT_CIRCUIT_BREAKER_CONFIG: CircuitBreakerConfig = {\n failureThreshold: 5,\n resetTimeout: 30000,\n successThreshold: 1,\n};\n\n/**\n * Error thrown when circuit is open\n */\nexport class CircuitOpenError extends Error {\n readonly timeUntilReset: number;\n\n constructor(timeUntilReset: number) {\n super(`Circuit breaker is open. Reset in ${timeUntilReset}ms`);\n this.name = 'CircuitOpenError';\n this.timeUntilReset = timeUntilReset;\n Object.setPrototypeOf(this, CircuitOpenError.prototype);\n }\n}\n\n/**\n * Circuit breaker for protecting against cascading failures\n *\n * State transitions:\n * - CLOSED -> OPEN: When failures >= failureThreshold\n * - OPEN -> HALF_OPEN: After resetTimeout\n * - HALF_OPEN -> CLOSED: After successThreshold successes\n * - HALF_OPEN -> OPEN: On any failure\n */\nexport class CircuitBreaker {\n private state: CircuitState = CircuitState.CLOSED;\n private failures = 0;\n private successes = 0;\n private lastFailureTime = 0;\n private readonly config: CircuitBreakerConfig;\n private readonly logger?: Logger;\n\n constructor(config?: Partial<CircuitBreakerConfig>, logger?: Logger) {\n this.config = { ...DEFAULT_CIRCUIT_BREAKER_CONFIG, ...config };\n this.logger = logger;\n }\n\n /**\n * Get current circuit state\n */\n getState(): CircuitState {\n this.checkStateTransition();\n return this.state;\n }\n\n /**\n * Execute an operation through the circuit breaker\n */\n async execute<T>(operation: () => Promise<T>): Promise<T> {\n this.checkStateTransition();\n\n if (this.state === CircuitState.OPEN) {\n const timeUntilReset =\n this.config.resetTimeout - (Date.now() - this.lastFailureTime);\n throw new CircuitOpenError(Math.max(0, timeUntilReset));\n }\n\n try {\n const result = await operation();\n this.onSuccess();\n return result;\n } catch (error) {\n this.onFailure();\n throw error;\n }\n }\n\n /**\n * Record a success\n */\n onSuccess(): void {\n if (this.state === CircuitState.HALF_OPEN) {\n this.successes++;\n\n if (this.successes >= this.config.successThreshold) {\n this.transitionTo(CircuitState.CLOSED);\n this.reset();\n }\n } else if (this.state === CircuitState.CLOSED) {\n // Reset failure count on success in closed state\n this.failures = 0;\n }\n }\n\n /**\n * Record a failure\n */\n onFailure(): void {\n this.failures++;\n this.lastFailureTime = Date.now();\n\n if (this.state === CircuitState.HALF_OPEN) {\n // Any failure in half-open state opens the circuit\n this.transitionTo(CircuitState.OPEN);\n this.successes = 0;\n } else if (\n this.state === CircuitState.CLOSED &&\n this.failures >= this.config.failureThreshold\n ) {\n this.transitionTo(CircuitState.OPEN);\n }\n }\n\n /**\n * Manually reset the circuit breaker\n */\n reset(): void {\n this.state = CircuitState.CLOSED;\n this.failures = 0;\n this.successes = 0;\n this.lastFailureTime = 0;\n\n this.logger?.debug('Circuit breaker reset');\n }\n\n /**\n * Check if state should transition from OPEN to HALF_OPEN\n */\n private checkStateTransition(): void {\n if (this.state === CircuitState.OPEN) {\n const timeSinceLastFailure = Date.now() - this.lastFailureTime;\n\n if (timeSinceLastFailure >= this.config.resetTimeout) {\n this.transitionTo(CircuitState.HALF_OPEN);\n this.successes = 0;\n }\n }\n }\n\n /**\n * Transition to a new state\n */\n private transitionTo(newState: CircuitState): void {\n const previousState = this.state;\n this.state = newState;\n\n this.logger?.debug(`Circuit breaker state: ${previousState} -> ${newState}`, {\n failures: this.failures,\n successes: this.successes,\n });\n }\n\n /**\n * Get circuit breaker statistics\n */\n getStats(): {\n state: CircuitState;\n failures: number;\n successes: number;\n lastFailureTime: number;\n } {\n return {\n state: this.state,\n failures: this.failures,\n successes: this.successes,\n lastFailureTime: this.lastFailureTime,\n };\n }\n}\n","import type { Logger } from '../utils/logger';\nimport { isRetryableError } from '../errors/flagkit-error';\n\n/**\n * Retry configuration\n */\nexport interface RetryConfig {\n /** Maximum number of retry attempts. Default: 3 */\n maxAttempts: number;\n\n /** Base delay in milliseconds. Default: 1000 */\n baseDelay: number;\n\n /** Maximum delay in milliseconds. Default: 30000 */\n maxDelay: number;\n\n /** Backoff multiplier. Default: 2 */\n backoffMultiplier: number;\n\n /** Maximum jitter in milliseconds. Default: 100 */\n jitter: number;\n}\n\n/**\n * Default retry configuration\n */\nexport const DEFAULT_RETRY_CONFIG: RetryConfig = {\n maxAttempts: 3,\n baseDelay: 1000,\n maxDelay: 30000,\n backoffMultiplier: 2,\n jitter: 100,\n};\n\n/**\n * Calculate backoff delay with exponential backoff and jitter\n */\nexport function calculateBackoff(attempt: number, config: RetryConfig): number {\n // Exponential backoff: baseDelay * (multiplier ^ attempt)\n const exponentialDelay =\n config.baseDelay * Math.pow(config.backoffMultiplier, attempt - 1);\n\n // Cap at maxDelay\n const cappedDelay = Math.min(exponentialDelay, config.maxDelay);\n\n // Add jitter to prevent thundering herd\n const jitter = Math.random() * config.jitter;\n\n return cappedDelay + jitter;\n}\n\n/**\n * Sleep for the specified duration\n */\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Retry result wrapper\n */\nexport interface RetryResult<T> {\n success: boolean;\n value?: T;\n error?: Error;\n attempts: number;\n}\n\n/**\n * Execute an operation with retry logic\n */\nexport async function withRetry<T>(\n operation: () => Promise<T>,\n config: Partial<RetryConfig> = {},\n options?: {\n logger?: Logger;\n operationName?: string;\n shouldRetry?: (error: unknown) => boolean;\n onRetry?: (attempt: number, error: unknown, delay: number) => void;\n }\n): Promise<T> {\n const resolvedConfig: RetryConfig = {\n ...DEFAULT_RETRY_CONFIG,\n ...config,\n };\n\n const { logger, operationName = 'operation', shouldRetry, onRetry } = options ?? {};\n\n let lastError: Error | undefined;\n\n for (let attempt = 1; attempt <= resolvedConfig.maxAttempts; attempt++) {\n try {\n return await operation();\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n\n // Check if we should retry\n const canRetry = shouldRetry\n ? shouldRetry(error)\n : isRetryableError(error);\n\n if (!canRetry) {\n logger?.debug(`${operationName} failed with non-retryable error`, {\n error: lastError.message,\n attempt,\n });\n throw lastError;\n }\n\n // Check if we've exhausted retries\n if (attempt >= resolvedConfig.maxAttempts) {\n logger?.warn(`${operationName} failed after ${attempt} attempts`, {\n error: lastError.message,\n });\n throw lastError;\n }\n\n // Calculate and apply backoff\n const delay = calculateBackoff(attempt, resolvedConfig);\n\n logger?.debug(`${operationName} failed, retrying in ${delay}ms`, {\n attempt,\n maxAttempts: resolvedConfig.maxAttempts,\n error: lastError.message,\n delay,\n });\n\n // Call onRetry callback if provided\n onRetry?.(attempt, error, delay);\n\n // Wait before retrying\n await sleep(delay);\n }\n }\n\n // This should never be reached, but TypeScript needs it\n throw lastError ?? new Error('Retry failed');\n}\n\n/**\n * Parse Retry-After header value\n * Can be either a number of seconds or an HTTP date\n */\nexport function parseRetryAfter(value: string | null): number | undefined {\n if (!value) {\n return undefined;\n }\n\n // Try parsing as number of seconds\n const seconds = parseInt(value, 10);\n if (!isNaN(seconds) && seconds > 0) {\n return seconds;\n }\n\n // Try parsing as HTTP date\n const date = new Date(value);\n if (!isNaN(date.getTime())) {\n const now = Date.now();\n const retryAt = date.getTime();\n if (retryAt > now) {\n return Math.ceil((retryAt - now) / 1000);\n }\n }\n\n return undefined;\n}\n","/**\n * Security utilities for FlagKit SDK\n */\n\nimport type { Logger } from './logger';\nimport { isBrowser, isNode } from './platform';\n\n/**\n * Common PII field patterns (case-insensitive)\n */\nconst PII_PATTERNS = [\n 'email',\n 'phone',\n 'telephone',\n 'mobile',\n 'ssn',\n 'social_security',\n 'socialSecurity',\n 'credit_card',\n 'creditCard',\n 'card_number',\n 'cardNumber',\n 'cvv',\n 'password',\n 'passwd',\n 'secret',\n 'token',\n 'api_key',\n 'apiKey',\n 'private_key',\n 'privateKey',\n 'access_token',\n 'accessToken',\n 'refresh_token',\n 'refreshToken',\n 'auth_token',\n 'authToken',\n 'address',\n 'street',\n 'zip_code',\n 'zipCode',\n 'postal_code',\n 'postalCode',\n 'date_of_birth',\n 'dateOfBirth',\n 'dob',\n 'birth_date',\n 'birthDate',\n 'passport',\n 'driver_license',\n 'driverLicense',\n 'national_id',\n 'nationalId',\n 'bank_account',\n 'bankAccount',\n 'routing_number',\n 'routingNumber',\n 'iban',\n 'swift',\n];\n\n/**\n * Check if a field name potentially contains PII\n */\nexport function isPotentialPIIField(fieldName: string): boolean {\n const lowerName = fieldName.toLowerCase();\n return PII_PATTERNS.some((pattern) => lowerName.includes(pattern.toLowerCase()));\n}\n\n/**\n * Detect potential PII in an object and return the field names\n */\nexport function detectPotentialPII(\n data: Record<string, unknown>,\n prefix = ''\n): string[] {\n const piiFields: string[] = [];\n\n for (const [key, value] of Object.entries(data)) {\n const fullPath = prefix ? `${prefix}.${key}` : key;\n\n if (isPotentialPIIField(key)) {\n piiFields.push(fullPath);\n }\n\n // Recursively check nested objects\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n const nestedPII = detectPotentialPII(value as Record<string, unknown>, fullPath);\n piiFields.push(...nestedPII);\n }\n }\n\n return piiFields;\n}\n\n/**\n * PII detection result\n */\nexport interface PIIDetectionResult {\n hasPII: boolean;\n fields: string[];\n message: string;\n}\n\n/**\n * Check for potential PII in data and return detailed result\n */\nexport function checkForPotentialPII(\n data: Record<string, unknown> | undefined,\n dataType: 'context' | 'event'\n): PIIDetectionResult {\n if (!data) {\n return { hasPII: false, fields: [], message: '' };\n }\n\n const piiFields = detectPotentialPII(data);\n\n if (piiFields.length === 0) {\n return { hasPII: false, fields: [], message: '' };\n }\n\n const message =\n `[FlagKit Security] Potential PII detected in ${dataType} data: ${piiFields.join(', ')}. ` +\n (dataType === 'context'\n ? 'Consider adding these to privateAttributes.'\n : 'Consider removing sensitive data from events.');\n\n return { hasPII: true, fields: piiFields, message };\n}\n\n/**\n * Warn about potential PII in data\n */\nexport function warnIfPotentialPII(\n data: Record<string, unknown> | undefined,\n dataType: 'context' | 'event',\n logger?: Logger\n): void {\n if (!data || !logger) {\n return;\n }\n\n const result = checkForPotentialPII(data, dataType);\n\n if (result.hasPII) {\n logger.warn(result.message);\n }\n}\n\n/**\n * Check if an API key is a server key\n */\nexport function isServerKey(apiKey: string): boolean {\n return apiKey.startsWith('srv_');\n}\n\n/**\n * Check if an API key is a client/SDK key\n */\nexport function isClientKey(apiKey: string): boolean {\n return apiKey.startsWith('sdk_') || apiKey.startsWith('cli_');\n}\n\n/**\n * Warn if server key is used in browser environment\n */\nexport function warnIfServerKeyInBrowser(apiKey: string, logger?: Logger): void {\n if (isBrowser() && isServerKey(apiKey)) {\n const message =\n '[FlagKit Security] WARNING: Server keys (srv_) should not be used in browser environments. ' +\n 'This exposes your server key in client-side code, which is a security risk. ' +\n 'Use SDK keys (sdk_) for client-side applications instead. ' +\n 'See: https://docs.flagkit.dev/sdk/security#api-keys';\n\n // Always log to console for visibility\n console.warn(message);\n\n // Also log through the SDK logger if available\n logger?.warn(message);\n }\n}\n\n/**\n * Security configuration options\n */\nexport interface SecurityConfig {\n /** Warn about potential PII in context/events. Default: true in development */\n warnOnPotentialPII?: boolean;\n\n /** Warn when server keys are used in browser. Default: true */\n warnOnServerKeyInBrowser?: boolean;\n\n /** Custom PII patterns to detect */\n additionalPIIPatterns?: string[];\n}\n\n/**\n * Default security configuration\n */\nexport const DEFAULT_SECURITY_CONFIG: Required<SecurityConfig> = {\n warnOnPotentialPII: process?.env?.NODE_ENV !== 'production',\n warnOnServerKeyInBrowser: true,\n additionalPIIPatterns: [],\n};\n\n/**\n * Signed payload structure for beacon requests\n */\nexport interface SignedPayload<T = unknown> {\n data: T;\n signature: string;\n timestamp: number;\n keyId: string;\n}\n\n/**\n * Get the first 8 characters of an API key for identification\n * This is safe to expose as it doesn't reveal the full key\n */\nexport function getKeyId(apiKey: string): string {\n return apiKey.substring(0, 8);\n}\n\n/**\n * Convert ArrayBuffer to hex string\n */\nfunction arrayBufferToHex(buffer: ArrayBuffer): string {\n return Array.from(new Uint8Array(buffer))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n}\n\n/**\n * Generate HMAC-SHA256 signature using Web Crypto API (browser)\n */\nasync function hmacSHA256WebCrypto(\n message: string,\n key: string\n): Promise<string> {\n const encoder = new TextEncoder();\n const keyData = encoder.encode(key);\n const messageData = encoder.encode(message);\n\n const cryptoKey = await crypto.subtle.importKey(\n 'raw',\n keyData.buffer as ArrayBuffer,\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign']\n );\n\n const signature = await crypto.subtle.sign('HMAC', cryptoKey, messageData.buffer as ArrayBuffer);\n return arrayBufferToHex(signature);\n}\n\n/**\n * Generate HMAC-SHA256 signature using Node.js crypto module\n */\nasync function hmacSHA256Node(message: string, key: string): Promise<string> {\n // Dynamic import for Node.js crypto\n const nodeCrypto = await import('crypto');\n const hmac = nodeCrypto.createHmac('sha256', key);\n hmac.update(message);\n return hmac.digest('hex');\n}\n\n/**\n * Generate HMAC-SHA256 signature\n * Uses Web Crypto API in browser, Node.js crypto in server\n */\nexport async function generateHMACSHA256(\n message: string,\n key: string\n): Promise<string> {\n if (isBrowser()) {\n return hmacSHA256WebCrypto(message, key);\n }\n\n if (isNode()) {\n return hmacSHA256Node(message, key);\n }\n\n // Fallback for unknown environments - try Web Crypto first\n if (typeof crypto !== 'undefined' && crypto.subtle) {\n return hmacSHA256WebCrypto(message, key);\n }\n\n throw new Error('No cryptographic implementation available');\n}\n\n/**\n * Sign a payload with HMAC-SHA256\n */\nexport async function signPayload<T>(\n data: T,\n apiKey: string,\n timestamp?: number\n): Promise<SignedPayload<T>> {\n const ts = timestamp ?? Date.now();\n const payload = JSON.stringify(data);\n const message = `${ts}.${payload}`;\n const signature = await generateHMACSHA256(message, apiKey);\n\n return {\n data,\n signature,\n timestamp: ts,\n keyId: getKeyId(apiKey),\n };\n}\n\n/**\n * Create signature string for request headers\n * Format: timestamp.signature\n */\nexport async function createRequestSignature(\n body: string,\n apiKey: string,\n timestamp?: number\n): Promise<{ signature: string; timestamp: number }> {\n const ts = timestamp ?? Date.now();\n const message = `${ts}.${body}`;\n const signature = await generateHMACSHA256(message, apiKey);\n\n return { signature, timestamp: ts };\n}\n\n/**\n * Verify a signed payload (for testing/debugging)\n */\nexport async function verifySignedPayload<T>(\n signedPayload: SignedPayload<T>,\n apiKey: string,\n maxAgeMs: number = 300000 // 5 minutes default\n): Promise<boolean> {\n // Check timestamp age\n const age = Date.now() - signedPayload.timestamp;\n if (age > maxAgeMs || age < 0) {\n return false;\n }\n\n // Verify key ID matches\n if (signedPayload.keyId !== getKeyId(apiKey)) {\n return false;\n }\n\n // Verify signature\n const payload = JSON.stringify(signedPayload.data);\n const message = `${signedPayload.timestamp}.${payload}`;\n const expectedSignature = await generateHMACSHA256(message, apiKey);\n\n return signedPayload.signature === expectedSignature;\n}\n\n/**\n * Check if environment is production\n */\nexport function isProductionEnvironment(): boolean {\n if (typeof process !== 'undefined' && process.env) {\n return process.env.NODE_ENV === 'production';\n }\n return false;\n}\n\n/**\n * Result of bootstrap signature verification\n */\nexport interface BootstrapVerificationResult {\n /** Whether the signature is valid */\n valid: boolean;\n /** Error message if verification failed */\n error?: string;\n}\n\n/**\n * Bootstrap configuration structure for verification\n */\nexport interface BootstrapConfigForVerification {\n flags: Record<string, unknown>;\n signature?: string;\n timestamp?: number;\n}\n\n/**\n * Options for bootstrap verification\n */\nexport interface BootstrapVerifyOptions {\n enabled?: boolean;\n maxAge?: number;\n onFailure?: 'warn' | 'error' | 'ignore';\n}\n\n/**\n * Canonicalize an object for consistent signature verification.\n * Sorts keys recursively and stringifies with no whitespace.\n */\nexport function canonicalizeObject(obj: Record<string, unknown>): string {\n return JSON.stringify(sortObjectKeys(obj));\n}\n\n/**\n * Recursively sort object keys for canonical representation\n */\nfunction sortObjectKeys(obj: unknown): unknown {\n if (obj === null || obj === undefined) {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map(sortObjectKeys);\n }\n\n if (typeof obj === 'object') {\n const sorted: Record<string, unknown> = {};\n const keys = Object.keys(obj as Record<string, unknown>).sort();\n for (const key of keys) {\n sorted[key] = sortObjectKeys((obj as Record<string, unknown>)[key]);\n }\n return sorted;\n }\n\n return obj;\n}\n\n/**\n * Verify the HMAC-SHA256 signature of bootstrap flag values.\n *\n * The signature is computed as: HMAC-SHA256(canonicalize(flags), apiKey)\n *\n * @param bootstrap - Bootstrap configuration with flags, signature, and optional timestamp\n * @param apiKey - API key used as HMAC secret\n * @param options - Verification options\n * @returns Verification result with valid flag and optional error message\n */\nexport async function verifyBootstrapSignature(\n bootstrap: BootstrapConfigForVerification,\n apiKey: string,\n options?: BootstrapVerifyOptions\n): Promise<BootstrapVerificationResult> {\n const maxAge = options?.maxAge ?? 86400000; // 24 hours default\n\n // No signature to verify\n if (!bootstrap.signature) {\n return { valid: true };\n }\n\n // Check timestamp if present\n if (bootstrap.timestamp !== undefined) {\n const age = Date.now() - bootstrap.timestamp;\n\n // Reject if timestamp is in the future (with 5 minute tolerance for clock skew)\n if (age < -300000) {\n return {\n valid: false,\n error: `Bootstrap timestamp is in the future: ${new Date(bootstrap.timestamp).toISOString()}`,\n };\n }\n\n // Reject if too old\n if (age > maxAge) {\n const ageHours = Math.floor(age / 3600000);\n return {\n valid: false,\n error: `Bootstrap data is expired: ${ageHours} hours old (max: ${Math.floor(maxAge / 3600000)} hours)`,\n };\n }\n }\n\n // Compute expected signature\n const canonicalFlags = canonicalizeObject(bootstrap.flags);\n const expectedSignature = await generateHMACSHA256(canonicalFlags, apiKey);\n\n // Compare signatures (constant-time comparison to prevent timing attacks)\n if (!constantTimeEqual(bootstrap.signature, expectedSignature)) {\n return {\n valid: false,\n error: 'Bootstrap signature verification failed: signature does not match',\n };\n }\n\n return { valid: true };\n}\n\n/**\n * Constant-time string comparison to prevent timing attacks\n */\nfunction constantTimeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) {\n return false;\n }\n\n let result = 0;\n for (let i = 0; i < a.length; i++) {\n result |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n return result === 0;\n}\n","import type { Logger } from '../utils/logger';\nimport { getSDKUserAgent, isBrowser } from '../utils/platform';\nimport {\n NetworkError,\n AuthenticationError,\n createErrorFromResponse,\n} from '../errors/flagkit-error';\nimport { CircuitBreaker, CircuitOpenError } from './circuit-breaker';\nimport { withRetry, parseRetryAfter } from './retry';\nimport type { RetryConfig } from './retry';\nimport type { CircuitBreakerConfig } from './circuit-breaker';\nimport {\n signPayload,\n createRequestSignature,\n getKeyId,\n} from '../utils/security';\n\n/**\n * SDK version - should be updated with releases\n */\nexport const SDK_VERSION = '1.0.0';\n\n/**\n * Default FlagKit API base URL\n */\nexport const BASE_URL = 'https://api.flagkit.dev/api/v1';\n\n/**\n * Get the base URL for API requests\n * @param localPort - When set, uses http://localhost:{port}/api/v1\n */\nexport const getBaseUrl = (localPort?: number): string =>\n localPort ? `http://localhost:${localPort}/api/v1` : BASE_URL;\n\n/**\n * HTTP request options\n */\nexport interface RequestOptions {\n /** HTTP method */\n method?: 'GET' | 'POST' | 'PUT' | 'DELETE';\n\n /** Request headers */\n headers?: Record<string, string>;\n\n /** Request body (will be JSON serialized) */\n body?: unknown;\n\n /** Request timeout in ms */\n timeout?: number;\n\n /** Skip retry logic */\n skipRetry?: boolean;\n\n /** Skip circuit breaker */\n skipCircuitBreaker?: boolean;\n}\n\n/**\n * HTTP response wrapper\n */\nexport interface HttpResponse<T = unknown> {\n /** Response status code */\n status: number;\n\n /** Response headers */\n headers: Record<string, string>;\n\n /** Parsed response body */\n data: T;\n\n /** Server request ID if available */\n requestId?: string;\n\n /** Usage metrics from response headers */\n usageMetrics?: UsageMetrics;\n}\n\n/**\n * Usage metrics extracted from response headers\n */\nexport interface UsageMetrics {\n /** Percentage of API call limit used this period (0-150+) */\n apiUsagePercent?: number;\n\n /** Percentage of evaluation limit used (0-150+) */\n evaluationUsagePercent?: number;\n\n /** Whether approaching rate limit threshold */\n rateLimitWarning: boolean;\n\n /** Current subscription status */\n subscriptionStatus?: 'active' | 'trial' | 'past_due' | 'suspended' | 'cancelled';\n}\n\n/**\n * Usage update callback type\n */\nexport type UsageUpdateCallback = (metrics: UsageMetrics) => void;\n\n/**\n * HTTP client configuration\n */\nexport interface HttpClientConfig {\n /** Base URL for all requests */\n baseUrl: string;\n\n /** API key for authentication */\n apiKey: string;\n\n /** Secondary API key for key rotation */\n secondaryApiKey?: string;\n\n /** Grace period for key rotation in ms. Default: 300000 (5 minutes) */\n keyRotationGracePeriod?: number;\n\n /** Default request timeout in ms */\n timeout: number;\n\n /** Retry configuration */\n retry: Partial<RetryConfig>;\n\n /** Circuit breaker configuration */\n circuitBreaker: Partial<CircuitBreakerConfig>;\n\n /** Logger instance */\n logger?: Logger;\n\n /** Enable request signing for POST requests. Default: true */\n enableRequestSigning?: boolean;\n\n /** Callback for usage metrics updates */\n onUsageUpdate?: UsageUpdateCallback;\n}\n\n/**\n * HTTP client for FlagKit API communication\n *\n * Features:\n * - Automatic retry with exponential backoff\n * - Circuit breaker for failure protection\n * - Request timeout handling\n * - Rate limit header parsing\n * - HMAC-SHA256 request signing for POST requests\n * - Signed beacon payloads for page unload events\n * - Key rotation support with automatic failover\n */\nexport class HttpClient {\n private readonly config: HttpClientConfig;\n private readonly circuitBreaker: CircuitBreaker;\n private readonly logger?: Logger;\n private currentApiKey: string;\n private keyRotationTimestamp: number | null = null;\n\n constructor(config: HttpClientConfig) {\n this.config = {\n ...config,\n keyRotationGracePeriod: config.keyRotationGracePeriod ?? 300000,\n enableRequestSigning: config.enableRequestSigning ?? true,\n };\n this.currentApiKey = config.apiKey;\n this.logger = config.logger;\n this.circuitBreaker = new CircuitBreaker(\n config.circuitBreaker,\n config.logger\n );\n }\n\n /**\n * Get the current active API key\n */\n getActiveApiKey(): string {\n return this.currentApiKey;\n }\n\n /**\n * Get the key identifier (first 8 chars) for the current key\n */\n getKeyId(): string {\n return getKeyId(this.currentApiKey);\n }\n\n /**\n * Check if key rotation is currently active\n */\n isInKeyRotation(): boolean {\n if (!this.keyRotationTimestamp) {\n return false;\n }\n const elapsed = Date.now() - this.keyRotationTimestamp;\n return elapsed < (this.config.keyRotationGracePeriod ?? 300000);\n }\n\n /**\n * Rotate to secondary API key\n */\n private rotateToSecondaryKey(): boolean {\n if (!this.config.secondaryApiKey) {\n return false;\n }\n\n if (this.currentApiKey === this.config.secondaryApiKey) {\n // Already using secondary key\n return false;\n }\n\n this.logger?.info('Rotating to secondary API key due to authentication failure');\n this.currentApiKey = this.config.secondaryApiKey;\n this.keyRotationTimestamp = Date.now();\n return true;\n }\n\n /**\n * Handle key rotation on authentication failure\n * Returns true if rotation was performed and request should be retried\n */\n private async handleAuthFailure(): Promise<boolean> {\n return this.rotateToSecondaryKey();\n }\n\n /**\n * Make a GET request\n */\n async get<T>(\n path: string,\n options?: Omit<RequestOptions, 'method' | 'body'>\n ): Promise<HttpResponse<T>> {\n return this.request<T>(path, { ...options, method: 'GET' });\n }\n\n /**\n * Make a POST request with automatic signing\n */\n async post<T>(\n path: string,\n body?: unknown,\n options?: Omit<RequestOptions, 'method'>\n ): Promise<HttpResponse<T>> {\n // Add signing headers for POST requests\n const signingHeaders: Record<string, string> = {};\n\n if (this.config.enableRequestSigning && body) {\n try {\n const bodyString = JSON.stringify(body);\n const { signature, timestamp } = await createRequestSignature(\n bodyString,\n this.currentApiKey\n );\n signingHeaders['X-Signature'] = signature;\n signingHeaders['X-Timestamp'] = timestamp.toString();\n signingHeaders['X-Key-Id'] = this.getKeyId();\n } catch (error) {\n this.logger?.warn('Failed to sign request, proceeding without signature', {\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n }\n\n return this.request<T>(path, {\n ...options,\n method: 'POST',\n body,\n headers: {\n ...signingHeaders,\n ...options?.headers,\n },\n });\n }\n\n /**\n * Make an HTTP request\n */\n async request<T>(path: string, options: RequestOptions = {}): Promise<HttpResponse<T>> {\n const {\n method = 'GET',\n headers = {},\n body,\n timeout = this.config.timeout,\n skipRetry = false,\n skipCircuitBreaker = false,\n } = options;\n\n const url = this.buildUrl(path);\n\n const doRequest = async (): Promise<HttpResponse<T>> => {\n // Build headers with current API key (may change during key rotation)\n const requestHeaders = this.buildHeaders(headers);\n\n return this.executeRequest<T>(url, {\n method,\n headers: requestHeaders,\n body,\n timeout,\n });\n };\n\n // Wrap with key rotation support\n const withKeyRotation = async (): Promise<HttpResponse<T>> => {\n try {\n return await doRequest();\n } catch (error) {\n // Handle 401 errors with key rotation\n if (\n error instanceof AuthenticationError &&\n error.code === 'AUTH_INVALID_KEY' &&\n this.config.secondaryApiKey\n ) {\n const rotated = await this.handleAuthFailure();\n if (rotated) {\n this.logger?.debug('Retrying request with secondary API key');\n return doRequest();\n }\n }\n throw error;\n }\n };\n\n // Wrap with circuit breaker if enabled\n const withCircuitBreaker = skipCircuitBreaker\n ? withKeyRotation\n : () => this.circuitBreaker.execute(withKeyRotation);\n\n // Wrap with retry if enabled\n if (skipRetry) {\n return withCircuitBreaker();\n }\n\n return withRetry(withCircuitBreaker, this.config.retry, {\n logger: this.logger,\n operationName: `${method} ${path}`,\n shouldRetry: (error) => {\n // Don't retry circuit open errors\n if (error instanceof CircuitOpenError) {\n return false;\n }\n // Don't retry auth errors (key rotation already attempted)\n if (error instanceof AuthenticationError) {\n return false;\n }\n // Retry network errors\n if (error instanceof NetworkError) {\n return error.recoverable;\n }\n return false;\n },\n });\n }\n\n /**\n * Execute a single HTTP request\n */\n private async executeRequest<T>(\n url: string,\n options: {\n method: string;\n headers: Record<string, string>;\n body?: unknown;\n timeout: number;\n }\n ): Promise<HttpResponse<T>> {\n const { method, headers, body, timeout } = options;\n\n // Create abort controller for timeout\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n this.logger?.debug(`HTTP ${method} ${url}`, {\n hasBody: !!body,\n timeout,\n });\n\n const response = await fetch(url, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n // Extract headers\n const responseHeaders: Record<string, string> = {};\n response.headers.forEach((value, key) => {\n responseHeaders[key.toLowerCase()] = value;\n });\n\n const requestId = responseHeaders['x-request-id'];\n\n // Parse response body\n let data: T;\n const contentType = responseHeaders['content-type'] ?? '';\n\n if (contentType.includes('application/json')) {\n data = (await response.json()) as T;\n } else {\n data = (await response.text()) as unknown as T;\n }\n\n // Handle error responses\n if (!response.ok) {\n const retryAfter = parseRetryAfter(\n responseHeaders['retry-after'] ?? null\n );\n\n throw createErrorFromResponse(\n response.status,\n data as { error?: string; message?: string; requestId?: string },\n retryAfter\n );\n }\n\n // Extract usage metrics from headers\n const usageMetrics = this.extractUsageMetrics(responseHeaders);\n if (usageMetrics && this.config.onUsageUpdate) {\n this.config.onUsageUpdate(usageMetrics);\n }\n\n this.logger?.debug(`HTTP ${method} ${url} -> ${response.status}`, {\n requestId,\n });\n\n return {\n status: response.status,\n headers: responseHeaders,\n data,\n requestId,\n usageMetrics,\n };\n } catch (error) {\n clearTimeout(timeoutId);\n\n // Handle abort (timeout)\n if (error instanceof Error && error.name === 'AbortError') {\n throw new NetworkError(\n 'NETWORK_TIMEOUT',\n `Request timed out after ${timeout}ms`\n );\n }\n\n // Handle fetch errors\n if (error instanceof TypeError) {\n throw new NetworkError('NETWORK_ERROR', error.message, {\n cause: error,\n });\n }\n\n // Re-throw FlagKit errors\n throw error;\n }\n }\n\n /**\n * Build full URL from path\n */\n private buildUrl(path: string): string {\n const base = this.config.baseUrl.replace(/\\/+$/, '');\n const normalizedPath = path.startsWith('/') ? path : `/${path}`;\n return `${base}${normalizedPath}`;\n }\n\n /**\n * Build request headers\n */\n private buildHeaders(custom: Record<string, string> = {}): Record<string, string> {\n return {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n 'X-API-Key': this.currentApiKey,\n 'User-Agent': getSDKUserAgent(SDK_VERSION),\n 'X-FlagKit-SDK-Version': SDK_VERSION,\n 'X-FlagKit-SDK-Language': 'typescript',\n ...custom,\n };\n }\n\n /**\n * Extract usage metrics from response headers\n */\n private extractUsageMetrics(headers: Record<string, string>): UsageMetrics | undefined {\n const apiUsage = headers['x-api-usage-percent'];\n const evalUsage = headers['x-evaluation-usage-percent'];\n const rateLimitWarning = headers['x-rate-limit-warning'];\n const subscriptionStatus = headers['x-subscription-status'];\n\n // Return undefined if no usage headers present\n if (!apiUsage && !evalUsage && !rateLimitWarning && !subscriptionStatus) {\n return undefined;\n }\n\n const metrics: UsageMetrics = {\n rateLimitWarning: rateLimitWarning === 'true',\n };\n\n if (apiUsage) {\n const parsed = parseFloat(apiUsage);\n if (!isNaN(parsed)) {\n metrics.apiUsagePercent = parsed;\n }\n }\n\n if (evalUsage) {\n const parsed = parseFloat(evalUsage);\n if (!isNaN(parsed)) {\n metrics.evaluationUsagePercent = parsed;\n }\n }\n\n if (subscriptionStatus) {\n const validStatuses = ['active', 'trial', 'past_due', 'suspended', 'cancelled'] as const;\n if (validStatuses.includes(subscriptionStatus as typeof validStatuses[number])) {\n metrics.subscriptionStatus = subscriptionStatus as UsageMetrics['subscriptionStatus'];\n }\n }\n\n // Log warnings for high usage\n if (metrics.apiUsagePercent !== undefined && metrics.apiUsagePercent >= 80) {\n this.logger?.warn(`[FlagKit] API usage at ${metrics.apiUsagePercent}%`);\n }\n if (metrics.evaluationUsagePercent !== undefined && metrics.evaluationUsagePercent >= 80) {\n this.logger?.warn(`[FlagKit] Evaluation usage at ${metrics.evaluationUsagePercent}%`);\n }\n if (metrics.subscriptionStatus === 'suspended') {\n this.logger?.error('[FlagKit] Subscription suspended - service degraded');\n }\n\n return metrics;\n }\n\n /**\n * Send events using beacon API (for page unload)\n * Only available in browser environments\n *\n * VULN-025: Uses HMAC-SHA256 signed payload for beacon authentication.\n * Beacon requests cannot include Authorization headers, so authentication\n * is done via payload-based HMAC signatures.\n *\n * Payload format:\n * {\n * data: object, // Event data\n * signature: string, // HMAC-SHA256 signature of data\n * timestamp: number, // Unix timestamp in milliseconds\n * apiKeyId: string // Last 8 characters of API key\n * }\n *\n * Note: This method uses a pre-computed signature approach since\n * sendBeacon must complete synchronously. For better security,\n * use sendSignedBeacon when you have time (e.g., visibilitychange).\n */\n sendBeacon(path: string, data: unknown): boolean {\n if (!isBrowser() || typeof navigator === 'undefined' || !navigator.sendBeacon) {\n return false;\n }\n\n const url = this.buildUrl(path);\n const timestamp = Date.now();\n const apiKeyId = this.currentApiKey.slice(-8); // Last 8 characters per VULN-025\n\n // VULN-025: Beacon payload structure\n // Note: Signature is computed synchronously if possible, otherwise empty\n // Server should handle both signed and unsigned beacons with appropriate trust levels\n const beaconPayload = {\n data,\n signature: '', // Synchronous signing not available, use sendSignedBeacon for signed payloads\n timestamp,\n apiKeyId,\n };\n\n const blob = new Blob([JSON.stringify(beaconPayload)], {\n type: 'application/json',\n });\n\n const sent = navigator.sendBeacon(url, blob);\n\n if (sent) {\n this.logger?.debug('Beacon sent successfully', { path, apiKeyId });\n } else {\n this.logger?.warn('Beacon failed to send', { path });\n }\n\n return sent;\n }\n\n /**\n * Send events using beacon API with HMAC-SHA256 signing\n * This is the preferred method when you have time before page unload\n * (e.g., during visibilitychange event)\n *\n * VULN-025: Computes full HMAC-SHA256 signature for authenticated beacons.\n */\n async sendSignedBeacon(path: string, data: unknown): Promise<boolean> {\n if (!isBrowser() || typeof navigator === 'undefined' || !navigator.sendBeacon) {\n return false;\n }\n\n const url = this.buildUrl(path);\n\n try {\n // VULN-025: Sign the payload with full HMAC-SHA256\n const signedPayload = await signPayload(data, this.currentApiKey);\n\n // Update apiKeyId to use last 8 chars as per VULN-025 spec\n const beaconPayload = {\n data: signedPayload.data,\n signature: signedPayload.signature,\n timestamp: signedPayload.timestamp,\n apiKeyId: this.currentApiKey.slice(-8), // Last 8 characters\n };\n\n const blob = new Blob([JSON.stringify(beaconPayload)], {\n type: 'application/json',\n });\n\n const sent = navigator.sendBeacon(url, blob);\n\n if (sent) {\n this.logger?.debug('Signed beacon sent successfully', {\n path,\n apiKeyId: beaconPayload.apiKeyId,\n });\n } else {\n this.logger?.warn('Signed beacon failed to send', { path });\n }\n\n return sent;\n } catch (error) {\n this.logger?.error('Failed to sign beacon payload', {\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n // Fall back to unsigned beacon\n return this.sendBeacon(path, data);\n }\n }\n\n /**\n * Get circuit breaker state\n */\n getCircuitState() {\n return this.circuitBreaker.getState();\n }\n\n /**\n * Reset circuit breaker\n */\n resetCircuit(): void {\n this.circuitBreaker.reset();\n }\n}\n","import type { Logger } from '../utils/logger';\n\n/**\n * Polling configuration\n */\nexport interface PollingConfig {\n /** Polling interval in milliseconds. Default: 30000 */\n interval: number;\n\n /** Jitter in milliseconds. Default: 1000 */\n jitter: number;\n\n /** Backoff multiplier for errors. Default: 2 */\n backoffMultiplier: number;\n\n /** Maximum interval in milliseconds. Default: 300000 (5 minutes) */\n maxInterval: number;\n\n /** Callback when poll is triggered */\n onPoll: () => Promise<void>;\n\n /** Logger instance */\n logger?: Logger;\n}\n\n/**\n * Default polling configuration\n */\nexport const DEFAULT_POLLING_CONFIG: Omit<PollingConfig, 'onPoll' | 'logger'> = {\n interval: 30000,\n jitter: 1000,\n backoffMultiplier: 2,\n maxInterval: 300000,\n};\n\n/**\n * Manages background polling for flag updates\n *\n * Features:\n * - Configurable polling interval\n * - Jitter to prevent thundering herd\n * - Exponential backoff on errors\n */\nexport class PollingManager {\n private readonly config: PollingConfig;\n private readonly logger?: Logger;\n\n private currentInterval: number;\n private timerId: ReturnType<typeof setTimeout> | null = null;\n private isRunning = false;\n private consecutiveErrors = 0;\n\n constructor(config: Partial<PollingConfig> & Pick<PollingConfig, 'onPoll'>) {\n this.config = { ...DEFAULT_POLLING_CONFIG, ...config };\n this.logger = config.logger;\n this.currentInterval = this.config.interval;\n }\n\n /**\n * Start polling\n */\n start(): void {\n if (this.isRunning) {\n return;\n }\n\n this.isRunning = true;\n this.scheduleNext();\n this.logger?.debug('Polling started', { interval: this.currentInterval });\n }\n\n /**\n * Stop polling\n */\n stop(): void {\n if (!this.isRunning) {\n return;\n }\n\n this.isRunning = false;\n if (this.timerId) {\n clearTimeout(this.timerId);\n this.timerId = null;\n }\n this.logger?.debug('Polling stopped');\n }\n\n /**\n * Check if polling is active\n */\n isActive(): boolean {\n return this.isRunning;\n }\n\n /**\n * Get current polling interval\n */\n getCurrentInterval(): number {\n return this.currentInterval;\n }\n\n /**\n * Handle successful poll\n */\n onSuccess(): void {\n this.consecutiveErrors = 0;\n this.currentInterval = this.config.interval;\n }\n\n /**\n * Handle failed poll\n */\n onError(): void {\n this.consecutiveErrors++;\n this.currentInterval = Math.min(\n this.currentInterval * this.config.backoffMultiplier,\n this.config.maxInterval\n );\n this.logger?.debug('Polling backoff', {\n interval: this.currentInterval,\n consecutiveErrors: this.consecutiveErrors,\n });\n }\n\n /**\n * Calculate next poll delay with jitter\n */\n private getNextDelay(): number {\n const jitter = Math.random() * this.config.jitter;\n return this.currentInterval + jitter;\n }\n\n /**\n * Schedule the next poll\n */\n private scheduleNext(): void {\n if (!this.isRunning) {\n return;\n }\n\n const delay = this.getNextDelay();\n this.timerId = setTimeout(() => this.poll(), delay);\n }\n\n /**\n * Execute poll\n */\n private async poll(): Promise<void> {\n if (!this.isRunning) {\n return;\n }\n\n try {\n await this.config.onPoll();\n this.onSuccess();\n } catch (error) {\n this.onError();\n this.logger?.warn('Poll failed', {\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n } finally {\n this.scheduleNext();\n }\n }\n\n /**\n * Force an immediate poll\n */\n async pollNow(): Promise<void> {\n // Cancel scheduled poll\n if (this.timerId) {\n clearTimeout(this.timerId);\n this.timerId = null;\n }\n\n // Execute poll immediately\n await this.poll();\n }\n\n /**\n * Reset the polling manager\n */\n reset(): void {\n this.consecutiveErrors = 0;\n this.currentInterval = this.config.interval;\n\n if (this.isRunning) {\n // Restart with reset interval\n if (this.timerId) {\n clearTimeout(this.timerId);\n }\n this.scheduleNext();\n }\n }\n}\n","import type { Logger } from '../utils/logger';\nimport type { FlagState } from '../types/flag';\n\n/**\n * Stream event types from server\n */\nexport type StreamEventType = 'flag_updated' | 'flag_deleted' | 'flags_reset' | 'heartbeat' | 'error';\n\nexport interface StreamEvent {\n type: StreamEventType;\n data: FlagState | { key: string } | FlagState[] | { timestamp: string } | StreamErrorData;\n}\n\n/**\n * SSE error event data structure\n */\nexport interface StreamErrorData {\n code: StreamErrorCode;\n message: string;\n}\n\n/**\n * SSE error codes from server\n */\nexport type StreamErrorCode =\n | 'TOKEN_INVALID'\n | 'TOKEN_EXPIRED'\n | 'SUBSCRIPTION_SUSPENDED'\n | 'CONNECTION_LIMIT'\n | 'STREAMING_UNAVAILABLE';\n\n/**\n * Response from the stream token endpoint\n */\nexport interface StreamTokenResponse {\n /** Short-lived token for SSE connection */\n token: string;\n /** Token expiry time in seconds */\n expiresIn: number;\n}\n\n/**\n * Streaming configuration\n */\nexport interface StreamingConfig {\n /** Base URL for API endpoints */\n baseUrl: string;\n\n /** Reconnection interval in ms. Default: 3000 */\n reconnectInterval: number;\n\n /** Maximum reconnection attempts before fallback. Default: 3 */\n maxReconnectAttempts: number;\n\n /** Expected heartbeat interval in ms. Default: 30000 */\n heartbeatInterval: number;\n\n /** API key for authentication (used to fetch stream token) */\n apiKey: string;\n\n /** Callback when flag is updated */\n onFlagUpdate: (flag: FlagState) => void;\n\n /** Callback when flag is deleted */\n onFlagDelete: (key: string) => void;\n\n /** Callback when all flags are reset */\n onFlagsReset: (flags: FlagState[]) => void;\n\n /** Callback when streaming fails and falls back to polling */\n onFallbackToPolling: () => void;\n\n /** Callback when subscription error occurs (e.g., suspended) */\n onSubscriptionError?: (message: string) => void;\n\n /** Callback when connection limit is reached */\n onConnectionLimitError?: () => void;\n\n /** Logger instance */\n logger?: Logger;\n}\n\n/**\n * Default streaming configuration\n */\nexport const DEFAULT_STREAMING_CONFIG: Omit<\n StreamingConfig,\n 'baseUrl' | 'apiKey' | 'onFlagUpdate' | 'onFlagDelete' | 'onFlagsReset' | 'onFallbackToPolling' | 'logger'\n> = {\n reconnectInterval: 3000,\n maxReconnectAttempts: 3,\n heartbeatInterval: 30000,\n};\n\n/**\n * Connection states for streaming\n */\nexport type StreamingState = 'disconnected' | 'connecting' | 'connected' | 'reconnecting' | 'failed';\n\n/**\n * Manages Server-Sent Events (SSE) connection for real-time flag updates\n *\n * Security: Uses token exchange pattern to avoid exposing API keys in URLs.\n * 1. Fetches short-lived token via POST with API key in header\n * 2. Connects to SSE endpoint with disposable token in URL\n *\n * Features:\n * - Secure token-based authentication\n * - Automatic token refresh before expiry\n * - Automatic reconnection with exponential backoff\n * - Graceful degradation to polling after max failures\n * - Heartbeat monitoring for connection health\n * - Event parsing and dispatch\n */\nexport class StreamingManager {\n private readonly config: StreamingConfig;\n private readonly logger?: Logger;\n\n private eventSource: EventSource | null = null;\n private state: StreamingState = 'disconnected';\n private consecutiveFailures = 0;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private heartbeatTimer: ReturnType<typeof setTimeout> | null = null;\n private tokenRefreshTimer: ReturnType<typeof setTimeout> | null = null;\n private lastHeartbeat: number = 0;\n private retryStreamingTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(config: Partial<StreamingConfig> & Pick<StreamingConfig, 'baseUrl' | 'apiKey' | 'onFlagUpdate' | 'onFlagDelete' | 'onFlagsReset' | 'onFallbackToPolling'>) {\n this.config = { ...DEFAULT_STREAMING_CONFIG, ...config };\n this.logger = config.logger;\n }\n\n /**\n * Get current connection state\n */\n getState(): StreamingState {\n return this.state;\n }\n\n /**\n * Check if streaming is active\n */\n isConnected(): boolean {\n return this.state === 'connected';\n }\n\n /**\n * Start streaming connection\n */\n connect(): void {\n if (this.state === 'connected' || this.state === 'connecting') {\n return;\n }\n\n this.setState('connecting');\n this.initiateConnection();\n }\n\n /**\n * Stop streaming connection\n */\n disconnect(): void {\n this.cleanup();\n this.setState('disconnected');\n this.consecutiveFailures = 0;\n this.logger?.debug('Streaming disconnected');\n }\n\n /**\n * Retry streaming connection (called periodically after fallback to polling)\n */\n retryConnection(): void {\n if (this.state === 'connected' || this.state === 'connecting') {\n return;\n }\n\n this.consecutiveFailures = 0;\n this.connect();\n }\n\n /**\n * Initiate connection by first fetching a stream token\n */\n private async initiateConnection(): Promise<void> {\n try {\n // Step 1: Fetch short-lived stream token\n const tokenResponse = await this.fetchStreamToken();\n\n // Step 2: Schedule token refresh before expiry (refresh at 80% of TTL)\n this.scheduleTokenRefresh(tokenResponse.expiresIn * 0.8 * 1000);\n\n // Step 3: Create SSE connection with token\n this.createConnection(tokenResponse.token);\n } catch (error) {\n this.logger?.error('Failed to fetch stream token', {\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n this.handleConnectionFailure();\n }\n }\n\n /**\n * Fetch a short-lived stream token from the API\n * Token is fetched via POST with API key in header (secure)\n */\n private async fetchStreamToken(): Promise<StreamTokenResponse> {\n const tokenUrl = `${this.config.baseUrl}/sdk/stream/token`;\n this.logger?.debug('Fetching stream token', { tokenUrl });\n\n const response = await fetch(tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-API-Key': this.config.apiKey,\n },\n });\n\n if (!response.ok) {\n throw new Error(`Failed to fetch stream token: ${response.status} ${response.statusText}`);\n }\n\n return response.json() as Promise<StreamTokenResponse>;\n }\n\n /**\n * Schedule token refresh before expiry\n */\n private scheduleTokenRefresh(delayMs: number): void {\n this.clearTokenRefreshTimer();\n\n this.tokenRefreshTimer = setTimeout(async () => {\n this.tokenRefreshTimer = null;\n\n try {\n this.logger?.debug('Refreshing stream token');\n const tokenResponse = await this.fetchStreamToken();\n\n // Schedule next refresh\n this.scheduleTokenRefresh(tokenResponse.expiresIn * 0.8 * 1000);\n\n this.logger?.debug('Stream token refreshed successfully');\n } catch (error) {\n this.logger?.warn('Failed to refresh stream token, reconnecting', {\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n // Token refresh failed, force reconnection\n this.cleanup();\n this.connect();\n }\n }, delayMs);\n }\n\n /**\n * Clear token refresh timer\n */\n private clearTokenRefreshTimer(): void {\n if (this.tokenRefreshTimer) {\n clearTimeout(this.tokenRefreshTimer);\n this.tokenRefreshTimer = null;\n }\n }\n\n /**\n * Create SSE connection with token\n */\n private createConnection(token: string): void {\n try {\n // Build URL with short-lived token (NOT the API key)\n const streamUrl = new URL(`${this.config.baseUrl}/sdk/stream`);\n streamUrl.searchParams.set('token', token);\n\n this.eventSource = new EventSource(streamUrl.toString());\n\n this.eventSource.onopen = () => {\n this.handleOpen();\n };\n\n this.eventSource.onmessage = (event) => {\n this.handleMessage(event);\n };\n\n this.eventSource.onerror = (event) => {\n this.handleError(event);\n };\n\n // Listen for specific event types\n this.eventSource.addEventListener('flag_updated', (event) => {\n this.handleFlagUpdated(event as MessageEvent);\n });\n\n this.eventSource.addEventListener('flag_deleted', (event) => {\n this.handleFlagDeleted(event as MessageEvent);\n });\n\n this.eventSource.addEventListener('flags_reset', (event) => {\n this.handleFlagsReset(event as MessageEvent);\n });\n\n this.eventSource.addEventListener('heartbeat', (event) => {\n this.handleHeartbeat(event as MessageEvent);\n });\n\n // Listen for SSE error events (distinct from connection errors)\n this.eventSource.addEventListener('error', (event) => {\n this.handleStreamError(event as MessageEvent);\n });\n\n } catch (error) {\n this.logger?.error('Failed to create EventSource', {\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n this.handleConnectionFailure();\n }\n }\n\n /**\n * Handle successful connection\n */\n private handleOpen(): void {\n this.setState('connected');\n this.consecutiveFailures = 0;\n this.lastHeartbeat = Date.now();\n this.startHeartbeatMonitor();\n\n this.logger?.info('Streaming connected');\n }\n\n /**\n * Handle generic message (fallback for unnamed events)\n */\n private handleMessage(event: MessageEvent): void {\n try {\n const data = JSON.parse(event.data) as StreamEvent;\n this.dispatchEvent(data);\n } catch (error) {\n this.logger?.warn('Failed to parse stream message', {\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n }\n\n /**\n * Handle flag_updated event\n */\n private handleFlagUpdated(event: MessageEvent): void {\n try {\n const flag = JSON.parse(event.data) as FlagState;\n this.logger?.debug('Flag updated via stream', { key: flag.key });\n this.config.onFlagUpdate(flag);\n } catch (error) {\n this.logger?.warn('Failed to parse flag_updated event', {\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n }\n\n /**\n * Handle flag_deleted event\n */\n private handleFlagDeleted(event: MessageEvent): void {\n try {\n const data = JSON.parse(event.data) as { key: string };\n this.logger?.debug('Flag deleted via stream', { key: data.key });\n this.config.onFlagDelete(data.key);\n } catch (error) {\n this.logger?.warn('Failed to parse flag_deleted event', {\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n }\n\n /**\n * Handle flags_reset event\n */\n private handleFlagsReset(event: MessageEvent): void {\n try {\n const flags = JSON.parse(event.data) as FlagState[];\n this.logger?.debug('Flags reset via stream', { count: flags.length });\n this.config.onFlagsReset(flags);\n } catch (error) {\n this.logger?.warn('Failed to parse flags_reset event', {\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n }\n\n /**\n * Handle heartbeat event\n */\n private handleHeartbeat(_event: MessageEvent): void {\n this.lastHeartbeat = Date.now();\n this.logger?.debug('Heartbeat received');\n }\n\n /**\n * Handle SSE error event from server\n * These are application-level errors sent as SSE events, not connection errors\n *\n * Error codes:\n * - TOKEN_INVALID: Re-authenticate completely\n * - TOKEN_EXPIRED: Refresh token and reconnect\n * - SUBSCRIPTION_SUSPENDED: Notify user, fall back to cached values\n * - CONNECTION_LIMIT: Implement backoff or close other connections\n * - STREAMING_UNAVAILABLE: Fall back to polling\n */\n private handleStreamError(event: MessageEvent): void {\n try {\n // Try to parse as JSON error event\n if (event.data) {\n const errorData = JSON.parse(event.data) as StreamErrorData;\n this.logger?.warn('SSE error event received', {\n code: errorData.code,\n message: errorData.message,\n });\n\n switch (errorData.code) {\n case 'TOKEN_EXPIRED':\n // Token expired, refresh and reconnect\n this.logger?.info('Stream token expired, refreshing...');\n this.cleanup();\n this.connect(); // Will fetch new token\n break;\n\n case 'TOKEN_INVALID':\n // Token is invalid, need full re-authentication\n this.logger?.error('Stream token invalid, re-authenticating...');\n this.cleanup();\n this.connect(); // Will fetch new token\n break;\n\n case 'SUBSCRIPTION_SUSPENDED':\n // Subscription issue - notify and fall back\n this.logger?.error('Subscription suspended', { message: errorData.message });\n this.config.onSubscriptionError?.(errorData.message);\n this.cleanup();\n this.setState('failed');\n this.config.onFallbackToPolling();\n break;\n\n case 'CONNECTION_LIMIT':\n // Too many connections - implement backoff\n this.logger?.warn('Connection limit reached, backing off...');\n this.config.onConnectionLimitError?.();\n this.handleConnectionFailure();\n break;\n\n case 'STREAMING_UNAVAILABLE':\n // Streaming not available - fall back to polling\n this.logger?.warn('Streaming service unavailable, falling back to polling');\n this.cleanup();\n this.setState('failed');\n this.config.onFallbackToPolling();\n break;\n\n default:\n this.logger?.warn('Unknown stream error code', { code: errorData.code });\n this.handleConnectionFailure();\n }\n }\n } catch {\n // Not a JSON error event, likely a connection error\n // Let the onerror handler deal with it\n this.logger?.debug('Non-JSON error event received');\n }\n }\n\n /**\n * Dispatch parsed event to appropriate handler\n */\n private dispatchEvent(event: StreamEvent): void {\n switch (event.type) {\n case 'flag_updated':\n this.config.onFlagUpdate(event.data as FlagState);\n break;\n case 'flag_deleted':\n this.config.onFlagDelete((event.data as { key: string }).key);\n break;\n case 'flags_reset':\n this.config.onFlagsReset(event.data as FlagState[]);\n break;\n case 'heartbeat':\n this.lastHeartbeat = Date.now();\n break;\n }\n }\n\n /**\n * Handle connection error\n */\n private handleError(_event: Event): void {\n this.logger?.warn('Streaming error', {\n readyState: this.eventSource?.readyState,\n });\n\n // EventSource automatically tries to reconnect\n // We track failures to implement fallback\n if (this.eventSource?.readyState === EventSource.CLOSED) {\n this.handleConnectionFailure();\n }\n }\n\n /**\n * Handle connection failure\n */\n private handleConnectionFailure(): void {\n this.cleanup();\n this.consecutiveFailures++;\n\n if (this.consecutiveFailures >= this.config.maxReconnectAttempts) {\n this.setState('failed');\n this.logger?.warn('Streaming failed, falling back to polling', {\n failures: this.consecutiveFailures,\n });\n this.config.onFallbackToPolling();\n\n // Schedule retry of streaming in 5 minutes\n this.scheduleStreamingRetry();\n } else {\n this.setState('reconnecting');\n this.scheduleReconnect();\n }\n }\n\n /**\n * Schedule reconnection attempt\n */\n private scheduleReconnect(): void {\n const delay = this.getReconnectDelay();\n this.logger?.debug('Scheduling reconnect', { delay, attempt: this.consecutiveFailures });\n\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n this.connect();\n }, delay);\n }\n\n /**\n * Get reconnection delay with exponential backoff\n */\n private getReconnectDelay(): number {\n const baseDelay = this.config.reconnectInterval;\n const backoff = Math.pow(2, this.consecutiveFailures - 1);\n const delay = baseDelay * backoff;\n // Cap at 30 seconds\n return Math.min(delay, 30000);\n }\n\n /**\n * Schedule retry of streaming after fallback to polling\n */\n private scheduleStreamingRetry(): void {\n // Retry streaming every 5 minutes\n const retryInterval = 5 * 60 * 1000;\n\n this.retryStreamingTimer = setTimeout(() => {\n this.retryStreamingTimer = null;\n this.logger?.info('Retrying streaming connection');\n this.retryConnection();\n }, retryInterval);\n }\n\n /**\n * Start heartbeat monitoring\n */\n private startHeartbeatMonitor(): void {\n this.stopHeartbeatMonitor();\n\n // Check heartbeat at 1.5x the expected interval\n const checkInterval = this.config.heartbeatInterval * 1.5;\n\n this.heartbeatTimer = setInterval(() => {\n const timeSinceLastHeartbeat = Date.now() - this.lastHeartbeat;\n\n if (timeSinceLastHeartbeat > this.config.heartbeatInterval * 2) {\n this.logger?.warn('Heartbeat timeout, reconnecting', {\n timeSinceLastHeartbeat,\n });\n this.handleConnectionFailure();\n }\n }, checkInterval);\n }\n\n /**\n * Stop heartbeat monitoring\n */\n private stopHeartbeatMonitor(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n }\n\n /**\n * Set connection state\n */\n private setState(state: StreamingState): void {\n this.state = state;\n }\n\n /**\n * Cleanup resources\n */\n private cleanup(): void {\n if (this.eventSource) {\n this.eventSource.close();\n this.eventSource = null;\n }\n\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n if (this.retryStreamingTimer) {\n clearTimeout(this.retryStreamingTimer);\n this.retryStreamingTimer = null;\n }\n\n this.clearTokenRefreshTimer();\n this.stopHeartbeatMonitor();\n }\n}\n","import type { EvaluationReason } from './flag';\n\n/**\n * Base event structure for all FlagKit events\n */\nexport interface BaseEvent {\n /** Event type identifier */\n eventType: string;\n\n /** ISO 8601 timestamp */\n timestamp: string;\n\n /** SDK version */\n sdkVersion: string;\n\n /** SDK language identifier */\n sdkLanguage: string;\n\n /** Session identifier */\n sessionId: string;\n\n /** Environment UUID */\n environmentId: string;\n\n /** User identifier */\n userId?: string;\n\n /** Alternative user key */\n userKey?: string;\n\n /** Whether the user is anonymous */\n anonymous?: boolean;\n\n /** Custom event data */\n eventData?: Record<string, unknown>;\n\n /** Event metadata */\n metadata?: EventMetadata;\n}\n\n/**\n * Optional metadata for events\n */\nexport interface EventMetadata {\n /** Event source (sdk, api, webhook) */\n source?: string;\n\n /** Platform (web, ios, android, server) */\n platform?: string;\n\n /** Device identifier */\n deviceId?: string;\n\n /** Application version */\n appVersion?: string;\n\n /** User locale (e.g., en-US) */\n locale?: string;\n\n /** User timezone */\n timezone?: string;\n}\n\n/**\n * Flag evaluation event (automatic, opt-in)\n */\nexport interface FlagEvaluatedEvent extends BaseEvent {\n eventType: 'flag.evaluated';\n eventData: {\n flagKey: string;\n value: unknown;\n defaultValue: unknown;\n reason: EvaluationReason;\n variationId?: string;\n ruleId?: string;\n segmentId?: string;\n version: number;\n evaluationTimeMs: number;\n fromCache: boolean;\n };\n}\n\n/**\n * Custom event tracked by user code\n */\nexport interface CustomEvent extends BaseEvent {\n eventType: string;\n eventData: Record<string, unknown>;\n}\n\n/**\n * SDK system event types\n */\nexport type SystemEventType =\n | 'sdk.initialized'\n | 'sdk.ready'\n | 'sdk.error'\n | 'flag.evaluated'\n | 'context.identified'\n | 'context.reset';\n\n/**\n * Event queue configuration\n */\nexport interface EventQueueConfig {\n /** Maximum events to queue. Default: 100 */\n maxQueueSize: number;\n\n /** Batch size for sending. Default: 10 */\n batchSize: number;\n\n /** Flush interval in ms. Default: 30000 */\n flushInterval: number;\n\n /** Maximum retry attempts. Default: 3 */\n maxRetries: number;\n\n /** Base retry delay in ms. Default: 1000 */\n retryDelay: number;\n\n /** Retry backoff multiplier. Default: 2 */\n retryBackoff: number;\n\n /** Persist queue to storage. Default: false */\n persistQueue: boolean;\n\n /** Storage key for persistence. Default: 'flagkit_events' */\n storageKey: string;\n\n /** Enabled event types. Default: ['*'] (all) */\n enabledEventTypes: string[];\n\n /** Disabled event types. Default: [] */\n disabledEventTypes: string[];\n\n /** Event sampling rate (0.0 - 1.0). Default: 1.0 */\n sampleRate: number;\n}\n\n/**\n * Default event queue configuration\n */\nexport const DEFAULT_EVENT_QUEUE_CONFIG: EventQueueConfig = {\n maxQueueSize: 100,\n batchSize: 10,\n flushInterval: 30000,\n maxRetries: 3,\n retryDelay: 1000,\n retryBackoff: 2,\n persistQueue: false,\n storageKey: 'flagkit_events',\n enabledEventTypes: ['*'],\n disabledEventTypes: [],\n sampleRate: 1.0,\n};\n\n/**\n * API response for batch events\n */\nexport interface BatchEventsResponse {\n success: boolean;\n message: string;\n recorded: number;\n errors: number;\n}\n","import type { FlagKitOptions } from '../types/config';\nimport type { EvaluationContext } from '../types/context';\nimport { InitializationError, SecurityError } from '../errors/flagkit-error';\nimport { warnIfServerKeyInBrowser, isProductionEnvironment } from './security';\nimport type { Logger } from './logger';\n\n/**\n * API key prefixes\n */\nconst API_KEY_PREFIXES = ['sdk_', 'srv_', 'cli_'] as const;\n\n/**\n * Validate API key format\n */\nexport function isValidApiKey(apiKey: string): boolean {\n if (!apiKey || typeof apiKey !== 'string') {\n return false;\n }\n\n // Check for valid prefix\n return API_KEY_PREFIXES.some((prefix) => apiKey.startsWith(prefix));\n}\n\n/**\n * Validate FlagKit options\n * @throws {InitializationError} If options are invalid\n * @throws {SecurityError} If security violations are detected\n */\nexport function validateOptions(options: FlagKitOptions, logger?: Logger): void {\n // API key is required\n if (!options.apiKey) {\n throw new InitializationError(\n 'INIT_MISSING_API_KEY',\n 'apiKey is required in FlagKitOptions'\n );\n }\n\n // Validate API key format\n if (!isValidApiKey(options.apiKey)) {\n throw new InitializationError(\n 'INIT_INVALID_CONFIG',\n `Invalid API key format. API key must start with one of: ${API_KEY_PREFIXES.join(', ')}`\n );\n }\n\n // Security check: warn if server key is used in browser\n warnIfServerKeyInBrowser(options.apiKey, logger);\n\n // CRITICAL: Prevent localPort from being used in production\n if (options.localPort !== undefined && isProductionEnvironment()) {\n throw new SecurityError(\n 'SECURITY_LOCAL_PORT_IN_PRODUCTION',\n 'localPort cannot be used in production environments. ' +\n 'This option is only for local development. ' +\n 'See: https://docs.flagkit.dev/sdk/security#local-development'\n );\n }\n\n // Validate secondary API key format if provided\n if (options.secondaryApiKey && !isValidApiKey(options.secondaryApiKey)) {\n throw new InitializationError(\n 'INIT_INVALID_CONFIG',\n `Invalid secondary API key format. API key must start with one of: ${API_KEY_PREFIXES.join(', ')}`\n );\n }\n\n // Validate numeric options\n if (\n options.pollingInterval !== undefined &&\n (typeof options.pollingInterval !== 'number' || options.pollingInterval < 0)\n ) {\n throw new InitializationError(\n 'INIT_INVALID_CONFIG',\n 'pollingInterval must be a positive number'\n );\n }\n\n if (\n options.timeout !== undefined &&\n (typeof options.timeout !== 'number' || options.timeout < 0)\n ) {\n throw new InitializationError(\n 'INIT_INVALID_CONFIG',\n 'timeout must be a positive number'\n );\n }\n\n if (\n options.retries !== undefined &&\n (typeof options.retries !== 'number' || options.retries < 0)\n ) {\n throw new InitializationError(\n 'INIT_INVALID_CONFIG',\n 'retries must be a non-negative number'\n );\n }\n\n if (\n options.cacheTTL !== undefined &&\n (typeof options.cacheTTL !== 'number' || options.cacheTTL < 0)\n ) {\n throw new InitializationError(\n 'INIT_INVALID_CONFIG',\n 'cacheTTL must be a positive number'\n );\n }\n\n if (\n options.keyRotationGracePeriod !== undefined &&\n (typeof options.keyRotationGracePeriod !== 'number' || options.keyRotationGracePeriod < 0)\n ) {\n throw new InitializationError(\n 'INIT_INVALID_CONFIG',\n 'keyRotationGracePeriod must be a positive number'\n );\n }\n}\n\n/**\n * Validate flag key\n */\nexport function isValidFlagKey(key: unknown): key is string {\n return typeof key === 'string' && key.length > 0 && key.length <= 256;\n}\n\n/**\n * Validate evaluation context\n */\nexport function isValidContext(\n context: unknown\n): context is EvaluationContext | undefined {\n if (context === undefined || context === null) {\n return true;\n }\n\n if (typeof context !== 'object') {\n return false;\n }\n\n const ctx = context as EvaluationContext;\n\n // Validate string fields\n if (ctx.userId !== undefined && typeof ctx.userId !== 'string') {\n return false;\n }\n if (ctx.userKey !== undefined && typeof ctx.userKey !== 'string') {\n return false;\n }\n if (ctx.email !== undefined && typeof ctx.email !== 'string') {\n return false;\n }\n if (ctx.name !== undefined && typeof ctx.name !== 'string') {\n return false;\n }\n if (ctx.country !== undefined && typeof ctx.country !== 'string') {\n return false;\n }\n if (ctx.ip !== undefined && typeof ctx.ip !== 'string') {\n return false;\n }\n if (ctx.userAgent !== undefined && typeof ctx.userAgent !== 'string') {\n return false;\n }\n\n // Validate boolean field\n if (ctx.anonymous !== undefined && typeof ctx.anonymous !== 'boolean') {\n return false;\n }\n\n // Validate custom object\n if (ctx.custom !== undefined && typeof ctx.custom !== 'object') {\n return false;\n }\n\n // Validate privateAttributes array\n if (ctx.privateAttributes !== undefined) {\n if (!Array.isArray(ctx.privateAttributes)) {\n return false;\n }\n if (!ctx.privateAttributes.every((attr) => typeof attr === 'string')) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Validate event type\n */\nexport function isValidEventType(eventType: unknown): eventType is string {\n return (\n typeof eventType === 'string' &&\n eventType.length > 0 &&\n eventType.length <= 128 &&\n /^[a-zA-Z][a-zA-Z0-9_.-]*$/.test(eventType)\n );\n}\n\n/**\n * Validate event data\n */\nexport function isValidEventData(\n data: unknown\n): data is Record<string, unknown> | undefined {\n if (data === undefined || data === null) {\n return true;\n }\n\n if (typeof data !== 'object' || Array.isArray(data)) {\n return false;\n }\n\n // Check if JSON serializable\n try {\n JSON.stringify(data);\n return true;\n } catch {\n return false;\n }\n}\n","import type { BaseEvent, EventQueueConfig, BatchEventsResponse } from '../types/events';\nimport { DEFAULT_EVENT_QUEUE_CONFIG } from '../types/events';\nimport type { HttpClient } from '../http/http-client';\nimport type { Logger } from '../utils/logger';\nimport { isBrowser, getCurrentTimestamp } from '../utils/platform';\nimport { isValidEventType, isValidEventData } from '../utils/validators';\n\n/**\n * Event queue options\n */\nexport interface EventQueueOptions {\n httpClient: HttpClient;\n logger?: Logger;\n sessionId: string;\n environmentId: string;\n sdkVersion: string;\n config?: Partial<EventQueueConfig>;\n}\n\n/**\n * Manages event batching and delivery\n *\n * Features:\n * - Batching (default: 10 events or 30 seconds)\n * - Automatic retry on failure\n * - Browser unload handling with sendBeacon\n * - Event sampling\n */\nexport class EventQueue {\n private queue: BaseEvent[] = [];\n private readonly httpClient: HttpClient;\n private readonly config: EventQueueConfig;\n private readonly logger?: Logger;\n private readonly sessionId: string;\n private readonly sdkVersion: string;\n\n private environmentId: string;\n private flushTimer: ReturnType<typeof setTimeout> | null = null;\n private isFlushing = false;\n private unloadHandler: (() => void) | null = null;\n\n constructor(options: EventQueueOptions) {\n this.httpClient = options.httpClient;\n this.logger = options.logger;\n this.sessionId = options.sessionId;\n this.environmentId = options.environmentId;\n this.sdkVersion = options.sdkVersion;\n this.config = { ...DEFAULT_EVENT_QUEUE_CONFIG, ...options.config };\n\n // Set up browser unload handler\n if (isBrowser()) {\n this.setupUnloadHandler();\n }\n\n // Start flush timer\n this.startFlushTimer();\n }\n\n /**\n * Set environment ID (called after initialization)\n */\n setEnvironmentId(id: string): void {\n this.environmentId = id;\n }\n\n /**\n * Track a custom event\n */\n track(eventType: string, eventData?: Record<string, unknown>): void {\n // Validate event type\n if (!isValidEventType(eventType)) {\n this.logger?.warn('Invalid event type', { eventType });\n return;\n }\n\n // Validate event data\n if (!isValidEventData(eventData)) {\n this.logger?.warn('Invalid event data', { eventType });\n return;\n }\n\n // Check if event type is enabled\n if (!this.isEventTypeEnabled(eventType)) {\n return;\n }\n\n // Apply sampling\n if (!this.shouldSample(eventType)) {\n return;\n }\n\n // Create event\n const event: BaseEvent = {\n eventType,\n timestamp: getCurrentTimestamp(),\n sdkVersion: this.sdkVersion,\n sdkLanguage: 'typescript',\n sessionId: this.sessionId,\n environmentId: this.environmentId,\n eventData,\n };\n\n // Add to queue\n this.addToQueue(event);\n }\n\n /**\n * Flush pending events immediately\n */\n async flush(): Promise<void> {\n if (this.queue.length === 0 || this.isFlushing) {\n return;\n }\n\n this.isFlushing = true;\n\n // Get events to send\n const events = [...this.queue];\n this.queue = [];\n\n try {\n await this.sendEvents(events);\n this.logger?.debug('Events flushed', { count: events.length });\n } catch (error) {\n // Re-queue failed events (up to max size)\n const requeue = events.slice(0, this.config.maxQueueSize - this.queue.length);\n this.queue = [...requeue, ...this.queue];\n\n this.logger?.warn('Failed to flush events', {\n error: error instanceof Error ? error.message : 'Unknown error',\n requeued: requeue.length,\n });\n\n throw error;\n } finally {\n this.isFlushing = false;\n }\n }\n\n /**\n * Get queued events (for debugging)\n */\n getQueuedEvents(): BaseEvent[] {\n return [...this.queue];\n }\n\n /**\n * Clear the event queue\n */\n clearQueue(): void {\n this.queue = [];\n this.logger?.debug('Event queue cleared');\n }\n\n /**\n * Get queue size\n */\n getQueueSize(): number {\n return this.queue.length;\n }\n\n /**\n * Stop the event queue\n */\n stop(): void {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n\n if (this.unloadHandler && isBrowser()) {\n window.removeEventListener('beforeunload', this.unloadHandler);\n this.unloadHandler = null;\n }\n }\n\n /**\n * Add event to queue\n */\n private addToQueue(event: BaseEvent): void {\n // Enforce max queue size\n if (this.queue.length >= this.config.maxQueueSize) {\n // Drop oldest event\n this.queue.shift();\n this.logger?.warn('Event queue full, dropping oldest event');\n }\n\n this.queue.push(event);\n this.logger?.debug('Event queued', { eventType: event.eventType });\n\n // Flush if batch size reached\n if (this.queue.length >= this.config.batchSize) {\n void this.flush();\n }\n }\n\n /**\n * Send events to server\n */\n private async sendEvents(events: BaseEvent[]): Promise<void> {\n if (events.length === 0) {\n return;\n }\n\n await this.httpClient.post<BatchEventsResponse>('/sdk/events/batch', {\n events,\n });\n }\n\n /**\n * Check if event type is enabled\n */\n private isEventTypeEnabled(eventType: string): boolean {\n // Check disabled list first\n if (this.config.disabledEventTypes.includes(eventType)) {\n return false;\n }\n\n // Check enabled list\n if (\n this.config.enabledEventTypes.includes('*') ||\n this.config.enabledEventTypes.includes(eventType)\n ) {\n return true;\n }\n\n return false;\n }\n\n /**\n * Apply sampling to event\n */\n private shouldSample(_eventType: string): boolean {\n if (this.config.sampleRate >= 1.0) {\n return true;\n }\n if (this.config.sampleRate <= 0.0) {\n return false;\n }\n return Math.random() < this.config.sampleRate;\n }\n\n /**\n * Start periodic flush timer\n */\n private startFlushTimer(): void {\n if (this.flushTimer) {\n return;\n }\n\n this.flushTimer = setInterval(() => {\n void this.flush();\n }, this.config.flushInterval);\n }\n\n /**\n * Set up browser unload handler\n */\n private setupUnloadHandler(): void {\n this.unloadHandler = () => {\n if (this.queue.length > 0) {\n // Try sendBeacon for reliable delivery\n const sent = this.httpClient.sendBeacon('/sdk/events/batch', {\n events: this.queue,\n });\n\n if (sent) {\n this.queue = [];\n }\n }\n };\n\n window.addEventListener('beforeunload', this.unloadHandler);\n }\n}\n","/**\n * Log levels supported by the SDK\n */\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'none';\n\n/**\n * Log entry structure\n */\nexport interface LogEntry {\n level: LogLevel;\n message: string;\n timestamp: Date;\n data?: Record<string, unknown>;\n}\n\n/**\n * Logger interface for custom implementations\n */\nexport interface Logger {\n debug(message: string, data?: Record<string, unknown>): void;\n info(message: string, data?: Record<string, unknown>): void;\n warn(message: string, data?: Record<string, unknown>): void;\n error(message: string, data?: Record<string, unknown>): void;\n}\n\n/**\n * Log level numeric values for comparison\n */\nconst LOG_LEVEL_VALUES: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n none: 4,\n};\n\n/**\n * Default console logger implementation\n */\nexport class ConsoleLogger implements Logger {\n private readonly prefix: string;\n private readonly minLevel: LogLevel;\n\n constructor(options?: { prefix?: string; level?: LogLevel }) {\n this.prefix = options?.prefix ?? '[FlagKit]';\n this.minLevel = options?.level ?? 'warn';\n }\n\n private shouldLog(level: LogLevel): boolean {\n return LOG_LEVEL_VALUES[level] >= LOG_LEVEL_VALUES[this.minLevel];\n }\n\n private formatMessage(level: LogLevel, message: string): string {\n const timestamp = new Date().toISOString();\n return `${timestamp} ${this.prefix} ${level.toUpperCase()}: ${message}`;\n }\n\n debug(message: string, data?: Record<string, unknown>): void {\n if (this.shouldLog('debug')) {\n const formatted = this.formatMessage('debug', message);\n if (data) {\n console.debug(formatted, data);\n } else {\n console.debug(formatted);\n }\n }\n }\n\n info(message: string, data?: Record<string, unknown>): void {\n if (this.shouldLog('info')) {\n const formatted = this.formatMessage('info', message);\n if (data) {\n console.info(formatted, data);\n } else {\n console.info(formatted);\n }\n }\n }\n\n warn(message: string, data?: Record<string, unknown>): void {\n if (this.shouldLog('warn')) {\n const formatted = this.formatMessage('warn', message);\n if (data) {\n console.warn(formatted, data);\n } else {\n console.warn(formatted);\n }\n }\n }\n\n error(message: string, data?: Record<string, unknown>): void {\n if (this.shouldLog('error')) {\n const formatted = this.formatMessage('error', message);\n if (data) {\n console.error(formatted, data);\n } else {\n console.error(formatted);\n }\n }\n }\n}\n\n/**\n * No-op logger that discards all messages\n */\nexport class NoopLogger implements Logger {\n debug(): void {\n // Intentionally empty\n }\n\n info(): void {\n // Intentionally empty\n }\n\n warn(): void {\n // Intentionally empty\n }\n\n error(): void {\n // Intentionally empty\n }\n}\n\n/**\n * Create a logger instance based on configuration\n */\nexport function createLogger(options?: {\n logger?: Logger;\n debug?: boolean;\n}): Logger {\n if (options?.logger) {\n return options.logger;\n }\n\n if (options?.debug) {\n return new ConsoleLogger({ level: 'debug' });\n }\n\n return new ConsoleLogger({ level: 'warn' });\n}\n","/**\n * Semantic version comparison utilities for SDK version metadata handling.\n *\n * These utilities are used to compare the current SDK version against\n * server-provided version requirements (min, recommended, latest).\n */\n\n/**\n * Parse a semantic version string into numeric components.\n * Returns null if the version is not a valid semver.\n */\nexport function parseVersion(version: string): { major: number; minor: number; patch: number } | null {\n if (!version || typeof version !== 'string') {\n return null;\n }\n\n // Trim whitespace and strip leading 'v' or 'V' if present\n const trimmed = version.trim();\n if (trimmed.length === 0) {\n return null;\n }\n\n const normalized = trimmed.startsWith('v') || trimmed.startsWith('V')\n ? trimmed.slice(1)\n : trimmed;\n\n // Match semver pattern (allows pre-release suffix but ignores it for comparison)\n const match = normalized.match(/^(\\d+)\\.(\\d+)\\.(\\d+)/);\n if (!match) {\n return null;\n }\n\n const major = parseInt(match[1], 10);\n const minor = parseInt(match[2], 10);\n const patch = parseInt(match[3], 10);\n\n // Validate parsed numbers are safe integers (handles overflow edge cases)\n if (!Number.isSafeInteger(major) || !Number.isSafeInteger(minor) || !Number.isSafeInteger(patch)) {\n return null;\n }\n\n // Reject negative values (shouldn't happen with regex, but defensive)\n if (major < 0 || minor < 0 || patch < 0) {\n return null;\n }\n\n return { major, minor, patch };\n}\n\n/**\n * Compare two semantic versions.\n * Returns:\n * - negative number if a < b\n * - 0 if a == b\n * - positive number if a > b\n *\n * Returns 0 if either version is invalid.\n */\nexport function compareVersions(a: string, b: string): number {\n const parsedA = parseVersion(a);\n const parsedB = parseVersion(b);\n\n if (!parsedA || !parsedB) {\n return 0;\n }\n\n // Compare major\n if (parsedA.major !== parsedB.major) {\n return parsedA.major - parsedB.major;\n }\n\n // Compare minor\n if (parsedA.minor !== parsedB.minor) {\n return parsedA.minor - parsedB.minor;\n }\n\n // Compare patch\n return parsedA.patch - parsedB.patch;\n}\n\n/**\n * Check if version a is less than version b.\n */\nexport function isVersionLessThan(a: string, b: string): boolean {\n return compareVersions(a, b) < 0;\n}\n\n/**\n * Check if version a is greater than or equal to version b.\n */\nexport function isVersionAtLeast(a: string, b: string): boolean {\n return compareVersions(a, b) >= 0;\n}\n","import type { FlagKitOptions, ResolvedConfig } from './types/config';\nimport type { EvaluationContext } from './types/context';\nimport type {\n FlagState,\n FlagValue,\n EvaluationResult,\n InitResponse,\n UpdatesResponse,\n} from './types/flag';\nimport { createDefaultResult } from './types/flag';\nimport { FlagCache } from './core/cache';\nimport { ContextManager } from './core/context-manager';\nimport { HttpClient, SDK_VERSION, getBaseUrl } from './http/http-client';\nimport { PollingManager } from './core/polling-manager';\nimport { StreamingManager } from './core/streaming-manager';\nimport { EventQueue } from './core/event-queue';\nimport { createLogger, type Logger } from './utils/logger';\nimport { validateOptions, isValidFlagKey, isValidContext } from './utils/validators';\nimport { generateSessionId } from './utils/platform';\nimport { checkForPotentialPII, verifyBootstrapSignature } from './utils/security';\nimport { isVersionLessThan } from './utils/version';\nimport { FlagKitError, InitializationError, SecurityError } from './errors/flagkit-error';\nimport type { BootstrapConfig } from './types/config';\n\n/**\n * FlagKit SDK Client\n *\n * Main interface for feature flag evaluation and event tracking.\n */\nexport class FlagKitClient {\n private readonly config: ResolvedConfig;\n private readonly cache: FlagCache;\n private readonly contextManager: ContextManager;\n private readonly httpClient: HttpClient;\n private readonly eventQueue: EventQueue;\n private readonly logger: Logger;\n private readonly sessionId: string;\n\n private pollingManager: PollingManager | null = null;\n private streamingManager: StreamingManager | null = null;\n private readyPromise: Promise<void> | null = null;\n private isReadyFlag = false;\n private isClosedFlag = false;\n private lastUpdateTime: string | null = null;\n private isStreamingActive = false;\n\n constructor(options: FlagKitOptions) {\n // Build logger first for validation warnings\n this.logger = createLogger({\n logger: options.logger,\n debug: options.debug,\n });\n\n // Validate options (includes security checks)\n validateOptions(options, this.logger);\n\n this.config = {\n apiKey: options.apiKey,\n pollingInterval: options.pollingInterval ?? 30000,\n enablePolling: options.enablePolling ?? true,\n cacheEnabled: options.cacheEnabled ?? true,\n cacheTTL: options.cacheTTL ?? 300000,\n offline: options.offline ?? false,\n timeout: options.timeout ?? 5000,\n retries: options.retries ?? 3,\n logger: this.logger,\n bootstrap: options.bootstrap ?? {},\n bootstrapVerification: {\n enabled: options.bootstrapVerification?.enabled ?? true,\n maxAge: options.bootstrapVerification?.maxAge ?? 86400000,\n onFailure: options.bootstrapVerification?.onFailure ?? 'warn',\n },\n persistCache: options.persistCache ?? false,\n cacheStorageKey: options.cacheStorageKey ?? 'flagkit_cache',\n onReady: options.onReady,\n onError: options.onError,\n onUpdate: options.onUpdate,\n onUsageUpdate: options.onUsageUpdate,\n debug: options.debug ?? false,\n localPort: options.localPort,\n secondaryApiKey: options.secondaryApiKey,\n keyRotationGracePeriod: options.keyRotationGracePeriod ?? 300000,\n strictPIIMode: options.strictPIIMode ?? false,\n evaluationJitter: {\n enabled: options.evaluationJitter?.enabled ?? false,\n minMs: options.evaluationJitter?.minMs ?? 5,\n maxMs: options.evaluationJitter?.maxMs ?? 15,\n },\n errorSanitization: {\n enabled: options.errorSanitization?.enabled ?? true,\n preserveOriginal: options.errorSanitization?.preserveOriginal ?? false,\n },\n streaming: {\n enabled: options.streaming?.enabled ?? true,\n reconnectInterval: options.streaming?.reconnectInterval ?? 3000,\n maxReconnectAttempts: options.streaming?.maxReconnectAttempts ?? 3,\n heartbeatInterval: options.streaming?.heartbeatInterval ?? 30000,\n },\n };\n\n this.sessionId = generateSessionId();\n\n // Initialize components\n this.cache = new FlagCache({\n ttl: this.config.cacheTTL,\n logger: this.logger,\n });\n\n this.contextManager = new ContextManager(this.logger);\n\n this.httpClient = new HttpClient({\n baseUrl: getBaseUrl(this.config.localPort),\n apiKey: this.config.apiKey,\n secondaryApiKey: this.config.secondaryApiKey,\n keyRotationGracePeriod: this.config.keyRotationGracePeriod,\n timeout: this.config.timeout,\n retry: { maxAttempts: this.config.retries },\n circuitBreaker: {},\n logger: this.logger,\n enableRequestSigning: true,\n onUsageUpdate: options.onUsageUpdate,\n });\n\n this.eventQueue = new EventQueue({\n httpClient: this.httpClient,\n logger: this.logger,\n sessionId: this.sessionId,\n environmentId: '', // Will be set after init\n sdkVersion: SDK_VERSION,\n });\n\n // Apply bootstrap values\n this.applyBootstrap();\n\n this.logger.info('FlagKit client created', {\n offline: this.config.offline,\n });\n }\n\n /**\n * Initialize the SDK by fetching flag configurations\n */\n async initialize(): Promise<void> {\n if (this.readyPromise) {\n return this.readyPromise;\n }\n\n this.readyPromise = this.doInitialize();\n return this.readyPromise;\n }\n\n private async doInitialize(): Promise<void> {\n if (this.config.offline) {\n this.logger.info('Offline mode enabled, skipping initialization');\n this.isReadyFlag = true;\n this.config.onReady?.();\n return;\n }\n\n try {\n this.logger.debug('Initializing SDK');\n\n const response = await this.httpClient.get<InitResponse>('/sdk/init');\n const data = response.data;\n\n // Set environment ID for event tracking\n this.eventQueue.setEnvironmentId(data.environmentId);\n\n // Check SDK version metadata and emit warnings\n this.checkVersionMetadata(data);\n\n // Update cache with flags\n this.cache.setMany(data.flags, this.config.cacheTTL);\n this.lastUpdateTime = data.serverTime;\n\n // Start streaming or polling for real-time updates\n if (this.config.streaming.enabled) {\n this.startStreaming();\n } else if (this.config.enablePolling) {\n this.startPolling(data.pollingIntervalSeconds * 1000);\n }\n\n this.isReadyFlag = true;\n this.logger.info('SDK initialized', {\n flagCount: data.flags.length,\n environment: data.environment,\n });\n\n this.config.onReady?.();\n } catch (error) {\n const flagKitError =\n error instanceof FlagKitError\n ? error\n : new InitializationError(\n 'INIT_FAILED',\n error instanceof Error ? error.message : 'Unknown error'\n );\n\n this.logger.error('SDK initialization failed', {\n error: flagKitError.message,\n });\n\n this.config.onError?.(flagKitError);\n\n // Mark as ready anyway (will use cache/bootstrap/defaults)\n this.isReadyFlag = true;\n this.config.onReady?.();\n\n throw flagKitError;\n }\n }\n\n /**\n * Check if SDK is ready\n */\n isReady(): boolean {\n return this.isReadyFlag;\n }\n\n /**\n * Wait for SDK to be ready\n */\n async waitForReady(): Promise<void> {\n if (this.isReadyFlag) {\n return;\n }\n\n if (this.readyPromise) {\n try {\n await this.readyPromise;\n } catch {\n // Ignore errors - SDK is still usable with defaults\n }\n }\n }\n\n /**\n * Evaluate a boolean flag\n */\n async getBooleanValue(\n key: string,\n defaultValue: boolean,\n context?: EvaluationContext\n ): Promise<boolean> {\n const result = await this.evaluateFlag<boolean>(key, defaultValue, context, 'boolean');\n return result.value;\n }\n\n /**\n * Evaluate a string flag\n */\n async getStringValue(\n key: string,\n defaultValue: string,\n context?: EvaluationContext\n ): Promise<string> {\n const result = await this.evaluateFlag<string>(key, defaultValue, context, 'string');\n return result.value;\n }\n\n /**\n * Evaluate a number flag\n */\n async getNumberValue(\n key: string,\n defaultValue: number,\n context?: EvaluationContext\n ): Promise<number> {\n const result = await this.evaluateFlag<number>(key, defaultValue, context, 'number');\n return result.value;\n }\n\n /**\n * Evaluate a JSON flag\n */\n async getJsonValue<T extends Record<string, unknown>>(\n key: string,\n defaultValue: T,\n context?: EvaluationContext\n ): Promise<T> {\n const result = await this.evaluateFlag<T>(key, defaultValue, context, 'json');\n return result.value;\n }\n\n /**\n * Evaluate a flag and return full result details\n */\n async evaluate(key: string, context?: EvaluationContext): Promise<EvaluationResult> {\n return this.evaluateFlag<FlagValue>(key, null as unknown as FlagValue, context);\n }\n\n /**\n * Synchronously get a boolean flag value from cache\n * Returns the default value if not cached\n */\n getBooleanValueSync(key: string, defaultValue: boolean): boolean {\n const result = this.evaluateFlagSync<boolean>(key, defaultValue, 'boolean');\n return result.value;\n }\n\n /**\n * Synchronously get a string flag value from cache\n * Returns the default value if not cached\n */\n getStringValueSync(key: string, defaultValue: string): string {\n const result = this.evaluateFlagSync<string>(key, defaultValue, 'string');\n return result.value;\n }\n\n /**\n * Synchronously get a number flag value from cache\n * Returns the default value if not cached\n */\n getNumberValueSync(key: string, defaultValue: number): number {\n const result = this.evaluateFlagSync<number>(key, defaultValue, 'number');\n return result.value;\n }\n\n /**\n * Synchronously get a JSON flag value from cache\n * Returns the default value if not cached\n */\n getJsonValueSync<T extends Record<string, unknown>>(key: string, defaultValue: T): T {\n const result = this.evaluateFlagSync<T>(key, defaultValue, 'json');\n return result.value;\n }\n\n /**\n * Synchronously evaluate a flag from cache and return full result details\n * Returns a default result if not cached\n */\n evaluateSync(key: string, defaultValue: FlagValue = false): EvaluationResult {\n return this.evaluateFlagSync<FlagValue>(key, defaultValue, undefined);\n }\n\n /**\n * Evaluate all flags\n */\n async evaluateAll(context?: EvaluationContext): Promise<Record<string, EvaluationResult>> {\n const results: Record<string, EvaluationResult> = {};\n const keys = this.getAllFlagKeys();\n\n for (const key of keys) {\n results[key] = await this.evaluate(key, context);\n }\n\n return results;\n }\n\n /**\n * Get bootstrap flags (handles both legacy and new format)\n */\n private getBootstrapFlags(): Record<string, unknown> {\n if (this.isBootstrapConfig(this.config.bootstrap)) {\n return (this.config.bootstrap as BootstrapConfig).flags;\n }\n return this.config.bootstrap as Record<string, unknown>;\n }\n\n /**\n * Check if a flag exists\n */\n hasFlag(key: string): boolean {\n const bootstrapFlags = this.getBootstrapFlags();\n return this.cache.has(key) || key in bootstrapFlags;\n }\n\n /**\n * Get all flag keys\n */\n getAllFlagKeys(): string[] {\n const cacheKeys = new Set(this.cache.getAllKeys());\n const bootstrapFlags = this.getBootstrapFlags();\n const bootstrapKeys = Object.keys(bootstrapFlags);\n\n for (const key of bootstrapKeys) {\n cacheKeys.add(key);\n }\n\n return Array.from(cacheKeys);\n }\n\n /**\n * Set global evaluation context\n * @throws {SecurityError} If strictPIIMode is enabled and PII is detected without privateAttributes\n */\n setContext(context: EvaluationContext): void {\n if (!isValidContext(context)) {\n this.logger.warn('Invalid context provided to setContext');\n return;\n }\n\n // Security: check for potential PII not marked as private\n if (context.custom && !context.privateAttributes?.length) {\n const piiResult = checkForPotentialPII(context.custom, 'context');\n\n if (piiResult.hasPII) {\n if (this.config.strictPIIMode) {\n throw new SecurityError(\n 'SECURITY_PII_DETECTED',\n `PII detected in context without privateAttributes: ${piiResult.fields.join(', ')}. ` +\n 'Either add these fields to privateAttributes or remove them from the context. ' +\n 'See: https://docs.flagkit.dev/sdk/security#pii-handling'\n );\n } else {\n this.logger.warn(piiResult.message);\n }\n }\n }\n\n this.contextManager.setContext(context);\n }\n\n /**\n * Get current global context\n */\n getContext(): EvaluationContext | null {\n return this.contextManager.getContext();\n }\n\n /**\n * Clear global context\n */\n clearContext(): void {\n this.contextManager.clearContext();\n }\n\n /**\n * Identify a user\n * @throws {SecurityError} If strictPIIMode is enabled and PII is detected without privateAttributes\n */\n identify(userId: string, attributes?: Partial<EvaluationContext>): void {\n // Security: check for potential PII in attributes\n if (attributes?.custom && !attributes.privateAttributes?.length) {\n const piiResult = checkForPotentialPII(attributes.custom, 'context');\n\n if (piiResult.hasPII) {\n if (this.config.strictPIIMode) {\n throw new SecurityError(\n 'SECURITY_PII_DETECTED',\n `PII detected in identify attributes without privateAttributes: ${piiResult.fields.join(', ')}. ` +\n 'Either add these fields to privateAttributes or remove them. ' +\n 'See: https://docs.flagkit.dev/sdk/security#pii-handling'\n );\n } else {\n this.logger.warn(piiResult.message);\n }\n }\n }\n\n this.contextManager.identify(userId, attributes);\n this.eventQueue.track('context.identified', { userId });\n }\n\n /**\n * Reset to anonymous user\n */\n reset(): void {\n this.contextManager.reset();\n this.eventQueue.track('context.reset');\n }\n\n /**\n * Track a custom event\n * @throws {SecurityError} If strictPIIMode is enabled and PII is detected in event data\n */\n track(eventType: string, eventData?: Record<string, unknown>): void {\n // Security: check for potential PII in event data\n if (eventData) {\n const piiResult = checkForPotentialPII(eventData, 'event');\n\n if (piiResult.hasPII) {\n if (this.config.strictPIIMode) {\n throw new SecurityError(\n 'SECURITY_PII_DETECTED',\n `PII detected in event data: ${piiResult.fields.join(', ')}. ` +\n 'Remove sensitive data from events before tracking. ' +\n 'See: https://docs.flagkit.dev/sdk/security#pii-handling'\n );\n } else {\n this.logger.warn(piiResult.message);\n }\n }\n }\n\n this.eventQueue.track(eventType, eventData);\n }\n\n /**\n * Flush pending events\n */\n async flush(): Promise<void> {\n await this.eventQueue.flush();\n }\n\n /**\n * Force refresh flags from server\n */\n async refresh(): Promise<void> {\n if (this.config.offline || this.isClosedFlag) {\n return;\n }\n\n try {\n const since = this.lastUpdateTime ?? new Date(Date.now() - 3600000).toISOString();\n const response = await this.httpClient.get<UpdatesResponse>(\n `/sdk/updates?since=${encodeURIComponent(since)}`\n );\n\n if (response.data.flags.length > 0) {\n this.cache.setMany(response.data.flags);\n this.lastUpdateTime = response.data.checkedAt;\n\n this.logger.debug('Flags refreshed', {\n count: response.data.flags.length,\n });\n\n this.config.onUpdate?.(response.data.flags);\n }\n } catch (error) {\n this.logger.warn('Failed to refresh flags', {\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n }\n\n /**\n * Close the SDK and cleanup resources\n */\n async close(): Promise<void> {\n if (this.isClosedFlag) {\n return;\n }\n\n this.isClosedFlag = true;\n this.logger.debug('Closing SDK');\n\n // Stop streaming\n this.streamingManager?.disconnect();\n this.streamingManager = null;\n this.isStreamingActive = false;\n\n // Stop polling\n this.pollingManager?.stop();\n this.pollingManager = null;\n\n // Flush events\n try {\n await this.eventQueue.flush();\n } catch (error) {\n this.logger.warn('Failed to flush events on close', {\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n\n this.logger.info('SDK closed');\n }\n\n /**\n * Synchronous flag evaluation from cache only\n * Used by React hooks for immediate value access\n */\n private evaluateFlagSync<T extends FlagValue>(\n key: string,\n defaultValue: T,\n expectedType?: string\n ): EvaluationResult<T> {\n // Validate key\n if (!isValidFlagKey(key)) {\n this.logger.warn('Invalid flag key', { key });\n return createDefaultResult(key, defaultValue, 'DEFAULT');\n }\n\n // Try cache first\n const cached = this.cache.get(key);\n if (cached) {\n // Type check if expected type provided\n if (expectedType && cached.flagType !== expectedType) {\n this.logger.warn(`Flag type mismatch: expected ${expectedType}, got ${cached.flagType}`, {\n key,\n });\n return createDefaultResult(key, defaultValue, 'EVALUATION_ERROR');\n }\n\n return {\n flagKey: key,\n value: cached.value as T,\n enabled: cached.enabled,\n reason: 'CACHED',\n version: cached.version,\n timestamp: new Date(),\n };\n }\n\n // Try stale cache\n const stale = this.cache.getStale(key);\n if (stale) {\n this.logger.debug('Using stale cached value', { key });\n return {\n flagKey: key,\n value: stale.value as T,\n enabled: stale.enabled,\n reason: 'STALE_CACHE',\n version: stale.version,\n timestamp: new Date(),\n };\n }\n\n // Try bootstrap\n const bootstrapFlags = this.getBootstrapFlags();\n if (key in bootstrapFlags) {\n this.logger.debug('Using bootstrap value', { key });\n return {\n flagKey: key,\n value: bootstrapFlags[key] as T,\n enabled: true,\n reason: 'BOOTSTRAP',\n version: 0,\n timestamp: new Date(),\n };\n }\n\n // Return default\n return createDefaultResult(key, defaultValue, 'DEFAULT');\n }\n\n /**\n * Internal flag evaluation logic\n */\n private async evaluateFlag<T extends FlagValue>(\n key: string,\n defaultValue: T,\n _context?: EvaluationContext,\n expectedType?: string\n ): Promise<EvaluationResult<T>> {\n // Apply evaluation jitter for cache timing attack protection\n if (this.config.evaluationJitter.enabled) {\n const { minMs, maxMs } = this.config.evaluationJitter;\n const jitter = minMs + Math.random() * (maxMs - minMs);\n await new Promise((resolve) => setTimeout(resolve, jitter));\n }\n\n // Validate key\n if (!isValidFlagKey(key)) {\n this.logger.warn('Invalid flag key', { key });\n return createDefaultResult(key, defaultValue, 'DEFAULT');\n }\n\n // Try cache first\n const cached = this.cache.get(key);\n if (cached) {\n // Type check if expected type provided\n if (expectedType && cached.flagType !== expectedType) {\n this.logger.warn(`Flag type mismatch: expected ${expectedType}, got ${cached.flagType}`, {\n key,\n });\n return createDefaultResult(key, defaultValue, 'EVALUATION_ERROR');\n }\n\n return {\n flagKey: key,\n value: cached.value as T,\n enabled: cached.enabled,\n reason: 'CACHED',\n version: cached.version,\n timestamp: new Date(),\n };\n }\n\n // Try stale cache\n const stale = this.cache.getStale(key);\n if (stale) {\n this.logger.debug('Using stale cached value', { key });\n return {\n flagKey: key,\n value: stale.value as T,\n enabled: stale.enabled,\n reason: 'STALE_CACHE',\n version: stale.version,\n timestamp: new Date(),\n };\n }\n\n // Try bootstrap\n const bootstrapFlags = this.getBootstrapFlags();\n if (key in bootstrapFlags) {\n const bootstrapValue = bootstrapFlags[key] as T;\n this.logger.debug('Using bootstrap value', { key });\n return createDefaultResult(key, bootstrapValue, 'BOOTSTRAP');\n }\n\n // Return default\n this.logger.debug('Flag not found, using default', { key });\n return createDefaultResult(key, defaultValue, 'FLAG_NOT_FOUND');\n }\n\n /**\n * Check if bootstrap data is in the new BootstrapConfig format\n */\n private isBootstrapConfig(data: unknown): data is BootstrapConfig {\n return (\n typeof data === 'object' &&\n data !== null &&\n 'flags' in data &&\n typeof (data as BootstrapConfig).flags === 'object'\n );\n }\n\n /**\n * Apply bootstrap values to cache\n */\n private applyBootstrap(): void {\n // Kick off async verification but don't block\n this.applyBootstrapAsync().catch((error) => {\n this.logger.error('Failed to apply bootstrap', {\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n });\n }\n\n /**\n * Apply bootstrap values to cache with async verification\n */\n private async applyBootstrapAsync(): Promise<void> {\n const bootstrap = this.config.bootstrap;\n\n // Determine if using new format or legacy format\n let flags: Record<string, unknown>;\n\n if (this.isBootstrapConfig(bootstrap)) {\n // New format with flags property\n const bootstrapConfig = bootstrap as BootstrapConfig;\n flags = bootstrapConfig.flags;\n\n // Verify signature if present and verification is enabled\n if (bootstrapConfig.signature && this.config.bootstrapVerification.enabled) {\n const result = await verifyBootstrapSignature(\n bootstrapConfig,\n this.config.apiKey,\n this.config.bootstrapVerification\n );\n\n if (!result.valid) {\n const errorMessage = `Bootstrap verification failed: ${result.error}`;\n\n switch (this.config.bootstrapVerification.onFailure) {\n case 'error':\n this.logger.error(errorMessage);\n throw new SecurityError('SECURITY_BOOTSTRAP_VERIFICATION_FAILED', errorMessage);\n\n case 'warn':\n this.logger.warn(errorMessage);\n // Continue to apply bootstrap values despite warning\n break;\n\n case 'ignore':\n // Silently continue\n break;\n }\n } else {\n this.logger.debug('Bootstrap signature verified successfully');\n }\n }\n } else {\n // Legacy format - bootstrap is directly the flags object\n flags = bootstrap as Record<string, unknown>;\n }\n\n // Apply flags to cache\n for (const [key, value] of Object.entries(flags)) {\n const flagState: FlagState = {\n key,\n value: value as FlagValue,\n enabled: true,\n version: 0,\n flagType: this.inferFlagType(value),\n lastModified: new Date().toISOString(),\n };\n this.cache.set(key, flagState, Infinity); // Bootstrap values don't expire\n }\n }\n\n /**\n * Infer flag type from value\n */\n private inferFlagType(value: unknown): FlagState['flagType'] {\n if (typeof value === 'boolean') return 'boolean';\n if (typeof value === 'string') return 'string';\n if (typeof value === 'number') return 'number';\n return 'json';\n }\n\n /**\n * Start background polling\n */\n private startPolling(interval: number): void {\n if (this.pollingManager) {\n return;\n }\n\n this.pollingManager = new PollingManager({\n interval: Math.max(interval, this.config.pollingInterval),\n onPoll: () => this.refresh(),\n logger: this.logger,\n });\n\n this.pollingManager.start();\n }\n\n /**\n * Start SSE streaming for real-time flag updates\n */\n private startStreaming(): void {\n if (this.streamingManager) {\n return;\n }\n\n const baseUrl = getBaseUrl(this.config.localPort);\n\n this.streamingManager = new StreamingManager({\n baseUrl,\n apiKey: this.config.apiKey,\n reconnectInterval: this.config.streaming.reconnectInterval,\n maxReconnectAttempts: this.config.streaming.maxReconnectAttempts,\n heartbeatInterval: this.config.streaming.heartbeatInterval,\n logger: this.logger,\n onFlagUpdate: (flag: FlagState) => this.handleStreamFlagUpdate(flag),\n onFlagDelete: (key: string) => this.handleStreamFlagDelete(key),\n onFlagsReset: (flags: FlagState[]) => this.handleStreamFlagsReset(flags),\n onFallbackToPolling: () => this.handleStreamingFallback(),\n });\n\n this.streamingManager.connect();\n this.isStreamingActive = true;\n this.logger.info('Streaming started for real-time flag updates');\n }\n\n /**\n * Handle flag update from streaming\n */\n private handleStreamFlagUpdate(flag: FlagState): void {\n this.cache.set(flag.key, flag);\n this.logger.debug('Flag updated via streaming', { key: flag.key });\n this.config.onUpdate?.([flag]);\n }\n\n /**\n * Handle flag deletion from streaming\n */\n private handleStreamFlagDelete(key: string): void {\n this.cache.delete(key);\n this.logger.debug('Flag deleted via streaming', { key });\n }\n\n /**\n * Handle flags reset from streaming\n */\n private handleStreamFlagsReset(flags: FlagState[]): void {\n this.cache.clear();\n this.cache.setMany(flags, this.config.cacheTTL);\n this.logger.debug('Flags reset via streaming', { count: flags.length });\n this.config.onUpdate?.(flags);\n }\n\n /**\n * Handle streaming fallback to polling\n */\n private handleStreamingFallback(): void {\n this.isStreamingActive = false;\n this.logger.warn('Streaming failed, falling back to polling');\n\n // Start polling as fallback\n if (this.config.enablePolling && !this.pollingManager) {\n this.startPolling(this.config.pollingInterval);\n }\n }\n\n /**\n * Check if streaming is currently active\n */\n isStreaming(): boolean {\n return this.isStreamingActive && this.streamingManager?.isConnected() === true;\n }\n\n /**\n * Check SDK version metadata from init response and emit appropriate warnings.\n *\n * Per spec, the SDK should parse and surface:\n * - sdkVersionMin: Minimum required version (older may not work)\n * - sdkVersionRecommended: Recommended version for optimal experience\n * - sdkVersionLatest: Latest available version\n * - deprecationWarning: Server-provided deprecation message\n */\n private checkVersionMetadata(response: InitResponse): void {\n const metadata = response.metadata;\n if (!metadata) {\n return;\n }\n\n // Check for server-provided deprecation warning first\n if (metadata.deprecationWarning) {\n this.logger.warn(`[FlagKit] Deprecation Warning: ${metadata.deprecationWarning}`);\n }\n\n // Check minimum version requirement\n if (metadata.sdkVersionMin && isVersionLessThan(SDK_VERSION, metadata.sdkVersionMin)) {\n this.logger.error(\n `[FlagKit] SDK version ${SDK_VERSION} is below minimum required version ${metadata.sdkVersionMin}. ` +\n 'Some features may not work correctly. Please upgrade the SDK.'\n );\n }\n\n // Check recommended version\n if (\n metadata.sdkVersionRecommended &&\n isVersionLessThan(SDK_VERSION, metadata.sdkVersionRecommended)\n ) {\n this.logger.warn(\n `[FlagKit] SDK version ${SDK_VERSION} is below recommended version ${metadata.sdkVersionRecommended}. ` +\n 'Consider upgrading for the best experience.'\n );\n }\n\n // Log if a newer version is available (info level, not a warning)\n if (\n metadata.sdkVersionLatest &&\n isVersionLessThan(SDK_VERSION, metadata.sdkVersionLatest) &&\n // Only log if we haven't already warned about recommended\n (!metadata.sdkVersionRecommended ||\n !isVersionLessThan(SDK_VERSION, metadata.sdkVersionRecommended))\n ) {\n this.logger.info(\n `[FlagKit] SDK version ${SDK_VERSION} - a newer version ${metadata.sdkVersionLatest} is available.`\n );\n }\n }\n}\n","import type { FlagKitOptions } from './types/config';\nimport { FlagKitClient } from './client';\nimport { InitializationError } from './errors/flagkit-error';\n\n/**\n * FlagKit SDK static factory\n *\n * Provides a singleton interface for SDK initialization and access.\n */\nexport class FlagKit {\n private static instance: FlagKitClient | null = null;\n private static initPromise: Promise<FlagKitClient> | null = null;\n\n /**\n * Initialize the FlagKit SDK\n *\n * @param options SDK configuration options\n * @returns Promise resolving to the FlagKit client\n *\n * @example\n * ```typescript\n * const client = await FlagKit.initialize({\n * apiKey: 'sdk_your_api_key',\n * onReady: () => console.log('FlagKit ready!'),\n * });\n *\n * const darkMode = client.getBooleanValue('dark-mode', false);\n * ```\n */\n static async initialize(options: FlagKitOptions): Promise<FlagKitClient> {\n // Check if already initialized\n if (FlagKit.instance) {\n throw new InitializationError(\n 'INIT_ALREADY_INITIALIZED',\n 'FlagKit is already initialized. Call FlagKit.reset() first to reinitialize.'\n );\n }\n\n // Check if initialization is in progress\n if (FlagKit.initPromise) {\n return FlagKit.initPromise;\n }\n\n // Start initialization\n FlagKit.initPromise = FlagKit.doInitialize(options);\n\n try {\n return await FlagKit.initPromise;\n } finally {\n FlagKit.initPromise = null;\n }\n }\n\n /**\n * Get the current FlagKit client instance\n *\n * @throws Error if SDK is not initialized\n */\n static getInstance(): FlagKitClient {\n if (!FlagKit.instance) {\n throw new Error(\n 'FlagKit is not initialized. Call FlagKit.initialize() first.'\n );\n }\n return FlagKit.instance;\n }\n\n /**\n * Check if SDK is initialized\n */\n static isInitialized(): boolean {\n return FlagKit.instance !== null;\n }\n\n /**\n * Reset the SDK (for testing or reinitialization)\n */\n static async reset(): Promise<void> {\n if (FlagKit.instance) {\n await FlagKit.instance.close();\n FlagKit.instance = null;\n }\n FlagKit.initPromise = null;\n }\n\n /**\n * Internal initialization logic\n */\n private static async doInitialize(\n options: FlagKitOptions\n ): Promise<FlagKitClient> {\n const client = new FlagKitClient(options);\n\n try {\n await client.initialize();\n } catch {\n // Initialization failed but client is still usable\n // with cached/bootstrap/default values\n }\n\n FlagKit.instance = client;\n return client;\n }\n}\n","import type { Storage } from './storage';\nimport { isBrowser } from '../utils/platform';\n\n/**\n * Browser localStorage adapter\n */\nexport class LocalStorage implements Storage {\n private readonly prefix: string;\n private available: boolean | null = null;\n\n constructor(prefix = 'flagkit_') {\n this.prefix = prefix;\n }\n\n /**\n * Get an item from localStorage\n */\n get(key: string): string | null {\n if (!this.isAvailable()) {\n return null;\n }\n\n try {\n return localStorage.getItem(this.prefixKey(key));\n } catch {\n return null;\n }\n }\n\n /**\n * Set an item in localStorage\n */\n set(key: string, value: string): void {\n if (!this.isAvailable()) {\n return;\n }\n\n try {\n localStorage.setItem(this.prefixKey(key), value);\n } catch {\n // Storage full or other error\n }\n }\n\n /**\n * Remove an item from localStorage\n */\n remove(key: string): void {\n if (!this.isAvailable()) {\n return;\n }\n\n try {\n localStorage.removeItem(this.prefixKey(key));\n } catch {\n // Ignore errors\n }\n }\n\n /**\n * Clear all FlagKit items from localStorage\n */\n clear(): void {\n if (!this.isAvailable()) {\n return;\n }\n\n try {\n const keys: string[] = [];\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key?.startsWith(this.prefix)) {\n keys.push(key);\n }\n }\n for (const key of keys) {\n localStorage.removeItem(key);\n }\n } catch {\n // Ignore errors\n }\n }\n\n /**\n * Check if localStorage is available\n */\n isAvailable(): boolean {\n if (this.available !== null) {\n return this.available;\n }\n\n if (!isBrowser()) {\n this.available = false;\n return false;\n }\n\n try {\n const testKey = '__flagkit_test__';\n localStorage.setItem(testKey, 'test');\n localStorage.removeItem(testKey);\n this.available = true;\n return true;\n } catch {\n this.available = false;\n return false;\n }\n }\n\n /**\n * Add prefix to key\n */\n private prefixKey(key: string): string {\n return `${this.prefix}${key}`;\n }\n}\n","import type { Storage } from './storage';\n\n/**\n * In-memory storage adapter\n * Used as fallback when localStorage is not available\n */\nexport class MemoryStorage implements Storage {\n private readonly store = new Map<string, string>();\n\n /**\n * Get an item from memory\n */\n get(key: string): string | null {\n return this.store.get(key) ?? null;\n }\n\n /**\n * Set an item in memory\n */\n set(key: string, value: string): void {\n this.store.set(key, value);\n }\n\n /**\n * Remove an item from memory\n */\n remove(key: string): void {\n this.store.delete(key);\n }\n\n /**\n * Clear all items from memory\n */\n clear(): void {\n this.store.clear();\n }\n\n /**\n * Memory storage is always available\n */\n isAvailable(): boolean {\n return true;\n }\n}\n","/**\n * Encrypted storage wrapper using AES-256-GCM\n *\n * Wraps another storage implementation and encrypts/decrypts data automatically.\n * Uses Web Crypto API in browser and Node.js crypto in server environments.\n */\nimport type { Storage } from './storage';\nimport { isBrowser, isNode } from '../utils/platform';\nimport type { Logger } from '../utils/logger';\n\n/**\n * Configuration for encrypted storage\n */\nexport interface EncryptedStorageConfig {\n /** The underlying storage to wrap */\n storage: Storage;\n\n /** API key used to derive encryption key */\n apiKey: string;\n\n /** Optional logger for debugging */\n logger?: Logger;\n}\n\n/**\n * Encrypted data format stored in underlying storage\n */\ninterface EncryptedData {\n /** Base64-encoded initialization vector */\n iv: string;\n\n /** Base64-encoded encrypted data */\n data: string;\n\n /** Base64-encoded authentication tag (for GCM) */\n tag: string;\n\n /** Version of encryption format */\n version: number;\n}\n\n// Encryption constants\nconst ENCRYPTION_VERSION = 1;\nconst IV_LENGTH = 12; // 96 bits for GCM\nconst TAG_LENGTH = 16; // 128 bits for GCM\nconst SALT = 'FlagKit-v1-cache'; // Static salt for key derivation\n\n/**\n * Encrypted storage wrapper\n *\n * Provides transparent encryption for cached data using AES-256-GCM.\n * Falls back to unencrypted storage if encryption is unavailable.\n */\nexport class EncryptedStorage implements Storage {\n private readonly storage: Storage;\n private readonly apiKey: string;\n private readonly logger?: Logger;\n private derivedKey: CryptoKey | Buffer | null = null;\n private keyDerivationPromise: Promise<void> | null = null;\n private cryptoAvailable: boolean | null = null;\n\n constructor(config: EncryptedStorageConfig) {\n this.storage = config.storage;\n this.apiKey = config.apiKey;\n this.logger = config.logger;\n\n // Start key derivation immediately\n this.keyDerivationPromise = this.deriveKey().catch((error) => {\n this.logger?.warn('Failed to derive encryption key, storage will be unencrypted', {\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n });\n }\n\n /**\n * Check if crypto is available\n */\n private isCryptoAvailable(): boolean {\n if (this.cryptoAvailable !== null) {\n return this.cryptoAvailable;\n }\n\n if (isBrowser()) {\n this.cryptoAvailable = typeof crypto !== 'undefined' && crypto.subtle !== undefined;\n } else if (isNode()) {\n try {\n require('crypto');\n this.cryptoAvailable = true;\n } catch {\n this.cryptoAvailable = false;\n }\n } else {\n // Try Web Crypto as fallback\n this.cryptoAvailable = typeof crypto !== 'undefined' && crypto.subtle !== undefined;\n }\n\n return this.cryptoAvailable;\n }\n\n /**\n * Derive encryption key from API key\n */\n private async deriveKey(): Promise<void> {\n if (!this.isCryptoAvailable()) {\n this.logger?.debug('Crypto not available, skipping key derivation');\n return;\n }\n\n try {\n if (isBrowser() || (typeof crypto !== 'undefined' && crypto.subtle)) {\n await this.deriveKeyWebCrypto();\n } else if (isNode()) {\n await this.deriveKeyNode();\n }\n } catch (error) {\n this.logger?.warn('Key derivation failed', {\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n }\n\n /**\n * Derive key using Web Crypto API\n */\n private async deriveKeyWebCrypto(): Promise<void> {\n const encoder = new TextEncoder();\n const keyMaterial = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(this.apiKey),\n 'PBKDF2',\n false,\n ['deriveKey']\n );\n\n this.derivedKey = await crypto.subtle.deriveKey(\n {\n name: 'PBKDF2',\n salt: encoder.encode(SALT),\n iterations: 100000,\n hash: 'SHA-256',\n },\n keyMaterial,\n { name: 'AES-GCM', length: 256 },\n false,\n ['encrypt', 'decrypt']\n );\n }\n\n /**\n * Derive key using Node.js crypto\n */\n private async deriveKeyNode(): Promise<void> {\n const nodeCrypto = await import('crypto');\n this.derivedKey = nodeCrypto.pbkdf2Sync(\n this.apiKey,\n SALT,\n 100000,\n 32, // 256 bits\n 'sha256'\n );\n }\n\n /**\n * Wait for key derivation to complete\n */\n private async ensureKeyReady(): Promise<boolean> {\n if (this.keyDerivationPromise) {\n await this.keyDerivationPromise;\n }\n return this.derivedKey !== null;\n }\n\n /**\n * Encrypt data using AES-256-GCM\n */\n private async encrypt(plaintext: string): Promise<string | null> {\n if (!(await this.ensureKeyReady())) {\n return null;\n }\n\n try {\n if (isBrowser() || (typeof crypto !== 'undefined' && crypto.subtle)) {\n return this.encryptWebCrypto(plaintext);\n } else if (isNode()) {\n return this.encryptNode(plaintext);\n }\n return null;\n } catch (error) {\n this.logger?.warn('Encryption failed', {\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n return null;\n }\n }\n\n /**\n * Encrypt using Web Crypto API\n */\n private async encryptWebCrypto(plaintext: string): Promise<string> {\n const encoder = new TextEncoder();\n const iv = crypto.getRandomValues(new Uint8Array(IV_LENGTH));\n const plaintextData = encoder.encode(plaintext);\n\n const ciphertext = await crypto.subtle.encrypt(\n { name: 'AES-GCM', iv: iv.buffer as ArrayBuffer, tagLength: TAG_LENGTH * 8 },\n this.derivedKey as CryptoKey,\n plaintextData.buffer as ArrayBuffer\n );\n\n // In Web Crypto, the tag is appended to the ciphertext\n const ciphertextArray = new Uint8Array(ciphertext);\n const data = ciphertextArray.slice(0, -TAG_LENGTH);\n const tag = ciphertextArray.slice(-TAG_LENGTH);\n\n const encryptedData: EncryptedData = {\n iv: this.arrayToBase64(iv),\n data: this.arrayToBase64(data),\n tag: this.arrayToBase64(tag),\n version: ENCRYPTION_VERSION,\n };\n\n return JSON.stringify(encryptedData);\n }\n\n /**\n * Encrypt using Node.js crypto\n */\n private async encryptNode(plaintext: string): Promise<string> {\n const nodeCrypto = await import('crypto');\n const iv = nodeCrypto.randomBytes(IV_LENGTH);\n\n const cipher = nodeCrypto.createCipheriv(\n 'aes-256-gcm',\n this.derivedKey as Buffer,\n iv\n );\n\n const encrypted = Buffer.concat([\n cipher.update(plaintext, 'utf8'),\n cipher.final(),\n ]);\n\n const tag = cipher.getAuthTag();\n\n const encryptedData: EncryptedData = {\n iv: iv.toString('base64'),\n data: encrypted.toString('base64'),\n tag: tag.toString('base64'),\n version: ENCRYPTION_VERSION,\n };\n\n return JSON.stringify(encryptedData);\n }\n\n /**\n * Decrypt data using AES-256-GCM\n */\n private async decrypt(encrypted: string): Promise<string | null> {\n if (!(await this.ensureKeyReady())) {\n return null;\n }\n\n try {\n const encryptedData = JSON.parse(encrypted) as EncryptedData;\n\n if (encryptedData.version !== ENCRYPTION_VERSION) {\n this.logger?.warn('Unsupported encryption version', {\n version: encryptedData.version,\n });\n return null;\n }\n\n if (isBrowser() || (typeof crypto !== 'undefined' && crypto.subtle)) {\n return await this.decryptWebCrypto(encryptedData);\n } else if (isNode()) {\n return await this.decryptNode(encryptedData);\n }\n return null;\n } catch (error) {\n this.logger?.warn('Decryption failed', {\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n return null;\n }\n }\n\n /**\n * Decrypt using Web Crypto API\n */\n private async decryptWebCrypto(encryptedData: EncryptedData): Promise<string> {\n const decoder = new TextDecoder();\n const iv = this.base64ToArray(encryptedData.iv);\n const data = this.base64ToArray(encryptedData.data);\n const tag = this.base64ToArray(encryptedData.tag);\n\n // In Web Crypto, we need to append the tag to the ciphertext\n const ciphertext = new Uint8Array(data.length + tag.length);\n ciphertext.set(data, 0);\n ciphertext.set(tag, data.length);\n\n const plaintext = await crypto.subtle.decrypt(\n { name: 'AES-GCM', iv: iv.buffer as ArrayBuffer, tagLength: TAG_LENGTH * 8 },\n this.derivedKey as CryptoKey,\n ciphertext.buffer as ArrayBuffer\n );\n\n return decoder.decode(plaintext);\n }\n\n /**\n * Decrypt using Node.js crypto\n */\n private async decryptNode(encryptedData: EncryptedData): Promise<string> {\n const nodeCrypto = await import('crypto');\n const iv = Buffer.from(encryptedData.iv, 'base64');\n const data = Buffer.from(encryptedData.data, 'base64');\n const tag = Buffer.from(encryptedData.tag, 'base64');\n\n const decipher = nodeCrypto.createDecipheriv(\n 'aes-256-gcm',\n this.derivedKey as Buffer,\n iv\n );\n decipher.setAuthTag(tag);\n\n const decrypted = Buffer.concat([\n decipher.update(data),\n decipher.final(),\n ]);\n\n return decrypted.toString('utf8');\n }\n\n /**\n * Convert Uint8Array to Base64\n */\n private arrayToBase64(array: Uint8Array): string {\n if (typeof Buffer !== 'undefined') {\n return Buffer.from(array).toString('base64');\n }\n // Browser fallback\n let binary = '';\n for (let i = 0; i < array.length; i++) {\n binary += String.fromCharCode(array[i]);\n }\n return btoa(binary);\n }\n\n /**\n * Convert Base64 to Uint8Array\n */\n private base64ToArray(base64: string): Uint8Array {\n if (typeof Buffer !== 'undefined') {\n return new Uint8Array(Buffer.from(base64, 'base64'));\n }\n // Browser fallback\n const binary = atob(base64);\n const array = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n array[i] = binary.charCodeAt(i);\n }\n return array;\n }\n\n /**\n * Get an item from storage (decrypted)\n */\n get(key: string): string | null {\n const encrypted = this.storage.get(key);\n if (!encrypted) {\n return null;\n }\n\n // Try to parse as encrypted data\n try {\n const parsed = JSON.parse(encrypted);\n if (parsed.version && parsed.iv && parsed.data && parsed.tag) {\n // This is encrypted data - we need async decryption\n // For sync interface, we'll store a promise and return null\n // The caller should use getAsync for encrypted data\n return null;\n }\n } catch {\n // Not encrypted, return as-is (legacy data)\n return encrypted;\n }\n\n return null;\n }\n\n /**\n * Check if data looks like encrypted format\n */\n private isEncryptedFormat(data: string): boolean {\n try {\n const parsed = JSON.parse(data);\n return (\n typeof parsed === 'object' &&\n parsed !== null &&\n 'iv' in parsed &&\n 'data' in parsed &&\n 'tag' in parsed &&\n 'version' in parsed\n );\n } catch {\n return false;\n }\n }\n\n /**\n * Get an item from storage (async, with decryption)\n */\n async getAsync(key: string): Promise<string | null> {\n const encrypted = this.storage.get(key);\n if (!encrypted) {\n return null;\n }\n\n // Check if data looks like encrypted format\n if (this.isEncryptedFormat(encrypted)) {\n // Try to decrypt - return null if decryption fails\n return this.decrypt(encrypted);\n }\n\n // Not encrypted format, return as-is (legacy unencrypted data)\n return encrypted;\n }\n\n /**\n * Set an item in storage (encrypted)\n */\n set(key: string, value: string): void {\n // For sync interface, we store unencrypted\n // Use setAsync for encrypted storage\n this.storage.set(key, value);\n }\n\n /**\n * Set an item in storage (async, with encryption)\n */\n async setAsync(key: string, value: string): Promise<void> {\n const encrypted = await this.encrypt(value);\n if (encrypted) {\n this.storage.set(key, encrypted);\n } else {\n // Fallback to unencrypted if encryption fails\n this.storage.set(key, value);\n }\n }\n\n /**\n * Remove an item from storage\n */\n remove(key: string): void {\n this.storage.remove(key);\n }\n\n /**\n * Clear all items from storage\n */\n clear(): void {\n this.storage.clear();\n }\n\n /**\n * Check if storage is available\n */\n isAvailable(): boolean {\n return this.storage.isAvailable();\n }\n\n /**\n * Check if encryption is available\n */\n isEncryptionAvailable(): boolean {\n return this.derivedKey !== null;\n }\n}\n","// Main exports\nexport { FlagKit } from './flagkit';\nexport { FlagKitClient } from './client';\n\n// Types\nexport type { FlagKitOptions, ResolvedConfig } from './types/config';\nexport type { EvaluationContext, ResolvedContext } from './types/context';\nexport type {\n FlagType,\n FlagValue,\n FlagState,\n EvaluationResult,\n EvaluationReason,\n InitResponse,\n EvaluateResponse,\n BatchEvaluateResponse,\n UpdatesResponse,\n} from './types/flag';\nexport type {\n BaseEvent,\n EventMetadata,\n FlagEvaluatedEvent,\n CustomEvent,\n SystemEventType,\n EventQueueConfig,\n BatchEventsResponse,\n} from './types/events';\n\n// Errors\nexport {\n FlagKitError,\n InitializationError,\n AuthenticationError,\n NetworkError,\n EvaluationError,\n SecurityError,\n isFlagKitError,\n isRetryableError,\n createErrorFromResponse,\n} from './errors/flagkit-error';\nexport { ErrorCodes, type ErrorCode, isRetryableCode } from './errors/error-codes';\n\n// Utilities\nexport type { Logger, LogLevel, LogEntry } from './utils/logger';\nexport { ConsoleLogger, NoopLogger, createLogger } from './utils/logger';\n\n// Security utilities\nexport type { SecurityConfig, SignedPayload, PIIDetectionResult } from './utils/security';\nexport {\n isPotentialPIIField,\n detectPotentialPII,\n checkForPotentialPII,\n warnIfPotentialPII,\n isServerKey,\n isClientKey,\n warnIfServerKeyInBrowser,\n isProductionEnvironment,\n getKeyId,\n generateHMACSHA256,\n signPayload,\n createRequestSignature,\n verifySignedPayload,\n DEFAULT_SECURITY_CONFIG,\n} from './utils/security';\n\n// Storage\nexport type { Storage } from './storage/storage';\nexport { LocalStorage } from './storage/local-storage';\nexport { MemoryStorage } from './storage/memory-storage';\nexport { EncryptedStorage } from './storage/encrypted-storage';\nexport type { EncryptedStorageConfig } from './storage/encrypted-storage';\n\n// HTTP (for advanced usage)\nexport { HttpClient, SDK_VERSION } from './http/http-client';\nexport { CircuitBreaker, CircuitState, CircuitOpenError } from './http/circuit-breaker';\nexport { withRetry, calculateBackoff, parseRetryAfter } from './http/retry';\nexport type { RetryConfig } from './http/retry';\nexport type { CircuitBreakerConfig } from './http/circuit-breaker';\nexport type { UsageMetrics, UsageUpdateCallback, HttpResponse } from './http/http-client';\n\n// Streaming (for advanced usage)\nexport { StreamingManager } from './core/streaming-manager';\nexport type {\n StreamEventType,\n StreamEvent,\n StreamingConfig,\n StreamingState,\n StreamTokenResponse,\n StreamErrorCode,\n StreamErrorData,\n} from './core/streaming-manager';\n\n// Default export\nexport default FlagKit;\n\nimport { FlagKit } from './flagkit';\n"]}