@amityco/ts-sdk 0.0.1-beta.42.2 → 0.0.1-beta.43

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 (308) hide show
  1. package/dist/@types/core/events.d.ts +11 -1
  2. package/dist/@types/core/events.d.ts.map +1 -1
  3. package/dist/@types/core/marker.d.ts +37 -0
  4. package/dist/@types/core/marker.d.ts.map +1 -0
  5. package/dist/@types/core/model.d.ts +10 -0
  6. package/dist/@types/core/model.d.ts.map +1 -1
  7. package/dist/@types/core/payload.d.ts +44 -0
  8. package/dist/@types/core/payload.d.ts.map +1 -1
  9. package/dist/@types/domains/channel.d.ts +5 -8
  10. package/dist/@types/domains/channel.d.ts.map +1 -1
  11. package/dist/@types/domains/client.d.ts +1 -0
  12. package/dist/@types/domains/client.d.ts.map +1 -1
  13. package/dist/@types/domains/marker.d.ts +15 -0
  14. package/dist/@types/domains/marker.d.ts.map +1 -0
  15. package/dist/@types/domains/message.d.ts +3 -0
  16. package/dist/@types/domains/message.d.ts.map +1 -1
  17. package/dist/@types/domains/partials.d.ts +3 -0
  18. package/dist/@types/domains/partials.d.ts.map +1 -1
  19. package/dist/@types/domains/subChannel.d.ts +2 -0
  20. package/dist/@types/domains/subChannel.d.ts.map +1 -1
  21. package/dist/channel/api/getChannels.d.ts.map +1 -1
  22. package/dist/channel/api/index.d.ts +0 -2
  23. package/dist/channel/api/index.d.ts.map +1 -1
  24. package/dist/channel/events/onChannelUpdated.d.ts.map +1 -1
  25. package/dist/channel/utils/index.d.ts +1 -2
  26. package/dist/channel/utils/index.d.ts.map +1 -1
  27. package/dist/channel/utils/prepareChannelPayload.d.ts +6 -0
  28. package/dist/channel/utils/prepareChannelPayload.d.ts.map +1 -0
  29. package/dist/channel/utils/tests/prepareChannelPayload.test.d.ts +5 -1
  30. package/dist/channel/utils/tests/prepareChannelPayload.test.d.ts.map +1 -1
  31. package/dist/client/api/activeUser.d.ts +2 -2
  32. package/dist/client/api/activeUser.d.ts.map +1 -1
  33. package/dist/client/api/connectClient.d.ts.map +1 -1
  34. package/dist/client/api/index.d.ts +2 -0
  35. package/dist/client/api/index.d.ts.map +1 -1
  36. package/dist/client/api/markerSync.d.ts +21 -0
  37. package/dist/client/api/markerSync.d.ts.map +1 -0
  38. package/dist/client/observers/getTotalUnreadCount.d.ts +18 -0
  39. package/dist/client/observers/getTotalUnreadCount.d.ts.map +1 -0
  40. package/dist/client/observers/index.d.ts +2 -0
  41. package/dist/client/observers/index.d.ts.map +1 -0
  42. package/dist/client/observers/tests/getTotalUnreadCount.test.d.ts +2 -0
  43. package/dist/client/observers/tests/getTotalUnreadCount.test.d.ts.map +1 -0
  44. package/dist/client/utils/index.d.ts +2 -0
  45. package/dist/client/utils/index.d.ts.map +1 -0
  46. package/dist/client/utils/markerSyncEngine.d.ts +46 -0
  47. package/dist/client/utils/markerSyncEngine.d.ts.map +1 -0
  48. package/dist/comment/api/getComments.d.ts.map +1 -1
  49. package/dist/core/events.d.ts +3 -3
  50. package/dist/core/events.d.ts.map +1 -1
  51. package/dist/core/model/idResolvers.d.ts.map +1 -1
  52. package/dist/core/model/index.d.ts.map +1 -1
  53. package/dist/index.cjs.js +1931 -1159
  54. package/dist/index.d.ts +5 -0
  55. package/dist/index.d.ts.map +1 -1
  56. package/dist/index.esm.js +1901 -1160
  57. package/dist/index.umd.js +4 -4
  58. package/dist/marker/api/getChannelMarkers.d.ts +18 -0
  59. package/dist/marker/api/getChannelMarkers.d.ts.map +1 -0
  60. package/dist/marker/api/getMessageMarkers.d.ts +18 -0
  61. package/dist/marker/api/getMessageMarkers.d.ts.map +1 -0
  62. package/dist/marker/api/getSubChannelMarkers.d.ts +18 -0
  63. package/dist/marker/api/getSubChannelMarkers.d.ts.map +1 -0
  64. package/dist/marker/api/getUserMarker.d.ts +8 -0
  65. package/dist/marker/api/getUserMarker.d.ts.map +1 -0
  66. package/dist/marker/api/index.d.ts +5 -0
  67. package/dist/marker/api/index.d.ts.map +1 -0
  68. package/dist/marker/api/tests/getChannelMarkers.test.d.ts +2 -0
  69. package/dist/marker/api/tests/getChannelMarkers.test.d.ts.map +1 -0
  70. package/dist/marker/api/tests/getMessageMarkers.test.d.ts +2 -0
  71. package/dist/marker/api/tests/getMessageMarkers.test.d.ts.map +1 -0
  72. package/dist/marker/api/tests/getSubChannelMarkers.test.d.ts +2 -0
  73. package/dist/marker/api/tests/getSubChannelMarkers.test.d.ts.map +1 -0
  74. package/dist/marker/events/index.d.ts +7 -0
  75. package/dist/marker/events/index.d.ts.map +1 -0
  76. package/dist/marker/events/onChannelMarkerFetched.d.ts +17 -0
  77. package/dist/marker/events/onChannelMarkerFetched.d.ts.map +1 -0
  78. package/dist/marker/events/onFeedlMarkerFetched.d.ts +17 -0
  79. package/dist/marker/events/onFeedlMarkerFetched.d.ts.map +1 -0
  80. package/dist/marker/events/onMessageMarkerFetched.d.ts +17 -0
  81. package/dist/marker/events/onMessageMarkerFetched.d.ts.map +1 -0
  82. package/dist/marker/events/onSubChannelMarkerFetched.d.ts +17 -0
  83. package/dist/marker/events/onSubChannelMarkerFetched.d.ts.map +1 -0
  84. package/dist/marker/events/onSubChannelMarkerUpdated.d.ts +17 -0
  85. package/dist/marker/events/onSubChannelMarkerUpdated.d.ts.map +1 -0
  86. package/dist/marker/events/onUserMarkerFetched.d.ts +17 -0
  87. package/dist/marker/events/onUserMarkerFetched.d.ts.map +1 -0
  88. package/dist/message/api/getMessage.d.ts.map +1 -1
  89. package/dist/message/api/getMessages.d.ts.map +1 -1
  90. package/dist/message/api/index.d.ts +1 -0
  91. package/dist/message/api/index.d.ts.map +1 -1
  92. package/dist/message/api/markAsDelivered.d.ts +17 -0
  93. package/dist/message/api/markAsDelivered.d.ts.map +1 -0
  94. package/dist/message/api/queryMessages.d.ts.map +1 -1
  95. package/dist/message/api/tests/markAsDelivered.test.d.ts +2 -0
  96. package/dist/message/api/tests/markAsDelivered.test.d.ts.map +1 -0
  97. package/dist/message/api/updateMessage.d.ts.map +1 -1
  98. package/dist/message/events/index.d.ts +1 -0
  99. package/dist/message/events/index.d.ts.map +1 -1
  100. package/dist/message/events/onMessageCreated.d.ts +2 -1
  101. package/dist/message/events/onMessageCreated.d.ts.map +1 -1
  102. package/dist/message/events/onMessageUpdated.d.ts.map +1 -1
  103. package/dist/message/utils/index.d.ts +1 -18
  104. package/dist/message/utils/index.d.ts.map +1 -1
  105. package/dist/message/utils/prepareMessagePayload.d.ts +16 -0
  106. package/dist/message/utils/prepareMessagePayload.d.ts.map +1 -0
  107. package/dist/post/api/getPosts.d.ts.map +1 -1
  108. package/dist/post/api/tests/getPosts.test.d.ts +2 -0
  109. package/dist/post/api/tests/getPosts.test.d.ts.map +1 -0
  110. package/dist/report/api/createReport.d.ts.map +1 -1
  111. package/dist/report/api/deleteReport.d.ts.map +1 -1
  112. package/dist/subChannel/api/getSubChannels.d.ts.map +1 -1
  113. package/dist/subChannel/api/index.d.ts +2 -0
  114. package/dist/subChannel/api/index.d.ts.map +1 -1
  115. package/dist/subChannel/api/startReadingAPI.d.ts +17 -0
  116. package/dist/subChannel/api/startReadingAPI.d.ts.map +1 -0
  117. package/dist/subChannel/api/stopReadingAPI.d.ts +17 -0
  118. package/dist/subChannel/api/stopReadingAPI.d.ts.map +1 -0
  119. package/dist/subChannel/events/onSubChannelUpdated.d.ts +1 -1
  120. package/dist/subChannel/events/onSubChannelUpdated.d.ts.map +1 -1
  121. package/dist/subChannel/observers/liveSubChannel.d.ts.map +1 -1
  122. package/dist/subChannel/utils/index.d.ts +2 -7
  123. package/dist/subChannel/utils/index.d.ts.map +1 -1
  124. package/dist/subChannel/utils/markReadEngine.d.ts +33 -0
  125. package/dist/subChannel/utils/markReadEngine.d.ts.map +1 -0
  126. package/dist/subChannel/utils/prepareSubChannelPayload.d.ts +15 -0
  127. package/dist/subChannel/utils/prepareSubChannelPayload.d.ts.map +1 -0
  128. package/dist/utils/liveObject.d.ts +1 -1
  129. package/dist/utils/liveObject.d.ts.map +1 -1
  130. package/dist/utils/tests/client.d.ts +1 -0
  131. package/dist/utils/tests/client.d.ts.map +1 -1
  132. package/dist/utils/tests/dummy/channel.d.ts +4 -0
  133. package/dist/utils/tests/dummy/channel.d.ts.map +1 -1
  134. package/dist/utils/tests/dummy/comment.d.ts.map +1 -1
  135. package/dist/utils/tests/dummy/index.d.ts +1 -0
  136. package/dist/utils/tests/dummy/index.d.ts.map +1 -1
  137. package/dist/utils/tests/dummy/marker.d.ts +6 -0
  138. package/dist/utils/tests/dummy/marker.d.ts.map +1 -0
  139. package/dist/utils/tests/dummy/message.d.ts +2 -0
  140. package/dist/utils/tests/dummy/message.d.ts.map +1 -1
  141. package/dist/utils/tests/dummy/subChannel.d.ts +1 -0
  142. package/dist/utils/tests/dummy/subChannel.d.ts.map +1 -1
  143. package/dist/utils/tests/utils.d.ts.map +1 -1
  144. package/package.json +1 -1
  145. package/src/@types/core/events.ts +13 -1
  146. package/src/@types/core/marker.ts +42 -0
  147. package/src/@types/core/model.ts +12 -0
  148. package/src/@types/core/payload.ts +52 -0
  149. package/src/@types/domains/channel.ts +5 -16
  150. package/src/@types/domains/client.ts +2 -0
  151. package/src/@types/domains/marker.ts +15 -0
  152. package/src/@types/domains/message.ts +3 -0
  153. package/src/@types/domains/partials.ts +4 -0
  154. package/src/@types/domains/subChannel.ts +2 -0
  155. package/src/channel/api/addChannelMembers.ts +1 -1
  156. package/src/channel/api/addChannelMembersRole.ts +1 -1
  157. package/src/channel/api/banChannelMembers.ts +1 -1
  158. package/src/channel/api/createChannel.ts +1 -1
  159. package/src/channel/api/getChannel.ts +1 -1
  160. package/src/channel/api/getChannels.ts +21 -5
  161. package/src/channel/api/index.ts +0 -3
  162. package/src/channel/api/joinChannel.ts +1 -1
  163. package/src/channel/api/leaveChannel.ts +1 -1
  164. package/src/channel/api/queryChannelMembers.ts +1 -1
  165. package/src/channel/api/queryChannels.ts +3 -3
  166. package/src/channel/api/removeChannelMembers.ts +1 -1
  167. package/src/channel/api/removeChannelMembersRole.ts +1 -1
  168. package/src/channel/api/tests/addChannelMembers.test.ts +16 -0
  169. package/src/channel/api/tests/createChannel.test.ts +29 -8
  170. package/src/channel/api/tests/getChannel.test.ts +11 -4
  171. package/src/channel/api/tests/getChannels.test.ts +22 -14
  172. package/src/channel/api/tests/queryChannelMembers.test.ts +13 -4
  173. package/src/channel/api/tests/queryChannels.test.ts +19 -9
  174. package/src/channel/api/unbanChannelMembers.ts +1 -1
  175. package/src/channel/api/updateChannel.ts +1 -1
  176. package/src/channel/events/onChannelCreated.ts +2 -2
  177. package/src/channel/events/onChannelDeleted.ts +4 -4
  178. package/src/channel/events/onChannelJoined.ts +2 -2
  179. package/src/channel/events/onChannelLeft.ts +2 -2
  180. package/src/channel/events/onChannelMemberAdded.ts +2 -2
  181. package/src/channel/events/onChannelMemberBanned.ts +3 -3
  182. package/src/channel/events/onChannelMemberRemoved.ts +2 -2
  183. package/src/channel/events/onChannelMemberUnbanned.ts +2 -2
  184. package/src/channel/events/onChannelMuted.ts +2 -2
  185. package/src/channel/events/onChannelUpdated.ts +25 -4
  186. package/src/channel/events/tests/onChannelCreated.test.ts +4 -1
  187. package/src/channel/events/tests/onChannelJoined.test.ts +5 -1
  188. package/src/channel/events/tests/onChannelMemberAdded.test.ts +5 -1
  189. package/src/channel/events/tests/onChannelMemberBanned.test.ts +4 -1
  190. package/src/channel/events/tests/onChannelMemberRemoved.test.ts +5 -1
  191. package/src/channel/events/tests/onChannelMemberUnbanned.test.ts +10 -10
  192. package/src/channel/events/tests/onChannelUpdated.test.ts +5 -1
  193. package/src/channel/observers/tests/liveChannelMembers.test.ts +5 -11
  194. package/src/channel/observers/tests/liveChannels.test.ts +21 -24
  195. package/src/channel/utils/index.ts +1 -57
  196. package/src/channel/utils/prepareChannelPayload.ts +91 -0
  197. package/src/channel/utils/tests/prepareChannelPayload.test.ts +102 -104
  198. package/src/client/api/activeUser.ts +2 -2
  199. package/src/client/api/connectClient.ts +2 -1
  200. package/src/client/api/index.ts +3 -0
  201. package/src/client/api/markerSync.ts +42 -0
  202. package/src/client/observers/getTotalUnreadCount.ts +52 -0
  203. package/src/client/observers/index.ts +1 -0
  204. package/src/client/observers/tests/getTotalUnreadCount.test.ts +126 -0
  205. package/src/client/utils/index.ts +1 -0
  206. package/src/client/utils/markerSyncEngine.ts +179 -0
  207. package/src/comment/api/getComments.ts +20 -4
  208. package/src/comment/api/tests/getComments.test.ts +12 -1
  209. package/src/comment/api/tests/queryComments.test.ts +2 -2
  210. package/src/core/model/idResolvers.ts +7 -0
  211. package/src/core/model/identifyModel.ts +1 -1
  212. package/src/core/model/index.ts +6 -0
  213. package/src/core/tests/query/query/runQuery.test.ts +3 -1
  214. package/src/group/utils/withUser.ts +2 -2
  215. package/src/index.ts +6 -0
  216. package/src/marker/api/getChannelMarkers.ts +53 -0
  217. package/src/marker/api/getMessageMarkers.ts +54 -0
  218. package/src/marker/api/getSubChannelMarkers.ts +54 -0
  219. package/src/marker/api/getUserMarker.ts +47 -0
  220. package/src/marker/api/index.ts +4 -0
  221. package/src/marker/api/tests/getChannelMarkers.test.ts +109 -0
  222. package/src/marker/api/tests/getMessageMarkers.test.ts +114 -0
  223. package/src/marker/api/tests/getSubChannelMarkers.test.ts +116 -0
  224. package/src/marker/events/index.ts +10 -0
  225. package/src/marker/events/onChannelMarkerFetched.ts +34 -0
  226. package/src/marker/events/onFeedlMarkerFetched.ts +34 -0
  227. package/src/marker/events/onMessageMarkerFetched.ts +34 -0
  228. package/src/marker/events/onSubChannelMarkerFetched.ts +34 -0
  229. package/src/marker/events/onSubChannelMarkerUpdated.ts +34 -0
  230. package/src/marker/events/onUserMarkerFetched.ts +34 -0
  231. package/src/message/api/createMessage.ts +1 -1
  232. package/src/message/api/getMessage.ts +6 -5
  233. package/src/message/api/getMessages.ts +7 -6
  234. package/src/message/api/index.ts +1 -0
  235. package/src/message/api/markAsDelivered.ts +36 -0
  236. package/src/message/api/queryMessages.ts +8 -6
  237. package/src/message/api/tests/createMessage.test.ts +13 -4
  238. package/src/message/api/tests/getMessage.test.ts +12 -3
  239. package/src/message/api/tests/getMessages.test.ts +14 -5
  240. package/src/message/api/tests/markAsDelivered.test.ts +83 -0
  241. package/src/message/api/tests/queryMessages.test.ts +14 -3
  242. package/src/message/api/updateMessage.ts +8 -7
  243. package/src/message/events/index.ts +2 -0
  244. package/src/message/events/onMessageCreated.ts +14 -41
  245. package/src/message/events/onMessageDeleted.ts +2 -2
  246. package/src/message/events/onMessageFlagCleared.ts +2 -2
  247. package/src/message/events/onMessageFlagged.ts +2 -2
  248. package/src/message/events/onMessageReactionAdded.ts +2 -2
  249. package/src/message/events/onMessageReactionRemoved.ts +2 -2
  250. package/src/message/events/onMessageUnflagged.ts +2 -2
  251. package/src/message/events/onMessageUpdated.ts +27 -5
  252. package/src/message/tests/events.test.ts +4 -2
  253. package/src/message/tests/observers/liveMessage.test.ts +22 -10
  254. package/src/message/tests/observers/liveMessages.test.ts +25 -18
  255. package/src/message/utils/index.ts +1 -140
  256. package/src/message/utils/prepareMessagePayload.ts +182 -0
  257. package/src/post/api/getPosts.ts +20 -4
  258. package/src/post/api/tests/getPosts.test.ts +18 -0
  259. package/src/reaction/events/onReactionAdded.ts +2 -2
  260. package/src/reaction/events/onReactionRemoved.ts +2 -2
  261. package/src/reaction/events/onReactorAdded.ts +2 -2
  262. package/src/reaction/events/onReactorRemoved.ts +2 -2
  263. package/src/report/api/createReport.ts +2 -1
  264. package/src/report/api/deleteReport.ts +2 -1
  265. package/src/subChannel/api/createSubChannel.ts +1 -1
  266. package/src/subChannel/api/getSubChannel.ts +1 -1
  267. package/src/subChannel/api/getSubChannels.ts +2 -1
  268. package/src/subChannel/api/index.ts +3 -0
  269. package/src/subChannel/api/querySubChannels.ts +1 -1
  270. package/src/subChannel/api/startReadingAPI.ts +33 -0
  271. package/src/subChannel/api/stopReadingAPI.ts +33 -0
  272. package/src/subChannel/api/tests/createSubChannel.test.ts +6 -3
  273. package/src/subChannel/api/tests/deleteSubChannel.test.ts +7 -5
  274. package/src/subChannel/api/tests/getSubChannel.test.ts +6 -4
  275. package/src/subChannel/api/tests/getSubChannels.test.ts +6 -3
  276. package/src/subChannel/api/tests/updateSubChannel.test.ts +6 -3
  277. package/src/subChannel/api/updateSubChannel.ts +1 -1
  278. package/src/subChannel/events/onSubChannelCreated.ts +2 -2
  279. package/src/subChannel/events/onSubChannelDeleted.ts +2 -2
  280. package/src/subChannel/events/onSubChannelUpdated.ts +43 -4
  281. package/src/subChannel/observers/liveSubChannel.ts +2 -0
  282. package/src/subChannel/observers/tests/liveSubChannel.test.ts +15 -10
  283. package/src/subChannel/observers/tests/liveSubChannels.test.ts +21 -14
  284. package/src/subChannel/utils/index.ts +2 -50
  285. package/src/subChannel/utils/markReadEngine.ts +117 -0
  286. package/src/subChannel/utils/prepareSubChannelPayload.ts +132 -0
  287. package/src/utils/liveObject.ts +15 -4
  288. package/src/utils/tests/client.ts +3 -1
  289. package/src/utils/tests/dummy/channel.ts +38 -21
  290. package/src/utils/tests/dummy/comment.ts +2 -2
  291. package/src/utils/tests/dummy/index.ts +1 -0
  292. package/src/utils/tests/dummy/marker.ts +68 -0
  293. package/src/utils/tests/dummy/message.ts +42 -2
  294. package/src/utils/tests/dummy/post.ts +1 -1
  295. package/src/utils/tests/dummy/subChannel.ts +16 -5
  296. package/src/utils/tests/utils.ts +4 -1
  297. package/dist/channel/api/startReading.d.ts +0 -17
  298. package/dist/channel/api/startReading.d.ts.map +0 -1
  299. package/dist/channel/api/stopReading.d.ts +0 -16
  300. package/dist/channel/api/stopReading.d.ts.map +0 -1
  301. package/dist/channel/api/tests/startReading.test.d.ts +0 -2
  302. package/dist/channel/api/tests/startReading.test.d.ts.map +0 -1
  303. package/dist/channel/api/tests/stopReading.test.d.ts +0 -2
  304. package/dist/channel/api/tests/stopReading.test.d.ts.map +0 -1
  305. package/src/channel/api/startReading.ts +0 -57
  306. package/src/channel/api/stopReading.ts +0 -53
  307. package/src/channel/api/tests/startReading.test.ts +0 -25
  308. package/src/channel/api/tests/stopReading.test.ts +0 -25
