@go-to-k/cdkd 0.226.0 → 0.227.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
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { A as withErrorHandling, B as generateResourceNameWithFallback, C as StackHasActiveImportsError, F as getLiveRenderer, H as withStackName, I as PATTERN_B_NAME_PROPERTIES, L as PATTERN_B_RESOURCE_TYPES, M as getLogger, P as runStackBuffered, S as ResourceUpdateNotSupportedError, V as withSkipPrefix, _ as MissingCdkCliError, a as assertRegionMatch, b as ProvisioningError, f as LocalInvokeBuildError$1, i as resolveExplicitPhysicalId, k as normalizeAwsError, l as CdkdError, m as LocalStartServiceError, n as matchesCdkPath, o as disableInstanceApiTermination, p as LocalMigrateError, r as normalizeAwsTagsToCfn, s as isTerminationProtectionPropagationError, t as CDK_PATH_TAG, v as NestedStackChildDirectDestroyError, w as StackTerminationProtectionError, x as ResourceTimeoutError, y as PartialFailureError, z as generateResourceName } from "./import-helpers-wLipXr5g.js";
3
3
  import { a as setAwsClients, i as resetAwsClients, r as getAwsClients, t as AwsClients } from "./aws-clients-pjPwZz1r.js";
4
- import { $ as AssemblyReader, A as shouldRetainResource, B as getDefaultStateBucketName, C as applyRoleArnIfSet, D as LockManager, E as TemplateParser, F as formatDockerLoginError, G as resolveStateBucketWithDefault, H as resolveApp, I as getDockerCmd, J as CFN_TEMPLATE_BODY_LIMIT, K as resolveStateBucketWithDefaultAndSource, L as runDockerForeground, M as stringifyValue, N as WorkGraph, O as S3StateBackend, P as buildDockerImage, Q as uploadCfnTemplate, R as runDockerStreaming, S as IntrinsicFunctionResolver, T as DagBuilder, U as resolveCaptureObservedState, V as getLegacyStateBucketName, W as resolveSkipPrefix, X as MIGRATE_TMP_PREFIX, Y as CFN_TEMPLATE_URL_LIMIT, Z as findLargeInlineResources, _ as IAMRoleProvider, a as withRetry, b as findActionableSilentDrops, c as computeImplicitDeleteEdges, d as bold, f as cyan, g as yellow, h as red, i as withResourceDeadline, j as AssetPublisher, k as rebuildClientForBucketRegion, l as extractDeploymentEventError, m as green, n as DEFAULT_RESOURCE_WARN_AFTER_MS, o as isRetryableTransientError, p as gray, q as warnDeprecatedNoPrefixCliFlag, r as DeployEngine, s as IMPLICIT_DELETE_DEPENDENCIES, t as DEFAULT_RESOURCE_TIMEOUT_MS, tt as resolveBucketRegion, u as formatResourceLine, v as collectInlinePolicyNamesManagedBySiblings, w as DiffCalculator, x as CloudControlProvider, y as ProviderRegistry, z as Synthesizer } from "./deploy-engine-DM557Qjg.js";
4
+ import { $ as findLargeInlineResources, A as shouldRetainResource, B as getDockerImageBySourceHash, C as applyRoleArnIfSet, D as LockManager, E as TemplateParser, F as formatDockerLoginError, G as resolveCaptureObservedState, H as getDefaultStateBucketName, I as getDockerCmd, J as resolveStateBucketWithDefaultAndSource, K as resolveSkipPrefix, L as runDockerForeground, M as stringifyValue, N as WorkGraph, O as S3StateBackend, P as buildDockerImage, Q as MIGRATE_TMP_PREFIX, R as runDockerStreaming, S as IntrinsicFunctionResolver, T as DagBuilder, U as getLegacyStateBucketName, V as Synthesizer, W as resolveApp, X as CFN_TEMPLATE_BODY_LIMIT, Y as warnDeprecatedNoPrefixCliFlag, Z as CFN_TEMPLATE_URL_LIMIT, _ as IAMRoleProvider, a as withRetry, b as findActionableSilentDrops, c as computeImplicitDeleteEdges, d as bold, et as uploadCfnTemplate, f as cyan, g as yellow, h as red, i as withResourceDeadline, j as AssetPublisher, k as rebuildClientForBucketRegion, l as extractDeploymentEventError, m as green, n as DEFAULT_RESOURCE_WARN_AFTER_MS, o as isRetryableTransientError, p as gray, q as resolveStateBucketWithDefault, r as DeployEngine, rt as resolveBucketRegion, s as IMPLICIT_DELETE_DEPENDENCIES, t as DEFAULT_RESOURCE_TIMEOUT_MS, tt as AssemblyReader, u as formatResourceLine, v as collectInlinePolicyNamesManagedBySiblings, w as DiffCalculator, x as CloudControlProvider, y as ProviderRegistry, z as AssetManifestLoader } from "./deploy-engine-CBzCsd24.js";
5
5
  import { t as ASGProvider } from "./asg-provider-B_hrCxRx.js";
