@amityco/ts-sdk 0.0.1-beta.30 → 0.0.1-beta.32

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.
Files changed (233) hide show
  1. package/dist/@types/core/cache.d.ts +3 -0
  2. package/dist/@types/core/cache.d.ts.map +1 -1
  3. package/dist/@types/core/errors.d.ts +2 -1
  4. package/dist/@types/core/errors.d.ts.map +1 -1
  5. package/dist/@types/core/events.d.ts +2 -0
  6. package/dist/@types/core/events.d.ts.map +1 -1
  7. package/dist/@types/core/live.d.ts +8 -4
  8. package/dist/@types/core/live.d.ts.map +1 -1
  9. package/dist/@types/core/query.d.ts +1 -1
  10. package/dist/@types/core/query.d.ts.map +1 -1
  11. package/dist/@types/domains/channel.d.ts +1 -0
  12. package/dist/@types/domains/channel.d.ts.map +1 -1
  13. package/dist/@types/domains/message.d.ts +13 -6
  14. package/dist/@types/domains/message.d.ts.map +1 -1
  15. package/dist/@types/domains/post.d.ts +10 -3
  16. package/dist/@types/domains/post.d.ts.map +1 -1
  17. package/dist/@types/domains/user.d.ts +1 -0
  18. package/dist/@types/domains/user.d.ts.map +1 -1
  19. package/dist/@types/index.d.ts +2 -2
  20. package/dist/@types/index.d.ts.map +1 -1
  21. package/dist/cache/api/backupCache.d.ts.map +1 -1
  22. package/dist/cache/api/isInTombstone.d.ts +18 -0
  23. package/dist/cache/api/isInTombstone.d.ts.map +1 -0
  24. package/dist/cache/api/pushToTombstone.d.ts +17 -0
  25. package/dist/cache/api/pushToTombstone.d.ts.map +1 -0
  26. package/dist/cache/api/tests/pushToCache.test.d.ts +2 -0
  27. package/dist/cache/api/tests/pushToCache.test.d.ts.map +1 -0
  28. package/dist/cache/utils/index.d.ts +17 -0
  29. package/dist/cache/utils/index.d.ts.map +1 -1
  30. package/dist/channel/api/addChannelMembers.d.ts.map +1 -1
  31. package/dist/channel/api/getChannel.d.ts.map +1 -1
  32. package/dist/channel/api/queryChannelMembers.d.ts +1 -1
  33. package/dist/channel/api/queryChannelMembers.d.ts.map +1 -1
  34. package/dist/channel/api/queryChannels.d.ts +1 -1
  35. package/dist/channel/api/queryChannels.d.ts.map +1 -1
  36. package/dist/channel/api/tests/addChannelMembers.test.d.ts +2 -0
  37. package/dist/channel/api/tests/addChannelMembers.test.d.ts.map +1 -0
  38. package/dist/channel/api/tests/getChannel.test.d.ts +2 -0
  39. package/dist/channel/api/tests/getChannel.test.d.ts.map +1 -0
  40. package/dist/channel/api/tests/queryChannelMembers.test.d.ts +2 -0
  41. package/dist/channel/api/tests/queryChannelMembers.test.d.ts.map +1 -0
  42. package/dist/channel/api/tests/queryChannels.test.d.ts +2 -0
  43. package/dist/channel/api/tests/queryChannels.test.d.ts.map +1 -0
  44. package/dist/channel/events/index.d.ts +2 -0
  45. package/dist/channel/events/index.d.ts.map +1 -1
  46. package/dist/channel/events/onChannelMemberAdded.d.ts.map +1 -1
  47. package/dist/channel/events/onChannelMemberBanned.d.ts +17 -0
  48. package/dist/channel/events/onChannelMemberBanned.d.ts.map +1 -0
  49. package/dist/channel/events/onChannelMemberUnbanned.d.ts +17 -0
  50. package/dist/channel/events/onChannelMemberUnbanned.d.ts.map +1 -0
  51. package/dist/channel/events/tests/onChannelMemberBanned.test.d.ts +2 -0
  52. package/dist/channel/events/tests/onChannelMemberBanned.test.d.ts.map +1 -0
  53. package/dist/channel/events/tests/onChannelMemberUnbanned.test.d.ts +2 -0
  54. package/dist/channel/events/tests/onChannelMemberUnbanned.test.d.ts.map +1 -0
  55. package/dist/channel/observers/liveChannelMembers.d.ts.map +1 -1
  56. package/dist/channel/observers/liveChannels.d.ts.map +1 -1
  57. package/dist/channel/{tests/utils → utils/tests}/prepareChannelPayload.test.d.ts +0 -0
  58. package/dist/channel/utils/tests/prepareChannelPayload.test.d.ts.map +1 -0
  59. package/dist/core/events.d.ts +3 -3
  60. package/dist/core/events.d.ts.map +1 -1
  61. package/dist/core/query/filtering.d.ts +11 -0
  62. package/dist/core/query/filtering.d.ts.map +1 -1
  63. package/dist/core/query/query.d.ts.map +1 -1
  64. package/dist/core/transports/http.d.ts +5 -0
  65. package/dist/core/transports/http.d.ts.map +1 -1
  66. package/dist/core/transports/test/http.test.d.ts +2 -0
  67. package/dist/core/transports/test/http.test.d.ts.map +1 -0
  68. package/dist/index.cjs.js +980 -534
  69. package/dist/index.esm.js +962 -526
  70. package/dist/index.umd.js +4 -4
  71. package/dist/message/api/createMessage.d.ts +4 -1
  72. package/dist/message/api/createMessage.d.ts.map +1 -1
  73. package/dist/message/api/deleteMessage.d.ts.map +1 -1
  74. package/dist/message/api/getMessage.d.ts +1 -1
  75. package/dist/message/api/getMessage.d.ts.map +1 -1
  76. package/dist/message/api/getMessages.d.ts.map +1 -1
  77. package/dist/message/api/queryMessages.d.ts.map +1 -1
  78. package/dist/message/api/tests/createMessage.test.d.ts +2 -0
  79. package/dist/message/api/tests/createMessage.test.d.ts.map +1 -0
  80. package/dist/message/api/tests/deleteMessage.test.d.ts +2 -0
  81. package/dist/message/api/tests/deleteMessage.test.d.ts.map +1 -0
  82. package/dist/message/api/tests/getMessage.test.d.ts +2 -0
  83. package/dist/message/api/tests/getMessage.test.d.ts.map +1 -0
  84. package/dist/message/api/tests/getMessages.test.d.ts +2 -0
  85. package/dist/message/api/tests/getMessages.test.d.ts.map +1 -0
  86. package/dist/message/api/tests/queryMessages.test.d.ts +2 -0
  87. package/dist/message/api/tests/queryMessages.test.d.ts.map +1 -0
  88. package/dist/message/api/tests/updateMessage.test.d.ts +2 -0
  89. package/dist/message/api/tests/updateMessage.test.d.ts.map +1 -0
  90. package/dist/message/api/updateMessage.d.ts.map +1 -1
  91. package/dist/message/events/index.d.ts +1 -0
  92. package/dist/message/events/index.d.ts.map +1 -1
  93. package/dist/message/events/onMessageFetched.d.ts +17 -0
  94. package/dist/message/events/onMessageFetched.d.ts.map +1 -0
  95. package/dist/message/observers/index.d.ts +2 -1
  96. package/dist/message/observers/index.d.ts.map +1 -1
  97. package/dist/message/observers/liveMessage.d.ts +18 -0
  98. package/dist/message/observers/liveMessage.d.ts.map +1 -0
  99. package/dist/message/observers/liveMessages.d.ts.map +1 -1
  100. package/dist/message/observers/observeMessage.d.ts.map +1 -1
  101. package/dist/message/tests/observers/liveMessage.test.d.ts +2 -0
  102. package/dist/message/tests/observers/liveMessage.test.d.ts.map +1 -0
  103. package/dist/message/{observers/tests → tests/observers}/liveMessages.test.d.ts +0 -0
  104. package/dist/message/tests/observers/liveMessages.test.d.ts.map +1 -0
  105. package/dist/post/api/deletePost.d.ts.map +1 -1
  106. package/dist/post/api/getPost.d.ts.map +1 -1
  107. package/dist/post/api/updatePost.d.ts +6 -1
  108. package/dist/post/api/updatePost.d.ts.map +1 -1
  109. package/dist/reaction/api/addReaction.d.ts.map +1 -1
  110. package/dist/reaction/api/removeReaction.d.ts.map +1 -1
  111. package/dist/reaction/api/tests/addReaction.test.d.ts +2 -0
  112. package/dist/reaction/api/tests/addReaction.test.d.ts.map +1 -0
  113. package/dist/reaction/api/tests/removeReaction.test.d.ts +2 -0
  114. package/dist/reaction/api/tests/removeReaction.test.d.ts.map +1 -0
  115. package/dist/user/api/getUser.d.ts +1 -1
  116. package/dist/user/api/getUser.d.ts.map +1 -1
  117. package/dist/user/api/getUsers.d.ts.map +1 -1
  118. package/dist/user/api/queryUsers.d.ts.map +1 -1
  119. package/dist/user/api/tests/queryUsers.test.d.ts +2 -0
  120. package/dist/user/api/tests/queryUsers.test.d.ts.map +1 -0
  121. package/dist/user/api/updateUser.d.ts.map +1 -1
  122. package/dist/user/events/index.d.ts +1 -0
  123. package/dist/user/events/index.d.ts.map +1 -1
  124. package/dist/user/events/onUserFetched.d.ts +17 -0
  125. package/dist/user/events/onUserFetched.d.ts.map +1 -0
  126. package/dist/user/observers/index.d.ts +1 -0
  127. package/dist/user/observers/index.d.ts.map +1 -1
  128. package/dist/user/observers/liveUser.d.ts +18 -0
  129. package/dist/user/observers/liveUser.d.ts.map +1 -0
  130. package/dist/user/observers/observeUser.d.ts.map +1 -1
  131. package/dist/user/tests/api/getUser.test.d.ts +2 -0
  132. package/dist/user/tests/api/getUser.test.d.ts.map +1 -0
  133. package/dist/user/tests/observers/liveUser.test.d.ts +2 -0
  134. package/dist/user/tests/observers/liveUser.test.d.ts.map +1 -0
  135. package/dist/utils/constants.d.ts +3 -0
  136. package/dist/utils/constants.d.ts.map +1 -1
  137. package/dist/utils/tests/dummy/channel.d.ts +15 -0
  138. package/dist/utils/tests/dummy/channel.d.ts.map +1 -1
  139. package/dist/utils/tests/dummy/message.d.ts +12 -1
  140. package/dist/utils/tests/dummy/message.d.ts.map +1 -1
  141. package/dist/utils/tests/dummy/post.d.ts +12 -1
  142. package/dist/utils/tests/dummy/post.d.ts.map +1 -1
  143. package/dist/utils/tests/dummy/user.d.ts +10 -0
  144. package/dist/utils/tests/dummy/user.d.ts.map +1 -1
  145. package/package.json +2 -1
  146. package/src/@types/core/cache.ts +4 -0
  147. package/src/@types/core/errors.ts +1 -0
  148. package/src/@types/core/events.ts +2 -0
  149. package/src/@types/core/live.ts +10 -4
  150. package/src/@types/core/query.ts +1 -1
  151. package/src/@types/domains/channel.ts +6 -0
  152. package/src/@types/domains/message.ts +13 -10
  153. package/src/@types/domains/post.ts +10 -3
  154. package/src/@types/domains/user.ts +8 -0
  155. package/src/@types/index.ts +2 -2
  156. package/src/cache/api/backupCache.ts +0 -1
  157. package/src/cache/api/index.ts +2 -1
  158. package/src/cache/api/isInTombstone.ts +41 -0
  159. package/src/cache/api/pushToTombstone.ts +33 -0
  160. package/src/cache/api/tests/pushToCache.test.ts +57 -0
  161. package/src/cache/utils/index.ts +22 -0
  162. package/src/channel/api/addChannelMembers.ts +9 -1
  163. package/src/channel/api/getChannel.ts +20 -5
  164. package/src/channel/api/queryChannelMembers.ts +53 -5
  165. package/src/channel/api/queryChannels.ts +31 -4
  166. package/src/channel/api/tests/addChannelMembers.test.ts +95 -0
  167. package/src/channel/api/tests/getChannel.test.ts +108 -0
  168. package/src/channel/api/tests/queryChannelMembers.test.ts +115 -0
  169. package/src/channel/api/tests/queryChannels.test.ts +121 -0
  170. package/src/channel/events/index.ts +5 -0
  171. package/src/channel/events/onChannelMemberAdded.ts +1 -1
  172. package/src/channel/events/onChannelMemberBanned.ts +36 -0
  173. package/src/channel/events/onChannelMemberUnbanned.ts +36 -0
  174. package/src/channel/events/tests/onChannelMemberBanned.test.ts +58 -0
  175. package/src/channel/events/tests/onChannelMemberUnbanned.test.ts +58 -0
  176. package/src/channel/observers/liveChannelMembers.ts +28 -4
  177. package/src/channel/observers/liveChannels.ts +7 -1
  178. package/src/channel/observers/tests/liveChannelMembers.test.ts +53 -11
  179. package/src/channel/observers/tests/liveChannels.test.ts +50 -21
  180. package/src/channel/{tests/utils → utils/tests}/prepareChannelPayload.test.ts +1 -1
  181. package/src/core/events.ts +2 -1
  182. package/src/core/query/filtering.ts +49 -0
  183. package/src/core/query/query.ts +9 -6
  184. package/src/core/tests/query/query.test.ts +12 -2
  185. package/src/core/transports/http.ts +3 -17
  186. package/src/core/transports/test/http.test.ts +83 -0
  187. package/src/message/api/createMessage.ts +15 -9
  188. package/src/message/api/deleteMessage.ts +4 -4
  189. package/src/message/api/getMessage.ts +32 -4
  190. package/src/message/api/getMessages.ts +6 -1
  191. package/src/message/api/queryMessages.ts +3 -0
  192. package/src/message/api/tests/createMessage.test.ts +99 -0
  193. package/src/message/api/tests/deleteMessage.test.ts +110 -0
  194. package/src/message/api/tests/getMessage.test.ts +121 -0
  195. package/src/message/api/tests/getMessages.test.ts +108 -0
  196. package/src/message/api/tests/queryMessages.test.ts +115 -0
  197. package/src/message/api/tests/updateMessage.test.ts +100 -0
  198. package/src/message/api/updateMessage.ts +2 -0
  199. package/src/message/events/index.ts +1 -0
  200. package/src/message/events/onMessageFetched.ts +30 -0
  201. package/src/message/observers/index.ts +2 -1
  202. package/src/message/observers/liveMessage.ts +100 -0
  203. package/src/message/observers/liveMessages.ts +3 -1
  204. package/src/message/observers/observeMessage.ts +4 -0
  205. package/src/message/tests/observers/liveMessage.test.ts +248 -0
  206. package/src/message/{observers/tests → tests/observers}/liveMessages.test.ts +29 -3
  207. package/src/post/api/deletePost.ts +4 -3
  208. package/src/post/api/getPost.ts +8 -4
  209. package/src/post/api/updatePost.ts +6 -1
  210. package/src/post/tests/api/queryPosts.test.ts +117 -18
  211. package/src/reaction/api/addReaction.ts +1 -4
  212. package/src/reaction/api/removeReaction.ts +1 -4
  213. package/src/reaction/api/tests/addReaction.test.ts +37 -0
  214. package/src/reaction/api/tests/removeReaction.test.ts +43 -0
  215. package/src/user/api/getUser.ts +32 -5
  216. package/src/user/api/getUsers.ts +3 -0
  217. package/src/user/api/queryUsers.ts +27 -5
  218. package/src/user/api/tests/queryUsers.test.ts +124 -0
  219. package/src/user/api/updateUser.ts +3 -0
  220. package/src/user/events/index.ts +1 -0
  221. package/src/user/events/onUserFetched.ts +19 -0
  222. package/src/user/observers/index.ts +1 -0
  223. package/src/user/observers/liveUser.ts +89 -0
  224. package/src/user/observers/observeUser.ts +2 -0
  225. package/src/user/tests/api/getUser.test.ts +112 -0
  226. package/src/user/tests/observers/liveUser.test.ts +224 -0
  227. package/src/utils/constants.ts +5 -0
  228. package/src/utils/tests/dummy/channel.ts +43 -0
  229. package/src/utils/tests/dummy/message.ts +16 -2
  230. package/src/utils/tests/dummy/post.ts +26 -3
  231. package/src/utils/tests/dummy/user.ts +11 -0
  232. package/dist/channel/tests/utils/prepareChannelPayload.test.d.ts.map +0 -1
  233. package/dist/message/observers/tests/liveMessages.test.d.ts.map +0 -1
