Skip to content

Commit 6b8d6c2

Browse files
committed
fix(codegen): awsQueryCompat error matching and error shape
1 parent 82b4537 commit 6b8d6c2

File tree

5 files changed

+243
-188
lines changed

5 files changed

+243
-188
lines changed

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

Lines changed: 28 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,28 @@ 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, Collection<OperationShape> operations) {
313+
Map<String, TreeSet<String>> aliases = new HashMap<>();
314+
ServiceShape service = context.getService();
315+
boolean awsQueryCompatible = service.hasTrait(AwsQueryCompatibleTrait.class);
316+
if (awsQueryCompatible) {
317+
for (OperationShape operation : operations) {
318+
List<ShapeId> errors = operation.getErrors();
319+
for (ShapeId error : errors) {
320+
Shape errorShape = context.getModel().expectShape(error);
321+
if (errorShape.hasTrait(AwsQueryErrorTrait.class)) {
322+
String alias = errorShape.expectTrait(AwsQueryErrorTrait.class).getCode();
323+
aliases.computeIfAbsent(error.toString(), k -> new TreeSet<>()).add(alias);
324+
}
325+
}
326+
}
327+
}
328+
return aliases;
329+
}
330+
303331
private static boolean filterProtocolTests(
304332
ServiceShape service,
305333
OperationShape operation,

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

Lines changed: 12 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,16 @@ 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, Collection<OperationShape> operations) {
38+
return AwsProtocolUtils.getErrorAliases(context, operations);
39+
}
40+
3941
@Override
4042
protected void writeSharedRequestHeaders(ProtocolGenerator.GenerationContext context) {
4143
TypeScriptWriter writer = context.getWriter();

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

Lines changed: 40 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,36 @@ 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, Collection<OperationShape> operations) {
89+
return AwsProtocolUtils.getErrorAliases(context, operations);
90+
}
91+
5992
@Override
6093
protected String getOperationPath(GenerationContext context, OperationShape operationShape) {
6194
return "/";
@@ -97,26 +130,6 @@ protected void generateDocumentBodyShapeDeserializers(GenerationContext context,
97130
);
98131
}
99132

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-
120133
@Override
121134
protected void writeRequestHeaders(GenerationContext context, OperationShape operation) {
122135
TypeScriptWriter writer = context.getWriter();
@@ -164,10 +177,6 @@ protected void serializeInputDocument(
164177
writer.write("body = JSON.stringify($L);", inputStructure.accept(getMemberSerVisitor(context, "input")));
165178
}
166179

167-
private DocumentMemberSerVisitor getMemberSerVisitor(GenerationContext context, String dataSource) {
168-
return new JsonMemberSerVisitor(context, dataSource, getDocumentTimestampFormat());
169-
}
170-
171180
@Override
172181
protected boolean writeUndefinedInputBody(GenerationContext context, OperationShape operation) {
173182
TypeScriptWriter writer = context.getWriter();
@@ -203,17 +212,16 @@ protected void deserializeOutputDocument(
203212
writer.write("contents = $L;", outputStructure.accept(getMemberDeserVisitor(context, "data")));
204213
}
205214

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

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

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

0 commit comments

Comments
 (0)