@go-to-k/cdkd 0.283.0 → 0.283.2
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-BNuwJ11q.js → asg-provider-Cl4ATw1l.js} +2 -2
- package/dist/{asg-provider-BNuwJ11q.js.map → asg-provider-Cl4ATw1l.js.map} +1 -1
- package/dist/cli.js +301 -33
- package/dist/cli.js.map +1 -1
- package/dist/{deploy-engine-CEzMNZTA.js → deploy-engine-DuYBir2W.js} +3 -3
- package/dist/{deploy-engine-CEzMNZTA.js.map → deploy-engine-DuYBir2W.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 configStringRefusal, $t as resolveStateBucketWithDefaultAndSource, A as green, An as NestedStackChildDirectDestroyError, At as BOOTSTRAP_MARKER_PREFIX, B as slowCcOperationTimeoutMs, Bt as runDockerForeground, C as MULTI_REGION_RECREATE_BLOCKED_TYPES, Ct as stringifyValue, D as bold, Dn as LocalStartServiceError, Dt as loadPublishableAssetManifest, E as formatResourceLine, En as LocalMigrateError, Et as createAssetRedirectResolver, F as clearOnUpdateRemoval, Fn as StackHasActiveImportsError, Ft as validateContainerRepoName, G as getAccountInfo, Gt as synthesisStatusMessage, H as isTerminationProtectionPropagationError, Hn as withErrorHandling, Ht as AssetManifestLoader, I as ProviderRegistry, In as StackTerminationProtectionError, It as buildDenyExternalAccessPolicy, J as normalizeAwsTagsToCfn, Jt as resolveApp, K as refStateLookupFromResource, Kt as getDefaultStateBucketName, L as findActionableSilentDrops, Lt as buildDockerImage, M as yellow, Mn as ProvisioningError, Mt as getBootstrapMarkerKey, N as IAMRoleProvider, Nn as ResourceTimeoutError, Nt as parseBootstrapMarker, O as cyan, Ot as rewriteTemplateAssetReferences, P as collectInlinePolicyNamesManagedBySiblings, Pn as ResourceUpdateNotSupportedError, Pt as validateAssetBucketName, Q as configBooleanRefusal, Qt as resolveStateBucketWithDefault, R as findSilentDropProperties, Rt as formatDockerLoginError, S as extractDeploymentEventError, St as AssetPublisher, T as renderStatefulReason, Tn as LocalInvokeBuildError$1, Tt as buildAssetRedirectMap, U as IntrinsicFunctionResolver, Ut as getDockerImageBySourceHash, V as disableInstanceApiTermination, Vn as normalizeAwsError, Vt as runDockerStreaming, W as cfnRefValueFromPhysicalId, Wt as Synthesizer, X as assertRegionMatch, Xt as resolveCaptureObservedState, Y as resolveExplicitPhysicalId, Yt as resolveAutoAssetStorage, Z as coerceCfnBoolean, Zt as resolveSkipPrefix, _ as createPreDeleteFinalSnapshot, _n as getAwsClients, _t as TemplateParser, a as DeploymentEventsStore, an as MIGRATE_TMP_PREFIX, at as s3BucketArn, b as unsupportedFinalSnapshotError, bt as rebuildClientForBucketRegion, c as replayFailedOperations, cn as expectedOwnerParam, ct as s3BucketRegionalDomainName, d as IMPLICIT_DELETE_DEPENDENCIES, dn as derivePartitionAndUrlSuffix, dt as DiffCalculator, en as resolveUseCdkBootstrapAssets, et as readConfigString, f as computeImplicitDeleteEdges, fn as AssemblyReader, ft as describeTypeWithThrottleRetry, g as ccRoutedFinalSnapshotError, gn as AwsClients, gt as DagBuilder, h as buildFinalSnapshotIdentifier, hn as resolveBucketRegion, ht as isThrottlingError, i as DeploymentEventsReader, in as CFN_TEMPLATE_URL_LIMIT, it as requireConfigString, j as red, jn as PartialFailureError, jt as ensureAssetStorage, k as gray, kn as MissingCdkCliError, kt as AssetModeResolver, l as replayRollback, ln as PARTITION_TABLE, lt as s3BucketWebsiteUrl, m as PRE_DELETE_SNAPSHOT_TYPES, mt as isRetryableTransientError, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as warnDeprecatedNoPrefixCliFlag, nt as requireConfigArray, o as planFailedOps, on as findLargeInlineResources, ot as s3BucketDomainName, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as processStackMessages, pt as withRetry, q as WAFv2WebACLProvider, qt as getLegacyStateBucketName, r as DeployEngine, rn as CFN_TEMPLATE_BODY_LIMIT, rt as requireConfigObject, s as planRollback, sn as uploadCfnTemplate, st as s3BucketDualStackDomainName, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as stateBucketExistenceConfirmed, tt as replayWarn, u as withResourceDeadline, un as canonicalizeRegion, ut as applyRoleArnIfSet, v as isFinalSnapshotError, vn as resetAwsClients, vt as LockManager, w as isStatefulRecreateTargetSync, wn as DeployCancelledError, wt as WorkGraph, x as makeCanonicalizePropertiesFn, xn as CdkdError, xt as shouldRetainResource, y as refusesFinalSnapshot, yn as setAwsClients, yt as S3StateBackend, z as CloudControlProvider, zt as getDockerCmd } from "./deploy-engine-
|
|
2
|
+
import { $ as configStringRefusal, $t as resolveStateBucketWithDefaultAndSource, A as green, An as NestedStackChildDirectDestroyError, At as BOOTSTRAP_MARKER_PREFIX, B as slowCcOperationTimeoutMs, Bt as runDockerForeground, C as MULTI_REGION_RECREATE_BLOCKED_TYPES, Ct as stringifyValue, D as bold, Dn as LocalStartServiceError, Dt as loadPublishableAssetManifest, E as formatResourceLine, En as LocalMigrateError, Et as createAssetRedirectResolver, F as clearOnUpdateRemoval, Fn as StackHasActiveImportsError, Ft as validateContainerRepoName, G as getAccountInfo, Gt as synthesisStatusMessage, H as isTerminationProtectionPropagationError, Hn as withErrorHandling, Ht as AssetManifestLoader, I as ProviderRegistry, In as StackTerminationProtectionError, It as buildDenyExternalAccessPolicy, J as normalizeAwsTagsToCfn, Jt as resolveApp, K as refStateLookupFromResource, Kt as getDefaultStateBucketName, L as findActionableSilentDrops, Lt as buildDockerImage, M as yellow, Mn as ProvisioningError, Mt as getBootstrapMarkerKey, N as IAMRoleProvider, Nn as ResourceTimeoutError, Nt as parseBootstrapMarker, O as cyan, Ot as rewriteTemplateAssetReferences, P as collectInlinePolicyNamesManagedBySiblings, Pn as ResourceUpdateNotSupportedError, Pt as validateAssetBucketName, Q as configBooleanRefusal, Qt as resolveStateBucketWithDefault, R as findSilentDropProperties, Rt as formatDockerLoginError, S as extractDeploymentEventError, St as AssetPublisher, T as renderStatefulReason, Tn as LocalInvokeBuildError$1, Tt as buildAssetRedirectMap, U as IntrinsicFunctionResolver, Ut as getDockerImageBySourceHash, V as disableInstanceApiTermination, Vn as normalizeAwsError, Vt as runDockerStreaming, W as cfnRefValueFromPhysicalId, Wt as Synthesizer, X as assertRegionMatch, Xt as resolveCaptureObservedState, Y as resolveExplicitPhysicalId, Yt as resolveAutoAssetStorage, Z as coerceCfnBoolean, Zt as resolveSkipPrefix, _ as createPreDeleteFinalSnapshot, _n as getAwsClients, _t as TemplateParser, a as DeploymentEventsStore, an as MIGRATE_TMP_PREFIX, at as s3BucketArn, b as unsupportedFinalSnapshotError, bt as rebuildClientForBucketRegion, c as replayFailedOperations, cn as expectedOwnerParam, ct as s3BucketRegionalDomainName, d as IMPLICIT_DELETE_DEPENDENCIES, dn as derivePartitionAndUrlSuffix, dt as DiffCalculator, en as resolveUseCdkBootstrapAssets, et as readConfigString, f as computeImplicitDeleteEdges, fn as AssemblyReader, ft as describeTypeWithThrottleRetry, g as ccRoutedFinalSnapshotError, gn as AwsClients, gt as DagBuilder, h as buildFinalSnapshotIdentifier, hn as resolveBucketRegion, ht as isThrottlingError, i as DeploymentEventsReader, in as CFN_TEMPLATE_URL_LIMIT, it as requireConfigString, j as red, jn as PartialFailureError, jt as ensureAssetStorage, k as gray, kn as MissingCdkCliError, kt as AssetModeResolver, l as replayRollback, ln as PARTITION_TABLE, lt as s3BucketWebsiteUrl, m as PRE_DELETE_SNAPSHOT_TYPES, mt as isRetryableTransientError, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as warnDeprecatedNoPrefixCliFlag, nt as requireConfigArray, o as planFailedOps, on as findLargeInlineResources, ot as s3BucketDomainName, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as processStackMessages, pt as withRetry, q as WAFv2WebACLProvider, qt as getLegacyStateBucketName, r as DeployEngine, rn as CFN_TEMPLATE_BODY_LIMIT, rt as requireConfigObject, s as planRollback, sn as uploadCfnTemplate, st as s3BucketDualStackDomainName, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as stateBucketExistenceConfirmed, tt as replayWarn, u as withResourceDeadline, un as canonicalizeRegion, ut as applyRoleArnIfSet, v as isFinalSnapshotError, vn as resetAwsClients, vt as LockManager, w as isStatefulRecreateTargetSync, wn as DeployCancelledError, wt as WorkGraph, x as makeCanonicalizePropertiesFn, xn as CdkdError, xt as shouldRetainResource, y as refusesFinalSnapshot, yn as setAwsClients, yt as S3StateBackend, z as CloudControlProvider, zt as getDockerCmd } from "./deploy-engine-DuYBir2W.js";
|
|
3
3
|
import { a as getLiveRenderer, c as PATTERN_B_RESOURCE_TYPES, d as generateResourceNameWithFallback, h as withStackName, i as runStackBuffered, m as withSkipPrefix, n as getLogger, o as PATTERN_B_NAME_OPTIONS, s as PATTERN_B_NAME_PROPERTIES, u as generateResourceName } from "./logger-zRrlbaQt.js";
|
|
4
|
-
import { t as ASGProvider } from "./asg-provider-
|
|
4
|
+
import { t as ASGProvider } from "./asg-provider-Cl4ATw1l.js";
|
|
5
5
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
6
6
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
7
7
|
import { CopyObjectCommand, CreateBucketCommand, DeleteBucketAnalyticsConfigurationCommand, DeleteBucketCommand, DeleteBucketCorsCommand, DeleteBucketEncryptionCommand, DeleteBucketIntelligentTieringConfigurationCommand, DeleteBucketInventoryConfigurationCommand, DeleteBucketLifecycleCommand, DeleteBucketMetricsConfigurationCommand, DeleteBucketOwnershipControlsCommand, DeleteBucketPolicyCommand, DeleteBucketReplicationCommand, DeleteBucketTaggingCommand, DeleteBucketWebsiteCommand, DeleteObjectsCommand, GetBucketAccelerateConfigurationCommand, GetBucketCorsCommand, GetBucketEncryptionCommand, GetBucketLifecycleConfigurationCommand, GetBucketLocationCommand, GetBucketLoggingCommand, GetBucketNotificationConfigurationCommand, GetBucketOwnershipControlsCommand, GetBucketPolicyCommand, GetBucketReplicationCommand, GetBucketTaggingCommand, GetBucketVersioningCommand, GetBucketWebsiteCommand, GetObjectCommand, GetObjectLockConfigurationCommand, GetPublicAccessBlockCommand, HeadBucketCommand, ListBucketAnalyticsConfigurationsCommand, ListBucketIntelligentTieringConfigurationsCommand, ListBucketInventoryConfigurationsCommand, ListBucketMetricsConfigurationsCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchBucket, PutBucketAccelerateConfigurationCommand, PutBucketAnalyticsConfigurationCommand, PutBucketCorsCommand, PutBucketEncryptionCommand, PutBucketIntelligentTieringConfigurationCommand, PutBucketInventoryConfigurationCommand, PutBucketLifecycleConfigurationCommand, PutBucketLoggingCommand, PutBucketMetricsConfigurationCommand, PutBucketNotificationConfigurationCommand, PutBucketOwnershipControlsCommand, PutBucketPolicyCommand, PutBucketReplicationCommand, PutBucketTaggingCommand, PutBucketVersioningCommand, PutBucketWebsiteCommand, PutObjectCommand, PutObjectLockConfigurationCommand, PutPublicAccessBlockCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
|
|
@@ -9139,15 +9139,24 @@ var SQSQueueProvider = class {
|
|
|
9139
9139
|
}
|
|
9140
9140
|
}
|
|
9141
9141
|
/**
|
|
9142
|
-
* Construct SQS queue ARN from account/region/queue name
|
|
9142
|
+
* Construct SQS queue ARN from account/region/queue name.
|
|
9143
|
+
*
|
|
9144
|
+
* The partition is derived from the region through the same closed mapping
|
|
9145
|
+
* `${AWS::Partition}` uses (issue #1815) rather than hardcoded to `aws` —
|
|
9146
|
+
* this ARN is recorded into state and served as the queue's `Arn`
|
|
9147
|
+
* attribute, so a commercial literal is structurally valid but wrong in
|
|
9148
|
+
* `aws-cn` / `aws-us-gov` and nothing downstream rejects it.
|
|
9143
9149
|
*/
|
|
9144
9150
|
async constructArn(queueName) {
|
|
9145
9151
|
try {
|
|
9146
9152
|
const accountId = (await this.stsClient.send(new GetCallerIdentityCommand({}))).Account;
|
|
9147
|
-
|
|
9153
|
+
const region = await this.sqsClient.config.region();
|
|
9154
|
+
const { partition } = derivePartitionAndUrlSuffix(region);
|
|
9155
|
+
return `arn:${partition}:sqs:${region}:${accountId}:${queueName}`;
|
|
9148
9156
|
} catch {
|
|
9149
9157
|
this.logger.warn("Failed to construct SQS ARN from STS, using placeholder");
|
|
9150
|
-
|
|
9158
|
+
const { partition } = derivePartitionAndUrlSuffix(process.env["AWS_REGION"] ?? "");
|
|
9159
|
+
return `arn:${partition}:sqs:unknown:unknown:${queueName}`;
|
|
9151
9160
|
}
|
|
9152
9161
|
}
|
|
9153
9162
|
/**
|
|
@@ -15484,10 +15493,16 @@ var DynamoDBGlobalTableProvider = class {
|
|
|
15484
15493
|
};
|
|
15485
15494
|
if (tableArn) await this.applyTagDiff(tableArn, extractLocalTags(previousProperties), extractLocalTags(properties));
|
|
15486
15495
|
const recordedOldBilling = previousProperties["BillingMode"];
|
|
15487
|
-
const
|
|
15488
|
-
const
|
|
15489
|
-
const
|
|
15490
|
-
|
|
15496
|
+
const recordedOldBillingAbsent = recordedOldBilling === void 0;
|
|
15497
|
+
const recordedOldBillingUsable = typeof recordedOldBilling === "string" && recordedOldBilling.trim() !== "";
|
|
15498
|
+
const rawLiveBillingMode = describeResp.Table?.BillingModeSummary?.BillingMode;
|
|
15499
|
+
const reportedBillingMode = rawLiveBillingMode === "PROVISIONED" || rawLiveBillingMode === "PAY_PER_REQUEST" ? rawLiveBillingMode : void 0;
|
|
15500
|
+
const liveBillingMode = reportedBillingMode ?? "PROVISIONED";
|
|
15501
|
+
const desiredDeclaresBillingMode = properties["BillingMode"] !== void 0;
|
|
15502
|
+
const seedAbsentFromLive = recordedOldBillingAbsent && desiredDeclaresBillingMode;
|
|
15503
|
+
const oldBilling = recordedOldBillingUsable ? recordedOldBilling : recordedOldBillingAbsent ? seedAbsentFromLive ? liveBillingMode : "PAY_PER_REQUEST" : liveBillingMode;
|
|
15504
|
+
if (!recordedOldBillingUsable && !recordedOldBillingAbsent) this.logger.warn(`AWS::DynamoDB::GlobalTable ${logicalId}: the recorded previous BillingMode is unusable (${JSON.stringify(recordedOldBilling)}) — using the table's actual billing mode (${oldBilling}) as the comparison baseline for this update so a corrected template does not issue a same-mode UpdateTable.`);
|
|
15505
|
+
if (seedAbsentFromLive && oldBilling !== "PAY_PER_REQUEST") this.logger.warn(`AWS::DynamoDB::GlobalTable ${logicalId}: the cdkd state record declares no BillingMode — using ${oldBilling} as the comparison baseline for this update (${reportedBillingMode !== void 0 ? "the mode DescribeTable reports" : "inferred: DescribeTable reports no BillingModeSummary, which means the table was created without an explicit mode"}), so a template declaring a different mode still applies the flip instead of comparing equal to the create-path default.`);
|
|
15491
15506
|
let billingUnusable = false;
|
|
15492
15507
|
const requestedBilling = requireConfigString(properties["BillingMode"], "PAY_PER_REQUEST", "AWS::DynamoDB::GlobalTable BillingMode", { onUnusable: (message) => {
|
|
15493
15508
|
billingUnusable = true;
|
|
@@ -15575,6 +15590,7 @@ var DynamoDBGlobalTableProvider = class {
|
|
|
15575
15590
|
effectiveProperties = { ...effectiveProperties ?? properties };
|
|
15576
15591
|
if (recordedOldBilling === void 0) delete effectiveProperties["BillingMode"];
|
|
15577
15592
|
else effectiveProperties["BillingMode"] = oldBilling;
|
|
15593
|
+
effectiveProperties = retainUnsendableCapacityMembers(effectiveProperties, previousProperties, newBilling);
|
|
15578
15594
|
}
|
|
15579
15595
|
const awsOnDemand = describeResp.Table?.OnDemandThroughput;
|
|
15580
15596
|
const onDemandPayload = {};
|
|
@@ -17533,6 +17549,185 @@ function stripProvisionedCapacityKeys(properties) {
|
|
|
17533
17549
|
return result;
|
|
17534
17550
|
}
|
|
17535
17551
|
/**
|
|
17552
|
+
* The capacity member keys that can only reach AWS while the table is
|
|
17553
|
+
* PROVISIONED, per container level (issue #1738).
|
|
17554
|
+
*
|
|
17555
|
+
* Identical to the set {@link stripProvisionedCapacityKeys} removes, and that
|
|
17556
|
+
* is not a coincidence: both answer "which members are unsendable once the mode
|
|
17557
|
+
* is PAY_PER_REQUEST". The two spellings a pre-#1387 cdkd wrote into state
|
|
17558
|
+
* (`ProvisionedThroughput` / `ProvisionedThroughputOverride`) are included for
|
|
17559
|
+
* the same reason — a state replay is exactly that population.
|
|
17560
|
+
*/
|
|
17561
|
+
const PROVISIONED_ONLY_CAPACITY_KEYS = {
|
|
17562
|
+
table: ["WriteProvisionedThroughputSettings"],
|
|
17563
|
+
index: [
|
|
17564
|
+
"WriteProvisionedThroughputSettings",
|
|
17565
|
+
"ReadProvisionedThroughputSettings",
|
|
17566
|
+
"ProvisionedThroughput"
|
|
17567
|
+
],
|
|
17568
|
+
replica: ["ReadProvisionedThroughputSettings", "ProvisionedThroughputOverride"],
|
|
17569
|
+
replicaIndex: ["ReadProvisionedThroughputSettings", "ProvisionedThroughputOverride"]
|
|
17570
|
+
};
|
|
17571
|
+
/**
|
|
17572
|
+
* The mirror set: capacity members that can only reach AWS while the table is
|
|
17573
|
+
* PAY_PER_REQUEST (issue #1738).
|
|
17574
|
+
*
|
|
17575
|
+
* `stripProvisionedCapacityKeys` has no equivalent because the create arm it
|
|
17576
|
+
* serves always substitutes PAY_PER_REQUEST — the mode under which these ARE
|
|
17577
|
+
* sent, which is why its header says they are deliberately not stripped. On the
|
|
17578
|
+
* UPDATE path the kept mode can be PROVISIONED, and then it is this half that
|
|
17579
|
+
* never leaves the process.
|
|
17580
|
+
*/
|
|
17581
|
+
const ON_DEMAND_ONLY_CAPACITY_KEYS = {
|
|
17582
|
+
table: ["WriteOnDemandThroughputSettings"],
|
|
17583
|
+
index: [
|
|
17584
|
+
"WriteOnDemandThroughputSettings",
|
|
17585
|
+
"ReadOnDemandThroughputSettings",
|
|
17586
|
+
"OnDemandThroughput"
|
|
17587
|
+
],
|
|
17588
|
+
replica: ["ReadOnDemandThroughputSettings", "OnDemandThroughputOverride"],
|
|
17589
|
+
replicaIndex: ["ReadOnDemandThroughputSettings", "OnDemandThroughputOverride"]
|
|
17590
|
+
};
|
|
17591
|
+
/**
|
|
17592
|
+
* Replace every capacity member the KEPT billing mode cannot send with the
|
|
17593
|
+
* PREVIOUS record's value (issue #1738).
|
|
17594
|
+
*
|
|
17595
|
+
* Called from `update()`'s `BillingMode` warn-and-KEEP arm, where an unusable
|
|
17596
|
+
* desired mode suppresses the flip: AWS is left holding the mode it already
|
|
17597
|
+
* had, so every block belonging to the OTHER mode was silently dropped on the
|
|
17598
|
+
* way out while the engine recorded what the template declared.
|
|
17599
|
+
*
|
|
17600
|
+
* **The split is per MEMBER against the KEPT mode**, and each side was read off
|
|
17601
|
+
* the gates in this file rather than off the member's name-shape (the
|
|
17602
|
+
* name-shape trap #1726 records — an on-demand ceiling looks like capacity and
|
|
17603
|
+
* goes on the wire under precisely the on-demand mode):
|
|
17604
|
+
*
|
|
17605
|
+
* - KEPT `PROVISIONED` — the on-demand half is unsendable. Step 3's table-level
|
|
17606
|
+
* `OnDemandThroughput` is gated on `newBilling !== 'PROVISIONED'`;
|
|
17607
|
+
* `toSdkGlobalSecondaryIndexes` and `toSdkReplicaThroughputOverrides` both
|
|
17608
|
+
* drop their on-demand branch under PROVISIONED. The provisioned half is NOT
|
|
17609
|
+
* retained: step 4b and step 6b's auto-scaling reconcile are live whenever
|
|
17610
|
+
* either side is PROVISIONED, and step 6's GSI diff carries per-index
|
|
17611
|
+
* `ProvisionedThroughput` — those blocks really are applied.
|
|
17612
|
+
* - KEPT `PAY_PER_REQUEST` — the provisioned half is unsendable. The table-level
|
|
17613
|
+
* `ProvisionedThroughput` rides step 4's flip and nothing else, the two
|
|
17614
|
+
* auto-scaling reconciles are gated on either side being PROVISIONED, and both
|
|
17615
|
+
* translators drop their provisioned branch. The on-demand half is NOT
|
|
17616
|
+
* retained: step 3 sends the table-level ceilings and step 6 the per-index
|
|
17617
|
+
* ones under exactly this mode.
|
|
17618
|
+
*
|
|
17619
|
+
* One residual is deliberately NOT covered, because the suppression did not
|
|
17620
|
+
* create it: the TABLE-level provisioned capacity NUMBER rides step 4's flip
|
|
17621
|
+
* and nothing else, so on ANY non-flip PROVISIONED -> PROVISIONED update it is
|
|
17622
|
+
* unsent while its `*CapacityAutoScalingSettings` sibling in the same block IS
|
|
17623
|
+
* reconciled. Retaining the block wholesale under a kept PROVISIONED mode would
|
|
17624
|
+
* therefore erase a real auto-scaling update to hide a pre-existing gap — so
|
|
17625
|
+
* the block stays as declared and the gap stays where it already lives.
|
|
17626
|
+
*
|
|
17627
|
+
* Retaining rather than DROPPING is the UPDATE row of
|
|
17628
|
+
* `.claude/rules/providers.md`: the call never ran, so AWS still holds the
|
|
17629
|
+
* previously-applied block and that IS what state should describe. Dropping
|
|
17630
|
+
* would leave a later template that REMOVES the block deriving no removal, so
|
|
17631
|
+
* the live setting would survive forever.
|
|
17632
|
+
*
|
|
17633
|
+
* **The previous side is VALIDATED before it is retained** (the #1653-review
|
|
17634
|
+
* rule) through `asRecord` — the SAME predicate every wire read of these blocks
|
|
17635
|
+
* applies, so the two cannot disagree about what a bare string / an array / a
|
|
17636
|
+
* number means. Be honest about what that buys: it refuses exactly the
|
|
17637
|
+
* not-a-plain-object shapes, and a block whose NUMERIC member is an unresolved
|
|
17638
|
+
* intrinsic passes it, because the wire accepts that block too (and then sends
|
|
17639
|
+
* nothing for the member, which is the same "AWS keeps what it had" outcome).
|
|
17640
|
+
* When the previous side is unusable OR absent the key is DROPPED — there is no
|
|
17641
|
+
* value cdkd can vouch for either way.
|
|
17642
|
+
*
|
|
17643
|
+
* COPIES each retained block one level rather than aliasing it: the rollback
|
|
17644
|
+
* executor spreads the returned bag shallowly, so handing back the previous
|
|
17645
|
+
* record's own object would leave two state records sharing one mutable value.
|
|
17646
|
+
* Scope that claim honestly — it covers the retained blocks only; every other
|
|
17647
|
+
* key of the input bag stays aliased, exactly as the sibling arms leave it.
|
|
17648
|
+
*
|
|
17649
|
+
* Deliberately NOT paired with a `canonicalizeDesiredProperties` twin: this is
|
|
17650
|
+
* a SKIP, not a narrowing, so there is no pure function of the desired bag to
|
|
17651
|
+
* fold both comparison sides with, and folding one would derive a REMOVAL of a
|
|
17652
|
+
* live capacity block from a template whose only fault is `BillingMode`.
|
|
17653
|
+
*
|
|
17654
|
+
* Pure and non-mutating at every level.
|
|
17655
|
+
*/
|
|
17656
|
+
function retainUnsendableCapacityMembers(desired, previous, keptBillingMode) {
|
|
17657
|
+
const unsendable = keptBillingMode === "PROVISIONED" ? ON_DEMAND_ONLY_CAPACITY_KEYS : PROVISIONED_ONLY_CAPACITY_KEYS;
|
|
17658
|
+
const result = retainCapacityKeys({ ...desired }, previous, unsendable.table);
|
|
17659
|
+
const indexes = result["GlobalSecondaryIndexes"];
|
|
17660
|
+
if (Array.isArray(indexes)) {
|
|
17661
|
+
const previousIndexes = indexCapacityContainers(previous["GlobalSecondaryIndexes"], "IndexName");
|
|
17662
|
+
result["GlobalSecondaryIndexes"] = indexes.map((entry) => {
|
|
17663
|
+
const gsi = asRecord$1(entry);
|
|
17664
|
+
if (!gsi) return entry;
|
|
17665
|
+
const previousGsi = previousIndexes.get(gsi["IndexName"]);
|
|
17666
|
+
return retainCapacityKeys({ ...gsi }, previousGsi, unsendable.index);
|
|
17667
|
+
});
|
|
17668
|
+
}
|
|
17669
|
+
const replicas = result["Replicas"];
|
|
17670
|
+
if (Array.isArray(replicas)) {
|
|
17671
|
+
const previousReplicas = indexCapacityContainers(previous["Replicas"], "Region");
|
|
17672
|
+
result["Replicas"] = replicas.map((entry) => {
|
|
17673
|
+
const replica = asRecord$1(entry);
|
|
17674
|
+
if (!replica) return entry;
|
|
17675
|
+
const previousReplica = previousReplicas.get(replica["Region"]);
|
|
17676
|
+
const copy = retainCapacityKeys({ ...replica }, previousReplica, unsendable.replica);
|
|
17677
|
+
const replicaIndexes = copy["GlobalSecondaryIndexes"];
|
|
17678
|
+
if (Array.isArray(replicaIndexes)) {
|
|
17679
|
+
const previousReplicaIndexes = indexCapacityContainers(previousReplica?.["GlobalSecondaryIndexes"], "IndexName");
|
|
17680
|
+
const kept = replicaIndexes.map((indexEntry) => {
|
|
17681
|
+
const gsi = asRecord$1(indexEntry);
|
|
17682
|
+
if (!gsi) return indexEntry;
|
|
17683
|
+
const previousGsi = previousReplicaIndexes.get(gsi["IndexName"]);
|
|
17684
|
+
return retainCapacityKeys({ ...gsi }, previousGsi, unsendable.replicaIndex);
|
|
17685
|
+
}).filter((entry) => {
|
|
17686
|
+
const gsi = asRecord$1(entry);
|
|
17687
|
+
if (!gsi) return true;
|
|
17688
|
+
return Object.keys(gsi).some((k) => k !== "IndexName");
|
|
17689
|
+
});
|
|
17690
|
+
if (kept.length > 0) copy["GlobalSecondaryIndexes"] = kept;
|
|
17691
|
+
else delete copy["GlobalSecondaryIndexes"];
|
|
17692
|
+
}
|
|
17693
|
+
return copy;
|
|
17694
|
+
});
|
|
17695
|
+
}
|
|
17696
|
+
return result;
|
|
17697
|
+
}
|
|
17698
|
+
/**
|
|
17699
|
+
* Retain (or drop) one container's unsendable capacity members, in place on a
|
|
17700
|
+
* bag the caller already copied.
|
|
17701
|
+
*
|
|
17702
|
+
* The counterpart container being `undefined` — no matching index / replica in
|
|
17703
|
+
* the previous record — is the ABSENT case, not a special one: there is nothing
|
|
17704
|
+
* to vouch for, so the key is dropped exactly as it is for an unusable value.
|
|
17705
|
+
*/
|
|
17706
|
+
function retainCapacityKeys(target, previousContainer, keys) {
|
|
17707
|
+
for (const key of keys) {
|
|
17708
|
+
const previousValue = asRecord$1(previousContainer?.[key]);
|
|
17709
|
+
if (previousValue) target[key] = { ...previousValue };
|
|
17710
|
+
else delete target[key];
|
|
17711
|
+
}
|
|
17712
|
+
return target;
|
|
17713
|
+
}
|
|
17714
|
+
/**
|
|
17715
|
+
* Index a previous-side array by its identity member, so a per-index /
|
|
17716
|
+
* per-replica retain reads the counterpart entry rather than the positional
|
|
17717
|
+
* one — AWS does not guarantee readback order and a template edit can reorder
|
|
17718
|
+
* either list.
|
|
17719
|
+
*/
|
|
17720
|
+
function indexCapacityContainers(value, identityKey) {
|
|
17721
|
+
const byIdentity = /* @__PURE__ */ new Map();
|
|
17722
|
+
if (!Array.isArray(value)) return byIdentity;
|
|
17723
|
+
for (const entry of value) {
|
|
17724
|
+
const record = asRecord$1(entry);
|
|
17725
|
+
const identity = record?.[identityKey];
|
|
17726
|
+
if (record && typeof identity === "string") byIdentity.set(identity, record);
|
|
17727
|
+
}
|
|
17728
|
+
return byIdentity;
|
|
17729
|
+
}
|
|
17730
|
+
/**
|
|
17536
17731
|
* True when a CFn sub-object is nothing but an unresolved intrinsic
|
|
17537
17732
|
* (`{"Fn::If": […]}` / `{"Ref": …}`), i.e. the template DID declare the block
|
|
17538
17733
|
* but its value could not be resolved to a shape with members.
|
|
@@ -18239,14 +18434,23 @@ var LogsLogGroupProvider = class {
|
|
|
18239
18434
|
}
|
|
18240
18435
|
}
|
|
18241
18436
|
/**
|
|
18242
|
-
* Build log group ARN from name
|
|
18437
|
+
* Build log group ARN from name.
|
|
18438
|
+
*
|
|
18439
|
+
* The partition is derived from the region through the same closed mapping
|
|
18440
|
+
* `${AWS::Partition}` uses (issue #1815) rather than hardcoded to `aws` —
|
|
18441
|
+
* this ARN is recorded into state and served as the log group's `Arn`
|
|
18442
|
+
* attribute, so a commercial literal is structurally valid but wrong in
|
|
18443
|
+
* `aws-cn` / `aws-us-gov` and nothing downstream rejects it.
|
|
18243
18444
|
*/
|
|
18244
18445
|
async buildArn(logGroupName) {
|
|
18245
18446
|
try {
|
|
18246
18447
|
const accountId = (await this.stsClient.send(new GetCallerIdentityCommand({}))).Account;
|
|
18247
|
-
|
|
18448
|
+
const region = await this.logsClient.config.region() || process.env["AWS_REGION"] || "us-east-1";
|
|
18449
|
+
const { partition } = derivePartitionAndUrlSuffix(region);
|
|
18450
|
+
return `arn:${partition}:logs:${region}:${accountId}:log-group:${logGroupName}:*`;
|
|
18248
18451
|
} catch {
|
|
18249
|
-
|
|
18452
|
+
const { partition } = derivePartitionAndUrlSuffix(process.env["AWS_REGION"] ?? "");
|
|
18453
|
+
return `arn:${partition}:logs:unknown:unknown:log-group:${logGroupName}:*`;
|
|
18250
18454
|
}
|
|
18251
18455
|
}
|
|
18252
18456
|
/**
|
|
@@ -18507,9 +18711,12 @@ var CloudWatchAlarmProvider = class {
|
|
|
18507
18711
|
this.logger.debug(`Failed to describe alarm ${alarmName}, constructing ARN from config: ${error instanceof Error ? error.message : String(error)}`);
|
|
18508
18712
|
}
|
|
18509
18713
|
try {
|
|
18510
|
-
|
|
18714
|
+
const region = await this.cloudWatchClient.config.region() || process.env["AWS_REGION"] || "us-east-1";
|
|
18715
|
+
const { partition } = derivePartitionAndUrlSuffix(region);
|
|
18716
|
+
return `arn:${partition}:cloudwatch:${region}:*:alarm:${alarmName}`;
|
|
18511
18717
|
} catch {
|
|
18512
|
-
|
|
18718
|
+
const { partition } = derivePartitionAndUrlSuffix(process.env["AWS_REGION"] ?? "");
|
|
18719
|
+
return `arn:${partition}:cloudwatch:*:*:alarm:${alarmName}`;
|
|
18513
18720
|
}
|
|
18514
18721
|
}
|
|
18515
18722
|
/**
|
|
@@ -24797,13 +25004,23 @@ var ApiGatewayProvider = class ApiGatewayProvider {
|
|
|
24797
25004
|
/**
|
|
24798
25005
|
* Build the ARN for an API Gateway Stage, used for tag mutations.
|
|
24799
25006
|
*
|
|
24800
|
-
* Format:
|
|
25007
|
+
* Format:
|
|
25008
|
+
* `arn:{partition}:apigateway:{region}::/restapis/{restApiId}/stages/{stageName}`.
|
|
24801
25009
|
* The double colon (`::`) is intentional: API Gateway tagging uses an
|
|
24802
25010
|
* account-id-less ARN.
|
|
25011
|
+
*
|
|
25012
|
+
* The partition is derived from the region through the same closed mapping
|
|
25013
|
+
* `${AWS::Partition}` uses (issue #1815) rather than hardcoded to `aws`.
|
|
25014
|
+
* Unlike the pure attribute builders this one is passed straight to
|
|
25015
|
+
* `TagResource` / `UntagResource` as `resourceArn`, so in `aws-cn` /
|
|
25016
|
+
* `aws-us-gov` a commercial literal does not just record a wrong string —
|
|
25017
|
+
* it aims the tag mutation at an ARN that names no stage.
|
|
24803
25018
|
*/
|
|
24804
25019
|
async buildStageArn(restApiId, stageName) {
|
|
24805
25020
|
try {
|
|
24806
|
-
|
|
25021
|
+
const region = await this.apiGatewayClient.config.region();
|
|
25022
|
+
const { partition } = derivePartitionAndUrlSuffix(region);
|
|
25023
|
+
return `arn:${partition}:apigateway:${region}::/restapis/${restApiId}/stages/${stageName}`;
|
|
24807
25024
|
} catch {
|
|
24808
25025
|
return;
|
|
24809
25026
|
}
|
|
@@ -38556,11 +38773,19 @@ var ServiceDiscoveryProvider = class ServiceDiscoveryProvider {
|
|
|
38556
38773
|
}
|
|
38557
38774
|
/**
|
|
38558
38775
|
* Build a namespace ARN from namespace ID.
|
|
38559
|
-
* Format: arn:
|
|
38776
|
+
* Format: `arn:{partition}:servicediscovery:{region}:{account}:namespace/{namespaceId}`
|
|
38777
|
+
*
|
|
38778
|
+
* The partition is derived from the region through the same closed mapping
|
|
38779
|
+
* `${AWS::Partition}` uses (issue #1815) rather than hardcoded to `aws` —
|
|
38780
|
+
* this ARN is recorded into state and served as the namespace's `Arn`
|
|
38781
|
+
* attribute, so a commercial-partition literal is silently wrong (but
|
|
38782
|
+
* structurally valid, hence unrejected) in `aws-cn` / `aws-us-gov`.
|
|
38560
38783
|
*/
|
|
38561
38784
|
async buildNamespaceArn(namespaceId) {
|
|
38562
38785
|
const accountId = (await this.getStsClient().send(new GetCallerIdentityCommand({}))).Account || "";
|
|
38563
|
-
|
|
38786
|
+
const region = await this.getClient().config.region();
|
|
38787
|
+
const { partition } = derivePartitionAndUrlSuffix(region);
|
|
38788
|
+
return `arn:${partition}:servicediscovery:${region}:${accountId}:namespace/${namespaceId}`;
|
|
38564
38789
|
}
|
|
38565
38790
|
};
|
|
38566
38791
|
|
|
@@ -43208,12 +43433,35 @@ var BudgetsBudgetProvider = class {
|
|
|
43208
43433
|
}
|
|
43209
43434
|
/**
|
|
43210
43435
|
* Budget ARN for the tagging APIs (`ListTagsForResource` / `TagResource` /
|
|
43211
|
-
* `UntagResource`)
|
|
43212
|
-
*
|
|
43213
|
-
* ARNs
|
|
43214
|
-
|
|
43215
|
-
|
|
43216
|
-
|
|
43436
|
+
* `UntagResource`), and the `Arn` attribute recorded into state.
|
|
43437
|
+
*
|
|
43438
|
+
* Budgets ARNs carry no region component, but they DO carry a partition, so
|
|
43439
|
+
* a region is still needed to name it. It is read from the RESOLVED region
|
|
43440
|
+
* of the very client that receives this ARN — the same
|
|
43441
|
+
* `getClient().config.region()` the `delete()` path already consults for
|
|
43442
|
+
* its `assertRegionMatch` guard — and routed through the closed mapping
|
|
43443
|
+
* `${AWS::Partition}` uses (issue #1815).
|
|
43444
|
+
*
|
|
43445
|
+
* Asking the CLIENT rather than `providerRegion` is what makes the ARN and
|
|
43446
|
+
* its consumer agree. `providerRegion` is `process.env['AWS_REGION']`, and
|
|
43447
|
+
* when that is unset `getClient()` builds `new BudgetsClient({})`, leaving
|
|
43448
|
+
* the SDK to resolve the region from its OWN chain (`AWS_DEFAULT_REGION`,
|
|
43449
|
+
* the `~/.aws/config` profile). So a profile-configured `cn-north-1` /
|
|
43450
|
+
* `us-gov-*` caller would have derived the COMMERCIAL partition from an
|
|
43451
|
+
* empty string while the client itself talked to a non-commercial endpoint
|
|
43452
|
+
* — on the PRIMARY path, not a fallback.
|
|
43453
|
+
*
|
|
43454
|
+
* The `aws` partition USED to be hardcoded here on the stated assumption
|
|
43455
|
+
* that non-`aws` partitions were unsupported. That was wrong in the quiet
|
|
43456
|
+
* direction: the literal is structurally valid everywhere, so in `aws-cn` /
|
|
43457
|
+
* `aws-us-gov` nothing rejected it — the ARN was simply recorded into state
|
|
43458
|
+
* and handed to `TagResource` naming no budget. A client whose region is
|
|
43459
|
+
* unset or unrecognized still derives to `aws`, so commercial output is
|
|
43460
|
+
* unchanged byte for byte.
|
|
43461
|
+
*/
|
|
43462
|
+
async budgetArn(accountId, budgetName) {
|
|
43463
|
+
const { partition } = derivePartitionAndUrlSuffix(await this.getClient().config.region() ?? "");
|
|
43464
|
+
return `arn:${partition}:budgets::${accountId}:budget/${budgetName}`;
|
|
43217
43465
|
}
|
|
43218
43466
|
/**
|
|
43219
43467
|
* Convert a CFn `Spend` shape to the SDK shape. CFn templates carry
|
|
@@ -43369,7 +43617,7 @@ var BudgetsBudgetProvider = class {
|
|
|
43369
43617
|
this.logger.debug(`Successfully created budget ${logicalId}: ${name}`);
|
|
43370
43618
|
return {
|
|
43371
43619
|
physicalId: name,
|
|
43372
|
-
attributes: { Arn: this.budgetArn(accountId, name) }
|
|
43620
|
+
attributes: { Arn: await this.budgetArn(accountId, name) }
|
|
43373
43621
|
};
|
|
43374
43622
|
} catch (error) {
|
|
43375
43623
|
if (error instanceof ProvisioningError) throw error;
|
|
@@ -43396,7 +43644,7 @@ var BudgetsBudgetProvider = class {
|
|
|
43396
43644
|
return {
|
|
43397
43645
|
physicalId,
|
|
43398
43646
|
wasReplaced: false,
|
|
43399
|
-
attributes: { Arn: this.budgetArn(accountId, physicalId) }
|
|
43647
|
+
attributes: { Arn: await this.budgetArn(accountId, physicalId) }
|
|
43400
43648
|
};
|
|
43401
43649
|
} catch (error) {
|
|
43402
43650
|
if (error instanceof ProvisioningError) throw error;
|
|
@@ -43512,7 +43760,7 @@ var BudgetsBudgetProvider = class {
|
|
|
43512
43760
|
async reconcileResourceTags(accountId, budgetName, oldTags, newTags) {
|
|
43513
43761
|
const sortedJson = (tags) => JSON.stringify([...tags].sort((a, b) => (a.Key ?? "").localeCompare(b.Key ?? "")));
|
|
43514
43762
|
if (sortedJson(oldTags) === sortedJson(newTags)) return;
|
|
43515
|
-
const arn = this.budgetArn(accountId, budgetName);
|
|
43763
|
+
const arn = await this.budgetArn(accountId, budgetName);
|
|
43516
43764
|
const newKeys = new Set(newTags.map((t) => t.Key));
|
|
43517
43765
|
const removedKeys = oldTags.map((t) => t.Key).filter((k) => {
|
|
43518
43766
|
return typeof k === "string" && !newKeys.has(k);
|
|
@@ -43555,7 +43803,7 @@ var BudgetsBudgetProvider = class {
|
|
|
43555
43803
|
/**
|
|
43556
43804
|
* `Fn::GetAtt` support. CloudFormation documents no attributes for
|
|
43557
43805
|
* `AWS::Budgets::Budget`; `Arn` is served as a cdkd convenience (computed
|
|
43558
|
-
* — Budgets ARNs are `arn:
|
|
43806
|
+
* — Budgets ARNs are `arn:{partition}:budgets::{account}:budget/{name}`, verified
|
|
43559
43807
|
* to exist via `DescribeBudget` first).
|
|
43560
43808
|
*/
|
|
43561
43809
|
async getAttribute(physicalId, resourceType, attributeName) {
|
|
@@ -43566,7 +43814,7 @@ var BudgetsBudgetProvider = class {
|
|
|
43566
43814
|
AccountId: accountId,
|
|
43567
43815
|
BudgetName: physicalId
|
|
43568
43816
|
}));
|
|
43569
|
-
return this.budgetArn(accountId, physicalId);
|
|
43817
|
+
return await this.budgetArn(accountId, physicalId);
|
|
43570
43818
|
} catch (error) {
|
|
43571
43819
|
const cause = error instanceof Error ? error : void 0;
|
|
43572
43820
|
throw new ProvisioningError(`Failed to resolve Arn for budget ${physicalId}: ${cause?.message ?? String(error)}`, resourceType, physicalId, physicalId, cause);
|
|
@@ -43591,7 +43839,7 @@ var BudgetsBudgetProvider = class {
|
|
|
43591
43839
|
}));
|
|
43592
43840
|
return {
|
|
43593
43841
|
physicalId: explicit,
|
|
43594
|
-
attributes: { Arn: this.budgetArn(accountId, explicit) }
|
|
43842
|
+
attributes: { Arn: await this.budgetArn(accountId, explicit) }
|
|
43595
43843
|
};
|
|
43596
43844
|
} catch (error) {
|
|
43597
43845
|
if (error instanceof NotFoundException$5) return null;
|
|
@@ -51387,13 +51635,33 @@ var S3DirectoryBucketProvider = class {
|
|
|
51387
51635
|
return { Arn: await this.buildBucketArn(bucketName) };
|
|
51388
51636
|
}
|
|
51389
51637
|
/**
|
|
51390
|
-
* Directory bucket ARN:
|
|
51638
|
+
* Directory bucket ARN:
|
|
51639
|
+
* `arn:{partition}:s3express:{region}:{account}:bucket/{name}`.
|
|
51391
51640
|
* Also the `ResourceArn` for the S3 Control tag operations. Callers that
|
|
51392
51641
|
* already resolved the account (for the S3 Control `AccountId` parameter)
|
|
51393
51642
|
* pass it in so the STS lookup runs once per operation.
|
|
51643
|
+
*
|
|
51644
|
+
* The partition is derived from the region through the same closed mapping
|
|
51645
|
+
* `${AWS::Partition}` uses (issue #1815) rather than hardcoded to `aws`.
|
|
51646
|
+
* Here it is load-bearing TWICE over: the value is served as the bucket's
|
|
51647
|
+
* `Arn` attribute AND passed to S3 Control as the `ResourceArn` of a tag
|
|
51648
|
+
* mutation, so outside the commercial partition the wrong literal does not
|
|
51649
|
+
* merely record a bad string — it aims the tag call at an ARN that does not
|
|
51650
|
+
* name this bucket.
|
|
51651
|
+
*
|
|
51652
|
+
* KNOWN BOUND (pre-existing, not introduced by #1815): the region — and now
|
|
51653
|
+
* the partition derived from it — comes from `s3Client`, while the tag
|
|
51654
|
+
* calls that consume this ARN go through `s3ControlClient`, built from
|
|
51655
|
+
* `providerRegion` (`process.env['AWS_REGION']`). Those two can disagree,
|
|
51656
|
+
* so the ARN can name a different region than the client receiving it. The
|
|
51657
|
+
* region SEGMENT already had this exposure before the partition rode along
|
|
51658
|
+
* with it; unifying the two clients' region resolution is a separate change.
|
|
51394
51659
|
*/
|
|
51395
51660
|
async buildBucketArn(bucketName, accountId) {
|
|
51396
|
-
|
|
51661
|
+
const region = await this.getRegion();
|
|
51662
|
+
const account = accountId ?? await this.getAccountId();
|
|
51663
|
+
const { partition } = derivePartitionAndUrlSuffix(region);
|
|
51664
|
+
return `arn:${partition}:s3express:${region}:${account}:bucket/${bucketName}`;
|
|
51397
51665
|
}
|
|
51398
51666
|
/**
|
|
51399
51667
|
* Create an S3 Express Directory Bucket
|
|
@@ -76252,7 +76520,7 @@ function createMigrateCommand() {
|
|
|
76252
76520
|
*/
|
|
76253
76521
|
function buildProgram() {
|
|
76254
76522
|
const program = new Command();
|
|
76255
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.283.
|
|
76523
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.283.2");
|
|
76256
76524
|
program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
76257
76525
|
const { profile } = actionCommand.optsWithGlobals();
|
|
76258
76526
|
if (profile !== void 0) process.env["AWS_PROFILE"] = profile;
|