@@ -0,0 +1,108 @@
1
+ import { ASCApiError } from '~/core/errors';
2
+ import { disableCache, enableCache, pushToCache } from '~/cache/api';
3
+ import { client, channelQueryResponse } from '~/utils/tests';
4
+
5
+ import { pushToTombstone } from '~/cache/api/pushToTombstone';
6
+ import { isInTombstone } from '~/cache/api/isInTombstone';
7
+
8
+ import { getChannel } from '../getChannel';
9
+
10
+ const { channelId } = channelQueryResponse.data.channels[0];
11
+ const channel = channelQueryResponse.data.channels[0];
12
+
13
+ describe('getChannel', () => {
14
+ test('it should return a channel', async () => {
15
+ client.http.get = jest.fn().mockResolvedValueOnce(channelQueryResponse);
16
+
17
+ const expected = channel;
18
+ const { data: received } = await getChannel(channelId);
19
+
20
+ expect(received).toStrictEqual(expected);
21
+ });
22
+
23
+ test('it should update cache after fetch from server', async () => {
24
+ enableCache();
25
+ client.http.get = jest.fn().mockResolvedValue(channelQueryResponse);
26
+ await getChannel(channelId);
27
+
28
+ expect(getChannel.locally(channelId)).toBeDefined();
29
+
30
+ disableCache();
31
+ });
32
+
33
+ test('it should return an error', async () => {
34
+ client.http.get = jest.fn().mockRejectedValueOnce(new Error('error'));
35
+
36
+ await expect(getChannel(channelId)).rejects.toThrow('error');
37
+ });
38
+
39
+ test('it should return an error if channel in cache but api throws not found', async () => {
40
+ enableCache();
41
+ pushToCache(['channel', 'get', channelId], channel, { cachedAt: Date.now() });
42
+
43
+ client.http.get = jest
44
+ .fn()
45
+ .mockRejectedValueOnce(
46
+ new ASCApiError('not found!', Amity.ServerError.ITEM_NOT_FOUND, Amity.ErrorLevel.ERROR),
47
+ );
48
+
49
+ await expect(getChannel(channelId)).rejects.toThrow();
50
+ expect(getChannel.locally(channelId)).toBeUndefined();
51
+
52
+ disableCache();
53
+ });
54
+ });
55
+
56
+ describe('getChannel locally', () => {
57
+ test('it should return data from cache', () => {
58
+ enableCache();
59
+
60
+ const cachedAt = Date.now();
61
+
62
+ pushToCache(['channel', 'get', channelId], channel, { cachedAt });
63
+
64
+ const data = getChannel.locally(channelId);
65
+
66
+ expect(data).toBeDefined();
67
+ expect(data?.data).toEqual(channel);
68
+ expect(data?.cachedAt).toEqual(cachedAt);
69
+
70
+ disableCache();
71
+ });
72
+
73
+ test('should return undefined if channel not in cache', () => {
74
+ expect(getChannel.locally('non-existent-channel')).toBeUndefined();
75
+ });
76
+
77
+ test('should return undefined if cache not enabled', () => {
78
+ expect(getChannel.locally(channelId)).toBeUndefined();
79
+ });
80
+ });
81
+
82
+ describe('getChannel tombostone', () => {
83
+ test('it should add channel to tombostone if 404', async () => {
84
+ enableCache();
85
+
86
+ client.http.get = jest
87
+ .fn()
88
+ .mockRejectedValueOnce(
89
+ new ASCApiError('not found!', Amity.ServerError.ITEM_NOT_FOUND, Amity.ErrorLevel.ERROR),
90
+ );
91
+
92
+ await expect(getChannel(channelId)).rejects.toThrow();
93
+ expect(() => {
94
+ isInTombstone('channel', channelId);
95
+ }).toThrow();
96
+
97
+ disableCache();
98
+ });
99
+
100
+ test('it should throw error if channel not found in tombostone', async () => {
101
+ enableCache();
102
+
103
+ pushToTombstone('channel', channelId);
104
+ await expect(getChannel(channelId)).rejects.toThrow();
105
+
106
+ disableCache();
107
+ });
108
+ });
@@ -0,0 +1,115 @@
1
+ import { getResolver } from '~/core/model';
2
+
3
+ import { disableCache, enableCache, pushToCache } from '~/cache/api';
4
+ import { ingestInCache } from '~/cache/api/ingestInCache';
5
+
6
+ import { prepareChannelPayload } from '~/channel/utils';
7
+ import { client, channelUserQueryResponse } from '~/utils/tests';
8
+
9
+ import { queryChannelMembers } from '../queryChannelMembers';
10
+
11
+ describe('queryChannelMembers', () => {
12
+ const { channelId } = channelUserQueryResponse.data.channels[0];
13
+
14
+ test('it should return channel members', async () => {
15
+ const expected = channelUserQueryResponse.data.channelUsers;
16
+ client.http.get = jest.fn().mockResolvedValue(channelUserQueryResponse);
17
+
18
+ const { data } = await queryChannelMembers({ channelId });
19
+
20
+ expect(data).toEqual(expected);
21
+ });
22
+
23
+ test('it should throw error', async () => {
24
+ client.http.get = jest.fn().mockRejectedValueOnce(new Error('error'));
25
+
26
+ await expect(queryChannelMembers({ channelId })).rejects.toThrow('error');
27
+ });
28
+
29
+ test('it should update cache upon fetching data from server', async () => {
30
+ enableCache();
31
+ client.http.get = jest.fn().mockResolvedValue(channelUserQueryResponse);
32
+
33
+ const { data: got } = await queryChannelMembers({ channelId });
34
+ const { data } = queryChannelMembers.locally({ channelId })!;
35
+
36
+ expect(data).toBeDefined();
37
+ expect(got).toEqual(data);
38
+
39
+ disableCache();
40
+ });
41
+ });
42
+
43
+ describe('queryChannelMembers.locally', () => {
44
+ const { channelId } = channelUserQueryResponse.data.channels[0];
45
+ const cacheKey = [
46
+ 'channelUsers',
47
+ 'query',
48
+ { channelId, options: { limit: 10, after: undefined } },
49
+ ];
50
+
51
+ test('it should fetch query locally if present in cache', () => {
52
+ enableCache();
53
+
54
+ const { paging, ...payload } = channelUserQueryResponse.data;
55
+ const data = prepareChannelPayload(payload);
56
+ const { channelUsers } = data;
57
+
58
+ ingestInCache(data as Amity.ChannelMembershipPayload);
59
+
60
+ pushToCache(cacheKey, {
61
+ channelUsers: channelUsers.map(({ channelId, userId }) =>
62
+ getResolver('channelUsers')({ channelId, userId }),
63
+ ),
64
+ paging,
65
+ });
66
+
67
+ const { data: got } = queryChannelMembers.locally({ channelId })!;
68
+
69
+ expect(got).toBeDefined();
70
+ expect(got).toEqual(channelUsers);
71
+
72
+ disableCache();
73
+ });
74
+
75
+ test('it should return undefined if only partial data in cache', () => {
76
+ enableCache();
77
+
78
+ const { paging, ...payload } = channelUserQueryResponse.data;
79
+ const data = prepareChannelPayload(payload);
80
+ const { channelUsers } = data;
81
+
82
+ // ingest incomplete data
83
+ ingestInCache({
84
+ ...data,
85
+ channelUsers: [data.channelUsers[0]],
86
+ } as Amity.ChannelMembershipPayload);
87
+
88
+ pushToCache(cacheKey, {
89
+ channelUsers: channelUsers.map(({ channelId, userId }) =>
90
+ getResolver('channelUsers')({ channelId, userId }),
91
+ ),
92
+ paging,
93
+ });
94
+
95
+ const got = queryChannelMembers.locally({ channelId })!;
96
+
97
+ expect(got).toBeUndefined();
98
+
99
+ disableCache();
100
+ });
101
+
102
+ test('it should return undefined if data not in cache', () => {
103
+ enableCache();
104
+
105
+ const got = queryChannelMembers.locally({ channelId });
106
+
107
+ expect(got).toBeUndefined();
108
+
109
+ disableCache();
110
+ });
111
+
112
+ test('it should return undefined if cache disabled', () => {
113
+ expect(queryChannelMembers.locally({ channelId })).toBeUndefined();
114
+ });
115
+ });
@@ -0,0 +1,121 @@
1
+ import { getResolver } from '~/core/model';
2
+
3
+ import { disableCache, enableCache, pushToCache } from '~/cache/api';
4
+ import { ingestInCache } from '~/cache/api/ingestInCache';
5
+
6
+ import { prepareChannelPayload } from '~/channel/utils';
7
+ import { client, channelQueryResponse } from '~/utils/tests';
8
+
9
+ import { queryChannels } from '../queryChannels';
10
+
11
+ describe('queryChannels', () => {
12
+ test('it should return channels', async () => {
13
+ const expected = prepareChannelPayload(channelQueryResponse.data).channels;
14
+ client.http.get = jest.fn().mockResolvedValue(channelQueryResponse);
15
+
16
+ const { data } = await queryChannels();
17
+
18
+ expect(data).toEqual(expected);
19
+ });
20
+
21
+ test('it should throw error', async () => {
22
+ client.http.get = jest.fn().mockRejectedValueOnce(new Error('error'));
23
+
24
+ await expect(queryChannels()).rejects.toThrow('error');
25
+ });
26
+
27
+ test('it should update cache upon fetching data from server', async () => {
28
+ enableCache();
29
+ client.http.get = jest.fn().mockResolvedValue(channelQueryResponse);
30
+
31
+ const { data: got } = await queryChannels();
32
+ const { data } = queryChannels.locally()!;
33
+
34
+ expect(data).toBeDefined();
35
+ expect(got).toEqual(data);
36
+
37
+ disableCache();
38
+ });
39
+ });
40
+
41
+ describe('queryChannels.locally', () => {
42
+ const cacheKey = ['channel', 'query', { options: { limit: 10, after: undefined } }];
43
+
44
+ test('it should fetch query locally if present in cache', () => {
45
+ enableCache();
46
+
47
+ const { paging, ...payload } = channelQueryResponse.data;
48
+ const data = prepareChannelPayload(payload);
49
+ const { channels } = data;
50
+
51
+ ingestInCache(data as Amity.ChannelMembershipPayload);
52
+
53
+ pushToCache(cacheKey, { channels: channels.map(getResolver('channel')), paging });
54
+
55
+ const { data: got } = queryChannels.locally()!;
56
+
57
+ expect(got).toBeDefined();
58
+ expect(got).toEqual(channels);
59
+
60
+ disableCache();
61
+ });
62
+
63
+ test('it should return undefined if only partial data in cache', () => {
64
+ enableCache();
65
+
66
+ const { paging, ...payload } = channelQueryResponse.data;
67
+ const data = prepareChannelPayload(payload);
68
+ const { channels } = data;
69
+
70
+ // ingest incomplete data
71
+ ingestInCache({
72
+ ...data,
73
+ channels: [data.channels[0]],
74
+ } as Amity.ChannelPayload);
75
+
76
+ pushToCache(cacheKey, {
77
+ channels: channels.map(getResolver('channel')),
78
+ paging,
79
+ });
80
+
81
+ const got = queryChannels.locally()!;
82
+
83
+ expect(got).toBeUndefined();
84
+
85
+ disableCache();
86
+ });
87
+
88
+ test('it should return undefined if params do not match', () => {
89
+ enableCache();
90
+
91
+ const { data } = channelQueryResponse;
92
+ const { channels: expected, paging } = data;
93
+
94
+ ingestInCache(data as Amity.ChannelPayload);
95
+
96
+ pushToCache(cacheKey, { channels: expected.map(getResolver('channel')), paging });
97
+
98
+ const { data: received } = queryChannels.locally()!;
99
+ const received2 = queryChannels.locally({ displayName: 'test' })!;
100
+
101
+ expect(received).toBeDefined();
102
+ expect(received).toEqual(expected);
103
+ expect(received2).toBeUndefined();
104
+
105
+ disableCache();
106
+ });
107
+
108
+ test('it should return undefined if data not in cache', () => {
109
+ enableCache();
110
+
111
+ const got = queryChannels.locally();
112
+
113
+ expect(got).toBeUndefined();
114
+
115
+ disableCache();
116
+ });
117
+
118
+ test('it should return undefined if cache disabled', () => {
119
+ expect(queryChannels.locally()).toBeUndefined();
120
+ });
121
+ });
@@ -1,7 +1,12 @@
1
1
  export * from './onChannelCreated';
