@go-to-k/cdkd 0.85.0 → 0.86.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
@@ -79317,6 +79317,38 @@ var PRIMARY_IDENTIFIER_FALLBACK = {
79317
79317
  "AWS::Cognito::UserPool": "UserPoolId",
79318
79318
  "AWS::ECR::Repository": "RepositoryName"
79319
79319
  };
79320
+ var COMPOSITE_ID_SPLITTERS = {
79321
+ // cdkd stores `restApiId|resourceId|httpMethod` (apigateway-provider.ts);
79322
+ // CFn primary identifier is [RestApiId, ResourceId, HttpMethod] — same order.
79323
+ "AWS::ApiGateway::Method": (id) => {
79324
+ const parts = id.split("|");
79325
+ if (parts.length !== 3) {
79326
+ throw new Error(
79327
+ `expected 3 parts (restApiId|resourceId|httpMethod), got ${parts.length}: '${id}'`
79328
+ );
79329
+ }
79330
+ return { RestApiId: parts[0], ResourceId: parts[1], HttpMethod: parts[2] };
79331
+ },
79332
+ // cdkd stores `restApiId|resourceId` (apigateway-provider.ts);
79333
+ // CFn primary identifier is [RestApiId, ResourceId].
79334
+ "AWS::ApiGateway::Resource": (id) => {
79335
+ const parts = id.split("|");
79336
+ if (parts.length !== 2) {
79337
+ throw new Error(`expected 2 parts (restApiId|resourceId), got ${parts.length}: '${id}'`);
79338
+ }
79339
+ return { RestApiId: parts[0], ResourceId: parts[1] };
79340
+ },
79341
+ // cdkd stores `IGW|VpcId` (ec2-provider.ts);
79342
+ // CFn primary identifier is [VpcId, InternetGatewayId] — DIFFERENT order
79343
+ // from cdkd. Splitter reorders explicitly.
79344
+ "AWS::EC2::VPCGatewayAttachment": (id) => {
79345
+ const parts = id.split("|");
79346
+ if (parts.length !== 2) {
79347
+ throw new Error(`expected 2 parts (IGW|VpcId), got ${parts.length}: '${id}'`);
79348
+ }
79349
+ return { VpcId: parts[1], InternetGatewayId: parts[0] };
79350
+ }
79351
+ };
79320
79352
  async function exportCommand(stackArg, options) {
79321
79353
  const logger = getLogger();
79322
79354
  if (options.verbose) {
@@ -79587,14 +79619,19 @@ async function buildImportPlan(state, template, cfnClient) {
79587
79619
  });
79588
79620
  continue;
79589
79621
  }
79590
- let identifierKey;
79622
+ let resourceIdentifier;
79591
79623
  try {
79592
- identifierKey = await resolvePrimaryIdentifier(resourceType, cfnClient, identifierCache);
79624
+ resourceIdentifier = await resolveResourceIdentifier(
79625
+ resourceType,
79626
+ stateEntry.physicalId,
79627
+ cfnClient,
79628
+ identifierCache
79629
+ );
79593
79630
  } catch (err) {
79594
79631
  skipped.push({
79595
79632
  logicalId,
79596
79633
  resourceType,
79597
- reason: "could not resolve primary identifier: " + (err instanceof Error ? err.message : String(err))
79634
+ reason: "could not resolve resource identifier: " + (err instanceof Error ? err.message : String(err))
79598
79635
  });
79599
79636
  continue;
79600
79637
  }
@@ -79602,15 +79639,44 @@ async function buildImportPlan(state, template, cfnClient) {
79602
79639
  logicalId,
79603
79640
  resourceType,
79604
79641
  physicalId: stateEntry.physicalId,
79605
- identifierKey
79642
+ resourceIdentifier
79606
79643
  });
79607
79644
  }
79608
79645
  return { plan, skipped };
79609
79646
  }
