@stream-io/feeds-client 0.1.0
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.
- package/@react-bindings/index.ts +2 -0
- package/CHANGELOG.md +44 -0
- package/LICENSE +219 -0
- package/README.md +9 -0
- package/dist/@react-bindings/hooks/useComments.d.ts +12 -0
- package/dist/@react-bindings/hooks/useStateStore.d.ts +3 -0
- package/dist/@react-bindings/index.d.ts +2 -0
- package/dist/index-react-bindings.browser.cjs +56 -0
- package/dist/index-react-bindings.browser.cjs.map +1 -0
- package/dist/index-react-bindings.browser.js +53 -0
- package/dist/index-react-bindings.browser.js.map +1 -0
- package/dist/index-react-bindings.node.cjs +56 -0
- package/dist/index-react-bindings.node.cjs.map +1 -0
- package/dist/index-react-bindings.node.js +53 -0
- package/dist/index-react-bindings.node.js.map +1 -0
- package/dist/index.browser.cjs +5799 -0
- package/dist/index.browser.cjs.map +1 -0
- package/dist/index.browser.js +5782 -0
- package/dist/index.browser.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.node.cjs +5799 -0
- package/dist/index.node.cjs.map +1 -0
- package/dist/index.node.js +5782 -0
- package/dist/index.node.js.map +1 -0
- package/dist/src/Feed.d.ts +109 -0
- package/dist/src/FeedsClient.d.ts +63 -0
- package/dist/src/ModerationClient.d.ts +3 -0
- package/dist/src/common/ActivitySearchSource.d.ts +17 -0
- package/dist/src/common/ApiClient.d.ts +20 -0
- package/dist/src/common/BaseSearchSource.d.ts +87 -0
- package/dist/src/common/ConnectionIdManager.d.ts +11 -0
- package/dist/src/common/EventDispatcher.d.ts +11 -0
- package/dist/src/common/FeedSearchSource.d.ts +17 -0
- package/dist/src/common/Poll.d.ts +34 -0
- package/dist/src/common/SearchController.d.ts +41 -0
- package/dist/src/common/StateStore.d.ts +124 -0
- package/dist/src/common/TokenManager.d.ts +29 -0
- package/dist/src/common/UserSearchSource.d.ts +17 -0
- package/dist/src/common/gen-imports.d.ts +2 -0
- package/dist/src/common/rate-limit.d.ts +2 -0
- package/dist/src/common/real-time/StableWSConnection.d.ts +144 -0
- package/dist/src/common/real-time/event-models.d.ts +36 -0
- package/dist/src/common/types.d.ts +29 -0
- package/dist/src/common/utils.d.ts +54 -0
- package/dist/src/gen/feeds/FeedApi.d.ts +26 -0
- package/dist/src/gen/feeds/FeedsApi.d.ts +237 -0
- package/dist/src/gen/model-decoders/decoders.d.ts +3 -0
- package/dist/src/gen/model-decoders/event-decoder-mapping.d.ts +6 -0
- package/dist/src/gen/models/index.d.ts +3437 -0
- package/dist/src/gen/moderation/ModerationApi.d.ts +21 -0
- package/dist/src/gen-imports.d.ts +3 -0
- package/dist/src/state-updates/activity-reaction-utils.d.ts +10 -0
- package/dist/src/state-updates/activity-utils.d.ts +13 -0
- package/dist/src/state-updates/bookmark-utils.d.ts +14 -0
- package/dist/src/types-internal.d.ts +4 -0
- package/dist/src/types.d.ts +13 -0
- package/dist/src/utils.d.ts +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/index.ts +13 -0
- package/package.json +85 -0
- package/src/Feed.ts +1070 -0
- package/src/FeedsClient.ts +352 -0
- package/src/ModerationClient.ts +3 -0
- package/src/common/ActivitySearchSource.ts +46 -0
- package/src/common/ApiClient.ts +197 -0
- package/src/common/BaseSearchSource.ts +238 -0
- package/src/common/ConnectionIdManager.ts +51 -0
- package/src/common/EventDispatcher.ts +52 -0
- package/src/common/FeedSearchSource.ts +94 -0
- package/src/common/Poll.ts +313 -0
- package/src/common/SearchController.ts +152 -0
- package/src/common/StateStore.ts +314 -0
- package/src/common/TokenManager.ts +112 -0
- package/src/common/UserSearchSource.ts +93 -0
- package/src/common/gen-imports.ts +2 -0
- package/src/common/rate-limit.ts +23 -0
- package/src/common/real-time/StableWSConnection.ts +761 -0
- package/src/common/real-time/event-models.ts +38 -0
- package/src/common/types.ts +40 -0
- package/src/common/utils.ts +194 -0
- package/src/gen/feeds/FeedApi.ts +129 -0
- package/src/gen/feeds/FeedsApi.ts +2192 -0
- package/src/gen/model-decoders/decoders.ts +1877 -0
- package/src/gen/model-decoders/event-decoder-mapping.ts +150 -0
- package/src/gen/models/index.ts +5882 -0
- package/src/gen/moderation/ModerationApi.ts +270 -0
- package/src/gen-imports.ts +3 -0
- package/src/state-updates/activity-reaction-utils.test.ts +348 -0
- package/src/state-updates/activity-reaction-utils.ts +107 -0
- package/src/state-updates/activity-utils.test.ts +257 -0
- package/src/state-updates/activity-utils.ts +80 -0
- package/src/state-updates/bookmark-utils.test.ts +383 -0
- package/src/state-updates/bookmark-utils.ts +157 -0
- package/src/types-internal.ts +5 -0
- package/src/types.ts +20 -0
- package/src/utils.ts +4 -0
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
BookmarkAddedEvent,
|
|
4
|
+
BookmarkDeletedEvent,
|
|
5
|
+
BookmarkUpdatedEvent,
|
|
6
|
+
ActivityResponse,
|
|
7
|
+
BookmarkResponse,
|
|
8
|
+
UserResponse,
|
|
9
|
+
} from '../gen/models';
|
|
10
|
+
import {
|
|
11
|
+
addBookmarkToActivity,
|
|
12
|
+
removeBookmarkFromActivity,
|
|
13
|
+
updateBookmarkInActivity,
|
|
14
|
+
addBookmarkToActivities,
|
|
15
|
+
removeBookmarkFromActivities,
|
|
16
|
+
updateBookmarkInActivities,
|
|
17
|
+
} from './bookmark-utils';
|
|
18
|
+
|
|
19
|
+
const createMockUser = (id: string): UserResponse => ({
|
|
20
|
+
id,
|
|
21
|
+
created_at: new Date(),
|
|
22
|
+
updated_at: new Date(),
|
|
23
|
+
banned: false,
|
|
24
|
+
language: 'en',
|
|
25
|
+
online: false,
|
|
26
|
+
role: 'user',
|
|
27
|
+
blocked_user_ids: [],
|
|
28
|
+
teams: [],
|
|
29
|
+
custom: {},
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const createMockActivity = (id: string): ActivityResponse => ({
|
|
33
|
+
id,
|
|
34
|
+
type: 'test',
|
|
35
|
+
created_at: new Date(),
|
|
36
|
+
updated_at: new Date(),
|
|
37
|
+
visibility: 'public',
|
|
38
|
+
bookmark_count: 0,
|
|
39
|
+
comment_count: 0,
|
|
40
|
+
share_count: 0,
|
|
41
|
+
attachments: [],
|
|
42
|
+
comments: [],
|
|
43
|
+
feeds: [],
|
|
44
|
+
filter_tags: [],
|
|
45
|
+
interest_tags: [],
|
|
46
|
+
latest_reactions: [],
|
|
47
|
+
mentioned_users: [],
|
|
48
|
+
own_bookmarks: [],
|
|
49
|
+
own_reactions: [],
|
|
50
|
+
custom: {},
|
|
51
|
+
reaction_groups: {},
|
|
52
|
+
search_data: {},
|
|
53
|
+
popularity: 0,
|
|
54
|
+
score: 0,
|
|
55
|
+
user: createMockUser('user1'),
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const createMockBookmark = (
|
|
59
|
+
user: UserResponse,
|
|
60
|
+
activity: ActivityResponse,
|
|
61
|
+
): BookmarkResponse => ({
|
|
62
|
+
created_at: new Date(),
|
|
63
|
+
updated_at: new Date(),
|
|
64
|
+
activity,
|
|
65
|
+
user,
|
|
66
|
+
custom: {},
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const createMockAddedEvent = (
|
|
70
|
+
bookmark: BookmarkResponse,
|
|
71
|
+
): BookmarkAddedEvent => ({
|
|
72
|
+
bookmark,
|
|
73
|
+
created_at: new Date(),
|
|
74
|
+
custom: {},
|
|
75
|
+
type: 'bookmark.added',
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const createMockDeletedEvent = (
|
|
79
|
+
bookmark: BookmarkResponse,
|
|
80
|
+
): BookmarkDeletedEvent => ({
|
|
81
|
+
bookmark,
|
|
82
|
+
created_at: new Date(),
|
|
83
|
+
custom: {},
|
|
84
|
+
type: 'bookmark.deleted',
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const createMockUpdatedEvent = (
|
|
88
|
+
bookmark: BookmarkResponse,
|
|
89
|
+
): BookmarkUpdatedEvent => ({
|
|
90
|
+
bookmark,
|
|
91
|
+
created_at: new Date(),
|
|
92
|
+
custom: {},
|
|
93
|
+
type: 'bookmark.updated',
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
describe('bookmark-utils', () => {
|
|
97
|
+
describe('addBookmarkToActivity', () => {
|
|
98
|
+
it('should add bookmark to own_bookmarks when from current user', () => {
|
|
99
|
+
const activity = createMockActivity('activity1');
|
|
100
|
+
const user = createMockUser('user1');
|
|
101
|
+
const bookmark = createMockBookmark(user, activity);
|
|
102
|
+
const event = createMockAddedEvent(bookmark);
|
|
103
|
+
|
|
104
|
+
const result = addBookmarkToActivity(event, activity, true);
|
|
105
|
+
|
|
106
|
+
expect(result.changed).toBe(true);
|
|
107
|
+
expect(result.own_bookmarks).toHaveLength(1);
|
|
108
|
+
expect(result.own_bookmarks[0]).toEqual(bookmark);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('should not add bookmark to own_bookmarks when not from current user', () => {
|
|
112
|
+
const activity = createMockActivity('activity1');
|
|
113
|
+
const user = createMockUser('user2');
|
|
114
|
+
const bookmark = createMockBookmark(user, activity);
|
|
115
|
+
const event = createMockAddedEvent(bookmark);
|
|
116
|
+
|
|
117
|
+
const result = addBookmarkToActivity(event, activity, false);
|
|
118
|
+
|
|
119
|
+
expect(result.changed).toBe(true);
|
|
120
|
+
expect(result.own_bookmarks).toHaveLength(0);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('should handle existing bookmarks correctly', () => {
|
|
124
|
+
const activity = createMockActivity('activity1');
|
|
125
|
+
const user = createMockUser('user1');
|
|
126
|
+
const existingBookmark = createMockBookmark(user, activity);
|
|
127
|
+
activity.own_bookmarks = [existingBookmark];
|
|
128
|
+
|
|
129
|
+
const newBookmark = createMockBookmark(user, activity);
|
|
130
|
+
const event = createMockAddedEvent(newBookmark);
|
|
131
|
+
|
|
132
|
+
const result = addBookmarkToActivity(event, activity, true);
|
|
133
|
+
|
|
134
|
+
expect(result.changed).toBe(true);
|
|
135
|
+
expect(result.own_bookmarks).toHaveLength(2);
|
|
136
|
+
expect(result.own_bookmarks).toContain(existingBookmark);
|
|
137
|
+
expect(result.own_bookmarks).toContain(newBookmark);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
describe('removeBookmarkFromActivity', () => {
|
|
142
|
+
it('should remove bookmark from own_bookmarks when from current user', () => {
|
|
143
|
+
const activity = createMockActivity('activity1');
|
|
144
|
+
const user = createMockUser('user1');
|
|
145
|
+
const bookmark = createMockBookmark(user, activity);
|
|
146
|
+
activity.own_bookmarks = [bookmark];
|
|
147
|
+
|
|
148
|
+
const event = createMockDeletedEvent(bookmark);
|
|
149
|
+
const result = removeBookmarkFromActivity(event, activity, true);
|
|
150
|
+
|
|
151
|
+
expect(result.changed).toBe(true);
|
|
152
|
+
expect(result.own_bookmarks).toHaveLength(0);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('should not remove bookmark from own_bookmarks when not from current user', () => {
|
|
156
|
+
const activity = createMockActivity('activity1');
|
|
157
|
+
const user = createMockUser('user1');
|
|
158
|
+
const bookmark = createMockBookmark(user, activity);
|
|
159
|
+
activity.own_bookmarks = [bookmark];
|
|
160
|
+
|
|
161
|
+
const event = createMockDeletedEvent(bookmark);
|
|
162
|
+
const result = removeBookmarkFromActivity(event, activity, false);
|
|
163
|
+
|
|
164
|
+
expect(result.changed).toBe(true);
|
|
165
|
+
expect(result.own_bookmarks).toHaveLength(1);
|
|
166
|
+
expect(result.own_bookmarks[0]).toEqual(bookmark);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it('should remove correct bookmark when multiple bookmarks exist', () => {
|
|
170
|
+
const activity = createMockActivity('activity1');
|
|
171
|
+
const user1 = createMockUser('user1');
|
|
172
|
+
const user2 = createMockUser('user2');
|
|
173
|
+
const bookmark1 = createMockBookmark(user1, activity);
|
|
174
|
+
const bookmark2 = createMockBookmark(user2, activity);
|
|
175
|
+
activity.own_bookmarks = [bookmark1, bookmark2];
|
|
176
|
+
|
|
177
|
+
const event = createMockDeletedEvent(bookmark1);
|
|
178
|
+
const result = removeBookmarkFromActivity(event, activity, true);
|
|
179
|
+
|
|
180
|
+
expect(result.changed).toBe(true);
|
|
181
|
+
expect(result.own_bookmarks).toHaveLength(1);
|
|
182
|
+
expect(result.own_bookmarks[0]).toEqual(bookmark2);
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
describe('updateBookmarkInActivity', () => {
|
|
187
|
+
it('should update bookmark in own_bookmarks when from current user', () => {
|
|
188
|
+
const activity = createMockActivity('activity1');
|
|
189
|
+
const user = createMockUser('user1');
|
|
190
|
+
const bookmark = createMockBookmark(user, activity);
|
|
191
|
+
activity.own_bookmarks = [bookmark];
|
|
192
|
+
|
|
193
|
+
const updatedBookmark = {
|
|
194
|
+
...bookmark,
|
|
195
|
+
custom: { updated: true },
|
|
196
|
+
};
|
|
197
|
+
const event = createMockUpdatedEvent(updatedBookmark);
|
|
198
|
+
const result = updateBookmarkInActivity(event, activity, true);
|
|
199
|
+
|
|
200
|
+
expect(result.changed).toBe(true);
|
|
201
|
+
expect(result.own_bookmarks).toHaveLength(1);
|
|
202
|
+
expect(result.own_bookmarks[0]).toEqual(updatedBookmark);
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it('should not update bookmark in own_bookmarks when not from current user', () => {
|
|
206
|
+
const activity = createMockActivity('activity1');
|
|
207
|
+
const user = createMockUser('user1');
|
|
208
|
+
const bookmark = createMockBookmark(user, activity);
|
|
209
|
+
activity.own_bookmarks = [bookmark];
|
|
210
|
+
|
|
211
|
+
const updatedBookmark = {
|
|
212
|
+
...bookmark,
|
|
213
|
+
custom: { updated: true },
|
|
214
|
+
};
|
|
215
|
+
const event = createMockUpdatedEvent(updatedBookmark);
|
|
216
|
+
const result = updateBookmarkInActivity(event, activity, false);
|
|
217
|
+
|
|
218
|
+
expect(result.changed).toBe(true);
|
|
219
|
+
expect(result.own_bookmarks).toHaveLength(1);
|
|
220
|
+
expect(result.own_bookmarks[0]).toEqual(bookmark); // unchanged
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it('should not update bookmark if it does not exist', () => {
|
|
224
|
+
const activity = createMockActivity('activity1');
|
|
225
|
+
const user = createMockUser('user1');
|
|
226
|
+
const bookmark = createMockBookmark(user, activity);
|
|
227
|
+
activity.own_bookmarks = [bookmark];
|
|
228
|
+
|
|
229
|
+
const differentUser = createMockUser('user2');
|
|
230
|
+
const differentBookmark = createMockBookmark(differentUser, activity);
|
|
231
|
+
const event = createMockUpdatedEvent(differentBookmark);
|
|
232
|
+
const result = updateBookmarkInActivity(event, activity, true);
|
|
233
|
+
|
|
234
|
+
expect(result.changed).toBe(true);
|
|
235
|
+
expect(result.own_bookmarks).toHaveLength(1);
|
|
236
|
+
expect(result.own_bookmarks[0]).toEqual(bookmark); // unchanged
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
describe('addBookmarkToActivities', () => {
|
|
241
|
+
it('should add bookmark to correct activity', () => {
|
|
242
|
+
const activity1 = createMockActivity('activity1');
|
|
243
|
+
const activity2 = createMockActivity('activity2');
|
|
244
|
+
const activities = [activity1, activity2];
|
|
245
|
+
|
|
246
|
+
const user = createMockUser('user1');
|
|
247
|
+
const bookmark = createMockBookmark(user, activity1);
|
|
248
|
+
const event = createMockAddedEvent(bookmark);
|
|
249
|
+
|
|
250
|
+
const result = addBookmarkToActivities(event, activities, true);
|
|
251
|
+
|
|
252
|
+
expect(result.changed).toBe(true);
|
|
253
|
+
expect(result.activities).toHaveLength(2);
|
|
254
|
+
expect(result.activities[0].own_bookmarks).toHaveLength(1);
|
|
255
|
+
expect(result.activities[0].own_bookmarks[0]).toEqual(bookmark);
|
|
256
|
+
expect(result.activities[1].own_bookmarks).toHaveLength(0);
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it('should return unchanged when activity not found', () => {
|
|
260
|
+
const activity1 = createMockActivity('activity1');
|
|
261
|
+
const activities = [activity1];
|
|
262
|
+
|
|
263
|
+
const user = createMockUser('user1');
|
|
264
|
+
const differentActivity = createMockActivity('activity2');
|
|
265
|
+
const bookmark = createMockBookmark(user, differentActivity);
|
|
266
|
+
const event = createMockAddedEvent(bookmark);
|
|
267
|
+
|
|
268
|
+
const result = addBookmarkToActivities(event, activities, true);
|
|
269
|
+
|
|
270
|
+
expect(result.changed).toBe(false);
|
|
271
|
+
expect(result.activities).toEqual(activities);
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
it('should handle undefined activities', () => {
|
|
275
|
+
const user = createMockUser('user1');
|
|
276
|
+
const activity = createMockActivity('activity1');
|
|
277
|
+
const bookmark = createMockBookmark(user, activity);
|
|
278
|
+
const event = createMockAddedEvent(bookmark);
|
|
279
|
+
|
|
280
|
+
const result = addBookmarkToActivities(event, undefined, true);
|
|
281
|
+
|
|
282
|
+
expect(result.changed).toBe(false);
|
|
283
|
+
expect(result.activities).toEqual([]);
|
|
284
|
+
});
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
describe('removeBookmarkFromActivities', () => {
|
|
288
|
+
it('should remove bookmark from correct activity', () => {
|
|
289
|
+
const activity1 = createMockActivity('activity1');
|
|
290
|
+
const activity2 = createMockActivity('activity2');
|
|
291
|
+
const user = createMockUser('user1');
|
|
292
|
+
const bookmark = createMockBookmark(user, activity1);
|
|
293
|
+
activity1.own_bookmarks = [bookmark];
|
|
294
|
+
const activities = [activity1, activity2];
|
|
295
|
+
|
|
296
|
+
const event = createMockDeletedEvent(bookmark);
|
|
297
|
+
const result = removeBookmarkFromActivities(event, activities, true);
|
|
298
|
+
|
|
299
|
+
expect(result.changed).toBe(true);
|
|
300
|
+
expect(result.activities).toHaveLength(2);
|
|
301
|
+
expect(result.activities[0].own_bookmarks).toHaveLength(0);
|
|
302
|
+
expect(result.activities[1].own_bookmarks).toHaveLength(0);
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it('should return unchanged when activity not found', () => {
|
|
306
|
+
const activity1 = createMockActivity('activity1');
|
|
307
|
+
const activities = [activity1];
|
|
308
|
+
|
|
309
|
+
const user = createMockUser('user1');
|
|
310
|
+
const differentActivity = createMockActivity('activity2');
|
|
311
|
+
const bookmark = createMockBookmark(user, differentActivity);
|
|
312
|
+
const event = createMockDeletedEvent(bookmark);
|
|
313
|
+
|
|
314
|
+
const result = removeBookmarkFromActivities(event, activities, true);
|
|
315
|
+
|
|
316
|
+
expect(result.changed).toBe(false);
|
|
317
|
+
expect(result.activities).toEqual(activities);
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
it('should handle undefined activities', () => {
|
|
321
|
+
const user = createMockUser('user1');
|
|
322
|
+
const activity = createMockActivity('activity1');
|
|
323
|
+
const bookmark = createMockBookmark(user, activity);
|
|
324
|
+
const event = createMockDeletedEvent(bookmark);
|
|
325
|
+
|
|
326
|
+
const result = removeBookmarkFromActivities(event, undefined, true);
|
|
327
|
+
|
|
328
|
+
expect(result.changed).toBe(false);
|
|
329
|
+
expect(result.activities).toEqual([]);
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
describe('updateBookmarkInActivities', () => {
|
|
334
|
+
it('should update bookmark in correct activity', () => {
|
|
335
|
+
const activity1 = createMockActivity('activity1');
|
|
336
|
+
const activity2 = createMockActivity('activity2');
|
|
337
|
+
const user = createMockUser('user1');
|
|
338
|
+
const bookmark = createMockBookmark(user, activity1);
|
|
339
|
+
activity1.own_bookmarks = [bookmark];
|
|
340
|
+
const activities = [activity1, activity2];
|
|
341
|
+
|
|
342
|
+
const updatedBookmark = {
|
|
343
|
+
...bookmark,
|
|
344
|
+
custom: { updated: true },
|
|
345
|
+
};
|
|
346
|
+
const event = createMockUpdatedEvent(updatedBookmark);
|
|
347
|
+
const result = updateBookmarkInActivities(event, activities, true);
|
|
348
|
+
|
|
349
|
+
expect(result.changed).toBe(true);
|
|
350
|
+
expect(result.activities).toHaveLength(2);
|
|
351
|
+
expect(result.activities[0].own_bookmarks).toHaveLength(1);
|
|
352
|
+
expect(result.activities[0].own_bookmarks[0]).toEqual(updatedBookmark);
|
|
353
|
+
expect(result.activities[1].own_bookmarks).toHaveLength(0);
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
it('should return unchanged when activity not found', () => {
|
|
357
|
+
const activity1 = createMockActivity('activity1');
|
|
358
|
+
const activities = [activity1];
|
|
359
|
+
|
|
360
|
+
const user = createMockUser('user1');
|
|
361
|
+
const differentActivity = createMockActivity('activity2');
|
|
362
|
+
const bookmark = createMockBookmark(user, differentActivity);
|
|
363
|
+
const event = createMockUpdatedEvent(bookmark);
|
|
364
|
+
|
|
365
|
+
const result = updateBookmarkInActivities(event, activities, true);
|
|
366
|
+
|
|
367
|
+
expect(result.changed).toBe(false);
|
|
368
|
+
expect(result.activities).toEqual(activities);
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
it('should handle undefined activities', () => {
|
|
372
|
+
const user = createMockUser('user1');
|
|
373
|
+
const activity = createMockActivity('activity1');
|
|
374
|
+
const bookmark = createMockBookmark(user, activity);
|
|
375
|
+
const event = createMockUpdatedEvent(bookmark);
|
|
376
|
+
|
|
377
|
+
const result = updateBookmarkInActivities(event, undefined, true);
|
|
378
|
+
|
|
379
|
+
expect(result.changed).toBe(false);
|
|
380
|
+
expect(result.activities).toEqual([]);
|
|
381
|
+
});
|
|
382
|
+
});
|
|
383
|
+
});
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BookmarkAddedEvent,
|
|
3
|
+
BookmarkDeletedEvent,
|
|
4
|
+
BookmarkUpdatedEvent,
|
|
5
|
+
ActivityResponse,
|
|
6
|
+
} from '../gen/models';
|
|
7
|
+
import { UpdateStateResult } from '../types-internal';
|
|
8
|
+
|
|
9
|
+
const updateActivityInActivities = (
|
|
10
|
+
updatedActivity: ActivityResponse,
|
|
11
|
+
activities: ActivityResponse[],
|
|
12
|
+
): UpdateStateResult<{ activities: ActivityResponse[] }> => {
|
|
13
|
+
const index = activities.findIndex((a) => a.id === updatedActivity.id);
|
|
14
|
+
if (index !== -1) {
|
|
15
|
+
const newActivities = [...activities];
|
|
16
|
+
newActivities[index] = updatedActivity;
|
|
17
|
+
return { changed: true, activities: newActivities };
|
|
18
|
+
} else {
|
|
19
|
+
return { changed: false, activities };
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const addBookmarkToActivity = (
|
|
24
|
+
event: BookmarkAddedEvent,
|
|
25
|
+
activity: ActivityResponse,
|
|
26
|
+
isCurrentUser: boolean,
|
|
27
|
+
): UpdateStateResult<ActivityResponse> => {
|
|
28
|
+
// Update own_bookmarks if the bookmark is from the current user
|
|
29
|
+
const ownBookmarks = [...(activity.own_bookmarks || [])];
|
|
30
|
+
if (isCurrentUser) {
|
|
31
|
+
ownBookmarks.push(event.bookmark);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
...activity,
|
|
36
|
+
own_bookmarks: ownBookmarks,
|
|
37
|
+
changed: true,
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const removeBookmarkFromActivity = (
|
|
42
|
+
event: BookmarkDeletedEvent,
|
|
43
|
+
activity: ActivityResponse,
|
|
44
|
+
isCurrentUser: boolean,
|
|
45
|
+
): UpdateStateResult<ActivityResponse> => {
|
|
46
|
+
// Update own_bookmarks if the bookmark is from the current user
|
|
47
|
+
const ownBookmarks = isCurrentUser
|
|
48
|
+
? (activity.own_bookmarks || []).filter(
|
|
49
|
+
(bookmark) =>
|
|
50
|
+
bookmark.user.id !== event.bookmark.user.id ||
|
|
51
|
+
bookmark.activity.id !== event.bookmark.activity.id,
|
|
52
|
+
)
|
|
53
|
+
: activity.own_bookmarks;
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
...activity,
|
|
57
|
+
own_bookmarks: ownBookmarks,
|
|
58
|
+
changed: true,
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export const updateBookmarkInActivity = (
|
|
63
|
+
event: BookmarkUpdatedEvent,
|
|
64
|
+
activity: ActivityResponse,
|
|
65
|
+
isCurrentUser: boolean,
|
|
66
|
+
): UpdateStateResult<ActivityResponse> => {
|
|
67
|
+
// Update own_bookmarks if the bookmark is from the current user
|
|
68
|
+
let ownBookmarks = activity.own_bookmarks || [];
|
|
69
|
+
if (isCurrentUser) {
|
|
70
|
+
const bookmarkIndex = ownBookmarks.findIndex(
|
|
71
|
+
(bookmark) =>
|
|
72
|
+
bookmark.user.id === event.bookmark.user.id &&
|
|
73
|
+
bookmark.activity.id === event.bookmark.activity.id,
|
|
74
|
+
);
|
|
75
|
+
if (bookmarkIndex !== -1) {
|
|
76
|
+
ownBookmarks = [...ownBookmarks];
|
|
77
|
+
ownBookmarks[bookmarkIndex] = event.bookmark;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return {
|
|
82
|
+
...activity,
|
|
83
|
+
own_bookmarks: ownBookmarks,
|
|
84
|
+
changed: true,
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export const addBookmarkToActivities = (
|
|
89
|
+
event: BookmarkAddedEvent,
|
|
90
|
+
activities: ActivityResponse[] | undefined,
|
|
91
|
+
isCurrentUser: boolean,
|
|
92
|
+
): UpdateStateResult<{ activities: ActivityResponse[] }> => {
|
|
93
|
+
if (!activities) {
|
|
94
|
+
return { changed: false, activities: [] };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const activityIndex = activities.findIndex(
|
|
98
|
+
(a) => a.id === event.bookmark.activity.id,
|
|
99
|
+
);
|
|
100
|
+
if (activityIndex === -1) {
|
|
101
|
+
return { changed: false, activities };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const activity = activities[activityIndex];
|
|
105
|
+
const updatedActivity = addBookmarkToActivity(event, activity, isCurrentUser);
|
|
106
|
+
return updateActivityInActivities(updatedActivity, activities);
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
export const removeBookmarkFromActivities = (
|
|
110
|
+
event: BookmarkDeletedEvent,
|
|
111
|
+
activities: ActivityResponse[] | undefined,
|
|
112
|
+
isCurrentUser: boolean,
|
|
113
|
+
): UpdateStateResult<{ activities: ActivityResponse[] }> => {
|
|
114
|
+
if (!activities) {
|
|
115
|
+
return { changed: false, activities: [] };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const activityIndex = activities.findIndex(
|
|
119
|
+
(a) => a.id === event.bookmark.activity.id,
|
|
120
|
+
);
|
|
121
|
+
if (activityIndex === -1) {
|
|
122
|
+
return { changed: false, activities };
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const activity = activities[activityIndex];
|
|
126
|
+
const updatedActivity = removeBookmarkFromActivity(
|
|
127
|
+
event,
|
|
128
|
+
activity,
|
|
129
|
+
isCurrentUser,
|
|
130
|
+
);
|
|
131
|
+
return updateActivityInActivities(updatedActivity, activities);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
export const updateBookmarkInActivities = (
|
|
135
|
+
event: BookmarkUpdatedEvent,
|
|
136
|
+
activities: ActivityResponse[] | undefined,
|
|
137
|
+
isCurrentUser: boolean,
|
|
138
|
+
): UpdateStateResult<{ activities: ActivityResponse[] }> => {
|
|
139
|
+
if (!activities) {
|
|
140
|
+
return { changed: false, activities: [] };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const activityIndex = activities.findIndex(
|
|
144
|
+
(a) => a.id === event.bookmark.activity.id,
|
|
145
|
+
);
|
|
146
|
+
if (activityIndex === -1) {
|
|
147
|
+
return { changed: false, activities };
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const activity = activities[activityIndex];
|
|
151
|
+
const updatedActivity = updateBookmarkInActivity(
|
|
152
|
+
event,
|
|
153
|
+
activity,
|
|
154
|
+
isCurrentUser,
|
|
155
|
+
);
|
|
156
|
+
return updateActivityInActivities(updatedActivity, activities);
|
|
157
|
+
};
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ConnectionChangedEvent } from './common/real-time/event-models';
|
|
2
|
+
import { NetworkChangedEvent } from './common/types';
|
|
3
|
+
import { PagerResponse, WSEvent } from './gen/models';
|
|
4
|
+
import { FeedsClient } from './FeedsClient';
|
|
5
|
+
|
|
6
|
+
export type FeedsEvent = WSEvent | ConnectionChangedEvent | NetworkChangedEvent;
|
|
7
|
+
export type ActivityIdOrCommentId = string;
|
|
8
|
+
|
|
9
|
+
export type GetCommentsRequest = Parameters<FeedsClient['getComments']>[0];
|
|
10
|
+
|
|
11
|
+
export type GetCommentsRepliesRequest = Parameters<
|
|
12
|
+
FeedsClient['getCommentReplies']
|
|
13
|
+
>[0];
|
|
14
|
+
|
|
15
|
+
export type PagerResponseWithLoadingStates = PagerResponse & LoadingStates;
|
|
16
|
+
|
|
17
|
+
export type LoadingStates = {
|
|
18
|
+
loading_next_page?: boolean;
|
|
19
|
+
loading_prev_page?: boolean;
|
|
20
|
+
};
|
package/src/utils.ts
ADDED