@amityco/ts-sdk 6.4.6-bdc04db.0 → 6.4.6-be7e4df.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/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 -4
- 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 +32 -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/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 +371 -166
- package/dist/index.esm.js +371 -166
- 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/utils/tests/dummy/reaction.d.ts +1 -1
- package/dist/utils/tests/dummy/reaction.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/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 +4 -4
- package/src/communityRepository/api/getTopTrendingCommunities.ts +5 -2
- package/src/communityRepository/api/getTrendingCommunities.ts +97 -0
- package/src/communityRepository/api/index.ts +1 -1
- package/src/communityRepository/api/test/getTrendingCommunities.test.ts +102 -0
- package/src/communityRepository/observers/getCommunities.ts +2 -2
- package/src/communityRepository/observers/getCommunity.ts +2 -2
- package/src/communityRepository/observers/getRecommendedCommunities.ts +133 -0
- package/src/communityRepository/observers/getTrendingCommunities.ts +133 -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/utils/tests/dummy/reaction.ts +6 -10
|
@@ -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
|
+
});
|
|
@@ -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
|
* ```
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/* eslint-disable no-use-before-define */
|
|
2
|
+
import { getResolver } from '~/core/model';
|
|
3
|
+
import { dropFromCache, pullFromCache, pushToCache } from '~/cache/api';
|
|
4
|
+
import { getActiveClient } from '~/client/api';
|
|
5
|
+
import { createQuery, queryOptions, runQuery } from '~/core/query';
|
|
6
|
+
import {
|
|
7
|
+
COLLECTION_DEFAULT_CACHING_POLICY,
|
|
8
|
+
COLLECTION_DEFAULT_PAGINATION_LIMIT,
|
|
9
|
+
ENABLE_CACHE_MESSAGE,
|
|
10
|
+
} from '~/utils/constants';
|
|
11
|
+
|
|
12
|
+
import { onCommunityUserChanged } from '../communityMembership/events';
|
|
13
|
+
import { queryCommunities } from '../api/queryCommunities';
|
|
14
|
+
import { CACHE_SHORTEN_LIFESPAN } from '~/cache/utils';
|
|
15
|
+
import { communityQueryFilter } from '../utils/communityQueryFilter';
|
|
16
|
+
|
|
17
|
+
/* begin_public_function
|
|
18
|
+
id: community.query
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* ```js
|
|
22
|
+
* import { CommunityRepository } from '@amityco/ts-sdk'
|
|
23
|
+
*
|
|
24
|
+
* let communities = []
|
|
25
|
+
* const unsub = CommunityRepository.getCommunities({
|
|
26
|
+
* displayName: Amity.Community['displayName'],
|
|
27
|
+
* }, response => merge(communities, response.data))
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* Observe all mutations on a list of {@link Amity.Community}s
|
|
31
|
+
*
|
|
32
|
+
* @param params for querying communities
|
|
33
|
+
* @param callback the function to call when new data are available
|
|
34
|
+
* @returns An {@link Amity.Unsubscriber} function to run when willing to stop observing the communities
|
|
35
|
+
*
|
|
36
|
+
* @category Community Live Collection
|
|
37
|
+
*/
|
|
38
|
+
export const getRecommendedCommunities = (
|
|
39
|
+
params: Amity.CommunityLiveCollection,
|
|
40
|
+
callback: Amity.LiveCollectionCallback<Amity.Community>,
|
|
41
|
+
config?: Amity.LiveCollectionConfig,
|
|
42
|
+
) => {
|
|
43
|
+
const { log, cache, userId } = getActiveClient();
|
|
44
|
+
|
|
45
|
+
if (!cache) {
|
|
46
|
+
console.log(ENABLE_CACHE_MESSAGE);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const timestamp = Date.now();
|
|
50
|
+
log(`getRecommendedCommunities(tmpid: ${timestamp}) > listen`);
|
|
51
|
+
|
|
52
|
+
const { limit: queryLimit, ...queryParams } = params;
|
|
53
|
+
|
|
54
|
+
const limit = queryLimit ?? COLLECTION_DEFAULT_PAGINATION_LIMIT;
|
|
55
|
+
const { policy = COLLECTION_DEFAULT_CACHING_POLICY } = config ?? {};
|
|
56
|
+
|
|
57
|
+
const disposers: Amity.Unsubscriber[] = [];
|
|
58
|
+
const cacheKey = ['community', 'recommended', { params: { options: { limit } } }];
|
|
59
|
+
|
|
60
|
+
const responder = (data: Amity.CommunityLiveCollectionCache, isEventModel = false) => {
|
|
61
|
+
const communities: Amity.Community[] =
|
|
62
|
+
data.data
|
|
63
|
+
.map(communityId => pullFromCache<Amity.Community>(['community', 'get', communityId])!)
|
|
64
|
+
.filter(Boolean)
|
|
65
|
+
.map(({ data }) => data) ?? [];
|
|
66
|
+
|
|
67
|
+
callback({
|
|
68
|
+
onNextPage: onFetch,
|
|
69
|
+
data: isEventModel ? communityQueryFilter(communities, params, userId!) : communities,
|
|
70
|
+
hasNextPage: !!data.params?.page,
|
|
71
|
+
loading: data.loading,
|
|
72
|
+
error: data.error,
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const realtimeRouter = (_: Amity.CommunityActionType) => (community: Amity.Community) => {
|
|
77
|
+
const collection = pullFromCache<Amity.CommunityLiveCollectionCache>(cacheKey)?.data;
|
|
78
|
+
if (!collection) return;
|
|
79
|
+
|
|
80
|
+
/*
|
|
81
|
+
* Simply update collection and let responder decide what to do with data
|
|
82
|
+
*/
|
|
83
|
+
collection.data = [...new Set([community.communityId, ...collection.data])];
|
|
84
|
+
|
|
85
|
+
pushToCache(cacheKey, collection);
|
|
86
|
+
responder(collection);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const onFetch = (initial = false) => {
|
|
90
|
+
const collection = pullFromCache<Amity.CommunityLiveCollectionCache>(cacheKey)?.data;
|
|
91
|
+
|
|
92
|
+
const communities = collection?.data ?? [];
|
|
93
|
+
|
|
94
|
+
if (!initial && communities.length > 0 && !collection?.params.page) return;
|
|
95
|
+
|
|
96
|
+
const query = createQuery(queryCommunities, {
|
|
97
|
+
...queryParams,
|
|
98
|
+
page: (!initial ? collection?.params.page : undefined) ?? { limit },
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
runQuery(
|
|
102
|
+
query,
|
|
103
|
+
({ data: result, error, loading, nextPage: page }) => {
|
|
104
|
+
const data = {
|
|
105
|
+
loading,
|
|
106
|
+
error,
|
|
107
|
+
params: { page },
|
|
108
|
+
data: communities,
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
if (result) {
|
|
112
|
+
data.data = [...new Set([...communities, ...result.map(getResolver('community'))])];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
pushToCache(cacheKey, data);
|
|
116
|
+
|
|
117
|
+
responder(data);
|
|
118
|
+
},
|
|
119
|
+
queryOptions(policy, CACHE_SHORTEN_LIFESPAN),
|
|
120
|
+
);
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
disposers.push(onCommunityUserChanged(realtimeRouter('onMemberCountChanged')));
|
|
124
|
+
|
|
125
|
+
onFetch(true);
|
|
126
|
+
disposers.push(() => dropFromCache(cacheKey));
|
|
127
|
+
|
|
128
|
+
return () => {
|
|
129
|
+
log(`getRecommendedCommunities(tmpid: ${timestamp}) > dispose`);
|
|
130
|
+
disposers.forEach(fn => fn());
|
|
131
|
+
};
|
|
132
|
+
};
|
|
133
|
+
/* end_public_function */
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/* eslint-disable no-use-before-define */
|
|
2
|
+
import { getResolver } from '~/core/model';
|
|
3
|
+
import { dropFromCache, pullFromCache, pushToCache } from '~/cache/api';
|
|
4
|
+
import { getActiveClient } from '~/client/api';
|
|
5
|
+
import { createQuery, queryOptions, runQuery } from '~/core/query';
|
|
6
|
+
import {
|
|
7
|
+
COLLECTION_DEFAULT_CACHING_POLICY,
|
|
8
|
+
COLLECTION_DEFAULT_PAGINATION_LIMIT,
|
|
9
|
+
ENABLE_CACHE_MESSAGE,
|
|
10
|
+
} from '~/utils/constants';
|
|
11
|
+
|
|
12
|
+
import { onCommunityUserChanged } from '../communityMembership/events';
|
|
13
|
+
import { queryCommunities } from '../api/queryCommunities';
|
|
14
|
+
import { CACHE_SHORTEN_LIFESPAN } from '~/cache/utils';
|
|
15
|
+
import { communityQueryFilter } from '../utils/communityQueryFilter';
|
|
16
|
+
|
|
17
|
+
/* begin_public_function
|
|
18
|
+
id: community.query
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* ```js
|
|
22
|
+
* import { CommunityRepository } from '@amityco/ts-sdk'
|
|
23
|
+
*
|
|
24
|
+
* let communities = []
|
|
25
|
+
* const unsub = CommunityRepository.getCommunities({
|
|
26
|
+
* displayName: Amity.Community['displayName'],
|
|
27
|
+
* }, response => merge(communities, response.data))
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* Observe all mutations on a list of {@link Amity.Community}s
|
|
31
|
+
*
|
|
32
|
+
* @param params for querying communities
|
|
33
|
+
* @param callback the function to call when new data are available
|
|
34
|
+
* @returns An {@link Amity.Unsubscriber} function to run when willing to stop observing the communities
|
|
35
|
+
*
|
|
36
|
+
* @category Community Live Collection
|
|
37
|
+
*/
|
|
38
|
+
export const getTrendingCommunities = (
|
|
39
|
+
params: Amity.CommunityLiveCollection,
|
|
40
|
+
callback: Amity.LiveCollectionCallback<Amity.Community>,
|
|
41
|
+
config?: Amity.LiveCollectionConfig,
|
|
42
|
+
) => {
|
|
43
|
+
const { log, cache, userId } = getActiveClient();
|
|
44
|
+
|
|
45
|
+
if (!cache) {
|
|
46
|
+
console.log(ENABLE_CACHE_MESSAGE);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const timestamp = Date.now();
|
|
50
|
+
log(`getTrendingCommunities(tmpid: ${timestamp}) > listen`);
|
|
51
|
+
|
|
52
|
+
const { limit: queryLimit, ...queryParams } = params;
|
|
53
|
+
|
|
54
|
+
const limit = queryLimit ?? COLLECTION_DEFAULT_PAGINATION_LIMIT;
|
|
55
|
+
const { policy = COLLECTION_DEFAULT_CACHING_POLICY } = config ?? {};
|
|
56
|
+
|
|
57
|
+
const disposers: Amity.Unsubscriber[] = [];
|
|
58
|
+
const cacheKey = ['community', 'top-trending', { params: { options: { limit } } }];
|
|
59
|
+
|
|
60
|
+
const responder = (data: Amity.CommunityLiveCollectionCache, isEventModel = false) => {
|
|
61
|
+
const communities: Amity.Community[] =
|
|
62
|
+
data.data
|
|
63
|
+
.map(communityId => pullFromCache<Amity.Community>(['community', 'get', communityId])!)
|
|
64
|
+
.filter(Boolean)
|
|
65
|
+
.map(({ data }) => data) ?? [];
|
|
66
|
+
|
|
67
|
+
callback({
|
|
68
|
+
onNextPage: onFetch,
|
|
69
|
+
data: isEventModel ? communityQueryFilter(communities, params, userId!) : communities,
|
|
70
|
+
hasNextPage: !!data.params?.page,
|
|
71
|
+
loading: data.loading,
|
|
72
|
+
error: data.error,
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const realtimeRouter = (_: Amity.CommunityActionType) => (community: Amity.Community) => {
|
|
77
|
+
const collection = pullFromCache<Amity.CommunityLiveCollectionCache>(cacheKey)?.data;
|
|
78
|
+
if (!collection) return;
|
|
79
|
+
|
|
80
|
+
/*
|
|
81
|
+
* Simply update collection and let responder decide what to do with data
|
|
82
|
+
*/
|
|
83
|
+
collection.data = [...new Set([community.communityId, ...collection.data])];
|
|
84
|
+
|
|
85
|
+
pushToCache(cacheKey, collection);
|
|
86
|
+
responder(collection);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const onFetch = (initial = false) => {
|
|
90
|
+
const collection = pullFromCache<Amity.CommunityLiveCollectionCache>(cacheKey)?.data;
|
|
91
|
+
|
|
92
|
+
const communities = collection?.data ?? [];
|
|
93
|
+
|
|
94
|
+
if (!initial && communities.length > 0 && !collection?.params.page) return;
|
|
95
|
+
|
|
96
|
+
const query = createQuery(queryCommunities, {
|
|
97
|
+
...queryParams,
|
|
98
|
+
page: (!initial ? collection?.params.page : undefined) ?? { limit },
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
runQuery(
|
|
102
|
+
query,
|
|
103
|
+
({ data: result, error, loading, nextPage: page }) => {
|
|
104
|
+
const data = {
|
|
105
|
+
loading,
|
|
106
|
+
error,
|
|
107
|
+
params: { page },
|
|
108
|
+
data: communities,
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
if (result) {
|
|
112
|
+
data.data = [...new Set([...communities, ...result.map(getResolver('community'))])];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
pushToCache(cacheKey, data);
|
|
116
|
+
|
|
117
|
+
responder(data);
|
|
118
|
+
},
|
|
119
|
+
queryOptions(policy, CACHE_SHORTEN_LIFESPAN),
|
|
120
|
+
);
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
disposers.push(onCommunityUserChanged(realtimeRouter('onMemberCountChanged')));
|
|
124
|
+
|
|
125
|
+
onFetch(true);
|
|
126
|
+
disposers.push(() => dropFromCache(cacheKey));
|
|
127
|
+
|
|
128
|
+
return () => {
|
|
129
|
+
log(`getTrendingCommunities(tmpid: ${timestamp}) > dispose`);
|
|
130
|
+
disposers.forEach(fn => fn());
|
|
131
|
+
};
|
|
132
|
+
};
|
|
133
|
+
/* end_public_function */
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import {
|
|
2
|
+
filterByCommunityMembership,
|
|
3
|
+
filterByPropEquality,
|
|
4
|
+
sortByDisplayName,
|
|
5
|
+
sortByFirstCreated,
|
|
6
|
+
sortByLastCreated,
|
|
7
|
+
} from '~/core/query';
|
|
8
|
+
|
|
9
|
+
export const communityQueryFilter = (
|
|
10
|
+
data: Amity.Community[],
|
|
11
|
+
params: Amity.CommunityLiveCollection,
|
|
12
|
+
userId: string,
|
|
13
|
+
): Amity.Community[] => {
|
|
14
|
+
let communities = data;
|
|
15
|
+
communities = filterByPropEquality(communities, 'displayName', params.displayName);
|
|
16
|
+
|
|
17
|
+
if (!params.includeDeleted) {
|
|
18
|
+
communities = filterByPropEquality(communities, 'isDeleted', false);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (params.categoryId) {
|
|
22
|
+
communities = communities.filter(c => c.categoryIds?.includes(params.categoryId!));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (params.tags) {
|
|
26
|
+
communities = communities.filter(c => c.tags?.some(t => params.tags?.includes(t)));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (params.membership && userId) {
|
|
30
|
+
communities = filterByCommunityMembership(communities, params.membership, userId);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const sortBy = params.sortBy || 'lastCreated';
|
|
34
|
+
|
|
35
|
+
if (sortBy === 'lastCreated' || sortBy === 'firstCreated') {
|
|
36
|
+
communities = communities.sort(
|
|
37
|
+
sortBy === 'lastCreated' ? sortByLastCreated : sortByFirstCreated,
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/*
|
|
42
|
+
* The server returns communities with empty | null displayName's first before
|
|
43
|
+
* returning sorted list of communities with displayNames
|
|
44
|
+
*
|
|
45
|
+
* This section needs to be updated as displayNames can be null as well
|
|
46
|
+
*/
|
|
47
|
+
if (sortBy === 'displayName') {
|
|
48
|
+
communities = communities
|
|
49
|
+
// this needs to be aligned with the backend data type
|
|
50
|
+
.map(c => (c.displayName ? c : { ...c, displayName: '' }))
|
|
51
|
+
// @ts-ignore
|
|
52
|
+
.sort(sortByDisplayName);
|
|
53
|
+
}
|
|
54
|
+
return communities;
|
|
55
|
+
};
|
|
@@ -33,7 +33,8 @@ const idResolvers: Resolvers = {
|
|
|
33
33
|
post: ({ postId }) => postId,
|
|
34
34
|
comment: ({ commentId }) => commentId,
|
|
35
35
|
poll: ({ pollId }) => pollId,
|
|
36
|
-
reaction: ({
|
|
36
|
+
reaction: ({ referenceType, referenceId }) => `${referenceType}#${referenceId}`,
|
|
37
|
+
reactor: ({ reactionId }) => reactionId,
|
|
37
38
|
|
|
38
39
|
stream: ({ streamId }) => streamId,
|
|
39
40
|
|
|
@@ -21,10 +21,10 @@ type Criterias<T extends Amity.Domain = Amity.Domain> = {
|
|
|
21
21
|
*/
|
|
22
22
|
const CRITERIAS: Criterias = {
|
|
23
23
|
file: ['fileId', 'attributes'],
|
|
24
|
-
user: ['userId', 'avatarFileId'],
|
|
24
|
+
user: ['userId', 'avatarFileId', 'roles', 'permissions'],
|
|
25
25
|
role: ['roleId'],
|
|
26
|
-
channel: ['channelId', '
|
|
27
|
-
subChannel: ['subChannelId'],
|
|
26
|
+
channel: ['channelId', 'defaultSubChannelId'],
|
|
27
|
+
subChannel: ['subChannelId', 'latestMessageId'],
|
|
28
28
|
channelUsers: ['channelId', 'userId', 'membership'],
|
|
29
29
|
message: ['messageId'],
|
|
30
30
|
community: ['communityId', 'postSetting'],
|
|
@@ -33,7 +33,8 @@ const CRITERIAS: Criterias = {
|
|
|
33
33
|
post: ['postId', 'feedId'],
|
|
34
34
|
comment: ['commentId', 'referenceId'],
|
|
35
35
|
poll: ['pollId'],
|
|
36
|
-
reaction: ['
|
|
36
|
+
reaction: ['referenceId', 'referenceType', 'reactors'],
|
|
37
|
+
reactor: ['reactionId'],
|
|
37
38
|
stream: ['streamId'],
|
|
38
39
|
follow: ['from', 'to'],
|
|
39
40
|
feed: ['feedId', 'feedType'],
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { liveObject } from '~/utils/liveObject';
|
|
2
|
+
import { getPoll as _getPoll } from '../api/getPoll';
|
|
3
|
+
import { onPollDeleted, onPollUpdated } from '../events';
|
|
4
|
+
|
|
5
|
+
/* begin_public_function
|
|
6
|
+
id: poll.get
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* ```js
|
|
10
|
+
* import { PollRepository } from '@amityco/ts-sdk';
|
|
11
|
+
*
|
|
12
|
+
* let poll;
|
|
13
|
+
*
|
|
14
|
+
* const unsub = PollRepository.getPoll(commentId, response => {
|
|
15
|
+
* poll = response.data;
|
|
16
|
+
* });
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* Observe all mutation on a given {@link Amity.Poll}
|
|
20
|
+
*
|
|
21
|
+
* @param pollId the ID of the poll to observe
|
|
22
|
+
* @param callback the function to call when new data are available
|
|
23
|
+
* @returns An {@link Amity.Unsubscriber} function to run when willing to stop observing the poll
|
|
24
|
+
*
|
|
25
|
+
* @category Poll Live Object
|
|
26
|
+
*/
|
|
27
|
+
export const getPoll = (
|
|
28
|
+
pollId: Amity.Poll['pollId'],
|
|
29
|
+
callback: Amity.LiveObjectCallback<Amity.Poll>,
|
|
30
|
+
): Amity.Unsubscriber => {
|
|
31
|
+
return liveObject(pollId, callback, 'pollId', _getPoll, [onPollUpdated, onPollDeleted]);
|
|
32
|
+
};
|
|
33
|
+
/* end_public_function */
|
|
@@ -2,7 +2,7 @@ import { getActiveClient } from '~/client/api';
|
|
|
2
2
|
|
|
3
3
|
import { createQuery, runQuery, queryOptions } from '~/core/query';
|
|
4
4
|
|
|
5
|
-
import { getPoll } from '../api';
|
|
5
|
+
import { getPoll as _getPoll } from '../api/getPoll';
|
|
6
6
|
|
|
7
7
|
import { onPollUpdated, onPollDeleted } from '../events';
|
|
8
8
|
|
|
@@ -55,7 +55,7 @@ export const observePoll = <Events extends ['onFetch', 'onUpdate', 'onDelete']>(
|
|
|
55
55
|
);
|
|
56
56
|
|
|
57
57
|
runQuery(
|
|
58
|
-
createQuery(
|
|
58
|
+
createQuery(_getPoll, pollId),
|
|
59
59
|
result => (result.data || result.error) && router(result, 'onFetch'),
|
|
60
60
|
queryOptions(policy),
|
|
61
61
|
);
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { onPostReactionAdded } from '../onPostReactionAdded';
|
|
2
1
|
import {
|
|
3
2
|
client,
|
|
4
3
|
connectClient,
|
|
5
4
|
disconnectClient,
|
|
6
5
|
postPayload,
|
|
7
6
|
post11,
|
|
8
|
-
|
|
7
|
+
reactor11,
|
|
9
8
|
} from '~/utils/tests';
|
|
10
9
|
|
|
10
|
+
import { onPostReactionAdded } from '../onPostReactionAdded';
|
|
11
|
+
|
|
11
12
|
describe('onPostReactionAdded', () => {
|
|
12
13
|
beforeAll(async () => {
|
|
13
14
|
await connectClient();
|
|
@@ -20,12 +21,12 @@ describe('onPostReactionAdded', () => {
|
|
|
20
21
|
test('it should got event after add reaction to post', () => {
|
|
21
22
|
const callback = jest.fn();
|
|
22
23
|
const unsub = onPostReactionAdded(callback);
|
|
23
|
-
client.emitter.emit('post.addReaction', { ...postPayload, reactor:
|
|
24
|
+
client.emitter.emit('post.addReaction', { ...postPayload, reactor: reactor11 });
|
|
24
25
|
|
|
25
26
|
unsub();
|
|
26
27
|
|
|
27
28
|
expect(callback).toHaveBeenCalled();
|
|
28
|
-
expect(callback).toHaveBeenCalledWith({ ...post11, myReactions: [
|
|
29
|
+
expect(callback).toHaveBeenCalledWith({ ...post11, myReactions: [reactor11.reactionName] });
|
|
29
30
|
});
|
|
30
31
|
|
|
31
32
|
test('it should got nothing if we did unsubscribe before got event', () => {
|
|
@@ -34,7 +35,7 @@ describe('onPostReactionAdded', () => {
|
|
|
34
35
|
|
|
35
36
|
unsub();
|
|
36
37
|
|
|
37
|
-
client.emitter.emit('post.addReaction', { ...postPayload, reactor:
|
|
38
|
+
client.emitter.emit('post.addReaction', { ...postPayload, reactor: reactor11 });
|
|
38
39
|
expect(callback).not.toHaveBeenCalled();
|
|
39
40
|
});
|
|
40
41
|
});
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { onPostReactionRemoved } from '../onPostReactionRemoved';
|
|
2
1
|
import {
|
|
3
2
|
client,
|
|
4
3
|
connectClient,
|
|
5
4
|
disconnectClient,
|
|
6
5
|
postPayload,
|
|
7
6
|
post11,
|
|
8
|
-
|
|
7
|
+
reactor11,
|
|
9
8
|
} from '~/utils/tests';
|
|
10
9
|
|
|
10
|
+
import { onPostReactionRemoved } from '../onPostReactionRemoved';
|
|
11
|
+
|
|
11
12
|
describe('onPostReactionRemoved', () => {
|
|
12
13
|
beforeAll(async () => {
|
|
13
14
|
await connectClient();
|
|
@@ -20,7 +21,7 @@ describe('onPostReactionRemoved', () => {
|
|
|
20
21
|
test('it should got event after reaction got removed from post', () => {
|
|
21
22
|
const callback = jest.fn();
|
|
22
23
|
const unsub = onPostReactionRemoved(callback);
|
|
23
|
-
client.emitter.emit('post.removeReaction', { ...postPayload, reactor:
|
|
24
|
+
client.emitter.emit('post.removeReaction', { ...postPayload, reactor: reactor11 });
|
|
24
25
|
|
|
25
26
|
unsub();
|
|
26
27
|
|
|
@@ -34,7 +35,7 @@ describe('onPostReactionRemoved', () => {
|
|
|
34
35
|
|
|
35
36
|
unsub();
|
|
36
37
|
|
|
37
|
-
client.emitter.emit('post.removeReaction', { ...postPayload, reactor:
|
|
38
|
+
client.emitter.emit('post.removeReaction', { ...postPayload, reactor: reactor11 });
|
|
38
39
|
expect(callback).not.toHaveBeenCalled();
|
|
39
40
|
});
|
|
40
41
|
});
|
|
@@ -16,11 +16,11 @@ import {
|
|
|
16
16
|
*/
|
|
17
17
|
/**
|
|
18
18
|
* ```js
|
|
19
|
-
* import {
|
|
19
|
+
* import { PostRepository } from '@amityco/ts-sdk';
|
|
20
20
|
*
|
|
21
21
|
* let post;
|
|
22
22
|
*
|
|
23
|
-
* const
|
|
23
|
+
* const unsub = PostRepository.getPost(postId, response => {
|
|
24
24
|
* post = response.data;
|
|
25
25
|
* });
|
|
26
26
|
* ```
|
|
@@ -76,12 +76,10 @@ describe('getPost', () => {
|
|
|
76
76
|
data: { text: 'new-text' },
|
|
77
77
|
updatedAt: getFutureDate(post.updatedAt),
|
|
78
78
|
};
|
|
79
|
-
const reactor: Amity.
|
|
79
|
+
const reactor: Amity.Reactor = {
|
|
80
80
|
createdAt: getFutureDate(post.updatedAt),
|
|
81
81
|
reactionId: 'like',
|
|
82
82
|
reactionName: 'like',
|
|
83
|
-
referenceId: post.postId,
|
|
84
|
-
referenceType: 'post',
|
|
85
83
|
userId: user12.userId,
|
|
86
84
|
};
|
|
87
85
|
const callback = jest.fn();
|