@amityco/ts-sdk 0.0.1-beta.36 → 0.0.1-beta.38
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/.eslintrc.json +3 -5
- package/dist/@types/core/errors.d.ts +1 -0
- package/dist/@types/core/errors.d.ts.map +1 -1
- package/dist/@types/core/events.d.ts +5 -0
- package/dist/@types/core/events.d.ts.map +1 -1
- package/dist/@types/domains/category.d.ts +7 -0
- package/dist/@types/domains/category.d.ts.map +1 -1
- package/dist/@types/domains/client.d.ts +21 -1
- package/dist/@types/domains/client.d.ts.map +1 -1
- package/dist/@types/domains/community.d.ts +12 -0
- package/dist/@types/domains/community.d.ts.map +1 -1
- package/dist/@types/global.d.ts +12 -0
- package/dist/@types/global.d.ts.map +1 -1
- package/dist/category/api/queryCategories.d.ts +1 -5
- package/dist/category/api/queryCategories.d.ts.map +1 -1
- package/dist/category/observers/index.d.ts +2 -0
- package/dist/category/observers/index.d.ts.map +1 -0
- package/dist/category/observers/liveCategories.d.ts +18 -0
- package/dist/category/observers/liveCategories.d.ts.map +1 -0
- package/dist/category/observers/tests/liveCategories.test.d.ts +2 -0
- package/dist/category/observers/tests/liveCategories.test.d.ts.map +1 -0
- package/dist/channel/api/tests/getChannels.test.d.ts +2 -0
- package/dist/channel/api/tests/getChannels.test.d.ts.map +1 -0
- package/dist/channel/api/tests/leaveChannel.test.d.ts +2 -0
- package/dist/channel/api/tests/leaveChannel.test.d.ts.map +1 -0
- package/dist/channel/observers/liveChannel.d.ts.map +1 -1
- package/dist/client/api/accessTokenExpiryWatcher.d.ts +7 -0
- package/dist/client/api/accessTokenExpiryWatcher.d.ts.map +1 -0
- package/dist/client/api/activeUser.d.ts +1 -1
- package/dist/client/api/activeUser.d.ts.map +1 -1
- package/dist/client/api/connectClient.d.ts +1 -1
- package/dist/client/api/connectClient.d.ts.map +1 -1
- package/dist/client/api/createClient.d.ts +1 -1
- package/dist/client/api/createClient.d.ts.map +1 -1
- package/dist/client/api/disconnectClient.d.ts +0 -1
- package/dist/client/api/disconnectClient.d.ts.map +1 -1
- package/dist/client/api/getToken.d.ts +7 -5
- package/dist/client/api/getToken.d.ts.map +1 -1
- package/dist/client/api/index.d.ts +1 -0
- package/dist/client/api/index.d.ts.map +1 -1
- package/dist/client/api/renewal.d.ts +2 -0
- package/dist/client/api/renewal.d.ts.map +1 -0
- package/dist/client/api/setSessionState.d.ts +12 -0
- package/dist/client/api/setSessionState.d.ts.map +1 -0
- package/dist/client/api/terminateClient.d.ts +9 -0
- package/dist/client/api/terminateClient.d.ts.map +1 -0
- package/dist/client/api/tests/accessTokenExpiryWatcher.test.d.ts +2 -0
- package/dist/client/api/tests/accessTokenExpiryWatcher.test.d.ts.map +1 -0
- package/dist/client/api/tests/connectClient.test.d.ts +2 -0
- package/dist/client/api/tests/connectClient.test.d.ts.map +1 -0
- package/dist/client/api/tests/disconnectClient.test.d.ts +2 -0
- package/dist/client/api/tests/disconnectClient.test.d.ts.map +1 -0
- package/dist/client/api/tests/getToken.test.d.ts +2 -0
- package/dist/client/api/tests/getToken.test.d.ts.map +1 -0
- package/dist/client/api/tests/renewal.test.d.ts +2 -0
- package/dist/client/api/tests/renewal.test.d.ts.map +1 -0
- package/dist/client/api/tests/setSessionState.test.d.ts +2 -0
- package/dist/client/api/tests/setSessionState.test.d.ts.map +1 -0
- package/dist/client/api/tests/terminateClient.test.d.ts +2 -0
- package/dist/client/api/tests/terminateClient.test.d.ts.map +1 -0
- package/dist/client/events/index.d.ts +1 -0
- package/dist/client/events/index.d.ts.map +1 -1
- package/dist/client/events/onClientBanned.d.ts +1 -1
- package/dist/client/events/onClientBanned.d.ts.map +1 -1
- package/dist/client/events/onSessionStateChange.d.ts +17 -0
- package/dist/client/events/onSessionStateChange.d.ts.map +1 -0
- package/dist/client/events/onTokenExpired.d.ts +17 -0
- package/dist/client/events/onTokenExpired.d.ts.map +1 -0
- package/dist/client/events/onTokenTerminated.d.ts +11 -0
- package/dist/client/events/onTokenTerminated.d.ts.map +1 -0
- package/dist/client/events/tests/onSessionStateChange.test.d.ts +2 -0
- package/dist/client/events/tests/onSessionStateChange.test.d.ts.map +1 -0
- package/dist/client/events/tests/onTokenTerminated.test.d.ts +2 -0
- package/dist/client/events/tests/onTokenTerminated.test.d.ts.map +1 -0
- package/dist/client/utils/setClientToken.d.ts +19 -0
- package/dist/client/utils/setClientToken.d.ts.map +1 -0
- package/dist/comment/api/deleteComment.d.ts.map +1 -1
- package/dist/comment/api/getComment.d.ts.map +1 -1
- package/dist/comment/events/tests/onCommentDeleted.test.d.ts +2 -0
- package/dist/comment/events/tests/onCommentDeleted.test.d.ts.map +1 -0
- package/dist/comment/observers/index.d.ts +1 -0
- package/dist/comment/observers/index.d.ts.map +1 -1
- package/dist/comment/observers/liveComment.d.ts +21 -0
- package/dist/comment/observers/liveComment.d.ts.map +1 -0
- package/dist/comment/observers/tests/liveComment.test.d.ts +2 -0
- package/dist/comment/observers/tests/liveComment.test.d.ts.map +1 -0
- package/dist/community/api/queryCommunities.d.ts +1 -10
- package/dist/community/api/queryCommunities.d.ts.map +1 -1
- package/dist/community/events/index.d.ts +1 -0
- package/dist/community/events/index.d.ts.map +1 -1
- package/dist/community/events/onCommunityUserChanged.d.ts +17 -0
- package/dist/community/events/onCommunityUserChanged.d.ts.map +1 -0
- package/dist/community/events/utils.d.ts +1 -0
- package/dist/community/events/utils.d.ts.map +1 -1
- package/dist/community/observers/index.d.ts +1 -0
- package/dist/community/observers/index.d.ts.map +1 -1
- package/dist/community/observers/liveCommunities.d.ts +20 -0
- package/dist/community/observers/liveCommunities.d.ts.map +1 -0
- package/dist/community/observers/tests/liveCommunities.test.d.ts +2 -0
- package/dist/community/observers/tests/liveCommunities.test.d.ts.map +1 -0
- package/dist/core/events.d.ts +3 -3
- package/dist/core/events.d.ts.map +1 -1
- package/dist/core/query/sorting.d.ts +6 -0
- package/dist/core/query/sorting.d.ts.map +1 -1
- package/dist/core/subscription.d.ts.map +1 -1
- package/dist/core/transports/http.d.ts +0 -5
- package/dist/core/transports/http.d.ts.map +1 -1
- package/dist/file/api/test/createImage.test.d.ts +2 -0
- package/dist/file/api/test/createImage.test.d.ts.map +1 -0
- package/dist/file/api/test/createVideo.test.d.ts +2 -0
- package/dist/file/api/test/createVideo.test.d.ts.map +1 -0
- package/dist/index.cjs.js +944 -332
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +937 -332
- package/dist/index.umd.js +4 -4
- package/dist/message/observers/liveMessage.d.ts.map +1 -1
- package/dist/post/observers/index.d.ts +1 -0
- package/dist/post/observers/index.d.ts.map +1 -1
- package/dist/post/observers/livePost.d.ts +21 -0
- package/dist/post/observers/livePost.d.ts.map +1 -0
- package/dist/post/observers/tests/livePost.test.d.ts +2 -0
- package/dist/post/observers/tests/livePost.test.d.ts.map +1 -0
- package/dist/stream/api/tests/createStream.test.d.ts +2 -0
- package/dist/stream/api/tests/createStream.test.d.ts.map +1 -0
- package/dist/stream/api/tests/deleteStream.test.d.ts +2 -0
- package/dist/stream/api/tests/deleteStream.test.d.ts.map +1 -0
- package/dist/stream/api/tests/getStream.test.d.ts +2 -0
- package/dist/stream/api/tests/getStream.test.d.ts.map +1 -0
- package/dist/subChannel/api/tests/createSubChannel.test.d.ts +2 -0
- package/dist/subChannel/api/tests/createSubChannel.test.d.ts.map +1 -0
- package/dist/subChannel/api/tests/deleteSubChannel.test.d.ts +2 -0
- package/dist/subChannel/api/tests/deleteSubChannel.test.d.ts.map +1 -0
- package/dist/subChannel/api/tests/getSubChannel.test.d.ts +2 -0
- package/dist/subChannel/api/tests/getSubChannel.test.d.ts.map +1 -0
- package/dist/subChannel/api/tests/getSubChannels.test.d.ts +2 -0
- package/dist/subChannel/api/tests/getSubChannels.test.d.ts.map +1 -0
- package/dist/subChannel/api/tests/updateSubChannel.test.d.ts +2 -0
- package/dist/subChannel/api/tests/updateSubChannel.test.d.ts.map +1 -0
- package/dist/subChannel/observers/liveSubChannel.d.ts.map +1 -1
- package/dist/user/api/tests/updateUser.test.d.ts +2 -0
- package/dist/user/api/tests/updateUser.test.d.ts.map +1 -0
- package/dist/user/observers/liveUser.d.ts.map +1 -1
- package/dist/utils/constants.d.ts +2 -0
- package/dist/utils/constants.d.ts.map +1 -1
- package/dist/utils/liveObject.d.ts +2 -0
- package/dist/utils/liveObject.d.ts.map +1 -0
- package/dist/utils/tests/client.d.ts.map +1 -1
- package/dist/utils/tests/dummy/category.d.ts +64 -0
- package/dist/utils/tests/dummy/category.d.ts.map +1 -0
- package/dist/utils/tests/dummy/channel.d.ts +50 -0
- package/dist/utils/tests/dummy/channel.d.ts.map +1 -1
- package/dist/utils/tests/dummy/community.d.ts +132 -0
- package/dist/utils/tests/dummy/community.d.ts.map +1 -1
- package/dist/utils/tests/dummy/file.d.ts +3 -0
- package/dist/utils/tests/dummy/file.d.ts.map +1 -1
- package/dist/utils/tests/dummy/index.d.ts +3 -0
- package/dist/utils/tests/dummy/index.d.ts.map +1 -1
- package/dist/utils/tests/dummy/post.d.ts +2 -0
- package/dist/utils/tests/dummy/post.d.ts.map +1 -1
- package/dist/utils/tests/dummy/stream.d.ts +83 -0
- package/dist/utils/tests/dummy/stream.d.ts.map +1 -0
- package/dist/utils/tests/dummy/token.d.ts +11 -0
- package/dist/utils/tests/dummy/token.d.ts.map +1 -0
- package/dist/utils/tests/dummy/user.d.ts +18 -0
- package/dist/utils/tests/dummy/user.d.ts.map +1 -1
- package/dist/utils/tests/liveObject.test.d.ts +2 -0
- package/dist/utils/tests/liveObject.test.d.ts.map +1 -0
- package/package.json +4 -4
- package/src/@types/core/errors.ts +1 -0
- package/src/@types/core/events.ts +7 -0
- package/src/@types/domains/category.ts +13 -0
- package/src/@types/domains/client.ts +45 -1
- package/src/@types/domains/community.ts +25 -0
- package/src/@types/global.ts +19 -0
- package/src/category/api/queryCategories.ts +3 -5
- package/src/category/observers/index.ts +1 -0
- package/src/category/observers/liveCategories.ts +141 -0
- package/src/category/observers/tests/liveCategories.test.ts +147 -0
- package/src/channel/api/tests/createChannel.test.ts +30 -6
- package/src/channel/api/tests/getChannel.test.ts +3 -1
- package/src/channel/api/tests/getChannels.test.ts +97 -0
- package/src/channel/api/tests/joinChannel.test.ts +62 -3
- package/src/channel/api/tests/leaveChannel.test.ts +90 -0
- package/src/channel/api/tests/queryChannels.test.ts +38 -1
- package/src/channel/observers/liveChannel.ts +8 -80
- package/src/client/api/accessTokenExpiryWatcher.ts +85 -0
- package/src/client/api/activeUser.ts +1 -1
- package/src/client/api/connectClient.ts +105 -24
- package/src/client/api/createClient.ts +9 -1
- package/src/client/api/disconnectClient.ts +26 -2
- package/src/client/api/getToken.ts +6 -6
- package/src/client/api/index.ts +2 -0
- package/src/client/api/renewal.ts +74 -0
- package/src/client/api/setSessionState.ts +75 -0
- package/src/client/api/terminateClient.ts +20 -0
- package/src/client/api/tests/accessTokenExpiryWatcher.test.ts +132 -0
- package/src/client/api/tests/connectClient.test.ts +84 -0
- package/src/client/api/tests/createClient.test.ts +8 -0
- package/src/client/api/tests/disconnectClient.test.ts +78 -0
- package/src/client/api/tests/getToken.test.ts +36 -0
- package/src/client/api/tests/renewal.test.ts +67 -0
- package/src/client/api/tests/setSessionState.test.ts +62 -0
- package/src/client/api/tests/terminateClient.test.ts +29 -0
- package/src/client/events/index.ts +2 -0
- package/src/client/events/onClientBanned.ts +12 -5
- package/src/client/events/onSessionStateChange.ts +31 -0
- package/src/client/events/onTokenExpired.ts +26 -0
- package/src/client/events/onTokenTerminated.ts +20 -0
- package/src/client/events/tests/onSessionStateChange.test.ts +37 -0
- package/src/client/events/tests/onTokenTerminated.test.ts +37 -0
- package/src/client/tests/connectClient.test.ts +6 -1
- package/src/client/utils/setClientToken.ts +39 -0
- package/src/comment/api/deleteComment.ts +5 -5
- package/src/comment/api/getComment.ts +8 -3
- package/src/comment/events/tests/onCommentDeleted.test.ts +27 -0
- package/src/comment/observers/index.ts +1 -0
- package/src/comment/observers/liveComment.ts +43 -0
- package/src/comment/observers/tests/liveComment.test.ts +95 -0
- package/src/community/api/queryCommunities.ts +3 -10
- package/src/community/api/test/addCommunityMember.test.ts +14 -2
- package/src/community/api/test/joinCommunity.test.ts +14 -2
- package/src/community/api/test/leaveCommunity.test.ts +11 -1
- package/src/community/api/test/removeCommunityMembers.test.ts +11 -1
- package/src/community/events/index.ts +1 -0
- package/src/community/events/onCommunityUserChanged.ts +20 -0
- package/src/community/events/test/onCommunityJoined.test.ts +1 -1
- package/src/community/events/test/onCommunityUserAdded.test.ts +1 -1
- package/src/community/events/test/onCommunityUserBanned.test.ts +1 -1
- package/src/community/events/test/onCommunityUserUnbaned.test.ts +1 -1
- package/src/community/events/test/utils.test.ts +52 -3
- package/src/community/events/utils.ts +49 -0
- package/src/community/observers/index.ts +1 -0
- package/src/community/observers/liveCommunities.ts +188 -0
- package/src/community/observers/tests/liveCommunities.test.ts +284 -0
- package/src/core/events.ts +5 -3
- package/src/core/query/sorting.ts +8 -0
- package/src/core/subscription.ts +3 -1
- package/src/core/transports/http.ts +52 -13
- package/src/core/transports/mqtt.ts +1 -1
- package/src/core/transports/test/http.test.ts +49 -60
- package/src/external/api/createUserToken.ts +2 -2
- package/src/file/api/createFile.ts +1 -1
- package/src/file/api/createImage.ts +1 -1
- package/src/file/api/createVideo.ts +1 -1
- package/src/file/api/test/createImage.test.ts +69 -0
- package/src/file/api/test/createVideo.test.ts +81 -0
- package/src/index.ts +1 -0
- package/src/message/observers/liveMessage.ts +11 -83
- package/src/message/tests/observers/liveMessage.test.ts +1 -143
- package/src/post/observers/index.ts +1 -0
- package/src/post/observers/livePost.ts +47 -0
- package/src/post/observers/tests/livePost.test.ts +97 -0
- package/src/stream/api/tests/createStream.test.ts +22 -0
- package/src/stream/api/tests/deleteStream.test.ts +50 -0
- package/src/stream/api/tests/getStream.test.ts +23 -0
- package/src/subChannel/api/tests/createSubChannel.test.ts +110 -0
- package/src/subChannel/api/tests/deleteSubChannel.test.ts +112 -0
- package/src/subChannel/api/tests/getSubChannel.test.ts +97 -0
- package/src/subChannel/api/tests/getSubChannels.test.ts +97 -0
- package/src/subChannel/api/tests/updateSubChannel.test.ts +86 -0
- package/src/subChannel/observers/liveSubChannel.ts +6 -56
- package/src/subChannel/observers/tests/liveSubChannel.test.ts +0 -82
- package/src/user/api/tests/updateUser.test.ts +60 -0
- package/src/user/observers/liveUser.ts +9 -61
- package/src/user/tests/observers/liveUser.test.ts +1 -154
- package/src/utils/constants.ts +2 -0
- package/src/utils/liveObject.ts +86 -0
- package/src/utils/tests/client.ts +18 -2
- package/src/utils/tests/dummy/category.ts +57 -0
- package/src/utils/tests/dummy/channel.ts +51 -1
- package/src/utils/tests/dummy/community.ts +94 -0
- package/src/utils/tests/dummy/file.ts +32 -0
- package/src/utils/tests/dummy/index.ts +4 -0
- package/src/utils/tests/dummy/post.ts +56 -45
- package/src/utils/tests/dummy/stream.ts +86 -0
- package/src/utils/tests/dummy/token.ts +12 -0
- package/src/utils/tests/dummy/user.ts +21 -0
- package/src/utils/tests/liveObject.test.ts +172 -0
|
@@ -4,19 +4,34 @@ import { disconnectClient } from '~/client/api/disconnectClient';
|
|
|
4
4
|
import { getDeviceId } from '~/core/device';
|
|
5
5
|
import { proxyWebsocketEvents } from '~/core/events';
|
|
6
6
|
import {
|
|
7
|
+
getUserTopic,
|
|
7
8
|
getNetworkTopic,
|
|
8
9
|
getSmartFeedChannelTopic,
|
|
9
10
|
getSmartFeedMessageTopic,
|
|
10
11
|
getSmartFeedSubChannelTopic,
|
|
11
12
|
subscribeTopic,
|
|
12
13
|
} from '~/core/subscription';
|
|
14
|
+
|
|
13
15
|
import { onUserDeleted } from '~/user/events/onUserDeleted';
|
|
14
16
|
|
|
15
17
|
import { getActiveClient } from './activeClient';
|
|
16
|
-
import {
|
|
18
|
+
import { terminateClient } from './terminateClient';
|
|
19
|
+
import { setActiveUser, getActiveUser } from './activeUser';
|
|
20
|
+
|
|
21
|
+
import { setSessionState } from './setSessionState';
|
|
17
22
|
|
|
18
|
-
import { getToken } from './getToken';
|
|
19
23
|
import { onClientBanned } from '../events';
|
|
24
|
+
import { onTokenExpired } from '../events/onTokenExpired';
|
|
25
|
+
import { onTokenTerminated } from '../events/onTokenTerminated';
|
|
26
|
+
|
|
27
|
+
import { setClientToken } from '../utils/setClientToken';
|
|
28
|
+
|
|
29
|
+
/*
|
|
30
|
+
* declared earlier to accomodate case when logging in with a different user
|
|
31
|
+
* than the one already connected, in which case the existing subscriptions need
|
|
32
|
+
* to be cleared
|
|
33
|
+
*/
|
|
34
|
+
const subscriptions: Amity.Unsubscriber[] = [];
|
|
20
35
|
|
|
21
36
|
/**
|
|
22
37
|
* ```js
|
|
@@ -40,52 +55,118 @@ import { onClientBanned } from '../events';
|
|
|
40
55
|
*/
|
|
41
56
|
export const connectClient = async (
|
|
42
57
|
params: Amity.ConnectClientParams,
|
|
58
|
+
sessionHandler: Amity.SessionHandler,
|
|
43
59
|
config?: Amity.ConnectClientConfig,
|
|
44
60
|
): Promise<boolean> => {
|
|
45
61
|
const client = getActiveClient();
|
|
46
|
-
|
|
62
|
+
let unsubWatcher: Amity.Unsubscriber;
|
|
63
|
+
|
|
64
|
+
client.log('client/api/connectClient', {
|
|
65
|
+
apiKey: client.apiKey,
|
|
66
|
+
sessionState: client.sessionState,
|
|
67
|
+
...params,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// if connecting to a different userId than the one that is connected currently
|
|
71
|
+
if (client.userId && client.userId !== params.userId) {
|
|
72
|
+
await disconnectClient();
|
|
73
|
+
|
|
74
|
+
// Remove subscription to ban and delete
|
|
75
|
+
subscriptions.forEach(fn => fn());
|
|
76
|
+
}
|
|
47
77
|
|
|
48
78
|
// default values
|
|
49
79
|
params.deviceId ??= getDeviceId();
|
|
50
80
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
81
|
+
try {
|
|
82
|
+
// @ts-ignore: in that particular case, typing can be
|
|
83
|
+
// ignored since we enforce default values just before.
|
|
84
|
+
const { users } = await setClientToken(params);
|
|
54
85
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
86
|
+
// FIXME: events are duplicated if connectClient is called few times without disconnectClient
|
|
87
|
+
// wire websocket events to our event emitter
|
|
88
|
+
proxyWebsocketEvents(client.ws, client.emitter);
|
|
58
89
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
90
|
+
// TODO: in phase 2, this should not be necessary. we should have WS
|
|
91
|
+
// to be connected "on demand" rather than "by default"
|
|
92
|
+
await new Promise(resolve => {
|
|
93
|
+
client.ws.once('connect', resolve);
|
|
94
|
+
client.ws.open();
|
|
95
|
+
});
|
|
62
96
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
client.ws.once('connect', resolve);
|
|
67
|
-
client.ws.open();
|
|
68
|
-
});
|
|
97
|
+
client.userId = params.userId;
|
|
98
|
+
|
|
99
|
+
client.sessionHandler = sessionHandler;
|
|
69
100
|
|
|
70
|
-
|
|
71
|
-
|
|
101
|
+
/*
|
|
102
|
+
* Cannot push to subscriptions as watcher needs to continue working even if
|
|
103
|
+
* token expires
|
|
104
|
+
*/
|
|
105
|
+
unsubWatcher = client.accessTokenExpiryWatcher(
|
|
106
|
+
client.token?.issuedAt!,
|
|
107
|
+
client.token?.expiresAt!,
|
|
108
|
+
sessionHandler!,
|
|
109
|
+
);
|
|
72
110
|
|
|
73
|
-
|
|
111
|
+
setActiveUser(users[0]);
|
|
112
|
+
} catch (error) {
|
|
113
|
+
/*
|
|
114
|
+
* if getting token failed session state reverts to initial state when app
|
|
115
|
+
* is first launched
|
|
116
|
+
*/
|
|
117
|
+
setSessionState(Amity.SessionStates.NOT_LOGGED_IN);
|
|
118
|
+
|
|
119
|
+
// pass error down tree so the calling function handle it
|
|
120
|
+
throw error;
|
|
121
|
+
}
|
|
74
122
|
|
|
75
123
|
if (config?.disableRTE !== true) {
|
|
76
124
|
subscribeTopic(getNetworkTopic());
|
|
77
125
|
subscribeTopic(getSmartFeedChannelTopic());
|
|
78
126
|
subscribeTopic(getSmartFeedSubChannelTopic());
|
|
79
127
|
subscribeTopic(getSmartFeedMessageTopic());
|
|
128
|
+
// subscribing to user topic is necessary to handle ban event
|
|
129
|
+
subscribeTopic(getUserTopic(getActiveUser()));
|
|
80
130
|
}
|
|
81
131
|
|
|
82
|
-
|
|
83
|
-
|
|
132
|
+
subscriptions.push(
|
|
133
|
+
// GLOBAL_BAN
|
|
134
|
+
onClientBanned((_: Amity.UserPayload) => {
|
|
135
|
+
terminateClient();
|
|
136
|
+
|
|
137
|
+
subscriptions.forEach(fn => fn());
|
|
138
|
+
|
|
139
|
+
unsubWatcher();
|
|
140
|
+
}),
|
|
141
|
+
|
|
142
|
+
onTokenTerminated(_ => {
|
|
143
|
+
terminateClient();
|
|
144
|
+
|
|
145
|
+
subscriptions.forEach(fn => fn());
|
|
146
|
+
|
|
147
|
+
unsubWatcher();
|
|
148
|
+
}),
|
|
149
|
+
|
|
150
|
+
onUserDeleted((user: Amity.User) => {
|
|
151
|
+
if (user.userId === client.userId) {
|
|
152
|
+
terminateClient();
|
|
153
|
+
|
|
154
|
+
subscriptions.forEach(fn => fn());
|
|
155
|
+
|
|
156
|
+
unsubWatcher();
|
|
157
|
+
}
|
|
158
|
+
}),
|
|
159
|
+
|
|
160
|
+
onTokenExpired(state => {
|
|
161
|
+
setSessionState(state);
|
|
162
|
+
|
|
84
163
|
disconnectClient();
|
|
164
|
+
|
|
85
165
|
subscriptions.forEach(fn => fn());
|
|
86
166
|
}),
|
|
167
|
+
|
|
87
168
|
onUserDeleted(() => null),
|
|
88
|
-
|
|
169
|
+
);
|
|
89
170
|
|
|
90
171
|
return client.ws.connected;
|
|
91
172
|
};
|
|
@@ -14,6 +14,8 @@ import { createEventEmitter } from '~/core/events';
|
|
|
14
14
|
import { getActiveClient, setActiveClient } from './activeClient';
|
|
15
15
|
import { getFeedSettings } from './getFeedSettings';
|
|
16
16
|
|
|
17
|
+
import { accessTokenExpiryWatcher } from './accessTokenExpiryWatcher';
|
|
18
|
+
|
|
17
19
|
const DEFAULT_DEBUG_SESSION = 'amity';
|
|
18
20
|
|
|
19
21
|
/**
|
|
@@ -27,7 +29,7 @@ const DEFAULT_DEBUG_SESSION = 'amity';
|
|
|
27
29
|
* @param apiKey for the {@link Amity.Client} instance
|
|
28
30
|
* @param apiRegion endpoint to connect to
|
|
29
31
|
* @param apiEndpoint custom endpoint in case you don't want to use a preset endpoint
|
|
30
|
-
* @param debugSession session's identifier for the client's logger instance
|
|
32
|
+
* @param param.debugSession session's identifier for the client's logger instance
|
|
31
33
|
* @returns A {@link Amity.Client} instance
|
|
32
34
|
*
|
|
33
35
|
* @category Client API
|
|
@@ -59,6 +61,9 @@ export const createClient = (
|
|
|
59
61
|
|
|
60
62
|
const emitter = createEventEmitter();
|
|
61
63
|
|
|
64
|
+
const sessionState = Amity.SessionStates.NOT_LOGGED_IN;
|
|
65
|
+
const sessionHandler = undefined;
|
|
66
|
+
|
|
62
67
|
const client = {
|
|
63
68
|
version: `${VERSION}`,
|
|
64
69
|
|
|
@@ -68,8 +73,11 @@ export const createClient = (
|
|
|
68
73
|
ws,
|
|
69
74
|
mqtt,
|
|
70
75
|
emitter,
|
|
76
|
+
accessTokenExpiryWatcher,
|
|
71
77
|
use: () => setActiveClient(client),
|
|
72
78
|
|
|
79
|
+
sessionState,
|
|
80
|
+
sessionHandler,
|
|
73
81
|
getFeedSettings,
|
|
74
82
|
};
|
|
75
83
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getActiveClient } from './activeClient';
|
|
2
|
+
import { setSessionState } from './setSessionState';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* ```js
|
|
@@ -8,7 +9,6 @@ import { getActiveClient } from './activeClient';
|
|
|
8
9
|
*
|
|
9
10
|
* Disconnects an {@link Amity.Client} instance from ASC servers
|
|
10
11
|
*
|
|
11
|
-
* @param client The {@link Amity.Client} instance to disconnect
|
|
12
12
|
* @returns a success boolean if disconnected
|
|
13
13
|
*
|
|
14
14
|
* @category Client API
|
|
@@ -16,6 +16,7 @@ import { getActiveClient } from './activeClient';
|
|
|
16
16
|
*/
|
|
17
17
|
export const disconnectClient = async (): Promise<boolean> => {
|
|
18
18
|
const client = getActiveClient();
|
|
19
|
+
|
|
19
20
|
client.log('client/api/disconnectClient');
|
|
20
21
|
|
|
21
22
|
await new Promise(resolve => {
|
|
@@ -29,7 +30,30 @@ export const disconnectClient = async (): Promise<boolean> => {
|
|
|
29
30
|
client.ws.removeAllListeners();
|
|
30
31
|
client.mqtt.removeAllListeners();
|
|
31
32
|
client.userId = undefined;
|
|
32
|
-
client.
|
|
33
|
+
client.token = undefined;
|
|
34
|
+
|
|
35
|
+
client.http.defaults.headers.common.Authorization = '';
|
|
36
|
+
client.ws.io.opts.query = { token: '' };
|
|
37
|
+
|
|
38
|
+
/*
|
|
39
|
+
* for cases when session state is terminated (example on ban) or token expired,
|
|
40
|
+
* the terminating block will set session state to terminated or for the or
|
|
41
|
+
* in the case of expired token the same happens
|
|
42
|
+
*
|
|
43
|
+
* establishing state also ignored in cases where accessTokenExpiryWatcher
|
|
44
|
+
* calls renewal. There is a possibility that renewal will be called before
|
|
45
|
+
* disconnectClient finishes execution
|
|
46
|
+
*/
|
|
47
|
+
if (client.sessionState === Amity.SessionStates.ESTABLISHED)
|
|
48
|
+
setSessionState(Amity.SessionStates.NOT_LOGGED_IN);
|
|
49
|
+
|
|
50
|
+
/*
|
|
51
|
+
* Cache should be usable if tokenExpired
|
|
52
|
+
* https://ekoapp.atlassian.net/wiki/spaces/UP/pages/2082537485/ASC+Core+-+Session+Management+3.0#SDK-usability-based-on-Session-State
|
|
53
|
+
*/
|
|
54
|
+
if (client.sessionState !== Amity.SessionStates.TOKEN_EXPIRED && client.cache) {
|
|
55
|
+
client.cache = { data: {} };
|
|
56
|
+
}
|
|
33
57
|
|
|
34
58
|
return !client.ws.connected;
|
|
35
59
|
};
|
|
@@ -5,10 +5,10 @@ import { getDeviceInfo } from '~/core/device';
|
|
|
5
5
|
/**
|
|
6
6
|
* Retrieves a pair of {@link Amity.Tokens} necessary for connection
|
|
7
7
|
*
|
|
8
|
-
* @param userId The userId to use to issue a token
|
|
9
|
-
* @param displayName The user's displayName
|
|
10
|
-
* @param deviceId The user's device Id (can be manually set for native users)
|
|
11
|
-
* @param authToken The authentication token - necessary when network option is set to secure
|
|
8
|
+
* @param params.userId The userId to use to issue a token
|
|
9
|
+
* @param params.displayName The user's displayName
|
|
10
|
+
* @param params.deviceId The user's device Id (can be manually set for native users)
|
|
11
|
+
* @param params.authToken The authentication token - necessary when network option is set to secure
|
|
12
12
|
* @return The accessToken for the given userId
|
|
13
13
|
*
|
|
14
14
|
* @category Client API
|
|
@@ -23,10 +23,10 @@ export const getToken = async (params: {
|
|
|
23
23
|
const client = getActiveClient();
|
|
24
24
|
client.log('client/api/getToken', params);
|
|
25
25
|
|
|
26
|
-
const deviceInfo =
|
|
26
|
+
const deviceInfo = getDeviceInfo();
|
|
27
27
|
|
|
28
28
|
const { data } = await client.http.post<Amity.Tokens & { users: Amity.User[] }>(
|
|
29
|
-
'/
|
|
29
|
+
'/api/v3/sessions',
|
|
30
30
|
{
|
|
31
31
|
...params,
|
|
32
32
|
deviceInfo,
|
package/src/client/api/index.ts
CHANGED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { getDeviceId } from '~/core/device';
|
|
2
|
+
import { ACCESS_TOKEN_WATCHER_INTERVAL } from '~/utils/constants';
|
|
3
|
+
|
|
4
|
+
import { getActiveUser } from './activeUser';
|
|
5
|
+
import { setClientToken as refreshToken } from '../utils/setClientToken';
|
|
6
|
+
import { getActiveClient } from './activeClient';
|
|
7
|
+
import { connectClient } from './connectClient';
|
|
8
|
+
|
|
9
|
+
/*
|
|
10
|
+
* Renewal defintion accepted by SessionHandler interface
|
|
11
|
+
*
|
|
12
|
+
* Tech Spec:
|
|
13
|
+
* https://ekoapp.atlassian.net/wiki/spaces/UP/pages/2082537485/ASC+Core+-+Session+Management+3.0#Session-Handler
|
|
14
|
+
*
|
|
15
|
+
* @category private
|
|
16
|
+
*/
|
|
17
|
+
export const renewal = (): Amity.AccessTokenRenewal => {
|
|
18
|
+
let tokenRenewed = false;
|
|
19
|
+
let renewTimeoutId: ReturnType<typeof setTimeout>;
|
|
20
|
+
|
|
21
|
+
const client = getActiveClient();
|
|
22
|
+
|
|
23
|
+
client.log('initiating access token renewal');
|
|
24
|
+
/*
|
|
25
|
+
* Renews a token if it is hasn't been renewed before. Also marks token as
|
|
26
|
+
* renewed once done
|
|
27
|
+
* Per instance of Renewal, only one renewal is allowed
|
|
28
|
+
*/
|
|
29
|
+
const renewToken = async (authToken?: Amity.ConnectClientParams['authToken']): Promise<void> => {
|
|
30
|
+
const { userId, displayName } = getActiveUser();
|
|
31
|
+
const deviceId = getDeviceId();
|
|
32
|
+
|
|
33
|
+
const params = { userId, displayName, authToken, deviceId };
|
|
34
|
+
|
|
35
|
+
if (client.sessionState === Amity.SessionStates.TOKEN_EXPIRED) {
|
|
36
|
+
// sessionHandler will never be empty when renewal is instantiatied
|
|
37
|
+
await connectClient(params, client.sessionHandler!);
|
|
38
|
+
} else {
|
|
39
|
+
// about to expire
|
|
40
|
+
|
|
41
|
+
// @ts-ignore: in that particular case, typing can be
|
|
42
|
+
// ignored since we enforce default values just before.
|
|
43
|
+
await refreshToken(params);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
tokenRenewed = true;
|
|
47
|
+
|
|
48
|
+
if (renewTimeoutId) clearTimeout(renewTimeoutId);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
renew: () => {
|
|
53
|
+
if (tokenRenewed) {
|
|
54
|
+
console.log("'renew' method can be called only once per renewal instance");
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
renewToken();
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
renewWithAuthToken: (authToken: string) => {
|
|
61
|
+
if (tokenRenewed) {
|
|
62
|
+
console.log("'renewWithAuthToken' method can be called only once per renewal instance");
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
renewToken(authToken);
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
unableToRetrieveAuthToken: () => {
|
|
69
|
+
renewTimeoutId = setTimeout(() => {
|
|
70
|
+
client.sessionHandler?.sessionWillRenewAccessToken(renewal());
|
|
71
|
+
}, ACCESS_TOKEN_WATCHER_INTERVAL);
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { fireEvent } from '~/core/events';
|
|
2
|
+
import { ASCError } from '~/core/errors';
|
|
3
|
+
|
|
4
|
+
import { getActiveClient } from './activeClient';
|
|
5
|
+
|
|
6
|
+
/*
|
|
7
|
+
* Session States cannot be set arbitarily.
|
|
8
|
+
* These are the possible new states based on the current state
|
|
9
|
+
* Check tech spec for details:
|
|
10
|
+
* https://ekoapp.atlassian.net/wiki/spaces/UP/pages/2082537485/ASC+Core+-+Session+Management+3.0#Session-State
|
|
11
|
+
*/
|
|
12
|
+
const sessisonStateTransitions: Record<Amity.SessionStates, Amity.SessionStates[]> = {
|
|
13
|
+
// notLoggedIn -> establishing
|
|
14
|
+
[Amity.SessionStates.NOT_LOGGED_IN]: [Amity.SessionStates.ESTABLISHING],
|
|
15
|
+
// terminated -> establishing
|
|
16
|
+
[Amity.SessionStates.TERMINATED]: [Amity.SessionStates.ESTABLISHING],
|
|
17
|
+
// establishing -> notLoggedIn, established
|
|
18
|
+
[Amity.SessionStates.ESTABLISHING]: [
|
|
19
|
+
Amity.SessionStates.NOT_LOGGED_IN,
|
|
20
|
+
Amity.SessionStates.ESTABLISHED,
|
|
21
|
+
],
|
|
22
|
+
/*
|
|
23
|
+
* established -> notLoggedIn, terminated, tokenExpired, establishing (for
|
|
24
|
+
* cases when logging in same user)
|
|
25
|
+
*/
|
|
26
|
+
[Amity.SessionStates.ESTABLISHED]: [
|
|
27
|
+
Amity.SessionStates.NOT_LOGGED_IN,
|
|
28
|
+
Amity.SessionStates.TERMINATED,
|
|
29
|
+
Amity.SessionStates.TOKEN_EXPIRED,
|
|
30
|
+
Amity.SessionStates.ESTABLISHING,
|
|
31
|
+
],
|
|
32
|
+
// tokenExpired -> establishing
|
|
33
|
+
[Amity.SessionStates.TOKEN_EXPIRED]: [Amity.SessionStates.ESTABLISHING],
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const isValidStateChange = (
|
|
37
|
+
prevState: Amity.SessionStates,
|
|
38
|
+
nextState: Amity.SessionStates,
|
|
39
|
+
): boolean => {
|
|
40
|
+
return sessisonStateTransitions[prevState].includes(nextState);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Checks if a {@link Amity.Client} instance is connected to ASC servers
|
|
45
|
+
*
|
|
46
|
+
*
|
|
47
|
+
* @param state the new session state
|
|
48
|
+
* @returns a success boolean if connected
|
|
49
|
+
*
|
|
50
|
+
* @category private
|
|
51
|
+
*/
|
|
52
|
+
export const setSessionState = (state: Amity.SessionStates): boolean => {
|
|
53
|
+
const client = getActiveClient();
|
|
54
|
+
|
|
55
|
+
client.log('client/api/setSessionState', state);
|
|
56
|
+
|
|
57
|
+
const { sessionState: prevState } = client;
|
|
58
|
+
|
|
59
|
+
if (prevState === state) return false;
|
|
60
|
+
|
|
61
|
+
// check if transition is valid
|
|
62
|
+
if (!isValidStateChange(prevState, state)) {
|
|
63
|
+
throw new ASCError(
|
|
64
|
+
`Session state cannot change from ${prevState} to ${state}`,
|
|
65
|
+
Amity.ClientError.UNKNOWN_ERROR,
|
|
66
|
+
Amity.ErrorLevel.ERROR,
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
client.sessionState = state;
|
|
71
|
+
|
|
72
|
+
fireEvent('sessionStateChange', state);
|
|
73
|
+
|
|
74
|
+
return true;
|
|
75
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { disconnectClient } from './disconnectClient';
|
|
2
|
+
import { setSessionState } from './setSessionState';
|
|
3
|
+
import { getActiveClient } from './activeClient';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Terminates {@link Amity.Client} instance
|
|
7
|
+
*
|
|
8
|
+
*
|
|
9
|
+
*
|
|
10
|
+
* @category private
|
|
11
|
+
*/
|
|
12
|
+
export const terminateClient = () => {
|
|
13
|
+
const client = getActiveClient();
|
|
14
|
+
|
|
15
|
+
setSessionState(Amity.SessionStates.TERMINATED);
|
|
16
|
+
|
|
17
|
+
client.sessionHandler = undefined;
|
|
18
|
+
|
|
19
|
+
disconnectClient();
|
|
20
|
+
};
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { client, connectClient, disconnectClient } from '~/utils/tests';
|
|
2
|
+
import { ACCESS_TOKEN_WATCHER_INTERVAL } from '~/utils/constants';
|
|
3
|
+
|
|
4
|
+
import { accessTokenExpiryWatcher, isAboutToExpire, isExpired } from '../accessTokenExpiryWatcher';
|
|
5
|
+
|
|
6
|
+
import { onTokenExpired } from '~/client/events/onTokenExpired';
|
|
7
|
+
|
|
8
|
+
describe('accessTokenExpiryWatcher', () => {
|
|
9
|
+
beforeAll(async () => {
|
|
10
|
+
await connectClient();
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
afterAll(async () => {
|
|
14
|
+
await disconnectClient();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const expiresAt = new Date().toISOString();
|
|
18
|
+
const issuedAt = new Date().toISOString();
|
|
19
|
+
|
|
20
|
+
test('it should fire event when session expires', async () => {
|
|
21
|
+
const sessionHandler: Amity.SessionHandler = {
|
|
22
|
+
sessionWillRenewAccessToken(_) {
|
|
23
|
+
// do nothing
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
jest.useFakeTimers();
|
|
28
|
+
const callback = jest.fn();
|
|
29
|
+
const expected = Amity.SessionStates.TOKEN_EXPIRED;
|
|
30
|
+
|
|
31
|
+
const unsub = onTokenExpired(callback);
|
|
32
|
+
const stopWatcher = accessTokenExpiryWatcher(expiresAt, issuedAt, sessionHandler!);
|
|
33
|
+
|
|
34
|
+
jest.advanceTimersByTime(ACCESS_TOKEN_WATCHER_INTERVAL + 1);
|
|
35
|
+
|
|
36
|
+
expect(callback).toBeCalledWith(expected);
|
|
37
|
+
|
|
38
|
+
unsub();
|
|
39
|
+
stopWatcher();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test('it should renew token if session is about to expire', async () => {
|
|
43
|
+
jest.useFakeTimers();
|
|
44
|
+
const callback = jest.fn();
|
|
45
|
+
|
|
46
|
+
const sessionHandler = { sessionWillRenewAccessToken: callback };
|
|
47
|
+
client.sessionHandler = sessionHandler;
|
|
48
|
+
|
|
49
|
+
const stopWatcher = accessTokenExpiryWatcher(expiresAt, issuedAt, sessionHandler);
|
|
50
|
+
|
|
51
|
+
const oldIssuedAtTime = new Date();
|
|
52
|
+
const aboutToExpireTime = new Date();
|
|
53
|
+
|
|
54
|
+
aboutToExpireTime.setMinutes(aboutToExpireTime.getMinutes() + 30);
|
|
55
|
+
oldIssuedAtTime.setDate(oldIssuedAtTime.getDate() - 1);
|
|
56
|
+
|
|
57
|
+
aboutToExpireTime.setHours(aboutToExpireTime.getHours() + 1);
|
|
58
|
+
|
|
59
|
+
if (client.token) {
|
|
60
|
+
client.token.expiresAt = aboutToExpireTime.toISOString();
|
|
61
|
+
client.token.issuedAt = oldIssuedAtTime.toISOString();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
jest.advanceTimersByTime(ACCESS_TOKEN_WATCHER_INTERVAL + 1);
|
|
65
|
+
stopWatcher();
|
|
66
|
+
|
|
67
|
+
expect(callback).toHaveBeenCalled();
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test('it should renew token if session has expired', async () => {
|
|
71
|
+
jest.useFakeTimers();
|
|
72
|
+
const callback = jest.fn();
|
|
73
|
+
|
|
74
|
+
const sessionHandler = { sessionWillRenewAccessToken: callback };
|
|
75
|
+
client.sessionHandler = sessionHandler;
|
|
76
|
+
|
|
77
|
+
const stopWatcher = accessTokenExpiryWatcher(expiresAt, issuedAt, sessionHandler);
|
|
78
|
+
if (client.token) client.token.expiresAt = new Date().toISOString();
|
|
79
|
+
|
|
80
|
+
jest.advanceTimersByTime(ACCESS_TOKEN_WATCHER_INTERVAL + 1);
|
|
81
|
+
|
|
82
|
+
expect(callback).toHaveBeenCalled();
|
|
83
|
+
|
|
84
|
+
stopWatcher();
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
describe('accessTokenExpiryWatcher > aboutToExpire', () => {
|
|
89
|
+
const expiresAt = new Date().toISOString();
|
|
90
|
+
const issuedAt = new Date().toISOString();
|
|
91
|
+
const oldIssuedAtTime = new Date();
|
|
92
|
+
const aboutToExpireTime = new Date();
|
|
93
|
+
|
|
94
|
+
test('it should return true if about to expire', () => {
|
|
95
|
+
oldIssuedAtTime.setDate(oldIssuedAtTime.getDate() - 1);
|
|
96
|
+
|
|
97
|
+
aboutToExpireTime.setHours(aboutToExpireTime.getHours() + 1);
|
|
98
|
+
|
|
99
|
+
expect(
|
|
100
|
+
isAboutToExpire({
|
|
101
|
+
expiresAt: aboutToExpireTime.toISOString(),
|
|
102
|
+
issuedAt: oldIssuedAtTime.toISOString(),
|
|
103
|
+
}),
|
|
104
|
+
).toBe(true);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test('it should return false if token expired', () => {
|
|
108
|
+
expect(isAboutToExpire({ expiresAt, issuedAt })).toBe(false);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
test('it should return false if not about to expire', () => {
|
|
112
|
+
oldIssuedAtTime.setDate(oldIssuedAtTime.getDate() - 10);
|
|
113
|
+
|
|
114
|
+
expect(isAboutToExpire({ expiresAt, issuedAt })).toBe(false);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
describe('accessTokenExpiryWatcher > isExpired', () => {
|
|
119
|
+
let expiresAt = new Date().toISOString();
|
|
120
|
+
|
|
121
|
+
test('it should return true if token expired', () => {
|
|
122
|
+
expect(isExpired(expiresAt)).toBe(true);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test('it should return false if token not about expired', () => {
|
|
126
|
+
const laterDate = new Date();
|
|
127
|
+
laterDate.setMonth(laterDate.getMonth() + 1);
|
|
128
|
+
expiresAt = laterDate.toISOString();
|
|
129
|
+
|
|
130
|
+
expect(isExpired(expiresAt)).toBe(false);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { ASCApiError } from '~/core/errors';
|
|
2
|
+
import { sessionResponse, user11, disconnectClient } from '~/utils/tests';
|
|
3
|
+
import { connectClient, createClient } from '..';
|
|
4
|
+
import { setActiveClient } from '../activeClient';
|
|
5
|
+
|
|
6
|
+
let client: Amity.Client;
|
|
7
|
+
|
|
8
|
+
const sessionHandler: Amity.SessionHandler = {
|
|
9
|
+
sessionWillRenewAccessToken(_) {
|
|
10
|
+
// do nothing
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const onConnect = () =>
|
|
15
|
+
setTimeout(() => {
|
|
16
|
+
const CONNECT_PACKET = { type: 0, nsp: client.ws.nsp };
|
|
17
|
+
|
|
18
|
+
client.ws.emit('connect');
|
|
19
|
+
|
|
20
|
+
// simulate a connection ack packet from server
|
|
21
|
+
client.ws.io.emit('packet', CONNECT_PACKET);
|
|
22
|
+
}, 50);
|
|
23
|
+
|
|
24
|
+
describe('connectClient', () => {
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
client = createClient('key', 'sg');
|
|
27
|
+
client.mqtt.connect = jest.fn();
|
|
28
|
+
client.mqtt.subscribe = jest.fn();
|
|
29
|
+
client.http.post = jest.fn().mockResolvedValueOnce(sessionResponse);
|
|
30
|
+
|
|
31
|
+
setActiveClient(client);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
afterEach(async () => {
|
|
35
|
+
if (client.sessionState === Amity.SessionStates.ESTABLISHED) await disconnectClient();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test('it should connect client', async () => {
|
|
39
|
+
onConnect().unref();
|
|
40
|
+
|
|
41
|
+
const recieved = await connectClient({ userId: user11.userId }, sessionHandler);
|
|
42
|
+
|
|
43
|
+
expect(recieved).toBe(true);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test('it should establish connection', async () => {
|
|
47
|
+
onConnect().unref();
|
|
48
|
+
|
|
49
|
+
await connectClient({ userId: user11.userId }, sessionHandler);
|
|
50
|
+
const { sessionState } = client;
|
|
51
|
+
|
|
52
|
+
expect(sessionState).toBe(Amity.SessionStates.ESTABLISHED);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test('it should have session state establishing while connecting client', () => {
|
|
56
|
+
connectClient({ userId: user11.userId }, sessionHandler);
|
|
57
|
+
|
|
58
|
+
expect(client.sessionState).toBe(Amity.SessionStates.ESTABLISHING);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test('it should have session state notLoggedIn on failure', async () => {
|
|
62
|
+
client.http.post = jest
|
|
63
|
+
.fn()
|
|
64
|
+
.mockRejectedValue(
|
|
65
|
+
new ASCApiError('unauthorzed', Amity.ServerError.UNAUTHORIZED, Amity.ErrorLevel.FATAL),
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
await expect(connectClient({ userId: user11.userId }, sessionHandler)).rejects.toThrow(
|
|
69
|
+
'unauthorzed',
|
|
70
|
+
);
|
|
71
|
+
expect(client.sessionState).toBe(Amity.SessionStates.NOT_LOGGED_IN);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test('it should terminate session on ban', async () => {
|
|
75
|
+
onConnect().unref();
|
|
76
|
+
|
|
77
|
+
await connectClient({ userId: user11.userId }, sessionHandler);
|
|
78
|
+
|
|
79
|
+
// ban user
|
|
80
|
+
client.emitter.emit('user.didGlobalBan', {} as Amity.UserPayload);
|
|
81
|
+
|
|
82
|
+
expect(client.sessionState).toBe(Amity.SessionStates.TERMINATED);
|
|
83
|
+
});
|
|
84
|
+
});
|