@go-to-k/cdkd 0.311.0 → 0.313.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/README.md +2 -2
  2. package/dist/{asg-provider-CIg_guZ-.js → asg-provider-CqPtIngx.js} +3 -3
  3. package/dist/{asg-provider-CIg_guZ-.js.map → asg-provider-CqPtIngx.js.map} +1 -1
  4. package/dist/cli.js +2 -2
  5. package/dist/{created-resource-sink-DlzoIY-1.js → created-resource-sink-BT2Dfnpt.js} +2 -2
  6. package/dist/{created-resource-sink-DlzoIY-1.js.map → created-resource-sink-BT2Dfnpt.js.map} +1 -1
  7. package/dist/{db-instance-modify-retry-1y0kIPCO.js → db-instance-modify-retry-D7wXWxVo.js} +2 -2
  8. package/dist/{db-instance-modify-retry-1y0kIPCO.js.map → db-instance-modify-retry-D7wXWxVo.js.map} +1 -1
  9. package/dist/{deploy-engine-BF5exXUb.js → deploy-engine-CwpnkMCZ.js} +419 -100
  10. package/dist/deploy-engine-CwpnkMCZ.js.map +1 -0
  11. package/dist/{iam-role-provider-qvhlVnrn.js → iam-role-provider-ARR3C50J.js} +3 -3
  12. package/dist/{iam-role-provider-qvhlVnrn.js.map → iam-role-provider-ARR3C50J.js.map} +1 -1
  13. package/dist/index.js +3 -3
  14. package/dist/{neptune-provider-D9ac71Ca.js → neptune-provider-DfPOAG0q.js} +53 -6
  15. package/dist/neptune-provider-DfPOAG0q.js.map +1 -0
  16. package/dist/{program-DbnTHlwR.js → program-CMP_YVVn.js} +16 -10
  17. package/dist/program-CMP_YVVn.js.map +1 -0
  18. package/dist/{provider-classes-DktsDsTf.js → provider-classes-DefoNqY7.js} +1128 -107
  19. package/dist/provider-classes-DefoNqY7.js.map +1 -0
  20. package/dist/{rds-provider-0LUsn9Wl.js → rds-provider-Dn-7U1CR.js} +160 -16
  21. package/dist/rds-provider-Dn-7U1CR.js.map +1 -0
  22. package/dist/{version-BA4rBBLp.js → version-CsWxTnUg.js} +2 -2
  23. package/dist/{version-BA4rBBLp.js.map → version-CsWxTnUg.js.map} +1 -1
  24. package/package.json +2 -2
  25. package/dist/deploy-engine-BF5exXUb.js.map +0 -1
  26. package/dist/neptune-provider-D9ac71Ca.js.map +0 -1
  27. package/dist/program-DbnTHlwR.js.map +0 -1
  28. package/dist/provider-classes-DktsDsTf.js.map +0 -1
  29. package/dist/rds-provider-0LUsn9Wl.js.map +0 -1
@@ -1,14 +1,14 @@
1
1
  import { r as getAwsClients, s as withApiGatewayPacing } from "./aws-clients-Bu9EMILF.js";
2
2
  import { B as SECRET_REF_MAX_CODE_POINTS, C as generateResourceName, D as getCurrentStackInstanceId, J as displayStackName, K as displayIdent, M as recordedGeneratedNameKept, Q as safeMsg, T as generatedNameFor, Y as isPasteableIdent, Z as plainIdentOr, a as safeStringify, i as isAwsAuthoredFailure, k as isBeforeStateRead, n as describeAwsFailure, q as displaySafe, r as describeAwsStatusReason, s as getLogger, t as VERBOSE_POINTER, w as generateResourceNameWithFallback } from "./aws-failure-text-NSBdKPYK.js";
3
- import { $ as observeThenDisableProtection, A as RESOURCE_NOT_FOUND, An as ProvisioningError, Ar as wrapMaskedAwsError, At as isSecretDerivedValue, B as refusalTypeShown, Bt as isAuxiliaryFailure, C as ambiguousAttemptLead, Cr as isTransientServerError, Ct as logicalIdShown, D as replayedSendWindow, Dr as isThrottlingError, Dt as stateOrphanRecordRemedy, E as replayFollowedAmbiguousAttempt, Er as isMarkedNonRetryable, Et as segmentAfterAnchor, F as isPlainImportJson, H as resolveExplicitPhysicalId, Ht as markAuxiliaryFailure, I as isPlainImportValue, It as clearCreatedBeforeFailure, Jn as isInertUnquoted, K as deleteAfterProtectionFlipWithFinalSnapshot, Kn as commandHole, L as isQuotableImportValue, M as markNotGone, Mn as ResourceUpdateNotSupportedError, Mt as maskerOrIdentity, N as assertRegionMatch, Nt as withDerivedNameMasks, O as setBounded, Or as markNonRetryable, Ot as createMaskedLogSinks, P as VALUE_NOT_SHOWN, Q as logGroupProtectionSite, R as normalizeAwsTagsToCfn, S as RecentIdSet, Sr as isRetryableTransientError, St as compositeIdSkipResult, T as isInsideWindow, Tr as THROTTLING_ERROR_NAMES, Ut as markCreatedBeforeFailure, V as remedyLogicalId, W as ProtectionFlipRegistry, Wt as markSupersedesEarlierCreate, X as isTerminalDbWaitStatus, Yn as pasteableCommand, Z as isTerminalDeleteFailure, Zn as plainOrDescribed, _t as isInterruptedWaitError, a as retractCreatedResource, b as AMBIGUOUS_LATCH_TTL_MS, br as isExplicitDenyError, bt as compositeIdFormatMessage, c as SECRET_DERIVED_READ_LIVE, cn as withPasteableAwsProfile, ct as isAwsCliLiteral, d as readPrincipalLists, dn as clientDefaultsFor, dr as markReplayMayCollide, dt as renderDisableCommand, er as shellQuote, et as protectionFlipKey, fn as credentialFingerprint, fr as relayedNameCollision, ft as ElapsedBudgetRegistry, gr as explicitDenyPolicyKind, h as clearOnUpdateRemoval, hn as CdkdError, i as reportCreatedResource, in as injectiveKeyPrefix, it as userPoolProtectionSite, jt as maskDeep, k as withoutServerErrorRetries, kr as markRedactedCause, kt as createMaskedRetryLogger, l as holdsSecretDerivedEntry, ln as ambientClientDefaults, lt as pasteableAwsCommand, ot as UNNAMEABLE_ID_CLAUSE, p as recordedPrincipalsRepair, pn as AccountIdUnavailableError, q as deleteWithProtectionCompensation, qn as hasClauseBreak, rn as injectiveKey, st as WITHHELD_AWS_COMMAND, tr as withheldTargetClause, tt as rdsFamilyProtectionSite, u as onlySecretDerived, un as ambientCredentialConfig, ur as markNameCollision, ut as protectedReplacementAdvice, v as withRemovalDefaults, vt as startInterruptWatch, w as createAttemptKey, wt as packCompositeId, x as AmbiguousCreateLatch, xt as compositeIdSeparatorRefusal, yr as isAmbiguousOutcomeError, yt as canonicalizeRoute53QueryName, z as quotedRemedyLogicalId } from "./created-resource-sink-DlzoIY-1.js";
3
+ import { $ as logGroupProtectionSite, $n as plainOrDescribed, A as withoutServerErrorRetries, Ar as markNonRetryable, At as createMaskedLogSinks, B as quotedRemedyLogicalId, C as RecentIdSet, Ct as compositeIdSeparatorRefusal, D as replayFollowedAmbiguousAttempt, Dr as THROTTLING_ERROR_NAMES, E as isInsideWindow, Et as packCompositeId, F as VALUE_NOT_SHOWN, Ft as withDerivedNameMasks, G as ProtectionFlipRegistry, Gt as markCreatedBeforeFailure, H as remedyLogicalId, Ht as isAuxiliaryFailure, I as isPlainImportJson, J as deleteWithProtectionCompensation, Jn as commandHole, Kt as markSupersedesEarlierCreate, L as isPlainImportValue, Mn as ProvisioningError, Mr as wrapMaskedAwsError, Mt as isSecretDerivedValue, N as markNotGone, Nt as maskDeep, O as replayedSendWindow, Or as isMarkedNonRetryable, Ot as segmentAfterAnchor, P as assertRegionMatch, Pn as ResourceUpdateNotSupportedError, Pt as maskerOrIdentity, Q as isTerminalDeleteFailure, R as isQuotableImportValue, Rt as clearCreatedBeforeFailure, S as AmbiguousCreateLatch, Sr as isExplicitDenyError, St as compositeIdFormatMessage, T as createAttemptKey, Tr as isTransientServerError, Tt as logicalIdShown, U as resolveExplicitPhysicalId, V as refusalTypeShown, Wt as markAuxiliaryFailure, Xn as isInertUnquoted, Yn as hasClauseBreak, Z as isTerminalDbWaitStatus, Zn as pasteableCommand, _n as CdkdError, a as retractCreatedResource, an as injectiveKey, at as userPoolProtectionSite, bt as startInterruptWatch, c as SECRET_DERIVED_READ_LIVE, ct as WITHHELD_AWS_COMMAND, d as readPrincipalLists, dn as ambientClientDefaults, dt as protectedReplacementAdvice, et as observeThenDisableProtection, fn as ambientCredentialConfig, fr as markNameCollision, ft as renderDisableCommand, h as clearOnUpdateRemoval, hn as AccountIdUnavailableError, i as reportCreatedResource, j as RESOURCE_NOT_FOUND, jr as markRedactedCause, jt as createMaskedRetryLogger, k as setBounded, kr as isThrottlingError, kt as stateOrphanRecordRemedy, l as holdsSecretDerivedEntry, lt as isAwsCliLiteral, mn as credentialFingerprint, mr as relayedNameCollision, mt as ElapsedBudgetRegistry, nr as shellQuote, nt as rdsFamilyProtectionSite, on as injectiveKeyPrefix, p as recordedPrincipalsRepair, pn as clientDefaultsFor, pr as markReplayMayCollide, pt as ElapsedBudget, q as deleteAfterProtectionFlipWithFinalSnapshot, rr as withheldTargetClause, st as UNNAMEABLE_ID_CLAUSE, tt as protectionFlipKey, u as onlySecretDerived, un as withPasteableAwsProfile, ut as pasteableAwsCommand, v as removedTemplateKeys, vr as explicitDenyPolicyKind, w as ambiguousAttemptLead, wr as isRetryableTransientError, wt as compositeIdSkipResult, x as AMBIGUOUS_LATCH_TTL_MS, xr as isAmbiguousOutcomeError, xt as canonicalizeRoute53QueryName, y as withRemovalDefaults, yt as isInterruptedWaitError, z as normalizeAwsTagsToCfn } from "./created-resource-sink-BT2Dfnpt.js";
4
4
  import { c as ambientRegion } from "./aws-client-defaults-BX9Y_fKp.js";
5
- import { $s as coerceCfnBoolean, $t as isAccessDeniedError, A as DYNAMODB_DELETE_POLL_COST_MS, B as relayedIndexBusyDelete, Bc as snapshotPassProvenance, Bi as tagPlanWarning, Bn as redactedDeleteAddressSkip, C as planContributorInsightsOp, Ca as isUsableAttemptedName, Cs as refuseMalformedResourcesForDestroy, D as reverseMapTableContributorInsights, Dd as renderAssemblyPathEscape, E as reverseMapIndexContributorInsights, Ed as displayAssemblyPath, Ei as reserveStackCreateToken, F as resolveDynamoDbDeleteBudgetMs, Fa as s3BucketRegionalDomainName, Fi as DBPROXY_TAG_OPTIONS, Fn as getCurrentProducerRegions, Fr as replacedDeleteFailureVerdict, Fs as withheldAccountClause, G as readTtlSpec, H as isTtlAlreadyDisabled, Hi as stringifyIfAssigned, Ht as withNestedStackContext, I as DELETE_INDEX_WAIT_PROCEED_NOTE, Ia as s3BucketWebsiteUrl, Ii as planTagDiff, J as S3_AUTO_DELETE_OBJECTS_TAG, Ji as waitForLambdaFunctionActive, Js as WARM_THROUGHPUT_MEMBERS, K as sendTtlWaitingOutRateLimit, L as INDEX_SETTLE_POLL_INTERVAL_MS, Lc as markSameGenerationBag, Li as readTagList, Ln as REDACTED_DELETE_ADDRESS_SKIP_REASON, Ls as findSilentDropProperties, Lt as revertNestedChildFromJournal, M as compensateRemovedDeletionProtection, Ma as s3BucketArn, Mi as isRefusedByName, N as deleteBudgetKey, Na as s3BucketDomainName, Ni as markDeleteStarted, Nr as getStackRecords, O as stripIndexContributorInsights, Od as resolveAssemblyPath, Oi as acquireIdempotencyToken, Oo as accountArgs, P as resolveDynamoDbDeleteBudgetClock, Pa as s3BucketDualStackDomainName, Pi as DBPROXY_TAGS_WHAT, Pt as getNestedRevertRun, Q as markRefusedBeforeApplying, Qi as getCurrentResourceSecrets, Qs as toFiniteNumber, Qt as chunks, R as deleteTableWithIndexBusyRetry, Rc as redactForState, Ri as refuseMalformedDesiredTags, Rn as isRedactedRecordedValue, S as indexDeclaresContributorInsights, T as readContributorInsightsSpec, Td as describeFileReadFailure, U as isTtlRateLimited, Uc as hasMaskableValues, V as waitForIndexesSettled, Va as outputReferenceProvenanceOf, Vi as definedAttributes, Vt as getCurrentNestedStackContext, W as planTimeToLive, X as isTruthyCfnBoolean, Xs as isWarmThroughputDecrease, Y as hasCdkAutoDeleteTag, Ys as coerceWarmThroughput$1, Z as getPriorAttempts, Zs as toCfnInteger, _ as streamMemberRefusals, _a as isTerminationProtectionPropagationError, _c as canonicalLambdaFunctionName, _l as carriesSecretMask, _t as enclosingDeadlineRemainingMs, aa as onlySecretReferencesDiffer, ac as replayWarn, al as dynamicReferenceTokens, b as CONTRIBUTOR_INSIGHTS_KEY, ba as reEnableInstanceApiTermination, c as DynamoDBGlobalTableProvider, cc as requireConfigString, cd as decodeListingKey, ct as isAbsoluteAssetPath, d as declaredStreamPolicyMember, da as deleteSkipReason, dd as canonicalizeRegion, di as secretNamedAttributeNamesOf, ec as coerceCfnInteger, en as lookupEachName, f as declaredStreamTagsMember, fa as withIndeterminateGuard, fc as withRetry, fd as derivePartitionAndUrlSuffix, fl as recoverMaskedOutput, g as streamDeclaresTags, ga as ec2InstanceProtectionSite, gc as emrClusterInstancesReplaced, gt as enclosingDeadlineExpired, h as streamDeclaresPolicy, hc as ecsServiceLaunchTypeSetOrChanged, ia as slowCcOperationTimeoutMs, ic as readConfigString, iu as stringifyValue, j as beginDeleteWait, ja as isSettledInstanceState, jc as passedNoEchoParametersOf, jr as awaitInFlightSibling, k as DYNAMODB_DELETE_MIN_RESOURCE_TIMEOUT_MS, l as STREAM_POLICY_KEY, lt as listNestedTemplateRows, lu as rewriteTemplateAssetReferences, m as reverseMapStreamPolicy, ma as markWaitAbandoned, ml as recordAttributeIdCopy, nc as configIntegerRefusal, oa as unchangedBehindSecretReference, oc as requireConfigArray, p as planStreamMemberOps, pa as isWaitAbandonedError, pc as blockDeviceMappingsDifferOnlyInDeleteOnTermination, pl as physicalNameCopiesOf, q as ECR_AUTO_DELETE_IMAGES_TAG, rc as configStringRefusal, rl as withoutPhysicalNameCopies, rs as refuseMalformedNestedChildOutputs, sc as requireConfigObject, so as getAccountInfo, st as findNestedTemplateTreeDefect, t as DeployEngine, tc as configBooleanRefusal, tn as withApiLimit, tu as timePhase, u as STREAM_TAGS_KEY, ut as renderNestedTemplateTreeDefect, v as streamPolicyMatchesDeclared, va as observeThenDisableInstanceApiTermination, vc as lambdaFunctionNameForMask, vo as parseWebACLArn, w as planIndexContributorInsightsOps, wi as earliestDefined, x as contributorInsightsRefusals, xo as passedParameterClassesOf, y as streamTagsMatchDeclared, ya as reDisableInstanceApiTermination, yc as sameLambdaFunctionAddress, z as maskedLogger, zc as recordReferenceProvenanceEntry, zi as tagMapAsList, zn as redactedDeleteAddressFields, zs as withoutSilentDropProperties } from "./deploy-engine-BF5exXUb.js";
6
- import { n as collectInlinePolicyNamesManagedBySiblings, r as IamCreateClientCache, t as IAMRoleProvider } from "./iam-role-provider-qvhlVnrn.js";
7
- import { a as resolveSecretDerivedPrincipals, i as isResolvableSecretPrincipalList, n as runDestroyForStack, o as canonicalizeIpProtocolValue, r as holdsUnprovenSecretPrincipalToken, s as resolvedResourceTimeoutMs, t as canonicalizeIpv4Cidr } from "./program-DbnTHlwR.js";
8
- import { t as modifyDbInstanceWhenAvailable } from "./db-instance-modify-retry-1y0kIPCO.js";
9
- import { RDSProvider } from "./rds-provider-0LUsn9Wl.js";
10
- import { NeptuneProvider } from "./neptune-provider-D9ac71Ca.js";
11
- import { ASGProvider } from "./asg-provider-CIg_guZ-.js";
5
+ import { $ as getPriorAttempts, $s as isWarmThroughputDecrease, A as DYNAMODB_DELETE_MIN_RESOURCE_TIMEOUT_MS, Ad as renderAssemblyPathEscape, Ai as acquireIdempotencyToken, Ao as accountArgs, B as deleteTableWithIndexBusyRetry, Bc as markSameGenerationBag, Bi as refuseMalformedDesiredTags, Bn as isRedactedRecordedValue, Bs as findSilentDropProperties, C as planContributorInsightsOp, Co as passedParameterClassesOf, D as reverseMapTableContributorInsights, E as reverseMapIndexContributorInsights, Ei as earliestDefined, F as resolveDynamoDbDeleteBudgetClock, Fa as s3BucketDomainName, Fi as markDeleteStarted, Fr as getStackRecords, G as isTtlRateLimited, H as relayedIndexBusyDelete, Hc as recordReferenceProvenanceEntry, Hi as tagPlanWarning, Hn as redactedDeleteAddressSkip, Hs as withoutSilentDropProperties, I as resolveDynamoDbDeleteBudgetMs, Ia as s3BucketDualStackDomainName, Ii as DBPROXY_TAGS_WHAT, It as getNestedRevertRun, J as sendTtlWaitingOutRateLimit, K as planTimeToLive, Kc as hasMaskableValues, L as DELETE_INDEX_WAIT_PROCEED_NOTE, La as s3BucketRegionalDomainName, Li as DBPROXY_TAG_OPTIONS, Ln as getCurrentProducerRegions, Lr as replacedDeleteFailureVerdict, Ls as withheldAccountClause, M as beginDeleteWait, N as compensateRemovedDeletionProtection, Na as isSettledInstanceState, Nr as awaitInFlightSibling, O as stripIndexContributorInsights, Od as describeFileReadFailure, Oi as reserveStackCreateToken, P as deleteBudgetKey, Pa as s3BucketArn, Pc as passedNoEchoParametersOf, Pi as isRefusedByName, Q as isTruthyCfnBoolean, Qs as coerceWarmThroughput$1, R as INDEX_SETTLE_POLL_INTERVAL_MS, Ra as s3BucketWebsiteUrl, Ri as planTagDiff, S as indexDeclaresContributorInsights, Sa as reEnableInstanceApiTermination, Sc as sameLambdaFunctionAddress, T as readContributorInsightsSpec, Ta as isUsableAttemptedName, Ts as refuseMalformedResourcesForDestroy, U as waitForIndexesSettled, Ua as outputReferenceProvenanceOf, Uc as snapshotPassProvenance, Ui as definedAttributes, Ut as getCurrentNestedStackContext, V as maskedLogger, Vc as redactForState, Vi as tagMapAsList, Vn as redactedDeleteAddressFields, W as isTtlAlreadyDisabled, Wi as stringifyIfAssigned, Wt as withNestedStackContext, X as S3_AUTO_DELETE_OBJECTS_TAG, Xi as waitForLambdaFunctionActive, Y as ECR_AUTO_DELETE_IMAGES_TAG, Z as hasCdkAutoDeleteTag, Zs as WARM_THROUGHPUT_MEMBERS, _ as streamMemberRefusals, _l as recordAttributeIdCopy, ac as configIntegerRefusal, as as refuseMalformedNestedChildOutputs, b as CONTRIBUTOR_INSIGHTS_KEY, ba as observeThenDisableInstanceApiTermination, bc as canonicalLambdaFunctionName, bl as carriesSecretMask, bo as parseWebACLArn, c as DynamoDBGlobalTableProvider, ca as unchangedBehindSecretReference, cc as replayWarn, cl as dynamicReferenceTokens, d as declaredStreamPolicyMember, dc as requireConfigString, dd as decodeListingKey, dt as listNestedTemplateRows, ea as getCurrentResourceSecrets, ec as toCfnInteger, en as chunks, et as markRefusedBeforeApplying, f as declaredStreamTagsMember, ft as renderNestedTemplateTreeDefect, fu as rewriteTemplateAssetReferences, g as streamDeclaresTags, ga as markWaitAbandoned, gc as blockDeviceMappingsDifferOnlyInDeleteOnTermination, gl as physicalNameCopiesOf, h as streamDeclaresPolicy, ha as isWaitAbandonedError, hc as withRetry, hd as derivePartitionAndUrlSuffix, hl as recoverMaskedOutput, ic as configBooleanRefusal, iu as timePhase, j as DYNAMODB_DELETE_POLL_COST_MS, jd as resolveAssemblyPath, k as DYNAMODB_DELETE_DEADLINE_MARGIN_MS, kd as displayAssemblyPath, l as STREAM_POLICY_KEY, lc as requireConfigArray, lo as getAccountInfo, lt as findNestedTemplateTreeDefect, m as reverseMapStreamPolicy, ma as withIndeterminateGuard, md as canonicalizeRegion, nc as coerceCfnBoolean, nn as lookupEachName, oa as slowCcOperationTimeoutMs, oc as configStringRefusal, ol as withoutPhysicalNameCopies, p as planStreamMemberOps, pa as deleteSkipReason, pi as secretNamedAttributeNamesOf, q as readTtlSpec, rc as coerceCfnInteger, rn as withApiLimit, sa as onlySecretReferencesDiffer, sc as readConfigString, su as stringifyValue, t as DeployEngine, tc as toFiniteNumber, tn as isAccessDeniedError, u as STREAM_TAGS_KEY, uc as requireConfigObject, ut as isAbsoluteAssetPath, v as streamPolicyMatchesDeclared, va as ec2InstanceProtectionSite, vc as ecsServiceLaunchTypeSetOrChanged, vt as enclosingDeadlineExpired, w as planIndexContributorInsightsOps, x as contributorInsightsRefusals, xa as reDisableInstanceApiTermination, xc as lambdaFunctionNameForMask, y as streamTagsMatchDeclared, ya as isTerminationProtectionPropagationError, yc as emrClusterInstancesReplaced, yt as enclosingDeadlineRemainingMs, z as TABLE_INDEX_NOUN, zi as readTagList, zn as REDACTED_DELETE_ADDRESS_SKIP_REASON, zt as revertNestedChildFromJournal } from "./deploy-engine-CwpnkMCZ.js";
6
+ import { n as collectInlinePolicyNamesManagedBySiblings, r as IamCreateClientCache, t as IAMRoleProvider } from "./iam-role-provider-ARR3C50J.js";
7
+ import { a as resolveSecretDerivedPrincipals, i as isResolvableSecretPrincipalList, n as runDestroyForStack, o as canonicalizeIpProtocolValue, r as holdsUnprovenSecretPrincipalToken, s as resolvedResourceTimeoutMs, t as canonicalizeIpv4Cidr } from "./program-CMP_YVVn.js";
8
+ import { t as modifyDbInstanceWhenAvailable } from "./db-instance-modify-retry-D7wXWxVo.js";
9
+ import { RDSProvider } from "./rds-provider-Dn-7U1CR.js";
10
+ import { NeptuneProvider } from "./neptune-provider-DfPOAG0q.js";
11
+ import { ASGProvider } from "./asg-provider-CqPtIngx.js";
12
12
  import { createHash, randomUUID } from "node:crypto";
