@@ -70,6 +70,7 @@ class CodegenVisitor extends ShapeVisitor.Default<Void> {
70
70
private final ServiceShape service ;
71
71
private final FileManifest fileManifest ;
72
72
private final SymbolProvider symbolProvider ;
73
+ private final SymbolProvider serverSymbolProvider ;
73
74
private final Model nonTraits ;
74
75
private final TypeScriptDelegator writers ;
75
76
private final List <TypeScriptIntegration > integrations = new ArrayList <>();
@@ -107,14 +108,20 @@ class CodegenVisitor extends ShapeVisitor.Default<Void> {
107
108
nonTraits = context .getModelWithoutTraitShapes ();
108
109
service = settings .getService (model );
109
110
fileManifest = context .getFileManifest ();
110
- LOGGER .info (() -> "Generating TypeScript client for service " + service .getId ());
111
+ LOGGER .info (() -> String .format ("Generating TypeScript %s for service %s" ,
112
+ settings .generateClient () ? "client" : "server" , service .getId ()));
111
113
112
114
// Decorate the symbol provider using integrations.
113
115
SymbolProvider resolvedProvider = TypeScriptCodegenPlugin .createSymbolProvider (model , settings );
114
116
for (TypeScriptIntegration integration : integrations ) {
115
117
resolvedProvider = integration .decorateSymbolProvider (settings , model , resolvedProvider );
116
118
}
117
119
symbolProvider = SymbolProvider .cache (resolvedProvider );
120
+ if (settings .generateServerSdk ()) {
121
+ serverSymbolProvider = SymbolProvider .cache (new ServerSymbolVisitor (model , symbolProvider ));
122
+ } else {
123
+ serverSymbolProvider = symbolProvider ;
124
+ }
118
125
119
126
// Resolve the nullable protocol generator and application protocol.
120
127
protocolGenerator = resolveProtocolGenerator (integrations , service , settings );
@@ -175,11 +182,15 @@ void execute() {
175
182
// Generate the client Node and Browser configuration files. These
176
183
// files are switched between in package.json based on the targeted
177
184
// environment.
178
- RuntimeConfigGenerator configGenerator = new RuntimeConfigGenerator (
179
- settings , model , symbolProvider , writers , integrations );
180
- for (LanguageTarget target : LanguageTarget .values ()) {
181
- LOGGER .fine ("Generating " + target + " runtime configuration" );
182
- configGenerator .generate (target );
185
+ if (settings .generateClient ()) {
186
+ // For now these are only generated for clients.
187
+ // TODO: generate ssdk config
188
+ RuntimeConfigGenerator configGenerator = new RuntimeConfigGenerator (
189
+ settings , model , symbolProvider , writers , integrations );
190
+ for (LanguageTarget target : LanguageTarget .values ()) {
191
+ LOGGER .fine ("Generating " + target + " runtime configuration" );
192
+ configGenerator .generate (target );
193
+ }
183
194
}
184
195
185
196
// Write each custom file.
@@ -189,12 +200,18 @@ void execute() {
189
200
}
190
201
191
202
// Generate index for client.
192
- IndexGenerator .writeIndex (settings , model , symbolProvider , fileManifest , integrations );
203
+ IndexGenerator .writeIndex (settings , model , symbolProvider , fileManifest , integrations , protocolGenerator );
204
+
205
+ if (settings .generateServerSdk ()) {
206
+ // Generate index for server
207
+ IndexGenerator .writeServerIndex (settings , model , serverSymbolProvider , fileManifest );
208
+ }
193
209
194
210
// Generate protocol tests IFF found in the model.
195
211
if (protocolGenerator != null ) {
196
212
ShapeId protocol = protocolGenerator .getProtocol ();
197
- new HttpProtocolTestGenerator (settings , model , protocol , symbolProvider , writers ).run ();
213
+ new HttpProtocolTestGenerator (
214
+ settings , model , protocol , symbolProvider , serverSymbolProvider , writers , protocolGenerator ).run ();
198
215
}
199
216
200
217
// Write each pending writer.
@@ -270,13 +287,74 @@ public Void stringShape(StringShape shape) {
270
287
return null ;
271
288
}
272
289
290
+ @ Override
291
+ public Void operationShape (OperationShape operation ) {
292
+ if (settings .generateServerSdk ()) {
293
+ writers .useShapeWriter (operation , serverSymbolProvider , w -> {
294
+ ServerGenerator .generateOperationHandler (serverSymbolProvider , service , operation , w );
295
+ });
296
+ }
297
+ return null ;
298
+ }
299
+
273
300
@ Override
274
301
public Void serviceShape (ServiceShape shape ) {
275
302
if (!Objects .equals (service , shape )) {
276
303
LOGGER .fine (() -> "Skipping `" + shape .getId () + "` because it is not `" + service .getId () + "`" );
277
304
return null ;
278
305
}
279
306
307
+ if (settings .generateClient ()) {
308
+ generateClient (shape );
309
+ }
310
+ if (settings .generateClient () || settings .generateServerSdk ()) {
311
+ generateCommands (shape );
312
+ }
313
+
314
+ if (settings .generateServerSdk ()) {
315
+ generateServiceInterface (shape );
316
+ generateServerErrors (shape );
317
+ }
318
+
319
+ if (protocolGenerator != null ) {
320
+ LOGGER .info ("Generating serde for protocol " + protocolGenerator .getName () + " on " + shape .getId ());
321
+ String fileName = "protocols/" + ProtocolGenerator .getSanitizedName (protocolGenerator .getName ()) + ".ts" ;
322
+ writers .useFileWriter (fileName , writer -> {
323
+ ProtocolGenerator .GenerationContext context = new ProtocolGenerator .GenerationContext ();
324
+ context .setProtocolName (protocolGenerator .getName ());
325
+ context .setIntegrations (integrations );
326
+ context .setModel (model );
327
+ context .setService (shape );
328
+ context .setSettings (settings );
329
+ context .setSymbolProvider (symbolProvider );
330
+ context .setWriter (writer );
331
+ if (context .getSettings ().generateClient ()) {
332
+ protocolGenerator .generateRequestSerializers (context );
333
+ protocolGenerator .generateResponseDeserializers (context );
334
+ }
335
+ if (context .getSettings ().generateServerSdk ()) {
336
+ ProtocolGenerator .GenerationContext serverContext =
337
+ context .withSymbolProvider (serverSymbolProvider );
338
+ protocolGenerator .generateRequestDeserializers (serverContext );
339
+ protocolGenerator .generateResponseSerializers (serverContext );
340
+ protocolGenerator .generateFrameworkErrorSerializer (serverContext );
341
+ writers .useShapeWriter (shape , serverSymbolProvider , w -> {
342
+ protocolGenerator .generateServiceHandlerFactory (serverContext .withWriter (w ));
343
+ });
344
+ for (OperationShape operation : TopDownIndex .of (model ).getContainedOperations (service )) {
345
+ writers .useShapeWriter (operation , serverSymbolProvider , w -> {
346
+ protocolGenerator .generateOperationHandlerFactory (serverContext .withWriter (w ), operation );
347
+ });
348
+ }
349
+ }
350
+ protocolGenerator .generateSharedComponents (context );
351
+ });
352
+ }
353
+
354
+ return null ;
355
+ }
356
+
357
+ private void generateClient (ServiceShape shape ) {
280
358
// Generate the modular service client.
281
359
writers .useShapeWriter (shape , writer -> new ServiceGenerator (
282
360
settings , model , symbolProvider , writer , integrations , runtimePlugins , applicationProtocol ).run ());
@@ -294,9 +372,6 @@ public Void serviceShape(ServiceShape shape) {
294
372
boolean hasPaginatedOperation = false ;
295
373
296
374
for (OperationShape operation : containedOperations ) {
297
- writers .useShapeWriter (operation , commandWriter -> new CommandGenerator (
298
- settings , model , operation , symbolProvider , commandWriter ,
299
- runtimePlugins , protocolGenerator , applicationProtocol ).run ());
300
375
if (operation .hasTrait (PaginatedTrait .ID )) {
301
376
hasPaginatedOperation = true ;
302
377
String outputFilename = PaginationGenerator .getOutputFilelocation (operation );
@@ -323,25 +398,48 @@ public Void serviceShape(ServiceShape shape) {
323
398
serviceSymbol ,
324
399
paginationWriter ));
325
400
}
401
+ }
326
402
327
- if (protocolGenerator != null ) {
328
- LOGGER .info ("Generating serde for protocol " + protocolGenerator .getName () + " on " + shape .getId ());
329
- String fileName = "protocols/" + ProtocolGenerator .getSanitizedName (protocolGenerator .getName ()) + ".ts" ;
330
- writers .useFileWriter (fileName , writer -> {
331
- ProtocolGenerator .GenerationContext context = new ProtocolGenerator .GenerationContext ();
332
- context .setProtocolName (protocolGenerator .getName ());
333
- context .setIntegrations (integrations );
334
- context .setModel (model );
335
- context .setService (shape );
336
- context .setSettings (settings );
337
- context .setSymbolProvider (symbolProvider );
338
- context .setWriter (writer );
339
- protocolGenerator .generateRequestSerializers (context );
340
- protocolGenerator .generateResponseDeserializers (context );
341
- protocolGenerator .generateSharedComponents (context );
342
- });
343
- }
403
+ private void generateServiceInterface (ServiceShape shape ) {
404
+ TopDownIndex topDownIndex = TopDownIndex .of (model );
405
+ Set <OperationShape > operations = new TreeSet <>(topDownIndex .getContainedOperations (shape ));
406
+ writers .useShapeWriter (shape , serverSymbolProvider , writer -> {
407
+ ServerGenerator .generateOperationsType (serverSymbolProvider , shape , operations , writer );
408
+ ServerGenerator .generateServerInterfaces (serverSymbolProvider , shape , operations , writer );
409
+ ServerGenerator .generateServiceHandler (serverSymbolProvider , shape , operations , writer );
410
+ });
411
+ }
344
412
345
- return null ;
413
+ private void generateServerErrors (ServiceShape service ) {
414
+ TopDownIndex .of (model )
415
+ .getContainedOperations (service )
416
+ .stream ()
417
+ .flatMap (o -> o .getErrors ().stream ())
418
+ .distinct ()
419
+ .map (id -> model .expectShape (id ).asStructureShape ().orElseThrow (IllegalArgumentException ::new ))
420
+ .sorted ()
421
+ .forEachOrdered (error -> writers .useShapeWriter (service , serverSymbolProvider , writer -> {
422
+ new ServerErrorGenerator (settings , model , error , serverSymbolProvider , writer ).run ();
423
+ }));
424
+ }
425
+
426
+ private void generateCommands (ServiceShape shape ) {
427
+ // Generate each operation for the service.
428
+ TopDownIndex topDownIndex = TopDownIndex .of (model );
429
+ Set <OperationShape > containedOperations = new TreeSet <>(topDownIndex .getContainedOperations (shape ));
430
+ for (OperationShape operation : containedOperations ) {
431
+ // Right now this only generates stubs
432
+ if (settings .generateClient ()) {
433
+ writers .useShapeWriter (operation , commandWriter -> new CommandGenerator (
434
+ settings , model , operation , symbolProvider , commandWriter ,
435
+ runtimePlugins , protocolGenerator , applicationProtocol ).run ());
436
+ }
437
+
438
+ if (settings .generateServerSdk ()) {
439
+ writers .useShapeWriter (operation , serverSymbolProvider , commandWriter -> new ServerCommandGenerator (
440
+ settings , model , operation , serverSymbolProvider , commandWriter ,
441
+ protocolGenerator , applicationProtocol ).run ());
442
+ }
443
+ }
346
444
}
347
445
}
0 commit comments