@amityco/ts-sdk 0.0.1-beta.36 → 0.0.1-beta.38

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 (279) hide show
  1. package/.eslintrc.json +3 -5
  2. package/dist/@types/core/errors.d.ts +1 -0
  3. package/dist/@types/core/errors.d.ts.map +1 -1
  4. package/dist/@types/core/events.d.ts +5 -0
  5. package/dist/@types/core/events.d.ts.map +1 -1
  6. package/dist/@types/domains/category.d.ts +7 -0
  7. package/dist/@types/domains/category.d.ts.map +1 -1
  8. package/dist/@types/domains/client.d.ts +21 -1
  9. package/dist/@types/domains/client.d.ts.map +1 -1
  10. package/dist/@types/domains/community.d.ts +12 -0
  11. package/dist/@types/domains/community.d.ts.map +1 -1
  12. package/dist/@types/global.d.ts +12 -0
  13. package/dist/@types/global.d.ts.map +1 -1
  14. package/dist/category/api/queryCategories.d.ts +1 -5
  15. package/dist/category/api/queryCategories.d.ts.map +1 -1
  16. package/dist/category/observers/index.d.ts +2 -0
  17. package/dist/category/observers/index.d.ts.map +1 -0
  18. package/dist/category/observers/liveCategories.d.ts +18 -0
  19. package/dist/category/observers/liveCategories.d.ts.map +1 -0
  20. package/dist/category/observers/tests/liveCategories.test.d.ts +2 -0
  21. package/dist/category/observers/tests/liveCategories.test.d.ts.map +1 -0
  22. package/dist/channel/api/tests/getChannels.test.d.ts +2 -0
  23. package/dist/channel/api/tests/getChannels.test.d.ts.map +1 -0
  24. package/dist/channel/api/tests/leaveChannel.test.d.ts +2 -0
  25. package/dist/channel/api/tests/leaveChannel.test.d.ts.map +1 -0
  26. package/dist/channel/observers/liveChannel.d.ts.map +1 -1
  27. package/dist/client/api/accessTokenExpiryWatcher.d.ts +7 -0
  28. package/dist/client/api/accessTokenExpiryWatcher.d.ts.map +1 -0
  29. package/dist/client/api/activeUser.d.ts +1 -1
  30. package/dist/client/api/activeUser.d.ts.map +1 -1
  31. package/dist/client/api/connectClient.d.ts +1 -1
  32. package/dist/client/api/connectClient.d.ts.map +1 -1
  33. package/dist/client/api/createClient.d.ts +1 -1
  34. package/dist/client/api/createClient.d.ts.map +1 -1
  35. package/dist/client/api/disconnectClient.d.ts +0 -1
  36. package/dist/client/api/disconnectClient.d.ts.map +1 -1
  37. package/dist/client/api/getToken.d.ts +7 -5
  38. package/dist/client/api/getToken.d.ts.map +1 -1
  39. package/dist/client/api/index.d.ts +1 -0
  40. package/dist/client/api/index.d.ts.map +1 -1
  41. package/dist/client/api/renewal.d.ts +2 -0
  42. package/dist/client/api/renewal.d.ts.map +1 -0
  43. package/dist/client/api/setSessionState.d.ts +12 -0
  44. package/dist/client/api/setSessionState.d.ts.map +1 -0
  45. package/dist/client/api/terminateClient.d.ts +9 -0
  46. package/dist/client/api/terminateClient.d.ts.map +1 -0
  47. package/dist/client/api/tests/accessTokenExpiryWatcher.test.d.ts +2 -0
  48. package/dist/client/api/tests/accessTokenExpiryWatcher.test.d.ts.map +1 -0
  49. package/dist/client/api/tests/connectClient.test.d.ts +2 -0
  50. package/dist/client/api/tests/connectClient.test.d.ts.map +1 -0
  51. package/dist/client/api/tests/disconnectClient.test.d.ts +2 -0
  52. package/dist/client/api/tests/disconnectClient.test.d.ts.map +1 -0
  53. package/dist/client/api/tests/getToken.test.d.ts +2 -0
  54. package/dist/client/api/tests/getToken.test.d.ts.map +1 -0
  55. package/dist/client/api/tests/renewal.test.d.ts +2 -0
  56. package/dist/client/api/tests/renewal.test.d.ts.map +1 -0
  57. package/dist/client/api/tests/setSessionState.test.d.ts +2 -0
  58. package/dist/client/api/tests/setSessionState.test.d.ts.map +1 -0
  59. package/dist/client/api/tests/terminateClient.test.d.ts +2 -0
  60. package/dist/client/api/tests/terminateClient.test.d.ts.map +1 -0
  61. package/dist/client/events/index.d.ts +1 -0
  62. package/dist/client/events/index.d.ts.map +1 -1
  63. package/dist/client/events/onClientBanned.d.ts +1 -1
  64. package/dist/client/events/onClientBanned.d.ts.map +1 -1
  65. package/dist/client/events/onSessionStateChange.d.ts +17 -0
  66. package/dist/client/events/onSessionStateChange.d.ts.map +1 -0
  67. package/dist/client/events/onTokenExpired.d.ts +17 -0
  68. package/dist/client/events/onTokenExpired.d.ts.map +1 -0
  69. package/dist/client/events/onTokenTerminated.d.ts +11 -0
  70. package/dist/client/events/onTokenTerminated.d.ts.map +1 -0
  71. package/dist/client/events/tests/onSessionStateChange.test.d.ts +2 -0
  72. package/dist/client/events/tests/onSessionStateChange.test.d.ts.map +1 -0
  73. package/dist/client/events/tests/onTokenTerminated.test.d.ts +2 -0
  74. package/dist/client/events/tests/onTokenTerminated.test.d.ts.map +1 -0
  75. package/dist/client/utils/setClientToken.d.ts +19 -0
  76. package/dist/client/utils/setClientToken.d.ts.map +1 -0
  77. package/dist/comment/api/deleteComment.d.ts.map +1 -1
  78. package/dist/comment/api/getComment.d.ts.map +1 -1
  79. package/dist/comment/events/tests/onCommentDeleted.test.d.ts +2 -0
  80. package/dist/comment/events/tests/onCommentDeleted.test.d.ts.map +1 -0
  81. package/dist/comment/observers/index.d.ts +1 -0
  82. package/dist/comment/observers/index.d.ts.map +1 -1
  83. package/dist/comment/observers/liveComment.d.ts +21 -0
  84. package/dist/comment/observers/liveComment.d.ts.map +1 -0
  85. package/dist/comment/observers/tests/liveComment.test.d.ts +2 -0
  86. package/dist/comment/observers/tests/liveComment.test.d.ts.map +1 -0
  87. package/dist/community/api/queryCommunities.d.ts +1 -10
  88. package/dist/community/api/queryCommunities.d.ts.map +1 -1
  89. package/dist/community/events/index.d.ts +1 -0
  90. package/dist/community/events/index.d.ts.map +1 -1
  91. package/dist/community/events/onCommunityUserChanged.d.ts +17 -0
  92. package/dist/community/events/onCommunityUserChanged.d.ts.map +1 -0
  93. package/dist/community/events/utils.d.ts +1 -0
  94. package/dist/community/events/utils.d.ts.map +1 -1
  95. package/dist/community/observers/index.d.ts +1 -0
  96. package/dist/community/observers/index.d.ts.map +1 -1
  97. package/dist/community/observers/liveCommunities.d.ts +20 -0
  98. package/dist/community/observers/liveCommunities.d.ts.map +1 -0
  99. package/dist/community/observers/tests/liveCommunities.test.d.ts +2 -0
  100. package/dist/community/observers/tests/liveCommunities.test.d.ts.map +1 -0
  101. package/dist/core/events.d.ts +3 -3
  102. package/dist/core/events.d.ts.map +1 -1
  103. package/dist/core/query/sorting.d.ts +6 -0
  104. package/dist/core/query/sorting.d.ts.map +1 -1
  105. package/dist/core/subscription.d.ts.map +1 -1
  106. package/dist/core/transports/http.d.ts +0 -5
  107. package/dist/core/transports/http.d.ts.map +1 -1
  108. package/dist/file/api/test/createImage.test.d.ts +2 -0
  109. package/dist/file/api/test/createImage.test.d.ts.map +1 -0
  110. package/dist/file/api/test/createVideo.test.d.ts +2 -0
  111. package/dist/file/api/test/createVideo.test.d.ts.map +1 -0
  112. package/dist/index.cjs.js +944 -332
  113. package/dist/index.d.ts +1 -0
  114. package/dist/index.d.ts.map +1 -1
  115. package/dist/index.esm.js +937 -332
  116. package/dist/index.umd.js +4 -4
  117. package/dist/message/observers/liveMessage.d.ts.map +1 -1
  118. package/dist/post/observers/index.d.ts +1 -0
  119. package/dist/post/observers/index.d.ts.map +1 -1
  120. package/dist/post/observers/livePost.d.ts +21 -0
  121. package/dist/post/observers/livePost.d.ts.map +1 -0
  122. package/dist/post/observers/tests/livePost.test.d.ts +2 -0
  123. package/dist/post/observers/tests/livePost.test.d.ts.map +1 -0
  124. package/dist/stream/api/tests/createStream.test.d.ts +2 -0
  125. package/dist/stream/api/tests/createStream.test.d.ts.map +1 -0
  126. package/dist/stream/api/tests/deleteStream.test.d.ts +2 -0
  127. package/dist/stream/api/tests/deleteStream.test.d.ts.map +1 -0
  128. package/dist/stream/api/tests/getStream.test.d.ts +2 -0
  129. package/dist/stream/api/tests/getStream.test.d.ts.map +1 -0
  130. package/dist/subChannel/api/tests/createSubChannel.test.d.ts +2 -0
  131. package/dist/subChannel/api/tests/createSubChannel.test.d.ts.map +1 -0
  132. package/dist/subChannel/api/tests/deleteSubChannel.test.d.ts +2 -0
  133. package/dist/subChannel/api/tests/deleteSubChannel.test.d.ts.map +1 -0
  134. package/dist/subChannel/api/tests/getSubChannel.test.d.ts +2 -0
  135. package/dist/subChannel/api/tests/getSubChannel.test.d.ts.map +1 -0
  136. package/dist/subChannel/api/tests/getSubChannels.test.d.ts +2 -0
  137. package/dist/subChannel/api/tests/getSubChannels.test.d.ts.map +1 -0
  138. package/dist/subChannel/api/tests/updateSubChannel.test.d.ts +2 -0
  139. package/dist/subChannel/api/tests/updateSubChannel.test.d.ts.map +1 -0
  140. package/dist/subChannel/observers/liveSubChannel.d.ts.map +1 -1
  141. package/dist/user/api/tests/updateUser.test.d.ts +2 -0
  142. package/dist/user/api/tests/updateUser.test.d.ts.map +1 -0
  143. package/dist/user/observers/liveUser.d.ts.map +1 -1
  144. package/dist/utils/constants.d.ts +2 -0
  145. package/dist/utils/constants.d.ts.map +1 -1
  146. package/dist/utils/liveObject.d.ts +2 -0
  147. package/dist/utils/liveObject.d.ts.map +1 -0
  148. package/dist/utils/tests/client.d.ts.map +1 -1
  149. package/dist/utils/tests/dummy/category.d.ts +64 -0
  150. package/dist/utils/tests/dummy/category.d.ts.map +1 -0
  151. package/dist/utils/tests/dummy/channel.d.ts +50 -0
  152. package/dist/utils/tests/dummy/channel.d.ts.map +1 -1
  153. package/dist/utils/tests/dummy/community.d.ts +132 -0
  154. package/dist/utils/tests/dummy/community.d.ts.map +1 -1
  155. package/dist/utils/tests/dummy/file.d.ts +3 -0
  156. package/dist/utils/tests/dummy/file.d.ts.map +1 -1
  157. package/dist/utils/tests/dummy/index.d.ts +3 -0
  158. package/dist/utils/tests/dummy/index.d.ts.map +1 -1
  159. package/dist/utils/tests/dummy/post.d.ts +2 -0
  160. package/dist/utils/tests/dummy/post.d.ts.map +1 -1
  161. package/dist/utils/tests/dummy/stream.d.ts +83 -0
  162. package/dist/utils/tests/dummy/stream.d.ts.map +1 -0
  163. package/dist/utils/tests/dummy/token.d.ts +11 -0
  164. package/dist/utils/tests/dummy/token.d.ts.map +1 -0
  165. package/dist/utils/tests/dummy/user.d.ts +18 -0
  166. package/dist/utils/tests/dummy/user.d.ts.map +1 -1
  167. package/dist/utils/tests/liveObject.test.d.ts +2 -0
  168. package/dist/utils/tests/liveObject.test.d.ts.map +1 -0
  169. package/package.json +4 -4
  170. package/src/@types/core/errors.ts +1 -0
  171. package/src/@types/core/events.ts +7 -0
  172. package/src/@types/domains/category.ts +13 -0
  173. package/src/@types/domains/client.ts +45 -1
  174. package/src/@types/domains/community.ts +25 -0
  175. package/src/@types/global.ts +19 -0
  176. package/src/category/api/queryCategories.ts +3 -5
  177. package/src/category/observers/index.ts +1 -0
  178. package/src/category/observers/liveCategories.ts +141 -0
  179. package/src/category/observers/tests/liveCategories.test.ts +147 -0
  180. package/src/channel/api/tests/createChannel.test.ts +30 -6
  181. package/src/channel/api/tests/getChannel.test.ts +3 -1
  182. package/src/channel/api/tests/getChannels.test.ts +97 -0
  183. package/src/channel/api/tests/joinChannel.test.ts +62 -3
  184. package/src/channel/api/tests/leaveChannel.test.ts +90 -0
  185. package/src/channel/api/tests/queryChannels.test.ts +38 -1
  186. package/src/channel/observers/liveChannel.ts +8 -80
  187. package/src/client/api/accessTokenExpiryWatcher.ts +85 -0
  188. package/src/client/api/activeUser.ts +1 -1
  189. package/src/client/api/connectClient.ts +105 -24
  190. package/src/client/api/createClient.ts +9 -1
  191. package/src/client/api/disconnectClient.ts +26 -2
  192. package/src/client/api/getToken.ts +6 -6
  193. package/src/client/api/index.ts +2 -0
  194. package/src/client/api/renewal.ts +74 -0
  195. package/src/client/api/setSessionState.ts +75 -0
  196. package/src/client/api/terminateClient.ts +20 -0
  197. package/src/client/api/tests/accessTokenExpiryWatcher.test.ts +132 -0
  198. package/src/client/api/tests/connectClient.test.ts +84 -0
  199. package/src/client/api/tests/createClient.test.ts +8 -0
  200. package/src/client/api/tests/disconnectClient.test.ts +78 -0
  201. package/src/client/api/tests/getToken.test.ts +36 -0
  202. package/src/client/api/tests/renewal.test.ts +67 -0
  203. package/src/client/api/tests/setSessionState.test.ts +62 -0
  204. package/src/client/api/tests/terminateClient.test.ts +29 -0
  205. package/src/client/events/index.ts +2 -0
  206. package/src/client/events/onClientBanned.ts +12 -5
  207. package/src/client/events/onSessionStateChange.ts +31 -0
  208. package/src/client/events/onTokenExpired.ts +26 -0
  209. package/src/client/events/onTokenTerminated.ts +20 -0
  210. package/src/client/events/tests/onSessionStateChange.test.ts +37 -0
  211. package/src/client/events/tests/onTokenTerminated.test.ts +37 -0
  212. package/src/client/tests/connectClient.test.ts +6 -1
  213. package/src/client/utils/setClientToken.ts +39 -0
  214. package/src/comment/api/deleteComment.ts +5 -5
  215. package/src/comment/api/getComment.ts +8 -3
  216. package/src/comment/events/tests/onCommentDeleted.test.ts +27 -0
  217. package/src/comment/observers/index.ts +1 -0
  218. package/src/comment/observers/liveComment.ts +43 -0
  219. package/src/comment/observers/tests/liveComment.test.ts +95 -0
  220. package/src/community/api/queryCommunities.ts +3 -10
  221. package/src/community/api/test/addCommunityMember.test.ts +14 -2
  222. package/src/community/api/test/joinCommunity.test.ts +14 -2
  223. package/src/community/api/test/leaveCommunity.test.ts +11 -1
  224. package/src/community/api/test/removeCommunityMembers.test.ts +11 -1
  225. package/src/community/events/index.ts +1 -0
  226. package/src/community/events/onCommunityUserChanged.ts +20 -0
  227. package/src/community/events/test/onCommunityJoined.test.ts +1 -1
  228. package/src/community/events/test/onCommunityUserAdded.test.ts +1 -1
  229. package/src/community/events/test/onCommunityUserBanned.test.ts +1 -1
  230. package/src/community/events/test/onCommunityUserUnbaned.test.ts +1 -1
  231. package/src/community/events/test/utils.test.ts +52 -3
  232. package/src/community/events/utils.ts +49 -0
  233. package/src/community/observers/index.ts +1 -0
  234. package/src/community/observers/liveCommunities.ts +188 -0
  235. package/src/community/observers/tests/liveCommunities.test.ts +284 -0
  236. package/src/core/events.ts +5 -3
  237. package/src/core/query/sorting.ts +8 -0
  238. package/src/core/subscription.ts +3 -1
  239. package/src/core/transports/http.ts +52 -13
  240. package/src/core/transports/mqtt.ts +1 -1
  241. package/src/core/transports/test/http.test.ts +49 -60
  242. package/src/external/api/createUserToken.ts +2 -2
  243. package/src/file/api/createFile.ts +1 -1
  244. package/src/file/api/createImage.ts +1 -1
  245. package/src/file/api/createVideo.ts +1 -1
  246. package/src/file/api/test/createImage.test.ts +69 -0
  247. package/src/file/api/test/createVideo.test.ts +81 -0
  248. package/src/index.ts +1 -0
  249. package/src/message/observers/liveMessage.ts +11 -83
  250. package/src/message/tests/observers/liveMessage.test.ts +1 -143
  251. package/src/post/observers/index.ts +1 -0
  252. package/src/post/observers/livePost.ts +47 -0
  253. package/src/post/observers/tests/livePost.test.ts +97 -0
  254. package/src/stream/api/tests/createStream.test.ts +22 -0
  255. package/src/stream/api/tests/deleteStream.test.ts +50 -0
  256. package/src/stream/api/tests/getStream.test.ts +23 -0
  257. package/src/subChannel/api/tests/createSubChannel.test.ts +110 -0
  258. package/src/subChannel/api/tests/deleteSubChannel.test.ts +112 -0
  259. package/src/subChannel/api/tests/getSubChannel.test.ts +97 -0
  260. package/src/subChannel/api/tests/getSubChannels.test.ts +97 -0
  261. package/src/subChannel/api/tests/updateSubChannel.test.ts +86 -0
  262. package/src/subChannel/observers/liveSubChannel.ts +6 -56
  263. package/src/subChannel/observers/tests/liveSubChannel.test.ts +0 -82
  264. package/src/user/api/tests/updateUser.test.ts +60 -0
  265. package/src/user/observers/liveUser.ts +9 -61
  266. package/src/user/tests/observers/liveUser.test.ts +1 -154
  267. package/src/utils/constants.ts +2 -0
  268. package/src/utils/liveObject.ts +86 -0
  269. package/src/utils/tests/client.ts +18 -2
  270. package/src/utils/tests/dummy/category.ts +57 -0
  271. package/src/utils/tests/dummy/channel.ts +51 -1
  272. package/src/utils/tests/dummy/community.ts +94 -0
  273. package/src/utils/tests/dummy/file.ts +32 -0
  274. package/src/utils/tests/dummy/index.ts +4 -0
  275. package/src/utils/tests/dummy/post.ts +56 -45
  276. package/src/utils/tests/dummy/stream.ts +86 -0
  277. package/src/utils/tests/dummy/token.ts +12 -0
  278. package/src/utils/tests/dummy/user.ts +21 -0
  279. package/src/utils/tests/liveObject.test.ts +172 -0
