@amityco/ts-sdk 7.8.3-1fdb2885.0 → 7.8.3-b5109db.0
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/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/@types/domains/client.d.ts +2 -0
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/@types/domains/client.d.ts.map +1 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/@types/domains/client.js.map +1 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/client/api/createClient.d.ts.map +1 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/client/api/createClient.js +2 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/client/api/createClient.js.map +1 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/client/api/isConnected.d.ts.map +1 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/client/api/isConnected.js +5 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/client/api/isConnected.js.map +1 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/client/api/login.d.ts.map +1 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/client/api/login.js +6 -0
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/client/api/login.js.map +1 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/client/api/logout.d.ts.map +1 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/client/api/logout.js +9 -2
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/client/api/logout.js.map +1 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/client/api/resumeSession.d.ts.map +1 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/client/api/resumeSession.js +13 -0
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/client/api/resumeSession.js.map +1 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/client/api/tests/createClient.test.js +4 -0
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/client/api/tests/createClient.test.js.map +1 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/client/api/tests/login.test.js +7 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/client/api/tests/login.test.js.map +1 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/client/api/tests/logout.test.js +8 -0
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/client/api/tests/logout.test.js.map +1 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/client/api/tests/resumeSession.test.js +8 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/client/api/tests/resumeSession.test.js.map +1 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/client/api/tests/terminateClient.test.js +3 -0
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/client/api/tests/terminateClient.test.js.map +1 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/client/utils/setClientToken.d.ts.map +1 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/client/utils/setClientToken.js +3 -0
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/client/utils/setClientToken.js.map +1 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/core/events.d.ts +11 -0
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/core/events.d.ts.map +1 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/core/events.js +17 -0
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/core/events.js.map +1 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/core/transports/index.d.ts +1 -0
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/core/transports/index.d.ts.map +1 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/core/transports/index.js +1 -0
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/core/transports/index.js.map +1 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/core/transports/ws.d.ts +27 -0
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/core/transports/ws.d.ts.map +1 -0
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/core/transports/ws.js +53 -0
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/core/transports/ws.js.map +1 -0
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/utils/tests/client.d.ts.map +1 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/utils/tests/client.js +6 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/dist/utils/tests/client.js.map +1 -1
- package/.rollup.cache/home/runner/work/AmityTypescriptSDK/AmityTypescriptSDK/packages/sdk/tsconfig.tsbuildinfo +1 -1
- package/dist/@types/domains/client.d.ts +2 -0
- package/dist/@types/domains/client.d.ts.map +1 -1
- package/dist/client/api/createClient.d.ts.map +1 -1
- package/dist/client/api/isConnected.d.ts.map +1 -1
- package/dist/client/api/login.d.ts.map +1 -1
- package/dist/client/api/logout.d.ts.map +1 -1
- package/dist/client/api/resumeSession.d.ts.map +1 -1
- package/dist/client/utils/setClientToken.d.ts.map +1 -1
- package/dist/core/events.d.ts +11 -0
- package/dist/core/events.d.ts.map +1 -1
- package/dist/core/transports/index.d.ts +1 -0
- package/dist/core/transports/index.d.ts.map +1 -1
- package/dist/core/transports/ws.d.ts +27 -0
- package/dist/core/transports/ws.d.ts.map +1 -0
- package/dist/index.cjs.js +87 -3
- package/dist/index.esm.js +86 -3
- package/dist/index.umd.js +4 -3
- package/dist/utils/tests/client.d.ts.map +1 -1
- package/package.json +4 -2
- package/src/@types/domains/client.ts +1 -0
- package/src/client/api/createClient.ts +1 -0
- package/src/client/api/isConnected.ts +8 -1
- package/src/client/api/login.ts +6 -0
- package/src/client/api/logout.ts +8 -1
- package/src/client/api/resumeSession.ts +12 -0
- package/src/client/api/tests/createClient.test.ts +6 -0
- package/src/client/api/tests/login.test.ts +51 -42
- package/src/client/api/tests/logout.test.ts +12 -1
- package/src/client/api/tests/resumeSession.test.ts +111 -102
- package/src/client/api/tests/terminateClient.test.ts +6 -0
- package/src/client/utils/setClientToken.ts +3 -0
- package/src/core/events.ts +18 -0
- package/src/core/transports/index.ts +1 -0
- package/src/core/transports/ws.ts +60 -0
- package/src/utils/tests/client.ts +7 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/utils/tests/client.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,UAAU,YAAS,CAAC;AAYjC,eAAO,MAAM,MAAM,cAA4B,CAAC;AAMhD,eAAO,MAAM,aAAa,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/utils/tests/client.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,UAAU,YAAS,CAAC;AAYjC,eAAO,MAAM,MAAM,cAA4B,CAAC;AAMhD,eAAO,MAAM,aAAa,qBAuBzB,CAAC;AAEF,eAAO,MAAM,gBAAgB,qBAE5B,CAAC;;AAEF,wBAAkB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@amityco/ts-sdk",
|
|
3
|
-
"version": "7.8.3-
|
|
3
|
+
"version": "7.8.3-b5109db.0",
|
|
4
4
|
"license": "CC-BY-ND-4.0",
|
|
5
5
|
"author": "amity.co <developers@amity.co> (https://amity.co)",
|
|
6
6
|
"description": "Amity Social Cloud Typescript SDK",
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"@types/jest": "^27.5.1",
|
|
44
44
|
"@types/node": "^18.6.4",
|
|
45
45
|
"@types/object-hash": "^3.0.6",
|
|
46
|
+
"@types/socket.io-client": "^1.4.34",
|
|
46
47
|
"chalk": "^4.1.2",
|
|
47
48
|
"concurrently": "^6.1.0",
|
|
48
49
|
"form-data": "^4.0.0",
|
|
@@ -66,6 +67,7 @@
|
|
|
66
67
|
"mitt": "^3.0.0",
|
|
67
68
|
"mqtt": "^4.3.7",
|
|
68
69
|
"object-hash": "^3.0.0",
|
|
69
|
-
"react-native-uuid": "^2.0.1"
|
|
70
|
+
"react-native-uuid": "^2.0.1",
|
|
71
|
+
"socket.io-client": "2.2.0"
|
|
70
72
|
}
|
|
71
73
|
}
|
|
@@ -16,5 +16,12 @@ export const isConnected = (): boolean => {
|
|
|
16
16
|
const client = getActiveClient();
|
|
17
17
|
client.log('client/api/isConnected', client);
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
// if client is connected to ws, it means client is connected. If ws is undefined, it means ws is not used.
|
|
20
|
+
const isWsConnected = (client.ws && client.ws.connected) || !!client.ws;
|
|
21
|
+
|
|
22
|
+
return !!(
|
|
23
|
+
client.userId &&
|
|
24
|
+
String(client.http.defaults.headers.common?.Authorization)?.length &&
|
|
25
|
+
isWsConnected
|
|
26
|
+
);
|
|
20
27
|
};
|
package/src/client/api/login.ts
CHANGED
|
@@ -122,6 +122,12 @@ export const login = async (
|
|
|
122
122
|
return false;
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
+
// FIXME: events are duplicated if connectClient is called few times without disconnectClient
|
|
126
|
+
// wire websocket events to our event emitter
|
|
127
|
+
proxyWebsocketEvents(client.ws, client.emitter);
|
|
128
|
+
|
|
129
|
+
client.ws?.open();
|
|
130
|
+
|
|
125
131
|
client.userId = user.userId;
|
|
126
132
|
|
|
127
133
|
client.sessionHandler = sessionHandler;
|
package/src/client/api/logout.ts
CHANGED
|
@@ -26,6 +26,10 @@ export const logout = async (): Promise<boolean> => {
|
|
|
26
26
|
client.mqtt.disconnect();
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
if (client.ws && client.ws.connected) {
|
|
30
|
+
client.ws.disconnect();
|
|
31
|
+
}
|
|
32
|
+
|
|
29
33
|
/*
|
|
30
34
|
* for cases when session state is terminated (example on ban) or token expired,
|
|
31
35
|
* the terminating block will set session state to terminated or for the or
|
|
@@ -42,7 +46,8 @@ export const logout = async (): Promise<boolean> => {
|
|
|
42
46
|
setSessionState(Amity.SessionStates.NOT_LOGGED_IN);
|
|
43
47
|
|
|
44
48
|
client.emitter.all.clear();
|
|
45
|
-
|
|
49
|
+
// FIXME: it removes listener in ws.ts, it breaks global ban event
|
|
50
|
+
client.ws?.removeAllListeners();
|
|
46
51
|
client.mqtt?.removeAllListeners();
|
|
47
52
|
client.userId = undefined;
|
|
48
53
|
client.token = undefined;
|
|
@@ -54,6 +59,8 @@ export const logout = async (): Promise<boolean> => {
|
|
|
54
59
|
isUserDeleted: false,
|
|
55
60
|
};
|
|
56
61
|
|
|
62
|
+
if (client.ws) client.ws.io.opts.query = { token: '' };
|
|
63
|
+
|
|
57
64
|
if (typeof document !== 'undefined') {
|
|
58
65
|
document.cookie = '_ascSession=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
|
|
59
66
|
}
|
|
@@ -97,6 +97,9 @@ const validateAccessToken = async ({ token, userId }: Params) => {
|
|
|
97
97
|
isUserDeleted: false,
|
|
98
98
|
};
|
|
99
99
|
|
|
100
|
+
// manually setup the token for ws transport
|
|
101
|
+
if (client.ws) client.ws.io.opts.query = { token: token.accessToken };
|
|
102
|
+
|
|
100
103
|
client.token = token;
|
|
101
104
|
|
|
102
105
|
setSessionState(Amity.SessionStates.ESTABLISHED);
|
|
@@ -149,6 +152,9 @@ export const resumeSession = async (
|
|
|
149
152
|
if (client.mqtt && client.mqtt.connected) {
|
|
150
153
|
client.mqtt.disconnect();
|
|
151
154
|
}
|
|
155
|
+
if (client.ws && client.ws.connected) {
|
|
156
|
+
client.ws.disconnect();
|
|
157
|
+
}
|
|
152
158
|
|
|
153
159
|
// Clear existing subscriptions
|
|
154
160
|
subscriptions.forEach(fn => fn());
|
|
@@ -184,6 +190,12 @@ export const resumeSession = async (
|
|
|
184
190
|
return false;
|
|
185
191
|
}
|
|
186
192
|
|
|
193
|
+
// FIXME: events are duplicated if connectClient is called few times without disconnectClient
|
|
194
|
+
// wire websocket events to our event emitter
|
|
195
|
+
proxyWebsocketEvents(client.ws, client.emitter);
|
|
196
|
+
|
|
197
|
+
client.ws?.open();
|
|
198
|
+
|
|
187
199
|
client.userId = user.userId;
|
|
188
200
|
|
|
189
201
|
client.sessionHandler = sessionHandler;
|
|
@@ -13,6 +13,12 @@ describe('createClient', () => {
|
|
|
13
13
|
expect(client.http).toBeDefined();
|
|
14
14
|
});
|
|
15
15
|
|
|
16
|
+
test('it should define ws transport', () => {
|
|
17
|
+
const client = createClient('test-api-key');
|
|
18
|
+
|
|
19
|
+
expect(client.ws).toBeDefined();
|
|
20
|
+
});
|
|
21
|
+
|
|
16
22
|
test('it should define mqtt transport', () => {
|
|
17
23
|
const client = createClient('test-api-key');
|
|
18
24
|
|
|
@@ -12,62 +12,71 @@ const sessionHandler: Amity.SessionHandler = {
|
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
const onConnect = () =>
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
client = createClient('key', 'sg');
|
|
18
|
-
client.mqtt.connect = jest.fn();
|
|
19
|
-
client.mqtt.subscribe = jest.fn();
|
|
20
|
-
client.http.post = jest.fn().mockResolvedValueOnce(sessionResponse);
|
|
15
|
+
setTimeout(() => {
|
|
16
|
+
const CONNECT_PACKET = { type: 0, nsp: client.ws.nsp };
|
|
21
17
|
|
|
22
|
-
|
|
23
|
-
});
|
|
18
|
+
client.ws.emit('connect');
|
|
24
19
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
// simulate a connection ack packet from server
|
|
21
|
+
client.ws.io.emit('packet', CONNECT_PACKET);
|
|
22
|
+
}, 50);
|
|
28
23
|
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
describe('login', () => {
|
|
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);
|
|
31
30
|
|
|
32
|
-
|
|
31
|
+
setActiveClient(client);
|
|
32
|
+
});
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
afterEach(async () => {
|
|
35
|
+
if (client.sessionState === Amity.SessionStates.ESTABLISHED) await disconnectClient();
|
|
36
|
+
});
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
test('it should connect client', async () => {
|
|
39
|
+
onConnect().unref();
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
const { sessionState } = client;
|
|
41
|
+
const recieved = await login({ userId: user11.userId }, sessionHandler);
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
expect(recieved).toBe(true);
|
|
44
|
+
});
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
test('it should establish connection', async () => {
|
|
47
|
+
onConnect().unref();
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
}
|
|
49
|
+
await login({ userId: user11.userId }, sessionHandler);
|
|
50
|
+
const { sessionState } = client;
|
|
51
|
+
|
|
52
|
+
expect(sessionState).toBe(Amity.SessionStates.ESTABLISHED);
|
|
53
|
+
});
|
|
51
54
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
.fn()
|
|
55
|
-
.mockRejectedValue(
|
|
56
|
-
new ASCApiError('unauthorzed', Amity.ServerError.UNAUTHORIZED, Amity.ErrorLevel.FATAL),
|
|
57
|
-
);
|
|
55
|
+
test('it should have session state establishing while connecting client', () => {
|
|
56
|
+
login({ userId: user11.userId }, sessionHandler);
|
|
58
57
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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(login({ userId: user11.userId }, sessionHandler)).rejects.toThrow('unauthorzed');
|
|
69
|
+
expect(client.sessionState).toBe(Amity.SessionStates.NOT_LOGGED_IN);
|
|
70
|
+
});
|
|
62
71
|
|
|
63
|
-
|
|
64
|
-
|
|
72
|
+
test('it should terminate session on ban', async () => {
|
|
73
|
+
onConnect().unref();
|
|
65
74
|
|
|
66
|
-
|
|
75
|
+
await login({ userId: user11.userId }, sessionHandler);
|
|
67
76
|
|
|
68
|
-
|
|
69
|
-
|
|
77
|
+
// ban user
|
|
78
|
+
client.emitter.emit('user.didGlobalBan', {} as Amity.UserPayload);
|
|
70
79
|
|
|
71
|
-
|
|
72
|
-
});
|
|
80
|
+
expect(client.sessionState).toBe(Amity.SessionStates.TERMINATED);
|
|
73
81
|
});
|
|
82
|
+
});
|
|
@@ -3,18 +3,23 @@ import { client, connectClient, message11 as message } from '~/utils/tests';
|
|
|
3
3
|
|
|
4
4
|
import { logout } from '..';
|
|
5
5
|
|
|
6
|
+
const disconnect = () => setTimeout(() => client.ws.emit('disconnect'), 500);
|
|
7
|
+
|
|
6
8
|
describe('logout', () => {
|
|
7
9
|
beforeEach(async () => {
|
|
8
10
|
await connectClient();
|
|
9
11
|
});
|
|
10
12
|
|
|
11
13
|
test('it should disconnect client', async () => {
|
|
14
|
+
disconnect().unref();
|
|
15
|
+
|
|
12
16
|
const recieved = await logout();
|
|
13
17
|
|
|
14
18
|
expect(recieved).toBe(true);
|
|
15
19
|
});
|
|
16
20
|
|
|
17
21
|
test('it should set sesion state to notLoggedIn after disconnect', async () => {
|
|
22
|
+
disconnect().unref();
|
|
18
23
|
await logout();
|
|
19
24
|
|
|
20
25
|
expect(client.sessionState).toBe(Amity.SessionStates.NOT_LOGGED_IN);
|
|
@@ -22,6 +27,7 @@ describe('logout', () => {
|
|
|
22
27
|
|
|
23
28
|
test('it should not update sesion state if session state terminated', async () => {
|
|
24
29
|
client.sessionState = Amity.SessionStates.TERMINATED;
|
|
30
|
+
disconnect().unref();
|
|
25
31
|
|
|
26
32
|
await logout();
|
|
27
33
|
|
|
@@ -29,6 +35,8 @@ describe('logout', () => {
|
|
|
29
35
|
});
|
|
30
36
|
|
|
31
37
|
test('it should clear userId and accessToken on disconnect', async () => {
|
|
38
|
+
disconnect().unref();
|
|
39
|
+
|
|
32
40
|
await logout();
|
|
33
41
|
|
|
34
42
|
expect(client.userId).toBeUndefined();
|
|
@@ -36,12 +44,15 @@ describe('logout', () => {
|
|
|
36
44
|
});
|
|
37
45
|
|
|
38
46
|
test('it should clear auth header on disconnect', async () => {
|
|
47
|
+
disconnect().unref();
|
|
48
|
+
|
|
39
49
|
await logout();
|
|
40
50
|
|
|
41
51
|
expect(client.http.defaults.headers.common.Authorization).toBeFalsy();
|
|
42
52
|
});
|
|
43
53
|
|
|
44
54
|
test('it should clear cache on disconnect', async () => {
|
|
55
|
+
disconnect().unref();
|
|
45
56
|
enableCache();
|
|
46
57
|
|
|
47
58
|
const cacheKey = ['message', 'get', message.messageId];
|
|
@@ -54,7 +65,7 @@ describe('logout', () => {
|
|
|
54
65
|
|
|
55
66
|
test('it should not clear cache if tokenExpired', async () => {
|
|
56
67
|
client.sessionState = Amity.SessionStates.TOKEN_EXPIRED;
|
|
57
|
-
|
|
68
|
+
disconnect().unref();
|
|
58
69
|
enableCache();
|
|
59
70
|
|
|
60
71
|
const cacheKey = ['message', 'get', message.messageId];
|
|
@@ -24,141 +24,150 @@ const mockUserResponse = {
|
|
|
24
24
|
};
|
|
25
25
|
|
|
26
26
|
const onConnect = () =>
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
client = createClient('key', 'sg');
|
|
30
|
-
client.mqtt?.connect && (client.mqtt.connect = jest.fn());
|
|
31
|
-
client.mqtt?.subscribe && (client.mqtt.subscribe = jest.fn());
|
|
32
|
-
client.http.get = jest.fn().mockResolvedValueOnce(mockUserResponse);
|
|
33
|
-
|
|
34
|
-
setActiveClient(client);
|
|
35
|
-
});
|
|
27
|
+
setTimeout(() => {
|
|
28
|
+
const CONNECT_PACKET = { type: 0, nsp: client.ws?.nsp };
|
|
36
29
|
|
|
37
|
-
|
|
38
|
-
if (client.sessionState === Amity.SessionStates.ESTABLISHED) await disconnectClient();
|
|
39
|
-
});
|
|
30
|
+
client.ws?.emit('connect');
|
|
40
31
|
|
|
41
|
-
|
|
42
|
-
|
|
32
|
+
// simulate a connection ack packet from server
|
|
33
|
+
client.ws?.io.emit('packet', CONNECT_PACKET);
|
|
34
|
+
}, 50);
|
|
43
35
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
36
|
+
describe('resumeSession', () => {
|
|
37
|
+
beforeEach(() => {
|
|
38
|
+
client = createClient('key', 'sg');
|
|
39
|
+
client.mqtt?.connect && (client.mqtt.connect = jest.fn());
|
|
40
|
+
client.mqtt?.subscribe && (client.mqtt.subscribe = jest.fn());
|
|
41
|
+
client.http.get = jest.fn().mockResolvedValueOnce(mockUserResponse);
|
|
48
42
|
|
|
49
|
-
|
|
50
|
-
|
|
43
|
+
setActiveClient(client);
|
|
44
|
+
});
|
|
51
45
|
|
|
52
|
-
|
|
53
|
-
|
|
46
|
+
afterEach(async () => {
|
|
47
|
+
if (client.sessionState === Amity.SessionStates.ESTABLISHED) await disconnectClient();
|
|
48
|
+
});
|
|
54
49
|
|
|
55
|
-
|
|
56
|
-
|
|
50
|
+
test('it should connect client with access token', async () => {
|
|
51
|
+
onConnect().unref();
|
|
57
52
|
|
|
58
|
-
|
|
59
|
-
|
|
53
|
+
const received = await resumeSession(
|
|
54
|
+
{ userId: user11.userId, token: mockToken },
|
|
55
|
+
sessionHandler,
|
|
56
|
+
);
|
|
60
57
|
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
expect(received).toBe(true);
|
|
59
|
+
});
|
|
63
60
|
|
|
64
|
-
|
|
65
|
-
|
|
61
|
+
test('it should establish connection', async () => {
|
|
62
|
+
onConnect().unref();
|
|
66
63
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
.fn()
|
|
70
|
-
.mockRejectedValue(
|
|
71
|
-
new ASCApiError('unauthorized', Amity.ServerError.UNAUTHORIZED, Amity.ErrorLevel.FATAL),
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
await expect(
|
|
75
|
-
resumeSession({ userId: user11.userId, token: mockToken }, sessionHandler),
|
|
76
|
-
).rejects.toThrow('unauthorized');
|
|
77
|
-
expect(client.sessionState).toBe(Amity.SessionStates.NOT_LOGGED_IN);
|
|
78
|
-
});
|
|
64
|
+
await resumeSession({ userId: user11.userId, token: mockToken }, sessionHandler);
|
|
65
|
+
const { sessionState } = client;
|
|
79
66
|
|
|
80
|
-
|
|
81
|
-
|
|
67
|
+
expect(sessionState).toBe(Amity.SessionStates.ESTABLISHED);
|
|
68
|
+
});
|
|
82
69
|
|
|
83
|
-
|
|
70
|
+
test('it should have session state establishing while connecting client', () => {
|
|
71
|
+
resumeSession({ userId: user11.userId, token: mockToken }, sessionHandler);
|
|
84
72
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
73
|
+
expect(client.sessionState).toBe(Amity.SessionStates.ESTABLISHING);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test('it should have session state notLoggedIn on failure', async () => {
|
|
77
|
+
client.http.get = jest
|
|
78
|
+
.fn()
|
|
79
|
+
.mockRejectedValue(
|
|
80
|
+
new ASCApiError('unauthorized', Amity.ServerError.UNAUTHORIZED, Amity.ErrorLevel.FATAL),
|
|
90
81
|
);
|
|
91
|
-
});
|
|
92
82
|
|
|
93
|
-
|
|
94
|
-
|
|
83
|
+
await expect(
|
|
84
|
+
resumeSession({ userId: user11.userId, token: mockToken }, sessionHandler),
|
|
85
|
+
).rejects.toThrow('unauthorized');
|
|
86
|
+
expect(client.sessionState).toBe(Amity.SessionStates.NOT_LOGGED_IN);
|
|
87
|
+
});
|
|
95
88
|
|
|
96
|
-
|
|
89
|
+
test('it should set authorization header with token', async () => {
|
|
90
|
+
onConnect().unref();
|
|
97
91
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
92
|
+
await resumeSession({ userId: user11.userId, token: mockToken }, sessionHandler);
|
|
93
|
+
|
|
94
|
+
expect(client.http.defaults.headers.common.Authorization).toBe(
|
|
95
|
+
`Bearer ${mockToken.accessToken}`,
|
|
96
|
+
);
|
|
97
|
+
expect(client.upload.defaults.headers.common.Authorization).toBe(
|
|
98
|
+
`Bearer ${mockToken.accessToken}`,
|
|
99
|
+
);
|
|
100
|
+
});
|
|
105
101
|
|
|
106
|
-
|
|
107
|
-
|
|
102
|
+
test('it should set token metadata', async () => {
|
|
103
|
+
onConnect().unref();
|
|
108
104
|
|
|
109
|
-
|
|
105
|
+
await resumeSession({ userId: user11.userId, token: mockToken }, sessionHandler);
|
|
110
106
|
|
|
111
|
-
|
|
107
|
+
expect(client.token).toEqual(mockToken);
|
|
108
|
+
expect(client.http.defaults.metadata).toEqual({
|
|
109
|
+
tokenExpiry: mockToken.expiresAt,
|
|
110
|
+
isGlobalBanned: false,
|
|
111
|
+
isUserDeleted: false,
|
|
112
112
|
});
|
|
113
|
+
});
|
|
113
114
|
|
|
114
|
-
|
|
115
|
-
|
|
115
|
+
test('it should call user endpoint to validate token', async () => {
|
|
116
|
+
onConnect().unref();
|
|
116
117
|
|
|
117
|
-
|
|
118
|
+
await resumeSession({ userId: user11.userId, token: mockToken }, sessionHandler);
|
|
118
119
|
|
|
119
|
-
|
|
120
|
-
|
|
120
|
+
expect(client.http.get).toHaveBeenCalledWith(`/api/v3/users/${user11.userId}`);
|
|
121
|
+
});
|
|
121
122
|
|
|
122
|
-
|
|
123
|
-
|
|
123
|
+
test('it should terminate session on ban', async () => {
|
|
124
|
+
onConnect().unref();
|
|
124
125
|
|
|
125
|
-
|
|
126
|
-
onConnect().unref();
|
|
126
|
+
await resumeSession({ userId: user11.userId, token: mockToken }, sessionHandler);
|
|
127
127
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
expect(client.sessionState).toBe(Amity.SessionStates.ESTABLISHED);
|
|
131
|
-
expect(client.userId).toBe(user11.userId);
|
|
128
|
+
// ban user
|
|
129
|
+
client.emitter.emit('user.didGlobalBan', {} as Amity.UserPayload);
|
|
132
130
|
|
|
133
|
-
|
|
134
|
-
|
|
131
|
+
expect(client.sessionState).toBe(Amity.SessionStates.TERMINATED);
|
|
132
|
+
});
|
|
135
133
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
await resumeSession({ userId: user11.userId, token: mockToken }, sessionHandler);
|
|
134
|
+
test('it should reset client state when user is already connected with same userId', async () => {
|
|
135
|
+
onConnect().unref();
|
|
139
136
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
137
|
+
// First connection
|
|
138
|
+
await resumeSession({ userId: user11.userId, token: mockToken }, sessionHandler);
|
|
139
|
+
expect(client.sessionState).toBe(Amity.SessionStates.ESTABLISHED);
|
|
140
|
+
expect(client.userId).toBe(user11.userId);
|
|
144
141
|
|
|
145
|
-
|
|
146
|
-
|
|
142
|
+
// Mock the HTTP call for second connection
|
|
143
|
+
client.http.get = jest.fn().mockResolvedValueOnce(mockUserResponse);
|
|
147
144
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
client.cache.data = { test: 'data' };
|
|
152
|
-
}
|
|
145
|
+
// Second connection with same userId should treat as token expiry (preserve cache)
|
|
146
|
+
onConnect().unref();
|
|
147
|
+
await resumeSession({ userId: user11.userId, token: mockToken }, sessionHandler);
|
|
153
148
|
|
|
154
|
-
|
|
155
|
-
|
|
149
|
+
// Verify that the client is properly reset and reconnected
|
|
150
|
+
expect(client.sessionState).toBe(Amity.SessionStates.ESTABLISHED);
|
|
151
|
+
expect(client.userId).toBe(user11.userId);
|
|
152
|
+
});
|
|
156
153
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
await resumeSession({ userId: user11.userId, token: mockToken }, sessionHandler);
|
|
154
|
+
test('it should preserve cache when resuming session with same userId', async () => {
|
|
155
|
+
onConnect().unref();
|
|
160
156
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
157
|
+
// First connection - set some cache data
|
|
158
|
+
await resumeSession({ userId: user11.userId, token: mockToken }, sessionHandler);
|
|
159
|
+
if (client.cache) {
|
|
160
|
+
client.cache.data = { test: 'data' };
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Mock the HTTP call for second connection
|
|
164
|
+
client.http.get = jest.fn().mockResolvedValueOnce(mockUserResponse);
|
|
165
|
+
|
|
166
|
+
// Second connection with same userId
|
|
167
|
+
onConnect().unref();
|
|
168
|
+
await resumeSession({ userId: user11.userId, token: mockToken }, sessionHandler);
|
|
169
|
+
|
|
170
|
+
// Cache should be preserved when same userId is used
|
|
171
|
+
expect(client.cache?.data).toEqual({ test: 'data' });
|
|
164
172
|
});
|
|
173
|
+
});
|
|
@@ -2,12 +2,16 @@ import { client, connectClient } from '~/utils/tests';
|
|
|
2
2
|
|
|
3
3
|
import { terminateClient } from '../terminateClient';
|
|
4
4
|
|
|
5
|
+
const disconnect = () => setTimeout(() => client.ws.emit('disconnect'), 500);
|
|
6
|
+
|
|
5
7
|
describe('terminateClient', () => {
|
|
6
8
|
beforeAll(async () => {
|
|
7
9
|
await connectClient();
|
|
8
10
|
});
|
|
9
11
|
|
|
10
12
|
test('it should terminate client session', async () => {
|
|
13
|
+
disconnect().unref();
|
|
14
|
+
|
|
11
15
|
const expected = Amity.SessionStates.TERMINATED;
|
|
12
16
|
|
|
13
17
|
terminateClient();
|
|
@@ -16,6 +20,8 @@ describe('terminateClient', () => {
|
|
|
16
20
|
});
|
|
17
21
|
|
|
18
22
|
test('it should clear sessionHandler', async () => {
|
|
23
|
+
disconnect().unref();
|
|
24
|
+
|
|
19
25
|
terminateClient();
|
|
20
26
|
|
|
21
27
|
expect(client.sessionHandler).toBeUndefined();
|
|
@@ -38,6 +38,9 @@ export const setClientToken = async (params: Parameters<typeof getToken>[0]) =>
|
|
|
38
38
|
isUserDeleted: false,
|
|
39
39
|
};
|
|
40
40
|
|
|
41
|
+
// manually setup the token for ws transport
|
|
42
|
+
if (client.ws) client.ws.io.opts.query = { token: accessToken };
|
|
43
|
+
|
|
41
44
|
client.token = { accessToken, issuedAt, expiresAt };
|
|
42
45
|
|
|
43
46
|
setSessionState(Amity.SessionStates.ESTABLISHED);
|
package/src/core/events.ts
CHANGED
|
@@ -43,6 +43,24 @@ export const createEventEmitter = () => {
|
|
|
43
43
|
return mitt<Amity.Events>();
|
|
44
44
|
};
|
|
45
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Wraps the websocket events into the client's event emitter for
|
|
48
|
+
* abstraction of transport.
|
|
49
|
+
*
|
|
50
|
+
* @param ws A websocket connection to listen from
|
|
51
|
+
* @param emitter An event emitter to wire the events to
|
|
52
|
+
*
|
|
53
|
+
* @category Transport
|
|
54
|
+
* @hidden
|
|
55
|
+
*/
|
|
56
|
+
export const proxyWebsocketEvents = (ws: Amity.Client['ws'], emitter: Amity.Client['emitter']) => {
|
|
57
|
+
WS_EVENTS.forEach(event => {
|
|
58
|
+
ws?.on(event, (param: Amity.Events[typeof event]) => {
|
|
59
|
+
emitter.emit(event, param);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
|
|
46
64
|
export const proxyMqttEvents = (
|
|
47
65
|
mqttClient: Amity.Client['mqtt'],
|
|
48
66
|
emitter: Amity.Client['emitter'],
|