@go-to-k/cdkd 0.162.3 → 0.164.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -37,6 +37,8 @@ import { AddTagsToResourceCommand as AddTagsToResourceCommand$1, CreateDBCluster
37
37
  import { Command, Option } from "commander";
38
38
  import { writeFileSync as writeFileSync$1 } from "fs";
39
39
  import { join as join$1 } from "path";
40
+ import * as readline$1 from "node:readline/promises";
41
+ import readline from "node:readline/promises";
40
42
  import * as zlib from "node:zlib";
41
43
  import { ApplicationAutoScalingClient, DeleteScalingPolicyCommand, DeregisterScalableTargetCommand, DescribeScalableTargetsCommand, DescribeScalingPoliciesCommand, PutScalingPolicyCommand, RegisterScalableTargetCommand } from "@aws-sdk/client-application-auto-scaling";
42
44
  import { ApiGatewayV2Client, CreateApiCommand, CreateAuthorizerCommand as CreateAuthorizerCommand$1, CreateIntegrationCommand, CreateRouteCommand as CreateRouteCommand$1, CreateStageCommand as CreateStageCommand$1, DeleteApiCommand, DeleteAuthorizerCommand as DeleteAuthorizerCommand$1, DeleteIntegrationCommand, DeleteRouteCommand as DeleteRouteCommand$1, DeleteStageCommand as DeleteStageCommand$1, GetApiCommand, GetApisCommand, GetAuthorizerCommand as GetAuthorizerCommand$1, GetIntegrationCommand, GetRouteCommand, GetStageCommand as GetStageCommand$1, NotFoundException as NotFoundException$3, UpdateApiCommand, UpdateAuthorizerCommand as UpdateAuthorizerCommand$1, UpdateIntegrationCommand, UpdateRouteCommand, UpdateStageCommand as UpdateStageCommand$1 } from "@aws-sdk/client-apigatewayv2";
@@ -59,7 +61,6 @@ import { BatchGetProjectsCommand, CodeBuildClient, CreateProjectCommand, DeleteP
59
61
  import { CreateVectorBucketCommand, DeleteIndexCommand, DeleteVectorBucketCommand, GetVectorBucketCommand, ListIndexesCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$18, ListVectorBucketsCommand, S3VectorsClient } from "@aws-sdk/client-s3vectors";
60
62
  import { CreateNamespaceCommand, CreateTableBucketCommand, CreateTableCommand as CreateTableCommand$2, DeleteNamespaceCommand as DeleteNamespaceCommand$1, DeleteTableBucketCommand, DeleteTableCommand as DeleteTableCommand$2, GetTableBucketCommand, GetTableCommand as GetTableCommand$1, ListNamespacesCommand as ListNamespacesCommand$1, ListTableBucketsCommand, ListTablesCommand as ListTablesCommand$1, ListTagsForResourceCommand as ListTagsForResourceCommand$19, NotFoundException as NotFoundException$5, S3TablesClient } from "@aws-sdk/client-s3tables";
61
63
  import { AttachLoadBalancerTargetGroupsCommand, AttachLoadBalancersCommand, AttachTrafficSourcesCommand, AutoScalingClient, CreateAutoScalingGroupCommand, CreateOrUpdateTagsCommand, DeleteAutoScalingGroupCommand, DeleteLifecycleHookCommand, DeleteNotificationConfigurationCommand, DeleteTagsCommand as DeleteTagsCommand$1, DescribeAutoScalingGroupsCommand, DescribeLifecycleHooksCommand, DescribeNotificationConfigurationsCommand, DescribeTrafficSourcesCommand, DetachLoadBalancerTargetGroupsCommand, DetachLoadBalancersCommand, DetachTrafficSourcesCommand, DisableMetricsCollectionCommand, EnableMetricsCollectionCommand, PutLifecycleHookCommand, PutNotificationConfigurationCommand, UpdateAutoScalingGroupCommand } from "@aws-sdk/client-auto-scaling";
62
- import * as readline from "node:readline/promises";
63
64
  import { Document, Pair, Scalar, YAMLMap, YAMLSeq, parse as parse$1, stringify } from "yaml";
64
65
  import { mkdir, mkdtemp } from "node:fs/promises";
65
66
  import { Readable } from "node:stream";
@@ -1004,9 +1005,12 @@ const MULTI_REGION_RECREATE_BLOCKED_TYPES = new Set(["AWS::DynamoDB::GlobalTable
1004
1005
  * Cheap, synchronous read of the resource's recorded properties only.
1005
1006
  * For `AWS::S3::Bucket` this returns `null` — the live `ListObjectsV2`
1006
1007
  * probe to distinguish empty buckets (safe to recreate) from
1007
- * non-empty (data loss) needs an S3 client + an AWS round-trip and is
1008
- * deferred to a follow-up issue (v1 sync-defers; an `--force-stateful-
1009
- * recreation` is recommended for any potentially-non-empty S3 target).
1008
+ * non-empty (data loss) lives in
1009
+ * `src/deployment/recreate-targets.ts#probeStatefulRecreateTargetsAsync`
1010
+ * (issue [#648]) and runs after this sync first-cut. Sync callers can
1011
+ * still treat `null` as "not stateful" — the deploy command does both
1012
+ * passes back-to-back; only callers that explicitly opt out of the
1013
+ * async probe need to assume conservative "stateful" semantics.
1010
1014
  *
1011
1015
  * Returns the {@link StatefulReason} when the type is stateful (or
1012
1016
  * `null` for non-stateful types).
@@ -1038,11 +1042,47 @@ function renderStatefulReason(reason) {
1038
1042
  //#endregion
1039
1043
  //#region src/deployment/recreate-targets.ts
1040
1044
  /**
1045
+ * Pre-flight validation for `--recreate-via-cc-api <LogicalId>` deploy
1046
+ * flag (issue [#615]).
1047
+ *
1048
+ * Three things to validate before the deploy engine acts on the user's
1049
+ * recreate list:
1050
+ *
1051
+ * 1. Every named logical id MUST exist in the synth template. A typo
1052
+ * should fail fast, not silently skip.
1053
+ * 2. Every named logical id MUST exist in cdkd state (the recreate
1054
+ * operation requires an existing physical resource to destroy +
1055
+ * recreate). A logical id in the template but absent from state
1056
+ * is a CREATE on the next deploy regardless — recreate is a
1057
+ * no-op for fresh deploys and should error out with a clear
1058
+ * message rather than silently apply.
1059
+ * 3. Stateful-resource guard: every named target whose resource type
1060
+ * is in {@link STATEFUL_TYPES} (or conditionally stateful — S3
1061
+ * bucket with objects, LogGroup with retention) MUST be matched
1062
+ * by an explicit `--force-stateful-recreation` flag. The sync
1063
+ * first-cut runs from the recorded properties alone; the live
1064
+ * `s3:ListObjectsV2` probe (issue [#648]) promotes a `null`
1065
+ * reason to `'has-objects'` when a bucket actually contains data.
1066
+ * 4. Multi-region refusal: every named target whose resource type
1067
+ * is in {@link MULTI_REGION_RECREATE_BLOCKED_TYPES} (e.g.
1068
+ * `AWS::DynamoDB::GlobalTable`) is refused outright. Out of
1069
+ * scope for v1; no `--force-stateful-recreation` bypass since
1070
+ * this is a structural limitation, not a data-loss footgun.
1071
+ *
1072
+ * Plus one cross-flag invariant: `--recreate-via-cc-api MyLambda`
1073
+ * combined with `--allow-unsupported-properties AWS::Lambda::Function:LoggingConfig`
1074
+ * on a resource whose template carries `LoggingConfig` is **ambiguous
1075
+ * intent** — does the user want SDK + silent drop, or CC migration?
1076
+ * Fail fast and let the user pick one strategy per resource.
1077
+ */
1078
+ /**
1041
1079
  * Plan-time validation of the user's recreate-via-cc-api list.
1042
1080
  *
1043
- * Pure with respect to AWS — does NOT probe S3 bucket emptiness. The
1044
- * S3 conditional check is deferred to a follow-up issue (the live
1045
- * `s3:ListObjectsV2` probe is out of scope for v1).
1081
+ * Pure with respect to AWS — does NOT probe S3 bucket emptiness. Wrap
1082
+ * the result with {@link probeAndRevalidateStateful} to promote S3
1083
+ * targets' `statefulReason` via a live `s3:ListObjectsV2` round-trip
1084
+ * before rendering errors. The deploy command does this; the validator
1085
+ * itself stays sync so unit tests don't need an S3 mock.
1046
1086
  *
1047
1087
  * Input order is preserved; duplicate logical ids in the user's input
1048
1088
  * are deduplicated.
@@ -1137,6 +1177,140 @@ function renderRecreateTargetsErrors(validation) {
1137
1177
  }
1138
1178
  return lines.length > 0 ? lines.join("\n") : null;
1139
1179
  }
1180
+ /**
1181
+ * Async S3 object probe (issue [#648]).
1182
+ *
1183
+ * For every `AWS::S3::Bucket` target whose sync {@link StatefulReason}
1184
+ * is `null` (the sync map defers — see {@link isStatefulRecreateTargetSync}),
1185
+ * issues a single-page `ListObjectVersions(MaxKeys=1)` against the
1186
+ * bucket's recorded physical id. When the bucket has at least one
1187
+ * current object, prior version, OR delete-marker, promotes the
1188
+ * target's `statefulReason` to `'has-objects'`.
1189
+ *
1190
+ * Uses `ListObjectVersions` rather than `ListObjectsV2` so the probe
1191
+ * mirrors the s3-bucket-provider's `emptyBucket` view: a versioned
1192
+ * bucket whose current keys have all been soft-deleted (so
1193
+ * `ListObjectsV2.KeyCount === 0`) still holds prior versions +
1194
+ * delete-markers that the destroy + recreate cycle would lose. Using
1195
+ * the same listing API as the provider ensures the probe and the
1196
+ * destroy path agree on "empty".
1197
+ *
1198
+ * **Soft-fail on probe errors**: if `ListObjectVersions` throws
1199
+ * (permission denied, bucket-not-found mid-flight, transient network
1200
+ * error), logs a warn and leaves the target's `statefulReason` at the
1201
+ * sync result (`null`). The user can decide to proceed without the
1202
+ * probe by passing `--force-stateful-recreation`.
1203
+ *
1204
+ * Returns a NEW array of targets; the input is not mutated. Non-S3
1205
+ * targets and S3 targets whose sync reason is already non-null are
1206
+ * passed through unchanged.
1207
+ */
1208
+ async function probeStatefulRecreateTargetsAsync(targets, s3Client, logger = getLogger().child("recreate-targets")) {
1209
+ const promoted = [];
1210
+ for (const target of targets) {
1211
+ if (target.resourceType !== "AWS::S3::Bucket" || target.statefulReason !== null) {
1212
+ promoted.push({ ...target });
1213
+ continue;
1214
+ }
1215
+ try {
1216
+ const result = await s3Client.send(new ListObjectVersionsCommand({
1217
+ Bucket: target.physicalId,
1218
+ MaxKeys: 1
1219
+ }));
1220
+ const hasVersions = (result.Versions?.length ?? 0) > 0;
1221
+ const hasDeleteMarkers = (result.DeleteMarkers?.length ?? 0) > 0;
1222
+ if (hasVersions || hasDeleteMarkers) promoted.push({
1223
+ ...target,
1224
+ statefulReason: "has-objects"
1225
+ });
1226
+ else promoted.push({ ...target });
1227
+ } catch (e) {
1228
+ logger.warn(`--recreate-via-cc-api: live S3 probe failed for ${target.logicalId} (bucket ${target.physicalId}); leaving stateful guard at the sync result. If the bucket might be non-empty, re-run with --force-stateful-recreation. Underlying error: ${e instanceof Error ? e.message : String(e)}`);
1229
+ promoted.push({ ...target });
1230
+ }
1231
+ }
1232
+ return promoted;
1233
+ }
1234
+ /**
1235
+ * Async re-validation of the stateful-guard slice of a
1236
+ * {@link RecreateTargetsValidation}, after promoting S3 bucket reasons
1237
+ * via {@link probeStatefulRecreateTargetsAsync}.
1238
+ *
1239
+ * Skips the probe entirely when `forceStatefulRecreation: true` — the
1240
+ * sync validation already omits the blocked list in that case, and
1241
+ * skipping avoids an unnecessary AWS round-trip (plus permission-denied
1242
+ * warn-and-skip cycle on low-privilege CI roles).
1243
+ *
1244
+ * Returns a NEW validation; the input is not mutated. Non-stateful
1245
+ * categories (`unknownLogicalIds` / `missingFromState` /
1246
+ * `ambiguousIntent` / `blockedMultiRegionTargets`) are preserved verbatim.
1247
+ */
1248
+ async function probeAndRevalidateStateful(input) {
1249
+ if (input.forceStatefulRecreation) return input.validation;
1250
+ const promoted = await probeStatefulRecreateTargetsAsync(input.validation.targets, input.s3Client);
1251
+ const blockedStatefulTargets = promoted.filter((t) => t.statefulReason !== null);
1252
+ return {
1253
+ ...input.validation,
1254
+ targets: promoted,
1255
+ blockedStatefulTargets
1256
+ };
1257
+ }
1258
+
1259
+ //#endregion
1260
+ //#region src/cli/commands/recreate-confirm-prompt.ts
1261
+ /**
1262
+ * Interactive confirmation prompt for `cdkd deploy --recreate-via-cc-api`
1263
+ * (issue [#649]).
1264
+ *
1265
+ * Mirror of {@link ../prefix-migration-check.ts}'s `promptMigrationConfirm`
1266
+ * but for the recreate-via-cc-api destroy+recreate cycle:
1267
+ *
1268
+ * - `opts.yes` (CDK CLI parity `-y` / `--yes`) skips the prompt and
1269
+ * prints the per-target plan as a `WARN` block (the existing v1
1270
+ * surface). CI use case.
1271
+ * - When `opts.yes` is false, the prompt fires after the per-target
1272
+ * plan. Default is `N` because the side effect is destructive
1273
+ * (a per-resource destroy + recreate cycle).
1274
+ * - Non-TTY guard: if `opts.yes` is false AND stdin is not a TTY,
1275
+ * throws with an actionable message rather than hanging or
1276
+ * silently declining. CI runs without `--yes` would otherwise look
1277
+ * like a successful skipped-deploy.
1278
+ *
1279
+ * The per-target plan surfaces a **DATA LOSS** prefix for stateful
1280
+ * targets (those with a non-null `statefulReason` after the live
1281
+ * `s3:ListObjectsV2` probe — see issue [#648]); these reached pre-flight
1282
+ * only because the user opted in with `--force-stateful-recreation`,
1283
+ * so the prompt's **DATA LOSS** wording is the third "stop and think"
1284
+ * moment.
1285
+ */
1286
+ async function promptRecreateConfirm(input) {
1287
+ if (input.targets.length === 0) return true;
1288
+ const logger = getLogger();
1289
+ logger.warn("");
1290
+ logger.warn(`--recreate-via-cc-api will destroy + recreate ${input.targets.length} resource(s) via Cloud Control API on stack ${input.stackName}:`);
1291
+ for (const t of input.targets) {
1292
+ const stateful = t.statefulReason !== null;
1293
+ const dataLossPrefix = stateful ? "**DATA LOSS** " : "";
1294
+ const stateNote = stateful ? ` — stateful (${t.statefulReason}); --force-stateful-recreation acknowledged` : "";
1295
+ logger.warn(` - ${dataLossPrefix}${t.logicalId} (${t.resourceType})${stateNote}`);
1296
+ if (stateful) logger.warn(` DATA: all data in ${t.logicalId} will be lost (no automatic data migration)`);
1297
+ }
1298
+ logger.warn(" The destroy + recreate cycle is per-resource; sibling resources are unaffected. Downstream consumers of any recreated resource's outputs (Fn::GetStackOutput / Fn::ImportValue) will need a re-deploy to see the new physical id.");
1299
+ if (input.yes) return true;
1300
+ if (process.stdin.isTTY !== true) throw new Error("--recreate-via-cc-api confirm prompt cannot run in a non-interactive environment. Pass --yes / -y to confirm the destroy + recreate cycle, or run the deploy from a real terminal.");
1301
+ const rl = readline.createInterface({
1302
+ input: process.stdin,
1303
+ output: process.stdout
1304
+ });
1305
+ try {
1306
+ const trimmed = (await rl.question("\nContinue? (y/N): ")).trim().toLowerCase();
1307
+ if (trimmed === "y" || trimmed === "yes") return true;
1308
+ logger.info("Deploy cancelled — no resources modified.");
1309
+ return false;
1310
+ } finally {
1311
+ rl.close();
1312
+ }
1313
+ }
1140
1314
 
1141
1315
  //#endregion
1142
1316
  //#region src/state/export-index-store.ts
@@ -32334,7 +32508,7 @@ async function runDestroyForStack(stackName, state, ctx) {
32334
32508
  for (const [logicalId, resource] of Object.entries(state.resources)) logger.info(` - ${logicalId} (${resource.resourceType})`);
32335
32509
  const protectedCount = ctx.removeProtection ? countProtectedResources(state) : 0;
32336
32510
  if (!ctx.skipConfirmation) {
32337
- const rl = readline.createInterface({
32511
+ const rl = readline$1.createInterface({
32338
32512
  input: process.stdin,
32339
32513
  output: process.stdout
32340
32514
  });
@@ -33405,7 +33579,7 @@ async function promptMigrationConfirm(renames, opts) {
33405
33579
  logger.warn("These resources will be REPLACED because the new naming convention drops the stack-name prefix.");
33406
33580
  if (opts.yes) return true;
33407
33581
  if (process.stdin.isTTY !== true) throw new Error("--no-prefix-user-supplied-names migration confirm prompt cannot run in a non-interactive environment. Pass --yes / -y to confirm the REPLACEMENT, or run the deploy from a real terminal.");
33408
- const rl = readline.createInterface({
33582
+ const rl = readline$1.createInterface({
33409
33583
  input: process.stdin,
33410
33584
  output: process.stdout
33411
33585
  });
@@ -33597,30 +33771,33 @@ async function deployCommand(stacks, options) {
33597
33771
  let recreateViaCcApiTargets;
33598
33772
  if (options.recreateViaCcApi?.length) {
33599
33773
  const stateForRecreateCheck = await stackStateBackend.getState(stackInfo.stackName, stackRegion);
33600
- const validation = validateRecreateTargets({
33601
- template: stackInfo.template,
33602
- state: stateForRecreateCheck?.state ?? {
33603
- version: 7,
33604
- stackName: stackInfo.stackName,
33605
- region: stackRegion,
33606
- resources: {},
33607
- outputs: {},
33608
- lastModified: Date.now()
33609
- },
33610
- recreateViaCcApi: options.recreateViaCcApi,
33611
- allowUnsupportedProperties: new Set(options.allowUnsupportedProperties ?? []),
33774
+ const validation = await probeAndRevalidateStateful({
33775
+ validation: validateRecreateTargets({
33776
+ template: stackInfo.template,
33777
+ state: stateForRecreateCheck?.state ?? {
33778
+ version: 7,
33779
+ stackName: stackInfo.stackName,
33780
+ region: stackRegion,
33781
+ resources: {},
33782
+ outputs: {},
33783
+ lastModified: Date.now()
33784
+ },
33785
+ recreateViaCcApi: options.recreateViaCcApi,
33786
+ allowUnsupportedProperties: new Set(options.allowUnsupportedProperties ?? []),
33787
+ forceStatefulRecreation: options.forceStatefulRecreation ?? false
33788
+ }),
33789
+ s3Client: stackAwsClients.s3,
33612
33790
  forceStatefulRecreation: options.forceStatefulRecreation ?? false
33613
33791
  });
33614
33792
  const errorBlock = renderRecreateTargetsErrors(validation);
33615
33793
  if (errorBlock) throw new CdkdError(errorBlock, "RECREATE_VIA_CC_API_INVALID");
33616
33794
  recreateViaCcApiTargets = new Set(validation.targets.map((t) => t.logicalId));
33617
33795
  if (recreateViaCcApiTargets.size > 0) {
33618
- logger.warn(`--recreate-via-cc-api will destroy + recreate ${recreateViaCcApiTargets.size} resource(s) via Cloud Control API on stack ${stackInfo.stackName}:`);
33619
- for (const t of validation.targets) {
33620
- const stateNote = t.statefulReason !== null ? ` ⚠ stateful (${t.statefulReason}) — --force-stateful-recreation acknowledged` : "";
33621
- logger.warn(` - ${t.logicalId} (${t.resourceType})${stateNote}`);
33622
- }
33623
- logger.warn(" The destroy + recreate cycle is per-resource; sibling resources are unaffected. Downstream consumers of any recreated resource's outputs (Fn::GetStackOutput / Fn::ImportValue) will need a re-deploy to see the new physical id.");
33796
+ if (!await promptRecreateConfirm({
33797
+ stackName: stackInfo.stackName,
33798
+ targets: validation.targets,
33799
+ yes: options.yes ?? false
33800
+ })) return;
33624
33801
  }
33625
33802
  }
33626
33803
  const deployEngineOptions = {
@@ -34513,7 +34690,7 @@ async function walkCfnStackTree(stackName, physicalId, cfnClient) {
34513
34690
  };
34514
34691
  }
34515
34692
  async function confirmPrompt$5(prompt) {
34516
- const rl = readline.createInterface({
34693
+ const rl = readline$1.createInterface({
34517
34694
  input: process.stdin,
34518
34695
  output: process.stdout
34519
34696
  });
@@ -35793,7 +35970,7 @@ async function runWithConcurrency(tasks, concurrency) {
35793
35970
  await Promise.all(workers);
35794
35971
  }
35795
35972
  async function confirmPrompt$4(prompt) {
35796
- const rl = readline.createInterface({
35973
+ const rl = readline$1.createInterface({
35797
35974
  input: process.stdin,
35798
35975
  output: process.stdout
35799
35976
  });
@@ -36762,7 +36939,7 @@ function stringifyForAudit(value) {
36762
36939
  return JSON.stringify(value);
36763
36940
  }
36764
36941
  async function confirmPrompt$3(prompt) {
36765
- const rl = readline.createInterface({
36942
+ const rl = readline$1.createInterface({
36766
36943
  input: process.stdin,
36767
36944
  output: process.stdout
36768
36945
  });
@@ -37251,7 +37428,7 @@ async function emptyBucketAllVersions(s3, bucket) {
37251
37428
  } while (keyMarker || versionIdMarker);
37252
37429
  }
37253
37430
  async function confirmPrompt$2(prompt) {
37254
- const rl = readline.createInterface({
37431
+ const rl = readline$1.createInterface({
37255
37432
  input: process.stdin,
37256
37433
  output: process.stdout
37257
37434
  });
@@ -39668,7 +39845,7 @@ function printNextSteps(args) {
39668
39845
  logger.info("");
39669
39846
  }
39670
39847
  async function confirmPrompt$1(prompt) {
39671
- const rl = readline.createInterface({
39848
+ const rl = readline$1.createInterface({
39672
39849
  input: process.stdin,
39673
39850
  output: process.stdout
39674
39851
  });
@@ -40247,7 +40424,7 @@ async function stateOrphanCommand(stackArgs, options) {
40247
40424
  if (!options.yes && !options.force) {
40248
40425
  const targetList = targets.map((t) => formatStackRef(t)).join(", ");
40249
40426
  process.stdout.write(`\nWARNING: This removes cdkd's state record for [${targetList}] only. AWS resources will NOT be deleted.\nUse 'cdkd destroy ${stackName}' if you want to delete the actual resources.\n\n`);
40250
- const rl = readline.createInterface({
40427
+ const rl = readline$1.createInterface({
40251
40428
  input: process.stdin,
40252
40429
  output: process.stdout
40253
40430
  });
@@ -40344,7 +40521,7 @@ async function stateDestroyCommand(stackArgs, options) {
40344
40521
  process.stdout.write(`\nWARNING: This destroys ${stackNames.length} stack(s) and removes their state records:\n`);
40345
40522
  for (const name of stackNames) process.stdout.write(` - ${name}\n`);
40346
40523
  process.stdout.write("\n");
40347
- const rl = readline.createInterface({
40524
+ const rl = readline$1.createInterface({
40348
40525
  input: process.stdin,
40349
40526
  output: process.stdout
40350
40527
  });
@@ -40807,7 +40984,7 @@ async function refreshObservedForStack(stackName, region, stateBackend, lockMana
40807
40984
  }
40808
40985
  }
40809
40986
  async function confirmRefresh(prompt) {
40810
- const rl = readline.createInterface({
40987
+ const rl = readline$1.createInterface({
40811
40988
  input: process.stdin,
40812
40989
  output: process.stdout
40813
40990
  });
@@ -41423,7 +41600,7 @@ function formatOutcome(outcome) {
41423
41600
  }
41424
41601
  }
41425
41602
  async function confirmPrompt(prompt) {
41426
- const rl = readline.createInterface({
41603
+ const rl = readline$1.createInterface({
41427
41604
  input: process.stdin,
41428
41605
  output: process.stdout
41429
41606
  });
@@ -60328,7 +60505,7 @@ function reorderArgs(argv) {
60328
60505
  */
60329
60506
  async function main() {
60330
60507
  const program = new Command();
60331
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.162.3");
60508
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.164.0");
60332
60509
  program.addCommand(createBootstrapCommand());
60333
60510
  program.addCommand(createSynthCommand());
60334
60511
  program.addCommand(createListCommand());