@eleven-am/pondsocket 0.1.168 → 0.1.170
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/abstracts/middleware.js +40 -17
- package/abstracts/redisClient.js +278 -0
- package/engines/channelEngine.js +163 -0
- package/engines/endpointEngine.js +163 -0
- package/engines/lobbyEngine.js +79 -0
- package/errors/httpError.js +11 -0
- package/index.js +2 -2
- package/managers/distributedManager.js +115 -0
- package/managers/localManager.js +41 -0
- package/managers/manager.js +219 -0
- package/managers/managerFactory.js +31 -0
- package/package.json +24 -14
- package/requests/eventRequest.js +51 -0
- package/requests/joinRequest.js +56 -0
- package/responses/connectionResponse.js +89 -0
- package/{channel → responses}/eventResponse.js +8 -79
- package/{lobby → responses}/joinResponse.js +25 -84
- package/server/{pondSocket.js → server.js} +55 -55
- package/types.d.ts +33 -106
- package/wrappers/channel.js +70 -0
- package/wrappers/endpoint.js +32 -0
- package/wrappers/pondChannel.js +48 -0
- package/abstracts/abstractRequest.js +0 -57
- package/abstracts/abstractRequest.test.js +0 -48
- package/abstracts/middleware.test.js +0 -70
- package/channel/channel.js +0 -351
- package/channel/channel.test.js +0 -435
- package/channel/eventRequest.js +0 -25
- package/channel/eventRequest.test.js +0 -30
- package/channel/eventResponse.test.js +0 -175
- package/endpoint/endpoint.js +0 -299
- package/endpoint/endpoint.test.js +0 -299
- package/endpoint/response.js +0 -129
- package/errors/pondError.js +0 -28
- package/lobby/JoinRequest.test.js +0 -50
- package/lobby/JoinResponse.test.js +0 -142
- package/lobby/joinRequest.js +0 -43
- package/lobby/lobby.js +0 -186
- package/matcher/matcher.test.js +0 -90
- package/presence/presence.js +0 -112
- package/presence/presenceEngine.test.js +0 -129
package/endpoint/response.js
DELETED
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
3
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
4
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
5
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
6
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
7
|
-
};
|
|
8
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
9
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
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
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
|
-
};
|
|
13
|
-
var _ConnectionResponse_instances, _ConnectionResponse_webSocket, _ConnectionResponse_engine, _ConnectionResponse_clientId, _ConnectionResponse_executed, _ConnectionResponse_assigns, _ConnectionResponse_requestId, _ConnectionResponse_sendMessage, _ConnectionResponse_performChecks;
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.ConnectionResponse = void 0;
|
|
16
|
-
const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
|
|
17
|
-
const ws_1 = require("ws");
|
|
18
|
-
const pondError_1 = require("../errors/pondError");
|
|
19
|
-
class ConnectionResponse {
|
|
20
|
-
constructor(webSocket, engine, clientId) {
|
|
21
|
-
_ConnectionResponse_instances.add(this);
|
|
22
|
-
_ConnectionResponse_webSocket.set(this, void 0);
|
|
23
|
-
_ConnectionResponse_engine.set(this, void 0);
|
|
24
|
-
_ConnectionResponse_clientId.set(this, void 0);
|
|
25
|
-
_ConnectionResponse_executed.set(this, void 0);
|
|
26
|
-
_ConnectionResponse_assigns.set(this, void 0);
|
|
27
|
-
_ConnectionResponse_requestId.set(this, void 0);
|
|
28
|
-
__classPrivateFieldSet(this, _ConnectionResponse_webSocket, webSocket, "f");
|
|
29
|
-
__classPrivateFieldSet(this, _ConnectionResponse_engine, engine, "f");
|
|
30
|
-
__classPrivateFieldSet(this, _ConnectionResponse_clientId, clientId, "f");
|
|
31
|
-
__classPrivateFieldSet(this, _ConnectionResponse_assigns, {}, "f");
|
|
32
|
-
__classPrivateFieldSet(this, _ConnectionResponse_executed, false, "f");
|
|
33
|
-
__classPrivateFieldSet(this, _ConnectionResponse_requestId, (0, pondsocket_common_1.uuid)(), "f");
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* @desc Whether the server has responded to the request
|
|
37
|
-
*/
|
|
38
|
-
get hasResponded() {
|
|
39
|
-
return __classPrivateFieldGet(this, _ConnectionResponse_executed, "f");
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* @desc Assigns data to the user
|
|
43
|
-
* @param assigns - the data to assign
|
|
44
|
-
*/
|
|
45
|
-
assign(assigns) {
|
|
46
|
-
if (!__classPrivateFieldGet(this, _ConnectionResponse_executed, "f")) {
|
|
47
|
-
__classPrivateFieldSet(this, _ConnectionResponse_assigns, Object.assign(Object.assign({}, __classPrivateFieldGet(this, _ConnectionResponse_assigns, "f")), assigns), "f");
|
|
48
|
-
}
|
|
49
|
-
else {
|
|
50
|
-
const user = __classPrivateFieldGet(this, _ConnectionResponse_engine, "f").getUser(__classPrivateFieldGet(this, _ConnectionResponse_clientId, "f"));
|
|
51
|
-
user.assigns = Object.assign(Object.assign({}, user.assigns), assigns);
|
|
52
|
-
}
|
|
53
|
-
return this;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* @desc Accepts the join request
|
|
57
|
-
*/
|
|
58
|
-
accept() {
|
|
59
|
-
__classPrivateFieldGet(this, _ConnectionResponse_instances, "m", _ConnectionResponse_performChecks).call(this);
|
|
60
|
-
const cache = {
|
|
61
|
-
clientId: __classPrivateFieldGet(this, _ConnectionResponse_clientId, "f"),
|
|
62
|
-
socket: __classPrivateFieldGet(this, _ConnectionResponse_webSocket, "f"),
|
|
63
|
-
assigns: __classPrivateFieldGet(this, _ConnectionResponse_assigns, "f"),
|
|
64
|
-
subscriptions: new Map(),
|
|
65
|
-
};
|
|
66
|
-
__classPrivateFieldGet(this, _ConnectionResponse_engine, "f").manageSocket(cache);
|
|
67
|
-
return this;
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* @desc Rejects the request with the given error message
|
|
71
|
-
* @param message - the error message
|
|
72
|
-
* @param errorCode - the error code
|
|
73
|
-
*/
|
|
74
|
-
decline(message, errorCode) {
|
|
75
|
-
__classPrivateFieldGet(this, _ConnectionResponse_instances, "m", _ConnectionResponse_performChecks).call(this);
|
|
76
|
-
const payload = {
|
|
77
|
-
message: message || 'Unauthorized connection',
|
|
78
|
-
code: errorCode || 401,
|
|
79
|
-
};
|
|
80
|
-
__classPrivateFieldGet(this, _ConnectionResponse_instances, "m", _ConnectionResponse_sendMessage).call(this, pondsocket_common_1.ServerActions.ERROR, pondsocket_common_1.ErrorTypes.UNAUTHORIZED_CONNECTION, payload);
|
|
81
|
-
__classPrivateFieldGet(this, _ConnectionResponse_webSocket, "f").close();
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* @desc Emits a direct message to the client
|
|
85
|
-
* @param event - the event name
|
|
86
|
-
* @param payload - the payload to send
|
|
87
|
-
*/
|
|
88
|
-
reply(event, payload) {
|
|
89
|
-
if (__classPrivateFieldGet(this, _ConnectionResponse_webSocket, "f").readyState !== ws_1.WebSocket.OPEN) {
|
|
90
|
-
throw new pondError_1.EndpointError('Socket is not open', 400);
|
|
91
|
-
}
|
|
92
|
-
__classPrivateFieldGet(this, _ConnectionResponse_instances, "m", _ConnectionResponse_sendMessage).call(this, pondsocket_common_1.ServerActions.BROADCAST, event, payload);
|
|
93
|
-
return this;
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* @desc Subscribes the client to a channel
|
|
97
|
-
* @param channel - the channel to subscribe to
|
|
98
|
-
*/
|
|
99
|
-
subscribeTo(channel) {
|
|
100
|
-
__classPrivateFieldGet(this, _ConnectionResponse_engine, "f").subscribeTo(__classPrivateFieldGet(this, _ConnectionResponse_clientId, "f"), channel);
|
|
101
|
-
return this;
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* @desc Unsubscribes the client from a channel
|
|
105
|
-
* @param channel - the channel to unsubscribe from
|
|
106
|
-
*/
|
|
107
|
-
unsubscribeFrom(channel) {
|
|
108
|
-
__classPrivateFieldGet(this, _ConnectionResponse_engine, "f").unsubscribeFrom(__classPrivateFieldGet(this, _ConnectionResponse_clientId, "f"), channel);
|
|
109
|
-
return this;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
exports.ConnectionResponse = ConnectionResponse;
|
|
113
|
-
_ConnectionResponse_webSocket = new WeakMap(), _ConnectionResponse_engine = new WeakMap(), _ConnectionResponse_clientId = new WeakMap(), _ConnectionResponse_executed = new WeakMap(), _ConnectionResponse_assigns = new WeakMap(), _ConnectionResponse_requestId = new WeakMap(), _ConnectionResponse_instances = new WeakSet(), _ConnectionResponse_sendMessage = function _ConnectionResponse_sendMessage(action, event, payload) {
|
|
114
|
-
const message = {
|
|
115
|
-
event,
|
|
116
|
-
action,
|
|
117
|
-
payload,
|
|
118
|
-
requestId: __classPrivateFieldGet(this, _ConnectionResponse_requestId, "f"),
|
|
119
|
-
channelName: pondsocket_common_1.SystemSender.ENDPOINT,
|
|
120
|
-
};
|
|
121
|
-
__classPrivateFieldGet(this, _ConnectionResponse_engine, "f").sendMessage(__classPrivateFieldGet(this, _ConnectionResponse_webSocket, "f"), message);
|
|
122
|
-
}, _ConnectionResponse_performChecks = function _ConnectionResponse_performChecks() {
|
|
123
|
-
if (__classPrivateFieldGet(this, _ConnectionResponse_executed, "f")) {
|
|
124
|
-
const message = 'Cannot execute response more than once';
|
|
125
|
-
const code = 403;
|
|
126
|
-
throw new pondError_1.EndpointError(message, code);
|
|
127
|
-
}
|
|
128
|
-
__classPrivateFieldSet(this, _ConnectionResponse_executed, true, "f");
|
|
129
|
-
};
|
package/errors/pondError.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PresenceError = exports.ChannelError = exports.EndpointError = exports.PondError = void 0;
|
|
4
|
-
class PondError extends Error {
|
|
5
|
-
constructor(message, code) {
|
|
6
|
-
super(message);
|
|
7
|
-
this.code = code;
|
|
8
|
-
this.message = message;
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
exports.PondError = PondError;
|
|
12
|
-
class EndpointError extends PondError {
|
|
13
|
-
}
|
|
14
|
-
exports.EndpointError = EndpointError;
|
|
15
|
-
class ChannelError extends EndpointError {
|
|
16
|
-
constructor(message, code, channel) {
|
|
17
|
-
super(message, code);
|
|
18
|
-
this.channel = channel;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
exports.ChannelError = ChannelError;
|
|
22
|
-
class PresenceError extends ChannelError {
|
|
23
|
-
constructor(message, code, channel, event) {
|
|
24
|
-
super(message, code, channel);
|
|
25
|
-
this.event = event;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
exports.PresenceError = PresenceError;
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createMockSocket = void 0;
|
|
4
|
-
const joinRequest_1 = require("./joinRequest");
|
|
5
|
-
const eventResponse_test_1 = require("../channel/eventResponse.test");
|
|
6
|
-
const createMockSocket = () => {
|
|
7
|
-
const { channelEngine } = (0, eventResponse_test_1.createChannelEngine)();
|
|
8
|
-
const socket = {
|
|
9
|
-
clientId: 'sender',
|
|
10
|
-
assigns: { assign: 'assign' },
|
|
11
|
-
channelName: 'channel',
|
|
12
|
-
requestId: 'requestId',
|
|
13
|
-
subscriptions: new Map(),
|
|
14
|
-
socket: {
|
|
15
|
-
send: jest.fn(),
|
|
16
|
-
},
|
|
17
|
-
};
|
|
18
|
-
return {
|
|
19
|
-
channelEngine,
|
|
20
|
-
socket,
|
|
21
|
-
};
|
|
22
|
-
};
|
|
23
|
-
exports.createMockSocket = createMockSocket;
|
|
24
|
-
const createJoinRequest = (params = {}) => {
|
|
25
|
-
const { channelEngine, socket } = (0, exports.createMockSocket)();
|
|
26
|
-
const request = new joinRequest_1.JoinRequest(socket, params, channelEngine);
|
|
27
|
-
return {
|
|
28
|
-
channelEngine,
|
|
29
|
-
socket,
|
|
30
|
-
request,
|
|
31
|
-
};
|
|
32
|
-
};
|
|
33
|
-
describe('JoinRequest', () => {
|
|
34
|
-
it('should create a new PondChannelResponse', () => {
|
|
35
|
-
const { request } = createJoinRequest();
|
|
36
|
-
expect(request).toBeDefined();
|
|
37
|
-
});
|
|
38
|
-
it('should return the join params', () => {
|
|
39
|
-
const { request } = createJoinRequest({ params: 'params' });
|
|
40
|
-
expect(request.joinParams).toEqual({ params: 'params' });
|
|
41
|
-
});
|
|
42
|
-
it('should return the user data', () => {
|
|
43
|
-
const { request } = createJoinRequest();
|
|
44
|
-
expect(request.user).toEqual({
|
|
45
|
-
id: 'sender',
|
|
46
|
-
assigns: { assign: 'assign' },
|
|
47
|
-
presence: {},
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
});
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
|
|
4
|
-
const JoinRequest_test_1 = require("./JoinRequest.test");
|
|
5
|
-
const joinResponse_1 = require("./joinResponse");
|
|
6
|
-
const createPondResponse = () => {
|
|
7
|
-
const { channelEngine, socket } = (0, JoinRequest_test_1.createMockSocket)();
|
|
8
|
-
const response = new joinResponse_1.JoinResponse(socket, channelEngine);
|
|
9
|
-
return {
|
|
10
|
-
channelEngine,
|
|
11
|
-
socket,
|
|
12
|
-
response,
|
|
13
|
-
};
|
|
14
|
-
};
|
|
15
|
-
describe('JoinResponse', () => {
|
|
16
|
-
it('should create a new PondChannelResponse', () => {
|
|
17
|
-
const { response } = createPondResponse();
|
|
18
|
-
expect(response).toBeDefined();
|
|
19
|
-
});
|
|
20
|
-
it('should accept the request', () => {
|
|
21
|
-
const { response, channelEngine, socket } = createPondResponse();
|
|
22
|
-
// spy on the channelEngine to see if the user was added
|
|
23
|
-
jest.spyOn(channelEngine, 'addUser');
|
|
24
|
-
response.accept();
|
|
25
|
-
// check if the response was sent
|
|
26
|
-
expect(channelEngine.addUser).toHaveBeenCalledWith(socket.clientId, socket.assigns, expect.any(Function));
|
|
27
|
-
expect(channelEngine.getUserData(socket.clientId)).not.toBeNull();
|
|
28
|
-
});
|
|
29
|
-
it('should reject the request', () => {
|
|
30
|
-
const { response, channelEngine, socket } = createPondResponse();
|
|
31
|
-
// spy on the channelEngine to see if the user was added
|
|
32
|
-
jest.spyOn(channelEngine, 'addUser');
|
|
33
|
-
response.decline();
|
|
34
|
-
// check if the response was sent
|
|
35
|
-
expect(channelEngine.addUser).not.toHaveBeenCalled();
|
|
36
|
-
expect(channelEngine.getUserData(socket.clientId)).toBeUndefined();
|
|
37
|
-
// also check if the socket was sent a message
|
|
38
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
39
|
-
// @ts-expect-error - we are mocking the socket
|
|
40
|
-
const params = socket.socket.send.mock.calls[0][0];
|
|
41
|
-
expect(JSON.parse(params)).toEqual(expect.objectContaining({
|
|
42
|
-
event: pondsocket_common_1.ErrorTypes.UNAUTHORIZED_JOIN_REQUEST,
|
|
43
|
-
payload: {
|
|
44
|
-
message: 'Unauthorized connection',
|
|
45
|
-
code: 401,
|
|
46
|
-
},
|
|
47
|
-
channelName: 'test',
|
|
48
|
-
action: pondsocket_common_1.ServerActions.ERROR,
|
|
49
|
-
}));
|
|
50
|
-
});
|
|
51
|
-
it('should send a direct message', () => {
|
|
52
|
-
const { response, channelEngine, socket } = createPondResponse();
|
|
53
|
-
// spy on the channelEngine to see if the user was added
|
|
54
|
-
jest.spyOn(channelEngine, 'addUser');
|
|
55
|
-
const endpoint = channelEngine.parent.parent;
|
|
56
|
-
jest.spyOn(endpoint, 'sendMessage');
|
|
57
|
-
response
|
|
58
|
-
.accept()
|
|
59
|
-
.reply('POND_MESSAGE', { message: 'message' })
|
|
60
|
-
.assign({ assign: 'assign' });
|
|
61
|
-
expect(channelEngine.addUser).toHaveBeenCalled();
|
|
62
|
-
// check if the response was sent
|
|
63
|
-
expect(channelEngine.getUserData(socket.clientId)).toStrictEqual({
|
|
64
|
-
assigns: {
|
|
65
|
-
assign: 'assign',
|
|
66
|
-
},
|
|
67
|
-
id: 'sender',
|
|
68
|
-
presence: {},
|
|
69
|
-
});
|
|
70
|
-
// also check if the socket was sent a message
|
|
71
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
72
|
-
// @ts-expect-error - we are mocking the socket
|
|
73
|
-
const first = endpoint.sendMessage.mock.calls[0][1];
|
|
74
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
75
|
-
// @ts-expect-error - we are mocking the socket
|
|
76
|
-
const params = endpoint.sendMessage.mock.calls[1][1];
|
|
77
|
-
expect(first).toEqual(expect.objectContaining({
|
|
78
|
-
channelName: 'test',
|
|
79
|
-
action: pondsocket_common_1.ServerActions.SYSTEM,
|
|
80
|
-
payload: {},
|
|
81
|
-
event: pondsocket_common_1.Events.ACKNOWLEDGE,
|
|
82
|
-
}));
|
|
83
|
-
expect(params).toEqual(expect.objectContaining({
|
|
84
|
-
channelName: 'test',
|
|
85
|
-
action: pondsocket_common_1.ServerActions.SYSTEM,
|
|
86
|
-
payload: {
|
|
87
|
-
message: 'message',
|
|
88
|
-
},
|
|
89
|
-
event: 'POND_MESSAGE',
|
|
90
|
-
}));
|
|
91
|
-
});
|
|
92
|
-
// auxiliary functions
|
|
93
|
-
it('should send messages to different users', () => {
|
|
94
|
-
const { response, channelEngine } = createPondResponse();
|
|
95
|
-
// spy on the channelEngine to see if any messages were published
|
|
96
|
-
const broadcast = jest.spyOn(channelEngine, 'sendMessage');
|
|
97
|
-
const receiver = jest.fn();
|
|
98
|
-
// add a second user to the channel
|
|
99
|
-
channelEngine.addUser('user2', { assign: 'assign' }, receiver);
|
|
100
|
-
// send a message to a single user
|
|
101
|
-
// this is because the sender does not exist in the channel yet
|
|
102
|
-
expect(() => response.broadcastTo('hello_everyone', { message: 'hello' }, ['user2'])).toThrow();
|
|
103
|
-
// clear the spy
|
|
104
|
-
broadcast.mockClear();
|
|
105
|
-
// add the sender to the channel by using the response.accept() method
|
|
106
|
-
response.accept().broadcastTo('hello_everyone', { message: 'hello' }, ['user2']);
|
|
107
|
-
// check if the message was sent
|
|
108
|
-
expect(broadcast).toHaveBeenCalledWith('sender', ['user2'], pondsocket_common_1.ServerActions.BROADCAST, 'hello_everyone', { message: 'hello' }, 'requestId');
|
|
109
|
-
// clear the spy
|
|
110
|
-
broadcast.mockClear();
|
|
111
|
-
// send a message to all users
|
|
112
|
-
response.broadcast('hello_everyone', { message: 'hello' });
|
|
113
|
-
expect(broadcast).toHaveBeenCalledWith('sender', pondsocket_common_1.ChannelReceiver.ALL_USERS, pondsocket_common_1.ServerActions.BROADCAST, 'hello_everyone', { message: 'hello' }, 'requestId');
|
|
114
|
-
// clear the spy
|
|
115
|
-
broadcast.mockClear();
|
|
116
|
-
// send a message to all users except the sender
|
|
117
|
-
response.broadcastFrom('hello_everyone', { message: 'hello' });
|
|
118
|
-
expect(broadcast).toHaveBeenCalledWith('sender', pondsocket_common_1.ChannelReceiver.ALL_EXCEPT_SENDER, pondsocket_common_1.ServerActions.BROADCAST, 'hello_everyone', { message: 'hello' }, 'requestId');
|
|
119
|
-
});
|
|
120
|
-
it('should be able to track the presence of users', () => {
|
|
121
|
-
const { response, channelEngine } = createPondResponse();
|
|
122
|
-
// spy on the channelEngine to see if the trackPresence method was called
|
|
123
|
-
const trackPresence = jest.spyOn(channelEngine.presenceEngine, 'trackPresence');
|
|
124
|
-
// add a second user to the channel
|
|
125
|
-
response.accept()
|
|
126
|
-
.trackPresence({
|
|
127
|
-
status: 'online',
|
|
128
|
-
});
|
|
129
|
-
// check if the trackPresence method was called
|
|
130
|
-
expect(trackPresence).toHaveBeenCalledWith('sender', { status: 'online' });
|
|
131
|
-
});
|
|
132
|
-
it('should throw an error if accept, reject / send is called more than once', () => {
|
|
133
|
-
const { response, channelEngine, socket } = createPondResponse();
|
|
134
|
-
jest.spyOn(channelEngine, 'addUser');
|
|
135
|
-
expect(channelEngine.addUser).not.toHaveBeenCalled();
|
|
136
|
-
response.accept();
|
|
137
|
-
expect(channelEngine.addUser).toHaveBeenCalledWith(socket.clientId, socket.assigns, expect.any(Function));
|
|
138
|
-
expect(() => response.accept()).toThrow('Request to join channel test rejected: Request already executed');
|
|
139
|
-
expect(() => response.decline()).toThrow('Request to join channel test rejected: Request already executed');
|
|
140
|
-
expect(() => response.reply('event', { payload: 'payload' })).not.toThrow();
|
|
141
|
-
});
|
|
142
|
-
});
|
package/lobby/joinRequest.js
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
3
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
4
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
5
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
6
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
7
|
-
};
|
|
8
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
9
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
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
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
|
-
};
|
|
13
|
-
var _JoinRequest_params, _JoinRequest_clientId, _JoinRequest_assigns;
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.JoinRequest = void 0;
|
|
16
|
-
const abstractRequest_1 = require("../abstracts/abstractRequest");
|
|
17
|
-
const channel_1 = require("../channel/channel");
|
|
18
|
-
class JoinRequest extends abstractRequest_1.AbstractRequest {
|
|
19
|
-
constructor(event, params, engine) {
|
|
20
|
-
super(engine.name, engine, params);
|
|
21
|
-
_JoinRequest_params.set(this, void 0);
|
|
22
|
-
_JoinRequest_clientId.set(this, void 0);
|
|
23
|
-
_JoinRequest_assigns.set(this, void 0);
|
|
24
|
-
__classPrivateFieldSet(this, _JoinRequest_params, params, "f");
|
|
25
|
-
__classPrivateFieldSet(this, _JoinRequest_clientId, event.clientId, "f");
|
|
26
|
-
__classPrivateFieldSet(this, _JoinRequest_assigns, event.assigns, "f");
|
|
27
|
-
}
|
|
28
|
-
get joinParams() {
|
|
29
|
-
return __classPrivateFieldGet(this, _JoinRequest_params, "f");
|
|
30
|
-
}
|
|
31
|
-
get user() {
|
|
32
|
-
return {
|
|
33
|
-
id: __classPrivateFieldGet(this, _JoinRequest_clientId, "f"),
|
|
34
|
-
assigns: __classPrivateFieldGet(this, _JoinRequest_assigns, "f"),
|
|
35
|
-
presence: {},
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
get channel() {
|
|
39
|
-
return new channel_1.Channel(this._engine);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
exports.JoinRequest = JoinRequest;
|
|
43
|
-
_JoinRequest_params = new WeakMap(), _JoinRequest_clientId = new WeakMap(), _JoinRequest_assigns = new WeakMap();
|
package/lobby/lobby.js
DELETED
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
3
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
4
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
5
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
6
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
7
|
-
};
|
|
8
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
9
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
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
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
|
-
};
|
|
13
|
-
var _LobbyEngine_instances, _LobbyEngine_channels, _LobbyEngine_middleware, _LobbyEngine_leaveCallback, _LobbyEngine_parentEngine, _LobbyEngine_path, _LobbyEngine_performAction, _PondChannel_lobby;
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.PondChannel = exports.LobbyEngine = void 0;
|
|
16
|
-
const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
|
|
17
|
-
const middleware_1 = require("../abstracts/middleware");
|
|
18
|
-
const channel_1 = require("../channel/channel");
|
|
19
|
-
const pondError_1 = require("../errors/pondError");
|
|
20
|
-
const matcher_1 = require("../matcher/matcher");
|
|
21
|
-
class LobbyEngine {
|
|
22
|
-
constructor(endpointEngine, path) {
|
|
23
|
-
_LobbyEngine_instances.add(this);
|
|
24
|
-
_LobbyEngine_channels.set(this, void 0);
|
|
25
|
-
_LobbyEngine_middleware.set(this, void 0);
|
|
26
|
-
_LobbyEngine_leaveCallback.set(this, void 0);
|
|
27
|
-
_LobbyEngine_parentEngine.set(this, void 0);
|
|
28
|
-
_LobbyEngine_path.set(this, void 0);
|
|
29
|
-
__classPrivateFieldSet(this, _LobbyEngine_parentEngine, endpointEngine, "f");
|
|
30
|
-
__classPrivateFieldSet(this, _LobbyEngine_channels, new Set(), "f");
|
|
31
|
-
__classPrivateFieldSet(this, _LobbyEngine_middleware, new middleware_1.Middleware(), "f");
|
|
32
|
-
__classPrivateFieldSet(this, _LobbyEngine_path, path, "f");
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* @desc The parent engine
|
|
36
|
-
*/
|
|
37
|
-
get parent() {
|
|
38
|
-
return __classPrivateFieldGet(this, _LobbyEngine_parentEngine, "f");
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* @desc The leave callback
|
|
42
|
-
*/
|
|
43
|
-
get leaveCallback() {
|
|
44
|
-
return __classPrivateFieldGet(this, _LobbyEngine_leaveCallback, "f");
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* @desc The middleware to use
|
|
48
|
-
*/
|
|
49
|
-
get middleware() {
|
|
50
|
-
return __classPrivateFieldGet(this, _LobbyEngine_middleware, "f");
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* @desc Handles an event request made by a user
|
|
54
|
-
* @param event - The event to listen for
|
|
55
|
-
* @param handler - The handler to execute when the event is received
|
|
56
|
-
* @example
|
|
57
|
-
* pond.onEvent('echo', (request, response) => {
|
|
58
|
-
* response.send('echo', {
|
|
59
|
-
* message: request.event.payload,
|
|
60
|
-
* });
|
|
61
|
-
* });
|
|
62
|
-
*/
|
|
63
|
-
onEvent(event, handler) {
|
|
64
|
-
__classPrivateFieldGet(this, _LobbyEngine_middleware, "f").use((request, response, next) => {
|
|
65
|
-
if (request._parseQueries(event)) {
|
|
66
|
-
return handler(request, response);
|
|
67
|
-
}
|
|
68
|
-
next();
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* @desc Handles the leave event for a user, can occur when a user disconnects or leaves a channel, use this to clean up any resources
|
|
73
|
-
* @param callback - The callback to execute when a user leaves
|
|
74
|
-
*/
|
|
75
|
-
onLeave(callback) {
|
|
76
|
-
__classPrivateFieldSet(this, _LobbyEngine_leaveCallback, callback, "f");
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* @desc Gets a channel by name
|
|
80
|
-
* @param channelName - The name of the channel to get
|
|
81
|
-
* @private
|
|
82
|
-
*/
|
|
83
|
-
getChannel(channelName) {
|
|
84
|
-
return Array.from(__classPrivateFieldGet(this, _LobbyEngine_channels, "f"))
|
|
85
|
-
.find((channel) => channel.name === channelName);
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* @desc Destroys a channel
|
|
89
|
-
* @param channel - The name of the channel to destroy
|
|
90
|
-
* @private
|
|
91
|
-
*/
|
|
92
|
-
destroyChannel(channel) {
|
|
93
|
-
const newChannel = this.getChannel(channel);
|
|
94
|
-
if (newChannel) {
|
|
95
|
-
__classPrivateFieldGet(this, _LobbyEngine_channels, "f").delete(newChannel);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* @desc Creates a new channel
|
|
100
|
-
* @param channelName - The name of the channel to create
|
|
101
|
-
* @private
|
|
102
|
-
*/
|
|
103
|
-
createChannel(channelName) {
|
|
104
|
-
const newChannel = new channel_1.ChannelEngine(channelName, this);
|
|
105
|
-
__classPrivateFieldGet(this, _LobbyEngine_channels, "f").add(newChannel);
|
|
106
|
-
return newChannel;
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* @desc Sends a message to all clients in the channel
|
|
110
|
-
* @param channelName - the name of the channel to send the message to
|
|
111
|
-
* @param event - the event to send
|
|
112
|
-
* @param payload - the payload to send
|
|
113
|
-
*/
|
|
114
|
-
broadcast(channelName, event, payload) {
|
|
115
|
-
__classPrivateFieldGet(this, _LobbyEngine_instances, "m", _LobbyEngine_performAction).call(this, channelName, (channel) => {
|
|
116
|
-
channel.sendMessage(pondsocket_common_1.SystemSender.CHANNEL, pondsocket_common_1.ChannelReceiver.ALL_USERS, pondsocket_common_1.ServerActions.BROADCAST, event, payload);
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* @desc Sends a message to all clients in the channel except the client making the request
|
|
121
|
-
* @param channelName - the name of the channel to send the message to
|
|
122
|
-
* @param event - the event to send
|
|
123
|
-
* @param payload - the payload to send
|
|
124
|
-
*/
|
|
125
|
-
broadcastFrom(channelName, event, payload) {
|
|
126
|
-
__classPrivateFieldGet(this, _LobbyEngine_instances, "m", _LobbyEngine_performAction).call(this, channelName, (channel) => {
|
|
127
|
-
channel.sendMessage(pondsocket_common_1.SystemSender.CHANNEL, pondsocket_common_1.ChannelReceiver.ALL_EXCEPT_SENDER, pondsocket_common_1.ServerActions.BROADCAST, event, payload);
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* @desc Sends a message to a set of clients in the channel
|
|
132
|
-
* @param channelName - the name of the channel to send the message to
|
|
133
|
-
* @param event - the event to send
|
|
134
|
-
* @param payload - the payload to send
|
|
135
|
-
* @param userIds - the ids of the clients to send the message to
|
|
136
|
-
*/
|
|
137
|
-
broadcastTo(channelName, event, payload, userIds) {
|
|
138
|
-
const ids = Array.isArray(userIds) ? userIds : [userIds];
|
|
139
|
-
__classPrivateFieldGet(this, _LobbyEngine_instances, "m", _LobbyEngine_performAction).call(this, channelName, (channel) => {
|
|
140
|
-
channel.sendMessage(pondsocket_common_1.SystemSender.CHANNEL, ids, pondsocket_common_1.ServerActions.BROADCAST, event, payload);
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
exports.LobbyEngine = LobbyEngine;
|
|
145
|
-
_LobbyEngine_channels = new WeakMap(), _LobbyEngine_middleware = new WeakMap(), _LobbyEngine_leaveCallback = new WeakMap(), _LobbyEngine_parentEngine = new WeakMap(), _LobbyEngine_path = new WeakMap(), _LobbyEngine_instances = new WeakSet(), _LobbyEngine_performAction = function _LobbyEngine_performAction(channelName, handler) {
|
|
146
|
-
const matches = (0, matcher_1.parseAddress)(__classPrivateFieldGet(this, _LobbyEngine_path, "f"), channelName);
|
|
147
|
-
if (matches === null) {
|
|
148
|
-
throw new pondError_1.EndpointError('Invalid channel name', 402);
|
|
149
|
-
}
|
|
150
|
-
const channel = this.getChannel(channelName) || this.createChannel(channelName);
|
|
151
|
-
const assigns = channel.getAssigns();
|
|
152
|
-
handler(channel);
|
|
153
|
-
if (Object.keys(assigns).length === 0) {
|
|
154
|
-
this.destroyChannel(channelName);
|
|
155
|
-
}
|
|
156
|
-
};
|
|
157
|
-
class PondChannel {
|
|
158
|
-
constructor(lobby) {
|
|
159
|
-
_PondChannel_lobby.set(this, void 0);
|
|
160
|
-
__classPrivateFieldSet(this, _PondChannel_lobby, lobby, "f");
|
|
161
|
-
}
|
|
162
|
-
onEvent(event, handler) {
|
|
163
|
-
__classPrivateFieldGet(this, _PondChannel_lobby, "f").onEvent(event, handler);
|
|
164
|
-
}
|
|
165
|
-
onLeave(callback) {
|
|
166
|
-
__classPrivateFieldGet(this, _PondChannel_lobby, "f").onLeave(callback);
|
|
167
|
-
}
|
|
168
|
-
getChannel(channelName) {
|
|
169
|
-
const channel = __classPrivateFieldGet(this, _PondChannel_lobby, "f").getChannel(channelName);
|
|
170
|
-
if (channel) {
|
|
171
|
-
return new channel_1.Channel(channel);
|
|
172
|
-
}
|
|
173
|
-
return null;
|
|
174
|
-
}
|
|
175
|
-
broadcast(channelName, event, payload) {
|
|
176
|
-
__classPrivateFieldGet(this, _PondChannel_lobby, "f").broadcast(channelName, event, payload);
|
|
177
|
-
}
|
|
178
|
-
broadcastFrom(channelName, event, payload) {
|
|
179
|
-
__classPrivateFieldGet(this, _PondChannel_lobby, "f").broadcastFrom(channelName, event, payload);
|
|
180
|
-
}
|
|
181
|
-
broadcastTo(channelName, event, payload, userIds) {
|
|
182
|
-
__classPrivateFieldGet(this, _PondChannel_lobby, "f").broadcastTo(channelName, event, payload, userIds);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
exports.PondChannel = PondChannel;
|
|
186
|
-
_PondChannel_lobby = new WeakMap();
|
package/matcher/matcher.test.js
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const matcher_1 = require("./matcher");
|
|
4
|
-
describe('parseAddress', () => {
|
|
5
|
-
it('should return null if a string does not match a regex and {} if it does', () => {
|
|
6
|
-
const regex = new RegExp(/^test/);
|
|
7
|
-
expect((0, matcher_1.parseAddress)(regex, 'test')).toStrictEqual({
|
|
8
|
-
params: {},
|
|
9
|
-
query: {},
|
|
10
|
-
});
|
|
11
|
-
const regex2 = new RegExp(/^test2/);
|
|
12
|
-
expect((0, matcher_1.parseAddress)(regex2, 'test')).toBe(null);
|
|
13
|
-
});
|
|
14
|
-
it('should return the params of a string matching the pattern', () => {
|
|
15
|
-
const pattern = '/test/:id';
|
|
16
|
-
const secondPattern = '/test/:id/:id2';
|
|
17
|
-
const string = '/test/5';
|
|
18
|
-
const secondString = '/test/5/6';
|
|
19
|
-
expect((0, matcher_1.parseAddress)(pattern, string))
|
|
20
|
-
.toStrictEqual({
|
|
21
|
-
params: {
|
|
22
|
-
id: '5',
|
|
23
|
-
},
|
|
24
|
-
query: {},
|
|
25
|
-
});
|
|
26
|
-
expect((0, matcher_1.parseAddress)(secondPattern, secondString))
|
|
27
|
-
.toStrictEqual({
|
|
28
|
-
params: {
|
|
29
|
-
id: '5',
|
|
30
|
-
id2: '6',
|
|
31
|
-
},
|
|
32
|
-
query: {},
|
|
33
|
-
});
|
|
34
|
-
expect((0, matcher_1.parseAddress)(pattern, secondString))
|
|
35
|
-
.toBe(null);
|
|
36
|
-
expect((0, matcher_1.parseAddress)(secondPattern, string))
|
|
37
|
-
.toBe(null);
|
|
38
|
-
});
|
|
39
|
-
it('should not match colons without slashes', () => {
|
|
40
|
-
const pattern = '/test:id';
|
|
41
|
-
const string = '/test5';
|
|
42
|
-
expect((0, matcher_1.parseAddress)(pattern, string))
|
|
43
|
-
.toBe(null);
|
|
44
|
-
});
|
|
45
|
-
it('should match when there is a *', () => {
|
|
46
|
-
const pattern = '/test/:id/*';
|
|
47
|
-
const string = '/test/5/6';
|
|
48
|
-
expect((0, matcher_1.parseAddress)(pattern, string))
|
|
49
|
-
.toStrictEqual({
|
|
50
|
-
params: {
|
|
51
|
-
id: '5',
|
|
52
|
-
'*': '/6',
|
|
53
|
-
},
|
|
54
|
-
query: {},
|
|
55
|
-
});
|
|
56
|
-
const secondPattern = '*';
|
|
57
|
-
const secondString = '/test/5/6';
|
|
58
|
-
expect((0, matcher_1.parseAddress)(secondPattern, secondString))
|
|
59
|
-
.toStrictEqual({
|
|
60
|
-
params: {
|
|
61
|
-
'*': '/test/5/6',
|
|
62
|
-
},
|
|
63
|
-
query: {},
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
it('should return the query of string', () => {
|
|
67
|
-
const pattern = '/test/:id';
|
|
68
|
-
const string = '/test/5?test=5';
|
|
69
|
-
const secondString = '/test/5?test=5&test2=6';
|
|
70
|
-
expect((0, matcher_1.parseAddress)(pattern, string))
|
|
71
|
-
.toStrictEqual({
|
|
72
|
-
params: {
|
|
73
|
-
id: '5',
|
|
74
|
-
},
|
|
75
|
-
query: {
|
|
76
|
-
test: '5',
|
|
77
|
-
},
|
|
78
|
-
});
|
|
79
|
-
expect((0, matcher_1.parseAddress)(pattern, secondString))
|
|
80
|
-
.toStrictEqual({
|
|
81
|
-
params: {
|
|
82
|
-
id: '5',
|
|
83
|
-
},
|
|
84
|
-
query: {
|
|
85
|
-
test: '5',
|
|
86
|
-
test2: '6',
|
|
87
|
-
},
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
});
|