@@ -1,6 +1,5 @@
1
1
  /* eslint-disable no-param-reassign */
2
2
  /* eslint-disable require-atomic-updates */
3
- import { disconnectClient } from '~/client/api/disconnectClient';
4
3
  import { getDeviceId } from '~/core/device';
5
4
  import { proxyWebsocketEvents } from '~/core/events';
6
5
  import {
@@ -14,6 +13,8 @@ import {
14
13
 
15
14
  import { onUserDeleted } from '~/user/events/onUserDeleted';
16
15
 
16
+ import { disconnectClient } from './disconnectClient';
17
+
17
18
  import { getActiveClient } from './activeClient';
18
19
  import { terminateClient } from './terminateClient';
19
20
  import { setActiveUser, getActiveUser } from './activeUser';
@@ -1,4 +1,5 @@
1
1
  export { getActiveClient } from './activeClient';
2
+ export * from './activeUser';
2
3
 
3
4
  export * from './createClient';
4
5
 
@@ -10,3 +11,5 @@ export * from './isConnected';
10
11
  export * from './getFeedSettings';
11
12
 
12
13
  export * from './renewal';
14
+
15
+ export * from './markerSync';
@@ -0,0 +1,42 @@
1
+ import { fireEvent } from '~/core/events';
2
+ import { ingestInCache } from '~/cache/api/ingestInCache';
3
+
4
+ import { getActiveClient } from './activeClient';
5
+
6
+ /**
7
+ * ```js
8
+ * import { markerSync } from '@amityco/ts-sdk'
9
+ * const success = await markerSync()
10
+ * ```
11
+ *
12
+ * Make all markers synced
13
+ * * If response is empty means that the sync has ended.
14
+ * * If response is not empty, the sync has not ended. You must call markerSync
15
+ * again to continue syncing.
16
+ *
17
+ * @return {hasMore} A success boolean if the marker sync was ended.
18
+ *
19
+ * @category Marker API
20
+ * @async
21
+ * @private
22
+ */
23
+ export const markerSync = async (): Promise<{ hasMore: boolean }> => {
24
+ const client = getActiveClient();
25
+ client.log('channel/markerSync');
26
+
27
+ const { data: payload } = await client.http.post<Amity.MarkerSyncPayload>(`/api/v1/markers/sync`);
28
+
29
+ const { userEntityMarkers, userFeedMarkers, feedMarkers, userMarkers } = payload;
30
+
31
+ const cachedAt = client.cache && Date.now();
32
+ if (client.cache) ingestInCache(payload as Amity.MarkerSyncPayload, { cachedAt });
33
+
34
+ feedMarkers.length && fireEvent('local.feedMarker.fetched', { feedMarkers });
35
+ userEntityMarkers.length && fireEvent('local.channelMarker.fetched', { userEntityMarkers });
36
+ userFeedMarkers.length && fireEvent('local.subChannelMarker.fetched', { userFeedMarkers });
37
+ userMarkers.length && fireEvent('local.userMarker.fetched', { userMarkers });
38
+
39
+ return {
40
+ hasMore: payload.feedMarkers.length > 0,
41
+ };
42
+ };
@@ -0,0 +1,52 @@
1
+ import { ASCError } from '~/core/errors';
2
+ import { getUserMarker } from '~/marker/api';
3
+ import { onUserMarkerFetched } from '~/marker/events';
4
+ import { liveObject } from '~/utils/liveObject';
5
+
6
+ import { getActiveUser } from '../api';
7
+
8
+ /**
9
+ * ```js
10
+ * import { getTotalUnreadCount } from '@amityco/ts-sdk';
11
+ *
12
+ * const unsubscribe = getTotalUnreadCount(response => {
13
+ * totalUnreadCount = response.data;
14
+ * });
15
+ * ```
16
+ *
17
+ * Observe current user's unread count from {@link Amity.UserMarker}
18
+ *
19
+ * @param callback the function to call when new data are available
20
+ * @returns An {@link Amity.Unsubscriber} function to run when willing to stop observing the events
21
+ *
22
+ * @category Message Live Object
23
+ */
24
+ export const getTotalUnreadCount = (
25
+ callback: Amity.LiveObjectCallback<number>,
26
+ ): Amity.Unsubscriber => {
27
+ const { _id: userId } = getActiveUser();
28
+
29
+ if (!userId)
30
+ throw new ASCError(
31
+ 'The _id has not been defined in ActiveUser',
32
+ Amity.ClientError.UNKNOWN_ERROR,
33
+ Amity.ErrorLevel.ERROR,
34
+ );
35
+
36
+ const callbackPayloadSelector = (data: Amity.UserMarker) => data?.unreadCount ?? 0;
37
+
38
+ // based on the mobile specs, unreadCount will not trigger observer when userMarker
39
+ // is re-fetched, so apply this filter to ensure the behavior is the same.
40
+ const callbackFilter = (newModel: Amity.UserMarker, oldModel: Amity.UserMarker) =>
41
+ newModel?.unreadCount !== oldModel?.unreadCount;
42
+
43
+ return liveObject(
44
+ userId,
45
+ callback,
46
+ 'userId',
47
+ getUserMarker,
48
+ [onUserMarkerFetched],
49
+ callbackPayloadSelector,
50
+ callbackFilter,
51
+ );
52
+ };
@@ -0,0 +1 @@
1
+ export * from './getTotalUnreadCount';
@@ -0,0 +1,126 @@
1
+ import { getActiveUser, setActiveUser } from '~/client/api/activeUser';
2
+ import { getTotalUnreadCount } from '~/client/observers';
3
+ import { disableCache, enableCache, pushToCache } from '~/cache/api';
4
+ import { getResolver } from '~/core/model';
5
+ import { pause, client, connectClient, disconnectClient, generateUserMarker } from '~/utils/tests';
6
+
7
+ const refreshUpdateTime = <T extends ValueOf<Amity.Events>>(eventPayload: T): T => {
8
+ if (!eventPayload) return eventPayload;
9
+
10
+ // @ts-ignore
11
+ return Object.fromEntries(
12
+ Object.entries(eventPayload).map(([k, v]) => [
13
+ k,
14
+ v.map((model: Amity.Model) => ({
15
+ ...model,
16
+ updatedAt: Date.now(),
17
+ })),
18
+ ]),
19
+ );
20
+ };
21
+
22
+ const userId = 'user1';
23
+
24
+ describe('getTotalUnreadCount', () => {
25
+ beforeAll(async () => {
26
+ await connectClient();
27
+
28
+ // overwrite active userId with test id
29
+ setActiveUser({ ...getActiveUser(), _id: userId });
30
+ });
31
+
32
+ afterAll(disconnectClient);
33
+
34
+ beforeEach(enableCache);
35
+ afterEach(disableCache);
36
+
37
+ const events: [string, keyof Amity.Events, ValueOf<Amity.Events>, any][] = [
38
+ [
39
+ 'it should return correct payload on `onUserMarkerFetched`',
40
+ 'local.userMarker.fetched',
41
+ {
42
+ userMarkers: [generateUserMarker({ userId, unreadCount: 2 })],
43
+ },
44
+ {
45
+ origin: 'event',
46
+ loading: false,
47
+ data: 2,
48
+ },
49
+ ],
50
+ ];
51
+
52
+ test.each(events)('%s', async (test, event, eventPayload, expected) => {
53
+ const callback = jest.fn();
54
+
55
+ getTotalUnreadCount(callback);
56
+
57
+ await pause();
58
+
59
+ expect(callback).toHaveBeenCalledTimes(1);
60
+ // on initial, expect 0 unread count
61
+ expect(callback).toHaveBeenLastCalledWith({
62
+ origin: 'local',
63
+ loading: false,
64
+ error: undefined,
65
+ data: 0,
66
+ });
67
+
68
+ client.emitter.emit(event, refreshUpdateTime(eventPayload));
69
+
70
+ await pause();
71
+
72
+ expect(callback).toHaveBeenCalledTimes(2);
73
+ expect(callback).toHaveBeenLastCalledWith(expected);
74
+ });
75
+
76
+ test('it should trigger the initiate callback to align with the cache', async () => {
77
+ const callback = jest.fn();
78
+
79
+ pushToCache(
80
+ ['userMarker', 'get', getResolver('userMarker')({ userId })],
81
+ generateUserMarker({ userId, unreadCount: 1 }),
82
+ {
83
+ cachedAt: Date.now(),
84
+ },
85
+ );
86
+
87
+ getTotalUnreadCount(callback);
88
+
89
+ expect(callback).toHaveBeenCalledTimes(1);
90
+ expect(callback).toHaveBeenLastCalledWith({
91
+ origin: 'local',
92
+ loading: false,
93
+ error: undefined,
94
+ data: 1,
95
+ });
96
+ });
97
+
98
+ test('it should filter out duplicated callback', async () => {
99
+ const callback = jest.fn();
100
+
101
+ const eventPayload = {
102
+ userMarkers: [generateUserMarker({ userId, unreadCount: 2 })],
103
+ };
104
+
105
+ getTotalUnreadCount(callback);
106
+
107
+ await pause();
108
+
109
+ // initial callback
110
+ expect(callback).toHaveBeenCalledTimes(1);
111
+
112
+ client.emitter.emit('local.userMarker.fetched', refreshUpdateTime(eventPayload));
113
+
114
+ await pause();
115
+
116
+ expect(callback).toHaveBeenCalledTimes(2);
117
+
118
+ // emit duplicated event
119
+ client.emitter.emit('local.userMarker.fetched', refreshUpdateTime(eventPayload));
120
+
121
+ await pause();
122
+
123
+ // should not re-trigger
124
+ expect(callback).toHaveBeenCalledTimes(2);
125
+ });
126
+ });
@@ -0,0 +1 @@
1
+ export * from './markerSyncEngine';
@@ -0,0 +1,179 @@
1
+ import { onMessageCreated } from '~/message/events';
2
+ import { onSubChannelCreated, onSubChannelDeleted } from '~/subChannel/events';
3
+ import { isUnreadCountSupport } from '~/subChannel/utils';
4
+
5
+ import { markerSync } from '../api';
6
+
7
+ const FORCE_SYNC_INTERVAL_TIME = 8000;
8
+ const SYNC_TRIGGER_INTERVAL_TIME = 2000;
9
+
10
+ let clearSyncTrigger: Amity.Unsubscriber | undefined;
11
+ let disposers: (() => void)[] = [];
12
+ let isWaitingForResponse = false;
13
+
14
+ /**
15
+ * list of conditions that make timer still trigger the syncing process.
16
+ * If it's empty, it means sync is stopped.
17
+ * if it's not empty, sync will resume.
18
+ */
19
+ let events: Amity.MarkerSyncEvent[] = [];
20
+
21
+ /**
22
+ * get current marker sync event list
23
+ * @private
24
+ */
25
+ export const getMarkerSyncEvents = () => events;
26
+
27
+ /**
28
+ * set marker sync events
29
+ * @private
30
+ */
31
+ export const setMarkerSyncEvents = (newEvents: Amity.MarkerSyncEvent[]) => {
32
+ events = newEvents;
33
+ };
34
+
35
+ /**
36
+ * push new event to marker sync events
37
+ * @private
38
+ */
39
+ export const pushMarkerSyncEvent = (event: Amity.MarkerSyncEvent) => events.push(event);
40
+
41
+ /**
42
+ * interval task
43
+ * @private
44
+ */
45
+ export const markerSyncTrigger = async (markerSync: () => Promise<{ hasMore: boolean }>) => {
46
+ if (isWaitingForResponse) {
47
+ // waiting for the response no need to make another API call
48
+ return;
49
+ }
50
+
51
+ if (events.length === 0) {
52
+ // no event that require to call marker sync API
53
+ return;
54
+ }
55
+
56
+ isWaitingForResponse = true;
57
+
58
+ // any past events are considered processed here.
59
+ // however during waiting for the response, RTE could add the new message event;
60
+ // which will make the engine trigger another call next round.
61
+ events = [];
62
+
63
+ const response = await markerSync();
64
+
65
+ if (response.hasMore) {
66
+ events.push(Amity.MarkerSyncEvent.HAS_MORE);
67
+ }
68
+
69
+ // eslint-disable-next-line require-atomic-updates
70
+ isWaitingForResponse = false;
71
+ };
72
+
73
+ /**
74
+ * the event callback when app is back to online
75
+ */
76
+ const onOnline = () => {
77
+ // should add RESUME to the event to trigger marker syncing again
78
+ const callback = () => events.push(Amity.MarkerSyncEvent.RESUME);
79
+
80
+ window.addEventListener('online', callback);
81
+
82
+ return () => window.removeEventListener('online', callback);
83
+ };
84
+
85
+ const setIntervalTask = (handler: () => void, timeout: number) => {
86
+ const timer = setInterval(handler, timeout);
87
+ return () => clearInterval(timer);
88
+ };
89
+
90
+ const registerEventListeners = () => {
91
+ // based on the tech spec design, we designed a fetch marker in case of these events
92
+ // - new message
93
+ // - create channel
94
+ // - remove channel
95
+ // - app going to online again after offline
96
+ disposers.push(
97
+ onOnline(),
98
+
99
+ onMessageCreated(
100
+ message => {
101
+ // only conversation, community and broadcast types can sync
102
+ if (isUnreadCountSupport(message)) events.push(Amity.MarkerSyncEvent.NEW_MESSAGE);
103
+ },
104
+ // only trigger sync from remote events to prevent an unread count equal `-1`
105
+ // when an optimistic message creation is performed.
106
+ false,
107
+ ),
108
+
109
+ onSubChannelCreated(() => events.push(Amity.MarkerSyncEvent.SUB_CHANNEL_CREATED)),
110
+ onSubChannelDeleted(() => events.push(Amity.MarkerSyncEvent.SUBCHANNEL_IS_DELETED)),
111
+
112
+ // In real-world use, we've encountered some cases where BE returns empty result
113
+ // even if a marker changes in the database, causing the SDK to mistakenly believe that
114
+ // no changes have been made in the database and end the sync prematurely.
115
+ // Did miss update the unread count
116
+ //
117
+ // We found that some time BE loads were too high, causing the calculation
118
+ // marker not to finish within the sync time, so it returned an empty value.
119
+ //
120
+ // Therefore, solve this problem by creating a second interval loop that
121
+ // runs every 8 seconds regardless of whether an event occurs or not so that
122
+ // the unread count is always updated in case of an error like the above.
123
+ setIntervalTask(() => events.push(Amity.MarkerSyncEvent.FORCE_SYNC), FORCE_SYNC_INTERVAL_TIME),
124
+ );
125
+ };
126
+
127
+ const unRegisterEventListeners = () => {
128
+ disposers.forEach(fn => fn());
129
+ disposers = [];
130
+ };
131
+
132
+ /**
133
+ ```js
134
+ * import { startUnreadSync } from '@amityco/ts-sdk'
135
+ * startUnreadSync()
136
+ * ```
137
+ *
138
+ * start syncing to keep feed markers, channel markers and user makers cache
139
+ * update to the server.
140
+ *
141
+ * @category Marker API
142
+ */
143
+ export const startUnreadSync = () => {
144
+ pushMarkerSyncEvent(Amity.MarkerSyncEvent.START_SYNCING);
145
+
146
+ if (!clearSyncTrigger) {
147
+ // it is possible to repeatedly call the API when multiple events occur at the same time.
148
+ // This is very burdensome to the BE Server, so we have an interval loop for
149
+ // grouping every event that occurs within 2 seconds into a single API call.
150
+ //
151
+ // interval loop is also useful for fetching large results. Because if the result
152
+ // is more than 20 records, the API will split the result into multiple pages
153
+ // and the SDK will need to fetch it repeatedly until all the results are available.
154
+ // So we need an interval loop for repeat fetch.
155
+ clearSyncTrigger = setIntervalTask(
156
+ () => markerSyncTrigger(markerSync),
157
+ SYNC_TRIGGER_INTERVAL_TIME,
158
+ );
159
+ }
160
+
161
+ registerEventListeners();
162
+ };
163
+
164
+ /**
165
+ ```js
166
+ * import { stopUnreadSyncing } from '@amityco/ts-sdk'
167
+ * stopUnreadSyncing()
168
+ * ```
169
+ *
170
+ * stop unread syncing
171
+ *
172
+ * @category Marker API
173
+ */
174
+ export const stopUnreadSyncing = () => {
175
+ clearSyncTrigger?.();
176
+ clearSyncTrigger = undefined;
177
+ setMarkerSyncEvents([]);
178
+ unRegisterEventListeners();
179
+ };
@@ -2,6 +2,8 @@ import { getActiveClient } from '~/client/api';
2
2
 
3
3
  import { pullFromCache } from '~/cache/api';
4
4
  import { ingestInCache } from '~/cache/api/ingestInCache';
5
+ import { checkIfShouldGoesToTombstone } from '~/cache/utils';
6
+ import { pushToTombstone } from '~/cache/api/pushToTombstone';
5
7
 
6
8
  /* begin_public_function
7
9
  id: comment.get_by_ids
@@ -28,10 +30,24 @@ export const getComments = async (
28
30
 
29
31
  const encodedCommentIds = commentIds.map(commentId => encodeURIComponent(commentId));
30
32
 
31
- // API-FIX: endpoint should not be /list, parameters should be querystring.
32
- const { data } = await client.http.get<Amity.CommentPayload>(`/api/v3/comments/list`, {
33
- params: { commentIds: encodedCommentIds },
34
- });
33
+ let data: Amity.CommentPayload;
34
+
35
+ try {
36
+ // API-FIX: endpoint should not be /list, parameters should be querystring.
37
+ const response = await client.http.get<Amity.CommentPayload>(`/api/v3/comments/list`, {
38
+ params: { commentIds: encodedCommentIds },
39
+ });
40
+
41
+ data = response.data;
42
+ } catch (error) {
43
+ commentIds.forEach(commentId => {
44
+ if (checkIfShouldGoesToTombstone((error as Amity.ErrorResponse)?.code)) {
45
+ pushToTombstone('comment', commentId);
46
+ }
47
+ });
48
+
49
+ throw error;
50
+ }
35
51
 
36
52
  const cachedAt = client.cache && Date.now();
37
53
  if (client.cache) ingestInCache(data, { cachedAt });
@@ -1,5 +1,6 @@
1
1
  import { enableCache } from '~/cache/api';
2
- import { client, connectClient, disconnectClient, comment11, user11 } from '~/utils/tests';
2
+ import { client, comment11, connectClient, disconnectClient, user11 } from '~/utils/tests';
3
+ import { ASCApiError } from '~/core/errors';
3
4
  import { getComments } from '../getComments';
4
5
 
5
6
  const apiResponse = {
@@ -33,4 +34,14 @@ describe('getComments', () => {
33
34
 
34
35
  expect(comments?.data).toEqual(commentsListResponse.data);
35
36
  });
37
+
38
+ test('Should return Error: 400400 when getComments from invalid commentId', async () => {
39
+ client.http.get = jest
40
+ .fn()
41
+ .mockRejectedValueOnce(
42
+ new ASCApiError('not found!', Amity.ServerError.ITEM_NOT_FOUND, Amity.ErrorLevel.ERROR),
43
+ );
44
+
45
+ await expect(getComments([comment11.commentId])).rejects.toThrow();
46
+ });
36
47
  });
@@ -1,5 +1,3 @@
1
- import { queryComments } from '../queryComments';
2
-
3
1
  import {
4
2
  client,
5
3
  connectClient,
@@ -18,6 +16,8 @@ import {
18
16
  } from '~/utils/tests';
19
17
  import { ASCApiError } from '~/core/errors';
20
18
 
19
+ import { queryComments } from '../queryComments';
20
+
21
21
  type mockParamAndResponse = {
22
22
  query: Amity.QueryComments;
23
23
  response: Amity.Comment[];
@@ -20,6 +20,13 @@ const idResolvers: Resolvers = {
20
20
  channelUsers: ({ channelId, userId }) => `${channelId}#${userId}`,
21
21
  message: ({ messageId }) => messageId,
22
22
 
23
+ channelMarker: ({ entityId, userId }) => `${entityId}#${userId}`,
24
+ subChannelMarker: ({ entityId, feedId, userId }) => `${entityId}#${feedId}#${userId}`,
25
+ messageMarker: ({ feedId, contentId, creatorId }) => `${feedId}#${contentId}#${creatorId}`,
26
+ feedMarker: ({ feedId, entityId }) => `${feedId}#${entityId}`,
27
+
28
+ userMarker: ({ userId }) => userId,
29
+
23
30
  community: ({ communityId }) => communityId,
24
31
  category: ({ categoryId }) => categoryId,
25
32
  communityUsers: ({ communityId, userId }) => `${communityId}#${userId}`,
@@ -6,7 +6,7 @@
6
6
  * @hidden
7
7
  */
8
8
  type Criterias<T extends Amity.Domain = Amity.Domain> = {
9
- [K in T]: (keyof Amity.Models[K])[];
9
+ [K in T]?: (keyof Amity.Models[K])[];
10
10
  };
11
11
 
12
12
  /**
@@ -15,6 +15,12 @@ export const PAYLOAD2MODEL: Record<string, Amity.Domain> = {
15
15
  channelUsers: 'channelUsers',
16
16
  messages: 'message',
17
17
 
18
+ userEntityMarkers: 'channelMarker',
19
+ userFeedMarkers: 'subChannelMarker',
20
+ contentMarkers: 'messageMarker',
21
+ feedMarkers: 'feedMarker',
22
+ userMarkers: 'userMarker',
23
+
18
24
  communities: 'community',
19
25
  categories: 'category',
20
26
  communityUsers: 'communityUsers',
@@ -20,8 +20,10 @@ const post = { postId: posts.page1[0] };
20
20
  const deletingMsgId = 'deletingId';
21
21
 
22
22
  describe('Core/Query/runQuery', () => {
23
- beforeEach(enableCache);
23
+ beforeAll(enableCache);
24
+ afterAll(disableCache);
24
25
 
26
+ beforeEach(enableCache);
25
27
  afterEach(disableCache);
26
28
 
27
29
  test('should call query with arguments', () => {
@@ -1,5 +1,5 @@
1
- import { pullFromCache } from '~/cache/api';
2
- import { getActiveClient } from '~/client/api';
1
+ import { pullFromCache } from '~/cache/api/pullFromCache';
2
+ import { getActiveClient } from '~/client/api/activeClient';
3
3
 
4
4
  /**
5
5
  * Attach user object to membership model
package/src/index.ts CHANGED
@@ -10,6 +10,8 @@ export * from './cache/api';
10
10
 
11
11
  export * from './client/api';
12
12
  export * from './client/events';
13
+ export * from './client/observers';
14
+ export * from './client/utils';
13
15
  export { API_REGIONS } from './client/utils/endpoints';
14
16
 
15
17
  // asc core
@@ -37,11 +39,15 @@ export * from './channel/observers';
37
39
  export * from './subChannel/api';
38
40
  export * from './subChannel/events';
39
41
  export * from './subChannel/observers';
42
+ export * from './subChannel/utils';
40
43
 
41
44
  export * from './message/api';
42
45
  export * from './message/events';
43
46
  export * from './message/observers';
44
47
 
48
+ export * from './marker/api';
49
+ export * from './marker/events';
50
+
45
51
  // // asc social
46
52
  export * from './community/api';
47
53
  export * from './community/events';
@@ -0,0 +1,53 @@
1
+ import { getActiveClient } from '~/client/api/activeClient';
2
+ import { fireEvent } from '~/core/events';
3
+ import { toPage, toToken } from '~/core/query';
4
+ import { ingestInCache } from '~/cache/api/ingestInCache';
5
+
6
+ /**
7
+ * ```js
8
+ * import { getChannelMarker } from '@amityco/ts-sdk'
9
+ * const channelMarkers = await getChannelMarkers(['ch1', 'ch2'])
10
+ * ```
11
+ *
12
+ * Fetches a paginable list of {@link Amity.ChannelMarker} objects
13
+ *
14
+ * @param channelIds the IDs of the {@link Amity.RawChannel} marker to fetch
15
+ * @param page
16
+ * @returns A page of {@link Amity.ChannelMarker} objects
17
+ *
18
+ * @category Channel API
19
+ * @async
20
+ * @private
21
+ */
22
+ export const getChannelMarkers = async (
23
+ channelIds: Amity.Channel['channelId'][],
24
+ page: Amity.Page = { limit: 100 },
25
+ ): Promise<Amity.Cached<Amity.Paged<Amity.ChannelMarker>>> => {
26
+ const client = getActiveClient();
27
+ client.log('channel/getChannelMarkers', channelIds, page);
28
+
29
+ const { data: queryPayload } = await client.http.get<
30
+ Amity.ChannelMarkerPayload & Amity.Pagination
31
+ >(`/api/v1/markers/channels`, {
32
+ params: {
33
+ channelIds,
34
+ options: {
35
+ token: toToken(page, 'skiplimit'),
36
+ },
37
+ },
38
+ });
39
+
40
+ const { paging, ...payload } = queryPayload;
41
+ const { userEntityMarkers, userMarkers } = payload;
42
+
43
+ const cachedAt = client.cache && Date.now();
44
+ if (client.cache) ingestInCache(payload as Amity.ChannelMarkerPayload, { cachedAt });
45
+
46
+ userEntityMarkers.length && fireEvent('local.channelMarker.fetched', { userEntityMarkers });
47
+ userMarkers.length && fireEvent('local.userMarker.fetched', { userMarkers });
48
+
49
+ const nextPage = toPage(paging.next);
50
+ const prevPage = toPage(paging.previous);
51
+
52
+ return { data: userEntityMarkers, cachedAt, prevPage, nextPage };
53
+ };