@amityco/ts-sdk 0.0.1-beta.24 → 0.0.1-beta.27

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 (199) hide show
  1. package/.eslintrc.json +4 -1
  2. package/dist/@types/core/events.d.ts +12 -8
  3. package/dist/@types/core/events.d.ts.map +1 -1
  4. package/dist/@types/core/live.d.ts +23 -0
  5. package/dist/@types/core/live.d.ts.map +1 -0
  6. package/dist/@types/core/paging.d.ts +1 -1
  7. package/dist/@types/core/paging.d.ts.map +1 -1
  8. package/dist/@types/core/payload.d.ts +3 -5
  9. package/dist/@types/core/payload.d.ts.map +1 -1
  10. package/dist/@types/domains/comment.d.ts +14 -0
  11. package/dist/@types/domains/comment.d.ts.map +1 -1
  12. package/dist/@types/domains/follow.d.ts +2 -1
  13. package/dist/@types/domains/follow.d.ts.map +1 -1
  14. package/dist/@types/domains/post.d.ts +17 -0
  15. package/dist/@types/domains/post.d.ts.map +1 -1
  16. package/dist/@types/domains/reaction.d.ts +10 -0
  17. package/dist/@types/domains/reaction.d.ts.map +1 -1
  18. package/dist/@types/index.d.ts +1 -0
  19. package/dist/@types/index.d.ts.map +1 -1
  20. package/dist/cache/api/ingestInCache.d.ts +1 -1
  21. package/dist/cache/api/ingestInCache.d.ts.map +1 -1
  22. package/dist/cache/api/mergeInCache.d.ts +1 -1
  23. package/dist/cache/api/mergeInCache.d.ts.map +1 -1
  24. package/dist/category/api/queryCategories.d.ts +3 -3
  25. package/dist/category/api/queryCategories.d.ts.map +1 -1
  26. package/dist/channel/api/banChannelMembers.d.ts +16 -0
  27. package/dist/channel/api/banChannelMembers.d.ts.map +1 -0
  28. package/dist/channel/api/index.d.ts +2 -0
  29. package/dist/channel/api/index.d.ts.map +1 -1
  30. package/dist/channel/api/queryChannels.d.ts +6 -6
  31. package/dist/channel/api/queryChannels.d.ts.map +1 -1
  32. package/dist/channel/api/unbanChannelMembers.d.ts +16 -0
  33. package/dist/channel/api/unbanChannelMembers.d.ts.map +1 -0
  34. package/dist/client/api/connectClient.d.ts +1 -1
  35. package/dist/client/api/connectClient.d.ts.map +1 -1
  36. package/dist/client/api/createClient.d.ts +1 -1
  37. package/dist/client/api/createClient.d.ts.map +1 -1
  38. package/dist/comment/api/queryComments.d.ts +1 -9
  39. package/dist/comment/api/queryComments.d.ts.map +1 -1
  40. package/dist/comment/observers/index.d.ts +1 -0
  41. package/dist/comment/observers/index.d.ts.map +1 -1
  42. package/dist/comment/observers/liveComments.d.ts +22 -0
  43. package/dist/comment/observers/liveComments.d.ts.map +1 -0
  44. package/dist/comment/observers/observeComments.d.ts.map +1 -1
  45. package/dist/community/api/getRecommendedCommunities.d.ts +1 -1
  46. package/dist/community/api/getRecommendedCommunities.d.ts.map +1 -1
  47. package/dist/community/api/getTopTrendingCommunities.d.ts +1 -1
  48. package/dist/community/api/getTopTrendingCommunities.d.ts.map +1 -1
  49. package/dist/community/api/queryCommunities.d.ts +7 -7
  50. package/dist/community/api/queryCommunities.d.ts.map +1 -1
  51. package/dist/core/debug.d.ts +1 -1
  52. package/dist/core/debug.d.ts.map +1 -1
  53. package/dist/core/events.d.ts +3 -3
  54. package/dist/core/events.d.ts.map +1 -1
  55. package/dist/core/query/paging.d.ts +2 -2
  56. package/dist/core/query/paging.d.ts.map +1 -1
  57. package/dist/core/query/query.d.ts +1 -1
  58. package/dist/core/query/query.d.ts.map +1 -1
  59. package/dist/core/tests/query/filtering.test.d.ts +2 -0
  60. package/dist/core/tests/query/filtering.test.d.ts.map +1 -0
  61. package/dist/core/tests/query/query.test.d.ts +2 -0
  62. package/dist/core/tests/query/query.test.d.ts.map +1 -0
  63. package/dist/core/transports/ws.d.ts +1 -1
  64. package/dist/core/transports/ws.d.ts.map +1 -1
  65. package/dist/external/api/createUserToken.d.ts +1 -1
  66. package/dist/external/api/createUserToken.d.ts.map +1 -1
  67. package/dist/feed/api/queryGlobalFeed.d.ts +4 -4
  68. package/dist/feed/api/queryGlobalFeed.d.ts.map +1 -1
  69. package/dist/follow/api/follow.d.ts.map +1 -1
  70. package/dist/follow/api/getFollowInfo.d.ts.map +1 -1
  71. package/dist/follow/api/queryFollowers.d.ts +4 -4
  72. package/dist/follow/api/queryFollowers.d.ts.map +1 -1
  73. package/dist/follow/api/queryFollowings.d.ts +4 -4
  74. package/dist/follow/api/queryFollowings.d.ts.map +1 -1
  75. package/dist/follow/api/utils.d.ts +4 -4
  76. package/dist/follow/api/utils.d.ts.map +1 -1
  77. package/dist/follow/events/utils.d.ts.map +1 -1
  78. package/dist/index.cjs.js +18341 -17625
  79. package/dist/index.d.ts +3 -0
  80. package/dist/index.d.ts.map +1 -1
  81. package/dist/index.esm.js +18329 -17626
  82. package/dist/index.umd.js +4 -19
  83. package/dist/poll/api/closePoll.d.ts.map +1 -1
  84. package/dist/poll/api/deletePoll.d.ts.map +1 -1
  85. package/dist/poll/api/votePoll.d.ts.map +1 -1
  86. package/dist/poll/events/index.d.ts +3 -0
  87. package/dist/poll/events/index.d.ts.map +1 -0
  88. package/dist/poll/events/onPollDeleted.d.ts +17 -0
  89. package/dist/poll/events/onPollDeleted.d.ts.map +1 -0
  90. package/dist/poll/events/onPollUpdated.d.ts +17 -0
  91. package/dist/poll/events/onPollUpdated.d.ts.map +1 -0
  92. package/dist/poll/observers/index.d.ts +2 -0
  93. package/dist/poll/observers/index.d.ts.map +1 -0
  94. package/dist/poll/observers/observePoll.d.ts +18 -0
  95. package/dist/poll/observers/observePoll.d.ts.map +1 -0
  96. package/dist/post/api/approvePost.d.ts +17 -0
  97. package/dist/post/api/approvePost.d.ts.map +1 -0
  98. package/dist/post/api/declinePost.d.ts +17 -0
  99. package/dist/post/api/declinePost.d.ts.map +1 -0
  100. package/dist/post/api/index.d.ts +2 -0
  101. package/dist/post/api/index.d.ts.map +1 -1
  102. package/dist/post/api/queryPosts.d.ts +1 -12
  103. package/dist/post/api/queryPosts.d.ts.map +1 -1
  104. package/dist/post/observers/index.d.ts +1 -0
  105. package/dist/post/observers/index.d.ts.map +1 -1
  106. package/dist/post/observers/livePosts.d.ts +22 -0
  107. package/dist/post/observers/livePosts.d.ts.map +1 -0
  108. package/dist/post/observers/observePosts.d.ts.map +1 -1
  109. package/dist/post/tests/api/getPost.test.d.ts +2 -0
  110. package/dist/post/tests/api/getPost.test.d.ts.map +1 -0
  111. package/dist/post/tests/api/queryPosts.test.d.ts +2 -0
  112. package/dist/post/tests/api/queryPosts.test.d.ts.map +1 -0
  113. package/dist/reaction/api/queryReactions.d.ts +1 -6
  114. package/dist/reaction/api/queryReactions.d.ts.map +1 -1
  115. package/dist/reaction/events/index.d.ts +3 -0
  116. package/dist/reaction/events/index.d.ts.map +1 -1
  117. package/dist/reaction/events/onReactorAdded.d.ts +19 -0
  118. package/dist/reaction/events/onReactorAdded.d.ts.map +1 -0
  119. package/dist/reaction/events/onReactorRemoved.d.ts +19 -0
  120. package/dist/reaction/events/onReactorRemoved.d.ts.map +1 -0
  121. package/dist/reaction/observers/index.d.ts +2 -0
  122. package/dist/reaction/observers/index.d.ts.map +1 -0
  123. package/dist/reaction/observers/liveReactions.d.ts +22 -0
  124. package/dist/reaction/observers/liveReactions.d.ts.map +1 -0
  125. package/dist/report/api/createReport.d.ts.map +1 -1
  126. package/dist/report/api/deleteReport.d.ts.map +1 -1
  127. package/dist/role/api/queryRoles.d.ts +4 -4
  128. package/dist/role/api/queryRoles.d.ts.map +1 -1
  129. package/dist/stream/api/queryStreams.d.ts +6 -6
  130. package/dist/stream/api/queryStreams.d.ts.map +1 -1
  131. package/dist/utils/constants.d.ts +3 -0
  132. package/dist/utils/constants.d.ts.map +1 -0
  133. package/dist/utils/tests/client.d.ts +3 -0
  134. package/dist/utils/tests/client.d.ts.map +1 -0
  135. package/dist/utils/tests/dummy.d.ts +8 -0
  136. package/dist/utils/tests/dummy.d.ts.map +1 -0
  137. package/dist/utils/tests/index.d.ts +3 -0
  138. package/dist/utils/tests/index.d.ts.map +1 -0
  139. package/jest.config.ts +15 -0
  140. package/package.json +21 -16
  141. package/src/@types/core/events.ts +13 -8
  142. package/src/@types/core/live.ts +28 -0
  143. package/src/@types/core/paging.ts +1 -1
  144. package/src/@types/core/payload.ts +5 -6
  145. package/src/@types/domains/comment.ts +31 -0
  146. package/src/@types/domains/follow.ts +3 -1
  147. package/src/@types/domains/post.ts +37 -0
  148. package/src/@types/domains/reaction.ts +17 -0
  149. package/src/@types/index.ts +1 -0
  150. package/src/channel/api/banChannelMembers.ts +41 -0
  151. package/src/channel/api/index.ts +3 -0
  152. package/src/channel/api/unbanChannelMembers.ts +41 -0
  153. package/src/comment/api/queryComments.ts +3 -9
  154. package/src/comment/observers/index.ts +1 -0
  155. package/src/comment/observers/liveComments.ts +172 -0
  156. package/src/comment/observers/observeComments.ts +1 -11
  157. package/src/core/query/query.ts +15 -2
  158. package/src/core/tests/query/filtering.test.ts +11 -0
  159. package/src/core/tests/query/query.test.ts +19 -0
  160. package/src/follow/api/acceptFollower.ts +1 -1
  161. package/src/follow/api/declineFollower.ts +1 -1
  162. package/src/follow/api/follow.ts +1 -4
  163. package/src/follow/api/getFollowInfo.ts +8 -5
  164. package/src/follow/api/queryFollowers.ts +5 -4
  165. package/src/follow/api/queryFollowings.ts +5 -4
  166. package/src/follow/api/unfollow.ts +1 -1
  167. package/src/follow/api/utils.ts +10 -10
  168. package/src/follow/events/utils.ts +9 -6
  169. package/src/index.ts +3 -0
  170. package/src/poll/api/closePoll.ts +3 -0
  171. package/src/poll/api/deletePoll.ts +3 -0
  172. package/src/poll/api/votePoll.ts +3 -0
  173. package/src/poll/events/index.ts +2 -0
  174. package/src/poll/events/onPollDeleted.ts +31 -0
  175. package/src/poll/events/onPollUpdated.ts +31 -0
  176. package/src/poll/observers/index.ts +1 -0
  177. package/src/poll/observers/observePoll.ts +67 -0
  178. package/src/post/api/approvePost.ts +48 -0
  179. package/src/post/api/declinePost.ts +48 -0
  180. package/src/post/api/index.ts +3 -0
  181. package/src/post/api/queryPosts.ts +3 -12
  182. package/src/post/observers/index.ts +1 -0
  183. package/src/post/observers/livePosts.ts +170 -0
  184. package/src/post/observers/observePosts.ts +1 -13
  185. package/src/post/tests/api/getPost.test.ts +88 -0
  186. package/src/post/tests/api/queryPosts.test.ts +23 -0
  187. package/src/reaction/api/queryReactions.ts +14 -14
  188. package/src/reaction/events/index.ts +4 -0
  189. package/src/reaction/events/onReactorAdded.ts +80 -0
  190. package/src/reaction/events/onReactorRemoved.ts +85 -0
  191. package/src/reaction/observers/index.ts +1 -0
  192. package/src/reaction/observers/liveReactions.ts +142 -0
  193. package/src/report/api/createReport.ts +7 -1
  194. package/src/report/api/deleteReport.ts +7 -1
  195. package/src/utils/constants.ts +2 -0
  196. package/src/utils/tests/client.ts +5 -0
  197. package/src/utils/tests/dummy.ts +7 -0
  198. package/src/utils/tests/index.ts +2 -0
  199. package/tsconfig.json +23 -22