@@ -1,7 +1,4 @@
1
- import { getActiveClient } from '~/client/api';
2
- import { createQuery, runQuery } from '~/core/query';
3
- import { LIVE_OBJECT_ENABLE_CACHE_MESSAGE } from '~/utils/constants';
4
- import { hasUpdates } from '~/core/model';
1
+ import { liveObject } from '~/utils/liveObject';
5
2
  import { getSubChannel } from '../api';
6
3
  import { onSubChannelDeleted, onSubChannelUpdated } from '../events';
7
4
  import { onSubChannelFetched } from '../events/onSubChannelFetched';
@@ -29,56 +26,9 @@ export const liveSubChannel = (
29
26
  subChannelId: Amity.SubChannel['subChannelId'],
30
27
  callback: Amity.LiveObjectCallback<Amity.SubChannel>,
31
28
  ): Amity.Unsubscriber => {
32
- const { log, cache } = getActiveClient();
33
- const timestamp = Date.now();
34
- log(`liveSubChannel(tmpid: ${timestamp}) > listen`);
35
-
36
- if (!cache) {
37
- console.log(LIVE_OBJECT_ENABLE_CACHE_MESSAGE);
38
- }
39
-
40
- let subChannel: Amity.SubChannel;
41
- const disposers: Amity.Unsubscriber[] = [];
42
-
43
- const dispatcher = (data: Amity.LiveObject<Amity.SubChannel>) => {
44
- subChannel = data.data;
45
- callback(data);
46
- };
47
-
48
- const realtimeRouter = (eventSubChannel: Amity.SubChannel) => {
49
- if (subChannelId !== eventSubChannel.subChannelId) {
50
- return;
51
- }
52
-
53
- if (subChannel && !hasUpdates(subChannel, eventSubChannel)) {
54
- return;
55
- }
56
-
57
- dispatcher({ loading: false, data: eventSubChannel, origin: 'event' });
58
- };
59
-
60
- const onFetch = () => {
61
- const query = createQuery(getSubChannel, subChannelId);
62
-
63
- runQuery(query, ({ error, data, loading, origin }) => {
64
- dispatcher({ error, data, loading, origin });
65
-
66
- if (error) {
67
- disposers.forEach(fn => fn());
68
- }
69
- });
70
- };
71
-
72
- disposers.push(
73
- onSubChannelFetched(realtimeRouter),
74
- onSubChannelUpdated(realtimeRouter),
75
- onSubChannelDeleted(realtimeRouter),
76
- );
77
-
78
- onFetch();
79
-
80
- return () => {
81
- log(`liveSubChannel(tmpid: ${timestamp}) > dispose`);
82
- disposers.forEach(fn => fn());
83
- };
29
+ return liveObject(subChannelId, callback, 'subChannelId', getSubChannel, [
30
+ onSubChannelFetched,
31
+ onSubChannelUpdated,
32
+ onSubChannelDeleted,
33
+ ]);
84
34
  };
