@stream-io/feeds-client 0.2.7 → 0.2.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.
- package/CHANGELOG.md +20 -0
- package/dist/cjs/index.js +408 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/react-bindings.js +1368 -0
- package/dist/cjs/react-bindings.js.map +1 -0
- package/dist/es/index.mjs +398 -0
- package/dist/es/index.mjs.map +1 -0
- package/dist/es/react-bindings.mjs +1368 -0
- package/dist/es/react-bindings.mjs.map +1 -0
- package/dist/index-B0Mm2xFU.js +6492 -0
- package/dist/index-B0Mm2xFU.js.map +1 -0
- package/dist/index-rSXIDTdA.mjs +6476 -0
- package/dist/index-rSXIDTdA.mjs.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/bindings/index.d.ts +2 -0
- package/dist/types/bindings/index.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/contexts/StreamFeedContext.d.ts +2 -1
- package/dist/types/bindings/react/contexts/StreamFeedContext.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/contexts/StreamFeedsContext.d.ts +2 -1
- package/dist/types/bindings/react/contexts/StreamFeedsContext.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/contexts/StreamSearchContext.d.ts +2 -1
- package/dist/types/bindings/react/contexts/StreamSearchContext.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/contexts/StreamSearchResultsContext.d.ts +2 -1
- package/dist/types/bindings/react/contexts/StreamSearchResultsContext.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/hooks/client-state-hooks/index.d.ts +1 -0
- package/dist/types/bindings/react/hooks/client-state-hooks/index.d.ts.map +1 -0
- package/dist/types/bindings/react/hooks/client-state-hooks/useClientConnectedUser.d.ts +5 -0
- package/dist/types/bindings/react/hooks/client-state-hooks/useClientConnectedUser.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/hooks/client-state-hooks/useWsConnectionState.d.ts +1 -0
- package/dist/types/bindings/react/hooks/client-state-hooks/useWsConnectionState.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/hooks/feed-state-hooks/index.d.ts +1 -0
- package/dist/types/bindings/react/hooks/feed-state-hooks/index.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/hooks/feed-state-hooks/useAggregatedActivities.d.ts +3 -2
- package/dist/types/bindings/react/hooks/feed-state-hooks/useAggregatedActivities.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/hooks/feed-state-hooks/useComments.d.ts +2 -3
- package/dist/types/bindings/react/hooks/feed-state-hooks/useComments.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/hooks/feed-state-hooks/useFeedActivities.d.ts +3 -2
- package/dist/types/bindings/react/hooks/feed-state-hooks/useFeedActivities.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/hooks/feed-state-hooks/useFeedMetadata.d.ts +3 -2
- package/dist/types/bindings/react/hooks/feed-state-hooks/useFeedMetadata.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/hooks/feed-state-hooks/useFollowers.d.ts +5 -4
- package/dist/types/bindings/react/hooks/feed-state-hooks/useFollowers.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/hooks/feed-state-hooks/useFollowing.d.ts +5 -4
- package/dist/types/bindings/react/hooks/feed-state-hooks/useFollowing.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/hooks/feed-state-hooks/useIsAggregatedActivityRead.d.ts +2 -2
- package/dist/types/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivityRead.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/hooks/feed-state-hooks/useIsAggregatedActivitySeen.d.ts +2 -2
- package/dist/types/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivitySeen.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/hooks/feed-state-hooks/useNotificationStatus.d.ts +2 -1
- package/dist/types/bindings/react/hooks/feed-state-hooks/useNotificationStatus.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/hooks/feed-state-hooks/useOwnCapabilities.d.ts +2 -1
- package/dist/types/bindings/react/hooks/feed-state-hooks/useOwnCapabilities.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/hooks/feed-state-hooks/useOwnFollows.d.ts +3 -2
- package/dist/types/bindings/react/hooks/feed-state-hooks/useOwnFollows.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/hooks/internal/index.d.ts +1 -0
- package/dist/types/bindings/react/hooks/internal/index.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/hooks/internal/useStableCallback.d.ts +1 -0
- package/dist/types/bindings/react/hooks/internal/useStableCallback.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/hooks/search-state-hooks/index.d.ts +1 -0
- package/dist/types/bindings/react/hooks/search-state-hooks/index.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/hooks/search-state-hooks/useSearchQuery.d.ts +2 -1
- package/dist/types/bindings/react/hooks/search-state-hooks/useSearchQuery.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/hooks/search-state-hooks/useSearchResult.d.ts +2 -1
- package/dist/types/bindings/react/hooks/search-state-hooks/useSearchResult.d.ts.map +1 -0
- package/dist/types/bindings/react/hooks/search-state-hooks/useSearchSources.d.ts +5 -0
- package/dist/types/bindings/react/hooks/search-state-hooks/useSearchSources.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/hooks/useCreateFeedsClient.d.ts +2 -4
- package/dist/types/bindings/react/hooks/useCreateFeedsClient.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/hooks/util/index.d.ts +1 -0
- package/dist/types/bindings/react/hooks/util/index.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/hooks/util/useBookmarkActions.d.ts +2 -1
- package/dist/types/bindings/react/hooks/util/useBookmarkActions.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/hooks/util/useReactionActions.d.ts +2 -1
- package/dist/types/bindings/react/hooks/util/useReactionActions.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/index.d.ts +2 -1
- package/dist/types/bindings/react/index.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/wrappers/StreamFeed.d.ts +2 -1
- package/dist/types/bindings/react/wrappers/StreamFeed.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/wrappers/StreamFeeds.d.ts +1 -0
- package/dist/types/bindings/react/wrappers/StreamFeeds.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/wrappers/StreamSearch.d.ts +2 -1
- package/dist/types/bindings/react/wrappers/StreamSearch.d.ts.map +1 -0
- package/dist/{@react-bindings → types/bindings/react}/wrappers/StreamSearchResults.d.ts +2 -1
- package/dist/types/bindings/react/wrappers/StreamSearchResults.d.ts.map +1 -0
- package/dist/{src → types}/common/ApiClient.d.ts +18 -0
- package/dist/types/common/ApiClient.d.ts.map +1 -0
- package/dist/{src → types}/common/ConnectionIdManager.d.ts +1 -0
- package/dist/types/common/ConnectionIdManager.d.ts.map +1 -0
- package/dist/{src → types}/common/EventDispatcher.d.ts +1 -0
- package/dist/types/common/EventDispatcher.d.ts.map +1 -0
- package/dist/{src → types}/common/Poll.d.ts +2 -1
- package/dist/types/common/Poll.d.ts.map +1 -0
- package/dist/{src → types}/common/TokenManager.d.ts +2 -0
- package/dist/types/common/TokenManager.d.ts.map +1 -0
- package/dist/{src → types}/common/gen-imports.d.ts +1 -0
- package/dist/types/common/gen-imports.d.ts.map +1 -0
- package/dist/{src → types}/common/rate-limit.d.ts +1 -0
- package/dist/types/common/rate-limit.d.ts.map +1 -0
- package/dist/{src → types}/common/real-time/StableWSConnection.d.ts +4 -4
- package/dist/types/common/real-time/StableWSConnection.d.ts.map +1 -0
- package/dist/{src → types}/common/real-time/event-models.d.ts +1 -0
- package/dist/types/common/real-time/event-models.d.ts.map +1 -0
- package/dist/{src → types}/common/search/ActivitySearchSource.d.ts +1 -0
- package/dist/types/common/search/ActivitySearchSource.d.ts.map +1 -0
- package/dist/{src → types}/common/search/BaseSearchSource.d.ts +2 -1
- package/dist/types/common/search/BaseSearchSource.d.ts.map +1 -0
- package/dist/{src → types}/common/search/FeedSearchSource.d.ts +1 -0
- package/dist/types/common/search/FeedSearchSource.d.ts.map +1 -0
- package/dist/{src → types}/common/search/SearchController.d.ts +2 -1
- package/dist/types/common/search/SearchController.d.ts.map +1 -0
- package/dist/{src → types}/common/search/UserSearchSource.d.ts +2 -1
- package/dist/types/common/search/UserSearchSource.d.ts.map +1 -0
- package/dist/{src → types}/common/search/index.d.ts +1 -0
- package/dist/types/common/search/index.d.ts.map +1 -0
- package/dist/{src → types}/common/search/types.d.ts +1 -0
- package/dist/types/common/search/types.d.ts.map +1 -0
- package/dist/{src → types}/common/types.d.ts +3 -1
- package/dist/types/common/types.d.ts.map +1 -0
- package/dist/{src → types}/common/utils.d.ts +1 -0
- package/dist/types/common/utils.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/activity/handle-activity-added.d.ts +3 -2
- package/dist/types/feed/event-handlers/activity/handle-activity-added.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/activity/handle-activity-deleted.d.ts +3 -2
- package/dist/types/feed/event-handlers/activity/handle-activity-deleted.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/activity/handle-activity-marked.d.ts +1 -0
- package/dist/types/feed/event-handlers/activity/handle-activity-marked.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/activity/handle-activity-pinned.d.ts +1 -0
- package/dist/types/feed/event-handlers/activity/handle-activity-pinned.d.ts.map +1 -0
- package/dist/types/feed/event-handlers/activity/handle-activity-reaction-added.d.ts +15 -0
- package/dist/types/feed/event-handlers/activity/handle-activity-reaction-added.d.ts.map +1 -0
- package/dist/types/feed/event-handlers/activity/handle-activity-reaction-deleted.d.ts +15 -0
- package/dist/types/feed/event-handlers/activity/handle-activity-reaction-deleted.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/activity/handle-activity-removed-from-feed.d.ts +1 -0
- package/dist/types/feed/event-handlers/activity/handle-activity-removed-from-feed.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/activity/handle-activity-unpinned.d.ts +1 -0
- package/dist/types/feed/event-handlers/activity/handle-activity-unpinned.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/activity/handle-activity-updated.d.ts +1 -0
- package/dist/types/feed/event-handlers/activity/handle-activity-updated.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/activity/index.d.ts +1 -0
- package/dist/types/feed/event-handlers/activity/index.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/bookmark/handle-bookmark-added.d.ts +1 -0
- package/dist/types/feed/event-handlers/bookmark/handle-bookmark-added.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/bookmark/handle-bookmark-deleted.d.ts +1 -0
- package/dist/types/feed/event-handlers/bookmark/handle-bookmark-deleted.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/bookmark/handle-bookmark-updated.d.ts +1 -0
- package/dist/types/feed/event-handlers/bookmark/handle-bookmark-updated.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/bookmark/index.d.ts +1 -0
- package/dist/types/feed/event-handlers/bookmark/index.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/comment/handle-comment-added.d.ts +1 -0
- package/dist/types/feed/event-handlers/comment/handle-comment-added.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/comment/handle-comment-deleted.d.ts +1 -0
- package/dist/types/feed/event-handlers/comment/handle-comment-deleted.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/comment/handle-comment-reaction.d.ts +1 -0
- package/dist/types/feed/event-handlers/comment/handle-comment-reaction.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/comment/handle-comment-updated.d.ts +1 -0
- package/dist/types/feed/event-handlers/comment/handle-comment-updated.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/comment/index.d.ts +1 -0
- package/dist/types/feed/event-handlers/comment/index.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/feed/handle-feed-updated.d.ts +1 -0
- package/dist/types/feed/event-handlers/feed/handle-feed-updated.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/feed/index.d.ts +1 -0
- package/dist/types/feed/event-handlers/feed/index.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/feed-member/handle-feed-member-added.d.ts +1 -0
- package/dist/types/feed/event-handlers/feed-member/handle-feed-member-added.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/feed-member/handle-feed-member-removed.d.ts +1 -0
- package/dist/types/feed/event-handlers/feed-member/handle-feed-member-removed.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/feed-member/handle-feed-member-updated.d.ts +1 -0
- package/dist/types/feed/event-handlers/feed-member/handle-feed-member-updated.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/feed-member/index.d.ts +1 -0
- package/dist/types/feed/event-handlers/feed-member/index.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/follow/handle-follow-created.d.ts +3 -2
- package/dist/types/feed/event-handlers/follow/handle-follow-created.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/follow/handle-follow-deleted.d.ts +2 -1
- package/dist/types/feed/event-handlers/follow/handle-follow-deleted.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/follow/handle-follow-updated.d.ts +3 -2
- package/dist/types/feed/event-handlers/follow/handle-follow-updated.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/follow/index.d.ts +1 -0
- package/dist/types/feed/event-handlers/follow/index.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/index.d.ts +1 -0
- package/dist/types/feed/event-handlers/index.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/notification-feed/handle-notification-feed-updated.d.ts +1 -0
- package/dist/types/feed/event-handlers/notification-feed/handle-notification-feed-updated.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/notification-feed/index.d.ts +1 -0
- package/dist/types/feed/event-handlers/notification-feed/index.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/watch/handle-watch-started.d.ts +1 -0
- package/dist/types/feed/event-handlers/watch/handle-watch-started.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/watch/handle-watch-stopped.d.ts +1 -0
- package/dist/types/feed/event-handlers/watch/handle-watch-stopped.d.ts.map +1 -0
- package/dist/{src → types}/feed/event-handlers/watch/index.d.ts +1 -0
- package/dist/types/feed/event-handlers/watch/index.d.ts.map +1 -0
- package/dist/{src → types}/feed/feed.d.ts +9 -6
- package/dist/types/feed/feed.d.ts.map +1 -0
- package/dist/{src → types}/feed/index.d.ts +1 -0
- package/dist/types/feed/index.d.ts.map +1 -0
- package/dist/{src → types}/feeds-client/event-handlers/index.d.ts +1 -0
- package/dist/types/feeds-client/event-handlers/index.d.ts.map +1 -0
- package/dist/{src → types}/feeds-client/event-handlers/user/handle-user-updated.d.ts +1 -0
- package/dist/types/feeds-client/event-handlers/user/handle-user-updated.d.ts.map +1 -0
- package/dist/{src → types}/feeds-client/feeds-client.d.ts +18 -10
- package/dist/types/feeds-client/feeds-client.d.ts.map +1 -0
- package/dist/{src → types}/feeds-client/index.d.ts +1 -0
- package/dist/types/feeds-client/index.d.ts.map +1 -0
- package/dist/{src → types}/gen/feeds/FeedApi.d.ts +1 -0
- package/dist/types/gen/feeds/FeedApi.d.ts.map +1 -0
- package/dist/{src → types}/gen/feeds/FeedsApi.d.ts +1 -0
- package/dist/types/gen/feeds/FeedsApi.d.ts.map +1 -0
- package/dist/{src → types}/gen/model-decoders/decoders.d.ts +1 -0
- package/dist/types/gen/model-decoders/decoders.d.ts.map +1 -0
- package/dist/{src → types}/gen/model-decoders/event-decoder-mapping.d.ts +1 -0
- package/dist/types/gen/model-decoders/event-decoder-mapping.d.ts.map +1 -0
- package/dist/{src → types}/gen/models/index.d.ts +43 -2
- package/dist/types/gen/models/index.d.ts.map +1 -0
- package/dist/{src → types}/gen/moderation/ModerationApi.d.ts +1 -0
- package/dist/types/gen/moderation/ModerationApi.d.ts.map +1 -0
- package/dist/{src → types}/gen-imports.d.ts +1 -0
- package/dist/types/gen-imports.d.ts.map +1 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/{src → types}/moderation-client.d.ts +1 -0
- package/dist/types/moderation-client.d.ts.map +1 -0
- package/dist/{src → types}/types-internal.d.ts +4 -0
- package/dist/types/types-internal.d.ts.map +1 -0
- package/dist/{src → types}/types.d.ts +1 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/{src → types}/utils/check-has-another-page.d.ts +1 -0
- package/dist/types/utils/check-has-another-page.d.ts.map +1 -0
- package/dist/{src → types}/utils/constants.d.ts +1 -0
- package/dist/types/utils/constants.d.ts.map +1 -0
- package/dist/{src → types}/utils/index.d.ts +2 -0
- package/dist/types/utils/index.d.ts.map +1 -0
- package/dist/types/utils/is-react-native.d.ts +5 -0
- package/dist/types/utils/is-react-native.d.ts.map +1 -0
- package/dist/types/utils/logger.d.ts +61 -0
- package/dist/types/utils/logger.d.ts.map +1 -0
- package/dist/types/utils/state-update-queue.d.ts +83 -0
- package/dist/types/utils/state-update-queue.d.ts.map +1 -0
- package/dist/types/utils/type-assertions.d.ts +12 -0
- package/dist/types/utils/type-assertions.d.ts.map +1 -0
- package/dist/{src → types}/utils/unique-array-merge.d.ts +1 -0
- package/dist/types/utils/unique-array-merge.d.ts.map +1 -0
- package/dist/{src → types}/utils/update-entity-in-array.d.ts +1 -0
- package/dist/types/utils/update-entity-in-array.d.ts.map +1 -0
- package/package.json +21 -33
- package/src/bindings/index.ts +1 -0
- package/src/bindings/react/contexts/StreamFeedContext.tsx +18 -0
- package/src/bindings/react/contexts/StreamFeedsContext.tsx +21 -0
- package/src/bindings/react/contexts/StreamSearchContext.tsx +18 -0
- package/src/bindings/react/contexts/StreamSearchResultsContext.tsx +20 -0
- package/src/bindings/react/hooks/client-state-hooks/useClientConnectedUser.ts +18 -0
- package/src/bindings/react/hooks/client-state-hooks/useWsConnectionState.ts +18 -0
- package/src/bindings/react/hooks/feed-state-hooks/useAggregatedActivities.ts +25 -0
- package/src/bindings/react/hooks/feed-state-hooks/useComments.ts +91 -0
- package/src/bindings/react/hooks/feed-state-hooks/useFeedActivities.ts +36 -0
- package/src/bindings/react/hooks/feed-state-hooks/useFeedMetadata.ts +28 -0
- package/src/bindings/react/hooks/feed-state-hooks/useFollowers.ts +54 -0
- package/src/bindings/react/hooks/feed-state-hooks/useFollowing.ts +54 -0
- package/src/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivityRead.ts +29 -0
- package/src/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivitySeen.ts +28 -0
- package/src/bindings/react/hooks/feed-state-hooks/useNotificationStatus.ts +28 -0
- package/src/bindings/react/hooks/feed-state-hooks/useOwnCapabilities.ts +70 -0
- package/src/bindings/react/hooks/feed-state-hooks/useOwnFollows.ts +18 -0
- package/src/bindings/react/hooks/internal/useStableCallback.ts +37 -0
- package/src/bindings/react/hooks/search-state-hooks/useSearchQuery.ts +14 -0
- package/src/bindings/react/hooks/search-state-hooks/useSearchResult.ts +36 -0
- package/src/bindings/react/hooks/search-state-hooks/useSearchSources.ts +17 -0
- package/src/bindings/react/hooks/useCreateFeedsClient.ts +73 -0
- package/src/bindings/react/hooks/util/useBookmarkActions.ts +40 -0
- package/src/bindings/react/hooks/util/useReactionActions.ts +56 -0
- package/{@react-bindings → src/bindings/react}/index.ts +1 -1
- package/src/bindings/react/wrappers/StreamFeed.tsx +23 -0
- package/src/bindings/react/wrappers/StreamFeeds.tsx +13 -0
- package/src/bindings/react/wrappers/StreamSearch.tsx +23 -0
- package/src/bindings/react/wrappers/StreamSearchResults.tsx +23 -0
- package/src/common/ApiClient.ts +86 -33
- package/src/common/EventDispatcher.ts +3 -6
- package/src/common/Poll.ts +1 -1
- package/src/common/TokenManager.ts +4 -0
- package/src/common/real-time/StableWSConnection.ts +64 -60
- package/src/common/search/BaseSearchSource.ts +11 -4
- package/src/common/search/SearchController.ts +4 -2
- package/src/common/types.ts +3 -2
- package/src/feed/event-handlers/activity/activity-utils.test.ts +40 -9
- package/src/feed/event-handlers/activity/handle-activity-added.test.ts +1 -1
- package/src/feed/event-handlers/activity/handle-activity-added.ts +7 -7
- package/src/feed/event-handlers/activity/handle-activity-deleted.ts +15 -12
- package/src/feed/event-handlers/activity/handle-activity-reaction-added.test.ts +101 -1
- package/src/feed/event-handlers/activity/handle-activity-reaction-added.ts +55 -29
- package/src/feed/event-handlers/activity/handle-activity-reaction-deleted.test.ts +118 -1
- package/src/feed/event-handlers/activity/handle-activity-reaction-deleted.ts +59 -32
- package/src/feed/event-handlers/activity/handle-activity-removed-from-feed.ts +1 -1
- package/src/feed/event-handlers/follow/follow-state-update-queue.test.ts +219 -0
- package/src/feed/event-handlers/follow/handle-follow-created.ts +7 -2
- package/src/feed/event-handlers/follow/handle-follow-deleted.ts +5 -0
- package/src/feed/event-handlers/follow/handle-follow-updated.test.ts +0 -43
- package/src/feed/event-handlers/follow/handle-follow-updated.ts +7 -2
- package/src/feed/feed.test.ts +90 -0
- package/src/feed/feed.ts +25 -4
- package/src/feeds-client/feeds-client.ts +35 -4
- package/src/gen/feeds/FeedsApi.ts +2 -0
- package/src/gen/model-decoders/decoders.ts +22 -0
- package/src/gen/models/index.ts +71 -3
- package/src/index.ts +9 -0
- package/src/test-utils/response-generators.ts +12 -3
- package/src/types-internal.ts +4 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/is-react-native.ts +7 -0
- package/src/utils/logger.ts +18 -0
- package/src/utils/state-update-queue.test.ts +85 -9
- package/src/utils/state-update-queue.ts +104 -11
- package/src/utils/type-assertions.ts +22 -1
- package/dist/@react-bindings/hooks/client-state-hooks/useClientConnectedUser.d.ts +0 -4
- package/dist/@react-bindings/hooks/search-state-hooks/useSearchSources.d.ts +0 -4
- package/dist/@react-bindings/hooks/useStateStore.d.ts +0 -3
- package/dist/index-react-bindings.browser.cjs +0 -6607
- package/dist/index-react-bindings.browser.cjs.map +0 -1
- package/dist/index-react-bindings.browser.js +0 -6574
- package/dist/index-react-bindings.browser.js.map +0 -1
- package/dist/index-react-bindings.node.cjs +0 -6607
- package/dist/index-react-bindings.node.cjs.map +0 -1
- package/dist/index-react-bindings.node.js +0 -6574
- package/dist/index-react-bindings.node.js.map +0 -1
- package/dist/index.browser.cjs +0 -6578
- package/dist/index.browser.cjs.map +0 -1
- package/dist/index.browser.js +0 -6551
- package/dist/index.browser.js.map +0 -1
- package/dist/index.d.ts +0 -9
- package/dist/index.node.cjs +0 -6578
- package/dist/index.node.cjs.map +0 -1
- package/dist/index.node.js +0 -6551
- package/dist/index.node.js.map +0 -1
- package/dist/src/common/StateStore.d.ts +0 -125
- package/dist/src/feed/event-handlers/activity/handle-activity-reaction-added.d.ts +0 -12
- package/dist/src/feed/event-handlers/activity/handle-activity-reaction-deleted.d.ts +0 -12
- package/dist/src/utils/state-update-queue.d.ts +0 -6
- package/dist/src/utils/type-assertions.d.ts +0 -7
- package/index.ts +0 -9
- package/src/common/StateStore.ts +0 -332
- /package/{@react-bindings → src/bindings/react}/hooks/client-state-hooks/index.ts +0 -0
- /package/{@react-bindings → src/bindings/react}/hooks/feed-state-hooks/index.ts +0 -0
- /package/{@react-bindings → src/bindings/react}/hooks/internal/index.ts +0 -0
- /package/{@react-bindings → src/bindings/react}/hooks/search-state-hooks/index.ts +0 -0
- /package/{@react-bindings → src/bindings/react}/hooks/util/index.ts +0 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Feed, FeedState } from '@self';
|
|
2
|
+
import { useFeedContext } from '../../contexts/StreamFeedContext';
|
|
3
|
+
import { useStateStore } from '@stream-io/state-store/react-bindings';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A React hook that returns a reactive array of feeds that the current user
|
|
7
|
+
* owns and are following the respective feed that we are observing.
|
|
8
|
+
*/
|
|
9
|
+
export const useOwnFollows = (feedFromProps?: Feed) => {
|
|
10
|
+
const feedFromContext = useFeedContext();
|
|
11
|
+
const feed = feedFromProps ?? feedFromContext;
|
|
12
|
+
|
|
13
|
+
return useStateStore(feed?.state, selector);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const selector = ({ own_follows }: FeedState) => ({
|
|
17
|
+
own_follows,
|
|
18
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { useCallback, useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
export type StableCallback<A extends unknown[], R> = (...args: A) => R;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A utility hook implementing a stable callback. It takes in an unstable method that
|
|
7
|
+
* is supposed to be invoked somewhere deeper in the DOM tree without making it
|
|
8
|
+
* change its reference every time the parent component rerenders. It will also return
|
|
9
|
+
* the value of the callback if it does return one.
|
|
10
|
+
* A common use-case would be having a function whose invocation depends on state
|
|
11
|
+
* somewhere high up in the DOM tree and wanting to use the same function deeper
|
|
12
|
+
* down, for example in a leaf node and simply using useCallback results in
|
|
13
|
+
* cascading dependency hell. If we wrap it in useStableCallback, we would be able
|
|
14
|
+
* to:
|
|
15
|
+
* - Use the same function as a dependency of another hook (since it is stable)
|
|
16
|
+
* - Still invoke it and get the latest state
|
|
17
|
+
*
|
|
18
|
+
* **Caveats:**
|
|
19
|
+
* - Never wrap a function that is supposed to return a React.ReactElement in
|
|
20
|
+
* useStableCallback, since React will not know that the DOM needs to be updated
|
|
21
|
+
* whenever the callback value changes (for example, renderItem from FlatList must
|
|
22
|
+
* never be wrapped in this hook)
|
|
23
|
+
* - Always prefer using a standard useCallback/stable function wherever possible
|
|
24
|
+
* (the purpose of useStableCallback is to bridge the gap between top level contexts
|
|
25
|
+
* and cascading rereders in downstream components - **not** as an escape hatch)
|
|
26
|
+
* @param callback - the callback we want to stabilize
|
|
27
|
+
*/
|
|
28
|
+
export const useStableCallback = <A extends unknown[], R>(
|
|
29
|
+
callback: StableCallback<A, R>,
|
|
30
|
+
): StableCallback<A, R> => {
|
|
31
|
+
const ref = useRef(callback);
|
|
32
|
+
ref.current = callback;
|
|
33
|
+
|
|
34
|
+
return useCallback<StableCallback<A, R>>((...args) => {
|
|
35
|
+
return ref.current(...args);
|
|
36
|
+
}, []);
|
|
37
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { SearchController, SearchControllerState } from '@self';
|
|
2
|
+
import { useSearchContext } from '../../contexts/StreamSearchContext';
|
|
3
|
+
import { useStateStore } from '@stream-io/state-store/react-bindings';
|
|
4
|
+
|
|
5
|
+
export const useSearchQuery = (controllerFromProps?: SearchController) => {
|
|
6
|
+
const controllerFromState = useSearchContext();
|
|
7
|
+
const controller = controllerFromProps ?? controllerFromState;
|
|
8
|
+
|
|
9
|
+
return useStateStore(controller?.state, selector);
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const selector = ({ searchQuery }: SearchControllerState) => ({
|
|
13
|
+
searchQuery,
|
|
14
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { SearchSource, SearchSourceState } from '@self';
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { useSearchResultsContext } from '../../contexts/StreamSearchResultsContext';
|
|
4
|
+
import { useStateStore } from '@stream-io/state-store/react-bindings';
|
|
5
|
+
import { useStableCallback } from '../internal';
|
|
6
|
+
|
|
7
|
+
export const useSearchResult = (sourceFromProps?: SearchSource) => {
|
|
8
|
+
const sourceFromContext = useSearchResultsContext();
|
|
9
|
+
const source = sourceFromProps ?? sourceFromContext;
|
|
10
|
+
|
|
11
|
+
const { items, error, isLoading, hasNext } =
|
|
12
|
+
useStateStore(source?.state, selector) ?? {};
|
|
13
|
+
|
|
14
|
+
const loadMore = useStableCallback(async () => {
|
|
15
|
+
if (hasNext) {
|
|
16
|
+
source?.search();
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
return useMemo(
|
|
21
|
+
() => ({ items, error, isLoading, hasNext, loadMore }),
|
|
22
|
+
[error, hasNext, isLoading, items, loadMore],
|
|
23
|
+
);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const selector = ({
|
|
27
|
+
items,
|
|
28
|
+
isLoading,
|
|
29
|
+
hasNext,
|
|
30
|
+
lastQueryError,
|
|
31
|
+
}: SearchSourceState) => ({
|
|
32
|
+
items,
|
|
33
|
+
isLoading,
|
|
34
|
+
hasNext,
|
|
35
|
+
error: lastQueryError,
|
|
36
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
SearchController,
|
|
3
|
+
SearchControllerState,
|
|
4
|
+
} from '@self';
|
|
5
|
+
import { useSearchContext } from '../../contexts/StreamSearchContext';
|
|
6
|
+
import { useStateStore } from '@stream-io/state-store/react-bindings';
|
|
7
|
+
|
|
8
|
+
export const useSearchSources = (controllerFromProps?: SearchController) => {
|
|
9
|
+
const controllerFromState = useSearchContext();
|
|
10
|
+
const controller = controllerFromProps ?? controllerFromState;
|
|
11
|
+
|
|
12
|
+
return useStateStore(controller?.state, selector);
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const selector = ({ sources }: SearchControllerState) => ({
|
|
16
|
+
sources,
|
|
17
|
+
});
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
FeedsClient,
|
|
4
|
+
type FeedsClientOptions,
|
|
5
|
+
type UserRequest,
|
|
6
|
+
type TokenOrProvider,
|
|
7
|
+
} from '@self';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A React hook to create, connect and return an instance of `FeedsClient`.
|
|
11
|
+
*/
|
|
12
|
+
export const useCreateFeedsClient = ({
|
|
13
|
+
apiKey,
|
|
14
|
+
tokenOrProvider,
|
|
15
|
+
userData,
|
|
16
|
+
options,
|
|
17
|
+
}: {
|
|
18
|
+
apiKey: string;
|
|
19
|
+
tokenOrProvider: TokenOrProvider;
|
|
20
|
+
userData: UserRequest;
|
|
21
|
+
options?: FeedsClientOptions;
|
|
22
|
+
}) => {
|
|
23
|
+
const [client, setClient] = useState<FeedsClient | null>(
|
|
24
|
+
() => new FeedsClient(apiKey, options),
|
|
25
|
+
);
|
|
26
|
+
const [error, setError] = useState<Error | null>(null);
|
|
27
|
+
const [cachedUserData, setCachedUserData] = useState(userData);
|
|
28
|
+
|
|
29
|
+
const [cachedOptions] = useState(options);
|
|
30
|
+
|
|
31
|
+
if (error) {
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (userData.id !== cachedUserData.id) {
|
|
36
|
+
setCachedUserData(userData);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
const _client = new FeedsClient(apiKey, cachedOptions);
|
|
41
|
+
|
|
42
|
+
const connectionPromise = _client
|
|
43
|
+
.connectUser(cachedUserData, tokenOrProvider)
|
|
44
|
+
.then(() => {
|
|
45
|
+
setError(null);
|
|
46
|
+
console.log('Successfully connected user: ', cachedUserData.id);
|
|
47
|
+
})
|
|
48
|
+
.catch((err) => {
|
|
49
|
+
setError(err);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
setClient(_client);
|
|
53
|
+
|
|
54
|
+
return () => {
|
|
55
|
+
setClient(null);
|
|
56
|
+
connectionPromise
|
|
57
|
+
.then(() => {
|
|
58
|
+
setError(null);
|
|
59
|
+
return _client.disconnectUser();
|
|
60
|
+
})
|
|
61
|
+
.catch((err) => {
|
|
62
|
+
setError(err);
|
|
63
|
+
})
|
|
64
|
+
.then(() => {
|
|
65
|
+
console.log(
|
|
66
|
+
`Connection for user "${cachedUserData.id}" has been closed`,
|
|
67
|
+
);
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
}, [apiKey, cachedUserData, cachedOptions, tokenOrProvider]);
|
|
71
|
+
|
|
72
|
+
return client;
|
|
73
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import type { ActivityResponse } from '@self';
|
|
3
|
+
import { useFeedsClient } from '../../contexts/StreamFeedsContext';
|
|
4
|
+
import { useStableCallback } from '../internal';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A utility hook that takes in an entity and creates bookmark actions
|
|
8
|
+
* that can then be used on the UI. The entity is expected to be an ActivityResponse.
|
|
9
|
+
* @param entity - The entity to which we want to apply reaction actions, expects an ActivityResponse.
|
|
10
|
+
*/
|
|
11
|
+
export const useBookmarkActions = ({
|
|
12
|
+
entity,
|
|
13
|
+
}: {
|
|
14
|
+
entity: ActivityResponse;
|
|
15
|
+
}) => {
|
|
16
|
+
const client = useFeedsClient();
|
|
17
|
+
|
|
18
|
+
const hasOwnBookmark = entity.own_bookmarks?.length > 0;
|
|
19
|
+
|
|
20
|
+
const addBookmark = useStableCallback(async () => {
|
|
21
|
+
await client?.addBookmark({ activity_id: entity.id });
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const removeBookmark = useStableCallback(async () => {
|
|
25
|
+
await client?.deleteBookmark({ activity_id: entity.id });
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const toggleBookmark = useStableCallback(async () => {
|
|
29
|
+
if (hasOwnBookmark) {
|
|
30
|
+
await removeBookmark();
|
|
31
|
+
} else {
|
|
32
|
+
await addBookmark();
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
return useMemo(
|
|
37
|
+
() => ({ addBookmark, removeBookmark, toggleBookmark }),
|
|
38
|
+
[addBookmark, removeBookmark, toggleBookmark],
|
|
39
|
+
);
|
|
40
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import { isCommentResponse, CommentParent } from '@self';
|
|
3
|
+
import { useStableCallback } from '../internal';
|
|
4
|
+
import { useFeedsClient } from '../../contexts/StreamFeedsContext';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A utility hook that takes in an entity and a reaction type, and creates reaction actions
|
|
8
|
+
* that can then be used on the UI. The entity can be either an ActivityResponse or a CommentResponse
|
|
9
|
+
* as the hook determines internally which APIs it is supposed to use, while taking the
|
|
10
|
+
* correct ownCapabilities into account.
|
|
11
|
+
* @param entity - The entity to which we want to apply reaction actions, can be either ActivityResponse or CommentResponse.
|
|
12
|
+
* @param type - The type of reaction we want to add or remove.
|
|
13
|
+
*/
|
|
14
|
+
export const useReactionActions = ({
|
|
15
|
+
entity,
|
|
16
|
+
type,
|
|
17
|
+
}: {
|
|
18
|
+
entity: CommentParent;
|
|
19
|
+
type: string;
|
|
20
|
+
}) => {
|
|
21
|
+
const client = useFeedsClient();
|
|
22
|
+
|
|
23
|
+
const isComment = isCommentResponse(entity);
|
|
24
|
+
const hasOwnReaction = useMemo(
|
|
25
|
+
() => !!entity.own_reactions?.find((r) => r.type === type),
|
|
26
|
+
[entity.own_reactions, type],
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
const addReaction = useStableCallback(async () => {
|
|
30
|
+
await (isComment
|
|
31
|
+
? client?.addCommentReaction({ id: entity.id, type })
|
|
32
|
+
: client?.addReaction({ activity_id: entity.id, type }));
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const removeReaction = useStableCallback(async () => {
|
|
36
|
+
await (isComment
|
|
37
|
+
? client?.deleteCommentReaction({ id: entity.id, type })
|
|
38
|
+
: client?.deleteActivityReaction({
|
|
39
|
+
activity_id: entity.id,
|
|
40
|
+
type,
|
|
41
|
+
}));
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const toggleReaction = useStableCallback(async () => {
|
|
45
|
+
if (hasOwnReaction) {
|
|
46
|
+
await removeReaction();
|
|
47
|
+
} else {
|
|
48
|
+
await addReaction();
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
return useMemo(
|
|
53
|
+
() => ({ addReaction, removeReaction, toggleReaction }),
|
|
54
|
+
[addReaction, removeReaction, toggleReaction],
|
|
55
|
+
);
|
|
56
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { PropsWithChildren } from 'react';
|
|
2
|
+
import { StreamFeedContext } from '../contexts/StreamFeedContext';
|
|
3
|
+
import type { Feed } from '@self';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The props for the StreamFeed component. It accepts a `Feed` instance.
|
|
7
|
+
*/
|
|
8
|
+
export type StreamFeedProps = {
|
|
9
|
+
feed: Feed;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const StreamFeed = ({
|
|
13
|
+
feed,
|
|
14
|
+
children,
|
|
15
|
+
}: PropsWithChildren<StreamFeedProps>) => {
|
|
16
|
+
return (
|
|
17
|
+
<StreamFeedContext.Provider value={feed}>
|
|
18
|
+
{children}
|
|
19
|
+
</StreamFeedContext.Provider>
|
|
20
|
+
);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
StreamFeed.displayName = 'StreamFeed';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { PropsWithChildren } from 'react';
|
|
2
|
+
import { StreamFeedsContext } from '../contexts/StreamFeedsContext';
|
|
3
|
+
import type { StreamFeedsContextProps } from '../contexts/StreamFeedsContext';
|
|
4
|
+
|
|
5
|
+
export const StreamFeeds = ({ client, children }: PropsWithChildren<StreamFeedsContextProps>) => {
|
|
6
|
+
return (
|
|
7
|
+
<StreamFeedsContext.Provider value={client}>
|
|
8
|
+
{children}
|
|
9
|
+
</StreamFeedsContext.Provider>
|
|
10
|
+
);
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
StreamFeeds.displayName = 'StreamFeeds';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { PropsWithChildren } from 'react';
|
|
2
|
+
import { StreamSearchContext } from '../contexts/StreamSearchContext';
|
|
3
|
+
import type { SearchController } from '@self';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The props for the StreamSearch component. It accepts a `SearchController` instance.
|
|
7
|
+
*/
|
|
8
|
+
export type StreamSearchProps = {
|
|
9
|
+
searchController: SearchController | undefined;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const StreamSearch = ({
|
|
13
|
+
searchController,
|
|
14
|
+
children,
|
|
15
|
+
}: PropsWithChildren<StreamSearchProps>) => {
|
|
16
|
+
return (
|
|
17
|
+
<StreamSearchContext.Provider value={searchController}>
|
|
18
|
+
{children}
|
|
19
|
+
</StreamSearchContext.Provider>
|
|
20
|
+
);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
StreamSearch.displayName = 'StreamSearch';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { PropsWithChildren } from 'react';
|
|
2
|
+
import { StreamSearchResultsContext } from '../contexts/StreamSearchResultsContext';
|
|
3
|
+
import type { SearchSource } from '@self';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The props for the StreamSearchResults component. It accepts a `SearchSource` instance.
|
|
7
|
+
*/
|
|
8
|
+
export type StreamSearchResultsProps = {
|
|
9
|
+
source: SearchSource;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const StreamSearchResults = ({
|
|
13
|
+
source,
|
|
14
|
+
children,
|
|
15
|
+
}: PropsWithChildren<StreamSearchResultsProps>) => {
|
|
16
|
+
return (
|
|
17
|
+
<StreamSearchResultsContext.Provider value={source}>
|
|
18
|
+
{children}
|
|
19
|
+
</StreamSearchResultsContext.Provider>
|
|
20
|
+
);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
StreamSearchResults.displayName = 'StreamSearchResults';
|
package/src/common/ApiClient.ts
CHANGED
|
@@ -9,11 +9,26 @@ import { getRateLimitFromResponseHeader } from './rate-limit';
|
|
|
9
9
|
import { KnownCodes, randomId } from './utils';
|
|
10
10
|
import { TokenManager } from './TokenManager';
|
|
11
11
|
import { ConnectionIdManager } from './ConnectionIdManager';
|
|
12
|
+
import { getLogger } from '../utils/logger';
|
|
13
|
+
// this gets replaced during the build process (var version = 'x.y.z';)
|
|
14
|
+
import { version } from '../../package.json';
|
|
15
|
+
|
|
16
|
+
type RequiredAtLeastOne<T> = {
|
|
17
|
+
[K in keyof T]: Required<Pick<T, K>> & Partial<Omit<T, K>>;
|
|
18
|
+
}[keyof T];
|
|
19
|
+
|
|
20
|
+
// Information that can be set to be sent as part of the header of each request
|
|
21
|
+
export type ExtraHeaderInformation = Partial<{
|
|
22
|
+
sdkIdentifier: { name: string; version: string };
|
|
23
|
+
deviceIdentifier: RequiredAtLeastOne<{ os: string; model: string }>;
|
|
24
|
+
}>;
|
|
12
25
|
|
|
13
26
|
export class ApiClient {
|
|
14
27
|
public readonly baseUrl: string;
|
|
15
28
|
private readonly axiosInstance: AxiosInstance;
|
|
16
29
|
private timeout: number;
|
|
30
|
+
public extraHeaderInformation: ExtraHeaderInformation = {};
|
|
31
|
+
private readonly logger = getLogger('api-client');
|
|
17
32
|
|
|
18
33
|
constructor(
|
|
19
34
|
public readonly apiKey: string,
|
|
@@ -47,6 +62,7 @@ export class ApiClient {
|
|
|
47
62
|
body?.watch ||
|
|
48
63
|
body?.presence
|
|
49
64
|
) {
|
|
65
|
+
this.logger.info('Getting connection_id for watch or presence request');
|
|
50
66
|
const connectionId = await this.connectionIdManager.getConnectionId();
|
|
51
67
|
queryParams.connection_id = connectionId;
|
|
52
68
|
}
|
|
@@ -83,6 +99,11 @@ export class ApiClient {
|
|
|
83
99
|
}
|
|
84
100
|
|
|
85
101
|
try {
|
|
102
|
+
this.logger.debug(
|
|
103
|
+
`Sending request ${method.toUpperCase()}:${requestUrl} with:`,
|
|
104
|
+
{ queryParams },
|
|
105
|
+
{ body },
|
|
106
|
+
);
|
|
86
107
|
const response = await this.axiosInstance.request<T>({
|
|
87
108
|
url: requestUrl,
|
|
88
109
|
method,
|
|
@@ -101,41 +122,43 @@ export class ApiClient {
|
|
|
101
122
|
);
|
|
102
123
|
|
|
103
124
|
return { body: response.data, metadata };
|
|
104
|
-
} catch (error
|
|
105
|
-
if (this.isAxiosError(error)) {
|
|
106
|
-
if (!error.response) {
|
|
107
|
-
throw new StreamApiError(`Stream error ${error.message}`);
|
|
108
|
-
} else {
|
|
109
|
-
// Stream specific error response
|
|
110
|
-
const data = error.response.data as StreamApiError;
|
|
111
|
-
const code = data?.code ?? error.response.status;
|
|
112
|
-
const message = data?.message ?? error.response.statusText;
|
|
113
|
-
if (
|
|
114
|
-
code === KnownCodes.TOKEN_EXPIRED &&
|
|
115
|
-
error.response.status === 401 &&
|
|
116
|
-
!this.tokenManager.isStatic()
|
|
117
|
-
) {
|
|
118
|
-
await this.tokenManager.loadToken();
|
|
119
|
-
return await this.sendRequest(
|
|
120
|
-
method,
|
|
121
|
-
url,
|
|
122
|
-
pathParams,
|
|
123
|
-
queryParams,
|
|
124
|
-
body,
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
throw new StreamApiError(
|
|
128
|
-
`Stream error code ${code}: ${message}`,
|
|
129
|
-
this.getRequestMetadata(client_request_id, error.response),
|
|
130
|
-
code,
|
|
131
|
-
undefined,
|
|
132
|
-
);
|
|
133
|
-
}
|
|
134
|
-
} else {
|
|
125
|
+
} catch (error) {
|
|
126
|
+
if (!this.isAxiosError(error)) {
|
|
135
127
|
throw new Error('Unknown error received during an API call', {
|
|
136
128
|
cause: error,
|
|
137
129
|
});
|
|
130
|
+
} else if (!error.response) {
|
|
131
|
+
throw new StreamApiError(`Stream error ${error.message}`);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Stream specific error response
|
|
135
|
+
const data = error.response.data as StreamApiError;
|
|
136
|
+
const code = data?.code ?? error.response.status;
|
|
137
|
+
const message = data?.message ?? error.response.statusText;
|
|
138
|
+
if (
|
|
139
|
+
code === KnownCodes.TOKEN_EXPIRED &&
|
|
140
|
+
error.response.status === 401 &&
|
|
141
|
+
!this.tokenManager.isStatic()
|
|
142
|
+
) {
|
|
143
|
+
this.logger.info(
|
|
144
|
+
'Token expired, fetching a new one and retrying request',
|
|
145
|
+
);
|
|
146
|
+
await this.tokenManager.loadToken();
|
|
147
|
+
return await this.sendRequest(
|
|
148
|
+
method,
|
|
149
|
+
url,
|
|
150
|
+
pathParams,
|
|
151
|
+
queryParams,
|
|
152
|
+
body,
|
|
153
|
+
);
|
|
138
154
|
}
|
|
155
|
+
|
|
156
|
+
throw new StreamApiError(
|
|
157
|
+
`Stream error code ${code}: ${message}`,
|
|
158
|
+
this.getRequestMetadata(client_request_id, error.response),
|
|
159
|
+
code,
|
|
160
|
+
undefined,
|
|
161
|
+
);
|
|
139
162
|
}
|
|
140
163
|
};
|
|
141
164
|
|
|
@@ -153,11 +176,41 @@ export class ApiClient {
|
|
|
153
176
|
return `${wsBaseURL}/api/v2/connect?${params.toString()}`;
|
|
154
177
|
}
|
|
155
178
|
|
|
179
|
+
public generateStreamClientHeader() {
|
|
180
|
+
// TODO: figure out a way to inject this during the build process
|
|
181
|
+
const clientBundle = import.meta.env.VITE_CLIENT_BUNDLE;
|
|
182
|
+
|
|
183
|
+
let userAgentString = '';
|
|
184
|
+
if (this.extraHeaderInformation.sdkIdentifier) {
|
|
185
|
+
userAgentString = `stream-feeds-${this.extraHeaderInformation.sdkIdentifier.name}-v${this.extraHeaderInformation.sdkIdentifier.version}-llc-v${version}`;
|
|
186
|
+
} else {
|
|
187
|
+
userAgentString = `stream-feeds-js-v${version}`;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const { os, model } = this.extraHeaderInformation.deviceIdentifier ?? {};
|
|
191
|
+
|
|
192
|
+
return (
|
|
193
|
+
[
|
|
194
|
+
// reports the device OS, if provided
|
|
195
|
+
['os', os],
|
|
196
|
+
// reports the device model, if provided
|
|
197
|
+
['device_model', model],
|
|
198
|
+
// reports which bundle is being picked from the exports
|
|
199
|
+
['client_bundle', clientBundle],
|
|
200
|
+
] as const
|
|
201
|
+
).reduce(
|
|
202
|
+
(withArguments, [key, value]) =>
|
|
203
|
+
value && value.length > 0
|
|
204
|
+
? withArguments.concat(`|${key}=${value}`)
|
|
205
|
+
: withArguments,
|
|
206
|
+
userAgentString,
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
|
|
156
210
|
private get commonHeaders(): Record<string, string> {
|
|
157
211
|
return {
|
|
158
212
|
'stream-auth-type': 'jwt',
|
|
159
|
-
|
|
160
|
-
'X-Stream-Client': 'stream-feeds-js-',
|
|
213
|
+
'X-Stream-Client': this.generateStreamClientHeader(),
|
|
161
214
|
};
|
|
162
215
|
}
|
|
163
216
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FeedsEvent } from '../types';
|
|
2
|
-
import {
|
|
2
|
+
import { getLogger } from '../utils/logger';
|
|
3
3
|
|
|
4
4
|
export class EventDispatcher<
|
|
5
5
|
Type extends string = FeedsEvent['type'],
|
|
@@ -9,10 +9,7 @@ export class EventDispatcher<
|
|
|
9
9
|
Record<Type | 'all', Array<(event: Event) => void> | undefined>
|
|
10
10
|
> = {};
|
|
11
11
|
|
|
12
|
-
private readonly logger = (
|
|
13
|
-
// TODO implement logging
|
|
14
|
-
console.log(level, message, extra);
|
|
15
|
-
};
|
|
12
|
+
private readonly logger = getLogger('event-dispatcher');
|
|
16
13
|
|
|
17
14
|
dispatch = (event: Event) => {
|
|
18
15
|
const listeners = [
|
|
@@ -24,7 +21,7 @@ export class EventDispatcher<
|
|
|
24
21
|
fn(event);
|
|
25
22
|
} catch (e) {
|
|
26
23
|
// TODO: do we really want to silence this error?
|
|
27
|
-
this.logger('
|
|
24
|
+
this.logger.error('Listener failed with error', e);
|
|
28
25
|
}
|
|
29
26
|
}
|
|
30
27
|
};
|
package/src/common/Poll.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getLogger } from '../utils/logger';
|
|
1
2
|
import { isFunction, sleep } from './utils';
|
|
2
3
|
|
|
3
4
|
/**
|
|
@@ -10,6 +11,7 @@ export class TokenManager {
|
|
|
10
11
|
type: 'static' | 'provider';
|
|
11
12
|
token?: string;
|
|
12
13
|
tokenProvider?: string | (() => Promise<string>);
|
|
14
|
+
private readonly logger = getLogger('token-manager');
|
|
13
15
|
|
|
14
16
|
constructor() {
|
|
15
17
|
this.loadTokenPromise = null;
|
|
@@ -49,6 +51,8 @@ export class TokenManager {
|
|
|
49
51
|
// Fetches a token from tokenProvider function and sets in tokenManager.
|
|
50
52
|
// In case of static token, it will simply resolve to static token.
|
|
51
53
|
loadToken = () => {
|
|
54
|
+
this.logger.info('Loading a new token');
|
|
55
|
+
|
|
52
56
|
if (this.loadTokenPromise) {
|
|
53
57
|
return this.loadTokenPromise;
|
|
54
58
|
}
|