@intentius/chant-lexicon-aws 0.0.12 → 0.0.13
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/dist/integrity.json +4 -4
- package/dist/manifest.json +1 -1
- package/dist/meta.json +446 -59
- package/dist/types/index.d.ts +381 -0
- package/package.json +2 -2
- package/src/codegen/docs.ts +1 -0
- package/src/codegen/generate-typescript.ts +1 -1
- package/src/codegen/generate.ts +3 -2
- package/src/composites/composites.test.ts +148 -0
- package/src/composites/index.ts +2 -0
- package/src/composites/rds-instance.ts +173 -0
- package/src/coverage.test.ts +31 -0
- package/src/generated/index.d.ts +381 -0
- package/src/generated/index.ts +85 -85
- package/src/generated/lexicon-aws.json +446 -59
- package/src/index.ts +2 -2
- package/src/spec/parse.test.ts +50 -0
- package/src/spec/parse.ts +9 -6
- package/src/validate.test.ts +34 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentius/chant-lexicon-aws",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.13",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": ["src/", "dist/"],
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"prepack": "bun run bundle && bun run validate"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@intentius/chant": "0.0.
|
|
25
|
+
"@intentius/chant": "0.0.12",
|
|
26
26
|
"fflate": "^0.8.2",
|
|
27
27
|
"js-yaml": "^4.1.0"
|
|
28
28
|
},
|
package/src/codegen/docs.ts
CHANGED
|
@@ -407,6 +407,7 @@ The AWS lexicon ships ready-to-use composites for common patterns. Import them f
|
|
|
407
407
|
| \`FargateAlb\` | \`cluster\`, \`executionRole\`, \`taskRole\`, \`logGroup\`, \`taskDef\`, \`albSg\`, \`taskSg\`, \`alb\`, \`targetGroup\`, \`listener\`, \`service\` | Fargate service behind an ALB. Accepts VPC outputs as props. |
|
|
408
408
|
| \`AlbShared\` | \`cluster\`, \`executionRole\`, \`albSg\`, \`alb\`, \`listener\` | Shared ALB infrastructure (ECS cluster, execution role, ALB, listener with 404 default). Created once, consumed by multiple \`FargateService\` instances. |
|
|
409
409
|
| \`FargateService\` | \`taskRole\`, \`logGroup\`, \`taskDef\`, \`taskSg\`, \`targetGroup\`, \`rule\`, \`service\` | Per-service Fargate resources with listener rule routing. Wire to an \`AlbShared\` instance for multi-service ALB patterns. |
|
|
410
|
+
| \`RdsInstance\` | \`subnetGroup\`, \`sg\`, \`db\` (+ \`parameterGroup\` if configured) | RDS instance (postgres, mysql, mariadb) in private subnets. Creates DB subnet group, security group, and optionally a parameter group. Engine-specific defaults for port, username, and version. Encrypted by default. |
|
|
410
411
|
|
|
411
412
|
All built-in composites accept \`ManagedPolicyArns\` and \`Policies\` for adding IAM permissions to the auto-created role.
|
|
412
413
|
|
|
@@ -78,7 +78,7 @@ export function generateTypeScriptDeclarations(
|
|
|
78
78
|
description: p.description,
|
|
79
79
|
}));
|
|
80
80
|
const dtsAttrs: DtsAttribute[] = r.resource.attributes.map((a) => ({
|
|
81
|
-
name: a.name,
|
|
81
|
+
name: a.name.replace(/\./g, "_").replace(/\*/g, "Item"), // Subscribers.*.Status → Subscribers_Item_Status
|
|
82
82
|
type: a.tsType,
|
|
83
83
|
}));
|
|
84
84
|
|
package/src/codegen/generate.ts
CHANGED
|
@@ -170,10 +170,11 @@ function generateRuntimeIndex(
|
|
|
170
170
|
const tsName = naming.resolve(cfnType);
|
|
171
171
|
if (!tsName) continue;
|
|
172
172
|
|
|
173
|
-
// Build attrs map
|
|
173
|
+
// Build attrs map: TS key (underscores) → CF attr name (dots)
|
|
174
174
|
const attrs: Record<string, string> = {};
|
|
175
175
|
for (const a of r.resource.attributes) {
|
|
176
|
-
|
|
176
|
+
const tsKey = a.name.replace(/\./g, "_").replace(/\*/g, "Item"); // Subscribers.*.Status → Subscribers_Item_Status
|
|
177
|
+
attrs[tsKey] = a.name; // maps to "Endpoint.Address" for GetAtt
|
|
177
178
|
}
|
|
178
179
|
|
|
179
180
|
resourceEntries.push({ tsName, resourceType: cfnType, attrs });
|
|
@@ -13,6 +13,7 @@ import { VpcDefault } from "./vpc-default";
|
|
|
13
13
|
import { FargateAlb } from "./fargate-alb";
|
|
14
14
|
import { AlbShared } from "./alb-shared";
|
|
15
15
|
import { FargateService } from "./fargate-service";
|
|
16
|
+
import { RdsInstance } from "./rds-instance";
|
|
16
17
|
|
|
17
18
|
const baseProps = {
|
|
18
19
|
name: "TestFunc",
|
|
@@ -633,3 +634,150 @@ describe("FargateService", () => {
|
|
|
633
634
|
expect(svcProps.DesiredCount).toBe(2);
|
|
634
635
|
});
|
|
635
636
|
});
|
|
637
|
+
|
|
638
|
+
describe("RdsInstance", () => {
|
|
639
|
+
const rdsProps = {
|
|
640
|
+
vpcId: "vpc-123",
|
|
641
|
+
subnetIds: ["subnet-1", "subnet-2"],
|
|
642
|
+
masterPassword: "secret",
|
|
643
|
+
};
|
|
644
|
+
|
|
645
|
+
test("returns subnetGroup, sg, db members", () => {
|
|
646
|
+
const instance = RdsInstance(rdsProps);
|
|
647
|
+
const names = Object.keys(instance.members);
|
|
648
|
+
expect(names).toContain("subnetGroup");
|
|
649
|
+
expect(names).toContain("sg");
|
|
650
|
+
expect(names).toContain("db");
|
|
651
|
+
expect(names).toHaveLength(3);
|
|
652
|
+
});
|
|
653
|
+
|
|
654
|
+
test("expandComposite produces correct logical names", () => {
|
|
655
|
+
const expanded = expandComposite("myDb", RdsInstance(rdsProps));
|
|
656
|
+
expect(expanded.has("myDbSubnetGroup")).toBe(true);
|
|
657
|
+
expect(expanded.has("myDbSg")).toBe(true);
|
|
658
|
+
expect(expanded.has("myDbDb")).toBe(true);
|
|
659
|
+
expect(expanded.size).toBe(3);
|
|
660
|
+
});
|
|
661
|
+
|
|
662
|
+
test("with parameterGroupFamily, also returns parameterGroup", () => {
|
|
663
|
+
const instance = RdsInstance({
|
|
664
|
+
...rdsProps,
|
|
665
|
+
parameterGroupFamily: "postgres16",
|
|
666
|
+
parameters: { shared_preload_libraries: "pg_stat_statements" },
|
|
667
|
+
});
|
|
668
|
+
const names = Object.keys(instance.members);
|
|
669
|
+
expect(names).toContain("parameterGroup");
|
|
670
|
+
expect(names).toHaveLength(4);
|
|
671
|
+
});
|
|
672
|
+
|
|
673
|
+
test("expandComposite with parameterGroup produces 4 entries", () => {
|
|
674
|
+
const expanded = expandComposite("pg", RdsInstance({
|
|
675
|
+
...rdsProps,
|
|
676
|
+
parameterGroupFamily: "postgres16",
|
|
677
|
+
}));
|
|
678
|
+
expect(expanded.has("pgSubnetGroup")).toBe(true);
|
|
679
|
+
expect(expanded.has("pgSg")).toBe(true);
|
|
680
|
+
expect(expanded.has("pgDb")).toBe(true);
|
|
681
|
+
expect(expanded.has("pgParameterGroup")).toBe(true);
|
|
682
|
+
expect(expanded.size).toBe(4);
|
|
683
|
+
});
|
|
684
|
+
|
|
685
|
+
test("ingress from SG produces SourceSecurityGroupId rule", () => {
|
|
686
|
+
const instance = RdsInstance({
|
|
687
|
+
...rdsProps,
|
|
688
|
+
ingressSourceSG: "sg-app123",
|
|
689
|
+
});
|
|
690
|
+
const sgProps = (instance.sg as any).props;
|
|
691
|
+
expect(sgProps.SecurityGroupIngress).toHaveLength(1);
|
|
692
|
+
const ingress = (sgProps.SecurityGroupIngress[0] as any).props;
|
|
693
|
+
expect(ingress.SourceSecurityGroupId).toBe("sg-app123");
|
|
694
|
+
expect(ingress.FromPort).toBe(5432);
|
|
695
|
+
expect(ingress.ToPort).toBe(5432);
|
|
696
|
+
});
|
|
697
|
+
|
|
698
|
+
test("ingress from CIDR produces CidrIp rule", () => {
|
|
699
|
+
const instance = RdsInstance({
|
|
700
|
+
...rdsProps,
|
|
701
|
+
ingressCidr: "10.0.0.0/16",
|
|
702
|
+
});
|
|
703
|
+
const sgProps = (instance.sg as any).props;
|
|
704
|
+
expect(sgProps.SecurityGroupIngress).toHaveLength(1);
|
|
705
|
+
const ingress = (sgProps.SecurityGroupIngress[0] as any).props;
|
|
706
|
+
expect(ingress.CidrIp).toBe("10.0.0.0/16");
|
|
707
|
+
expect(ingress.FromPort).toBe(5432);
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
test("no ingress when neither SG nor CIDR provided", () => {
|
|
711
|
+
const instance = RdsInstance(rdsProps);
|
|
712
|
+
const sgProps = (instance.sg as any).props;
|
|
713
|
+
expect(sgProps.SecurityGroupIngress).toBeUndefined();
|
|
714
|
+
});
|
|
715
|
+
|
|
716
|
+
test("default engine is postgres with correct defaults", () => {
|
|
717
|
+
const instance = RdsInstance(rdsProps);
|
|
718
|
+
const dbProps = (instance.db as any).props;
|
|
719
|
+
expect(dbProps.Engine).toBe("postgres");
|
|
720
|
+
expect(dbProps.EngineVersion).toBe("16.6");
|
|
721
|
+
expect(dbProps.DBInstanceClass).toBe("db.t4g.micro");
|
|
722
|
+
expect(dbProps.AllocatedStorage).toBe("20");
|
|
723
|
+
expect(dbProps.StorageType).toBe("gp3");
|
|
724
|
+
expect(dbProps.StorageEncrypted).toBe(true);
|
|
725
|
+
expect(dbProps.MultiAZ).toBe(false);
|
|
726
|
+
expect(dbProps.BackupRetentionPeriod).toBe(7);
|
|
727
|
+
expect(dbProps.CopyTagsToSnapshot).toBe(true);
|
|
728
|
+
expect(dbProps.AutoMinorVersionUpgrade).toBe(true);
|
|
729
|
+
expect(dbProps.PubliclyAccessible).toBe(false);
|
|
730
|
+
expect(dbProps.DeletionProtection).toBe(false);
|
|
731
|
+
expect(dbProps.MasterUsername).toBe("postgres");
|
|
732
|
+
});
|
|
733
|
+
|
|
734
|
+
test("engine: mysql uses mysql-specific defaults", () => {
|
|
735
|
+
const instance = RdsInstance({
|
|
736
|
+
...rdsProps,
|
|
737
|
+
engine: "mysql",
|
|
738
|
+
ingressCidr: "10.0.0.0/16",
|
|
739
|
+
});
|
|
740
|
+
const dbProps = (instance.db as any).props;
|
|
741
|
+
expect(dbProps.Engine).toBe("mysql");
|
|
742
|
+
expect(dbProps.EngineVersion).toBe("8.0.40");
|
|
743
|
+
expect(dbProps.MasterUsername).toBe("admin");
|
|
744
|
+
expect(dbProps.Port).toBe("3306");
|
|
745
|
+
const ingress = ((instance.sg as any).props.SecurityGroupIngress[0] as any).props;
|
|
746
|
+
expect(ingress.FromPort).toBe(3306);
|
|
747
|
+
expect(ingress.ToPort).toBe(3306);
|
|
748
|
+
});
|
|
749
|
+
|
|
750
|
+
test("engine: mariadb uses mariadb-specific defaults", () => {
|
|
751
|
+
const instance = RdsInstance({
|
|
752
|
+
...rdsProps,
|
|
753
|
+
engine: "mariadb",
|
|
754
|
+
});
|
|
755
|
+
const dbProps = (instance.db as any).props;
|
|
756
|
+
expect(dbProps.Engine).toBe("mariadb");
|
|
757
|
+
expect(dbProps.EngineVersion).toBe("11.4.3");
|
|
758
|
+
expect(dbProps.MasterUsername).toBe("admin");
|
|
759
|
+
expect(dbProps.Port).toBe("3306");
|
|
760
|
+
});
|
|
761
|
+
|
|
762
|
+
test("custom port is applied to SG and DB", () => {
|
|
763
|
+
const instance = RdsInstance({
|
|
764
|
+
...rdsProps,
|
|
765
|
+
port: 3306,
|
|
766
|
+
ingressCidr: "10.0.0.0/8",
|
|
767
|
+
});
|
|
768
|
+
const dbProps = (instance.db as any).props;
|
|
769
|
+
expect(dbProps.Port).toBe("3306");
|
|
770
|
+
const ingress = ((instance.sg as any).props.SecurityGroupIngress[0] as any).props;
|
|
771
|
+
expect(ingress.FromPort).toBe(3306);
|
|
772
|
+
expect(ingress.ToPort).toBe(3306);
|
|
773
|
+
});
|
|
774
|
+
|
|
775
|
+
test("db references subnet group and security group", () => {
|
|
776
|
+
const instance = RdsInstance(rdsProps);
|
|
777
|
+
const dbProps = (instance.db as any).props;
|
|
778
|
+
// Subnet group is passed as a resource instance (serializer resolves to { Ref: ... })
|
|
779
|
+
expect(dbProps.DBSubnetGroupName).toBe(instance.subnetGroup);
|
|
780
|
+
expect(dbProps.VPCSecurityGroups).toHaveLength(1);
|
|
781
|
+
expect(dbProps.VPCSecurityGroups[0]).toBeInstanceOf(AttrRef);
|
|
782
|
+
});
|
|
783
|
+
});
|
package/src/composites/index.ts
CHANGED
|
@@ -22,3 +22,5 @@ export { AlbShared } from "./alb-shared";
|
|
|
22
22
|
export type { AlbSharedProps } from "./alb-shared";
|
|
23
23
|
export { FargateService } from "./fargate-service";
|
|
24
24
|
export type { FargateServiceProps } from "./fargate-service";
|
|
25
|
+
export { RdsInstance, RdsInstance as RdsPostgres } from "./rds-instance";
|
|
26
|
+
export type { RdsInstanceProps, RdsInstanceProps as RdsPostgresProps } from "./rds-instance";
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { Composite } from "@intentius/chant";
|
|
2
|
+
import {
|
|
3
|
+
DbInstance,
|
|
4
|
+
RDSDBSubnetGroup,
|
|
5
|
+
RDSDBParameterGroup,
|
|
6
|
+
SecurityGroup,
|
|
7
|
+
SecurityGroup_Ingress,
|
|
8
|
+
} from "../generated";
|
|
9
|
+
|
|
10
|
+
const ENGINE_DEFAULTS: Record<string, { port: number; username: string; version: string; logExport: string }> = {
|
|
11
|
+
postgres: { port: 5432, username: "postgres", version: "16.6", logExport: "postgresql" },
|
|
12
|
+
mysql: { port: 3306, username: "admin", version: "8.0.40", logExport: "general" },
|
|
13
|
+
mariadb: { port: 3306, username: "admin", version: "11.4.3", logExport: "general" },
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export interface RdsInstanceProps {
|
|
17
|
+
// ── Engine ──────────────────────────────────────────────────────
|
|
18
|
+
engine?: "postgres" | "mysql" | "mariadb";
|
|
19
|
+
|
|
20
|
+
// ── Networking (required) ─────────────────────────────────────
|
|
21
|
+
vpcId: string;
|
|
22
|
+
subnetIds: string[];
|
|
23
|
+
ingressSourceSG?: string;
|
|
24
|
+
ingressCidr?: string;
|
|
25
|
+
port?: number;
|
|
26
|
+
publiclyAccessible?: boolean;
|
|
27
|
+
|
|
28
|
+
// ── Identity & auth (required) ────────────────────────────────
|
|
29
|
+
masterUsername?: string;
|
|
30
|
+
masterPassword: string;
|
|
31
|
+
|
|
32
|
+
// ── Engine version ──────────────────────────────────────────────
|
|
33
|
+
engineVersion?: string;
|
|
34
|
+
databaseName?: string;
|
|
35
|
+
|
|
36
|
+
// ── Instance sizing ───────────────────────────────────────────
|
|
37
|
+
instanceClass?: string;
|
|
38
|
+
allocatedStorage?: number;
|
|
39
|
+
storageType?: string;
|
|
40
|
+
maxAllocatedStorage?: number;
|
|
41
|
+
|
|
42
|
+
// ── High availability ─────────────────────────────────────────
|
|
43
|
+
multiAZ?: boolean;
|
|
44
|
+
|
|
45
|
+
// ── Encryption ────────────────────────────────────────────────
|
|
46
|
+
storageEncrypted?: boolean;
|
|
47
|
+
kmsKeyId?: string;
|
|
48
|
+
|
|
49
|
+
// ── Backup ────────────────────────────────────────────────────
|
|
50
|
+
backupRetentionPeriod?: number;
|
|
51
|
+
preferredBackupWindow?: string;
|
|
52
|
+
copyTagsToSnapshot?: boolean;
|
|
53
|
+
|
|
54
|
+
// ── Maintenance ───────────────────────────────────────────────
|
|
55
|
+
preferredMaintenanceWindow?: string;
|
|
56
|
+
autoMinorVersionUpgrade?: boolean;
|
|
57
|
+
|
|
58
|
+
// ── Monitoring ────────────────────────────────────────────────
|
|
59
|
+
enableCloudwatchLogs?: boolean;
|
|
60
|
+
enablePerformanceInsights?: boolean;
|
|
61
|
+
performanceInsightsRetentionPeriod?: number;
|
|
62
|
+
|
|
63
|
+
// ── Parameter group ───────────────────────────────────────────
|
|
64
|
+
parameterGroupFamily?: string;
|
|
65
|
+
parameters?: Record<string, string>;
|
|
66
|
+
|
|
67
|
+
// ── Protection ────────────────────────────────────────────────
|
|
68
|
+
deletionProtection?: boolean;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export const RdsInstance = Composite<RdsInstanceProps>((props) => {
|
|
72
|
+
const engine = props.engine ?? "postgres";
|
|
73
|
+
const defaults = ENGINE_DEFAULTS[engine];
|
|
74
|
+
const port = props.port ?? defaults.port;
|
|
75
|
+
const masterUsername = props.masterUsername ?? defaults.username;
|
|
76
|
+
const engineVersion = props.engineVersion ?? defaults.version;
|
|
77
|
+
const instanceClass = props.instanceClass ?? "db.t4g.micro";
|
|
78
|
+
const allocatedStorage = props.allocatedStorage ?? 20;
|
|
79
|
+
const storageType = props.storageType ?? "gp3";
|
|
80
|
+
const multiAZ = props.multiAZ ?? false;
|
|
81
|
+
const storageEncrypted = props.storageEncrypted ?? true;
|
|
82
|
+
const backupRetentionPeriod = props.backupRetentionPeriod ?? 7;
|
|
83
|
+
const copyTagsToSnapshot = props.copyTagsToSnapshot ?? true;
|
|
84
|
+
const autoMinorVersionUpgrade = props.autoMinorVersionUpgrade ?? true;
|
|
85
|
+
const publiclyAccessible = props.publiclyAccessible ?? false;
|
|
86
|
+
const deletionProtection = props.deletionProtection ?? false;
|
|
87
|
+
|
|
88
|
+
// DB Subnet Group
|
|
89
|
+
const subnetGroup = new RDSDBSubnetGroup({
|
|
90
|
+
DBSubnetGroupDescription: "Subnet group for RDS instance",
|
|
91
|
+
SubnetIds: props.subnetIds,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// Security Group
|
|
95
|
+
const ingressRules: InstanceType<typeof SecurityGroup_Ingress>[] = [];
|
|
96
|
+
if (props.ingressSourceSG) {
|
|
97
|
+
ingressRules.push(
|
|
98
|
+
new SecurityGroup_Ingress({
|
|
99
|
+
IpProtocol: "tcp",
|
|
100
|
+
FromPort: port,
|
|
101
|
+
ToPort: port,
|
|
102
|
+
SourceSecurityGroupId: props.ingressSourceSG,
|
|
103
|
+
}),
|
|
104
|
+
);
|
|
105
|
+
} else if (props.ingressCidr) {
|
|
106
|
+
ingressRules.push(
|
|
107
|
+
new SecurityGroup_Ingress({
|
|
108
|
+
IpProtocol: "tcp",
|
|
109
|
+
FromPort: port,
|
|
110
|
+
ToPort: port,
|
|
111
|
+
CidrIp: props.ingressCidr,
|
|
112
|
+
}),
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const sg = new SecurityGroup({
|
|
117
|
+
GroupDescription: "Security group for RDS instance",
|
|
118
|
+
VpcId: props.vpcId,
|
|
119
|
+
SecurityGroupIngress: ingressRules.length > 0 ? ingressRules : undefined,
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// Optional Parameter Group
|
|
123
|
+
let parameterGroup: InstanceType<typeof RDSDBParameterGroup> | undefined;
|
|
124
|
+
if (props.parameterGroupFamily) {
|
|
125
|
+
parameterGroup = new RDSDBParameterGroup({
|
|
126
|
+
Family: props.parameterGroupFamily,
|
|
127
|
+
Description: "Custom parameter group",
|
|
128
|
+
Parameters: props.parameters,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// DB Instance
|
|
133
|
+
const dbProps: Record<string, any> = {
|
|
134
|
+
Engine: engine,
|
|
135
|
+
EngineVersion: engineVersion,
|
|
136
|
+
DBInstanceClass: instanceClass,
|
|
137
|
+
MasterUsername: masterUsername,
|
|
138
|
+
MasterUserPassword: props.masterPassword,
|
|
139
|
+
AllocatedStorage: String(allocatedStorage),
|
|
140
|
+
StorageType: storageType,
|
|
141
|
+
DBSubnetGroupName: subnetGroup.Ref,
|
|
142
|
+
VPCSecurityGroups: [sg.GroupId],
|
|
143
|
+
Port: String(port),
|
|
144
|
+
PubliclyAccessible: publiclyAccessible,
|
|
145
|
+
MultiAZ: multiAZ,
|
|
146
|
+
StorageEncrypted: storageEncrypted,
|
|
147
|
+
BackupRetentionPeriod: backupRetentionPeriod,
|
|
148
|
+
CopyTagsToSnapshot: copyTagsToSnapshot,
|
|
149
|
+
AutoMinorVersionUpgrade: autoMinorVersionUpgrade,
|
|
150
|
+
DeletionProtection: deletionProtection,
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
if (props.databaseName) dbProps.DBName = props.databaseName;
|
|
154
|
+
if (props.kmsKeyId) dbProps.KmsKeyId = props.kmsKeyId;
|
|
155
|
+
if (props.maxAllocatedStorage) dbProps.MaxAllocatedStorage = props.maxAllocatedStorage;
|
|
156
|
+
if (props.preferredBackupWindow) dbProps.PreferredBackupWindow = props.preferredBackupWindow;
|
|
157
|
+
if (props.preferredMaintenanceWindow) dbProps.PreferredMaintenanceWindow = props.preferredMaintenanceWindow;
|
|
158
|
+
if (props.enableCloudwatchLogs) dbProps.EnableCloudwatchLogsExports = [defaults.logExport];
|
|
159
|
+
if (props.enablePerformanceInsights) {
|
|
160
|
+
dbProps.EnablePerformanceInsights = true;
|
|
161
|
+
if (props.performanceInsightsRetentionPeriod) {
|
|
162
|
+
dbProps.PerformanceInsightsRetentionPeriod = props.performanceInsightsRetentionPeriod;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (parameterGroup) dbProps.DBParameterGroupName = parameterGroup.Ref;
|
|
166
|
+
|
|
167
|
+
const db = new DbInstance(dbProps);
|
|
168
|
+
|
|
169
|
+
const result: Record<string, any> = { subnetGroup, sg, db };
|
|
170
|
+
if (parameterGroup) result.parameterGroup = parameterGroup;
|
|
171
|
+
|
|
172
|
+
return result;
|
|
173
|
+
}, "RdsInstance");
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { describe, test, expect } from "bun:test";
|
|
2
|
+
import { existsSync } from "fs";
|
|
3
|
+
import { join, dirname } from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
|
|
6
|
+
const pkgDir = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
7
|
+
const generatedDir = join(pkgDir, "src", "generated");
|
|
8
|
+
const hasGenerated = existsSync(join(generatedDir, "lexicon-aws.json"));
|
|
9
|
+
|
|
10
|
+
describe("coverage", () => {
|
|
11
|
+
test.skipIf(!hasGenerated)("computeCoverage function exists", async () => {
|
|
12
|
+
const { computeCoverage } = await import("./coverage");
|
|
13
|
+
expect(typeof computeCoverage).toBe("function");
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test.skipIf(!hasGenerated)("overallPct function exists", async () => {
|
|
17
|
+
const { overallPct } = await import("./coverage");
|
|
18
|
+
expect(typeof overallPct).toBe("function");
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test("handles missing generated files gracefully", async () => {
|
|
22
|
+
const { computeCoverage } = await import("./coverage");
|
|
23
|
+
if (!hasGenerated) {
|
|
24
|
+
try {
|
|
25
|
+
await computeCoverage(generatedDir);
|
|
26
|
+
} catch {
|
|
27
|
+
// Expected — no generated files
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
});
|