Skip to content

Commit c389258

Browse files
Merge pull request #281 from adamthom-amzn/symbolprovider
Introduce a server-specific symbol provider.
2 parents 4bf58c3 + 6e8f090 commit c389258

File tree

7 files changed

+290
-90
lines changed

7 files changed

+290
-90
lines changed

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

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ class CodegenVisitor extends ShapeVisitor.Default<Void> {
7575
private final ServiceShape service;
7676
private final FileManifest fileManifest;
7777
private final SymbolProvider symbolProvider;
78+
private final SymbolProvider serverSymbolProvider;
7879
private final Model nonTraits;
7980
private final TypeScriptDelegator writers;
8081
private final List<TypeScriptIntegration> integrations = new ArrayList<>();
@@ -120,6 +121,11 @@ class CodegenVisitor extends ShapeVisitor.Default<Void> {
120121
resolvedProvider = integration.decorateSymbolProvider(settings, model, resolvedProvider);
121122
}
122123
symbolProvider = SymbolProvider.cache(resolvedProvider);
124+
if (settings.generateServerSdk()) {
125+
serverSymbolProvider = SymbolProvider.cache(new ServerSymbolVisitor(model, symbolProvider));
126+
} else {
127+
serverSymbolProvider = symbolProvider;
128+
}
123129

124130
// Resolve the nullable protocol generator and application protocol.
125131
protocolGenerator = resolveProtocolGenerator(integrations, service, settings);
@@ -199,6 +205,11 @@ void execute() {
199205
// Generate index for client.
200206
IndexGenerator.writeIndex(settings, model, symbolProvider, fileManifest, protocolGenerator);
201207

208+
if (settings.generateServerSdk()) {
209+
// Generate index for server
210+
IndexGenerator.writeServerIndex(settings, model, serverSymbolProvider, fileManifest);
211+
}
212+
202213
// Generate protocol tests IFF found in the model.
203214
if (protocolGenerator != null) {
204215
ShapeId protocol = protocolGenerator.getProtocol();
@@ -294,10 +305,6 @@ public Void serviceShape(ServiceShape shape) {
294305

295306
if (settings.generateServerSdk()) {
296307
generateServiceInterface(shape);
297-
writers.useFileWriter("server/index.ts", writer -> {
298-
writer.write("export * from \"./interfaces\";");
299-
writer.write("export * from \"./handler\";");
300-
});
301308
}
302309

303310
if (protocolGenerator != null) {
@@ -317,10 +324,12 @@ public Void serviceShape(ServiceShape shape) {
317324
protocolGenerator.generateResponseDeserializers(context);
318325
}
319326
if (context.getSettings().generateServerSdk()) {
320-
protocolGenerator.generateRequestDeserializers(context);
321-
protocolGenerator.generateResponseSerializers(context);
322-
protocolGenerator.generateMux(context);
323-
protocolGenerator.generateHandlerFactory(context);
327+
ProtocolGenerator.GenerationContext serverContext =
328+
context.withSymbolProvider(serverSymbolProvider);
329+
protocolGenerator.generateRequestDeserializers(serverContext);
330+
protocolGenerator.generateResponseSerializers(serverContext);
331+
protocolGenerator.generateMux(serverContext);
332+
protocolGenerator.generateHandlerFactory(serverContext);
324333
}
325334
protocolGenerator.generateSharedComponents(context);
326335
});
@@ -378,11 +387,11 @@ private void generateClient(ServiceShape shape) {
378387
private void generateServiceInterface(ServiceShape shape) {
379388
TopDownIndex topDownIndex = TopDownIndex.of(model);
380389
Set<OperationShape> operations = new TreeSet<>(topDownIndex.getContainedOperations(shape));
381-
writers.useFileWriter("server/interfaces.ts", interfaceWriter ->
382-
ServerGenerator.generateServerInterfaces(symbolProvider, shape, operations, interfaceWriter));
383-
writers.useFileWriter("server/handler.ts", interfaceWriter ->
384-
ServerGenerator.generateServiceHandler(shape, operations, interfaceWriter));
385-
390+
writers.useShapeWriter(shape, serverSymbolProvider, writer -> {
391+
ServerGenerator.generateOperationsType(serverSymbolProvider, shape, operations, writer);
392+
ServerGenerator.generateServerInterfaces(serverSymbolProvider, shape, operations, writer);
393+
ServerGenerator.generateServiceHandler(serverSymbolProvider, shape, operations, writer);
394+
});
386395
}
387396

388397
private void generateCommands(ServiceShape shape) {
@@ -391,9 +400,17 @@ private void generateCommands(ServiceShape shape) {
391400
Set<OperationShape> containedOperations = new TreeSet<>(topDownIndex.getContainedOperations(shape));
392401
for (OperationShape operation : containedOperations) {
393402
// Right now this only generates stubs
394-
writers.useShapeWriter(operation, commandWriter -> new CommandGenerator(
395-
settings, model, operation, symbolProvider, commandWriter,
396-
runtimePlugins, protocolGenerator, applicationProtocol).run());
403+
if (settings.generateClient()) {
404+
writers.useShapeWriter(operation, commandWriter -> new CommandGenerator(
405+
settings, model, operation, symbolProvider, commandWriter,
406+
runtimePlugins, protocolGenerator, applicationProtocol).run());
407+
}
408+
409+
if (settings.generateServerSdk()) {
410+
writers.useShapeWriter(operation, serverSymbolProvider, commandWriter -> new CommandGenerator(
411+
settings, model, operation, serverSymbolProvider, commandWriter,
412+
runtimePlugins, protocolGenerator, applicationProtocol).run());
413+
}
397414
}
398415
}
399416

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,26 @@ private static void writeProtocolExports(ProtocolGenerator protocolGenerator, Ty
6464
writer.write("export * as $L from \"./protocols/$L\";", protocolName, protocolName);
6565
}
6666

67+
static void writeServerIndex(
68+
TypeScriptSettings settings,
69+
Model model,
70+
SymbolProvider symbolProvider,
71+
FileManifest fileManifest
72+
) {
73+
TypeScriptWriter writer = new TypeScriptWriter("");
74+
75+
ServiceShape service = settings.getService(model);
76+
Symbol symbol = symbolProvider.toSymbol(service);
77+
78+
TopDownIndex topDownIndex = TopDownIndex.of(model);
79+
Set<OperationShape> containedOperations = new TreeSet<>(topDownIndex.getContainedOperations(service));
80+
for (OperationShape operation : containedOperations) {
81+
writer.write("export * from \"./types/$L\";", symbolProvider.toSymbol(operation).getName());
82+
}
83+
writer.write("export * from \"./$L\"", symbol.getName());
84+
fileManifest.writeFile("server/index.ts", writer.toString());
85+
}
86+
6787
private static void writeClientExports(
6888
TypeScriptSettings settings,
6989
Model model,

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

Lines changed: 47 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,35 @@
1515

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

18-
import java.util.LinkedHashSet;
18+
import java.util.Iterator;
1919
import java.util.Set;
2020
import software.amazon.smithy.codegen.core.Symbol;
2121
import software.amazon.smithy.codegen.core.SymbolProvider;
2222
import software.amazon.smithy.model.shapes.OperationShape;
2323
import software.amazon.smithy.model.shapes.ServiceShape;
24-
import software.amazon.smithy.utils.StringUtils;
24+
import software.amazon.smithy.model.shapes.Shape;
2525

2626
final class ServerGenerator {
2727

2828
private ServerGenerator() {}
2929

30-
static void generateServiceHandler(ServiceShape service,
30+
static void generateOperationsType(SymbolProvider symbolProvider,
31+
Shape serviceShape,
32+
Set<OperationShape> operations,
33+
TypeScriptWriter writer) {
34+
Symbol serviceSymbol = symbolProvider.toSymbol(serviceShape);
35+
writer.writeInline("type $L = ", serviceSymbol.expectProperty("operations", Symbol.class).getName());
36+
for (Iterator<OperationShape> iter = operations.iterator(); iter.hasNext();) {
37+
writer.writeInline("$S", iter.next().getId().getName());
38+
if (iter.hasNext()) {
39+
writer.writeInline(" | ");
40+
}
41+
}
42+
writer.write(";");
43+
}
44+
45+
static void generateServiceHandler(SymbolProvider symbolProvider,
46+
Shape serviceShape,
3147
Set<OperationShape> operations,
3248
TypeScriptWriter writer) {
3349
writer.addImport("ServiceHandler", null, "@aws-smithy/server-common");
@@ -42,17 +58,15 @@ static void generateServiceHandler(ServiceShape service,
4258
writer.addImport("HttpRequest", null, "@aws-sdk/protocol-http");
4359
writer.addImport("HttpResponse", null, "@aws-sdk/protocol-http");
4460

45-
String serviceName = StringUtils.capitalize(service.getId().getName());
46-
String operationsTypeName = serviceName + "Operations";
47-
48-
writer.addImport(serviceName + "Service", null, ".");
49-
writer.write("type $L = keyof $L;", operationsTypeName, serviceName + "Service");
61+
Symbol serviceSymbol = symbolProvider.toSymbol(serviceShape);
62+
Symbol handlerSymbol = serviceSymbol.expectProperty("handler", Symbol.class);
63+
Symbol operationsType = serviceSymbol.expectProperty("operations", Symbol.class);
5064

51-
writer.openBlock("export class $LServiceHandler implements ServiceHandler {", "}", serviceName, () -> {
52-
writer.write("private service: $LService;", serviceName);
53-
writer.write("private mux: Mux<$S, $L>;", serviceName, operationsTypeName);
54-
writer.write("private serializers: Record<$1L, OperationSerializer<$2LService, $1L>>;",
55-
operationsTypeName, serviceName);
65+
writer.openBlock("export class $L implements ServiceHandler {", "}", handlerSymbol.getName(), () -> {
66+
writer.write("private service: $T;", serviceSymbol);
67+
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());
5670
writer.openBlock("private serdeContextBase = {", "};", () -> {
5771
writer.write("base64Encoder: toBase64,");
5872
writer.write("base64Decoder: fromBase64,");
@@ -63,19 +77,19 @@ static void generateServiceHandler(ServiceShape service,
6377
writer.write("disableHostPrefix: true");
6478
});
6579
writer.write("/**");
66-
writer.write(" * Construct a $LService handler.", serviceName);
67-
writer.write(" * @param service The {@link $LService} implementation that supplies", serviceName);
68-
writer.write(" * the business logic for $LService", serviceName);
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);
6983
writer.write(" * @param mux The {@link Mux} that determines which service and operation are being");
7084
writer.write(" * invoked by a given {@link HttpRequest}");
7185
writer.write(" * @param serializers An {@link OperationSerializer} for each operation in");
72-
writer.write(" * $LService that handles deserialization of requests and", serviceName);
73-
writer.write(" * serialization of responses");
86+
writer.write(" * $T that handles deserialization of requests", serviceSymbol);
87+
writer.write(" * and serialization of responses");
7488
writer.write(" */");
75-
writer.openBlock("constructor(service: $1LService, "
76-
+ "mux: Mux<$1S, $2L>, "
77-
+ "serializers: Record<$2L, OperationSerializer<$1LService, $2L>>) {", "}",
78-
serviceName, operationsTypeName, () -> {
89+
writer.openBlock("constructor(service: $1T, "
90+
+ "mux: Mux<$3S, $2T>, "
91+
+ "serializers: Record<$2T, OperationSerializer<$1T, $2T>>) {", "}",
92+
serviceSymbol, operationsType, serviceShape.getId().getName(), () -> {
7993
writer.write("this.service = service;");
8094
writer.write("this.mux = mux;");
8195
writer.write("this.serializers = serializers;");
@@ -88,22 +102,25 @@ static void generateServiceHandler(ServiceShape service,
88102
});
89103
writer.openBlock("switch (target.operation) {", "}", () -> {
90104
for (OperationShape operation : operations) {
91-
generateHandlerCase(writer, serviceName, operation);
105+
generateHandlerCase(writer, serviceSymbol, operation, symbolProvider.toSymbol(operation));
92106
}
93107
});
94108
});
95109
});
96110
}
97111

98-
private static void generateHandlerCase(TypeScriptWriter writer, String serviceName, OperationShape operation) {
99-
String opName = operation.getId().getName();
112+
private static void generateHandlerCase(TypeScriptWriter writer,
113+
Symbol serviceSymbol,
114+
Shape operationShape,
115+
Symbol operationSymbol) {
116+
String opName = operationShape.getId().getName();
100117
writer.openBlock("case $S : {", "}", opName, () -> {
101-
writer.write("let serializer = this.serializers.$1L as OperationSerializer<$2LService, $1S>;",
102-
opName, serviceName);
118+
writer.write("let serializer = this.serializers.$2L as OperationSerializer<$1L, $2S>;",
119+
serviceSymbol.getName(), opName);
103120
writer.openBlock("let input = await serializer.deserialize(request, {", "});", () -> {
104121
writer.write("endpoint: () => Promise.resolve(request), ...this.serdeContextBase");
105122
});
106-
writer.write("let output = this.service.$L(input, request);", opName);
123+
writer.write("let output = this.service.$L(input, request);", operationSymbol.getName());
107124
writer.write("return serializer.serialize(output, this.serdeContextBase);");
108125
});
109126
}
@@ -114,41 +131,16 @@ static void generateServerInterfaces(SymbolProvider symbolProvider,
114131
TypeScriptWriter writer) {
115132
writer.addImport("Operation", "__Operation", "@aws-smithy/server-common");
116133

117-
String serviceInterfaceName = StringUtils.capitalize(service.getId().getName()) + "Service";
134+
String serviceInterfaceName = symbolProvider.toSymbol(service).getName();
118135

119136
writer.openBlock("export interface $L {", "}", serviceInterfaceName, () -> {
120137
for (OperationShape operation : operations) {
121138
Symbol symbol = symbolProvider.toSymbol(operation);
122-
writer.write("$L: $L<$T, $T>", StringUtils.capitalize(operation.getId().getName()),
139+
writer.write("$L: $L<$T, $T>", symbol.getName(),
123140
"__Operation",
124141
symbol.expectProperty("inputType", Symbol.class),
125142
symbol.expectProperty("outputType", Symbol.class));
126143
}
127144
});
128-
129-
writer.addImport("ParsedRequest", "__ParsedRequest", "@aws-smithy/server-common");
130-
writer.addImport("PreparedResponse", "__PreparedResponse", "@aws-smithy/server-common");
131-
132-
Set<String> requestInterfaces = new LinkedHashSet<>();
133-
Set<String> responseInterfaces = new LinkedHashSet<>();
134-
for (OperationShape operation : operations) {
135-
String opName = StringUtils.capitalize(operation.getId().getName());
136-
String requestInterfaceName = "Parsed" + opName + "Request";
137-
String responseInterfaceName = "Prepared" + opName + "Response";
138-
139-
writer.write("export interface $L extends $L<$L, $S> {}",
140-
requestInterfaceName, "__ParsedRequest", serviceInterfaceName, opName);
141-
writer.write("export interface $L extends $L<$L, $S> {}",
142-
responseInterfaceName, "__PreparedResponse", serviceInterfaceName, opName);
143-
144-
requestInterfaces.add(requestInterfaceName);
145-
responseInterfaces.add(responseInterfaceName);
146-
}
147-
148-
writer.write("export type $LRequests = $L;",
149-
serviceInterfaceName, String.join(" | ", requestInterfaces));
150-
151-
writer.write("export type $LResponses = $L;",
152-
serviceInterfaceName, String.join(" | ", responseInterfaces));
153145
}
154146
}

0 commit comments

Comments
 (0)