@go-to-k/cdkd 0.39.0 → 0.41.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
@@ -9747,6 +9747,42 @@ var IAMInstanceProfileProvider = class {
9747
9747
  );
9748
9748
  }
9749
9749
  }
9750
+ /**
9751
+ * Read the AWS-current IAM instance profile configuration in CFn-property
9752
+ * shape.
9753
+ *
9754
+ * Issues a single `GetInstanceProfile` and surfaces the keys `create()`
9755
+ * accepts (`InstanceProfileName`, `Path`, `Roles`). The Roles list maps
9756
+ * the inline `Role[]` (each carrying `{RoleName, Arn, ...}`) back to the
9757
+ * `string[]` of role names that CFn / cdkd state holds.
9758
+ *
9759
+ * Returns `undefined` when the profile is gone (`NoSuchEntityException`).
9760
+ */
9761
+ async readCurrentState(physicalId, _logicalId, _resourceType) {
9762
+ let profile;
9763
+ try {
9764
+ const resp = await this.iamClient.send(
9765
+ new GetInstanceProfileCommand({ InstanceProfileName: physicalId })
9766
+ );
9767
+ profile = resp.InstanceProfile;
9768
+ } catch (err) {
9769
+ if (err instanceof NoSuchEntityException3)
9770
+ return void 0;
9771
+ throw err;
9772
+ }
9773
+ if (!profile)
9774
+ return void 0;
9775
+ const result = {};
9776
+ if (profile.InstanceProfileName !== void 0) {
9777
+ result["InstanceProfileName"] = profile.InstanceProfileName;
9778
+ }
9779
+ if (profile.Path !== void 0)
9780
+ result["Path"] = profile.Path;
9781
+ const roleNames = (profile.Roles ?? []).map((r) => r.RoleName).filter((n) => !!n);
9782
+ if (roleNames.length > 0)
9783
+ result["Roles"] = roleNames;
9784
+ return result;
9785
+ }
9750
9786
  /**
9751
9787
  * Adopt an existing IAM instance profile into cdkd state.
9752
9788
  *
@@ -10799,6 +10835,123 @@ var IAMUserGroupProvider = class {
10799
10835
  );
10800
10836
  }
10801
10837
  }
10838
+ // ─── readCurrentState dispatch ───────────────────────────────────
10839
+ /**
10840
+ * Read the AWS-current configuration for an IAM user / group /
10841
+ * UserToGroupAddition in CFn-property shape.
10842
+ *
10843
+ * - **AWS::IAM::User**: `GetUser` for `UserName`, `Path`,
10844
+ * `PermissionsBoundary` (re-shaped from `PermissionsBoundary.Arn`);
10845
+ * `ListAttachedUserPolicies` for `ManagedPolicyArns`;
10846
+ * `ListGroupsForUser` for `Groups`. `Tags`, `LoginProfile`, and
10847
+ * `Policies` (inline policy bodies) are intentionally omitted —
10848
+ * same shape decisions as `iam-role-provider` (LoginProfile contains a
10849
+ * one-time password and inline policy bodies cost N extra round-trips
10850
+ * that are out of scope for v1).
10851
+ * - **AWS::IAM::Group**: `GetGroup` for `GroupName`, `Path`;
10852
+ * `ListAttachedGroupPolicies` for `ManagedPolicyArns`. `Policies`
10853
+ * (inline policy bodies) is omitted for the same reason as User /
10854
+ * Role.
10855
+ * - **AWS::IAM::UserToGroupAddition**: SKIPPED — returns `undefined`
10856
+ * because the resource is metadata-only (group-membership attachments
10857
+ * written via `AddUserToGroup`). A meaningful drift check would
10858
+ * require both the `GroupName` and the source-of-truth `Users` list
10859
+ * from state, neither of which `readCurrentState` receives. The
10860
+ * drift comparator falls back to "drift unknown" and the user can
10861
+ * inspect the membership manually.
10862
+ *
10863
+ * Returns `undefined` when the user / group is gone
10864
+ * (`NoSuchEntityException`).
10865
+ */
10866
+ async readCurrentState(physicalId, logicalId, resourceType) {
10867
+ switch (resourceType) {
10868
+ case "AWS::IAM::User":
10869
+ return this.readUserCurrentState(physicalId);
10870
+ case "AWS::IAM::Group":
10871
+ return this.readGroupCurrentState(physicalId);
10872
+ case "AWS::IAM::UserToGroupAddition":
10873
+ return void 0;
10874
+ default:
10875
+ this.logger.debug(
10876
+ `readCurrentState: unsupported resource type ${resourceType} for ${logicalId}`
10877
+ );
10878
+ return void 0;
10879
+ }
10880
+ }
10881
+ async readUserCurrentState(physicalId) {
10882
+ let user;
10883
+ try {
10884
+ const resp = await this.iamClient.send(new GetUserCommand({ UserName: physicalId }));
10885
+ user = resp.User;
10886
+ } catch (err) {
10887
+ if (err instanceof NoSuchEntityException4)
10888
+ return void 0;
10889
+ throw err;
10890
+ }
10891
+ if (!user)
10892
+ return void 0;
10893
+ const result = {};
10894
+ if (user.UserName !== void 0)
10895
+ result["UserName"] = user.UserName;
10896
+ if (user.Path !== void 0)
10897
+ result["Path"] = user.Path;
10898
+ if (user.PermissionsBoundary?.PermissionsBoundaryArn !== void 0) {
10899
+ result["PermissionsBoundary"] = user.PermissionsBoundary.PermissionsBoundaryArn;
10900
+ }
10901
+ try {
10902
+ const attached = await this.iamClient.send(
10903
+ new ListAttachedUserPoliciesCommand({ UserName: physicalId })
10904
+ );
10905
+ const arns = (attached.AttachedPolicies ?? []).map((p) => p.PolicyArn).filter((arn) => !!arn);
10906
+ if (arns.length > 0)
10907
+ result["ManagedPolicyArns"] = arns;
10908
+ } catch (err) {
10909
+ if (!(err instanceof NoSuchEntityException4))
10910
+ throw err;
10911
+ }
10912
+ try {
10913
+ const groups = await this.iamClient.send(
10914
+ new ListGroupsForUserCommand({ UserName: physicalId })
10915
+ );
10916
+ const names = (groups.Groups ?? []).map((g) => g.GroupName).filter((n) => !!n);
10917
+ if (names.length > 0)
10918
+ result["Groups"] = names;
10919
+ } catch (err) {
10920
+ if (!(err instanceof NoSuchEntityException4))
10921
+ throw err;
10922
+ }
10923
+ return result;
10924
+ }
10925
+ async readGroupCurrentState(physicalId) {
10926
+ let group;
10927
+ try {
10928
+ const resp = await this.iamClient.send(new GetGroupCommand({ GroupName: physicalId }));
10929
+ group = resp.Group;
10930
+ } catch (err) {
10931
+ if (err instanceof NoSuchEntityException4)
10932
+ return void 0;
10933
+ throw err;
10934
+ }
10935
+ if (!group)
10936
+ return void 0;
10937
+ const result = {};
10938
+ if (group.GroupName !== void 0)
10939
+ result["GroupName"] = group.GroupName;
10940
+ if (group.Path !== void 0)
10941
+ result["Path"] = group.Path;
10942
+ try {
10943
+ const attached = await this.iamClient.send(
10944
+ new ListAttachedGroupPoliciesCommand({ GroupName: physicalId })
10945
+ );
10946
+ const arns = (attached.AttachedPolicies ?? []).map((p) => p.PolicyArn).filter((arn) => !!arn);
10947
+ if (arns.length > 0)
10948
+ result["ManagedPolicyArns"] = arns;
10949
+ } catch (err) {
10950
+ if (!(err instanceof NoSuchEntityException4))
10951
+ throw err;
10952
+ }
10953
+ return result;
10954
+ }
10802
10955
  // ─── Import dispatch ──────────────────────────────────────────────
