@eleven-am/pondsocket 0.1.169 → 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 -104
  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
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
12
+ if (kind === "m") throw new TypeError("Private method is not writable");
13
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
14
+ 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");
15
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
16
+ };
17
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
18
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
19
+ 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");
20
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
21
+ };
22
+ var _EndpointEngine_instances, _EndpointEngine_clientFactory, _EndpointEngine_sockets, _EndpointEngine_middleware, _EndpointEngine_lobbyEngines, _EndpointEngine_handleSocketClose, _EndpointEngine_handleMessage, _EndpointEngine_joinChannel, _EndpointEngine_leaveChannel, _EndpointEngine_retrieveChannel, _EndpointEngine_buildError, _EndpointEngine_broadcastMessage, _EndpointEngine_readMessage;
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.EndpointEngine = void 0;
25
+ const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
26
+ const lobbyEngine_1 = require("./lobbyEngine");
27
+ const middleware_1 = require("../abstracts/middleware");
28
+ const httpError_1 = require("../errors/httpError");
29
+ const managerFactory_1 = require("../managers/managerFactory");
30
+ const matcher_1 = require("../matcher/matcher");
31
+ const joinRequest_1 = require("../requests/joinRequest");
32
+ const joinResponse_1 = require("../responses/joinResponse");
33
+ const pondChannel_1 = require("../wrappers/pondChannel");
34
+ class EndpointEngine {
35
+ constructor(clientFactory) {
36
+ _EndpointEngine_instances.add(this);
37
+ _EndpointEngine_clientFactory.set(this, void 0);
38
+ _EndpointEngine_sockets.set(this, void 0);
39
+ _EndpointEngine_middleware.set(this, void 0);
40
+ _EndpointEngine_lobbyEngines.set(this, void 0);
41
+ __classPrivateFieldSet(this, _EndpointEngine_sockets, new Map(), "f");
42
+ __classPrivateFieldSet(this, _EndpointEngine_lobbyEngines, new Map(), "f");
43
+ __classPrivateFieldSet(this, _EndpointEngine_middleware, new middleware_1.Middleware(), "f");
44
+ __classPrivateFieldSet(this, _EndpointEngine_clientFactory, clientFactory, "f");
45
+ }
46
+ createChannel(path, handler) {
47
+ const pondChannel = new lobbyEngine_1.LobbyEngine(this);
48
+ __classPrivateFieldGet(this, _EndpointEngine_middleware, "f").use((user, joinParams, next) => __awaiter(this, void 0, void 0, function* () {
49
+ const event = (0, matcher_1.parseAddress)(path, user.channelName);
50
+ if (event) {
51
+ const options = {
52
+ clientId: user.clientId,
53
+ assigns: user.assigns,
54
+ params: event,
55
+ joinParams,
56
+ };
57
+ const channel = yield pondChannel.getOrCreateChannel(user.channelName);
58
+ const request = new joinRequest_1.JoinRequest(options, channel);
59
+ const response = new joinResponse_1.JoinResponse(user, channel);
60
+ return handler(request, response, next);
61
+ }
62
+ next();
63
+ }));
64
+ __classPrivateFieldGet(this, _EndpointEngine_lobbyEngines, "f").set(path, pondChannel);
65
+ return new pondChannel_1.PondChannel(pondChannel);
66
+ }
67
+ getClients() {
68
+ return [...__classPrivateFieldGet(this, _EndpointEngine_sockets, "f").values()];
69
+ }
70
+ getUser(clientId) {
71
+ const user = __classPrivateFieldGet(this, _EndpointEngine_sockets, "f").get(clientId);
72
+ if (!user) {
73
+ throw new httpError_1.HttpError(404, `GatewayEngine: User ${clientId} does not exist`);
74
+ }
75
+ return user;
76
+ }
77
+ manageSocket(cache) {
78
+ __classPrivateFieldGet(this, _EndpointEngine_sockets, "f").set(cache.clientId, cache);
79
+ cache.socket.on('message', (message) => __classPrivateFieldGet(this, _EndpointEngine_instances, "m", _EndpointEngine_readMessage).call(this, cache, message));
80
+ cache.socket.on('close', () => __classPrivateFieldGet(this, _EndpointEngine_instances, "m", _EndpointEngine_handleSocketClose).call(this, cache));
81
+ cache.socket.on('error', () => __classPrivateFieldGet(this, _EndpointEngine_instances, "m", _EndpointEngine_handleSocketClose).call(this, cache));
82
+ const event = {
83
+ event: pondsocket_common_1.Events.CONNECTION,
84
+ action: pondsocket_common_1.ServerActions.CONNECT,
85
+ channelName: pondsocket_common_1.SystemSender.ENDPOINT,
86
+ requestId: (0, pondsocket_common_1.uuid)(),
87
+ payload: {},
88
+ };
89
+ this.sendMessage(cache.socket, event);
90
+ }
91
+ createManager(channelName, onLeave) {
92
+ return managerFactory_1.ManagerFactory.create(channelName, __classPrivateFieldGet(this, _EndpointEngine_clientFactory, "f"), onLeave);
93
+ }
94
+ sendMessage(socket, message) {
95
+ socket.send(JSON.stringify(message));
96
+ }
97
+ closeConnection(clientIds) {
98
+ const clients = typeof clientIds === 'string' ? [clientIds] : clientIds;
99
+ this.getClients()
100
+ .forEach(({ clientId, socket }) => {
101
+ if (clients.includes(clientId)) {
102
+ socket.close();
103
+ }
104
+ });
105
+ }
106
+ }
107
+ exports.EndpointEngine = EndpointEngine;
108
+ _EndpointEngine_clientFactory = new WeakMap(), _EndpointEngine_sockets = new WeakMap(), _EndpointEngine_middleware = new WeakMap(), _EndpointEngine_lobbyEngines = new WeakMap(), _EndpointEngine_instances = new WeakSet(), _EndpointEngine_handleSocketClose = function _EndpointEngine_handleSocketClose(cache) {
109
+ __classPrivateFieldGet(this, _EndpointEngine_sockets, "f").delete(cache.clientId);
110
+ cache.subscriptions.forEach((unsubscribe) => unsubscribe());
111
+ }, _EndpointEngine_handleMessage = function _EndpointEngine_handleMessage(cache, message) {
112
+ switch (message.action) {
113
+ case pondsocket_common_1.ClientActions.JOIN_CHANNEL:
114
+ __classPrivateFieldGet(this, _EndpointEngine_instances, "m", _EndpointEngine_joinChannel).call(this, message.channelName, cache, message.payload, message.requestId);
115
+ break;
116
+ case pondsocket_common_1.ClientActions.LEAVE_CHANNEL:
117
+ __classPrivateFieldGet(this, _EndpointEngine_instances, "m", _EndpointEngine_leaveChannel).call(this, message.channelName, cache);
118
+ break;
119
+ case pondsocket_common_1.ClientActions.BROADCAST:
120
+ __classPrivateFieldGet(this, _EndpointEngine_instances, "m", _EndpointEngine_broadcastMessage).call(this, cache, message);
121
+ break;
122
+ default:
123
+ throw new Error(`GatewayEngine: Action ${message.action} does not exist`);
124
+ }
125
+ }, _EndpointEngine_joinChannel = function _EndpointEngine_joinChannel(channel, socket, joinParams, requestId) {
126
+ const cache = Object.assign(Object.assign({}, socket), { requestId, channelName: channel });
127
+ __classPrivateFieldGet(this, _EndpointEngine_middleware, "f").run(cache, joinParams, (error) => {
128
+ error = error || new httpError_1.HttpError(404, `GatewayEngine: Channel ${channel} does not exist`);
129
+ throw error;
130
+ });
131
+ }, _EndpointEngine_leaveChannel = function _EndpointEngine_leaveChannel(channel, socket) {
132
+ const engine = __classPrivateFieldGet(this, _EndpointEngine_instances, "m", _EndpointEngine_retrieveChannel).call(this, channel);
133
+ engine.removeUser(socket.clientId);
134
+ }, _EndpointEngine_retrieveChannel = function _EndpointEngine_retrieveChannel(channel) {
135
+ for (const [path, manager] of __classPrivateFieldGet(this, _EndpointEngine_lobbyEngines, "f")) {
136
+ const event = (0, matcher_1.parseAddress)(path, channel);
137
+ if (event) {
138
+ return manager.getChannel(channel);
139
+ }
140
+ }
141
+ throw new httpError_1.HttpError(404, `GatewayEngine: Channel ${channel} does not exist`);
142
+ }, _EndpointEngine_buildError = function _EndpointEngine_buildError(error) {
143
+ const event = {
144
+ event: pondsocket_common_1.ErrorTypes.INVALID_MESSAGE,
145
+ action: pondsocket_common_1.ServerActions.ERROR,
146
+ channelName: pondsocket_common_1.SystemSender.ENDPOINT,
147
+ requestId: (0, pondsocket_common_1.uuid)(),
148
+ payload: {},
149
+ };
150
+ return event;
151
+ }, _EndpointEngine_broadcastMessage = function _EndpointEngine_broadcastMessage(socket, message) {
152
+ const engine = __classPrivateFieldGet(this, _EndpointEngine_instances, "m", _EndpointEngine_retrieveChannel).call(this, message.channelName);
153
+ engine.broadcastMessage(socket.clientId, message);
154
+ }, _EndpointEngine_readMessage = function _EndpointEngine_readMessage(cache, message) {
155
+ try {
156
+ const data = JSON.parse(message);
157
+ const result = pondsocket_common_1.clientMessageSchema.parse(data);
158
+ __classPrivateFieldGet(this, _EndpointEngine_instances, "m", _EndpointEngine_handleMessage).call(this, cache, result);
159
+ }
160
+ catch (e) {
161
+ this.sendMessage(cache.socket, __classPrivateFieldGet(this, _EndpointEngine_instances, "m", _EndpointEngine_buildError).call(this, e));
162
+ }
163
+ };
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
12
+ if (kind === "m") throw new TypeError("Private method is not writable");
13
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
14
+ 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");
15
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
16
+ };
17
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
18
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
19
+ 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");
20
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
21
+ };
22
+ var _LobbyEngine_instances, _LobbyEngine_channels, _LobbyEngine_getChannel, _LobbyEngine_createChannel;
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.LobbyEngine = void 0;
25
+ const channelEngine_1 = require("./channelEngine");
26
+ const middleware_1 = require("../abstracts/middleware");
27
+ const httpError_1 = require("../errors/httpError");
28
+ const matcher_1 = require("../matcher/matcher");
29
+ const eventRequest_1 = require("../requests/eventRequest");
30
+ const eventResponse_1 = require("../responses/eventResponse");
31
+ class LobbyEngine {
32
+ constructor(parent) {
33
+ _LobbyEngine_instances.add(this);
34
+ this.parent = parent;
35
+ _LobbyEngine_channels.set(this, void 0);
36
+ this.middleware = new middleware_1.Middleware();
37
+ __classPrivateFieldSet(this, _LobbyEngine_channels, new Map(), "f");
38
+ }
39
+ onLeave(callback) {
40
+ this.leaveCallback = callback;
41
+ }
42
+ onEvent(event, handler) {
43
+ this.middleware.use((requestEvent, channel, next) => {
44
+ const params = (0, matcher_1.parseAddress)(event, requestEvent.event);
45
+ if (params) {
46
+ const eventRequest = new eventRequest_1.EventRequest(requestEvent, params, channel);
47
+ const response = new eventResponse_1.EventResponse(requestEvent, channel);
48
+ return handler(eventRequest, response, next);
49
+ }
50
+ return next();
51
+ });
52
+ }
53
+ getOrCreateChannel(channelName) {
54
+ const oldChannel = __classPrivateFieldGet(this, _LobbyEngine_instances, "m", _LobbyEngine_getChannel).call(this, channelName);
55
+ if (oldChannel) {
56
+ return oldChannel;
57
+ }
58
+ return __classPrivateFieldGet(this, _LobbyEngine_instances, "m", _LobbyEngine_createChannel).call(this, channelName);
59
+ }
60
+ getChannel(channelName) {
61
+ const channel = __classPrivateFieldGet(this, _LobbyEngine_channels, "f").get(channelName);
62
+ if (!channel) {
63
+ throw new httpError_1.HttpError(404, `Channel ${channelName} not found`);
64
+ }
65
+ return channel;
66
+ }
67
+ }
68
+ exports.LobbyEngine = LobbyEngine;
69
+ _LobbyEngine_channels = new WeakMap(), _LobbyEngine_instances = new WeakSet(), _LobbyEngine_getChannel = function _LobbyEngine_getChannel(channelName) {
70
+ return __classPrivateFieldGet(this, _LobbyEngine_channels, "f").get(channelName) || null;
71
+ }, _LobbyEngine_createChannel = function _LobbyEngine_createChannel(channelName) {
72
+ return __awaiter(this, void 0, void 0, function* () {
73
+ const onManagerClose = __classPrivateFieldGet(this, _LobbyEngine_channels, "f").delete.bind(__classPrivateFieldGet(this, _LobbyEngine_channels, "f"), channelName);
74
+ const manager = yield this.parent.createManager(channelName, onManagerClose);
75
+ const channel = new channelEngine_1.ChannelEngine(this, channelName, manager);
76
+ __classPrivateFieldGet(this, _LobbyEngine_channels, "f").set(channelName, channel);
77
+ return channel;
78
+ });
79
+ };
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HttpError = void 0;
4
+ class HttpError extends Error {
5
+ constructor(statusCode, message) {
6
+ super(message);
7
+ this.statusCode = statusCode;
8
+ this.name = 'HttpError';
9
+ }
10
+ }
11
+ exports.HttpError = HttpError;
package/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const pondSocket_1 = require("./server/pondSocket");
4
- exports.default = pondSocket_1.PondSocket;
3
+ const server_1 = require("./server/server");
4
+ exports.default = server_1.PondSocket;
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
12
+ if (kind === "m") throw new TypeError("Private method is not writable");
13
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
14
+ 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");
15
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
16
+ };
17
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
18
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
19
+ 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");
20
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
21
+ };
22
+ var _DistributedManager_client, _DistributedManager_subscriptions;
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.DistributedManager = void 0;
25
+ const manager_1 = require("./manager");
26
+ class DistributedManager extends manager_1.Manager {
27
+ constructor(client) {
28
+ super(client.channelId);
29
+ _DistributedManager_client.set(this, void 0);
30
+ _DistributedManager_subscriptions.set(this, null);
31
+ __classPrivateFieldSet(this, _DistributedManager_client, client, "f");
32
+ }
33
+ trackPresence(userId, data) {
34
+ const message = this.processPresenceData(manager_1.ActionTypes.CREATE, userId, data);
35
+ __classPrivateFieldGet(this, _DistributedManager_client, "f").publishPresenceChange(userId, data);
36
+ return this.broadcast(message);
37
+ }
38
+ updatePresence(userId, data) {
39
+ const message = this.processPresenceData(manager_1.ActionTypes.UPDATE, userId, data);
40
+ __classPrivateFieldGet(this, _DistributedManager_client, "f").publishPresenceChange(userId, data);
41
+ return this.broadcast(message);
42
+ }
43
+ removePresence(userId) {
44
+ const message = this.processPresenceData(manager_1.ActionTypes.DELETE, userId, null);
45
+ __classPrivateFieldGet(this, _DistributedManager_client, "f").publishPresenceChange(userId, null);
46
+ return this.broadcast(message);
47
+ }
48
+ setAssigns(userId, data) {
49
+ this.processAssignsData(manager_1.ActionTypes.CREATE, userId, data);
50
+ __classPrivateFieldGet(this, _DistributedManager_client, "f").publishAssignsChange(userId, data);
51
+ }
52
+ updateAssigns(userId, data) {
53
+ this.processAssignsData(manager_1.ActionTypes.UPDATE, userId, data);
54
+ __classPrivateFieldGet(this, _DistributedManager_client, "f").publishAssignsChange(userId, data);
55
+ }
56
+ removeAssigns(userId) {
57
+ this.processAssignsData(manager_1.ActionTypes.DELETE, userId, null);
58
+ __classPrivateFieldGet(this, _DistributedManager_client, "f").publishAssignsChange(userId, null);
59
+ }
60
+ removeUser(userId) {
61
+ const userData = super.removeUser(userId);
62
+ __classPrivateFieldGet(this, _DistributedManager_client, "f").publishUserLeave(userId);
63
+ return userData;
64
+ }
65
+ broadcast(message) {
66
+ __classPrivateFieldGet(this, _DistributedManager_client, "f").publishChannelMessage(message);
67
+ }
68
+ initialize(unsubscribe) {
69
+ const _super = Object.create(null, {
70
+ initialize: { get: () => super.initialize }
71
+ });
72
+ return __awaiter(this, void 0, void 0, function* () {
73
+ yield _super.initialize.call(this, unsubscribe);
74
+ this.presenceCache = yield __classPrivateFieldGet(this, _DistributedManager_client, "f").getPresenceCache();
75
+ this.assignsCache = yield __classPrivateFieldGet(this, _DistributedManager_client, "f").getAssignsCache();
76
+ const leaveSubscription = __classPrivateFieldGet(this, _DistributedManager_client, "f").subscribeToUserLeaves((userId) => {
77
+ var _a;
78
+ (_a = this.userSubscriptions.get(userId)) === null || _a === void 0 ? void 0 : _a();
79
+ this.userSubscriptions.delete(userId);
80
+ });
81
+ const presenceSubscription = __classPrivateFieldGet(this, _DistributedManager_client, "f").subscribeToPresenceChanges(({ userId, state }) => {
82
+ if (state) {
83
+ this.presenceCache.set(userId, state);
84
+ }
85
+ else {
86
+ this.presenceCache.delete(userId);
87
+ }
88
+ });
89
+ const assignSubscription = __classPrivateFieldGet(this, _DistributedManager_client, "f").subscribeToAssignsChanges(({ userId, state }) => {
90
+ if (state) {
91
+ this.assignsCache.set(userId, state);
92
+ }
93
+ else {
94
+ this.assignsCache.delete(userId);
95
+ }
96
+ });
97
+ const messageSubscription = __classPrivateFieldGet(this, _DistributedManager_client, "f").subscribeToChannelMessages((message) => {
98
+ this.publisher.publish(message);
99
+ });
100
+ __classPrivateFieldSet(this, _DistributedManager_subscriptions, () => {
101
+ leaveSubscription();
102
+ presenceSubscription();
103
+ assignSubscription();
104
+ messageSubscription();
105
+ }, "f");
106
+ });
107
+ }
108
+ close() {
109
+ var _a;
110
+ (_a = __classPrivateFieldGet(this, _DistributedManager_subscriptions, "f")) === null || _a === void 0 ? void 0 : _a.call(this);
111
+ return super.close();
112
+ }
113
+ }
114
+ exports.DistributedManager = DistributedManager;
115
+ _DistributedManager_client = new WeakMap(), _DistributedManager_subscriptions = new WeakMap();
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LocalManager = void 0;
4
+ const manager_1 = require("./manager");
5
+ class LocalManager extends manager_1.Manager {
6
+ constructor(channelId) {
7
+ super(channelId);
8
+ }
9
+ trackPresence(userId, data) {
10
+ const message = this.processPresenceData(manager_1.ActionTypes.CREATE, userId, data);
11
+ return this.broadcast(message);
12
+ }
13
+ updatePresence(userId, data) {
14
+ const message = this.processPresenceData(manager_1.ActionTypes.UPDATE, userId, data);
15
+ return this.broadcast(message);
16
+ }
17
+ removePresence(userId) {
18
+ const message = this.processPresenceData(manager_1.ActionTypes.DELETE, userId, null);
19
+ return this.broadcast(message);
20
+ }
21
+ setAssigns(userId, data) {
22
+ return this.processAssignsData(manager_1.ActionTypes.CREATE, userId, data);
23
+ }
24
+ updateAssigns(userId, data) {
25
+ return this.processAssignsData(manager_1.ActionTypes.UPDATE, userId, data);
26
+ }
27
+ removeAssigns(userId) {
28
+ return this.processAssignsData(manager_1.ActionTypes.DELETE, userId, null);
29
+ }
30
+ removeUser(userId) {
31
+ var _a;
32
+ const userData = super.removeUser(userId);
33
+ (_a = this.userSubscriptions.get(userId)) === null || _a === void 0 ? void 0 : _a();
34
+ this.userSubscriptions.delete(userId);
35
+ return userData;
36
+ }
37
+ broadcast(message) {
38
+ this.publisher.publish(message);
39
+ }
40
+ }
41
+ exports.LocalManager = LocalManager;
@@ -0,0 +1,219 @@
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 __rest = (this && this.__rest) || function (s, e) {
14
+ var t = {};
15
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
16
+ t[p] = s[p];
17
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
18
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
19
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
20
+ t[p[i]] = s[p[i]];
21
+ }
22
+ return t;
23
+ };
24
+ var _Manager_instances, _Manager_onClose, _Manager_processData;
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.Manager = exports.ActionTypes = void 0;
27
+ const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
28
+ const httpError_1 = require("../errors/httpError");
29
+ var DataTypes;
30
+ (function (DataTypes) {
31
+ DataTypes["PRESENCE"] = "presence";
32
+ DataTypes["ASSIGNS"] = "assigns";
33
+ })(DataTypes || (DataTypes = {}));
34
+ var ActionTypes;
35
+ (function (ActionTypes) {
36
+ ActionTypes["CREATE"] = "create";
37
+ ActionTypes["UPDATE"] = "update";
38
+ ActionTypes["DELETE"] = "delete";
39
+ })(ActionTypes || (exports.ActionTypes = ActionTypes = {}));
40
+ class Manager {
41
+ constructor(channelId) {
42
+ _Manager_instances.add(this);
43
+ this.channelId = channelId;
44
+ this.userSubscriptions = new Map();
45
+ this.publisher = new pondsocket_common_1.Subject();
46
+ this.presenceCache = new Map();
47
+ this.assignsCache = new Map();
48
+ _Manager_onClose.set(this, null);
49
+ }
50
+ get userIds() {
51
+ return new Set(this.assignsCache.keys());
52
+ }
53
+ /**
54
+ * @desc Initializes the data manager
55
+ * @param unsubscribe - The callback to call when the manager is closed
56
+ */
57
+ initialize(unsubscribe) {
58
+ __classPrivateFieldSet(this, _Manager_onClose, unsubscribe, "f");
59
+ return Promise.resolve();
60
+ }
61
+ /**
62
+ * @desc Returns the presence of a user
63
+ * @param userId - The id of the user
64
+ */
65
+ getPresence(userId) {
66
+ return this.presenceCache.get(userId) || null;
67
+ }
68
+ /**
69
+ * @desc Returns all the presence
70
+ */
71
+ getAllPresence() {
72
+ return new Map(this.presenceCache);
73
+ }
74
+ /**
75
+ * @desc Creates or updates the presence of a user
76
+ * @param userId - The id of the user
77
+ * @param data - The presence data
78
+ */
79
+ upsertPresence(userId, data) {
80
+ if (this.presenceCache.has(userId)) {
81
+ this.updatePresence(userId, data);
82
+ }
83
+ else {
84
+ this.trackPresence(userId, data);
85
+ }
86
+ }
87
+ /**
88
+ * @desc Returns the assigns of a user
89
+ * @param userId - The id of the user
90
+ */
91
+ getAssigns(userId) {
92
+ return this.assignsCache.get(userId) || null;
93
+ }
94
+ /**
95
+ * @desc Returns all the assigns
96
+ */
97
+ getAllAssigns() {
98
+ return new Map(this.assignsCache);
99
+ }
100
+ /**
101
+ * @desc Closes the data manager
102
+ */
103
+ close() {
104
+ var _a;
105
+ this.publisher.close();
106
+ this.presenceCache.clear();
107
+ this.assignsCache.clear();
108
+ this.userSubscriptions.forEach((unsubscribe) => unsubscribe());
109
+ this.userSubscriptions.clear();
110
+ (_a = __classPrivateFieldGet(this, _Manager_onClose, "f")) === null || _a === void 0 ? void 0 : _a.call(this);
111
+ }
112
+ /**
113
+ * @desc Subscribes to incoming messages
114
+ * @param userId - The id of the user
115
+ * @param assigns - The assigns of the user
116
+ * @param onMessage - The callback to call when a message is received
117
+ */
118
+ addUser(userId, assigns, onMessage) {
119
+ this.setAssigns(userId, assigns);
120
+ const subscription = this.publisher.subscribe((_a) => {
121
+ var { recipients } = _a, event = __rest(_a, ["recipients"]);
122
+ if (recipients.includes(userId)) {
123
+ onMessage(event);
124
+ }
125
+ });
126
+ this.userSubscriptions.set(userId, subscription);
127
+ }
128
+ /**
129
+ * @desc Unsubscribes from incoming messages
130
+ * @param userId - The id of the user
131
+ */
132
+ removeUser(userId) {
133
+ var _a;
134
+ const userData = this.getUserData(userId);
135
+ this.removePresence(userId);
136
+ this.removeAssigns(userId);
137
+ (_a = this.userSubscriptions.get(userId)) === null || _a === void 0 ? void 0 : _a();
138
+ this.userSubscriptions.delete(userId);
139
+ if (this.assignsCache.size === 0) {
140
+ this.close();
141
+ }
142
+ return userData;
143
+ }
144
+ /**
145
+ * @desc Returns the data of a user
146
+ * @param userId - The id of the user
147
+ */
148
+ getUserData(userId) {
149
+ const presence = this.getPresence(userId);
150
+ const assigns = this.getAssigns(userId);
151
+ if (!presence && !assigns) {
152
+ const message = `User with id ${userId} does not exist in the channel ${this.channelId}`;
153
+ const code = 404;
154
+ throw new httpError_1.HttpError(code, message);
155
+ }
156
+ return {
157
+ assigns: assigns || {},
158
+ presence: presence || {},
159
+ id: userId,
160
+ };
161
+ }
162
+ /**
163
+ * @desc Processes presence data
164
+ * @param action - The action to perform
165
+ * @param userId - The id of the user
166
+ * @param data - The presence data
167
+ */
168
+ processPresenceData(action, userId, data) {
169
+ const current = data ? data : this.presenceCache.get(userId);
170
+ __classPrivateFieldGet(this, _Manager_instances, "m", _Manager_processData).call(this, this.presenceCache, DataTypes.PRESENCE, action, userId, data);
171
+ const total = Array.from(this.presenceCache.values());
172
+ const userIds = Array.from(this.presenceCache.keys());
173
+ const event = action === ActionTypes.CREATE ? pondsocket_common_1.PresenceEventTypes.JOIN : action === ActionTypes.UPDATE ? pondsocket_common_1.PresenceEventTypes.UPDATE : pondsocket_common_1.PresenceEventTypes.LEAVE;
174
+ return {
175
+ event,
176
+ requestId: (0, pondsocket_common_1.uuid)(),
177
+ recipients: userIds,
178
+ channelName: this.channelId,
179
+ action: pondsocket_common_1.ServerActions.PRESENCE,
180
+ payload: {
181
+ changed: current,
182
+ presence: total,
183
+ },
184
+ };
185
+ }
186
+ /**
187
+ * @desc Processes assigns data
188
+ * @param action - The action to perform
189
+ * @param userId - The id of the user
190
+ * @param data - The assigns data
191
+ */
192
+ processAssignsData(action, userId, data) {
193
+ __classPrivateFieldGet(this, _Manager_instances, "m", _Manager_processData).call(this, this.assignsCache, DataTypes.ASSIGNS, action, userId, data);
194
+ }
195
+ }
196
+ exports.Manager = Manager;
197
+ _Manager_onClose = new WeakMap(), _Manager_instances = new WeakSet(), _Manager_processData = function _Manager_processData(cache, dataType, action, userId, data) {
198
+ if (action === ActionTypes.CREATE && cache.has(userId)) {
199
+ const message = `User with id ${userId} already exists in the ${dataType} cache`;
200
+ const code = 409;
201
+ throw new httpError_1.HttpError(code, message);
202
+ }
203
+ else if ((action === ActionTypes.UPDATE || action === ActionTypes.DELETE) && !cache.has(userId)) {
204
+ const message = `User with id ${userId} does not exist in the ${dataType} cache`;
205
+ const code = 404;
206
+ throw new httpError_1.HttpError(code, message);
207
+ }
208
+ if (action !== ActionTypes.DELETE && !data) {
209
+ const message = `Data is required for ${action} action`;
210
+ const code = 400;
211
+ throw new httpError_1.HttpError(code, message);
212
+ }
213
+ if (data) {
214
+ cache.set(userId, data);
215
+ }
216
+ else {
217
+ cache.delete(userId);
218
+ }
219
+ };