stream-chat
Version:
JS SDK for the Stream Chat API
1,866 lines (1,686 loc) • 112 kB
text/typescript
import type { EVENT_MAP } from './events';
import type { Channel } from './channel';
import type { AxiosRequestConfig, AxiosResponse } from 'axios';
import type { StableWSConnection } from './connection';
import type { Role } from './permissions';
import type {
CustomAttachmentData,
CustomChannelData,
CustomCommandData,
CustomEventData,
CustomMemberData,
CustomMessageData,
CustomPollData,
CustomPollOptionData,
CustomReactionData,
CustomThreadData,
CustomUserData,
} from './custom_types';
import type { NotificationManager } from './notifications';
import type { RESERVED_UPDATED_MESSAGE_FIELDS } from './constants';
/**
* Utility Types
*/
export type Readable<T> = {
[key in keyof T]: T[key];
} & {};
export type ArrayOneOrMore<T> = {
0: T;
} & Array<T>;
export type ArrayTwoOrMore<T> = {
0: T;
1: T;
} & Array<T>;
export type KnownKeys<T> = {
[K in keyof T]: string extends K ? never : number extends K ? never : K;
} extends { [_ in keyof T]: infer U }
? U
: never;
export type RequireAtLeastOne<T> = {
[K in keyof T]-?: Required<Pick<T, K>> & Partial<Omit<T, K>>;
}[keyof T];
export type RequireOnlyOne<T, Keys extends keyof T = keyof T> = Omit<T, Keys> &
{
[K in Keys]-?: Required<Pick<T, K>> & Partial<Record<Exclude<Keys, K>, undefined>>;
}[Keys];
export type PartializeKeys<T, K extends keyof T> = Partial<Pick<T, K>> & Omit<T, K>;
/* Unknown Record */
export type UR = Record<string, unknown>;
export type UnknownType = UR; //alias to avoid breaking change
export type Unpacked<T> = T extends (infer U)[]
? U // eslint-disable-next-line @typescript-eslint/no-explicit-any
: T extends (...args: any[]) => infer U
? U
: T extends Promise<infer U>
? U
: T;
/**
* Response Types
*/
export type APIResponse = {
duration: string;
};
export type TranslateResponse = {
language: string;
translated_text: string;
};
export type AppSettingsAPIResponse = APIResponse & {
app?: {
// TODO
// eslint-disable-next-line @typescript-eslint/no-explicit-any
call_types: any;
channel_configs: Record<
string,
{
reminders: boolean;
automod?: ChannelConfigAutomod;
automod_behavior?: ChannelConfigAutomodBehavior;
automod_thresholds?: ChannelConfigAutomodThresholds;
blocklist_behavior?: ChannelConfigAutomodBehavior;
commands?: CommandVariants[];
connect_events?: boolean;
created_at?: string;
custom_events?: boolean;
delivery_events?: boolean;
mark_messages_pending?: boolean;
max_message_length?: number;
message_retention?: string;
mutes?: boolean;
name?: string;
polls?: boolean;
push_notifications?: boolean;
quotes?: boolean;
reactions?: boolean;
read_events?: boolean;
replies?: boolean;
search?: boolean;
typing_events?: boolean;
updated_at?: string;
uploads?: boolean;
url_enrichment?: boolean;
user_message_reminders?: boolean;
}
>;
reminders_interval: number;
async_moderation_config?: AsyncModerationOptions;
async_url_enrich_enabled?: boolean;
auto_translation_enabled?: boolean;
before_message_send_hook_url?: string;
campaign_enabled?: boolean;
cdn_expiration_seconds?: number;
custom_action_handler_url?: string;
datadog_info?: {
api_key: string;
site: string;
enabled?: boolean;
};
disable_auth_checks?: boolean;
disable_permissions_checks?: boolean;
enforce_unique_usernames?: 'no' | 'app' | 'team';
event_hooks?: Array<EventHook>;
file_upload_config?: FileUploadConfig;
geofences?: Array<{
country_codes: Array<string>;
description: string;
name: string;
type: string;
}>;
grants?: Record<string, string[]>;
image_moderation_enabled?: boolean;
image_upload_config?: FileUploadConfig;
multi_tenant_enabled?: boolean;
name?: string;
organization?: string;
permission_version?: string;
policies?: Record<string, Policy[]>;
poll_enabled?: boolean;
push_notifications?: {
offline_only: boolean;
version: string;
apn?: APNConfig;
firebase?: FirebaseConfig;
huawei?: HuaweiConfig;
providers?: PushProviderConfig[];
xiaomi?: XiaomiConfig;
};
revoke_tokens_issued_before?: string | null;
search_backend?: 'disabled' | 'elasticsearch' | 'postgres';
sns_key?: string;
sns_secret?: string;
sns_topic_arn?: string;
sqs_key?: string;
sqs_secret?: string;
sqs_url?: string;
suspended?: boolean;
suspended_explanation?: string;
user_search_disallowed_roles?: string[] | null;
video_provider?: string;
webhook_events?: Array<string>;
webhook_url?: string;
};
};
export type ModerationResult = {
action: string;
created_at: string;
message_id: string;
updated_at: string;
user_bad_karma: boolean;
user_karma: number;
blocked_word?: string;
blocklist_name?: string;
moderated_by?: string;
};
export type AutomodDetails = {
action?: string;
image_labels?: Array<string>;
original_message_type?: string;
result?: ModerationResult;
};
export type FlagDetails = {
automod?: AutomodDetails;
};
export type Flag = {
created_at: string;
created_by_automod: boolean;
updated_at: string;
details?: FlagDetails;
target_message?: MessageResponse;
target_user?: UserResponse;
user?: UserResponse;
};
export type FlagsResponse = APIResponse & {
flags?: Array<Flag>;
};
export type MessageFlagsResponse = APIResponse & {
flags?: Array<{
message: MessageResponse;
user: UserResponse;
approved_at?: string;
created_at?: string;
created_by_automod?: boolean;
moderation_result?: ModerationResult;
rejected_at?: string;
reviewed_at?: string;
reviewed_by?: UserResponse;
updated_at?: string;
}>;
};
export type FlagReport = {
flags_count: number;
id: string;
message: MessageResponse;
user: UserResponse;
created_at?: string;
details?: FlagDetails;
first_reporter?: UserResponse;
review_result?: string;
reviewed_at?: string;
reviewed_by?: UserResponse;
updated_at?: string;
};
export type FlagReportsResponse = APIResponse & {
flag_reports: Array<FlagReport>;
};
export type ReviewFlagReportResponse = APIResponse & {
flag_report: FlagReport;
};
export type BannedUsersResponse = APIResponse & {
bans?: Array<{
user: UserResponse;
banned_by?: UserResponse;
channel?: ChannelResponse;
expires?: string;
ip_ban?: boolean;
reason?: string;
timeout?: number;
}>;
};
export type BlockListResponse = BlockList & {
created_at?: string;
type?: string;
updated_at?: string;
};
export type ChannelResponse = CustomChannelData & {
cid: string;
disabled: boolean;
frozen: boolean;
id: string;
type: string;
blocked?: boolean;
auto_translation_enabled?: boolean;
auto_translation_language?: TranslationLanguages;
hide_messages_before?: string;
config?: ChannelConfigWithInfo;
cooldown?: number;
created_at?: string;
created_by?: UserResponse | null;
created_by_id?: string;
deleted_at?: string;
hidden?: boolean;
invites?: string[];
joined?: boolean;
last_message_at?: string;
member_count?: number;
members?: ChannelMemberResponse[];
message_count?: number;
muted?: boolean;
mute_expires_at?: string;
own_capabilities?: string[];
team?: string;
truncated_at?: string;
truncated_by?: UserResponse;
truncated_by_id?: string;
updated_at?: string;
};
export type QueryReactionsOptions = Pager;
export type QueryReactionsAPIResponse = APIResponse & {
reactions: ReactionResponse[];
next?: string;
};
export type QueryChannelsAPIResponse = APIResponse & {
channels: Omit<ChannelAPIResponse, keyof APIResponse>[];
};
export type QueryChannelAPIResponse = APIResponse & ChannelAPIResponse;
export type ChannelAPIResponse = {
channel: ChannelResponse;
members: ChannelMemberResponse[];
messages: MessageResponse[];
pinned_messages: MessageResponse[];
draft?: DraftResponse;
hidden?: boolean;
membership?: ChannelMemberResponse | null;
pending_messages?: PendingMessageResponse[];
push_preferences?: PushPreference;
read?: ReadResponse[];
threads?: ThreadResponse[];
watcher_count?: number;
watchers?: UserResponse[];
active_live_locations?: SharedLocationResponse[];
};
export type ChannelUpdateOptions = {
hide_history?: boolean;
skip_push?: boolean;
};
export type ChannelMemberAPIResponse = APIResponse & {
members: ChannelMemberResponse[];
};
export type ChannelMemberUpdates = CustomMemberData & {
archived?: boolean;
channel_role?: Role;
pinned?: boolean;
};
export type ChannelMemberResponse = CustomMemberData & {
archived_at?: string | null;
ban_expires?: string;
banned?: boolean;
channel_role?: Role;
created_at?: string;
invite_accepted_at?: string;
invite_rejected_at?: string;
invited?: boolean;
is_moderator?: boolean;
notifications_muted?: boolean;
pinned_at?: string | null;
role?: string;
shadow_banned?: boolean;
status?: InviteStatus;
updated_at?: string;
user?: UserResponse;
user_id?: string;
};
export type PartialUpdateMemberAPIResponse = APIResponse & {
channel_member: ChannelMemberResponse;
};
export type CheckPushResponse = APIResponse & {
device_errors?: {
[deviceID: string]: {
error_message?: string;
provider?: PushProvider;
provider_name?: string;
};
};
general_errors?: string[];
rendered_apn_template?: string;
rendered_firebase_template?: string;
rendered_message?: {};
skip_devices?: boolean;
};
export type CheckSQSResponse = APIResponse & {
status: string;
data?: {};
error?: string;
};
export type CheckSNSResponse = APIResponse & {
status: string;
data?: {};
error?: string;
};
export type CommandResponse = Partial<CreatedAtUpdatedAt> & {
args?: string;
description?: string;
name?: CommandVariants;
set?: CommandVariants;
};
export type ConnectAPIResponse = Promise<void | ConnectionOpen>;
export type CreateChannelResponse = APIResponse &
Omit<CreateChannelOptions, 'client_id' | 'connection_id'> & {
created_at: string;
updated_at: string;
grants?: Record<string, string[]>;
};
export type CreateCommandResponse = APIResponse & {
command: CreateCommandOptions & CreatedAtUpdatedAt;
};
export type DeleteChannelAPIResponse = APIResponse & {
channel: ChannelResponse;
};
export type DeleteCommandResponse = APIResponse & {
name?: CommandVariants;
};
export type EventAPIResponse = APIResponse & {
event: Event;
};
export type ExportChannelResponse = {
task_id: string;
};
export type ExportUsersResponse = {
task_id: string;
};
export type ExportChannelStatusResponse = {
created_at?: string;
error?: {};
result?: {};
updated_at?: string;
};
export type FlagMessageResponse = APIResponse & {
flag: {
created_at: string;
created_by_automod: boolean;
target_message_id: string;
updated_at: string;
user: UserResponse;
approved_at?: string;
channel_cid?: string;
details?: object; // Any JSON
message_user_id?: string;
rejected_at?: string;
reviewed_at?: string;
reviewed_by?: string;
};
review_queue_item_id?: string;
};
export type FlagUserResponse = APIResponse & {
flag: {
created_at: string;
created_by_automod: boolean;
target_user: UserResponse;
updated_at: string;
user: UserResponse;
approved_at?: string;
details?: object; // Any JSON
rejected_at?: string;
reviewed_at?: string;
reviewed_by?: string;
};
review_queue_item_id?: string;
};
export type LocalMessageBase = Omit<
MessageResponseBase,
'created_at' | 'deleted_at' | 'pinned_at' | 'status' | 'updated_at'
> & {
created_at: Date;
deleted_at: Date | null;
pinned_at: Date | null;
status: string;
updated_at: Date;
};
export type LocalMessage = LocalMessageBase & {
error?: ErrorFromResponse<APIErrorResponse>;
quoted_message?: LocalMessageBase;
};
/**
* @deprecated in favor of LocalMessage
*/
export type FormatMessageResponse = LocalMessage;
export type GetCommandResponse = APIResponse & CreateCommandOptions & CreatedAtUpdatedAt;
export type GetMessageAPIResponse = SendMessageAPIResponse;
export interface ThreadResponse extends CustomThreadData {
// FIXME: according to OpenAPI, `channel` could be undefined but since cid is provided I'll asume that it's wrong
channel: ChannelResponse;
channel_cid: string;
created_at: string;
created_by_user_id: string;
latest_replies: Array<MessageResponse>;
parent_message: MessageResponse;
parent_message_id: string;
title: string;
updated_at: string;
active_participant_count?: number;
created_by?: UserResponse;
deleted_at?: string;
draft?: DraftResponse;
last_message_at?: string;
participant_count?: number;
read?: Array<ReadResponse>;
reply_count?: number;
thread_participants?: Array<{
channel_cid: string;
created_at: string;
last_read_at: string;
last_thread_message_at?: string;
left_thread_at?: string;
thread_id?: string;
user?: UserResponse;
user_id?: string;
}>;
// TODO: when moving to API v2 we should do this instead
// custom: CustomThreadType;
}
// TODO: Figure out a way to strongly type set and unset.
export type PartialThreadUpdate = {
set?: Partial<Record<string, unknown>>;
unset?: Array<string>;
};
export type QueryThreadsOptions = {
filter?: ThreadFilters;
limit?: number;
member_limit?: number;
next?: string;
participant_limit?: number;
reply_limit?: number;
sort?: ThreadSort;
watch?: boolean;
};
export type QueryThreadsAPIResponse = APIResponse & {
threads: ThreadResponse[];
next?: string;
};
export type GetThreadOptions = {
member_limit?: number;
participant_limit?: number;
reply_limit?: number;
watch?: boolean;
};
export type GetThreadAPIResponse = APIResponse & {
thread: ThreadResponse;
};
export type GetMultipleMessagesAPIResponse = APIResponse & {
messages: MessageResponse[];
};
export type GetRateLimitsResponse = APIResponse & {
android?: RateLimitsMap;
ios?: RateLimitsMap;
server_side?: RateLimitsMap;
web?: RateLimitsMap;
};
export enum Product {
Chat = 'chat',
Video = 'video',
Moderation = 'moderation',
Feeds = 'feeds',
}
export type HookEvent = {
name: string;
description: string;
products: Product[];
};
export type GetHookEventsResponse = APIResponse & {
events: HookEvent[];
};
export type GetReactionsAPIResponse = APIResponse & {
reactions: ReactionResponse[];
};
export type GetRepliesAPIResponse = APIResponse & {
messages: MessageResponse[];
};
export type GetUnreadCountAPIResponse = APIResponse & {
channel_type: {
channel_count: number;
channel_type: string;
unread_count: number;
}[];
channels: {
channel_id: string;
last_read: string;
unread_count: number;
}[];
threads: {
last_read: string;
last_read_message_id: string;
parent_message_id: string;
unread_count: number;
}[];
total_unread_count: number;
total_unread_threads_count: number;
total_unread_count_by_team?: Record<string, number>;
};
export type ChatLevelPushPreference = 'all' | 'none' | 'mentions' | (string & {});
export type PushPreference = {
callLevel?: 'all' | 'none' | (string & {});
chatLevel?: ChatLevelPushPreference;
disabledUntil?: string; // snooze till this time
removeDisable?: boolean; // Temporary flag for resetting disabledUntil
};
export type ChannelPushPreference = {
chatLevel?: ChatLevelPushPreference; // "all", "none", "mentions", or other custom strings
disabledUntil?: string;
removeDisable?: boolean; // Temporary flag for resetting disabledUntil
};
export type UpsertPushPreferencesResponse = APIResponse & {
// Mapping of user IDs to their push preferences
userChannelPreferences: Record<string, Record<string, ChannelPushPreference>>;
userPreferences: Record<string, PushPreference>; // Mapping of user -> channel id -> push preferences
};
export type GetUnreadCountBatchAPIResponse = APIResponse & {
counts_by_user: { [userId: string]: GetUnreadCountAPIResponse };
};
export type ListChannelResponse = APIResponse & {
channel_types: Record<
string,
Omit<CreateChannelOptions, 'client_id' | 'connection_id' | 'commands'> & {
commands: CommandResponse[];
created_at: string;
updated_at: string;
grants?: Record<string, string[]>;
}
>;
};
export type ListChannelTypesAPIResponse = ListChannelResponse;
export type ListCommandsResponse = APIResponse & {
commands: Array<CreateCommandOptions & Partial<CreatedAtUpdatedAt>>;
};
export type MuteChannelAPIResponse = APIResponse & {
channel_mute: ChannelMute;
own_user: OwnUserResponse;
channel_mutes?: ChannelMute[];
mute?: MuteResponse;
};
export type MessageResponse = MessageResponseBase & {
quoted_message?: MessageResponseBase;
};
export type MessageResponseBase = MessageBase & {
type: MessageLabel;
args?: string;
before_message_send_failed?: boolean;
channel?: ChannelResponse;
cid?: string;
command?: string;
command_info?: { name?: string };
created_at?: string;
deleted_at?: string;
deleted_reply_count?: number;
i18n?: RequireAtLeastOne<Record<`${TranslationLanguages}_text`, string>> & {
language: TranslationLanguages;
};
latest_reactions?: ReactionResponse[];
member?: ChannelMemberResponse;
mentioned_users?: UserResponse[];
message_text_updated_at?: string;
moderation?: ModerationResponse; // present only with Moderation v2
moderation_details?: ModerationDetailsResponse; // present only with Moderation v1
own_reactions?: ReactionResponse[] | null;
pin_expires?: string | null;
pinned_at?: string | null;
pinned_by?: UserResponse | null;
poll?: PollResponse;
reaction_counts?: { [key: string]: number } | null;
reaction_groups?: { [key: string]: ReactionGroupResponse } | null;
reaction_scores?: { [key: string]: number } | null;
reminder?: ReminderResponseBase;
reply_count?: number;
shadowed?: boolean;
shared_location?: SharedLocationResponse;
status?: string;
thread_participants?: UserResponse[];
updated_at?: string;
deleted_for_me?: boolean;
};
export type ReactionGroupResponse = {
count: number;
sum_scores: number;
first_reaction_at?: string;
last_reaction_at?: string;
};
export type ModerationDetailsResponse = {
action: 'MESSAGE_RESPONSE_ACTION_BOUNCE' | (string & {});
error_msg: string;
harms: ModerationHarmResponse[];
original_text: string;
};
export type ModerationHarmResponse = {
name: string;
phrase_list_ids: number[];
};
export type ModerationAction = 'bounce' | 'flag' | 'remove' | 'shadow';
export type ModerationResponse = {
action: ModerationAction;
original_text: string;
};
export type MuteResponse = {
user: UserResponse;
created_at?: string;
expires?: string;
target?: UserResponse;
updated_at?: string;
};
export type MuteUserResponse = APIResponse & {
mute?: MuteResponse;
mutes?: Array<Mute>;
own_user?: OwnUserResponse;
};
export type BlockUserAPIResponse = APIResponse & {
blocked_at: string;
blocked_by_user_id: string;
blocked_user_id: string;
};
export type GetBlockedUsersAPIResponse = APIResponse & {
blocks: BlockedUserDetails[];
};
export type BlockedUserDetails = APIResponse & {
blocked_user: UserResponse;
blocked_user_id: string;
created_at: string;
user: UserResponse;
user_id: string;
};
export type OwnUserBase = {
channel_mutes: ChannelMute[];
devices: Device[];
mutes: Mute[];
total_unread_count: number;
unread_channels: number;
unread_count: number;
unread_threads: number;
invisible?: boolean;
privacy_settings?: PrivacySettings;
push_preferences?: PushPreference;
roles?: string[];
};
export type OwnUserResponse = UserResponse & OwnUserBase;
export type PartialUpdateChannelAPIResponse = APIResponse & {
channel: ChannelResponse;
members: ChannelMemberResponse[];
};
export type PermissionAPIResponse = APIResponse & {
permission?: PermissionAPIObject;
};
export type PermissionsAPIResponse = APIResponse & {
permissions?: PermissionAPIObject[];
};
export type ReactionAPIResponse = APIResponse & {
message: MessageResponse;
reaction: ReactionResponse;
};
export type ReactionResponse = Reaction & {
created_at: string;
message_id: string;
updated_at: string;
};
export type ReadResponse = {
last_read: string;
user: UserResponse;
last_read_message_id?: string;
unread_messages?: number;
last_delivered_at?: string;
last_delivered_message_id?: string;
};
export type SearchAPIResponse = APIResponse & {
results: {
message: MessageResponse;
}[];
next?: string;
previous?: string;
results_warning?: SearchWarning | null;
};
export type SearchWarning = {
channel_search_cids: string[];
channel_search_count: number;
warning_code: number;
warning_description: string;
};
// Thumb URL(thumb_url) is added considering video attachments as the backend will return the thumbnail in the response.
export type SendFileAPIResponse = APIResponse & { file: string; thumb_url?: string };
export type SendMessageAPIResponse = APIResponse & {
message: MessageResponse;
pending_message_metadata?: Record<string, string> | null;
};
export type SyncResponse = APIResponse & {
events: Event[];
inaccessible_cids?: string[];
};
export type TruncateChannelAPIResponse = APIResponse & {
channel: ChannelResponse;
message?: MessageResponse;
};
export type UpdateChannelAPIResponse = APIResponse & {
channel: ChannelResponse;
members: ChannelMemberResponse[];
message?: MessageResponse;
};
export type UpdateChannelResponse = APIResponse &
Omit<CreateChannelOptions, 'client_id' | 'connection_id'> & {
created_at: string;
updated_at: string;
};
export type UpdateCommandResponse = APIResponse & {
command: UpdateCommandOptions &
CreatedAtUpdatedAt & {
name: CommandVariants;
};
};
export type UpdateMessageAPIResponse = APIResponse & {
message: MessageResponse;
};
export type UsersAPIResponse = APIResponse & {
users: Array<UserResponse>;
};
export type UpdateUsersAPIResponse = APIResponse & {
users: { [key: string]: UserResponse };
};
export type UserResponse = CustomUserData & {
id: string;
anon?: boolean;
banned?: boolean;
blocked_user_ids?: string[];
created_at?: string;
deactivated_at?: string;
deleted_at?: string;
image?: string;
language?: TranslationLanguages | '';
last_active?: string;
name?: string;
notifications_muted?: boolean;
online?: boolean;
privacy_settings?: PrivacySettings;
push_notifications?: PushNotificationSettings;
revoke_tokens_issued_before?: string;
role?: string;
shadow_banned?: boolean;
teams?: string[];
teams_role?: TeamsRole;
updated_at?: string;
username?: string;
avg_response_time?: number;
};
export type TeamsRole = { [team: string]: string };
export type PrivacySettings = {
read_receipts?: {
enabled?: boolean;
};
typing_indicators?: {
enabled?: boolean;
};
delivery_receipts?: {
enabled?: boolean;
};
};
export type PushNotificationSettings = {
disabled?: boolean;
disabled_until?: string | null;
};
/**
* Option Types
*/
export type MessageFlagsPaginationOptions = {
limit?: number;
offset?: number;
};
export type FlagsPaginationOptions = {
limit?: number;
offset?: number;
};
export type FlagReportsPaginationOptions = {
limit?: number;
offset?: number;
};
export type ReviewFlagReportOptions = {
review_details?: object;
user_id?: string;
};
export type BannedUsersPaginationOptions = Omit<
PaginationOptions,
'id_gt' | 'id_gte' | 'id_lt' | 'id_lte'
> & {
exclude_expired_bans?: boolean;
};
export type BanUserOptions = UnBanUserOptions & {
banned_by?: UserResponse;
banned_by_id?: string;
ip_ban?: boolean;
reason?: string;
timeout?: number;
delete_messages?: MessageDeletionStrategy;
};
export type ChannelOptions = {
limit?: number;
member_limit?: number;
message_limit?: number;
offset?: number;
presence?: boolean;
state?: boolean;
user_id?: string;
watch?: boolean;
};
export type ChannelQueryOptions = {
client_id?: string;
connection_id?: string;
created_by?: UserResponse | null;
created_by_id?: UserResponse['id'];
data?: ChannelResponse;
hide_for_creator?: boolean;
members?: PaginationOptions;
messages?: MessagePaginationOptions;
presence?: boolean;
state?: boolean;
watch?: boolean;
watchers?: PaginationOptions;
};
export type ChannelStateOptions = {
offlineMode?: boolean;
skipInitialization?: string[];
skipHydration?: boolean;
};
export type CreateChannelOptions = {
automod?: ChannelConfigAutomod;
automod_behavior?: ChannelConfigAutomodBehavior;
automod_thresholds?: ChannelConfigAutomodThresholds;
blocklist?: string;
blocklist_behavior?: ChannelConfigAutomodBehavior;
client_id?: string;
commands?: CommandVariants[];
connect_events?: boolean;
connection_id?: string;
custom_events?: boolean;
delivery_events?: boolean;
grants?: Record<string, string[]>;
mark_messages_pending?: boolean;
max_message_length?: number;
message_retention?: string;
mutes?: boolean;
name?: string;
permissions?: PermissionObject[];
polls?: boolean;
push_notifications?: boolean;
quotes?: boolean;
reactions?: boolean;
read_events?: boolean;
reminders?: boolean;
replies?: boolean;
search?: boolean;
skip_last_msg_update_for_system_msgs?: boolean;
typing_events?: boolean;
uploads?: boolean;
url_enrichment?: boolean;
user_message_reminders?: boolean;
};
export type CreateCommandOptions = {
description: string;
name: CommandVariants;
args?: string;
set?: CommandVariants;
};
export type CustomPermissionOptions = {
action: string;
condition: object;
id: string;
name: string;
description?: string;
owner?: boolean;
same_team?: boolean;
};
export type DeactivateUsersOptions = {
created_by_id?: string;
mark_messages_deleted?: boolean;
};
export type NewMemberPayload = CustomMemberData &
Pick<ChannelMemberResponse, 'user_id' | 'channel_role'>;
export type Thresholds = Record<
'explicit' | 'spam' | 'toxic',
Partial<{ block: number; flag: number }>
>;
export type BlockListOptions = {
behavior: BlocklistBehavior;
blocklist: string;
};
export type PolicyRequest = {
action: 'Deny' | 'Allow' | (string & {});
/**
* @description User-friendly policy name
*/
name: string;
/**
* @description Whether policy applies to resource owner or not
*/
owner: boolean;
priority: number;
/**
* @description List of resources to apply policy to
*/
resources: string[];
/**
* @description List of roles to apply policy to
*/
roles: string[];
};
export type Automod = 'disabled' | 'simple' | 'AI' | (string & {});
export type AutomodBehavior = 'flag' | 'block' | 'shadow_block' | (string & {});
export type BlocklistBehavior = AutomodBehavior;
export type Command = {
args: string;
description: string;
name: string;
set: string;
created_at?: string;
updated_at?: string;
};
export type UpdateChannelTypeRequest =
// these three properties are required in OpenAPI spec but omitted in some QA tests
Partial<{
automod: Automod;
automod_behavior: AutomodBehavior;
max_message_length: number;
}> & {
allowed_flag_reasons?: string[];
automod_thresholds?: Thresholds;
blocklist?: string;
blocklist_behavior?: BlocklistBehavior;
blocklists?: BlockListOptions[];
commands?: CommandVariants[];
connect_events?: boolean;
custom_events?: boolean;
delivery_events?: boolean;
grants?: Record<string, string[]>;
mark_messages_pending?: boolean;
mutes?: boolean;
partition_size?: number;
/**
* @example 24h
*/
partition_ttl?: string | null;
permissions?: PolicyRequest[];
polls?: boolean;
push_notifications?: boolean;
quotes?: boolean;
reactions?: boolean;
read_events?: boolean;
reminders?: boolean;
replies?: boolean;
search?: boolean;
skip_last_msg_update_for_system_msgs?: boolean;
typing_events?: boolean;
uploads?: boolean;
url_enrichment?: boolean;
count_messages?: boolean;
};
export type UpdateChannelTypeResponse = {
automod: Automod;
automod_behavior: AutomodBehavior;
commands: CommandVariants[];
connect_events: boolean;
created_at: string;
custom_events: boolean;
delivery_events: boolean;
duration: string;
grants: Record<string, string[]>;
mark_messages_pending: boolean;
max_message_length: number;
mutes: boolean;
name: string;
permissions: PolicyRequest[];
polls: boolean;
push_notifications: boolean;
quotes: boolean;
reactions: boolean;
read_events: boolean;
reminders: boolean;
replies: boolean;
search: boolean;
skip_last_msg_update_for_system_msgs: boolean;
typing_events: boolean;
updated_at: string;
uploads: boolean;
url_enrichment: boolean;
allowed_flag_reasons?: string[];
automod_thresholds?: Thresholds;
blocklist?: string;
blocklist_behavior?: BlocklistBehavior;
blocklists?: BlockListOptions[];
partition_size?: number;
partition_ttl?: string;
count_messages?: boolean;
};
export type GetChannelTypeResponse = {
automod: Automod;
automod_behavior: AutomodBehavior;
commands: Command[];
connect_events: boolean;
created_at: string;
custom_events: boolean;
delivery_events: boolean;
duration: string;
grants: Record<string, string[]>;
mark_messages_pending: boolean;
max_message_length: number;
mutes: boolean;
name: string;
permissions: PolicyRequest[];
polls: boolean;
push_notifications: boolean;
quotes: boolean;
reactions: boolean;
read_events: boolean;
reminders: boolean;
replies: boolean;
search: boolean;
skip_last_msg_update_for_system_msgs: boolean;
typing_events: boolean;
updated_at: string;
uploads: boolean;
url_enrichment: boolean;
allowed_flag_reasons?: string[];
automod_thresholds?: Thresholds;
blocklist?: string;
blocklist_behavior?: BlocklistBehavior;
blocklists?: BlockListOptions[];
partition_size?: number;
partition_ttl?: string;
count_messages?: boolean;
};
export type UpdateChannelOptions = Partial<{
accept_invite: boolean;
add_members: string[];
add_moderators: string[];
client_id: string;
connection_id: string;
data: Omit<ChannelResponse, 'id' | 'cid'>;
demote_moderators: string[];
invites: string[];
message: MessageResponse;
reject_invite: boolean;
remove_members: string[];
user: UserResponse;
user_id: string;
}>;
export type MarkChannelsReadOptions = {
client_id?: string;
connection_id?: string;
read_by_channel?: Record<string, string>;
user?: UserResponse;
user_id?: string;
};
export type MarkReadOptions = {
client_id?: string;
connection_id?: string;
thread_id?: string;
user?: UserResponse;
user_id?: string;
};
export type MarkUnreadOptions = {
client_id?: string;
connection_id?: string;
message_id?: string;
thread_id?: string;
user?: UserResponse;
user_id?: string;
};
export type DeliveredMessageConfirmation = {
cid: string;
id: string;
parent_id?: string; // todo: should we include parent_id if thread delivery receipts are not yet supported?
};
export type MarkDeliveredOptions = {
latest_delivered_messages: DeliveredMessageConfirmation[];
user?: UserResponse;
user_id?: string;
};
export type MuteUserOptions = {
client_id?: string;
connection_id?: string;
id?: string;
reason?: string;
target_user_id?: string;
timeout?: number;
type?: string;
user?: UserResponse;
user_id?: string;
};
export type PaginationOptions = {
created_at_after?: string | Date;
created_at_after_or_equal?: string | Date;
created_at_before?: string | Date;
created_at_before_or_equal?: string | Date;
id_gt?: string;
id_gte?: string;
id_lt?: string;
id_lte?: string;
limit?: number;
offset?: number; // should be avoided with channel.query()
};
export type MessagePaginationOptions = PaginationOptions & {
created_at_around?: string | Date;
id_around?: string;
};
export type PinnedMessagePaginationOptions = {
id_around?: string;
id_gt?: string;
id_gte?: string;
id_lt?: string;
id_lte?: string;
limit?: number;
offset?: number;
pinned_at_after?: string | Date;
pinned_at_after_or_equal?: string | Date;
pinned_at_around?: string | Date;
pinned_at_before?: string | Date;
pinned_at_before_or_equal?: string | Date;
};
export type QueryMembersOptions = {
// Pagination option: select members created after the date (RFC399)
created_at_after?: string;
// Pagination option: select members created after or equal the date (RFC399)
created_at_after_or_equal?: string;
// Pagination option: select members created before the date (RFC399)
created_at_before?: string;
// Pagination option: select members created before or equal the date (RFC399)
created_at_before_or_equal?: string;
// Number of members to return, default 100
limit?: number;
// Offset (max is 1000)
offset?: number;
// Pagination option: excludes members with ID less or equal the value
user_id_gt?: string;
// Pagination option: excludes members with ID less than the value
user_id_gte?: string;
// Pagination option: excludes members with ID greater or equal the value
user_id_lt?: string;
// Pagination option: excludes members with ID greater than the value
user_id_lte?: string;
};
export type ReactivateUserOptions = {
created_by_id?: string;
name?: string;
restore_messages?: boolean;
};
export type ReactivateUsersOptions = {
created_by_id?: string;
restore_messages?: boolean;
};
export type SearchOptions = {
limit?: number;
next?: string;
offset?: number;
sort?: SearchMessageSort;
};
export type StreamChatOptions = AxiosRequestConfig & {
/**
* Used to disable warnings that are triggered by using connectUser or connectAnonymousUser server-side.
*/
allowServerSideConnect?: boolean;
axiosRequestConfig?: AxiosRequestConfig;
/**
* Base url to use for API
* such as https://chat-proxy-dublin.stream-io-api.com
*/
baseURL?: string;
browser?: boolean;
device?: BaseDeviceFields;
/**
* Disables the hydration of all caches within the JS Client. This includes this.activeChannels,
* this.polls.pollCache and this.config.
* It is mainly meant to be used for integrations where stream-chat is used as a server-side service
* interacting with Stream's REST API, not depending on any state and purely serving as a wrapper
* around HTTP requests. Using this property on either the client side or a backend implementation
* that also relies on WS events will break these functionalities, so please use carefully.
*/
disableCache?: boolean;
enableInsights?: boolean;
/** experimental feature, please contact support if you want this feature enabled for you */
enableWSFallback?: boolean;
logger?: Logger;
/**
* Custom notification manager service to use for the client.
* If not provided, a default notification manager will be created.
* Notifications are used to communicate events like errors, warnings, info, etc. Other services can publish notifications or subscribe to the NotificationManager state changes.
*/
notifications?: NotificationManager;
/**
* When true, user will be persisted on client. Otherwise if `connectUser` call fails, then you need to
* call `connectUser` again to retry.
* This is mainly useful for chat application working in offline mode, where you will need client.user to
* persist even if connectUser call fails.
*/
persistUserOnConnectionFailure?: boolean;
/**
* When network is recovered, we re-query the active channels on client. But in single query, you can recover
* only 30 channels. So its not guaranteed that all the channels in activeChannels object have updated state.
* Thus in UI sdks, state recovery is managed by components themselves, they don't rely on js client for this.
*
* `recoverStateOnReconnect` parameter can be used in such cases, to disable state recovery within js client.
* When false, user/consumer of this client will need to make sure all the channels present on UI by
* manually calling queryChannels endpoint.
*/
recoverStateOnReconnect?: boolean;
warmUp?: boolean;
/**
* Set the instance of StableWSConnection on chat client. Its purely for testing purpose and should
* not be used in production apps.
*/
wsConnection?: StableWSConnection;
/**
* Sets a suffix to the wsUrl when it is being built in `wsConnection`. Is meant to be
* used purely in testing suites and should not be used in production apps.
*/
wsUrlParams?: URLSearchParams;
};
export type SyncOptions = {
/**
* This will behave as queryChannels option.
*/
watch?: boolean;
/**
* Return channels from request that user does not have access to in a separate
* field in the response called 'inaccessible_cids' instead of
* adding them as 'notification.removed_from_channel' events.
*/
with_inaccessible_cids?: boolean;
};
export type UnBanUserOptions = {
client_id?: string;
connection_id?: string;
id?: string;
shadow?: boolean;
target_user_id?: string;
type?: string;
};
export type UpdateCommandOptions = {
description: string;
args?: string;
set?: CommandVariants;
};
export type UserOptions = {
include_deactivated_users?: boolean;
limit?: number;
offset?: number;
presence?: boolean;
};
/**
* Event Types
*/
export type ConnectionChangeEvent = {
type: EventTypes;
online?: boolean;
};
export type Event = CustomEventData & {
type: EventTypes;
ai_message?: string;
ai_state?: AIState;
channel?: ChannelResponse;
channel_custom?: CustomChannelData;
channel_id?: string;
channel_member_count?: number;
channel_type?: string;
cid?: string;
clear_history?: boolean;
connection_id?: string;
// event creation timestamp, format Date ISO string
created_at?: string;
deleted_for_me?: boolean;
draft?: DraftResponse;
// id of the message that was marked as unread - all the following messages are considered unread. (notification.mark_unread)
first_unread_message_id?: string;
hard_delete?: boolean;
last_delivered_at?: string;
last_delivered_message_id?: string;
// creation date of a message with last_read_message_id, formatted as Date ISO string
last_read_at?: string;
last_read_message_id?: string;
live_location?: SharedLocationResponse;
mark_messages_deleted?: boolean;
me?: OwnUserResponse;
member?: ChannelMemberResponse;
message?: MessageResponse;
message_id?: string;
mode?: string;
online?: boolean;
own_capabilities?: string[];
parent_id?: string;
poll?: PollResponse;
poll_vote?: PollVote | PollAnswer;
queriedChannels?: {
channels: ChannelAPIResponse[];
isLatestMessageSet?: boolean;
};
offlineReactions?: ReactionResponse[];
reaction?: ReactionResponse;
received_at?: string | Date;
reminder?: ReminderResponse;
shadow?: boolean;
team?: string;
thread?: ThreadResponse;
// @deprecated number of all unread messages across all current user's unread channels, equals unread_count
total_unread_count?: number;
// number of all current user's channels with at least one unread message including the channel in this event
unread_channels?: number;
// number of all unread messages across all current user's unread channels
unread_count?: number;
// number of unread messages in the channel from this event (notification.mark_unread)
unread_messages?: number;
unread_thread_messages?: number;
unread_threads?: number;
user?: UserResponse;
user_id?: string;
watcher_count?: number;
channel_last_message_at?: string;
app?: Record<string, unknown>; // TODO: further specify type
};
export type UserCustomEvent = CustomEventData & {
type: string;
};
export type EventHandler = (event: Event) => void;
export type EventTypes = 'all' | keyof typeof EVENT_MAP;
/**
* Filter Types
*/
export type AscDesc = 1 | -1;
export type MessageFlagsFiltersOptions = {
channel_cid?: string;
is_reviewed?: boolean;
team?: string;
user_id?: string;
};
export type MessageFlagsFilters = QueryFilters<
{
channel_cid?:
| RequireOnlyOne<
Pick<QueryFilter<MessageFlagsFiltersOptions['channel_cid']>, '$eq' | '$in'>
>
| PrimitiveFilter<MessageFlagsFiltersOptions['channel_cid']>;
} & {
team?:
| RequireOnlyOne<
Pick<QueryFilter<MessageFlagsFiltersOptions['team']>, '$eq' | '$in'>
>
| PrimitiveFilter<MessageFlagsFiltersOptions['team']>;
} & {
user_id?:
| RequireOnlyOne<
Pick<QueryFilter<MessageFlagsFiltersOptions['user_id']>, '$eq' | '$in'>
>
| PrimitiveFilter<MessageFlagsFiltersOptions['user_id']>;
} & {
[Key in keyof Omit<
MessageFlagsFiltersOptions,
'channel_cid' | 'user_id' | 'is_reviewed'
>]:
| RequireOnlyOne<QueryFilter<MessageFlagsFiltersOptions[Key]>>
| PrimitiveFilter<MessageFlagsFiltersOptions[Key]>;
}
>;
export type FlagsFiltersOptions = {
channel_cid?: string;
message_id?: string;
message_user_id?: string;
reporter_id?: string;
team?: string;
user_id?: string;
};
export type FlagsFilters = QueryFilters<
{
user_id?:
| RequireOnlyOne<Pick<QueryFilter<FlagsFiltersOptions['user_id']>, '$eq' | '$in'>>
| PrimitiveFilter<FlagsFiltersOptions['user_id']>;
} & {
message_id?:
| RequireOnlyOne<
Pick<QueryFilter<FlagsFiltersOptions['message_id']>, '$eq' | '$in'>
>
| PrimitiveFilter<FlagsFiltersOptions['message_id']>;
} & {
message_user_id?:
| RequireOnlyOne<
Pick<QueryFilter<FlagsFiltersOptions['message_user_id']>, '$eq' | '$in'>
>
| PrimitiveFilter<FlagsFiltersOptions['message_user_id']>;
} & {
channel_cid?:
| RequireOnlyOne<
Pick<QueryFilter<FlagsFiltersOptions['channel_cid']>, '$eq' | '$in'>
>
| PrimitiveFilter<FlagsFiltersOptions['channel_cid']>;
} & {
reporter_id?:
| RequireOnlyOne<
Pick<QueryFilter<FlagsFiltersOptions['reporter_id']>, '$eq' | '$in'>
>
| PrimitiveFilter<FlagsFiltersOptions['reporter_id']>;
} & {
team?:
| RequireOnlyOne<Pick<QueryFilter<FlagsFiltersOptions['team']>, '$eq' | '$in'>>
| PrimitiveFilter<FlagsFiltersOptions['team']>;
}
>;
export type FlagReportsFiltersOptions = {
channel_cid?: string;
is_reviewed?: boolean;
message_id?: string;
message_user_id?: string;
report_id?: string;
review_result?: string;
reviewed_by?: string;
team?: string;
user_id?: string;
};
export type FlagReportsFilters = QueryFilters<
{
report_id?:
| RequireOnlyOne<
Pick<QueryFilter<FlagReportsFiltersOptions['report_id']>, '$eq' | '$in'>
>
| PrimitiveFilter<FlagReportsFiltersOptions['report_id']>;
} & {
review_result?:
| RequireOnlyOne<
Pick<QueryFilter<FlagReportsFiltersOptions['review_result']>, '$eq' | '$in'>
>
| PrimitiveFilter<FlagReportsFiltersOptions['review_result']>;
} & {
reviewed_by?:
| RequireOnlyOne<
Pick<QueryFilter<FlagReportsFiltersOptions['reviewed_by']>, '$eq' | '$in'>
>
| PrimitiveFilter<FlagReportsFiltersOptions['reviewed_by']>;
} & {
user_id?:
| RequireOnlyOne<
Pick<QueryFilter<FlagReportsFiltersOptions['user_id']>, '$eq' | '$in'>
>
| PrimitiveFilter<FlagReportsFiltersOptions['user_id']>;
} & {
message_id?:
| RequireOnlyOne<
Pick<QueryFilter<FlagReportsFiltersOptions['message_id']>, '$eq' | '$in'>
>
| PrimitiveFilter<FlagReportsFiltersOptions['message_id']>;
} & {
message_user_id?:
| RequireOnlyOne<
Pick<QueryFilter<FlagReportsFiltersOptions['message_user_id']>, '$eq' | '$in'>
>
| PrimitiveFilter<FlagReportsFiltersOptions['message_user_id']>;
} & {
channel_cid?:
| RequireOnlyOne<
Pick<QueryFilter<FlagReportsFiltersOptions['channel_cid']>, '$eq' | '$in'>
>
| PrimitiveFilter<FlagReportsFiltersOptions['channel_cid']>;
} & {
team?:
| RequireOnlyOne<
Pick<QueryFilter<FlagReportsFiltersOptions['team']>, '$eq' | '$in'>
>
| PrimitiveFilter<FlagReportsFiltersOptions['team']>;
} & {
[Key in keyof Omit<
FlagReportsFiltersOptions,
'report_id' | 'user_id' | 'message_id' | 'review_result' | 'reviewed_by'
>]:
| RequireOnlyOne<QueryFilter<FlagReportsFiltersOptions[Key]>>
| PrimitiveFilter<FlagReportsFiltersOptions[Key]>;
}
>;
export type BannedUsersFilterOptions = {
banned_by_id?: string;
channel_cid?: string;
created_at?: string;
reason?: string;
user_id?: string;
};
export type BannedUsersFilters = QueryFilters<
{
channel_cid?:
| RequireOnlyOne<
Pick<QueryFilter<BannedUsersFilterOptions['channel_cid']>, '$eq' | '$in'>
>
| PrimitiveFilter<BannedUsersFilterOptions['channel_cid']>;
} & {
reason?:
| RequireOnlyOne<
{
$autocomplete?: BannedUsersFilterOptions['reason'];
} & QueryFilter<BannedUsersFilterOptions['reason']>
>
| PrimitiveFilter<BannedUsersFilterOptions['reason']>;
} & {
[Key in keyof Omit<BannedUsersFilterOptions, 'channel_cid' | 'reason'>]:
| RequireOnlyOne<QueryFilter<BannedUsersFilterOptions[Key]>>
| PrimitiveFilter<BannedUsersFilterOptions[Key]>;
}
>;
export type ReactionFilters = QueryFilters<
{
user_id?:
| RequireOnlyOne<Pick<QueryFilter<ReactionResponse['user_id']>, '$eq' | '$in'>>
| PrimitiveFilter<ReactionResponse['user_id']>;
} & {
type?:
| RequireOnlyOne<Pick<QueryFilter<ReactionResponse['type']>, '$eq'>>
| PrimitiveFilter<ReactionResponse['type']>;
} & {
created_at?:
| RequireOnlyOne<
Pick<
QueryFilter<PollResponse['created_at']>,
'$eq' | '$gt' | '$lt' | '$gte' | '$lte'
>
>
| PrimitiveFilter<PollResponse['created_at']>;
}
>;
export type ChannelFilters = QueryFilters<
ContainsOperator<Omit<CustomChannelData, 'name'>> & {
archived?: boolean;
'member.user.name'?:
| RequireOnlyOne<{
$autocomplete?: string;
$eq?: string;
}>
| string;
members?:
| RequireOnlyOne<Pick<QueryFilter<string>, '$in'>>
| RequireOnlyOne<Pick<QueryFilter<string[]>, '$eq'>>
| PrimitiveFilter<string[]>;
name?:
| RequireOnlyOne<
{
$autocomplete?: string;
} & QueryFilter<string>
>
| PrimitiveFilter<string>;
pinned?: boolean;
last_updated?:
| RequireOnlyOne<Pick<QueryFilter<string>, '$eq' | '$gt' | '$gte' | '$lt' | '$lte'>>
| PrimitiveFilter<string>;
} & {
[Key in keyof Omit<ChannelResponse, 'name' | 'members' | keyof CustomChannelData>]:
| RequireOnlyOne<QueryFilter<ChannelResponse[Key]>>
| PrimitiveFilter<ChannelResponse[Key]>;
}
>;
export type DraftFilters = {
channel_cid?:
| RequireOnlyOne<Pick<QueryFilter<DraftResponse['channel_cid']>, '$in' | '$eq'>>
| PrimitiveFilter<DraftResponse['channel_cid']>;
created_at?:
| RequireOnlyOne<
Pick<
QueryFilter<DraftResponse['created_at']>,
'$eq' | '$gt' | '$lt' | '$gte' | '$lte'
>
>
| PrimitiveFilter<DraftResponse['created_at']>;
parent_id?:
| RequireOnlyOne<
Pick<QueryFilter<DraftResponse['created_at']>, '$in' | '$eq' | '$exists'>
>
| PrimitiveFilter<DraftResponse['parent_id']>;
};
export type QueryPollsParams = {
filter?: QueryPollsFilters;
options?: QueryPollsOptions;
sort?: PollSort;
};
export type QueryPollsOptions = Pager;
export type VotesFiltersOptions = {
is_answer?: boolean;
option_id?: string;
user_id?: string;
};
export type QueryVotesOptions = Pager;
export type QueryPollsFilters = QueryFilters<
{
id?:
| RequireOnlyOne<Pick<QueryFilter<PollResponse['id']>, '$eq' | '$in'>>
| PrimitiveFilter<PollResponse['id']>;
} & {
user_id?:
| RequireOnlyOne<Pick<QueryFilter<VotesFiltersOptions['user_id']>, '$eq' | '$in'>>
| PrimitiveFilter<VotesFiltersOptions['user_id']>;
} & {
is_closed?:
| RequireOnlyOne<Pick<QueryFilter<PollResponse['is_closed']>, '$eq'>>
| PrimitiveFilter<PollResponse['is_closed']>;
} & {
max_votes_allowed?:
| RequireOnlyOne<
Pick<
QueryFilter<PollResponse['max_votes_allowed']>,
'$eq' | '$gt' | '$lt' | '$gte' | '$lte'
>
>
| PrimitiveFilter<PollResponse['max_votes_allowed']>;
} & {
allow_answers?:
| RequireOnlyOne<Pick<QueryFilter<PollResponse['allow_answers']>, '$eq'>>
| PrimitiveFilter<PollResponse['allow_answers']>;
} & {
allow_user_suggested_options?:
| RequireOnlyOne<
Pick<QueryFilter<PollResponse['allow_user_suggested_options']>, '$eq'>
>
| PrimitiveFilter<PollResponse['allow_user_suggested_options']>;
} & {
voting_visibility?:
| RequireOnlyOne<Pick<QueryFilter<PollResponse['voting_visibility']>, '$eq'>>
| PrimitiveFilter<PollResponse['voting_visibility']>;
} & {
created_at?:
| RequireOnlyOne<
Pick<
QueryFilter<PollResponse['created_at']>,
'$eq' | '$gt' | '$lt' | '$gte' | '$lte'
>
>
| PrimitiveFilter<PollResponse['created_at']>;
} & {
created_by_id?:
| RequireOnlyOne<