@stream-io/feeds-client 0.3.7 → 0.3.9

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 (54) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/index.js +2 -1
  3. package/dist/cjs/index.js.map +1 -1
  4. package/dist/cjs/react-bindings.js +76 -14
  5. package/dist/cjs/react-bindings.js.map +1 -1
  6. package/dist/es/index.mjs +3 -2
  7. package/dist/es/react-bindings.mjs +76 -14
  8. package/dist/es/react-bindings.mjs.map +1 -1
  9. package/dist/{feeds-client-3aXF89xy.mjs → feeds-client-CI-WG0y0.mjs} +280 -52
  10. package/dist/feeds-client-CI-WG0y0.mjs.map +1 -0
  11. package/dist/{feeds-client-DLiLkrA0.js → feeds-client-DvR7ZYd1.js} +280 -52
  12. package/dist/feeds-client-DvR7ZYd1.js.map +1 -0
  13. package/dist/types/activity-with-state-updates/activity-with-state-updates.d.ts +49 -0
  14. package/dist/types/activity-with-state-updates/activity-with-state-updates.d.ts.map +1 -0
  15. package/dist/types/activity-with-state-updates/get-feed.d.ts +3 -0
  16. package/dist/types/activity-with-state-updates/get-feed.d.ts.map +1 -0
  17. package/dist/types/bindings/react/hooks/feed-state-hooks/index.d.ts +1 -0
  18. package/dist/types/bindings/react/hooks/feed-state-hooks/index.d.ts.map +1 -1
  19. package/dist/types/bindings/react/hooks/feed-state-hooks/useActivityComments.d.ts +32 -0
  20. package/dist/types/bindings/react/hooks/feed-state-hooks/useActivityComments.d.ts.map +1 -0
  21. package/dist/types/bindings/react/hooks/feed-state-hooks/useComments.d.ts +4 -0
  22. package/dist/types/bindings/react/hooks/feed-state-hooks/useComments.d.ts.map +1 -1
  23. package/dist/types/bindings/react/hooks/feed-state-hooks/useOwnCapabilities.d.ts.map +1 -1
  24. package/dist/types/bindings/react/hooks/useCreateFeedsClient.d.ts.map +1 -1
  25. package/dist/types/common/real-time/event-models.d.ts +1 -0
  26. package/dist/types/common/real-time/event-models.d.ts.map +1 -1
  27. package/dist/types/feed/event-handlers/activity/handle-activity-updated.d.ts.map +1 -1
  28. package/dist/types/feed/feed.d.ts +1 -1
  29. package/dist/types/feed/feed.d.ts.map +1 -1
  30. package/dist/types/feeds-client/active-activity.d.ts +8 -0
  31. package/dist/types/feeds-client/active-activity.d.ts.map +1 -0
  32. package/dist/types/feeds-client/feeds-client.d.ts +36 -3
  33. package/dist/types/feeds-client/feeds-client.d.ts.map +1 -1
  34. package/dist/types/index.d.ts +1 -0
  35. package/dist/types/index.d.ts.map +1 -1
  36. package/dist/types/types.d.ts.map +1 -1
  37. package/package.json +1 -1
  38. package/src/activity-with-state-updates/activity-with-state-updates.ts +190 -0
  39. package/src/activity-with-state-updates/get-feed.ts +5 -0
  40. package/src/bindings/react/hooks/feed-state-hooks/index.ts +1 -0
  41. package/src/bindings/react/hooks/feed-state-hooks/useActivityComments.ts +113 -0
  42. package/src/bindings/react/hooks/feed-state-hooks/useComments.ts +4 -0
  43. package/src/bindings/react/hooks/feed-state-hooks/useOwnCapabilities.ts +12 -9
  44. package/src/bindings/react/hooks/useCreateFeedsClient.ts +0 -6
  45. package/src/common/real-time/event-models.ts +5 -1
  46. package/src/feed/event-handlers/activity/handle-activity-updated.ts +11 -0
  47. package/src/feed/feed.ts +16 -6
  48. package/src/feeds-client/active-activity.ts +42 -0
  49. package/src/feeds-client/feeds-client.ts +162 -53
  50. package/src/index.ts +1 -0
  51. package/src/test-utils/response-generators.ts +1 -0
  52. package/src/types.ts +8 -10
  53. package/dist/feeds-client-3aXF89xy.mjs.map +0 -1
  54. package/dist/feeds-client-DLiLkrA0.js.map +0 -1
