{"version":3,"file":"flag-engine.mjs","sources":["../../../../src/lib/flags/advanced/flag-engine.ts"],"sourcesContent":["/**\n * @fileoverview Core flag evaluation engine with comprehensive targeting support.\n *\n * This module provides the main evaluation engine for feature flags with support for:\n * - Targeting rules with complex conditions\n * - Percentage-based rollouts with consistent hashing\n * - Segment-based targeting\n * - Multi-variate flags\n * - Dependency resolution\n * - Caching and offline support\n *\n * @module flags/advanced/flag-engine\n *\n * @example\n * ```typescript\n * const engine = new FlagEngine({\n *   debug: process.env.NODE_ENV === 'development',\n *   offlineMode: false,\n * });\n *\n * // Register flags\n * engine.registerFlags(flagDefinitions);\n *\n * // Set context\n * engine.setContext({\n *   user: { id: 'user-123', email: 'user@example.com' },\n *   application: { environment: 'production' },\n * });\n *\n * // Evaluate a flag\n * const result = engine.evaluate('new-feature');\n * console.log(result.value); // true/false or variant value\n * ```\n */\n\nimport type {\n  FeatureFlag,\n  FlagId,\n  EvaluationContext,\n  EvaluationResult,\n  EvaluationReason,\n  EvaluationError,\n  Variant,\n  Segment,\n  FlagEngineConfig,\n  FlagEvaluationEvent,\n  FlagExposureEvent,\n  FlagChangeEvent,\n  JsonValue,\n  FlagDependency,\n} from './types';\nimport { TargetingRulesEngine } from './targeting-rules';\nimport { PercentageRolloutEngine } from './percentage-rollout';\nimport { SegmentMatcher } from './flag-segments';\nimport { DependencyResolver } from './flag-dependencies';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst DEFAULT_CACHE_TTL = 5 * 60 * 1000; // 5 minutes\n\n// ============================================================================\n// MurmurHash3 Implementation (for consistent hashing)\n// ============================================================================\n\n/**\n * MurmurHash3 implementation for consistent percentage rollouts.\n * Provides good distribution and is fast for short strings.\n */\nfunction murmurHash3(key: string, seed: number = 0): number {\n  const remainder = key.length & 3; // key.length % 4\n  const bytes = key.length - remainder;\n  let h1 = seed;\n  const c1 = 0xcc9e2d51;\n  const c2 = 0x1b873593;\n  let i = 0;\n\n  while (i < bytes) {\n    let k1 =\n      (key.charCodeAt(i) & 0xff) |\n      ((key.charCodeAt(++i) & 0xff) << 8) |\n      ((key.charCodeAt(++i) & 0xff) << 16) |\n      ((key.charCodeAt(++i) & 0xff) << 24);\n    ++i;\n\n    k1 =\n      ((k1 & 0xffff) * c1 + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff;\n    k1 = (k1 << 15) | (k1 >>> 17);\n    k1 =\n      ((k1 & 0xffff) * c2 + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff;\n\n    h1 ^= k1;\n    h1 = (h1 << 13) | (h1 >>> 19);\n    const h1b =\n      ((h1 & 0xffff) * 5 + ((((h1 >>> 16) * 5) & 0xffff) << 16)) & 0xffffffff;\n    h1 = (h1b & 0xffff) + 0x6b64 + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16);\n  }\n\n  let k1 = 0;\n\n  switch (remainder) {\n    case 3:\n      k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16;\n      break;\n    case 2:\n      k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8;\n      break;\n    case 1:\n      k1 ^= key.charCodeAt(i) & 0xff;\n      k1 =\n        ((k1 & 0xffff) * c1 + ((((k1 >>> 16) * c1) & 0xffff) << 16)) &\n        0xffffffff;\n      k1 = (k1 << 15) | (k1 >>> 17);\n      k1 =\n        ((k1 & 0xffff) * c2 + ((((k1 >>> 16) * c2) & 0xffff) << 16)) &\n        0xffffffff;\n      h1 ^= k1;\n  }\n\n  h1 ^= key.length;\n\n  h1 ^= h1 >>> 16;\n  h1 =\n    ((h1 & 0xffff) * 0x85ebca6b +\n      ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) &\n    0xffffffff;\n  h1 ^= h1 >>> 13;\n  h1 =\n    ((h1 & 0xffff) * 0xc2b2ae35 +\n      ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16)) &\n    0xffffffff;\n  h1 ^= h1 >>> 16;\n\n  return h1 >>> 0;\n}\n\n/**\n * Default hash function that returns a value between 0 and 100.\n */\nfunction defaultHashFunction(key: string, salt: string = ''): number {\n  const hash = murmurHash3(key + salt);\n  return (hash % 10000) / 100; // Returns 0.00 to 99.99\n}\n\n// ============================================================================\n// Cache Implementation\n// ============================================================================\n\ninterface CacheEntry<T> {\n  value: T;\n  expiresAt: number;\n  isStale: boolean;\n}\n\n/**\n * Simple in-memory cache with TTL support.\n */\nclass EvaluationCache {\n  private cache = new Map<string, CacheEntry<EvaluationResult>>();\n  private readonly ttl: number;\n\n  constructor(ttl: number = DEFAULT_CACHE_TTL) {\n    this.ttl = ttl;\n  }\n\n  /**\n   * Get a cached evaluation result.\n   */\n  get(flagKey: string, context: EvaluationContext): EvaluationResult | null {\n    const key = this.generateKey(flagKey, context);\n    const entry = this.cache.get(key);\n\n    if (!entry) {\n      return null;\n    }\n\n    const now = Date.now();\n    if (now > entry.expiresAt) {\n      // Entry is expired but return as stale\n      entry.isStale = true;\n    }\n\n    return entry.isStale ? { ...entry.value, isStale: true } : entry.value;\n  }\n\n  /**\n   * Set a cached evaluation result.\n   */\n  set(\n    flagKey: string,\n    context: EvaluationContext,\n    result: EvaluationResult\n  ): void {\n    const key = this.generateKey(flagKey, context);\n    this.cache.set(key, {\n      value: result,\n      expiresAt: Date.now() + this.ttl,\n      isStale: false,\n    });\n  }\n\n  /**\n   * Invalidate cache for a specific flag.\n   */\n  invalidate(flagKey: string): void {\n    for (const key of this.cache.keys()) {\n      if (key.startsWith(`${flagKey}:`)) {\n        this.cache.delete(key);\n      }\n    }\n  }\n\n  /**\n   * Clear all cached entries.\n   */\n  clear(): void {\n    this.cache.clear();\n  }\n\n  /**\n   * Get cache statistics.\n   */\n  getStats(): { size: number; keys: string[] } {\n    return {\n      size: this.cache.size,\n      keys: Array.from(this.cache.keys()),\n    };\n  }\n\n  /**\n   * Generate a cache key from flag key and context.\n   */\n  private generateKey(flagKey: string, context: EvaluationContext): string {\n    const userId = context.user?.id ?? 'anonymous';\n    const sessionId = context.session?.sessionId ?? '';\n    return `${flagKey}:${userId}:${sessionId}`;\n  }\n}\n\n// ============================================================================\n// Flag Engine\n// ============================================================================\n\n/**\n * Core feature flag evaluation engine.\n *\n * Provides comprehensive flag evaluation with support for targeting rules,\n * percentage rollouts, segments, and dependencies.\n */\nexport class FlagEngine {\n  private flags = new Map<FlagId, FeatureFlag>();\n  private segments = new Map<string, Segment>();\n  private context: EvaluationContext = {};\n  private cache: EvaluationCache;\n  private config: FlagEngineConfig;\n  private targetingEngine: TargetingRulesEngine;\n  private rolloutEngine: PercentageRolloutEngine;\n  private segmentMatcher: SegmentMatcher;\n  private dependencyResolver: DependencyResolver;\n  private readonly hashFunction: (key: string, salt?: string) => number;\n  private previousValues = new Map<FlagId, JsonValue>();\n  private initialized = false;\n\n  constructor(config: FlagEngineConfig = {}) {\n    this.config = config;\n    this.cache = new EvaluationCache(config.cacheTtl ?? DEFAULT_CACHE_TTL);\n    this.hashFunction = config.hashFunction ?? defaultHashFunction;\n\n    // Initialize sub-engines\n    this.targetingEngine = new TargetingRulesEngine();\n    this.rolloutEngine = new PercentageRolloutEngine(this.hashFunction);\n    this.segmentMatcher = new SegmentMatcher();\n    this.dependencyResolver = new DependencyResolver();\n\n    if (config.defaultContext) {\n      this.context = { ...config.defaultContext };\n    }\n\n    this.log('FlagEngine initialized');\n  }\n\n  // ==========================================================================\n  // Configuration\n  // ==========================================================================\n\n  /**\n   * Set the evaluation context.\n   */\n  setContext(context: EvaluationContext): void {\n    const oldContext = this.context;\n    this.context = { ...this.context, ...context };\n\n    // Clear cache if user changed\n    if (oldContext.user?.id !== context.user?.id) {\n      this.cache.clear();\n    }\n\n    this.log('Context updated', context);\n  }\n\n  /**\n   * Update specific context properties.\n   */\n  updateContext(updates: Partial<EvaluationContext>): void {\n    this.context = {\n      ...this.context,\n      ...updates,\n      custom: {\n        ...this.context.custom,\n        ...updates.custom,\n      },\n    };\n    this.log('Context updated', updates);\n  }\n\n  /**\n   * Get the current context.\n   */\n  getContext(): EvaluationContext {\n    return { ...this.context };\n  }\n\n  /**\n   * Register feature flags.\n   */\n  registerFlags(flags: readonly FeatureFlag[]): void {\n    for (const flag of flags) {\n      this.flags.set(flag.id, flag);\n      this.log(`Flag registered: ${flag.key}`);\n    }\n\n    // Build dependency graph\n    const dependencies: FlagDependency[] = [];\n    for (const flag of flags) {\n      if (flag.dependencies) {\n        dependencies.push(...flag.dependencies);\n      }\n    }\n    this.dependencyResolver.buildGraph(dependencies);\n\n    this.initialized = true;\n  }\n\n  /**\n   * Register a single flag.\n   */\n  registerFlag(flag: FeatureFlag): void {\n    this.flags.set(flag.id, flag);\n    this.cache.invalidate(flag.key);\n    this.log(`Flag registered: ${flag.key}`);\n  }\n\n  /**\n   * Remove a flag.\n   */\n  removeFlag(flagId: FlagId): void {\n    const flag = this.flags.get(flagId);\n    if (flag) {\n      this.flags.delete(flagId);\n      this.cache.invalidate(flag.key);\n      this.log(`Flag removed: ${flag.key}`);\n    }\n  }\n\n  /**\n   * Register segments.\n   */\n  registerSegments(segments: readonly Segment[]): void {\n    for (const segment of segments) {\n      this.segments.set(segment.id, segment);\n      this.log(`Segment registered: ${segment.name}`);\n    }\n  }\n\n  /**\n   * Get a flag by key.\n   */\n  getFlag(key: string): FeatureFlag | undefined {\n    for (const flag of this.flags.values()) {\n      if (flag.key === key) {\n        return flag;\n      }\n    }\n    return undefined;\n  }\n\n  /**\n   * Get all registered flags.\n   */\n  getAllFlags(): FeatureFlag[] {\n    return Array.from(this.flags.values());\n  }\n\n  // ==========================================================================\n  // Evaluation\n  // ==========================================================================\n\n  /**\n   * Evaluate a feature flag.\n   */\n  evaluate<T = JsonValue>(\n    flagKey: string,\n    contextOverrides?: Partial<EvaluationContext>\n  ): EvaluationResult<T> {\n    const startTime = performance.now();\n    const context = contextOverrides\n      ? { ...this.context, ...contextOverrides }\n      : this.context;\n\n    try {\n      // Check cache first\n      const cached = this.cache.get(flagKey, context);\n      if (cached && !cached.isStale) {\n        return cached as EvaluationResult<T>;\n      }\n\n      const result = this.evaluateInternal<T>(flagKey, context, startTime);\n\n      // Cache the result\n      this.cache.set(flagKey, context, result as EvaluationResult);\n\n      // Track evaluation event\n      this.trackEvaluation(result as EvaluationResult, context);\n\n      // Check for value changes\n      this.checkForChanges(flagKey, result.value as JsonValue);\n\n      return result;\n    } catch (error) {\n      return this.createErrorResult<T>(flagKey, error, startTime);\n    }\n  }\n\n  /**\n   * Evaluate a boolean flag (convenience method).\n   */\n  isEnabled(\n    flagKey: string,\n    contextOverrides?: Partial<EvaluationContext>\n  ): boolean {\n    const result = this.evaluate<boolean>(flagKey, contextOverrides);\n    return Boolean(result.value);\n  }\n\n  /**\n   * Evaluate a string flag.\n   */\n  getStringValue(\n    flagKey: string,\n    _defaultValue: string,\n    contextOverrides?: Partial<EvaluationContext>\n  ): string {\n    const result = this.evaluate<string>(flagKey, contextOverrides);\n    return result.value;\n  }\n\n  /**\n   * Evaluate a number flag.\n   */\n  getNumberValue(\n    flagKey: string,\n    _defaultValue: number,\n    contextOverrides?: Partial<EvaluationContext>\n  ): number {\n    const result = this.evaluate<number>(flagKey, contextOverrides);\n    return result.value;\n  }\n\n  /**\n   * Evaluate a JSON flag.\n   */\n  getJsonValue<T extends JsonValue>(\n    flagKey: string,\n    defaultValue: T,\n    contextOverrides?: Partial<EvaluationContext>\n  ): T {\n    const result = this.evaluate<T>(flagKey, contextOverrides);\n    return result.value ?? defaultValue;\n  }\n\n  /**\n   * Evaluate multiple flags at once.\n   */\n  evaluateAll(\n    flagKeys: readonly string[],\n    contextOverrides?: Partial<EvaluationContext>\n  ): Map<string, EvaluationResult> {\n    const results = new Map<string, EvaluationResult>();\n    for (const key of flagKeys) {\n      results.set(key, this.evaluate(key, contextOverrides));\n    }\n    return results;\n  }\n\n  /**\n   * Get all enabled flags.\n   */\n  getEnabledFlags(\n    contextOverrides?: Partial<EvaluationContext>\n  ): Map<string, EvaluationResult> {\n    const results = new Map<string, EvaluationResult>();\n    for (const flag of this.flags.values()) {\n      const result = this.evaluate(flag.key, contextOverrides);\n      if (result.value === true || result.reason !== 'OFF') {\n        results.set(flag.key, result);\n      }\n    }\n    return results;\n  }\n\n  // ==========================================================================\n  // Internal Evaluation\n  // ==========================================================================\n\n  /**\n   * Track an exposure event (for experiments).\n   */\n  trackExposure(\n    flagKey: string,\n    experimentId?: string,\n    metadata?: Record<string, JsonValue>\n  ): void {\n    if (!this.config.onExposure) {\n      return;\n    }\n\n    const result = this.evaluate(flagKey);\n    const event: FlagExposureEvent = {\n      type: 'exposure',\n      flagKey,\n      variantId: result.variantId,\n      experimentId,\n      userId: this.context.user?.id ?? 'anonymous',\n      sessionId: this.context.session?.sessionId ?? '',\n      timestamp: new Date(),\n      metadata,\n    };\n\n    this.config.onExposure(event);\n  }\n\n  /**\n   * Invalidate cache for a flag.\n   */\n  invalidateCache(flagKey: string): void {\n    this.cache.invalidate(flagKey);\n  }\n\n  /**\n   * Clear all cached evaluations.\n   */\n  clearCache(): void {\n    this.cache.clear();\n  }\n\n  // ==========================================================================\n  // Result Creation\n  // ==========================================================================\n\n  /**\n   * Get cache statistics.\n   */\n  getCacheStats(): { size: number; keys: string[] } {\n    return this.cache.getStats();\n  }\n\n  /**\n   * Check if the engine is initialized.\n   */\n  isInitialized(): boolean {\n    return this.initialized;\n  }\n\n  /**\n   * Get engine statistics.\n   */\n  getStats(): {\n    flagCount: number;\n    segmentCount: number;\n    cacheSize: number;\n    initialized: boolean;\n  } {\n    return {\n      flagCount: this.flags.size,\n      segmentCount: this.segments.size,\n      cacheSize: this.cache.getStats().size,\n      initialized: this.initialized,\n    };\n  }\n\n  // ==========================================================================\n  // Event Tracking\n  // ==========================================================================\n\n  /**\n   * Reset the engine to initial state.\n   */\n  reset(): void {\n    this.flags.clear();\n    this.segments.clear();\n    this.cache.clear();\n    this.previousValues.clear();\n    this.context = this.config.defaultContext ?? {};\n    this.initialized = false;\n    this.log('Engine reset');\n  }\n\n  private evaluateInternal<T>(\n    flagKey: string,\n    context: EvaluationContext,\n    startTime: number\n  ): EvaluationResult<T> {\n    const flag = this.getFlag(flagKey);\n\n    if (!flag) {\n      return this.createDefaultResult<T>(\n        flagKey,\n        'OFF',\n        startTime,\n        undefined,\n        {\n          code: 'FLAG_NOT_FOUND',\n          message: `Flag '${flagKey}' not found`,\n          isTransient: false,\n        }\n      );\n    }\n\n    // Check if flag is enabled\n    if (!flag.enabled) {\n      const offVariant = flag.variants.find((v) => v.id === flag.offVariant);\n      const variant = offVariant ?? flag.variants[0];\n      if (!variant) {\n        throw new Error(`Flag ${flag.id} has no variants`);\n      }\n      return this.createResult<T>(\n        flag,\n        variant,\n        'OFF',\n        startTime\n      );\n    }\n\n    // Check dependencies\n    if (flag.dependencies && flag.dependencies.length > 0) {\n      const depResult = this.checkDependencies(flag, context);\n      if (!depResult.satisfied) {\n        const offVariant = flag.variants.find((v) => v.id === flag.offVariant);\n        const variant = offVariant ?? flag.variants[0];\n        if (!variant) {\n          throw new Error(`Flag ${flag.id} has no variants`);\n        }\n        return this.createResult<T>(\n          flag,\n          variant,\n          'DEPENDENCY_FAILED',\n          startTime,\n          undefined,\n          undefined,\n          depResult.failedDependency != null ? { failedDependency: depResult.failedDependency } : {}\n        );\n      }\n    }\n\n    // Check segment prerequisites\n    if (flag.segments != null && flag.segments.length > 0) {\n      const inSegment = this.checkSegments(flag.segments, context);\n      if (!inSegment) {\n        const defaultVariant = flag.variants.find(\n          (v) => v.id === flag.defaultVariant\n        );\n        const variant = defaultVariant ?? flag.variants[0];\n        if (!variant) {\n          throw new Error(`Flag ${flag.id} has no variants`);\n        }\n        return this.createResult<T>(\n          flag,\n          variant,\n          'DEFAULT',\n          startTime\n        );\n      }\n    }\n\n    // Evaluate targeting rules\n    if (flag.targetingRules != null && flag.targetingRules.length > 0) {\n      const ruleResult = this.targetingEngine.evaluate(\n        flag.targetingRules,\n        context\n      );\n      if (ruleResult.matched && ruleResult.variantId != null) {\n        const variant = flag.variants.find((v) => v.id === ruleResult.variantId);\n        if (variant) {\n          return this.createResult<T>(\n            flag,\n            variant,\n            'RULE_MATCH',\n            startTime,\n            ruleResult.ruleId\n          );\n        }\n      }\n    }\n\n    // Evaluate rollout\n    if (flag.rollout) {\n      const rolloutResult = this.rolloutEngine.evaluate(\n        flag.rollout,\n        context,\n        flag.key,\n        flag.variants\n      );\n      if (rolloutResult.included) {\n        const variant = flag.variants.find(\n          (v) => v.id === rolloutResult.variantId\n        );\n        if (variant) {\n          return this.createResult<T>(\n            flag,\n            variant,\n            'ROLLOUT',\n            startTime,\n            undefined,\n            undefined,\n            { rolloutPercentage: rolloutResult.percentage ?? 0 }\n          );\n        }\n      }\n    }\n\n    // Return default variant\n    const defaultVariant = flag.variants.find(\n      (v) => v.id === flag.defaultVariant\n    );\n    const variant = defaultVariant ?? flag.variants[0];\n    if (!variant) {\n      throw new Error(`Flag ${flag.id} has no variants`);\n    }\n    return this.createResult<T>(\n      flag,\n      variant,\n      'DEFAULT',\n      startTime\n    );\n  }\n\n  private checkDependencies(\n    flag: FeatureFlag,\n    context: EvaluationContext\n  ): { satisfied: boolean; failedDependency?: string } {\n    if (!flag.dependencies) {\n      return { satisfied: true };\n    }\n\n    for (const dep of flag.dependencies) {\n      const targetFlag = this.getFlag(dep.targetFlag);\n      if (!targetFlag) {\n        continue;\n      }\n\n      const targetResult = this.evaluate(dep.targetFlag, context);\n\n      switch (dep.type) {\n        case 'requires':\n          if (dep.requiredVariant != null) {\n            if (targetResult.variantId !== dep.requiredVariant) {\n              return { satisfied: false, failedDependency: dep.targetFlag };\n            }\n          } else if (targetResult.value == null || targetResult.value === false) {\n            return { satisfied: false, failedDependency: dep.targetFlag };\n          }\n          break;\n        case 'conflicts':\n          if (targetResult.value != null && targetResult.value !== false) {\n            return { satisfied: false, failedDependency: dep.targetFlag };\n          }\n          break;\n      }\n    }\n\n    return { satisfied: true };\n  }\n\n  // ==========================================================================\n  // Cache Management\n  // ==========================================================================\n\n  private checkSegments(\n    segmentIds: readonly string[],\n    context: EvaluationContext\n  ): boolean {\n    for (const segmentId of segmentIds) {\n      const segment = this.segments.get(segmentId);\n      if (segment && this.segmentMatcher.matches(segment, context)) {\n        return true;\n      }\n    }\n    return false;\n  }\n\n  private createResult<T>(\n    flag: FeatureFlag,\n    variant: Variant,\n    reason: EvaluationReason,\n    startTime: number,\n    ruleId?: string,\n    segmentId?: string,\n    metadata?: Record<string, JsonValue>\n  ): EvaluationResult<T> {\n    return {\n      flagKey: flag.key,\n      value: variant.value as T,\n      variantId: variant.id,\n      reason,\n      ruleId,\n      segmentId,\n      isStale: false,\n      timestamp: new Date(),\n      durationMs: performance.now() - startTime,\n      metadata,\n    };\n  }\n\n  private createDefaultResult<T>(\n    flagKey: string,\n    reason: EvaluationReason,\n    startTime: number,\n    fallbackValue?: T,\n    error?: EvaluationError\n  ): EvaluationResult<T> {\n    const fallback =\n      fallbackValue ?? (this.config.fallbacks?.[flagKey] as T) ?? (false as T);\n    return {\n      flagKey,\n      value: fallback,\n      variantId: 'default',\n      reason,\n      isStale: this.config.offlineMode ?? false,\n      timestamp: new Date(),\n      durationMs: performance.now() - startTime,\n      error,\n    };\n  }\n\n  // ==========================================================================\n  // Utilities\n  // ==========================================================================\n\n  private createErrorResult<T>(\n    flagKey: string,\n    error: unknown,\n    startTime: number\n  ): EvaluationResult<T> {\n    const evaluationError: EvaluationError = {\n      code: 'EVALUATION_ERROR',\n      message: error instanceof Error ? error.message : String(error),\n      isTransient: true,\n      stack:\n        this.config.debug === true && error instanceof Error ? error.stack : undefined,\n    };\n\n    this.config.onError?.(\n      error instanceof Error ? error : new Error(String(error)),\n      flagKey\n    );\n\n    return this.createDefaultResult<T>(\n      flagKey,\n      'ERROR',\n      startTime,\n      undefined,\n      evaluationError\n    );\n  }\n\n  private trackEvaluation(\n    result: EvaluationResult,\n    context: EvaluationContext\n  ): void {\n    if (!this.config.onEvaluation) {\n      return;\n    }\n\n    const event: FlagEvaluationEvent = {\n      type: 'evaluation',\n      flagKey: result.flagKey,\n      variantId: result.variantId,\n      value: result.value,\n      reason: result.reason,\n      context,\n      timestamp: result.timestamp,\n      durationMs: result.durationMs,\n    };\n\n    this.config.onEvaluation(event);\n  }\n\n  private checkForChanges(flagKey: string, newValue: JsonValue): void {\n    if (!this.config.onChange) {\n      return;\n    }\n\n    const previousValue = this.previousValues.get(flagKey);\n    if (\n      previousValue !== undefined &&\n      JSON.stringify(previousValue) !== JSON.stringify(newValue)\n    ) {\n      const event: FlagChangeEvent = {\n        type: 'change',\n        flagKey,\n        previousValue,\n        newValue,\n        previousVariantId: 'unknown',\n        newVariantId: 'unknown',\n        timestamp: new Date(),\n      };\n      this.config.onChange(event);\n    }\n\n    this.previousValues.set(flagKey, newValue);\n  }\n\n  private log(message: string, data?: unknown): void {\n    if (this.config.debug === true) {\n      // eslint-disable-next-line no-console\n      console.log(`[FlagEngine] ${message}`, data ?? '');\n    }\n  }\n}\n\n// ============================================================================\n// Singleton Instance\n// ============================================================================\n\nlet instance: FlagEngine | null = null;\n\n/**\n * Get the singleton flag engine instance.\n */\nexport function getFlagEngine(): FlagEngine {\n  instance ??= new FlagEngine();\n  return instance;\n}\n\n/**\n * Initialize the flag engine with configuration.\n */\nexport function initFlagEngine(config: FlagEngineConfig): FlagEngine {\n  instance = new FlagEngine(config);\n  return instance;\n}\n\n/**\n * Reset the singleton instance.\n */\nexport function resetFlagEngine(): void {\n  if (instance) {\n    instance.reset();\n  }\n  instance = null;\n}\n"],"names":["DEFAULT_CACHE_TTL","murmurHash3","key","seed","remainder","bytes","h1","c1","c2","i","k1","h1b","defaultHashFunction","salt","EvaluationCache","ttl","flagKey","context","entry","result","userId","sessionId","FlagEngine","config","TargetingRulesEngine","PercentageRolloutEngine","SegmentMatcher","DependencyResolver","oldContext","updates","flags","flag","dependencies","flagId","segments","segment","contextOverrides","startTime","cached","error","_defaultValue","defaultValue","flagKeys","results","experimentId","metadata","event","variant","v","depResult","ruleResult","rolloutResult","dep","targetResult","segmentIds","segmentId","reason","ruleId","fallbackValue","fallback","evaluationError","newValue","previousValue","message","data","instance","getFlagEngine","initFlagEngine","resetFlagEngine"],"mappings":"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"}