@stream-io/feeds-client 0.1.1 → 0.1.2
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 +13 -1
- package/CHANGELOG.md +18 -0
- package/dist/@react-bindings/contexts/StreamFeedsContext.d.ts +15 -0
- package/dist/@react-bindings/hooks/clientStateHooks.d.ts +10 -0
- package/dist/@react-bindings/hooks/useCreateFeedsClient.d.ts +13 -0
- package/dist/@react-bindings/hooks/useStateStore.d.ts +1 -1
- package/dist/@react-bindings/index.d.ts +4 -0
- package/dist/@react-bindings/wrappers/StreamFeeds.d.ts +6 -0
- package/dist/index-react-bindings.browser.cjs +5388 -12
- package/dist/index-react-bindings.browser.cjs.map +1 -1
- package/dist/index-react-bindings.browser.js +5384 -14
- package/dist/index-react-bindings.browser.js.map +1 -1
- package/dist/index-react-bindings.node.cjs +5388 -12
- package/dist/index-react-bindings.node.cjs.map +1 -1
- package/dist/index-react-bindings.node.js +5384 -14
- package/dist/index-react-bindings.node.js.map +1 -1
- package/dist/index.browser.cjs +97 -31
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +97 -31
- package/dist/index.browser.js.map +1 -1
- package/dist/index.node.cjs +97 -31
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.js +97 -31
- package/dist/index.node.js.map +1 -1
- package/dist/src/Feed.d.ts +2 -2
- package/dist/src/FeedsClient.d.ts +8 -5
- package/dist/src/common/StateStore.d.ts +1 -0
- package/dist/src/common/real-time/StableWSConnection.d.ts +3 -3
- package/dist/src/gen/feeds/FeedsApi.d.ts +7 -1
- package/dist/src/gen/models/index.d.ts +41 -0
- package/dist/src/types.d.ts +2 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -6
- package/src/Feed.ts +19 -12
- package/src/FeedsClient.ts +24 -17
- package/src/common/StateStore.ts +30 -12
- package/src/common/utils.ts +1 -1
- package/src/gen/feeds/FeedsApi.ts +51 -0
- package/src/gen/model-decoders/decoders.ts +29 -0
- package/src/gen/model-decoders/event-decoder-mapping.ts +6 -0
- package/src/gen/models/index.ts +60 -0
- package/src/types.ts +4 -0
package/dist/index.browser.cjs
CHANGED
|
@@ -261,6 +261,14 @@ decoders.BookmarkDeletedEvent = (input) => {
|
|
|
261
261
|
};
|
|
262
262
|
return decode(typeMappings, input);
|
|
263
263
|
};
|
|
264
|
+
decoders.BookmarkFolderDeletedEvent = (input) => {
|
|
265
|
+
const typeMappings = {
|
|
266
|
+
created_at: { type: 'DatetimeType', isSingle: true },
|
|
267
|
+
bookmark_folder: { type: 'BookmarkFolderResponse', isSingle: true },
|
|
268
|
+
received_at: { type: 'DatetimeType', isSingle: true },
|
|
269
|
+
};
|
|
270
|
+
return decode(typeMappings, input);
|
|
271
|
+
};
|
|
264
272
|
decoders.BookmarkFolderResponse = (input) => {
|
|
265
273
|
const typeMappings = {
|
|
266
274
|
created_at: { type: 'DatetimeType', isSingle: true },
|
|
@@ -268,6 +276,14 @@ decoders.BookmarkFolderResponse = (input) => {
|
|
|
268
276
|
};
|
|
269
277
|
return decode(typeMappings, input);
|
|
270
278
|
};
|
|
279
|
+
decoders.BookmarkFolderUpdatedEvent = (input) => {
|
|
280
|
+
const typeMappings = {
|
|
281
|
+
created_at: { type: 'DatetimeType', isSingle: true },
|
|
282
|
+
bookmark_folder: { type: 'BookmarkFolderResponse', isSingle: true },
|
|
283
|
+
received_at: { type: 'DatetimeType', isSingle: true },
|
|
284
|
+
};
|
|
285
|
+
return decode(typeMappings, input);
|
|
286
|
+
};
|
|
271
287
|
decoders.BookmarkResponse = (input) => {
|
|
272
288
|
const typeMappings = {
|
|
273
289
|
created_at: { type: 'DatetimeType', isSingle: true },
|
|
@@ -1227,6 +1243,12 @@ decoders.UpdateBlockListResponse = (input) => {
|
|
|
1227
1243
|
};
|
|
1228
1244
|
return decode(typeMappings, input);
|
|
1229
1245
|
};
|
|
1246
|
+
decoders.UpdateBookmarkFolderResponse = (input) => {
|
|
1247
|
+
const typeMappings = {
|
|
1248
|
+
bookmark_folder: { type: 'BookmarkFolderResponse', isSingle: true },
|
|
1249
|
+
};
|
|
1250
|
+
return decode(typeMappings, input);
|
|
1251
|
+
};
|
|
1230
1252
|
decoders.UpdateBookmarkResponse = (input) => {
|
|
1231
1253
|
const typeMappings = {
|
|
1232
1254
|
bookmark: { type: 'BookmarkResponse', isSingle: true },
|
|
@@ -1647,6 +1669,26 @@ class FeedsApi {
|
|
|
1647
1669
|
decoders.QueryBookmarkFoldersResponse?.(response.body);
|
|
1648
1670
|
return { ...response.body, metadata: response.metadata };
|
|
1649
1671
|
}
|
|
1672
|
+
async deleteBookmarkFolder(request) {
|
|
1673
|
+
const pathParams = {
|
|
1674
|
+
folder_id: request?.folder_id,
|
|
1675
|
+
};
|
|
1676
|
+
const response = await this.apiClient.sendRequest('DELETE', '/api/v2/feeds/bookmark_folders/{folder_id}', pathParams, undefined);
|
|
1677
|
+
decoders.DeleteBookmarkFolderResponse?.(response.body);
|
|
1678
|
+
return { ...response.body, metadata: response.metadata };
|
|
1679
|
+
}
|
|
1680
|
+
async updateBookmarkFolder(request) {
|
|
1681
|
+
const pathParams = {
|
|
1682
|
+
folder_id: request?.folder_id,
|
|
1683
|
+
};
|
|
1684
|
+
const body = {
|
|
1685
|
+
name: request?.name,
|
|
1686
|
+
custom: request?.custom,
|
|
1687
|
+
};
|
|
1688
|
+
const response = await this.apiClient.sendRequest('PATCH', '/api/v2/feeds/bookmark_folders/{folder_id}', pathParams, undefined, body, 'application/json');
|
|
1689
|
+
decoders.UpdateBookmarkFolderResponse?.(response.body);
|
|
1690
|
+
return { ...response.body, metadata: response.metadata };
|
|
1691
|
+
}
|
|
1650
1692
|
async queryBookmarks(request) {
|
|
1651
1693
|
const body = {
|
|
1652
1694
|
limit: request?.limit,
|
|
@@ -2323,14 +2365,9 @@ class StateStore {
|
|
|
2323
2365
|
let previouslySelectedValues;
|
|
2324
2366
|
const wrappedHandler = (nextValue) => {
|
|
2325
2367
|
const newlySelectedValues = selector(nextValue);
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
continue;
|
|
2330
|
-
hasUpdatedValues = true;
|
|
2331
|
-
break;
|
|
2332
|
-
}
|
|
2333
|
-
if (!hasUpdatedValues)
|
|
2368
|
+
// shallow comparison of previouslySelectedValues and newlySelectedValues
|
|
2369
|
+
const selectionsAreEqual = StateStore.doSelectionsEqual(previouslySelectedValues, newlySelectedValues);
|
|
2370
|
+
if (selectionsAreEqual)
|
|
2334
2371
|
return;
|
|
2335
2372
|
// save a copy of previouslySelectedValues before running
|
|
2336
2373
|
// handler - if previouslySelectedValues are set to
|
|
@@ -2361,7 +2398,7 @@ class StateStore {
|
|
|
2361
2398
|
? newValueOrPatch(this.value)
|
|
2362
2399
|
: newValueOrPatch;
|
|
2363
2400
|
// do not notify subscribers if the value hasn't changed
|
|
2364
|
-
if (newValue
|
|
2401
|
+
if (Object.is(newValue, this.value))
|
|
2365
2402
|
return;
|
|
2366
2403
|
this.preprocessors.forEach((preprocessor) => preprocessor(newValue, this.value));
|
|
2367
2404
|
const oldValue = this.value;
|
|
@@ -2378,6 +2415,19 @@ class StateStore {
|
|
|
2378
2415
|
this.handlers.delete(handler);
|
|
2379
2416
|
};
|
|
2380
2417
|
}
|
|
2418
|
+
static doSelectionsEqual(previouslySelectedValues, newlySelectedValues) {
|
|
2419
|
+
let selectionsAreEqual;
|
|
2420
|
+
if ((selectionsAreEqual = typeof previouslySelectedValues !== 'undefined')) {
|
|
2421
|
+
for (const key in newlySelectedValues) {
|
|
2422
|
+
if (Object.is(previouslySelectedValues[key], newlySelectedValues[key])) {
|
|
2423
|
+
continue;
|
|
2424
|
+
}
|
|
2425
|
+
selectionsAreEqual = false;
|
|
2426
|
+
break;
|
|
2427
|
+
}
|
|
2428
|
+
}
|
|
2429
|
+
return selectionsAreEqual;
|
|
2430
|
+
}
|
|
2381
2431
|
/**
|
|
2382
2432
|
* Registers a preprocessor function that will be called before the state is updated.
|
|
2383
2433
|
*
|
|
@@ -2603,7 +2653,7 @@ function getRandomValuesWithMathRandom(bytes) {
|
|
|
2603
2653
|
}
|
|
2604
2654
|
}
|
|
2605
2655
|
const getRandomValues = (() => {
|
|
2606
|
-
if (typeof crypto?.getRandomValues !== 'undefined') {
|
|
2656
|
+
if (typeof crypto !== 'undefined' && typeof crypto?.getRandomValues !== 'undefined') {
|
|
2607
2657
|
return crypto.getRandomValues.bind(crypto);
|
|
2608
2658
|
}
|
|
2609
2659
|
else if (typeof msCrypto !== 'undefined') {
|
|
@@ -3612,6 +3662,8 @@ const eventDecoderMapping = {
|
|
|
3612
3662
|
'feeds.bookmark.added': (data) => decoders.BookmarkAddedEvent(data),
|
|
3613
3663
|
'feeds.bookmark.deleted': (data) => decoders.BookmarkDeletedEvent(data),
|
|
3614
3664
|
'feeds.bookmark.updated': (data) => decoders.BookmarkUpdatedEvent(data),
|
|
3665
|
+
'feeds.bookmark_folder.deleted': (data) => decoders.BookmarkFolderDeletedEvent(data),
|
|
3666
|
+
'feeds.bookmark_folder.updated': (data) => decoders.BookmarkFolderUpdatedEvent(data),
|
|
3615
3667
|
'feeds.comment.added': (data) => decoders.CommentAddedEvent(data),
|
|
3616
3668
|
'feeds.comment.deleted': (data) => decoders.CommentDeletedEvent(data),
|
|
3617
3669
|
'feeds.comment.reaction.added': (data) => decoders.CommentReactionAddedEvent(data),
|
|
@@ -4014,6 +4066,8 @@ class Feed extends FeedApi {
|
|
|
4014
4066
|
'feeds.bookmark.added': this.handleBookmarkAdded.bind(this),
|
|
4015
4067
|
'feeds.bookmark.deleted': this.handleBookmarkDeleted.bind(this),
|
|
4016
4068
|
'feeds.bookmark.updated': this.handleBookmarkUpdated.bind(this),
|
|
4069
|
+
'feeds.bookmark_folder.deleted': Feed.noop,
|
|
4070
|
+
'feeds.bookmark_folder.updated': Feed.noop,
|
|
4017
4071
|
'feeds.comment.added': (event) => {
|
|
4018
4072
|
const { comment } = event;
|
|
4019
4073
|
const forId = comment.parent_id ?? comment.object_id;
|
|
@@ -4103,16 +4157,19 @@ class Feed extends FeedApi {
|
|
|
4103
4157
|
return;
|
|
4104
4158
|
// this feed followed someone
|
|
4105
4159
|
if (event.follow.source_feed.fid === this.fid) {
|
|
4106
|
-
|
|
4107
|
-
|
|
4160
|
+
this.state.next((currentState) => {
|
|
4161
|
+
const newState = {
|
|
4108
4162
|
...currentState,
|
|
4109
4163
|
...event.follow.source_feed,
|
|
4164
|
+
};
|
|
4165
|
+
if (currentState.following_pagination?.next === END_OF_LIST) {
|
|
4110
4166
|
// TODO: respect sort
|
|
4111
|
-
following
|
|
4167
|
+
newState.following = currentState.following
|
|
4112
4168
|
? currentState.following.concat(event.follow)
|
|
4113
|
-
: [event.follow]
|
|
4114
|
-
}
|
|
4115
|
-
|
|
4169
|
+
: [event.follow];
|
|
4170
|
+
}
|
|
4171
|
+
return newState;
|
|
4172
|
+
});
|
|
4116
4173
|
}
|
|
4117
4174
|
else if (
|
|
4118
4175
|
// someone followed this feed
|
|
@@ -4122,14 +4179,14 @@ class Feed extends FeedApi {
|
|
|
4122
4179
|
this.state.next((currentState) => {
|
|
4123
4180
|
const newState = { ...currentState, ...event.follow.target_feed };
|
|
4124
4181
|
if (source.created_by.id === connectedUser?.id) {
|
|
4125
|
-
newState.own_follows =
|
|
4126
|
-
?
|
|
4182
|
+
newState.own_follows = currentState.own_follows
|
|
4183
|
+
? currentState.own_follows.concat(event.follow)
|
|
4127
4184
|
: [event.follow];
|
|
4128
4185
|
}
|
|
4129
4186
|
if (currentState.followers_pagination?.next === END_OF_LIST) {
|
|
4130
4187
|
// TODO: respect sort
|
|
4131
|
-
newState.followers =
|
|
4132
|
-
?
|
|
4188
|
+
newState.followers = currentState.followers
|
|
4189
|
+
? currentState.followers.concat(event.follow)
|
|
4133
4190
|
: [event.follow];
|
|
4134
4191
|
}
|
|
4135
4192
|
return newState;
|
|
@@ -4155,9 +4212,9 @@ class Feed extends FeedApi {
|
|
|
4155
4212
|
this.state.next((currentState) => {
|
|
4156
4213
|
const newState = { ...currentState, ...event.follow.target_feed };
|
|
4157
4214
|
if (source.created_by.id === connectedUser?.id) {
|
|
4158
|
-
newState.own_follows =
|
|
4215
|
+
newState.own_follows = currentState.own_follows?.filter((follow) => follow.source_feed.fid !== event.follow.source_feed.fid);
|
|
4159
4216
|
}
|
|
4160
|
-
newState.followers =
|
|
4217
|
+
newState.followers = currentState.followers?.filter((follow) => follow.source_feed.fid !== event.follow.source_feed.fid);
|
|
4161
4218
|
return newState;
|
|
4162
4219
|
});
|
|
4163
4220
|
}
|
|
@@ -5065,7 +5122,10 @@ class FeedsClient extends FeedsApi {
|
|
|
5065
5122
|
}, this.tokenManager, this.connectionIdManager, [decodeWSEvent]);
|
|
5066
5123
|
this.wsConnection.on('all', (event) => this.eventDispatcher.dispatch(event));
|
|
5067
5124
|
const connectedEvent = await this.wsConnection.connect();
|
|
5068
|
-
this.state.partialNext({
|
|
5125
|
+
this.state.partialNext({
|
|
5126
|
+
connectedUser: connectedEvent?.me,
|
|
5127
|
+
isWsConnectionHealthy: this.wsConnection.isHealthy,
|
|
5128
|
+
});
|
|
5069
5129
|
}
|
|
5070
5130
|
catch (err) {
|
|
5071
5131
|
await this.disconnectUser();
|
|
@@ -5120,13 +5180,20 @@ class FeedsClient extends FeedsApi {
|
|
|
5120
5180
|
removeConnectionEventListeners(this.updateNetworkConnectionStatus);
|
|
5121
5181
|
this.connectionIdManager.reset();
|
|
5122
5182
|
this.tokenManager.reset();
|
|
5123
|
-
this.state.partialNext({ connectedUser: undefined });
|
|
5183
|
+
this.state.partialNext({ connectedUser: undefined, isWsConnectionHealthy: false });
|
|
5124
5184
|
};
|
|
5125
5185
|
this.on = this.eventDispatcher.on;
|
|
5126
5186
|
this.off = this.eventDispatcher.off;
|
|
5127
5187
|
this.feed = (groupId, id) => {
|
|
5128
5188
|
return this.getOrCreateActiveFeed(groupId, id);
|
|
5129
5189
|
};
|
|
5190
|
+
this.updateNetworkConnectionStatus = (event) => {
|
|
5191
|
+
const networkEvent = {
|
|
5192
|
+
type: 'network.changed',
|
|
5193
|
+
online: event.type === 'online',
|
|
5194
|
+
};
|
|
5195
|
+
this.eventDispatcher.dispatch(networkEvent);
|
|
5196
|
+
};
|
|
5130
5197
|
this.getOrCreateActiveFeed = (group, id, data) => {
|
|
5131
5198
|
const fid = `${group}:${id}`;
|
|
5132
5199
|
if (this.activeFeeds[fid]) {
|
|
@@ -5138,15 +5205,9 @@ class FeedsClient extends FeedsApi {
|
|
|
5138
5205
|
return feed;
|
|
5139
5206
|
}
|
|
5140
5207
|
};
|
|
5141
|
-
this.updateNetworkConnectionStatus = (event) => {
|
|
5142
|
-
const networkEvent = {
|
|
5143
|
-
type: 'network.changed',
|
|
5144
|
-
online: event.type === 'online',
|
|
5145
|
-
};
|
|
5146
|
-
this.eventDispatcher.dispatch(networkEvent);
|
|
5147
|
-
};
|
|
5148
5208
|
this.state = new StateStore({
|
|
5149
5209
|
connectedUser: undefined,
|
|
5210
|
+
isWsConnectionHealthy: false,
|
|
5150
5211
|
});
|
|
5151
5212
|
this.moderation = new ModerationClient(apiClient);
|
|
5152
5213
|
this.tokenManager = tokenManager;
|
|
@@ -5156,6 +5217,11 @@ class FeedsClient extends FeedsApi {
|
|
|
5156
5217
|
const fid = event.fid;
|
|
5157
5218
|
const feed = typeof fid === 'string' ? this.activeFeeds[fid] : undefined;
|
|
5158
5219
|
switch (event.type) {
|
|
5220
|
+
case 'connection.changed': {
|
|
5221
|
+
const { online } = event;
|
|
5222
|
+
this.state.partialNext({ isWsConnectionHealthy: online });
|
|
5223
|
+
break;
|
|
5224
|
+
}
|
|
5159
5225
|
case 'feeds.feed.created': {
|
|
5160
5226
|
if (feed)
|
|
5161
5227
|
break;
|