@amityco/ts-sdk 0.0.1-beta.13 → 0.0.1-beta.16

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 (190) hide show
  1. package/README.md +3 -3
  2. package/dist/@types/core/cache.d.ts +2 -2
  3. package/dist/@types/core/cache.d.ts.map +1 -1
  4. package/dist/@types/core/events.d.ts +12 -3
  5. package/dist/@types/core/events.d.ts.map +1 -1
  6. package/dist/@types/core/model.d.ts +4 -0
  7. package/dist/@types/core/model.d.ts.map +1 -1
  8. package/dist/@types/core/paging.d.ts +22 -41
  9. package/dist/@types/core/paging.d.ts.map +1 -1
  10. package/dist/@types/core/payload.d.ts +10 -0
  11. package/dist/@types/core/payload.d.ts.map +1 -1
  12. package/dist/@types/core/query.d.ts +13 -4
  13. package/dist/@types/core/query.d.ts.map +1 -1
  14. package/dist/@types/domains/client.d.ts +0 -1
  15. package/dist/@types/domains/client.d.ts.map +1 -1
  16. package/dist/@types/domains/comment.d.ts +1 -2
  17. package/dist/@types/domains/comment.d.ts.map +1 -1
  18. package/dist/@types/domains/follow.d.ts +20 -0
  19. package/dist/@types/domains/follow.d.ts.map +1 -0
  20. package/dist/@types/domains/mention.d.ts +23 -0
  21. package/dist/@types/domains/mention.d.ts.map +1 -0
  22. package/dist/@types/domains/message.d.ts +1 -1
  23. package/dist/@types/domains/message.d.ts.map +1 -1
  24. package/dist/@types/domains/partials.d.ts +0 -10
  25. package/dist/@types/domains/partials.d.ts.map +1 -1
  26. package/dist/@types/domains/post.d.ts +1 -2
  27. package/dist/@types/domains/post.d.ts.map +1 -1
  28. package/dist/@types/index.d.ts +2 -0
  29. package/dist/@types/index.d.ts.map +1 -1
  30. package/dist/category/api/queryCategories.d.ts +2 -2
  31. package/dist/channel/api/createChannel.d.ts +1 -1
  32. package/dist/channel/api/queryChannelMembers.d.ts.map +1 -1
  33. package/dist/client/api/activeUser.d.ts +6 -0
  34. package/dist/client/api/activeUser.d.ts.map +1 -0
  35. package/dist/client/api/connectClient.d.ts.map +1 -1
  36. package/dist/client/api/createClient.d.ts +3 -3
  37. package/dist/client/api/createClient.d.ts.map +1 -1
  38. package/dist/client/utils/endpoints.d.ts +12 -0
  39. package/dist/client/utils/endpoints.d.ts.map +1 -0
  40. package/dist/community/api/getRecommendedCommunities.d.ts +32 -0
  41. package/dist/community/api/getRecommendedCommunities.d.ts.map +1 -0
  42. package/dist/community/api/getTopTrendingCommunities.d.ts +32 -0
  43. package/dist/community/api/getTopTrendingCommunities.d.ts.map +1 -0
  44. package/dist/community/api/index.d.ts +2 -0
  45. package/dist/community/api/index.d.ts.map +1 -1
  46. package/dist/core/debug.d.ts.map +1 -1
  47. package/dist/core/device.d.ts.map +1 -1
  48. package/dist/core/events.d.ts +3 -3
  49. package/dist/core/events.d.ts.map +1 -1
  50. package/dist/core/microtasks.d.ts +13 -0
  51. package/dist/core/microtasks.d.ts.map +1 -0
  52. package/dist/core/model/idResolvers.d.ts.map +1 -1
  53. package/dist/core/model/identifyModel.d.ts.map +1 -1
  54. package/dist/core/model/index.d.ts.map +1 -1
  55. package/dist/core/query/paging.d.ts +5 -16
  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/subscription.d.ts +2 -0
  60. package/dist/core/subscription.d.ts.map +1 -1
  61. package/dist/feed/api/queryGlobalFeed.d.ts +22 -4
  62. package/dist/feed/api/queryGlobalFeed.d.ts.map +1 -1
  63. package/dist/follow/api/acceptFollower.d.ts +16 -0
  64. package/dist/follow/api/acceptFollower.d.ts.map +1 -0
  65. package/dist/follow/api/declineFollower.d.ts +16 -0
  66. package/dist/follow/api/declineFollower.d.ts.map +1 -0
  67. package/dist/follow/api/follow.d.ts +16 -0
  68. package/dist/follow/api/follow.d.ts.map +1 -0
  69. package/dist/follow/api/getFollowInfo.d.ts +32 -0
  70. package/dist/follow/api/getFollowInfo.d.ts.map +1 -0
  71. package/dist/follow/api/index.d.ts +8 -0
  72. package/dist/follow/api/index.d.ts.map +1 -0
  73. package/dist/follow/api/queryFollowers.d.ts +36 -0
  74. package/dist/follow/api/queryFollowers.d.ts.map +1 -0
  75. package/dist/follow/api/queryFollowings.d.ts +36 -0
  76. package/dist/follow/api/queryFollowings.d.ts.map +1 -0
  77. package/dist/follow/api/unfollow.d.ts +16 -0
  78. package/dist/follow/api/unfollow.d.ts.map +1 -0
  79. package/dist/follow/api/utils.d.ts +9 -0
  80. package/dist/follow/api/utils.d.ts.map +1 -0
  81. package/dist/follow/events/index.d.ts +9 -0
  82. package/dist/follow/events/index.d.ts.map +1 -0
  83. package/dist/follow/events/onFollowInfoUpdated.d.ts +17 -0
  84. package/dist/follow/events/onFollowInfoUpdated.d.ts.map +1 -0
  85. package/dist/follow/events/onFollowRequestAccepted.d.ts +17 -0
  86. package/dist/follow/events/onFollowRequestAccepted.d.ts.map +1 -0
  87. package/dist/follow/events/onFollowRequestCanceled.d.ts +17 -0
  88. package/dist/follow/events/onFollowRequestCanceled.d.ts.map +1 -0
  89. package/dist/follow/events/onFollowRequestDeclined.d.ts +17 -0
  90. package/dist/follow/events/onFollowRequestDeclined.d.ts.map +1 -0
  91. package/dist/follow/events/onFollowerDeleted.d.ts +17 -0
  92. package/dist/follow/events/onFollowerDeleted.d.ts.map +1 -0
  93. package/dist/follow/events/onFollowerRequested.d.ts +17 -0
  94. package/dist/follow/events/onFollowerRequested.d.ts.map +1 -0
  95. package/dist/follow/events/onUserFollowed.d.ts +17 -0
  96. package/dist/follow/events/onUserFollowed.d.ts.map +1 -0
  97. package/dist/follow/events/onUserUnfollowed.d.ts +17 -0
  98. package/dist/follow/events/onUserUnfollowed.d.ts.map +1 -0
  99. package/dist/follow/events/utils.d.ts +2 -0
  100. package/dist/follow/events/utils.d.ts.map +1 -0
  101. package/dist/follow/observers/index.d.ts +4 -0
  102. package/dist/follow/observers/index.d.ts.map +1 -0
  103. package/dist/follow/observers/observeFollowInfo.d.ts +18 -0
  104. package/dist/follow/observers/observeFollowInfo.d.ts.map +1 -0
  105. package/dist/follow/observers/observeFollowers.d.ts +18 -0
  106. package/dist/follow/observers/observeFollowers.d.ts.map +1 -0
  107. package/dist/follow/observers/observeFollowings.d.ts +18 -0
  108. package/dist/follow/observers/observeFollowings.d.ts.map +1 -0
  109. package/dist/index.cjs.js +845 -74
  110. package/dist/index.d.ts +4 -0
  111. package/dist/index.d.ts.map +1 -1
  112. package/dist/index.esm.js +823 -74
  113. package/dist/index.umd.js +5 -5
  114. package/dist/message/api/createMessage.d.ts +2 -2
  115. package/dist/message/api/createMessage.d.ts.map +1 -1
  116. package/dist/message/api/updateMessage.d.ts +2 -2
  117. package/dist/message/api/updateMessage.d.ts.map +1 -1
  118. package/dist/post/api/queryPosts.d.ts +3 -3
  119. package/dist/post/api/queryPosts.d.ts.map +1 -1
  120. package/dist/utils/env.d.ts +5 -0
  121. package/dist/utils/env.d.ts.map +1 -0
  122. package/dist/version.d.ts.map +1 -1
  123. package/package.json +1 -1
  124. package/src/@types/core/cache.ts +2 -2
  125. package/src/@types/core/events.ts +12 -1
  126. package/src/@types/core/model.ts +6 -0
  127. package/src/@types/core/paging.ts +31 -46
  128. package/src/@types/core/payload.ts +14 -0
  129. package/src/@types/core/query.ts +11 -3
  130. package/src/@types/domains/client.ts +0 -1
  131. package/src/@types/domains/comment.ts +1 -3
  132. package/src/@types/domains/follow.ts +25 -0
  133. package/src/@types/domains/mention.ts +26 -0
  134. package/src/@types/domains/message.ts +1 -0
  135. package/src/@types/domains/partials.ts +0 -8
  136. package/src/@types/domains/post.ts +1 -3
  137. package/src/@types/index.ts +3 -0
  138. package/src/channel/api/createChannel.ts +1 -1
  139. package/src/channel/api/queryChannelMembers.ts +2 -1
  140. package/src/client/api/activeUser.ts +26 -0
  141. package/src/client/api/connectClient.ts +3 -1
  142. package/src/client/api/createClient.ts +7 -7
  143. package/src/client/utils/endpoints.ts +14 -0
  144. package/src/community/api/getRecommendedCommunities.ts +86 -0
  145. package/src/community/api/getTopTrendingCommunities.ts +86 -0
  146. package/src/community/api/index.ts +3 -0
  147. package/src/community/api/queryCommunityMembers.ts +1 -1
  148. package/src/core/debug.ts +3 -1
  149. package/src/core/device.ts +3 -2
  150. package/src/core/events.ts +3 -1
  151. package/src/core/microtasks.ts +27 -0
  152. package/src/core/model/idResolvers.ts +3 -0
  153. package/src/core/model/identifyModel.ts +2 -0
  154. package/src/core/model/index.ts +3 -0
  155. package/src/core/query/paging.ts +16 -51
  156. package/src/core/query/query.ts +5 -5
  157. package/src/core/subscription.ts +21 -3
  158. package/src/feed/api/queryGlobalFeed.ts +58 -5
  159. package/src/follow/api/acceptFollower.ts +32 -0
  160. package/src/follow/api/declineFollower.ts +32 -0
  161. package/src/follow/api/follow.ts +40 -0
  162. package/src/follow/api/getFollowInfo.ts +75 -0
  163. package/src/follow/api/index.ts +8 -0
  164. package/src/follow/api/queryFollowers.ts +42 -0
  165. package/src/follow/api/queryFollowings.ts +42 -0
  166. package/src/follow/api/unfollow.ts +32 -0
  167. package/src/follow/api/utils.ts +77 -0
  168. package/src/follow/events/index.ts +10 -0
  169. package/src/follow/events/onFollowInfoUpdated.ts +43 -0
  170. package/src/follow/events/onFollowRequestAccepted.ts +19 -0
  171. package/src/follow/events/onFollowRequestCanceled.ts +19 -0
  172. package/src/follow/events/onFollowRequestDeclined.ts +19 -0
  173. package/src/follow/events/onFollowerDeleted.ts +19 -0
  174. package/src/follow/events/onFollowerRequested.ts +19 -0
  175. package/src/follow/events/onUserFollowed.ts +19 -0
  176. package/src/follow/events/onUserUnfollowed.ts +19 -0
  177. package/src/follow/events/utils.ts +38 -0
  178. package/src/follow/observers/index.ts +3 -0
  179. package/src/follow/observers/observeFollowInfo.ts +68 -0
  180. package/src/follow/observers/observeFollowers.ts +78 -0
  181. package/src/follow/observers/observeFollowings.ts +78 -0
  182. package/src/index.ts +5 -0
  183. package/src/message/api/createMessage.ts +2 -2
  184. package/src/message/api/updateMessage.ts +2 -2
  185. package/src/post/api/queryPosts.ts +5 -5
  186. package/src/utils/env.ts +7 -0
  187. package/src/version.ts +3 -1
  188. package/dist/core/network.d.ts +0 -11
  189. package/dist/core/network.d.ts.map +0 -1
  190. package/src/core/network.ts +0 -14
