@amityco/ts-sdk 0.0.1-beta.37 → 0.0.1-beta.39

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 (251) hide show
  1. package/.eslintrc.json +3 -5
  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/model.d.ts +2 -0
  5. package/dist/@types/core/model.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/channel.d.ts +2 -2
  9. package/dist/@types/domains/channel.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/domains/feed.d.ts +1 -2
  13. package/dist/@types/domains/feed.d.ts.map +1 -1
  14. package/dist/@types/domains/message.d.ts +1 -1
  15. package/dist/@types/domains/message.d.ts.map +1 -1
  16. package/dist/@types/domains/post.d.ts +1 -1
  17. package/dist/@types/domains/post.d.ts.map +1 -1
  18. package/dist/@types/domains/user.d.ts +8 -0
  19. package/dist/@types/domains/user.d.ts.map +1 -1
  20. package/dist/@types/global.d.ts +5 -0
  21. package/dist/@types/global.d.ts.map +1 -1
  22. package/dist/category/api/queryCategories.d.ts +1 -5
  23. package/dist/category/api/queryCategories.d.ts.map +1 -1
  24. package/dist/category/observers/index.d.ts +2 -0
  25. package/dist/category/observers/index.d.ts.map +1 -0
  26. package/dist/category/observers/liveCategories.d.ts +18 -0
  27. package/dist/category/observers/liveCategories.d.ts.map +1 -0
  28. package/dist/category/observers/tests/liveCategories.test.d.ts +2 -0
  29. package/dist/category/observers/tests/liveCategories.test.d.ts.map +1 -0
  30. package/dist/channel/api/tests/getChannels.test.d.ts +2 -0
  31. package/dist/channel/api/tests/getChannels.test.d.ts.map +1 -0
  32. package/dist/channel/api/tests/leaveChannel.test.d.ts +2 -0
  33. package/dist/channel/api/tests/leaveChannel.test.d.ts.map +1 -0
  34. package/dist/channel/observers/liveChannel.d.ts.map +1 -1
  35. package/dist/channel/observers/liveChannels.d.ts.map +1 -1
  36. package/dist/client/api/accessTokenExpiryWatcher.d.ts +4 -1
  37. package/dist/client/api/accessTokenExpiryWatcher.d.ts.map +1 -1
  38. package/dist/client/api/connectClient.d.ts.map +1 -1
  39. package/dist/client/api/getToken.d.ts +3 -1
  40. package/dist/client/api/getToken.d.ts.map +1 -1
  41. package/dist/client/utils/setClientToken.d.ts +3 -3
  42. package/dist/comment/api/deleteComment.d.ts.map +1 -1
  43. package/dist/comment/api/getComment.d.ts.map +1 -1
  44. package/dist/comment/observers/index.d.ts +1 -0
  45. package/dist/comment/observers/index.d.ts.map +1 -1
  46. package/dist/comment/observers/liveComment.d.ts +21 -0
  47. package/dist/comment/observers/liveComment.d.ts.map +1 -0
  48. package/dist/comment/observers/tests/liveComment.test.d.ts +2 -0
  49. package/dist/comment/observers/tests/liveComment.test.d.ts.map +1 -0
  50. package/dist/community/api/queryCommunities.d.ts +1 -10
  51. package/dist/community/api/queryCommunities.d.ts.map +1 -1
  52. package/dist/community/events/index.d.ts +1 -0
  53. package/dist/community/events/index.d.ts.map +1 -1
  54. package/dist/community/events/onCommunityUserChanged.d.ts +17 -0
  55. package/dist/community/events/onCommunityUserChanged.d.ts.map +1 -0
  56. package/dist/community/events/utils.d.ts +1 -0
  57. package/dist/community/events/utils.d.ts.map +1 -1
  58. package/dist/community/observers/index.d.ts +1 -0
  59. package/dist/community/observers/index.d.ts.map +1 -1
  60. package/dist/community/observers/liveCommunities.d.ts +20 -0
  61. package/dist/community/observers/liveCommunities.d.ts.map +1 -0
  62. package/dist/community/observers/tests/liveCommunities.test.d.ts +2 -0
  63. package/dist/community/observers/tests/liveCommunities.test.d.ts.map +1 -0
  64. package/dist/core/events.d.ts +3 -3
  65. package/dist/core/events.d.ts.map +1 -1
  66. package/dist/core/model/idResolvers.d.ts.map +1 -1
  67. package/dist/core/model/identifyModel.d.ts.map +1 -1
  68. package/dist/core/model/index.d.ts.map +1 -1
  69. package/dist/core/query/filtering.d.ts +10 -0
  70. package/dist/core/query/filtering.d.ts.map +1 -1
  71. package/dist/core/query/paging.d.ts +2 -2
  72. package/dist/core/query/paging.d.ts.map +1 -1
  73. package/dist/core/query/sorting.d.ts +6 -0
  74. package/dist/core/query/sorting.d.ts.map +1 -1
  75. package/dist/core/query/tests/paging.test.d.ts +2 -0
  76. package/dist/core/query/tests/paging.test.d.ts.map +1 -0
  77. package/dist/core/transports/http.d.ts +0 -5
  78. package/dist/core/transports/http.d.ts.map +1 -1
  79. package/dist/file/api/test/createImage.test.d.ts +2 -0
  80. package/dist/file/api/test/createImage.test.d.ts.map +1 -0
  81. package/dist/file/api/test/createVideo.test.d.ts +2 -0
  82. package/dist/file/api/test/createVideo.test.d.ts.map +1 -0
  83. package/dist/index.cjs.js +607 -252
  84. package/dist/index.d.ts +1 -0
  85. package/dist/index.d.ts.map +1 -1
  86. package/dist/index.esm.js +599 -251
  87. package/dist/index.umd.js +4 -4
  88. package/dist/message/api/queryMessages.d.ts +2 -2
  89. package/dist/message/api/queryMessages.d.ts.map +1 -1
  90. package/dist/message/observers/liveMessage.d.ts.map +1 -1
  91. package/dist/post/observers/index.d.ts +1 -0
  92. package/dist/post/observers/index.d.ts.map +1 -1
  93. package/dist/post/observers/livePost.d.ts +21 -0
  94. package/dist/post/observers/livePost.d.ts.map +1 -0
  95. package/dist/post/observers/livePosts.d.ts +2 -2
  96. package/dist/post/observers/livePosts.d.ts.map +1 -1
  97. package/dist/post/observers/tests/livePost.test.d.ts +2 -0
  98. package/dist/post/observers/tests/livePost.test.d.ts.map +1 -0
  99. package/dist/report/api/createReport.d.ts.map +1 -1
  100. package/dist/report/api/deleteReport.d.ts.map +1 -1
  101. package/dist/report/api/tests/createReport.test.d.ts +2 -0
  102. package/dist/report/api/tests/createReport.test.d.ts.map +1 -0
  103. package/dist/report/api/tests/deleteReport.test.d.ts +2 -0
  104. package/dist/report/api/tests/deleteReport.test.d.ts.map +1 -0
  105. package/dist/subChannel/api/tests/deleteSubChannel.test.d.ts +2 -0
  106. package/dist/subChannel/api/tests/deleteSubChannel.test.d.ts.map +1 -0
  107. package/dist/subChannel/api/tests/getSubChannel.test.d.ts +2 -0
  108. package/dist/subChannel/api/tests/getSubChannel.test.d.ts.map +1 -0
  109. package/dist/subChannel/api/tests/getSubChannels.test.d.ts +2 -0
  110. package/dist/subChannel/api/tests/getSubChannels.test.d.ts.map +1 -0
  111. package/dist/subChannel/api/tests/updateSubChannel.test.d.ts +2 -0
  112. package/dist/subChannel/api/tests/updateSubChannel.test.d.ts.map +1 -0
  113. package/dist/subChannel/observers/liveSubChannel.d.ts.map +1 -1
  114. package/dist/user/api/queryUsers.d.ts +1 -6
  115. package/dist/user/api/queryUsers.d.ts.map +1 -1
  116. package/dist/user/api/tests/updateUser.test.d.ts +2 -0
  117. package/dist/user/api/tests/updateUser.test.d.ts.map +1 -0
  118. package/dist/user/observers/index.d.ts +1 -0
  119. package/dist/user/observers/index.d.ts.map +1 -1
  120. package/dist/user/observers/liveUser.d.ts.map +1 -1
  121. package/dist/user/observers/liveUsers.d.ts +18 -0
  122. package/dist/user/observers/liveUsers.d.ts.map +1 -0
  123. package/dist/user/observers/tests/liveUsers.test.d.ts +2 -0
  124. package/dist/user/observers/tests/liveUsers.test.d.ts.map +1 -0
  125. package/dist/utils/liveObject.d.ts +2 -0
  126. package/dist/utils/liveObject.d.ts.map +1 -0
  127. package/dist/utils/tests/dummy/category.d.ts +64 -0
  128. package/dist/utils/tests/dummy/category.d.ts.map +1 -0
  129. package/dist/utils/tests/dummy/channel.d.ts +50 -0
  130. package/dist/utils/tests/dummy/channel.d.ts.map +1 -1
  131. package/dist/utils/tests/dummy/community.d.ts +132 -0
  132. package/dist/utils/tests/dummy/community.d.ts.map +1 -1
  133. package/dist/utils/tests/dummy/feed.d.ts +21 -0
  134. package/dist/utils/tests/dummy/feed.d.ts.map +1 -0
  135. package/dist/utils/tests/dummy/file.d.ts +3 -0
  136. package/dist/utils/tests/dummy/file.d.ts.map +1 -1
  137. package/dist/utils/tests/dummy/index.d.ts +2 -0
  138. package/dist/utils/tests/dummy/index.d.ts.map +1 -1
  139. package/dist/utils/tests/dummy/post.d.ts +11 -0
  140. package/dist/utils/tests/dummy/post.d.ts.map +1 -1
  141. package/dist/utils/tests/dummy/subChannel.d.ts +0 -20
  142. package/dist/utils/tests/dummy/subChannel.d.ts.map +1 -1
  143. package/dist/utils/tests/dummy/user.d.ts +81 -0
  144. package/dist/utils/tests/dummy/user.d.ts.map +1 -1
  145. package/dist/utils/tests/liveObject.test.d.ts +2 -0
  146. package/dist/utils/tests/liveObject.test.d.ts.map +1 -0
  147. package/package.json +4 -4
  148. package/src/@types/core/events.ts +1 -0
  149. package/src/@types/core/model.ts +4 -0
  150. package/src/@types/domains/category.ts +13 -0
  151. package/src/@types/domains/channel.ts +2 -2
  152. package/src/@types/domains/community.ts +25 -0
  153. package/src/@types/domains/feed.ts +1 -3
  154. package/src/@types/domains/message.ts +4 -1
  155. package/src/@types/domains/post.ts +1 -1
  156. package/src/@types/domains/user.ts +14 -0
  157. package/src/@types/global.ts +5 -0
  158. package/src/cache/api/tests/ingestInCache.test.ts +2 -0
  159. package/src/category/api/queryCategories.ts +3 -5
  160. package/src/category/observers/index.ts +1 -0
  161. package/src/category/observers/liveCategories.ts +141 -0
  162. package/src/category/observers/tests/liveCategories.test.ts +147 -0
  163. package/src/channel/api/tests/createChannel.test.ts +30 -6
  164. package/src/channel/api/tests/getChannel.test.ts +3 -1
  165. package/src/channel/api/tests/getChannels.test.ts +97 -0
  166. package/src/channel/api/tests/joinChannel.test.ts +62 -3
  167. package/src/channel/api/tests/leaveChannel.test.ts +90 -0
  168. package/src/channel/api/tests/queryChannels.test.ts +38 -1
  169. package/src/channel/observers/liveChannel.ts +8 -80
  170. package/src/channel/observers/liveChannels.ts +29 -24
  171. package/src/client/api/accessTokenExpiryWatcher.ts +7 -5
  172. package/src/client/api/connectClient.ts +0 -2
  173. package/src/client/api/tests/accessTokenExpiryWatcher.test.ts +8 -5
  174. package/src/comment/api/deleteComment.ts +5 -5
  175. package/src/comment/api/getComment.ts +8 -3
  176. package/src/comment/observers/index.ts +1 -0
  177. package/src/comment/observers/liveComment.ts +43 -0
  178. package/src/comment/observers/tests/liveComment.test.ts +95 -0
  179. package/src/community/api/queryCommunities.ts +3 -10
  180. package/src/community/api/test/addCommunityMember.test.ts +14 -2
  181. package/src/community/api/test/joinCommunity.test.ts +14 -2
  182. package/src/community/api/test/leaveCommunity.test.ts +11 -1
  183. package/src/community/api/test/removeCommunityMembers.test.ts +11 -1
  184. package/src/community/events/index.ts +1 -0
  185. package/src/community/events/onCommunityUserChanged.ts +20 -0
  186. package/src/community/events/test/onCommunityJoined.test.ts +1 -1
  187. package/src/community/events/test/onCommunityUserAdded.test.ts +1 -1
  188. package/src/community/events/test/onCommunityUserBanned.test.ts +1 -1
  189. package/src/community/events/test/onCommunityUserUnbaned.test.ts +1 -1
  190. package/src/community/events/test/utils.test.ts +52 -3
  191. package/src/community/events/utils.ts +49 -0
  192. package/src/community/observers/index.ts +1 -0
  193. package/src/community/observers/liveCommunities.ts +188 -0
  194. package/src/community/observers/tests/liveCommunities.test.ts +284 -0
  195. package/src/core/model/idResolvers.ts +2 -0
  196. package/src/core/model/identifyModel.ts +1 -0
  197. package/src/core/model/index.ts +2 -0
  198. package/src/core/query/filtering.ts +33 -3
  199. package/src/core/query/paging.ts +5 -4
  200. package/src/core/query/sorting.ts +8 -0
  201. package/src/core/query/tests/paging.test.ts +66 -0
  202. package/src/core/transports/http.ts +17 -13
  203. package/src/core/transports/test/http.test.ts +49 -60
  204. package/src/file/api/createFile.ts +1 -1
  205. package/src/file/api/createImage.ts +1 -1
  206. package/src/file/api/createVideo.ts +1 -1
  207. package/src/file/api/test/createImage.test.ts +69 -0
  208. package/src/file/api/test/createVideo.test.ts +81 -0
  209. package/src/index.ts +1 -0
  210. package/src/message/api/queryMessages.ts +7 -7
  211. package/src/message/api/tests/queryMessages.test.ts +6 -6
  212. package/src/message/observers/liveMessage.ts +11 -83
  213. package/src/message/tests/observers/liveMessage.test.ts +1 -143
  214. package/src/message/tests/observers/liveMessages.test.ts +4 -4
  215. package/src/post/observers/index.ts +1 -0
  216. package/src/post/observers/livePost.ts +47 -0
  217. package/src/post/observers/livePosts.ts +14 -22
  218. package/src/post/observers/tests/livePost.test.ts +97 -0
  219. package/src/post/observers/tests/livePosts.test.ts +65 -8
  220. package/src/report/api/createReport.ts +1 -6
  221. package/src/report/api/deleteReport.ts +2 -6
  222. package/src/report/api/tests/createReport.test.ts +93 -0
  223. package/src/report/api/tests/deleteReport.test.ts +93 -0
  224. package/src/stream/api/tests/createStream.test.ts +3 -11
  225. package/src/stream/api/tests/deleteStream.test.ts +5 -3
  226. package/src/subChannel/api/tests/createSubChannel.test.ts +21 -14
  227. package/src/subChannel/api/tests/deleteSubChannel.test.ts +112 -0
  228. package/src/subChannel/api/tests/getSubChannel.test.ts +97 -0
  229. package/src/subChannel/api/tests/getSubChannels.test.ts +97 -0
  230. package/src/subChannel/api/tests/updateSubChannel.test.ts +86 -0
  231. package/src/subChannel/observers/liveSubChannel.ts +6 -56
  232. package/src/subChannel/observers/tests/liveSubChannel.test.ts +0 -82
  233. package/src/user/api/queryUsers.ts +1 -6
  234. package/src/user/api/tests/updateUser.test.ts +60 -0
  235. package/src/user/observers/index.ts +1 -0
  236. package/src/user/observers/liveUser.ts +9 -61
  237. package/src/user/observers/liveUsers.ts +162 -0
  238. package/src/user/observers/tests/liveUsers.test.ts +202 -0
  239. package/src/user/tests/observers/liveUser.test.ts +1 -154
  240. package/src/utils/liveObject.ts +86 -0
  241. package/src/utils/tests/dummy/category.ts +57 -0
  242. package/src/utils/tests/dummy/channel.ts +52 -1
  243. package/src/utils/tests/dummy/community.ts +94 -0
  244. package/src/utils/tests/dummy/feed.ts +13 -0
  245. package/src/utils/tests/dummy/file.ts +32 -0
  246. package/src/utils/tests/dummy/index.ts +3 -0
  247. package/src/utils/tests/dummy/post.ts +62 -47
  248. package/src/utils/tests/dummy/stream.ts +73 -73
  249. package/src/utils/tests/dummy/subChannel.ts +0 -22
  250. package/src/utils/tests/dummy/user.ts +57 -0
  251. package/src/utils/tests/liveObject.test.ts +172 -0
