Skip to content

Commit 26c2e49

Browse files
authored
fix(push-preferences): align chat push preference types with the API (#1786)
## CLA - [ ] I have signed the [Stream CLA](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform) (required). - [ ] Code changes are tested ## Description of the changes, What, Why and How? **What** — Re-models the chat push notification preference types so they match the client-side API. **Why** — Reported in GetStream/stream-chat-react-native#3341. The shipped `PushPreference` was camelCase (`callLevel`, `chatLevel`, `disabledUntil`, `removeDisable`) and missing `channel_cid` / `user_id`, so channel-level and server-side preferences couldn't be set type-safely. The canonical client-side OpenAPI spec (`chat-openapi-clientside.yaml`) shows `/push_preferences` is entirely **snake_case**, and `setPushPreferences` posts the body verbatim (no camelCase→snake_case transform) — so the existing camelCase keys never reached the server. **How** — Aligned to `PushPreferenceInput` / `PushPreferencesResponse` / `ChannelPushPreferencesResponse`, scoped to chat and calls (feeds out of scope): - `PushPreference` (input): `call_level`, `channel_cid`, `chat_level`, `chat_preferences`, `disabled_until`, `remove_disable`, `user_id`. - New `ChatPreferences` (granular per-mention prefs) and `PushPreferencesResponse`. - Widened `ChatLevelPushPreference` to `all | mentions | direct_mentions | all_mentions | none | default`. - Fixed `ChannelPushPreference`, `UpsertPushPreferencesResponse`, and `push_preferences` on `ChannelAPIResponse` / `OwnUserBase`. - `client.setPushPreferences(prefs: PushPreference[])` is unchanged — it already wraps the array as `{ preferences }`. ⚠️ **Breaking (type-level):** the old camelCase keys are **removed**, not kept as aliases — `callLevel`, `chatLevel`, `disabledUntil`, `removeDisable` on the input types and `userPreferences` / `userChannelPreferences` on the response. They were silently ignored by the server (input) or never populated (response), so nothing breaks at runtime, but code referencing the old names will need to switch to snake_case. Verified with `yarn types` and `yarn lint` (zero warnings); full unit suite green. ## Changelog - Fix `PushPreference` types to match the API: add `channel_cid` and `user_id`, switch to snake_case (`chat_level`, `chat_preferences`, `disabled_until`, `remove_disable`), add `ChatPreferences` / `PushPreferencesResponse`, and remove the non-functional camelCase keys.
1 parent c60134d commit 26c2e49

2 files changed

Lines changed: 57 additions & 15 deletions

File tree

src/channel.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import type {
2121
ChannelFilters,
2222
ChannelMemberAPIResponse,
2323
ChannelMemberResponse,
24+
ChannelPushPreference,
2425
ChannelQueryOptions,
2526
ChannelResponse,
2627
ChannelUpdateOptions,
@@ -56,7 +57,6 @@ import type {
5657
PinnedMessagePaginationOptions,
5758
PinnedMessagesSort,
5859
PollVoteData,
59-
PushPreference,
6060
QueryChannelAPIResponse,
6161
QueryMembersOptions,
6262
Reaction,
@@ -112,7 +112,7 @@ export class Channel {
112112
lastTypingEvent: Date | null;
113113
isTyping: boolean;
114114
disconnected: boolean;
115-
push_preferences?: PushPreference;
115+
push_preferences?: ChannelPushPreference;
116116
public readonly messageComposer: MessageComposer;
117117
public readonly messageReceiptsTracker: MessageReceiptsTracker;
118118
public readonly cooldownTimer: CooldownTimer;

src/types.ts

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ export type ChannelAPIResponse = {
380380
hidden?: boolean;
381381
membership?: ChannelMemberResponse | null;
382382
pending_messages?: PendingMessageResponse[];
383-
push_preferences?: PushPreference;
383+
push_preferences?: ChannelPushPreference;
384384
read?: ReadResponse[];
385385
threads?: ThreadResponse[];
386386
watcher_count?: number;
@@ -685,25 +685,67 @@ export type GetUnreadCountAPIResponse = APIResponse & {
685685
total_unread_count_by_team?: Record<string, number>;
686686
};
687687

688-
export type ChatLevelPushPreference = 'all' | 'none' | 'mentions' | (string & {});
688+
export type ChatLevelPushPreference =
689+
| 'all'
690+
| 'mentions' // deprecated by the API in favor of 'direct_mentions'
691+
| 'direct_mentions'
692+
| 'all_mentions'
693+
| 'none'
694+
| 'default'
695+
| (string & {});
696+
697+
export type CallLevelPushPreference = 'all' | 'none' | 'default' | (string & {});
698+
699+
/** Granular all/none toggle used by the chat sub-preferences. */
700+
export type PushPreferenceLevel = 'all' | 'none' | (string & {});
689701

702+
/** Per-mention-type chat push preferences (matches OpenAPI `ChatPreferencesInput`). */
703+
export type ChatPreferences = {
704+
channel_mentions?: PushPreferenceLevel;
705+
default_preference?: PushPreferenceLevel;
706+
direct_mentions?: PushPreferenceLevel;
707+
group_mentions?: PushPreferenceLevel;
708+
here_mentions?: PushPreferenceLevel;
709+
role_mentions?: PushPreferenceLevel;
710+
thread_replies?: PushPreferenceLevel;
711+
};
712+
713+
/**
714+
* Input accepted by {@link StreamChat.setPushPreferences} (matches OpenAPI `PushPreferenceInput`).
715+
*
716+
* Set `channel_cid` to scope the preference to a single channel; leave it empty to
717+
* set the user-level default. `user_id` is required for server-side auth and
718+
* defaults to the connected user for client-side auth.
719+
*/
690720
export type PushPreference = {
691-
callLevel?: 'all' | 'none' | (string & {});
692-
chatLevel?: ChatLevelPushPreference;
693-
disabledUntil?: string; // snooze till this time
694-
removeDisable?: boolean; // Temporary flag for resetting disabledUntil
721+
call_level?: CallLevelPushPreference;
722+
channel_cid?: string;
723+
chat_level?: ChatLevelPushPreference;
724+
chat_preferences?: ChatPreferences;
725+
disabled_until?: string; // snooze until this time
726+
remove_disable?: boolean; // stop snoozing (clears disabled_until)
727+
user_id?: string;
728+
};
729+
730+
/** Per-user push preferences returned by the API (matches OpenAPI `PushPreferencesResponse`). */
731+
export type PushPreferencesResponse = {
732+
call_level?: CallLevelPushPreference;
733+
chat_level?: ChatLevelPushPreference;
734+
chat_preferences?: ChatPreferences;
735+
disabled_until?: string;
695736
};
696737

738+
/** Per-channel push preferences returned by the API (matches OpenAPI `ChannelPushPreferencesResponse`). */
697739
export type ChannelPushPreference = {
698-
chatLevel?: ChatLevelPushPreference; // "all", "none", "mentions", or other custom strings
699-
disabledUntil?: string;
700-
removeDisable?: boolean; // Temporary flag for resetting disabledUntil
740+
chat_level?: ChatLevelPushPreference; // "all", "mentions", "direct_mentions", "all_mentions", "none", "default" or other custom strings
741+
disabled_until?: string;
701742
};
702743

703744
export type UpsertPushPreferencesResponse = APIResponse & {
704-
// Mapping of user IDs to their push preferences
705-
userChannelPreferences: Record<string, Record<string, ChannelPushPreference>>;
706-
userPreferences: Record<string, PushPreference>; // Mapping of user -> channel id -> push preferences
745+
// Mapping of user id -> channel cid -> channel push preferences
746+
user_channel_preferences: Record<string, Record<string, ChannelPushPreference>>;
747+
// Mapping of user id -> user push preferences
748+
user_preferences: Record<string, PushPreferencesResponse>;
707749
};
708750

709751
export type GetUnreadCountBatchAPIResponse = APIResponse & {
@@ -862,7 +904,7 @@ export type OwnUserBase = {
862904
unread_threads: number;
863905
invisible?: boolean;
864906
privacy_settings?: PrivacySettings;
865-
push_preferences?: PushPreference;
907+
push_preferences?: PushPreferencesResponse;
866908
roles?: string[];
867909
total_unread_count_by_team?: Record<string, number> | null;
868910
};

0 commit comments

Comments
 (0)