@go-to-k/cdkd 0.230.30 → 0.230.32

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 generateResourceName, C as StackHasActiveImportsError, F as getLiveRenderer, H as withSkipPrefix, I as PATTERN_B_NAME_OPTIONS, L as PATTERN_B_NAME_PROPERTIES, M as getLogger, P as runStackBuffered, R as PATTERN_B_RESOURCE_TYPES, S as ResourceUpdateNotSupportedError, U as withStackName, V as generateResourceNameWithFallback, _ 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 } from "./import-helpers-DayvBD4T.js";
3
3
  import { a as setAwsClients, i as resetAwsClients, r as getAwsClients, t as AwsClients } from "./aws-clients-pjPwZz1r.js";
4
- import { $ as resolveStateBucketWithDefaultAndSource, A as TemplateParser, B as getDockerCmd, C as findActionableSilentDrops, D as applyRoleArnIfSet, E as cfnRefValueFromPhysicalId, F as AssetPublisher, G as Synthesizer, H as runDockerStreaming, I as stringifyValue, J as getLegacyStateBucketName, K as synthesisStatusMessage, L as WorkGraph, M as S3StateBackend, N as rebuildClientForBucketRegion, O as DiffCalculator, P as shouldRetainResource, Q as resolveStateBucketWithDefault, R as buildDockerImage, S as ProviderRegistry, T as IntrinsicFunctionResolver, U as AssetManifestLoader, V as runDockerForeground, W as getDockerImageBySourceHash, X as resolveCaptureObservedState, Y as resolveApp, Z as resolveSkipPrefix, _ as green, a as withRetry, at as uploadCfnTemplate, b as IAMRoleProvider, c as computeImplicitDeleteEdges, ct as resolveBucketRegion, d as isStatefulRecreateTargetSync, et as warnDeprecatedNoPrefixCliFlag, f as renderStatefulReason, g as gray, h as cyan, i as withResourceDeadline, it as findLargeInlineResources, j as LockManager, k as DagBuilder, l as extractDeploymentEventError, m as bold, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nt as CFN_TEMPLATE_URL_LIMIT, o as isRetryableTransientError, ot as AssemblyReader, p as formatResourceLine, q as getDefaultStateBucketName, r as DeployEngine, rt as MIGRATE_TMP_PREFIX, s as IMPLICIT_DELETE_DEPENDENCIES, t as DEFAULT_RESOURCE_TIMEOUT_MS, tt as CFN_TEMPLATE_BODY_LIMIT, u as MULTI_REGION_RECREATE_BLOCKED_TYPES, v as red, w as CloudControlProvider, x as collectInlinePolicyNamesManagedBySiblings, y as yellow, z as formatDockerLoginError } from "./deploy-engine-ByCHAN3p.js";
4
+ import { $ as resolveStateBucketWithDefaultAndSource, A as TemplateParser, B as getDockerCmd, C as findActionableSilentDrops, D as applyRoleArnIfSet, E as cfnRefValueFromPhysicalId, F as AssetPublisher, G as Synthesizer, H as runDockerStreaming, I as stringifyValue, J as getLegacyStateBucketName, K as synthesisStatusMessage, L as WorkGraph, M as S3StateBackend, N as rebuildClientForBucketRegion, O as DiffCalculator, P as shouldRetainResource, Q as resolveStateBucketWithDefault, R as buildDockerImage, S as ProviderRegistry, T as IntrinsicFunctionResolver, U as AssetManifestLoader, V as runDockerForeground, W as getDockerImageBySourceHash, X as resolveCaptureObservedState, Y as resolveApp, Z as resolveSkipPrefix, _ as green, a as withRetry, at as uploadCfnTemplate, b as IAMRoleProvider, c as computeImplicitDeleteEdges, ct as resolveBucketRegion, d as isStatefulRecreateTargetSync, et as warnDeprecatedNoPrefixCliFlag, f as renderStatefulReason, g as gray, h as cyan, i as withResourceDeadline, it as findLargeInlineResources, j as LockManager, k as DagBuilder, l as extractDeploymentEventError, m as bold, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nt as CFN_TEMPLATE_URL_LIMIT, o as isRetryableTransientError, ot as AssemblyReader, p as formatResourceLine, q as getDefaultStateBucketName, r as DeployEngine, rt as MIGRATE_TMP_PREFIX, s as IMPLICIT_DELETE_DEPENDENCIES, t as DEFAULT_RESOURCE_TIMEOUT_MS, tt as CFN_TEMPLATE_BODY_LIMIT, u as MULTI_REGION_RECREATE_BLOCKED_TYPES, v as red, w as CloudControlProvider, x as collectInlinePolicyNamesManagedBySiblings, y as yellow, z as formatDockerLoginError } from "./deploy-engine-EV5BfAvn.js";
5
5
  import { t as ASGProvider } from "./asg-provider-Dgj3loIG.js";
