@eleven-am/pondsocket 0.1.214 → 0.1.215
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/distributor.d.ts +13 -0
- package/abstracts/distributor.js +121 -54
- package/abstracts/middleware.d.ts +22 -0
- package/abstracts/middleware.js +8 -1
- package/abstracts/types.d.ts +64 -0
- package/abstracts/types.js +0 -14
- package/contexts/baseContext.d.ts +20 -0
- package/contexts/baseContext.js +17 -25
- package/contexts/connectionContext.d.ts +66 -0
- package/contexts/eventContext.d.ts +15 -0
- package/contexts/eventContext.js +5 -49
- package/contexts/joinContext.d.ts +17 -0
- package/contexts/joinContext.js +5 -54
- package/contexts/outgoingContext.d.ts +28 -0
- package/contexts/outgoingContext.js +3 -0
- package/engines/channelEngine.d.ts +26 -0
- package/engines/channelEngine.js +212 -192
- package/engines/endpointEngine.d.ts +34 -0
- package/engines/endpointEngine.js +15 -7
- package/engines/lobbyEngine.d.ts +54 -0
- package/engines/lobbyEngine.js +1 -1
- package/engines/presenceEngine.d.ts +15 -0
- package/engines/presenceEngine.js +6 -59
- package/errors/httpError.d.ts +6 -0
- package/errors/httpError.js +2 -0
- package/index.d.ts +14 -5
- package/index.js +37 -3
- package/matcher/matcher.d.ts +2 -0
- package/matcher/matcher.js +5 -5
- package/package.json +41 -18
- package/server/server.d.ts +21 -0
- package/server/server.js +48 -12
- package/types.d.ts +32 -621
- package/types.js +16 -0
- package/wrappers/channel.d.ts +54 -0
- package/wrappers/endpoint.d.ts +10 -0
- package/wrappers/pondChannel.d.ts +15 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Unsubscribe } from '@eleven-am/pondsocket-common';
|
|
2
|
+
import { DistributedChannelMessage, IDistributedBackend, RedisDistributedBackendOptions } from '../types';
|
|
3
|
+
export declare class RedisDistributedBackend implements IDistributedBackend {
|
|
4
|
+
#private;
|
|
5
|
+
get nodeId(): string;
|
|
6
|
+
get heartbeatTimeoutMs(): number;
|
|
7
|
+
constructor(options?: RedisDistributedBackendOptions);
|
|
8
|
+
subscribeToChannel(endpointName: string, channelName: string, handler: (message: DistributedChannelMessage) => void): Promise<Unsubscribe>;
|
|
9
|
+
subscribeToHeartbeats(handler: (nodeId: string) => void): Unsubscribe;
|
|
10
|
+
broadcast(endpointName: string, channelName: string, message: DistributedChannelMessage): Promise<void>;
|
|
11
|
+
cleanup(): Promise<void>;
|
|
12
|
+
initialize(): Promise<void>;
|
|
13
|
+
}
|
package/abstracts/distributor.js
CHANGED
|
@@ -8,84 +8,113 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
12
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
13
|
+
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");
|
|
14
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
15
|
+
};
|
|
11
16
|
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
12
17
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
13
18
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
14
19
|
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
20
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
16
21
|
};
|
|
17
|
-
var
|
|
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 _RedisDistributedBackend_instances, _RedisDistributedBackend_publishClient, _RedisDistributedBackend_subscribeClient, _RedisDistributedBackend_keyPrefix, _RedisDistributedBackend_subject, _RedisDistributedBackend_nodeId, _RedisDistributedBackend_isConnected, _RedisDistributedBackend_initialize, _RedisDistributedBackend_handleRedisMessage, _RedisDistributedBackend_isValidMessage, _RedisDistributedBackend_buildKey;
|
|
22
|
+
var _RedisDistributedBackend_instances, _RedisDistributedBackend_publishClient, _RedisDistributedBackend_subscribeClient, _RedisDistributedBackend_keyPrefix, _RedisDistributedBackend_heartbeatSubject, _RedisDistributedBackend_nodeId, _RedisDistributedBackend_heartbeatIntervalMs, _RedisDistributedBackend_heartbeatTimeoutMs, _RedisDistributedBackend_onError, _RedisDistributedBackend_isConnected, _RedisDistributedBackend_heartbeatTimer, _RedisDistributedBackend_attachEventHandlers, _RedisDistributedBackend_startHeartbeat, _RedisDistributedBackend_publishHeartbeat, _RedisDistributedBackend_handleHeartbeatMessage, _RedisDistributedBackend_isValidMessage, _RedisDistributedBackend_buildKey;
|
|
23
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
24
|
exports.RedisDistributedBackend = void 0;
|
|
25
25
|
const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
|
|
26
26
|
const redis_1 = require("redis");
|
|
27
|
-
const types_1 = require("
|
|
27
|
+
const types_1 = require("../types");
|
|
28
28
|
class RedisDistributedBackend {
|
|
29
|
+
get nodeId() {
|
|
30
|
+
return __classPrivateFieldGet(this, _RedisDistributedBackend_nodeId, "f");
|
|
31
|
+
}
|
|
32
|
+
get heartbeatTimeoutMs() {
|
|
33
|
+
return __classPrivateFieldGet(this, _RedisDistributedBackend_heartbeatTimeoutMs, "f");
|
|
34
|
+
}
|
|
29
35
|
constructor(options = {}) {
|
|
30
36
|
_RedisDistributedBackend_instances.add(this);
|
|
31
37
|
_RedisDistributedBackend_publishClient.set(this, void 0);
|
|
32
38
|
_RedisDistributedBackend_subscribeClient.set(this, void 0);
|
|
33
39
|
_RedisDistributedBackend_keyPrefix.set(this, void 0);
|
|
34
|
-
|
|
40
|
+
_RedisDistributedBackend_heartbeatSubject.set(this, void 0);
|
|
35
41
|
_RedisDistributedBackend_nodeId.set(this, void 0);
|
|
42
|
+
_RedisDistributedBackend_heartbeatIntervalMs.set(this, void 0);
|
|
43
|
+
_RedisDistributedBackend_heartbeatTimeoutMs.set(this, void 0);
|
|
44
|
+
_RedisDistributedBackend_onError.set(this, void 0);
|
|
36
45
|
_RedisDistributedBackend_isConnected.set(this, false);
|
|
37
|
-
|
|
46
|
+
_RedisDistributedBackend_heartbeatTimer.set(this, null);
|
|
47
|
+
const { host = 'localhost', port = 6379, password, database = 0, url, keyPrefix = 'pondsocket', heartbeatIntervalMs = 30000, heartbeatTimeoutMs = 90000, onError = null, } = options;
|
|
38
48
|
__classPrivateFieldSet(this, _RedisDistributedBackend_keyPrefix, keyPrefix, "f");
|
|
49
|
+
__classPrivateFieldSet(this, _RedisDistributedBackend_heartbeatIntervalMs, heartbeatIntervalMs, "f");
|
|
50
|
+
__classPrivateFieldSet(this, _RedisDistributedBackend_heartbeatTimeoutMs, heartbeatTimeoutMs, "f");
|
|
51
|
+
__classPrivateFieldSet(this, _RedisDistributedBackend_onError, onError, "f");
|
|
39
52
|
__classPrivateFieldSet(this, _RedisDistributedBackend_nodeId, Math.random().toString(36)
|
|
40
53
|
.substring(2, 15), "f");
|
|
41
|
-
__classPrivateFieldSet(this,
|
|
42
|
-
|
|
54
|
+
__classPrivateFieldSet(this, _RedisDistributedBackend_heartbeatSubject, new pondsocket_common_1.Subject(), "f");
|
|
55
|
+
const reconnectStrategy = (retries) => {
|
|
56
|
+
const delay = Math.min(retries * 100, 5000);
|
|
57
|
+
return delay;
|
|
58
|
+
};
|
|
43
59
|
const clientConfig = url
|
|
44
|
-
? { url
|
|
45
|
-
|
|
46
|
-
|
|
60
|
+
? { url,
|
|
61
|
+
socket: { reconnectStrategy } }
|
|
62
|
+
: {
|
|
63
|
+
socket: { host,
|
|
64
|
+
port,
|
|
65
|
+
reconnectStrategy },
|
|
47
66
|
password,
|
|
48
|
-
database
|
|
67
|
+
database,
|
|
68
|
+
};
|
|
49
69
|
__classPrivateFieldSet(this, _RedisDistributedBackend_publishClient, (0, redis_1.createClient)(clientConfig), "f");
|
|
50
70
|
__classPrivateFieldSet(this, _RedisDistributedBackend_subscribeClient, __classPrivateFieldGet(this, _RedisDistributedBackend_publishClient, "f").duplicate(), "f");
|
|
51
|
-
|
|
71
|
+
__classPrivateFieldGet(this, _RedisDistributedBackend_instances, "m", _RedisDistributedBackend_attachEventHandlers).call(this, __classPrivateFieldGet(this, _RedisDistributedBackend_publishClient, "f"), 'publish');
|
|
72
|
+
__classPrivateFieldGet(this, _RedisDistributedBackend_instances, "m", _RedisDistributedBackend_attachEventHandlers).call(this, __classPrivateFieldGet(this, _RedisDistributedBackend_subscribeClient, "f"), 'subscribe');
|
|
52
73
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
74
|
+
subscribeToChannel(endpointName, channelName, handler) {
|
|
75
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
76
|
+
const key = __classPrivateFieldGet(this, _RedisDistributedBackend_instances, "m", _RedisDistributedBackend_buildKey).call(this, endpointName, channelName);
|
|
77
|
+
const listener = (message) => {
|
|
78
|
+
try {
|
|
79
|
+
const parsedMessage = JSON.parse(message);
|
|
80
|
+
if (!__classPrivateFieldGet(this, _RedisDistributedBackend_instances, "m", _RedisDistributedBackend_isValidMessage).call(this, parsedMessage)) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (parsedMessage.nodeId !== __classPrivateFieldGet(this, _RedisDistributedBackend_nodeId, "f")) {
|
|
84
|
+
handler(parsedMessage);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch (_) {
|
|
88
|
+
void 0;
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
yield __classPrivateFieldGet(this, _RedisDistributedBackend_subscribeClient, "f").subscribe(key, listener);
|
|
92
|
+
return () => {
|
|
93
|
+
__classPrivateFieldGet(this, _RedisDistributedBackend_subscribeClient, "f").unsubscribe(key).catch(() => { });
|
|
94
|
+
};
|
|
67
95
|
});
|
|
68
96
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
97
|
+
subscribeToHeartbeats(handler) {
|
|
98
|
+
return __classPrivateFieldGet(this, _RedisDistributedBackend_heartbeatSubject, "f").subscribe(handler);
|
|
99
|
+
}
|
|
72
100
|
broadcast(endpointName, channelName, message) {
|
|
73
101
|
return __awaiter(this, void 0, void 0, function* () {
|
|
74
102
|
if (!__classPrivateFieldGet(this, _RedisDistributedBackend_isConnected, "f")) {
|
|
75
103
|
throw new Error('Redis backend is not connected');
|
|
76
104
|
}
|
|
77
105
|
const key = __classPrivateFieldGet(this, _RedisDistributedBackend_instances, "m", _RedisDistributedBackend_buildKey).call(this, endpointName, channelName);
|
|
78
|
-
const distributedMessage = Object.assign(Object.assign({}, message), { nodeId: __classPrivateFieldGet(this, _RedisDistributedBackend_nodeId, "f") });
|
|
106
|
+
const distributedMessage = Object.assign(Object.assign({}, message), { nodeId: __classPrivateFieldGet(this, _RedisDistributedBackend_nodeId, "f"), sourceNodeId: __classPrivateFieldGet(this, _RedisDistributedBackend_nodeId, "f") });
|
|
79
107
|
const serializedMessage = JSON.stringify(distributedMessage);
|
|
80
108
|
yield __classPrivateFieldGet(this, _RedisDistributedBackend_publishClient, "f").publish(key, serializedMessage);
|
|
81
109
|
});
|
|
82
110
|
}
|
|
83
|
-
/**
|
|
84
|
-
* Cleanup and close all Redis connections
|
|
85
|
-
*/
|
|
86
111
|
cleanup() {
|
|
87
112
|
return __awaiter(this, void 0, void 0, function* () {
|
|
88
|
-
this
|
|
113
|
+
if (__classPrivateFieldGet(this, _RedisDistributedBackend_heartbeatTimer, "f")) {
|
|
114
|
+
clearInterval(__classPrivateFieldGet(this, _RedisDistributedBackend_heartbeatTimer, "f"));
|
|
115
|
+
__classPrivateFieldSet(this, _RedisDistributedBackend_heartbeatTimer, null, "f");
|
|
116
|
+
}
|
|
117
|
+
__classPrivateFieldGet(this, _RedisDistributedBackend_heartbeatSubject, "f").close();
|
|
89
118
|
if (__classPrivateFieldGet(this, _RedisDistributedBackend_subscribeClient, "f").isOpen) {
|
|
90
119
|
yield __classPrivateFieldGet(this, _RedisDistributedBackend_subscribeClient, "f").quit();
|
|
91
120
|
}
|
|
@@ -95,29 +124,67 @@ class RedisDistributedBackend {
|
|
|
95
124
|
__classPrivateFieldSet(this, _RedisDistributedBackend_isConnected, false, "f");
|
|
96
125
|
});
|
|
97
126
|
}
|
|
127
|
+
initialize() {
|
|
128
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
129
|
+
yield Promise.all([
|
|
130
|
+
__classPrivateFieldGet(this, _RedisDistributedBackend_publishClient, "f").connect(),
|
|
131
|
+
__classPrivateFieldGet(this, _RedisDistributedBackend_subscribeClient, "f").connect(),
|
|
132
|
+
]);
|
|
133
|
+
const heartbeatKey = __classPrivateFieldGet(this, _RedisDistributedBackend_instances, "m", _RedisDistributedBackend_buildKey).call(this, '__heartbeat__', '__heartbeat__');
|
|
134
|
+
yield __classPrivateFieldGet(this, _RedisDistributedBackend_subscribeClient, "f").subscribe(heartbeatKey, (message) => {
|
|
135
|
+
__classPrivateFieldGet(this, _RedisDistributedBackend_instances, "m", _RedisDistributedBackend_handleHeartbeatMessage).call(this, message);
|
|
136
|
+
});
|
|
137
|
+
__classPrivateFieldSet(this, _RedisDistributedBackend_isConnected, true, "f");
|
|
138
|
+
__classPrivateFieldGet(this, _RedisDistributedBackend_instances, "m", _RedisDistributedBackend_startHeartbeat).call(this);
|
|
139
|
+
});
|
|
140
|
+
}
|
|
98
141
|
}
|
|
99
142
|
exports.RedisDistributedBackend = RedisDistributedBackend;
|
|
100
|
-
_RedisDistributedBackend_publishClient = new WeakMap(), _RedisDistributedBackend_subscribeClient = new WeakMap(), _RedisDistributedBackend_keyPrefix = new WeakMap(),
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
__classPrivateFieldGet(this,
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
143
|
+
_RedisDistributedBackend_publishClient = new WeakMap(), _RedisDistributedBackend_subscribeClient = new WeakMap(), _RedisDistributedBackend_keyPrefix = new WeakMap(), _RedisDistributedBackend_heartbeatSubject = new WeakMap(), _RedisDistributedBackend_nodeId = new WeakMap(), _RedisDistributedBackend_heartbeatIntervalMs = new WeakMap(), _RedisDistributedBackend_heartbeatTimeoutMs = new WeakMap(), _RedisDistributedBackend_onError = new WeakMap(), _RedisDistributedBackend_isConnected = new WeakMap(), _RedisDistributedBackend_heartbeatTimer = new WeakMap(), _RedisDistributedBackend_instances = new WeakSet(), _RedisDistributedBackend_attachEventHandlers = function _RedisDistributedBackend_attachEventHandlers(client, label) {
|
|
144
|
+
client.on('error', (err) => {
|
|
145
|
+
__classPrivateFieldSet(this, _RedisDistributedBackend_isConnected, false, "f");
|
|
146
|
+
if (__classPrivateFieldGet(this, _RedisDistributedBackend_onError, "f")) {
|
|
147
|
+
__classPrivateFieldGet(this, _RedisDistributedBackend_onError, "f").call(this, new Error(`Redis ${label} client error: ${err.message}`));
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
client.on('ready', () => {
|
|
151
|
+
if (__classPrivateFieldGet(this, _RedisDistributedBackend_publishClient, "f").isReady && __classPrivateFieldGet(this, _RedisDistributedBackend_subscribeClient, "f").isReady) {
|
|
152
|
+
__classPrivateFieldSet(this, _RedisDistributedBackend_isConnected, true, "f");
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
client.on('end', () => {
|
|
156
|
+
__classPrivateFieldSet(this, _RedisDistributedBackend_isConnected, false, "f");
|
|
157
|
+
});
|
|
158
|
+
}, _RedisDistributedBackend_startHeartbeat = function _RedisDistributedBackend_startHeartbeat() {
|
|
159
|
+
__classPrivateFieldGet(this, _RedisDistributedBackend_instances, "m", _RedisDistributedBackend_publishHeartbeat).call(this);
|
|
160
|
+
__classPrivateFieldSet(this, _RedisDistributedBackend_heartbeatTimer, setInterval(() => {
|
|
161
|
+
__classPrivateFieldGet(this, _RedisDistributedBackend_instances, "m", _RedisDistributedBackend_publishHeartbeat).call(this);
|
|
162
|
+
}, __classPrivateFieldGet(this, _RedisDistributedBackend_heartbeatIntervalMs, "f")), "f");
|
|
163
|
+
}, _RedisDistributedBackend_publishHeartbeat = function _RedisDistributedBackend_publishHeartbeat() {
|
|
164
|
+
if (!__classPrivateFieldGet(this, _RedisDistributedBackend_isConnected, "f")) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
const heartbeatMessage = {
|
|
168
|
+
type: types_1.DistributedMessageType.NODE_HEARTBEAT,
|
|
169
|
+
endpointName: '__heartbeat__',
|
|
170
|
+
channelName: '__heartbeat__',
|
|
171
|
+
nodeId: __classPrivateFieldGet(this, _RedisDistributedBackend_nodeId, "f"),
|
|
172
|
+
};
|
|
173
|
+
const key = __classPrivateFieldGet(this, _RedisDistributedBackend_instances, "m", _RedisDistributedBackend_buildKey).call(this, '__heartbeat__', '__heartbeat__');
|
|
174
|
+
__classPrivateFieldGet(this, _RedisDistributedBackend_publishClient, "f").publish(key, JSON.stringify(heartbeatMessage)).catch((err) => {
|
|
175
|
+
if (__classPrivateFieldGet(this, _RedisDistributedBackend_onError, "f")) {
|
|
176
|
+
__classPrivateFieldGet(this, _RedisDistributedBackend_onError, "f").call(this, new Error(`Failed to publish heartbeat: ${err.message}`));
|
|
177
|
+
}
|
|
111
178
|
});
|
|
112
|
-
},
|
|
179
|
+
}, _RedisDistributedBackend_handleHeartbeatMessage = function _RedisDistributedBackend_handleHeartbeatMessage(message) {
|
|
113
180
|
try {
|
|
114
181
|
const parsedMessage = JSON.parse(message);
|
|
115
|
-
if (__classPrivateFieldGet(this,
|
|
116
|
-
this.
|
|
182
|
+
if (parsedMessage.type === types_1.DistributedMessageType.NODE_HEARTBEAT && parsedMessage.nodeId !== __classPrivateFieldGet(this, _RedisDistributedBackend_nodeId, "f")) {
|
|
183
|
+
__classPrivateFieldGet(this, _RedisDistributedBackend_heartbeatSubject, "f").publish(parsedMessage.nodeId);
|
|
117
184
|
}
|
|
118
185
|
}
|
|
119
|
-
catch (
|
|
120
|
-
|
|
186
|
+
catch (_) {
|
|
187
|
+
void 0;
|
|
121
188
|
}
|
|
122
189
|
}, _RedisDistributedBackend_isValidMessage = function _RedisDistributedBackend_isValidMessage(message) {
|
|
123
190
|
return (typeof message === 'object' &&
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { MiddlewareFunction, NextFunction } from './types';
|
|
2
|
+
export declare class Middleware<Request, Response> {
|
|
3
|
+
#private;
|
|
4
|
+
constructor(second?: Middleware<Request, Response>);
|
|
5
|
+
/**
|
|
6
|
+
* @desc Returns the middleware stack length
|
|
7
|
+
*/
|
|
8
|
+
get length(): number;
|
|
9
|
+
/**
|
|
10
|
+
* @desc Adds a middleware function to the middleware stack
|
|
11
|
+
* @param middleware - the middleware function to add
|
|
12
|
+
*/
|
|
13
|
+
use(middleware: MiddlewareFunction<Request, Response> | Middleware<Request, Response>): this;
|
|
14
|
+
/**
|
|
15
|
+
* @desc Runs the middleware stack
|
|
16
|
+
* @param req - the request object
|
|
17
|
+
* @param res - the response object
|
|
18
|
+
* @param final - the final function to call
|
|
19
|
+
*/
|
|
20
|
+
run(req: Request, res: Response, final: NextFunction): void;
|
|
21
|
+
runAsync(req: Request, res: Response, final: NextFunction): Promise<void>;
|
|
22
|
+
}
|
package/abstracts/middleware.js
CHANGED
|
@@ -64,7 +64,14 @@ class Middleware {
|
|
|
64
64
|
try {
|
|
65
65
|
const result = middleware(req, res, next);
|
|
66
66
|
if (result instanceof Promise) {
|
|
67
|
-
result.catch(
|
|
67
|
+
result.catch((error) => {
|
|
68
|
+
try {
|
|
69
|
+
final(__classPrivateFieldGet(this, _Middleware_instances, "m", _Middleware_handleError).call(this, error));
|
|
70
|
+
}
|
|
71
|
+
catch (_) {
|
|
72
|
+
void 0;
|
|
73
|
+
}
|
|
74
|
+
});
|
|
68
75
|
}
|
|
69
76
|
}
|
|
70
77
|
catch (error) {
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { IncomingHttpHeaders } from 'http';
|
|
2
|
+
import { IncomingMessage } from 'node:http';
|
|
3
|
+
import internal from 'node:stream';
|
|
4
|
+
import { ChannelEvent, EventParams, JoinParams, PondAssigns, PondMessage, ServerActions, SystemSender, Unsubscribe, UserData } from '@eleven-am/pondsocket-common';
|
|
5
|
+
import { WebSocket, WebSocketServer } from 'ws';
|
|
6
|
+
import { ConnectionContext } from '../contexts/connectionContext';
|
|
7
|
+
import { EventContext } from '../contexts/eventContext';
|
|
8
|
+
import { JoinContext } from '../contexts/joinContext';
|
|
9
|
+
import { OutgoingContext } from '../contexts/outgoingContext';
|
|
10
|
+
import { EndpointEngine } from '../engines/endpointEngine';
|
|
11
|
+
import { HttpError } from '../errors/httpError';
|
|
12
|
+
import { Channel } from '../wrappers/channel';
|
|
13
|
+
export type NextFunction<Error extends HttpError = HttpError> = (error?: Error) => void;
|
|
14
|
+
export type MiddlewareFunction<Request, Response> = (req: Request, res: Response, next: NextFunction) => void | Promise<void>;
|
|
15
|
+
export interface SocketRequest {
|
|
16
|
+
id: string;
|
|
17
|
+
headers: IncomingHttpHeaders;
|
|
18
|
+
address: string;
|
|
19
|
+
}
|
|
20
|
+
export type ConnectionHandler<Path extends string> = (ctx: ConnectionContext<Path>, next: NextFunction) => void | Promise<void>;
|
|
21
|
+
export type AuthorizationHandler<Path extends string> = (ctx: JoinContext<Path>, next: NextFunction) => void | Promise<void>;
|
|
22
|
+
export type EventHandler<Path extends string> = (ctx: EventContext<Path>, next: NextFunction) => void | Promise<void>;
|
|
23
|
+
export type OutgoingEventHandler<Event extends string> = (event: OutgoingContext<Event>, next: NextFunction) => PondMessage | Promise<PondMessage> | void | Promise<void>;
|
|
24
|
+
export interface ConnectionParams {
|
|
25
|
+
head: Buffer;
|
|
26
|
+
socket: internal.Duplex;
|
|
27
|
+
request: IncomingMessage;
|
|
28
|
+
requestId: string;
|
|
29
|
+
}
|
|
30
|
+
export interface SocketCache {
|
|
31
|
+
clientId: string;
|
|
32
|
+
socket: WebSocket;
|
|
33
|
+
assigns: PondAssigns;
|
|
34
|
+
subscriptions: Set<Unsubscribe>;
|
|
35
|
+
}
|
|
36
|
+
export interface ConnectionResponseOptions {
|
|
37
|
+
engine: EndpointEngine;
|
|
38
|
+
params: ConnectionParams;
|
|
39
|
+
webSocketServer: WebSocketServer;
|
|
40
|
+
}
|
|
41
|
+
export interface JoinRequestOptions<Path extends string> {
|
|
42
|
+
clientId: string;
|
|
43
|
+
assigns: PondAssigns;
|
|
44
|
+
joinParams: JoinParams;
|
|
45
|
+
params: EventParams<Path>;
|
|
46
|
+
}
|
|
47
|
+
export interface RequestCache extends SocketCache {
|
|
48
|
+
channelName: string;
|
|
49
|
+
requestId: string;
|
|
50
|
+
}
|
|
51
|
+
export type InternalChannelEvent = ChannelEvent & {
|
|
52
|
+
recipients: string[];
|
|
53
|
+
};
|
|
54
|
+
export type ChannelSenders = SystemSender.CHANNEL | string;
|
|
55
|
+
export type BroadcastEvent = Omit<InternalChannelEvent, 'action' | 'payload' | 'recipients'> & {
|
|
56
|
+
action: ServerActions.BROADCAST;
|
|
57
|
+
sender: ChannelSenders;
|
|
58
|
+
payload: PondMessage;
|
|
59
|
+
};
|
|
60
|
+
export interface LeaveEvent {
|
|
61
|
+
user: UserData;
|
|
62
|
+
channel: Channel;
|
|
63
|
+
}
|
|
64
|
+
export type LeaveCallback = (event: LeaveEvent) => void;
|
package/abstracts/types.js
CHANGED
|
@@ -1,16 +1,2 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DistributedMessageType = void 0;
|
|
4
|
-
var DistributedMessageType;
|
|
5
|
-
(function (DistributedMessageType) {
|
|
6
|
-
DistributedMessageType["STATE_REQUEST"] = "STATE_REQUEST";
|
|
7
|
-
DistributedMessageType["STATE_RESPONSE"] = "STATE_RESPONSE";
|
|
8
|
-
DistributedMessageType["USER_JOINED"] = "USER_JOINED";
|
|
9
|
-
DistributedMessageType["USER_LEFT"] = "USER_LEFT";
|
|
10
|
-
DistributedMessageType["USER_MESSAGE"] = "USER_MESSAGE";
|
|
11
|
-
DistributedMessageType["PRESENCE_UPDATE"] = "PRESENCE_UPDATE";
|
|
12
|
-
DistributedMessageType["PRESENCE_REMOVED"] = "PRESENCE_REMOVED";
|
|
13
|
-
DistributedMessageType["ASSIGNS_UPDATE"] = "ASSIGNS_UPDATE";
|
|
14
|
-
DistributedMessageType["ASSIGNS_REMOVED"] = "ASSIGNS_REMOVED";
|
|
15
|
-
DistributedMessageType["EVICT_USER"] = "EVICT_USER";
|
|
16
|
-
})(DistributedMessageType || (exports.DistributedMessageType = DistributedMessageType = {}));
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ChannelReceivers, EventParams, PondEvent, PondMessage, PondObject, UserAssigns, UserPresences } from '@eleven-am/pondsocket-common';
|
|
2
|
+
import { ChannelEngine } from '../engines/channelEngine';
|
|
3
|
+
import { Channel } from '../wrappers/channel';
|
|
4
|
+
export declare abstract class BaseContext<Path extends string> {
|
|
5
|
+
#private;
|
|
6
|
+
constructor(engine: ChannelEngine, params: EventParams<Path>, event: string, payload: PondMessage, sender: string);
|
|
7
|
+
get event(): PondEvent<Path>;
|
|
8
|
+
get channelName(): string;
|
|
9
|
+
get channel(): Channel;
|
|
10
|
+
get presences(): UserPresences;
|
|
11
|
+
get assigns(): UserAssigns;
|
|
12
|
+
get user(): import("@eleven-am/pondsocket-common").UserData<PondObject, PondObject>;
|
|
13
|
+
broadcast(event: string, payload: PondMessage): this;
|
|
14
|
+
broadcastFrom(event: string, payload: PondMessage): this;
|
|
15
|
+
broadcastTo(event: string, payload: PondMessage, userIds: string | string[]): this;
|
|
16
|
+
protected abstract _sendMessageToRecipients(recipient: ChannelReceivers, event: string, payload: PondObject): void;
|
|
17
|
+
protected get engine(): ChannelEngine;
|
|
18
|
+
protected get sender(): string;
|
|
19
|
+
protected updateParams(params: EventParams<Path>): void;
|
|
20
|
+
}
|
package/contexts/baseContext.js
CHANGED
|
@@ -13,6 +13,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
13
13
|
var _BaseContext_engine, _BaseContext_params, _BaseContext_event, _BaseContext_sender, _BaseContext_payload;
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.BaseContext = void 0;
|
|
16
|
+
const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
|
|
16
17
|
const channel_1 = require("../wrappers/channel");
|
|
17
18
|
class BaseContext {
|
|
18
19
|
constructor(engine, params, event, payload, sender) {
|
|
@@ -27,9 +28,6 @@ class BaseContext {
|
|
|
27
28
|
__classPrivateFieldSet(this, _BaseContext_payload, payload, "f");
|
|
28
29
|
__classPrivateFieldSet(this, _BaseContext_sender, sender, "f");
|
|
29
30
|
}
|
|
30
|
-
/**
|
|
31
|
-
* The event information
|
|
32
|
-
*/
|
|
33
31
|
get event() {
|
|
34
32
|
return {
|
|
35
33
|
event: __classPrivateFieldGet(this, _BaseContext_event, "f"),
|
|
@@ -38,46 +36,40 @@ class BaseContext {
|
|
|
38
36
|
payload: __classPrivateFieldGet(this, _BaseContext_payload, "f"),
|
|
39
37
|
};
|
|
40
38
|
}
|
|
41
|
-
/**
|
|
42
|
-
* The channel name
|
|
43
|
-
*/
|
|
44
39
|
get channelName() {
|
|
45
40
|
return __classPrivateFieldGet(this, _BaseContext_engine, "f").name;
|
|
46
41
|
}
|
|
47
|
-
/**
|
|
48
|
-
* The channel instance
|
|
49
|
-
*/
|
|
50
42
|
get channel() {
|
|
51
43
|
return new channel_1.Channel(__classPrivateFieldGet(this, _BaseContext_engine, "f"));
|
|
52
44
|
}
|
|
53
|
-
/**
|
|
54
|
-
* All current presences in the channel
|
|
55
|
-
*/
|
|
56
45
|
get presences() {
|
|
57
46
|
return __classPrivateFieldGet(this, _BaseContext_engine, "f").getPresence();
|
|
58
47
|
}
|
|
59
|
-
/**
|
|
60
|
-
* All current assigns in the channel
|
|
61
|
-
*/
|
|
62
48
|
get assigns() {
|
|
63
49
|
return __classPrivateFieldGet(this, _BaseContext_engine, "f").getAssigns();
|
|
64
50
|
}
|
|
65
|
-
/**
|
|
66
|
-
* The user who sent the request
|
|
67
|
-
*/
|
|
68
51
|
get user() {
|
|
69
52
|
return this.channel.getUserData(__classPrivateFieldGet(this, _BaseContext_sender, "f"));
|
|
70
53
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
54
|
+
broadcast(event, payload) {
|
|
55
|
+
this._sendMessageToRecipients(pondsocket_common_1.ChannelReceiver.ALL_USERS, event, payload);
|
|
56
|
+
return this;
|
|
57
|
+
}
|
|
58
|
+
broadcastFrom(event, payload) {
|
|
59
|
+
this._sendMessageToRecipients(pondsocket_common_1.ChannelReceiver.ALL_EXCEPT_SENDER, event, payload);
|
|
60
|
+
return this;
|
|
61
|
+
}
|
|
62
|
+
broadcastTo(event, payload, userIds) {
|
|
63
|
+
const ids = Array.isArray(userIds) ? userIds : [userIds];
|
|
64
|
+
this._sendMessageToRecipients(ids, event, payload);
|
|
65
|
+
return this;
|
|
66
|
+
}
|
|
75
67
|
get engine() {
|
|
76
68
|
return __classPrivateFieldGet(this, _BaseContext_engine, "f");
|
|
77
69
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
70
|
+
get sender() {
|
|
71
|
+
return __classPrivateFieldGet(this, _BaseContext_sender, "f");
|
|
72
|
+
}
|
|
81
73
|
updateParams(params) {
|
|
82
74
|
__classPrivateFieldSet(this, _BaseContext_params, params, "f");
|
|
83
75
|
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { IncomingHttpHeaders } from 'http';
|
|
2
|
+
import { PondAssigns, PondMessage, IncomingConnection, Params, EventParams } from '@eleven-am/pondsocket-common';
|
|
3
|
+
import { ConnectionResponseOptions } from '../abstracts/types';
|
|
4
|
+
/**
|
|
5
|
+
* ConnectionContext combines IncomingConnection data with ConnectionResponse functionality.
|
|
6
|
+
*/
|
|
7
|
+
export declare class ConnectionContext<Path extends string> {
|
|
8
|
+
#private;
|
|
9
|
+
constructor(connectionData: IncomingConnection<Path>, { engine, params, webSocketServer }: ConnectionResponseOptions);
|
|
10
|
+
/**
|
|
11
|
+
* Whether the connection has been handled
|
|
12
|
+
*/
|
|
13
|
+
get hasResponded(): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Connection details including headers, cookies, address, id, etc.
|
|
16
|
+
*/
|
|
17
|
+
get connection(): IncomingConnection<Path>;
|
|
18
|
+
/**
|
|
19
|
+
* The request parameters
|
|
20
|
+
*/
|
|
21
|
+
get requestId(): string;
|
|
22
|
+
/**
|
|
23
|
+
* The client ID
|
|
24
|
+
*/
|
|
25
|
+
get clientId(): string;
|
|
26
|
+
/**
|
|
27
|
+
* The request headers
|
|
28
|
+
*/
|
|
29
|
+
get headers(): IncomingHttpHeaders;
|
|
30
|
+
/**
|
|
31
|
+
* The request cookies
|
|
32
|
+
*/
|
|
33
|
+
get cookies(): Record<string, string>;
|
|
34
|
+
/**
|
|
35
|
+
* The client address
|
|
36
|
+
*/
|
|
37
|
+
get address(): string;
|
|
38
|
+
/**
|
|
39
|
+
* The event parameters
|
|
40
|
+
*/
|
|
41
|
+
get event(): EventParams<Path>;
|
|
42
|
+
/**
|
|
43
|
+
* The query parameters
|
|
44
|
+
*/
|
|
45
|
+
get query(): Record<string, string>;
|
|
46
|
+
/**
|
|
47
|
+
* The path parameters
|
|
48
|
+
*/
|
|
49
|
+
get params(): Params<Path>;
|
|
50
|
+
/**
|
|
51
|
+
* Assigns data to the client
|
|
52
|
+
*/
|
|
53
|
+
assign(assigns: PondAssigns): ConnectionContext<Path>;
|
|
54
|
+
/**
|
|
55
|
+
* Accepts the connection request
|
|
56
|
+
*/
|
|
57
|
+
accept(): ConnectionContext<Path>;
|
|
58
|
+
/**
|
|
59
|
+
* Declines the connection request
|
|
60
|
+
*/
|
|
61
|
+
decline(message?: string, errorCode?: number): ConnectionContext<Path>;
|
|
62
|
+
/**
|
|
63
|
+
* Sends a direct reply to the client
|
|
64
|
+
*/
|
|
65
|
+
reply(event: string, payload: PondMessage): ConnectionContext<Path>;
|
|
66
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ChannelReceivers, EventParams, PondAssigns, PondMessage, PondObject, PondPresence } from '@eleven-am/pondsocket-common';
|
|
2
|
+
import { BaseContext } from './baseContext';
|
|
3
|
+
import { BroadcastEvent } from '../abstracts/types';
|
|
4
|
+
import { ChannelEngine } from '../engines/channelEngine';
|
|
5
|
+
export declare class EventContext<Path extends string> extends BaseContext<Path> {
|
|
6
|
+
#private;
|
|
7
|
+
constructor(event: BroadcastEvent, params: EventParams<Path>, engine: ChannelEngine);
|
|
8
|
+
assign(assigns: PondAssigns): EventContext<Path>;
|
|
9
|
+
reply(event: string, payload: PondMessage): this;
|
|
10
|
+
trackPresence(presence: PondPresence, userId?: string): EventContext<Path>;
|
|
11
|
+
updatePresence(presence: PondPresence, userId?: string): EventContext<Path>;
|
|
12
|
+
evictUser(reason: string, userId?: string): EventContext<Path>;
|
|
13
|
+
removePresence(userId?: string): EventContext<Path>;
|
|
14
|
+
protected _sendMessageToRecipients(recipient: ChannelReceivers, event: string, payload: PondObject): void;
|
|
15
|
+
}
|