@go-to-k/cdkd 0.37.0 → 0.39.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -16532,6 +16532,52 @@ var SecretsManagerSecretProvider = class {
16532
16532
  }
16533
16533
  return password;
16534
16534
  }
16535
+ /**
16536
+ * Read the AWS-current secret configuration in CFn-property shape.
16537
+ *
16538
+ * Issues `DescribeSecret` and surfaces `Name`, `Description`, `KmsKeyId`,
16539
+ * and `ReplicaRegions` (re-shaping `ReplicationStatus[]` to CFn's
16540
+ * `[{Region, KmsKeyId}]`).
16541
+ *
16542
+ * Intentionally omitted:
16543
+ * - `SecretString` / `GenerateSecretString`: `DescribeSecret` does not
16544
+ * return the secret value (that's `GetSecretValue`, which we never
16545
+ * call to avoid surfacing plaintext through drift). Cdkd state holds
16546
+ * the user-supplied string verbatim; comparing against AWS would
16547
+ * require pulling the value, so this is deliberately deferred.
16548
+ * - `Tags`: `DescribeSecret` returns Tags, but the auto-injected
16549
+ * `aws:cdk:path` tag-shape question is out of scope here.
16550
+ *
16551
+ * Returns `undefined` when the secret is gone (`ResourceNotFoundException`).
16552
+ */
16553
+ async readCurrentState(physicalId, _logicalId, _resourceType) {
16554
+ try {
16555
+ const resp = await this.smClient.send(new DescribeSecretCommand({ SecretId: physicalId }));
16556
+ const result = {};
16557
+ if (resp.Name !== void 0)
16558
+ result["Name"] = resp.Name;
16559
+ if (resp.Description !== void 0 && resp.Description !== "") {
16560
+ result["Description"] = resp.Description;
16561
+ }
16562
+ if (resp.KmsKeyId !== void 0)
16563
+ result["KmsKeyId"] = resp.KmsKeyId;
16564
+ if (resp.ReplicationStatus && resp.ReplicationStatus.length > 0) {
16565
+ result["ReplicaRegions"] = resp.ReplicationStatus.map((r) => {
16566
+ const out = {};
16567
+ if (r.Region)
16568
+ out["Region"] = r.Region;
16569
+ if (r.KmsKeyId)
16570
+ out["KmsKeyId"] = r.KmsKeyId;
16571
+ return out;
16572
+ });
16573
+ }
16574
+ return result;
16575
+ } catch (err) {
16576
+ if (err instanceof ResourceNotFoundException8)
16577
+ return void 0;
16578
+ throw err;
16579
+ }
16580
+ }
16535
16581
  /**
16536
16582
  * Adopt an existing Secrets Manager secret into cdkd state.
16537
16583
  *
@@ -16802,6 +16848,74 @@ var SSMParameterProvider = class {
16802
16848
  );
16803
16849
  }
16804
16850
  }
16851
+ /**
16852
+ * Read the AWS-current SSM parameter configuration in CFn-property shape.
16853
+ *
16854
+ * Issues `GetParameter` (with `WithDecryption: false` so SecureString
16855
+ * values stay encrypted on the wire) for `Type` / `Value` / `DataType`,
16856
+ * then `DescribeParameters` filtered on the parameter name to fetch
16857
+ * metadata (`Description`, `AllowedPattern`, `Tier`) that `GetParameter`
16858
+ * does not return.
16859
+ *
16860
+ * `Name` is set to the physical id. `Tags` and `Policies` are intentionally
16861
+ * out of scope (`Tags` requires a separate `ListTagsForResource` round-trip
16862
+ * and the auto-injected `aws:cdk:path` tag-shape question is unresolved;
16863
+ * `Policies` is returned by `DescribeParameters.Policies` as a structured
16864
+ * array but cdkd state holds the raw JSON string the user typed — comparing
16865
+ * the two accurately needs more work).
16866
+ *
16867
+ * **Note**: For `SecureString` parameters, AWS returns the encrypted
16868
+ * blob in `Value` (we pass `WithDecryption: false`). cdkd state usually
16869
+ * holds the plaintext value the user typed in their CDK app, so a
16870
+ * SecureString parameter will surface as `Value` drift on every run.
16871
+ * That's the correct conservative behavior — surfacing the discrepancy
16872
+ * is more useful than silently masking it.
16873
+ *
16874
+ * Returns `undefined` when the parameter is gone (`ParameterNotFound`).
16875
+ */
16876
+ async readCurrentState(physicalId, _logicalId, _resourceType) {
16877
+ let getResp;
16878
+ try {
16879
+ getResp = await this.ssmClient.send(
16880
+ new GetParameterCommand3({ Name: physicalId, WithDecryption: false })
16881
+ );
16882
+ } catch (err) {
16883
+ if (err instanceof ParameterNotFound)
16884
+ return void 0;
16885
+ throw err;
16886
+ }
16887
+ const param = getResp.Parameter;
16888
+ if (!param)
16889
+ return void 0;
16890
+ const result = { Name: physicalId };
16891
+ if (param.Type !== void 0)
16892
+ result["Type"] = param.Type;
16893
+ if (param.Value !== void 0)
16894
+ result["Value"] = param.Value;
16895
+ if (param.DataType !== void 0)
16896
+ result["DataType"] = param.DataType;
16897
+ try {
16898
+ const desc = await this.ssmClient.send(
16899
+ new DescribeParametersCommand({
16900
+ ParameterFilters: [{ Key: "Name", Values: [physicalId] }]
16901
+ })
16902
+ );
16903
+ const meta = desc.Parameters?.[0];
16904
+ if (meta) {
16905
+ if (meta.Description !== void 0 && meta.Description !== "") {
16906
+ result["Description"] = meta.Description;
16907
+ }
16908
+ if (meta.AllowedPattern !== void 0 && meta.AllowedPattern !== "") {
16909
+ result["AllowedPattern"] = meta.AllowedPattern;
16910
+ }
16911
+ if (meta.Tier !== void 0) {
16912
+ result["Tier"] = meta.Tier;
16913
+ }
16914
+ }
16915
+ } catch {
16916
+ }
16917
+ return result;
16918
+ }
16805
16919
  /**
16806
16920
  * Adopt an existing SSM parameter into cdkd state.
16807
16921
  *
@@ -17132,6 +17246,78 @@ var EventBridgeRuleProvider = class {
17132
17246
  }
17133
17247
  throw new Error(`Unsupported attribute: ${attributeName} for AWS::Events::Rule`);
17134
17248
  }
17249
+ /**
17250
+ * Read the AWS-current EventBridge rule configuration in CFn-property shape.
17251
+ *
17252
+ * Issues `DescribeRule` for the rule's main config, then a separate
17253
+ * `ListTargetsByRule` for `Targets`.
17254
+ *
17255
+ * Surfaced keys (when present): `Name`, `Description`, `EventBusName`,
17256
+ * `EventPattern` (parsed from JSON string back to object — cdkd state holds
17257
+ * it as the user typed it, typically an object), `ScheduleExpression`,
17258
+ * `State`, `RoleArn`, `Targets` (CFn shape `[{Id, Arn, ...}]`).
17259
+ *
17260
+ * `Tags` is omitted (separate `ListTagsForResource` round-trip; auto-injected
17261
+ * `aws:cdk:path` tag-shape question is out of scope here).
17262
+ *
17263
+ * Returns `undefined` when the rule is gone (`ResourceNotFoundException`).
17264
+ */
17265
+ async readCurrentState(physicalId, _logicalId, _resourceType) {
17266
+ const ruleName = this.extractRuleNameFromArn(physicalId);
17267
+ const eventBusName = this.extractBusNameFromArn(physicalId);
17268
+ let resp;
17269
+ try {
17270
+ resp = await this.eventBridgeClient.send(
17271
+ new DescribeRuleCommand({
17272
+ Name: ruleName,
17273
+ ...eventBusName && eventBusName !== "default" ? { EventBusName: eventBusName } : {}
17274
+ })
17275
+ );
17276
+ } catch (err) {
17277
+ if (err instanceof ResourceNotFoundException9)
17278
+ return void 0;
17279
+ throw err;
17280
+ }
17281
+ const result = {};
17282
+ if (resp.Name !== void 0)
17283
+ result["Name"] = resp.Name;
17284
+ if (resp.Description !== void 0 && resp.Description !== "") {
17285
+ result["Description"] = resp.Description;
17286
+ }
17287
+ if (resp.EventBusName !== void 0 && resp.EventBusName !== "default") {
17288
+ result["EventBusName"] = resp.EventBusName;
17289
+ }
17290
+ if (resp.EventPattern !== void 0) {
17291
+ try {
17292
+ result["EventPattern"] = JSON.parse(resp.EventPattern);
17293
+ } catch {
17294
+ result["EventPattern"] = resp.EventPattern;
17295
+ }
17296
+ }
17297
+ if (resp.ScheduleExpression !== void 0) {
17298
+ result["ScheduleExpression"] = resp.ScheduleExpression;
17299
+ }
17300
+ if (resp.State !== void 0)
17301
+ result["State"] = resp.State;
17302
+ if (resp.RoleArn !== void 0)
17303
+ result["RoleArn"] = resp.RoleArn;
17304
+ try {
17305
+ const targetsResp = await this.eventBridgeClient.send(
17306
+ new ListTargetsByRuleCommand({
17307
+ Rule: ruleName,
17308
+ ...eventBusName && eventBusName !== "default" ? { EventBusName: eventBusName } : {}
17309
+ })
17310
+ );
17311
+ if (targetsResp.Targets && targetsResp.Targets.length > 0) {
17312
+ result["Targets"] = targetsResp.Targets;
17313
+ }
17314
+ } catch (err) {
17315
+ if (!(err instanceof ResourceNotFoundException9)) {
17316
+ throw err;
17317
+ }
17318
+ }
17319
+ return result;
17320
+ }
17135
17321
  /**
17136
17322
  * Adopt an existing EventBridge rule into cdkd state.
17137
17323
  *
@@ -17224,6 +17410,22 @@ var EventBridgeRuleProvider = class {
17224
17410
  const parts = arn.split("/");
17225
17411
  return parts[parts.length - 1] ?? arn;
17226
17412
  }
17413
+ /**
17414
+ * Extract the event bus name from a rule ARN.
17415
+ *
17416
+ * ARN format: `arn:aws:events:region:account:rule/rule-name` (default bus, returns 'default')
17417
+ * or `arn:aws:events:region:account:rule/bus-name/rule-name` (custom bus).
17418
+ *
17419
+ * Returns `undefined` when the input is not an ARN (we can't tell which bus).
17420
+ */
17421
+ extractBusNameFromArn(arn) {
17422
+ if (!arn.startsWith("arn:"))
17423
+ return void 0;
17424
+ const parts = arn.split("/");
17425
+ if (parts.length === 3)
17426
+ return parts[1];
17427
+ return "default";
17428
+ }
17227
17429
  };
