@go-to-k/cdkd 0.229.7 → 0.230.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
@@ -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 findLargeInlineResources, A as shouldRetainResource, B as getDockerImageBySourceHash, C as applyRoleArnIfSet, D as LockManager, E as TemplateParser, F as formatDockerLoginError, G as resolveCaptureObservedState, H as getDefaultStateBucketName, I as getDockerCmd, J as resolveStateBucketWithDefaultAndSource, K as resolveSkipPrefix, L as runDockerForeground, M as stringifyValue, N as WorkGraph, O as S3StateBackend, P as buildDockerImage, Q as MIGRATE_TMP_PREFIX, R as runDockerStreaming, S as IntrinsicFunctionResolver, T as DagBuilder, U as getLegacyStateBucketName, V as Synthesizer, W as resolveApp, X as CFN_TEMPLATE_BODY_LIMIT, Y as warnDeprecatedNoPrefixCliFlag, Z as CFN_TEMPLATE_URL_LIMIT, _ as IAMRoleProvider, a as withRetry, b as findActionableSilentDrops, c as computeImplicitDeleteEdges, d as bold, et as uploadCfnTemplate, f as cyan, g as yellow, h as red, i as withResourceDeadline, j as AssetPublisher, k as rebuildClientForBucketRegion, l as extractDeploymentEventError, m as green, n as DEFAULT_RESOURCE_WARN_AFTER_MS, o as isRetryableTransientError, p as gray, q as resolveStateBucketWithDefault, r as DeployEngine, rt as resolveBucketRegion, s as IMPLICIT_DELETE_DEPENDENCIES, t as DEFAULT_RESOURCE_TIMEOUT_MS, tt as AssemblyReader, u as formatResourceLine, v as collectInlinePolicyNamesManagedBySiblings, w as DiffCalculator, x as CloudControlProvider, y as ProviderRegistry, z as AssetManifestLoader } from "./deploy-engine-BIYc-qWo.js";
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.229.7";
1448
+ return "0.230.0";
1560
1449
  }
1561
1450
  /**
1562
1451
  * Generate a time-sortable unique run id, e.g.
@@ -9629,12 +9518,15 @@ var LambdaLayerVersionProvider = class {
9629
9518
  * which is never what `--revert` should do.
9630
9519
  * - On the deploy path, content / runtime / arch changes flow
9631
9520
  * through CDK's hash-based logical naming, which produces a fresh
9632
- * logical ID and a CREATE+DELETE in cdkd's diff `update()` is
9633
- * not the path taken in practice. Users who hit this on a non-CDK
9634
- * template should re-deploy with `--replace`.
9521
+ * logical ID and a CREATE+DELETE in cdkd's diff. For a hand-authored
9522
+ * template that edits the SAME logical id in place, the replacement
9523
+ * rule for `AWS::Lambda::LayerVersion` (every property is
9524
+ * "Update requires: Replacement") drives a DELETE+CREATE before
9525
+ * `update()` is ever reached, so this method is a defensive fallback
9526
+ * that should not fire in normal use.
9635
9527
  */
9636
9528
  async update(logicalId, _physicalId, resourceType, _properties, _previousProperties) {
9637
- return Promise.reject(new ResourceUpdateNotSupportedError(resourceType, logicalId, "AWS Lambda LayerVersion is immutable on AWS — there is no UpdateLayerVersion API; every change requires PublishLayerVersion (a new version with a new LayerVersionArn). Re-deploy with cdkd deploy --replace, or change the resource definition to publish a new version."));
9529
+ return Promise.reject(new ResourceUpdateNotSupportedError(resourceType, logicalId, "AWS Lambda LayerVersion is immutable on AWS — there is no UpdateLayerVersion API; every change requires PublishLayerVersion (a new version with a new LayerVersionArn). cdkd normally classifies any LayerVersion property change as a replacement (DELETE + CREATE), so reaching this path is unexpected; re-run the deploy or change the resource definition to publish a new version."));
9638
9530
  }
