@eleven-am/pondsocket 0.1.197 → 0.1.198
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/engines/channelEngine.js +192 -39
- package/engines/endpointEngine.js +27 -15
- package/engines/lobbyEngine.js +94 -5
- package/engines/presenceEngine.js +140 -0
- package/index.js +0 -3
- package/package.json +3 -3
- package/requests/eventRequest.js +19 -1
- package/responses/eventResponse.js +30 -0
- package/responses/joinResponse.js +29 -3
- package/server/server.js +21 -32
- package/types.d.ts +32 -24
- package/wrappers/channel.js +37 -1
- package/wrappers/pondChannel.js +4 -0
- package/abstracts/redisClient.js +0 -499
- package/errors/redisError.js +0 -10
- package/managers/distributedManager.js +0 -165
- package/managers/localManager.js +0 -41
- package/managers/manager.js +0 -172
- package/managers/managerFactory.js +0 -20
|
@@ -0,0 +1,140 @@
|
|
|
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 _PresenceEngine_instances, _PresenceEngine_presenceCache, _PresenceEngine_publisher, _PresenceEngine_channelId, _PresenceEngine_processPresenceAction;
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.PresenceEngine = void 0;
|
|
16
|
+
const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
|
|
17
|
+
/**
|
|
18
|
+
* Manages user presence for a channel
|
|
19
|
+
*/
|
|
20
|
+
class PresenceEngine {
|
|
21
|
+
/**
|
|
22
|
+
* Creates a new Presence manager
|
|
23
|
+
* @param channelId - The ID of the channel this presence belongs to
|
|
24
|
+
*/
|
|
25
|
+
constructor(channelId) {
|
|
26
|
+
_PresenceEngine_instances.add(this);
|
|
27
|
+
_PresenceEngine_presenceCache.set(this, new Map());
|
|
28
|
+
_PresenceEngine_publisher.set(this, new pondsocket_common_1.Subject());
|
|
29
|
+
_PresenceEngine_channelId.set(this, void 0);
|
|
30
|
+
__classPrivateFieldSet(this, _PresenceEngine_channelId, channelId, "f");
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Gets the number of users with presence data
|
|
34
|
+
*/
|
|
35
|
+
get presenceCount() {
|
|
36
|
+
return __classPrivateFieldGet(this, _PresenceEngine_presenceCache, "f").size;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Track a new user's presence
|
|
40
|
+
* @param userId - The ID of the user
|
|
41
|
+
* @param data - The presence data
|
|
42
|
+
* @returns The generated presence event
|
|
43
|
+
*/
|
|
44
|
+
trackPresence(userId, data) {
|
|
45
|
+
return __classPrivateFieldGet(this, _PresenceEngine_instances, "m", _PresenceEngine_processPresenceAction).call(this, pondsocket_common_1.PresenceEventTypes.JOIN, userId, data);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Update an existing user's presence
|
|
49
|
+
* @param userId - The ID of the user
|
|
50
|
+
* @param data - The updated presence data
|
|
51
|
+
* @returns The generated presence event
|
|
52
|
+
*/
|
|
53
|
+
updatePresence(userId, data) {
|
|
54
|
+
return __classPrivateFieldGet(this, _PresenceEngine_instances, "m", _PresenceEngine_processPresenceAction).call(this, pondsocket_common_1.PresenceEventTypes.UPDATE, userId, data);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Remove a user's presence
|
|
58
|
+
* @param userId - The ID of the user
|
|
59
|
+
* @returns The generated presence event
|
|
60
|
+
*/
|
|
61
|
+
removePresence(userId) {
|
|
62
|
+
return __classPrivateFieldGet(this, _PresenceEngine_instances, "m", _PresenceEngine_processPresenceAction).call(this, pondsocket_common_1.PresenceEventTypes.LEAVE, userId, null);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Add or update a user's presence
|
|
66
|
+
* @param userId - The ID of the user
|
|
67
|
+
* @param data - The presence data
|
|
68
|
+
* @returns The generated presence event
|
|
69
|
+
*/
|
|
70
|
+
upsertPresence(userId, data) {
|
|
71
|
+
if (__classPrivateFieldGet(this, _PresenceEngine_presenceCache, "f").has(userId)) {
|
|
72
|
+
return this.updatePresence(userId, data);
|
|
73
|
+
}
|
|
74
|
+
return this.trackPresence(userId, data);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Get a specific user's presence
|
|
78
|
+
* @param userId - The ID of the user
|
|
79
|
+
* @returns The user's presence data or null if not found
|
|
80
|
+
*/
|
|
81
|
+
getPresence(userId) {
|
|
82
|
+
return __classPrivateFieldGet(this, _PresenceEngine_presenceCache, "f").get(userId) || null;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Get presence data for all users
|
|
86
|
+
* @returns A copy of all presence data
|
|
87
|
+
*/
|
|
88
|
+
getAllPresence() {
|
|
89
|
+
return new Map(__classPrivateFieldGet(this, _PresenceEngine_presenceCache, "f"));
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Subscribe to presence events
|
|
93
|
+
* @param callback - The callback to invoke when presence changes
|
|
94
|
+
* @returns A function to unsubscribe
|
|
95
|
+
*/
|
|
96
|
+
subscribe(callback) {
|
|
97
|
+
return __classPrivateFieldGet(this, _PresenceEngine_publisher, "f").subscribe(callback);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Clear all presence data and close the publisher
|
|
101
|
+
*/
|
|
102
|
+
close() {
|
|
103
|
+
__classPrivateFieldGet(this, _PresenceEngine_presenceCache, "f").clear();
|
|
104
|
+
__classPrivateFieldGet(this, _PresenceEngine_publisher, "f").close();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
exports.PresenceEngine = PresenceEngine;
|
|
108
|
+
_PresenceEngine_presenceCache = new WeakMap(), _PresenceEngine_publisher = new WeakMap(), _PresenceEngine_channelId = new WeakMap(), _PresenceEngine_instances = new WeakSet(), _PresenceEngine_processPresenceAction = function _PresenceEngine_processPresenceAction(action, userId, data) {
|
|
109
|
+
if (action === pondsocket_common_1.PresenceEventTypes.JOIN && __classPrivateFieldGet(this, _PresenceEngine_presenceCache, "f").has(userId)) {
|
|
110
|
+
throw new Error(`User with id ${userId} already exists in the presence cache`);
|
|
111
|
+
}
|
|
112
|
+
else if ((action === pondsocket_common_1.PresenceEventTypes.UPDATE || action === pondsocket_common_1.PresenceEventTypes.LEAVE) && !__classPrivateFieldGet(this, _PresenceEngine_presenceCache, "f").has(userId)) {
|
|
113
|
+
throw new Error(`User with id ${userId} does not exist in the presence cache`);
|
|
114
|
+
}
|
|
115
|
+
if (action !== pondsocket_common_1.PresenceEventTypes.LEAVE && !data) {
|
|
116
|
+
throw new Error(`Data is required for ${action} action`);
|
|
117
|
+
}
|
|
118
|
+
const current = __classPrivateFieldGet(this, _PresenceEngine_presenceCache, "f").get(userId);
|
|
119
|
+
if (data) {
|
|
120
|
+
__classPrivateFieldGet(this, _PresenceEngine_presenceCache, "f").set(userId, data);
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
__classPrivateFieldGet(this, _PresenceEngine_presenceCache, "f").delete(userId);
|
|
124
|
+
}
|
|
125
|
+
const total = Array.from(__classPrivateFieldGet(this, _PresenceEngine_presenceCache, "f").values());
|
|
126
|
+
const userIds = Array.from(__classPrivateFieldGet(this, _PresenceEngine_presenceCache, "f").keys());
|
|
127
|
+
// Create the presence event
|
|
128
|
+
const internalEvent = {
|
|
129
|
+
event: action,
|
|
130
|
+
requestId: (0, pondsocket_common_1.uuid)(),
|
|
131
|
+
recipients: userIds,
|
|
132
|
+
channelName: __classPrivateFieldGet(this, _PresenceEngine_channelId, "f"),
|
|
133
|
+
action: pondsocket_common_1.ServerActions.PRESENCE,
|
|
134
|
+
payload: {
|
|
135
|
+
changed: current || data || {},
|
|
136
|
+
presence: total,
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
__classPrivateFieldGet(this, _PresenceEngine_publisher, "f").publish(internalEvent);
|
|
140
|
+
};
|
package/index.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RedisError = void 0;
|
|
4
3
|
const server_1 = require("./server/server");
|
|
5
|
-
var redisError_1 = require("./errors/redisError");
|
|
6
|
-
Object.defineProperty(exports, "RedisError", { enumerable: true, get: function () { return redisError_1.RedisError; } });
|
|
7
4
|
exports.default = server_1.PondSocket;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eleven-am/pondsocket",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.198",
|
|
4
4
|
"description": "PondSocket is a fast simple socket server",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"socket",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"@types/jest": "^29.5.14",
|
|
47
47
|
"@types/node": "^22.15.3",
|
|
48
48
|
"@types/ws": "^8.18.1",
|
|
49
|
-
"@typescript-eslint/eslint-plugin": "^8.31.
|
|
50
|
-
"@typescript-eslint/parser": "^8.31.
|
|
49
|
+
"@typescript-eslint/eslint-plugin": "^8.31.1",
|
|
50
|
+
"@typescript-eslint/parser": "^8.31.1",
|
|
51
51
|
"eslint": "^9.25.1",
|
|
52
52
|
"eslint-config-prettier": "^10.1.2",
|
|
53
53
|
"eslint-import-resolver-node": "^0.3.9",
|
package/requests/eventRequest.js
CHANGED
|
@@ -23,6 +23,9 @@ class EventRequest {
|
|
|
23
23
|
__classPrivateFieldSet(this, _EventRequest_params, params, "f");
|
|
24
24
|
__classPrivateFieldSet(this, _EventRequest_engine, engine, "f");
|
|
25
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* The event information
|
|
28
|
+
*/
|
|
26
29
|
get event() {
|
|
27
30
|
return {
|
|
28
31
|
event: __classPrivateFieldGet(this, _EventRequest_event, "f").event,
|
|
@@ -31,20 +34,35 @@ class EventRequest {
|
|
|
31
34
|
payload: __classPrivateFieldGet(this, _EventRequest_event, "f").payload,
|
|
32
35
|
};
|
|
33
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* The channel name
|
|
39
|
+
*/
|
|
34
40
|
get channelName() {
|
|
35
41
|
return __classPrivateFieldGet(this, _EventRequest_engine, "f").name;
|
|
36
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* The channel instance
|
|
45
|
+
*/
|
|
37
46
|
get channel() {
|
|
38
47
|
return new channel_1.Channel(__classPrivateFieldGet(this, _EventRequest_engine, "f"));
|
|
39
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* All current presences in the channel
|
|
51
|
+
*/
|
|
40
52
|
get presences() {
|
|
41
53
|
return __classPrivateFieldGet(this, _EventRequest_engine, "f").getPresence();
|
|
42
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* All current assigns in the channel
|
|
57
|
+
*/
|
|
43
58
|
get assigns() {
|
|
44
59
|
return __classPrivateFieldGet(this, _EventRequest_engine, "f").getAssigns();
|
|
45
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* The user who sent the request
|
|
63
|
+
*/
|
|
46
64
|
get user() {
|
|
47
|
-
return __classPrivateFieldGet(this, _EventRequest_engine, "f").
|
|
65
|
+
return __classPrivateFieldGet(this, _EventRequest_engine, "f").getUserData(__classPrivateFieldGet(this, _EventRequest_event, "f").sender);
|
|
48
66
|
}
|
|
49
67
|
}
|
|
50
68
|
exports.EventRequest = EventRequest;
|
|
@@ -24,42 +24,72 @@ class EventResponse {
|
|
|
24
24
|
__classPrivateFieldSet(this, _EventResponse_engine, engine, "f");
|
|
25
25
|
__classPrivateFieldSet(this, _EventResponse_requestId, event.requestId, "f");
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Whether the response has been handled
|
|
29
|
+
*/
|
|
27
30
|
get hasResponded() {
|
|
28
31
|
return false;
|
|
29
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Assigns data to the client
|
|
35
|
+
*/
|
|
30
36
|
assign(assigns) {
|
|
31
37
|
__classPrivateFieldGet(this, _EventResponse_engine, "f").updateAssigns(__classPrivateFieldGet(this, _EventResponse_event, "f").sender, assigns);
|
|
32
38
|
return this;
|
|
33
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Sends a direct reply to the client
|
|
42
|
+
*/
|
|
34
43
|
reply(event, payload) {
|
|
35
44
|
__classPrivateFieldGet(this, _EventResponse_engine, "f").sendMessage(pondsocket_common_1.SystemSender.CHANNEL, [__classPrivateFieldGet(this, _EventResponse_event, "f").sender], pondsocket_common_1.ServerActions.SYSTEM, event, payload, __classPrivateFieldGet(this, _EventResponse_requestId, "f"));
|
|
36
45
|
return this;
|
|
37
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Broadcasts a message to all users in the channel
|
|
49
|
+
*/
|
|
38
50
|
broadcast(event, payload) {
|
|
39
51
|
__classPrivateFieldGet(this, _EventResponse_instances, "m", _EventResponse_sendMessage).call(this, pondsocket_common_1.ChannelReceiver.ALL_USERS, event, payload);
|
|
40
52
|
return this;
|
|
41
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Broadcasts a message to all users except the sender
|
|
56
|
+
*/
|
|
42
57
|
broadcastFrom(event, payload) {
|
|
43
58
|
__classPrivateFieldGet(this, _EventResponse_instances, "m", _EventResponse_sendMessage).call(this, pondsocket_common_1.ChannelReceiver.ALL_EXCEPT_SENDER, event, payload);
|
|
44
59
|
return this;
|
|
45
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Broadcasts a message to specific users
|
|
63
|
+
*/
|
|
46
64
|
broadcastTo(event, payload, userIds) {
|
|
47
65
|
const ids = Array.isArray(userIds) ? userIds : [userIds];
|
|
48
66
|
__classPrivateFieldGet(this, _EventResponse_instances, "m", _EventResponse_sendMessage).call(this, ids, event, payload);
|
|
49
67
|
return this;
|
|
50
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Tracks a user's presence
|
|
71
|
+
*/
|
|
51
72
|
trackPresence(presence, userId = __classPrivateFieldGet(this, _EventResponse_event, "f").sender) {
|
|
52
73
|
__classPrivateFieldGet(this, _EventResponse_engine, "f").trackPresence(userId, presence);
|
|
53
74
|
return this;
|
|
54
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Updates a user's presence
|
|
78
|
+
*/
|
|
55
79
|
updatePresence(presence, userId = __classPrivateFieldGet(this, _EventResponse_event, "f").sender) {
|
|
56
80
|
__classPrivateFieldGet(this, _EventResponse_engine, "f").updatePresence(userId, presence);
|
|
57
81
|
return this;
|
|
58
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Kicks a user from the channel
|
|
85
|
+
*/
|
|
59
86
|
evictUser(reason, userId = __classPrivateFieldGet(this, _EventResponse_event, "f").sender) {
|
|
60
87
|
__classPrivateFieldGet(this, _EventResponse_engine, "f").kickUser(userId, reason);
|
|
61
88
|
return this;
|
|
62
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Removes a user's presence
|
|
92
|
+
*/
|
|
63
93
|
removePresence(userId = __classPrivateFieldGet(this, _EventResponse_event, "f").sender) {
|
|
64
94
|
__classPrivateFieldGet(this, _EventResponse_engine, "f").removePresence(userId);
|
|
65
95
|
return this;
|
|
@@ -29,9 +29,15 @@ class JoinResponse {
|
|
|
29
29
|
__classPrivateFieldSet(this, _JoinResponse_accepted, false, "f");
|
|
30
30
|
__classPrivateFieldSet(this, _JoinResponse_newAssigns, Object.assign({}, user.assigns), "f");
|
|
31
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Whether the request has been handled
|
|
34
|
+
*/
|
|
32
35
|
get hasResponded() {
|
|
33
36
|
return __classPrivateFieldGet(this, _JoinResponse_executed, "f");
|
|
34
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Accepts the join request
|
|
40
|
+
*/
|
|
35
41
|
accept() {
|
|
36
42
|
__classPrivateFieldGet(this, _JoinResponse_instances, "m", _JoinResponse_performChecks).call(this);
|
|
37
43
|
const onMessage = __classPrivateFieldGet(this, _JoinResponse_engine, "f").parent.parent.sendMessage.bind(__classPrivateFieldGet(this, _JoinResponse_engine, "f").parent.parent, __classPrivateFieldGet(this, _JoinResponse_user, "f").socket);
|
|
@@ -40,6 +46,9 @@ class JoinResponse {
|
|
|
40
46
|
__classPrivateFieldSet(this, _JoinResponse_accepted, true, "f");
|
|
41
47
|
return this;
|
|
42
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Declines the join request
|
|
51
|
+
*/
|
|
43
52
|
decline(message, errorCode) {
|
|
44
53
|
__classPrivateFieldGet(this, _JoinResponse_instances, "m", _JoinResponse_performChecks).call(this);
|
|
45
54
|
const errorMessage = {
|
|
@@ -55,15 +64,21 @@ class JoinResponse {
|
|
|
55
64
|
__classPrivateFieldGet(this, _JoinResponse_instances, "m", _JoinResponse_directMessage).call(this, errorMessage);
|
|
56
65
|
return this;
|
|
57
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Assigns data to the user
|
|
69
|
+
*/
|
|
58
70
|
assign(assigns) {
|
|
59
71
|
if (__classPrivateFieldGet(this, _JoinResponse_accepted, "f")) {
|
|
60
|
-
|
|
72
|
+
__classPrivateFieldGet(this, _JoinResponse_engine, "f").updateAssigns(__classPrivateFieldGet(this, _JoinResponse_user, "f").clientId, assigns);
|
|
61
73
|
}
|
|
62
74
|
else {
|
|
63
75
|
__classPrivateFieldSet(this, _JoinResponse_newAssigns, Object.assign(Object.assign({}, __classPrivateFieldGet(this, _JoinResponse_newAssigns, "f")), assigns), "f");
|
|
64
76
|
}
|
|
65
77
|
return this;
|
|
66
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* Sends a direct reply to the user
|
|
81
|
+
*/
|
|
67
82
|
reply(event, payload) {
|
|
68
83
|
const message = {
|
|
69
84
|
action: pondsocket_common_1.ServerActions.SYSTEM,
|
|
@@ -75,19 +90,31 @@ class JoinResponse {
|
|
|
75
90
|
__classPrivateFieldGet(this, _JoinResponse_instances, "m", _JoinResponse_directMessage).call(this, message);
|
|
76
91
|
return this;
|
|
77
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* Broadcasts a message to specific users
|
|
95
|
+
*/
|
|
78
96
|
broadcastTo(event, payload, userIds) {
|
|
79
97
|
const ids = Array.isArray(userIds) ? userIds : [userIds];
|
|
80
98
|
__classPrivateFieldGet(this, _JoinResponse_instances, "m", _JoinResponse_sendMessage).call(this, ids, event, payload);
|
|
81
99
|
return this;
|
|
82
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* Broadcasts a message to all users in the channel
|
|
103
|
+
*/
|
|
83
104
|
broadcast(event, payload) {
|
|
84
105
|
__classPrivateFieldGet(this, _JoinResponse_instances, "m", _JoinResponse_sendMessage).call(this, pondsocket_common_1.ChannelReceiver.ALL_USERS, event, payload);
|
|
85
106
|
return this;
|
|
86
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* Broadcasts a message to all users except the sender
|
|
110
|
+
*/
|
|
87
111
|
broadcastFrom(event, payload) {
|
|
88
112
|
__classPrivateFieldGet(this, _JoinResponse_instances, "m", _JoinResponse_sendMessage).call(this, pondsocket_common_1.ChannelReceiver.ALL_EXCEPT_SENDER, event, payload);
|
|
89
113
|
return this;
|
|
90
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* Tracks the user's presence
|
|
117
|
+
*/
|
|
91
118
|
trackPresence(presence) {
|
|
92
119
|
__classPrivateFieldGet(this, _JoinResponse_engine, "f").trackPresence(__classPrivateFieldGet(this, _JoinResponse_user, "f").clientId, presence);
|
|
93
120
|
return this;
|
|
@@ -101,8 +128,7 @@ _JoinResponse_user = new WeakMap(), _JoinResponse_engine = new WeakMap(), _JoinR
|
|
|
101
128
|
}, _JoinResponse_performChecks = function _JoinResponse_performChecks() {
|
|
102
129
|
if (__classPrivateFieldGet(this, _JoinResponse_executed, "f")) {
|
|
103
130
|
const message = `Request to join channel ${__classPrivateFieldGet(this, _JoinResponse_engine, "f").name} rejected: Request already executed`;
|
|
104
|
-
|
|
105
|
-
throw new httpError_1.HttpError(code, message);
|
|
131
|
+
throw new httpError_1.HttpError(403, message);
|
|
106
132
|
}
|
|
107
133
|
__classPrivateFieldSet(this, _JoinResponse_executed, true, "f");
|
|
108
134
|
};
|
package/server/server.js
CHANGED
|
@@ -1,13 +1,4 @@
|
|
|
1
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
2
|
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
12
3
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
13
4
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
@@ -19,48 +10,47 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
19
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");
|
|
20
11
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
21
12
|
};
|
|
22
|
-
var _PondSocket_instances, _PondSocket_exclusiveServer, _PondSocket_server, _PondSocket_socketServer,
|
|
13
|
+
var _PondSocket_instances, _PondSocket_exclusiveServer, _PondSocket_server, _PondSocket_socketServer, _PondSocket_middleware, _PondSocket_manageHeartbeat, _PondSocket_init, _PondSocket_getCookies;
|
|
23
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
15
|
exports.PondSocket = void 0;
|
|
25
16
|
const http_1 = require("http");
|
|
26
17
|
const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
|
|
27
18
|
const ws_1 = require("ws");
|
|
28
19
|
const middleware_1 = require("../abstracts/middleware");
|
|
29
|
-
const redisClient_1 = require("../abstracts/redisClient");
|
|
30
20
|
const endpointEngine_1 = require("../engines/endpointEngine");
|
|
31
21
|
const matcher_1 = require("../matcher/matcher");
|
|
32
22
|
const connectionResponse_1 = require("../responses/connectionResponse");
|
|
33
23
|
const endpoint_1 = require("../wrappers/endpoint");
|
|
34
24
|
class PondSocket {
|
|
35
|
-
constructor({ server, socketServer,
|
|
25
|
+
constructor({ server, socketServer, exclusiveServer = true } = {}) {
|
|
36
26
|
_PondSocket_instances.add(this);
|
|
37
27
|
_PondSocket_exclusiveServer.set(this, void 0);
|
|
38
28
|
_PondSocket_server.set(this, void 0);
|
|
39
29
|
_PondSocket_socketServer.set(this, void 0);
|
|
40
|
-
_PondSocket_redisClient.set(this, void 0);
|
|
41
30
|
_PondSocket_middleware.set(this, void 0);
|
|
42
31
|
__classPrivateFieldSet(this, _PondSocket_middleware, new middleware_1.Middleware(), "f");
|
|
43
32
|
__classPrivateFieldSet(this, _PondSocket_exclusiveServer, exclusiveServer, "f");
|
|
44
33
|
__classPrivateFieldSet(this, _PondSocket_server, server !== null && server !== void 0 ? server : new http_1.Server(), "f");
|
|
45
|
-
__classPrivateFieldSet(this, _PondSocket_redisClient, redisOptions ? new redisClient_1.RedisClient(redisOptions) : null, "f");
|
|
46
34
|
__classPrivateFieldSet(this, _PondSocket_socketServer, socketServer !== null && socketServer !== void 0 ? socketServer : new ws_1.WebSocketServer({ noServer: true }), "f");
|
|
47
35
|
__classPrivateFieldGet(this, _PondSocket_instances, "m", _PondSocket_init).call(this);
|
|
48
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Start listening for connections
|
|
39
|
+
*/
|
|
49
40
|
listen(...args) {
|
|
50
|
-
|
|
51
|
-
__classPrivateFieldGet(this, _PondSocket_redisClient, "f").initialize()
|
|
52
|
-
.then(() => __classPrivateFieldGet(this, _PondSocket_server, "f").listen(...args));
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
return __classPrivateFieldGet(this, _PondSocket_server, "f").listen(...args);
|
|
56
|
-
}
|
|
41
|
+
return __classPrivateFieldGet(this, _PondSocket_server, "f").listen(...args);
|
|
57
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Close the server
|
|
45
|
+
*/
|
|
58
46
|
close(callback) {
|
|
59
47
|
return __classPrivateFieldGet(this, _PondSocket_server, "f").close(callback);
|
|
60
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Create a new endpoint
|
|
51
|
+
*/
|
|
61
52
|
createEndpoint(path, handler) {
|
|
62
|
-
|
|
63
|
-
const endpoint = new endpointEngine_1.EndpointEngine((_b = (_a = __classPrivateFieldGet(this, _PondSocket_redisClient, "f")) === null || _a === void 0 ? void 0 : _a.buildClient(String(path))) !== null && _b !== void 0 ? _b : null);
|
|
53
|
+
const endpoint = new endpointEngine_1.EndpointEngine();
|
|
64
54
|
__classPrivateFieldGet(this, _PondSocket_middleware, "f").use((req, params, next) => {
|
|
65
55
|
const event = (0, matcher_1.parseAddress)(path, req.address);
|
|
66
56
|
if (event) {
|
|
@@ -77,6 +67,9 @@ class PondSocket {
|
|
|
77
67
|
});
|
|
78
68
|
return new endpoint_1.Endpoint(endpoint);
|
|
79
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Handle WebSocket upgrade requests
|
|
72
|
+
*/
|
|
80
73
|
handleUpgrade(req, socket, head) {
|
|
81
74
|
const clientId = req.headers['sec-websocket-key'];
|
|
82
75
|
const request = {
|
|
@@ -105,7 +98,7 @@ class PondSocket {
|
|
|
105
98
|
}
|
|
106
99
|
}
|
|
107
100
|
exports.PondSocket = PondSocket;
|
|
108
|
-
_PondSocket_exclusiveServer = new WeakMap(), _PondSocket_server = new WeakMap(), _PondSocket_socketServer = new WeakMap(),
|
|
101
|
+
_PondSocket_exclusiveServer = new WeakMap(), _PondSocket_server = new WeakMap(), _PondSocket_socketServer = new WeakMap(), _PondSocket_middleware = new WeakMap(), _PondSocket_instances = new WeakSet(), _PondSocket_manageHeartbeat = function _PondSocket_manageHeartbeat() {
|
|
109
102
|
__classPrivateFieldGet(this, _PondSocket_socketServer, "f").on('connection', (socket) => {
|
|
110
103
|
socket.on('pong', () => {
|
|
111
104
|
socket.isAlive = true;
|
|
@@ -122,17 +115,13 @@ _PondSocket_exclusiveServer = new WeakMap(), _PondSocket_server = new WeakMap(),
|
|
|
122
115
|
}, 30000);
|
|
123
116
|
}, _PondSocket_init = function _PondSocket_init() {
|
|
124
117
|
const timeout = __classPrivateFieldGet(this, _PondSocket_instances, "m", _PondSocket_manageHeartbeat).call(this);
|
|
125
|
-
__classPrivateFieldGet(this, _PondSocket_server, "f").on('error', (error) =>
|
|
126
|
-
var _a;
|
|
118
|
+
__classPrivateFieldGet(this, _PondSocket_server, "f").on('error', (error) => {
|
|
127
119
|
clearInterval(timeout);
|
|
128
|
-
yield ((_a = __classPrivateFieldGet(this, _PondSocket_redisClient, "f")) === null || _a === void 0 ? void 0 : _a.shutdown());
|
|
129
120
|
throw new Error(error.message);
|
|
130
|
-
})
|
|
131
|
-
__classPrivateFieldGet(this, _PondSocket_server, "f").on('close', () =>
|
|
132
|
-
var _a;
|
|
121
|
+
});
|
|
122
|
+
__classPrivateFieldGet(this, _PondSocket_server, "f").on('close', () => {
|
|
133
123
|
clearInterval(timeout);
|
|
134
|
-
|
|
135
|
-
}));
|
|
124
|
+
});
|
|
136
125
|
__classPrivateFieldGet(this, _PondSocket_server, "f").on('upgrade', this.handleUpgrade.bind(this));
|
|
137
126
|
}, _PondSocket_getCookies = function _PondSocket_getCookies(headers) {
|
|
138
127
|
const cookieHeader = headers.cookie;
|
package/types.d.ts
CHANGED
|
@@ -12,33 +12,32 @@ import {
|
|
|
12
12
|
UserPresences,
|
|
13
13
|
UserAssigns,
|
|
14
14
|
JoinParams,
|
|
15
|
+
EventParams,
|
|
15
16
|
} from '@eleven-am/pondsocket-common';
|
|
16
17
|
import { WebSocket, WebSocketServer } from 'ws';
|
|
17
18
|
|
|
18
19
|
export * from '@eleven-am/pondsocket-common';
|
|
19
20
|
|
|
20
|
-
export interface RedisOptions {
|
|
21
|
-
host: string;
|
|
22
|
-
port: number;
|
|
23
|
-
db?: number;
|
|
24
|
-
username?: string;
|
|
25
|
-
password?: string;
|
|
26
|
-
instanceTtl?: number;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
21
|
export interface LeaveEvent<EventTypes extends PondEventMap = PondEventMap, PresenceType extends PondPresence = PondPresence, AssignType extends PondAssigns = PondAssigns> {
|
|
30
22
|
user: UserData<PresenceType, AssignType>;
|
|
31
23
|
channel: Channel<EventTypes, PresenceType, AssignType>;
|
|
32
24
|
}
|
|
33
25
|
|
|
26
|
+
export interface OutgoingEvent<Event extends string, EventTypes extends PondEventMap = PondEventMap, PresenceType extends PondPresence = PondPresence, AssignType extends PondAssigns = PondAssigns> {
|
|
27
|
+
payload: PondMessage;
|
|
28
|
+
event: EventParams<Event>;
|
|
29
|
+
channel: Channel<EventTypes, PresenceType, AssignType>;
|
|
30
|
+
}
|
|
31
|
+
|
|
34
32
|
export type LeaveCallback<EventTypes extends PondEventMap = PondEventMap, PresenceType extends PondPresence = PondPresence, AssignType extends PondAssigns = PondAssigns> = (event: LeaveEvent<EventTypes, PresenceType, AssignType>) => void;
|
|
35
33
|
|
|
34
|
+
export type OutgoingHandler<Event extends string, EventTypes extends PondEventMap = PondEventMap, PresenceType extends PondPresence = PondPresence, AssignType extends PondAssigns = PondAssigns> = (event: OutgoingEvent<Event, EventTypes, PresenceType, AssignType>) => PondMessage | Promise<PondMessage> | void | Promise<void>;
|
|
35
|
+
|
|
36
36
|
export type RequestHandler<Request, Response> = (request: Request, response: Response) => void | Promise<void>;
|
|
37
37
|
|
|
38
38
|
export interface PondSocketOptions {
|
|
39
39
|
server?: Server;
|
|
40
40
|
exclusiveServer?: boolean;
|
|
41
|
-
redisOptions?: RedisOptions;
|
|
42
41
|
socketServer?: WebSocketServer;
|
|
43
42
|
}
|
|
44
43
|
|
|
@@ -130,6 +129,19 @@ export declare class PondChannel<EventType extends PondEventMap = PondEventMap,
|
|
|
130
129
|
*/
|
|
131
130
|
onLeave(callback: LeaveCallback<EventType, PresenceType, AssignType>): void;
|
|
132
131
|
|
|
132
|
+
/**
|
|
133
|
+
* @desc Handles an outgoing event, this is useful for modifying the event before it is sent to the client
|
|
134
|
+
* @param {PondPath<string>} event - The event to handle
|
|
135
|
+
* @param {OutgoingHandler} handler - The handler to execute when the event is sent
|
|
136
|
+
* @example
|
|
137
|
+
* pond.onOutgoing('echo', (event) => {
|
|
138
|
+
* return {
|
|
139
|
+
* message: 'Hello, world!'
|
|
140
|
+
* };
|
|
141
|
+
* });
|
|
142
|
+
*/
|
|
143
|
+
onOutgoing<Event extends string> (event: PondPath<Event>, handler: OutgoingHandler<Event, EventType, PresenceType, AssignType>): void;
|
|
144
|
+
|
|
133
145
|
/**
|
|
134
146
|
* @desc Gets a channel by name
|
|
135
147
|
* @param {string} channelName - The name of the channel to get
|
|
@@ -185,7 +197,7 @@ export declare class PondChannel<EventType extends PondEventMap = PondEventMap,
|
|
|
185
197
|
broadcastTo <Key extends keyof EventType> (channelName: string, event: Key, payload: EventType[Key], userIds: string | string[]): void;
|
|
186
198
|
}
|
|
187
199
|
|
|
188
|
-
export declare class Channel<
|
|
200
|
+
export declare class Channel<EventTypes extends PondEventMap = PondEventMap, PresenceType extends PondPresence = PondPresence, AssignType extends PondAssigns = PondAssigns> {
|
|
189
201
|
/**
|
|
190
202
|
* The name of the channel.
|
|
191
203
|
*/
|
|
@@ -212,7 +224,7 @@ export declare class Channel<EventType extends PondEventMap = PondEventMap, Pres
|
|
|
212
224
|
* @param {string} event - The event to send.
|
|
213
225
|
* @param {PondMessage} payload - The message to send.
|
|
214
226
|
*/
|
|
215
|
-
broadcast<Key extends keyof
|
|
227
|
+
broadcast<Key extends keyof EventTypes>(event: Key, payload: EventTypes[Key]): Channel<EventTypes, PresenceType, AssignType>;
|
|
216
228
|
|
|
217
229
|
/**
|
|
218
230
|
* @desc Broadcasts a message to every client in the channel except the sender,
|
|
@@ -220,7 +232,7 @@ export declare class Channel<EventType extends PondEventMap = PondEventMap, Pres
|
|
|
220
232
|
* @param {string} event - The event to send.
|
|
221
233
|
* @param {PondMessage} payload - The message to send.
|
|
222
234
|
*/
|
|
223
|
-
broadcastFrom<Key extends keyof
|
|
235
|
+
broadcastFrom<Key extends keyof EventTypes>(userId: string, event: Key, payload: EventTypes[Key]): Channel<EventTypes, PresenceType, AssignType>;
|
|
224
236
|
|
|
225
237
|
/**
|
|
226
238
|
* @desc Sends a message to a specific client in the channel.
|
|
@@ -228,48 +240,48 @@ export declare class Channel<EventType extends PondEventMap = PondEventMap, Pres
|
|
|
228
240
|
* @param {string} event - The event to send.
|
|
229
241
|
* @param {PondMessage} payload - The message to send.
|
|
230
242
|
*/
|
|
231
|
-
broadcastTo<Key extends keyof
|
|
243
|
+
broadcastTo<Key extends keyof EventTypes>(clientIds: string | string[], event: Key, payload: EventTypes[Key]): Channel<EventTypes, PresenceType, AssignType>;
|
|
232
244
|
|
|
233
245
|
/**
|
|
234
246
|
* @desc Bans a user from the channel.
|
|
235
247
|
* @param {string} userId - The id of the user to ban.
|
|
236
248
|
* @param {string} reason - The reason for the ban.
|
|
237
249
|
*/
|
|
238
|
-
evictUser(userId: string, reason?: string): Channel<
|
|
250
|
+
evictUser(userId: string, reason?: string): Channel<EventTypes, PresenceType, AssignType>;
|
|
239
251
|
|
|
240
252
|
/**
|
|
241
253
|
* @desc tracks a user's presence in the channel
|
|
242
254
|
* @param {string} userId - the id of the user to track
|
|
243
255
|
* @param {PondPresence} presence - the presence data to track
|
|
244
256
|
*/
|
|
245
|
-
trackPresence(userId: string, presence: PresenceType): Channel<
|
|
257
|
+
trackPresence(userId: string, presence: PresenceType): Channel<EventTypes, PresenceType, AssignType>;
|
|
246
258
|
|
|
247
259
|
/**
|
|
248
260
|
* @desc removes a user's presence from the channel
|
|
249
261
|
* @param {string} userId - the id of the user to remove
|
|
250
262
|
*/
|
|
251
|
-
removePresence(userId: string): Channel<
|
|
263
|
+
removePresence(userId: string): Channel<EventTypes, PresenceType, AssignType>;
|
|
252
264
|
|
|
253
265
|
/**
|
|
254
266
|
* @desc updates a user's presence in the channel
|
|
255
267
|
* @param {string} userId - the id of the user to update
|
|
256
268
|
* @param {PondPresence} presence - the presence data to update
|
|
257
269
|
*/
|
|
258
|
-
updatePresence(userId: string, presence: Partial<PresenceType>): Channel<
|
|
270
|
+
updatePresence(userId: string, presence: Partial<PresenceType>): Channel<EventTypes, PresenceType, AssignType>;
|
|
259
271
|
|
|
260
272
|
/**
|
|
261
273
|
* @desc Updates a user's assigns in the channel
|
|
262
274
|
* @param userId - the id of the user to update
|
|
263
275
|
* @param assigns - the assigns data to update
|
|
264
276
|
*/
|
|
265
|
-
updateAssigns(userId: string, assigns: Partial<AssignType>): Channel<
|
|
277
|
+
updateAssigns(userId: string, assigns: Partial<AssignType>): Channel<EventTypes, PresenceType, AssignType>;
|
|
266
278
|
|
|
267
279
|
/**
|
|
268
280
|
* @desc Tracks or updates a user's presence in the channel
|
|
269
281
|
* @param userId - the id of the user to upsert
|
|
270
282
|
* @param presence - the presence data to upsert
|
|
271
283
|
*/
|
|
272
|
-
upsertPresence
|
|
284
|
+
upsertPresence(userId: string, presence: PresenceType): Channel<EventTypes, PresenceType, AssignType>;
|
|
273
285
|
}
|
|
274
286
|
|
|
275
287
|
export declare class JoinRequest<Path extends string, PresenceType extends PondPresence = PondPresence, AssignType extends PondAssigns = PondAssigns> {
|
|
@@ -474,7 +486,3 @@ export declare class EventResponse<EventType extends PondEventMap = PondEventMap
|
|
|
474
486
|
*/
|
|
475
487
|
evictUser(reason: string, userId?: string): EventResponse;
|
|
476
488
|
}
|
|
477
|
-
|
|
478
|
-
export declare class RedisError extends Error {
|
|
479
|
-
constructor(message: string);
|
|
480
|
-
}
|