17228
17430
 
17229
17431
  // src/provisioning/providers/eventbridge-bus-provider.ts
@@ -17475,6 +17677,53 @@ var EventBridgeBusProvider = class {
17475
17677
  );
17476
17678
  }
17477
17679
  }
17680
+ /**
17681
+ * Read the AWS-current EventBus configuration in CFn-property shape.
17682
+ *
17683
+ * Issues `DescribeEventBus` and surfaces `Name`, `Description`,
17684
+ * `KmsKeyIdentifier`, `DeadLetterConfig`, and `Policy` (the latter is a
17685
+ * JSON string in `DescribeEventBus.Policy`; cdkd state holds it the way
17686
+ * the user typed it, which may be either an object or a string — the
17687
+ * comparator handles either side).
17688
+ *
17689
+ * `Tags` and `EventSourceName` are intentionally omitted: tags require a
17690
+ * separate `ListTagsForResource` round-trip and the auto-injected
17691
+ * `aws:cdk:path` tag-shape question is out of scope; `EventSourceName`
17692
+ * is set at create time only and not surfaced by `DescribeEventBus`.
17693
+ *
17694
+ * Returns `undefined` when the bus is gone (`ResourceNotFoundException`).
17695
+ */
17696
+ async readCurrentState(physicalId, _logicalId, _resourceType) {
17697
+ try {
17698
+ const resp = await this.eventBridgeClient.send(
17699
+ new DescribeEventBusCommand({ Name: physicalId })
17700
+ );
17701
+ const result = {};
17702
+ if (resp.Name !== void 0)
17703
+ result["Name"] = resp.Name;
17704
+ if (resp.Description !== void 0 && resp.Description !== "") {
17705
+ result["Description"] = resp.Description;
17706
+ }
17707
+ if (resp.KmsKeyIdentifier !== void 0) {
17708
+ result["KmsKeyIdentifier"] = resp.KmsKeyIdentifier;
17709
+ }
17710
+ if (resp.DeadLetterConfig?.Arn) {
17711
+ result["DeadLetterConfig"] = { Arn: resp.DeadLetterConfig.Arn };
17712
+ }
17713
+ if (resp.Policy) {
17714
+ try {
17715
+ result["Policy"] = JSON.parse(resp.Policy);
17716
+ } catch {
17717
+ result["Policy"] = resp.Policy;
17718
+ }
17719
+ }
17720
+ return result;
17721
+ } catch (err) {
17722
+ if (err instanceof ResourceNotFoundException10)
17723
+ return void 0;
17724
+ throw err;
17725
+ }
17726
+ }
17478
17727
  /**
17479
17728
  * Adopt an existing EventBridge event bus into cdkd state.
17480
17729
  *
@@ -19728,6 +19977,7 @@ var EC2Provider = class {
19728
19977
  // src/provisioning/providers/apigateway-provider.ts
19729
19978
  import {
19730
19979
  UpdateAccountCommand,
19980
+ GetAccountCommand,
19731
19981
  CreateResourceCommand as CreateResourceCommand2,
19732
19982
  DeleteResourceCommand as DeleteResourceCommand2,
19733
19983
  CreateDeploymentCommand,
@@ -19737,6 +19987,7 @@ import {
19737
19987
  DeleteStageCommand,
19738
19988
  PutMethodCommand,
19739
19989
  DeleteMethodCommand,
19990
+ GetMethodCommand,
19740
19991
  PutIntegrationCommand,
19741
19992
  PutMethodResponseCommand,
19742
19993
  CreateAuthorizerCommand,
@@ -20727,6 +20978,81 @@ var ApiGatewayProvider = class _ApiGatewayProvider {
20727
20978
  }
20728
20979
  return result;
20729
20980
  }
20981
+ /**
20982
+ * Read the AWS-current API Gateway resource configuration in CFn-property
20983
+ * shape.
20984
+ *
20985
+ * **Coverage**:
20986
+ * - `AWS::ApiGateway::Account` → `GetAccount` for `CloudWatchRoleArn`.
20987
+ * - `AWS::ApiGateway::Method` → `GetMethod`. PhysicalId is the composite
20988
+ * `restApiId|resourceId|httpMethod`, so we have everything needed
20989
+ * without `Properties`.
20990
+ *
20991
+ * **Out of scope** (returns `undefined`, falls back to "drift unknown"):
20992
+ * - `AWS::ApiGateway::Authorizer` / `Resource` / `Deployment` / `Stage`:
20993
+ * each needs the parent `RestApiId` to issue a `Get*` call, but cdkd's
20994
+ * `readCurrentState` interface does not pass `Properties` (only the
20995
+ * physicalId, which for these types is just the sub-resource id).
20996
+ * CC API drift detection picks up `AWS::ApiGateway::RestApi` itself
20997
+ * once the user works through the SDK provider boundary; per-sub
20998
+ * drift detection here would need a contract change.
20999
+ */
21000
+ async readCurrentState(physicalId, _logicalId, resourceType) {
21001
+ switch (resourceType) {
21002
+ case "AWS::ApiGateway::Account":
21003
+ return this.readCurrentStateAccount();
21004
+ case "AWS::ApiGateway::Method":
21005
+ return this.readCurrentStateMethod(physicalId);
21006
+ default:
21007
+ return void 0;
21008
+ }
21009
+ }
21010
+ async readCurrentStateAccount() {
21011
+ try {
21012
+ const resp = await this.apiGatewayClient.send(new GetAccountCommand({}));
21013
+ const result = {};
21014
+ if (resp.cloudwatchRoleArn !== void 0) {
21015
+ result["CloudWatchRoleArn"] = resp.cloudwatchRoleArn;
21016
+ }
21017
+ return result;
21018
+ } catch (err) {
21019
+ if (err instanceof NotFoundException3)
21020
+ return void 0;
21021
+ throw err;
21022
+ }
21023
+ }
21024
+ async readCurrentStateMethod(physicalId) {
21025
+ const parts = physicalId.split("|");
21026
+ if (parts.length !== 3)
21027
+ return void 0;
21028
+ const [restApiId, resourceId, httpMethod] = parts;
21029
+ try {
21030
+ const resp = await this.apiGatewayClient.send(
21031
+ new GetMethodCommand({ restApiId, resourceId, httpMethod })
21032
+ );
21033
+ const result = {};
21034
+ if (restApiId !== void 0)
21035
+ result["RestApiId"] = restApiId;
21036
+ if (resourceId !== void 0)
21037
+ result["ResourceId"] = resourceId;
21038
+ if (resp.httpMethod !== void 0)
21039
+ result["HttpMethod"] = resp.httpMethod;
21040
+ if (resp.authorizationType !== void 0) {
21041
+ result["AuthorizationType"] = resp.authorizationType;
21042
+ }
21043
+ if (resp.authorizerId !== void 0)
21044
+ result["AuthorizerId"] = resp.authorizerId;
21045
+ if (resp.methodIntegration)
21046
+ result["Integration"] = resp.methodIntegration;
21047
+ if (resp.methodResponses)
21048
+ result["MethodResponses"] = resp.methodResponses;
21049
+ return result;
21050
+ } catch (err) {
21051
+ if (err instanceof NotFoundException3)
21052
+ return void 0;
21053
+ throw err;
21054
+ }
21055
+ }
20730
21056
  /**
20731
21057
  * Adopt an existing API Gateway sub-resource into cdkd state.
20732
21058
  *
@@ -21303,6 +21629,45 @@ var ApiGatewayV2Provider = class {
21303
21629
  );
21304
21630
  }
21305
21631
  }
21632
+ // ─── Drift detection ──────────────────────────────────────────────
21633
+ /**
21634
+ * Read the AWS-current API Gateway V2 resource configuration in
21635
+ * CFn-property shape.
21636
+ *
21637
+ * **Coverage**:
21638
+ * - `AWS::ApiGatewayV2::Api` → `GetApi`. PhysicalId is the apiId,
21639
+ * self-sufficient.
21640
+ *
21641
+ * **Out of scope** (returns `undefined`, falls back to "drift unknown"):
21642
+ * - `AWS::ApiGatewayV2::Stage` / `Integration` / `Route` / `Authorizer`:
21643
+ * each needs the parent `ApiId` to issue a `Get*` call, but cdkd's
21644
+ * `readCurrentState` interface does not pass `Properties` (only the
21645
+ * physicalId, which for these types is just the sub-resource id).
21646
+ * Per-sub drift detection here would need a contract change.
21647
+ */
21648
+ async readCurrentState(physicalId, _logicalId, resourceType) {
21649
+ if (resourceType !== "AWS::ApiGatewayV2::Api") {
21650
+ return void 0;
21651
+ }
21652
+ try {
21653
+ const resp = await this.getClient().send(new GetApiCommand({ ApiId: physicalId }));
21654
+ const result = {};
21655
+ if (resp.Name !== void 0)
21656
+ result["Name"] = resp.Name;
21657
+ if (resp.ProtocolType !== void 0)
21658
+ result["ProtocolType"] = resp.ProtocolType;
21659
+ if (resp.Description !== void 0 && resp.Description !== "") {
21660
+ result["Description"] = resp.Description;
21661
+ }
21662
+ if (resp.CorsConfiguration)
21663
+ result["CorsConfiguration"] = resp.CorsConfiguration;
21664
+ return result;
21665
+ } catch (err) {
21666
+ if (err instanceof NotFoundException4)
21667
+ return void 0;
21668
+ throw err;
21669
+ }
21670
+ }
21306
21671
  // ─── Import ───────────────────────────────────────────────────────