6
6
  import { AsyncLocalStorage } from "node:async_hooks";
7
7
  import { randomBytes, randomUUID } from "node:crypto";
@@ -32,13 +32,13 @@ import { tmpdir } from "node:os";
32
32
  import { AssociateVPCWithHostedZoneCommand, ChangeResourceRecordSetsCommand, ChangeTagsForResourceCommand, CreateHostedZoneCommand, CreateQueryLoggingConfigCommand, DeleteHostedZoneCommand, DeleteQueryLoggingConfigCommand, DisassociateVPCFromHostedZoneCommand, GetHostedZoneCommand, ListHostedZonesByNameCommand, ListHostedZonesCommand, ListQueryLoggingConfigsCommand, ListResourceRecordSetsCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$6, Route53Client, UpdateHostedZoneCommentCommand, UpdateHostedZoneFeaturesCommand } from "@aws-sdk/client-route-53";
33
33
  import { AddTagsCommand, CreateListenerCommand, CreateLoadBalancerCommand, CreateTargetGroupCommand, DeleteListenerCommand, DeleteLoadBalancerCommand, DeleteTargetGroupCommand, DescribeListenerAttributesCommand, DescribeListenersCommand, DescribeLoadBalancerAttributesCommand, DescribeLoadBalancersCommand, DescribeTagsCommand, DescribeTargetGroupsCommand, ElasticLoadBalancingV2Client, ModifyListenerAttributesCommand, ModifyListenerCommand, ModifyLoadBalancerAttributesCommand, ModifyTargetGroupCommand, RemoveTagsCommand, SetIpAddressTypeCommand, SetSecurityGroupsCommand, SetSubnetsCommand } from "@aws-sdk/client-elastic-load-balancing-v2";
34
34
  import { CreateAliasCommand, CreateKeyCommand, DeleteAliasCommand, DescribeKeyCommand, DisableKeyCommand, DisableKeyRotationCommand, EnableKeyCommand, EnableKeyRotationCommand, GetKeyPolicyCommand, GetKeyRotationStatusCommand, KMSClient, ListAliasesCommand, ListKeysCommand, ListResourceTagsCommand, NotFoundException as NotFoundException$2, PutKeyPolicyCommand, ScheduleKeyDeletionCommand, TagResourceCommand as TagResourceCommand$9, UntagResourceCommand as UntagResourceCommand$9, UpdateAliasCommand, UpdateKeyDescriptionCommand } from "@aws-sdk/client-kms";
35
+ import { join as join$1 } from "path";
35
36
  import { CreateRepositoryCommand, DeleteLifecyclePolicyCommand, DeleteRepositoryCommand, DeleteRepositoryPolicyCommand, DescribeRepositoriesCommand, ECRClient, GetAuthorizationTokenCommand, GetLifecyclePolicyCommand, LifecyclePolicyNotFoundException, ListTagsForResourceCommand as ListTagsForResourceCommand$7, PutImageScanningConfigurationCommand, PutImageTagMutabilityCommand, PutLifecyclePolicyCommand, RepositoryNotFoundException, SetRepositoryPolicyCommand, TagResourceCommand as TagResourceCommand$10 } from "@aws-sdk/client-ecr";
