@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.
Files changed (41) hide show
  1. package/abstracts/middleware.js +40 -17
  2. package/abstracts/redisClient.js +278 -0
  3. package/engines/channelEngine.js +163 -0
  4. package/engines/endpointEngine.js +163 -0
  5. package/engines/lobbyEngine.js +79 -0
  6. package/errors/httpError.js +11 -0
  7. package/index.js +2 -2
  8. package/managers/distributedManager.js +115 -0
  9. package/managers/localManager.js +41 -0
  10. package/managers/manager.js +219 -0
  11. package/managers/managerFactory.js +31 -0
  12. package/package.json +24 -14
  13. package/requests/eventRequest.js +51 -0
  14. package/requests/joinRequest.js +56 -0
  15. package/responses/connectionResponse.js +89 -0
  16. package/{channel → responses}/eventResponse.js +8 -79
  17. package/{lobby → responses}/joinResponse.js +25 -84
  18. package/server/{pondSocket.js → server.js} +55 -55
  19. package/types.d.ts +33 -106
  20. package/wrappers/channel.js +70 -0
  21. package/wrappers/endpoint.js +32 -0
  22. package/wrappers/pondChannel.js +48 -0
  23. package/abstracts/abstractRequest.js +0 -57
  24. package/abstracts/abstractRequest.test.js +0 -48
  25. package/abstracts/middleware.test.js +0 -70
  26. package/channel/channel.js +0 -351
  27. package/channel/channel.test.js +0 -435
  28. package/channel/eventRequest.js +0 -25
  29. package/channel/eventRequest.test.js +0 -30
  30. package/channel/eventResponse.test.js +0 -175
  31. package/endpoint/endpoint.js +0 -299
  32. package/endpoint/endpoint.test.js +0 -299
  33. package/endpoint/response.js +0 -129
  34. package/errors/pondError.js +0 -28
  35. package/lobby/JoinRequest.test.js +0 -50
  36. package/lobby/JoinResponse.test.js +0 -142
  37. package/lobby/joinRequest.js +0 -43
  38. package/lobby/lobby.js +0 -186
  39. package/matcher/matcher.test.js +0 -90
  40. package/presence/presence.js +0 -112
  41. package/presence/presenceEngine.test.js +0 -129
@@ -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
- };
@@ -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
- });
@@ -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();
@@ -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
- });