21307
21672
  /**
21308
21673
  * Adopt an existing API Gateway V2 resource into cdkd state.
@@ -21516,6 +21881,36 @@ var CloudFrontOAIProvider = class {
21516
21881
  `Unsupported attribute: ${attributeName} for AWS::CloudFront::CloudFrontOriginAccessIdentity`
21517
21882
  );
21518
21883
  }
21884
+ /**
21885
+ * Read the AWS-current OAI configuration in CFn-property shape.
21886
+ *
21887
+ * Issues a single `GetCloudFrontOriginAccessIdentity` and surfaces the
21888
+ * `CloudFrontOriginAccessIdentityConfig.Comment` key — the only
21889
+ * cdkd-managed property (CallerReference is set by cdkd itself and is
21890
+ * not part of the user-configurable surface).
21891
+ *
21892
+ * Returns `undefined` when the OAI is gone (`NoSuchCloudFrontOriginAccessIdentity`).
21893
+ */
21894
+ async readCurrentState(physicalId, _logicalId, _resourceType) {
21895
+ try {
21896
+ const resp = await this.cloudFrontClient.send(
21897
+ new GetCloudFrontOriginAccessIdentityCommand2({ Id: physicalId })
21898
+ );
21899
+ const config = resp.CloudFrontOriginAccessIdentity?.CloudFrontOriginAccessIdentityConfig;
21900
+ if (!config)
21901
+ return void 0;
21902
+ const inner = {};
21903
+ if (config.Comment !== void 0)
21904
+ inner["Comment"] = config.Comment;
21905
+ return {
21906
+ CloudFrontOriginAccessIdentityConfig: inner
21907
+ };
21908
+ } catch (err) {
21909
+ if (err instanceof NoSuchCloudFrontOriginAccessIdentity)
21910
+ return void 0;
21911
+ throw err;
21912
+ }
21913
+ }
21519
21914
  /**
21520
21915
  * Adopt an existing CloudFront Origin Access Identity into cdkd state.
21521
21916
  *
@@ -22472,6 +22867,95 @@ var StepFunctionsProvider = class {
22472
22867
  );
22473
22868
  }
22474
22869
  }
22870
+ /**
22871
+ * Read the AWS-current Step Functions state machine config in CFn-property
22872
+ * shape.
22873
+ *
22874
+ * Issues a single `DescribeStateMachine` and surfaces:
22875
+ * - `StateMachineName` (`name`)
22876
+ * - `RoleArn` (`roleArn`)
22877
+ * - `StateMachineType` (`type`)
22878
+ * - `LoggingConfiguration` / `TracingConfiguration` / `EncryptionConfiguration`
22879
+ * (re-mapped to CFn PascalCase)
22880
+ * - `Definition` (parsed from JSON; cdkd state may hold either the
22881
+ * stringified `DefinitionString` or the object `Definition`, so we
22882
+ * surface as the object form — the comparator handles either side).
22883
+ *
22884
+ * `DefinitionSubstitutions` is omitted because they are applied at create
22885
+ * time and not surfaced by `DescribeStateMachine` (the response carries
22886
+ * the already-substituted definition).
22887
+ *
22888
+ * `Tags` is omitted (separate `ListTagsForResource` round-trip; auto-injected
22889
+ * `aws:cdk:path` tag-shape question is out of scope here).
22890
+ *
22891
+ * Returns `undefined` when the state machine is gone (`StateMachineDoesNotExist`).
22892
+ */
22893
+ async readCurrentState(physicalId, _logicalId, _resourceType) {
22894
+ let resp;
22895
+ try {
22896
+ resp = await this.getClient().send(
22897
+ new DescribeStateMachineCommand({ stateMachineArn: physicalId })
22898
+ );
22899
+ } catch (err) {
22900
+ if (err instanceof StateMachineDoesNotExist)
22901
+ return void 0;
22902
+ throw err;
22903
+ }
22904
+ const result = {};
22905
+ if (resp.name !== void 0)
22906
+ result["StateMachineName"] = resp.name;
22907
+ if (resp.roleArn !== void 0)
22908
+ result["RoleArn"] = resp.roleArn;
22909
+ if (resp.type !== void 0)
22910
+ result["StateMachineType"] = resp.type;
22911
+ if (resp.definition !== void 0) {
22912
+ try {
22913
+ result["Definition"] = JSON.parse(resp.definition);
22914
+ } catch {
22915
+ result["Definition"] = resp.definition;
22916
+ }
22917
+ }
22918
+ if (resp.loggingConfiguration) {
22919
+ const lc = {};
22920
+ if (resp.loggingConfiguration.level !== void 0) {
22921
+ lc["Level"] = resp.loggingConfiguration.level;
22922
+ }
22923
+ if (resp.loggingConfiguration.includeExecutionData !== void 0) {
22924
+ lc["IncludeExecutionData"] = resp.loggingConfiguration.includeExecutionData;
22925
+ }
22926
+ if (resp.loggingConfiguration.destinations) {
22927
+ lc["Destinations"] = resp.loggingConfiguration.destinations.map((d) => {
22928
+ const inner = {};
22929
+ if (d.cloudWatchLogsLogGroup?.logGroupArn) {
22930
+ inner["CloudWatchLogsLogGroup"] = {
22931
+ LogGroupArn: d.cloudWatchLogsLogGroup.logGroupArn
22932
+ };
22933
+ }
22934
+ return inner;
22935
+ });
22936
+ }
22937
+ if (Object.keys(lc).length > 0)
22938
+ result["LoggingConfiguration"] = lc;
22939
+ }
22940
+ if (resp.tracingConfiguration?.enabled !== void 0) {
22941
+ result["TracingConfiguration"] = { Enabled: resp.tracingConfiguration.enabled };
22942
+ }
22943
+ if (resp.encryptionConfiguration) {
22944
+ const ec = {};
22945
+ if (resp.encryptionConfiguration.type !== void 0) {
22946
+ ec["Type"] = resp.encryptionConfiguration.type;
22947
+ }
22948
+ if (resp.encryptionConfiguration.kmsKeyId !== void 0) {
22949
+ ec["KmsKeyId"] = resp.encryptionConfiguration.kmsKeyId;
22950
+ }
22951
+ if (resp.encryptionConfiguration.kmsDataKeyReusePeriodSeconds !== void 0) {
22952
+ ec["KmsDataKeyReusePeriodSeconds"] = resp.encryptionConfiguration.kmsDataKeyReusePeriodSeconds;
22953
+ }
22954
+ if (Object.keys(ec).length > 0)
22955
+ result["EncryptionConfiguration"] = ec;
22956
+ }
22957
+ return result;
22958
+ }
22475
22959
  /**
22476
22960
  * Adopt an existing Step Functions state machine into cdkd state.
22477
22961
  *
@@ -23301,6 +23785,173 @@ var ECSProvider = class {
23301
23785
  }
23302
23786
  return false;
23303
23787
  }
23788
+ /**
23789
+ * Read the AWS-current ECS resource configuration in CFn-property shape.
23790
+ *
23791
+ * Dispatches by resource type:
23792
+ * - `AWS::ECS::Cluster` → `DescribeClusters`
23793
+ * - `AWS::ECS::Service` → `DescribeServices`. Service physicalIds use
23794
+ * the composite form `<clusterArn>|<serviceName>`; we split on `|`.
23795
+ * - `AWS::ECS::TaskDefinition` → `DescribeTaskDefinition`
23796
+ *
23797
+ * Each branch surfaces only the keys cdkd's `create()` accepts, mapping
23798
+ * the SDK's camelCase to CFn PascalCase. Tags are intentionally omitted
23799
+ * (separate `ListTagsForResource` round-trip).
23800
+ */
23801
+ async readCurrentState(physicalId, _logicalId, resourceType) {
23802
+ switch (resourceType) {
23803
+ case "AWS::ECS::Cluster":
23804
+ return this.readCurrentStateCluster(physicalId);
23805
+ case "AWS::ECS::Service":
23806
+ return this.readCurrentStateService(physicalId);
23807
+ case "AWS::ECS::TaskDefinition":
23808
+ return this.readCurrentStateTaskDefinition(physicalId);
23809
+ default:
23810
+ return void 0;
23811
+ }
23812
+ }
23813
+ async readCurrentStateCluster(physicalId) {
23814
+ let resp;
23815
+ try {
23816
+ resp = await this.getClient().send(
23817
+ new DescribeClustersCommand({ clusters: [physicalId] })
23818
+ );
23819
+ } catch {
23820
+ return void 0;
23821
+ }
23822
+ const c = resp.clusters?.[0];
23823
+ if (!c || !c.clusterName)
23824
+ return void 0;
23825
+ const result = { ClusterName: c.clusterName };
23826
+ if (c.capacityProviders && c.capacityProviders.length > 0) {
23827
+ result["CapacityProviders"] = [...c.capacityProviders];
23828
+ }
23829
+ if (c.defaultCapacityProviderStrategy && c.defaultCapacityProviderStrategy.length > 0) {
23830
+ result["DefaultCapacityProviderStrategy"] = c.defaultCapacityProviderStrategy;
23831
+ }
23832
+ if (c.configuration)
23833
+ result["Configuration"] = c.configuration;
23834
+ if (c.settings && c.settings.length > 0) {
23835
+ result["ClusterSettings"] = c.settings.map((s) => ({
23836
+ Name: s.name,
23837
+ Value: s.value
23838
+ }));
23839
+ }
23840
+ return result;
23841
+ }
23842
+ async readCurrentStateService(physicalId) {
23843
+ const sep = physicalId.indexOf("|");
23844
+ if (sep < 0)
23845
+ return void 0;
23846
+ const clusterArn = physicalId.substring(0, sep);
23847
+ const serviceName = physicalId.substring(sep + 1);
23848
+ let resp;
23849
+ try {
23850
+ resp = await this.getClient().send(
23851
+ new DescribeServicesCommand({ cluster: clusterArn, services: [serviceName] })
23852
+ );
23853
+ } catch {
23854
+ return void 0;
23855
+ }
23856
+ const s = resp.services?.[0];
23857
+ if (!s || !s.serviceName)
23858
+ return void 0;
23859
+ const result = {};
23860
+ if (s.serviceName !== void 0)
23861
+ result["ServiceName"] = s.serviceName;
23862
+ if (s.clusterArn !== void 0)
23863
+ result["Cluster"] = s.clusterArn;
23864
+ if (s.taskDefinition !== void 0)
23865
+ result["TaskDefinition"] = s.taskDefinition;
23866
+ if (s.desiredCount !== void 0)
23867
+ result["DesiredCount"] = s.desiredCount;
23868
+ if (s.launchType !== void 0)
23869
+ result["LaunchType"] = s.launchType;
23870
+ if (s.platformVersion !== void 0)
23871
+ result["PlatformVersion"] = s.platformVersion;
23872
+ if (s.schedulingStrategy !== void 0)
23873
+ result["SchedulingStrategy"] = s.schedulingStrategy;
23874
+ if (s.propagateTags !== void 0)
23875
+ result["PropagateTags"] = s.propagateTags;
23876
+ if (s.enableECSManagedTags !== void 0) {
23877
+ result["EnableECSManagedTags"] = s.enableECSManagedTags;
23878
+ }
23879
+ if (s.enableExecuteCommand !== void 0) {
23880
+ result["EnableExecuteCommand"] = s.enableExecuteCommand;
23881
+ }
23882
+ if (s.healthCheckGracePeriodSeconds !== void 0) {
23883
+ result["HealthCheckGracePeriodSeconds"] = s.healthCheckGracePeriodSeconds;
23884
+ }
23885
+ if (s.networkConfiguration)
23886
+ result["NetworkConfiguration"] = s.networkConfiguration;
23887
+ if (s.loadBalancers && s.loadBalancers.length > 0) {
23888
+ result["LoadBalancers"] = s.loadBalancers;
23889
+ }
23890
+ if (s.capacityProviderStrategy && s.capacityProviderStrategy.length > 0) {
23891
+ result["CapacityProviderStrategy"] = s.capacityProviderStrategy;
23892
+ }
23893
+ if (s.deploymentConfiguration)
23894
+ result["DeploymentConfiguration"] = s.deploymentConfiguration;
23895
+ if (s.placementConstraints && s.placementConstraints.length > 0) {
23896
+ result["PlacementConstraints"] = s.placementConstraints;
23897
+ }
23898
+ if (s.placementStrategy && s.placementStrategy.length > 0) {
23899
+ result["PlacementStrategy"] = s.placementStrategy;
23900
+ }
23901
+ if (s.serviceRegistries && s.serviceRegistries.length > 0) {
23902
+ result["ServiceRegistries"] = s.serviceRegistries;
23903
+ }
23904
+ return result;
23905
+ }
23906
+ async readCurrentStateTaskDefinition(physicalId) {
23907
+ let resp;
23908
+ try {
23909
+ resp = await this.getClient().send(
23910
+ new DescribeTaskDefinitionCommand({ taskDefinition: physicalId })
23911
+ );
23912
+ } catch {
23913
+ return void 0;
23914
+ }
23915
+ const td = resp.taskDefinition;
23916
+ if (!td)
23917
+ return void 0;
23918
+ const result = {};
23919
+ if (td.family !== void 0)
23920
+ result["Family"] = td.family;
23921
+ if (td.cpu !== void 0)
23922
+ result["Cpu"] = td.cpu;
23923
+ if (td.memory !== void 0)
23924
+ result["Memory"] = td.memory;
23925
+ if (td.networkMode !== void 0)
23926
+ result["NetworkMode"] = td.networkMode;
23927
+ if (td.requiresCompatibilities && td.requiresCompatibilities.length > 0) {
23928
+ result["RequiresCompatibilities"] = [...td.requiresCompatibilities];
23929
+ }
23930
+ if (td.executionRoleArn !== void 0)
23931
+ result["ExecutionRoleArn"] = td.executionRoleArn;
23932
+ if (td.taskRoleArn !== void 0)
23933
+ result["TaskRoleArn"] = td.taskRoleArn;
23934
+ if (td.volumes && td.volumes.length > 0)
23935
+ result["Volumes"] = td.volumes;
23936
+ if (td.placementConstraints && td.placementConstraints.length > 0) {
23937
+ result["PlacementConstraints"] = td.placementConstraints;
23938
+ }
23939
+ if (td.runtimePlatform)
23940
+ result["RuntimePlatform"] = td.runtimePlatform;
23941
+ if (td.proxyConfiguration)
23942
+ result["ProxyConfiguration"] = td.proxyConfiguration;
23943
+ if (td.pidMode !== void 0)
23944
+ result["PidMode"] = td.pidMode;
23945
+ if (td.ipcMode !== void 0)
23946
+ result["IpcMode"] = td.ipcMode;
23947
+ if (td.ephemeralStorage?.sizeInGiB !== void 0) {
23948
+ result["EphemeralStorage"] = { SizeInGiB: td.ephemeralStorage.sizeInGiB };
23949
+ }
23950
+ if (td.containerDefinitions && td.containerDefinitions.length > 0) {
23951
+ result["ContainerDefinitions"] = td.containerDefinitions;
23952
+ }
23953
+ return result;
23954
+ }
23304
23955
  /**
23305
23956
  * Adopt an existing ECS resource into cdkd state.
23306
23957
  *
@@ -24675,6 +25326,146 @@ var RDSProvider = class {
24675
25326
  return null;
24676
25327
  }
24677
25328
  }
25329
+ /**
25330
+ * Read the AWS-current RDS resource configuration in CFn-property shape.
25331
+ *
25332
+ * Dispatches by resource type:
25333
+ * - `AWS::RDS::DBInstance` → `DescribeDBInstances`
25334
+ * - `AWS::RDS::DBCluster` → `DescribeDBClusters`
25335
+ * - `AWS::RDS::DBSubnetGroup` → `DescribeDBSubnetGroups`
25336
+ *
25337
+ * Each branch surfaces only the keys cdkd's `create()` accepts. Sensitive
25338
+ * fields like `MasterUserPassword` are NEVER surfaced (RDS does not return
25339
+ * them in the Describe responses). `Tags` are intentionally omitted
25340
+ * (separate `ListTagsForResource` round-trip).
25341
+ *
25342
+ * Returns `undefined` when the resource is gone (`*NotFoundFault`).
25343
+ */
25344
+ async readCurrentState(physicalId, _logicalId, resourceType) {
25345
+ switch (resourceType) {
25346
+ case "AWS::RDS::DBInstance":
25347
+ return this.readCurrentStateDBInstance(physicalId);
25348
+ case "AWS::RDS::DBCluster":
25349
+ return this.readCurrentStateDBCluster(physicalId);
25350
+ case "AWS::RDS::DBSubnetGroup":
25351
+ return this.readCurrentStateDBSubnetGroup(physicalId);
25352
+ default:
25353
+ return void 0;
25354
+ }
25355
+ }
25356
+ async readCurrentStateDBInstance(physicalId) {
25357
+ let inst;
25358
+ try {
25359
+ inst = await this.describeDBInstance(physicalId);
25360
+ } catch (err) {
25361
+ if (this.isNotFoundError(err, "DBInstanceNotFoundFault"))
25362
+ return void 0;
25363
+ throw err;
25364
+ }
25365
+ if (!inst)
25366
+ return void 0;
25367
+ const result = {};
25368
+ if (inst.DBInstanceIdentifier !== void 0) {
25369
+ result["DBInstanceIdentifier"] = inst.DBInstanceIdentifier;
25370
+ }
25371
+ if (inst.DBInstanceClass !== void 0)
25372
+ result["DBInstanceClass"] = inst.DBInstanceClass;
25373
+ if (inst.Engine !== void 0)
25374
+ result["Engine"] = inst.Engine;
25375
+ if (inst.DBClusterIdentifier !== void 0) {
25376
+ result["DBClusterIdentifier"] = inst.DBClusterIdentifier;
25377
+ }
25378
+ if (inst.DBSubnetGroup?.DBSubnetGroupName !== void 0) {
25379
+ result["DBSubnetGroupName"] = inst.DBSubnetGroup.DBSubnetGroupName;
25380
+ }
25381
+ if (inst.PubliclyAccessible !== void 0) {
25382
+ result["PubliclyAccessible"] = inst.PubliclyAccessible;
25383
+ }
25384
+ return result;
25385
+ }
25386
+ async readCurrentStateDBCluster(physicalId) {
25387
+ let cluster;
25388
+ try {
25389
+ cluster = await this.describeDBCluster(physicalId);
25390
+ } catch (err) {
25391
+ if (this.isNotFoundError(err, "DBClusterNotFoundFault"))
25392
+ return void 0;
25393
+ throw err;
25394
+ }
25395
+ if (!cluster)
25396
+ return void 0;
25397
+ const result = {};
25398
+ if (cluster.DBClusterIdentifier !== void 0) {
25399
+ result["DBClusterIdentifier"] = cluster.DBClusterIdentifier;
25400
+ }
25401
+ if (cluster.Engine !== void 0)
25402
+ result["Engine"] = cluster.Engine;
25403
+ if (cluster.EngineVersion !== void 0)
25404
+ result["EngineVersion"] = cluster.EngineVersion;
25405
+ if (cluster.MasterUsername !== void 0)
25406
+ result["MasterUsername"] = cluster.MasterUsername;
25407
+ if (cluster.DatabaseName !== void 0)
25408
+ result["DatabaseName"] = cluster.DatabaseName;
25409
+ if (cluster.Port !== void 0)
25410
+ result["Port"] = cluster.Port;
25411
+ if (cluster.VpcSecurityGroups && cluster.VpcSecurityGroups.length > 0) {
25412
+ result["VpcSecurityGroupIds"] = cluster.VpcSecurityGroups.map(
25413
+ (sg) => sg.VpcSecurityGroupId
25414
+ ).filter((id) => !!id);
25415
+ }
25416
+ if (cluster.DBSubnetGroup !== void 0)
25417
+ result["DBSubnetGroupName"] = cluster.DBSubnetGroup;
25418
+ if (cluster.StorageEncrypted !== void 0) {
25419
+ result["StorageEncrypted"] = cluster.StorageEncrypted;
25420
+ }
25421
+ if (cluster.KmsKeyId !== void 0)
25422
+ result["KmsKeyId"] = cluster.KmsKeyId;
25423
+ if (cluster.BackupRetentionPeriod !== void 0) {
25424
+ result["BackupRetentionPeriod"] = cluster.BackupRetentionPeriod;
25425
+ }
25426
+ if (cluster.DeletionProtection !== void 0) {
25427
+ result["DeletionProtection"] = cluster.DeletionProtection;
25428
+ }
25429
+ if (cluster.ServerlessV2ScalingConfiguration) {
25430
+ const sc = {};
25431
+ if (cluster.ServerlessV2ScalingConfiguration.MinCapacity !== void 0) {
25432
+ sc["MinCapacity"] = cluster.ServerlessV2ScalingConfiguration.MinCapacity;
25433
+ }
25434
+ if (cluster.ServerlessV2ScalingConfiguration.MaxCapacity !== void 0) {
25435
+ sc["MaxCapacity"] = cluster.ServerlessV2ScalingConfiguration.MaxCapacity;
25436
+ }
25437
+ if (Object.keys(sc).length > 0)
25438
+ result["ServerlessV2ScalingConfiguration"] = sc;
25439
+ }
25440
+ return result;
25441
+ }
25442
+ async readCurrentStateDBSubnetGroup(physicalId) {
25443
+ let resp;
25444
+ try {
25445
+ resp = await this.getClient().send(
25446
+ new DescribeDBSubnetGroupsCommand({ DBSubnetGroupName: physicalId })
25447
+ );
25448
+ } catch (err) {
25449
+ if (this.isNotFoundError(err, "DBSubnetGroupNotFoundFault"))
25450
+ return void 0;
25451
+ throw err;
25452
+ }
25453
+ const sg = resp.DBSubnetGroups?.[0];
25454
+ if (!sg)
25455
+ return void 0;
25456
+ const result = {};
25457
+ if (sg.DBSubnetGroupName !== void 0)
25458
+ result["DBSubnetGroupName"] = sg.DBSubnetGroupName;
25459
+ if (sg.DBSubnetGroupDescription !== void 0) {
25460
+ result["DBSubnetGroupDescription"] = sg.DBSubnetGroupDescription;
25461
+ }
25462
+ if (sg.Subnets && sg.Subnets.length > 0) {
25463
+ result["SubnetIds"] = sg.Subnets.map((s) => s.SubnetIdentifier).filter(
25464
+ (id) => !!id
25465
+ );
25466
+ }
25467
+ return result;
25468
+ }
24678
25469
  async importDBInstance(input) {
24679
25470
  const explicit = resolveExplicitPhysicalId(input, "DBInstanceIdentifier");
24680
25471
  if (explicit) {
@@ -26127,6 +26918,98 @@ var CognitoUserPoolProvider = class {
26127
26918
  );
26128
26919
  }
26129
26920
  }
