{"version":3,"file":"decorators.cjs","names":["getConfig","createTraceContext","SpanStatusCode"],"sources":["../src/decorators.ts"],"sourcesContent":["/**\n * TypeScript 5+ Decorators for autotel\n *\n * Provides @Trace decorator for class-based code.\n *\n * **Requires TypeScript 5.0+**\n *\n * @example Method decorator\n * ```typescript\n * import { Trace } from 'autotel/decorators'\n *\n * class OrderService {\n *   @Trace('order.create', { withMetrics: true })\n *   async createOrder(data: OrderData) {\n *     return await db.orders.create(data)\n *   }\n *\n *   @Trace() // Uses method name as span name\n *   async processPayment(orderId: string) {\n *     return await stripe.charge(orderId)\n *   }\n * }\n * ```\n */\n\nimport type { TracingOptions, TraceContext } from './functional';\nimport { getConfig } from './config';\nimport { SpanStatusCode } from '@opentelemetry/api';\nimport { createTraceContext } from './trace-context';\n\n/**\n * Options for @Trace method decorator\n */\nexport interface TraceDecoratorOptions extends Omit<TracingOptions, 'name'> {\n  /**\n   * Custom span name. If not provided, uses the method name.\n   */\n  name?: string;\n}\n\n/**\n * @Trace - Method decorator for fine-grained tracing\n *\n * Wraps a class method with automatic tracing. Supports both patterns:\n * - Simple: method doesn't use ctx\n * - Advanced: method accesses ctx via this.ctx\n *\n * @example Simple usage (no ctx)\n * ```typescript\n * class OrderService {\n *   @Trace()\n *   async createOrder(data: OrderData) {\n *     return await db.orders.create(data)\n *   }\n * }\n * ```\n *\n * @example With custom name and options\n * ```typescript\n * class PaymentService {\n *   @Trace('payment.charge', { withMetrics: true })\n *   async chargeCard(amount: number) {\n *     return await stripe.charges.create({ amount })\n *   }\n * }\n * ```\n *\n * @example Accessing ctx\n * ```typescript\n * interface WithTraceContext {\n *   ctx?: TraceContext\n * }\n *\n * class UserService {\n *   @Trace()\n *   async createUser(data: UserData) {\n *     // Access ctx via this.ctx (available during execution)\n *     const ctx = (this as unknown as WithTraceContext).ctx\n *     if (ctx) {\n *       ctx.setAttribute('user.id', data.id)\n *     }\n *     return await db.users.create(data)\n *   }\n * }\n * ```\n */\nexport function Trace(\n  options?: TraceDecoratorOptions,\n): <T extends (...args: unknown[]) => Promise<unknown>>(\n  originalMethod: T,\n  context: ClassMethodDecoratorContext,\n) => T;\nexport function Trace(\n  name?: string,\n  options?: TraceDecoratorOptions,\n): <T extends (...args: unknown[]) => Promise<unknown>>(\n  originalMethod: T,\n  context: ClassMethodDecoratorContext,\n) => T;\nexport function Trace(\n  nameOrOptions?: string | TraceDecoratorOptions,\n  maybeOptions?: TraceDecoratorOptions,\n): <T extends (...args: unknown[]) => Promise<unknown>>(\n  originalMethod: T,\n  context: ClassMethodDecoratorContext,\n) => T {\n  // Parse arguments\n  const name =\n    typeof nameOrOptions === 'string' ? nameOrOptions : nameOrOptions?.name;\n  // Options are used in the returned decorator function, not here\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  const _options: TraceDecoratorOptions =\n    typeof nameOrOptions === 'string'\n      ? maybeOptions || {}\n      : nameOrOptions || {};\n\n  // TypeScript 5+ decorator signature\n  return function <T extends (...args: unknown[]) => Promise<unknown>>(\n    originalMethod: T,\n    context: ClassMethodDecoratorContext,\n  ): T {\n    const methodName = String(context.name);\n\n    // Skip if not an async function\n    // Check multiple ways to detect async functions (for different transpilation environments)\n    // TypeScript decorators run at class definition time, so we need robust detection\n    const methodStr = originalMethod?.toString() || '';\n    const isAsync =\n      originalMethod &&\n      (originalMethod.constructor?.name === 'AsyncFunction' ||\n        methodStr.trim().startsWith('async ') ||\n        (methodStr.includes('[native code]') && methodStr.includes('async')) ||\n        // Fallback: if function has async in its string representation\n        /async\\s+/.test(methodStr));\n\n    if (!isAsync) {\n      // Not an async function, return as-is\n      return originalMethod;\n    }\n\n    const spanName = name || methodName;\n\n    return async function <This>(\n      this: This,\n      ...args: unknown[]\n    ): Promise<unknown> {\n      const config = getConfig();\n      const tracer = config.tracer;\n\n      return tracer.startActiveSpan(spanName, async (span) => {\n        try {\n          // Make ctx available via this.ctx for methods that need it\n          const ctx: TraceContext = createTraceContext(span);\n\n          const originalCtx = (this as { ctx?: TraceContext }).ctx;\n          try {\n            (this as { ctx?: TraceContext }).ctx = ctx;\n            const result = await originalMethod.apply(this, args as []);\n            span.setStatus({ code: SpanStatusCode.OK });\n            return result;\n          } finally {\n            // Restore original ctx\n            if (originalCtx === undefined) {\n              delete (this as { ctx?: TraceContext }).ctx;\n            } else {\n              (this as { ctx?: TraceContext }).ctx = originalCtx;\n            }\n          }\n        } catch (error) {\n          span.setStatus({\n            code: SpanStatusCode.ERROR,\n            message: error instanceof Error ? error.message : 'Unknown error',\n          });\n          span.recordException(\n            error instanceof Error ? error : new Error(String(error)),\n          );\n          throw error;\n        } finally {\n          span.end();\n        }\n      });\n    } as T;\n  };\n}\n\n// Re-export types for convenience\n\nexport { type TraceContext, type TracingOptions } from './functional';\n"],"mappings":";;;;;;AAmGA,SAAgB,MACd,eACA,cAIK;CAEL,MAAM,OACJ,OAAO,kBAAkB,WAAW,gBAAgB,eAAe;CASrE,OAAO,SACL,gBACA,SACG;EACH,MAAM,aAAa,OAAO,QAAQ,IAAI;EAKtC,MAAM,YAAY,gBAAgB,SAAS,KAAK;EAShD,IAAI,EAPF,mBACC,eAAe,aAAa,SAAS,mBACpC,UAAU,KAAK,CAAC,CAAC,WAAW,QAAQ,KACnC,UAAU,SAAS,eAAe,KAAK,UAAU,SAAS,OAAO,KAElE,WAAW,KAAK,SAAS,KAI3B,OAAO;EAGT,MAAM,WAAW,QAAQ;EAEzB,OAAO,eAEL,GAAG,MACe;GAIlB,OAHeA,yBACK,CAAC,CAAC,OAER,gBAAgB,UAAU,OAAO,SAAS;IACtD,IAAI;KAEF,MAAM,MAAoBC,iCAAmB,IAAI;KAEjD,MAAM,cAAe,KAAgC;KACrD,IAAI;MACF,AAAC,KAAgC,MAAM;MACvC,MAAM,SAAS,MAAM,eAAe,MAAM,MAAM,IAAU;MAC1D,KAAK,UAAU,EAAE,MAAMC,kCAAe,GAAG,CAAC;MAC1C,OAAO;KACT,UAAU;MAER,IAAI,gBAAgB,QAClB,OAAQ,KAAgC;WAExC,AAAC,KAAgC,MAAM;KAE3C;IACF,SAAS,OAAO;KACd,KAAK,UAAU;MACb,MAAMA,kCAAe;MACrB,SAAS,iBAAiB,QAAQ,MAAM,UAAU;KACpD,CAAC;KACD,KAAK,gBACH,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,CAC1D;KACA,MAAM;IACR,UAAU;KACR,KAAK,IAAI;IACX;GACF,CAAC;EACH;CACF;AACF"}