@amityco/ts-sdk 0.0.1-beta.8 → 0.0.1-beta.9
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.
- package/dist/@types/core/events.d.ts +63 -17
- package/dist/@types/core/events.d.ts.map +1 -1
- package/dist/@types/core/transport.d.ts +15 -0
- package/dist/@types/core/transport.d.ts.map +1 -1
- package/dist/@types/domains/client.d.ts +3 -0
- package/dist/@types/domains/client.d.ts.map +1 -1
- package/dist/@types/domains/comment.d.ts +1 -1
- package/dist/@types/domains/comment.d.ts.map +1 -1
- package/dist/@types/domains/community.d.ts +1 -1
- package/dist/@types/domains/community.d.ts.map +1 -1
- package/dist/@types/domains/group.d.ts +2 -2
- package/dist/@types/domains/group.d.ts.map +1 -1
- package/dist/@types/domains/partials.d.ts +3 -0
- package/dist/@types/domains/partials.d.ts.map +1 -1
- package/dist/@types/domains/post.d.ts +1 -1
- package/dist/@types/domains/post.d.ts.map +1 -1
- package/dist/@types/domains/user.d.ts +2 -1
- package/dist/@types/domains/user.d.ts.map +1 -1
- package/dist/client/api/connectClient.d.ts.map +1 -1
- package/dist/client/api/createClient.d.ts +2 -1
- package/dist/client/api/createClient.d.ts.map +1 -1
- package/dist/client/api/disconnectClient.d.ts.map +1 -1
- package/dist/client/api/getToken.d.ts +3 -1
- package/dist/client/api/getToken.d.ts.map +1 -1
- package/dist/comment/api/deleteComment.d.ts +1 -0
- package/dist/comment/api/deleteComment.d.ts.map +1 -1
- package/dist/comment/events/index.d.ts +4 -0
- package/dist/comment/events/index.d.ts.map +1 -1
- package/dist/comment/events/onCommentCreated.d.ts +1 -1
- package/dist/comment/events/onCommentCreated.d.ts.map +1 -1
- package/dist/comment/events/onCommentDeleted.d.ts +1 -1
- package/dist/comment/events/onCommentDeleted.d.ts.map +1 -1
- package/dist/comment/events/onCommentFlagged.d.ts +17 -0
- package/dist/comment/events/onCommentFlagged.d.ts.map +1 -0
- package/dist/comment/events/onCommentReactionAdded.d.ts +17 -0
- package/dist/comment/events/onCommentReactionAdded.d.ts.map +1 -0
- package/dist/comment/events/onCommentReactionRemoved.d.ts +17 -0
- package/dist/comment/events/onCommentReactionRemoved.d.ts.map +1 -0
- package/dist/comment/events/onCommentUnflagged.d.ts +17 -0
- package/dist/comment/events/onCommentUnflagged.d.ts.map +1 -0
- package/dist/comment/events/onCommentUpdated.d.ts +1 -1
- package/dist/comment/events/onCommentUpdated.d.ts.map +1 -1
- package/dist/comment/events/utils.d.ts +2 -0
- package/dist/comment/events/utils.d.ts.map +1 -0
- package/dist/comment/observers/observeComment.d.ts +1 -1
- package/dist/comment/observers/observeComment.d.ts.map +1 -1
- package/dist/comment/observers/observeComments.d.ts +5 -1
- package/dist/comment/observers/observeComments.d.ts.map +1 -1
- package/dist/community/events/index.d.ts +4 -0
- package/dist/community/events/index.d.ts.map +1 -1
- package/dist/community/events/onCommunityCreated.d.ts +2 -2
- package/dist/community/events/onCommunityCreated.d.ts.map +1 -1
- package/dist/community/events/onCommunityDeleted.d.ts +2 -2
- package/dist/community/events/onCommunityDeleted.d.ts.map +1 -1
- package/dist/community/events/onCommunityJoined.d.ts +3 -3
- package/dist/community/events/onCommunityJoined.d.ts.map +1 -1
- package/dist/community/events/onCommunityLeft.d.ts +3 -3
- package/dist/community/events/onCommunityLeft.d.ts.map +1 -1
- package/dist/community/events/onCommunityUpdated.d.ts +2 -2
- package/dist/community/events/onCommunityUpdated.d.ts.map +1 -1
- package/dist/community/events/onCommunityUserAdded.d.ts +17 -0
- package/dist/community/events/onCommunityUserAdded.d.ts.map +1 -0
- package/dist/community/events/onCommunityUserBanned.d.ts +17 -0
- package/dist/community/events/onCommunityUserBanned.d.ts.map +1 -0
- package/dist/community/events/onCommunityUserRemoved.d.ts +17 -0
- package/dist/community/events/onCommunityUserRemoved.d.ts.map +1 -0
- package/dist/community/events/onCommunityUserUnbanned.d.ts +17 -0
- package/dist/community/events/onCommunityUserUnbanned.d.ts.map +1 -0
- package/dist/community/events/utils.d.ts +3 -0
- package/dist/community/events/utils.d.ts.map +1 -0
- package/dist/community/observers/observeCommunity.d.ts +1 -1
- package/dist/community/observers/observeCommunity.d.ts.map +1 -1
- package/dist/core/cache/ingest.d.ts.map +1 -1
- package/dist/core/events.d.ts +4 -2
- package/dist/core/events.d.ts.map +1 -1
- package/dist/core/model/index.d.ts +1 -0
- package/dist/core/model/index.d.ts.map +1 -1
- package/dist/core/model/isMatch.d.ts +3 -0
- package/dist/core/model/isMatch.d.ts.map +1 -0
- package/dist/core/network.d.ts +11 -0
- package/dist/core/network.d.ts.map +1 -0
- package/dist/core/subscription.d.ts +14 -0
- package/dist/core/subscription.d.ts.map +1 -0
- package/dist/core/transports/http.d.ts +11 -0
- package/dist/core/transports/http.d.ts.map +1 -0
- package/dist/core/transports/index.d.ts +4 -0
- package/dist/core/transports/index.d.ts.map +1 -0
- package/dist/core/transports/mqtt.d.ts +17 -0
- package/dist/core/transports/mqtt.d.ts.map +1 -0
- package/dist/core/transports/utils.d.ts +13 -0
- package/dist/core/transports/utils.d.ts.map +1 -0
- package/dist/core/transports/ws.d.ts +27 -0
- package/dist/core/transports/ws.d.ts.map +1 -0
- package/dist/index.cjs.js +1208 -514
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +1185 -515
- package/dist/index.umd.js +5 -3
- package/dist/post/api/deletePost.d.ts +1 -0
- package/dist/post/api/deletePost.d.ts.map +1 -1
- package/dist/post/events/index.d.ts +6 -0
- package/dist/post/events/index.d.ts.map +1 -1
- package/dist/post/events/onPostApproved.d.ts +17 -0
- package/dist/post/events/onPostApproved.d.ts.map +1 -0
- package/dist/post/events/onPostCreated.d.ts +1 -1
- package/dist/post/events/onPostCreated.d.ts.map +1 -1
- package/dist/post/events/onPostDeclined.d.ts +17 -0
- package/dist/post/events/onPostDeclined.d.ts.map +1 -0
- package/dist/post/events/onPostDeleted.d.ts +1 -1
- package/dist/post/events/onPostDeleted.d.ts.map +1 -1
- package/dist/post/events/onPostFlagged.d.ts +17 -0
- package/dist/post/events/onPostFlagged.d.ts.map +1 -0
- package/dist/post/events/onPostReactionAdded.d.ts +17 -0
- package/dist/post/events/onPostReactionAdded.d.ts.map +1 -0
- package/dist/post/events/onPostReactionRemoved.d.ts +17 -0
- package/dist/post/events/onPostReactionRemoved.d.ts.map +1 -0
- package/dist/post/events/onPostUnflagged.d.ts +17 -0
- package/dist/post/events/onPostUnflagged.d.ts.map +1 -0
- package/dist/post/events/onPostUpdated.d.ts +1 -1
- package/dist/post/events/onPostUpdated.d.ts.map +1 -1
- package/dist/post/events/utils.d.ts +2 -0
- package/dist/post/events/utils.d.ts.map +1 -0
- package/dist/post/observers/observePost.d.ts +1 -1
- package/dist/post/observers/observePost.d.ts.map +1 -1
- package/dist/post/observers/observePosts.d.ts +1 -1
- package/dist/post/observers/observePosts.d.ts.map +1 -1
- package/dist/reaction/events/onReactionAdded.d.ts +4 -2
- package/dist/reaction/events/onReactionAdded.d.ts.map +1 -1
- package/dist/reaction/events/onReactionRemoved.d.ts +4 -2
- package/dist/reaction/events/onReactionRemoved.d.ts.map +1 -1
- package/dist/reaction/utils/index.d.ts +1 -0
- package/dist/reaction/utils/index.d.ts.map +1 -1
- package/dist/reaction/utils/preparePayloadForCache.d.ts +3 -0
- package/dist/reaction/utils/preparePayloadForCache.d.ts.map +1 -0
- package/dist/report/api/createReport.d.ts.map +1 -1
- package/dist/report/api/deleteReport.d.ts.map +1 -1
- package/dist/user/events/index.d.ts +3 -0
- package/dist/user/events/index.d.ts.map +1 -1
- package/dist/user/events/onUserFlagCleared.d.ts +17 -0
- package/dist/user/events/onUserFlagCleared.d.ts.map +1 -0
- package/dist/user/events/onUserFlagged.d.ts +17 -0
- package/dist/user/events/onUserFlagged.d.ts.map +1 -0
- package/dist/user/events/onUserUnflagged.d.ts +17 -0
- package/dist/user/events/onUserUnflagged.d.ts.map +1 -0
- package/dist/user/events/onUserUpdated.d.ts +1 -1
- package/dist/user/events/onUserUpdated.d.ts.map +1 -1
- package/dist/user/events/utils.d.ts +2 -0
- package/dist/user/events/utils.d.ts.map +1 -0
- package/dist/user/observers/observeUser.d.ts +1 -1
- package/dist/user/observers/observeUser.d.ts.map +1 -1
- package/package.json +4 -1
- package/rollup.config.js +2 -2
- package/src/@types/core/events.ts +64 -23
- package/src/@types/core/transport.ts +14 -0
- package/src/@types/domains/client.ts +3 -0
- package/src/@types/domains/comment.ts +1 -0
- package/src/@types/domains/community.ts +1 -0
- package/src/@types/domains/group.ts +2 -2
- package/src/@types/domains/partials.ts +4 -0
- package/src/@types/domains/post.ts +1 -0
- package/src/@types/domains/user.ts +2 -0
- package/src/client/api/connectClient.ts +12 -2
- package/src/client/api/createClient.ts +7 -7
- package/src/client/api/disconnectClient.ts +5 -0
- package/src/client/api/getToken.ts +1 -1
- package/src/client/events/onConnectionError.ts +1 -1
- package/src/comment/api/createComment.ts +2 -2
- package/src/comment/api/deleteComment.ts +2 -2
- package/src/comment/api/updateComment.ts +1 -1
- package/src/comment/events/index.ts +6 -0
- package/src/comment/events/onCommentCreated.ts +4 -22
- package/src/comment/events/onCommentDeleted.ts +4 -22
- package/src/comment/events/onCommentFlagged.ts +21 -0
- package/src/comment/events/onCommentReactionAdded.ts +52 -0
- package/src/comment/events/onCommentReactionRemoved.ts +52 -0
- package/src/comment/events/onCommentUnflagged.ts +21 -0
- package/src/comment/events/onCommentUpdated.ts +4 -22
- package/src/comment/events/utils.ts +34 -0
- package/src/comment/observers/observeComment.ts +21 -7
- package/src/comment/observers/observeComments.ts +11 -3
- package/src/community/api/addCommunityMembers.ts +1 -1
- package/src/community/api/createCommunity.ts +1 -1
- package/src/community/api/deleteCommunity.ts +1 -1
- package/src/community/api/joinCommunity.ts +1 -1
- package/src/community/api/leaveCommunity.ts +1 -1
- package/src/community/api/removeCommunityMembers.ts +1 -1
- package/src/community/api/updateCommunity.ts +1 -1
- package/src/community/events/index.ts +5 -0
- package/src/community/events/onCommunityCreated.ts +5 -23
- package/src/community/events/onCommunityDeleted.ts +5 -23
- package/src/community/events/onCommunityJoined.ts +5 -23
- package/src/community/events/onCommunityLeft.ts +5 -23
- package/src/community/events/onCommunityUpdated.ts +5 -23
- package/src/community/events/onCommunityUserAdded.ts +19 -0
- package/src/community/events/onCommunityUserBanned.ts +19 -0
- package/src/community/events/onCommunityUserRemoved.ts +19 -0
- package/src/community/events/onCommunityUserUnbanned.ts +19 -0
- package/src/community/events/utils.ts +108 -0
- package/src/community/observers/observeCommunity.ts +23 -9
- package/src/core/cache/ingest.ts +19 -3
- package/src/core/events.ts +45 -4
- package/src/core/model/index.ts +1 -0
- package/src/core/model/isMatch.ts +12 -0
- package/src/core/network.ts +14 -0
- package/src/core/subscription.ts +75 -0
- package/src/core/transports/http.ts +63 -0
- package/src/core/transports/index.ts +3 -0
- package/src/core/transports/mqtt.ts +141 -0
- package/src/core/transports/utils.ts +25 -0
- package/src/core/transports/ws.ts +61 -0
- package/src/index.ts +1 -0
- package/src/post/api/createPost.ts +2 -2
- package/src/post/api/deletePost.ts +2 -2
- package/src/post/api/updatePost.ts +1 -1
- package/src/post/events/index.ts +9 -0
- package/src/post/events/onPostApproved.ts +19 -0
- package/src/post/events/onPostCreated.ts +4 -24
- package/src/post/events/onPostDeclined.ts +19 -0
- package/src/post/events/onPostDeleted.ts +4 -24
- package/src/post/events/onPostFlagged.ts +19 -0
- package/src/post/events/onPostReactionAdded.ts +50 -0
- package/src/post/events/onPostReactionRemoved.ts +50 -0
- package/src/post/events/onPostUnflagged.ts +19 -0
- package/src/post/events/onPostUpdated.ts +4 -24
- package/src/post/events/utils.ts +40 -0
- package/src/post/observers/observePost.ts +25 -7
- package/src/post/observers/observePosts.ts +12 -2
- package/src/reaction/events/onReactionAdded.ts +36 -15
- package/src/reaction/events/onReactionRemoved.ts +37 -14
- package/src/reaction/utils/dispatchReactable.ts +2 -2
- package/src/reaction/utils/index.ts +1 -0
- package/src/reaction/utils/preparePayloadForCache.ts +45 -0
- package/src/report/api/createReport.ts +5 -1
- package/src/report/api/deleteReport.ts +5 -1
- package/src/user/events/index.ts +4 -0
- package/src/user/events/onUserFlagCleared.ts +19 -0
- package/src/user/events/onUserFlagged.ts +19 -0
- package/src/user/events/onUserUnflagged.ts +19 -0
- package/src/user/events/onUserUpdated.ts +4 -24
- package/src/user/events/utils.ts +24 -0
- package/src/user/observers/observeUser.ts +11 -3
- package/dist/core/transports.d.ts +0 -49
- package/dist/core/transports.d.ts.map +0 -1
- package/src/core/transports.ts +0 -151
package/src/core/events.ts
CHANGED
|
@@ -3,15 +3,13 @@ import mitt from 'mitt'
|
|
|
3
3
|
import { getActiveClient } from '~/client/api/activeClient'
|
|
4
4
|
|
|
5
5
|
// need to sync up the list
|
|
6
|
-
const
|
|
6
|
+
const WS_EVENTS = [
|
|
7
7
|
'disconnected',
|
|
8
8
|
'error',
|
|
9
9
|
'connect_error',
|
|
10
10
|
'reconnect_error',
|
|
11
11
|
'reconnect_failed',
|
|
12
12
|
|
|
13
|
-
'v3.user.didUpdate',
|
|
14
|
-
|
|
15
13
|
'v3.channel.didUpdate',
|
|
16
14
|
'v3.channel.didUpdate',
|
|
17
15
|
'v3.channel.didJoin',
|
|
@@ -26,6 +24,16 @@ const EVENTS = [
|
|
|
26
24
|
'v3.message.didDelete',
|
|
27
25
|
] as const
|
|
28
26
|
|
|
27
|
+
const MQTT_EVENTS = [
|
|
28
|
+
'connect',
|
|
29
|
+
'message',
|
|
30
|
+
'disconnect',
|
|
31
|
+
'error',
|
|
32
|
+
'close',
|
|
33
|
+
'end',
|
|
34
|
+
'reconnect'
|
|
35
|
+
] as const;
|
|
36
|
+
|
|
29
37
|
/** @hidden */
|
|
30
38
|
export const createEventEmitter = () => {
|
|
31
39
|
return mitt<Amity.Events>()
|
|
@@ -42,11 +50,24 @@ export const createEventEmitter = () => {
|
|
|
42
50
|
* @hidden
|
|
43
51
|
*/
|
|
44
52
|
export const proxyWebsocketEvents = (ws: Amity.Client['ws'], emitter: Amity.Client['emitter']) => {
|
|
45
|
-
|
|
53
|
+
WS_EVENTS.forEach(event => {
|
|
46
54
|
ws.on(event, (param: Amity.Events[typeof event]) => emitter.emit(event, param))
|
|
47
55
|
})
|
|
48
56
|
}
|
|
49
57
|
|
|
58
|
+
export const proxyMqttEvents = (mqttClient: Amity.Client['mqtt'], emitter: Amity.Client['emitter']) => {
|
|
59
|
+
MQTT_EVENTS.forEach(event => {
|
|
60
|
+
mqttClient.on(event, (...params: any[]) => emitter.emit(event, params.length === 1 ? params[0] : params))
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
// @ts-ignore
|
|
64
|
+
mqttClient.on('message', (topic: string, payload: Buffer) => {
|
|
65
|
+
const message = JSON.parse(payload.toString());
|
|
66
|
+
|
|
67
|
+
emitter.emit(message.eventType, message.data)
|
|
68
|
+
})
|
|
69
|
+
}
|
|
70
|
+
|
|
50
71
|
/**
|
|
51
72
|
* Standardize the subscription of SSE through web sockets
|
|
52
73
|
*
|
|
@@ -83,6 +104,26 @@ export const createEventSubscriber = <T extends keyof Amity.Events>(
|
|
|
83
104
|
}
|
|
84
105
|
}
|
|
85
106
|
|
|
107
|
+
export const createMqttMessageSubscriber = <T extends keyof Amity.Events>(
|
|
108
|
+
client: Amity.Client,
|
|
109
|
+
namespace: string,
|
|
110
|
+
event: string,
|
|
111
|
+
fn: (params: Object) => void,
|
|
112
|
+
): Amity.Unsubscriber => {
|
|
113
|
+
return createEventSubscriber(
|
|
114
|
+
client,
|
|
115
|
+
namespace,
|
|
116
|
+
'message',
|
|
117
|
+
([topic, message]) => {
|
|
118
|
+
const payload = JSON.parse(message.toString());
|
|
119
|
+
|
|
120
|
+
if (payload.eventType === event) {
|
|
121
|
+
fn(payload.data);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
)
|
|
125
|
+
}
|
|
126
|
+
|
|
86
127
|
/**
|
|
87
128
|
* Wrapper around dispatch event
|
|
88
129
|
*
|
package/src/core/model/index.ts
CHANGED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import isMatchWith from 'lodash.ismatchwith'
|
|
2
|
+
|
|
3
|
+
/** @hidden */
|
|
4
|
+
export const isMatch =<T extends Amity.Domain>(model1: Amity.Model[T], model2: Amity.Model[T]) => {
|
|
5
|
+
const customizer = (oldValue: any, newValue: any, key: string | number | symbol) => {
|
|
6
|
+
if (key === 'syncedAt') {
|
|
7
|
+
return true
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return isMatchWith(model1, model2, customizer)
|
|
12
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const API_ENDPOINT = {
|
|
2
|
+
EU: 'eu',
|
|
3
|
+
SG: 'sg',
|
|
4
|
+
US: 'us',
|
|
5
|
+
} as const
|
|
6
|
+
|
|
7
|
+
export enum UrlTemplate {
|
|
8
|
+
HTTP = 'https://api.{region}.amity.co',
|
|
9
|
+
MQTT = 'wss://sse.{region}.amity.co:443/mqtt',
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const getUrlFromTemplate = ( template: UrlTemplate, region: string ) => {
|
|
13
|
+
return template.replace( '{region}', region);
|
|
14
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { getActiveClient } from '~/client/api'
|
|
2
|
+
import { ASCError } from '~/core/errors'
|
|
3
|
+
import { proxyMqttEvents } from '~/core/events'
|
|
4
|
+
|
|
5
|
+
export enum SubscriptionLevels {
|
|
6
|
+
COMMUNITY = 'community',
|
|
7
|
+
POST = 'post',
|
|
8
|
+
COMMENT = 'comment',
|
|
9
|
+
POST_AND_COMMENT = 'post_and_comment',
|
|
10
|
+
USER = 'user',
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const getCommunityUserTopic = (
|
|
14
|
+
{ path }: Amity.Subscribable,
|
|
15
|
+
level?: SubscriptionLevels,
|
|
16
|
+
): string => {
|
|
17
|
+
switch (level) {
|
|
18
|
+
case 'post':
|
|
19
|
+
return `${path}/post/+`;
|
|
20
|
+
case 'comment':
|
|
21
|
+
return `${path}/post/+/comment/+`;
|
|
22
|
+
case 'post_and_comment':
|
|
23
|
+
return `${path}/post/#`;
|
|
24
|
+
default:
|
|
25
|
+
return path;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const getCommunityTopic = (
|
|
30
|
+
{ path }: Amity.Subscribable,
|
|
31
|
+
level: Exclude<SubscriptionLevels, SubscriptionLevels.USER> = SubscriptionLevels.COMMUNITY,
|
|
32
|
+
): string =>
|
|
33
|
+
getCommunityUserTopic({ path }, level)
|
|
34
|
+
|
|
35
|
+
export const getUserTopic = (
|
|
36
|
+
{ path }: Amity.Subscribable,
|
|
37
|
+
level: Exclude<SubscriptionLevels, SubscriptionLevels.COMMUNITY> = SubscriptionLevels.USER,
|
|
38
|
+
): string =>
|
|
39
|
+
getCommunityUserTopic({ path }, level)
|
|
40
|
+
|
|
41
|
+
export const getPostTopic = (
|
|
42
|
+
{ path }: Amity.Subscribable,
|
|
43
|
+
level: SubscriptionLevels.POST | SubscriptionLevels.COMMENT = SubscriptionLevels.POST
|
|
44
|
+
): string => {
|
|
45
|
+
switch (level) {
|
|
46
|
+
case 'comment':
|
|
47
|
+
return `${path}/comment/+`;
|
|
48
|
+
default:
|
|
49
|
+
return path;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const getCommentTopic = ({ path }: Amity.Subscribable): string => {
|
|
54
|
+
return path;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
let mqttAccessToken: string;
|
|
58
|
+
let mqttUserId: string;
|
|
59
|
+
|
|
60
|
+
export function subscribeTopic(
|
|
61
|
+
topic: string,
|
|
62
|
+
callback?: Amity.Listener<ASCError | void>
|
|
63
|
+
): Amity.Unsubscriber {
|
|
64
|
+
const { mqtt, emitter, accessToken, user } = getActiveClient()
|
|
65
|
+
|
|
66
|
+
if (mqttAccessToken !== accessToken || mqttUserId !== user!._id) {
|
|
67
|
+
mqttAccessToken = accessToken!
|
|
68
|
+
mqttUserId = user!._id
|
|
69
|
+
|
|
70
|
+
mqtt.connect({ accessToken: accessToken!, userId: user!._id })
|
|
71
|
+
proxyMqttEvents(mqtt, emitter)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return mqtt.subscribe(topic, callback)
|
|
75
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import axios from 'axios'
|
|
2
|
+
import HttpAgent, { HttpsAgent } from 'agentkeepalive'
|
|
3
|
+
|
|
4
|
+
import { unwrapPayload } from './utils'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Axios param serializer (for querystring)
|
|
8
|
+
* @hidden
|
|
9
|
+
*/
|
|
10
|
+
const stringify = (params: object, prefix?: string): string => {
|
|
11
|
+
return Object.entries(params)
|
|
12
|
+
.filter(([, value]) => value !== undefined)
|
|
13
|
+
.map(([name, value]) => {
|
|
14
|
+
const key = prefix ? `${prefix}[${name}]` : name
|
|
15
|
+
|
|
16
|
+
if (Array.isArray(value)) {
|
|
17
|
+
return value.map(item => `${key}[]=${item}`).join('&')
|
|
18
|
+
} else if (typeof value !== 'object') {
|
|
19
|
+
return `${key}=${value}`
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return stringify(value, prefix ?? name)
|
|
23
|
+
})
|
|
24
|
+
.join('&')
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Creates a pre-configured axios instance
|
|
29
|
+
*
|
|
30
|
+
* @param endpoint The ASC rest api server's URL
|
|
31
|
+
* @returns A pre-configured axios instance
|
|
32
|
+
*
|
|
33
|
+
* @category Transport
|
|
34
|
+
* @hidden
|
|
35
|
+
*/
|
|
36
|
+
export const createHttpTransport = (endpoint: string) => {
|
|
37
|
+
const options = {
|
|
38
|
+
maxSockets: 100,
|
|
39
|
+
maxFreeSockets: 10,
|
|
40
|
+
timeout: 60000,
|
|
41
|
+
freeSocketTimeout: 30000,
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const instance = axios.create({
|
|
45
|
+
baseURL: endpoint,
|
|
46
|
+
httpAgent: new HttpAgent(options),
|
|
47
|
+
httpsAgent: new HttpsAgent(options),
|
|
48
|
+
paramsSerializer: stringify,
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
instance.interceptors.response.use(
|
|
52
|
+
(response) => response,
|
|
53
|
+
(error) => {
|
|
54
|
+
const { response } = error
|
|
55
|
+
console.error(response?.data ?? error)
|
|
56
|
+
|
|
57
|
+
if (response)
|
|
58
|
+
unwrapPayload(response.data)
|
|
59
|
+
}
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
return instance
|
|
63
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import mqtt, { MqttClient, IClientOptions, ISubscriptionGrant } from 'mqtt'
|
|
2
|
+
import { ASCError, ASCUnknownError } from '~/core/errors'
|
|
3
|
+
|
|
4
|
+
const QOS_FAILURE_CODE = 128
|
|
5
|
+
|
|
6
|
+
const RETRY_BASE_TIMEOUT = 1000;
|
|
7
|
+
const RETRY_COUNT_MAX = 10;
|
|
8
|
+
|
|
9
|
+
const enum MqttError {
|
|
10
|
+
IDENTIFIER_REJECTED = 2,
|
|
11
|
+
BAD_USERNAME_OR_PASSWORD = 4,
|
|
12
|
+
NOT_AUTHORIZED = 5,
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function getMqttOptions(params: { username: string, password: string, clientId?: string }): IClientOptions {
|
|
16
|
+
return {
|
|
17
|
+
clean: false, // keep subscriptions
|
|
18
|
+
clientId: `mqttjs_ + ${Math.random().toString(16).substr(2, 8)}`,
|
|
19
|
+
protocolId: 'MQTT',
|
|
20
|
+
protocolVersion: 4,
|
|
21
|
+
reconnectPeriod: 0, // disable auto reconnect
|
|
22
|
+
will: {
|
|
23
|
+
topic: 'WillMsg',
|
|
24
|
+
payload: 'Connection Closed abnormally..!',
|
|
25
|
+
qos: 0,
|
|
26
|
+
retain: false
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
...params
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Creates a pre-configured socket.io instance
|
|
35
|
+
*
|
|
36
|
+
* @param endpoint The mqtt server's URL
|
|
37
|
+
* @returns A pre-configured (non-connected) mqtt client instance
|
|
38
|
+
*
|
|
39
|
+
* @category Transport
|
|
40
|
+
* @hidden
|
|
41
|
+
*/
|
|
42
|
+
export const createMqttTransport = (endpoint: string): Amity.MqttClient => {
|
|
43
|
+
let mqttClient: MqttClient | void;
|
|
44
|
+
let retryCount = 0
|
|
45
|
+
let allowReconnection = true
|
|
46
|
+
|
|
47
|
+
async function connect(params: { accessToken: string, userId: string }): Promise<void> {
|
|
48
|
+
if (mqttClient) {
|
|
49
|
+
mqttClient.removeAllListeners();
|
|
50
|
+
mqttClient.end(true)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
mqttClient = mqtt.connect(endpoint, getMqttOptions({ username: params.userId, password: params.accessToken }))
|
|
54
|
+
|
|
55
|
+
mqttClient.on('connect', () => {
|
|
56
|
+
retryCount = 0
|
|
57
|
+
allowReconnection = true
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
mqttClient.on('error', (error: Error & { code: number }) => {
|
|
61
|
+
switch (error.code) {
|
|
62
|
+
case MqttError.IDENTIFIER_REJECTED:
|
|
63
|
+
case MqttError.BAD_USERNAME_OR_PASSWORD:
|
|
64
|
+
case MqttError.NOT_AUTHORIZED:
|
|
65
|
+
allowReconnection = false
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
mqttClient.on('close', () => {
|
|
70
|
+
if (allowReconnection) {
|
|
71
|
+
reconnect()
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
return new Promise(resolve => mqttClient!.once('connect', () => resolve()))
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const reconnect = () => {
|
|
79
|
+
setTimeout(() => {
|
|
80
|
+
retryCount = retryCount + 1
|
|
81
|
+
mqttClient!.reconnect()
|
|
82
|
+
}, RETRY_BASE_TIMEOUT * Math.pow(2, retryCount > RETRY_COUNT_MAX ? RETRY_COUNT_MAX : retryCount))
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return {
|
|
86
|
+
connect,
|
|
87
|
+
async disconnect(): Promise<void> {
|
|
88
|
+
allowReconnection = false
|
|
89
|
+
|
|
90
|
+
if (this.connected) {
|
|
91
|
+
return new Promise(resolve => mqttClient?.end(true, undefined, () => resolve()))
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
get connected() {
|
|
95
|
+
return !!mqttClient?.connected
|
|
96
|
+
},
|
|
97
|
+
on<T extends keyof Amity.MqttEvents>(event: T, handler: (payload: Amity.MqttEvents[T]) => void) {
|
|
98
|
+
mqttClient?.on(event, handler)
|
|
99
|
+
},
|
|
100
|
+
once<T extends keyof Amity.MqttEvents>(event: T, handler: (payload: Amity.MqttEvents[T]) => void) {
|
|
101
|
+
mqttClient?.once(event, handler)
|
|
102
|
+
},
|
|
103
|
+
off<T extends keyof Amity.MqttEvents>(event: T, handler?: (payload: Amity.MqttEvents[T]) => void) {
|
|
104
|
+
if (handler !== undefined) {
|
|
105
|
+
mqttClient?.off(event, handler)
|
|
106
|
+
} else {
|
|
107
|
+
mqttClient?.removeAllListeners(event)
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
removeAllListeners() {
|
|
111
|
+
mqttClient?.removeAllListeners()
|
|
112
|
+
},
|
|
113
|
+
subscribe(topic: string, callback?: Amity.Listener<ASCError | void>): Amity.Unsubscriber {
|
|
114
|
+
const callbackWrapper = (error: Error, granted: ISubscriptionGrant[]) => {
|
|
115
|
+
if (error || granted[0].qos === QOS_FAILURE_CODE) {
|
|
116
|
+
const ascError = error
|
|
117
|
+
? new ASCError(error.message, Amity.ClientError.UNKNOWN_ERROR, Amity.ErrorLevel.ERROR)
|
|
118
|
+
// TODO throw the actual error, once BE can tell us the actual error code
|
|
119
|
+
: new ASCUnknownError(Amity.ClientError.UNKNOWN_ERROR, Amity.ErrorLevel.ERROR)
|
|
120
|
+
|
|
121
|
+
console.error(`Failed to subscribe to topic ${topic}`, ascError)
|
|
122
|
+
callback?.(ascError)
|
|
123
|
+
} else {
|
|
124
|
+
console.log(`Subscribed to topic ${granted[0].topic}`)
|
|
125
|
+
callback?.()
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (mqttClient) {
|
|
130
|
+
mqttClient.subscribe(topic, { qos: 0 }, callbackWrapper)
|
|
131
|
+
} else {
|
|
132
|
+
callbackWrapper(new Error('No connection to broker'), []);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return () => mqttClient?.unsubscribe(topic)
|
|
136
|
+
},
|
|
137
|
+
unsubscribe(topic: string) {
|
|
138
|
+
mqttClient?.unsubscribe(topic)
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ASCApiError, ASCUnknownError } from '~/core/errors'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Unwraps v3 server payload (for error handling and type extraction)
|
|
5
|
+
*
|
|
6
|
+
* @param response A typical "v3" response (related to backend's service strategy)
|
|
7
|
+
*
|
|
8
|
+
* @returns The data returned by the backend
|
|
9
|
+
* @throws An error related to backend's rejection
|
|
10
|
+
*
|
|
11
|
+
* @category Transport
|
|
12
|
+
* @hidden
|
|
13
|
+
*/
|
|
14
|
+
export const unwrapPayload = <T>(response: Amity.Response<T>): T => {
|
|
15
|
+
if (response.status === 'success') {
|
|
16
|
+
return response.data
|
|
17
|
+
} else if (response.status === 'fail') {
|
|
18
|
+
throw new ASCUnknownError(response.code)
|
|
19
|
+
} else if (response.status === 'error') {
|
|
20
|
+
throw new ASCApiError(response.message, response.code, Amity.ErrorLevel.ERROR)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// unjust, but helps force uncast "T | undefined" to allow deconstruction without warnings
|
|
24
|
+
return undefined as unknown as T
|
|
25
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import io from 'socket.io-client'
|
|
2
|
+
import { unwrapPayload } from './utils'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Creates a pre-configured socket.io instance
|
|
6
|
+
*
|
|
7
|
+
* @param endpoint The socket.io server's URL
|
|
8
|
+
* @returns A pre-configured (non-connected) socket.io client instance
|
|
9
|
+
*
|
|
10
|
+
* @category Transport
|
|
11
|
+
* @hidden
|
|
12
|
+
*/
|
|
13
|
+
export const createWebsocketTransport = (endpoint: string) => {
|
|
14
|
+
const socket = io(endpoint, {
|
|
15
|
+
autoConnect: false,
|
|
16
|
+
reconnectionDelay: 2000,
|
|
17
|
+
transports: ['websocket'],
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
// FIXME: disconnectClient removes this listener and client can get global ban event
|
|
21
|
+
socket.on('disconnect', (reason: string) => {
|
|
22
|
+
if (reason === 'io server disconnect')
|
|
23
|
+
socket.connect()
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
return socket
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Promisify a websocket event emission - resulting in a synchronous http-like XHR (ws legacy)
|
|
31
|
+
*
|
|
32
|
+
* @param client The current client for which to send the event with
|
|
33
|
+
* @param event The websocket event name
|
|
34
|
+
* @param data The event's payload
|
|
35
|
+
*
|
|
36
|
+
* @returns The data returned by the backend
|
|
37
|
+
* @throws An error related to backend's rejection
|
|
38
|
+
*
|
|
39
|
+
* @category Transport
|
|
40
|
+
* @async
|
|
41
|
+
* @hidden
|
|
42
|
+
*/
|
|
43
|
+
export const synchronousWSCall = async <T>(
|
|
44
|
+
client: Amity.Client,
|
|
45
|
+
event: string,
|
|
46
|
+
data?: Object,
|
|
47
|
+
)=> {
|
|
48
|
+
const { ws } = client
|
|
49
|
+
|
|
50
|
+
const value = await new Promise<T | undefined>((resolve, reject) => {
|
|
51
|
+
ws.emit(event, data, (response: Amity.Response<T>) => {
|
|
52
|
+
try {
|
|
53
|
+
resolve(unwrapPayload(response))
|
|
54
|
+
} catch (error) {
|
|
55
|
+
reject(error)
|
|
56
|
+
}
|
|
57
|
+
})
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
return value
|
|
61
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -41,8 +41,8 @@ export const createPost = async <T extends Amity.PostContentType | string>(
|
|
|
41
41
|
decoratePayload(data)
|
|
42
42
|
ingestInCache(data)
|
|
43
43
|
|
|
44
|
-
fireEvent('
|
|
45
|
-
fireEvent('
|
|
44
|
+
fireEvent('community.updated', { communities: data.communities! })
|
|
45
|
+
fireEvent('post.created', data)
|
|
46
46
|
|
|
47
47
|
const { posts } = data
|
|
48
48
|
return posts[0]
|
|
@@ -44,13 +44,13 @@ export const deletePost = async (
|
|
|
44
44
|
// later when realtime events covers that for us.
|
|
45
45
|
if (post.targetType === 'community') {
|
|
46
46
|
const community = await getCommunity(post.targetId);
|
|
47
|
-
fireEvent('
|
|
47
|
+
fireEvent('community.updated', { communities: [community] })
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
// to support hard deletion
|
|
51
51
|
const deleted = { ...post, isDeleted: true }
|
|
52
52
|
|
|
53
|
-
fireEvent('
|
|
53
|
+
fireEvent('post.deleted', { posts: [deleted] })
|
|
54
54
|
|
|
55
55
|
if (permanent) {
|
|
56
56
|
setTimeout(() => {
|
package/src/post/events/index.ts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
1
|
export * from './onPostCreated'
|
|
2
2
|
export * from './onPostUpdated'
|
|
3
3
|
export * from './onPostDeleted'
|
|
4
|
+
|
|
5
|
+
export * from './onPostApproved'
|
|
6
|
+
export * from './onPostDeclined'
|
|
7
|
+
|
|
8
|
+
export * from './onPostFlagged'
|
|
9
|
+
export * from './onPostUnflagged'
|
|
10
|
+
|
|
11
|
+
export * from './onPostReactionAdded'
|
|
12
|
+
export * from './onPostReactionRemoved'
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { createPostEventSubscriber } from './utils'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ```js
|
|
5
|
+
* import { onPostApproved } from '@amityco/ts-sdk'
|
|
6
|
+
* const dispose = onPostApproved(post => {
|
|
7
|
+
* // ...
|
|
8
|
+
* })
|
|
9
|
+
* ```
|
|
10
|
+
*
|
|
11
|
+
* Fired when a {@link Amity.Post} has been updated
|
|
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 Post Events
|
|
17
|
+
*/
|
|
18
|
+
export const onPostApproved = (callback: Amity.Listener<Amity.Post>): Amity.Unsubscriber =>
|
|
19
|
+
createPostEventSubscriber('post.approved', callback)
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { createEventSubscriber } from '~/core/events'
|
|
3
|
-
|
|
4
|
-
import { decoratePayload } from '~/core/query'
|
|
5
|
-
import { ingestInCache } from '~/core/cache'
|
|
1
|
+
import { createPostEventSubscriber } from './utils'
|
|
6
2
|
|
|
7
3
|
/**
|
|
8
4
|
* ```js
|
|
@@ -12,28 +8,12 @@ import { ingestInCache } from '~/core/cache'
|
|
|
12
8
|
* })
|
|
13
9
|
* ```
|
|
14
10
|
*
|
|
15
|
-
* Fired when
|
|
11
|
+
* Fired when {@link Amity.Post} has been created
|
|
16
12
|
*
|
|
17
13
|
* @param callback The function to call when the event was fired
|
|
18
14
|
* @returns an {@link Amity.Unsubscriber} function to stop listening
|
|
19
15
|
*
|
|
20
16
|
* @category Post Events
|
|
21
17
|
*/
|
|
22
|
-
export const onPostCreated = (
|
|
23
|
-
callback
|
|
24
|
-
): Amity.Unsubscriber => {
|
|
25
|
-
const client = getActiveClient()
|
|
26
|
-
|
|
27
|
-
const filter = (payload: Amity.PostPayload) => {
|
|
28
|
-
decoratePayload(payload)
|
|
29
|
-
ingestInCache(payload)
|
|
30
|
-
callback(payload.posts[0])
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return createEventSubscriber(
|
|
34
|
-
client,
|
|
35
|
-
'message/onPostCreated',
|
|
36
|
-
'v3.post.didCreate',
|
|
37
|
-
filter
|
|
38
|
-
)
|
|
39
|
-
}
|
|
18
|
+
export const onPostCreated = (callback: Amity.Listener<Amity.Post>): Amity.Unsubscriber =>
|
|
19
|
+
createPostEventSubscriber('post.created', callback)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { createPostEventSubscriber } from './utils'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ```js
|
|
5
|
+
* import { onPostDeclined } from '@amityco/ts-sdk'
|
|
6
|
+
* const dispose = onPostDeclined(post => {
|
|
7
|
+
* // ...
|
|
8
|
+
* })
|
|
9
|
+
* ```
|
|
10
|
+
*
|
|
11
|
+
* Fired when a {@link Amity.Post} has been updated
|
|
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 Post Events
|
|
17
|
+
*/
|
|
18
|
+
export const onPostDeclined = (callback: Amity.Listener<Amity.Post>): Amity.Unsubscriber =>
|
|
19
|
+
createPostEventSubscriber('post.declined', callback)
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { createEventSubscriber } from '~/core/events'
|
|
3
|
-
|
|
4
|
-
import { decoratePayload } from '~/core/query'
|
|
5
|
-
import { ingestInCache } from '~/core/cache'
|
|
1
|
+
import { createPostEventSubscriber } from './utils'
|
|
6
2
|
|
|
7
3
|
/**
|
|
8
4
|
* ```js
|
|
@@ -12,28 +8,12 @@ import { ingestInCache } from '~/core/cache'
|
|
|
12
8
|
* })
|
|
13
9
|
* ```
|
|
14
10
|
*
|
|
15
|
-
* Fired when
|
|
11
|
+
* Fired when a {@link Amity.Post} has been deleted
|
|
16
12
|
*
|
|
17
13
|
* @param callback The function to call when the event was fired
|
|
18
14
|
* @returns an {@link Amity.Unsubscriber} function to stop listening
|
|
19
15
|
*
|
|
20
16
|
* @category Post Events
|
|
21
17
|
*/
|
|
22
|
-
export const onPostDeleted = (
|
|
23
|
-
callback
|
|
24
|
-
): Amity.Unsubscriber => {
|
|
25
|
-
const client = getActiveClient()
|
|
26
|
-
|
|
27
|
-
const filter = (payload: Amity.PostPayload) => {
|
|
28
|
-
decoratePayload(payload)
|
|
29
|
-
ingestInCache(payload)
|
|
30
|
-
callback(payload.posts[0])
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return createEventSubscriber(
|
|
34
|
-
client,
|
|
35
|
-
'message/onPostDeleted',
|
|
36
|
-
'v3.post.didDelete',
|
|
37
|
-
filter
|
|
38
|
-
)
|
|
39
|
-
}
|
|
18
|
+
export const onPostDeleted = (callback: Amity.Listener<Amity.Post>): Amity.Unsubscriber =>
|
|
19
|
+
createPostEventSubscriber('post.deleted', callback)
|