{"version":3,"file":"mixpanel.cjs","names":[],"sources":["../src/mixpanel.ts"],"sourcesContent":["/**\n * Mixpanel Subscriber for autotel\n *\n * Send events to Mixpanel for product events.\n *\n * @example\n * ```typescript\n * import { Events } from 'autotel/events';\n * import { MixpanelSubscriber } from 'autotel-subscribers/mixpanel';\n *\n * const events = new Events('checkout', {\n *   subscribers: [\n *     new MixpanelSubscriber({\n *       token: process.env.MIXPANEL_TOKEN!\n *     })\n *   ]\n * });\n *\n * events.trackEvent('order.completed', { userId: '123', amount: 99.99 });\n * ```\n */\n\nimport type {\n  EventSubscriber,\n  EventAttributes,\n  FunnelStatus,\n  OutcomeStatus,\n  EventTrackingOptions,\n  AutotelEventContext,\n} from 'autotel/event-subscriber';\n\nexport interface MixpanelConfig {\n  /** Mixpanel project token */\n  token: string;\n  /** Enable/disable the subscriber */\n  enabled?: boolean;\n}\n\nexport class MixpanelSubscriber implements EventSubscriber {\n  readonly name = 'MixpanelSubscriber';\n  readonly version = '1.0.0';\n\n  private mixpanel: any;\n  private enabled: boolean;\n  private config: MixpanelConfig;\n  private initPromise: Promise<void> | null = null;\n\n  constructor(config: MixpanelConfig) {\n    this.enabled = config.enabled ?? true;\n    this.config = config;\n\n    if (this.enabled) {\n      // Start initialization immediately but don't block constructor\n      this.initPromise = this.initialize();\n    }\n  }\n\n  private async initialize(): Promise<void> {\n    try {\n      // Dynamic import to avoid adding mixpanel as a hard dependency\n      const Mixpanel = await import('mixpanel');\n      this.mixpanel = Mixpanel.default.init(this.config.token);\n    } catch (error) {\n      console.error(\n        'Mixpanel subscriber failed to initialize. Install mixpanel: pnpm add mixpanel',\n        error,\n      );\n      this.enabled = false;\n    }\n  }\n\n  private async ensureInitialized(): Promise<void> {\n    if (this.initPromise) {\n      await this.initPromise;\n      this.initPromise = null;\n    }\n  }\n\n  /**\n   * Map autotel context to Mixpanel properties\n   *\n   * Mixpanel uses standard snake_case field names:\n   * - autotel.trace_id → trace_id\n   * - autotel.span_id → span_id\n   * - autotel.correlation_id → correlation_id\n   */\n  private mapAutotelContext(\n    autotel?: AutotelEventContext,\n  ): Record<string, unknown> {\n    if (!autotel) return {};\n\n    const mapped: Record<string, unknown> = {};\n\n    if (autotel.trace_id) {\n      mapped.trace_id = autotel.trace_id;\n    }\n    if (autotel.span_id) {\n      mapped.span_id = autotel.span_id;\n    }\n    if (autotel.correlation_id) {\n      mapped.correlation_id = autotel.correlation_id;\n    }\n    if (autotel.trace_flags) {\n      mapped.trace_flags = autotel.trace_flags;\n    }\n    if (autotel.trace_state) {\n      mapped.trace_state = autotel.trace_state;\n    }\n    if (autotel.trace_url) {\n      mapped.trace_url = autotel.trace_url;\n    }\n    // Batch/fan-in context\n    if (autotel.linked_trace_id_count !== undefined) {\n      mapped.linked_trace_id_count = autotel.linked_trace_id_count;\n    }\n    if (autotel.linked_trace_id_hash) {\n      mapped.linked_trace_id_hash = autotel.linked_trace_id_hash;\n    }\n    if (autotel.linked_trace_ids) {\n      mapped.linked_trace_ids = autotel.linked_trace_ids;\n    }\n\n    return mapped;\n  }\n\n  async trackEvent(\n    name: string,\n    attributes?: EventAttributes,\n    options?: EventTrackingOptions,\n  ): Promise<void> {\n    if (!this.enabled) return;\n\n    await this.ensureInitialized();\n    const distinctId = attributes?.userId || attributes?.user_id || 'anonymous';\n    const autotelProps = this.mapAutotelContext(options?.autotel);\n\n    this.mixpanel?.track(name, {\n      distinct_id: distinctId,\n      ...attributes,\n      ...autotelProps,\n    });\n  }\n\n  async trackFunnelStep(\n    funnelName: string,\n    step: FunnelStatus,\n    attributes?: EventAttributes,\n    options?: EventTrackingOptions,\n  ): Promise<void> {\n    if (!this.enabled) return;\n\n    await this.ensureInitialized();\n    const distinctId = attributes?.userId || attributes?.user_id || 'anonymous';\n    const autotelProps = this.mapAutotelContext(options?.autotel);\n\n    this.mixpanel?.track(`${funnelName}.${step}`, {\n      distinct_id: distinctId,\n      funnel: funnelName,\n      step,\n      ...attributes,\n      ...autotelProps,\n    });\n  }\n\n  async trackOutcome(\n    operationName: string,\n    outcome: OutcomeStatus,\n    attributes?: EventAttributes,\n    options?: EventTrackingOptions,\n  ): Promise<void> {\n    if (!this.enabled) return;\n\n    await this.ensureInitialized();\n    const distinctId = attributes?.userId || attributes?.user_id || 'anonymous';\n    const autotelProps = this.mapAutotelContext(options?.autotel);\n\n    this.mixpanel?.track(`${operationName}.${outcome}`, {\n      distinct_id: distinctId,\n      operation: operationName,\n      outcome,\n      ...attributes,\n      ...autotelProps,\n    });\n  }\n\n  async trackValue(\n    name: string,\n    value: number,\n    attributes?: EventAttributes,\n    options?: EventTrackingOptions,\n  ): Promise<void> {\n    if (!this.enabled) return;\n\n    await this.ensureInitialized();\n    const distinctId = attributes?.userId || attributes?.user_id || 'anonymous';\n    const autotelProps = this.mapAutotelContext(options?.autotel);\n\n    this.mixpanel?.track(name, {\n      distinct_id: distinctId,\n      value,\n      ...attributes,\n      ...autotelProps,\n    });\n  }\n}\n"],"mappings":";;;;AAsCA,IAAa,qBAAb,MAA2D;CACzD,AAAS,OAAO;CAChB,AAAS,UAAU;CAEnB,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ,cAAoC;CAE5C,YAAY,QAAwB;EAClC,KAAK,UAAU,OAAO,WAAW;EACjC,KAAK,SAAS;EAEd,IAAI,KAAK,SAEP,KAAK,cAAc,KAAK,WAAW;CAEvC;CAEA,MAAc,aAA4B;EACxC,IAAI;GAEF,MAAM,WAAW,iFAAM;GACvB,KAAK,WAAW,SAAS,QAAQ,KAAK,KAAK,OAAO,KAAK;EACzD,SAAS,OAAO;GACd,QAAQ,MACN,iFACA,KACF;GACA,KAAK,UAAU;EACjB;CACF;CAEA,MAAc,oBAAmC;EAC/C,IAAI,KAAK,aAAa;GACpB,MAAM,KAAK;GACX,KAAK,cAAc;EACrB;CACF;;;;;;;;;CAUA,AAAQ,kBACN,SACyB;EACzB,IAAI,CAAC,SAAS,OAAO,CAAC;EAEtB,MAAM,SAAkC,CAAC;EAEzC,IAAI,QAAQ,UACV,OAAO,WAAW,QAAQ;EAE5B,IAAI,QAAQ,SACV,OAAO,UAAU,QAAQ;EAE3B,IAAI,QAAQ,gBACV,OAAO,iBAAiB,QAAQ;EAElC,IAAI,QAAQ,aACV,OAAO,cAAc,QAAQ;EAE/B,IAAI,QAAQ,aACV,OAAO,cAAc,QAAQ;EAE/B,IAAI,QAAQ,WACV,OAAO,YAAY,QAAQ;EAG7B,IAAI,QAAQ,0BAA0B,QACpC,OAAO,wBAAwB,QAAQ;EAEzC,IAAI,QAAQ,sBACV,OAAO,uBAAuB,QAAQ;EAExC,IAAI,QAAQ,kBACV,OAAO,mBAAmB,QAAQ;EAGpC,OAAO;CACT;CAEA,MAAM,WACJ,MACA,YACA,SACe;EACf,IAAI,CAAC,KAAK,SAAS;EAEnB,MAAM,KAAK,kBAAkB;EAC7B,MAAM,aAAa,YAAY,UAAU,YAAY,WAAW;EAChE,MAAM,eAAe,KAAK,kBAAkB,SAAS,OAAO;EAE5D,KAAK,UAAU,MAAM,MAAM;GACzB,aAAa;GACb,GAAG;GACH,GAAG;EACL,CAAC;CACH;CAEA,MAAM,gBACJ,YACA,MACA,YACA,SACe;EACf,IAAI,CAAC,KAAK,SAAS;EAEnB,MAAM,KAAK,kBAAkB;EAC7B,MAAM,aAAa,YAAY,UAAU,YAAY,WAAW;EAChE,MAAM,eAAe,KAAK,kBAAkB,SAAS,OAAO;EAE5D,KAAK,UAAU,MAAM,GAAG,WAAW,GAAG,QAAQ;GAC5C,aAAa;GACb,QAAQ;GACR;GACA,GAAG;GACH,GAAG;EACL,CAAC;CACH;CAEA,MAAM,aACJ,eACA,SACA,YACA,SACe;EACf,IAAI,CAAC,KAAK,SAAS;EAEnB,MAAM,KAAK,kBAAkB;EAC7B,MAAM,aAAa,YAAY,UAAU,YAAY,WAAW;EAChE,MAAM,eAAe,KAAK,kBAAkB,SAAS,OAAO;EAE5D,KAAK,UAAU,MAAM,GAAG,cAAc,GAAG,WAAW;GAClD,aAAa;GACb,WAAW;GACX;GACA,GAAG;GACH,GAAG;EACL,CAAC;CACH;CAEA,MAAM,WACJ,MACA,OACA,YACA,SACe;EACf,IAAI,CAAC,KAAK,SAAS;EAEnB,MAAM,KAAK,kBAAkB;EAC7B,MAAM,aAAa,YAAY,UAAU,YAAY,WAAW;EAChE,MAAM,eAAe,KAAK,kBAAkB,SAAS,OAAO;EAE5D,KAAK,UAAU,MAAM,MAAM;GACzB,aAAa;GACb;GACA,GAAG;GACH,GAAG;EACL,CAAC;CACH;AACF"}