{"version":3,"file":"flag-segments.mjs","sources":["../../../../src/lib/flags/advanced/flag-segments.ts"],"sourcesContent":["/**\n * @fileoverview User segmentation for feature flag targeting.\n *\n * Provides comprehensive segment management including:\n * - Rule-based segment membership\n * - Explicit user inclusion/exclusion\n * - Segment composition (union, intersection)\n * - Segment caching and optimization\n *\n * @module flags/advanced/flag-segments\n *\n * @example\n * ```typescript\n * const matcher = new SegmentMatcher();\n *\n * const betaUsers: Segment = {\n *   id: 'beta-users',\n *   name: 'Beta Users',\n *   rules: {\n *     operator: 'or',\n *     conditions: [\n *       { attribute: 'user.isBeta', operator: 'equals', value: true },\n *       { attribute: 'user.email', operator: 'endsWith', value: '@company.com' },\n *     ],\n *   },\n *   updatedAt: new Date(),\n * };\n *\n * const isInSegment = matcher.matches(betaUsers, context);\n * ```\n */\n\nimport type {\n  Segment,\n  SegmentId,\n  UserId,\n  EvaluationContext,\n  ConditionGroup,\n  TargetingCondition,\n  JsonValue,\n} from './types';\n// import type { Mutable } from '../../utils/types';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Result of segment matching.\n */\nexport interface SegmentMatchResult {\n  /** Whether the context matches the segment */\n  readonly matched: boolean;\n  /** The segment that was matched */\n  readonly segmentId: SegmentId;\n  /** Reason for the match result */\n  readonly reason: SegmentMatchReason;\n  /** Detailed match information */\n  readonly details?: SegmentMatchDetails;\n}\n\n/**\n * Reasons for segment match results.\n */\nexport type SegmentMatchReason =\n  | 'RULE_MATCH'\n  | 'EXPLICIT_INCLUDE'\n  | 'EXPLICIT_EXCLUDE'\n  | 'NO_MATCH';\n\n/**\n * Detailed information about segment matching.\n */\nexport interface SegmentMatchDetails {\n  /** Rules that were evaluated */\n  readonly rulesEvaluated: number;\n  /** Evaluation time in ms */\n  readonly evaluationTimeMs: number;\n  /** Specific conditions that matched */\n  readonly matchedConditions?: string[];\n}\n\n/**\n * Segment composition operations.\n */\nexport type SegmentCompositionOp = 'union' | 'intersection' | 'difference';\n\n/**\n * A composed segment.\n */\nexport interface ComposedSegment {\n  /** The operation to perform */\n  readonly operation: SegmentCompositionOp;\n  /** Segments to compose */\n  readonly segments: readonly SegmentId[];\n}\n\n// ============================================================================\n// Segment Matcher\n// ============================================================================\n\n/**\n * Matches evaluation contexts against segment definitions.\n */\nexport class SegmentMatcher {\n  private cache = new Map<string, { result: boolean; expiresAt: number }>();\n  private readonly cacheTtl: number;\n\n  constructor(options: { cacheTtl?: number } = {}) {\n    this.cacheTtl = options.cacheTtl ?? 60000; // 1 minute default\n  }\n\n  /**\n   * Check if a context matches a segment.\n   */\n  matches(segment: Segment, context: EvaluationContext): boolean {\n    const result = this.matchWithDetails(segment, context);\n    return result.matched;\n  }\n\n  /**\n   * Check if a context matches a segment with detailed results.\n   */\n  matchWithDetails(segment: Segment, context: EvaluationContext): SegmentMatchResult {\n    const startTime = performance.now();\n    const userId = context.user?.id;\n\n    // Check cache\n    const cacheKey = this.getCacheKey(segment.id, context);\n    const cached = this.cache.get(cacheKey);\n    if (cached && cached.expiresAt > Date.now()) {\n      return {\n        matched: cached.result,\n        segmentId: segment.id,\n        reason: cached.result ? 'RULE_MATCH' : 'NO_MATCH',\n      };\n    }\n\n    // Check explicit exclusions first\n    if (userId != null && userId !== '' && segment.excludedUsers?.includes(userId) === true) {\n      this.cacheResult(cacheKey, false);\n      return {\n        matched: false,\n        segmentId: segment.id,\n        reason: 'EXPLICIT_EXCLUDE',\n        details: {\n          rulesEvaluated: 0,\n          evaluationTimeMs: performance.now() - startTime,\n        },\n      };\n    }\n\n    // Check explicit inclusions\n    if (userId != null && userId !== '' && segment.includedUsers?.includes(userId) === true) {\n      this.cacheResult(cacheKey, true);\n      return {\n        matched: true,\n        segmentId: segment.id,\n        reason: 'EXPLICIT_INCLUDE',\n        details: {\n          rulesEvaluated: 0,\n          evaluationTimeMs: performance.now() - startTime,\n        },\n      };\n    }\n\n    // Evaluate rules\n    const matchedConditions: string[] = [];\n    const matched = this.evaluateConditionGroup(segment.rules, context, matchedConditions);\n\n    this.cacheResult(cacheKey, matched);\n\n    return {\n      matched,\n      segmentId: segment.id,\n      reason: matched ? 'RULE_MATCH' : 'NO_MATCH',\n      details: {\n        rulesEvaluated: matchedConditions.length,\n        evaluationTimeMs: performance.now() - startTime,\n        matchedConditions: matched ? matchedConditions : undefined,\n      },\n    };\n  }\n\n  /**\n   * Check if a context matches any of the given segments.\n   */\n  matchesAny(\n    segments: readonly Segment[],\n    context: EvaluationContext\n  ): { matched: boolean; matchedSegment?: Segment } {\n    for (const segment of segments) {\n      if (this.matches(segment, context)) {\n        return { matched: true, matchedSegment: segment };\n      }\n    }\n    return { matched: false };\n  }\n\n  /**\n   * Check if a context matches all of the given segments.\n   */\n  matchesAll(segments: readonly Segment[], context: EvaluationContext): boolean {\n    return segments.every((segment) => this.matches(segment, context));\n  }\n\n  /**\n   * Get all segments that match a context.\n   */\n  getMatchingSegments(segments: readonly Segment[], context: EvaluationContext): Segment[] {\n    return segments.filter((segment) => this.matches(segment, context));\n  }\n\n  // ==========================================================================\n  // Condition Evaluation\n  // ==========================================================================\n\n  /**\n   * Clear the segment cache.\n   */\n  clearCache(): void {\n    this.cache.clear();\n  }\n\n  /**\n   * Clear cache for a specific segment.\n   */\n  clearSegmentCache(segmentId: SegmentId): void {\n    for (const key of this.cache.keys()) {\n      if (key.startsWith(`${segmentId}:`)) {\n        this.cache.delete(key);\n      }\n    }\n  }\n\n  private evaluateConditionGroup(\n    group: ConditionGroup,\n    context: EvaluationContext,\n    matchedConditions: string[]\n  ): boolean {\n    if (group.operator === 'and') {\n      return group.conditions.every((condition) =>\n        this.evaluateConditionOrGroup(condition, context, matchedConditions)\n      );\n    } else {\n      return group.conditions.some((condition) =>\n        this.evaluateConditionOrGroup(condition, context, matchedConditions)\n      );\n    }\n  }\n\n  private evaluateConditionOrGroup(\n    conditionOrGroup: TargetingCondition | ConditionGroup,\n    context: EvaluationContext,\n    matchedConditions: string[]\n  ): boolean {\n    if ('operator' in conditionOrGroup && 'conditions' in conditionOrGroup) {\n      return this.evaluateConditionGroup(conditionOrGroup, context, matchedConditions);\n    } else {\n      return this.evaluateCondition(conditionOrGroup, context, matchedConditions);\n    }\n  }\n\n  private evaluateCondition(\n    condition: TargetingCondition,\n    context: EvaluationContext,\n    matchedConditions: string[]\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    if (matched) {\n      matchedConditions.push(condition.attribute);\n    }\n\n    return matched;\n  }\n\n  // ==========================================================================\n  // Cache Management\n  // ==========================================================================\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  private compare(\n    actual: JsonValue | undefined,\n    operator: string,\n    expected: JsonValue | readonly JsonValue[],\n    caseSensitive: boolean\n  ): boolean {\n    const normalize = (v: unknown): string => (caseSensitive ? String(v) : String(v).toLowerCase());\n\n    switch (operator) {\n      case 'equals':\n        if (typeof actual === 'string' && typeof expected === 'string') {\n          return normalize(actual) === normalize(expected);\n        }\n        return actual === expected;\n\n      case 'notEquals':\n        return actual !== expected;\n\n      case 'contains':\n        if (typeof actual === 'string' && typeof expected === 'string') {\n          return normalize(actual).includes(normalize(expected));\n        }\n        if (Array.isArray(actual)) {\n          return actual.some((item) =>\n            caseSensitive ? item === expected : normalize(item) === normalize(expected)\n          );\n        }\n        return false;\n\n      case 'notContains':\n        return !this.compare(actual, 'contains', expected, caseSensitive);\n\n      case 'startsWith':\n        return (\n          typeof actual === 'string' &&\n          typeof expected === 'string' &&\n          normalize(actual).startsWith(normalize(expected))\n        );\n\n      case 'endsWith':\n        return (\n          typeof actual === 'string' &&\n          typeof expected === 'string' &&\n          normalize(actual).endsWith(normalize(expected))\n        );\n\n      case 'matches':\n        if (typeof actual !== 'string' || typeof expected !== 'string') {\n          return false;\n        }\n        try {\n          return new RegExp(expected, caseSensitive ? '' : 'i').test(actual);\n        } catch {\n          return false;\n        }\n\n      case 'in':\n        if (!Array.isArray(expected)) return false;\n        return expected.some((item) =>\n          caseSensitive ? actual === item : normalize(actual) === normalize(item)\n        );\n\n      case 'notIn':\n        return !this.compare(actual, 'in', expected, caseSensitive);\n\n      case 'greaterThan':\n        return typeof actual === 'number' && typeof expected === 'number' && actual > expected;\n\n      case 'greaterThanOrEquals':\n        return typeof actual === 'number' && typeof expected === 'number' && actual >= expected;\n\n      case 'lessThan':\n        return typeof actual === 'number' && typeof expected === 'number' && actual < expected;\n\n      case 'lessThanOrEquals':\n        return typeof actual === 'number' && typeof expected === 'number' && actual <= expected;\n\n      case 'exists':\n        return actual !== undefined && actual !== null;\n\n      case 'notExists':\n        return actual === undefined || actual === null;\n\n      default:\n        return false;\n    }\n  }\n\n  private getCacheKey(segmentId: SegmentId, context: EvaluationContext): string {\n    const userId = context.user?.id ?? 'anonymous';\n    return `${segmentId}:${userId}`;\n  }\n\n  private cacheResult(key: string, result: boolean): void {\n    this.cache.set(key, {\n      result,\n      expiresAt: Date.now() + this.cacheTtl,\n    });\n  }\n}\n\n// ============================================================================\n// Segment Builder\n// ============================================================================\n\n/**\n * Mutable segment type for builder.\n */\ntype MutableSegment = {\n  -readonly [K in keyof Segment]: Segment[K];\n};\n\n/**\n * Fluent builder for creating segments.\n */\nexport class SegmentBuilder {\n  private segment: Partial<MutableSegment> = {\n    includedUsers: [],\n    excludedUsers: [],\n    tags: [],\n  };\n  private conditions: (TargetingCondition | ConditionGroup)[] = [];\n  private groupOperator: 'and' | 'or' = 'and';\n\n  /**\n   * Set the segment ID.\n   */\n  id(id: SegmentId): this {\n    this.segment.id = id;\n    return this;\n  }\n\n  /**\n   * Set the segment name.\n   */\n  name(name: string): this {\n    this.segment.name = name;\n    return this;\n  }\n\n  /**\n   * Set the segment description.\n   */\n  description(description: string): this {\n    this.segment.description = description;\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.\n   */\n  where(\n    attribute: string,\n    operator: TargetingCondition['operator'],\n    value: JsonValue | readonly JsonValue[]\n  ): this {\n    this.conditions.push({ attribute, operator, value });\n    return this;\n  }\n\n  /**\n   * Add an equals condition.\n   */\n  equals(attribute: string, value: JsonValue): this {\n    return this.where(attribute, 'equals', value);\n  }\n\n  /**\n   * Add an in condition.\n   */\n  in(attribute: string, values: readonly JsonValue[]): this {\n    return this.where(attribute, 'in', values as unknown as JsonValue);\n  }\n\n  /**\n   * Add a contains condition.\n   */\n  contains(attribute: string, value: string): this {\n    return this.where(attribute, 'contains', value);\n  }\n\n  /**\n   * Add a starts with condition.\n   */\n  startsWith(attribute: string, value: string): this {\n    return this.where(attribute, 'startsWith', value);\n  }\n\n  /**\n   * Add an ends with condition.\n   */\n  endsWith(attribute: string, value: string): this {\n    return this.where(attribute, 'endsWith', value);\n  }\n\n  /**\n   * Add users to explicitly include.\n   */\n  include(...userIds: UserId[]): this {\n    this.segment.includedUsers = [...(this.segment.includedUsers ?? []), ...userIds];\n    return this;\n  }\n\n  /**\n   * Add users to explicitly exclude.\n   */\n  exclude(...userIds: UserId[]): this {\n    this.segment.excludedUsers = [...(this.segment.excludedUsers ?? []), ...userIds];\n    return this;\n  }\n\n  /**\n   * Add tags.\n   */\n  tag(...tags: string[]): this {\n    this.segment.tags = [...(this.segment.tags ?? []), ...tags];\n    return this;\n  }\n\n  /**\n   * Set estimated size.\n   */\n  estimatedSize(size: number): this {\n    this.segment.estimatedSize = size;\n    return this;\n  }\n\n  /**\n   * Build the segment.\n   */\n  build(): Segment {\n    if (this.segment.id == null || this.segment.id === '') {\n      throw new Error('Segment ID is required');\n    }\n    if (this.segment.name == null || this.segment.name === '') {\n      throw new Error('Segment name is required');\n    }\n\n    return {\n      id: this.segment.id,\n      name: this.segment.name,\n      description: this.segment.description,\n      rules: {\n        operator: this.groupOperator,\n        conditions: this.conditions,\n      },\n      includedUsers: this.segment.includedUsers,\n      excludedUsers: this.segment.excludedUsers,\n      estimatedSize: this.segment.estimatedSize,\n      updatedAt: new Date(),\n      tags: this.segment.tags,\n    };\n  }\n}\n\n/**\n * Create a new segment builder.\n */\nexport function createSegment(): SegmentBuilder {\n  return new SegmentBuilder();\n}\n\n// ============================================================================\n// Predefined Segment Factories\n// ============================================================================\n\n/**\n * Factory functions for common segment patterns.\n */\nexport const SegmentFactories = {\n  /**\n   * Create an internal users segment (employees).\n   */\n  internal(id: string = 'internal', emailDomain: string = '@company.com'): Segment {\n    return createSegment()\n      .id(id)\n      .name('Internal Users')\n      .description('Company employees and internal users')\n      .or()\n      .endsWith('user.email', emailDomain)\n      .equals('user.isInternal', true)\n      .tag('internal', 'employees')\n      .build();\n  },\n\n  /**\n   * Create a beta users segment.\n   */\n  beta(id: string = 'beta'): Segment {\n    return createSegment()\n      .id(id)\n      .name('Beta Users')\n      .description('Users enrolled in the beta program')\n      .equals('user.isBeta', true)\n      .tag('beta')\n      .build();\n  },\n\n  /**\n   * Create a segment for specific plans/tiers.\n   */\n  plan(id: string, plans: string[]): Segment {\n    return createSegment()\n      .id(id)\n      .name(`${plans.join(' / ')} Users`)\n      .description(`Users on ${plans.join(' or ')} plans`)\n      .in('user.plan', plans)\n      .tag('plan', ...plans)\n      .build();\n  },\n\n  /**\n   * Create a segment for users with specific roles.\n   */\n  roles(id: string, roles: string[]): Segment {\n    return createSegment()\n      .id(id)\n      .name(`${roles.join(' / ')} Roles`)\n      .description(`Users with ${roles.join(' or ')} roles`)\n      .where('user.roles', 'contains', roles[0] ?? '')\n      .tag('rbac', ...roles)\n      .build();\n  },\n\n  /**\n   * Create a geographic segment.\n   */\n  country(id: string, countryCodes: string[]): Segment {\n    return createSegment()\n      .id(id)\n      .name(`${countryCodes.join(' / ')} Region`)\n      .description(`Users from ${countryCodes.join(' or ')}`)\n      .in('network.countryCode', countryCodes)\n      .tag('geo', ...countryCodes)\n      .build();\n  },\n\n  /**\n   * Create a mobile users segment.\n   */\n  mobile(id: string = 'mobile'): Segment {\n    return createSegment()\n      .id(id)\n      .name('Mobile Users')\n      .description('Users on mobile devices')\n      .in('device.type', ['mobile', 'tablet'])\n      .tag('device', 'mobile')\n      .build();\n  },\n\n  /**\n   * Create a new users segment (registered in last N days).\n   */\n  newUsers(id: string, daysAgo: number): Segment {\n    const cutoffDate = new Date();\n    cutoffDate.setDate(cutoffDate.getDate() - daysAgo);\n\n    return createSegment()\n      .id(id)\n      .name(`New Users (${daysAgo} days)`)\n      .description(`Users who registered in the last ${daysAgo} days`)\n      .where('user.createdAt', 'after', cutoffDate.toISOString())\n      .tag('cohort', 'new-users')\n      .build();\n  },\n};\n\n// ============================================================================\n// Segment Composition\n// ============================================================================\n\n/**\n * Compose segments using set operations.\n */\nexport function composeSegments(\n  segments: Map<SegmentId, Segment>,\n  composition: ComposedSegment,\n  context: EvaluationContext,\n  matcher: SegmentMatcher\n): boolean {\n  const segmentList = composition.segments\n    .map((id) => segments.get(id))\n    .filter((s): s is Segment => s !== undefined);\n\n  switch (composition.operation) {\n    case 'union':\n      return matcher.matchesAny(segmentList, context).matched;\n\n    case 'intersection':\n      return matcher.matchesAll(segmentList, context);\n\n    case 'difference': {\n      if (segmentList.length < 2) return false;\n      const [first, ...rest] = segmentList;\n      const firstSegment =\n        first ??\n        ({\n          id: 'dummy',\n          name: 'dummy',\n          rules: { operator: 'and', conditions: [] },\n          createdAt: new Date(),\n          updatedAt: new Date(),\n        } as Segment);\n      return matcher.matches(firstSegment, context) && !matcher.matchesAny(rest, context).matched;\n    }\n\n    default:\n      return false;\n  }\n}\n"],"names":["SegmentMatcher","options","segment","context","startTime","userId","cacheKey","cached","matchedConditions","matched","segments","segmentId","key","group","condition","conditionOrGroup","actualValue","path","parts","current","part","actual","operator","expected","caseSensitive","normalize","v","item","result","SegmentBuilder","id","name","description","attribute","value","values","userIds","tags","size","createSegment","SegmentFactories","emailDomain","plans","roles","countryCodes","daysAgo","cutoffDate","composeSegments","composition","matcher","segmentList","s","first","rest","firstSegment"],"mappings":"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"}