10803
10956
  /**
10804
10957
  * Adopt an existing IAM user / group / user-to-group addition into cdkd state.
@@ -12002,6 +12155,7 @@ var S3BucketProvider = class {
12002
12155
  import {
12003
12156
  PutBucketPolicyCommand as PutBucketPolicyCommand2,
12004
12157
  DeleteBucketPolicyCommand,
12158
+ GetBucketPolicyCommand,
12005
12159
  NoSuchBucket as NoSuchBucket2
12006
12160
  } from "@aws-sdk/client-s3";
12007
12161
  init_aws_clients();
@@ -12159,6 +12313,43 @@ var S3BucketPolicyProvider = class {
12159
12313
  );
12160
12314
  }
12161
12315
  }
12316
+ /**
12317
+ * Read the AWS-current S3 bucket policy in CFn-property shape.
12318
+ *
12319
+ * Issues `GetBucketPolicy` against the bucket (physicalId === bucket
12320
+ * name) and surfaces:
12321
+ * - `Bucket` — derived directly from `physicalId`.
12322
+ * - `PolicyDocument` — JSON-parsed back to the object form cdkd state
12323
+ * typically holds.
12324
+ *
12325
+ * Returns `undefined` when the bucket is gone (`NoSuchBucket`) or when
12326
+ * no policy is currently attached (`NoSuchBucketPolicy`).
12327
+ */
12328
+ async readCurrentState(physicalId, _logicalId, _resourceType) {
12329
+ let policyJson;
12330
+ try {
12331
+ const resp = await this.s3Client.send(new GetBucketPolicyCommand({ Bucket: physicalId }));
12332
+ policyJson = resp.Policy;
12333
+ } catch (err) {
12334
+ if (err instanceof NoSuchBucket2)
12335
+ return void 0;
12336
+ const e = err;
12337
+ if (e.name === "NoSuchBucketPolicy")
12338
+ return void 0;
12339
+ throw err;
12340
+ }
12341
+ if (!policyJson)
12342
+ return void 0;
12343
+ const result = {
12344
+ Bucket: physicalId
12345
+ };
12346
+ try {
12347
+ result["PolicyDocument"] = JSON.parse(policyJson);
12348
+ } catch {
12349
+ result["PolicyDocument"] = policyJson;
12350
+ }
12351
+ return result;
12352
+ }
12162
12353
  /**
12163
12354
  * Adopt an existing S3 bucket policy into cdkd state.
12164
12355
  *
@@ -12582,7 +12773,10 @@ var SQSQueueProvider = class {
12582
12773
  };
12583
12774
 
12584
12775
  // src/provisioning/providers/sqs-queue-policy-provider.ts
12585
- import { SetQueueAttributesCommand as SetQueueAttributesCommand2 } from "@aws-sdk/client-sqs";
12776
+ import {
12777
+ SetQueueAttributesCommand as SetQueueAttributesCommand2,
12778
+ GetQueueAttributesCommand as GetQueueAttributesCommand2
12779
+ } from "@aws-sdk/client-sqs";
12586
12780
  init_aws_clients();
12587
12781
  var SQSQueuePolicyProvider = class {
12588
12782
  sqsClient;
@@ -12735,6 +12929,52 @@ var SQSQueuePolicyProvider = class {
12735
12929
  );
12736
12930
  }
12737
12931
  }
12932
+ /**
12933
+ * Read the AWS-current SQS queue policy in CFn-property shape.
12934
+ *
12935
+ * The provider's `create()` records `physicalId` as the first queue URL
12936
+ * in the `Queues` array. Drift here surfaces:
12937
+ * - `Queues` — single-element array containing `physicalId`. The full
12938
+ * state list of queues isn't recoverable from AWS (no reverse index)
12939
+ * and the comparator only descends into keys present in state, so a
12940
+ * state with multiple queues will still surface drift on
12941
+ * `PolicyDocument` for the first queue (the most common drift case).
12942
+ * - `PolicyDocument` — fetched via `GetQueueAttributes` for
12943
+ * `Policy`, JSON-parsed back to the object form cdkd state holds.
12944
+ *
12945
+ * Returns `undefined` when the queue is gone (`QueueDoesNotExist`) or
12946
+ * when no policy is currently attached (the `Policy` attribute is
12947
+ * absent / empty).
12948
+ */
12949
+ async readCurrentState(physicalId, _logicalId, _resourceType) {
12950
+ let policyAttr;
12951
+ try {
12952
+ const resp = await this.sqsClient.send(
12953
+ new GetQueueAttributesCommand2({
12954
+ QueueUrl: physicalId,
12955
+ AttributeNames: ["Policy"]
12956
+ })
12957
+ );
12958
+ policyAttr = resp.Attributes?.["Policy"];
12959
+ } catch (err) {
12960
+ const e = err;
12961
+ if (e.name === "QueueDoesNotExist" || typeof e.message === "string" && e.message.includes("does not exist")) {
12962
+ return void 0;
12963
+ }
12964
+ throw err;
12965
+ }
12966
+ if (!policyAttr)
12967
+ return void 0;
12968
+ const result = {
12969
+ Queues: [physicalId]
12970
+ };
12971
+ try {
12972
+ result["PolicyDocument"] = JSON.parse(policyAttr);
12973
+ } catch {
12974
+ result["PolicyDocument"] = policyAttr;
12975
+ }
12976
+ return result;
12977
+ }
12738
12978
  /**
12739
12979
  * Adopt an existing SQS queue policy into cdkd state.
12740
12980
  *
@@ -13207,6 +13447,7 @@ var SNSTopicProvider = class {
13207
13447
  import {
13208
13448
  SubscribeCommand,
13209
13449
  UnsubscribeCommand,
13450
+ GetSubscriptionAttributesCommand,
13210
13451
  NotFoundException as NotFoundException2
13211
13452
  } from "@aws-sdk/client-sns";
13212
13453
  init_aws_clients();
@@ -13338,6 +13579,52 @@ var SNSSubscriptionProvider = class {
13338
13579
  );
13339
13580
  }
13340
13581
  }
13582
+ /**
13583
+ * Read the AWS-current SNS Subscription configuration in CFn-property shape.
13584
+ *
13585
+ * Issues `GetSubscriptionAttributes`. AWS returns ALL attribute values
13586
+ * as strings; we type-coerce `RawMessageDelivery` to a boolean and
13587
+ * JSON-parse `FilterPolicy` so the comparator matches cdkd state's
13588
+ * already-typed values. `TopicArn`, `Protocol`, `Endpoint` pass through
13589
+ * as strings.
13590
+ *
13591
+ * Returns `undefined` when the subscription is gone (`NotFoundException`),
13592
+ * including the special "PendingConfirmation" case where the
13593
+ * `SubscriptionArn` has not yet been confirmed and `Attributes` is null.
13594
+ */
13595
+ async readCurrentState(physicalId, _logicalId, _resourceType) {
13596
+ let attributes;
13597
+ try {
13598
+ const resp = await this.snsClient.send(
13599
+ new GetSubscriptionAttributesCommand({ SubscriptionArn: physicalId })
13600
+ );
13601
+ attributes = resp.Attributes;
13602
+ } catch (err) {
13603
+ if (err instanceof NotFoundException2)
13604
+ return void 0;
13605
+ throw err;
13606
+ }
13607
+ if (!attributes)
13608
+ return void 0;
13609
+ const result = {};
13610
+ if (attributes["TopicArn"] !== void 0)
13611
+ result["TopicArn"] = attributes["TopicArn"];
13612
+ if (attributes["Protocol"] !== void 0)
13613
+ result["Protocol"] = attributes["Protocol"];
13614
+ if (attributes["Endpoint"] !== void 0)
13615
+ result["Endpoint"] = attributes["Endpoint"];
13616
+ if (attributes["RawMessageDelivery"] !== void 0) {
13617
+ result["RawMessageDelivery"] = attributes["RawMessageDelivery"] === "true";
13618
+ }
13619
+ if (attributes["FilterPolicy"]) {
13620
+ try {
13621
+ result["FilterPolicy"] = JSON.parse(attributes["FilterPolicy"]);
13622
+ } catch {
13623
+ result["FilterPolicy"] = attributes["FilterPolicy"];
13624
+ }
13625
+ }
13626
+ return result;
13627
+ }
13341
13628
  /**
13342
13629
  * Adopt an existing SNS subscription into cdkd state.
13343
13630
  *
@@ -13360,7 +13647,7 @@ var SNSSubscriptionProvider = class {
13360
13647
  };
13361
13648
 
13362
13649
  // src/provisioning/providers/sns-topic-policy-provider.ts
13363
- import { SetTopicAttributesCommand as SetTopicAttributesCommand2 } from "@aws-sdk/client-sns";
13650
+ import { SetTopicAttributesCommand as SetTopicAttributesCommand2, GetTopicAttributesCommand as GetTopicAttributesCommand2 } from "@aws-sdk/client-sns";
13364
13651
  init_aws_clients();
13365
13652
  var SNSTopicPolicyProvider = class {
13366
13653
  logger = getLogger().child("SNSTopicPolicyProvider");
@@ -13496,6 +13783,57 @@ var SNSTopicPolicyProvider = class {
13496
13783
  }
13497
13784
  this.logger.debug(`Successfully deleted SNS topic policy ${logicalId}`);
13498
13785
  }
13786
+ /**
13787
+ * Read the AWS-current SNS topic policy in CFn-property shape.
13788
+ *
13789
+ * The provider's `create()` builds `physicalId` as a comma-joined list
13790
+ * of topic ARNs. We:
13791
+ * 1. Split the physical id back into the list of topic ARNs and surface
13792
+ * them as `Topics` (matching `create()` shape).
13793
+ * 2. Fetch `GetTopicAttributes` on the FIRST topic to retrieve the
13794
+ * `Policy` attribute and surface it as `PolicyDocument` (JSON-parsed
13795
+ * to match the object form cdkd state holds).
13796
+ *
13797
+ * Single-topic fetch is intentional: cdkd applies the same policy to
13798
+ * every topic in `Topics`, so the body is the same on each. A future
13799
+ * enhancement could verify per-topic that the policy actually matches
13800
+ * (catches manual divergence between multiple targets), but the bulk of
13801
+ * drift cases involve a single topic and the body content is what users
13802
+ * actually care about.
13803
+ *
13804
+ * Returns `undefined` when no topics are listed in the physical id, or
13805
+ * when the first listed topic is gone (`NotFoundException`).
13806
+ */
13807
+ async readCurrentState(physicalId, _logicalId, _resourceType) {
13808
+ const topics = physicalId.split(",").filter((t) => t.length > 0);
13809
+ if (topics.length === 0)
13810
+ return void 0;
13811
+ const firstTopic = topics[0];
13812
+ let policyAttr;
13813
+ try {
13814
+ const resp = await getAwsClients().sns.send(
13815
+ new GetTopicAttributesCommand2({ TopicArn: firstTopic })
13816
+ );
13817
+ policyAttr = resp.Attributes?.["Policy"];
13818
+ } catch (err) {
13819
+ const e = err;
13820
+ if (e.name === "NotFoundException" || e.name === "NotFound" || typeof e.message === "string" && e.message.includes("does not exist")) {
13821
+ return void 0;
13822
+ }
13823
+ throw err;
13824
+ }
13825
+ const result = {
13826
+ Topics: topics
13827
+ };
13828
+ if (policyAttr) {
13829
+ try {
13830
+ result["PolicyDocument"] = JSON.parse(policyAttr);
13831
+ } catch {
13832
+ result["PolicyDocument"] = policyAttr;
13833
+ }
13834
+ }
13835
+ return result;
13836
+ }
13499
13837
  /**
13500
13838
  * Adopt an existing SNS topic policy into cdkd state.
13501
13839
  *
@@ -14746,6 +15084,66 @@ var LambdaUrlProvider = class {
14746
15084
  throw err;
14747
15085
  }
14748
15086
  }
15087
+ /**
15088
+ * Read the AWS-current Lambda Function URL configuration in CFn-property
15089
+ * shape.
15090
+ *
15091
+ * Issues `GetFunctionUrlConfig` with the parent function's ARN/name (the
15092
+ * physical id) and surfaces `AuthType`, `InvokeMode`, and `Cors`.
15093
+ * AWS-managed fields (`FunctionUrl`, `FunctionArn`, `CreationTime`,
15094
+ * `LastModifiedTime`) are filtered at the wire layer.
15095
+ *
15096
+ * `TargetFunctionArn` is surfaced from `physicalId` (the create() flow
15097
+ * stores the parent function's ARN/name there). `Qualifier` is NOT
15098
+ * available from `GetFunctionUrlConfig` (it's only an input on Create);
15099
+ * cdkd state stores it but AWS does not surface it back, so we omit it
15100
+ * from the snapshot — the comparator's "key absent in state never
15101
+ * drifts" rule handles the omission cleanly when state lacks Qualifier
15102
+ * too, and cases where state HAS Qualifier surface as drift only when
15103
+ * the qualifier was changed via Update (which the SDK supports through
15104
+ * `physicalId` rather than the qualifier itself).
15105
+ *
15106
+ * Returns `undefined` when the URL config is gone
15107
+ * (`ResourceNotFoundException`).
15108
+ */
15109
+ async readCurrentState(physicalId, _logicalId, _resourceType) {
15110
+ let resp;
15111
+ try {
15112
+ resp = await this.lambdaClient.send(
15113
+ new GetFunctionUrlConfigCommand2({ FunctionName: physicalId })
15114
+ );
15115
+ } catch (err) {
15116
+ if (err instanceof ResourceNotFoundException3)
15117
+ return void 0;
15118
+ throw err;
15119
+ }
15120
+ const result = {
15121
+ TargetFunctionArn: physicalId
15122
+ };
15123
+ if (resp.AuthType !== void 0)
15124
+ result["AuthType"] = resp.AuthType;
15125
+ if (resp.InvokeMode !== void 0)
15126
+ result["InvokeMode"] = resp.InvokeMode;
15127
+ if (resp.Cors !== void 0) {
15128
+ const cors = {};
15129
+ if (resp.Cors.AllowOrigins)
15130
+ cors["AllowOrigins"] = [...resp.Cors.AllowOrigins];
15131
+ if (resp.Cors.AllowMethods)
15132
+ cors["AllowMethods"] = [...resp.Cors.AllowMethods];
15133
+ if (resp.Cors.AllowHeaders)
15134
+ cors["AllowHeaders"] = [...resp.Cors.AllowHeaders];
15135
+ if (resp.Cors.ExposeHeaders)
15136
+ cors["ExposeHeaders"] = [...resp.Cors.ExposeHeaders];
15137
+ if (resp.Cors.MaxAge !== void 0)
15138
+ cors["MaxAge"] = resp.Cors.MaxAge;
15139
+ if (resp.Cors.AllowCredentials !== void 0) {
15140
+ cors["AllowCredentials"] = resp.Cors.AllowCredentials;
15141
+ }
15142
+ if (Object.keys(cors).length > 0)
15143
+ result["Cors"] = cors;
15144
+ }
15145
+ return result;
15146
+ }
14749
15147
  /**
14750
15148
  * Adopt an existing Lambda Function URL into cdkd state.
14751
15149
  *
@@ -15008,6 +15406,96 @@ var LambdaEventSourceMappingProvider = class {
15008
15406
  );
15009
15407
  }
15010
15408
  }
15409
+ /**
15410
+ * Read the AWS-current Lambda event source mapping configuration in
15411
+ * CFn-property shape.
15412
+ *
15413
+ * Issues `GetEventSourceMapping` for the UUID and surfaces the keys
15414
+ * `create()` accepts. AWS-managed fields (`UUID`, `LastModified`,
15415
+ * `LastProcessingResult`, `State`, `StateTransitionReason`,
15416
+ * `EventSourceMappingArn`) are filtered at the wire layer.
15417
+ *
15418
+ * `FunctionName` is surfaced as the AWS `FunctionArn` (which is what
15419
+ * `GetEventSourceMapping` returns) — cdkd state typically holds this
15420
+ * resolved ARN form already after intrinsic resolution. The drift
15421
+ * comparator can match against both forms when state holds a name vs an
15422
+ * ARN; mismatched-shape false positives are out of scope for v1.
15423
+ *
15424
+ * `Tags` is omitted: cdkd `create()` reshapes CFn tag arrays into a
15425
+ * tags map at create time, but `GetEventSourceMapping` does not return
15426
+ * tags (`ListTags(Resource: arn)` does). Same shape-decision rationale
15427
+ * as Lambda function tags drift — out of scope for v1.
15428
+ *
15429
+ * Returns `undefined` when the mapping is gone
15430
+ * (`ResourceNotFoundException`).
15431
+ */
15432
+ async readCurrentState(physicalId, _logicalId, _resourceType) {
15433
+ let resp;
15434
+ try {
15435
+ resp = await this.lambdaClient.send(new GetEventSourceMappingCommand({ UUID: physicalId }));
15436
+ } catch (err) {
15437
+ if (err instanceof ResourceNotFoundException4)
15438
+ return void 0;
15439
+ throw err;
15440
+ }
15441
+ const result = {};
15442
+ if (resp.FunctionArn !== void 0)
15443
+ result["FunctionName"] = resp.FunctionArn;
15444
+ if (resp.EventSourceArn !== void 0)
15445
+ result["EventSourceArn"] = resp.EventSourceArn;
15446
+ if (resp.BatchSize !== void 0)
15447
+ result["BatchSize"] = resp.BatchSize;
15448
+ if (resp.StartingPosition !== void 0)
15449
+ result["StartingPosition"] = resp.StartingPosition;
15450
+ if (resp.MaximumBatchingWindowInSeconds !== void 0) {
15451
+ result["MaximumBatchingWindowInSeconds"] = resp.MaximumBatchingWindowInSeconds;
15452
+ }
15453
+ if (resp.MaximumRetryAttempts !== void 0) {
15454
+ result["MaximumRetryAttempts"] = resp.MaximumRetryAttempts;
15455
+ }
15456
+ if (resp.BisectBatchOnFunctionError !== void 0) {
15457
+ result["BisectBatchOnFunctionError"] = resp.BisectBatchOnFunctionError;
15458
+ }
15459
+ if (resp.MaximumRecordAgeInSeconds !== void 0) {
15460
+ result["MaximumRecordAgeInSeconds"] = resp.MaximumRecordAgeInSeconds;
15461
+ }
15462
+ if (resp.ParallelizationFactor !== void 0) {
15463
+ result["ParallelizationFactor"] = resp.ParallelizationFactor;
15464
+ }
15465
+ if (resp.FilterCriteria !== void 0)
15466
+ result["FilterCriteria"] = resp.FilterCriteria;
15467
+ if (resp.DestinationConfig !== void 0) {
15468
+ result["DestinationConfig"] = resp.DestinationConfig;
15469
+ }
15470
+ if (resp.TumblingWindowInSeconds !== void 0) {
15471
+ result["TumblingWindowInSeconds"] = resp.TumblingWindowInSeconds;
15472
+ }
15473
+ if (resp.FunctionResponseTypes !== void 0 && resp.FunctionResponseTypes.length > 0) {
15474
+ result["FunctionResponseTypes"] = [...resp.FunctionResponseTypes];
15475
+ }
15476
+ if (resp.SourceAccessConfigurations !== void 0 && resp.SourceAccessConfigurations.length > 0) {
15477
+ result["SourceAccessConfigurations"] = resp.SourceAccessConfigurations;
15478
+ }
15479
+ if (resp.SelfManagedEventSource !== void 0) {
15480
+ result["SelfManagedEventSource"] = resp.SelfManagedEventSource;
15481
+ }
15482
+ if (resp.SelfManagedKafkaEventSourceConfig !== void 0) {
15483
+ result["SelfManagedKafkaEventSourceConfig"] = resp.SelfManagedKafkaEventSourceConfig;
15484
+ }
15485
+ if (resp.AmazonManagedKafkaEventSourceConfig !== void 0) {
15486
+ result["AmazonManagedKafkaEventSourceConfig"] = resp.AmazonManagedKafkaEventSourceConfig;
15487
+ }
15488
+ if (resp.DocumentDBEventSourceConfig !== void 0) {
15489
+ result["DocumentDBEventSourceConfig"] = resp.DocumentDBEventSourceConfig;
15490
+ }
15491
+ if (resp.ScalingConfig !== void 0)
15492
+ result["ScalingConfig"] = resp.ScalingConfig;
15493
+ if (resp.State !== void 0) {
15494
+ const enabled = resp.State === "Enabled" || resp.State === "Enabling" || resp.State === "Updating";
15495
+ result["Enabled"] = enabled;
15496
+ }
15497
+ return result;
15498
+ }
15011
15499
  /**
15012
15500
  * Adopt an existing Lambda event source mapping into cdkd state.
15013
15501
  *
@@ -15176,6 +15664,57 @@ var LambdaLayerVersionProvider = class {
15176
15664
  );
15177
15665
  }
15178
15666
  }
15667
+ /**
15668
+ * Read the AWS-current Lambda layer version configuration in CFn-property
15669
+ * shape.
15670
+ *
15671
+ * Issues `GetLayerVersionByArn` (the physical id is the version ARN) and
15672
+ * surfaces `LayerName`, `Description`, `CompatibleRuntimes`,
15673
+ * `CompatibleArchitectures`, and `LicenseInfo`. AWS-managed fields
15674
+ * (`Version`, `CreatedDate`, `LayerVersionArn`, `LayerArn`,
15675
+ * `Content.CodeSize`, `Content.CodeSha256`) are filtered at the wire
15676
+ * layer.
15677
+ *
15678
+ * `Content` is intentionally omitted: like Lambda function `Code`, the
15679
+ * `GetLayerVersionByArn` response contains a pre-signed S3 URL for the
15680
+ * deployed content, not the asset hash cdkd state stored. The two could
15681
+ * never match, so excluding it avoids a guaranteed false-positive.
15682
+ *
15683
+ * `LayerName` is derived from the ARN tail when not surfaced directly:
15684
+ * the version ARN format is
15685
+ * `arn:aws:lambda:<region>:<account>:layer:<name>:<version>`.
15686
+ *
15687
+ * Returns `undefined` when the layer version is gone
15688
+ * (`ResourceNotFoundException`).
15689
+ */
15690
+ async readCurrentState(physicalId, _logicalId, _resourceType) {
15691
+ let resp;
15692
+ try {
15693
+ resp = await this.lambdaClient.send(new GetLayerVersionByArnCommand({ Arn: physicalId }));
15694
+ } catch (err) {
15695
+ if (err instanceof ResourceNotFoundException5)
15696
+ return void 0;
15697
+ throw err;
15698
+ }
15699
+ const result = {};
15700
+ const arnParts = physicalId.split(":");
15701
+ if (arnParts.length >= 7 && arnParts[6]) {
15702
+ result["LayerName"] = arnParts[6];
15703
+ }
15704
+ if (resp.Description !== void 0 && resp.Description !== "") {
15705
+ result["Description"] = resp.Description;
15706
+ }
15707
+ if (resp.CompatibleRuntimes !== void 0 && resp.CompatibleRuntimes.length > 0) {
15708
+ result["CompatibleRuntimes"] = [...resp.CompatibleRuntimes];
15709
+ }
15710
+ if (resp.CompatibleArchitectures !== void 0 && resp.CompatibleArchitectures.length > 0) {
15711
+ result["CompatibleArchitectures"] = [...resp.CompatibleArchitectures];
15712
+ }
15713
+ if (resp.LicenseInfo !== void 0 && resp.LicenseInfo !== "") {
15714
+ result["LicenseInfo"] = resp.LicenseInfo;
15715
+ }
15716
+ return result;
15717
+ }
15179
15718
  /**
15180
15719
  * Adopt an existing Lambda layer version into cdkd state.
15181
15720
  *
@@ -16209,6 +16748,82 @@ var CloudWatchAlarmProvider = class {
16209
16748
  * 2. `DescribeAlarms` paginated, then `ListTagsForResource(AlarmArn)` per
16210
16749
  * alarm to match `aws:cdk:path`.
16211
16750
  */
