{"version":3,"sources":["../../src/clients/api-outbound-middleware.ts"],"names":[],"mappings":";;;;AAoBA,MAAM,+BAAA,0BAAyC,+CAA+C,CAAA;AAoBvF,SAAS,wBAAA,CACd,UACA,UAAA,EACyB;AACzB,EAAA,MAAM,IAAA,GAAO,EAAE,GAAI,UAAA,IAAc,EAAC,EAAG;AACrC,EAAA,IAAA,CAAK,+BAA+B,CAAA,GAAI,QAAA;AACxC,EAAA,OAAO,IAAA;AACT;AASO,SAAS,qCAAqC,MAAA,EAAoG;AACvJ,EAAA,IAAI,CAAC,OAAO,WAAA,CAAY,IAAA,CAAK,CAAC,UAAA,KAAe,UAAA,YAAsB,8BAA8B,CAAA,EAAG;AAClG,IAAA,MAAA,CAAO,GAAA,CAAI,IAAI,8BAAA,EAAgC,CAAA;AAAA,EACjD;AACF;AAOO,MAAM,8BAAA,CAAqD;AAAA,EAChE,MAAM,MAAA,CACJ,OAAA,EACA,IAAA,EACY;AACZ,IAAA,MAAM,QAAA,GAAW,+BAAA,CAAgC,OAAA,CAAQ,MAAA,CAAO,UAAU,CAAA;AAC1E,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,OAAO,IAAA,EAAK;AAAA,IACd;AAEA,IAAA,OAAO,mBAAkB,CAAE,eAAA;AAAA,MACzB,cAAA,CAAe,SAAA;AAAA,MACf;AAAA,QACE,MAAM,QAAA,CAAS,MAAA;AAAA,QACf,YAAY,QAAA,CAAS;AAAA,OACvB;AAAA,MACA,OAAO,IAAA,KAAS;AACd,QAAA,0BAAA,CAA2B,SAAS,SAAS,CAAA;AAE7C,QAAA,IAAI;AACF,UAAA,IAAI,GAAA;AAIJ,UAAA,IAAI;AACF,YAAA,GAAA,GAAM,MAAM,IAAA,EAAK;AAAA,UACnB,SAAS,KAAA,EAAO;AACd,YAAA,2BAAA,CAA4B,SAAS,SAAS,CAAA;AAC9C,YAAA,uBAAA,CAAwB,MAAM,KAAK,CAAA;AACnC,YAAA,MAAM,KAAA;AAAA,UACR;AAOA,UAAA,IAAI,SAAS,UAAA,EAAY;AACvB,YAAA,IAAI;AACF,cAAA,MAAM,QAAA,CAAS,UAAA,CAAW,IAAA,EAAM,GAAoB,CAAA;AAAA,YACtD,SAAS,SAAA,EAAW;AAClB,cAAA,OAAA,CAAQ,GAAA,CAAI,IAAA;AAAA,gBACV,6DAAA;AAAA,gBACA;AAAA,eACF;AAAA,YACF;AAAA,UACF;AAEA,UAAA,OAAO,GAAA;AAAA,QACT,CAAA,SAAE;AACA,UAAA,IAAA,CAAK,GAAA,EAAI;AAAA,QACX;AAAA,MACF;AAAA,KACF;AAAA,EACF;AACF;AAEA,SAAS,gCACP,UAAA,EAC0C;AAC1C,EAAA,OAAQ,aAA4D,+BAA+B,CAAA;AACrG","file":"api-outbound-middleware.mjs","sourcesContent":["import { SpanKind, type Span } from '@opentelemetry/api';\nimport type { AxiosResponse } from 'axios';\n\nimport type {\n  Middleware,\n  MiddlewareContext,\n  MiddlewareNext\n} from '@microsoft/teams.common';\n\nimport {\n  API_SPAN_NAMES,\n  type ConversationActivityOperation\n} from '../diagnostics/constants';\nimport {\n  getTeamsApiTracer,\n  recordTeamsApiException,\n  recordTeamsApiOutboundCall,\n  recordTeamsApiOutboundError\n} from '../diagnostics/helpers';\n\nconst apiOutboundTelemetryMetadataKey = Symbol('Microsoft.Teams.Api.outboundTelemetryMetadata');\n\ntype ApiOutboundTelemetryMetadata = {\n  readonly operation: ConversationActivityOperation;\n  readonly attributes: Record<string, string>;\n  readonly onResponse?: (span: Span, res: AxiosResponse) => void | Promise<void>;\n};\n\ntype ApiOutboundTelemetryExtensions = Record<string, unknown> & {\n  [apiOutboundTelemetryMetadataKey]?: ApiOutboundTelemetryMetadata;\n};\n\n/**\n * @internal\n * Creates SDK-private request metadata for API outbound telemetry.\n *\n * API client methods use this immediately before calling the shared\n * `HttpClient` so outbound telemetry middleware can create the span and\n * metrics without each method managing telemetry mechanics directly.\n */\nexport function withApiOutboundTelemetry(\n  metadata: ApiOutboundTelemetryMetadata,\n  extensions?: Record<string, unknown>\n): Record<string, unknown> {\n  const next = { ...(extensions ?? {}) } as ApiOutboundTelemetryExtensions;\n  next[apiOutboundTelemetryMetadataKey] = metadata;\n  return next;\n}\n\n/**\n * @internal\n * Ensures Teams API outbound telemetry middleware is registered once.\n *\n * API client construction calls this after creating or receiving the common\n * `HttpClient`; callers can inspect `client.middlewares` for dedupe.\n */\nexport function ensureApiOutboundTelemetryMiddleware(client: { readonly middlewares: readonly Middleware[]; use(middleware: Middleware): number }): void {\n  if (!client.middlewares.some((middleware) => middleware instanceof ApiOutboundTelemetryMiddleware)) {\n    client.use(new ApiOutboundTelemetryMiddleware());\n  }\n}\n\n/**\n * @internal\n * Common HTTP middleware that owns Teams API outbound span lifecycle, metrics,\n * exception recording, and optional response hooks.\n */\nexport class ApiOutboundTelemetryMiddleware implements Middleware {\n  async invoke<R = AxiosResponse, D = any>(\n    context: MiddlewareContext<D>,\n    next: MiddlewareNext<R>\n  ): Promise<R> {\n    const metadata = getApiOutboundTelemetryMetadata(context.config.extensions);\n    if (!metadata) {\n      return next();\n    }\n\n    return getTeamsApiTracer().startActiveSpan(\n      API_SPAN_NAMES.apiClient,\n      {\n        kind: SpanKind.CLIENT,\n        attributes: metadata.attributes,\n      },\n      async (span) => {\n        recordTeamsApiOutboundCall(metadata.operation);\n\n        try {\n          let res: R;\n\n          // next() owns the error path: only genuine call failures are counted\n          // as outbound errors and recorded as exceptions on the span.\n          try {\n            res = await next();\n          } catch (error) {\n            recordTeamsApiOutboundError(metadata.operation);\n            recordTeamsApiException(span, error);\n            throw error;\n          }\n\n          // Telemetry response hooks run in their own try, separate from\n          // next(), so they can never fail the underlying API call: a throwing\n          // or rejecting hook would otherwise discard a successful response, be\n          // counted as an outbound error, and propagate to the caller. Isolate\n          // the hook and swallow (logging) any failure.\n          if (metadata.onResponse) {\n            try {\n              await metadata.onResponse(span, res as AxiosResponse);\n            } catch (hookError) {\n              context.log.warn(\n                'Microsoft.Teams.Api outbound telemetry response hook failed',\n                hookError\n              );\n            }\n          }\n\n          return res;\n        } finally {\n          span.end();\n        }\n      }\n    );\n  }\n}\n\nfunction getApiOutboundTelemetryMetadata(\n  extensions: Record<string, unknown> | undefined\n): ApiOutboundTelemetryMetadata | undefined {\n  return (extensions as ApiOutboundTelemetryExtensions | undefined)?.[apiOutboundTelemetryMetadataKey];\n}\n"]}