79610
- async function resolvePrimaryIdentifier(resourceType, cfnClient, cache2) {
79611
- const cached = cache2.get(resourceType);
79612
- if (cached !== void 0)
79613
- return cached;
79647
+ async function resolveResourceIdentifier(resourceType, physicalId, cfnClient, cache2) {
79648
+ let entry = cache2.get(resourceType);
79649
+ if (entry === void 0) {
79650
+ entry = await fetchPrimaryIdentifier(resourceType, cfnClient);
79651
+ cache2.set(resourceType, entry);
79652
+ }
79653
+ if (entry.fields.length === 1) {
79654
+ return { [entry.fields[0]]: physicalId };
79655
+ }
79656
+ const splitter = COMPOSITE_ID_SPLITTERS[resourceType];
79657
+ if (!splitter) {
79658
+ throw new Error(
79659
+ `resource type uses a composite primary identifier (${entry.fields.length} fields: ${entry.fields.join(", ")}); add an entry to COMPOSITE_ID_SPLITTERS in src/cli/commands/export.ts that parses cdkd's physicalId for this type, or destroy the resource first and let CFn create it fresh`
79660
+ );
79661
+ }
79662
+ let split;
79663
+ try {
79664
+ split = splitter(physicalId);
79665
+ } catch (err) {
79666
+ throw new Error(
79667
+ `composite-id splitter for ${resourceType} failed: ` + (err instanceof Error ? err.message : String(err))
79668
+ );
79669
+ }
79670
+ for (const f of entry.fields) {
79671
+ if (!(f in split)) {
79672
+ throw new Error(
79673
+ `composite-id splitter for ${resourceType} did not produce field '${f}' (produced: ${Object.keys(split).join(", ")})`
79674
+ );
79675
+ }
79676
+ }
79677
+ return split;
79678
+ }
79679
+ async function fetchPrimaryIdentifier(resourceType, cfnClient) {
79614
79680
  try {
79615
79681
  const resp = await cfnClient.send(
79616
79682
  new DescribeTypeCommand({ Type: "RESOURCE", TypeName: resourceType })
@@ -79618,15 +79684,9 @@ async function resolvePrimaryIdentifier(resourceType, cfnClient, cache2) {
79618
79684
  if (resp.Schema) {
79619
79685
  const parsed = JSON.parse(resp.Schema);
79620
79686
  const primary = parsed.primaryIdentifier;
79621
- if (Array.isArray(primary) && primary.length === 1 && typeof primary[0] === "string") {
79622
- const propName = primary[0].replace(/^\/properties\//, "");
79623
- cache2.set(resourceType, propName);
79624
- return propName;
79625
- }
79626
- if (Array.isArray(primary) && primary.length > 1) {
79627
- throw new Error(
79628
- `resource type uses a composite primary identifier (${primary.length} fields); cdkd does not yet support composite identifiers for cdkd export`
79629
- );
79687
+ if (Array.isArray(primary) && primary.length > 0 && primary.every((p) => typeof p === "string")) {
79688
+ const fields = primary.map((p) => p.replace(/^\/properties\//, ""));
79689
+ return { fields };
79630
79690
  }
79631
79691
  }
79632
79692
  } catch (err) {
@@ -79635,8 +79695,7 @@ async function resolvePrimaryIdentifier(resourceType, cfnClient, cache2) {
79635
79695
  }
79636
79696
  const fallback = PRIMARY_IDENTIFIER_FALLBACK[resourceType];
79637
79697
  if (fallback) {
79638
- cache2.set(resourceType, fallback);
79639
- return fallback;
79698
+ return { fields: [fallback] };
79640
79699
  }
79641
79700
  throw new Error(
79642
79701
  `primary identifier unknown (DescribeType returned no usable schema and no fallback is registered). Add ${resourceType} to PRIMARY_IDENTIFIER_FALLBACK in export.ts, or open an issue.`
@@ -79696,9 +79755,8 @@ function printPlan(plan, cfnStackName) {
79696
79755
  logger.info("");
79697
79756
  logger.info(`Import plan for CloudFormation stack '${cfnStackName}':`);
79698
79757
  for (const entry of plan) {
79699
- logger.info(
79700
- ` ${entry.logicalId} (${entry.resourceType}) \u2190 ${entry.identifierKey}=${entry.physicalId}`
79701
- );
79758
+ const idStr = Object.entries(entry.resourceIdentifier).map(([k, v]) => `${k}=${v}`).join(", ");
79759
+ logger.info(` ${entry.logicalId} (${entry.resourceType}) \u2190 ${idStr}`);
79702
79760
  }
79703
79761
  logger.info("");
79704
79762
  }
@@ -79709,7 +79767,7 @@ async function executeImportChangeSet(cfnClient, stackName, template, plan) {
79709
79767
  const resourcesToImport = plan.map((entry) => ({
79710
79768
  ResourceType: entry.resourceType,
79711
79769
  LogicalResourceId: entry.logicalId,
79712
- ResourceIdentifier: { [entry.identifierKey]: entry.physicalId }
79770
+ ResourceIdentifier: entry.resourceIdentifier
79713
79771
  }));
79714
79772
  logger.info(
79715
79773
  `Creating IMPORT changeset '${changeSetName}' for stack '${stackName}' (${plan.length} resource(s), ${templateBody.length} bytes)...`
@@ -79880,7 +79938,7 @@ function reorderArgs(argv) {
79880
79938
  }
79881
79939
  async function main() {
79882
79940
  const program = new Command18();
79883
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.85.0");
79941
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.86.0");
79884
79942
  program.addCommand(createBootstrapCommand());
79885
79943
  program.addCommand(createSynthCommand());
79886
79944
  program.addCommand(createListCommand());