1import {
2 getEnv,
3 getEnvRedacted,
4 getEnvRedactedRequired,
5 getEnvRequired,
6 mapPromptCancellation,
7} from "@/Auth/Env.ts";
8import { AuthError } from "@/Auth/AuthProvider.ts";
9import { TerminalCancelled } from "@/Cli/CliKit/index.ts";
10import { expect, it } from "alchemy-test";
11import * as ConfigProvider from "effect/ConfigProvider";
12import * as Effect from "effect/Effect";
13import * as Redacted from "effect/Redacted";
14
15const provideConfig = (values: Record<string, unknown>) =>
16 Effect.provideService(
17 ConfigProvider.ConfigProvider,
18 ConfigProvider.fromUnknown(values),
19 );
20
21it.effect(
22 "reads optional environment configuration",
23 () =>
24 Effect.gen(function* () {
25 expect(yield* getEnv("PRESENT")).toBe("value");
26 expect(yield* getEnv("MISSING")).toBeUndefined();
27 }).pipe(provideConfig({ PRESENT: "value" })),
28 { tags: ["unit", "local"] },
29);
30
31it.effect(
32 "preserves the configuration error as the cause of AuthError",
33 () =>
34 getEnvRequired("MISSING").pipe(
35 Effect.flip,
36 Effect.tap((error) =>
37 Effect.sync(() => {
38 expect(error).toBeInstanceOf(AuthError);
39 expect(error.message).toBe("Missing required env: MISSING");
40 expect(error.cause).toBeDefined();
41 }),
42 ),
43 provideConfig({}),
44 ),
45 { tags: ["unit", "local"] },
46);
47
48it.effect(
49 "handles optional and required redacted configuration",
50 () =>
51 Effect.gen(function* () {
52 const present = yield* getEnvRedactedRequired("SECRET");
53 expect(Redacted.value(present)).toBe("secret");
54 expect(yield* getEnvRedacted("MISSING")).toBeUndefined();
55 }).pipe(provideConfig({ SECRET: "secret" })),
56 { tags: ["unit", "local"] },
57);
58
59it.effect(
60 "maps prompt cancellation without retrying the prompt",
61 () =>
62 Effect.gen(function* () {
63 let attempts = 0;
64 const error = yield* mapPromptCancellation(
65 Effect.suspend(() => {
66 attempts++;
67 return Effect.fail(new TerminalCancelled());
68 }),
69 ).pipe(Effect.flip);
70
71 expect(attempts).toBe(1);
72 expect(error).toBeInstanceOf(AuthError);
73 expect(error.cause).toBeInstanceOf(TerminalCancelled);
74 }),
75 { tags: ["unit", "local"] },
76);