@@ -1,5 +1,4 @@
1
1
  import axios from 'axios';
2
- import qs from 'qs';
3
2
  import HttpAgent, { HttpsAgent } from 'agentkeepalive';
4
3
 
5
4
  import { ASCError } from '~/core/errors';
@@ -7,14 +6,6 @@ import { ASCError } from '~/core/errors';
7
6
  import { fireEvent } from '../events';
8
7
  import { unwrapPayload } from './utils';
9
8
 
10
- /**
11
- * Axios param serializer (for querystring)
12
- * @hidden
13
- */
14
- export const stringify = (params: Record<string, unknown>): string => {
15
- return qs.stringify(params, { arrayFormat: 'brackets' });
16
- };
17
-
18
9
  /**
19
10
  * Creates a pre-configured axios instance
20
11
  *
@@ -36,7 +27,14 @@ export const createHttpTransport = (endpoint: string) => {
36
27
  baseURL: endpoint,
37
28
  httpAgent: new HttpAgent(options),
38
29
  httpsAgent: new HttpsAgent(options),
39
- paramsSerializer: stringify,
30
+ /*
31
+ * If paramSerializer is required, use the serialize option to stringify
32
+ * params. The encode option will pass complex params as string only whereas
33
+ * the serialize option will pass params in the format Record<string, any>
34
+ *
35
+ * For more details:
36
+ * https://github.com/axios/axios#request-config
37
+ */
40
38
  });
