Skip to content

Commit fdb88f8

Browse files
committed
feat: support generating eventstream signing customizations
1 parent 54a24e8 commit fdb88f8

File tree

7 files changed

+182
-12
lines changed

7 files changed

+182
-12
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package software.amazon.smithy.aws.typescript.codegen;
2+
3+
import java.util.Collections;
4+
import java.util.List;
5+
import java.util.Map;
6+
import java.util.Set;
7+
import java.util.function.Consumer;
8+
9+
import software.amazon.smithy.codegen.core.SymbolProvider;
10+
import software.amazon.smithy.model.Model;
11+
import software.amazon.smithy.model.knowledge.EventStreamIndex;
12+
import software.amazon.smithy.model.knowledge.TopDownIndex;
13+
import software.amazon.smithy.model.shapes.OperationShape;
14+
import software.amazon.smithy.model.shapes.ServiceShape;
15+
import software.amazon.smithy.typescript.codegen.LanguageTarget;
16+
import software.amazon.smithy.typescript.codegen.TypeScriptDependency;
17+
import software.amazon.smithy.typescript.codegen.TypeScriptSettings;
18+
import software.amazon.smithy.typescript.codegen.TypeScriptWriter;
19+
import software.amazon.smithy.typescript.codegen.integration.RuntimeClientPlugin;
20+
import software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration;
21+
import software.amazon.smithy.utils.ListUtils;
22+
import software.amazon.smithy.utils.MapUtils;
23+
24+
public class AddEventStreamSigningDependency implements TypeScriptIntegration {
25+
@Override
26+
public List<RuntimeClientPlugin> getClientPlugins() {
27+
return ListUtils.of(
28+
RuntimeClientPlugin.builder()
29+
.withConventions(AwsDependency.MIDDLEWARE_EVENTSTREAM_SIGNING.dependency,
30+
"EventStream")
31+
.servicePredicate(AddEventStreamSigningDependency::hasEventStreamInput)
32+
.build()
33+
);
34+
}
35+
36+
@Override
37+
public void addConfigInterfaceFields(
38+
TypeScriptSettings settings,
39+
Model model,
40+
SymbolProvider symbolProvider,
41+
TypeScriptWriter writer
42+
) {
43+
if (hasEventStreamInput(model, settings.getService(model))) {
44+
writer.addImport("EventStreamSignerProvider", "__EventStreamSignerProvider",
45+
TypeScriptDependency.AWS_SDK_TYPES.packageName);
46+
writer.writeDocs("The function that provides necessary utilities for singing event stream");
47+
writer.write("eventStreamSignerProvider?: __EventStreamSignerProvider;\n");
48+
}
49+
}
50+
51+
@Override
52+
public Map<String, Consumer<TypeScriptWriter>> getRuntimeConfigWriters(
53+
TypeScriptSettings settings,
54+
Model model,
55+
SymbolProvider symbolProvider,
56+
LanguageTarget target
57+
) {
58+
ServiceShape service = settings.getService(model);
59+
if (!hasEventStreamInput(model, service)) {
60+
return Collections.emptyMap();
61+
}
62+
63+
switch (target) {
64+
case NODE:
65+
return MapUtils.of("eventStreamSignerProvider", writer -> {
66+
writer.addDependency(AwsDependency.AWS_SDK_EVENTSTREAM_SIGNER_NODE);
67+
writer.addImport("eventStreamSignerProvider", "eventStreamSignerProvider",
68+
AwsDependency.AWS_SDK_EVENTSTREAM_SIGNER_NODE.packageName);
69+
writer.write("eventStreamSignerProvider,");
70+
});
71+
case BROWSER:
72+
/**
73+
* Browser doesn't support streaming requests as of March 2020.
74+
* Here we don't supply invalidFunction. Each service client needs to support eventstream request
75+
* in browsers has to implement a customization providing its own eventStreamSignerProvider
76+
* TODO: update this when WebSocket event stream support lands
77+
*/
78+
return MapUtils.of("eventStreamSignerProvider", writer -> {
79+
writer.addDependency(TypeScriptDependency.INVALID_DEPENDENCY);
80+
writer.addImport("invalidFunction", "invalidFunction",
81+
TypeScriptDependency.INVALID_DEPENDENCY.packageName);
82+
writer.openBlock("eventStreamSignerProvider: () => ({", "}),", () -> {
83+
writer.write("sign: invalidFunction(\"event stream request is not supported in browser.\"),");
84+
});
85+
});
86+
case REACT_NATIVE:
87+
/**
88+
* ReactNative doesn't support streaming requests as of March 2020.
89+
* Here we don't supply invalidFunction. Each service client needs to support eventstream request
90+
* in RN has to implement a customization providing its own eventStreamSignerProvider
91+
*/
92+
return MapUtils.of("eventStreamSignerProvider", writer -> {
93+
writer.addDependency(TypeScriptDependency.INVALID_DEPENDENCY);
94+
writer.addImport("invalidFunction", "invalidFunction",
95+
TypeScriptDependency.INVALID_DEPENDENCY.packageName);
96+
writer.openBlock("eventStreamSignerProvider: () => ({", "}),", () -> {
97+
writer.write("sign: invalidFunction(\"event stream request is not supported in ReactNative.\"),");
98+
});
99+
});
100+
default:
101+
return Collections.emptyMap();
102+
}
103+
}
104+
105+
private static boolean hasEventStreamInput(
106+
Model model,
107+
ServiceShape service
108+
) {
109+
TopDownIndex topDownIndex = model.getKnowledge(TopDownIndex.class);
110+
Set<OperationShape> operations = topDownIndex.getContainedOperations(service);
111+
EventStreamIndex eventStreamIndex = model.getKnowledge(EventStreamIndex.class);
112+
for (OperationShape operation : operations) {
113+
if (eventStreamIndex.getInputInfo(operation).isPresent()) {
114+
return true;
115+
}
116+
}
117+
return false;
118+
}
119+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package software.amazon.smithy.aws.typescript.codegen;
2+
3+
import java.util.Collections;
4+
import java.util.Map;
5+
import java.util.function.Consumer;
6+
7+
import software.amazon.smithy.aws.traits.ServiceTrait;
8+
import software.amazon.smithy.codegen.core.SymbolProvider;
9+
import software.amazon.smithy.model.Model;
10+
import software.amazon.smithy.model.shapes.ServiceShape;
11+
import software.amazon.smithy.typescript.codegen.LanguageTarget;
12+
import software.amazon.smithy.typescript.codegen.TypeScriptDependency;
13+
import software.amazon.smithy.typescript.codegen.TypeScriptSettings;
14+
import software.amazon.smithy.typescript.codegen.TypeScriptWriter;
15+
import software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration;
16+
import software.amazon.smithy.utils.MapUtils;
17+
18+
public class AddHttp2Dependency implements TypeScriptIntegration {
19+
@Override
20+
public Map<String, Consumer<TypeScriptWriter>> getRuntimeConfigWriters(
21+
TypeScriptSettings settings,
22+
Model model,
23+
SymbolProvider symbolProvider,
24+
LanguageTarget target
25+
) {
26+
if(!isHttp2Applicable(settings.getService(model))) {
27+
return Collections.emptyMap();
28+
}
29+
switch (target) {
30+
case NODE:
31+
return MapUtils.of("requestHandler", writer -> {
32+
writer.addDependency(TypeScriptDependency.AWS_SDK_NODE_HTTP_HANDLER);
33+
writer.addImport("NodeHttp2Handler", "NodeHttp2Handler",
34+
TypeScriptDependency.AWS_SDK_NODE_HTTP_HANDLER.packageName);
35+
writer.write("requestHandler: new NodeHttp2Handler(),");
36+
});
37+
default:
38+
return Collections.emptyMap();
39+
}
40+
}
41+
42+
private static boolean isHttp2Applicable(ServiceShape service) {
43+
String serviceId = service.getTrait(ServiceTrait.class).map(ServiceTrait::getSdkId).orElse("");
44+
return serviceId.equals("Transcribe Streaming") || serviceId.equals("Kinesis");
45+
}
46+
}

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

Lines changed: 0 additions & 4 deletions
This file was deleted.

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ public enum AwsDependency implements SymbolDependencyContainer {
5555
XML_BUILDER(NORMAL_DEPENDENCY, "@aws-sdk/xml-builder", "^1.0.0-beta.1"),
5656
XML_PARSER(NORMAL_DEPENDENCY, "fast-xml-parser", "^3.16.0"),
5757
UUID_GENERATOR(NORMAL_DEPENDENCY, "uuid", "^7.0.0"),
58-
UUID_GENERATOR_TYPES(DEV_DEPENDENCY, "@types/uuid", "^7.0.0");
58+
UUID_GENERATOR_TYPES(DEV_DEPENDENCY, "@types/uuid", "^7.0.0"),
59+
MIDDLEWARE_EVENTSTREAM_SIGNING(NORMAL_DEPENDENCY, "@aws-sdk/middleware-eventstream-signing", "^1.0.0-beta.0"),
60+
AWS_SDK_EVENTSTREAM_SIGNER_NODE(NORMAL_DEPENDENCY, "@aws-sdk/eventstream-signer-node", "^1.0.0-beta.0");
5961

6062
public final String packageName;
6163
public final String version;

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import software.amazon.smithy.model.shapes.ShapeId;
2929
import software.amazon.smithy.model.shapes.StructureShape;
3030
import software.amazon.smithy.model.shapes.UnionShape;
31+
import software.amazon.smithy.model.traits.EventStreamTrait;
3132
import software.amazon.smithy.model.traits.TimestampFormatTrait.Format;
3233
import software.amazon.smithy.typescript.codegen.TypeScriptWriter;
3334
import software.amazon.smithy.typescript.codegen.integration.HttpBindingProtocolGenerator;
@@ -207,7 +208,8 @@ protected void serializeInputPayload(
207208
getInputValue(context, Location.PAYLOAD, "input." + memberName, member, target));
208209

209210
// Structure and Union payloads will serialize as XML documents via XmlNode.
210-
if (target instanceof StructureShape || target instanceof UnionShape) {
211+
if ((target instanceof StructureShape || target instanceof UnionShape)
212+
&& member.hasTrait(EventStreamTrait.class)) {
211213
// Start with the XML declaration.
212214
writer.write("body = \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?>\";");
213215

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

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import software.amazon.smithy.model.shapes.Shape;
2525
import software.amazon.smithy.model.shapes.StructureShape;
2626
import software.amazon.smithy.model.shapes.UnionShape;
27+
import software.amazon.smithy.model.traits.EventStreamTrait;
2728
import software.amazon.smithy.model.traits.JsonNameTrait;
2829
import software.amazon.smithy.model.traits.TimestampFormatTrait;
2930
import software.amazon.smithy.typescript.codegen.TypeScriptWriter;
@@ -143,12 +144,14 @@ protected void serializeInputPayload(
143144
super.serializeInputPayload(context, operation, payloadBinding);
144145

145146
TypeScriptWriter writer = context.getWriter();
146-
Shape target = context.getModel().expectShape(payloadBinding.getMember().getTarget());
147-
148-
// Default to an empty JSON body instead of an undefined body if
149-
// the target is a structure or union, and make sure any structure
150-
// or union content ends up as a JSON string.
151-
if (target instanceof StructureShape || target instanceof UnionShape) {
147+
MemberShape payloadMember = payloadBinding.getMember();
148+
Shape target = context.getModel().expectShape(payloadMember.getTarget());
149+
150+
// When payload is not event stream and the target is a structure or union, default to an
151+
// empty JSON body instead of an undefined body and make sure any structure or union
152+
// content ends up as a JSON string.
153+
if (!payloadMember.hasTrait(EventStreamTrait.class)
154+
&& (target instanceof StructureShape || target instanceof UnionShape)) {
152155
writer.openBlock("if (body === undefined) {", "}", () -> writer.write("body = {};"));
153156
writer.write("body = JSON.stringify(body);");
154157
}

codegen/smithy-aws-typescript-codegen/src/main/resources/META-INF/services/software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,5 @@ software.amazon.smithy.aws.typescript.codegen.AddMd5HashDependency
88
software.amazon.smithy.aws.typescript.codegen.AddStreamHasherDependency
99
software.amazon.smithy.aws.typescript.codegen.AddBodyChecksumGeneratorDependency
1010
software.amazon.smithy.aws.typescript.codegen.AddS3Config
11+
software.amazon.smithy.aws.typescript.codegen.AddEventStreamSigningDependency
12+
software.amazon.smithy.aws.typescript.codegen.AddHttp2Dependency

0 commit comments

Comments
 (0)