@go-to-k/cdkd 0.280.23 → 0.280.25

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 requireConfigString, $t as processStackMessages, A as red, At as runDockerStreaming, B as isTerminationProtectionPropagationError, Bt as resolveSkipPrefix, C as isStatefulRecreateTargetSync, Ct as parseBootstrapMarker, D as cyan, Dn as normalizeAwsError, Dt as formatDockerLoginError, E as bold, Et as buildDockerImage, F as ProviderRegistry, Ft as getDefaultStateBucketName, G as normalizeAwsTagsToCfn, Gt as warnDeprecatedNoPrefixCliFlag, H as cfnRefValueFromPhysicalId, Ht as resolveStateBucketWithDefaultAndSource, I as findActionableSilentDrops, It as getLegacyStateBucketName, J as configStringRefusal, Jt as MIGRATE_TMP_PREFIX, K as resolveExplicitPhysicalId, Kt as CFN_TEMPLATE_BODY_LIMIT, L as CloudControlProvider, Lt as resolveApp, M as IAMRoleProvider, Mt as getDockerImageBySourceHash, N as collectInlinePolicyNamesManagedBySiblings, Nt as Synthesizer, O as gray, On as withErrorHandling, Ot as getDockerCmd, P as clearOnUpdateRemoval, Pt as synthesisStatusMessage, Q as requireConfigObject, Qt as AssemblyReader, R as slowCcOperationTimeoutMs, Rt as resolveAutoAssetStorage, S as MULTI_REGION_RECREATE_BLOCKED_TYPES, Sn as StackTerminationProtectionError, St as getBootstrapMarkerKey, T as formatResourceLine, Tt as validateContainerRepoName, U as refStateLookupFromResource, Ut as resolveUseCdkBootstrapAssets, V as IntrinsicFunctionResolver, Vt as resolveStateBucketWithDefault, W as WAFv2WebACLProvider, Wt as stateBucketExistenceConfirmed, X as replayWarn, Xt as uploadCfnTemplate, Y as readConfigString, Yt as findLargeInlineResources, Z as requireConfigArray, Zt as expectedOwnerParam, _ as createPreDeleteFinalSnapshot, _n as PartialFailureError, _t as loadPublishableAssetManifest, a as DeploymentEventsStore, an as setAwsClients, at as isThrottlingError, b as unsupportedFinalSnapshotError, bn as ResourceUpdateNotSupportedError, bt as BOOTSTRAP_MARKER_PREFIX, c as replayFailedOperations, ct as LockManager, d as IMPLICIT_DELETE_DEPENDENCIES, dn as LocalInvokeBuildError$1, dt as shouldRetainResource, et as applyRoleArnIfSet, f as computeImplicitDeleteEdges, fn as LocalMigrateError, ft as AssetPublisher, g as ccRoutedFinalSnapshotError, gn as NestedStackChildDirectDestroyError, gt as createAssetRedirectResolver, h as buildFinalSnapshotIdentifier, hn as MissingCdkCliError, ht as buildAssetRedirectMap, i as DeploymentEventsReader, in as resetAwsClients, it as isRetryableTransientError, j as yellow, jt as AssetManifestLoader, k as green, kt as runDockerForeground, l as replayRollback, lt as S3StateBackend, m as PRE_DELETE_SNAPSHOT_TYPES, mt as WorkGraph, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as AwsClients, nt as describeTypeWithThrottleRetry, o as planFailedOps, ot as DagBuilder, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as LocalStartServiceError, pt as stringifyValue, q as assertRegionMatch, qt as CFN_TEMPLATE_URL_LIMIT, r as DeployEngine, rn as getAwsClients, rt as withRetry, s as planRollback, sn as CdkdError, st as TemplateParser, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as resolveBucketRegion, tt as DiffCalculator, u as withResourceDeadline, un as DeployCancelledError, ut as rebuildClientForBucketRegion, v as isFinalSnapshotError, vn as ProvisioningError, vt as rewriteTemplateAssetReferences, w as renderStatefulReason, wt as validateAssetBucketName, x as extractDeploymentEventError, xn as StackHasActiveImportsError, xt as ensureAssetStorage, y as refusesFinalSnapshot, yn as ResourceTimeoutError, yt as AssetModeResolver, z as disableInstanceApiTermination, zt as resolveCaptureObservedState } from "./deploy-engine-DmxpjXP8.js";
2
+ import { $ as requireConfigObject, $t as AssemblyReader, A as green, At as runDockerForeground, B as disableInstanceApiTermination, Bt as resolveCaptureObservedState, C as MULTI_REGION_RECREATE_BLOCKED_TYPES, Cn as StackTerminationProtectionError, Ct as getBootstrapMarkerKey, D as bold, Dt as buildDockerImage, E as formatResourceLine, Et as validateContainerRepoName, F as clearOnUpdateRemoval, Ft as synthesisStatusMessage, G as WAFv2WebACLProvider, Gt as stateBucketExistenceConfirmed, H as IntrinsicFunctionResolver, Ht as resolveStateBucketWithDefault, I as ProviderRegistry, It as getDefaultStateBucketName, J as assertRegionMatch, Jt as CFN_TEMPLATE_URL_LIMIT, K as normalizeAwsTagsToCfn, Kt as warnDeprecatedNoPrefixCliFlag, L as findActionableSilentDrops, Lt as getLegacyStateBucketName, M as yellow, Mt as AssetManifestLoader, N as IAMRoleProvider, Nt as getDockerImageBySourceHash, O as cyan, On as normalizeAwsError, Ot as formatDockerLoginError, P as collectInlinePolicyNamesManagedBySiblings, Pt as Synthesizer, Q as requireConfigArray, Qt as expectedOwnerParam, R as CloudControlProvider, Rt as resolveApp, S as extractDeploymentEventError, Sn as StackHasActiveImportsError, St as ensureAssetStorage, T as renderStatefulReason, Tt as validateAssetBucketName, U as cfnRefValueFromPhysicalId, Ut as resolveStateBucketWithDefaultAndSource, V as isTerminationProtectionPropagationError, Vt as resolveSkipPrefix, W as refStateLookupFromResource, Wt as resolveUseCdkBootstrapAssets, X as readConfigString, Xt as findLargeInlineResources, Y as configStringRefusal, Yt as MIGRATE_TMP_PREFIX, Z as replayWarn, Zt as uploadCfnTemplate, _ as createPreDeleteFinalSnapshot, _n as NestedStackChildDirectDestroyError, _t as createAssetRedirectResolver, a as DeploymentEventsStore, an as resetAwsClients, at as isRetryableTransientError, b as unsupportedFinalSnapshotError, bn as ResourceTimeoutError, bt as AssetModeResolver, c as replayFailedOperations, cn as CdkdError, ct as TemplateParser, d as IMPLICIT_DELETE_DEPENDENCIES, dn as DeployCancelledError, dt as rebuildClientForBucketRegion, en as processStackMessages, et as requireConfigString, f as computeImplicitDeleteEdges, fn as LocalInvokeBuildError$1, ft as shouldRetainResource, g as ccRoutedFinalSnapshotError, gn as MissingCdkCliError, gt as buildAssetRedirectMap, h as buildFinalSnapshotIdentifier, ht as WorkGraph, i as DeploymentEventsReader, in as getAwsClients, it as withRetry, j as red, jt as runDockerStreaming, k as gray, kn as withErrorHandling, kt as getDockerCmd, l as replayRollback, lt as LockManager, m as PRE_DELETE_SNAPSHOT_TYPES, mn as LocalStartServiceError, mt as stringifyValue, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as resolveBucketRegion, nt as DiffCalculator, o as planFailedOps, on as setAwsClients, ot as isThrottlingError, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as LocalMigrateError, pt as AssetPublisher, q as resolveExplicitPhysicalId, qt as CFN_TEMPLATE_BODY_LIMIT, r as DeployEngine, rn as AwsClients, rt as describeTypeWithThrottleRetry, s as planRollback, st as DagBuilder, t as DEFAULT_RESOURCE_TIMEOUT_MS, tt as applyRoleArnIfSet, u as withResourceDeadline, ut as S3StateBackend, v as isFinalSnapshotError, vn as PartialFailureError, vt as loadPublishableAssetManifest, w as isStatefulRecreateTargetSync, wt as parseBootstrapMarker, x as makeCanonicalizePropertiesFn, xn as ResourceUpdateNotSupportedError, xt as BOOTSTRAP_MARKER_PREFIX, y as refusesFinalSnapshot, yn as ProvisioningError, yt as rewriteTemplateAssetReferences, z as slowCcOperationTimeoutMs, zt as resolveAutoAssetStorage } from "./deploy-engine-DOjLU2Et.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-DsxUvLEc.js";
4
+ import { t as ASGProvider } from "./asg-provider-Do4MnkQh.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";
@@ -17949,6 +17949,47 @@ var EventBridgeBusProvider = class {
17949
17949
  //#endregion
17950
17950
  //#region src/provisioning/providers/ec2-provider.ts
17951
17951
  /**
17952
+ * The `AWS::EC2::Route` destination keys, in CloudFormation's own precedence
17953
+ * order — which is also the order `createRoute`'s
17954
+ * `DestinationCidrBlock || DestinationIpv6CidrBlock || DestinationPrefixListId`
17955
+ * chain resolves them.
17956
+ */
17957
+ const ROUTE_DESTINATION_KEYS = [
17958
+ "DestinationCidrBlock",
17959
+ "DestinationIpv6CidrBlock",
17960
+ "DestinationPrefixListId"
17961
+ ];
17962
+ /**
17963
+ * Split a Route property bag into the destination keys it DECLARES and the bag
17964
+ * carrying only the one that would actually be sent (issue #1591).
17965
+ *
17966
+ * ONE source for a decision two very different call sites have to agree on: the
17967
+ * provisioning path (`createRoute`, which narrows and warns) and the DIFF path
17968
+ * (the engine's canonicalizer, which must not report the losers as a change).
17969
+ * If those two disagreed the fix would be worse than the bug — state and
17970
+ * template would each be narrowed to a different key.
17971
+ *
17972
+ * The winner is simply `declared[0]`. That is not a shortcut: the list is built
17973
+ * in the same order and with the same truthiness predicate as the `||` chain,
17974
+ * so the first declared key IS what the chain resolves to. The predicate is
17975
+ * `Boolean`, not a hand-listed `undefined | null | ''` set, because the bag is
17976
+ * `unknown`-valued at runtime — an unquoted YAML `0` must be skipped by the
17977
+ * narrowing exactly as the chain skips it, or the two disagree on which key
17978
+ * was sent.
17979
+ *
17980
+ * `narrowed` is always a fresh object: the caller's bag is the engine's
17981
+ * `resolvedProps`, which it records for every resource that does NOT narrow.
17982
+ */
17983
+ function narrowRouteDestinations(properties) {
17984
+ const declared = ROUTE_DESTINATION_KEYS.filter((key) => Boolean(properties[key]));
17985
+ const narrowed = { ...properties };
17986
+ for (const losingKey of declared.slice(1)) delete narrowed[losingKey];
17987
+ return {
17988
+ declared,
17989
+ narrowed
17990
+ };
17991
+ }
17992
+ /**
17952
17993
  * AWS EC2 Networking Provider
17953
17994
  *
17954
17995
  * Implements resource provisioning for EC2 networking resources:
@@ -18796,15 +18837,15 @@ var EC2Provider = class {
18796
18837
  const destinationPrefixListId = properties["DestinationPrefixListId"];
18797
18838
  const destination = destinationCidrBlock || destinationIpv6CidrBlock || destinationPrefixListId;
18798
18839
  if (!routeTableId || !destination) throw new ProvisioningError(`RouteTableId and one of DestinationCidrBlock/DestinationIpv6CidrBlock/DestinationPrefixListId are required for Route ${logicalId}`, resourceType, logicalId);
18799
- const declaredDestinations = [
18800
- ["DestinationCidrBlock", destinationCidrBlock],
18801
- ["DestinationIpv6CidrBlock", destinationIpv6CidrBlock],
18802
- ["DestinationPrefixListId", destinationPrefixListId]
18803
- ].filter(([, value]) => Boolean(value)).map(([key]) => key);
18840
+ const { declared: declaredDestinations, narrowed: narrowedProperties } = narrowRouteDestinations(properties);
18841
+ let effectiveProperties;
18804
18842
  if (declaredDestinations.length > 1) {
18805
18843
  const message = `Route ${logicalId} declares more than one destination (${declaredDestinations.join(", ")}). CloudFormation and EC2 accept exactly one of DestinationCidrBlock/DestinationIpv6CidrBlock/DestinationPrefixListId; remove the extra keys from the template.`;
18806
- if (onMultipleDestinations) onMultipleDestinations(`${message} Continuing with ${destination === destinationCidrBlock ? "DestinationCidrBlock" : destination === destinationIpv6CidrBlock ? "DestinationIpv6CidrBlock" : "DestinationPrefixListId"} and ignoring the rest.`);
18807
- else throw new ProvisioningError(message, resourceType, logicalId);
18844
+ if (onMultipleDestinations) {
18845
+ const usedKey = declaredDestinations[0];
18846
+ effectiveProperties = narrowedProperties;
18847
+ onMultipleDestinations(`${message} Continuing with ${usedKey} and ignoring the rest.`);
18848
+ } else throw new ProvisioningError(message, resourceType, logicalId);
18808
18849
  }
18809
18850
  try {
18810
18851
  await this.ec2Client.send(new CreateRouteCommand({
@@ -18826,7 +18867,8 @@ var EC2Provider = class {
18826
18867
  this.logger.debug(`Successfully created Route ${logicalId}: ${physicalId}`);
18827
18868
  return {
18828
18869
  physicalId,
18829
- attributes: {}
18870
+ attributes: {},
18871
+ ...effectiveProperties && { effectiveProperties }
18830
18872
  };
18831
18873
  } catch (error) {
18832
18874
  const cause = error instanceof Error ? error : void 0;
@@ -18845,7 +18887,8 @@ var EC2Provider = class {
18845
18887
  return {
18846
18888
  physicalId: createResult.physicalId,
18847
18889
  wasReplaced: true,
18848
- ...createResult.attributes && { attributes: createResult.attributes }
18890
+ ...createResult.attributes && { attributes: createResult.attributes },
18891
+ ...createResult.effectiveProperties && { effectiveProperties: createResult.effectiveProperties }
18849
18892
  };
18850
18893
  } catch (error) {
18851
18894
  if (error instanceof CdkdError) throw error;
@@ -20249,6 +20292,26 @@ var EC2Provider = class {
20249
20292
  default: return [];
20250
20293
  }
20251
20294
  }
20295
+ /**
20296
+ * The diff-side half of the Route multi-destination narrowing (issue #1591).
20297
+ *
20298
+ * `createRoute` sends exactly one destination key and reports the narrowed
20299
+ * bag via `effectiveProperties`, so state carries one key. Without the same
20300
+ * narrowing here the template's extra keys read as an ADDED property on the
20301
+ * next deploy — and every destination key is create-only in the registry
20302
+ * schema, so the diff would classify a REPLACEMENT and the engine's
20303
+ * replacement create (which passes no context, and so gets no
20304
+ * `onMultipleDestinations` downgrade) would hit the #1566 refusal. A
20305
+ * previously-green no-op deploy would start failing.
20306
+ *
20307
+ * Shares `narrowRouteDestinations` with the provisioning path so the two
20308
+ * cannot disagree about which key survives.
20309
+ */
20310
+ canonicalizeDesiredProperties(resourceType, properties) {
20311
+ if (resourceType !== "AWS::EC2::Route") return properties;
20312
+ const { declared, narrowed } = narrowRouteDestinations(properties);
20313
+ return declared.length > 1 ? narrowed : properties;
20314
+ }
20252
20315
  async readVpcCurrentState(physicalId) {
20253
20316
  const vpc = (await this.ec2Client.send(new DescribeVpcsCommand({ VpcIds: [physicalId] }))).Vpcs?.[0];
20254
20317
  if (!vpc) return void 0;
@@ -35578,6 +35641,31 @@ var AppSyncProvider = class {
35578
35641
  throw new ProvisioningError(message, resourceType, options?.logicalId ?? "");
35579
35642
  }
35580
35643
  /**
35644
+ * CFn declares `DeltaSyncConfig.BaseTableTTL` / `.DeltaSyncTableTTL` as
35645
+ * STRINGS (CDK's L1 types them `string` too) while the SDK models both as
35646
+ * longs, so the value needs a real conversion rather than a cast — a string
35647
+ * handed to the number member is dropped by the serializer, which is the
35648
+ * silent-drop shape this batch closes.
35649
+ *
35650
+ * A non-numeric value is refused LOUDLY: `Number('abc')` is `NaN`, and NaN
35651
+ * would serialize to `null` and reach AWS as a confusing type error far from
35652
+ * the template line that caused it.
35653
+ *
35654
+ * `Number()` alone is NOT that refusal, which is the trap this guard exists
35655
+ * for: it coerces `''` / `' '` / `null` / `[]` / `false` to `0` and `true`
35656
+ * to `1`, all of which are finite. An unresolved intrinsic or an empty CFn
35657
+ * value would therefore have deployed a live data source with a ZERO-minute
35658
+ * delta-sync TTL — the "validate the FIELD, not just the container" class in
35659
+ * .claude/rules/providers.md. So the accepted shapes are enumerated instead:
35660
+ * a finite NUMBER, or a NON-BLANK string that parses to one.
35661
+ */
35662
+ toDeltaSyncTtl(value, path, logicalId, resourceType) {
35663
+ const numeric = typeof value === "number" ? value : typeof value === "string" ? value.trim() : void 0;
35664
+ const parsed = numeric === void 0 || numeric === "" ? NaN : Number(numeric);
35665
+ if (!Number.isFinite(parsed)) throw new ProvisioningError(`${resourceType} ${path} must be a number of minutes (CFn types it as a string), got ${JSON.stringify(value)} — cdkd refuses to drop it silently`, resourceType, logicalId);
35666
+ return parsed;
35667
+ }
35668
+ /**
35581
35669
  * NOTE: `awsRegion` / `defaultAction` are passed through VERBATIM, including
35582
35670
  * when the template omits them. cdkd deliberately does NOT substitute a
35583
35671
  * default: `DefaultAction` decides whether an unauthenticated request is
@@ -35922,15 +36010,40 @@ var AppSyncProvider = class {
35922
36010
  if (properties["Description"] !== void 0) input.description = properties["Description"];
35923
36011
  if (properties["ServiceRoleArn"] !== void 0) input.serviceRoleArn = properties["ServiceRoleArn"];
35924
36012
  const dynamo = this.asObject(properties["DynamoDBConfig"], "DynamoDBConfig", { logicalId }, resourceType);
35925
- if (dynamo) input.dynamodbConfig = {
35926
- tableName: dynamo["TableName"],
35927
- awsRegion: dynamo["AwsRegion"],
35928
- ...dynamo["UseCallerCredentials"] !== void 0 ? { useCallerCredentials: dynamo["UseCallerCredentials"] } : {}
35929
- };
36013
+ if (dynamo) {
36014
+ const ddbConfig = {
36015
+ tableName: dynamo["TableName"],
36016
+ awsRegion: dynamo["AwsRegion"],
36017
+ ...dynamo["UseCallerCredentials"] !== void 0 ? { useCallerCredentials: dynamo["UseCallerCredentials"] } : {},
36018
+ ...dynamo["Versioned"] !== void 0 ? { versioned: dynamo["Versioned"] } : {}
36019
+ };
36020
+ const delta = this.asObject(dynamo["DeltaSyncConfig"], "DynamoDBConfig.DeltaSyncConfig", { logicalId }, resourceType);
36021
+ if (delta) {
36022
+ const deltaConfig = {};
36023
+ if (delta["BaseTableTTL"] !== void 0) deltaConfig.baseTableTTL = this.toDeltaSyncTtl(delta["BaseTableTTL"], "DynamoDBConfig.DeltaSyncConfig.BaseTableTTL", logicalId, resourceType);
36024
+ if (delta["DeltaSyncTableName"] !== void 0) deltaConfig.deltaSyncTableName = delta["DeltaSyncTableName"];
36025
+ if (delta["DeltaSyncTableTTL"] !== void 0) deltaConfig.deltaSyncTableTTL = this.toDeltaSyncTtl(delta["DeltaSyncTableTTL"], "DynamoDBConfig.DeltaSyncConfig.DeltaSyncTableTTL", logicalId, resourceType);
36026
+ ddbConfig.deltaSyncConfig = deltaConfig;
36027
+ }
36028
+ input.dynamodbConfig = ddbConfig;
36029
+ }
35930
36030
  const lambda = this.asObject(properties["LambdaConfig"], "LambdaConfig", { logicalId }, resourceType);
35931
36031
  if (lambda) input.lambdaConfig = { lambdaFunctionArn: lambda["LambdaFunctionArn"] };
35932
36032
  const http = this.asObject(properties["HttpConfig"], "HttpConfig", { logicalId }, resourceType);
35933
- if (http) input.httpConfig = { endpoint: http["Endpoint"] };
36033
+ if (http) {
36034
+ const httpConfig = { endpoint: http["Endpoint"] };
36035
+ const auth = this.asObject(http["AuthorizationConfig"], "HttpConfig.AuthorizationConfig", { logicalId }, resourceType);
36036
+ if (auth) {
36037
+ const authConfig = { authorizationType: auth["AuthorizationType"] };
36038
+ const iam = this.asObject(auth["AwsIamConfig"], "HttpConfig.AuthorizationConfig.AwsIamConfig", { logicalId }, resourceType);
36039
+ if (iam) authConfig.awsIamConfig = {
36040
+ ...iam["SigningRegion"] !== void 0 ? { signingRegion: iam["SigningRegion"] } : {},
36041
+ ...iam["SigningServiceName"] !== void 0 ? { signingServiceName: iam["SigningServiceName"] } : {}
36042
+ };
36043
+ httpConfig.authorizationConfig = authConfig;
36044
+ }
36045
+ input.httpConfig = httpConfig;
36046
+ }
35934
36047
  const es = this.asObject(properties["ElasticsearchConfig"], "ElasticsearchConfig", { logicalId }, resourceType);
35935
36048
  if (es) input.elasticsearchConfig = {
35936
36049
  endpoint: es["Endpoint"],
@@ -36407,10 +36520,36 @@ var AppSyncProvider = class {
36407
36520
  if (ds.dynamodbConfig.tableName !== void 0) dynamo["TableName"] = ds.dynamodbConfig.tableName;
36408
36521
  if (ds.dynamodbConfig.awsRegion !== void 0) dynamo["AwsRegion"] = ds.dynamodbConfig.awsRegion;
36409
36522
  if (ds.dynamodbConfig.useCallerCredentials !== void 0) dynamo["UseCallerCredentials"] = ds.dynamodbConfig.useCallerCredentials;
36523
+ if (ds.dynamodbConfig.versioned !== void 0) dynamo["Versioned"] = ds.dynamodbConfig.versioned;
36524
+ const delta = ds.dynamodbConfig.deltaSyncConfig;
36525
+ if (delta) {
36526
+ const deltaOut = {};
36527
+ if (delta.baseTableTTL !== void 0) deltaOut["BaseTableTTL"] = String(delta.baseTableTTL);
36528
+ if (delta.deltaSyncTableName !== void 0) deltaOut["DeltaSyncTableName"] = delta.deltaSyncTableName;
36529
+ if (delta.deltaSyncTableTTL !== void 0) deltaOut["DeltaSyncTableTTL"] = String(delta.deltaSyncTableTTL);
36530
+ if (Object.keys(deltaOut).length > 0) dynamo["DeltaSyncConfig"] = deltaOut;
36531
+ }
36410
36532
  if (Object.keys(dynamo).length > 0) result["DynamoDBConfig"] = dynamo;
36411
36533
  }
36412
36534
  if (ds.lambdaConfig?.lambdaFunctionArn !== void 0) result["LambdaConfig"] = { LambdaFunctionArn: ds.lambdaConfig.lambdaFunctionArn };
36413
- if (ds.httpConfig?.endpoint !== void 0) result["HttpConfig"] = { Endpoint: ds.httpConfig.endpoint };
36535
+ if (ds.httpConfig) {
36536
+ const httpOut = {};
36537
+ if (ds.httpConfig.endpoint !== void 0) httpOut["Endpoint"] = ds.httpConfig.endpoint;
36538
+ const authRead = ds.httpConfig.authorizationConfig;
36539
+ if (authRead) {
36540
+ const authOut = {};
36541
+ if (authRead.authorizationType !== void 0) authOut["AuthorizationType"] = authRead.authorizationType;
36542
+ const iamRead = authRead.awsIamConfig;
36543
+ if (iamRead) {
36544
+ const iamOut = {};
36545
+ if (iamRead.signingRegion !== void 0) iamOut["SigningRegion"] = iamRead.signingRegion;
36546
+ if (iamRead.signingServiceName !== void 0) iamOut["SigningServiceName"] = iamRead.signingServiceName;
36547
+ if (Object.keys(iamOut).length > 0) authOut["AwsIamConfig"] = iamOut;
36548
+ }
36549
+ if (Object.keys(authOut).length > 0) httpOut["AuthorizationConfig"] = authOut;
36550
+ }
36551
+ if (Object.keys(httpOut).length > 0) result["HttpConfig"] = httpOut;
36552
+ }
36414
36553
  if (ds.elasticsearchConfig) {
36415
36554
  const es = {};
36416
36555
  if (ds.elasticsearchConfig.endpoint !== void 0) es["Endpoint"] = ds.elasticsearchConfig.endpoint;
@@ -51274,7 +51413,7 @@ async function loadStateOrEmpty(stackName, region, stateBackend) {
51274
51413
  * Pure with respect to AWS state mutation — only reads state (the resolver
51275
51414
  * may read producer state for `Fn::ImportValue` / `Fn::GetStackOutput`).
51276
51415
  */
51277
- async function computeStackDiff(currentState, template, region, stackName, stateBackend, diffCalculator, parameters) {
51416
+ async function computeStackDiff(currentState, template, region, stackName, stateBackend, diffCalculator, parameters, canonicalizeProperties) {
51278
51417
  const intrinsicResolver = new IntrinsicFunctionResolver(region);
51279
51418
  let mergedParameters = parameters;
51280
51419
  let parametersBound = false;
@@ -51314,7 +51453,7 @@ async function computeStackDiff(currentState, template, region, stackName, state
51314
51453
  ...mergedParameters && { parameters: mergedParameters },
51315
51454
  ...conditions && { conditions }
51316
51455
  });
51317
- return diffCalculator.calculateDiff(currentState, effectiveTemplate, resolveFn);
51456
+ return diffCalculator.calculateDiff(currentState, effectiveTemplate, resolveFn, canonicalizeProperties);
51318
51457
  }
51319
51458
  /**
51320
51459
  * Resolve a nested-stack child's input `Parameters` (declared on the parent's
@@ -51375,13 +51514,13 @@ async function resolveChildStackParameters(parentStackRow, parentTemplate, paren
51375
51514
  * fail at deploy time.
51376
51515
  */
51377
51516
  async function buildDiffTree(args) {
51378
- const { stackName, displayName, region, template, nestedTemplates, recursive, stateBackend, diffCalculator, parameters, assetRedirect } = args;
51517
+ const { stackName, displayName, region, template, nestedTemplates, recursive, stateBackend, diffCalculator, parameters, canonicalizeProperties, assetRedirect } = args;
51379
51518
  const state = await loadStateOrEmpty(stackName, region, stateBackend);
51380
51519
  const node = {
51381
51520
  stackName,
51382
51521
  displayName,
51383
51522
  region,
51384
- changes: await computeStackDiff(state, template, region, stackName, stateBackend, diffCalculator, parameters),
51523
+ changes: await computeStackDiff(state, template, region, stackName, stateBackend, diffCalculator, parameters, canonicalizeProperties),
51385
51524
  ccApiRoutes: collectCcApiRoutes(template, state),
51386
51525
  children: []
51387
51526
  };
@@ -51407,6 +51546,7 @@ async function buildDiffTree(args) {
51407
51546
  stateBackend,
51408
51547
  diffCalculator,
51409
51548
  parameters: childParameters,
51549
+ ...canonicalizeProperties && { canonicalizeProperties },
51410
51550
  ...assetRedirect && { assetRedirect }
51411
51551
  }));
51412
51552
  }
