@go-to-k/cdkd 0.278.26 → 0.278.28

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
- import { $ as isThrottlingError, $t as setAwsClients, A as red, At as getLegacyStateBucketName, B as isTerminationProtectionPropagationError, Bt as CFN_TEMPLATE_BODY_LIMIT, C as isStatefulRecreateTargetSync, Ct as runDockerForeground, D as cyan, Dt as Synthesizer, E as bold, Et as getDockerImageBySourceHash, F as ProviderRegistry, Ft as resolveStateBucketWithDefault, G as normalizeAwsTagsToCfn, Gt as expectedOwnerParam, H as cfnRefValueFromPhysicalId, Ht as MIGRATE_TMP_PREFIX, I as findActionableSilentDrops, It as resolveStateBucketWithDefaultAndSource, J as applyRoleArnIfSet, K as resolveExplicitPhysicalId, Kt as AssemblyReader, L as CloudControlProvider, Lt as resolveUseCdkBootstrapAssets, M as IAMRoleProvider, Mt as resolveAutoAssetStorage, N as collectInlinePolicyNamesManagedBySiblings, Nt as resolveCaptureObservedState, O as gray, Ot as synthesisStatusMessage, P as clearOnUpdateRemoval, Pt as resolveSkipPrefix, Q as isRetryableTransientError, Qt as resetAwsClients, R as slowCcOperationTimeoutMs, Rt as stateBucketExistenceConfirmed, S as MULTI_REGION_RECREATE_BLOCKED_TYPES, Sn as withErrorHandling, St as getDockerCmd, T as formatResourceLine, Tt as AssetManifestLoader, U as refStateLookupFromResource, Ut as findLargeInlineResources, V as IntrinsicFunctionResolver, Vt as CFN_TEMPLATE_URL_LIMIT, W as WAFv2WebACLProvider, Wt as uploadCfnTemplate, X as describeTypeWithThrottleRetry, Xt as AwsClients, Y as DiffCalculator, Yt as resolveBucketRegion, Z as withRetry, Zt as getAwsClients, _ as createPreDeleteFinalSnapshot, _t as parseBootstrapMarker, a as DeploymentEventsStore, an as LocalInvokeBuildError$1, at as shouldRetainResource, b as unsupportedFinalSnapshotError, bt as buildDockerImage, c as replayFailedOperations, ct as WorkGraph, d as IMPLICIT_DELETE_DEPENDENCIES, dn as PartialFailureError, dt as loadPublishableAssetManifest, et as DagBuilder, f as computeImplicitDeleteEdges, fn as ProvisioningError, ft as rewriteTemplateAssetReferences, g as ccRoutedFinalSnapshotError, gn as StackTerminationProtectionError, gt as getBootstrapMarkerKey, h as buildFinalSnapshotIdentifier, hn as StackHasActiveImportsError, ht as ensureAssetStorage, i as DeploymentEventsReader, in as DeployCancelledError, it as rebuildClientForBucketRegion, j as yellow, jt as resolveApp, k as green, kt as getDefaultStateBucketName, l as replayRollback, ln as MissingCdkCliError, lt as buildAssetRedirectMap, m as PRE_DELETE_SNAPSHOT_TYPES, mn as ResourceUpdateNotSupportedError, mt as BOOTSTRAP_MARKER_PREFIX, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nt as LockManager, o as planFailedOps, on as LocalMigrateError, ot as AssetPublisher, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as ResourceTimeoutError, pt as AssetModeResolver, q as assertRegionMatch, qt as processStackMessages, r as DeployEngine, rt as S3StateBackend, s as planRollback, sn as LocalStartServiceError, st as stringifyValue, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as CdkdError, tt as TemplateParser, u as withResourceDeadline, un as NestedStackChildDirectDestroyError, ut as createAssetRedirectResolver, v as isFinalSnapshotError, vt as validateAssetBucketName, w as renderStatefulReason, wt as runDockerStreaming, x as extractDeploymentEventError, xn as normalizeAwsError, xt as formatDockerLoginError, y as refusesFinalSnapshot, yt as validateContainerRepoName, z as disableInstanceApiTermination, zt as warnDeprecatedNoPrefixCliFlag } from "./deploy-engine-BsHkBRtK.js";
2
+ import { $ as withRetry, $t as getAwsClients, A as red, At as synthesisStatusMessage, B as isTerminationProtectionPropagationError, Bt as stateBucketExistenceConfirmed, C as isStatefulRecreateTargetSync, Cn as normalizeAwsError, Ct as formatDockerLoginError, D as cyan, Dt as AssetManifestLoader, E as bold, Et as runDockerStreaming, F as ProviderRegistry, Ft as resolveCaptureObservedState, G as normalizeAwsTagsToCfn, Gt as findLargeInlineResources, H as cfnRefValueFromPhysicalId, Ht as CFN_TEMPLATE_BODY_LIMIT, I as findActionableSilentDrops, It as resolveSkipPrefix, J as readConfigString, Jt as AssemblyReader, K as resolveExplicitPhysicalId, Kt as uploadCfnTemplate, L as CloudControlProvider, Lt as resolveStateBucketWithDefault, M as IAMRoleProvider, Mt as getLegacyStateBucketName, N as collectInlinePolicyNamesManagedBySiblings, Nt as resolveApp, O as gray, Ot as getDockerImageBySourceHash, P as clearOnUpdateRemoval, Pt as resolveAutoAssetStorage, Q as describeTypeWithThrottleRetry, Qt as AwsClients, R as slowCcOperationTimeoutMs, Rt as resolveStateBucketWithDefaultAndSource, S as MULTI_REGION_RECREATE_BLOCKED_TYPES, St as buildDockerImage, T as formatResourceLine, Tt as runDockerForeground, U as refStateLookupFromResource, Ut as CFN_TEMPLATE_URL_LIMIT, V as IntrinsicFunctionResolver, Vt as warnDeprecatedNoPrefixCliFlag, W as WAFv2WebACLProvider, Wt as MIGRATE_TMP_PREFIX, X as applyRoleArnIfSet, Y as requireConfigString, Yt as processStackMessages, Z as DiffCalculator, Zt as resolveBucketRegion, _ as createPreDeleteFinalSnapshot, _n as StackHasActiveImportsError, _t as ensureAssetStorage, a as DeploymentEventsStore, at as S3StateBackend, b as unsupportedFinalSnapshotError, bt as validateAssetBucketName, c as replayFailedOperations, cn as LocalMigrateError, ct as AssetPublisher, d as IMPLICIT_DELETE_DEPENDENCIES, dn as MissingCdkCliError, dt as buildAssetRedirectMap, en as resetAwsClients, et as isRetryableTransientError, f as computeImplicitDeleteEdges, fn as NestedStackChildDirectDestroyError, ft as createAssetRedirectResolver, g as ccRoutedFinalSnapshotError, gn as ResourceUpdateNotSupportedError, gt as BOOTSTRAP_MARKER_PREFIX, h as buildFinalSnapshotIdentifier, hn as ResourceTimeoutError, ht as AssetModeResolver, i as DeploymentEventsReader, it as LockManager, j as yellow, jt as getDefaultStateBucketName, k as green, kt as Synthesizer, l as replayRollback, ln as LocalStartServiceError, lt as stringifyValue, m as PRE_DELETE_SNAPSHOT_TYPES, mn as ProvisioningError, mt as rewriteTemplateAssetReferences, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nt as DagBuilder, o as planFailedOps, on as DeployCancelledError, ot as rebuildClientForBucketRegion, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as PartialFailureError, pt as loadPublishableAssetManifest, q as assertRegionMatch, qt as expectedOwnerParam, r as DeployEngine, rn as CdkdError, rt as TemplateParser, s as planRollback, sn as LocalInvokeBuildError$1, st as shouldRetainResource, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as setAwsClients, tt as isThrottlingError, u as withResourceDeadline, ut as WorkGraph, v as isFinalSnapshotError, vn as StackTerminationProtectionError, vt as getBootstrapMarkerKey, w as renderStatefulReason, wn as withErrorHandling, wt as getDockerCmd, x as extractDeploymentEventError, xt as validateContainerRepoName, y as refusesFinalSnapshot, yt as parseBootstrapMarker, z as disableInstanceApiTermination, zt as resolveUseCdkBootstrapAssets } from "./deploy-engine-Dcg1nH3d.js";
3
3
  import { a as getLiveRenderer, c as PATTERN_B_RESOURCE_TYPES, d as generateResourceNameWithFallback, f as withSkipPrefix, i as runStackBuffered, n as getLogger, o as PATTERN_B_NAME_OPTIONS, p as withStackName, s as PATTERN_B_NAME_PROPERTIES, u as generateResourceName } from "./logger-BYMEE-BS.js";
