{"version":3,"sources":["../src/messaging-adapters.ts"],"names":["TraceFlags","traceId","spanId","sampled"],"mappings":"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","file":"messaging-adapters.cjs","sourcesContent":["/**\n * Pre-built adapter configurations for common messaging systems.\n *\n * These adapters provide ready-to-use hook configurations for systems\n * not explicitly supported by the core messaging module. Use them with\n * traceProducer/traceConsumer to get system-specific attributes.\n *\n * @example NATS consumer\n * ```typescript\n * import { traceConsumer } from 'autotel/messaging';\n * import { natsAdapter } from 'autotel/messaging/adapters';\n *\n * const processMessage = traceConsumer({\n *   system: 'nats',\n *   destination: 'orders',\n *   ...natsAdapter.consumer,\n * })(ctx => async (msg) => {\n *   // msg.subject, msg.info.stream are now captured as span attributes\n *   await handleOrder(msg.data);\n * });\n * ```\n *\n * @example Datadog context propagation\n * ```typescript\n * import { traceConsumer } from 'autotel/messaging';\n * import { datadogContextExtractor } from 'autotel/messaging/adapters';\n *\n * const processMessage = traceConsumer({\n *   system: 'kafka',\n *   destination: 'events',\n *   customContextExtractor: datadogContextExtractor,\n * })(ctx => async (msg) => {\n *   // Parent span from Datadog trace headers is linked\n * });\n * ```\n *\n * @module\n */\n\nimport type { AttributeValue, SpanContext } from '@opentelemetry/api';\nimport { TraceFlags } from '@opentelemetry/api';\nimport type { ProducerContext, ConsumerContext } from './messaging';\n\n// ============================================================================\n// Adapter Types\n// ============================================================================\n\n/**\n * Producer adapter configuration\n */\nexport interface ProducerAdapter {\n  /**\n   * Hook to add system-specific attributes to producer spans\n   */\n  customAttributes?: (\n    ctx: ProducerContext,\n    args: unknown[],\n  ) => Record<string, AttributeValue>;\n\n  /**\n   * Hook to inject custom headers beyond W3C traceparent\n   */\n  customHeaders?: (ctx: ProducerContext) => Record<string, string>;\n}\n\n/**\n * Consumer adapter configuration\n */\nexport interface ConsumerAdapter {\n  /**\n   * Extract headers from the message for trace context propagation\n   */\n  headersFrom?: (msg: unknown) => Record<string, string> | undefined;\n\n  /**\n   * Hook to add system-specific attributes to consumer spans\n   */\n  customAttributes?: (\n    ctx: ConsumerContext,\n    msg: unknown,\n  ) => Record<string, AttributeValue>;\n\n  /**\n   * Hook to extract parent span context from non-W3C header formats\n   */\n  customContextExtractor?: (\n    headers: Record<string, string>,\n  ) => SpanContext | null;\n}\n\n/**\n * Combined producer and consumer adapter\n */\nexport interface MessagingAdapter {\n  producer?: ProducerAdapter;\n  consumer?: ConsumerAdapter;\n}\n\n// ============================================================================\n// NATS JetStream Adapter\n// ============================================================================\n\n/**\n * NATS JetStream message type (for reference)\n *\n * @internal Not exported - users bring their own NATS types\n */\ninterface NatsJetStreamMsg {\n  subject: string;\n  reply?: string;\n  data: Uint8Array;\n  headers?: {\n    /** Convert headers to plain object (some NATS implementations) */\n    toJSON?: () => Record<string, string> | unknown;\n    /** Get a header value by key (Headers-like interface) */\n    get?: (key: string) => string | undefined;\n    /** Iterate over header entries */\n    entries?: () => Iterable<[string, string]>;\n  };\n  info?: {\n    stream: string;\n    consumer: string;\n    redeliveryCount?: number;\n    pending?: number;\n    timestampNanos?: bigint;\n  };\n}\n\n/**\n * NATS JetStream adapter\n *\n * Captures NATS-specific attributes following NATS observability conventions.\n *\n * @example Producer\n * ```typescript\n * const publishOrder = traceProducer({\n *   system: 'nats',\n *   destination: 'orders.created',\n *   ...natsAdapter.producer,\n * })(ctx => async (subject, payload, opts) => {\n *   const headers = ctx.getTraceHeaders();\n *   await nc.publish(subject, payload, { headers });\n * });\n * ```\n *\n * @example Consumer\n * ```typescript\n * const processOrder = traceConsumer({\n *   system: 'nats',\n *   destination: 'orders.created',\n *   consumerGroup: 'order-processor',\n *   ...natsAdapter.consumer,\n * })(ctx => async (msg: JsMsg) => {\n *   await handleOrder(msg.data);\n *   msg.ack();\n * });\n * ```\n */\nexport const natsAdapter: MessagingAdapter = {\n  producer: {\n    customAttributes: (_ctx, args) => {\n      const msg = args[0] as\n        | { subject?: string; replyTo?: string; stream?: string }\n        | undefined;\n      const attrs: Record<string, AttributeValue> = {};\n\n      if (msg?.subject) attrs['nats.subject'] = msg.subject;\n      if (msg?.replyTo) attrs['nats.reply_to'] = msg.replyTo;\n      if (msg?.stream) attrs['nats.stream'] = msg.stream;\n\n      return attrs;\n    },\n  },\n  consumer: {\n    headersFrom: (msg) => {\n      const natsMsg = msg as NatsJetStreamMsg;\n      const headers = natsMsg.headers;\n\n      if (!headers) return;\n\n      // Try toJSON() first (some NATS implementations)\n      if (typeof headers.toJSON === 'function') {\n        const json = headers.toJSON();\n        if (json && typeof json === 'object') {\n          return json as Record<string, string>;\n        }\n      }\n\n      // Fallback: use .get() for common trace headers\n      // This handles Headers-like objects that only expose .get()\n      if (typeof headers.get === 'function') {\n        const result: Record<string, string> = {};\n        const traceHeaders = [\n          'traceparent',\n          'tracestate',\n          'baggage',\n          'x-b3-traceid',\n          'x-b3-spanid',\n          'x-b3-sampled',\n          'b3',\n        ];\n        for (const key of traceHeaders) {\n          const value = headers.get(key);\n          if (value) {\n            result[key] = value;\n          }\n        }\n        if (Object.keys(result).length > 0) {\n          return result;\n        }\n      }\n\n      // Fallback: try to iterate if it's iterable (e.g., entries())\n      if (typeof headers.entries === 'function') {\n        const result: Record<string, string> = {};\n        for (const [key, value] of headers.entries()) {\n          if (typeof key === 'string' && typeof value === 'string') {\n            result[key] = value;\n          }\n        }\n        if (Object.keys(result).length > 0) {\n          return result;\n        }\n      }\n\n      return;\n    },\n    customAttributes: (_ctx, msg) => {\n      const natsMsg = msg as NatsJetStreamMsg;\n      const attrs: Record<string, AttributeValue> = {};\n\n      if (natsMsg.subject) attrs['nats.subject'] = natsMsg.subject;\n      if (natsMsg.reply) attrs['nats.reply_to'] = natsMsg.reply;\n      if (natsMsg.info?.stream) attrs['nats.stream'] = natsMsg.info.stream;\n      if (natsMsg.info?.consumer)\n        attrs['nats.consumer'] = natsMsg.info.consumer;\n      if (natsMsg.info?.redeliveryCount !== undefined) {\n        attrs['nats.delivered_count'] = natsMsg.info.redeliveryCount;\n      }\n      if (natsMsg.info?.pending !== undefined) {\n        attrs['nats.pending'] = natsMsg.info.pending;\n      }\n\n      return attrs;\n    },\n  },\n};\n\n// ============================================================================\n// Temporal Adapter\n// ============================================================================\n\n/**\n * Temporal activity/workflow info type (for reference)\n *\n * @internal Not exported - users bring their own Temporal types\n */\ninterface TemporalActivityInfo {\n  workflowId?: string;\n  runId?: string;\n  activityId?: string;\n  taskQueue?: string;\n  attempt?: number;\n  workflowType?: string;\n  activityType?: string;\n  startToCloseTimeout?: string;\n  scheduleToCloseTimeout?: string;\n}\n\n/**\n * Temporal adapter\n *\n * Captures Temporal-specific attributes for workflow activities.\n * Use this when instrumenting Temporal activity handlers.\n *\n * @example Activity handler\n * ```typescript\n * const processOrder = traceConsumer({\n *   system: 'temporal',\n *   destination: 'order-activities',\n *   ...temporalAdapter.consumer,\n * })(ctx => async (info: ActivityInfo, input: OrderInput) => {\n *   // Temporal attributes are captured automatically\n *   return processOrderLogic(input);\n * });\n * ```\n *\n * @example Workflow signal/query\n * ```typescript\n * const sendSignal = traceProducer({\n *   system: 'temporal',\n *   destination: 'order-signals',\n *   ...temporalAdapter.producer,\n * })(ctx => async (workflowId, signalName, payload) => {\n *   await client.workflow.signal(workflowId, signalName, payload);\n * });\n * ```\n */\nexport const temporalAdapter: MessagingAdapter = {\n  producer: {\n    customAttributes: (_ctx, args) => {\n      const info = args[0] as TemporalActivityInfo | undefined;\n      const attrs: Record<string, AttributeValue> = {};\n\n      if (info?.workflowId) attrs['temporal.workflow_id'] = info.workflowId;\n      if (info?.runId) attrs['temporal.run_id'] = info.runId;\n      if (info?.taskQueue) attrs['temporal.task_queue'] = info.taskQueue;\n      if (info?.workflowType)\n        attrs['temporal.workflow_type'] = info.workflowType;\n\n      return attrs;\n    },\n  },\n  consumer: {\n    customAttributes: (_ctx, msg) => {\n      const info = msg as TemporalActivityInfo;\n      const attrs: Record<string, AttributeValue> = {};\n\n      if (info.workflowId) attrs['temporal.workflow_id'] = info.workflowId;\n      if (info.runId) attrs['temporal.run_id'] = info.runId;\n      if (info.activityId) attrs['temporal.activity_id'] = info.activityId;\n      if (info.taskQueue) attrs['temporal.task_queue'] = info.taskQueue;\n      if (info.attempt !== undefined) attrs['temporal.attempt'] = info.attempt;\n      if (info.activityType)\n        attrs['temporal.activity_type'] = info.activityType;\n\n      return attrs;\n    },\n  },\n};\n\n// ============================================================================\n// Cloudflare Queues Adapter\n// ============================================================================\n\n/**\n * Cloudflare Queue message type (for reference)\n *\n * @internal Not exported - users bring their own Cloudflare types\n */\ninterface CloudflareQueueMessage {\n  id: string;\n  timestamp: Date;\n  body: unknown;\n  attempts: number;\n}\n\n/**\n * Cloudflare Queues adapter\n *\n * Captures Cloudflare Queue-specific attributes.\n *\n * @example Queue consumer\n * ```typescript\n * export default {\n *   async queue(batch: MessageBatch, env: Env) {\n *     for (const msg of batch.messages) {\n *       await processMessage(msg);\n *     }\n *   },\n * };\n *\n * const processMessage = traceConsumer({\n *   system: 'cloudflare_queues',\n *   destination: 'my-queue',\n *   ...cloudflareQueuesAdapter.consumer,\n * })(ctx => async (msg: Message) => {\n *   await handleMessage(msg.body);\n *   msg.ack();\n * });\n * ```\n */\nexport const cloudflareQueuesAdapter: MessagingAdapter = {\n  consumer: {\n    customAttributes: (_ctx, msg) => {\n      const cfMsg = msg as CloudflareQueueMessage;\n      const attrs: Record<string, AttributeValue> = {};\n\n      if (cfMsg.id) attrs['cloudflare.queue.message_id'] = cfMsg.id;\n      if (cfMsg.timestamp) {\n        attrs['cloudflare.queue.timestamp_ms'] = cfMsg.timestamp.getTime();\n      }\n      if (cfMsg.attempts !== undefined) {\n        attrs['cloudflare.queue.attempts'] = cfMsg.attempts;\n      }\n\n      return attrs;\n    },\n  },\n};\n\n// ============================================================================\n// Context Extractors for Non-W3C Formats\n// ============================================================================\n\n/**\n * Datadog trace context extractor\n *\n * Extracts parent span context from Datadog-format trace headers.\n * Converts Datadog's decimal IDs to OpenTelemetry's hex format.\n *\n * Note: Datadog sends trace/span IDs as decimal strings, not hex.\n * This extractor converts decimal -> hex before formatting for OTel.\n *\n * @example\n * ```typescript\n * const processMessage = traceConsumer({\n *   system: 'kafka',\n *   destination: 'events',\n *   customContextExtractor: datadogContextExtractor,\n * })(ctx => async (msg) => {\n *   // Links to parent Datadog span automatically\n * });\n * ```\n */\nexport function datadogContextExtractor(\n  headers: Record<string, string>,\n): SpanContext | null {\n  const traceIdDecimal = headers['x-datadog-trace-id'];\n  const spanIdDecimal = headers['x-datadog-parent-id'];\n  const samplingPriority = headers['x-datadog-sampling-priority'];\n\n  if (!traceIdDecimal || !spanIdDecimal) return null;\n\n  // Datadog sends IDs as decimal strings - convert to hex\n  // Use BigInt for 64-bit values that exceed Number.MAX_SAFE_INTEGER\n  let otelTraceId: string;\n  let otelSpanId: string;\n\n  try {\n    // Convert decimal to hex and pad to OTel format\n    // OTel trace IDs are 32 hex chars (128-bit), Datadog uses 64-bit\n    otelTraceId = BigInt(traceIdDecimal).toString(16).padStart(32, '0');\n    // OTel span IDs are 16 hex chars (64-bit)\n    otelSpanId = BigInt(spanIdDecimal).toString(16).padStart(16, '0');\n  } catch {\n    // Invalid decimal string\n    return null;\n  }\n\n  // Sampling priority > 0 means sampled\n  const sampled = samplingPriority\n    ? Number.parseInt(samplingPriority, 10) > 0\n    : true;\n\n  return {\n    traceId: otelTraceId,\n    spanId: otelSpanId,\n    traceFlags: sampled ? TraceFlags.SAMPLED : TraceFlags.NONE,\n    isRemote: true,\n  };\n}\n\n/**\n * B3 (Zipkin) trace context extractor\n *\n * Extracts parent span context from B3 format headers.\n * Supports both single-header (b3) and multi-header formats.\n *\n * @see https://github.com/openzipkin/b3-propagation\n *\n * @example Single-header format\n * ```typescript\n * // Header: b3: 80f198ee56343ba864fe8b2a57d3eff7-e457b5a2e4d86bd1-1\n * const processMessage = traceConsumer({\n *   system: 'rabbitmq',\n *   destination: 'events',\n *   customContextExtractor: b3ContextExtractor,\n * })(ctx => async (msg) => {\n *   // Links to parent Zipkin span\n * });\n * ```\n *\n * @example Multi-header format\n * ```typescript\n * // Headers: X-B3-TraceId, X-B3-SpanId, X-B3-Sampled\n * ```\n */\nexport function b3ContextExtractor(\n  headers: Record<string, string>,\n): SpanContext | null {\n  // Try single-header format first: {TraceId}-{SpanId}-{SamplingState}-{ParentSpanId}\n  const b3Single = headers['b3'] || headers['B3'];\n  if (b3Single) {\n    // Handle \"0\" (not sampled, no trace) case\n    if (b3Single === '0') return null;\n\n    const parts = b3Single.split('-');\n    const traceId = parts[0];\n    const spanId = parts[1];\n    const sampledFlag = parts[2];\n\n    if (traceId && spanId) {\n      const sampled = sampledFlag !== '0' && sampledFlag !== 'd';\n\n      return {\n        traceId: traceId.padStart(32, '0'),\n        spanId: spanId.padStart(16, '0'),\n        traceFlags: sampled ? TraceFlags.SAMPLED : TraceFlags.NONE,\n        isRemote: true,\n      };\n    }\n  }\n\n  // Fall back to multi-header format\n  const traceId =\n    headers['x-b3-traceid'] ||\n    headers['X-B3-TraceId'] ||\n    headers['X-B3-Traceid'];\n  const spanId =\n    headers['x-b3-spanid'] || headers['X-B3-SpanId'] || headers['X-B3-Spanid'];\n  const sampledHeader =\n    headers['x-b3-sampled'] ||\n    headers['X-B3-Sampled'] ||\n    headers['x-b3-flags'] ||\n    headers['X-B3-Flags'];\n\n  if (!traceId || !spanId) return null;\n\n  // x-b3-sampled: \"1\" or \"true\" = sampled, \"0\" or \"false\" = not sampled\n  // x-b3-flags: \"1\" = debug (implies sampled)\n  const sampled =\n    sampledHeader === '1' ||\n    sampledHeader === 'true' ||\n    sampledHeader === undefined; // Default to sampled if not specified\n\n  return {\n    traceId: traceId.padStart(32, '0'),\n    spanId: spanId.padStart(16, '0'),\n    traceFlags: sampled ? TraceFlags.SAMPLED : TraceFlags.NONE,\n    isRemote: true,\n  };\n}\n\n/**\n * AWS X-Ray trace context extractor\n *\n * Extracts parent span context from AWS X-Ray trace header.\n * Format: Root=1-{timestamp}-{random};Parent={parent-id};Sampled={0|1}\n *\n * @example\n * ```typescript\n * const processMessage = traceConsumer({\n *   system: 'sqs',\n *   destination: 'my-queue',\n *   customContextExtractor: xrayContextExtractor,\n * })(ctx => async (msg) => {\n *   // Links to parent X-Ray trace\n * });\n * ```\n */\nexport function xrayContextExtractor(\n  headers: Record<string, string>,\n): SpanContext | null {\n  const xrayHeader = headers['x-amzn-trace-id'] || headers['X-Amzn-Trace-Id'];\n\n  if (!xrayHeader) return null;\n\n  // Parse: Root=1-{8-char-timestamp}-{24-char-random};Parent={16-char-parent};Sampled=1\n  const rootMatch = xrayHeader.match(/Root=1-([a-f0-9]{8})-([a-f0-9]{24})/i);\n  const parentMatch = xrayHeader.match(/Parent=([a-f0-9]{16})/i);\n  const sampledMatch = xrayHeader.match(/Sampled=([01])/);\n\n  if (!rootMatch || !parentMatch) return null;\n\n  // X-Ray trace ID format: 1-{timestamp}-{random} -> OTel: {timestamp}{random}\n  const timestamp = rootMatch[1];\n  const random = rootMatch[2];\n  const parentId = parentMatch[1];\n\n  if (!timestamp || !random || !parentId) return null;\n\n  const traceId = `${timestamp}${random}`;\n  const spanId = parentId;\n  const sampled = sampledMatch ? sampledMatch[1] === '1' : true;\n\n  return {\n    traceId,\n    spanId,\n    traceFlags: sampled ? TraceFlags.SAMPLED : TraceFlags.NONE,\n    isRemote: true,\n  };\n}\n"]}