@amityco/ts-sdk 0.0.1-beta.28 → 0.0.1-beta.29
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/payload.d.ts +3 -3
- package/dist/@types/core/payload.d.ts.map +1 -1
- package/dist/@types/domains/channel.d.ts +12 -0
- package/dist/@types/domains/channel.d.ts.map +1 -1
- package/dist/@types/domains/community.d.ts +24 -2
- package/dist/@types/domains/community.d.ts.map +1 -1
- package/dist/@types/domains/content.d.ts +2 -1
- package/dist/@types/domains/content.d.ts.map +1 -1
- package/dist/@types/index.d.ts +1 -1
- package/dist/@types/index.d.ts.map +1 -1
- package/dist/channel/api/queryChannels.d.ts +1 -10
- package/dist/channel/api/queryChannels.d.ts.map +1 -1
- package/dist/channel/observers/index.d.ts +1 -0
- package/dist/channel/observers/index.d.ts.map +1 -1
- package/dist/channel/observers/liveChannels.d.ts +20 -0
- package/dist/channel/observers/liveChannels.d.ts.map +1 -0
- package/dist/channel/observers/tests/liveChannels.test.d.ts +2 -0
- package/dist/channel/observers/tests/liveChannels.test.d.ts.map +1 -0
- package/dist/community/api/createCommunity.d.ts +1 -1
- package/dist/community/api/createCommunity.d.ts.map +1 -1
- package/dist/community/api/getCommunities.d.ts.map +1 -1
- package/dist/community/api/getCommunity.d.ts.map +1 -1
- package/dist/community/api/getRecommendedCommunities.d.ts.map +1 -1
- package/dist/community/api/getTopTrendingCommunities.d.ts.map +1 -1
- package/dist/community/api/queryCommunities.d.ts.map +1 -1
- package/dist/community/api/updateCommunity.d.ts +1 -1
- package/dist/community/api/updateCommunity.d.ts.map +1 -1
- package/dist/community/events/utils.d.ts.map +1 -1
- package/dist/community/utils/index.d.ts +2 -0
- package/dist/community/utils/index.d.ts.map +1 -0
- package/dist/community/utils/payload.d.ts +11 -0
- package/dist/community/utils/payload.d.ts.map +1 -0
- package/dist/follow/tests/observers/liveFollowers.test.d.ts +2 -0
- package/dist/follow/tests/observers/liveFollowers.test.d.ts.map +1 -0
- package/dist/follow/tests/observers/liveFollowings.test.d.ts +2 -0
- package/dist/follow/tests/observers/liveFollowings.test.d.ts.map +1 -0
- package/dist/index.cjs.js +201 -20
- package/dist/index.esm.js +198 -21
- package/dist/index.umd.js +4 -4
- package/dist/utils/tests/dummy/channel.d.ts +25 -2
- package/dist/utils/tests/dummy/channel.d.ts.map +1 -1
- package/dist/utils/tests/dummy/follow.d.ts +12 -0
- package/dist/utils/tests/dummy/follow.d.ts.map +1 -0
- package/dist/utils/tests/dummy/index.d.ts +1 -0
- package/dist/utils/tests/dummy/index.d.ts.map +1 -1
- package/dist/utils/tests/dummy/user.d.ts +3 -0
- package/dist/utils/tests/dummy/user.d.ts.map +1 -1
- package/dist/utils/tests/index.d.ts +1 -0
- package/dist/utils/tests/index.d.ts.map +1 -1
- package/dist/utils/tests/utils.d.ts +2 -0
- package/dist/utils/tests/utils.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/@types/core/payload.ts +3 -3
- package/src/@types/domains/channel.ts +18 -0
- package/src/@types/domains/community.ts +27 -2
- package/src/@types/domains/content.ts +2 -1
- package/src/@types/index.ts +1 -1
- package/src/channel/api/queryChannels.ts +3 -10
- package/src/channel/observers/index.ts +1 -0
- package/src/channel/observers/liveChannels.ts +178 -0
- package/src/channel/observers/tests/liveChannels.test.ts +173 -0
- package/src/community/api/createCommunity.ts +9 -3
- package/src/community/api/getCommunities.ts +10 -3
- package/src/community/api/getCommunity.ts +5 -1
- package/src/community/api/getRecommendedCommunities.ts +5 -2
- package/src/community/api/getTopTrendingCommunities.ts +4 -1
- package/src/community/api/queryCommunities.ts +5 -2
- package/src/community/api/updateCommunity.ts +7 -3
- package/src/community/events/utils.ts +13 -7
- package/src/community/utils/index.ts +1 -0
- package/src/community/utils/payload.ts +44 -0
- package/src/core/model/identifyModel.ts +1 -1
- package/src/follow/observers/liveFollowers.ts +1 -1
- package/src/follow/observers/liveFollowings.ts +1 -1
- package/src/follow/tests/observers/liveFollowers.test.ts +240 -0
- package/src/follow/tests/observers/liveFollowings.test.ts +239 -0
- package/src/message/observers/tests/liveMessages.test.ts +202 -22
- package/src/utils/tests/dummy/channel.ts +48 -4
- package/src/utils/tests/dummy/follow.ts +60 -0
- package/src/utils/tests/dummy/index.ts +1 -0
- package/src/utils/tests/dummy/user.ts +15 -0
- package/src/utils/tests/index.ts +1 -0
- package/src/utils/tests/utils.ts +3 -0
|
@@ -1,10 +1,33 @@
|
|
|
1
1
|
export declare const channelRaw1: Amity.ChannelRaw;
|
|
2
2
|
export declare const channelRaw2: Amity.ChannelRaw;
|
|
3
|
+
export declare const channelRaw3: Amity.ChannelRaw;
|
|
3
4
|
export declare const channel11: Amity.Channel;
|
|
4
5
|
export declare const channel12: Amity.Channel;
|
|
6
|
+
export declare const channel21: Amity.Channel;
|
|
5
7
|
export declare const channelUser1: Amity.Membership<'channel'>;
|
|
6
8
|
export declare const channelUser2: Amity.Membership<'channel'>;
|
|
7
|
-
export declare const
|
|
8
|
-
|
|
9
|
+
export declare const channelQueryResponse: {
|
|
10
|
+
data: {
|
|
11
|
+
channels: Amity.Channel<any>[];
|
|
12
|
+
channelUsers: never[];
|
|
13
|
+
files: never[];
|
|
14
|
+
users: never[];
|
|
15
|
+
paging: {
|
|
16
|
+
previous: string;
|
|
17
|
+
next: string;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
export declare const channelQueryResponsePage2: {
|
|
22
|
+
data: {
|
|
23
|
+
channels: Amity.Channel<any>[];
|
|
24
|
+
channelUsers: never[];
|
|
25
|
+
files: never[];
|
|
26
|
+
users: never[];
|
|
27
|
+
paging: {
|
|
28
|
+
previous: string;
|
|
29
|
+
next: string;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
9
32
|
};
|
|
10
33
|
//# sourceMappingURL=channel.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../../../src/utils/tests/dummy/channel.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,UAK/B,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,UAK/B,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../../../src/utils/tests/dummy/channel.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,UAK/B,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,UAK/B,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,UAK/B,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,OAO7B,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,OAO7B,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,OAO7B,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,UAAU,CAAC,SAAS,CAYpD,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,UAAU,CAAC,SAAS,CAKpD,CAAC;AAEF,eAAO,MAAM,oBAAoB;;;;;;;;;;;CAWhC,CAAC;AAEF,eAAO,MAAM,yBAAyB;;;;;;;;;;;CAWrC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const follow11: Amity.FollowStatus;
|
|
2
|
+
export declare const follow12: Amity.FollowStatus;
|
|
3
|
+
export declare const follow13: Amity.FollowStatus;
|
|
4
|
+
export declare const follow21: Amity.FollowStatus;
|
|
5
|
+
export declare const follow22: Amity.FollowStatus;
|
|
6
|
+
export declare const follow23: Amity.FollowStatus;
|
|
7
|
+
export declare const follows: {
|
|
8
|
+
userId: string;
|
|
9
|
+
page1: Amity.FollowStatus[];
|
|
10
|
+
page2: Amity.FollowStatus[];
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=follow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"follow.d.ts","sourceRoot":"","sources":["../../../../src/utils/tests/dummy/follow.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,YAK5B,CAAC;AAGF,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,YAK5B,CAAC;AAGF,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,YAK5B,CAAC;AAGF,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,YAK5B,CAAC;AAGF,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,YAK5B,CAAC;AAGF,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,YAK5B,CAAC;AAEF,eAAO,MAAM,OAAO;;;;CAInB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/utils/tests/dummy/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,IAAI,QAA2B,CAAC;AAC7C,eAAO,MAAM,mBAAmB;;;CAAiC,CAAC;AAElE,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/utils/tests/dummy/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,IAAI,QAA2B,CAAC;AAC7C,eAAO,MAAM,mBAAmB;;;CAAiC,CAAC;AAElE,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../../../../src/utils/tests/dummy/user.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,MAAM,EAAE,KAAK,CAAC,IAQ1B,CAAC"}
|
|
1
|
+
{"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../../../../src/utils/tests/dummy/user.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,MAAM,EAAE,KAAK,CAAC,IAQ1B,CAAC;AAEF,eAAO,MAAM,MAAM,EAAE,KAAK,CAAC,IAG1B,CAAC;AAEF,eAAO,MAAM,MAAM,EAAE,KAAK,CAAC,IAG1B,CAAC;AAEF,eAAO,MAAM,MAAM,EAAE,KAAK,CAAC,IAG1B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/tests/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/tests/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/utils/tests/utils.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,UAAU,UAAW,OAAO,MAAM,EAAE,GAAG,CAAC,WAAkC,CAAC"}
|
package/package.json
CHANGED
|
@@ -65,7 +65,7 @@ declare global {
|
|
|
65
65
|
};
|
|
66
66
|
|
|
67
67
|
type CommunityPayload = {
|
|
68
|
-
communities: Amity.
|
|
68
|
+
communities: Amity.RawCommunity[];
|
|
69
69
|
communityUsers?: Amity.Membership<'community'>[];
|
|
70
70
|
categories?: Amity.Category[];
|
|
71
71
|
feeds?: Amity.Feed[];
|
|
@@ -79,7 +79,7 @@ declare global {
|
|
|
79
79
|
};
|
|
80
80
|
|
|
81
81
|
type CommunityMembershipPayload = {
|
|
82
|
-
communities: Amity.
|
|
82
|
+
communities: Amity.RawCommunity[];
|
|
83
83
|
communityUsers: Amity.Membership<'community'>[];
|
|
84
84
|
categories?: Amity.Category[];
|
|
85
85
|
feeds?: Amity.Feed[];
|
|
@@ -90,7 +90,7 @@ declare global {
|
|
|
90
90
|
type PostPayload<T extends Amity.PostContentType = any> = {
|
|
91
91
|
posts: Amity.Post<T>[];
|
|
92
92
|
postChildren?: Amity.Post[];
|
|
93
|
-
communities?: Amity.
|
|
93
|
+
communities?: Amity.RawCommunity[];
|
|
94
94
|
communityUsers?: Amity.Membership<'community'>[];
|
|
95
95
|
categories?: Amity.Category[];
|
|
96
96
|
comments?: Amity.Comment[];
|
|
@@ -46,5 +46,23 @@ declare global {
|
|
|
46
46
|
Amity.SoftDelete;
|
|
47
47
|
|
|
48
48
|
type ChannelRaw<T extends ChannelType = any> = Omit<Channel<T>, 'unreadCount' | 'hasMention'>;
|
|
49
|
+
|
|
50
|
+
type QueryChannels = {
|
|
51
|
+
displayName?: string;
|
|
52
|
+
membership?: 'all' | 'member' | 'notMember';
|
|
53
|
+
sortBy?: 'displayName' | 'firstCreated' | 'lastCreated';
|
|
54
|
+
types?: Amity.ChannelType[];
|
|
55
|
+
isDeleted?: Amity.Channel['isDeleted'];
|
|
56
|
+
tags?: Amity.Taggable['tags'];
|
|
57
|
+
excludeTags?: Amity.Taggable['tags'];
|
|
58
|
+
page?: Amity.Page;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
type ChannelLiveCollection = Amity.LiveCollectionParams<Omit<QueryChannels, 'page'>>;
|
|
62
|
+
|
|
63
|
+
type ChannelLiveCollectionCache = Amity.LiveCollectionCache<
|
|
64
|
+
Amity.Channel['channelId'],
|
|
65
|
+
Pick<QueryChannels, 'page'>
|
|
66
|
+
>;
|
|
49
67
|
}
|
|
50
68
|
}
|
|
@@ -1,8 +1,29 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export const CommunityPostSettings = Object.freeze({
|
|
2
|
+
ONLY_ADMIN_CAN_POST: 'ONLY_ADMIN_CAN_POST',
|
|
3
|
+
ADMIN_REVIEW_POST_REQUIRED: 'ADMIN_REVIEW_POST_REQUIRED',
|
|
4
|
+
ANYONE_CAN_POST: 'ANYONE_CAN_POST',
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
export const CommunityPostSettingMaps = Object.freeze({
|
|
8
|
+
ONLY_ADMIN_CAN_POST: {
|
|
9
|
+
needApprovalOnPostCreation: false,
|
|
10
|
+
onlyAdminCanPost: true,
|
|
11
|
+
},
|
|
12
|
+
ADMIN_REVIEW_POST_REQUIRED: {
|
|
13
|
+
needApprovalOnPostCreation: true,
|
|
14
|
+
onlyAdminCanPost: false,
|
|
15
|
+
},
|
|
16
|
+
ANYONE_CAN_POST: {
|
|
17
|
+
needApprovalOnPostCreation: false,
|
|
18
|
+
onlyAdminCanPost: false,
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export const DefaultCommunityPostSetting = 'ONLY_ADMIN_CAN_POST';
|
|
2
23
|
|
|
3
24
|
declare global {
|
|
4
25
|
namespace Amity {
|
|
5
|
-
type
|
|
26
|
+
type RawCommunity = {
|
|
6
27
|
communityId: string;
|
|
7
28
|
|
|
8
29
|
displayName: string;
|
|
@@ -30,5 +51,9 @@ declare global {
|
|
|
30
51
|
Amity.Timestamps &
|
|
31
52
|
Amity.SoftDelete &
|
|
32
53
|
Amity.Subscribable;
|
|
54
|
+
|
|
55
|
+
type Community = Omit<Amity.RawCommunity, 'onlyAdminCanPost' | 'needApprovalOnPostCreation'> & {
|
|
56
|
+
postSetting?: ValueOf<typeof CommunityPostSettings>;
|
|
57
|
+
};
|
|
33
58
|
}
|
|
34
59
|
}
|
package/src/@types/index.ts
CHANGED
|
@@ -23,7 +23,6 @@ import './domains/group';
|
|
|
23
23
|
import './domains/channel';
|
|
24
24
|
import './domains/message';
|
|
25
25
|
|
|
26
|
-
import './domains/community';
|
|
27
26
|
import './domains/category';
|
|
28
27
|
import './domains/post';
|
|
29
28
|
import './domains/comment';
|
|
@@ -34,5 +33,6 @@ import './domains/mention';
|
|
|
34
33
|
|
|
35
34
|
import './domains/poll';
|
|
36
35
|
|
|
36
|
+
export * from './domains/community';
|
|
37
37
|
export * from './domains/content';
|
|
38
38
|
export * from './domains/file';
|
|
@@ -22,16 +22,9 @@ import { prepareChannelPayload } from '../utils';
|
|
|
22
22
|
* @category Channel API
|
|
23
23
|
* @async
|
|
24
24
|
*/
|
|
25
|
-
export const queryChannels = async (
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
sortBy?: 'displayName' | 'firstCreated' | 'lastCreated';
|
|
29
|
-
types?: Amity.ChannelType;
|
|
30
|
-
isDeleted?: Amity.Channel['isDeleted'];
|
|
31
|
-
tags?: Amity.Taggable['tags'];
|
|
32
|
-
excludeTags?: Amity.Taggable['tags'];
|
|
33
|
-
page?: Amity.Page;
|
|
34
|
-
}): Promise<Amity.Cached<Amity.Paged<Amity.Channel>>> => {
|
|
25
|
+
export const queryChannels = async (
|
|
26
|
+
query?: Amity.QueryChannels,
|
|
27
|
+
): Promise<Amity.Cached<Amity.Paged<Amity.Channel>>> => {
|
|
35
28
|
const client = getActiveClient();
|
|
36
29
|
client.log('channel/queryChannels', query);
|
|
37
30
|
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/* eslint-disable no-use-before-define */
|
|
2
|
+
import { getResolver } from '~/core/model';
|
|
3
|
+
import { pullFromCache, pushToCache } from '~/cache/api';
|
|
4
|
+
import { getActiveClient } from '~/client/api';
|
|
5
|
+
import {
|
|
6
|
+
createQuery,
|
|
7
|
+
runQuery,
|
|
8
|
+
queryOptions,
|
|
9
|
+
filterByPropEquality,
|
|
10
|
+
sortByLastCreated,
|
|
11
|
+
sortByDisplayName,
|
|
12
|
+
sortByFirstCreated,
|
|
13
|
+
} from '~/core/query';
|
|
14
|
+
import { onChannelCreated, onChannelDeleted, onChannelUpdated } from '../events';
|
|
15
|
+
import { queryChannels } from '../api';
|
|
16
|
+
|
|
17
|
+
import {
|
|
18
|
+
COLLECTION_DEFAULT_CACHING_POLICY,
|
|
19
|
+
COLLECTION_DEFAULT_PAGINATION_LIMIT,
|
|
20
|
+
ENABLE_CACHE_MESSAGE,
|
|
21
|
+
} from '~/utils/constants';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* ```js
|
|
25
|
+
* import { liveChannels } from '@amityco/ts-sdk'
|
|
26
|
+
*
|
|
27
|
+
* let channels = []
|
|
28
|
+
* const unsub = liveChannels({
|
|
29
|
+
* displayName: Amity.Channel['displayName'],
|
|
30
|
+
* }, response => merge(channels, response.data))
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* Observe all mutations on a list of {@link Amity.Channel}s
|
|
34
|
+
*
|
|
35
|
+
* @param params for querying channels
|
|
36
|
+
* @param callback the function to call when new data are available
|
|
37
|
+
* @returns An {@link Amity.Unsubscriber} function to run when willing to stop observing the channels
|
|
38
|
+
*
|
|
39
|
+
* @category Channel Live Collection
|
|
40
|
+
*/
|
|
41
|
+
export const liveChannels = (
|
|
42
|
+
params: Amity.ChannelLiveCollection,
|
|
43
|
+
callback: Amity.LiveCollectionCallback<Amity.Channel>,
|
|
44
|
+
config?: Amity.LiveCollectionConfig,
|
|
45
|
+
) => {
|
|
46
|
+
const { log, cache } = getActiveClient();
|
|
47
|
+
|
|
48
|
+
if (!cache) {
|
|
49
|
+
console.log(ENABLE_CACHE_MESSAGE);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const timestamp = Date.now();
|
|
53
|
+
log(`liveChannels(tmpid: ${timestamp}) > listen`);
|
|
54
|
+
|
|
55
|
+
const { limit: queryLimit, ...queryParams } = params;
|
|
56
|
+
|
|
57
|
+
const limit = queryLimit ?? COLLECTION_DEFAULT_PAGINATION_LIMIT;
|
|
58
|
+
const { policy = COLLECTION_DEFAULT_CACHING_POLICY } = config ?? {};
|
|
59
|
+
|
|
60
|
+
const disposers: Amity.Unsubscriber[] = [];
|
|
61
|
+
const cacheKey = ['channel', 'collection', {}];
|
|
62
|
+
|
|
63
|
+
const responder = (data: Amity.ChannelLiveCollectionCache) => {
|
|
64
|
+
let channels: Amity.Channel[] =
|
|
65
|
+
data.data
|
|
66
|
+
.map(channelId => pullFromCache<Amity.Channel>(['channel', 'get', channelId])!)
|
|
67
|
+
.filter(Boolean)
|
|
68
|
+
.map(({ data }) => data) ?? [];
|
|
69
|
+
|
|
70
|
+
channels = filterByPropEquality(channels, 'isDeleted', params.isDeleted);
|
|
71
|
+
channels = filterByPropEquality(channels, 'displayName', params.displayName);
|
|
72
|
+
|
|
73
|
+
if (params.types) {
|
|
74
|
+
channels = channels.filter(c => params.types?.includes(c.type));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (params.tags) {
|
|
78
|
+
channels = channels.filter(c => c.tags?.some(t => params.tags?.includes(t)));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (params.excludeTags) {
|
|
82
|
+
channels = channels.filter(c => !c.tags?.some(t => params.excludeTags?.includes(t)));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const sortBy = params.sortBy || 'lastCreated';
|
|
86
|
+
|
|
87
|
+
if (sortBy === 'lastCreated' || sortBy === 'firstCreated') {
|
|
88
|
+
channels = channels.sort(sortBy === 'lastCreated' ? sortByLastCreated : sortByFirstCreated);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/*
|
|
92
|
+
* The server returns channels with empty | null displayName's first before
|
|
93
|
+
* returning sorted list of channels with displayNames
|
|
94
|
+
*
|
|
95
|
+
* This section needs to be updated as displayNames can be null as well
|
|
96
|
+
*/
|
|
97
|
+
if (sortBy === 'displayName') {
|
|
98
|
+
channels = channels
|
|
99
|
+
// this needs to be aligned with the backend data type
|
|
100
|
+
.map(c => (c.displayName ? c : { ...c, displayName: '' }))
|
|
101
|
+
// @ts-ignore
|
|
102
|
+
.sort(sortByDisplayName);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
callback({
|
|
106
|
+
onNextPage: onFetch,
|
|
107
|
+
data: channels,
|
|
108
|
+
hasNextPage: !!data.params?.page,
|
|
109
|
+
loading: data.loading,
|
|
110
|
+
error: data.error,
|
|
111
|
+
});
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const realtimeRouter = (channel: Amity.Channel, action: Amity.ChannelActionType) => {
|
|
115
|
+
const collection = pullFromCache<Amity.ChannelLiveCollectionCache>(cacheKey)?.data;
|
|
116
|
+
if (!collection) return;
|
|
117
|
+
|
|
118
|
+
if (action === 'onCreate') {
|
|
119
|
+
collection.data = [...new Set([channel.channelId, ...collection.data])];
|
|
120
|
+
/*
|
|
121
|
+
* if the filter isDeleted is set, only collection item must be updated and not
|
|
122
|
+
* the collection
|
|
123
|
+
*/
|
|
124
|
+
} else if (action === 'onDelete' && !params.isDeleted) {
|
|
125
|
+
collection.data = collection.data.filter(c => c !== channel.channelId);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
pushToCache(cacheKey, collection);
|
|
129
|
+
responder(collection);
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const onFetch = () => {
|
|
133
|
+
const collection = pullFromCache<Amity.ChannelLiveCollectionCache>(cacheKey)?.data;
|
|
134
|
+
|
|
135
|
+
const channels = collection?.data ?? [];
|
|
136
|
+
|
|
137
|
+
if (channels.length > 0 && !collection?.params.page) return;
|
|
138
|
+
|
|
139
|
+
const query = createQuery(queryChannels, {
|
|
140
|
+
...queryParams,
|
|
141
|
+
page: collection?.params.page ?? { limit },
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
runQuery(
|
|
145
|
+
query,
|
|
146
|
+
({ data: result, error, loading, nextPage: page }) => {
|
|
147
|
+
const data = {
|
|
148
|
+
loading,
|
|
149
|
+
error,
|
|
150
|
+
params: { page },
|
|
151
|
+
data: channels,
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
if (result) {
|
|
155
|
+
data.data = [...new Set([...channels, ...result.map(getResolver('channel'))])];
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
pushToCache(cacheKey, data);
|
|
159
|
+
|
|
160
|
+
responder(data);
|
|
161
|
+
},
|
|
162
|
+
queryOptions(policy),
|
|
163
|
+
);
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
disposers.push(
|
|
167
|
+
onChannelCreated(channel => realtimeRouter(channel, 'onCreate')),
|
|
168
|
+
onChannelDeleted(channel => realtimeRouter(channel, 'onDelete')),
|
|
169
|
+
onChannelUpdated(channel => realtimeRouter(channel, 'onUpdate')),
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
onFetch();
|
|
173
|
+
|
|
174
|
+
return () => {
|
|
175
|
+
log(`liveChannels(tmpid: ${timestamp}) > dispose`);
|
|
176
|
+
disposers.forEach(fn => fn());
|
|
177
|
+
};
|
|
178
|
+
};
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { disableCache, enableCache } from '~/cache/api';
|
|
2
|
+
|
|
3
|
+
import { liveChannels } from '../liveChannels';
|
|
4
|
+
import { queryChannels } from '~/channel/api';
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
client,
|
|
8
|
+
connectClient,
|
|
9
|
+
disconnectClient,
|
|
10
|
+
channel11,
|
|
11
|
+
channel12,
|
|
12
|
+
channelUser1,
|
|
13
|
+
channelQueryResponse,
|
|
14
|
+
channelQueryResponsePage2,
|
|
15
|
+
} from '~/utils/tests';
|
|
16
|
+
|
|
17
|
+
const getSnapshot = () => {
|
|
18
|
+
return {
|
|
19
|
+
data: [] as Amity.Channel[],
|
|
20
|
+
loading: true,
|
|
21
|
+
error: undefined as any,
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
describe('liveChannels', () => {
|
|
26
|
+
beforeAll(async () => {
|
|
27
|
+
await connectClient();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
afterAll(async () => {
|
|
31
|
+
await disconnectClient();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
beforeEach(enableCache);
|
|
35
|
+
|
|
36
|
+
afterEach(disableCache);
|
|
37
|
+
|
|
38
|
+
test('it should return channel collection', async () => {
|
|
39
|
+
// mock response of queryChannels and validate
|
|
40
|
+
const callback = jest.fn();
|
|
41
|
+
client.http.get = jest.fn().mockResolvedValue(channelQueryResponse);
|
|
42
|
+
|
|
43
|
+
liveChannels({}, callback);
|
|
44
|
+
|
|
45
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
46
|
+
|
|
47
|
+
const snapshot = getSnapshot();
|
|
48
|
+
|
|
49
|
+
// check if cache data returned (should be empty)
|
|
50
|
+
expect(callback).toHaveBeenCalledWith(expect.objectContaining(snapshot));
|
|
51
|
+
|
|
52
|
+
await expect(queryChannels()).resolves.toBeTruthy();
|
|
53
|
+
|
|
54
|
+
expect(callback).toHaveBeenCalledTimes(2);
|
|
55
|
+
|
|
56
|
+
snapshot.data = channelQueryResponse.data.channels;
|
|
57
|
+
snapshot.loading = false;
|
|
58
|
+
|
|
59
|
+
expect(callback).toHaveBeenCalledWith(expect.objectContaining(snapshot));
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// table for channel filters
|
|
63
|
+
const filters: [string, Amity.ChannelLiveCollection][] = [
|
|
64
|
+
['deleted', { isDeleted: false }],
|
|
65
|
+
['tagged', { tags: ['tag2'] }],
|
|
66
|
+
['out excluded tags', { excludeTags: ['tag1'] }],
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
test.each(filters)('it should filter %s channels', async (filter, params) => {
|
|
70
|
+
const callback = jest.fn();
|
|
71
|
+
client.http.get = jest.fn().mockResolvedValue(channelQueryResponse);
|
|
72
|
+
|
|
73
|
+
liveChannels(params, callback);
|
|
74
|
+
|
|
75
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
76
|
+
|
|
77
|
+
const snapshot = getSnapshot();
|
|
78
|
+
// check if cache data returned (should be empty)
|
|
79
|
+
expect(callback).toHaveBeenCalledWith(expect.objectContaining(snapshot));
|
|
80
|
+
|
|
81
|
+
await expect(queryChannels()).resolves.toBeTruthy();
|
|
82
|
+
|
|
83
|
+
expect(callback).toHaveBeenCalledTimes(2);
|
|
84
|
+
|
|
85
|
+
snapshot.loading = false;
|
|
86
|
+
snapshot.data = [channelQueryResponse.data.channels[0]];
|
|
87
|
+
|
|
88
|
+
expect(callback).toHaveBeenCalledWith(expect.objectContaining(snapshot));
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test('it should return method to fetch next page', async () => {
|
|
92
|
+
const callback = jest.fn();
|
|
93
|
+
client.http.get = jest
|
|
94
|
+
.fn()
|
|
95
|
+
.mockResolvedValue(channelQueryResponse)
|
|
96
|
+
.mockResolvedValueOnce(channelQueryResponsePage2);
|
|
97
|
+
|
|
98
|
+
liveChannels({}, callback);
|
|
99
|
+
|
|
100
|
+
expect(callback).toHaveBeenCalled();
|
|
101
|
+
|
|
102
|
+
await expect(queryChannels()).resolves.toBeTruthy();
|
|
103
|
+
|
|
104
|
+
expect(callback.mock.lastCall).toHaveLength(1);
|
|
105
|
+
|
|
106
|
+
const { onNextPage, hasNextPage } = callback.mock.lastCall[0];
|
|
107
|
+
|
|
108
|
+
expect(hasNextPage).toBe(true);
|
|
109
|
+
expect(onNextPage).toBeTruthy();
|
|
110
|
+
|
|
111
|
+
onNextPage();
|
|
112
|
+
|
|
113
|
+
await expect(queryChannels()).resolves.toBeTruthy();
|
|
114
|
+
|
|
115
|
+
// 4 -> becuase 1 local & server call each per call (2)
|
|
116
|
+
expect(callback).toHaveBeenCalledTimes(4);
|
|
117
|
+
|
|
118
|
+
const snapshot = getSnapshot();
|
|
119
|
+
snapshot.loading = false;
|
|
120
|
+
snapshot.data = [
|
|
121
|
+
...channelQueryResponsePage2.data.channels,
|
|
122
|
+
...channelQueryResponse.data.channels,
|
|
123
|
+
];
|
|
124
|
+
|
|
125
|
+
expect(callback).toHaveBeenNthCalledWith(4, expect.objectContaining(snapshot));
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
const events: [string, keyof Amity.Events, Amity.Channel][] = [
|
|
129
|
+
[
|
|
130
|
+
'it should add new channel to collection onCreate',
|
|
131
|
+
'v3.channel.didCreate',
|
|
132
|
+
{ ...channel11, channelId: 'new-channel-id' },
|
|
133
|
+
],
|
|
134
|
+
['it should edit channel in collection onUpdate', 'v3.channel.didUpdate', channel11],
|
|
135
|
+
['it should remove channel from collection onDelete', 'v3.channel.didDelete', channel11],
|
|
136
|
+
];
|
|
137
|
+
|
|
138
|
+
test.each(events)('%s', async (test, event, channel) => {
|
|
139
|
+
const snapshot = getSnapshot();
|
|
140
|
+
|
|
141
|
+
const callback = jest.fn();
|
|
142
|
+
client.http.get = jest.fn().mockResolvedValue(channelQueryResponse);
|
|
143
|
+
|
|
144
|
+
liveChannels({}, callback);
|
|
145
|
+
|
|
146
|
+
await expect(queryChannels()).resolves.toBeTruthy();
|
|
147
|
+
expect(callback).toHaveBeenCalledTimes(2);
|
|
148
|
+
|
|
149
|
+
client.emitter.emit(event, {
|
|
150
|
+
channels: [channel],
|
|
151
|
+
channelUsers: [channelUser1],
|
|
152
|
+
users: [],
|
|
153
|
+
files: [],
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
snapshot.loading = false;
|
|
157
|
+
// get data based on event
|
|
158
|
+
switch (event) {
|
|
159
|
+
case 'v3.channel.didCreate':
|
|
160
|
+
snapshot.data = [channel, channel11, channel12];
|
|
161
|
+
break;
|
|
162
|
+
|
|
163
|
+
case 'v3.channel.didUpdate':
|
|
164
|
+
snapshot.data = channelQueryResponse.data.channels;
|
|
165
|
+
break;
|
|
166
|
+
|
|
167
|
+
default:
|
|
168
|
+
snapshot.data = [channel12];
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
expect(callback).toHaveBeenNthCalledWith(3, expect.objectContaining(snapshot));
|
|
172
|
+
});
|
|
173
|
+
});
|
|
@@ -3,6 +3,8 @@ import { getActiveClient } from '~/client/api';
|
|
|
3
3
|
import { ingestInCache } from '~/cache/api/ingestInCache';
|
|
4
4
|
import { fireEvent } from '~/core/events';
|
|
5
5
|
|
|
6
|
+
import { packCommunityPayload, unpackCommunityPayload } from '../utils';
|
|
7
|
+
|
|
6
8
|
/**
|
|
7
9
|
* ```js
|
|
8
10
|
* import { createCommunity } from '@amityco/ts-sdk'
|
|
@@ -25,8 +27,7 @@ export const createCommunity = async (
|
|
|
25
27
|
| 'description'
|
|
26
28
|
| 'isPublic'
|
|
27
29
|
| 'isOfficial'
|
|
28
|
-
| '
|
|
29
|
-
| 'needApprovalOnPostCreation'
|
|
30
|
+
| 'postSetting'
|
|
30
31
|
| 'tags'
|
|
31
32
|
| 'metadata'
|
|
32
33
|
> & {
|
|
@@ -38,7 +39,12 @@ export const createCommunity = async (
|
|
|
38
39
|
const client = getActiveClient();
|
|
39
40
|
client.log('user/createCommunity', bundle);
|
|
40
41
|
|
|
41
|
-
const { data } = await client.http.post<Amity.CommunityPayload>(
|
|
42
|
+
const { data: payload } = await client.http.post<Amity.CommunityPayload>(
|
|
43
|
+
'/api/v3/communities/',
|
|
44
|
+
packCommunityPayload(bundle),
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
const data = unpackCommunityPayload(payload);
|
|
42
48
|
|
|
43
49
|
const cachedAt = client.cache && Date.now();
|
|
44
50
|
if (client.cache) ingestInCache(data, { cachedAt });
|
|
@@ -3,6 +3,8 @@ import { getActiveClient } from '~/client/api';
|
|
|
3
3
|
import { pullFromCache } from '~/cache/api';
|
|
4
4
|
import { ingestInCache } from '~/cache/api/ingestInCache';
|
|
5
5
|
|
|
6
|
+
import { unpackCommunityPayload } from '../utils';
|
|
7
|
+
|
|
6
8
|
/**
|
|
7
9
|
* ```js
|
|
8
10
|
* import { getCommunities } from '@amityco/ts-sdk'
|
|
@@ -24,9 +26,14 @@ export const getCommunities = async (
|
|
|
24
26
|
client.log('community/getCommunities', communityIds);
|
|
25
27
|
|
|
26
28
|
// API-FIX: endpoint should not be /list, parameters should be querystring.
|
|
27
|
-
const { data } = await client.http.get<Amity.CommunityPayload>(
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
const { data: payload } = await client.http.get<Amity.CommunityPayload>(
|
|
30
|
+
`/api/v3/communities/list`,
|
|
31
|
+
{
|
|
32
|
+
params: { communityIds },
|
|
33
|
+
},
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
const data = unpackCommunityPayload(payload);
|
|
30
37
|
|
|
31
38
|
const cachedAt = client.cache && Date.now();
|
|
32
39
|
if (client.cache) ingestInCache(data, { cachedAt });
|