1import * as Effect from "effect/Effect";
2
3/**
4 * Shared scaffolding for Cognito's grouped HTTP bindings.
5 *
6 * NOT exported from `index.ts`. Unlike services whose capabilities are one
7 * operation per `Binding.Service`, Cognito's runtime bindings are grouped
8 * clients (`UserPoolAuth`, `UserPoolAdmin`, `IdentityPoolAuth`,
9 * `IdentityPoolAdmin`) — many operations sharing one bound resource. The
10 * boilerplate factored here is the per-method wrapper: a traced `Effect.fn`
11 * named `{binding}.{method}({logicalId})` that injects the bound resource's
12 * resolved identifier (`UserPoolId` / `ClientId` / `IdentityPoolId`) into
13 * every request before calling the distilled operation.
14 */
15export const cognitoMethods = (bindingId: string, logicalId: string) => ({
16 /**
17 * Build a client method that merges the resolved identifier field(s) in
18 * `inject` into every request. The exposed request type is the distilled
19 * request with the injected keys omitted.
20 */
21 injecting:
22 <I extends object>(inject: Effect.Effect<I>) =>
23 <A extends I, O, E>(
24 name: string,
25 op: (input: A) => Effect.Effect<O, E>,
26 ): ((request: Omit<A, keyof I>) => Effect.Effect<O, E>) =>
27 Effect.fn(`${bindingId}.${name}(${logicalId})`)(function* (
28 request: Omit<A, keyof I>,
29 ) {
30 return yield* op({ ...request, ...(yield* inject) } as unknown as A);
31 }),
32
33 /** Build a client method that passes the request through unchanged
34 * (operations authorized purely by an access token in the request). */
35 plain: <A, O, E>(
36 name: string,
37 op: (input: A) => Effect.Effect<O, E>,
38 ): ((request: A) => Effect.Effect<O, E>) =>
39 Effect.fn(`${bindingId}.${name}(${logicalId})`)(function* (request: A) {
40 return yield* op(request);
41 }),
42});