13
13
  import { 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, ListBucketsCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchBucket, PutBucketAccelerateConfigurationCommand, PutBucketAnalyticsConfigurationCommand, PutBucketCorsCommand, PutBucketEncryptionCommand, PutBucketIntelligentTieringConfigurationCommand, PutBucketInventoryConfigurationCommand, PutBucketLifecycleConfigurationCommand, PutBucketLoggingCommand, PutBucketMetricsConfigurationCommand, PutBucketNotificationConfigurationCommand, PutBucketOwnershipControlsCommand, PutBucketPolicyCommand, PutBucketReplicationCommand, PutBucketTaggingCommand, PutBucketVersioningCommand, PutBucketWebsiteCommand, PutObjectLockConfigurationCommand, PutPublicAccessBlockCommand, S3Client } from "@aws-sdk/client-s3";
14
14
  import { AddRoleToInstanceProfileCommand, AddUserToGroupCommand, AttachGroupPolicyCommand, AttachRolePolicyCommand, AttachUserPolicyCommand, CreateAccessKeyCommand, CreateGroupCommand, CreateInstanceProfileCommand, CreateLoginProfileCommand, CreatePolicyCommand, CreatePolicyVersionCommand, CreateUserCommand, DeleteAccessKeyCommand, DeleteGroupCommand, DeleteGroupPolicyCommand, DeleteInstanceProfileCommand, DeleteLoginProfileCommand, DeletePolicyCommand, DeletePolicyVersionCommand, DeleteRolePolicyCommand, DeleteUserCommand, DeleteUserPermissionsBoundaryCommand, DeleteUserPolicyCommand, DetachGroupPolicyCommand, DetachRolePolicyCommand, DetachUserPolicyCommand, GetAccessKeyLastUsedCommand, GetGroupCommand, GetGroupPolicyCommand, GetInstanceProfileCommand, GetPolicyCommand, GetPolicyVersionCommand, GetRolePolicyCommand, GetUserCommand, GetUserPolicyCommand, IAMClient, ListAccessKeysCommand, ListAttachedGroupPoliciesCommand, ListAttachedUserPoliciesCommand, ListEntitiesForPolicyCommand, ListGroupPoliciesCommand, ListGroupsForUserCommand, ListPoliciesCommand, ListPolicyTagsCommand, ListPolicyVersionsCommand, ListUserPoliciesCommand, NoSuchEntityException, PutGroupPolicyCommand, PutRolePolicyCommand, PutUserPermissionsBoundaryCommand, PutUserPolicyCommand, RemoveRoleFromInstanceProfileCommand, RemoveUserFromGroupCommand, TagPolicyCommand, TagUserCommand, UntagPolicyCommand, UntagUserCommand, UpdateAccessKeyCommand, UpdateGroupCommand, UpdateLoginProfileCommand, UpdateUserCommand } from "@aws-sdk/client-iam";