@@ -1,5 +1,5 @@
1
1
  import { getActiveClient } from '~/client/api';
2
- import { toPage, toToken } from '~/core/query';
2
+ import { toPageRaw, toToken } from '~/core/query';
3
3
  import { ingestInCache } from '~/cache/api/ingestInCache';
4
4
  import { pullFromCache, pushToCache } from '~/cache/api';
5
5
  import { getResolver } from '~/core/model';
@@ -8,10 +8,10 @@ export const queryFollows = async (
8
8
  key: 'followers' | 'following',
9
9
  query: {
10
10
  userId: Amity.User['userId'];
11
- status?: 'all' | Exclude<Amity.FollowStatus['status'], 'none'>;
12
- page?: Amity.Page;
11
+ status?: Exclude<Amity.FollowStatusType, 'none'>;
12
+ page?: Amity.PageRaw;
13
13
  },
14
- ): Promise<Amity.Cached<Amity.Paged<Amity.FollowStatus>>> => {
14
+ ): Promise<Amity.Cached<Amity.Paged<Amity.FollowStatus, Amity.PageRaw>>> => {
15
15
  const client = getActiveClient();
16
16
  client.log(`follow/queryF${key.substring(1)}`, query);
17
17
 
@@ -22,7 +22,7 @@ export const queryFollows = async (
22
22
  {
23
23
  params: {
24
24
  ...params,
25
- token: toToken(page, 'skiplimit'),
25
+ token: toToken(page, 'afterbeforeraw'),
26
26
  },
27
27
  },
28
28
  );
@@ -43,8 +43,8 @@ export const queryFollows = async (
43
43
  pushToCache(cacheKey, { follows: follows.map(getResolver('follow')), paging });
44
44
  }
45
45
 
46
- const nextPage = toPage(paging.next);
47
- const prevPage = toPage(paging.previous);
46
+ const nextPage = toPageRaw(paging.next);
47
+ const prevPage = toPageRaw(paging.previous);
48
48
 
49
49
  return { data: follows, cachedAt, prevPage, nextPage };
50
50
  };