41
39
 
42
40
  instance.interceptors.request.use(config => {
@@ -59,8 +57,6 @@ export const createHttpTransport = (endpoint: string) => {
59
57
  response => response,
60
58
  error => {
61
59
  const { response } = error;
62
- // eslint-disable-next-line no-console
63
- console.error(response?.data ?? error);
64
60
 
65
61
  // handle unauthorized request
66
62
  if (response.data.code === Amity.ServerError.UNAUTHORIZED) {
@@ -78,7 +74,15 @@ export const createHttpTransport = (endpoint: string) => {
78
74
  );
79
75
  }
80
76
 
81
- if (response?.data) unwrapPayload(response.data);
77
+ // if it's an error with status in the response payload,
78
+ // then it's an expected error.
79
+ if (response?.data?.status) {
80
+ unwrapPayload(response?.data);
81
+ }
82
+ // unexpected error.
83
+ else {
84
+ throw new Error(response?.data ?? error);
85
+ }
82
86
  },
83
87
  );
84
88
 
@@ -1,83 +1,72 @@
1
- import { createHttpTransport, stringify } from '../http';
1
+ import nock from 'nock';
2
+
3
+ import { ASCApiError, ASCUnknownError } from '~/core/errors';
4
+ import { createFileFormData } from '~/utils/tests';
5
+
6
+ import { createHttpTransport } from '../http';
7
+
8
+ const baseUrl = 'https://non-exist.domain';
2
9
 
3
10
  describe('core/transports', () => {
4
- describe('stringify', () => {
5
- test('should serializer simple string', () => {
6
- const params = { a: 'c' };
7
- const url = stringify(params);
8
- expect(url).toBe('a=c');
9
- });
11
+ describe('createHttpTransport', () => {
12
+ beforeAll(nock.disableNetConnect);
13
+ beforeEach(nock.cleanAll);
10
14
 
11
- test('should serializer empty string', () => {
12
- const params = { a: '' };
13
- const url = stringify(params);
14
- expect(url).toBe('a=');
15
- });
15
+ test('should create axios instance with out error', () => {
16
+ nock(baseUrl).get(/./).reply(200);
16
17
 
17
- test('should serializer special character', () => {
18
- const params = { a: '✓', b: 'ø' };
19
- const url = stringify(params);
20
- expect(url).toBe('a=%E2%9C%93&b=%C3%B8');
18
+ expect(createHttpTransport(baseUrl)).not.toThrow();
21
19
  });
22
20
 
23
- test('should serializer boolean', () => {
24
- const params = { a: true, b: false };
25
- const url = stringify(params);
26
- expect(url).toBe('a=true&b=false');
27
- });
21
+ test('instance should resolved http request', async () => {
22
+ const expectedResolveValue = { foo: 'bar' };
23
+ nock(baseUrl).get('/foo').reply(200, expectedResolveValue);
28
24
 
29
- test('should serializer null ', () => {
30
- const params = { a: null };
31
- const url = stringify(params);
32
- expect(url).toBe('a=');
33
- });
25
+ const instance = createHttpTransport(baseUrl);
34
26
 
35
- test('should serializer undefined', () => {
36
- const params = { a: undefined };
37
- const url = stringify(params);
38
- expect(url).toBe('');
27
+ const expected = expect.objectContaining({ data: expectedResolveValue });
28
+ await expect(instance.get('/foo')).resolves.toEqual(expected);
39
29
  });
40
30
 
41
- test('should serializer NaN', () => {
42
- const params = { a: NaN };
43
- const url = stringify(params);
44
- expect(url).toBe('a=NaN');
45
- });
31
+ test('instance should throw Error when got 400 response code', async () => {
32
+ nock(baseUrl).get('/foo').reply(400);
46
33
 
47
- test('should serializer simple array', () => {
48
- const params = { a: ['b', 'c', 'd'] };
49
- const url = stringify(params);
50
- expect(url).toBe('a%5B%5D=b&a%5B%5D=c&a%5B%5D=d');
51
- });
34
+ const instance = createHttpTransport(baseUrl);
52
35
 
53
- test('should serializer complex array', () => {
54
- const params = { a: ['b', { c: 'd' }] };
55
- const url = stringify(params);
56
- expect(url).toBe('a%5B%5D=b&a%5B%5D%5Bc%5D=d');
36
+ await expect(instance.get('/foo')).rejects.toThrow(Error);
57
37
  });
58
38
 
59
- test('should serializer nested object', () => {
60
- const params = { a: { b: 'c' } };
61
- const url = stringify(params);
62
- expect(url).toBe('a%5Bb%5D=c');
39
+ test('instance should throw Error when got 500 response code', async () => {
40
+ nock(baseUrl).get('/foo').reply(500);
41
+
42
+ const instance = createHttpTransport(baseUrl);
43
+
44
+ await expect(instance.get('/foo')).rejects.toThrow(Error);
63
45
  });
64
46
 
65
- test('should serializer deep nested object', () => {
66
- const params = { a: { b: { c: { d: { e: { f: { g: { h: { i: 'j' } } } } } } } } };
67
- const url = stringify(params);
68
- expect(url).toBe('a%5Bb%5D%5Bc%5D%5Bd%5D%5Be%5D%5Bf%5D%5Bg%5D%5Bh%5D%5Bi%5D=j');
47
+ test('instance should throw `ASCUnknownError` when got `fail` status in payload', async () => {
48
+ nock(baseUrl).get('/foo').reply(500, { status: 'fail', message: 'something fail' });
49
+
50
+ const instance = createHttpTransport(baseUrl);
51
+
52
+ await expect(instance.get('/foo')).rejects.toThrow(ASCUnknownError);
69
53
  });
70
54
 
71
- test('should serializer empty object', () => {
72
- const params = { a: { b: [] } };
73
- const url = stringify(params);
74
- expect(url).toBe('');
55
+ test('instance should throw `ASCApiError` when got `error` status in payload', async () => {
56
+ nock(baseUrl).get('/foo').reply(500, { status: 'error', message: 'something error' });
57
+
58
+ const instance = createHttpTransport(baseUrl);
59
+
60
+ await expect(instance.get('/foo')).rejects.toThrow(ASCApiError);
75
61
  });
76
- });
77
62
 
78
- describe('createHttpTransport', () => {
79
- test('should create axios instance with out error', () => {
80
- expect(createHttpTransport('/')).not.toThrow();
63
+ test('instance should receive formData', async () => {
64
+ const formData = createFileFormData();
65
+ nock(baseUrl).post('/foo').reply(200);
66
+
67
+ const instance = createHttpTransport(baseUrl);
68
+
69
+ await expect(instance.post('/foo', formData)).resolves.not.toThrow();
81
70
  });
82
71
  });
83
72
  });
@@ -34,7 +34,7 @@ export const createFile = async <T extends Amity.FileType = any>(
34
34
 
35
35
  const { data } = await client.http.post<Amity.CreateFilePayload<T>>('/api/v4/files', formData, {
36
36
  headers,
37
- onUploadProgress({ loaded, total }) {
37
+ onUploadProgress({ loaded, total = 100 }) {
38
38
  onProgress && onProgress(Math.round((loaded * 100) / total));
39
39
  },
40
40
  });
@@ -37,7 +37,7 @@ export const createImage = async (
37
37
  formData,
38
38
  {
39
39
  headers,
40
- onUploadProgress({ loaded, total }) {
40
+ onUploadProgress({ loaded, total = 100 }) {
41
41
  onProgress && onProgress(Math.round((loaded * 100) / total));
42
42
  },
43
43
  },
@@ -43,7 +43,7 @@ export const createVideo = async (
43
43
  formData,
44
44
  {
45
45
  headers,
46
- onUploadProgress({ loaded, total }) {
46
+ onUploadProgress({ loaded, total = 100 }) {
47
47
  onProgress && onProgress(Math.round((loaded * 100) / total));
48
48
  },
49
49
  },
@@ -0,0 +1,69 @@
1
+ import { disableCache, enableCache, pullFromCache } from '~/cache/api';
2
+ import { client, file11, createEmptyFormData, createFileFormData } from '~/utils/tests';
3
+
4
+ import { createImage } from '../createImage';
5
+
6
+ const imageToCreate = [file11];
7
+ const createIds = imageToCreate.map(({ fileId }) => fileId);
8
+ const resolvedPayloadValue = { data: imageToCreate };
9
+
10
+ describe('createImage', () => {
11
+ test('should return created image', async () => {
12
+ const formData = createFileFormData();
13
+ client.http.post = jest.fn().mockResolvedValue(resolvedPayloadValue);
14
+
15
+ const received = createImage(formData);
16
+
17
+ await expect(received).resolves.toEqual(expect.objectContaining({ data: imageToCreate }));
18
+ });
19
+
20
+ test('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(createImage(formData)).rejects.toThrow('error');
25
+ });
26
+
27
+ test('should throw an error if formData is empty', async () => {
28
+ const emptyFormData = createEmptyFormData();
29
+
30
+ await expect(createImage(emptyFormData)).rejects.toThrow(
31
+ 'The formData object must have a `files` key.',
32
+ );
33
+ });
34
+
35
+ test('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
+ (url, data, 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 createImage(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('should create cache after created image', async () => {
58
+ enableCache();
59
+ const formData = createFileFormData();
60
+ client.http.post = jest.fn().mockResolvedValue(resolvedPayloadValue);
61
+
62
+ await createImage(formData);
63
+ const received = createIds.map(id => pullFromCache(['file', 'get', id])?.data);
64
+
65
+ expect(received).toEqual(expect.objectContaining(imageToCreate));
66
+
67
+ disableCache();
68
+ });
69
+ });
@@ -0,0 +1,81 @@
1
+ import { ContentFeedType } from '~/@types';
2
+ import { disableCache, enableCache, pullFromCache } from '~/cache/api';
3
+ import { client, file12, createEmptyFormData, createFileFormData } from '~/utils/tests';
4
+
5
+ import { createVideo } from '../createVideo';
6
+
7
+ const videoToCreate = [file12];
8
+ const createIds = videoToCreate.map(({ fileId }) => fileId);
9
+ const resolvedPayloadValue = { data: videoToCreate };
10
+
11
+ describe('createVideo', () => {
12
+ test('should return created video', async () => {
13
+ const formData = createFileFormData();
14
+ client.http.post = jest.fn().mockResolvedValue(resolvedPayloadValue);
15
+
16
+ const received = createVideo(formData);
17
+
18
+ await expect(received).resolves.toEqual(expect.objectContaining({ data: videoToCreate }));
19
+ });
20
+
21
+ test('should throw an error if request fails', async () => {
22
+ const formData = createFileFormData();
23
+ client.http.post = jest.fn().mockRejectedValueOnce(new Error('error'));
24
+
25
+ await expect(createVideo(formData)).rejects.toThrow('error');
26
+ });
27
+
28
+ test('should throw an error if formData is empty', async () => {
29
+ const emptyFormData = createEmptyFormData();
30
+
31
+ await expect(createVideo(emptyFormData)).rejects.toThrow(
32
+ 'The formData object must have a `files` key.',
33
+ );
34
+ });
35
+
36
+ // There is currently no polyfill or native API for generating complete formData
37
+ // in Node.js, so I'll skip this until 100% browser-compatible formData can be created.
38
+ test.skip('should append feedType to formData when define feedType param', async () => {
39
+ const formData = createFileFormData();
40
+ client.http.post = jest.fn().mockResolvedValue(resolvedPayloadValue);
41
+
42
+ await createVideo(formData, ContentFeedType.POST);
43
+
44
+ expect(formData.get('feedType')).toEqual(ContentFeedType.POST);
45
+ });
46
+
47
+ test('should call onProgress params on upload progress updated', async () => {
48
+ expect.assertions(3);
49
+ const formData = createFileFormData();
50
+ const onProgress = jest.fn();
51
+
52
+ jest.spyOn(client.http, 'post').mockImplementationOnce(
53
+ (url, data, config) =>
54
+ new Promise((resolve, _reject) => {
55
+ config?.onUploadProgress?.({ loaded: 0, bytes: 0, total: 100 });
56
+ config?.onUploadProgress?.({ loaded: 40, bytes: 40, total: 100 });
57
+ config?.onUploadProgress?.({ loaded: 100, bytes: 100, total: 100 });
58
+ resolve(resolvedPayloadValue);
59
+ }),
60
+ );
61
+
62
+ await createVideo(formData, undefined, onProgress);
63
+
64
+ expect(onProgress).toHaveBeenNthCalledWith(1, 0);
65
+ expect(onProgress).toHaveBeenNthCalledWith(2, 40);
66
+ expect(onProgress).toHaveBeenNthCalledWith(3, 100);
67
+ });
68
+
69
+ test('should create cache after created video', async () => {
70
+ enableCache();
71
+ const formData = createFileFormData();
72
+ client.http.post = jest.fn().mockResolvedValue(resolvedPayloadValue);
73
+
74
+ await createVideo(formData);
75
+ const received = createIds.map(id => pullFromCache(['file', 'get', id])?.data);
76
+
77
+ expect(received).toEqual(expect.objectContaining(videoToCreate));
78
+
79
+ disableCache();
80
+ });
81
+ });
package/src/index.ts CHANGED
@@ -48,6 +48,7 @@ export * from './community/events';
48
48
  export * from './community/observers';
49
49
 
50
50
  export * from './category/api';
51
+ export * from './category/observers';
51
52
 
52
53
  export * from './feed/api';
53
54
 
@@ -1,7 +1,7 @@
1
1
  import { getActiveClient } from '~/client/api';
2
2
 
3
3
  import { fireEvent } from '~/core/events';
4
- import { toPage } from '~/core/query';
4
+ import { toPageRaw } from '~/core/query';
5
5
  import { pullFromCache, pushToCache } from '~/cache/api';
6
6
  import { ingestInCache } from '~/cache/api/ingestInCache';
7
7
  import { getResolver } from '~/core/model';
@@ -23,7 +23,7 @@ import { convertQueryParams, convertResponseFromRaw } from '../utils';
23
23
  */
24
24
  export const queryMessages = async (
25
25
  query: Amity.QueryMessages,
26
- ): Promise<Amity.Cached<Amity.Paged<Amity.Message>>> => {
26
+ ): Promise<Amity.Cached<Amity.Paged<Amity.Message, Amity.Page<string>>>> => {
27
27
  const client = getActiveClient();
28
28
  client.log('message/queryMessages', query);
29
29
 
@@ -53,8 +53,8 @@ export const queryMessages = async (
53
53
 
54
54
  fireEvent('local.message.fetched', { messages });
55
55
 
56
- const nextPage = toPage(paging.next);
57
- const prevPage = toPage(paging.previous);
56
+ const nextPage = toPageRaw(paging.next);
57
+ const prevPage = toPageRaw(paging.previous);
58
58
 
59
59
  return { data: messages, cachedAt, prevPage, nextPage };
60
60
  };
@@ -74,7 +74,7 @@ export const queryMessages = async (
74
74
  */
75
75
  queryMessages.locally = (
76
76
  query: Parameters<typeof queryMessages>[0],
77
- ): Amity.Cached<Amity.Paged<Amity.Message>> | undefined => {
77
+ ): Amity.Cached<Amity.Paged<Amity.Message, Amity.Page<string>>> | undefined => {
78
78
  const client = getActiveClient();
79
79
  client.log('message/queryMessages.locally', query);
80
80
 
@@ -94,8 +94,8 @@ queryMessages.locally = (
94
94
  .filter(Boolean)
95
95
  .map(({ data }) => data);
96
96
 
97
- const prevPage = toPage(data?.paging.previous);
98
- const nextPage = toPage(data?.paging.next);
97
+ const prevPage = toPageRaw(data?.paging.previous);
98
+ const nextPage = toPageRaw(data?.paging.next);
99
99
 
100
100
  return messages.length === data?.messages?.length
101
101
  ? { data: messages, cachedAt, prevPage, nextPage }
@@ -14,9 +14,9 @@ const messageIds = messagesToQuery.map(x => x.messageId);
14
14
  const queryCriteriaWithoutPage = { subChannelId: messagesToQuery[0].subChannelId };
15
15
  const queryCriteria = { ...queryCriteriaWithoutPage, page: { limit: 10 } };
16
16
  const paging = {
17
- previous: 'eyJiZWZvcmUiOjU1LCJsYXN0IjoxMH0=',
18
- next: 'eyJiZWZvcmUiOjU1LCJsYXN0IjoxMH0=',
17
+ next: 'eyJsaW1pdCI6MiwiYmVmb3JlIjo2MzQ3MTYxNDM5MTExMTAwMDAwMH0',
19
18
  };
19
+ const nextPage = { before: 63471614391111000000, limit: 2 };
20
20
 
21
21
  const getResolvedMessageValue = () => ({
22
22
  data: {
@@ -34,8 +34,8 @@ describe('queryMessages', () => {
34
34
  await expect(queryMessages(queryCriteria)).resolves.toEqual(
35
35
  expect.objectContaining({
36
36
  data: messagesToQuery,
37
- prevPage: { before: 55, limit: 10 },
38
- nextPage: { before: 55, limit: 10 },
37
+ nextPage,
38
+ prevPage: undefined,
39
39
  }),
40
40
  );
41
41
  });
@@ -91,8 +91,8 @@ describe('queryMessages.locally', () => {
91
91
  expect(queryMessages.locally(queryCriteria)).toEqual(
92
92
  expect.objectContaining({
93
93
  data: messagesToQuery,
94
- prevPage: { before: 55, limit: 10 },
95
- nextPage: { before: 55, limit: 10 },
94
+ prevPage: undefined,
95
+ nextPage,
96
96
  }),
97
97
  );
98
98
  });
@@ -1,12 +1,4 @@
1
- import { ASCApiError } from '~/core/errors';
2
- import { getActiveClient } from '~/client/api';
3
- import { createQuery, runQuery } from '~/core/query';
4
- import {
5
- LIVE_OBJECT_ENABLE_CACHE_MESSAGE,
6
- UNSYNCED_OBJECT_CACHED_AT_MESSAGE,
7
- UNSYNCED_OBJECT_CACHED_AT_VALUE,
8
- } from '~/utils/constants';
9
- import { hasUpdates } from '~/core/model';
1
+ import { liveObject } from '~/utils/liveObject';
10
2
  import { getMessage } from '../api';
11
3
  import {
12
4
  onMessageUpdated,
@@ -42,78 +34,14 @@ export const liveMessage = (
42
34
  messageId: Amity.Message['messageId'],
43
35
  callback: Amity.LiveObjectCallback<Amity.Message>,
44
36
  ): Amity.Unsubscriber => {
45
- const { log, cache } = getActiveClient();
46
- const timestamp = Date.now();
47
- log(`liveMessage(tmpid: ${timestamp}) > listen`);
48
-
49
- if (!cache) {
50
- console.log(LIVE_OBJECT_ENABLE_CACHE_MESSAGE);
51
- }
52
-
53
- let message: Amity.Message;
54
- let isUnsyncedObject = false;
55
- const disposers: Amity.Unsubscriber[] = [];
56
-
57
- const dispatcher = (data: Amity.LiveObject<Amity.Message>) => {
58
- message = data.data;
59
- callback(data);
60
- };
61
-
62
- const realtimeRouter = (eventMessage: Amity.Message) => {
63
- if (messageId !== eventMessage.messageId) {
64
- return;
65
- }
66
-
67
- if (message && !hasUpdates(message, eventMessage)) {
68
- return;
69
- }
70
-
71
- dispatcher({ loading: false, data: eventMessage, origin: 'event' });
72
- };
73
-
74
- const onFetch = () => {
75
- const query = createQuery(getMessage, messageId, true);
76
-
77
- runQuery(query, ({ loading, data, error, origin, cachedAt }) => {
78
- if (cachedAt === UNSYNCED_OBJECT_CACHED_AT_VALUE) {
79
- dispatcher({
80
- data,
81
- origin,
82
- loading: false,
83
- error: new ASCApiError(
84
- UNSYNCED_OBJECT_CACHED_AT_MESSAGE,
85
- Amity.ClientError.DISALOOW_UNSYNCED_OBJECT,
86
- Amity.ErrorLevel.ERROR,
87
- ),
88
- });
89
-
90
- isUnsyncedObject = true;
91
- disposers.forEach(fn => fn());
92
- } else if (!isUnsyncedObject) {
93
- dispatcher({ loading, data, origin, error });
94
- }
95
-
96
- if (error) {
97
- disposers.forEach(fn => fn());
98
- }
99
- });
100
- };
101
-
102
- disposers.push(
103
- onMessageFetched(realtimeRouter),
104
- onMessageUpdated(realtimeRouter),
105
- onMessageDeleted(realtimeRouter),
106
- onMessageFlagged(realtimeRouter),
107
- onMessageUnflagged(realtimeRouter),
108
- onMessageFlagCleared(realtimeRouter),
109
- onMessageReactionAdded(realtimeRouter),
110
- onMessageReactionRemoved(realtimeRouter),
111
- );
112
-
113
- onFetch();
114
-
115
- return () => {
116
- log(`liveMessage(tmpid: ${timestamp}) > dispose`);
117
- disposers.forEach(fn => fn());
118
- };
37
+ return liveObject(messageId, callback, 'messageId', getMessage, [
38
+ onMessageFetched,
39
+ onMessageUpdated,
40
+ onMessageDeleted,
41
+ onMessageFlagged,
42
+ onMessageUnflagged,
43
+ onMessageFlagCleared,
44
+ onMessageReactionAdded,
45
+ onMessageReactionRemoved,
46
+ ]);
119
47
  };