18
18
import static software .amazon .smithy .typescript .codegen .CodegenUtils .getBlobStreamingMembers ;
19
19
import static software .amazon .smithy .typescript .codegen .CodegenUtils .writeStreamingMemberType ;
20
20
21
+ import java .util .Iterator ;
21
22
import java .util .List ;
22
23
import java .util .Optional ;
23
24
import software .amazon .smithy .codegen .core .Symbol ;
26
27
import software .amazon .smithy .model .knowledge .OperationIndex ;
27
28
import software .amazon .smithy .model .shapes .MemberShape ;
28
29
import software .amazon .smithy .model .shapes .OperationShape ;
30
+ import software .amazon .smithy .model .shapes .ShapeId ;
29
31
import software .amazon .smithy .model .shapes .StructureShape ;
32
+ import software .amazon .smithy .typescript .codegen .integration .ProtocolGenerator ;
30
33
31
34
/**
32
35
* Generates server operation types.
@@ -41,29 +44,40 @@ final class ServerCommandGenerator implements Runnable {
41
44
private final OperationIndex operationIndex ;
42
45
private final Symbol inputType ;
43
46
private final Symbol outputType ;
47
+ private final Symbol errorsType ;
48
+ private final ProtocolGenerator protocolGenerator ;
49
+ private final ApplicationProtocol applicationProtocol ;
44
50
45
51
ServerCommandGenerator (
46
52
TypeScriptSettings settings ,
47
53
Model model ,
48
54
OperationShape operation ,
49
55
SymbolProvider symbolProvider ,
50
- TypeScriptWriter writer
56
+ TypeScriptWriter writer ,
57
+ ProtocolGenerator protocolGenerator ,
58
+ ApplicationProtocol applicationProtocol
51
59
) {
52
60
this .settings = settings ;
53
61
this .model = model ;
54
62
this .operation = operation ;
55
63
this .symbolProvider = symbolProvider ;
56
64
this .writer = writer ;
65
+ this .protocolGenerator = protocolGenerator ;
66
+ this .applicationProtocol = applicationProtocol ;
57
67
58
68
Symbol operationSymbol = symbolProvider .toSymbol (operation );
59
69
operationIndex = OperationIndex .of (model );
60
70
inputType = operationSymbol .expectProperty ("inputType" , Symbol .class );
61
71
outputType = operationSymbol .expectProperty ("outputType" , Symbol .class );
72
+ errorsType = operationSymbol .expectProperty ("errorsType" , Symbol .class );
62
73
}
63
74
64
75
@ Override
65
76
public void run () {
77
+ writeOperationType ();
66
78
addInputAndOutputTypes ();
79
+ writeErrorType ();
80
+ writeOperationSerializer ();
67
81
}
68
82
69
83
private void addInputAndOutputTypes () {
@@ -99,4 +113,93 @@ private void writeOutputType(String typeName, Optional<StructureShape> outputSha
99
113
writer .write ("export type $L = __MetadataBearer" , typeName );
100
114
}
101
115
}
116
+
117
+ private void writeErrorType () {
118
+ if (operation .getErrors ().isEmpty ()) {
119
+ writer .write ("export type $L = never;" , errorsType .getName ());
120
+ } else {
121
+ writer .writeInline ("export type $L = " , errorsType .getName ());
122
+ for (Iterator <ShapeId > iter = operation .getErrors ().iterator (); iter .hasNext ();) {
123
+ writer .writeInline ("$T" , symbolProvider .toSymbol (model .expectShape (iter .next ())));
124
+ if (iter .hasNext ()) {
125
+ writer .writeInline (" | " );
126
+ }
127
+ }
128
+ writer .write ("" );
129
+ }
130
+ writer .write ("" );
131
+ }
132
+
133
+ private void writeOperationType () {
134
+ Symbol operationSymbol = symbolProvider .toSymbol (operation );
135
+ writer .addImport ("Operation" , "__Operation" , "@aws-smithy/server-common" );
136
+ writer .write ("export type $L = __Operation<$T, $T>" , operationSymbol .getName (), inputType , outputType );
137
+ writer .write ("" );
138
+ }
139
+
140
+ private void writeOperationSerializer () {
141
+ Symbol operationSymbol = symbolProvider .toSymbol (operation );
142
+ String serializerName = operationSymbol .expectProperty ("serializerType" , Symbol .class ).getName ();
143
+ Symbol serverSymbol = symbolProvider .toSymbol (model .expectShape (settings .getService ()));
144
+
145
+ writer .addImport ("OperationSerializer" , null , "@aws-smithy/server-common" );
146
+ writer .openBlock ("export class $L implements OperationSerializer<$T, $S, $T> {" , "}" ,
147
+ serializerName , serverSymbol , operation .getId ().getName (), errorsType , () -> {
148
+ String serializerFunction = ProtocolGenerator .getGenericSerFunctionName (operationSymbol ) + "Response" ;
149
+ String deserializerFunction = ProtocolGenerator .getGenericDeserFunctionName (operationSymbol ) + "Request" ;
150
+ writer .addImport (serializerFunction , null ,
151
+ "./protocols/" + ProtocolGenerator .getSanitizedName (protocolGenerator .getName ()));
152
+ writer .addImport (deserializerFunction , null ,
153
+ "./protocols/" + ProtocolGenerator .getSanitizedName (protocolGenerator .getName ()));
154
+ writer .write ("serialize = $L;" , serializerFunction );
155
+ writer .write ("deserialize = $L;" , deserializerFunction );
156
+ writer .write ("" );
157
+ writeErrorChecker ();
158
+ writeErrorHandler ();
159
+ });
160
+ writer .write ("" );
161
+ }
162
+
163
+ private void writeErrorChecker () {
164
+ writer .openBlock ("isOperationError(error: any): error is $T {" , "};" , errorsType , () -> {
165
+ if (operation .getErrors ().isEmpty ()) {
166
+ writer .write ("return false;" );
167
+ } else {
168
+ writer .writeInline ("const names: $T['name'][] = [" , errorsType );
169
+ for (Iterator <ShapeId > iter = operation .getErrors ().iterator (); iter .hasNext ();) {
170
+ writer .writeInline ("$S" , iter .next ().getName ());
171
+ if (iter .hasNext ()) {
172
+ writer .writeInline (", " );
173
+ }
174
+ }
175
+ writer .write ("];" );
176
+ writer .write ("return names.includes(error.name);" );
177
+ }
178
+ });
179
+ writer .write ("" );
180
+ }
181
+
182
+ private void writeErrorHandler () {
183
+ writer .addImport ("SerdeContext" , null , "@aws-sdk/types" );
184
+ writer .openBlock ("serializeError(error: $T, ctx: Omit<SerdeContext, 'endpoint'>): Promise<$T> {" , "}" ,
185
+ errorsType , applicationProtocol .getResponseType (), () -> {
186
+ writer .openBlock ("switch (error.name) {" , "}" , () -> {
187
+ for (ShapeId errorId : operation .getErrors ()) {
188
+ writeErrorHandlerCase (errorId );
189
+ }
190
+ writer .openBlock ("default: {" , "}" , () -> writer .write ("throw error;" ));
191
+ });
192
+ });
193
+ writer .write ("" );
194
+ }
195
+
196
+ private void writeErrorHandlerCase (ShapeId errorId ) {
197
+ Symbol errorSymbol = symbolProvider .toSymbol (model .expectShape (errorId ));
198
+ String serializerFunction = ProtocolGenerator .getGenericSerFunctionName (errorSymbol ) + "Error" ;
199
+ writer .addImport (serializerFunction , null ,
200
+ "./protocols/" + ProtocolGenerator .getSanitizedName (protocolGenerator .getName ()));
201
+ writer .openBlock ("case $S: {" , "}" , errorId .getName (), () -> {
202
+ writer .write ("return $L(error, ctx);" , serializerFunction );
203
+ });
204
+ }
102
205
}
0 commit comments