@go-to-k/cdkd 0.98.0 → 0.98.2

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
@@ -904,6 +904,23 @@ function createListCommand() {
904
904
  */
905
905
  /** Schema version for the exports index file. Separate from state.json's version. */
906
906
  const EXPORT_INDEX_VERSION = 1;
907
+ /**
908
+ * Shallow-deep equality on the two `name → ExportIndexEntry` maps used
909
+ * to detect no-op writes in `applyStackUpdate`. Values are compared via
910
+ * JSON.stringify (Output values are always JSON-serializable).
911
+ */
912
+ function mapsEqual(a, b) {
913
+ if (a.size !== b.size) return false;
914
+ for (const [name, entry] of a) {
915
+ const other = b.get(name);
916
+ if (!other) return false;
917
+ if (other.producerStack !== entry.producerStack || other.producerRegion !== entry.producerRegion) return false;
918
+ if (other.value !== entry.value) {
919
+ if (JSON.stringify(other.value) !== JSON.stringify(entry.value)) return false;
920
+ }
921
+ }
922
+ return true;
923
+ }
907
924
  const DEFAULT_OPTIONS = {
908
925
  maxWriteRetries: 5,
909
926
  initialBackoffMs: 100,
@@ -1137,6 +1154,7 @@ var ExportIndexStore = class {
1137
1154
  producerStack: stackName,
1138
1155
  producerRegion
1139
1156
  });
1157
+ if (mapsEqual(this.loadState.entries, next)) return;
1140
1158
  await this.persist(next);
1141
1159
  }