26921
+ /**
26922
+ * Read the AWS-current Cognito User Pool configuration in CFn-property shape.
26923
+ *
26924
+ * Issues `DescribeUserPool` and surfaces the keys cdkd's `create()` accepts.
26925
+ * AWS-managed fields (Arn, Id, CreationDate, LastModifiedDate, EstimatedNumberOfUsers,
26926
+ * etc.) are filtered at the wire layer.
26927
+ *
26928
+ * **Note**: Cognito only supports `AWS::Cognito::UserPool` in this provider;
26929
+ * `UserPoolClient`, `UserPoolGroup`, and other Cognito sub-resources go
26930
+ * through the CC API fallback (which has its own `readCurrentState`).
26931
+ *
26932
+ * `UserPoolTags` is intentionally omitted (Cognito returns tags via a
26933
+ * separate `ListTagsForResource` round-trip; auto-injected `aws:cdk:path`
26934
+ * tag-shape question is out of scope here).
26935
+ *
26936
+ * Returns `undefined` when the pool is gone (`ResourceNotFoundException`).
26937
+ */
26938
+ async readCurrentState(physicalId, _logicalId, resourceType) {
26939
+ if (resourceType !== "AWS::Cognito::UserPool")
26940
+ return void 0;
26941
+ let resp;
26942
+ try {
26943
+ resp = await this.getClient().send(new DescribeUserPoolCommand({ UserPoolId: physicalId }));
26944
+ } catch (err) {
26945
+ if (err instanceof ResourceNotFoundException12)
26946
+ return void 0;
26947
+ throw err;
26948
+ }
26949
+ const pool = resp.UserPool;
26950
+ if (!pool)
26951
+ return void 0;
26952
+ const result = {};
26953
+ if (pool.Name !== void 0)
26954
+ result["UserPoolName"] = pool.Name;
26955
+ if (pool.AutoVerifiedAttributes && pool.AutoVerifiedAttributes.length > 0) {
26956
+ result["AutoVerifiedAttributes"] = [...pool.AutoVerifiedAttributes];
26957
+ }
26958
+ if (pool.UsernameAttributes && pool.UsernameAttributes.length > 0) {
26959
+ result["UsernameAttributes"] = [...pool.UsernameAttributes];
26960
+ }
26961
+ if (pool.AliasAttributes && pool.AliasAttributes.length > 0) {
26962
+ result["AliasAttributes"] = [...pool.AliasAttributes];
26963
+ }
26964
+ if (pool.Policies)
26965
+ result["Policies"] = pool.Policies;
26966
+ if (pool.SchemaAttributes && pool.SchemaAttributes.length > 0) {
26967
+ result["Schema"] = pool.SchemaAttributes;
26968
+ }
26969
+ if (pool.LambdaConfig && Object.keys(pool.LambdaConfig).length > 0) {
26970
+ result["LambdaConfig"] = pool.LambdaConfig;
26971
+ }
26972
+ if (pool.MfaConfiguration !== void 0)
26973
+ result["MfaConfiguration"] = pool.MfaConfiguration;
26974
+ if (pool.AdminCreateUserConfig)
26975
+ result["AdminCreateUserConfig"] = pool.AdminCreateUserConfig;
26976
+ if (pool.AccountRecoverySetting) {
26977
+ result["AccountRecoverySetting"] = pool.AccountRecoverySetting;
26978
+ }
26979
+ if (pool.UserAttributeUpdateSettings) {
26980
+ result["UserAttributeUpdateSettings"] = pool.UserAttributeUpdateSettings;
26981
+ }
26982
+ if (pool.DeletionProtection !== void 0) {
26983
+ result["DeletionProtection"] = pool.DeletionProtection;
26984
+ }
26985
+ if (pool.EmailConfiguration)
26986
+ result["EmailConfiguration"] = pool.EmailConfiguration;
26987
+ if (pool.SmsConfiguration)
26988
+ result["SmsConfiguration"] = pool.SmsConfiguration;
26989
+ if (pool.VerificationMessageTemplate) {
26990
+ result["VerificationMessageTemplate"] = pool.VerificationMessageTemplate;
26991
+ }
26992
+ if (pool.UsernameConfiguration) {
26993
+ result["UsernameConfiguration"] = pool.UsernameConfiguration;
26994
+ }
26995
+ if (pool.DeviceConfiguration)
26996
+ result["DeviceConfiguration"] = pool.DeviceConfiguration;
26997
+ if (pool.UserPoolAddOns)
26998
+ result["UserPoolAddOns"] = pool.UserPoolAddOns;
26999
+ if (pool.EmailVerificationMessage !== void 0) {
27000
+ result["EmailVerificationMessage"] = pool.EmailVerificationMessage;
27001
+ }
27002
+ if (pool.EmailVerificationSubject !== void 0) {
27003
+ result["EmailVerificationSubject"] = pool.EmailVerificationSubject;
27004
+ }
27005
+ if (pool.SmsAuthenticationMessage !== void 0) {
27006
+ result["SmsAuthenticationMessage"] = pool.SmsAuthenticationMessage;
27007
+ }
27008
+ if (pool.SmsVerificationMessage !== void 0) {
27009
+ result["SmsVerificationMessage"] = pool.SmsVerificationMessage;
27010
+ }
27011
+ return result;
27012
+ }
26130
27013
  /**
26131
27014
  * Adopt an existing Cognito User Pool into cdkd state.
26132
27015
  *
@@ -28700,6 +29583,88 @@ var KMSProvider = class {
28700
29583
  );
28701
29584
  }
28702
29585
  }
29586
+ /**
29587
+ * Read the AWS-current KMS resource configuration in CFn-property shape.
29588
+ *
29589
+ * Dispatches by resource type:
29590
+ * - `AWS::KMS::Key` → `DescribeKey`. Surfaces `Description`, `KeySpec`,
29591
+ * `KeyUsage`, `Enabled`, `MultiRegion`, `Origin`. `KeyPolicy` is
29592
+ * intentionally NOT retrieved — `GetKeyPolicy` is a separate call
29593
+ * and the policy body needs JSON parsing for comparison; deferred
29594
+ * to a follow-up. `EnableKeyRotation` / `RotationPeriodInDays`
29595
+ * would require `GetKeyRotationStatus`; also deferred.
29596
+ * - `AWS::KMS::Alias` → `ListAliases` filtered to the alias name.
29597
+ * Surfaces `AliasName`, `TargetKeyId`. `ListAliases` is paginated
29598
+ * since there's no direct "describe one alias" API.
29599
+ *
29600
+ * `Tags` is intentionally omitted (separate `ListResourceTags` round-trip
29601
+ * for keys; auto-injected `aws:cdk:path` tag-shape question is out of
29602
+ * scope here). `BypassPolicyLockoutSafetyCheck` and `PendingWindowInDays`
29603
+ * are not part of the persisted AWS state visible via `DescribeKey`.
29604
+ *
29605
+ * Returns `undefined` when the resource is gone (`NotFoundException`).
29606
+ */
29607
+ async readCurrentState(physicalId, _logicalId, resourceType) {
29608
+ switch (resourceType) {
29609
+ case "AWS::KMS::Key":
29610
+ return this.readCurrentStateKey(physicalId);
29611
+ case "AWS::KMS::Alias":
29612
+ return this.readCurrentStateAlias(physicalId);
29613
+ default:
29614
+ return void 0;
29615
+ }
29616
+ }
29617
+ async readCurrentStateKey(physicalId) {
29618
+ let resp;
29619
+ try {
29620
+ resp = await this.getClient().send(
29621
+ new DescribeKeyCommand({ KeyId: physicalId })
29622
+ );
29623
+ } catch (err) {
29624
+ if (err instanceof NotFoundException5)
29625
+ return void 0;
29626
+ throw err;
29627
+ }
29628
+ const md = resp.KeyMetadata;
29629
+ if (!md)
29630
+ return void 0;
29631
+ const result = {};
29632
+ if (md.Description !== void 0 && md.Description !== "") {
29633
+ result["Description"] = md.Description;
29634
+ }
29635
+ if (md.KeySpec !== void 0)
29636
+ result["KeySpec"] = md.KeySpec;
29637
+ if (md.KeyUsage !== void 0)
29638
+ result["KeyUsage"] = md.KeyUsage;
29639
+ if (md.Enabled !== void 0)
29640
+ result["Enabled"] = md.Enabled;
29641
+ if (md.MultiRegion !== void 0)
29642
+ result["MultiRegion"] = md.MultiRegion;
29643
+ if (md.Origin !== void 0)
29644
+ result["Origin"] = md.Origin;
29645
+ return result;
29646
+ }
29647
+ async readCurrentStateAlias(physicalId) {
29648
+ let marker;
29649
+ do {
29650
+ const list = await this.getClient().send(
29651
+ new ListAliasesCommand2({ ...marker && { Marker: marker } })
29652
+ );
29653
+ const found = list.Aliases?.find(
29654
+ (a) => a.AliasName === physicalId
29655
+ );
29656
+ if (found) {
29657
+ const result = {};
29658
+ if (found.AliasName)
29659
+ result["AliasName"] = found.AliasName;
29660
+ if (found.TargetKeyId)
29661
+ result["TargetKeyId"] = found.TargetKeyId;
29662
+ return result;
29663
+ }
29664
+ marker = list.NextMarker;
29665
+ } while (marker);
29666
+ return void 0;
29667
+ }
28703
29668
  /**
28704
29669
  * Adopt an existing KMS key or alias into cdkd state.
28705
29670
  *
@@ -31712,12 +32677,14 @@ import {
31712
32677
  CreateRepositoryCommand,
31713
32678
  DeleteRepositoryCommand,
31714
32679
  DescribeRepositoriesCommand,
32680
+ GetLifecyclePolicyCommand,
31715
32681
  PutLifecyclePolicyCommand,
31716
32682
  SetRepositoryPolicyCommand,
31717
32683
  PutImageScanningConfigurationCommand,
31718
32684
  PutImageTagMutabilityCommand,
31719
32685
  TagResourceCommand as TagResourceCommand7,
31720
32686
  ListTagsForResourceCommand as ListTagsForResourceCommand18,
32687
+ LifecyclePolicyNotFoundException,
31721
32688
  RepositoryNotFoundException
31722
32689
  } from "@aws-sdk/client-ecr";
31723
32690
  var ECRProvider = class {
@@ -31951,6 +32918,82 @@ var ECRProvider = class {
31951
32918
  );
31952
32919
  }
31953
32920
  }
32921
+ /**
32922
+ * Read the AWS-current ECR repository configuration in CFn-property shape.
32923
+ *
32924
+ * Issues `DescribeRepositories(filtered=[name])` for the repository's
32925
+ * configuration, then a separate `GetLifecyclePolicy` for `LifecyclePolicy`
32926
+ * (which `DescribeRepositories` doesn't return).
32927
+ *
32928
+ * Surfaced keys: `RepositoryName`, `ImageTagMutability`,
32929
+ * `ImageScanningConfiguration`, `EncryptionConfiguration`, `LifecyclePolicy`
32930
+ * (when configured — `LifecyclePolicyNotFoundException` is caught and the
32931
+ * key omitted, NOT propagated as repo-gone).
32932
+ *
32933
+ * Intentionally omitted:
32934
+ * - `RepositoryPolicyText`: requires a separate `GetRepositoryPolicy`
32935
+ * round-trip; cdkd state holds the policy as either a string or an
32936
+ * object (depending on user input), and the comparator round-trip
32937
+ * is not yet handled here.
32938
+ * - `Tags`: requires `ListTagsForResource`; auto-injected
32939
+ * `aws:cdk:path` tag-shape question is out of scope.
32940
+ * - `EmptyOnDelete` / `ImageTagMutabilityExclusionFilters`: not part
32941
+ * of the persisted AWS state visible via standard Describe.
32942
+ *
32943
+ * Returns `undefined` when the repository is gone (`RepositoryNotFoundException`).
32944
+ */
32945
+ async readCurrentState(physicalId, _logicalId, _resourceType) {
32946
+ let repo;
32947
+ try {
32948
+ repo = await this.getClient().send(
32949
+ new DescribeRepositoriesCommand({ repositoryNames: [physicalId] })
32950
+ );
32951
+ } catch (err) {
32952
+ if (err instanceof RepositoryNotFoundException)
32953
+ return void 0;
32954
+ throw err;
32955
+ }
32956
+ const r = repo.repositories?.[0];
32957
+ if (!r)
32958
+ return void 0;
32959
+ const result = {};
32960
+ if (r.repositoryName !== void 0)
32961
+ result["RepositoryName"] = r.repositoryName;
32962
+ if (r.imageTagMutability !== void 0)
32963
+ result["ImageTagMutability"] = r.imageTagMutability;
32964
+ if (r.imageScanningConfiguration) {
32965
+ const inner = {};
32966
+ if (r.imageScanningConfiguration.scanOnPush !== void 0) {
32967
+ inner["ScanOnPush"] = r.imageScanningConfiguration.scanOnPush;
32968
+ }
32969
+ if (Object.keys(inner).length > 0)
32970
+ result["ImageScanningConfiguration"] = inner;
32971
+ }
32972
+ if (r.encryptionConfiguration) {
32973
+ const inner = {};
32974
+ if (r.encryptionConfiguration.encryptionType !== void 0) {
32975
+ inner["EncryptionType"] = r.encryptionConfiguration.encryptionType;
32976
+ }
32977
+ if (r.encryptionConfiguration.kmsKey !== void 0) {
32978
+ inner["KmsKey"] = r.encryptionConfiguration.kmsKey;
32979
+ }
32980
+ if (Object.keys(inner).length > 0)
32981
+ result["EncryptionConfiguration"] = inner;
32982
+ }
32983
+ try {
32984
+ const lp = await this.getClient().send(
32985
+ new GetLifecyclePolicyCommand({ repositoryName: physicalId })
32986
+ );
32987
+ if (lp.lifecyclePolicyText) {
32988
+ result["LifecyclePolicy"] = { LifecyclePolicyText: lp.lifecyclePolicyText };
32989
+ }
32990
+ } catch (err) {
32991
+ if (!(err instanceof LifecyclePolicyNotFoundException)) {
32992
+ throw err;
32993
+ }
32994
+ }
32995
+ return result;
32996
+ }
31954
32997
  /**
31955
32998
  * Adopt an existing ECR repository into cdkd state.
31956
32999
  *
@@ -34066,6 +35109,7 @@ function createDiffCommand() {
34066
35109
  }
34067
35110
 
34068
35111
  // src/cli/commands/drift.ts
35112
+ import * as readline from "node:readline/promises";
34069
35113
  import { Command as Command6, Option as Option3 } from "commander";
34070
35114
  init_aws_clients();
34071
35115
 
@@ -34141,6 +35185,11 @@ async function driftCommand(stacks, options) {
34141
35185
  if (!options.all && stacks.length === 0) {
34142
35186
  throw new Error("Stack name is required. Usage: cdkd drift <stack> [<stack>...] | --all");
34143
35187
  }
35188
+ if (options.accept && options.revert) {
35189
+ throw new Error(
35190
+ "--accept and --revert are mutually exclusive. Use --accept to update cdkd state from AWS, or --revert to push cdkd state values back into AWS."
35191
+ );
35192
+ }
34144
35193
  await applyRoleArnIfSet({ roleArn: options.roleArn, region: options.region });
34145
35194
  const awsClients = new AwsClients({
34146
35195
  ...options.region && { region: options.region },
@@ -34151,14 +35200,11 @@ async function driftCommand(stacks, options) {
34151
35200
  const region = options.region || process.env["AWS_REGION"] || "us-east-1";
34152
35201
  const bucket = await resolveStateBucketWithDefault(options.stateBucket, region);
34153
35202
  const prefix = options.statePrefix;
34154
- const stateBackend = new S3StateBackend(
34155
- awsClients.s3,
34156
- { bucket, prefix },
34157
- {
34158
- region,
34159
- ...options.profile && { profile: options.profile }
34160
- }
34161
- );
35203
+ const stateConfig = { bucket, prefix };
35204
+ const stateBackend = new S3StateBackend(awsClients.s3, stateConfig, {
35205
+ region,
35206
+ ...options.profile && { profile: options.profile }
35207
+ });
34162
35208
  await stateBackend.verifyBucketExists();
34163
35209
  const providerRegistry = new ProviderRegistry();
34164
35210
  registerAllProviders(providerRegistry);
@@ -34186,8 +35232,22 @@ async function driftCommand(stacks, options) {
34186
35232
  writeHumanReport(reports);
34187
35233
  }
34188
35234
  const drifted = reports.some((r) => r.outcomes.some((o) => o.kind === "drifted"));
34189
- if (drifted) {
34190
- throw new DriftDetectedError();
35235
+ if (!options.accept && !options.revert) {
35236
+ if (drifted) {
35237
+ throw new DriftDetectedError();
35238
+ }
35239
+ return;
35240
+ }
35241
+ if (!drifted) {
35242
+ logger.info(
35243
+ options.accept ? "No drift detected \u2014 nothing to accept." : "No drift detected \u2014 nothing to revert."
35244
+ );
35245
+ return;
35246
+ }
35247
+ if (options.accept) {
35248
+ await runAccept(reports, stateBackend, stateConfig, awsClients, options);
35249
+ } else {
35250
+ await runRevert(reports, providerRegistry, stateConfig, awsClients, options);
34191
35251
  }
34192
35252
  } finally {
34193
35253
  awsClients.destroy();
@@ -34288,13 +35348,261 @@ async function runDriftForStack(stackName, region, stateBackend, providerRegistr
34288
35348
  kind: "drifted",
34289
35349
  logicalId,
34290
35350
  resourceType: resource.resourceType,
34291
- changes
35351
+ changes,
35352
+ awsProperties: aws
34292
35353
  });
34293
35354
  }
34294
35355
  }
34295
- return { stackName, region, outcomes };
35356
+ return {
35357
+ stackName,
35358
+ region,
35359
+ outcomes,
35360
+ state,
35361
+ etag: result.etag,
35362
+ migrationPending: result.migrationPending ?? false
35363
+ };
34296
35364
  });
34297
35365
  }
35366
+ function setAtPath(target, path, value) {
35367
+ if (path.length === 0) {
35368
+ return;
35369
+ }
35370
+ const segments = path.split(".");
35371
+ let cursor = target;
35372
+ for (let i = 0; i < segments.length - 1; i++) {
35373
+ const key = segments[i];
35374
+ const next = cursor[key];
35375
+ if (next === void 0 || next === null || typeof next !== "object" || Array.isArray(next)) {
35376
+ const fresh = {};
35377
+ cursor[key] = fresh;
35378
+ cursor = fresh;
35379
+ } else {
35380
+ cursor = next;
35381
+ }
35382
+ }
35383
+ cursor[segments[segments.length - 1]] = value;
35384
+ }
35385
+ async function runAccept(reports, stateBackend, stateConfig, awsClients, options) {
35386
+ const logger = getLogger();
35387
+ printAcceptPlan(reports);
35388
+ if (options.dryRun) {
35389
+ logger.info("--dry-run: state will NOT be written. Re-run without --dry-run to apply.");
35390
+ return;
35391
+ }
35392
+ if (!options.yes) {
35393
+ const ok = await confirmPrompt(`Update cdkd state with the AWS-current values shown above?`);
35394
+ if (!ok) {
35395
+ logger.info("Aborted.");
35396
+ return;
35397
+ }
35398
+ }
35399
+ const lockManager = new LockManager(awsClients.s3, stateConfig);
35400
+ const owner = `${process.env["USER"] || "unknown"}@${process.env["HOSTNAME"] || "host"}:${process.pid}`;
35401
+ for (const report of reports) {
35402
+ const driftedOutcomes = report.outcomes.filter(
35403
+ (o) => o.kind === "drifted"
35404
+ );
35405
+ if (driftedOutcomes.length === 0) {
35406
+ continue;
35407
+ }
35408
+ await lockManager.acquireLock(report.stackName, report.region, owner, "drift-accept");
35409
+ try {
35410
+ const resources = { ...report.state.resources };
35411
+ for (const outcome of driftedOutcomes) {
35412
+ const existing = resources[outcome.logicalId];
35413
+ if (!existing)
35414
+ continue;
35415
+ const newProperties = JSON.parse(JSON.stringify(existing.properties ?? {}));
35416
+ for (const change of outcome.changes) {
35417
+ setAtPath(newProperties, change.path, change.awsValue);
35418
+ }
35419
+ resources[outcome.logicalId] = {
35420
+ ...existing,
35421
+ properties: newProperties
35422
+ };
35423
+ }
35424
+ const newState = {
35425
+ ...report.state,
35426
+ resources,
35427
+ lastModified: Date.now()
35428
+ };
35429
+ const saveOptions = {
35430
+ expectedEtag: report.etag
35431
+ };
35432
+ if (report.migrationPending) {
35433
+ saveOptions.migrateLegacy = true;
35434
+ }
35435
+ await stateBackend.saveState(report.stackName, report.region, newState, saveOptions);
35436
+ logger.info(
35437
+ `\u2713 State updated for ${report.stackName} (${report.region}): accepted drift on ${driftedOutcomes.length} resource(s).`
35438
+ );
35439
+ } finally {
35440
+ await lockManager.releaseLock(report.stackName, report.region).catch((err) => {
35441
+ logger.warn(
35442
+ `Failed to release lock for ${report.stackName} (${report.region}): ` + (err instanceof Error ? err.message : String(err))
35443
+ );
35444
+ });
35445
+ }
35446
+ }
35447
+ }
35448
+ async function runRevert(reports, providerRegistry, stateConfig, awsClients, options) {
35449
+ const logger = getLogger();
35450
+ printRevertPlan(reports);
35451
+ if (options.dryRun) {
35452
+ logger.info("--dry-run: AWS will NOT be modified. Re-run without --dry-run to apply.");
35453
+ return;
35454
+ }
35455
+ if (!options.yes) {
35456
+ const ok = await confirmPrompt(
35457
+ `Push cdkd state values back into AWS for the resources shown above?`
35458
+ );
35459
+ if (!ok) {
35460
+ logger.info("Aborted.");
35461
+ return;
35462
+ }
35463
+ }
35464
+ const lockManager = new LockManager(awsClients.s3, stateConfig);
35465
+ const owner = `${process.env["USER"] || "unknown"}@${process.env["HOSTNAME"] || "host"}:${process.pid}`;
35466
+ const concurrency = Math.max(1, options.concurrency ?? 4);
35467
+ let totalFailed = 0;
35468
+ let totalSucceeded = 0;
35469
+ for (const report of reports) {
35470
+ const driftedOutcomes = report.outcomes.filter(
35471
+ (o) => o.kind === "drifted"
35472
+ );
35473
+ if (driftedOutcomes.length === 0) {
35474
+ continue;
35475
+ }
35476
+ await lockManager.acquireLock(report.stackName, report.region, owner, "drift-revert");
35477
+ try {
35478
+ const tasks = driftedOutcomes.map((outcome) => async () => {
35479
+ const stateResource = report.state.resources[outcome.logicalId];
35480
+ if (!stateResource) {
35481
+ totalFailed++;
35482
+ logger.error(
35483
+ ` \u2717 ${report.stackName}/${outcome.logicalId} (${outcome.resourceType}): resource missing from state; skipped.`
35484
+ );
35485
+ return;
35486
+ }
35487
+ const provider = providerRegistry.getProvider(outcome.resourceType);
35488
+ try {
35489
+ await withRetry(
35490
+ () => provider.update(
35491
+ outcome.logicalId,
35492
+ stateResource.physicalId,
35493
+ outcome.resourceType,
35494
+ stateResource.properties ?? {},
35495
+ outcome.awsProperties
35496
+ ),
35497
+ outcome.logicalId,
35498
+ { logger: { debug: (msg) => logger.debug(msg) } }
35499
+ );
35500
+ totalSucceeded++;
35501
+ logger.info(
35502
+ ` \u2713 ${report.stackName}/${outcome.logicalId} (${outcome.resourceType}): reverted.`
35503
+ );
35504
+ } catch (err) {
35505
+ totalFailed++;
35506
+ const msg = err instanceof Error ? err.message : String(err);
35507
+ logger.error(
35508
+ ` \u2717 ${report.stackName}/${outcome.logicalId} (${outcome.resourceType}): ${msg}`
35509
+ );
35510
+ }
35511
+ });
35512
+ await runWithConcurrency(tasks, concurrency);
35513
+ } finally {
35514
+ await lockManager.releaseLock(report.stackName, report.region).catch((err) => {
35515
+ logger.warn(
35516
+ `Failed to release lock for ${report.stackName} (${report.region}): ` + (err instanceof Error ? err.message : String(err))
35517
+ );
35518
+ });
35519
+ }
35520
+ }
35521
+ logger.info(`
35522
+ Revert summary: ${totalSucceeded} reverted, ${totalFailed} failed.`);
35523
+ if (totalFailed > 0) {
35524
+ throw new PartialFailureError(
35525
+ `Revert completed with ${totalFailed} resource error(s). Re-run 'cdkd drift <stack>' to see the remaining drift, then 'cdkd drift <stack> --revert' to retry.`
35526
+ );
35527
+ }
35528
+ }
35529
+ function printAcceptPlan(reports) {
35530
+ for (const report of reports) {
35531
+ const drifted = report.outcomes.filter(
35532
+ (o) => o.kind === "drifted"
35533
+ );
35534
+ if (drifted.length === 0)
35535
+ continue;
35536
+ process.stdout.write(
35537
+ `
35538
+ Plan (--accept): update cdkd state for ${report.stackName} (${report.region}):
35539
+ `
35540
+ );
35541
+ for (const o of drifted) {
35542
+ process.stdout.write(` ~ ${o.logicalId} (${o.resourceType})
35543
+ `);
35544
+ for (const change of o.changes) {
35545
+ process.stdout.write(
35546
+ ` ${change.path}: ${formatScalar(change.stateValue)} -> ${formatScalar(change.awsValue)}
35547
+ `
35548
+ );
35549
+ }
35550
+ }
35551
+ }
35552
+ }
35553
+ function printRevertPlan(reports) {
35554
+ for (const report of reports) {
35555
+ const drifted = report.outcomes.filter(
35556
+ (o) => o.kind === "drifted"
35557
+ );
35558
+ if (drifted.length === 0)
35559
+ continue;
35560
+ process.stdout.write(
35561
+ `
35562
+ Plan (--revert): push cdkd state values back into AWS for ${report.stackName} (${report.region}):
35563
+ `
35564
+ );
35565
+ for (const o of drifted) {
35566
+ const word = o.changes.length === 1 ? "property path" : "property paths";
35567
+ process.stdout.write(
35568
+ ` \u2192 provider.update on ${o.logicalId} (${o.resourceType}): revert ${o.changes.length} ${word}
35569
+ `
35570
+ );
35571
+ for (const change of o.changes) {
35572
+ process.stdout.write(
35573
+ ` ${change.path}: ${formatScalar(change.awsValue)} -> ${formatScalar(change.stateValue)}
35574
+ `
35575
+ );
35576
+ }
35577
+ }
35578
+ }
35579
+ }
35580
+ async function runWithConcurrency(tasks, concurrency) {
35581
+ const queue = [...tasks];
35582
+ const workers = [];
35583
+ for (let i = 0; i < Math.min(concurrency, queue.length); i++) {
35584
+ workers.push(
35585
+ (async () => {
35586
+ while (queue.length > 0) {
35587
+ const task = queue.shift();
35588
+ if (!task)
35589
+ break;
35590
+ await task();
35591
+ }
35592
+ })()
35593
+ );
35594
+ }
35595
+ await Promise.all(workers);
35596
+ }
35597
+ async function confirmPrompt(prompt) {
35598
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
35599
+ try {
35600
+ const ans = await rl.question(`${prompt} [y/N] `);
35601
+ return /^y(es)?$/i.test(ans.trim());
35602
+ } finally {
35603
+ rl.close();
35604
+ }
35605
+ }
34298
35606
  function writeJsonReport(reports) {
34299
35607
  const payload = reports.map((r) => {
34300
35608
  const drifted = r.outcomes.filter((o) => o.kind === "drifted").map((o) => ({ logicalId: o.logicalId, type: o.resourceType, changes: o.changes }));
@@ -34371,8 +35679,25 @@ function stackRegionOption() {
34371
35679
  }
34372
35680
  function createDriftCommand() {
34373
35681
  const cmd = new Command6("drift").description(
34374
- "Detect drift between cdkd state and AWS reality. Exits 0 when no drift, 1 when drift is detected."
34375
- ).argument("[stacks...]", "Stack name(s) to check (physical CloudFormation names)").option("--all", "Check every stack in the state bucket", false).option("--json", "Output as JSON", false).addOption(stackRegionOption()).action(withErrorHandling(driftCommand));
35682
+ "Detect drift between cdkd state and AWS reality. Exits 0 when no drift, 1 when drift is detected. Pass --accept to update cdkd state from AWS, or --revert to push cdkd state values back into AWS."
35683
+ ).argument("[stacks...]", "Stack name(s) to check (physical CloudFormation names)").option("--all", "Check every stack in the state bucket", false).option("--json", "Output as JSON", false).option(
35684
+ "--accept",
35685
+ "Update cdkd state with the AWS-current values for every drifted property (state \u2190 AWS). Mutually exclusive with --revert.",
35686
+ false
35687
+ ).option(
35688
+ "--revert",
35689
+ "Push cdkd state values back into AWS via provider.update for every drifted resource (AWS \u2190 state). Mutually exclusive with --accept.",
35690
+ false
35691
+ ).option(
35692
+ "--dry-run",
35693
+ "Print the planned mutations without acquiring a lock or hitting AWS / S3. Honored by --accept and --revert.",
35694
+ false
35695
+ ).option(
35696
+ "--concurrency <number>",
35697
+ "Maximum concurrent provider.update calls during --revert",
35698
+ (value) => parseInt(value, 10),
35699
+ 4
35700
+ ).addOption(stackRegionOption()).action(withErrorHandling(driftCommand));
34376
35701
  [...commonOptions, ...stateOptions].forEach((opt) => cmd.addOption(opt));
34377
35702
  cmd.addOption(deprecatedRegionOption);
34378
35703
  return cmd;
@@ -34383,7 +35708,7 @@ import { Command as Command7 } from "commander";
34383
35708
  init_aws_clients();
34384
35709
 
34385
35710
  // src/cli/commands/destroy-runner.ts
34386
- import * as readline from "node:readline/promises";
35711
+ import * as readline2 from "node:readline/promises";
34387
35712
  init_aws_clients();
34388
35713
  async function runDestroyForStack(stackName, state, ctx) {
34389
35714
  const logger = getLogger();
@@ -34409,7 +35734,7 @@ Resources to be deleted (${resourceCount}):`);
34409
35734
  logger.info(` - ${logicalId} (${resource.resourceType})`);
34410
35735
  }
34411
35736
  if (!ctx.skipConfirmation) {
34412
- const rl = readline.createInterface({
35737
+ const rl = readline2.createInterface({
34413
35738
  input: process.stdin,
34414
35739
  output: process.stdout
34415
35740
  });
@@ -34820,7 +36145,7 @@ function createDestroyCommand() {
34820
36145
  }
34821
36146
 
34822
36147
  // src/cli/commands/orphan.ts
34823
- import * as readline2 from "node:readline/promises";
36148
+ import * as readline3 from "node:readline/promises";
34824
36149
  import { Command as Command8 } from "commander";
34825
36150
  init_aws_clients();
34826
36151
 
@@ -35353,7 +36678,7 @@ Re-run with --force to fall back to cached attribute values from state, or fix t
35353
36678
  return;
35354
36679
  }
35355
36680
  if (!options.yes && !options.force) {
35356
- const ok = await confirmPrompt(
36681
+ const ok = await confirmPrompt2(
35357
36682
  `Orphan ${orphanLogicalIds.length} resource(s) from cdkd state for ${stackInfo.stackName} (${targetRegion})? AWS resources will NOT be deleted.`
35358
36683
  );
35359
36684
  if (!ok) {
@@ -35492,8 +36817,8 @@ function stringifyForAudit(value) {
35492
36817
  return JSON.stringify(value);
35493
36818
  return JSON.stringify(value);
35494
36819
  }
35495
- async function confirmPrompt(prompt) {
35496
- const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
36820
+ async function confirmPrompt2(prompt) {
36821
+ const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
35497
36822
  try {
35498
36823
  const ans = await rl.question(`${prompt} [y/N] `);
35499
36824
  return /^y(es)?$/i.test(ans.trim());
@@ -35768,7 +37093,7 @@ function createForceUnlockCommand() {
35768
37093
  }
35769
37094
 
35770
37095
  // src/cli/commands/state.ts
35771
- import * as readline4 from "node:readline/promises";
37096
+ import * as readline5 from "node:readline/promises";
35772
37097
  import { Command as Command12, Option as Option6 } from "commander";
35773
37098
  import {
35774
37099
  GetBucketLocationCommand as GetBucketLocationCommand2,
@@ -35778,7 +37103,7 @@ import {
35778
37103
  init_aws_clients();
35779
37104
 
35780
37105
  // src/cli/commands/state-migrate.ts
35781
- import * as readline3 from "node:readline/promises";
37106
+ import * as readline4 from "node:readline/promises";
35782
37107
  import { Command as Command11 } from "commander";
35783
37108
  import {
35784
37109
  CopyObjectCommand,
@@ -35848,7 +37173,7 @@ async function stateMigrateCommand(options) {
35848
37173
  }
35849
37174
  if (!options.yes) {
35850
37175
  const action = options.removeLegacy ? "and DELETE the source bucket" : "(source bucket will be kept)";
35851
- const ok = await confirmPrompt2(
37176
+ const ok = await confirmPrompt3(
35852
37177
  `Copy ${sourceObjects.length} object(s) from ${legacyBucket} -> ${newBucket} ${action}?`
35853
37178
  );
35854
37179
  if (!ok) {
@@ -36053,8 +37378,8 @@ async function emptyBucketAllVersions(s3, bucket) {
36053
37378
  versionIdMarker = resp.NextVersionIdMarker;
36054
37379
  } while (keyMarker || versionIdMarker);
36055
37380
  }
36056
- async function confirmPrompt2(prompt) {
36057
- const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
37381
+ async function confirmPrompt3(prompt) {
37382
+ const rl = readline4.createInterface({ input: process.stdin, output: process.stdout });
36058
37383
  try {
36059
37384
  const ans = await rl.question(`${prompt} [y/N] `);
36060
37385
  return /^y(es)?$/i.test(ans.trim());
@@ -36462,7 +37787,7 @@ Use 'cdkd destroy ${stackName}' if you want to delete the actual resources.
36462
37787
 
36463
37788
  `
36464
37789
  );
36465
- const rl = readline4.createInterface({
37790
+ const rl = readline5.createInterface({
36466
37791
  input: process.stdin,
36467
37792
  output: process.stdout
36468
37793
  });
@@ -36553,7 +37878,7 @@ WARNING: This destroys ${stackNames.length} stack(s) and removes their state rec
36553
37878
  `);
36554
37879
  }
36555
37880
  process.stdout.write("\n");
36556
- const rl = readline4.createInterface({
37881
+ const rl = readline5.createInterface({
36557
37882
  input: process.stdin,
36558
37883
  output: process.stdout
36559
37884
  });
@@ -36795,12 +38120,12 @@ function createStateCommand() {
36795
38120
 
36796
38121
  // src/cli/commands/import.ts
36797
38122
  import { readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "node:fs";
36798
- import * as readline6 from "node:readline/promises";
38123
+ import * as readline7 from "node:readline/promises";
36799
38124
  import { Command as Command13 } from "commander";
36800
38125
  init_aws_clients();
36801
38126
 
36802
38127
  // src/cli/commands/retire-cfn-stack.ts
36803
- import * as readline5 from "node:readline/promises";
38128
+ import * as readline6 from "node:readline/promises";
36804
38129
  import {
36805
38130
  DescribeStacksCommand,
36806
38131
  DescribeStackResourcesCommand,
@@ -36845,7 +38170,7 @@ async function retireCloudFormationStack(options) {
36845
38170
  }
36846
38171
  const { body: newBody, modified } = injectRetainPolicies(tpl.TemplateBody, cfnStackName);
36847
38172
  if (!yes) {
36848
- const ok = await confirmPrompt3(
38173
+ const ok = await confirmPrompt4(
36849
38174
  `Set DeletionPolicy=Retain and UpdateReplacePolicy=Retain on every resource in CloudFormation stack '${cfnStackName}', then delete the stack? AWS resources will NOT be deleted (cdkd state has been written).`
36850
38175
  );
36851
38176
  if (!ok) {
@@ -37005,8 +38330,8 @@ async function getCloudFormationResourceMapping(cfnStackName, cfnClient) {
37005
38330
  }
37006
38331
  return map;
37007
38332
  }
37008
- async function confirmPrompt3(prompt) {
37009
- const rl = readline5.createInterface({ input: process.stdin, output: process.stdout });
38333
+ async function confirmPrompt4(prompt) {
38334
+ const rl = readline6.createInterface({ input: process.stdin, output: process.stdout });
37010
38335
  try {
37011
38336
  const ans = await rl.question(`${prompt} [y/N] `);
37012
38337
  return /^y(es)?$/i.test(ans.trim());
@@ -37205,7 +38530,7 @@ async function importCommand(stackArg, options) {
37205
38530
  const preservedCount = selectiveMode && existingState ? Object.keys(existingState.resources).filter((id) => !overrides.has(id)).length : 0;
37206
38531
  const totalAfter = importedCount + preservedCount;
37207
38532
  const breakdown = preservedCount > 0 ? ` (${importedCount} new/overwritten + ${preservedCount} preserved)` : "";
37208
- const ok = await confirmPrompt4(
38533
+ const ok = await confirmPrompt5(
37209
38534
  `Write state for ${stackInfo.stackName} (${targetRegion}) with ${totalAfter} resource(s)${breakdown}?`
37210
38535
  );
37211
38536
  if (!ok) {
@@ -37466,8 +38791,8 @@ function formatOutcome(outcome) {
37466
38791
  return "\u2717";
37467
38792
  }
37468
38793
  }
37469
- async function confirmPrompt4(prompt) {
37470
- const rl = readline6.createInterface({ input: process.stdin, output: process.stdout });
38794
+ async function confirmPrompt5(prompt) {
38795
+ const rl = readline7.createInterface({ input: process.stdin, output: process.stdout });
37471
38796
  try {
37472
38797
  const ans = await rl.question(`${prompt} [y/N] `);
37473
38798
  return /^y(es)?$/i.test(ans.trim());
@@ -37544,7 +38869,7 @@ function reorderArgs(argv) {
37544
38869
  }
37545
38870
  async function main() {
37546
38871
  const program = new Command14();
37547
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.37.0");
38872
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.39.0");
37548
38873
  program.addCommand(createBootstrapCommand());
37549
38874
  program.addCommand(createSynthCommand());
37550
38875
  program.addCommand(createListCommand());