@stream-io/feeds-client 0.1.1 → 0.1.3

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 (44) hide show
  1. package/@react-bindings/index.ts +13 -1
  2. package/CHANGELOG.md +31 -0
  3. package/dist/@react-bindings/contexts/StreamFeedsContext.d.ts +15 -0
  4. package/dist/@react-bindings/hooks/clientStateHooks.d.ts +10 -0
  5. package/dist/@react-bindings/hooks/useCreateFeedsClient.d.ts +13 -0
  6. package/dist/@react-bindings/hooks/useStateStore.d.ts +1 -1
  7. package/dist/@react-bindings/index.d.ts +4 -0
  8. package/dist/@react-bindings/wrappers/StreamFeeds.d.ts +6 -0
  9. package/dist/index-react-bindings.browser.cjs +5411 -12
  10. package/dist/index-react-bindings.browser.cjs.map +1 -1
  11. package/dist/index-react-bindings.browser.js +5407 -14
  12. package/dist/index-react-bindings.browser.js.map +1 -1
  13. package/dist/index-react-bindings.node.cjs +5411 -12
  14. package/dist/index-react-bindings.node.cjs.map +1 -1
  15. package/dist/index-react-bindings.node.js +5407 -14
  16. package/dist/index-react-bindings.node.js.map +1 -1
  17. package/dist/index.browser.cjs +125 -36
  18. package/dist/index.browser.cjs.map +1 -1
  19. package/dist/index.browser.js +125 -36
  20. package/dist/index.browser.js.map +1 -1
  21. package/dist/index.node.cjs +125 -36
  22. package/dist/index.node.cjs.map +1 -1
  23. package/dist/index.node.js +125 -36
  24. package/dist/index.node.js.map +1 -1
  25. package/dist/src/Feed.d.ts +4 -2
  26. package/dist/src/FeedsClient.d.ts +9 -5
  27. package/dist/src/common/ApiClient.d.ts +1 -0
  28. package/dist/src/common/StateStore.d.ts +1 -0
  29. package/dist/src/common/real-time/StableWSConnection.d.ts +3 -3
  30. package/dist/src/gen/feeds/FeedsApi.d.ts +7 -1
  31. package/dist/src/gen/models/index.d.ts +41 -0
  32. package/dist/src/types.d.ts +2 -0
  33. package/dist/tsconfig.tsbuildinfo +1 -1
  34. package/package.json +2 -6
  35. package/src/Feed.ts +33 -15
  36. package/src/FeedsClient.ts +37 -17
  37. package/src/common/ApiClient.ts +10 -3
  38. package/src/common/StateStore.ts +30 -12
  39. package/src/common/utils.ts +1 -1
  40. package/src/gen/feeds/FeedsApi.ts +51 -0
  41. package/src/gen/model-decoders/decoders.ts +29 -0
  42. package/src/gen/model-decoders/event-decoder-mapping.ts +6 -0
  43. package/src/gen/models/index.ts +60 -0
  44. package/src/types.ts +4 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stream-io/feeds-client",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "packageManager": "yarn@3.2.4",
5
5
  "main": "./dist/index.node.js",
6
6
  "exports": {
@@ -62,17 +62,13 @@
62
62
  "@rollup/plugin-replace": "^6.0.1",
63
63
  "@rollup/plugin-typescript": "^12.1.0",
64
64
  "@types/react": "^19.1.8",
65
- "@vitest/browser": "^2.1.3",
66
- "@vitest/coverage-v8": "^2.1.2",
67
65
  "dotenv": "^16.4.5",
68
- "playwright": "^1.48.1",
69
66
  "react": "19.0.0",
70
67
  "rimraf": "^6.0.1",
71
68
  "rollup": "^4.24.0",
72
69
  "typescript": "^5.8.3",
73
70
  "vite": "^5.4.8",
74
- "vitest": "^2.1.2",
75
- "vitest-mock-extended": "^2.0.2"
71
+ "vitest": "^3.2.1"
76
72
  },
