@eleven-am/pondsocket 0.1.126 → 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.
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const joinRequest_1 = require("./joinRequest");
4
+ const eventResponse_test_1 = require("../channel/eventResponse.test");
5
+ const createMockSocket = (params = {}) => {
6
+ const channelEngine = (0, eventResponse_test_1.createChannelEngine)();
7
+ const socket = {
8
+ clientId: 'sender',
9
+ assigns: { assign: 'assign' },
10
+ requestId: 'requestId',
11
+ channelName: 'channel',
12
+ socket: {
13
+ send: jest.fn(),
14
+ },
15
+ };
16
+ const request = new joinRequest_1.JoinRequest(socket, params, channelEngine);
17
+ return {
18
+ channelEngine,
19
+ socket,
20
+ request,
21
+ };
22
+ };
23
+ describe('JoinRequest', () => {
24
+ it('should create a new PondChannelResponse', () => {
25
+ const { request } = createMockSocket();
26
+ expect(request).toBeDefined();
27
+ });
28
+ it('should return the join params', () => {
29
+ const { request } = createMockSocket({ params: 'params' });
30
+ expect(request.joinParams).toEqual({ params: 'params' });
31
+ });
32
+ it('should return the user data', () => {
33
+ const { request } = createMockSocket();
34
+ expect(request.user).toEqual({
35
+ id: 'sender',
36
+ assigns: { assign: 'assign' },
37
+ presence: {},
38
+ });
39
+ });
40
+ });
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
4
+ const joinResponse_1 = require("./joinResponse");
5
+ const eventResponse_test_1 = require("../channel/eventResponse.test");
6
+ const createPondResponse = () => {
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
+ socket: {
14
+ send: jest.fn(),
15
+ },
16
+ };
17
+ const response = new joinResponse_1.JoinResponse(socket, channelEngine);
18
+ return {
19
+ channelEngine,
20
+ socket,
21
+ response,
22
+ };
23
+ };
24
+ describe('JoinResponse', () => {
25
+ it('should create a new PondChannelResponse', () => {
26
+ const { response } = createPondResponse();
27
+ expect(response).toBeDefined();
28
+ });
29
+ it('should accept 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.accept();
34
+ // check if the response was sent
35
+ expect(channelEngine.addUser).toHaveBeenCalledWith(socket.clientId, socket.assigns, expect.any(Function));
36
+ expect(channelEngine.getUserData(socket.clientId)).not.toBeNull();
37
+ });
38
+ it('should reject the request', () => {
39
+ const { response, channelEngine, socket } = createPondResponse();
40
+ // spy on the channelEngine to see if the user was added
41
+ jest.spyOn(channelEngine, 'addUser');
42
+ response.reject();
43
+ // check if the response was sent
44
+ expect(channelEngine.addUser).not.toHaveBeenCalled();
45
+ expect(channelEngine.getUserData(socket.clientId)).toBeUndefined();
46
+ // also check if the socket was sent a message
47
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
48
+ // @ts-expect-error - we are mocking the socket
49
+ const params = socket.socket.send.mock.calls[0][0];
50
+ expect(JSON.parse(params)).toEqual(expect.objectContaining({
51
+ event: pondsocket_common_1.ErrorTypes.UNAUTHORIZED_JOIN_REQUEST,
52
+ payload: {
53
+ message: 'Unauthorized connection',
54
+ code: 401,
55
+ },
56
+ channelName: 'test',
57
+ action: pondsocket_common_1.ServerActions.ERROR,
58
+ }));
59
+ });
60
+ it('should send a direct message', () => {
61
+ const { response, channelEngine, socket } = createPondResponse();
62
+ // spy on the channelEngine to see if the user was added
63
+ jest.spyOn(channelEngine, 'addUser');
64
+ response.send('POND_MESSAGE', { message: 'message' });
65
+ // check if the response was sent
66
+ expect(channelEngine.addUser).toHaveBeenCalled();
67
+ expect(channelEngine.getUserData(socket.clientId)).toStrictEqual({
68
+ assigns: {
69
+ assign: 'assign',
70
+ },
71
+ id: 'sender',
72
+ presence: {},
73
+ });
74
+ // also check if the socket was sent a message
75
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
76
+ // @ts-expect-error - we are mocking the socket
77
+ const first = socket.socket.send.mock.calls[0][0];
78
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
79
+ // @ts-expect-error - we are mocking the socket
80
+ const params = socket.socket.send.mock.calls[1][0];
81
+ expect(JSON.parse(params)).toEqual(expect.objectContaining({
82
+ channelName: 'test',
83
+ action: pondsocket_common_1.ServerActions.SYSTEM,
84
+ payload: {
85
+ message: 'message',
86
+ },
87
+ event: 'POND_MESSAGE',
88
+ }));
89
+ expect(JSON.parse(first)).toEqual(expect.objectContaining({
90
+ channelName: 'test',
91
+ action: pondsocket_common_1.ServerActions.SYSTEM,
92
+ payload: {},
93
+ event: pondsocket_common_1.Events.ACKNOWLEDGE,
94
+ }));
95
+ });
96
+ // auxiliary functions
97
+ it('should send messages to different users', () => {
98
+ const { response, channelEngine } = createPondResponse();
99
+ // spy on the channelEngine to see if any messages were published
100
+ const broadcast = jest.spyOn(channelEngine, 'sendMessage');
101
+ // add a second user to the channel
102
+ channelEngine.addUser('user2', { assign: 'assign' }, () => { });
103
+ // send a message to a single user
104
+ // this is because the sender does not exist in the channel yet
105
+ expect(() => response.sendToUsers('hello_everyone', { message: 'hello' }, ['user2'])).toThrow();
106
+ // clear the spy
107
+ broadcast.mockClear();
108
+ // add the sender to the channel by using the response.accept() method
109
+ response.accept().sendToUsers('hello_everyone', { message: 'hello' }, ['user2']);
110
+ // check if the message was sent
111
+ expect(broadcast).toHaveBeenCalledWith('requestId', 'sender', ['user2'], pondsocket_common_1.ServerActions.BROADCAST, 'hello_everyone', { message: 'hello' });
112
+ // clear the spy
113
+ broadcast.mockClear();
114
+ // send a message to all users
115
+ response.broadcast('hello_everyone', { message: 'hello' });
116
+ expect(broadcast).toHaveBeenCalledWith('requestId', 'sender', pondsocket_common_1.ChannelReceiver.ALL_USERS, pondsocket_common_1.ServerActions.BROADCAST, 'hello_everyone', { message: 'hello' });
117
+ // clear the spy
118
+ broadcast.mockClear();
119
+ // send a message to all users except the sender
120
+ response.broadcastFromUser('hello_everyone', { message: 'hello' });
121
+ expect(broadcast).toHaveBeenCalledWith('requestId', 'sender', pondsocket_common_1.ChannelReceiver.ALL_EXCEPT_SENDER, pondsocket_common_1.ServerActions.BROADCAST, 'hello_everyone', { message: 'hello' });
122
+ });
123
+ it('should be able to track the presence of users', () => {
124
+ const { response, channelEngine } = createPondResponse();
125
+ // spy on the channelEngine to see if the trackPresence method was called
126
+ const trackPresence = jest.spyOn(channelEngine.presenceEngine, 'trackPresence');
127
+ // add a second user to the channel
128
+ response.accept()
129
+ .trackPresence({
130
+ status: 'online',
131
+ });
132
+ // check if the trackPresence method was called
133
+ expect(trackPresence).toHaveBeenCalledWith('sender', { status: 'online' });
134
+ });
135
+ it('should throw an error if accept, reject / send is called more than once', () => {
136
+ const { response, channelEngine, socket } = createPondResponse();
137
+ jest.spyOn(channelEngine, 'addUser');
138
+ expect(channelEngine.addUser).not.toHaveBeenCalled();
139
+ response.accept();
140
+ expect(channelEngine.addUser).toHaveBeenCalledWith(socket.clientId, socket.assigns, expect.any(Function));
141
+ expect(() => response.accept()).toThrow('Request to join channel test rejected: Request already executed');
142
+ expect(() => response.reject()).toThrow('Request to join channel test rejected: Request already executed');
143
+ expect(() => response.send('event', { payload: 'payload' })).toThrow('Request to join channel test rejected: Request already executed');
144
+ });
145
+ });
@@ -13,8 +13,8 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
13
13
  var _JoinResponse_instances, _JoinResponse_user, _JoinResponse_engine, _JoinResponse_executed, _JoinResponse_performChecks;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.JoinResponse = void 0;