@@ -3844,7 +3844,7 @@ const getRateLimitFromResponseHeader = (response_headers) => {
3844
3844
  };
3845
3845
  return result;
3846
3846
  };
3847
- const version = "0.3.7";
3847
+ const version = "0.3.9";
3848
3848
  class ApiClient {
3849
3849
  constructor(apiKey, tokenManager, connectionIdManager, options) {
3850
3850
  this.apiKey = apiKey;
@@ -5564,6 +5564,12 @@ function handleActivityUpdated(payload, fromWs) {
5564
5564
  activities: currentActivities,
5565
5565
  pinned_activities: currentPinnedActivities
5566
5566
  } = this.currentState;
5567
+ const currentActivity = currentActivities?.find(
5568
+ (a) => a.id === payload.activity.id
5569
+ );
5570
+ if (!payload.activity.current_feed && payload.activity.feeds.length === 1 && currentActivity?.current_feed) {
5571
+ payload.activity.current_feed = currentActivity.current_feed;
5572
+ }
5567
5573
  const [result1, result2] = [
5568
5574
  this.hasActivity(payload.activity.id) ? updateActivityInState(payload, currentActivities) : void 0,
5569
5575
  updatePinnedActivityInState(payload, currentPinnedActivities)
@@ -6480,7 +6486,7 @@ const _Feed = class _Feed extends FeedApi {
6480
6486
  }
6481
6487
  }
6482
6488
  async loadNextPageActivityComments(activity, request) {
6483
- const currentEntityState = this.currentState.comments_by_entity_id[activity.id];
6489
+ const currentEntityState = this.currentState.comments_by_entity_id[typeof activity === "string" ? activity : activity.id];
6484
6490
  const currentPagination = currentEntityState?.pagination;
6485
6491
  const currentNextCursor = currentPagination?.next;
6486
6492
  const currentSort = currentPagination?.sort;
@@ -6489,12 +6495,13 @@ const _Feed = class _Feed extends FeedApi {
6489
6495
  if (isLoading || !checkHasAnotherPage(currentEntityState?.comments, currentNextCursor)) {
6490
6496
  return;
6491
6497
  }
6498
+ const entityId = typeof activity === "string" ? activity : activity.id;
6492
6499
  await this.loadNextPageComments({
6493
- entityId: activity.id,
6500
+ entityId,
6494
6501
  base: () => this.client.getComments({
6495
6502
  ...request,
6496
6503
  sort,
6497
- object_id: activity.id,
6504
+ object_id: entityId,
6498
6505
  object_type: "activity",
6499
6506
  next: currentNextCursor
6500
6507
  }),
@@ -6729,7 +6736,7 @@ const _Feed = class _Feed extends FeedApi {
6729
6736
  eventHandler?.(event);
6730
6737
  }
6731
6738
  if (typeof eventHandler === "undefined") {
6732
- console.warn(`Received unknown event type: ${event.type}`, event);
6739
+ feedsLoggerSystem.getLogger("event-dispatcher").warn(`Received unknown feed event, type: ${event.type}`, event);
6733
6740
  }
6734
6741
  this.eventDispatcher.dispatch(event);
6735
6742
  }
@@ -6871,6 +6878,156 @@ function queueBatchedOwnCapabilities({ feeds }) {
6871
6878
  function clearQueuedFeeds() {
6872
6879
  queuedFeeds.clear();
6873
6880
  }
6881
+ function connectActivityToFeed({
6882
+ fid
6883
+ }) {
6884
+ const [group, id] = fid.split(":");
6885
+ const activeFeed = this.activeFeeds[fid];
6886
+ const feed = new Feed(
6887
+ this,
6888
+ group,
6889
+ id,
6890
+ void 0,
6891
+ activeFeed?.currentState.watch
6892
+ );
6893
+ return feed;
6894
+ }
6895
+ function isAnyFeedWatched(fids) {
6896
+ for (const fid of fids) {
6897
+ const feed = this.activeFeeds[fid];
6898
+ if (feed && feed.currentState.last_get_or_create_request_config?.watch) {
6899
+ return true;
6900
+ }
6901
+ }
6902
+ return false;
6903
+ }
6904
+ function disconnectActivityFromFeed(id) {
6905
+ const activeFeed = this.activeActivities[id];
6906
+ if (activeFeed) {
6907
+ delete this.activeActivities[id];
6908
+ }
6909
+ }
6910
+ class ActivityWithStateUpdates {
6911
+ constructor(id, feedsClient) {
6912
+ this.id = id;
6913
+ this.feedsClient = feedsClient;
6914
+ this.state = new StateStore({
6915
+ activity: void 0,
6916
+ comments_by_entity_id: {},
6917
+ is_loading: false
6918
+ });
6919
+ }
6920
+ get currentState() {
6921
+ return this.state.getLatestValue();
6922
+ }
6923
+ get feeds() {
6924
+ return this.currentState.activity?.feeds ?? [];
6925
+ }
6926
+ /**
6927
+ * Fetch activity and load it into state
6928
+ * @param watch - Whether to watch the feed the activity belongs to for real-time updates
6929
+ * @param feed - The feed to watch. Use only if the activity belongs to multiple feeds and you want to specify the feed explicitly.
6930
+ * @param feedSelector - A function to select the feed from the activity response. Use only if the activity belongs to multiple feeds and you want to specify the feed explicitly.
6931
+ */
6932
+ async get(request = {}) {
6933
+ if (this.inProgressGet && deepEqual(this.inProgressGet.request, request)) {
6934
+ return this.inProgressGet.promise;
6935
+ }
6936
+ const { comments } = request;
6937
+ this.state.partialNext({
6938
+ is_loading: true,
6939
+ last_get_request_config: request
6940
+ });
6941
+ const getActivityRequest = this.feedsClient.getActivity({
6942
+ id: this.id
6943
+ }).then((response) => response.activity);
6944
+ this.inProgressGet = { request, promise: getActivityRequest };
6945
+ const activityResponse = await getActivityRequest;
6946
+ this.feedsClient.hydratePollCache([activityResponse]);
6947
+ this.setFeed({
6948
+ // We set feed to first containing feed
6949
+ // But in WS event handler we match events by any of the containing feeds, so as long as any of the containing feeds are watched, we'll do a state update
6950
+ // This is a bit hacky, proper solution would be to refactor all activity event handlers and detach them from feed instance
6951
+ fid: activityResponse.feeds[0],
6952
+ initialState: activityResponse
6953
+ });
6954
+ if (this.feed) {
6955
+ this.feed.activityAddedEventFilter = () => false;
6956
+ }
6957
+ if (comments) {
6958
+ await this.loadNextPageActivityComments(comments);
6959
+ }
6960
+ this.subscribeToFeedState();
6961
+ this.inProgressGet = void 0;
6962
+ return activityResponse;
6963
+ }
6964
+ loadNextPageActivityComments(request) {
6965
+ const activity = this.feed?.currentState.activities?.[0];
6966
+ if (!activity || !this.feed) {
6967
+ throw new Error("Initialize activity first");
6968
+ }
6969
+ if (!this.currentState.last_get_request_config?.comments) {
6970
+ this.state.partialNext({
6971
+ last_get_request_config: {
6972
+ ...this.currentState.last_get_request_config,
6973
+ comments: request
6974
+ }
6975
+ });
6976
+ }
6977
+ return this.feed.loadNextPageActivityComments(activity, request);
6978
+ }
6979
+ loadNextPageCommentReplies(...params) {
6980
+ if (!this.feed) {
6981
+ throw new Error("Initialize activity first");
6982
+ }
6983
+ return this.feed.loadNextPageCommentReplies(...params);
6984
+ }
6985
+ dispose() {
6986
+ this.unsubscribeFromFeedState?.();
6987
+ disconnectActivityFromFeed.call(this.feedsClient, this.id);
6988
+ }
6989
+ /**
6990
+ * @internal
6991
+ */
6992
+ async synchronize() {
6993
+ const allFids = this.currentState.activity?.feeds ?? [];
6994
+ if (!isAnyFeedWatched.call(this.feedsClient, allFids)) {
6995
+ return;
6996
+ }
6997
+ this.inProgressGet = void 0;
6998
+ return this.get(this.currentState.last_get_request_config);
6999
+ }
7000
+ setFeed({
7001
+ fid,
7002
+ initialState
7003
+ }) {
7004
+ this.feed = connectActivityToFeed.call(this.feedsClient, { fid });
7005
+ this.feed.state.partialNext({
7006
+ activities: [initialState]
7007
+ });
7008
+ }
7009
+ subscribeToFeedState() {
7010
+ this.unsubscribeFromFeedState?.();
7011
+ this.unsubscribeFromFeedState = this.feed?.state.subscribeWithSelector(
7012
+ (state) => ({
7013
+ activity: state.activities?.find((activity) => activity.id === this.id),
7014
+ comments_by_entity_id: state.comments_by_entity_id
7015
+ }),
7016
+ (state) => {
7017
+ if (state.activity) {
7018
+ this.state.partialNext({
7019
+ activity: state.activity,
7020
+ comments_by_entity_id: state.comments_by_entity_id,
7021
+ is_loading: false
7022
+ });
7023
+ }
7024
+ }
7025
+ );
7026
+ }
7027
+ }
7028
+ function getFeed() {
7029
+ return this.feed;
7030
+ }
6874
7031
  class FeedsClient extends FeedsApi {
6875
7032
  constructor(apiKey, options) {
6876
7033
  const tokenManager = new TokenManager();
@@ -6883,6 +7040,7 @@ class FeedsClient extends FeedsApi {
6883
7040
  );
6884
7041
  super(apiClient);
6885
7042
  this.eventDispatcher = new EventDispatcher();
7043
+ this.activeActivities = {};
6886
7044
  this.activeFeeds = {};
6887
7045
  this.healthyConnectionChangedEventCount = 0;
6888
7046
  this.setGetBatchOwnCapabilitiesThrottlingInterval = (throttlingMs) => {
@@ -6911,13 +7069,20 @@ class FeedsClient extends FeedsApi {
6911
7069
  this.recoverOnReconnect = async () => {
6912
7070
  this.healthyConnectionChangedEventCount++;
6913
7071
  if (this.healthyConnectionChangedEventCount > 1) {
6914
- const entries = Object.entries(this.activeFeeds);
6915
- const results = await Promise.allSettled(
6916
- entries.map(([, feed]) => feed.synchronize())
6917
- );
6918
- const failures = results.flatMap(
6919
- (result, index) => result.status === "rejected" ? [{ feed: entries[index][0], reason: result.reason }] : []
6920
- );
7072
+ const feedEntries = Object.entries(this.activeFeeds);
7073
+ const activityEntries = Object.entries(this.activeActivities);
7074
+ const results = await Promise.allSettled([
7075
+ ...feedEntries.map(([, feed]) => feed.synchronize()),
7076
+ ...activityEntries.map(([, activity]) => activity.synchronize())
7077
+ ]);
7078
+ const failures = results.flatMap((result, index) => {
7079
+ if (result.status === "fulfilled") {
7080
+ return [];
7081
+ }
7082
+ const activity = activityEntries[index - feedEntries.length]?.[1];
7083
+ const feed = feedEntries[index]?.[0] ?? (activity && getFeed.call(activity)?.feed);
7084
+ return [{ feed, reason: result.reason, activity_id: activity?.id }];
7085
+ });
6921
7086
  this.eventDispatcher.dispatch({
6922
7087
  type: "errors.unhandled",
6923
7088
  error_type: UnhandledErrorType.ReconnectionReconciliation,
@@ -6986,7 +7151,7 @@ class FeedsClient extends FeedsApi {
6986
7151
  };
6987
7152
  this.updateActivity = async (request) => {
6988
7153
  const response = await super.updateActivity(request);
6989
- for (const feed of Object.values(this.activeFeeds)) {
7154
+ for (const feed of this.allActiveFeeds) {
6990
7155
  handleActivityUpdated.bind(feed)(response, false);
6991
7156
  }
6992
7157
  return response;
@@ -6994,7 +7159,7 @@ class FeedsClient extends FeedsApi {
6994
7159
  this.addComment = async (request) => {
6995
7160
  const response = await super.addComment(request);
6996
7161
  const { comment } = response;
6997
- for (const feed of Object.values(this.activeFeeds)) {
7162
+ for (const feed of this.allActiveFeeds) {
6998
7163
  handleCommentAdded.bind(feed)(response, false);
6999
7164
  const parentActivityId = comment.object_id;
7000
7165
  if (feed.hasActivity(parentActivityId)) {
@@ -7017,7 +7182,7 @@ class FeedsClient extends FeedsApi {
7017
7182
  };
7018
7183
  this.updateComment = async (request) => {
7019
7184
  const response = await super.updateComment(request);
7020
- for (const feed of Object.values(this.activeFeeds)) {
7185
+ for (const feed of this.allActiveFeeds) {
7021
7186
  handleCommentUpdated.bind(feed)(response, false);
7022
7187
  }
7023
7188
  return response;
@@ -7025,7 +7190,7 @@ class FeedsClient extends FeedsApi {
7025
7190
  this.deleteComment = async (request) => {
7026
7191
  const response = await super.deleteComment(request);
7027
7192
  const { activity, comment } = response;
7028
- for (const feed of Object.values(this.activeFeeds)) {
7193
+ for (const feed of this.allActiveFeeds) {
7029
7194
  handleCommentDeleted.bind(feed)({ comment }, false);
7030
7195
  updateCommentCount.bind(feed)({
7031
7196
  activity,
@@ -7038,7 +7203,7 @@ class FeedsClient extends FeedsApi {
7038
7203
  this.addActivityReaction = async (request) => {
7039
7204
  const shouldEnforceUnique = request.enforce_unique;
7040
7205
  const response = await super.addActivityReaction(request);
7041
- for (const feed of Object.values(this.activeFeeds)) {
7206
+ for (const feed of this.allActiveFeeds) {
7042
7207
  if (shouldEnforceUnique) {
7043
7208
  handleActivityReactionUpdated.bind(feed)(response, false);
7044
7209
  } else {
@@ -7052,7 +7217,7 @@ class FeedsClient extends FeedsApi {
7052
7217
  };
7053
7218
  this.deleteActivityReaction = async (request) => {
7054
7219
  const response = await super.deleteActivityReaction(request);
7055
- for (const feed of Object.values(this.activeFeeds)) {
7220
+ for (const feed of this.allActiveFeeds) {
7056
7221
  handleActivityReactionDeleted.bind(feed)(response, false);
7057
7222
  }
7058
7223
  return response;
@@ -7060,7 +7225,7 @@ class FeedsClient extends FeedsApi {
7060
7225
  this.addCommentReaction = async (request) => {
7061
7226
  const shouldEnforceUnique = request.enforce_unique;
7062
7227
  const response = await super.addCommentReaction(request);
7063
- for (const feed of Object.values(this.activeFeeds)) {
7228
+ for (const feed of this.allActiveFeeds) {
7064
7229
  if (shouldEnforceUnique) {
7065
7230
  handleCommentReactionUpdated.bind(feed)(response, false);
7066
7231
  } else {
@@ -7071,7 +7236,7 @@ class FeedsClient extends FeedsApi {
7071
7236
  };
7072
7237
  this.deleteCommentReaction = async (request) => {
7073
7238
  const response = await super.deleteCommentReaction(request);
7074
- for (const feed of Object.values(this.activeFeeds)) {
7239
+ for (const feed of this.allActiveFeeds) {
7075
7240
  handleCommentReactionDeleted.bind(feed)(response, false);
7076
7241
  }
7077
7242
  return response;
@@ -7101,6 +7266,8 @@ class FeedsClient extends FeedsApi {
7101
7266
  this.connectionIdManager.reset();
7102
7267
  this.tokenManager.reset();
7103
7268
  this.polls_by_id.clear();
7269
+ this.activeActivities = {};
7270
+ this.activeFeeds = {};
7104
7271
  this.state.partialNext({
7105
7272
  connected_user: void 0,
7106
7273
  is_ws_connection_healthy: false,
@@ -7121,6 +7288,14 @@ class FeedsClient extends FeedsApi {
7121
7288
  options2?.activityAddedEventFilter
7122
7289
  );
7123
7290
  };
7291
+ this.activityWithStateUpdates = (id) => {
7292
+ let activity = this.activeActivities[id];
7293
+ if (!activity) {
7294
+ activity = new ActivityWithStateUpdates(id, this);
7295
+ this.activeActivities[id] = activity;
7296
+ }
7297
+ return activity;
7298
+ };
7124
7299
  this.updateNetworkConnectionStatus = (event) => {
7125
7300
  const networkEvent = {
7126
7301
  type: "network.changed",
@@ -7161,7 +7336,7 @@ class FeedsClient extends FeedsApi {
7161
7336
  feedsLoggerSystem.configureLoggers(options?.configure_loggers_options);
7162
7337
  this.on("all", (event) => {
7163
7338
  const fid = event.fid;
7164
- const feed = typeof fid === "string" ? this.activeFeeds[fid] : void 0;
7339
+ const feeds = this.findAllActiveFeedsFromWSEvent(event);
7165
7340
  switch (event.type) {
7166
7341
  case "connection.changed": {
7167
7342
  const { online } = event;
@@ -7169,14 +7344,14 @@ class FeedsClient extends FeedsApi {
7169
7344
  if (online) {
7170
7345
  this.recoverOnReconnect();
7171
7346
  } else {
7172
- for (const activeFeed of Object.values(this.activeFeeds)) {
7347
+ for (const activeFeed of this.allActiveFeeds) {
7173
7348
  handleWatchStopped.bind(activeFeed)();
7174
7349
  }
7175
7350
  }
7176
7351
  break;
7177
7352
  }
7178
7353
  case "feeds.feed.created": {
7179
- if (feed) break;
7354
+ if (this.activeFeeds[event.feed.id]) break;
7180
7355
  this.getOrCreateActiveFeed(
7181
7356
  event.feed.group_id,
7182
7357
  event.feed.id,
@@ -7185,9 +7360,15 @@ class FeedsClient extends FeedsApi {
7185
7360
  break;
7186
7361
  }
7187
7362
  case "feeds.feed.deleted": {
7188
- feed?.handleWSEvent(event);
7363
+ feeds.forEach((f) => f.handleWSEvent(event));
7189
7364
  if (typeof fid === "string") {
7190
7365
  delete this.activeFeeds[fid];
7366
+ Object.keys(this.activeActivities).forEach((activityId) => {
7367
+ const activity = this.activeActivities[activityId];
7368
+ if (getFeed.call(activity)?.feed === fid) {
7369
+ delete this.activeActivities[activityId];
7370
+ }
7371
+ });
7191
7372
  }
7192
7373
  break;
7193
7374
  }
@@ -7200,7 +7381,7 @@ class FeedsClient extends FeedsApi {
7200
7381
  case "feeds.poll.deleted": {
7201
7382
  if (event.poll?.id) {
7202
7383
  this.polls_by_id.delete(event.poll.id);
7203
- for (const activeFeed of Object.values(this.activeFeeds)) {
7384
+ for (const activeFeed of this.allActiveFeeds) {
7204
7385
  const currentActivities = activeFeed.currentState.activities;
7205
7386
  if (currentActivities) {
7206
7387
  const newActivities = [];
@@ -7248,14 +7429,14 @@ class FeedsClient extends FeedsApi {
7248
7429
  case "feeds.bookmark.deleted":
7249
7430
  case "feeds.bookmark.updated": {
7250
7431
  const activityId = event.bookmark.activity.id;
7251
- const feeds = this.findActiveFeedsByActivityId(activityId);
7252
- feeds.forEach((f) => f.handleWSEvent(event));
7432
+ const allFeeds = this.findAllActiveFeedsByActivityId(activityId);
7433
+ allFeeds.forEach((f) => f.handleWSEvent(event));
7253
7434
  break;
7254
7435
  }
7255
7436
  case "feeds.activity.feedback": {
7256
7437
  const activityId = event.activity_feedback.activity_id;
7257
- const feeds = this.findActiveFeedsByActivityId(activityId);
7258
- feeds.forEach((f) => f.handleWSEvent(event));
7438
+ const allFeeds = this.findAllActiveFeedsByActivityId(activityId);
7439
+ allFeeds.forEach((f) => f.handleWSEvent(event));
7259
7440
  break;
7260
7441
  }
7261
7442
  case "user.updated": {
@@ -7263,11 +7444,20 @@ class FeedsClient extends FeedsApi {
7263
7444
  break;
7264
7445
  }
7265
7446
  default: {
7266
- feed?.handleWSEvent(event);
7447
+ feeds.forEach((f) => f.handleWSEvent(event));
7448
+ if (event.type === "feeds.activity.deleted") {
7449
+ delete this.activeActivities[event.activity.id];
7450
+ }
7267
7451
  }
7268
7452
  }
7269
7453
  });
7270
7454
  }
7455
+ get allActiveFeeds() {
7456
+ return [
7457
+ ...Object.values(this.activeFeeds),
7458
+ ...Object.values(this.activeActivities).filter((a) => !!getFeed.call(a)).map((a) => getFeed.call(a))
7459
+ ];
7460
+ }
7271
7461
  hydratePollCache(activities) {
7272
7462
  for (const activity of activities) {
7273
7463
  if (!activity.poll) {
@@ -7339,10 +7529,8 @@ class FeedsClient extends FeedsApi {
7339
7529
  response.follow.source_feed.feed,
7340
7530
  response.follow.target_feed.feed
7341
7531
  ].forEach((fid) => {
7342
- const feed = this.activeFeeds[fid];
7343
- if (feed) {
7344
- handleFollowUpdated.bind(feed)(response, false);
7345
- }
7532
+ const feeds = this.findAllActiveFeedsByFid(fid);
7533
+ feeds.forEach((f) => handleFollowUpdated.bind(f)(response, false));
7346
7534
  });
7347
7535
  return response;
7348
7536
  }
@@ -7353,30 +7541,24 @@ class FeedsClient extends FeedsApi {
7353
7541
  response.follow.source_feed.feed,
7354
7542
  response.follow.target_feed.feed
7355
7543
  ].forEach((fid) => {
7356
- const feed = this.activeFeeds[fid];
7357
- if (feed) {
7358
- handleFollowCreated.bind(feed)(response, false);
7359
- }
7544
+ const feeds = this.findAllActiveFeedsByFid(fid);
7545
+ feeds.forEach((f) => handleFollowCreated.bind(f)(response, false));
7360
7546
  });
7361
7547
  return response;
7362
7548
  }
7363
7549
  async followBatch(request) {
7364
7550
  const response = await super.followBatch(request);
7365
7551
  response.follows.forEach((follow) => {
7366
- const feed = this.activeFeeds[follow.source_feed.feed];
7367
- if (feed) {
7368
- handleFollowCreated.bind(feed)({ follow });
7369
- }
7552
+ const feeds = this.findAllActiveFeedsByFid(follow.source_feed.feed);
7553
+ feeds.forEach((f) => handleFollowCreated.bind(f)({ follow }, false));
7370
7554
  });
7371
7555
  return response;
7372
7556
  }
7373
7557
  async unfollow(request) {
7374
7558
  const response = await super.unfollow(request);
7375
7559
  [request.source, request.target].forEach((fid) => {
7376
- const feed = this.activeFeeds[fid];
7377
- if (feed) {
7378
- handleFollowDeleted.bind(feed)(response, false);
7379
- }
7560
+ const feeds = this.findAllActiveFeedsByFid(fid);
7561
+ feeds.forEach((f) => handleFollowDeleted.bind(f)(response, false));
7380
7562
  });
7381
7563
  return response;
7382
7564
  }
@@ -7386,19 +7568,65 @@ class FeedsClient extends FeedsApi {
7386
7568
  ...request,
7387
7569
  connection_id: connectionId
7388
7570
  });
7389
- const feed = this.activeFeeds[`${request.feed_group_id}:${request.feed_id}`];
7390
- if (feed) {
7391
- handleWatchStopped.bind(feed)();
7571
+ const feeds = this.findAllActiveFeedsByFid(
7572
+ `${request.feed_group_id}:${request.feed_id}`
7573
+ );
7574
+ feeds.forEach((f) => handleWatchStopped.bind(f)());
7575
+ return response;
7576
+ }
7577
+ async getOrCreateFeed(request) {
7578
+ const response = await super.getOrCreateFeed(request);
7579
+ this.hydrateCapabilitiesCache([response.feed]);
7580
+ if (request.watch) {
7581
+ const feeds = this.findAllActiveFeedsByFid(
7582
+ `${request.feed_group_id}:${request.feed_id}`
7583
+ );
7584
+ feeds.forEach((f) => handleWatchStarted.bind(f)());
7392
7585
  }
7393
7586
  return response;
7394
7587
  }
7395
- findActiveFeedsByActivityId(activityId) {
7396
- return Object.values(this.activeFeeds).filter(
7588
+ findAllActiveFeedsByActivityId(activityId) {
7589
+ return [
7590
+ ...Object.values(this.activeFeeds),
7591
+ ...Object.values(this.activeActivities).filter((a) => !!getFeed.call(a)).map((a) => getFeed.call(a))
7592
+ ].filter(
7397
7593
  (feed) => feed.hasActivity(activityId) || feed.hasPinnedActivity(activityId)
7398
7594
  );
7399
7595
  }
7596
+ findAllActiveFeedsByFid(fid) {
7597
+ if (!fid) return [];
7598
+ const activeFeed = this.activeFeeds[fid];
7599
+ return [
7600
+ ...activeFeed ? [activeFeed] : [],
7601
+ ...Object.values(this.activeActivities).filter((a) => getFeed.call(a)?.feed === fid).map((a) => getFeed.call(a))
7602
+ ];
7603
+ }
7604
+ /**
7605
+ * When updating from WS events we need a special logic:
7606
+ * - Find active feeds that match a given fid.
7607
+ * - Find active feed from activities where fid matches any of the feeds the activity is posted to.
7608
+ *
7609
+ * This logic is different from `findAllActiveFeedsByFid` which only checks the first feed an activity is posted to.
7610
+ *
7611
+ * @param fid
7612
+ * @param activityId
7613
+ * @returns
7614
+ */
7615
+ findAllActiveFeedsFromWSEvent(event) {
7616
+ const fid = "fid" in event ? event.fid : void 0;
7617
+ if (!fid) return [];
7618
+ const activeFeed = fid ? this.activeFeeds[fid] : void 0;
7619
+ return [
7620
+ ...activeFeed ? [activeFeed] : [],
7621
+ ...Object.values(this.activeActivities).filter((a) => {
7622
+ const feed = getFeed.call(a);
7623
+ return feed?.feed === fid || a.currentState.activity?.feeds.some((f) => f === fid);
7624
+ }).map((a) => getFeed.call(a))
7625
+ ];
7626
+ }
7400
7627
  }
7401
7628
  export {
7629
+ ActivityWithStateUpdates as A,
7402
7630
  Constants as C,
7403
7631
  FeedsClient as F,
7404
7632
  StreamApiError as S,
@@ -7420,4 +7648,4 @@ export {
7420
7648
  shouldUpdateState as s,
7421
7649
  uniqueArrayMerge as u
7422
7650
  };
7423
- //# sourceMappingURL=feeds-client-3aXF89xy.mjs.map
7651
+ //# sourceMappingURL=feeds-client-CI-WG0y0.mjs.map