1import * as appsignals from "@distilled.cloud/aws/application-signals";
2import * as Effect from "effect/Effect";
3import * as Provider from "../../Provider.ts";
4import { Resource } from "../../Resource.ts";
5import { AWSEnvironment } from "../Environment.ts";
6import type { Providers } from "../Providers.ts";
7
8export interface DiscoveryProps {}
9
10export interface Discovery extends Resource<
11 "AWS.ApplicationSignals.Discovery",
12 DiscoveryProps,
13 {
14 /**
15 * The AWS account in which Application Signals discovery was enabled.
16 */
17 accountId: string;
18 /**
19 * The region in which Application Signals discovery was enabled.
20 */
21 region: string;
22 },
23 never,
24 Providers
25> {}
26
27/**
28 * Enables CloudWatch Application Signals for this account by creating the
29 * `AWSServiceRoleForCloudWatchApplicationSignals` service-linked role and the
30 * service-linked CloudTrail event channel used for change-event correlation
31 * (mirrors CloudFormation's `AWS::ApplicationSignals::Discovery`).
32 *
33 * `StartDiscovery` is idempotent, and AWS provides no API to disable
34 * discovery or observe its enablement, so this resource is
35 * provision-only: deleting it from the stack leaves discovery enabled
36 * (the delete is a no-op, matching CloudFormation's behavior).
37 *
38 * ### Enabling Application Signals
39 * **Example:** Enable Discovery for the Account
40 * ```typescript
41 * import * as AWS from "alchemy/AWS";
42 *
43 * const discovery = yield* AWS.ApplicationSignals.Discovery("Discovery", {});
44 * ```
45 *
46 * @resource
47 */
48export const Discovery = Resource<Discovery>(
49 "AWS.ApplicationSignals.Discovery",
50);
51
52export const DiscoveryProvider = () =>
53 Provider.effect(
54 Discovery,
55 Effect.gen(function* () {
56 return {
57 stables: ["accountId", "region"],
58
59 read: Effect.fn(function* ({ output }) {
60 // There is no API to observe whether discovery is enabled — echo
61 // the recorded state; a lost state falls through to a (harmless,
62 // idempotent) re-enable on the next reconcile.
63 return output;
64 }),
65
66 reconcile: Effect.fn(function* ({ session }) {
67 const { accountId, region } = yield* AWSEnvironment.current;
68 // StartDiscovery is idempotent: re-enabling an already-enabled
69 // account succeeds without side effects.
70 yield* appsignals.startDiscovery({});
71 yield* session.note(`application-signals discovery ${accountId}`);
72 return { accountId, region };
73 }),
74
75 delete: Effect.fn(function* () {
76 // Discovery cannot be disabled via API — deletion is a no-op
77 // (CloudFormation's AWS::ApplicationSignals::Discovery behaves the
78 // same way).
79 }),
80
81 list: () => Effect.succeed([]),
82 };
83 }),
84 );