@eleven-am/pondsocket 0.1.126 → 0.1.127
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/README.md +5 -15
- package/abstracts/abstractRequest.test.js +42 -0
- package/abstracts/middleware.test.js +70 -0
- package/channel/channel.js +18 -20
- package/channel/channel.test.js +415 -0
- package/channel/eventRequest.test.js +30 -0
- package/channel/eventResponse.js +7 -7
- package/channel/eventResponse.test.js +197 -0
- package/endpoint/endpoint.js +16 -19
- package/endpoint/endpoint.test.js +297 -0
- package/endpoint/response.js +5 -6
- package/index.d.ts +2 -0
- package/lobby/JoinRequest.test.js +40 -0
- package/lobby/JoinResponse.test.js +145 -0
- package/lobby/joinResponse.js +9 -9
- package/lobby/lobby.js +3 -4
- package/matcher/matcher.test.js +90 -0
- package/package.json +32 -13
- package/presence/presence.js +8 -9
- package/presence/presenceEngine.test.js +128 -0
- package/schema.js +3 -3
- package/server/pondSocket.js +5 -4
- package/types.d.ts +0 -496
- package/types.js +2 -0
- package/client/channel.js +0 -305
- package/client.d.ts +0 -5
- package/client.js +0 -107
- package/enums.js +0 -56
- package/express.d.ts +0 -3
- package/express.js +0 -17
- package/misc/uuid.js +0 -12
- package/nest.d.ts +0 -19
- package/nest.js +0 -769
- package/node.d.ts +0 -3
- package/node.js +0 -30
- package/subjects/subject.js +0 -137
package/README.md
CHANGED
|
@@ -30,18 +30,6 @@ const endpoint = pond.createEndpoint('/api/socket', (req, res) => {
|
|
|
30
30
|
|
|
31
31
|
// Start the server
|
|
32
32
|
pond.listen(3000);
|
|
33
|
-
|
|
34
|
-
// Or alternatively, working with express
|
|
35
|
-
import pondSocket from "@eleven-am/pondsocket/express";
|
|
36
|
-
import express from "express";
|
|
37
|
-
|
|
38
|
-
const app = pondSocket(express());
|
|
39
|
-
|
|
40
|
-
const endpoint = app.upgrade('/api/socket', (req, res) => {
|
|
41
|
-
// Handle socket connection and authentication
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
app.listen(3000);
|
|
45
33
|
```
|
|
46
34
|
|
|
47
35
|
Within each endpoint, sockets interact through channels. Channels provide an organized way to group users and manage efficient communication among them. When users join a channel, they can participate in real-time events and exchange information with other users in the same channel.
|
|
@@ -57,7 +45,7 @@ const channel = endpoint.createChannel('/channel/:id', (req, res) => {
|
|
|
57
45
|
On the client-side, PondSocket provides the PondClient class to establish connections with the server. Clients can easily initiate connections, join channels, and participate in real-time interactions.
|
|
58
46
|
|
|
59
47
|
```javascript
|
|
60
|
-
import PondClient from "@eleven-am/pondsocket
|
|
48
|
+
import PondClient from "@eleven-am/pondsocket-client";
|
|
61
49
|
|
|
62
50
|
const socket = new PondClient('/api/socket', {});
|
|
63
51
|
socket.connect();
|
|
@@ -75,7 +63,7 @@ channel.join();
|
|
|
75
63
|
PondSocket also offers a Node.js client, which can be imported using:
|
|
76
64
|
|
|
77
65
|
```javascript
|
|
78
|
-
import PondClient from "@eleven-am/pondsocket
|
|
66
|
+
import PondClient from "@eleven-am/pondsocket-client";
|
|
79
67
|
```
|
|
80
68
|
|
|
81
69
|
This node client allows you to turn another server into a client, enabling easy communication between different server instances.
|
|
@@ -96,7 +84,7 @@ This node client allows you to turn another server into a client, enabling easy
|
|
|
96
84
|
To connect to the PondSocket server and send messages while associating a username with the client connection, follow the steps below:
|
|
97
85
|
|
|
98
86
|
```javascript
|
|
99
|
-
import PondClient from "@eleven-am/pondsocket
|
|
87
|
+
import PondClient from "@eleven-am/pondsocket-client";
|
|
100
88
|
|
|
101
89
|
// Your server URL
|
|
102
90
|
const serverUrl = 'ws://your-server-url/api/socket';
|
|
@@ -500,6 +488,8 @@ The `ClientChannel` class represents a channel in the PondClient.
|
|
|
500
488
|
|
|
501
489
|
- `sendMessage(event: string, payload: PondMessage, recipient: string[]): void`: Sends a message to specific clients in the channel with the specified event, payload, and recipient.
|
|
502
490
|
|
|
491
|
+
- `sendForResponse(event: string, payload: PondMessage): Promise<PondMessage>`: Sends a message to the server with the specified event, payload, and returns a promise that resolves with the response.
|
|
492
|
+
|
|
503
493
|
- `broadcastFrom(event: string, payload: PondMessage): void`: Broadcasts a message to every other client in the channel except yourself with the specified event and payload.
|
|
504
494
|
|
|
505
495
|
- `broadcast(event: string, payload: PondMessage): void`: Broadcasts a message to the channel, including yourself, with the specified event and payload.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const abstractRequest_1 = require("./abstractRequest");
|
|
4
|
+
const createMockChannelEngine = () => ({
|
|
5
|
+
name: 'test',
|
|
6
|
+
getAssigns: () => ({}),
|
|
7
|
+
getPresence: () => ({}),
|
|
8
|
+
});
|
|
9
|
+
describe('AbstractRequest', () => {
|
|
10
|
+
it('should be able to be instantiated', () => {
|
|
11
|
+
const request = new abstractRequest_1.AbstractRequest('/test', createMockChannelEngine(), {});
|
|
12
|
+
expect(request).toBeTruthy();
|
|
13
|
+
expect(request.channelName).toBe('test');
|
|
14
|
+
expect(request.assigns).toEqual({});
|
|
15
|
+
expect(request.presence).toEqual({});
|
|
16
|
+
});
|
|
17
|
+
it('should be able to parse queries', () => {
|
|
18
|
+
const request = new abstractRequest_1.AbstractRequest('/1234?choke=balls', createMockChannelEngine(), {});
|
|
19
|
+
expect(() => request.event).toThrowError('Event was not parsed');
|
|
20
|
+
expect(request['_parseQueries']('/:id')).toBe(true);
|
|
21
|
+
expect(request.event).toEqual({
|
|
22
|
+
event: '/1234?choke=balls',
|
|
23
|
+
params: { id: '1234' },
|
|
24
|
+
query: { choke: 'balls' },
|
|
25
|
+
payload: {},
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
it('should be return the value of the payload', () => {
|
|
29
|
+
const request = new abstractRequest_1.AbstractRequest('/test', createMockChannelEngine(), { test: 'test' });
|
|
30
|
+
expect(request['_parseQueries']('/:id')).toBe(true);
|
|
31
|
+
expect(request.event.payload).toEqual({ test: 'test' });
|
|
32
|
+
const request2 = new abstractRequest_1.AbstractRequest('/test', createMockChannelEngine(), {
|
|
33
|
+
test: 'test',
|
|
34
|
+
test2: 'test2',
|
|
35
|
+
});
|
|
36
|
+
expect(request2['_parseQueries']('/:id')).toBe(true);
|
|
37
|
+
expect(request2.event.payload).toEqual({
|
|
38
|
+
test: 'test',
|
|
39
|
+
test2: 'test2',
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
});
|
|
@@ -0,0 +1,70 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const middleware_1 = require("./middleware");
|
|
13
|
+
describe('Middleware', () => {
|
|
14
|
+
it('should be able to add middleware to the stack', () => {
|
|
15
|
+
const middleware = new middleware_1.Middleware();
|
|
16
|
+
middleware.use(() => { });
|
|
17
|
+
expect(middleware.length).toBe(1);
|
|
18
|
+
});
|
|
19
|
+
it('should be able to run middleware', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
20
|
+
const middleware = new middleware_1.Middleware();
|
|
21
|
+
const mock = jest.fn();
|
|
22
|
+
middleware.use(mock);
|
|
23
|
+
yield middleware.run({}, {}, () => { });
|
|
24
|
+
expect(mock).toHaveBeenCalled();
|
|
25
|
+
}));
|
|
26
|
+
it('should be able to run multiple middleware', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
27
|
+
const middleware = new middleware_1.Middleware();
|
|
28
|
+
const mock = jest.fn();
|
|
29
|
+
middleware.use((_, __, next) => {
|
|
30
|
+
mock('first');
|
|
31
|
+
next();
|
|
32
|
+
});
|
|
33
|
+
middleware.use((_, __, next) => {
|
|
34
|
+
mock('second');
|
|
35
|
+
next();
|
|
36
|
+
});
|
|
37
|
+
yield middleware.run({}, {}, () => { });
|
|
38
|
+
expect(mock).toHaveBeenCalledTimes(2);
|
|
39
|
+
expect(mock.mock.calls[0][2]).toBe(mock.mock.calls[1][2]);
|
|
40
|
+
}));
|
|
41
|
+
it('should be merge middleware in the correct order', () => {
|
|
42
|
+
const middleware = new middleware_1.Middleware();
|
|
43
|
+
const mock = jest.fn();
|
|
44
|
+
middleware.use(mock);
|
|
45
|
+
middleware.use(mock);
|
|
46
|
+
const middleware2 = new middleware_1.Middleware(middleware);
|
|
47
|
+
expect(middleware2.length).toBe(2);
|
|
48
|
+
});
|
|
49
|
+
it('should call the final function when the middleware stack is empty', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
50
|
+
const middleware = new middleware_1.Middleware();
|
|
51
|
+
const mock = jest.fn();
|
|
52
|
+
yield middleware.run({}, {}, mock);
|
|
53
|
+
expect(mock).toHaveBeenCalled();
|
|
54
|
+
}));
|
|
55
|
+
it('should be able to run middleware in the correct order when using a second middleware', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
56
|
+
const middleware = new middleware_1.Middleware();
|
|
57
|
+
const mock = jest.fn();
|
|
58
|
+
middleware.use((_, __, next) => {
|
|
59
|
+
mock('first');
|
|
60
|
+
next();
|
|
61
|
+
});
|
|
62
|
+
middleware.use((_, __, next) => {
|
|
63
|
+
mock('second');
|
|
64
|
+
next();
|
|
65
|
+
});
|
|
66
|
+
const middleware2 = new middleware_1.Middleware(middleware);
|
|
67
|
+
yield middleware2.run({}, {}, () => { });
|
|
68
|
+
expect(mock.mock.calls[0][2]).toBe(mock.mock.calls[1][2]);
|
|
69
|
+
}));
|
|
70
|
+
});
|
package/channel/channel.js
CHANGED
|
@@ -24,13 +24,11 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
24
24
|
var _Channel_engine, _ChannelEngine_instances, _ChannelEngine_receiver, _ChannelEngine_presenceEngine, _ChannelEngine_users, _ChannelEngine_parentEngine, _ChannelEngine_subscribe, _ChannelEngine_getUsersFromRecipients;
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
26
|
exports.ChannelEngine = exports.Channel = void 0;
|
|
27
|
+
const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
|
|
27
28
|
const eventRequest_1 = require("./eventRequest");
|
|
28
29
|
const eventResponse_1 = require("./eventResponse");
|
|
29
|
-
const enums_1 = require("../enums");
|
|
30
30
|
const pondError_1 = require("../errors/pondError");
|
|
31
|
-
const uuid_1 = require("../misc/uuid");
|
|
32
31
|
const presence_1 = require("../presence/presence");
|
|
33
|
-
const subject_1 = require("../subjects/subject");
|
|
34
32
|
class Channel {
|
|
35
33
|
constructor(engine) {
|
|
36
34
|
_Channel_engine.set(this, void 0);
|
|
@@ -46,16 +44,16 @@ class Channel {
|
|
|
46
44
|
return __classPrivateFieldGet(this, _Channel_engine, "f").getUserData(userId);
|
|
47
45
|
}
|
|
48
46
|
broadcastMessage(event, payload) {
|
|
49
|
-
__classPrivateFieldGet(this, _Channel_engine, "f").sendMessage((0,
|
|
47
|
+
__classPrivateFieldGet(this, _Channel_engine, "f").sendMessage((0, pondsocket_common_1.uuid)(), pondsocket_common_1.SystemSender.CHANNEL, pondsocket_common_1.ChannelReceiver.ALL_USERS, pondsocket_common_1.ServerActions.BROADCAST, event, payload);
|
|
50
48
|
}
|
|
51
49
|
broadcastMessageFromUser(userId, event, payload) {
|
|
52
|
-
__classPrivateFieldGet(this, _Channel_engine, "f").sendMessage((0,
|
|
50
|
+
__classPrivateFieldGet(this, _Channel_engine, "f").sendMessage((0, pondsocket_common_1.uuid)(), userId, pondsocket_common_1.ChannelReceiver.ALL_EXCEPT_SENDER, pondsocket_common_1.ServerActions.BROADCAST, event, payload);
|
|
53
51
|
}
|
|
54
52
|
sendToUser(userId, event, payload) {
|
|
55
|
-
__classPrivateFieldGet(this, _Channel_engine, "f").sendMessage((0,
|
|
53
|
+
__classPrivateFieldGet(this, _Channel_engine, "f").sendMessage((0, pondsocket_common_1.uuid)(), pondsocket_common_1.SystemSender.CHANNEL, [userId], pondsocket_common_1.ServerActions.BROADCAST, event, payload);
|
|
56
54
|
}
|
|
57
55
|
sendToUsers(userIds, event, payload) {
|
|
58
|
-
__classPrivateFieldGet(this, _Channel_engine, "f").sendMessage((0,
|
|
56
|
+
__classPrivateFieldGet(this, _Channel_engine, "f").sendMessage((0, pondsocket_common_1.uuid)(), pondsocket_common_1.SystemSender.CHANNEL, userIds, pondsocket_common_1.ServerActions.BROADCAST, event, payload);
|
|
59
57
|
}
|
|
60
58
|
evictUser(userId, reason) {
|
|
61
59
|
__classPrivateFieldGet(this, _Channel_engine, "f").kickUser(userId, reason !== null && reason !== void 0 ? reason : 'You have been banned from the channel');
|
|
@@ -80,7 +78,7 @@ class ChannelEngine {
|
|
|
80
78
|
_ChannelEngine_users.set(this, void 0);
|
|
81
79
|
_ChannelEngine_parentEngine.set(this, void 0);
|
|
82
80
|
this.name = name;
|
|
83
|
-
__classPrivateFieldSet(this, _ChannelEngine_receiver, new
|
|
81
|
+
__classPrivateFieldSet(this, _ChannelEngine_receiver, new pondsocket_common_1.Subject(), "f");
|
|
84
82
|
__classPrivateFieldSet(this, _ChannelEngine_users, new Map(), "f");
|
|
85
83
|
__classPrivateFieldSet(this, _ChannelEngine_parentEngine, parent, "f");
|
|
86
84
|
}
|
|
@@ -133,12 +131,12 @@ class ChannelEngine {
|
|
|
133
131
|
* @param reason - The reason for kicking the user
|
|
134
132
|
*/
|
|
135
133
|
kickUser(userId, reason) {
|
|
136
|
-
this.sendMessage((0,
|
|
134
|
+
this.sendMessage((0, pondsocket_common_1.uuid)(), pondsocket_common_1.SystemSender.CHANNEL, [userId], pondsocket_common_1.ServerActions.SYSTEM, 'kicked_out', {
|
|
137
135
|
message: reason,
|
|
138
136
|
code: 403,
|
|
139
137
|
});
|
|
140
138
|
this.removeUser(userId);
|
|
141
|
-
this.sendMessage((0,
|
|
139
|
+
this.sendMessage((0, pondsocket_common_1.uuid)(), pondsocket_common_1.SystemSender.CHANNEL, pondsocket_common_1.ChannelReceiver.ALL_USERS, pondsocket_common_1.ServerActions.SYSTEM, 'kicked', {
|
|
142
140
|
userId,
|
|
143
141
|
reason,
|
|
144
142
|
});
|
|
@@ -148,7 +146,7 @@ class ChannelEngine {
|
|
|
148
146
|
* @param reason - The reason for self-destructing the channel
|
|
149
147
|
*/
|
|
150
148
|
destroy(reason) {
|
|
151
|
-
this.sendMessage((0,
|
|
149
|
+
this.sendMessage((0, pondsocket_common_1.uuid)(), pondsocket_common_1.SystemSender.CHANNEL, pondsocket_common_1.ChannelReceiver.ALL_USERS, pondsocket_common_1.ServerActions.ERROR, 'destroyed', {
|
|
152
150
|
message: reason !== null && reason !== void 0 ? reason : 'Channel has been destroyed',
|
|
153
151
|
});
|
|
154
152
|
__classPrivateFieldGet(this, _ChannelEngine_parentEngine, "f").destroyChannel();
|
|
@@ -204,7 +202,7 @@ class ChannelEngine {
|
|
|
204
202
|
* @param payload - The payload of the message
|
|
205
203
|
*/
|
|
206
204
|
sendMessage(requestId, sender, recipient, action, event, payload) {
|
|
207
|
-
if (!__classPrivateFieldGet(this, _ChannelEngine_users, "f").has(sender) && sender !==
|
|
205
|
+
if (!__classPrivateFieldGet(this, _ChannelEngine_users, "f").has(sender) && sender !== pondsocket_common_1.SystemSender.CHANNEL) {
|
|
208
206
|
throw new pondError_1.ChannelError(`ChannelEngine: User with id ${sender} does not exist in channel ${this.name}`, 404, this.name);
|
|
209
207
|
}
|
|
210
208
|
const eventMessage = {
|
|
@@ -230,15 +228,15 @@ class ChannelEngine {
|
|
|
230
228
|
sender: userId,
|
|
231
229
|
event: message.event,
|
|
232
230
|
payload: message.payload,
|
|
233
|
-
action:
|
|
231
|
+
action: pondsocket_common_1.ServerActions.BROADCAST,
|
|
234
232
|
channelName: this.name,
|
|
235
233
|
requestId: message.requestId,
|
|
236
|
-
recipients: __classPrivateFieldGet(this, _ChannelEngine_instances, "m", _ChannelEngine_getUsersFromRecipients).call(this, message.addresses ||
|
|
234
|
+
recipients: __classPrivateFieldGet(this, _ChannelEngine_instances, "m", _ChannelEngine_getUsersFromRecipients).call(this, message.addresses || pondsocket_common_1.ChannelReceiver.ALL_USERS, userId),
|
|
237
235
|
};
|
|
238
236
|
const request = new eventRequest_1.EventRequest(responseEvent, this);
|
|
239
237
|
const response = new eventResponse_1.EventResponse(responseEvent, this);
|
|
240
238
|
__classPrivateFieldGet(this, _ChannelEngine_parentEngine, "f").execute(request, response, () => {
|
|
241
|
-
this.sendMessage(responseEvent.requestId,
|
|
239
|
+
this.sendMessage(responseEvent.requestId, pondsocket_common_1.SystemSender.CHANNEL, [userId], pondsocket_common_1.ServerActions.ERROR, pondsocket_common_1.ErrorTypes.HANDLER_NOT_FOUND, {
|
|
242
240
|
message: 'A handler did not respond to the event',
|
|
243
241
|
code: 404,
|
|
244
242
|
});
|
|
@@ -272,17 +270,17 @@ _ChannelEngine_receiver = new WeakMap(), _ChannelEngine_presenceEngine = new Wea
|
|
|
272
270
|
const allUsers = Array.from(__classPrivateFieldGet(this, _ChannelEngine_users, "f").keys());
|
|
273
271
|
let users;
|
|
274
272
|
switch (recipients) {
|
|
275
|
-
case
|
|
273
|
+
case pondsocket_common_1.ChannelReceiver.ALL_USERS:
|
|
276
274
|
users = allUsers;
|
|
277
275
|
break;
|
|
278
|
-
case
|
|
279
|
-
if (sender ===
|
|
280
|
-
throw new pondError_1.ChannelError(`ChannelEngine: Cannot use ${
|
|
276
|
+
case pondsocket_common_1.ChannelReceiver.ALL_EXCEPT_SENDER:
|
|
277
|
+
if (sender === pondsocket_common_1.SystemSender.CHANNEL) {
|
|
278
|
+
throw new pondError_1.ChannelError(`ChannelEngine: Cannot use ${pondsocket_common_1.ChannelReceiver.ALL_EXCEPT_SENDER} with ${pondsocket_common_1.SystemSender.CHANNEL}`, 500, this.name);
|
|
281
279
|
}
|
|
282
280
|
users = allUsers.filter((user) => user !== sender);
|
|
283
281
|
break;
|
|
284
282
|
default:
|
|
285
|
-
if (!Array.isArray(recipients)
|
|
283
|
+
if (!Array.isArray(recipients)) {
|
|
286
284
|
throw new pondError_1.ChannelError(`ChannelEngine: Invalid recipients ${recipients}`, 500, this.name);
|
|
287
285
|
}
|
|
288
286
|
if (recipients.some((user) => !allUsers.includes(user))) {
|