@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.
- package/abstracts/middleware.js +40 -17
- package/abstracts/redisClient.js +278 -0
- package/engines/channelEngine.js +163 -0
- package/engines/endpointEngine.js +163 -0
- package/engines/lobbyEngine.js +79 -0
- package/errors/httpError.js +11 -0
- package/index.js +2 -2
- package/managers/distributedManager.js +115 -0
- package/managers/localManager.js +41 -0
- package/managers/manager.js +219 -0
- package/managers/managerFactory.js +31 -0
- package/package.json +24 -14
- package/requests/eventRequest.js +51 -0
- package/requests/joinRequest.js +56 -0
- package/responses/connectionResponse.js +89 -0
- package/{channel → responses}/eventResponse.js +8 -79
- package/{lobby → responses}/joinResponse.js +25 -84
- package/server/{pondSocket.js → server.js} +55 -55
- package/types.d.ts +33 -104
- package/wrappers/channel.js +70 -0
- package/wrappers/endpoint.js +32 -0
- package/wrappers/pondChannel.js +48 -0
- package/abstracts/abstractRequest.js +0 -57
- package/abstracts/abstractRequest.test.js +0 -48
- package/abstracts/middleware.test.js +0 -70
- package/channel/channel.js +0 -351
- package/channel/channel.test.js +0 -435
- package/channel/eventRequest.js +0 -25
- package/channel/eventRequest.test.js +0 -30
- package/channel/eventResponse.test.js +0 -175
- package/endpoint/endpoint.js +0 -299
- package/endpoint/endpoint.test.js +0 -299
- package/endpoint/response.js +0 -129
- package/errors/pondError.js +0 -28
- package/lobby/JoinRequest.test.js +0 -50
- package/lobby/JoinResponse.test.js +0 -142
- package/lobby/joinRequest.js +0 -43
- package/lobby/lobby.js +0 -186
- package/matcher/matcher.test.js +0 -90
- package/presence/presence.js +0 -112
- package/presence/presenceEngine.test.js +0 -129
|
@@ -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
|
@@ -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
|
+
};
|