2
2
  export * from './onChannelUpdated';
3
3
  export * from './onChannelDeleted';
4
+
4
5
  export * from './onChannelJoined';
5
6
  export * from './onChannelLeft';
7
+
6
8
  export * from './onChannelMemberAdded';
7
9
  export * from './onChannelMemberRemoved';
10
+
11
+ export * from './onChannelMemberBanned';
12
+ export * from './onChannelMemberUnbanned';
@@ -22,7 +22,7 @@ import { prepareChannelPayload } from '../utils';
22
22
  */
23
23
  export const onChannelMemberAdded = (
24
24
  callback: (channel: Amity.Channel, member: Amity.Membership<'channel'>) => void,
25
- ) => {
25
+ ): Amity.Unsubscriber => {
26
26
  const client = getActiveClient();
27
27
 
28
28
  const filter = (payload: Amity.ChannelMembershipPayload) => {
@@ -0,0 +1,36 @@
1
+ import { getActiveClient } from '~/client/api';
2
+ import { createEventSubscriber } from '~/core/events';
3
+
4
+ import { ingestInCache } from '~/cache/api/ingestInCache';
5
+
6
+ import { prepareChannelPayload } from '../utils';
7
+
8
+ /**
9
+ * ```js
10
+ * import { onChannelMemberBanned } from '@amityco/ts-sdk'
11
+ * const dispose = onChannelMemberBanned((channel, member) => {
12
+ * // ...
13
+ * })
14
+ * ```
15
+ *
16
+ * Fired when any {@link Amity.User} has been banned from any {@link Amity.Channel}
17
+ *
18
+ * @param callback The function to call when the event was fired
19
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
20
+ *
21
+ * @category Channel Events
22
+ */
23
+ export const onChannelMemberBanned = (
24
+ callback: (channel: Amity.Channel, member: Amity.Membership<'channel'>) => void,
25
+ ) => {
26
+ const client = getActiveClient();
27
+
28
+ const filter = (payload: Amity.ChannelMembershipPayload) => {
29
+ const data = prepareChannelPayload(payload);
30
+
31
+ ingestInCache(data);
32
+ callback(data.channels[0], data.channelUsers.find(cu => cu.membership === 'banned')!);
33
+ };
34
+
35
+ return createEventSubscriber(client, 'onChannelMemberBanned', 'v3.channel.didBan', filter);
36
+ };
@@ -0,0 +1,36 @@
1
+ import { getActiveClient } from '~/client/api';
2
+ import { createEventSubscriber } from '~/core/events';
3
+
4
+ import { ingestInCache } from '~/cache/api/ingestInCache';
5
+
6
+ import { prepareChannelPayload } from '../utils';
7
+
8
+ /**
9
+ * ```js
10
+ * import { onChannelMemberUnbanned } from '@amityco/ts-sdk'
11
+ * const dispose = onChannelMemberUnbanned((channel, member) => {
12
+ * // ...
13
+ * })
14
+ * ```
15
+ *
16
+ * Fired when any {@link Amity.User} has been unbanned from any {@link Amity.Channel}
17
+ *
18
+ * @param callback The function to call when the event was fired
19
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
20
+ *
21
+ * @category Channel Events
22
+ */
23
+ export const onChannelMemberUnbanned = (
24
+ callback: (channel: Amity.Channel, member: Amity.Membership<'channel'>) => void,
25
+ ) => {
26
+ const client = getActiveClient();
27
+
28
+ const filter = (payload: Amity.ChannelMembershipPayload) => {
29
+ const data = prepareChannelPayload(payload);
30
+
31
+ ingestInCache(data);
32
+ callback(data.channels[0], data.channelUsers.find(cu => cu.membership === 'none')!);
33
+ };
34
+
35
+ return createEventSubscriber(client, 'onChannelMemberBanned', 'v3.channel.didUnban', filter);
36
+ };
@@ -0,0 +1,58 @@
1
+ import { disableCache, enableCache } from '~/cache/api';
2
+
3
+ import {
4
+ client,
5
+ connectClient,
6
+ disconnectClient,
7
+ channel11,
8
+ channelUser1,
9
+ channelUser5,
10
+ } from '~/utils/tests';
11
+
12
+ import { onChannelMemberBanned } from '../onChannelMemberBanned';
13
+
14
+ describe('onChannelMemberBanned event', () => {
15
+ beforeAll(async () => {
16
+ await connectClient();
17
+ });
18
+
19
+ afterAll(async () => {
20
+ await disconnectClient();
21
+ });
22
+
23
+ beforeEach(async () => {
24
+ enableCache();
25
+ });
26
+
27
+ afterEach(disableCache);
28
+
29
+ const channelPayload: Amity.ChannelMembershipPayload = {
30
+ channelUsers: [channelUser1, channelUser5],
31
+ channels: [channel11],
32
+ files: [],
33
+ users: [],
34
+ };
35
+
36
+ test('it should call callback with channel and banned member', () => {
37
+ const callback = jest.fn();
38
+
39
+ const unsub = onChannelMemberBanned(callback);
40
+ client.emitter.emit('v3.channel.didBan', channelPayload);
41
+
42
+ unsub();
43
+
44
+ expect(callback).toHaveBeenCalled();
45
+ expect(callback).toHaveBeenCalledWith(channel11, channelUser5);
46
+ });
47
+
48
+ test('it should return an unsubscriber', () => {
49
+ const callback = jest.fn();
50
+
51
+ const unsub = onChannelMemberBanned(callback);
52
+ unsub();
53
+
54
+ client.emitter.emit('v3.channel.didBan', channelPayload);
55
+
56
+ expect(callback).not.toHaveBeenCalled();
57
+ });
58
+ });
@@ -0,0 +1,58 @@
1
+ import { disableCache, enableCache } from '~/cache/api';
2
+
3
+ import {
4
+ client,
5
+ connectClient,
6
+ disconnectClient,
7
+ channel11,
8
+ channelUser1,
9
+ channelUser3,
10
+ } from '~/utils/tests';
11
+
12
+ import { onChannelMemberUnbanned } from '../onChannelMemberUnbanned';
13
+
14
+ describe('onChannelMemberBanned event', () => {
15
+ beforeAll(async () => {
16
+ await connectClient();
17
+ });
18
+
19
+ afterAll(async () => {
20
+ await disconnectClient();
21
+ });
22
+
23
+ beforeEach(async () => {
24
+ enableCache();
25
+ });
26
+
27
+ afterEach(disableCache);
28
+
29
+ const channelPayload: Amity.ChannelMembershipPayload = {
30
+ channelUsers: [channelUser1, channelUser3],
31
+ channels: [channel11],
32
+ files: [],
33
+ users: [],
34
+ };
35
+
36
+ test('it should call callback with channel and unbanned member', () => {
37
+ const callback = jest.fn();
38
+
39
+ const unsub = onChannelMemberUnbanned(callback);
40
+ client.emitter.emit('v3.channel.didUnban', channelPayload);
41
+
42
+ unsub();
43
+
44
+ expect(callback).toHaveBeenCalled();
45
+ expect(callback).toHaveBeenCalledWith(channel11, channelUser3);
46
+ });
47
+
48
+ test('it should return an Unsubscriber', () => {
49
+ const callback = jest.fn();
50
+
51
+ const unsub = onChannelMemberUnbanned(callback);
52
+ unsub();
53
+
54
+ client.emitter.emit('v3.channel.didUnban', channelPayload);
55
+
56
+ expect(callback).not.toHaveBeenCalled();
57
+ });
58
+ });
@@ -16,7 +16,12 @@ import {
16
16
  COLLECTION_DEFAULT_PAGINATION_LIMIT,
17
17
  ENABLE_CACHE_MESSAGE,
18
18
  } from '~/utils/constants';
19
- import { onChannelMemberAdded, onChannelMemberRemoved } from '../events';
19
+ import {
20
+ onChannelMemberAdded,
21
+ onChannelMemberRemoved,
22
+ onChannelMemberBanned,
23
+ onChannelMemberUnbanned,
24
+ } from '../events';
20
25
  import { queryChannelMembers } from '../api';
21
26
 
22
27
  /**
@@ -67,7 +72,22 @@ export const liveChannelMembers = (
67
72
  .map(({ data }) => data) ?? [];
68
73
 
69
74
  channelMembers = filterByPropEquality(channelMembers, 'roles', params.roles);
70
- channelMembers = filterByPropInclusion(channelMembers, 'membership', params.memberships);
75
+
76
+ if (params.memberships) {
77
+ /*
78
+ * even though membership includes muted as a possible value
79
+ * when querying the server.
80
+ * Muted is specified under seperarte property namely isMuted
81
+ * Hence why I've seperately checked for it's equality
82
+ */
83
+ if (params.memberships.some(m => ['member', 'banned'].includes(m))) {
84
+ channelMembers = filterByPropInclusion(channelMembers, 'membership', params.memberships);
85
+ }
86
+
87
+ if (params.memberships.includes('muted')) {
88
+ channelMembers = filterByPropEquality(channelMembers, 'isMuted', true);
89
+ }
90
+ }
71
91
 
72
92
  if (params.search) {
73
93
  const containsMatcher = new RegExp(params.search);
@@ -91,7 +111,7 @@ export const liveChannelMembers = (
91
111
 
92
112
  const realtimeRouter = (
93
113
  channelMember: Amity.Membership<'channel'>,
94
- action: 'onMemberAdded' | 'onMemberRemoved',
114
+ action: Amity.ChannelMemberActionType,
95
115
  ) => {
96
116
  const collection = pullFromCache<Amity.ChannelMembersLiveCollectionCache>(cacheKey)?.data;
97
117
  if (!collection) return;
@@ -103,7 +123,9 @@ export const liveChannelMembers = (
103
123
 
104
124
  if (action === 'onMemberAdded') {
105
125
  collection.data = [...new Set([channelMemberCacheId, ...collection.data])];
106
- } else {
126
+ }
127
+
128
+ if (action === 'onMemberRemoved') {
107
129
  collection.data = collection.data.filter(m => m !== channelMemberCacheId);
108
130
  }
109
131
 
@@ -148,6 +170,8 @@ export const liveChannelMembers = (
148
170
  disposers.push(
149
171
  onChannelMemberAdded((_, member) => realtimeRouter(member, 'onMemberAdded')),
150
172
  onChannelMemberRemoved((_, member) => realtimeRouter(member, 'onMemberRemoved')),
173
+ onChannelMemberBanned((_, member) => realtimeRouter(member, 'onChannelMemberBanned')),
174
+ onChannelMemberUnbanned((_, member) => realtimeRouter(member, 'onChannelMemberUnbanned')),
151
175
  );
152
176
 
153
177
  onFetch();
@@ -7,6 +7,7 @@ import {
7
7
  runQuery,
8
8
  queryOptions,
9
9
  filterByPropEquality,
10
+ filterByChannelMembership,
10
11
  sortByLastCreated,
11
12
  sortByDisplayName,
12
13
  sortByFirstCreated,
@@ -43,7 +44,7 @@ export const liveChannels = (
43
44
  callback: Amity.LiveCollectionCallback<Amity.Channel>,
44
45
  config?: Amity.LiveCollectionConfig,
45
46
  ) => {
46
- const { log, cache } = getActiveClient();
47
+ const { log, cache, userId } = getActiveClient();
47
48
 
48
49
  if (!cache) {
49
50
  console.log(ENABLE_CACHE_MESSAGE);
@@ -82,6 +83,11 @@ export const liveChannels = (
82
83
  channels = channels.filter(c => !c.tags?.some(t => params.excludeTags?.includes(t)));
83
84
  }
84
85
 
86
+ // userId is required to be able to filter channel by current active user
87
+ if (params.membership && userId) {
88
+ channels = filterByChannelMembership(channels, params.membership, userId);
89
+ }
90
+
85
91
  const sortBy = params.sortBy || 'lastCreated';
86
92
 
87
93
  if (sortBy === 'lastCreated' || sortBy === 'firstCreated') {