16751
+ /**
16752
+ * Read the AWS-current CloudWatch Alarm configuration in CFn-property shape.
16753
+ *
16754
+ * Issues `DescribeAlarms` filtered by `AlarmNames=[physicalId]` and
16755
+ * surfaces the keys cdkd's `create()` accepts (`AlarmName`,
16756
+ * `AlarmDescription`, `MetricName`, `Namespace`, `Statistic`,
16757
+ * `ComparisonOperator`, `Threshold`, `EvaluationPeriods`, `Period`,
16758
+ * `DatapointsToAlarm`, `ActionsEnabled`, `AlarmActions`,
16759
+ * `OKActions`, `InsufficientDataActions`, `TreatMissingData`, `Unit`,
16760
+ * `Dimensions`, `Metrics`).
16761
+ *
16762
+ * `DescribeAlarms` returns the result via either `MetricAlarms` (single-
16763
+ * metric form) or `CompositeAlarms` (composite form). cdkd's provider
16764
+ * only handles the single-metric form, so we look at `MetricAlarms` only.
16765
+ *
16766
+ * Returns `undefined` when the alarm is gone (no matching `MetricAlarms`).
16767
+ */
16768
+ async readCurrentState(physicalId, _logicalId, _resourceType) {
16769
+ const resp = await this.cloudWatchClient.send(
16770
+ new DescribeAlarmsCommand({ AlarmNames: [physicalId], AlarmTypes: ["MetricAlarm"] })
16771
+ );
16772
+ const alarm = resp.MetricAlarms?.[0];
16773
+ if (!alarm)
16774
+ return void 0;
16775
+ const result = {};
16776
+ if (alarm.AlarmName !== void 0)
16777
+ result["AlarmName"] = alarm.AlarmName;
16778
+ if (alarm.AlarmDescription !== void 0 && alarm.AlarmDescription !== "") {
16779
+ result["AlarmDescription"] = alarm.AlarmDescription;
16780
+ }
16781
+ if (alarm.MetricName !== void 0)
16782
+ result["MetricName"] = alarm.MetricName;
16783
+ if (alarm.Namespace !== void 0)
16784
+ result["Namespace"] = alarm.Namespace;
16785
+ if (alarm.Statistic !== void 0)
16786
+ result["Statistic"] = alarm.Statistic;
16787
+ if (alarm.ComparisonOperator !== void 0) {
16788
+ result["ComparisonOperator"] = alarm.ComparisonOperator;
16789
+ }
16790
+ if (alarm.Threshold !== void 0)
16791
+ result["Threshold"] = alarm.Threshold;
16792
+ if (alarm.EvaluationPeriods !== void 0) {
16793
+ result["EvaluationPeriods"] = alarm.EvaluationPeriods;
16794
+ }
16795
+ if (alarm.Period !== void 0)
16796
+ result["Period"] = alarm.Period;
16797
+ if (alarm.DatapointsToAlarm !== void 0) {
16798
+ result["DatapointsToAlarm"] = alarm.DatapointsToAlarm;
16799
+ }
16800
+ if (alarm.ActionsEnabled !== void 0)
16801
+ result["ActionsEnabled"] = alarm.ActionsEnabled;
16802
+ if (alarm.AlarmActions && alarm.AlarmActions.length > 0) {
16803
+ result["AlarmActions"] = [...alarm.AlarmActions];
16804
+ }
16805
+ if (alarm.OKActions && alarm.OKActions.length > 0) {
16806
+ result["OKActions"] = [...alarm.OKActions];
16807
+ }
16808
+ if (alarm.InsufficientDataActions && alarm.InsufficientDataActions.length > 0) {
16809
+ result["InsufficientDataActions"] = [...alarm.InsufficientDataActions];
16810
+ }
16811
+ if (alarm.TreatMissingData !== void 0) {
16812
+ result["TreatMissingData"] = alarm.TreatMissingData;
16813
+ }
16814
+ if (alarm.Unit !== void 0)
16815
+ result["Unit"] = alarm.Unit;
16816
+ if (alarm.Dimensions && alarm.Dimensions.length > 0) {
16817
+ result["Dimensions"] = alarm.Dimensions.map((d) => ({
16818
+ ...d.Name !== void 0 ? { Name: d.Name } : {},
16819
+ ...d.Value !== void 0 ? { Value: d.Value } : {}
16820
+ }));
16821
+ }
16822
+ if (alarm.Metrics && alarm.Metrics.length > 0) {
16823
+ result["Metrics"] = alarm.Metrics.map((m) => m);
16824
+ }
16825
+ return result;
16826
+ }
16212
16827
  async import(input) {
16213
16828
  const explicit = resolveExplicitPhysicalId(input, "AlarmName");
16214
16829
  if (explicit) {
@@ -17777,7 +18392,10 @@ import {
17777
18392
  CreateVpcCommand,
17778
18393
  DeleteVpcCommand,
17779
18394
  ModifyVpcAttributeCommand,
18395
+ DescribeVpcAttributeCommand,
17780
18396
  DescribeVpcsCommand as DescribeVpcsCommand2,
18397
+ DescribeInternetGatewaysCommand,
18398
+ DescribeRouteTablesCommand as DescribeRouteTablesCommand2,
17781
18399
  CreateSubnetCommand,
17782
18400
  DeleteSubnetCommand,
17783
18401
  CreateInternetGatewayCommand,
@@ -19937,9 +20555,226 @@ var EC2Provider = class {
19937
20555
  throw error;
19938
20556
  }
19939
20557
  }
19940
- async verifyExplicit(resourceType, physicalId) {
19941
- try {
19942
- switch (resourceType) {
20558
+ /**
20559
+ * Read the AWS-current EC2 networking resource configuration in
20560
+ * CFn-property shape.
20561
+ *
20562
+ * Supported types (highest-value drift coverage):
20563
+ * - **AWS::EC2::VPC**: `DescribeVpcs` for `CidrBlock` + `InstanceTenancy`;
20564
+ * `DescribeVpcAttribute(enableDnsHostnames|enableDnsSupport)` for the
20565
+ * DNS booleans (CFn defaults: hostnames=false, support=true — we only
20566
+ * surface them if AWS reports them, so the comparator's "key-absent
20567
+ * never drifts" rule applies cleanly to state without these keys).
20568
+ * - **AWS::EC2::Subnet**: `DescribeSubnets` for `VpcId`, `CidrBlock`,
20569
+ * `AvailabilityZone`, `MapPublicIpOnLaunch`.
20570
+ * - **AWS::EC2::InternetGateway**: `DescribeInternetGateways` for
20571
+ * existence verification. The provider only handles `Tags`, which is
20572
+ * out of scope for v1 drift.
20573
+ * - **AWS::EC2::NatGateway**: `DescribeNatGateways` for `SubnetId`,
20574
+ * `AllocationId`, `ConnectivityType`, `PrivateIpAddress`.
20575
+ * - **AWS::EC2::RouteTable**: `DescribeRouteTables` for `VpcId`.
20576
+ * - **AWS::EC2::SecurityGroup**: `DescribeSecurityGroups` for
20577
+ * `GroupName`, `GroupDescription`, `VpcId`. Ingress / egress rules
20578
+ * are NOT surfaced — the CFn shape is rule-list-style, while AWS
20579
+ * returns IpPermissions in a different normalized form, and a
20580
+ * faithful reverse-mapping is out of scope for v1.
20581
+ * - **AWS::EC2::Instance**: `DescribeInstances` for `ImageId`,
20582
+ * `InstanceType`, `KeyName`, `SubnetId`. SecurityGroupIds /
20583
+ * BlockDeviceMappings shape-match is out of scope for v1.
20584
+ * - **AWS::EC2::NetworkAcl**: `DescribeNetworkAcls` for `VpcId`.
20585
+ *
20586
+ * Skipped (return `undefined`, falls through to the comparator's
20587
+ * "unsupported" outcome):
20588
+ * - **AWS::EC2::VPCGatewayAttachment**: physical id is
20589
+ * `IGW|VpcId`. The two ids are immutable inputs to the SDK call;
20590
+ * drift detection on this resource has no useful signal beyond
20591
+ * existence verification (which the user can do via the parent IGW
20592
+ * / VPC drift report).
20593
+ * - **AWS::EC2::Route**, **AWS::EC2::SubnetRouteTableAssociation**,
20594
+ * **AWS::EC2::SecurityGroupIngress**, **AWS::EC2::NetworkAclEntry**,
20595
+ * **AWS::EC2::SubnetNetworkAclAssociation**: rule / association
20596
+ * sub-resources whose AWS API surfaces them inside the parent's
20597
+ * list, not as standalone Get* responses. v1 drift coverage focuses
20598
+ * on top-level resources where the property shape comparison is
20599
+ * cheap and unambiguous; these sub-resources need a more elaborate
20600
+ * extraction layer that's out of scope for this PR.
20601
+ *
20602
+ * Returns `undefined` when the resource is gone (any `*NotFound` /
20603
+ * `Invalid*` error from the EC2 SDK matches `isNotFoundError`).
20604
+ */
20605
+ async readCurrentState(physicalId, logicalId, resourceType) {
20606
+ try {
20607
+ switch (resourceType) {
20608
+ case "AWS::EC2::VPC":
20609
+ return await this.readVpcCurrentState(physicalId);
20610
+ case "AWS::EC2::Subnet":
20611
+ return await this.readSubnetCurrentState(physicalId);
20612
+ case "AWS::EC2::InternetGateway":
20613
+ return await this.readInternetGatewayCurrentState(physicalId);
20614
+ case "AWS::EC2::NatGateway":
20615
+ return await this.readNatGatewayCurrentState(physicalId);
20616
+ case "AWS::EC2::RouteTable":
20617
+ return await this.readRouteTableCurrentState(physicalId);
20618
+ case "AWS::EC2::SecurityGroup":
20619
+ return await this.readSecurityGroupCurrentState(physicalId);
20620
+ case "AWS::EC2::Instance":
20621
+ return await this.readInstanceCurrentState(physicalId);
20622
+ case "AWS::EC2::NetworkAcl":
20623
+ return await this.readNetworkAclCurrentState(physicalId);
20624
+ default:
20625
+ this.logger.debug(
20626
+ `readCurrentState: unsupported resource type ${resourceType} for ${logicalId}`
20627
+ );
20628
+ return void 0;
20629
+ }
20630
+ } catch (err) {
20631
+ if (this.isNotFoundError(err))
20632
+ return void 0;
20633
+ throw err;
20634
+ }
20635
+ }
20636
+ async readVpcCurrentState(physicalId) {
20637
+ const resp = await this.ec2Client.send(new DescribeVpcsCommand2({ VpcIds: [physicalId] }));
20638
+ const vpc = resp.Vpcs?.[0];
20639
+ if (!vpc)
20640
+ return void 0;
20641
+ const result = {};
20642
+ if (vpc.CidrBlock !== void 0)
20643
+ result["CidrBlock"] = vpc.CidrBlock;
20644
+ if (vpc.InstanceTenancy !== void 0)
20645
+ result["InstanceTenancy"] = vpc.InstanceTenancy;
20646
+ try {
20647
+ const dnsHost = await this.ec2Client.send(
20648
+ new DescribeVpcAttributeCommand({ VpcId: physicalId, Attribute: "enableDnsHostnames" })
20649
+ );
20650
+ if (dnsHost.EnableDnsHostnames?.Value !== void 0) {
20651
+ result["EnableDnsHostnames"] = dnsHost.EnableDnsHostnames.Value;
20652
+ }
20653
+ } catch (err) {
20654
+ if (!this.isNotFoundError(err))
20655
+ throw err;
20656
+ }
20657
+ try {
20658
+ const dnsSupp = await this.ec2Client.send(
20659
+ new DescribeVpcAttributeCommand({ VpcId: physicalId, Attribute: "enableDnsSupport" })
20660
+ );
20661
+ if (dnsSupp.EnableDnsSupport?.Value !== void 0) {
20662
+ result["EnableDnsSupport"] = dnsSupp.EnableDnsSupport.Value;
20663
+ }
20664
+ } catch (err) {
20665
+ if (!this.isNotFoundError(err))
20666
+ throw err;
20667
+ }
20668
+ return result;
20669
+ }
20670
+ async readSubnetCurrentState(physicalId) {
20671
+ const resp = await this.ec2Client.send(new DescribeSubnetsCommand2({ SubnetIds: [physicalId] }));
20672
+ const subnet = resp.Subnets?.[0];
20673
+ if (!subnet)
20674
+ return void 0;
20675
+ const result = {};
20676
+ if (subnet.VpcId !== void 0)
20677
+ result["VpcId"] = subnet.VpcId;
20678
+ if (subnet.CidrBlock !== void 0)
20679
+ result["CidrBlock"] = subnet.CidrBlock;
20680
+ if (subnet.AvailabilityZone !== void 0) {
20681
+ result["AvailabilityZone"] = subnet.AvailabilityZone;
20682
+ }
20683
+ if (subnet.MapPublicIpOnLaunch !== void 0) {
20684
+ result["MapPublicIpOnLaunch"] = subnet.MapPublicIpOnLaunch;
20685
+ }
20686
+ return result;
20687
+ }
20688
+ async readInternetGatewayCurrentState(physicalId) {
20689
+ const resp = await this.ec2Client.send(
20690
+ new DescribeInternetGatewaysCommand({ InternetGatewayIds: [physicalId] })
20691
+ );
20692
+ const igw = resp.InternetGateways?.[0];
20693
+ if (!igw)
20694
+ return void 0;
20695
+ return {};
20696
+ }
20697
+ async readNatGatewayCurrentState(physicalId) {
20698
+ const resp = await this.ec2Client.send(
20699
+ new DescribeNatGatewaysCommand({ NatGatewayIds: [physicalId] })
20700
+ );
20701
+ const gw = resp.NatGateways?.find((g) => g.State !== "deleted" && g.State !== "deleting");
20702
+ if (!gw)
20703
+ return void 0;
20704
+ const result = {};
20705
+ if (gw.SubnetId !== void 0)
20706
+ result["SubnetId"] = gw.SubnetId;
20707
+ if (gw.ConnectivityType !== void 0)
20708
+ result["ConnectivityType"] = gw.ConnectivityType;
20709
+ const primary = gw.NatGatewayAddresses?.[0];
20710
+ if (primary?.AllocationId !== void 0)
20711
+ result["AllocationId"] = primary.AllocationId;
20712
+ if (primary?.PrivateIp !== void 0)
20713
+ result["PrivateIpAddress"] = primary.PrivateIp;
20714
+ return result;
20715
+ }
20716
+ async readRouteTableCurrentState(physicalId) {
20717
+ const resp = await this.ec2Client.send(
20718
+ new DescribeRouteTablesCommand2({ RouteTableIds: [physicalId] })
20719
+ );
20720
+ const rt = resp.RouteTables?.[0];
20721
+ if (!rt)
20722
+ return void 0;
20723
+ const result = {};
20724
+ if (rt.VpcId !== void 0)
20725
+ result["VpcId"] = rt.VpcId;
20726
+ return result;
20727
+ }
20728
+ async readSecurityGroupCurrentState(physicalId) {
20729
+ const resp = await this.ec2Client.send(
20730
+ new DescribeSecurityGroupsCommand2({ GroupIds: [physicalId] })
20731
+ );
20732
+ const sg = resp.SecurityGroups?.[0];
20733
+ if (!sg)
20734
+ return void 0;
20735
+ const result = {};
20736
+ if (sg.GroupName !== void 0)
20737
+ result["GroupName"] = sg.GroupName;
20738
+ if (sg.Description !== void 0)
20739
+ result["GroupDescription"] = sg.Description;
20740
+ if (sg.VpcId !== void 0)
20741
+ result["VpcId"] = sg.VpcId;
20742
+ return result;
20743
+ }
20744
+ async readInstanceCurrentState(physicalId) {
20745
+ const resp = await this.ec2Client.send(
20746
+ new DescribeInstancesCommand({ InstanceIds: [physicalId] })
20747
+ );
20748
+ const instance = resp.Reservations?.[0]?.Instances?.[0];
20749
+ if (!instance || instance.State?.Name === "terminated" || instance.State?.Name === "shutting-down") {
20750
+ return void 0;
20751
+ }
20752
+ const result = {};
20753
+ if (instance.ImageId !== void 0)
20754
+ result["ImageId"] = instance.ImageId;
20755
+ if (instance.InstanceType !== void 0)
20756
+ result["InstanceType"] = instance.InstanceType;
20757
+ if (instance.KeyName !== void 0)
20758
+ result["KeyName"] = instance.KeyName;
20759
+ if (instance.SubnetId !== void 0)
20760
+ result["SubnetId"] = instance.SubnetId;
20761
+ return result;
20762
+ }
20763
+ async readNetworkAclCurrentState(physicalId) {
20764
+ const resp = await this.ec2Client.send(
20765
+ new DescribeNetworkAclsCommand({ NetworkAclIds: [physicalId] })
20766
+ );
20767
+ const acl = resp.NetworkAcls?.[0];
20768
+ if (!acl)
20769
+ return void 0;
20770
+ const result = {};
20771
+ if (acl.VpcId !== void 0)
20772
+ result["VpcId"] = acl.VpcId;
20773
+ return result;
20774
+ }
20775
+ async verifyExplicit(resourceType, physicalId) {
20776
+ try {
20777
+ switch (resourceType) {
19943
20778
  case "AWS::EC2::VPC": {
19944
20779
  const resp = await this.ec2Client.send(new DescribeVpcsCommand2({ VpcIds: [physicalId] }));
19945
20780
  return resp.Vpcs?.[0] ? { physicalId, attributes: {} } : null;
@@ -22419,6 +23254,23 @@ function pascalToCamelCaseKeys(value) {
22419
23254
  }
22420
23255
  return value;
22421
23256
  }
23257
+ function camelToPascalCaseKeys(value) {
23258
+ if (value === null || value === void 0) {
23259
+ return value;
23260
+ }
23261
+ if (Array.isArray(value)) {
23262
+ return value.map(camelToPascalCaseKeys);
23263
+ }
23264
+ if (typeof value === "object") {
23265
+ const result = {};
23266
+ for (const [key, val] of Object.entries(value)) {
23267
+ const pascalKey = key.charAt(0).toUpperCase() + key.slice(1);
23268
+ result[pascalKey] = camelToPascalCaseKeys(val);
23269
+ }
23270
+ return result;
23271
+ }
23272
+ return value;
23273
+ }
22422
23274
  var AgentCoreRuntimeProvider = class {
22423
23275
  client;
22424
23276
  logger = getLogger().child("AgentCoreRuntimeProvider");
@@ -22653,6 +23505,68 @@ var AgentCoreRuntimeProvider = class {
22653
23505
  }
22654
23506
  throw new Error(`Unsupported attribute: ${attributeName} for AWS::BedrockAgentCore::Runtime`);
22655
23507
  }
23508
+ /**
23509
+ * Read the AWS-current BedrockAgentCore Runtime configuration in
23510
+ * CFn-property shape.
23511
+ *
23512
+ * Issues `GetAgentRuntime` (the physical id is the runtime id) and
23513
+ * surfaces the keys `create()` accepts. The SDK returns camelCase keys
23514
+ * (`agentRuntimeName`, `roleArn`, `agentRuntimeArtifact`, etc.); we
23515
+ * re-shape back to PascalCase via `camelToPascalCaseKeys` so the
23516
+ * comparator matches cdkd state.
23517
+ *
23518
+ * `ProtocolConfiguration` parity: `create()` accepts a CFn-style string
23519
+ * (`"HTTP"`) and converts it to `{serverProtocol: "HTTP"}` for the SDK.
23520
+ * The SDK returns the object form. We surface the object form here; if
23521
+ * cdkd state holds the original string the comparator will report drift
23522
+ * — users can inspect and dismiss this case manually. (A more elaborate
23523
+ * shape negotiation belongs in a follow-up that knows about both forms.)
23524
+ *
23525
+ * `ClientToken` is omitted: AWS does not surface it back via
23526
+ * `GetAgentRuntime` (it's an idempotency token only meaningful at create
23527
+ * time).
23528
+ *
23529
+ * Returns `undefined` when the runtime is gone
23530
+ * (`ResourceNotFoundException`).
23531
+ */
23532
+ async readCurrentState(physicalId, _logicalId, _resourceType) {
23533
+ let resp;
23534
+ try {
23535
+ resp = await this.client.send(new GetAgentRuntimeCommand({ agentRuntimeId: physicalId }));
23536
+ } catch (err) {
23537
+ if (err instanceof ResourceNotFoundException11)
23538
+ return void 0;
23539
+ throw err;
23540
+ }
23541
+ const result = {};
23542
+ if (resp.agentRuntimeName !== void 0) {
23543
+ result["AgentRuntimeName"] = resp.agentRuntimeName;
23544
+ }
23545
+ if (resp.roleArn !== void 0)
23546
+ result["RoleArn"] = resp.roleArn;
23547
+ if (resp.agentRuntimeArtifact !== void 0) {
23548
+ result["AgentRuntimeArtifact"] = camelToPascalCaseKeys(resp.agentRuntimeArtifact);
23549
+ }
23550
+ if (resp.networkConfiguration !== void 0) {
23551
+ result["NetworkConfiguration"] = camelToPascalCaseKeys(resp.networkConfiguration);
23552
+ }
23553
+ if (resp.description !== void 0 && resp.description !== "") {
23554
+ result["Description"] = resp.description;
23555
+ }
23556
+ if (resp.authorizerConfiguration !== void 0) {
23557
+ result["AuthorizerConfiguration"] = camelToPascalCaseKeys(resp.authorizerConfiguration);
23558
+ }
23559
+ if (resp.protocolConfiguration !== void 0) {
23560
+ result["ProtocolConfiguration"] = camelToPascalCaseKeys(resp.protocolConfiguration);
23561
+ }
23562
+ if (resp.lifecycleConfiguration !== void 0) {
23563
+ result["LifecycleConfiguration"] = camelToPascalCaseKeys(resp.lifecycleConfiguration);
23564
+ }
23565
+ if (resp.environmentVariables !== void 0) {
23566
+ result["EnvironmentVariables"] = resp.environmentVariables;
23567
+ }
23568
+ return result;
23569
+ }
22656
23570
  /**
22657
23571
  * Adopt an existing BedrockAgentCore Runtime into cdkd state.
22658
23572
  *
@@ -24089,7 +25003,8 @@ import {
24089
25003
  DescribeTagsCommand,
24090
25004
  CreateListenerCommand,
24091
25005
  DeleteListenerCommand,
24092
- ModifyListenerCommand
25006
+ ModifyListenerCommand,
25007
+ DescribeListenersCommand as DescribeListenersCommand2
24093
25008
  } from "@aws-sdk/client-elastic-load-balancing-v2";
24094
25009
  var ELBv2Provider = class {
24095
25010
  elbv2Client;
@@ -24582,6 +25497,170 @@ var ELBv2Provider = class {
24582
25497
  return void 0;
24583
25498
  return certificates;
24584
25499
  }
25500
+ /**
25501
+ * Read the AWS-current ELBv2 resource configuration in CFn-property shape.
25502
+ *
25503
+ * Dispatch per resource type:
25504
+ * - `LoadBalancer` → `DescribeLoadBalancers` (Name, Subnets via
25505
+ * `AvailabilityZones[].SubnetId`, SecurityGroups, Scheme, Type,
25506
+ * IpAddressType). LoadBalancerAttributes is omitted for v1 — it
25507
+ * requires a separate `DescribeLoadBalancerAttributes` call and the
25508
+ * drift comparator only descends into keys present in state, so an
25509
+ * absent key cannot fire false drift.
25510
+ * - `TargetGroup` → `DescribeTargetGroups` (Protocol, Port, VpcId,
25511
+ * TargetType, ProtocolVersion, HealthCheck*, Matcher, Name).
25512
+ * - `Listener` → `DescribeListeners` (LoadBalancerArn, Certificates,
25513
+ * DefaultActions, Port, Protocol, SslPolicy).
25514
+ *
25515
+ * Tags are skipped (CDK auto-tag handling deferred). Returns `undefined`
25516
+ * when the resource is gone (`*NotFoundException`).
25517
+ */
25518
+ async readCurrentState(physicalId, _logicalId, resourceType) {
25519
+ switch (resourceType) {
25520
+ case "AWS::ElasticLoadBalancingV2::LoadBalancer":
25521
+ return this.readLoadBalancer(physicalId);
25522
+ case "AWS::ElasticLoadBalancingV2::TargetGroup":
25523
+ return this.readTargetGroup(physicalId);
25524
+ case "AWS::ElasticLoadBalancingV2::Listener":
25525
+ return this.readListener(physicalId);
25526
+ default:
25527
+ return void 0;
25528
+ }
25529
+ }
25530
+ async readLoadBalancer(physicalId) {
25531
+ let lb;
25532
+ try {
25533
+ const resp = await this.getClient().send(
25534
+ new DescribeLoadBalancersCommand2({ LoadBalancerArns: [physicalId] })
25535
+ );
25536
+ lb = resp.LoadBalancers?.[0];
25537
+ } catch (err) {
25538
+ if (this.isNotFoundError(err))
25539
+ return void 0;
25540
+ throw err;
25541
+ }
25542
+ if (!lb)
25543
+ return void 0;
25544
+ const result = {};
25545
+ if (lb.LoadBalancerName !== void 0)
25546
+ result["Name"] = lb.LoadBalancerName;
25547
+ if (lb.AvailabilityZones && lb.AvailabilityZones.length > 0) {
25548
+ const subnets = lb.AvailabilityZones.map((az) => az.SubnetId).filter(
25549
+ (id) => !!id
25550
+ );
25551
+ if (subnets.length > 0)
25552
+ result["Subnets"] = subnets;
25553
+ }
25554
+ if (lb.SecurityGroups && lb.SecurityGroups.length > 0) {
25555
+ result["SecurityGroups"] = [...lb.SecurityGroups];
25556
+ }
25557
+ if (lb.Scheme !== void 0)
25558
+ result["Scheme"] = lb.Scheme;
25559
+ if (lb.Type !== void 0)
25560
+ result["Type"] = lb.Type;
25561
+ if (lb.IpAddressType !== void 0)
25562
+ result["IpAddressType"] = lb.IpAddressType;
25563
+ return result;
25564
+ }
25565
+ async readTargetGroup(physicalId) {
25566
+ let tg;
25567
+ try {
25568
+ const resp = await this.getClient().send(
25569
+ new DescribeTargetGroupsCommand({ TargetGroupArns: [physicalId] })
25570
+ );
25571
+ tg = resp.TargetGroups?.[0];
25572
+ } catch (err) {
25573
+ if (this.isNotFoundError(err))
25574
+ return void 0;
25575
+ throw err;
25576
+ }
25577
+ if (!tg)
25578
+ return void 0;
25579
+ const result = {};
25580
+ if (tg.TargetGroupName !== void 0)
25581
+ result["Name"] = tg.TargetGroupName;
25582
+ if (tg.Protocol !== void 0)
25583
+ result["Protocol"] = tg.Protocol;
25584
+ if (tg.Port !== void 0)
25585
+ result["Port"] = tg.Port;
25586
+ if (tg.VpcId !== void 0)
25587
+ result["VpcId"] = tg.VpcId;
25588
+ if (tg.TargetType !== void 0)
25589
+ result["TargetType"] = tg.TargetType;
25590
+ if (tg.ProtocolVersion !== void 0)
25591
+ result["ProtocolVersion"] = tg.ProtocolVersion;
25592
+ if (tg.HealthCheckProtocol !== void 0)
25593
+ result["HealthCheckProtocol"] = tg.HealthCheckProtocol;
25594
+ if (tg.HealthCheckPort !== void 0)
25595
+ result["HealthCheckPort"] = tg.HealthCheckPort;
25596
+ if (tg.HealthCheckPath !== void 0)
25597
+ result["HealthCheckPath"] = tg.HealthCheckPath;
25598
+ if (tg.HealthCheckEnabled !== void 0)
25599
+ result["HealthCheckEnabled"] = tg.HealthCheckEnabled;
25600
+ if (tg.HealthCheckIntervalSeconds !== void 0) {
25601
+ result["HealthCheckIntervalSeconds"] = tg.HealthCheckIntervalSeconds;
25602
+ }
25603
+ if (tg.HealthCheckTimeoutSeconds !== void 0) {
25604
+ result["HealthCheckTimeoutSeconds"] = tg.HealthCheckTimeoutSeconds;
25605
+ }
25606
+ if (tg.HealthyThresholdCount !== void 0) {
25607
+ result["HealthyThresholdCount"] = tg.HealthyThresholdCount;
25608
+ }
25609
+ if (tg.UnhealthyThresholdCount !== void 0) {
25610
+ result["UnhealthyThresholdCount"] = tg.UnhealthyThresholdCount;
25611
+ }
25612
+ if (tg.Matcher) {
25613
+ const matcher = {};
25614
+ if (tg.Matcher.HttpCode !== void 0)
25615
+ matcher["HttpCode"] = tg.Matcher.HttpCode;
25616
+ if (tg.Matcher.GrpcCode !== void 0)
25617
+ matcher["GrpcCode"] = tg.Matcher.GrpcCode;
25618
+ if (Object.keys(matcher).length > 0)
25619
+ result["Matcher"] = matcher;
25620
+ }
25621
+ return result;
25622
+ }
25623
+ async readListener(physicalId) {
25624
+ let listener;
25625
+ try {
25626
+ const resp = await this.getClient().send(
25627
+ new DescribeListenersCommand2({ ListenerArns: [physicalId] })
25628
+ );
25629
+ listener = resp.Listeners?.[0];
25630
+ } catch (err) {
25631
+ if (this.isNotFoundError(err))
25632
+ return void 0;
25633
+ throw err;
25634
+ }
25635
+ if (!listener)
25636
+ return void 0;
25637
+ const result = {};
25638
+ if (listener.LoadBalancerArn !== void 0) {
25639
+ result["LoadBalancerArn"] = listener.LoadBalancerArn;
25640
+ }
25641
+ if (listener.Port !== void 0)
25642
+ result["Port"] = listener.Port;
25643
+ if (listener.Protocol !== void 0)
25644
+ result["Protocol"] = listener.Protocol;
25645
+ if (listener.SslPolicy !== void 0)
25646
+ result["SslPolicy"] = listener.SslPolicy;
25647
+ if (listener.Certificates && listener.Certificates.length > 0) {
25648
+ result["Certificates"] = listener.Certificates.map((c) => {
25649
+ const out = {};
25650
+ if (c.CertificateArn !== void 0)
25651
+ out["CertificateArn"] = c.CertificateArn;
25652
+ if (c.IsDefault !== void 0)
25653
+ out["IsDefault"] = c.IsDefault;
25654
+ return out;
25655
+ });
25656
+ }
25657
+ if (listener.DefaultActions && listener.DefaultActions.length > 0) {
25658
+ result["DefaultActions"] = listener.DefaultActions.map(
25659
+ (a) => a
25660
+ );
25661
+ }
25662
+ return result;
25663
+ }
24585
25664
  /**
24586
25665
  * Adopt an existing ELBv2 LoadBalancer or TargetGroup into cdkd state.
24587
25666
  *
@@ -25589,6 +26668,7 @@ import {
25589
26668
  ListQueryLoggingConfigsCommand,
25590
26669
  ListHostedZonesByNameCommand as ListHostedZonesByNameCommand2,
25591
26670
  ListHostedZonesCommand,
26671
+ ListResourceRecordSetsCommand,
25592
26672
  ListTagsForResourceCommand as ListTagsForResourceCommand11
25593
26673
  } from "@aws-sdk/client-route-53";
25594
26674
  var Route53Provider = class {
@@ -26236,6 +27316,150 @@ var Route53Provider = class {
26236
27316
  physicalId
26237
27317
  );
26238
27318
  }
27319
+ /**
27320
+ * Read the AWS-current Route 53 resource configuration in CFn-property shape.
27321
+ *
27322
+ * Dispatch per resource type:
27323
+ * - `HostedZone` → `GetHostedZone` (Name, HostedZoneConfig{Comment,
27324
+ * PrivateZone}, VPCs from `VPCs[]`). Tags are skipped (CDK auto-tag
27325
+ * handling deferred); QueryLoggingConfig is skipped because it's a
27326
+ * separate `ListQueryLoggingConfigs` call and the v1 surface does
27327
+ * not surface it.
27328
+ * - `RecordSet` → `ListResourceRecordSets` filtered to the exact
27329
+ * `(name, type)` pair from the composite physicalId
27330
+ * (`{zoneId}|{name}|{type}`). Surfaces TTL, ResourceRecords (with
27331
+ * `[{Value}]` -> string[] re-shape to match cdkd state), AliasTarget,
27332
+ * Weight, Region, Failover, MultiValueAnswer, HealthCheckId,
27333
+ * GeoLocation, SetIdentifier.
27334
+ *
27335
+ * Returns `undefined` when the parent zone is gone (`NoSuchHostedZone`).
27336
+ */
27337
+ async readCurrentState(physicalId, _logicalId, resourceType) {
27338
+ switch (resourceType) {
27339
+ case "AWS::Route53::HostedZone":
27340
+ return this.readHostedZone(physicalId);
27341
+ case "AWS::Route53::RecordSet":
27342
+ return this.readRecordSet(physicalId);
27343
+ default:
27344
+ return void 0;
27345
+ }
27346
+ }
27347
+ async readHostedZone(physicalId) {
27348
+ let resp;
27349
+ try {
27350
+ resp = await this.getClient().send(new GetHostedZoneCommand2({ Id: physicalId }));
27351
+ } catch (err) {
27352
+ if (err instanceof Error && err.name === "NoSuchHostedZone")
27353
+ return void 0;
27354
+ throw err;
27355
+ }
27356
+ if (!resp.HostedZone)
27357
+ return void 0;
27358
+ const result = {};
27359
+ if (resp.HostedZone.Name !== void 0)
27360
+ result["Name"] = resp.HostedZone.Name;
27361
+ if (resp.HostedZone.Config) {
27362
+ const cfg = {};
27363
+ if (resp.HostedZone.Config.Comment !== void 0) {
27364
+ cfg["Comment"] = resp.HostedZone.Config.Comment;
27365
+ }
27366
+ if (resp.HostedZone.Config.PrivateZone !== void 0) {
27367
+ cfg["PrivateZone"] = resp.HostedZone.Config.PrivateZone;
27368
+ }
27369
+ if (Object.keys(cfg).length > 0)
27370
+ result["HostedZoneConfig"] = cfg;
27371
+ }
27372
+ if (resp.VPCs && resp.VPCs.length > 0) {
27373
+ result["VPCs"] = resp.VPCs.map((v) => {
27374
+ const out = {};
27375
+ if (v.VPCId !== void 0)
27376
+ out["VPCId"] = v.VPCId;
27377
+ if (v.VPCRegion !== void 0)
27378
+ out["VPCRegion"] = v.VPCRegion;
27379
+ return out;
27380
+ });
27381
+ }
27382
+ return result;
27383
+ }
27384
+ async readRecordSet(physicalId) {
27385
+ const parts = physicalId.split("|");
27386
+ if (parts.length < 3)
27387
+ return void 0;
27388
+ const [hostedZoneId, name, type] = parts;
27389
+ if (!hostedZoneId || !name || !type)
27390
+ return void 0;
27391
+ let resp;
27392
+ try {
27393
+ resp = await this.getClient().send(
27394
+ new ListResourceRecordSetsCommand({
27395
+ HostedZoneId: hostedZoneId,
27396
+ StartRecordName: name,
27397
+ StartRecordType: type,
27398
+ MaxItems: 1
27399
+ })
27400
+ );
27401
+ } catch (err) {
27402
+ if (err instanceof Error && err.name === "NoSuchHostedZone")
27403
+ return void 0;
27404
+ throw err;
27405
+ }
27406
+ const recordSet = resp.ResourceRecordSets?.find((r) => r.Name === name && r.Type === type);
27407
+ if (!recordSet)
27408
+ return void 0;
27409
+ const result = {
27410
+ HostedZoneId: hostedZoneId,
27411
+ Name: name,
27412
+ Type: type
27413
+ };
27414
+ if (recordSet.TTL !== void 0)
27415
+ result["TTL"] = recordSet.TTL;
27416
+ if (recordSet.ResourceRecords && recordSet.ResourceRecords.length > 0) {
27417
+ result["ResourceRecords"] = recordSet.ResourceRecords.map((r) => r.Value).filter(
27418
+ (v) => typeof v === "string"
27419
+ );
27420
+ }
27421
+ if (recordSet.AliasTarget) {
27422
+ const at = {};
27423
+ if (recordSet.AliasTarget.HostedZoneId !== void 0) {
27424
+ at["HostedZoneId"] = recordSet.AliasTarget.HostedZoneId;
27425
+ }
27426
+ if (recordSet.AliasTarget.DNSName !== void 0) {
27427
+ at["DNSName"] = recordSet.AliasTarget.DNSName;
27428
+ }
27429
+ if (recordSet.AliasTarget.EvaluateTargetHealth !== void 0) {
27430
+ at["EvaluateTargetHealth"] = recordSet.AliasTarget.EvaluateTargetHealth;
27431
+ }
27432
+ result["AliasTarget"] = at;
27433
+ }
27434
+ if (recordSet.SetIdentifier !== void 0)
27435
+ result["SetIdentifier"] = recordSet.SetIdentifier;
27436
+ if (recordSet.Weight !== void 0)
27437
+ result["Weight"] = recordSet.Weight;
27438
+ if (recordSet.Region !== void 0)
27439
+ result["Region"] = recordSet.Region;
27440
+ if (recordSet.Failover !== void 0)
27441
+ result["Failover"] = recordSet.Failover;
27442
+ if (recordSet.MultiValueAnswer !== void 0) {
27443
+ result["MultiValueAnswer"] = recordSet.MultiValueAnswer;
27444
+ }
27445
+ if (recordSet.HealthCheckId !== void 0)
27446
+ result["HealthCheckId"] = recordSet.HealthCheckId;
27447
+ if (recordSet.GeoLocation) {
27448
+ const geo = {};
27449
+ if (recordSet.GeoLocation.ContinentCode !== void 0) {
27450
+ geo["ContinentCode"] = recordSet.GeoLocation.ContinentCode;
27451
+ }
27452
+ if (recordSet.GeoLocation.CountryCode !== void 0) {
27453
+ geo["CountryCode"] = recordSet.GeoLocation.CountryCode;
27454
+ }
27455
+ if (recordSet.GeoLocation.SubdivisionCode !== void 0) {
27456
+ geo["SubdivisionCode"] = recordSet.GeoLocation.SubdivisionCode;
27457
+ }
27458
+ if (Object.keys(geo).length > 0)
27459
+ result["GeoLocation"] = geo;
27460
+ }
27461
+ return result;
27462
+ }
26239
27463
  /**
26240
27464
  * Adopt an existing Route 53 resource into cdkd state.
26241
27465
  *
@@ -26525,33 +27749,102 @@ var WAFv2WebACLProvider = class {
26525
27749
  }
26526
27750
  }
26527
27751
  /**
26528
- * Adopt an existing WAFv2 WebACL into cdkd state.
27752
+ * Read the AWS-current WAFv2 WebACL configuration in CFn-property shape.
26529
27753
  *
26530
- * Lookup order:
26531
- * 1. `--resource <id>=<arn>` override verify with `GetWebACL` (parses
26532
- * Name/Id/Scope back out of the ARN).
26533
- * 2. Walk `ListWebACLs(Scope)` match `aws:cdk:path` via
26534
- * `ListTagsForResource(ResourceARN)` (returns
26535
- * `TagInfoForResource.TagList`, standard `Key`/`Value` shape).
27754
+ * The cdkd physicalId is the WebACL ARN; we parse it back to
27755
+ * `(id, name, scope)` and call `GetWebACL`. The response holds Name,
27756
+ * Description, DefaultAction, Rules, VisibilityConfig,
27757
+ * CustomResponseBodies, CaptchaConfig, ChallengeConfig, TokenDomains,
27758
+ * and AssociationConfig — every key cdkd state declares as
27759
+ * `handledProperties`. `Scope` is recovered from the ARN parse.
26536
27760
  *
26537
- * `Scope` is required by `ListWebACLs` read from
26538
- * `Properties.Scope` (`REGIONAL` is the default).
27761
+ * Tags are skipped (CDK auto-tag handling deferred). Returns `undefined`
27762
+ * when the ARN can't be parsed or the WebACL is gone
27763
+ * (`WAFNonexistentItemException`).
26539
27764
  */
26540
- async import(input) {
26541
- if (input.knownPhysicalId) {
26542
- try {
26543
- const { id, name, scope: scope2 } = parseWebACLArn(input.knownPhysicalId);
26544
- await this.getClient().send(new GetWebACLCommand({ Id: id, Name: name, Scope: scope2 }));
26545
- return { physicalId: input.knownPhysicalId, attributes: {} };
26546
- } catch (err) {
26547
- if (err instanceof WAFNonexistentItemException)
26548
- return null;
26549
- throw err;
26550
- }
27765
+ async readCurrentState(physicalId, _logicalId, _resourceType) {
27766
+ let id;
27767
+ let name;
27768
+ let scope;
27769
+ try {
27770
+ ({ id, name, scope } = parseWebACLArn(physicalId));
27771
+ } catch {
27772
+ return void 0;
26551
27773
  }
26552
- if (!input.cdkPath)
26553
- return null;
26554
- const scope = input.properties["Scope"] || "REGIONAL";
27774
+ let webACL;
27775
+ try {
27776
+ const resp = await this.getClient().send(
27777
+ new GetWebACLCommand({ Id: id, Name: name, Scope: scope })
27778
+ );
27779
+ webACL = resp.WebACL;
27780
+ } catch (err) {
27781
+ if (err instanceof WAFNonexistentItemException)
27782
+ return void 0;
27783
+ throw err;
27784
+ }
27785
+ if (!webACL)
27786
+ return void 0;
27787
+ const result = {};
27788
+ if (webACL.Name !== void 0)
27789
+ result["Name"] = webACL.Name;
27790
+ result["Scope"] = scope;
27791
+ if (webACL.Description !== void 0 && webACL.Description !== "") {
27792
+ result["Description"] = webACL.Description;
27793
+ }
27794
+ if (webACL.DefaultAction) {
27795
+ result["DefaultAction"] = webACL.DefaultAction;
27796
+ }
27797
+ if (webACL.Rules && webACL.Rules.length > 0) {
27798
+ result["Rules"] = webACL.Rules.map((r) => r);
27799
+ }
27800
+ if (webACL.VisibilityConfig) {
27801
+ result["VisibilityConfig"] = webACL.VisibilityConfig;
27802
+ }
27803
+ if (webACL.CustomResponseBodies && Object.keys(webACL.CustomResponseBodies).length > 0) {
27804
+ result["CustomResponseBodies"] = webACL.CustomResponseBodies;
27805
+ }
27806
+ if (webACL.CaptchaConfig) {
27807
+ result["CaptchaConfig"] = webACL.CaptchaConfig;
27808
+ }
27809
+ if (webACL.ChallengeConfig) {
27810
+ result["ChallengeConfig"] = webACL.ChallengeConfig;
27811
+ }
27812
+ if (webACL.TokenDomains && webACL.TokenDomains.length > 0) {
27813
+ result["TokenDomains"] = [...webACL.TokenDomains];
27814
+ }
27815
+ if (webACL.AssociationConfig) {
27816
+ result["AssociationConfig"] = webACL.AssociationConfig;
27817
+ }
27818
+ return result;
27819
+ }
27820
+ /**
27821
+ * Adopt an existing WAFv2 WebACL into cdkd state.
27822
+ *
27823
+ * Lookup order:
27824
+ * 1. `--resource <id>=<arn>` override → verify with `GetWebACL` (parses
27825
+ * Name/Id/Scope back out of the ARN).
27826
+ * 2. Walk `ListWebACLs(Scope)` → match `aws:cdk:path` via
27827
+ * `ListTagsForResource(ResourceARN)` (returns
27828
+ * `TagInfoForResource.TagList`, standard `Key`/`Value` shape).
27829
+ *
27830
+ * `Scope` is required by `ListWebACLs` — read from
27831
+ * `Properties.Scope` (`REGIONAL` is the default).
27832
+ */
27833
+ async import(input) {
27834
+ if (input.knownPhysicalId) {
27835
+ try {
27836
+ const { id, name, scope: scope2 } = parseWebACLArn(input.knownPhysicalId);
27837
+ await this.getClient().send(new GetWebACLCommand({ Id: id, Name: name, Scope: scope2 }));
27838
+ return { physicalId: input.knownPhysicalId, attributes: {} };
27839
+ } catch (err) {
27840
+ if (err instanceof WAFNonexistentItemException)
27841
+ return null;
27842
+ throw err;
27843
+ }
27844
+ }
27845
+ if (!input.cdkPath)
27846
+ return null;
27847
+ const scope = input.properties["Scope"] || "REGIONAL";
26555
27848
  let nextMarker;
26556
27849
  do {
26557
27850
  const list = await this.getClient().send(
@@ -27496,6 +28789,133 @@ var ElastiCacheProvider = class {
27496
28789
  sleep(ms) {
27497
28790
  return new Promise((resolve4) => setTimeout(resolve4, ms));
27498
28791
  }
28792
+ /**
28793
+ * Read the AWS-current ElastiCache resource configuration in CFn-property shape.
28794
+ *
28795
+ * Dispatch per resource type:
28796
+ * - `CacheCluster` → `DescribeCacheClusters` filtered by `CacheClusterId`,
28797
+ * surfacing `Engine`, `CacheNodeType`, `NumCacheNodes`,
28798
+ * `CacheSubnetGroupName`, `Port`, `EngineVersion`,
28799
+ * `CacheParameterGroupName`, `PreferredMaintenanceWindow`,
28800
+ * `PreferredAvailabilityZone`, `SnapshotRetentionLimit`,
28801
+ * `SnapshotWindow`, `AutoMinorVersionUpgrade`, `NotificationTopicArn`,
28802
+ * `IpDiscovery`, `NetworkType`, `TransitEncryptionEnabled`, plus
28803
+ * `VpcSecurityGroupIds` derived from the cluster's `SecurityGroups[]`.
28804
+ * - `SubnetGroup` → `DescribeCacheSubnetGroups` filtered by name,
28805
+ * surfacing `CacheSubnetGroupName`, `CacheSubnetGroupDescription`,
28806
+ * and `SubnetIds` derived from `Subnets[].SubnetIdentifier`.
28807
+ *
28808
+ * Tags are skipped (CDK auto-tag handling deferred). Returns `undefined`
28809
+ * when the resource is gone (`*NotFoundFault`).
28810
+ */
28811
+ async readCurrentState(physicalId, _logicalId, resourceType) {
28812
+ switch (resourceType) {
28813
+ case "AWS::ElastiCache::CacheCluster":
28814
+ return this.readCacheCluster(physicalId);
28815
+ case "AWS::ElastiCache::SubnetGroup":
28816
+ return this.readSubnetGroup(physicalId);
28817
+ default:
28818
+ return void 0;
28819
+ }
28820
+ }
28821
+ async readCacheCluster(physicalId) {
28822
+ let cluster;
28823
+ try {
28824
+ const resp = await this.getClient().send(
28825
+ new DescribeCacheClustersCommand({
28826
+ CacheClusterId: physicalId,
28827
+ ShowCacheNodeInfo: true
28828
+ })
28829
+ );
28830
+ cluster = resp.CacheClusters?.[0];
28831
+ } catch (err) {
28832
+ if (this.isNotFoundError(err, "CacheClusterNotFoundFault"))
28833
+ return void 0;
28834
+ throw err;
28835
+ }
28836
+ if (!cluster)
28837
+ return void 0;
28838
+ const result = {};
28839
+ if (cluster.CacheClusterId !== void 0)
28840
+ result["ClusterName"] = cluster.CacheClusterId;
28841
+ if (cluster.Engine !== void 0)
28842
+ result["Engine"] = cluster.Engine;
28843
+ if (cluster.CacheNodeType !== void 0)
28844
+ result["CacheNodeType"] = cluster.CacheNodeType;
28845
+ if (cluster.NumCacheNodes !== void 0)
28846
+ result["NumCacheNodes"] = cluster.NumCacheNodes;
28847
+ if (cluster.CacheSubnetGroupName !== void 0) {
28848
+ result["CacheSubnetGroupName"] = cluster.CacheSubnetGroupName;
28849
+ }
28850
+ if (cluster.EngineVersion !== void 0)
28851
+ result["EngineVersion"] = cluster.EngineVersion;
28852
+ if (cluster.CacheParameterGroup?.CacheParameterGroupName !== void 0) {
28853
+ result["CacheParameterGroupName"] = cluster.CacheParameterGroup.CacheParameterGroupName;
28854
+ }
28855
+ if (cluster.PreferredMaintenanceWindow !== void 0) {
28856
+ result["PreferredMaintenanceWindow"] = cluster.PreferredMaintenanceWindow;
28857
+ }
28858
+ if (cluster.PreferredAvailabilityZone !== void 0) {
28859
+ result["PreferredAvailabilityZone"] = cluster.PreferredAvailabilityZone;
28860
+ }
28861
+ if (cluster.SnapshotRetentionLimit !== void 0) {
28862
+ result["SnapshotRetentionLimit"] = cluster.SnapshotRetentionLimit;
28863
+ }
28864
+ if (cluster.SnapshotWindow !== void 0)
28865
+ result["SnapshotWindow"] = cluster.SnapshotWindow;
28866
+ if (cluster.AutoMinorVersionUpgrade !== void 0) {
28867
+ result["AutoMinorVersionUpgrade"] = cluster.AutoMinorVersionUpgrade;
28868
+ }
28869
+ if (cluster.NotificationConfiguration?.TopicArn !== void 0) {
28870
+ result["NotificationTopicArn"] = cluster.NotificationConfiguration.TopicArn;
28871
+ }
28872
+ if (cluster.IpDiscovery !== void 0)
28873
+ result["IpDiscovery"] = cluster.IpDiscovery;
28874
+ if (cluster.NetworkType !== void 0)
28875
+ result["NetworkType"] = cluster.NetworkType;
28876
+ if (cluster.TransitEncryptionEnabled !== void 0) {
28877
+ result["TransitEncryptionEnabled"] = cluster.TransitEncryptionEnabled;
28878
+ }
28879
+ if (cluster.CacheNodes?.[0]?.Endpoint?.Port !== void 0) {
28880
+ result["Port"] = cluster.CacheNodes[0].Endpoint.Port;
28881
+ }
28882
+ if (cluster.SecurityGroups && cluster.SecurityGroups.length > 0) {
28883
+ const ids = cluster.SecurityGroups.map((sg) => sg.SecurityGroupId).filter(
28884
+ (id) => !!id
28885
+ );
28886
+ if (ids.length > 0)
28887
+ result["VpcSecurityGroupIds"] = ids;
28888
+ }
28889
+ return result;
28890
+ }
28891
+ async readSubnetGroup(physicalId) {
28892
+ let group;
28893
+ try {
28894
+ const resp = await this.getClient().send(
28895
+ new DescribeCacheSubnetGroupsCommand({ CacheSubnetGroupName: physicalId })
28896
+ );
28897
+ group = resp.CacheSubnetGroups?.[0];
28898
+ } catch (err) {
28899
+ if (this.isNotFoundError(err, "CacheSubnetGroupNotFoundFault"))
28900
+ return void 0;
28901
+ throw err;
28902
+ }
28903
+ if (!group)
28904
+ return void 0;
28905
+ const result = {};
28906
+ if (group.CacheSubnetGroupName !== void 0) {
28907
+ result["CacheSubnetGroupName"] = group.CacheSubnetGroupName;
28908
+ }
28909
+ if (group.CacheSubnetGroupDescription !== void 0) {
28910
+ result["CacheSubnetGroupDescription"] = group.CacheSubnetGroupDescription;
28911
+ }
28912
+ if (group.Subnets && group.Subnets.length > 0) {
28913
+ const ids = group.Subnets.map((s) => s.SubnetIdentifier).filter((id) => !!id);
28914
+ if (ids.length > 0)
28915
+ result["SubnetIds"] = ids;
28916
+ }
28917
+ return result;
28918
+ }
27499
28919
  /**
27500
28920
  * Adopt an existing ElastiCache resource into cdkd state.
27501
28921
  *
@@ -27968,6 +29388,87 @@ var ServiceDiscoveryProvider = class {
27968
29388
  * - **AWS::ServiceDiscovery::Service**: same shape — `ListServices` +
27969
29389
  * `ListTagsForResource`. Both use `Tag[]` arrays.
27970
29390
  */
29391
+ /**
29392
+ * Read the AWS-current ServiceDiscovery resource configuration in CFn-property shape.
29393
+ *
29394
+ * Dispatch per resource type:
29395
+ * - `PrivateDnsNamespace` → `GetNamespace` (Name, Description). `Vpc`
29396
+ * is NOT returned by `GetNamespace` — Cloud Map exposes the VPC only
29397
+ * at create time and via `ListNamespaces`-side `Properties.DnsProperties.HostedZoneId`,
29398
+ * not as a directly comparable VPC ID. We skip it; the comparator
29399
+ * only descends into keys present in cdkd state, so an absent key
29400
+ * cannot fire false drift, but a `Vpc` change will not be detected
29401
+ * via this provider's drift surface (use the CFn-side `aws cloudmap`
29402
+ * CLI for that edge case).
29403
+ * - `Service` → `GetService` (Name, NamespaceId, Description, Type,
29404
+ * DnsConfig, HealthCheckConfig, HealthCheckCustomConfig).
29405
+ *
29406
+ * Tags are skipped (CDK auto-tag handling deferred). Returns `undefined`
29407
+ * when the resource is gone (`NamespaceNotFound` / `ServiceNotFound`).
29408
+ */
29409
+ async readCurrentState(physicalId, _logicalId, resourceType) {
29410
+ switch (resourceType) {
29411
+ case "AWS::ServiceDiscovery::PrivateDnsNamespace":
29412
+ return this.readNamespace(physicalId);
29413
+ case "AWS::ServiceDiscovery::Service":
29414
+ return this.readService(physicalId);
29415
+ default:
29416
+ return void 0;
29417
+ }
29418
+ }
29419
+ async readNamespace(physicalId) {
29420
+ let ns;
29421
+ try {
29422
+ const resp = await this.getClient().send(new GetNamespaceCommand({ Id: physicalId }));
29423
+ ns = resp.Namespace;
29424
+ } catch (err) {
29425
+ if (err instanceof NamespaceNotFound)
29426
+ return void 0;
29427
+ throw err;
29428
+ }
29429
+ if (!ns)
29430
+ return void 0;
29431
+ const result = {};
29432
+ if (ns.Name !== void 0)
29433
+ result["Name"] = ns.Name;
29434
+ if (ns.Description !== void 0 && ns.Description !== "") {
29435
+ result["Description"] = ns.Description;
29436
+ }
29437
+ return result;
29438
+ }
29439
+ async readService(physicalId) {
29440
+ let svc;
29441
+ try {
29442
+ const resp = await this.getClient().send(new GetServiceCommand({ Id: physicalId }));
29443
+ svc = resp.Service;
29444
+ } catch (err) {
29445
+ if (err instanceof ServiceNotFound)
29446
+ return void 0;
29447
+ throw err;
29448
+ }
29449
+ if (!svc)
29450
+ return void 0;
29451
+ const result = {};
29452
+ if (svc.Name !== void 0)
29453
+ result["Name"] = svc.Name;
29454
+ if (svc.NamespaceId !== void 0)
29455
+ result["NamespaceId"] = svc.NamespaceId;
29456
+ if (svc.Description !== void 0 && svc.Description !== "") {
29457
+ result["Description"] = svc.Description;
29458
+ }
29459
+ if (svc.Type !== void 0)
29460
+ result["Type"] = svc.Type;
29461
+ if (svc.DnsConfig) {
29462
+ result["DnsConfig"] = svc.DnsConfig;
29463
+ }
29464
+ if (svc.HealthCheckConfig) {
29465
+ result["HealthCheckConfig"] = svc.HealthCheckConfig;
29466
+ }
29467
+ if (svc.HealthCheckCustomConfig) {
29468
+ result["HealthCheckCustomConfig"] = svc.HealthCheckCustomConfig;
29469
+ }
29470
+ return result;
29471
+ }
27971
29472
  async import(input) {
27972
29473
  switch (input.resourceType) {
27973
29474
  case "AWS::ServiceDiscovery::PrivateDnsNamespace":
@@ -28084,6 +29585,9 @@ import {
28084
29585
  DeleteApiKeyCommand,
28085
29586
  StartSchemaCreationCommand,
28086
29587
  GetGraphqlApiCommand,
29588
+ GetDataSourceCommand,
29589
+ GetResolverCommand,
29590
+ ListApiKeysCommand,
28087
29591
  ListGraphqlApisCommand,
28088
29592
  NotFoundException as AppSyncNotFoundException
28089
29593
  } from "@aws-sdk/client-appsync";
@@ -28593,6 +30097,209 @@ var AppSyncProvider = class {
28593
30097
  const name = error.name ?? "";
28594
30098
  return message.includes("not found") || message.includes("does not exist") || name === "NotFoundException";
28595
30099
  }
30100
+ /**
30101
+ * Read the AWS-current AppSync resource configuration in CFn-property shape.
30102
+ *
30103
+ * Dispatches per resource type:
30104
+ * - `GraphQLApi` → `GetGraphqlApi` (Name, AuthenticationType, XrayEnabled,
30105
+ * LogConfig). Tags are skipped (CDK auto-tag handling deferred).
30106
+ * - `DataSource` → `GetDataSource` (Name, Type, Description,
30107
+ * ServiceRoleArn, DynamoDBConfig, LambdaConfig, HttpConfig). The
30108
+ * `ApiId` cdkd holds is recovered from the `apiId|name` physicalId.
30109
+ * - `Resolver` → `GetResolver` (TypeName, FieldName, DataSourceName,
30110
+ * request/response templates, Kind, PipelineConfig, Runtime, Code).
30111
+ * - `ApiKey` → `ListApiKeys` filtered by id (no `GetApiKey` SDK call;
30112
+ * AppSync only exposes list-based access). Surfaces Description and
30113
+ * Expires.
30114
+ * - `GraphQLSchema` → `GetSchemaCreationStatus` is the closest live
30115
+ * state, but it returns a status string only (not the full schema
30116
+ * body). Schema bodies live in cdkd state's `Definition` and would
30117
+ * need `GetIntrospectionSchema` + reverse-mapping to compare; that's
30118
+ * a separate task. Returns `undefined` so the comparator marks it
30119
+ * as "drift unknown" rather than firing a false positive.
30120
+ *
30121
+ * Returns `undefined` when the parent resource is gone (`NotFoundException`).
30122
+ */
30123
+ async readCurrentState(physicalId, _logicalId, resourceType) {
30124
+ switch (resourceType) {
30125
+ case "AWS::AppSync::GraphQLApi":
30126
+ return this.readGraphQLApi(physicalId);
30127
+ case "AWS::AppSync::DataSource":
30128
+ return this.readDataSource(physicalId);
30129
+ case "AWS::AppSync::Resolver":
30130
+ return this.readResolver(physicalId);
30131
+ case "AWS::AppSync::ApiKey":
30132
+ return this.readApiKey(physicalId);
30133
+ case "AWS::AppSync::GraphQLSchema":
30134
+ return void 0;
30135
+ default:
30136
+ return void 0;
30137
+ }
30138
+ }
30139
+ async readGraphQLApi(physicalId) {
30140
+ let api;
30141
+ try {
30142
+ const resp = await this.getClient().send(new GetGraphqlApiCommand({ apiId: physicalId }));
30143
+ api = resp.graphqlApi;
30144
+ } catch (err) {
30145
+ if (err instanceof AppSyncNotFoundException)
30146
+ return void 0;
30147
+ throw err;
30148
+ }
30149
+ if (!api)
30150
+ return void 0;
30151
+ const result = {};
30152
+ if (api.name !== void 0)
30153
+ result["Name"] = api.name;
30154
+ if (api.authenticationType !== void 0) {
30155
+ result["AuthenticationType"] = api.authenticationType;
30156
+ }
30157
+ if (api.xrayEnabled !== void 0)
30158
+ result["XrayEnabled"] = api.xrayEnabled;
30159
+ if (api.logConfig) {
30160
+ const log = {};
30161
+ if (api.logConfig.cloudWatchLogsRoleArn !== void 0) {
30162
+ log["CloudWatchLogsRoleArn"] = api.logConfig.cloudWatchLogsRoleArn;
30163
+ }
30164
+ if (api.logConfig.fieldLogLevel !== void 0) {
30165
+ log["FieldLogLevel"] = api.logConfig.fieldLogLevel;
30166
+ }
30167
+ if (api.logConfig.excludeVerboseContent !== void 0) {
30168
+ log["ExcludeVerboseContent"] = api.logConfig.excludeVerboseContent;
30169
+ }
30170
+ if (Object.keys(log).length > 0)
30171
+ result["LogConfig"] = log;
30172
+ }
30173
+ return result;
30174
+ }
30175
+ async readDataSource(physicalId) {
30176
+ const [apiId, name] = physicalId.split("|");
30177
+ if (!apiId || !name)
30178
+ return void 0;
30179
+ let ds;
30180
+ try {
30181
+ const resp = await this.getClient().send(new GetDataSourceCommand({ apiId, name }));
30182
+ ds = resp.dataSource;
30183
+ } catch (err) {
30184
+ if (err instanceof AppSyncNotFoundException)
30185
+ return void 0;
30186
+ throw err;
30187
+ }
30188
+ if (!ds)
30189
+ return void 0;
30190
+ const result = { ApiId: apiId };
30191
+ if (ds.name !== void 0)
30192
+ result["Name"] = ds.name;
30193
+ if (ds.type !== void 0)
30194
+ result["Type"] = ds.type;
30195
+ if (ds.description !== void 0 && ds.description !== "") {
30196
+ result["Description"] = ds.description;
30197
+ }
30198
+ if (ds.serviceRoleArn !== void 0)
30199
+ result["ServiceRoleArn"] = ds.serviceRoleArn;
30200
+ if (ds.dynamodbConfig) {
30201
+ const dynamo = {};
30202
+ if (ds.dynamodbConfig.tableName !== void 0)
30203
+ dynamo["TableName"] = ds.dynamodbConfig.tableName;
30204
+ if (ds.dynamodbConfig.awsRegion !== void 0)
30205
+ dynamo["AwsRegion"] = ds.dynamodbConfig.awsRegion;
30206
+ if (ds.dynamodbConfig.useCallerCredentials !== void 0) {
30207
+ dynamo["UseCallerCredentials"] = ds.dynamodbConfig.useCallerCredentials;
30208
+ }
30209
+ if (Object.keys(dynamo).length > 0)
30210
+ result["DynamoDBConfig"] = dynamo;
30211
+ }
30212
+ if (ds.lambdaConfig?.lambdaFunctionArn !== void 0) {
30213
+ result["LambdaConfig"] = { LambdaFunctionArn: ds.lambdaConfig.lambdaFunctionArn };
30214
+ }
30215
+ if (ds.httpConfig?.endpoint !== void 0) {
30216
+ result["HttpConfig"] = { Endpoint: ds.httpConfig.endpoint };
30217
+ }
30218
+ return result;
30219
+ }
30220
+ async readResolver(physicalId) {
30221
+ const parts = physicalId.split("|");
30222
+ if (parts.length < 3)
30223
+ return void 0;
30224
+ const [apiId, typeName, fieldName] = parts;
30225
+ if (!apiId || !typeName || !fieldName)
30226
+ return void 0;
30227
+ let resolver;
30228
+ try {
30229
+ const resp = await this.getClient().send(
30230
+ new GetResolverCommand({ apiId, typeName, fieldName })
30231
+ );
30232
+ resolver = resp.resolver;
30233
+ } catch (err) {
30234
+ if (err instanceof AppSyncNotFoundException)
30235
+ return void 0;
30236
+ throw err;
30237
+ }
30238
+ if (!resolver)
30239
+ return void 0;
30240
+ const result = { ApiId: apiId };
30241
+ if (resolver.typeName !== void 0)
30242
+ result["TypeName"] = resolver.typeName;
30243
+ if (resolver.fieldName !== void 0)
30244
+ result["FieldName"] = resolver.fieldName;
30245
+ if (resolver.dataSourceName !== void 0)
30246
+ result["DataSourceName"] = resolver.dataSourceName;
30247
+ if (resolver.requestMappingTemplate !== void 0) {
30248
+ result["RequestMappingTemplate"] = resolver.requestMappingTemplate;
30249
+ }
30250
+ if (resolver.responseMappingTemplate !== void 0) {
30251
+ result["ResponseMappingTemplate"] = resolver.responseMappingTemplate;
30252
+ }
30253
+ if (resolver.kind !== void 0)
30254
+ result["Kind"] = resolver.kind;
30255
+ if (resolver.pipelineConfig?.functions && resolver.pipelineConfig.functions.length > 0) {
30256
+ result["PipelineConfig"] = { Functions: [...resolver.pipelineConfig.functions] };
30257
+ }
30258
+ if (resolver.runtime) {
30259
+ const runtime = {};
30260
+ if (resolver.runtime.name !== void 0)
30261
+ runtime["Name"] = resolver.runtime.name;
30262
+ if (resolver.runtime.runtimeVersion !== void 0) {
30263
+ runtime["RuntimeVersion"] = resolver.runtime.runtimeVersion;
30264
+ }
30265
+ if (Object.keys(runtime).length > 0)
30266
+ result["Runtime"] = runtime;
30267
+ }
30268
+ if (resolver.code !== void 0)
30269
+ result["Code"] = resolver.code;
30270
+ return result;
30271
+ }
30272
+ async readApiKey(physicalId) {
30273
+ const [apiId, apiKeyId] = physicalId.split("|");
30274
+ if (!apiId || !apiKeyId)
30275
+ return void 0;
30276
+ let nextToken;
30277
+ do {
30278
+ let resp;
30279
+ try {
30280
+ resp = await this.getClient().send(
30281
+ new ListApiKeysCommand({ apiId, ...nextToken && { nextToken } })
30282
+ );
30283
+ } catch (err) {
30284
+ if (err instanceof AppSyncNotFoundException)
30285
+ return void 0;
30286
+ throw err;
30287
+ }
30288
+ for (const key of resp.apiKeys ?? []) {
30289
+ if (key.id === apiKeyId) {
30290
+ const result = { ApiId: apiId };
30291
+ if (key.description !== void 0 && key.description !== "") {
30292
+ result["Description"] = key.description;
30293
+ }
30294
+ if (key.expires !== void 0)
30295
+ result["Expires"] = key.expires;
30296
+ return result;
30297
+ }
30298
+ }
30299
+ nextToken = resp.nextToken;
30300
+ } while (nextToken);
30301
+ return void 0;
30302
+ }
28596
30303
  /**
28597
30304
  * Adopt an existing AppSync resource into cdkd state.
28598
30305
  *
@@ -29044,6 +30751,116 @@ var GlueProvider = class {
29044
30751
  * Glue list APIs return only names — ARNs are constructed locally
29045
30752
  * for the per-item GetTags call.
29046
30753
  */
30754
+ /**
30755
+ * Read the AWS-current Glue resource configuration in CFn-property shape.
30756
+ *
30757
+ * Dispatch per resource type:
30758
+ * - `Database` → `GetDatabase` returning DatabaseInput-shape
30759
+ * (`Name`, `Description`, `LocationUri`, `Parameters`).
30760
+ * - `Table` → `GetTable` returning the same-named TableInput-shape
30761
+ * fields (`Name`, `Description`, `Owner`, `Retention`, `TableType`,
30762
+ * `PartitionKeys`, `Parameters`, `StorageDescriptor`, `ViewOriginalText`,
30763
+ * `ViewExpandedText`, `TargetTable`). The table physicalId is
30764
+ * `databaseName|tableName`; we recover both from the split.
30765
+ *
30766
+ * `CatalogId` is intentionally not surfaced — `GetDatabase` /
30767
+ * `GetTable` do not echo it back, and cdkd state's `CatalogId` is
30768
+ * usually the AWS account id (defaulted by the API). Comparator only
30769
+ * descends into keys present in state, so an absent surface key cannot
30770
+ * fire false drift here.
30771
+ *
30772
+ * Returns `undefined` when the resource is gone (`EntityNotFoundException`).
30773
+ * Other Glue resource types (`Job`, `Crawler`, `Connection`, `Trigger`,
30774
+ * `Workflow`, `SecurityConfiguration`, etc.) are out of scope for v1 —
30775
+ * the provider's `create()` only handles Database/Table; CC API picks
30776
+ * up drift detection for the rest.
30777
+ */
30778
+ async readCurrentState(physicalId, _logicalId, resourceType) {
30779
+ switch (resourceType) {
30780
+ case "AWS::Glue::Database":
30781
+ return this.readDatabase(physicalId);
30782
+ case "AWS::Glue::Table":
30783
+ return this.readTable(physicalId);
30784
+ default:
30785
+ return void 0;
30786
+ }
30787
+ }
30788
+ async readDatabase(physicalId) {
30789
+ let db;
30790
+ try {
30791
+ const resp = await this.getClient().send(new GetDatabaseCommand({ Name: physicalId }));
30792
+ db = resp.Database;
30793
+ } catch (err) {
30794
+ if (err instanceof EntityNotFoundException)
30795
+ return void 0;
30796
+ throw err;
30797
+ }
30798
+ if (!db)
30799
+ return void 0;
30800
+ const dbInput = {};
30801
+ if (db.Name !== void 0)
30802
+ dbInput["Name"] = db.Name;
30803
+ if (db.Description !== void 0 && db.Description !== "") {
30804
+ dbInput["Description"] = db.Description;
30805
+ }
30806
+ if (db.LocationUri !== void 0)
30807
+ dbInput["LocationUri"] = db.LocationUri;
30808
+ if (db.Parameters && Object.keys(db.Parameters).length > 0) {
30809
+ dbInput["Parameters"] = db.Parameters;
30810
+ }
30811
+ return { DatabaseInput: dbInput };
30812
+ }
30813
+ async readTable(physicalId) {
30814
+ const [databaseName, tableName] = physicalId.split("|");
30815
+ if (!databaseName || !tableName)
30816
+ return void 0;
30817
+ let table;
30818
+ try {
30819
+ const resp = await this.getClient().send(
30820
+ new GetTableCommand({ DatabaseName: databaseName, Name: tableName })
30821
+ );
30822
+ table = resp.Table;
30823
+ } catch (err) {
30824
+ if (err instanceof EntityNotFoundException)
30825
+ return void 0;
30826
+ throw err;
30827
+ }
30828
+ if (!table)
30829
+ return void 0;
30830
+ const tableInput = {};
30831
+ if (table.Name !== void 0)
30832
+ tableInput["Name"] = table.Name;
30833
+ if (table.Description !== void 0 && table.Description !== "") {
30834
+ tableInput["Description"] = table.Description;
30835
+ }
30836
+ if (table.Owner !== void 0)
30837
+ tableInput["Owner"] = table.Owner;
30838
+ if (table.Retention !== void 0)
30839
+ tableInput["Retention"] = table.Retention;
30840
+ if (table.TableType !== void 0)
30841
+ tableInput["TableType"] = table.TableType;
30842
+ if (table.PartitionKeys && table.PartitionKeys.length > 0) {
30843
+ tableInput["PartitionKeys"] = table.PartitionKeys.map(
30844
+ (k) => k
30845
+ );
30846
+ }
30847
+ if (table.Parameters && Object.keys(table.Parameters).length > 0) {
30848
+ tableInput["Parameters"] = table.Parameters;
30849
+ }
30850
+ if (table.StorageDescriptor) {
30851
+ tableInput["StorageDescriptor"] = table.StorageDescriptor;
30852
+ }
30853
+ if (table.ViewOriginalText !== void 0) {
30854
+ tableInput["ViewOriginalText"] = table.ViewOriginalText;
30855
+ }
30856
+ if (table.ViewExpandedText !== void 0) {
30857
+ tableInput["ViewExpandedText"] = table.ViewExpandedText;
30858
+ }
30859
+ if (table.TargetTable) {
30860
+ tableInput["TargetTable"] = table.TargetTable;
30861
+ }
30862
+ return { DatabaseName: databaseName, TableInput: tableInput };
30863
+ }
29047
30864
  async import(input) {
29048
30865
  switch (input.resourceType) {
29049
30866
  case "AWS::Glue::Database":
@@ -30020,6 +31837,57 @@ var KinesisStreamProvider = class {
30020
31837
  * Kinesis tags use the standard `Tag[]` array shape (`Key`/`Value`),
30021
31838
  * so `matchesCdkPath` from import-helpers applies directly.
30022
31839
  */
31840
+ /**
31841
+ * Read the AWS-current Kinesis stream configuration in CFn-property shape.
31842
+ *
31843
+ * Issues `DescribeStream` and surfaces the keys cdkd's `create()`
31844
+ * accepts: `Name`, `StreamModeDetails`, `ShardCount`, `RetentionPeriodHours`,
31845
+ * and `StreamEncryption`. Tags are skipped (CDK auto-tag handling deferred).
31846
+ *
31847
+ * `ShardCount` is reported as the count of `Shards[]` in the stream
31848
+ * description (only present for PROVISIONED-mode streams; ON_DEMAND
31849
+ * mode reports an empty list).
31850
+ *
31851
+ * Returns `undefined` when the stream is gone (`ResourceNotFoundException`).
31852
+ * Only `AWS::Kinesis::Stream` is supported (the provider does not handle
31853
+ * `AWS::Kinesis::StreamConsumer`).
31854
+ */
31855
+ async readCurrentState(physicalId, _logicalId, resourceType) {
31856
+ if (resourceType !== "AWS::Kinesis::Stream")
31857
+ return void 0;
31858
+ let stream;
31859
+ try {
31860
+ const resp = await this.getClient().send(
31861
+ new DescribeStreamCommand({ StreamName: physicalId })
31862
+ );
31863
+ stream = resp.StreamDescription;
31864
+ } catch (err) {
31865
+ if (err instanceof ResourceNotFoundException13)
31866
+ return void 0;
31867
+ throw err;
31868
+ }
31869
+ if (!stream)
31870
+ return void 0;
31871
+ const result = {};
31872
+ if (stream.StreamName !== void 0)
31873
+ result["Name"] = stream.StreamName;
31874
+ if (stream.StreamModeDetails?.StreamMode !== void 0) {
31875
+ result["StreamModeDetails"] = { StreamMode: stream.StreamModeDetails.StreamMode };
31876
+ }
31877
+ if (stream.Shards && stream.Shards.length > 0) {
31878
+ result["ShardCount"] = stream.Shards.length;
31879
+ }
31880
+ if (stream.RetentionPeriodHours !== void 0) {
31881
+ result["RetentionPeriodHours"] = stream.RetentionPeriodHours;
31882
+ }
31883
+ if (stream.EncryptionType !== void 0 && stream.EncryptionType !== "NONE") {
31884
+ const encryption = { EncryptionType: stream.EncryptionType };
31885
+ if (stream.KeyId !== void 0)
31886
+ encryption["KeyId"] = stream.KeyId;
31887
+ result["StreamEncryption"] = encryption;
31888
+ }
31889
+ return result;
31890
+ }
30023
31891
  async import(input) {
30024
31892
  const explicit = resolveExplicitPhysicalId(input, "Name");
30025
31893
  if (explicit) {
@@ -30099,6 +31967,8 @@ import {
30099
31967
  DeleteAccessPointCommand,
30100
31968
  DescribeFileSystemsCommand,
30101
31969
  DescribeAccessPointsCommand,
31970
+ DescribeLifecycleConfigurationCommand,
31971
+ DescribeBackupPolicyCommand,
30102
31972
  FileSystemNotFound,
30103
31973
  MountTargetNotFound,
30104
31974
  AccessPointNotFound
@@ -30500,6 +32370,173 @@ var EFSProvider = class {
30500
32370
  );
30501
32371
  }
30502
32372
  }
32373
+ /**
32374
+ * Read the AWS-current EFS resource configuration in CFn-property shape.
32375
+ *
32376
+ * Dispatch per resource type:
32377
+ * - `FileSystem` → `DescribeFileSystems` filtered by id (PerformanceMode,
32378
+ * ThroughputMode, Encrypted, KmsKeyId, ProvisionedThroughputInMibps),
32379
+ * plus optional `DescribeLifecycleConfiguration` and
32380
+ * `DescribeBackupPolicy` enrichment. Each enrichment call is wrapped
32381
+ * in its own try/catch so a "not configured" error on either omits
32382
+ * the corresponding key without failing the whole snapshot.
32383
+ * - `AccessPoint` → `DescribeAccessPoints` filtered by id (PosixUser,
32384
+ * RootDirectory).
32385
+ * - `MountTarget` → `DescribeMountTargets` (FileSystemId, SubnetId).
32386
+ * SecurityGroups requires a separate call and is omitted for v1.
32387
+ *
32388
+ * Tags are skipped across all three (CDK auto-tag handling deferred).
32389
+ * Returns `undefined` when the resource is gone (`*NotFound`).
32390
+ */
32391
+ async readCurrentState(physicalId, _logicalId, resourceType) {
32392
+ switch (resourceType) {
32393
+ case "AWS::EFS::FileSystem":
32394
+ return this.readFileSystem(physicalId);
32395
+ case "AWS::EFS::AccessPoint":
32396
+ return this.readAccessPoint(physicalId);
32397
+ case "AWS::EFS::MountTarget":
32398
+ return this.readMountTarget(physicalId);
32399
+ default:
32400
+ return void 0;
32401
+ }
32402
+ }
32403
+ async readFileSystem(physicalId) {
32404
+ let fs;
32405
+ try {
32406
+ const resp = await this.getClient().send(
32407
+ new DescribeFileSystemsCommand({ FileSystemId: physicalId })
32408
+ );
32409
+ fs = resp.FileSystems?.[0];
32410
+ } catch (err) {
32411
+ if (err instanceof FileSystemNotFound)
32412
+ return void 0;
32413
+ throw err;
32414
+ }
32415
+ if (!fs)
32416
+ return void 0;
32417
+ const result = {};
32418
+ if (fs.PerformanceMode !== void 0)
32419
+ result["PerformanceMode"] = fs.PerformanceMode;
32420
+ if (fs.ThroughputMode !== void 0)
32421
+ result["ThroughputMode"] = fs.ThroughputMode;
32422
+ if (fs.Encrypted !== void 0)
32423
+ result["Encrypted"] = fs.Encrypted;
32424
+ if (fs.KmsKeyId !== void 0)
32425
+ result["KmsKeyId"] = fs.KmsKeyId;
32426
+ if (fs.ProvisionedThroughputInMibps !== void 0) {
32427
+ result["ProvisionedThroughputInMibps"] = fs.ProvisionedThroughputInMibps;
32428
+ }
32429
+ try {
32430
+ const resp = await this.getClient().send(
32431
+ new DescribeLifecycleConfigurationCommand({ FileSystemId: physicalId })
32432
+ );
32433
+ const policies = resp.LifecyclePolicies;
32434
+ if (policies && policies.length > 0) {
32435
+ result["LifecyclePolicies"] = policies.map((p) => {
32436
+ const out = {};
32437
+ if (p.TransitionToIA !== void 0)
32438
+ out["TransitionToIA"] = p.TransitionToIA;
32439
+ if (p.TransitionToPrimaryStorageClass !== void 0) {
32440
+ out["TransitionToPrimaryStorageClass"] = p.TransitionToPrimaryStorageClass;
32441
+ }
32442
+ if (p.TransitionToArchive !== void 0)
32443
+ out["TransitionToArchive"] = p.TransitionToArchive;
32444
+ return out;
32445
+ });
32446
+ }
32447
+ } catch (err) {
32448
+ if (err instanceof FileSystemNotFound)
32449
+ return void 0;
32450
+ const e = err;
32451
+ if (e.name !== "PolicyNotFound") {
32452
+ }
32453
+ }
32454
+ try {
32455
+ const resp = await this.getClient().send(
32456
+ new DescribeBackupPolicyCommand({ FileSystemId: physicalId })
32457
+ );
32458
+ if (resp.BackupPolicy?.Status !== void 0) {
32459
+ result["BackupPolicy"] = { Status: resp.BackupPolicy.Status };
32460
+ }
32461
+ } catch (err) {
32462
+ if (err instanceof FileSystemNotFound)
32463
+ return void 0;
32464
+ }
32465
+ return result;
32466
+ }
32467
+ async readAccessPoint(physicalId) {
32468
+ let ap;
32469
+ try {
32470
+ const resp = await this.getClient().send(
32471
+ new DescribeAccessPointsCommand({ AccessPointId: physicalId })
32472
+ );
32473
+ ap = resp.AccessPoints?.[0];
32474
+ } catch (err) {
32475
+ if (err instanceof AccessPointNotFound)
32476
+ return void 0;
32477
+ throw err;
32478
+ }
32479
+ if (!ap)
32480
+ return void 0;
32481
+ const result = {};
32482
+ if (ap.FileSystemId !== void 0)
32483
+ result["FileSystemId"] = ap.FileSystemId;
32484
+ if (ap.PosixUser) {
32485
+ const posix = {};
32486
+ if (ap.PosixUser.Uid !== void 0)
32487
+ posix["Uid"] = ap.PosixUser.Uid;
32488
+ if (ap.PosixUser.Gid !== void 0)
32489
+ posix["Gid"] = ap.PosixUser.Gid;
32490
+ if (ap.PosixUser.SecondaryGids && ap.PosixUser.SecondaryGids.length > 0) {
32491
+ posix["SecondaryGids"] = [...ap.PosixUser.SecondaryGids];
32492
+ }
32493
+ if (Object.keys(posix).length > 0)
32494
+ result["PosixUser"] = posix;
32495
+ }
32496
+ if (ap.RootDirectory) {
32497
+ const root = {};
32498
+ if (ap.RootDirectory.Path !== void 0)
32499
+ root["Path"] = ap.RootDirectory.Path;
32500
+ if (ap.RootDirectory.CreationInfo) {
32501
+ const ci = {};
32502
+ if (ap.RootDirectory.CreationInfo.OwnerUid !== void 0) {
32503
+ ci["OwnerUid"] = ap.RootDirectory.CreationInfo.OwnerUid;
32504
+ }
32505
+ if (ap.RootDirectory.CreationInfo.OwnerGid !== void 0) {
32506
+ ci["OwnerGid"] = ap.RootDirectory.CreationInfo.OwnerGid;
32507
+ }
32508
+ if (ap.RootDirectory.CreationInfo.Permissions !== void 0) {
32509
+ ci["Permissions"] = ap.RootDirectory.CreationInfo.Permissions;
32510
+ }
32511
+ if (Object.keys(ci).length > 0)
32512
+ root["CreationInfo"] = ci;
32513
+ }
32514
+ if (Object.keys(root).length > 0)
32515
+ result["RootDirectory"] = root;
32516
+ }
32517
+ return result;
32518
+ }
32519
+ async readMountTarget(physicalId) {
32520
+ let mt;
32521
+ try {
32522
+ const resp = await this.getClient().send(
32523
+ new DescribeMountTargetsCommand({ MountTargetId: physicalId })
32524
+ );
32525
+ mt = resp.MountTargets?.[0];
32526
+ } catch (err) {
32527
+ if (err instanceof MountTargetNotFound)
32528
+ return void 0;
32529
+ throw err;
32530
+ }
32531
+ if (!mt)
32532
+ return void 0;
32533
+ const result = {};
32534
+ if (mt.FileSystemId !== void 0)
32535
+ result["FileSystemId"] = mt.FileSystemId;
32536
+ if (mt.SubnetId !== void 0)
32537
+ result["SubnetId"] = mt.SubnetId;
32538
+ return result;
32539
+ }
30503
32540
  /**
30504
32541
  * Adopt an existing EFS resource into cdkd state.
30505
32542
  *
@@ -30952,6 +32989,63 @@ var FirehoseProvider = class {
30952
32989
  *
30953
32990
  * Firehose tags use the standard `Tag[]` array shape (`Key`/`Value`).
30954
32991
  */
32992
+ /**
32993
+ * Read the AWS-current Firehose delivery stream configuration in CFn-property shape.
32994
+ *
32995
+ * Surfaces top-level configuration that has a clean 1:1 mapping back to
32996
+ * cdkd state — `DeliveryStreamName`, `DeliveryStreamType`, and the
32997
+ * `KinesisStreamSourceConfiguration` parent fields when present (the
32998
+ * `DescribeDeliveryStream` response splits source under `Source.KinesisStreamSourceDescription`).
32999
+ *
33000
+ * Destination configurations (`*DestinationConfiguration` in CFn vs.
33001
+ * `*DestinationDescription` in `DescribeDeliveryStream`) are intentionally
33002
+ * not re-shaped here. Their nested fields are large and the description
33003
+ * vs. configuration shape divergence (extra metadata, write-only fields
33004
+ * like `Password` redacted) makes a clean comparator surface impossible
33005
+ * for v1. We do surface the destination *kind* under a stable key so
33006
+ * users at least see destination drift across types, but not the inner
33007
+ * fields. Drift on destination contents is best chased manually via
33008
+ * `aws firehose describe-delivery-stream` for now.
33009
+ *
33010
+ * Tags + DeliveryStreamEncryptionConfigurationInput are skipped (they
33011
+ * each need separate calls / shape decisions).
33012
+ *
33013
+ * Returns `undefined` when the stream is gone (`ResourceNotFoundException`).
33014
+ */
33015
+ async readCurrentState(physicalId, _logicalId, _resourceType) {
33016
+ let desc;
33017
+ try {
33018
+ const resp = await this.getClient().send(
33019
+ new DescribeDeliveryStreamCommand({ DeliveryStreamName: physicalId })
33020
+ );
33021
+ desc = resp.DeliveryStreamDescription;
33022
+ } catch (err) {
33023
+ if (err instanceof ResourceNotFoundException14)
33024
+ return void 0;
33025
+ throw err;
33026
+ }
33027
+ if (!desc)
33028
+ return void 0;
33029
+ const result = {};
33030
+ if (desc.DeliveryStreamName !== void 0) {
33031
+ result["DeliveryStreamName"] = desc.DeliveryStreamName;
33032
+ }
33033
+ if (desc.DeliveryStreamType !== void 0) {
33034
+ result["DeliveryStreamType"] = desc.DeliveryStreamType;
33035
+ }
33036
+ if (desc.Source?.KinesisStreamSourceDescription) {
33037
+ const src = desc.Source.KinesisStreamSourceDescription;
33038
+ const srcOut = {};
33039
+ if (src.KinesisStreamARN !== void 0)
33040
+ srcOut["KinesisStreamARN"] = src.KinesisStreamARN;
33041
+ if (src.RoleARN !== void 0)
33042
+ srcOut["RoleARN"] = src.RoleARN;
33043
+ if (Object.keys(srcOut).length > 0) {
33044
+ result["KinesisStreamSourceConfiguration"] = srcOut;
33045
+ }
33046
+ }
33047
+ return result;
33048
+ }
30955
33049
  async import(input) {
30956
33050
  const explicit = resolveExplicitPhysicalId(input, "DeliveryStreamName");
30957
33051
  if (explicit) {
@@ -31027,6 +33121,8 @@ import {
31027
33121
  PutEventSelectorsCommand,
31028
33122
  PutInsightSelectorsCommand,
31029
33123
  GetTrailCommand,
33124
+ GetTrailStatusCommand,
33125
+ GetEventSelectorsCommand,
31030
33126
  ListTrailsCommand,
31031
33127
  ListTagsCommand as ListTagsCommand3,
31032
33128
  TrailNotFoundException
@@ -31268,6 +33364,86 @@ var CloudTrailProvider = class {
31268
33364
  * 2. `ListTrails` + `ListTags` (CloudTrail uses `Tag[]` arrays per ARN),
31269
33365
  * match `aws:cdk:path` tag.
31270
33366
  */
33367
+ /**
33368
+ * Read the AWS-current CloudTrail Trail configuration in CFn-property shape.
33369
+ *
33370
+ * Issues `GetTrail`, plus best-effort `GetTrailStatus` (for `IsLogging`)
33371
+ * and `GetEventSelectors` (for `EventSelectors`). Each enrichment call is
33372
+ * wrapped in its own try/catch so an "AccessDenied" or other transient
33373
+ * error on the secondary calls omits that key without failing the
33374
+ * whole snapshot — the comparator only descends into keys present in
33375
+ * state.
33376
+ *
33377
+ * Mapping: AWS `GetTrail` returns `KmsKeyId` (lowercase `s`) while CFn
33378
+ * uses `KMSKeyId`; we re-shape the key. SnsTopicARN is the Trail's
33379
+ * derived field; the cdkd state property is `SnsTopicName` so we
33380
+ * surface `SnsTopicName` directly from `GetTrail.SnsTopicName`.
33381
+ *
33382
+ * Tags + InsightSelectors are skipped for v1 (each needs its own
33383
+ * separate call + shape mapping).
33384
+ *
33385
+ * Returns `undefined` when the trail is gone (`TrailNotFoundException`).
33386
+ */
33387
+ async readCurrentState(physicalId, _logicalId, _resourceType) {
33388
+ let trail;
33389
+ try {
33390
+ const resp = await this.getClient().send(new GetTrailCommand({ Name: physicalId }));
33391
+ trail = resp.Trail;
33392
+ } catch (err) {
33393
+ if (err instanceof TrailNotFoundException)
33394
+ return void 0;
33395
+ throw err;
33396
+ }
33397
+ if (!trail)
33398
+ return void 0;
33399
+ const result = {};
33400
+ if (trail.Name !== void 0)
33401
+ result["TrailName"] = trail.Name;
33402
+ if (trail.S3BucketName !== void 0)
33403
+ result["S3BucketName"] = trail.S3BucketName;
33404
+ if (trail.S3KeyPrefix !== void 0)
33405
+ result["S3KeyPrefix"] = trail.S3KeyPrefix;
33406
+ if (trail.IsMultiRegionTrail !== void 0) {
33407
+ result["IsMultiRegionTrail"] = trail.IsMultiRegionTrail;
33408
+ }
33409
+ if (trail.IncludeGlobalServiceEvents !== void 0) {
33410
+ result["IncludeGlobalServiceEvents"] = trail.IncludeGlobalServiceEvents;
33411
+ }
33412
+ if (trail.LogFileValidationEnabled !== void 0) {
33413
+ result["EnableLogFileValidation"] = trail.LogFileValidationEnabled;
33414
+ }
33415
+ if (trail.CloudWatchLogsLogGroupArn !== void 0) {
33416
+ result["CloudWatchLogsLogGroupArn"] = trail.CloudWatchLogsLogGroupArn;
33417
+ }
33418
+ if (trail.CloudWatchLogsRoleArn !== void 0) {
33419
+ result["CloudWatchLogsRoleArn"] = trail.CloudWatchLogsRoleArn;
33420
+ }
33421
+ if (trail.KmsKeyId !== void 0)
33422
+ result["KMSKeyId"] = trail.KmsKeyId;
33423
+ if (trail.SnsTopicName !== void 0)
33424
+ result["SnsTopicName"] = trail.SnsTopicName;
33425
+ if (trail.IsOrganizationTrail !== void 0) {
33426
+ result["IsOrganizationTrail"] = trail.IsOrganizationTrail;
33427
+ }
33428
+ try {
33429
+ const status = await this.getClient().send(new GetTrailStatusCommand({ Name: physicalId }));
33430
+ if (status.IsLogging !== void 0)
33431
+ result["IsLogging"] = status.IsLogging;
33432
+ } catch {
33433
+ }
33434
+ try {
33435
+ const sel = await this.getClient().send(
33436
+ new GetEventSelectorsCommand({ TrailName: physicalId })
33437
+ );
33438
+ if (sel.EventSelectors && sel.EventSelectors.length > 0) {
33439
+ result["EventSelectors"] = sel.EventSelectors.map(
33440
+ (es) => es
33441
+ );
33442
+ }
33443
+ } catch {
33444
+ }
33445
+ return result;
33446
+ }
31271
33447
  async import(input) {
31272
33448
  const explicit = resolveExplicitPhysicalId(input, "TrailName");
31273
33449
  if (explicit) {
@@ -31585,6 +33761,141 @@ var CodeBuildProvider = class {
31585
33761
  * `key`/`value` tags, not the standard `Key`/`Value`), match
31586
33762
  * `aws:cdk:path` tag.
31587
33763
  */
33764
+ /**
33765
+ * Read the AWS-current CodeBuild Project configuration in CFn-property shape.
33766
+ *
33767
+ * Issues `BatchGetProjects` and re-shapes the SDK's camelCase response back
33768
+ * to CFn's PascalCase shape (the `mapProperties` helper above goes the
33769
+ * other way at create time). The drift comparator only descends into
33770
+ * keys present in cdkd state, so we focus on the high-value top-level
33771
+ * fields and the most commonly-set `Source` / `Artifacts` /
33772
+ * `Environment` sub-fields. Less common nested config (full
33773
+ * `LogsConfig`, `VpcConfig` rebuild, secondary sources/artifacts, etc.)
33774
+ * is left to a follow-up — surfacing them with a partial shape would
33775
+ * fire false drift on every project that uses them.
33776
+ *
33777
+ * Tags are skipped (CDK auto-tag handling deferred). Returns `undefined`
33778
+ * when the project is gone (`projects` array empty / `projectsNotFound` set).
33779
+ */
33780
+ async readCurrentState(physicalId, _logicalId, _resourceType) {
33781
+ let project;
33782
+ try {
33783
+ const resp = await this.getClient().send(
33784
+ new BatchGetProjectsCommand({ names: [physicalId] })
33785
+ );
33786
+ project = resp.projects?.[0];
33787
+ } catch (err) {
33788
+ if (err instanceof ResourceNotFoundException15)
33789
+ return void 0;
33790
+ throw err;
33791
+ }
33792
+ if (!project)
33793
+ return void 0;
33794
+ const result = {};
33795
+ if (project.name !== void 0)
33796
+ result["Name"] = project.name;
33797
+ if (project.description !== void 0 && project.description !== "") {
33798
+ result["Description"] = project.description;
33799
+ }
33800
+ if (project.serviceRole !== void 0)
33801
+ result["ServiceRole"] = project.serviceRole;
33802
+ if (project.timeoutInMinutes !== void 0) {
33803
+ result["TimeoutInMinutes"] = project.timeoutInMinutes;
33804
+ }
33805
+ if (project.queuedTimeoutInMinutes !== void 0) {
33806
+ result["QueuedTimeoutInMinutes"] = project.queuedTimeoutInMinutes;
33807
+ }
33808
+ if (project.encryptionKey !== void 0)
33809
+ result["EncryptionKey"] = project.encryptionKey;
33810
+ if (project.concurrentBuildLimit !== void 0) {
33811
+ result["ConcurrentBuildLimit"] = project.concurrentBuildLimit;
33812
+ }
33813
+ if (project.badge?.badgeEnabled !== void 0) {
33814
+ result["BadgeEnabled"] = project.badge.badgeEnabled;
33815
+ }
33816
+ if (project.sourceVersion !== void 0)
33817
+ result["SourceVersion"] = project.sourceVersion;
33818
+ if (project.source) {
33819
+ const src = {};
33820
+ if (project.source.type !== void 0)
33821
+ src["Type"] = project.source.type;
33822
+ if (project.source.location !== void 0)
33823
+ src["Location"] = project.source.location;
33824
+ if (project.source.buildspec !== void 0)
33825
+ src["BuildSpec"] = project.source.buildspec;
33826
+ if (project.source.gitCloneDepth !== void 0) {
33827
+ src["GitCloneDepth"] = project.source.gitCloneDepth;
33828
+ }
33829
+ if (project.source.insecureSsl !== void 0)
33830
+ src["InsecureSsl"] = project.source.insecureSsl;
33831
+ if (project.source.reportBuildStatus !== void 0) {
33832
+ src["ReportBuildStatus"] = project.source.reportBuildStatus;
33833
+ }
33834
+ if (Object.keys(src).length > 0)
33835
+ result["Source"] = src;
33836
+ }
33837
+ if (project.artifacts) {
33838
+ const art = {};
33839
+ if (project.artifacts.type !== void 0)
33840
+ art["Type"] = project.artifacts.type;
33841
+ if (project.artifacts.location !== void 0)
33842
+ art["Location"] = project.artifacts.location;
33843
+ if (project.artifacts.path !== void 0)
33844
+ art["Path"] = project.artifacts.path;
33845
+ if (project.artifacts.name !== void 0)
33846
+ art["Name"] = project.artifacts.name;
33847
+ if (project.artifacts.namespaceType !== void 0) {
33848
+ art["NamespaceType"] = project.artifacts.namespaceType;
33849
+ }
33850
+ if (project.artifacts.packaging !== void 0)
33851
+ art["Packaging"] = project.artifacts.packaging;
33852
+ if (project.artifacts.encryptionDisabled !== void 0) {
33853
+ art["EncryptionDisabled"] = project.artifacts.encryptionDisabled;
33854
+ }
33855
+ if (project.artifacts.overrideArtifactName !== void 0) {
33856
+ art["OverrideArtifactName"] = project.artifacts.overrideArtifactName;
33857
+ }
33858
+ if (project.artifacts.artifactIdentifier !== void 0) {
33859
+ art["ArtifactIdentifier"] = project.artifacts.artifactIdentifier;
33860
+ }
33861
+ if (Object.keys(art).length > 0)
33862
+ result["Artifacts"] = art;
33863
+ }
33864
+ if (project.environment) {
33865
+ const env = {};
33866
+ if (project.environment.type !== void 0)
33867
+ env["Type"] = project.environment.type;
33868
+ if (project.environment.image !== void 0)
33869
+ env["Image"] = project.environment.image;
33870
+ if (project.environment.computeType !== void 0) {
33871
+ env["ComputeType"] = project.environment.computeType;
33872
+ }
33873
+ if (project.environment.privilegedMode !== void 0) {
33874
+ env["PrivilegedMode"] = project.environment.privilegedMode;
33875
+ }
33876
+ if (project.environment.imagePullCredentialsType !== void 0) {
33877
+ env["ImagePullCredentialsType"] = project.environment.imagePullCredentialsType;
33878
+ }
33879
+ if (project.environment.certificate !== void 0) {
33880
+ env["Certificate"] = project.environment.certificate;
33881
+ }
33882
+ if (project.environment.environmentVariables && project.environment.environmentVariables.length > 0) {
33883
+ env["EnvironmentVariables"] = project.environment.environmentVariables.map((ev) => {
33884
+ const out = {};
33885
+ if (ev.name !== void 0)
33886
+ out["Name"] = ev.name;
33887
+ if (ev.value !== void 0)
33888
+ out["Value"] = ev.value;
33889
+ if (ev.type !== void 0)
33890
+ out["Type"] = ev.type;
33891
+ return out;
33892
+ });
33893
+ }
33894
+ if (Object.keys(env).length > 0)
33895
+ result["Environment"] = env;
33896
+ }
33897
+ return result;
33898
+ }
31588
33899
  async import(input) {
31589
33900
  const explicit = resolveExplicitPhysicalId(input, "Name");
31590
33901
  if (explicit) {
@@ -31791,6 +34102,49 @@ var S3VectorsProvider = class {
31791
34102
  nextToken = listResult.nextToken;
31792
34103
  } while (nextToken);
31793
34104
  }
34105
+ /**
34106
+ * Read the AWS-current S3 Vector Bucket configuration in CFn-property
34107
+ * shape.
34108
+ *
34109
+ * Issues `GetVectorBucket` for the bucket name (the physical id) and
34110
+ * surfaces `VectorBucketName` and `EncryptionConfiguration` (re-shaping
34111
+ * the camelCase SDK response back to PascalCase CFn property names —
34112
+ * `sseType` → `SSEType`, `kmsKeyArn` → `KMSKeyArn`).
34113
+ *
34114
+ * Returns `undefined` when the bucket is gone (`NotFoundException` /
34115
+ * `NoSuchVectorBucket`).
34116
+ */
34117
+ async readCurrentState(physicalId, _logicalId, _resourceType) {
34118
+ let resp;
34119
+ try {
34120
+ resp = await this.getClient().send(
34121
+ new GetVectorBucketCommand({ vectorBucketName: physicalId })
34122
+ );
34123
+ } catch (err) {
34124
+ if (this.isNotFoundError(err))
34125
+ return void 0;
34126
+ throw err;
34127
+ }
34128
+ const result = {};
34129
+ const bucket = resp.vectorBucket;
34130
+ if (bucket?.vectorBucketName !== void 0) {
34131
+ result["VectorBucketName"] = bucket.vectorBucketName;
34132
+ } else {
34133
+ result["VectorBucketName"] = physicalId;
34134
+ }
34135
+ if (bucket?.encryptionConfiguration) {
34136
+ const enc = {};
34137
+ if (bucket.encryptionConfiguration.sseType !== void 0) {
34138
+ enc["SSEType"] = bucket.encryptionConfiguration.sseType;
34139
+ }
34140
+ if (bucket.encryptionConfiguration.kmsKeyArn !== void 0) {
34141
+ enc["KMSKeyArn"] = bucket.encryptionConfiguration.kmsKeyArn;
34142
+ }
34143
+ if (Object.keys(enc).length > 0)
34144
+ result["EncryptionConfiguration"] = enc;
34145
+ }
34146
+ return result;
34147
+ }
31794
34148
  /**
31795
34149
  * Adopt an existing S3 Vector Bucket into cdkd state.
31796
34150
  *
@@ -32060,6 +34414,48 @@ var S3DirectoryBucketProvider = class {
32060
34414
  continuationToken = listResponse.IsTruncated ? listResponse.NextContinuationToken : void 0;
32061
34415
  } while (continuationToken);
32062
34416
  }
34417
+ /**
34418
+ * Read the AWS-current S3 Express Directory Bucket configuration in
34419
+ * CFn-property shape.
34420
+ *
34421
+ * Issues `HeadBucket` to verify existence and surfaces `BucketName`
34422
+ * (the physicalId). `DataRedundancy` and `LocationName` are not exposed
34423
+ * by any cheap S3 Express API — the only way to inspect them is by
34424
+ * parsing the bucket name's `--<az-id>--x-s3` suffix, which is best
34425
+ * effort. We surface them when they are recoverable from the bucket
34426
+ * name to give the comparator a chance to detect mismatches.
34427
+ *
34428
+ * `--<az-id>--x-s3` suffix parsing: directory bucket names follow the
34429
+ * format `<base>--<az-id>--x-s3`, e.g.
34430
+ * `my-bucket--use1-az1--x-s3`. We don't reverse the AZ-ID -> AZ-name
34431
+ * mapping here (that would require a per-call EC2 `DescribeAvailabilityZones`
34432
+ * round-trip); state's `LocationName` is `us-east-1a--x-s3`-style,
34433
+ * while the bucket name carries the AZ-ID `use1-az1`. Cross-region
34434
+ * mapping is too expensive for v1 — we omit `LocationName` from the
34435
+ * snapshot and rely on the comparator's "key absent in state never
34436
+ * drifts" rule to no-op against state.
34437
+ *
34438
+ * Returns `undefined` when the bucket is gone (`HeadBucket` returns
34439
+ * `NotFound` / `NoSuchBucket`).
34440
+ */
34441
+ async readCurrentState(physicalId, _logicalId, _resourceType) {
34442
+ try {
34443
+ await this.s3Client.send(new HeadBucketCommand4({ Bucket: physicalId }));
34444
+ } catch (err) {
34445
+ const e = err;
34446
+ if (e.name === "NotFound" || e.name === "NoSuchBucket" || e.name === "BucketNotFound") {
34447
+ return void 0;
34448
+ }
34449
+ throw err;
34450
+ }
34451
+ const result = {
34452
+ BucketName: physicalId
34453
+ };
34454
+ if (physicalId.endsWith("--x-s3")) {
34455
+ result["DataRedundancy"] = "SingleAvailabilityZone";
34456
+ }
34457
+ return result;
34458
+ }
32063
34459
  /**
32064
34460
  * Adopt an existing S3 Express Directory Bucket into cdkd state.
32065
34461
  *
@@ -32464,6 +34860,97 @@ var S3TablesProvider = class {
32464
34860
  );
32465
34861
  }
32466
34862
  }
34863
+ // ─── readCurrentState dispatch ───────────────────────────────────
34864
+ /**
34865
+ * Read the AWS-current S3 Tables resource configuration in CFn-property
34866
+ * shape.
34867
+ *
34868
+ * - **AWS::S3Tables::TableBucket**: `GetTableBucket` for the ARN; we
34869
+ * surface `TableBucketName` (the only mutable cdkd-managed property).
34870
+ * - **AWS::S3Tables::Namespace**: parses `tableBucketARN|namespace`
34871
+ * from physical id and surfaces `TableBucketARN` and `Namespace`
34872
+ * (as a `string[]` with one entry, matching `create()`'s shape).
34873
+ * No GetNamespace call — the physical id IS the source of truth and
34874
+ * AWS surfaces no additional managed fields cdkd cares about.
34875
+ * - **AWS::S3Tables::Table**: parses `tableBucketARN|namespace|name`
34876
+ * from physical id, calls `GetTable` to verify existence and recover
34877
+ * `format`, surfaces `TableBucketARN`, `Namespace` (string), `Name`,
34878
+ * `Format`.
34879
+ *
34880
+ * Returns `undefined` when the resource is gone (`NotFoundException`).
34881
+ */
34882
+ async readCurrentState(physicalId, logicalId, resourceType) {
34883
+ switch (resourceType) {
34884
+ case "AWS::S3Tables::TableBucket":
34885
+ return this.readTableBucketCurrentState(physicalId);
34886
+ case "AWS::S3Tables::Namespace":
34887
+ return this.readNamespaceCurrentState(physicalId);
34888
+ case "AWS::S3Tables::Table":
34889
+ return this.readTableCurrentState(physicalId);
34890
+ default:
34891
+ this.logger.debug(
34892
+ `readCurrentState: unsupported resource type ${resourceType} for ${logicalId}`
34893
+ );
34894
+ return void 0;
34895
+ }
34896
+ }
34897
+ async readTableBucketCurrentState(physicalId) {
34898
+ let bucket;
34899
+ try {
34900
+ const resp = await this.getClient().send(
34901
+ new GetTableBucketCommand({ tableBucketARN: physicalId })
34902
+ );
34903
+ bucket = resp;
34904
+ } catch (err) {
34905
+ if (err instanceof NotFoundException6)
34906
+ return void 0;
34907
+ throw err;
34908
+ }
34909
+ const result = {};
34910
+ if (bucket.name !== void 0)
34911
+ result["TableBucketName"] = bucket.name;
34912
+ return result;
34913
+ }
34914
+ // eslint-disable-next-line @typescript-eslint/require-await -- structural; physical id is the source of truth
34915
+ async readNamespaceCurrentState(physicalId) {
34916
+ const [tableBucketARN, namespaceName] = physicalId.split("|");
34917
+ if (!tableBucketARN || !namespaceName)
34918
+ return void 0;
34919
+ return {
34920
+ TableBucketARN: tableBucketARN,
34921
+ Namespace: [namespaceName]
34922
+ };
34923
+ }
34924
+ async readTableCurrentState(physicalId) {
34925
+ const parts = physicalId.split("|");
34926
+ if (parts.length < 3)
34927
+ return void 0;
34928
+ const [tableBucketARN, namespace, name] = parts;
34929
+ if (!tableBucketARN || !namespace || !name)
34930
+ return void 0;
34931
+ let resp;
34932
+ try {
34933
+ resp = await this.getClient().send(
34934
+ new GetTableCommand2({
34935
+ tableBucketARN,
34936
+ namespace,
34937
+ name
34938
+ })
34939
+ );
34940
+ } catch (err) {
34941
+ if (err instanceof NotFoundException6)
34942
+ return void 0;
34943
+ throw err;
34944
+ }
34945
+ const result = {
34946
+ TableBucketARN: tableBucketARN,
34947
+ Namespace: namespace,
34948
+ Name: resp.name ?? name
34949
+ };
34950
+ if (resp.format !== void 0)
34951
+ result["Format"] = resp.format;
34952
+ return result;
34953
+ }
32467
34954
  // ─── Import dispatch ──────────────────────────────────────────────
32468
34955
  /**
32469
34956
  * Adopt an existing S3 Tables resource into cdkd state.
@@ -38869,7 +41356,7 @@ function reorderArgs(argv) {
38869
41356
  }
38870
41357
  async function main() {
38871
41358
  const program = new Command14();
38872
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.39.0");
41359
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.41.0");
38873
41360
  program.addCommand(createBootstrapCommand());
38874
41361
  program.addCommand(createSynthCommand());
38875
41362
  program.addCommand(createListCommand());