@stream-io/feeds-client 0.1.9 → 0.1.11

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 (167) hide show
  1. package/@react-bindings/hooks/search-state-hooks/index.ts +3 -0
  2. package/@react-bindings/index.ts +5 -0
  3. package/CHANGELOG.md +20 -0
  4. package/dist/@react-bindings/contexts/StreamFeedContext.d.ts +1 -1
  5. package/dist/@react-bindings/contexts/StreamFeedsContext.d.ts +1 -1
  6. package/dist/@react-bindings/contexts/StreamSearchContext.d.ts +12 -0
  7. package/dist/@react-bindings/contexts/StreamSearchResultsContext.d.ts +12 -0
  8. package/dist/@react-bindings/hooks/feed-state-hooks/useComments.d.ts +1 -1
  9. package/dist/@react-bindings/hooks/feed-state-hooks/useFeedActivities.d.ts +1 -1
  10. package/dist/@react-bindings/hooks/feed-state-hooks/useFeedMetadata.d.ts +1 -1
  11. package/dist/@react-bindings/hooks/feed-state-hooks/useFollowers.d.ts +1 -1
  12. package/dist/@react-bindings/hooks/feed-state-hooks/useFollowing.d.ts +1 -1
  13. package/dist/@react-bindings/hooks/feed-state-hooks/useOwnCapabilities.d.ts +1 -1
  14. package/dist/@react-bindings/hooks/feed-state-hooks/useOwnFollows.d.ts +1 -1
  15. package/dist/@react-bindings/hooks/search-state-hooks/index.d.ts +3 -0
  16. package/dist/@react-bindings/hooks/search-state-hooks/useSearchQuery.d.ts +4 -0
  17. package/dist/@react-bindings/hooks/search-state-hooks/useSearchResult.d.ts +8 -0
  18. package/dist/@react-bindings/hooks/search-state-hooks/useSearchSources.d.ts +4 -0
  19. package/dist/@react-bindings/hooks/useCreateFeedsClient.d.ts +1 -1
  20. package/dist/@react-bindings/index.d.ts +5 -0
  21. package/dist/@react-bindings/wrappers/StreamFeed.d.ts +1 -1
  22. package/dist/@react-bindings/wrappers/StreamSearch.d.ts +12 -0
  23. package/dist/@react-bindings/wrappers/StreamSearchResults.d.ts +12 -0
  24. package/dist/index-react-bindings.browser.cjs +1669 -1529
  25. package/dist/index-react-bindings.browser.cjs.map +1 -1
  26. package/dist/index-react-bindings.browser.js +1661 -1530
  27. package/dist/index-react-bindings.browser.js.map +1 -1
  28. package/dist/index-react-bindings.node.cjs +1669 -1529
  29. package/dist/index-react-bindings.node.cjs.map +1 -1
  30. package/dist/index-react-bindings.node.js +1661 -1530
  31. package/dist/index-react-bindings.node.js.map +1 -1
  32. package/dist/index.browser.cjs +1615 -1640
  33. package/dist/index.browser.cjs.map +1 -1
  34. package/dist/index.browser.js +1613 -1641
  35. package/dist/index.browser.js.map +1 -1
  36. package/dist/index.d.ts +2 -2
  37. package/dist/index.node.cjs +1615 -1640
  38. package/dist/index.node.cjs.map +1 -1
  39. package/dist/index.node.js +1613 -1641
  40. package/dist/index.node.js.map +1 -1
  41. package/dist/src/common/ActivitySearchSource.d.ts +1 -1
  42. package/dist/src/common/BaseSearchSource.d.ts +3 -1
  43. package/dist/src/common/FeedSearchSource.d.ts +7 -3
  44. package/dist/src/common/Poll.d.ts +1 -1
  45. package/dist/src/common/SearchController.d.ts +2 -0
  46. package/dist/src/common/UserSearchSource.d.ts +1 -1
  47. package/dist/src/common/real-time/StableWSConnection.d.ts +3 -3
  48. package/dist/src/feed/event-handlers/activity/handle-activity-added.d.ts +7 -0
  49. package/dist/src/feed/event-handlers/activity/handle-activity-deleted.d.ts +8 -0
  50. package/dist/src/feed/event-handlers/activity/handle-activity-reaction-added.d.ts +8 -0
  51. package/dist/src/feed/event-handlers/activity/handle-activity-reaction-deleted.d.ts +8 -0
  52. package/dist/src/feed/event-handlers/activity/handle-activity-removed-from-feed.d.ts +3 -0
  53. package/dist/src/feed/event-handlers/activity/handle-activity-updated.d.ts +8 -0
  54. package/dist/src/feed/event-handlers/activity/index.d.ts +6 -0
  55. package/dist/src/feed/event-handlers/bookmark/handle-bookmark-added.d.ts +8 -0
  56. package/dist/src/feed/event-handlers/bookmark/handle-bookmark-deleted.d.ts +9 -0
  57. package/dist/src/feed/event-handlers/bookmark/handle-bookmark-updated.d.ts +8 -0
  58. package/dist/src/feed/event-handlers/bookmark/index.d.ts +3 -0
  59. package/dist/src/feed/event-handlers/comment/handle-comment-added.d.ts +3 -0
  60. package/dist/src/feed/event-handlers/comment/handle-comment-deleted.d.ts +3 -0
  61. package/dist/src/feed/event-handlers/comment/handle-comment-reaction.d.ts +3 -0
  62. package/dist/src/feed/event-handlers/comment/handle-comment-updated.d.ts +3 -0
  63. package/dist/src/feed/event-handlers/comment/index.d.ts +4 -0
  64. package/dist/src/feed/event-handlers/feed/handle-feed-updated.d.ts +3 -0
  65. package/dist/src/feed/event-handlers/feed/index.d.ts +1 -0
  66. package/dist/src/feed/event-handlers/feed-member/handle-feed-member-added.d.ts +3 -0
  67. package/dist/src/feed/event-handlers/feed-member/handle-feed-member-removed.d.ts +3 -0
  68. package/dist/src/feed/event-handlers/feed-member/handle-feed-member-updated.d.ts +3 -0
  69. package/dist/src/feed/event-handlers/feed-member/index.d.ts +3 -0
  70. package/dist/src/feed/event-handlers/follow/handle-follow-created.d.ts +7 -0
  71. package/dist/src/feed/event-handlers/follow/handle-follow-deleted.d.ts +7 -0
  72. package/dist/src/feed/event-handlers/follow/handle-follow-updated.d.ts +3 -0
  73. package/dist/src/feed/event-handlers/follow/index.d.ts +3 -0
  74. package/dist/src/feed/event-handlers/index.d.ts +7 -0
  75. package/dist/src/feed/event-handlers/notification-feed/handle-notification-feed-updated.d.ts +3 -0
  76. package/dist/src/feed/event-handlers/notification-feed/index.d.ts +1 -0
  77. package/dist/src/{Feed.d.ts → feed/feed.d.ts} +15 -34
  78. package/dist/src/feed/index.d.ts +2 -0
  79. package/dist/src/{FeedsClient.d.ts → feeds-client.d.ts} +6 -5
  80. package/dist/src/gen/models/index.d.ts +5 -0
  81. package/dist/src/gen-imports.d.ts +1 -1
  82. package/dist/src/test-utils/index.d.ts +1 -0
  83. package/dist/src/test-utils/response-generators.d.ts +9 -0
  84. package/dist/src/types-internal.d.ts +7 -0
  85. package/dist/src/types.d.ts +1 -1
  86. package/dist/src/utils/check-has-another-page.d.ts +1 -0
  87. package/dist/src/utils/constants.d.ts +3 -0
  88. package/dist/src/utils/index.d.ts +5 -0
  89. package/dist/src/utils/state-update-queue.d.ts +6 -0
  90. package/dist/src/utils/type-assertions.d.ts +7 -0
  91. package/dist/src/utils/unique-array-merge.d.ts +1 -0
  92. package/dist/tsconfig.tsbuildinfo +1 -1
  93. package/index.ts +2 -2
  94. package/package.json +2 -1
  95. package/src/common/ActivitySearchSource.ts +6 -16
  96. package/src/common/BaseSearchSource.ts +9 -9
  97. package/src/common/FeedSearchSource.ts +22 -67
  98. package/src/common/Poll.ts +1 -1
  99. package/src/common/SearchController.ts +2 -0
  100. package/src/common/UserSearchSource.ts +10 -62
  101. package/src/{state-updates → feed/event-handlers/activity}/activity-reaction-utils.test.ts +12 -2
  102. package/src/{state-updates → feed/event-handlers/activity}/activity-utils.test.ts +3 -2
  103. package/src/{state-updates/activity-utils.ts → feed/event-handlers/activity/handle-activity-added.ts} +16 -36
  104. package/src/feed/event-handlers/activity/handle-activity-deleted.ts +30 -0
  105. package/src/feed/event-handlers/activity/handle-activity-reaction-added.ts +67 -0
  106. package/src/feed/event-handlers/activity/handle-activity-reaction-deleted.ts +75 -0
  107. package/src/feed/event-handlers/activity/handle-activity-removed-from-feed.ts +16 -0
  108. package/src/feed/event-handlers/activity/handle-activity-updated.ts +47 -0
  109. package/src/feed/event-handlers/activity/index.ts +6 -0
  110. package/src/{state-updates → feed/event-handlers/bookmark}/bookmark-utils.test.ts +2 -2
  111. package/src/feed/event-handlers/bookmark/handle-bookmark-added.ts +63 -0
  112. package/src/feed/event-handlers/bookmark/handle-bookmark-deleted.ts +84 -0
  113. package/src/feed/event-handlers/bookmark/handle-bookmark-updated.ts +76 -0
  114. package/src/feed/event-handlers/bookmark/index.ts +3 -0
  115. package/src/feed/event-handlers/comment/handle-comment-added.ts +38 -0
  116. package/src/feed/event-handlers/comment/handle-comment-deleted.ts +35 -0
  117. package/src/feed/event-handlers/comment/handle-comment-reaction.ts +61 -0
  118. package/src/feed/event-handlers/comment/handle-comment-updated.ts +35 -0
  119. package/src/feed/event-handlers/comment/index.ts +4 -0
  120. package/src/feed/event-handlers/feed/handle-feed-updated.ts +9 -0
  121. package/src/feed/event-handlers/feed/index.ts +1 -0
  122. package/src/feed/event-handlers/feed-member/handle-feed-member-added.ts +31 -0
  123. package/src/feed/event-handlers/feed-member/handle-feed-member-removed.ts +24 -0
  124. package/src/feed/event-handlers/feed-member/handle-feed-member-updated.ts +40 -0
  125. package/src/feed/event-handlers/feed-member/index.ts +3 -0
  126. package/src/feed/event-handlers/follow/handle-follow-created.test.ts +246 -0
  127. package/src/feed/event-handlers/follow/handle-follow-created.ts +93 -0
  128. package/src/feed/event-handlers/follow/handle-follow-deleted.test.ts +264 -0
  129. package/src/feed/event-handlers/follow/handle-follow-deleted.ts +95 -0
  130. package/src/feed/event-handlers/follow/handle-follow-updated.test.ts +174 -0
  131. package/src/feed/event-handlers/follow/handle-follow-updated.ts +88 -0
  132. package/src/feed/event-handlers/follow/index.ts +3 -0
  133. package/src/feed/event-handlers/index.ts +7 -0
  134. package/src/feed/event-handlers/notification-feed/handle-notification-feed-updated.ts +10 -0
  135. package/src/feed/event-handlers/notification-feed/index.ts +1 -0
  136. package/src/{Feed.ts → feed/feed.ts} +72 -483
  137. package/src/feed/index.ts +2 -0
  138. package/src/{FeedsClient.ts → feeds-client.ts} +26 -8
  139. package/src/gen/model-decoders/decoders.ts +7 -0
  140. package/src/gen/models/index.ts +10 -0
  141. package/src/gen-imports.ts +1 -1
  142. package/src/test-utils/index.ts +1 -0
  143. package/src/test-utils/response-generators.ts +102 -0
  144. package/src/types-internal.ts +11 -0
  145. package/src/types.ts +1 -1
  146. package/src/utils/check-has-another-page.ts +6 -0
  147. package/src/utils/constants.ts +3 -0
  148. package/src/utils/index.ts +5 -0
  149. package/src/{state-updates → utils}/state-update-queue.test.ts +6 -6
  150. package/src/utils/state-update-queue.ts +42 -0
  151. package/src/utils/type-assertions.ts +22 -0
  152. package/src/{utils.test.ts → utils/unique-array-merge.test.ts} +7 -3
  153. package/src/utils/unique-array-merge.ts +19 -0
  154. package/dist/src/state-updates/activity-reaction-utils.d.ts +0 -10
  155. package/dist/src/state-updates/activity-utils.d.ts +0 -13
  156. package/dist/src/state-updates/bookmark-utils.d.ts +0 -14
  157. package/dist/src/state-updates/follow-utils.d.ts +0 -19
  158. package/dist/src/state-updates/state-update-queue.d.ts +0 -15
  159. package/dist/src/utils.d.ts +0 -10
  160. package/src/state-updates/activity-reaction-utils.ts +0 -107
  161. package/src/state-updates/bookmark-utils.ts +0 -167
  162. package/src/state-updates/follow-utils.test.ts +0 -552
  163. package/src/state-updates/follow-utils.ts +0 -126
  164. package/src/state-updates/state-update-queue.ts +0 -35
  165. package/src/utils.ts +0 -48
  166. /package/dist/src/{ModerationClient.d.ts → moderation-client.d.ts} +0 -0
  167. /package/src/{ModerationClient.ts → moderation-client.ts} +0 -0
