diff --git a/packages/core-shared/src/instrumentation/with-span.test.ts b/packages/core-shared/src/instrumentation/with-span.test.ts index bb87a03..91ccac4 100644 --- a/packages/core-shared/src/instrumentation/with-span.test.ts +++ b/packages/core-shared/src/instrumentation/with-span.test.ts @@ -1,6 +1,7 @@ -import { describe, it, expect, vi } from "vitest"; +import { describe, it, expect, expectTypeOf, vi } from "vitest"; import { withSpan } from "@/instrumentation/with-span"; import type { ITracer, ISpan, SpanOpts } from "@/instrumentation/tracer.interface"; +import type { Instrumented } from "@/conformance/brands"; function makeRecordingTracer() { const calls: SpanOpts[] = []; @@ -60,3 +61,12 @@ describe("withSpan", () => { expect(calls.every((c) => c.name === "test.same")).toBe(true); }); }); + +describe("withSpan — brand", () => { + it("returns an Instrumented", () => { + const { tracer } = makeRecordingTracer(); + const fn = async (a: number) => a + 1; + const wrapped = withSpan(tracer, { name: "test.brand", op: "use-case" }, fn); + expectTypeOf(wrapped).toMatchTypeOf>(); + }); +}); diff --git a/packages/core-shared/src/instrumentation/with-span.ts b/packages/core-shared/src/instrumentation/with-span.ts index 5867660..eeb6b09 100644 --- a/packages/core-shared/src/instrumentation/with-span.ts +++ b/packages/core-shared/src/instrumentation/with-span.ts @@ -1,12 +1,16 @@ import type { ITracer, SpanOpts } from "./tracer.interface"; +import type { Instrumented } from "../conformance/brands"; export function withSpan( tracer: ITracer, opts: SpanOpts | ((args: Args) => SpanOpts), fn: (...args: Args) => Promise, -): (...args: Args) => Promise { - return (...args) => { +): Instrumented<(...args: Args) => Promise> { + const wrapped: (...args: Args) => Promise = (...args) => { const resolved = typeof opts === "function" ? opts(args) : opts; return tracer.startSpan(resolved, () => fn(...args)); }; + // Cast is the only runtime concession — the brand is a phantom type; + // there is no real `__instrumented` property at runtime. + return wrapped as Instrumented<(...args: Args) => Promise>; }