@go-to-k/cdkd 0.207.5 → 0.208.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/README.md CHANGED
@@ -59,7 +59,7 @@ Reproduce the first two with `./tests/benchmark/run-benchmark.sh all`. See [test
59
59
  - **Rollback on failure**: When a deploy errors mid-stack, cdkd rolls back the resources it just created so the stack state stays consistent (CloudFormation parity — but cdkd does this without round-tripping through CFn). Pass `cdkd deploy --no-rollback` to skip rollback and keep the partial state for Terraform-style inspection / repair. See [Rollback behavior](#rollback-behavior).
60
60
  - **`--no-wait` for async resources**: Skip the multi-minute wait on CloudFront / RDS / ElastiCache / NAT Gateway and return as soon as the create call returns (CloudFormation always blocks)
61
61
  - **VPC route DependsOn relaxation (on by default)**: Drop CDK-injected defensive `DependsOn` edges from VPC Lambdas onto private-subnet routes so `CloudFront::Distribution` and `Lambda::Url` start their ~3-min propagation in parallel with NAT Gateway stabilization (~50% faster on VPC + Lambda + CloudFront stacks). Pass `--no-aggressive-vpc-parallel` to opt out.
62
- - **Local execution** (`cdkd local invoke` / `start-api` / `run-task` / `start-service` / `invoke-agentcore`): run Lambdas, API Gateway routes, ECS tasks, long-running ECS services, and Bedrock AgentCore Runtimes from your CDK code via Docker. All AWS Lambda runtimes, container Lambdas, REST v1 / HTTP v2 / Function URL routes, Service Connect / Cloud Map, AgentCore HTTP / MCP / A2A / AGUI / WebSocket protocols. Works for both `cdkd deploy`-managed (`--from-state`) AND `cdk deploy`-managed (`--from-cfn-stack`) stacks. See [Local execution](#local-execution).
62
+ - **Local execution** (`cdkd local invoke` / `start-api` / `run-task` / `start-service` / `start-alb` / `start-cloudfront` / `invoke-agentcore`): run Lambdas, API Gateway routes, ECS tasks, long-running ECS services, CloudFront distributions, and Bedrock AgentCore Runtimes from your CDK code. All AWS Lambda runtimes, container Lambdas, REST v1 / HTTP v2 / Function URL routes, Service Connect / Cloud Map, AgentCore HTTP / MCP / A2A / AGUI / WebSocket protocols. The Docker-backed commands work for both `cdkd deploy`-managed (`--from-state`) AND `cdk deploy`-managed (`--from-cfn-stack`) stacks; `start-cloudfront` serves the viewer-request -> S3 origin -> viewer-response pipeline in-process (no Docker, no state binding). See [Local execution](#local-execution).
63
63
  - **Bidirectional CloudFormation migration**: `cdkd import --migrate-from-cloudformation` adopts existing CFn stacks (including `cdk deploy`-managed) into cdkd state without re-creating resources; `cdkd export` hands a cdkd stack back to CloudFormation when production-ready. See [Importing](#importing-existing-resources) / [Exporting](#exporting-a-stack-back-to-cloudformation).
64
64
 
65
65
  > **Note**: Resource types not covered by either SDK Providers or Cloud Control API cannot be deployed with cdkd. Deployment fails with a clear error message naming the type + a 1-click issue link.
@@ -243,12 +243,15 @@ maintain, no `cdk synth | sam ...` round-trip.
243
243
  | `cdkd local start-service <target>` | Long-running ECS Service emulator — `DesiredCount` replicas with restart-on-exit (no local load balancer in v1) |
244
244
  | `cdkd local invoke-agentcore <target>` | One-shot Bedrock AgentCore Runtime invoke (HTTP `/invocations` / MCP `/mcp` / A2A `/a2a` / AGUI / WebSocket `--ws`) |
245
245
  | `cdkd local start-alb <targets...>` | Long-running local ALB front-door (HTTP + HTTPS listeners, path / host / header / weighted / redirect / fixed-response routing, authenticate-cognito / authenticate-oidc) for ECS / Lambda backing services |
246
+ | `cdkd local start-cloudfront [target]` | Long-running local CloudFront distribution — viewer-request -> S3 origin -> viewer-response pipeline, CloudFront Functions run in-process (no Docker) |
246
247
 
247
- Requires Docker. Pass `--from-state` (cdkd-deployed) or
248
- `--from-cfn-stack` (cdk-deployed / CFn-managed) to substitute deployed
249
- physical IDs into intrinsic-valued env vars / secrets / image URIs;
250
- without either, intrinsic values are dropped with a per-key warning
251
- (matches `sam local *`). The two flags are mutually exclusive.
248
+ The Docker-backed commands above require Docker. Pass `--from-state`
249
+ (cdkd-deployed) or `--from-cfn-stack` (cdk-deployed / CFn-managed) to
250
+ substitute deployed physical IDs into intrinsic-valued env vars /
251
+ secrets / image URIs; without either, intrinsic values are dropped with
252
+ a per-key warning (matches `sam local *`). The two flags are mutually
253
+ exclusive. `start-cloudfront` is the exception: it serves entirely
254
+ in-process (no Docker) and makes no AWS call, so it takes neither flag.
252
255
 
253
256
  ### `local invoke`
254
257
 
@@ -328,6 +331,28 @@ interpreted-handler source edits go through the bind-mount fast path
328
331
  (no rebuild); Dockerfile / dependency / compiled-source edits fall
329
332
  through to a rebuild + atomic front-door pool swap.
330
333
 
334
+ ### `local start-cloudfront`
335
+
336
+ ```bash
337
+ cdkd local start-cloudfront # interactive picker
338
+ cdkd local start-cloudfront MyStack/MyDistribution # name the distribution
339
+ cdkd local start-cloudfront MyStack/MyDistribution --watch # re-synth + swap on edit
340
+ cdkd local start-cloudfront MyStack/MyDistribution --tls # real HTTPS termination
341
+ ```
342
+
343
+ Serves a CloudFront distribution's **viewer-request -> S3 origin ->
344
+ viewer-response** pipeline locally so a routing-function change is
345
+ verifiable in seconds instead of a deploy round-trip. The distribution's
346
+ `AWS::CloudFront::Function`s (URL rewrites, trailing-slash normalization,
347
+ SPA fallback, header tweaks) run in-process in a `node:vm` sandbox; the
348
+ S3 origin content is the `BucketDeployment` source asset resolved out of
349
+ the cloud assembly, served with `DefaultRootObject` and
350
+ `CustomErrorResponses`. Path patterns route across the default + ordered
351
+ cache behaviors. Pure-local: no Docker, no AWS call — `--watch` is just
352
+ re-synth + an in-memory routing-model swap. S3 origins only (custom /
353
+ Lambda@Edge origins are warn-and-skip); `--origin <id>=<dir>` points an
354
+ origin at a local directory when `BucketDeployment` resolution can't.
355
+
331
356
  See **[docs/local-emulation.md](docs/local-emulation.md)** for the
332
357
  full reference — runtimes, target resolution, every flag, integration
333
358
  and authorizer detail, route precedence, container pool, networking,
package/dist/cli.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { a as setAwsClients, i as resetAwsClients, r as getAwsClients, t as AwsClients } from "./aws-clients-DWUnLza1.js";
3
- import { $ as findLargeInlineResources, A as LockManager, At as getLiveRenderer, B as runDockerStreaming, C as CloudControlProvider, D as DiffCalculator, Dt as getLogger, E as applyRoleArnIfSet, F as WorkGraph, Ft as withSkipPrefix, G as resolveCaptureObservedState, H as getDefaultStateBucketName, I as buildDockerImage, It as withStackName, J as resolveStateBucketWithDefaultAndSource, K as resolveSkipPrefix, L as formatDockerLoginError, M as shouldRetainResource, Mt as PATTERN_B_RESOURCE_TYPES, N as AssetPublisher, Nt as generateResourceName, O as DagBuilder, P as stringifyValue, Pt as generateResourceNameWithFallback, Q as MIGRATE_TMP_PREFIX, R as getDockerCmd, S as findActionableSilentDrops, T as IntrinsicFunctionResolver, Tt as withErrorHandling, 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 CDK_PATH_TAG, _t as ResourceUpdateNotSupportedError, a as withRetry, at as CdkdError, b as resolveExplicitPhysicalId, c as formatResourceLine, ct as LocalInvokeBuildError$1, d as gray, et as uploadCfnTemplate, f as green, ft as MissingCdkCliError, g as collectInlinePolicyNamesManagedBySiblings, gt as ResourceTimeoutError, h as IAMRoleProvider, ht as ProvisioningError, i as withResourceDeadline, j as S3StateBackend, jt as PATTERN_B_NAME_PROPERTIES, k as TemplateParser, kt as runStackBuffered, l as bold, lt as LocalMigrateError, m as yellow, mt as PartialFailureError, n as DEFAULT_RESOURCE_WARN_AFTER_MS, o as isRetryableTransientError, p as red, pt as NestedStackChildDirectDestroyError, 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 cyan, ut as LocalStartServiceError, v as matchesCdkPath, vt as StackHasActiveImportsError, w as assertRegionMatch, wt as normalizeAwsError, x as ProviderRegistry, y as normalizeAwsTagsToCfn, yt as StackTerminationProtectionError, z as runDockerForeground } from "./deploy-engine-ai3rix-L.js";
3
+ import { $ as CFN_TEMPLATE_URL_LIMIT, A as DagBuilder, B as getDockerCmd, C as CloudControlProvider, D as IntrinsicFunctionResolver, Dt as withErrorHandling, E as isTerminationProtectionPropagationError, Et as normalizeAwsError, F as AssetPublisher, Ft as generateResourceName, G as getLegacyStateBucketName, H as runDockerStreaming, I as stringifyValue, It as generateResourceNameWithFallback, J as resolveSkipPrefix, K as resolveApp, L as WorkGraph, Lt as withSkipPrefix, M as LockManager, Mt as getLiveRenderer, N as S3StateBackend, Nt as PATTERN_B_NAME_PROPERTIES, O as applyRoleArnIfSet, P as shouldRetainResource, Pt as PATTERN_B_RESOURCE_TYPES, Q as CFN_TEMPLATE_BODY_LIMIT, R as buildDockerImage, Rt as withStackName, S as findActionableSilentDrops, T as disableInstanceApiTermination, U as Synthesizer, V as runDockerForeground, W as getDefaultStateBucketName, X as resolveStateBucketWithDefaultAndSource, Y as resolveStateBucketWithDefault, Z as warnDeprecatedNoPrefixCliFlag, _ as CDK_PATH_TAG, _t as ProvisioningError, a as withRetry, at as resolveBucketRegion, b as resolveExplicitPhysicalId, bt as StackHasActiveImportsError, c as formatResourceLine, d as gray, dt as LocalMigrateError, et as MIGRATE_TMP_PREFIX, f as green, ft as LocalStartServiceError, g as collectInlinePolicyNamesManagedBySiblings, gt as PartialFailureError, h as IAMRoleProvider, ht as NestedStackChildDirectDestroyError, i as withResourceDeadline, j as TemplateParser, jt as runStackBuffered, k as DiffCalculator, kt as getLogger, l as bold, m as yellow, mt as MissingCdkCliError, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nt as uploadCfnTemplate, o as isRetryableTransientError, p as red, q as resolveCaptureObservedState, r as DeployEngine, rt as AssemblyReader, s as IMPLICIT_DELETE_DEPENDENCIES, st as CdkdError, t as DEFAULT_RESOURCE_TIMEOUT_MS, tt as findLargeInlineResources, u as cyan, ut as LocalInvokeBuildError$1, v as matchesCdkPath, vt as ResourceTimeoutError, w as assertRegionMatch, x as ProviderRegistry, xt as StackTerminationProtectionError, y as normalizeAwsTagsToCfn, yt as ResourceUpdateNotSupportedError, z as formatDockerLoginError } from "./deploy-engine-DMggQBl4.js";
4
4
  import { AsyncLocalStorage } from "node:async_hooks";
5
5
  import { randomBytes, randomUUID } from "node:crypto";
6
6
  import { CopyObjectCommand, CreateBucketCommand, DeleteBucketAnalyticsConfigurationCommand, DeleteBucketCommand, DeleteBucketCorsCommand, DeleteBucketIntelligentTieringConfigurationCommand, DeleteBucketInventoryConfigurationCommand, DeleteBucketLifecycleCommand, DeleteBucketMetricsConfigurationCommand, DeleteBucketPolicyCommand, DeleteBucketReplicationCommand, DeleteBucketTaggingCommand, DeleteBucketWebsiteCommand, DeleteObjectsCommand, GetBucketAccelerateConfigurationCommand, GetBucketCorsCommand, GetBucketEncryptionCommand, GetBucketLifecycleConfigurationCommand, GetBucketLocationCommand, GetBucketLoggingCommand, GetBucketNotificationConfigurationCommand, GetBucketPolicyCommand, GetBucketReplicationCommand, GetBucketTaggingCommand, GetBucketVersioningCommand, GetBucketWebsiteCommand, GetObjectCommand, GetObjectLockConfigurationCommand, GetPublicAccessBlockCommand, HeadBucketCommand, ListBucketAnalyticsConfigurationsCommand, ListBucketIntelligentTieringConfigurationsCommand, ListBucketInventoryConfigurationsCommand, ListBucketMetricsConfigurationsCommand, ListBucketsCommand, ListDirectoryBucketsCommand, 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";
@@ -9,7 +9,7 @@ import { CreateQueueCommand, DeleteQueueCommand, GetQueueAttributesCommand, GetQ
9
9
  import { CreateTopicCommand, DeleteTopicCommand, GetSubscriptionAttributesCommand, GetTopicAttributesCommand, ListTagsForResourceCommand, ListTopicsCommand, NotFoundException, SNSClient, SetTopicAttributesCommand, SubscribeCommand, TagResourceCommand, UnsubscribeCommand, UntagResourceCommand } from "@aws-sdk/client-sns";
10
10
  import { AddPermissionCommand, CreateEventSourceMappingCommand, CreateFunctionCommand, CreateFunctionUrlConfigCommand, DeleteEventSourceMappingCommand, DeleteFunctionCommand, DeleteFunctionConcurrencyCommand, DeleteFunctionUrlConfigCommand, DeleteLayerVersionCommand, GetEventSourceMappingCommand, GetFunctionCommand, GetFunctionConcurrencyCommand, GetFunctionRecursionConfigCommand, GetFunctionUrlConfigCommand, GetLayerVersionByArnCommand, GetPolicyCommand as GetPolicyCommand$1, LambdaClient, ListFunctionsCommand, ListLayersCommand, ListTagsCommand, PublishLayerVersionCommand, PutFunctionConcurrencyCommand, PutFunctionRecursionConfigCommand, RemovePermissionCommand, ResourceNotFoundException, TagResourceCommand as TagResourceCommand$1, UntagResourceCommand as UntagResourceCommand$1, UpdateEventSourceMappingCommand, UpdateFunctionCodeCommand, UpdateFunctionConfigurationCommand, UpdateFunctionUrlConfigCommand, waitUntilFunctionUpdatedV2 } from "@aws-sdk/client-lambda";
11
11
  import { AssumeRoleCommand, GetCallerIdentityCommand, STSClient } from "@aws-sdk/client-sts";
12
- import { AssociateRouteTableCommand, AttachInternetGatewayCommand, AuthorizeSecurityGroupEgressCommand, AuthorizeSecurityGroupIngressCommand, CreateInternetGatewayCommand, CreateNatGatewayCommand, CreateNetworkAclCommand, CreateNetworkAclEntryCommand, CreateRouteCommand, CreateRouteTableCommand, CreateSecurityGroupCommand, CreateSubnetCommand, CreateTagsCommand, CreateVpcCommand, DeleteInternetGatewayCommand, DeleteNatGatewayCommand, DeleteNetworkAclCommand, DeleteNetworkAclEntryCommand, DeleteNetworkInterfaceCommand, DeleteRouteCommand, DeleteRouteTableCommand, DeleteSecurityGroupCommand, DeleteSubnetCommand, DeleteTagsCommand, DeleteVpcCommand, DescribeAvailabilityZonesCommand, DescribeInstanceAttributeCommand, DescribeInstancesCommand, DescribeInternetGatewaysCommand, DescribeNatGatewaysCommand, DescribeNetworkAclsCommand, DescribeNetworkInterfacesCommand, DescribeRouteTablesCommand, DescribeSecurityGroupsCommand, DescribeSubnetsCommand, DescribeVolumesCommand, DescribeVpcAttributeCommand, DescribeVpcsCommand, DetachInternetGatewayCommand, DisassociateRouteTableCommand, EC2Client, ModifyInstanceAttributeCommand, ModifySubnetAttributeCommand, ModifyVpcAttributeCommand, ReplaceNetworkAclAssociationCommand, RevokeSecurityGroupEgressCommand, RevokeSecurityGroupIngressCommand, RunInstancesCommand, TerminateInstancesCommand, waitUntilInstanceRunning, waitUntilInstanceTerminated, waitUntilNatGatewayAvailable, waitUntilNatGatewayDeleted } from "@aws-sdk/client-ec2";
12
+ import { AssociateRouteTableCommand, AttachInternetGatewayCommand, AuthorizeSecurityGroupEgressCommand, AuthorizeSecurityGroupIngressCommand, CreateInternetGatewayCommand, CreateNatGatewayCommand, CreateNetworkAclCommand, CreateNetworkAclEntryCommand, CreateRouteCommand, CreateRouteTableCommand, CreateSecurityGroupCommand, CreateSubnetCommand, CreateTagsCommand, CreateVpcCommand, DeleteInternetGatewayCommand, DeleteNatGatewayCommand, DeleteNetworkAclCommand, DeleteNetworkAclEntryCommand, DeleteNetworkInterfaceCommand, DeleteRouteCommand, DeleteRouteTableCommand, DeleteSecurityGroupCommand, DeleteSubnetCommand, DeleteTagsCommand, DeleteVpcCommand, DescribeAvailabilityZonesCommand, DescribeInstanceAttributeCommand, DescribeInstancesCommand, DescribeInternetGatewaysCommand, DescribeNatGatewaysCommand, DescribeNetworkAclsCommand, DescribeNetworkInterfacesCommand, DescribeRouteTablesCommand, DescribeSecurityGroupsCommand, DescribeSubnetsCommand, DescribeVolumesCommand, DescribeVpcAttributeCommand, DescribeVpcsCommand, DetachInternetGatewayCommand, DisassociateRouteTableCommand, EC2Client, ModifySubnetAttributeCommand, ModifyVpcAttributeCommand, ReplaceNetworkAclAssociationCommand, RevokeSecurityGroupEgressCommand, RevokeSecurityGroupIngressCommand, RunInstancesCommand, TerminateInstancesCommand, waitUntilInstanceRunning, waitUntilInstanceTerminated, waitUntilNatGatewayAvailable, waitUntilNatGatewayDeleted } from "@aws-sdk/client-ec2";
13
13
  import { CreateTableCommand, DeleteTableCommand, DescribeContinuousBackupsCommand, DescribeContributorInsightsCommand, DescribeKinesisStreamingDestinationCommand, DescribeTableCommand, DescribeTimeToLiveCommand, DynamoDBClient, ListTablesCommand, ListTagsOfResourceCommand, ResourceNotFoundException as ResourceNotFoundException$1, TagResourceCommand as TagResourceCommand$2, UntagResourceCommand as UntagResourceCommand$2, UpdateContinuousBackupsCommand, UpdateTableCommand, UpdateTimeToLiveCommand } from "@aws-sdk/client-dynamodb";
14
14
  import { CloudFormationClient, CreateChangeSetCommand, DeleteChangeSetCommand, DeleteStackCommand, DescribeChangeSetCommand, DescribeStackEventsCommand, DescribeStackResourcesCommand, DescribeStacksCommand, DescribeTypeCommand, ExecuteChangeSetCommand, GetTemplateCommand, UpdateStackCommand, waitUntilChangeSetCreateComplete, waitUntilStackDeleteComplete, waitUntilStackImportComplete, waitUntilStackUpdateComplete } from "@aws-sdk/client-cloudformation";
15
15
  import { APIGatewayClient, CreateAuthorizerCommand, CreateDeploymentCommand, CreateResourceCommand, CreateStageCommand, DeleteAuthorizerCommand, DeleteDeploymentCommand, DeleteMethodCommand, DeleteResourceCommand, DeleteStageCommand, GetAccountCommand, GetAuthorizerCommand, GetDeploymentCommand, GetMethodCommand, GetResourceCommand, GetStageCommand, NotFoundException as NotFoundException$1, PutIntegrationCommand, PutIntegrationResponseCommand, PutMethodCommand, PutMethodResponseCommand, TagResourceCommand as TagResourceCommand$3, UntagResourceCommand as UntagResourceCommand$3, UpdateAccountCommand, UpdateAuthorizerCommand, UpdateMethodCommand, UpdateStageCommand } from "@aws-sdk/client-api-gateway";
@@ -61,7 +61,7 @@ import { CreateVectorBucketCommand, DeleteIndexCommand, DeleteVectorBucketComman
61
61
  import { CreateNamespaceCommand, CreateTableBucketCommand, CreateTableCommand as CreateTableCommand$2, DeleteNamespaceCommand as DeleteNamespaceCommand$1, DeleteTableBucketCommand, DeleteTableCommand as DeleteTableCommand$2, GetTableBucketCommand, GetTableCommand as GetTableCommand$1, ListNamespacesCommand as ListNamespacesCommand$1, ListTableBucketsCommand, ListTablesCommand as ListTablesCommand$1, ListTagsForResourceCommand as ListTagsForResourceCommand$19, NotFoundException as NotFoundException$5, S3TablesClient, TagResourceCommand as TagResourceCommand$16, UntagResourceCommand as UntagResourceCommand$15 } from "@aws-sdk/client-s3tables";
62
62
  import { AttachLoadBalancerTargetGroupsCommand, AttachLoadBalancersCommand, AttachTrafficSourcesCommand, AutoScalingClient, CreateAutoScalingGroupCommand, CreateOrUpdateTagsCommand, DeleteAutoScalingGroupCommand, DeleteLifecycleHookCommand, DeleteNotificationConfigurationCommand, DeleteTagsCommand as DeleteTagsCommand$1, DescribeAutoScalingGroupsCommand, DescribeLifecycleHooksCommand, DescribeNotificationConfigurationsCommand, DescribeTrafficSourcesCommand, DetachLoadBalancerTargetGroupsCommand, DetachLoadBalancersCommand, DetachTrafficSourcesCommand, DisableMetricsCollectionCommand, EnableMetricsCollectionCommand, PutLifecycleHookCommand, PutNotificationConfigurationCommand, UpdateAutoScalingGroupCommand } from "@aws-sdk/client-auto-scaling";
63
63
  import { Document, Pair, Scalar, YAMLMap, YAMLSeq, parse as parse$1, stringify } from "yaml";
64
- import { createLocalStateProvider, getEmbedConfig, isCfnFlagPresent, listTargets, rejectExplicitCfnStackWithMultipleStacks, resolveCfnFallbackRegion, setEmbedConfig, substituteAgainstState, substituteAgainstStateAsync, substituteEnvVarsFromState, substituteEnvVarsFromStateAsync } from "cdk-local";
64
+ import { createLocalStartCloudFrontCommand, createLocalStateProvider, getEmbedConfig, isCfnFlagPresent, listTargets, rejectExplicitCfnStackWithMultipleStacks, resolveCfnFallbackRegion, setEmbedConfig, substituteAgainstState, substituteAgainstStateAsync, substituteEnvVarsFromState, substituteEnvVarsFromStateAsync } from "cdk-local";
65
65
  import { A2A_CONTAINER_PORT, A2A_PATH, AGENTCORE_A2A_PROTOCOL, AGENTCORE_AGUI_PROTOCOL, AGENTCORE_MCP_PROTOCOL, ConnectionRegistry, EcsTaskResolutionError, HOST_GATEWAY_MIN_VERSION, LocalInvokeBuildError, MCP_CONTAINER_PORT, MCP_PATH, a2aInvokeOnce, addAlbSpecificOptions, addCommonEcsServiceOptions, addStartServiceSpecificOptions, albStrategy, architectureToPlatform, attachAuthorizers, attachStageContext, availableApiIdentifiers, bufferToBody, buildAgentCoreCodeImage, buildCognitoJwksUrl, buildConnectEvent, buildContainerImage, buildCorsConfigByApiId, buildCorsConfigFromCloudFrontChain, buildDisconnectEvent, buildJwksUrlFromIssuer, buildMessageEvent, buildMgmtEndpointEnvUrl, buildStageMap, classifySourceChange, createAuthorizerCache, createFileWatcher, createFileWatcher as createFileWatcher$1, createJwksCache, createWatchPredicates, defaultCredentialsLoader, derivePseudoParametersFromRegion, discoverRoutes, discoverWebSocketApis, downloadAndExtractS3Bundle, filterRoutesByApiIdentifier, groupRoutesByServer, handleConnectionsRequest, invokeAgentCore, invokeAgentCoreWs, materializeLayerFromArn, mcpInvokeOnce, parseConnectionsPath, parseSelectionExpressionPath, pickAgentCoreCandidateStack, pickAgentCoreCandidateStack as pickAgentCoreCandidateStack$1, probeHostGatewaySupport, readMtlsMaterialsFromDisk, resolveAgentCoreTarget, resolveEnvVars, resolveRuntimeCodeMountPath, resolveRuntimeFileExtension, resolveRuntimeImage, resolveSingleTarget, resolveWatchConfig, runEcsServiceEmulator, signAgentCoreInvocation, startApiServer, substituteImagePlaceholders, tryResolveImageFnJoin, verifyJwtViaDiscovery, waitForAgentCorePing } from "cdk-local/internal";
66
66
  import { createServer } from "node:net";
67
67
  import { promisify } from "node:util";
@@ -13834,16 +13834,10 @@ var EC2Provider = class {
13834
13834
  }
13835
13835
  async deleteInstance(logicalId, physicalId, resourceType, context) {
13836
13836
  this.logger.debug(`Terminating EC2 Instance ${logicalId}: ${physicalId}`);
13837
- if (context?.removeProtection === true) try {
13838
- await this.ec2Client.send(new ModifyInstanceAttributeCommand({
13839
- InstanceId: physicalId,
13840
- DisableApiTermination: { Value: false }
13841
- }));
13842
- this.logger.debug(`Disabled DisableApiTermination on EC2 Instance ${logicalId} before termination`);
13843
- } catch (flipError) {
13844
- if (!this.isNotFoundError(flipError)) this.logger.debug(`Could not disable DisableApiTermination on ${physicalId}: ${flipError instanceof Error ? flipError.message : String(flipError)}`);
13845
- }
13846
- try {
13837
+ const removeProtection = context?.removeProtection === true;
13838
+ if (removeProtection) await disableInstanceApiTermination(this.ec2Client, physicalId, this.logger);
13839
+ const maxTerminateAttempts = removeProtection ? 5 : 1;
13840
+ for (let attempt = 1;; attempt++) try {
13847
13841
  await this.ec2Client.send(new TerminateInstancesCommand({ InstanceIds: [physicalId] }));
13848
13842
  this.logger.debug(`Terminate requested for EC2 Instance ${logicalId}, waiting...`);
13849
13843
  await waitUntilInstanceTerminated({
@@ -13851,14 +13845,22 @@ var EC2Provider = class {
13851
13845
  maxWaitTime: 300
13852
13846
  }, { InstanceIds: [physicalId] });
13853
13847
  this.logger.debug(`EC2 Instance ${logicalId} terminated: ${physicalId}`);
13848
+ return;
13854
13849
  } catch (error) {
13855
13850
  if (this.isNotFoundError(error)) {
13856
13851
  assertRegionMatch(await this.ec2Client.config.region(), context?.expectedRegion, resourceType, logicalId, physicalId);
13857
13852
  this.logger.debug(`EC2 Instance ${physicalId} already terminated (not found), treating as success`);
13858
13853
  return;
13859
13854
  }
13855
+ const msg = error instanceof Error ? error.message : String(error);
13856
+ if (removeProtection && isTerminationProtectionPropagationError(msg) && attempt < maxTerminateAttempts) {
13857
+ this.logger.debug(`Terminate of EC2 Instance ${logicalId} raced the DisableApiTermination flip-off (attempt ${attempt}/${maxTerminateAttempts}); re-flipping and retrying`);
13858
+ await disableInstanceApiTermination(this.ec2Client, physicalId, this.logger);
13859
+ await this.sleep(3e3 * attempt);
13860
+ continue;
13861
+ }
13860
13862
  const cause = error instanceof Error ? error : void 0;
13861
- throw new ProvisioningError(`Failed to terminate EC2 Instance ${logicalId}: ${error instanceof Error ? error.message : String(error)}`, resourceType, logicalId, physicalId, cause);
13863
+ throw new ProvisioningError(`Failed to terminate EC2 Instance ${logicalId}: ${msg}`, resourceType, logicalId, physicalId, cause);
13862
13864
  }
13863
13865
  }
13864
13866
  async getInstanceAttribute(physicalId, attributeName) {
@@ -50802,6 +50804,37 @@ function createLocalStartAlbCommand() {
50802
50804
  return addCommonEcsServiceOptions(cmd);
50803
50805
  }
50804
50806
 
50807
+ //#endregion
50808
+ //#region src/cli/commands/local-start-cloudfront.ts
50809
+ /**
50810
+ * `cdkd local start-cloudfront <distribution>` — serve a CloudFront distribution
50811
+ * locally: its S3 origin content (resolved from the BucketDeployment source in
50812
+ * the cloud assembly) plus its viewer-request / viewer-response CloudFront
50813
+ * Functions, reproducing the distribution routing so a rewrite / routing change
50814
+ * is verifiable in seconds. Inherited from cdk-local (go-to-k/cdk-local#363).
50815
+ *
50816
+ * Unlike the `start-api` / `start-alb` / `start-service` wrappers, this command
50817
+ * is a THIN pass-through to cdk-local's factory and adds NO cdkd-specific
50818
+ * options. `start-cloudfront` is pure-local: it runs no container and makes no
50819
+ * AWS call (it serves the distribution's local BucketDeployment source + runs
50820
+ * CloudFront Functions in-process), so it declares NEITHER `--from-cfn-stack`
50821
+ * NOR `--assume-role`, and there is no deployed state to bind — hence no
50822
+ * `--from-state` / `--state-bucket` / `--state-prefix` options and no
50823
+ * `cdkdExtraStateProviders` threading. The flags it exposes are `--port` /
50824
+ * `--host` / `--origin <originId>=<dir>` / `--tls` / `--tls-cert` /
50825
+ * `--tls-key` / `--watch` plus the shared common / app / context / region /
50826
+ * profile options, all owned by cdk-local.
50827
+ *
50828
+ * The active cdkd embed config is re-handed to the factory so branding stays
50829
+ * cdkd: cdk-local's factory calls `setEmbedConfig(opts.embedConfig)`, and
50830
+ * passing the current config (set once by `createLocalCommand` before the
50831
+ * subcommands are built) keeps it as a no-op re-set rather than a reset back to
50832
+ * cdk-local's `cdkl` defaults.
50833
+ */
50834
+ function createLocalStartCloudFrontCommand$1() {
50835
+ return createLocalStartCloudFrontCommand({ embedConfig: getEmbedConfig() });
50836
+ }
50837
+
50805
50838
  //#endregion
50806
50839
  //#region src/cli/commands/local-invoke.ts
50807
50840
  /**
@@ -51606,6 +51639,7 @@ function createLocalCommand() {
51606
51639
  local.addCommand(createLocalStartServiceCommand());
51607
51640
  local.addCommand(createLocalInvokeAgentCoreCommand());
51608
51641
  local.addCommand(createLocalStartAlbCommand());
51642
+ local.addCommand(createLocalStartCloudFrontCommand$1());
51609
51643
  return local;
51610
51644
  }
51611
51645
 
@@ -52676,6 +52710,31 @@ function createMigrateCommand() {
52676
52710
  return new Command("migrate").description("Adopt a plain (non-CDK) CloudFormation stack into a cdkd-managed CDK app. Generates new CDK code via upstream `cdk migrate`, builds a logical-ID mapping between the source CFn template and the synth template, writes cdkd state, and (optionally) retires the source CFn stack. AWS resources are never modified.").argument("[stack]", "Source CFn stack name. Alias for --from-cfn-stack.").addOption(new Option("--from-cfn-stack <name>", "Source CloudFormation stack name to adopt. Required (or pass positionally).")).addOption(new Option("--output-dir <dir>", "Directory to write the generated CDK app to. Defaults to <cwd>/<CfnStackName>.")).addOption(new Option("--language <choice>", "Generated code language. v1: typescript only.").choices(["typescript"]).default("typescript")).addOption(new Option("--region <region>", "AWS region. Defaults to AWS_REGION env / profile.")).addOption(new Option("--account <id>", "AWS account ID. Auto-detected via STS when omitted.")).addOption(new Option("--retire-cfn-stack", "After cdkd state is written, inject DeletionPolicy=Retain on every resource in the source CFn stack and DeleteStack. AWS resources stay; the CFn stack record is gone. Off by default.").default(false)).addOption(new Option("--filter <key=value>", "Pass-through to `cdk migrate --filter` for resource subsetting. Repeatable.").argParser((value, previous) => [...previous ?? [], value]).default([])).addOption(new Option("--skip-install", "Skip `npm install` after codegen.").default(false)).addOption(new Option("--skip-synth", "Skip `cdk synth` (does NOT write cdkd state). Mutually exclusive with --retire-cfn-stack.").default(false)).addOption(new Option("--dry-run", "Print the import plan without writing state or retiring the CFn stack. Mutually exclusive with --retire-cfn-stack.").default(false)).addOption(new Option("-y, --yes", "Auto-confirm the import + retirement prompts.").default(false)).addOption(new Option("--cdk-bin <path>", "Override the `cdk` binary path.")).addOption(new Option("--resource-mapping <file>", `Path to a JSON file of {sourceLogicalId: synthLogicalId} overrides. Same shape as the auto-written ${RESOURCE_MAPPING_FILENAME}.`)).addOption(new Option("--state-bucket <name>", "cdkd state bucket. Defaults to cdkd-state-<accountId>.")).addOption(new Option("--state-prefix <prefix>", "cdkd state prefix inside the bucket.").default("cdkd")).addOption(new Option("--profile <name>", "AWS profile name.")).addOption(new Option("--role-arn <arn>", "IAM role to assume before any AWS call.")).addOption(new Option("--verbose", "Enable debug-level logging.").default(false)).action(withErrorHandling(migrateCommandAction));
52677
52711
  }
52678
52712
 
52713
+ //#endregion
52714
+ //#region src/cli/pipe-close-handler.ts
52715
+ /**
52716
+ * Exit cleanly when a downstream consumer closes our stdout/stderr early.
52717
+ *
52718
+ * Piping a cdkd command into a reader that stops reading — `cdkd state list |
52719
+ * grep -q foo`, `... | head`, `... | less` then `q` — closes the pipe while
52720
+ * cdkd is still writing. Node then emits an unhandled `'error'` (EPIPE) on the
52721
+ * stream and the process dies with a stack trace + non-zero exit. That is
52722
+ * normal Unix behavior for the *consumer* to stop reading, so the CLI must
52723
+ * treat it as success, not a crash. (Surfaced by the `remove-protection` integ,
52724
+ * whose `cdkd state list | grep -q` assertion crashed cdkd on EPIPE and the
52725
+ * test misread the non-zero exit as a stripped-state failure.)
52726
+ *
52727
+ * Installed once before any command runs so it covers every subcommand's
52728
+ * output, including long / streamed listings. Non-EPIPE stream errors are
52729
+ * re-thrown unchanged (they are real faults, not a closed pipe).
52730
+ */
52731
+ function installPipeCloseHandler(streams = [process.stdout, process.stderr], exit = process.exit) {
52732
+ for (const stream of streams) stream.on("error", (err) => {
52733
+ if (err.code !== "EPIPE") throw err;
52734
+ exit(0);
52735
+ });
52736
+ }
52737
+
52679
52738
  //#endregion
52680
52739
  //#region src/cli/index.ts
52681
52740
  const SUBCOMMANDS = new Set([
@@ -52717,8 +52776,9 @@ function reorderArgs(argv) {
52717
52776
  * Main CLI program
52718
52777
  */
52719
52778
  async function main() {
52779
+ installPipeCloseHandler();
52720
52780
  const program = new Command();
52721
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.207.5");
52781
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.208.0");
52722
52782
  program.addCommand(createBootstrapCommand());
52723
52783
  program.addCommand(createSynthCommand());
52724
52784
  program.addCommand(createListCommand());