← ClaudeAtlas

effect-client-wrapperlisted

Pattern for wrapping third-party SDK clients (Stripe, Resend, AWS, etc.) with Effect. Use when creating Effect services that wrap external libraries with Promise-based APIs. Provides type-safe error handling, automatic tracing, and clean dependency injection via the "use" pattern.
Mark-Life/agent-task-manager · ★ 0 · AI & Automation · score 62
Install: claude install-skill Mark-Life/agent-task-manager
# Effect Client Wrapper Pattern Wrap third-party SDK clients with Effect using the "use" pattern for consistent error handling, tracing, and dependency injection. ## Pattern Structure ```typescript import { Context, Data, Effect, Layer, Config, Redacted } from "effect"; // 1. Define tagged errors export class MyClientError extends Data.TaggedError("MyClientError")<{ cause: unknown; }> {} export class MyClientInstantiationError extends Data.TaggedError( "MyClientInstantiationError" )<{ cause: unknown; }> {} // 2. Define service interface with `use` method export type IMyClient = Readonly<{ client: ThirdPartyClient; use: <A>( fn: (client: ThirdPartyClient) => Promise<A> ) => Effect.Effect<A, MyClientError, never>; }>; // 3. Create the service implementation const make = Effect.gen(function* () { const apiKey = yield* Config.redacted("MY_CLIENT_API_KEY"); const client = yield* Effect.try({ try: () => new ThirdPartyClient(Redacted.value(apiKey)), catch: (cause) => new MyClientInstantiationError({ cause }), }); const use = <A>(fn: (client: ThirdPartyClient) => Promise<A>) => Effect.tryPromise({ try: () => fn(client), catch: (cause) => new MyClientError({ cause }), }).pipe(Effect.withSpan(`my_client.${fn.name ?? "use"}`)); return { client, use }; }); // 4. Export as Context.Tag with Default layer export class MyClient extends Context.Tag("MyClient")<MyClient, IMyClient>() { static Default = Layer.effect(this, make).