@go-to-k/cdkd 0.53.0 → 0.54.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
@@ -22622,11 +22622,13 @@ import {
22622
22622
  DeleteStageCommand,
22623
22623
  GetStageCommand,
22624
22624
  PutMethodCommand,
22625
+ UpdateMethodCommand,
22625
22626
  DeleteMethodCommand,
22626
22627
  GetMethodCommand,
22627
22628
  PutIntegrationCommand,
22628
22629
  PutMethodResponseCommand,
22629
22630
  CreateAuthorizerCommand,
22631
+ UpdateAuthorizerCommand,
22630
22632
  DeleteAuthorizerCommand,
22631
22633
  GetAuthorizerCommand,
22632
22634
  TagResourceCommand as TagResourceCommand10,
@@ -22713,7 +22715,13 @@ var ApiGatewayProvider = class _ApiGatewayProvider {
22713
22715
  case "AWS::ApiGateway::Account":
22714
22716
  return this.updateAccount(logicalId, physicalId, resourceType, properties);
22715
22717
  case "AWS::ApiGateway::Authorizer":
22716
- return this.updateAuthorizer(logicalId, physicalId, resourceType);
22718
+ return this.updateAuthorizer(
22719
+ logicalId,
22720
+ physicalId,
22721
+ resourceType,
22722
+ properties,
22723
+ previousProperties
22724
+ );
22717
22725
  case "AWS::ApiGateway::Resource":
22718
22726
  return this.updateResource(
22719
22727
  logicalId,
@@ -22733,7 +22741,13 @@ var ApiGatewayProvider = class _ApiGatewayProvider {
22733
22741
  previousProperties
22734
22742
  );
22735
22743
  case "AWS::ApiGateway::Method":
22736
- return this.updateMethod(logicalId, physicalId);
22744
+ return this.updateMethod(
22745
+ logicalId,
22746
+ physicalId,
22747
+ resourceType,
22748
+ properties,
22749
+ previousProperties
22750
+ );
22737
22751
  default:
22738
22752
  throw new ProvisioningError(
22739
22753
  `Unsupported resource type: ${resourceType}`,
@@ -22963,22 +22977,94 @@ var ApiGatewayProvider = class _ApiGatewayProvider {
22963
22977
  }
22964
22978
  }
22965
22979
  /**
22966
- * Update an API Gateway Authorizer.
22980
+ * Update an API Gateway Authorizer via `UpdateAuthorizerCommand` (RFC 6902
22981
+ * JSON Patch operations).
22982
+ *
22983
+ * Mutable fields (per AWS API Gateway PATCH operations docs):
22984
+ * `/name`, `/authType`, `/authorizerUri`, `/authorizerCredentials`,
22985
+ * `/identitySource`, `/identityValidationExpression`,
22986
+ * `/authorizerResultTtlInSeconds`, `/providerARNs`.
22967
22987
  *
22968
- * AWS exposes `UpdateAuthorizer` (PATCH) but cdkd does not yet plumb the
22969
- * patch-operations builder through. Authorizers are recreated by the
22970
- * deploy engine's immutable-property replacement path. `cdkd drift
22971
- * --revert` surfaces a clear "use --replace or re-deploy" message
22972
- * instead of silently no-op'ing the revert.
22988
+ * `Type` and `RestApiId` are immutable (the deploy engine's replacement
22989
+ * path handles those changes via DELETE + CREATE before this method is
22990
+ * called).
22991
+ *
22992
+ * The `gate on !== undefined` pattern (NOT truthy) is load-bearing for
22993
+ * `cdkd drift --revert`: an empty placeholder coming from
22994
+ * `readCurrentStateAuthorizer` (e.g. `IdentitySource: ''` on a Cognito
22995
+ * authorizer) MUST reach AWS as `replace /<field> ''` so a console-side
22996
+ * change away from "" is actually cleared on revert. A truthy gate would
22997
+ * silently drop the empty placeholder and the next drift run would
22998
+ * re-detect the same divergence forever.
22973
22999
  */
22974
- updateAuthorizer(logicalId, _physicalId, _resourceType) {
22975
- return Promise.reject(
22976
- new ResourceUpdateNotSupportedError(
22977
- "AWS::ApiGateway::Authorizer",
23000
+ async updateAuthorizer(logicalId, physicalId, resourceType, properties, previousProperties) {
23001
+ this.logger.debug(`Updating API Gateway Authorizer ${logicalId}: ${physicalId}`);
23002
+ const restApiId = properties["RestApiId"];
23003
+ if (!restApiId) {
23004
+ throw new ProvisioningError(
23005
+ `RestApiId is required to update API Gateway Authorizer ${logicalId}`,
23006
+ resourceType,
22978
23007
  logicalId,
22979
- "API Gateway Authorizer updates are not yet implemented in cdkd; re-deploy with cdkd deploy --replace, or destroy + redeploy the stack"
22980
- )
22981
- );
23008
+ physicalId
23009
+ );
23010
+ }
23011
+ const patchOperations = [];
23012
+ const primitiveFields = [
23013
+ { key: "Name", path: "/name" },
23014
+ { key: "AuthType", path: "/authType" },
23015
+ { key: "AuthorizerUri", path: "/authorizerUri" },
23016
+ { key: "AuthorizerCredentials", path: "/authorizerCredentials" },
23017
+ { key: "IdentitySource", path: "/identitySource" },
23018
+ { key: "IdentityValidationExpression", path: "/identityValidationExpression" },
23019
+ { key: "AuthorizerResultTtlInSeconds", path: "/authorizerResultTtlInSeconds" }
23020
+ ];
23021
+ for (const { key, path } of primitiveFields) {
23022
+ const newVal = properties[key];
23023
+ const prevVal = previousProperties[key];
23024
+ if (newVal !== prevVal) {
23025
+ patchOperations.push({
23026
+ op: "replace",
23027
+ path,
23028
+ value: newVal !== void 0 ? String(newVal) : ""
23029
+ });
23030
+ }
23031
+ }
23032
+ const newArns = properties["ProviderARNs"];
23033
+ const prevArns = previousProperties["ProviderARNs"];
23034
+ const arnsChanged = (newArns?.length ?? 0) !== (prevArns?.length ?? 0) || (newArns ?? []).some((a, i) => a !== prevArns?.[i]);
23035
+ if (arnsChanged) {
23036
+ patchOperations.push({
23037
+ op: "replace",
23038
+ path: "/providerARNs",
23039
+ value: (newArns ?? []).join(",")
23040
+ });
23041
+ }
23042
+ if (patchOperations.length === 0) {
23043
+ this.logger.debug(`No changes detected for API Gateway Authorizer ${logicalId}`);
23044
+ return { physicalId, wasReplaced: false };
23045
+ }
23046
+ try {
23047
+ await this.apiGatewayClient.send(
23048
+ new UpdateAuthorizerCommand({
23049
+ restApiId,
23050
+ authorizerId: physicalId,
23051
+ patchOperations
23052
+ })
23053
+ );
23054
+ this.logger.debug(
23055
+ `Successfully updated API Gateway Authorizer ${logicalId} (${patchOperations.length} patch ops)`
23056
+ );
23057
+ return { physicalId, wasReplaced: false };
23058
+ } catch (error) {
23059
+ const cause = error instanceof Error ? error : void 0;
23060
+ throw new ProvisioningError(
23061
+ `Failed to update API Gateway Authorizer ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
23062
+ resourceType,
23063
+ logicalId,
23064
+ physicalId,
23065
+ cause
23066
+ );
23067
+ }
22982
23068
  }
22983
23069
  /**
22984
23070
  * Delete an API Gateway Authorizer
@@ -23524,22 +23610,106 @@ var ApiGatewayProvider = class _ApiGatewayProvider {
23524
23610
  }
23525
23611
  }
23526
23612
  /**
23527
- * Update an API Gateway Method.
23613
+ * Update an API Gateway Method via `UpdateMethodCommand` (RFC 6902 JSON
23614
+ * Patch operations).
23615
+ *
23616
+ * Mutable top-level fields:
23617
+ * `/authorizationType`, `/authorizerId`, `/apiKeyRequired`,
23618
+ * `/operationName`, `/requestValidatorId`.
23619
+ *
23620
+ * Map fields (`RequestParameters`, `RequestModels`) emit per-key
23621
+ * `add` / `remove` / `replace` ops with paths like
23622
+ * `/requestParameters/method.request.querystring.foo`
23623
+ * `/requestModels/application~1json` (slashes escaped per RFC 6901).
23528
23624
  *
23529
- * AWS exposes `UpdateMethod` (PATCH) but cdkd does not yet plumb the
23530
- * patch-operations builder through. Methods are recreated by the deploy
23531
- * engine's immutable-property replacement path. `cdkd drift --revert`
23532
- * surfaces a clear "use --replace or re-deploy" message instead of
23533
- * silently no-op'ing the revert.
23625
+ * `HttpMethod`, `ResourceId`, `RestApiId` are immutable (replacement
23626
+ * layer handles them via DELETE + CREATE).
23627
+ *
23628
+ * `Integration` and `MethodResponses` are NOT touched here they are
23629
+ * separate API Gateway sub-resources (`UpdateIntegration` /
23630
+ * `UpdateMethodResponse`) and the cdkd `create()` path treats them as
23631
+ * inline children of the Method. Round-tripping their structurally-
23632
+ * incomplete `{}` placeholders through `updateMethod` would require
23633
+ * destroying / recreating the integration; that work is deferred and
23634
+ * the empty placeholders are blocked from reaching AWS by the
23635
+ * `!== undefined` gate plus the explicit "ignore Integration /
23636
+ * MethodResponses" comment in this method body.
23637
+ *
23638
+ * The `gate on !== undefined` pattern (NOT truthy) is load-bearing for
23639
+ * `cdkd drift --revert`: `ApiKeyRequired: false` and empty-string
23640
+ * placeholders must reach AWS as a real `replace` op so a console-
23641
+ * side toggle is actually cleared on revert.
23534
23642
  */
23535
- updateMethod(logicalId, _physicalId) {
23536
- return Promise.reject(
23537
- new ResourceUpdateNotSupportedError(
23538
- "AWS::ApiGateway::Method",
23643
+ async updateMethod(logicalId, physicalId, resourceType, properties, previousProperties) {
23644
+ this.logger.debug(`Updating API Gateway Method ${logicalId}: ${physicalId}`);
23645
+ const parts = physicalId.split("|");
23646
+ if (parts.length !== 3) {
23647
+ throw new ProvisioningError(
23648
+ `Invalid physicalId format for API Gateway Method ${logicalId}: expected "restApiId|resourceId|httpMethod", got "${physicalId}"`,
23649
+ resourceType,
23539
23650
  logicalId,
23540
- "API Gateway Method updates are not yet implemented in cdkd; re-deploy with cdkd deploy --replace, or destroy + redeploy the stack"
23541
- )
23651
+ physicalId
23652
+ );
23653
+ }
23654
+ const [restApiId, resourceId, httpMethod] = parts;
23655
+ const patchOperations = [];
23656
+ const primitiveFields = [
23657
+ { key: "AuthorizationType", path: "/authorizationType" },
23658
+ { key: "AuthorizerId", path: "/authorizerId" },
23659
+ { key: "ApiKeyRequired", path: "/apiKeyRequired" },
23660
+ { key: "OperationName", path: "/operationName" },
23661
+ { key: "RequestValidatorId", path: "/requestValidatorId" }
23662
+ ];
23663
+ for (const { key, path } of primitiveFields) {
23664
+ const newVal = properties[key];
23665
+ const prevVal = previousProperties[key];
23666
+ if (newVal !== prevVal) {
23667
+ patchOperations.push({
23668
+ op: "replace",
23669
+ path,
23670
+ value: newVal !== void 0 ? String(newVal) : ""
23671
+ });
23672
+ }
23673
+ }
23674
+ appendMapPatchOps(
23675
+ patchOperations,
23676
+ "/requestParameters",
23677
+ properties["RequestParameters"] ?? {},
23678
+ previousProperties["RequestParameters"] ?? {}
23679
+ );
23680
+ appendMapPatchOps(
23681
+ patchOperations,
23682
+ "/requestModels",
23683
+ properties["RequestModels"] ?? {},
23684
+ previousProperties["RequestModels"] ?? {}
23542
23685
  );
23686
+ if (patchOperations.length === 0) {
23687
+ this.logger.debug(`No changes detected for API Gateway Method ${logicalId}`);
23688
+ return { physicalId, wasReplaced: false };
23689
+ }
23690
+ try {
23691
+ await this.apiGatewayClient.send(
23692
+ new UpdateMethodCommand({
23693
+ restApiId,
23694
+ resourceId,
23695
+ httpMethod,
23696
+ patchOperations
23697
+ })
23698
+ );
23699
+ this.logger.debug(
23700
+ `Successfully updated API Gateway Method ${logicalId} (${patchOperations.length} patch ops)`
23701
+ );
23702
+ return { physicalId, wasReplaced: false };
23703
+ } catch (error) {
23704
+ const cause = error instanceof Error ? error : void 0;
23705
+ throw new ProvisioningError(
23706
+ `Failed to update API Gateway Method ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
23707
+ resourceType,
23708
+ logicalId,
23709
+ physicalId,
23710
+ cause
23711
+ );
23712
+ }
23543
23713
  }
23544
23714
  /**
23545
23715
  * Delete an API Gateway Method
@@ -23866,6 +24036,23 @@ var ApiGatewayProvider = class _ApiGatewayProvider {
23866
24036
  return null;
23867
24037
  }
23868
24038
  };
24039
+ function appendMapPatchOps(ops, basePath, next, prev) {
24040
+ const escape = (k) => k.replace(/~/g, "~0").replace(/\//g, "~1");
24041
+ for (const [key, val] of Object.entries(next)) {
24042
+ const path = `${basePath}/${escape(key)}`;
24043
+ const stringValue = String(val);
24044
+ if (!(key in prev)) {
24045
+ ops.push({ op: "add", path, value: stringValue });
24046
+ } else if (String(prev[key]) !== stringValue) {
24047
+ ops.push({ op: "replace", path, value: stringValue });
24048
+ }
24049
+ }
24050
+ for (const key of Object.keys(prev)) {
24051
+ if (!(key in next)) {
24052
+ ops.push({ op: "remove", path: `${basePath}/${escape(key)}` });
24053
+ }
24054
+ }
24055
+ }
23869
24056
 
23870
24057
  // src/provisioning/providers/apigatewayv2-provider.ts
23871
24058
  import {
@@ -45602,7 +45789,7 @@ function reorderArgs(argv) {
45602
45789
  }
45603
45790
  async function main() {
45604
45791
  const program = new Command14();
45605
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.53.0");
45792
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.54.0");
45606
45793
  program.addCommand(createBootstrapCommand());
45607
45794
  program.addCommand(createSynthCommand());
45608
45795
  program.addCommand(createListCommand());