@go-to-k/cdkd 0.280.39 → 0.280.41

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 requireConfigObject, $t as AssemblyReader, A as green, At as runDockerForeground, B as disableInstanceApiTermination, Bt as resolveCaptureObservedState, C as MULTI_REGION_RECREATE_BLOCKED_TYPES, Cn as StackTerminationProtectionError, Ct as getBootstrapMarkerKey, D as bold, Dt as buildDockerImage, E as formatResourceLine, Et as validateContainerRepoName, F as clearOnUpdateRemoval, Ft as synthesisStatusMessage, G as WAFv2WebACLProvider, Gt as stateBucketExistenceConfirmed, H as IntrinsicFunctionResolver, Ht as resolveStateBucketWithDefault, I as ProviderRegistry, It as getDefaultStateBucketName, J as assertRegionMatch, Jt as CFN_TEMPLATE_URL_LIMIT, K as normalizeAwsTagsToCfn, Kt as warnDeprecatedNoPrefixCliFlag, L as findActionableSilentDrops, Lt as getLegacyStateBucketName, M as yellow, Mt as AssetManifestLoader, N as IAMRoleProvider, Nt as getDockerImageBySourceHash, O as cyan, On as normalizeAwsError, Ot as formatDockerLoginError, P as collectInlinePolicyNamesManagedBySiblings, Pt as Synthesizer, Q as requireConfigArray, Qt as expectedOwnerParam, R as CloudControlProvider, Rt as resolveApp, S as extractDeploymentEventError, Sn as StackHasActiveImportsError, St as ensureAssetStorage, T as renderStatefulReason, Tt as validateAssetBucketName, U as cfnRefValueFromPhysicalId, Ut as resolveStateBucketWithDefaultAndSource, V as isTerminationProtectionPropagationError, Vt as resolveSkipPrefix, W as refStateLookupFromResource, Wt as resolveUseCdkBootstrapAssets, X as readConfigString, Xt as findLargeInlineResources, Y as configStringRefusal, Yt as MIGRATE_TMP_PREFIX, Z as replayWarn, Zt as uploadCfnTemplate, _ as createPreDeleteFinalSnapshot, _n as NestedStackChildDirectDestroyError, _t as createAssetRedirectResolver, a as DeploymentEventsStore, an as resetAwsClients, at as isRetryableTransientError, b as unsupportedFinalSnapshotError, bn as ResourceTimeoutError, bt as AssetModeResolver, c as replayFailedOperations, cn as CdkdError, ct as TemplateParser, d as IMPLICIT_DELETE_DEPENDENCIES, dn as DeployCancelledError, dt as rebuildClientForBucketRegion, en as processStackMessages, et as requireConfigString, f as computeImplicitDeleteEdges, fn as LocalInvokeBuildError$1, ft as shouldRetainResource, g as ccRoutedFinalSnapshotError, gn as MissingCdkCliError, gt as buildAssetRedirectMap, h as buildFinalSnapshotIdentifier, ht as WorkGraph, i as DeploymentEventsReader, in as getAwsClients, it as withRetry, j as red, jt as runDockerStreaming, k as gray, kn as withErrorHandling, kt as getDockerCmd, l as replayRollback, lt as LockManager, m as PRE_DELETE_SNAPSHOT_TYPES, mn as LocalStartServiceError, mt as stringifyValue, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as resolveBucketRegion, nt as DiffCalculator, o as planFailedOps, on as setAwsClients, ot as isThrottlingError, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as LocalMigrateError, pt as AssetPublisher, q as resolveExplicitPhysicalId, qt as CFN_TEMPLATE_BODY_LIMIT, r as DeployEngine, rn as AwsClients, rt as describeTypeWithThrottleRetry, s as planRollback, st as DagBuilder, t as DEFAULT_RESOURCE_TIMEOUT_MS, tt as applyRoleArnIfSet, u as withResourceDeadline, ut as S3StateBackend, v as isFinalSnapshotError, vn as PartialFailureError, vt as loadPublishableAssetManifest, w as isStatefulRecreateTargetSync, wt as parseBootstrapMarker, x as makeCanonicalizePropertiesFn, xn as ResourceUpdateNotSupportedError, xt as BOOTSTRAP_MARKER_PREFIX, y as refusesFinalSnapshot, yn as ProvisioningError, yt as rewriteTemplateAssetReferences, z as slowCcOperationTimeoutMs, zt as resolveAutoAssetStorage } from "./deploy-engine-BXVYshtP.js";
2
+ import { $ as requireConfigObject, $t as AssemblyReader, A as green, At as runDockerForeground, B as disableInstanceApiTermination, Bt as resolveCaptureObservedState, C as MULTI_REGION_RECREATE_BLOCKED_TYPES, Cn as StackTerminationProtectionError, Ct as getBootstrapMarkerKey, D as bold, Dt as buildDockerImage, E as formatResourceLine, Et as validateContainerRepoName, F as clearOnUpdateRemoval, Ft as synthesisStatusMessage, G as WAFv2WebACLProvider, Gt as stateBucketExistenceConfirmed, H as IntrinsicFunctionResolver, Ht as resolveStateBucketWithDefault, I as ProviderRegistry, It as getDefaultStateBucketName, J as assertRegionMatch, Jt as CFN_TEMPLATE_URL_LIMIT, K as normalizeAwsTagsToCfn, Kt as warnDeprecatedNoPrefixCliFlag, L as findActionableSilentDrops, Lt as getLegacyStateBucketName, M as yellow, Mt as AssetManifestLoader, N as IAMRoleProvider, Nt as getDockerImageBySourceHash, O as cyan, On as normalizeAwsError, Ot as formatDockerLoginError, P as collectInlinePolicyNamesManagedBySiblings, Pt as Synthesizer, Q as requireConfigArray, Qt as expectedOwnerParam, R as CloudControlProvider, Rt as resolveApp, S as extractDeploymentEventError, Sn as StackHasActiveImportsError, St as ensureAssetStorage, T as renderStatefulReason, Tt as validateAssetBucketName, U as cfnRefValueFromPhysicalId, Ut as resolveStateBucketWithDefaultAndSource, V as isTerminationProtectionPropagationError, Vt as resolveSkipPrefix, W as refStateLookupFromResource, Wt as resolveUseCdkBootstrapAssets, X as readConfigString, Xt as findLargeInlineResources, Y as configStringRefusal, Yt as MIGRATE_TMP_PREFIX, Z as replayWarn, Zt as uploadCfnTemplate, _ as createPreDeleteFinalSnapshot, _n as NestedStackChildDirectDestroyError, _t as createAssetRedirectResolver, a as DeploymentEventsStore, an as resetAwsClients, at as isRetryableTransientError, b as unsupportedFinalSnapshotError, bn as ResourceTimeoutError, bt as AssetModeResolver, c as replayFailedOperations, cn as CdkdError, ct as TemplateParser, d as IMPLICIT_DELETE_DEPENDENCIES, dn as DeployCancelledError, dt as rebuildClientForBucketRegion, en as processStackMessages, et as requireConfigString, f as computeImplicitDeleteEdges, fn as LocalInvokeBuildError$1, ft as shouldRetainResource, g as ccRoutedFinalSnapshotError, gn as MissingCdkCliError, gt as buildAssetRedirectMap, h as buildFinalSnapshotIdentifier, ht as WorkGraph, i as DeploymentEventsReader, in as getAwsClients, it as withRetry, j as red, jt as runDockerStreaming, k as gray, kn as withErrorHandling, kt as getDockerCmd, l as replayRollback, lt as LockManager, m as PRE_DELETE_SNAPSHOT_TYPES, mn as LocalStartServiceError, mt as stringifyValue, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as resolveBucketRegion, nt as DiffCalculator, o as planFailedOps, on as setAwsClients, ot as isThrottlingError, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as LocalMigrateError, pt as AssetPublisher, q as resolveExplicitPhysicalId, qt as CFN_TEMPLATE_BODY_LIMIT, r as DeployEngine, rn as AwsClients, rt as describeTypeWithThrottleRetry, s as planRollback, st as DagBuilder, t as DEFAULT_RESOURCE_TIMEOUT_MS, tt as applyRoleArnIfSet, u as withResourceDeadline, ut as S3StateBackend, v as isFinalSnapshotError, vn as PartialFailureError, vt as loadPublishableAssetManifest, w as isStatefulRecreateTargetSync, wt as parseBootstrapMarker, x as makeCanonicalizePropertiesFn, xn as ResourceUpdateNotSupportedError, xt as BOOTSTRAP_MARKER_PREFIX, y as refusesFinalSnapshot, yn as ProvisioningError, yt as rewriteTemplateAssetReferences, z as slowCcOperationTimeoutMs, zt as resolveAutoAssetStorage } from "./deploy-engine-D3j4WK7_.js";
3
3
  import { a as getLiveRenderer, c as PATTERN_B_RESOURCE_TYPES, d as generateResourceNameWithFallback, h as withStackName, i as runStackBuffered, m as withSkipPrefix, n as getLogger, o as PATTERN_B_NAME_OPTIONS, s as PATTERN_B_NAME_PROPERTIES, u as generateResourceName } from "./logger-zRrlbaQt.js";
