@fjall/components-infrastructure 0.95.0 → 0.99.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/dist/lib/app.d.ts +90 -107
  2. package/dist/lib/app.js +149 -139
  3. package/dist/lib/config/aws/__t17fixture.d.ts +1 -0
  4. package/dist/lib/config/aws/__t17fixture.js +3 -0
  5. package/dist/lib/config/aws/__t17fixtureType.d.ts +2 -0
  6. package/dist/lib/config/aws/__t17fixtureType.js +1 -0
  7. package/dist/lib/config/aws/alarmTopic.js +8 -4
  8. package/dist/lib/config/aws/cloudTrail.js +1 -1
  9. package/dist/lib/config/aws/disasterRecovery.js +11 -16
  10. package/dist/lib/config/aws/ecrDefaultImage.d.ts +0 -1
  11. package/dist/lib/config/aws/ecrDefaultImage.js +13 -23
  12. package/dist/lib/config/aws/identityCenter.d.ts +10 -3
  13. package/dist/lib/config/aws/identityCenter.js +101 -37
  14. package/dist/lib/config/aws/identityCenterGroupMembership.js +8 -2
  15. package/dist/lib/config/aws/identityCenterMembership.d.ts +11 -0
  16. package/dist/lib/config/aws/identityCenterMembership.js +61 -0
  17. package/dist/lib/config/aws/index.d.ts +1 -1
  18. package/dist/lib/config/aws/index.js +1 -1
  19. package/dist/lib/config/aws/ipam.js +6 -11
  20. package/dist/lib/config/aws/oidcConnector.js +5 -1
  21. package/dist/lib/config/aws/scpPreset.js +4 -1
  22. package/dist/lib/patterns/aws/_eslint_test_tmp/leak.d.ts +1 -0
  23. package/dist/lib/patterns/aws/_eslint_test_tmp/leak.js +4 -0
  24. package/dist/lib/patterns/aws/account.js +7 -8
  25. package/dist/lib/patterns/aws/apexDomainPattern.js +10 -10
  26. package/dist/lib/patterns/aws/bastionFactory.d.ts +10 -0
  27. package/dist/lib/patterns/aws/bastionFactory.js +29 -0
  28. package/dist/lib/patterns/aws/buildkite.d.ts +2 -2
  29. package/dist/lib/patterns/aws/buildkite.js +51 -97
  30. package/dist/lib/patterns/aws/cdn.js +1 -1
  31. package/dist/lib/patterns/aws/clickhouseDatabase.d.ts +172 -0
  32. package/dist/lib/patterns/aws/clickhouseDatabase.js +600 -0
  33. package/dist/lib/patterns/aws/compute.d.ts +4 -6
  34. package/dist/lib/patterns/aws/compute.js +7 -13
  35. package/dist/lib/patterns/aws/computeEcs.d.ts +95 -396
  36. package/dist/lib/patterns/aws/computeEcs.js +880 -46
  37. package/dist/lib/patterns/aws/computeEcsTypes.d.ts +889 -0
  38. package/dist/lib/patterns/aws/computeEcsTypes.js +12 -0
  39. package/dist/lib/patterns/aws/computeLambda.d.ts +0 -5
  40. package/dist/lib/patterns/aws/computeLambda.js +1 -2
  41. package/dist/lib/patterns/aws/database.d.ts +50 -8
  42. package/dist/lib/patterns/aws/database.js +183 -27
  43. package/dist/lib/patterns/aws/domain.js +8 -7
  44. package/dist/lib/patterns/aws/index.d.ts +3 -0
  45. package/dist/lib/patterns/aws/index.js +3 -0
  46. package/dist/lib/patterns/aws/interfaces/compute.d.ts +13 -1
  47. package/dist/lib/patterns/aws/interfaces/connector.d.ts +1 -1
  48. package/dist/lib/patterns/aws/interfaces/connector.js +1 -1
  49. package/dist/lib/patterns/aws/interfaces/database.d.ts +187 -8
  50. package/dist/lib/patterns/aws/interfaces/database.js +17 -3
  51. package/dist/lib/patterns/aws/interfaces/index.d.ts +4 -2
  52. package/dist/lib/patterns/aws/interfaces/index.js +4 -2
  53. package/dist/lib/patterns/aws/interfaces/messaging.d.ts +7 -0
  54. package/dist/lib/patterns/aws/interfaces/migrationContributor.d.ts +47 -0
  55. package/dist/lib/patterns/aws/interfaces/migrationContributor.js +9 -0
  56. package/dist/lib/patterns/aws/interfaces/vpcPeer.d.ts +7 -0
  57. package/dist/lib/patterns/aws/interfaces/vpcPeer.js +1 -0
  58. package/dist/lib/patterns/aws/messaging.d.ts +66 -10
  59. package/dist/lib/patterns/aws/messaging.js +115 -20
  60. package/dist/lib/patterns/aws/network.js +16 -7
  61. package/dist/lib/patterns/aws/organisation.d.ts +4 -0
  62. package/dist/lib/patterns/aws/organisation.js +24 -5
  63. package/dist/lib/patterns/aws/storage.d.ts +1 -2
  64. package/dist/lib/patterns/aws/storage.js +3 -2
  65. package/dist/lib/patterns/aws/vpcPeer.d.ts +34 -0
  66. package/dist/lib/patterns/aws/vpcPeer.js +38 -0
  67. package/dist/lib/patterns/aws/vpcPeerAccepter.d.ts +29 -0
  68. package/dist/lib/patterns/aws/vpcPeerAccepter.js +196 -0
  69. package/dist/lib/resources/aws/analytics/clickhouse.js +25 -7
  70. package/dist/lib/resources/aws/analytics/clickhouseAlarms.d.ts +49 -0
  71. package/dist/lib/resources/aws/analytics/clickhouseAlarms.js +140 -0
  72. package/dist/lib/resources/aws/analytics/clickhouseConstants.d.ts +4 -4
  73. package/dist/lib/resources/aws/analytics/clickhouseConstants.js +6 -4
  74. package/dist/lib/resources/aws/analytics/clickhouseTypes.d.ts +12 -0
  75. package/dist/lib/resources/aws/analytics/clickhouseUserData.d.ts +1 -0
  76. package/dist/lib/resources/aws/analytics/clickhouseUserData.js +56 -5
  77. package/dist/lib/resources/aws/analytics/index.d.ts +2 -0
  78. package/dist/lib/resources/aws/analytics/index.js +1 -0
  79. package/dist/lib/resources/aws/base/awsStack.js +4 -2
  80. package/dist/lib/resources/aws/compute/__tmp__/regression-shape.d.ts +2 -0
  81. package/dist/lib/resources/aws/compute/__tmp__/regression-shape.js +11 -0
  82. package/dist/lib/resources/aws/compute/asgInlineLifecycleHook.d.ts +52 -0
  83. package/dist/lib/resources/aws/compute/asgInlineLifecycleHook.js +60 -0
  84. package/dist/lib/resources/aws/compute/blockDeviceVolume.d.ts +8 -0
  85. package/dist/lib/resources/aws/compute/blockDeviceVolume.js +10 -0
  86. package/dist/lib/resources/aws/compute/ec2.d.ts +132 -12
  87. package/dist/lib/resources/aws/compute/ec2.js +163 -23
  88. package/dist/lib/resources/aws/compute/ec2GracefulTerminationHandler.d.ts +41 -0
  89. package/dist/lib/resources/aws/compute/ec2GracefulTerminationHandler.js +194 -0
  90. package/dist/lib/resources/aws/compute/ec2GracefulTerminationLambda.source.cjs +458 -0
  91. package/dist/lib/resources/aws/compute/ecs.d.ts +27 -1
  92. package/dist/lib/resources/aws/compute/ecs.js +42 -2
  93. package/dist/lib/resources/aws/compute/ecsConstants.d.ts +9 -0
  94. package/dist/lib/resources/aws/compute/ecsConstants.js +16 -0
  95. package/dist/lib/resources/aws/compute/ecsImages.js +32 -20
  96. package/dist/lib/resources/aws/compute/ecsLifecycleHookMigration.d.ts +96 -0
  97. package/dist/lib/resources/aws/compute/ecsLifecycleHookMigration.js +113 -0
  98. package/dist/lib/resources/aws/compute/ecsNetworking.d.ts +2 -1
  99. package/dist/lib/resources/aws/compute/ecsNetworking.js +18 -6
  100. package/dist/lib/resources/aws/compute/ecsRemoteConnections.d.ts +38 -0
  101. package/dist/lib/resources/aws/compute/ecsRemoteConnections.js +80 -0
  102. package/dist/lib/resources/aws/compute/ecsServiceFactory.d.ts +13 -4
  103. package/dist/lib/resources/aws/compute/ecsServiceFactory.js +155 -33
  104. package/dist/lib/resources/aws/compute/ecsTaskDefinition.d.ts +31 -1
  105. package/dist/lib/resources/aws/compute/ecsTaskDefinition.js +110 -6
  106. package/dist/lib/resources/aws/compute/ecsTypes.d.ts +180 -13
  107. package/dist/lib/resources/aws/compute/ecsValidation.d.ts +9 -0
  108. package/dist/lib/resources/aws/compute/ecsValidation.js +63 -0
  109. package/dist/lib/resources/aws/compute/index.d.ts +2 -0
  110. package/dist/lib/resources/aws/compute/index.js +2 -0
  111. package/dist/lib/resources/aws/compute/lambda.d.ts +7 -13
  112. package/dist/lib/resources/aws/compute/lambda.js +30 -38
  113. package/dist/lib/resources/aws/compute/lifecycleHookLambda.source.cjs +192 -0
  114. package/dist/lib/resources/aws/compute/persistentDataVolume.d.ts +104 -0
  115. package/dist/lib/resources/aws/compute/persistentDataVolume.js +245 -0
  116. package/dist/lib/resources/aws/compute/persistentDataVolumeLambda.source.cjs +398 -0
  117. package/dist/lib/resources/aws/compute/samApplication.d.ts +15 -0
  118. package/dist/lib/resources/aws/compute/samApplication.js +27 -0
  119. package/dist/lib/resources/aws/database/clickhouseConstants.d.ts +159 -0
  120. package/dist/lib/resources/aws/database/clickhouseConstants.js +181 -0
  121. package/dist/lib/resources/aws/database/clickhouseSchemas.d.ts +71 -0
  122. package/dist/lib/resources/aws/database/clickhouseSchemas.js +157 -0
  123. package/dist/lib/resources/aws/database/clickhouseSecurityGroup.d.ts +14 -0
  124. package/dist/lib/resources/aws/database/clickhouseSecurityGroup.js +23 -0
  125. package/dist/lib/resources/aws/database/clickhouseUserData.d.ts +69 -0
  126. package/dist/lib/resources/aws/database/clickhouseUserData.js +371 -0
  127. package/dist/lib/resources/aws/database/clickhouseXmlRenderer.d.ts +56 -0
  128. package/dist/lib/resources/aws/database/clickhouseXmlRenderer.js +112 -0
  129. package/dist/lib/resources/aws/database/rdsAurora.d.ts +8 -1
  130. package/dist/lib/resources/aws/database/rdsAurora.js +42 -32
  131. package/dist/lib/resources/aws/database/rdsAuroraGlobal.d.ts +15 -2
  132. package/dist/lib/resources/aws/database/rdsAuroraGlobal.js +39 -43
  133. package/dist/lib/resources/aws/database/rdsDefaults.d.ts +6 -0
  134. package/dist/lib/resources/aws/database/rdsDefaults.js +7 -1
  135. package/dist/lib/resources/aws/database/rdsHelpers.d.ts +3 -3
  136. package/dist/lib/resources/aws/database/rdsHelpers.js +1 -0
  137. package/dist/lib/resources/aws/database/rdsInstance.d.ts +8 -1
  138. package/dist/lib/resources/aws/database/rdsInstance.js +51 -34
  139. package/dist/lib/resources/aws/database/rdsProxyOutput.d.ts +1 -1
  140. package/dist/lib/resources/aws/database/rdsProxyOutput.js +1 -1
  141. package/dist/lib/resources/aws/iam/delegationRole.js +12 -5
  142. package/dist/lib/resources/aws/iam/identityCenter/groupMembership.d.ts +9 -0
  143. package/dist/lib/resources/aws/iam/identityCenter/groupMembership.js +12 -0
  144. package/dist/lib/resources/aws/iam/identityCenter/index.d.ts +1 -0
  145. package/dist/lib/resources/aws/iam/identityCenter/index.js +1 -0
  146. package/dist/lib/resources/aws/iam/identityCenter/permissionSet.d.ts +1 -0
  147. package/dist/lib/resources/aws/iam/identityCenter/permissionSet.js +1 -0
  148. package/dist/lib/resources/aws/logging/logGroup.d.ts +0 -8
  149. package/dist/lib/resources/aws/logging/logGroup.js +0 -11
  150. package/dist/lib/resources/aws/messaging/defaultEventBus.d.ts +7 -0
  151. package/dist/lib/resources/aws/messaging/defaultEventBus.js +21 -0
  152. package/dist/lib/resources/aws/messaging/eventBridgeRule.d.ts +96 -0
  153. package/dist/lib/resources/aws/messaging/eventBridgeRule.js +110 -0
  154. package/dist/lib/resources/aws/messaging/eventTargets.d.ts +84 -0
  155. package/dist/lib/resources/aws/messaging/eventTargets.js +152 -0
  156. package/dist/lib/resources/aws/messaging/eventbridge.d.ts +25 -2
  157. package/dist/lib/resources/aws/messaging/eventbridge.js +22 -10
  158. package/dist/lib/resources/aws/messaging/index.d.ts +5 -0
  159. package/dist/lib/resources/aws/messaging/index.js +2 -0
  160. package/dist/lib/resources/aws/messaging/schedule.d.ts +118 -0
  161. package/dist/lib/resources/aws/messaging/schedule.js +64 -0
  162. package/dist/lib/resources/aws/messaging/sns.d.ts +2 -1
  163. package/dist/lib/resources/aws/messaging/sqs.d.ts +2 -1
  164. package/dist/lib/resources/aws/messaging/subscription.d.ts +112 -0
  165. package/dist/lib/resources/aws/messaging/subscription.js +67 -0
  166. package/dist/lib/resources/aws/messaging/utils.d.ts +6 -0
  167. package/dist/lib/resources/aws/messaging/utils.js +10 -0
  168. package/dist/lib/resources/aws/monitoring/clickhouseAlarms.d.ts +60 -0
  169. package/dist/lib/resources/aws/monitoring/clickhouseAlarms.js +139 -0
  170. package/dist/lib/resources/aws/monitoring/index.d.ts +2 -0
  171. package/dist/lib/resources/aws/monitoring/index.js +2 -0
  172. package/dist/lib/resources/aws/monitoring/scheduleAlarms.d.ts +47 -0
  173. package/dist/lib/resources/aws/monitoring/scheduleAlarms.js +106 -0
  174. package/dist/lib/resources/aws/networking/crossAccountDelegationRecord.js +6 -3
  175. package/dist/lib/resources/aws/networking/crossAccountReturnRoutes.d.ts +40 -0
  176. package/dist/lib/resources/aws/networking/crossAccountReturnRoutes.js +158 -0
  177. package/dist/lib/resources/aws/networking/dnsRecord/dnsRecordBase.js +7 -4
  178. package/dist/lib/resources/aws/networking/domainCertificate.d.ts +2 -2
  179. package/dist/lib/resources/aws/networking/domainCertificate.js +6 -3
  180. package/dist/lib/resources/aws/networking/hostedZone.js +6 -4
  181. package/dist/lib/resources/aws/networking/index.d.ts +3 -0
  182. package/dist/lib/resources/aws/networking/index.js +3 -0
  183. package/dist/lib/resources/aws/networking/serviceDiscovery.d.ts +96 -0
  184. package/dist/lib/resources/aws/networking/serviceDiscovery.js +96 -0
  185. package/dist/lib/resources/aws/networking/vpc.d.ts +4 -1
  186. package/dist/lib/resources/aws/networking/vpc.js +10 -3
  187. package/dist/lib/resources/aws/networking/vpcPeeringAccepterRole.d.ts +18 -0
  188. package/dist/lib/resources/aws/networking/vpcPeeringAccepterRole.js +61 -0
  189. package/dist/lib/resources/aws/networking/vpcPeeringConnection.d.ts +49 -0
  190. package/dist/lib/resources/aws/networking/vpcPeeringConnection.js +106 -0
  191. package/dist/lib/resources/aws/organisation/costAllocationTagActivator.d.ts +16 -5
  192. package/dist/lib/resources/aws/organisation/costAllocationTagActivator.js +17 -3
  193. package/dist/lib/resources/aws/organisation/index.d.ts +1 -1
  194. package/dist/lib/resources/aws/organisation/organisationPolicy.d.ts +2 -0
  195. package/dist/lib/resources/aws/organisation/organisationPolicy.js +3 -2
  196. package/dist/lib/resources/aws/secrets/secret.d.ts +7 -0
  197. package/dist/lib/resources/aws/secrets/secret.js +4 -3
  198. package/dist/lib/resources/aws/storage/bucketDeployment.d.ts +16 -0
  199. package/dist/lib/resources/aws/storage/bucketDeployment.js +17 -0
  200. package/dist/lib/resources/aws/storage/ecr.js +5 -5
  201. package/dist/lib/resources/aws/storage/index.d.ts +1 -0
  202. package/dist/lib/resources/aws/storage/index.js +1 -0
  203. package/dist/lib/resources/aws/storage/s3.js +10 -3
  204. package/dist/lib/resources/aws/utilities/customResource.js +18 -9
  205. package/dist/lib/synth_dump.d.ts +1 -0
  206. package/dist/lib/synth_dump.js +42 -0
  207. package/dist/lib/utils/bastionFactory.d.ts +10 -0
  208. package/dist/lib/utils/bastionFactory.js +29 -0
  209. package/dist/lib/utils/capitaliseString.d.ts +1 -1
  210. package/dist/lib/utils/capitaliseString.js +1 -1
  211. package/dist/lib/utils/cdkContext.d.ts +10 -0
  212. package/dist/lib/utils/cdkContext.js +13 -0
  213. package/dist/lib/utils/connections.d.ts +7 -1
  214. package/dist/lib/utils/connections.js +21 -0
  215. package/dist/lib/utils/connector.d.ts +30 -2
  216. package/dist/lib/utils/connector.js +6 -1
  217. package/dist/lib/utils/costAllocationTags.d.ts +15 -0
  218. package/dist/lib/utils/costAllocationTags.js +16 -0
  219. package/dist/lib/utils/databaseTypes.d.ts +14 -0
  220. package/dist/lib/utils/getConfig.d.ts +2 -0
  221. package/dist/lib/utils/getConfig.js +2 -0
  222. package/dist/lib/utils/index.d.ts +4 -0
  223. package/dist/lib/utils/index.js +4 -0
  224. package/dist/lib/utils/manifestWriter.d.ts +6 -89
  225. package/dist/lib/utils/manifestWriter.js +36 -23
  226. package/dist/lib/utils/migrationVersionResolvers.d.ts +2 -0
  227. package/dist/lib/utils/migrationVersionResolvers.js +2 -0
  228. package/dist/lib/utils/orgConfigParser.js +2 -1
  229. package/dist/lib/utils/resolveAlertsTopic.d.ts +14 -0
  230. package/dist/lib/utils/resolveAlertsTopic.js +30 -0
  231. package/dist/lib/utils/validationLogger.js +6 -3
  232. package/dist/lib/utils/vpcPeerInterface.d.ts +22 -0
  233. package/dist/lib/utils/vpcPeerInterface.js +1 -0
  234. package/package.json +22 -18