6
6
  import { AsyncLocalStorage } from "node:async_hooks";
7
7
  import { createHash, randomBytes, randomUUID } from "node:crypto";
@@ -1446,7 +1446,7 @@ const FLUSH_INTERVAL_MS = 2e3;
1446
1446
  const FLUSH_EVENT_THRESHOLD = 50;
1447
1447
  /** Build-time cdkd version, with a dev fallback for non-built contexts. */
1448
1448
  function getCdkdVersion() {
1449
- return "0.230.30";
1449
+ return "0.230.32";
1450
1450
  }
1451
1451
  /**
1452
1452
  * Generate a time-sortable unique run id, e.g.
@@ -55650,7 +55650,7 @@ function reorderArgs(argv) {
55650
55650
  async function main() {
55651
55651
  installPipeCloseHandler();
55652
55652
  const program = new Command();
55653
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.230.30");
55653
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.230.32");
55654
55654
  program.addCommand(createBootstrapCommand());
55655
55655
  program.addCommand(createSynthCommand());
55656
55656
  program.addCommand(createListCommand());
@@ -6073,12 +6073,19 @@ const AWS_NO_VALUE = Symbol("AWS::NoValue");
6073
6073
  /**
6074
6074
  * Resource types whose CloudFormation `Ref` returns the segment AFTER the LAST
6075
6075
  * pipe in cdkd's compound Cloud Control physical id (rather than the whole
6076
- * physical id). These are Cloud-Control-provisioned types whose CC
6077
- * primaryIdentifier is compound (`<parentId>|<ref>`, or `<a>|<b>|<ref>` for
6076
+ * physical id). These are types provisioned via Cloud Control either because
6077
+ * they have no SDK provider, or because the #614 silent-drop routing sent an
6078
+ * SDK-backed type through CC (e.g. an ApiGateway Stage carrying
6079
+ * `MethodSettings`, which the SDK provider does not wire — issue #963). Their
6080
+ * CC primaryIdentifier is compound (`<parentId>|<ref>`, or `<a>|<b>|<ref>` for
6078
6081
  * triple-segment AppConfig children) while CFn's `Ref` returns only the
6079
- * trailing `<ref>` component:
6082
+ * trailing `<ref>` component. For SDK-provisioned instances of the same types
6083
+ * the stored physical id has no pipe, so the extraction is a no-op:
6080
6084
  * - AWS::ApiGateway::Model `<restApiId>|<modelName>` -> model name
6081
6085
  * - AWS::ApiGateway::RequestValidator `<restApiId>|<validatorId>` -> validator id
6086
+ * - AWS::ApiGateway::Stage `<restApiId>|<stageName>` -> stage name
6087
+ * - AWS::ApiGateway::Resource `<restApiId>|<resourceId>` -> resource id
6088
+ * - AWS::ApiGateway::Authorizer `<restApiId>|<authorizerId>` -> authorizer id
6082
6089
  * - AWS::Cognito::UserPoolClient `<userPoolId>|<clientId>` -> client id
6083
6090
  * - AWS::Cognito::UserPoolResourceServer `<userPoolId>|<identifier>` -> resource-server identifier
6084
6091
  * - AWS::Cognito::UserPoolGroup `<userPoolId>|<groupName>` -> group name
@@ -6108,12 +6115,26 @@ const AWS_NO_VALUE = Symbol("AWS::NoValue");
6108
6115
  * 3. EXCLUDE types whose `Ref` returns a synthetic / prefixed string rather
6109
6116
  * than a bare id segment — e.g. Cognito::UserPoolRiskConfigurationAttachment
6110
6117
  * / ::UserPoolUICustomizationAttachment return
6111
- * `<TypeName>-<UserPoolId>-<ClientId>`, NOT the after-pipe segment.
6112
- * 4. Pin each addition with a unit test in intrinsic-functions.test.ts.
6118
+ * `<TypeName>-<UserPoolId>-<ClientId>`, NOT the after-pipe segment;
6119
+ * ApiGateway::Method is in this category too (its documented `Ref` is a
6120
+ * CFn-generated synthetic id like `mysta-metho-01234b567890example`, not
6121
+ * reconstructible from the `<apiId>|<resourceId>|<verb>` physical id).
6122
+ * Also EXCLUDE types whose AWS-docs page documents NO `Ref` return value
6123
+ * at all (ApiGateway::DocumentationVersion) — with no contract to honor,
6124
+ * the raw physical id is the least-surprising value.
6125
+ * 4. Types whose primaryIdentifier puts the `Ref` component FIRST
6126
+ * (`[<refId>, <parentId>]` — e.g. ApiGateway::Deployment /
6127
+ * ::DocumentationPart) belong in
6128
+ * {@link REF_RETURNS_SEGMENT_BEFORE_FIRST_PIPE} instead of this Set: the
6129
+ * after-last-pipe extraction would return the PARENT id for them.
6130
+ * 5. Pin each addition with a unit test in intrinsic-functions.test.ts.
6113
6131
  */
