@fjall/components-infrastructure 0.96.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 (209) hide show
  1. package/dist/lib/app.d.ts +68 -1
  2. package/dist/lib/app.js +113 -4
  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 +2 -4
  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 +93 -5
  36. package/dist/lib/patterns/aws/computeEcs.js +867 -37
  37. package/dist/lib/patterns/aws/computeEcsTypes.d.ts +528 -25
  38. package/dist/lib/patterns/aws/computeEcsTypes.js +10 -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 +6 -4
  44. package/dist/lib/patterns/aws/index.d.ts +1 -0
  45. package/dist/lib/patterns/aws/index.js +1 -0
  46. package/dist/lib/patterns/aws/interfaces/compute.d.ts +7 -1
  47. package/dist/lib/patterns/aws/interfaces/database.d.ts +187 -8
  48. package/dist/lib/patterns/aws/interfaces/database.js +17 -3
  49. package/dist/lib/patterns/aws/interfaces/index.d.ts +2 -1
  50. package/dist/lib/patterns/aws/interfaces/index.js +3 -1
  51. package/dist/lib/patterns/aws/interfaces/messaging.d.ts +7 -0
  52. package/dist/lib/patterns/aws/interfaces/migrationContributor.d.ts +47 -0
  53. package/dist/lib/patterns/aws/interfaces/migrationContributor.js +9 -0
  54. package/dist/lib/patterns/aws/messaging.d.ts +66 -10
  55. package/dist/lib/patterns/aws/messaging.js +115 -20
  56. package/dist/lib/patterns/aws/network.js +16 -7
  57. package/dist/lib/patterns/aws/organisation.d.ts +4 -0
  58. package/dist/lib/patterns/aws/organisation.js +22 -4
  59. package/dist/lib/patterns/aws/storage.d.ts +1 -2
  60. package/dist/lib/patterns/aws/storage.js +3 -2
  61. package/dist/lib/patterns/aws/vpcPeer.js +3 -1
  62. package/dist/lib/resources/aws/analytics/clickhouse.js +18 -9
  63. package/dist/lib/resources/aws/analytics/clickhouseAlarms.d.ts +24 -9
  64. package/dist/lib/resources/aws/analytics/clickhouseAlarms.js +61 -10
  65. package/dist/lib/resources/aws/analytics/clickhouseConstants.d.ts +3 -3
  66. package/dist/lib/resources/aws/analytics/clickhouseConstants.js +3 -3
  67. package/dist/lib/resources/aws/analytics/clickhouseTypes.d.ts +7 -1
  68. package/dist/lib/resources/aws/analytics/clickhouseUserData.d.ts +1 -1
  69. package/dist/lib/resources/aws/analytics/clickhouseUserData.js +53 -3
  70. package/dist/lib/resources/aws/base/awsStack.js +4 -2
  71. package/dist/lib/resources/aws/compute/__tmp__/regression-shape.d.ts +2 -0
  72. package/dist/lib/resources/aws/compute/__tmp__/regression-shape.js +11 -0
  73. package/dist/lib/resources/aws/compute/asgInlineLifecycleHook.d.ts +52 -0
  74. package/dist/lib/resources/aws/compute/asgInlineLifecycleHook.js +60 -0
  75. package/dist/lib/resources/aws/compute/blockDeviceVolume.d.ts +8 -0
  76. package/dist/lib/resources/aws/compute/blockDeviceVolume.js +10 -0
  77. package/dist/lib/resources/aws/compute/ec2.d.ts +132 -12
  78. package/dist/lib/resources/aws/compute/ec2.js +163 -23
  79. package/dist/lib/resources/aws/compute/ec2GracefulTerminationHandler.d.ts +41 -0
  80. package/dist/lib/resources/aws/compute/ec2GracefulTerminationHandler.js +194 -0
  81. package/dist/lib/resources/aws/compute/ec2GracefulTerminationLambda.source.cjs +458 -0
  82. package/dist/lib/resources/aws/compute/ecs.d.ts +27 -1
  83. package/dist/lib/resources/aws/compute/ecs.js +42 -2
  84. package/dist/lib/resources/aws/compute/ecsConstants.d.ts +9 -0
  85. package/dist/lib/resources/aws/compute/ecsConstants.js +16 -0
  86. package/dist/lib/resources/aws/compute/ecsImages.js +32 -20
  87. package/dist/lib/resources/aws/compute/ecsLifecycleHookMigration.d.ts +96 -0
  88. package/dist/lib/resources/aws/compute/ecsLifecycleHookMigration.js +113 -0
  89. package/dist/lib/resources/aws/compute/ecsNetworking.d.ts +2 -1
  90. package/dist/lib/resources/aws/compute/ecsNetworking.js +18 -6
  91. package/dist/lib/resources/aws/compute/ecsServiceFactory.d.ts +13 -4
  92. package/dist/lib/resources/aws/compute/ecsServiceFactory.js +155 -33
  93. package/dist/lib/resources/aws/compute/ecsTaskDefinition.d.ts +31 -1
  94. package/dist/lib/resources/aws/compute/ecsTaskDefinition.js +102 -6
  95. package/dist/lib/resources/aws/compute/ecsTypes.d.ts +173 -13
  96. package/dist/lib/resources/aws/compute/ecsValidation.d.ts +9 -0
  97. package/dist/lib/resources/aws/compute/ecsValidation.js +63 -0
  98. package/dist/lib/resources/aws/compute/index.d.ts +2 -0
  99. package/dist/lib/resources/aws/compute/index.js +2 -0
  100. package/dist/lib/resources/aws/compute/lambda.d.ts +7 -13
  101. package/dist/lib/resources/aws/compute/lambda.js +30 -38
  102. package/dist/lib/resources/aws/compute/lifecycleHookLambda.source.cjs +192 -0
  103. package/dist/lib/resources/aws/compute/persistentDataVolume.d.ts +104 -0
  104. package/dist/lib/resources/aws/compute/persistentDataVolume.js +245 -0
  105. package/dist/lib/resources/aws/compute/persistentDataVolumeLambda.source.cjs +398 -0
  106. package/dist/lib/resources/aws/compute/samApplication.d.ts +15 -0
  107. package/dist/lib/resources/aws/compute/samApplication.js +27 -0
  108. package/dist/lib/resources/aws/database/clickhouseConstants.d.ts +159 -0
  109. package/dist/lib/resources/aws/database/clickhouseConstants.js +181 -0
  110. package/dist/lib/resources/aws/database/clickhouseSchemas.d.ts +71 -0
  111. package/dist/lib/resources/aws/database/clickhouseSchemas.js +157 -0
  112. package/dist/lib/resources/aws/database/clickhouseSecurityGroup.d.ts +14 -0
  113. package/dist/lib/resources/aws/database/clickhouseSecurityGroup.js +23 -0
  114. package/dist/lib/resources/aws/database/clickhouseUserData.d.ts +69 -0
  115. package/dist/lib/resources/aws/database/clickhouseUserData.js +371 -0
  116. package/dist/lib/resources/aws/database/clickhouseXmlRenderer.d.ts +56 -0
  117. package/dist/lib/resources/aws/database/clickhouseXmlRenderer.js +112 -0
  118. package/dist/lib/resources/aws/database/rdsAurora.d.ts +8 -1
  119. package/dist/lib/resources/aws/database/rdsAurora.js +42 -32
  120. package/dist/lib/resources/aws/database/rdsAuroraGlobal.d.ts +15 -2
  121. package/dist/lib/resources/aws/database/rdsAuroraGlobal.js +39 -43
  122. package/dist/lib/resources/aws/database/rdsDefaults.d.ts +6 -0
  123. package/dist/lib/resources/aws/database/rdsDefaults.js +7 -1
  124. package/dist/lib/resources/aws/database/rdsHelpers.d.ts +3 -3
  125. package/dist/lib/resources/aws/database/rdsHelpers.js +1 -0
  126. package/dist/lib/resources/aws/database/rdsInstance.d.ts +8 -1
  127. package/dist/lib/resources/aws/database/rdsInstance.js +51 -34
  128. package/dist/lib/resources/aws/database/rdsProxyOutput.d.ts +1 -1
  129. package/dist/lib/resources/aws/database/rdsProxyOutput.js +1 -1
  130. package/dist/lib/resources/aws/iam/delegationRole.js +1 -1
  131. package/dist/lib/resources/aws/iam/identityCenter/groupMembership.d.ts +9 -0
  132. package/dist/lib/resources/aws/iam/identityCenter/groupMembership.js +12 -0
  133. package/dist/lib/resources/aws/iam/identityCenter/index.d.ts +1 -0
  134. package/dist/lib/resources/aws/iam/identityCenter/index.js +1 -0
  135. package/dist/lib/resources/aws/iam/identityCenter/permissionSet.d.ts +1 -0
  136. package/dist/lib/resources/aws/iam/identityCenter/permissionSet.js +1 -0
  137. package/dist/lib/resources/aws/logging/logGroup.d.ts +0 -8
  138. package/dist/lib/resources/aws/logging/logGroup.js +0 -11
  139. package/dist/lib/resources/aws/messaging/defaultEventBus.d.ts +7 -0
  140. package/dist/lib/resources/aws/messaging/defaultEventBus.js +21 -0
  141. package/dist/lib/resources/aws/messaging/eventBridgeRule.d.ts +96 -0
  142. package/dist/lib/resources/aws/messaging/eventBridgeRule.js +110 -0
  143. package/dist/lib/resources/aws/messaging/eventTargets.d.ts +84 -0
  144. package/dist/lib/resources/aws/messaging/eventTargets.js +152 -0
  145. package/dist/lib/resources/aws/messaging/eventbridge.d.ts +25 -2
  146. package/dist/lib/resources/aws/messaging/eventbridge.js +22 -10
  147. package/dist/lib/resources/aws/messaging/index.d.ts +5 -0
  148. package/dist/lib/resources/aws/messaging/index.js +2 -0
  149. package/dist/lib/resources/aws/messaging/schedule.d.ts +118 -0
  150. package/dist/lib/resources/aws/messaging/schedule.js +64 -0
  151. package/dist/lib/resources/aws/messaging/sns.d.ts +2 -1
  152. package/dist/lib/resources/aws/messaging/sqs.d.ts +2 -1
  153. package/dist/lib/resources/aws/messaging/subscription.d.ts +112 -0
  154. package/dist/lib/resources/aws/messaging/subscription.js +67 -0
  155. package/dist/lib/resources/aws/messaging/utils.d.ts +6 -0
  156. package/dist/lib/resources/aws/messaging/utils.js +10 -0
  157. package/dist/lib/resources/aws/monitoring/clickhouseAlarms.d.ts +60 -0
  158. package/dist/lib/resources/aws/monitoring/clickhouseAlarms.js +139 -0
  159. package/dist/lib/resources/aws/monitoring/index.d.ts +2 -0
  160. package/dist/lib/resources/aws/monitoring/index.js +2 -0
  161. package/dist/lib/resources/aws/monitoring/scheduleAlarms.d.ts +47 -0
  162. package/dist/lib/resources/aws/monitoring/scheduleAlarms.js +106 -0
  163. package/dist/lib/resources/aws/networking/crossAccountDelegationRecord.js +6 -4
  164. package/dist/lib/resources/aws/networking/crossAccountReturnRoutes.js +17 -13
  165. package/dist/lib/resources/aws/networking/dnsRecord/dnsRecordBase.js +7 -5
  166. package/dist/lib/resources/aws/networking/domainCertificate.d.ts +2 -2
  167. package/dist/lib/resources/aws/networking/domainCertificate.js +6 -4
  168. package/dist/lib/resources/aws/networking/hostedZone.js +6 -5
  169. package/dist/lib/resources/aws/networking/serviceDiscovery.d.ts +96 -0
  170. package/dist/lib/resources/aws/networking/serviceDiscovery.js +96 -0
  171. package/dist/lib/resources/aws/networking/vpc.d.ts +4 -1
  172. package/dist/lib/resources/aws/networking/vpc.js +4 -1
  173. package/dist/lib/resources/aws/networking/vpcPeeringConnection.js +21 -3
  174. package/dist/lib/resources/aws/organisation/costAllocationTagActivator.d.ts +16 -5
  175. package/dist/lib/resources/aws/organisation/costAllocationTagActivator.js +17 -3
  176. package/dist/lib/resources/aws/organisation/index.d.ts +1 -1
  177. package/dist/lib/resources/aws/organisation/organisationPolicy.d.ts +2 -0
  178. package/dist/lib/resources/aws/organisation/organisationPolicy.js +3 -2
  179. package/dist/lib/resources/aws/secrets/secret.d.ts +7 -0
  180. package/dist/lib/resources/aws/secrets/secret.js +4 -3
  181. package/dist/lib/resources/aws/storage/bucketDeployment.d.ts +16 -0
  182. package/dist/lib/resources/aws/storage/bucketDeployment.js +17 -0
  183. package/dist/lib/resources/aws/storage/ecr.js +5 -5
  184. package/dist/lib/resources/aws/storage/index.d.ts +1 -0
  185. package/dist/lib/resources/aws/storage/index.js +1 -0
  186. package/dist/lib/resources/aws/storage/s3.js +10 -3
  187. package/dist/lib/resources/aws/utilities/customResource.js +18 -9
  188. package/dist/lib/synth_dump.d.ts +1 -0
  189. package/dist/lib/synth_dump.js +42 -0
  190. package/dist/lib/utils/cdkContext.d.ts +2 -0
  191. package/dist/lib/utils/cdkContext.js +4 -2
  192. package/dist/lib/utils/connections.js +6 -0
  193. package/dist/lib/utils/connector.d.ts +12 -0
  194. package/dist/lib/utils/costAllocationTags.d.ts +9 -0
  195. package/dist/lib/utils/costAllocationTags.js +11 -1
  196. package/dist/lib/utils/databaseTypes.d.ts +14 -0
  197. package/dist/lib/utils/getConfig.d.ts +2 -0
  198. package/dist/lib/utils/getConfig.js +2 -0
  199. package/dist/lib/utils/index.d.ts +1 -0
  200. package/dist/lib/utils/index.js +1 -0
  201. package/dist/lib/utils/manifestWriter.d.ts +6 -89
  202. package/dist/lib/utils/manifestWriter.js +36 -23
  203. package/dist/lib/utils/migrationVersionResolvers.d.ts +2 -0
  204. package/dist/lib/utils/migrationVersionResolvers.js +2 -0
  205. package/dist/lib/utils/orgConfigParser.js +2 -1
  206. package/dist/lib/utils/resolveAlertsTopic.d.ts +14 -0
  207. package/dist/lib/utils/resolveAlertsTopic.js +30 -0
  208. package/dist/lib/utils/validationLogger.js +6 -3
  209. package/package.json +22 -19
