@go-to-k/cdkd 0.104.0 → 0.105.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
@@ -35,6 +35,7 @@ import { Command, Option } from "commander";
35
35
  import { writeFileSync as writeFileSync$1 } from "fs";
36
36
  import { join as join$1 } from "path";
37
37
  import * as zlib from "node:zlib";
38
+ import { ApplicationAutoScalingClient, DescribeScalingPoliciesCommand } from "@aws-sdk/client-application-auto-scaling";
38
39
  import { ApiGatewayV2Client, CreateApiCommand, CreateAuthorizerCommand as CreateAuthorizerCommand$1, CreateIntegrationCommand, CreateRouteCommand as CreateRouteCommand$1, CreateStageCommand as CreateStageCommand$1, DeleteApiCommand, DeleteAuthorizerCommand as DeleteAuthorizerCommand$1, DeleteIntegrationCommand, DeleteRouteCommand as DeleteRouteCommand$1, DeleteStageCommand as DeleteStageCommand$1, GetApiCommand, GetApisCommand, GetAuthorizerCommand as GetAuthorizerCommand$1, GetIntegrationCommand, GetRouteCommand, GetStageCommand as GetStageCommand$1, NotFoundException as NotFoundException$3, UpdateApiCommand, UpdateAuthorizerCommand as UpdateAuthorizerCommand$1, UpdateIntegrationCommand, UpdateRouteCommand, UpdateStageCommand as UpdateStageCommand$1 } from "@aws-sdk/client-apigatewayv2";
39
40
  import { CreateStateMachineCommand, DeleteStateMachineCommand, DescribeStateMachineCommand, ListStateMachinesCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$9, SFNClient, StateMachineDoesNotExist, TagResourceCommand as TagResourceCommand$10, UntagResourceCommand as UntagResourceCommand$9, UpdateStateMachineCommand } from "@aws-sdk/client-sfn";
40
41
  import { CreateClusterCommand, CreateServiceCommand, DeleteClusterCommand, DeleteServiceCommand, DeregisterTaskDefinitionCommand, DescribeClustersCommand, DescribeServicesCommand, DescribeTaskDefinitionCommand, ECSClient, ListClustersCommand, ListServicesCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$10, PutClusterCapacityProvidersCommand, RegisterTaskDefinitionCommand, TagResourceCommand as TagResourceCommand$11, UntagResourceCommand as UntagResourceCommand$10, UpdateClusterCommand, UpdateServiceCommand } from "@aws-sdk/client-ecs";