@@ -1,4 +1,3 @@
1
- import { ASCApiError } from '~/core/errors';
2
1
  import { disableCache, enableCache } from '~/cache/api';
3
2
  import {
4
3
  pause,
@@ -30,27 +29,6 @@ describe('liveSubChannel', () => {
30
29
 
31
30
  afterEach(disableCache);
32
31
 
33
- test('should get sub channel', async () => {
34
- const callback = jest.fn();
35
- client.http.get = jest.fn().mockResolvedValue(response);
36
-
37
- liveSubChannel(rawSubChannel.messageFeedId, callback);
38
- await pause();
39
-
40
- expect(callback).toHaveBeenCalledTimes(2);
41
- expect(callback).toHaveBeenNthCalledWith(
42
- 1,
43
- expect.objectContaining({ data: undefined, loading: true }),
44
- );
45
- expect(callback).toHaveBeenNthCalledWith(
46
- 2,
47
- expect.objectContaining({
48
- data: convertFromRaw(rawSubChannel),
49
- loading: false,
50
- }),
51
- );
52
- });
53
-
54
32
  const events: [string, keyof Amity.Events][] = [
55
33
  ['should get update on message-feed.updated event', 'message-feed.updated'],
56
34
  ['should get update on message-feed.deleted event', 'message-feed.deleted'],
@@ -149,64 +127,4 @@ describe('liveSubChannel', () => {
149
127
  );
150
128
  });
151
129
  });
152
-
153
- test('should not get update on api failure', async () => {
154
- const error = new ASCApiError(
155
- 'server error!',
156
- Amity.ServerError.ITEM_NOT_FOUND,
157
- Amity.ErrorLevel.ERROR,
158
- );
159
- const update = {
160
- ...rawSubChannel,
161
- name: 'new name',
162
- updatedAt: getFutureDate(rawSubChannel.updatedAt),
163
- };
164
- const callback = jest.fn();
165
- client.http.get = jest.fn().mockRejectedValue(error);
166
-
167
- liveSubChannel(subChannel.subChannelId, callback);
168
- await pause();
169
- client.emitter.emit('message-feed.updated', { messageFeeds: [update] });
170
- await pause();
171
-
172
- expect(callback).toHaveBeenCalledTimes(2);
173
- expect(callback).toHaveBeenNthCalledWith(
174
- 2,
175
- expect.objectContaining({
176
- data: undefined,
177
- error,
178
- loading: false,
179
- }),
180
- );
181
- });
182
-
183
- test('should not call callback if liveMessage is disposed', async () => {
184
- const update = {
185
- ...rawSubChannel,
186
- name: 'new name',
187
- updatedAt: getFutureDate(rawSubChannel.updatedAt),
188
- };
189
- const callback = jest.fn();
190
- client.http.get = jest.fn().mockResolvedValue(response);
191
-
192
- const dispose = liveSubChannel(subChannel.subChannelId, callback);
193
- await pause();
194
- dispose();
195
- client.emitter.emit('message-feed.updated', { messageFeeds: [update] });
196
- await pause();
197
-
198
- expect(callback).toHaveBeenCalledTimes(2);
199
- });
200
-
201
- test('should not call callback if data is the same', async () => {
202
- const callback = jest.fn();
203
- client.http.get = jest.fn().mockResolvedValue(response);
204
-
205
- liveSubChannel(subChannel.subChannelId, callback);
206
- await pause();
207
- client.emitter.emit('message-feed.updated', { messageFeeds: response.data.messageFeeds });
208
- await pause();
209
-
210
- expect(callback).toHaveBeenCalledTimes(2);
211
- });
212
130
  });
