@amityco/ts-sdk 6.4.6-e12bdf9.0 → 6.5.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/dist/@types/core/events.d.ts +4 -4
- package/dist/@types/core/events.d.ts.map +1 -1
- package/dist/@types/core/model.d.ts +3 -1
- package/dist/@types/core/model.d.ts.map +1 -1
- package/dist/@types/core/payload.d.ts +1 -1
- package/dist/@types/core/payload.d.ts.map +1 -1
- package/dist/@types/domains/post.d.ts +1 -1
- package/dist/@types/domains/post.d.ts.map +1 -1
- package/dist/@types/domains/reaction.d.ts +4 -5
- package/dist/@types/domains/reaction.d.ts.map +1 -1
- package/dist/channelRepsitory/channelMembership/observers/getMembers.d.ts +1 -0
- package/dist/channelRepsitory/channelMembership/observers/getMembers.d.ts.map +1 -1
- package/dist/client/observers/getTotalUnreadCount.d.ts.map +1 -1
- package/dist/client/utils/markerSyncEngine.d.ts.map +1 -1
- package/dist/commentRepository/observers/getComment.d.ts +2 -2
- package/dist/communityRepository/api/getCommunity.d.ts +4 -4
- package/dist/communityRepository/api/getRecommendedCommunities.d.ts +4 -19
- package/dist/communityRepository/api/getRecommendedCommunities.d.ts.map +1 -1
- package/dist/communityRepository/api/getTopTrendingCommunities.d.ts +5 -2
- package/dist/communityRepository/api/getTopTrendingCommunities.d.ts.map +1 -1
- package/dist/communityRepository/api/getTrendingCommunities.d.ts +17 -0
- package/dist/communityRepository/api/getTrendingCommunities.d.ts.map +1 -0
- package/dist/communityRepository/api/index.d.ts +0 -1
- package/dist/communityRepository/api/index.d.ts.map +1 -1
- package/dist/communityRepository/api/test/getTrendingCommunities.test.d.ts +2 -0
- package/dist/communityRepository/api/test/getTrendingCommunities.test.d.ts.map +1 -0
- package/dist/communityRepository/communityMembership/observers/getMembers.d.ts +1 -0
- package/dist/communityRepository/communityMembership/observers/getMembers.d.ts.map +1 -1
- package/dist/communityRepository/observers/getCommunities.d.ts +2 -2
- package/dist/communityRepository/observers/getCommunity.d.ts +2 -2
- package/dist/communityRepository/observers/getRecommendedCommunities.d.ts +20 -0
- package/dist/communityRepository/observers/getRecommendedCommunities.d.ts.map +1 -0
- package/dist/communityRepository/observers/getTrendingCommunities.d.ts +20 -0
- package/dist/communityRepository/observers/getTrendingCommunities.d.ts.map +1 -0
- package/dist/communityRepository/observers/index.d.ts +2 -0
- package/dist/communityRepository/observers/index.d.ts.map +1 -1
- package/dist/communityRepository/utils/communityQueryFilter.d.ts +2 -0
- package/dist/communityRepository/utils/communityQueryFilter.d.ts.map +1 -0
- package/dist/core/model/idResolvers.d.ts.map +1 -1
- package/dist/core/model/identifyModel.d.ts.map +1 -1
- package/dist/index.cjs.js +554 -237
- package/dist/index.esm.js +554 -237
- package/dist/index.umd.js +4 -4
- package/dist/pollRepository/api/index.d.ts +0 -1
- package/dist/pollRepository/api/index.d.ts.map +1 -1
- package/dist/pollRepository/observers/getPoll.d.ts +21 -0
- package/dist/pollRepository/observers/getPoll.d.ts.map +1 -0
- package/dist/pollRepository/observers/index.d.ts +1 -0
- package/dist/pollRepository/observers/index.d.ts.map +1 -1
- package/dist/postRepository/observers/getPost.d.ts +2 -2
- package/dist/reactionRepository/api/addReaction.d.ts +2 -2
- package/dist/reactionRepository/api/addReaction.d.ts.map +1 -1
- package/dist/reactionRepository/api/queryReactions.d.ts +2 -2
- package/dist/reactionRepository/api/queryReactions.d.ts.map +1 -1
- package/dist/reactionRepository/api/queryReactor.d.ts +19 -0
- package/dist/reactionRepository/api/queryReactor.d.ts.map +1 -0
- package/dist/reactionRepository/api/removeReaction.d.ts +2 -2
- package/dist/reactionRepository/api/removeReaction.d.ts.map +1 -1
- package/dist/reactionRepository/observers/getReactions.d.ts +3 -3
- package/dist/reactionRepository/observers/getReactions.d.ts.map +1 -1
- package/dist/streamRepository/observers/getStreamById.d.ts +19 -2
- package/dist/streamRepository/observers/getStreamById.d.ts.map +1 -1
- package/dist/streamRepository/observers/getStreams.d.ts.map +1 -1
- package/dist/streamRepository/observers/tests/getStreamById.test.d.ts +2 -0
- package/dist/streamRepository/observers/tests/getStreamById.test.d.ts.map +1 -0
- package/dist/userRepository/observers/getUsers.d.ts +1 -0
- package/dist/userRepository/observers/getUsers.d.ts.map +1 -1
- package/dist/utils/tests/dummy/reaction.d.ts +1 -1
- package/dist/utils/tests/dummy/reaction.d.ts.map +1 -1
- package/dist/utils/tests/dummy/stream.d.ts +22 -0
- package/dist/utils/tests/dummy/stream.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/@types/core/events.ts +4 -4
- package/src/@types/core/model.ts +3 -1
- package/src/@types/core/payload.ts +1 -1
- package/src/@types/domains/post.ts +1 -1
- package/src/@types/domains/reaction.ts +8 -9
- package/src/categoryRepository/api/queryCategories.ts +1 -1
- package/src/channelRepsitory/channelMembership/observers/getMembers.ts +47 -39
- package/src/channelRepsitory/channelMembership/observers/tests/getMembers.test.ts +82 -5
- package/src/client/observers/getTotalUnreadCount.ts +1 -7
- package/src/client/observers/tests/getTotalUnreadCount.test.ts +3 -10
- package/src/client/utils/markerSyncEngine.ts +13 -2
- package/src/commentRepository/events/onCommentReactionAdded.ts +1 -1
- package/src/commentRepository/events/onCommentReactionRemoved.ts +1 -1
- package/src/commentRepository/observers/getComment.ts +2 -2
- package/src/commentRepository/observers/tests/getComment.test.ts +1 -3
- package/src/communityRepository/api/getCommunity.ts +4 -4
- package/src/communityRepository/api/getRecommendedCommunities.ts +7 -48
- package/src/communityRepository/api/getTopTrendingCommunities.ts +5 -2
- package/src/communityRepository/api/getTrendingCommunities.ts +50 -0
- package/src/communityRepository/api/index.ts +1 -1
- package/src/communityRepository/api/test/getTrendingCommunities.test.ts +102 -0
- package/src/communityRepository/communityMembership/observers/getMembers.ts +31 -23
- package/src/communityRepository/communityMembership/observers/tests/getMembers.test.ts +80 -2
- package/src/communityRepository/observers/getCommunities.ts +2 -2
- package/src/communityRepository/observers/getCommunity.ts +2 -2
- package/src/communityRepository/observers/getRecommendedCommunities.ts +130 -0
- package/src/communityRepository/observers/getTrendingCommunities.ts +130 -0
- package/src/communityRepository/observers/index.ts +2 -0
- package/src/communityRepository/utils/communityQueryFilter.ts +55 -0
- package/src/core/model/idResolvers.ts +2 -1
- package/src/core/model/identifyModel.ts +5 -4
- package/src/pollRepository/api/index.ts +0 -2
- package/src/pollRepository/observers/getPoll.ts +33 -0
- package/src/pollRepository/observers/index.ts +1 -0
- package/src/pollRepository/observers/observePoll.ts +2 -2
- package/src/postRepository/events/tests/onPostReactionAdded.test.ts +6 -5
- package/src/postRepository/events/tests/onPostReactionRemoved.test.ts +5 -4
- package/src/postRepository/observers/getPost.ts +2 -2
- package/src/postRepository/observers/getPosts.ts +1 -1
- package/src/postRepository/observers/tests/getPost.test.ts +1 -3
- package/src/postRepository/observers/tests/getPosts.test.ts +1 -5
- package/src/reactionRepository/api/addReaction.ts +2 -2
- package/src/reactionRepository/api/queryReactions.ts +2 -2
- package/src/reactionRepository/api/queryReactor.ts +31 -0
- package/src/reactionRepository/api/removeReaction.ts +2 -2
- package/src/reactionRepository/observers/getReactions.ts +6 -8
- package/src/streamRepository/observers/getStreamById.ts +35 -1
- package/src/streamRepository/observers/getStreams.ts +6 -5
- package/src/streamRepository/observers/tests/getStreamById.test.ts +44 -0
- package/src/userRepository/observers/getUsers.ts +32 -24
- package/src/userRepository/observers/tests/getUsers.test.ts +46 -1
- package/src/utils/tests/dummy/reaction.ts +6 -10
- package/src/utils/tests/dummy/stream.ts +47 -0
|
@@ -33,15 +33,9 @@ export const getTotalUnreadCount = (
|
|
|
33
33
|
Amity.ErrorLevel.ERROR,
|
|
34
34
|
);
|
|
35
35
|
|
|
36
|
-
const callbackDataSelector = (data: Amity.UserMarker) => data?.unreadCount ?? 0;
|
|
37
|
-
|
|
38
|
-
// based on the mobile specs, unreadCount will not trigger observer when userMarker
|
|
39
|
-
// is re-fetched, so apply this filter to ensure the behavior is the same.
|
|
40
|
-
const callbackFilter = (newModel: Amity.UserMarker, oldModel: Amity.UserMarker) =>
|
|
41
|
-
newModel?.unreadCount !== oldModel?.unreadCount;
|
|
36
|
+
const callbackDataSelector = (data: Amity.UserMarker | undefined) => data?.unreadCount ?? 0;
|
|
42
37
|
|
|
43
38
|
return liveObject(userId, callback, 'userId', getUserMarker, [onUserMarkerFetched], {
|
|
44
39
|
callbackDataSelector,
|
|
45
|
-
callbackFilter,
|
|
46
40
|
});
|
|
47
41
|
};
|
|
@@ -59,7 +59,7 @@ describe('getTotalUnreadCount', () => {
|
|
|
59
59
|
|
|
60
60
|
await pause();
|
|
61
61
|
|
|
62
|
-
expect(callback).toHaveBeenCalledTimes(
|
|
62
|
+
expect(callback).toHaveBeenCalledTimes(2);
|
|
63
63
|
// on initial, expect 0 unread count
|
|
64
64
|
expect(callback).toHaveBeenLastCalledWith({
|
|
65
65
|
origin: 'server',
|
|
@@ -72,7 +72,7 @@ describe('getTotalUnreadCount', () => {
|
|
|
72
72
|
|
|
73
73
|
await pause();
|
|
74
74
|
|
|
75
|
-
expect(callback).toHaveBeenCalledTimes(
|
|
75
|
+
expect(callback).toHaveBeenCalledTimes(3);
|
|
76
76
|
expect(callback).toHaveBeenLastCalledWith(expected);
|
|
77
77
|
});
|
|
78
78
|
|
|
@@ -89,12 +89,6 @@ describe('getTotalUnreadCount', () => {
|
|
|
89
89
|
await pause();
|
|
90
90
|
|
|
91
91
|
// initial callback
|
|
92
|
-
expect(callback).toHaveBeenCalledTimes(1);
|
|
93
|
-
|
|
94
|
-
client.emitter.emit('local.userMarker.fetched', refreshUpdateTime(eventPayload));
|
|
95
|
-
|
|
96
|
-
await pause();
|
|
97
|
-
|
|
98
92
|
expect(callback).toHaveBeenCalledTimes(2);
|
|
99
93
|
|
|
100
94
|
// emit duplicated event
|
|
@@ -102,7 +96,6 @@ describe('getTotalUnreadCount', () => {
|
|
|
102
96
|
|
|
103
97
|
await pause();
|
|
104
98
|
|
|
105
|
-
|
|
106
|
-
expect(callback).toHaveBeenCalledTimes(2);
|
|
99
|
+
expect(callback).toHaveBeenCalledTimes(3);
|
|
107
100
|
});
|
|
108
101
|
});
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
onChannelJoined,
|
|
5
5
|
onChannelLeft,
|
|
6
6
|
} from '~/channelRepsitory';
|
|
7
|
-
import { onUserMarkerSync } from '~/marker/events/onUserMarkerSync'
|
|
7
|
+
import { onUserMarkerSync } from '~/marker/events/onUserMarkerSync';
|
|
8
8
|
import { setIntervalTask } from '~/utils/timer';
|
|
9
9
|
import { getUserMarker } from '~/marker/api';
|
|
10
10
|
import { onFeedMarkerUpdated } from '~/marker/events';
|
|
@@ -15,6 +15,7 @@ import { isUnreadCountSupport } from '~/subChannelRepository/utils';
|
|
|
15
15
|
import { markerSync } from '../api';
|
|
16
16
|
|
|
17
17
|
const SYNC_TRIGGER_INTERVAL_TIME = 2000;
|
|
18
|
+
const ON_SUB_CHANNEL_DELETE_SYNC_TRIGGER_DELAY = 2000;
|
|
18
19
|
|
|
19
20
|
let clearSyncTrigger: Amity.Unsubscriber | undefined;
|
|
20
21
|
let disposers: (() => void)[] = [];
|
|
@@ -138,7 +139,17 @@ const registerEventListeners = () => {
|
|
|
138
139
|
onChannelJoined(() => events.push(Amity.MarkerSyncEvent.CHANNEL_JOINED)),
|
|
139
140
|
onChannelLeft(() => events.push(Amity.MarkerSyncEvent.CHANNEL_LEFT)),
|
|
140
141
|
onSubChannelCreated(() => events.push(Amity.MarkerSyncEvent.SUB_CHANNEL_CREATED)),
|
|
141
|
-
onSubChannelDeleted(() =>
|
|
142
|
+
onSubChannelDeleted(() =>
|
|
143
|
+
/*
|
|
144
|
+
workaround: when receiving the event for sub-channel deletion,
|
|
145
|
+
before triggering marker update, the SDK will have to add a 2-second delay.
|
|
146
|
+
so that the unread count is calculated correctly.
|
|
147
|
+
*/
|
|
148
|
+
setTimeout(
|
|
149
|
+
() => events.push(Amity.MarkerSyncEvent.SUBCHANNEL_IS_DELETED),
|
|
150
|
+
ON_SUB_CHANNEL_DELETE_SYNC_TRIGGER_DELAY,
|
|
151
|
+
),
|
|
152
|
+
),
|
|
142
153
|
onFeedMarkerUpdated(() => events.push(Amity.MarkerSyncEvent.MARKER_UPDATED)),
|
|
143
154
|
onUserMarkerSync(() => events.push(Amity.MarkerSyncEvent.MARKER_UPDATED)),
|
|
144
155
|
);
|
|
@@ -24,7 +24,7 @@ export const onCommentReactionAdded = (
|
|
|
24
24
|
): Amity.Unsubscriber => {
|
|
25
25
|
const client = getActiveClient();
|
|
26
26
|
|
|
27
|
-
const filter = (payload: Amity.CommentPayload & { reactor: Amity.
|
|
27
|
+
const filter = (payload: Amity.CommentPayload & { reactor: Amity.Reactor }) => {
|
|
28
28
|
if (!client.cache) {
|
|
29
29
|
callback(payload.comments[0]);
|
|
30
30
|
} else {
|
|
@@ -24,7 +24,7 @@ export const onCommentReactionRemoved = (
|
|
|
24
24
|
): Amity.Unsubscriber => {
|
|
25
25
|
const client = getActiveClient();
|
|
26
26
|
|
|
27
|
-
const filter = (payload: Amity.CommentPayload & { reactor: Amity.
|
|
27
|
+
const filter = (payload: Amity.CommentPayload & { reactor: Amity.Reactor }) => {
|
|
28
28
|
if (!client.cache) {
|
|
29
29
|
callback(payload.comments[0]);
|
|
30
30
|
} else {
|
|
@@ -14,11 +14,11 @@ import {
|
|
|
14
14
|
*/
|
|
15
15
|
/**
|
|
16
16
|
* ```js
|
|
17
|
-
* import {
|
|
17
|
+
* import { CommentRepository } from '@amityco/ts-sdk';
|
|
18
18
|
*
|
|
19
19
|
* let comment;
|
|
20
20
|
*
|
|
21
|
-
* const
|
|
21
|
+
* const unsub = CommentRepository.getComment(commentId, response => {
|
|
22
22
|
* comment = response.data;
|
|
23
23
|
* });
|
|
24
24
|
* ```
|
|
@@ -75,12 +75,10 @@ describe('getComment', () => {
|
|
|
75
75
|
data: { text: 'new-text' },
|
|
76
76
|
updatedAt: getFutureDate(comment.updatedAt),
|
|
77
77
|
};
|
|
78
|
-
const reactor: Amity.
|
|
78
|
+
const reactor: Amity.Reactor = {
|
|
79
79
|
createdAt: getFutureDate(comment.updatedAt),
|
|
80
80
|
reactionId: 'like',
|
|
81
81
|
reactionName: 'like',
|
|
82
|
-
referenceId: comment.commentId,
|
|
83
|
-
referenceType: 'comment',
|
|
84
82
|
userId: user12.userId,
|
|
85
83
|
};
|
|
86
84
|
const callback = jest.fn();
|
|
@@ -7,8 +7,8 @@ import { prepareCommunityPayload } from '../utils';
|
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* ```js
|
|
10
|
-
* import {
|
|
11
|
-
* const community = await getCommunity('foobar')
|
|
10
|
+
* import { CommunityRepository } from '@amityco/ts-sdk'
|
|
11
|
+
* const community = await CommunityRepository.getCommunity('foobar')
|
|
12
12
|
* ```
|
|
13
13
|
*
|
|
14
14
|
* Fetches a {@link Amity.Community} object
|
|
@@ -45,8 +45,8 @@ export const getCommunity = async (
|
|
|
45
45
|
|
|
46
46
|
/**
|
|
47
47
|
* ```js
|
|
48
|
-
* import {
|
|
49
|
-
* const community = getCommunity.locally('foobar')
|
|
48
|
+
* import { CommunityRepository } from '@amityco/ts-sdk'
|
|
49
|
+
* const community = CommunityRepository.getCommunity.locally('foobar')
|
|
50
50
|
* ```
|
|
51
51
|
*
|
|
52
52
|
* Fetches a {@link Amity.Community} object from cache
|
|
@@ -5,14 +5,15 @@ import { pullFromCache, pushToCache } from '~/cache/api';
|
|
|
5
5
|
import { ingestInCache } from '~/cache/api/ingestInCache';
|
|
6
6
|
|
|
7
7
|
import { prepareCommunityPayload } from '../utils';
|
|
8
|
+
import { COLLECTION_DEFAULT_PAGINATION_LIMIT } from '~/utils/constants';
|
|
8
9
|
|
|
9
10
|
/* begin_public_function
|
|
10
11
|
id: community.query.recommended_communities
|
|
11
12
|
*/
|
|
12
13
|
/**
|
|
13
14
|
* ```js
|
|
14
|
-
* import {
|
|
15
|
-
* const communities = await getRecommendedCommunities()
|
|
15
|
+
* import { CommunityRepository } from '@amityco/ts-sdk'
|
|
16
|
+
* const communities = await CommunityRepository.getRecommendedCommunities()
|
|
16
17
|
* ```
|
|
17
18
|
*
|
|
18
19
|
* Gets a list of recommended {@link Amity.Community} objects
|
|
@@ -22,14 +23,15 @@ import { prepareCommunityPayload } from '../utils';
|
|
|
22
23
|
*
|
|
23
24
|
* @category Community API
|
|
24
25
|
* @async
|
|
26
|
+
* @private
|
|
25
27
|
*/
|
|
26
28
|
export const getRecommendedCommunities = async (
|
|
27
|
-
query?:
|
|
29
|
+
query?: Amity.PageLimit,
|
|
28
30
|
): Promise<Amity.Cached<Amity.Community[]>> => {
|
|
29
31
|
const client = getActiveClient();
|
|
30
|
-
client.log('
|
|
32
|
+
client.log('community/getRecommendedCommunities', query);
|
|
31
33
|
|
|
32
|
-
const { limit =
|
|
34
|
+
const { limit = COLLECTION_DEFAULT_PAGINATION_LIMIT } = query ?? {};
|
|
33
35
|
|
|
34
36
|
// API-FIX: backend doesnt answer Amity.Response
|
|
35
37
|
// const { data: payload } = await client.http.get<Amity.Response<CommunityPayload>>(
|
|
@@ -45,50 +47,7 @@ export const getRecommendedCommunities = async (
|
|
|
45
47
|
|
|
46
48
|
if (client.cache) {
|
|
47
49
|
ingestInCache(data, { cachedAt });
|
|
48
|
-
|
|
49
|
-
const cacheKey = ['community', 'recommended', { params: { options: { limit } } }];
|
|
50
|
-
pushToCache(cacheKey, { communities: communities.map(getResolver('community')) });
|
|
51
50
|
}
|
|
52
51
|
|
|
53
52
|
return { data: communities, cachedAt };
|
|
54
53
|
};
|
|
55
|
-
/* end_public_function */
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* ```js
|
|
59
|
-
* import { getRecommendedCommunities } from '@amityco/ts-sdk'
|
|
60
|
-
* const communities = getRecommendedCommunities.locally()
|
|
61
|
-
* ```
|
|
62
|
-
*
|
|
63
|
-
* Gets a list of recommended {@link Amity.Community} objects from cache
|
|
64
|
-
*
|
|
65
|
-
* @param query The query parameters
|
|
66
|
-
* @returns communities
|
|
67
|
-
*
|
|
68
|
-
* @category Community API
|
|
69
|
-
*/
|
|
70
|
-
getRecommendedCommunities.locally = (
|
|
71
|
-
query: Parameters<typeof getRecommendedCommunities>[0],
|
|
72
|
-
): Amity.Cached<Amity.Community[]> | undefined => {
|
|
73
|
-
const client = getActiveClient();
|
|
74
|
-
client.log('community/getRecommendedCommunities.locally', query);
|
|
75
|
-
|
|
76
|
-
if (!client.cache) return;
|
|
77
|
-
|
|
78
|
-
const { limit = 5 } = query ?? {};
|
|
79
|
-
|
|
80
|
-
const queryKey = ['community', 'recommended', { params: { options: { limit } } }];
|
|
81
|
-
const { data, cachedAt } =
|
|
82
|
-
pullFromCache<{ communities: Pick<Amity.Community, 'communityId'>[] }>(queryKey) ?? {};
|
|
83
|
-
|
|
84
|
-
if (!data?.communities.length) return;
|
|
85
|
-
|
|
86
|
-
const communities: Amity.Community[] = data.communities
|
|
87
|
-
.map(communityId => pullFromCache<Amity.Community>(['community', 'get', communityId])!)
|
|
88
|
-
.filter(Boolean)
|
|
89
|
-
.map(({ data }) => data);
|
|
90
|
-
|
|
91
|
-
return communities.length === data?.communities?.length
|
|
92
|
-
? { data: communities, cachedAt }
|
|
93
|
-
: undefined;
|
|
94
|
-
};
|
|
@@ -10,9 +10,12 @@ import { prepareCommunityPayload } from '../utils';
|
|
|
10
10
|
id: community.query.trending_communities
|
|
11
11
|
*/
|
|
12
12
|
/**
|
|
13
|
+
* @deprecated This API renamed to `getTrendingCommunities()`.
|
|
14
|
+
* Please use getTrendingCommunities() instead.
|
|
15
|
+
*
|
|
13
16
|
* ```js
|
|
14
|
-
* import {
|
|
15
|
-
* const trendingCommunities = await
|
|
17
|
+
* import { CommunityRepository } from '@amityco/ts-sdk'
|
|
18
|
+
* const trendingCommunities = await CommunityRepository.getTrendingCommunities()
|
|
16
19
|
* ```
|
|
17
20
|
*
|
|
18
21
|
* Gets a list of top trending {@link Amity.Community} objects
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { getActiveClient } from '~/client/api';
|
|
2
|
+
|
|
3
|
+
import { getResolver } from '~/core/model';
|
|
4
|
+
import { pullFromCache, pushToCache } from '~/cache/api';
|
|
5
|
+
import { ingestInCache } from '~/cache/api/ingestInCache';
|
|
6
|
+
|
|
7
|
+
import { prepareCommunityPayload } from '../utils';
|
|
8
|
+
import { COLLECTION_DEFAULT_PAGINATION_LIMIT } from '~/utils/constants';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* ```js
|
|
12
|
+
* import { CommunityRepository } from '@amityco/ts-sdk'
|
|
13
|
+
* const trendingCommunities = await CommunityRepository.getTrendingCommunities()
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* Gets a list of top trending {@link Amity.Community} objects
|
|
17
|
+
*
|
|
18
|
+
* @param query The query parameters
|
|
19
|
+
* @returns A list of {@link Amity.Community} objects
|
|
20
|
+
*
|
|
21
|
+
* @category Community API
|
|
22
|
+
* @async
|
|
23
|
+
* @private
|
|
24
|
+
*/
|
|
25
|
+
export const getTrendingCommunities = async (
|
|
26
|
+
query?: Amity.PageLimit,
|
|
27
|
+
): Promise<Amity.Cached<Amity.Community[]>> => {
|
|
28
|
+
const client = getActiveClient();
|
|
29
|
+
client.log('community/getTrendingCommunities', query);
|
|
30
|
+
|
|
31
|
+
const { limit = COLLECTION_DEFAULT_PAGINATION_LIMIT } = query ?? {};
|
|
32
|
+
|
|
33
|
+
// API-FIX: backend doesnt answer Amity.Response
|
|
34
|
+
// const { data } = await client.http.get<Amity.Response<CommunityPayload>>(
|
|
35
|
+
const { data: payload } = await client.http.get<Amity.CommunityPayload>(
|
|
36
|
+
`/api/v3/communities/top-trending`,
|
|
37
|
+
{ params: { options: { limit } } },
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
const data = prepareCommunityPayload(payload);
|
|
41
|
+
const { communities } = data;
|
|
42
|
+
|
|
43
|
+
const cachedAt = client.cache && Date.now();
|
|
44
|
+
|
|
45
|
+
if (client.cache) {
|
|
46
|
+
ingestInCache(data, { cachedAt });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return { data: communities, cachedAt };
|
|
50
|
+
};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { disableCache, enableCache, pullFromCache, pushToCache } from '~/cache/api';
|
|
2
|
+
import { client, community11, community21 } from '~/utils/tests';
|
|
3
|
+
|
|
4
|
+
import { getTrendingCommunities } from '../getTrendingCommunities';
|
|
5
|
+
|
|
6
|
+
const topTrendCommunities = [community11, community21];
|
|
7
|
+
const topTrendIds = topTrendCommunities.map(({ communityId }) => communityId);
|
|
8
|
+
|
|
9
|
+
const pagingToken = {
|
|
10
|
+
previous: 'eyJiZWZvcmUiOjU1LCJsYXN0IjoxMH0=',
|
|
11
|
+
next: 'eyJiZWZvcmUiOjU1LCJsYXN0IjoxMH0=',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const pagingCriteria = { limit: 10 };
|
|
15
|
+
|
|
16
|
+
const resolvedGetValue = {
|
|
17
|
+
data: {
|
|
18
|
+
communities: topTrendCommunities,
|
|
19
|
+
communityUsers: [community11, community21],
|
|
20
|
+
files: [],
|
|
21
|
+
users: [],
|
|
22
|
+
categories: [],
|
|
23
|
+
feeds: [],
|
|
24
|
+
paging: pagingToken,
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
describe('getTrendingCommunities', () => {
|
|
29
|
+
test('should return fetched top trend communities with correct paging', async () => {
|
|
30
|
+
client.http.get = jest.fn().mockResolvedValueOnce(resolvedGetValue);
|
|
31
|
+
|
|
32
|
+
await expect(getTrendingCommunities(pagingCriteria)).resolves.toEqual(
|
|
33
|
+
expect.objectContaining({ data: topTrendCommunities }),
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test('should update cache after fetching top trend communities', async () => {
|
|
38
|
+
enableCache();
|
|
39
|
+
client.http.get = jest.fn().mockResolvedValue(resolvedGetValue);
|
|
40
|
+
|
|
41
|
+
await getTrendingCommunities(pagingCriteria);
|
|
42
|
+
|
|
43
|
+
const recieved = pullFromCache([
|
|
44
|
+
'community',
|
|
45
|
+
'top-trending',
|
|
46
|
+
{ params: { options: pagingCriteria } },
|
|
47
|
+
])?.data;
|
|
48
|
+
|
|
49
|
+
expect(recieved).toEqual({ communities: topTrendIds });
|
|
50
|
+
|
|
51
|
+
disableCache();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('should throw an error if request fails', async () => {
|
|
55
|
+
client.http.get = jest.fn().mockRejectedValueOnce(new Error('error'));
|
|
56
|
+
|
|
57
|
+
await expect(getTrendingCommunities(pagingCriteria)).rejects.toThrow('error');
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe('getTopTrendingCommunities.locally', () => {
|
|
62
|
+
beforeEach(() => enableCache());
|
|
63
|
+
afterEach(() => disableCache());
|
|
64
|
+
|
|
65
|
+
test('should return cached top trend communities', () => {
|
|
66
|
+
topTrendCommunities.forEach(community =>
|
|
67
|
+
pushToCache(['community', 'get', community.communityId], community),
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
pushToCache(['community', 'top-trending', { params: { options: pagingCriteria } }], {
|
|
71
|
+
communities: topTrendIds,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
expect(getTrendingCommunities.locally(pagingCriteria)?.data).toEqual(topTrendCommunities);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test('it should return undefined if top trend communities not in cache', () => {
|
|
78
|
+
topTrendCommunities.forEach(community =>
|
|
79
|
+
pushToCache(['community', 'get', community.communityId], community),
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
pushToCache(['community', 'top-trending', { params: { options: pagingCriteria } }], {
|
|
83
|
+
communities: topTrendIds,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
expect(getTrendingCommunities.locally({ limit: -1 })).toBeUndefined();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test('should return undefined if cache not enabled', () => {
|
|
90
|
+
disableCache();
|
|
91
|
+
|
|
92
|
+
topTrendCommunities.forEach(community =>
|
|
93
|
+
pushToCache(['community', 'get', community.communityId], community),
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
pushToCache(['community', 'top-trending', { params: { options: pagingCriteria } }], {
|
|
97
|
+
communities: topTrendIds,
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
expect(getTrendingCommunities.locally(pagingCriteria)).toBeUndefined();
|
|
101
|
+
});
|
|
102
|
+
});
|
|
@@ -27,6 +27,35 @@ import {
|
|
|
27
27
|
} from '../events';
|
|
28
28
|
import { queryCommunityMembers } from '../api/queryCommunityMembers';
|
|
29
29
|
|
|
30
|
+
/*
|
|
31
|
+
* Exported for testing
|
|
32
|
+
* @hidden
|
|
33
|
+
*/
|
|
34
|
+
export const applyFilter = <T extends Amity.Membership<'community'>>(
|
|
35
|
+
data: T[],
|
|
36
|
+
params: Amity.CommunityMemberLiveCollection,
|
|
37
|
+
): T[] => {
|
|
38
|
+
let communityMembers = filterByPropIntersection(data, 'roles', params.roles);
|
|
39
|
+
|
|
40
|
+
if (params.membership) {
|
|
41
|
+
communityMembers = communityMembers.filter(({ communityMembership }) =>
|
|
42
|
+
// @ts-ignore
|
|
43
|
+
params.membership.includes(communityMembership),
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (params.search) {
|
|
48
|
+
communityMembers = filterBySearchTerm(communityMembers, params.search);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const sortBy = params.sortBy ? params.sortBy : 'lastCreated';
|
|
52
|
+
communityMembers = communityMembers.sort(
|
|
53
|
+
sortBy === 'lastCreated' ? sortByLastCreated : sortByFirstCreated,
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
return communityMembers;
|
|
57
|
+
};
|
|
58
|
+
|
|
30
59
|
/* begin_public_function
|
|
31
60
|
id: community.membership.query
|
|
32
61
|
*/
|
|
@@ -56,6 +85,7 @@ export const getMembers = (
|
|
|
56
85
|
const { log, cache } = getActiveClient();
|
|
57
86
|
|
|
58
87
|
if (!cache) {
|
|
88
|
+
// eslint-disable-next-line no-console
|
|
59
89
|
console.log(ENABLE_CACHE_MESSAGE);
|
|
60
90
|
}
|
|
61
91
|
|
|
@@ -70,28 +100,6 @@ export const getMembers = (
|
|
|
70
100
|
const disposers: Amity.Unsubscriber[] = [];
|
|
71
101
|
const cacheKey = ['communityUsers', 'collection', { communityId: params.communityId }];
|
|
72
102
|
|
|
73
|
-
const applyFilter = <T extends Amity.Membership<'community'>>(data: T[]): T[] => {
|
|
74
|
-
let communityMembers = filterByPropIntersection(data, 'roles', params.roles);
|
|
75
|
-
|
|
76
|
-
if (params.membership) {
|
|
77
|
-
communityMembers = communityMembers.filter(({ communityMembership }) =>
|
|
78
|
-
// @ts-ignore
|
|
79
|
-
params.membership.includes(communityMembership),
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (params.search) {
|
|
84
|
-
communityMembers = filterBySearchTerm(communityMembers, params.search);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const sortBy = params.sortBy ? params.sortBy : 'lastCreated';
|
|
88
|
-
communityMembers = communityMembers.sort(
|
|
89
|
-
sortBy === 'lastCreated' ? sortByLastCreated : sortByFirstCreated,
|
|
90
|
-
);
|
|
91
|
-
|
|
92
|
-
return communityMembers;
|
|
93
|
-
};
|
|
94
|
-
|
|
95
103
|
const responder = (data: Amity.CommunityMemberLiveCollectionCache, isEventModel = false) => {
|
|
96
104
|
const communityMembers: Amity.Membership<'community'>[] =
|
|
97
105
|
data.data
|
|
@@ -101,7 +109,7 @@ export const getMembers = (
|
|
|
101
109
|
|
|
102
110
|
callback({
|
|
103
111
|
onNextPage: onFetch,
|
|
104
|
-
data: isEventModel ? applyFilter(communityMembers) : communityMembers,
|
|
112
|
+
data: isEventModel ? applyFilter(communityMembers, params) : communityMembers,
|
|
105
113
|
hasNextPage: !!data.params?.page,
|
|
106
114
|
loading: data.loading,
|
|
107
115
|
error: data.error,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { getPastDate } from '~/core/model';
|
|
1
2
|
import { disableCache, enableCache } from '~/cache/api';
|
|
2
|
-
|
|
3
3
|
import {
|
|
4
4
|
client,
|
|
5
5
|
connectClient,
|
|
@@ -19,7 +19,10 @@ import {
|
|
|
19
19
|
convertedCommunityUser3,
|
|
20
20
|
} from '~/utils/tests';
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
// makes it easier to spy on applyFilter
|
|
23
|
+
import * as getMembersModule from '../getMembers';
|
|
24
|
+
|
|
25
|
+
const { getMembers, applyFilter } = getMembersModule;
|
|
23
26
|
|
|
24
27
|
const getSnapshot = (params?: Record<string, any>) => {
|
|
25
28
|
return {
|
|
@@ -166,4 +169,79 @@ describe('getMembers', () => {
|
|
|
166
169
|
),
|
|
167
170
|
);
|
|
168
171
|
});
|
|
172
|
+
|
|
173
|
+
test('it should apply fileters on RTE only', async () => {
|
|
174
|
+
const callback = jest.fn();
|
|
175
|
+
const applyFilterSpy = jest.spyOn(getMembersModule, 'applyFilter');
|
|
176
|
+
client.http.get = jest.fn().mockResolvedValue(communityUserQueryResponse);
|
|
177
|
+
|
|
178
|
+
getMembers({ communityId, sortBy: 'firstCreated' }, callback);
|
|
179
|
+
await pause();
|
|
180
|
+
|
|
181
|
+
expect(applyFilterSpy).not.toHaveBeenCalled();
|
|
182
|
+
|
|
183
|
+
client.emitter.emit('community.joined', {
|
|
184
|
+
communities: [community11],
|
|
185
|
+
communityUsers: [communityUser13],
|
|
186
|
+
users: [user13],
|
|
187
|
+
files: [],
|
|
188
|
+
categories: [],
|
|
189
|
+
feeds: [],
|
|
190
|
+
});
|
|
191
|
+
await pause();
|
|
192
|
+
|
|
193
|
+
expect(applyFilterSpy).toHaveBeenCalled();
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
describe('getMembers > applyFilter', () => {
|
|
198
|
+
const { communityId } = community11;
|
|
199
|
+
|
|
200
|
+
const m1 = {
|
|
201
|
+
communityId,
|
|
202
|
+
userId: 'test',
|
|
203
|
+
communityMembership: 'member',
|
|
204
|
+
roles: ['test-role'],
|
|
205
|
+
createdAt: new Date().toISOString(),
|
|
206
|
+
} as Amity.Membership<'community'>;
|
|
207
|
+
|
|
208
|
+
const m2 = {
|
|
209
|
+
communityId,
|
|
210
|
+
userId: 'searchable',
|
|
211
|
+
communityMembership: 'banned',
|
|
212
|
+
createdAt: getPastDate(),
|
|
213
|
+
} as Amity.Membership<'community'>;
|
|
214
|
+
|
|
215
|
+
const filters: [
|
|
216
|
+
string,
|
|
217
|
+
Amity.CommunityMemberLiveCollection,
|
|
218
|
+
Amity.Membership<'community'>[],
|
|
219
|
+
Amity.Membership<'community'>[],
|
|
220
|
+
][] = [
|
|
221
|
+
['it should filter by roles', { communityId, roles: ['test-role'] }, [m1, m2], [m1]],
|
|
222
|
+
[
|
|
223
|
+
'it should filter by membership:member',
|
|
224
|
+
{ communityId, membership: ['member'] },
|
|
225
|
+
[m1, m2],
|
|
226
|
+
[m1],
|
|
227
|
+
],
|
|
228
|
+
[
|
|
229
|
+
'it should filter by membership:banned',
|
|
230
|
+
{ communityId, membership: ['banned'] },
|
|
231
|
+
[m1, m2],
|
|
232
|
+
[m2],
|
|
233
|
+
],
|
|
234
|
+
['it should sort by last created', { communityId }, [m1, m2], [m1, m2]],
|
|
235
|
+
[
|
|
236
|
+
'it should sort by first created',
|
|
237
|
+
{ communityId, sortBy: 'firstCreated' },
|
|
238
|
+
[m1, m2],
|
|
239
|
+
[m2, m1],
|
|
240
|
+
],
|
|
241
|
+
['it should filter by search term', { communityId, search: 'sea' }, [m1, m2], [m2]],
|
|
242
|
+
];
|
|
243
|
+
|
|
244
|
+
test.each(filters)('%s', (test, param, input, expected) => {
|
|
245
|
+
expect(applyFilter(input, param)).toStrictEqual(expected);
|
|
246
|
+
});
|
|
169
247
|
});
|
|
@@ -31,10 +31,10 @@ import { CACHE_SHORTEN_LIFESPAN } from '~/cache/utils';
|
|
|
31
31
|
*/
|
|
32
32
|
/**
|
|
33
33
|
* ```js
|
|
34
|
-
* import {
|
|
34
|
+
* import { CommunityRepository } from '@amityco/ts-sdk'
|
|
35
35
|
*
|
|
36
36
|
* let communities = []
|
|
37
|
-
* const unsub = getCommunities({
|
|
37
|
+
* const unsub = CommunityRepository.getCommunities({
|
|
38
38
|
* displayName: Amity.Community['displayName'],
|
|
39
39
|
* }, response => merge(communities, response.data))
|
|
40
40
|
* ```
|
|
@@ -14,11 +14,11 @@ import {
|
|
|
14
14
|
*/
|
|
15
15
|
/**
|
|
16
16
|
* ```js
|
|
17
|
-
* import {
|
|
17
|
+
* import { CommunityRepository } from '@amityco/ts-sdk';
|
|
18
18
|
*
|
|
19
19
|
* let community;
|
|
20
20
|
*
|
|
21
|
-
* const
|
|
21
|
+
* const unsub = CommunityRepository.getCommunity(communityId, response => {
|
|
22
22
|
* community = response.data;
|
|
23
23
|
* });
|
|
24
24
|
* ```
|