@amityco/ts-sdk 6.2.0 → 6.2.1-0cf9bee.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.
Files changed (236) hide show
  1. package/README.md +0 -4
  2. package/dist/@types/core/events.d.ts +1 -0
  3. package/dist/@types/core/events.d.ts.map +1 -1
  4. package/dist/@types/core/payload.d.ts +4 -0
  5. package/dist/@types/core/payload.d.ts.map +1 -1
  6. package/dist/@types/domains/channel.d.ts +5 -1
  7. package/dist/@types/domains/channel.d.ts.map +1 -1
  8. package/dist/@types/domains/marker.d.ts +2 -1
  9. package/dist/@types/domains/marker.d.ts.map +1 -1
  10. package/dist/channelRepsitory/api/createChannel.d.ts +1 -1
  11. package/dist/channelRepsitory/api/markAsRead.d.ts +1 -1
  12. package/dist/channelRepsitory/api/muteChannel.d.ts.map +1 -1
  13. package/dist/client/utils/markerSyncEngine.d.ts.map +1 -1
  14. package/dist/communityRepository/{communityModeration → communityMembership}/api/addMembers.d.ts.map +1 -1
  15. package/dist/communityRepository/communityMembership/api/index.d.ts +3 -0
  16. package/dist/communityRepository/communityMembership/api/index.d.ts.map +1 -0
  17. package/dist/communityRepository/{communityModeration → communityMembership}/api/removeMembers.d.ts.map +1 -1
  18. package/dist/communityRepository/communityMembership/api/tests/addMembers.test.d.ts.map +1 -0
  19. package/dist/communityRepository/communityMembership/api/tests/removeMembers.test.d.ts.map +1 -0
  20. package/dist/communityRepository/communityMembership/index.d.ts +1 -0
  21. package/dist/communityRepository/communityMembership/index.d.ts.map +1 -1
  22. package/dist/communityRepository/communityMembership/observers/getMembers.d.ts.map +1 -1
  23. package/dist/communityRepository/communityModeration/api/banMembers.d.ts +16 -0
  24. package/dist/communityRepository/communityModeration/api/banMembers.d.ts.map +1 -0
  25. package/dist/communityRepository/communityModeration/api/index.d.ts +2 -2
  26. package/dist/communityRepository/communityModeration/api/index.d.ts.map +1 -1
  27. package/dist/communityRepository/communityModeration/api/test/banMembers.test.d.ts +2 -0
  28. package/dist/communityRepository/communityModeration/api/test/banMembers.test.d.ts.map +1 -0
  29. package/dist/communityRepository/communityModeration/api/test/unbanMembers.test.d.ts +2 -0
  30. package/dist/communityRepository/communityModeration/api/test/unbanMembers.test.d.ts.map +1 -0
  31. package/dist/communityRepository/communityModeration/api/unbanMembers.d.ts +16 -0
  32. package/dist/communityRepository/communityModeration/api/unbanMembers.d.ts.map +1 -0
  33. package/dist/core/events.d.ts +3 -3
  34. package/dist/core/events.d.ts.map +1 -1
  35. package/dist/core/query/filtering.d.ts +1 -0
  36. package/dist/core/query/filtering.d.ts.map +1 -1
  37. package/dist/core/query/sorting.d.ts.map +1 -1
  38. package/dist/core/transports/mqtt.d.ts +1 -1
  39. package/dist/core/transports/mqtt.d.ts.map +1 -1
  40. package/dist/feedRepository/api/getCustomRankingGlobalFeed.d.ts +36 -0
  41. package/dist/feedRepository/api/getCustomRankingGlobalFeed.d.ts.map +1 -0
  42. package/dist/feedRepository/api/index.d.ts +1 -0
  43. package/dist/feedRepository/api/index.d.ts.map +1 -1
  44. package/dist/feedRepository/api/queryGlobalFeed.d.ts.map +1 -1
  45. package/dist/feedRepository/api/test/getCustomRankingGlobalFeed.test.d.ts +2 -0
  46. package/dist/feedRepository/api/test/getCustomRankingGlobalFeed.test.d.ts.map +1 -0
  47. package/dist/fileRepository/api/index.d.ts +3 -3
  48. package/dist/fileRepository/api/test/uploadFile.test.d.ts +2 -0
  49. package/dist/fileRepository/api/test/uploadFile.test.d.ts.map +1 -0
  50. package/dist/fileRepository/api/test/uploadImage.test.d.ts +2 -0
  51. package/dist/fileRepository/api/test/uploadImage.test.d.ts.map +1 -0
  52. package/dist/fileRepository/api/test/uploadVideo.test.d.ts +2 -0
  53. package/dist/fileRepository/api/test/uploadVideo.test.d.ts.map +1 -0
  54. package/dist/fileRepository/api/{createFile.d.ts → uploadFile.d.ts} +4 -4
  55. package/dist/fileRepository/api/uploadFile.d.ts.map +1 -0
  56. package/dist/fileRepository/api/{createImage.d.ts → uploadImage.d.ts} +4 -4
  57. package/dist/fileRepository/api/uploadImage.d.ts.map +1 -0
  58. package/dist/fileRepository/api/{createVideo.d.ts → uploadVideo.d.ts} +5 -5
  59. package/dist/fileRepository/api/uploadVideo.d.ts.map +1 -0
  60. package/dist/index.cjs.js +795 -193
  61. package/dist/index.esm.js +794 -194
  62. package/dist/index.umd.js +4 -4
  63. package/dist/marker/events/index.d.ts +1 -0
  64. package/dist/marker/events/index.d.ts.map +1 -1
  65. package/dist/marker/events/onFeedlMarkerUpdated.d.ts +17 -0
  66. package/dist/marker/events/onFeedlMarkerUpdated.d.ts.map +1 -0
  67. package/dist/messageRepository/api/createMessage.d.ts +1 -1
  68. package/dist/messageRepository/api/editMessage.d.ts +38 -0
  69. package/dist/messageRepository/api/editMessage.d.ts.map +1 -0
  70. package/dist/messageRepository/api/flagMessage.d.ts +14 -0
  71. package/dist/messageRepository/api/flagMessage.d.ts.map +1 -0
  72. package/dist/messageRepository/api/index.d.ts +5 -1
  73. package/dist/messageRepository/api/index.d.ts.map +1 -1
  74. package/dist/messageRepository/api/isMessageFlaggedByMe.d.ts +14 -0
  75. package/dist/messageRepository/api/isMessageFlaggedByMe.d.ts.map +1 -0
  76. package/dist/messageRepository/api/markAsDelivered.d.ts +2 -2
  77. package/dist/messageRepository/api/{deleteMessage.d.ts → softDeleteMessage.d.ts} +6 -6
  78. package/dist/messageRepository/api/softDeleteMessage.d.ts.map +1 -0
  79. package/dist/messageRepository/api/tests/editMessage.test.d.ts +2 -0
  80. package/dist/messageRepository/api/tests/editMessage.test.d.ts.map +1 -0
  81. package/dist/messageRepository/api/tests/flagMessage.test.d.ts +2 -0
  82. package/dist/messageRepository/api/tests/flagMessage.test.d.ts.map +1 -0
  83. package/dist/messageRepository/api/tests/unflagMessage.test.d.ts +2 -0
  84. package/dist/messageRepository/api/tests/unflagMessage.test.d.ts.map +1 -0
  85. package/dist/messageRepository/api/unflagMessage.d.ts +14 -0
  86. package/dist/messageRepository/api/unflagMessage.d.ts.map +1 -0
  87. package/dist/messageRepository/api/updateMessage.d.ts.map +1 -1
  88. package/dist/postRepository/api/deletePost.d.ts +1 -1
  89. package/dist/postRepository/api/deletePost.d.ts.map +1 -1
  90. package/dist/postRepository/api/editPost.d.ts +24 -0
  91. package/dist/postRepository/api/editPost.d.ts.map +1 -0
  92. package/dist/postRepository/api/flagPost.d.ts +14 -0
  93. package/dist/postRepository/api/flagPost.d.ts.map +1 -0
  94. package/dist/postRepository/api/hardDeletePost.d.ts +16 -0
  95. package/dist/postRepository/api/hardDeletePost.d.ts.map +1 -0
  96. package/dist/postRepository/api/index.d.ts +6 -0
  97. package/dist/postRepository/api/index.d.ts.map +1 -1
  98. package/dist/postRepository/api/isPostFlaggedByMe.d.ts +14 -0
  99. package/dist/postRepository/api/isPostFlaggedByMe.d.ts.map +1 -0
  100. package/dist/postRepository/api/softDeletePost.d.ts +16 -0
  101. package/dist/postRepository/api/softDeletePost.d.ts.map +1 -0
  102. package/dist/postRepository/api/unflagPost.d.ts +14 -0
  103. package/dist/postRepository/api/unflagPost.d.ts.map +1 -0
  104. package/dist/postRepository/api/updatePost.d.ts.map +1 -1
  105. package/dist/subChannelRepository/api/startReadingAPI.d.ts.map +1 -1
  106. package/dist/subChannelRepository/api/stopReadingAPI.d.ts.map +1 -1
  107. package/dist/userRepository/api/flagUser.d.ts +14 -0
  108. package/dist/userRepository/api/flagUser.d.ts.map +1 -0
  109. package/dist/userRepository/api/index.d.ts +3 -0
  110. package/dist/userRepository/api/index.d.ts.map +1 -1
  111. package/dist/userRepository/api/isUserFlaggedByMe.d.ts +14 -0
  112. package/dist/userRepository/api/isUserFlaggedByMe.d.ts.map +1 -0
  113. package/dist/userRepository/{relationship/block/api → api}/queryBlockedUsers.d.ts +2 -2
  114. package/dist/userRepository/api/queryBlockedUsers.d.ts.map +1 -0
  115. package/dist/userRepository/api/tests/flagUser.test.d.ts +2 -0
  116. package/dist/userRepository/api/tests/flagUser.test.d.ts.map +1 -0
  117. package/dist/userRepository/api/tests/queryBlockedUsers.test.d.ts.map +1 -0
  118. package/dist/userRepository/api/tests/unflagUser.test.d.ts +2 -0
  119. package/dist/userRepository/api/tests/unflagUser.test.d.ts.map +1 -0
  120. package/dist/userRepository/api/unflagUser.d.ts +14 -0
  121. package/dist/userRepository/api/unflagUser.d.ts.map +1 -0
  122. package/dist/userRepository/observers/getBlockedUsers.d.ts +2 -0
  123. package/dist/userRepository/observers/getBlockedUsers.d.ts.map +1 -0
  124. package/dist/userRepository/observers/index.d.ts +1 -0
  125. package/dist/userRepository/observers/index.d.ts.map +1 -1
  126. package/dist/userRepository/relationship/block/observers/getBlockedUsers.d.ts.map +1 -1
  127. package/package.json +1 -1
  128. package/src/@types/core/events.ts +1 -0
  129. package/src/@types/core/payload.ts +5 -0
  130. package/src/@types/domains/channel.ts +7 -2
  131. package/src/@types/domains/marker.ts +1 -0
  132. package/src/categoryRepository/observers/getCategories.ts +4 -4
  133. package/src/channelRepsitory/api/markAsRead.ts +1 -1
  134. package/src/channelRepsitory/api/muteChannel.ts +8 -0
  135. package/src/channelRepsitory/api/tests/muteChannel.test.ts +12 -0
  136. package/src/channelRepsitory/channelMembership/observers/getMembers.ts +6 -6
  137. package/src/channelRepsitory/observers/getChannels.ts +5 -5
  138. package/src/channelRepsitory/observers/tests/getChannels.test.ts +3 -9
  139. package/src/client/utils/markerSyncEngine.ts +2 -14
  140. package/src/commentRepository/observers/getComments.ts +5 -5
  141. package/src/communityRepository/communityMembership/api/index.ts +2 -0
  142. package/src/communityRepository/{communityModeration/api/test → communityMembership/api/tests}/addMembers.test.ts +1 -1
  143. package/src/communityRepository/{communityModeration/api/test → communityMembership/api/tests}/removeMembers.test.ts +1 -1
  144. package/src/communityRepository/communityMembership/index.ts +1 -0
  145. package/src/communityRepository/communityMembership/observers/getMembers.ts +6 -8
  146. package/src/communityRepository/communityModeration/api/banMembers.ts +50 -0
  147. package/src/communityRepository/communityModeration/api/index.ts +3 -2
  148. package/src/communityRepository/communityModeration/api/test/banMembers.test.ts +70 -0
  149. package/src/communityRepository/communityModeration/api/test/unbanMembers.test.ts +70 -0
  150. package/src/communityRepository/communityModeration/api/unbanMembers.ts +50 -0
  151. package/src/communityRepository/observers/getCommunities.ts +5 -5
  152. package/src/core/query/filtering.ts +22 -2
  153. package/src/core/query/sorting.ts +2 -4
  154. package/src/core/query/tests/filtering.test.ts +6 -0
  155. package/src/core/query/tests/runQuery.test.ts +3 -3
  156. package/src/core/transports/mqtt.ts +3 -2
  157. package/src/feedRepository/api/getCustomRankingGlobalFeed.ts +117 -0
  158. package/src/feedRepository/api/index.ts +1 -0
  159. package/src/feedRepository/api/queryGlobalFeed.ts +12 -4
  160. package/src/feedRepository/api/test/getCustomRankingGlobalFeed.test.ts +130 -0
  161. package/src/feedRepository/api/test/queryGlobalFeed.test.ts +1 -15
  162. package/src/fileRepository/api/index.ts +3 -3
  163. package/src/fileRepository/api/test/uploadFile.test.ts +69 -0
  164. package/src/fileRepository/api/test/{createImage.test.ts → uploadImage.test.ts} +7 -7
  165. package/src/fileRepository/api/test/{createVideo.test.ts → uploadVideo.test.ts} +8 -8
  166. package/src/fileRepository/api/{createFile.ts → uploadFile.ts} +4 -6
  167. package/src/fileRepository/api/{createImage.ts → uploadImage.ts} +4 -6
  168. package/src/fileRepository/api/{createVideo.ts → uploadVideo.ts} +5 -7
  169. package/src/marker/events/index.ts +1 -0
  170. package/src/marker/events/onFeedlMarkerUpdated.ts +34 -0
  171. package/src/messageRepository/api/editMessage.ts +100 -0
  172. package/src/messageRepository/api/flagMessage.ts +40 -0
  173. package/src/messageRepository/api/index.ts +7 -1
  174. package/src/messageRepository/api/isMessageFlaggedByMe.ts +30 -0
  175. package/src/messageRepository/api/markAsDelivered.ts +2 -2
  176. package/src/messageRepository/api/{deleteMessage.ts → softDeleteMessage.ts} +8 -8
  177. package/src/messageRepository/api/tests/deleteMessage.test.ts +11 -11
  178. package/src/messageRepository/api/tests/{updateMessage.test.ts → editMessage.test.ts} +10 -10
  179. package/src/messageRepository/api/tests/flagMessage.test.ts +87 -0
  180. package/src/messageRepository/api/tests/unflagMessage.test.ts +87 -0
  181. package/src/messageRepository/api/unflagMessage.ts +40 -0
  182. package/src/messageRepository/api/updateMessage.ts +4 -0
  183. package/src/messageRepository/events/onMessageDeleted.ts +1 -1
  184. package/src/messageRepository/observers/getMessages.ts +5 -5
  185. package/src/postRepository/api/deletePost.ts +1 -7
  186. package/src/postRepository/api/editPost.ts +58 -0
  187. package/src/postRepository/api/flagPost.ts +38 -0
  188. package/src/postRepository/api/hardDeletePost.ts +30 -0
  189. package/src/postRepository/api/index.ts +8 -0
  190. package/src/postRepository/api/isPostFlaggedByMe.ts +33 -0
  191. package/src/postRepository/api/softDeletePost.ts +30 -0
  192. package/src/postRepository/api/unflagPost.ts +39 -0
  193. package/src/postRepository/api/updatePost.ts +4 -0
  194. package/src/postRepository/observers/getPosts.ts +5 -5
  195. package/src/reactionRepository/observers/getReactions.ts +4 -4
  196. package/src/report/api/createReport.ts +1 -1
  197. package/src/report/api/tests/createReport.test.ts +2 -62
  198. package/src/report/api/tests/deleteReport.test.ts +2 -62
  199. package/src/subChannelRepository/api/startReadingAPI.ts +13 -0
  200. package/src/subChannelRepository/api/stopReadingAPI.ts +13 -0
  201. package/src/userRepository/api/flagUser.ts +37 -0
  202. package/src/userRepository/api/index.ts +4 -0
  203. package/src/userRepository/api/isUserFlaggedByMe.ts +33 -0
  204. package/src/userRepository/{relationship/block/api → api}/queryBlockedUsers.ts +3 -2
  205. package/src/userRepository/api/tests/flagUser.test.ts +81 -0
  206. package/src/userRepository/{relationship/block/api → api}/tests/queryBlockedUsers.test.ts +1 -1
  207. package/src/userRepository/api/tests/unflagUser.test.ts +80 -0
  208. package/src/userRepository/api/unflagUser.ts +37 -0
  209. package/src/userRepository/observers/getBlockedUsers.ts +104 -0
  210. package/src/userRepository/observers/getUsers.ts +4 -4
  211. package/src/userRepository/observers/index.ts +1 -0
  212. package/src/userRepository/observers/tests/getUsers.test.ts +3 -9
  213. package/src/userRepository/relationship/block/observers/getBlockedUsers.ts +5 -96
  214. package/src/userRepository/relationship/follow/observers/getFollowers.ts +4 -4
  215. package/src/userRepository/relationship/follow/observers/getFollowings.ts +4 -4
  216. package/dist/communityRepository/communityModeration/api/test/addMembers.test.d.ts.map +0 -1
  217. package/dist/communityRepository/communityModeration/api/test/removeMembers.test.d.ts.map +0 -1
  218. package/dist/fileRepository/api/createFile.d.ts.map +0 -1
  219. package/dist/fileRepository/api/createImage.d.ts.map +0 -1
  220. package/dist/fileRepository/api/createVideo.d.ts.map +0 -1
  221. package/dist/fileRepository/api/test/createImage.test.d.ts +0 -2
  222. package/dist/fileRepository/api/test/createImage.test.d.ts.map +0 -1
  223. package/dist/fileRepository/api/test/createVideo.test.d.ts +0 -2
  224. package/dist/fileRepository/api/test/createVideo.test.d.ts.map +0 -1
  225. package/dist/messageRepository/api/deleteMessage.d.ts.map +0 -1
  226. package/dist/messageRepository/api/tests/updateMessage.test.d.ts +0 -2
  227. package/dist/messageRepository/api/tests/updateMessage.test.d.ts.map +0 -1
  228. package/dist/userRepository/relationship/block/api/queryBlockedUsers.d.ts.map +0 -1
  229. package/dist/userRepository/relationship/block/api/tests/queryBlockedUsers.test.d.ts.map +0 -1
  230. /package/dist/communityRepository/{communityModeration → communityMembership}/api/addMembers.d.ts +0 -0
  231. /package/dist/communityRepository/{communityModeration → communityMembership}/api/removeMembers.d.ts +0 -0
  232. /package/dist/communityRepository/{communityModeration/api/test → communityMembership/api/tests}/addMembers.test.d.ts +0 -0
  233. /package/dist/communityRepository/{communityModeration/api/test → communityMembership/api/tests}/removeMembers.test.d.ts +0 -0
  234. /package/dist/userRepository/{relationship/block/api → api}/tests/queryBlockedUsers.test.d.ts +0 -0
  235. /package/src/communityRepository/{communityModeration → communityMembership}/api/addMembers.ts +0 -0
  236. /package/src/communityRepository/{communityModeration → communityMembership}/api/removeMembers.ts +0 -0