36
37
  import graphlib from "graphlib";
37
38
  import { AddTagsToResourceCommand as AddTagsToResourceCommand$1, CreateDBClusterCommand, CreateDBInstanceCommand, CreateDBProxyCommand, CreateDBProxyEndpointCommand, CreateDBSubnetGroupCommand, DBProxyEndpointNotFoundFault, DBProxyNotFoundFault, DBProxyTargetGroupNotFoundFault, DBProxyTargetNotFoundFault, DeleteDBClusterCommand, DeleteDBInstanceCommand, DeleteDBProxyCommand, DeleteDBProxyEndpointCommand, DeleteDBSubnetGroupCommand, DeregisterDBProxyTargetsCommand, DescribeDBClustersCommand, DescribeDBInstancesCommand, DescribeDBProxiesCommand, DescribeDBProxyEndpointsCommand, DescribeDBProxyTargetGroupsCommand, DescribeDBProxyTargetsCommand, DescribeDBSubnetGroupsCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$8, ModifyDBClusterCommand, ModifyDBInstanceCommand, ModifyDBProxyCommand, ModifyDBProxyEndpointCommand, ModifyDBProxyTargetGroupCommand, ModifyDBSubnetGroupCommand, RDSClient, RegisterDBProxyTargetsCommand, RemoveTagsFromResourceCommand as RemoveTagsFromResourceCommand$1 } from "@aws-sdk/client-rds";
38
39
  import { AddTagsToResourceCommand as AddTagsToResourceCommand$2, CreateCacheClusterCommand, CreateCacheSubnetGroupCommand, DeleteCacheClusterCommand, DeleteCacheSubnetGroupCommand, DescribeCacheClustersCommand, DescribeCacheSubnetGroupsCommand, ElastiCacheClient, ListTagsForResourceCommand as ListTagsForResourceCommand$9, ModifyCacheClusterCommand, ModifyCacheSubnetGroupCommand, RemoveTagsFromResourceCommand as RemoveTagsFromResourceCommand$2 } from "@aws-sdk/client-elasticache";
39
40
  import { Command, Option } from "commander";
40
41
  import { writeFileSync as writeFileSync$1 } from "fs";
41
- import { join as join$1 } from "path";
42
42
  import * as readline$1 from "node:readline/promises";
43
43
  import readline from "node:readline/promises";
44
44
  import * as zlib from "node:zlib";
