@eleven-am/pondsocket 0.1.125 → 0.1.127
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/README.md +5 -15
- package/abstracts/abstractRequest.test.js +42 -0
- package/abstracts/abstractResponse.js +3 -0
- package/abstracts/middleware.test.js +70 -0
- package/channel/channel.js +22 -20
- package/channel/channel.test.js +415 -0
- package/channel/eventRequest.test.js +30 -0
- package/channel/eventResponse.js +9 -9
- package/channel/eventResponse.test.js +197 -0
- package/endpoint/endpoint.js +34 -40
- package/endpoint/endpoint.test.js +297 -0
- package/endpoint/response.js +7 -6
- package/index.d.ts +2 -0
- package/lobby/JoinRequest.test.js +40 -0
- package/lobby/JoinResponse.test.js +145 -0
- package/lobby/joinResponse.js +12 -10
- package/lobby/lobby.js +3 -3
- package/matcher/matcher.test.js +90 -0
- package/package.json +32 -13
- package/presence/presence.js +8 -8
- package/presence/presenceEngine.test.js +128 -0
- package/schema.js +13 -0
- package/server/pondSocket.js +5 -4
- package/types.d.ts +0 -496
- package/types.js +2 -0
- package/client/channel.js +0 -304
- package/client.d.ts +0 -5
- package/client.js +0 -107
- package/enums.js +0 -56
- package/express.d.ts +0 -3
- package/express.js +0 -17
- package/nest.d.ts +0 -19
- package/nest.js +0 -769
- package/node.d.ts +0 -3
- package/node.js +0 -30
- package/subjects/subject.js +0 -137
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createChannelEvent = exports.createChannelEngine = void 0;
|
|
4
|
+
const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
|
|
5
|
+
const channel_1 = require("./channel");
|
|
6
|
+
const channel_test_1 = require("./channel.test");
|
|
7
|
+
const eventResponse_1 = require("./eventResponse");
|
|
8
|
+
const createChannelEngine = () => {
|
|
9
|
+
const parentEngine = (0, channel_test_1.createParentEngine)();
|
|
10
|
+
return new channel_1.ChannelEngine('test', parentEngine);
|
|
11
|
+
};
|
|
12
|
+
exports.createChannelEngine = createChannelEngine;
|
|
13
|
+
const createChannelEvent = (name) => {
|
|
14
|
+
const responseEvent = {
|
|
15
|
+
event: 'event',
|
|
16
|
+
payload: {
|
|
17
|
+
payload: 'payload',
|
|
18
|
+
},
|
|
19
|
+
sender: 'sender',
|
|
20
|
+
action: pondsocket_common_1.ServerActions.BROADCAST,
|
|
21
|
+
recipients: ['recipient'],
|
|
22
|
+
channelName: name,
|
|
23
|
+
requestId: 'requestId',
|
|
24
|
+
};
|
|
25
|
+
return responseEvent;
|
|
26
|
+
};
|
|
27
|
+
exports.createChannelEvent = createChannelEvent;
|
|
28
|
+
const createChannelResponse = () => {
|
|
29
|
+
const channelEngine = (0, exports.createChannelEngine)();
|
|
30
|
+
const event = (0, exports.createChannelEvent)(channelEngine.name);
|
|
31
|
+
channelEngine.addUser(event.sender, { assign: 'assign' }, () => { });
|
|
32
|
+
channelEngine.addUser(event.recipients[0], { assign: 'assign' }, () => { });
|
|
33
|
+
const response = new eventResponse_1.EventResponse(event, channelEngine);
|
|
34
|
+
return {
|
|
35
|
+
channelEngine,
|
|
36
|
+
event,
|
|
37
|
+
response,
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
describe('ChannelResponse', () => {
|
|
41
|
+
it('should create a new ChannelResponse', () => {
|
|
42
|
+
const { response } = createChannelResponse();
|
|
43
|
+
expect(response).toBeDefined();
|
|
44
|
+
});
|
|
45
|
+
it('should accept the request', () => {
|
|
46
|
+
const { response, channelEngine } = createChannelResponse();
|
|
47
|
+
jest.spyOn(channelEngine, 'sendMessage');
|
|
48
|
+
response.accept();
|
|
49
|
+
expect(channelEngine.sendMessage).toHaveBeenCalledWith('requestId', 'sender', ['recipient'], pondsocket_common_1.ServerActions.BROADCAST, 'event', { payload: 'payload' });
|
|
50
|
+
});
|
|
51
|
+
it('should reject the request', () => {
|
|
52
|
+
const { response, channelEngine, event } = createChannelResponse();
|
|
53
|
+
jest.spyOn(channelEngine, 'sendMessage');
|
|
54
|
+
response.reject();
|
|
55
|
+
expect(channelEngine.sendMessage).toHaveBeenCalledWith('requestId', pondsocket_common_1.SystemSender.CHANNEL, [event.sender], pondsocket_common_1.ServerActions.ERROR, pondsocket_common_1.ErrorTypes.UNAUTHORIZED_BROADCAST, {
|
|
56
|
+
message: 'Unauthorized request',
|
|
57
|
+
code: 403,
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
it('should send a direct message', () => {
|
|
61
|
+
const { response, channelEngine, event } = createChannelResponse();
|
|
62
|
+
jest.spyOn(channelEngine, 'sendMessage');
|
|
63
|
+
response.send('event', { payload: 'payload' });
|
|
64
|
+
expect(channelEngine.sendMessage).toHaveBeenCalledWith('requestId', pondsocket_common_1.SystemSender.CHANNEL, [event.sender], pondsocket_common_1.ServerActions.SYSTEM, 'event', { payload: 'payload' });
|
|
65
|
+
});
|
|
66
|
+
it('should broadcast a message', () => {
|
|
67
|
+
const { response, channelEngine } = createChannelResponse();
|
|
68
|
+
jest.spyOn(channelEngine, 'sendMessage');
|
|
69
|
+
response.broadcast('event', { payload: 'payload' });
|
|
70
|
+
expect(channelEngine.sendMessage).toHaveBeenCalledWith('requestId', 'sender', pondsocket_common_1.ChannelReceiver.ALL_USERS, pondsocket_common_1.ServerActions.BROADCAST, 'event', { payload: 'payload' });
|
|
71
|
+
});
|
|
72
|
+
it('should broadcastFromUser a message', () => {
|
|
73
|
+
const { response, channelEngine } = createChannelResponse();
|
|
74
|
+
jest.spyOn(channelEngine, 'sendMessage');
|
|
75
|
+
response.broadcastFromUser('event', { payload: 'payload' });
|
|
76
|
+
expect(channelEngine.sendMessage).toHaveBeenCalledWith('requestId', 'sender', pondsocket_common_1.ChannelReceiver.ALL_EXCEPT_SENDER, pondsocket_common_1.ServerActions.BROADCAST, 'event', { payload: 'payload' });
|
|
77
|
+
});
|
|
78
|
+
it('should sendToUsers a message', () => {
|
|
79
|
+
const { response, channelEngine } = createChannelResponse();
|
|
80
|
+
jest.spyOn(channelEngine, 'sendMessage');
|
|
81
|
+
response.sendToUsers('event', { payload: 'payload' }, ['recipient']);
|
|
82
|
+
expect(channelEngine.sendMessage).toHaveBeenCalledWith('requestId', 'sender', ['recipient'], pondsocket_common_1.ServerActions.BROADCAST, 'event', { payload: 'payload' });
|
|
83
|
+
});
|
|
84
|
+
it('should fail to send to non existing users', () => {
|
|
85
|
+
const { event, response, channelEngine } = createChannelResponse();
|
|
86
|
+
jest.spyOn(channelEngine, 'sendMessage');
|
|
87
|
+
event.recipients = ['non_existing_user'];
|
|
88
|
+
expect(() => response.accept()).toThrow('ChannelEngine: Invalid recipients non_existing_user some users do not exist in channel test');
|
|
89
|
+
expect(channelEngine.sendMessage).toHaveBeenCalledWith('requestId', event.sender, ['non_existing_user'], pondsocket_common_1.ServerActions.BROADCAST, event.event, event.payload);
|
|
90
|
+
expect(() => response.sendToUsers('event', { payload: 'payload' }, ['non_existing_user']))
|
|
91
|
+
.toThrow('ChannelEngine: Invalid recipients non_existing_user some users do not exist in channel test');
|
|
92
|
+
});
|
|
93
|
+
it('should track a trackPresence', () => {
|
|
94
|
+
const { response, channelEngine } = createChannelResponse();
|
|
95
|
+
jest.spyOn(channelEngine.presenceEngine, 'trackPresence');
|
|
96
|
+
response.trackPresence({ status: 'online' });
|
|
97
|
+
expect(channelEngine.presenceEngine.trackPresence).toHaveBeenCalledWith('sender', { status: 'online' });
|
|
98
|
+
});
|
|
99
|
+
it('should update a users assign data', () => {
|
|
100
|
+
const { response, channelEngine } = createChannelResponse();
|
|
101
|
+
jest.spyOn(channelEngine, 'updateAssigns');
|
|
102
|
+
response.accept({ assign: 'updated' });
|
|
103
|
+
expect(channelEngine.updateAssigns).toHaveBeenCalledWith('sender', { assign: 'updated' });
|
|
104
|
+
});
|
|
105
|
+
it('should evict a user', () => {
|
|
106
|
+
const { response, channelEngine } = createChannelResponse();
|
|
107
|
+
jest.spyOn(channelEngine, 'kickUser');
|
|
108
|
+
response.evictUser('recipient');
|
|
109
|
+
expect(channelEngine.kickUser).toHaveBeenCalledWith('sender', 'recipient');
|
|
110
|
+
});
|
|
111
|
+
it('should destroy the channel', () => {
|
|
112
|
+
const { response, channelEngine } = createChannelResponse();
|
|
113
|
+
jest.spyOn(channelEngine, 'destroy');
|
|
114
|
+
response.closeChannel('recipient');
|
|
115
|
+
expect(channelEngine.destroy).toHaveBeenCalledWith('recipient');
|
|
116
|
+
});
|
|
117
|
+
it('should call the presence engine when the trackPresence is called', () => {
|
|
118
|
+
const { response, channelEngine } = createChannelResponse();
|
|
119
|
+
jest.spyOn(channelEngine.presenceEngine, 'trackPresence');
|
|
120
|
+
expect(channelEngine.presenceEngine.trackPresence).not.toHaveBeenCalled();
|
|
121
|
+
response.accept();
|
|
122
|
+
response.trackPresence({ status: 'online' });
|
|
123
|
+
expect(channelEngine.presenceEngine.trackPresence).toHaveBeenCalledWith('sender', { status: 'online' });
|
|
124
|
+
});
|
|
125
|
+
it('should throw an error if trackPresence is called twice', () => {
|
|
126
|
+
const { response, channelEngine } = createChannelResponse();
|
|
127
|
+
jest.spyOn(channelEngine.presenceEngine, 'trackPresence');
|
|
128
|
+
expect(channelEngine.presenceEngine.trackPresence).not.toHaveBeenCalled();
|
|
129
|
+
response.accept();
|
|
130
|
+
response.trackPresence({ status: 'online' });
|
|
131
|
+
expect(channelEngine.presenceEngine.trackPresence).toHaveBeenCalledWith('sender', { status: 'online' });
|
|
132
|
+
expect(() => response.trackPresence({ status: 'online' })).toThrow('PresenceEngine: Presence with key sender already exists');
|
|
133
|
+
});
|
|
134
|
+
it('should throw an error if trackPresence is called for a non existing user', () => {
|
|
135
|
+
const { response, channelEngine } = createChannelResponse();
|
|
136
|
+
jest.spyOn(channelEngine.presenceEngine, 'trackPresence');
|
|
137
|
+
expect(channelEngine.presenceEngine.trackPresence).not.toHaveBeenCalled();
|
|
138
|
+
response.accept();
|
|
139
|
+
expect(() => response.trackPresence({ status: 'online' }, 'non_existent_user'))
|
|
140
|
+
.toThrow('ChannelEngine: Invalid recipients non_existent_user some users do not exist in channel test');
|
|
141
|
+
});
|
|
142
|
+
it('should update the presence of a user that is already tracked', () => {
|
|
143
|
+
var _a, _b;
|
|
144
|
+
const { response, channelEngine } = createChannelResponse();
|
|
145
|
+
jest.spyOn(channelEngine.presenceEngine, 'trackPresence');
|
|
146
|
+
expect(channelEngine.presenceEngine.trackPresence).not.toHaveBeenCalled();
|
|
147
|
+
response.accept();
|
|
148
|
+
response.trackPresence({ status: 'online' });
|
|
149
|
+
expect(channelEngine.presenceEngine.trackPresence).toHaveBeenCalledWith('sender', { status: 'online' });
|
|
150
|
+
expect((_a = channelEngine.presenceEngine) === null || _a === void 0 ? void 0 : _a.getPresence()).toEqual({
|
|
151
|
+
sender: { status: 'online' },
|
|
152
|
+
});
|
|
153
|
+
response.updatePresence({ status: 'offline' });
|
|
154
|
+
expect((_b = channelEngine.presenceEngine) === null || _b === void 0 ? void 0 : _b.getPresence()).toEqual({
|
|
155
|
+
sender: { status: 'offline' },
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
it('should throw an error if updatePresence is called for a non existing user', () => {
|
|
159
|
+
const { response, channelEngine } = createChannelResponse();
|
|
160
|
+
jest.spyOn(channelEngine.presenceEngine, 'trackPresence');
|
|
161
|
+
expect(channelEngine.presenceEngine.trackPresence).not.toHaveBeenCalled();
|
|
162
|
+
response.accept();
|
|
163
|
+
response.trackPresence({ status: 'online' });
|
|
164
|
+
expect(() => response.updatePresence({ status: 'online' }, 'non_existent_user'))
|
|
165
|
+
.toThrow('PresenceEngine: Presence with key non_existent_user does not exist');
|
|
166
|
+
});
|
|
167
|
+
it('should unTrack a trackPresence', () => {
|
|
168
|
+
var _a, _b;
|
|
169
|
+
const { response, channelEngine } = createChannelResponse();
|
|
170
|
+
response.trackPresence({ status: 'online' });
|
|
171
|
+
expect((_a = channelEngine.presenceEngine) === null || _a === void 0 ? void 0 : _a.getPresence()).toEqual({
|
|
172
|
+
sender: { status: 'online' },
|
|
173
|
+
});
|
|
174
|
+
response.unTrackPresence();
|
|
175
|
+
expect((_b = channelEngine.presenceEngine) === null || _b === void 0 ? void 0 : _b.getPresence()).toEqual({});
|
|
176
|
+
});
|
|
177
|
+
it('should throw an error if unTrackPresence is called for a non existing user', () => {
|
|
178
|
+
var _a;
|
|
179
|
+
const { response, channelEngine } = createChannelResponse();
|
|
180
|
+
response.trackPresence({ status: 'online' });
|
|
181
|
+
expect((_a = channelEngine.presenceEngine) === null || _a === void 0 ? void 0 : _a.getPresence()).toEqual({
|
|
182
|
+
sender: { status: 'online' },
|
|
183
|
+
});
|
|
184
|
+
expect(() => response.unTrackPresence('non_existent_user'))
|
|
185
|
+
.toThrow('PresenceEngine: Presence with key non_existent_user does not exist');
|
|
186
|
+
});
|
|
187
|
+
it('should throw an error if accept, reject / send is called more than once', () => {
|
|
188
|
+
const { response, channelEngine } = createChannelResponse();
|
|
189
|
+
jest.spyOn(channelEngine, 'sendMessage');
|
|
190
|
+
expect(channelEngine.sendMessage).not.toHaveBeenCalled();
|
|
191
|
+
response.accept();
|
|
192
|
+
expect(channelEngine.sendMessage).toHaveBeenCalledWith('requestId', 'sender', ['recipient'], pondsocket_common_1.ServerActions.BROADCAST, 'event', { payload: 'payload' });
|
|
193
|
+
expect(() => response.accept()).toThrow('Event response has already been executed');
|
|
194
|
+
expect(() => response.reject()).toThrow('Event response has already been executed');
|
|
195
|
+
expect(() => response.send('event', { payload: 'payload' })).toThrow('Event response has already been executed');
|
|
196
|
+
});
|
|
197
|
+
});
|
package/endpoint/endpoint.js
CHANGED
|
@@ -10,16 +10,18 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
10
10
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
11
11
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
12
|
};
|
|
13
|
-
var _Endpoint_instances, _Endpoint_middleware, _Endpoint_channels, _Endpoint_sockets, _Endpoint_sendMessage, _Endpoint_joinChannel, _Endpoint_execute, _Endpoint_handleMessage, _Endpoint_readMessage
|
|
13
|
+
var _Endpoint_instances, _Endpoint_middleware, _Endpoint_channels, _Endpoint_sockets, _Endpoint_sendMessage, _Endpoint_joinChannel, _Endpoint_execute, _Endpoint_handleMessage, _Endpoint_readMessage;
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.Endpoint = void 0;
|
|
16
|
+
const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
|
|
17
|
+
const zod_1 = require("zod");
|
|
16
18
|
const middleware_1 = require("../abstracts/middleware");
|
|
17
|
-
const enums_1 = require("../enums");
|
|
18
19
|
const pondError_1 = require("../errors/pondError");
|
|
19
20
|
const joinRequest_1 = require("../lobby/joinRequest");
|
|
20
21
|
const joinResponse_1 = require("../lobby/joinResponse");
|
|
21
22
|
const lobby_1 = require("../lobby/lobby");
|
|
22
23
|
const matcher_1 = require("../matcher/matcher");
|
|
24
|
+
const schema_1 = require("../schema");
|
|
23
25
|
class Endpoint {
|
|
24
26
|
constructor() {
|
|
25
27
|
_Endpoint_instances.add(this);
|
|
@@ -83,8 +85,9 @@ class Endpoint {
|
|
|
83
85
|
const message = {
|
|
84
86
|
event,
|
|
85
87
|
payload,
|
|
86
|
-
|
|
87
|
-
|
|
88
|
+
requestId: (0, pondsocket_common_1.uuid)(),
|
|
89
|
+
action: pondsocket_common_1.ServerActions.BROADCAST,
|
|
90
|
+
channelName: pondsocket_common_1.SystemSender.ENDPOINT,
|
|
88
91
|
};
|
|
89
92
|
__classPrivateFieldGet(this, _Endpoint_instances, "m", _Endpoint_sendMessage).call(this, socket, message);
|
|
90
93
|
});
|
|
@@ -125,8 +128,8 @@ class Endpoint {
|
|
|
125
128
|
exports.Endpoint = Endpoint;
|
|
126
129
|
_Endpoint_middleware = new WeakMap(), _Endpoint_channels = new WeakMap(), _Endpoint_sockets = new WeakMap(), _Endpoint_instances = new WeakSet(), _Endpoint_sendMessage = function _Endpoint_sendMessage(socket, message) {
|
|
127
130
|
socket.send(JSON.stringify(message));
|
|
128
|
-
}, _Endpoint_joinChannel = function _Endpoint_joinChannel(channel, socket, joinParams) {
|
|
129
|
-
const cache = Object.assign(Object.assign({}, socket), { channelName: channel });
|
|
131
|
+
}, _Endpoint_joinChannel = function _Endpoint_joinChannel(channel, socket, joinParams, requestId) {
|
|
132
|
+
const cache = Object.assign(Object.assign({}, socket), { requestId, channelName: channel });
|
|
130
133
|
__classPrivateFieldGet(this, _Endpoint_middleware, "f").run(cache, joinParams, () => {
|
|
131
134
|
throw new pondError_1.EndpointError(`GatewayEngine: Channel ${channel} does not exist`, 404);
|
|
132
135
|
});
|
|
@@ -141,15 +144,15 @@ _Endpoint_middleware = new WeakMap(), _Endpoint_channels = new WeakMap(), _Endpo
|
|
|
141
144
|
throw new Error(`GatewayEngine: Channel ${channel} does not exist`);
|
|
142
145
|
}, _Endpoint_handleMessage = function _Endpoint_handleMessage(cache, message) {
|
|
143
146
|
switch (message.action) {
|
|
144
|
-
case
|
|
145
|
-
__classPrivateFieldGet(this, _Endpoint_instances, "m", _Endpoint_joinChannel).call(this, message.channelName, cache, message.payload);
|
|
147
|
+
case pondsocket_common_1.ClientActions.JOIN_CHANNEL:
|
|
148
|
+
__classPrivateFieldGet(this, _Endpoint_instances, "m", _Endpoint_joinChannel).call(this, message.channelName, cache, message.payload, message.requestId);
|
|
146
149
|
break;
|
|
147
|
-
case
|
|
150
|
+
case pondsocket_common_1.ClientActions.LEAVE_CHANNEL:
|
|
148
151
|
__classPrivateFieldGet(this, _Endpoint_instances, "m", _Endpoint_execute).call(this, message.channelName, (channel) => {
|
|
149
152
|
channel.removeUser(cache.clientId);
|
|
150
153
|
});
|
|
151
154
|
break;
|
|
152
|
-
case
|
|
155
|
+
case pondsocket_common_1.ClientActions.BROADCAST:
|
|
153
156
|
__classPrivateFieldGet(this, _Endpoint_instances, "m", _Endpoint_execute).call(this, message.channelName, (channel) => {
|
|
154
157
|
channel.broadcastMessage(cache.clientId, message);
|
|
155
158
|
});
|
|
@@ -159,49 +162,37 @@ _Endpoint_middleware = new WeakMap(), _Endpoint_channels = new WeakMap(), _Endpo
|
|
|
159
162
|
}
|
|
160
163
|
}, _Endpoint_readMessage = function _Endpoint_readMessage(cache, message) {
|
|
161
164
|
const errorMessage = {
|
|
162
|
-
event:
|
|
163
|
-
action:
|
|
164
|
-
channelName:
|
|
165
|
+
event: pondsocket_common_1.ErrorTypes.INVALID_MESSAGE,
|
|
166
|
+
action: pondsocket_common_1.ServerActions.ERROR,
|
|
167
|
+
channelName: pondsocket_common_1.SystemSender.ENDPOINT,
|
|
168
|
+
requestId: (0, pondsocket_common_1.uuid)(),
|
|
165
169
|
payload: {},
|
|
166
170
|
};
|
|
167
171
|
try {
|
|
168
172
|
const data = JSON.parse(message);
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
else if (!data.channelName) {
|
|
175
|
-
errorMessage.payload = {
|
|
176
|
-
message: 'No channel name provided',
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
else if (!data.payload) {
|
|
173
|
+
const result = schema_1.clientMessageSchema.parse(data);
|
|
174
|
+
__classPrivateFieldGet(this, _Endpoint_instances, "m", _Endpoint_handleMessage).call(this, cache, result);
|
|
175
|
+
}
|
|
176
|
+
catch (e) {
|
|
177
|
+
if (e instanceof zod_1.ZodError) {
|
|
180
178
|
errorMessage.payload = {
|
|
181
|
-
message:
|
|
179
|
+
message: e.message,
|
|
180
|
+
code: 400,
|
|
182
181
|
};
|
|
183
182
|
}
|
|
184
|
-
if (
|
|
185
|
-
__classPrivateFieldGet(this, _Endpoint_instances, "m", _Endpoint_sendMessage).call(this, cache.socket, errorMessage);
|
|
186
|
-
}
|
|
187
|
-
else {
|
|
188
|
-
__classPrivateFieldGet(this, _Endpoint_instances, "m", _Endpoint_handleMessage).call(this, cache, data);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
catch (e) {
|
|
192
|
-
if (e instanceof SyntaxError) {
|
|
183
|
+
else if (e instanceof SyntaxError) {
|
|
193
184
|
errorMessage.payload = {
|
|
194
185
|
message: 'Invalid JSON',
|
|
195
186
|
};
|
|
196
187
|
}
|
|
197
188
|
else if (e instanceof Error) {
|
|
198
|
-
errorMessage.event =
|
|
189
|
+
errorMessage.event = pondsocket_common_1.ErrorTypes.INTERNAL_SERVER_ERROR;
|
|
199
190
|
errorMessage.payload = {
|
|
200
191
|
message: e.message,
|
|
201
192
|
};
|
|
202
193
|
}
|
|
203
194
|
else if (e instanceof pondError_1.PresenceError) {
|
|
204
|
-
errorMessage.event =
|
|
195
|
+
errorMessage.event = pondsocket_common_1.ErrorTypes.PRESENCE_ERROR;
|
|
205
196
|
errorMessage.channelName = e.channel;
|
|
206
197
|
errorMessage.payload = {
|
|
207
198
|
message: e.message,
|
|
@@ -210,7 +201,7 @@ _Endpoint_middleware = new WeakMap(), _Endpoint_channels = new WeakMap(), _Endpo
|
|
|
210
201
|
};
|
|
211
202
|
}
|
|
212
203
|
else if (e instanceof pondError_1.ChannelError) {
|
|
213
|
-
errorMessage.event =
|
|
204
|
+
errorMessage.event = pondsocket_common_1.ErrorTypes.CHANNEL_ERROR;
|
|
214
205
|
errorMessage.channelName = e.channel;
|
|
215
206
|
errorMessage.payload = {
|
|
216
207
|
message: e.message,
|
|
@@ -218,14 +209,17 @@ _Endpoint_middleware = new WeakMap(), _Endpoint_channels = new WeakMap(), _Endpo
|
|
|
218
209
|
};
|
|
219
210
|
}
|
|
220
211
|
else if (e instanceof pondError_1.EndpointError) {
|
|
221
|
-
errorMessage.event =
|
|
212
|
+
errorMessage.event = pondsocket_common_1.ErrorTypes.ENDPOINT_ERROR;
|
|
222
213
|
errorMessage.payload = {
|
|
223
214
|
message: e.message,
|
|
224
215
|
code: e.code,
|
|
225
216
|
};
|
|
226
217
|
}
|
|
218
|
+
else {
|
|
219
|
+
errorMessage.payload = {
|
|
220
|
+
message: 'Unknown error',
|
|
221
|
+
};
|
|
222
|
+
}
|
|
227
223
|
__classPrivateFieldGet(this, _Endpoint_instances, "m", _Endpoint_sendMessage).call(this, cache.socket, errorMessage);
|
|
228
224
|
}
|
|
229
|
-
}, _Endpoint_isObjectEmpty = function _Endpoint_isObjectEmpty(obj) {
|
|
230
|
-
return Object.keys(obj).length === 0;
|
|
231
225
|
};
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
|
|
16
|
+
const superwstest_1 = __importDefault(require("superwstest"));
|
|
17
|
+
const pondSocket_1 = require("../server/pondSocket");
|
|
18
|
+
/* eslint-disable line-comment-position, no-inline-comments */
|
|
19
|
+
describe('endpoint', () => {
|
|
20
|
+
let socket;
|
|
21
|
+
let server;
|
|
22
|
+
beforeEach((done) => {
|
|
23
|
+
socket = new pondSocket_1.PondSocket();
|
|
24
|
+
server = socket.listen(3000, 'localhost', done);
|
|
25
|
+
});
|
|
26
|
+
afterEach((done) => {
|
|
27
|
+
server.close(done);
|
|
28
|
+
});
|
|
29
|
+
it('should be able to close a single socket', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
30
|
+
let count = 0;
|
|
31
|
+
const endpoint = socket.createEndpoint('/api/:room', (req, res) => {
|
|
32
|
+
if (req.params.room === 'socket') {
|
|
33
|
+
res.accept();
|
|
34
|
+
count++;
|
|
35
|
+
setTimeout(() => {
|
|
36
|
+
endpoint.closeConnection(req.id);
|
|
37
|
+
}, 1000);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
res.reject();
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
yield (0, superwstest_1.default)(server)
|
|
44
|
+
.ws('/api/socket')
|
|
45
|
+
.expectUpgrade((res) => expect(res.statusCode).toBe(101))
|
|
46
|
+
.wait(200)
|
|
47
|
+
.expectClosed();
|
|
48
|
+
expect(count).toBe(1);
|
|
49
|
+
}));
|
|
50
|
+
it('should be able to list connections', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
51
|
+
const endpoint = socket.createEndpoint('/api/:room', (req, res) => {
|
|
52
|
+
if (req.params.room === 'socket') {
|
|
53
|
+
res.accept();
|
|
54
|
+
const connections = endpoint.listConnections();
|
|
55
|
+
expect(connections).toHaveLength(1);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
res.reject();
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
yield (0, superwstest_1.default)(server)
|
|
62
|
+
.ws('/api/socket')
|
|
63
|
+
.expectUpgrade((res) => expect(res.statusCode).toBe(101));
|
|
64
|
+
}));
|
|
65
|
+
it('should be able to refuse connections to the endpoint', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
66
|
+
let count = 0;
|
|
67
|
+
socket.createEndpoint('/api/:path', (req, res) => {
|
|
68
|
+
count++;
|
|
69
|
+
expect(req.params.path).toBe('socket');
|
|
70
|
+
res.reject();
|
|
71
|
+
});
|
|
72
|
+
yield (0, superwstest_1.default)(server)
|
|
73
|
+
.ws('/api/socket')
|
|
74
|
+
.expectUpgrade((res) => expect(res.statusCode).toBe(101)) // the connection is still upgraded, so we can send error messages
|
|
75
|
+
.expectMessage(expect.objectContaining({
|
|
76
|
+
action: pondsocket_common_1.ServerActions.ERROR,
|
|
77
|
+
event: pondsocket_common_1.ErrorTypes.UNAUTHORIZED_CONNECTION,
|
|
78
|
+
channelName: pondsocket_common_1.SystemSender.ENDPOINT,
|
|
79
|
+
payload: {
|
|
80
|
+
message: 'Unauthorized connection',
|
|
81
|
+
code: 401,
|
|
82
|
+
},
|
|
83
|
+
}))
|
|
84
|
+
.expectClosed();
|
|
85
|
+
expect(count).toBe(1);
|
|
86
|
+
}));
|
|
87
|
+
it('should be able to send a message to all connection', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
88
|
+
const endpoint = socket.createEndpoint('/api/:room', (req, res) => {
|
|
89
|
+
if (req.params.room === 'socket') {
|
|
90
|
+
res.accept();
|
|
91
|
+
const connections = endpoint.listConnections();
|
|
92
|
+
expect(connections).toHaveLength(1);
|
|
93
|
+
endpoint.broadcast('TEST', { test: 'test' });
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
res.reject();
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
yield (0, superwstest_1.default)(server)
|
|
100
|
+
.ws('/api/socket')
|
|
101
|
+
.expectUpgrade((res) => expect(res.statusCode).toBe(101))
|
|
102
|
+
.expectMessage(expect.objectContaining({
|
|
103
|
+
event: 'TEST',
|
|
104
|
+
action: pondsocket_common_1.ServerActions.BROADCAST,
|
|
105
|
+
channelName: pondsocket_common_1.SystemSender.ENDPOINT,
|
|
106
|
+
payload: {
|
|
107
|
+
test: 'test',
|
|
108
|
+
},
|
|
109
|
+
}));
|
|
110
|
+
}));
|
|
111
|
+
it('should be able to accept connections on this handler', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
112
|
+
const message = {
|
|
113
|
+
action: pondsocket_common_1.ClientActions.JOIN_CHANNEL,
|
|
114
|
+
channelName: '/test/socket',
|
|
115
|
+
event: 'TEST',
|
|
116
|
+
payload: {},
|
|
117
|
+
};
|
|
118
|
+
const endpoint = socket.createEndpoint('/api/:room', (req, res) => {
|
|
119
|
+
if (req.params.room === 'socket') {
|
|
120
|
+
res.accept();
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
res.reject();
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
endpoint.createChannel('/test/:room', (req, res) => {
|
|
127
|
+
expect(req.event.params.room).toBeDefined();
|
|
128
|
+
res.accept({
|
|
129
|
+
assigns: {
|
|
130
|
+
status: 'online',
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
yield (0, superwstest_1.default)(server)
|
|
135
|
+
.ws('/api/socket')
|
|
136
|
+
.expectUpgrade((res) => expect(res.statusCode).toBe(101))
|
|
137
|
+
.sendJson(message)
|
|
138
|
+
.close()
|
|
139
|
+
.expectClosed();
|
|
140
|
+
yield (0, superwstest_1.default)(server)
|
|
141
|
+
.ws('/api/socket')
|
|
142
|
+
.expectUpgrade((res) => expect(res.statusCode).toBe(101))
|
|
143
|
+
.sendJson(Object.assign(Object.assign({}, message), { channelName: '/socket/socket' }))
|
|
144
|
+
.expectMessage(expect.objectContaining({
|
|
145
|
+
action: pondsocket_common_1.ServerActions.SYSTEM,
|
|
146
|
+
channelName: '/socket/socket',
|
|
147
|
+
event: pondsocket_common_1.Events.ACKNOWLEDGE,
|
|
148
|
+
payload: {},
|
|
149
|
+
}))
|
|
150
|
+
.close()
|
|
151
|
+
.expectClosed();
|
|
152
|
+
}));
|
|
153
|
+
it('should send an error when the channel exists but other things happen', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
154
|
+
const message = {
|
|
155
|
+
action: pondsocket_common_1.ClientActions.JOIN_CHANNEL,
|
|
156
|
+
channelName: '/test/socket',
|
|
157
|
+
event: 'TEST',
|
|
158
|
+
payload: {},
|
|
159
|
+
};
|
|
160
|
+
const endpoint = socket.createEndpoint('/api/:room', (_, res) => {
|
|
161
|
+
res.accept();
|
|
162
|
+
});
|
|
163
|
+
endpoint.createChannel('/test/:room', (req, res) => {
|
|
164
|
+
expect(req.event.params.room).toBeDefined();
|
|
165
|
+
res.reject('Something went wrong');
|
|
166
|
+
});
|
|
167
|
+
yield (0, superwstest_1.default)(server)
|
|
168
|
+
.ws('/api/socket')
|
|
169
|
+
.expectUpgrade((res) => expect(res.statusCode).toBe(101))
|
|
170
|
+
.sendJson(message)
|
|
171
|
+
.expectMessage(expect.objectContaining({
|
|
172
|
+
action: pondsocket_common_1.ServerActions.ERROR,
|
|
173
|
+
channelName: '/test/socket',
|
|
174
|
+
event: pondsocket_common_1.ErrorTypes.UNAUTHORIZED_JOIN_REQUEST,
|
|
175
|
+
payload: {
|
|
176
|
+
message: 'Request to join channel /test/socket rejected: Something went wrong',
|
|
177
|
+
code: 403,
|
|
178
|
+
},
|
|
179
|
+
}))
|
|
180
|
+
.close()
|
|
181
|
+
.expectClosed();
|
|
182
|
+
}));
|
|
183
|
+
it('should be able to track the presence of its users', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
184
|
+
const message = {
|
|
185
|
+
action: pondsocket_common_1.ClientActions.JOIN_CHANNEL,
|
|
186
|
+
channelName: '/test/socket',
|
|
187
|
+
event: 'TEST',
|
|
188
|
+
payload: {},
|
|
189
|
+
};
|
|
190
|
+
const endpoint = socket.createEndpoint('/api/:room', (_, res) => {
|
|
191
|
+
res.accept();
|
|
192
|
+
});
|
|
193
|
+
endpoint.createChannel('/test/:room', (req, res) => {
|
|
194
|
+
expect(req.event.params.room).toBeDefined();
|
|
195
|
+
res
|
|
196
|
+
.accept()
|
|
197
|
+
.trackPresence({
|
|
198
|
+
status: 'online',
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
yield (0, superwstest_1.default)(server)
|
|
202
|
+
.ws('/api/socket')
|
|
203
|
+
.expectUpgrade((res) => expect(res.statusCode).toBe(101))
|
|
204
|
+
.sendJson(message)
|
|
205
|
+
.expectMessage(expect.objectContaining({
|
|
206
|
+
action: pondsocket_common_1.ServerActions.SYSTEM,
|
|
207
|
+
channelName: '/test/socket',
|
|
208
|
+
event: pondsocket_common_1.Events.ACKNOWLEDGE,
|
|
209
|
+
payload: {},
|
|
210
|
+
}))
|
|
211
|
+
.close();
|
|
212
|
+
}));
|
|
213
|
+
it('should throw an error if accept, reject / send is called more than once', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
214
|
+
socket.createEndpoint('/api/:room', (_, res) => {
|
|
215
|
+
res.send('hello', {
|
|
216
|
+
test: 'test',
|
|
217
|
+
});
|
|
218
|
+
expect(() => res.accept()).toThrowError('Cannot execute response more than once');
|
|
219
|
+
});
|
|
220
|
+
yield (0, superwstest_1.default)(server)
|
|
221
|
+
.ws('/api/socket')
|
|
222
|
+
.expectUpgrade((res) => expect(res.statusCode).toBe(101))
|
|
223
|
+
.expectMessage(expect.objectContaining({
|
|
224
|
+
action: pondsocket_common_1.ServerActions.BROADCAST,
|
|
225
|
+
channelName: pondsocket_common_1.SystemSender.ENDPOINT,
|
|
226
|
+
event: 'hello',
|
|
227
|
+
payload: {
|
|
228
|
+
test: 'test',
|
|
229
|
+
},
|
|
230
|
+
}));
|
|
231
|
+
}));
|
|
232
|
+
it('should be able to connect, join a channel and send a message', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
233
|
+
const message = {
|
|
234
|
+
action: pondsocket_common_1.ClientActions.JOIN_CHANNEL,
|
|
235
|
+
channelName: '/test/socket',
|
|
236
|
+
event: 'TEST',
|
|
237
|
+
payload: {},
|
|
238
|
+
};
|
|
239
|
+
const endpoint = socket.createEndpoint('/api/:room', (_, res) => {
|
|
240
|
+
res.accept();
|
|
241
|
+
});
|
|
242
|
+
const channel = endpoint.createChannel('/test/:room', (req, res) => {
|
|
243
|
+
expect(req.event.params.room).toBeDefined();
|
|
244
|
+
res.accept();
|
|
245
|
+
});
|
|
246
|
+
channel.onEvent('echo', (req, res) => {
|
|
247
|
+
res.send('echo', req.event.payload);
|
|
248
|
+
});
|
|
249
|
+
channel.onEvent('broadcast', (req) => {
|
|
250
|
+
channel.broadcast('broadcast', Object.assign(Object.assign({}, req.event.payload), { broadcast: true }));
|
|
251
|
+
});
|
|
252
|
+
yield (0, superwstest_1.default)(server)
|
|
253
|
+
.ws('/api/socket')
|
|
254
|
+
.expectUpgrade((res) => expect(res.statusCode).toBe(101))
|
|
255
|
+
.sendJson(message)
|
|
256
|
+
.expectMessage(expect.objectContaining({
|
|
257
|
+
action: pondsocket_common_1.ServerActions.SYSTEM,
|
|
258
|
+
channelName: '/test/socket',
|
|
259
|
+
event: pondsocket_common_1.Events.ACKNOWLEDGE,
|
|
260
|
+
payload: {},
|
|
261
|
+
}))
|
|
262
|
+
.sendJson({
|
|
263
|
+
addresses: pondsocket_common_1.ChannelReceiver.ALL_EXCEPT_SENDER,
|
|
264
|
+
action: pondsocket_common_1.ClientActions.BROADCAST,
|
|
265
|
+
channelName: '/test/socket',
|
|
266
|
+
event: 'echo',
|
|
267
|
+
payload: {
|
|
268
|
+
test: 'test',
|
|
269
|
+
},
|
|
270
|
+
})
|
|
271
|
+
.expectMessage(expect.objectContaining({
|
|
272
|
+
action: pondsocket_common_1.ServerActions.SYSTEM,
|
|
273
|
+
channelName: '/test/socket',
|
|
274
|
+
event: 'echo',
|
|
275
|
+
payload: {
|
|
276
|
+
test: 'test',
|
|
277
|
+
},
|
|
278
|
+
}))
|
|
279
|
+
.sendJson({
|
|
280
|
+
action: pondsocket_common_1.ClientActions.BROADCAST,
|
|
281
|
+
channelName: '/test/socket',
|
|
282
|
+
event: 'broadcast',
|
|
283
|
+
payload: {
|
|
284
|
+
test: 'test',
|
|
285
|
+
},
|
|
286
|
+
})
|
|
287
|
+
.expectMessage(expect.objectContaining({
|
|
288
|
+
action: pondsocket_common_1.ServerActions.SYSTEM,
|
|
289
|
+
channelName: '/test/socket',
|
|
290
|
+
event: 'broadcast',
|
|
291
|
+
payload: {
|
|
292
|
+
test: 'test',
|
|
293
|
+
broadcast: true,
|
|
294
|
+
},
|
|
295
|
+
}));
|
|
296
|
+
}));
|
|
297
|
+
});
|