@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
@@ -4,22 +4,36 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
4
4
  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");
5
5
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
6
6
  };
7
- var _Middleware_stack;
7
+ var _Middleware_instances, _Middleware_stack, _Middleware_handleError;
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.Middleware = void 0;
10
+ const httpError_1 = require("../errors/httpError");
10
11
  class Middleware {
11
12
  constructor(second) {
13
+ _Middleware_instances.add(this);
12
14
  _Middleware_stack.set(this, []);
13
15
  if (second) {
14
16
  __classPrivateFieldGet(this, _Middleware_stack, "f").push(...__classPrivateFieldGet(second, _Middleware_stack, "f"));
15
17
  }
16
18
  }
19
+ /**
20
+ * @desc Returns the middleware stack length
21
+ */
22
+ get length() {
23
+ return __classPrivateFieldGet(this, _Middleware_stack, "f").length;
24
+ }
17
25
  /**
18
26
  * @desc Adds a middleware function to the middleware stack
19
27
  * @param middleware - the middleware function to add
20
28
  */
21
29
  use(middleware) {
22
- __classPrivateFieldGet(this, _Middleware_stack, "f").push(middleware);
30
+ if (middleware instanceof Middleware) {
31
+ __classPrivateFieldGet(this, _Middleware_stack, "f").push(...__classPrivateFieldGet(middleware, _Middleware_stack, "f"));
32
+ }
33
+ else {
34
+ __classPrivateFieldGet(this, _Middleware_stack, "f").push(middleware);
35
+ }
36
+ return this;
23
37
  }
24
38
  /**
25
39
  * @desc Runs the middleware stack
@@ -28,24 +42,33 @@ class Middleware {
28
42
  * @param final - the final function to call
29
43
  */
30
44
  run(req, res, final) {
31
- const temp = __classPrivateFieldGet(this, _Middleware_stack, "f").concat();
32
- const nextFunction = () => {
33
- const middleware = temp.shift();
34
- if (middleware) {
35
- middleware(req, res, nextFunction);
45
+ let index = 0;
46
+ const next = (err) => {
47
+ if (err) {
48
+ return final(__classPrivateFieldGet(this, _Middleware_instances, "m", _Middleware_handleError).call(this, err));
49
+ }
50
+ if (index >= __classPrivateFieldGet(this, _Middleware_stack, "f").length) {
51
+ return final();
36
52
  }
37
- else {
38
- final();
53
+ const middleware = __classPrivateFieldGet(this, _Middleware_stack, "f")[index];
54
+ index++;
55
+ try {
56
+ const result = middleware(req, res, next);
57
+ if (result instanceof Promise) {
58
+ result.catch(next);
59
+ }
60
+ }
61
+ catch (error) {
62
+ return final(__classPrivateFieldGet(this, _Middleware_instances, "m", _Middleware_handleError).call(this, error));
39
63
  }
40
64
  };
41
- nextFunction();
42
- }
43
- /**
44
- * @desc Returns the middleware stack length
45
- */
46
- get length() {
47
- return __classPrivateFieldGet(this, _Middleware_stack, "f").length;
65
+ next();
48
66
  }
49
67
  }
50
68
  exports.Middleware = Middleware;
51
- _Middleware_stack = new WeakMap();
69
+ _Middleware_stack = new WeakMap(), _Middleware_instances = new WeakSet(), _Middleware_handleError = function _Middleware_handleError(error) {
70
+ if (error instanceof httpError_1.HttpError) {
71
+ return error;
72
+ }
73
+ return new httpError_1.HttpError(500, error instanceof Error ? error.message : 'An error occurred while processing the request');
74
+ };
@@ -0,0 +1,278 @@
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 __rest = (this && this.__rest) || function (s, e) {
23
+ var t = {};
24
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
25
+ t[p] = s[p];
26
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
27
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
28
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
29
+ t[p[i]] = s[p[i]];
30
+ }
31
+ return t;
32
+ };
33
+ var __importDefault = (this && this.__importDefault) || function (mod) {
34
+ return (mod && mod.__esModule) ? mod : { "default": mod };
35
+ };
36
+ var _RedisClient_instances, _RedisClient_redisClient, _RedisClient_pubClient, _RedisClient_subClient, _RedisClient_instanceId, _RedisClient_assignsPublisher, _RedisClient_presencePublisher, _RedisClient_userLeavesPublisher, _RedisClient_channelMessagePublisher, _RedisClient_ttlRefreshInterval, _RedisClient_presence_changes_channel_get, _RedisClient_assigns_changes_channel_get, _RedisClient_channel_messages_channel_get, _RedisClient_user_leaves_channel_get, _RedisClient_cleanup, _RedisClient_handleErrors, _RedisClient_getPresenceCacheChannel, _RedisClient_getAssignsCacheChannel, _RedisClient_publishPresenceChange, _RedisClient_publishAssignsChange, _RedisClient_publishChannelMessage, _RedisClient_publishUserLeave, _RedisClient_getPresenceCache, _RedisClient_getAssignsCache, _RedisClient_sendHeartbeat, _RedisClient_startTTLRefresh, _RedisClient_registerInstance, _RedisClient_unregisterInstance, _RedisClient_unsubscribeFromChannels, _RedisClient_subscribeToChannels, _RedisClient_handleRedisMessage, _RedisClient_publishCacheMessage, _RedisClient_readCachedData, _RedisClient_subscribeToCacheChanges, _RedisClient_subscribeToChannelMessages, _RedisClient_subscribeToUserLeaves, _RedisClient_handleExit;
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ exports.RedisClient = void 0;
39
+ const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
40
+ const ioredis_1 = __importDefault(require("ioredis"));
41
+ class RedisClient {
42
+ constructor(redisOptions) {
43
+ _RedisClient_instances.add(this);
44
+ this.TTL_REFRESH_INTERVAL = 30 * 1000;
45
+ this.INSTANCE_TTL = 90;
46
+ _RedisClient_redisClient.set(this, void 0);
47
+ _RedisClient_pubClient.set(this, void 0);
48
+ _RedisClient_subClient.set(this, void 0);
49
+ _RedisClient_instanceId.set(this, void 0);
50
+ _RedisClient_assignsPublisher.set(this, void 0);
51
+ _RedisClient_presencePublisher.set(this, void 0);
52
+ _RedisClient_userLeavesPublisher.set(this, void 0);
53
+ _RedisClient_channelMessagePublisher.set(this, void 0);
54
+ _RedisClient_ttlRefreshInterval.set(this, void 0);
55
+ __classPrivateFieldSet(this, _RedisClient_redisClient, new ioredis_1.default(redisOptions), "f");
56
+ __classPrivateFieldSet(this, _RedisClient_pubClient, new ioredis_1.default(redisOptions), "f");
57
+ __classPrivateFieldSet(this, _RedisClient_subClient, new ioredis_1.default(redisOptions), "f");
58
+ __classPrivateFieldSet(this, _RedisClient_assignsPublisher, new pondsocket_common_1.Subject(), "f");
59
+ __classPrivateFieldSet(this, _RedisClient_presencePublisher, new pondsocket_common_1.Subject(), "f");
60
+ __classPrivateFieldSet(this, _RedisClient_userLeavesPublisher, new pondsocket_common_1.Subject(), "f");
61
+ __classPrivateFieldSet(this, _RedisClient_channelMessagePublisher, new pondsocket_common_1.Subject(), "f");
62
+ __classPrivateFieldSet(this, _RedisClient_instanceId, (0, pondsocket_common_1.uuid)(), "f");
63
+ }
64
+ buildClient(endpointId) {
65
+ return (channelId) => ({
66
+ channelId,
67
+ getPresenceCache: __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_getPresenceCache).bind(this, endpointId, channelId),
68
+ getAssignsCache: __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_getAssignsCache).bind(this, endpointId, channelId),
69
+ publishPresenceChange: __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_publishPresenceChange).bind(this, endpointId, channelId),
70
+ publishAssignsChange: __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_publishAssignsChange).bind(this, endpointId, channelId),
71
+ publishChannelMessage: __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_publishChannelMessage).bind(this, endpointId, channelId),
72
+ publishUserLeave: __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_publishUserLeave).bind(this, endpointId, channelId),
73
+ subscribeToUserLeaves: __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_subscribeToUserLeaves).bind(this, endpointId, channelId),
74
+ subscribeToPresenceChanges: __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_subscribeToCacheChanges).bind(this, endpointId, channelId, true),
75
+ subscribeToAssignsChanges: __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_subscribeToCacheChanges).bind(this, endpointId, channelId, false),
76
+ subscribeToChannelMessages: __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_subscribeToChannelMessages).bind(this, endpointId, channelId),
77
+ });
78
+ }
79
+ initialize() {
80
+ return __awaiter(this, void 0, void 0, function* () {
81
+ __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_handleErrors).call(this);
82
+ __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_startTTLRefresh).call(this);
83
+ yield __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_registerInstance).call(this);
84
+ yield __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_subscribeToChannels).call(this);
85
+ process.on('SIGINT', __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_handleExit).bind(this));
86
+ process.on('SIGTERM', __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_handleExit).bind(this));
87
+ });
88
+ }
89
+ shutdown() {
90
+ return __awaiter(this, void 0, void 0, function* () {
91
+ clearInterval(__classPrivateFieldGet(this, _RedisClient_ttlRefreshInterval, "f"));
92
+ yield __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_unsubscribeFromChannels).call(this);
93
+ yield __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_unregisterInstance).call(this);
94
+ yield __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_cleanup).call(this);
95
+ });
96
+ }
97
+ }
98
+ exports.RedisClient = RedisClient;
99
+ _RedisClient_redisClient = new WeakMap(), _RedisClient_pubClient = new WeakMap(), _RedisClient_subClient = new WeakMap(), _RedisClient_instanceId = new WeakMap(), _RedisClient_assignsPublisher = new WeakMap(), _RedisClient_presencePublisher = new WeakMap(), _RedisClient_userLeavesPublisher = new WeakMap(), _RedisClient_channelMessagePublisher = new WeakMap(), _RedisClient_ttlRefreshInterval = new WeakMap(), _RedisClient_instances = new WeakSet(), _RedisClient_presence_changes_channel_get = function _RedisClient_presence_changes_channel_get() {
100
+ return 'presence_changes';
101
+ }, _RedisClient_assigns_changes_channel_get = function _RedisClient_assigns_changes_channel_get() {
102
+ return 'assigns_changes';
103
+ }, _RedisClient_channel_messages_channel_get = function _RedisClient_channel_messages_channel_get() {
104
+ return 'channel_messages';
105
+ }, _RedisClient_user_leaves_channel_get = function _RedisClient_user_leaves_channel_get() {
106
+ return 'user_leaves';
107
+ }, _RedisClient_cleanup = function _RedisClient_cleanup() {
108
+ return __awaiter(this, void 0, void 0, function* () {
109
+ const pipeline = __classPrivateFieldGet(this, _RedisClient_redisClient, "f").pipeline();
110
+ const presenceKeys = yield __classPrivateFieldGet(this, _RedisClient_redisClient, "f").keys('presence_cache:*');
111
+ presenceKeys.forEach((key) => pipeline.del(key));
112
+ const assignsKeys = yield __classPrivateFieldGet(this, _RedisClient_redisClient, "f").keys('assigns_cache:*');
113
+ assignsKeys.forEach((key) => pipeline.del(key));
114
+ yield pipeline.exec();
115
+ });
116
+ }, _RedisClient_handleErrors = function _RedisClient_handleErrors() {
117
+ __classPrivateFieldGet(this, _RedisClient_redisClient, "f").on('error', (err) => console.error('Redis client error:', err));
118
+ __classPrivateFieldGet(this, _RedisClient_pubClient, "f").on('error', (err) => console.error('Redis pub client error:', err));
119
+ __classPrivateFieldGet(this, _RedisClient_subClient, "f").on('error', (err) => console.error('Redis sub client error:', err));
120
+ }, _RedisClient_getPresenceCacheChannel = function _RedisClient_getPresenceCacheChannel(endpointId, channelId) {
121
+ return `presence_cache:${endpointId}:${channelId}`;
122
+ }, _RedisClient_getAssignsCacheChannel = function _RedisClient_getAssignsCacheChannel(endpointId, channelId) {
123
+ return `assigns_cache:${endpointId}:${channelId}`;
124
+ }, _RedisClient_publishPresenceChange = function _RedisClient_publishPresenceChange(endpointId, channelId, userId, state) {
125
+ const message = {
126
+ userId,
127
+ channelId,
128
+ endpointId,
129
+ state,
130
+ };
131
+ const key = __classPrivateFieldGet(this, _RedisClient_instances, "a", _RedisClient_presence_changes_channel_get);
132
+ const cacheKey = __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_getPresenceCacheChannel).call(this, message.endpointId, message.channelId);
133
+ return __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_publishCacheMessage).call(this, key, cacheKey, message);
134
+ }, _RedisClient_publishAssignsChange = function _RedisClient_publishAssignsChange(endpointId, channelId, userId, state) {
135
+ const message = {
136
+ userId,
137
+ channelId,
138
+ endpointId,
139
+ state,
140
+ };
141
+ const key = __classPrivateFieldGet(this, _RedisClient_instances, "a", _RedisClient_assigns_changes_channel_get);
142
+ const cacheKey = __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_getAssignsCacheChannel).call(this, message.endpointId, message.channelId);
143
+ return __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_publishCacheMessage).call(this, key, cacheKey, message);
144
+ }, _RedisClient_publishChannelMessage = function _RedisClient_publishChannelMessage(endpointId, channelId, message) {
145
+ return __awaiter(this, void 0, void 0, function* () {
146
+ const messageData = JSON.stringify({
147
+ endpointId,
148
+ channelId,
149
+ message,
150
+ });
151
+ yield __classPrivateFieldGet(this, _RedisClient_pubClient, "f").publish(__classPrivateFieldGet(this, _RedisClient_instances, "a", _RedisClient_channel_messages_channel_get), messageData);
152
+ });
153
+ }, _RedisClient_publishUserLeave = function _RedisClient_publishUserLeave(endpointId, channelId, userId) {
154
+ return __awaiter(this, void 0, void 0, function* () {
155
+ const message = JSON.stringify({
156
+ endpointId,
157
+ channelId,
158
+ userId,
159
+ });
160
+ yield __classPrivateFieldGet(this, _RedisClient_pubClient, "f").publish(__classPrivateFieldGet(this, _RedisClient_instances, "a", _RedisClient_user_leaves_channel_get), message);
161
+ });
162
+ }, _RedisClient_getPresenceCache = function _RedisClient_getPresenceCache(endpointId, channelId) {
163
+ const cacheKey = __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_getPresenceCacheChannel).call(this, endpointId, channelId);
164
+ return __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_readCachedData).call(this, cacheKey);
165
+ }, _RedisClient_getAssignsCache = function _RedisClient_getAssignsCache(endpointId, channelId) {
166
+ const cacheKey = __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_getAssignsCacheChannel).call(this, endpointId, channelId);
167
+ return __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_readCachedData).call(this, cacheKey);
168
+ }, _RedisClient_sendHeartbeat = function _RedisClient_sendHeartbeat() {
169
+ return __awaiter(this, void 0, void 0, function* () {
170
+ yield __classPrivateFieldGet(this, _RedisClient_redisClient, "f").expire(`instance:${__classPrivateFieldGet(this, _RedisClient_instanceId, "f")}`, this.INSTANCE_TTL);
171
+ });
172
+ }, _RedisClient_startTTLRefresh = function _RedisClient_startTTLRefresh() {
173
+ __classPrivateFieldSet(this, _RedisClient_ttlRefreshInterval, setInterval(() => __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_sendHeartbeat).call(this), this.TTL_REFRESH_INTERVAL), "f");
174
+ }, _RedisClient_registerInstance = function _RedisClient_registerInstance() {
175
+ return __awaiter(this, void 0, void 0, function* () {
176
+ const multi = __classPrivateFieldGet(this, _RedisClient_redisClient, "f").multi();
177
+ multi.sadd('distributed_instances:', __classPrivateFieldGet(this, _RedisClient_instanceId, "f"));
178
+ multi.setex(`instance:${__classPrivateFieldGet(this, _RedisClient_instanceId, "f")}`, this.INSTANCE_TTL, '1');
179
+ yield multi.exec();
180
+ });
181
+ }, _RedisClient_unregisterInstance = function _RedisClient_unregisterInstance() {
182
+ return __awaiter(this, void 0, void 0, function* () {
183
+ const multi = __classPrivateFieldGet(this, _RedisClient_redisClient, "f").multi();
184
+ multi.srem('distributed_instances', __classPrivateFieldGet(this, _RedisClient_instanceId, "f"));
185
+ multi.del(`instance:${__classPrivateFieldGet(this, _RedisClient_instanceId, "f")}`);
186
+ multi.scard('distributed_instances');
187
+ const results = yield multi.exec();
188
+ if (results && results[2] && results[2][1] === 0) {
189
+ // No more instances, clean up
190
+ }
191
+ });
192
+ }, _RedisClient_unsubscribeFromChannels = function _RedisClient_unsubscribeFromChannels() {
193
+ return __awaiter(this, void 0, void 0, function* () {
194
+ yield __classPrivateFieldGet(this, _RedisClient_subClient, "f").unsubscribe(__classPrivateFieldGet(this, _RedisClient_instances, "a", _RedisClient_presence_changes_channel_get), __classPrivateFieldGet(this, _RedisClient_instances, "a", _RedisClient_assigns_changes_channel_get), __classPrivateFieldGet(this, _RedisClient_instances, "a", _RedisClient_channel_messages_channel_get), __classPrivateFieldGet(this, _RedisClient_instances, "a", _RedisClient_user_leaves_channel_get));
195
+ });
196
+ }, _RedisClient_subscribeToChannels = function _RedisClient_subscribeToChannels() {
197
+ return new Promise((resolve, reject) => {
198
+ __classPrivateFieldGet(this, _RedisClient_subClient, "f").subscribe(__classPrivateFieldGet(this, _RedisClient_instances, "a", _RedisClient_presence_changes_channel_get), __classPrivateFieldGet(this, _RedisClient_instances, "a", _RedisClient_assigns_changes_channel_get), __classPrivateFieldGet(this, _RedisClient_instances, "a", _RedisClient_channel_messages_channel_get), __classPrivateFieldGet(this, _RedisClient_instances, "a", _RedisClient_user_leaves_channel_get), (err) => {
199
+ if (err) {
200
+ reject(err);
201
+ }
202
+ else {
203
+ resolve();
204
+ }
205
+ });
206
+ __classPrivateFieldGet(this, _RedisClient_subClient, "f").on('message', __classPrivateFieldGet(this, _RedisClient_instances, "m", _RedisClient_handleRedisMessage).bind(this));
207
+ });
208
+ }, _RedisClient_handleRedisMessage = function _RedisClient_handleRedisMessage(channel, message) {
209
+ const data = JSON.parse(message);
210
+ switch (channel) {
211
+ case __classPrivateFieldGet(this, _RedisClient_instances, "a", _RedisClient_presence_changes_channel_get):
212
+ __classPrivateFieldGet(this, _RedisClient_presencePublisher, "f").publish(data);
213
+ break;
214
+ case __classPrivateFieldGet(this, _RedisClient_instances, "a", _RedisClient_assigns_changes_channel_get):
215
+ __classPrivateFieldGet(this, _RedisClient_assignsPublisher, "f").publish(data);
216
+ break;
217
+ case __classPrivateFieldGet(this, _RedisClient_instances, "a", _RedisClient_channel_messages_channel_get):
218
+ __classPrivateFieldGet(this, _RedisClient_channelMessagePublisher, "f").publish(data);
219
+ break;
220
+ case __classPrivateFieldGet(this, _RedisClient_instances, "a", _RedisClient_user_leaves_channel_get):
221
+ __classPrivateFieldGet(this, _RedisClient_userLeavesPublisher, "f").publish(data);
222
+ break;
223
+ default:
224
+ throw new Error(`Unknown channel: ${channel}`);
225
+ }
226
+ }, _RedisClient_publishCacheMessage = function _RedisClient_publishCacheMessage(key, cacheKey, message) {
227
+ return __awaiter(this, void 0, void 0, function* () {
228
+ const messageData = JSON.stringify(message);
229
+ if (message.state) {
230
+ yield __classPrivateFieldGet(this, _RedisClient_redisClient, "f").hset(cacheKey, message.userId, JSON.stringify(message.state));
231
+ }
232
+ else {
233
+ yield __classPrivateFieldGet(this, _RedisClient_redisClient, "f").hdel(cacheKey, message.userId);
234
+ }
235
+ yield __classPrivateFieldGet(this, _RedisClient_pubClient, "f").publish(key, messageData);
236
+ });
237
+ }, _RedisClient_readCachedData = function _RedisClient_readCachedData(cacheKey) {
238
+ return __awaiter(this, void 0, void 0, function* () {
239
+ try {
240
+ const data = yield __classPrivateFieldGet(this, _RedisClient_redisClient, "f").hgetall(cacheKey);
241
+ return new Map(Object.entries(data).map(([key, value]) => [key, JSON.parse(value)]));
242
+ }
243
+ catch (error) {
244
+ console.error(error);
245
+ return new Map();
246
+ }
247
+ });
248
+ }, _RedisClient_subscribeToCacheChanges = function _RedisClient_subscribeToCacheChanges(endpoint, channel, presence, callback) {
249
+ const subject = presence ? __classPrivateFieldGet(this, _RedisClient_presencePublisher, "f") : __classPrivateFieldGet(this, _RedisClient_assignsPublisher, "f");
250
+ return subject.subscribe((_a) => {
251
+ var { endpointId, channelId } = _a, data = __rest(_a, ["endpointId", "channelId"]);
252
+ if (endpointId === endpoint && channelId === channel) {
253
+ return callback(data);
254
+ }
255
+ });
256
+ }, _RedisClient_subscribeToChannelMessages = function _RedisClient_subscribeToChannelMessages(endpoint, channel, callback) {
257
+ return __classPrivateFieldGet(this, _RedisClient_channelMessagePublisher, "f").subscribe(({ endpointId, channelId, message }) => {
258
+ if (endpointId === endpoint && channelId === channel) {
259
+ return callback(message);
260
+ }
261
+ });
262
+ }, _RedisClient_subscribeToUserLeaves = function _RedisClient_subscribeToUserLeaves(endpoint, channel, callback) {
263
+ return __classPrivateFieldGet(this, _RedisClient_userLeavesPublisher, "f").subscribe(({ endpointId, channelId, userId }) => {
264
+ if (endpointId === endpoint && channelId === channel) {
265
+ return callback(userId);
266
+ }
267
+ });
268
+ }, _RedisClient_handleExit = function _RedisClient_handleExit() {
269
+ return __awaiter(this, void 0, void 0, function* () {
270
+ try {
271
+ yield this.shutdown();
272
+ process.exit(0);
273
+ }
274
+ catch (error) {
275
+ process.exit(1);
276
+ }
277
+ });
278
+ };
@@ -0,0 +1,163 @@
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 _ChannelEngine_instances, _ChannelEngine_manager, _ChannelEngine_getUsersFromRecipients;
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.ChannelEngine = void 0;
16
+ const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
17
+ const httpError_1 = require("../errors/httpError");
18
+ const channel_1 = require("../wrappers/channel");
19
+ class ChannelEngine {
20
+ constructor(parent, name, manager) {
21
+ _ChannelEngine_instances.add(this);
22
+ this.parent = parent;
23
+ this.name = name;
24
+ _ChannelEngine_manager.set(this, void 0);
25
+ __classPrivateFieldSet(this, _ChannelEngine_manager, manager, "f");
26
+ }
27
+ get users() {
28
+ return __classPrivateFieldGet(this, _ChannelEngine_manager, "f").userIds;
29
+ }
30
+ addUser(userId, assigns, onMessage) {
31
+ if (this.users.has(userId)) {
32
+ const message = `ChannelEngine: User with id ${userId} already exists in channel ${this.name}`;
33
+ const code = 400;
34
+ throw new httpError_1.HttpError(code, message);
35
+ }
36
+ __classPrivateFieldGet(this, _ChannelEngine_manager, "f").addUser(userId, assigns, onMessage);
37
+ this.sendMessage(pondsocket_common_1.SystemSender.CHANNEL, [userId], pondsocket_common_1.ServerActions.SYSTEM, pondsocket_common_1.Events.ACKNOWLEDGE, {});
38
+ return this.removeUser.bind(this, userId);
39
+ }
40
+ sendMessage(sender, recipient, action, event, payload, requestId = (0, pondsocket_common_1.uuid)()) {
41
+ if (!this.users.has(sender) && sender !== pondsocket_common_1.SystemSender.CHANNEL) {
42
+ const message = `ChannelEngine: User with id ${sender} does not exist in channel ${this.name}`;
43
+ const code = 404;
44
+ throw new httpError_1.HttpError(code, message);
45
+ }
46
+ const channelEvent = {
47
+ channelName: this.name,
48
+ requestId,
49
+ action,
50
+ event,
51
+ payload,
52
+ };
53
+ const recipients = __classPrivateFieldGet(this, _ChannelEngine_instances, "m", _ChannelEngine_getUsersFromRecipients).call(this, recipient, sender);
54
+ const internalEvent = Object.assign(Object.assign({}, channelEvent), { recipients });
55
+ __classPrivateFieldGet(this, _ChannelEngine_manager, "f").broadcast(internalEvent);
56
+ }
57
+ broadcastMessage(userId, message) {
58
+ if (!this.users.has(userId)) {
59
+ const message = `ChannelEngine: User with id ${userId} does not exist in channel ${this.name}`;
60
+ const code = 404;
61
+ throw new httpError_1.HttpError(code, message);
62
+ }
63
+ const responseEvent = Object.assign(Object.assign({}, message), { sender: userId, action: pondsocket_common_1.ServerActions.BROADCAST });
64
+ this.parent.middleware.run(responseEvent, this, (error) => {
65
+ this.sendMessage(pondsocket_common_1.SystemSender.CHANNEL, [userId], pondsocket_common_1.ServerActions.ERROR, pondsocket_common_1.ErrorTypes.HANDLER_NOT_FOUND, {
66
+ message: (error === null || error === void 0 ? void 0 : error.message) || 'A handler did not respond to the event',
67
+ code: (error === null || error === void 0 ? void 0 : error.statusCode) || 500,
68
+ }, message.requestId);
69
+ });
70
+ }
71
+ trackPresence(userId, presence) {
72
+ return __classPrivateFieldGet(this, _ChannelEngine_manager, "f").trackPresence(userId, presence);
73
+ }
74
+ updatePresence(userId, presence) {
75
+ return __classPrivateFieldGet(this, _ChannelEngine_manager, "f").updatePresence(userId, presence);
76
+ }
77
+ removePresence(userId) {
78
+ return __classPrivateFieldGet(this, _ChannelEngine_manager, "f").removePresence(userId);
79
+ }
80
+ upsertPresence(userId, presence) {
81
+ return __classPrivateFieldGet(this, _ChannelEngine_manager, "f").upsertPresence(userId, presence);
82
+ }
83
+ updateAssigns(userId, assigns) {
84
+ return __classPrivateFieldGet(this, _ChannelEngine_manager, "f").updateAssigns(userId, assigns);
85
+ }
86
+ kickUser(userId, reason) {
87
+ this.sendMessage(pondsocket_common_1.SystemSender.CHANNEL, [userId], pondsocket_common_1.ServerActions.SYSTEM, 'kicked_out', {
88
+ message: reason,
89
+ code: 403,
90
+ });
91
+ this.removeUser(userId);
92
+ this.sendMessage(pondsocket_common_1.SystemSender.CHANNEL, pondsocket_common_1.ChannelReceiver.ALL_USERS, pondsocket_common_1.ServerActions.SYSTEM, 'kicked', {
93
+ userId,
94
+ reason,
95
+ });
96
+ }
97
+ getAssigns() {
98
+ return Array
99
+ .from(__classPrivateFieldGet(this, _ChannelEngine_manager, "f").getAllAssigns().entries())
100
+ .reduce((acc, [id, assigns]) => {
101
+ acc[id] = assigns;
102
+ return acc;
103
+ }, {});
104
+ }
105
+ getPresence() {
106
+ return Array
107
+ .from(__classPrivateFieldGet(this, _ChannelEngine_manager, "f").getAllPresence().entries())
108
+ .reduce((acc, [id, presence]) => {
109
+ acc[id] = presence;
110
+ return acc;
111
+ }, {});
112
+ }
113
+ destroy(reason) {
114
+ this.sendMessage(pondsocket_common_1.SystemSender.CHANNEL, pondsocket_common_1.ChannelReceiver.ALL_USERS, pondsocket_common_1.ServerActions.ERROR, 'destroyed', {
115
+ message: reason !== null && reason !== void 0 ? reason : 'Channel has been destroyed',
116
+ });
117
+ __classPrivateFieldGet(this, _ChannelEngine_manager, "f").close();
118
+ }
119
+ removeUser(userId) {
120
+ const userData = __classPrivateFieldGet(this, _ChannelEngine_manager, "f").removeUser(userId);
121
+ if (this.parent.leaveCallback) {
122
+ this.parent.leaveCallback({
123
+ user: userData,
124
+ channel: new channel_1.Channel(this),
125
+ });
126
+ }
127
+ }
128
+ getUser(userId) {
129
+ return __classPrivateFieldGet(this, _ChannelEngine_manager, "f").getUserData(userId);
130
+ }
131
+ }
132
+ exports.ChannelEngine = ChannelEngine;
133
+ _ChannelEngine_manager = new WeakMap(), _ChannelEngine_instances = new WeakSet(), _ChannelEngine_getUsersFromRecipients = function _ChannelEngine_getUsersFromRecipients(recipients, sender) {
134
+ const allUsers = Array.from(this.users);
135
+ let users;
136
+ switch (recipients) {
137
+ case pondsocket_common_1.ChannelReceiver.ALL_USERS:
138
+ users = allUsers;
139
+ break;
140
+ case pondsocket_common_1.ChannelReceiver.ALL_EXCEPT_SENDER:
141
+ if (sender === pondsocket_common_1.SystemSender.CHANNEL) {
142
+ const message = `ChannelEngine: Invalid sender ${sender} for recipients ${recipients}`;
143
+ const code = 400;
144
+ throw new httpError_1.HttpError(code, message);
145
+ }
146
+ users = allUsers.filter((user) => user !== sender);
147
+ break;
148
+ default:
149
+ if (!Array.isArray(recipients)) {
150
+ const message = `ChannelEngine: Invalid recipients ${recipients} must be an array of user ids or ${pondsocket_common_1.ChannelReceiver.ALL_USERS}`;
151
+ const code = 400;
152
+ throw new httpError_1.HttpError(code, message);
153
+ }
154
+ if (recipients.some((user) => !allUsers.includes(user))) {
155
+ const message = `ChannelEngine: Invalid user ids in recipients ${recipients}`;
156
+ const code = 400;
157
+ throw new httpError_1.HttpError(code, message);
158
+ }
159
+ users = recipients;
160
+ break;
161
+ }
162
+ return users;
163
+ };