4
- import { t as ASGProvider } from "./asg-provider-DPYPr-Op.js";
4
+ import { t as ASGProvider } from "./asg-provider-Bdmv1zQr.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";
@@ -22724,13 +22724,33 @@ var ApiGatewayProvider = class ApiGatewayProvider {
22724
22724
  * Users adopting an existing API Gateway should pass
22725
22725
  * `--resource <logicalId>=<physicalId>` for each sub-resource; the
22726
22726
  * physical id format follows what `create()` returns for the same
22727
- * type (e.g. `<restApiId>|<resourceId>` for `AWS::ApiGateway::Resource`).
22727
+ * type. Note this is NOT uniformly a composite: `create()` returns a
22728
+ * BARE `resourceId` for `AWS::ApiGateway::Resource` (the parent
22729
+ * `RestApiId` is read from the recorded properties by every other
22730
+ * method), while `AWS::ApiGateway::Method` genuinely is
22731
+ * `<restApiId>|<resourceId>|<httpMethod>`.
22732
+ *
22733
+ * `import()` otherwise honours the supplied id verbatim, so a composite
22734
+ * passed for a type whose provider stores a SCALAR would be written to
22735
+ * state and then fed to the API as a resource id (issue #1663). That is
22736
+ * not merely a failed call: `deleteResource` treats `NotFoundException`
22737
+ * as an idempotent success, so the bad id would be reported as deleted
22738
+ * while the resource stayed live in AWS — a silent orphan, the same class
22739
+ * as issues #1651 / #1658. So the one type whose stored shape is
22740
+ * unambiguously scalar refuses a composite up front, where the user can
22741
+ * still act on it.
22728
22742
  */
22729
22743
  async import(input) {
22730
- if (input.knownPhysicalId) return {
22731
- physicalId: input.knownPhysicalId,
22732
- attributes: {}
22733
- };
22744
+ if (input.knownPhysicalId) {
22745
+ if (input.resourceType === "AWS::ApiGateway::Resource" && input.knownPhysicalId.includes("|")) {
22746
+ this.logger.warn(`AWS::ApiGateway::Resource ${input.logicalId}: '${input.knownPhysicalId}' looks like a composite, but cdkd stores a BARE resourceId for this type (the parent RestApiId comes from the template). Adopting it would send the whole string to the API as a resource id, and the delete path would then report success on the NotFound. Pass just the resourceId.`);
22747
+ return null;
22748
+ }
22749
+ return {
22750
+ physicalId: input.knownPhysicalId,
22751
+ attributes: {}
22752
+ };
22753
+ }
22734
22754
  return null;
22735
22755
  }
22736
22756
  };
@@ -37386,6 +37406,97 @@ var AppSyncProvider = class {
37386
37406
  function importableString(value) {
37387
37407
  return typeof value === "string" && value.length > 0 ? value : void 0;
37388
37408
  }
37409
+ /** The one pseudo parameter whose value IS the Glue API's `CatalogId` default. */
37410
+ const ACCOUNT_ID_PSEUDO_PARAMETER = "AWS::AccountId";
37411
+ const ACCOUNT_ID_SUB_TEMPLATE = "${AWS::AccountId}";
37412
+ /**
37413
+ * Is this unresolved intrinsic PROVABLY the caller's own account id?
37414
+ *
37415
+ * `@aws-cdk/aws-glue-alpha` sets `catalogId: Stack.of(this).account`, which
37416
+ * renders as `{Ref: AWS::AccountId}` (or an `Fn::Sub` wrapper) for an
37417
+ * environment-agnostic stack. A pseudo parameter is never in the import
37418
+ * overrides map, so a `cdkd import`-written state record holds the intrinsic
37419
+ * verbatim — but its resolved value is exactly what OMITTING `CatalogId` gives
37420
+ * the Glue API, so dropping it is not a loss and a NotFound afterwards is
37421
+ * ordinary idempotency, not the silent-leak shape.
37422
+ *
37423
+ * Kept deliberately narrow. An intrinsic object has exactly ONE key, and only
37424
+ * the two account-id spellings qualify: `{Ref: SomeParam}`, `Fn::ImportValue`,
37425
+ * an `Fn::Sub` of anything else, and every other shape stay UNUSABLE, because
37426
+ * their resolved value could be any catalog at all.
37427
+ */
37428
+ function isAccountIdPseudoParameter(value) {
37429
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
37430
+ const keys = Object.keys(value);
37431
+ if (keys.length !== 1) return false;
37432
+ const bag = value;
37433
+ if (keys[0] === "Ref") return bag["Ref"] === ACCOUNT_ID_PSEUDO_PARAMETER;
37434
+ if (keys[0] === "Fn::Sub") {
37435
+ const arg = bag["Fn::Sub"];
37436
+ if (typeof arg === "string") return arg === ACCOUNT_ID_SUB_TEMPLATE;
37437
+ return Array.isArray(arg) && arg[0] === ACCOUNT_ID_SUB_TEMPLATE;
37438
+ }
37439
+ return false;
37440
+ }
37441
+ /**
37442
+ * Coerce a template-borne `CatalogId` into the string the Glue API wants, or
37443
+ * `undefined` when no usable value is present (issue
37444
+ * [#1675](https://github.com/go-to-k/cdkd/issues/1675)).
37445
+ *
37446
+ * This is {@link importableString} plus a NUMBER arm, and the number arm is
37447
+ * load-bearing rather than defensive: `cdkd import --migrate-from-cloudformation`
37448
+ * reads the stack's ORIGINAL template (`cfn-stack-prefetch.ts`), where an
37449
+ * unquoted YAML `CatalogId: 123456789012` parses as a JSON number. Rejecting it
37450
+ * as "not a string" would drop the field and silently retarget the call at the
37451
+ * account's DEFAULT catalog — which on a DELETE can destroy a same-named
37452
+ * resource that happens to live there. `Number.isFinite` keeps `NaN` /
37453
+ * `Infinity` out (they fall through to the unusable arm, where they are
37454
+ * reported); a non-integer is stringified and AWS rejects it loudly, which is
37455
+ * the right failure.
37456
+ *
37457
+ * The coercion lives HERE rather than inside `importableString`: that helper is
37458
+ * shared with `DatabaseName` / `TableInput.Name` reads, where a number is a
37459
+ * malformed template rather than a YAML scalar to recover.
37460
+ */
37461
+ function catalogIdForApi(value) {
37462
+ if (typeof value === "number" && Number.isFinite(value)) return String(value);
37463
+ return importableString(value);
37464
+ }
37465
+ function deleteCatalogId(properties) {
37466
+ const raw = properties?.["CatalogId"];
37467
+ const catalogId = catalogIdForApi(raw);
37468
+ return {
37469
+ catalogId,
37470
+ declaredButUnusable: catalogId === void 0 && raw != null && !isAccountIdPseudoParameter(raw)
37471
+ };
37472
+ }
37473
+ /** Human-readable name for the catalog a call addressed, for log messages. */
37474
+ function describeCatalog(catalogId) {
37475
+ return catalogId === void 0 ? "this account's default Data Catalog" : `Data Catalog ${catalogId}`;
37476
+ }
37477
+ /**
37478
+ * Report the `EntityNotFoundException` arm of a Glue delete, at the severity
37479
+ * the evidence supports (issue #1675).
37480
+ *
37481
+ * With a correctly-targeted delete a NotFound means the resource is already
37482
+ * gone and the skip is ordinary idempotency — debug. When the template DECLARED
37483
+ * a `CatalogId` that {@link deleteCatalogId} could not use, cdkd addressed the
37484
+ * DEFAULT catalog instead, so a NotFound is equally consistent with "the
37485
+ * resource is alive in the declared catalog" — that is the silent-leak shape,
37486
+ * and it gets a warning.
37487
+ *
37488
+ * BOTH arms name the catalog actually addressed. A LITERAL-but-wrong
37489
+ * `CatalogId` (a typo, a stale account id) is otherwise indistinguishable from
37490
+ * an already-deleted resource in the log, and it takes the debug arm.
37491
+ */
37492
+ function logCatalogScopedDeleteSkip(logger, target, kind, logicalId, physicalId) {
37493
+ const where = describeCatalog(target.catalogId);
37494
+ if (!target.declaredButUnusable) {
37495
+ logger.debug(`Glue ${kind} ${physicalId} does not exist in ${where}, skipping deletion`);
37496
+ return;
37497
+ }
37498
+ logger.warn(`Glue ${kind} ${logicalId} (${physicalId}) was not found, so cdkd skipped its deletion — but the recorded CatalogId is not a usable value (likely an unresolved intrinsic), so the delete targeted ${where}. If the resource lives in a different Data Catalog it still exists. cdkd cannot retry this delete: the state record is dropped once the destroy completes, so check the intended catalog (aws glue get-${kind.toLowerCase()} --catalog-id <id> ...) and delete the resource there by hand.`);
37499
+ }
37389
37500
  function resolveTableIdentity(input) {
37390
37501
  const { knownPhysicalId, templateDatabaseName, templateTableName } = input;
37391
37502
  let databaseName;
@@ -37517,17 +37628,18 @@ var GlueProvider = class {
37517
37628
  }
37518
37629
  async deleteDatabase(logicalId, physicalId, resourceType, properties, context) {
37519
37630
  this.logger.debug(`Deleting Glue Database ${logicalId}: ${physicalId}`);
37631
+ const target = deleteCatalogId(properties);
37632
+ if (target.declaredButUnusable) this.logger.debug(`Glue Database ${logicalId}: CatalogId is not a usable value (likely an unresolved intrinsic), so DeleteDatabase targets ${describeCatalog(target.catalogId)}.`);
37520
37633
  try {
37521
- const catalogId = properties?.["CatalogId"];
37522
37634
  await this.getClient().send(new DeleteDatabaseCommand({
37523
37635
  Name: physicalId,
37524
- ...catalogId && { CatalogId: catalogId }
37636
+ ...target.catalogId !== void 0 && { CatalogId: target.catalogId }
37525
37637
  }));
37526
37638
  this.logger.debug(`Successfully deleted Glue Database ${logicalId}`);
37527
37639
  } catch (error) {
37528
37640
  if (error instanceof EntityNotFoundException) {
37529
37641
  assertRegionMatch(await this.getClient().config.region(), context?.expectedRegion, resourceType, logicalId, physicalId);
37530
- this.logger.debug(`Glue Database ${physicalId} does not exist, skipping deletion`);
37642
+ logCatalogScopedDeleteSkip(this.logger, target, "Database", logicalId, physicalId);
37531
37643
  return;
37532
37644
  }
37533
37645
  const cause = error instanceof Error ? error : void 0;
@@ -37602,15 +37714,18 @@ var GlueProvider = class {
37602
37714
  throw new ProvisioningError(message, resourceType, logicalId, physicalId, cause);
37603
37715
  }
37604
37716
  }
37605
- async deleteTable(logicalId, physicalId, resourceType, _properties, context) {
37717
+ async deleteTable(logicalId, physicalId, resourceType, properties, context) {
37606
37718
  this.logger.debug(`Deleting Glue Table ${logicalId}: ${physicalId}`);
37607
37719
  const [databaseName, tableName] = physicalId.split("|");
37608
37720
  if (!databaseName || !tableName) {
37609
37721
  this.logger.warn(`Invalid Glue Table physical ID format: ${physicalId}, skipping`);
37610
37722
  return;
37611
37723
  }
37724
+ const target = deleteCatalogId(properties);
37725
+ if (target.declaredButUnusable) this.logger.debug(`Glue Table ${logicalId}: CatalogId is not a usable value (likely an unresolved intrinsic), so DeleteTable targets ${describeCatalog(target.catalogId)}.`);
37612
37726
  try {
37613
37727
  await this.getClient().send(new DeleteTableCommand$1({
37728
+ ...target.catalogId !== void 0 && { CatalogId: target.catalogId },
37614
37729
  DatabaseName: databaseName,
37615
37730
  Name: tableName
37616
37731
  }));
@@ -37618,7 +37733,7 @@ var GlueProvider = class {
37618
37733
  } catch (error) {
37619
37734
  if (error instanceof EntityNotFoundException) {
37620
37735
  assertRegionMatch(await this.getClient().config.region(), context?.expectedRegion, resourceType, logicalId, physicalId);
37621
- this.logger.debug(`Glue Table ${physicalId} does not exist, skipping deletion`);
37736
+ logCatalogScopedDeleteSkip(this.logger, target, "Table", logicalId, physicalId);
37622
37737
  return;
37623
37738
  }
37624
37739
  const cause = error instanceof Error ? error : void 0;
@@ -37965,7 +38080,7 @@ var GlueProvider = class {
37965
38080
  * up drift detection for the rest.
37966
38081
  */
37967
38082
  async readCurrentState(physicalId, _logicalId, resourceType, properties) {
37968
- const catalogId = properties?.["CatalogId"];
38083
+ const catalogId = catalogIdForApi(properties?.["CatalogId"]);
37969
38084
  switch (resourceType) {
37970
38085
  case "AWS::Glue::Database": return this.readDatabase(physicalId, catalogId);
37971
38086
  case "AWS::Glue::Table": return this.readTable(physicalId, catalogId);
@@ -38050,7 +38165,7 @@ var GlueProvider = class {
38050
38165
  }
38051
38166
  async importDatabase(input) {
38052
38167
  const explicitName = input.knownPhysicalId ?? importableString(input.properties["DatabaseInput"]?.["Name"]);
38053
- const catalogId = importableString(input.properties["CatalogId"]);
38168
+ const catalogId = catalogIdForApi(input.properties["CatalogId"]);
38054
38169
  if (explicitName) try {
38055
38170
  await this.getClient().send(new GetDatabaseCommand({
38056
38171
  Name: explicitName,
@@ -38070,7 +38185,7 @@ var GlueProvider = class {
38070
38185
  const databaseName = importableString(input.properties["DatabaseName"]);
38071
38186
  const tableInput = input.properties["TableInput"];
38072
38187
  const templateTableName = importableString(tableInput?.["Name"]);
38073
- const catalogId = importableString(input.properties["CatalogId"]);
38188
+ const catalogId = catalogIdForApi(input.properties["CatalogId"]);
38074
38189
  const identity = resolveTableIdentity({
38075
38190
  knownPhysicalId: input.knownPhysicalId,
38076
38191
  templateDatabaseName: databaseName,
@@ -39338,16 +39453,17 @@ var GlueConnectionProvider = class {
39338
39453
  }
39339
39454
  async delete(logicalId, physicalId, resourceType, properties, context) {
39340
39455
  this.logger.debug(`Deleting Glue Connection ${logicalId}: ${physicalId}`);
39341
- const catalogId = properties?.["CatalogId"];
39456
+ const target = deleteCatalogId(properties);
39457
+ if (target.declaredButUnusable) this.logger.debug(`Glue Connection ${logicalId}: CatalogId is not a usable value (likely an unresolved intrinsic), so DeleteConnection targets ${describeCatalog(target.catalogId)}.`);
39342
39458
  try {
39343
39459
  await this.getClient().send(new DeleteConnectionCommand({
39344
39460
  ConnectionName: physicalId,
39345
- ...catalogId && { CatalogId: catalogId }
39461
+ ...target.catalogId !== void 0 && { CatalogId: target.catalogId }
39346
39462
  }));
39347
39463
  } catch (error) {
39348
39464
  if (error instanceof EntityNotFoundException) {
39349
39465
  assertRegionMatch(await this.getClient().config.region(), context?.expectedRegion, resourceType, logicalId, physicalId);
39350
- this.logger.debug(`Glue Connection ${physicalId} does not exist, skipping deletion`);
39466
+ logCatalogScopedDeleteSkip(this.logger, target, "Connection", logicalId, physicalId);
39351
39467
  return;
39352
39468
  }
39353
39469
  const cause = error instanceof Error ? error : void 0;
@@ -39358,12 +39474,12 @@ var GlueConnectionProvider = class {
39358
39474
  if (attributeName === "Id" || attributeName === "Ref" || attributeName === "Name") return physicalId;
39359
39475
  }
39360
39476
  async readCurrentState(physicalId, _logicalId, _resourceType, properties) {
39361
- const catalogId = properties?.["CatalogId"];
39477
+ const catalogId = catalogIdForApi(properties?.["CatalogId"]);
39362
39478
  let conn;
39363
39479
  try {
39364
39480
  conn = (await this.getClient().send(new GetConnectionCommand({
39365
39481
  Name: physicalId,
39366
- ...catalogId && { CatalogId: catalogId }
39482
+ ...catalogId !== void 0 && { CatalogId: catalogId }
39367
39483
  }))).Connection;
39368
39484
  } catch (err) {
39369
39485
  if (err instanceof EntityNotFoundException) return void 0;
@@ -39385,11 +39501,11 @@ var GlueConnectionProvider = class {
39385
39501
  async import(input) {
39386
39502
  const explicitName = input.knownPhysicalId ?? input.properties["ConnectionInput"]?.["Name"];
39387
39503
  if (!explicitName) return null;
39388
- const catalogId = input.properties["CatalogId"];
39504
+ const catalogId = catalogIdForApi(input.properties["CatalogId"]);
39389
39505
  try {
39390
39506
  await this.getClient().send(new GetConnectionCommand({
39391
39507
  Name: explicitName,
39392
- ...catalogId && { CatalogId: catalogId }
39508
+ ...catalogId !== void 0 && { CatalogId: catalogId }
39393
39509
  }));
39394
39510
  return {
39395
39511
  physicalId: explicitName,
@@ -55535,13 +55651,29 @@ const COMPOSITE_ID_SPLITTERS = {
55535
55651
  HttpMethod: parts[2]
55536
55652
  } };
55537
55653
  },
55538
- "AWS::ApiGateway::Resource": (id) => {
55539
- const parts = id.split("|");
55540
- if (parts.length !== 2) throw new Error(`expected 2 parts (restApiId|resourceId), got ${parts.length}: '${id}'`);
55541
- return { resourceIdentifier: {
55542
- RestApiId: parts[0],
55543
- ResourceId: parts[1]
55544
- } };
55654
+ "AWS::ApiGateway::Resource": (physicalId, properties) => {
55655
+ if (!physicalId.trim()) throw new Error("empty physical id for AWS::ApiGateway::Resource (expected a resourceId)");
55656
+ const parts = physicalId.split("|");
55657
+ if (parts.length > 2) throw new Error(`expected a bare resourceId or 'restApiId|resourceId', got ${parts.length} parts: '${physicalId}'`);
55658
+ if (parts.length === 2) {
55659
+ const [restApiId, resourceId] = parts;
55660
+ if (!restApiId || !resourceId) throw new Error(`empty part in 'restApiId|resourceId': '${physicalId}'`);
55661
+ return {
55662
+ resourceIdentifier: {
55663
+ RestApiId: restApiId,
55664
+ ResourceId: resourceId
55665
+ },
55666
+ propertiesOverlay: { RestApiId: restApiId }
55667
+ };
55668
+ }
55669
+ const restApiId = readStringProperty(properties, "RestApiId", "AWS::ApiGateway::Resource");
55670
+ return {
55671
+ resourceIdentifier: {
55672
+ RestApiId: restApiId,
55673
+ ResourceId: physicalId
55674
+ },
55675
+ propertiesOverlay: { RestApiId: restApiId }
55676
+ };
55545
55677
  },
55546
55678
  "AWS::EC2::VPCGatewayAttachment": (id) => {
55547
55679
  const parts = id.split("|");
@@ -71574,7 +71706,7 @@ function createMigrateCommand() {
71574
71706
  */
71575
71707
  function buildProgram() {
71576
71708
  const program = new Command();
71577
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.280.39");
71709
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.280.41");
71578
71710
  program.hook("preAction", (_thisCommand, actionCommand) => {
71579
71711
  const { profile } = actionCommand.optsWithGlobals();
71580
71712
  if (profile !== void 0) process.env["AWS_PROFILE"] = profile;