@@ -19,10 +19,12 @@ export class RdsAurora extends Construct {
19
19
  databaseProxy;
20
20
  databaseCredentials;
21
21
  cfnCluster;
22
+ databaseNameValue;
22
23
  constructor(scope, id, props) {
23
24
  super(scope, id);
24
25
  this.constructId = id;
25
26
  this.port = props.port ?? RDS_DEFAULTS.DEFAULT_PORT;
27
+ this.databaseNameValue = props.databaseName ?? id;
26
28
  // PostgreSQL fallback for direct usage - ensure engine and engineConfig match
27
29
  this.engineConfig = props.engineConfig ?? DEFAULT_POSTGRES_ENGINE_CONFIG;
28
30
  const { piEnabled, piConfig } = resolveDatabaseInsights(props.databaseInsights);
@@ -32,13 +34,13 @@ export class RdsAurora extends Construct {
32
34
  : (props.credentials?.username ?? this.engineConfig.defaultUsername);
33
35
  // Global secondary clusters import replicated secret instead of creating new
34
36
  if (props.isGlobalSecondary) {
35
- this.databaseCredentials = new Secret(this, `${props.databaseName}Credentials`, {
37
+ this.databaseCredentials = new Secret(this, `${this.databaseNameValue}Credentials`, {
36
38
  secretName: ResourceNaming.credentialsSecretName(id),
37
39
  importExisting: true
38
40
  });
39
41
  }
40
42
  else {
41
- this.databaseCredentials = new Secret(this, `${props.databaseName}Credentials`, {
43
+ this.databaseCredentials = new Secret(this, `${this.databaseNameValue}Credentials`, {
42
44
  secretName: ResourceNaming.credentialsSecretName(id),
43
45
  generateSecretString: {
44
46
  secretStringTemplate: JSON.stringify({ username }),
@@ -49,11 +51,11 @@ export class RdsAurora extends Construct {
49
51
  replicaRegions: props.secretReplicaRegions
50
52
  });
51
53
  }
52
- const storageEncryptionKey = resolveStorageEncryptionKey(this, props.databaseName, props.encryption?.storageKey);
53
- const performanceInsightsKey = resolvePerformanceInsightsKey(this, props.databaseName, piEnabled, piConfig?.encryptionKey);
54
+ const storageEncryptionKey = resolveStorageEncryptionKey(this, this.databaseNameValue, props.encryption?.storageKey);
55
+ const performanceInsightsKey = resolvePerformanceInsightsKey(this, this.databaseNameValue, piEnabled, piConfig?.encryptionKey);
54
56
  const clusterSecurityGroup = new SecurityGroup(this, `${id}SecurityGroup`, {
55
57
  vpc: props.vpc,
56
- description: `Security group for Aurora cluster ${props.databaseName}`
58
+ description: `Security group for Aurora cluster ${this.databaseNameValue}`
57
59
  });
58
60
  clusterSecurityGroup.addIngressRule(clusterSecurityGroup, Port.tcp(this.port));
59
61
  // Allow VPC-wide access when enabled (avoids cross-stack cyclic dependencies)
@@ -73,8 +75,7 @@ export class RdsAurora extends Construct {
73
75
  const writerSuffix = writerConfig.identifierSuffix;
74
76
  const diMode = piConfig?.mode ?? "standard";
75
77
  const performanceInsightsRetention = getDatabaseInsightsRetention(diMode);
76
- const databaseName = props.databaseName || id;
77
- const writer = ClusterInstance.serverlessV2(`${databaseName}Writer`, {
78
+ const writer = ClusterInstance.serverlessV2(`${this.databaseNameValue}Writer`, {
78
79
  enablePerformanceInsights: writerPI,
79
80
  performanceInsightEncryptionKey: writerPI
80
81
  ? performanceInsightsKey
@@ -94,9 +95,9 @@ export class RdsAurora extends Construct {
94
95
  DatabaseClusterEngine.auroraPostgres({
95
96
  version: AuroraPostgresEngineVersion.of("16.6", "16")
96
97
  });
97
- const parameterGroup = new ParameterGroup(this, `${props.databaseName}ParameterGroup`, {
98
+ const parameterGroup = new ParameterGroup(this, `${this.databaseNameValue}ParameterGroup`, {
98
99
  engine,
99
- description: `Parameter group for ${props.databaseName} with security defaults`,
100
+ description: `Parameter group for ${this.databaseNameValue} with security defaults`,
100
101
  parameters: this.engineConfig.sslParameters
101
102
  });
102
103
  // Use public subnets when publicly accessible, otherwise private
@@ -110,12 +111,14 @@ export class RdsAurora extends Construct {
110
111
  securityGroups: [clusterSecurityGroup],
111
112
  engine,
112
113
  parameterGroup,
113
- backup: { retention: Duration.days(props.backupRetention ?? 14) },
114
+ backup: {
115
+ retention: Duration.days(props.backupRetention ?? RDS_DEFAULTS.BACKUP_RETENTION_DEFAULT_DAYS)
116
+ },
114
117
  storageEncrypted: true,
115
118
  ...(storageEncryptionKey && { storageEncryptionKey }),
116
119
  clusterIdentifier: props.clusterIdentifier?.toLowerCase() || ResourceNaming.clusterId(id),
117
- monitoringInterval: props.monitoringInterval || RDS_DEFAULTS.MONITORING_INTERVAL,
118
- preferredMaintenanceWindow: props.preferredMaintenanceWindow ||
120
+ monitoringInterval: props.monitoringInterval ?? RDS_DEFAULTS.MONITORING_INTERVAL,
121
+ preferredMaintenanceWindow: props.preferredMaintenanceWindow ??
119
122
  RDS_DEFAULTS.PREFERRED_MAINTENANCE_WINDOW,
120
123
  port: this.port,
121
124
  removalPolicy: RemovalPolicy.SNAPSHOT,
@@ -132,26 +135,21 @@ export class RdsAurora extends Construct {
132
135
  defaultDatabaseName: (props.databaseName || id.replace("Rds", "")).replace(/[^a-zA-Z0-9_]/g, "")
133
136
  };
134
137
  if (props.snapshotIdentifier) {
135
- // Create from snapshot - credentials need SnapshotCredentials type
136
- const snapshotCredentials = props.isGlobalSecondary
137
- ? {}
138
- : {
139
- credentials: SnapshotCredentials.fromSecret(this.databaseCredentials.secret)
140
- };
141
- this.databaseCluster = new DatabaseClusterFromSnapshot(this, `${id}Database`,
142
- // Type assertion: CDK's SnapshotCredentials.username is string | undefined
143
- // but DatabaseClusterFromSnapshotProps expects string. Works at runtime.
144
- {
138
+ const snapshotProps = {
145
139
  ...baseClusterProps,
146
- ...snapshotCredentials,
140
+ snapshotCredentials: props.isGlobalSecondary
141
+ ? undefined
142
+ : SnapshotCredentials.fromSecret(this.databaseCredentials.secret),
147
143
  snapshotIdentifier: props.snapshotIdentifier
148
- });
144
+ };
145
+ this.databaseCluster = new DatabaseClusterFromSnapshot(this, `${id}Database`, snapshotProps);
149
146
  }
150
147
  else {
151
- // Create new cluster
152
- this.databaseCluster = new DatabaseCluster(this, `${id}Database`,
153
- // Type assertion: spread types don't preserve required property narrowing
154
- { ...baseClusterProps, ...primaryClusterProps });
148
+ const clusterProps = {
149
+ ...baseClusterProps,
150
+ ...primaryClusterProps
151
+ };
152
+ this.databaseCluster = new DatabaseCluster(this, `${id}Database`, clusterProps);
155
153
  }
156
154
  this.cfnCluster = this.databaseCluster.node.defaultChild;
157
155
  // Global secondary clusters can't specify these properties
@@ -202,7 +200,7 @@ export class RdsAurora extends Construct {
202
200
  : defaultPIEnabled;
203
201
  return readerConfigs.map((config, index) => {
204
202
  const enablePI = config.enableDatabaseInsights ?? defaultPI;
205
- return ClusterInstance.serverlessV2(`${props.databaseName}Reader${index + 1}`, {
203
+ return ClusterInstance.serverlessV2(`${this.databaseNameValue}Reader${index + 1}`, {
206
204
  scaleWithWriter: config.scaleWithWriter ?? index === 0,
207
205
  enablePerformanceInsights: enablePI,
208
206
  performanceInsightEncryptionKey: enablePI ? piKey : undefined,
@@ -223,7 +221,7 @@ export class RdsAurora extends Construct {
223
221
  const vpcSubnets = proxyConfig.vpcSubnets ?? {
224
222
  subnetType: SubnetType.PRIVATE_WITH_EGRESS
225
223
  };
226
- this.databaseProxy = new DatabaseProxy(this, `${props.databaseName}DatabaseProxy`, {
224
+ this.databaseProxy = new DatabaseProxy(this, `${this.databaseNameValue}DatabaseProxy`, {
227
225
  dbProxyName: ResourceNaming.proxyName(this.constructId),
228
226
  proxyTarget: ProxyTarget.fromCluster(this.databaseCluster),
229
227
  secrets: [this.databaseCredentials.secret],
@@ -237,12 +235,12 @@ export class RdsAurora extends Construct {
237
235
  maxConnectionsPercent: proxyConfig.maxConnections,
238
236
  maxIdleConnectionsPercent: proxyConfig.maxIdleConnections
239
237
  });
240
- addProxyCfnOutput(this, this.constructId, props.databaseName, this.databaseProxy);
238
+ addProxyCfnOutput(this, this.constructId, this.databaseNameValue, this.databaseProxy);
241
239
  }
242
240
  addSecretRotation(props) {
243
241
  addMultiUserSecretRotation({
244
242
  scope: this,
245
- databaseName: props.databaseName,
243
+ databaseName: this.databaseNameValue,
246
244
  constructId: this.constructId,
247
245
  engineConfig: this.engineConfig,
248
246
  credentialsConfig: props.credentials,
@@ -264,6 +262,18 @@ export class RdsAurora extends Construct {
264
262
  getCredentials() {
265
263
  return this.databaseCredentials;
266
264
  }
265
+ getClusterIdentifier() {
266
+ return this.databaseCluster.clusterIdentifier;
267
+ }
268
+ getSnapshotTarget() {
269
+ return { kind: "cluster", arn: this.databaseCluster.clusterArn };
270
+ }
271
+ getDatabaseName() {
272
+ return this.databaseNameValue;
273
+ }
274
+ getConnectionString() {
275
+ return `${this.engineConfig.family}://${this.getHostEndpoint()}:${this.getHostPort()}/${this.getDatabaseName()}`;
276
+ }
267
277
  getCfnCluster() {
268
278
  return this.cfnCluster;
269
279
  }
@@ -2,8 +2,10 @@ import { type Duration } from "aws-cdk-lib";
2
2
  import { Construct } from "constructs";
3
3
  import { type IVpc, type Connections, type IConnectable } from "aws-cdk-lib/aws-ec2";
4
4
  import { type IClusterEngine } from "aws-cdk-lib/aws-rds";
5
+ import { type ITopic } from "aws-cdk-lib/aws-sns";
5
6
  import { type Secret } from "../secrets/index.js";
6
- import { type EngineConfig, type ProxyConfig, type CredentialsConfig, type AuroraEncryptionConfig, type AuroraWriterConfig, type AuroraReadersConfig, type DatabaseInsightsConfig } from "../../../utils/databaseTypes.js";
7
+ import { type RdsAlarmThresholds } from "../monitoring/index.js";
8
+ import { type EngineConfig, type ProxyConfig, type CredentialsConfig, type AuroraEncryptionConfig, type AuroraWriterConfig, type AuroraReadersConfig, type DatabaseInsightsConfig, type SnapshotTarget } from "../../../utils/databaseTypes.js";
7
9
  interface RdsAuroraGlobalProps {
8
10
  vpc: IVpc;
9
11
  databaseName: string;
@@ -49,6 +51,12 @@ interface RdsAuroraGlobalProps {
49
51
  snapshotIdentifier?: string;
50
52
  /** Username from the snapshot (required when restoring from snapshot to reset password) */
51
53
  snapshotUsername?: string;
54
+ /** SNS topic for alarm notifications. Required for alarm creation. */
55
+ alertsTopic?: ITopic;
56
+ /** Alarm thresholds. false to disable, undefined for defaults, object to override. */
57
+ alarms?: RdsAlarmThresholds | false;
58
+ /** Application ID for alarm tagging. */
59
+ applicationId?: string;
52
60
  }
53
61
  export declare class RdsAuroraGlobal extends Construct implements IConnectable {
54
62
  connections: Connections;
@@ -62,12 +70,17 @@ export declare class RdsAuroraGlobal extends Construct implements IConnectable {
62
70
  constructor(scope: Construct, id: string, props: RdsAuroraGlobalProps);
63
71
  getGlobalClusterIdentifier(): string;
64
72
  getPrimaryClusterIdentifier(): string;
65
- private getGlobalClusterEngineString;
66
73
  private addGlobalCluster;
67
74
  private addAuroraCluster;
68
75
  private addOutputs;
69
76
  getCredentials(): Secret;
70
77
  getHostEndpoint(): string;
71
78
  getHostPort(): string;
79
+ getClusterIdentifier(): string;
80
+ getSnapshotTarget(): Extract<SnapshotTarget, {
81
+ kind: "cluster";
82
+ }>;
83
+ getDatabaseName(): string;
84
+ getConnectionString(): string;
72
85
  }
73
86
  export {};
@@ -1,4 +1,4 @@
1
- import { CfnOutput, Stack } from "aws-cdk-lib";
1
+ import { ArnFormat, CfnOutput, Stack } from "aws-cdk-lib";
2
2
  import { CfnGlobalCluster } from "aws-cdk-lib/aws-rds";
3
3
  import { Construct } from "constructs";
4
4
  import { RdsAurora } from "./rdsAurora.js";
@@ -32,41 +32,6 @@ export class RdsAuroraGlobal extends Construct {
32
32
  getPrimaryClusterIdentifier() {
33
33
  return ResourceNaming.primaryClusterId(this.constructId);
34
34
  }
35
- getGlobalClusterEngineString() {
36
- // Default to aurora-postgresql if no engine specified (matches existing behaviour)
37
- if (!this.props.engine)
38
- return "aurora-postgresql";
39
- // Handle different engine formats safely using unknown and type guards
40
- const engine = this.props.engine;
41
- // CDK's IClusterEngine interface does not expose engineType/engine/name
42
- // properties directly, but the concrete implementations (e.g. AuroraMysqlEngineVersion)
43
- // do have them at runtime. Cast through unknown to probe these internal fields.
44
- // CDK engine internals — may break on CDK upgrades. See rdsAuroraGlobal unit test.
45
- const engineRecord = engine;
46
- let engineType = engineRecord.engineType ?? engineRecord.engine ?? engineRecord.name;
47
- // If the engine was provided as a raw string (unlikely but support it)
48
- if (typeof engine === "string") {
49
- engineType = engine;
50
- }
51
- // Fallback to toString() for Token-like objects
52
- if (!engineType && typeof engineRecord.toString === "function") {
53
- try {
54
- engineType = engineRecord.toString();
55
- }
56
- catch (_e) {
57
- // toString() may throw on CDK Token objects — fall back to undefined
58
- engineType = undefined;
59
- }
60
- }
61
- if (typeof engineType !== "string")
62
- return "aurora-postgresql";
63
- // Normalise common forms: AURORA_POSTGRESQL -> aurora-postgresql, aurora_postgresql -> aurora-postgresql
64
- const normalised = engineType.toLowerCase().replace(/_/g, "-");
65
- // If the normalised value is just 'aurora', prefer the more specific postgres default
66
- if (normalised === "aurora")
67
- return "aurora-postgresql";
68
- return normalised;
69
- }
70
35
  // create the CfnGlobalCluster only in the primary region
71
36
  addGlobalCluster() {
72
37
  if (this.props.primaryRegion !== this.currentRegion)
@@ -79,9 +44,7 @@ export class RdsAuroraGlobal extends Construct {
79
44
  if (this.primaryCluster) {
80
45
  // Use the helper on RdsAurora to get the underlying L1 DBCluster (more reliable
81
46
  // than relying on node.defaultChild which can vary depending on construct ordering)
82
- primaryL1 =
83
- this.primaryCluster.getCfnCluster &&
84
- this.primaryCluster.getCfnCluster();
47
+ primaryL1 = this.primaryCluster.getCfnCluster();
85
48
  if (primaryL1) {
86
49
  sourceIdentifier = primaryL1.ref;
87
50
  }
@@ -93,7 +56,7 @@ export class RdsAuroraGlobal extends Construct {
93
56
  // ensure the underlying primary DBCluster L1 has the globalClusterIdentifier set
94
57
  if (primaryL1) {
95
58
  // Make the CFN dependency explicit so the DBCluster is created before the GlobalCluster
96
- this.globalCluster.addDependsOn(primaryL1);
59
+ this.globalCluster.addDependency(primaryL1);
97
60
  // IMPORTANT: do NOT set the primary DBCluster's `globalClusterIdentifier` here.
98
61
  // If we set the primary DBCluster to reference the global cluster, CloudFormation
99
62
  // will attempt to validate that the global cluster exists when creating the
@@ -125,7 +88,10 @@ export class RdsAuroraGlobal extends Construct {
125
88
  databaseInsights: this.props.databaseInsights,
126
89
  deletionProtection: this.props.deletionProtection,
127
90
  snapshotIdentifier: this.props.snapshotIdentifier,
128
- snapshotUsername: this.props.snapshotUsername
91
+ snapshotUsername: this.props.snapshotUsername,
92
+ alertsTopic: this.props.alertsTopic,
93
+ alarms: this.props.alarms,
94
+ applicationId: this.props.applicationId
129
95
  };
130
96
  if (this.props.primaryRegion === this.currentRegion) {
131
97
  // primary
@@ -153,8 +119,7 @@ export class RdsAuroraGlobal extends Construct {
153
119
  ...commonConfig
154
120
  });
155
121
  // set the L1 DBCluster property so CloudFormation will join it to the global cluster
156
- const regionalL1 = this.regionalCluster.getCfnCluster &&
157
- this.regionalCluster.getCfnCluster();
122
+ const regionalL1 = this.regionalCluster.getCfnCluster();
158
123
  if (regionalL1) {
159
124
  regionalL1.globalClusterIdentifier = this.globalId;
160
125
  // Enable write forwarding if requested
@@ -192,4 +157,35 @@ export class RdsAuroraGlobal extends Construct {
192
157
  return this.regionalCluster.getHostPort();
193
158
  throw new Error("No Aurora cluster available to return port from");
194
159
  }
160
+ getClusterIdentifier() {
161
+ return this.getPrimaryClusterIdentifier();
162
+ }
163
+ getSnapshotTarget() {
164
+ // The primary cluster lives in `primaryRegion`; pin region explicitly so
165
+ // a secondary-region stack still emits the correct ARN.
166
+ return {
167
+ kind: "cluster",
168
+ arn: Stack.of(this).formatArn({
169
+ service: "rds",
170
+ resource: "cluster",
171
+ resourceName: this.getPrimaryClusterIdentifier(),
172
+ region: this.props.primaryRegion,
173
+ arnFormat: ArnFormat.COLON_RESOURCE_NAME
174
+ })
175
+ };
176
+ }
177
+ getDatabaseName() {
178
+ if (this.primaryCluster)
179
+ return this.primaryCluster.getDatabaseName();
180
+ if (this.regionalCluster)
181
+ return this.regionalCluster.getDatabaseName();
182
+ throw new Error("No Aurora cluster available to return database name from");
183
+ }
184
+ getConnectionString() {
185
+ if (this.primaryCluster)
186
+ return this.primaryCluster.getConnectionString();
187
+ if (this.regionalCluster)
188
+ return this.regionalCluster.getConnectionString();
189
+ throw new Error("No Aurora cluster available to return connection string from");
190
+ }
195
191
  }
@@ -8,4 +8,10 @@ export declare const RDS_DEFAULTS: Readonly<{
8
8
  readonly MONITORING_INTERVAL: Duration;
9
9
  /** SecretsManager rotation application version for multi-user rotation */
10
10
  readonly ROTATION_APP_VERSION: "1.1.367";
11
+ /** Default backup retention in days — applied uniformly across Aurora and RDS Instance */
12
+ readonly BACKUP_RETENTION_DEFAULT_DAYS: 14;
13
+ /** Default instance type — primary and read-replica must stay in lockstep */
14
+ readonly DEFAULT_INSTANCE_TYPE: "t4g.large";
15
+ /** Default storage autoscaling ceiling (GiB) — applied to primary and replica */
16
+ readonly DEFAULT_MAX_ALLOCATED_STORAGE_GIB: 500;
11
17
  }>;
@@ -7,5 +7,11 @@ export const RDS_DEFAULTS = Object.freeze({
7
7
  /** 1 minute — balances monitoring granularity against CloudWatch costs */
8
8
  MONITORING_INTERVAL: Duration.minutes(1),
9
9
  /** SecretsManager rotation application version for multi-user rotation */
10
- ROTATION_APP_VERSION: "1.1.367"
10
+ ROTATION_APP_VERSION: "1.1.367",
11
+ /** Default backup retention in days — applied uniformly across Aurora and RDS Instance */
12
+ BACKUP_RETENTION_DEFAULT_DAYS: 14,
13
+ /** Default instance type — primary and read-replica must stay in lockstep */
14
+ DEFAULT_INSTANCE_TYPE: "t4g.large",
15
+ /** Default storage autoscaling ceiling (GiB) — applied to primary and replica */
16
+ DEFAULT_MAX_ALLOCATED_STORAGE_GIB: 500
11
17
  });
@@ -12,12 +12,12 @@ export declare const DEFAULT_POSTGRES_ENGINE_CONFIG: EngineConfig;
12
12
  * - AWS managed / undefined → returns undefined (CDK default)
13
13
  * - IKey → returns the key as-is
14
14
  */
15
- export declare function resolveStorageEncryptionKey(scope: Construct, databaseName: string | undefined, storageKey: EncryptionKeySpec | undefined): IKey | undefined;
15
+ export declare function resolveStorageEncryptionKey(scope: Construct, databaseName: string, storageKey: EncryptionKeySpec | undefined): IKey | undefined;
16
16
  /**
17
17
  * Resolve a Performance Insights encryption key spec into an IKey or undefined.
18
18
  * Only creates a CMK when PI is enabled and CMK is requested.
19
19
  */
20
- export declare function resolvePerformanceInsightsKey(scope: Construct, databaseName: string | undefined, piEnabled: boolean, encryptionKey: EncryptionKeySpec | undefined): IKey | undefined;
20
+ export declare function resolvePerformanceInsightsKey(scope: Construct, databaseName: string, piEnabled: boolean, encryptionKey: EncryptionKeySpec | undefined): IKey | undefined;
21
21
  /** Resolve the databaseInsights prop into an enabled flag and optional config object. */
22
22
  export declare function resolveDatabaseInsights(databaseInsights: DatabaseInsightsConfig | false | undefined): {
23
23
  piEnabled: boolean;
@@ -29,7 +29,7 @@ export declare function resolveDatabaseInsights(databaseInsights: DatabaseInsigh
29
29
  */
30
30
  export declare function addMultiUserSecretRotation(params: {
31
31
  scope: Construct;
32
- databaseName: string | undefined;
32
+ databaseName: string;
33
33
  constructId: string;
34
34
  engineConfig: EngineConfig;
35
35
  credentialsConfig: CredentialsConfig | undefined;
@@ -6,6 +6,7 @@ import { RDS_DEFAULTS } from "./rdsDefaults.js";
6
6
  import { isAwsManagedKey, isCMKRequested } from "../../../utils/databaseTypes.js";
7
7
  /** Default PostgreSQL engine configuration used by both Aurora and Instance constructs. */
8
8
  export const DEFAULT_POSTGRES_ENGINE_CONFIG = {
9
+ family: "postgresql",
9
10
  defaultUsername: "postgres",
10
11
  sslParameters: { "rds.force_ssl": "1" },
11
12
  rotationAppName: "SecretsManagerRDSPostgreSQLRotationMultiUser"
@@ -5,7 +5,7 @@ import { Construct } from "constructs";
5
5
  import { SecurityGroup } from "../networking/securityGroup.js";
6
6
  import { Secret } from "../secrets/index.js";
7
7
  import { type StackBuilder } from "../base/awsStack.js";
8
- import { type EngineConfig, type ProxyConfig, type ReadReplicaConfig, type CredentialsConfig, type EncryptionConfig, type DatabaseInsightsConfig } from "../../../utils/databaseTypes.js";
8
+ import { type EngineConfig, type ProxyConfig, type ReadReplicaConfig, type CredentialsConfig, type EncryptionConfig, type DatabaseInsightsConfig, type SnapshotTarget } from "../../../utils/databaseTypes.js";
9
9
  import type { ITopic } from "aws-cdk-lib/aws-sns";
10
10
  import { type RdsAlarmThresholds } from "../monitoring/index.js";
11
11
  interface RdsProps {
@@ -54,6 +54,7 @@ export declare class RdsInstance extends Construct implements IConnectable {
54
54
  private databaseProxy?;
55
55
  private databaseProxySecurityGroup?;
56
56
  private readReplicaSecurityGroup?;
57
+ private databaseNameValue;
57
58
  private readonly constructId;
58
59
  constructor(scope: Construct, id: string, props: RdsProps);
59
60
  private addDatabase;
@@ -63,6 +64,12 @@ export declare class RdsInstance extends Construct implements IConnectable {
63
64
  getHostEndpoint(): string;
64
65
  getHostPort(): string;
65
66
  getCredentials(): Secret;
67
+ getInstanceIdentifier(): string;
68
+ getSnapshotTarget(): Extract<SnapshotTarget, {
69
+ kind: "instance";
70
+ }>;
71
+ getDatabaseName(): string;
72
+ getConnectionString(): string;
66
73
  static build(id: string, props: RdsProps): (sb: StackBuilder) => Construct;
67
74
  }
68
75
  export {};
@@ -26,12 +26,14 @@ export class RdsInstance extends Construct {
26
26
  databaseProxy;
27
27
  databaseProxySecurityGroup;
28
28
  readReplicaSecurityGroup;
29
+ databaseNameValue;
29
30
  constructId;
30
31
  constructor(scope, id, props) {
31
32
  super(scope, id);
32
33
  this.constructId = id;
33
- this.port = props.port || RDS_DEFAULTS.DEFAULT_PORT;
34
+ this.port = props.port ?? RDS_DEFAULTS.DEFAULT_PORT;
34
35
  this.vpc = props.vpc;
36
+ this.databaseNameValue = props.databaseName ?? id.replace("Rds", "");
35
37
  // PostgreSQL fallback for direct usage - ensure engine and engineConfig match
36
38
  this.engineConfig = props.engineConfig ?? DEFAULT_POSTGRES_ENGINE_CONFIG;
37
39
  this.addDatabase(props);
@@ -62,7 +64,7 @@ export class RdsInstance extends Construct {
62
64
  const username = props.snapshotIdentifier && props.snapshotUsername
63
65
  ? props.snapshotUsername
64
66
  : (props.credentials?.username ?? this.engineConfig.defaultUsername);
65
- this.databaseCredentials = new Secret(this, `${props.databaseName}Credentials`, {
67
+ this.databaseCredentials = new Secret(this, `${this.databaseNameValue}Credentials`, {
66
68
  secretName: ResourceNaming.credentialsSecretName(this.constructId),
67
69
  generateSecretString: {
68
70
  secretStringTemplate: JSON.stringify({
@@ -73,9 +75,9 @@ export class RdsInstance extends Construct {
73
75
  generateStringKey: "password"
74
76
  }
75
77
  });
76
- this.databaseSecurityGroup = new SecurityGroup(this, `${props.databaseName}SecurityGroup`, {
78
+ this.databaseSecurityGroup = new SecurityGroup(this, `${this.databaseNameValue}SecurityGroup`, {
77
79
  vpc: this.vpc,
78
- description: `Security group for RDS database instance ${props.databaseName}`
80
+ description: `Security group for RDS database instance ${this.databaseNameValue}`
79
81
  });
80
82
  // Self-referencing rule for multi-AZ communication
81
83
  this.databaseSecurityGroup.addIngressRule(this.databaseSecurityGroup, Port.tcp(this.port));
@@ -83,9 +85,9 @@ export class RdsInstance extends Construct {
83
85
  securityGroups: [this.databaseSecurityGroup],
84
86
  defaultPort: Port.tcp(this.port)
85
87
  });
86
- const storageEncryptionKey = resolveStorageEncryptionKey(this, props.databaseName, props.encryption?.storageKey);
88
+ const storageEncryptionKey = resolveStorageEncryptionKey(this, this.databaseNameValue, props.encryption?.storageKey);
87
89
  const { piEnabled, piConfig } = resolveDatabaseInsights(props.databaseInsights);
88
- const performanceInsightsEncryptionKey = resolvePerformanceInsightsKey(this, props.databaseName, piEnabled, piConfig?.encryptionKey);
90
+ const performanceInsightsEncryptionKey = resolvePerformanceInsightsKey(this, this.databaseNameValue, piEnabled, piConfig?.encryptionKey);
89
91
  const diMode = piConfig?.mode ?? "standard";
90
92
  const performanceInsightsRetention = piEnabled
91
93
  ? getDatabaseInsightsRetention(diMode)
@@ -94,9 +96,9 @@ export class RdsInstance extends Construct {
94
96
  DatabaseInstanceEngine.postgres({
95
97
  version: PostgresEngineVersion.VER_17_5
96
98
  });
97
- const parameterGroup = new ParameterGroup(this, `${props.databaseName}ParameterGroup`, {
99
+ const parameterGroup = new ParameterGroup(this, `${this.databaseNameValue}ParameterGroup`, {
98
100
  engine,
99
- description: `Parameter group for ${props.databaseName} with security defaults`,
101
+ description: `Parameter group for ${this.databaseNameValue} with security defaults`,
100
102
  parameters: this.engineConfig.sslParameters
101
103
  });
102
104
  // Use PUBLIC subnet for publiclyAccessible databases (e.g., tinkerer tier without NAT)
@@ -112,8 +114,9 @@ export class RdsInstance extends Construct {
112
114
  engine,
113
115
  parameterGroup,
114
116
  allocatedStorage: props.allocatedStorage,
115
- backupRetention: props.backupRetention || Duration.days(14),
116
- preferredBackupWindow: props.preferredBackupWindow || "02:00-03:00",
117
+ backupRetention: props.backupRetention ??
118
+ Duration.days(RDS_DEFAULTS.BACKUP_RETENTION_DEFAULT_DAYS),
119
+ preferredBackupWindow: props.preferredBackupWindow ?? "02:00-03:00",
117
120
  storageEncrypted: true,
118
121
  storageEncryptionKey,
119
122
  storageType: StorageType.GP3,
@@ -124,21 +127,20 @@ export class RdsInstance extends Construct {
124
127
  performanceInsightEncryptionKey: performanceInsightsEncryptionKey,
125
128
  performanceInsightRetention: performanceInsightsRetention,
126
129
  instanceIdentifier: ResourceNaming.dbInstanceId(this.constructId),
127
- instanceType: props.instanceType
128
- ? new InstanceType(props.instanceType)
129
- : new InstanceType("t4g.large"),
130
- maxAllocatedStorage: props.maxAllocatedStorage || 500,
131
- monitoringInterval: props.monitoringInterval || RDS_DEFAULTS.MONITORING_INTERVAL,
130
+ instanceType: new InstanceType(props.instanceType ?? RDS_DEFAULTS.DEFAULT_INSTANCE_TYPE),
131
+ maxAllocatedStorage: props.maxAllocatedStorage ??
132
+ RDS_DEFAULTS.DEFAULT_MAX_ALLOCATED_STORAGE_GIB,
133
+ monitoringInterval: props.monitoringInterval ?? RDS_DEFAULTS.MONITORING_INTERVAL,
132
134
  multiAz: props.multiAz !== false,
133
135
  port: this.port,
134
136
  deletionProtection: props.deletionProtection ?? true,
135
- preferredMaintenanceWindow: props.preferredMaintenanceWindow ||
137
+ preferredMaintenanceWindow: props.preferredMaintenanceWindow ??
136
138
  RDS_DEFAULTS.PREFERRED_MAINTENANCE_WINDOW,
137
139
  publiclyAccessible: props.publiclyAccessible ?? false
138
140
  };
139
141
  if (props.snapshotIdentifier) {
140
142
  // Create from snapshot
141
- this.database = new DatabaseInstanceFromSnapshot(this, `${props.databaseName}Database`, {
143
+ this.database = new DatabaseInstanceFromSnapshot(this, `${this.databaseNameValue}Database`, {
142
144
  ...commonInstanceProps,
143
145
  snapshotIdentifier: props.snapshotIdentifier,
144
146
  // For snapshots, credentials are used to reset the password
@@ -147,7 +149,7 @@ export class RdsInstance extends Construct {
147
149
  }
148
150
  else {
149
151
  // Create new instance
150
- this.database = new DatabaseInstance(this, `${props.databaseName}Database`, {
152
+ this.database = new DatabaseInstance(this, `${this.databaseNameValue}Database`, {
151
153
  ...commonInstanceProps,
152
154
  databaseName: props.databaseName,
153
155
  credentials: Credentials.fromSecret(this.databaseCredentials.secret)
@@ -157,7 +159,7 @@ export class RdsInstance extends Construct {
157
159
  rotateSecret(props) {
158
160
  this.masterSecret = addMultiUserSecretRotation({
159
161
  scope: this,
160
- databaseName: props.databaseName,
162
+ databaseName: this.databaseNameValue,
161
163
  constructId: this.constructId,
162
164
  engineConfig: this.engineConfig,
163
165
  credentialsConfig: props.credentials,
@@ -173,13 +175,13 @@ export class RdsInstance extends Construct {
173
175
  const vpcSubnets = proxyConfig.vpcSubnets ?? {
174
176
  subnetType: SubnetType.PRIVATE_WITH_EGRESS
175
177
  };
176
- this.databaseProxySecurityGroup = new SecurityGroup(this, `${props.databaseName}ProxySecurityGroup`, {
178
+ this.databaseProxySecurityGroup = new SecurityGroup(this, `${this.databaseNameValue}ProxySecurityGroup`, {
177
179
  vpc: this.vpc,
178
- description: `Security group for RDS Proxy for ${props.databaseName}`
180
+ description: `Security group for RDS Proxy for ${this.databaseNameValue}`
179
181
  });
180
182
  // Allow proxy to connect to database
181
183
  this.databaseSecurityGroup.addIngressRule(this.databaseProxySecurityGroup, Port.tcp(this.port), "Allow RDS Proxy to connect to database");
182
- this.databaseProxy = new DatabaseProxy(this, `${props.databaseName}DatabaseProxy`, {
184
+ this.databaseProxy = new DatabaseProxy(this, `${this.databaseNameValue}DatabaseProxy`, {
183
185
  dbProxyName: ResourceNaming.proxyName(this.constructId),
184
186
  proxyTarget: ProxyTarget.fromInstance(this.database),
185
187
  secrets: [this.databaseCredentials.secret],
@@ -193,22 +195,24 @@ export class RdsInstance extends Construct {
193
195
  maxConnectionsPercent: proxyConfig.maxConnections,
194
196
  maxIdleConnectionsPercent: proxyConfig.maxIdleConnections
195
197
  });
196
- addProxyCfnOutput(this, this.constructId, props.databaseName, this.databaseProxy);
198
+ addProxyCfnOutput(this, this.constructId, this.databaseNameValue, this.databaseProxy);
197
199
  }
198
200
  addReadReplica(props) {
199
201
  if (!props.readReplica)
200
202
  return;
201
203
  const replicaConfig = props.readReplica;
202
- const replicaInstanceType = replicaConfig.instanceType ?? props.instanceType ?? "t4g.large";
204
+ const replicaInstanceType = replicaConfig.instanceType ??
205
+ props.instanceType ??
206
+ RDS_DEFAULTS.DEFAULT_INSTANCE_TYPE;
203
207
  const { piEnabled, piConfig } = resolveDatabaseInsights(props.databaseInsights);
204
208
  const readReplicaPerformanceInsightsKey = piEnabled && isCMKRequested(piConfig?.encryptionKey)
205
- ? new CustomerManagedKey(this, `${props.databaseName}ReadReplicaReaderInsightsKey`, {
206
- aliasName: `cmk/rds/${props.databaseName}/ReadReplicaInsightsKey`
209
+ ? new CustomerManagedKey(this, `${this.databaseNameValue}ReadReplicaReaderInsightsKey`, {
210
+ aliasName: `cmk/rds/${this.databaseNameValue}/ReadReplicaInsightsKey`
207
211
  }).key
208
212
  : undefined;
209
- this.readReplicaSecurityGroup = new SecurityGroup(this, `${props.databaseName}ReadReplicaSecurityGroup`, {
213
+ this.readReplicaSecurityGroup = new SecurityGroup(this, `${this.databaseNameValue}ReadReplicaSecurityGroup`, {
210
214
  vpc: this.vpc,
211
- description: `Security group for RDS read replica of ${props.databaseName}`
215
+ description: `Security group for RDS read replica of ${this.databaseNameValue}`
212
216
  });
213
217
  // Allow primary database to replicate to read replica
214
218
  this.readReplicaSecurityGroup.addIngressRule(this.databaseSecurityGroup, Port.tcp(this.port), "Allow primary database to replicate to read replica");
@@ -217,10 +221,10 @@ export class RdsInstance extends Construct {
217
221
  // Without this waiter, the final snapshot creation fails.
218
222
  const instanceId = ResourceNaming.dbInstanceId(this.constructId);
219
223
  const waiterTimeout = Duration.minutes(10);
220
- const deletionWaiter = new CustomResource(this, `${props.databaseName}DeletionWaiter`, {
224
+ const deletionWaiter = new CustomResource(this, `${this.databaseNameValue}DeletionWaiter`, {
221
225
  runtime: Runtime.NODEJS_22_X,
222
226
  timeout: waiterTimeout.plus(Duration.seconds(30)),
223
- lambdaDescription: `${props.databaseName} deletion waiter`,
227
+ lambdaDescription: `${this.databaseNameValue} deletion waiter`,
224
228
  inlineCode: `
225
229
  const { RDSClient } = require('@aws-sdk/client-rds');
226
230
  const { waitUntilDBInstanceAvailable } = require('@aws-sdk/client-rds');
@@ -266,7 +270,7 @@ exports.handler = async (event) => {
266
270
  }
267
271
  });
268
272
  deletionWaiter.resource.node.addDependency(this.database);
269
- const readReplica = new DatabaseInstanceReadReplica(this, `${props.databaseName}ReadReplica`, {
273
+ const readReplica = new DatabaseInstanceReadReplica(this, `${this.databaseNameValue}ReadReplica`, {
270
274
  sourceDatabaseInstance: this.database,
271
275
  vpc: this.vpc,
272
276
  vpcSubnets: {
@@ -287,12 +291,13 @@ exports.handler = async (event) => {
287
291
  instanceIdentifier: ResourceNaming.readReplicaId(this.constructId),
288
292
  instanceType: new InstanceType(replicaInstanceType),
289
293
  availabilityZone: replicaConfig.availabilityZone,
290
- maxAllocatedStorage: props.maxAllocatedStorage || 500,
291
- monitoringInterval: props.monitoringInterval || RDS_DEFAULTS.MONITORING_INTERVAL,
294
+ maxAllocatedStorage: props.maxAllocatedStorage ??
295
+ RDS_DEFAULTS.DEFAULT_MAX_ALLOCATED_STORAGE_GIB,
296
+ monitoringInterval: props.monitoringInterval ?? RDS_DEFAULTS.MONITORING_INTERVAL,
292
297
  multiAz: props.multiAz !== false,
293
298
  port: this.port,
294
299
  deletionProtection: props.deletionProtection ?? true,
295
- preferredMaintenanceWindow: props.preferredMaintenanceWindow ||
300
+ preferredMaintenanceWindow: props.preferredMaintenanceWindow ??
296
301
  RDS_DEFAULTS.PREFERRED_MAINTENANCE_WINDOW
297
302
  });
298
303
  readReplica.node.addDependency(deletionWaiter.resource);
@@ -311,6 +316,18 @@ exports.handler = async (event) => {
311
316
  getCredentials() {
312
317
  return this.databaseCredentials;
313
318
  }
319
+ getInstanceIdentifier() {
320
+ return this.database.instanceIdentifier;
321
+ }
322
+ getSnapshotTarget() {
323
+ return { kind: "instance", arn: this.database.instanceArn };
324
+ }
325
+ getDatabaseName() {
326
+ return this.databaseNameValue;
327
+ }
328
+ getConnectionString() {
329
+ return `${this.engineConfig.family}://${this.getHostEndpoint()}:${this.getHostPort()}/${this.getDatabaseName()}`;
330
+ }
314
331
  static build(id, props) {
315
332
  return (sb) => {
316
333
  const newProps = {