@@ -18,7 +18,10 @@ export const filterByPropEquality = <T = Record<string, unknown>>(
18
18
  collection: T[],
19
19
  key: keyof T,
20
20
  value: any,
21
- ) => (value !== undefined ? collection.filter(item => item[key] === value) : collection);
21
+ ) =>
22
+ value !== undefined
23
+ ? collection.filter(item => JSON.stringify(item[key]) === JSON.stringify(value))
24
+ : collection;
22
25
 
23
26
  export const filterByPropInclusion = <T = Record<string, unknown>>(
24
27
  collection: T[],
@@ -26,6 +29,19 @@ export const filterByPropInclusion = <T = Record<string, unknown>>(
26
29
  value: any[] | undefined,
27
30
  ) => (value !== undefined ? collection.filter(item => value.includes(item[key])) : collection);
28
31
 
32
+ export const filterByPropIntersection = <T extends Record<string, unknown>>(
33
+ collection: T[],
34
+ key: keyof T,
35
+ values: any[] | undefined,
36
+ ) => {
37
+ if (!values?.length) return collection;
38
+
39
+ return collection.filter(
40
+ item =>
41
+ Array.isArray(item[key]) && values.some(value => (item[key] as unknown[]).includes(value)),
42
+ );
43
+ };
44
+
29
45
  /**
30
46
  * Filter a channel collection by membership of the userId
31
47
  *
@@ -189,7 +205,11 @@ export const filterBySearchTerm = <T extends { userId: Amity.User['userId']; use
189
205
  collection: T[],
190
206
  searchTerm: string,
191
207
  ): T[] => {
192
- const containsMatcher = new RegExp(searchTerm);
208
+ /*
209
+ * Search term should match regardless of the case.
210
+ * Hence, the flag "i", is passed to the created regex
211
+ */
212
+ const containsMatcher = new RegExp(searchTerm, 'i');
193
213
 
194
214
  return collection.filter(m => {
195
215
  if (m.userId.match(containsMatcher)) return true;
@@ -18,10 +18,8 @@ export const sortByDisplayName: SortingFunc<{ displayName: string }> = (
18
18
  /**
19
19
  * Alphabetic sorting of objects having a name
20
20
  */
21
- export const sortByName: SortingFunc<{ name: string }> = ({ name: a }, { name: b }) => {
22
- if (a === b) return 0;
23
- return a < b ? -1 : 1;
24
- };
21
+ export const sortByName: SortingFunc<{ name: string }> = ({ name: a }, { name: b }) =>
22
+ a.localeCompare(b);
25
23
 
26
24
  /**
27
25
  * Sorting a collection by their apparition order (oldest first)
@@ -13,6 +13,12 @@ describe('filtering:', () => {
13
13
  ]);
14
14
  });
15
15
 
16
+ test('it should ignore search term case', () => {
17
+ expect(filterBySearchTerm(searchTermCollection, 'USER')).toStrictEqual([
18
+ searchTermCollection[0],
19
+ ]);
20
+ });
21
+
16
22
  test('it should return items that match displayName', () => {
17
23
  expect(filterBySearchTerm(searchTermCollection, 'displ')).toStrictEqual([
18
24
  searchTermCollection[0],
@@ -3,7 +3,7 @@ import { disableCache, enableCache, pushToCache } from '~/cache/api';
3
3
  import { runQuery, createQuery } from '~/core/query';
4
4
  import { createPost } from '~/postRepository/api';
5
5
  import { getPost } from '~/postRepository/api/getPost';
6
- import { deleteMessage } from '~/messageRepository/api';
6
+ import { softDeleteMessage } from '~/messageRepository/api';
7
7
 
8
8
  import { posts, client, pause, emptyPostPayload } from '~/utils/tests';
9
9
 
@@ -115,7 +115,7 @@ describe('Core/Query/runQuery', () => {
115
115
  // 'get', gets called after delete to verify delete
116
116
  client.http.get = jest.fn();
117
117
 
118
- const query = createQuery(deleteMessage, deletingMsgId);
118
+ const query = createQuery(softDeleteMessage, deletingMsgId);
119
119
  runQuery(query);
120
120
 
121
121
  expect(client.http.delete).toHaveBeenCalledWith(`/api/v5/messages/${deletingMsgId}`);
@@ -148,7 +148,7 @@ describe('Core/Query/runQuery', () => {
148
148
  );
149
149
  const callback = jest.fn();
150
150
 
151
- const query = createQuery(deleteMessage, deletingMsgId);
151
+ const query = createQuery(softDeleteMessage, deletingMsgId);
152
152
  runQuery(query, callback);
153
153
  await pause();
154
154
 
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable no-console */
2
2
  /* eslint-disable no-promise-executor-return */
3
- import mqtt, { MqttClient, IClientOptions, ISubscriptionGrant } from 'mqtt/dist/mqtt';
3
+ import mqtt, { IClientOptions, ISubscriptionGrant, MqttClient } from 'mqtt/dist/mqtt';
4
4
  import { ASCError, ASCUnknownError } from '~/core/errors';
5
5
 
6
6
  const QOS_FAILURE_CODE = 128;
@@ -138,7 +138,8 @@ export const createMqttTransport = (endpoint: string): Amity.MqttClient => {
138
138
  : // TODO throw the actual error, once BE can tell us the actual error code
139
139
  new ASCUnknownError(Amity.ClientError.UNKNOWN_ERROR, Amity.ErrorLevel.ERROR);
140
140
 
141
- console.error(`Failed to subscribe to topic ${topic}`, ascError);
141
+ // Use warning lv instead of error lv to prevent misunderstanding of user
142
+ console.warn(`Failed to subscribe to topic ${topic}`, ascError);
142
143
  callback?.(ascError);
143
144
  } else {
144
145
  console.log(`Subscribed to topic ${granted[0].topic}`);
@@ -0,0 +1,117 @@
1
+ import { getActiveClient } from '~/client/api/activeClient';
2
+
3
+ import { toPage, toToken } from '~/core/query';
4
+ import { ingestInCache } from '~/cache/api/ingestInCache';
5
+ import { pullFromCache, pushToCache } from '~/cache/api';
6
+ import { getResolver } from '~/core/model';
7
+ import { prepareMembershipPayload } from '~/group/utils';
8
+
9
+ /* begin_public_function
10
+ id: feed.query.custom_ranking_feed
11
+ */
12
+ /**
13
+ * ```js
14
+ * import { FeedRepository } from '@amityco/ts-sdk'
15
+ * const posts = await FeedRepository.getCustomRankingGlobalFeed()
16
+ * ```
17
+ *
18
+ * Queries a paginable list of {@link Amity.Post} objects
19
+ *
20
+ * @param query The query parameters
21
+ * @returns A page of {@link Amity.Post} objects
22
+ *
23
+ * @category Feed API
24
+ * @async
25
+ * */
26
+ export const getCustomRankingGlobalFeed = async (query?: {
27
+ dataTypes?: ('video' | 'image' | 'file' | 'liveStream')[];
28
+ page?: Amity.Page;
29
+ }): Promise<Amity.Cached<Amity.Paged<Amity.Post>>> => {
30
+ const client = getActiveClient();
31
+ client.log('feed/getCustomRankingGlobalFeed', query);
32
+
33
+ const { page, ...params } = query ?? {};
34
+
35
+ const { data: queryPayload } = await client.http.get<Amity.PostPayload & Amity.Pagination>(
36
+ `/api/v5/me/global-feeds`,
37
+ {
38
+ params: {
39
+ ...params,
40
+ options: {
41
+ token: toToken(page, 'skiplimit'),
42
+ },
43
+ },
44
+ },
45
+ );
46
+
47
+ const { paging, ...payload } = queryPayload;
48
+
49
+ const data = prepareMembershipPayload(payload, 'communityUsers');
50
+
51
+ const { posts } = data;
52
+
53
+ const cachedAt = client.cache && Date.now();
54
+
55
+ if (client.cache) {
56
+ ingestInCache(data);
57
+
58
+ const cacheKey = [
59
+ 'customGlobalFeed',
60
+ 'query',
61
+ { ...params, options: { ...page } } as Amity.Serializable,
62
+ ];
63
+ pushToCache(cacheKey, { posts: posts.map(getResolver('post')), paging });
64
+ }
65
+
66
+ const nextPage = toPage(paging.next);
67
+ const prevPage = toPage(paging.previous);
68
+
69
+ return { data: posts, cachedAt, prevPage, nextPage };
70
+ };
71
+ /* end_public_function */
72
+
73
+ /**
74
+ * ```js
75
+ * import { FeedRepository } from '@amityco/ts-sdk'
76
+ * const posts = await FeedRepository.getCustomRankingGlobalFeed.locally()
77
+ * ```
78
+ *
79
+ * Queries a paginable list of {@link Amity.Post} objects from cache
80
+ *
81
+ * @param query The query parameters
82
+ * @returns A page of {@link Amity.Post} objects
83
+ *
84
+ * @category Feed API
85
+ * @async
86
+ * */
87
+ getCustomRankingGlobalFeed.locally = (
88
+ query?: Parameters<typeof getCustomRankingGlobalFeed>[0],
89
+ ): Amity.Cached<Amity.Paged<Amity.Post>> | undefined => {
90
+ const client = getActiveClient();
91
+ client.log('post/getCustomRankingGlobalFeed.locally', query);
92
+
93
+ if (!client.cache) return;
94
+
95
+ const { page, ...params } = query ?? {};
96
+
97
+ const queryKey = [
98
+ 'customGlobalFeed',
99
+ 'query',
100
+ { ...params, options: { ...page } } as Amity.Serializable,
101
+ ];
102
+ const { data, cachedAt } = pullFromCache<{ posts: string[] } & Amity.Pagination>(queryKey) ?? {};
103
+
104
+ if (!data?.posts.length) return;
105
+
106
+ const posts: Amity.Post[] = data.posts
107
+ .map(postId => pullFromCache<Amity.Post>(['post', 'get', postId])!)
108
+ .filter(Boolean)
109
+ .map(({ data }) => data);
110
+
111
+ const prevPage = toPage(data?.paging.previous);
112
+ const nextPage = toPage(data?.paging.next);
113
+
114
+ return posts.length === data?.posts?.length
115
+ ? { data: posts, cachedAt, prevPage, nextPage }
116
+ : undefined;
117
+ };
@@ -1 +1,2 @@
1
1
  export * from './queryGlobalFeed';
2
+ export * from './getCustomRankingGlobalFeed';
@@ -33,8 +33,16 @@ export const queryGlobalFeed = async (query?: {
33
33
 
34
34
  const { useCustomRanking, page, ...params } = query ?? {};
35
35
 
36
+ /*
37
+ * TODO: Remove useCustomRanking key from query
38
+ */
39
+ if (useCustomRanking)
40
+ console.warn(
41
+ 'The param "useCustomRanking" has been deprecated. To get custom ranking feed use FeedRepository.getCustomRankingGlobalFeed instead',
42
+ );
43
+
36
44
  const { data: queryPayload } = await client.http.get<Amity.PostPayload & Amity.Pagination>(
37
- useCustomRanking ? `/api/v5/me/global-feeds` : `/api/v4/me/global-feeds`,
45
+ `/api/v4/me/global-feeds`,
38
46
  {
39
47
  params: {
40
48
  ...params,
@@ -59,7 +67,7 @@ export const queryGlobalFeed = async (query?: {
59
67
  const cacheKey = [
60
68
  'globalFeed',
61
69
  'query',
62
- { ...params, useCustomRanking, options: { ...page } } as Amity.Serializable,
70
+ { ...params, options: { ...page } } as Amity.Serializable,
63
71
  ];
64
72
  pushToCache(cacheKey, { posts: posts.map(getResolver('post')), paging });
65
73
  }
@@ -93,12 +101,12 @@ queryGlobalFeed.locally = (
93
101
 
94
102
  if (!client.cache) return;
95
103
 
96
- const { useCustomRanking, page, ...params } = query ?? {};
104
+ const { page, ...params } = query ?? {};
97
105
 
98
106
  const queryKey = [
99
107
  'globalFeed',
100
108
  'query',
101
- { ...params, useCustomRanking, options: { ...page } } as Amity.Serializable,
109
+ { ...params, options: { ...page } } as Amity.Serializable,
102
110
  ];
103
111
  const { data, cachedAt } = pullFromCache<{ posts: string[] } & Amity.Pagination>(queryKey) ?? {};
104
112
 
@@ -0,0 +1,130 @@
1
+ import { disableCache, enableCache, pullFromCache, pushToCache } from '~/cache/api';
2
+
3
+ import { client, post11, post12 } from '~/utils/tests';
4
+
5
+ import { getCustomRankingGlobalFeed } from '../getCustomRankingGlobalFeed';
6
+
7
+ const pagingToken = {
8
+ previous: 'eyJiZWZvcmUiOjU1LCJsYXN0IjoxMH0=',
9
+ next: 'eyJiZWZvcmUiOjU1LCJsYXN0IjoxMH0=',
10
+ };
11
+
12
+ const postsToQuery = [post11, post12];
13
+ const postIdsToQuery = postsToQuery.map(post => post.postId);
14
+ const pagingCriteria = { limit: 10 };
15
+ const queryCriteriaWithoutPage = {};
16
+ const queryCriteria = { ...queryCriteriaWithoutPage, page: pagingCriteria };
17
+
18
+ const resolvedQueryFeedValue = {
19
+ data: {
20
+ posts: postsToQuery,
21
+ postChildren: [],
22
+ categories: [],
23
+ comments: [],
24
+ communityUsers: [],
25
+ feeds: [],
26
+ files: [],
27
+ polls: [],
28
+ users: [],
29
+ paging: pagingToken,
30
+ },
31
+ };
32
+
33
+ describe('getCustomRankingGlobalFeed', () => {
34
+ test('it should return fetched feed with correct paging', async () => {
35
+ client.http.get = jest.fn().mockResolvedValueOnce(resolvedQueryFeedValue);
36
+
37
+ await expect(getCustomRankingGlobalFeed(queryCriteria)).resolves.toEqual(
38
+ expect.objectContaining({
39
+ data: postsToQuery,
40
+ prevPage: { before: 55, limit: 10 },
41
+ nextPage: { before: 55, limit: 10 },
42
+ }),
43
+ );
44
+ });
45
+
46
+ test('it should update cache after fetching feed', async () => {
47
+ enableCache();
48
+ client.http.get = jest.fn().mockResolvedValue(resolvedQueryFeedValue);
49
+
50
+ await getCustomRankingGlobalFeed(queryCriteria);
51
+
52
+ const recieved = pullFromCache([
53
+ 'customGlobalFeed',
54
+ 'query',
55
+ { ...queryCriteriaWithoutPage, options: pagingCriteria },
56
+ ])?.data;
57
+
58
+ expect(recieved).toEqual({
59
+ posts: postIdsToQuery,
60
+ paging: pagingToken,
61
+ });
62
+
63
+ disableCache();
64
+ });
65
+
66
+ test('it should call the correct api', async () => {
67
+ const resolver = jest.fn().mockResolvedValue(resolvedQueryFeedValue);
68
+ client.http.get = resolver;
69
+
70
+ await getCustomRankingGlobalFeed(queryCriteria);
71
+
72
+ expect(resolver).toHaveBeenCalledWith(`/api/v5/me/global-feeds`, expect.any(Object));
73
+ });
74
+
75
+ test('it should throw an error if request fails', async () => {
76
+ client.http.get = jest.fn().mockRejectedValueOnce(new Error('error'));
77
+
78
+ await expect(getCustomRankingGlobalFeed(queryCriteria)).rejects.toThrow('error');
79
+ });
80
+ });
81
+
82
+ describe('getCustomRankingGlobalFeed.locally', () => {
83
+ beforeEach(enableCache);
84
+ afterEach(disableCache);
85
+
86
+ test('it should return cached feed', () => {
87
+ postsToQuery.forEach(post => pushToCache(['post', 'get', post.postId], post));
88
+
89
+ pushToCache(
90
+ ['customGlobalFeed', 'query', { ...queryCriteriaWithoutPage, options: pagingCriteria }],
91
+ {
92
+ posts: postIdsToQuery,
93
+ paging: pagingToken,
94
+ },
95
+ );
96
+
97
+ expect(getCustomRankingGlobalFeed.locally(queryCriteria)).toEqual(
98
+ expect.objectContaining({
99
+ data: postsToQuery,
100
+ prevPage: { before: 55, limit: 10 },
101
+ nextPage: { before: 55, limit: 10 },
102
+ }),
103
+ );
104
+ });
105
+
106
+ test('it should accept undefined query param', async () => {
107
+ client.http.get = jest.fn().mockResolvedValueOnce(resolvedQueryFeedValue);
108
+
109
+ expect(() => getCustomRankingGlobalFeed.locally()).not.toThrow();
110
+ });
111
+
112
+ test(`it shouldn't return if individual feed cache not exist`, () => {
113
+ pushToCache(['globalFeed', 'query', { ...queryCriteriaWithoutPage, options: pagingCriteria }], {
114
+ posts: postIdsToQuery,
115
+ paging: pagingToken,
116
+ });
117
+
118
+ expect(getCustomRankingGlobalFeed.locally(queryCriteria)).toBeUndefined();
119
+ });
120
+
121
+ test('it should return undefined if feed not in cache', () => {
122
+ expect(getCustomRankingGlobalFeed.locally({})).toBeUndefined();
123
+ });
124
+
125
+ test('it should return undefined if cache disabled', () => {
126
+ disableCache();
127
+
128
+ expect(getCustomRankingGlobalFeed.locally({})).toBeUndefined();
129
+ });
130
+ });
@@ -12,7 +12,7 @@ const pagingToken = {
12
12
  const postsToQuery = [post11, post12];
13
13
  const postIdsToQuery = postsToQuery.map(post => post.postId);
14
14
  const pagingCriteria = { limit: 10 };
15
- const queryCriteriaWithoutPage = { useCustomRanking: false };
15
+ const queryCriteriaWithoutPage = {};
16
16
  const queryCriteria = { ...queryCriteriaWithoutPage, page: pagingCriteria };
17
17
 
18
18
  const resolvedQueryFeedValue = {
@@ -69,20 +69,6 @@ describe('queryGlobalFeed', () => {
69
69
  disableCache();
70
70
  });
71
71
 
72
- test('should switch endpoint correctly according to the `useCustomRanking` condition', async () => {
73
- expect.assertions(2);
74
- const resolver = jest.fn().mockResolvedValue(resolvedQueryFeedValue);
75
- client.http.get = resolver;
76
-
77
- await queryGlobalFeed({ ...queryCriteria, useCustomRanking: true });
78
-
79
- expect(resolver).toHaveBeenCalledWith(`/api/v5/me/global-feeds`, expect.any(Object));
80
-
81
- await queryGlobalFeed({ ...queryCriteria, useCustomRanking: false });
82
-
83
- expect(resolver).toHaveBeenCalledWith(`/api/v4/me/global-feeds`, expect.any(Object));
84
- });
85
-
86
72
  test('should throw an error if request fails', async () => {
87
73
  client.http.get = jest.fn().mockRejectedValueOnce(new Error('error'));
88
74
 
@@ -1,6 +1,6 @@
1
1
  export * from './getFile';
2
- export * from './createFile';
2
+ export * from './uploadFile';
3
3
  export * from './deleteFile';
4
4
  export * from './fileUrlWithSize';
5
- export * from './createVideo';
6
- export * from './createImage';
5
+ export * from './uploadVideo';
6
+ export * from './uploadImage';
@@ -0,0 +1,69 @@
1
+ import { disableCache, enableCache, pullFromCache } from '~/cache/api';
2
+ import { client, file12, createEmptyFormData, createFileFormData } from '~/utils/tests';
3
+
4
+ import { uploadFile } from '../uploadFile';
5
+
6
+ const videoToCreate = [file12];
7
+ const createIds = videoToCreate.map(({ fileId }) => fileId);
8
+ const resolvedPayloadValue = { data: videoToCreate };
9
+
10
+ describe('uploadFile', () => {
11
+ test('it should return created file', async () => {
12
+ const formData = createFileFormData();
13
+ client.http.post = jest.fn().mockResolvedValue(resolvedPayloadValue);
14
+
15
+ const received = uploadFile(formData);
16
+
17
+ await expect(received).resolves.toEqual(expect.objectContaining({ data: videoToCreate }));
18
+ });
19
+
20
+ test('it should throw an error if request fails', async () => {
21
+ const formData = createFileFormData();
22
+ client.http.post = jest.fn().mockRejectedValueOnce(new Error('error'));
23
+
24
+ await expect(uploadFile(formData)).rejects.toThrow('error');
25
+ });
26
+
27
+ test('it should throw an error if formData is empty', async () => {
28
+ const emptyFormData = createEmptyFormData();
29
+
30
+ await expect(uploadFile(emptyFormData)).rejects.toThrow(
31
+ 'The formData object must have a `files` key.',
32
+ );
33
+ });
34
+
35
+ test('it should call onProgress params on upload progress updated', async () => {
36
+ expect.assertions(3);
37
+ const formData = createFileFormData();
38
+ const onProgress = jest.fn();
39
+
40
+ jest.spyOn(client.http, 'post').mockImplementationOnce(
41
+ (_, __, config) =>
42
+ new Promise((resolve, _reject) => {
43
+ config?.onUploadProgress?.({ loaded: 0, bytes: 0, total: 100 });
44
+ config?.onUploadProgress?.({ loaded: 40, bytes: 40, total: 100 });
45
+ config?.onUploadProgress?.({ loaded: 100, bytes: 100, total: 100 });
46
+ resolve(resolvedPayloadValue);
47
+ }),
48
+ );
49
+
50
+ await uploadFile(formData, onProgress);
51
+
52
+ expect(onProgress).toHaveBeenNthCalledWith(1, 0);
53
+ expect(onProgress).toHaveBeenNthCalledWith(2, 40);
54
+ expect(onProgress).toHaveBeenNthCalledWith(3, 100);
55
+ });
56
+
57
+ test('it should create cache after created file', async () => {
58
+ enableCache();
59
+ const formData = createFileFormData();
60
+ client.http.post = jest.fn().mockResolvedValue(resolvedPayloadValue);
61
+
62
+ await uploadFile(formData);
63
+ const received = createIds.map(id => pullFromCache(['file', 'get', id])?.data);
64
+
65
+ expect(received).toEqual(expect.objectContaining(videoToCreate));
66
+
67
+ disableCache();
68
+ });
69
+ });
@@ -1,18 +1,18 @@
1
1
  import { disableCache, enableCache, pullFromCache } from '~/cache/api';
2
2
  import { client, file11, createEmptyFormData, createFileFormData } from '~/utils/tests';
3
3
 
4
- import { createImage } from '../createImage';
4
+ import { uploadImage } from '../uploadImage';
5
5
 
6
6
  const imageToCreate = [file11];
7
7
  const createIds = imageToCreate.map(({ fileId }) => fileId);
8
8
  const resolvedPayloadValue = { data: imageToCreate };
9
9
 
10
- describe('createImage', () => {
10
+ describe('uploadImage', () => {
11
11
  test('should return created image', async () => {
12
12
  const formData = createFileFormData();
13
13
  client.http.post = jest.fn().mockResolvedValue(resolvedPayloadValue);
14
14
 
15
- const received = createImage(formData);
15
+ const received = uploadImage(formData);
16
16
 
17
17
  await expect(received).resolves.toEqual(expect.objectContaining({ data: imageToCreate }));
18
18
  });
@@ -21,13 +21,13 @@ describe('createImage', () => {
21
21
  const formData = createFileFormData();
22
22
  client.http.post = jest.fn().mockRejectedValueOnce(new Error('error'));
23
23
 
24
- await expect(createImage(formData)).rejects.toThrow('error');
24
+ await expect(uploadImage(formData)).rejects.toThrow('error');
25
25
  });
26
26
 
27
27
  test('should throw an error if formData is empty', async () => {
28
28
  const emptyFormData = createEmptyFormData();
29
29
 
30
- await expect(createImage(emptyFormData)).rejects.toThrow(
30
+ await expect(uploadImage(emptyFormData)).rejects.toThrow(
31
31
  'The formData object must have a `files` key.',
32
32
  );
33
33
  });
@@ -47,7 +47,7 @@ describe('createImage', () => {
47
47
  }),
48
48
  );
49
49
 
50
- await createImage(formData, onProgress);
50
+ await uploadImage(formData, onProgress);
51
51
 
52
52
  expect(onProgress).toHaveBeenNthCalledWith(1, 0);
53
53
  expect(onProgress).toHaveBeenNthCalledWith(2, 40);
@@ -59,7 +59,7 @@ describe('createImage', () => {
59
59
  const formData = createFileFormData();
60
60
  client.http.post = jest.fn().mockResolvedValue(resolvedPayloadValue);
61
61
 
62
- await createImage(formData);
62
+ await uploadImage(formData);
63
63
  const received = createIds.map(id => pullFromCache(['file', 'get', id])?.data);
64
64
 
65
65
  expect(received).toEqual(expect.objectContaining(imageToCreate));
@@ -2,18 +2,18 @@ import { ContentFeedType } from '~/@types';
2
2
  import { disableCache, enableCache, pullFromCache } from '~/cache/api';
3
3
  import { client, file12, createEmptyFormData, createFileFormData } from '~/utils/tests';
4
4
 
5
- import { createVideo } from '../createVideo';
5
+ import { uploadVideo } from '../uploadVideo';
6
6
 
7
7
  const videoToCreate = [file12];
8
8
  const createIds = videoToCreate.map(({ fileId }) => fileId);
9
9
  const resolvedPayloadValue = { data: videoToCreate };
10
10
 
11
- describe('createVideo', () => {
11
+ describe('uploadVideo', () => {
12
12
  test('should return created video', async () => {
13
13
  const formData = createFileFormData();
14
14
  client.http.post = jest.fn().mockResolvedValue(resolvedPayloadValue);
15
15
 
16
- const received = createVideo(formData);
16
+ const received = uploadVideo(formData);
17
17
 
18
18
  await expect(received).resolves.toEqual(expect.objectContaining({ data: videoToCreate }));
19
19
  });
@@ -22,13 +22,13 @@ describe('createVideo', () => {
22
22
  const formData = createFileFormData();
23
23
  client.http.post = jest.fn().mockRejectedValueOnce(new Error('error'));
24
24
 
25
- await expect(createVideo(formData)).rejects.toThrow('error');
25
+ await expect(uploadVideo(formData)).rejects.toThrow('error');
26
26
  });
27
27
 
28
28
  test('should throw an error if formData is empty', async () => {
29
29
  const emptyFormData = createEmptyFormData();
30
30
 
31
- await expect(createVideo(emptyFormData)).rejects.toThrow(
31
+ await expect(uploadVideo(emptyFormData)).rejects.toThrow(
32
32
  'The formData object must have a `files` key.',
33
33
  );
34
34
  });
@@ -39,7 +39,7 @@ describe('createVideo', () => {
39
39
  const formData = createFileFormData();
40
40
  client.http.post = jest.fn().mockResolvedValue(resolvedPayloadValue);
41
41
 
42
- await createVideo(formData, ContentFeedType.POST);
42
+ await uploadVideo(formData, ContentFeedType.POST);
43
43
 
44
44
  expect(formData.get('feedType')).toEqual(ContentFeedType.POST);
45
45
  });
@@ -59,7 +59,7 @@ describe('createVideo', () => {
59
59
  }),
60
60
  );
61
61
 
62
- await createVideo(formData, undefined, onProgress);
62
+ await uploadVideo(formData, undefined, onProgress);
63
63
 
64
64
  expect(onProgress).toHaveBeenNthCalledWith(1, 0);
65
65
  expect(onProgress).toHaveBeenNthCalledWith(2, 40);
@@ -71,7 +71,7 @@ describe('createVideo', () => {
71
71
  const formData = createFileFormData();
72
72
  client.http.post = jest.fn().mockResolvedValue(resolvedPayloadValue);
73
73
 
74
- await createVideo(formData);
74
+ await uploadVideo(formData);
75
75
  const received = createIds.map(id => pullFromCache(['file', 'get', id])?.data);
76
76
 
77
77
  expect(received).toEqual(expect.objectContaining(videoToCreate));
@@ -7,8 +7,8 @@ import { ingestInCache } from '~/cache/api/ingestInCache';
7
7
  */
8
8
  /**
9
9
  * ```js
10
- * import { createFile } from '@amityco/ts-sdk'
11
- * const created = await createFile(formData)
10
+ * import { FileRepository } from '@amityco/ts-sdk'
11
+ * const created = await FileRepository.uploadFile(formData)
12
12
  * ```
13
13
  *
14
14
  * Creates an {@link Amity.File}
@@ -20,12 +20,12 @@ import { ingestInCache } from '~/cache/api/ingestInCache';
20
20
  * @category File API
21
21
  * @async
22
22
  */
23
- export const createFile = async <T extends Amity.FileType = any>(
23
+ export const uploadFile = async <T extends Amity.FileType = any>(
24
24
  formData: FormData,
25
25
  onProgress?: (percent: number) => void,
26
26
  ): Promise<Amity.Cached<Amity.File[]>> => {
27
27
  const client = getActiveClient();
28
- client.log('file/createFile', formData);
28
+ client.log('file/uploadFile', formData);
29
29
 
30
30
  if (!formData.getAll('files').length)
31
31
  throw new Error('The formData object must have a `files` key.');
@@ -54,5 +54,3 @@ export const createFile = async <T extends Amity.FileType = any>(
54
54
  };
55
55
  };
56
56
  /* end_public_function */
57
-
58
- // TODO: consider doing local creation with URL.createObjectURL()