@stream-io/feeds-client 0.2.3 → 0.2.5

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 +27 -0
  2. package/dist/index-react-bindings.browser.cjs +36 -19
  3. package/dist/index-react-bindings.browser.cjs.map +1 -1
  4. package/dist/index-react-bindings.browser.js +36 -19
  5. package/dist/index-react-bindings.browser.js.map +1 -1
  6. package/dist/index-react-bindings.node.cjs +36 -19
  7. package/dist/index-react-bindings.node.cjs.map +1 -1
  8. package/dist/index-react-bindings.node.js +36 -19
  9. package/dist/index-react-bindings.node.js.map +1 -1
  10. package/dist/index.browser.cjs +35 -20
  11. package/dist/index.browser.cjs.map +1 -1
  12. package/dist/index.browser.js +35 -20
  13. package/dist/index.browser.js.map +1 -1
  14. package/dist/index.node.cjs +35 -20
  15. package/dist/index.node.cjs.map +1 -1
  16. package/dist/index.node.js +35 -20
  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/common/search/FeedSearchSource.d.ts +2 -2
  21. package/dist/src/feed/event-handlers/feed/handle-feed-updated.d.ts +2 -2
  22. package/dist/src/feeds-client/feeds-client.d.ts +3 -2
  23. package/dist/src/gen/models/index.d.ts +18 -8
  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/common/search/BaseSearchSource.ts +1 -1
  29. package/src/common/search/FeedSearchSource.ts +3 -2
  30. package/src/feed/event-handlers/feed/handle-feed-updated.ts +2 -2
  31. package/src/feeds-client/feeds-client.ts +51 -20
  32. package/src/gen/models/index.ts +26 -8
  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.3",
3
+ "version": "0.2.5",
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
+ );
@@ -188,7 +188,7 @@ abstract class BaseSearchSourceBase<T> implements ISearchSource<T> {
188
188
  const { items, next } = result;
189
189
 
190
190
  const stateUpdate: Partial<SearchSourceState<T>> = {};
191
- if (next || next === null) {
191
+ if (Object.prototype.hasOwnProperty.call(result, 'next')) {
192
192
  stateUpdate.next = next;
193
193
  stateUpdate.hasNext = !!next;
194
194
  } else {
@@ -9,14 +9,15 @@ export type FeedSearchSourceOptions = SearchSourceOptions & {
9
9
  };
10
10
 
11
11
  export class FeedSearchSource extends BaseSearchSource<Feed> {
12
- readonly type = 'feed' as const;
12
+ readonly type: string;
13
+ readonly feedGroupId?: string | undefined;
13
14
  private readonly client: FeedsClient;
14
- private readonly feedGroupId?: string | undefined;
15
15
 
16
16
  constructor(client: FeedsClient, options?: FeedSearchSourceOptions) {
17
17
  super(options);
18
18
  this.client = client;
19
19
  this.feedGroupId = options?.groupId;
20
+ this.type = `${this.feedGroupId}-feed`;
20
21
  }
21
22
 
22
23
  protected async query(searchQuery: string) {
@@ -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) {
@@ -2265,6 +2265,8 @@ export interface DeleteCommentResponse {
2265
2265
 
2266
2266
  export interface DeleteFeedResponse {
2267
2267
  duration: string;
2268
+
2269
+ task_id: string;
2268
2270
  }
2269
2271
 
2270
2272
  export interface DeleteMessageRequest {
@@ -2909,14 +2911,18 @@ export interface FeedUpdatedEvent {
2909
2911
  user?: UserResponseCommonFields;
2910
2912
  }
2911
2913
 
2912
- export interface FeedsEventPreferences {
2913
- comments?: string;
2914
+ export interface FeedsPreferences {
2915
+ comment?: string;
2916
+
2917
+ comment_reaction?: string;
2918
+
2919
+ follow?: string;
2914
2920
 
2915
- mentions?: string;
2921
+ mention?: string;
2916
2922
 
2917
- new_followers?: string;
2923
+ reaction?: string;
2918
2924
 
2919
- reactions?: string;
2925
+ custom_activity_types?: Record<string, string>;
2920
2926
  }
2921
2927
 
2922
2928
  export interface FeedsReactionResponse {
@@ -4551,9 +4557,9 @@ export interface PrivacySettingsResponse {
4551
4557
  }
4552
4558
 
4553
4559
  export interface PushNotificationConfig {
4554
- enabled?: boolean;
4560
+ enable_push?: boolean;
4555
4561
 
4556
- activity_types?: string[];
4562
+ push_types?: string[];
4557
4563
  }
4558
4564
 
4559
4565
  export interface PushPreferences {
@@ -4565,7 +4571,7 @@ export interface PushPreferences {
4565
4571
 
4566
4572
  feeds_level?: string;
4567
4573
 
4568
- feeds_events?: FeedsEventPreferences;
4574
+ feeds_preferences?: FeedsPreferences;
4569
4575
  }
4570
4576
 
4571
4577
  export interface Quality {
@@ -5324,6 +5330,8 @@ export interface STTEgressConfig {
5324
5330
  translation_languages?: string[];
5325
5331
 
5326
5332
  external_storage?: ExternalStorage;
5333
+
5334
+ speech_segment_config?: SpeechSegmentConfig;
5327
5335
  }
5328
5336
 
5329
5337
  export interface ScreensharingSettings {
@@ -5450,6 +5458,12 @@ export interface SortParamRequest {
5450
5458
  field?: string;
5451
5459
  }
5452
5460
 
5461
+ export interface SpeechSegmentConfig {
5462
+ max_speech_caption_ms?: number;
5463
+
5464
+ silence_duration_ms?: number;
5465
+ }
5466
+
5453
5467
  export interface StoriesConfig {
5454
5468
  expiration_behaviour?: 'hide_for_everyone' | 'visible_for_author';
5455
5469
 
@@ -5653,6 +5667,8 @@ export interface TranscriptionSettings {
5653
5667
  | 'sk';
5654
5668
 
5655
5669
  mode: 'available' | 'disabled' | 'auto-on';
5670
+
5671
+ speech_segment_config?: SpeechSegmentConfig;
5656
5672
  }
5657
5673
 
5658
5674
  export interface TranscriptionSettingsResponse {
@@ -5698,6 +5714,8 @@ export interface TranscriptionSettingsResponse {
5698
5714
  | 'sk';
5699
5715
 
5700
5716
  mode: 'available' | 'disabled' | 'auto-on';
5717
+
5718
+ speech_segment_config?: SpeechSegmentConfig;
5701
5719
  }
5702
5720
 
5703
5721
  export interface TypingIndicators {
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];