@@ -15,19 +15,44 @@
15
15
  */
16
16
  import { type ITable } from "aws-cdk-lib/aws-dynamodb";
17
17
  import { type IConnectable } from "aws-cdk-lib/aws-ec2";
18
- import { type IGrantable, type Grant } from "aws-cdk-lib/aws-iam";
18
+ import { type TaskDefinition } from "aws-cdk-lib/aws-ecs";
19
+ import { type IGrantable, type Grant, type PolicyStatement } from "aws-cdk-lib/aws-iam";
20
+ import { type IBucket } from "aws-cdk-lib/aws-s3";
19
21
  import { type Construct } from "constructs";
20
22
  import { type Secret } from "../../../resources/aws/secrets/index.js";
23
+ import { type SnapshotTarget } from "../../../utils/databaseTypes.js";
24
+ import { type IMigrationContributor } from "./migrationContributor.js";
25
+ export { type SnapshotTarget } from "../../../utils/databaseTypes.js";
26
+ export { MIGRATION_SNAPSHOT_NAME_PREFIX, EXPECTED_SCHEMA_VERSION_ENV, EXPECTED_SCHEMA_VERSION_TOOL_ENV } from "@fjall/util";
27
+ /**
28
+ * Declarative migration configuration on a relational database. Drives:
29
+ * - the schema-version resolver at synth (filesystem scan of `dir`)
30
+ * - the env auto-injection through every connected service's containers
31
+ *
32
+ * `tool: "prisma"` uses the built-in `^\d{14}_/` directory-name resolver.
33
+ * `tool: "custom"` accepts a user-supplied resolver — pure function from
34
+ * directory path to version string. Drizzle / Flyway / Rails users wire
35
+ * their own resolver without waiting for first-class support.
36
+ */
37
+ export type MigrationsConfig = {
38
+ readonly tool: "prisma";
39
+ readonly dir: string;
40
+ } | {
41
+ readonly tool: "custom";
42
+ readonly dir: string;
43
+ readonly versionResolver: (dir: string) => string;
44
+ };
21
45
  /**
22
46
  * Database type discriminator.
23
47
  * Relational types share the IRelationalDatabase interface.
24
48
  * DynamoDB has its own IDynamoDBDatabase interface.
25
49
  */
