@go-to-k/cdkd 0.276.4 → 0.276.6

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 DagBuilder, A as red, At as resolveApp, B as isTerminationProtectionPropagationError, Bt as CFN_TEMPLATE_URL_LIMIT, C as isStatefulRecreateTargetSync, Ct as runDockerStreaming, D as cyan, Dt as synthesisStatusMessage, E as bold, Et as Synthesizer, F as ProviderRegistry, Ft as resolveStateBucketWithDefaultAndSource, G as normalizeAwsTagsToCfn, Gt as AssemblyReader, H as cfnRefValueFromPhysicalId, Ht as findLargeInlineResources, I as findActionableSilentDrops, It as resolveUseCdkBootstrapAssets, J as applyRoleArnIfSet, Jt as resolveBucketRegion, K as resolveExplicitPhysicalId, Kt as processStackMessages, L as CloudControlProvider, Lt as stateBucketExistenceConfirmed, M as IAMRoleProvider, Mt as resolveCaptureObservedState, N as collectInlinePolicyNamesManagedBySiblings, Nt as resolveSkipPrefix, O as gray, Ot as getDefaultStateBucketName, P as clearOnUpdateRemoval, Pt as resolveStateBucketWithDefault, Q as isRetryableTransientError, Qt as setAwsClients, R as slowCcOperationTimeoutMs, Rt as warnDeprecatedNoPrefixCliFlag, S as MULTI_REGION_RECREATE_BLOCKED_TYPES, St as runDockerForeground, T as formatResourceLine, Tt as getDockerImageBySourceHash, U as refStateLookupFromResource, Ut as uploadCfnTemplate, V as IntrinsicFunctionResolver, Vt as MIGRATE_TMP_PREFIX, W as WAFv2WebACLProvider, Wt as expectedOwnerParam, X as describeTypeWithThrottleRetry, Xt as getAwsClients, Y as DiffCalculator, Yt as AwsClients, Z as withRetry, Zt as resetAwsClients, _ as createPreDeleteFinalSnapshot, _t as validateAssetBucketName, a as DeploymentEventsStore, an as LocalMigrateError, at as AssetPublisher, b as unsupportedFinalSnapshotError, bn as normalizeAwsError, bt as formatDockerLoginError, c as replayFailedOperations, cn as MissingCdkCliError, ct as buildAssetRedirectMap, d as IMPLICIT_DELETE_DEPENDENCIES, dn as ProvisioningError, dt as rewriteTemplateAssetReferences, en as CdkdError, et as TemplateParser, f as computeImplicitDeleteEdges, fn as ResourceTimeoutError, ft as AssetModeResolver, g as ccRoutedFinalSnapshotError, gt as parseBootstrapMarker, h as buildFinalSnapshotIdentifier, hn as StackTerminationProtectionError, ht as getBootstrapMarkerKey, i as DeploymentEventsReader, in as LocalInvokeBuildError$1, it as shouldRetainResource, j as yellow, jt as resolveAutoAssetStorage, k as green, kt as getLegacyStateBucketName, l as replayRollback, ln as NestedStackChildDirectDestroyError, lt as createAssetRedirectResolver, m as PRE_DELETE_SNAPSHOT_TYPES, mn as StackHasActiveImportsError, mt as ensureAssetStorage, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nt as S3StateBackend, o as planFailedOps, on as LocalStartServiceError, ot as stringifyValue, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as ResourceUpdateNotSupportedError, pt as BOOTSTRAP_MARKER_PREFIX, q as assertRegionMatch, r as DeployEngine, rn as DeployCancelledError, rt as rebuildClientForBucketRegion, s as planRollback, st as WorkGraph, t as DEFAULT_RESOURCE_TIMEOUT_MS, tt as LockManager, u as withResourceDeadline, un as PartialFailureError, ut as loadPublishableAssetManifest, v as isFinalSnapshotError, vt as validateContainerRepoName, w as renderStatefulReason, wt as AssetManifestLoader, x as extractDeploymentEventError, xn as withErrorHandling, xt as getDockerCmd, y as refusesFinalSnapshot, yt as buildDockerImage, z as disableInstanceApiTermination, zt as CFN_TEMPLATE_BODY_LIMIT } from "./deploy-engine-us-U4a0a.js";
2
+ import { $ as DagBuilder, A as red, At as resolveApp, B as isTerminationProtectionPropagationError, Bt as CFN_TEMPLATE_URL_LIMIT, C as isStatefulRecreateTargetSync, Ct as runDockerStreaming, D as cyan, Dt as synthesisStatusMessage, E as bold, Et as Synthesizer, F as ProviderRegistry, Ft as resolveStateBucketWithDefaultAndSource, G as normalizeAwsTagsToCfn, Gt as AssemblyReader, H as cfnRefValueFromPhysicalId, Ht as findLargeInlineResources, I as findActionableSilentDrops, It as resolveUseCdkBootstrapAssets, J as applyRoleArnIfSet, Jt as resolveBucketRegion, K as resolveExplicitPhysicalId, Kt as processStackMessages, L as CloudControlProvider, Lt as stateBucketExistenceConfirmed, M as IAMRoleProvider, Mt as resolveCaptureObservedState, N as collectInlinePolicyNamesManagedBySiblings, Nt as resolveSkipPrefix, O as gray, Ot as getDefaultStateBucketName, P as clearOnUpdateRemoval, Pt as resolveStateBucketWithDefault, Q as isRetryableTransientError, Qt as setAwsClients, R as slowCcOperationTimeoutMs, Rt as warnDeprecatedNoPrefixCliFlag, S as MULTI_REGION_RECREATE_BLOCKED_TYPES, St as runDockerForeground, T as formatResourceLine, Tt as getDockerImageBySourceHash, U as refStateLookupFromResource, Ut as uploadCfnTemplate, V as IntrinsicFunctionResolver, Vt as MIGRATE_TMP_PREFIX, W as WAFv2WebACLProvider, Wt as expectedOwnerParam, X as describeTypeWithThrottleRetry, Xt as getAwsClients, Y as DiffCalculator, Yt as AwsClients, Z as withRetry, Zt as resetAwsClients, _ as createPreDeleteFinalSnapshot, _t as validateAssetBucketName, a as DeploymentEventsStore, an as LocalMigrateError, at as AssetPublisher, b as unsupportedFinalSnapshotError, bn as normalizeAwsError, bt as formatDockerLoginError, c as replayFailedOperations, cn as MissingCdkCliError, ct as buildAssetRedirectMap, d as IMPLICIT_DELETE_DEPENDENCIES, dn as ProvisioningError, dt as rewriteTemplateAssetReferences, en as CdkdError, et as TemplateParser, f as computeImplicitDeleteEdges, fn as ResourceTimeoutError, ft as AssetModeResolver, g as ccRoutedFinalSnapshotError, gt as parseBootstrapMarker, h as buildFinalSnapshotIdentifier, hn as StackTerminationProtectionError, ht as getBootstrapMarkerKey, i as DeploymentEventsReader, in as LocalInvokeBuildError$1, it as shouldRetainResource, j as yellow, jt as resolveAutoAssetStorage, k as green, kt as getLegacyStateBucketName, l as replayRollback, ln as NestedStackChildDirectDestroyError, lt as createAssetRedirectResolver, m as PRE_DELETE_SNAPSHOT_TYPES, mn as StackHasActiveImportsError, mt as ensureAssetStorage, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nt as S3StateBackend, o as planFailedOps, on as LocalStartServiceError, ot as stringifyValue, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as ResourceUpdateNotSupportedError, pt as BOOTSTRAP_MARKER_PREFIX, q as assertRegionMatch, r as DeployEngine, rn as DeployCancelledError, rt as rebuildClientForBucketRegion, s as planRollback, st as WorkGraph, t as DEFAULT_RESOURCE_TIMEOUT_MS, tt as LockManager, u as withResourceDeadline, un as PartialFailureError, ut as loadPublishableAssetManifest, v as isFinalSnapshotError, vt as validateContainerRepoName, w as renderStatefulReason, wt as AssetManifestLoader, x as extractDeploymentEventError, xn as withErrorHandling, xt as getDockerCmd, y as refusesFinalSnapshot, yt as buildDockerImage, z as disableInstanceApiTermination, zt as CFN_TEMPLATE_BODY_LIMIT } from "./deploy-engine-1kK9dZKt.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-xUGPo-HF.js";
4
+ import { t as ASGProvider } from "./asg-provider-Br39eGQt.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, DeleteBucketIntelligentTieringConfigurationCommand, DeleteBucketInventoryConfigurationCommand, DeleteBucketLifecycleCommand, DeleteBucketMetricsConfigurationCommand, DeleteBucketPolicyCommand, DeleteBucketReplicationCommand, DeleteBucketTaggingCommand, DeleteBucketWebsiteCommand, DeleteObjectsCommand, GetBucketAccelerateConfigurationCommand, GetBucketCorsCommand, GetBucketEncryptionCommand, GetBucketLifecycleConfigurationCommand, GetBucketLocationCommand, GetBucketLoggingCommand, GetBucketNotificationConfigurationCommand, 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";
@@ -14168,8 +14168,8 @@ function buildDeleteParams(properties) {
14168
14168
  function toDate(value) {
14169
14169
  if (value === void 0) return void 0;
14170
14170
  if (value instanceof Date) return value;
14171
- const parsed = new Date(String(value));
14172
- if (Number.isNaN(parsed.getTime())) throw new Error(`Configuration.ExcludedTimeRanges contains an unparsable time value: ${String(value)}`);
14171
+ const parsed = typeof value === "string" || typeof value === "number" ? new Date(value) : /* @__PURE__ */ new Date(NaN);
14172
+ if (Number.isNaN(parsed.getTime())) throw new Error(`Configuration.ExcludedTimeRanges contains an unparsable time value: ${JSON.stringify(value)}`);
14173
14173
  return parsed;
14174
14174
  }
14175
14175
  /**
@@ -21042,6 +21042,79 @@ const QUANTITY_ITEM_FIELDS = [
21042
21042
  "Aliases"
21043
21043
  ];
21044
21044
  /**
21045
+ * `ViewerCertificate` members whose ACRONYM CASING differs between the CFn
21046
+ * resource schema and the CloudFront API (issue #1370). The CFn template
21047
+ * carries the left-hand spelling; the SDK model only knows the right-hand
21048
+ * one, so an unrenamed key silently never reaches AWS — a custom-domain
21049
+ * distribution then fails to create ("Your ViewerCertificate is missing one
21050
+ * of ACMCertificateArn, IAMCertificateId, or CloudFrontDefaultCertificate").
21051
+ */
21052
+ const VIEWER_CERTIFICATE_CFN_TO_SDK = {
21053
+ AcmCertificateArn: "ACMCertificateArn",
21054
+ SslSupportMethod: "SSLSupportMethod",
21055
+ IamCertificateId: "IAMCertificateId"
21056
+ };
21057
+ /**
21058
+ * Top-level `DistributionConfig` members with the same CFn-vs-SDK casing
21059
+ * divergence (issue #1370): the template's `IPV6Enabled` is `IsIPV6Enabled`
21060
+ * in the SDK model, so it was silently dropped (IPv6 ended up disabled).
21061
+ */
21062
+ const TOP_LEVEL_CFN_TO_SDK = { IPV6Enabled: "IsIPV6Enabled" };
21063
+ /**
21064
+ * CloudFormation defaults applied when a top-level `DistributionConfig`
21065
+ * member present in the PREVIOUS template is REMOVED from the new one
21066
+ * (issue #1371). `UpdateDistribution` is a read-modify-write API taking the
21067
+ * complete config, so the update path merges the template over the live
21068
+ * config — but a member the user deleted from the template must reset to
21069
+ * its CloudFormation default (CFn semantics), not silently keep its live
21070
+ * value. Values are in SDK shape.
21071
+ *
21072
+ * Sources: the AWS::CloudFront::Distribution registry schema `default`
21073
+ * annotations (Comment / DefaultRootObject / HttpVersion / PriceClass /
21074
+ * Restrictions / ViewerCertificate / WebACLId — verified via
21075
+ * `cloudformation:DescribeType`, 2026-08-09); list members reset to the
21076
+ * empty `{ Quantity: 0, Items: [] }` wrapper (removing a list property
21077
+ * means "no items"); `Logging` to the API's documented off shape. Removed
21078
+ * members with NO entry here (e.g. `IsIPV6Enabled` / `Staging` — no
21079
+ * schema-documented default) keep their live value with a warning: a
21080
+ * visible conservative choice, never a silent guess.
21081
+ */
21082
+ const REMOVAL_RESET_DEFAULTS = {
21083
+ Aliases: {
21084
+ Quantity: 0,
21085
+ Items: []
21086
+ },
21087
+ CacheBehaviors: {
21088
+ Quantity: 0,
21089
+ Items: []
21090
+ },
21091
+ Comment: "",
21092
+ CustomErrorResponses: {
21093
+ Quantity: 0,
21094
+ Items: []
21095
+ },
21096
+ DefaultRootObject: "",
21097
+ HttpVersion: "http1.1",
21098
+ Logging: {
21099
+ Enabled: false,
21100
+ IncludeCookies: false,
21101
+ Bucket: "",
21102
+ Prefix: ""
21103
+ },
21104
+ OriginGroups: {
21105
+ Quantity: 0,
21106
+ Items: []
21107
+ },
21108
+ PriceClass: "PriceClass_All",
21109
+ Restrictions: { GeoRestriction: {
21110
+ RestrictionType: "none",
21111
+ Quantity: 0,
21112
+ Items: []
21113
+ } },
21114
+ ViewerCertificate: { CloudFrontDefaultCertificate: true },
21115
+ WebACLId: ""
21116
+ };
21117
+ /**
21045
21118
  * Nested fields inside each CacheBehavior / DefaultCacheBehavior that use
21046
21119
  * the Quantity + Items pattern.
21047
21120
  */
@@ -21107,8 +21180,18 @@ var CloudFrontDistributionProvider = class {
21107
21180
  /**
21108
21181
  * Update a CloudFront Distribution
21109
21182
  *
21110
- * Gets the current config via GetDistributionConfigCommand, merges new properties,
21111
- * then calls UpdateDistributionCommand with the required IfMatch ETag.
21183
+ * `UpdateDistribution` is a read-modify-write API that expects the COMPLETE
21184
+ * configuration, while a CFn template legitimately omits every optional
21185
+ * member the user did not set — sending the template verbatim fails on the
21186
+ * first required-on-update member the template lacks ("WebACLId is missing
21187
+ * for the resource", issue #1371). So the update merges per top-level
21188
+ * member: `GetDistributionConfigCommand`'s current config is the base, the
21189
+ * template is the authority for every member it carries, a member REMOVED
21190
+ * since the previous template resets to its CloudFormation default
21191
+ * (matching CFn's omission-resets semantics rather than silently keeping
21192
+ * the live value), and `CallerReference` is always preserved from the
21193
+ * current config. Then calls `UpdateDistributionCommand` with the required
21194
+ * IfMatch ETag.
21112
21195
  */
21113
21196
  async update(logicalId, physicalId, resourceType, properties, previousProperties) {
21114
21197
  this.logger.debug(`Updating CloudFront Distribution ${logicalId}: ${physicalId}`);
@@ -21117,10 +21200,8 @@ var CloudFrontDistributionProvider = class {
21117
21200
  const etag = getConfigResponse.ETag;
21118
21201
  const currentConfig = getConfigResponse.DistributionConfig;
21119
21202
  const newDistributionConfig = properties["DistributionConfig"] ?? {};
21120
- const sdkConfig = this.convertToSdkFormat({
21121
- ...newDistributionConfig,
21122
- CallerReference: currentConfig.CallerReference
21123
- });
21203
+ const previousDistributionConfig = previousProperties["DistributionConfig"] ?? {};
21204
+ const sdkConfig = this.mergeUpdateConfig(currentConfig, newDistributionConfig, previousDistributionConfig, logicalId);
21124
21205
  await this.cloudFrontClient.send(new UpdateDistributionCommand({
21125
21206
  Id: physicalId,
21126
21207
  IfMatch: etag,
@@ -21276,6 +21357,21 @@ var CloudFrontDistributionProvider = class {
21276
21357
  return ["DistributionConfig.CallerReference", "DistributionConfig.Logging.Bucket"];
21277
21358
  }
21278
21359
  /**
21360
+ * Plain-string arrays that are semantically UNORDERED sets, per
21361
+ * {@link ResourceProvider.getDriftUnorderedPaths}.
21362
+ *
21363
+ * `GeoRestriction.Locations` is a set of ISO country codes — the
21364
+ * CloudFront API reference documents no ordering semantics and the
21365
+ * service does not echo the submitted order back (observed live in the
21366
+ * `s3-cloudfront` integ, 2026-08-09: a template `[JP, US]` allowlist
21367
+ * read back as `[US, JP]`), so a positional compare fires guaranteed
21368
+ * phantom drift on any multi-country restriction.
21369
+ */
21370
+ getDriftUnorderedPaths(resourceType) {
21371
+ if (resourceType !== "AWS::CloudFront::Distribution") return [];
21372
+ return ["DistributionConfig.Restrictions.GeoRestriction.Locations"];
21373
+ }
21374
+ /**
21279
21375
  * Get resource attribute (for Fn::GetAtt resolution)
21280
21376
  */
21281
21377
  async getAttribute(physicalId, _resourceType, attributeName) {
@@ -21361,6 +21457,124 @@ var CloudFrontDistributionProvider = class {
21361
21457
  }
21362
21458
  }
21363
21459
  /**
21460
+ * Build the complete SDK-shape `DistributionConfig` for an update
21461
+ * (issue #1371). Per top-level member:
21462
+ *
21463
+ * - present in the new template -> template value (authority)
21464
+ * - removed since the previous template -> CloudFormation default
21465
+ * ({@link REMOVAL_RESET_DEFAULTS}); a member with no known default keeps
21466
+ * its live value with a WARN (visible, never a silent decision)
21467
+ * - never templated -> live value from `currentConfig`
21468
+ * (the AWS-side default filled at create, or an out-of-band setting cdkd
21469
+ * never managed)
21470
+ *
21471
+ * One deliberate exception to the never-templated rule: `Comment` is
21472
+ * always present in `templateSdk` ({@link convertToSdkFormat} injects
21473
+ * `''` when absent — the SDK requires a non-null string), so an
21474
+ * untemplated Comment resets to `''` rather than keeping the live value.
21475
+ * That matches its CFn registry-schema default and the pre-merge
21476
+ * behavior.
21477
+ *
21478
+ * `CallerReference` is always preserved from the current config (a
21479
+ * create-time idempotency token the template never carries).
21480
+ */
21481
+ mergeUpdateConfig(currentConfig, newDistributionConfig, previousDistributionConfig, logicalId) {
21482
+ const templateSdk = this.convertToSdkFormat(newDistributionConfig);
21483
+ const previousSdk = this.convertToSdkFormat(previousDistributionConfig);
21484
+ const merged = { ...currentConfig };
21485
+ for (const key of Object.keys(previousSdk)) {
21486
+ if (key in templateSdk || key === "CallerReference") continue;
21487
+ if (key in REMOVAL_RESET_DEFAULTS) merged[key] = structuredClone(REMOVAL_RESET_DEFAULTS[key]);
21488
+ else {
21489
+ const cfnKey = Object.entries(TOP_LEVEL_CFN_TO_SDK).find(([, sdkKey]) => sdkKey === key)?.[0] ?? key;
21490
+ this.logger.warn(`CloudFront Distribution ${logicalId}: '${cfnKey}' was removed from the template but has no known CloudFormation default; keeping the live value. Set the property explicitly in the template to control it.`);
21491
+ }
21492
+ }
21493
+ Object.assign(merged, templateSdk);
21494
+ merged["CallerReference"] = currentConfig["CallerReference"];
21495
+ this.completeRequiredUpdateFields(merged);
21496
+ return merged;
21497
+ }
21498
+ /**
21499
+ * Fill the sub-fields `UpdateDistribution` REQUIRES but a CFn template
21500
+ * legitimately omits (issue #1371, second layer). The top-level merge
21501
+ * makes the payload complete per member, but the template-authoritative
21502
+ * `Origins` / `DefaultCacheBehavior` / `CacheBehaviors` members carry the
21503
+ * template's SPARSE sub-shapes, and the API — which accepts them sparse
21504
+ * on CREATE — rejects an update with per-field errors ("The
21505
+ * 'OriginCustomHeaders' field is missing", "OriginReadTimeout is required
21506
+ * for updates", "The parameter SmoothStreaming flag is missing", ...).
21507
+ *
21508
+ * The set below is the EMPIRICALLY REQUIRED list (probed live against
21509
+ * UpdateDistribution, 2026-08-09) plus its symmetric CFn-default
21510
+ * companions (`FunctionAssociations` / `TrustedSigners` /
21511
+ * `TrustedKeyGroups` — same association/signer family, filled with the
21512
+ * same disabled/empty CFn defaults CloudFormation submits for an
21513
+ * omitted property). Values a template DOES carry always win — every
21514
+ * fill is absent-only. Legacy `ForwardedValues`-mode TTLs are
21515
+ * deliberately NOT filled (they are forbidden alongside `CachePolicyId`,
21516
+ * so a wrong guess would break the modern mode; a legacy template that
21517
+ * needs them fails loudly and can be added here).
21518
+ */
21519
+ completeRequiredUpdateFields(config) {
21520
+ const origins = config["Origins"];
21521
+ if (origins && Array.isArray(origins["Items"])) origins["Items"] = origins["Items"].map((origin) => {
21522
+ const o = { ...origin };
21523
+ if (o["OriginPath"] === void 0) o["OriginPath"] = "";
21524
+ if (o["CustomHeaders"] === void 0) o["CustomHeaders"] = {
21525
+ Quantity: 0,
21526
+ Items: []
21527
+ };
21528
+ if (o["CustomOriginConfig"] && typeof o["CustomOriginConfig"] === "object") {
21529
+ const c = { ...o["CustomOriginConfig"] };
21530
+ if (c["OriginReadTimeout"] === void 0) c["OriginReadTimeout"] = 30;
21531
+ if (c["OriginKeepaliveTimeout"] === void 0) c["OriginKeepaliveTimeout"] = 5;
21532
+ o["CustomOriginConfig"] = c;
21533
+ }
21534
+ return o;
21535
+ });
21536
+ const fillBehavior = (behavior) => {
21537
+ const b = { ...behavior };
21538
+ if (b["SmoothStreaming"] === void 0) b["SmoothStreaming"] = false;
21539
+ if (b["FieldLevelEncryptionId"] === void 0) b["FieldLevelEncryptionId"] = "";
21540
+ if (b["LambdaFunctionAssociations"] === void 0) b["LambdaFunctionAssociations"] = {
21541
+ Quantity: 0,
21542
+ Items: []
21543
+ };
21544
+ if (b["FunctionAssociations"] === void 0) b["FunctionAssociations"] = {
21545
+ Quantity: 0,
21546
+ Items: []
21547
+ };
21548
+ if (b["TrustedSigners"] === void 0) b["TrustedSigners"] = {
21549
+ Enabled: false,
21550
+ Quantity: 0
21551
+ };
21552
+ if (b["TrustedKeyGroups"] === void 0) b["TrustedKeyGroups"] = {
21553
+ Enabled: false,
21554
+ Quantity: 0
21555
+ };
21556
+ if (b["AllowedMethods"] === void 0) b["AllowedMethods"] = {
21557
+ Quantity: 2,
21558
+ Items: ["GET", "HEAD"],
21559
+ CachedMethods: {
21560
+ Quantity: 2,
21561
+ Items: ["GET", "HEAD"]
21562
+ }
21563
+ };
21564
+ else if (b["AllowedMethods"] && typeof b["AllowedMethods"] === "object" && b["AllowedMethods"]["CachedMethods"] === void 0) b["AllowedMethods"] = {
21565
+ ...b["AllowedMethods"],
21566
+ CachedMethods: {
21567
+ Quantity: 2,
21568
+ Items: ["GET", "HEAD"]
21569
+ }
21570
+ };
21571
+ return b;
21572
+ };
21573
+ if (config["DefaultCacheBehavior"] && typeof config["DefaultCacheBehavior"] === "object") config["DefaultCacheBehavior"] = fillBehavior(config["DefaultCacheBehavior"]);
21574
+ const cacheBehaviors = config["CacheBehaviors"];
21575
+ if (cacheBehaviors && Array.isArray(cacheBehaviors["Items"])) cacheBehaviors["Items"] = cacheBehaviors["Items"].map((cb) => fillBehavior(cb));
21576
+ }
21577
+ /**
21364
21578
  * Convert CDK/CloudFormation DistributionConfig format to SDK format.
21365
21579
  *
21366
21580
  * The main transformation is adding Quantity fields where the SDK expects
@@ -21370,21 +21584,49 @@ var CloudFrontDistributionProvider = class {
21370
21584
  convertToSdkFormat(config) {
21371
21585
  const result = { ...config };
21372
21586
  if (result["Comment"] === null || result["Comment"] === void 0) result["Comment"] = "";
21587
+ for (const [cfnKey, sdkKey] of Object.entries(TOP_LEVEL_CFN_TO_SDK)) if (result[cfnKey] !== void 0) {
21588
+ result[sdkKey] = result[cfnKey];
21589
+ delete result[cfnKey];
21590
+ }
21591
+ if (result["ViewerCertificate"] && typeof result["ViewerCertificate"] === "object") {
21592
+ const viewerCertificate = { ...result["ViewerCertificate"] };
21593
+ for (const [cfnKey, sdkKey] of Object.entries(VIEWER_CERTIFICATE_CFN_TO_SDK)) if (viewerCertificate[cfnKey] !== void 0) {
21594
+ viewerCertificate[sdkKey] = viewerCertificate[cfnKey];
21595
+ delete viewerCertificate[cfnKey];
21596
+ }
21597
+ result["ViewerCertificate"] = viewerCertificate;
21598
+ }
21599
+ if (result["Restrictions"] && typeof result["Restrictions"] === "object") {
21600
+ const restrictions = { ...result["Restrictions"] };
21601
+ if (restrictions["GeoRestriction"] && typeof restrictions["GeoRestriction"] === "object") {
21602
+ const geo = { ...restrictions["GeoRestriction"] };
21603
+ if (Array.isArray(geo["Locations"])) {
21604
+ geo["Items"] = geo["Locations"];
21605
+ delete geo["Locations"];
21606
+ }
21607
+ if (geo["Quantity"] === void 0) geo["Quantity"] = Array.isArray(geo["Items"]) ? geo["Items"].length : 0;
21608
+ restrictions["GeoRestriction"] = geo;
21609
+ }
21610
+ result["Restrictions"] = restrictions;
21611
+ }
21373
21612
  if (result["Logging"] && typeof result["Logging"] === "object") {
21374
- const logging = result["Logging"];
21613
+ const logging = { ...result["Logging"] };
21375
21614
  if (logging["IncludeCookies"] === void 0) logging["IncludeCookies"] = false;
21376
21615
  if (logging["Enabled"] === void 0) logging["Enabled"] = true;
21377
21616
  if (logging["Prefix"] === void 0) logging["Prefix"] = "";
21617
+ result["Logging"] = logging;
21378
21618
  }
21379
21619
  for (const field of QUANTITY_ITEM_FIELDS) if (result[field] !== void 0) result[field] = this.wrapWithQuantity(result[field]);
21380
21620
  if (result["DefaultCacheBehavior"] && typeof result["DefaultCacheBehavior"] === "object") result["DefaultCacheBehavior"] = this.convertCacheBehavior(result["DefaultCacheBehavior"]);
21381
21621
  if (result["CacheBehaviors"] && typeof result["CacheBehaviors"] === "object") {
21382
- const cacheBehaviors = result["CacheBehaviors"];
21622
+ const cacheBehaviors = { ...result["CacheBehaviors"] };
21383
21623
  if (Array.isArray(cacheBehaviors["Items"])) cacheBehaviors["Items"] = cacheBehaviors["Items"].map((cb) => this.convertCacheBehavior(cb));
21624
+ result["CacheBehaviors"] = cacheBehaviors;
21384
21625
  }
21385
21626
  if (result["Origins"] && typeof result["Origins"] === "object") {
21386
- const origins = result["Origins"];
21627
+ const origins = { ...result["Origins"] };
21387
21628
  if (Array.isArray(origins["Items"])) origins["Items"] = origins["Items"].map((origin) => this.convertOrigin(origin));
21629
+ result["Origins"] = origins;
21388
21630
  }
21389
21631
  return result;
21390
21632
  }
@@ -21415,6 +21657,31 @@ var CloudFrontDistributionProvider = class {
21415
21657
  convertToCfnFormat(config) {
21416
21658
  const result = { ...config };
21417
21659
  delete result["CallerReference"];
21660
+ for (const [cfnKey, sdkKey] of Object.entries(TOP_LEVEL_CFN_TO_SDK)) if (result[sdkKey] !== void 0) {
21661
+ result[cfnKey] = result[sdkKey];
21662
+ delete result[sdkKey];
21663
+ }
21664
+ if (result["ViewerCertificate"] && typeof result["ViewerCertificate"] === "object") {
21665
+ const viewerCertificate = { ...result["ViewerCertificate"] };
21666
+ for (const [cfnKey, sdkKey] of Object.entries(VIEWER_CERTIFICATE_CFN_TO_SDK)) if (viewerCertificate[sdkKey] !== void 0) {
21667
+ viewerCertificate[cfnKey] = viewerCertificate[sdkKey];
21668
+ delete viewerCertificate[sdkKey];
21669
+ }
21670
+ result["ViewerCertificate"] = viewerCertificate;
21671
+ }
21672
+ if (result["Restrictions"] && typeof result["Restrictions"] === "object") {
21673
+ const restrictions = { ...result["Restrictions"] };
21674
+ if (restrictions["GeoRestriction"] && typeof restrictions["GeoRestriction"] === "object") {
21675
+ const geo = { ...restrictions["GeoRestriction"] };
21676
+ if (Array.isArray(geo["Items"])) {
21677
+ geo["Locations"] = geo["Items"];
21678
+ delete geo["Items"];
21679
+ }
21680
+ delete geo["Quantity"];
21681
+ restrictions["GeoRestriction"] = geo;
21682
+ }
21683
+ result["Restrictions"] = restrictions;
21684
+ }
21418
21685
  for (const field of QUANTITY_ITEM_FIELDS) if (result[field] !== void 0) result[field] = this.unwrapQuantity(result[field]);
21419
21686
  if (result["DefaultCacheBehavior"] && typeof result["DefaultCacheBehavior"] === "object") result["DefaultCacheBehavior"] = this.revertCacheBehavior(result["DefaultCacheBehavior"]);
21420
21687
  if (Array.isArray(result["CacheBehaviors"])) result["CacheBehaviors"] = result["CacheBehaviors"].map((cb) => this.revertCacheBehavior(cb));
@@ -21462,7 +21729,10 @@ var CloudFrontDistributionProvider = class {
21462
21729
  if (result["CustomHeaders"] !== void 0) result["CustomHeaders"] = this.unwrapQuantity(result["CustomHeaders"]);
21463
21730
  if (result["CustomOriginConfig"] && typeof result["CustomOriginConfig"] === "object") {
21464
21731
  const customOriginConfig = { ...result["CustomOriginConfig"] };
21465
- if (customOriginConfig["OriginSslProtocols"] !== void 0) customOriginConfig["OriginSslProtocols"] = this.unwrapQuantity(customOriginConfig["OriginSslProtocols"]);
21732
+ if (customOriginConfig["OriginSslProtocols"] !== void 0) {
21733
+ customOriginConfig["OriginSSLProtocols"] = this.unwrapQuantity(customOriginConfig["OriginSslProtocols"]);
21734
+ delete customOriginConfig["OriginSslProtocols"];
21735
+ }
21466
21736
  result["CustomOriginConfig"] = customOriginConfig;
21467
21737
  }
21468
21738
  return result;
@@ -21518,6 +21788,15 @@ var CloudFrontDistributionProvider = class {
21518
21788
  const parts = fieldPath.split(".");
21519
21789
  this.applyQuantityAtPath(result, parts);
21520
21790
  }
21791
+ if (result["CachedMethods"] !== void 0) {
21792
+ const allowedMethods = result["AllowedMethods"] && typeof result["AllowedMethods"] === "object" ? { ...result["AllowedMethods"] } : {
21793
+ Quantity: 2,
21794
+ Items: ["GET", "HEAD"]
21795
+ };
21796
+ allowedMethods["CachedMethods"] = result["CachedMethods"];
21797
+ result["AllowedMethods"] = allowedMethods;
21798
+ delete result["CachedMethods"];
21799
+ }
21521
21800
  return result;
21522
21801
  }
21523
21802
  /**
@@ -21529,6 +21808,10 @@ var CloudFrontDistributionProvider = class {
21529
21808
  if (result["CustomHeaders"] !== void 0) result["CustomHeaders"] = this.wrapWithQuantity(result["CustomHeaders"]);
21530
21809
  if (result["CustomOriginConfig"] && typeof result["CustomOriginConfig"] === "object") {
21531
21810
  const customOriginConfig = { ...result["CustomOriginConfig"] };
21811
+ if (customOriginConfig["OriginSSLProtocols"] !== void 0) {
21812
+ customOriginConfig["OriginSslProtocols"] = customOriginConfig["OriginSSLProtocols"];
21813
+ delete customOriginConfig["OriginSSLProtocols"];
21814
+ }
21532
21815
  if (customOriginConfig["OriginSslProtocols"] !== void 0) customOriginConfig["OriginSslProtocols"] = this.wrapWithQuantity(customOriginConfig["OriginSslProtocols"]);
21533
21816
  if (customOriginConfig["HTTPPort"] === null || customOriginConfig["HTTPPort"] === void 0) customOriginConfig["HTTPPort"] = 80;
21534
21817
  if (customOriginConfig["HTTPSPort"] === null || customOriginConfig["HTTPSPort"] === void 0) customOriginConfig["HTTPSPort"] = 443;
@@ -51382,11 +51665,11 @@ async function rollbackCommand(stackArg, options) {
51382
51665
  if (segment.failedOperations && segment.failedOperations.length > 0) if (options.revertFailed) {
51383
51666
  const failedPlan = planFailedOps(segment.failedOperations, planStateView);
51384
51667
  for (const item of failedPlan) logger.info(failedActionLabel(item, options.skipFinalSnapshot === true));
51385
- applyFailedPlanToPreview(failedPlan, planStateView);
51668
+ applyFailedPlanToPreview(failedPlan, planStateView, options.skipFinalSnapshot === true);
51386
51669
  } else for (const fop of segment.failedOperations) logger.info(` - (left as-is) ${fop.logicalId} (${fop.resourceType}) — its ${fop.changeType} FAILED mid-deploy; pass --revert-failed to attempt reverting it`);
51387
51670
  const plan = planRollback(segment.operations, planStateView, orphanLogicalIds);
51388
51671
  for (const item of plan) logger.info(actionLabel(item, options.skipFinalSnapshot === true));
51389
- applyPlanToPreview(plan, planStateView);
51672
+ applyPlanToPreview(plan, planStateView, options.skipFinalSnapshot === true);
51390
51673
  }
51391
51674
  logger.info("");
51392
51675
  if (!skipConfirmation) {
@@ -51520,16 +51803,30 @@ async function rollbackCommand(stackArg, options) {
51520
51803
  }
51521
51804
  }
51522
51805
  /**
51806
+ * Will the replay REFUSE this planned Snapshot delete instead of performing
51807
+ * it (issue #1368)? The preview must not unwind a record for an op that
51808
+ * never runs — the same question {@link snapshotNote} answers for the label,
51809
+ * asked with the same predicate and the same route, so the label and the
51810
+ * previewed state cannot disagree.
51811
+ */
51812
+ function planItemWillBeRefused(resourceType, effectiveProvisionedBy, skipFinalSnapshot) {
51813
+ if (skipFinalSnapshot) return false;
51814
+ return refusesFinalSnapshot(resourceType, effectiveProvisionedBy);
51815
+ }
51816
+ /**
51523
51817
  * Apply a planned segment's effect to the plan-preview state so the NEXT
51524
51818
  * (older) segment's plan is classified against already-unwound state.
51525
51819
  * Mirrors what `replayRollback` mutates, without touching AWS.
51526
51820
  */
51527
- function applyPlanToPreview(plan, previewState) {
51821
+ function applyPlanToPreview(plan, previewState, skipFinalSnapshot) {
51528
51822
  for (const item of plan) {
51529
51823
  const { op, action } = item;
51530
51824
  switch (action) {
51531
- case "delete":
51532
51825
  case "delete-with-final-snapshot":
51826
+ if (planItemWillBeRefused(op.resourceType, item.effectiveProvisionedBy, skipFinalSnapshot)) break;
51827
+ if (op.changeType === "CREATE") delete previewState[op.logicalId];
51828
+ break;
51829
+ case "delete":
51533
51830
  case "orphan-retain":
51534
51831
  case "orphan-flag":
51535
51832
  if (op.changeType === "CREATE") delete previewState[op.logicalId];
@@ -51547,12 +51844,15 @@ function applyPlanToPreview(plan, previewState) {
51547
51844
  * Apply a planned FAILED-op revert's effect to the plan-preview state
51548
51845
  * (issue #1198). Mirrors `replayFailedOperations` without touching AWS.
51549
51846
  */
51550
- function applyFailedPlanToPreview(plan, previewState) {
51847
+ function applyFailedPlanToPreview(plan, previewState, skipFinalSnapshot) {
51551
51848
  for (const item of plan) {
51552
51849
  const { op, action } = item;
51553
51850
  switch (action) {
51554
- case "delete-failed-create":
51555
51851
  case "delete-failed-create-with-final-snapshot":
51852
+ if (planItemWillBeRefused(op.resourceType, item.effectiveProvisionedBy, skipFinalSnapshot)) break;
51853
+ delete previewState[op.logicalId];
51854
+ break;
51855
+ case "delete-failed-create":
51556
51856
  case "orphan-failed-create-retain":
51557
51857
  delete previewState[op.logicalId];
51558
51858
  break;
@@ -63752,7 +64052,7 @@ function createMigrateCommand() {
63752
64052
  */
63753
64053
  function buildProgram() {
63754
64054
  const program = new Command();
63755
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.276.4");
64055
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.276.6");
63756
64056
  program.hook("preAction", (_thisCommand, actionCommand) => {
63757
64057
  const { profile } = actionCommand.optsWithGlobals();
63758
64058
  if (profile !== void 0) process.env["AWS_PROFILE"] = profile;