@go-to-k/cdkd 0.152.1 → 0.153.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.
@@ -5423,6 +5423,69 @@ async function applyRoleArnIfSet(opts) {
5423
5423
  * This is used for conditional property omission in CloudFormation templates.
5424
5424
  */
5425
5425
  const AWS_NO_VALUE = Symbol("AWS::NoValue");
5426
+ /**
5427
+ * Intrinsic-function keys the resolver knows how to handle.
5428
+ *
5429
+ * A CloudFormation intrinsic is ALWAYS a single-key object — `{ "Ref": ... }`
5430
+ * or `{ "Fn::X": ... }`. When `resolveValue` encounters a single-key object
5431
+ * whose key is `Ref` or starts with `Fn::` but is NOT in this set, it throws
5432
+ * (rather than silently passing the broken value through to the provider).
5433
+ *
5434
+ * `Fn::Transform` (CloudFormation macros) is intentionally treated as handled:
5435
+ * it is expanded server-side at the SYNTHESIS layer (see
5436
+ * `src/synthesis/macro-expander.ts`, routed via `Synthesizer`) BEFORE the
5437
+ * resolver ever runs, so by resolution time it should already be gone. Listing
5438
+ * it here keeps a stray (already-expanded) occurrence from hard-erroring.
5439
+ */
5440
+ const HANDLED_INTRINSIC_KEYS = new Set([
5441
+ "Ref",
5442
+ "Fn::GetAtt",
5443
+ "Fn::Join",
5444
+ "Fn::Sub",
5445
+ "Fn::Select",
5446
+ "Fn::Split",
5447
+ "Fn::If",
5448
+ "Fn::Equals",
5449
+ "Fn::And",
5450
+ "Fn::Or",
5451
+ "Fn::Not",
5452
+ "Fn::ImportValue",
5453
+ "Fn::GetStackOutput",
5454
+ "Fn::FindInMap",
5455
+ "Fn::Base64",
5456
+ "Fn::GetAZs",
5457
+ "Fn::Cidr",
5458
+ "Fn::Transform"
5459
+ ]);
5460
+ /**
5461
+ * Detect an unresolved / unknown CloudFormation intrinsic function.
5462
+ *
5463
+ * A CloudFormation intrinsic is ALWAYS a single-key object whose key is `Ref`
5464
+ * or starts with `Fn::`. Requiring EXACTLY ONE key avoids false positives on a
5465
+ * real resource property that happens to be literally named `Ref` or
5466
+ * `Fn::Something` (those would be multi-key objects, or sit alongside sibling
5467
+ * keys), so only a genuine lone intrinsic node is flagged.
5468
+ *
5469
+ * @returns the unknown intrinsic key (e.g. `Fn::ToJsonString`) or `undefined`
5470
+ * when the object is not an unknown single-key intrinsic.
5471
+ */
5472
+ function detectUnknownIntrinsicKey(obj) {
5473
+ const keys = Object.keys(obj);
5474
+ if (keys.length !== 1) return;
5475
+ const key = keys[0];
5476
+ if (key !== "Ref" && !key.startsWith("Fn::")) return;
5477
+ if (HANDLED_INTRINSIC_KEYS.has(key)) return;
5478
+ return key;
5479
+ }
5480
+ /**
5481
+ * Build a clear, English error message for an unsupported intrinsic, including
5482
+ * a one-click pre-filled GitHub issue link so users can request support.
5483
+ */
5484
+ function buildUnknownIntrinsicError(key) {
5485
+ const title = `Support intrinsic ${key}`;
5486
+ const issueUrl = `https://github.com/go-to-k/cdkd/issues/new?title=${encodeURIComponent(title)}&labels=intrinsic-support`;
5487
+ return /* @__PURE__ */ new Error(`Unsupported CloudFormation intrinsic function "${key}": cdkd does not support resolving it yet. Deploying this template would produce a broken value. Please request support by opening an issue: ${issueUrl}`);
5488
+ }
5426
5489
  let cachedAccountInfo = null;
5427
5490
  /**
5428
5491
  * Cache for availability zones per region
@@ -5588,6 +5651,8 @@ var IntrinsicFunctionResolver = class {
5588
5651
  if ("Fn::Base64" in obj) return await this.resolveBase64(obj["Fn::Base64"], context);
5589
5652
  if ("Fn::GetAZs" in obj) return await this.resolveGetAZs(obj["Fn::GetAZs"], context);
5590
5653
  if ("Fn::Cidr" in obj) return await this.resolveCidr(obj["Fn::Cidr"], context);
5654
+ const unknownIntrinsicKey = detectUnknownIntrinsicKey(obj);
5655
+ if (unknownIntrinsicKey !== void 0) throw buildUnknownIntrinsicError(unknownIntrinsicKey);
5591
5656
  const resolved = {};
5592
5657
  for (const [key, val] of Object.entries(obj)) {
5593
5658
  const resolvedVal = await this.resolveValue(val, context);
@@ -8530,6 +8595,32 @@ const cyan = (s) => `${codes.cyan}${s}${codes.reset}`;
8530
8595
  const gray = (s) => `${codes.gray}${s}${codes.reset}`;
8531
8596
  const bold = (s) => `${codes.bright}${s}${codes.reset}`;
8532
8597
 
8598
+ //#endregion
8599
+ //#region src/utils/resource-line.ts
8600
+ /**
8601
+ * Format the per-resource status line printed by `cdkd deploy` / `cdkd destroy`.
8602
+ *
8603
+ * All three operations share the layout `<glyph> <id> (<type>) <verb>`; callers
8604
+ * prepend their own prefix (a two-space indent, or a `[current/total] ` counter).
8605
+ *
8606
+ * Every successful op uses a green/colored check (✓), NOT a cross (✗): the op
8607
+ * succeeded, and a red ✗ reads as a failure — which is exactly what the separate
8608
+ * "✗ Failed to delete" error path prints. The op is distinguished by COLOR, not
8609
+ * glyph: green = created, yellow = updated, green-check-with-red-verb = deleted
8610
+ * (the verb stays red to keep the destructive nature of the delete visible).
8611
+ *
8612
+ * `verbOverride` replaces the default verb word (e.g. `'updated (metadata)'` for
8613
+ * a metadata-only update) while keeping the op's glyph and color.
8614
+ */
8615
+ function formatResourceLine(op, logicalId, resourceType, verbOverride) {
8616
+ const body = `${bold(logicalId)} ${gray(`(${resourceType})`)}`;
8617
+ switch (op) {
8618
+ case "created": return `${green("✓")} ${body} ${green(verbOverride ?? "created")}`;
8619
+ case "updated": return `${yellow("✓")} ${body} ${yellow(verbOverride ?? "updated")}`;
8620
+ case "deleted": return `${green("✓")} ${body} ${red(verbOverride ?? "deleted")}`;
8621
+ }
8622
+ }
8623
+
8533
8624
  //#endregion
8534
8625
  //#region src/deployment/dag-executor.ts
8535
8626
  /**
@@ -9635,7 +9726,7 @@ var DeployEngine = class {
9635
9726
  if (progress) progress.current++;
9636
9727
  const createPrefix = progress ? `[${progress.current}/${progress.total}] ` : " ";
9637
9728
  renderer.removeTask(logicalId);
9638
- this.logger.info(`${createPrefix}${green("")} ${bold(logicalId)} ${gray(`(${resourceType})`)} ${green("created")}`);
9729
+ this.logger.info(`${createPrefix}${formatResourceLine("created", logicalId, resourceType)}`);
9639
9730
  break;
9640
9731
  }
9641
9732
  case "UPDATE": {
@@ -9662,7 +9753,7 @@ var DeployEngine = class {
9662
9753
  if (progress) progress.current++;
9663
9754
  const attrPrefix = progress ? `[${progress.current}/${progress.total}] ` : " ";
9664
9755
  renderer.removeTask(logicalId);
9665
- this.logger.info(`${attrPrefix}${yellow("~")} ${bold(logicalId)} ${gray(`(${resourceType})`)} ${yellow("updated (metadata)")}`);
9756
+ this.logger.info(`${attrPrefix}${formatResourceLine("updated", logicalId, resourceType, "updated (metadata)")}`);
9666
9757
  break;
9667
9758
  }
9668
9759
  this.logger.debug(`Skipping ${logicalId}: no actual changes after intrinsic function resolution`);
@@ -9741,7 +9832,7 @@ var DeployEngine = class {
9741
9832
  if (progress) progress.current++;
9742
9833
  const updatePrefix = progress ? `[${progress.current}/${progress.total}] ` : " ";
9743
9834
  renderer.removeTask(logicalId);
9744
- this.logger.info(`${updatePrefix}${yellow("~")} ${bold(logicalId)} ${gray(`(${resourceType})`)} ${yellow("updated")}`);
9835
+ this.logger.info(`${updatePrefix}${formatResourceLine("updated", logicalId, resourceType)}`);
9745
9836
  }
9746
9837
  break;
9747
9838
  }
@@ -9767,7 +9858,7 @@ var DeployEngine = class {
9767
9858
  if (progress) progress.current++;
9768
9859
  const deletePrefix = progress ? `[${progress.current}/${progress.total}] ` : " ";
9769
9860
  renderer.removeTask(logicalId);
9770
- this.logger.info(`${deletePrefix}${red("")} ${bold(logicalId)} ${gray(`(${resourceType})`)} ${red("deleted")}`);
9861
+ this.logger.info(`${deletePrefix}${formatResourceLine("deleted", logicalId, resourceType)}`);
9771
9862
  break;
9772
9863
  }
9773
9864
  }
@@ -9973,5 +10064,5 @@ var DeployEngine = class {
9973
10064
  };
9974
10065
 
9975
10066
  //#endregion
9976
- export { ConfigError as $, AssetPublisher as A, resolveStateBucketWithDefault as B, applyRoleArnIfSet as C, LockManager as D, TemplateParser as E, getDefaultStateBucketName as F, MIGRATE_TMP_PREFIX as G, warnDeprecatedNoPrefixCliFlag as H, getLegacyStateBucketName as I, AssemblyReader as J, findLargeInlineResources as K, resolveApp as L, WorkGraph as M, buildDockerImage as N, S3StateBackend as O, Synthesizer as P, CdkdError as Q, resolveCaptureObservedState as R, IntrinsicFunctionResolver as S, DagBuilder as T, CFN_TEMPLATE_BODY_LIMIT as U, resolveStateBucketWithDefaultAndSource as V, CFN_TEMPLATE_URL_LIMIT as W, resolveBucketRegion as X, clearBucketRegionCache as Y, AssetError as Z, normalizeAwsTagsToCfn as _, isCdkdError as _t, withRetry as a, MissingCdkCliError as at, CloudControlProvider as b, cyan as c, ProvisioningError as ct, red as d, RouteDiscoveryError as dt, DependencyError as et, yellow as f, StackHasActiveImportsError as ft, matchesCdkPath as g, formatError as gt, CDK_PATH_TAG as h, SynthesisError as ht, withResourceDeadline as i, LockError as it, stringifyValue as j, shouldRetainResource as k, gray as l, ResourceTimeoutError as lt, collectInlinePolicyNamesManagedBySiblings as m, StateError as mt, DEFAULT_RESOURCE_WARN_AFTER_MS as n, LocalMigrateError as nt, IMPLICIT_DELETE_DEPENDENCIES as o, NestedStackChildDirectDestroyError as ot, IAMRoleProvider as p, StackTerminationProtectionError as pt, uploadCfnTemplate as q, DeployEngine as r, LocalStartServiceError as rt, bold as s, PartialFailureError as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, LocalInvokeBuildError as tt, green as u, ResourceUpdateNotSupportedError as ut, resolveExplicitPhysicalId as v, normalizeAwsError as vt, DiffCalculator as w, assertRegionMatch as x, ProviderRegistry as y, withErrorHandling as yt, resolveSkipPrefix as z };
9977
- //# sourceMappingURL=deploy-engine-CpPWAdiO.js.map
10067
+ export { CdkdError as $, shouldRetainResource as A, resolveSkipPrefix as B, IntrinsicFunctionResolver as C, TemplateParser as D, DagBuilder as E, Synthesizer as F, CFN_TEMPLATE_URL_LIMIT as G, resolveStateBucketWithDefaultAndSource as H, getDefaultStateBucketName as I, uploadCfnTemplate as J, MIGRATE_TMP_PREFIX as K, getLegacyStateBucketName as L, stringifyValue as M, WorkGraph as N, LockManager as O, buildDockerImage as P, AssetError as Q, resolveApp as R, assertRegionMatch as S, DiffCalculator as T, warnDeprecatedNoPrefixCliFlag as U, resolveStateBucketWithDefault as V, CFN_TEMPLATE_BODY_LIMIT as W, clearBucketRegionCache as X, AssemblyReader as Y, resolveBucketRegion as Z, matchesCdkPath as _, formatError as _t, withRetry as a, LockError as at, ProviderRegistry as b, withErrorHandling as bt, bold as c, PartialFailureError as ct, green as d, ResourceUpdateNotSupportedError as dt, ConfigError as et, red as f, RouteDiscoveryError as ft, CDK_PATH_TAG as g, SynthesisError as gt, collectInlinePolicyNamesManagedBySiblings as h, StateError as ht, withResourceDeadline as i, LocalStartServiceError as it, AssetPublisher as j, S3StateBackend as k, cyan as l, ProvisioningError as lt, IAMRoleProvider as m, StackTerminationProtectionError as mt, DEFAULT_RESOURCE_WARN_AFTER_MS as n, LocalInvokeBuildError as nt, IMPLICIT_DELETE_DEPENDENCIES as o, MissingCdkCliError as ot, yellow as p, StackHasActiveImportsError as pt, findLargeInlineResources as q, DeployEngine as r, LocalMigrateError as rt, formatResourceLine as s, NestedStackChildDirectDestroyError as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, DependencyError as tt, gray as u, ResourceTimeoutError as ut, normalizeAwsTagsToCfn as v, isCdkdError as vt, applyRoleArnIfSet as w, CloudControlProvider as x, resolveExplicitPhysicalId as y, normalizeAwsError as yt, resolveCaptureObservedState as z };
10068
+ //# sourceMappingURL=deploy-engine-9Ct1Z9oH.js.map