@go-to-k/cdkd 0.281.9 → 0.281.11

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
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { $ as replayWarn, $t as uploadCfnTemplate, A as green, An as normalizeAwsError, At as formatDockerLoginError, B as slowCcOperationTimeoutMs, Bt as resolveApp, C as MULTI_REGION_RECREATE_BLOCKED_TYPES, Cn as ResourceUpdateNotSupportedError, Ct as BOOTSTRAP_MARKER_PREFIX, D as bold, Dt as validateAssetBucketName, E as formatResourceLine, Et as parseBootstrapMarker, F as clearOnUpdateRemoval, Ft as getDockerImageBySourceHash, G as getAccountInfo, Gt as resolveStateBucketWithDefaultAndSource, H as isTerminationProtectionPropagationError, Ht as resolveCaptureObservedState, I as ProviderRegistry, It as Synthesizer, J as normalizeAwsTagsToCfn, Jt as warnDeprecatedNoPrefixCliFlag, K as refStateLookupFromResource, Kt as resolveUseCdkBootstrapAssets, L as findActionableSilentDrops, Lt as synthesisStatusMessage, M as yellow, Mt as runDockerForeground, N as IAMRoleProvider, Nt as runDockerStreaming, O as cyan, Ot as validateContainerRepoName, P as collectInlinePolicyNamesManagedBySiblings, Pt as AssetManifestLoader, Q as readConfigString, Qt as findLargeInlineResources, R as findSilentDropProperties, Rt as getDefaultStateBucketName, S as extractDeploymentEventError, Sn as ResourceTimeoutError, St as AssetModeResolver, T as renderStatefulReason, Tn as StackTerminationProtectionError, Tt as getBootstrapMarkerKey, U as IntrinsicFunctionResolver, Ut as resolveSkipPrefix, V as disableInstanceApiTermination, Vt as resolveAutoAssetStorage, W as cfnRefValueFromPhysicalId, Wt as resolveStateBucketWithDefault, X as assertRegionMatch, Xt as CFN_TEMPLATE_URL_LIMIT, Y as resolveExplicitPhysicalId, Yt as CFN_TEMPLATE_BODY_LIMIT, Z as configStringRefusal, Zt as MIGRATE_TMP_PREFIX, _ as createPreDeleteFinalSnapshot, _t as WorkGraph, a as DeploymentEventsStore, an as AwsClients, at as describeTypeWithThrottleRetry, b as unsupportedFinalSnapshotError, bn as PartialFailureError, bt as loadPublishableAssetManifest, c as replayFailedOperations, cn as setAwsClients, ct as isThrottlingError, d as IMPLICIT_DELETE_DEPENDENCIES, dt as LockManager, en as expectedOwnerParam, et as requireConfigArray, f as computeImplicitDeleteEdges, ft as S3StateBackend, g as ccRoutedFinalSnapshotError, gn as LocalStartServiceError, gt as stringifyValue, h as buildFinalSnapshotIdentifier, hn as LocalMigrateError, ht as AssetPublisher, i as DeploymentEventsReader, in as resolveBucketRegion, it as DiffCalculator, j as red, jn as withErrorHandling, jt as getDockerCmd, k as gray, kt as buildDockerImage, l as replayRollback, lt as DagBuilder, m as PRE_DELETE_SNAPSHOT_TYPES, mn as LocalInvokeBuildError$1, mt as shouldRetainResource, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as processStackMessages, nt as requireConfigString, o as planFailedOps, on as getAwsClients, ot as withRetry, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as DeployCancelledError, pt as rebuildClientForBucketRegion, q as WAFv2WebACLProvider, qt as stateBucketExistenceConfirmed, r as DeployEngine, rt as applyRoleArnIfSet, s as planRollback, sn as resetAwsClients, st as isRetryableTransientError, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as AssemblyReader, tt as requireConfigObject, u as withResourceDeadline, un as CdkdError, ut as TemplateParser, v as isFinalSnapshotError, vn as MissingCdkCliError, vt as buildAssetRedirectMap, w as isStatefulRecreateTargetSync, wn as StackHasActiveImportsError, wt as ensureAssetStorage, x as makeCanonicalizePropertiesFn, xn as ProvisioningError, xt as rewriteTemplateAssetReferences, y as refusesFinalSnapshot, yn as NestedStackChildDirectDestroyError, yt as createAssetRedirectResolver, z as CloudControlProvider, zt as getLegacyStateBucketName } from "./deploy-engine-DQ9kW3Pu.js";
2
+ import { $ as replayWarn, $t as uploadCfnTemplate, A as green, An as normalizeAwsError, At as formatDockerLoginError, B as slowCcOperationTimeoutMs, Bt as resolveApp, C as MULTI_REGION_RECREATE_BLOCKED_TYPES, Cn as ResourceUpdateNotSupportedError, Ct as BOOTSTRAP_MARKER_PREFIX, D as bold, Dt as validateAssetBucketName, E as formatResourceLine, Et as parseBootstrapMarker, F as clearOnUpdateRemoval, Ft as getDockerImageBySourceHash, G as getAccountInfo, Gt as resolveStateBucketWithDefaultAndSource, H as isTerminationProtectionPropagationError, Ht as resolveCaptureObservedState, I as ProviderRegistry, It as Synthesizer, J as normalizeAwsTagsToCfn, Jt as warnDeprecatedNoPrefixCliFlag, K as refStateLookupFromResource, Kt as resolveUseCdkBootstrapAssets, L as findActionableSilentDrops, Lt as synthesisStatusMessage, M as yellow, Mt as runDockerForeground, N as IAMRoleProvider, Nt as runDockerStreaming, O as cyan, Ot as validateContainerRepoName, P as collectInlinePolicyNamesManagedBySiblings, Pt as AssetManifestLoader, Q as readConfigString, Qt as findLargeInlineResources, R as findSilentDropProperties, Rt as getDefaultStateBucketName, S as extractDeploymentEventError, Sn as ResourceTimeoutError, St as AssetModeResolver, T as renderStatefulReason, Tn as StackTerminationProtectionError, Tt as getBootstrapMarkerKey, U as IntrinsicFunctionResolver, Ut as resolveSkipPrefix, V as disableInstanceApiTermination, Vt as resolveAutoAssetStorage, W as cfnRefValueFromPhysicalId, Wt as resolveStateBucketWithDefault, X as assertRegionMatch, Xt as CFN_TEMPLATE_URL_LIMIT, Y as resolveExplicitPhysicalId, Yt as CFN_TEMPLATE_BODY_LIMIT, Z as configStringRefusal, Zt as MIGRATE_TMP_PREFIX, _ as createPreDeleteFinalSnapshot, _t as WorkGraph, a as DeploymentEventsStore, an as AwsClients, at as describeTypeWithThrottleRetry, b as unsupportedFinalSnapshotError, bn as PartialFailureError, bt as loadPublishableAssetManifest, c as replayFailedOperations, cn as setAwsClients, ct as isThrottlingError, d as IMPLICIT_DELETE_DEPENDENCIES, dt as LockManager, en as expectedOwnerParam, et as requireConfigArray, f as computeImplicitDeleteEdges, ft as S3StateBackend, g as ccRoutedFinalSnapshotError, gn as LocalStartServiceError, gt as stringifyValue, h as buildFinalSnapshotIdentifier, hn as LocalMigrateError, ht as AssetPublisher, i as DeploymentEventsReader, in as resolveBucketRegion, it as DiffCalculator, j as red, jn as withErrorHandling, jt as getDockerCmd, k as gray, kt as buildDockerImage, l as replayRollback, lt as DagBuilder, m as PRE_DELETE_SNAPSHOT_TYPES, mn as LocalInvokeBuildError$1, mt as shouldRetainResource, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as processStackMessages, nt as requireConfigString, o as planFailedOps, on as getAwsClients, ot as withRetry, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as DeployCancelledError, pt as rebuildClientForBucketRegion, q as WAFv2WebACLProvider, qt as stateBucketExistenceConfirmed, r as DeployEngine, rt as applyRoleArnIfSet, s as planRollback, sn as resetAwsClients, st as isRetryableTransientError, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as AssemblyReader, tt as requireConfigObject, u as withResourceDeadline, un as CdkdError, ut as TemplateParser, v as isFinalSnapshotError, vn as MissingCdkCliError, vt as buildAssetRedirectMap, w as isStatefulRecreateTargetSync, wn as StackHasActiveImportsError, wt as ensureAssetStorage, x as makeCanonicalizePropertiesFn, xn as ProvisioningError, xt as rewriteTemplateAssetReferences, y as refusesFinalSnapshot, yn as NestedStackChildDirectDestroyError, yt as createAssetRedirectResolver, z as CloudControlProvider, zt as getLegacyStateBucketName } from "./deploy-engine-BErTJjXl.js";
3
3
  import { a as getLiveRenderer, c as PATTERN_B_RESOURCE_TYPES, d as generateResourceNameWithFallback, h as withStackName, i as runStackBuffered, m as withSkipPrefix, n as getLogger, o as PATTERN_B_NAME_OPTIONS, s as PATTERN_B_NAME_PROPERTIES, u as generateResourceName } from "./logger-zRrlbaQt.js";