6114
6132
  const REF_RETURNS_SEGMENT_AFTER_PIPE = new Set([
6115
6133
  "AWS::ApiGateway::Model",
6116
6134
  "AWS::ApiGateway::RequestValidator",
6135
+ "AWS::ApiGateway::Stage",
6136
+ "AWS::ApiGateway::Resource",
6137
+ "AWS::ApiGateway::Authorizer",
6117
6138
  "AWS::Cognito::UserPoolClient",
6118
6139
  "AWS::Cognito::UserPoolResourceServer",
6119
6140
  "AWS::Cognito::UserPoolGroup",
@@ -6126,6 +6147,23 @@ const REF_RETURNS_SEGMENT_AFTER_PIPE = new Set([
6126
6147
  "AWS::AppConfig::Deployment"
6127
6148
  ]);
6128
6149
  /**
6150
+ * Sibling of {@link REF_RETURNS_SEGMENT_AFTER_PIPE} for compound-id types
6151
+ * whose CC primaryIdentifier puts the `Ref` component FIRST
6152
+ * (`[<refId>, <parentId>]` — segment order REVERSED vs the after-pipe family),
6153
+ * so CFn's `Ref` value is the segment BEFORE the FIRST pipe (issue #963
6154
+ * family audit; both confirmed against the AWS-docs "Return values / Ref"
6155
+ * section):
6156
+ * - AWS::ApiGateway::Deployment `<deploymentId>|<restApiId>` -> deployment id
6157
+ * - AWS::ApiGateway::DocumentationPart `<docPartId>|<restApiId>` -> documentation part id
6158
+ *
6159
+ * Deployment matters in practice: every CDK-generated template wires the
6160
+ * Stage's `DeploymentId` as `{ Ref: <Deployment> }`, so a CC-routed
6161
+ * Deployment would otherwise hand the Stage a compound id AWS rejects. Same
6162
+ * maintenance rules as the after-pipe Set (docs-verified Ref semantics +
6163
+ * a pinning unit test per entry).
6164
+ */
6165
+ const REF_RETURNS_SEGMENT_BEFORE_FIRST_PIPE = new Set(["AWS::ApiGateway::Deployment", "AWS::ApiGateway::DocumentationPart"]);
6166
+ /**
6129
6167
  * SDK-provisioned types whose provider stores the resource ARN as the physical
6130
6168
  * id (their delete / update paths need the ARN), while CloudFormation's `Ref`
6131
6169
  * returns the CFn physical resource id — which for these types is NOT the ARN:
@@ -6142,8 +6180,8 @@ const REF_RETURNS_NAME_FROM_ARN = new Map([["AWS::Events::Rule", ":rule/"], ["AW
6142
6180
  * type and cdkd-stored physical id. Pure function shared by the deploy-time
6143
6181
  * resolver ({@link IntrinsicFunctionResolver.resolveRefValue}) and the
6144
6182
  * `cdkd orphan` rewriter's `{Ref: <orphan>}` substitution, so both derive
6145
- * identical CFn `Ref` semantics (after-pipe compound-id extraction and
6146
- * name-from-ARN extraction included).
6183
+ * identical CFn `Ref` semantics (after-pipe / before-first-pipe compound-id
6184
+ * extraction and name-from-ARN extraction included).
6147
6185
  */
6148
6186
  function cfnRefValueFromPhysicalId(resourceType, physicalId) {
6149
6187
  const nameMarker = REF_RETURNS_NAME_FROM_ARN.get(resourceType);
@@ -6160,6 +6198,10 @@ function cfnRefValueFromPhysicalId(resourceType, physicalId) {
6160
6198
  const pipeIdx = physicalId.lastIndexOf("|");
6161
6199
  if (pipeIdx >= 0) return physicalId.substring(pipeIdx + 1);
6162
6200
  }
6201
+ if (REF_RETURNS_SEGMENT_BEFORE_FIRST_PIPE.has(resourceType)) {
6202
+ const pipeIdx = physicalId.indexOf("|");
6203
+ if (pipeIdx >= 0) return physicalId.substring(0, pipeIdx);
6204
+ }
6163
6205
  return physicalId;
6164
6206
  }
6165
6207
  /**
@@ -6470,9 +6512,10 @@ var IntrinsicFunctionResolver = class {
6470
6512
  * physical id, and returning the raw physical id breaks downstream consumers.
6471
6513
  *
6472
6514
  * The {@link REF_RETURNS_SEGMENT_AFTER_PIPE} types are provisioned via Cloud
6473
- * Control (no SDK provider), whose primary identifier and thus cdkd's
6474
- * physical id is the compound `<parentId>|<ref>`, while CFn's `Ref` returns
6475
- * only the trailing `<ref>` segment:
6515
+ * Control (either they have no SDK provider, or the #614 silent-drop routing
6516
+ * sent an SDK-backed type through CC), whose primary identifier and thus
6517
+ * cdkd's physical id — is the compound `<parentId>|<ref>`, while CFn's `Ref`
6518
+ * returns only the trailing `<ref>` segment:
6476
6519
  * - `AWS::ApiGateway::Model` → Ref is the model NAME; physical id is
6477
6520
  * `<restApiId>|<modelName>`. A method wiring
6478
6521
  * `RequestModels: { "application/json": { "Ref": <Model> } }` would
@@ -6490,6 +6533,11 @@ var IntrinsicFunctionResolver = class {
6490
6533
  * In every case the `Ref` value is the segment after the pipe (the parent id
6491
6534
  * is the first identifier component).
6492
6535
  *
6536
+ * The {@link REF_RETURNS_SEGMENT_BEFORE_FIRST_PIPE} types are the mirror
6537
+ * image: their compound primaryIdentifier puts the `Ref` component FIRST
6538
+ * (`<refId>|<parentId>` — e.g. `AWS::ApiGateway::Deployment`), so the value
6539
+ * is the segment before the first pipe.
6540
+ *
6493
6541
  * The {@link REF_RETURNS_NAME_FROM_ARN} types are SDK-provisioned with the
6494
6542
  * resource ARN stored as the physical id, while CFn's `Ref` returns the
6495
6543
  * resource NAME (the CFn physical resource id) — e.g. `AWS::Events::Rule`
@@ -12870,7 +12918,7 @@ async function withRetry(operation, logicalId, opts = {}) {
12870
12918
  } catch (error) {
12871
12919
  lastError = error;
12872
12920
  const message = error instanceof Error ? error.message : String(error);
12873
- if (!isRetryableTransientError(error, message) || attempt >= maxRetries) throw error;
12921
+ if (!(opts.isRetryable ? opts.isRetryable(message, error) : isRetryableTransientError(error, message)) || attempt >= maxRetries) throw error;
12874
12922
  const delay = Math.min(initialDelayMs * Math.pow(2, attempt), maxDelayMs);
12875
12923
  opts.logger?.debug(` ⏳ Retrying ${logicalId} in ${delay / 1e3}s (attempt ${attempt + 1}/${maxRetries}) - ${message}`);
12876
12924
  for (let waited = 0; waited < delay; waited += 1e3) {
@@ -14075,8 +14123,38 @@ var DeployEngine = class {
14075
14123
  createResult = await this.withRetry(() => replaceProvider.create(logicalId, resourceType, replaceProps), logicalId, void 0, void 0, replaceProvider);
14076
14124
  } else {
14077
14125
  this.logger.info(` Creating new ${logicalId}...`);
14078
- createResult = await this.withRetry(() => replaceProvider.create(logicalId, resourceType, replaceProps), logicalId, void 0, void 0, replaceProvider);
14079
- if (updateReplacePolicy === "Retain") this.logger.info(` Retaining old ${logicalId} (${currentResource.physicalId}) - UpdateReplacePolicy: Retain`);
14126
+ let deletedOldFirst = false;
14127
+ try {
14128
+ createResult = await this.withRetry(() => replaceProvider.create(logicalId, resourceType, replaceProps), logicalId, void 0, void 0, replaceProvider);
14129
+ } catch (createError) {
14130
+ const createMsg = createError instanceof Error ? createError.message : String(createError);
14131
+ if (!(/already exists/i.test(createMsg) || createMsg.includes("AlreadyExists"))) throw createError;
14132
+ if (updateReplacePolicy === "Retain") throw new CdkdError(`${logicalId} (${resourceType}) requires replacement, but its user-supplied physical name is still held by the existing resource AND UpdateReplacePolicy: Retain pins that resource in place. Rename the resource in your CDK code — with Retain, the old resource keeps the name, so a same-name replacement can never proceed.`, "NAMED_REPLACEMENT_COLLISION");
14133
+ if (this.options.replace !== true) throw new CdkdError(`${logicalId} (${resourceType}) requires replacement, but the create-first attempt collided with the existing resource: ${createMsg}. The resource has a user-supplied physical name, so the CloudFormation-style safe replacement order (create the new resource before deleting the old) cannot reuse the occupied name — CloudFormation refuses this shape with "cannot update a stack when a custom-named resource requires replacing". Either rename the resource in your CDK code (a fresh name lets the safe create-first order proceed), or re-run with \`cdkd deploy --replace\` to delete the old resource FIRST and recreate it under the same name (the resource is briefly unavailable while it is recreated).`, "NAMED_REPLACEMENT_COLLISION");
14134
+ this.logger.info(` Create-first collided with the custom-named resource and --replace is set — deleting old ${logicalId} (${currentResource.physicalId}) first...`);
14135
+ try {
14136
+ await oldDeleteProvider.delete(logicalId, currentResource.physicalId, resourceType, currentResource.properties, { expectedRegion: this.stackRegion });
14137
+ } catch (deleteError) {
14138
+ throw new Error(`Failed to delete old resource ${logicalId} (${currentResource.physicalId}) during the --replace delete-first fallback: ${deleteError instanceof Error ? deleteError.message : String(deleteError)}`);
14139
+ }
14140
+ this.logger.info(` ${green("✓")} Old resource deleted`);
14141
+ deletedOldFirst = true;
14142
+ this.logger.info(` Re-creating ${logicalId}...`);
14143
+ try {
14144
+ createResult = await withRetry(() => this.withRetry(() => replaceProvider.create(logicalId, resourceType, replaceProps), logicalId, void 0, void 0, replaceProvider), logicalId, {
14145
+ maxRetries: 5,
14146
+ initialDelayMs: 2e3,
14147
+ maxDelayMs: 1e4,
14148
+ logger: this.logger,
14149
+ isInterrupted: () => this.interrupted,
14150
+ onInterrupted: () => new InterruptedError(this.interruptCause ?? "user"),
14151
+ isRetryable: (message) => /already exists/i.test(message) || message.includes("AlreadyExists")
14152
+ });
14153
+ } catch (recreateError) {
14154
+ throw new Error(`Failed to re-create ${logicalId} after the --replace delete-first fallback already deleted the old resource (${currentResource.physicalId}): ${recreateError instanceof Error ? recreateError.message : String(recreateError)}. Re-run the deploy to create it fresh.`);
14155
+ }
14156
+ }
14157
+ if (deletedOldFirst) {} else if (updateReplacePolicy === "Retain") this.logger.info(` Retaining old ${logicalId} (${currentResource.physicalId}) - UpdateReplacePolicy: Retain`);
14080
14158
  else {
14081
14159
  this.logger.info(` Deleting old ${logicalId} (${currentResource.physicalId})...`);
14082
14160
  try {
@@ -14400,4 +14478,4 @@ var DeployEngine = class {
14400
14478
 
14401
14479
  //#endregion
14402
14480
  export { resolveStateBucketWithDefaultAndSource as $, TemplateParser as A, getDockerCmd as B, findActionableSilentDrops as C, applyRoleArnIfSet as D, cfnRefValueFromPhysicalId as E, AssetPublisher as F, Synthesizer as G, runDockerStreaming as H, stringifyValue as I, getLegacyStateBucketName as J, synthesisStatusMessage as K, WorkGraph as L, S3StateBackend as M, rebuildClientForBucketRegion as N, DiffCalculator as O, shouldRetainResource as P, resolveStateBucketWithDefault as Q, buildDockerImage as R, ProviderRegistry as S, IntrinsicFunctionResolver as T, AssetManifestLoader as U, runDockerForeground as V, getDockerImageBySourceHash as W, resolveCaptureObservedState as X, resolveApp as Y, resolveSkipPrefix as Z, green as _, withRetry as a, uploadCfnTemplate as at, IAMRoleProvider as b, computeImplicitDeleteEdges as c, resolveBucketRegion as ct, isStatefulRecreateTargetSync as d, warnDeprecatedNoPrefixCliFlag as et, renderStatefulReason as f, gray as g, cyan as h, withResourceDeadline as i, findLargeInlineResources as it, LockManager as j, DagBuilder as k, extractDeploymentEventError as l, bold as m, DEFAULT_RESOURCE_WARN_AFTER_MS as n, CFN_TEMPLATE_URL_LIMIT as nt, isRetryableTransientError as o, AssemblyReader as ot, formatResourceLine as p, getDefaultStateBucketName as q, DeployEngine as r, MIGRATE_TMP_PREFIX as rt, IMPLICIT_DELETE_DEPENDENCIES as s, clearBucketRegionCache as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, CFN_TEMPLATE_BODY_LIMIT as tt, MULTI_REGION_RECREATE_BLOCKED_TYPES as u, red as v, CloudControlProvider as w, collectInlinePolicyNamesManagedBySiblings as x, yellow as y, formatDockerLoginError as z };
14403
- //# sourceMappingURL=deploy-engine-ByCHAN3p.js.map
14481
+ //# sourceMappingURL=deploy-engine-EV5BfAvn.js.map