1- import type { Channel , StreamChat } from 'stream-chat' ;
1+ import type {
2+ Channel ,
3+ ChannelMemberResponse ,
4+ Event ,
5+ MessageResponseBase ,
6+ ReactionResponse ,
7+ StreamChat ,
8+ UserResponse ,
9+ } from 'stream-chat' ;
210
311import {
4- websocketEventTemplateDefinitions ,
512 type SupportedWebsocketEventType ,
613 type WebSocketEventTemplateContext ,
14+ websocketEventTemplateDefinitions ,
715} from './websocketEventTemplates' ;
816import type { SimulationState , SimulationUser } from './types' ;
917
10- type JsonObject = Record < string , unknown > ;
11- type HandleEventArgument = Parameters < StreamChat [ 'handleEvent' ] > [ 0 ] ;
18+ type UnknownRecord = Record < string , unknown > ;
19+ type EventPayload = Omit <
20+ Partial < Event > ,
21+ 'channel' | 'member' | 'message' | 'reaction' | 'user'
22+ > & {
23+ channel ?: Partial < WebSocketEventTemplateContext [ 'channel' ] > ;
24+ member ?: ChannelMemberResponse ;
25+ message ?: Partial < MessageResponseBase > ;
26+ reaction ?: ReactionResponse ;
27+ user ?: UserResponse ;
28+ } ;
1229
1330const messageTextFragments = [
1431 'debug event payload' ,
@@ -20,12 +37,12 @@ const messageTextFragments = [
2037
2138const reactionTypes = [ 'love' , 'haha' , 'wow' , 'like' , 'sad' ] as const ;
2239
23- const asJsonObject = ( value : unknown ) : JsonObject | undefined => {
40+ const asJsonObject = ( value : unknown ) : UnknownRecord | undefined => {
2441 if ( ! value || typeof value !== 'object' || Array . isArray ( value ) ) {
2542 return undefined ;
2643 }
2744
28- return value as JsonObject ;
45+ return value as UnknownRecord ;
2946} ;
3047
3148const getId = ( value : unknown ) => {
@@ -45,10 +62,33 @@ const getMessageUser = (message: unknown) => asJsonObject(asJsonObject(message)?
4562const getMessageMember = ( message : unknown ) =>
4663 asJsonObject ( asJsonObject ( message ) ?. member ) ;
4764
65+ const asUserResponse = ( value : unknown ) : UserResponse | undefined => {
66+ const user = asJsonObject ( value ) ;
67+
68+ return typeof user ?. id === 'string' ? ( user as unknown as UserResponse ) : undefined ;
69+ } ;
70+
71+ const asChannelMemberResponse = ( value : unknown ) : ChannelMemberResponse | undefined => {
72+ const member = asJsonObject ( value ) ;
73+
74+ if ( ! member ) return undefined ;
75+
76+ const userId = getId ( member . user_id ) ?? getUserId ( member . user ) ;
77+
78+ return userId ? ( member as unknown as ChannelMemberResponse ) : undefined ;
79+ } ;
80+
4881const buildRandomMessageText = ( sequence : number ) =>
4982 `${ messageTextFragments [ sequence % messageTextFragments . length ] } #${ sequence } ` ;
5083
51- const buildReactionState = ( { reaction } : { reaction : JsonObject } ) : JsonObject => {
84+ const buildReactionState = ( {
85+ reaction,
86+ } : {
87+ reaction : ReactionResponse ;
88+ } ) : Pick <
89+ MessageResponseBase ,
90+ 'latest_reactions' | 'reaction_counts' | 'reaction_groups' | 'reaction_scores'
91+ > => {
5292 const reactionType = getId ( reaction . type ) ?? 'love' ;
5393 const reactionScore =
5494 typeof reaction . score === 'number' && Number . isFinite ( reaction . score )
@@ -100,7 +140,7 @@ const getChannelMembersForCid = (
100140 cid : string ,
101141 simulationState : SimulationState ,
102142 templateContext : WebSocketEventTemplateContext ,
103- ) => {
143+ ) : ChannelMemberResponse [ ] => {
104144 const knownMembers = Object . values ( simulationState . membersByCid [ cid ] ?? { } ) ;
105145
106146 if ( knownMembers . length > 0 ) {
@@ -122,7 +162,7 @@ const buildFreshContext = (
122162 templateContext ,
123163 ) ;
124164 const memberCount = channelMembers . length || templateContext . memberCount ;
125- const baseChannel = asJsonObject ( templateContext . channel ) ?? { } ;
165+ const baseChannel = templateContext . channel ;
126166
127167 return {
128168 ...templateContext ,
@@ -212,9 +252,9 @@ const registerUserAndMember = ({
212252 user,
213253} : {
214254 cid : string ;
215- member ?: JsonObject ;
255+ member ?: ChannelMemberResponse ;
216256 simulationState : SimulationState ;
217- user ?: JsonObject ;
257+ user ?: UserResponse ;
218258} ) => {
219259 if ( user ) {
220260 const userId = getUserId ( user ) ;
@@ -266,9 +306,9 @@ export const createInitialSimulationState = ({
266306
267307 registerUserAndMember ( {
268308 cid,
269- member : templateContext . actorMember ,
309+ member : templateContext . actorMember as ChannelMemberResponse ,
270310 simulationState : state ,
271- user : templateContext . actor ,
311+ user : templateContext . actor as UserResponse ,
272312 } ) ;
273313 registerUserAndMember ( {
274314 cid,
@@ -284,9 +324,9 @@ export const createInitialSimulationState = ({
284324
285325 registerUserAndMember ( {
286326 cid,
287- member : memberObject ,
327+ member : asChannelMemberResponse ( memberObject ) ,
288328 simulationState : state ,
289- user : userObject ,
329+ user : asUserResponse ( userObject ) ,
290330 } ) ;
291331 } ) ;
292332
@@ -305,9 +345,9 @@ export const createInitialSimulationState = ({
305345
306346 registerUserAndMember ( {
307347 cid,
308- member : getMessageMember ( messageObject ) ,
348+ member : asChannelMemberResponse ( getMessageMember ( messageObject ) ) ,
309349 simulationState : state ,
310- user : getMessageUser ( messageObject ) ,
350+ user : asUserResponse ( getMessageUser ( messageObject ) ) ,
311351 } ) ;
312352 } ) ;
313353
@@ -322,11 +362,11 @@ export const buildFreshWebSocketEventPayload = ({
322362 eventType : SupportedWebsocketEventType ;
323363 simulationState : SimulationState ;
324364 templateContext : WebSocketEventTemplateContext ;
325- } ) : JsonObject => {
365+ } ) : EventPayload => {
326366 const freshContext = buildFreshContext ( templateContext , simulationState ) ;
327367 const basePayload = websocketEventTemplateDefinitions [ eventType ] . buildDefault (
328368 freshContext ,
329- ) as JsonObject ;
369+ ) as EventPayload ;
330370
331371 switch ( eventType ) {
332372 case 'message.new' :
@@ -454,7 +494,7 @@ export const trackSimulationStateFromPayload = ({
454494 simulationState,
455495 templateContext,
456496} : {
457- payload : JsonObject ;
497+ payload : Event ;
458498 simulationState : SimulationState ;
459499 templateContext : WebSocketEventTemplateContext ;
460500} ) => {
@@ -471,15 +511,15 @@ export const trackSimulationStateFromPayload = ({
471511
472512 registerUserAndMember ( {
473513 cid,
474- member : asJsonObject ( payload . member ) ,
514+ member : asChannelMemberResponse ( payload . member ) ,
475515 simulationState,
476- user : asJsonObject ( payload . user ) ,
516+ user : asUserResponse ( payload . user ) ,
477517 } ) ;
478518 registerUserAndMember ( {
479519 cid,
480- member : getMessageMember ( message ) ,
520+ member : asChannelMemberResponse ( getMessageMember ( message ) ) ,
481521 simulationState,
482- user : getMessageUser ( message ) ,
522+ user : asUserResponse ( getMessageUser ( message ) ) ,
483523 } ) ;
484524
485525 const channelObject = asJsonObject ( payload . channel ) ;
@@ -494,9 +534,9 @@ export const trackSimulationStateFromPayload = ({
494534
495535 registerUserAndMember ( {
496536 cid,
497- member,
537+ member : asChannelMemberResponse ( member ) ,
498538 simulationState,
499- user : asJsonObject ( member . user ) ,
539+ user : asUserResponse ( member . user ) ,
500540 } ) ;
501541 } ) ;
502542 }
@@ -511,18 +551,16 @@ export const emitWebSocketEventPayload = ({
511551} : {
512552 client : StreamChat ;
513553 eventType : SupportedWebsocketEventType ;
514- payload : JsonObject ;
554+ payload : EventPayload ;
515555 simulationState : SimulationState ;
516556 templateContext : WebSocketEventTemplateContext ;
517557} ) => {
518558 const emittedPayload = {
519559 ...payload ,
520560 type : eventType ,
521- } ;
561+ } as Event ;
522562
523- client . handleEvent ( {
524- data : JSON . stringify ( emittedPayload ) ,
525- } as HandleEventArgument ) ;
563+ client . dispatchEvent ( emittedPayload ) ;
526564
527565 trackSimulationStateFromPayload ( {
528566 payload : emittedPayload ,
0 commit comments