16
+ const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
16
17
  const abstractResponse_1 = require("../abstracts/abstractResponse");
17
- const enums_1 = require("../enums");
18
18
  const pondError_1 = require("../errors/pondError");
19
19
  class JoinResponse extends abstractResponse_1.PondResponse {
20
20
  constructor(user, engine) {
@@ -41,9 +41,9 @@ class JoinResponse extends abstractResponse_1.PondResponse {
41
41
  __classPrivateFieldGet(this, _JoinResponse_instances, "m", _JoinResponse_performChecks).call(this);
42
42
  const newAssigns = Object.assign(Object.assign({}, assigns || {}), __classPrivateFieldGet(this, _JoinResponse_user, "f").assigns);
43
43
  const acknowledgement = {
44
- action: enums_1.ServerActions.SYSTEM,
44
+ action: pondsocket_common_1.ServerActions.SYSTEM,
45
45
  channelName: __classPrivateFieldGet(this, _JoinResponse_engine, "f").name,
46
- event: enums_1.Events.ACKNOWLEDGE,
46
+ event: pondsocket_common_1.Events.ACKNOWLEDGE,
47
47
  requestId: this.requestId,
48
48
  payload: {},
49
49
  };
@@ -61,13 +61,13 @@ class JoinResponse extends abstractResponse_1.PondResponse {
61
61
  reject(message, errorCode) {
62
62
  __classPrivateFieldGet(this, _JoinResponse_instances, "m", _JoinResponse_performChecks).call(this);
63
63
  const errorMessage = {
64
- event: enums_1.ErrorTypes.UNAUTHORIZED_JOIN_REQUEST,
64
+ event: pondsocket_common_1.ErrorTypes.UNAUTHORIZED_JOIN_REQUEST,
65
65
  payload: {
66
66
  message: message || 'Unauthorized connection',
67
67
  code: errorCode || 401,
68
68
  },
69
69
  channelName: __classPrivateFieldGet(this, _JoinResponse_engine, "f").name,
70
- action: enums_1.ServerActions.ERROR,
70
+ action: pondsocket_common_1.ServerActions.ERROR,
71
71
  requestId: this.requestId,
72
72
  };
73
73
  __classPrivateFieldGet(this, _JoinResponse_user, "f").socket.send(JSON.stringify(errorMessage));
@@ -81,7 +81,7 @@ class JoinResponse extends abstractResponse_1.PondResponse {
81
81
  */
82
82
  send(event, payload, assigns) {
83
83
  this.accept(assigns);
84
- __classPrivateFieldGet(this, _JoinResponse_engine, "f").sendMessage(this.requestId, enums_1.SystemSender.CHANNEL, [__classPrivateFieldGet(this, _JoinResponse_user, "f").clientId], enums_1.ServerActions.SYSTEM, event, payload);
84
+ __classPrivateFieldGet(this, _JoinResponse_engine, "f").sendMessage(this.requestId, pondsocket_common_1.SystemSender.CHANNEL, [__classPrivateFieldGet(this, _JoinResponse_user, "f").clientId], pondsocket_common_1.ServerActions.SYSTEM, event, payload);
85
85
  return this;
86
86
  }
87
87
  /**
@@ -90,7 +90,7 @@ class JoinResponse extends abstractResponse_1.PondResponse {
90
90
  * @param payload - the payload to send
91
91
  */
92
92
  broadcast(event, payload) {
93
- __classPrivateFieldGet(this, _JoinResponse_engine, "f").sendMessage(this.requestId, __classPrivateFieldGet(this, _JoinResponse_user, "f").clientId, enums_1.ChannelReceiver.ALL_USERS, enums_1.ServerActions.BROADCAST, event, payload);
93
+ __classPrivateFieldGet(this, _JoinResponse_engine, "f").sendMessage(this.requestId, __classPrivateFieldGet(this, _JoinResponse_user, "f").clientId, pondsocket_common_1.ChannelReceiver.ALL_USERS, pondsocket_common_1.ServerActions.BROADCAST, event, payload);
94
94
  return this;
95
95
  }
96
96
  /**
@@ -99,7 +99,7 @@ class JoinResponse extends abstractResponse_1.PondResponse {
99
99
  * @param payload - the payload to send
100
100
  */
101
101
  broadcastFromUser(event, payload) {
102
- __classPrivateFieldGet(this, _JoinResponse_engine, "f").sendMessage(this.requestId, __classPrivateFieldGet(this, _JoinResponse_user, "f").clientId, enums_1.ChannelReceiver.ALL_EXCEPT_SENDER, enums_1.ServerActions.BROADCAST, event, payload);
102
+ __classPrivateFieldGet(this, _JoinResponse_engine, "f").sendMessage(this.requestId, __classPrivateFieldGet(this, _JoinResponse_user, "f").clientId, pondsocket_common_1.ChannelReceiver.ALL_EXCEPT_SENDER, pondsocket_common_1.ServerActions.BROADCAST, event, payload);
103
103
  return this;
104
104
  }
105
105
  /**
@@ -109,7 +109,7 @@ class JoinResponse extends abstractResponse_1.PondResponse {
109
109
  * @param userIds - the ids of the clients to send the message to
110
110
  */
111
111
  sendToUsers(event, payload, userIds) {
112
- __classPrivateFieldGet(this, _JoinResponse_engine, "f").sendMessage(this.requestId, __classPrivateFieldGet(this, _JoinResponse_user, "f").clientId, userIds, enums_1.ServerActions.BROADCAST, event, payload);
112
+ __classPrivateFieldGet(this, _JoinResponse_engine, "f").sendMessage(this.requestId, __classPrivateFieldGet(this, _JoinResponse_user, "f").clientId, userIds, pondsocket_common_1.ServerActions.BROADCAST, event, payload);
113
113
  return this;
114
114
  }
115
115
  /**
package/lobby/lobby.js CHANGED
@@ -13,10 +13,9 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
13
13
  var _LobbyEngine_channels, _LobbyEngine_middleware, _LobbyEngine_leaveCallback, _PondChannel_lobby;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.PondChannel = exports.LobbyEngine = void 0;
16
+ const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
16
17
  const middleware_1 = require("../abstracts/middleware");
17
18
  const channel_1 = require("../channel/channel");
18
- const enums_1 = require("../enums");
19
- const uuid_1 = require("../misc/uuid");
20
19
  class LobbyEngine {
21
20
  constructor() {
22
21
  _LobbyEngine_channels.set(this, void 0);
@@ -69,11 +68,11 @@ class LobbyEngine {
69
68
  if (!channel) {
70
69
  throw new Error(`GatewayEngine: Channel ${channelName} does not exist`);
71
70
  }
72
- channel.sendMessage((0, uuid_1.uuid)(), enums_1.SystemSender.CHANNEL, enums_1.ChannelReceiver.ALL_USERS, enums_1.ServerActions.SYSTEM, event, payload);
71
+ channel.sendMessage((0, pondsocket_common_1.uuid)(), pondsocket_common_1.SystemSender.CHANNEL, pondsocket_common_1.ChannelReceiver.ALL_USERS, pondsocket_common_1.ServerActions.SYSTEM, event, payload);
73
72
  }
74
73
  else {
75
74
  __classPrivateFieldGet(this, _LobbyEngine_channels, "f").forEach((channel) => {
76
- channel.sendMessage((0, uuid_1.uuid)(), enums_1.SystemSender.CHANNEL, enums_1.ChannelReceiver.ALL_USERS, enums_1.ServerActions.SYSTEM, event, payload);
75
+ channel.sendMessage((0, pondsocket_common_1.uuid)(), pondsocket_common_1.SystemSender.CHANNEL, pondsocket_common_1.ChannelReceiver.ALL_USERS, pondsocket_common_1.ServerActions.SYSTEM, event, payload);
77
76
  });
78
77
  }
79
78
  }
@@ -0,0 +1,90 @@
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
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eleven-am/pondsocket",
3
- "version": "0.1.126",
3
+ "version": "0.1.127",
4
4
  "description": "PondSocket is a fast simple socket server",
5
5
  "keywords": [
6
6
  "socket",
@@ -16,28 +16,31 @@
16
16
  "access": "public"
17
17
  },
18
18
  "scripts": {
19
- "test": "jest --coverage --verbose --watchAll",
20
- "build": "tsc --project tsconfig.build.json",
21
- "publishToNpm": "npm version patch && npm publish"
19
+ "test": "jest --coverage --verbose",
20
+ "build": "rimraf dist && tsc && npm run remove",
21
+ "lint": "eslint --ext .ts src",
22
+ "lint:fix": "eslint --fix --ext .ts src",
23
+ "remove": "rm dist/dist.js dist/distIndex.js",
24
+ "copy": "cp src/dist.ts dist/types.d.ts && cp src/distIndex.ts dist/index.d.ts && cp package.json dist && cp README.md dist && cp LICENSE dist",
25
+ "push": "npm version patch && npm run copy && cd dist && npm publish && cd ..",
26
+ "pipeline": "npm run lint && npm run test && npm run build && npm run push"
22
27
  },
23
28
  "author": "Roy OSSAI",
24
29
  "license": "GPL-3.0",
25
- "main": "index.js",
26
- "types": "index.d.ts",
30
+ "main": "./index.js",
31
+ "types": "./index.d.ts",
27
32
  "repository": {
28
33
  "type": "git",
29
34
  "url": "git+https://github.com/Eleven-am/pondSocket.git"
30
35
  },
31
36
  "dependencies": {
32
- "websocket": "^1.0.34",
33
- "ws": "^8.16.0"
37
+ "@eleven-am/pondsocket-common": "^0.0.5",
38
+ "ws": "^8.16.0",
39
+ "zod": "^3.22.4"
34
40
  },
35
41
  "devDependencies": {
36
- "@nestjs/common": "^10.3.0",
37
- "@nestjs/core": "^10.3.0",
38
- "@types/express": "^4.17.21",
39
42
  "@types/jest": "^29.5.11",
40
- "@types/node": "^20.10.5",
43
+ "@types/node": "^20.10.6",
41
44
  "@types/websocket": "^1.0.10",
42
45
  "@types/ws": "^8.5.10",
43
46
  "@typescript-eslint/eslint-plugin": "^6.16.0",
@@ -45,10 +48,26 @@
45
48
  "eslint-plugin-file-progress": "^1.3.0",
46
49
  "eslint-plugin-import": "^2.29.1",
47
50
  "jest": "^29.7.0",
48
- "reflect-metadata": "^0.1.14",
49
51
  "superwstest": "^2.0.3",
50
52
  "ts-jest": "^29.1.1",
51
53
  "ts-node": "^10.9.2",
52
54
  "typescript": "^5.3.3"
55
+ },
56
+ "jest": {
57
+ "moduleFileExtensions": [
58
+ "js",
59
+ "json",
60
+ "ts"
61
+ ],
62
+ "rootDir": "src",
63
+ "testRegex": ".*\\.test\\.ts$",
64
+ "transform": {
65
+ "^.+\\.(t|j)s$": "ts-jest"
66
+ },
67
+ "collectCoverageFrom": [
68
+ "**/*.(t|j)s"
69
+ ],
70
+ "coverageDirectory": "../coverage",
71
+ "testEnvironment": "node"
53
72
  }
54
73
  }
@@ -13,9 +13,8 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
13
13
  var _PresenceEngine_instances, _PresenceEngine_presenceMap, _PresenceEngine_channel, _PresenceEngine_publish;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.PresenceEngine = void 0;
16
- const enums_1 = require("../enums");
16
+ const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
17
17
  const pondError_1 = require("../errors/pondError");
18
- const uuid_1 = require("../misc/uuid");
19
18
  class PresenceEngine {
20
19
  constructor(channel) {
21
20
  _PresenceEngine_instances.add(this);
@@ -49,7 +48,7 @@ class PresenceEngine {
49
48
  trackPresence(presenceKey, presence) {
50
49
  if (!__classPrivateFieldGet(this, _PresenceEngine_presenceMap, "f").has(presenceKey)) {
51
50
  __classPrivateFieldGet(this, _PresenceEngine_presenceMap, "f").set(presenceKey, presence);
52
- __classPrivateFieldGet(this, _PresenceEngine_instances, "m", _PresenceEngine_publish).call(this, enums_1.PresenceEventTypes.JOIN, {
51
+ __classPrivateFieldGet(this, _PresenceEngine_instances, "m", _PresenceEngine_publish).call(this, pondsocket_common_1.PresenceEventTypes.JOIN, {
53
52
  changed: presence,
54
53
  presence: Array.from(__classPrivateFieldGet(this, _PresenceEngine_presenceMap, "f").values()),
55
54
  });
@@ -57,7 +56,7 @@ class PresenceEngine {
57
56
  else {
58
57
  const code = 400;
59
58
  const message = `PresenceEngine: Presence with key ${presenceKey} already exists`;
60
- throw new pondError_1.PresenceError(message, code, __classPrivateFieldGet(this, _PresenceEngine_channel, "f").name, enums_1.PresenceEventTypes.JOIN);
59
+ throw new pondError_1.PresenceError(message, code, __classPrivateFieldGet(this, _PresenceEngine_channel, "f").name, pondsocket_common_1.PresenceEventTypes.JOIN);
61
60
  }
62
61
  }
63
62
  /**
@@ -69,7 +68,7 @@ class PresenceEngine {
69
68
  const presence = __classPrivateFieldGet(this, _PresenceEngine_presenceMap, "f").get(presenceKey);
70
69
  if (presence) {
71
70
  __classPrivateFieldGet(this, _PresenceEngine_presenceMap, "f").delete(presenceKey);
72
- __classPrivateFieldGet(this, _PresenceEngine_instances, "m", _PresenceEngine_publish).call(this, enums_1.PresenceEventTypes.LEAVE, {
71
+ __classPrivateFieldGet(this, _PresenceEngine_instances, "m", _PresenceEngine_publish).call(this, pondsocket_common_1.PresenceEventTypes.LEAVE, {
73
72
  changed: presence,
74
73
  presence: Array.from(__classPrivateFieldGet(this, _PresenceEngine_presenceMap, "f").values()),
75
74
  });
@@ -77,7 +76,7 @@ class PresenceEngine {
77
76
  else if (!graceful) {
78
77
  const code = 404;
79
78
  const message = `PresenceEngine: Presence with key ${presenceKey} does not exist`;
80
- throw new pondError_1.PresenceError(message, code, __classPrivateFieldGet(this, _PresenceEngine_channel, "f").name, enums_1.PresenceEventTypes.LEAVE);
79
+ throw new pondError_1.PresenceError(message, code, __classPrivateFieldGet(this, _PresenceEngine_channel, "f").name, pondsocket_common_1.PresenceEventTypes.LEAVE);
81
80
  }
82
81
  }
83
82
  /**
@@ -90,7 +89,7 @@ class PresenceEngine {
90
89
  if (oldPresence) {
91
90
  const newPresence = Object.assign(Object.assign({}, oldPresence), presence);
92
91
  __classPrivateFieldGet(this, _PresenceEngine_presenceMap, "f").set(presenceKey, newPresence);
93
- __classPrivateFieldGet(this, _PresenceEngine_instances, "m", _PresenceEngine_publish).call(this, enums_1.PresenceEventTypes.UPDATE, {
92
+ __classPrivateFieldGet(this, _PresenceEngine_instances, "m", _PresenceEngine_publish).call(this, pondsocket_common_1.PresenceEventTypes.UPDATE, {
94
93
  changed: newPresence,
95
94
  presence: Array.from(__classPrivateFieldGet(this, _PresenceEngine_presenceMap, "f").values()),
96
95
  });
@@ -98,7 +97,7 @@ class PresenceEngine {
98
97
  else {
99
98
  const code = 404;
100
99
  const message = `PresenceEngine: Presence with key ${presenceKey} does not exist`;
101
- throw new pondError_1.PresenceError(message, code, __classPrivateFieldGet(this, _PresenceEngine_channel, "f").name, enums_1.PresenceEventTypes.UPDATE);
100
+ throw new pondError_1.PresenceError(message, code, __classPrivateFieldGet(this, _PresenceEngine_channel, "f").name, pondsocket_common_1.PresenceEventTypes.UPDATE);
102
101
  }
103
102
  }
104
103
  }
@@ -108,5 +107,5 @@ _PresenceEngine_presenceMap = new WeakMap(), _PresenceEngine_channel = new WeakM
108
107
  if (recipients.length === 0) {
109
108
  return;
110
109
  }
111
- __classPrivateFieldGet(this, _PresenceEngine_channel, "f").sendMessage((0, uuid_1.uuid)(), enums_1.SystemSender.CHANNEL, recipients, enums_1.ServerActions.PRESENCE, event, payload);
110
+ __classPrivateFieldGet(this, _PresenceEngine_channel, "f").sendMessage((0, pondsocket_common_1.uuid)(), pondsocket_common_1.SystemSender.CHANNEL, recipients, pondsocket_common_1.ServerActions.PRESENCE, event, payload);
112
111
  };
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
4
+ const presence_1 = require("./presence");
5
+ const eventResponse_test_1 = require("../channel/eventResponse.test");
6
+ describe('PresenceEngine', () => {
7
+ let presenceEngine;
8
+ let presence;
9
+ let presenceKey;
10
+ let channel;
11
+ beforeEach(() => {
12
+ channel = (0, eventResponse_test_1.createChannelEngine)();
13
+ channel.addUser('presenceKey', { assign: 'assign' }, () => {
14
+ // do nothing
15
+ });
16
+ presenceEngine = new presence_1.PresenceEngine(channel);
17
+ presence = {
18
+ id: 'id',
19
+ name: 'name',
20
+ color: 'color',
21
+ type: 'type',
22
+ location: 'location',
23
+ };
24
+ presenceKey = 'presenceKey';
25
+ });
26
+ describe('trackPresence', () => {
27
+ it('should insert a presence into the presence engine', () => {
28
+ // spy on the channel sendMessage method
29
+ const sendMessage = jest.spyOn(channel, 'sendMessage');
30
+ presenceEngine.trackPresence(presenceKey, presence);
31
+ // get all the params
32
+ const params = sendMessage.mock.calls[0];
33
+ // remove the first element as it contains the request id which is random
34
+ params.shift();
35
+ expect(params).toEqual([
36
+ pondsocket_common_1.SystemSender.CHANNEL,
37
+ ['presenceKey'],
38
+ pondsocket_common_1.ServerActions.PRESENCE,
39
+ pondsocket_common_1.PresenceEventTypes.JOIN,
40
+ {
41
+ changed: presence,
42
+ presence: [presence],
43
+ },
44
+ ]);
45
+ });
46
+ it('should throw an error if the presence already exists', () => {
47
+ presenceEngine.trackPresence(presenceKey, presence);
48
+ expect(() => presenceEngine.trackPresence(presenceKey, presence)).toThrowError(`PresenceEngine: Presence with key ${presenceKey} already exists`);
49
+ });
50
+ });
51
+ describe('updatePresence', () => {
52
+ it('should update a presence', () => {
53
+ presenceEngine.trackPresence(presenceKey, presence);
54
+ const newPresence = {
55
+ id: 'id',
56
+ name: 'name',
57
+ color: 'color',
58
+ type: 'type',
59
+ location: 'location',
60
+ };
61
+ const sendMessage = jest.spyOn(channel, 'sendMessage');
62
+ presenceEngine.updatePresence(presenceKey, newPresence);
63
+ // get all the params
64
+ const params = sendMessage.mock.calls[0];
65
+ // remove the first element as it contains the request id which is random
66
+ params.shift();
67
+ expect(params).toEqual([
68
+ pondsocket_common_1.SystemSender.CHANNEL,
69
+ ['presenceKey'],
70
+ pondsocket_common_1.ServerActions.PRESENCE,
71
+ pondsocket_common_1.PresenceEventTypes.UPDATE,
72
+ {
73
+ changed: Object.assign(Object.assign({}, presence), newPresence),
74
+ presence: [newPresence],
75
+ },
76
+ ]);
77
+ });
78
+ it('should throw an error if the presence does not exist', () => {
79
+ expect(() => presenceEngine.updatePresence(presenceKey, presence)).toThrowError(`PresenceEngine: Presence with key ${presenceKey} does not exist`);
80
+ });
81
+ });
82
+ describe('removePresence', () => {
83
+ it('should remove a presence from the presence engine', () => {
84
+ const listener = jest.spyOn(channel, 'sendMessage');
85
+ // before we can track a presence, we need make sure the user is in the channel
86
+ channel.addUser('presenceKey2', { assign: 'assign' }, () => {
87
+ // do nothing
88
+ });
89
+ presenceEngine.trackPresence(presenceKey, presence);
90
+ presenceEngine.trackPresence('presenceKey2', Object.assign(Object.assign({}, presence), { key: 'presence2' }));
91
+ expect(listener).toHaveBeenCalledTimes(2);
92
+ // clear the mock
93
+ listener.mockClear();
94
+ presenceEngine.removePresence(presenceKey);
95
+ expect(listener).toHaveBeenCalledTimes(1);
96
+ // get all the params
97
+ const params = listener.mock.calls[0];
98
+ // remove the first element as it contains the request id which is random
99
+ params.shift();
100
+ expect(params).toEqual([
101
+ pondsocket_common_1.SystemSender.CHANNEL,
102
+ ['presenceKey2'],
103
+ pondsocket_common_1.ServerActions.PRESENCE,
104
+ pondsocket_common_1.PresenceEventTypes.LEAVE,
105
+ {
106
+ changed: presence,
107
+ presence: [
108
+ Object.assign(Object.assign({}, presence), { key: 'presence2' }),
109
+ ],
110
+ },
111
+ ]);
112
+ listener.mockClear();
113
+ presenceEngine.removePresence('presenceKey2');
114
+ expect(listener).toHaveBeenCalledTimes(0);
115
+ });
116
+ it('should throw an error if the presence does not exist', () => {
117
+ expect(() => presenceEngine.removePresence(presenceKey)).toThrowError(`PresenceEngine: Presence with key ${presenceKey} does not exist`);
118
+ });
119
+ });
120
+ describe('getPresence', () => {
121
+ it('should return the presence', () => {
122
+ presenceEngine.trackPresence(presenceKey, presence);
123
+ const data = {};
124
+ data[presenceKey] = presence;
125
+ expect(presenceEngine.getPresence()).toEqual(data);
126
+ });
127
+ });
128
+ });