import type { ITracer, SpanOpts } from "./tracer.interface"; import type { Instrumented } from "../conformance/brands"; import { attachBrand } from "../conformance/brand-runtime"; export function withSpan( tracer: ITracer, opts: SpanOpts | ((args: Args) => SpanOpts), fn: ((...args: Args) => Promise) & Extra, ): Instrumented<((...args: Args) => Promise) & Extra>; export function withSpan( tracer: ITracer, opts: SpanOpts | ((args: Args) => SpanOpts), fn: (...args: Args) => Promise, ): Instrumented<(...args: Args) => Promise>; export function withSpan( tracer: ITracer, opts: SpanOpts | ((args: Args) => SpanOpts), fn: (...args: Args) => Promise, ): Instrumented<(...args: Args) => Promise> { const wrapped: (...args: Args) => Promise = (...args) => { const resolved = typeof opts === "function" ? opts(args) : opts; return tracer.startSpan(resolved, () => fn(...args)); }; attachBrand(wrapped, "__instrumented"); // Cast is the type-level concession — the brand is now also a non-enumerable // runtime property attached above by `attachBrand`. return wrapped as Instrumented<(...args: Args) => Promise>; }