4
- import { t as ASGProvider } from "./asg-provider-DLScqiT2.js";
4
+ import { t as ASGProvider } from "./asg-provider-BJnh483x.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";
@@ -4936,7 +4936,7 @@ var S3BucketProvider = class S3BucketProvider {
4936
4936
  * Apply versioning configuration if specified
4937
4937
  */
4938
4938
  async applyVersioning(bucketName, versioningConfig) {
4939
- const status = versioningConfig["Status"] || "Suspended";
4939
+ const status = readConfigString(versioningConfig, "Status", "Suspended", "AWS::S3::Bucket VersioningConfiguration");
4940
4940
  await this.s3Client.send(new PutBucketVersioningCommand({
4941
4941
  Bucket: bucketName,
4942
4942
  VersioningConfiguration: { Status: status }
@@ -5045,7 +5045,7 @@ var S3BucketProvider = class S3BucketProvider {
5045
5045
  const rules = lifecycleConfig.Rules.map((rule) => {
5046
5046
  const sdkRule = {
5047
5047
  ID: rule["Id"],
5048
- Status: rule["Status"] || "Enabled",
5048
+ Status: readConfigString(rule, "Status", "Enabled", "AWS::S3::Bucket LifecycleConfiguration.Rules[]"),
5049
5049
  Prefix: useFilterForm ? void 0 : rule["Prefix"]
5050
5050
  };
5051
5051
  const expiration = rule["ExpirationInDays"] || rule["ExpirationDate"] || rule["Expiration"];
@@ -5168,7 +5168,8 @@ var S3BucketProvider = class S3BucketProvider {
5168
5168
  * SDK: PutBucketLogging with BucketLoggingStatus.LoggingEnabled
5169
5169
  */
5170
5170
  async applyLoggingConfiguration(bucketName, loggingConfig) {
5171
- if (!loggingConfig || !loggingConfig["DestinationBucketName"]) {
5171
+ const destinationBucket = readConfigString(loggingConfig, "DestinationBucketName", "", "AWS::S3::Bucket LoggingConfiguration");
5172
+ if (!loggingConfig || destinationBucket === "") {
5172
5173
  await this.s3Client.send(new PutBucketLoggingCommand({
5173
5174
  Bucket: bucketName,
5174
5175
  BucketLoggingStatus: {}
@@ -5179,8 +5180,8 @@ var S3BucketProvider = class S3BucketProvider {
5179
5180
  await this.s3Client.send(new PutBucketLoggingCommand({
5180
5181
  Bucket: bucketName,
5181
5182
  BucketLoggingStatus: { LoggingEnabled: {
5182
- TargetBucket: loggingConfig["DestinationBucketName"],
5183
- TargetPrefix: loggingConfig["LogFilePrefix"] || ""
5183
+ TargetBucket: destinationBucket,
5184
+ TargetPrefix: readConfigString(loggingConfig, "LogFilePrefix", "", "AWS::S3::Bucket LoggingConfiguration")
5184
5185
  } }
5185
5186
  }));
5186
5187
  this.logger.debug(`Applied logging configuration to bucket ${bucketName}`);
@@ -5358,11 +5359,11 @@ var S3BucketProvider = class S3BucketProvider {
5358
5359
  const dest = dataExport["Destination"];
5359
5360
  const s3Dest = dest?.["BucketAccountId"] || dest?.["BucketArn"] || dest?.["Format"] ? dest : dest?.["S3BucketDestination"];
5360
5361
  analyticsConfig.StorageClassAnalysis = { DataExport: {
5361
- OutputSchemaVersion: dataExport["OutputSchemaVersion"] || "V_1",
5362
+ OutputSchemaVersion: readConfigString(dataExport, "OutputSchemaVersion", "V_1", "AWS::S3::Bucket AnalyticsConfigurations[].StorageClassAnalysis.DataExport"),
5362
5363
  Destination: s3Dest ? { S3BucketDestination: {
5363
5364
  Bucket: s3Dest["BucketArn"] ?? s3Dest["Bucket"],
5364
5365
  BucketAccountId: s3Dest["BucketAccountId"],
5365
- Format: s3Dest["Format"] || "CSV",
5366
+ Format: readConfigString(s3Dest, "Format", "CSV", "AWS::S3::Bucket AnalyticsConfigurations[].StorageClassAnalysis.DataExport.Destination.S3BucketDestination"),
5366
5367
  Prefix: s3Dest["Prefix"]
5367
5368
  } } : void 0
5368
5369
  } };
@@ -5387,7 +5388,7 @@ var S3BucketProvider = class S3BucketProvider {
5387
5388
  const tierings = config["Tierings"];
5388
5389
  const itConfig = {
5389
5390
  Id: id,
5390
- Status: config["Status"] || "Enabled",
5391
+ Status: readConfigString(config, "Status", "Enabled", "AWS::S3::Bucket IntelligentTieringConfigurations[]"),
5391
5392
  Tierings: (tierings || []).map((t) => ({
5392
5393
  AccessTier: t["AccessTier"],
5393
5394
  Days: t["Days"]
@@ -5425,12 +5426,12 @@ var S3BucketProvider = class S3BucketProvider {
5425
5426
  const inventoryConfig = {
5426
5427
  Id: id,
5427
5428
  IsEnabled: config["Enabled"] ?? true,
5428
- IncludedObjectVersions: config["IncludedObjectVersions"] || "All",
5429
- Schedule: { Frequency: config["ScheduleFrequency"] ?? config["Schedule"]?.["Frequency"] ?? "Weekly" },
5429
+ IncludedObjectVersions: readConfigString(config, "IncludedObjectVersions", "All", "AWS::S3::Bucket InventoryConfigurations[]"),
5430
+ Schedule: { Frequency: config["ScheduleFrequency"] !== void 0 ? requireConfigString(config["ScheduleFrequency"], "Weekly", "AWS::S3::Bucket InventoryConfigurations[].ScheduleFrequency") : readConfigString(config["Schedule"], "Frequency", "Weekly", "AWS::S3::Bucket InventoryConfigurations[].Schedule") },
5430
5431
  Destination: { S3BucketDestination: s3Dest ? {
5431
5432
  Bucket: s3Dest["BucketArn"] ?? s3Dest["Bucket"],
5432
5433
  AccountId: s3Dest["BucketAccountId"],
5433
- Format: s3Dest["Format"] || "CSV",
5434
+ Format: readConfigString(s3Dest, "Format", "CSV", "AWS::S3::Bucket InventoryConfigurations[].Destination.S3BucketDestination"),
5434
5435
  Prefix: s3Dest["Prefix"]
5435
5436
  } : void 0 },
5436
5437
  OptionalFields: config["OptionalFields"],
@@ -5462,7 +5463,7 @@ var S3BucketProvider = class S3BucketProvider {
5462
5463
  const dest = rule["Destination"];
5463
5464
  const sdkRule = {
5464
5465
  ID: rule["Id"],
5465
- Status: rule["Status"] || "Enabled",
5466
+ Status: readConfigString(rule, "Status", "Enabled", "AWS::S3::Bucket ReplicationConfiguration.Rules[]"),
5466
5467
  Priority: rule["Priority"],
5467
5468
  Destination: {
5468
5469
  Bucket: dest["Bucket"],
@@ -5539,7 +5540,7 @@ var S3BucketProvider = class S3BucketProvider {
5539
5540
  async applyConfiguration(bucketName, properties, options = {}) {
5540
5541
  const { skipTags = false, skipDiffManaged = false } = options;
5541
5542
  const versioningConfig = properties["VersioningConfiguration"];
5542
- if (!skipDiffManaged && versioningConfig) await this.applyVersioning(bucketName, versioningConfig);
5543
+ if (!skipDiffManaged && versioningConfig != null) await this.applyVersioning(bucketName, versioningConfig);
5543
5544
  const tags = properties["Tags"];
5544
5545
  if (!skipTags && tags && Array.isArray(tags) && tags.length > 0) await this.applyTags(bucketName, tags);
5545
5546
  const ownershipControls = properties["OwnershipControls"];
@@ -5594,10 +5595,10 @@ var S3BucketProvider = class S3BucketProvider {
5594
5595
  * declares the config.
5595
5596
  *
5596
5597
  * NOTE this helper does NOT cover `VersioningConfiguration` (it has no list
5597
- * key), and that property is NOT malformed-shape-refused anywhere: a
5598
- * malformed value there still resolves to 'Suspended', matching `main`.
5599
- * That pre-existing gap is tracked in issue #1471 — see the note in
5600
- * `applySubConfigDiffs` for why guarding it is not as simple as it looks.
5598
+ * key). That property is malformed-shape-refused separately, by
5599
+ * `readConfigString` in `applyVersioning` + `applySubConfigDiffs`
5600
+ * (issue #1471) — same outcome, different mechanism, because a versioning
5601
+ * block has an inner FIELD to validate rather than a list to measure.
5601
5602
  */
5602
5603
  static emptyListConfigToUndefined(config, listKey) {
5603
5604
  if (config === void 0 || config === null) return void 0;
@@ -5672,7 +5673,7 @@ var S3BucketProvider = class S3BucketProvider {
5672
5673
  const previousVersioning = previousProperties["VersioningConfiguration"];
5673
5674
  const nextVersioning = properties["VersioningConfiguration"];
5674
5675
  const versioningChanged = JSON.stringify(previousVersioning ?? null) !== JSON.stringify(nextVersioning ?? null);
5675
- const desiredVersioningStatus = nextVersioning == null ? "Suspended" : nextVersioning["Status"] || "Suspended";
5676
+ const desiredVersioningStatus = readConfigString(nextVersioning, "Status", "Suspended", "AWS::S3::Bucket VersioningConfiguration");
5676
5677
  if (versioningChanged && nextVersioning != null && desiredVersioningStatus !== "Suspended") await this.applyVersioning(bucketName, nextVersioning);
5677
5678
  await this.diffSubConfig(bucketName, S3BucketProvider.emptyListConfigToUndefined(previousProperties["OwnershipControls"], "Rules"), S3BucketProvider.emptyListConfigToUndefined(properties["OwnershipControls"], "Rules"), async (cfg) => this.applyOwnershipControls(bucketName, cfg), async () => {
5678
5679
  await this.s3Client.send(new DeleteBucketOwnershipControlsCommand({ Bucket: bucketName }));
@@ -5763,7 +5764,7 @@ var S3BucketProvider = class S3BucketProvider {
5763
5764
  const lifecycleConfig = properties["LifecycleConfiguration"];
5764
5765
  if (lifecycleConfig?.Rules && Array.isArray(lifecycleConfig.Rules) && lifecycleConfig.Rules.length > 0) await this.applyLifecycleConfiguration(bucketName, lifecycleConfig);
5765
5766
  const loggingConfig = properties["LoggingConfiguration"];
5766
- if (loggingConfig?.["DestinationBucketName"]) await this.applyLoggingConfiguration(bucketName, loggingConfig);
5767
+ if (readConfigString(loggingConfig, "DestinationBucketName", "", "AWS::S3::Bucket LoggingConfiguration") !== "") await this.applyLoggingConfiguration(bucketName, loggingConfig);
5767
5768
  const websiteConfig = properties["WebsiteConfiguration"];
5768
5769
  if (websiteConfig) await this.applyWebsiteConfiguration(bucketName, websiteConfig);
5769
5770
  const accelerateConfig = properties["AccelerateConfiguration"];
@@ -15276,7 +15277,7 @@ var SecretsManagerSecretProvider = class {
15276
15277
  const excludeLowercase = config["ExcludeLowercase"];
15277
15278
  const excludeNumbers = config["ExcludeNumbers"];
15278
15279
  const excludePunctuation = config["ExcludePunctuation"];
15279
- const excludeCharacters = config["ExcludeCharacters"] || "";
15280
+ const excludeCharacters = readConfigString(config, "ExcludeCharacters", "", "AWS::SecretsManager::Secret GenerateSecretString");
15280
15281
  let chars = "";
15281
15282
  if (!excludeUppercase) chars += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
15282
15283
  if (!excludeLowercase) chars += "abcdefghijklmnopqrstuvwxyz";
@@ -33105,10 +33106,10 @@ var GlueProvider = class {
33105
33106
  if (!this.client) this.client = new GlueClient(this.providerRegion ? { region: this.providerRegion } : {});
33106
33107
  return this.client;
33107
33108
  }
33108
- async create(logicalId, resourceType, properties) {
33109
+ async create(logicalId, resourceType, properties, context) {
33109
33110
  switch (resourceType) {
33110
33111
  case "AWS::Glue::Database": return this.createDatabase(logicalId, resourceType, properties);
33111
- case "AWS::Glue::Table": return this.createTable(logicalId, resourceType, properties);
33112
+ case "AWS::Glue::Table": return this.createTable(logicalId, resourceType, properties, context);
33112
33113
  default: throw new ProvisioningError(`Unsupported resource type: ${resourceType}`, resourceType, logicalId);
33113
33114
  }
33114
33115
  }
@@ -33191,7 +33192,7 @@ var GlueProvider = class {
33191
33192
  throw new ProvisioningError(`Failed to delete Glue Database ${logicalId}: ${error instanceof Error ? error.message : String(error)}`, resourceType, logicalId, physicalId, cause);
33192
33193
  }
33193
33194
  }
33194
- async createTable(logicalId, resourceType, properties) {
33195
+ async createTable(logicalId, resourceType, properties, context) {
33195
33196
  this.logger.debug(`Creating Glue Table ${logicalId}`);
33196
33197
  const databaseName = properties["DatabaseName"];
33197
33198
  if (!databaseName) throw new ProvisioningError(`DatabaseName is required for Glue Table ${logicalId}`, resourceType, logicalId);
@@ -33200,7 +33201,10 @@ var GlueProvider = class {
33200
33201
  const tableName = tableInput["Name"] ?? properties["Name"];
33201
33202
  if (!tableName) throw new ProvisioningError(`TableInput.Name or top-level Name is required for Glue Table ${logicalId}`, resourceType, logicalId);
33202
33203
  const catalogId = properties["CatalogId"];
33203
- assertIcebergTableInputAbsent(logicalId, resourceType, properties);
33204
+ enforceIcebergTableInputAbsent(logicalId, resourceType, properties, {
33205
+ warn: (message) => this.logger.warn(message),
33206
+ replayingState: context?.replayingState === true
33207
+ });
33204
33208
  const openTableFormatInput = properties["OpenTableFormatInput"];
33205
33209
  try {
33206
33210
  await this.getClient().send(new CreateTableCommand$1({
@@ -33990,15 +33994,35 @@ function findIcebergTableInputKey(properties) {
33990
33994
  * produce a late, cryptic AWS error. Failing fast with the working shape spelled
33991
33995
  * out is strictly more useful.
33992
33996
  *
33993
- * **CREATE only — update WARNS instead.** See the comment at the `updateTable`
33994
- * call site: rollback replays from cdkd STATE, and a table created by a
33995
- * pre-#1390 build carries the key in its state record, so refusing on update
33996
- * would make such a table unrollbackable with no template-side remedy. cdkd
33997
- * does not wire Glue's update-only `UpdateOpenTableFormatInput` shape and
33998
- * `buildTableInput` is an explicit allow-list, so warning there forwards
33999
- * nothing and loses no protection. One rollback arm is still exposed — the
34000
- * reverse-replacement re-create replays a state record through `create()`;
34001
- * see issue #1463 and the note at the `updateTable` call site.
33997
+ * **TEMPLATE creates only — every STATE REPLAY warns instead.** The refusal is
33998
+ * conditioned on the ORIGIN of the properties, not on the operation name:
33999
+ *
34000
+ * - `update()` warns unconditionally. Rollback replays from cdkd STATE, and a
34001
+ * table created by a pre-#1390 build carries the key in its state record, so
34002
+ * refusing there would make such a table unrollbackable with no
34003
+ * template-side remedy. cdkd does not wire Glue's update-only
34004
+ * `UpdateOpenTableFormatInput` shape and `buildTableInput` is an explicit
34005
+ * allow-list, so warning forwards nothing and loses no protection.
34006
+ * - `create()` warns when {@link CreateContext.replayingState} is set — the
34007
+ * rollback executor's reverse-replacement arm, which revives the OLD
34008
+ * resource from `previousState.properties` (issue #1463). Same reasoning:
34009
+ * the user cannot edit a state record from the template. Unlike the update
34010
+ * path this one DOES forward the value, so the re-created table is degraded
34011
+ * in exactly the way the original was (the CFn spelling is dropped by the
34012
+ * SDK serializer per #1390; the SDK spelling is sent and Glue rejects it) —
34013
+ * the warning says so, and the fix-forward is a `cdkd deploy`.
34014
+ * - Every deploy-engine `create()` refuses: the CREATE branch, the
34015
+ * property-driven replacement, the `--recreate-via-*` destroy-then-create,
34016
+ * the `--replace` delete-first fallback, and the update-failure replacement.
34017
+ * All are driven by freshly resolved TEMPLATE properties, so the user CAN
34018
+ * fix the input and a fast, actionable refusal is strictly better.
34019
+ *
34020
+ * The asymmetry constrains where this provider may re-create. `GlueProvider`
34021
+ * must never call `this.create()` from inside its own `update()` the way ACM /
34022
+ * IAM / Lambda-permission / SNS-subscription do: those internal re-creates
34023
+ * forward `update()`'s `properties` — a STATE record during a rollback replay —
34024
+ * and `update()` has no context parameter to carry the flag, so this refusal
34025
+ * would fire on a replay with no way to detect it.
34002
34026
  *
34003
34027
  * **Known bypass: the sticky Cloud Control route.** This is a GlueProvider
34004
34028
  * pre-flight, so it only runs on the SDK route. When a table's state record
@@ -34019,19 +34043,23 @@ function findIcebergTableInputKey(properties) {
34019
34043
  * relaxed, the rename MUST be restored in the same change — otherwise the
34020
34044
  * silent-drop bug of #1390 comes straight back.
34021
34045
  */
34022
- function assertIcebergTableInputAbsent(logicalId, resourceType, properties, physicalId) {
34046
+ function enforceIcebergTableInputAbsent(logicalId, resourceType, properties, options) {
34023
34047
  const key = findIcebergTableInputKey(properties);
34024
34048
  if (key === void 0) return;
34025
- throw new ProvisioningError(icebergTableInputRefusalMessage(logicalId, key, "create"), resourceType, logicalId, physicalId);
34049
+ if (options.replayingState) {
34050
+ options.warn(icebergTableInputRefusalMessage(logicalId, key, "create-replay"));
34051
+ return;
34052
+ }
34053
+ throw new ProvisioningError(icebergTableInputRefusalMessage(logicalId, key, "create"), resourceType, logicalId);
34026
34054
  }
34027
34055
  /**
34028
- * The shared #1454 message body, so the CREATE refusal and the UPDATE warning
34029
- * cannot drift apart. `mode` only changes the lead clause — everything after it
34030
- * (the probe evidence and the working shape) is identical, because the user's
34031
- * next action is the same either way.
34056
+ * The shared #1454 message body, so the CREATE refusal, the UPDATE warning and
34057
+ * the rollback-replay CREATE warning cannot drift apart. `mode` only changes
34058
+ * the lead clause — everything after it (the probe evidence and the working
34059
+ * shape) is identical, because the user's next action is the same either way.
34032
34060
  */
34033
34061
  function icebergTableInputRefusalMessage(logicalId, key, mode) {
34034
- return `AWS::Glue::Table ${logicalId}: OpenTableFormatInput.IcebergInput.${key} ${mode === "create" ? `cannot be deployed by AWS in any shape, so cdkd refuses it before calling Glue (issue #1454).` : "cannot be deployed by AWS in any shape and is IGNORED on update — cdkd does not wire Glue's update-only UpdateOpenTableFormatInput shape, so it forwards nothing here and only warns (issue #1454). A CREATE of this table would be refused outright."}\n Live-probed 2026-08-09 in us-east-1 (issue #1408): glue:CreateTable — the API cdkd calls — rejects every Iceberg table spec ("Location information cannot be null while creating an iceberg table" without a TableInput.StorageDescriptor, "Table metadata information present at multiple parts of input request" with one), and CloudFormation rolls the same template back with "Table metadata is expected only via TableInput or via IcebergTableInputProperties inside OpenTableFormatInput" — a property name that exists in neither the CFn registry schema (IcebergInput.IcebergTableInput) nor @aws-sdk/client-glue (IcebergInput.CreateIcebergTableInput).\n Working shape — put the table metadata in TableInput and leave IcebergInput carrying only the create-time directive:\n TableInput: { Name, TableType: 'EXTERNAL_TABLE', StorageDescriptor: { Location: 's3://your-bucket/prefix/', Columns: [...] } }\n OpenTableFormatInput: { IcebergInput: { MetadataOperation: 'CREATE' } } // Version: '2' is also accepted\n Glue then writes the Iceberg metadata itself — the created table comes back with Parameters.table_type = ICEBERG and a populated Parameters.metadata_location.`;
34062
+ return `AWS::Glue::Table ${logicalId}: OpenTableFormatInput.IcebergInput.${key} ${mode === "create" ? `cannot be deployed by AWS in any shape, so cdkd refuses it before calling Glue (issue #1454).` : mode === "create-replay" ? "cannot be deployed by AWS in any shape, so cdkd normally refuses it before calling Glue (issue #1454) — but this create is REPLAYING a historical cdkd STATE record (a rollback reverse-replacement re-creating the OLD table), not your template, and refusing would leave that table unrestorable with no template-side remedy, only a hand-edit of state.json. cdkd therefore warns and proceeds (issue #1463). The re-created table is DEGRADED exactly as the original was: under the CFn spelling IcebergTableInput the AWS SDK serializer drops the unknown member (issue #1390), so the table comes back without its Iceberg metadata; under the SDK spelling CreateIcebergTableInput the value IS sent and Glue rejects the call, failing this one rollback operation. Either way, fix it forward with 'cdkd deploy' using the working shape below." : "cannot be deployed by AWS in any shape and is IGNORED on update — cdkd does not wire Glue's update-only UpdateOpenTableFormatInput shape, so it forwards nothing here and only warns (issue #1454). A CREATE of this table would be refused outright."}\n Live-probed 2026-08-09 in us-east-1 (issue #1408): glue:CreateTable — the API cdkd calls — rejects every Iceberg table spec ("Location information cannot be null while creating an iceberg table" without a TableInput.StorageDescriptor, "Table metadata information present at multiple parts of input request" with one), and CloudFormation rolls the same template back with "Table metadata is expected only via TableInput or via IcebergTableInputProperties inside OpenTableFormatInput" — a property name that exists in neither the CFn registry schema (IcebergInput.IcebergTableInput) nor @aws-sdk/client-glue (IcebergInput.CreateIcebergTableInput).\n Working shape — put the table metadata in TableInput and leave IcebergInput carrying only the create-time directive:\n TableInput: { Name, TableType: 'EXTERNAL_TABLE', StorageDescriptor: { Location: 's3://your-bucket/prefix/', Columns: [...] } }\n OpenTableFormatInput: { IcebergInput: { MetadataOperation: 'CREATE' } } // Version: '2' is also accepted\n Glue then writes the Iceberg metadata itself — the created table comes back with Parameters.table_type = ICEBERG and a populated Parameters.metadata_location.`;
34035
34063
  }
34036
34064
  /**
34037
34065
  * Build the SDK `EncryptionConfiguration` from the CFn-shape input
@@ -36093,7 +36121,8 @@ var KinesisStreamProvider = class {
36093
36121
  this.logger.debug(`Creating Kinesis stream ${logicalId}`);
36094
36122
  const streamName = properties["Name"] || generateResourceName(logicalId, { maxLength: 128 });
36095
36123
  try {
36096
- const streamMode = properties["StreamModeDetails"]?.["StreamMode"] || "PROVISIONED";
36124
+ const streamModeDetails = properties["StreamModeDetails"];
36125
+ const streamMode = readConfigString(streamModeDetails, "StreamMode", "PROVISIONED", "AWS::Kinesis::Stream StreamModeDetails");
36097
36126
  const shardCount = streamMode === "PROVISIONED" ? Number(properties["ShardCount"] ?? 1) : void 0;
36098
36127
  await this.getClient().send(new CreateStreamCommand({
36099
36128
  StreamName: streamName,
@@ -36157,7 +36186,8 @@ var KinesisStreamProvider = class {
36157
36186
  async update(logicalId, physicalId, resourceType, properties, previousProperties) {
36158
36187
  this.logger.debug(`Updating Kinesis stream ${logicalId}: ${physicalId}`);
36159
36188
  try {
36160
- const streamMode = properties["StreamModeDetails"]?.["StreamMode"] || "PROVISIONED";
36189
+ const streamModeDetails = properties["StreamModeDetails"];
36190
+ const streamMode = readConfigString(streamModeDetails, "StreamMode", "PROVISIONED", "AWS::Kinesis::Stream StreamModeDetails");
36161
36191
  const oldStreamMode = previousProperties["StreamModeDetails"]?.["StreamMode"] || "PROVISIONED";
36162
36192
  const modeChanged = oldStreamMode !== streamMode;
36163
36193
  if (modeChanged) {
@@ -43460,7 +43490,7 @@ var S3DirectoryBucketProvider = class {
43460
43490
  */
43461
43491
  async create(logicalId, resourceType, properties) {
43462
43492
  this.logger.debug(`Creating S3 Express Directory Bucket ${logicalId}`);
43463
- const dataRedundancy = properties["DataRedundancy"] || "SingleAvailabilityZone";
43493
+ const dataRedundancy = requireConfigString(properties["DataRedundancy"], "SingleAvailabilityZone", "AWS::S3Express::DirectoryBucket DataRedundancy");
43464
43494
  const azName = properties["LocationName"]?.replace(/--x-s3$/, "") || "us-east-1a";
43465
43495
  const azId = await this.getAzId(azName);
43466
43496
  let bucketName = properties["BucketName"];
@@ -65936,7 +65966,7 @@ function createMigrateCommand() {
65936
65966
  */
65937
65967
  function buildProgram() {
65938
65968
  const program = new Command();
65939
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.278.26");
65969
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.278.28");
65940
65970
  program.hook("preAction", (_thisCommand, actionCommand) => {
65941
65971
  const { profile } = actionCommand.optsWithGlobals();
65942
65972
  if (profile !== void 0) process.env["AWS_PROFILE"] = profile;