{"version":3,"file":"targeting-rules.mjs","sources":["../../../../src/lib/flags/advanced/targeting-rules.ts"],"sourcesContent":["/**\n * @fileoverview Targeting rules engine for feature flag evaluation.\n *\n * Provides comprehensive condition evaluation with support for:\n * - Complex nested conditions (AND/OR groups)\n * - Multiple comparison operators\n * - Attribute path resolution (dot notation)\n * - Type coercion and validation\n * - Schedule-based rules\n *\n * @module flags/advanced/targeting-rules\n *\n * @example\n * ```typescript\n * const engine = new TargetingRulesEngine();\n *\n * const rules: TargetingRule[] = [{\n *   id: 'beta-users',\n *   name: 'Beta Users',\n *   priority: 1,\n *   enabled: true,\n *   variantId: 'enabled',\n *   conditions: {\n *     operator: 'and',\n *     conditions: [\n *       { attribute: 'user.isBeta', operator: 'equals', value: true },\n *       { attribute: 'user.plan', operator: 'in', value: ['pro', 'enterprise'] },\n *     ],\n *   },\n * }];\n *\n * const result = engine.evaluate(rules, context);\n * ```\n */\n\nimport type {\n  EvaluationContext,\n  TargetingRule,\n  TargetingCondition,\n  ConditionGroup,\n  ComparisonOperator,\n  RuleSchedule,\n  VariantId,\n  JsonValue,\n} from './types';\n// import type { Mutable } from '../../utils/types';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Result of targeting rule evaluation.\n */\nexport interface TargetingResult {\n  /** Whether any rule matched */\n  readonly matched: boolean;\n  /** The variant to serve */\n  readonly variantId?: VariantId;\n  /** The rule that matched */\n  readonly ruleId?: string;\n  /** The rule name */\n  readonly ruleName?: string;\n  /** Evaluation details for debugging */\n  readonly details?: TargetingDetails;\n}\n\n/**\n * Detailed evaluation information for debugging.\n */\nexport interface TargetingDetails {\n  /** All rules that were evaluated */\n  readonly evaluatedRules: readonly RuleEvaluation[];\n  /** Total evaluation time in ms */\n  readonly evaluationTimeMs: number;\n}\n\n/**\n * Evaluation result for a single rule.\n */\nexport interface RuleEvaluation {\n  readonly ruleId: string;\n  readonly ruleName: string;\n  readonly matched: boolean;\n  readonly skipped: boolean;\n  readonly skipReason?: string;\n  readonly conditionResults?: readonly ConditionResult[];\n}\n\n/**\n * Evaluation result for a single condition.\n */\nexport interface ConditionResult {\n  readonly attribute: string;\n  readonly operator: ComparisonOperator;\n  readonly expectedValue: JsonValue | readonly JsonValue[];\n  readonly actualValue: JsonValue | undefined;\n  readonly matched: boolean;\n}\n\n// ============================================================================\n// Targeting Rules Engine\n// ============================================================================\n\n/**\n * Engine for evaluating targeting rules against evaluation context.\n */\nexport class TargetingRulesEngine {\n  private readonly debug: boolean;\n\n  constructor(options: { debug?: boolean } = {}) {\n    this.debug = options.debug ?? false;\n  }\n\n  /**\n   * Evaluate targeting rules and return the first matching variant.\n   */\n  evaluate(rules: readonly TargetingRule[], context: EvaluationContext): TargetingResult {\n    const startTime = performance.now();\n    const evaluatedRules: RuleEvaluation[] = [];\n\n    // Sort rules by priority (lower number = higher priority)\n    const sortedRules = [...rules].sort((a, b) => a.priority - b.priority);\n\n    for (const rule of sortedRules) {\n      const evaluation = this.evaluateRule(rule, context);\n      evaluatedRules.push(evaluation);\n\n      if (evaluation.matched) {\n        return {\n          matched: true,\n          variantId: rule.variantId,\n          ruleId: rule.id,\n          ruleName: rule.name,\n          details: this.debug\n            ? {\n                evaluatedRules,\n                evaluationTimeMs: performance.now() - startTime,\n              }\n            : undefined,\n        };\n      }\n    }\n\n    return {\n      matched: false,\n      details: this.debug\n        ? {\n            evaluatedRules,\n            evaluationTimeMs: performance.now() - startTime,\n          }\n        : undefined,\n    };\n  }\n\n  /**\n   * Evaluate a single targeting rule.\n   */\n  evaluateRule(rule: TargetingRule, context: EvaluationContext): RuleEvaluation {\n    // Check if rule is enabled\n    if (!rule.enabled) {\n      return {\n        ruleId: rule.id,\n        ruleName: rule.name,\n        matched: false,\n        skipped: true,\n        skipReason: 'Rule is disabled',\n      };\n    }\n\n    // Check schedule constraints\n    if (rule.schedule && !this.isWithinSchedule(rule.schedule, context)) {\n      return {\n        ruleId: rule.id,\n        ruleName: rule.name,\n        matched: false,\n        skipped: true,\n        skipReason: 'Outside schedule',\n      };\n    }\n\n    // Evaluate conditions\n    const conditionResults: ConditionResult[] = [];\n    const matched = this.evaluateConditionGroup(rule.conditions, context, conditionResults);\n\n    return {\n      ruleId: rule.id,\n      ruleName: rule.name,\n      matched,\n      skipped: false,\n      conditionResults: this.debug ? conditionResults : undefined,\n    };\n  }\n\n  /**\n   * Evaluate a condition group (AND/OR).\n   */\n  private evaluateConditionGroup(\n    group: ConditionGroup,\n    context: EvaluationContext,\n    results: ConditionResult[]\n  ): boolean {\n    const { conditions } = group;\n\n    if (group.operator === 'and') {\n      return conditions.every((condition) =>\n        this.evaluateConditionOrGroup(condition, context, results)\n      );\n    } else {\n      return conditions.some((condition) =>\n        this.evaluateConditionOrGroup(condition, context, results)\n      );\n    }\n  }\n\n  /**\n   * Evaluate either a condition or a nested group.\n   */\n  private evaluateConditionOrGroup(\n    conditionOrGroup: TargetingCondition | ConditionGroup,\n    context: EvaluationContext,\n    results: ConditionResult[]\n  ): boolean {\n    if ('operator' in conditionOrGroup && 'conditions' in conditionOrGroup) {\n      // It's a nested group\n      return this.evaluateConditionGroup(conditionOrGroup, context, results);\n    } else {\n      // It's a condition\n      return this.evaluateCondition(conditionOrGroup, context, results);\n    }\n  }\n\n  /**\n   * Evaluate a single condition.\n   */\n  private evaluateCondition(\n    condition: TargetingCondition,\n    context: EvaluationContext,\n    results: ConditionResult[]\n  ): boolean {\n    const actualValue = this.resolveAttributePath(condition.attribute, context);\n    let matched = this.compare(\n      actualValue,\n      condition.operator,\n      condition.value,\n      condition.caseSensitive ?? true\n    );\n\n    if (condition.negate === true) {\n      matched = !matched;\n    }\n\n    results.push({\n      attribute: condition.attribute,\n      operator: condition.operator,\n      expectedValue: condition.value,\n      actualValue,\n      matched,\n    });\n\n    return matched;\n  }\n\n  /**\n   * Resolve an attribute path to a value.\n   * Supports dot notation: \"user.custom.department\"\n   */\n  private resolveAttributePath(path: string, context: EvaluationContext): JsonValue | undefined {\n    const parts = path.split('.');\n    let current: unknown = context;\n\n    for (const part of parts) {\n      if (current === null || current === undefined) {\n        return undefined;\n      }\n      if (typeof current !== 'object') {\n        return undefined;\n      }\n      current = (current as Record<string, unknown>)[part];\n    }\n\n    return current as JsonValue | undefined;\n  }\n\n  /**\n   * Compare a value using the specified operator.\n   */\n  private compare(\n    actual: JsonValue | undefined,\n    operator: ComparisonOperator,\n    expected: JsonValue | readonly JsonValue[],\n    caseSensitive: boolean\n  ): boolean {\n    switch (operator) {\n      case 'equals':\n        return this.equals(actual, expected, caseSensitive);\n\n      case 'notEquals':\n        return !this.equals(actual, expected, caseSensitive);\n\n      case 'contains':\n        return this.contains(actual, expected, caseSensitive);\n\n      case 'notContains':\n        return !this.contains(actual, expected, caseSensitive);\n\n      case 'startsWith':\n        return this.startsWith(actual, expected, caseSensitive);\n\n      case 'endsWith':\n        return this.endsWith(actual, expected, caseSensitive);\n\n      case 'matches':\n        return this.matchesRegex(actual, expected);\n\n      case 'in':\n        return this.isIn(actual, expected, caseSensitive);\n\n      case 'notIn':\n        return !this.isIn(actual, expected, caseSensitive);\n\n      case 'greaterThan':\n        return this.greaterThan(actual, expected);\n\n      case 'greaterThanOrEquals':\n        return this.greaterThanOrEquals(actual, expected);\n\n      case 'lessThan':\n        return this.lessThan(actual, expected);\n\n      case 'lessThanOrEquals':\n        return this.lessThanOrEquals(actual, expected);\n\n      case 'before':\n        return this.before(actual, expected);\n\n      case 'after':\n        return this.after(actual, expected);\n\n      case 'exists':\n        return actual !== undefined && actual !== null;\n\n      case 'notExists':\n        return actual === undefined || actual === null;\n\n      case 'semverGreaterThan':\n        return this.semverCompare(actual, expected) > 0;\n\n      case 'semverLessThan':\n        return this.semverCompare(actual, expected) < 0;\n\n      case 'semverEquals':\n        return this.semverCompare(actual, expected) === 0;\n\n      default:\n        return false;\n    }\n  }\n\n  // ==========================================================================\n  // Comparison Helpers\n  // ==========================================================================\n\n  private normalizeString(value: unknown, caseSensitive: boolean): string {\n    const str = typeof value === 'object' && value !== null ? JSON.stringify(value) : String(value);\n    return caseSensitive ? str : str.toLowerCase();\n  }\n\n  private equals(\n    actual: JsonValue | undefined,\n    expected: JsonValue | readonly JsonValue[],\n    caseSensitive: boolean\n  ): boolean {\n    if (actual === undefined || actual === null) {\n      return expected === null || expected === undefined;\n    }\n\n    if (typeof actual === 'string' && typeof expected === 'string') {\n      return (\n        this.normalizeString(actual, caseSensitive) ===\n        this.normalizeString(expected, caseSensitive)\n      );\n    }\n\n    if (typeof actual === 'object' && typeof expected === 'object') {\n      return JSON.stringify(actual) === JSON.stringify(expected);\n    }\n\n    return actual === expected;\n  }\n\n  private contains(\n    actual: JsonValue | undefined,\n    expected: JsonValue | readonly JsonValue[],\n    caseSensitive: boolean\n  ): boolean {\n    if (actual === undefined || actual === null) {\n      return false;\n    }\n\n    if (typeof actual === 'string' && typeof expected === 'string') {\n      return this.normalizeString(actual, caseSensitive).includes(\n        this.normalizeString(expected, caseSensitive)\n      );\n    }\n\n    if (Array.isArray(actual)) {\n      return actual.some((item) => this.equals(item, expected, caseSensitive));\n    }\n\n    return false;\n  }\n\n  private startsWith(\n    actual: JsonValue | undefined,\n    expected: JsonValue | readonly JsonValue[],\n    caseSensitive: boolean\n  ): boolean {\n    if (typeof actual !== 'string' || typeof expected !== 'string') {\n      return false;\n    }\n\n    return this.normalizeString(actual, caseSensitive).startsWith(\n      this.normalizeString(expected, caseSensitive)\n    );\n  }\n\n  private endsWith(\n    actual: JsonValue | undefined,\n    expected: JsonValue | readonly JsonValue[],\n    caseSensitive: boolean\n  ): boolean {\n    if (typeof actual !== 'string' || typeof expected !== 'string') {\n      return false;\n    }\n\n    return this.normalizeString(actual, caseSensitive).endsWith(\n      this.normalizeString(expected, caseSensitive)\n    );\n  }\n\n  private matchesRegex(\n    actual: JsonValue | undefined,\n    expected: JsonValue | readonly JsonValue[]\n  ): boolean {\n    if (typeof actual !== 'string' || typeof expected !== 'string') {\n      return false;\n    }\n\n    try {\n      const regex = new RegExp(expected);\n      return regex.test(actual);\n    } catch {\n      return false;\n    }\n  }\n\n  private isIn(\n    actual: JsonValue | undefined,\n    expected: JsonValue | readonly JsonValue[],\n    caseSensitive: boolean\n  ): boolean {\n    if (!Array.isArray(expected)) {\n      return false;\n    }\n\n    return expected.some((item) => this.equals(actual, item, caseSensitive));\n  }\n\n  private greaterThan(\n    actual: JsonValue | undefined,\n    expected: JsonValue | readonly JsonValue[]\n  ): boolean {\n    if (typeof actual !== 'number' || typeof expected !== 'number') {\n      return false;\n    }\n    return actual > expected;\n  }\n\n  private greaterThanOrEquals(\n    actual: JsonValue | undefined,\n    expected: JsonValue | readonly JsonValue[]\n  ): boolean {\n    if (typeof actual !== 'number' || typeof expected !== 'number') {\n      return false;\n    }\n    return actual >= expected;\n  }\n\n  private lessThan(\n    actual: JsonValue | undefined,\n    expected: JsonValue | readonly JsonValue[]\n  ): boolean {\n    if (typeof actual !== 'number' || typeof expected !== 'number') {\n      return false;\n    }\n    return actual < expected;\n  }\n\n  private lessThanOrEquals(\n    actual: JsonValue | undefined,\n    expected: JsonValue | readonly JsonValue[]\n  ): boolean {\n    if (typeof actual !== 'number' || typeof expected !== 'number') {\n      return false;\n    }\n    return actual <= expected;\n  }\n\n  private before(\n    actual: JsonValue | undefined,\n    expected: JsonValue | readonly JsonValue[]\n  ): boolean {\n    const actualDate = this.parseDate(actual);\n    const expectedDate = this.parseDate(expected);\n\n    if (!actualDate || !expectedDate) {\n      return false;\n    }\n\n    return actualDate.getTime() < expectedDate.getTime();\n  }\n\n  private after(\n    actual: JsonValue | undefined,\n    expected: JsonValue | readonly JsonValue[]\n  ): boolean {\n    const actualDate = this.parseDate(actual);\n    const expectedDate = this.parseDate(expected);\n\n    if (!actualDate || !expectedDate) {\n      return false;\n    }\n\n    return actualDate.getTime() > expectedDate.getTime();\n  }\n\n  private parseDate(value: unknown): Date | null {\n    if (value instanceof Date) {\n      return value;\n    }\n    if (typeof value === 'string' || typeof value === 'number') {\n      const date = new Date(value);\n      return isNaN(date.getTime()) ? null : date;\n    }\n    return null;\n  }\n\n  private semverCompare(\n    actual: JsonValue | undefined,\n    expected: JsonValue | readonly JsonValue[]\n  ): number {\n    if (typeof actual !== 'string' || typeof expected !== 'string') {\n      return 0;\n    }\n\n    const parseVersion = (v: string): number[] => {\n      const parts = v.replace(/^v/, '').split(/[.-]/);\n      return parts.map((p) => parseInt(p, 10) || 0);\n    };\n\n    const actualParts = parseVersion(actual);\n    const expectedParts = parseVersion(expected);\n\n    const maxLength = Math.max(actualParts.length, expectedParts.length);\n\n    for (let i = 0; i < maxLength; i++) {\n      const a = actualParts[i] ?? 0;\n      const e = expectedParts[i] ?? 0;\n      if (a > e) return 1;\n      if (a < e) return -1;\n    }\n\n    return 0;\n  }\n\n  // ==========================================================================\n  // Schedule Evaluation\n  // ==========================================================================\n\n  private isWithinSchedule(schedule: RuleSchedule, context: EvaluationContext): boolean {\n    const now = context.timestamp ?? new Date();\n    const timezone = schedule.timezone ?? 'UTC';\n\n    // Convert to timezone-aware date\n    const localDate = this.toTimezone(now, timezone);\n\n    // Check date range\n    if (schedule.startTime && now < schedule.startTime) {\n      return false;\n    }\n    if (schedule.endTime && now > schedule.endTime) {\n      return false;\n    }\n\n    // Check day of week (0 = Sunday)\n    if (schedule.daysOfWeek && schedule.daysOfWeek.length > 0) {\n      const dayOfWeek = localDate.getDay();\n      if (!schedule.daysOfWeek.includes(dayOfWeek)) {\n        return false;\n      }\n    }\n\n    // Check hour of day (0-23)\n    if (schedule.hoursOfDay && schedule.hoursOfDay.length > 0) {\n      const hour = localDate.getHours();\n      if (!schedule.hoursOfDay.includes(hour)) {\n        return false;\n      }\n    }\n\n    return true;\n  }\n\n  private toTimezone(date: Date, timezone: string): Date {\n    try {\n      const options: Intl.DateTimeFormatOptions = {\n        timeZone: timezone,\n        year: 'numeric',\n        month: 'numeric',\n        day: 'numeric',\n        hour: 'numeric',\n        minute: 'numeric',\n        second: 'numeric',\n        hour12: false,\n      };\n\n      const formatted = new Intl.DateTimeFormat('en-US', options).format(date);\n      return new Date(formatted);\n    } catch {\n      return date;\n    }\n  }\n}\n\n// ============================================================================\n// Rule Builder\n// ============================================================================\n\n/**\n * Mutable targeting rule type for builder.\n */\ntype MutableTargetingRule = {\n  -readonly [K in keyof TargetingRule]: TargetingRule[K];\n};\n\n/**\n * Fluent builder for creating targeting rules.\n */\nexport class TargetingRuleBuilder {\n  private rule: Partial<MutableTargetingRule> = {\n    enabled: true,\n    priority: 0,\n  };\n  private conditions: (TargetingCondition | ConditionGroup)[] = [];\n  private groupOperator: 'and' | 'or' = 'and';\n\n  /**\n   * Set the rule ID.\n   */\n  id(id: string): this {\n    this.rule.id = id;\n    return this;\n  }\n\n  /**\n   * Set the rule name.\n   */\n  name(name: string): this {\n    this.rule.name = name;\n    return this;\n  }\n\n  /**\n   * Set the rule description.\n   */\n  description(description: string): this {\n    this.rule.description = description;\n    return this;\n  }\n\n  /**\n   * Set the rule priority.\n   */\n  priority(priority: number): this {\n    this.rule.priority = priority;\n    return this;\n  }\n\n  /**\n   * Set whether the rule is enabled.\n   */\n  enabled(enabled: boolean): this {\n    this.rule.enabled = enabled;\n    return this;\n  }\n\n  /**\n   * Set the variant to serve when matched.\n   */\n  variant(variantId: VariantId): this {\n    this.rule.variantId = variantId;\n    return this;\n  }\n\n  /**\n   * Use AND to combine conditions.\n   */\n  and(): this {\n    this.groupOperator = 'and';\n    return this;\n  }\n\n  /**\n   * Use OR to combine conditions.\n   */\n  or(): this {\n    this.groupOperator = 'or';\n    return this;\n  }\n\n  /**\n   * Add a condition to the rule.\n   */\n  condition(condition: TargetingCondition): this {\n    this.conditions.push(condition);\n    return this;\n  }\n\n  /**\n   * Add an attribute equals condition.\n   */\n  where(attribute: string, value: JsonValue): this {\n    this.conditions.push({\n      attribute,\n      operator: 'equals',\n      value,\n    });\n    return this;\n  }\n\n  /**\n   * Add an attribute in list condition.\n   */\n  whereIn(attribute: string, values: readonly JsonValue[]): this {\n    this.conditions.push({\n      attribute,\n      operator: 'in',\n      value: values,\n    });\n    return this;\n  }\n\n  /**\n   * Add an attribute exists condition.\n   */\n  whereExists(attribute: string): this {\n    this.conditions.push({\n      attribute,\n      operator: 'exists',\n      value: true,\n    });\n    return this;\n  }\n\n  /**\n   * Add a nested condition group.\n   */\n  group(builder: (group: ConditionGroupBuilder) => void): this {\n    const groupBuilder = new ConditionGroupBuilder();\n    builder(groupBuilder);\n    this.conditions.push(groupBuilder.build());\n    return this;\n  }\n\n  /**\n   * Set schedule constraints.\n   */\n  schedule(schedule: RuleSchedule): this {\n    this.rule.schedule = schedule;\n    return this;\n  }\n\n  /**\n   * Build the targeting rule.\n   */\n  build(): TargetingRule {\n    if (this.rule.id == null || this.rule.id === '') {\n      throw new Error('Rule ID is required');\n    }\n    if (this.rule.name == null || this.rule.name === '') {\n      throw new Error('Rule name is required');\n    }\n    if (this.rule.variantId == null || this.rule.variantId === '') {\n      throw new Error('Variant ID is required');\n    }\n\n    return {\n      id: this.rule.id,\n      name: this.rule.name,\n      description: this.rule.description,\n      priority: this.rule.priority ?? 0,\n      enabled: this.rule.enabled ?? true,\n      variantId: this.rule.variantId,\n      conditions: {\n        operator: this.groupOperator,\n        conditions: this.conditions,\n      },\n      schedule: this.rule.schedule,\n    };\n  }\n}\n\n/**\n * Builder for condition groups.\n */\nexport class ConditionGroupBuilder {\n  private conditions: (TargetingCondition | ConditionGroup)[] = [];\n  private operator: 'and' | 'or' = 'and';\n\n  and(): this {\n    this.operator = 'and';\n    return this;\n  }\n\n  or(): this {\n    this.operator = 'or';\n    return this;\n  }\n\n  condition(condition: TargetingCondition): this {\n    this.conditions.push(condition);\n    return this;\n  }\n\n  where(attribute: string, value: JsonValue): this {\n    this.conditions.push({\n      attribute,\n      operator: 'equals',\n      value,\n    });\n    return this;\n  }\n\n  build(): ConditionGroup {\n    return {\n      operator: this.operator,\n      conditions: this.conditions,\n    };\n  }\n}\n\n/**\n * Create a new targeting rule builder.\n */\nexport function createTargetingRule(): TargetingRuleBuilder {\n  return new TargetingRuleBuilder();\n}\n"],"names":["TargetingRulesEngine","options","rules","context","startTime","evaluatedRules","sortedRules","a","b","rule","evaluation","conditionResults","matched","group","results","conditions","condition","conditionOrGroup","actualValue","path","parts","current","part","actual","operator","expected","caseSensitive","value","str","item","actualDate","expectedDate","date","parseVersion","v","p","actualParts","expectedParts","maxLength","i","e","schedule","now","timezone","localDate","dayOfWeek","hour","formatted","TargetingRuleBuilder","id","name","description","priority","enabled","variantId","attribute","values","builder","groupBuilder","ConditionGroupBuilder","createTargetingRule"],"mappings":"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"}