Skip to content

Commit b0fa4fd

Browse files
committed
fix: fix types for WebSocketEventPromptDialog
1 parent ac77e5b commit b0fa4fd

4 files changed

Lines changed: 105 additions & 49 deletions

File tree

examples/vite/src/AppSettings/ActionsMenu/WebSocketEventPromptDialog/WebSocketEventPromptDialog.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { ReactNode, Ref } from 'react';
22
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
3+
import type { Event } from 'stream-chat';
34
import {
45
Dropdown,
56
type DropdownTriggerProps,
@@ -808,7 +809,7 @@ export const WebSocketEventPromptDialog = ({
808809
throw new Error('Payload must be a JSON object');
809810
}
810811

811-
return parsedPayload as Record<string, unknown>;
812+
return parsedPayload as Partial<Event>;
812813
}, []);
813814

814815
const emitConfiguredEvent = useCallback(

examples/vite/src/AppSettings/ActionsMenu/WebSocketEventPromptDialog/types.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { ChannelMemberResponse, UserResponse } from 'stream-chat';
12
import type { SupportedWebsocketEventType } from './websocketEventTemplates';
23

34
export type PayloadMode = 'fixed' | 'fresh';
@@ -63,12 +64,12 @@ export type IntervalEmitter = {
6364

6465
export type DialogMode = 'single' | 'pipeline' | 'intervals';
6566

66-
export type SimulationUser = Record<string, unknown> & {
67-
id: string;
67+
export type SimulationUser = UserResponse & {
68+
invisible?: boolean;
6869
};
6970

7071
export type SimulationState = {
71-
membersByCid: Record<string, Record<string, Record<string, unknown>>>;
72+
membersByCid: Record<string, Record<string, ChannelMemberResponse>>;
7273
messageIdsByCid: Record<string, string[]>;
7374
nextReactionTypeIndex: number;
7475
nextSequence: number;

examples/vite/src/AppSettings/ActionsMenu/WebSocketEventPromptDialog/websocketEventAutomation.ts

Lines changed: 67 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
import type { Channel, Event, 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

311
import {
412
type SupportedWebsocketEventType,
@@ -7,7 +15,17 @@ import {
715
} from './websocketEventTemplates';
816
import type { SimulationState, SimulationUser } from './types';
917

10-
type JsonObject = Record<string, unknown>;
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+
};
1129

1230
const messageTextFragments = [
1331
'debug event payload',
@@ -19,12 +37,12 @@ const messageTextFragments = [
1937

2038
const reactionTypes = ['love', 'haha', 'wow', 'like', 'sad'] as const;
2139

22-
const asJsonObject = (value: unknown): JsonObject | undefined => {
40+
const asJsonObject = (value: unknown): UnknownRecord | undefined => {
2341
if (!value || typeof value !== 'object' || Array.isArray(value)) {
2442
return undefined;
2543
}
2644

27-
return value as JsonObject;
45+
return value as UnknownRecord;
2846
};
2947

3048
const getId = (value: unknown) => {
@@ -44,10 +62,33 @@ const getMessageUser = (message: unknown) => asJsonObject(asJsonObject(message)?
4462
const getMessageMember = (message: unknown) =>
4563
asJsonObject(asJsonObject(message)?.member);
4664

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+
4781
const buildRandomMessageText = (sequence: number) =>
4882
`${messageTextFragments[sequence % messageTextFragments.length]} #${sequence}`;
4983

50-
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+
> => {
5192
const reactionType = getId(reaction.type) ?? 'love';
5293
const reactionScore =
5394
typeof reaction.score === 'number' && Number.isFinite(reaction.score)
@@ -99,7 +140,7 @@ const getChannelMembersForCid = (
99140
cid: string,
100141
simulationState: SimulationState,
101142
templateContext: WebSocketEventTemplateContext,
102-
) => {
143+
): ChannelMemberResponse[] => {
103144
const knownMembers = Object.values(simulationState.membersByCid[cid] ?? {});
104145

105146
if (knownMembers.length > 0) {
@@ -121,7 +162,7 @@ const buildFreshContext = (
121162
templateContext,
122163
);
123164
const memberCount = channelMembers.length || templateContext.memberCount;
124-
const baseChannel = asJsonObject(templateContext.channel) ?? {};
165+
const baseChannel = templateContext.channel;
125166

126167
return {
127168
...templateContext,
@@ -211,9 +252,9 @@ const registerUserAndMember = ({
211252
user,
212253
}: {
213254
cid: string;
214-
member?: JsonObject;
255+
member?: ChannelMemberResponse;
215256
simulationState: SimulationState;
216-
user?: JsonObject;
257+
user?: UserResponse;
217258
}) => {
218259
if (user) {
219260
const userId = getUserId(user);
@@ -265,9 +306,9 @@ export const createInitialSimulationState = ({
265306

266307
registerUserAndMember({
267308
cid,
268-
member: templateContext.actorMember,
309+
member: templateContext.actorMember as ChannelMemberResponse,
269310
simulationState: state,
270-
user: templateContext.actor,
311+
user: templateContext.actor as UserResponse,
271312
});
272313
registerUserAndMember({
273314
cid,
@@ -283,9 +324,9 @@ export const createInitialSimulationState = ({
283324

284325
registerUserAndMember({
285326
cid,
286-
member: memberObject,
327+
member: asChannelMemberResponse(memberObject),
287328
simulationState: state,
288-
user: userObject,
329+
user: asUserResponse(userObject),
289330
});
290331
});
291332

@@ -304,9 +345,9 @@ export const createInitialSimulationState = ({
304345

305346
registerUserAndMember({
306347
cid,
307-
member: getMessageMember(messageObject),
348+
member: asChannelMemberResponse(getMessageMember(messageObject)),
308349
simulationState: state,
309-
user: getMessageUser(messageObject),
350+
user: asUserResponse(getMessageUser(messageObject)),
310351
});
311352
});
312353

@@ -321,11 +362,11 @@ export const buildFreshWebSocketEventPayload = ({
321362
eventType: SupportedWebsocketEventType;
322363
simulationState: SimulationState;
323364
templateContext: WebSocketEventTemplateContext;
324-
}): JsonObject => {
365+
}): EventPayload => {
325366
const freshContext = buildFreshContext(templateContext, simulationState);
326367
const basePayload = websocketEventTemplateDefinitions[eventType].buildDefault(
327368
freshContext,
328-
) as JsonObject;
369+
) as EventPayload;
329370

330371
switch (eventType) {
331372
case 'message.new':
@@ -470,15 +511,15 @@ export const trackSimulationStateFromPayload = ({
470511

471512
registerUserAndMember({
472513
cid,
473-
member: asJsonObject(payload.member),
514+
member: asChannelMemberResponse(payload.member),
474515
simulationState,
475-
user: asJsonObject(payload.user),
516+
user: asUserResponse(payload.user),
476517
});
477518
registerUserAndMember({
478519
cid,
479-
member: getMessageMember(message),
520+
member: asChannelMemberResponse(getMessageMember(message)),
480521
simulationState,
481-
user: getMessageUser(message),
522+
user: asUserResponse(getMessageUser(message)),
482523
});
483524

484525
const channelObject = asJsonObject(payload.channel);
@@ -493,9 +534,9 @@ export const trackSimulationStateFromPayload = ({
493534

494535
registerUserAndMember({
495536
cid,
496-
member,
537+
member: asChannelMemberResponse(member),
497538
simulationState,
498-
user: asJsonObject(member.user),
539+
user: asUserResponse(member.user),
499540
});
500541
});
501542
}
@@ -510,14 +551,14 @@ export const emitWebSocketEventPayload = ({
510551
}: {
511552
client: StreamChat;
512553
eventType: SupportedWebsocketEventType;
513-
payload: Event;
554+
payload: EventPayload;
514555
simulationState: SimulationState;
515556
templateContext: WebSocketEventTemplateContext;
516557
}) => {
517-
const emittedPayload: Event = {
558+
const emittedPayload = {
518559
...payload,
519560
type: eventType,
520-
};
561+
} as Event;
521562

522563
client.dispatchEvent(emittedPayload);
523564

examples/vite/src/AppSettings/ActionsMenu/WebSocketEventPromptDialog/websocketEventTemplates.ts

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
1-
import type { Channel, StreamChat } from 'stream-chat';
1+
import type {
2+
Channel,
3+
ChannelMemberResponse,
4+
ChannelResponse,
5+
StreamChat,
6+
UserResponse,
7+
} from 'stream-chat';
28

39
type JsonObject = Record<string, unknown>;
10+
type DebugUserResponse = UserResponse & { invisible?: boolean };
11+
type DebugChannelResponse = ChannelResponse & { name?: string };
412

513
export const supportedWebsocketEventTypes = [
614
'ai_indicator.clear',
@@ -84,11 +92,11 @@ export type WebSocketEventPresetOption = {
8492
};
8593

8694
export type WebSocketEventTemplateContext = {
87-
actor: JsonObject;
88-
actorMember: JsonObject;
95+
actor: DebugUserResponse;
96+
actorMember: ChannelMemberResponse;
8997
actorId: string;
90-
channel: JsonObject;
91-
channelMembers: JsonObject[];
98+
channel: DebugChannelResponse;
99+
channelMembers: ChannelMemberResponse[];
92100
channelId: string;
93101
channelName: string;
94102
channelType: string;
@@ -97,8 +105,8 @@ export type WebSocketEventTemplateContext = {
97105
lastReadAt: string;
98106
memberCount: number;
99107
messageId: string;
100-
otherMember: JsonObject;
101-
otherUser: JsonObject;
108+
otherMember: ChannelMemberResponse;
109+
otherUser: DebugUserResponse;
102110
parentMessageId: string;
103111
pollId: string;
104112
reactionType: string;
@@ -108,7 +116,11 @@ export type WebSocketEventTemplateContext = {
108116
watcherCount: number;
109117
};
110118

111-
const createFallbackUser = (id: string, createdAt: string): JsonObject => ({
119+
type BuildChannelSeedContext = Omit<WebSocketEventTemplateContext, 'channel'> & {
120+
channel: Partial<DebugChannelResponse>;
121+
};
122+
123+
const createFallbackUser = (id: string, createdAt: string): DebugUserResponse => ({
112124
banned: false,
113125
blocked_user_ids: [],
114126
created_at: createdAt,
@@ -124,10 +136,10 @@ const createFallbackUser = (id: string, createdAt: string): JsonObject => ({
124136
updated_at: createdAt,
125137
});
126138

127-
const getUserId = (user: JsonObject) =>
139+
const getUserId = (user: DebugUserResponse) =>
128140
typeof user.id === 'string' ? user.id : 'debug-user';
129141

130-
const createMember = (user: JsonObject): JsonObject => {
142+
const createMember = (user: DebugUserResponse): ChannelMemberResponse => {
131143
const createdAt =
132144
typeof user.created_at === 'string' ? user.created_at : new Date().toISOString();
133145

@@ -159,9 +171,9 @@ const getMemberUserId = (member: { user?: unknown; user_id?: unknown }) => {
159171
};
160172

161173
const buildChannel = (
162-
context: WebSocketEventTemplateContext,
174+
context: BuildChannelSeedContext,
163175
overrides: JsonObject = {},
164-
): JsonObject => {
176+
): DebugChannelResponse => {
165177
const createdAt = context.createdAt;
166178

167179
return {
@@ -235,6 +247,7 @@ const buildChannel = (
235247
hidden: false,
236248
id: context.channelId,
237249
last_message_at: createdAt,
250+
metadata: [],
238251
member_count: context.memberCount,
239252
members: context.channelMembers,
240253
name: context.channelName,
@@ -274,7 +287,7 @@ const buildNotificationChannelMutesUpdatedPayload = (
274287

275288
const buildMuteEntry = (
276289
context: WebSocketEventTemplateContext,
277-
target: JsonObject = context.otherUser,
290+
target: DebugUserResponse = context.otherUser,
278291
overrides: JsonObject = {},
279292
): JsonObject => ({
280293
created_at: context.createdAt,
@@ -749,7 +762,7 @@ export const createWebSocketEventTemplateContext = ({
749762
const createdAt = new Date().toISOString();
750763
const actorUser =
751764
client.user && typeof client.user === 'object'
752-
? ({ ...client.user } as JsonObject)
765+
? ({ ...client.user } as DebugUserResponse)
753766
: createFallbackUser('debug-user', createdAt);
754767
const actorId = typeof actorUser.id === 'string' ? actorUser.id : 'debug-user';
755768

@@ -758,24 +771,24 @@ export const createWebSocketEventTemplateContext = ({
758771
(member) => getMemberUserId(member) === actorId,
759772
);
760773
const actorMember = actorMemberFromChannel
761-
? ({ ...actorMemberFromChannel } as JsonObject)
774+
? ({ ...actorMemberFromChannel } as ChannelMemberResponse)
762775
: createMember(actorUser);
763776

764777
const otherMemberFromChannel = members.find(
765778
(member) => getMemberUserId(member) !== actorId,
766779
);
767780
const otherUser =
768781
otherMemberFromChannel?.user && typeof otherMemberFromChannel.user === 'object'
769-
? ({ ...otherMemberFromChannel.user } as JsonObject)
782+
? ({ ...otherMemberFromChannel.user } as DebugUserResponse)
770783
: createFallbackUser('debug-other-user', createdAt);
771784
const otherMember = otherMemberFromChannel
772-
? ({ ...otherMemberFromChannel } as JsonObject)
785+
? ({ ...otherMemberFromChannel } as ChannelMemberResponse)
773786
: createMember(otherUser);
774787
const channelMembers = (
775788
members.length
776-
? members.map((member) => ({ ...member }) as JsonObject)
789+
? members.map((member) => ({ ...member }) as ChannelMemberResponse)
777790
: [actorMember, otherMember]
778-
) as JsonObject[];
791+
) as ChannelMemberResponse[];
779792

780793
const channelData = channel?.data as
781794
| {

0 commit comments

Comments
 (0)