Skip to content

Commit

Permalink
Cleanup and general fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
arnautov-anton committed Jan 31, 2025
1 parent d17fc82 commit fe6b938
Show file tree
Hide file tree
Showing 10 changed files with 43 additions and 91 deletions.
24 changes: 8 additions & 16 deletions src/channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ import {
MessageOptions,
PushPreference,
UpdateChannelOptions,
CustomChannelType,
} from './types';
import { Role } from './permissions';
import { DEFAULT_QUERY_CHANNEL_MESSAGE_LIST_PAGE_SIZE } from './constants';
Expand All @@ -71,8 +72,8 @@ export class Channel {
_client: StreamChat;
type: string;
id: string | undefined;
data: ChannelData | ChannelResponse | undefined;
_data: ChannelData | ChannelResponse;
data: Partial<ChannelData & ChannelResponse> | undefined;
_data: Partial<ChannelData & ChannelResponse>;
cid: string;
/** */
listeners: { [key: string]: (string | EventHandler)[] };
Expand Down Expand Up @@ -371,12 +372,13 @@ export class Channel {
* @return {Promise<UpdateChannelAPIResponse>} The server response
*/
async update(
channelData: Partial<ChannelData> | Partial<ChannelResponse> = {},
channelData: Partial<ChannelData & ChannelResponse> = {},
updateMessage?: Message,
options?: ChannelUpdateOptions,
) {
// Strip out reserved names that will result in API errors.
const reserved = [
// TODO: this needs to be typed better
const reserved: Exclude<keyof (ChannelResponse & ChannelData), keyof CustomChannelType>[] = [
'config',
'cid',
'created_by',
Expand All @@ -388,8 +390,8 @@ export class Channel {
'last_message_at',
'own_capabilities',
];

reserved.forEach((key) => {
// @ts-expect-error certain keys don't exist
delete channelData[key];
});

Expand All @@ -412,15 +414,13 @@ export class Channel {

const areCapabilitiesChanged =
[...(data.channel.own_capabilities || [])].sort().join() !==
// @ts-expect-error capabilities do not exist on channel
[...(Array.isArray(this.data?.own_capabilities) ? (this.data?.own_capabilities as string[]) : [])].sort().join();
this.data = data.channel;
// If the capabiltities are changed, we trigger the `capabilities.changed` event.
if (areCapabilitiesChanged) {
this.getClient().dispatchEvent({
type: 'capabilities.changed',
cid: this.cid,
// @ts-expect-error capabilities do not exist on channel
own_capabilities: data.channel.own_capabilities,
});
}
Expand Down Expand Up @@ -1050,7 +1050,6 @@ export class Channel {
if (message.user?.id && this.getClient().userMuteStatus(message.user.id)) return false;

// Return false if channel doesn't allow read events.
// @ts-expect-error capabilities
if (Array.isArray(this.data?.own_capabilities) && !this.data?.own_capabilities.includes('read-events')) {
return false;
}
Expand Down Expand Up @@ -1185,16 +1184,14 @@ export class Channel {

const areCapabilitiesChanged =
[...(state.channel.own_capabilities || [])].sort().join() !==
// @ts-expect-error capabilities
[...(Array.isArray(this.data?.own_capabilities) ? (this.data?.own_capabilities as string[]) : [])].sort().join();
[...(this.data && Array.isArray(this.data?.own_capabilities) ? this.data.own_capabilities : [])].sort().join();
this.data = state.channel;
this.offlineMode = false;

if (areCapabilitiesChanged) {
this.getClient().dispatchEvent({
type: 'capabilities.changed',
cid: this.cid,
// @ts-expect-error capabilities
own_capabilities: state.channel.own_capabilities,
});
}
Expand Down Expand Up @@ -1569,16 +1566,13 @@ export class Channel {
}
case 'channel.updated':
if (event.channel) {
// @ts-expect-error frozen
const isFrozenChanged = event.channel?.frozen !== undefined && event.channel.frozen !== channel.data?.frozen;
if (isFrozenChanged) {
this.query({ state: false, messages: { limit: 0 }, watchers: { limit: 0 } });
}
channel.data = {
...event.channel,
// @ts-expect-error hidden
hidden: event.channel?.hidden ?? channel.data?.hidden,
// @ts-expect-error capabilities
own_capabilities: event.channel?.own_capabilities ?? channel.data?.own_capabilities,
};
}
Expand Down Expand Up @@ -1612,9 +1606,7 @@ export class Channel {
if (!event.user?.id) break;
channelState.members[event.user.id] = {
...(channelState.members[event.user.id] || {}),
// @ts-expect-error shadow
shadow_banned: !!event.shadow,
// @ts-expect-error shadow
banned: !event.shadow,
user: { ...(channelState.members[event.user.id]?.user || {}), ...event.user },
};
Expand Down
33 changes: 6 additions & 27 deletions src/channel_state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,11 +280,7 @@ export class ChannelState {
this.pinnedMessages = result;
}

addReaction(
reaction: ReactionResponse,
message?: MessageResponse,
enforce_unique?: boolean,
) {
addReaction(reaction: ReactionResponse, message?: MessageResponse, enforce_unique?: boolean) {
if (!message) return;
const messageWithReaction = message;
this._updateMessage(message, (msg) => {
Expand Down Expand Up @@ -313,10 +309,7 @@ export class ChannelState {
return ownReactions;
}

_removeOwnReactionFromMessage(
ownReactions: ReactionResponse[] | null | undefined,
reaction: ReactionResponse,
) {
_removeOwnReactionFromMessage(ownReactions: ReactionResponse[] | null | undefined, reaction: ReactionResponse) {
if (ownReactions) {
return ownReactions.filter((item) => item.user_id !== reaction.user_id || item.type !== reaction.type);
}
Expand All @@ -333,13 +326,7 @@ export class ChannelState {
return messageWithReaction;
}

_updateQuotedMessageReferences({
message,
remove,
}: {
message: MessageResponse;
remove?: boolean;
}) {
_updateQuotedMessageReferences({ message, remove }: { message: MessageResponse; remove?: boolean }) {
const parseMessage = (m: ReturnType<ChannelState['formatMessage']>) =>
(({
...m,
Expand Down Expand Up @@ -382,9 +369,7 @@ export class ChannelState {
pinned?: boolean;
show_in_channel?: boolean;
},
updateFunc: (
msg: ReturnType<ChannelState['formatMessage']>,
) => ReturnType<ChannelState['formatMessage']>,
updateFunc: (msg: ReturnType<ChannelState['formatMessage']>) => ReturnType<ChannelState['formatMessage']>,
) {
const { parent_id, show_in_channel, pinned } = message;

Expand Down Expand Up @@ -495,10 +480,7 @@ export class ChannelState {
* @param {UserResponse} user
*/
updateUserMessages = (user: UserResponse) => {
const _updateUserMessages = (
messages: Array<ReturnType<ChannelState['formatMessage']>>,
user: UserResponse,
) => {
const _updateUserMessages = (messages: Array<ReturnType<ChannelState['formatMessage']>>, user: UserResponse) => {
for (let i = 0; i < messages.length; i++) {
const m = messages[i];
if (m.user?.id === user.id) {
Expand Down Expand Up @@ -701,10 +683,7 @@ export class ChannelState {
addIfDoesNotExist = true,
messageSetToAddToIfDoesNotExist: MessageSetType = 'current',
) {
let messagesToAdd: (
| MessageResponse
| ReturnType<ChannelState['formatMessage']>
)[] = newMessages;
let messagesToAdd: (MessageResponse | ReturnType<ChannelState['formatMessage']>)[] = newMessages;
let targetMessageSetIndex!: number;
if (addIfDoesNotExist) {
const overlappingMessageSetIndices = this.messageSets
Expand Down
14 changes: 5 additions & 9 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,6 @@ import {
ListImportsResponse,
Logger,
MarkChannelsReadOptions,
Message,
MessageFilters,
MessageFlagsFilters,
MessageFlagsPaginationOptions,
Expand Down Expand Up @@ -1250,12 +1249,11 @@ export class StreamChat {
}

/** Updating only available properties in _user object. */
for (const key in event.user) {
if (_user && key in _user) {
const updateKey = key as keyof typeof event.user;
for (const key in _user) {
const updateKey = key as keyof typeof _user;

// TODO: revisit
// @ts-expect-error ???
if (updateKey in event.user) {
// @ts-expect-error it has an issue with this, not sure why
_user[updateKey] = event.user[updateKey];
}
}
Expand Down Expand Up @@ -2612,8 +2610,7 @@ export class StreamChat {
throw Error('Please specify the message id when calling updateMessage');
}

// FIXME: brother in fucking christ
const clonedMessage: Partial<UpdatedMessage & { __html: string }> = { ...message };
const clonedMessage: Partial<UpdatedMessage> = { ...message };
delete clonedMessage.id;

const reservedMessageFields: Array<ReservedMessageFields> = [
Expand All @@ -2628,7 +2625,6 @@ export class StreamChat {
'type',
'updated_at',
'user',
'__html',
];

reservedMessageFields.forEach(function (item) {
Expand Down
5 changes: 4 additions & 1 deletion src/connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,10 @@ export class StableWSConnection {
this.client.insightMetrics.wsConsecutiveFailures++;
this.client.insightMetrics.wsTotalFailures++;

const insights = buildWsFatalInsight((this as unknown) as StableWSConnection, convertErrorToJson(error as Error));
const insights = buildWsFatalInsight(
(this as unknown) as StableWSConnection,
convertErrorToJson(error as Error),
);
postInsights?.('ws_fatal', insights);
}
throw error;
Expand Down
11 changes: 4 additions & 7 deletions src/moderation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,10 @@ export class Moderation {
* @returns
*/
async muteUser(targetID: string, options: ModerationMuteOptions = {}) {
return await this.client.post<MuteUserResponse & APIResponse>(
this.client.baseURL + '/api/v2/moderation/mute',
{
target_ids: [targetID],
...options,
},
);
return await this.client.post<MuteUserResponse & APIResponse>(this.client.baseURL + '/api/v2/moderation/mute', {
target_ids: [targetID],
...options,
});
}

/**
Expand Down
30 changes: 10 additions & 20 deletions src/poll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,22 +48,13 @@ type PollVoteCastedRemoved = PollVoteEvent & {
type: 'poll.vote_removed';
};

const isPollUpdatedEvent = (e: Event): e is PollUpdatedEvent =>
e.type === 'poll.updated';
const isPollClosedEventEvent = (e: Event): e is PollClosedEvent =>
e.type === 'poll.closed';
const isPollVoteCastedEvent = (e: Event): e is PollVoteCastedEvent =>
e.type === 'poll.vote_casted';
const isPollVoteChangedEvent = (
e: Event,
): e is PollVoteCastedChanged => e.type === 'poll.vote_changed';
const isPollVoteRemovedEvent = (
e: Event,
): e is PollVoteCastedRemoved => e.type === 'poll.vote_removed';

export const isVoteAnswer = (
vote: PollVote | PollAnswer,
): vote is PollAnswer => !!(vote as PollAnswer)?.answer_text;
const isPollUpdatedEvent = (e: Event): e is PollUpdatedEvent => e.type === 'poll.updated';
const isPollClosedEventEvent = (e: Event): e is PollClosedEvent => e.type === 'poll.closed';
const isPollVoteCastedEvent = (e: Event): e is PollVoteCastedEvent => e.type === 'poll.vote_casted';
const isPollVoteChangedEvent = (e: Event): e is PollVoteCastedChanged => e.type === 'poll.vote_changed';
const isPollVoteRemovedEvent = (e: Event): e is PollVoteCastedRemoved => e.type === 'poll.vote_removed';

export const isVoteAnswer = (vote: PollVote | PollAnswer): vote is PollAnswer => !!(vote as PollAnswer)?.answer_text;

export type PollAnswersQueryParams = {
filter?: QueryVotesFilters;
Expand All @@ -79,7 +70,8 @@ export type PollOptionVotesQueryParams = {

type OptionId = string;

export type PollState = CustomPollType &
// FIXME: ideally this would work without the unknown record...
export type PollState = (CustomPollType & Record<string, unknown>) &
Omit<PollResponse, 'own_votes' | 'id'> & {
lastActivityAt: Date; // todo: would be ideal to get this from the BE
maxVotedOptionIds: OptionId[];
Expand Down Expand Up @@ -381,9 +373,7 @@ function getOwnVotesByOptionId(ownVotes: PollVote[]) {
}, {});
}

export function extractPollData(
pollResponse: PollResponse,
): PollData {
export function extractPollData(pollResponse: PollResponse): PollData {
return {
allow_answers: pollResponse.allow_answers,
allow_user_suggested_options: pollResponse.allow_user_suggested_options,
Expand Down
6 changes: 1 addition & 5 deletions src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@ function isPatch<T>(value: T | Patch<T>): value is Patch<T> {
return typeof value === 'function';
}

// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface EmptyInterface {}
type StateShape = Record<string, unknown> | EmptyInterface;

export class StateStore<T extends StateShape> {
export class StateStore<T extends Record<string, unknown>> {
private handlerSet = new Set<Handler<T>>();

private static logCount = 5;
Expand Down
2 changes: 1 addition & 1 deletion src/token_manager.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Secret } from 'jsonwebtoken';
import { UserFromToken, JWTServerToken, JWTUserToken } from './signing';
import { isFunction } from './utils';
import { TokenOrProvider, UserResponse } from './types';
import { TokenOrProvider, UserResponse } from './types';

/**
* TokenManager
Expand Down
5 changes: 3 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1253,6 +1253,7 @@ export type Event = CustomEventType & {
message_id?: string;
mode?: string;
online?: boolean;
own_capabilities?: string[];
parent_id?: string;
poll?: PollResponse;
poll_vote?: PollVote | PollAnswer;
Expand All @@ -1262,6 +1263,7 @@ export type Event = CustomEventType & {
};
reaction?: ReactionResponse;
received_at?: string | Date;
shadow?: boolean;
team?: string;
thread?: ThreadResponse;
// @deprecated number of all unread messages across all current user's unread channels, equals unread_count
Expand Down Expand Up @@ -2619,8 +2621,7 @@ export type ReservedMessageFields =
| 'reply_count'
| 'type'
| 'updated_at'
| 'user'
| '__html';
| 'user';

export type UpdatedMessage = Omit<MessageResponse, 'mentioned_users'> & { mentioned_users?: string[] };

Expand Down
4 changes: 1 addition & 3 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -721,9 +721,7 @@ const messagePaginationLinear = ({
return newPagination;
};

export const messageSetPagination = (
params: MessagePaginationUpdatedParams,
) => {
export const messageSetPagination = (params: MessagePaginationUpdatedParams) => {
if (params.parentSet.messages.length < params.returnedPage.length) {
params.logger?.('error', 'Corrupted message set state: parent set size < returned page size');
return params.parentSet.pagination;
Expand Down

0 comments on commit fe6b938

Please sign in to comment.