@go-to-k/cdkd 0.278.10 → 0.278.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{asg-provider-BlBwcSG-.js → asg-provider-BAnnBKci.js} +2 -2
- package/dist/{asg-provider-BlBwcSG-.js.map → asg-provider-BAnnBKci.js.map} +1 -1
- package/dist/cli.js +282 -32
- package/dist/cli.js.map +1 -1
- package/dist/{deploy-engine-BFUaBWTW.js → deploy-engine-BKfqbjsz.js} +3 -3
- package/dist/{deploy-engine-BFUaBWTW.js.map → deploy-engine-BKfqbjsz.js.map} +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as DagBuilder, A as red, At as resolveApp, B as isTerminationProtectionPropagationError, Bt as CFN_TEMPLATE_URL_LIMIT, C as isStatefulRecreateTargetSync, Ct as runDockerStreaming, D as cyan, Dt as synthesisStatusMessage, E as bold, Et as Synthesizer, F as ProviderRegistry, Ft as resolveStateBucketWithDefaultAndSource, G as normalizeAwsTagsToCfn, Gt as AssemblyReader, H as cfnRefValueFromPhysicalId, Ht as findLargeInlineResources, I as findActionableSilentDrops, It as resolveUseCdkBootstrapAssets, J as applyRoleArnIfSet, Jt as resolveBucketRegion, K as resolveExplicitPhysicalId, Kt as processStackMessages, L as CloudControlProvider, Lt as stateBucketExistenceConfirmed, M as IAMRoleProvider, Mt as resolveCaptureObservedState, N as collectInlinePolicyNamesManagedBySiblings, Nt as resolveSkipPrefix, O as gray, Ot as getDefaultStateBucketName, P as clearOnUpdateRemoval, Pt as resolveStateBucketWithDefault, Q as isRetryableTransientError, Qt as setAwsClients, R as slowCcOperationTimeoutMs, Rt as warnDeprecatedNoPrefixCliFlag, S as MULTI_REGION_RECREATE_BLOCKED_TYPES, St as runDockerForeground, T as formatResourceLine, Tt as getDockerImageBySourceHash, U as refStateLookupFromResource, Ut as uploadCfnTemplate, V as IntrinsicFunctionResolver, Vt as MIGRATE_TMP_PREFIX, W as WAFv2WebACLProvider, Wt as expectedOwnerParam, X as describeTypeWithThrottleRetry, Xt as getAwsClients, Y as DiffCalculator, Yt as AwsClients, Z as withRetry, Zt as resetAwsClients, _ as createPreDeleteFinalSnapshot, _t as validateAssetBucketName, a as DeploymentEventsStore, an as LocalMigrateError, at as AssetPublisher, b as unsupportedFinalSnapshotError, bn as normalizeAwsError, bt as formatDockerLoginError, c as replayFailedOperations, cn as MissingCdkCliError, ct as buildAssetRedirectMap, d as IMPLICIT_DELETE_DEPENDENCIES, dn as ProvisioningError, dt as rewriteTemplateAssetReferences, en as CdkdError, et as TemplateParser, f as computeImplicitDeleteEdges, fn as ResourceTimeoutError, ft as AssetModeResolver, g as ccRoutedFinalSnapshotError, gt as parseBootstrapMarker, h as buildFinalSnapshotIdentifier, hn as StackTerminationProtectionError, ht as getBootstrapMarkerKey, i as DeploymentEventsReader, in as LocalInvokeBuildError$1, it as shouldRetainResource, j as yellow, jt as resolveAutoAssetStorage, k as green, kt as getLegacyStateBucketName, l as replayRollback, ln as NestedStackChildDirectDestroyError, lt as createAssetRedirectResolver, m as PRE_DELETE_SNAPSHOT_TYPES, mn as StackHasActiveImportsError, mt as ensureAssetStorage, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nt as S3StateBackend, o as planFailedOps, on as LocalStartServiceError, ot as stringifyValue, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as ResourceUpdateNotSupportedError, pt as BOOTSTRAP_MARKER_PREFIX, q as assertRegionMatch, r as DeployEngine, rn as DeployCancelledError, rt as rebuildClientForBucketRegion, s as planRollback, st as WorkGraph, t as DEFAULT_RESOURCE_TIMEOUT_MS, tt as LockManager, u as withResourceDeadline, un as PartialFailureError, ut as loadPublishableAssetManifest, v as isFinalSnapshotError, vt as validateContainerRepoName, w as renderStatefulReason, wt as AssetManifestLoader, x as extractDeploymentEventError, xn as withErrorHandling, xt as getDockerCmd, y as refusesFinalSnapshot, yt as buildDockerImage, z as disableInstanceApiTermination, zt as CFN_TEMPLATE_BODY_LIMIT } from "./deploy-engine-
|
|
2
|
+
import { $ as DagBuilder, A as red, At as resolveApp, B as isTerminationProtectionPropagationError, Bt as CFN_TEMPLATE_URL_LIMIT, C as isStatefulRecreateTargetSync, Ct as runDockerStreaming, D as cyan, Dt as synthesisStatusMessage, E as bold, Et as Synthesizer, F as ProviderRegistry, Ft as resolveStateBucketWithDefaultAndSource, G as normalizeAwsTagsToCfn, Gt as AssemblyReader, H as cfnRefValueFromPhysicalId, Ht as findLargeInlineResources, I as findActionableSilentDrops, It as resolveUseCdkBootstrapAssets, J as applyRoleArnIfSet, Jt as resolveBucketRegion, K as resolveExplicitPhysicalId, Kt as processStackMessages, L as CloudControlProvider, Lt as stateBucketExistenceConfirmed, M as IAMRoleProvider, Mt as resolveCaptureObservedState, N as collectInlinePolicyNamesManagedBySiblings, Nt as resolveSkipPrefix, O as gray, Ot as getDefaultStateBucketName, P as clearOnUpdateRemoval, Pt as resolveStateBucketWithDefault, Q as isRetryableTransientError, Qt as setAwsClients, R as slowCcOperationTimeoutMs, Rt as warnDeprecatedNoPrefixCliFlag, S as MULTI_REGION_RECREATE_BLOCKED_TYPES, St as runDockerForeground, T as formatResourceLine, Tt as getDockerImageBySourceHash, U as refStateLookupFromResource, Ut as uploadCfnTemplate, V as IntrinsicFunctionResolver, Vt as MIGRATE_TMP_PREFIX, W as WAFv2WebACLProvider, Wt as expectedOwnerParam, X as describeTypeWithThrottleRetry, Xt as getAwsClients, Y as DiffCalculator, Yt as AwsClients, Z as withRetry, Zt as resetAwsClients, _ as createPreDeleteFinalSnapshot, _t as validateAssetBucketName, a as DeploymentEventsStore, an as LocalMigrateError, at as AssetPublisher, b as unsupportedFinalSnapshotError, bn as normalizeAwsError, bt as formatDockerLoginError, c as replayFailedOperations, cn as MissingCdkCliError, ct as buildAssetRedirectMap, d as IMPLICIT_DELETE_DEPENDENCIES, dn as ProvisioningError, dt as rewriteTemplateAssetReferences, en as CdkdError, et as TemplateParser, f as computeImplicitDeleteEdges, fn as ResourceTimeoutError, ft as AssetModeResolver, g as ccRoutedFinalSnapshotError, gt as parseBootstrapMarker, h as buildFinalSnapshotIdentifier, hn as StackTerminationProtectionError, ht as getBootstrapMarkerKey, i as DeploymentEventsReader, in as LocalInvokeBuildError$1, it as shouldRetainResource, j as yellow, jt as resolveAutoAssetStorage, k as green, kt as getLegacyStateBucketName, l as replayRollback, ln as NestedStackChildDirectDestroyError, lt as createAssetRedirectResolver, m as PRE_DELETE_SNAPSHOT_TYPES, mn as StackHasActiveImportsError, mt as ensureAssetStorage, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nt as S3StateBackend, o as planFailedOps, on as LocalStartServiceError, ot as stringifyValue, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as ResourceUpdateNotSupportedError, pt as BOOTSTRAP_MARKER_PREFIX, q as assertRegionMatch, r as DeployEngine, rn as DeployCancelledError, rt as rebuildClientForBucketRegion, s as planRollback, st as WorkGraph, t as DEFAULT_RESOURCE_TIMEOUT_MS, tt as LockManager, u as withResourceDeadline, un as PartialFailureError, ut as loadPublishableAssetManifest, v as isFinalSnapshotError, vt as validateContainerRepoName, w as renderStatefulReason, wt as AssetManifestLoader, x as extractDeploymentEventError, xn as withErrorHandling, xt as getDockerCmd, y as refusesFinalSnapshot, yt as buildDockerImage, z as disableInstanceApiTermination, zt as CFN_TEMPLATE_BODY_LIMIT } from "./deploy-engine-BKfqbjsz.js";
|
|
3
3
|
import { a as getLiveRenderer, c as PATTERN_B_RESOURCE_TYPES, d as generateResourceNameWithFallback, f as withSkipPrefix, i as runStackBuffered, n as getLogger, o as PATTERN_B_NAME_OPTIONS, p as withStackName, s as PATTERN_B_NAME_PROPERTIES, u as generateResourceName } from "./logger-BYMEE-BS.js";
|
|
4
|
-
import { t as ASGProvider } from "./asg-provider-
|
|
4
|
+
import { t as ASGProvider } from "./asg-provider-BAnnBKci.js";
|
|
5
5
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
6
6
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
7
7
|
import { CopyObjectCommand, CreateBucketCommand, DeleteBucketAnalyticsConfigurationCommand, DeleteBucketCommand, DeleteBucketCorsCommand, DeleteBucketIntelligentTieringConfigurationCommand, DeleteBucketInventoryConfigurationCommand, DeleteBucketLifecycleCommand, DeleteBucketMetricsConfigurationCommand, DeleteBucketPolicyCommand, DeleteBucketReplicationCommand, DeleteBucketTaggingCommand, DeleteBucketWebsiteCommand, DeleteObjectsCommand, GetBucketAccelerateConfigurationCommand, GetBucketCorsCommand, GetBucketEncryptionCommand, GetBucketLifecycleConfigurationCommand, GetBucketLocationCommand, GetBucketLoggingCommand, GetBucketNotificationConfigurationCommand, GetBucketPolicyCommand, GetBucketReplicationCommand, GetBucketTaggingCommand, GetBucketVersioningCommand, GetBucketWebsiteCommand, GetObjectCommand, GetObjectLockConfigurationCommand, GetPublicAccessBlockCommand, HeadBucketCommand, ListBucketAnalyticsConfigurationsCommand, ListBucketIntelligentTieringConfigurationsCommand, ListBucketInventoryConfigurationsCommand, ListBucketMetricsConfigurationsCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchBucket, PutBucketAccelerateConfigurationCommand, PutBucketAnalyticsConfigurationCommand, PutBucketCorsCommand, PutBucketEncryptionCommand, PutBucketIntelligentTieringConfigurationCommand, PutBucketInventoryConfigurationCommand, PutBucketLifecycleConfigurationCommand, PutBucketLoggingCommand, PutBucketMetricsConfigurationCommand, PutBucketNotificationConfigurationCommand, PutBucketOwnershipControlsCommand, PutBucketPolicyCommand, PutBucketReplicationCommand, PutBucketTaggingCommand, PutBucketVersioningCommand, PutBucketWebsiteCommand, PutObjectCommand, PutObjectLockConfigurationCommand, PutPublicAccessBlockCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
|
|
@@ -11948,10 +11948,15 @@ var DynamoDBTableProvider = class {
|
|
|
11948
11948
|
* - `update()` covers every mutable surface — Tags, DeletionProtection,
|
|
11949
11949
|
* TableClass, SSE, StreamSpec, OnDemand throughput, BillingMode flip,
|
|
11950
11950
|
* Replica add / remove / modify, GSI add / remove / modify, TTL toggle.
|
|
11951
|
-
* - The serialization is load-bearing: AWS's `UpdateTable`
|
|
11952
|
-
*
|
|
11953
|
-
*
|
|
11954
|
-
*
|
|
11951
|
+
* - The serialization is load-bearing: AWS's `UpdateTable` does not accept
|
|
11952
|
+
* `ReplicaUpdates` alongside `BillingMode` / `GlobalSecondaryIndexUpdates`,
|
|
11953
|
+
* so each category is its own SDK round-trip with a wait-for-ACTIVE in
|
|
11954
|
+
* between. `BillingMode` and `GlobalSecondaryIndexUpdates` DO combine, and
|
|
11955
|
+
* only in the `PAY_PER_REQUEST -> PROVISIONED` flip, where AWS REQUIRES
|
|
11956
|
+
* per-GSI `ProvisionedThroughput` in the SAME call as `BillingMode` ("you
|
|
11957
|
+
* must specify read and write capacity unit values for the table and for
|
|
11958
|
+
* each global secondary index") — so that path deliberately sends both
|
|
11959
|
+
* together (Issue #1387). Immutable property changes (TableName, KeySchema,
|
|
11955
11960
|
* AttributeDefinitions removal, LocalSecondaryIndexes) throw
|
|
11956
11961
|
* `ProvisioningError` naming the offending field — the deploy engine's
|
|
11957
11962
|
* diff classification should catch these as REPLACEMENT before ever
|
|
@@ -12146,7 +12151,13 @@ var DynamoDBGlobalTableProvider = class {
|
|
|
12146
12151
|
StreamViewType: "NEW_AND_OLD_IMAGES"
|
|
12147
12152
|
};
|
|
12148
12153
|
}
|
|
12149
|
-
|
|
12154
|
+
let sdkIndexes;
|
|
12155
|
+
try {
|
|
12156
|
+
sdkIndexes = toSdkGlobalSecondaryIndexes(properties, currentRegion, billingMode);
|
|
12157
|
+
} catch (error) {
|
|
12158
|
+
throw new ProvisioningError(error instanceof Error ? error.message : String(error), resourceType, logicalId, void 0, error instanceof Error ? error : void 0);
|
|
12159
|
+
}
|
|
12160
|
+
if (sdkIndexes.length > 0) createParams.GlobalSecondaryIndexes = sdkIndexes;
|
|
12150
12161
|
if (properties["LocalSecondaryIndexes"]) createParams.LocalSecondaryIndexes = properties["LocalSecondaryIndexes"];
|
|
12151
12162
|
if (properties["SSESpecification"]) {
|
|
12152
12163
|
const sse = properties["SSESpecification"];
|
|
@@ -12237,11 +12248,26 @@ var DynamoDBGlobalTableProvider = class {
|
|
|
12237
12248
|
* `DescribeTable` until the replica's `ReplicaStatus` flips to ACTIVE.
|
|
12238
12249
|
* Capped at 10 minutes per replica (AWS Replica provisioning typically
|
|
12239
12250
|
* takes 1–5 min).
|
|
12251
|
+
*
|
|
12252
|
+
* DELIBERATELY UNMAPPED replica sub-keys (Issue #1387 — recorded rather
|
|
12253
|
+
* than silently dropped; `CreateReplicationGroupMemberAction` simply has
|
|
12254
|
+
* no member for them, so they need their own follow-up API calls):
|
|
12255
|
+
* - `ReplicaStreamSpecification.ResourcePolicy` — the DynamoDB Streams
|
|
12256
|
+
* resource policy is set by `PutResourcePolicy` against the replica's
|
|
12257
|
+
* STREAM ARN, not by any `UpdateTable` field.
|
|
12258
|
+
* - `ResourcePolicy` — the table-level resource policy, likewise a
|
|
12259
|
+
* separate `PutResourcePolicy` call.
|
|
12260
|
+
* - `GlobalSecondaryIndexes[].ContributorInsightsSpecification` — a
|
|
12261
|
+
* per-index `UpdateContributorInsights` call.
|
|
12262
|
+
* `Replicas` is declared in `handledProperties` at the TOP level, which
|
|
12263
|
+
* is the granularity cdkd's pre-flight property-coverage check works at;
|
|
12264
|
+
* these nested keys are tracked as a known gap, not a supported surface.
|
|
12240
12265
|
*/
|
|
12241
12266
|
async addReplica(tableName, replica, region, logicalId) {
|
|
12242
12267
|
const create = { RegionName: region };
|
|
12243
12268
|
if (replica["KMSMasterKeyId"]) create.KMSMasterKeyId = replica["KMSMasterKeyId"];
|
|
12244
|
-
|
|
12269
|
+
const replicaIndexes = toSdkReplicaGlobalSecondaryIndexes(replica["GlobalSecondaryIndexes"]);
|
|
12270
|
+
if (replicaIndexes) create.GlobalSecondaryIndexes = replicaIndexes;
|
|
12245
12271
|
if (replica["TableClassOverride"]) create.TableClassOverride = replica["TableClassOverride"];
|
|
12246
12272
|
const replicaUpdates = [{ Create: create }];
|
|
12247
12273
|
await this.dynamoDBClient.send(new UpdateTableCommand({
|
|
@@ -12253,10 +12279,14 @@ var DynamoDBGlobalTableProvider = class {
|
|
|
12253
12279
|
/**
|
|
12254
12280
|
* Update a DynamoDB Global Table in place.
|
|
12255
12281
|
*
|
|
12256
|
-
* AWS-side state-machine constraint: `UpdateTable`
|
|
12257
|
-
* `
|
|
12282
|
+
* AWS-side state-machine constraint: `UpdateTable` does not accept
|
|
12283
|
+
* `ReplicaUpdates` alongside `BillingMode` / `GlobalSecondaryIndexUpdates`,
|
|
12258
12284
|
* so each category must serialize into its own SDK round-trip with a
|
|
12259
|
-
* `waitForTableActiveAfterUpdate` between every step.
|
|
12285
|
+
* `waitForTableActiveAfterUpdate` between every step. `BillingMode` and
|
|
12286
|
+
* `GlobalSecondaryIndexUpdates` DO combine, and only in step 4's
|
|
12287
|
+
* `PAY_PER_REQUEST -> PROVISIONED` flip, which AWS requires to carry
|
|
12288
|
+
* per-GSI `ProvisionedThroughput` in the same call (Issue #1387).
|
|
12289
|
+
* Order:
|
|
12260
12290
|
* 1. Wait for current ACTIVE (defensive).
|
|
12261
12291
|
* 2. Tags diff (TagResource / UntagResource — no wait needed).
|
|
12262
12292
|
* 3. Non-conflicting flat fields (DeletionProtectionEnabled / TableClass
|
|
@@ -12335,12 +12365,41 @@ var DynamoDBGlobalTableProvider = class {
|
|
|
12335
12365
|
}
|
|
12336
12366
|
const oldBilling = previousProperties["BillingMode"] ?? "PAY_PER_REQUEST";
|
|
12337
12367
|
const newBilling = properties["BillingMode"] ?? "PAY_PER_REQUEST";
|
|
12368
|
+
const gsiHandledByBillingFlip = /* @__PURE__ */ new Set();
|
|
12338
12369
|
if (oldBilling !== newBilling) {
|
|
12339
12370
|
const billingUpdate = {
|
|
12340
12371
|
TableName: physicalId,
|
|
12341
12372
|
BillingMode: newBilling
|
|
12342
12373
|
};
|
|
12343
|
-
if (newBilling === "PROVISIONED")
|
|
12374
|
+
if (newBilling === "PROVISIONED") {
|
|
12375
|
+
billingUpdate.ProvisionedThroughput = derivePerCallProvisionedThroughput(properties, currentRegion);
|
|
12376
|
+
const provisionedIndexes = toSdkGlobalSecondaryIndexes(properties, currentRegion, newBilling);
|
|
12377
|
+
const previousCfnIndexes = previousProperties["GlobalSecondaryIndexes"];
|
|
12378
|
+
const existingIndexNames = new Set((Array.isArray(previousCfnIndexes) ? previousCfnIndexes : []).map((entry) => entry?.["IndexName"]).filter((name) => typeof name === "string"));
|
|
12379
|
+
const previousByIndexName = /* @__PURE__ */ new Map();
|
|
12380
|
+
for (const gsi of toSdkGlobalSecondaryIndexes(previousProperties, currentRegion, newBilling)) if (gsi.IndexName) previousByIndexName.set(gsi.IndexName, gsi);
|
|
12381
|
+
const byIndexName = new Map(previousByIndexName);
|
|
12382
|
+
const survivingIndexNames = /* @__PURE__ */ new Set();
|
|
12383
|
+
for (const gsi of provisionedIndexes) {
|
|
12384
|
+
if (!gsi.IndexName) continue;
|
|
12385
|
+
survivingIndexNames.add(gsi.IndexName);
|
|
12386
|
+
byIndexName.set(gsi.IndexName, gsi);
|
|
12387
|
+
}
|
|
12388
|
+
const indexUpdates = [];
|
|
12389
|
+
for (const indexName of existingIndexNames) {
|
|
12390
|
+
const gsi = byIndexName.get(indexName);
|
|
12391
|
+
if (!gsi?.ProvisionedThroughput) continue;
|
|
12392
|
+
const previousWarm = previousByIndexName.get(indexName)?.WarmThroughput;
|
|
12393
|
+
const warmChanged = gsi.WarmThroughput !== void 0 && !deepEqual$1(gsi.WarmThroughput, previousWarm);
|
|
12394
|
+
indexUpdates.push({ Update: {
|
|
12395
|
+
IndexName: indexName,
|
|
12396
|
+
ProvisionedThroughput: gsi.ProvisionedThroughput,
|
|
12397
|
+
...warmChanged && { WarmThroughput: gsi.WarmThroughput }
|
|
12398
|
+
} });
|
|
12399
|
+
if (survivingIndexNames.has(indexName)) gsiHandledByBillingFlip.add(indexName);
|
|
12400
|
+
}
|
|
12401
|
+
if (indexUpdates.length > 0) billingUpdate.GlobalSecondaryIndexUpdates = indexUpdates;
|
|
12402
|
+
}
|
|
12344
12403
|
await this.dynamoDBClient.send(new UpdateTableCommand(billingUpdate));
|
|
12345
12404
|
await this.waitForTableActiveAfterUpdate(physicalId, logicalId);
|
|
12346
12405
|
}
|
|
@@ -12391,7 +12450,8 @@ var DynamoDBGlobalTableProvider = class {
|
|
|
12391
12450
|
}
|
|
12392
12451
|
const updateAction = { RegionName: region };
|
|
12393
12452
|
if (replica["KMSMasterKeyId"] !== void 0) updateAction.KMSMasterKeyId = replica["KMSMasterKeyId"];
|
|
12394
|
-
|
|
12453
|
+
const replicaIndexes = toSdkReplicaGlobalSecondaryIndexes(replica["GlobalSecondaryIndexes"]);
|
|
12454
|
+
if (replicaIndexes) updateAction.GlobalSecondaryIndexes = replicaIndexes;
|
|
12395
12455
|
if (replica["TableClassOverride"]) updateAction.TableClassOverride = replica["TableClassOverride"];
|
|
12396
12456
|
if (!(updateAction.KMSMasterKeyId !== void 0 || updateAction.GlobalSecondaryIndexes !== void 0 || updateAction.TableClassOverride !== void 0)) {
|
|
12397
12457
|
this.logger.debug(`Cross-region replica ${region} of ${physicalId}: only Tags-style changes detected; UpdateReplica skipped (AWS rejects empty Update actions). Tags propagation handled above via per-region client.`);
|
|
@@ -12403,7 +12463,10 @@ var DynamoDBGlobalTableProvider = class {
|
|
|
12403
12463
|
}));
|
|
12404
12464
|
await this.waitForReplicaActive(physicalId, region, logicalId);
|
|
12405
12465
|
}
|
|
12406
|
-
const
|
|
12466
|
+
const previousSdkIndexes = toSdkGlobalSecondaryIndexes(previousProperties, currentRegion, oldBilling);
|
|
12467
|
+
const gsiDiff = diffGlobalSecondaryIndexes(previousSdkIndexes, toSdkGlobalSecondaryIndexes(properties, currentRegion, newBilling));
|
|
12468
|
+
const previousSdkByName = /* @__PURE__ */ new Map();
|
|
12469
|
+
for (const prev of previousSdkIndexes) if (prev.IndexName) previousSdkByName.set(prev.IndexName, prev);
|
|
12407
12470
|
for (const gsi of gsiDiff.removed) {
|
|
12408
12471
|
if (!gsi.IndexName) continue;
|
|
12409
12472
|
const gsiUpdate = { Delete: { IndexName: gsi.IndexName } };
|
|
@@ -12420,7 +12483,8 @@ var DynamoDBGlobalTableProvider = class {
|
|
|
12420
12483
|
KeySchema: gsi.KeySchema,
|
|
12421
12484
|
Projection: gsi.Projection,
|
|
12422
12485
|
...gsi.ProvisionedThroughput && { ProvisionedThroughput: gsi.ProvisionedThroughput },
|
|
12423
|
-
...gsi.OnDemandThroughput && { OnDemandThroughput: gsi.OnDemandThroughput }
|
|
12486
|
+
...gsi.OnDemandThroughput && { OnDemandThroughput: gsi.OnDemandThroughput },
|
|
12487
|
+
...gsi.WarmThroughput && { WarmThroughput: gsi.WarmThroughput }
|
|
12424
12488
|
} };
|
|
12425
12489
|
await this.dynamoDBClient.send(new UpdateTableCommand({
|
|
12426
12490
|
TableName: physicalId,
|
|
@@ -12431,11 +12495,18 @@ var DynamoDBGlobalTableProvider = class {
|
|
|
12431
12495
|
}
|
|
12432
12496
|
for (const gsi of gsiDiff.modified) {
|
|
12433
12497
|
if (!gsi.IndexName) continue;
|
|
12434
|
-
|
|
12435
|
-
|
|
12436
|
-
|
|
12437
|
-
|
|
12438
|
-
|
|
12498
|
+
if (gsiHandledByBillingFlip.has(gsi.IndexName)) continue;
|
|
12499
|
+
const billingFlipped = oldBilling !== newBilling;
|
|
12500
|
+
const update = { IndexName: gsi.IndexName };
|
|
12501
|
+
if (gsi.OnDemandThroughput) update.OnDemandThroughput = gsi.OnDemandThroughput;
|
|
12502
|
+
if (!billingFlipped && gsi.ProvisionedThroughput) update.ProvisionedThroughput = gsi.ProvisionedThroughput;
|
|
12503
|
+
const previousSdk = previousSdkByName.get(gsi.IndexName);
|
|
12504
|
+
if (gsi.WarmThroughput !== void 0 && !deepEqual$1(gsi.WarmThroughput, previousSdk?.WarmThroughput)) update.WarmThroughput = gsi.WarmThroughput;
|
|
12505
|
+
if (!update.ProvisionedThroughput && !update.OnDemandThroughput && !update.WarmThroughput) {
|
|
12506
|
+
if (!billingFlipped) this.logger.warn(`GSI '${gsi.IndexName}' on ${physicalId} changed in a way DynamoDB's UpdateTable cannot express (KeySchema / Projection are immutable on an existing index). Recreate the index under a new name to apply the change.`);
|
|
12507
|
+
continue;
|
|
12508
|
+
}
|
|
12509
|
+
const gsiUpdate = { Update: update };
|
|
12439
12510
|
await this.dynamoDBClient.send(new UpdateTableCommand({
|
|
12440
12511
|
TableName: physicalId,
|
|
12441
12512
|
GlobalSecondaryIndexUpdates: [gsiUpdate]
|
|
@@ -13200,11 +13271,16 @@ var DynamoDBGlobalTableProvider = class {
|
|
|
13200
13271
|
*
|
|
13201
13272
|
* Source of truth (CFn `AWS::DynamoDB::GlobalTable` shape):
|
|
13202
13273
|
* - WriteCapacityUnits → `properties.WriteProvisionedThroughputSettings`
|
|
13203
|
-
* (top-level on the table).
|
|
13204
|
-
*
|
|
13274
|
+
* (top-level on the table). That block's ONLY member is
|
|
13275
|
+
* `WriteCapacityAutoScalingSettings` — write capacity on a GlobalTable is
|
|
13276
|
+
* always auto-scaled, so there is no literal `WriteCapacityUnits` to
|
|
13277
|
+
* prefer. `CreateTable` needs one concrete number, so the auto-scaling
|
|
13278
|
+
* block's `SeedCapacity` (documented as the value used until the scaling
|
|
13279
|
+
* policies exist) is taken before `MinCapacity`; 5 if the block is absent.
|
|
13205
13280
|
* - ReadCapacityUnits → `Replicas[?Region==<region>].ReadProvisionedThroughputSettings`
|
|
13206
|
-
* (per-replica, the deploy region's setting).
|
|
13207
|
-
* scaling
|
|
13281
|
+
* (per-replica, the deploy region's setting). That block DOES carry a
|
|
13282
|
+
* literal `ReadCapacityUnits`, which is taken before its auto-scaling
|
|
13283
|
+
* `SeedCapacity` / `MinCapacity`; 5 if absent.
|
|
13208
13284
|
*/
|
|
13209
13285
|
/**
|
|
13210
13286
|
* Extract the local replica's `DeletionProtectionEnabled` from a CFn
|
|
@@ -13227,16 +13303,190 @@ function extractLocalDeletionProtection(props, region) {
|
|
|
13227
13303
|
return typeof topLevel === "boolean" ? topLevel : void 0;
|
|
13228
13304
|
}
|
|
13229
13305
|
function derivePerCallProvisionedThroughput(properties, region) {
|
|
13230
|
-
const wps = properties["WriteProvisionedThroughputSettings"];
|
|
13231
|
-
const writeAutoScaling = wps?.["WriteCapacityAutoScalingSettings"];
|
|
13232
|
-
const writeCapacity = Number(wps?.["WriteCapacityUnits"] ?? writeAutoScaling?.["MinCapacity"] ?? 5);
|
|
13233
|
-
const localReadSettings = (properties["Replicas"] ?? []).find((r) => r["Region"] === region)?.["ReadProvisionedThroughputSettings"];
|
|
13234
|
-
const readAutoScaling = localReadSettings?.["ReadCapacityAutoScalingSettings"];
|
|
13235
13306
|
return {
|
|
13236
|
-
ReadCapacityUnits:
|
|
13237
|
-
WriteCapacityUnits:
|
|
13307
|
+
ReadCapacityUnits: deriveReadCapacityUnits(asRecord((properties["Replicas"] ?? []).find((r) => r["Region"] === region)?.["ReadProvisionedThroughputSettings"])) ?? DEFAULT_CAPACITY_UNITS,
|
|
13308
|
+
WriteCapacityUnits: deriveWriteCapacityUnits(asRecord(properties["WriteProvisionedThroughputSettings"])) ?? DEFAULT_CAPACITY_UNITS
|
|
13238
13309
|
};
|
|
13239
13310
|
}
|
|
13311
|
+
/**
|
|
13312
|
+
* Capacity units applied when a PROVISIONED template carries no usable
|
|
13313
|
+
* capacity value at all. Matches the pre-existing table-level default.
|
|
13314
|
+
*/
|
|
13315
|
+
const DEFAULT_CAPACITY_UNITS = 5;
|
|
13316
|
+
/** Narrow an unknown CFn sub-object to a record (or `undefined`). */
|
|
13317
|
+
function asRecord(value) {
|
|
13318
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
13319
|
+
}
|
|
13320
|
+
/** Coerce a CFn numeric (CFn is stringly-typed) to a finite number. */
|
|
13321
|
+
function toFiniteNumber(value) {
|
|
13322
|
+
if (value === void 0 || value === null || value === "") return void 0;
|
|
13323
|
+
const n = Number(value);
|
|
13324
|
+
return Number.isFinite(n) ? n : void 0;
|
|
13325
|
+
}
|
|
13326
|
+
/**
|
|
13327
|
+
* Derive a single WRITE capacity number from a CFn
|
|
13328
|
+
* `WriteProvisionedThroughputSettings` block.
|
|
13329
|
+
*
|
|
13330
|
+
* The `AWS::DynamoDB::GlobalTable` registry schema (verified 2026-08-09 via
|
|
13331
|
+
* `aws cloudformation describe-type`) declares this block with exactly ONE
|
|
13332
|
+
* member — `WriteCapacityAutoScalingSettings` — i.e. write capacity on a
|
|
13333
|
+
* GlobalTable is ALWAYS auto-scaled; there is no literal `WriteCapacityUnits`
|
|
13334
|
+
* (that is why CDK 2.244's `TableV2` rejects `Capacity.fixed()` for write).
|
|
13335
|
+
* `CreateTable` / `UpdateTable` still require a concrete starting number, so
|
|
13336
|
+
* we take `SeedCapacity` ("the initial provisioned capacity units") when the
|
|
13337
|
+
* template supplies it, else `MinCapacity`.
|
|
13338
|
+
*
|
|
13339
|
+
* A literal `WriteCapacityUnits` is still honored first: the CFn schema
|
|
13340
|
+
* forbids it, but hand-authored / imported templates and cdkd state written
|
|
13341
|
+
* before this helper existed can carry it, and honoring it is strictly more
|
|
13342
|
+
* faithful than ignoring it.
|
|
13343
|
+
*/
|
|
13344
|
+
function deriveWriteCapacityUnits(settings) {
|
|
13345
|
+
if (!settings) return void 0;
|
|
13346
|
+
const literal = toFiniteNumber(settings["WriteCapacityUnits"]);
|
|
13347
|
+
if (literal !== void 0) return literal;
|
|
13348
|
+
const autoScaling = asRecord(settings["WriteCapacityAutoScalingSettings"]);
|
|
13349
|
+
if (!autoScaling) return void 0;
|
|
13350
|
+
return toFiniteNumber(autoScaling["SeedCapacity"]) ?? toFiniteNumber(autoScaling["MinCapacity"]);
|
|
13351
|
+
}
|
|
13352
|
+
/**
|
|
13353
|
+
* Derive a single READ capacity number from a CFn
|
|
13354
|
+
* `ReadProvisionedThroughputSettings` block (both the per-replica shape,
|
|
13355
|
+
* which carries `ReadCapacityUnits` + `ReadCapacityAutoScalingSettings`, and
|
|
13356
|
+
* the GSI/table-level `GlobalReadProvisionedThroughputSettings` shape, which
|
|
13357
|
+
* carries only `ReadCapacityUnits`). Same Seed-before-Min precedence as the
|
|
13358
|
+
* write side.
|
|
13359
|
+
*/
|
|
13360
|
+
function deriveReadCapacityUnits(settings) {
|
|
13361
|
+
if (!settings) return void 0;
|
|
13362
|
+
const literal = toFiniteNumber(settings["ReadCapacityUnits"]);
|
|
13363
|
+
if (literal !== void 0) return literal;
|
|
13364
|
+
const autoScaling = asRecord(settings["ReadCapacityAutoScalingSettings"]);
|
|
13365
|
+
if (!autoScaling) return void 0;
|
|
13366
|
+
return toFiniteNumber(autoScaling["SeedCapacity"]) ?? toFiniteNumber(autoScaling["MinCapacity"]);
|
|
13367
|
+
}
|
|
13368
|
+
/**
|
|
13369
|
+
* Translate the CFn `AWS::DynamoDB::GlobalTable` `GlobalSecondaryIndexes[]`
|
|
13370
|
+
* blob into the SDK's `GlobalSecondaryIndex[]` shape (Issue #1387).
|
|
13371
|
+
*
|
|
13372
|
+
* The two schemas model per-GSI throughput COMPLETELY differently, and the
|
|
13373
|
+
* AWS SDK v3 serializer silently drops unknown members — so the pre-fix raw
|
|
13374
|
+
* cast meant a PROVISIONED GlobalTable with a GSI failed `CreateTable`
|
|
13375
|
+
* outright (AWS requires `ProvisionedThroughput` on every GSI), and every
|
|
13376
|
+
* `TableV2` per-GSI on-demand limit vanished without a trace.
|
|
13377
|
+
*
|
|
13378
|
+
* Verified mapping (CFn registry schema `AWS::DynamoDB::GlobalTable` +
|
|
13379
|
+
* `@aws-sdk/client-dynamodb` `models_0.d.ts`, both read 2026-08-09; the CFn
|
|
13380
|
+
* side additionally confirmed against a real `cdk synth` of `TableV2` with a
|
|
13381
|
+
* GSI under both billing modes):
|
|
13382
|
+
*
|
|
13383
|
+
* | CFn | SDK |
|
|
13384
|
+
* | ---------------------------------------------------------------------- | --------------------------------------- |
|
|
13385
|
+
* | `GSI.WriteProvisionedThroughputSettings.WriteCapacityAutoScalingSettings` | `ProvisionedThroughput.WriteCapacityUnits` |
|
|
13386
|
+
* | `Replicas[local].GlobalSecondaryIndexes[].ReadProvisionedThroughputSettings.ReadCapacityUnits` | `ProvisionedThroughput.ReadCapacityUnits` |
|
|
13387
|
+
* | `GSI.WriteOnDemandThroughputSettings.MaxWriteRequestUnits` | `OnDemandThroughput.MaxWriteRequestUnits` |
|
|
13388
|
+
* | `Replicas[local].GlobalSecondaryIndexes[].ReadOnDemandThroughputSettings.MaxReadRequestUnits` | `OnDemandThroughput.MaxReadRequestUnits` |
|
|
13389
|
+
* | `GSI.WarmThroughput` | `WarmThroughput` (same spelling) |
|
|
13390
|
+
*
|
|
13391
|
+
* READ capacity really does live on the REPLICA's GSI entry, not on the
|
|
13392
|
+
* top-level GSI — CDK's `globalSecondaryIndexes[].readCapacity` synthesizes
|
|
13393
|
+
* to `Replicas[?Region==<deploy region>].GlobalSecondaryIndexes[].
|
|
13394
|
+
* ReadProvisionedThroughputSettings`. `CreateTable` only ever provisions the
|
|
13395
|
+
* LOCAL replica, so the local entry is the right source. The GSI-level
|
|
13396
|
+
* `ReadProvisionedThroughputSettings` / `ReadOnDemandThroughputSettings`
|
|
13397
|
+
* (which the schema also permits) are honored as a fallback for
|
|
13398
|
+
* hand-authored templates.
|
|
13399
|
+
*
|
|
13400
|
+
* Already-SDK-shaped `ProvisionedThroughput` / `OnDemandThroughput` members
|
|
13401
|
+
* win over the derivation: the CFn schema forbids them, but cdkd state
|
|
13402
|
+
* written before this fix (and hand-authored templates) can carry them, and
|
|
13403
|
+
* silently re-deriving over an explicit value would be a regression.
|
|
13404
|
+
*/
|
|
13405
|
+
function toSdkGlobalSecondaryIndexes(properties, region, billingMode) {
|
|
13406
|
+
const rawIndexes = properties["GlobalSecondaryIndexes"];
|
|
13407
|
+
if (rawIndexes !== void 0 && !Array.isArray(rawIndexes)) throw new Error(`AWS::DynamoDB::GlobalTable GlobalSecondaryIndexes must be an array, got ${typeof rawIndexes} (${JSON.stringify(rawIndexes)?.slice(0, 200)}). An unresolved intrinsic here would otherwise deploy a table with no indexes.`);
|
|
13408
|
+
const cfnIndexes = rawIndexes ?? [];
|
|
13409
|
+
if (cfnIndexes.length === 0) return [];
|
|
13410
|
+
const replicas = properties["Replicas"] ?? [];
|
|
13411
|
+
const localReplicaIndexes = (Array.isArray(replicas) ? replicas.find((r) => asRecord(r)?.["Region"] === region) : void 0)?.["GlobalSecondaryIndexes"] ?? [];
|
|
13412
|
+
const localByName = /* @__PURE__ */ new Map();
|
|
13413
|
+
if (Array.isArray(localReplicaIndexes)) for (const entry of localReplicaIndexes) {
|
|
13414
|
+
const record = asRecord(entry);
|
|
13415
|
+
const name = record?.["IndexName"];
|
|
13416
|
+
if (record && typeof name === "string") localByName.set(name, record);
|
|
13417
|
+
}
|
|
13418
|
+
const result = [];
|
|
13419
|
+
for (const entry of cfnIndexes) {
|
|
13420
|
+
const gsi = asRecord(entry);
|
|
13421
|
+
if (!gsi) {
|
|
13422
|
+
result.push(entry);
|
|
13423
|
+
continue;
|
|
13424
|
+
}
|
|
13425
|
+
const indexName = gsi["IndexName"];
|
|
13426
|
+
const localEntry = typeof indexName === "string" ? localByName.get(indexName) : void 0;
|
|
13427
|
+
const sdk = {
|
|
13428
|
+
IndexName: indexName,
|
|
13429
|
+
KeySchema: gsi["KeySchema"],
|
|
13430
|
+
Projection: gsi["Projection"]
|
|
13431
|
+
};
|
|
13432
|
+
if (gsi["WarmThroughput"] !== void 0) sdk.WarmThroughput = gsi["WarmThroughput"];
|
|
13433
|
+
const explicitProvisioned = asRecord(gsi["ProvisionedThroughput"]);
|
|
13434
|
+
const explicitOnDemand = asRecord(gsi["OnDemandThroughput"]);
|
|
13435
|
+
if (explicitProvisioned) sdk.ProvisionedThroughput = explicitProvisioned;
|
|
13436
|
+
else if (billingMode === "PROVISIONED") sdk.ProvisionedThroughput = {
|
|
13437
|
+
ReadCapacityUnits: deriveReadCapacityUnits(asRecord(localEntry?.["ReadProvisionedThroughputSettings"])) ?? deriveReadCapacityUnits(asRecord(gsi["ReadProvisionedThroughputSettings"])) ?? DEFAULT_CAPACITY_UNITS,
|
|
13438
|
+
WriteCapacityUnits: deriveWriteCapacityUnits(asRecord(gsi["WriteProvisionedThroughputSettings"])) ?? DEFAULT_CAPACITY_UNITS
|
|
13439
|
+
};
|
|
13440
|
+
if (explicitOnDemand) sdk.OnDemandThroughput = explicitOnDemand;
|
|
13441
|
+
else if (billingMode !== "PROVISIONED") {
|
|
13442
|
+
const maxWrite = toFiniteNumber(asRecord(gsi["WriteOnDemandThroughputSettings"])?.["MaxWriteRequestUnits"]);
|
|
13443
|
+
const maxRead = toFiniteNumber(asRecord(localEntry?.["ReadOnDemandThroughputSettings"])?.["MaxReadRequestUnits"]) ?? toFiniteNumber(asRecord(gsi["ReadOnDemandThroughputSettings"])?.["MaxReadRequestUnits"]);
|
|
13444
|
+
if (maxWrite !== void 0 || maxRead !== void 0) sdk.OnDemandThroughput = {
|
|
13445
|
+
...maxRead !== void 0 && { MaxReadRequestUnits: maxRead },
|
|
13446
|
+
...maxWrite !== void 0 && { MaxWriteRequestUnits: maxWrite }
|
|
13447
|
+
};
|
|
13448
|
+
}
|
|
13449
|
+
result.push(sdk);
|
|
13450
|
+
}
|
|
13451
|
+
return result;
|
|
13452
|
+
}
|
|
13453
|
+
/**
|
|
13454
|
+
* Translate a CFn `Replicas[].GlobalSecondaryIndexes[]` blob (the
|
|
13455
|
+
* `ReplicaGlobalSecondaryIndexSpecification` shape) into the SDK's
|
|
13456
|
+
* `ReplicaGlobalSecondaryIndex[]` used by `CreateReplicationGroupMemberAction`
|
|
13457
|
+
* / `UpdateReplicationGroupMemberAction` (Issue #1387).
|
|
13458
|
+
*
|
|
13459
|
+
* Verified mapping:
|
|
13460
|
+
*
|
|
13461
|
+
* | CFn | SDK |
|
|
13462
|
+
* | ---------------------------------------------------------- | ---------------------------------------------- |
|
|
13463
|
+
* | `ReadProvisionedThroughputSettings.ReadCapacityUnits` | `ProvisionedThroughputOverride.ReadCapacityUnits` |
|
|
13464
|
+
* | `ReadOnDemandThroughputSettings.MaxReadRequestUnits` | `OnDemandThroughputOverride.MaxReadRequestUnits` |
|
|
13465
|
+
*
|
|
13466
|
+
* DELIBERATELY UNMAPPED: `ContributorInsightsSpecification`. The replica-GSI
|
|
13467
|
+
* SDK shape has no member for it — per-index contributor insights are toggled
|
|
13468
|
+
* by a separate `UpdateContributorInsights(TableName, IndexName)` call, which
|
|
13469
|
+
* this provider does not issue for any index (it only reads the TABLE-level
|
|
13470
|
+
* status back in `readCurrentState`). Recorded here rather than silently
|
|
13471
|
+
* dropped; tracked with the other GlobalTable nested-key gaps.
|
|
13472
|
+
*/
|
|
13473
|
+
function toSdkReplicaGlobalSecondaryIndexes(replicaIndexes) {
|
|
13474
|
+
if (!Array.isArray(replicaIndexes) || replicaIndexes.length === 0) return void 0;
|
|
13475
|
+
return replicaIndexes.map((entry) => {
|
|
13476
|
+
const cfn = asRecord(entry);
|
|
13477
|
+
if (!cfn) return entry;
|
|
13478
|
+
const sdk = { IndexName: cfn["IndexName"] };
|
|
13479
|
+
const explicitProvisioned = asRecord(cfn["ProvisionedThroughputOverride"]);
|
|
13480
|
+
const explicitOnDemand = asRecord(cfn["OnDemandThroughputOverride"]);
|
|
13481
|
+
const readCapacity = deriveReadCapacityUnits(asRecord(cfn["ReadProvisionedThroughputSettings"]));
|
|
13482
|
+
const maxReadRequestUnits = toFiniteNumber(asRecord(cfn["ReadOnDemandThroughputSettings"])?.["MaxReadRequestUnits"]);
|
|
13483
|
+
if (explicitProvisioned) sdk.ProvisionedThroughputOverride = explicitProvisioned;
|
|
13484
|
+
else if (readCapacity !== void 0) sdk.ProvisionedThroughputOverride = { ReadCapacityUnits: readCapacity };
|
|
13485
|
+
if (explicitOnDemand) sdk.OnDemandThroughputOverride = explicitOnDemand;
|
|
13486
|
+
else if (maxReadRequestUnits !== void 0) sdk.OnDemandThroughputOverride = { MaxReadRequestUnits: maxReadRequestUnits };
|
|
13487
|
+
return sdk;
|
|
13488
|
+
});
|
|
13489
|
+
}
|
|
13240
13490
|
function diffReplicas(oldReplicas, newReplicas) {
|
|
13241
13491
|
const oldByRegion = /* @__PURE__ */ new Map();
|
|
13242
13492
|
const newByRegion = /* @__PURE__ */ new Map();
|
|
@@ -64596,7 +64846,7 @@ function createMigrateCommand() {
|
|
|
64596
64846
|
*/
|
|
64597
64847
|
function buildProgram() {
|
|
64598
64848
|
const program = new Command();
|
|
64599
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.278.
|
|
64849
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.278.12");
|
|
64600
64850
|
program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
64601
64851
|
const { profile } = actionCommand.optsWithGlobals();
|
|
64602
64852
|
if (profile !== void 0) process.env["AWS_PROFILE"] = profile;
|