1import * as ses from "@distilled.cloud/aws/ses";
2import * as Effect from "effect/Effect";
3import * as Provider from "../../Provider.ts";
4import { Resource } from "../../Resource.ts";
5import type { Providers } from "../Providers.ts";
6
7export interface ActiveReceiptRuleSetProps {
8 /**
9 * Name of the receipt rule set to make active for the account in the current
10 * region. Typically the `ruleSetName` output of a `SES.ReceiptRuleSet`.
11 * Re-pointing to a different rule set updates the active pointer in place.
12 */
13 ruleSetName: string;
14}
15
16export interface ActiveReceiptRuleSet extends Resource<
17 "AWS.SES.ActiveReceiptRuleSet",
18 ActiveReceiptRuleSetProps,
19 {
20 /** Name of the rule set that is active for the account. */
21 ruleSetName: string;
22 },
23 never,
24 Providers
25> {}
26
27/**
28 * The account's active Amazon SES receipt rule set — the single rule set (per
29 * account, per region) that SES actually evaluates against inbound mail.
30 *
31 * This is an account-level singleton pointer, not a container: only one rule
32 * set can be active at a time. Deleting this resource deactivates email
33 * receiving (clears the pointer) only when the account is still pointed at the
34 * rule set this resource set; if something else has since become active, the
35 * delete is a no-op.
36 * ### Activating a Rule Set
37 * **Example:** Make a Rule Set Active
38 * ```typescript
39 * import * as SES from "alchemy/AWS/SES";
40 *
41 * const ruleSet = yield* SES.ReceiptRuleSet("Inbound", {});
42 * const active = yield* SES.ActiveReceiptRuleSet("Active", {
43 * ruleSetName: ruleSet.ruleSetName,
44 * });
45 * ```
46 *
47 * @resource
48 */
49export const ActiveReceiptRuleSet = Resource<ActiveReceiptRuleSet>(
50 "AWS.SES.ActiveReceiptRuleSet",
51);
52
53const activeRuleSetName = Effect.fn(function* () {
54 const response = yield* ses.describeActiveReceiptRuleSet({});
55 return response.Metadata?.Name;
56});
57
58export const ActiveReceiptRuleSetProvider = () =>
59 Provider.succeed(ActiveReceiptRuleSet, {
60 // Account/region singleton setting: "deleting" it only clears the active
61 // pointer, so nuke skips it (and would otherwise disable email receiving
62 // account-wide).
63 nuke: { singleton: true },
64
65 list: () => Effect.succeed([]),
66
67 read: Effect.fn(function* () {
68 const name = yield* activeRuleSetName();
69 return name ? { ruleSetName: name } : undefined;
70 }),
71
72 reconcile: Effect.fn(function* ({ news }) {
73 // OBSERVE the current active pointer; only re-point on a mismatch.
74 const observed = yield* activeRuleSetName();
75 if (observed !== news.ruleSetName) {
76 yield* ses.setActiveReceiptRuleSet({ RuleSetName: news.ruleSetName });
77 }
78 return { ruleSetName: news.ruleSetName };
79 }),
80
81 delete: Effect.fn(function* ({ output }) {
82 // Only deactivate if the account is still pointed at the rule set we
83 // activated; otherwise another owner has taken over and we leave it be.
84 const observed = yield* activeRuleSetName();
85 if (observed === output.ruleSetName) {
86 yield* ses.setActiveReceiptRuleSet({});
87 }
88 }),
89 });