1142
1160
  async applyPatch(exportName, entry) {
@@ -4736,23 +4754,75 @@ var SQSQueuePolicyProvider = class {
4736
4754
  /**
4737
4755
  * Adopt an existing SQS queue policy into cdkd state.
4738
4756
  *
4739
- * **Explicit override only.** A `QueuePolicy` is an attachment applied to
4740
- * a queue via `SetQueueAttributes(Policy=...)`it has no standalone
4741
- * identity and is not independently taggable. There is no `aws:cdk:path`
4742
- * tag to look up by; only the queue itself is taggable.
4743
- *
4744
- * Users adopting an existing queue policy should pass
4745
- * `--resource <logicalId>=<queueUrl>` (matching the physical id format
4746
- * returned by `create()`, which uses the first queue URL).
4757
+ * The operational identifier for a `QueuePolicy` is the **queue URL**
4758
+ * (`https://sqs.<region>.amazonaws.com/<account>/<name>`) — every AWS
4759
+ * SDK call (`SetQueueAttributes` / `GetQueueAttributes`) takes a queue
4760
+ * URL via the `QueueUrl` parameter, and cdkd's `create()` records the
4761
+ * first `Queues` entry as the resource's `physicalId` so subsequent
4762
+ * `update()` / `delete()` / `readCurrentState()` calls hit the right
4763
+ * queue. A `QueuePolicy` has no standalone identity, no taggable ARN,
4764
+ * and no `aws:cdk:path` lookup only the parent queue is taggable.
4765
+ *
4766
+ * Resolution order (closes [#351](https://github.com/go-to-k/cdkd/issues/351)):
4767
+ *
4768
+ * 1. **`knownPhysicalId` if it is a valid queue URL.** Preserves the
4769
+ * `cdkd import --resource <logicalId>=<queueUrl>` path that has
4770
+ * always worked.
4771
+ * 2. **First entry of `properties.Queues` if it is a literal queue URL.**
4772
+ * Closes the `--migrate-from-cloudformation` case: AWS CloudFormation's
4773
+ * `DescribeStackResources` returns the CFn-generated policy NAME for
4774
+ * `AWS::SQS::QueuePolicy` (e.g. `MyStack-MyQueuePolicy-XXXXXXXXXX`),
4775
+ * which is NOT a valid `QueueUrl` and crashes the AWS SDK
4776
+ * `queueUrlMiddleware` with `TypeError: Invalid URL` the first time
4777
+ * cdkd touches it (typically `captureObservedForImportedResources` →
4778
+ * `readCurrentState` → `GetQueueAttributes`). The user can also
4779
+ * point `--migrate-from-cloudformation` at a stack whose QueuePolicy
4780
+ * is templated as `Queues: ['https://sqs...']` (rare but valid) —
4781
+ * that literal form falls into this branch.
4782
+ * 3. **Hard error** when neither path resolves a queue URL. This
4783
+ * covers (a) `--migrate-from-cloudformation` against a CFn stack
4784
+ * whose template carries `Queues: [{Ref: <MyQueue>}]` (the typical
4785
+ * CDK shape) when the referenced queue is NOT in the importable
4786
+ * set (or hasn't been imported yet in the current run), and (b)
4787
+ * explicit `--resource <logicalId>=<non-url>` typos. Pointing the
4788
+ * user at `--resource <logicalId>=<queueUrl>` is the recovery path
4789
+ * that always works.
4790
+ *
4791
+ * Intrinsic-valued `Queues[0]` (e.g. `{Ref: <MyQueue>}`) falls into
4792
+ * branch 3 here even when the referenced sibling has been imported in
4793
+ * the same run — `import()` is called BEFORE
4794
+ * `resolveImportedProperties` runs the synth template's Properties
4795
+ * through the intrinsic resolver, so the raw intrinsic object is what
4796
+ * we see. The recovery message names `--resource` as the explicit
4797
+ * escape hatch.
4747
4798
  */
4748
4799
  async import(input) {
4749
- if (input.knownPhysicalId) return {
4800
+ if (input.knownPhysicalId && isSqsQueueUrl(input.knownPhysicalId)) return {
4750
4801
  physicalId: input.knownPhysicalId,
4751
4802
  attributes: {}
4752
4803
  };
4753
- return null;
4804
+ const queues = input.properties["Queues"];
4805
+ if (Array.isArray(queues) && queues.length > 0) {
4806
+ const first = queues[0];
4807
+ if (typeof first === "string" && isSqsQueueUrl(first)) return {
4808
+ physicalId: first,
4809
+ attributes: {}
4810
+ };
4811
+ }
4812
+ const knownNote = input.knownPhysicalId ? ` Got knownPhysicalId='${input.knownPhysicalId}' (not a queue URL; CloudFormation returns the policy resource NAME for AWS::SQS::QueuePolicy, which is not the operational identifier).` : "";
4813
+ const queuesNote = Array.isArray(queues) && queues.length > 0 ? ` Properties.Queues[0]=${JSON.stringify(queues[0])} did not resolve to a literal queue URL (intrinsic-valued entries like {Ref: <Queue>} are not resolved at import time).` : " Properties.Queues is missing or empty.";
4814
+ throw new Error(`Cannot determine queue URL for ${input.resourceType} '${input.logicalId}'.${knownNote}${queuesNote} Re-run with --resource ${input.logicalId}=<queueUrl> (e.g. https://sqs.${input.region}.amazonaws.com/<account>/<queue-name>) to point cdkd at the queue this policy is attached to.`);
4754
4815
  }
4755
4816
  };
4817
+ /**
4818
+ * Recognize an SQS queue URL. AWS standard form is
4819
+ * `https://sqs.<region>.amazonaws.com/<account>/<name>`; FIFO queues end
4820
+ * in `.fifo`. Non-standard partitions (`amazonaws.com.cn` /
4821
+ * `c2s.ic.gov` / etc.) are accepted via the broader prefix check.
4822
+ */
4823
+ function isSqsQueueUrl(value) {
4824
+ return value.startsWith("https://sqs.") && value.includes("/");
4825
+ }
4756
4826
 
4757
4827
  //#endregion
4758
4828
  //#region src/provisioning/providers/sns-topic-provider.ts
@@ -42225,7 +42295,7 @@ function reorderArgs(argv) {
42225
42295
  */
42226
42296
  async function main() {
42227
42297
  const program = new Command();
42228
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.97.0");
42298
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.98.1");
42229
42299
  program.addCommand(createBootstrapCommand());
42230
42300
  program.addCommand(createSynthCommand());
42231
42301
  program.addCommand(createListCommand());