@go-to-k/cdkd 0.279.0 → 0.280.1

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 DiffCalculator, $t as resolveBucketRegion, A as red, At as getDockerImageBySourceHash, B as isTerminationProtectionPropagationError, Bt as resolveStateBucketWithDefaultAndSource, C as isStatefulRecreateTargetSync, Ct as validateContainerRepoName, D as cyan, Dt as runDockerForeground, E as bold, En as withErrorHandling, Et as getDockerCmd, F as ProviderRegistry, Ft as resolveApp, G as normalizeAwsTagsToCfn, Gt as CFN_TEMPLATE_URL_LIMIT, H as cfnRefValueFromPhysicalId, Ht as stateBucketExistenceConfirmed, I as findActionableSilentDrops, It as resolveAutoAssetStorage, J as readConfigString, Jt as uploadCfnTemplate, K as resolveExplicitPhysicalId, Kt as MIGRATE_TMP_PREFIX, L as CloudControlProvider, Lt as resolveCaptureObservedState, M as IAMRoleProvider, Mt as synthesisStatusMessage, N as collectInlinePolicyNamesManagedBySiblings, Nt as getDefaultStateBucketName, O as gray, Ot as runDockerStreaming, P as clearOnUpdateRemoval, Pt as getLegacyStateBucketName, Q as applyRoleArnIfSet, R as slowCcOperationTimeoutMs, Rt as resolveSkipPrefix, S as MULTI_REGION_RECREATE_BLOCKED_TYPES, St as validateAssetBucketName, T as formatResourceLine, Tn as normalizeAwsError, Tt as formatDockerLoginError, U as refStateLookupFromResource, Ut as warnDeprecatedNoPrefixCliFlag, V as IntrinsicFunctionResolver, Vt as resolveUseCdkBootstrapAssets, W as WAFv2WebACLProvider, Wt as CFN_TEMPLATE_BODY_LIMIT, X as requireConfigArray, Xt as AssemblyReader, Y as replayWarn, Yt as expectedOwnerParam, Z as requireConfigString, Zt as processStackMessages, _ as createPreDeleteFinalSnapshot, _n as ResourceTimeoutError, _t as AssetModeResolver, a as DeploymentEventsStore, an as CdkdError, at as TemplateParser, b as unsupportedFinalSnapshotError, bn as StackTerminationProtectionError, bt as getBootstrapMarkerKey, c as replayFailedOperations, cn as DeployCancelledError, ct as rebuildClientForBucketRegion, d as IMPLICIT_DELETE_DEPENDENCIES, dn as LocalStartServiceError, dt as stringifyValue, en as AwsClients, et as describeTypeWithThrottleRetry, f as computeImplicitDeleteEdges, ft as WorkGraph, g as ccRoutedFinalSnapshotError, gn as ProvisioningError, gt as rewriteTemplateAssetReferences, h as buildFinalSnapshotIdentifier, hn as PartialFailureError, ht as loadPublishableAssetManifest, i as DeploymentEventsReader, it as DagBuilder, j as yellow, jt as Synthesizer, k as green, kt as AssetManifestLoader, l as replayRollback, ln as LocalInvokeBuildError$1, lt as shouldRetainResource, m as PRE_DELETE_SNAPSHOT_TYPES, mn as NestedStackChildDirectDestroyError, mt as createAssetRedirectResolver, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as resetAwsClients, nt as isRetryableTransientError, o as planFailedOps, ot as LockManager, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as MissingCdkCliError, pt as buildAssetRedirectMap, q as assertRegionMatch, qt as findLargeInlineResources, r as DeployEngine, rn as setAwsClients, rt as isThrottlingError, s as planRollback, st as S3StateBackend, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as getAwsClients, tt as withRetry, u as withResourceDeadline, un as LocalMigrateError, ut as AssetPublisher, v as isFinalSnapshotError, vn as ResourceUpdateNotSupportedError, vt as BOOTSTRAP_MARKER_PREFIX, w as renderStatefulReason, wt as buildDockerImage, x as extractDeploymentEventError, xt as parseBootstrapMarker, y as refusesFinalSnapshot, yn as StackHasActiveImportsError, yt as ensureAssetStorage, z as disableInstanceApiTermination, zt as resolveStateBucketWithDefault } from "./deploy-engine-CFVg2o__.js";
2
+ import { $ as DiffCalculator, $t as resolveBucketRegion, A as red, At as getDockerImageBySourceHash, B as isTerminationProtectionPropagationError, Bt as resolveStateBucketWithDefaultAndSource, C as isStatefulRecreateTargetSync, Ct as validateContainerRepoName, D as cyan, Dt as runDockerForeground, E as bold, En as withErrorHandling, Et as getDockerCmd, F as ProviderRegistry, Ft as resolveApp, G as normalizeAwsTagsToCfn, Gt as CFN_TEMPLATE_URL_LIMIT, H as cfnRefValueFromPhysicalId, Ht as stateBucketExistenceConfirmed, I as findActionableSilentDrops, It as resolveAutoAssetStorage, J as readConfigString, Jt as uploadCfnTemplate, K as resolveExplicitPhysicalId, Kt as MIGRATE_TMP_PREFIX, L as CloudControlProvider, Lt as resolveCaptureObservedState, M as IAMRoleProvider, Mt as synthesisStatusMessage, N as collectInlinePolicyNamesManagedBySiblings, Nt as getDefaultStateBucketName, O as gray, Ot as runDockerStreaming, P as clearOnUpdateRemoval, Pt as getLegacyStateBucketName, Q as applyRoleArnIfSet, R as slowCcOperationTimeoutMs, Rt as resolveSkipPrefix, S as MULTI_REGION_RECREATE_BLOCKED_TYPES, St as validateAssetBucketName, T as formatResourceLine, Tn as normalizeAwsError, Tt as formatDockerLoginError, U as refStateLookupFromResource, Ut as warnDeprecatedNoPrefixCliFlag, V as IntrinsicFunctionResolver, Vt as resolveUseCdkBootstrapAssets, W as WAFv2WebACLProvider, Wt as CFN_TEMPLATE_BODY_LIMIT, X as requireConfigArray, Xt as AssemblyReader, Y as replayWarn, Yt as expectedOwnerParam, Z as requireConfigString, Zt as processStackMessages, _ as createPreDeleteFinalSnapshot, _n as ResourceTimeoutError, _t as AssetModeResolver, a as DeploymentEventsStore, an as CdkdError, at as TemplateParser, b as unsupportedFinalSnapshotError, bn as StackTerminationProtectionError, bt as getBootstrapMarkerKey, c as replayFailedOperations, cn as DeployCancelledError, ct as rebuildClientForBucketRegion, d as IMPLICIT_DELETE_DEPENDENCIES, dn as LocalStartServiceError, dt as stringifyValue, en as AwsClients, et as describeTypeWithThrottleRetry, f as computeImplicitDeleteEdges, ft as WorkGraph, g as ccRoutedFinalSnapshotError, gn as ProvisioningError, gt as rewriteTemplateAssetReferences, h as buildFinalSnapshotIdentifier, hn as PartialFailureError, ht as loadPublishableAssetManifest, i as DeploymentEventsReader, it as DagBuilder, j as yellow, jt as Synthesizer, k as green, kt as AssetManifestLoader, l as replayRollback, ln as LocalInvokeBuildError$1, lt as shouldRetainResource, m as PRE_DELETE_SNAPSHOT_TYPES, mn as NestedStackChildDirectDestroyError, mt as createAssetRedirectResolver, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as resetAwsClients, nt as isRetryableTransientError, o as planFailedOps, ot as LockManager, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as MissingCdkCliError, pt as buildAssetRedirectMap, q as assertRegionMatch, qt as findLargeInlineResources, r as DeployEngine, rn as setAwsClients, rt as isThrottlingError, s as planRollback, st as S3StateBackend, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as getAwsClients, tt as withRetry, u as withResourceDeadline, un as LocalMigrateError, ut as AssetPublisher, v as isFinalSnapshotError, vn as ResourceUpdateNotSupportedError, vt as BOOTSTRAP_MARKER_PREFIX, w as renderStatefulReason, wt as buildDockerImage, x as extractDeploymentEventError, xt as parseBootstrapMarker, y as refusesFinalSnapshot, yn as StackHasActiveImportsError, yt as ensureAssetStorage, z as disableInstanceApiTermination, zt as resolveStateBucketWithDefault } from "./deploy-engine-CWPDckBl.js";
3
3
  import { a as getLiveRenderer, c as PATTERN_B_RESOURCE_TYPES, d as generateResourceNameWithFallback, f as withSkipPrefix, i as runStackBuffered, n as getLogger, o as PATTERN_B_NAME_OPTIONS, p as withStackName, s as PATTERN_B_NAME_PROPERTIES, u as generateResourceName } from "./logger-BYMEE-BS.js";
