1import * as machines from "@distilled.cloud/fly-io/machines";
2import * as Effect from "effect/Effect";
3import * as Layer from "effect/Layer";
4import * as Redacted from "effect/Redacted";
5import * as FetchHttpClient from "effect/http/FetchHttpClient";
6import { CredentialsFromAmbientOrEnv } from "./Credentials.ts";
7import { Decrypt, type DecryptRequest } from "./Decrypt.ts";
8import { unwrapSecretValue } from "./SecretHttp.ts";
9import {
10 base64ToBytes,
11 bytesToBase64,
12 makeHttpSecretKeyBinding,
13} from "./SecretKeyHttp.ts";
14
15/**
16 * HTTP implementation of {@link Decrypt}. Provide it on the
17 * {@link Service} or Action Effect.
18 *
19 *
20 * ### Provide the layer
21 * **Example:** On a Service
22 * ```typescript
23 * Effect.gen(function* () {
24 * const decrypt = yield* Fly.Decrypt(Box);
25 * // ...
26 * }).pipe(Effect.provide(Fly.DecryptHttp))
27 * ```
28 *
29 * @layer
30 * @product Secret Key
31 * @provides Fly.Decrypt
32 */
33export const DecryptHttp = Layer.effect(
34 Decrypt,
35 Effect.suspend(() =>
36 makeHttpSecretKeyBinding({
37 makeClient: (auth, appName, secretName) =>
38 Effect.fn("Fly.Decrypt")(function* (request: DecryptRequest) {
39 const res = yield* auth.authorize(
40 machines.decryptSecretKey({
41 app_name: yield* appName,
42 secret_name: yield* secretName,
43 ciphertext: bytesToBase64(request.ciphertext),
44 associated_data:
45 request.associatedData === undefined
46 ? undefined
47 : bytesToBase64(request.associatedData),
48 }),
49 );
50 return {
51 plaintext: Redacted.make(
52 base64ToBytes(unwrapSecretValue(res.plaintext ?? "")),
53 ),
54 };
55 }),
56 }),
57 ),
58).pipe(
59 Layer.provide(FetchHttpClient.layer),
60 Layer.provide(CredentialsFromAmbientOrEnv),
61);