11import  {  NormalizedSchema  }  from  "@smithy/core/schema" ; 
2+ import  {  SCHEMA  }  from  "@smithy/core/schema" ; 
23import  {  HttpRequest ,  HttpResponse  }  from  "@smithy/protocol-http" ; 
3- import  { 
4+ import  type   { 
45  ClientProtocol , 
56  Codec , 
67  Endpoint , 
78  EndpointBearer , 
89  EndpointV2 , 
10+   EventStreamMarshaller , 
11+   EventStreamSerdeContext , 
912  HandlerExecutionContext , 
1013  HttpRequest  as  IHttpRequest , 
1114  HttpResponse  as  IHttpResponse , 
15+   Message  as  EventStreamMessage , 
16+   MessageHeaders , 
1217  MetadataBearer , 
1318  OperationSchema , 
1419  ResponseMetadata , 
@@ -17,6 +22,7 @@ import {
1722  ShapeDeserializer , 
1823  ShapeSerializer , 
1924}  from  "@smithy/types" ; 
25+ import  {  fromUtf8  }  from  "@smithy/util-utf8" ; 
2026
2127/** 
2228 * Abstract base for HTTP-based client protocols. 
@@ -138,6 +144,78 @@ export abstract class HttpProtocol implements ClientProtocol<IHttpRequest, IHttp
138144    } ; 
139145  } 
140146
147+   protected  serializeEventStream ( {  input,  unionSchema } : {  input : AsyncIterable < any > ;  unionSchema : NormalizedSchema  } )  { 
148+     const  marshaller  =  this . getEventStreamMarshaller ( ) ; 
149+     const  memberSchemas  =  unionSchema . getMemberSchemas ( ) ; 
150+ 
151+     return  marshaller . serialize ( input ,  ( event : any ) : EventStreamMessage  =>  { 
152+       const  unionMember  = 
153+         Object . keys ( event ) . find ( ( key )  =>  { 
154+           return  key  !==  "__type" ; 
155+         } )  ??  "" ; 
156+       const  eventStreamSchema  =  memberSchemas [ unionMember ]  ??  NormalizedSchema . of ( SCHEMA . DOCUMENT ) ; 
157+ 
158+       this . serializer . write ( eventStreamSchema ,  event ) ; 
159+       const  messageSerialization  =  this . serializer . flush ( ) ; 
160+ 
161+       const  body  = 
162+         typeof  messageSerialization  ===  "string" 
163+           ? ( this . serdeContext ?. utf8Decoder  ??  fromUtf8 ) ( messageSerialization ) 
164+           : messageSerialization ; 
165+ 
166+       const  headers : MessageHeaders  =  { 
167+         ":event-type" : {  type : "string" ,  value : unionMember  } , 
168+         ":message-type" : {  type : "string" ,  value : "event"  } , 
169+         ":content-type" : {  type : "string" ,  value : this . getDefaultContentType ( )  } , 
170+       } ; 
171+ 
172+       return  { 
173+         headers, 
174+         body, 
175+       } ; 
176+     } ) ; 
177+   } 
178+ 
179+   protected  deserializeEventStream ( { 
180+     response, 
181+     unionSchema, 
182+   } : { 
183+     response : IHttpResponse ; 
184+     unionSchema : NormalizedSchema ; 
185+   } ) : AsyncIterable < {  [ key : string ] : any ;  $unknown ?: unknown  } >  { 
186+     const  marshaller  =  this . getEventStreamMarshaller ( ) ; 
187+     const  memberSchemas  =  unionSchema . getMemberSchemas ( ) ; 
188+ 
189+     return  marshaller . deserialize ( response . body ,  async  ( event )  =>  { 
190+       const  unionMember  = 
191+         Object . keys ( event ) . find ( ( key )  =>  { 
192+           return  key  !==  "__type" ; 
193+         } )  ??  "" ; 
194+       if  ( unionMember  in  memberSchemas )  { 
195+         const  eventStreamSchema  =  memberSchemas [ unionMember ] ; 
196+         return  { 
197+           [ unionMember ] : await  this . deserializer . read ( eventStreamSchema ,  event [ unionMember ] . body ) , 
198+         } ; 
199+       }  else  { 
200+         // todo(schema): This union convention is ignored by the event stream marshaller. 
201+         // todo(schema): This should be returned to the user instead. 
202+         // see "if (deserialized.$unknown) return;" in getUnmarshalledStream.ts 
203+         return  { 
204+           $unknown : event , 
205+         } ; 
206+       } 
207+     } ) ; 
208+   } 
209+ 
210+   /** 
211+    * @returns  content-type default header value for event stream events and other documents. 
212+    */ 
213+   protected  getDefaultContentType ( ) : string  { 
214+     throw  new  Error ( 
215+       `@smithy/core/protocols - ${ this . constructor . name }   getDefaultContentType() implementation missing.` 
216+     ) ; 
217+   } 
218+ 
141219  /** 
142220   * For HTTP binding protocols, this method is overridden in {@link  HttpBindingProtocol}. 
143221   * 
@@ -172,4 +250,12 @@ export abstract class HttpProtocol implements ClientProtocol<IHttpRequest, IHttp
172250    // It should remain unused. 
173251    return  [ ] ; 
174252  } 
253+ 
254+   protected  getEventStreamMarshaller ( ) : EventStreamMarshaller  { 
255+     const  context  =  this . serdeContext  as  unknown  as  EventStreamSerdeContext ; 
256+     if  ( ! context . eventStreamMarshaller )  { 
257+       throw  new  Error ( "@smithy/core - HttpProtocol: eventStreamMarshaller missing in serdeContext." ) ; 
258+     } 
259+     return  context . eventStreamMarshaller ; 
260+   } 
175261} 
0 commit comments