@stream-io/feeds-client 0.2.4 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/index-react-bindings.browser.cjs +48 -18
  3. package/dist/index-react-bindings.browser.cjs.map +1 -1
  4. package/dist/index-react-bindings.browser.js +48 -18
  5. package/dist/index-react-bindings.browser.js.map +1 -1
  6. package/dist/index-react-bindings.node.cjs +48 -18
  7. package/dist/index-react-bindings.node.cjs.map +1 -1
  8. package/dist/index-react-bindings.node.js +48 -18
  9. package/dist/index-react-bindings.node.js.map +1 -1
  10. package/dist/index.browser.cjs +48 -18
  11. package/dist/index.browser.cjs.map +1 -1
  12. package/dist/index.browser.js +48 -18
  13. package/dist/index.browser.js.map +1 -1
  14. package/dist/index.node.cjs +48 -18
  15. package/dist/index.node.cjs.map +1 -1
  16. package/dist/index.node.js +48 -18
  17. package/dist/index.node.js.map +1 -1
  18. package/dist/src/common/real-time/StableWSConnection.d.ts +3 -3
  19. package/dist/src/common/real-time/event-models.d.ts +14 -0
  20. package/dist/src/feed/event-handlers/feed/handle-feed-updated.d.ts +2 -2
  21. package/dist/src/feeds-client/feeds-client.d.ts +3 -2
  22. package/dist/src/gen/feeds/FeedsApi.d.ts +2 -1
  23. package/dist/src/gen/models/index.d.ts +32 -5
  24. package/dist/src/types.d.ts +2 -2
  25. package/dist/tsconfig.tsbuildinfo +1 -1
  26. package/package.json +1 -1
  27. package/src/common/real-time/event-models.ts +16 -0
  28. package/src/feed/event-handlers/feed/handle-feed-updated.ts +2 -2
  29. package/src/feeds-client/feeds-client.ts +51 -20
  30. package/src/gen/feeds/FeedsApi.ts +26 -0
  31. package/src/gen/model-decoders/decoders.ts +7 -0
  32. package/src/gen/models/index.ts +52 -5
  33. package/src/types.ts +5 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stream-io/feeds-client",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "packageManager": "yarn@3.2.4",
5
5
  "main": "./dist/index.node.js",