9639
9531
  /**
9640
9532
  * Delete a Lambda layer version
@@ -29210,7 +29102,7 @@ var GlueSecurityConfigurationProvider = class {
29210
29102
  /**
29211
29103
  * Read AWS-current SecurityConfiguration shape via
29212
29104
  * `GetSecurityConfiguration`. Always emits the three CFn-modeled
29213
- * sub-configs (`S3Encryption: []`, `CloudWatchEncryption: {}`,
29105
+ * sub-configs (`S3Encryptions: []`, `CloudWatchEncryption: {}`,
29214
29106
  * `JobBookmarksEncryption: {}`) per PR #145 even when AWS reports
29215
29107
  * nothing — closes the "console-side encryption enable on a previously
29216
29108
  * default config" detection gap on the v3 baseline.
@@ -29273,13 +29165,14 @@ function sleep$1(ms) {
29273
29165
  /**
29274
29166
  * Build the SDK `EncryptionConfiguration` from the CFn-shape input
29275
29167
  * (`AWS::Glue::SecurityConfiguration.EncryptionConfiguration`). Each
29276
- * sub-config (`S3Encryption[]` / `CloudWatchEncryption` /
29277
- * `JobBookmarksEncryption`) field-renames are pure pass-throughthe
29278
- * CFn property names match the SDK member names verbatim.
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.
29279
29172
  */
29280
29173
  function buildEncryptionConfiguration(input) {
29281
29174
  const result = {};
29282
- if (Array.isArray(input["S3Encryption"])) result.S3Encryption = input["S3Encryption"].map((entry) => {
29175
+ if (Array.isArray(input["S3Encryptions"])) result.S3Encryption = input["S3Encryptions"].map((entry) => {
29283
29176
  const e = entry;
29284
29177
  const item = {};
29285
29178
  if (typeof e["S3EncryptionMode"] === "string") item.S3EncryptionMode = e["S3EncryptionMode"];
@@ -29305,7 +29198,7 @@ function buildEncryptionConfiguration(input) {
29305
29198
  /**
29306
29199
  * Reverse-map AWS's `EncryptionConfiguration` SDK shape into the CFn
29307
29200
  * shape with always-emit placeholders (PR #145):
29308
- * - `S3Encryption[]` → `?? []` (so console-side ADD is detectable)
29201
+ * - `S3Encryptions[]` → `?? []` (so console-side ADD is detectable)
29309
29202
  * - `CloudWatchEncryption` → `?? {}`
29310
29203
  * - `JobBookmarksEncryption` → `?? {}`
29311
29204
  * - `DataQualityEncryption` → silently dropped (not in CFn schema)
@@ -29313,7 +29206,7 @@ function buildEncryptionConfiguration(input) {
29313
29206
  function mapEncryptionConfigurationToCfn(cfg) {
29314
29207
  const c = cfg ?? {};
29315
29208
  return {
29316
- S3Encryption: (c.S3Encryption ?? []).map((entry) => {
29209
+ S3Encryptions: (c.S3Encryption ?? []).map((entry) => {
29317
29210
  const out = {};
29318
29211
  if (entry.S3EncryptionMode !== void 0) out["S3EncryptionMode"] = entry.S3EncryptionMode;
29319
29212
  if (entry.KmsKeyArn !== void 0) out["KmsKeyArn"] = entry.KmsKeyArn;
@@ -37069,6 +36962,8 @@ async function deployCommand(stacks, options) {
37069
36962
  ...eventRecorder && { eventRecorder },
37070
36963
  ...recreateViaCcApiTargets && recreateViaCcApiTargets.size > 0 && { recreateViaCcApiTargets },
37071
36964
  ...recreateViaSdkProviderTargets && recreateViaSdkProviderTargets.size > 0 && { recreateViaSdkProviderTargets },
36965
+ ...options.replace && { replace: true },
36966
+ ...options.forceStatefulRecreation && { forceStatefulRecreation: true },
37072
36967
  captureObservedState: resolveCaptureObservedState(options.captureObservedState),
37073
36968
  ...options.resourceWarnAfter?.globalMs !== void 0 && { resourceWarnAfterMs: options.resourceWarnAfter.globalMs },
37074
36969
  ...options.resourceTimeout?.globalMs !== void 0 && { resourceTimeoutMs: options.resourceTimeout.globalMs },
@@ -55067,7 +54962,7 @@ function reorderArgs(argv) {
55067
54962
  async function main() {
55068
54963
  installPipeCloseHandler();
55069
54964
  const program = new Command();
55070
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.229.7");
54965
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.230.0");
55071
54966
  program.addCommand(createBootstrapCommand());
55072
54967
  program.addCommand(createSynthCommand());
55073
54968
  program.addCommand(createListCommand());