26
- export type DatabaseType = "Aurora" | "Instance" | "GlobalAurora" | "DynamoDB";
50
+ export type DatabaseType = "Aurora" | "Instance" | "GlobalAurora" | "DynamoDB" | "ClickHouse";
27
51
  /**
28
52
  * Relational database type discriminator.
29
53
  */
30
- export type RelationalDatabaseType = "Aurora" | "Instance" | "GlobalAurora";
54
+ export declare const RELATIONAL_DATABASE_TYPES: readonly ["Aurora", "Instance", "GlobalAurora"];
55
+ export type RelationalDatabaseType = (typeof RELATIONAL_DATABASE_TYPES)[number];
31
56
  /**
32
57
  * Base database interface.
33
58
  * All database types implement this interface.
@@ -39,19 +64,74 @@ export interface IDatabase {
39
64
  readonly node: Construct["node"];
40
65
  }
41
66
  /**
42
- * Relational database interface (Aurora, RDS Instance, GlobalAurora).
43
- * Provides access to connection details, credentials, and security group connections.
67
+ * Shared base for all relational databases (Aurora, RDS Instance, GlobalAurora).
68
+ * Carries everything that does not depend on the variant — connection details,
69
+ * credentials, snapshot target, security group connections.
44
70
  */
45
- export interface IRelationalDatabase extends IDatabase, IConnectable {
71
+ export interface IRelationalDatabaseBase extends IDatabase, IConnectable, IMigrationContributor {
46
72
  readonly databaseType: RelationalDatabaseType;
47
73
  /** Get the database host endpoint. */
48
74
  getHostEndpoint(): string;
49
75
  /** Get the database port. */
50
76
  getHostPort(): string;
77
+ /**
78
+ * Database connection string WITHOUT credentials.
79
+ * Returns `<scheme>://<host>:<port>/<dbname>` where scheme is `postgresql` or
80
+ * `mysql` depending on engine family.
81
+ *
82
+ * Callers compose the final URL at runtime by injecting credentials from
83
+ * `getCredentials().getImport(...)`. Credentials are deliberately excluded
84
+ * from the connection string because Secrets Manager `SecretValue` references
85
+ * cannot be safely interpolated at synth time — leaking them to the URL
86
+ * would bake plaintext into the CloudFormation template.
87
+ *
88
+ * @example
89
+ * // Synth time (CDK):
90
+ * environment: { DATABASE_URL_BASE: database.getConnectionString() }
91
+ * secretsImport: {
92
+ * DATABASE_USER: database.getCredentials().getImport("username"),
93
+ * DATABASE_PASSWORD: database.getCredentials().getImport("password"),
94
+ * }
95
+ * // Runtime (app):
96
+ * const u = new URL(process.env.DATABASE_URL_BASE);
97
+ * u.username = process.env.DATABASE_USER;
98
+ * u.password = process.env.DATABASE_PASSWORD;
99
+ * const finalUrl = u.toString();
100
+ */
101
+ getConnectionString(): string;
51
102
  /** Get the database name. */
52
103
  getDatabaseName(): string;
53
104
  /** Get the database credentials secret (Fjall Secret wrapper with getImport() support). */
54
105
  getCredentials(): Secret;
106
+ /**
107
+ * Discriminated snapshot target. Instance variants return
108
+ * `{ kind: "instance", arn }`; cluster variants return
109
+ * `{ kind: "cluster", arn }`. Consumers branch on `kind` to choose between
110
+ * `rds:CreateDBSnapshot` and `rds:CreateDBClusterSnapshot`.
111
+ */
112
+ getSnapshotTarget(): SnapshotTarget;
113
+ /**
114
+ * Returns the IAM PolicyStatement granting the migration runner the rights
115
+ * needed to take and tag a pre-migration snapshot of this database. Action
116
+ * triple and resource ARN segment derive from `this.getSnapshotTarget().kind`.
117
+ * Snapshot name glob is bound to `MIGRATION_SNAPSHOT_NAME_PREFIX`.
118
+ */
119
+ getMigrationSnapshotPolicy(): PolicyStatement;
120
+ /**
121
+ * Returns the migration configuration declared on this database, or
122
+ * `undefined` if the user did not declare one. When set, every container
123
+ * of every service in this database's `connections:` graph receives an
124
+ * `EXPECTED_SCHEMA_VERSION` env entry (unless service-level
125
+ * `schemaGate: false`).
126
+ */
127
+ getMigrationsConfig(): MigrationsConfig | undefined;
128
+ /**
129
+ * Resolves `migrations.dir` via the tool's resolver at synth time. Returns
130
+ * `undefined` when no `migrations:` was declared. Throws when declared
131
+ * but the directory is empty / unreadable / contains no matching entries
132
+ * — fail loud, never silent.
133
+ */
134
+ getExpectedSchemaVersion(): string | undefined;
55
135
  /**
56
136
  * Grant connect permissions to a grantee.
57
137
  * This adds the grantee to the database security group.
@@ -59,11 +139,39 @@ export interface IRelationalDatabase extends IDatabase, IConnectable {
59
139
  */
60
140
  grantConnect(grantee: IConnectable): void;
61
141
  }
142
+ /**
143
+ * Single-instance RDS variant. Exposes the instance identifier directly and
144
+ * narrows `getSnapshotTarget()` to the `"instance"` arm of the discriminated union.
145
+ */
146
+ export interface IRelationalInstanceDatabase extends IRelationalDatabaseBase {
147
+ /** RDS DB instance identifier for `rds:CreateDBSnapshot`. */
148
+ getInstanceIdentifier(): string;
149
+ getSnapshotTarget(): Extract<SnapshotTarget, {
150
+ kind: "instance";
151
+ }>;
152
+ }
153
+ /**
154
+ * Aurora cluster variant (regional or global). Exposes the cluster identifier
155
+ * directly and narrows `getSnapshotTarget()` to the `"cluster"` arm.
156
+ */
157
+ export interface IRelationalClusterDatabase extends IRelationalDatabaseBase {
158
+ /** RDS DB cluster identifier for `rds:CreateDBClusterSnapshot`. */
159
+ getClusterIdentifier(): string;
160
+ getSnapshotTarget(): Extract<SnapshotTarget, {
161
+ kind: "cluster";
162
+ }>;
163
+ }
164
+ /**
165
+ * Relational database interface — discriminated union of the variant
166
+ * interfaces. Consumers either narrow on `databaseType` (or via `kind` after
167
+ * `getSnapshotTarget()`), or accept the union and branch exhaustively.
168
+ */
169
+ export type IRelationalDatabase = IRelationalInstanceDatabase | IRelationalClusterDatabase;
62
170
  /**
63
171
  * DynamoDB database interface.
64
172
  * Provides access to table-specific methods and IAM grants.
65
173
  */
66
- export interface IDynamoDBDatabase extends IDatabase {
174
+ export interface IDynamoDBDatabase extends IDatabase, IMigrationContributor {
67
175
  readonly databaseType: "DynamoDB";
68
176
  /** Get the table name. */
69
177
  getTableName(): string;
@@ -99,11 +207,78 @@ export interface IDynamoDBDatabase extends IDatabase {
99
207
  */
100
208
  grantStreamRead(grantee: IGrantable): Grant;
101
209
  }
210
+ /**
211
+ * ClickHouse analytics database interface.
212
+ *
213
+ * Per the 2026-05-14 Phase 4b `users:` prop iteration, ClickHouse exposes
214
+ * its workload users via the `users:` construct prop. Consumers look them
215
+ * up by name via `getUser(name)` — there are no typed accessors for
216
+ * specific roles.
217
+ *
218
+ * Cold-tier bucket access is conditional: `getColdTierBucket()` returns
219
+ * `undefined` when the user disabled the cold tier via `coldTier: false`
220
+ * (per D12 + D19).
221
+ */
222
+ export interface IClickHouseDatabase extends IDatabase, IConnectable, IMigrationContributor {
223
+ readonly databaseType: "ClickHouse";
224
+ /**
225
+ * Returns the Fjall `Secret` wrapper for the named user. Throws with a
226
+ * `Known users:` list if the name is not present in the `users:` prop.
227
+ */
228
+ getUser(name: string): Secret;
229
+ /**
230
+ * Returns the Fjall `Secret` wrapper for the named user, or `undefined`
231
+ * when the user is not declared. Use for optional secret contributions
232
+ * (e.g. `SCHEMA_ADMIN_PASSWORD` only when a `schema_admin` user exists).
233
+ */
234
+ tryGetUser(name: string): Secret | undefined;
235
+ /**
236
+ * Wires a task definition to connect to ClickHouse as `opts.user` (if
237
+ * supplied). Adds `CLICKHOUSE_URL` / `CLICKHOUSE_DATABASE` env vars to the
238
+ * task's default container; when `opts.user` is set, also adds
239
+ * `CLICKHOUSE_USER` (plain env) and `CLICKHOUSE_PASSWORD` (Secrets
240
+ * Manager-backed). Callers separately call `grantConnect(service)` on the
241
+ * resulting ECS service for the network grant.
242
+ */
243
+ connectFromTask(task: TaskDefinition, opts?: {
244
+ user?: string;
245
+ }): void;
246
+ /** HTTP port (typically 8123). */
247
+ getHttpPort(): number;
248
+ /** Native TCP port (typically 9000). */
249
+ getNativePort(): number;
250
+ /**
251
+ * HTTP URL for clickhouse-client / chproxy (`http://<host>:<httpPort>`).
252
+ * No credentials in the URL — ClickHouse HTTP uses Basic Auth headers or
253
+ * `X-ClickHouse-User`/`X-ClickHouse-Key` headers. Compose creds at runtime
254
+ * via `getUser(name).getImport(...)`.
255
+ */
256
+ getHttpUrl(): string;
257
+ /**
258
+ * Native TCP URL (`tcp://<host>:<nativePort>`).
259
+ * No credentials in the URL — the native protocol handshake carries them.
260
+ */
261
+ getNativeUrl(): string;
262
+ /** Get the database host endpoint (Cloud Map FQDN). */
263
+ getHostEndpoint(): string;
264
+ /** Get the database name. */
265
+ getDatabaseName(): string;
266
+ /** Get the backup bucket. */
267
+ getBackupBucket(): IBucket;
268
+ /** Get the cold-tier bucket, or `undefined` when cold-tier storage is disabled. */
269
+ getColdTierBucket(): IBucket | undefined;
270
+ /**
271
+ * Grant connect permissions to a grantee.
272
+ * Adds the grantee to the database security group on both ports.
273
+ * @param grantee The principal to grant connect permissions to
274
+ */
275
+ grantConnect(grantee: IConnectable): void;
276
+ }
102
277
  /**
103
278
  * Union type representing any database interface.
104
279
  * Use with type guards for generic handling.
105
280
  */
106
- export type AnyDatabase = IRelationalDatabase | IDynamoDBDatabase;
281
+ export type AnyDatabase = IRelationalDatabase | IDynamoDBDatabase | IClickHouseDatabase;
107
282
  /**
108
283
  * Type guard to check if a database is relational (Aurora, Instance, GlobalAurora).
109
284
  */
@@ -112,6 +287,10 @@ export declare function isRelationalDatabase(database: IDatabase): database is I
112
287
  * Type guard to check if a database is DynamoDB.
113
288
  */
114
289
  export declare function isDynamoDBDatabase(database: IDatabase): database is IDynamoDBDatabase;
290
+ /**
291
+ * Type guard to check if a database is ClickHouse.
292
+ */
293
+ export declare function isClickHouseDatabase(database: IDatabase): database is IClickHouseDatabase;
115
294
  /**
116
295
  * Type guard to check if a database is Aurora.
117
296
  */
@@ -13,13 +13,21 @@
13
13
  * dynamo.getTableName(); // ✓ Available on IDynamoDBDatabase
14
14
  * dynamo.getHostEndpoint(); // ✗ Compile error - not on IDynamoDBDatabase
15
15
  */
16
+ export { MIGRATION_SNAPSHOT_NAME_PREFIX, EXPECTED_SCHEMA_VERSION_ENV, EXPECTED_SCHEMA_VERSION_TOOL_ENV } from "@fjall/util";
17
+ /**
18
+ * Relational database type discriminator.
19
+ */
20
+ export const RELATIONAL_DATABASE_TYPES = [
21
+ "Aurora",
22
+ "Instance",
23
+ "GlobalAurora"
24
+ ];
25
+ const RELATIONAL_DATABASE_TYPE_SET = new Set(RELATIONAL_DATABASE_TYPES);
16
26
  /**
17
27
  * Type guard to check if a database is relational (Aurora, Instance, GlobalAurora).
18
28
  */
19
29
  export function isRelationalDatabase(database) {
20
- return (database.databaseType === "Aurora" ||
21
- database.databaseType === "Instance" ||
22
- database.databaseType === "GlobalAurora");
30
+ return RELATIONAL_DATABASE_TYPE_SET.has(database.databaseType);
23
31
  }
24
32
  /**
25
33
  * Type guard to check if a database is DynamoDB.
@@ -27,6 +35,12 @@ export function isRelationalDatabase(database) {
27
35
  export function isDynamoDBDatabase(database) {
28
36
  return database.databaseType === "DynamoDB";
29
37
  }
38
+ /**
39
+ * Type guard to check if a database is ClickHouse.
40
+ */
41
+ export function isClickHouseDatabase(database) {
42
+ return database.databaseType === "ClickHouse";
43
+ }
30
44
  /**
31
45
  * Type guard to check if a database is Aurora.
32
46
  */
@@ -5,7 +5,8 @@
5
5
  * factory pattern implementations.
6
6
  */
7
7
  export { type ComputeType, type ICompute, type IEcsCompute, type ILambdaCompute, type IEc2Compute, type AnyCompute, isCompute, isEcsCompute, isLambdaCompute, isEc2Compute } from "./compute.js";
8
- export { type DatabaseType, type RelationalDatabaseType, type IDatabase, type IRelationalDatabase, type IDynamoDBDatabase, type AnyDatabase, isDatabase, isRelationalDatabase, isDynamoDBDatabase, isAuroraDatabase, isInstanceDatabase, isGlobalAuroraDatabase } from "./database.js";
8
+ export { type DatabaseType, type RelationalDatabaseType, type IDatabase, type IRelationalDatabase, type IDynamoDBDatabase, type AnyDatabase, type MigrationsConfig, isDatabase, isRelationalDatabase, isDynamoDBDatabase, isAuroraDatabase, isInstanceDatabase, isGlobalAuroraDatabase, MIGRATION_SNAPSHOT_NAME_PREFIX, EXPECTED_SCHEMA_VERSION_ENV } from "./database.js";
9
+ export { type MigrationContributions, type IMigrationContributor, isMigrationContributor } from "./migrationContributor.js";
9
10
  export { type MessagingType, type IMessaging, type IQueueMessaging, type ITopicMessaging, type IEventBusMessaging, type AnyMessaging, isMessaging, isQueueMessaging, isTopicMessaging, isEventBusMessaging } from "./messaging.js";
10
11
  export { type IStorage, isStorage } from "./storage.js";
11
12
  export { type CdnType, type ICdn, type AnyCdn, isCdn } from "./cdn.js";
@@ -7,7 +7,9 @@
7
7
  // Compute interfaces
8
8
  export { isCompute, isEcsCompute, isLambdaCompute, isEc2Compute } from "./compute.js";
9
9
  // Database interfaces
10
- export { isDatabase, isRelationalDatabase, isDynamoDBDatabase, isAuroraDatabase, isInstanceDatabase, isGlobalAuroraDatabase } from "./database.js";
10
+ export { isDatabase, isRelationalDatabase, isDynamoDBDatabase, isAuroraDatabase, isInstanceDatabase, isGlobalAuroraDatabase, MIGRATION_SNAPSHOT_NAME_PREFIX, EXPECTED_SCHEMA_VERSION_ENV } from "./database.js";
11
+ // Migration contributor (per-resource contribution shape)
12
+ export { isMigrationContributor } from "./migrationContributor.js";
11
13
  // Messaging interfaces
12
14
  export { isMessaging, isQueueMessaging, isTopicMessaging, isEventBusMessaging } from "./messaging.js";
13
15
  // Storage interfaces
@@ -25,6 +25,7 @@ import { type ITopic } from "aws-cdk-lib/aws-sns";
25
25
  import { type IEventBus } from "aws-cdk-lib/aws-events";
26
26
  import { type IGrantable, type Grant } from "aws-cdk-lib/aws-iam";
27
27
  import { type Construct } from "constructs";
28
+ import type { Subscription, SubscriptionProps } from "../../../resources/aws/messaging/subscription.js";
28
29
  export type { IQueue, ITopic, IEventBus };
29
30
  /**
30
31
  * Messaging type discriminator.
@@ -123,6 +124,12 @@ export interface IEventBusMessaging extends IMessaging {
123
124
  * @param grantee The principal to grant put events permissions to
124
125
  */
125
126
  grantPutEventsTo(grantee: IGrantable): Grant;
127
+ /**
128
+ * Add a pub/sub subscription scoped to this bus. The returned `Subscription`
129
+ * handle exposes `getRule()` / `getRuleArn()` / `deadLetterQueue?` per the
130
+ * shared four-member EventBridge surface.
131
+ */
132
+ subscribe(id: string, props: SubscriptionProps): Subscription;
126
133
  }
127
134
  /**
128
135
  * Union type representing any messaging interface.
@@ -0,0 +1,47 @@
1
+ import { type IPeer, type Port } from "aws-cdk-lib/aws-ec2";
2
+ import { type PolicyStatement } from "aws-cdk-lib/aws-iam";
3
+ import { type SecretImport } from "../../../resources/aws/secrets/index.js";
4
+ /**
5
+ * What a resource contributes to a migration task that connects to it.
6
+ *
7
+ * The framework merges contributions from every `IMigrationContributor` in the
8
+ * parent service's `connections:` array and wires the result into the separate
9
+ * migration task definition. Author-explicit values in the service's
10
+ * `migrations:` block win on collision (env / secrets) with a synth warning;
11
+ * `taskRolePolicies` and `egress` are additively merged.
12
+ *
13
+ * Consumed by `synthesiseMigrationTaskDef` at
14
+ * `lib/patterns/aws/computeEcs.ts § synthesiseMigrationTaskDef` via the
15
+ * module-private `collectMigrationContributions` helper.
16
+ */
17
+ export interface MigrationContributions {
18
+ /** Env vars to inject into the migration task's main container. */
19
+ readonly environment?: Record<string, string>;
20
+ /** Secrets-Manager imports to inject. */
21
+ readonly secretsImport?: Record<string, SecretImport>;
22
+ /** IAM policy statements to attach to the migration task role. */
23
+ readonly taskRolePolicies?: readonly PolicyStatement[];
24
+ /**
25
+ * Egress rules to wire from the migration task to this resource. The
26
+ * framework constructs the migration SG (when any contributor has egress)
27
+ * and calls `addEgressRule(peer, port, description)` for each entry.
28
+ */
29
+ readonly egress?: ReadonlyArray<{
30
+ readonly peer: IPeer;
31
+ readonly port: Port;
32
+ readonly description: string;
33
+ }>;
34
+ }
35
+ /**
36
+ * Opt-in structural interface. Resources implement this to declare what they
37
+ * contribute when a migration task connects to them via the parent service's
38
+ * `connections:` array. Return `undefined` to contribute nothing.
39
+ */
40
+ export interface IMigrationContributor {
41
+ getMigrationContributions(): MigrationContributions | undefined;
42
+ }
43
+ /**
44
+ * Structural type guard. Used by `collectMigrationContributions` to dispatch
45
+ * over heterogeneous `connections:` entries.
46
+ */
47
+ export declare function isMigrationContributor(x: unknown): x is IMigrationContributor;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Structural type guard. Used by `collectMigrationContributions` to dispatch
3
+ * over heterogeneous `connections:` entries.
4
+ */
5
+ export function isMigrationContributor(x) {
6
+ return (x !== null &&
7
+ typeof x === "object" &&
8
+ typeof x.getMigrationContributions === "function");
9
+ }
@@ -1,9 +1,12 @@
1
1
  import { type Construct } from "constructs";
2
2
  import { type IGrantable, type Grant } from "aws-cdk-lib/aws-iam";
3
+ import { type IEventBus } from "aws-cdk-lib/aws-events";
3
4
  import type App from "../../app.js";
4
5
  import { SQSQueue } from "../../resources/aws/messaging/sqs.js";
5
- import { SNSTopic } from "../../resources/aws/messaging/sns.js";
6
+ import { SNSTopic, type SNSTopicProps } from "../../resources/aws/messaging/sns.js";
6
7
  import { EventBridgeBus } from "../../resources/aws/messaging/eventbridge.js";
8
+ import { type RemovalPolicyString } from "../../resources/aws/messaging/utils.js";
9
+ import { Subscription, type SubscriptionProps } from "../../resources/aws/messaging/subscription.js";
7
10
  import { type IQueueMessaging, type ITopicMessaging, type IEventBusMessaging, type AnyMessaging } from "./interfaces/messaging.js";
8
11
  import { type IQueueConnector } from "./interfaces/connector.js";
9
12
  /**
@@ -27,19 +30,16 @@ export interface IQueueProps {
27
30
  contentBasedDeduplication?: boolean;
28
31
  fifoThroughputLimit?: "perQueue" | "perMessageGroupId";
29
32
  deduplicationScope?: "queue" | "messageGroup";
30
- removalPolicy?: "DESTROY" | "RETAIN";
33
+ removalPolicy?: RemovalPolicyString;
31
34
  }
32
35
  /**
33
- * Topic messaging props with type discriminator.
36
+ * Topic messaging props with type discriminator. Extends SNSTopicProps so the
37
+ * pattern surface stays in lockstep with the resource — adding a field to
38
+ * SNSTopicProps automatically reaches the pattern entrypoint.
34
39
  */
35
- export interface ITopicProps {
40
+ export interface ITopicProps extends SNSTopicProps {
36
41
  /** Type discriminator for messaging type. */
37
42
  type: "topic";
38
- topicName?: string;
39
- displayName?: string;
40
- fifo?: boolean;
41
- contentBasedDeduplication?: boolean;
42
- removalPolicy?: "DESTROY" | "RETAIN";
43
43
  }
44
44
  /**
45
45
  * EventBus messaging props with type discriminator.
@@ -48,7 +48,24 @@ export interface IEventBusProps {
48
48
  /** Type discriminator for messaging type. */
49
49
  type: "eventBus";
50
50
  eventBusName?: string;
51
- removalPolicy?: "DESTROY" | "RETAIN";
51
+ appName?: string;
52
+ description?: string;
53
+ removalPolicy?: RemovalPolicyString;
54
+ /**
55
+ * Internal: forwarded to `EventBridgeBusProps.importedBus` so
56
+ * `EventBusMessaging.fromEventBusArn(...)` skips creating a fresh
57
+ * `AWS::Events::EventBus`. Per D19 the wrapper holds the imported handle
58
+ * and bus-level mutations are no-ops.
59
+ */
60
+ importedBus?: IEventBus;
61
+ /**
62
+ * Internal: marks the wrapper as targeting the AWS-managed account+region
63
+ * default bus rather than a custom Fjall app bus. Set by
64
+ * `EventBusMessaging.fromAwsServiceBus(...)`. Disables the `aws.*`
65
+ * source-pattern guard on `subscribe(...)` since AWS service events fire
66
+ * only on the default bus.
67
+ */
68
+ awsServiceBus?: boolean;
52
69
  }
53
70
  /**
54
71
  * Union type for all messaging props.
@@ -114,6 +131,7 @@ export declare class TopicMessaging extends SNSTopic implements ITopicMessaging
114
131
  * Provides grant methods and Fjall patterns for event-driven messaging.
115
132
  */
116
133
  export declare class EventBusMessaging extends EventBridgeBus implements IEventBusMessaging {
134
+ #private;
117
135
  /** Type discriminator for runtime type narrowing. */
118
136
  readonly messagingType: "eventBus";
119
137
  constructor(scope: Construct, id: string, props: IEventBusProps);
@@ -122,6 +140,43 @@ export declare class EventBusMessaging extends EventBridgeBus implements IEventB
122
140
  * Implements IEventBusMessaging.grantPutEventsTo.
123
141
  */
124
142
  grantPutEventsTo(grantee: IGrantable): Grant;
143
+ /**
144
+ * Add a pub/sub subscription scoped to this bus. Threads the bus's
145
+ * `IEventBus` and the captured `appName` into the Subscription so the
146
+ * synthesised rule attaches to this bus (not the default AWS bus) and the
147
+ * default description picks up the bus's app context.
148
+ *
149
+ * Refuses `aws.*` source patterns when the wrapper is an app bus rather
150
+ * than the AWS-managed default bus. AWS service events fire only on the
151
+ * account+region default bus; subscribing them on a custom app bus
152
+ * synthesises and deploys cleanly but never invokes the target. Use
153
+ * `EventBusMessaging.fromAwsServiceBus(...)` to import the default bus
154
+ * for AWS service event traffic.
155
+ */
156
+ subscribe(id: string, props: SubscriptionProps): Subscription;
157
+ /**
158
+ * Wrap a bus imported from another account/region by ARN per D19. The
159
+ * returned handle supports `subscribe(...)` identically to created buses;
160
+ * rules are owned by the importing stack and attach to the imported bus's
161
+ * ARN. The base wrapper short-circuits resource creation when `importedBus`
162
+ * is set, so no `AWS::Events::EventBus` is synthesised and bus-level
163
+ * mutations (description, removalPolicy, CfnOutputs) are skipped.
164
+ */
165
+ static fromEventBusArn(scope: Construct, id: string, arn: string): EventBusMessaging;
166
+ /**
167
+ * Wrap the AWS-managed account+region `default` event bus. This is the
168
+ * bus that receives `aws.*` service events emitted via CloudTrail
169
+ * (`aws.ecr` `CreateRepository`, `aws.ec2` state-change, etc.); custom
170
+ * Fjall app buses do not receive this traffic. The returned wrapper has
171
+ * the AWS-service brand set, so `subscribe(...)` accepts `aws.*` source
172
+ * patterns; subscribing app-source patterns is still allowed but
173
+ * unusual (the canonical app-source path is `app.getEventBus()`).
174
+ *
175
+ * @param region AWS region holding the default bus (typically the stack
176
+ * region — the default bus is per-account-per-region).
177
+ * @param account AWS account id holding the default bus.
178
+ */
179
+ static fromAwsServiceBus(scope: Construct, id: string, region: string, account: string): EventBusMessaging;
125
180
  }
126
181
  /**
127
182
  * Factory for creating messaging resources.
@@ -179,5 +234,6 @@ export declare class MessagingFactory {
179
234
  export type { SQSQueueProps } from "../../resources/aws/messaging/sqs.js";
180
235
  export type { SNSTopicProps } from "../../resources/aws/messaging/sns.js";
181
236
  export type { EventBridgeBusProps } from "../../resources/aws/messaging/eventbridge.js";
237
+ export { EventField, RuleTargetInput, type EventPattern } from "aws-cdk-lib/aws-events";
182
238
  export type { IQueueMessaging, ITopicMessaging, IEventBusMessaging, AnyMessaging, IQueue, ITopic, IEventBus } from "./interfaces/messaging.js";
183
239
  export { isQueueMessaging, isTopicMessaging, isEventBusMessaging } from "./interfaces/messaging.js";