@@ -52,7 +52,7 @@ export const queryFollows = async (
52
52
  queryFollows.locally = (
53
53
  key: Parameters<typeof queryFollows>[0],
54
54
  query: Parameters<typeof queryFollows>[1],
55
- ): Amity.Cached<Amity.Paged<Amity.FollowStatus>> | undefined => {
55
+ ): Amity.Cached<Amity.Paged<Amity.FollowStatus, Amity.PageRaw>> | undefined => {
56
56
  const client = getActiveClient();
57
57
  client.log(`follow/queryF${key.substring(1)}.locally`, query);
58
58
 
@@ -73,8 +73,8 @@ queryFollows.locally = (
73
73
  .filter(Boolean)
74
74
  .map(({ data }) => data);
75
75
 
76
- const prevPage = toPage(data?.paging.previous);
77
- const nextPage = toPage(data?.paging.next);
76
+ const prevPage = toPageRaw(data?.paging.previous);
77
+ const nextPage = toPageRaw(data?.paging.next);
78
78
 
79
79
  return follows.length === data?.follows?.length
80
80
  ? { data: follows, cachedAt, prevPage, nextPage }
@@ -9,11 +9,11 @@ export const createFollowEventSubscriber = (
9
9
  ) => {
10
10
  const client = getActiveClient();
11
11
 
12
- const filter = (payload: Amity.FollowStatus) => {
12
+ const filter = (payload: Amity.FollowersPayload | Amity.FollowStatusPayload) => {
13
13
  if (!client.cache) {
14
- callback(payload);
14
+ callback(payload.follows[0]);
15
15
  } else {
16
- ingestInCache({ follows: [payload] });
16
+ ingestInCache(payload);
17
17
 
18
18
  const queries = [
19
19
  ...(queryCache(['followers', 'query']) ?? []),
@@ -21,11 +21,14 @@ export const createFollowEventSubscriber = (
21
21
  ];
22
22
 
23
23
  queries
24
- // @ts-ignore
25
- .filter(({ key }) => key[2].userId === payload.from || key[2].userId === payload.to)
24
+ .filter(
25
+ ({ key }) =>
26
+ // @ts-ignore
27
+ key[2].userId === payload.follows[0].from || key[2].userId === payload.follows[0].to,
28
+ )
26
29
  .forEach(({ key, data }) => upsertInCache(key, data as any, { cachedAt: -1 }));
27
30
 
28
- callback(payload);
31
+ callback(payload.follows[0]);
29
32
  }
30
33
  };
31
34
 
package/src/index.ts CHANGED
@@ -25,6 +25,7 @@ export * from './role/api';
25
25
  // // asc partials
26
26
  export * from './reaction/api';
27
27
  export * from './reaction/events';
28
+ export * from './reaction/observers';
28
29
 
29
30
  export * from './report/api';
30
31
 
@@ -59,6 +60,8 @@ export * from './comment/events';
59
60
  export * from './comment/observers';
60
61
 
61
62
  export * from './poll/api';
63
+ export * from './poll/events';
64
+ export * from './poll/observers';
62
65
 
63
66
  export * from './stream/api';
64
67
  export * from './stream/events';
@@ -1,3 +1,4 @@
1
+ import { fireEvent } from '~/core/events';
1
2
  import { getActiveClient } from '~/client/api';
2
3
 
3
4
  import { ingestInCache } from '~/cache/api/ingestInCache';
@@ -30,6 +31,8 @@ export const closePoll = async (
30
31
  const cachedAt = client.cache && Date.now();
31
32
  if (client.cache) ingestInCache(data, { cachedAt });
32
33
 
34
+ fireEvent('poll.updated', data);
35
+
33
36
  const { polls } = data;
34
37
 
35
38
  return {
@@ -1,3 +1,4 @@
1
+ import { fireEvent } from '~/core/events';
1
2
  import { getActiveClient } from '~/client/api';
2
3
 
3
4
  import { upsertInCache } from '~/cache/api';
@@ -32,5 +33,7 @@ export const deletePoll = async (pollId: Amity.Poll['pollId']): Promise<boolean>
32
33
 
33
34
  upsertInCache(['poll', 'get', pollId], deleted);
34
35
 
36
+ fireEvent('poll.deleted', { polls: [deleted], users: [] });
37
+
35
38
  return success;
36
39
  };
@@ -1,3 +1,4 @@
1
+ import { fireEvent } from '~/core/events';
1
2
  import { getActiveClient } from '~/client/api';
2
3
 
3
4
  import { ingestInCache } from '~/cache/api/ingestInCache';
@@ -34,6 +35,8 @@ export const votePoll = async (
34
35
 
35
36
  const { polls } = data;
36
37
 
38
+ fireEvent('poll.updated', data);
39
+
37
40
  return {
38
41
  data: polls.find(poll => poll.pollId === pollId)!,
39
42
  cachedAt,
@@ -0,0 +1,2 @@
1
+ export * from './onPollUpdated';
2
+ export * from './onPollDeleted';
@@ -0,0 +1,31 @@
1
+ import { getActiveClient } from '~/client/api';
2
+ import { createEventSubscriber } from '~/core/events';
3
+
4
+ import { ingestInCache } from '~/cache/api/ingestInCache';
5
+
6
+ /**
7
+ * ```js
8
+ * import { onPollDeleted } from '@amityco/ts-sdk'
9
+ * const dispose = onPollDeleted(poll => {
10
+ * // ...
11
+ * })
12
+ * ```
13
+ *
14
+ * Fired when an {@link Amity.Poll} has been deleted
15
+ *
16
+ * @param callback The function to call when the event was fired
17
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
18
+ *
19
+ * @category Poll Events
20
+ */
21
+ export const onPollDeleted = (callback: Amity.Listener<Amity.Poll>): Amity.Unsubscriber => {
22
+ const client = getActiveClient();
23
+
24
+ const filter = (payload: Amity.PollPayload) => {
25
+ if (client.cache) ingestInCache(payload);
26
+
27
+ callback(payload.polls[0]);
28
+ };
29
+
30
+ return createEventSubscriber(client, 'poll/onPollDeleted', 'poll.deleted', filter);
31
+ };
@@ -0,0 +1,31 @@
1
+ import { getActiveClient } from '~/client/api';
2
+ import { createEventSubscriber } from '~/core/events';
3
+
4
+ import { ingestInCache } from '~/cache/api/ingestInCache';
5
+
6
+ /**
7
+ * ```js
8
+ * import { onPollUpdated } from '@amityco/ts-sdk'
9
+ * const dispose = onPollUpdated(poll => {
10
+ * // ...
11
+ * })
12
+ * ```
13
+ *
14
+ * Fired when an {@link Amity.Poll} has been updated
15
+ *
16
+ * @param callback The function to call when the event was fired
17
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
18
+ *
19
+ * @category Poll Events
20
+ */
21
+ export const onPollUpdated = (callback: Amity.Listener<Amity.Poll>): Amity.Unsubscriber => {
22
+ const client = getActiveClient();
23
+
24
+ const filter = (payload: Amity.PollPayload) => {
25
+ if (client.cache) ingestInCache(payload);
26
+
27
+ callback(payload.polls[0]);
28
+ };
29
+
30
+ return createEventSubscriber(client, 'poll/onPollUpdated', 'poll.updated', filter);
31
+ };
@@ -0,0 +1 @@
1
+ export * from './observePoll';
@@ -0,0 +1,67 @@
1
+ import { getActiveClient } from '~/client/api';
2
+
3
+ import { createQuery, runQuery, queryOptions } from '~/core/query';
4
+
5
+ import { getPoll } from '../api';
6
+
7
+ import { onPollUpdated, onPollDeleted } from '../events';
8
+
9
+ /**
10
+ * ```js
11
+ * import { observePoll } from '@amityco/ts-sdk'
12
+ *
13
+ * let poll = {}
14
+ * const dispose = observePoll(pollId, updated => poll = updated)
15
+ * ```
16
+ *
17
+ * Observe all mutation on a given {@link Amity.Poll}
18
+ *
19
+ * @param pollId the ID of the poll to observe
20
+ * @param callback the function to call when new data are available
21
+ * @returns An {@link Amity.Unsubscriber} function to run when willing to stop observing the poll
22
+ *
23
+ * @category Poll Observer
24
+ */
25
+ export const observePoll = <Events extends ['onFetch', 'onUpdate', 'onDelete']>(
26
+ pollId: string,
27
+ callback: Amity.ObjectListener<Amity.Snapshot<Amity.Poll | undefined>, Events>,
28
+ policy: Amity.QueryPolicy = 'cache_then_server',
29
+ ): Amity.Unsubscriber => {
30
+ const { log } = getActiveClient();
31
+
32
+ const timestamp = Date.now();
33
+ log(`observePoll(tmpid: ${timestamp}) > listen`);
34
+
35
+ // wrapper function to make sure
36
+ const router = (result: Amity.Snapshot<Amity.Poll | undefined>, action: Events[number]) => {
37
+ if (callback instanceof Function) return callback(result);
38
+
39
+ if (action !== 'onFetch') callback.onEvent?.(action, result);
40
+
41
+ callback[action]?.(result);
42
+ };
43
+
44
+ const realtimeRouter = (result: Amity.Snapshot<Amity.Poll>, action: Events[number]) => {
45
+ if (result.data?.pollId !== pollId) return;
46
+
47
+ router(result, action);
48
+ };
49
+
50
+ const disposers: Amity.Unsubscriber[] = [];
51
+
52
+ disposers.push(
53
+ onPollUpdated(data => realtimeRouter({ data, loading: false, origin: 'event' }, 'onUpdate')),
54
+ onPollDeleted(data => realtimeRouter({ data, loading: false, origin: 'event' }, 'onDelete')),
55
+ );
56
+
57
+ runQuery(
58
+ createQuery(getPoll, pollId),
59
+ result => (result.data || result.error) && router(result, 'onFetch'),
60
+ queryOptions(policy),
61
+ );
62
+
63
+ return () => {
64
+ log(`observePoll(tmpid: ${timestamp}) > dispose`);
65
+ disposers.forEach(fn => fn());
66
+ };
67
+ };
@@ -0,0 +1,48 @@
1
+ import { getActiveClient } from '~/client/api';
2
+
3
+ import { ingestInCache } from '~/cache/api/ingestInCache';
4
+ import { fireEvent } from '~/core/events';
5
+
6
+ /**
7
+ * ```js
8
+ * import { approvePost } from '@amityco/ts-sdk'
9
+ *
10
+ * const { data: post } = await approvePost('postId')
11
+ * ```
12
+ *
13
+ * Approves a {@link Amity.Post}
14
+ *
15
+ * @param postId The {@link Amity.Post} ID to be approved
16
+ * @return A {@link Amity.Post} that was approved
17
+ *
18
+ * @category Post API
19
+ * @async
20
+ */
21
+ export const approvePost = async (
22
+ postId: Amity.Post['postId'],
23
+ ): Promise<Amity.Cached<Amity.Post>> => {
24
+ const client = getActiveClient();
25
+ client.log('post/approvePost', postId);
26
+
27
+ const { data: approved } = await client.http.post<Amity.PostPayload>(
28
+ `/api/v3/posts/${encodeURIComponent(postId)}/approve`,
29
+ );
30
+
31
+ const cachedAt = client.cache && Date.now();
32
+ if (client.cache) ingestInCache(approved, { cachedAt });
33
+
34
+ // fire virtual event for community update
35
+ if (approved.posts[0].targetType === 'community') {
36
+ const community = approved.communities?.[0];
37
+
38
+ // @ts-ignore as communities is optional currently in PostPayload
39
+ fireEvent('community.updated', { communities: [community] });
40
+ }
41
+
42
+ fireEvent('post.approved', { posts: [approved.posts[0]] });
43
+
44
+ return {
45
+ data: approved.posts.find(post => post.postId === postId)!,
46
+ cachedAt,
47
+ };
48
+ };
@@ -0,0 +1,48 @@
1
+ import { getActiveClient } from '~/client/api';
2
+
3
+ import { ingestInCache } from '~/cache/api/ingestInCache';
4
+ import { fireEvent } from '~/core/events';
5
+
6
+ /**
7
+ * ```js
8
+ * import { declinePost } from '@amityco/ts-sdk'
9
+ *
10
+ * const {data: post} = await declinePost('postId')
11
+ * ```
12
+ *
13
+ * Declines a {@link Amity.Post}
14
+ *
15
+ * @param postId The {@link Amity.Post} ID to be declined
16
+ * @return A {@link Amity.Post} that was declined
17
+ *
18
+ * @category Post API
19
+ * @async
20
+ */
21
+ export const declinePost = async (
22
+ postId: Amity.Post['postId'],
23
+ ): Promise<Amity.Cached<Amity.Post>> => {
24
+ const client = getActiveClient();
25
+ client.log('post/declinePost', postId);
26
+
27
+ const { data: declined } = await client.http.post<Amity.PostPayload>(
28
+ `/api/v3/posts/${encodeURIComponent(postId)}/decline`,
29
+ );
30
+
31
+ const cachedAt = client.cache && Date.now();
32
+ if (client.cache) ingestInCache(declined, { cachedAt });
33
+
34
+ // fire virtual event
35
+ if (declined.posts[0].targetType === 'community') {
36
+ const community = declined.communities?.[0];
37
+
38
+ // @ts-ignore as communities is optional currently in PostPayload
39
+ fireEvent('community.updated', { communities: [community] });
40
+ }
41
+
42
+ fireEvent('post.declined', { posts: [declined.posts[0]] });
43
+
44
+ return {
45
+ data: declined.posts.find(post => post.postId === postId)!,
46
+ cachedAt,
47
+ };
48
+ };
@@ -5,3 +5,6 @@ export * from './getPost';
5
5
  export * from './createPost';
6
6
  export * from './updatePost';
7
7
  export * from './deletePost';
8
+
9
+ export * from './approvePost';
10
+ export * from './declinePost';
@@ -20,18 +20,9 @@ import { getResolver } from '~/core/model';
20
20
  * @category Post API
21
21
  * @async
22
22
  */
23
- export const queryPosts = async (query: {
24
- targetId: string;
25
- targetType: Amity.Post['targetType'];
26
- sortBy?: 'lastCreated' | 'firstCreated' | 'lastUpdated' | 'firstUpdated';
27
- dataType?: string;
28
- isDeleted?: Amity.Post['isDeleted'];
29
- hasFlag?: boolean;
30
- feedType?: 'reviewing' | 'published';
31
- tags?: Amity.Taggable['tags'];
32
- matchingOnlyParentPost?: boolean;
33
- page?: Amity.PageRaw;
34
- }): Promise<Amity.Cached<Amity.Paged<Amity.Post, Amity.PageRaw>>> => {
23
+ export const queryPosts = async (
24
+ query: Amity.QueryPosts,
25
+ ): Promise<Amity.Cached<Amity.Paged<Amity.Post, Amity.PageRaw>>> => {
35
26
  const client = getActiveClient();
36
27
  client.log('post/queryPosts', query);
37
28
 
@@ -1,2 +1,3 @@
1
1
  export * from './observePosts';
2
2
  export * from './observePost';
3
+ export * from './livePosts';
@@ -0,0 +1,170 @@
1
+ /* eslint-disable no-use-before-define */
2
+ import { getResolver } from '~/core/model';
3
+ import { getActiveClient } from '~/client/api';
4
+ import { pushToCache, pullFromCache } from '~/cache/api';
5
+ import {
6
+ createQuery,
7
+ runQuery,
8
+ queryOptions,
9
+ filterByPropEquality,
10
+ sortByFirstCreated,
11
+ sortByLastCreated,
12
+ } from '~/core/query';
13
+
14
+ import {
15
+ COLLECTION_DEFAULT_CACHING_POLICY,
16
+ COLLECTION_DEFAULT_PAGINATION_LIMIT,
17
+ } from '~/utils/constants';
18
+
19
+ import {
20
+ onPostCreated,
21
+ onPostUpdated,
22
+ onPostDeleted,
23
+ onPostApproved,
24
+ onPostDeclined,
25
+ onPostFlagged,
26
+ onPostUnflagged,
27
+ onPostReactionAdded,
28
+ onPostReactionRemoved,
29
+ } from '../events';
30
+ import { queryPosts } from '../api';
31
+
32
+ /**
33
+ * ```js
34
+ * import { livePosts } from '@amityco/ts-sdk'
35
+ *
36
+ * let posts = []
37
+ * const unsub = livePosts({
38
+ * targetType: Amity.PostTargetType,
39
+ * targetId: Amity.Post['targetId'],
40
+ * }, response => merge(posts, response.data))
41
+ * ```
42
+ *
43
+ * Observe all mutations on a list of {@link Amity.Post} for a given target object
44
+ *
45
+ * @param targetType the type of the target
46
+ * @param targetId the ID of the target
47
+ * @param callback the function to call when new data are available
48
+ * @returns An {@link Amity.Unsubscriber} function to run when willing to stop observing the messages
49
+ *
50
+ * @category Posts Live Collection
51
+ */
52
+ export const livePosts = (
53
+ params: Amity.PostLiveCollection,
54
+ callback: Amity.LiveCollectionCallback<Amity.Post>,
55
+ config?: Amity.LiveCollectionConfig,
56
+ ): Amity.Unsubscriber => {
57
+ const { log, cache } = getActiveClient();
58
+
59
+ if (!cache) {
60
+ console.log('For using Live Collection feature you need to enable Cache!');
61
+ }
62
+
63
+ const timestamp = Date.now();
64
+ log(`livePosts(tmpid: ${timestamp}) > listen`);
65
+
66
+ const { limit: queryLimit, ...queryParams } = params;
67
+
68
+ const limit = queryLimit ?? COLLECTION_DEFAULT_PAGINATION_LIMIT;
69
+ const { policy = COLLECTION_DEFAULT_CACHING_POLICY } = config ?? {};
70
+
71
+ const disposers: Amity.Unsubscriber[] = [];
72
+ const cacheKey = [
73
+ 'post',
74
+ 'collection',
75
+ { targetId: params.targetId, targetType: params.targetType },
76
+ ];
77
+
78
+ const responder = (data: Amity.PostLiveCollectionCache) => {
79
+ let posts: Amity.Post[] =
80
+ data.data
81
+ .map(postId => pullFromCache<Amity.Post>(['post', 'get', postId])!)
82
+ .filter(Boolean)
83
+ .map(({ data }) => data) ?? [];
84
+
85
+ posts = filterByPropEquality(posts, 'isDeleted', params.isDeleted);
86
+
87
+ const sortBy = params.sortBy ? params.sortBy : 'lastCreated';
88
+
89
+ posts = posts.sort(sortBy === 'lastCreated' ? sortByLastCreated : sortByFirstCreated);
90
+
91
+ callback({
92
+ onNextPage: onFetch,
93
+ data: posts,
94
+ hasNextPage: !!data.params?.page,
95
+ loading: data.loading,
96
+ error: data.error,
97
+ });
98
+ };
99
+
100
+ const realtimeRouter = (post: Amity.Post, action: Amity.PostActionType) => {
101
+ const collection = pullFromCache<Amity.PostLiveCollectionCache>(cacheKey)?.data;
102
+
103
+ if (params.targetId !== post.targetId || params.targetType !== post.targetType || !collection)
104
+ return;
105
+
106
+ if (action === 'onCreate') {
107
+ collection.data = [...new Set([post.postId, ...collection.data])];
108
+ } else if (['onDelete', 'onDeclined'].includes(action)) {
109
+ collection.data = collection.data.filter(p => p !== post.postId);
110
+ }
111
+
112
+ pushToCache(cacheKey, collection);
113
+
114
+ responder(collection);
115
+ };
116
+
117
+ const onFetch = () => {
118
+ const collection = pullFromCache<Amity.PostLiveCollectionCache>(cacheKey)?.data;
119
+
120
+ const posts = collection?.data ?? [];
121
+
122
+ if (posts.length > 0 && !collection?.params?.page) return;
123
+
124
+ const query = createQuery(queryPosts, {
125
+ ...queryParams,
126
+ page: collection?.params?.page ?? { limit },
127
+ });
128
+
129
+ runQuery(
130
+ query,
131
+ ({ data: result, error, loading, nextPage: page }) => {
132
+ const data = {
133
+ loading,
134
+ error,
135
+ params: { page },
136
+ data: posts,
137
+ };
138
+
139
+ if (result) {
140
+ data.data = [...new Set([...posts, ...result.map(getResolver('post'))])];
141
+ }
142
+
143
+ pushToCache(cacheKey, data);
144
+
145
+ responder(data);
146
+ },
147
+ queryOptions(policy),
148
+ );
149
+ };
150
+
151
+ disposers.push(
152
+ onPostCreated(post => realtimeRouter(post, 'onCreate')),
153
+ onPostApproved(post => realtimeRouter(post, 'onApproved')),
154
+ onPostDeclined(post => realtimeRouter(post, 'onDeclined')),
155
+ onPostDeleted(post => realtimeRouter(post, 'onDelete')),
156
+
157
+ onPostUpdated(post => realtimeRouter(post, 'onUpdate')),
158
+ onPostFlagged(post => realtimeRouter(post, 'onFlagged')),
159
+ onPostUnflagged(post => realtimeRouter(post, 'onUnflagged')),
160
+ onPostReactionAdded(post => realtimeRouter(post, 'onReactionAdded')),
161
+ onPostReactionRemoved(post => realtimeRouter(post, 'onReactionRemoved')),
162
+ );
163
+
164
+ onFetch();
165
+
166
+ return () => {
167
+ log(`livePosts(tmpid: ${timestamp}) > dispose`);
168
+ disposers.forEach(fn => fn());
169
+ };
170
+ };
@@ -59,19 +59,7 @@ export const observePosts = (
59
59
 
60
60
  const disposers: Amity.Unsubscriber[] = [];
61
61
 
62
- const router = (
63
- post: Amity.Post,
64
- action:
65
- | 'onCreate'
66
- | 'onUpdate'
67
- | 'onDelete'
68
- | 'onApproved'
69
- | 'onDeclined'
70
- | 'onFlagged'
71
- | 'onUnflagged'
72
- | 'onReactionAdded'
73
- | 'onReactionRemoved',
74
- ) => {
62
+ const router = (post: Amity.Post, action: Exclude<Amity.PostActionType, 'onFetch'>) => {
75
63
  if (params.targetId !== post.targetId || params.targetType !== post.targetType) return;
76
64
 
77
65
  if (callback instanceof Function) return callback(post);