@@ -0,0 +1,60 @@
1
+ import { disableCache, enableCache, pushToCache, pullFromCache } from '~/cache/api';
2
+
3
+ import { client, userUpdateResponse } from '~/utils/tests';
4
+
5
+ import { updateUser } from '../updateUser';
6
+ import { onUserUpdated } from '../../events/onUserUpdated';
7
+
8
+ describe('updateUser', () => {
9
+ const displayName = 'updated-display-name';
10
+ const userId = 'test-user';
11
+ const avatarCustomUrl = 'updated-avatarUrl';
12
+
13
+ // integration_test_id: a1a8260f-3314-41ba-9f5f-3a96dd52453d
14
+ test('it should return updated user on success', async () => {
15
+ const { users: expected } = userUpdateResponse.data;
16
+ client.http.put = jest.fn().mockResolvedValue(userUpdateResponse);
17
+
18
+ const { data: received } = await updateUser(userId, { displayName, avatarCustomUrl });
19
+
20
+ expect(received).toStrictEqual(expected[0]);
21
+ });
22
+
23
+ // integration_test_id: 67cb7ad8-28a9-4950-a86c-35497bb5212c
24
+ test('it should return 400301 when updating another user', async () => {
25
+ client.http.put = jest.fn().mockRejectedValueOnce(new Error('400301'));
26
+
27
+ await expect(
28
+ updateUser('different-user', { displayName: 'updated-display-name' }),
29
+ ).rejects.toThrow('400301');
30
+ });
31
+
32
+ test('it should update cache with updated user', async () => {
33
+ enableCache();
34
+
35
+ const expected = userUpdateResponse.data.users[0];
36
+ pushToCache(['user', 'get', userId], { ...expected, displayName: 'old-displayName' });
37
+
38
+ client.http.put = jest.fn().mockResolvedValue(userUpdateResponse);
39
+ await updateUser(userId, { displayName, avatarCustomUrl });
40
+
41
+ const received = pullFromCache(['user', 'get', userId])?.data;
42
+
43
+ expect(received).toStrictEqual(expected);
44
+ disableCache();
45
+ });
46
+
47
+ test('it should fire event for updated user', async () => {
48
+ let dispose;
49
+ const { users: expected } = userUpdateResponse.data;
50
+ client.http.put = jest.fn().mockResolvedValue(userUpdateResponse);
51
+
52
+ const callbackPromise = new Promise(resolve => {
53
+ dispose = onUserUpdated(resolve);
54
+ }).finally(dispose);
55
+
56
+ await updateUser(userId, { displayName, avatarCustomUrl });
57
+
58
+ await expect(callbackPromise).resolves.toEqual(expect.objectContaining(expected[0]));
59
+ });
60
+ });
@@ -1,9 +1,4 @@
1
- import { getActiveClient } from '~/client/api';
2
- import { createQuery, runQuery } from '~/core/query';
3
-
4
- import { LIVE_OBJECT_ENABLE_CACHE_MESSAGE } from '~/utils/constants';
5
-
6
- import { hasUpdates } from '~/core/model';
1
+ import { liveObject } from '~/utils/liveObject';
7
2
  import {
8
3
  onUserDeleted,
9
4
  onUserUpdated,
@@ -37,59 +32,12 @@ export const liveUser = (
37
32
  userId: Amity.User['userId'],
38
33
  callback: Amity.LiveObjectCallback<Amity.User>,
39
34
  ): Amity.Unsubscriber => {
40
- const { log, cache } = getActiveClient();
41
- const timestamp = Date.now();
42
- log(`liveUser(tmpid: ${timestamp}) > listen`);
43
-
44
- if (!cache) {
45
- console.log(LIVE_OBJECT_ENABLE_CACHE_MESSAGE);
46
- }
47
-
48
- let user: Amity.User;
49
- const disposers: Amity.Unsubscriber[] = [];
50
-
51
- const dispatcher = (data: Amity.LiveObject<Amity.User>) => {
52
- user = data.data;
53
- callback(data);
54
- };
55
-
56
- const realtimeRouter = (eventUser: Amity.User) => {
57
- if (userId !== eventUser.userId) {
58
- return;
59
- }
60
-
61
- if (user && !hasUpdates(user, eventUser)) {
62
- return;
63
- }
64
-
65
- dispatcher({ loading: false, data: eventUser, origin: 'event' });
66
- };
67
-
68
- const onFetch = () => {
69
- const query = createQuery(getUser, userId, true);
70
-
71
- runQuery(query, ({ loading, data, error, origin }) => {
72
- dispatcher({ loading, data, origin, error });
73
-
74
- if (error) {
75
- disposers.forEach(fn => fn());
76
- }
77
- });
78
- };
79
-
80
- disposers.push(
81
- onUserFetched(realtimeRouter),
82
- onUserUpdated(realtimeRouter),
83
- onUserDeleted(realtimeRouter),
84
- onUserFlagged(realtimeRouter),
85
- onUserUnflagged(realtimeRouter),
86
- onUserFlagCleared(realtimeRouter),
87
- );
88
-
89
- onFetch();
90
-
91
- return () => {
92
- log(`liveUser(tmpid: ${timestamp}) > dispose`);
93
- disposers.forEach(fn => fn());
94
- };
35
+ return liveObject(userId, callback, 'userId', getUser, [
36
+ onUserFetched,
37
+ onUserUpdated,
38
+ onUserDeleted,
39
+ onUserFlagged,
40
+ onUserUnflagged,
41
+ onUserFlagCleared,
42
+ ]);
95
43
  };
@@ -1,6 +1,4 @@
1
- import { ASCApiError } from '~/core/errors';
2
1
  import { disableCache, enableCache } from '~/cache/api';
3
- import { LIVE_OBJECT_ENABLE_CACHE_MESSAGE } from '~/utils/constants';
4
2
  import {
5
3
  client,
6
4
  connectClient,
@@ -29,161 +27,10 @@ describe('liveUser', () => {
29
27
  await disconnectClient();
30
28
  });
31
29
 
32
- beforeEach(async () => {
33
- enableCache();
34
- });
30
+ beforeEach(enableCache);
35
31
 
36
32
  afterEach(disableCache);
37
33
 
38
- test('it should show user if cache not enabled', () => {
39
- /*
40
- * NOTE: at the time of writing this test cache is diabled by default, but
41
- * there is a proposal to enable cache by default. So I'm disabling cache
42
- * here to ensure cache is disabled
43
- */
44
- disableCache();
45
-
46
- const callback = jest.fn();
47
- jest.spyOn(global.console, 'log');
48
- client.http.get = jest.fn();
49
-
50
- // call liveUser check if mocked console get's called with the correct
51
- // user
52
- client.use();
53
- liveUser(defaultUser.userId, callback);
54
-
55
- expect(console.log).toBeCalledWith(LIVE_OBJECT_ENABLE_CACHE_MESSAGE);
56
- });
57
-
58
- test('it should return user live object', async () => {
59
- const snapshot = getSnapshot();
60
-
61
- // mock response of queryUsers and validate
62
- const callback = jest.fn();
63
- client.http.get = jest.fn().mockResolvedValue(userQueryResponse);
64
-
65
- liveUser(defaultUser.userId, callback);
66
-
67
- expect(callback).toHaveBeenCalledTimes(1);
68
-
69
- // check if cache data returned (should be empty)
70
- expect(callback).toHaveBeenCalledWith(expect.objectContaining(snapshot));
71
-
72
- await pause();
73
-
74
- expect(callback).toHaveBeenCalledTimes(2);
75
-
76
- snapshot.loading = false;
77
- snapshot.data = defaultUser;
78
-
79
- expect(callback).toHaveBeenCalledWith(expect.objectContaining(snapshot));
80
- });
81
-
82
- test('it should return error on api failure', async () => {
83
- const snapshot = getSnapshot();
84
- const error = new ASCApiError(
85
- 'server error!',
86
- Amity.ServerError.ITEM_NOT_FOUND,
87
- Amity.ErrorLevel.ERROR,
88
- );
89
-
90
- // mock response of queryUsers and validate
91
- const callback = jest.fn();
92
- client.http.get = jest.fn().mockRejectedValue(error);
93
-
94
- liveUser(defaultUser.userId, callback);
95
-
96
- expect(callback).toHaveBeenCalledTimes(1);
97
-
98
- // check if cache data returned (should be empty)
99
- expect(callback).toHaveBeenCalledWith(expect.objectContaining(snapshot));
100
-
101
- await pause();
102
-
103
- expect(callback).toHaveBeenCalledTimes(2);
104
-
105
- snapshot.error = error;
106
- snapshot.loading = false;
107
- expect(callback).toHaveBeenLastCalledWith(expect.objectContaining(snapshot));
108
- });
109
-
110
- test('it should terminate updates on api failure', async () => {
111
- const snapshot = getSnapshot();
112
- const error = new ASCApiError(
113
- 'server error!',
114
- Amity.ServerError.ITEM_NOT_FOUND,
115
- Amity.ErrorLevel.ERROR,
116
- );
117
-
118
- // mock response of queryUsers and validate
119
- const callback = jest.fn();
120
- client.http.get = jest.fn().mockRejectedValue(error);
121
-
122
- liveUser(defaultUser.userId, callback);
123
-
124
- expect(callback).toHaveBeenCalledTimes(1);
125
-
126
- // check if cache data returned (should be empty)
127
- expect(callback).toHaveBeenCalledWith(expect.objectContaining(snapshot));
128
-
129
- await pause();
130
-
131
- expect(callback).toHaveBeenCalledTimes(2);
132
-
133
- snapshot.error = error;
134
- snapshot.loading = false;
135
- expect(callback).toHaveBeenLastCalledWith(expect.objectContaining(snapshot));
136
-
137
- const updatedAt = new Date(defaultUser?.updatedAt ?? new Date());
138
- updatedAt.setDate(updatedAt.getDate() + 7);
139
-
140
- const updatedUser = {
141
- ...defaultUser,
142
- updatedAt: updatedAt.toISOString(),
143
- };
144
- client.emitter.emit('user.updated', { users: [updatedUser], files: [] });
145
-
146
- delete snapshot.error;
147
- snapshot.loading = false;
148
- snapshot.data = updatedUser;
149
- expect(callback).not.toHaveBeenNthCalledWith(3, expect.objectContaining(snapshot));
150
- });
151
-
152
- test('it should not return updates on obtain once!', async () => {
153
- const snapshot = getSnapshot();
154
-
155
- // mock response of queryUsers and validate
156
- const callback = jest.fn();
157
- client.http.get = jest.fn().mockResolvedValue(userQueryResponse);
158
-
159
- const unsub = liveUser(defaultUser.userId, callback);
160
-
161
- expect(callback).toHaveBeenCalledTimes(1);
162
-
163
- // check if cache data returned (should be empty)
164
- expect(callback).toHaveBeenCalledWith(expect.objectContaining(snapshot));
165
-
166
- await pause();
167
-
168
- expect(callback).toHaveBeenCalledTimes(2);
169
-
170
- unsub();
171
-
172
- const updatedAt = new Date(defaultUser?.updatedAt ?? new Date());
173
- updatedAt.setDate(updatedAt.getDate() + 7);
174
-
175
- const updatedUser = {
176
- ...defaultUser,
177
- updatedAt: updatedAt.toISOString(),
178
- };
179
- client.emitter.emit('user.updated', { users: [updatedUser], files: [] });
180
-
181
- delete snapshot.error;
182
- snapshot.loading = false;
183
- snapshot.data = updatedUser;
184
- expect(callback).not.toHaveBeenNthCalledWith(3, expect.objectContaining(snapshot));
185
- });
186
-
187
34
  const events: [string, keyof Amity.Events][] = [
188
35
  ['it should return updated user on onFetch', 'user.fetched'],
189
36
  ['it should return updated user on onUpdate', 'user.updated'],
@@ -6,3 +6,5 @@ export const LIVE_OBJECT_ENABLE_CACHE_MESSAGE =
6
6
  export const UNSYNCED_OBJECT_CACHED_AT_MESSAGE =
7
7
  'Observing unsynced object is not supported by Live Object.';
8
8
  export const UNSYNCED_OBJECT_CACHED_AT_VALUE = -5;
9
+ export const MINUTE = 60 * 1000;
10
+ export const ACCESS_TOKEN_WATCHER_INTERVAL = 10 * MINUTE;
@@ -0,0 +1,86 @@
1
+ import { getActiveClient } from '~/client/api';
2
+ import {
3
+ LIVE_OBJECT_ENABLE_CACHE_MESSAGE,
4
+ UNSYNCED_OBJECT_CACHED_AT_MESSAGE,
5
+ UNSYNCED_OBJECT_CACHED_AT_VALUE,
6
+ } from '~/utils/constants';
7
+ import { hasUpdates } from '~/core/model';
8
+ import { createQuery, runQuery } from '~/core/query';
9
+ import { ASCApiError } from '~/core/errors';
10
+
11
+ export const liveObject = <
12
+ T extends Exclude<Amity.Model[Amity.Domain], Amity.Reaction | Amity.FollowCount>,
13
+ K extends keyof T,
14
+ >(
15
+ id: T[K],
16
+ callback: Amity.LiveObjectCallback<T>,
17
+ key: K,
18
+ fetcher: (id: T[K]) => Promise<Amity.Cached<T>>,
19
+ eventHandlers: Array<(callback: Amity.Listener<T>) => Amity.Unsubscriber>,
20
+ ): Amity.Unsubscriber => {
21
+ const { cache } = getActiveClient();
22
+
23
+ if (!cache) {
24
+ console.log(LIVE_OBJECT_ENABLE_CACHE_MESSAGE);
25
+ }
26
+
27
+ let model: T;
28
+ let isUnsyncedModel = false; // for messages
29
+ const disposers: Amity.Unsubscriber[] = [];
30
+
31
+ const dispatcher = (data: Amity.LiveObject<T>) => {
32
+ model = data.data;
33
+ callback(data);
34
+ };
35
+
36
+ const realtimeRouter = (eventModel: T) => {
37
+ if (id !== eventModel[key]) {
38
+ return;
39
+ }
40
+
41
+ if (model && !hasUpdates(model, eventModel)) {
42
+ return;
43
+ }
44
+
45
+ dispatcher({ loading: false, data: eventModel, origin: 'event' });
46
+ };
47
+
48
+ const onFetch = () => {
49
+ // @ts-ignore
50
+ const query = createQuery(fetcher, id, true);
51
+
52
+ runQuery(query, ({ error, data, loading, origin, cachedAt }) => {
53
+ if (cachedAt === UNSYNCED_OBJECT_CACHED_AT_VALUE) {
54
+ dispatcher({
55
+ // @ts-ignore
56
+ data,
57
+ origin,
58
+ loading: false,
59
+ error: new ASCApiError(
60
+ UNSYNCED_OBJECT_CACHED_AT_MESSAGE,
61
+ Amity.ClientError.DISALOOW_UNSYNCED_OBJECT,
62
+ Amity.ErrorLevel.ERROR,
63
+ ),
64
+ });
65
+
66
+ isUnsyncedModel = true;
67
+ disposers.forEach(fn => fn());
68
+ } else if (!isUnsyncedModel) {
69
+ // @ts-ignore
70
+ dispatcher({ loading, data, origin, error });
71
+ }
72
+
73
+ if (error) {
74
+ disposers.forEach(fn => fn());
75
+ }
76
+ });
77
+ };
78
+
79
+ disposers.push(...eventHandlers.map(fn => fn(realtimeRouter)));
80
+
81
+ onFetch();
82
+
83
+ return () => {
84
+ disposers.forEach(fn => fn());
85
+ };
86
+ };
@@ -6,9 +6,22 @@ import {
6
6
 
7
7
  import { user11 } from './dummy';
8
8
 
9
+ const sessionHandler: Amity.SessionHandler = {
10
+ sessionWillRenewAccessToken(_) {
11
+ // do nothing
12
+ },
13
+ };
14
+
9
15
  export const client = createClient('key', 'sg');
16
+ client.accessTokenExpiryWatcher = (_, __, ___) => () => {
17
+ //
18
+ };
10
19
 
11
20
  export const connectClient = async () => {
21
+ const now = new Date();
22
+ const nextMonth = new Date();
23
+ nextMonth.setDate(now.getDate() + 30);
24
+
12
25
  client.mqtt.connect = jest.fn();
13
26
  client.mqtt.subscribe = jest.fn();
14
27
  client.http.post = jest.fn().mockReturnValueOnce({
@@ -16,14 +29,17 @@ export const connectClient = async () => {
16
29
  accessToken: 'accessToken',
17
30
  refreshToken: 'refreshToken',
18
31
  users: [user11],
32
+ expiresAt: nextMonth.toISOString(),
33
+ issuedAt: now.toISOString(),
19
34
  },
20
35
  });
21
36
 
22
37
  setTimeout(() => {
23
38
  client.ws.emit('connect');
24
- }, 500);
39
+ // fixes jest warning of open handles
40
+ }, 500).unref();
25
41
 
26
- await sdkConnectClient({ userId: 'test' });
42
+ await sdkConnectClient({ userId: 'test' }, sessionHandler);
27
43
  };
28
44
 
29
45
  export const disconnectClient = async () => {
@@ -0,0 +1,57 @@
1
+ export const category11 = {
2
+ name: 'a-hello',
3
+ updatedAt: '2022-11-25T04:19:34.446Z',
4
+ createdAt: '2022-11-25T04:19:34.446Z',
5
+ isDeleted: false,
6
+ categoryId: '2ddea5ad242d0a2bd5dc5be8ae9fc8c2',
7
+ };
8
+
9
+ export const category12 = {
10
+ name: 'b-testing-category',
11
+ updatedAt: '2022-11-25T03:56:06.238Z',
12
+ createdAt: '2022-11-25T03:56:06.238Z',
13
+ isDeleted: false,
14
+ categoryId: '88d175da65cbfeb39b81e722b322430e',
15
+ };
16
+
17
+ export const category13 = {
18
+ name: 'c-deleted-category',
19
+ updatedAt: '2022-11-25T03:56:06.238Z',
20
+ createdAt: '2022-11-25T03:56:06.238Z',
21
+ isDeleted: true,
22
+ categoryId: '88d175da65cbfeb39b81e722b322430d',
23
+ };
24
+
25
+ export const category21 = {
26
+ name: 'a-0asd',
27
+ updatedAt: '2022-11-25T04:18:59.180Z',
28
+ createdAt: '2022-11-25T04:18:59.180Z',
29
+ isDeleted: false,
30
+ categoryId: '10051d82a1f371c6be3a8f4a4654b8a1',
31
+ };
32
+
33
+ export const category22 = {
34
+ name: 'b-A Category',
35
+ updatedAt: '2022-11-25T03:56:29.037Z',
36
+ createdAt: '2022-11-25T03:56:29.037Z',
37
+ isDeleted: false,
38
+ categoryId: '639942c6b2f121bed3901cf4a4c296e7',
39
+ };
40
+
41
+ export const categoryQueryResponse = {
42
+ data: {
43
+ categories: [category11, category12, category13],
44
+ paging: {
45
+ next: 'eyJza2lwIjoxMCwibGltaXQiOjEwfQ==',
46
+ },
47
+ },
48
+ };
49
+
50
+ export const categoryQueryResponsePage2 = {
51
+ data: {
52
+ categories: [category21, category22],
53
+ paging: {
54
+ next: 'eyJza2lwIjoxMCwibGltaXQiOjEwfQ==',
55
+ },
56
+ },
57
+ };