@@ -51764,6 +51904,9 @@ async function diffCommand(stacks, options) {
51764
51904
  ...options.profile && { profile: options.profile }
51765
51905
  });
51766
51906
  const diffCalculator = new DiffCalculator();
51907
+ const diffProviderRegistry = new ProviderRegistry();
51908
+ registerAllProviders(diffProviderRegistry);
51909
+ const canonicalizeProperties = makeCanonicalizePropertiesFn(diffProviderRegistry);
51767
51910
  const recursive = options.recursive ?? false;
51768
51911
  const resolveAssetRedirect = createAssetRedirectResolver({
51769
51912
  stateBackend,
@@ -51790,6 +51933,7 @@ async function diffCommand(stacks, options) {
51790
51933
  recursive,
51791
51934
  stateBackend,
51792
51935
  diffCalculator,
51936
+ canonicalizeProperties,
51793
51937
  ...assetRedirect && { assetRedirect }
51794
51938
  }));
51795
51939
  }
@@ -70273,7 +70417,7 @@ function createMigrateCommand() {
70273
70417
  */
70274
70418
  function buildProgram() {
70275
70419
  const program = new Command();
70276
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.280.23");
70420
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.280.25");
70277
70421
  program.hook("preAction", (_thisCommand, actionCommand) => {
70278
70422
  const { profile } = actionCommand.optsWithGlobals();
70279
70423
  if (profile !== void 0) process.env["AWS_PROFILE"] = profile;