6
6
  "exports": {
@@ -36,3 +36,19 @@ export interface ConnectedEvent {
36
36
  */
37
37
  type: string;
38
38
  }
39
+
40
+ export enum UnhandledErrorType {
41
+ ReconnectionReconciliation = 'reconnection-reconciliation',
42
+ }
43
+
44
+ export type SyncFailure = { feed: string, reason: unknown };
45
+
46
+ export type UnhandledErrorEvent = {
47
+ type: 'errors.unhandled';
48
+ error_type: UnhandledErrorType;
49
+ } & (
50
+ | {
51
+ error_type: UnhandledErrorType.ReconnectionReconciliation;
52
+ failures: SyncFailure[];
53
+ }
54
+ );
@@ -1,9 +1,9 @@
1
1
  import { Feed } from '../../../feed';
2
- import { EventPayload } from '../../../types-internal';
2
+ import { EventPayload, PartializeAllBut } from '../../../types-internal';
3
3
 
4
4
  export function handleFeedUpdated(
5
5
  this: Feed,
6
- event: EventPayload<'feeds.feed.updated'>,
6
+ event: PartializeAllBut<EventPayload<'feeds.feed.updated'>, 'feed'>,
7
7
  ) {
8
8
  this.state.partialNext({ ...event.feed });
9
9
  }
@@ -37,6 +37,7 @@ import { ModerationClient } from '../moderation-client';
37
37
  import { StreamPoll } from '../common/Poll';
38
38
  import {
39
39
  Feed,
40
+ handleFeedUpdated,
40
41
  handleFollowCreated,
41
42
  handleFollowDeleted,
42
43
  handleFollowUpdated,
@@ -44,6 +45,10 @@ import {
44
45
  handleWatchStopped,
45
46
  } from '../feed';
46
47
  import { handleUserUpdated } from './event-handlers';
48
+ import {
49
+ SyncFailure,
50
+ UnhandledErrorType,
51
+ } from '../common/real-time/event-models';
47
52
 
48
53
  export type FeedsClientState = {
49
54
  connected_user: OwnUser | undefined;
@@ -100,14 +105,7 @@ export class FeedsClient extends FeedsApi {
100
105
  this.state.partialNext({ is_ws_connection_healthy: online });
101
106
 
102
107
  if (online) {
103
- this.healthyConnectionChangedEventCount++;
104
-
105
- // we skip the first event as we could potentially be querying twice
106
- if (this.healthyConnectionChangedEventCount > 1) {
107
- for (const activeFeed of Object.values(this.activeFeeds)) {
108
- activeFeed.synchronize();
109
- }
110
- }
108
+ this.recoverOnReconnect();
111
109
  } else {
112
110
  for (const activeFeed of Object.values(this.activeFeeds)) {
113
111
  handleWatchStopped.bind(activeFeed)();
@@ -208,6 +206,31 @@ export class FeedsClient extends FeedsApi {
208
206
  });
209
207
  }
210
208
 
209
+ private recoverOnReconnect = async () => {
210
+ this.healthyConnectionChangedEventCount++;
211
+
212
+ // we skip the first event as we could potentially be querying twice
213
+ if (this.healthyConnectionChangedEventCount > 1) {
214
+ const entries = Object.entries(this.activeFeeds);
215
+
216
+ const results = await Promise.allSettled(
217
+ entries.map(([, feed]) => feed.synchronize()),
218
+ );
219
+
220
+ const failures: SyncFailure[] = results.flatMap((result, index) =>
221
+ result.status === 'rejected'
222
+ ? [{ feed: entries[index][0], reason: result.reason }]
223
+ : [],
224
+ );
225
+
226
+ this.eventDispatcher.dispatch({
227
+ type: 'errors.unhandled',
228
+ error_type: UnhandledErrorType.ReconnectionReconciliation,
229
+ failures,
230
+ });
231
+ }
232
+ };
233
+
211
234
  public pollFromState = (id: string) => this.polls_by_id.get(id);
212
235
 
213
236
  public hydratePollCache(activities: ActivityResponse[]) {
@@ -353,8 +376,13 @@ export class FeedsClient extends FeedsApi {
353
376
  async queryFeeds(request?: QueryFeedsRequest) {
354
377
  const response = await this._queryFeeds(request);
355
378
 
356
- const feeds = response.feeds.map((f) =>
357
- this.getOrCreateActiveFeed(f.group_id, f.id, f, request?.watch),
379
+ const feeds = response.feeds.map((feedResponse) =>
380
+ this.getOrCreateActiveFeed(
381
+ feedResponse.group_id,
382
+ feedResponse.id,
383
+ feedResponse,
384
+ request?.watch,
385
+ ),
358
386
  );
359
387
 
360
388
  return {
@@ -458,17 +486,20 @@ export class FeedsClient extends FeedsApi {
458
486
  watch?: boolean,
459
487
  ) => {
460
488
  const fid = `${group}:${id}`;
461
- if (this.activeFeeds[fid]) {
462
- const feed = this.activeFeeds[fid];
463
- if (watch && !feed.currentState.watch) {
464
- handleWatchStarted.bind(feed)();
465
- }
466
- return feed;
467
- } else {
468
- const feed = new Feed(this, group, id, data, watch);
469
- this.activeFeeds[fid] = feed;
470
- return feed;
489
+
490
+ if (!this.activeFeeds[fid]) {
491
+ this.activeFeeds[fid] = new Feed(this, group, id, data, watch);
471
492
  }
493
+
494
+ const feed = this.activeFeeds[fid];
495
+
496
+ if (!feed.currentState.watch) {
497
+ // feed isn't watched and may be stale, update it
498
+ if (data) handleFeedUpdated.call(feed, { feed: data });
499
+ if (watch) handleWatchStarted.call(feed);
500
+ }
501
+
502
+ return feed;
472
503
  };
473
504
 
474
505
  private findActiveFeedByActivityId(activityId: string) {
@@ -127,6 +127,8 @@ import {
127
127
  UpdateUsersResponse,
128
128
  UpsertActivitiesRequest,
129
129
  UpsertActivitiesResponse,
130
+ UpsertPushPreferencesRequest,
131
+ UpsertPushPreferencesResponse,
130
132
  WSAuthMessage,
131
133
  } from '../models';
132
134
  import { decoders } from '../model-decoders/decoders';
@@ -726,6 +728,7 @@ export class FeedsApi {
726
728
  text: request?.text,
727
729
  visibility: request?.visibility,
728
730
  attachments: request?.attachments,
731
+ feeds: request?.feeds,
729
732
  filter_tags: request?.filter_tags,
730
733
  interest_tags: request?.interest_tags,
731
734
  custom: request?.custom,
@@ -2073,6 +2076,29 @@ export class FeedsApi {
2073
2076
  return { ...response.body, metadata: response.metadata };
2074
2077
  }
2075
2078
 
2079
+ async updatePushNotificationPreferences(
2080
+ request: UpsertPushPreferencesRequest,
2081
+ ): Promise<StreamResponse<UpsertPushPreferencesResponse>> {
2082
+ const body = {
2083
+ preferences: request?.preferences,
2084
+ };
2085
+
2086
+ const response = await this.apiClient.sendRequest<
2087
+ StreamResponse<UpsertPushPreferencesResponse>
2088
+ >(
2089
+ 'POST',
2090
+ '/api/v2/push_preferences',
2091
+ undefined,
2092
+ undefined,
2093
+ body,
2094
+ 'application/json',
2095
+ );
2096
+
2097
+ decoders.UpsertPushPreferencesResponse?.(response.body);
2098
+
2099
+ return { ...response.body, metadata: response.metadata };
2100
+ }
2101
+
2076
2102
  async deleteFile(request?: {
2077
2103
  url?: string;
2078
2104
  }): Promise<StreamResponse<Response>> {
@@ -1849,6 +1849,13 @@ decoders.UpsertConfigResponse = (input?: Record<string, any>) => {
1849
1849
  return decode(typeMappings, input);
1850
1850
  };
1851
1851
 
1852
+ decoders.UpsertPushPreferencesResponse = (input?: Record<string, any>) => {
1853
+ const typeMappings: TypeMapping = {
1854
+ user_preferences: { type: 'PushPreferences', isSingle: false },
1855
+ };
1856
+ return decode(typeMappings, input);
1857
+ };
1858
+
1852
1859
  decoders.User = (input?: Record<string, any>) => {
1853
1860
  const typeMappings: TypeMapping = {
1854
1861
  ban_expires: { type: 'DatetimeType', isSingle: true },
@@ -1221,6 +1221,8 @@ export interface CallEgress {
1221
1221
 
1222
1222
  export interface CallIngressResponse {
1223
1223
  rtmp: RTMPIngress;
1224
+
1225
+ srt: SRTIngress;
1224
1226
  }
1225
1227
 
1226
1228
  export interface CallMember {
@@ -1783,6 +1785,12 @@ export const ChannelOwnCapability = {
1783
1785
  export type ChannelOwnCapability =
1784
1786
  (typeof ChannelOwnCapability)[keyof typeof ChannelOwnCapability];
1785
1787
 
1788
+ export interface ChannelPushPreferences {
1789
+ chat_level?: string;
1790
+
1791
+ disabled_until?: Date;
1792
+ }
1793
+
1786
1794
  export interface ChannelResponse {
1787
1795
  cid: string;
1788
1796
 
@@ -2912,15 +2920,15 @@ export interface FeedUpdatedEvent {
2912
2920
  }
2913
2921
 
2914
2922
  export interface FeedsPreferences {
2915
- comment?: string;
2923
+ comment?: 'all' | 'none';
2916
2924
 
2917
- comment_reaction?: string;
2925
+ comment_reaction?: 'all' | 'none';
2918
2926
 
2919
- follow?: string;
2927
+ follow?: 'all' | 'none';
2920
2928
 
2921
- mention?: string;
2929
+ mention?: 'all' | 'none';
2922
2930
 
2923
- reaction?: string;
2931
+ reaction?: 'all' | 'none';
2924
2932
 
2925
2933
  custom_activity_types?: Record<string, string>;
2926
2934
  }
@@ -4562,6 +4570,24 @@ export interface PushNotificationConfig {
4562
4570
  push_types?: string[];
4563
4571
  }
4564
4572
 
4573
+ export interface PushPreferenceInput {
4574
+ call_level?: 'all' | 'none' | 'default';
4575
+
4576
+ channel_cid?: string;
4577
+
4578
+ chat_level?: 'all' | 'mentions' | 'none' | 'default';
4579
+
4580
+ disabled_until?: Date;
4581
+
4582
+ feeds_level?: 'all' | 'none' | 'default';
4583
+
4584
+ remove_disable?: boolean;
4585
+
4586
+ user_id?: string;
4587
+
4588
+ feeds_preferences?: FeedsPreferences;
4589
+ }
4590
+
4565
4591
  export interface PushPreferences {
4566
4592
  call_level?: string;
4567
4593
 
@@ -5314,6 +5340,10 @@ export interface SFUIDLastSeen {
5314
5340
  process_start_time: number;
5315
5341
  }
5316
5342
 
5343
+ export interface SRTIngress {
5344
+ address: string;
5345
+ }
5346
+
5317
5347
  export interface STTEgressConfig {
5318
5348
  closed_captions_enabled?: boolean;
5319
5349
 
@@ -5777,6 +5807,8 @@ export interface UpdateActivityRequest {
5777
5807
 
5778
5808
  attachments?: Attachment[];
5779
5809
 
5810
+ feeds?: string[];
5811
+
5780
5812
  filter_tags?: string[];
5781
5813
 
5782
5814
  interest_tags?: string[];
@@ -6024,6 +6056,21 @@ export interface UpsertConfigResponse {
6024
6056
  config?: ConfigResponse;
6025
6057
  }
6026
6058
 
6059
+ export interface UpsertPushPreferencesRequest {
6060
+ preferences: PushPreferenceInput[];
6061
+ }
6062
+
6063
+ export interface UpsertPushPreferencesResponse {
6064
+ duration: string;
6065
+
6066
+ user_channel_preferences: Record<
6067
+ string,
6068
+ Record<string, ChannelPushPreferences | null>
6069
+ >;
6070
+
6071
+ user_preferences: Record<string, PushPreferences>;
6072
+ }
6073
+
6027
6074
  export interface User {
6028
6075
  banned: boolean;
6029
6076
 
package/src/types.ts CHANGED
@@ -1,4 +1,7 @@
1
- import { ConnectionChangedEvent } from './common/real-time/event-models';
1
+ import {
2
+ ConnectionChangedEvent,
3
+ UnhandledErrorEvent,
4
+ } from './common/real-time/event-models';
2
5
  import { NetworkChangedEvent } from './common/types';
3
6
  import {
4
7
  PagerResponse,
@@ -10,7 +13,7 @@ import type {
10
13
  } from './gen/models';
11
14
  import { FeedsClient } from './feeds-client';
12
15
 
13
- export type FeedsEvent = WSEvent | ConnectionChangedEvent | NetworkChangedEvent;
16
+ export type FeedsEvent = WSEvent | ConnectionChangedEvent | NetworkChangedEvent | UnhandledErrorEvent;
14
17
  export type ActivityIdOrCommentId = string;
15
18
 
16
19
  export type GetCommentsRequest = Parameters<FeedsClient['getComments']>[0];