Skip to content

Commit c4fe747

Browse files
authored
fix(codegen): awsQueryCompat error matching and error shape (#7133)
* fix(codegen): awsQueryCompat error matching and error shape * chore: line lengths
1 parent 82b4537 commit c4fe747

File tree

7 files changed

+278
-192
lines changed

7 files changed

+278
-192
lines changed

clients/client-sqs/src/protocols/Aws_json1_0.ts

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -883,33 +883,40 @@ const de_CommandError = async (output: __HttpResponse, context: __SerdeContext):
883883
throw await de_OverLimitRes(parsedOutput, context);
884884
case "QueueDoesNotExist":
885885
case "com.amazonaws.sqs#QueueDoesNotExist":
886+
case "AWS.SimpleQueueService.NonExistentQueue":
886887
throw await de_QueueDoesNotExistRes(parsedOutput, context);
887888
case "RequestThrottled":
888889
case "com.amazonaws.sqs#RequestThrottled":
889890
throw await de_RequestThrottledRes(parsedOutput, context);
890891
case "UnsupportedOperation":
891892
case "com.amazonaws.sqs#UnsupportedOperation":
893+
case "AWS.SimpleQueueService.UnsupportedOperation":
892894
throw await de_UnsupportedOperationRes(parsedOutput, context);
893895
case "ResourceNotFoundException":
894896
case "com.amazonaws.sqs#ResourceNotFoundException":
895897
throw await de_ResourceNotFoundExceptionRes(parsedOutput, context);
896898
case "MessageNotInflight":
897899
case "com.amazonaws.sqs#MessageNotInflight":
900+
case "AWS.SimpleQueueService.MessageNotInflight":
898901
throw await de_MessageNotInflightRes(parsedOutput, context);
899902
case "ReceiptHandleIsInvalid":
900903
case "com.amazonaws.sqs#ReceiptHandleIsInvalid":
901904
throw await de_ReceiptHandleIsInvalidRes(parsedOutput, context);
902905
case "BatchEntryIdsNotDistinct":
903906
case "com.amazonaws.sqs#BatchEntryIdsNotDistinct":
907+
case "AWS.SimpleQueueService.BatchEntryIdsNotDistinct":
904908
throw await de_BatchEntryIdsNotDistinctRes(parsedOutput, context);
905909
case "EmptyBatchRequest":
906910
case "com.amazonaws.sqs#EmptyBatchRequest":
911+
case "AWS.SimpleQueueService.EmptyBatchRequest":
907912
throw await de_EmptyBatchRequestRes(parsedOutput, context);
908913
case "InvalidBatchEntryId":
909914
case "com.amazonaws.sqs#InvalidBatchEntryId":
915+
case "AWS.SimpleQueueService.InvalidBatchEntryId":
910916
throw await de_InvalidBatchEntryIdRes(parsedOutput, context);
911917
case "TooManyEntriesInBatchRequest":
912918
case "com.amazonaws.sqs#TooManyEntriesInBatchRequest":
919+
case "AWS.SimpleQueueService.TooManyEntriesInBatchRequest":
913920
throw await de_TooManyEntriesInBatchRequestRes(parsedOutput, context);
914921
case "InvalidAttributeName":
915922
case "com.amazonaws.sqs#InvalidAttributeName":
@@ -919,42 +926,53 @@ const de_CommandError = async (output: __HttpResponse, context: __SerdeContext):
919926
throw await de_InvalidAttributeValueRes(parsedOutput, context);
920927
case "QueueDeletedRecently":
921928
case "com.amazonaws.sqs#QueueDeletedRecently":
929+
case "AWS.SimpleQueueService.QueueDeletedRecently":
922930
throw await de_QueueDeletedRecentlyRes(parsedOutput, context);
923931
case "QueueNameExists":
924932
case "com.amazonaws.sqs#QueueNameExists":
933+
case "QueueAlreadyExists":
925934
throw await de_QueueNameExistsRes(parsedOutput, context);
926935
case "InvalidIdFormat":
927936
case "com.amazonaws.sqs#InvalidIdFormat":
928937
throw await de_InvalidIdFormatRes(parsedOutput, context);
929938
case "PurgeQueueInProgress":
930939
case "com.amazonaws.sqs#PurgeQueueInProgress":
940+
case "AWS.SimpleQueueService.PurgeQueueInProgress":
931941
throw await de_PurgeQueueInProgressRes(parsedOutput, context);
932942
case "KmsAccessDenied":
933943
case "com.amazonaws.sqs#KmsAccessDenied":
944+
case "KMS.AccessDeniedException":
934945
throw await de_KmsAccessDeniedRes(parsedOutput, context);
935946
case "KmsDisabled":
936947
case "com.amazonaws.sqs#KmsDisabled":
948+
case "KMS.DisabledException":
937949
throw await de_KmsDisabledRes(parsedOutput, context);
938950
case "KmsInvalidKeyUsage":
939951
case "com.amazonaws.sqs#KmsInvalidKeyUsage":
952+
case "KMS.InvalidKeyUsageException":
940953
throw await de_KmsInvalidKeyUsageRes(parsedOutput, context);
941954
case "KmsInvalidState":
942955
case "com.amazonaws.sqs#KmsInvalidState":
956+
case "KMS.InvalidStateException":
943957
throw await de_KmsInvalidStateRes(parsedOutput, context);
944958
case "KmsNotFound":
945959
case "com.amazonaws.sqs#KmsNotFound":
960+
case "KMS.NotFoundException":
946961
throw await de_KmsNotFoundRes(parsedOutput, context);
947962
case "KmsOptInRequired":
948963
case "com.amazonaws.sqs#KmsOptInRequired":
964+
case "KMS.OptInRequired":
949965
throw await de_KmsOptInRequiredRes(parsedOutput, context);
950966
case "KmsThrottled":
951967
case "com.amazonaws.sqs#KmsThrottled":
968+
case "KMS.ThrottlingException":
952969
throw await de_KmsThrottledRes(parsedOutput, context);
953970
case "InvalidMessageContents":
954971
case "com.amazonaws.sqs#InvalidMessageContents":
955972
throw await de_InvalidMessageContentsRes(parsedOutput, context);
956973
case "BatchRequestTooLong":
957974
case "com.amazonaws.sqs#BatchRequestTooLong":
975+
case "AWS.SimpleQueueService.BatchRequestTooLong":
958976
throw await de_BatchRequestTooLongRes(parsedOutput, context);
959977
default:
960978
const parsedBody = parsedOutput.body;
@@ -2094,8 +2112,17 @@ function sharedHeaders(operation: string): __HeaderBag {
20942112
const populateBodyWithQueryCompatibility = (parsedOutput: any, headers: __HeaderBag) => {
20952113
const queryErrorHeader = headers["x-amzn-query-error"];
20962114
if (parsedOutput.body !== undefined && queryErrorHeader != null) {
2097-
const codeAndType = queryErrorHeader.split(";");
2098-
parsedOutput.body.Code = codeAndType[0];
2099-
parsedOutput.body.Type = codeAndType[1];
2115+
const [Code, Type] = queryErrorHeader.split(";");
2116+
const entries = Object.entries(parsedOutput.body);
2117+
const Error = {
2118+
Type,
2119+
Code,
2120+
} as any;
2121+
Object.assign(parsedOutput.body, Error);
2122+
for (const [k, v] of entries) {
2123+
Error[k] = v;
2124+
}
2125+
delete Error.__type;
2126+
parsedOutput.body.Error = Error;
21002127
}
21012128
};

codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AwsProtocolUtils.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,24 @@
1818
import static software.amazon.smithy.model.knowledge.HttpBinding.Location.DOCUMENT;
1919

2020
import java.util.Arrays;
21+
import java.util.Collection;
22+
import java.util.HashMap;
2123
import java.util.List;
24+
import java.util.Map;
2225
import java.util.Optional;
2326
import java.util.Set;
2427
import java.util.TreeSet;
2528
import software.amazon.smithy.aws.traits.auth.UnsignedPayloadTrait;
29+
import software.amazon.smithy.aws.traits.protocols.AwsQueryCompatibleTrait;
30+
import software.amazon.smithy.aws.traits.protocols.AwsQueryErrorTrait;
2631
import software.amazon.smithy.model.knowledge.HttpBindingIndex;
2732
import software.amazon.smithy.model.knowledge.NeighborProviderIndex;
2833
import software.amazon.smithy.model.neighbor.Walker;
2934
import software.amazon.smithy.model.shapes.MemberShape;
3035
import software.amazon.smithy.model.shapes.OperationShape;
3136
import software.amazon.smithy.model.shapes.ServiceShape;
3237
import software.amazon.smithy.model.shapes.Shape;
38+
import software.amazon.smithy.model.shapes.ShapeId;
3339
import software.amazon.smithy.model.shapes.ShapeVisitor;
3440
import software.amazon.smithy.model.traits.IdempotencyTokenTrait;
3541
import software.amazon.smithy.model.traits.TimestampFormatTrait;
@@ -300,6 +306,29 @@ static void generateProtocolTests(ProtocolGenerator generator, GenerationContext
300306
AwsProtocolUtils::filterMalformedRequestTests).run();
301307
}
302308

309+
/**
310+
* @return map of error full shape id to alias strings having AwsQueryCompat error code.
311+
*/
312+
static Map<String, TreeSet<String>> getErrorAliases(GenerationContext context,
313+
Collection<OperationShape> operations) {
314+
Map<String, TreeSet<String>> aliases = new HashMap<>();
315+
ServiceShape service = context.getService();
316+
boolean awsQueryCompatible = service.hasTrait(AwsQueryCompatibleTrait.class);
317+
if (awsQueryCompatible) {
318+
for (OperationShape operation : operations) {
319+
List<ShapeId> errors = operation.getErrors();
320+
for (ShapeId error : errors) {
321+
Shape errorShape = context.getModel().expectShape(error);
322+
if (errorShape.hasTrait(AwsQueryErrorTrait.class)) {
323+
String alias = errorShape.expectTrait(AwsQueryErrorTrait.class).getCode();
324+
aliases.computeIfAbsent(error.toString(), k -> new TreeSet<>()).add(alias);
325+
}
326+
}
327+
}
328+
}
329+
return aliases;
330+
}
331+
303332
private static boolean filterProtocolTests(
304333
ServiceShape service,
305334
OperationShape operation,

codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AwsSmithyRpcV2Cbor.java

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,17 @@
55

66
package software.amazon.smithy.aws.typescript.codegen;
77

8+
import java.util.Collection;
9+
import java.util.Map;
10+
import java.util.TreeSet;
811
import software.amazon.smithy.aws.traits.protocols.AwsQueryCompatibleTrait;
12+
import software.amazon.smithy.model.shapes.OperationShape;
913
import software.amazon.smithy.typescript.codegen.SmithyCoreSubmodules;
1014
import software.amazon.smithy.typescript.codegen.TypeScriptDependency;
1115
import software.amazon.smithy.typescript.codegen.TypeScriptWriter;
1216
import software.amazon.smithy.typescript.codegen.integration.ProtocolGenerator;
1317
import software.amazon.smithy.typescript.codegen.protocols.cbor.SmithyRpcV2Cbor;
18+
import software.amazon.smithy.utils.IoUtils;
1419

1520
/**
1621
* Extension of the Smithy RPCv2 CBOR protocol generator, adding
@@ -23,19 +28,17 @@ public void generateSharedComponents(GenerationContext context) {
2328
if (context.getService().hasTrait(AwsQueryCompatibleTrait.class)) {
2429
TypeScriptWriter writer = context.getWriter();
2530
writer.addImport("HeaderBag", "__HeaderBag", TypeScriptDependency.SMITHY_TYPES);
26-
writer.write("""
27-
const populateBodyWithQueryCompatibility = (parsedOutput: any, headers: __HeaderBag) => {
28-
const queryErrorHeader = headers["x-amzn-query-error"];
29-
if (parsedOutput.body !== undefined && queryErrorHeader != null) {
30-
const codeAndType = queryErrorHeader.split(";");
31-
parsedOutput.body.Code = codeAndType[0];
32-
parsedOutput.body.Type = codeAndType[1];
33-
}
34-
};
35-
""");
31+
writer.write(IoUtils.readUtf8Resource(
32+
AwsProtocolUtils.class, "populate-body-with-query-compatibility-code-stub.ts"));
3633
}
3734
}
3835

36+
@Override
37+
public Map<String, TreeSet<String>> getErrorAliases(GenerationContext context,
38+
Collection<OperationShape> operations) {
39+
return AwsProtocolUtils.getErrorAliases(context, operations);
40+
}
41+
3942
@Override
4043
protected void writeSharedRequestHeaders(ProtocolGenerator.GenerationContext context) {
4144
TypeScriptWriter writer = context.getWriter();

codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/JsonRpcProtocolGenerator.java

Lines changed: 41 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@
1515

1616
package software.amazon.smithy.aws.typescript.codegen;
1717

18+
import java.util.Collection;
19+
import java.util.Map;
1820
import java.util.Set;
21+
import java.util.TreeSet;
1922
import software.amazon.smithy.aws.traits.ServiceTrait;
2023
import software.amazon.smithy.aws.traits.protocols.AwsQueryCompatibleTrait;
2124
import software.amazon.smithy.aws.typescript.codegen.protocols.DeserializerElisionDenyList;
@@ -56,6 +59,37 @@ abstract class JsonRpcProtocolGenerator extends HttpRpcProtocolGenerator {
5659
super(true);
5760
}
5861

62+
@Override
63+
public void generateSharedComponents(GenerationContext context) {
64+
super.generateSharedComponents(context);
65+
AwsProtocolUtils.generateJsonParseBody(context);
66+
AwsProtocolUtils.generateJsonParseErrorBody(context);
67+
AwsProtocolUtils.addItempotencyAutofillImport(context);
68+
69+
TypeScriptWriter writer = context.getWriter();
70+
writer.addUseImports(getApplicationProtocol().getResponseType());
71+
writer.addDependency(AwsDependency.AWS_SDK_CORE);
72+
writer.addImport("loadRestJsonErrorCode", null, AwsDependency.AWS_SDK_CORE);
73+
74+
if (context.getService().hasTrait(AwsQueryCompatibleTrait.class)) {
75+
AwsProtocolUtils.generateJsonParseBodyWithQueryHeader(context);
76+
}
77+
writer.write(
78+
context.getStringStore().flushVariableDeclarationCode()
79+
);
80+
}
81+
82+
@Override
83+
public void generateProtocolTests(GenerationContext context) {
84+
AwsProtocolUtils.generateProtocolTests(this, context);
85+
}
86+
87+
@Override
88+
public Map<String, TreeSet<String>> getErrorAliases(GenerationContext context,
89+
Collection<OperationShape> operations) {
90+
return AwsProtocolUtils.getErrorAliases(context, operations);
91+
}
92+
5993
@Override
6094
protected String getOperationPath(GenerationContext context, OperationShape operationShape) {
6195
return "/";
@@ -97,26 +131,6 @@ protected void generateDocumentBodyShapeDeserializers(GenerationContext context,
97131
);
98132
}
99133

100-
@Override
101-
public void generateSharedComponents(GenerationContext context) {
102-
super.generateSharedComponents(context);
103-
AwsProtocolUtils.generateJsonParseBody(context);
104-
AwsProtocolUtils.generateJsonParseErrorBody(context);
105-
AwsProtocolUtils.addItempotencyAutofillImport(context);
106-
107-
TypeScriptWriter writer = context.getWriter();
108-
writer.addUseImports(getApplicationProtocol().getResponseType());
109-
writer.addDependency(AwsDependency.AWS_SDK_CORE);
110-
writer.addImport("loadRestJsonErrorCode", null, AwsDependency.AWS_SDK_CORE);
111-
112-
if (context.getService().hasTrait(AwsQueryCompatibleTrait.class)) {
113-
AwsProtocolUtils.generateJsonParseBodyWithQueryHeader(context);
114-
}
115-
writer.write(
116-
context.getStringStore().flushVariableDeclarationCode()
117-
);
118-
}
119-
120134
@Override
121135
protected void writeRequestHeaders(GenerationContext context, OperationShape operation) {
122136
TypeScriptWriter writer = context.getWriter();
@@ -164,10 +178,6 @@ protected void serializeInputDocument(
164178
writer.write("body = JSON.stringify($L);", inputStructure.accept(getMemberSerVisitor(context, "input")));
165179
}
166180

167-
private DocumentMemberSerVisitor getMemberSerVisitor(GenerationContext context, String dataSource) {
168-
return new JsonMemberSerVisitor(context, dataSource, getDocumentTimestampFormat());
169-
}
170-
171181
@Override
172182
protected boolean writeUndefinedInputBody(GenerationContext context, OperationShape operation) {
173183
TypeScriptWriter writer = context.getWriter();
@@ -203,17 +213,16 @@ protected void deserializeOutputDocument(
203213
writer.write("contents = $L;", outputStructure.accept(getMemberDeserVisitor(context, "data")));
204214
}
205215

206-
private ShapeVisitor<String> getMemberDeserVisitor(GenerationContext context, String dataSource) {
207-
return new JsonMemberDeserVisitor(context, dataSource, getDocumentTimestampFormat());
216+
@Override
217+
protected boolean enableSerdeElision() {
218+
return true;
208219
}
209220

210-
@Override
211-
public void generateProtocolTests(GenerationContext context) {
212-
AwsProtocolUtils.generateProtocolTests(this, context);
221+
private DocumentMemberSerVisitor getMemberSerVisitor(GenerationContext context, String dataSource) {
222+
return new JsonMemberSerVisitor(context, dataSource, getDocumentTimestampFormat());
213223
}
214224

215-
@Override
216-
protected boolean enableSerdeElision() {
217-
return true;
225+
private ShapeVisitor<String> getMemberDeserVisitor(GenerationContext context, String dataSource) {
226+
return new JsonMemberDeserVisitor(context, dataSource, getDocumentTimestampFormat());
218227
}
219228
}

0 commit comments

Comments
 (0)