@@ -63,7 +63,7 @@ import { CodeCommitClient, CreateCommitCommand, CreateRepositoryCommand as Creat
63
63
  import { CreateLifecyclePolicyCommand, DLMClient, DeleteLifecyclePolicyCommand as DeleteLifecyclePolicyCommand$1, GetLifecyclePoliciesCommand, GetLifecyclePolicyCommand as GetLifecyclePolicyCommand$1, ResourceNotFoundException as ResourceNotFoundException$16, TagResourceCommand as TagResourceCommand$26, UntagResourceCommand as UntagResourceCommand$27, UpdateLifecyclePolicyCommand } from "@aws-sdk/client-dlm";
64
64
  import { CreateVectorBucketCommand, DeleteIndexCommand, DeleteVectorBucketCommand, GetVectorBucketCommand, ListIndexesCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$18, S3VectorsClient, TagResourceCommand as TagResourceCommand$27, UntagResourceCommand as UntagResourceCommand$28 } from "@aws-sdk/client-s3vectors";
65
65
  import { ListTagsForResourceCommand as ListTagsForResourceCommand$19, S3ControlClient, TagResourceCommand as TagResourceCommand$28, UntagResourceCommand as UntagResourceCommand$29 } from "@aws-sdk/client-s3-control";
66
- import { CreateNamespaceCommand, CreateTableBucketCommand, CreateTableCommand as CreateTableCommand$2, DeleteNamespaceCommand as DeleteNamespaceCommand$1, DeleteTableBucketCommand, DeleteTableCommand as DeleteTableCommand$2, GetNamespaceCommand as GetNamespaceCommand$1, GetTableBucketCommand, GetTableCommand as GetTableCommand$1, ListNamespacesCommand as ListNamespacesCommand$1, ListTableBucketsCommand, ListTablesCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$20, NotFoundException as NotFoundException$7, RenameTableCommand, S3TablesClient, TagResourceCommand as TagResourceCommand$29, UntagResourceCommand as UntagResourceCommand$30 } from "@aws-sdk/client-s3tables";
66
+ import { CreateNamespaceCommand, CreateTableBucketCommand, CreateTableCommand as CreateTableCommand$2, DeleteNamespaceCommand as DeleteNamespaceCommand$1, DeleteTableBucketCommand, DeleteTableBucketMetricsConfigurationCommand, DeleteTableBucketReplicationCommand, DeleteTableCommand as DeleteTableCommand$2, GetNamespaceCommand as GetNamespaceCommand$1, GetTableBucketCommand, GetTableBucketEncryptionCommand, GetTableBucketMaintenanceConfigurationCommand, GetTableBucketMetricsConfigurationCommand, GetTableBucketReplicationCommand, GetTableBucketStorageClassCommand, GetTableCommand as GetTableCommand$1, GetTableMaintenanceConfigurationCommand, ListNamespacesCommand as ListNamespacesCommand$1, ListTableBucketsCommand, ListTablesCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$20, NotFoundException as NotFoundException$7, PutTableBucketEncryptionCommand, PutTableBucketMaintenanceConfigurationCommand, PutTableBucketMetricsConfigurationCommand, PutTableBucketReplicationCommand, PutTableBucketStorageClassCommand, PutTableMaintenanceConfigurationCommand, RenameTableCommand, S3TablesClient, TagResourceCommand as TagResourceCommand$29, UntagResourceCommand as UntagResourceCommand$30 } from "@aws-sdk/client-s3tables";
67
67
 
68
68
  //#region src/provisioning/providers/iam-policy-provider.ts
69
69
  const POLICY_NAME_SKIP_REASON = "no policy name in state — no delete issued";
@@ -9379,13 +9379,17 @@ function toCfnSelfManagedEventSource(selfManagedEventSource) {
9379
9379
  return renameEndpointsKey(selfManagedEventSource, SDK_KAFKA_ENDPOINTS_KEY, CFN_KAFKA_ENDPOINTS_KEY);
9380
9380
  }
9381
9381
  const KAFKA_CONSUMPTION_MODE_KEY = "ConsumptionMode";
9382
- function declaredConsumptionMode(properties) {
9382
+ const KAFKA_DEFAULT_CONSUMPTION_MODE = "Stream";
9383
+ function consumptionModeOf(properties) {
9383
9384
  const config = properties["SelfManagedKafkaEventSourceConfig"];
9384
- if (typeof config !== "object" || config === null || Array.isArray(config)) return void 0;
9385
- return config[KAFKA_CONSUMPTION_MODE_KEY];
9385
+ if (typeof config !== "object" || config === null || Array.isArray(config)) return KAFKA_DEFAULT_CONSUMPTION_MODE;
9386
+ return config[KAFKA_CONSUMPTION_MODE_KEY] ?? KAFKA_DEFAULT_CONSUMPTION_MODE;
9386
9387
  }
9387
- function consumptionModeRefusalMessage(logicalId, mode) {
9388
- return `AWS::Lambda::EventSourceMapping ${logicalId}: SelfManagedKafkaEventSourceConfig.${KAFKA_CONSUMPTION_MODE_KEY} cannot be sent by cdkd yet — the AWS SDK for JavaScript does not model the member, so it would be dropped from the ${mode === "create" ? "CreateEventSourceMapping" : "UpdateEventSourceMapping"} request without an error. Remove ${KAFKA_CONSUMPTION_MODE_KEY} from SelfManagedKafkaEventSourceConfig to deploy the mapping without it.`;
9388
+ function replayableKafkaConfig(properties) {
9389
+ if (consumptionModeOf(properties) !== "Queue") return void 0;
9390
+ if (properties["StartingPosition"] === void 0 && properties["StartingPositionTimestamp"] === void 0 && properties["MaximumBatchingWindowInSeconds"] === void 0) return;
9391
+ const { [KAFKA_CONSUMPTION_MODE_KEY]: _dropped, ...rest } = properties["SelfManagedKafkaEventSourceConfig"];
9392
+ return rest;
9389
9393
  }
9390
9394
  function kafkaConfigForUpdate(desired, previous, options) {
9391
9395
  const asObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v) ? v : void 0;
@@ -9573,11 +9577,6 @@ var LambdaEventSourceMappingProvider = class {
9573
9577
  const desiredTags = refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, void 0, "Tags", DBPROXY_TAGS_WHAT, DBPROXY_TAG_OPTIONS);
9574
9578
  const functionName = properties["FunctionName"];
9575
9579
  if (!functionName) throw new ProvisioningError(`FunctionName is required for event source mapping ${logicalId}`, resourceType, logicalId);
9576
- if (declaredConsumptionMode(properties) !== void 0) {
9577
- const message = consumptionModeRefusalMessage(logicalId, "create");
9578
- if (context?.replayingState !== true) throw new ProvisioningError(message, resourceType, logicalId);
9579
- log.warn(safeMsg`${message} Proceeding without it: this create replays a cdkd state record.`);
9580
- }
9581
9580
  try {
9582
9581
  const params = { FunctionName: functionName };
9583
9582
  if (properties["EventSourceArn"]) params.EventSourceArn = properties["EventSourceArn"];
@@ -9596,6 +9595,11 @@ var LambdaEventSourceMappingProvider = class {
9596
9595
  if (properties["SourceAccessConfigurations"]) params.SourceAccessConfigurations = properties["SourceAccessConfigurations"];
9597
9596
  if (properties["SelfManagedEventSource"]) params.SelfManagedEventSource = toSdkSelfManagedEventSource(properties["SelfManagedEventSource"]);
9598
9597
  if (properties["SelfManagedKafkaEventSourceConfig"]) params.SelfManagedKafkaEventSourceConfig = properties["SelfManagedKafkaEventSourceConfig"];
9598
+ const replayableKafka = context?.replayingState === true ? replayableKafkaConfig(properties) : void 0;
9599
+ if (replayableKafka !== void 0) {
9600
+ log.warn(safeMsg`AWS::Lambda::EventSourceMapping ${logicalId}: the state record holds ConsumptionMode Queue beside a member Lambda refuses with it, so the mapping it records never ran in Queue mode. Proceeding without ConsumptionMode: this create replays a cdkd state record.`);
9601
+ params.SelfManagedKafkaEventSourceConfig = replayableKafka;
9602
+ }
9599
9603
  if (properties["AmazonManagedKafkaEventSourceConfig"]) params.AmazonManagedKafkaEventSourceConfig = properties["AmazonManagedKafkaEventSourceConfig"];
9600
9604
  if (properties["DocumentDBEventSourceConfig"]) params.DocumentDBEventSourceConfig = properties["DocumentDBEventSourceConfig"];
9601
9605
  if (properties["ScalingConfig"]) params.ScalingConfig = properties["ScalingConfig"];
@@ -9632,7 +9636,11 @@ var LambdaEventSourceMappingProvider = class {
9632
9636
  attributes: {
9633
9637
  Id: uuid,
9634
9638
  EventSourceMappingArn: response.EventSourceMappingArn
9635
- }
9639
+ },
9640
+ ...replayableKafka !== void 0 && { effectiveProperties: {
9641
+ ...properties,
9642
+ SelfManagedKafkaEventSourceConfig: replayableKafka
9643
+ } }
9636
9644
  };
9637
9645
  } catch (error) {
9638
9646
  const cause = error instanceof Error ? error : void 0;
@@ -9666,18 +9674,15 @@ var LambdaEventSourceMappingProvider = class {
9666
9674
  const log = this.operationSinks(context?.maskSecrets, properties, previousProperties);
9667
9675
  refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, physicalId, "Tags", DBPROXY_TAGS_WHAT, DBPROXY_TAG_OPTIONS);
9668
9676
  const restoring = context?.replayingState === true || context?.desiredFromAwsReadback === true;
9669
- for (const key of ["Queues", "Topics"]) {
9670
- if (JSON.stringify(properties[key]) === JSON.stringify(previousProperties[key])) continue;
9671
- const reason = `${key} cannot be changed on an existing event source mapping (UpdateEventSourceMapping does not take it, and CloudFormation refuses the change too)`;
9677
+ const refuseChange = (reason) => {
9672
9678
  if (!restoring) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `${reason}; deploy with --replace to delete and recreate the mapping`);
9673
9679
  log.warn(safeMsg`AWS::Lambda::EventSourceMapping ${logicalId}: ${reason}. Proceeding without it: this update restores a recorded or read-back configuration.`);
9680
+ };
9681
+ for (const key of ["Queues", "Topics"]) {
9682
+ if (JSON.stringify(properties[key]) === JSON.stringify(previousProperties[key])) continue;
9683
+ refuseChange(`${key} cannot be changed on an existing event source mapping (UpdateEventSourceMapping does not take it, and CloudFormation refuses the change too)`);
9674
9684
  }
9675
- const desiredMode = declaredConsumptionMode(properties);
9676
- if (desiredMode !== void 0 && JSON.stringify(desiredMode) !== JSON.stringify(declaredConsumptionMode(previousProperties))) {
9677
- const message = consumptionModeRefusalMessage(logicalId, "update");
9678
- if (!restoring) throw new ProvisioningError(message, resourceType, logicalId, physicalId);
9679
- log.warn(safeMsg`${message} Proceeding without it: this update restores a recorded or read-back configuration.`);
9680
- }
9685
+ if (JSON.stringify(consumptionModeOf(properties)) !== JSON.stringify(consumptionModeOf(previousProperties))) refuseChange(`SelfManagedKafkaEventSourceConfig.${KAFKA_CONSUMPTION_MODE_KEY} cannot be changed on an existing event source mapping (UpdateEventSourceMapping refuses it)`);
9681
9686
  try {
9682
9687
  return await this.applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties, log, restoring);
9683
9688
  } catch (error) {
@@ -9905,6 +9910,24 @@ var LambdaEventSourceMappingProvider = class {
9905
9910
  result["Tags"] = tags;
9906
9911
  return result;
9907
9912
  }
9913
+ async canonicalizeDriftPair(_resourceType, baseline, aws, properties) {
9914
+ const key = "SelfManagedKafkaEventSourceConfig";
9915
+ const block = baseline[key];
9916
+ if (typeof block !== "object" || block === null || Array.isArray(block) || KAFKA_CONSUMPTION_MODE_KEY in block || consumptionModeOf(aws) !== KAFKA_DEFAULT_CONSUMPTION_MODE || consumptionModeOf(properties ?? {}) !== KAFKA_DEFAULT_CONSUMPTION_MODE || aws[key]?.[KAFKA_CONSUMPTION_MODE_KEY] === void 0) return {
9917
+ baseline,
9918
+ aws
9919
+ };
9920
+ return {
9921
+ baseline: {
9922
+ ...baseline,
9923
+ [key]: {
9924
+ ...block,
9925
+ [KAFKA_CONSUMPTION_MODE_KEY]: KAFKA_DEFAULT_CONSUMPTION_MODE
9926
+ }
9927
+ },
9928
+ aws
9929
+ };
9930
+ }
9908
9931
  async import(input) {
9909
9932
  if (!input.knownPhysicalId) return null;
9910
9933
  let resp;
@@ -11517,6 +11540,11 @@ var LambdaNetworkConnectorProvider = class {
11517
11540
  const tagList = refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, void 0, "Tags", DBPROXY_TAGS_WHAT, DBPROXY_TAG_OPTIONS);
11518
11541
  const name = typeof properties["Name"] === "string" && properties["Name"] !== "" ? properties["Name"] : generatedNameFor("AWS::Lambda::NetworkConnector", logicalId);
11519
11542
  const vpc = this.readVpcEgress(properties, logicalId, resourceType, void 0);
11543
+ if (declaredElasticIp(properties) !== void 0) {
11544
+ const message = elasticIpRefusalMessage(logicalId, "create");
11545
+ if (context?.replayingState !== true) throw new ProvisioningError(message, resourceType, logicalId);
11546
+ this.logger.warn(safeMsg`${message} Proceeding without it: this create replays a cdkd state record.`);
11547
+ }
11520
11548
  const createToken = acquireIdempotencyToken({
11521
11549
  scope: "CreateNetworkConnector",
11522
11550
  logicalId
@@ -11556,6 +11584,12 @@ var LambdaNetworkConnectorProvider = class {
11556
11584
  assertRegionMatch(context?.expectedRegion ? await this.client.config.region() : void 0, context?.expectedRegion, resourceType, logicalId, physicalId, "pre-update");
11557
11585
  refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, physicalId, "Tags", DBPROXY_TAGS_WHAT, DBPROXY_TAG_OPTIONS);
11558
11586
  const vpc = this.readVpcEgress(properties, logicalId, resourceType, physicalId);
11587
+ const desiredElasticIp = declaredElasticIp(properties);
11588
+ if (desiredElasticIp !== void 0 && !isDeepStrictEqual(desiredElasticIp, declaredElasticIp(previousProperties))) {
11589
+ const message = elasticIpRefusalMessage(logicalId, "update");
11590
+ if (context?.replayingState !== true && context?.desiredFromAwsReadback !== true) throw new ProvisioningError(message, resourceType, logicalId, physicalId);
11591
+ this.logger.warn(safeMsg`${message} Proceeding without it: this update restores a recorded or read-back configuration.`);
11592
+ }
11559
11593
  const updateRole = this.readOperatorRole(properties, logicalId, resourceType, physicalId, context);
11560
11594
  if (typeof previousProperties["OperatorRole"] === "string" && properties["OperatorRole"] === void 0 && context?.replayingState !== true && context?.desiredFromAwsReadback !== true) throw new ProvisioningError(`OperatorRole cannot be removed in place for Lambda network connector ${logicalIdShown(logicalId)}: cdkd sends no role when the template declares none, so the current one would stay attached. Set it to another role, or replace the connector (change its Name).`, resourceType, logicalId, physicalId);
11561
11595
  try {
@@ -11754,6 +11788,15 @@ var LambdaNetworkConnectorProvider = class {
11754
11788
  return markRedactedCause(build(`${failure.summary}${relayedNameCollision(failure.detail)}`));
11755
11789
  }
11756
11790
  };
11791
+ const ELASTIC_IP_KEY = "ElasticIpConfiguration";
11792
+ function declaredElasticIp(properties) {
11793
+ const config = properties["Configuration"];
11794
+ const vpc = isPlainRecord$3(config) ? config["VpcEgressConfiguration"] : void 0;
11795
+ return isPlainRecord$3(vpc) ? vpc[ELASTIC_IP_KEY] : void 0;
11796
+ }
11797
+ function elasticIpRefusalMessage(logicalId, mode) {
11798
+ return `AWS::Lambda::NetworkConnector ${logicalIdShown(logicalId)}: Configuration.VpcEgressConfiguration.${ELASTIC_IP_KEY} cannot be sent by cdkd yet — the AWS SDK for JavaScript (@aws-sdk/client-lambda-core) does not model the member, so it would be dropped from the ${mode === "create" ? "CreateNetworkConnector" : "UpdateNetworkConnector"} request without an error. Remove ${ELASTIC_IP_KEY} from Configuration.VpcEgressConfiguration to deploy the connector without it.`;
11799
+ }
11757
11800
  var TerminalConnectorStateError = class extends Error {};
11758
11801
  function buildAttributes(resp) {
11759
11802
  return definedAttributes({
@@ -11820,6 +11863,120 @@ async function waitForGoneAfterDelete(opts) {
11820
11863
  }
11821
11864
  }
11822
11865
 
11866
+ //#endregion
11867
+ //#region src/provisioning/dynamodb-vector-indexes.ts
11868
+ function vectorIndexesByName(value) {
11869
+ const out = /* @__PURE__ */ new Map();
11870
+ if (!Array.isArray(value)) return out;
11871
+ for (const entry of value) {
11872
+ if (typeof entry !== "object" || entry === null || Array.isArray(entry)) continue;
11873
+ const name = entry["IndexName"];
11874
+ if (typeof name === "string") out.set(name, entry);
11875
+ }
11876
+ return out;
11877
+ }
11878
+ function vectorIndexForSend(entry) {
11879
+ const out = {};
11880
+ for (const key of [
11881
+ "IndexName",
11882
+ "VectorAttribute",
11883
+ "Projection",
11884
+ "DistanceFunction"
11885
+ ]) if (entry[key] !== void 0) out[key] = entry[key];
11886
+ if (entry["Dimensions"] !== void 0) out["Dimensions"] = coerceCfnInteger(entry["Dimensions"]) ?? entry["Dimensions"];
11887
+ if (entry["SearchSchema"] !== void 0) out["SearchSchema"] = entry["SearchSchema"];
11888
+ return out;
11889
+ }
11890
+ function vectorIndexesForCreate(value) {
11891
+ if (value === void 0 || value === null) return void 0;
11892
+ if (!Array.isArray(value)) return value;
11893
+ return value.map((entry) => typeof entry === "object" && entry !== null && !Array.isArray(entry) ? vectorIndexForSend(entry) : entry);
11894
+ }
11895
+ function sortedByJson(list) {
11896
+ if (!Array.isArray(list)) return list;
11897
+ return [...list].sort((a, b) => {
11898
+ const x = JSON.stringify(a) ?? "";
11899
+ const y = JSON.stringify(b) ?? "";
11900
+ return x < y ? -1 : x > y ? 1 : 0;
11901
+ });
11902
+ }
11903
+ function vectorIndexKey(entry) {
11904
+ const e = entry;
11905
+ const projection = e["Projection"];
11906
+ const normalizedProjection = typeof projection === "object" && projection !== null && !Array.isArray(projection) ? {
11907
+ ProjectionType: projection["ProjectionType"],
11908
+ NonKeyAttributes: sortedByJson(nonEmpty(projection["NonKeyAttributes"]))
11909
+ } : projection;
11910
+ const attribute = e["VectorAttribute"];
11911
+ return JSON.stringify([
11912
+ e["IndexName"],
11913
+ typeof attribute === "object" && attribute !== null ? attribute["AttributeName"] : attribute,
11914
+ coerceCfnInteger(e["Dimensions"]) ?? e["Dimensions"],
11915
+ e["DistanceFunction"],
11916
+ normalizedProjection,
11917
+ sortedByJson(Array.isArray(e["SearchSchema"]) && e["SearchSchema"].length > 0 ? e["SearchSchema"].map((s) => typeof s === "object" && s !== null ? {
11918
+ AttributeName: s["AttributeName"],
11919
+ SearchSchemaElementType: s["SearchSchemaElementType"]
11920
+ } : s) : nonEmpty(e["SearchSchema"]))
11921
+ ]);
11922
+ }
11923
+ function nonEmpty(value) {
11924
+ return Array.isArray(value) && value.length === 0 ? void 0 : value;
11925
+ }
11926
+ function planVectorIndexUpdates(previous, desired, live) {
11927
+ const prevByName = vectorIndexesByName(previous);
11928
+ const desiredByName = vectorIndexesByName(desired);
11929
+ const liveByName = live === void 0 ? void 0 : new Map(live.filter((d) => typeof d.IndexName === "string").map((d) => [d.IndexName, d]));
11930
+ const plan = {
11931
+ ops: [],
11932
+ changed: [],
11933
+ adopted: [],
11934
+ alreadyGone: []
11935
+ };
11936
+ const liveHolds = (name, entry) => {
11937
+ const l = liveByName?.get(name);
11938
+ return l !== void 0 && l.IndexStatus !== "DELETING" && vectorIndexKey(l) === vectorIndexKey(entry);
11939
+ };
11940
+ for (const name of prevByName.keys()) {
11941
+ if (desiredByName.has(name)) continue;
11942
+ const l = liveByName?.get(name);
11943
+ if (liveByName !== void 0 && (l === void 0 || l.IndexStatus === "DELETING")) {
11944
+ plan.alreadyGone.push(name);
11945
+ continue;
11946
+ }
11947
+ plan.ops.push({ Delete: { IndexName: name } });
11948
+ }
11949
+ for (const [name, entry] of desiredByName) {
11950
+ const before = prevByName.get(name);
11951
+ if (before === void 0) {
11952
+ const l = liveByName?.get(name);
11953
+ if (l === void 0 || l.IndexStatus === "DELETING") plan.ops.push({ Create: vectorIndexForSend(entry) });
11954
+ else if (liveHolds(name, entry)) plan.adopted.push(name);
11955
+ else plan.changed.push(name);
11956
+ continue;
11957
+ }
11958
+ if (vectorIndexKey(before) === vectorIndexKey(entry)) continue;
11959
+ if (!liveHolds(name, entry)) plan.changed.push(name);
11960
+ }
11961
+ return plan;
11962
+ }
11963
+ function readbackVectorIndexes(live) {
11964
+ if (live === void 0 || live.length === 0) return void 0;
11965
+ return live.map((d) => {
11966
+ const out = {};
11967
+ if (d.IndexName !== void 0) out["IndexName"] = d.IndexName;
11968
+ if (d.VectorAttribute !== void 0) out["VectorAttribute"] = d.VectorAttribute;
11969
+ if (d.Dimensions !== void 0) out["Dimensions"] = d.Dimensions;
11970
+ if (d.DistanceFunction !== void 0) out["DistanceFunction"] = d.DistanceFunction;
11971
+ if (d.Projection !== void 0) out["Projection"] = d.Projection;
11972
+ if (d.SearchSchema !== void 0 && d.SearchSchema.length > 0) out["SearchSchema"] = d.SearchSchema;
11973
+ return out;
11974
+ });
11975
+ }
11976
+ function vectorIndexesSettled(live) {
11977
+ return (live ?? []).every((d) => d.IndexStatus === void 0 || d.IndexStatus === "ACTIVE");
11978
+ }
11979
+
11823
11980
  //#endregion
11824
11981
  //#region src/provisioning/providers/dynamodb-table-provider.ts
11825
11982
  function isTableName(id) {
@@ -12246,7 +12403,7 @@ var DynamoDBTableProvider = class {
12246
12403
  if (!failure.redacted) return wrapMaskedAwsError(m, error, build);
12247
12404
  this.logger.debug(m(build(m(failure.detail)).message));
12248
12405
  const relay = isAuxiliaryFailure(error) ? "" : relayedNameCollision(failure.detail);
12249
- const wrapped = build(`${m(failure.summary)}${relay}${relayedIndexBusyDelete(failure.detail)}`);
12406
+ const wrapped = build(`${m(failure.summary)}${relay}${relayedIndexBusyDelete(failure.detail, TABLE_INDEX_NOUN)}`);
12250
12407
  return error instanceof Error ? markRedactedCause(wrapped) : wrapped;
12251
12408
  }
12252
12409
  handledProperties = /* @__PURE__ */ new Map([["AWS::DynamoDB::Table", /* @__PURE__ */ new Set([
@@ -12268,7 +12425,8 @@ var DynamoDBTableProvider = class {
12268
12425
  "TimeToLiveSpecification",
12269
12426
  "ResourcePolicy",
12270
12427
  "KinesisStreamSpecification",
12271
- "ContributorInsightsSpecification"
12428
+ "ContributorInsightsSpecification",
12429
+ "VectorIndexes"
12272
12430
  ])]]);
12273
12431
  unhandledByDesign = /* @__PURE__ */ new Map([["AWS::DynamoDB::Table", /* @__PURE__ */ new Map([["ImportSourceSpecification", "S3 import uses the separate ImportTable API (not CreateTable) and is create-only with no readback; deferred to a dedicated import-from-S3 PR"]])]]);
12274
12432
  deleteBudgets = new ElapsedBudgetRegistry();
@@ -12342,6 +12500,8 @@ var DynamoDBTableProvider = class {
12342
12500
  const declaredGsis = properties["GlobalSecondaryIndexes"];
12343
12501
  createParams.GlobalSecondaryIndexes = Array.isArray(declaredGsis) ? declaredGsis.map((entry) => this.coerceIndexThroughputForCreate(logicalId, stripIndexContributorInsights(entry), maskSecrets)) : declaredGsis;
12344
12502
  }
12503
+ const createVectorIndexes = vectorIndexesForCreate(properties["VectorIndexes"]);
12504
+ if (createVectorIndexes !== void 0) createParams.VectorIndexes = createVectorIndexes;
12345
12505
  if (properties["LocalSecondaryIndexes"]) createParams.LocalSecondaryIndexes = properties["LocalSecondaryIndexes"];
12346
12506
  const sseCreateRefusal = sseSpecificationRefusal(properties["SSESpecification"], logicalId);
12347
12507
  if (sseCreateRefusal !== void 0 && context?.replayingState !== true) throw new ProvisioningError(`${maskSecrets(sseCreateRefusal)}. Nothing was created; fix the template value`, resourceType, logicalId);
@@ -12366,8 +12526,12 @@ var DynamoDBTableProvider = class {
12366
12526
  tableCreated = true;
12367
12527
  createdTableId = createOut?.TableDescription?.TableId;
12368
12528
  reportCreatedResource(logicalId, resourceType, tableName, createdTableId);
12369
- this.logger.debug(`CreateTable initiated for ${tableName}, waiting for ACTIVE status`);
12370
- const tableInfo = await timePhase("provider waits", "DynamoDB table: wait for ACTIVE", () => this.waitForTableActive(tableName), logicalId);
12529
+ debug(`CreateTable initiated for ${tableName}, waiting for ACTIVE status`);
12530
+ const tableInfo = await timePhase("provider waits", "DynamoDB table: wait for ACTIVE", () => this.waitForTableActive(tableName, maskSecrets), logicalId);
12531
+ if (createVectorIndexes !== void 0) await timePhase("provider waits", "DynamoDB table: wait for vector indexes", () => this.waitForTableAndIndexesActive(tableName, void 0, {
12532
+ after: "CreateTable",
12533
+ maskSecrets
12534
+ }), logicalId);
12371
12535
  await this.applyPointInTimeRecovery(tableName, properties["PointInTimeRecoverySpecification"], void 0, maskSecrets);
12372
12536
  await this.applyTimeToLive(tableName, properties["TimeToLiveSpecification"], void 0, "create", {
12373
12537
  logicalId,
@@ -12378,7 +12542,7 @@ var DynamoDBTableProvider = class {
12378
12542
  await this.applyContributorInsights(tableName, properties["ContributorInsightsSpecification"], void 0, maskSecrets);
12379
12543
  await this.applyIndexContributorInsights(tableName, properties["GlobalSecondaryIndexes"], void 0, maskSecrets);
12380
12544
  await this.applyStreamMembers(logicalId, resourceType, tableName, tableInfo.streamArn, properties["StreamSpecification"], void 0, true, maskSecrets);
12381
- this.logger.debug(`Successfully created DynamoDB table ${logicalId}: ${tableName}`);
12545
+ debug(`Successfully created DynamoDB table ${logicalId}: ${tableName}`);
12382
12546
  return {
12383
12547
  physicalId: tableName,
12384
12548
  attributes: {
@@ -12392,7 +12556,7 @@ var DynamoDBTableProvider = class {
12392
12556
  let tableLeftBehind = false;
12393
12557
  if (tableCreated) {
12394
12558
  try {
12395
- await this.dynamoDBClient.send(new DeleteTableCommand({ TableName: tableName }));
12559
+ await this.rollBackCreatedTable(logicalId, tableName, maskSecrets);
12396
12560
  retractCreatedResource(logicalId, resourceType, tableName);
12397
12561
  debug(`Rolled back partially-created DynamoDB table ${tableName}`);
12398
12562
  } catch (cleanupError) {
@@ -12410,6 +12574,38 @@ var DynamoDBTableProvider = class {
12410
12574
  throw thrown;
12411
12575
  }
12412
12576
  }
12577
+ async rollBackCreatedTable(logicalId, tableName, maskSecrets) {
12578
+ const logger = maskedLogger(this.logger, maskSecrets, tableName);
12579
+ const allowanceMs = Math.min(resolveDynamoDbDeleteBudgetMs(), enclosingDeadlineRemainingMs() - DYNAMODB_DELETE_DEADLINE_MARGIN_MS);
12580
+ const budget = allowanceMs > 0 ? new ElapsedBudget(allowanceMs, resolveDynamoDbDeleteBudgetClock()) : void 0;
12581
+ await deleteTableWithIndexBusyRetry({
12582
+ logicalId,
12583
+ physicalId: tableName,
12584
+ typeLabel: "table",
12585
+ indexNoun: TABLE_INDEX_NOUN,
12586
+ maxRetries: 14,
12587
+ logger,
12588
+ deleteTable: async () => {
12589
+ await this.dynamoDBClient.send(new DeleteTableCommand({ TableName: tableName }));
12590
+ },
12591
+ reArm: () => {
12592
+ const wait = beginDeleteWait(900, budget);
12593
+ return waitForIndexesSettled({
12594
+ tableName,
12595
+ logicalId,
12596
+ logger,
12597
+ describeTable: () => this.dynamoDBClient.send(new DescribeTableCommand({ TableName: tableName })),
12598
+ maxAttempts: wait.grantedPolls,
12599
+ budgetWait: wait,
12600
+ shortCapUnlessVectorBusy: 60,
12601
+ proceedNote: DELETE_INDEX_WAIT_PROCEED_NOTE
12602
+ });
12603
+ },
12604
+ shouldKeepRetrying: () => budget !== void 0 && !budget.isExhausted(),
12605
+ retryWarning: () => `DynamoDB table ${logicalId}: AWS refused the DeleteTable rolling back the partially-created table ${tableName} because ${TABLE_INDEX_NOUN} is still being created, updated or deleted. Waiting for the indexes to settle and retrying (up to ${14} retries in all, within ~${Math.max(1, Math.round((budget?.totalMs ?? 0) / 6e4))} minutes).`,
12606
+ sleepSeam: deleteTableRetryDelays
12607
+ });
12608
+ }
12413
12609
  async update(logicalId, physicalId, resourceType, properties, previousProperties, context) {
12414
12610
  const markUnsettled = (key) => context?.markUnsettled?.(key);
12415
12611
  const maskSecrets = context?.maskSecrets ?? ((text) => text);
@@ -12454,6 +12650,12 @@ var DynamoDBTableProvider = class {
12454
12650
  if (context?.replayingState !== true && context?.desiredFromAwsReadback !== true) throw new ProvisioningError(`${lsiMessage}. Nothing was applied to the table; revert the LocalSecondaryIndexes change, or create a new table under a new logical ID (a new table starts empty)`, resourceType, logicalId, physicalId);
12455
12651
  warn(`${lsiMessage}; the LocalSecondaryIndexes change was not applied`);
12456
12652
  }
12653
+ const vectorIndexPlan = JSON.stringify(properties["VectorIndexes"]) !== JSON.stringify(previousProperties["VectorIndexes"]) ? planVectorIndexUpdates(previousProperties["VectorIndexes"], properties["VectorIndexes"], table?.VectorIndexes ?? (table === void 0 ? void 0 : [])) : void 0;
12654
+ if (vectorIndexPlan !== void 0 && vectorIndexPlan.changed.length > 0) {
12655
+ const vectorMessage = `AWS::DynamoDB::Table ${logicalId}: VectorIndexes ${vectorIndexPlan.changed.map((n) => maskSecrets(n)).join(", ")} changed definition, which DynamoDB cannot modify in place`;
12656
+ if (context?.replayingState !== true && context?.desiredFromAwsReadback !== true) throw new ProvisioningError(`${maskSecrets(vectorMessage)}. Nothing was applied to the table; rename the index (so it is dropped and re-created) or revert the change`, resourceType, logicalId, physicalId);
12657
+ warn(`${vectorMessage}; that change was not applied`);
12658
+ }
12457
12659
  let latestStreamArn = table?.LatestStreamArn;
12458
12660
  if (table?.TableArn) await this.applyTagDiff(table.TableArn, resourceType, logicalId, previousProperties["Tags"], properties["Tags"], {
12459
12661
  forceUpsert: context?.unsettledProperties?.has("Tags") === true,
@@ -12572,7 +12774,7 @@ var DynamoDBTableProvider = class {
12572
12774
  if (tableClassChanged) markUnsettled("TableClass");
12573
12775
  if (updateInput.GlobalSecondaryIndexUpdates !== void 0) markUnsettled("GlobalSecondaryIndexes");
12574
12776
  await this.dynamoDBClient.send(new UpdateTableCommand(updateInput));
12575
- if (billingMode !== liveBillingMode) await this.waitForTableAndIndexesActive(physicalId, BILLING_FLIP_ACTIVE_WAIT_ATTEMPTS);
12777
+ if (billingMode !== liveBillingMode) await this.waitForTableAndIndexesActive(physicalId, BILLING_FLIP_ACTIVE_WAIT_ATTEMPTS, { maskSecrets });
12576
12778
  else await this.waitForTableActiveAfterUpdate(physicalId, 60);
12577
12779
  this.logger.debug(`Updated BillingMode/ProvisionedThroughput/TableClass on DynamoDB table ${physicalId}`);
12578
12780
  }
@@ -12687,6 +12889,7 @@ var DynamoDBTableProvider = class {
12687
12889
  markUnsettled("GlobalSecondaryIndexes");
12688
12890
  await this.applyGsiUpdates(physicalId, resourceType, logicalId, previousProperties["GlobalSecondaryIndexes"], properties["GlobalSecondaryIndexes"], properties["AttributeDefinitions"], gsiHandledByBillingFlip, currentLiveIndexNames, currentLiveIndexByName, liveCapacityComparable, effectiveBillingMode === "PAY_PER_REQUEST", maskSecrets, (indexName) => context?.markAttempted?.("GlobalSecondaryIndexes", [indexName]));
12689
12891
  }
12892
+ if (vectorIndexPlan !== void 0) await this.applyVectorIndexUpdates(physicalId, vectorIndexPlan, properties["AttributeDefinitions"], maskSecrets, () => markUnsettled("VectorIndexes"), (indexName) => context?.markAttempted?.("VectorIndexes", [indexName]));
12690
12893
  if (JSON.stringify(properties["PointInTimeRecoverySpecification"]) !== JSON.stringify(previousProperties["PointInTimeRecoverySpecification"])) {
12691
12894
  markUnsettled("PointInTimeRecoverySpecification");
12692
12895
  await this.applyPointInTimeRecovery(physicalId, properties["PointInTimeRecoverySpecification"], previousProperties["PointInTimeRecoverySpecification"], maskSecrets);
@@ -12802,16 +13005,18 @@ var DynamoDBTableProvider = class {
12802
13005
  }
12803
13006
  try {
12804
13007
  const reArmPolls = () => {
12805
- const wait = beginDeleteWait(60, budget);
13008
+ const wait = beginDeleteWait(900, budget);
12806
13009
  return {
12807
13010
  maxAttempts: wait.grantedPolls,
12808
- budgetWait: wait
13011
+ budgetWait: wait,
13012
+ shortCapUnlessVectorBusy: 60
12809
13013
  };
12810
13014
  };
12811
13015
  await deleteTableWithIndexBusyRetry({
12812
13016
  logicalId,
12813
13017
  physicalId,
12814
13018
  typeLabel: "table",
13019
+ indexNoun: TABLE_INDEX_NOUN,
12815
13020
  maxRetries: 14,
12816
13021
  logger: loopLogger,
12817
13022
  deleteTable: async () => {
@@ -13203,7 +13408,7 @@ var DynamoDBTableProvider = class {
13203
13408
  const warn = (message) => this.logger.warn(maskSecrets(message));
13204
13409
  const ops = planIndexContributorInsightsOps(desiredIndexes, previousIndexes, (indexName, reason) => warn(`${this.indexScopeAt(indexName, tableName, maskSecrets)}: ${reason}, so its Contributor Insights was left as it is. Fix the template value and re-deploy.`));
13205
13410
  if (ops.length === 0) return;
13206
- await this.waitForTableAndIndexesActive(tableName);
13411
+ await this.waitForTableAndIndexesActive(tableName, void 0, { maskSecrets });
13207
13412
  for (const op of ops) {
13208
13413
  beforeSend();
13209
13414
  await this.sendContributorInsightsOp(tableName, op, maskSecrets);
@@ -13220,11 +13425,11 @@ var DynamoDBTableProvider = class {
13220
13425
  })), `set ContributorInsights on ${target}`);
13221
13426
  debug(`Set ContributorInsightsAction=${op.action}${op.mode !== void 0 ? ` Mode=${op.mode}` : ""} on ${target}`);
13222
13427
  }
13223
- async waitForTableActive(tableName, maxAttempts = 60) {
13428
+ async waitForTableActive(tableName, maskSecrets, maxAttempts = 60) {
13224
13429
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
13225
13430
  const response = await this.dynamoDBClient.send(new DescribeTableCommand({ TableName: tableName }));
13226
13431
  const status = response.Table?.TableStatus;
13227
- this.logger.debug(`Table ${tableName} status: ${status} (attempt ${attempt}/${maxAttempts})`);
13432
+ this.logger.debug(maskSecrets(`Table ${tableName} status: ${status} (attempt ${attempt}/${maxAttempts})`));
13228
13433
  if (status === "ACTIVE") return {
13229
13434
  tableArn: response.Table?.TableArn,
13230
13435
  tableId: response.Table?.TableId,
@@ -13262,15 +13467,36 @@ var DynamoDBTableProvider = class {
13262
13467
  }
13263
13468
  throw new Error(maskSecrets(`DynamoDB table ${tableName} was still ${last ?? "unread"} ${KINESIS_DESTINATION_SETTLE_POLLS * KINESIS_DESTINATION_SETTLE_POLL_MS / 1e3} seconds after its encryption change`));
13264
13469
  }
13265
- async waitForTableAndIndexesActive(tableName, maxAttempts = 1800) {
13470
+ async waitForTableAndIndexesActive(tableName, maxAttempts = 1800, opts = {}) {
13266
13471
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
13267
13472
  const table = (await this.dynamoDBClient.send(new DescribeTableCommand({ TableName: tableName }))).Table;
13268
13473
  const tableActive = table?.TableStatus === "ACTIVE";
13269
13474
  const indexesActive = (table?.GlobalSecondaryIndexes ?? []).every((gsi) => gsi.IndexStatus === "ACTIVE");
13270
- if (tableActive && indexesActive) return;
13475
+ if (tableActive && indexesActive && vectorIndexesSettled(table?.VectorIndexes)) return;
13271
13476
  await new Promise((resolve) => setTimeout(resolve, 1e3));
13272
13477
  }
13273
- throw new Error(`Table ${tableName} and its global secondary indexes did not reach ACTIVE within ${maxAttempts} seconds after UpdateTable`);
13478
+ const m = maskerOrIdentity(opts.maskSecrets);
13479
+ throw new Error(m(`Table ${m(tableName)} and its indexes did not reach ACTIVE within ${maxAttempts} seconds after ${opts.after ?? "UpdateTable"}`));
13480
+ }
13481
+ async applyVectorIndexUpdates(physicalId, plan, desiredAttributeDefinitions, maskSecrets, beforeFirstOp, onCreated) {
13482
+ const debug = (message) => this.logger.debug(maskSecrets(message));
13483
+ const warn = (message) => this.logger.warn(maskSecrets(message));
13484
+ for (const name of plan.alreadyGone) debug(`${this.vectorIndexScopeAt(name, physicalId, maskSecrets)} is recorded in cdkd state but not live; skipping its Delete (already removed)`);
13485
+ for (const name of plan.adopted) warn(`${this.vectorIndexScopeAt(name, physicalId, maskSecrets)} already exists in AWS with the declared definition but is absent from cdkd's recorded previous state, so its Create is being skipped. This usually means an earlier deploy created the index and then failed before state was written.`);
13486
+ if (plan.ops.length === 0) return;
13487
+ await this.waitForTableAndIndexesActive(physicalId, void 0, { maskSecrets });
13488
+ beforeFirstOp();
13489
+ for (const op of plan.ops) {
13490
+ const input = {
13491
+ TableName: physicalId,
13492
+ VectorIndexUpdates: [op]
13493
+ };
13494
+ if (op.Create && desiredAttributeDefinitions) input.AttributeDefinitions = desiredAttributeDefinitions;
13495
+ await this.dynamoDBClient.send(new UpdateTableCommand(input));
13496
+ if (op.Create?.IndexName !== void 0) onCreated(op.Create.IndexName);
13497
+ await this.waitForTableAndIndexesActive(physicalId, void 0, { maskSecrets });
13498
+ debug(`${op.Create ? "created" : "deleted"} ` + this.vectorIndexScopeAt(op.Create?.IndexName ?? op.Delete?.IndexName, physicalId, maskSecrets));
13499
+ }
13274
13500
  }
13275
13501
  async applyGsiUpdates(physicalId, resourceType, logicalId, previousGsis, desiredGsis, desiredAttributeDefinitions, handledByBillingFlip, liveIndexNames, liveIndexByName, liveCapacityComparable, onDemandCeilingsSendable, maskSecrets, onCreated = () => void 0) {
13276
13502
  const warn = (message) => this.logger.warn(maskSecrets(message));
@@ -13374,6 +13600,9 @@ var DynamoDBTableProvider = class {
13374
13600
  this.logger.warn(maskSecrets(`${this.indexScopeAt(name, physicalId, maskSecrets)} is live, but neither cdkd's record nor the template declares it, so cdkd left it in place while converging the unsettled GlobalSecondaryIndexes (CloudFormation never deletes an index it did not record). It may belong to another tool, or an earlier failed cdkd update may have created it; cdkd cannot tell which. If it should not exist, delete it ` + (secretDerived ? `with an UpdateTable GlobalSecondaryIndexUpdates Delete for the index.` : `with: aws dynamodb update-table --table-name ${physicalId} --global-secondary-index-updates '[{"Delete":{"IndexName":"${name}"}}]' (in the table's region)`)));
13375
13601
  }
13376
13602
  }
13603
+ vectorIndexScopeAt(indexName, physicalId, maskSecrets) {
13604
+ return `vector index ${typeof indexName === "string" ? maskSecrets(indexName) : "<unnamed>"} on DynamoDB table ${maskSecrets(physicalId)}`;
13605
+ }
13377
13606
  indexScopeAt(indexName, physicalId, maskSecrets) {
13378
13607
  return `GSI ${typeof indexName === "string" ? maskSecrets(indexName) : "<unnamed>"} on DynamoDB table ${physicalId}`;
13379
13608
  }
@@ -13521,7 +13750,7 @@ var DynamoDBTableProvider = class {
13521
13750
  if (op.Create && desiredAttributeDefinitions) input.AttributeDefinitions = desiredAttributeDefinitions;
13522
13751
  await this.dynamoDBClient.send(new UpdateTableCommand(input));
13523
13752
  if (op.Create?.IndexName !== void 0) onCreated(op.Create.IndexName);
13524
- await this.waitForTableAndIndexesActive(physicalId);
13753
+ await this.waitForTableAndIndexesActive(physicalId, void 0, { maskSecrets });
13525
13754
  debug(`${op.Create ? "created" : op.Delete ? "deleted" : "updated"} ${this.indexScopeAt(op.Create?.IndexName ?? op.Delete?.IndexName ?? op.Update?.IndexName, physicalId, maskSecrets)}`);
13526
13755
  }
13527
13756
  }
@@ -13583,7 +13812,8 @@ var DynamoDBTableProvider = class {
13583
13812
  return [
13584
13813
  "AttributeDefinitions",
13585
13814
  "GlobalSecondaryIndexes[]",
13586
- "LocalSecondaryIndexes[]"
13815
+ "LocalSecondaryIndexes[]",
13816
+ "VectorIndexes"
13587
13817
  ];
13588
13818
  }
13589
13819
  getDriftUnknownPaths(resourceType, properties) {
@@ -13670,6 +13900,10 @@ var DynamoDBTableProvider = class {
13670
13900
  out["GlobalSecondaryIndexes"] = projectIndexesOnto(out["GlobalSecondaryIndexes"], recordedProperties?.["GlobalSecondaryIndexes"], desiredProperties?.["GlobalSecondaryIndexes"], attemptedItems?.get("GlobalSecondaryIndexes"));
13671
13901
  if (out["GlobalSecondaryIndexes"] === void 0) delete out["GlobalSecondaryIndexes"];
13672
13902
  }
13903
+ if (names.has("VectorIndexes")) {
13904
+ out["VectorIndexes"] = projectIndexesOnto(out["VectorIndexes"], recordedProperties?.["VectorIndexes"], desiredProperties?.["VectorIndexes"], attemptedItems?.get("VectorIndexes"));
13905
+ if (out["VectorIndexes"] === void 0) delete out["VectorIndexes"];
13906
+ }
13673
13907
  const strict = async (key, read) => {
13674
13908
  if (!names.has(key)) return;
13675
13909
  const value = await read();
@@ -13758,6 +13992,8 @@ var DynamoDBTableProvider = class {
13758
13992
  const desiredByName = desiredIndexEntriesByName(properties?.["LocalSecondaryIndexes"]);
13759
13993
  result["LocalSecondaryIndexes"] = table.LocalSecondaryIndexes.map((live) => reverseMapSecondaryIndex(live, live.IndexName === void 0 ? void 0 : desiredByName.get(live.IndexName), bagInformative));
13760
13994
  }
13995
+ const liveVectorIndexes = readbackVectorIndexes(table.VectorIndexes);
13996
+ if (liveVectorIndexes !== void 0) result["VectorIndexes"] = liveVectorIndexes;
13761
13997
  if (table.SSEDescription?.Status === "ENABLED") {
13762
13998
  const sse = { SSEEnabled: true };
13763
13999
  if (table.SSEDescription.KMSMasterKeyArn !== void 0) sse["KMSMasterKeyId"] = table.SSEDescription.KMSMasterKeyArn;
@@ -22917,6 +23153,20 @@ var ApiGatewayV2Provider = class ApiGatewayV2Provider {
22917
23153
  ])]
22918
23154
  ]);
22919
23155
  removalDefaults = /* @__PURE__ */ new Map([["AWS::ApiGatewayV2::Authorizer", /* @__PURE__ */ new Map([["IdentitySource", []]])]]);
23156
+ removalHandledInUpdate = /* @__PURE__ */ new Map([["AWS::ApiGatewayV2::Route", /* @__PURE__ */ new Set([
23157
+ "ApiId",
23158
+ "RouteKey",
23159
+ "AuthorizationScopes",
23160
+ "Target",
23161
+ "AuthorizationType",
23162
+ "AuthorizerId",
23163
+ "OperationName",
23164
+ "ApiKeyRequired",
23165
+ "RequestModels",
23166
+ "RequestParameters",
23167
+ "ModelSelectionExpression",
23168
+ "RouteResponseSelectionExpression"
23169
+ ])]]);
22920
23170
  unhandledByDesign = /* @__PURE__ */ new Map([["AWS::ApiGatewayV2::Api", /* @__PURE__ */ new Map([
22921
23171
  ["Body", "OpenAPI/Swagger inline spec; routed through ImportApi, not the field-by-field CreateApi path."],
22922
23172
  ["BodyS3Location", "OpenAPI/Swagger spec on S3; routed through ImportApi, not the field-by-field CreateApi path."],
@@ -23954,12 +24204,15 @@ var ApiGatewayV2Provider = class ApiGatewayV2Provider {
23954
24204
  input.OperationName = properties["OperationName"];
23955
24205
  changed = true;
23956
24206
  }
23957
- {
24207
+ if (restoreFromAws) {
23958
24208
  const r = this.clearableUpdate(properties["ApiKeyRequired"], previousProperties["ApiKeyRequired"], false);
23959
24209
  if (r.changed) {
23960
24210
  input.ApiKeyRequired = r.value;
23961
24211
  changed = true;
23962
24212
  }
24213
+ } else if (properties["ApiKeyRequired"] !== void 0 && properties["ApiKeyRequired"] !== previousProperties["ApiKeyRequired"]) {
24214
+ input.ApiKeyRequired = properties["ApiKeyRequired"];
24215
+ changed = true;
23963
24216
  }
23964
24217
  if (restoreFromAws) {
23965
24218
  const merged = this.mapWithRemovals(properties["RequestModels"], previousProperties["RequestModels"]);
@@ -26412,6 +26665,60 @@ function isEcsErrorNamed(error, names) {
26412
26665
  return typeof name === "string" && names.includes(name);
26413
26666
  }
26414
26667
  const settleRolloutDelays = { sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)) };
26668
+ function requestedRolloutOf(service) {
26669
+ if (!service) return void 0;
26670
+ const primary = service.deployments?.find((d) => d.status === "PRIMARY");
26671
+ const deploymentId = typeof primary?.id === "string" && primary.id ? primary.id : void 0;
26672
+ const taskDefinitionRaw = primary?.taskDefinition ?? service.taskDefinition;
26673
+ const taskDefinition = typeof taskDefinitionRaw === "string" && taskDefinitionRaw ? taskDefinitionRaw : void 0;
26674
+ if (deploymentId === void 0 && taskDefinition === void 0) return void 0;
26675
+ return {
26676
+ deploymentId,
26677
+ taskDefinition
26678
+ };
26679
+ }
26680
+ function failedRequestedDeployment(requested, deployments) {
26681
+ if (!Array.isArray(deployments)) return void 0;
26682
+ const target = requested?.deploymentId !== void 0 ? deployments.find((d) => d?.id === requested.deploymentId) : deployments.find((d) => d?.status === "PRIMARY");
26683
+ return target?.rolloutState === "FAILED" ? target : void 0;
26684
+ }
26685
+ function taskDefinitionRevision(arn) {
26686
+ const match = typeof arn === "string" ? /:task-definition\/[^:]+:(\d+)$/.exec(arn) : null;
26687
+ return match ? match[1] : void 0;
26688
+ }
26689
+ function describeRollout(rollout) {
26690
+ const revision = taskDefinitionRevision(rollout.taskDefinition);
26691
+ const id = typeof rollout.id === "string" && /^ecs-svc\/\d+$/.test(rollout.id) ? rollout.id : void 0;
26692
+ if (id && revision) return `deployment ${id} (task definition revision ${revision})`;
26693
+ if (id) return `deployment ${id}`;
26694
+ if (revision) return `task definition revision ${revision}`;
26695
+ return "another deployment";
26696
+ }
26697
+ var EcsCircuitBreakerVerdict = class extends Error {
26698
+ constructor(message) {
26699
+ super(message);
26700
+ this.name = "EcsCircuitBreakerVerdict";
26701
+ }
26702
+ };
26703
+ function wrapBreakerFailedError(failed) {
26704
+ return new EcsCircuitBreakerVerdict(`its deployment circuit breaker failed the rollout of ${describeRollout(failed)} (deployment FAILED). The new tasks failed to start or failed their health checks`);
26705
+ }
26706
+ function controllerSkipsWait(properties) {
26707
+ let type;
26708
+ try {
26709
+ type = readConfigString(properties["DeploymentController"], "Type", "ECS", "DeploymentController");
26710
+ } catch {
26711
+ return "its DeploymentController could not be read";
26712
+ }
26713
+ if (type === "ECS") return void 0;
26714
+ if (type === "CODE_DEPLOY" || type === "EXTERNAL") return `its DeploymentController is ${type}, which ECS does not settle`;
26715
+ return "its DeploymentController type is not one cdkd can settle";
26716
+ }
26717
+ function rolloutSupersededBy(requested, settled) {
26718
+ if (!requested || !settled) return void 0;
26719
+ if (requested.deploymentId !== void 0 && typeof settled.id === "string" && settled.id) return settled.id === requested.deploymentId ? void 0 : describeRollout(settled);
26720
+ if (requested.taskDefinition !== void 0 && typeof settled.taskDefinition === "string" && settled.taskDefinition) return settled.taskDefinition === requested.taskDefinition ? void 0 : describeRollout(settled);
26721
+ }
26415
26722
  function markNotGoneOnNotFoundClass$1(error, wrapped) {
26416
26723
  return error instanceof Error && error.name.includes("NotFound") ? markNotGone(wrapped) : wrapped;
26417
26724
  }
@@ -26561,7 +26868,7 @@ var ECSProvider = class {
26561
26868
  switch (resourceType) {
26562
26869
  case "AWS::ECS::Cluster": return this.createCluster(logicalId, resourceType, properties, this.operationSinks(context, [[properties["ClusterName"], properties["ClusterName"]]]));
26563
26870
  case "AWS::ECS::TaskDefinition": return this.createTaskDefinition(logicalId, resourceType, properties, this.operationSinks(context, [[properties["Family"], properties["Family"]]]));
26564
- case "AWS::ECS::Service": return this.createService(logicalId, resourceType, properties, this.operationSinks(context, [[properties["ServiceName"], properties["ServiceName"]], [properties["Cluster"], clusterNameOfRef(properties["Cluster"])]]));
26871
+ case "AWS::ECS::Service": return this.createService(logicalId, resourceType, properties, this.operationSinks(context, [[properties["ServiceName"], properties["ServiceName"]], [properties["Cluster"], clusterNameOfRef(properties["Cluster"])]]), context?.replayingState === true);
26565
26872
  default: throw new ProvisioningError(`Unsupported resource type: ${resourceType}`, resourceType, logicalId);
26566
26873
  }
26567
26874
  }
@@ -26578,7 +26885,7 @@ var ECSProvider = class {
26578
26885
  [properties["Cluster"], recordedCluster],
26579
26886
  [previousProperties["Cluster"], recordedCluster],
26580
26887
  [properties["Cluster"], clusterNameOfRef(properties["Cluster"])]
26581
- ]), context?.desiredFromAwsReadback === true);
26888
+ ]), context?.desiredFromAwsReadback === true, context?.replayingState === true);
26582
26889
  }
26583
26890
  default: throw new ProvisioningError(`Unsupported resource type: ${resourceType}`, resourceType, logicalId, physicalId);
26584
26891
  }
@@ -26798,14 +27105,15 @@ var ECSProvider = class {
26798
27105
  default: return;
26799
27106
  }
26800
27107
  }
26801
- async createService(logicalId, resourceType, properties, log) {
27108
+ async createService(logicalId, resourceType, properties, log, replayingState) {
26802
27109
  log.debug(`Creating ECS service ${logicalId}`);
26803
27110
  const desiredTags = refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId);
26804
27111
  const client = this.getClient();
26805
27112
  const serviceName = properties["ServiceName"] || generatedNameFor("AWS::ECS::Service", logicalId);
26806
27113
  let survivorArn;
26807
27114
  try {
26808
- const heldBefore = process.env["CDKD_FULL_WAIT"] === "true" ? await nameHeldBefore(() => this.serviceNameHeld(properties["Cluster"], serviceName), (error) => hasErrorName(error, ["ClusterNotFoundException"])) : "free";
27115
+ const skipReason = controllerSkipsWait(properties);
27116
+ const heldBefore = process.env["CDKD_NO_WAIT"] !== "true" && skipReason === void 0 && !replayingState ? await nameHeldBefore(() => this.serviceNameHeld(properties["Cluster"], serviceName), (error) => hasErrorName(error, ["ClusterNotFoundException"])) : "free";
26809
27117
  const service = (await client.send(new CreateServiceCommand({
26810
27118
  cluster: properties["Cluster"],
26811
27119
  serviceName,
@@ -26838,8 +27146,18 @@ var ECSProvider = class {
26838
27146
  log.debug(`Successfully created ECS service ${logicalId}: ${service.serviceArn}`);
26839
27147
  if (heldBefore === "free") reportCreatedResource(logicalId, resourceType, service.serviceArn);
26840
27148
  try {
26841
- await this.settleService(logicalId, service.serviceName ?? service.serviceArn, properties["Cluster"], log);
27149
+ await this.settleService(logicalId, service.serviceName ?? service.serviceArn, properties["Cluster"], log, requestedRolloutOf(service), skipReason);
26842
27150
  } catch (waitError) {
27151
+ if (replayingState) {
27152
+ log.warn(`${this.wrapSteadyStateError(logicalId, waitError, properties["Cluster"], log, false).message} Continuing the rollback: the restored service stays recorded.`);
27153
+ return {
27154
+ physicalId: service.serviceArn,
27155
+ attributes: {
27156
+ ServiceArn: service.serviceArn,
27157
+ Name: service.serviceName
27158
+ }
27159
+ };
27160
+ }
26843
27161
  const aws = pasteableAwsCommand(log.mask);
26844
27162
  const cleanupCluster = properties["Cluster"];
26845
27163
  const clusterArg = cleanupCluster ? aws` --cluster ${cleanupCluster}` : aws``;
@@ -26861,10 +27179,7 @@ var ECSProvider = class {
26861
27179
  if (cleanupFailure.redacted) log.debug(`${cleanupHead}${cleanupFailure.detail}`);
26862
27180
  log.warn(`${cleanupHead}${cleanupFailure.redacted ? `${cleanupFailure.summary} ` : `${cleanupFailure.detail}. `}Manual deletion may be required before the next deploy: ${deleteCommand.render()}`);
26863
27181
  }
26864
- const waitFailure = describeAwsFailure(waitError);
26865
- if (waitFailure.redacted) log.debug(`ECS service ${logicalId} steady-state wait failed: ${waitFailure.detail}`);
26866
- const steadyStateError = new Error(`ECS service ${logicalIdShown(logicalId)} did not reach steady state under --full-wait: ${waitFailure.summary.replace(/\.$/, "")}. Inspect why its tasks stopped (stopped tasks stay visible for about an hour): ${listStopped.render()}, then ${aws`aws ecs describe-tasks${clusterArg} --tasks '<task-arn>' --query 'tasks[].[stoppedReason,containers[].reason]'`.render()}`, { cause: waitError });
26867
- throw waitFailure.redacted ? markRedactedCause(steadyStateError) : steadyStateError;
27182
+ throw this.wrapSteadyStateError(logicalId, waitError, properties["Cluster"], log);
26868
27183
  }
26869
27184
  return {
26870
27185
  physicalId: service.serviceArn,
@@ -26907,30 +27222,68 @@ var ECSProvider = class {
26907
27222
  reduced.name = error.name;
26908
27223
  return markRedactedCause(reduced);
26909
27224
  }
26910
- async settleService(logicalId, serviceRef, cluster, log) {
26911
- if (process.env["CDKD_FULL_WAIT"] === "true") {
27225
+ wrapSteadyStateError(logicalId, waitError, cluster, log, offerNoWait = true) {
27226
+ const aws = pasteableAwsCommand(log.mask);
27227
+ const clusterArg = cluster ? aws` --cluster ${cluster}` : aws``;
27228
+ const listStopped = aws`aws ecs list-tasks${clusterArg} --desired-status STOPPED`;
27229
+ const waitFailure = describeAwsFailure(waitError);
27230
+ if (waitFailure.redacted) log.debug(`ECS service ${logicalId} steady-state wait failed: ${waitFailure.detail}`);
27231
+ const flagsAvailable = offerNoWait && process.env["CDKD_WAIT_FLAGS_AVAILABLE"] === "true";
27232
+ const timeoutHint = flagsAvailable && !(waitError instanceof EcsCircuitBreakerVerdict) ? ` To wait longer, raise the limit with --resource-timeout AWS::ECS::Service=${commandHole("duration")}.` : "";
27233
+ const noWaitHint = flagsAvailable ? " To deploy without waiting for steady state, pass --no-wait." : "";
27234
+ const steadyStateError = new Error(`ECS service ${logicalIdShown(logicalId)} did not reach steady state: ${waitFailure.summary.replace(/\.$/, "")}. Inspect why its tasks stopped (stopped tasks stay visible for about an hour): ${listStopped.render()}, then ${aws`aws ecs describe-tasks${clusterArg} --tasks '<task-arn>' --query 'tasks[].[stoppedReason,containers[].reason]'`.render()}.${timeoutHint}${noWaitHint}`, { cause: waitError });
27235
+ return waitFailure.redacted ? markRedactedCause(steadyStateError) : steadyStateError;
27236
+ }
27237
+ async settleService(logicalId, serviceRef, cluster, log, requested, skipReason) {
27238
+ if (skipReason !== void 0) {
27239
+ this.logger.info(log.mask(`ECS service ${logicalIdShown(logicalId)} accepted (not waiting for steady state: ${skipReason}).`));
27240
+ return;
27241
+ }
27242
+ if (process.env["CDKD_NO_WAIT"] !== "true") {
26912
27243
  log.debug(`Waiting for ECS service ${logicalId} to reach steady state...`);
26913
27244
  const maxWaitTime = Math.max(600, (resolvedResourceTimeoutMs("AWS::ECS::Service") ?? 0) / 1e3);
27245
+ const client = this.getClient();
27246
+ const breakerVerdict = new AbortController();
27247
+ let failedRollout;
27248
+ const watchedClient = { send: async (command) => {
27249
+ const output = await client.send(command);
27250
+ if (failedRollout === void 0) {
27251
+ failedRollout = failedRequestedDeployment(requested, output?.services?.[0]?.deployments);
27252
+ if (failedRollout !== void 0) breakerVerdict.abort();
27253
+ }
27254
+ return output;
27255
+ } };
26914
27256
  try {
26915
27257
  await waitUntilServicesStable({
26916
- client: this.getClient(),
27258
+ client: watchedClient,
26917
27259
  maxWaitTime,
26918
27260
  minDelay: 5,
26919
- maxDelay: 10
27261
+ maxDelay: 10,
27262
+ abortSignal: breakerVerdict.signal
26920
27263
  }, {
26921
27264
  cluster,
26922
27265
  services: [serviceRef]
26923
27266
  });
26924
27267
  } catch (waiterError) {
27268
+ if (failedRollout !== void 0) {
27269
+ log.debug(`ECS service ${logicalId} deployment ${failedRollout.id ?? "(no id)"} FAILED: ${failedRollout.rolloutStateReason ?? "(no rollout reason)"}`);
27270
+ throw wrapBreakerFailedError(failedRollout);
27271
+ }
26925
27272
  throw this.wrapWaiterResultError(waiterError, logicalId, log);
26926
27273
  }
27274
+ if (failedRollout !== void 0) throw wrapBreakerFailedError(failedRollout);
26927
27275
  const rolloutDeadline = Date.now() + 12e4;
27276
+ let settledDeployment;
26928
27277
  for (;;) {
26929
27278
  const deployments = (await this.getClient().send(new DescribeServicesCommand({
26930
27279
  cluster,
26931
27280
  services: [serviceRef]
26932
27281
  })))?.services?.[0]?.deployments;
26933
- const rolloutState = deployments && deployments.length === 1 ? deployments[0]?.rolloutState : void 0;
27282
+ const failedNow = failedRequestedDeployment(requested, deployments);
27283
+ if (failedNow !== void 0) throw wrapBreakerFailedError(failedNow);
27284
+ settledDeployment = deployments && deployments.length === 1 ? deployments[0] : void 0;
27285
+ const rolloutState = settledDeployment?.rolloutState;
27286
+ if (settledDeployment !== void 0 && rolloutState === "FAILED") throw wrapBreakerFailedError(settledDeployment);
26934
27287
  if (rolloutState === void 0 || rolloutState === "COMPLETED") break;
26935
27288
  if (Date.now() >= rolloutDeadline) {
26936
27289
  log.warn(`ECS service ${logicalId} is steady but its rollout is still ${rolloutState} after the post-stability grace window; continuing`);
@@ -26938,15 +27291,22 @@ var ECSProvider = class {
26938
27291
  }
26939
27292
  await settleRolloutDelays.sleep(3e3);
26940
27293
  }
27294
+ const supersededBy = rolloutSupersededBy(requested, settledDeployment);
27295
+ if (supersededBy !== void 0) {
27296
+ log.debug(`ECS service ${logicalId} settled deployment ${settledDeployment?.id ?? "(no id)"}: ${settledDeployment?.rolloutStateReason ?? "(no rollout reason)"}`);
27297
+ throw new EcsCircuitBreakerVerdict(`its deployment circuit breaker rolled the rollout back: the service settled on ${supersededBy}, not on the deployment this update started (${describeRollout({
27298
+ id: requested.deploymentId,
27299
+ taskDefinition: requested.taskDefinition
27300
+ })}). The new tasks failed to start or failed their health checks`);
27301
+ }
26941
27302
  log.debug(`ECS service ${logicalId} reached steady state`);
26942
27303
  return;
26943
27304
  }
26944
27305
  const aws = pasteableAwsCommand(log.mask);
26945
27306
  const clusterArg = cluster ? aws` --cluster ${cluster}` : aws``;
26946
- const fullWaitHint = process.env["CDKD_WAIT_FLAGS_AVAILABLE"] === "true" ? "; pass --full-wait to wait" : "";
26947
- this.logger.info(log.mask(`ECS service ${logicalIdShown(logicalId)} accepted (not waiting for steady state${fullWaitHint}). To wait manually: ${aws`aws ecs wait services-stable${clusterArg} --services ${serviceRef}`.render()}`));
27307
+ this.logger.info(log.mask(`ECS service ${logicalIdShown(logicalId)} accepted (not waiting for steady state under --no-wait). To wait manually: ${aws`aws ecs wait services-stable${clusterArg} --services ${serviceRef}`.render()}`));
26948
27308
  }
26949
- async updateService(logicalId, physicalId, resourceType, properties, previousProperties, log, desiredFromAwsReadback) {
27309
+ async updateService(logicalId, physicalId, resourceType, properties, previousProperties, log, desiredFromAwsReadback, replayingState) {
26950
27310
  log.debug(`Updating ECS service ${logicalId}: ${physicalId}`);
26951
27311
  refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, physicalId);
26952
27312
  const client = this.getClient();
@@ -27016,7 +27376,12 @@ var ECSProvider = class {
27016
27376
  forceNewDeployment: forceNewDeploymentInput
27017
27377
  }))).service;
27018
27378
  if (service?.serviceArn) await this.applyTagDiff(service.serviceArn, resourceType, logicalId, previousProperties["Tags"], properties["Tags"], log);
27019
- await this.settleService(logicalId, service?.serviceName ?? physicalId, properties["Cluster"], log);
27379
+ try {
27380
+ await this.settleService(logicalId, service?.serviceName ?? physicalId, properties["Cluster"], log, requestedRolloutOf(service), desiredFromAwsReadback ? "a drift revert does not wait for it" : controllerSkipsWait(properties));
27381
+ } catch (waitError) {
27382
+ if (replayingState) log.warn(`${this.wrapSteadyStateError(logicalId, waitError, properties["Cluster"], log, false).message} The rollback update was applied; continuing.`);
27383
+ else throw this.wrapSteadyStateError(logicalId, waitError, properties["Cluster"], log);
27384
+ }
27020
27385
  return {
27021
27386
  physicalId,
27022
27387
  wasReplaced: false,
@@ -29360,6 +29725,7 @@ const POLL_INTERVAL_MS$1 = 5e3;
29360
29725
  const POLL_TIMEOUT_MS$1 = 18e5;
29361
29726
  const RETAINED_ON_REMOVAL = [
29362
29727
  "Auth",
29728
+ "DefaultAuthScheme",
29363
29729
  "RequireTLS",
29364
29730
  "IdleClientTimeout",
29365
29731
  "DebugLogging",
@@ -29371,7 +29737,14 @@ const CFN_KEEPS_ON_REMOVAL$1 = /* @__PURE__ */ new Set([
29371
29737
  "DebugLogging",
29372
29738
  "VpcSecurityGroupIds"
29373
29739
  ]);
29374
- const authRemovalRefused = (properties) => {
29740
+ const authRemovalRefused = (properties, previousProperties) => authRequired({ DefaultAuthScheme: properties["DefaultAuthScheme"] !== void 0 ? properties["DefaultAuthScheme"] : previousProperties["DefaultAuthScheme"] });
29741
+ const leavesProxyWithoutAuth = (properties, previousProperties) => {
29742
+ const desired = properties["Auth"];
29743
+ const declaredEmpty = desired === null || Array.isArray(desired) && desired.length === 0;
29744
+ if (properties["DefaultAuthScheme"] === "NONE" && previousProperties["DefaultAuthScheme"] !== "NONE" && (desired === void 0 || declaredEmpty)) return true;
29745
+ return declaredEmpty && JSON.stringify(desired) !== JSON.stringify(previousProperties["Auth"]) && authRemovalRefused(properties, previousProperties);
29746
+ };
29747
+ const authRequired = (properties) => {
29375
29748
  const scheme = properties["DefaultAuthScheme"];
29376
29749
  return scheme === void 0 || scheme === "NONE";
29377
29750
  };
@@ -29391,6 +29764,9 @@ var RDSDBProxyProvider = class {
29391
29764
  "RequireTLS",
29392
29765
  "IdleClientTimeout",
29393
29766
  "DebugLogging",
29767
+ "DefaultAuthScheme",
29768
+ "EndpointNetworkType",
29769
+ "TargetConnectionNetworkType",
29394
29770
  "Tags"
29395
29771
  ])]]);
29396
29772
  getClient() {
@@ -29417,18 +29793,21 @@ var RDSDBProxyProvider = class {
29417
29793
  const engineFamily = properties["EngineFamily"];
29418
29794
  if (!engineFamily) throw new ProvisioningError(`EngineFamily is required for AWS::RDS::DBProxy ${logicalId}`, resourceType, logicalId);
29419
29795
  const auth = properties["Auth"];
29420
- if (!auth || auth.length === 0) throw new ProvisioningError(`Auth (at least one entry) is required for AWS::RDS::DBProxy ${logicalId}`, resourceType, logicalId);
29796
+ if ((!auth || auth.length === 0) && authRequired(properties)) throw new ProvisioningError(`Auth (at least one entry) is required for AWS::RDS::DBProxy ${logicalId} while DefaultAuthScheme is NONE or unset`, resourceType, logicalId);
29421
29797
  const roleArn = properties["RoleArn"];
29422
29798
  if (!roleArn) throw new ProvisioningError(`RoleArn is required for AWS::RDS::DBProxy ${logicalId}`, resourceType, logicalId);
29423
29799
  const vpcSubnetIds = properties["VpcSubnetIds"];
29424
29800
  if (!vpcSubnetIds || vpcSubnetIds.length === 0) throw new ProvisioningError(`VpcSubnetIds (at least one) is required for AWS::RDS::DBProxy ${logicalId}`, resourceType, logicalId);
29425
29801
  const client = this.getClient();
29426
- this.logger.debug(`Creating DBProxy ${dbProxyName} (${engineFamily})`);
29802
+ this.logger.debug(mask(`Creating DBProxy ${dbProxyName} (${engineFamily})`));
29427
29803
  try {
29428
29804
  await this.getCreateClient().send(new CreateDBProxyCommand({
29429
29805
  DBProxyName: dbProxyName,
29430
29806
  EngineFamily: engineFamily,
29431
- Auth: auth,
29807
+ Auth: auth && auth.length > 0 ? auth : void 0,
29808
+ DefaultAuthScheme: properties["DefaultAuthScheme"],
29809
+ EndpointNetworkType: properties["EndpointNetworkType"],
29810
+ TargetConnectionNetworkType: properties["TargetConnectionNetworkType"],
29432
29811
  RoleArn: roleArn,
29433
29812
  VpcSubnetIds: vpcSubnetIds,
29434
29813
  VpcSecurityGroupIds: properties["VpcSecurityGroupIds"],
@@ -29480,13 +29859,16 @@ var RDSDBProxyProvider = class {
29480
29859
  }
29481
29860
  async update(logicalId, physicalId, resourceType, properties, previousProperties, context) {
29482
29861
  refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, physicalId, "Tags", DBPROXY_TAGS_WHAT, DBPROXY_TAG_OPTIONS);
29483
- if (context?.replayingState !== true && context?.desiredFromAwsReadback !== true && this.removedRetained(properties, previousProperties, context).includes("Auth") && authRemovalRefused(properties)) throw markNonRetryable(new ProvisioningError(safeMsg`${logicalId} (${resourceType}): Auth was removed from the template, but AWS requires Auth while DefaultAuthScheme is NONE or unset, and CloudFormation's update fails on the same change. Declare Auth again; nothing was changed.`, resourceType, logicalId, physicalId));
29862
+ if (context?.replayingState !== true && context?.desiredFromAwsReadback !== true && this.removedRetained(properties, previousProperties, context).includes("Auth") && authRemovalRefused(properties, previousProperties)) throw markNonRetryable(new ProvisioningError(safeMsg`${logicalId} (${resourceType}): Auth was removed from the template, but AWS requires Auth while DefaultAuthScheme is NONE or unset, and CloudFormation's update fails on the same change. Declare Auth again; nothing was changed.`, resourceType, logicalId, physicalId));
29863
+ if (context?.replayingState !== true && context?.desiredFromAwsReadback !== true && leavesProxyWithoutAuth(properties, previousProperties)) throw markNonRetryable(new ProvisioningError(safeMsg`${logicalId} (${resourceType}): the update leaves the proxy with no Auth while DefaultAuthScheme is NONE or unset, and AWS requires Auth then. Declare Auth; nothing was changed.`, resourceType, logicalId, physicalId));
29484
29864
  const client = this.getClient();
29485
29865
  const { mask } = withDerivedNameMasks(this.logger, createMaskedLogSinks(this.logger, context?.maskSecrets), [[previousProperties["DBProxyName"], physicalId]]);
29486
29866
  for (const field of [
29487
29867
  "DBProxyName",
29488
29868
  "EngineFamily",
29489
- "VpcSubnetIds"
29869
+ "VpcSubnetIds",
29870
+ "EndpointNetworkType",
29871
+ "TargetConnectionNetworkType"
29490
29872
  ]) if (JSON.stringify(properties[field]) !== JSON.stringify(previousProperties[field]) && !await unchangedBehindSecretReference({
29491
29873
  resourceType,
29492
29874
  key: field,
@@ -29499,6 +29881,7 @@ var RDSDBProxyProvider = class {
29499
29881
  let hasModify = false;
29500
29882
  for (const key of [
29501
29883
  "Auth",
29884
+ "DefaultAuthScheme",
29502
29885
  "RequireTLS",
29503
29886
  "IdleClientTimeout",
29504
29887
  "DebugLogging",
@@ -29626,7 +30009,10 @@ var RDSDBProxyProvider = class {
29626
30009
  SecretArn: a.SecretArn,
29627
30010
  IAMAuth: a.IAMAuth,
29628
30011
  ClientPasswordAuthType: a.ClientPasswordAuthType
29629
- }))
30012
+ })),
30013
+ ...p.DefaultAuthScheme !== void 0 && { DefaultAuthScheme: p.DefaultAuthScheme },
30014
+ ...p.EndpointNetworkType !== void 0 && { EndpointNetworkType: p.EndpointNetworkType },
30015
+ ...p.TargetConnectionNetworkType !== void 0 && { TargetConnectionNetworkType: p.TargetConnectionNetworkType }
29630
30016
  };
29631
30017
  if (p.DBProxyArn) try {
29632
30018
  const tagResp = await client.send(new ListTagsForResourceCommand$10({ ResourceName: p.DBProxyArn }));
@@ -29729,6 +30115,7 @@ var RDSDBProxyEndpointProvider = class {
29729
30115
  "VpcSubnetIds",
29730
30116
  "VpcSecurityGroupIds",
29731
30117
  "TargetRole",
30118
+ "EndpointNetworkType",
29732
30119
  "Tags"
29733
30120
  ])]]);
29734
30121
  getClient() {
@@ -29765,6 +30152,7 @@ var RDSDBProxyEndpointProvider = class {
29765
30152
  VpcSubnetIds: vpcSubnetIds,
29766
30153
  VpcSecurityGroupIds: properties["VpcSecurityGroupIds"],
29767
30154
  TargetRole: properties["TargetRole"],
30155
+ EndpointNetworkType: properties["EndpointNetworkType"],
29768
30156
  Tags: tags.length > 0 ? tags : void 0
29769
30157
  }));
29770
30158
  } catch (error) {
@@ -29820,7 +30208,8 @@ var RDSDBProxyEndpointProvider = class {
29820
30208
  "DBProxyName",
29821
30209
  "DBProxyEndpointName",
29822
30210
  "VpcSubnetIds",
29823
- "TargetRole"
30211
+ "TargetRole",
30212
+ "EndpointNetworkType"
29824
30213
  ]) if (JSON.stringify(properties[field]) !== JSON.stringify(previousProperties[field]) && !await unchangedBehindSecretReference({
29825
30214
  resourceType,
29826
30215
  key: field,
@@ -29924,7 +30313,8 @@ var RDSDBProxyEndpointProvider = class {
29924
30313
  DBProxyName: e.DBProxyName,
29925
30314
  VpcSubnetIds: e.VpcSubnetIds ?? [],
29926
30315
  VpcSecurityGroupIds: e.VpcSecurityGroupIds ?? [],
29927
- TargetRole: e.TargetRole ?? "READ_WRITE"
30316
+ TargetRole: e.TargetRole ?? "READ_WRITE",
30317
+ ...e.EndpointNetworkType !== void 0 && { EndpointNetworkType: e.EndpointNetworkType }
29928
30318
  };
29929
30319
  if (e.DBProxyEndpointArn) try {
29930
30320
  const tagResp = await client.send(new ListTagsForResourceCommand$10({ ResourceName: e.DBProxyEndpointArn }));
@@ -30587,6 +30977,25 @@ function masterUserPasswordToSend(properties, previousProperties, context) {
30587
30977
  return typeof desired === "string" && typeof recorded === "string" && recorded === desired && dynamicReferenceTokens(recorded).length === 0 && recorded !== "***" ? void 0 : desired;
30588
30978
  }
30589
30979
  const DOCDB_DEFAULT_PORT = 27017;
30980
+ const DOCDB_CLUSTER_KEPT_ON_REMOVAL = [
30981
+ "DeletionProtection",
30982
+ "BackupRetentionPeriod",
30983
+ "VpcSecurityGroupIds",
30984
+ "EngineVersion",
30985
+ "PreferredBackupWindow",
30986
+ "PreferredMaintenanceWindow",
30987
+ "DBClusterParameterGroupName"
30988
+ ];
30989
+ const DOCDB_INSTANCE_KEPT_ON_REMOVAL = ["PreferredMaintenanceWindow"];
30990
+ function keptOnRemovalWarning$1(keys, properties, previousProperties, context, logicalId, resourceType) {
30991
+ const removedSet = context?.removedProperties ?? new Set(removedTemplateKeys(previousProperties, properties));
30992
+ const removed = keys.filter((key) => removedSet.has(key));
30993
+ if (removed.length === 0) return void 0;
30994
+ const one = removed.length === 1;
30995
+ const names = `${one ? "property" : "properties"} ${removed.join(", ")}`;
30996
+ const modify = resourceType === "AWS::DocDB::DBInstance" ? "ModifyDBInstance" : "ModifyDBCluster";
30997
+ return context?.replayingState ? safeMsg`${logicalId} (${resourceType}): ${names} ${one ? "is" : "are"} absent from the state being restored; ${modify} keeps a setting it is not sent, so the rollback leaves any value the failed deploy applied in place.` : safeMsg`${logicalId} (${resourceType}): ${names} ${one ? "was" : "were"} removed from the template; cdkd leaves the current AWS ${one ? "value" : "values"} in place, as CloudFormation does. Declare ${one ? "it" : "them"} to change ${one ? "it" : "them"}.`;
30998
+ }
30590
30999
  const SECURITY_GROUP_CHANGE_MEMBER_STATUSES = /* @__PURE__ */ new Set(["modifying"]);
30591
31000
  const PORT_CHANGE_MEMBER_STATUSES = /* @__PURE__ */ new Set(["modifying", "rebooting"]);
30592
31001
  function numberOrUndefined(value) {
@@ -30628,6 +31037,25 @@ var DocDBProvider = class {
30628
31037
  logger = getLogger().child("DocDBProvider");
30629
31038
  protectionFlips = new ProtectionFlipRegistry();
30630
31039
  disableCcApiFallback = true;
31040
+ removalHandledInUpdate = /* @__PURE__ */ new Map([["AWS::DocDB::DBCluster", /* @__PURE__ */ new Set([
31041
+ "DBClusterIdentifier",
31042
+ "DBSubnetGroupName",
31043
+ "KmsKeyId",
31044
+ "MasterUsername",
31045
+ "StorageEncrypted",
31046
+ "Port",
31047
+ "Tags",
31048
+ "MasterUserPassword",
31049
+ ...DOCDB_CLUSTER_KEPT_ON_REMOVAL
31050
+ ])], ["AWS::DocDB::DBInstance", /* @__PURE__ */ new Set([
31051
+ "DBInstanceIdentifier",
31052
+ "DBClusterIdentifier",
31053
+ "AvailabilityZone",
31054
+ "DBInstanceClass",
31055
+ "Tags",
31056
+ "AutoMinorVersionUpgrade",
31057
+ ...DOCDB_INSTANCE_KEPT_ON_REMOVAL
31058
+ ])]]);
30631
31059
  handledProperties = /* @__PURE__ */ new Map([["AWS::DocDB::DBCluster", /* @__PURE__ */ new Set([
30632
31060
  "DBClusterIdentifier",
30633
31061
  "EngineVersion",
@@ -30681,7 +31109,7 @@ var DocDBProvider = class {
30681
31109
  async update(logicalId, physicalId, resourceType, properties, previousProperties, context) {
30682
31110
  switch (resourceType) {
30683
31111
  case "AWS::DocDB::DBCluster": return this.updateDBCluster(logicalId, physicalId, resourceType, properties, previousProperties, context);
30684
- case "AWS::DocDB::DBInstance": return this.updateDBInstance(logicalId, physicalId, resourceType, properties, previousProperties, context?.maskSecrets);
31112
+ case "AWS::DocDB::DBInstance": return this.updateDBInstance(logicalId, physicalId, resourceType, properties, previousProperties, context);
30685
31113
  default: throw new ProvisioningError(`Unsupported resource type: ${resourceType}`, resourceType, logicalId, physicalId);
30686
31114
  }
30687
31115
  }
@@ -30773,6 +31201,8 @@ var DocDBProvider = class {
30773
31201
  for (const member of described?.DBClusterMembers ?? []) if (member.DBInstanceIdentifier) await this.waitForMemberAfterClusterChange(member.DBInstanceIdentifier, logicalId, SECURITY_GROUP_CHANGE_MEMBER_STATUSES, "VPC security groups");
30774
31202
  }
30775
31203
  if (described?.DBClusterArn) await applyDocDBTagDiff(this.getClient(), this.logger, described.DBClusterArn, resourceType, logicalId, previousProperties["Tags"], properties["Tags"]);
31204
+ const keptWarning = keptOnRemovalWarning$1(DOCDB_CLUSTER_KEPT_ON_REMOVAL, properties, previousProperties, context, logicalId, resourceType);
31205
+ if (keptWarning !== void 0) this.logger.warn(keptWarning);
30776
31206
  return {
30777
31207
  physicalId,
30778
31208
  wasReplaced: false,
@@ -30896,8 +31326,9 @@ var DocDBProvider = class {
30896
31326
  throw thrown;
30897
31327
  }
30898
31328
  }
30899
- async updateDBInstance(logicalId, physicalId, resourceType, properties, previousProperties, mask) {
31329
+ async updateDBInstance(logicalId, physicalId, resourceType, properties, previousProperties, context) {
30900
31330
  this.logger.debug(`Updating DocDB DBInstance ${logicalId}: ${physicalId}`);
31331
+ const mask = context?.maskSecrets;
30901
31332
  refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, physicalId);
30902
31333
  try {
30903
31334
  await modifyDbInstanceWhenAvailable({
@@ -30918,6 +31349,8 @@ var DocDBProvider = class {
30918
31349
  this.logger.debug(`Successfully updated DocDB DBInstance ${logicalId}`);
30919
31350
  const described = await this.describeDBInstance(physicalId);
30920
31351
  if (described?.DBInstanceArn) await applyDocDBTagDiff(this.getClient(), this.logger, described.DBInstanceArn, resourceType, logicalId, previousProperties["Tags"], properties["Tags"]);
31352
+ const keptWarning = keptOnRemovalWarning$1(DOCDB_INSTANCE_KEPT_ON_REMOVAL, properties, previousProperties, context, logicalId, resourceType);
31353
+ if (keptWarning !== void 0) this.logger.warn(keptWarning);
30921
31354
  return {
30922
31355
  physicalId,
30923
31356
  wasReplaced: false,
@@ -34150,6 +34583,36 @@ function nodesToRemove(nodes, desiredCount, desiredZones) {
34150
34583
  if (keep.size + unnamed < desiredCount) return void 0;
34151
34584
  return named.map((n) => n.id).filter((id) => !keep.has(id)).sort();
34152
34585
  }
34586
+ const KEPT_ON_REMOVAL$1 = [
34587
+ "EngineVersion",
34588
+ "CacheParameterGroupName",
34589
+ "PreferredMaintenanceWindow",
34590
+ "SnapshotWindow",
34591
+ "IpDiscovery",
34592
+ "SnapshotRetentionLimit",
34593
+ "AutoMinorVersionUpgrade",
34594
+ "NotificationTopicArn",
34595
+ "VpcSecurityGroupIds",
34596
+ "TransitEncryptionEnabled",
34597
+ "PreferredAvailabilityZone"
34598
+ ];
34599
+ const NOT_MODIFIABLE = /* @__PURE__ */ new Set(["TransitEncryptionEnabled", "PreferredAvailabilityZone"]);
34600
+ const PLACEMENT_ON_REMOVAL = ["AZMode", "PreferredAvailabilityZones"];
34601
+ const removalWarnings = (logicalId, kept, placement, caller) => {
34602
+ const lines = [];
34603
+ const head = (names) => safeMsg`${logicalId} (AWS::ElastiCache::CacheCluster): ${names.length === 1 ? "property" : "properties"} ${names.join(", ")}`;
34604
+ if (kept.length > 0) {
34605
+ const one = kept.length === 1;
34606
+ const fixed = kept.filter((name) => NOT_MODIFIABLE.has(name));
34607
+ const replaceNote = fixed.length === 0 ? "" : safeMsg` (${fixed.join(", ")} ${fixed.length === 1 ? "changes" : "change"} only by replacing the cluster)`;
34608
+ lines.push(caller === "rollback" ? `${head(kept)} ${one ? "is" : "are"} absent from the state being restored; the rollback sends nothing for ${one ? "it" : "them"}, so the cluster keeps the value it holds now.` : `${head(kept)} ${one ? "was" : "were"} removed from the template and ${one ? "keeps its" : "keep their"} current AWS value, as CloudFormation leaves ${one ? "it" : "them"}; cdkd sends nothing for a removed property. To change a value, declare it explicitly${replaceNote}.`);
34609
+ }
34610
+ if (placement.length > 0) {
34611
+ const one = placement.length === 1;
34612
+ lines.push(caller === "rollback" ? `${head(placement)} ${one ? "is" : "are"} absent from the state being restored; the rollback leaves the cluster unchanged.` : `${head(placement)} ${one ? "was" : "were"} removed from the template; cdkd sends nothing for a removed property, so the nodes stay in their zones. CloudFormation updates a cross-az cluster, or a single-az one that keeps its zone list, in place. It replaces a memcached single-az cluster left with no zone, and cdkd plans that replacement too (go-to-k/cdkd#5558). To move the nodes, replace the cluster, for example by changing its logical ID.`);
34613
+ }
34614
+ return lines;
34615
+ };
34153
34616
  var ElastiCacheProvider = class {
34154
34617
  client;
34155
34618
  createClient;
@@ -34199,6 +34662,22 @@ var ElastiCacheProvider = class {
34199
34662
  "TransitEncryptionEnabled"
34200
34663
  ])]]);
34201
34664
  unhandledByDesign = /* @__PURE__ */ new Map([["AWS::ElastiCache::CacheCluster", /* @__PURE__ */ new Map([["CacheSecurityGroupNames", "EC2-Classic-only — use VpcSecurityGroupIds for VPC-deployed clusters (EC2-Classic retired 2022-08-15)"]])]]);
34665
+ removalHandledInUpdate = /* @__PURE__ */ new Map([["AWS::ElastiCache::CacheCluster", /* @__PURE__ */ new Set([
34666
+ "CacheSubnetGroupName",
34667
+ "ClusterName",
34668
+ "Engine",
34669
+ "NetworkType",
34670
+ "Port",
34671
+ "SnapshotName",
34672
+ "SnapshotArns",
34673
+ "CacheSecurityGroupNames",
34674
+ "CacheNodeType",
34675
+ "NumCacheNodes",
34676
+ "Tags",
34677
+ "LogDeliveryConfigurations",
34678
+ ...KEPT_ON_REMOVAL$1,
34679
+ ...PLACEMENT_ON_REMOVAL
34680
+ ])]]);
34202
34681
  getClient() {
34203
34682
  if (!this.client) {
34204
34683
  this.client = new ElastiCacheClient({
@@ -34228,7 +34707,7 @@ var ElastiCacheProvider = class {
34228
34707
  const mask = context?.maskSecrets;
34229
34708
  switch (resourceType) {
34230
34709
  case "AWS::ElastiCache::SubnetGroup": return this.updateSubnetGroup(logicalId, physicalId, resourceType, properties, previousProperties, mask);
34231
- case "AWS::ElastiCache::CacheCluster": return this.updateCacheCluster(logicalId, physicalId, resourceType, properties, previousProperties, mask);
34710
+ case "AWS::ElastiCache::CacheCluster": return this.updateCacheCluster(logicalId, physicalId, resourceType, properties, previousProperties, mask, context);
34232
34711
  default: throw new ProvisioningError(`Unsupported resource type: ${resourceType}`, resourceType, logicalId, physicalId);
34233
34712
  }
34234
34713
  }
@@ -34360,7 +34839,7 @@ var ElastiCacheProvider = class {
34360
34839
  throw thrown;
34361
34840
  }
34362
34841
  }
34363
- async updateCacheCluster(logicalId, physicalId, resourceType, properties, previousProperties, mask) {
34842
+ async updateCacheCluster(logicalId, physicalId, resourceType, properties, previousProperties, mask, context) {
34364
34843
  this.logger.debug(`Updating CacheCluster ${logicalId}: ${physicalId}`);
34365
34844
  refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, physicalId);
34366
34845
  try {
@@ -34399,6 +34878,7 @@ var ElastiCacheProvider = class {
34399
34878
  const described = await this.describeCacheCluster(physicalId);
34400
34879
  this.warnTransitEncryptionNotApplied(logicalId, properties, previousProperties, described?.TransitEncryptionEnabled);
34401
34880
  if (described?.ARN) await this.applyTagDiff(described.ARN, resourceType, logicalId, previousProperties["Tags"], properties["Tags"]);
34881
+ this.warnRemovalsLeftInPlace(logicalId, properties, previousProperties, context);
34402
34882
  const attributes = {};
34403
34883
  if (described?.CacheNodes?.[0]?.Endpoint) {
34404
34884
  const endpoint = described.CacheNodes[0].Endpoint;
@@ -34499,6 +34979,13 @@ var ElastiCacheProvider = class {
34499
34979
  if (notApplied.length === 0) return;
34500
34980
  this.logger.warn(safeMsg`CacheCluster ${logicalId}: the ${notApplied.join(", ")} change is not applied to the ` + "existing cluster (ModifyCacheCluster cannot change it, and CloudFormation leaves it unchanged too). To apply it, replace the cluster, for example by changing its logical ID.");
34501
34981
  }
34982
+ warnRemovalsLeftInPlace(logicalId, properties, previousProperties, context) {
34983
+ if (context?.desiredFromAwsReadback) return;
34984
+ const removed = context?.removedProperties;
34985
+ const wasRemoved = (key) => removed !== void 0 ? removed.has(key) : properties[key] === void 0 && previousProperties[key] !== void 0;
34986
+ const lines = removalWarnings(logicalId, KEPT_ON_REMOVAL$1.filter(wasRemoved), PLACEMENT_ON_REMOVAL.filter(wasRemoved), context?.replayingState ? "rollback" : "deploy");
34987
+ for (const line of lines) this.logger.warn(line);
34988
+ }
34502
34989
  buildLogDeliveryConfigurationsForUpdate(newConfigs, previousConfigs) {
34503
34990
  const kept = newConfigs ?? [];
34504
34991
  const keptLogTypes = new Set(kept.map((c) => c.LogType).filter((t) => t !== void 0));
@@ -35665,6 +36152,25 @@ const APPSYNC_APIKEY_ID_FORMAT = {
35665
36152
  label: "AppSync ApiKey",
35666
36153
  segments: ["apiId", "apiKeyId"]
35667
36154
  };
36155
+ const CFN_APPSYNC_ARN_RESOURCE_PATHS = {
36156
+ "AWS::AppSync::GraphQLApi": /^apis\/([^/|]+)$/,
36157
+ "AWS::AppSync::DataSource": /^apis\/([^/|]+)\/datasources\/([^/|]+)$/,
36158
+ "AWS::AppSync::Resolver": /^apis\/([^/|]+)\/types\/([^/|]+)\/resolvers\/([^/|]+)$/,
36159
+ "AWS::AppSync::ApiKey": /^apis\/([^/|]+)\/apikeys?\/([^/|]+)$/
36160
+ };
36161
+ function graphQLSchemaApiId(physicalId) {
36162
+ const schema = /^([a-z0-9]+)GraphQLSchema$/.exec(physicalId);
36163
+ return schema ? schema[1] : physicalId;
36164
+ }
36165
+ function appSyncPhysicalIdFromCfn(resourceType, logicalId, physicalId, region) {
36166
+ if (resourceType === "AWS::AppSync::GraphQLSchema") return graphQLSchemaApiId(physicalId);
36167
+ const pathPattern = CFN_APPSYNC_ARN_RESOURCE_PATHS[resourceType];
36168
+ const arn = /^arn:[^:]+:appsync:([^:]*):[^:]*:(.+)$/.exec(physicalId);
36169
+ const segments = pathPattern && arn ? pathPattern.exec(arn[2]) : null;
36170
+ if (!arn || !segments) return physicalId;
36171
+ if (canonicalizeRegion(arn[1]) !== canonicalizeRegion(region)) throw markNonRetryable(new ProvisioningError(safeMsg`${resourceType} ${physicalId} is in region ${arn[1]}, not the import region ${region}`, resourceType, logicalId, physicalId));
36172
+ return segments.slice(1).join("|");
36173
+ }
35668
36174
  const MUTABLE_GRAPHQL_API_CONFIG_PROPERTIES = [
35669
36175
  "UserPoolConfig",
35670
36176
  "OpenIDConnectConfig",
@@ -35804,7 +36310,7 @@ var AppSyncProvider = class {
35804
36310
  }
35805
36311
  if (resourceType === "AWS::AppSync::ApiKey" && parts.length === 2) {
35806
36312
  const [apiId, apiKeyId] = parts;
35807
- const apiKeyArn = await arn(`apis/${apiId}/apikey/${apiKeyId}`);
36313
+ const apiKeyArn = await arn(`apis/${apiId}/apikeys/${apiKeyId}`);
35808
36314
  return {
35809
36315
  ApiKey: apiKeyId,
35810
36316
  ...apiKeyArn && { Arn: apiKeyArn }
@@ -35953,12 +36459,13 @@ var AppSyncProvider = class {
35953
36459
  };
35954
36460
  }
35955
36461
  async updateGraphQLSchema(logicalId, physicalId, resourceType, properties, previousProperties, mask = maskerOrIdentity(void 0)) {
36462
+ const recordedApiId = graphQLSchemaApiId(physicalId);
35956
36463
  if (properties["ApiId"] !== void 0 && previousProperties["ApiId"] !== void 0 && properties["ApiId"] !== previousProperties["ApiId"] && !await unchangedBehindSecretReference({
35957
36464
  resourceType,
35958
36465
  key: "ApiId",
35959
36466
  desired: properties["ApiId"],
35960
36467
  previous: previousProperties["ApiId"],
35961
- physicalName: physicalId,
36468
+ physicalName: recordedApiId,
35962
36469
  maskSecrets: mask
35963
36470
  })) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "AWS AppSync GraphQLSchema.ApiId cannot move a schema to another API in place (CloudFormation fails a template change of it too) — deploy with --replace, or give the schema a new logical ID, to create it on the new API");
35964
36471
  const newDef = properties["Definition"];
@@ -35983,7 +36490,7 @@ var AppSyncProvider = class {
35983
36490
  physicalId,
35984
36491
  wasReplaced: false
35985
36492
  };
35986
- const apiId = properties["ApiId"] ?? physicalId;
36493
+ const apiId = properties["ApiId"] ?? recordedApiId;
35987
36494
  try {
35988
36495
  await this.getClient().send(new StartSchemaCreationCommand({
35989
36496
  apiId,
@@ -36907,7 +37414,7 @@ var AppSyncProvider = class {
36907
37414
  maskSecrets: context?.maskSecrets,
36908
37415
  ...context?.replayingState === true && { onRefusal: (message) => this.logger.warn(message) }
36909
37416
  });
36910
- const apiKeyArn = await this.buildAppSyncArnOrWarn(`apis/${apiId}/apikey/${apiKeyId}`, logicalId, physicalId);
37417
+ const apiKeyArn = await this.buildAppSyncArnOrWarn(`apis/${apiId}/apikeys/${apiKeyId}`, logicalId, physicalId);
36911
37418
  return {
36912
37419
  physicalId,
36913
37420
  attributes: {
@@ -36992,10 +37499,11 @@ var AppSyncProvider = class {
36992
37499
  }
36993
37500
  }
36994
37501
  async readGraphQLSchema(physicalId, properties) {
37502
+ const apiId = graphQLSchemaApiId(physicalId);
36995
37503
  let resp;
36996
37504
  try {
36997
37505
  resp = await this.getClient().send(new GetIntrospectionSchemaCommand({
36998
- apiId: physicalId,
37506
+ apiId,
36999
37507
  format: "SDL"
37000
37508
  }));
37001
37509
  } catch (err) {
@@ -37012,7 +37520,7 @@ var AppSyncProvider = class {
37012
37520
  if (await this.canonicalizeSdl(stateDefinition, "state") === canonicalAws) definitionToReturn = stateDefinition;
37013
37521
  }
37014
37522
  return {
37015
- ApiId: physicalId,
37523
+ ApiId: apiId,
37016
37524
  Definition: definitionToReturn
37017
37525
  };
37018
37526
  }
@@ -37253,14 +37761,18 @@ var AppSyncProvider = class {
37253
37761
  return RESOURCE_NOT_FOUND;
37254
37762
  }
37255
37763
  async import(input) {
37764
+ const known = input.knownPhysicalId && appSyncPhysicalIdFromCfn(input.resourceType, input.logicalId, input.knownPhysicalId, input.region);
37256
37765
  if (input.resourceType !== "AWS::AppSync::GraphQLApi") {
37257
- if (input.knownPhysicalId) return {
37258
- physicalId: input.knownPhysicalId,
37259
- attributes: await this.childImportAttributes(input.resourceType, input.knownPhysicalId, input.region)
37766
+ if (known) return {
37767
+ physicalId: known,
37768
+ attributes: await this.childImportAttributes(input.resourceType, known, input.region)
37260
37769
  };
37261
37770
  return null;
37262
37771
  }
37263
- const explicit = resolveExplicitPhysicalId(input, null);
37772
+ const explicit = resolveExplicitPhysicalId(known ? {
37773
+ ...input,
37774
+ knownPhysicalId: known
37775
+ } : input, null);
37264
37776
  if (explicit) try {
37265
37777
  const response = await this.getClient().send(new GetGraphqlApiCommand({ apiId: explicit }));
37266
37778
  return {
@@ -43077,7 +43589,7 @@ var EFSProvider = class {
43077
43589
  const log = createMaskedLogSinks(this.logger, context?.maskSecrets);
43078
43590
  properties = withRemovalDefaults(this.removalDefaults, resourceType, properties, previousProperties, context);
43079
43591
  switch (resourceType) {
43080
- case "AWS::EFS::FileSystem": return this.updateFileSystem(logicalId, physicalId, resourceType, properties, previousProperties, log);
43592
+ case "AWS::EFS::FileSystem": return this.updateFileSystem(logicalId, physicalId, resourceType, properties, previousProperties, log, context?.replayingState === true || context?.desiredFromAwsReadback === true);
43081
43593
  case "AWS::EFS::MountTarget": return this.updateMountTarget(logicalId, physicalId, resourceType, properties, log);
43082
43594
  case "AWS::EFS::AccessPoint": return this.updateAccessPoint(logicalId, physicalId, resourceType, properties, previousProperties, log);
43083
43595
  default: throw new ProvisioningError(`Unsupported resource type: ${resourceType}`, resourceType, logicalId, physicalId);
@@ -43125,7 +43637,7 @@ var EFSProvider = class {
43125
43637
  throw this.wrapMaskedError(log, error, (text) => new ProvisioningError(`Failed to update EFS AccessPoint ${logicalId}: ${text}`, resourceType, logicalId, physicalId, cause));
43126
43638
  }
43127
43639
  }
43128
- async updateFileSystem(logicalId, physicalId, resourceType, properties, previousProperties, log) {
43640
+ async updateFileSystem(logicalId, physicalId, resourceType, properties, previousProperties, log, stateBorneDesired) {
43129
43641
  for (const key of [
43130
43642
  "Encrypted",
43131
43643
  "KmsKeyId",
@@ -43140,8 +43652,13 @@ var EFSProvider = class {
43140
43652
  const newProvisioned = properties["ProvisionedThroughputInMibps"];
43141
43653
  const oldThroughputMode = previousProperties["ThroughputMode"];
43142
43654
  const oldProvisioned = previousProperties["ProvisionedThroughputInMibps"];
43655
+ const throughputValueMissing = newThroughputMode === "provisioned" && newProvisioned === void 0 && (oldProvisioned !== void 0 || oldThroughputMode !== "provisioned");
43656
+ if (throughputValueMissing) {
43657
+ if (!stateBorneDesired) throw new ProvisioningError(`Failed to update EFS FileSystem ${logicalId}: Throughput value must be specified for provisioned throughput mode. The template sets ThroughputMode: provisioned without ProvisionedThroughputInMibps, which CloudFormation rejects too. Set ProvisionedThroughputInMibps, or change ThroughputMode (e.g. to bursting or elastic).`, resourceType, logicalId, physicalId);
43658
+ log.warn(`EFS FileSystem ${logicalId}: the desired properties (from cdkd state or an AWS readback, not the template) set ThroughputMode: provisioned without ProvisionedThroughputInMibps, which AWS rejects; leaving the file system's throughput as it is on AWS and applying the rest of the update. Its throughput may now differ from the record: run cdkd drift to see it.`);
43659
+ }
43143
43660
  const effectiveThroughputMode = newThroughputMode === void 0 && newProvisioned === void 0 && oldThroughputMode === "provisioned" ? "bursting" : newThroughputMode;
43144
- const throughputModeChanged = effectiveThroughputMode !== void 0 && effectiveThroughputMode !== oldThroughputMode;
43661
+ const throughputModeChanged = !throughputValueMissing && effectiveThroughputMode !== void 0 && effectiveThroughputMode !== oldThroughputMode;
43145
43662
  const provisionedChanged = newProvisioned !== void 0 && newProvisioned !== oldProvisioned;
43146
43663
  const changed = (key) => JSON.stringify(properties[key]) !== JSON.stringify(previousProperties[key]);
43147
43664
  const lifecycleChanged = changed("LifecyclePolicies");
@@ -43967,7 +44484,7 @@ const cfnKeepsOnRemoval = (name, shape, removed) => {
43967
44484
  if (narrow) return narrow(shape, removed);
43968
44485
  return !cfnRefusesRemoval(name, shape) && !shape.storageTypes.includes("INTELLIGENT_TIERING") && (CFN_KEEPS_ON_REMOVAL.has(name) || typeof shape.fileSystemType === "string" && CFN_KEEPS_TOP_LEVEL_ON_REMOVAL.get(shape.fileSystemType)?.has(name) === true);
43969
44486
  };
43970
- const leftInPlaceWarning$2 = (logicalId, names, caller, shape) => {
44487
+ const leftInPlaceWarning$3 = (logicalId, names, caller, shape) => {
43971
44488
  const one = names.length === 1;
43972
44489
  const subject = one ? "property" : "properties";
43973
44490
  const verb = one ? "is" : "are";
@@ -44331,7 +44848,7 @@ var FSxFileSystemProvider = class {
44331
44848
  const leftInPlaceNames = [...TOP_LEVEL_LEFT_IN_PLACE_PROPS.filter((key) => properties[key] === void 0 && previousProperties[key] !== void 0), ...leftInPlace.map((key) => `${variantConfigKey}.${key}`)];
44332
44849
  const warnLeftInPlace = () => {
44333
44850
  if (leftInPlaceNames.length === 0 || context?.desiredFromAwsReadback) return;
44334
- this.logger.warn(leftInPlaceWarning$2(logicalId, leftInPlaceNames, context?.replayingState ? "rollback" : "deploy", {
44851
+ this.logger.warn(leftInPlaceWarning$3(logicalId, leftInPlaceNames, context?.replayingState ? "rollback" : "deploy", {
44335
44852
  fileSystemType: properties["FileSystemType"] ?? previousProperties["FileSystemType"],
44336
44853
  storageTypes: [previousProperties["StorageType"], properties["StorageType"]],
44337
44854
  deploymentTypes: [previousProperties, properties].map((side) => variantConfigKey ? side[variantConfigKey]?.["DeploymentType"] : void 0),
@@ -45487,7 +46004,7 @@ const toNumber$1 = (v) => {
45487
46004
  };
45488
46005
  const jsonEqual$1 = (a, b) => JSON.stringify(a) === JSON.stringify(b);
45489
46006
  const LEFT_IN_PLACE_ON_REMOVAL$1 = ["ResizeSpecifications", "InstanceTypeConfigs"];
45490
- const leftInPlaceWarning$1 = (logicalId, names, caller) => {
46007
+ const leftInPlaceWarning$2 = (logicalId, names, caller) => {
45491
46008
  const one = names.length === 1;
45492
46009
  const subject = one ? "property" : "properties";
45493
46010
  const verb = one ? "is" : "are";
@@ -45676,7 +46193,7 @@ var EMRInstanceFleetConfigProvider = class {
45676
46193
  const leftInPlaceNames = LEFT_IN_PLACE_ON_REMOVAL$1.filter((key) => removed !== void 0 ? removed.has(key) : properties[key] === void 0 && previousProperties[key] !== void 0);
45677
46194
  const warnLeftInPlace = () => {
45678
46195
  if (leftInPlaceNames.length === 0 || context?.desiredFromAwsReadback) return;
45679
- this.logger.warn(leftInPlaceWarning$1(logicalId, leftInPlaceNames, context?.replayingState ? "rollback" : "deploy"));
46196
+ this.logger.warn(leftInPlaceWarning$2(logicalId, leftInPlaceNames, context?.replayingState ? "rollback" : "deploy"));
45680
46197
  };
45681
46198
  const leftInPlace = new Set(LEFT_IN_PLACE_ON_REMOVAL$1);
45682
46199
  if (![...MUTABLE].some((k) => changed(k) && !(leftInPlace.has(k) && properties[k] === void 0))) {
@@ -45837,7 +46354,7 @@ const MUTABLE_TOP_LEVEL_PROPS = /* @__PURE__ */ new Set([
45837
46354
  "AutoTerminationPolicy"
45838
46355
  ]);
45839
46356
  const LEFT_IN_PLACE_ON_REMOVAL = ["StepConcurrencyLevel"];
45840
- const leftInPlaceWarning = (logicalId, names, caller) => {
46357
+ const leftInPlaceWarning$1 = (logicalId, names, caller) => {
45841
46358
  const one = names.length === 1;
45842
46359
  const subject = one ? "property" : "properties";
45843
46360
  const verb = one ? "is" : "are";
@@ -46398,7 +46915,7 @@ var EMRClusterProvider = class {
46398
46915
  const leftInPlaceNames = LEFT_IN_PLACE_ON_REMOVAL.filter((key) => removed !== void 0 ? removed.has(key) : properties[key] === void 0 && previousProperties[key] !== void 0);
46399
46916
  const warnLeftInPlace = () => {
46400
46917
  if (leftInPlaceNames.length === 0 || context?.desiredFromAwsReadback) return;
46401
- this.logger.warn(leftInPlaceWarning(logicalId, leftInPlaceNames, context?.replayingState ? "rollback" : "deploy"));
46918
+ this.logger.warn(leftInPlaceWarning$1(logicalId, leftInPlaceNames, context?.replayingState ? "rollback" : "deploy"));
46402
46919
  };
46403
46920
  const visibleChanged = changed("VisibleToAllUsers");
46404
46921
  const stepConcurrencyChanged = changed("StepConcurrencyLevel") && properties["StepConcurrencyLevel"] !== void 0;
@@ -48057,6 +48574,19 @@ function withoutTrailIdentifiers(text, physicalId) {
48057
48574
  }
48058
48575
  return out;
48059
48576
  }
48577
+ function removalsLeftInPlace(properties, previousProperties, context, globalEventsResetSkipped) {
48578
+ if (context?.desiredFromAwsReadback) return [];
48579
+ const removed = context?.removedProperties;
48580
+ const wasRemoved = (key) => previousProperties[key] != null && properties[key] == null && (removed === void 0 || removed.has(key));
48581
+ const org = previousProperties["IsOrganizationTrail"];
48582
+ const globalEvents = previousProperties["IncludeGlobalServiceEvents"];
48583
+ return [...wasRemoved("IsOrganizationTrail") && org !== false && org !== "false" ? ["IsOrganizationTrail"] : [], ...globalEventsResetSkipped && wasRemoved("IncludeGlobalServiceEvents") && globalEvents !== false && globalEvents !== "false" ? ["IncludeGlobalServiceEvents"] : []];
48584
+ }
48585
+ function leftInPlaceWarning(logicalId, names, caller) {
48586
+ const one = names.length === 1;
48587
+ const subject = one ? "property" : "properties";
48588
+ return caller === "rollback" ? safeMsg`${logicalId} (AWS::CloudTrail::Trail): ${subject} ${names.join(", ")} ${one ? "is" : "are"} absent from the state being restored; UpdateTrail keeps a field it is not sent, so the rollback leaves the value the failed deploy applied in place.` : safeMsg`${logicalId} (AWS::CloudTrail::Trail): ${subject} ${names.join(", ")} ${one ? "was" : "were"} removed from the template; cdkd leaves the current AWS value in place (whether CloudFormation resets it is unmeasured). Declare the intended value explicitly to change it.`;
48589
+ }
48060
48590
  var CloudTrailProvider = class {
48061
48591
  client;
48062
48592
  createClient;
@@ -48072,6 +48602,23 @@ var CloudTrailProvider = class {
48072
48602
  return error instanceof Error ? markRedactedCause(wrapped) : wrapped;
48073
48603
  }
48074
48604
  removalDefaults = /* @__PURE__ */ new Map([["AWS::CloudTrail::Trail", /* @__PURE__ */ new Map([["IsMultiRegionTrail", false], ["EnableLogFileValidation", false]])]]);
48605
+ removalHandledInUpdate = /* @__PURE__ */ new Map([["AWS::CloudTrail::Trail", /* @__PURE__ */ new Set([
48606
+ "S3BucketName",
48607
+ "IsLogging",
48608
+ "TrailName",
48609
+ "S3KeyPrefix",
48610
+ "SnsTopicName",
48611
+ "KMSKeyId",
48612
+ "CloudWatchLogsLogGroupArn",
48613
+ "CloudWatchLogsRoleArn",
48614
+ "EventSelectors",
48615
+ "AdvancedEventSelectors",
48616
+ "InsightSelectors",
48617
+ "AggregationConfigurations",
48618
+ "Tags",
48619
+ "IncludeGlobalServiceEvents",
48620
+ "IsOrganizationTrail"
48621
+ ])]]);
48075
48622
  handledProperties = /* @__PURE__ */ new Map([["AWS::CloudTrail::Trail", /* @__PURE__ */ new Set([
48076
48623
  "S3BucketName",
48077
48624
  "TrailName",
@@ -48201,7 +48748,8 @@ var CloudTrailProvider = class {
48201
48748
  const s3BucketName = properties["S3BucketName"];
48202
48749
  const s3KeyPrefix = clearOnUpdateRemoval(emptyToUndefined(properties["S3KeyPrefix"]), emptyToUndefined(previousProperties["S3KeyPrefix"]), "");
48203
48750
  const isMultiRegionTrail = properties["IsMultiRegionTrail"];
48204
- const includeGlobalServiceEvents = isMultiRegionTrail === false ? clearOnUpdateRemoval(properties["IncludeGlobalServiceEvents"], previousProperties["IncludeGlobalServiceEvents"], false) : properties["IncludeGlobalServiceEvents"];
48751
+ const globalEventsResetSkipped = isMultiRegionTrail !== false;
48752
+ const includeGlobalServiceEvents = globalEventsResetSkipped ? properties["IncludeGlobalServiceEvents"] : clearOnUpdateRemoval(properties["IncludeGlobalServiceEvents"], previousProperties["IncludeGlobalServiceEvents"], false);
48205
48753
  const enableLogFileValidation = properties["EnableLogFileValidation"];
48206
48754
  const isLogging = properties["IsLogging"];
48207
48755
  const cwPair = resolveCloudWatchLogsPair(properties);
@@ -48226,6 +48774,8 @@ var CloudTrailProvider = class {
48226
48774
  SnsTopicName: snsTopicName,
48227
48775
  IsOrganizationTrail: isOrganizationTrail
48228
48776
  }));
48777
+ const keptNames = removalsLeftInPlace(properties, previousProperties, context, globalEventsResetSkipped);
48778
+ if (keptNames.length > 0) this.logger.warn(leftInPlaceWarning(logicalId, keptNames, context?.replayingState ? "rollback" : "deploy"));
48229
48779
  const basicRead = readListBlock(properties["EventSelectors"], "AWS::CloudTrail::Trail EventSelectors");
48230
48780
  const advancedRead = readListBlock(properties["AdvancedEventSelectors"], "AWS::CloudTrail::Trail AdvancedEventSelectors");
48231
48781
  for (const read of [basicRead, advancedRead]) if (read.kind === "unusable") this.logger.warn(safeMsg`${read.detail} The trail's existing event selectors are left untouched for this update rather than reset to the AWS default.`);
@@ -48642,7 +49192,8 @@ var CodeBuildProvider = class {
48642
49192
  batchReportMode: cfnBuildBatchConfig["BatchReportMode"],
48643
49193
  restrictions: restrictions ? {
48644
49194
  maximumBuildsAllowed: restrictions["MaximumBuildsAllowed"],
48645
- computeTypesAllowed: restrictions["ComputeTypesAllowed"]
49195
+ computeTypesAllowed: restrictions["ComputeTypesAllowed"],
49196
+ fleetsAllowed: restrictions["FleetsAllowed"]
48646
49197
  } : void 0
48647
49198
  };
48648
49199
  }
@@ -48951,6 +49502,7 @@ var CodeBuildProvider = class {
48951
49502
  const r = {};
48952
49503
  if (project.buildBatchConfig.restrictions.maximumBuildsAllowed !== void 0) r["MaximumBuildsAllowed"] = project.buildBatchConfig.restrictions.maximumBuildsAllowed;
48953
49504
  if (project.buildBatchConfig.restrictions.computeTypesAllowed !== void 0) r["ComputeTypesAllowed"] = project.buildBatchConfig.restrictions.computeTypesAllowed;
49505
+ if (project.buildBatchConfig.restrictions.fleetsAllowed !== void 0) r["FleetsAllowed"] = project.buildBatchConfig.restrictions.fleetsAllowed;
48954
49506
  bbc["Restrictions"] = r;
48955
49507
  }
48956
49508
  if (project.buildBatchConfig.timeoutInMins !== void 0) bbc["TimeoutInMins"] = project.buildBatchConfig.timeoutInMins;
@@ -49519,6 +50071,28 @@ var CodeCommitRepositoryProvider = class {
49519
50071
 
49520
50072
  //#endregion
49521
50073
  //#region src/provisioning/providers/dlm-lifecycle-policy-provider.ts
50074
+ const KEPT_ON_REMOVAL = [
50075
+ "Description",
50076
+ "ExecutionRoleArn",
50077
+ "State",
50078
+ "PolicyDetails",
50079
+ "CreateInterval",
50080
+ "RetainInterval",
50081
+ "CopyTags",
50082
+ "ExtendDeletion",
50083
+ "CrossRegionCopyTargets",
50084
+ "Exclusions"
50085
+ ];
50086
+ function keptRemovedNames(properties, previousProperties, context) {
50087
+ if (context?.desiredFromAwsReadback) return [];
50088
+ const removed = context?.removedProperties;
50089
+ return KEPT_ON_REMOVAL.filter((key) => previousProperties[key] != null && properties[key] == null && (removed === void 0 || removed.has(key) || properties[key] === null));
50090
+ }
50091
+ const keptOnRemovalWarning = (logicalId, names, caller) => {
50092
+ const one = names.length === 1;
50093
+ const subject = one ? "property" : "properties";
50094
+ return caller === "rollback" ? safeMsg`${logicalId} (AWS::DLM::LifecyclePolicy): ${subject} ${names.join(", ")} ${one ? "is" : "are"} absent from the state being restored; UpdateLifecyclePolicy keeps a field it is not sent, so the rollback leaves the value the failed deploy applied in place.` : safeMsg`${logicalId} (AWS::DLM::LifecyclePolicy): ${subject} ${names.join(", ")} ${one ? "was" : "were"} removed from the template and ${one ? "keeps its" : "keep their"} current AWS value, as CloudFormation leaves ${one ? "it" : "them"}; UpdateLifecyclePolicy keeps a field it is not sent. Declare the intended value explicitly to change it.`;
50095
+ };
49522
50096
  const createLifecyclePolicyLatch = new AmbiguousCreateLatch("dlm:CreateLifecyclePolicy");
49523
50097
  const policiesCreatedByThisProcess = new RecentIdSet();
49524
50098
  var DLMLifecyclePolicyProvider = class {
@@ -49548,6 +50122,11 @@ var DLMLifecyclePolicyProvider = class {
49548
50122
  "CrossRegionCopyTargets",
49549
50123
  "Exclusions"
49550
50124
  ])]]);
50125
+ removalHandledInUpdate = /* @__PURE__ */ new Map([["AWS::DLM::LifecyclePolicy", /* @__PURE__ */ new Set([
50126
+ ...KEPT_ON_REMOVAL,
50127
+ "Tags",
50128
+ "DefaultPolicy"
50129
+ ])]]);
49551
50130
  getClient() {
49552
50131
  if (!this.client) this.client = new DLMClient({
49553
50132
  ...ambientClientDefaults(),
@@ -49672,6 +50251,8 @@ var DLMLifecyclePolicyProvider = class {
49672
50251
  ...properties["CreateInterval"] != null && { CreateInterval: Number(properties["CreateInterval"]) },
49673
50252
  ...properties["RetainInterval"] != null && { RetainInterval: Number(properties["RetainInterval"]) }
49674
50253
  }));
50254
+ const keptNames = keptRemovedNames(properties, previousProperties, context);
50255
+ if (keptNames.length > 0) this.logger.warn(keptOnRemovalWarning(logicalId, keptNames, context?.replayingState ? "rollback" : "deploy"));
49675
50256
  const plan = planTagDiff(previousProperties["Tags"], properties["Tags"]);
49676
50257
  const tagWarning = tagPlanWarning(plan, resourceType, logicalId);
49677
50258
  if (tagWarning !== void 0) this.logger.warn(tagWarning);
@@ -50875,6 +51456,173 @@ function tableIdentityFromGetTable(tableARN, namespace, name) {
50875
51456
  name
50876
51457
  };
50877
51458
  }
51459
+ function isCfnObject(value) {
51460
+ return value !== null && typeof value === "object" && !Array.isArray(value);
51461
+ }
51462
+ function desiredObject(properties, key, resourceType, logicalId, physicalId) {
51463
+ const value = properties[key];
51464
+ if (value === void 0) return void 0;
51465
+ if (isCfnObject(value)) return value;
51466
+ throw new ProvisioningError(`${key} for ${resourceType} ${logicalId} must be an object; refusing before any call`, resourceType, logicalId, physicalId);
51467
+ }
51468
+ function recordedObject(properties, key) {
51469
+ const value = properties[key];
51470
+ return isCfnObject(value) ? value : void 0;
51471
+ }
51472
+ var NotAnInteger = class extends Error {
51473
+ member;
51474
+ constructor(member) {
51475
+ super(`${member} must be an integer`);
51476
+ this.member = member;
51477
+ }
51478
+ };
51479
+ function integer(value, member) {
51480
+ if (value === void 0) return void 0;
51481
+ const n = typeof value === "number" ? value : typeof value === "string" && value.trim() !== "" ? Number(value) : NaN;
51482
+ if (Number.isInteger(n)) return n;
51483
+ throw new NotAnInteger(member);
51484
+ }
51485
+ function refuseNonIntegers(convert, key, resourceType, logicalId, physicalId) {
51486
+ try {
51487
+ return convert();
51488
+ } catch (error) {
51489
+ if (!(error instanceof NotAnInteger)) throw error;
51490
+ throw new ProvisioningError(`${key}.${error.member} for ${resourceType} ${logicalId} must be an integer; refusing before any call`, resourceType, logicalId, physicalId, error);
51491
+ }
51492
+ }
51493
+ function list(value) {
51494
+ return Array.isArray(value) ? value : void 0;
51495
+ }
51496
+ function defined(value) {
51497
+ return Object.fromEntries(Object.entries(value).filter(([, v]) => v !== void 0));
51498
+ }
51499
+ function maintenanceStatus(value) {
51500
+ return typeof value === "string" ? value.toLowerCase() : void 0;
51501
+ }
51502
+ function sdkEncryption(cfn) {
51503
+ return defined({
51504
+ sseAlgorithm: cfn["SSEAlgorithm"],
51505
+ kmsKeyArn: cfn["KMSKeyArn"]
51506
+ });
51507
+ }
51508
+ function sdkStorageClass(cfn) {
51509
+ return defined({ storageClass: cfn["StorageClass"] });
51510
+ }
51511
+ function sdkReplication(cfn) {
51512
+ return defined({
51513
+ role: cfn["Role"],
51514
+ rules: list(cfn["Rules"])?.map((rule) => defined({ destinations: list(isCfnObject(rule) ? rule["Destinations"] : void 0)?.map((destination) => defined({ destinationTableBucketARN: isCfnObject(destination) ? destination["DestinationTableBucketARN"] : void 0 })) }))
51515
+ });
51516
+ }
51517
+ function sdkUnreferencedFileRemoval(cfn) {
51518
+ const unreferencedDays = integer(cfn["UnreferencedDays"], "UnreferencedDays");
51519
+ const nonCurrentDays = integer(cfn["NoncurrentDays"], "NoncurrentDays");
51520
+ return defined({
51521
+ status: maintenanceStatus(cfn["Status"]),
51522
+ settings: unreferencedDays === void 0 && nonCurrentDays === void 0 ? void 0 : { icebergUnreferencedFileRemoval: defined({
51523
+ unreferencedDays,
51524
+ nonCurrentDays
51525
+ }) }
51526
+ });
51527
+ }
51528
+ function sdkCompaction(cfn) {
51529
+ const targetFileSizeMB = integer(cfn["TargetFileSizeMB"], "TargetFileSizeMB");
51530
+ return defined({
51531
+ status: maintenanceStatus(cfn["Status"]),
51532
+ settings: targetFileSizeMB === void 0 ? void 0 : { icebergCompaction: { targetFileSizeMB } }
51533
+ });
51534
+ }
51535
+ function sdkSnapshotManagement(cfn) {
51536
+ const minSnapshotsToKeep = integer(cfn["MinSnapshotsToKeep"], "MinSnapshotsToKeep");
51537
+ const maxSnapshotAgeHours = integer(cfn["MaxSnapshotAgeHours"], "MaxSnapshotAgeHours");
51538
+ return defined({
51539
+ status: maintenanceStatus(cfn["Status"]),
51540
+ settings: minSnapshotsToKeep === void 0 && maxSnapshotAgeHours === void 0 ? void 0 : { icebergSnapshotManagement: defined({
51541
+ minSnapshotsToKeep,
51542
+ maxSnapshotAgeHours
51543
+ }) }
51544
+ });
51545
+ }
51546
+ function mapObjects(value, map) {
51547
+ return list(value)?.map((element) => map(isCfnObject(element) ? element : {}));
51548
+ }
51549
+ function sdkIcebergMetadata(cfn) {
51550
+ const schema = isCfnObject(cfn["IcebergSchema"]) ? cfn["IcebergSchema"] : void 0;
51551
+ const schemaV2 = isCfnObject(cfn["IcebergSchemaV2"]) ? cfn["IcebergSchemaV2"] : void 0;
51552
+ const partitionSpec = isCfnObject(cfn["IcebergPartitionSpec"]) ? cfn["IcebergPartitionSpec"] : void 0;
51553
+ const sortOrder = isCfnObject(cfn["IcebergSortOrder"]) ? cfn["IcebergSortOrder"] : void 0;
51554
+ return defined({
51555
+ schema: schema && defined({ fields: mapObjects(schema["SchemaFieldList"], (f) => defined({
51556
+ id: integer(f["Id"], "IcebergSchema.SchemaFieldList.Id"),
51557
+ name: f["Name"],
51558
+ type: f["Type"],
51559
+ required: f["Required"]
51560
+ })) }),
51561
+ schemaV2: schemaV2 && defined({
51562
+ type: schemaV2["SchemaV2FieldType"],
51563
+ fields: mapObjects(schemaV2["SchemaV2FieldList"], (f) => defined({
51564
+ id: integer(f["Id"], "IcebergSchemaV2.SchemaV2FieldList.Id"),
51565
+ name: f["Name"],
51566
+ type: f["Type"],
51567
+ required: f["Required"],
51568
+ doc: f["Doc"]
51569
+ })),
51570
+ schemaId: integer(schemaV2["SchemaId"], "IcebergSchemaV2.SchemaId"),
51571
+ identifierFieldIds: list(schemaV2["IdentifierFieldIds"])?.map((id) => integer(id, "IcebergSchemaV2.IdentifierFieldIds"))
51572
+ }),
51573
+ partitionSpec: partitionSpec && defined({
51574
+ fields: mapObjects(partitionSpec["Fields"], (f) => defined({
51575
+ sourceId: integer(f["SourceId"], "IcebergPartitionSpec.Fields.SourceId"),
51576
+ transform: f["Transform"],
51577
+ name: f["Name"],
51578
+ fieldId: integer(f["FieldId"], "IcebergPartitionSpec.Fields.FieldId")
51579
+ })),
51580
+ specId: integer(partitionSpec["SpecId"], "IcebergPartitionSpec.SpecId")
51581
+ }),
51582
+ writeOrder: sortOrder && defined({
51583
+ orderId: integer(sortOrder["OrderId"], "IcebergSortOrder.OrderId"),
51584
+ fields: mapObjects(sortOrder["Fields"], (f) => defined({
51585
+ sourceId: integer(f["SourceId"], "IcebergSortOrder.Fields.SourceId"),
51586
+ transform: f["Transform"],
51587
+ direction: f["Direction"],
51588
+ nullOrder: f["NullOrder"]
51589
+ }))
51590
+ }),
51591
+ properties: isCfnObject(cfn["TableProperties"]) ? cfn["TableProperties"] : void 0
51592
+ });
51593
+ }
51594
+ const UPDATABLE_CONFIG_KEYS = {
51595
+ "AWS::S3Tables::TableBucket": [
51596
+ "EncryptionConfiguration",
51597
+ "StorageClassConfiguration",
51598
+ "MetricsConfiguration",
51599
+ "UnreferencedFileRemoval",
51600
+ "ReplicationConfiguration"
51601
+ ],
51602
+ "AWS::S3Tables::Table": ["Compaction", "SnapshotManagement"]
51603
+ };
51604
+ function metricsEnabled(metrics, resourceType, logicalId, physicalId) {
51605
+ const status = metrics?.["Status"];
51606
+ if (status === void 0 || status === "Disabled") return false;
51607
+ if (status === "Enabled") return true;
51608
+ throw new ProvisioningError(safeMsg`MetricsConfiguration.Status for ${resourceType} ${logicalId} must be 'Enabled' or 'Disabled'; refusing before any call`, resourceType, logicalId, physicalId);
51609
+ }
51610
+ const TABLE_MAINTENANCE = [[
51611
+ "Compaction",
51612
+ "icebergCompaction",
51613
+ sdkCompaction
51614
+ ], [
51615
+ "SnapshotManagement",
51616
+ "icebergSnapshotManagement",
51617
+ sdkSnapshotManagement
51618
+ ]];
51619
+ const INTEGER_BEARING_CONFIGS = {
51620
+ "AWS::S3Tables::TableBucket": [["UnreferencedFileRemoval", sdkUnreferencedFileRemoval]],
51621
+ "AWS::S3Tables::Table": TABLE_MAINTENANCE.map(([key, , toSdk]) => [key, toSdk])
51622
+ };
51623
+ function cfnBucketStatus(status) {
51624
+ return status === void 0 ? void 0 : `${status.charAt(0).toUpperCase()}${status.slice(1)}`;
51625
+ }
50878
51626
  function sentence(text) {
50879
51627
  return text.endsWith(".") ? text : `${text}.`;
50880
51628
  }
@@ -50891,7 +51639,15 @@ var S3TablesProvider = class {
50891
51639
  return markRedactedCause(build(`${m(failure.summary)}${relayedNameCollision(failure.detail)}`));
50892
51640
  }
50893
51641
  handledProperties = /* @__PURE__ */ new Map([
50894
- ["AWS::S3Tables::TableBucket", /* @__PURE__ */ new Set(["TableBucketName", "Tags"])],
51642
+ ["AWS::S3Tables::TableBucket", /* @__PURE__ */ new Set([
51643
+ "TableBucketName",
51644
+ "Tags",
51645
+ "EncryptionConfiguration",
51646
+ "StorageClassConfiguration",
51647
+ "MetricsConfiguration",
51648
+ "UnreferencedFileRemoval",
51649
+ "ReplicationConfiguration"
51650
+ ])],
50895
51651
  ["AWS::S3Tables::Namespace", /* @__PURE__ */ new Set(["TableBucketARN", "Namespace"])],
50896
51652
  ["AWS::S3Tables::Table", /* @__PURE__ */ new Set([
50897
51653
  "TableBucketARN",
@@ -50900,9 +51656,24 @@ var S3TablesProvider = class {
50900
51656
  "Name",
50901
51657
  "OpenTableFormat",
50902
51658
  "Format",
50903
- "Tags"
51659
+ "Tags",
51660
+ "IcebergMetadata",
51661
+ "StorageClassConfiguration",
51662
+ "Compaction",
51663
+ "SnapshotManagement",
51664
+ "WithoutMetadata"
50904
51665
  ])]
50905
51666
  ]);
51667
+ getDriftUnknownPaths(resourceType) {
51668
+ return resourceType === "AWS::S3Tables::Table" ? [
51669
+ "IcebergMetadata",
51670
+ "StorageClassConfiguration",
51671
+ "WithoutMetadata"
51672
+ ] : [];
51673
+ }
51674
+ getDriftAbsentMeansDefaultKeys(resourceType, properties) {
51675
+ return resourceType === "AWS::S3Tables::TableBucket" && properties["ReplicationConfiguration"] === void 0 ? ["ReplicationConfiguration"] : [];
51676
+ }
50906
51677
  getClient() {
50907
51678
  if (!this.client) {
50908
51679
  this.client = new S3TablesClient({
@@ -50931,18 +51702,25 @@ var S3TablesProvider = class {
50931
51702
  async update(logicalId, physicalId, resourceType, properties, previousProperties, context) {
50932
51703
  assertRegionMatch(context?.expectedRegion ? await this.getClient().config.region() : void 0, context?.expectedRegion, resourceType, logicalId, physicalId, "pre-update");
50933
51704
  if (resourceType === "AWS::S3Tables::Table" || resourceType === "AWS::S3Tables::TableBucket") refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, physicalId);
51705
+ for (const key of UPDATABLE_CONFIG_KEYS[resourceType] ?? []) desiredObject(properties, key, resourceType, logicalId, physicalId);
51706
+ for (const [key, convert] of INTEGER_BEARING_CONFIGS[resourceType] ?? []) {
51707
+ const value = desiredObject(properties, key, resourceType, logicalId, physicalId);
51708
+ if (value !== void 0) refuseNonIntegers(() => convert(value), key, resourceType, logicalId, physicalId);
51709
+ }
51710
+ if (resourceType === "AWS::S3Tables::TableBucket") metricsEnabled(recordedObject(properties, "MetricsConfiguration"), resourceType, logicalId, physicalId);
50934
51711
  try {
50935
- return await this.applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties, context?.maskSecrets, context?.recordedAttributes);
51712
+ return await this.applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties, context?.maskSecrets, context?.recordedAttributes, (key) => context?.markUnsettled?.(key));
50936
51713
  } catch (error) {
50937
51714
  if (error instanceof CdkdError) throw error;
50938
51715
  const cause = error instanceof Error ? error : void 0;
50939
51716
  throw this.wrapCaughtError(context?.maskSecrets, error, (text) => new ProvisioningError(`Failed to update S3 Tables resource ${logicalId}: ${text}`, resourceType, logicalId, physicalId, cause));
50940
51717
  }
50941
51718
  }
50942
- async applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties, mask, recordedAttributes) {
51719
+ async applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties, mask, recordedAttributes, markUnsettled) {
50943
51720
  if (resourceType === "AWS::S3Tables::Table") {
50944
51721
  const rename = await this.planTableRename(logicalId, physicalId, resourceType, properties, mask);
50945
51722
  await this.applyTableTagsDiff(logicalId, physicalId, resourceType, previousProperties["Tags"], properties["Tags"], mask);
51723
+ await this.applyTableMaintenanceUpdate(logicalId, physicalId, resourceType, properties, previousProperties, markUnsettled);
50946
51724
  if (rename === void 0) return {
50947
51725
  physicalId,
50948
51726
  wasReplaced: false
@@ -50957,8 +51735,10 @@ var S3TablesProvider = class {
50957
51735
  physicalId: rename.physicalId,
50958
51736
  wasReplaced: false
50959
51737
  };
50960
- } else if (resourceType === "AWS::S3Tables::TableBucket") await this.applyTableBucketTagsDiff(logicalId, physicalId, resourceType, previousProperties["Tags"], properties["Tags"], mask);
50961
- else this.logger.debug(`Update is no-op for ${resourceType} ${logicalId}`);
51738
+ } else if (resourceType === "AWS::S3Tables::TableBucket") {
51739
+ await this.applyTableBucketTagsDiff(logicalId, physicalId, resourceType, previousProperties["Tags"], properties["Tags"], mask);
51740
+ await this.applyTableBucketConfigUpdate(logicalId, physicalId, resourceType, properties, previousProperties, markUnsettled);
51741
+ } else this.logger.debug(`Update is no-op for ${resourceType} ${logicalId}`);
50962
51742
  return {
50963
51743
  physicalId,
50964
51744
  wasReplaced: false
@@ -50979,11 +51759,32 @@ var S3TablesProvider = class {
50979
51759
  const tableBucketName = properties["TableBucketName"];
50980
51760
  if (!tableBucketName) throw new ProvisioningError(`TableBucketName is required for S3 Table Bucket ${logicalId}`, resourceType, logicalId);
50981
51761
  const tags = this.tagListToSdkMap(desiredTags);
51762
+ const encryption = desiredObject(properties, "EncryptionConfiguration", resourceType, logicalId);
51763
+ const storageClass = desiredObject(properties, "StorageClassConfiguration", resourceType, logicalId);
51764
+ const metricsOn = metricsEnabled(desiredObject(properties, "MetricsConfiguration", resourceType, logicalId), resourceType, logicalId);
51765
+ const unreferenced = desiredObject(properties, "UnreferencedFileRemoval", resourceType, logicalId);
51766
+ const replication = desiredObject(properties, "ReplicationConfiguration", resourceType, logicalId);
51767
+ const unreferencedValue = unreferenced && refuseNonIntegers(() => sdkUnreferencedFileRemoval(unreferenced), "UnreferencedFileRemoval", resourceType, logicalId);
51768
+ let createdArn;
50982
51769
  try {
50983
51770
  const tableBucketARN = (await this.getCreateClient().send(new CreateTableBucketCommand({
50984
51771
  name: tableBucketName,
51772
+ ...encryption !== void 0 && { encryptionConfiguration: sdkEncryption(encryption) },
51773
+ ...storageClass !== void 0 && { storageClassConfiguration: sdkStorageClass(storageClass) },
50985
51774
  ...tags !== void 0 && { tags }
50986
51775
  }))).arn;
51776
+ createdArn = tableBucketARN;
51777
+ reportCreatedResource(logicalId, resourceType, tableBucketARN);
51778
+ if (metricsOn) await this.getClient().send(new PutTableBucketMetricsConfigurationCommand({ tableBucketARN }));
51779
+ if (unreferencedValue !== void 0) await this.getClient().send(new PutTableBucketMaintenanceConfigurationCommand({
51780
+ tableBucketARN,
51781
+ type: "icebergUnreferencedFileRemoval",
51782
+ value: unreferencedValue
51783
+ }));
51784
+ if (replication !== void 0) await this.getClient().send(new PutTableBucketReplicationCommand({
51785
+ tableBucketARN,
51786
+ configuration: sdkReplication(replication)
51787
+ }));
50987
51788
  this.logger.debug(`Successfully created S3 Table Bucket ${logicalId}: ${tableBucketARN}`);
50988
51789
  return {
50989
51790
  physicalId: tableBucketARN,
@@ -50991,7 +51792,104 @@ var S3TablesProvider = class {
50991
51792
  };
50992
51793
  } catch (error) {
50993
51794
  const cause = error instanceof Error ? error : void 0;
50994
- throw this.wrapCaughtError(context?.maskSecrets, error, (text) => new ProvisioningError(`Failed to create S3 Table Bucket ${logicalId}: ${text}`, resourceType, logicalId, void 0, cause));
51795
+ const thrown = this.wrapCaughtError(context?.maskSecrets, error, (text) => new ProvisioningError(`Failed to create S3 Table Bucket ${logicalId}: ${text}`, resourceType, logicalId, void 0, cause));
51796
+ if (createdArn !== void 0) markCreatedBeforeFailure(thrown, logicalId, resourceType, createdArn);
51797
+ throw thrown;
51798
+ }
51799
+ }
51800
+ async applyTableBucketConfigUpdate(logicalId, tableBucketARN, resourceType, properties, previousProperties, markUnsettled) {
51801
+ const changed = (key) => {
51802
+ const next = desiredObject(properties, key, resourceType, logicalId, tableBucketARN);
51803
+ return [next, !isDeepStrictEqual(next, recordedObject(previousProperties, key))];
51804
+ };
51805
+ const client = this.getClient();
51806
+ const [encryption, encryptionChanged] = changed("EncryptionConfiguration");
51807
+ if (encryptionChanged) {
51808
+ if (encryption !== void 0) {
51809
+ markUnsettled("EncryptionConfiguration");
51810
+ await client.send(new PutTableBucketEncryptionCommand({
51811
+ tableBucketARN,
51812
+ encryptionConfiguration: sdkEncryption(encryption)
51813
+ }));
51814
+ } else this.warnRemovalKept(logicalId, "EncryptionConfiguration");
51815
+ }
51816
+ const [storageClass, storageClassChanged] = changed("StorageClassConfiguration");
51817
+ if (storageClassChanged) {
51818
+ if (storageClass !== void 0) {
51819
+ markUnsettled("StorageClassConfiguration");
51820
+ await client.send(new PutTableBucketStorageClassCommand({
51821
+ tableBucketARN,
51822
+ storageClassConfiguration: sdkStorageClass(storageClass)
51823
+ }));
51824
+ } else this.warnRemovalKept(logicalId, "StorageClassConfiguration");
51825
+ }
51826
+ const metricsOn = metricsEnabled(desiredObject(properties, "MetricsConfiguration", resourceType, logicalId, tableBucketARN), resourceType, logicalId);
51827
+ const metricsWasOn = recordedObject(previousProperties, "MetricsConfiguration")?.["Status"] === "Enabled";
51828
+ if (metricsOn && !metricsWasOn) {
51829
+ markUnsettled("MetricsConfiguration");
51830
+ await client.send(new PutTableBucketMetricsConfigurationCommand({ tableBucketARN }));
51831
+ } else if (!metricsOn && metricsWasOn) {
51832
+ markUnsettled("MetricsConfiguration");
51833
+ await this.deleteBucketConfig(tableBucketARN, new DeleteTableBucketMetricsConfigurationCommand({ tableBucketARN }));
51834
+ }
51835
+ const [unreferenced, unreferencedChanged] = changed("UnreferencedFileRemoval");
51836
+ if (unreferencedChanged) {
51837
+ if (unreferenced !== void 0) {
51838
+ markUnsettled("UnreferencedFileRemoval");
51839
+ await client.send(new PutTableBucketMaintenanceConfigurationCommand({
51840
+ tableBucketARN,
51841
+ type: "icebergUnreferencedFileRemoval",
51842
+ value: sdkUnreferencedFileRemoval(unreferenced)
51843
+ }));
51844
+ } else this.warnRemovalKept(logicalId, "UnreferencedFileRemoval");
51845
+ }
51846
+ const [replication, replicationChanged] = changed("ReplicationConfiguration");
51847
+ if (replicationChanged) {
51848
+ if (replication !== void 0) {
51849
+ markUnsettled("ReplicationConfiguration");
51850
+ await client.send(new PutTableBucketReplicationCommand({
51851
+ tableBucketARN,
51852
+ configuration: sdkReplication(replication)
51853
+ }));
51854
+ } else {
51855
+ markUnsettled("ReplicationConfiguration");
51856
+ await this.deleteBucketConfig(tableBucketARN, new DeleteTableBucketReplicationCommand({ tableBucketARN }));
51857
+ }
51858
+ }
51859
+ }
51860
+ async applyTableMaintenanceUpdate(logicalId, physicalId, resourceType, properties, previousProperties, markUnsettled) {
51861
+ const writes = [];
51862
+ for (const [key, type, toSdk] of TABLE_MAINTENANCE) {
51863
+ const next = desiredObject(properties, key, resourceType, logicalId, physicalId);
51864
+ if (isDeepStrictEqual(next, recordedObject(previousProperties, key))) continue;
51865
+ if (next === void 0) this.warnRemovalKept(logicalId, key);
51866
+ else writes.push({
51867
+ key,
51868
+ type,
51869
+ value: toSdk(next)
51870
+ });
51871
+ }
51872
+ if (writes.length === 0) return;
51873
+ const table = await this.resolveTableParts(physicalId);
51874
+ if (table === "not-found" || table === "unparseable") throw new ProvisioningError(table === "not-found" ? safeMsg`S3 Tables Table '${physicalId}' no longer exists (state is out of sync); ` + `refusing to record a maintenance configuration that was not applied` : compositeIdFormatMessage(S3_TABLES_TABLE_ID_FORMAT, logicalId, physicalId), resourceType, logicalId, physicalId);
51875
+ for (const { key, type, value } of writes) {
51876
+ markUnsettled(key);
51877
+ await this.getClient().send(new PutTableMaintenanceConfigurationCommand({
51878
+ ...table,
51879
+ type,
51880
+ value
51881
+ }));
51882
+ }
51883
+ }
51884
+ warnRemovalKept(logicalId, key) {
51885
+ this.logger.warn(safeMsg`${logicalId}: ${key} was removed from the template; cdkd leaves its current AWS value in ` + `place. Declare the value you want (e.g. its default) to change it.`);
51886
+ }
51887
+ async deleteBucketConfig(tableBucketARN, command) {
51888
+ try {
51889
+ await this.getClient().send(command);
51890
+ } catch (error) {
51891
+ if (!(error instanceof NotFoundException$7)) throw error;
51892
+ await this.getClient().send(new GetTableBucketCommand({ tableBucketARN }));
50995
51893
  }
50996
51894
  }
50997
51895
  async deleteTableBucket(logicalId, physicalId, resourceType, context) {
@@ -51126,6 +52024,17 @@ var S3TablesProvider = class {
51126
52024
  const format = properties["OpenTableFormat"] ?? properties["Format"];
51127
52025
  if (!format) throw new ProvisioningError(`OpenTableFormat is required for S3 Tables Table ${logicalId}`, resourceType, logicalId);
51128
52026
  const tags = this.tagListToSdkMap(desiredTags);
52027
+ const icebergCfn = desiredObject(properties, "IcebergMetadata", resourceType, logicalId);
52028
+ const iceberg = icebergCfn && refuseNonIntegers(() => sdkIcebergMetadata(icebergCfn), "IcebergMetadata", resourceType, logicalId);
52029
+ const storageClass = desiredObject(properties, "StorageClassConfiguration", resourceType, logicalId);
52030
+ const maintenance = [];
52031
+ for (const [key, type, toSdk] of TABLE_MAINTENANCE) {
52032
+ const value = desiredObject(properties, key, resourceType, logicalId);
52033
+ if (value !== void 0) maintenance.push({
52034
+ type,
52035
+ value: refuseNonIntegers(() => toSdk(value), key, resourceType, logicalId)
52036
+ });
52037
+ }
51129
52038
  const physicalId = packCompositeId(resourceType, logicalId, [
51130
52039
  {
51131
52040
  name: "tableBucketARN",
@@ -51150,10 +52059,18 @@ var S3TablesProvider = class {
51150
52059
  namespace,
51151
52060
  name,
51152
52061
  format,
52062
+ ...iceberg !== void 0 && { metadata: { iceberg } },
52063
+ ...storageClass !== void 0 && { storageClassConfiguration: sdkStorageClass(storageClass) },
51153
52064
  ...tags !== void 0 && { tags }
51154
52065
  }));
51155
52066
  tableCreated = true;
51156
52067
  reportCreatedResource(logicalId, resourceType, physicalId);
52068
+ for (const write of maintenance) await this.getClient().send(new PutTableMaintenanceConfigurationCommand({
52069
+ tableBucketARN,
52070
+ namespace,
52071
+ name,
52072
+ ...write
52073
+ }));
51157
52074
  if (!response.tableARN) throw new ProvisioningError(`CreateTable did not return a tableARN for ${logicalId} (${physicalId}) — refusing to record an empty TableARN attribute`, resourceType, logicalId, physicalId);
51158
52075
  const tableARN = response.tableARN;
51159
52076
  this.logger.debug(`Successfully created S3 Tables Table ${logicalId}: ${physicalId}`);
@@ -51189,8 +52106,58 @@ var S3TablesProvider = class {
51189
52106
  const result = {};
51190
52107
  if (bucket.name !== void 0) result["TableBucketName"] = bucket.name;
51191
52108
  result["Tags"] = await this.readTagsBestEffort(physicalId);
52109
+ Object.assign(result, await this.readTableBucketConfigs(physicalId));
51192
52110
  return result;
51193
52111
  }
52112
+ async readTableBucketConfigs(tableBucketARN, strict = false) {
52113
+ const client = this.getClient();
52114
+ const out = {};
52115
+ await this.readConfig(out, "EncryptionConfiguration", async () => {
52116
+ const e = (await client.send(new GetTableBucketEncryptionCommand({ tableBucketARN }))).encryptionConfiguration;
52117
+ return defined({
52118
+ SSEAlgorithm: e?.sseAlgorithm ?? "AES256",
52119
+ KMSKeyArn: e?.kmsKeyArn
52120
+ });
52121
+ }, { SSEAlgorithm: "AES256" }, strict);
52122
+ await this.readConfig(out, "StorageClassConfiguration", async () => {
52123
+ return { StorageClass: (await client.send(new GetTableBucketStorageClassCommand({ tableBucketARN }))).storageClassConfiguration?.storageClass ?? "STANDARD" };
52124
+ }, { StorageClass: "STANDARD" }, strict);
52125
+ await this.readConfig(out, "MetricsConfiguration", async () => {
52126
+ await client.send(new GetTableBucketMetricsConfigurationCommand({ tableBucketARN }));
52127
+ return { Status: "Enabled" };
52128
+ }, { Status: "Disabled" }, strict);
52129
+ await this.readConfig(out, "UnreferencedFileRemoval", async () => {
52130
+ const value = (await client.send(new GetTableBucketMaintenanceConfigurationCommand({ tableBucketARN }))).configuration?.icebergUnreferencedFileRemoval;
52131
+ const settings = value?.settings?.icebergUnreferencedFileRemoval;
52132
+ return defined({
52133
+ Status: cfnBucketStatus(value?.status) ?? "Enabled",
52134
+ UnreferencedDays: settings?.unreferencedDays,
52135
+ NoncurrentDays: settings?.nonCurrentDays
52136
+ });
52137
+ }, { Status: "Enabled" }, strict);
52138
+ await this.readConfig(out, "ReplicationConfiguration", async () => {
52139
+ const c = (await client.send(new GetTableBucketReplicationCommand({ tableBucketARN }))).configuration;
52140
+ if (c === void 0) return void 0;
52141
+ return defined({
52142
+ Role: c.role,
52143
+ Rules: (c.rules ?? []).map((rule) => ({ Destinations: (rule.destinations ?? []).map((d) => ({ DestinationTableBucketARN: d.destinationTableBucketARN })) }))
52144
+ });
52145
+ }, "absent", strict);
52146
+ return out;
52147
+ }
52148
+ async readConfig(out, key, read, notFound, strict = false) {
52149
+ try {
52150
+ const value = await read();
52151
+ if (value !== void 0) out[key] = value;
52152
+ } catch (err) {
52153
+ if (err instanceof NotFoundException$7) {
52154
+ if (notFound !== "absent") out[key] = notFound;
52155
+ return;
52156
+ }
52157
+ if (strict) throw err;
52158
+ this.logger.debug(safeMsg`readCurrentState: reading ${key} failed: ${describeAwsFailure(err).detail} — leaving it out`);
52159
+ }
52160
+ }
51194
52161
  async readNamespaceCurrentState(physicalId) {
51195
52162
  const [tableBucketARN, namespaceName] = physicalId.split("|");
51196
52163
  if (!tableBucketARN || !namespaceName) return void 0;
@@ -51264,8 +52231,62 @@ var S3TablesProvider = class {
51264
52231
  result["Format"] = resp.format;
51265
52232
  }
51266
52233
  result["Tags"] = resp.tableARN ? await this.readTagsBestEffort(resp.tableARN) : [];
52234
+ Object.assign(result, await this.readTableMaintenance(physicalId, {
52235
+ tableBucketARN,
52236
+ namespace,
52237
+ name
52238
+ }));
51267
52239
  return result;
51268
52240
  }
52241
+ async readTableMaintenance(physicalId, table, strict = false) {
52242
+ const result = {};
52243
+ let maintenance;
52244
+ let maintenanceRead = true;
52245
+ try {
52246
+ maintenance = (await this.getClient().send(new GetTableMaintenanceConfigurationCommand(table))).configuration;
52247
+ } catch (err) {
52248
+ maintenanceRead = err instanceof NotFoundException$7;
52249
+ if (!maintenanceRead) {
52250
+ if (strict) throw err;
52251
+ this.logger.debug(safeMsg`readCurrentState: reading the maintenance configuration of ${physicalId} failed: ` + safeMsg`${describeAwsFailure(err).detail} — leaving Compaction / SnapshotManagement out`);
52252
+ }
52253
+ }
52254
+ if (maintenanceRead) {
52255
+ const compaction = maintenance?.icebergCompaction;
52256
+ const compactionSettings = compaction?.settings && "icebergCompaction" in compaction.settings ? compaction.settings.icebergCompaction : void 0;
52257
+ result["Compaction"] = defined({
52258
+ Status: compaction?.status ?? "enabled",
52259
+ TargetFileSizeMB: compactionSettings?.targetFileSizeMB
52260
+ });
52261
+ const snapshots = maintenance?.icebergSnapshotManagement;
52262
+ const snapshotSettings = snapshots?.settings && "icebergSnapshotManagement" in snapshots.settings ? snapshots.settings.icebergSnapshotManagement : void 0;
52263
+ result["SnapshotManagement"] = defined({
52264
+ Status: snapshots?.status ?? "enabled",
52265
+ MinSnapshotsToKeep: snapshotSettings?.minSnapshotsToKeep,
52266
+ MaxSnapshotAgeHours: snapshotSettings?.maxSnapshotAgeHours
52267
+ });
52268
+ }
52269
+ return result;
52270
+ }
52271
+ async readUnsettled(physicalId, logicalId, resourceType, names) {
52272
+ let live;
52273
+ if (resourceType === "AWS::S3Tables::TableBucket") {
52274
+ try {
52275
+ await this.getClient().send(new GetTableBucketCommand({ tableBucketARN: physicalId }));
52276
+ } catch (err) {
52277
+ if (err instanceof NotFoundException$7) return RESOURCE_NOT_FOUND;
52278
+ throw err;
52279
+ }
52280
+ live = await this.readTableBucketConfigs(physicalId, true);
52281
+ } else if (resourceType === "AWS::S3Tables::Table") {
52282
+ const table = await this.resolveTableParts(physicalId);
52283
+ if (table === "not-found") return RESOURCE_NOT_FOUND;
52284
+ if (table === "unparseable") throw new ProvisioningError(compositeIdFormatMessage(S3_TABLES_TABLE_ID_FORMAT, logicalId, physicalId), resourceType, logicalId, physicalId);
52285
+ if (await this.lookupTableArn(table.tableBucketARN, table.namespace, table.name) === null) return RESOURCE_NOT_FOUND;
52286
+ live = await this.readTableMaintenance(physicalId, table, true);
52287
+ } else return;
52288
+ return Object.fromEntries(Object.entries(live).filter(([key]) => names.has(key)));
52289
+ }
51269
52290
  async import(input) {
51270
52291
  switch (input.resourceType) {
51271
52292
  case "AWS::S3Tables::TableBucket": return this.importTableBucket(input);
@@ -52713,4 +53734,4 @@ var ACMCertificateProvider = class {
52713
53734
 
52714
53735
  //#endregion
52715
53736
  export { ACMCertificateProvider, ASGProvider, AgentCoreBrowserProvider, AgentCoreCodeInterpreterProvider, AgentCoreEvaluatorProvider, AgentCoreRuntimeProvider, ApiGatewayProvider, ApiGatewayV2Provider, AppSyncProvider, BudgetsBudgetProvider, CloudFrontDistributionProvider, CloudFrontOACProvider, CloudFrontOAIProvider, CloudTrailProvider, CloudWatchAlarmProvider, CloudWatchAnomalyDetectorProvider, CodeBuildProvider, CodeCommitRepositoryProvider, CognitoUserPoolProvider, DLMLifecyclePolicyProvider, DocDBProvider, DocDBSubnetGroupProvider, DynamoDBGlobalTableProvider, DynamoDBTableProvider, EC2Provider, ECRProvider, ECSProvider, EFSProvider, ELBv2Provider, EMRClusterProvider, EMRInstanceFleetConfigProvider, EMRInstanceGroupConfigProvider, ElastiCacheProvider, EventBridgeBusProvider, EventBridgeRuleProvider, FSxFileSystemProvider, FirehoseProvider, GlueConnectionProvider, GlueCrawlerProvider, GlueJobProvider, GlueProvider, GlueSecurityConfigurationProvider, GlueTriggerProvider, GlueWorkflowProvider, IAMAccessKeyProvider, IAMInstanceProfileProvider, IAMManagedPolicyProvider, IAMPolicyProvider, IAMRoleProvider, IAMUserGroupProvider, KMSProvider, KinesisStreamConsumerProvider, KinesisStreamProvider, LambdaEventInvokeConfigProvider, LambdaEventSourceMappingProvider, LambdaFunctionProvider, LambdaLayerVersionProvider, LambdaMicrovmImageProvider, LambdaNetworkConnectorProvider, LambdaPermissionProvider, LambdaUrlProvider, LambdaWebFunctionEndpointProvider, LambdaWebFunctionRevisionProvider, LogsLogGroupProvider, NeptuneProvider, NestedStackProvider, PipesPipeProvider, RDSDBProxyEndpointProvider, RDSDBProxyProvider, RDSDBProxyTargetGroupProvider, RDSProvider, Route53Provider, S3BucketPolicyProvider, S3BucketProvider, S3DirectoryBucketProvider, S3TablesProvider, S3VectorsProvider, SNSSubscriptionProvider, SNSTopicPolicyProvider, SNSTopicProvider, SQSQueuePolicyProvider, SQSQueueProvider, SSMParameterProvider, SchedulerScheduleProvider, SecretsManagerSecretProvider, ServiceDiscoveryProvider, StepFunctionsProvider, WAFv2WebACLProvider, WaitConditionHandleProvider };
52716
- //# sourceMappingURL=provider-classes-DktsDsTf.js.map
53737
+ //# sourceMappingURL=provider-classes-DefoNqY7.js.map