4
- import { t as ASGProvider } from "./asg-provider-C-EXD6HS.js";
4
+ import { t as ASGProvider } from "./asg-provider-BdLzhYo9.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";
@@ -4863,7 +4863,7 @@ function s3BucketDestinationPath(dest, destinationPath) {
4863
4863
  * exported from there because `resolveS3BucketDestination` is S3-specific
4864
4864
  * branch selection, not a shared shape guard — the two only share the wording.
4865
4865
  */
4866
- function describeValue(value) {
4866
+ function describeValue$1(value) {
4867
4867
  if (value === null) return "null";
4868
4868
  if (Array.isArray(value)) return "an array";
4869
4869
  if (typeof value === "string") return `a string ${JSON.stringify(value)}`;
@@ -5433,11 +5433,11 @@ var S3BucketProvider = class S3BucketProvider {
5433
5433
  throw new Error(message);
5434
5434
  };
5435
5435
  if (dest === void 0 || dest === null) return;
5436
- if (!isPlainObject$1(dest)) return drop(`${destinationPath} must be an object (got ${describeValue(dest)}) — check for an unresolved intrinsic or a mis-nested template value; the destination would otherwise be dropped from the request with no error`);
5436
+ if (!isPlainObject$1(dest)) return drop(`${destinationPath} must be an object (got ${describeValue$1(dest)}) — check for an unresolved intrinsic or a mis-nested template value; the destination would otherwise be dropped from the request with no error`);
5437
5437
  const bag = isFlattenedDestination(dest) ? dest : dest["S3BucketDestination"];
5438
- if (bag === void 0 || bag === null) return drop(`${destinationPath} carries neither a bucket (BucketArn / Bucket) nor a nested S3BucketDestination object (got ${describeValue(dest)}) — the destination would otherwise be dropped from the request with no error`);
5439
- if (!isPlainObject$1(bag)) return drop(`${nestedPath} must be an object (got ${describeValue(bag)}) — check for an unresolved intrinsic or a mis-nested template value; the destination would otherwise be dropped from the request with no error`);
5440
- if (!bag["BucketArn"] && !bag["Bucket"]) return drop(`${bag === dest ? destinationPath : nestedPath} has no destination bucket (BucketArn / Bucket) (got ${describeValue(bag)}) — the request would be rejected by S3, or silently carry no destination`);
5438
+ if (bag === void 0 || bag === null) return drop(`${destinationPath} carries neither a bucket (BucketArn / Bucket) nor a nested S3BucketDestination object (got ${describeValue$1(dest)}) — the destination would otherwise be dropped from the request with no error`);
5439
+ if (!isPlainObject$1(bag)) return drop(`${nestedPath} must be an object (got ${describeValue$1(bag)}) — check for an unresolved intrinsic or a mis-nested template value; the destination would otherwise be dropped from the request with no error`);
5440
+ if (!bag["BucketArn"] && !bag["Bucket"]) return drop(`${bag === dest ? destinationPath : nestedPath} has no destination bucket (BucketArn / Bucket) (got ${describeValue$1(bag)}) — the request would be rejected by S3, or silently carry no destination`);
5441
5441
  return bag;
5442
5442
  }
5443
5443
  /**
@@ -20266,7 +20266,13 @@ var ApiGatewayProvider = class ApiGatewayProvider {
20266
20266
  "Tags",
20267
20267
  "TracingEnabled",
20268
20268
  "Variables",
20269
- "MethodSettings"
20269
+ "MethodSettings",
20270
+ "AccessLogSetting",
20271
+ "CacheClusterEnabled",
20272
+ "CacheClusterSize",
20273
+ "CanarySetting",
20274
+ "ClientCertificateId",
20275
+ "DocumentationVersion"
20270
20276
  ])],
20271
20277
  ["AWS::ApiGateway::Method", /* @__PURE__ */ new Set([
20272
20278
  "RestApiId",
@@ -20749,7 +20755,12 @@ var ApiGatewayProvider = class ApiGatewayProvider {
20749
20755
  const stageName = properties["StageName"];
20750
20756
  const deploymentId = properties["DeploymentId"];
20751
20757
  if (!restApiId || !stageName || !deploymentId) throw new ProvisioningError(`RestApiId, StageName, and DeploymentId are required for API Gateway Stage ${logicalId}`, resourceType, logicalId);
20758
+ for (const key of ["AccessLogSetting", "CanarySetting"]) {
20759
+ const block = properties[key];
20760
+ if (block != null && !isPlainObjectBlock(block)) throw new ProvisioningError(`AWS::ApiGateway::Stage ${key} for ${logicalId} must be an object block; got ${Array.isArray(block) ? "an array" : typeof block}. Fix the template value instead of letting cdkd drop the config.`, resourceType, logicalId);
20761
+ }
20752
20762
  try {
20763
+ const rawCacheClusterSize = properties["CacheClusterSize"];
20753
20764
  await this.apiGatewayClient.send(new CreateStageCommand({
20754
20765
  restApiId,
20755
20766
  stageName,
@@ -20757,15 +20768,38 @@ var ApiGatewayProvider = class ApiGatewayProvider {
20757
20768
  description: properties["Description"],
20758
20769
  tracingEnabled: properties["TracingEnabled"],
20759
20770
  variables: properties["Variables"],
20760
- tags: this.cfnTagsToRecord(properties["Tags"])
20771
+ tags: this.cfnTagsToRecord(properties["Tags"]),
20772
+ cacheClusterEnabled: properties["CacheClusterEnabled"],
20773
+ cacheClusterSize: rawCacheClusterSize != null ? String(rawCacheClusterSize) : void 0,
20774
+ documentationVersion: properties["DocumentationVersion"],
20775
+ canarySettings: toSdkCanarySettings(properties["CanarySetting"])
20761
20776
  }));
20762
20777
  const methodSettings = properties["MethodSettings"];
20763
- const methodSettingsOps = buildMethodSettingsPatchOps(void 0, methodSettings);
20764
- if (methodSettingsOps.length > 0) try {
20778
+ const postCreateOps = buildMethodSettingsPatchOps(void 0, methodSettings);
20779
+ const accessLogSetting = properties["AccessLogSetting"];
20780
+ if (accessLogSetting != null) {
20781
+ if (accessLogSetting.DestinationArn !== void 0) postCreateOps.push({
20782
+ op: "replace",
20783
+ path: "/accessLogSettings/destinationArn",
20784
+ value: normalizeAccessLogDestinationArn(String(accessLogSetting.DestinationArn))
20785
+ });
20786
+ if (accessLogSetting.Format !== void 0) postCreateOps.push({
20787
+ op: "replace",
20788
+ path: "/accessLogSettings/format",
20789
+ value: String(accessLogSetting.Format)
20790
+ });
20791
+ }
20792
+ const clientCertificateId = properties["ClientCertificateId"];
20793
+ if (clientCertificateId !== void 0) postCreateOps.push({
20794
+ op: "replace",
20795
+ path: "/clientCertificateId",
20796
+ value: clientCertificateId
20797
+ });
20798
+ if (postCreateOps.length > 0) try {
20765
20799
  await this.apiGatewayClient.send(new UpdateStageCommand({
20766
20800
  restApiId,
20767
20801
  stageName,
20768
- patchOperations: methodSettingsOps
20802
+ patchOperations: postCreateOps
20769
20803
  }));
20770
20804
  } catch (patchError) {
20771
20805
  try {
@@ -20774,7 +20808,7 @@ var ApiGatewayProvider = class ApiGatewayProvider {
20774
20808
  stageName
20775
20809
  }));
20776
20810
  } catch (cleanupError) {
20777
- this.logger.warn(`Failed to clean up stage ${stageName} after a MethodSettings patch failure: ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}`);
20811
+ this.logger.warn(`Failed to clean up stage ${stageName} after a post-create patch failure: ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}`);
20778
20812
  }
20779
20813
  throw patchError;
20780
20814
  }
@@ -20817,6 +20851,91 @@ var ApiGatewayProvider = class ApiGatewayProvider {
20817
20851
  path: "/tracingEnabled",
20818
20852
  value: String(tracingEnabled ?? false)
20819
20853
  });
20854
+ const cacheClusterEnabled = properties["CacheClusterEnabled"];
20855
+ if (cacheClusterEnabled !== previousProperties["CacheClusterEnabled"]) patchOperations.push({
20856
+ op: "replace",
20857
+ path: "/cacheClusterEnabled",
20858
+ value: String(cacheClusterEnabled ?? false)
20859
+ });
20860
+ const rawCacheClusterSize = properties["CacheClusterSize"];
20861
+ const prevRawCacheClusterSize = previousProperties["CacheClusterSize"];
20862
+ if (rawCacheClusterSize != null && (prevRawCacheClusterSize == null || String(rawCacheClusterSize) !== String(prevRawCacheClusterSize))) patchOperations.push({
20863
+ op: "replace",
20864
+ path: "/cacheClusterSize",
20865
+ value: String(rawCacheClusterSize)
20866
+ });
20867
+ const clientCertificateId = properties["ClientCertificateId"];
20868
+ if (clientCertificateId !== previousProperties["ClientCertificateId"]) patchOperations.push({
20869
+ op: "replace",
20870
+ path: "/clientCertificateId",
20871
+ value: clientCertificateId ?? ""
20872
+ });
20873
+ const documentationVersion = properties["DocumentationVersion"];
20874
+ if (documentationVersion !== previousProperties["DocumentationVersion"]) patchOperations.push({
20875
+ op: "replace",
20876
+ path: "/documentationVersion",
20877
+ value: documentationVersion ?? ""
20878
+ });
20879
+ const rawAccessLog = properties["AccessLogSetting"];
20880
+ const accessLogMalformed = rawAccessLog != null && !isPlainObjectBlock(rawAccessLog);
20881
+ if (accessLogMalformed) this.logger.warn(`AWS::ApiGateway::Stage AccessLogSetting for ${logicalId} is not an object block (got ${Array.isArray(rawAccessLog) ? "an array" : typeof rawAccessLog}); leaving the live access-log config untouched.`);
20882
+ const accessLog = accessLogMalformed ? void 0 : rawAccessLog;
20883
+ const prevAccessLog = previousProperties["AccessLogSetting"];
20884
+ if (accessLogMalformed) {} else if (accessLog == null) {
20885
+ if (prevAccessLog != null) patchOperations.push({
20886
+ op: "remove",
20887
+ path: "/accessLogSettings"
20888
+ });
20889
+ } else {
20890
+ if (accessLog.DestinationArn !== prevAccessLog?.DestinationArn) patchOperations.push({
20891
+ op: "replace",
20892
+ path: "/accessLogSettings/destinationArn",
20893
+ value: accessLog.DestinationArn !== void 0 ? normalizeAccessLogDestinationArn(String(accessLog.DestinationArn)) : ""
20894
+ });
20895
+ if (accessLog.Format !== prevAccessLog?.Format) patchOperations.push({
20896
+ op: "replace",
20897
+ path: "/accessLogSettings/format",
20898
+ value: accessLog.Format !== void 0 ? String(accessLog.Format) : ""
20899
+ });
20900
+ }
20901
+ const rawCanary = properties["CanarySetting"];
20902
+ const canaryMalformed = rawCanary != null && !isPlainObjectBlock(rawCanary);
20903
+ if (canaryMalformed) this.logger.warn(`AWS::ApiGateway::Stage CanarySetting for ${logicalId} is not an object block (got ${Array.isArray(rawCanary) ? "an array" : typeof rawCanary}); leaving the live canary config untouched.`);
20904
+ const canary = canaryMalformed ? void 0 : rawCanary;
20905
+ const prevCanary = previousProperties["CanarySetting"];
20906
+ if (canaryMalformed) {} else if (canary == null) {
20907
+ if (prevCanary != null) patchOperations.push({
20908
+ op: "remove",
20909
+ path: "/canarySettings"
20910
+ });
20911
+ } else {
20912
+ if (canary.PercentTraffic !== prevCanary?.PercentTraffic) patchOperations.push({
20913
+ op: "replace",
20914
+ path: "/canarySettings/percentTraffic",
20915
+ value: String(canary.PercentTraffic ?? 0)
20916
+ });
20917
+ if (canary.DeploymentId !== prevCanary?.DeploymentId) patchOperations.push({
20918
+ op: "replace",
20919
+ path: "/canarySettings/deploymentId",
20920
+ value: canary.DeploymentId ?? ""
20921
+ });
20922
+ if (canary.UseStageCache !== prevCanary?.UseStageCache) patchOperations.push({
20923
+ op: "replace",
20924
+ path: "/canarySettings/useStageCache",
20925
+ value: String(canary.UseStageCache ?? false)
20926
+ });
20927
+ const overrides = canary.StageVariableOverrides ?? {};
20928
+ const prevOverrides = prevCanary?.StageVariableOverrides ?? {};
20929
+ for (const [key, value] of Object.entries(overrides)) if (prevOverrides[key] !== value) patchOperations.push({
20930
+ op: "replace",
20931
+ path: `/canarySettings/stageVariableOverrides/${key}`,
20932
+ value
20933
+ });
20934
+ for (const key of Object.keys(prevOverrides)) if (!(key in overrides)) patchOperations.push({
20935
+ op: "remove",
20936
+ path: `/canarySettings/stageVariableOverrides/${key}`
20937
+ });
20938
+ }
20820
20939
  const variables = properties["Variables"] ?? {};
20821
20940
  const prevVariables = previousProperties["Variables"] ?? {};
20822
20941
  for (const [key, value] of Object.entries(variables)) if (prevVariables[key] !== value) patchOperations.push({
@@ -21333,6 +21452,24 @@ var ApiGatewayProvider = class ApiGatewayProvider {
21333
21452
  result["Description"] = resp.description ?? "";
21334
21453
  if (resp.tracingEnabled !== void 0) result["TracingEnabled"] = resp.tracingEnabled;
21335
21454
  if (resp.variables !== void 0) result["Variables"] = resp.variables;
21455
+ if (resp.cacheClusterEnabled !== void 0) result["CacheClusterEnabled"] = resp.cacheClusterEnabled;
21456
+ if (resp.cacheClusterSize !== void 0) result["CacheClusterSize"] = resp.cacheClusterSize;
21457
+ if (resp.clientCertificateId !== void 0) result["ClientCertificateId"] = resp.clientCertificateId;
21458
+ if (resp.documentationVersion !== void 0) result["DocumentationVersion"] = resp.documentationVersion;
21459
+ if (resp.accessLogSettings !== void 0) {
21460
+ const accessLog = {};
21461
+ if (resp.accessLogSettings.destinationArn !== void 0) accessLog["DestinationArn"] = resp.accessLogSettings.destinationArn;
21462
+ if (resp.accessLogSettings.format !== void 0) accessLog["Format"] = resp.accessLogSettings.format;
21463
+ result["AccessLogSetting"] = accessLog;
21464
+ }
21465
+ if (resp.canarySettings !== void 0) {
21466
+ const canary = {};
21467
+ if (resp.canarySettings.percentTraffic !== void 0) canary["PercentTraffic"] = resp.canarySettings.percentTraffic;
21468
+ if (resp.canarySettings.deploymentId !== void 0) canary["DeploymentId"] = resp.canarySettings.deploymentId;
21469
+ if (resp.canarySettings.stageVariableOverrides !== void 0) canary["StageVariableOverrides"] = resp.canarySettings.stageVariableOverrides;
21470
+ if (resp.canarySettings.useStageCache !== void 0) canary["UseStageCache"] = resp.canarySettings.useStageCache;
21471
+ result["CanarySetting"] = canary;
21472
+ }
21336
21473
  const stateMethodSettings = properties?.["MethodSettings"];
21337
21474
  if (stateMethodSettings && stateMethodSettings.length > 0) result["MethodSettings"] = stateMethodSettings.map((stateEntry) => {
21338
21475
  const awsEntry = (resp.methodSettings ?? {})[methodSettingKey(stateEntry)];
@@ -21412,6 +21549,43 @@ var ApiGatewayProvider = class ApiGatewayProvider {
21412
21549
  }
21413
21550
  };
21414
21551
  /**
21552
+ * A nested CFn config block must be a plain object; a string, array, or
21553
+ * unresolved intrinsic that leaks through resolution indexes every sub-field
21554
+ * to `undefined` (#1471/#1493 class). Create refuses such a block; update
21555
+ * warns and skips the property.
21556
+ */
21557
+ function isPlainObjectBlock(value) {
21558
+ return typeof value === "object" && value !== null && !Array.isArray(value);
21559
+ }
21560
+ /**
21561
+ * Strip the `:*` suffix off a CloudWatch Logs log-group ARN.
21562
+ *
21563
+ * CDK's canonical `LogGroupLogDestination` emits `Fn::GetAtt [LogGroup, Arn]`
21564
+ * for `AccessLogSetting.DestinationArn`, and a log group's Arn attribute ends
21565
+ * with `:*` — a shape API Gateway's UpdateStage REJECTS ("Access log
21566
+ * destination must only contain characters a-z, ..."). CloudFormation's Stage
21567
+ * handler normalizes the suffix and accepts the template (proven by the
21568
+ * apigw-stage-throttling fixture's CC-routed history), so the SDK provider
21569
+ * must match for parity or every CDK `deployOptions.accessLogDestination`
21570
+ * app fails on deploy (caught live by that integ, 2026-08-11).
21571
+ */
21572
+ function normalizeAccessLogDestinationArn(arn) {
21573
+ return arn.endsWith(":*") ? arn.slice(0, -2) : arn;
21574
+ }
21575
+ /**
21576
+ * Map the CFn `CanarySetting` block to the SDK `CreateStageCommand`
21577
+ * `canarySettings` shape (PascalCase -> camelCase member rename).
21578
+ */
21579
+ function toSdkCanarySettings(setting) {
21580
+ if (setting == null) return void 0;
21581
+ return {
21582
+ percentTraffic: setting.PercentTraffic,
21583
+ deploymentId: setting.DeploymentId,
21584
+ stageVariableOverrides: setting.StageVariableOverrides,
21585
+ useStageCache: setting.UseStageCache
21586
+ };
21587
+ }
21588
+ /**
21415
21589
  * CFn MethodSetting field → UpdateStage patch-path suffix under
21416
21590
  * `/{method_setting_key}/`. The get-stage response field for each is the
21417
21591
  * camelCase of the CFn name (used by the drift readback).
@@ -43152,6 +43326,87 @@ const DEFAULT_EVENT_SELECTORS = Object.freeze([Object.freeze({
43152
43326
  IncludeManagementEvents: true
43153
43327
  })]);
43154
43328
  /**
43329
+ * `undefined` for an absent / null / EMPTY optional string field.
43330
+ *
43331
+ * Module-scoped since issue #1565 so `create()` can use it too: an always-emit
43332
+ * placeholder can reach `create()` — `drift --accept` falls back to mutating
43333
+ * `properties` when `observedProperties` is absent, and the rollback executor
43334
+ * replays `previousState.properties` through `create()` on a reverse
43335
+ * replacement — and `CreateTrail` with `CloudWatchLogsLogGroupArn: ''` is an
43336
+ * UNPROBED shape that may 400 on ARN format. `''` there means "not
43337
+ * configured", which is exactly what omitting the field says.
43338
+ *
43339
+ * The update path is where the distinction between absent and `''` matters
43340
+ * (see {@link resolveCloudWatchLogsPair}); on create there is no previous
43341
+ * value to clear, so both collapse to "omit".
43342
+ */
43343
+ function emptyToUndefined(v) {
43344
+ if (v === void 0 || v === null || v === "") return void 0;
43345
+ return v;
43346
+ }
43347
+ /**
43348
+ * Resolve the `CloudWatchLogsLogGroupArn` / `CloudWatchLogsRoleArn` pair for an
43349
+ * `UpdateTrail`, distinguishing an ABSENT desired side from an explicit `''`.
43350
+ *
43351
+ * The pair is all-or-nothing on AWS, so the two fields are decided TOGETHER —
43352
+ * the caller cannot build the half-configured request AWS rejects.
43353
+ *
43354
+ * - ABSENT (`undefined` / `null`) on BOTH sides -> send neither. The template
43355
+ * never declared them, and the live CFn A/B (2026-08-10) measured a template
43356
+ * removal as RETAINED, so sending nothing IS the parity behavior. `null`
43357
+ * counts as absent because a JSON state round-trip can produce one where the
43358
+ * template had nothing.
43359
+ * - BOTH `''` -> send both. `''` is the clear, which is what makes a
43360
+ * `drift --revert` of a console-side enable actually revert (issue #1565).
43361
+ * On an already-unwired trail that re-asserts a null field, which AWS accepts
43362
+ * as the no-op it is, and it rides an `UpdateTrail` this method issues
43363
+ * anyway. Deliberately NOT gated on "differs from the previous side": that
43364
+ * gate would also stop forwarding an UNCHANGED populated pair, which
43365
+ * `cloudtrail-provider-roundtrip.test.ts` pins as a wire-layer guarantee.
43366
+ * - BOTH populated -> send both verbatim.
43367
+ * - Anything else — a non-string value, or exactly ONE half populated -> send
43368
+ * NEITHER, and report it. Both shapes are unusable rather than meaningful:
43369
+ * coercing them would send `''` next to a real ARN (the request AWS rejects)
43370
+ * or, worse, read a malformed `null` as a CLEAR and silently disable a live
43371
+ * trail's CloudWatch Logs delivery — the
43372
+ * `malformed-value-must-not-read-as-removal` class this same file already
43373
+ * guards for `EventSelectors`. Leaving the pair alone is the non-destructive
43374
+ * reading, and the caller warns so the divergence is loud.
43375
+ *
43376
+ * Only the DESIRED side decides, which keeps the guard-the-desired-side-only
43377
+ * rule intact.
43378
+ */
43379
+ function resolveCloudWatchLogsPair(properties) {
43380
+ const desiredGroup = properties["CloudWatchLogsLogGroupArn"];
43381
+ const desiredRole = properties["CloudWatchLogsRoleArn"];
43382
+ if (desiredGroup == null && desiredRole == null) return {
43383
+ logGroupArn: void 0,
43384
+ roleArn: void 0
43385
+ };
43386
+ if (typeof desiredGroup !== "string" || typeof desiredRole !== "string") return {
43387
+ logGroupArn: void 0,
43388
+ roleArn: void 0,
43389
+ unusable: `CloudWatchLogsLogGroupArn / CloudWatchLogsRoleArn must both be strings (got ${describeValue(desiredGroup)} / ${describeValue(desiredRole)}) — check for an unresolved intrinsic or a half-written state record`
43390
+ };
43391
+ if (desiredGroup === "" !== (desiredRole === "")) return {
43392
+ logGroupArn: void 0,
43393
+ roleArn: void 0,
43394
+ unusable: "CloudWatchLogsLogGroupArn / CloudWatchLogsRoleArn are all-or-nothing on AWS, but only one of them carries a value — sending the pair would be rejected"
43395
+ };
43396
+ return {
43397
+ logGroupArn: desiredGroup,
43398
+ roleArn: desiredRole
43399
+ };
43400
+ }
43401
+ /** Human-readable type for a warning, without echoing user data. */
43402
+ function describeValue(value) {
43403
+ if (value === null) return "null";
43404
+ if (value === void 0) return "nothing";
43405
+ if (Array.isArray(value)) return "an array";
43406
+ if (typeof value === "string") return value === "" ? "''" : "a string";
43407
+ return `a ${typeof value}`;
43408
+ }
43409
+ /**
43155
43410
  * SDK Provider for AWS CloudTrail resources
43156
43411
  *
43157
43412
  * Supports:
@@ -43190,16 +43445,16 @@ var CloudTrailProvider = class {
43190
43445
  const s3BucketName = properties["S3BucketName"];
43191
43446
  if (!s3BucketName) throw new ProvisioningError(`S3BucketName is required for CloudTrail Trail ${logicalId}`, resourceType, logicalId);
43192
43447
  const trailName = properties["TrailName"];
43193
- const s3KeyPrefix = properties["S3KeyPrefix"];
43448
+ const s3KeyPrefix = emptyToUndefined(properties["S3KeyPrefix"]);
43194
43449
  const isMultiRegionTrail = properties["IsMultiRegionTrail"];
43195
43450
  const includeGlobalServiceEvents = properties["IncludeGlobalServiceEvents"];
43196
43451
  const enableLogFileValidation = properties["EnableLogFileValidation"];
43197
43452
  const isLogging = properties["IsLogging"];
43198
43453
  const tags = properties["Tags"];
43199
- const cloudWatchLogsLogGroupArn = properties["CloudWatchLogsLogGroupArn"];
43200
- const cloudWatchLogsRoleArn = properties["CloudWatchLogsRoleArn"];
43201
- const kmsKeyId = properties["KMSKeyId"];
43202
- const snsTopicName = properties["SnsTopicName"];
43454
+ const cloudWatchLogsLogGroupArn = emptyToUndefined(properties["CloudWatchLogsLogGroupArn"]);
43455
+ const cloudWatchLogsRoleArn = emptyToUndefined(properties["CloudWatchLogsRoleArn"]);
43456
+ const kmsKeyId = emptyToUndefined(properties["KMSKeyId"]);
43457
+ const snsTopicName = emptyToUndefined(properties["SnsTopicName"]);
43203
43458
  const isOrganizationTrail = properties["IsOrganizationTrail"];
43204
43459
  const eventSelectors = properties["EventSelectors"];
43205
43460
  const insightSelectors = properties["InsightSelectors"];
@@ -43251,18 +43506,16 @@ var CloudTrailProvider = class {
43251
43506
  }
43252
43507
  async update(logicalId, physicalId, resourceType, properties, previousProperties) {
43253
43508
  this.logger.debug(`Updating CloudTrail Trail ${logicalId}: ${physicalId}`);
43254
- const emptyToUndefined = (v) => {
43255
- if (v === void 0 || v === null || v === "") return void 0;
43256
- return v;
43257
- };
43258
43509
  const s3BucketName = properties["S3BucketName"];
43259
43510
  const s3KeyPrefix = clearOnUpdateRemoval(emptyToUndefined(properties["S3KeyPrefix"]), emptyToUndefined(previousProperties["S3KeyPrefix"]), "");
43260
43511
  const isMultiRegionTrail = clearOnUpdateRemoval(properties["IsMultiRegionTrail"], previousProperties["IsMultiRegionTrail"], false);
43261
43512
  const includeGlobalServiceEvents = isMultiRegionTrail === false ? clearOnUpdateRemoval(properties["IncludeGlobalServiceEvents"], previousProperties["IncludeGlobalServiceEvents"], false) : properties["IncludeGlobalServiceEvents"];
43262
43513
  const enableLogFileValidation = clearOnUpdateRemoval(properties["EnableLogFileValidation"], previousProperties["EnableLogFileValidation"], false);
43263
43514
  const isLogging = properties["IsLogging"];
43264
- const cloudWatchLogsLogGroupArn = emptyToUndefined(properties["CloudWatchLogsLogGroupArn"]);
43265
- const cloudWatchLogsRoleArn = emptyToUndefined(properties["CloudWatchLogsRoleArn"]);
43515
+ const cwPair = resolveCloudWatchLogsPair(properties);
43516
+ if (cwPair.unusable !== void 0) this.logger.warn(`CloudTrail Trail ${logicalId}: ${cwPair.unusable}. The trail's existing CloudWatch Logs wiring is left untouched for this update.`);
43517
+ const cloudWatchLogsLogGroupArn = cwPair.logGroupArn;
43518
+ const cloudWatchLogsRoleArn = cwPair.roleArn;
43266
43519
  const kmsKeyId = emptyToUndefined(properties["KMSKeyId"]);
43267
43520
  const snsTopicName = clearOnUpdateRemoval(emptyToUndefined(properties["SnsTopicName"]), emptyToUndefined(previousProperties["SnsTopicName"]), "");
43268
43521
  const isOrganizationTrail = properties["IsOrganizationTrail"];
@@ -43444,10 +43697,8 @@ var CloudTrailProvider = class {
43444
43697
  result["IsMultiRegionTrail"] = trail.IsMultiRegionTrail ?? false;
43445
43698
  result["IncludeGlobalServiceEvents"] = trail.IncludeGlobalServiceEvents ?? true;
43446
43699
  result["EnableLogFileValidation"] = trail.LogFileValidationEnabled ?? false;
43447
- if (trail.CloudWatchLogsLogGroupArn && trail.CloudWatchLogsRoleArn) {
43448
- result["CloudWatchLogsLogGroupArn"] = trail.CloudWatchLogsLogGroupArn;
43449
- result["CloudWatchLogsRoleArn"] = trail.CloudWatchLogsRoleArn;
43450
- }
43700
+ result["CloudWatchLogsLogGroupArn"] = trail.CloudWatchLogsLogGroupArn ?? "";
43701
+ result["CloudWatchLogsRoleArn"] = trail.CloudWatchLogsRoleArn ?? "";
43451
43702
  result["KMSKeyId"] = trail.KmsKeyId ?? "";
43452
43703
  result["SnsTopicName"] = trail.SnsTopicName ?? "";
43453
43704
  result["IsOrganizationTrail"] = trail.IsOrganizationTrail ?? false;
@@ -68114,7 +68365,7 @@ function createMigrateCommand() {
68114
68365
  */
68115
68366
  function buildProgram() {
68116
68367
  const program = new Command();
68117
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.279.0");
68368
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.280.1");
68118
68369
  program.hook("preAction", (_thisCommand, actionCommand) => {
68119
68370
  const { profile } = actionCommand.optsWithGlobals();
68120
68371
  if (profile !== void 0) process.env["AWS_PROFILE"] = profile;