@@ -0,0 +1,174 @@
1
+ import { describe, it, expect, beforeEach } from 'vitest';
2
+ import { Feed } from '../../../feed';
3
+ import { FeedsClient } from '../../../feeds-client';
4
+ import { handleFollowUpdated } from './handle-follow-updated';
5
+ import {
6
+ generateFollowResponse,
7
+ generateFeedResponse,
8
+ getHumanId,
9
+ generateOwnUser,
10
+ } from '../../../test-utils/response-generators';
11
+ import { FollowResponse } from '../../../gen/models';
12
+ import { shouldUpdateState } from '../../../utils';
13
+
14
+ describe(handleFollowUpdated.name, () => {
15
+ let feed: Feed;
16
+ let client: FeedsClient;
17
+ let follow: FollowResponse;
18
+ let otherFollow: FollowResponse;
19
+ let ownFollow: FollowResponse;
20
+ let userId: string;
21
+
22
+ beforeEach(() => {
23
+ userId = getHumanId();
24
+ client = new FeedsClient('mock-api-key');
25
+
26
+ client.state.partialNext({
27
+ connected_user: generateOwnUser({ id: userId }),
28
+ });
29
+
30
+ const feedResponse = generateFeedResponse({
31
+ id: 'main',
32
+ group_id: 'user',
33
+ created_by: { id: userId },
34
+ });
35
+ feed = new Feed(client, 'user', 'main', feedResponse);
36
+ // Setup follows
37
+ follow = generateFollowResponse({
38
+ source_feed: generateFeedResponse({
39
+ id: 'main',
40
+ group_id: 'user',
41
+ created_by: { id: userId },
42
+ }),
43
+ target_feed: generateFeedResponse({
44
+ id: 'target',
45
+ group_id: 'user',
46
+ }),
47
+ });
48
+
49
+ otherFollow = generateFollowResponse({
50
+ source_feed: generateFeedResponse({
51
+ id: 'other',
52
+ group_id: 'user',
53
+ created_by: { id: getHumanId() },
54
+ }),
55
+ target_feed: generateFeedResponse({
56
+ id: 'main',
57
+ group_id: 'user',
58
+ }),
59
+ });
60
+
61
+ ownFollow = generateFollowResponse({
62
+ source_feed: generateFeedResponse({
63
+ id: 'other',
64
+ group_id: 'user',
65
+ created_by: { id: userId },
66
+ }),
67
+ target_feed: generateFeedResponse({
68
+ id: 'main',
69
+ group_id: 'user',
70
+ }),
71
+ });
72
+ // Set up initial state
73
+ feed.state.next((currentState) => ({
74
+ ...currentState,
75
+ following: [follow],
76
+ followers: [otherFollow],
77
+ own_follows: [ownFollow],
78
+ }));
79
+ });
80
+
81
+ it('updates a follow in following when this feed is the source', () => {
82
+ const updatedFollow: FollowResponse = { ...follow, status: 'pending' };
83
+
84
+ handleFollowUpdated.call(feed, { follow: updatedFollow });
85
+
86
+ const [updatedFollowAfter] = feed.currentState.following!;
87
+
88
+ expect(updatedFollowAfter).toBe(updatedFollow);
89
+ });
90
+
91
+ it('updates a follow in followers when this feed is the target', () => {
92
+ const updatedOtherFollow: FollowResponse = {
93
+ ...otherFollow,
94
+ status: 'rejected',
95
+ };
96
+
97
+ handleFollowUpdated.call(feed, { follow: updatedOtherFollow });
98
+
99
+ const [updatedOtherFollowAfter] = feed.currentState.followers!;
100
+
101
+ expect(updatedOtherFollowAfter).toBe(updatedOtherFollow);
102
+ });
103
+
104
+ it('updates a follow in own_follows when connected user is the creator', () => {
105
+ const updatedOwnFollow: FollowResponse = {
106
+ ...ownFollow,
107
+ status: 'pending',
108
+ };
109
+
110
+ handleFollowUpdated.call(feed, { follow: updatedOwnFollow });
111
+
112
+ const [ownFollowAfter] = feed.currentState.own_follows!;
113
+
114
+ expect(ownFollowAfter).toBe(updatedOwnFollow);
115
+ });
116
+
117
+ it('does not update if follow is not found', () => {
118
+ const unrelatedFollow = generateFollowResponse();
119
+
120
+ const stateBefore = feed.currentState;
121
+
122
+ handleFollowUpdated.call(feed, { follow: unrelatedFollow });
123
+
124
+ const stateAfter = feed.currentState;
125
+
126
+ expect(stateAfter.own_follows).toBe(stateBefore.own_follows);
127
+ expect(stateAfter.followers).toBe(stateBefore.followers);
128
+ expect(stateAfter.follower_count).toBe(stateBefore.follower_count);
129
+ expect(stateAfter.following).toBe(stateBefore.following);
130
+ expect(stateAfter.following_count).toBe(stateBefore.following_count);
131
+ });
132
+
133
+ describe(`${shouldUpdateState.name} integration`, () => {
134
+ it(`skips update if ${shouldUpdateState.name} returns false`, () => {
135
+ // Prepare feed, set as watched
136
+ feed.state.partialNext({ watch: true });
137
+
138
+ const updatedFollow: FollowResponse = { ...follow, status: 'pending' };
139
+
140
+ // Call once to populate queue
141
+ handleFollowUpdated.call(feed, { follow: updatedFollow });
142
+
143
+ // Call again, should be skipped
144
+ const stateBefore = feed.currentState;
145
+ handleFollowUpdated.call(feed, {
146
+ follow: { ...updatedFollow, status: 'accepted' },
147
+ });
148
+
149
+ // State should not change
150
+ const stateAfter = feed.currentState;
151
+ expect(stateAfter).toEqual(stateBefore);
152
+ });
153
+
154
+ it('allows update again after clearing stateUpdateQueue', () => {
155
+ const updatedFollow: FollowResponse = { ...follow, status: 'pending' };
156
+
157
+ handleFollowUpdated.call(feed, { follow: updatedFollow });
158
+
159
+ // Clear the queue
160
+ (feed as any).stateUpdateQueue.clear();
161
+
162
+ // Now update should be allowed
163
+ handleFollowUpdated.call(feed, {
164
+ follow: { ...updatedFollow, status: 'accepted' },
165
+ });
166
+
167
+ const [updatedFollowAfter] = feed.currentState.following!;
168
+
169
+ expect(updatedFollowAfter).toMatchObject({
170
+ status: 'accepted',
171
+ });
172
+ });
173
+ });
174
+ });
@@ -0,0 +1,88 @@
1
+ import type { Feed, FeedState } from '../../../feed';
2
+ import {
3
+ getStateUpdateQueueId,
4
+ shouldUpdateState,
5
+ } from '../../../utils';
6
+ import { EventPayload, PartializeAllBut } from '../../../types-internal';
7
+
8
+ export function handleFollowUpdated(
9
+ this: Feed,
10
+ eventOrResponse: PartializeAllBut<
11
+ EventPayload<'feeds.follow.updated'>,
12
+ 'follow'
13
+ >,
14
+ ) {
15
+ const follow = eventOrResponse.follow;
16
+ const connectedUserId = this.client.state.getLatestValue().connected_user?.id;
17
+ const currentFeedId = this.fid;
18
+
19
+ if (
20
+ !shouldUpdateState({
21
+ stateUpdateQueueId: getStateUpdateQueueId(follow, 'updated'),
22
+ stateUpdateQueue: this.stateUpdateQueue,
23
+ watch: this.currentState.watch,
24
+ })
25
+ ) {
26
+ return;
27
+ }
28
+
29
+ this.state.next((currentState) => {
30
+ let newState: FeedState | undefined;
31
+
32
+ // this feed followed someone
33
+ if (follow.source_feed.fid === currentFeedId) {
34
+ newState ??= {
35
+ ...currentState,
36
+ // Update FeedResponse fields, that has the new follower/following count
37
+ ...follow.source_feed,
38
+ };
39
+
40
+ const index =
41
+ currentState.following?.findIndex(
42
+ (f) => f.target_feed.fid === follow.target_feed.fid,
43
+ ) ?? -1;
44
+
45
+ if (index >= 0) {
46
+ newState.following = [...newState.following!];
47
+ newState.following[index] = follow;
48
+ }
49
+ } else if (
50
+ // someone followed this feed
51
+ follow.target_feed.fid === currentFeedId
52
+ ) {
53
+ const source = follow.source_feed;
54
+
55
+ newState ??= {
56
+ ...currentState,
57
+ // Update FeedResponse fields, that has the new follower/following count
58
+ ...follow.target_feed,
59
+ };
60
+
61
+ if (
62
+ source.created_by.id === connectedUserId &&
63
+ currentState.own_follows
64
+ ) {
65
+ const index = currentState.own_follows.findIndex(
66
+ (f) => f.source_feed.fid === follow.source_feed.fid,
67
+ );
68
+
69
+ if (index >= 0) {
70
+ newState.own_follows = [...currentState.own_follows];
71
+ newState.own_follows[index] = follow;
72
+ }
73
+ }
74
+
75
+ const index =
76
+ currentState.followers?.findIndex(
77
+ (f) => f.source_feed.fid === follow.source_feed.fid,
78
+ ) ?? -1;
79
+
80
+ if (index >= 0) {
81
+ newState.followers = [...newState.followers!];
82
+ newState.followers[index] = follow;
83
+ }
84
+ }
85
+
86
+ return newState ?? currentState;
87
+ });
88
+ }
@@ -0,0 +1,3 @@
1
+ export * from './handle-follow-created';
2
+ export * from './handle-follow-deleted';
3
+ export * from './handle-follow-updated';
@@ -0,0 +1,7 @@
1
+ export * from './follow';
2
+ export * from './comment';
3
+ export * from './feed-member';
4
+ export * from './bookmark';
5
+ export * from './activity';
6
+ export * from './feed';
7
+ export * from './notification-feed';
@@ -0,0 +1,10 @@
1
+ import type { Feed } from '../../../feed';
2
+ import type { EventPayload } from '../../../types-internal';
3
+
4
+ export function handleNotificationFeedUpdated(
5
+ this: Feed,
6
+ event: EventPayload<'feeds.notification_feed.updated'>,
7
+ ) {
8
+ console.info('notification feed updated', event);
9
+ // TODO: handle notification feed updates
10
+ }
@@ -0,0 +1 @@
1
+ export * from './handle-notification-feed-updated'