From 7b8bac45535966fb0e74adb7823434b5ed5ce52e Mon Sep 17 00:00:00 2001 From: mandryllo Date: Tue, 2 Dec 2025 15:54:30 +0100 Subject: [PATCH 01/71] Create db v2 component # Conflicts: # src/v2/components/database/index.ts --- src/v2/components/database/index.ts | 195 +++++++++++++++------------- 1 file changed, 108 insertions(+), 87 deletions(-) diff --git a/src/v2/components/database/index.ts b/src/v2/components/database/index.ts index bb97184..24802c3 100644 --- a/src/v2/components/database/index.ts +++ b/src/v2/components/database/index.ts @@ -6,44 +6,34 @@ import { Password } from '../../../components/password'; import { commonTags } from '../../../constants'; export namespace Database { - export type Instance = { + export type Args = { dbName?: pulumi.Input; - engineVersion?: pulumi.Input; + username?: pulumi.Input; + password?: pulumi.Input; + vpc: pulumi.Input; multiAz?: pulumi.Input; + applyImmediately?: pulumi.Input; + allocatedStorage?: pulumi.Input; + maxAllocatedStorage?: pulumi.Input; instanceClass?: pulumi.Input; allowMajorVersionUpgrade?: pulumi.Input; autoMinorVersionUpgrade?: pulumi.Input; - applyImmediately?: pulumi.Input; - }; - - export type Credentials = { - username?: pulumi.Input; - password?: pulumi.Input; - }; - - export type Storage = { - allocatedStorage?: pulumi.Input; - maxAllocatedStorage?: pulumi.Input; + kmsKeyId?: pulumi.Input; + parameterGroupName?: pulumi.Input; + customParameterGroupArgs?: pulumi.Input; + snapshotIdentifier?: pulumi.Input; + enableMonitoring?: pulumi.Input; + engineVersion?: pulumi.Input; + tags?: pulumi.Input<{ + [key: string]: pulumi.Input; + }>; }; - - export type Args = Instance & - Credentials & - Storage & { - vpc: pulumi.Input; - enableMonitoring?: pulumi.Input; - snapshotIdentifier?: pulumi.Input; - parameterGroupName?: pulumi.Input; - kmsKeyId?: pulumi.Input; - tags?: pulumi.Input<{ - [key: string]: pulumi.Input; - }>; - }; } const defaults = { multiAz: false, applyImmediately: false, - allocatedStorage: 20, + allocatedStorage: '20', maxAllocatedStorage: 100, instanceClass: 'db.t4g.micro', enableMonitoring: false, @@ -55,13 +45,13 @@ const defaults = { export class Database extends pulumi.ComponentResource { name: string; instance: awsNative.rds.DbInstance; - vpc: pulumi.Output; dbSubnetGroup: aws.rds.SubnetGroup; dbSecurityGroup: aws.ec2.SecurityGroup; password: Password; - kmsKeyId: pulumi.Output; - monitoringRole?: aws.iam.Role; encryptedSnapshotCopy?: aws.rds.SnapshotCopy; + monitoringRole?: aws.iam.Role; + kmsKeyId: pulumi.Input; + parameterGroupName?: pulumi.Input; constructor( name: string, @@ -73,12 +63,20 @@ export class Database extends pulumi.ComponentResource { this.name = name; const argsWithDefaults = Object.assign({}, defaults, args); - const { vpc, kmsKeyId, enableMonitoring, snapshotIdentifier } = - argsWithDefaults; + const { + kmsKeyId, + snapshotIdentifier, + enableMonitoring, + parameterGroupName, + customParameterGroupArgs, + } = argsWithDefaults; - this.vpc = pulumi.output(vpc); - this.dbSubnetGroup = this.createSubnetGroup(); - this.dbSecurityGroup = this.createSecurityGroup(); + const vpc = pulumi.output(argsWithDefaults.vpc); + this.dbSubnetGroup = this.createSubnetGroup(vpc.isolatedSubnetIds); + this.dbSecurityGroup = this.createSecurityGroup( + vpc.vpcId, + vpc.vpc.cidrBlock, + ); this.password = new Password( `${this.name}-database-password`, @@ -86,9 +84,11 @@ export class Database extends pulumi.ComponentResource { { parent: this }, ); - this.kmsKeyId = kmsKeyId - ? pulumi.output(kmsKeyId) - : this.createEncryptionKey().arn; + this.kmsKeyId = kmsKeyId || this.createEncryptionKey().arn; + + this.parameterGroupName = customParameterGroupArgs + ? this.createParameterGroup(customParameterGroupArgs).name + : parameterGroupName; if (enableMonitoring) { this.monitoringRole = this.createMonitoringRole(); @@ -99,43 +99,50 @@ export class Database extends pulumi.ComponentResource { this.createEncryptedSnapshotCopy(snapshotIdentifier); } - this.instance = this.createDatabaseInstance(argsWithDefaults); + this.instance = this.createDatabaseInstance(args); this.registerOutputs(); } - private createSubnetGroup() { - return new aws.rds.SubnetGroup( + private createSubnetGroup( + isolatedSubnetIds: awsx.ec2.Vpc['isolatedSubnetIds'], + ) { + const dbSubnetGroup = new aws.rds.SubnetGroup( `${this.name}-subnet-group`, { - subnetIds: this.vpc.isolatedSubnetIds, + subnetIds: isolatedSubnetIds, tags: commonTags, }, { parent: this }, ); + return dbSubnetGroup; } - private createSecurityGroup() { - return new aws.ec2.SecurityGroup( + private createSecurityGroup( + vpcId: awsx.ec2.Vpc['vpcId'], + vpcCidrBlock: pulumi.Input, + ) { + const dbSecurityGroup = new aws.ec2.SecurityGroup( `${this.name}-security-group`, { - vpcId: this.vpc.vpcId, + vpcId, ingress: [ { protocol: 'tcp', fromPort: 5432, toPort: 5432, - cidrBlocks: [this.vpc.vpc.cidrBlock], + cidrBlocks: [vpcCidrBlock], }, ], tags: commonTags, }, { parent: this }, ); + return dbSecurityGroup; } private createEncryptionKey() { - return new aws.kms.Key( + const kms = new aws.kms.Key( `${this.name}-rds-key`, { description: `${this.name} RDS encryption key`, @@ -148,27 +155,24 @@ export class Database extends pulumi.ComponentResource { }, { parent: this }, ); + return kms; } private createMonitoringRole() { - const monitoringRole = new aws.iam.Role( - `${this.name}-rds-monitoring`, - { - assumeRolePolicy: { - Version: '2012-10-17', - Statement: [ - { - Action: 'sts:AssumeRole', - Effect: 'Allow', - Principal: { - Service: 'monitoring.rds.amazonaws.com', - }, + const monitoringRole = new aws.iam.Role(`${this.name}-rds-monitoring`, { + assumeRolePolicy: { + Version: '2012-10-17', + Statement: [ + { + Action: 'sts:AssumeRole', + Effect: 'Allow', + Principal: { + Service: 'monitoring.rds.amazonaws.com', }, - ], - }, + }, + ], }, - { parent: this }, - ); + }); new aws.iam.RolePolicyAttachment( `${this.name}-rds-monitoring-role-attachment`, @@ -177,14 +181,13 @@ export class Database extends pulumi.ComponentResource { policyArn: 'arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole', }, - { parent: this }, ); return monitoringRole; } private createEncryptedSnapshotCopy( - snapshotIdentifier: Database.Args['snapshotIdentifier'], + snapshotIdentifier: pulumi.Input, ) { const sourceDbSnapshotIdentifier = pulumi .output(snapshotIdentifier) @@ -192,22 +195,42 @@ export class Database extends pulumi.ComponentResource { aws.rds.getSnapshot({ dbSnapshotIdentifier: snapshotIdentifier, }), - ).dbSnapshotArn; + ) + .apply(snapshot => snapshot.dbSnapshotArn); - return new aws.rds.SnapshotCopy( + const encryptedSnapshotCopy = new aws.rds.SnapshotCopy( `${this.name}-encrypted-snapshot-copy`, { sourceDbSnapshotIdentifier, - targetDbSnapshotIdentifier: pulumi.interpolate`${snapshotIdentifier}-encrypted-copy`, + targetDbSnapshotIdentifier: `${snapshotIdentifier}-encrypted-copy`, kmsKeyId: this.kmsKeyId, }, { parent: this }, ); + return encryptedSnapshotCopy; + } + + private createParameterGroup( + customParameterGroupArgs: pulumi.Input, + ) { + const parameterGroup = pulumi + .output(customParameterGroupArgs) + .apply(args => { + return new aws.rds.ParameterGroup( + `${this.name}-parameter-group`, + args, + { parent: this }, + ); + }); + + return parameterGroup; } private createDatabaseInstance(args: Database.Args) { + const argsWithDefaults = Object.assign({}, defaults, args); + const monitoringOptions = - args.enableMonitoring && this.monitoringRole + argsWithDefaults.enableMonitoring && this.monitoringRole ? { monitoringInterval: 60, monitoringRoleArn: this.monitoringRole.arn, @@ -221,19 +244,19 @@ export class Database extends pulumi.ComponentResource { { dbInstanceIdentifier: `${this.name}-db-instance`, engine: 'postgres', - engineVersion: args.engineVersion, - dbInstanceClass: args.instanceClass, - dbName: args.dbName, - masterUsername: args.username, + engineVersion: argsWithDefaults.engineVersion, + dbInstanceClass: argsWithDefaults.instanceClass, + dbName: argsWithDefaults.dbName, + masterUsername: argsWithDefaults.username, masterUserPassword: this.password.value, dbSubnetGroupName: this.dbSubnetGroup.name, vpcSecurityGroups: [this.dbSecurityGroup.id], - allocatedStorage: args.allocatedStorage?.toString(), - maxAllocatedStorage: args.maxAllocatedStorage, - multiAz: args.multiAz, - applyImmediately: args.applyImmediately, - allowMajorVersionUpgrade: args.allowMajorVersionUpgrade, - autoMinorVersionUpgrade: args.autoMinorVersionUpgrade, + allocatedStorage: argsWithDefaults.allocatedStorage, + maxAllocatedStorage: argsWithDefaults.maxAllocatedStorage, + multiAz: argsWithDefaults.multiAz, + applyImmediately: argsWithDefaults.applyImmediately, + allowMajorVersionUpgrade: argsWithDefaults.allowMajorVersionUpgrade, + autoMinorVersionUpgrade: argsWithDefaults.autoMinorVersionUpgrade, kmsKeyId: this.kmsKeyId, storageEncrypted: true, publiclyAccessible: false, @@ -241,17 +264,15 @@ export class Database extends pulumi.ComponentResource { preferredBackupWindow: '06:00-06:30', backupRetentionPeriod: 14, caCertificateIdentifier: 'rds-ca-rsa2048-g1', - dbParameterGroupName: args.parameterGroupName, + dbParameterGroupName: this.parameterGroupName, dbSnapshotIdentifier: this.encryptedSnapshotCopy?.targetDbSnapshotIdentifier, ...monitoringOptions, - tags: pulumi - .output(args.tags) - .apply(tags => [ - ...Object.entries({ ...commonTags, ...tags }).map( - ([key, value]) => ({ key, value }), - ), - ]), + tags: [ + ...Object.entries({ ...commonTags, ...argsWithDefaults.tags }).map( + ([key, value]) => ({ key, value }), + ), + ], }, { parent: this, dependsOn: [this.password] }, ); From 396e648db792efcfda4a25d4977f162606cb1795 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Fri, 5 Dec 2025 10:31:48 +0100 Subject: [PATCH 02/71] Remove ability to create custom parameter group --- src/v2/components/database/index.ts | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/src/v2/components/database/index.ts b/src/v2/components/database/index.ts index 24802c3..8e037af 100644 --- a/src/v2/components/database/index.ts +++ b/src/v2/components/database/index.ts @@ -20,7 +20,6 @@ export namespace Database { autoMinorVersionUpgrade?: pulumi.Input; kmsKeyId?: pulumi.Input; parameterGroupName?: pulumi.Input; - customParameterGroupArgs?: pulumi.Input; snapshotIdentifier?: pulumi.Input; enableMonitoring?: pulumi.Input; engineVersion?: pulumi.Input; @@ -51,7 +50,6 @@ export class Database extends pulumi.ComponentResource { encryptedSnapshotCopy?: aws.rds.SnapshotCopy; monitoringRole?: aws.iam.Role; kmsKeyId: pulumi.Input; - parameterGroupName?: pulumi.Input; constructor( name: string, @@ -67,8 +65,6 @@ export class Database extends pulumi.ComponentResource { kmsKeyId, snapshotIdentifier, enableMonitoring, - parameterGroupName, - customParameterGroupArgs, } = argsWithDefaults; const vpc = pulumi.output(argsWithDefaults.vpc); @@ -86,10 +82,6 @@ export class Database extends pulumi.ComponentResource { this.kmsKeyId = kmsKeyId || this.createEncryptionKey().arn; - this.parameterGroupName = customParameterGroupArgs - ? this.createParameterGroup(customParameterGroupArgs).name - : parameterGroupName; - if (enableMonitoring) { this.monitoringRole = this.createMonitoringRole(); } @@ -210,22 +202,6 @@ export class Database extends pulumi.ComponentResource { return encryptedSnapshotCopy; } - private createParameterGroup( - customParameterGroupArgs: pulumi.Input, - ) { - const parameterGroup = pulumi - .output(customParameterGroupArgs) - .apply(args => { - return new aws.rds.ParameterGroup( - `${this.name}-parameter-group`, - args, - { parent: this }, - ); - }); - - return parameterGroup; - } - private createDatabaseInstance(args: Database.Args) { const argsWithDefaults = Object.assign({}, defaults, args); @@ -264,7 +240,7 @@ export class Database extends pulumi.ComponentResource { preferredBackupWindow: '06:00-06:30', backupRetentionPeriod: 14, caCertificateIdentifier: 'rds-ca-rsa2048-g1', - dbParameterGroupName: this.parameterGroupName, + dbParameterGroupName: argsWithDefaults.parameterGroupName, dbSnapshotIdentifier: this.encryptedSnapshotCopy?.targetDbSnapshotIdentifier, ...monitoringOptions, From b295e286a94e5af7aa32cddf072b3a8fa1f908c6 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Fri, 5 Dec 2025 10:34:46 +0100 Subject: [PATCH 03/71] Cleanup --- src/v2/components/database/index.ts | 30 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/v2/components/database/index.ts b/src/v2/components/database/index.ts index 8e037af..297227d 100644 --- a/src/v2/components/database/index.ts +++ b/src/v2/components/database/index.ts @@ -91,7 +91,7 @@ export class Database extends pulumi.ComponentResource { this.createEncryptedSnapshotCopy(snapshotIdentifier); } - this.instance = this.createDatabaseInstance(args); + this.instance = this.createDatabaseInstance(argsWithDefaults); this.registerOutputs(); } @@ -203,10 +203,8 @@ export class Database extends pulumi.ComponentResource { } private createDatabaseInstance(args: Database.Args) { - const argsWithDefaults = Object.assign({}, defaults, args); - const monitoringOptions = - argsWithDefaults.enableMonitoring && this.monitoringRole + args.enableMonitoring && this.monitoringRole ? { monitoringInterval: 60, monitoringRoleArn: this.monitoringRole.arn, @@ -220,19 +218,19 @@ export class Database extends pulumi.ComponentResource { { dbInstanceIdentifier: `${this.name}-db-instance`, engine: 'postgres', - engineVersion: argsWithDefaults.engineVersion, - dbInstanceClass: argsWithDefaults.instanceClass, - dbName: argsWithDefaults.dbName, - masterUsername: argsWithDefaults.username, + engineVersion: args.engineVersion, + dbInstanceClass: args.instanceClass, + dbName: args.dbName, + masterUsername: args.username, masterUserPassword: this.password.value, dbSubnetGroupName: this.dbSubnetGroup.name, vpcSecurityGroups: [this.dbSecurityGroup.id], - allocatedStorage: argsWithDefaults.allocatedStorage, - maxAllocatedStorage: argsWithDefaults.maxAllocatedStorage, - multiAz: argsWithDefaults.multiAz, - applyImmediately: argsWithDefaults.applyImmediately, - allowMajorVersionUpgrade: argsWithDefaults.allowMajorVersionUpgrade, - autoMinorVersionUpgrade: argsWithDefaults.autoMinorVersionUpgrade, + allocatedStorage: args.allocatedStorage, + maxAllocatedStorage: args.maxAllocatedStorage, + multiAz: args.multiAz, + applyImmediately: args.applyImmediately, + allowMajorVersionUpgrade: args.allowMajorVersionUpgrade, + autoMinorVersionUpgrade: args.autoMinorVersionUpgrade, kmsKeyId: this.kmsKeyId, storageEncrypted: true, publiclyAccessible: false, @@ -240,12 +238,12 @@ export class Database extends pulumi.ComponentResource { preferredBackupWindow: '06:00-06:30', backupRetentionPeriod: 14, caCertificateIdentifier: 'rds-ca-rsa2048-g1', - dbParameterGroupName: argsWithDefaults.parameterGroupName, + dbParameterGroupName: args.parameterGroupName, dbSnapshotIdentifier: this.encryptedSnapshotCopy?.targetDbSnapshotIdentifier, ...monitoringOptions, tags: [ - ...Object.entries({ ...commonTags, ...argsWithDefaults.tags }).map( + ...Object.entries({ ...commonTags, ...args.tags }).map( ([key, value]) => ({ key, value }), ), ], From 35bc5cbce5c70b197a789aad1b1d19977892985d Mon Sep 17 00:00:00 2001 From: mandryllo Date: Fri, 5 Dec 2025 10:36:28 +0100 Subject: [PATCH 04/71] Fix kms key id type --- src/v2/components/database/index.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/v2/components/database/index.ts b/src/v2/components/database/index.ts index 297227d..689be95 100644 --- a/src/v2/components/database/index.ts +++ b/src/v2/components/database/index.ts @@ -49,7 +49,7 @@ export class Database extends pulumi.ComponentResource { password: Password; encryptedSnapshotCopy?: aws.rds.SnapshotCopy; monitoringRole?: aws.iam.Role; - kmsKeyId: pulumi.Input; + kmsKeyId: pulumi.Output; constructor( name: string, @@ -80,7 +80,9 @@ export class Database extends pulumi.ComponentResource { { parent: this }, ); - this.kmsKeyId = kmsKeyId || this.createEncryptionKey().arn; + this.kmsKeyId = kmsKeyId + ? pulumi.output(kmsKeyId) + : this.createEncryptionKey().arn; if (enableMonitoring) { this.monitoringRole = this.createMonitoringRole(); From 19c3ece25405a2db66f756b8fc2cc2c281f0ce43 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Fri, 5 Dec 2025 18:16:19 +0100 Subject: [PATCH 05/71] Cleanup --- src/v2/components/database/index.ts | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/v2/components/database/index.ts b/src/v2/components/database/index.ts index 689be95..4f53246 100644 --- a/src/v2/components/database/index.ts +++ b/src/v2/components/database/index.ts @@ -101,7 +101,7 @@ export class Database extends pulumi.ComponentResource { private createSubnetGroup( isolatedSubnetIds: awsx.ec2.Vpc['isolatedSubnetIds'], ) { - const dbSubnetGroup = new aws.rds.SubnetGroup( + return new aws.rds.SubnetGroup( `${this.name}-subnet-group`, { subnetIds: isolatedSubnetIds, @@ -109,14 +109,13 @@ export class Database extends pulumi.ComponentResource { }, { parent: this }, ); - return dbSubnetGroup; } private createSecurityGroup( vpcId: awsx.ec2.Vpc['vpcId'], vpcCidrBlock: pulumi.Input, ) { - const dbSecurityGroup = new aws.ec2.SecurityGroup( + return new aws.ec2.SecurityGroup( `${this.name}-security-group`, { vpcId, @@ -132,11 +131,10 @@ export class Database extends pulumi.ComponentResource { }, { parent: this }, ); - return dbSecurityGroup; } private createEncryptionKey() { - const kms = new aws.kms.Key( + return new aws.kms.Key( `${this.name}-rds-key`, { description: `${this.name} RDS encryption key`, @@ -149,7 +147,6 @@ export class Database extends pulumi.ComponentResource { }, { parent: this }, ); - return kms; } private createMonitoringRole() { @@ -166,7 +163,9 @@ export class Database extends pulumi.ComponentResource { }, ], }, - }); + }, + { parent: this }, + ); new aws.iam.RolePolicyAttachment( `${this.name}-rds-monitoring-role-attachment`, @@ -175,6 +174,7 @@ export class Database extends pulumi.ComponentResource { policyArn: 'arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole', }, + { parent: this }, ); return monitoringRole; @@ -189,8 +189,7 @@ export class Database extends pulumi.ComponentResource { aws.rds.getSnapshot({ dbSnapshotIdentifier: snapshotIdentifier, }), - ) - .apply(snapshot => snapshot.dbSnapshotArn); + ).dbSnapshotArn; const encryptedSnapshotCopy = new aws.rds.SnapshotCopy( `${this.name}-encrypted-snapshot-copy`, From ce83def8f7cdae2675c26e38efe6e3b828627199 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Fri, 5 Dec 2025 18:23:04 +0100 Subject: [PATCH 06/71] Cleanup vpc parameters --- src/v2/components/database/index.ts | 32 ++++++++++++----------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/src/v2/components/database/index.ts b/src/v2/components/database/index.ts index 4f53246..e121cd5 100644 --- a/src/v2/components/database/index.ts +++ b/src/v2/components/database/index.ts @@ -44,12 +44,13 @@ const defaults = { export class Database extends pulumi.ComponentResource { name: string; instance: awsNative.rds.DbInstance; + vpc: pulumi.Output; dbSubnetGroup: aws.rds.SubnetGroup; dbSecurityGroup: aws.ec2.SecurityGroup; password: Password; - encryptedSnapshotCopy?: aws.rds.SnapshotCopy; - monitoringRole?: aws.iam.Role; kmsKeyId: pulumi.Output; + monitoringRole?: aws.iam.Role; + encryptedSnapshotCopy?: aws.rds.SnapshotCopy; constructor( name: string, @@ -62,17 +63,15 @@ export class Database extends pulumi.ComponentResource { const argsWithDefaults = Object.assign({}, defaults, args); const { + vpc, kmsKeyId, - snapshotIdentifier, enableMonitoring, + snapshotIdentifier, } = argsWithDefaults; - const vpc = pulumi.output(argsWithDefaults.vpc); - this.dbSubnetGroup = this.createSubnetGroup(vpc.isolatedSubnetIds); - this.dbSecurityGroup = this.createSecurityGroup( - vpc.vpcId, - vpc.vpc.cidrBlock, - ); + this.vpc = pulumi.output(vpc); + this.dbSubnetGroup = this.createSubnetGroup(); + this.dbSecurityGroup = this.createSecurityGroup(); this.password = new Password( `${this.name}-database-password`, @@ -98,33 +97,28 @@ export class Database extends pulumi.ComponentResource { this.registerOutputs(); } - private createSubnetGroup( - isolatedSubnetIds: awsx.ec2.Vpc['isolatedSubnetIds'], - ) { + private createSubnetGroup() { return new aws.rds.SubnetGroup( `${this.name}-subnet-group`, { - subnetIds: isolatedSubnetIds, + subnetIds: this.vpc.isolatedSubnetIds, tags: commonTags, }, { parent: this }, ); } - private createSecurityGroup( - vpcId: awsx.ec2.Vpc['vpcId'], - vpcCidrBlock: pulumi.Input, - ) { + private createSecurityGroup() { return new aws.ec2.SecurityGroup( `${this.name}-security-group`, { - vpcId, + vpcId: this.vpc.vpcId, ingress: [ { protocol: 'tcp', fromPort: 5432, toPort: 5432, - cidrBlocks: [vpcCidrBlock], + cidrBlocks: [this.vpc.vpc.cidrBlock], }, ], tags: commonTags, From 292b549f4a15373e2ba455d5eac5d45d9d1a8b5f Mon Sep 17 00:00:00 2001 From: mandryllo Date: Fri, 5 Dec 2025 18:31:58 +0100 Subject: [PATCH 07/71] Cleanup types --- src/v2/components/database/index.ts | 36 +++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/src/v2/components/database/index.ts b/src/v2/components/database/index.ts index e121cd5..7ab620c 100644 --- a/src/v2/components/database/index.ts +++ b/src/v2/components/database/index.ts @@ -6,23 +6,41 @@ import { Password } from '../../../components/password'; import { commonTags } from '../../../constants'; export namespace Database { - export type Args = { + export type Instance = { dbName?: pulumi.Input; - username?: pulumi.Input; - password?: pulumi.Input; + engineVersion?: pulumi.Input; + instanceClass?: pulumi.Input; + allowMajorVersionUpgrade?: pulumi.Input; + autoMinorVersionUpgrade?: pulumi.Input; + }; + + export type Networking = { vpc: pulumi.Input; multiAz?: pulumi.Input; - applyImmediately?: pulumi.Input; + }; + + export type Credentials = { + username?: pulumi.Input; + password?: pulumi.Input; + }; + + export type Storage = { allocatedStorage?: pulumi.Input; maxAllocatedStorage?: pulumi.Input; - instanceClass?: pulumi.Input; - allowMajorVersionUpgrade?: pulumi.Input; - autoMinorVersionUpgrade?: pulumi.Input; kmsKeyId?: pulumi.Input; - parameterGroupName?: pulumi.Input; snapshotIdentifier?: pulumi.Input; + }; + + export type Monitoring = { enableMonitoring?: pulumi.Input; - engineVersion?: pulumi.Input; + applyImmediately?: pulumi.Input; + }; + + export type ParameterGroup = { + parameterGroupName?: pulumi.Input; + }; + + export type Args = Instance & Networking & Credentials & Storage & Monitoring & ParameterGroup & { tags?: pulumi.Input<{ [key: string]: pulumi.Input; }>; From d4120ceec0c5f4d8a77c2a8326fbd55bdc317b23 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Fri, 5 Dec 2025 18:32:30 +0100 Subject: [PATCH 08/71] Fix formatting --- src/v2/components/database/index.ts | 53 +++++++++++++++-------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/src/v2/components/database/index.ts b/src/v2/components/database/index.ts index 7ab620c..07b0d54 100644 --- a/src/v2/components/database/index.ts +++ b/src/v2/components/database/index.ts @@ -40,11 +40,16 @@ export namespace Database { parameterGroupName?: pulumi.Input; }; - export type Args = Instance & Networking & Credentials & Storage & Monitoring & ParameterGroup & { - tags?: pulumi.Input<{ - [key: string]: pulumi.Input; - }>; - }; + export type Args = Instance & + Networking & + Credentials & + Storage & + Monitoring & + ParameterGroup & { + tags?: pulumi.Input<{ + [key: string]: pulumi.Input; + }>; + }; } const defaults = { @@ -80,12 +85,8 @@ export class Database extends pulumi.ComponentResource { this.name = name; const argsWithDefaults = Object.assign({}, defaults, args); - const { - vpc, - kmsKeyId, - enableMonitoring, - snapshotIdentifier, - } = argsWithDefaults; + const { vpc, kmsKeyId, enableMonitoring, snapshotIdentifier } = + argsWithDefaults; this.vpc = pulumi.output(vpc); this.dbSubnetGroup = this.createSubnetGroup(); @@ -162,22 +163,24 @@ export class Database extends pulumi.ComponentResource { } private createMonitoringRole() { - const monitoringRole = new aws.iam.Role(`${this.name}-rds-monitoring`, { - assumeRolePolicy: { - Version: '2012-10-17', - Statement: [ - { - Action: 'sts:AssumeRole', - Effect: 'Allow', - Principal: { - Service: 'monitoring.rds.amazonaws.com', + const monitoringRole = new aws.iam.Role( + `${this.name}-rds-monitoring`, + { + assumeRolePolicy: { + Version: '2012-10-17', + Statement: [ + { + Action: 'sts:AssumeRole', + Effect: 'Allow', + Principal: { + Service: 'monitoring.rds.amazonaws.com', + }, }, - }, - ], + ], + }, }, - }, - { parent: this }, - ); + { parent: this }, + ); new aws.iam.RolePolicyAttachment( `${this.name}-rds-monitoring-role-attachment`, From b09a6c0ff024fb8ce049927ae74bad4835b4d5da Mon Sep 17 00:00:00 2001 From: mandryllo Date: Mon, 8 Dec 2025 10:55:58 +0100 Subject: [PATCH 09/71] Cleanup --- src/v2/components/database/index.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/v2/components/database/index.ts b/src/v2/components/database/index.ts index 07b0d54..ff48e7a 100644 --- a/src/v2/components/database/index.ts +++ b/src/v2/components/database/index.ts @@ -206,7 +206,7 @@ export class Database extends pulumi.ComponentResource { }), ).dbSnapshotArn; - const encryptedSnapshotCopy = new aws.rds.SnapshotCopy( + return new aws.rds.SnapshotCopy( `${this.name}-encrypted-snapshot-copy`, { sourceDbSnapshotIdentifier, @@ -215,7 +215,6 @@ export class Database extends pulumi.ComponentResource { }, { parent: this }, ); - return encryptedSnapshotCopy; } private createDatabaseInstance(args: Database.Args) { From 53061fe9366bfbf522f9d716a08efedfcedb416d Mon Sep 17 00:00:00 2001 From: mandryllo Date: Tue, 2 Dec 2025 17:35:43 +0100 Subject: [PATCH 10/71] Create db builder component --- src/v2/components/database/builder.ts | 128 +++++++++++++------------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/src/v2/components/database/builder.ts b/src/v2/components/database/builder.ts index 9cd343c..bc97869 100644 --- a/src/v2/components/database/builder.ts +++ b/src/v2/components/database/builder.ts @@ -1,119 +1,119 @@ -import { Database } from '.'; import * as pulumi from '@pulumi/pulumi'; +import * as aws from '@pulumi/aws'; +import * as awsx from '@pulumi/awsx'; +import { Database } from '.'; + +export namespace DatabaseBuilder { + export type Config = Omit< + Database.Args, + | 'vpc' + | 'enableMonitoring' + | 'parameterGroupName' + | 'customParameterGroupArgs' + | 'kmsKeyId' + | 'snapshotIdentifier' + >; +} export class DatabaseBuilder { - private name: string; - private instanceConfig?: Database.Instance; - private credentialsConfig?: Database.Credentials; - private storageConfig?: Database.Storage; - private vpc?: Database.Args['vpc']; - private enableMonitoring?: Database.Args['enableMonitoring']; - private snapshotIdentifier?: Database.Args['snapshotIdentifier']; - private kmsKeyId?: Database.Args['kmsKeyId']; - private parameterGroupName?: Database.Args['parameterGroupName']; - private tags?: Database.Args['tags']; + private _name: string; + private _config?: DatabaseBuilder.Config; + private _vpc?: Database.Args['vpc']; + private _enableMonitoring?: Database.Args['enableMonitoring']; + private _parameterGroupName?: Database.Args['parameterGroupName']; + private _customParameterGroupArgs?: Database.Args['customParameterGroupArgs']; + private _kmsKeyId?: Database.Args['kmsKeyId']; + private _snapshotIdentifier?: Database.Args['snapshotIdentifier']; constructor(name: string) { - this.name = name; + this._name = name; } - public withInstance(instanceConfig: Database.Instance = {}): this { - this.instanceConfig = instanceConfig; - - return this; - } - - public withCredentials(credentialsConfig: Database.Credentials = {}): this { - this.credentialsConfig = credentialsConfig; - - return this; - } - - public withStorage(storageConfig: Database.Storage = {}): this { - this.storageConfig = storageConfig; + public configure( + dbName: DatabaseBuilder.Config['dbName'], + username: DatabaseBuilder.Config['username'], + config: Omit = {}, + ): this { + this._config = { + dbName, + username, + ...config, + }; return this; } - public withVpc(vpc: Database.Args['vpc']): this { - this.vpc = pulumi.output(vpc); + public withVpc(vpc: pulumi.Input): this { + this._vpc = pulumi.output(vpc); return this; } public withMonitoring(): this { - this.enableMonitoring = true; + this._enableMonitoring = true; return this; } - public withSnapshot( - snapshotIdentifier: Database.Args['snapshotIdentifier'], - ): this { - this.snapshotIdentifier = snapshotIdentifier; + public createFromSnapshot(snapshotIdentifier: pulumi.Input): this { + this._snapshotIdentifier = snapshotIdentifier; return this; } - public withKms(kmsKeyId: Database.Args['kmsKeyId']): this { - this.kmsKeyId = kmsKeyId; + public useExistingParameterGroup( + parameterGroupName: pulumi.Input, + ): this { + this._parameterGroupName = parameterGroupName; return this; } - public withParameterGroup( - parameterGroupName: Database.Args['parameterGroupName'], + public withCustomParameterGroup( + customParameterGroupArgs: pulumi.Input, ): this { - this.parameterGroupName = parameterGroupName; + this._customParameterGroupArgs = customParameterGroupArgs; return this; } - public withTags(tags: Database.Args['tags']): this { - this.tags = tags; + public useExitingKms(kmsKeyId: pulumi.Input): this { + this._kmsKeyId = kmsKeyId; return this; } public build(opts: pulumi.ComponentResourceOptions = {}): Database { - if (!this.snapshotIdentifier && !this.instanceConfig?.dbName) { + if (!this._config && !this._snapshotIdentifier) { throw new Error( - 'DbName not provided. Make sure to call DatabaseBuilder.withInstance() and set dbName.', + `Database is not configured. Make sure to call DatabaseBuilder.configure() + or create it from a snapshot with DatabaseBuilder.createFromSnapshot().`, ); } - if (!this.snapshotIdentifier && !this.credentialsConfig?.username) { + if (!this._vpc) { throw new Error( - 'Username not provided. Make sure to call DatabaseBuilder.withCredentials() and set username.', + 'VPC not provided. Make sure to call DatabaseBuilder.withVpc().', ); } - if (this.snapshotIdentifier && this.instanceConfig?.dbName) { - throw new Error(`You can't set dbName when using snapshotIdentifier.`); - } - - if (this.snapshotIdentifier && this.credentialsConfig?.username) { - throw new Error(`You can't set username when using snapshotIdentifier.`); - } - - if (!this.vpc) { + if (this._parameterGroupName && this._customParameterGroupArgs) { throw new Error( - 'VPC not provided. Make sure to call DatabaseBuilder.withVpc().', + `You can't both use existing parameter group and create a custom one. + Make sure to call either DatabaseBuilder.useExistingParameterGroup() + or DatabaseBuilder.withCustomParameterGroup(), but not both.`, ); } return new Database( - this.name, + this._name, { - ...this.instanceConfig, - ...this.credentialsConfig, - ...this.storageConfig, - vpc: this.vpc, - enableMonitoring: this.enableMonitoring, - snapshotIdentifier: this.snapshotIdentifier, - kmsKeyId: this.kmsKeyId, - parameterGroupName: this.parameterGroupName, - tags: this.tags, + ...this._config, + vpc: this._vpc, + enableMonitoring: this._enableMonitoring, + snapshotIdentifier: this._snapshotIdentifier, + parameterGroupName: this._parameterGroupName, + kmsKeyId: this._kmsKeyId, }, opts, ); From c32427bff18456900ef426e6d1ce2889907ac081 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Wed, 3 Dec 2025 10:46:00 +0100 Subject: [PATCH 11/71] Fix typo --- src/v2/components/database/builder.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/v2/components/database/builder.ts b/src/v2/components/database/builder.ts index bc97869..9f6dfc7 100644 --- a/src/v2/components/database/builder.ts +++ b/src/v2/components/database/builder.ts @@ -77,7 +77,7 @@ export class DatabaseBuilder { return this; } - public useExitingKms(kmsKeyId: pulumi.Input): this { + public useExistingKms(kmsKeyId: pulumi.Input): this { this._kmsKeyId = kmsKeyId; return this; From cb12a135e5c7cfcb97183f76cf31c48dff710dd5 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Fri, 5 Dec 2025 18:33:24 +0100 Subject: [PATCH 12/71] Remove custom parameter group args --- src/v2/components/database/builder.ts | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/v2/components/database/builder.ts b/src/v2/components/database/builder.ts index 9f6dfc7..be232ba 100644 --- a/src/v2/components/database/builder.ts +++ b/src/v2/components/database/builder.ts @@ -21,7 +21,6 @@ export class DatabaseBuilder { private _vpc?: Database.Args['vpc']; private _enableMonitoring?: Database.Args['enableMonitoring']; private _parameterGroupName?: Database.Args['parameterGroupName']; - private _customParameterGroupArgs?: Database.Args['customParameterGroupArgs']; private _kmsKeyId?: Database.Args['kmsKeyId']; private _snapshotIdentifier?: Database.Args['snapshotIdentifier']; @@ -69,14 +68,6 @@ export class DatabaseBuilder { return this; } - public withCustomParameterGroup( - customParameterGroupArgs: pulumi.Input, - ): this { - this._customParameterGroupArgs = customParameterGroupArgs; - - return this; - } - public useExistingKms(kmsKeyId: pulumi.Input): this { this._kmsKeyId = kmsKeyId; @@ -97,14 +88,6 @@ export class DatabaseBuilder { ); } - if (this._parameterGroupName && this._customParameterGroupArgs) { - throw new Error( - `You can't both use existing parameter group and create a custom one. - Make sure to call either DatabaseBuilder.useExistingParameterGroup() - or DatabaseBuilder.withCustomParameterGroup(), but not both.`, - ); - } - return new Database( this._name, { From 784af7f3df16dc88c693e92cdbc810b79ad7cb63 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Fri, 5 Dec 2025 18:34:14 +0100 Subject: [PATCH 13/71] Cleanup private props --- src/v2/components/database/builder.ts | 46 +++++++++++++-------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/v2/components/database/builder.ts b/src/v2/components/database/builder.ts index be232ba..1821517 100644 --- a/src/v2/components/database/builder.ts +++ b/src/v2/components/database/builder.ts @@ -16,16 +16,16 @@ export namespace DatabaseBuilder { } export class DatabaseBuilder { - private _name: string; - private _config?: DatabaseBuilder.Config; - private _vpc?: Database.Args['vpc']; - private _enableMonitoring?: Database.Args['enableMonitoring']; - private _parameterGroupName?: Database.Args['parameterGroupName']; - private _kmsKeyId?: Database.Args['kmsKeyId']; - private _snapshotIdentifier?: Database.Args['snapshotIdentifier']; + private name: string; + private config?: DatabaseBuilder.Config; + private vpc?: Database.Args['vpc']; + private enableMonitoring?: Database.Args['enableMonitoring']; + private parameterGroupName?: Database.Args['parameterGroupName']; + private kmsKeyId?: Database.Args['kmsKeyId']; + private snapshotIdentifier?: Database.Args['snapshotIdentifier']; constructor(name: string) { - this._name = name; + this.name = name; } public configure( @@ -33,7 +33,7 @@ export class DatabaseBuilder { username: DatabaseBuilder.Config['username'], config: Omit = {}, ): this { - this._config = { + this.config = { dbName, username, ...config, @@ -43,19 +43,19 @@ export class DatabaseBuilder { } public withVpc(vpc: pulumi.Input): this { - this._vpc = pulumi.output(vpc); + this.vpc = pulumi.output(vpc); return this; } public withMonitoring(): this { - this._enableMonitoring = true; + this.enableMonitoring = true; return this; } public createFromSnapshot(snapshotIdentifier: pulumi.Input): this { - this._snapshotIdentifier = snapshotIdentifier; + this.snapshotIdentifier = snapshotIdentifier; return this; } @@ -63,40 +63,40 @@ export class DatabaseBuilder { public useExistingParameterGroup( parameterGroupName: pulumi.Input, ): this { - this._parameterGroupName = parameterGroupName; + this.parameterGroupName = parameterGroupName; return this; } public useExistingKms(kmsKeyId: pulumi.Input): this { - this._kmsKeyId = kmsKeyId; + this.kmsKeyId = kmsKeyId; return this; } public build(opts: pulumi.ComponentResourceOptions = {}): Database { - if (!this._config && !this._snapshotIdentifier) { + if (!this.config && !this.snapshotIdentifier) { throw new Error( `Database is not configured. Make sure to call DatabaseBuilder.configure() or create it from a snapshot with DatabaseBuilder.createFromSnapshot().`, ); } - if (!this._vpc) { + if (!this.vpc) { throw new Error( 'VPC not provided. Make sure to call DatabaseBuilder.withVpc().', ); } return new Database( - this._name, + this.name, { - ...this._config, - vpc: this._vpc, - enableMonitoring: this._enableMonitoring, - snapshotIdentifier: this._snapshotIdentifier, - parameterGroupName: this._parameterGroupName, - kmsKeyId: this._kmsKeyId, + ...this.config, + vpc: this.vpc, + enableMonitoring: this.enableMonitoring, + snapshotIdentifier: this.snapshotIdentifier, + parameterGroupName: this.parameterGroupName, + kmsKeyId: this.kmsKeyId, }, opts, ); From 4df93636b0c97979370776e956d97c7b780716f4 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Fri, 5 Dec 2025 18:34:53 +0100 Subject: [PATCH 14/71] Remove parameter group name from builder --- src/v2/components/database/builder.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/v2/components/database/builder.ts b/src/v2/components/database/builder.ts index 1821517..478847b 100644 --- a/src/v2/components/database/builder.ts +++ b/src/v2/components/database/builder.ts @@ -8,7 +8,6 @@ export namespace DatabaseBuilder { Database.Args, | 'vpc' | 'enableMonitoring' - | 'parameterGroupName' | 'customParameterGroupArgs' | 'kmsKeyId' | 'snapshotIdentifier' @@ -20,7 +19,6 @@ export class DatabaseBuilder { private config?: DatabaseBuilder.Config; private vpc?: Database.Args['vpc']; private enableMonitoring?: Database.Args['enableMonitoring']; - private parameterGroupName?: Database.Args['parameterGroupName']; private kmsKeyId?: Database.Args['kmsKeyId']; private snapshotIdentifier?: Database.Args['snapshotIdentifier']; @@ -60,14 +58,6 @@ export class DatabaseBuilder { return this; } - public useExistingParameterGroup( - parameterGroupName: pulumi.Input, - ): this { - this.parameterGroupName = parameterGroupName; - - return this; - } - public useExistingKms(kmsKeyId: pulumi.Input): this { this.kmsKeyId = kmsKeyId; @@ -95,7 +85,6 @@ export class DatabaseBuilder { vpc: this.vpc, enableMonitoring: this.enableMonitoring, snapshotIdentifier: this.snapshotIdentifier, - parameterGroupName: this.parameterGroupName, kmsKeyId: this.kmsKeyId, }, opts, From b439523132e9888ffac8d125a2ec5dc7f51f8668 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Fri, 5 Dec 2025 18:36:31 +0100 Subject: [PATCH 15/71] Cleanup naming --- src/v2/components/database/builder.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/v2/components/database/builder.ts b/src/v2/components/database/builder.ts index 478847b..9378b7a 100644 --- a/src/v2/components/database/builder.ts +++ b/src/v2/components/database/builder.ts @@ -8,7 +8,6 @@ export namespace DatabaseBuilder { Database.Args, | 'vpc' | 'enableMonitoring' - | 'customParameterGroupArgs' | 'kmsKeyId' | 'snapshotIdentifier' >; @@ -52,23 +51,22 @@ export class DatabaseBuilder { return this; } - public createFromSnapshot(snapshotIdentifier: pulumi.Input): this { + public withSnapshot(snapshotIdentifier: pulumi.Input): this { this.snapshotIdentifier = snapshotIdentifier; return this; } - public useExistingKms(kmsKeyId: pulumi.Input): this { + public withKms(kmsKeyId: pulumi.Input): this { this.kmsKeyId = kmsKeyId; return this; } public build(opts: pulumi.ComponentResourceOptions = {}): Database { - if (!this.config && !this.snapshotIdentifier) { + if (!this.config) { throw new Error( - `Database is not configured. Make sure to call DatabaseBuilder.configure() - or create it from a snapshot with DatabaseBuilder.createFromSnapshot().`, + `Database is not configured. Make sure to call DatabaseBuilder.configure().`, ); } From 019579710898176e4fae3a01086ba72e164c729a Mon Sep 17 00:00:00 2001 From: mandryllo Date: Fri, 5 Dec 2025 18:36:57 +0100 Subject: [PATCH 16/71] Fix formatting --- src/v2/components/database/builder.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/v2/components/database/builder.ts b/src/v2/components/database/builder.ts index 9378b7a..50b7eec 100644 --- a/src/v2/components/database/builder.ts +++ b/src/v2/components/database/builder.ts @@ -6,10 +6,7 @@ import { Database } from '.'; export namespace DatabaseBuilder { export type Config = Omit< Database.Args, - | 'vpc' - | 'enableMonitoring' - | 'kmsKeyId' - | 'snapshotIdentifier' + 'vpc' | 'enableMonitoring' | 'kmsKeyId' | 'snapshotIdentifier' >; } From 2d399cfbe50f8b044f4010fbf6134393f2e238d4 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Mon, 8 Dec 2025 11:02:29 +0100 Subject: [PATCH 17/71] Cleanup --- src/v2/components/database/builder.ts | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/v2/components/database/builder.ts b/src/v2/components/database/builder.ts index 50b7eec..2ed2af2 100644 --- a/src/v2/components/database/builder.ts +++ b/src/v2/components/database/builder.ts @@ -22,16 +22,8 @@ export class DatabaseBuilder { this.name = name; } - public configure( - dbName: DatabaseBuilder.Config['dbName'], - username: DatabaseBuilder.Config['username'], - config: Omit = {}, - ): this { - this.config = { - dbName, - username, - ...config, - }; + public withConfiguration(config: DatabaseBuilder.Config = {}): this { + this.config = config; return this; } @@ -63,7 +55,7 @@ export class DatabaseBuilder { public build(opts: pulumi.ComponentResourceOptions = {}): Database { if (!this.config) { throw new Error( - `Database is not configured. Make sure to call DatabaseBuilder.configure().`, + `Database is not configured. Make sure to call DatabaseBuilder.withConfiguration().`, ); } @@ -73,6 +65,15 @@ export class DatabaseBuilder { ); } + if ( + this.snapshotIdentifier && + (this.config.dbName || this.config.username) + ) { + throw new Error( + `You can't set dbName or username when using snapshotIdentifier.`, + ); + } + return new Database( this.name, { From b17a54f20756f3833b9ab20bc10e4776ce5e6c86 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Wed, 3 Dec 2025 11:20:04 +0100 Subject: [PATCH 18/71] Expose db v2 components --- src/v2/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/v2/index.ts b/src/v2/index.ts index aaaabc7..cc2a848 100644 --- a/src/v2/index.ts +++ b/src/v2/index.ts @@ -5,6 +5,8 @@ export { WebServerLoadBalancer } from './components/web-server/load-balancer'; export { ElastiCacheRedis } from './components/redis/elasticache-redis'; export { UpstashRedis } from './components/redis/upstash-redis'; export { Vpc } from './components/vpc'; +export { Database } from './components/database'; +export { DatabaseBuilder } from './components/database/builder'; import { OtelCollectorBuilder } from './otel/builder'; import { OtelCollector } from './otel'; From def9885c8baef041836ab4fc25d2410ead8fd1b9 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Mon, 8 Dec 2025 11:46:04 +0100 Subject: [PATCH 19/71] Add type tests --- tests/build/index.tst.ts | 60 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/tests/build/index.tst.ts b/tests/build/index.tst.ts index 749e9af..669f2b6 100644 --- a/tests/build/index.tst.ts +++ b/tests/build/index.tst.ts @@ -258,4 +258,64 @@ describe('Build output', () => { }); }); }); + + describe('Database', () => { + it('should export Database', () => { + expect(studion).type.toHaveProperty('Database'); + }); + + it('should export DatabaseBuilder', () => { + expect(studion).type.toHaveProperty('DatabaseBuilder'); + }); + + describe('Instantiation', () => { + const { Database, DatabaseBuilder } = studion; + + it('should construct Database', () => { + expect(Database).type.toBeConstructableWith('db-test', { + vpc: new awsx.ec2.Vpc('vpcName'), + dbName: 'dbName', + username: 'username', + }); + }); + + it('should construct DatabaseBuilder', () => { + expect(DatabaseBuilder).type.toBeConstructableWith('db-test'); + }); + }); + + describe('Builder', () => { + const builder = new studion.DatabaseBuilder('db-test'); + + it('should have build method', () => { + expect(builder.build).type.toBeCallableWith(); + }); + + it('should have withConfiguration method', () => { + expect(builder.withConfiguration).type.toBeCallableWith({ + dbName: 'dbName', + username: 'username', + password: 'password', + }); + }); + + it('should have withVpc method', () => { + expect(builder.withVpc).type.toBeCallableWith( + new awsx.ec2.Vpc('vpcName'), + ); + }); + + it('should have withMonitoring method', () => { + expect(builder.withMonitoring).type.toBeCallableWith(); + }); + + it('should have withSnapshot method', () => { + expect(builder.withSnapshot).type.toBeCallableWith('snapshot-id'); + }); + + it('should have withKms method', () => { + expect(builder.withKms).type.toBeCallableWith('kms-key-id'); + }); + }); + }); }); From 9cc3856714e9d93b1f7922bf6e11895cf6677c68 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Mon, 8 Dec 2025 11:49:43 +0100 Subject: [PATCH 20/71] Add default db tests --- package-lock.json | 1932 ++++++++++++++++++++--- package.json | 2 + tests/database/default-db.test.ts | 203 +++ tests/database/index.test.ts | 40 + tests/database/infrastructure/config.ts | 11 + tests/database/infrastructure/index.ts | 16 + tests/database/test-context.ts | 37 + 7 files changed, 2005 insertions(+), 236 deletions(-) create mode 100644 tests/database/default-db.test.ts create mode 100644 tests/database/index.test.ts create mode 100644 tests/database/infrastructure/config.ts create mode 100644 tests/database/infrastructure/index.ts create mode 100644 tests/database/test-context.ts diff --git a/package-lock.json b/package-lock.json index d1f5943..5b7a0d1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,6 +27,8 @@ "@aws-sdk/client-efs": "^3.758.0", "@aws-sdk/client-elastic-load-balancing-v2": "^3.764.0", "@aws-sdk/client-elasticache": "^3.901.0", + "@aws-sdk/client-kms": "^3.943.0", + "@aws-sdk/client-rds": "^3.943.0", "@aws-sdk/client-route-53": "^3.782.0", "@aws-sdk/client-secrets-manager": "^3.906.0", "@aws-sdk/client-servicediscovery": "^3.758.0", @@ -1539,6 +1541,1110 @@ ], "license": "MIT" }, + "node_modules/@aws-sdk/client-kms": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-kms/-/client-kms-3.943.0.tgz", + "integrity": "sha512-JKMOk0kP6cibt/BxPy211g+S8tTzx+Qzt/RbmlhGK5+2lSE+9aSg54SG0FsoagntT9tm4zeR0vs/8c6eTR4jSQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.943.0", + "@aws-sdk/credential-provider-node": "3.943.0", + "@aws-sdk/middleware-host-header": "3.936.0", + "@aws-sdk/middleware-logger": "3.936.0", + "@aws-sdk/middleware-recursion-detection": "3.936.0", + "@aws-sdk/middleware-user-agent": "3.943.0", + "@aws-sdk/region-config-resolver": "3.936.0", + "@aws-sdk/types": "3.936.0", + "@aws-sdk/util-endpoints": "3.936.0", + "@aws-sdk/util-user-agent-browser": "3.936.0", + "@aws-sdk/util-user-agent-node": "3.943.0", + "@smithy/config-resolver": "^4.4.3", + "@smithy/core": "^3.18.5", + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/hash-node": "^4.2.5", + "@smithy/invalid-dependency": "^4.2.5", + "@smithy/middleware-content-length": "^4.2.5", + "@smithy/middleware-endpoint": "^4.3.12", + "@smithy/middleware-retry": "^4.4.12", + "@smithy/middleware-serde": "^4.2.6", + "@smithy/middleware-stack": "^4.2.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/smithy-client": "^4.9.8", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.11", + "@smithy/util-defaults-mode-node": "^4.2.14", + "@smithy/util-endpoints": "^3.2.5", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-retry": "^4.2.5", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kms/node_modules/@aws-sdk/client-sso": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.943.0.tgz", + "integrity": "sha512-kOTO2B8Ks2qX73CyKY8PAajtf5n39aMe2spoiOF5EkgSzGV7hZ/HONRDyADlyxwfsX39Q2F2SpPUaXzon32IGw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.943.0", + "@aws-sdk/middleware-host-header": "3.936.0", + "@aws-sdk/middleware-logger": "3.936.0", + "@aws-sdk/middleware-recursion-detection": "3.936.0", + "@aws-sdk/middleware-user-agent": "3.943.0", + "@aws-sdk/region-config-resolver": "3.936.0", + "@aws-sdk/types": "3.936.0", + "@aws-sdk/util-endpoints": "3.936.0", + "@aws-sdk/util-user-agent-browser": "3.936.0", + "@aws-sdk/util-user-agent-node": "3.943.0", + "@smithy/config-resolver": "^4.4.3", + "@smithy/core": "^3.18.5", + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/hash-node": "^4.2.5", + "@smithy/invalid-dependency": "^4.2.5", + "@smithy/middleware-content-length": "^4.2.5", + "@smithy/middleware-endpoint": "^4.3.12", + "@smithy/middleware-retry": "^4.4.12", + "@smithy/middleware-serde": "^4.2.6", + "@smithy/middleware-stack": "^4.2.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/smithy-client": "^4.9.8", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.11", + "@smithy/util-defaults-mode-node": "^4.2.14", + "@smithy/util-endpoints": "^3.2.5", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-retry": "^4.2.5", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kms/node_modules/@aws-sdk/core": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.943.0.tgz", + "integrity": "sha512-8CBy2hI9ABF7RBVQuY1bgf/ue+WPmM/hl0adrXFlhnhkaQP0tFY5zhiy1Y+n7V+5f3/ORoHBmCCQmcHDDYJqJQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.936.0", + "@aws-sdk/xml-builder": "3.930.0", + "@smithy/core": "^3.18.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/signature-v4": "^5.3.5", + "@smithy/smithy-client": "^4.9.8", + "@smithy/types": "^4.9.0", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kms/node_modules/@aws-sdk/credential-provider-env": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.943.0.tgz", + "integrity": "sha512-WnS5w9fK9CTuoZRVSIHLOMcI63oODg9qd1vXMYb7QGLGlfwUm4aG3hdu7i9XvYrpkQfE3dzwWLtXF4ZBuL1Tew==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kms/node_modules/@aws-sdk/credential-provider-http": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.943.0.tgz", + "integrity": "sha512-SA8bUcYDEACdhnhLpZNnWusBpdmj4Vl67Vxp3Zke7SvoWSYbuxa+tiDiC+c92Z4Yq6xNOuLPW912ZPb9/NsSkA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/smithy-client": "^4.9.8", + "@smithy/types": "^4.9.0", + "@smithy/util-stream": "^4.5.6", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kms/node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.943.0.tgz", + "integrity": "sha512-BcLDb8l4oVW+NkuqXMlO7TnM6lBOWW318ylf4FRED/ply5eaGxkQYqdGvHSqGSN5Rb3vr5Ek0xpzSjeYD7C8Kw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.943.0", + "@aws-sdk/credential-provider-env": "3.943.0", + "@aws-sdk/credential-provider-http": "3.943.0", + "@aws-sdk/credential-provider-login": "3.943.0", + "@aws-sdk/credential-provider-process": "3.943.0", + "@aws-sdk/credential-provider-sso": "3.943.0", + "@aws-sdk/credential-provider-web-identity": "3.943.0", + "@aws-sdk/nested-clients": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/credential-provider-imds": "^4.2.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kms/node_modules/@aws-sdk/credential-provider-node": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.943.0.tgz", + "integrity": "sha512-14eddaH/gjCWoLSAELVrFOQNyswUYwWphIt+PdsJ/FqVfP4ay2HsiZVEIYbQtmrKHaoLJhiZKwBQRjcqJDZG0w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.943.0", + "@aws-sdk/credential-provider-http": "3.943.0", + "@aws-sdk/credential-provider-ini": "3.943.0", + "@aws-sdk/credential-provider-process": "3.943.0", + "@aws-sdk/credential-provider-sso": "3.943.0", + "@aws-sdk/credential-provider-web-identity": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/credential-provider-imds": "^4.2.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kms/node_modules/@aws-sdk/credential-provider-process": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.943.0.tgz", + "integrity": "sha512-GIY/vUkthL33AdjOJ8r9vOosKf/3X+X7LIiACzGxvZZrtoOiRq0LADppdiKIB48vTL63VvW+eRIOFAxE6UDekw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kms/node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.943.0.tgz", + "integrity": "sha512-1c5G11syUrru3D9OO6Uk+ul5e2lX1adb+7zQNyluNaLPXP6Dina6Sy6DFGRLu7tM8+M7luYmbS3w63rpYpaL+A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/client-sso": "3.943.0", + "@aws-sdk/core": "3.943.0", + "@aws-sdk/token-providers": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kms/node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.943.0.tgz", + "integrity": "sha512-VtyGKHxICSb4kKGuaqotxso8JVM8RjCS3UYdIMOxUt9TaFE/CZIfZKtjTr+IJ7M0P7t36wuSUb/jRLyNmGzUUA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.943.0", + "@aws-sdk/nested-clients": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kms/node_modules/@aws-sdk/middleware-host-header": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.936.0.tgz", + "integrity": "sha512-tAaObaAnsP1XnLGndfkGWFuzrJYuk9W0b/nLvol66t8FZExIAf/WdkT2NNAWOYxljVs++oHnyHBCxIlaHrzSiw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.936.0", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kms/node_modules/@aws-sdk/middleware-logger": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.936.0.tgz", + "integrity": "sha512-aPSJ12d3a3Ea5nyEnLbijCaaYJT2QjQ9iW+zGh5QcZYXmOGWbKVyPSxmVOboZQG+c1M8t6d2O7tqrwzIq8L8qw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.936.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kms/node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.936.0.tgz", + "integrity": "sha512-l4aGbHpXM45YNgXggIux1HgsCVAvvBoqHPkqLnqMl9QVapfuSTjJHfDYDsx1Xxct6/m7qSMUzanBALhiaGO2fA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.936.0", + "@aws/lambda-invoke-store": "^0.2.0", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kms/node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.943.0.tgz", + "integrity": "sha512-956n4kVEwFNXndXfhSAN5wO+KRgqiWEEY+ECwLvxmmO8uQ0NWOa8l6l65nTtyuiWzMX81c9BvlyNR5EgUeeUvA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@aws-sdk/util-endpoints": "3.936.0", + "@smithy/core": "^3.18.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kms/node_modules/@aws-sdk/nested-clients": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.943.0.tgz", + "integrity": "sha512-anFtB0p2FPuyUnbOULwGmKYqYKSq1M73c9uZ08jR/NCq6Trjq9cuF5TFTeHwjJyPRb4wMf2Qk859oiVfFqnQiw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.943.0", + "@aws-sdk/middleware-host-header": "3.936.0", + "@aws-sdk/middleware-logger": "3.936.0", + "@aws-sdk/middleware-recursion-detection": "3.936.0", + "@aws-sdk/middleware-user-agent": "3.943.0", + "@aws-sdk/region-config-resolver": "3.936.0", + "@aws-sdk/types": "3.936.0", + "@aws-sdk/util-endpoints": "3.936.0", + "@aws-sdk/util-user-agent-browser": "3.936.0", + "@aws-sdk/util-user-agent-node": "3.943.0", + "@smithy/config-resolver": "^4.4.3", + "@smithy/core": "^3.18.5", + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/hash-node": "^4.2.5", + "@smithy/invalid-dependency": "^4.2.5", + "@smithy/middleware-content-length": "^4.2.5", + "@smithy/middleware-endpoint": "^4.3.12", + "@smithy/middleware-retry": "^4.4.12", + "@smithy/middleware-serde": "^4.2.6", + "@smithy/middleware-stack": "^4.2.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/smithy-client": "^4.9.8", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.11", + "@smithy/util-defaults-mode-node": "^4.2.14", + "@smithy/util-endpoints": "^3.2.5", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-retry": "^4.2.5", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kms/node_modules/@aws-sdk/region-config-resolver": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.936.0.tgz", + "integrity": "sha512-wOKhzzWsshXGduxO4pqSiNyL9oUtk4BEvjWm9aaq6Hmfdoydq6v6t0rAGHWPjFwy9z2haovGRi3C8IxdMB4muw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.936.0", + "@smithy/config-resolver": "^4.4.3", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kms/node_modules/@aws-sdk/token-providers": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.943.0.tgz", + "integrity": "sha512-cRKyIzwfkS+XztXIFPoWORuaxlIswP+a83BJzelX4S1gUZ7FcXB4+lj9Jxjn8SbQhR4TPU3Owbpu+S7pd6IRbQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.943.0", + "@aws-sdk/nested-clients": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kms/node_modules/@aws-sdk/types": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.936.0.tgz", + "integrity": "sha512-uz0/VlMd2pP5MepdrHizd+T+OKfyK4r3OA9JI+L/lPKg0YFQosdJNCKisr6o70E3dh8iMpFYxF1UN/4uZsyARg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kms/node_modules/@aws-sdk/util-endpoints": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.936.0.tgz", + "integrity": "sha512-0Zx3Ntdpu+z9Wlm7JKUBOzS9EunwKAb4KdGUQQxDqh5Lc3ta5uBoub+FgmVuzwnmBu9U1Os8UuwVTH0Lgu+P5w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.936.0", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-endpoints": "^3.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kms/node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.936.0.tgz", + "integrity": "sha512-eZ/XF6NxMtu+iCma58GRNRxSq4lHo6zHQLOZRIeL/ghqYJirqHdenMOwrzPettj60KWlv827RVebP9oNVrwZbw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.936.0", + "@smithy/types": "^4.9.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-kms/node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.943.0.tgz", + "integrity": "sha512-gn+ILprVRrgAgTIBk2TDsJLRClzIOdStQFeFTcN0qpL8Z4GBCqMFhw7O7X+MM55Stt5s4jAauQ/VvoqmCADnQg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/middleware-user-agent": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "node_modules/@aws-sdk/client-kms/node_modules/@aws-sdk/xml-builder": { + "version": "3.930.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.930.0.tgz", + "integrity": "sha512-YIfkD17GocxdmlUVc3ia52QhcWuRIUJonbF8A2CYfcWNV3HzvAqpcPeC0bYUhkK+8e8YO1ARnLKZQE0TlwzorA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "fast-xml-parser": "5.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kms/node_modules/@aws/lambda-invoke-store": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.1.tgz", + "integrity": "sha512-sIyFcoPZkTtNu9xFeEoynMef3bPJIAbOfUh+ueYcfhVl6xm2VRtMcMclSxmZCMnHHd4hlYKJeq/aggmBEWynww==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kms/node_modules/fast-xml-parser": { + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz", + "integrity": "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "strnum": "^2.1.0" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/@aws-sdk/client-kms/node_modules/strnum": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.1.tgz", + "integrity": "sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, + "node_modules/@aws-sdk/client-rds": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-rds/-/client-rds-3.943.0.tgz", + "integrity": "sha512-Rn2yGj2mYy1HtiYCwWuUF5ZKPx30JqaWMCDDr08gDv1d6P0aXGeT7r4F/ghod9JRa6r4uEGC6r6u/rIJi5vOSg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.943.0", + "@aws-sdk/credential-provider-node": "3.943.0", + "@aws-sdk/middleware-host-header": "3.936.0", + "@aws-sdk/middleware-logger": "3.936.0", + "@aws-sdk/middleware-recursion-detection": "3.936.0", + "@aws-sdk/middleware-sdk-rds": "3.936.0", + "@aws-sdk/middleware-user-agent": "3.943.0", + "@aws-sdk/region-config-resolver": "3.936.0", + "@aws-sdk/types": "3.936.0", + "@aws-sdk/util-endpoints": "3.936.0", + "@aws-sdk/util-user-agent-browser": "3.936.0", + "@aws-sdk/util-user-agent-node": "3.943.0", + "@smithy/config-resolver": "^4.4.3", + "@smithy/core": "^3.18.5", + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/hash-node": "^4.2.5", + "@smithy/invalid-dependency": "^4.2.5", + "@smithy/middleware-content-length": "^4.2.5", + "@smithy/middleware-endpoint": "^4.3.12", + "@smithy/middleware-retry": "^4.4.12", + "@smithy/middleware-serde": "^4.2.6", + "@smithy/middleware-stack": "^4.2.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/smithy-client": "^4.9.8", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.11", + "@smithy/util-defaults-mode-node": "^4.2.14", + "@smithy/util-endpoints": "^3.2.5", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-retry": "^4.2.5", + "@smithy/util-utf8": "^4.2.0", + "@smithy/util-waiter": "^4.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/client-sso": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.943.0.tgz", + "integrity": "sha512-kOTO2B8Ks2qX73CyKY8PAajtf5n39aMe2spoiOF5EkgSzGV7hZ/HONRDyADlyxwfsX39Q2F2SpPUaXzon32IGw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.943.0", + "@aws-sdk/middleware-host-header": "3.936.0", + "@aws-sdk/middleware-logger": "3.936.0", + "@aws-sdk/middleware-recursion-detection": "3.936.0", + "@aws-sdk/middleware-user-agent": "3.943.0", + "@aws-sdk/region-config-resolver": "3.936.0", + "@aws-sdk/types": "3.936.0", + "@aws-sdk/util-endpoints": "3.936.0", + "@aws-sdk/util-user-agent-browser": "3.936.0", + "@aws-sdk/util-user-agent-node": "3.943.0", + "@smithy/config-resolver": "^4.4.3", + "@smithy/core": "^3.18.5", + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/hash-node": "^4.2.5", + "@smithy/invalid-dependency": "^4.2.5", + "@smithy/middleware-content-length": "^4.2.5", + "@smithy/middleware-endpoint": "^4.3.12", + "@smithy/middleware-retry": "^4.4.12", + "@smithy/middleware-serde": "^4.2.6", + "@smithy/middleware-stack": "^4.2.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/smithy-client": "^4.9.8", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.11", + "@smithy/util-defaults-mode-node": "^4.2.14", + "@smithy/util-endpoints": "^3.2.5", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-retry": "^4.2.5", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/core": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.943.0.tgz", + "integrity": "sha512-8CBy2hI9ABF7RBVQuY1bgf/ue+WPmM/hl0adrXFlhnhkaQP0tFY5zhiy1Y+n7V+5f3/ORoHBmCCQmcHDDYJqJQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.936.0", + "@aws-sdk/xml-builder": "3.930.0", + "@smithy/core": "^3.18.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/signature-v4": "^5.3.5", + "@smithy/smithy-client": "^4.9.8", + "@smithy/types": "^4.9.0", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/credential-provider-env": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.943.0.tgz", + "integrity": "sha512-WnS5w9fK9CTuoZRVSIHLOMcI63oODg9qd1vXMYb7QGLGlfwUm4aG3hdu7i9XvYrpkQfE3dzwWLtXF4ZBuL1Tew==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/credential-provider-http": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.943.0.tgz", + "integrity": "sha512-SA8bUcYDEACdhnhLpZNnWusBpdmj4Vl67Vxp3Zke7SvoWSYbuxa+tiDiC+c92Z4Yq6xNOuLPW912ZPb9/NsSkA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/smithy-client": "^4.9.8", + "@smithy/types": "^4.9.0", + "@smithy/util-stream": "^4.5.6", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.943.0.tgz", + "integrity": "sha512-BcLDb8l4oVW+NkuqXMlO7TnM6lBOWW318ylf4FRED/ply5eaGxkQYqdGvHSqGSN5Rb3vr5Ek0xpzSjeYD7C8Kw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.943.0", + "@aws-sdk/credential-provider-env": "3.943.0", + "@aws-sdk/credential-provider-http": "3.943.0", + "@aws-sdk/credential-provider-login": "3.943.0", + "@aws-sdk/credential-provider-process": "3.943.0", + "@aws-sdk/credential-provider-sso": "3.943.0", + "@aws-sdk/credential-provider-web-identity": "3.943.0", + "@aws-sdk/nested-clients": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/credential-provider-imds": "^4.2.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/credential-provider-node": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.943.0.tgz", + "integrity": "sha512-14eddaH/gjCWoLSAELVrFOQNyswUYwWphIt+PdsJ/FqVfP4ay2HsiZVEIYbQtmrKHaoLJhiZKwBQRjcqJDZG0w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.943.0", + "@aws-sdk/credential-provider-http": "3.943.0", + "@aws-sdk/credential-provider-ini": "3.943.0", + "@aws-sdk/credential-provider-process": "3.943.0", + "@aws-sdk/credential-provider-sso": "3.943.0", + "@aws-sdk/credential-provider-web-identity": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/credential-provider-imds": "^4.2.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/credential-provider-process": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.943.0.tgz", + "integrity": "sha512-GIY/vUkthL33AdjOJ8r9vOosKf/3X+X7LIiACzGxvZZrtoOiRq0LADppdiKIB48vTL63VvW+eRIOFAxE6UDekw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.943.0.tgz", + "integrity": "sha512-1c5G11syUrru3D9OO6Uk+ul5e2lX1adb+7zQNyluNaLPXP6Dina6Sy6DFGRLu7tM8+M7luYmbS3w63rpYpaL+A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/client-sso": "3.943.0", + "@aws-sdk/core": "3.943.0", + "@aws-sdk/token-providers": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.943.0.tgz", + "integrity": "sha512-VtyGKHxICSb4kKGuaqotxso8JVM8RjCS3UYdIMOxUt9TaFE/CZIfZKtjTr+IJ7M0P7t36wuSUb/jRLyNmGzUUA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.943.0", + "@aws-sdk/nested-clients": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/middleware-host-header": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.936.0.tgz", + "integrity": "sha512-tAaObaAnsP1XnLGndfkGWFuzrJYuk9W0b/nLvol66t8FZExIAf/WdkT2NNAWOYxljVs++oHnyHBCxIlaHrzSiw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.936.0", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/middleware-logger": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.936.0.tgz", + "integrity": "sha512-aPSJ12d3a3Ea5nyEnLbijCaaYJT2QjQ9iW+zGh5QcZYXmOGWbKVyPSxmVOboZQG+c1M8t6d2O7tqrwzIq8L8qw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.936.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.936.0.tgz", + "integrity": "sha512-l4aGbHpXM45YNgXggIux1HgsCVAvvBoqHPkqLnqMl9QVapfuSTjJHfDYDsx1Xxct6/m7qSMUzanBALhiaGO2fA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.936.0", + "@aws/lambda-invoke-store": "^0.2.0", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.943.0.tgz", + "integrity": "sha512-956n4kVEwFNXndXfhSAN5wO+KRgqiWEEY+ECwLvxmmO8uQ0NWOa8l6l65nTtyuiWzMX81c9BvlyNR5EgUeeUvA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@aws-sdk/util-endpoints": "3.936.0", + "@smithy/core": "^3.18.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/nested-clients": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.943.0.tgz", + "integrity": "sha512-anFtB0p2FPuyUnbOULwGmKYqYKSq1M73c9uZ08jR/NCq6Trjq9cuF5TFTeHwjJyPRb4wMf2Qk859oiVfFqnQiw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.943.0", + "@aws-sdk/middleware-host-header": "3.936.0", + "@aws-sdk/middleware-logger": "3.936.0", + "@aws-sdk/middleware-recursion-detection": "3.936.0", + "@aws-sdk/middleware-user-agent": "3.943.0", + "@aws-sdk/region-config-resolver": "3.936.0", + "@aws-sdk/types": "3.936.0", + "@aws-sdk/util-endpoints": "3.936.0", + "@aws-sdk/util-user-agent-browser": "3.936.0", + "@aws-sdk/util-user-agent-node": "3.943.0", + "@smithy/config-resolver": "^4.4.3", + "@smithy/core": "^3.18.5", + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/hash-node": "^4.2.5", + "@smithy/invalid-dependency": "^4.2.5", + "@smithy/middleware-content-length": "^4.2.5", + "@smithy/middleware-endpoint": "^4.3.12", + "@smithy/middleware-retry": "^4.4.12", + "@smithy/middleware-serde": "^4.2.6", + "@smithy/middleware-stack": "^4.2.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/smithy-client": "^4.9.8", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.11", + "@smithy/util-defaults-mode-node": "^4.2.14", + "@smithy/util-endpoints": "^3.2.5", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-retry": "^4.2.5", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/region-config-resolver": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.936.0.tgz", + "integrity": "sha512-wOKhzzWsshXGduxO4pqSiNyL9oUtk4BEvjWm9aaq6Hmfdoydq6v6t0rAGHWPjFwy9z2haovGRi3C8IxdMB4muw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.936.0", + "@smithy/config-resolver": "^4.4.3", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/token-providers": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.943.0.tgz", + "integrity": "sha512-cRKyIzwfkS+XztXIFPoWORuaxlIswP+a83BJzelX4S1gUZ7FcXB4+lj9Jxjn8SbQhR4TPU3Owbpu+S7pd6IRbQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.943.0", + "@aws-sdk/nested-clients": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/types": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.936.0.tgz", + "integrity": "sha512-uz0/VlMd2pP5MepdrHizd+T+OKfyK4r3OA9JI+L/lPKg0YFQosdJNCKisr6o70E3dh8iMpFYxF1UN/4uZsyARg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/util-endpoints": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.936.0.tgz", + "integrity": "sha512-0Zx3Ntdpu+z9Wlm7JKUBOzS9EunwKAb4KdGUQQxDqh5Lc3ta5uBoub+FgmVuzwnmBu9U1Os8UuwVTH0Lgu+P5w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.936.0", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-endpoints": "^3.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.936.0.tgz", + "integrity": "sha512-eZ/XF6NxMtu+iCma58GRNRxSq4lHo6zHQLOZRIeL/ghqYJirqHdenMOwrzPettj60KWlv827RVebP9oNVrwZbw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.936.0", + "@smithy/types": "^4.9.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.943.0.tgz", + "integrity": "sha512-gn+ILprVRrgAgTIBk2TDsJLRClzIOdStQFeFTcN0qpL8Z4GBCqMFhw7O7X+MM55Stt5s4jAauQ/VvoqmCADnQg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/middleware-user-agent": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/xml-builder": { + "version": "3.930.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.930.0.tgz", + "integrity": "sha512-YIfkD17GocxdmlUVc3ia52QhcWuRIUJonbF8A2CYfcWNV3HzvAqpcPeC0bYUhkK+8e8YO1ARnLKZQE0TlwzorA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "fast-xml-parser": "5.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-rds/node_modules/@aws/lambda-invoke-store": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.1.tgz", + "integrity": "sha512-sIyFcoPZkTtNu9xFeEoynMef3bPJIAbOfUh+ueYcfhVl6xm2VRtMcMclSxmZCMnHHd4hlYKJeq/aggmBEWynww==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-rds/node_modules/fast-xml-parser": { + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz", + "integrity": "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "strnum": "^2.1.0" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/@aws-sdk/client-rds/node_modules/strnum": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.1.tgz", + "integrity": "sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, "node_modules/@aws-sdk/client-route-53": { "version": "3.782.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-route-53/-/client-route-53-3.782.0.tgz", @@ -2674,89 +3780,394 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/core": { - "version": "3.758.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.758.0.tgz", - "integrity": "sha512-0RswbdR9jt/XKemaLNuxi2gGr4xGlHyGxkTdhSQzCyUe9A9OPCoLl3rIESRguQEech+oJnbHk/wuiwHqTuP9sg==", + "node_modules/@aws-sdk/core": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.758.0.tgz", + "integrity": "sha512-0RswbdR9jt/XKemaLNuxi2gGr4xGlHyGxkTdhSQzCyUe9A9OPCoLl3rIESRguQEech+oJnbHk/wuiwHqTuP9sg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.734.0", + "@smithy/core": "^3.1.5", + "@smithy/node-config-provider": "^4.0.1", + "@smithy/property-provider": "^4.0.1", + "@smithy/protocol-http": "^5.0.1", + "@smithy/signature-v4": "^5.0.1", + "@smithy/smithy-client": "^4.1.6", + "@smithy/types": "^4.1.0", + "@smithy/util-middleware": "^4.0.1", + "fast-xml-parser": "4.4.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.758.0.tgz", + "integrity": "sha512-N27eFoRrO6MeUNumtNHDW9WOiwfd59LPXPqDrIa3kWL/s+fOKFHb9xIcF++bAwtcZnAxKkgpDCUP+INNZskE+w==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/property-provider": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.758.0.tgz", + "integrity": "sha512-Xt9/U8qUCiw1hihztWkNeIR+arg6P+yda10OuCHX6kFVx3auTlU7+hCqs3UxqniGU4dguHuftf3mRpi5/GJ33Q==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/fetch-http-handler": "^5.0.1", + "@smithy/node-http-handler": "^4.0.3", + "@smithy/property-provider": "^4.0.1", + "@smithy/protocol-http": "^5.0.1", + "@smithy/smithy-client": "^4.1.6", + "@smithy/types": "^4.1.0", + "@smithy/util-stream": "^4.1.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.758.0.tgz", + "integrity": "sha512-cymSKMcP5d+OsgetoIZ5QCe1wnp2Q/tq+uIxVdh9MbfdBBEnl9Ecq6dH6VlYS89sp4QKuxHxkWXVnbXU3Q19Aw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.758.0", + "@aws-sdk/credential-provider-env": "3.758.0", + "@aws-sdk/credential-provider-http": "3.758.0", + "@aws-sdk/credential-provider-process": "3.758.0", + "@aws-sdk/credential-provider-sso": "3.758.0", + "@aws-sdk/credential-provider-web-identity": "3.758.0", + "@aws-sdk/nested-clients": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/credential-provider-imds": "^4.0.1", + "@smithy/property-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-login": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.943.0.tgz", + "integrity": "sha512-9iCOVkiRW+evxiJE94RqosCwRrzptAVPhRhGWv4osfYDhjNAvUMyrnZl3T1bjqCoKNcETRKEZIU3dqYHnUkcwQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.943.0", + "@aws-sdk/nested-clients": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-login/node_modules/@aws-sdk/core": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.943.0.tgz", + "integrity": "sha512-8CBy2hI9ABF7RBVQuY1bgf/ue+WPmM/hl0adrXFlhnhkaQP0tFY5zhiy1Y+n7V+5f3/ORoHBmCCQmcHDDYJqJQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.936.0", + "@aws-sdk/xml-builder": "3.930.0", + "@smithy/core": "^3.18.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/signature-v4": "^5.3.5", + "@smithy/smithy-client": "^4.9.8", + "@smithy/types": "^4.9.0", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-login/node_modules/@aws-sdk/middleware-host-header": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.936.0.tgz", + "integrity": "sha512-tAaObaAnsP1XnLGndfkGWFuzrJYuk9W0b/nLvol66t8FZExIAf/WdkT2NNAWOYxljVs++oHnyHBCxIlaHrzSiw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.936.0", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-login/node_modules/@aws-sdk/middleware-logger": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.936.0.tgz", + "integrity": "sha512-aPSJ12d3a3Ea5nyEnLbijCaaYJT2QjQ9iW+zGh5QcZYXmOGWbKVyPSxmVOboZQG+c1M8t6d2O7tqrwzIq8L8qw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.936.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-login/node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.936.0.tgz", + "integrity": "sha512-l4aGbHpXM45YNgXggIux1HgsCVAvvBoqHPkqLnqMl9QVapfuSTjJHfDYDsx1Xxct6/m7qSMUzanBALhiaGO2fA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.936.0", + "@aws/lambda-invoke-store": "^0.2.0", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-login/node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.943.0.tgz", + "integrity": "sha512-956n4kVEwFNXndXfhSAN5wO+KRgqiWEEY+ECwLvxmmO8uQ0NWOa8l6l65nTtyuiWzMX81c9BvlyNR5EgUeeUvA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@aws-sdk/util-endpoints": "3.936.0", + "@smithy/core": "^3.18.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-login/node_modules/@aws-sdk/nested-clients": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.943.0.tgz", + "integrity": "sha512-anFtB0p2FPuyUnbOULwGmKYqYKSq1M73c9uZ08jR/NCq6Trjq9cuF5TFTeHwjJyPRb4wMf2Qk859oiVfFqnQiw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.943.0", + "@aws-sdk/middleware-host-header": "3.936.0", + "@aws-sdk/middleware-logger": "3.936.0", + "@aws-sdk/middleware-recursion-detection": "3.936.0", + "@aws-sdk/middleware-user-agent": "3.943.0", + "@aws-sdk/region-config-resolver": "3.936.0", + "@aws-sdk/types": "3.936.0", + "@aws-sdk/util-endpoints": "3.936.0", + "@aws-sdk/util-user-agent-browser": "3.936.0", + "@aws-sdk/util-user-agent-node": "3.943.0", + "@smithy/config-resolver": "^4.4.3", + "@smithy/core": "^3.18.5", + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/hash-node": "^4.2.5", + "@smithy/invalid-dependency": "^4.2.5", + "@smithy/middleware-content-length": "^4.2.5", + "@smithy/middleware-endpoint": "^4.3.12", + "@smithy/middleware-retry": "^4.4.12", + "@smithy/middleware-serde": "^4.2.6", + "@smithy/middleware-stack": "^4.2.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/smithy-client": "^4.9.8", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.11", + "@smithy/util-defaults-mode-node": "^4.2.14", + "@smithy/util-endpoints": "^3.2.5", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-retry": "^4.2.5", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-login/node_modules/@aws-sdk/region-config-resolver": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.936.0.tgz", + "integrity": "sha512-wOKhzzWsshXGduxO4pqSiNyL9oUtk4BEvjWm9aaq6Hmfdoydq6v6t0rAGHWPjFwy9z2haovGRi3C8IxdMB4muw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.936.0", + "@smithy/config-resolver": "^4.4.3", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-login/node_modules/@aws-sdk/types": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.936.0.tgz", + "integrity": "sha512-uz0/VlMd2pP5MepdrHizd+T+OKfyK4r3OA9JI+L/lPKg0YFQosdJNCKisr6o70E3dh8iMpFYxF1UN/4uZsyARg==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.734.0", - "@smithy/core": "^3.1.5", - "@smithy/node-config-provider": "^4.0.1", - "@smithy/property-provider": "^4.0.1", - "@smithy/protocol-http": "^5.0.1", - "@smithy/signature-v4": "^5.0.1", - "@smithy/smithy-client": "^4.1.6", - "@smithy/types": "^4.1.0", - "@smithy/util-middleware": "^4.0.1", - "fast-xml-parser": "4.4.1", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.758.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.758.0.tgz", - "integrity": "sha512-N27eFoRrO6MeUNumtNHDW9WOiwfd59LPXPqDrIa3kWL/s+fOKFHb9xIcF++bAwtcZnAxKkgpDCUP+INNZskE+w==", + "node_modules/@aws-sdk/credential-provider-login/node_modules/@aws-sdk/util-endpoints": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.936.0.tgz", + "integrity": "sha512-0Zx3Ntdpu+z9Wlm7JKUBOzS9EunwKAb4KdGUQQxDqh5Lc3ta5uBoub+FgmVuzwnmBu9U1Os8UuwVTH0Lgu+P5w==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.758.0", - "@aws-sdk/types": "3.734.0", - "@smithy/property-provider": "^4.0.1", - "@smithy/types": "^4.1.0", + "@aws-sdk/types": "3.936.0", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-endpoints": "^3.2.5", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.758.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.758.0.tgz", - "integrity": "sha512-Xt9/U8qUCiw1hihztWkNeIR+arg6P+yda10OuCHX6kFVx3auTlU7+hCqs3UxqniGU4dguHuftf3mRpi5/GJ33Q==", + "node_modules/@aws-sdk/credential-provider-login/node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.936.0.tgz", + "integrity": "sha512-eZ/XF6NxMtu+iCma58GRNRxSq4lHo6zHQLOZRIeL/ghqYJirqHdenMOwrzPettj60KWlv827RVebP9oNVrwZbw==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.758.0", - "@aws-sdk/types": "3.734.0", - "@smithy/fetch-http-handler": "^5.0.1", - "@smithy/node-http-handler": "^4.0.3", - "@smithy/property-provider": "^4.0.1", - "@smithy/protocol-http": "^5.0.1", - "@smithy/smithy-client": "^4.1.6", - "@smithy/types": "^4.1.0", - "@smithy/util-stream": "^4.1.2", + "@aws-sdk/types": "3.936.0", + "@smithy/types": "^4.9.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/credential-provider-login/node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.943.0.tgz", + "integrity": "sha512-gn+ILprVRrgAgTIBk2TDsJLRClzIOdStQFeFTcN0qpL8Z4GBCqMFhw7O7X+MM55Stt5s4jAauQ/VvoqmCADnQg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/middleware-user-agent": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } } }, - "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.758.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.758.0.tgz", - "integrity": "sha512-cymSKMcP5d+OsgetoIZ5QCe1wnp2Q/tq+uIxVdh9MbfdBBEnl9Ecq6dH6VlYS89sp4QKuxHxkWXVnbXU3Q19Aw==", + "node_modules/@aws-sdk/credential-provider-login/node_modules/@aws-sdk/xml-builder": { + "version": "3.930.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.930.0.tgz", + "integrity": "sha512-YIfkD17GocxdmlUVc3ia52QhcWuRIUJonbF8A2CYfcWNV3HzvAqpcPeC0bYUhkK+8e8YO1ARnLKZQE0TlwzorA==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.758.0", - "@aws-sdk/credential-provider-env": "3.758.0", - "@aws-sdk/credential-provider-http": "3.758.0", - "@aws-sdk/credential-provider-process": "3.758.0", - "@aws-sdk/credential-provider-sso": "3.758.0", - "@aws-sdk/credential-provider-web-identity": "3.758.0", - "@aws-sdk/nested-clients": "3.758.0", - "@aws-sdk/types": "3.734.0", - "@smithy/credential-provider-imds": "^4.0.1", - "@smithy/property-provider": "^4.0.1", - "@smithy/shared-ini-file-loader": "^4.0.1", - "@smithy/types": "^4.1.0", + "@smithy/types": "^4.9.0", + "fast-xml-parser": "5.2.5", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, + "node_modules/@aws-sdk/credential-provider-login/node_modules/@aws/lambda-invoke-store": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.1.tgz", + "integrity": "sha512-sIyFcoPZkTtNu9xFeEoynMef3bPJIAbOfUh+ueYcfhVl6xm2VRtMcMclSxmZCMnHHd4hlYKJeq/aggmBEWynww==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-login/node_modules/fast-xml-parser": { + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz", + "integrity": "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "strnum": "^2.1.0" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/@aws-sdk/credential-provider-login/node_modules/strnum": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.1.tgz", + "integrity": "sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, "node_modules/@aws-sdk/credential-provider-node": { "version": "3.758.0", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.758.0.tgz", @@ -2897,6 +4308,55 @@ "node": ">=18.0.0" } }, + "node_modules/@aws-sdk/middleware-sdk-rds": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-rds/-/middleware-sdk-rds-3.936.0.tgz", + "integrity": "sha512-aU+kqh8gOSC4+bbTQRng1kVT7kjAlgMjiE3KN1XF//uzLaPHnN6lEQXfoXZt1L2ARl63PdUr/z9O82HCvQ2rSg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.936.0", + "@aws-sdk/util-format-url": "3.936.0", + "@smithy/middleware-endpoint": "^4.3.12", + "@smithy/protocol-http": "^5.3.5", + "@smithy/signature-v4": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-rds/node_modules/@aws-sdk/types": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.936.0.tgz", + "integrity": "sha512-uz0/VlMd2pP5MepdrHizd+T+OKfyK4r3OA9JI+L/lPKg0YFQosdJNCKisr6o70E3dh8iMpFYxF1UN/4uZsyARg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-rds/node_modules/@aws-sdk/util-format-url": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.936.0.tgz", + "integrity": "sha512-MS5eSEtDUFIAMHrJaMERiHAvDPdfxc/T869ZjDNFAIiZhyc037REw0aoTNeimNXDNy2txRNZJaAUn/kE4RwN+g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.936.0", + "@smithy/querystring-builder": "^4.2.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@aws-sdk/middleware-sdk-route53": { "version": "3.775.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-route53/-/middleware-sdk-route53-3.775.0.tgz", @@ -5228,12 +6688,12 @@ } }, "node_modules/@smithy/abort-controller": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.0.tgz", - "integrity": "sha512-PLUYa+SUKOEZtXFURBu/CNxlsxfaFGxSBPcStL13KpVeVWIfdezWyDqkz7iDLmwnxojXD0s5KzuB5HGHvt4Aeg==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.5.tgz", + "integrity": "sha512-j7HwVkBw68YW8UmFRcjZOmssE77Rvk0GWAIN1oFBhsaovQmZWYCIcGa9/pwRB0ExI8Sk9MWNALTjftjHZea7VA==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.6.0", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { @@ -5241,15 +6701,16 @@ } }, "node_modules/@smithy/config-resolver": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.3.0.tgz", - "integrity": "sha512-9oH+n8AVNiLPK/iK/agOsoWfrKZ3FGP3502tkksd6SRsKMYiu7AFX0YXo6YBADdsAj7C+G/aLKdsafIJHxuCkQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.3.tgz", + "integrity": "sha512-ezHLe1tKLUxDJo2LHtDuEDyWXolw8WGOR92qb4bQdWq/zKenO5BvctZGrVJBK08zjezSk7bmbKFOXIVyChvDLw==", "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.3.0", - "@smithy/types": "^4.6.0", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/types": "^4.9.0", "@smithy/util-config-provider": "^4.2.0", - "@smithy/util-middleware": "^4.2.0", + "@smithy/util-endpoints": "^3.2.5", + "@smithy/util-middleware": "^4.2.5", "tslib": "^2.6.2" }, "engines": { @@ -5257,18 +6718,18 @@ } }, "node_modules/@smithy/core": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.14.0.tgz", - "integrity": "sha512-XJ4z5FxvY/t0Dibms/+gLJrI5niRoY0BCmE02fwmPcRYFPI4KI876xaE79YGWIKnEslMbuQPsIEsoU/DXa0DoA==", + "version": "3.18.6", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.18.6.tgz", + "integrity": "sha512-8Q/ugWqfDUEU1Exw71+DoOzlONJ2Cn9QA8VeeDzLLjzO/qruh9UKFzbszy4jXcIYgGofxYiT0t1TT6+CT/GupQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/middleware-serde": "^4.2.0", - "@smithy/protocol-http": "^5.3.0", - "@smithy/types": "^4.6.0", - "@smithy/util-base64": "^4.2.0", + "@smithy/middleware-serde": "^4.2.6", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", - "@smithy/util-middleware": "^4.2.0", - "@smithy/util-stream": "^4.4.0", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-stream": "^4.5.6", "@smithy/util-utf8": "^4.2.0", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" @@ -5278,15 +6739,15 @@ } }, "node_modules/@smithy/credential-provider-imds": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.0.tgz", - "integrity": "sha512-SOhFVvFH4D5HJZytb0bLKxCrSnwcqPiNlrw+S4ZXjMnsC+o9JcUQzbZOEQcA8yv9wJFNhfsUiIUKiEnYL68Big==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.5.tgz", + "integrity": "sha512-BZwotjoZWn9+36nimwm/OLIcVe+KYRwzMjfhd4QT7QxPm9WY0HiOV8t/Wlh+HVUif0SBVV7ksq8//hPaBC/okQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.3.0", - "@smithy/property-provider": "^4.2.0", - "@smithy/types": "^4.6.0", - "@smithy/url-parser": "^4.2.0", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", "tslib": "^2.6.2" }, "engines": { @@ -5369,15 +6830,15 @@ } }, "node_modules/@smithy/fetch-http-handler": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.0.tgz", - "integrity": "sha512-BG3KSmsx9A//KyIfw+sqNmWFr1YBUr+TwpxFT7yPqAk0yyDh7oSNgzfNH7pS6OC099EGx2ltOULvumCFe8bcgw==", + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.6.tgz", + "integrity": "sha512-3+RG3EA6BBJ/ofZUeTFJA7mHfSYrZtQIrDP9dI8Lf7X6Jbos2jptuLrAAteDiFVrmbEmLSuRG/bUKzfAXk7dhg==", "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^5.3.0", - "@smithy/querystring-builder": "^4.2.0", - "@smithy/types": "^4.6.0", - "@smithy/util-base64": "^4.2.0", + "@smithy/protocol-http": "^5.3.5", + "@smithy/querystring-builder": "^4.2.5", + "@smithy/types": "^4.9.0", + "@smithy/util-base64": "^4.3.0", "tslib": "^2.6.2" }, "engines": { @@ -5385,12 +6846,12 @@ } }, "node_modules/@smithy/hash-node": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.0.tgz", - "integrity": "sha512-ugv93gOhZGysTctZh9qdgng8B+xO0cj+zN0qAZ+Sgh7qTQGPOJbMdIuyP89KNfUyfAqFSNh5tMvC+h2uCpmTtA==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.5.tgz", + "integrity": "sha512-DpYX914YOfA3UDT9CN1BM787PcHfWRBB43fFGCYrZFUH0Jv+5t8yYl+Pd5PW4+QzoGEDvn5d5QIO4j2HyYZQSA==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.6.0", + "@smithy/types": "^4.9.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" @@ -5400,12 +6861,12 @@ } }, "node_modules/@smithy/invalid-dependency": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.0.tgz", - "integrity": "sha512-ZmK5X5fUPAbtvRcUPtk28aqIClVhbfcmfoS4M7UQBTnDdrNxhsrxYVv0ZEl5NaPSyExsPWqL4GsPlRvtlwg+2A==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.5.tgz", + "integrity": "sha512-2L2erASEro1WC5nV+plwIMxrTXpvpfzl4e+Nre6vBVRR2HKeGGcvpJyyL3/PpiSg+cJG2KpTmZmq934Olb6e5A==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.6.0", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { @@ -5425,13 +6886,13 @@ } }, "node_modules/@smithy/middleware-content-length": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.0.tgz", - "integrity": "sha512-6ZAnwrXFecrA4kIDOcz6aLBhU5ih2is2NdcZtobBDSdSHtE9a+MThB5uqyK4XXesdOCvOcbCm2IGB95birTSOQ==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.5.tgz", + "integrity": "sha512-Y/RabVa5vbl5FuHYV2vUCwvh/dqzrEY/K2yWPSqvhFUwIY0atLqO4TienjBXakoy4zrKAMCZwg+YEqmH7jaN7A==", "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^5.3.0", - "@smithy/types": "^4.6.0", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { @@ -5439,18 +6900,18 @@ } }, "node_modules/@smithy/middleware-endpoint": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.3.0.tgz", - "integrity": "sha512-jFVjuQeV8TkxaRlcCNg0GFVgg98tscsmIrIwRFeC74TIUyLE3jmY9xgc1WXrPQYRjQNK3aRoaIk6fhFRGOIoGw==", + "version": "4.3.13", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.3.13.tgz", + "integrity": "sha512-X4za1qCdyx1hEVVXuAWlZuK6wzLDv1uw1OY9VtaYy1lULl661+frY7FeuHdYdl7qAARUxH2yvNExU2/SmRFfcg==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.14.0", - "@smithy/middleware-serde": "^4.2.0", - "@smithy/node-config-provider": "^4.3.0", - "@smithy/shared-ini-file-loader": "^4.3.0", - "@smithy/types": "^4.6.0", - "@smithy/url-parser": "^4.2.0", - "@smithy/util-middleware": "^4.2.0", + "@smithy/core": "^3.18.6", + "@smithy/middleware-serde": "^4.2.6", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-middleware": "^4.2.5", "tslib": "^2.6.2" }, "engines": { @@ -5458,18 +6919,18 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.0.tgz", - "integrity": "sha512-yaVBR0vQnOnzex45zZ8ZrPzUnX73eUC8kVFaAAbn04+6V7lPtxn56vZEBBAhgS/eqD6Zm86o6sJs6FuQVoX5qg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.3.0", - "@smithy/protocol-http": "^5.3.0", - "@smithy/service-error-classification": "^4.2.0", - "@smithy/smithy-client": "^4.7.0", - "@smithy/types": "^4.6.0", - "@smithy/util-middleware": "^4.2.0", - "@smithy/util-retry": "^4.2.0", + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.13.tgz", + "integrity": "sha512-RzIDF9OrSviXX7MQeKOm8r/372KTyY8Jmp6HNKOOYlrguHADuM3ED/f4aCyNhZZFLG55lv5beBin7nL0Nzy1Dw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/service-error-classification": "^4.2.5", + "@smithy/smithy-client": "^4.9.9", + "@smithy/types": "^4.9.0", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-retry": "^4.2.5", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" }, @@ -5478,13 +6939,13 @@ } }, "node_modules/@smithy/middleware-serde": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.0.tgz", - "integrity": "sha512-rpTQ7D65/EAbC6VydXlxjvbifTf4IH+sADKg6JmAvhkflJO2NvDeyU9qsWUNBelJiQFcXKejUHWRSdmpJmEmiw==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.6.tgz", + "integrity": "sha512-VkLoE/z7e2g8pirwisLz8XJWedUSY8my/qrp81VmAdyrhi94T+riBfwP+AOEEFR9rFTSonC/5D2eWNmFabHyGQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^5.3.0", - "@smithy/types": "^4.6.0", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { @@ -5492,12 +6953,12 @@ } }, "node_modules/@smithy/middleware-stack": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.0.tgz", - "integrity": "sha512-G5CJ//eqRd9OARrQu9MK1H8fNm2sMtqFh6j8/rPozhEL+Dokpvi1Og+aCixTuwDAGZUkJPk6hJT5jchbk/WCyg==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.5.tgz", + "integrity": "sha512-bYrutc+neOyWxtZdbB2USbQttZN0mXaOyYLIsaTbJhFsfpXyGWUxJpEuO1rJ8IIJm2qH4+xJT0mxUSsEDTYwdQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.6.0", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { @@ -5505,14 +6966,14 @@ } }, "node_modules/@smithy/node-config-provider": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.0.tgz", - "integrity": "sha512-5QgHNuWdT9j9GwMPPJCKxy2KDxZ3E5l4M3/5TatSZrqYVoEiqQrDfAq8I6KWZw7RZOHtVtCzEPdYz7rHZixwcA==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.5.tgz", + "integrity": "sha512-UTurh1C4qkVCtqggI36DGbLB2Kv8UlcFdMXDcWMbqVY2uRg0XmT9Pb4Vj6oSQ34eizO1fvR0RnFV4Axw4IrrAg==", "license": "Apache-2.0", "dependencies": { - "@smithy/property-provider": "^4.2.0", - "@smithy/shared-ini-file-loader": "^4.3.0", - "@smithy/types": "^4.6.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { @@ -5520,15 +6981,15 @@ } }, "node_modules/@smithy/node-http-handler": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.3.0.tgz", - "integrity": "sha512-RHZ/uWCmSNZ8cneoWEVsVwMZBKy/8123hEpm57vgGXA3Irf/Ja4v9TVshHK2ML5/IqzAZn0WhINHOP9xl+Qy6Q==", + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.4.5.tgz", + "integrity": "sha512-CMnzM9R2WqlqXQGtIlsHMEZfXKJVTIrqCNoSd/QpAyp+Dw0a1Vps13l6ma1fH8g7zSPNsA59B/kWgeylFuA/lw==", "license": "Apache-2.0", "dependencies": { - "@smithy/abort-controller": "^4.2.0", - "@smithy/protocol-http": "^5.3.0", - "@smithy/querystring-builder": "^4.2.0", - "@smithy/types": "^4.6.0", + "@smithy/abort-controller": "^4.2.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/querystring-builder": "^4.2.5", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { @@ -5536,12 +6997,12 @@ } }, "node_modules/@smithy/property-provider": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.0.tgz", - "integrity": "sha512-rV6wFre0BU6n/tx2Ztn5LdvEdNZ2FasQbPQmDOPfV9QQyDmsCkOAB0osQjotRCQg+nSKFmINhyda0D3AnjSBJw==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.5.tgz", + "integrity": "sha512-8iLN1XSE1rl4MuxvQ+5OSk/Zb5El7NJZ1td6Tn+8dQQHIjp59Lwl6bd0+nzw6SKm2wSSriH2v/I9LPzUic7EOg==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.6.0", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { @@ -5549,12 +7010,12 @@ } }, "node_modules/@smithy/protocol-http": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.0.tgz", - "integrity": "sha512-6POSYlmDnsLKb7r1D3SVm7RaYW6H1vcNcTWGWrF7s9+2noNYvUsm7E4tz5ZQ9HXPmKn6Hb67pBDRIjrT4w/d7Q==", + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.5.tgz", + "integrity": "sha512-RlaL+sA0LNMp03bf7XPbFmT5gN+w3besXSWMkA8rcmxLSVfiEXElQi4O2IWwPfxzcHkxqrwBFMbngB8yx/RvaQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.6.0", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { @@ -5562,12 +7023,12 @@ } }, "node_modules/@smithy/querystring-builder": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.0.tgz", - "integrity": "sha512-Q4oFD0ZmI8yJkiPPeGUITZj++4HHYCW3pYBYfIobUCkYpI6mbkzmG1MAQQ3lJYYWj3iNqfzOenUZu+jqdPQ16A==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.5.tgz", + "integrity": "sha512-y98otMI1saoajeik2kLfGyRp11e5U/iJYH/wLCh3aTV/XutbGT9nziKGkgCaMD1ghK7p6htHMm6b6scl9JRUWg==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.6.0", + "@smithy/types": "^4.9.0", "@smithy/util-uri-escape": "^4.2.0", "tslib": "^2.6.2" }, @@ -5576,12 +7037,12 @@ } }, "node_modules/@smithy/querystring-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.0.tgz", - "integrity": "sha512-BjATSNNyvVbQxOOlKse0b0pSezTWGMvA87SvoFoFlkRsKXVsN3bEtjCxvsNXJXfnAzlWFPaT9DmhWy1vn0sNEA==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.5.tgz", + "integrity": "sha512-031WCTdPYgiQRYNPXznHXof2YM0GwL6SeaSyTH/P72M1Vz73TvCNH2Nq8Iu2IEPq9QP2yx0/nrw5YmSeAi/AjQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.6.0", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { @@ -5589,24 +7050,24 @@ } }, "node_modules/@smithy/service-error-classification": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.0.tgz", - "integrity": "sha512-Ylv1ttUeKatpR0wEOMnHf1hXMktPUMObDClSWl2TpCVT4DwtJhCeighLzSLbgH3jr5pBNM0LDXT5yYxUvZ9WpA==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.5.tgz", + "integrity": "sha512-8fEvK+WPE3wUAcDvqDQG1Vk3ANLR8Px979te96m84CbKAjBVf25rPYSzb4xU4hlTyho7VhOGnh5i62D/JVF0JQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.6.0" + "@smithy/types": "^4.9.0" }, "engines": { "node": ">=18.0.0" } }, "node_modules/@smithy/shared-ini-file-loader": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.3.0.tgz", - "integrity": "sha512-VCUPPtNs+rKWlqqntX0CbVvWyjhmX30JCtzO+s5dlzzxrvSfRh5SY0yxnkirvc1c80vdKQttahL71a9EsdolSQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.0.tgz", + "integrity": "sha512-5WmZ5+kJgJDjwXXIzr1vDTG+RhF9wzSODQBfkrQ2VVkYALKGvZX1lgVSxEkgicSAFnFhPj5rudJV0zoinqS0bA==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.6.0", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { @@ -5614,16 +7075,16 @@ } }, "node_modules/@smithy/signature-v4": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.0.tgz", - "integrity": "sha512-MKNyhXEs99xAZaFhm88h+3/V+tCRDQ+PrDzRqL0xdDpq4gjxcMmf5rBA3YXgqZqMZ/XwemZEurCBQMfxZOWq/g==", + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.5.tgz", + "integrity": "sha512-xSUfMu1FT7ccfSXkoLl/QRQBi2rOvi3tiBZU2Tdy3I6cgvZ6SEi9QNey+lqps/sJRnogIS+lq+B1gxxbra2a/w==", "license": "Apache-2.0", "dependencies": { "@smithy/is-array-buffer": "^4.2.0", - "@smithy/protocol-http": "^5.3.0", - "@smithy/types": "^4.6.0", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", "@smithy/util-hex-encoding": "^4.2.0", - "@smithy/util-middleware": "^4.2.0", + "@smithy/util-middleware": "^4.2.5", "@smithy/util-uri-escape": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" @@ -5633,17 +7094,17 @@ } }, "node_modules/@smithy/smithy-client": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.7.0.tgz", - "integrity": "sha512-3BDx/aCCPf+kkinYf5QQhdQ9UAGihgOVqI3QO5xQfSaIWvUE4KYLtiGRWsNe1SR7ijXC0QEPqofVp5Sb0zC8xQ==", + "version": "4.9.9", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.9.9.tgz", + "integrity": "sha512-SUnZJMMo5yCmgjopJbiNeo1vlr8KvdnEfIHV9rlD77QuOGdRotIVBcOrBuMr+sI9zrnhtDtLP054bZVbpZpiQA==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.14.0", - "@smithy/middleware-endpoint": "^4.3.0", - "@smithy/middleware-stack": "^4.2.0", - "@smithy/protocol-http": "^5.3.0", - "@smithy/types": "^4.6.0", - "@smithy/util-stream": "^4.4.0", + "@smithy/core": "^3.18.6", + "@smithy/middleware-endpoint": "^4.3.13", + "@smithy/middleware-stack": "^4.2.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "@smithy/util-stream": "^4.5.6", "tslib": "^2.6.2" }, "engines": { @@ -5651,9 +7112,9 @@ } }, "node_modules/@smithy/types": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.6.0.tgz", - "integrity": "sha512-4lI9C8NzRPOv66FaY1LL1O/0v0aLVrq/mXP/keUa9mJOApEeae43LsLd2kZRUJw91gxOQfLIrV3OvqPgWz1YsA==", + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.9.0.tgz", + "integrity": "sha512-MvUbdnXDTwykR8cB1WZvNNwqoWVaTRA0RLlLmf/cIFNMM2cKWz01X4Ly6SMC4Kks30r8tT3Cty0jmeWfiuyHTA==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" @@ -5663,13 +7124,13 @@ } }, "node_modules/@smithy/url-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.0.tgz", - "integrity": "sha512-AlBmD6Idav2ugmoAL6UtR6ItS7jU5h5RNqLMZC7QrLCoITA9NzIN3nx9GWi8g4z1pfWh2r9r96SX/jHiNwPJ9A==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.5.tgz", + "integrity": "sha512-VaxMGsilqFnK1CeBX+LXnSuaMx4sTL/6znSZh2829txWieazdVxr54HmiyTsIbpOTLcf5nYpq9lpzmwRdxj6rQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/querystring-parser": "^4.2.0", - "@smithy/types": "^4.6.0", + "@smithy/querystring-parser": "^4.2.5", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { @@ -5677,9 +7138,9 @@ } }, "node_modules/@smithy/util-base64": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.2.0.tgz", - "integrity": "sha512-+erInz8WDv5KPe7xCsJCp+1WCjSbah9gWcmUXc9NqmhyPx59tf7jqFz+za1tRG1Y5KM1Cy1rWCcGypylFp4mvA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.3.0.tgz", + "integrity": "sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ==", "license": "Apache-2.0", "dependencies": { "@smithy/util-buffer-from": "^4.2.0", @@ -5703,9 +7164,9 @@ } }, "node_modules/@smithy/util-body-length-node": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.2.0.tgz", - "integrity": "sha512-U8q1WsSZFjXijlD7a4wsDQOvOwV+72iHSfq1q7VD+V75xP/pdtm0WIGuaFJ3gcADDOKj2MIBn4+zisi140HEnQ==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.2.1.tgz", + "integrity": "sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" @@ -5740,15 +7201,14 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.2.0.tgz", - "integrity": "sha512-qzHp7ZDk1Ba4LDwQVCNp90xPGqSu7kmL7y5toBpccuhi3AH7dcVBIT/pUxYcInK4jOy6FikrcTGq5wxcka8UaQ==", + "version": "4.3.12", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.12.tgz", + "integrity": "sha512-TKc6FnOxFULKxLgTNHYjcFqdOYzXVPFFVm5JhI30F3RdhT7nYOtOsjgaOwfDRmA/3U66O9KaBQ3UHoXwayRhAg==", "license": "Apache-2.0", "dependencies": { - "@smithy/property-provider": "^4.2.0", - "@smithy/smithy-client": "^4.7.0", - "@smithy/types": "^4.6.0", - "bowser": "^2.11.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/smithy-client": "^4.9.9", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { @@ -5756,17 +7216,17 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.0.tgz", - "integrity": "sha512-FxUHS3WXgx3bTWR6yQHNHHkQHZm/XKIi/CchTnKvBulN6obWpcbzJ6lDToXn+Wp0QlVKd7uYAz2/CTw1j7m+Kg==", + "version": "4.2.15", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.15.tgz", + "integrity": "sha512-94NqfQVo+vGc5gsQ9SROZqOvBkGNMQu6pjXbnn8aQvBUhc31kx49gxlkBEqgmaZQHUUfdRUin5gK/HlHKmbAwg==", "license": "Apache-2.0", "dependencies": { - "@smithy/config-resolver": "^4.3.0", - "@smithy/credential-provider-imds": "^4.2.0", - "@smithy/node-config-provider": "^4.3.0", - "@smithy/property-provider": "^4.2.0", - "@smithy/smithy-client": "^4.7.0", - "@smithy/types": "^4.6.0", + "@smithy/config-resolver": "^4.4.3", + "@smithy/credential-provider-imds": "^4.2.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/smithy-client": "^4.9.9", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { @@ -5774,13 +7234,13 @@ } }, "node_modules/@smithy/util-endpoints": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.2.0.tgz", - "integrity": "sha512-TXeCn22D56vvWr/5xPqALc9oO+LN+QpFjrSM7peG/ckqEPoI3zaKZFp+bFwfmiHhn5MGWPaLCqDOJPPIixk9Wg==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.2.5.tgz", + "integrity": "sha512-3O63AAWu2cSNQZp+ayl9I3NapW1p1rR5mlVHcF6hAB1dPZUQFfRPYtplWX/3xrzWthPGj5FqB12taJJCfH6s8A==", "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.3.0", - "@smithy/types": "^4.6.0", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { @@ -5800,12 +7260,12 @@ } }, "node_modules/@smithy/util-middleware": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.0.tgz", - "integrity": "sha512-u9OOfDa43MjagtJZ8AapJcmimP+K2Z7szXn8xbty4aza+7P1wjFmy2ewjSbhEiYQoW1unTlOAIV165weYAaowA==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.5.tgz", + "integrity": "sha512-6Y3+rvBF7+PZOc40ybeZMcGln6xJGVeY60E7jy9Mv5iKpMJpHgRE6dKy9ScsVxvfAYuEX4Q9a65DQX90KaQ3bA==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.6.0", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { @@ -5813,13 +7273,13 @@ } }, "node_modules/@smithy/util-retry": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.2.0.tgz", - "integrity": "sha512-BWSiuGbwRnEE2SFfaAZEX0TqaxtvtSYPM/J73PFVm+A29Fg1HTPiYFb8TmX1DXp4hgcdyJcNQmprfd5foeORsg==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.2.5.tgz", + "integrity": "sha512-GBj3+EZBbN4NAqJ/7pAhsXdfzdlznOh8PydUijy6FpNIMnHPSMO2/rP4HKu+UFeikJxShERk528oy7GT79YiJg==", "license": "Apache-2.0", "dependencies": { - "@smithy/service-error-classification": "^4.2.0", - "@smithy/types": "^4.6.0", + "@smithy/service-error-classification": "^4.2.5", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { @@ -5827,15 +7287,15 @@ } }, "node_modules/@smithy/util-stream": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.4.0.tgz", - "integrity": "sha512-vtO7ktbixEcrVzMRmpQDnw/Ehr9UWjBvSJ9fyAbadKkC4w5Cm/4lMO8cHz8Ysb8uflvQUNRcuux/oNHKPXkffg==", + "version": "4.5.6", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.6.tgz", + "integrity": "sha512-qWw/UM59TiaFrPevefOZ8CNBKbYEP6wBAIlLqxn3VAIo9rgnTNc4ASbVrqDmhuwI87usnjhdQrxodzAGFFzbRQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/fetch-http-handler": "^5.3.0", - "@smithy/node-http-handler": "^4.3.0", - "@smithy/types": "^4.6.0", - "@smithy/util-base64": "^4.2.0", + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/types": "^4.9.0", + "@smithy/util-base64": "^4.3.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-utf8": "^4.2.0", @@ -5871,13 +7331,13 @@ } }, "node_modules/@smithy/util-waiter": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.2.0.tgz", - "integrity": "sha512-0Z+nxUU4/4T+SL8BCNN4ztKdQjToNvUYmkF1kXO5T7Yz3Gafzh0HeIG6mrkN8Fz3gn9hSyxuAT+6h4vM+iQSBQ==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.2.5.tgz", + "integrity": "sha512-Dbun99A3InifQdIrsXZ+QLcC0PGBPAdrl4cj1mTgJvyc9N2zf7QSxg8TBkzsCmGJdE3TLbO9ycwpY0EkWahQ/g==", "license": "Apache-2.0", "dependencies": { - "@smithy/abort-controller": "^4.2.0", - "@smithy/types": "^4.6.0", + "@smithy/abort-controller": "^4.2.5", + "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "engines": { diff --git a/package.json b/package.json index 1bc0e81..792c5d3 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,8 @@ "@aws-sdk/client-efs": "^3.758.0", "@aws-sdk/client-elastic-load-balancing-v2": "^3.764.0", "@aws-sdk/client-elasticache": "^3.901.0", + "@aws-sdk/client-kms": "^3.943.0", + "@aws-sdk/client-rds": "^3.943.0", "@aws-sdk/client-route-53": "^3.782.0", "@aws-sdk/client-secrets-manager": "^3.906.0", "@aws-sdk/client-servicediscovery": "^3.758.0", diff --git a/tests/database/default-db.test.ts b/tests/database/default-db.test.ts new file mode 100644 index 0000000..c15e86f --- /dev/null +++ b/tests/database/default-db.test.ts @@ -0,0 +1,203 @@ +import { + DescribeKeyCommand, + GetKeyRotationStatusCommand, +} from '@aws-sdk/client-kms'; +import { + DescribeSecurityGroupsCommand, + IpPermission, +} from '@aws-sdk/client-ec2'; +import * as assert from 'node:assert'; +import { DatabaseTestContext } from './test-context'; +import { DescribeDBSubnetGroupsCommand } from '@aws-sdk/client-rds'; +import { it } from 'node:test'; + +export function testDefaultDb(ctx: DatabaseTestContext) { + it('should create a database and all other resources', () => { + const database = ctx.outputs.defaultDb.value; + + assert.ok(database, 'Database should be defined'); + assert.strictEqual( + database.name, + `${ctx.config.appName}-default`, + 'Database should have correct name', + ); + + assert.ok(database.instance, 'Db instance should be defined'); + assert.ok(database.dbSecurityGroup, 'Db security group should be defined'); + assert.ok(database.dbSubnetGroup, 'Db subnet group should be defined'); + assert.ok(database.kmsKeyId, 'Kms key id should be defined'); + assert.ok(database.password, 'Password should be defined'); + }); + + it('should create database instance with correct default configuration', () => { + const instance = ctx.outputs.defaultDb.value.instance; + + assert.strictEqual( + instance.dbName, + ctx.config.dbName, + 'Database instance should have correct dbName', + ); + assert.strictEqual( + instance.masterUsername, + ctx.config.dbUsername, + 'Database instance should have correct master username', + ); + assert.strictEqual( + instance.masterUserPassword, + ctx.config.dbPassword, + 'Database instance should have correct master user password', + ); + + assert.strictEqual( + instance.multiAz, + false, + 'Multi-AZ argument should be set to false', + ); + assert.strictEqual( + instance.applyImmediately, + false, + 'Apply immediately argument should be set to false', + ); + assert.strictEqual( + instance.allocatedStorage, + '20', + 'Allocated storage argument should be set to 20', + ); + assert.strictEqual( + instance.maxAllocatedStorage, + 100, + 'Max allocated storage argument should be set to 100', + ); + assert.strictEqual( + instance.dbInstanceClass, + 'db.t4g.micro', + 'DB instance class argument should be set to db.t4g.micro', + ); + assert.strictEqual( + instance.enablePerformanceInsights, + false, + 'Enable performance insights argument should be set to false', + ); + assert.strictEqual( + instance.allowMajorVersionUpgrade, + false, + 'Allow major version upgrade argument should be set to false', + ); + assert.strictEqual( + instance.autoMinorVersionUpgrade, + true, + 'Auto minor version upgrade argument should be set to true', + ); + assert.strictEqual( + instance.engineVersion, + '17.2', + 'Engine version argument should be set to 17.2', + ); + assert.strictEqual( + instance.engine, + 'postgres', + 'Engine argument should be set to postgres', + ); + assert.strictEqual( + instance.storageEncrypted, + true, + 'Storage encrypted argument should be set to true', + ); + assert.strictEqual( + instance.publiclyAccessible, + false, + 'Publicly accessible argument should be set to false', + ); + }); + + it('should create subnet group in the correct VPC', async () => { + const database = ctx.outputs.defaultDb.value; + const vpc = ctx.outputs.vpc.value; + const dbSubnetGroupName = database.dbSubnetGroup.name; + + const command = new DescribeDBSubnetGroupsCommand({ + DBSubnetGroupName: dbSubnetGroupName, + }); + + const { DBSubnetGroups } = await ctx.clients.rds.send(command); + assert.ok( + DBSubnetGroups && DBSubnetGroups.length > 0, + 'DB subnet groups should exist', + ); + const [subnetGroup] = DBSubnetGroups; + assert.strictEqual( + subnetGroup.VpcId, + vpc.vpc.vpcId, + 'DB subnet group should be in the correct VPC', + ); + assert.ok( + subnetGroup.Subnets && subnetGroup.Subnets.length > 0, + 'DB subnet group should have subnets', + ); + }); + + it('should create a security group with correct ingress rules', async () => { + const database = ctx.outputs.defaultDb.value; + const vpc = ctx.outputs.vpc.value; + const dbSecurityGroupId = database.dbSecurityGroup.id; + + const command = new DescribeSecurityGroupsCommand({ + GroupIds: [dbSecurityGroupId], + }); + const { SecurityGroups } = await ctx.clients.ec2.send(command); + assert.ok( + SecurityGroups && SecurityGroups.length > 0, + 'DB security groups should exist', + ); + const [securityGroup] = SecurityGroups; + assert.strictEqual( + securityGroup.VpcId, + vpc.vpc.vpcId, + 'DB security group should be in the correct VPC', + ); + + const postgresRule = securityGroup.IpPermissions?.find( + (rule: IpPermission) => rule.FromPort === 5432 && rule.ToPort === 5432, + ); + assert.ok(postgresRule, 'Should have postgres port 5432 ingress rule'); + assert.strictEqual( + postgresRule.IpProtocol, + 'tcp', + 'Should allow TCP protocol', + ); + }); + + it('should create a correctly configured RDS KMS key', async () => { + const database = ctx.outputs.defaultDb.value; + const kmsKeyId = database.kmsKeyId; + + const describeCommand = new DescribeKeyCommand({ + KeyId: kmsKeyId, + }); + const { KeyMetadata } = await ctx.clients.kms.send(describeCommand); + assert.strictEqual( + KeyMetadata?.KeySpec, + 'SYMMETRIC_DEFAULT', + 'KMS key should use SYMMETRIC_DEFAULT spec', + ); + assert.strictEqual( + KeyMetadata.KeyUsage, + 'ENCRYPT_DECRYPT', + 'KMS key should be used for encryption/decryption', + ); + assert.strictEqual(KeyMetadata.Enabled, true, 'KMS key should be enabled'); + assert.strictEqual( + KeyMetadata.MultiRegion, + false, + 'KMS key should not be multi-region', + ); + + const rotationCmd = new GetKeyRotationStatusCommand({ KeyId: kmsKeyId }); + const { KeyRotationEnabled } = await ctx.clients.kms.send(rotationCmd); + assert.strictEqual( + KeyRotationEnabled, + true, + 'KMS key rotation should be enabled', + ); + }); +} diff --git a/tests/database/index.test.ts b/tests/database/index.test.ts new file mode 100644 index 0000000..83b6ec5 --- /dev/null +++ b/tests/database/index.test.ts @@ -0,0 +1,40 @@ +import { describe, before, after } from 'node:test'; +import * as automation from '../automation'; +import * as config from './infrastructure/config'; +import { DatabaseTestContext } from './test-context'; +import { EC2Client } from '@aws-sdk/client-ec2'; +import { InlineProgramArgs } from '@pulumi/pulumi/automation'; +import { KMSClient } from '@aws-sdk/client-kms'; +import { RDSClient } from '@aws-sdk/client-rds'; +import { testDefaultDb } from './default-db.test'; + +const programArgs: InlineProgramArgs = { + stackName: 'dev', + projectName: 'icb-test-database', + program: () => import('./infrastructure'), +}; + +describe('Database component deployment', () => { + const region = process.env.AWS_REGION; + if (!region) { + throw new Error('AWS_REGION environment variable is required'); + } + + const ctx: DatabaseTestContext = { + outputs: {}, + config, + clients: { + rds: new RDSClient({ region }), + ec2: new EC2Client({ region }), + kms: new KMSClient({ region }), + }, + }; + + before(async () => { + ctx.outputs = await automation.deploy(programArgs); + }); + + after(() => automation.destroy(programArgs)); + + describe('Default database', () => testDefaultDb(ctx)); +}); diff --git a/tests/database/infrastructure/config.ts b/tests/database/infrastructure/config.ts new file mode 100644 index 0000000..ef9372f --- /dev/null +++ b/tests/database/infrastructure/config.ts @@ -0,0 +1,11 @@ +import * as pulumi from '@pulumi/pulumi'; + +export const appName = 'db-test'; +export const stackName = pulumi.getStack(); +export const tags = { + Project: appName, + Environment: stackName, +}; +export const dbName = 'dbname'; +export const dbUsername = 'dbusername'; +export const dbPassword = 'dbpassword'; diff --git a/tests/database/infrastructure/index.ts b/tests/database/infrastructure/index.ts new file mode 100644 index 0000000..b642e65 --- /dev/null +++ b/tests/database/infrastructure/index.ts @@ -0,0 +1,16 @@ +import { next as studion } from '@studion/infra-code-blocks'; +import * as config from './config'; + +const vpc = new studion.Vpc(`${config.appName}-vpc`, {}); + +const defaultDb = new studion.DatabaseBuilder(`${config.appName}-default`) + .withConfiguration({ + dbName: config.dbName, + username: config.dbUsername, + password: config.dbPassword, + tags: config.tags, + }) + .withVpc(vpc.vpc) + .build(); + +export { vpc, defaultDb }; diff --git a/tests/database/test-context.ts b/tests/database/test-context.ts new file mode 100644 index 0000000..366d4f6 --- /dev/null +++ b/tests/database/test-context.ts @@ -0,0 +1,37 @@ +import { EC2Client } from '@aws-sdk/client-ec2'; +import { KMSClient } from '@aws-sdk/client-kms'; +import { OutputMap } from '@pulumi/pulumi/automation'; +import { RDSClient } from '@aws-sdk/client-rds'; + +interface ConfigContext { + config: DatabaseTestConfig; +} + +interface DatabaseTestConfig { + appName: string; + stackName: string; + tags: { + Project: string; + Environment: string; + }; + dbName: string; + dbUsername: string; + dbPassword: string; +} + +interface PulumiProgramContext { + outputs: OutputMap; +} + +interface AwsContext { + clients: { + rds: RDSClient; + ec2: EC2Client; + kms: KMSClient; + }; +} + +export interface DatabaseTestContext + extends ConfigContext, + PulumiProgramContext, + AwsContext {} From bb298bc9169a7215c5b0f110750b5e5eef6ffc61 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Wed, 10 Dec 2025 10:22:54 +0100 Subject: [PATCH 21/71] Cleanup database types --- src/v2/components/database/index.ts | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/v2/components/database/index.ts b/src/v2/components/database/index.ts index ff48e7a..76c7af0 100644 --- a/src/v2/components/database/index.ts +++ b/src/v2/components/database/index.ts @@ -9,16 +9,12 @@ export namespace Database { export type Instance = { dbName?: pulumi.Input; engineVersion?: pulumi.Input; + multiAz?: pulumi.Input; instanceClass?: pulumi.Input; allowMajorVersionUpgrade?: pulumi.Input; autoMinorVersionUpgrade?: pulumi.Input; }; - export type Networking = { - vpc: pulumi.Input; - multiAz?: pulumi.Input; - }; - export type Credentials = { username?: pulumi.Input; password?: pulumi.Input; @@ -28,24 +24,16 @@ export namespace Database { allocatedStorage?: pulumi.Input; maxAllocatedStorage?: pulumi.Input; kmsKeyId?: pulumi.Input; - snapshotIdentifier?: pulumi.Input; - }; - - export type Monitoring = { - enableMonitoring?: pulumi.Input; - applyImmediately?: pulumi.Input; - }; - - export type ParameterGroup = { - parameterGroupName?: pulumi.Input; }; export type Args = Instance & - Networking & Credentials & - Storage & - Monitoring & - ParameterGroup & { + Storage & { + vpc: pulumi.Input; + enableMonitoring?: pulumi.Input; + applyImmediately?: pulumi.Input; + snapshotIdentifier?: pulumi.Input; + parameterGroupName?: pulumi.Input; tags?: pulumi.Input<{ [key: string]: pulumi.Input; }>; From 6af2d1b7ac72fe69a97ce91855048f4fc74c3514 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Wed, 10 Dec 2025 14:58:51 +0100 Subject: [PATCH 22/71] Cleanup --- src/v2/components/database/builder.ts | 70 ++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 13 deletions(-) diff --git a/src/v2/components/database/builder.ts b/src/v2/components/database/builder.ts index 2ed2af2..f5003fe 100644 --- a/src/v2/components/database/builder.ts +++ b/src/v2/components/database/builder.ts @@ -4,15 +4,27 @@ import * as awsx from '@pulumi/awsx'; import { Database } from '.'; export namespace DatabaseBuilder { + export type InstanceConfig = Database.Instance; + export type CredentialsConfig = Database.Credentials; + export type StorageConfig = Omit; export type Config = Omit< Database.Args, - 'vpc' | 'enableMonitoring' | 'kmsKeyId' | 'snapshotIdentifier' + | keyof Database.Instance + | keyof Database.Credentials + | keyof Database.Storage + | 'vpc' + | 'enableMonitoring' + | 'kmsKeyId' + | 'snapshotIdentifier' >; } export class DatabaseBuilder { private name: string; private config?: DatabaseBuilder.Config; + private instanceConfig?: DatabaseBuilder.InstanceConfig; + private credentialsConfig?: DatabaseBuilder.CredentialsConfig; + private storageConfig?: DatabaseBuilder.StorageConfig; private vpc?: Database.Args['vpc']; private enableMonitoring?: Database.Args['enableMonitoring']; private kmsKeyId?: Database.Args['kmsKeyId']; @@ -28,7 +40,29 @@ export class DatabaseBuilder { return this; } - public withVpc(vpc: pulumi.Input): this { + public withInstance( + instanceConfig: DatabaseBuilder.InstanceConfig = {}, + ): this { + this.instanceConfig = instanceConfig; + + return this; + } + + public withCredentials( + credentialsConfig: DatabaseBuilder.CredentialsConfig = {}, + ): this { + this.credentialsConfig = credentialsConfig; + + return this; + } + + public withStorage(storageConfig: DatabaseBuilder.StorageConfig = {}): this { + this.storageConfig = storageConfig; + + return this; + } + + public withVpc(vpc: Database.Args['vpc']): this { this.vpc = pulumi.output(vpc); return this; @@ -40,37 +74,44 @@ export class DatabaseBuilder { return this; } - public withSnapshot(snapshotIdentifier: pulumi.Input): this { + public withSnapshot( + snapshotIdentifier: Database.Args['snapshotIdentifier'], + ): this { this.snapshotIdentifier = snapshotIdentifier; return this; } - public withKms(kmsKeyId: pulumi.Input): this { + public withKms(kmsKeyId: Database.Args['kmsKeyId']): this { this.kmsKeyId = kmsKeyId; return this; } public build(opts: pulumi.ComponentResourceOptions = {}): Database { - if (!this.config) { + if (!this.snapshotIdentifier && !this.instanceConfig?.dbName) { throw new Error( - `Database is not configured. Make sure to call DatabaseBuilder.withConfiguration().`, + 'DbName not provided. Make sure to call DatabaseBuilder.withInstance() and set dbName.', ); } - if (!this.vpc) { + if (!this.snapshotIdentifier && !this.credentialsConfig?.username) { throw new Error( - 'VPC not provided. Make sure to call DatabaseBuilder.withVpc().', + 'Username not provided. Make sure to call DatabaseBuilder.withCredentials() and set username.', ); } - if ( - this.snapshotIdentifier && - (this.config.dbName || this.config.username) - ) { + if (this.snapshotIdentifier && !this.instanceConfig?.dbName) { + throw new Error(`You can't set dbName when using snapshotIdentifier.`); + } + + if (this.snapshotIdentifier && !this.credentialsConfig?.username) { + throw new Error(`You can't set username when using snapshotIdentifier.`); + } + + if (!this.vpc) { throw new Error( - `You can't set dbName or username when using snapshotIdentifier.`, + 'VPC not provided. Make sure to call DatabaseBuilder.withVpc().', ); } @@ -78,6 +119,9 @@ export class DatabaseBuilder { this.name, { ...this.config, + ...this.instanceConfig, + ...this.credentialsConfig, + ...this.storageConfig, vpc: this.vpc, enableMonitoring: this.enableMonitoring, snapshotIdentifier: this.snapshotIdentifier, From 950fe1ae45a3d0a986820877c03bafd54db92bed Mon Sep 17 00:00:00 2001 From: mandryllo Date: Wed, 10 Dec 2025 15:00:28 +0100 Subject: [PATCH 23/71] Revert allocatedStorage type to number --- src/v2/components/database/index.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/v2/components/database/index.ts b/src/v2/components/database/index.ts index 76c7af0..388740d 100644 --- a/src/v2/components/database/index.ts +++ b/src/v2/components/database/index.ts @@ -21,7 +21,7 @@ export namespace Database { }; export type Storage = { - allocatedStorage?: pulumi.Input; + allocatedStorage?: pulumi.Input; maxAllocatedStorage?: pulumi.Input; kmsKeyId?: pulumi.Input; }; @@ -43,7 +43,7 @@ export namespace Database { const defaults = { multiAz: false, applyImmediately: false, - allocatedStorage: '20', + allocatedStorage: 20, maxAllocatedStorage: 100, instanceClass: 'db.t4g.micro', enableMonitoring: false, @@ -228,7 +228,7 @@ export class Database extends pulumi.ComponentResource { masterUserPassword: this.password.value, dbSubnetGroupName: this.dbSubnetGroup.name, vpcSecurityGroups: [this.dbSecurityGroup.id], - allocatedStorage: args.allocatedStorage, + allocatedStorage: args.allocatedStorage?.toString(), maxAllocatedStorage: args.maxAllocatedStorage, multiAz: args.multiAz, applyImmediately: args.applyImmediately, From ff389f96875cb13d9908fdda97ba949f87dad8a9 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Wed, 10 Dec 2025 15:06:33 +0100 Subject: [PATCH 24/71] Remove withKms method from builder --- src/v2/components/database/builder.ts | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/v2/components/database/builder.ts b/src/v2/components/database/builder.ts index f5003fe..f1c8641 100644 --- a/src/v2/components/database/builder.ts +++ b/src/v2/components/database/builder.ts @@ -6,7 +6,7 @@ import { Database } from '.'; export namespace DatabaseBuilder { export type InstanceConfig = Database.Instance; export type CredentialsConfig = Database.Credentials; - export type StorageConfig = Omit; + export type StorageConfig = Database.Storage; export type Config = Omit< Database.Args, | keyof Database.Instance @@ -14,7 +14,6 @@ export namespace DatabaseBuilder { | keyof Database.Storage | 'vpc' | 'enableMonitoring' - | 'kmsKeyId' | 'snapshotIdentifier' >; } @@ -27,7 +26,6 @@ export class DatabaseBuilder { private storageConfig?: DatabaseBuilder.StorageConfig; private vpc?: Database.Args['vpc']; private enableMonitoring?: Database.Args['enableMonitoring']; - private kmsKeyId?: Database.Args['kmsKeyId']; private snapshotIdentifier?: Database.Args['snapshotIdentifier']; constructor(name: string) { @@ -82,12 +80,6 @@ export class DatabaseBuilder { return this; } - public withKms(kmsKeyId: Database.Args['kmsKeyId']): this { - this.kmsKeyId = kmsKeyId; - - return this; - } - public build(opts: pulumi.ComponentResourceOptions = {}): Database { if (!this.snapshotIdentifier && !this.instanceConfig?.dbName) { throw new Error( @@ -125,7 +117,6 @@ export class DatabaseBuilder { vpc: this.vpc, enableMonitoring: this.enableMonitoring, snapshotIdentifier: this.snapshotIdentifier, - kmsKeyId: this.kmsKeyId, }, opts, ); From 817f10004129a2dcd3c84667e27d458356d59442 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Wed, 10 Dec 2025 15:08:52 +0100 Subject: [PATCH 25/71] Update type tests --- tests/build/index.tst.ts | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/tests/build/index.tst.ts b/tests/build/index.tst.ts index 669f2b6..ee2ba5f 100644 --- a/tests/build/index.tst.ts +++ b/tests/build/index.tst.ts @@ -293,12 +293,29 @@ describe('Build output', () => { it('should have withConfiguration method', () => { expect(builder.withConfiguration).type.toBeCallableWith({ + applyImmediately: true, + }); + }); + + it('should have withInstance method', () => { + expect(builder.withInstance).type.toBeCallableWith({ dbName: 'dbName', + }); + }); + + it('should have withCredentials method', () => { + expect(builder.withCredentials).type.toBeCallableWith({ username: 'username', password: 'password', }); }); + it('should have withStorage method', () => { + expect(builder.withStorage).type.toBeCallableWith({ + kmsKeyId: 'kms-key-id', + }); + }); + it('should have withVpc method', () => { expect(builder.withVpc).type.toBeCallableWith( new awsx.ec2.Vpc('vpcName'), @@ -312,10 +329,6 @@ describe('Build output', () => { it('should have withSnapshot method', () => { expect(builder.withSnapshot).type.toBeCallableWith('snapshot-id'); }); - - it('should have withKms method', () => { - expect(builder.withKms).type.toBeCallableWith('kms-key-id'); - }); }); }); }); From 06058880b6cf3fa493aa0c0e7ac75916575d5e75 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Wed, 10 Dec 2025 15:13:51 +0100 Subject: [PATCH 26/71] Update integration tests --- tests/database/infrastructure/index.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/database/infrastructure/index.ts b/tests/database/infrastructure/index.ts index b642e65..d9e495f 100644 --- a/tests/database/infrastructure/index.ts +++ b/tests/database/infrastructure/index.ts @@ -4,10 +4,14 @@ import * as config from './config'; const vpc = new studion.Vpc(`${config.appName}-vpc`, {}); const defaultDb = new studion.DatabaseBuilder(`${config.appName}-default`) - .withConfiguration({ + .withInstance({ dbName: config.dbName, + }) + .withCredentials({ username: config.dbUsername, password: config.dbPassword, + }) + .withConfiguration({ tags: config.tags, }) .withVpc(vpc.vpc) From 15927fef067b7bcd6eb2f217fed2de66ecdd2264 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Wed, 10 Dec 2025 16:55:39 +0100 Subject: [PATCH 27/71] fix tags --- src/v2/components/database/index.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/v2/components/database/index.ts b/src/v2/components/database/index.ts index 388740d..93549d8 100644 --- a/src/v2/components/database/index.ts +++ b/src/v2/components/database/index.ts @@ -245,11 +245,13 @@ export class Database extends pulumi.ComponentResource { dbSnapshotIdentifier: this.encryptedSnapshotCopy?.targetDbSnapshotIdentifier, ...monitoringOptions, - tags: [ - ...Object.entries({ ...commonTags, ...args.tags }).map( - ([key, value]) => ({ key, value }), - ), - ], + tags: pulumi + .output(args.tags) + .apply(tags => [ + ...Object.entries({ ...commonTags, ...tags }).map( + ([key, value]) => ({ key, value }), + ), + ]), }, { parent: this, dependsOn: [this.password] }, ); From f72366fa860491f89ba3c0049a9e34cf678e95b1 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Wed, 10 Dec 2025 16:55:51 +0100 Subject: [PATCH 28/71] Fix snapshot id --- src/v2/components/database/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/v2/components/database/index.ts b/src/v2/components/database/index.ts index 93549d8..695d12a 100644 --- a/src/v2/components/database/index.ts +++ b/src/v2/components/database/index.ts @@ -184,7 +184,7 @@ export class Database extends pulumi.ComponentResource { } private createEncryptedSnapshotCopy( - snapshotIdentifier: pulumi.Input, + snapshotIdentifier: Database.Args['snapshotIdentifier'], ) { const sourceDbSnapshotIdentifier = pulumi .output(snapshotIdentifier) @@ -198,7 +198,7 @@ export class Database extends pulumi.ComponentResource { `${this.name}-encrypted-snapshot-copy`, { sourceDbSnapshotIdentifier, - targetDbSnapshotIdentifier: `${snapshotIdentifier}-encrypted-copy`, + targetDbSnapshotIdentifier: pulumi.interpolate`${snapshotIdentifier}-encrypted-copy`, kmsKeyId: this.kmsKeyId, }, { parent: this }, From 3b4d3e5d5f9d4ffa63541b67768669db6c0056a2 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Wed, 10 Dec 2025 17:07:43 +0100 Subject: [PATCH 29/71] Remove export --- src/v2/index.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/v2/index.ts b/src/v2/index.ts index cc2a848..aaaabc7 100644 --- a/src/v2/index.ts +++ b/src/v2/index.ts @@ -5,8 +5,6 @@ export { WebServerLoadBalancer } from './components/web-server/load-balancer'; export { ElastiCacheRedis } from './components/redis/elasticache-redis'; export { UpstashRedis } from './components/redis/upstash-redis'; export { Vpc } from './components/vpc'; -export { Database } from './components/database'; -export { DatabaseBuilder } from './components/database/builder'; import { OtelCollectorBuilder } from './otel/builder'; import { OtelCollector } from './otel'; From ef9fea4952de1f63536fa7417c33bdada6882774 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Wed, 10 Dec 2025 17:08:12 +0100 Subject: [PATCH 30/71] Fix imports in tests --- tests/build/index.tst.ts | 10 +++++----- tests/database/infrastructure/index.ts | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/tests/build/index.tst.ts b/tests/build/index.tst.ts index ee2ba5f..7ae8ec4 100644 --- a/tests/build/index.tst.ts +++ b/tests/build/index.tst.ts @@ -4,6 +4,8 @@ import { describe, expect, it } from 'tstyche'; import { next as studion } from '@studion/infra-code-blocks'; import { OtelCollector } from '../../dist/v2/otel'; import { OtelCollectorBuilder } from '../../dist/v2/otel/builder'; +import { Database } from '../../dist/v2/components/database'; +import { DatabaseBuilder } from '../../dist/v2/components/database/builder'; describe('Build output', () => { describe('ECS Service', () => { @@ -260,17 +262,15 @@ describe('Build output', () => { }); describe('Database', () => { - it('should export Database', () => { + it.skip('should export Database', () => { expect(studion).type.toHaveProperty('Database'); }); - it('should export DatabaseBuilder', () => { + it.skip('should export DatabaseBuilder', () => { expect(studion).type.toHaveProperty('DatabaseBuilder'); }); describe('Instantiation', () => { - const { Database, DatabaseBuilder } = studion; - it('should construct Database', () => { expect(Database).type.toBeConstructableWith('db-test', { vpc: new awsx.ec2.Vpc('vpcName'), @@ -285,7 +285,7 @@ describe('Build output', () => { }); describe('Builder', () => { - const builder = new studion.DatabaseBuilder('db-test'); + const builder = new DatabaseBuilder('db-test'); it('should have build method', () => { expect(builder.build).type.toBeCallableWith(); diff --git a/tests/database/infrastructure/index.ts b/tests/database/infrastructure/index.ts index d9e495f..6a584b2 100644 --- a/tests/database/infrastructure/index.ts +++ b/tests/database/infrastructure/index.ts @@ -1,9 +1,10 @@ import { next as studion } from '@studion/infra-code-blocks'; +import { DatabaseBuilder } from '../../../dist/v2/components/database/builder'; import * as config from './config'; const vpc = new studion.Vpc(`${config.appName}-vpc`, {}); -const defaultDb = new studion.DatabaseBuilder(`${config.appName}-default`) +const defaultDb = new DatabaseBuilder(`${config.appName}-default`) .withInstance({ dbName: config.dbName, }) From c826e1236719088ec4c8b3d25a682fc38d73905f Mon Sep 17 00:00:00 2001 From: mandryllo Date: Thu, 11 Dec 2025 13:09:14 +0100 Subject: [PATCH 31/71] Fix wrong condition --- src/v2/components/database/builder.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/v2/components/database/builder.ts b/src/v2/components/database/builder.ts index f1c8641..a9fda6d 100644 --- a/src/v2/components/database/builder.ts +++ b/src/v2/components/database/builder.ts @@ -93,11 +93,11 @@ export class DatabaseBuilder { ); } - if (this.snapshotIdentifier && !this.instanceConfig?.dbName) { + if (this.snapshotIdentifier && this.instanceConfig?.dbName) { throw new Error(`You can't set dbName when using snapshotIdentifier.`); } - if (this.snapshotIdentifier && !this.credentialsConfig?.username) { + if (this.snapshotIdentifier && this.credentialsConfig?.username) { throw new Error(`You can't set username when using snapshotIdentifier.`); } From 20a59e3ea50b3cb6d20ad3e973492e79fb6d10fa Mon Sep 17 00:00:00 2001 From: mandryllo Date: Mon, 15 Dec 2025 10:39:55 +0100 Subject: [PATCH 32/71] Cleanup final snapshots --- tests/database/index.test.ts | 2 ++ tests/database/utils/cleanup-snapshots.ts | 35 +++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 tests/database/utils/cleanup-snapshots.ts diff --git a/tests/database/index.test.ts b/tests/database/index.test.ts index 83b6ec5..549b88e 100644 --- a/tests/database/index.test.ts +++ b/tests/database/index.test.ts @@ -1,5 +1,6 @@ import { describe, before, after } from 'node:test'; import * as automation from '../automation'; +import { cleanupSnapshots } from './utils/cleanup-snapshots'; import * as config from './infrastructure/config'; import { DatabaseTestContext } from './test-context'; import { EC2Client } from '@aws-sdk/client-ec2'; @@ -37,4 +38,5 @@ describe('Database component deployment', () => { after(() => automation.destroy(programArgs)); describe('Default database', () => testDefaultDb(ctx)); + after(() => cleanupSnapshots(ctx)); }); diff --git a/tests/database/utils/cleanup-snapshots.ts b/tests/database/utils/cleanup-snapshots.ts new file mode 100644 index 0000000..7722b8e --- /dev/null +++ b/tests/database/utils/cleanup-snapshots.ts @@ -0,0 +1,35 @@ +import { + DeleteDBSnapshotCommand, + DescribeDBSnapshotsCommand, +} from '@aws-sdk/client-rds'; +import { createSpinner } from 'nanospinner'; +import { DatabaseTestContext } from '../test-context'; + +export async function cleanupSnapshots(ctx: DatabaseTestContext) { + const spinner = createSpinner('Deleting snapshots...').start(); + + const defaultDb = ctx.outputs.defaultDb.value; + await deleteSnapshot(ctx, defaultDb.instance.dbInstanceIdentifier); + + spinner.success({ text: 'Snapshots deleted' }); +} + +async function deleteSnapshot( + ctx: DatabaseTestContext, + DBInstanceIdentifier: string, +) { + const describeCommand = new DescribeDBSnapshotsCommand({ + DBInstanceIdentifier, + }); + const { DBSnapshots } = await ctx.clients.rds.send(describeCommand); + + if (!DBSnapshots || !DBSnapshots.length) { + throw new Error('Snapshot not found'); + } + const [DBSnapshot] = DBSnapshots; + + const deleteCommand = new DeleteDBSnapshotCommand({ + DBSnapshotIdentifier: DBSnapshot.DBSnapshotIdentifier, + }); + await ctx.clients.rds.send(deleteCommand); +} From 3648874f0c1dbdc564a5c2aa0a34224f27486505 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Mon, 15 Dec 2025 15:30:59 +0100 Subject: [PATCH 33/71] Fix getting snapshots --- tests/database/utils/cleanup-snapshots.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/database/utils/cleanup-snapshots.ts b/tests/database/utils/cleanup-snapshots.ts index 7722b8e..5779b50 100644 --- a/tests/database/utils/cleanup-snapshots.ts +++ b/tests/database/utils/cleanup-snapshots.ts @@ -20,6 +20,7 @@ async function deleteSnapshot( ) { const describeCommand = new DescribeDBSnapshotsCommand({ DBInstanceIdentifier, + SnapshotType: 'manual', }); const { DBSnapshots } = await ctx.clients.rds.send(describeCommand); From 3bba7844be1ef445ed832c85c9043061a9831520 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Tue, 16 Dec 2025 11:41:06 +0100 Subject: [PATCH 34/71] Update database builder --- src/v2/components/database/builder.ts | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/v2/components/database/builder.ts b/src/v2/components/database/builder.ts index a9fda6d..566088c 100644 --- a/src/v2/components/database/builder.ts +++ b/src/v2/components/database/builder.ts @@ -6,7 +6,7 @@ import { Database } from '.'; export namespace DatabaseBuilder { export type InstanceConfig = Database.Instance; export type CredentialsConfig = Database.Credentials; - export type StorageConfig = Database.Storage; + export type StorageConfig = Omit; export type Config = Omit< Database.Args, | keyof Database.Instance @@ -15,6 +15,7 @@ export namespace DatabaseBuilder { | 'vpc' | 'enableMonitoring' | 'snapshotIdentifier' + | 'parameterGroupName' >; } @@ -27,6 +28,8 @@ export class DatabaseBuilder { private vpc?: Database.Args['vpc']; private enableMonitoring?: Database.Args['enableMonitoring']; private snapshotIdentifier?: Database.Args['snapshotIdentifier']; + private kmsKeyId?: Database.Args['kmsKeyId']; + private parameterGroupName?: Database.Args['parameterGroupName']; constructor(name: string) { this.name = name; @@ -80,6 +83,20 @@ export class DatabaseBuilder { return this; } + public withKms(kmsKeyId: Database.Args['kmsKeyId']): this { + this.kmsKeyId = kmsKeyId; + + return this; + } + + public withParameterGroup( + parameterGroupName: Database.Args['parameterGroupName'], + ): this { + this.parameterGroupName = parameterGroupName; + + return this; + } + public build(opts: pulumi.ComponentResourceOptions = {}): Database { if (!this.snapshotIdentifier && !this.instanceConfig?.dbName) { throw new Error( @@ -117,6 +134,8 @@ export class DatabaseBuilder { vpc: this.vpc, enableMonitoring: this.enableMonitoring, snapshotIdentifier: this.snapshotIdentifier, + kmsKeyId: this.kmsKeyId, + parameterGroupName: this.parameterGroupName, }, opts, ); From 3602506080782e269f74ccb00cbfe71fc306c0b7 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Tue, 16 Dec 2025 11:41:47 +0100 Subject: [PATCH 35/71] Cleanup --- src/v2/components/database/builder.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/v2/components/database/builder.ts b/src/v2/components/database/builder.ts index 566088c..90c03d7 100644 --- a/src/v2/components/database/builder.ts +++ b/src/v2/components/database/builder.ts @@ -1,7 +1,5 @@ -import * as pulumi from '@pulumi/pulumi'; -import * as aws from '@pulumi/aws'; -import * as awsx from '@pulumi/awsx'; import { Database } from '.'; +import * as pulumi from '@pulumi/pulumi'; export namespace DatabaseBuilder { export type InstanceConfig = Database.Instance; From 78228942b5cc930cb8c55ce9cea015536dc164ff Mon Sep 17 00:00:00 2001 From: mandryllo Date: Tue, 16 Dec 2025 11:46:53 +0100 Subject: [PATCH 36/71] Fix type tests --- tests/build/index.tst.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/build/index.tst.ts b/tests/build/index.tst.ts index 7ae8ec4..fa3a385 100644 --- a/tests/build/index.tst.ts +++ b/tests/build/index.tst.ts @@ -312,7 +312,8 @@ describe('Build output', () => { it('should have withStorage method', () => { expect(builder.withStorage).type.toBeCallableWith({ - kmsKeyId: 'kms-key-id', + allocatedStorage: 50, + maxAllocatedStorage: 200, }); }); @@ -329,6 +330,16 @@ describe('Build output', () => { it('should have withSnapshot method', () => { expect(builder.withSnapshot).type.toBeCallableWith('snapshot-id'); }); + + it('should have withKms method', () => { + expect(builder.withKms).type.toBeCallableWith('kms-key-id'); + }); + + it('should have withParameterGroup method', () => { + expect(builder.withParameterGroup).type.toBeCallableWith( + 'parameter-group-name', + ); + }); }); }); }); From 3107de3f7f5e2eb4d309714314a7dcf76f4f2b41 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Tue, 2 Dec 2025 15:54:30 +0100 Subject: [PATCH 37/71] Create db v2 component # Conflicts: # src/v2/components/database/index.ts --- src/v2/components/database/index.ts | 193 +++++++++++++++------------- 1 file changed, 107 insertions(+), 86 deletions(-) diff --git a/src/v2/components/database/index.ts b/src/v2/components/database/index.ts index 695d12a..24802c3 100644 --- a/src/v2/components/database/index.ts +++ b/src/v2/components/database/index.ts @@ -6,44 +6,34 @@ import { Password } from '../../../components/password'; import { commonTags } from '../../../constants'; export namespace Database { - export type Instance = { + export type Args = { dbName?: pulumi.Input; - engineVersion?: pulumi.Input; + username?: pulumi.Input; + password?: pulumi.Input; + vpc: pulumi.Input; multiAz?: pulumi.Input; + applyImmediately?: pulumi.Input; + allocatedStorage?: pulumi.Input; + maxAllocatedStorage?: pulumi.Input; instanceClass?: pulumi.Input; allowMajorVersionUpgrade?: pulumi.Input; autoMinorVersionUpgrade?: pulumi.Input; - }; - - export type Credentials = { - username?: pulumi.Input; - password?: pulumi.Input; - }; - - export type Storage = { - allocatedStorage?: pulumi.Input; - maxAllocatedStorage?: pulumi.Input; kmsKeyId?: pulumi.Input; + parameterGroupName?: pulumi.Input; + customParameterGroupArgs?: pulumi.Input; + snapshotIdentifier?: pulumi.Input; + enableMonitoring?: pulumi.Input; + engineVersion?: pulumi.Input; + tags?: pulumi.Input<{ + [key: string]: pulumi.Input; + }>; }; - - export type Args = Instance & - Credentials & - Storage & { - vpc: pulumi.Input; - enableMonitoring?: pulumi.Input; - applyImmediately?: pulumi.Input; - snapshotIdentifier?: pulumi.Input; - parameterGroupName?: pulumi.Input; - tags?: pulumi.Input<{ - [key: string]: pulumi.Input; - }>; - }; } const defaults = { multiAz: false, applyImmediately: false, - allocatedStorage: 20, + allocatedStorage: '20', maxAllocatedStorage: 100, instanceClass: 'db.t4g.micro', enableMonitoring: false, @@ -55,13 +45,13 @@ const defaults = { export class Database extends pulumi.ComponentResource { name: string; instance: awsNative.rds.DbInstance; - vpc: pulumi.Output; dbSubnetGroup: aws.rds.SubnetGroup; dbSecurityGroup: aws.ec2.SecurityGroup; password: Password; - kmsKeyId: pulumi.Output; - monitoringRole?: aws.iam.Role; encryptedSnapshotCopy?: aws.rds.SnapshotCopy; + monitoringRole?: aws.iam.Role; + kmsKeyId: pulumi.Input; + parameterGroupName?: pulumi.Input; constructor( name: string, @@ -73,12 +63,20 @@ export class Database extends pulumi.ComponentResource { this.name = name; const argsWithDefaults = Object.assign({}, defaults, args); - const { vpc, kmsKeyId, enableMonitoring, snapshotIdentifier } = - argsWithDefaults; + const { + kmsKeyId, + snapshotIdentifier, + enableMonitoring, + parameterGroupName, + customParameterGroupArgs, + } = argsWithDefaults; - this.vpc = pulumi.output(vpc); - this.dbSubnetGroup = this.createSubnetGroup(); - this.dbSecurityGroup = this.createSecurityGroup(); + const vpc = pulumi.output(argsWithDefaults.vpc); + this.dbSubnetGroup = this.createSubnetGroup(vpc.isolatedSubnetIds); + this.dbSecurityGroup = this.createSecurityGroup( + vpc.vpcId, + vpc.vpc.cidrBlock, + ); this.password = new Password( `${this.name}-database-password`, @@ -86,9 +84,11 @@ export class Database extends pulumi.ComponentResource { { parent: this }, ); - this.kmsKeyId = kmsKeyId - ? pulumi.output(kmsKeyId) - : this.createEncryptionKey().arn; + this.kmsKeyId = kmsKeyId || this.createEncryptionKey().arn; + + this.parameterGroupName = customParameterGroupArgs + ? this.createParameterGroup(customParameterGroupArgs).name + : parameterGroupName; if (enableMonitoring) { this.monitoringRole = this.createMonitoringRole(); @@ -99,43 +99,50 @@ export class Database extends pulumi.ComponentResource { this.createEncryptedSnapshotCopy(snapshotIdentifier); } - this.instance = this.createDatabaseInstance(argsWithDefaults); + this.instance = this.createDatabaseInstance(args); this.registerOutputs(); } - private createSubnetGroup() { - return new aws.rds.SubnetGroup( + private createSubnetGroup( + isolatedSubnetIds: awsx.ec2.Vpc['isolatedSubnetIds'], + ) { + const dbSubnetGroup = new aws.rds.SubnetGroup( `${this.name}-subnet-group`, { - subnetIds: this.vpc.isolatedSubnetIds, + subnetIds: isolatedSubnetIds, tags: commonTags, }, { parent: this }, ); + return dbSubnetGroup; } - private createSecurityGroup() { - return new aws.ec2.SecurityGroup( + private createSecurityGroup( + vpcId: awsx.ec2.Vpc['vpcId'], + vpcCidrBlock: pulumi.Input, + ) { + const dbSecurityGroup = new aws.ec2.SecurityGroup( `${this.name}-security-group`, { - vpcId: this.vpc.vpcId, + vpcId, ingress: [ { protocol: 'tcp', fromPort: 5432, toPort: 5432, - cidrBlocks: [this.vpc.vpc.cidrBlock], + cidrBlocks: [vpcCidrBlock], }, ], tags: commonTags, }, { parent: this }, ); + return dbSecurityGroup; } private createEncryptionKey() { - return new aws.kms.Key( + const kms = new aws.kms.Key( `${this.name}-rds-key`, { description: `${this.name} RDS encryption key`, @@ -148,27 +155,24 @@ export class Database extends pulumi.ComponentResource { }, { parent: this }, ); + return kms; } private createMonitoringRole() { - const monitoringRole = new aws.iam.Role( - `${this.name}-rds-monitoring`, - { - assumeRolePolicy: { - Version: '2012-10-17', - Statement: [ - { - Action: 'sts:AssumeRole', - Effect: 'Allow', - Principal: { - Service: 'monitoring.rds.amazonaws.com', - }, + const monitoringRole = new aws.iam.Role(`${this.name}-rds-monitoring`, { + assumeRolePolicy: { + Version: '2012-10-17', + Statement: [ + { + Action: 'sts:AssumeRole', + Effect: 'Allow', + Principal: { + Service: 'monitoring.rds.amazonaws.com', }, - ], - }, + }, + ], }, - { parent: this }, - ); + }); new aws.iam.RolePolicyAttachment( `${this.name}-rds-monitoring-role-attachment`, @@ -177,14 +181,13 @@ export class Database extends pulumi.ComponentResource { policyArn: 'arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole', }, - { parent: this }, ); return monitoringRole; } private createEncryptedSnapshotCopy( - snapshotIdentifier: Database.Args['snapshotIdentifier'], + snapshotIdentifier: pulumi.Input, ) { const sourceDbSnapshotIdentifier = pulumi .output(snapshotIdentifier) @@ -192,22 +195,42 @@ export class Database extends pulumi.ComponentResource { aws.rds.getSnapshot({ dbSnapshotIdentifier: snapshotIdentifier, }), - ).dbSnapshotArn; + ) + .apply(snapshot => snapshot.dbSnapshotArn); - return new aws.rds.SnapshotCopy( + const encryptedSnapshotCopy = new aws.rds.SnapshotCopy( `${this.name}-encrypted-snapshot-copy`, { sourceDbSnapshotIdentifier, - targetDbSnapshotIdentifier: pulumi.interpolate`${snapshotIdentifier}-encrypted-copy`, + targetDbSnapshotIdentifier: `${snapshotIdentifier}-encrypted-copy`, kmsKeyId: this.kmsKeyId, }, { parent: this }, ); + return encryptedSnapshotCopy; + } + + private createParameterGroup( + customParameterGroupArgs: pulumi.Input, + ) { + const parameterGroup = pulumi + .output(customParameterGroupArgs) + .apply(args => { + return new aws.rds.ParameterGroup( + `${this.name}-parameter-group`, + args, + { parent: this }, + ); + }); + + return parameterGroup; } private createDatabaseInstance(args: Database.Args) { + const argsWithDefaults = Object.assign({}, defaults, args); + const monitoringOptions = - args.enableMonitoring && this.monitoringRole + argsWithDefaults.enableMonitoring && this.monitoringRole ? { monitoringInterval: 60, monitoringRoleArn: this.monitoringRole.arn, @@ -221,19 +244,19 @@ export class Database extends pulumi.ComponentResource { { dbInstanceIdentifier: `${this.name}-db-instance`, engine: 'postgres', - engineVersion: args.engineVersion, - dbInstanceClass: args.instanceClass, - dbName: args.dbName, - masterUsername: args.username, + engineVersion: argsWithDefaults.engineVersion, + dbInstanceClass: argsWithDefaults.instanceClass, + dbName: argsWithDefaults.dbName, + masterUsername: argsWithDefaults.username, masterUserPassword: this.password.value, dbSubnetGroupName: this.dbSubnetGroup.name, vpcSecurityGroups: [this.dbSecurityGroup.id], - allocatedStorage: args.allocatedStorage?.toString(), - maxAllocatedStorage: args.maxAllocatedStorage, - multiAz: args.multiAz, - applyImmediately: args.applyImmediately, - allowMajorVersionUpgrade: args.allowMajorVersionUpgrade, - autoMinorVersionUpgrade: args.autoMinorVersionUpgrade, + allocatedStorage: argsWithDefaults.allocatedStorage, + maxAllocatedStorage: argsWithDefaults.maxAllocatedStorage, + multiAz: argsWithDefaults.multiAz, + applyImmediately: argsWithDefaults.applyImmediately, + allowMajorVersionUpgrade: argsWithDefaults.allowMajorVersionUpgrade, + autoMinorVersionUpgrade: argsWithDefaults.autoMinorVersionUpgrade, kmsKeyId: this.kmsKeyId, storageEncrypted: true, publiclyAccessible: false, @@ -241,17 +264,15 @@ export class Database extends pulumi.ComponentResource { preferredBackupWindow: '06:00-06:30', backupRetentionPeriod: 14, caCertificateIdentifier: 'rds-ca-rsa2048-g1', - dbParameterGroupName: args.parameterGroupName, + dbParameterGroupName: this.parameterGroupName, dbSnapshotIdentifier: this.encryptedSnapshotCopy?.targetDbSnapshotIdentifier, ...monitoringOptions, - tags: pulumi - .output(args.tags) - .apply(tags => [ - ...Object.entries({ ...commonTags, ...tags }).map( - ([key, value]) => ({ key, value }), - ), - ]), + tags: [ + ...Object.entries({ ...commonTags, ...argsWithDefaults.tags }).map( + ([key, value]) => ({ key, value }), + ), + ], }, { parent: this, dependsOn: [this.password] }, ); From e0cae9ba24e5a68cd4e728a6446e5615256b2581 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Fri, 5 Dec 2025 10:31:48 +0100 Subject: [PATCH 38/71] Remove ability to create custom parameter group --- src/v2/components/database/index.ts | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/src/v2/components/database/index.ts b/src/v2/components/database/index.ts index 24802c3..8e037af 100644 --- a/src/v2/components/database/index.ts +++ b/src/v2/components/database/index.ts @@ -20,7 +20,6 @@ export namespace Database { autoMinorVersionUpgrade?: pulumi.Input; kmsKeyId?: pulumi.Input; parameterGroupName?: pulumi.Input; - customParameterGroupArgs?: pulumi.Input; snapshotIdentifier?: pulumi.Input; enableMonitoring?: pulumi.Input; engineVersion?: pulumi.Input; @@ -51,7 +50,6 @@ export class Database extends pulumi.ComponentResource { encryptedSnapshotCopy?: aws.rds.SnapshotCopy; monitoringRole?: aws.iam.Role; kmsKeyId: pulumi.Input; - parameterGroupName?: pulumi.Input; constructor( name: string, @@ -67,8 +65,6 @@ export class Database extends pulumi.ComponentResource { kmsKeyId, snapshotIdentifier, enableMonitoring, - parameterGroupName, - customParameterGroupArgs, } = argsWithDefaults; const vpc = pulumi.output(argsWithDefaults.vpc); @@ -86,10 +82,6 @@ export class Database extends pulumi.ComponentResource { this.kmsKeyId = kmsKeyId || this.createEncryptionKey().arn; - this.parameterGroupName = customParameterGroupArgs - ? this.createParameterGroup(customParameterGroupArgs).name - : parameterGroupName; - if (enableMonitoring) { this.monitoringRole = this.createMonitoringRole(); } @@ -210,22 +202,6 @@ export class Database extends pulumi.ComponentResource { return encryptedSnapshotCopy; } - private createParameterGroup( - customParameterGroupArgs: pulumi.Input, - ) { - const parameterGroup = pulumi - .output(customParameterGroupArgs) - .apply(args => { - return new aws.rds.ParameterGroup( - `${this.name}-parameter-group`, - args, - { parent: this }, - ); - }); - - return parameterGroup; - } - private createDatabaseInstance(args: Database.Args) { const argsWithDefaults = Object.assign({}, defaults, args); @@ -264,7 +240,7 @@ export class Database extends pulumi.ComponentResource { preferredBackupWindow: '06:00-06:30', backupRetentionPeriod: 14, caCertificateIdentifier: 'rds-ca-rsa2048-g1', - dbParameterGroupName: this.parameterGroupName, + dbParameterGroupName: argsWithDefaults.parameterGroupName, dbSnapshotIdentifier: this.encryptedSnapshotCopy?.targetDbSnapshotIdentifier, ...monitoringOptions, From 117e798b5adf3b99ecfad875d9d02de820fa37fa Mon Sep 17 00:00:00 2001 From: mandryllo Date: Fri, 5 Dec 2025 10:34:46 +0100 Subject: [PATCH 39/71] Cleanup --- src/v2/components/database/index.ts | 30 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/v2/components/database/index.ts b/src/v2/components/database/index.ts index 8e037af..297227d 100644 --- a/src/v2/components/database/index.ts +++ b/src/v2/components/database/index.ts @@ -91,7 +91,7 @@ export class Database extends pulumi.ComponentResource { this.createEncryptedSnapshotCopy(snapshotIdentifier); } - this.instance = this.createDatabaseInstance(args); + this.instance = this.createDatabaseInstance(argsWithDefaults); this.registerOutputs(); } @@ -203,10 +203,8 @@ export class Database extends pulumi.ComponentResource { } private createDatabaseInstance(args: Database.Args) { - const argsWithDefaults = Object.assign({}, defaults, args); - const monitoringOptions = - argsWithDefaults.enableMonitoring && this.monitoringRole + args.enableMonitoring && this.monitoringRole ? { monitoringInterval: 60, monitoringRoleArn: this.monitoringRole.arn, @@ -220,19 +218,19 @@ export class Database extends pulumi.ComponentResource { { dbInstanceIdentifier: `${this.name}-db-instance`, engine: 'postgres', - engineVersion: argsWithDefaults.engineVersion, - dbInstanceClass: argsWithDefaults.instanceClass, - dbName: argsWithDefaults.dbName, - masterUsername: argsWithDefaults.username, + engineVersion: args.engineVersion, + dbInstanceClass: args.instanceClass, + dbName: args.dbName, + masterUsername: args.username, masterUserPassword: this.password.value, dbSubnetGroupName: this.dbSubnetGroup.name, vpcSecurityGroups: [this.dbSecurityGroup.id], - allocatedStorage: argsWithDefaults.allocatedStorage, - maxAllocatedStorage: argsWithDefaults.maxAllocatedStorage, - multiAz: argsWithDefaults.multiAz, - applyImmediately: argsWithDefaults.applyImmediately, - allowMajorVersionUpgrade: argsWithDefaults.allowMajorVersionUpgrade, - autoMinorVersionUpgrade: argsWithDefaults.autoMinorVersionUpgrade, + allocatedStorage: args.allocatedStorage, + maxAllocatedStorage: args.maxAllocatedStorage, + multiAz: args.multiAz, + applyImmediately: args.applyImmediately, + allowMajorVersionUpgrade: args.allowMajorVersionUpgrade, + autoMinorVersionUpgrade: args.autoMinorVersionUpgrade, kmsKeyId: this.kmsKeyId, storageEncrypted: true, publiclyAccessible: false, @@ -240,12 +238,12 @@ export class Database extends pulumi.ComponentResource { preferredBackupWindow: '06:00-06:30', backupRetentionPeriod: 14, caCertificateIdentifier: 'rds-ca-rsa2048-g1', - dbParameterGroupName: argsWithDefaults.parameterGroupName, + dbParameterGroupName: args.parameterGroupName, dbSnapshotIdentifier: this.encryptedSnapshotCopy?.targetDbSnapshotIdentifier, ...monitoringOptions, tags: [ - ...Object.entries({ ...commonTags, ...argsWithDefaults.tags }).map( + ...Object.entries({ ...commonTags, ...args.tags }).map( ([key, value]) => ({ key, value }), ), ], From 7c2b479103eb3442d62edab1c42fcfd9c872b5e1 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Fri, 5 Dec 2025 10:36:28 +0100 Subject: [PATCH 40/71] Fix kms key id type --- src/v2/components/database/index.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/v2/components/database/index.ts b/src/v2/components/database/index.ts index 297227d..689be95 100644 --- a/src/v2/components/database/index.ts +++ b/src/v2/components/database/index.ts @@ -49,7 +49,7 @@ export class Database extends pulumi.ComponentResource { password: Password; encryptedSnapshotCopy?: aws.rds.SnapshotCopy; monitoringRole?: aws.iam.Role; - kmsKeyId: pulumi.Input; + kmsKeyId: pulumi.Output; constructor( name: string, @@ -80,7 +80,9 @@ export class Database extends pulumi.ComponentResource { { parent: this }, ); - this.kmsKeyId = kmsKeyId || this.createEncryptionKey().arn; + this.kmsKeyId = kmsKeyId + ? pulumi.output(kmsKeyId) + : this.createEncryptionKey().arn; if (enableMonitoring) { this.monitoringRole = this.createMonitoringRole(); From 06fe2d81a2422acb2d63a8659a82bb890baa2bef Mon Sep 17 00:00:00 2001 From: mandryllo Date: Fri, 5 Dec 2025 18:16:19 +0100 Subject: [PATCH 41/71] Cleanup --- src/v2/components/database/index.ts | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/v2/components/database/index.ts b/src/v2/components/database/index.ts index 689be95..4f53246 100644 --- a/src/v2/components/database/index.ts +++ b/src/v2/components/database/index.ts @@ -101,7 +101,7 @@ export class Database extends pulumi.ComponentResource { private createSubnetGroup( isolatedSubnetIds: awsx.ec2.Vpc['isolatedSubnetIds'], ) { - const dbSubnetGroup = new aws.rds.SubnetGroup( + return new aws.rds.SubnetGroup( `${this.name}-subnet-group`, { subnetIds: isolatedSubnetIds, @@ -109,14 +109,13 @@ export class Database extends pulumi.ComponentResource { }, { parent: this }, ); - return dbSubnetGroup; } private createSecurityGroup( vpcId: awsx.ec2.Vpc['vpcId'], vpcCidrBlock: pulumi.Input, ) { - const dbSecurityGroup = new aws.ec2.SecurityGroup( + return new aws.ec2.SecurityGroup( `${this.name}-security-group`, { vpcId, @@ -132,11 +131,10 @@ export class Database extends pulumi.ComponentResource { }, { parent: this }, ); - return dbSecurityGroup; } private createEncryptionKey() { - const kms = new aws.kms.Key( + return new aws.kms.Key( `${this.name}-rds-key`, { description: `${this.name} RDS encryption key`, @@ -149,7 +147,6 @@ export class Database extends pulumi.ComponentResource { }, { parent: this }, ); - return kms; } private createMonitoringRole() { @@ -166,7 +163,9 @@ export class Database extends pulumi.ComponentResource { }, ], }, - }); + }, + { parent: this }, + ); new aws.iam.RolePolicyAttachment( `${this.name}-rds-monitoring-role-attachment`, @@ -175,6 +174,7 @@ export class Database extends pulumi.ComponentResource { policyArn: 'arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole', }, + { parent: this }, ); return monitoringRole; @@ -189,8 +189,7 @@ export class Database extends pulumi.ComponentResource { aws.rds.getSnapshot({ dbSnapshotIdentifier: snapshotIdentifier, }), - ) - .apply(snapshot => snapshot.dbSnapshotArn); + ).dbSnapshotArn; const encryptedSnapshotCopy = new aws.rds.SnapshotCopy( `${this.name}-encrypted-snapshot-copy`, From 17f5e9e1a1b207f02977e016b16137761f7c12f6 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Fri, 5 Dec 2025 18:23:04 +0100 Subject: [PATCH 42/71] Cleanup vpc parameters --- src/v2/components/database/index.ts | 32 ++++++++++++----------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/src/v2/components/database/index.ts b/src/v2/components/database/index.ts index 4f53246..e121cd5 100644 --- a/src/v2/components/database/index.ts +++ b/src/v2/components/database/index.ts @@ -44,12 +44,13 @@ const defaults = { export class Database extends pulumi.ComponentResource { name: string; instance: awsNative.rds.DbInstance; + vpc: pulumi.Output; dbSubnetGroup: aws.rds.SubnetGroup; dbSecurityGroup: aws.ec2.SecurityGroup; password: Password; - encryptedSnapshotCopy?: aws.rds.SnapshotCopy; - monitoringRole?: aws.iam.Role; kmsKeyId: pulumi.Output; + monitoringRole?: aws.iam.Role; + encryptedSnapshotCopy?: aws.rds.SnapshotCopy; constructor( name: string, @@ -62,17 +63,15 @@ export class Database extends pulumi.ComponentResource { const argsWithDefaults = Object.assign({}, defaults, args); const { + vpc, kmsKeyId, - snapshotIdentifier, enableMonitoring, + snapshotIdentifier, } = argsWithDefaults; - const vpc = pulumi.output(argsWithDefaults.vpc); - this.dbSubnetGroup = this.createSubnetGroup(vpc.isolatedSubnetIds); - this.dbSecurityGroup = this.createSecurityGroup( - vpc.vpcId, - vpc.vpc.cidrBlock, - ); + this.vpc = pulumi.output(vpc); + this.dbSubnetGroup = this.createSubnetGroup(); + this.dbSecurityGroup = this.createSecurityGroup(); this.password = new Password( `${this.name}-database-password`, @@ -98,33 +97,28 @@ export class Database extends pulumi.ComponentResource { this.registerOutputs(); } - private createSubnetGroup( - isolatedSubnetIds: awsx.ec2.Vpc['isolatedSubnetIds'], - ) { + private createSubnetGroup() { return new aws.rds.SubnetGroup( `${this.name}-subnet-group`, { - subnetIds: isolatedSubnetIds, + subnetIds: this.vpc.isolatedSubnetIds, tags: commonTags, }, { parent: this }, ); } - private createSecurityGroup( - vpcId: awsx.ec2.Vpc['vpcId'], - vpcCidrBlock: pulumi.Input, - ) { + private createSecurityGroup() { return new aws.ec2.SecurityGroup( `${this.name}-security-group`, { - vpcId, + vpcId: this.vpc.vpcId, ingress: [ { protocol: 'tcp', fromPort: 5432, toPort: 5432, - cidrBlocks: [vpcCidrBlock], + cidrBlocks: [this.vpc.vpc.cidrBlock], }, ], tags: commonTags, From f4913323f14573732c2cadc3138ce75cb95fc5ef Mon Sep 17 00:00:00 2001 From: mandryllo Date: Fri, 5 Dec 2025 18:31:58 +0100 Subject: [PATCH 43/71] Cleanup types --- src/v2/components/database/index.ts | 36 +++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/src/v2/components/database/index.ts b/src/v2/components/database/index.ts index e121cd5..7ab620c 100644 --- a/src/v2/components/database/index.ts +++ b/src/v2/components/database/index.ts @@ -6,23 +6,41 @@ import { Password } from '../../../components/password'; import { commonTags } from '../../../constants'; export namespace Database { - export type Args = { + export type Instance = { dbName?: pulumi.Input; - username?: pulumi.Input; - password?: pulumi.Input; + engineVersion?: pulumi.Input; + instanceClass?: pulumi.Input; + allowMajorVersionUpgrade?: pulumi.Input; + autoMinorVersionUpgrade?: pulumi.Input; + }; + + export type Networking = { vpc: pulumi.Input; multiAz?: pulumi.Input; - applyImmediately?: pulumi.Input; + }; + + export type Credentials = { + username?: pulumi.Input; + password?: pulumi.Input; + }; + + export type Storage = { allocatedStorage?: pulumi.Input; maxAllocatedStorage?: pulumi.Input; - instanceClass?: pulumi.Input; - allowMajorVersionUpgrade?: pulumi.Input; - autoMinorVersionUpgrade?: pulumi.Input; kmsKeyId?: pulumi.Input; - parameterGroupName?: pulumi.Input; snapshotIdentifier?: pulumi.Input; + }; + + export type Monitoring = { enableMonitoring?: pulumi.Input; - engineVersion?: pulumi.Input; + applyImmediately?: pulumi.Input; + }; + + export type ParameterGroup = { + parameterGroupName?: pulumi.Input; + }; + + export type Args = Instance & Networking & Credentials & Storage & Monitoring & ParameterGroup & { tags?: pulumi.Input<{ [key: string]: pulumi.Input; }>; From 9056cf8040be3b5fea20cdcb30f7f698ed921964 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Fri, 5 Dec 2025 18:32:30 +0100 Subject: [PATCH 44/71] Fix formatting --- src/v2/components/database/index.ts | 53 +++++++++++++++-------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/src/v2/components/database/index.ts b/src/v2/components/database/index.ts index 7ab620c..07b0d54 100644 --- a/src/v2/components/database/index.ts +++ b/src/v2/components/database/index.ts @@ -40,11 +40,16 @@ export namespace Database { parameterGroupName?: pulumi.Input; }; - export type Args = Instance & Networking & Credentials & Storage & Monitoring & ParameterGroup & { - tags?: pulumi.Input<{ - [key: string]: pulumi.Input; - }>; - }; + export type Args = Instance & + Networking & + Credentials & + Storage & + Monitoring & + ParameterGroup & { + tags?: pulumi.Input<{ + [key: string]: pulumi.Input; + }>; + }; } const defaults = { @@ -80,12 +85,8 @@ export class Database extends pulumi.ComponentResource { this.name = name; const argsWithDefaults = Object.assign({}, defaults, args); - const { - vpc, - kmsKeyId, - enableMonitoring, - snapshotIdentifier, - } = argsWithDefaults; + const { vpc, kmsKeyId, enableMonitoring, snapshotIdentifier } = + argsWithDefaults; this.vpc = pulumi.output(vpc); this.dbSubnetGroup = this.createSubnetGroup(); @@ -162,22 +163,24 @@ export class Database extends pulumi.ComponentResource { } private createMonitoringRole() { - const monitoringRole = new aws.iam.Role(`${this.name}-rds-monitoring`, { - assumeRolePolicy: { - Version: '2012-10-17', - Statement: [ - { - Action: 'sts:AssumeRole', - Effect: 'Allow', - Principal: { - Service: 'monitoring.rds.amazonaws.com', + const monitoringRole = new aws.iam.Role( + `${this.name}-rds-monitoring`, + { + assumeRolePolicy: { + Version: '2012-10-17', + Statement: [ + { + Action: 'sts:AssumeRole', + Effect: 'Allow', + Principal: { + Service: 'monitoring.rds.amazonaws.com', + }, }, - }, - ], + ], + }, }, - }, - { parent: this }, - ); + { parent: this }, + ); new aws.iam.RolePolicyAttachment( `${this.name}-rds-monitoring-role-attachment`, From 75308bce802af167f03105a023aebbff323bc9e3 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Mon, 8 Dec 2025 10:55:58 +0100 Subject: [PATCH 45/71] Cleanup --- src/v2/components/database/index.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/v2/components/database/index.ts b/src/v2/components/database/index.ts index 07b0d54..ff48e7a 100644 --- a/src/v2/components/database/index.ts +++ b/src/v2/components/database/index.ts @@ -206,7 +206,7 @@ export class Database extends pulumi.ComponentResource { }), ).dbSnapshotArn; - const encryptedSnapshotCopy = new aws.rds.SnapshotCopy( + return new aws.rds.SnapshotCopy( `${this.name}-encrypted-snapshot-copy`, { sourceDbSnapshotIdentifier, @@ -215,7 +215,6 @@ export class Database extends pulumi.ComponentResource { }, { parent: this }, ); - return encryptedSnapshotCopy; } private createDatabaseInstance(args: Database.Args) { From 3ba47f52808b285130b778bbef83adc94ba0af5e Mon Sep 17 00:00:00 2001 From: mandryllo Date: Tue, 2 Dec 2025 17:35:43 +0100 Subject: [PATCH 46/71] Create db builder component --- src/v2/components/database/builder.ts | 130 +++++++++++--------------- 1 file changed, 55 insertions(+), 75 deletions(-) diff --git a/src/v2/components/database/builder.ts b/src/v2/components/database/builder.ts index 90c03d7..bc97869 100644 --- a/src/v2/components/database/builder.ts +++ b/src/v2/components/database/builder.ts @@ -1,139 +1,119 @@ -import { Database } from '.'; import * as pulumi from '@pulumi/pulumi'; +import * as aws from '@pulumi/aws'; +import * as awsx from '@pulumi/awsx'; +import { Database } from '.'; export namespace DatabaseBuilder { - export type InstanceConfig = Database.Instance; - export type CredentialsConfig = Database.Credentials; - export type StorageConfig = Omit; export type Config = Omit< Database.Args, - | keyof Database.Instance - | keyof Database.Credentials - | keyof Database.Storage | 'vpc' | 'enableMonitoring' - | 'snapshotIdentifier' | 'parameterGroupName' + | 'customParameterGroupArgs' + | 'kmsKeyId' + | 'snapshotIdentifier' >; } export class DatabaseBuilder { - private name: string; - private config?: DatabaseBuilder.Config; - private instanceConfig?: DatabaseBuilder.InstanceConfig; - private credentialsConfig?: DatabaseBuilder.CredentialsConfig; - private storageConfig?: DatabaseBuilder.StorageConfig; - private vpc?: Database.Args['vpc']; - private enableMonitoring?: Database.Args['enableMonitoring']; - private snapshotIdentifier?: Database.Args['snapshotIdentifier']; - private kmsKeyId?: Database.Args['kmsKeyId']; - private parameterGroupName?: Database.Args['parameterGroupName']; + private _name: string; + private _config?: DatabaseBuilder.Config; + private _vpc?: Database.Args['vpc']; + private _enableMonitoring?: Database.Args['enableMonitoring']; + private _parameterGroupName?: Database.Args['parameterGroupName']; + private _customParameterGroupArgs?: Database.Args['customParameterGroupArgs']; + private _kmsKeyId?: Database.Args['kmsKeyId']; + private _snapshotIdentifier?: Database.Args['snapshotIdentifier']; constructor(name: string) { - this.name = name; - } - - public withConfiguration(config: DatabaseBuilder.Config = {}): this { - this.config = config; - - return this; + this._name = name; } - public withInstance( - instanceConfig: DatabaseBuilder.InstanceConfig = {}, + public configure( + dbName: DatabaseBuilder.Config['dbName'], + username: DatabaseBuilder.Config['username'], + config: Omit = {}, ): this { - this.instanceConfig = instanceConfig; + this._config = { + dbName, + username, + ...config, + }; return this; } - public withCredentials( - credentialsConfig: DatabaseBuilder.CredentialsConfig = {}, - ): this { - this.credentialsConfig = credentialsConfig; + public withVpc(vpc: pulumi.Input): this { + this._vpc = pulumi.output(vpc); return this; } - public withStorage(storageConfig: DatabaseBuilder.StorageConfig = {}): this { - this.storageConfig = storageConfig; - - return this; - } - - public withVpc(vpc: Database.Args['vpc']): this { - this.vpc = pulumi.output(vpc); + public withMonitoring(): this { + this._enableMonitoring = true; return this; } - public withMonitoring(): this { - this.enableMonitoring = true; + public createFromSnapshot(snapshotIdentifier: pulumi.Input): this { + this._snapshotIdentifier = snapshotIdentifier; return this; } - public withSnapshot( - snapshotIdentifier: Database.Args['snapshotIdentifier'], + public useExistingParameterGroup( + parameterGroupName: pulumi.Input, ): this { - this.snapshotIdentifier = snapshotIdentifier; + this._parameterGroupName = parameterGroupName; return this; } - public withKms(kmsKeyId: Database.Args['kmsKeyId']): this { - this.kmsKeyId = kmsKeyId; + public withCustomParameterGroup( + customParameterGroupArgs: pulumi.Input, + ): this { + this._customParameterGroupArgs = customParameterGroupArgs; return this; } - public withParameterGroup( - parameterGroupName: Database.Args['parameterGroupName'], - ): this { - this.parameterGroupName = parameterGroupName; + public useExitingKms(kmsKeyId: pulumi.Input): this { + this._kmsKeyId = kmsKeyId; return this; } public build(opts: pulumi.ComponentResourceOptions = {}): Database { - if (!this.snapshotIdentifier && !this.instanceConfig?.dbName) { + if (!this._config && !this._snapshotIdentifier) { throw new Error( - 'DbName not provided. Make sure to call DatabaseBuilder.withInstance() and set dbName.', + `Database is not configured. Make sure to call DatabaseBuilder.configure() + or create it from a snapshot with DatabaseBuilder.createFromSnapshot().`, ); } - if (!this.snapshotIdentifier && !this.credentialsConfig?.username) { + if (!this._vpc) { throw new Error( - 'Username not provided. Make sure to call DatabaseBuilder.withCredentials() and set username.', + 'VPC not provided. Make sure to call DatabaseBuilder.withVpc().', ); } - if (this.snapshotIdentifier && this.instanceConfig?.dbName) { - throw new Error(`You can't set dbName when using snapshotIdentifier.`); - } - - if (this.snapshotIdentifier && this.credentialsConfig?.username) { - throw new Error(`You can't set username when using snapshotIdentifier.`); - } - - if (!this.vpc) { + if (this._parameterGroupName && this._customParameterGroupArgs) { throw new Error( - 'VPC not provided. Make sure to call DatabaseBuilder.withVpc().', + `You can't both use existing parameter group and create a custom one. + Make sure to call either DatabaseBuilder.useExistingParameterGroup() + or DatabaseBuilder.withCustomParameterGroup(), but not both.`, ); } return new Database( - this.name, + this._name, { - ...this.config, - ...this.instanceConfig, - ...this.credentialsConfig, - ...this.storageConfig, - vpc: this.vpc, - enableMonitoring: this.enableMonitoring, - snapshotIdentifier: this.snapshotIdentifier, - kmsKeyId: this.kmsKeyId, - parameterGroupName: this.parameterGroupName, + ...this._config, + vpc: this._vpc, + enableMonitoring: this._enableMonitoring, + snapshotIdentifier: this._snapshotIdentifier, + parameterGroupName: this._parameterGroupName, + kmsKeyId: this._kmsKeyId, }, opts, ); From 6b0648f03d37ac13fc64151346dddd98c1d8c891 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Wed, 3 Dec 2025 10:46:00 +0100 Subject: [PATCH 47/71] Fix typo --- src/v2/components/database/builder.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/v2/components/database/builder.ts b/src/v2/components/database/builder.ts index bc97869..9f6dfc7 100644 --- a/src/v2/components/database/builder.ts +++ b/src/v2/components/database/builder.ts @@ -77,7 +77,7 @@ export class DatabaseBuilder { return this; } - public useExitingKms(kmsKeyId: pulumi.Input): this { + public useExistingKms(kmsKeyId: pulumi.Input): this { this._kmsKeyId = kmsKeyId; return this; From 65f030a27360f24f4dc56191e501b70ff672ad2d Mon Sep 17 00:00:00 2001 From: mandryllo Date: Fri, 5 Dec 2025 18:33:24 +0100 Subject: [PATCH 48/71] Remove custom parameter group args --- src/v2/components/database/builder.ts | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/v2/components/database/builder.ts b/src/v2/components/database/builder.ts index 9f6dfc7..be232ba 100644 --- a/src/v2/components/database/builder.ts +++ b/src/v2/components/database/builder.ts @@ -21,7 +21,6 @@ export class DatabaseBuilder { private _vpc?: Database.Args['vpc']; private _enableMonitoring?: Database.Args['enableMonitoring']; private _parameterGroupName?: Database.Args['parameterGroupName']; - private _customParameterGroupArgs?: Database.Args['customParameterGroupArgs']; private _kmsKeyId?: Database.Args['kmsKeyId']; private _snapshotIdentifier?: Database.Args['snapshotIdentifier']; @@ -69,14 +68,6 @@ export class DatabaseBuilder { return this; } - public withCustomParameterGroup( - customParameterGroupArgs: pulumi.Input, - ): this { - this._customParameterGroupArgs = customParameterGroupArgs; - - return this; - } - public useExistingKms(kmsKeyId: pulumi.Input): this { this._kmsKeyId = kmsKeyId; @@ -97,14 +88,6 @@ export class DatabaseBuilder { ); } - if (this._parameterGroupName && this._customParameterGroupArgs) { - throw new Error( - `You can't both use existing parameter group and create a custom one. - Make sure to call either DatabaseBuilder.useExistingParameterGroup() - or DatabaseBuilder.withCustomParameterGroup(), but not both.`, - ); - } - return new Database( this._name, { From bfec1fc30baa76303595f81a597f75153688c33b Mon Sep 17 00:00:00 2001 From: mandryllo Date: Fri, 5 Dec 2025 18:34:14 +0100 Subject: [PATCH 49/71] Cleanup private props --- src/v2/components/database/builder.ts | 46 +++++++++++++-------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/v2/components/database/builder.ts b/src/v2/components/database/builder.ts index be232ba..1821517 100644 --- a/src/v2/components/database/builder.ts +++ b/src/v2/components/database/builder.ts @@ -16,16 +16,16 @@ export namespace DatabaseBuilder { } export class DatabaseBuilder { - private _name: string; - private _config?: DatabaseBuilder.Config; - private _vpc?: Database.Args['vpc']; - private _enableMonitoring?: Database.Args['enableMonitoring']; - private _parameterGroupName?: Database.Args['parameterGroupName']; - private _kmsKeyId?: Database.Args['kmsKeyId']; - private _snapshotIdentifier?: Database.Args['snapshotIdentifier']; + private name: string; + private config?: DatabaseBuilder.Config; + private vpc?: Database.Args['vpc']; + private enableMonitoring?: Database.Args['enableMonitoring']; + private parameterGroupName?: Database.Args['parameterGroupName']; + private kmsKeyId?: Database.Args['kmsKeyId']; + private snapshotIdentifier?: Database.Args['snapshotIdentifier']; constructor(name: string) { - this._name = name; + this.name = name; } public configure( @@ -33,7 +33,7 @@ export class DatabaseBuilder { username: DatabaseBuilder.Config['username'], config: Omit = {}, ): this { - this._config = { + this.config = { dbName, username, ...config, @@ -43,19 +43,19 @@ export class DatabaseBuilder { } public withVpc(vpc: pulumi.Input): this { - this._vpc = pulumi.output(vpc); + this.vpc = pulumi.output(vpc); return this; } public withMonitoring(): this { - this._enableMonitoring = true; + this.enableMonitoring = true; return this; } public createFromSnapshot(snapshotIdentifier: pulumi.Input): this { - this._snapshotIdentifier = snapshotIdentifier; + this.snapshotIdentifier = snapshotIdentifier; return this; } @@ -63,40 +63,40 @@ export class DatabaseBuilder { public useExistingParameterGroup( parameterGroupName: pulumi.Input, ): this { - this._parameterGroupName = parameterGroupName; + this.parameterGroupName = parameterGroupName; return this; } public useExistingKms(kmsKeyId: pulumi.Input): this { - this._kmsKeyId = kmsKeyId; + this.kmsKeyId = kmsKeyId; return this; } public build(opts: pulumi.ComponentResourceOptions = {}): Database { - if (!this._config && !this._snapshotIdentifier) { + if (!this.config && !this.snapshotIdentifier) { throw new Error( `Database is not configured. Make sure to call DatabaseBuilder.configure() or create it from a snapshot with DatabaseBuilder.createFromSnapshot().`, ); } - if (!this._vpc) { + if (!this.vpc) { throw new Error( 'VPC not provided. Make sure to call DatabaseBuilder.withVpc().', ); } return new Database( - this._name, + this.name, { - ...this._config, - vpc: this._vpc, - enableMonitoring: this._enableMonitoring, - snapshotIdentifier: this._snapshotIdentifier, - parameterGroupName: this._parameterGroupName, - kmsKeyId: this._kmsKeyId, + ...this.config, + vpc: this.vpc, + enableMonitoring: this.enableMonitoring, + snapshotIdentifier: this.snapshotIdentifier, + parameterGroupName: this.parameterGroupName, + kmsKeyId: this.kmsKeyId, }, opts, ); From a48d054b588b1faed0c370d9baf07b1a0338e167 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Fri, 5 Dec 2025 18:34:53 +0100 Subject: [PATCH 50/71] Remove parameter group name from builder --- src/v2/components/database/builder.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/v2/components/database/builder.ts b/src/v2/components/database/builder.ts index 1821517..478847b 100644 --- a/src/v2/components/database/builder.ts +++ b/src/v2/components/database/builder.ts @@ -8,7 +8,6 @@ export namespace DatabaseBuilder { Database.Args, | 'vpc' | 'enableMonitoring' - | 'parameterGroupName' | 'customParameterGroupArgs' | 'kmsKeyId' | 'snapshotIdentifier' @@ -20,7 +19,6 @@ export class DatabaseBuilder { private config?: DatabaseBuilder.Config; private vpc?: Database.Args['vpc']; private enableMonitoring?: Database.Args['enableMonitoring']; - private parameterGroupName?: Database.Args['parameterGroupName']; private kmsKeyId?: Database.Args['kmsKeyId']; private snapshotIdentifier?: Database.Args['snapshotIdentifier']; @@ -60,14 +58,6 @@ export class DatabaseBuilder { return this; } - public useExistingParameterGroup( - parameterGroupName: pulumi.Input, - ): this { - this.parameterGroupName = parameterGroupName; - - return this; - } - public useExistingKms(kmsKeyId: pulumi.Input): this { this.kmsKeyId = kmsKeyId; @@ -95,7 +85,6 @@ export class DatabaseBuilder { vpc: this.vpc, enableMonitoring: this.enableMonitoring, snapshotIdentifier: this.snapshotIdentifier, - parameterGroupName: this.parameterGroupName, kmsKeyId: this.kmsKeyId, }, opts, From 379dc30aef83298f470252eba2d7fca262349767 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Fri, 5 Dec 2025 18:36:31 +0100 Subject: [PATCH 51/71] Cleanup naming --- src/v2/components/database/builder.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/v2/components/database/builder.ts b/src/v2/components/database/builder.ts index 478847b..9378b7a 100644 --- a/src/v2/components/database/builder.ts +++ b/src/v2/components/database/builder.ts @@ -8,7 +8,6 @@ export namespace DatabaseBuilder { Database.Args, | 'vpc' | 'enableMonitoring' - | 'customParameterGroupArgs' | 'kmsKeyId' | 'snapshotIdentifier' >; @@ -52,23 +51,22 @@ export class DatabaseBuilder { return this; } - public createFromSnapshot(snapshotIdentifier: pulumi.Input): this { + public withSnapshot(snapshotIdentifier: pulumi.Input): this { this.snapshotIdentifier = snapshotIdentifier; return this; } - public useExistingKms(kmsKeyId: pulumi.Input): this { + public withKms(kmsKeyId: pulumi.Input): this { this.kmsKeyId = kmsKeyId; return this; } public build(opts: pulumi.ComponentResourceOptions = {}): Database { - if (!this.config && !this.snapshotIdentifier) { + if (!this.config) { throw new Error( - `Database is not configured. Make sure to call DatabaseBuilder.configure() - or create it from a snapshot with DatabaseBuilder.createFromSnapshot().`, + `Database is not configured. Make sure to call DatabaseBuilder.configure().`, ); } From 14d208b18b005c7b5d09ac599cf00f26ce926bbf Mon Sep 17 00:00:00 2001 From: mandryllo Date: Fri, 5 Dec 2025 18:36:57 +0100 Subject: [PATCH 52/71] Fix formatting --- src/v2/components/database/builder.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/v2/components/database/builder.ts b/src/v2/components/database/builder.ts index 9378b7a..50b7eec 100644 --- a/src/v2/components/database/builder.ts +++ b/src/v2/components/database/builder.ts @@ -6,10 +6,7 @@ import { Database } from '.'; export namespace DatabaseBuilder { export type Config = Omit< Database.Args, - | 'vpc' - | 'enableMonitoring' - | 'kmsKeyId' - | 'snapshotIdentifier' + 'vpc' | 'enableMonitoring' | 'kmsKeyId' | 'snapshotIdentifier' >; } From c62954604389ac418fba40fb5e5858237716e275 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Mon, 8 Dec 2025 11:02:29 +0100 Subject: [PATCH 53/71] Cleanup --- src/v2/components/database/builder.ts | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/v2/components/database/builder.ts b/src/v2/components/database/builder.ts index 50b7eec..2ed2af2 100644 --- a/src/v2/components/database/builder.ts +++ b/src/v2/components/database/builder.ts @@ -22,16 +22,8 @@ export class DatabaseBuilder { this.name = name; } - public configure( - dbName: DatabaseBuilder.Config['dbName'], - username: DatabaseBuilder.Config['username'], - config: Omit = {}, - ): this { - this.config = { - dbName, - username, - ...config, - }; + public withConfiguration(config: DatabaseBuilder.Config = {}): this { + this.config = config; return this; } @@ -63,7 +55,7 @@ export class DatabaseBuilder { public build(opts: pulumi.ComponentResourceOptions = {}): Database { if (!this.config) { throw new Error( - `Database is not configured. Make sure to call DatabaseBuilder.configure().`, + `Database is not configured. Make sure to call DatabaseBuilder.withConfiguration().`, ); } @@ -73,6 +65,15 @@ export class DatabaseBuilder { ); } + if ( + this.snapshotIdentifier && + (this.config.dbName || this.config.username) + ) { + throw new Error( + `You can't set dbName or username when using snapshotIdentifier.`, + ); + } + return new Database( this.name, { From 6906eb4bab7d0187627e1362dbc905ca436167cc Mon Sep 17 00:00:00 2001 From: mandryllo Date: Wed, 10 Dec 2025 10:22:54 +0100 Subject: [PATCH 54/71] Cleanup database types --- src/v2/components/database/index.ts | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/v2/components/database/index.ts b/src/v2/components/database/index.ts index ff48e7a..76c7af0 100644 --- a/src/v2/components/database/index.ts +++ b/src/v2/components/database/index.ts @@ -9,16 +9,12 @@ export namespace Database { export type Instance = { dbName?: pulumi.Input; engineVersion?: pulumi.Input; + multiAz?: pulumi.Input; instanceClass?: pulumi.Input; allowMajorVersionUpgrade?: pulumi.Input; autoMinorVersionUpgrade?: pulumi.Input; }; - export type Networking = { - vpc: pulumi.Input; - multiAz?: pulumi.Input; - }; - export type Credentials = { username?: pulumi.Input; password?: pulumi.Input; @@ -28,24 +24,16 @@ export namespace Database { allocatedStorage?: pulumi.Input; maxAllocatedStorage?: pulumi.Input; kmsKeyId?: pulumi.Input; - snapshotIdentifier?: pulumi.Input; - }; - - export type Monitoring = { - enableMonitoring?: pulumi.Input; - applyImmediately?: pulumi.Input; - }; - - export type ParameterGroup = { - parameterGroupName?: pulumi.Input; }; export type Args = Instance & - Networking & Credentials & - Storage & - Monitoring & - ParameterGroup & { + Storage & { + vpc: pulumi.Input; + enableMonitoring?: pulumi.Input; + applyImmediately?: pulumi.Input; + snapshotIdentifier?: pulumi.Input; + parameterGroupName?: pulumi.Input; tags?: pulumi.Input<{ [key: string]: pulumi.Input; }>; From 8f5939e6de3ce1c78a3c65ceeca21e40f3b0df57 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Wed, 10 Dec 2025 14:58:51 +0100 Subject: [PATCH 55/71] Cleanup --- src/v2/components/database/builder.ts | 70 ++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 13 deletions(-) diff --git a/src/v2/components/database/builder.ts b/src/v2/components/database/builder.ts index 2ed2af2..f5003fe 100644 --- a/src/v2/components/database/builder.ts +++ b/src/v2/components/database/builder.ts @@ -4,15 +4,27 @@ import * as awsx from '@pulumi/awsx'; import { Database } from '.'; export namespace DatabaseBuilder { + export type InstanceConfig = Database.Instance; + export type CredentialsConfig = Database.Credentials; + export type StorageConfig = Omit; export type Config = Omit< Database.Args, - 'vpc' | 'enableMonitoring' | 'kmsKeyId' | 'snapshotIdentifier' + | keyof Database.Instance + | keyof Database.Credentials + | keyof Database.Storage + | 'vpc' + | 'enableMonitoring' + | 'kmsKeyId' + | 'snapshotIdentifier' >; } export class DatabaseBuilder { private name: string; private config?: DatabaseBuilder.Config; + private instanceConfig?: DatabaseBuilder.InstanceConfig; + private credentialsConfig?: DatabaseBuilder.CredentialsConfig; + private storageConfig?: DatabaseBuilder.StorageConfig; private vpc?: Database.Args['vpc']; private enableMonitoring?: Database.Args['enableMonitoring']; private kmsKeyId?: Database.Args['kmsKeyId']; @@ -28,7 +40,29 @@ export class DatabaseBuilder { return this; } - public withVpc(vpc: pulumi.Input): this { + public withInstance( + instanceConfig: DatabaseBuilder.InstanceConfig = {}, + ): this { + this.instanceConfig = instanceConfig; + + return this; + } + + public withCredentials( + credentialsConfig: DatabaseBuilder.CredentialsConfig = {}, + ): this { + this.credentialsConfig = credentialsConfig; + + return this; + } + + public withStorage(storageConfig: DatabaseBuilder.StorageConfig = {}): this { + this.storageConfig = storageConfig; + + return this; + } + + public withVpc(vpc: Database.Args['vpc']): this { this.vpc = pulumi.output(vpc); return this; @@ -40,37 +74,44 @@ export class DatabaseBuilder { return this; } - public withSnapshot(snapshotIdentifier: pulumi.Input): this { + public withSnapshot( + snapshotIdentifier: Database.Args['snapshotIdentifier'], + ): this { this.snapshotIdentifier = snapshotIdentifier; return this; } - public withKms(kmsKeyId: pulumi.Input): this { + public withKms(kmsKeyId: Database.Args['kmsKeyId']): this { this.kmsKeyId = kmsKeyId; return this; } public build(opts: pulumi.ComponentResourceOptions = {}): Database { - if (!this.config) { + if (!this.snapshotIdentifier && !this.instanceConfig?.dbName) { throw new Error( - `Database is not configured. Make sure to call DatabaseBuilder.withConfiguration().`, + 'DbName not provided. Make sure to call DatabaseBuilder.withInstance() and set dbName.', ); } - if (!this.vpc) { + if (!this.snapshotIdentifier && !this.credentialsConfig?.username) { throw new Error( - 'VPC not provided. Make sure to call DatabaseBuilder.withVpc().', + 'Username not provided. Make sure to call DatabaseBuilder.withCredentials() and set username.', ); } - if ( - this.snapshotIdentifier && - (this.config.dbName || this.config.username) - ) { + if (this.snapshotIdentifier && !this.instanceConfig?.dbName) { + throw new Error(`You can't set dbName when using snapshotIdentifier.`); + } + + if (this.snapshotIdentifier && !this.credentialsConfig?.username) { + throw new Error(`You can't set username when using snapshotIdentifier.`); + } + + if (!this.vpc) { throw new Error( - `You can't set dbName or username when using snapshotIdentifier.`, + 'VPC not provided. Make sure to call DatabaseBuilder.withVpc().', ); } @@ -78,6 +119,9 @@ export class DatabaseBuilder { this.name, { ...this.config, + ...this.instanceConfig, + ...this.credentialsConfig, + ...this.storageConfig, vpc: this.vpc, enableMonitoring: this.enableMonitoring, snapshotIdentifier: this.snapshotIdentifier, From 80804befada01466e86965039e4a976562a18289 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Wed, 10 Dec 2025 15:00:28 +0100 Subject: [PATCH 56/71] Revert allocatedStorage type to number --- src/v2/components/database/index.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/v2/components/database/index.ts b/src/v2/components/database/index.ts index 76c7af0..388740d 100644 --- a/src/v2/components/database/index.ts +++ b/src/v2/components/database/index.ts @@ -21,7 +21,7 @@ export namespace Database { }; export type Storage = { - allocatedStorage?: pulumi.Input; + allocatedStorage?: pulumi.Input; maxAllocatedStorage?: pulumi.Input; kmsKeyId?: pulumi.Input; }; @@ -43,7 +43,7 @@ export namespace Database { const defaults = { multiAz: false, applyImmediately: false, - allocatedStorage: '20', + allocatedStorage: 20, maxAllocatedStorage: 100, instanceClass: 'db.t4g.micro', enableMonitoring: false, @@ -228,7 +228,7 @@ export class Database extends pulumi.ComponentResource { masterUserPassword: this.password.value, dbSubnetGroupName: this.dbSubnetGroup.name, vpcSecurityGroups: [this.dbSecurityGroup.id], - allocatedStorage: args.allocatedStorage, + allocatedStorage: args.allocatedStorage?.toString(), maxAllocatedStorage: args.maxAllocatedStorage, multiAz: args.multiAz, applyImmediately: args.applyImmediately, From 98fb66b97463e3795718b4e43737f5eae7c13989 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Wed, 10 Dec 2025 15:06:33 +0100 Subject: [PATCH 57/71] Remove withKms method from builder --- src/v2/components/database/builder.ts | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/v2/components/database/builder.ts b/src/v2/components/database/builder.ts index f5003fe..f1c8641 100644 --- a/src/v2/components/database/builder.ts +++ b/src/v2/components/database/builder.ts @@ -6,7 +6,7 @@ import { Database } from '.'; export namespace DatabaseBuilder { export type InstanceConfig = Database.Instance; export type CredentialsConfig = Database.Credentials; - export type StorageConfig = Omit; + export type StorageConfig = Database.Storage; export type Config = Omit< Database.Args, | keyof Database.Instance @@ -14,7 +14,6 @@ export namespace DatabaseBuilder { | keyof Database.Storage | 'vpc' | 'enableMonitoring' - | 'kmsKeyId' | 'snapshotIdentifier' >; } @@ -27,7 +26,6 @@ export class DatabaseBuilder { private storageConfig?: DatabaseBuilder.StorageConfig; private vpc?: Database.Args['vpc']; private enableMonitoring?: Database.Args['enableMonitoring']; - private kmsKeyId?: Database.Args['kmsKeyId']; private snapshotIdentifier?: Database.Args['snapshotIdentifier']; constructor(name: string) { @@ -82,12 +80,6 @@ export class DatabaseBuilder { return this; } - public withKms(kmsKeyId: Database.Args['kmsKeyId']): this { - this.kmsKeyId = kmsKeyId; - - return this; - } - public build(opts: pulumi.ComponentResourceOptions = {}): Database { if (!this.snapshotIdentifier && !this.instanceConfig?.dbName) { throw new Error( @@ -125,7 +117,6 @@ export class DatabaseBuilder { vpc: this.vpc, enableMonitoring: this.enableMonitoring, snapshotIdentifier: this.snapshotIdentifier, - kmsKeyId: this.kmsKeyId, }, opts, ); From 5cfb8f96818ccffadb5401589230235f5c0601d3 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Wed, 10 Dec 2025 16:55:39 +0100 Subject: [PATCH 58/71] fix tags --- src/v2/components/database/index.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/v2/components/database/index.ts b/src/v2/components/database/index.ts index 388740d..93549d8 100644 --- a/src/v2/components/database/index.ts +++ b/src/v2/components/database/index.ts @@ -245,11 +245,13 @@ export class Database extends pulumi.ComponentResource { dbSnapshotIdentifier: this.encryptedSnapshotCopy?.targetDbSnapshotIdentifier, ...monitoringOptions, - tags: [ - ...Object.entries({ ...commonTags, ...args.tags }).map( - ([key, value]) => ({ key, value }), - ), - ], + tags: pulumi + .output(args.tags) + .apply(tags => [ + ...Object.entries({ ...commonTags, ...tags }).map( + ([key, value]) => ({ key, value }), + ), + ]), }, { parent: this, dependsOn: [this.password] }, ); From 823598e45552d46df4ebd2c84c626d3868042014 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Wed, 10 Dec 2025 16:55:51 +0100 Subject: [PATCH 59/71] Fix snapshot id --- src/v2/components/database/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/v2/components/database/index.ts b/src/v2/components/database/index.ts index 93549d8..695d12a 100644 --- a/src/v2/components/database/index.ts +++ b/src/v2/components/database/index.ts @@ -184,7 +184,7 @@ export class Database extends pulumi.ComponentResource { } private createEncryptedSnapshotCopy( - snapshotIdentifier: pulumi.Input, + snapshotIdentifier: Database.Args['snapshotIdentifier'], ) { const sourceDbSnapshotIdentifier = pulumi .output(snapshotIdentifier) @@ -198,7 +198,7 @@ export class Database extends pulumi.ComponentResource { `${this.name}-encrypted-snapshot-copy`, { sourceDbSnapshotIdentifier, - targetDbSnapshotIdentifier: `${snapshotIdentifier}-encrypted-copy`, + targetDbSnapshotIdentifier: pulumi.interpolate`${snapshotIdentifier}-encrypted-copy`, kmsKeyId: this.kmsKeyId, }, { parent: this }, From 9d7d045ea1c7fb488f3ba11ec61e3a12fe22f356 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Thu, 11 Dec 2025 13:09:14 +0100 Subject: [PATCH 60/71] Fix wrong condition --- src/v2/components/database/builder.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/v2/components/database/builder.ts b/src/v2/components/database/builder.ts index f1c8641..a9fda6d 100644 --- a/src/v2/components/database/builder.ts +++ b/src/v2/components/database/builder.ts @@ -93,11 +93,11 @@ export class DatabaseBuilder { ); } - if (this.snapshotIdentifier && !this.instanceConfig?.dbName) { + if (this.snapshotIdentifier && this.instanceConfig?.dbName) { throw new Error(`You can't set dbName when using snapshotIdentifier.`); } - if (this.snapshotIdentifier && !this.credentialsConfig?.username) { + if (this.snapshotIdentifier && this.credentialsConfig?.username) { throw new Error(`You can't set username when using snapshotIdentifier.`); } From 1937146def5a4a7ab51b3a4c1d9c8305c2f2f25e Mon Sep 17 00:00:00 2001 From: mandryllo Date: Tue, 16 Dec 2025 11:41:06 +0100 Subject: [PATCH 61/71] Update database builder --- src/v2/components/database/builder.ts | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/v2/components/database/builder.ts b/src/v2/components/database/builder.ts index a9fda6d..566088c 100644 --- a/src/v2/components/database/builder.ts +++ b/src/v2/components/database/builder.ts @@ -6,7 +6,7 @@ import { Database } from '.'; export namespace DatabaseBuilder { export type InstanceConfig = Database.Instance; export type CredentialsConfig = Database.Credentials; - export type StorageConfig = Database.Storage; + export type StorageConfig = Omit; export type Config = Omit< Database.Args, | keyof Database.Instance @@ -15,6 +15,7 @@ export namespace DatabaseBuilder { | 'vpc' | 'enableMonitoring' | 'snapshotIdentifier' + | 'parameterGroupName' >; } @@ -27,6 +28,8 @@ export class DatabaseBuilder { private vpc?: Database.Args['vpc']; private enableMonitoring?: Database.Args['enableMonitoring']; private snapshotIdentifier?: Database.Args['snapshotIdentifier']; + private kmsKeyId?: Database.Args['kmsKeyId']; + private parameterGroupName?: Database.Args['parameterGroupName']; constructor(name: string) { this.name = name; @@ -80,6 +83,20 @@ export class DatabaseBuilder { return this; } + public withKms(kmsKeyId: Database.Args['kmsKeyId']): this { + this.kmsKeyId = kmsKeyId; + + return this; + } + + public withParameterGroup( + parameterGroupName: Database.Args['parameterGroupName'], + ): this { + this.parameterGroupName = parameterGroupName; + + return this; + } + public build(opts: pulumi.ComponentResourceOptions = {}): Database { if (!this.snapshotIdentifier && !this.instanceConfig?.dbName) { throw new Error( @@ -117,6 +134,8 @@ export class DatabaseBuilder { vpc: this.vpc, enableMonitoring: this.enableMonitoring, snapshotIdentifier: this.snapshotIdentifier, + kmsKeyId: this.kmsKeyId, + parameterGroupName: this.parameterGroupName, }, opts, ); From 311d79278385972ac3ab6fad6729f07780f53826 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Tue, 16 Dec 2025 11:41:47 +0100 Subject: [PATCH 62/71] Cleanup --- src/v2/components/database/builder.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/v2/components/database/builder.ts b/src/v2/components/database/builder.ts index 566088c..90c03d7 100644 --- a/src/v2/components/database/builder.ts +++ b/src/v2/components/database/builder.ts @@ -1,7 +1,5 @@ -import * as pulumi from '@pulumi/pulumi'; -import * as aws from '@pulumi/aws'; -import * as awsx from '@pulumi/awsx'; import { Database } from '.'; +import * as pulumi from '@pulumi/pulumi'; export namespace DatabaseBuilder { export type InstanceConfig = Database.Instance; From b43859c4551b62c56c3431fc8871858656ab2ae2 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Tue, 16 Dec 2025 13:26:15 +0100 Subject: [PATCH 63/71] Move applyImmediately to instance config --- src/v2/components/database/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/v2/components/database/index.ts b/src/v2/components/database/index.ts index 695d12a..461f922 100644 --- a/src/v2/components/database/index.ts +++ b/src/v2/components/database/index.ts @@ -13,6 +13,7 @@ export namespace Database { instanceClass?: pulumi.Input; allowMajorVersionUpgrade?: pulumi.Input; autoMinorVersionUpgrade?: pulumi.Input; + applyImmediately?: pulumi.Input; }; export type Credentials = { @@ -31,7 +32,6 @@ export namespace Database { Storage & { vpc: pulumi.Input; enableMonitoring?: pulumi.Input; - applyImmediately?: pulumi.Input; snapshotIdentifier?: pulumi.Input; parameterGroupName?: pulumi.Input; tags?: pulumi.Input<{ From 62b03d9131efb0a0fb7f4eafb9a4e87d58b94b1c Mon Sep 17 00:00:00 2001 From: mandryllo Date: Tue, 16 Dec 2025 13:28:43 +0100 Subject: [PATCH 64/71] Update builder methods --- src/v2/components/database/builder.ts | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/src/v2/components/database/builder.ts b/src/v2/components/database/builder.ts index 90c03d7..7762734 100644 --- a/src/v2/components/database/builder.ts +++ b/src/v2/components/database/builder.ts @@ -5,21 +5,10 @@ export namespace DatabaseBuilder { export type InstanceConfig = Database.Instance; export type CredentialsConfig = Database.Credentials; export type StorageConfig = Omit; - export type Config = Omit< - Database.Args, - | keyof Database.Instance - | keyof Database.Credentials - | keyof Database.Storage - | 'vpc' - | 'enableMonitoring' - | 'snapshotIdentifier' - | 'parameterGroupName' - >; } export class DatabaseBuilder { private name: string; - private config?: DatabaseBuilder.Config; private instanceConfig?: DatabaseBuilder.InstanceConfig; private credentialsConfig?: DatabaseBuilder.CredentialsConfig; private storageConfig?: DatabaseBuilder.StorageConfig; @@ -28,17 +17,12 @@ export class DatabaseBuilder { private snapshotIdentifier?: Database.Args['snapshotIdentifier']; private kmsKeyId?: Database.Args['kmsKeyId']; private parameterGroupName?: Database.Args['parameterGroupName']; + private tags?: Database.Args['tags']; constructor(name: string) { this.name = name; } - public withConfiguration(config: DatabaseBuilder.Config = {}): this { - this.config = config; - - return this; - } - public withInstance( instanceConfig: DatabaseBuilder.InstanceConfig = {}, ): this { @@ -95,6 +79,12 @@ export class DatabaseBuilder { return this; } + public withTags(tags: Database.Args['tags']): this { + this.tags = tags; + + return this; + } + public build(opts: pulumi.ComponentResourceOptions = {}): Database { if (!this.snapshotIdentifier && !this.instanceConfig?.dbName) { throw new Error( @@ -125,7 +115,6 @@ export class DatabaseBuilder { return new Database( this.name, { - ...this.config, ...this.instanceConfig, ...this.credentialsConfig, ...this.storageConfig, @@ -134,6 +123,7 @@ export class DatabaseBuilder { snapshotIdentifier: this.snapshotIdentifier, kmsKeyId: this.kmsKeyId, parameterGroupName: this.parameterGroupName, + tags: this.tags, }, opts, ); From e8a017b8bae5762b38588b276139dd4abcb6b844 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Tue, 16 Dec 2025 13:33:46 +0100 Subject: [PATCH 65/71] Update tests --- tests/build/index.tst.ts | 13 +++++++------ tests/database/infrastructure/index.ts | 4 +--- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/tests/build/index.tst.ts b/tests/build/index.tst.ts index fa3a385..395deda 100644 --- a/tests/build/index.tst.ts +++ b/tests/build/index.tst.ts @@ -291,12 +291,6 @@ describe('Build output', () => { expect(builder.build).type.toBeCallableWith(); }); - it('should have withConfiguration method', () => { - expect(builder.withConfiguration).type.toBeCallableWith({ - applyImmediately: true, - }); - }); - it('should have withInstance method', () => { expect(builder.withInstance).type.toBeCallableWith({ dbName: 'dbName', @@ -340,6 +334,13 @@ describe('Build output', () => { 'parameter-group-name', ); }); + + it('should have withTags method', () => { + expect(builder.withTags).type.toBeCallableWith({ + Project: 'db-test', + Environment: 'dev', + }); + }); }); }); }); diff --git a/tests/database/infrastructure/index.ts b/tests/database/infrastructure/index.ts index 6a584b2..2a30416 100644 --- a/tests/database/infrastructure/index.ts +++ b/tests/database/infrastructure/index.ts @@ -12,9 +12,7 @@ const defaultDb = new DatabaseBuilder(`${config.appName}-default`) username: config.dbUsername, password: config.dbPassword, }) - .withConfiguration({ - tags: config.tags, - }) + .withTags(config.tags) .withVpc(vpc.vpc) .build(); From f9fdc027719f6b14b2297e399068ed048a93d48a Mon Sep 17 00:00:00 2001 From: mandryllo Date: Tue, 16 Dec 2025 13:54:15 +0100 Subject: [PATCH 66/71] Move kms key from storage type --- src/v2/components/database/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/v2/components/database/index.ts b/src/v2/components/database/index.ts index 461f922..bb97184 100644 --- a/src/v2/components/database/index.ts +++ b/src/v2/components/database/index.ts @@ -24,7 +24,6 @@ export namespace Database { export type Storage = { allocatedStorage?: pulumi.Input; maxAllocatedStorage?: pulumi.Input; - kmsKeyId?: pulumi.Input; }; export type Args = Instance & @@ -34,6 +33,7 @@ export namespace Database { enableMonitoring?: pulumi.Input; snapshotIdentifier?: pulumi.Input; parameterGroupName?: pulumi.Input; + kmsKeyId?: pulumi.Input; tags?: pulumi.Input<{ [key: string]: pulumi.Input; }>; From 6467dff8a9b05eae9b4c5574a81b70ff71795e0d Mon Sep 17 00:00:00 2001 From: mandryllo Date: Tue, 16 Dec 2025 13:55:53 +0100 Subject: [PATCH 67/71] Update builder --- src/v2/components/database/builder.ts | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/src/v2/components/database/builder.ts b/src/v2/components/database/builder.ts index 7762734..9cd343c 100644 --- a/src/v2/components/database/builder.ts +++ b/src/v2/components/database/builder.ts @@ -1,17 +1,11 @@ import { Database } from '.'; import * as pulumi from '@pulumi/pulumi'; -export namespace DatabaseBuilder { - export type InstanceConfig = Database.Instance; - export type CredentialsConfig = Database.Credentials; - export type StorageConfig = Omit; -} - export class DatabaseBuilder { private name: string; - private instanceConfig?: DatabaseBuilder.InstanceConfig; - private credentialsConfig?: DatabaseBuilder.CredentialsConfig; - private storageConfig?: DatabaseBuilder.StorageConfig; + private instanceConfig?: Database.Instance; + private credentialsConfig?: Database.Credentials; + private storageConfig?: Database.Storage; private vpc?: Database.Args['vpc']; private enableMonitoring?: Database.Args['enableMonitoring']; private snapshotIdentifier?: Database.Args['snapshotIdentifier']; @@ -23,23 +17,19 @@ export class DatabaseBuilder { this.name = name; } - public withInstance( - instanceConfig: DatabaseBuilder.InstanceConfig = {}, - ): this { + public withInstance(instanceConfig: Database.Instance = {}): this { this.instanceConfig = instanceConfig; return this; } - public withCredentials( - credentialsConfig: DatabaseBuilder.CredentialsConfig = {}, - ): this { + public withCredentials(credentialsConfig: Database.Credentials = {}): this { this.credentialsConfig = credentialsConfig; return this; } - public withStorage(storageConfig: DatabaseBuilder.StorageConfig = {}): this { + public withStorage(storageConfig: Database.Storage = {}): this { this.storageConfig = storageConfig; return this; From 3375e860ee0e6b246fe8ff33caa4a3cf0200119f Mon Sep 17 00:00:00 2001 From: mandryllo Date: Tue, 16 Dec 2025 17:25:09 +0100 Subject: [PATCH 68/71] Cleanup default tests --- tests/database/default-db.test.ts | 5 ----- tests/database/infrastructure/config.ts | 8 -------- tests/database/infrastructure/index.ts | 2 -- tests/database/test-context.ts | 6 ------ 4 files changed, 21 deletions(-) diff --git a/tests/database/default-db.test.ts b/tests/database/default-db.test.ts index c15e86f..eaac25f 100644 --- a/tests/database/default-db.test.ts +++ b/tests/database/default-db.test.ts @@ -42,11 +42,6 @@ export function testDefaultDb(ctx: DatabaseTestContext) { ctx.config.dbUsername, 'Database instance should have correct master username', ); - assert.strictEqual( - instance.masterUserPassword, - ctx.config.dbPassword, - 'Database instance should have correct master user password', - ); assert.strictEqual( instance.multiAz, diff --git a/tests/database/infrastructure/config.ts b/tests/database/infrastructure/config.ts index ef9372f..52dca24 100644 --- a/tests/database/infrastructure/config.ts +++ b/tests/database/infrastructure/config.ts @@ -1,11 +1,3 @@ -import * as pulumi from '@pulumi/pulumi'; - export const appName = 'db-test'; -export const stackName = pulumi.getStack(); -export const tags = { - Project: appName, - Environment: stackName, -}; export const dbName = 'dbname'; export const dbUsername = 'dbusername'; -export const dbPassword = 'dbpassword'; diff --git a/tests/database/infrastructure/index.ts b/tests/database/infrastructure/index.ts index 2a30416..a35eb48 100644 --- a/tests/database/infrastructure/index.ts +++ b/tests/database/infrastructure/index.ts @@ -10,9 +10,7 @@ const defaultDb = new DatabaseBuilder(`${config.appName}-default`) }) .withCredentials({ username: config.dbUsername, - password: config.dbPassword, }) - .withTags(config.tags) .withVpc(vpc.vpc) .build(); diff --git a/tests/database/test-context.ts b/tests/database/test-context.ts index 366d4f6..d9eccd8 100644 --- a/tests/database/test-context.ts +++ b/tests/database/test-context.ts @@ -9,14 +9,8 @@ interface ConfigContext { interface DatabaseTestConfig { appName: string; - stackName: string; - tags: { - Project: string; - Environment: string; - }; dbName: string; dbUsername: string; - dbPassword: string; } interface PulumiProgramContext { From dce01039d1097ec478e4e9608b31a74139143c8f Mon Sep 17 00:00:00 2001 From: mandryllo Date: Tue, 16 Dec 2025 17:48:54 +0100 Subject: [PATCH 69/71] Fix allocated storage type --- tests/database/default-db.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/database/default-db.test.ts b/tests/database/default-db.test.ts index eaac25f..513e617 100644 --- a/tests/database/default-db.test.ts +++ b/tests/database/default-db.test.ts @@ -55,7 +55,7 @@ export function testDefaultDb(ctx: DatabaseTestContext) { ); assert.strictEqual( instance.allocatedStorage, - '20', + 20, 'Allocated storage argument should be set to 20', ); assert.strictEqual( From a783195641a7ae73b16ff548249518da7b75de6b Mon Sep 17 00:00:00 2001 From: mandryllo Date: Tue, 16 Dec 2025 18:26:44 +0100 Subject: [PATCH 70/71] Revert "Fix allocated storage type" This reverts commit f361e34d4707e7876697c241e3a460598d5c0e74. --- tests/database/default-db.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/database/default-db.test.ts b/tests/database/default-db.test.ts index 513e617..eaac25f 100644 --- a/tests/database/default-db.test.ts +++ b/tests/database/default-db.test.ts @@ -55,7 +55,7 @@ export function testDefaultDb(ctx: DatabaseTestContext) { ); assert.strictEqual( instance.allocatedStorage, - 20, + '20', 'Allocated storage argument should be set to 20', ); assert.strictEqual( From 41783a5d83b9ffaad04af90d127297679bcad5d7 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Fri, 19 Dec 2025 14:46:31 +0100 Subject: [PATCH 71/71] Update after merge --- tests/database/index.test.ts | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/tests/database/index.test.ts b/tests/database/index.test.ts index 549b88e..3042ba1 100644 --- a/tests/database/index.test.ts +++ b/tests/database/index.test.ts @@ -7,6 +7,7 @@ import { EC2Client } from '@aws-sdk/client-ec2'; import { InlineProgramArgs } from '@pulumi/pulumi/automation'; import { KMSClient } from '@aws-sdk/client-kms'; import { RDSClient } from '@aws-sdk/client-rds'; +import { requireEnv } from '../util'; import { testDefaultDb } from './default-db.test'; const programArgs: InlineProgramArgs = { @@ -15,22 +16,18 @@ const programArgs: InlineProgramArgs = { program: () => import('./infrastructure'), }; -describe('Database component deployment', () => { - const region = process.env.AWS_REGION; - if (!region) { - throw new Error('AWS_REGION environment variable is required'); - } - - const ctx: DatabaseTestContext = { - outputs: {}, - config, - clients: { - rds: new RDSClient({ region }), - ec2: new EC2Client({ region }), - kms: new KMSClient({ region }), - }, - }; +const region = requireEnv('AWS_REGION'); +const ctx: DatabaseTestContext = { + outputs: {}, + config, + clients: { + rds: new RDSClient({ region }), + ec2: new EC2Client({ region }), + kms: new KMSClient({ region }), + }, +}; +describe('Database component deployment', () => { before(async () => { ctx.outputs = await automation.deploy(programArgs); });