1import * as Effect from "effect/Effect";
2import { routeCacheLayer } from "../../Alchemist/Session.ts";
3import { recordCli } from "../../Telemetry/Metrics.ts";
4
5/**
6 * Wraps a command handler as one traced, metered unit that is also one
7 * route-cache scope: the stack sessions and auth registries its routes open
8 * are memoized for the command's duration (`routeCacheLayer`). Commands that
9 * never open a session (`dev`, which only supervises the exec child) stay
10 * off this wrapper and therefore never load `Alchemist/Session`.
11 */
12export const instrumentCommand =
13 <AttrsArgs = unknown>(
14 command: string,
15 attrs?: (args: AttrsArgs) => Record<string, unknown>,
16 ) =>
17 <Args extends AttrsArgs, A, E, R>(
18 handler: (args: Args) => Effect.Effect<A, E, R>,
19 ): ((args: Args) => Effect.Effect<A, E, R>) =>
20 (args) =>
21 handler(args).pipe(
22 Effect.withSpan(`cli.${command}`, {
23 attributes: attrs ? attrs(args) : {},
24 }),
25 recordCli(command),
26 Effect.provide(routeCacheLayer),
27 );