@fjall/components-infrastructure 0.86.0 → 0.87.3
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.
- package/README.md +3 -3
- package/dist/lib/app.d.ts +166 -6
- package/dist/lib/app.js +212 -20
- package/dist/lib/aspects/resourceInventory.d.ts +4 -4
- package/dist/lib/aspects/resourceInventory.js +3 -3
- package/dist/lib/config/aws/backupGlobalSettings.js +1 -2
- package/dist/lib/config/aws/identityCenter.js +1 -5
- package/dist/lib/config/aws/organisation.js +1 -4
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.js +7 -1
- package/dist/lib/patterns/aws/buildkite.js +3 -2
- package/dist/lib/patterns/aws/cdn.d.ts +164 -0
- package/dist/lib/patterns/aws/cdn.js +264 -0
- package/dist/lib/patterns/aws/compute.d.ts +278 -59
- package/dist/lib/patterns/aws/compute.js +384 -188
- package/dist/lib/patterns/aws/connections.d.ts +46 -0
- package/dist/lib/patterns/aws/connections.js +159 -0
- package/dist/lib/patterns/aws/database.d.ts +124 -11
- package/dist/lib/patterns/aws/database.js +188 -66
- package/dist/lib/patterns/aws/hostedZone.js +1 -1
- package/dist/lib/patterns/aws/index.d.ts +3 -0
- package/dist/lib/patterns/aws/index.js +4 -1
- package/dist/lib/patterns/aws/interfaces/compute.d.ts +121 -0
- package/dist/lib/patterns/aws/interfaces/compute.js +48 -0
- package/dist/lib/patterns/aws/interfaces/connector.d.ts +183 -0
- package/dist/lib/patterns/aws/interfaces/connector.js +117 -0
- package/dist/lib/patterns/aws/interfaces/database.d.ts +136 -0
- package/dist/lib/patterns/aws/interfaces/database.js +65 -0
- package/dist/lib/patterns/aws/interfaces/index.d.ts +12 -0
- package/dist/lib/patterns/aws/interfaces/index.js +49 -0
- package/dist/lib/patterns/aws/interfaces/messaging.d.ts +146 -0
- package/dist/lib/patterns/aws/interfaces/messaging.js +56 -0
- package/dist/lib/patterns/aws/interfaces/pattern.d.ts +403 -0
- package/dist/lib/patterns/aws/interfaces/pattern.js +36 -0
- package/dist/lib/patterns/aws/interfaces/storage.d.ts +136 -0
- package/dist/lib/patterns/aws/interfaces/storage.js +48 -0
- package/dist/lib/patterns/aws/messaging.d.ts +183 -0
- package/dist/lib/patterns/aws/messaging.js +239 -0
- package/dist/lib/patterns/aws/network.js +4 -4
- package/dist/lib/patterns/aws/pattern.d.ts +67 -0
- package/dist/lib/patterns/aws/pattern.js +69 -0
- package/dist/lib/patterns/aws/payload.d.ts +87 -0
- package/dist/lib/patterns/aws/payload.js +526 -0
- package/dist/lib/patterns/aws/storage.d.ts +127 -15
- package/dist/lib/patterns/aws/storage.js +234 -38
- package/dist/lib/resources/aws/backup/backupPlan.js +1 -6
- package/dist/lib/resources/aws/backup/backupVault.js +1 -2
- package/dist/lib/resources/aws/base/awsStack.d.ts +0 -2
- package/dist/lib/resources/aws/base/awsStack.js +1 -7
- package/dist/lib/resources/aws/cdn/cloudFront.d.ts +71 -0
- package/dist/lib/resources/aws/cdn/cloudFront.js +176 -0
- package/dist/lib/resources/aws/cdn/index.d.ts +1 -0
- package/dist/lib/resources/aws/cdn/index.js +18 -0
- package/dist/lib/resources/aws/compute/ec2.d.ts +5 -0
- package/dist/lib/resources/aws/compute/ec2.js +33 -6
- package/dist/lib/resources/aws/compute/ecs.d.ts +32 -25
- package/dist/lib/resources/aws/compute/ecs.js +31 -115
- package/dist/lib/resources/aws/compute/lambda.d.ts +94 -5
- package/dist/lib/resources/aws/compute/lambda.js +209 -32
- package/dist/lib/resources/aws/database/database.js +1 -1
- package/dist/lib/resources/aws/database/dynamodb.d.ts +70 -0
- package/dist/lib/resources/aws/database/dynamodb.js +181 -0
- package/dist/lib/resources/aws/database/index.d.ts +1 -0
- package/dist/lib/resources/aws/database/index.js +2 -1
- package/dist/lib/resources/aws/database/migrationLambda.d.ts +80 -0
- package/dist/lib/resources/aws/database/migrationLambda.js +119 -0
- package/dist/lib/resources/aws/database/rdsAurora.d.ts +15 -0
- package/dist/lib/resources/aws/database/rdsAurora.js +41 -18
- package/dist/lib/resources/aws/database/rdsAuroraGlobal.js +12 -8
- package/dist/lib/resources/aws/database/rdsInstance.js +2 -2
- package/dist/lib/resources/aws/index.d.ts +2 -0
- package/dist/lib/resources/aws/index.js +3 -1
- package/dist/lib/resources/aws/messaging/eventbridge.d.ts +28 -0
- package/dist/lib/resources/aws/messaging/eventbridge.js +53 -0
- package/dist/lib/resources/aws/messaging/index.d.ts +3 -0
- package/dist/lib/resources/aws/messaging/index.js +20 -0
- package/dist/lib/resources/aws/messaging/sns.d.ts +35 -0
- package/dist/lib/resources/aws/messaging/sns.js +70 -0
- package/dist/lib/resources/aws/messaging/sqs.d.ts +105 -0
- package/dist/lib/resources/aws/messaging/sqs.js +231 -0
- package/dist/lib/resources/aws/messaging/utils.d.ts +3 -0
- package/dist/lib/resources/aws/messaging/utils.js +7 -0
- package/dist/lib/resources/aws/networking/ipam.js +1 -2
- package/dist/lib/resources/aws/networking/ipamPool.js +3 -2
- package/dist/lib/resources/aws/networking/vpc.js +1 -2
- package/dist/lib/resources/aws/storage/ecr.js +8 -5
- package/dist/lib/resources/aws/storage/s3.js +1 -2
- package/dist/lib/resources/aws/utilities/awsCustomResource.js +1 -1
- package/dist/lib/resources/aws/utilities/customResource.js +1 -1
- package/dist/lib/utils/getConfig.js +3 -2
- package/dist/lib/utils/index.d.ts +1 -0
- package/dist/lib/utils/index.js +2 -1
- package/dist/lib/utils/manifestWriter.d.ts +174 -0
- package/dist/lib/utils/manifestWriter.js +233 -0
- package/dist/lib/utils/standardTagsAspect.js +1 -8
- package/dist/lib/utils/validationLogger.d.ts +34 -0
- package/dist/lib/utils/validationLogger.js +83 -0
- package/package.json +3 -3
- package/dist/lib/__tests__/setup.d.ts +0 -48
- package/dist/lib/__tests__/setup.js +0 -1
- package/dist/lib/patterns/aws/cicdRole.d.ts +0 -67
- package/dist/lib/patterns/aws/cicdRole.js +0 -68
- package/dist/lib/resources/aws/cicd/cicdRole.d.ts +0 -65
- package/dist/lib/resources/aws/cicd/cicdRole.js +0 -191
- package/dist/lib/resources/aws/compute/ecsFreeTier.d.ts +0 -75
- package/dist/lib/resources/aws/compute/ecsFreeTier.js +0 -1
- package/dist/lib/resources/aws/compute/ecsSpot.d.ts +0 -75
- package/dist/lib/resources/aws/compute/ecsSpot.js +0 -1
- package/dist/lib/resources/aws/compute/utilities/capacityProviderDrainWaiter.d.ts +0 -20
- package/dist/lib/resources/aws/compute/utilities/capacityProviderDrainWaiter.js +0 -1
- package/dist/lib/resources/aws/utilities/cfnOutput.d.ts +0 -5
- package/dist/lib/resources/aws/utilities/cfnOutput.js +0 -1
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared connection processor for unified connector interface.
|
|
3
|
+
*
|
|
4
|
+
* This module provides the `processConnections` function that handles
|
|
5
|
+
* both security group rules (IConnectable) and IAM grants (IGrantable)
|
|
6
|
+
* in a unified way.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* // In ECS service setup
|
|
10
|
+
* processConnections(
|
|
11
|
+
* serviceProps.connections,
|
|
12
|
+
* serviceData.taskRole, // IGrantable for IAM
|
|
13
|
+
* service // IConnectable for security groups
|
|
14
|
+
* );
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* // In Lambda setup
|
|
18
|
+
* processConnections(
|
|
19
|
+
* props.connections,
|
|
20
|
+
* this.lambdaFunction, // IGrantable (execution role)
|
|
21
|
+
* this.lambdaFunction // IConnectable (security group)
|
|
22
|
+
* );
|
|
23
|
+
*/
|
|
24
|
+
import { type IConnectable } from "aws-cdk-lib/aws-ec2";
|
|
25
|
+
import { type IGrantable } from "aws-cdk-lib/aws-iam";
|
|
26
|
+
import { type ConnectionSpec, type ConnectionResult } from "./interfaces/connector.js";
|
|
27
|
+
/**
|
|
28
|
+
* Process connections from compute resources to data resources.
|
|
29
|
+
*
|
|
30
|
+
* Handles the unified connector interface, dispatching to:
|
|
31
|
+
* - Security group rules for IConnectable and ISecurityGroupConnector resources
|
|
32
|
+
* - IAM grants for IStorageConnector, IDynamoDBConnector, and IQueueConnector resources
|
|
33
|
+
*
|
|
34
|
+
* @param connections - Array of connection specifications
|
|
35
|
+
* @param grantee - The IAM grantee (task role, execution role, etc.)
|
|
36
|
+
* @param connectable - Optional IConnectable for security group rules
|
|
37
|
+
* @returns Array of connection results
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* processConnections(
|
|
41
|
+
* [database, { resource: bucket, access: "read" }, queue],
|
|
42
|
+
* taskRole,
|
|
43
|
+
* service
|
|
44
|
+
* );
|
|
45
|
+
*/
|
|
46
|
+
export declare function processConnections(connections: ConnectionSpec[], grantee: IGrantable, connectable?: IConnectable): ConnectionResult[];
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Shared connection processor for unified connector interface.
|
|
4
|
+
*
|
|
5
|
+
* This module provides the `processConnections` function that handles
|
|
6
|
+
* both security group rules (IConnectable) and IAM grants (IGrantable)
|
|
7
|
+
* in a unified way.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* // In ECS service setup
|
|
11
|
+
* processConnections(
|
|
12
|
+
* serviceProps.connections,
|
|
13
|
+
* serviceData.taskRole, // IGrantable for IAM
|
|
14
|
+
* service // IConnectable for security groups
|
|
15
|
+
* );
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* // In Lambda setup
|
|
19
|
+
* processConnections(
|
|
20
|
+
* props.connections,
|
|
21
|
+
* this.lambdaFunction, // IGrantable (execution role)
|
|
22
|
+
* this.lambdaFunction // IConnectable (security group)
|
|
23
|
+
* );
|
|
24
|
+
*/
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.processConnections = processConnections;
|
|
27
|
+
const connector_js_1 = require("./interfaces/connector.js");
|
|
28
|
+
/** Default access levels for each connector type. */
|
|
29
|
+
const DEFAULT_ACCESS = {
|
|
30
|
+
storage: "readWrite",
|
|
31
|
+
dynamodb: "readWrite",
|
|
32
|
+
queue: "full"
|
|
33
|
+
};
|
|
34
|
+
/** Grant storage access based on access level. */
|
|
35
|
+
function processStorageConnection(connector, grantee, access) {
|
|
36
|
+
switch (access) {
|
|
37
|
+
case "read":
|
|
38
|
+
return connector.grantRead(grantee);
|
|
39
|
+
case "write":
|
|
40
|
+
return connector.grantWrite(grantee);
|
|
41
|
+
case "readWrite":
|
|
42
|
+
return connector.grantReadWrite(grantee);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/** Grant DynamoDB access based on access level. */
|
|
46
|
+
function processDynamoDBConnection(connector, grantee, access) {
|
|
47
|
+
switch (access) {
|
|
48
|
+
case "read":
|
|
49
|
+
return connector.grantReadData(grantee);
|
|
50
|
+
case "write":
|
|
51
|
+
return connector.grantWriteData(grantee);
|
|
52
|
+
case "readWrite":
|
|
53
|
+
return connector.grantReadWriteData(grantee);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** Grant queue access based on access level. */
|
|
57
|
+
function processQueueConnection(connector, grantee, access) {
|
|
58
|
+
switch (access) {
|
|
59
|
+
case "send":
|
|
60
|
+
return connector.grantSendMessages(grantee);
|
|
61
|
+
case "consume":
|
|
62
|
+
return connector.grantConsumeMessages(grantee);
|
|
63
|
+
case "full":
|
|
64
|
+
return connector.grantFull(grantee);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/** Build an IAM connection result. */
|
|
68
|
+
function buildIamResult(connector, grant) {
|
|
69
|
+
return { resource: connector, grant, connectionType: connector_js_1.CONNECTION_TYPE.IAM };
|
|
70
|
+
}
|
|
71
|
+
/** Build a security group connection result. */
|
|
72
|
+
function buildSecurityGroupResult(resource) {
|
|
73
|
+
return { resource, connectionType: connector_js_1.CONNECTION_TYPE.SECURITY_GROUP };
|
|
74
|
+
}
|
|
75
|
+
/** Validate and narrow access type for storage/dynamodb connectors. */
|
|
76
|
+
function validateConnectionAccess(access, connectorType, defaultAccess) {
|
|
77
|
+
if (access === undefined)
|
|
78
|
+
return defaultAccess;
|
|
79
|
+
if ((0, connector_js_1.isConnectionAccess)(access))
|
|
80
|
+
return access;
|
|
81
|
+
throw new Error(`Invalid access "${access}" for ${connectorType} connector. ` +
|
|
82
|
+
`Valid values: read, write, readWrite`);
|
|
83
|
+
}
|
|
84
|
+
/** Validate and narrow access type for queue connectors. */
|
|
85
|
+
function validateMessagingAccess(access, defaultAccess) {
|
|
86
|
+
if (access === undefined)
|
|
87
|
+
return defaultAccess;
|
|
88
|
+
if ((0, connector_js_1.isMessagingAccess)(access))
|
|
89
|
+
return access;
|
|
90
|
+
throw new Error(`Invalid access "${access}" for queue connector. ` +
|
|
91
|
+
`Valid values: send, consume, full`);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Require IConnectable for security group operations.
|
|
95
|
+
* Throws a descriptive error if not provided.
|
|
96
|
+
*/
|
|
97
|
+
function requireConnectable(connectable, context) {
|
|
98
|
+
if (!connectable) {
|
|
99
|
+
throw new Error(`${context} requires an IConnectable to be provided. ` +
|
|
100
|
+
"Ensure the compute resource (ECS, EC2, Lambda with VPC) implements IConnectable.");
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Process connections from compute resources to data resources.
|
|
105
|
+
*
|
|
106
|
+
* Handles the unified connector interface, dispatching to:
|
|
107
|
+
* - Security group rules for IConnectable and ISecurityGroupConnector resources
|
|
108
|
+
* - IAM grants for IStorageConnector, IDynamoDBConnector, and IQueueConnector resources
|
|
109
|
+
*
|
|
110
|
+
* @param connections - Array of connection specifications
|
|
111
|
+
* @param grantee - The IAM grantee (task role, execution role, etc.)
|
|
112
|
+
* @param connectable - Optional IConnectable for security group rules
|
|
113
|
+
* @returns Array of connection results
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* processConnections(
|
|
117
|
+
* [database, { resource: bucket, access: "read" }, queue],
|
|
118
|
+
* taskRole,
|
|
119
|
+
* service
|
|
120
|
+
* );
|
|
121
|
+
*/
|
|
122
|
+
function processConnections(connections, grantee, connectable) {
|
|
123
|
+
return connections.map((spec) => {
|
|
124
|
+
const { resource, access } = (0, connector_js_1.isConnectionConfig)(spec)
|
|
125
|
+
? { resource: spec.resource, access: spec.access }
|
|
126
|
+
: { resource: spec, access: undefined };
|
|
127
|
+
// Handle unified connector interface (isConnector now returns AnyConnector)
|
|
128
|
+
if ((0, connector_js_1.isConnector)(resource)) {
|
|
129
|
+
switch (resource.connectorType) {
|
|
130
|
+
case "storage": {
|
|
131
|
+
const validAccess = validateConnectionAccess(access, "storage", DEFAULT_ACCESS.storage);
|
|
132
|
+
return buildIamResult(resource, processStorageConnection(resource, grantee, validAccess));
|
|
133
|
+
}
|
|
134
|
+
case "dynamodb": {
|
|
135
|
+
const validAccess = validateConnectionAccess(access, "dynamodb", DEFAULT_ACCESS.dynamodb);
|
|
136
|
+
return buildIamResult(resource, processDynamoDBConnection(resource, grantee, validAccess));
|
|
137
|
+
}
|
|
138
|
+
case "queue": {
|
|
139
|
+
const validAccess = validateMessagingAccess(access, DEFAULT_ACCESS.queue);
|
|
140
|
+
return buildIamResult(resource, processQueueConnection(resource, grantee, validAccess));
|
|
141
|
+
}
|
|
142
|
+
case "securityGroup":
|
|
143
|
+
case "relational": {
|
|
144
|
+
requireConnectable(connectable, `${resource.connectorType} connector`);
|
|
145
|
+
connectable.connections.allowToDefaultPort(resource);
|
|
146
|
+
return buildSecurityGroupResult(resource);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// Legacy IConnectable path
|
|
151
|
+
if ((0, connector_js_1.isConnectable)(resource)) {
|
|
152
|
+
requireConnectable(connectable, "IConnectable resource");
|
|
153
|
+
connectable.connections.allowToDefaultPort(resource);
|
|
154
|
+
return buildSecurityGroupResult(resource);
|
|
155
|
+
}
|
|
156
|
+
throw new Error("Connection resource must be either an IConnector or IConnectable");
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29ubmVjdGlvbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9saWIvcGF0dGVybnMvYXdzL2Nvbm5lY3Rpb25zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXNCRzs7QUF5SkgsZ0RBdUVDO0FBNU5ELDREQWVtQztBQUVuQyxxREFBcUQ7QUFDckQsTUFBTSxjQUFjLEdBQUc7SUFDckIsT0FBTyxFQUFFLFdBQVc7SUFDcEIsUUFBUSxFQUFFLFdBQVc7SUFDckIsS0FBSyxFQUFFLE1BQU07Q0FDTCxDQUFDO0FBRVgsa0RBQWtEO0FBQ2xELFNBQVMsd0JBQXdCLENBQy9CLFNBQTRCLEVBQzVCLE9BQW1CLEVBQ25CLE1BQXdCO0lBRXhCLFFBQVEsTUFBTSxFQUFFLENBQUM7UUFDZixLQUFLLE1BQU07WUFDVCxPQUFPLFNBQVMsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDdEMsS0FBSyxPQUFPO1lBQ1YsT0FBTyxTQUFTLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3ZDLEtBQUssV0FBVztZQUNkLE9BQU8sU0FBUyxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUM3QyxDQUFDO0FBQ0gsQ0FBQztBQUVELG1EQUFtRDtBQUNuRCxTQUFTLHlCQUF5QixDQUNoQyxTQUE2QixFQUM3QixPQUFtQixFQUNuQixNQUF3QjtJQUV4QixRQUFRLE1BQU0sRUFBRSxDQUFDO1FBQ2YsS0FBSyxNQUFNO1lBQ1QsT0FBTyxTQUFTLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzFDLEtBQUssT0FBTztZQUNWLE9BQU8sU0FBUyxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMzQyxLQUFLLFdBQVc7WUFDZCxPQUFPLFNBQVMsQ0FBQyxrQkFBa0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNqRCxDQUFDO0FBQ0gsQ0FBQztBQUVELGdE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QUMsQ0FBQztRQUM1QyxDQUFDO1FBRUQsTUFBTSxJQUFJLEtBQUssQ0FDYixrRUFBa0UsQ0FDbkUsQ0FBQztJQUNKLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogU2hhcmVkIGNvbm5lY3Rpb24gcHJvY2Vzc29yIGZvciB1bmlmaWVkIGNvbm5lY3RvciBpbnRlcmZhY2UuXG4gKlxuICogVGhpcyBtb2R1bGUgcHJvdmlkZXMgdGhlIGBwcm9jZXNzQ29ubmVjdGlvbnNgIGZ1bmN0aW9uIHRoYXQgaGFuZGxlc1xuICogYm90aCBzZWN1cml0eSBncm91cCBydWxlcyAoSUNvbm5lY3RhYmxlKSBhbmQgSUFNIGdyYW50cyAoSUdyYW50YWJsZSlcbiAqIGluIGEgdW5pZmllZCB3YXkuXG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIEluIEVDUyBzZXJ2aWNlIHNldHVwXG4gKiBwcm9jZXNzQ29ubmVjdGlvbnMoXG4gKiAgIHNlcnZpY2VQcm9wcy5jb25uZWN0aW9ucyxcbiAqICAgc2VydmljZURhdGEudGFza1JvbGUsICAvLyBJR3JhbnRhYmxlIGZvciBJQU1cbiAqICAgc2VydmljZSAgICAgICAgICAgICAgIC8vIElDb25uZWN0YWJsZSBmb3Igc2VjdXJpdHkgZ3JvdXBzXG4gKiApO1xuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBJbiBMYW1iZGEgc2V0dXBcbiAqIHByb2Nlc3NDb25uZWN0aW9ucyhcbiAqICAgcHJvcHMuY29ubmVjdGlvbnMsXG4gKiAgIHRoaXMubGFtYmRhRnVuY3Rpb24sICAvLyBJR3JhbnRhYmxlIChleGVjdXRpb24gcm9sZSlcbiAqICAgdGhpcy5sYW1iZGFGdW5jdGlvbiAgIC8vIElDb25uZWN0YWJsZSAoc2VjdXJpdHkgZ3JvdXApXG4gKiApO1xuICovXG5cbmltcG9ydCB7IHR5cGUgSUNvbm5lY3RhYmxlIH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1lYzJcIjtcbmltcG9ydCB7IHR5cGUgSUdyYW50YWJsZSwgdHlwZSBHcmFudCB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtaWFtXCI7XG5pbXBvcnQge1xuICB0eXBlIENvbm5lY3Rpb25TcGVjLFxuICB0eXBlIENvbm5lY3Rpb25SZXN1bHQsXG4gIHR5cGUgQ29ubmVjdGlvbkFjY2VzcyxcbiAgdHlwZSBNZXNzYWdpbmdBY2Nlc3MsXG4gIHR5cGUgQW55Q29ubmVjdG9yLFxuICB0eXBlIElTdG9yYWdlQ29ubmVjdG9yLFxuICB0eXBlIElEeW5hbW9EQkNvbm5lY3RvcixcbiAgdHlwZSBJUXVldWVDb25uZWN0b3IsXG4gIENPTk5FQ1RJT05fVFlQRSxcbiAgaXNDb25uZWN0aW9uQ29uZmlnLFxuICBpc0Nvbm5lY3RvcixcbiAgaXNDb25uZWN0YWJsZSxcbiAgaXNDb25uZWN0aW9uQWNjZXNzLFxuICBpc01lc3NhZ2luZ0FjY2Vzc1xufSBmcm9tIFwiLi9pbnRlcmZhY2VzL2Nvbm5lY3Rvci5qc1wiO1xuXG4vKiogRGVmYXVsdCBhY2Nlc3MgbGV2ZWxzIGZvciBlYWNoIGNvbm5lY3RvciB0eXBlLiAqL1xuY29uc3QgREVGQVVMVF9BQ0NFU1MgPSB7XG4gIHN0b3JhZ2U6IFwicmVhZFdyaXRlXCIsXG4gIGR5bmFtb2RiOiBcInJlYWRXcml0ZVwiLFxuICBxdWV1ZTogXCJmdWxsXCJcbn0gYXMgY29uc3Q7XG5cbi8qKiBHcmFudCBzdG9yYWdlIGFjY2VzcyBiYXNlZCBvbiBhY2Nlc3MgbGV2ZWwuICovXG5mdW5jdGlvbiBwcm9jZXNzU3RvcmFnZUNvbm5lY3Rpb24oXG4gIGNvbm5lY3RvcjogSVN0b3JhZ2VDb25uZWN0b3IsXG4gIGdyYW50ZWU6IElHcmFudGFibGUsXG4gIGFjY2VzczogQ29ubmVjdGlvbkFjY2Vzc1xuKTogR3JhbnQge1xuICBzd2l0Y2ggKGFjY2Vzcykge1xuICAgIGNhc2UgXCJyZWFkXCI6XG4gICAgICByZXR1cm4gY29ubmVjdG9yLmdyYW50UmVhZChncmFudGVlKTtcbiAgICBjYXNlIFwid3JpdGVcIjpcbiAgICAgIHJldHVybiBjb25uZWN0b3IuZ3JhbnRXcml0ZShncmFudGVlKTtcbiAgICBjYXNlIFwicmVhZFdyaXRlXCI6XG4gICAgICByZXR1cm4gY29ubmVjdG9yLmdyYW50UmVhZFdyaXRlKGdyYW50ZWUpO1xuICB9XG59XG5cbi8qKiBHcmFudCBEeW5hbW9EQiBhY2Nlc3MgYmFzZWQgb24gYWNjZXNzIGxldmVsLiAqL1xuZnVuY3Rpb24gcHJvY2Vzc0R5bmFtb0RCQ29ubmVjdGlvbihcbiAgY29ubmVjdG9yOiBJRHluYW1vREJDb25uZWN0b3IsXG4gIGdyYW50ZWU6IElHcmFudGFibGUsXG4gIGFjY2VzczogQ29ubmVjdGlvbkFjY2Vzc1xuKTogR3JhbnQge1xuICBzd2l0Y2ggKGFjY2Vzcykge1xuICAgIGNhc2UgXCJyZWFkXCI6XG4gICAgICByZXR1cm4gY29ubmVjdG9yLmdyYW50UmVhZERhdGEoZ3JhbnRlZSk7XG4gICAgY2FzZSBcIndyaXRlXCI6XG4gICAgICByZXR1cm4gY29ubmVjdG9yLmdyYW50V3JpdGVEYXRhKGdyYW50ZWUpO1xuICAgIGNhc2UgXCJyZWFkV3JpdGVcIjpcbiAgICAgIHJldHVybiBjb25uZWN0b3IuZ3JhbnRSZWFkV3JpdGVEYXRhKGdyYW50ZWUpO1xuICB9XG59XG5cbi8qKiBHcmFudCBxdWV1ZSBhY2Nlc3MgYmFzZWQgb24gYWNjZXNzIGxldmVsLiAqL1xuZnVuY3Rpb24gcHJvY2Vzc1F1ZXVlQ29ubmVjdGlvbihcbiAgY29ubmVjdG9yOiBJUXVldWVDb25uZWN0b3IsXG4gIGdyYW50ZWU6IElHcmFudGFibGUsXG4gIGFjY2VzczogTWVzc2FnaW5nQWNjZXNzXG4pOiBHcmFudCB7XG4gIHN3aXRjaCAoYWNjZXNzKSB7XG4gICAgY2FzZSBcInNlbmRcIjpcbiAgICAgIHJldHVybiBjb25uZWN0b3IuZ3JhbnRTZW5kTWVzc2FnZXMoZ3JhbnRlZSk7XG4gICAgY2FzZSBcImNvbnN1bWVcIjpcbiAgICAgIHJldHVybiBjb25uZWN0b3IuZ3JhbnRDb25zdW1lTWVzc2FnZXMoZ3JhbnRlZSk7XG4gICAgY2FzZSBcImZ1bGxcIjpcbiAgICAgIHJldHVybiBjb25uZWN0b3IuZ3JhbnRGdWxsKGdyYW50ZWUpO1xuICB9XG59XG5cbi8qKiBCdWlsZCBhbiBJQU0gY29ubmVjdGlvbiByZXN1bHQuICovXG5mdW5jdGlvbiBidWlsZElhbVJlc3VsdChcbiAgY29ubmVjdG9yOiBBbnlDb25uZWN0b3IsXG4gIGdyYW50OiBHcmFudFxuKTogQ29ubmVjdGlvblJlc3VsdCB7XG4gIHJldHVybiB7IHJlc291cmNlOiBjb25uZWN0b3IsIGdyYW50LCBjb25uZWN0aW9uVHlwZTogQ09OTkVDVElPTl9UWVBFLklBTSB9O1xufVxuXG4vKiogQnVpbGQgYSBzZWN1cml0eSBncm91cCBjb25uZWN0aW9uIHJlc3VsdC4gKi9cbmZ1bmN0aW9uIGJ1aWxkU2VjdXJpdHlHcm91cFJlc3VsdChcbiAgcmVzb3VyY2U6IEFueUNvbm5lY3RvciB8IElDb25uZWN0YWJsZVxuKTogQ29ubmVjdGlvblJlc3VsdCB7XG4gIHJldHVybiB7IHJlc291cmNlLCBjb25uZWN0aW9uVHlwZTogQ09OTkVDVElPTl9UWVBFLlNFQ1VSSVRZX0dST1VQIH07XG59XG5cbi8qKiBWYWxpZGF0ZSBhbmQgbmFycm93IGFjY2VzcyB0eXBlIGZvciBzdG9yYWdlL2R5bmFtb2RiIGNvbm5lY3RvcnMuICovXG5mdW5jdGlvbiB2YWxpZGF0ZUNvbm5lY3Rpb25BY2Nlc3MoXG4gIGFjY2VzczogQ29ubmVjdGlvbkFjY2VzcyB8IE1lc3NhZ2luZ0FjY2VzcyB8IHVuZGVmaW5lZCxcbiAgY29ubmVjdG9yVHlwZTogc3RyaW5nLFxuICBkZWZhdWx0QWNjZXNzOiBDb25uZWN0aW9uQWNjZXNzXG4pOiBDb25uZWN0aW9uQWNjZXNzIHtcbiAgaWYgKGFjY2VzcyA9PT0gdW5kZWZpbmVkKSByZXR1cm4gZGVmYXVsdEFjY2VzcztcbiAgaWYgKGlzQ29ubmVjdGlvbkFjY2VzcyhhY2Nlc3MpKSByZXR1cm4gYWNjZXNzO1xuICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgYEludmFsaWQgYWNjZXNzIFwiJHthY2Nlc3N9XCIgZm9yICR7Y29ubmVjdG9yVHlwZX0gY29ubmVjdG9yLiBgICtcbiAgICAgIGBWYWxpZCB2YWx1ZXM6IHJlYWQsIHdyaXRlLCByZWFkV3JpdGVgXG4gICk7XG59XG5cbi8qKiBWYWxpZGF0ZSBhbmQgbmFycm93IGFjY2VzcyB0eXBlIGZvciBxdWV1ZSBjb25uZWN0b3JzLiAqL1xuZnVuY3Rpb24gdmFsaWRhdGVNZXNzYWdpbmdBY2Nlc3MoXG4gIGFjY2VzczogQ29ubmVjdGlvbkFjY2VzcyB8IE1lc3NhZ2luZ0FjY2VzcyB8IHVuZGVmaW5lZCxcbiAgZGVmYXVsdEFjY2VzczogTWVzc2FnaW5nQWNjZXNzXG4pOiBNZXNzYWdpbmdBY2Nlc3Mge1xuICBpZiAoYWNjZXNzID09PSB1bmRlZmluZWQpIHJldHVybiBkZWZhdWx0QWNjZXNzO1xuICBpZiAoaXNNZXNzYWdpbmdBY2Nlc3MoYWNjZXNzKSkgcmV0dXJuIGFjY2VzcztcbiAgdGhyb3cgbmV3IEVycm9yKFxuICAgIGBJbnZhbGlkIGFjY2VzcyBcIiR7YWNjZXNzfVwiIGZvciBxdWV1ZSBjb25uZWN0b3IuIGAgK1xuICAgICAgYFZhbGlkIHZhbHVlczogc2VuZCwgY29uc3VtZSwgZnVsbGBcbiAgKTtcbn1cblxuLyoqXG4gKiBSZXF1aXJlIElDb25uZWN0YWJsZSBmb3Igc2VjdXJpdHkgZ3JvdXAgb3BlcmF0aW9ucy5cbiAqIFRocm93cyBhIGRlc2NyaXB0aXZlIGVycm9yIGlmIG5vdCBwcm92aWRlZC5cbiAqL1xuZnVuY3Rpb24gcmVxdWlyZUNvbm5lY3RhYmxlKFxuICBjb25uZWN0YWJsZTogSUNvbm5lY3RhYmxlIHwgdW5kZWZpbmVkLFxuICBjb250ZXh0OiBzdHJpbmdcbik6IGFzc2VydHMgY29ubmVjdGFibGUgaXMgSUNvbm5lY3RhYmxlIHtcbiAgaWYgKCFjb25uZWN0YWJsZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGAke2NvbnRleHR9IHJlcXVpcmVzIGFuIElDb25uZWN0YWJsZSB0byBiZSBwcm92aWRlZC4gYCArXG4gICAgICAgIFwiRW5zdXJlIHRoZSBjb21wdXRlIHJlc291cmNlIChFQ1MsIEVDMiwgTGFtYmRhIHdpdGggVlBDKSBpbXBsZW1lbnRzIElDb25uZWN0YWJsZS5cIlxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBQcm9jZXNzIGNvbm5lY3Rpb25zIGZyb20gY29tcHV0ZSByZXNvdXJjZXMgdG8gZGF0YSByZXNvdXJjZXMuXG4gKlxuICogSGFuZGxlcyB0aGUgdW5pZmllZCBjb25uZWN0b3IgaW50ZXJmYWNlLCBkaXNwYXRjaGluZyB0bzpcbiAqIC0gU2VjdXJpdHkgZ3JvdXAgcnVsZXMgZm9yIElDb25uZWN0YWJsZSBhbmQgSVNlY3VyaXR5R3JvdXBDb25uZWN0b3IgcmVzb3VyY2VzXG4gKiAtIElBTSBncmFudHMgZm9yIElTdG9yYWdlQ29ubmVjdG9yLCBJRHluYW1vREJDb25uZWN0b3IsIGFuZCBJUXVldWVDb25uZWN0b3IgcmVzb3VyY2VzXG4gKlxuICogQHBhcmFtIGNvbm5lY3Rpb25zIC0gQXJyYXkgb2YgY29ubmVjdGlvbiBzcGVjaWZpY2F0aW9uc1xuICogQHBhcmFtIGdyYW50ZWUgLSBUaGUgSUFNIGdyYW50ZWUgKHRhc2sgcm9sZSwgZXhlY3V0aW9uIHJvbGUsIGV0Yy4pXG4gKiBAcGFyYW0gY29ubmVjdGFibGUgLSBPcHRpb25hbCBJQ29ubmVjdGFibGUgZm9yIHNlY3VyaXR5IGdyb3VwIHJ1bGVzXG4gKiBAcmV0dXJucyBBcnJheSBvZiBjb25uZWN0aW9uIHJlc3VsdHNcbiAqXG4gKiBAZXhhbXBsZVxuICogcHJvY2Vzc0Nvbm5lY3Rpb25zKFxuICogICBbZGF0YWJhc2UsIHsgcmVzb3VyY2U6IGJ1Y2tldCwgYWNjZXNzOiBcInJlYWRcIiB9LCBxdWV1ZV0sXG4gKiAgIHRhc2tSb2xlLFxuICogICBzZXJ2aWNlXG4gKiApO1xuICovXG5leHBvcnQgZnVuY3Rpb24gcHJvY2Vzc0Nvbm5lY3Rpb25zKFxuICBjb25uZWN0aW9uczogQ29ubmVjdGlvblNwZWNbXSxcbiAgZ3JhbnRlZTogSUdyYW50YWJsZSxcbiAgY29ubmVjdGFibGU/OiBJQ29ubmVjdGFibGVcbik6IENvbm5lY3Rpb25SZXN1bHRbXSB7XG4gIHJldHVybiBjb25uZWN0aW9ucy5tYXAoKHNwZWMpID0+IHtcbiAgICBjb25zdCB7IHJlc291cmNlLCBhY2Nlc3MgfSA9IGlzQ29ubmVjdGlvbkNvbmZpZyhzcGVjKVxuICAgICAgPyB7IHJlc291cmNlOiBzcGVjLnJlc291cmNlLCBhY2Nlc3M6IHNwZWMuYWNjZXNzIH1cbiAgICAgIDogeyByZXNvdXJjZTogc3BlYywgYWNjZXNzOiB1bmRlZmluZWQgfTtcblxuICAgIC8vIEhhbmRsZSB1bmlmaWVkIGNvbm5lY3RvciBpbnRlcmZhY2UgKGlzQ29ubmVjdG9yIG5vdyByZXR1cm5zIEFueUNvbm5lY3RvcilcbiAgICBpZiAoaXNDb25uZWN0b3IocmVzb3VyY2UpKSB7XG4gICAgICBzd2l0Y2ggKHJlc291cmNlLmNvbm5lY3RvclR5cGUpIHtcbiAgICAgICAgY2FzZSBcInN0b3JhZ2VcIjoge1xuICAgICAgICAgIGNvbnN0IHZhbGlkQWNjZXNzID0gdmFsaWRhdGVDb25uZWN0aW9uQWNjZXNzKFxuICAgICAgICAgICAgYWNjZXNzLFxuICAgICAgICAgICAgXCJzdG9yYWdlXCIsXG4gICAgICAgICAgICBERUZBVUxUX0FDQ0VTUy5zdG9yYWdlXG4gICAgICAgICAgKTtcbiAgICAgICAgICByZXR1cm4gYnVpbGRJYW1SZXN1bHQoXG4gICAgICAgICAgICByZXNvdXJjZSxcbiAgICAgICAgICAgIHByb2Nlc3NTdG9yYWdlQ29ubmVjdGlvbihyZXNvdXJjZSwgZ3JhbnRlZSwgdmFsaWRBY2Nlc3MpXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNhc2UgXCJkeW5hbW9kYlwiOiB7XG4gICAgICAgICAgY29uc3QgdmFsaWRBY2Nlc3MgPSB2YWxpZGF0ZUNvbm5lY3Rpb25BY2Nlc3MoXG4gICAgICAgICAgICBhY2Nlc3MsXG4gICAgICAgICAgICBcImR5bmFtb2RiXCIsXG4gICAgICAgICAgICBERUZBVUxUX0FDQ0VTUy5keW5hbW9kYlxuICAgICAgICAgICk7XG4gICAgICAgICAgcmV0dXJuIGJ1aWxkSWFtUmVzdWx0KFxuICAgICAgICAgICAgcmVzb3VyY2UsXG4gICAgICAgICAgICBwcm9jZXNzRHluYW1vREJDb25uZWN0aW9uKHJlc291cmNlLCBncmFudGVlLCB2YWxpZEFjY2VzcylcbiAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgY2FzZSBcInF1ZXVlXCI6IHtcbiAgICAgICAgICBjb25zdCB2YWxpZEFjY2VzcyA9IHZhbGlkYXRlTWVzc2FnaW5nQWNjZXNzKFxuICAgICAgICAgICAgYWNjZXNzLFxuICAgICAgICAgICAgREVGQVVMVF9BQ0NFU1MucXVldWVcbiAgICAgICAgICApO1xuICAgICAgICAgIHJldHVybiBidWlsZElhbVJlc3VsdChcbiAgICAgICAgICAgIHJlc291cmNlLFxuICAgICAgICAgICAgcHJvY2Vzc1F1ZXVlQ29ubmVjdGlvbihyZXNvdXJjZSwgZ3JhbnRlZSwgdmFsaWRBY2Nlc3MpXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNhc2UgXCJzZWN1cml0eUdyb3VwXCI6XG4gICAgICAgIGNhc2UgXCJyZWxhdGlvbmFsXCI6IHtcbiAgICAgICAgICByZXF1aXJlQ29ubmVjdGFibGUoXG4gICAgICAgICAgICBjb25uZWN0YWJsZSxcbiAgICAgICAgICAgIGAke3Jlc291cmNlLmNvbm5lY3RvclR5cGV9IGNvbm5lY3RvcmBcbiAgICAgICAgICApO1xuICAgICAgICAgIGNvbm5lY3RhYmxlLmNvbm5lY3Rpb25zLmFsbG93VG9EZWZhdWx0UG9ydChyZXNvdXJjZSk7XG4gICAgICAgICAgcmV0dXJuIGJ1aWxkU2VjdXJpdHlHcm91cFJlc3VsdChyZXNvdXJjZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBMZWdhY3kgSUNvbm5lY3RhYmxlIHBhdGhcbiAgICBpZiAoaXNDb25uZWN0YWJsZShyZXNvdXJjZSkpIHtcbiAgICAgIHJlcXVpcmVDb25uZWN0YWJsZShjb25uZWN0YWJsZSwgXCJJQ29ubmVjdGFibGUgcmVzb3VyY2VcIik7XG4gICAgICBjb25uZWN0YWJsZS5jb25uZWN0aW9ucy5hbGxvd1RvRGVmYXVsdFBvcnQocmVzb3VyY2UpO1xuICAgICAgcmV0dXJuIGJ1aWxkU2VjdXJpdHlHcm91cFJlc3VsdChyZXNvdXJjZSk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgXCJDb25uZWN0aW9uIHJlc291cmNlIG11c3QgYmUgZWl0aGVyIGFuIElDb25uZWN0b3Igb3IgSUNvbm5lY3RhYmxlXCJcbiAgICApO1xuICB9KTtcbn1cbiJdfQ==
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { Construct } from "constructs";
|
|
2
2
|
import type App from "../../app";
|
|
3
|
-
import { type
|
|
3
|
+
import { type DynamoDBKeySchema, type DynamoDBGlobalSecondaryIndex } from "../../resources/aws/database/dynamodb";
|
|
4
4
|
import { type Connections, type IConnectable, type IVpc, type SubnetSelection } from "aws-cdk-lib/aws-ec2";
|
|
5
|
+
import { type ITable } from "aws-cdk-lib/aws-dynamodb";
|
|
6
|
+
import { type Secret } from "../../resources/aws/secrets";
|
|
7
|
+
import { type IGrantable, type Grant } from "aws-cdk-lib/aws-iam";
|
|
8
|
+
import { type IRelationalDatabase, type IDynamoDBDatabase, type RelationalDatabaseType } from "./interfaces/database.js";
|
|
9
|
+
import { type IDynamoDBConnector, type ISecurityGroupConnector } from "./interfaces/connector.js";
|
|
5
10
|
import { type IInstanceEngine, type IClusterEngine } from "aws-cdk-lib/aws-rds";
|
|
6
11
|
import { Duration } from "aws-cdk-lib";
|
|
7
12
|
import { type IKey } from "aws-cdk-lib/aws-kms";
|
|
@@ -132,6 +137,21 @@ export interface AuroraDatabaseProps extends BaseDatabaseProps {
|
|
|
132
137
|
snapshotIdentifier?: string;
|
|
133
138
|
/** Username from the snapshot (required when restoring from snapshot to reset password) */
|
|
134
139
|
snapshotUsername?: string;
|
|
140
|
+
/** Allow access from VPC CIDR (avoids cross-stack cyclic dependencies with Lambda) */
|
|
141
|
+
allowVpcAccess?: boolean;
|
|
142
|
+
/**
|
|
143
|
+
* Make database publicly accessible from the internet.
|
|
144
|
+
* WARNING: This is a security risk and should only be used for development
|
|
145
|
+
* or when building Payload apps locally that need database access.
|
|
146
|
+
* When enabled, the database is placed in public subnets.
|
|
147
|
+
*/
|
|
148
|
+
publiclyAccessible?: boolean;
|
|
149
|
+
/**
|
|
150
|
+
* IP address to allow access from when publiclyAccessible is true.
|
|
151
|
+
* If not specified, access is restricted to VPC only even when public.
|
|
152
|
+
* Format: CIDR notation (e.g., "203.0.113.0/32" for single IP)
|
|
153
|
+
*/
|
|
154
|
+
allowedIpCidr?: string;
|
|
135
155
|
}
|
|
136
156
|
export interface GlobalAuroraDatabaseProps extends BaseDatabaseProps {
|
|
137
157
|
type: "GlobalAurora";
|
|
@@ -178,19 +198,106 @@ export interface InstanceDatabaseProps extends BaseDatabaseProps {
|
|
|
178
198
|
/** Username from the snapshot (required when restoring from snapshot to reset password) */
|
|
179
199
|
snapshotUsername?: string;
|
|
180
200
|
}
|
|
181
|
-
|
|
201
|
+
/**
|
|
202
|
+
* DynamoDB table configuration properties.
|
|
203
|
+
*/
|
|
204
|
+
export interface DynamoDBDatabaseProps {
|
|
205
|
+
type: "DynamoDB";
|
|
206
|
+
partitionKey: DynamoDBKeySchema;
|
|
207
|
+
sortKey?: DynamoDBKeySchema;
|
|
208
|
+
billingMode?: "PAY_PER_REQUEST" | "PROVISIONED";
|
|
209
|
+
readCapacity?: number;
|
|
210
|
+
writeCapacity?: number;
|
|
211
|
+
globalSecondaryIndexes?: DynamoDBGlobalSecondaryIndex[];
|
|
212
|
+
timeToLiveAttribute?: string;
|
|
213
|
+
stream?: "NEW_IMAGE" | "OLD_IMAGE" | "NEW_AND_OLD_IMAGES" | "KEYS_ONLY";
|
|
214
|
+
pointInTimeRecovery?: boolean;
|
|
215
|
+
encryption?: "AWS_OWNED" | "AWS_MANAGED" | "CUSTOMER_MANAGED";
|
|
216
|
+
removalPolicy?: "DESTROY" | "RETAIN" | "SNAPSHOT";
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Relational database props union (Aurora, Instance, GlobalAurora).
|
|
220
|
+
*/
|
|
221
|
+
export type IRelationalDatabaseProps = AuroraDatabaseProps | InstanceDatabaseProps | GlobalAuroraDatabaseProps;
|
|
222
|
+
/**
|
|
223
|
+
* All database props union.
|
|
224
|
+
*/
|
|
225
|
+
export type IDatabaseProps = AuroraDatabaseProps | InstanceDatabaseProps | GlobalAuroraDatabaseProps | DynamoDBDatabaseProps;
|
|
226
|
+
/**
|
|
227
|
+
* Factory for creating type-safe database resources.
|
|
228
|
+
*
|
|
229
|
+
* @example
|
|
230
|
+
* // Aurora database - returns RelationalDatabase
|
|
231
|
+
* const aurora = app.addDatabase(DatabaseFactory.build("Main", {
|
|
232
|
+
* type: "Aurora",
|
|
233
|
+
* databaseName: "myapp"
|
|
234
|
+
* }));
|
|
235
|
+
* aurora.getHostEndpoint(); // Available
|
|
236
|
+
*
|
|
237
|
+
* @example
|
|
238
|
+
* // DynamoDB table - returns DynamoDBDatabase
|
|
239
|
+
* const cache = app.addDatabase(DatabaseFactory.build("Cache", {
|
|
240
|
+
* type: "DynamoDB",
|
|
241
|
+
* partitionKey: { name: "id", type: "S" }
|
|
242
|
+
* }));
|
|
243
|
+
* cache.getTableName(); // Available
|
|
244
|
+
* cache.grantReadWriteData(lambda); // Available
|
|
245
|
+
*/
|
|
182
246
|
export declare class DatabaseFactory {
|
|
183
|
-
static build
|
|
247
|
+
static build(id: string, props: AuroraDatabaseProps): (app: App, scope: Construct) => RelationalDatabase;
|
|
248
|
+
static build(id: string, props: InstanceDatabaseProps): (app: App, scope: Construct) => RelationalDatabase;
|
|
249
|
+
static build(id: string, props: GlobalAuroraDatabaseProps): (app: App, scope: Construct) => RelationalDatabase;
|
|
250
|
+
static build(id: string, props: DynamoDBDatabaseProps): (app: App, scope: Construct) => DynamoDBDatabase;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* DynamoDB database wrapper implementing IDynamoDBDatabase interface.
|
|
254
|
+
* Provides type-safe access to DynamoDB table operations.
|
|
255
|
+
*
|
|
256
|
+
* @example
|
|
257
|
+
* const cache = app.addDatabase(DatabaseFactory.build("Cache", {
|
|
258
|
+
* type: "DynamoDB",
|
|
259
|
+
* partitionKey: { name: "id", type: "S" }
|
|
260
|
+
* }));
|
|
261
|
+
* cache.grantReadWriteData(lambda);
|
|
262
|
+
*/
|
|
263
|
+
export declare class DynamoDBDatabase extends Construct implements IDynamoDBDatabase, IDynamoDBConnector {
|
|
264
|
+
readonly databaseType: "DynamoDB";
|
|
265
|
+
readonly connectorType: "dynamodb";
|
|
266
|
+
readonly id: string;
|
|
267
|
+
private readonly table;
|
|
268
|
+
constructor(scope: Construct, id: string, props: DynamoDBDatabaseProps);
|
|
269
|
+
getTableName(): string;
|
|
270
|
+
getTableArn(): string;
|
|
271
|
+
getTable(): ITable;
|
|
272
|
+
getStreamArn(): string | undefined;
|
|
273
|
+
grantReadData(grantee: IGrantable): Grant;
|
|
274
|
+
grantWriteData(grantee: IGrantable): Grant;
|
|
275
|
+
grantReadWriteData(grantee: IGrantable): Grant;
|
|
276
|
+
grantFullAccess(grantee: IGrantable): Grant;
|
|
277
|
+
grantStreamRead(grantee: IGrantable): Grant;
|
|
184
278
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
279
|
+
/**
|
|
280
|
+
* Relational database wrapper implementing IRelationalDatabase interface.
|
|
281
|
+
* Supports Aurora, RDS Instance, and GlobalAurora database types.
|
|
282
|
+
*
|
|
283
|
+
* @example
|
|
284
|
+
* const db = app.addDatabase(DatabaseFactory.build("Main", {
|
|
285
|
+
* type: "Aurora",
|
|
286
|
+
* databaseName: "myapp"
|
|
287
|
+
* }));
|
|
288
|
+
* db.grantConnect(lambda);
|
|
289
|
+
*/
|
|
290
|
+
export declare class RelationalDatabase extends Construct implements IRelationalDatabase, ISecurityGroupConnector {
|
|
291
|
+
readonly id: string;
|
|
292
|
+
readonly scope: Construct;
|
|
293
|
+
readonly vpc: IVpc;
|
|
294
|
+
readonly databaseType: RelationalDatabaseType;
|
|
295
|
+
readonly connectorType: "relational";
|
|
189
296
|
connections: Connections;
|
|
190
|
-
private
|
|
297
|
+
private readonly _databaseName;
|
|
191
298
|
private database;
|
|
192
|
-
constructor(scope: Construct, id: string, props:
|
|
193
|
-
addDatabase(props:
|
|
299
|
+
constructor(scope: Construct, id: string, props: IRelationalDatabaseProps);
|
|
300
|
+
addDatabase(props: IRelationalDatabaseProps): void;
|
|
194
301
|
private addAurora;
|
|
195
302
|
private addAuroraGlobal;
|
|
196
303
|
private addRdsInstance;
|
|
@@ -199,5 +306,11 @@ export declare class Database extends Construct implements IConnectable {
|
|
|
199
306
|
getHostEndpoint(): string;
|
|
200
307
|
getHostPort(): string;
|
|
201
308
|
getDatabaseName(): string;
|
|
309
|
+
/**
|
|
310
|
+
* Grant connect permissions to a grantee by adding it to the database security group.
|
|
311
|
+
* @param grantee The connectable principal to grant connect permissions to
|
|
312
|
+
*/
|
|
313
|
+
grantConnect(grantee: IConnectable): void;
|
|
202
314
|
}
|
|
203
|
-
export {};
|
|
315
|
+
export type { DynamoDBKeySchema, DynamoDBGlobalSecondaryIndex, DynamoDBTableProps } from "../../resources/aws/database/dynamodb";
|
|
316
|
+
export { type IRelationalDatabase, type IDynamoDBDatabase, type AnyDatabase, type DatabaseType, type RelationalDatabaseType, isRelationalDatabase, isDynamoDBDatabase, isAuroraDatabase, isInstanceDatabase, isGlobalAuroraDatabase } from "./interfaces/database.js";
|