{"version":3,"file":"posthog.mjs","names":[],"sources":["../../src/adapters/posthog.ts"],"sourcesContent":["import type { WideEvent } from '../types'\nimport type { ConfigField } from './_config'\nimport { resolveAdapterConfig } from './_config'\nimport { defineDrain } from './_drain'\nimport { httpPost } from './_http'\nimport { sendBatchToOTLP } from './otlp'\nimport type { OTLPConfig } from './otlp'\n\nexport interface PostHogConfig {\n  /** PostHog project API key */\n  apiKey: string\n  /** PostHog host URL. Default: https://us.i.posthog.com */\n  host?: string\n  /** Request timeout in milliseconds. Default: 5000 */\n  timeout?: number\n}\n\nexport interface PostHogEventsConfig extends PostHogConfig {\n  /** PostHog event name. Default: mxllog_wide_event */\n  eventName?: string\n  /** Override distinct_id (defaults to event.service) */\n  distinctId?: string\n}\n\n/** PostHog event structure for the batch API */\nexport interface PostHogEvent {\n  event: string\n  distinct_id: string\n  timestamp: string\n  properties: Record<string, unknown>\n}\n\nconst POSTHOG_FIELDS: ConfigField<PostHogConfig>[] = [\n  { key: 'apiKey', env: ['NUXT_POSTHOG_API_KEY', 'POSTHOG_API_KEY'] },\n  { key: 'host', env: ['NUXT_POSTHOG_HOST', 'POSTHOG_HOST'] },\n  { key: 'timeout' },\n]\n\nconst POSTHOG_EVENTS_FIELDS: ConfigField<PostHogEventsConfig>[] = [\n  ...POSTHOG_FIELDS,\n  { key: 'eventName' },\n  { key: 'distinctId' },\n]\n\nfunction resolveHost(config: PostHogConfig): string {\n  return (config.host ?? 'https://us.i.posthog.com').replace(/\\/$/, '')\n}\n\nfunction toOTLPConfig(config: PostHogConfig): OTLPConfig {\n  const host = resolveHost(config)\n  return {\n    endpoint: `${host}/i`,\n    headers: { Authorization: `Bearer ${config.apiKey}` },\n    timeout: config.timeout,\n  }\n}\n\n/**\n * Convert a WideEvent to a PostHog custom event format.\n */\nexport function toPostHogEvent(event: WideEvent, config: PostHogEventsConfig): PostHogEvent {\n  const { timestamp, level, service, ...rest } = event\n\n  return {\n    event: config.eventName ?? 'mxllog_wide_event',\n    distinct_id: config.distinctId ?? (typeof event.userId === 'string' ? event.userId : undefined) ?? service,\n    timestamp,\n    properties: {\n      level,\n      service,\n      ...rest,\n    },\n  }\n}\n\n// ---------------------------------------------------------------------------\n// PostHog Logs (OTLP) — default\n// ---------------------------------------------------------------------------\n\n/**\n * Create a drain function for sending logs to PostHog Logs via OTLP.\n *\n * Configuration priority (highest to lowest):\n * 1. Overrides passed to createPostHogDrain()\n * 2. runtimeConfig.mxllog.posthog\n * 3. runtimeConfig.posthog\n * 4. Environment variables: NUXT_POSTHOG_*, POSTHOG_*\n *\n * @example\n * ```ts\n * // Zero config - just set NUXT_POSTHOG_API_KEY env var\n * nitroApp.hooks.hook('mxllog:drain', createPostHogDrain())\n *\n * // With overrides\n * nitroApp.hooks.hook('mxllog:drain', createPostHogDrain({\n *   apiKey: 'phc_...',\n *   host: 'https://eu.i.posthog.com',\n * }))\n * ```\n */\nexport function createPostHogDrain(overrides?: Partial<PostHogConfig>) {\n  return defineDrain<PostHogConfig>({\n    name: 'posthog',\n    resolve: () => {\n      const config = resolveAdapterConfig<PostHogConfig>('posthog', POSTHOG_FIELDS, overrides)\n      if (!config.apiKey) {\n        console.error('[mxllog/posthog] Missing apiKey. Set NUXT_POSTHOG_API_KEY/POSTHOG_API_KEY env var or pass to createPostHogDrain()')\n        return null\n      }\n      return config as PostHogConfig\n    },\n    send: sendBatchToPostHog,\n  })\n}\n\n/**\n * Send a single event to PostHog Logs via OTLP.\n *\n * @example\n * ```ts\n * await sendToPostHog(event, {\n *   apiKey: process.env.POSTHOG_API_KEY!,\n * })\n * ```\n */\nexport async function sendToPostHog(event: WideEvent, config: PostHogConfig): Promise<void> {\n  await sendBatchToPostHog([event], config)\n}\n\n/**\n * Send a batch of events to PostHog Logs via OTLP.\n *\n * @example\n * ```ts\n * await sendBatchToPostHog(events, {\n *   apiKey: process.env.POSTHOG_API_KEY!,\n * })\n * ```\n */\nexport async function sendBatchToPostHog(events: WideEvent[], config: PostHogConfig): Promise<void> {\n  if (events.length === 0) return\n  await sendBatchToOTLP(events, toOTLPConfig(config))\n}\n\n// ---------------------------------------------------------------------------\n// PostHog Events (custom events via /batch/)\n// ---------------------------------------------------------------------------\n\n/**\n * Create a drain function for sending logs to PostHog as custom events.\n *\n * Uses PostHog's `/batch/` API. Consider using `createPostHogDrain()` instead\n * which uses PostHog Logs (OTLP) and is significantly cheaper.\n *\n * Configuration priority (highest to lowest):\n * 1. Overrides passed to createPostHogEventsDrain()\n * 2. runtimeConfig.mxllog.posthog\n * 3. runtimeConfig.posthog\n * 4. Environment variables: NUXT_POSTHOG_API_KEY/POSTHOG_API_KEY, NUXT_POSTHOG_HOST/POSTHOG_HOST\n *\n * @example\n * ```ts\n * nitroApp.hooks.hook('mxllog:drain', createPostHogEventsDrain({\n *   eventName: 'server_request',\n * }))\n * ```\n */\nexport function createPostHogEventsDrain(overrides?: Partial<PostHogEventsConfig>) {\n  return defineDrain<PostHogEventsConfig>({\n    name: 'posthog-events',\n    resolve: () => {\n      const config = resolveAdapterConfig<PostHogEventsConfig>('posthog', POSTHOG_EVENTS_FIELDS, overrides)\n      if (!config.apiKey) {\n        console.error('[mxllog/posthog-events] Missing apiKey. Set NUXT_POSTHOG_API_KEY/POSTHOG_API_KEY env var or pass to createPostHogEventsDrain()')\n        return null\n      }\n      return config as PostHogEventsConfig\n    },\n    send: sendBatchToPostHogEvents,\n  })\n}\n\n/**\n * Send a single event to PostHog as a custom event.\n *\n * @example\n * ```ts\n * await sendToPostHogEvents(event, {\n *   apiKey: process.env.POSTHOG_API_KEY!,\n * })\n * ```\n */\nexport async function sendToPostHogEvents(event: WideEvent, config: PostHogEventsConfig): Promise<void> {\n  await sendBatchToPostHogEvents([event], config)\n}\n\n/**\n * Send a batch of events to PostHog as custom events via the `/batch/` API.\n *\n * @example\n * ```ts\n * await sendBatchToPostHogEvents(events, {\n *   apiKey: process.env.POSTHOG_API_KEY!,\n * })\n * ```\n */\nexport async function sendBatchToPostHogEvents(events: WideEvent[], config: PostHogEventsConfig): Promise<void> {\n  if (events.length === 0) return\n\n  const url = `${resolveHost(config)}/batch/`\n  const batch = events.map(event => toPostHogEvent(event, config))\n\n  await httpPost({\n    url,\n    headers: { 'Content-Type': 'application/json' },\n    body: JSON.stringify({ api_key: config.apiKey, batch }),\n    timeout: config.timeout ?? 5000,\n    label: 'PostHog',\n  })\n}\n"],"mappings":";;;AAgCA,MAAM,iBAA+C;CACnD;EAAE,KAAK;EAAU,KAAK,CAAC,wBAAwB,kBAAkB;EAAE;CACnE;EAAE,KAAK;EAAQ,KAAK,CAAC,qBAAqB,eAAe;EAAE;CAC3D,EAAE,KAAK,WAAW;CACnB;AAED,MAAM,wBAA4D;CAChE,GAAG;CACH,EAAE,KAAK,aAAa;CACpB,EAAE,KAAK,cAAc;CACtB;AAED,SAAS,YAAY,QAA+B;AAClD,SAAQ,OAAO,QAAQ,4BAA4B,QAAQ,OAAO,GAAG;;AAGvE,SAAS,aAAa,QAAmC;AAEvD,QAAO;EACL,UAAU,GAFC,YAAY,OAAO,CAEZ;EAClB,SAAS,EAAE,eAAe,UAAU,OAAO,UAAU;EACrD,SAAS,OAAO;EACjB;;;;;AAMH,SAAgB,eAAe,OAAkB,QAA2C;CAC1F,MAAM,EAAE,WAAW,OAAO,SAAS,GAAG,SAAS;AAE/C,QAAO;EACL,OAAO,OAAO,aAAa;EAC3B,aAAa,OAAO,eAAe,OAAO,MAAM,WAAW,WAAW,MAAM,SAAS,KAAA,MAAc;EACnG;EACA,YAAY;GACV;GACA;GACA,GAAG;GACJ;EACF;;;;;;;;;;;;;;;;;;;;;;;AA4BH,SAAgB,mBAAmB,WAAoC;AACrE,QAAO,YAA2B;EAChC,MAAM;EACN,eAAe;GACb,MAAM,SAAS,qBAAoC,WAAW,gBAAgB,UAAU;AACxF,OAAI,CAAC,OAAO,QAAQ;AAClB,YAAQ,MAAM,oHAAoH;AAClI,WAAO;;AAET,UAAO;;EAET,MAAM;EACP,CAAC;;;;;;;;;;;;AAaJ,eAAsB,cAAc,OAAkB,QAAsC;AAC1F,OAAM,mBAAmB,CAAC,MAAM,EAAE,OAAO;;;;;;;;;;;;AAa3C,eAAsB,mBAAmB,QAAqB,QAAsC;AAClG,KAAI,OAAO,WAAW,EAAG;AACzB,OAAM,gBAAgB,QAAQ,aAAa,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;AA0BrD,SAAgB,yBAAyB,WAA0C;AACjF,QAAO,YAAiC;EACtC,MAAM;EACN,eAAe;GACb,MAAM,SAAS,qBAA0C,WAAW,uBAAuB,UAAU;AACrG,OAAI,CAAC,OAAO,QAAQ;AAClB,YAAQ,MAAM,iIAAiI;AAC/I,WAAO;;AAET,UAAO;;EAET,MAAM;EACP,CAAC;;;;;;;;;;;;AAaJ,eAAsB,oBAAoB,OAAkB,QAA4C;AACtG,OAAM,yBAAyB,CAAC,MAAM,EAAE,OAAO;;;;;;;;;;;;AAajD,eAAsB,yBAAyB,QAAqB,QAA4C;AAC9G,KAAI,OAAO,WAAW,EAAG;CAEzB,MAAM,MAAM,GAAG,YAAY,OAAO,CAAC;CACnC,MAAM,QAAQ,OAAO,KAAI,UAAS,eAAe,OAAO,OAAO,CAAC;AAEhE,OAAM,SAAS;EACb;EACA,SAAS,EAAE,gBAAgB,oBAAoB;EAC/C,MAAM,KAAK,UAAU;GAAE,SAAS,OAAO;GAAQ;GAAO,CAAC;EACvD,SAAS,OAAO,WAAW;EAC3B,OAAO;EACR,CAAC"}