@@ -7878,13 +7879,26 @@ var DynamoDBTableProvider = class {
7878
7879
  * calling `update()`, but the guard is defense-in-depth.
7879
7880
  * - Per-replica drift (`ContributorInsightsSpecification` /
7880
7881
  * `PointInTimeRecoverySpecification` / `KinesisStreamSpecification`)
7881
- * is surfaced for the LOCAL replica only; cross-region replicas
7882
- * require per-region SDK clients which are out of scope for v1.
7882
+ * is surfaced for BOTH the LOCAL replica AND cross-region replicas
7883
+ * via per-region SDK clients (cached in `regionalClientCache` for
7884
+ * the deploy run). Issue #389 lifted the v1 LOCAL-only limitation.
7885
+ * - Cross-region replica Tags propagation (Issue #389): when the
7886
+ * update path detects a Tags-only diff on a non-local replica,
7887
+ * cdkd resolves the replica's table ARN by swapping the region
7888
+ * segment of the local ARN and issues `TagResource` /
7889
+ * `UntagResource` against a per-region client.
7883
7890
  */
7884
7891
  var DynamoDBGlobalTableProvider = class {
7885
7892
  dynamoDBClient;
7886
7893
  logger = getLogger().child("DynamoDBGlobalTableProvider");
7887
7894
  /**
7895
+ * Caches per-region `DynamoDBClient` instances for cross-region drift
7896
+ * reads (`readCurrentState`) and cross-region Tag propagation
7897
+ * (`update()`). Keyed by region string; reuses the default credential
7898
+ * chain. Lifetime is the provider instance — one deploy run.
7899
+ */
7900
+ regionalClientCache = /* @__PURE__ */ new Map();
7901
+ /**
7888
7902
  * Caches `getAttribute(physicalId, attribute)` results for the lifetime
7889
7903
  * of this provider instance (one deploy run). Safe under the current
7890
7904
  * `update()` contract because `update()` cannot mid-deploy mutate
@@ -7916,6 +7930,50 @@ var DynamoDBGlobalTableProvider = class {
7916
7930
  this.dynamoDBClient = awsClients.dynamoDB;
7917
7931
  }
7918
7932
  /**
7933
+ * Return a `DynamoDBClient` pinned to the given region, caching per
7934
+ * region for the lifetime of this provider instance. Uses the default
7935
+ * credential chain (env / shared config / IAM role) — no explicit
7936
+ * credential plumbing needed.
7937
+ *
7938
+ * Used by `readCurrentState` (cross-region per-replica sub-spec reads)
7939
+ * and `update()` (cross-region replica Tag propagation). Both code
7940
+ * paths fire region-scoped DynamoDB APIs (`DescribeContributorInsights`
7941
+ * / `DescribeContinuousBackups` / `DescribeKinesisStreamingDestination`
7942
+ * / `TagResource` / `UntagResource`) against the replica's region.
7943
+ *
7944
+ * The cache may return `this.dynamoDBClient` when `region` happens to
7945
+ * match the local client's region — in tests the local mock is
7946
+ * intercepted via `vi.mock('../../utils/aws-clients.js')` so reuse
7947
+ * is safe (and explicitly desired so the mock catches the call).
7948
+ */
7949
+ getRegionalClient(region) {
7950
+ const cached = this.regionalClientCache.get(region);
7951
+ if (cached) return cached;
7952
+ const client = new DynamoDBClient({ region });
7953
+ this.regionalClientCache.set(region, client);
7954
+ return client;
7955
+ }
7956
+ /**
7957
+ * Construct the regional table ARN for a cross-region replica of a
7958
+ * GlobalTable. AWS replicates the same `TableName` across every
7959
+ * replica region, with each replica's ARN differing only in the
7960
+ * `:<region>:` segment. Cheaper than a second `DescribeTable` round-
7961
+ * trip on the regional client.
7962
+ *
7963
+ * Example:
7964
+ * local ARN: arn:aws:dynamodb:us-east-1:123:table/Foo
7965
+ * for eu-west-1 → arn:aws:dynamodb:eu-west-1:123:table/Foo
7966
+ *
7967
+ * Returns `undefined` when the local ARN is malformed (defensive —
7968
+ * downstream callers omit the offending operation rather than throw).
7969
+ */
7970
+ replicaArnForRegion(localTableArn, targetRegion) {
7971
+ const segments = localTableArn.split(":");
7972
+ if (segments.length < 6) return void 0;
7973
+ segments[3] = targetRegion;
7974
+ return segments.join(":");
7975
+ }
7976
+ /**
7919
7977
  * Create a DynamoDB Global Table (CDK TableV2).
7920
7978
  *
7921
7979
  * GlobalTable is built on the regular DynamoDB Table primitive: cdkd issues
@@ -8167,12 +8225,24 @@ var DynamoDBGlobalTableProvider = class {
8167
8225
  for (const replica of replicaDiff.modified) {
8168
8226
  const region = replica["Region"];
8169
8227
  if (!region || region === currentRegion) continue;
8228
+ const oldReplicaTags = (previousProperties["Replicas"] ?? []).find((r) => r["Region"] === region)?.["Tags"];
8229
+ const newReplicaTags = replica["Tags"];
8230
+ if (!deepEqual$1(oldReplicaTags, newReplicaTags)) if (tableArn) {
8231
+ const replicaArn = this.replicaArnForRegion(tableArn, region);
8232
+ if (replicaArn) try {
8233
+ const regionalClient = this.getRegionalClient(region);
8234
+ await this.applyTagDiffOnClient(regionalClient, replicaArn, oldReplicaTags, newReplicaTags);
8235
+ } catch (tagErr) {
8236
+ this.logger.warn(`Could not apply Tags diff to cross-region replica ${region} of ${physicalId}: ${tagErr instanceof Error ? tagErr.message : String(tagErr)}. The replica's Tags state will surface as drift until the next successful deploy.`);
8237
+ }
8238
+ else this.logger.warn(`Could not derive replica ARN for region ${region} from ${tableArn} — skipping Tags propagation for ${physicalId}`);
8239
+ } else this.logger.warn(`Local DescribeTable returned no TableArn — cannot propagate Tags to cross-region replica ${region} of ${physicalId}`);
8170
8240
  const updateAction = { RegionName: region };
8171
8241
  if (replica["KMSMasterKeyId"] !== void 0) updateAction.KMSMasterKeyId = replica["KMSMasterKeyId"];
8172
8242
  if (replica["GlobalSecondaryIndexes"]) updateAction.GlobalSecondaryIndexes = replica["GlobalSecondaryIndexes"];
8173
8243
  if (replica["TableClassOverride"]) updateAction.TableClassOverride = replica["TableClassOverride"];
8174
8244
  if (!(updateAction.KMSMasterKeyId !== void 0 || updateAction.GlobalSecondaryIndexes !== void 0 || updateAction.TableClassOverride !== void 0)) {
8175
- this.logger.debug(`Cross-region replica ${region} of ${physicalId}: only Tags-style changes detected; skipping UpdateReplica (AWS rejects empty Update actions). Per-region Tag propagation is deferred.`);
8245
+ this.logger.debug(`Cross-region replica ${region} of ${physicalId}: only Tags-style changes detected; UpdateReplica skipped (AWS rejects empty Update actions). Tags propagation handled above via per-region client.`);
8176
8246
  continue;
8177
8247
  }
8178
8248
  await this.dynamoDBClient.send(new UpdateTableCommand({
@@ -8259,10 +8329,22 @@ var DynamoDBGlobalTableProvider = class {
8259
8329
  }
8260
8330
  /**
8261
8331
  * Apply a diff between old and new CFn-shape Tags arrays via DynamoDB's
8262
- * `TagResource` / `UntagResource` APIs. Both take the table ARN as
8263
- * `ResourceArn`.
8332
+ * `TagResource` / `UntagResource` APIs against the local client. Both
8333
+ * take the table ARN as `ResourceArn`.
8334
+ *
8335
+ * Local-replica convenience wrapper around `applyTagDiffOnClient` so
8336
+ * existing call sites stay unchanged.
8264
8337
  */
8265
8338
  async applyTagDiff(tableArn, oldTagsRaw, newTagsRaw) {
8339
+ await this.applyTagDiffOnClient(this.dynamoDBClient, tableArn, oldTagsRaw, newTagsRaw);
8340
+ }
8341
+ /**
8342
+ * Apply a Tags diff against the given `DynamoDBClient` (which may be
8343
+ * the local client or a per-region client returned by
8344
+ * `getRegionalClient`). Used by the local-replica path AND the
8345
+ * cross-region replica Tags propagation path (Issue #389).
8346
+ */
8347
+ async applyTagDiffOnClient(client, tableArn, oldTagsRaw, newTagsRaw) {
8266
8348
  const toMap = (tags) => {
8267
8349
  const m = /* @__PURE__ */ new Map();
8268
8350
  for (const t of tags ?? []) if (t.Key !== void 0 && t.Value !== void 0) m.set(t.Key, t.Value);
@@ -8278,14 +8360,14 @@ var DynamoDBGlobalTableProvider = class {
8278
8360
  const tagsToRemove = [];
8279
8361
  for (const k of oldMap.keys()) if (!newMap.has(k)) tagsToRemove.push(k);
8280
8362
  if (tagsToRemove.length > 0) {
8281
- await this.dynamoDBClient.send(new UntagResourceCommand$2({
8363
+ await client.send(new UntagResourceCommand$2({
8282
8364
  ResourceArn: tableArn,
8283
8365
  TagKeys: tagsToRemove
8284
8366
  }));
8285
8367
  this.logger.debug(`Removed ${tagsToRemove.length} tag(s) from DynamoDB GlobalTable ${tableArn}`);
8286
8368
  }
8287
8369
  if (tagsToAdd.length > 0) {
8288
- await this.dynamoDBClient.send(new TagResourceCommand$2({
8370
+ await client.send(new TagResourceCommand$2({
8289
8371
  ResourceArn: tableArn,
8290
8372
  Tags: tagsToAdd
8291
8373
  }));
@@ -8453,20 +8535,36 @@ var DynamoDBGlobalTableProvider = class {
8453
8535
  result["Replicas"] = await Promise.all((table.Replicas ?? []).map(async (r) => {
8454
8536
  const entry = { Region: r.RegionName };
8455
8537
  if (r.KMSMasterKeyId !== void 0) entry["KMSMasterKeyId"] = r.KMSMasterKeyId;
8456
- if (r.RegionName && r.RegionName === currentRegion) {
8457
- const subs = await this.readLocalReplicaSubSpecs(tableNameForSubs);
8458
- Object.assign(entry, subs);
8459
- if (table.TableArn) try {
8460
- entry["Tags"] = normalizeAwsTagsToCfn((await this.dynamoDBClient.send(new ListTagsOfResourceCommand({ ResourceArn: table.TableArn }))).Tags);
8461
- } catch (tagErr) {
8462
- if (tagErr instanceof ResourceNotFoundException$1) throw tagErr;
8463
- this.logger.warn(`Could not fetch tags for DynamoDB GlobalTable ${tableNameForSubs}: ${tagErr instanceof Error ? tagErr.message : String(tagErr)}`);
8538
+ if (!r.RegionName) return entry;
8539
+ const isLocal = r.RegionName === currentRegion;
8540
+ const client = isLocal ? this.dynamoDBClient : this.getRegionalClient(r.RegionName);
8541
+ const regionLabel = r.RegionName;
8542
+ const replicaArn = isLocal ? table.TableArn : table.TableArn ? this.replicaArnForRegion(table.TableArn, r.RegionName) : void 0;
8543
+ const subs = await this.readReplicaSubSpecs(client, tableNameForSubs, regionLabel);
8544
+ Object.assign(entry, subs);
8545
+ if (replicaArn) try {
8546
+ entry["Tags"] = normalizeAwsTagsToCfn((await client.send(new ListTagsOfResourceCommand({ ResourceArn: replicaArn }))).Tags);
8547
+ } catch (tagErr) {
8548
+ if (tagErr instanceof ResourceNotFoundException$1) {
8549
+ if (isLocal) throw tagErr;
8550
+ this.logger.debug(`Cross-region replica ${regionLabel} returned RNF on ListTagsOfResource; omitting Tags`);
8551
+ entry["Tags"] = [];
8552
+ } else {
8553
+ this.logger.warn(`Could not fetch tags for DynamoDB GlobalTable ${tableNameForSubs} in ${regionLabel}: ${tagErr instanceof Error ? tagErr.message : String(tagErr)}`);
8464
8554
  entry["Tags"] = [];
8465
8555
  }
8466
- else entry["Tags"] = [];
8467
8556
  }
8557
+ else entry["Tags"] = [];
8468
8558
  return entry;
8469
8559
  }));
8560
+ if (table.OnDemandThroughput?.MaxWriteRequestUnits !== void 0) result["WriteOnDemandThroughputSettings"] = { MaxWriteRequestUnits: table.OnDemandThroughput.MaxWriteRequestUnits };
8561
+ else result["WriteOnDemandThroughputSettings"] = {};
8562
+ if (billingMode === "PROVISIONED") {
8563
+ const writeCapacity = table.ProvisionedThroughput?.WriteCapacityUnits;
8564
+ if (writeCapacity !== void 0) if (!await this.hasWriteAutoScalingPolicy(tableNameForSubs)) result["WriteProvisionedThroughputSettings"] = { WriteCapacityUnits: writeCapacity };
8565
+ else result["WriteProvisionedThroughputSettings"] = {};
8566
+ else result["WriteProvisionedThroughputSettings"] = {};
8567
+ } else result["WriteProvisionedThroughputSettings"] = {};
8470
8568
  try {
8471
8569
  const ttlDesc = (await this.dynamoDBClient.send(new DescribeTimeToLiveCommand({ TableName: tableNameForSubs }))).TimeToLiveDescription;
8472
8570
  const ttlStatus = ttlDesc?.TimeToLiveStatus;
@@ -8485,7 +8583,9 @@ var DynamoDBGlobalTableProvider = class {
8485
8583
  }
8486
8584
  }
8487
8585
  /**
8488
- * Read per-replica sub-specifications for the LOCAL replica:
8586
+ * Read per-replica sub-specifications against the given `DynamoDBClient`
8587
+ * (which may be the local client or a per-region client returned by
8588
+ * `getRegionalClient`):
8489
8589
  * - `ContributorInsightsSpecification` via `DescribeContributorInsights`
8490
8590
  * (table-level; GSI overrides are NOT surfaced in v1 — they would
8491
8591
  * require one call per GSI and a different CFn nesting under the
@@ -8498,51 +8598,86 @@ var DynamoDBGlobalTableProvider = class {
8498
8598
  * Each call is best-effort: errors omit the offending key rather than
8499
8599
  * fail the whole drift read.
8500
8600
  *
8501
- * Cross-region replicas would need per-region SDK clients (the calls
8502
- * are region-scoped to the replica) deferred to a follow-up PR.
8601
+ * Issue #389 lifted the LOCAL-only limitation by parameterizing the
8602
+ * client the same reverse-mapping logic runs against any region's
8603
+ * client.
8503
8604
  */
8504
- async readLocalReplicaSubSpecs(tableName) {
8605
+ async readReplicaSubSpecs(client, tableName, regionLabel) {
8505
8606
  const out = {};
8506
8607
  try {
8507
- const ci = await this.dynamoDBClient.send(new DescribeContributorInsightsCommand({ TableName: tableName }));
8608
+ const ci = await client.send(new DescribeContributorInsightsCommand({ TableName: tableName }));
8508
8609
  if (ci.ContributorInsightsStatus) out["ContributorInsightsSpecification"] = { Enabled: ci.ContributorInsightsStatus === "ENABLED" };
8509
8610
  } catch (err) {
8510
- this.logger.debug(`Could not read ContributorInsights for ${tableName}: ${err instanceof Error ? err.message : String(err)}`);
8611
+ this.logger.debug(`Could not read ContributorInsights for ${tableName} in ${regionLabel}: ${err instanceof Error ? err.message : String(err)}`);
8511
8612
  }
8512
8613
  try {
8513
- const pitrStatus = (await this.dynamoDBClient.send(new DescribeContinuousBackupsCommand({ TableName: tableName }))).ContinuousBackupsDescription?.PointInTimeRecoveryDescription?.PointInTimeRecoveryStatus;
8614
+ const pitrStatus = (await client.send(new DescribeContinuousBackupsCommand({ TableName: tableName }))).ContinuousBackupsDescription?.PointInTimeRecoveryDescription?.PointInTimeRecoveryStatus;
8514
8615
  if (pitrStatus) out["PointInTimeRecoverySpecification"] = { PointInTimeRecoveryEnabled: pitrStatus === "ENABLED" };
8515
8616
  } catch (err) {
8516
- this.logger.debug(`Could not read PointInTimeRecovery for ${tableName}: ${err instanceof Error ? err.message : String(err)}`);
8617
+ this.logger.debug(`Could not read PointInTimeRecovery for ${tableName} in ${regionLabel}: ${err instanceof Error ? err.message : String(err)}`);
8517
8618
  }
8518
8619
  try {
8519
- const active = ((await this.dynamoDBClient.send(new DescribeKinesisStreamingDestinationCommand({ TableName: tableName }))).KinesisDataStreamDestinations ?? []).find((d) => d.DestinationStatus === "ACTIVE" || d.DestinationStatus === "ENABLING");
8620
+ const active = ((await client.send(new DescribeKinesisStreamingDestinationCommand({ TableName: tableName }))).KinesisDataStreamDestinations ?? []).find((d) => d.DestinationStatus === "ACTIVE" || d.DestinationStatus === "ENABLING");
8520
8621
  if (active?.StreamArn) {
8521
8622
  const ksOut = { StreamArn: active.StreamArn };
8522
8623
  if (active.ApproximateCreationDateTimePrecision !== void 0) ksOut["ApproximateCreationDateTimePrecision"] = active.ApproximateCreationDateTimePrecision;
8523
8624
  out["KinesisStreamSpecification"] = ksOut;
8524
8625
  }
8525
8626
  } catch (err) {
8526
- this.logger.debug(`Could not read KinesisStreamingDestination for ${tableName}: ${err instanceof Error ? err.message : String(err)}`);
8627
+ this.logger.debug(`Could not read KinesisStreamingDestination for ${tableName} in ${regionLabel}: ${err instanceof Error ? err.message : String(err)}`);
8527
8628
  }
8528
8629
  return out;
8529
8630
  }
8530
8631
  /**
8632
+ * Detect whether application-autoscaling has a scaling policy on this
8633
+ * table's WriteCapacityUnits dimension. Used to decide whether the
8634
+ * `WriteProvisionedThroughputSettings.WriteCapacityUnits` flat-value
8635
+ * surface in `readCurrentState` is safe to emit (auto-scaling
8636
+ * dynamically mutates capacity, so a flat snapshot would fire false
8637
+ * drift on every scale event — when an autoscaling policy is in play
8638
+ * we omit the flat surface so a follow-up PR can reverse-map the
8639
+ * full `WriteCapacityAutoScalingSettings` shape).
8640
+ *
8641
+ * Best-effort: errors return `false` (no autoscaling detected) so a
8642
+ * permissions gap on `application-autoscaling:DescribeScalingPolicies`
8643
+ * does not abort drift reads. Logged at debug.
8644
+ */
8645
+ async hasWriteAutoScalingPolicy(tableName) {
8646
+ try {
8647
+ return ((await new ApplicationAutoScalingClient({ region: await this.dynamoDBClient.config.region() ?? "" }).send(new DescribeScalingPoliciesCommand({
8648
+ ServiceNamespace: "dynamodb",
8649
+ ResourceId: `table/${tableName}`,
8650
+ ScalableDimension: "dynamodb:table:WriteCapacityUnits"
8651
+ }))).ScalingPolicies ?? []).length > 0;
8652
+ } catch (err) {
8653
+ this.logger.debug(`Could not query application-autoscaling for ${tableName}: ${err instanceof Error ? err.message : String(err)}`);
8654
+ return false;
8655
+ }
8656
+ }
8657
+ /**
8531
8658
  * State property paths cdkd's GlobalTable readCurrentState cannot (yet)
8532
8659
  * reverse-map. The drift comparator skips these so a templated value
8533
8660
  * doesn't fire guaranteed false drift on every clean run.
8534
8661
  *
8535
- * - `WriteProvisionedThroughputSettings` /
8536
- * `WriteOnDemandThroughputSettings`: CFn's shapes wrap
8537
- * auto-scaling / on-demand max-RU settings whose reverse-mapping
8538
- * from `DescribeTable.ProvisionedThroughput` / `OnDemandThroughput`
8539
- * is non-trivial and would fire false drift in v1.
8540
- *
8541
- * `TimeToLiveSpecification` is reverse-mapped via `DescribeTimeToLive`
8542
- * in `readCurrentState` (no longer in this list).
8662
+ * Issue #389 emptied this list:
8663
+ * - `WriteProvisionedThroughputSettings` (flat-WriteCapacityUnits
8664
+ * subset) is now reverse-mapped from `Table.ProvisionedThroughput`
8665
+ * when BillingMode is PROVISIONED AND application-autoscaling has
8666
+ * no policy on the WriteCapacityUnits dimension. Auto-scaling
8667
+ * cases emit an empty `{}` placeholder so the comparator does NOT
8668
+ * fire false drift on the literal `WriteCapacityUnits` subtree.
8669
+ * - `WriteOnDemandThroughputSettings` is reverse-mapped from
8670
+ * `Table.OnDemandThroughput.MaxWriteRequestUnits`. Always-emit
8671
+ * `{}` placeholder when AWS reports no override.
8672
+ * - `TimeToLiveSpecification` is reverse-mapped via
8673
+ * `DescribeTimeToLive` in `readCurrentState`.
8674
+ *
8675
+ * Returning an empty list is the canonical "no known-unknown paths"
8676
+ * shape — keeping the method present (rather than removing it) for
8677
+ * future additions and for backward compat on test reflection.
8543
8678
  */
8544
8679
  getDriftUnknownPaths(_resourceType) {
8545
- return ["WriteProvisionedThroughputSettings", "WriteOnDemandThroughputSettings"];
8680
+ return [];
8546
8681
  }
8547
8682
  /**
8548
8683
  * Adopt an existing DynamoDB GlobalTable into cdkd state.
@@ -44028,7 +44163,7 @@ function reorderArgs(argv) {
44028
44163
  */
44029
44164
  async function main() {
44030
44165
  const program = new Command();
44031
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.104.0");
44166
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.105.0");
44032
44167
  program.addCommand(createBootstrapCommand());
44033
44168
  program.addCommand(createSynthCommand());
44034
44169
  program.addCommand(createListCommand());