Skip to content

Commit f94a73f

Browse files
adamthom-amznsrchase
authored andcommitted
Get rid of needing to cast OperationSerializers.
Instead of using a Record, just do it Java-style with a factory function that can spit out the correctly-typed OperationSerializer.
1 parent 9b994bf commit f94a73f

File tree

5 files changed

+42
-52
lines changed

5 files changed

+42
-52
lines changed

smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/CodegenVisitor.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,6 @@ public Void serviceShape(ServiceShape shape) {
328328
context.withSymbolProvider(serverSymbolProvider);
329329
protocolGenerator.generateRequestDeserializers(serverContext);
330330
protocolGenerator.generateResponseSerializers(serverContext);
331-
protocolGenerator.generateMux(serverContext);
332331
protocolGenerator.generateHandlerFactory(serverContext);
333332
}
334333
protocolGenerator.generateSharedComponents(context);

smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/ServerGenerator.java

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ static void generateOperationsType(SymbolProvider symbolProvider,
3232
Set<OperationShape> operations,
3333
TypeScriptWriter writer) {
3434
Symbol serviceSymbol = symbolProvider.toSymbol(serviceShape);
35-
writer.writeInline("type $L = ", serviceSymbol.expectProperty("operations", Symbol.class).getName());
35+
writer.writeInline("export type $L = ", serviceSymbol.expectProperty("operations", Symbol.class).getName());
3636
for (Iterator<OperationShape> iter = operations.iterator(); iter.hasNext();) {
3737
writer.writeInline("$S", iter.next().getId().getName());
3838
if (iter.hasNext()) {
@@ -65,8 +65,8 @@ static void generateServiceHandler(SymbolProvider symbolProvider,
6565
writer.openBlock("export class $L implements ServiceHandler {", "}", handlerSymbol.getName(), () -> {
6666
writer.write("private service: $T;", serviceSymbol);
6767
writer.write("private mux: Mux<$S, $T>;", serviceShape.getId().getName(), operationsType);
68-
writer.write("private serializers: Record<$1T, OperationSerializer<$2L, $1T>>;",
69-
operationsType, serviceSymbol.getName());
68+
writer.write("private serializerFactory: <T extends $T>(operation: T) => OperationSerializer<$T, T>;",
69+
operationsType, serviceSymbol);
7070
writer.openBlock("private serdeContextBase = {", "};", () -> {
7171
writer.write("base64Encoder: toBase64,");
7272
writer.write("base64Decoder: fromBase64,");
@@ -76,23 +76,24 @@ static void generateServiceHandler(SymbolProvider symbolProvider,
7676
writer.write("requestHandler: new NodeHttpHandler(),");
7777
writer.write("disableHostPrefix: true");
7878
});
79-
writer.write("/**");
80-
writer.write(" * Construct a $T handler.", serviceSymbol);
81-
writer.write(" * @param service The {@link $T} implementation that supplies", serviceSymbol);
82-
writer.write(" * the business logic for $T", serviceSymbol);
83-
writer.write(" * @param mux The {@link Mux} that determines which service and operation are being");
84-
writer.write(" * invoked by a given {@link HttpRequest}");
85-
writer.write(" * @param serializers An {@link OperationSerializer} for each operation in");
86-
writer.write(" * $T that handles deserialization of requests", serviceSymbol);
87-
writer.write(" * and serialization of responses");
88-
writer.write(" */");
79+
writer.writeDocs(() -> {
80+
writer.write("Construct a $T handler.", serviceSymbol);
81+
writer.write("@param service The {@link $1T} implementation that supplies the business logic for $1T",
82+
serviceSymbol);
83+
writer.writeInline("@param mux The {@link Mux} that determines which service and operation are being ");
84+
writer.write("invoked by a given {@link HttpRequest}");
85+
writer.writeInline("@param serializerFactory A factory for an {@link OperationSerializer} for each ");
86+
writer.write("operation in $T that ", serviceSymbol);
87+
writer.writeInline(" ")
88+
.write("handles deserialization of requests and serialization of responses");
89+
});
8990
writer.openBlock("constructor(service: $1T, "
9091
+ "mux: Mux<$3S, $2T>, "
91-
+ "serializers: Record<$2T, OperationSerializer<$1T, $2T>>) {", "}",
92+
+ "serializerFactory: <T extends $2T>(op: T) => OperationSerializer<$1T, T>) {", "}",
9293
serviceSymbol, operationsType, serviceShape.getId().getName(), () -> {
9394
writer.write("this.service = service;");
9495
writer.write("this.mux = mux;");
95-
writer.write("this.serializers = serializers;");
96+
writer.write("this.serializerFactory = serializerFactory;");
9697
});
9798
writer.openBlock("async handle(request: HttpRequest): Promise<HttpResponse> {", "}", () -> {
9899
writer.write("const target = this.mux.match(request);");
@@ -115,8 +116,7 @@ private static void generateHandlerCase(TypeScriptWriter writer,
115116
Symbol operationSymbol) {
116117
String opName = operationShape.getId().getName();
117118
writer.openBlock("case $S : {", "}", opName, () -> {
118-
writer.write("let serializer = this.serializers.$2L as OperationSerializer<$1L, $2S>;",
119-
serviceSymbol.getName(), opName);
119+
writer.write("let serializer = this.serializerFactory($S);", opName);
120120
writer.openBlock("let input = await serializer.deserialize(request, {", "});", () -> {
121121
writer.write("endpoint: () => Promise.resolve(request), ...this.serdeContextBase");
122122
});

smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/HttpBindingProtocolGenerator.java

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.util.Set;
2727
import java.util.TreeMap;
2828
import java.util.TreeSet;
29+
import java.util.function.Consumer;
2930
import java.util.logging.Logger;
3031
import java.util.stream.Collectors;
3132
import software.amazon.smithy.codegen.core.CodegenException;
@@ -71,7 +72,6 @@
7172
import software.amazon.smithy.typescript.codegen.TypeScriptWriter;
7273
import software.amazon.smithy.utils.ListUtils;
7374
import software.amazon.smithy.utils.OptionalUtils;
74-
import software.amazon.smithy.utils.StringUtils;
7575

7676
/**
7777
* Abstract implementation useful for all protocols that use HTTP bindings.
@@ -216,23 +216,19 @@ public void generateResponseSerializers(GenerationContext context) {
216216
}
217217
}
218218

219-
@Override
220-
public void generateMux(GenerationContext context) {
219+
private void generateMux(GenerationContext context) {
221220
TopDownIndex topDownIndex = TopDownIndex.of(context.getModel());
222221
TypeScriptWriter writer = context.getWriter();
223-
Set<OperationShape> containedOperations = new TreeSet<>(
224-
topDownIndex.getContainedOperations(context.getService()));
225222

226223
writer.addImport("httpbinding", null, "@aws-smithy/server-common");
227224

228225
Symbol serviceSymbol = context.getSymbolProvider().toSymbol(context.getService());
229226

230-
writer.openBlock("const $L = new httpbinding.HttpBindingMux<$S, keyof $T>([", "]);",
231-
getMuxName(serviceSymbol),
227+
writer.openBlock("const mux = new httpbinding.HttpBindingMux<$S, keyof $T>([", "]);",
232228
context.getService().getId().getName(),
233229
serviceSymbol,
234230
() -> {
235-
for (OperationShape operation : containedOperations) {
231+
for (OperationShape operation : topDownIndex.getContainedOperations(context.getService())) {
236232
OptionalUtils.ifPresentOrElse(
237233
operation.getTrait(HttpTrait.class),
238234
httpTrait -> generateUriSpec(context, operation, httpTrait),
@@ -301,28 +297,36 @@ public void generateHandlerFactory(GenerationContext context) {
301297

302298
Symbol serviceSymbol = symbolProvider.toSymbol(context.getService());
303299
Symbol handlerSymbol = serviceSymbol.expectProperty("handler", Symbol.class);
300+
Symbol operationsSymbol = serviceSymbol.expectProperty("operations", Symbol.class);
304301

305302
writer.addImport("ServiceHandler", null, "@aws-smithy/server-common");
303+
writer.addImport("OperationSerializer", null, "@aws-smithy/server-common");
306304

307-
writer.openBlock("export const get$1L = (service: $2T): ServiceHandler => {", "}",
305+
writer.openBlock("export const get$L = (service: $T): ServiceHandler => {", "}",
308306
handlerSymbol.getName(), serviceSymbol, () -> {
309-
writer.openBlock("return new $T(service, $L, {", "});", handlerSymbol, getMuxName(serviceSymbol), () -> {
310-
operations.stream()
311-
.filter(o -> o.getTrait(HttpTrait.class).isPresent())
312-
.sorted()
313-
.forEach(operation -> {
314-
Symbol symbol = symbolProvider.toSymbol(operation);
315-
writer.openBlock("$L: {", "},", operation.getId().getName(), () -> {
316-
writer.write("serialize: $LResponse,", ProtocolGenerator.getGenericSerFunctionName(symbol));
317-
writer.write("deserialize: $LRequest,", ProtocolGenerator.getGenericDeserFunctionName(symbol));
318-
});
307+
generateMux(context);
308+
writer.openBlock("const serFn: (op: $1T) => OperationSerializer<$2T, $1T> = (op) => {", "};",
309+
operationsSymbol, serviceSymbol, () -> {
310+
writer.openBlock("switch (op) {", "}", () -> {
311+
operations.stream()
312+
.filter(o -> o.getTrait(HttpTrait.class).isPresent())
313+
.forEach(writeOperationCase(writer, symbolProvider));
319314
});
320315
});
316+
writer.write("return new $T(service, mux, serFn);", handlerSymbol);
321317
});
322318
}
323319

324-
private String getMuxName(Symbol serviceSymbol) {
325-
return StringUtils.uncapitalize(serviceSymbol.getName()) + "Mux";
320+
private Consumer<OperationShape> writeOperationCase(TypeScriptWriter writer, SymbolProvider symbolProvider) {
321+
return operation -> {
322+
Symbol symbol = symbolProvider.toSymbol(operation);
323+
writer.openBlock("case $S: {", "}", operation.getId().getName(), () -> {
324+
writer.openBlock("return {", "};", () -> {
325+
writer.write("serialize: $LResponse,", ProtocolGenerator.getGenericSerFunctionName(symbol));
326+
writer.write("deserialize: $LRequest,", ProtocolGenerator.getGenericDeserFunctionName(symbol));
327+
});
328+
});
329+
};
326330
}
327331

328332
@Override

smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/HttpRpcProtocolGenerator.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,6 @@ public void generateResponseSerializers(GenerationContext context) {
153153
LOGGER.warning("Response serialization is not currently supported for RPC protocols.");
154154
}
155155

156-
@Override
157-
public void generateMux(GenerationContext context) {
158-
LOGGER.warning("Router generation is not currently supported for RPC protocols.");
159-
}
160-
161156
@Override
162157
public void generateHandlerFactory(GenerationContext context) {
163158
LOGGER.warning("Handler factory generation is not currently supported for RPC protocols.");

smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/ProtocolGenerator.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -148,14 +148,6 @@ default void generateSharedComponents(GenerationContext context) {
148148
*/
149149
void generateResponseSerializers(GenerationContext context);
150150

151-
/**
152-
* Generates the code used to determine the service and operation
153-
* targeted by a given request.
154-
*
155-
* @param context Generation context.
156-
*/
157-
void generateMux(GenerationContext context);
158-
159151
/**
160152
* Generates the code used to determine the service and operation
161153
* targeted by a given request.

0 commit comments

Comments
 (0)