77
73
  "peerDependencies": {
78
74
  "react": "^18 || ^19"
package/src/Feed.ts CHANGED
@@ -106,6 +106,8 @@ export type FeedState = Omit<
106
106
  followers_pagination?: LoadingStates & { sort?: string };
107
107
 
108
108
  following_pagination?: LoadingStates & { sort?: string };
109
+
110
+ last_get_or_create_request_config?: GetOrCreateFeedRequest;
109
111
  };
110
112
 
111
113
  const END_OF_LIST = 'eol' as const;
@@ -207,6 +209,8 @@ export class Feed extends FeedApi {
207
209
  'feeds.bookmark.added': this.handleBookmarkAdded.bind(this),
208
210
  'feeds.bookmark.deleted': this.handleBookmarkDeleted.bind(this),
209
211
  'feeds.bookmark.updated': this.handleBookmarkUpdated.bind(this),
212
+ 'feeds.bookmark_folder.deleted': Feed.noop,
213
+ 'feeds.bookmark_folder.updated': Feed.noop,
210
214
  'feeds.comment.added': (event) => {
211
215
  const { comment } = event;
212
216
  const forId = comment.parent_id ?? comment.object_id;
@@ -310,16 +314,21 @@ export class Feed extends FeedApi {
310
314
 
311
315
  // this feed followed someone
312
316
  if (event.follow.source_feed.fid === this.fid) {
313
- if (this.currentState.following_pagination?.next === END_OF_LIST) {
314
- this.state.next((currentState) => ({
317
+ this.state.next((currentState) => {
318
+ const newState = {
315
319
  ...currentState,
316
320
  ...event.follow.source_feed,
321
+ };
322
+
323
+ if (currentState.following_pagination?.next === END_OF_LIST) {
317
324
  // TODO: respect sort
318
- following: currentState.following
325
+ newState.following = currentState.following
319
326
  ? currentState.following.concat(event.follow)
320
- : [event.follow],
321
- }));
322
- }
327
+ : [event.follow];
328
+ }
329
+
330
+ return newState;
331
+ });
323
332
  } else if (
324
333
  // someone followed this feed
325
334
  event.follow.target_feed.fid === this.fid
@@ -331,15 +340,15 @@ export class Feed extends FeedApi {
331
340
  const newState = { ...currentState, ...event.follow.target_feed };
332
341
 
333
342
  if (source.created_by.id === connectedUser?.id) {
334
- newState.own_follows = newState.own_follows
335
- ? newState.own_follows.concat(event.follow)
343
+ newState.own_follows = currentState.own_follows
344
+ ? currentState.own_follows.concat(event.follow)
336
345
  : [event.follow];
337
346
  }
338
347
 
339
348
  if (currentState.followers_pagination?.next === END_OF_LIST) {
340
349
  // TODO: respect sort
341
- newState.followers = newState.followers
342
- ? newState.followers.concat(event.follow)
350
+ newState.followers = currentState.followers
351
+ ? currentState.followers.concat(event.follow)
343
352
  : [event.follow];
344
353
  }
345
354
 
@@ -371,13 +380,13 @@ export class Feed extends FeedApi {
371
380
  const newState = { ...currentState, ...event.follow.target_feed };
372
381
 
373
382
  if (source.created_by.id === connectedUser?.id) {
374
- newState.own_follows = newState.own_follows?.filter(
383
+ newState.own_follows = currentState.own_follows?.filter(
375
384
  (follow) =>
376
385
  follow.source_feed.fid !== event.follow.source_feed.fid,
377
386
  );
378
387
  }
379
388
 
380
- newState.followers = newState.followers?.filter(
389
+ newState.followers = currentState.followers?.filter(
381
390
  (follow) => follow.source_feed.fid !== event.follow.source_feed.fid,
382
391
  );
383
392
 
@@ -548,6 +557,13 @@ export class Feed extends FeedApi {
548
557
  });
549
558
  }
550
559
 
560
+ async synchronize() {
561
+ const { last_get_or_create_request_config } = this.state.getLatestValue();
562
+ if (last_get_or_create_request_config?.watch) {
563
+ await this.getOrCreate(last_get_or_create_request_config);
564
+ }
565
+ }
566
+
551
567
  async getOrCreate(request?: GetOrCreateFeedRequest) {
552
568
  if (this.currentState.is_loading_activities) {
553
569
  throw new Error('Only one getOrCreate call is allowed at a time');
@@ -637,6 +653,8 @@ export class Feed extends FeedApi {
637
653
  delete nextState.following;
638
654
  }
639
655
 
656
+ nextState.last_get_or_create_request_config = request;
657
+
640
658
  return nextState;
641
659
  });
642
660
  }
@@ -1029,7 +1047,8 @@ export class Feed extends FeedApi {
1029
1047
 
1030
1048
  async getNextPage() {
1031
1049
  const currentState = this.currentState;
1032
- const response = await this.getOrCreate({
1050
+
1051
+ return await this.getOrCreate({
1033
1052
  member_pagination: {
1034
1053
  limit: 0,
1035
1054
  },
@@ -1040,9 +1059,8 @@ export class Feed extends FeedApi {
1040
1059
  limit: 0,
1041
1060
  },
1042
1061
  next: currentState.next,
1062
+ limit: currentState.last_get_or_create_request_config?.limit ?? 20,
1043
1063
  });
1044
-
1045
- return response;
1046
1064
  }
1047
1065
 
1048
1066
  addActivity(request: Omit<ActivityRequest, 'fids'>) {
@@ -12,7 +12,7 @@ import {
12
12
  UserRequest,
13
13
  WSEvent,
14
14
  } from './gen/models';
15
- import { FeedsEvent } from './types';
15
+ import { FeedsEvent, TokenOrProvider } from './types';
16
16
  import { StateStore } from './common/StateStore';
17
17
  import { TokenManager } from './common/TokenManager';
18
18
  import { ConnectionIdManager } from './common/ConnectionIdManager';
@@ -35,6 +35,7 @@ import { StreamPoll } from './common/Poll';
35
35
 
36
36
  export type FeedsClientState = {
37
37
  connectedUser: OwnUser | undefined;
38
+ isWsConnectionHealthy: boolean;
38
39
  };
39
40
 
40
41
  type FID = string;
@@ -55,6 +56,8 @@ export class FeedsClient extends FeedsApi {
55
56
 
56
57
  private activeFeeds: Record<FID, Feed> = {};
57
58
 
59
+ private healthyConnectionChangedEventCount = 0;
60
+
58
61
  constructor(apiKey: string, options?: FeedsClientOptions) {
59
62
  const tokenManager = new TokenManager();
60
63
  const connectionIdManager = new ConnectionIdManager();
@@ -67,6 +70,7 @@ export class FeedsClient extends FeedsApi {
67
70
  super(apiClient);
68
71
  this.state = new StateStore<FeedsClientState>({
69
72
  connectedUser: undefined,
73
+ isWsConnectionHealthy: false,
70
74
  });
71
75
  this.moderation = new ModerationClient(apiClient);
72
76
  this.tokenManager = tokenManager;
@@ -79,6 +83,22 @@ export class FeedsClient extends FeedsApi {
79
83
  typeof fid === 'string' ? this.activeFeeds[fid] : undefined;
80
84
 
81
85
  switch (event.type) {
86
+ case 'connection.changed': {
87
+ const { online } = event;
88
+ this.state.partialNext({ isWsConnectionHealthy: online });
89
+
90
+ if (online) {
91
+ this.healthyConnectionChangedEventCount++;
92
+
93
+ // we skip the first event as we could potentially be querying twice
94
+ if (this.healthyConnectionChangedEventCount > 1) {
95
+ for (const activeFeed of Object.values(this.activeFeeds)) {
96
+ activeFeed.synchronize();
97
+ }
98
+ }
99
+ }
100
+ break;
101
+ }
82
102
  case 'feeds.feed.created': {
83
103
  if (feed) break;
84
104
 
@@ -188,10 +208,7 @@ export class FeedsClient extends FeedsApi {
188
208
  }
189
209
  }
190
210
 
191
- connectUser = async (
192
- user: UserRequest,
193
- tokenProvider: string | (() => Promise<string>),
194
- ) => {
211
+ connectUser = async (user: UserRequest, tokenProvider: TokenOrProvider) => {
195
212
  if (
196
213
  this.state.getLatestValue().connectedUser !== undefined ||
197
214
  this.wsConnection
@@ -216,7 +233,10 @@ export class FeedsClient extends FeedsApi {
216
233
  this.eventDispatcher.dispatch(event),
217
234
  );
218
235
  const connectedEvent = await this.wsConnection.connect();
219
- this.state.partialNext({ connectedUser: connectedEvent?.me });
236
+ this.state.partialNext({
237
+ connectedUser: connectedEvent?.me,
238
+ isWsConnectionHealthy: this.wsConnection.isHealthy,
239
+ });
220
240
  } catch (err) {
221
241
  await this.disconnectUser();
222
242
  throw err;
@@ -291,7 +311,7 @@ export class FeedsClient extends FeedsApi {
291
311
 
292
312
  this.connectionIdManager.reset();
293
313
  this.tokenManager.reset();
294
- this.state.partialNext({ connectedUser: undefined });
314
+ this.state.partialNext({ connectedUser: undefined, isWsConnectionHealthy: false });
295
315
  };
296
316
 
297
317
  on = this.eventDispatcher.on;
@@ -317,6 +337,16 @@ export class FeedsClient extends FeedsApi {
317
337
  };
318
338
  }
319
339
 
340
+ updateNetworkConnectionStatus = (
341
+ event: { type: 'online' | 'offline' } | Event,
342
+ ) => {
343
+ const networkEvent: NetworkChangedEvent = {
344
+ type: 'network.changed',
345
+ online: event.type === 'online',
346
+ };
347
+ this.eventDispatcher.dispatch(networkEvent);
348
+ };
349
+
320
350
  private readonly getOrCreateActiveFeed = (
321
351
  group: string,
322
352
  id: string,
@@ -332,16 +362,6 @@ export class FeedsClient extends FeedsApi {
332
362
  }
333
363
  };
334
364
 
335
- private readonly updateNetworkConnectionStatus = (
336
- event: { type: 'online' | 'offline' } | Event,
337
- ) => {
338
- const networkEvent: NetworkChangedEvent = {
339
- type: 'network.changed',
340
- online: event.type === 'online',
341
- };
342
- this.eventDispatcher.dispatch(networkEvent);
343
- };
344
-
345
365
  private findActiveFeedByActivityId(activityId: string) {
346
366
  return Object.values(this.activeFeeds).filter((feed) =>
347
367
  feed.currentState.activities?.some(
@@ -13,6 +13,7 @@ import { ConnectionIdManager } from './ConnectionIdManager';
13
13
  export class ApiClient {
14
14
  public readonly baseUrl: string;
15
15
  private readonly axiosInstance: AxiosInstance;
16
+ private timeout: number;
16
17
 
17
18
  constructor(
18
19
  public readonly apiKey: string,
@@ -21,9 +22,9 @@ export class ApiClient {
21
22
  options?: FeedsClientOptions,
22
23
  ) {
23
24
  this.baseUrl = options?.base_url ?? 'https://video.stream-io-api.com';
25
+ this.timeout = options?.timeout ?? 3000;
24
26
  this.axiosInstance = axios.create({
25
27
  baseURL: this.baseUrl,
26
- timeout: options?.timeout ?? 3000,
27
28
  });
28
29
  }
29
30
 
@@ -74,7 +75,10 @@ export class ApiClient {
74
75
  requestContentType === 'multipart/form-data' ? new FormData() : body;
75
76
  if (requestContentType === 'multipart/form-data') {
76
77
  Object.keys(body).forEach((key) => {
77
- encodedBody.append(key, body[key]);
78
+ const value = body[key];
79
+ if (value != null) {
80
+ encodedBody.append(key, value);
81
+ }
78
82
  });
79
83
  }
80
84
 
@@ -84,8 +88,11 @@ export class ApiClient {
84
88
  method,
85
89
  headers,
86
90
  params: queryParams,
87
- paramsSerializer: params => this.queryParamsStringify(params),
91
+ paramsSerializer: (params) => this.queryParamsStringify(params),
88
92
  data: encodedBody,
93
+ timeout:
94
+ // multipart/form-data requests should not have a timeout allowing ample time for file uploads
95
+ requestContentType === 'multipart/form-data' ? 0 : this.timeout,
89
96
  });
90
97
 
91
98
  const metadata: RequestMetadata = this.getRequestMetadata(
@@ -9,7 +9,6 @@ export type Preprocessor<T> = Handler<T>;
9
9
  export const isPatch = <T>(value: ValueOrPatch<T>): value is Patch<T> =>
10
10
  typeof value === 'function';
11
11
 
12
-
13
12
  const noop = () => {};
14
13
 
15
14
  export class StateStore<T extends Record<string, unknown>> {
@@ -23,7 +22,6 @@ export class StateStore<T extends Record<string, unknown>> {
23
22
  * @experimental
24
23
  * This method is experimental and may change in future versions.
25
24
  */
26
-
27
25
  public merge<Q extends StateStore<any>>(
28
26
  stateStore: Q extends StateStore<infer L>
29
27
  ? Extract<keyof T, keyof L> extends never
@@ -44,7 +42,7 @@ export class StateStore<T extends Record<string, unknown>> {
44
42
  : newValueOrPatch;
45
43
 
46
44
  // do not notify subscribers if the value hasn't changed
47
- if (newValue === this.value) return;
45
+ if (Object.is(newValue, this.value)) return;
48
46
 
49
47
  this.preprocessors.forEach((preprocessor) =>
50
48
  preprocessor(newValue, this.value),
@@ -71,6 +69,29 @@ export class StateStore<T extends Record<string, unknown>> {
71
69
  };
72
70
  }
73
71
 
72
+ public static doSelectionsEqual<
73
+ O extends Readonly<Record<string, unknown>> | readonly unknown[],
74
+ >(previouslySelectedValues: O | undefined, newlySelectedValues: O): boolean {
75
+ let selectionsAreEqual: boolean;
76
+
77
+ if (
78
+ (selectionsAreEqual = typeof previouslySelectedValues !== 'undefined')
79
+ ) {
80
+ for (const key in newlySelectedValues) {
81
+ if (
82
+ Object.is(previouslySelectedValues[key], newlySelectedValues[key])
83
+ ) {
84
+ continue;
85
+ }
86
+
87
+ selectionsAreEqual = false;
88
+ break;
89
+ }
90
+ }
91
+
92
+ return selectionsAreEqual;
93
+ }
94
+
74
95
  public subscribeWithSelector = <
75
96
  O extends Readonly<Record<string, unknown>> | readonly unknown[],
76
97
  >(
@@ -83,16 +104,13 @@ export class StateStore<T extends Record<string, unknown>> {
83
104
  const wrappedHandler: Handler<T> = (nextValue) => {
84
105
  const newlySelectedValues = selector(nextValue);
85
106
 
86
- let hasUpdatedValues = typeof previouslySelectedValues === 'undefined';
87
-
88
- for (const key in previouslySelectedValues) {
89
- if (previouslySelectedValues[key] === newlySelectedValues[key])
90
- continue;
91
- hasUpdatedValues = true;
92
- break;
93
- }
107
+ // shallow comparison of previouslySelectedValues and newlySelectedValues
108
+ const selectionsAreEqual = StateStore.doSelectionsEqual(
109
+ previouslySelectedValues,
110
+ newlySelectedValues,
111
+ );
94
112
 
95
- if (!hasUpdatedValues) return;
113
+ if (selectionsAreEqual) return;
96
114
 
97
115
  // save a copy of previouslySelectedValues before running
98
116
  // handler - if previouslySelectedValues are set to
@@ -72,7 +72,7 @@ function getRandomValuesWithMathRandom(bytes: Uint8Array): void {
72
72
  declare const msCrypto: Crypto;
73
73
 
74
74
  const getRandomValues = (() => {
75
- if (typeof crypto?.getRandomValues !== 'undefined') {
75
+ if (typeof crypto !== 'undefined' && typeof crypto?.getRandomValues !== 'undefined') {
76
76
  return crypto.getRandomValues.bind(crypto);
77
77
  } else if (typeof msCrypto !== 'undefined') {
78
78
  return msCrypto.getRandomValues.bind(msCrypto);
@@ -32,6 +32,7 @@ import {
32
32
  DeleteActivitiesResponse,
33
33
  DeleteActivityReactionResponse,
34
34
  DeleteActivityResponse,
35
+ DeleteBookmarkFolderResponse,
35
36
  DeleteBookmarkResponse,
36
37
  DeleteCommentReactionResponse,
37
38
  DeleteCommentResponse,
@@ -103,6 +104,8 @@ import {
103
104
  UpdateActivityResponse,
104
105
  UpdateBlockListRequest,
105
106
  UpdateBlockListResponse,
107
+ UpdateBookmarkFolderRequest,
108
+ UpdateBookmarkFolderResponse,
106
109
  UpdateBookmarkRequest,
107
110
  UpdateBookmarkResponse,
108
111
  UpdateCommentRequest,
@@ -743,6 +746,54 @@ export class FeedsApi {
743
746
  return { ...response.body, metadata: response.metadata };
744
747
  }
745
748
 
749
+ async deleteBookmarkFolder(request: {
750
+ folder_id: string;
751
+ }): Promise<StreamResponse<DeleteBookmarkFolderResponse>> {
752
+ const pathParams = {
753
+ folder_id: request?.folder_id,
754
+ };
755
+
756
+ const response = await this.apiClient.sendRequest<
757
+ StreamResponse<DeleteBookmarkFolderResponse>
758
+ >(
759
+ 'DELETE',
760
+ '/api/v2/feeds/bookmark_folders/{folder_id}',
761
+ pathParams,
762
+ undefined,
763
+ );
764
+
765
+ decoders.DeleteBookmarkFolderResponse?.(response.body);
766
+
767
+ return { ...response.body, metadata: response.metadata };
768
+ }
769
+
770
+ async updateBookmarkFolder(
771
+ request: UpdateBookmarkFolderRequest & { folder_id: string },
772
+ ): Promise<StreamResponse<UpdateBookmarkFolderResponse>> {
773
+ const pathParams = {
774
+ folder_id: request?.folder_id,
775
+ };
776
+ const body = {
777
+ name: request?.name,
778
+ custom: request?.custom,
779
+ };
780
+
781
+ const response = await this.apiClient.sendRequest<
782
+ StreamResponse<UpdateBookmarkFolderResponse>
783
+ >(
784
+ 'PATCH',
785
+ '/api/v2/feeds/bookmark_folders/{folder_id}',
786
+ pathParams,
787
+ undefined,
788
+ body,
789
+ 'application/json',
790
+ );
791
+
792
+ decoders.UpdateBookmarkFolderResponse?.(response.body);
793
+
794
+ return { ...response.body, metadata: response.metadata };
795
+ }
796
+
746
797
  async queryBookmarks(
747
798
  request?: QueryBookmarksRequest,
748
799
  ): Promise<StreamResponse<QueryBookmarksResponse>> {
@@ -353,6 +353,17 @@ decoders.BookmarkDeletedEvent = (input?: Record<string, any>) => {
353
353
  return decode(typeMappings, input);
354
354
  };
355
355
 
356
+ decoders.BookmarkFolderDeletedEvent = (input?: Record<string, any>) => {
357
+ const typeMappings: TypeMapping = {
358
+ created_at: { type: 'DatetimeType', isSingle: true },
359
+
360
+ bookmark_folder: { type: 'BookmarkFolderResponse', isSingle: true },
361
+
362
+ received_at: { type: 'DatetimeType', isSingle: true },
363
+ };
364
+ return decode(typeMappings, input);
365
+ };
366
+
356
367
  decoders.BookmarkFolderResponse = (input?: Record<string, any>) => {
357
368
  const typeMappings: TypeMapping = {
358
369
  created_at: { type: 'DatetimeType', isSingle: true },
@@ -362,6 +373,17 @@ decoders.BookmarkFolderResponse = (input?: Record<string, any>) => {
362
373
  return decode(typeMappings, input);
363
374
  };
364
375
 
376
+ decoders.BookmarkFolderUpdatedEvent = (input?: Record<string, any>) => {
377
+ const typeMappings: TypeMapping = {
378
+ created_at: { type: 'DatetimeType', isSingle: true },
379
+
380
+ bookmark_folder: { type: 'BookmarkFolderResponse', isSingle: true },
381
+
382
+ received_at: { type: 'DatetimeType', isSingle: true },
383
+ };
384
+ return decode(typeMappings, input);
385
+ };
386
+
365
387
  decoders.BookmarkResponse = (input?: Record<string, any>) => {
366
388
  const typeMappings: TypeMapping = {
367
389
  created_at: { type: 'DatetimeType', isSingle: true },
@@ -1699,6 +1721,13 @@ decoders.UpdateBlockListResponse = (input?: Record<string, any>) => {
1699
1721
  return decode(typeMappings, input);
1700
1722
  };
1701
1723
 
1724
+ decoders.UpdateBookmarkFolderResponse = (input?: Record<string, any>) => {
1725
+ const typeMappings: TypeMapping = {
1726
+ bookmark_folder: { type: 'BookmarkFolderResponse', isSingle: true },
1727
+ };
1728
+ return decode(typeMappings, input);
1729
+ };
1730
+
1702
1731
  decoders.UpdateBookmarkResponse = (input?: Record<string, any>) => {
1703
1732
  const typeMappings: TypeMapping = {
1704
1733
  bookmark: { type: 'BookmarkResponse', isSingle: true },
@@ -46,6 +46,12 @@ const eventDecoderMapping: Record<
46
46
  'feeds.bookmark.updated': (data: Record<string, any>) =>
47
47
  decoders.BookmarkUpdatedEvent(data),
48
48
 
49
+ 'feeds.bookmark_folder.deleted': (data: Record<string, any>) =>
50
+ decoders.BookmarkFolderDeletedEvent(data),
51
+
52
+ 'feeds.bookmark_folder.updated': (data: Record<string, any>) =>
53
+ decoders.BookmarkFolderUpdatedEvent(data),
54
+
49
55
  'feeds.comment.added': (data: Record<string, any>) =>
50
56
  decoders.CommentAddedEvent(data),
51
57
 
@@ -373,6 +373,8 @@ export interface ActivityResponse {
373
373
 
374
374
  popularity: number;
375
375
 
376
+ reaction_count: number;
377
+
376
378
  score: number;
377
379
 
378
380
  share_count: number;
@@ -949,6 +951,20 @@ export interface BookmarkDeletedEvent {
949
951
  user?: UserResponseCommonFields;
950
952
  }
951
953
 
954
+ export interface BookmarkFolderDeletedEvent {
955
+ created_at: Date;
956
+
957
+ bookmark_folder: BookmarkFolderResponse;
958
+
959
+ custom: Record<string, any>;
960
+
961
+ type: string;
962
+
963
+ received_at?: Date;
964
+
965
+ user?: UserResponseCommonFields;
966
+ }
967
+
952
968
  export interface BookmarkFolderResponse {
953
969
  created_at: Date;
954
970
 
@@ -961,6 +977,20 @@ export interface BookmarkFolderResponse {
961
977
  custom?: Record<string, any>;
962
978
  }
963
979
 
980
+ export interface BookmarkFolderUpdatedEvent {
981
+ created_at: Date;
982
+
983
+ bookmark_folder: BookmarkFolderResponse;
984
+
985
+ custom: Record<string, any>;
986
+
987
+ type: string;
988
+
989
+ received_at?: Date;
990
+
991
+ user?: UserResponseCommonFields;
992
+ }
993
+
964
994
  export interface BookmarkResponse {
965
995
  created_at: Date;
966
996
 
@@ -2051,6 +2081,10 @@ export interface DeleteActivityResponse {
2051
2081
  duration: string;
2052
2082
  }
2053
2083
 
2084
+ export interface DeleteBookmarkFolderResponse {
2085
+ duration: string;
2086
+ }
2087
+
2054
2088
  export interface DeleteBookmarkResponse {
2055
2089
  duration: string;
2056
2090
 
@@ -2490,6 +2524,8 @@ export interface FeedInput {
2490
2524
 
2491
2525
  visibility?: 'public' | 'visible' | 'followers' | 'members' | 'private';
2492
2526
 
2527
+ filter_tags?: string[];
2528
+
2493
2529
  members?: FeedMemberRequest[];
2494
2530
 
2495
2531
  custom?: Record<string, any>;
@@ -2620,6 +2656,8 @@ export interface FeedRequest {
2620
2656
 
2621
2657
  visibility?: 'public' | 'visible' | 'followers' | 'members' | 'private';
2622
2658
 
2659
+ filter_tags?: string[];
2660
+
2623
2661
  members?: FeedMemberRequest[];
2624
2662
 
2625
2663
  custom?: Record<string, any>;
@@ -2654,6 +2692,8 @@ export interface FeedResponse {
2654
2692
 
2655
2693
  visibility?: string;
2656
2694
 
2695
+ filter_tags?: string[];
2696
+
2657
2697
  custom?: Record<string, any>;
2658
2698
  }
2659
2699
 
@@ -3678,6 +3718,8 @@ export interface OwnUser {
3678
3718
 
3679
3719
  custom: Record<string, any>;
3680
3720
 
3721
+ total_unread_count_by_team: Record<string, number>;
3722
+
3681
3723
  deactivated_at?: Date;
3682
3724
 
3683
3725
  deleted_at?: Date;
@@ -3757,6 +3799,8 @@ export interface OwnUserResponse {
3757
3799
  push_preferences?: PushPreferences;
3758
3800
 
3759
3801
  teams_role?: Record<string, string>;
3802
+
3803
+ total_unread_count_by_team?: Record<string, number>;
3760
3804
  }
3761
3805
 
3762
3806
  export interface PagerRequest {
@@ -5232,6 +5276,18 @@ export interface UpdateBlockListResponse {
5232
5276
  blocklist?: BlockListResponse;
5233
5277
  }
5234
5278
 
5279
+ export interface UpdateBookmarkFolderRequest {
5280
+ name?: string;
5281
+
5282
+ custom?: Record<string, any>;
5283
+ }
5284
+
5285
+ export interface UpdateBookmarkFolderResponse {
5286
+ duration: string;
5287
+
5288
+ bookmark_folder: BookmarkFolderResponse;
5289
+ }
5290
+
5235
5291
  export interface UpdateBookmarkRequest {
5236
5292
  folder_id?: string;
5237
5293
 
@@ -5805,6 +5861,8 @@ export type WSClientEvent =
5805
5861
  | ({ type: 'feeds.bookmark.added' } & BookmarkAddedEvent)
5806
5862
  | ({ type: 'feeds.bookmark.deleted' } & BookmarkDeletedEvent)
5807
5863
  | ({ type: 'feeds.bookmark.updated' } & BookmarkUpdatedEvent)
5864
+ | ({ type: 'feeds.bookmark_folder.deleted' } & BookmarkFolderDeletedEvent)
5865
+ | ({ type: 'feeds.bookmark_folder.updated' } & BookmarkFolderUpdatedEvent)
5808
5866
  | ({ type: 'feeds.comment.added' } & CommentAddedEvent)
5809
5867
  | ({ type: 'feeds.comment.deleted' } & CommentDeletedEvent)
5810
5868
  | ({ type: 'feeds.comment.reaction.added' } & CommentReactionAddedEvent)
@@ -5848,6 +5906,8 @@ export type WSEvent =
5848
5906
  | ({ type: 'feeds.bookmark.added' } & BookmarkAddedEvent)
5849
5907
  | ({ type: 'feeds.bookmark.deleted' } & BookmarkDeletedEvent)
5850
5908
  | ({ type: 'feeds.bookmark.updated' } & BookmarkUpdatedEvent)
5909
+ | ({ type: 'feeds.bookmark_folder.deleted' } & BookmarkFolderDeletedEvent)
5910
+ | ({ type: 'feeds.bookmark_folder.updated' } & BookmarkFolderUpdatedEvent)
5851
5911
  | ({ type: 'feeds.comment.added' } & CommentAddedEvent)
5852
5912
  | ({ type: 'feeds.comment.deleted' } & CommentDeletedEvent)
5853
5913
  | ({ type: 'feeds.comment.reaction.added' } & CommentReactionAddedEvent)
package/src/types.ts CHANGED
@@ -18,3 +18,7 @@ export type LoadingStates = {
18
18
  loading_next_page?: boolean;
19
19
  loading_prev_page?: boolean;
20
20
  };
21
+
22
+ export type TokenOrProvider = string | TokenProvider;
23
+
24
+ export type TokenProvider = () => Promise<string>;