@go-to-k/cdkd 0.229.8 → 0.230.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +46 -126
- package/dist/cli.js.map +1 -1
- package/dist/{deploy-engine-rMH9694Q.js → deploy-engine-_N5kVjZN.js} +144 -4
- package/dist/deploy-engine-_N5kVjZN.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/deploy-engine-rMH9694Q.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { A as withErrorHandling, B as generateResourceName, C as StackHasActiveImportsError, F as getLiveRenderer, H as withSkipPrefix, I as PATTERN_B_NAME_OPTIONS, L as PATTERN_B_NAME_PROPERTIES, M as getLogger, P as runStackBuffered, R as PATTERN_B_RESOURCE_TYPES, S as ResourceUpdateNotSupportedError, U as withStackName, V as generateResourceNameWithFallback, _ as MissingCdkCliError, a as assertRegionMatch, b as ProvisioningError, f as LocalInvokeBuildError$1, i as resolveExplicitPhysicalId, k as normalizeAwsError, l as CdkdError, m as LocalStartServiceError, n as matchesCdkPath, o as disableInstanceApiTermination, p as LocalMigrateError, r as normalizeAwsTagsToCfn, s as isTerminationProtectionPropagationError, t as CDK_PATH_TAG, v as NestedStackChildDirectDestroyError, w as StackTerminationProtectionError, x as ResourceTimeoutError, y as PartialFailureError } from "./import-helpers-DayvBD4T.js";
|
|
3
3
|
import { a as setAwsClients, i as resetAwsClients, r as getAwsClients, t as AwsClients } from "./aws-clients-pjPwZz1r.js";
|
|
4
|
-
import { $ as
|
|
4
|
+
import { $ as CFN_TEMPLATE_BODY_LIMIT, A as LockManager, B as runDockerForeground, C as findActionableSilentDrops, D as DiffCalculator, E as applyRoleArnIfSet, F as stringifyValue, G as getDefaultStateBucketName, H as AssetManifestLoader, I as WorkGraph, J as resolveCaptureObservedState, K as getLegacyStateBucketName, L as buildDockerImage, M as rebuildClientForBucketRegion, N as shouldRetainResource, O as DagBuilder, P as AssetPublisher, Q as warnDeprecatedNoPrefixCliFlag, R as formatDockerLoginError, S as ProviderRegistry, T as IntrinsicFunctionResolver, U as getDockerImageBySourceHash, V as runDockerStreaming, W as Synthesizer, X as resolveStateBucketWithDefault, Y as resolveSkipPrefix, Z as resolveStateBucketWithDefaultAndSource, _ as green, a as withRetry, b as IAMRoleProvider, c as computeImplicitDeleteEdges, d as isStatefulRecreateTargetSync, et as CFN_TEMPLATE_URL_LIMIT, f as renderStatefulReason, g as gray, h as cyan, i as withResourceDeadline, it as AssemblyReader, j as S3StateBackend, k as TemplateParser, l as extractDeploymentEventError, m as bold, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nt as findLargeInlineResources, o as isRetryableTransientError, ot as resolveBucketRegion, p as formatResourceLine, q as resolveApp, r as DeployEngine, rt as uploadCfnTemplate, s as IMPLICIT_DELETE_DEPENDENCIES, t as DEFAULT_RESOURCE_TIMEOUT_MS, tt as MIGRATE_TMP_PREFIX, u as MULTI_REGION_RECREATE_BLOCKED_TYPES, v as red, w as CloudControlProvider, x as collectInlinePolicyNamesManagedBySiblings, y as yellow, z as getDockerCmd } from "./deploy-engine-_N5kVjZN.js";
|
|
5
5
|
import { t as ASGProvider } from "./asg-provider-Dgj3loIG.js";
|
|
6
6
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
7
7
|
import { randomBytes, randomUUID } from "node:crypto";
|
|
@@ -491,6 +491,7 @@ const recreateViaSdkProviderOption = new Option("--recreate-via-sdk-provider <lo
|
|
|
491
491
|
* into a footgun; pretending to scope it per-resource is misleading).
|
|
492
492
|
*/
|
|
493
493
|
const forceStatefulRecreationOption = new Option("--force-stateful-recreation", "Bypass the stateful-resource guard for --recreate-via-cc-api targets. Required when ANY named target is a stateful type (RDS / DynamoDB / EFS / S3 with data / Logs with retention / Cognito / Secrets / SSM / Glue / ECR / CloudFront / Kinesis / OpenSearch). Destroy + recreate loses ALL data in the resource — no automatic data migration. Triple-opt-in for CI use: --recreate-via-cc-api <id> --force-stateful-recreation --yes.").default(false);
|
|
494
|
+
const replaceOption = new Option("--replace", "Replace (DELETE + CREATE) a resource whose in-place update is rejected because an immutable property changed and AWS exposes no update API for it (e.g. Lambda LayerVersion content, EFS AccessPoint, ECS TaskDefinition, ApiGatewayV2 immutable fields). Without this flag such a change fails the deploy. Stateful types (RDS / DynamoDB / EFS / S3 with data / Logs with retention / etc.) ALSO require --force-stateful-recreation since the replacement is a data-losing DELETE + CREATE.").default(false);
|
|
494
495
|
const deployOptions = [
|
|
495
496
|
new Option("--concurrency <number>", "Maximum concurrent resource operations").default(10).argParser((value) => parseInt(value, 10)),
|
|
496
497
|
new Option("--stack-concurrency <number>", "Maximum concurrent stack deployments").default(4).argParser((value) => parseInt(value, 10)),
|
|
@@ -509,6 +510,7 @@ const deployOptions = [
|
|
|
509
510
|
recreateViaCcApiOption,
|
|
510
511
|
recreateViaSdkProviderOption,
|
|
511
512
|
forceStatefulRecreationOption,
|
|
513
|
+
replaceOption,
|
|
512
514
|
...resourceTimeoutOptions
|
|
513
515
|
];
|
|
514
516
|
/**
|
|
@@ -983,119 +985,6 @@ function createListCommand() {
|
|
|
983
985
|
return cmd;
|
|
984
986
|
}
|
|
985
987
|
|
|
986
|
-
//#endregion
|
|
987
|
-
//#region src/provisioning/stateful-types.ts
|
|
988
|
-
/**
|
|
989
|
-
* Stateful-resource guard list (issue [#615]).
|
|
990
|
-
*
|
|
991
|
-
* `--recreate-via-cc-api <LogicalId>` destroys + recreates the named
|
|
992
|
-
* resource in one deploy so a previously-silent-dropped top-level CFn
|
|
993
|
-
* property reaches AWS via Cloud Control API. For most types this is
|
|
994
|
-
* safe — destroying + recreating an IAM Role or a Lambda Function
|
|
995
|
-
* loses no user data — but for **data-bearing** types the destroy
|
|
996
|
-
* cycle loses everything in the resource: rows in a DynamoDB table,
|
|
997
|
-
* objects in an S3 bucket, log lines in a LogGroup, images in an ECR
|
|
998
|
-
* repository, etc.
|
|
999
|
-
*
|
|
1000
|
-
* To avoid an accidental data-loss footgun, cdkd refuses to recreate
|
|
1001
|
-
* any resource whose type is in {@link STATEFUL_TYPES} unless the user
|
|
1002
|
-
* ALSO passes `--force-stateful-recreation`. The two-flag protection
|
|
1003
|
-
* mirrors `--remove-protection`'s pattern (see
|
|
1004
|
-
* `src/cli/commands/destroy-runner.ts`).
|
|
1005
|
-
*
|
|
1006
|
-
* The list is hand-curated and intentionally **conservative**: every
|
|
1007
|
-
* type here carries user data that the AWS service does NOT
|
|
1008
|
-
* automatically migrate to the replacement resource. Types that the
|
|
1009
|
-
* AWS service treats as ephemeral (e.g. Lambda Function, IAM Role)
|
|
1010
|
-
* are NOT in this list — recreate is cheap.
|
|
1011
|
-
*
|
|
1012
|
-
* Two entries are **conditionally stateful** — they only count when
|
|
1013
|
-
* the resource actually contains data:
|
|
1014
|
-
*
|
|
1015
|
-
* - `AWS::S3::Bucket`: empty buckets are safe to recreate. The
|
|
1016
|
-
* deploy engine probes `s3:ListObjectsV2` at plan time and only
|
|
1017
|
-
* refuses when the bucket has at least one object.
|
|
1018
|
-
* - `AWS::Logs::LogGroup`: a log group with `RetentionInDays`
|
|
1019
|
-
* undefined or zero is functionally ephemeral. The deploy engine
|
|
1020
|
-
* refuses only when `RetentionInDays > 0`.
|
|
1021
|
-
*
|
|
1022
|
-
* Both conditional checks live in {@link isStatefulRecreateTarget};
|
|
1023
|
-
* the bare {@link STATEFUL_TYPES} set is the type-only first-cut.
|
|
1024
|
-
*/
|
|
1025
|
-
const STATEFUL_TYPES = new Set([
|
|
1026
|
-
"AWS::RDS::DBInstance",
|
|
1027
|
-
"AWS::RDS::DBCluster",
|
|
1028
|
-
"AWS::DocDB::DBInstance",
|
|
1029
|
-
"AWS::DocDB::DBCluster",
|
|
1030
|
-
"AWS::Neptune::DBInstance",
|
|
1031
|
-
"AWS::Neptune::DBCluster",
|
|
1032
|
-
"AWS::DynamoDB::Table",
|
|
1033
|
-
"AWS::DynamoDB::GlobalTable",
|
|
1034
|
-
"AWS::EFS::FileSystem",
|
|
1035
|
-
"AWS::S3::Bucket",
|
|
1036
|
-
"AWS::ECR::Repository",
|
|
1037
|
-
"AWS::Kinesis::Stream",
|
|
1038
|
-
"AWS::Elasticsearch::Domain",
|
|
1039
|
-
"AWS::OpenSearchService::Domain",
|
|
1040
|
-
"AWS::Cognito::UserPool",
|
|
1041
|
-
"AWS::SecretsManager::Secret",
|
|
1042
|
-
"AWS::SSM::Parameter",
|
|
1043
|
-
"AWS::Glue::Database",
|
|
1044
|
-
"AWS::Glue::Table",
|
|
1045
|
-
"AWS::Logs::LogGroup",
|
|
1046
|
-
"AWS::CloudFront::Distribution"
|
|
1047
|
-
]);
|
|
1048
|
-
/**
|
|
1049
|
-
* Multi-region resource types — `--recreate-via-cc-api` refuses these
|
|
1050
|
-
* outright in v1 regardless of `--force-stateful-recreation`. Design
|
|
1051
|
-
* doc §8 calls these "out of scope": the destroy + recreate cycle
|
|
1052
|
-
* across replica regions is more involved than a single-region
|
|
1053
|
-
* destroy-and-create (replica regions, automated backups, eventual
|
|
1054
|
-
* consistency across the replication mesh, etc.).
|
|
1055
|
-
*
|
|
1056
|
-
* Distinct from {@link STATEFUL_TYPES} — STATEFUL_TYPES gates on data
|
|
1057
|
-
* loss (bypassable with `--force-stateful-recreation`); this set is
|
|
1058
|
-
* an out-of-scope refusal (no bypass).
|
|
1059
|
-
*/
|
|
1060
|
-
const MULTI_REGION_RECREATE_BLOCKED_TYPES = new Set(["AWS::DynamoDB::GlobalTable"]);
|
|
1061
|
-
/**
|
|
1062
|
-
* Cheap, synchronous read of the resource's recorded properties only.
|
|
1063
|
-
* For `AWS::S3::Bucket` this returns `null` — the live `ListObjectsV2`
|
|
1064
|
-
* probe to distinguish empty buckets (safe to recreate) from
|
|
1065
|
-
* non-empty (data loss) lives in
|
|
1066
|
-
* `src/deployment/recreate-targets.ts#probeStatefulRecreateTargetsAsync`
|
|
1067
|
-
* (issue [#648]) and runs after this sync first-cut. Sync callers can
|
|
1068
|
-
* still treat `null` as "not stateful" — the deploy command does both
|
|
1069
|
-
* passes back-to-back; only callers that explicitly opt out of the
|
|
1070
|
-
* async probe need to assume conservative "stateful" semantics.
|
|
1071
|
-
*
|
|
1072
|
-
* Returns the {@link StatefulReason} when the type is stateful (or
|
|
1073
|
-
* `null` for non-stateful types).
|
|
1074
|
-
*/
|
|
1075
|
-
function isStatefulRecreateTargetSync(resourceType, recordedProperties) {
|
|
1076
|
-
if (!STATEFUL_TYPES.has(resourceType)) return null;
|
|
1077
|
-
if (resourceType === "AWS::Logs::LogGroup") {
|
|
1078
|
-
const retention = recordedProperties?.["RetentionInDays"];
|
|
1079
|
-
if (typeof retention === "number" && retention > 0) return "has-retention";
|
|
1080
|
-
return null;
|
|
1081
|
-
}
|
|
1082
|
-
if (resourceType === "AWS::S3::Bucket") return null;
|
|
1083
|
-
return "always";
|
|
1084
|
-
}
|
|
1085
|
-
/**
|
|
1086
|
-
* Human-readable rendering of {@link StatefulReason} for error
|
|
1087
|
-
* messages. Used by the pre-flight guard's "X resources require
|
|
1088
|
-
* --force-stateful-recreation" listing.
|
|
1089
|
-
*/
|
|
1090
|
-
function renderStatefulReason(reason) {
|
|
1091
|
-
switch (reason) {
|
|
1092
|
-
case "always": return "destroy loses all data in the resource";
|
|
1093
|
-
case "has-objects": return "S3 bucket is non-empty";
|
|
1094
|
-
case "has-retention": return "log group retains data (RetentionInDays > 0)";
|
|
1095
|
-
case null: return "(not stateful)";
|
|
1096
|
-
}
|
|
1097
|
-
}
|
|
1098
|
-
|
|
1099
988
|
//#endregion
|
|
1100
989
|
//#region src/deployment/recreate-targets.ts
|
|
1101
990
|
/**
|
|
@@ -1556,7 +1445,7 @@ const FLUSH_INTERVAL_MS = 2e3;
|
|
|
1556
1445
|
const FLUSH_EVENT_THRESHOLD = 50;
|
|
1557
1446
|
/** Build-time cdkd version, with a dev fallback for non-built contexts. */
|
|
1558
1447
|
function getCdkdVersion() {
|
|
1559
|
-
return "0.
|
|
1448
|
+
return "0.230.1";
|
|
1560
1449
|
}
|
|
1561
1450
|
/**
|
|
1562
1451
|
* Generate a time-sortable unique run id, e.g.
|
|
@@ -29213,7 +29102,7 @@ var GlueSecurityConfigurationProvider = class {
|
|
|
29213
29102
|
/**
|
|
29214
29103
|
* Read AWS-current SecurityConfiguration shape via
|
|
29215
29104
|
* `GetSecurityConfiguration`. Always emits the three CFn-modeled
|
|
29216
|
-
* sub-configs (`
|
|
29105
|
+
* sub-configs (`S3Encryptions: []`, `CloudWatchEncryption: {}`,
|
|
29217
29106
|
* `JobBookmarksEncryption: {}`) per PR #145 even when AWS reports
|
|
29218
29107
|
* nothing — closes the "console-side encryption enable on a previously
|
|
29219
29108
|
* default config" detection gap on the v3 baseline.
|
|
@@ -29276,13 +29165,14 @@ function sleep$1(ms) {
|
|
|
29276
29165
|
/**
|
|
29277
29166
|
* Build the SDK `EncryptionConfiguration` from the CFn-shape input
|
|
29278
29167
|
* (`AWS::Glue::SecurityConfiguration.EncryptionConfiguration`). Each
|
|
29279
|
-
* sub-config (`
|
|
29280
|
-
* `JobBookmarksEncryption`)
|
|
29281
|
-
*
|
|
29168
|
+
* sub-config (`S3Encryptions[]` / `CloudWatchEncryption` /
|
|
29169
|
+
* `JobBookmarksEncryption`) maps to the SDK member names — `CloudWatchEncryption`
|
|
29170
|
+
* / `JobBookmarksEncryption` match verbatim, but the CFn `S3Encryptions` (plural)
|
|
29171
|
+
* list maps to the SDK `S3Encryption` (singular) field.
|
|
29282
29172
|
*/
|
|
29283
29173
|
function buildEncryptionConfiguration(input) {
|
|
29284
29174
|
const result = {};
|
|
29285
|
-
if (Array.isArray(input["
|
|
29175
|
+
if (Array.isArray(input["S3Encryptions"])) result.S3Encryption = input["S3Encryptions"].map((entry) => {
|
|
29286
29176
|
const e = entry;
|
|
29287
29177
|
const item = {};
|
|
29288
29178
|
if (typeof e["S3EncryptionMode"] === "string") item.S3EncryptionMode = e["S3EncryptionMode"];
|
|
@@ -29308,7 +29198,7 @@ function buildEncryptionConfiguration(input) {
|
|
|
29308
29198
|
/**
|
|
29309
29199
|
* Reverse-map AWS's `EncryptionConfiguration` SDK shape into the CFn
|
|
29310
29200
|
* shape with always-emit placeholders (PR #145):
|
|
29311
|
-
* - `
|
|
29201
|
+
* - `S3Encryptions[]` → `?? []` (so console-side ADD is detectable)
|
|
29312
29202
|
* - `CloudWatchEncryption` → `?? {}`
|
|
29313
29203
|
* - `JobBookmarksEncryption` → `?? {}`
|
|
29314
29204
|
* - `DataQualityEncryption` → silently dropped (not in CFn schema)
|
|
@@ -29316,7 +29206,7 @@ function buildEncryptionConfiguration(input) {
|
|
|
29316
29206
|
function mapEncryptionConfigurationToCfn(cfg) {
|
|
29317
29207
|
const c = cfg ?? {};
|
|
29318
29208
|
return {
|
|
29319
|
-
|
|
29209
|
+
S3Encryptions: (c.S3Encryption ?? []).map((entry) => {
|
|
29320
29210
|
const out = {};
|
|
29321
29211
|
if (entry.S3EncryptionMode !== void 0) out["S3EncryptionMode"] = entry.S3EncryptionMode;
|
|
29322
29212
|
if (entry.KmsKeyArn !== void 0) out["KmsKeyArn"] = entry.KmsKeyArn;
|
|
@@ -35203,6 +35093,32 @@ var ECRProvider = class {
|
|
|
35203
35093
|
return this.client;
|
|
35204
35094
|
}
|
|
35205
35095
|
/**
|
|
35096
|
+
* Map CFn `ImageScanningConfiguration` (PascalCase `{ ScanOnPush }`) to the
|
|
35097
|
+
* SDK shape (camelCase `{ scanOnPush }`). The SDK input keys are camelCase;
|
|
35098
|
+
* forwarding the CFn-cased object verbatim makes the SDK ignore the unknown
|
|
35099
|
+
* `ScanOnPush` key and silently default `scanOnPush` to `false` — so
|
|
35100
|
+
* `imageScanOnPush: true` never reached AWS. Returns `undefined` for an
|
|
35101
|
+
* absent config so the caller can omit the field.
|
|
35102
|
+
*/
|
|
35103
|
+
toSdkScanningConfig(cfn) {
|
|
35104
|
+
if (!cfn) return void 0;
|
|
35105
|
+
return { scanOnPush: Boolean(cfn["ScanOnPush"]) };
|
|
35106
|
+
}
|
|
35107
|
+
/**
|
|
35108
|
+
* Map CFn `EncryptionConfiguration` (PascalCase `{ EncryptionType, KmsKey }`)
|
|
35109
|
+
* to the SDK shape (camelCase `{ encryptionType, kmsKey }`). Same casing trap
|
|
35110
|
+
* as scanning config — a KMS repo's `KmsKey` would be silently dropped (and
|
|
35111
|
+
* the type would fall back to AES256) without this mapping.
|
|
35112
|
+
*/
|
|
35113
|
+
toSdkEncryptionConfig(cfn) {
|
|
35114
|
+
if (!cfn) return void 0;
|
|
35115
|
+
const encryptionType = cfn["EncryptionType"];
|
|
35116
|
+
if (!encryptionType) return void 0;
|
|
35117
|
+
const out = { encryptionType };
|
|
35118
|
+
if (encryptionType === "KMS" && cfn["KmsKey"]) out.kmsKey = cfn["KmsKey"];
|
|
35119
|
+
return out;
|
|
35120
|
+
}
|
|
35121
|
+
/**
|
|
35206
35122
|
* Create an ECR Repository
|
|
35207
35123
|
*/
|
|
35208
35124
|
async create(logicalId, resourceType, properties) {
|
|
@@ -35210,11 +35126,13 @@ var ECRProvider = class {
|
|
|
35210
35126
|
const repositoryName = properties["RepositoryName"] || generateResourceName(logicalId, { maxLength: 256 }).toLowerCase();
|
|
35211
35127
|
try {
|
|
35212
35128
|
const tags = properties["Tags"];
|
|
35129
|
+
const scanningConfig = this.toSdkScanningConfig(properties["ImageScanningConfiguration"]);
|
|
35130
|
+
const encryptionConfig = this.toSdkEncryptionConfig(properties["EncryptionConfiguration"]);
|
|
35213
35131
|
const repo = (await this.getClient().send(new CreateRepositoryCommand({
|
|
35214
35132
|
repositoryName,
|
|
35215
|
-
...
|
|
35133
|
+
...scanningConfig ? { imageScanningConfiguration: scanningConfig } : {},
|
|
35216
35134
|
...properties["ImageTagMutability"] ? { imageTagMutability: properties["ImageTagMutability"] } : {},
|
|
35217
|
-
...
|
|
35135
|
+
...encryptionConfig ? { encryptionConfiguration: encryptionConfig } : {},
|
|
35218
35136
|
...tags ? { tags } : {}
|
|
35219
35137
|
}))).repository;
|
|
35220
35138
|
if (!repo?.repositoryName) throw new Error("CreateRepository did not return repository name");
|
|
@@ -35265,7 +35183,7 @@ var ECRProvider = class {
|
|
|
35265
35183
|
if (JSON.stringify(newScanConfig) !== JSON.stringify(oldScanConfig)) {
|
|
35266
35184
|
await this.getClient().send(new PutImageScanningConfigurationCommand({
|
|
35267
35185
|
repositoryName: physicalId,
|
|
35268
|
-
imageScanningConfiguration: newScanConfig ?? { scanOnPush: false }
|
|
35186
|
+
imageScanningConfiguration: this.toSdkScanningConfig(newScanConfig) ?? { scanOnPush: false }
|
|
35269
35187
|
}));
|
|
35270
35188
|
this.logger.debug(`Updated image scanning configuration for ${physicalId}`);
|
|
35271
35189
|
}
|
|
@@ -37072,6 +36990,8 @@ async function deployCommand(stacks, options) {
|
|
|
37072
36990
|
...eventRecorder && { eventRecorder },
|
|
37073
36991
|
...recreateViaCcApiTargets && recreateViaCcApiTargets.size > 0 && { recreateViaCcApiTargets },
|
|
37074
36992
|
...recreateViaSdkProviderTargets && recreateViaSdkProviderTargets.size > 0 && { recreateViaSdkProviderTargets },
|
|
36993
|
+
...options.replace && { replace: true },
|
|
36994
|
+
...options.forceStatefulRecreation && { forceStatefulRecreation: true },
|
|
37075
36995
|
captureObservedState: resolveCaptureObservedState(options.captureObservedState),
|
|
37076
36996
|
...options.resourceWarnAfter?.globalMs !== void 0 && { resourceWarnAfterMs: options.resourceWarnAfter.globalMs },
|
|
37077
36997
|
...options.resourceTimeout?.globalMs !== void 0 && { resourceTimeoutMs: options.resourceTimeout.globalMs },
|
|
@@ -55070,7 +54990,7 @@ function reorderArgs(argv) {
|
|
|
55070
54990
|
async function main() {
|
|
55071
54991
|
installPipeCloseHandler();
|
|
55072
54992
|
const program = new Command();
|
|
55073
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.
|
|
54993
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.230.1");
|
|
55074
54994
|
program.addCommand(createBootstrapCommand());
|
|
55075
54995
|
program.addCommand(createSynthCommand());
|
|
55076
54996
|
program.addCommand(createListCommand());
|