@@ -0,0 +1,75 @@
1
+ import { getActiveClient } from '~/client/api'
2
+ import { pullFromCache, pushToCache } from '~/cache/api'
3
+
4
+ const getCacheKey = (userId: Amity.User['userId']) => ['followInfo', 'get', `${getActiveClient().userId}#${userId}`]
5
+
6
+ /**
7
+ * ```js
8
+ * import { getFollowInfo } from '@amityco/ts-sdk'
9
+ * const { data: followInfo } = await getFollowInfo('foobar')
10
+ * ```
11
+ *
12
+ * Fetches the number of followers, followings, pending requests and the follow status for current user
13
+ *
14
+ * @param userId the ID of the {@link Amity.User}
15
+ * @returns the associated {@link Amity.FollowInfo} object
16
+ *
17
+ * @category Follow API
18
+ * @async
19
+ */
20
+ export const getFollowInfo = async (userId: Amity.User['userId']): Promise<Amity.Cached<Amity.FollowInfo>> => {
21
+ const client = getActiveClient()
22
+ client.log('follow/getFollowInfo', userId)
23
+
24
+ const { data } = await client.http.get<Amity.FollowInfoPayload>(
25
+ client.userId === userId ? `/api/v4/me/followInfo` : `/api/v4/users/${userId}/followInfo`,
26
+ )
27
+
28
+ const cachedAt = client.cache && Date.now()
29
+ const followInfo = {
30
+ ...data.followCounts[0],
31
+ status: data.follows?.[0]?.status,
32
+ }
33
+
34
+ if (client.cache) {
35
+ pushToCache(getCacheKey(userId), followInfo, { cachedAt })
36
+ }
37
+
38
+ return {
39
+ data: followInfo,
40
+ cachedAt,
41
+ }
42
+ }
43
+
44
+ /**
45
+ * ```js
46
+ * import { getFollowInfo } from '@amityco/ts-sdk'
47
+ * const { data: followInfo } = getFollowInfo.locally('foobar')
48
+ * ```
49
+ *
50
+ * Fetches the number of followers, followings, pending requests and the follow status for current user from cache
51
+ *
52
+ * @param userId the ID of the {@link Amity.User}
53
+ * @returns the associated {@link Amity.FollowInfo} object
54
+ *
55
+ * @category Follow API
56
+ */
57
+ getFollowInfo.locally = (userId: Amity.User['userId']): Amity.Cached<Amity.FollowInfo> | undefined => {
58
+ const client = getActiveClient()
59
+ client.log('follow/getFollowInfo.locally', userId)
60
+
61
+ if (!client.cache) {
62
+ return
63
+ }
64
+
65
+ const cached = pullFromCache<Amity.FollowInfo>(getCacheKey(userId))
66
+
67
+ if (!cached) {
68
+ return
69
+ }
70
+
71
+ return {
72
+ data: cached.data,
73
+ cachedAt: cached.cachedAt,
74
+ }
75
+ }
@@ -0,0 +1,8 @@
1
+ export * from './queryFollowers'
2
+ export * from './queryFollowings'
3
+ export * from './getFollowInfo'
4
+
5
+ export * from './follow'
6
+ export * from './unfollow'
7
+ export * from './acceptFollower'
8
+ export * from './declineFollower'
@@ -0,0 +1,42 @@
1
+ import { queryFollows } from './utils'
2
+
3
+ /**
4
+ * ```js
5
+ * import { queryFollowers } from '@amityco/ts-sdk'
6
+ * const { data: followers, prevPage, nextPage } = await queryFollowers({ userId })
7
+ * ```
8
+ *
9
+ * Queries a paginable list of {@link Amity.FollowStatus}
10
+ *
11
+ * @param query The query parameters
12
+ * @returns followers
13
+ *
14
+ * @category Follow API
15
+ * @async
16
+ */
17
+ export const queryFollowers = async (
18
+ query: {
19
+ userId: Amity.User['userId']
20
+ status?: 'all' | Exclude<Amity.FollowStatus['status'], 'none'>,
21
+ page?: Amity.Page
22
+ }
23
+ ): Promise<Amity.Cached<Amity.Paged<Amity.FollowStatus>>> =>
24
+ queryFollows('followers', query)
25
+
26
+ /**
27
+ * ```js
28
+ * import { queryFollowers } from '@amityco/ts-sdk'
29
+ * const { data: followers, prevPage, nextPage } = queryFollowers.locally({ userId })
30
+ * ```
31
+ *
32
+ * Queries a paginable list of {@link Amity.FollowStatus} objects from cache
33
+ *
34
+ * @param query The query parameters
35
+ * @returns followers
36
+ *
37
+ * @category Post API
38
+ */
39
+ queryFollowers.locally = (
40
+ query: Parameters<typeof queryFollowers>[0],
41
+ ): Amity.Cached<Amity.Paged<Amity.FollowStatus>> | undefined =>
42
+ queryFollows.locally('followers', query)
@@ -0,0 +1,42 @@
1
+ import { queryFollows } from './utils'
2
+
3
+ /**
4
+ * ```js
5
+ * import { queryFollowings } from '@amityco/ts-sdk'
6
+ * const { data: followings, prevPage, nextPage } = await queryFollowings({ userId })
7
+ * ```
8
+ *
9
+ * Queries a paginable list of {@link Amity.FollowStatus}
10
+ *
11
+ * @param query The query parameters
12
+ * @returns followings
13
+ *
14
+ * @category Follow API
15
+ * @async
16
+ */
17
+ export const queryFollowings = async (
18
+ query: {
19
+ userId: Amity.User['userId']
20
+ status?: Exclude<Amity.FollowStatus['status'], 'none'>,
21
+ page?: Amity.Page
22
+ }
23
+ ): Promise<Amity.Cached<Amity.Paged<Amity.FollowStatus>>> =>
24
+ queryFollows('following', query)
25
+
26
+ /**
27
+ * ```js
28
+ * import { queryFollowings } from '@amityco/ts-sdk'
29
+ * const { data: followings, prevPage, nextPage } = queryFollowings.locally({ userId })
30
+ * ```
31
+ *
32
+ * Queries a paginable list of {@link Amity.FollowStatus} objects from cache
33
+ *
34
+ * @param query The query parameters
35
+ * @returns followings
36
+ *
37
+ * @category Post API
38
+ */
39
+ queryFollowings.locally = (
40
+ query: Parameters<typeof queryFollowings>[0],
41
+ ): Amity.Cached<Amity.Paged<Amity.FollowStatus>> | undefined =>
42
+ queryFollows.locally('following', query)
@@ -0,0 +1,32 @@
1
+ import { getActiveClient } from '~/client/api'
2
+ import { ingestInCache } from '~/cache/api/ingestInCache'
3
+ import { fireEvent } from '~/core/events'
4
+
5
+ /**
6
+ * ```js
7
+ * import { unfollow } from '@amityco/ts-sdk'
8
+ * await unfollow('foobar')
9
+ * ```
10
+ *
11
+ * Cancel the follow request or unfollow the user
12
+ *
13
+ * @param userId the ID of the {@link Amity.User}
14
+ * @returns A success boolean if the user {@link Amity.User} was unfollowed
15
+ *
16
+ * @category Follow API
17
+ * @async
18
+ */
19
+ export const unfollow = async (userId: Amity.User['userId']): Promise<boolean> => {
20
+ const client = getActiveClient()
21
+ client.log('follow/unfollow', userId)
22
+
23
+ const { data } = await client.http.delete<Amity.FollowStatusPayload>(`/api/v4/me/following/${userId}`)
24
+
25
+ if (client.cache) {
26
+ ingestInCache(data)
27
+ }
28
+
29
+ fireEvent('follow.unfollowed', data.follows[0])
30
+
31
+ return true
32
+ }
@@ -0,0 +1,77 @@
1
+ import { getActiveClient } from '~/client/api'
2
+ import { toPage, toToken } from '~/core/query'
3
+ import { ingestInCache } from '~/cache/api/ingestInCache'
4
+ import { pullFromCache, pushToCache } from '~/cache/api'
5
+ import { getResolver } from '~/core/model'
6
+
7
+ export const queryFollows = async (
8
+ key: 'followers' | 'following',
9
+ query: {
10
+ userId: Amity.User['userId']
11
+ status?: 'all' | Exclude<Amity.FollowStatus['status'], 'none'>,
12
+ page?: Amity.Page
13
+ },
14
+ ): Promise<Amity.Cached<Amity.Paged<Amity.FollowStatus>>> => {
15
+ const client = getActiveClient()
16
+ client.log(`follow/queryF${key.substring(1)}`, query)
17
+
18
+ const { userId, page, ...params } = query
19
+
20
+ const { data } = await client.http.get<Amity.FollowersPayload & Amity.Pagination>(
21
+ client.userId === userId ? `/api/v4/me/${key}` : `/api/v4/users/${userId}/${key}`,
22
+ {
23
+ params: {
24
+ ...params,
25
+ token: toToken(page, 'skiplimit'),
26
+ },
27
+ },
28
+ )
29
+
30
+ const { paging, ...payload } = data
31
+ const { follows } = payload
32
+
33
+ const cachedAt = client.cache && Date.now()
34
+
35
+ if (client.cache) {
36
+ ingestInCache(payload as Amity.FollowersPayload, { cachedAt })
37
+
38
+ const cacheKey = [key, 'query', { ...params, userId, options: { ...page } } as Amity.Serializable]
39
+ pushToCache(cacheKey, { follows: follows.map(getResolver('follow')), paging })
40
+ }
41
+
42
+ const nextPage = toPage(paging.next)
43
+ const prevPage = toPage(paging.previous)
44
+
45
+ return { data: follows, cachedAt, prevPage, nextPage }
46
+ }
47
+
48
+ queryFollows.locally = (
49
+ key: Parameters<typeof queryFollows>[0],
50
+ query: Parameters<typeof queryFollows>[1]
51
+ ): Amity.Cached<Amity.Paged<Amity.FollowStatus>> | undefined => {
52
+ const client = getActiveClient()
53
+ client.log(`follow/queryF${key.substring(1)}.locally`, query)
54
+
55
+ if (!client.cache) return
56
+
57
+ const { page, ...params } = query
58
+
59
+ const queryKey = [key, 'query', { ...params, options: { ...page } } as Amity.Serializable]
60
+ const { data, cachedAt } = pullFromCache<{ follows: string[] } & Amity.Pagination>(queryKey) ?? {}
61
+
62
+ if (!data?.follows.length) {
63
+ return;
64
+ }
65
+
66
+ const follows: Amity.FollowStatus[] = data.follows
67
+ .map(key => pullFromCache<Amity.FollowStatus>(['follow', 'get', key])!)
68
+ .filter(Boolean)
69
+ .map(({ data }) => data)
70
+
71
+ const prevPage = toPage(data?.paging.previous)
72
+ const nextPage = toPage(data?.paging.next)
73
+
74
+ return follows.length === data?.follows?.length
75
+ ? { data: follows, cachedAt, prevPage, nextPage }
76
+ : undefined
77
+ }
@@ -0,0 +1,10 @@
1
+ export * from './onUserFollowed'
2
+ export * from './onUserUnfollowed'
3
+ export * from './onFollowerDeleted'
4
+
5
+ export * from './onFollowerRequested'
6
+ export * from './onFollowRequestCanceled'
7
+ export * from './onFollowRequestAccepted'
8
+ export * from './onFollowRequestDeclined'
9
+
10
+ export * from './onFollowInfoUpdated'
@@ -0,0 +1,43 @@
1
+ import { createFollowEventSubscriber } from './utils'
2
+ import { getFollowInfo } from '~/follow/api'
3
+
4
+ /**
5
+ * ```js
6
+ * import { onFollowInfoUpdated } from '@amityco/ts-sdk'
7
+ * const dispose = onFollowInfoUpdated(followInfo => {
8
+ * // ...
9
+ * })
10
+ * ```
11
+ *
12
+ * Fired when a {@link Amity.FollowInfo} has been updated
13
+ *
14
+ * @param callback The function to call when the event was fired
15
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
16
+ *
17
+ * @category Follow Events
18
+ */
19
+ export const onFollowInfoUpdated = (callback: Amity.Listener<Amity.FollowInfo>): Amity.Unsubscriber => {
20
+ const handler = async (payload: Amity.FollowStatus) => {
21
+ const [
22
+ { data: followInfoFrom },
23
+ { data: followInfoTo },
24
+ ] = await Promise.all([getFollowInfo(payload.from), getFollowInfo(payload.to)])
25
+
26
+ callback(followInfoFrom);
27
+ callback(followInfoTo)
28
+ }
29
+
30
+ const disposers = [
31
+ createFollowEventSubscriber('follow.created', handler),
32
+ createFollowEventSubscriber('follow.requested', handler),
33
+ createFollowEventSubscriber('follow.accepted', handler),
34
+ createFollowEventSubscriber('follow.unfollowed', handler),
35
+ createFollowEventSubscriber('follow.requestCanceled', handler),
36
+ createFollowEventSubscriber('follow.requestDeclined', handler),
37
+ createFollowEventSubscriber('follow.followerDeleted', handler),
38
+ ]
39
+
40
+ return () => {
41
+ disposers.forEach(fn => fn())
42
+ }
43
+ }
@@ -0,0 +1,19 @@
1
+ import { createFollowEventSubscriber } from './utils'
2
+
3
+ /**
4
+ * ```js
5
+ * import { onFollowRequestAccepted } from '@amityco/ts-sdk'
6
+ * const dispose = onFollowRequestAccepted(status => {
7
+ * // ...
8
+ * })
9
+ * ```
10
+ *
11
+ * Fired when a follow request has been accepted
12
+ *
13
+ * @param callback The function to call when the event was fired
14
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
15
+ *
16
+ * @category Follow Events
17
+ */
18
+ export const onFollowRequestAccepted = (callback: Amity.Listener<Amity.FollowStatus>): Amity.Unsubscriber =>
19
+ createFollowEventSubscriber('follow.accepted', callback)
@@ -0,0 +1,19 @@
1
+ import { createFollowEventSubscriber } from './utils'
2
+
3
+ /**
4
+ * ```js
5
+ * import { onFollowRequestCanceled } from '@amityco/ts-sdk'
6
+ * const dispose = onFollowRequestCanceled(status => {
7
+ * // ...
8
+ * })
9
+ * ```
10
+ *
11
+ * Fired when a follow request has been canceled
12
+ *
13
+ * @param callback The function to call when the event was fired
14
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
15
+ *
16
+ * @category Follow Events
17
+ */
18
+ export const onFollowRequestCanceled = (callback: Amity.Listener<Amity.FollowStatus>): Amity.Unsubscriber =>
19
+ createFollowEventSubscriber('follow.requestCanceled', callback)
@@ -0,0 +1,19 @@
1
+ import { createFollowEventSubscriber } from './utils'
2
+
3
+ /**
4
+ * ```js
5
+ * import { onFollowRequestDeclined } from '@amityco/ts-sdk'
6
+ * const dispose = onFollowRequestDeclined(status => {
7
+ * // ...
8
+ * })
9
+ * ```
10
+ *
11
+ * Fired when a follow request has been declined
12
+ *
13
+ * @param callback The function to call when the event was fired
14
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
15
+ *
16
+ * @category Follow Events
17
+ */
18
+ export const onFollowRequestDeclined = (callback: Amity.Listener<Amity.FollowStatus>): Amity.Unsubscriber =>
19
+ createFollowEventSubscriber('follow.requestDeclined', callback)
@@ -0,0 +1,19 @@
1
+ import { createFollowEventSubscriber } from './utils'
2
+
3
+ /**
4
+ * ```js
5
+ * import { onFollowerDeleted } from '@amityco/ts-sdk'
6
+ * const dispose = onFollowerDeleted(status => {
7
+ * // ...
8
+ * })
9
+ * ```
10
+ *
11
+ * Fired when a follower has been deleted
12
+ *
13
+ * @param callback The function to call when the event was fired
14
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
15
+ *
16
+ * @category Follow Events
17
+ */
18
+ export const onFollowerDeleted = (callback: Amity.Listener<Amity.FollowStatus>): Amity.Unsubscriber =>
19
+ createFollowEventSubscriber('follow.followerDeleted', callback)
@@ -0,0 +1,19 @@
1
+ import { createFollowEventSubscriber } from './utils'
2
+
3
+ /**
4
+ * ```js
5
+ * import { onFollowerRequested } from '@amityco/ts-sdk'
6
+ * const dispose = onFollowerRequested(status => {
7
+ * // ...
8
+ * })
9
+ * ```
10
+ *
11
+ * Fired when a user follows another users and confirmation is required
12
+ *
13
+ * @param callback The function to call when the event was fired
14
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
15
+ *
16
+ * @category Follow Events
17
+ */
18
+ export const onFollowerRequested = (callback: Amity.Listener<Amity.FollowStatus>): Amity.Unsubscriber =>
19
+ createFollowEventSubscriber('follow.requested', callback)
@@ -0,0 +1,19 @@
1
+ import { createFollowEventSubscriber } from './utils'
2
+
3
+ /**
4
+ * ```js
5
+ * import { onUserFollowed } from '@amityco/ts-sdk'
6
+ * const dispose = onUserFollowed(status => {
7
+ * // ...
8
+ * })
9
+ * ```
10
+ *
11
+ * Fired when a user follows another users and confirmation is not required
12
+ *
13
+ * @param callback The function to call when the event was fired
14
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
15
+ *
16
+ * @category Follow Events
17
+ */
18
+ export const onUserFollowed = (callback: Amity.Listener<Amity.FollowStatus>): Amity.Unsubscriber =>
19
+ createFollowEventSubscriber('follow.created', callback)
@@ -0,0 +1,19 @@
1
+ import { createFollowEventSubscriber } from './utils'
2
+
3
+ /**
4
+ * ```js
5
+ * import { onUserUnfollowed } from '@amityco/ts-sdk'
6
+ * const dispose = onUserFollowed(status => {
7
+ * // ...
8
+ * })
9
+ * ```
10
+ *
11
+ * Fired when a user unfollows
12
+ *
13
+ * @param callback The function to call when the event was fired
14
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
15
+ *
16
+ * @category Follow Events
17
+ */
18
+ export const onUserUnfollowed = (callback: Amity.Listener<Amity.FollowStatus>): Amity.Unsubscriber =>
19
+ createFollowEventSubscriber('follow.unfollowed', callback)
@@ -0,0 +1,38 @@
1
+ import { getActiveClient } from '~/client/api'
2
+ import { ingestInCache } from '~/cache/api/ingestInCache'
3
+ import { createEventSubscriber } from '~/core/events'
4
+ import { queryCache, upsertInCache } from '~/cache/api'
5
+
6
+ export const createFollowEventSubscriber = (
7
+ event: keyof Amity.MqttFollowMessageEvents,
8
+ callback: Amity.Listener<Amity.FollowStatus>
9
+ ) => {
10
+ const client = getActiveClient()
11
+
12
+ const filter = (payload: Amity.FollowStatus) => {
13
+ if (!client.cache) {
14
+ callback(payload)
15
+ } else {
16
+ ingestInCache({ follows: [payload] })
17
+
18
+ const queries = [
19
+ ...queryCache(['followers', 'query']) ?? [],
20
+ ...queryCache(['followings', 'query']) ?? [],
21
+ ]
22
+
23
+ queries
24
+ // @ts-ignore
25
+ .filter(({ key }) => key[2].userId === payload.from || key[2].userId === payload.to)
26
+ .forEach(({ key, data }) => upsertInCache(key, data as any, { cachedAt: -1 }));
27
+
28
+ callback(payload)
29
+ }
30
+ }
31
+
32
+ return createEventSubscriber(
33
+ client,
34
+ event,
35
+ event,
36
+ filter
37
+ )
38
+ }
@@ -0,0 +1,3 @@
1
+ export * from './observeFollowInfo'
2
+ export * from './observeFollowers'
3
+ export * from './observeFollowings'
@@ -0,0 +1,68 @@
1
+ import { getActiveClient } from '~/client/api'
2
+ import { createQuery, runQuery, queryOptions } from '~/core/query'
3
+ import { getFollowInfo } from '../api'
4
+ import { onFollowInfoUpdated } from '../events'
5
+
6
+ /**
7
+ * ```js
8
+ * import { observeFollowInfo } from '@amityco/ts-sdk'
9
+ *
10
+ * let followInfo = {}
11
+ * const dispose = observeFollowInfo(userId, updated => followInfo = updated)
12
+ * ```
13
+ *
14
+ * Observe all mutation on a given {@link Amity.FollowInfo}
15
+ *
16
+ * @param userId the ID of the user to observe
17
+ * @param callback the function to call when new data are available
18
+ * @returns An {@link Amity.Unsubscriber} function to run when willing to stop observing the post
19
+ *
20
+ * @category Follow Observer
21
+ */
22
+ export const observeFollowInfo = <Events extends ['onFetch', 'onUpdate']>(
23
+ userId: Amity.User['userId'],
24
+ callback: Amity.ObjectListener<Amity.Snapshot<Amity.FollowInfo>, Events>,
25
+ policy: Amity.QueryPolicy = 'cache_then_server'
26
+ ): Amity.Unsubscriber => {
27
+ const { log } = getActiveClient()
28
+
29
+ const timestamp = Date.now()
30
+ log(`observeFollowInfo(tmpid: ${timestamp}) > listen`)
31
+
32
+ const router = (
33
+ result: Amity.Snapshot<Amity.FollowInfo>,
34
+ action: Events[number]
35
+ ) => {
36
+ if (callback instanceof Function) return callback(result)
37
+
38
+ if (action !== 'onFetch') callback.onEvent?.(action, result)
39
+
40
+ callback[action]?.(result)
41
+ }
42
+
43
+ const realtimeRouter = (
44
+ result: Amity.Snapshot<Amity.FollowInfo>,
45
+ action: Events[number]
46
+ ) => {
47
+ if (result.data?.userId !== userId) return
48
+
49
+ router(result, action)
50
+ }
51
+
52
+ const disposers: Amity.Unsubscriber[] = []
53
+
54
+ disposers.push(
55
+ onFollowInfoUpdated(data => realtimeRouter({ data, loading: false, origin: 'event' }, 'onUpdate')),
56
+ )
57
+
58
+ runQuery(
59
+ createQuery(getFollowInfo, userId),
60
+ result => (result.data || result.error) && router(result, 'onFetch'),
61
+ queryOptions(policy),
62
+ )
63
+
64
+ return () => {
65
+ log(`observeFollowInfo(tmpid: ${timestamp}) > dispose`)
66
+ disposers.forEach(fn => fn())
67
+ }
68
+ }
@@ -0,0 +1,78 @@
1
+ import { getActiveClient } from '~/client/api'
2
+
3
+ import {
4
+ onFollowerRequested,
5
+ onFollowRequestAccepted,
6
+ onFollowRequestDeclined,
7
+ onFollowRequestCanceled,
8
+ onUserFollowed,
9
+ onUserUnfollowed,
10
+ onFollowerDeleted
11
+ } from '../events'
12
+
13
+ /**
14
+ * ```js
15
+ * import { observeFollowers } from '@amityco/ts-sdk'
16
+ *
17
+ * let followers = []
18
+ * const unsub = observeFollowers('userId', follower => merge(followers, follower))
19
+ * ```
20
+ *
21
+ * Observe all mutations on a list of followers {@link Amity.FollowStatus} for a given user
22
+ *
23
+ * @param userId the ID of the {@link Amity.User}
24
+ * @param callback the function to call when new data are available
25
+ * @returns An {@link Amity.Unsubscriber} function to run when willing to stop observing the messages
26
+ *
27
+ * @category Follow Observer
28
+ */
29
+ export const observeFollowers = <Events extends [
30
+ 'onRequested',
31
+ 'onAccepted',
32
+ 'onDeclined',
33
+ 'onCanceled',
34
+ 'onFollowed',
35
+ 'onUnfollowed',
36
+ 'onDeleted',
37
+ ]>(
38
+ userId: Amity.User['userId'],
39
+ callback: Amity.ObjectListener<Amity.FollowStatus, Events>
40
+ ): Amity.Unsubscriber => {
41
+ const { log } = getActiveClient()
42
+
43
+ const timestamp = Date.now()
44
+ log(`observeFollowers(tmpid: ${timestamp}) > listen`)
45
+
46
+ const disposers: Amity.Unsubscriber[] = []
47
+
48
+ const router = (
49
+ status: Amity.FollowStatus,
50
+ action: Events[number],
51
+ ) => {
52
+ if (status.from !== userId) {
53
+ return;
54
+ }
55
+
56
+ if (callback instanceof Function) {
57
+ return callback(status)
58
+ }
59
+
60
+ callback.onEvent?.(action, status)
61
+ callback[action]?.(status)
62
+ }
63
+
64
+ disposers.push(
65
+ onFollowerRequested(x => router(x, 'onRequested')),
66
+ onFollowRequestAccepted(x => router(x, 'onAccepted')),
67
+ onFollowRequestDeclined(x => router(x, 'onDeclined')),
68
+ onFollowRequestCanceled(x => router(x, 'onCanceled')),
69
+ onUserFollowed(x => router(x, 'onFollowed')),
70
+ onUserUnfollowed(x => router(x, 'onUnfollowed')),
71
+ onFollowerDeleted(x => router(x, 'onDeleted')),
72
+ )
73
+
74
+ return () => {
75
+ log(`observeFollowers(tmpid: ${timestamp}) > dispose`)
76
+ disposers.forEach(fn => fn())
77
+ }
78
+ }