| 1 | import * as Effect from "effect/Effect"; |
| 2 | import * as Layer from "effect/Layer"; |
| 3 | import * as Binding from "../../Binding.ts"; |
| 4 | import * as Output from "../../Output.ts"; |
| 5 | import { unpackEnvValue } from "../../RuntimeContext.ts"; |
| 6 | import { isBindingHost } from "../Lambda/Function.ts"; |
| 7 | import { |
| 8 | ConnectReplicationGroup, |
| 9 | replicationGroupConnectEnvPrefix, |
| 10 | type ConnectReplicationGroupOptions, |
| 11 | } from "./ConnectReplicationGroup.ts"; |
| 12 | import type { ReplicationGroup } from "./ReplicationGroup.ts"; |
| 13 | |
| 14 | export const ConnectReplicationGroupHttp = Layer.effect( |
| 15 | ConnectReplicationGroup, |
| 16 | Effect.gen(function* () { |
| 17 | return Effect.fn(function* ( |
| 18 | group: ReplicationGroup, |
| 19 | options?: ConnectReplicationGroupOptions, |
| 20 | ) { |
| 21 | const prefix = replicationGroupConnectEnvPrefix(group.LogicalId); |
| 22 | // Outputs yield a deferred runtime effect. Keep the Output expressions |
| 23 | // for deploy-time bindings, where Apply resolves them before Lambda's |
| 24 | // API call, and use the deferred values only in the runtime closure. |
| 25 | const configurationHost = group.configurationEndpointAddress; |
| 26 | const primaryHost = group.primaryEndpointAddress; |
| 27 | const configurationPort = group.configurationEndpointPort; |
| 28 | const primaryPort = group.primaryEndpointPort; |
| 29 | const endpointHost = Output.flatMap(configurationHost, (host) => |
| 30 | host === undefined ? primaryHost : Output.asOutput(host), |
| 31 | ); |
| 32 | const endpointPort = Output.flatMap(configurationPort, (port) => |
| 33 | port === undefined ? primaryPort : Output.asOutput(port), |
| 34 | ); |
| 35 | const readerHost = Output.map( |
| 36 | group.readerEndpointAddress, |
| 37 | (host) => host ?? "", |
| 38 | ); |
| 39 | const readerPort = Output.map(group.readerEndpointPort, (port) => |
| 40 | port === undefined ? "" : String(port), |
| 41 | ); |
| 42 | if (!globalThis.__ALCHEMY_RUNTIME__) { |
| 43 | const host = yield* Binding.Host; |
| 44 | if (isBindingHost(host)) { |
| 45 | yield* host.bind`Allow(${host}, AWS.ElastiCache.ConnectReplicationGroup(${group}))`( |
| 46 | { |
| 47 | env: { |
| 48 | [`${prefix}_HOST`]: endpointHost, |
| 49 | [`${prefix}_PORT`]: Output.interpolate`${endpointPort}`, |
| 50 | [`${prefix}_TLS`]: Output.map( |
| 51 | group.transitEncryptionEnabled, |
| 52 | String, |
| 53 | ), |
| 54 | [`${prefix}_READER_HOST`]: readerHost, |
| 55 | [`${prefix}_READER_PORT`]: readerPort, |
| 56 | }, |
| 57 | ...(options?.subnetIds || options?.securityGroupIds |
| 58 | ? { |
| 59 | vpc: { |
| 60 | subnetIds: options?.subnetIds ?? [], |
| 61 | securityGroupIds: options?.securityGroupIds ?? [], |
| 62 | }, |
| 63 | } |
| 64 | : {}), |
| 65 | }, |
| 66 | ); |
| 67 | } |
| 68 | } |
| 69 | return Effect.gen(function* () { |
| 70 | const host = unpackEnvValue<string>(process.env[`${prefix}_HOST`]); |
| 71 | if (host !== undefined) { |
| 72 | const port = unpackEnvValue<number>(process.env[`${prefix}_PORT`]); |
| 73 | const tls = unpackEnvValue<boolean>(process.env[`${prefix}_TLS`]); |
| 74 | const readerHost = unpackEnvValue<string>( |
| 75 | process.env[`${prefix}_READER_HOST`], |
| 76 | ); |
| 77 | const readerPort = unpackEnvValue<number>( |
| 78 | process.env[`${prefix}_READER_PORT`], |
| 79 | ); |
| 80 | if (!host || port === undefined) { |
| 81 | return yield* Effect.die( |
| 82 | `ElastiCache endpoint for '${group.LogicalId}' is not available`, |
| 83 | ); |
| 84 | } |
| 85 | return { |
| 86 | host, |
| 87 | port, |
| 88 | readerHost: readerHost || undefined, |
| 89 | readerPort: readerHost ? readerPort : undefined, |
| 90 | tls: tls ?? true, |
| 91 | }; |
| 92 | } |
| 93 | const endpoint = yield* yield* endpointHost; |
| 94 | const port = yield* yield* endpointPort; |
| 95 | if (!endpoint || port === undefined) { |
| 96 | return yield* Effect.die( |
| 97 | `ElastiCache endpoint for '${group.LogicalId}' is not available yet`, |
| 98 | ); |
| 99 | } |
| 100 | return { |
| 101 | host: endpoint, |
| 102 | port, |
| 103 | readerHost: yield* yield* group.readerEndpointAddress, |
| 104 | readerPort: yield* yield* group.readerEndpointPort, |
| 105 | tls: yield* yield* group.transitEncryptionEnabled, |
| 106 | }; |
| 107 | }); |
| 108 | }); |
| 109 | }), |
| 110 | ); |