@@ -67,7 +67,6 @@ import { A2A_CONTAINER_PORT, A2A_PATH, AGENTCORE_A2A_PROTOCOL, AGENTCORE_AGUI_PR
67
67
  import { createServer } from "node:net";
68
68
  import { promisify } from "node:util";
69
69
  import { setTimeout as setTimeout$1 } from "node:timers/promises";
70
- import { readFile } from "fs/promises";
71
70
  import { mkdtemp, rm, writeFile } from "node:fs/promises";
72
71
  import { WebSocketServer } from "ws";
73
72
 
@@ -1553,7 +1552,7 @@ const FLUSH_INTERVAL_MS = 2e3;
1553
1552
  const FLUSH_EVENT_THRESHOLD = 50;
1554
1553
  /** Build-time cdkd version, with a dev fallback for non-built contexts. */
1555
1554
  function getCdkdVersion() {
1556
- return "0.226.0";
1555
+ return "0.227.0";
1557
1556
  }
1558
1557
  /**
1559
1558
  * Generate a time-sortable unique run id, e.g.
@@ -12093,6 +12092,21 @@ var CloudWatchAlarmProvider = class {
12093
12092
  "EvaluateLowSampleCountPercentile",
12094
12093
  "ThresholdMetricId"
12095
12094
  ])]]);
12095
+ /**
12096
+ * Properties this provider deliberately does NOT wire through to the SDK,
12097
+ * with a one-line rationale per entry (consumed by the property-coverage
12098
+ * check, issue #391).
12099
+ *
12100
+ * `EvaluationCriteria` / `EvaluationInterval` appear in the CloudFormation
12101
+ * `AWS::CloudWatch::Alarm` registry schema but are absent from BOTH the AWS
12102
+ * SDK `PutMetricAlarm` input (`@aws-sdk/client-cloudwatch`) AND the
12103
+ * aws-cdk-lib `CfnAlarm` L1 — a newer CFn-schema surface ahead of SDK / CDK
12104
+ * support, so there is no wire path to forward them and no CDK app can emit
12105
+ * them. Per the #609 backfillability rule (a property absent from EITHER the
12106
+ * SDK create input OR the CDK L1 is not backfillable), they are classified
12107
+ * unhandled-by-design rather than left as a "not yet implemented" TODO.
12108
+ */
12109
+ unhandledByDesign = new Map([["AWS::CloudWatch::Alarm", new Map([["EvaluationCriteria", "Absent from both the SDK PutMetricAlarm input and the aws-cdk-lib CfnAlarm L1 (a newer CFn-schema-only property ahead of SDK/CDK support); no wire path to forward it and no CDK app can emit it."], ["EvaluationInterval", "Absent from both the SDK PutMetricAlarm input and the aws-cdk-lib CfnAlarm L1 (a newer CFn-schema-only property ahead of SDK/CDK support); no wire path to forward it and no CDK app can emit it."]])]]);
12096
12110
  constructor() {
12097
12111
  const awsClients = getAwsClients();
12098
12112
  this.cloudWatchClient = awsClients.cloudWatch;
@@ -19294,6 +19308,7 @@ var AgentCoreRuntimeProvider = class {
19294
19308
  */
19295
19309
  var StepFunctionsProvider = class {
19296
19310
  sfnClient;
19311
+ s3Client;
19297
19312
  providerRegion = process.env["AWS_REGION"];
19298
19313
  logger = getLogger().child("StepFunctionsProvider");
19299
19314
  handledProperties = new Map([["AWS::StepFunctions::StateMachine", new Set([
@@ -19305,6 +19320,7 @@ var StepFunctionsProvider = class {
19305
19320
  "Tags",
19306
19321
  "DefinitionString",
19307
19322
  "Definition",
19323
+ "DefinitionS3Location",
19308
19324
  "DefinitionSubstitutions",
19309
19325
  "EncryptionConfiguration"
19310
19326
  ])]]);
@@ -19312,6 +19328,10 @@ var StepFunctionsProvider = class {
19312
19328
  if (!this.sfnClient) this.sfnClient = new SFNClient(this.providerRegion ? { region: this.providerRegion } : {});
19313
19329
  return this.sfnClient;
19314
19330
  }
19331
+ getS3Client() {
19332
+ if (!this.s3Client) this.s3Client = new S3Client(this.providerRegion ? { region: this.providerRegion } : {});
19333
+ return this.s3Client;
19334
+ }
19315
19335
  /**
19316
19336
  * Create a Step Functions state machine
19317
19337
  */
@@ -19321,7 +19341,7 @@ var StepFunctionsProvider = class {
19321
19341
  const roleArn = properties["RoleArn"];
19322
19342
  if (!roleArn) throw new ProvisioningError(`RoleArn is required for Step Functions state machine ${logicalId}`, resourceType, logicalId);
19323
19343
  try {
19324
- const definitionString = this.buildDefinitionString(properties);
19344
+ const definitionString = await this.buildDefinitionString(properties);
19325
19345
  let tags;
19326
19346
  if (properties["Tags"]) tags = properties["Tags"].map((tag) => ({
19327
19347
  key: tag.Key,
@@ -19364,7 +19384,7 @@ var StepFunctionsProvider = class {
19364
19384
  async update(logicalId, physicalId, resourceType, properties, previousProperties) {
19365
19385
  this.logger.debug(`Updating Step Functions state machine ${logicalId}: ${physicalId}`);
19366
19386
  try {
19367
- const definitionString = this.buildDefinitionString(properties);
19387
+ const definitionString = await this.buildDefinitionString(properties);
19368
19388
  const encryptionConfiguration = mapEncryptionConfiguration(properties["EncryptionConfiguration"]);
19369
19389
  const loggingConfiguration = mapLoggingConfiguration(properties["LoggingConfiguration"]);
19370
19390
  const tracingConfiguration = mapTracingConfiguration(properties["TracingConfiguration"]);
@@ -19564,10 +19584,22 @@ var StepFunctionsProvider = class {
19564
19584
  return false;
19565
19585
  }
19566
19586
  /**
19567
- * Build definition string from CDK properties.
19568
- * Handles both DefinitionString (string) and DefinitionString (object) forms.
19587
+ * Build the state-machine definition string from CDK properties.
19588
+ *
19589
+ * Precedence (mirrors CloudFormation): an inline `DefinitionString` /
19590
+ * `Definition` wins over `DefinitionS3Location`. The inline forms are
19591
+ * returned verbatim — any `DefinitionSubstitutions` they need are already
19592
+ * folded into the template as `Fn::Sub` and resolved by cdkd's intrinsic
19593
+ * resolver before the provider sees them.
19594
+ *
19595
+ * `DefinitionS3Location` ({@link https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-stepfunctions-statemachine-s3location.html S3Location})
19596
+ * has no SDK `CreateStateMachine` field — CloudFormation reads the S3 object
19597
+ * and inlines its contents as the `definition`. cdkd does the same: fetch
19598
+ * the object body, then apply `DefinitionSubstitutions` ourselves because
19599
+ * the intrinsic resolver cannot reach into S3 content (unlike the inline
19600
+ * path, where substitutions arrive pre-resolved).
19569
19601
  */
19570
- buildDefinitionString(properties) {
19602
+ async buildDefinitionString(properties) {
19571
19603
  const definitionString = properties["DefinitionString"];
19572
19604
  const definition = properties["Definition"];
19573
19605
  if (definitionString !== void 0) {
@@ -19578,8 +19610,44 @@ var StepFunctionsProvider = class {
19578
19610
  if (typeof definition === "string") return definition;
19579
19611
  return JSON.stringify(definition);
19580
19612
  }
19613
+ const s3Location = properties["DefinitionS3Location"];
19614
+ if (s3Location?.Bucket && s3Location.Key) {
19615
+ const body = await this.fetchDefinitionFromS3(s3Location.Bucket, s3Location.Key, s3Location.Version);
19616
+ return this.applyDefinitionSubstitutions(body, properties["DefinitionSubstitutions"]);
19617
+ }
19581
19618
  return "{}";
19582
19619
  }
19620
+ /**
19621
+ * Fetch a state-machine definition (Amazon States Language JSON/YAML) from
19622
+ * S3 and return its body as a UTF-8 string. Honors an optional object
19623
+ * version for versioning-enabled buckets.
19624
+ */
19625
+ async fetchDefinitionFromS3(bucket, key, version) {
19626
+ this.logger.debug(`Fetching state-machine definition from s3://${bucket}/${key}${version ? `?versionId=${version}` : ""}`);
19627
+ const resp = await this.getS3Client().send(new GetObjectCommand({
19628
+ Bucket: bucket,
19629
+ Key: key,
19630
+ ...version && { VersionId: version }
19631
+ }));
19632
+ if (!resp.Body) throw new Error(`DefinitionS3Location object s3://${bucket}/${key} returned no body`);
19633
+ const body = await resp.Body.transformToString();
19634
+ if (body.length === 0) throw new Error(`DefinitionS3Location object s3://${bucket}/${key} returned an empty body`);
19635
+ return body;
19636
+ }
19637
+ /**
19638
+ * Apply CloudFormation `DefinitionSubstitutions` (a `{ name: value }` map) to
19639
+ * a definition body by replacing each `${name}` token with its value.
19640
+ * Returns the body unchanged when no substitutions are supplied.
19641
+ */
19642
+ applyDefinitionSubstitutions(body, substitutions) {
19643
+ if (substitutions === null || typeof substitutions !== "object" || Array.isArray(substitutions)) return body;
19644
+ let result = body;
19645
+ for (const [name, value] of Object.entries(substitutions)) {
19646
+ if (typeof value !== "string" && typeof value !== "number" && typeof value !== "boolean") continue;
19647
+ result = result.split(`\${${name}}`).join(String(value));
19648
+ }
19649
+ return result;
19650
+ }
19583
19651
  };
19584
19652
  /**
19585
19653
  * Translate a CFn-shape `EncryptionConfiguration` (PascalCase) into the SDK's
@@ -47532,133 +47600,6 @@ const STREAM_PRELUDE_SEPARATOR = Buffer.from([
47532
47600
  0
47533
47601
  ]);
47534
47602
 
47535
- //#endregion
47536
- //#region src/assets/asset-manifest-loader.ts
47537
- /**
47538
- * Asset manifest loader
47539
- *
47540
- * Loads and parses CDK asset manifests from the CDK output directory
47541
- */
47542
- var AssetManifestLoader = class {
47543
- logger = getLogger().child("AssetManifestLoader");
47544
- /**
47545
- * Load asset manifest from CDK output directory
47546
- *
47547
- * @param cdkOutputDir CDK output directory (e.g., "cdk.out")
47548
- * @param stackName Stack name
47549
- * @returns Asset manifest or null if not found
47550
- */
47551
- async loadManifest(cdkOutputDir, stackName) {
47552
- const manifestPath = join$1(cdkOutputDir, `${stackName}.assets.json`);
47553
- try {
47554
- this.logger.debug(`Loading asset manifest from: ${manifestPath}`);
47555
- const content = await readFile(manifestPath, "utf-8");
47556
- const manifest = JSON.parse(content);
47557
- this.logger.debug(`Loaded asset manifest: ${Object.keys(manifest.files).length} file assets, ${Object.keys(manifest.dockerImages).length} docker image assets`);
47558
- return manifest;
47559
- } catch (error) {
47560
- if (error.code === "ENOENT") {
47561
- this.logger.debug(`Asset manifest not found: ${manifestPath}`);
47562
- return null;
47563
- }
47564
- throw new Error(`Failed to load asset manifest from ${manifestPath}: ${error instanceof Error ? error.message : String(error)}`);
47565
- }
47566
- }
47567
- /**
47568
- * Get file assets from manifest (excludes CloudFormation templates)
47569
- *
47570
- * @param manifest Asset manifest
47571
- * @returns Map of asset hash to file asset
47572
- */
47573
- getFileAssets(manifest) {
47574
- const fileAssets = /* @__PURE__ */ new Map();
47575
- for (const [assetHash, asset] of Object.entries(manifest.files)) {
47576
- if (asset.source.path.endsWith(".json") || asset.source.path.endsWith(".template.json")) {
47577
- this.logger.debug(`Skipping CloudFormation template asset: ${asset.displayName}`);
47578
- continue;
47579
- }
47580
- fileAssets.set(assetHash, asset);
47581
- }
47582
- this.logger.debug(`Found ${fileAssets.size} file assets (excluding templates)`);
47583
- return fileAssets;
47584
- }
47585
- /**
47586
- * Get asset source path (absolute path)
47587
- *
47588
- * @param cdkOutputDir CDK output directory
47589
- * @param asset File asset
47590
- * @returns Absolute path to asset source
47591
- */
47592
- getAssetSourcePath(cdkOutputDir, asset) {
47593
- return join$1(cdkOutputDir, asset.source.path);
47594
- }
47595
- /**
47596
- * Resolve asset destination values (replace ${AWS::AccountId}, ${AWS::Region}, etc.)
47597
- *
47598
- * @param value Value with placeholders
47599
- * @param accountId AWS account ID
47600
- * @param region AWS region
47601
- * @param partition AWS partition (default: "aws")
47602
- * @returns Resolved value
47603
- */
47604
- resolveAssetDestinationValue(value, accountId, region, partition = "aws") {
47605
- return value.replace(/\$\{AWS::AccountId\}/g, accountId).replace(/\$\{AWS::Region\}/g, region).replace(/\$\{AWS::Partition\}/g, partition);
47606
- }
47607
- };
47608
- /**
47609
- * Look up the docker-image asset that backs a Lambda's `Code.ImageUri`.
47610
- *
47611
- * The CDK template synthesizes `Code.ImageUri` as a `Fn::Sub` whose body
47612
- * references the bootstrap ECR repo and ends in `:<hash>` — that hash is
47613
- * the same key used in `manifest.dockerImages[<hash>]`. cdkd extracts the
47614
- * hash by walking known image-URI shapes; on miss, when the manifest has
47615
- * exactly one Docker image, we fall back to it (single-asset heuristic) so
47616
- * locally-built non-bootstrapped images still work. This is documented as
47617
- * a v1 limitation; immutable digest pins (`@sha256:<digest>`) hit the same
47618
- * fallback path.
47619
- *
47620
- * Returns the `(hash, asset)` pair when matched, or `undefined` when both
47621
- * the regex AND the single-asset fallback miss (typically: 0 docker assets,
47622
- * or 2+ docker assets with no hash match — the caller should treat this as
47623
- * "fall through to the ECR-pull path").
47624
- *
47625
- * Exported as a free function (not a method) so the local-invoke modules
47626
- * can reuse it without depending on the `AssetManifestLoader` instance —
47627
- * the manifest itself is a plain JSON shape.
47628
- */
47629
- function getDockerImageBySourceHash(manifest, imageUri) {
47630
- const dockerImages = manifest.dockerImages ?? {};
47631
- const entries = Object.entries(dockerImages);
47632
- if (entries.length === 0) return void 0;
47633
- const hash = extractHashFromImageUri(imageUri);
47634
- if (hash !== void 0) {
47635
- const asset = dockerImages[hash];
47636
- if (asset) return {
47637
- hash,
47638
- asset
47639
- };
47640
- }
47641
- if (entries.length === 1) {
47642
- const [singleHash, singleAsset] = entries[0];
47643
- return {
47644
- hash: singleHash,
47645
- asset: singleAsset
47646
- };
47647
- }
47648
- }
47649
- /**
47650
- * Extract the source hash from a Lambda `Code.ImageUri` string. CDK's
47651
- * bootstrap layout ends every image URI in `:<hex-hash>`, and that hash
47652
- * is the same key used in the asset manifest's `dockerImages` map.
47653
- *
47654
- * Returns `undefined` for shapes we can't parse (digest pins, missing tag,
47655
- * etc.) — the caller falls back to the single-asset heuristic.
47656
- */
47657
- function extractHashFromImageUri(imageUri) {
47658
- if (imageUri.includes("@sha256:")) return void 0;
47659
- return /:([a-f0-9]{8,})$/.exec(imageUri)?.[1];
47660
- }
47661
-
47662
47603
  //#endregion
47663
47604
  //#region src/utils/single-flight.ts
47664
47605
  /**
@@ -54681,7 +54622,7 @@ function reorderArgs(argv) {
54681
54622
  async function main() {
54682
54623
  installPipeCloseHandler();
54683
54624
  const program = new Command();
54684
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.226.0");
54625
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.227.0");
54685
54626
  program.addCommand(createBootstrapCommand());
54686
54627
  program.addCommand(createSynthCommand());
54687
54628
  program.addCommand(createListCommand());