4
- import { t as ASGProvider } from "./asg-provider-C4zMjWYv.js";
4
+ import { t as ASGProvider } from "./asg-provider-AKp6xuP0.js";
5
5
  import { AsyncLocalStorage } from "node:async_hooks";
6
6
  import { createHash, randomBytes, randomUUID } from "node:crypto";
7
7
  import { CopyObjectCommand, CreateBucketCommand, DeleteBucketAnalyticsConfigurationCommand, DeleteBucketCommand, DeleteBucketCorsCommand, DeleteBucketEncryptionCommand, DeleteBucketIntelligentTieringConfigurationCommand, DeleteBucketInventoryConfigurationCommand, DeleteBucketLifecycleCommand, DeleteBucketMetricsConfigurationCommand, DeleteBucketOwnershipControlsCommand, DeleteBucketPolicyCommand, DeleteBucketReplicationCommand, DeleteBucketTaggingCommand, DeleteBucketWebsiteCommand, DeleteObjectsCommand, GetBucketAccelerateConfigurationCommand, GetBucketCorsCommand, GetBucketEncryptionCommand, GetBucketLifecycleConfigurationCommand, GetBucketLocationCommand, GetBucketLoggingCommand, GetBucketNotificationConfigurationCommand, GetBucketOwnershipControlsCommand, GetBucketPolicyCommand, GetBucketReplicationCommand, GetBucketTaggingCommand, GetBucketVersioningCommand, GetBucketWebsiteCommand, GetObjectCommand, GetObjectLockConfigurationCommand, GetPublicAccessBlockCommand, HeadBucketCommand, ListBucketAnalyticsConfigurationsCommand, ListBucketIntelligentTieringConfigurationsCommand, ListBucketInventoryConfigurationsCommand, ListBucketMetricsConfigurationsCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchBucket, PutBucketAccelerateConfigurationCommand, PutBucketAnalyticsConfigurationCommand, PutBucketCorsCommand, PutBucketEncryptionCommand, PutBucketIntelligentTieringConfigurationCommand, PutBucketInventoryConfigurationCommand, PutBucketLifecycleConfigurationCommand, PutBucketLoggingCommand, PutBucketMetricsConfigurationCommand, PutBucketNotificationConfigurationCommand, PutBucketOwnershipControlsCommand, PutBucketPolicyCommand, PutBucketReplicationCommand, PutBucketTaggingCommand, PutBucketVersioningCommand, PutBucketWebsiteCommand, PutObjectCommand, PutObjectLockConfigurationCommand, PutPublicAccessBlockCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
@@ -6074,6 +6074,63 @@ var S3BucketProvider = class S3BucketProvider {
6074
6074
  return config;
6075
6075
  }
6076
6076
  /**
6077
+ * True when the DESIRED side DECLARES the property but its collection is
6078
+ * empty — the shape {@link emptyListConfigToUndefined} folds to `undefined`
6079
+ * and therefore cannot be told apart from an ABSENT property downstream
6080
+ * (issue #1713).
6081
+ *
6082
+ * That collapse is the whole defect. `OwnershipControls` /
6083
+ * `BucketEncryption` normalize BOTH sides through the fold before
6084
+ * `diffSubConfig`, so a non-empty previous against a declared-but-empty
6085
+ * desired took the **onDelete** arm and issued
6086
+ * `DeleteBucketOwnershipControls` / `DeleteBucketEncryption` — where the
6087
+ * lifecycle / CORS siblings SKIP the Put and leave the live configuration
6088
+ * alone (issue #1671). Measured against live CloudFormation (us-east-1,
6089
+ * 2026-08-12): updating a deployed bucket from an `aws:kms` default and a
6090
+ * `BucketOwnerPreferred` rule to `ServerSideEncryptionConfiguration: []` /
6091
+ * `Rules: []` drives the stack to `UPDATE_ROLLBACK_COMPLETE` with
6092
+ * `The XML you provided was not well-formed or did not validate against our
6093
+ * published schema`, and BOTH live configurations survive unchanged. So CFn
6094
+ * treats the empty collection as an INVALID template, not as a removal —
6095
+ * the same answer the #1671 A/B produced for lifecycle / CORS on the same
6096
+ * date and account — and cdkd was DELETING instead. For `BucketEncryption`
6097
+ * that silently drops a declared `aws:kms` default down to SSE-S3 / AES256
6098
+ * on a template whose only fault is a condition-pruned or
6099
+ * intrinsic-collapsed array.
6100
+ *
6101
+ * The fold itself is load-bearing and is NOT what changes here:
6102
+ * `readCurrentState` ALWAYS emits
6103
+ * `BucketEncryption: { ServerSideEncryptionConfiguration: [] }` and
6104
+ * `OwnershipControls: { Rules: [] }` for a bucket with no explicit setting,
6105
+ * so `cdkd drift --revert` feeds that placeholder back through `update()`
6106
+ * and both sides must keep normalizing for empty-vs-empty to compare EQUAL
6107
+ * and issue no call at all. This predicate rides alongside it and only
6108
+ * splits the arm the fold reaches: **declared-but-empty SKIPS, absent
6109
+ * DELETES**. A removal therefore still works — dropping the whole property
6110
+ * from the template is what expresses it, which is exactly what
6111
+ * `emptyCollectionSkip`'s warning tells the user.
6112
+ *
6113
+ * **Scoped to the shape #1713 MEASURED — the list key PRESENT and EMPTY —
6114
+ * and no wider.** The tempting spelling is "present, and the fold erased it",
6115
+ * i.e. delegate to {@link emptyListConfigToUndefined}. That is wrong here:
6116
+ * the fold ALSO erases a bare `{}`, which issue #1466 pinned as a REMOVAL and
6117
+ * #1713's live A/B did not exercise, so delegating would have reversed that
6118
+ * contract on evidence that does not cover it — caught when its pinned row
6119
+ * failed. (`{listKey: null}` as the sole key is NOT folded — the block
6120
+ * carries one key, so `emptyListConfigToUndefined` passes it through as
6121
+ * MALFORMED; an earlier draft of this comment claimed it was, which the
6122
+ * type's own `'{Rules: null} as the SOLE key is malformed'` test contradicts.)
6123
+ *
6124
+ * A MALFORMED block is out of scope for a different reason and needs no
6125
+ * clause here: the fold passes it through unchanged, so it never reaches the
6126
+ * Delete arm at all and is refused by name by the apply call.
6127
+ */
6128
+ static declaresEmptyCollection(config, listKey) {
6129
+ if (typeof config !== "object" || config === null || Array.isArray(config)) return false;
6130
+ const list = config[listKey];
6131
+ return Array.isArray(list) && list.length === 0;
6132
+ }
6133
+ /**
6077
6134
  * Turn a set of per-property overrides into the `effectiveProperties` bag the
6078
6135
  * deploy engine records in place of the desired one (issues #1612 / #1670).
6079
6136
  *
@@ -6327,7 +6384,7 @@ var S3BucketProvider = class S3BucketProvider {
6327
6384
  * direction: a later template that REMOVES the block would then derive no
6328
6385
  * removal and the live configuration would survive forever.
6329
6386
  */
6330
- async applySubConfigDiffs(bucketName, properties, previousProperties) {
6387
+ async applySubConfigDiffs(bucketName, properties, previousProperties, context) {
6331
6388
  const overrides = /* @__PURE__ */ new Map();
6332
6389
  /** Record a WHOLE-BLOCK skip: the effective value is the previous one. */
6333
6390
  const retainPrevious = (key) => {
@@ -6383,16 +6440,31 @@ var S3BucketProvider = class S3BucketProvider {
6383
6440
  if (versioningRefusal === void 0 && versioningChanged && nextVersioning != null && desiredVersioningStatus !== "Suspended") {
6384
6441
  if (!await this.applyVersioning(bucketName, nextVersioning, (m) => this.logger.warn(m))) retainPrevious("VersioningConfiguration");
6385
6442
  }
6443
+ const ownershipEmptyDesired = S3BucketProvider.declaresEmptyCollection(properties["OwnershipControls"], "Rules");
6386
6444
  await this.diffSubConfig(bucketName, S3BucketProvider.emptyListConfigToUndefined(previousProperties["OwnershipControls"], "Rules"), S3BucketProvider.emptyListConfigToUndefined(properties["OwnershipControls"], "Rules"), async (cfg) => this.applyOwnershipControls(bucketName, cfg), async () => {
6445
+ if (ownershipEmptyDesired && context?.desiredFromAwsReadback !== true) {
6446
+ this.emptyCollectionSkip("OwnershipControls", "OwnershipControls.Rules", previousProperties, retainPrevious);
6447
+ return;
6448
+ }
6387
6449
  await this.s3Client.send(new DeleteBucketOwnershipControlsCommand({ Bucket: bucketName }));
6388
6450
  this.logger.debug(`Deleted ownership controls on bucket ${bucketName}`);
6389
6451
  });
6452
+ const encryptionEmptyDesired = S3BucketProvider.declaresEmptyCollection(properties["BucketEncryption"], "ServerSideEncryptionConfiguration");
6390
6453
  await this.diffSubConfig(bucketName, S3BucketProvider.emptyListConfigToUndefined(previousProperties["BucketEncryption"], "ServerSideEncryptionConfiguration"), S3BucketProvider.emptyListConfigToUndefined(properties["BucketEncryption"], "ServerSideEncryptionConfiguration"), async (cfg) => this.applyBucketEncryption(bucketName, cfg), async () => {
6454
+ if (encryptionEmptyDesired && context?.desiredFromAwsReadback !== true) {
6455
+ this.emptyCollectionSkip("BucketEncryption", "BucketEncryption.ServerSideEncryptionConfiguration", previousProperties, retainPrevious);
6456
+ return;
6457
+ }
6391
6458
  await this.s3Client.send(new DeleteBucketEncryptionCommand({ Bucket: bucketName }));
6392
6459
  this.logger.debug(`Deleted bucket encryption on bucket ${bucketName}`);
6393
6460
  });
6394
6461
  await this.diffSubConfig(bucketName, previousProperties["LifecycleConfiguration"], properties["LifecycleConfiguration"], async (cfg) => {
6395
6462
  if (!cfg.Rules || !Array.isArray(cfg.Rules) || cfg.Rules.length === 0) {
6463
+ if (context?.desiredFromAwsReadback === true) {
6464
+ await this.s3Client.send(new DeleteBucketLifecycleCommand({ Bucket: bucketName }));
6465
+ this.logger.debug(`Deleted lifecycle configuration on bucket ${bucketName} (reverting to an unset baseline)`);
6466
+ return;
6467
+ }
6396
6468
  this.emptyCollectionSkip("LifecycleConfiguration", "LifecycleConfiguration.Rules", previousProperties, retainPrevious);
6397
6469
  return;
6398
6470
  }
@@ -6403,6 +6475,11 @@ var S3BucketProvider = class S3BucketProvider {
6403
6475
  });
6404
6476
  await this.diffSubConfig(bucketName, previousProperties["CorsConfiguration"], properties["CorsConfiguration"], async (cfg) => {
6405
6477
  if (!cfg.CorsRules || !Array.isArray(cfg.CorsRules) || cfg.CorsRules.length === 0) {
6478
+ if (context?.desiredFromAwsReadback === true) {
6479
+ await this.s3Client.send(new DeleteBucketCorsCommand({ Bucket: bucketName }));
6480
+ this.logger.debug(`Deleted CORS configuration on bucket ${bucketName} (reverting to an unset baseline)`);
6481
+ return;
6482
+ }
6406
6483
  this.emptyCollectionSkip("CorsConfiguration", "CorsConfiguration.CorsRules", previousProperties, retainPrevious);
6407
6484
  return;
6408
6485
  }
@@ -6613,7 +6690,7 @@ var S3BucketProvider = class S3BucketProvider {
6613
6690
  /**
6614
6691
  * Update an S3 bucket
6615
6692
  */
6616
- async update(logicalId, physicalId, resourceType, properties, previousProperties) {
6693
+ async update(logicalId, physicalId, resourceType, properties, previousProperties, context) {
6617
6694
  this.logger.debug(`Updating S3 bucket ${logicalId}: ${physicalId}`);
6618
6695
  const newBucketName = properties["BucketName"];
6619
6696
  if (newBucketName && newBucketName !== physicalId) {
@@ -6628,7 +6705,7 @@ var S3BucketProvider = class S3BucketProvider {
6628
6705
  skipTags: true,
6629
6706
  skipDiffManaged: true
6630
6707
  });
6631
- for (const [key, value] of await this.applySubConfigDiffs(physicalId, properties, previousProperties)) effectiveOverrides.set(key, value);
6708
+ for (const [key, value] of await this.applySubConfigDiffs(physicalId, properties, previousProperties, context)) effectiveOverrides.set(key, value);
6632
6709
  await this.applyTagDiff(physicalId, previousProperties["Tags"], properties["Tags"]);
6633
6710
  const attributes = await this.buildAttributes(physicalId);
6634
6711
  this.logger.debug(`Successfully updated S3 bucket ${logicalId}`);
@@ -13829,8 +13906,14 @@ var DynamoDBGlobalTableProvider = class {
13829
13906
  if (!keySchema) throw new ProvisioningError(`KeySchema is required for DynamoDB GlobalTable ${logicalId}`, resourceType, logicalId);
13830
13907
  if (!attributeDefinitions) throw new ProvisioningError(`AttributeDefinitions is required for DynamoDB GlobalTable ${logicalId}`, resourceType, logicalId);
13831
13908
  let billingMode;
13832
- try {
13833
- billingMode = requireConfigString(properties["BillingMode"], "PAY_PER_REQUEST", "AWS::DynamoDB::GlobalTable BillingMode", replayWarn(this.logger, context));
13909
+ let billingModeSubstituted = false;
13910
+ try {
13911
+ const billingReplayWarn = replayWarn(this.logger, context).onUnusable;
13912
+ billingMode = requireConfigString(properties["BillingMode"], "PAY_PER_REQUEST", "AWS::DynamoDB::GlobalTable BillingMode", billingReplayWarn ? { onUnusable: (message) => {
13913
+ billingModeSubstituted = true;
13914
+ billingReplayWarn(message);
13915
+ } } : {});
13916
+ if (billingReplayWarn && properties["BillingMode"] === void 0) this.logger.warn(`AWS::DynamoDB::GlobalTable ${logicalId}: the state record declares no BillingMode, so this replay creates the table PAY_PER_REQUEST. If it was PROVISIONED, set the mode in the template and redeploy.`);
13834
13917
  } catch (error) {
13835
13918
  throw new ProvisioningError(error instanceof Error ? error.message : String(error), resourceType, logicalId, void 0, error instanceof Error ? error : void 0);
13836
13919
  }
@@ -13845,6 +13928,10 @@ var DynamoDBGlobalTableProvider = class {
13845
13928
  const diagnostics = [];
13846
13929
  if (billingMode === "PROVISIONED") createParams.ProvisionedThroughput = derivePerCallProvisionedThroughput(properties, currentRegion, "min", diagnostics);
13847
13930
  let effectiveProperties;
13931
+ if (billingModeSubstituted) effectiveProperties = {
13932
+ ...properties,
13933
+ BillingMode: billingMode
13934
+ };
13848
13935
  const streamSpecInput = properties["StreamSpecification"];
13849
13936
  const needsStream = replicas.some((r) => r["Region"] !== currentRegion) || replicas.length > 1;
13850
13937
  if (streamSpecInput != null) {
@@ -13864,7 +13951,7 @@ var DynamoDBGlobalTableProvider = class {
13864
13951
  StreamViewType: streamViewType
13865
13952
  };
13866
13953
  if (streamSpecSubstituted) effectiveProperties = {
13867
- ...properties,
13954
+ ...effectiveProperties ?? properties,
13868
13955
  StreamSpecification: { StreamViewType: streamViewType }
13869
13956
  };
13870
13957
  } else if (needsStream) {
@@ -14095,7 +14182,7 @@ var DynamoDBGlobalTableProvider = class {
14095
14182
  let billingUnusable = false;
14096
14183
  const requestedBilling = requireConfigString(properties["BillingMode"], "PAY_PER_REQUEST", "AWS::DynamoDB::GlobalTable BillingMode", { onUnusable: (message) => {
14097
14184
  billingUnusable = true;
14098
- this.logger.warn(`${message} The table's current billing mode (${oldBilling}) is kept for this update rather than flipped to the default.`);
14185
+ this.logger.warn(`AWS::DynamoDB::GlobalTable ${logicalId}: ${message} The mode this update compared against (${oldBilling}) is kept for this update rather than flipped to the default.`);
14099
14186
  } });
14100
14187
  const newBilling = billingUnusable ? oldBilling : requestedBilling;
14101
14188
  const onDemandCeilingLive = oldBilling === "PAY_PER_REQUEST" && newBilling === "PAY_PER_REQUEST";
@@ -14160,11 +14247,26 @@ var DynamoDBGlobalTableProvider = class {
14160
14247
  } else {
14161
14248
  const previousStreamSpec = previousProperties["StreamSpecification"];
14162
14249
  const previousStreamSpecUsable = previousStreamSpec !== void 0 && previousStreamSpec !== null && configStringRefusal(previousStreamSpec, "StreamViewType", "NEW_AND_OLD_IMAGES", "AWS::DynamoDB::GlobalTable StreamSpecification") === void 0;
14163
- effectiveProperties = { ...properties };
14250
+ effectiveProperties = { ...effectiveProperties ?? properties };
14164
14251
  if (previousStreamSpecUsable) effectiveProperties["StreamSpecification"] = { ...previousStreamSpec };
14165
14252
  else delete effectiveProperties["StreamSpecification"];
14166
14253
  }
14167
14254
  }
14255
+ if (desiredGsiUnusable) {
14256
+ let previousGsiProbeUnusable = false;
14257
+ toSdkGlobalSecondaryIndexes(previousProperties, currentRegion, oldBilling, "min", void 0, () => {
14258
+ previousGsiProbeUnusable = true;
14259
+ });
14260
+ const previousIndexes = previousProperties["GlobalSecondaryIndexes"];
14261
+ effectiveProperties = { ...effectiveProperties ?? properties };
14262
+ if (!previousGsiProbeUnusable && previousIndexes !== void 0) effectiveProperties["GlobalSecondaryIndexes"] = [...previousIndexes];
14263
+ else delete effectiveProperties["GlobalSecondaryIndexes"];
14264
+ }
14265
+ if (billingUnusable) {
14266
+ effectiveProperties = { ...effectiveProperties ?? properties };
14267
+ if (recordedOldBilling === void 0) delete effectiveProperties["BillingMode"];
14268
+ else effectiveProperties["BillingMode"] = oldBilling;
14269
+ }
14168
14270
  const awsOnDemand = describeResp.Table?.OnDemandThroughput;
14169
14271
  const onDemandPayload = {};
14170
14272
  const resolveCeiling = (desired, live) => {
@@ -56226,7 +56328,7 @@ async function runRevert(reports, providerRegistry, stateBackend, stateConfig, a
56226
56328
  const desiredProperties = stateResource.observedProperties ?? stateResource.properties ?? {};
56227
56329
  const newProperties = buildRevertNewProperties(outcome.changes, desiredProperties, outcome.awsProperties, { preserveUntemplated: stateResource.observedProperties === void 0 });
56228
56330
  try {
56229
- const updateResult = await withRetry(() => provider.update(outcome.logicalId, stateResource.physicalId, outcome.resourceType, newProperties, outcome.awsProperties), outcome.logicalId, { logger: { debug: (msg) => logger.debug(msg) } });
56331
+ const updateResult = await withRetry(() => provider.update(outcome.logicalId, stateResource.physicalId, outcome.resourceType, newProperties, outcome.awsProperties, { desiredFromAwsReadback: true }), outcome.logicalId, { logger: { debug: (msg) => logger.debug(msg) } });
56230
56332
  totalSucceeded++;
56231
56333
  logger.info(` ✓ ${report.stackName}/${outcome.logicalId} (${outcome.resourceType}): reverted.`);
56232
56334
  try {
@@ -73411,7 +73513,7 @@ function createMigrateCommand() {
73411
73513
  */
73412
73514
  function buildProgram() {
73413
73515
  const program = new Command();
73414
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.281.9");
73516
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.281.11");
73415
73517
  program.hook("preAction", (_thisCommand, actionCommand) => {
73416
73518
  const { profile } = actionCommand.optsWithGlobals();
73417
73519
  if (profile !== void 0) process.env["AWS_PROFILE"] = profile;